From a62a32145a8e5f8ae68ef1caff766e53fd867380 Mon Sep 17 00:00:00 2001 From: Joe Huang Date: Tue, 19 Nov 2024 16:48:47 -0600 Subject: [PATCH 1/4] add solana commit codec, need to add test --- .../AcceptAdminRoleTokenAdminRegistry.go | 146 ++ .../AcceptAdminRoleTokenAdminRegistry_test.go | 32 + .../ccipsolana/ccip_router/AcceptOwnership.go | 117 ++ .../ccip_router/AcceptOwnership_test.go | 32 + .../ccip_router/AddChainSelector.go | 207 ++ .../ccip_router/AddChainSelector_test.go | 32 + .../ccip/ccipsolana/ccip_router/CcipSend.go | 250 +++ .../ccipsolana/ccip_router/CcipSend_test.go | 32 + .../ccip/ccipsolana/ccip_router/Commit.go | 279 +++ .../ccipsolana/ccip_router/Commit_test.go | 32 + .../ccip_router/DisableChainSelector.go | 184 ++ .../ccip_router/DisableChainSelector_test.go | 32 + .../ccip_router/EnableChainSelector.go | 184 ++ .../ccip_router/EnableChainSelector_test.go | 32 + .../ccip/ccipsolana/ccip_router/Execute.go | 293 +++ .../ccipsolana/ccip_router/Execute_test.go | 32 + .../ccip/ccipsolana/ccip_router/Initialize.go | 310 +++ .../ccipsolana/ccip_router/Initialize_test.go | 32 + .../ccipsolana/ccip_router/ManuallyExecute.go | 261 +++ .../ccip_router/ManuallyExecute_test.go | 32 + ...gisterTokenAdminRegistryViaGetCcipAdmin.go | 207 ++ ...rTokenAdminRegistryViaGetCcipAdmin_test.go | 32 + .../RegisterTokenAdminRegistryViaOwner.go | 155 ++ ...RegisterTokenAdminRegistryViaOwner_test.go | 32 + .../ccipsolana/ccip_router/SetOcrConfig.go | 215 ++ .../ccip_router/SetOcrConfig_test.go | 32 + .../ccip/ccipsolana/ccip_router/SetPool.go | 169 ++ .../ccipsolana/ccip_router/SetPool_test.go | 32 + .../ccipsolana/ccip_router/SetTokenBilling.go | 230 +++ .../ccip_router/SetTokenBilling_test.go | 32 + .../TransferAdminRoleTokenAdminRegistry.go | 169 ++ ...ransferAdminRoleTokenAdminRegistry_test.go | 32 + .../ccip_router/TransferOwnership.go | 146 ++ .../ccip_router/TransferOwnership_test.go | 32 + .../UpdateDefaultAllowOutOfOrderExecution.go | 165 ++ ...ateDefaultAllowOutOfOrderExecution_test.go | 32 + .../ccip_router/UpdateDefaultGasLimit.go | 165 ++ .../ccip_router/UpdateDefaultGasLimit_test.go | 32 + .../UpdateEnableManualExecutionAfter.go | 165 ++ .../UpdateEnableManualExecutionAfter_test.go | 32 + .../ccip_router/UpdateSolanaChainSelector.go | 165 ++ .../UpdateSolanaChainSelector_test.go | 32 + .../ccip/ccipsolana/ccip_router/accounts.go | 661 ++++++ .../ccipsolana/ccip_router/instructions.go | 304 +++ .../ccipsolana/ccip_router/testing_utils.go | 20 + .../ccip/ccipsolana/ccip_router/types.go | 1817 +++++++++++++++++ .../ccip/ccipsolana/commitcodec.go | 144 ++ 47 files changed, 7800 insertions(+) create mode 100644 core/capabilities/ccip/ccipsolana/ccip_router/AcceptAdminRoleTokenAdminRegistry.go create mode 100644 core/capabilities/ccip/ccipsolana/ccip_router/AcceptAdminRoleTokenAdminRegistry_test.go create mode 100644 core/capabilities/ccip/ccipsolana/ccip_router/AcceptOwnership.go create mode 100644 core/capabilities/ccip/ccipsolana/ccip_router/AcceptOwnership_test.go create mode 100644 core/capabilities/ccip/ccipsolana/ccip_router/AddChainSelector.go create mode 100644 core/capabilities/ccip/ccipsolana/ccip_router/AddChainSelector_test.go create mode 100644 core/capabilities/ccip/ccipsolana/ccip_router/CcipSend.go create mode 100644 core/capabilities/ccip/ccipsolana/ccip_router/CcipSend_test.go create mode 100644 core/capabilities/ccip/ccipsolana/ccip_router/Commit.go create mode 100644 core/capabilities/ccip/ccipsolana/ccip_router/Commit_test.go create mode 100644 core/capabilities/ccip/ccipsolana/ccip_router/DisableChainSelector.go create mode 100644 core/capabilities/ccip/ccipsolana/ccip_router/DisableChainSelector_test.go create mode 100644 core/capabilities/ccip/ccipsolana/ccip_router/EnableChainSelector.go create mode 100644 core/capabilities/ccip/ccipsolana/ccip_router/EnableChainSelector_test.go create mode 100644 core/capabilities/ccip/ccipsolana/ccip_router/Execute.go create mode 100644 core/capabilities/ccip/ccipsolana/ccip_router/Execute_test.go create mode 100644 core/capabilities/ccip/ccipsolana/ccip_router/Initialize.go create mode 100644 core/capabilities/ccip/ccipsolana/ccip_router/Initialize_test.go create mode 100644 core/capabilities/ccip/ccipsolana/ccip_router/ManuallyExecute.go create mode 100644 core/capabilities/ccip/ccipsolana/ccip_router/ManuallyExecute_test.go create mode 100644 core/capabilities/ccip/ccipsolana/ccip_router/RegisterTokenAdminRegistryViaGetCcipAdmin.go create mode 100644 core/capabilities/ccip/ccipsolana/ccip_router/RegisterTokenAdminRegistryViaGetCcipAdmin_test.go create mode 100644 core/capabilities/ccip/ccipsolana/ccip_router/RegisterTokenAdminRegistryViaOwner.go create mode 100644 core/capabilities/ccip/ccipsolana/ccip_router/RegisterTokenAdminRegistryViaOwner_test.go create mode 100644 core/capabilities/ccip/ccipsolana/ccip_router/SetOcrConfig.go create mode 100644 core/capabilities/ccip/ccipsolana/ccip_router/SetOcrConfig_test.go create mode 100644 core/capabilities/ccip/ccipsolana/ccip_router/SetPool.go create mode 100644 core/capabilities/ccip/ccipsolana/ccip_router/SetPool_test.go create mode 100644 core/capabilities/ccip/ccipsolana/ccip_router/SetTokenBilling.go create mode 100644 core/capabilities/ccip/ccipsolana/ccip_router/SetTokenBilling_test.go create mode 100644 core/capabilities/ccip/ccipsolana/ccip_router/TransferAdminRoleTokenAdminRegistry.go create mode 100644 core/capabilities/ccip/ccipsolana/ccip_router/TransferAdminRoleTokenAdminRegistry_test.go create mode 100644 core/capabilities/ccip/ccipsolana/ccip_router/TransferOwnership.go create mode 100644 core/capabilities/ccip/ccipsolana/ccip_router/TransferOwnership_test.go create mode 100644 core/capabilities/ccip/ccipsolana/ccip_router/UpdateDefaultAllowOutOfOrderExecution.go create mode 100644 core/capabilities/ccip/ccipsolana/ccip_router/UpdateDefaultAllowOutOfOrderExecution_test.go create mode 100644 core/capabilities/ccip/ccipsolana/ccip_router/UpdateDefaultGasLimit.go create mode 100644 core/capabilities/ccip/ccipsolana/ccip_router/UpdateDefaultGasLimit_test.go create mode 100644 core/capabilities/ccip/ccipsolana/ccip_router/UpdateEnableManualExecutionAfter.go create mode 100644 core/capabilities/ccip/ccipsolana/ccip_router/UpdateEnableManualExecutionAfter_test.go create mode 100644 core/capabilities/ccip/ccipsolana/ccip_router/UpdateSolanaChainSelector.go create mode 100644 core/capabilities/ccip/ccipsolana/ccip_router/UpdateSolanaChainSelector_test.go create mode 100644 core/capabilities/ccip/ccipsolana/ccip_router/accounts.go create mode 100644 core/capabilities/ccip/ccipsolana/ccip_router/instructions.go create mode 100644 core/capabilities/ccip/ccipsolana/ccip_router/testing_utils.go create mode 100644 core/capabilities/ccip/ccipsolana/ccip_router/types.go create mode 100644 core/capabilities/ccip/ccipsolana/commitcodec.go diff --git a/core/capabilities/ccip/ccipsolana/ccip_router/AcceptAdminRoleTokenAdminRegistry.go b/core/capabilities/ccip/ccipsolana/ccip_router/AcceptAdminRoleTokenAdminRegistry.go new file mode 100644 index 00000000000..6afa27007fe --- /dev/null +++ b/core/capabilities/ccip/ccipsolana/ccip_router/AcceptAdminRoleTokenAdminRegistry.go @@ -0,0 +1,146 @@ +// Code generated by https://github.com/gagliardetto/anchor-go. DO NOT EDIT. + +package ccip_router + +import ( + "errors" + ag_binary "github.com/gagliardetto/binary" + ag_solanago "github.com/gagliardetto/solana-go" + ag_format "github.com/gagliardetto/solana-go/text/format" + ag_treeout "github.com/gagliardetto/treeout" +) + +// The Pending Admin can accept the Admin Role of the Token Admin Registry +type AcceptAdminRoleTokenAdminRegistry struct { + Mint *ag_solanago.PublicKey + + // [0] = [WRITE] tokenAdminRegistry + // + // [1] = [WRITE, SIGNER] authority + ag_solanago.AccountMetaSlice `bin:"-" borsh_skip:"true"` +} + +// NewAcceptAdminRoleTokenAdminRegistryInstructionBuilder creates a new `AcceptAdminRoleTokenAdminRegistry` instruction builder. +func NewAcceptAdminRoleTokenAdminRegistryInstructionBuilder() *AcceptAdminRoleTokenAdminRegistry { + nd := &AcceptAdminRoleTokenAdminRegistry{ + AccountMetaSlice: make(ag_solanago.AccountMetaSlice, 2), + } + return nd +} + +// SetMint sets the "mint" parameter. +func (inst *AcceptAdminRoleTokenAdminRegistry) SetMint(mint ag_solanago.PublicKey) *AcceptAdminRoleTokenAdminRegistry { + inst.Mint = &mint + return inst +} + +// SetTokenAdminRegistryAccount sets the "tokenAdminRegistry" account. +func (inst *AcceptAdminRoleTokenAdminRegistry) SetTokenAdminRegistryAccount(tokenAdminRegistry ag_solanago.PublicKey) *AcceptAdminRoleTokenAdminRegistry { + inst.AccountMetaSlice[0] = ag_solanago.Meta(tokenAdminRegistry).WRITE() + return inst +} + +// GetTokenAdminRegistryAccount gets the "tokenAdminRegistry" account. +func (inst *AcceptAdminRoleTokenAdminRegistry) GetTokenAdminRegistryAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[0] +} + +// SetAuthorityAccount sets the "authority" account. +func (inst *AcceptAdminRoleTokenAdminRegistry) SetAuthorityAccount(authority ag_solanago.PublicKey) *AcceptAdminRoleTokenAdminRegistry { + inst.AccountMetaSlice[1] = ag_solanago.Meta(authority).WRITE().SIGNER() + return inst +} + +// GetAuthorityAccount gets the "authority" account. +func (inst *AcceptAdminRoleTokenAdminRegistry) GetAuthorityAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[1] +} + +func (inst AcceptAdminRoleTokenAdminRegistry) Build() *Instruction { + return &Instruction{BaseVariant: ag_binary.BaseVariant{ + Impl: inst, + TypeID: Instruction_AcceptAdminRoleTokenAdminRegistry, + }} +} + +// ValidateAndBuild validates the instruction parameters and accounts; +// if there is a validation error, it returns the error. +// Otherwise, it builds and returns the instruction. +func (inst AcceptAdminRoleTokenAdminRegistry) ValidateAndBuild() (*Instruction, error) { + if err := inst.Validate(); err != nil { + return nil, err + } + return inst.Build(), nil +} + +func (inst *AcceptAdminRoleTokenAdminRegistry) Validate() error { + // Check whether all (required) parameters are set: + { + if inst.Mint == nil { + return errors.New("Mint parameter is not set") + } + } + + // Check whether all (required) accounts are set: + { + if inst.AccountMetaSlice[0] == nil { + return errors.New("accounts.TokenAdminRegistry is not set") + } + if inst.AccountMetaSlice[1] == nil { + return errors.New("accounts.Authority is not set") + } + } + return nil +} + +func (inst *AcceptAdminRoleTokenAdminRegistry) EncodeToTree(parent ag_treeout.Branches) { + parent.Child(ag_format.Program(ProgramName, ProgramID)). + // + ParentFunc(func(programBranch ag_treeout.Branches) { + programBranch.Child(ag_format.Instruction("AcceptAdminRoleTokenAdminRegistry")). + // + ParentFunc(func(instructionBranch ag_treeout.Branches) { + + // Parameters of the instruction: + instructionBranch.Child("Params[len=1]").ParentFunc(func(paramsBranch ag_treeout.Branches) { + paramsBranch.Child(ag_format.Param("Mint", *inst.Mint)) + }) + + // Accounts of the instruction: + instructionBranch.Child("Accounts[len=2]").ParentFunc(func(accountsBranch ag_treeout.Branches) { + accountsBranch.Child(ag_format.Meta("tokenAdminRegistry", inst.AccountMetaSlice[0])) + accountsBranch.Child(ag_format.Meta(" authority", inst.AccountMetaSlice[1])) + }) + }) + }) +} + +func (obj AcceptAdminRoleTokenAdminRegistry) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { + // Serialize `Mint` param: + err = encoder.Encode(obj.Mint) + if err != nil { + return err + } + return nil +} +func (obj *AcceptAdminRoleTokenAdminRegistry) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { + // Deserialize `Mint`: + err = decoder.Decode(&obj.Mint) + if err != nil { + return err + } + return nil +} + +// NewAcceptAdminRoleTokenAdminRegistryInstruction declares a new AcceptAdminRoleTokenAdminRegistry instruction with the provided parameters and accounts. +func NewAcceptAdminRoleTokenAdminRegistryInstruction( + // Parameters: + mint ag_solanago.PublicKey, + // Accounts: + tokenAdminRegistry ag_solanago.PublicKey, + authority ag_solanago.PublicKey) *AcceptAdminRoleTokenAdminRegistry { + return NewAcceptAdminRoleTokenAdminRegistryInstructionBuilder(). + SetMint(mint). + SetTokenAdminRegistryAccount(tokenAdminRegistry). + SetAuthorityAccount(authority) +} diff --git a/core/capabilities/ccip/ccipsolana/ccip_router/AcceptAdminRoleTokenAdminRegistry_test.go b/core/capabilities/ccip/ccipsolana/ccip_router/AcceptAdminRoleTokenAdminRegistry_test.go new file mode 100644 index 00000000000..44baeb8e004 --- /dev/null +++ b/core/capabilities/ccip/ccipsolana/ccip_router/AcceptAdminRoleTokenAdminRegistry_test.go @@ -0,0 +1,32 @@ +// Code generated by https://github.com/gagliardetto/anchor-go. DO NOT EDIT. + +package ccip_router + +import ( + "bytes" + ag_gofuzz "github.com/gagliardetto/gofuzz" + ag_require "github.com/stretchr/testify/require" + "strconv" + "testing" +) + +func TestEncodeDecode_AcceptAdminRoleTokenAdminRegistry(t *testing.T) { + fu := ag_gofuzz.New().NilChance(0) + for i := 0; i < 1; i++ { + t.Run("AcceptAdminRoleTokenAdminRegistry"+strconv.Itoa(i), func(t *testing.T) { + { + params := new(AcceptAdminRoleTokenAdminRegistry) + fu.Fuzz(params) + params.AccountMetaSlice = nil + buf := new(bytes.Buffer) + err := encodeT(*params, buf) + ag_require.NoError(t, err) + got := new(AcceptAdminRoleTokenAdminRegistry) + err = decodeT(got, buf.Bytes()) + got.AccountMetaSlice = nil + ag_require.NoError(t, err) + ag_require.Equal(t, params, got) + } + }) + } +} diff --git a/core/capabilities/ccip/ccipsolana/ccip_router/AcceptOwnership.go b/core/capabilities/ccip/ccipsolana/ccip_router/AcceptOwnership.go new file mode 100644 index 00000000000..9354db59224 --- /dev/null +++ b/core/capabilities/ccip/ccipsolana/ccip_router/AcceptOwnership.go @@ -0,0 +1,117 @@ +// Code generated by https://github.com/gagliardetto/anchor-go. DO NOT EDIT. + +package ccip_router + +import ( + "errors" + ag_binary "github.com/gagliardetto/binary" + ag_solanago "github.com/gagliardetto/solana-go" + ag_format "github.com/gagliardetto/solana-go/text/format" + ag_treeout "github.com/gagliardetto/treeout" +) + +// AcceptOwnership is the `acceptOwnership` instruction. +type AcceptOwnership struct { + + // [0] = [WRITE] config + // + // [1] = [SIGNER] authority + ag_solanago.AccountMetaSlice `bin:"-" borsh_skip:"true"` +} + +// NewAcceptOwnershipInstructionBuilder creates a new `AcceptOwnership` instruction builder. +func NewAcceptOwnershipInstructionBuilder() *AcceptOwnership { + nd := &AcceptOwnership{ + AccountMetaSlice: make(ag_solanago.AccountMetaSlice, 2), + } + return nd +} + +// SetConfigAccount sets the "config" account. +func (inst *AcceptOwnership) SetConfigAccount(config ag_solanago.PublicKey) *AcceptOwnership { + inst.AccountMetaSlice[0] = ag_solanago.Meta(config).WRITE() + return inst +} + +// GetConfigAccount gets the "config" account. +func (inst *AcceptOwnership) GetConfigAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[0] +} + +// SetAuthorityAccount sets the "authority" account. +func (inst *AcceptOwnership) SetAuthorityAccount(authority ag_solanago.PublicKey) *AcceptOwnership { + inst.AccountMetaSlice[1] = ag_solanago.Meta(authority).SIGNER() + return inst +} + +// GetAuthorityAccount gets the "authority" account. +func (inst *AcceptOwnership) GetAuthorityAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[1] +} + +func (inst AcceptOwnership) Build() *Instruction { + return &Instruction{BaseVariant: ag_binary.BaseVariant{ + Impl: inst, + TypeID: Instruction_AcceptOwnership, + }} +} + +// ValidateAndBuild validates the instruction parameters and accounts; +// if there is a validation error, it returns the error. +// Otherwise, it builds and returns the instruction. +func (inst AcceptOwnership) ValidateAndBuild() (*Instruction, error) { + if err := inst.Validate(); err != nil { + return nil, err + } + return inst.Build(), nil +} + +func (inst *AcceptOwnership) Validate() error { + // Check whether all (required) accounts are set: + { + if inst.AccountMetaSlice[0] == nil { + return errors.New("accounts.Config is not set") + } + if inst.AccountMetaSlice[1] == nil { + return errors.New("accounts.Authority is not set") + } + } + return nil +} + +func (inst *AcceptOwnership) EncodeToTree(parent ag_treeout.Branches) { + parent.Child(ag_format.Program(ProgramName, ProgramID)). + // + ParentFunc(func(programBranch ag_treeout.Branches) { + programBranch.Child(ag_format.Instruction("AcceptOwnership")). + // + ParentFunc(func(instructionBranch ag_treeout.Branches) { + + // Parameters of the instruction: + instructionBranch.Child("Params[len=0]").ParentFunc(func(paramsBranch ag_treeout.Branches) {}) + + // Accounts of the instruction: + instructionBranch.Child("Accounts[len=2]").ParentFunc(func(accountsBranch ag_treeout.Branches) { + accountsBranch.Child(ag_format.Meta(" config", inst.AccountMetaSlice[0])) + accountsBranch.Child(ag_format.Meta("authority", inst.AccountMetaSlice[1])) + }) + }) + }) +} + +func (obj AcceptOwnership) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { + return nil +} +func (obj *AcceptOwnership) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { + return nil +} + +// NewAcceptOwnershipInstruction declares a new AcceptOwnership instruction with the provided parameters and accounts. +func NewAcceptOwnershipInstruction( + // Accounts: + config ag_solanago.PublicKey, + authority ag_solanago.PublicKey) *AcceptOwnership { + return NewAcceptOwnershipInstructionBuilder(). + SetConfigAccount(config). + SetAuthorityAccount(authority) +} diff --git a/core/capabilities/ccip/ccipsolana/ccip_router/AcceptOwnership_test.go b/core/capabilities/ccip/ccipsolana/ccip_router/AcceptOwnership_test.go new file mode 100644 index 00000000000..da475cd5d24 --- /dev/null +++ b/core/capabilities/ccip/ccipsolana/ccip_router/AcceptOwnership_test.go @@ -0,0 +1,32 @@ +// Code generated by https://github.com/gagliardetto/anchor-go. DO NOT EDIT. + +package ccip_router + +import ( + "bytes" + ag_gofuzz "github.com/gagliardetto/gofuzz" + ag_require "github.com/stretchr/testify/require" + "strconv" + "testing" +) + +func TestEncodeDecode_AcceptOwnership(t *testing.T) { + fu := ag_gofuzz.New().NilChance(0) + for i := 0; i < 1; i++ { + t.Run("AcceptOwnership"+strconv.Itoa(i), func(t *testing.T) { + { + params := new(AcceptOwnership) + fu.Fuzz(params) + params.AccountMetaSlice = nil + buf := new(bytes.Buffer) + err := encodeT(*params, buf) + ag_require.NoError(t, err) + got := new(AcceptOwnership) + err = decodeT(got, buf.Bytes()) + got.AccountMetaSlice = nil + ag_require.NoError(t, err) + ag_require.Equal(t, params, got) + } + }) + } +} diff --git a/core/capabilities/ccip/ccipsolana/ccip_router/AddChainSelector.go b/core/capabilities/ccip/ccipsolana/ccip_router/AddChainSelector.go new file mode 100644 index 00000000000..743d44c41e1 --- /dev/null +++ b/core/capabilities/ccip/ccipsolana/ccip_router/AddChainSelector.go @@ -0,0 +1,207 @@ +// Code generated by https://github.com/gagliardetto/anchor-go. DO NOT EDIT. + +package ccip_router + +import ( + "errors" + ag_binary "github.com/gagliardetto/binary" + ag_solanago "github.com/gagliardetto/solana-go" + ag_format "github.com/gagliardetto/solana-go/text/format" + ag_treeout "github.com/gagliardetto/treeout" +) + +// The Admin needs to add any new chain supported (this means both OnRamp and OffRamp). +type AddChainSelector struct { + NewChainSelector *uint64 + OnRampAddress *[]byte + + // [0] = [WRITE] chainState + // + // [1] = [] config + // + // [2] = [WRITE, SIGNER] authority + // + // [3] = [] systemProgram + ag_solanago.AccountMetaSlice `bin:"-" borsh_skip:"true"` +} + +// NewAddChainSelectorInstructionBuilder creates a new `AddChainSelector` instruction builder. +func NewAddChainSelectorInstructionBuilder() *AddChainSelector { + nd := &AddChainSelector{ + AccountMetaSlice: make(ag_solanago.AccountMetaSlice, 4), + } + return nd +} + +// SetNewChainSelector sets the "newChainSelector" parameter. +func (inst *AddChainSelector) SetNewChainSelector(newChainSelector uint64) *AddChainSelector { + inst.NewChainSelector = &newChainSelector + return inst +} + +// SetOnRampAddress sets the "onRampAddress" parameter. +func (inst *AddChainSelector) SetOnRampAddress(onRampAddress []byte) *AddChainSelector { + inst.OnRampAddress = &onRampAddress + return inst +} + +// SetChainStateAccount sets the "chainState" account. +func (inst *AddChainSelector) SetChainStateAccount(chainState ag_solanago.PublicKey) *AddChainSelector { + inst.AccountMetaSlice[0] = ag_solanago.Meta(chainState).WRITE() + return inst +} + +// GetChainStateAccount gets the "chainState" account. +func (inst *AddChainSelector) GetChainStateAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[0] +} + +// SetConfigAccount sets the "config" account. +func (inst *AddChainSelector) SetConfigAccount(config ag_solanago.PublicKey) *AddChainSelector { + inst.AccountMetaSlice[1] = ag_solanago.Meta(config) + return inst +} + +// GetConfigAccount gets the "config" account. +func (inst *AddChainSelector) GetConfigAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[1] +} + +// SetAuthorityAccount sets the "authority" account. +func (inst *AddChainSelector) SetAuthorityAccount(authority ag_solanago.PublicKey) *AddChainSelector { + inst.AccountMetaSlice[2] = ag_solanago.Meta(authority).WRITE().SIGNER() + return inst +} + +// GetAuthorityAccount gets the "authority" account. +func (inst *AddChainSelector) GetAuthorityAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[2] +} + +// SetSystemProgramAccount sets the "systemProgram" account. +func (inst *AddChainSelector) SetSystemProgramAccount(systemProgram ag_solanago.PublicKey) *AddChainSelector { + inst.AccountMetaSlice[3] = ag_solanago.Meta(systemProgram) + return inst +} + +// GetSystemProgramAccount gets the "systemProgram" account. +func (inst *AddChainSelector) GetSystemProgramAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[3] +} + +func (inst AddChainSelector) Build() *Instruction { + return &Instruction{BaseVariant: ag_binary.BaseVariant{ + Impl: inst, + TypeID: Instruction_AddChainSelector, + }} +} + +// ValidateAndBuild validates the instruction parameters and accounts; +// if there is a validation error, it returns the error. +// Otherwise, it builds and returns the instruction. +func (inst AddChainSelector) ValidateAndBuild() (*Instruction, error) { + if err := inst.Validate(); err != nil { + return nil, err + } + return inst.Build(), nil +} + +func (inst *AddChainSelector) Validate() error { + // Check whether all (required) parameters are set: + { + if inst.NewChainSelector == nil { + return errors.New("NewChainSelector parameter is not set") + } + if inst.OnRampAddress == nil { + return errors.New("OnRampAddress parameter is not set") + } + } + + // Check whether all (required) accounts are set: + { + if inst.AccountMetaSlice[0] == nil { + return errors.New("accounts.ChainState is not set") + } + if inst.AccountMetaSlice[1] == nil { + return errors.New("accounts.Config is not set") + } + if inst.AccountMetaSlice[2] == nil { + return errors.New("accounts.Authority is not set") + } + if inst.AccountMetaSlice[3] == nil { + return errors.New("accounts.SystemProgram is not set") + } + } + return nil +} + +func (inst *AddChainSelector) EncodeToTree(parent ag_treeout.Branches) { + parent.Child(ag_format.Program(ProgramName, ProgramID)). + // + ParentFunc(func(programBranch ag_treeout.Branches) { + programBranch.Child(ag_format.Instruction("AddChainSelector")). + // + ParentFunc(func(instructionBranch ag_treeout.Branches) { + + // Parameters of the instruction: + instructionBranch.Child("Params[len=2]").ParentFunc(func(paramsBranch ag_treeout.Branches) { + paramsBranch.Child(ag_format.Param("NewChainSelector", *inst.NewChainSelector)) + paramsBranch.Child(ag_format.Param(" OnRampAddress", *inst.OnRampAddress)) + }) + + // Accounts of the instruction: + instructionBranch.Child("Accounts[len=4]").ParentFunc(func(accountsBranch ag_treeout.Branches) { + accountsBranch.Child(ag_format.Meta(" chainState", inst.AccountMetaSlice[0])) + accountsBranch.Child(ag_format.Meta(" config", inst.AccountMetaSlice[1])) + accountsBranch.Child(ag_format.Meta(" authority", inst.AccountMetaSlice[2])) + accountsBranch.Child(ag_format.Meta("systemProgram", inst.AccountMetaSlice[3])) + }) + }) + }) +} + +func (obj AddChainSelector) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { + // Serialize `NewChainSelector` param: + err = encoder.Encode(obj.NewChainSelector) + if err != nil { + return err + } + // Serialize `OnRampAddress` param: + err = encoder.Encode(obj.OnRampAddress) + if err != nil { + return err + } + return nil +} +func (obj *AddChainSelector) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { + // Deserialize `NewChainSelector`: + err = decoder.Decode(&obj.NewChainSelector) + if err != nil { + return err + } + // Deserialize `OnRampAddress`: + err = decoder.Decode(&obj.OnRampAddress) + if err != nil { + return err + } + return nil +} + +// NewAddChainSelectorInstruction declares a new AddChainSelector instruction with the provided parameters and accounts. +func NewAddChainSelectorInstruction( + // Parameters: + newChainSelector uint64, + onRampAddress []byte, + // Accounts: + chainState ag_solanago.PublicKey, + config ag_solanago.PublicKey, + authority ag_solanago.PublicKey, + systemProgram ag_solanago.PublicKey) *AddChainSelector { + return NewAddChainSelectorInstructionBuilder(). + SetNewChainSelector(newChainSelector). + SetOnRampAddress(onRampAddress). + SetChainStateAccount(chainState). + SetConfigAccount(config). + SetAuthorityAccount(authority). + SetSystemProgramAccount(systemProgram) +} diff --git a/core/capabilities/ccip/ccipsolana/ccip_router/AddChainSelector_test.go b/core/capabilities/ccip/ccipsolana/ccip_router/AddChainSelector_test.go new file mode 100644 index 00000000000..8398360f7f6 --- /dev/null +++ b/core/capabilities/ccip/ccipsolana/ccip_router/AddChainSelector_test.go @@ -0,0 +1,32 @@ +// Code generated by https://github.com/gagliardetto/anchor-go. DO NOT EDIT. + +package ccip_router + +import ( + "bytes" + ag_gofuzz "github.com/gagliardetto/gofuzz" + ag_require "github.com/stretchr/testify/require" + "strconv" + "testing" +) + +func TestEncodeDecode_AddChainSelector(t *testing.T) { + fu := ag_gofuzz.New().NilChance(0) + for i := 0; i < 1; i++ { + t.Run("AddChainSelector"+strconv.Itoa(i), func(t *testing.T) { + { + params := new(AddChainSelector) + fu.Fuzz(params) + params.AccountMetaSlice = nil + buf := new(bytes.Buffer) + err := encodeT(*params, buf) + ag_require.NoError(t, err) + got := new(AddChainSelector) + err = decodeT(got, buf.Bytes()) + got.AccountMetaSlice = nil + ag_require.NoError(t, err) + ag_require.Equal(t, params, got) + } + }) + } +} diff --git a/core/capabilities/ccip/ccipsolana/ccip_router/CcipSend.go b/core/capabilities/ccip/ccipsolana/ccip_router/CcipSend.go new file mode 100644 index 00000000000..61cd343e929 --- /dev/null +++ b/core/capabilities/ccip/ccipsolana/ccip_router/CcipSend.go @@ -0,0 +1,250 @@ +// Code generated by https://github.com/gagliardetto/anchor-go. DO NOT EDIT. + +package ccip_router + +import ( + "errors" + ag_binary "github.com/gagliardetto/binary" + ag_solanago "github.com/gagliardetto/solana-go" + ag_format "github.com/gagliardetto/solana-go/text/format" + ag_treeout "github.com/gagliardetto/treeout" +) + +// ON RAMP FLOW +// The method name needs to be ccip_send with Anchor encoding. +// This function is called by the CCIP Sender Contract (or final user) to send a message to the CCIP Router. +// The size limit of data is 256 bytes. +// The message is sent to the receiver on the destination chain selector. +// This message emits the event CCIPSendRequested with all the necessary data to be retrieved by the OffChain Code +type CcipSend struct { + DestChainSelector *uint64 + Message *Solana2AnyMessage + + // [0] = [] config + // + // [1] = [WRITE] chainState + // + // [2] = [WRITE] nonce + // + // [3] = [WRITE, SIGNER] authority + // + // [4] = [] systemProgram + // + // [5] = [WRITE] tokenPoolsSigner + ag_solanago.AccountMetaSlice `bin:"-" borsh_skip:"true"` +} + +// NewCcipSendInstructionBuilder creates a new `CcipSend` instruction builder. +func NewCcipSendInstructionBuilder() *CcipSend { + nd := &CcipSend{ + AccountMetaSlice: make(ag_solanago.AccountMetaSlice, 6), + } + return nd +} + +// SetDestChainSelector sets the "destChainSelector" parameter. +func (inst *CcipSend) SetDestChainSelector(destChainSelector uint64) *CcipSend { + inst.DestChainSelector = &destChainSelector + return inst +} + +// SetMessage sets the "message" parameter. +func (inst *CcipSend) SetMessage(message Solana2AnyMessage) *CcipSend { + inst.Message = &message + return inst +} + +// SetConfigAccount sets the "config" account. +func (inst *CcipSend) SetConfigAccount(config ag_solanago.PublicKey) *CcipSend { + inst.AccountMetaSlice[0] = ag_solanago.Meta(config) + return inst +} + +// GetConfigAccount gets the "config" account. +func (inst *CcipSend) GetConfigAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[0] +} + +// SetChainStateAccount sets the "chainState" account. +func (inst *CcipSend) SetChainStateAccount(chainState ag_solanago.PublicKey) *CcipSend { + inst.AccountMetaSlice[1] = ag_solanago.Meta(chainState).WRITE() + return inst +} + +// GetChainStateAccount gets the "chainState" account. +func (inst *CcipSend) GetChainStateAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[1] +} + +// SetNonceAccount sets the "nonce" account. +func (inst *CcipSend) SetNonceAccount(nonce ag_solanago.PublicKey) *CcipSend { + inst.AccountMetaSlice[2] = ag_solanago.Meta(nonce).WRITE() + return inst +} + +// GetNonceAccount gets the "nonce" account. +func (inst *CcipSend) GetNonceAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[2] +} + +// SetAuthorityAccount sets the "authority" account. +func (inst *CcipSend) SetAuthorityAccount(authority ag_solanago.PublicKey) *CcipSend { + inst.AccountMetaSlice[3] = ag_solanago.Meta(authority).WRITE().SIGNER() + return inst +} + +// GetAuthorityAccount gets the "authority" account. +func (inst *CcipSend) GetAuthorityAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[3] +} + +// SetSystemProgramAccount sets the "systemProgram" account. +func (inst *CcipSend) SetSystemProgramAccount(systemProgram ag_solanago.PublicKey) *CcipSend { + inst.AccountMetaSlice[4] = ag_solanago.Meta(systemProgram) + return inst +} + +// GetSystemProgramAccount gets the "systemProgram" account. +func (inst *CcipSend) GetSystemProgramAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[4] +} + +// SetTokenPoolsSignerAccount sets the "tokenPoolsSigner" account. +func (inst *CcipSend) SetTokenPoolsSignerAccount(tokenPoolsSigner ag_solanago.PublicKey) *CcipSend { + inst.AccountMetaSlice[5] = ag_solanago.Meta(tokenPoolsSigner).WRITE() + return inst +} + +// GetTokenPoolsSignerAccount gets the "tokenPoolsSigner" account. +func (inst *CcipSend) GetTokenPoolsSignerAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[5] +} + +func (inst CcipSend) Build() *Instruction { + return &Instruction{BaseVariant: ag_binary.BaseVariant{ + Impl: inst, + TypeID: Instruction_CcipSend, + }} +} + +// ValidateAndBuild validates the instruction parameters and accounts; +// if there is a validation error, it returns the error. +// Otherwise, it builds and returns the instruction. +func (inst CcipSend) ValidateAndBuild() (*Instruction, error) { + if err := inst.Validate(); err != nil { + return nil, err + } + return inst.Build(), nil +} + +func (inst *CcipSend) Validate() error { + // Check whether all (required) parameters are set: + { + if inst.DestChainSelector == nil { + return errors.New("DestChainSelector parameter is not set") + } + if inst.Message == nil { + return errors.New("Message parameter is not set") + } + } + + // Check whether all (required) accounts are set: + { + if inst.AccountMetaSlice[0] == nil { + return errors.New("accounts.Config is not set") + } + if inst.AccountMetaSlice[1] == nil { + return errors.New("accounts.ChainState is not set") + } + if inst.AccountMetaSlice[2] == nil { + return errors.New("accounts.Nonce is not set") + } + if inst.AccountMetaSlice[3] == nil { + return errors.New("accounts.Authority is not set") + } + if inst.AccountMetaSlice[4] == nil { + return errors.New("accounts.SystemProgram is not set") + } + if inst.AccountMetaSlice[5] == nil { + return errors.New("accounts.TokenPoolsSigner is not set") + } + } + return nil +} + +func (inst *CcipSend) EncodeToTree(parent ag_treeout.Branches) { + parent.Child(ag_format.Program(ProgramName, ProgramID)). + // + ParentFunc(func(programBranch ag_treeout.Branches) { + programBranch.Child(ag_format.Instruction("CcipSend")). + // + ParentFunc(func(instructionBranch ag_treeout.Branches) { + + // Parameters of the instruction: + instructionBranch.Child("Params[len=2]").ParentFunc(func(paramsBranch ag_treeout.Branches) { + paramsBranch.Child(ag_format.Param("DestChainSelector", *inst.DestChainSelector)) + paramsBranch.Child(ag_format.Param(" Message", *inst.Message)) + }) + + // Accounts of the instruction: + instructionBranch.Child("Accounts[len=6]").ParentFunc(func(accountsBranch ag_treeout.Branches) { + accountsBranch.Child(ag_format.Meta(" config", inst.AccountMetaSlice[0])) + accountsBranch.Child(ag_format.Meta(" chainState", inst.AccountMetaSlice[1])) + accountsBranch.Child(ag_format.Meta(" nonce", inst.AccountMetaSlice[2])) + accountsBranch.Child(ag_format.Meta(" authority", inst.AccountMetaSlice[3])) + accountsBranch.Child(ag_format.Meta(" systemProgram", inst.AccountMetaSlice[4])) + accountsBranch.Child(ag_format.Meta("tokenPoolsSigner", inst.AccountMetaSlice[5])) + }) + }) + }) +} + +func (obj CcipSend) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { + // Serialize `DestChainSelector` param: + err = encoder.Encode(obj.DestChainSelector) + if err != nil { + return err + } + // Serialize `Message` param: + err = encoder.Encode(obj.Message) + if err != nil { + return err + } + return nil +} +func (obj *CcipSend) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { + // Deserialize `DestChainSelector`: + err = decoder.Decode(&obj.DestChainSelector) + if err != nil { + return err + } + // Deserialize `Message`: + err = decoder.Decode(&obj.Message) + if err != nil { + return err + } + return nil +} + +// NewCcipSendInstruction declares a new CcipSend instruction with the provided parameters and accounts. +func NewCcipSendInstruction( + // Parameters: + destChainSelector uint64, + message Solana2AnyMessage, + // Accounts: + config ag_solanago.PublicKey, + chainState ag_solanago.PublicKey, + nonce ag_solanago.PublicKey, + authority ag_solanago.PublicKey, + systemProgram ag_solanago.PublicKey, + tokenPoolsSigner ag_solanago.PublicKey) *CcipSend { + return NewCcipSendInstructionBuilder(). + SetDestChainSelector(destChainSelector). + SetMessage(message). + SetConfigAccount(config). + SetChainStateAccount(chainState). + SetNonceAccount(nonce). + SetAuthorityAccount(authority). + SetSystemProgramAccount(systemProgram). + SetTokenPoolsSignerAccount(tokenPoolsSigner) +} diff --git a/core/capabilities/ccip/ccipsolana/ccip_router/CcipSend_test.go b/core/capabilities/ccip/ccipsolana/ccip_router/CcipSend_test.go new file mode 100644 index 00000000000..a9f819342cb --- /dev/null +++ b/core/capabilities/ccip/ccipsolana/ccip_router/CcipSend_test.go @@ -0,0 +1,32 @@ +// Code generated by https://github.com/gagliardetto/anchor-go. DO NOT EDIT. + +package ccip_router + +import ( + "bytes" + ag_gofuzz "github.com/gagliardetto/gofuzz" + ag_require "github.com/stretchr/testify/require" + "strconv" + "testing" +) + +func TestEncodeDecode_CcipSend(t *testing.T) { + fu := ag_gofuzz.New().NilChance(0) + for i := 0; i < 1; i++ { + t.Run("CcipSend"+strconv.Itoa(i), func(t *testing.T) { + { + params := new(CcipSend) + fu.Fuzz(params) + params.AccountMetaSlice = nil + buf := new(bytes.Buffer) + err := encodeT(*params, buf) + ag_require.NoError(t, err) + got := new(CcipSend) + err = decodeT(got, buf.Bytes()) + got.AccountMetaSlice = nil + ag_require.NoError(t, err) + ag_require.Equal(t, params, got) + } + }) + } +} diff --git a/core/capabilities/ccip/ccipsolana/ccip_router/Commit.go b/core/capabilities/ccip/ccipsolana/ccip_router/Commit.go new file mode 100644 index 00000000000..898c086029b --- /dev/null +++ b/core/capabilities/ccip/ccipsolana/ccip_router/Commit.go @@ -0,0 +1,279 @@ +// Code generated by https://github.com/gagliardetto/anchor-go. DO NOT EDIT. + +package ccip_router + +import ( + "errors" + ag_binary "github.com/gagliardetto/binary" + ag_solanago "github.com/gagliardetto/solana-go" + ag_format "github.com/gagliardetto/solana-go/text/format" + ag_treeout "github.com/gagliardetto/treeout" +) + +// OFF RAMP FLOW +// +// The method name needs to be commit with Anchor encoding. +// +// This function is called by the OffChain when committing one Report to the Solana Router. +// In this Flow only one report is sent, the Commit Report. This is different as EVM does, +// this is because here all the chain state is stored in one account per Merkle Tree Root. +// So, to avoid having to send a dynamic size array of accounts, in this message only one Commit Report Account is sent. +// This message validates the signatures of the report and stores the Merkle Root in the Commit Report Account. +// The Report must contain an interval of messages, and the min of them must be the next sequence number expected. +// The max size of the interval is 64. +// This message emits two events: CommitReportAccepted and Transmitted. +type Commit struct { + ReportContext *[3][32]uint8 + Report *CommitInput + Signatures *[][65]uint8 + + // [0] = [] config + // + // [1] = [WRITE] chainState + // + // [2] = [WRITE] commitReport + // + // [3] = [WRITE, SIGNER] authority + // + // [4] = [] systemProgram + // + // [5] = [] sysvarInstructions + ag_solanago.AccountMetaSlice `bin:"-" borsh_skip:"true"` +} + +// NewCommitInstructionBuilder creates a new `Commit` instruction builder. +func NewCommitInstructionBuilder() *Commit { + nd := &Commit{ + AccountMetaSlice: make(ag_solanago.AccountMetaSlice, 6), + } + return nd +} + +// SetReportContext sets the "reportContext" parameter. +func (inst *Commit) SetReportContext(reportContext [3][32]uint8) *Commit { + inst.ReportContext = &reportContext + return inst +} + +// SetReport sets the "report" parameter. +func (inst *Commit) SetReport(report CommitInput) *Commit { + inst.Report = &report + return inst +} + +// SetSignatures sets the "signatures" parameter. +func (inst *Commit) SetSignatures(signatures [][65]uint8) *Commit { + inst.Signatures = &signatures + return inst +} + +// SetConfigAccount sets the "config" account. +func (inst *Commit) SetConfigAccount(config ag_solanago.PublicKey) *Commit { + inst.AccountMetaSlice[0] = ag_solanago.Meta(config) + return inst +} + +// GetConfigAccount gets the "config" account. +func (inst *Commit) GetConfigAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[0] +} + +// SetChainStateAccount sets the "chainState" account. +func (inst *Commit) SetChainStateAccount(chainState ag_solanago.PublicKey) *Commit { + inst.AccountMetaSlice[1] = ag_solanago.Meta(chainState).WRITE() + return inst +} + +// GetChainStateAccount gets the "chainState" account. +func (inst *Commit) GetChainStateAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[1] +} + +// SetCommitReportAccount sets the "commitReport" account. +func (inst *Commit) SetCommitReportAccount(commitReport ag_solanago.PublicKey) *Commit { + inst.AccountMetaSlice[2] = ag_solanago.Meta(commitReport).WRITE() + return inst +} + +// GetCommitReportAccount gets the "commitReport" account. +func (inst *Commit) GetCommitReportAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[2] +} + +// SetAuthorityAccount sets the "authority" account. +func (inst *Commit) SetAuthorityAccount(authority ag_solanago.PublicKey) *Commit { + inst.AccountMetaSlice[3] = ag_solanago.Meta(authority).WRITE().SIGNER() + return inst +} + +// GetAuthorityAccount gets the "authority" account. +func (inst *Commit) GetAuthorityAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[3] +} + +// SetSystemProgramAccount sets the "systemProgram" account. +func (inst *Commit) SetSystemProgramAccount(systemProgram ag_solanago.PublicKey) *Commit { + inst.AccountMetaSlice[4] = ag_solanago.Meta(systemProgram) + return inst +} + +// GetSystemProgramAccount gets the "systemProgram" account. +func (inst *Commit) GetSystemProgramAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[4] +} + +// SetSysvarInstructionsAccount sets the "sysvarInstructions" account. +func (inst *Commit) SetSysvarInstructionsAccount(sysvarInstructions ag_solanago.PublicKey) *Commit { + inst.AccountMetaSlice[5] = ag_solanago.Meta(sysvarInstructions) + return inst +} + +// GetSysvarInstructionsAccount gets the "sysvarInstructions" account. +func (inst *Commit) GetSysvarInstructionsAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[5] +} + +func (inst Commit) Build() *Instruction { + return &Instruction{BaseVariant: ag_binary.BaseVariant{ + Impl: inst, + TypeID: Instruction_Commit, + }} +} + +// ValidateAndBuild validates the instruction parameters and accounts; +// if there is a validation error, it returns the error. +// Otherwise, it builds and returns the instruction. +func (inst Commit) ValidateAndBuild() (*Instruction, error) { + if err := inst.Validate(); err != nil { + return nil, err + } + return inst.Build(), nil +} + +func (inst *Commit) Validate() error { + // Check whether all (required) parameters are set: + { + if inst.ReportContext == nil { + return errors.New("ReportContext parameter is not set") + } + if inst.Report == nil { + return errors.New("Report parameter is not set") + } + if inst.Signatures == nil { + return errors.New("Signatures parameter is not set") + } + } + + // Check whether all (required) accounts are set: + { + if inst.AccountMetaSlice[0] == nil { + return errors.New("accounts.Config is not set") + } + if inst.AccountMetaSlice[1] == nil { + return errors.New("accounts.ChainState is not set") + } + if inst.AccountMetaSlice[2] == nil { + return errors.New("accounts.CommitReport is not set") + } + if inst.AccountMetaSlice[3] == nil { + return errors.New("accounts.Authority is not set") + } + if inst.AccountMetaSlice[4] == nil { + return errors.New("accounts.SystemProgram is not set") + } + if inst.AccountMetaSlice[5] == nil { + return errors.New("accounts.SysvarInstructions is not set") + } + } + return nil +} + +func (inst *Commit) EncodeToTree(parent ag_treeout.Branches) { + parent.Child(ag_format.Program(ProgramName, ProgramID)). + // + ParentFunc(func(programBranch ag_treeout.Branches) { + programBranch.Child(ag_format.Instruction("Commit")). + // + ParentFunc(func(instructionBranch ag_treeout.Branches) { + + // Parameters of the instruction: + instructionBranch.Child("Params[len=3]").ParentFunc(func(paramsBranch ag_treeout.Branches) { + paramsBranch.Child(ag_format.Param("ReportContext", *inst.ReportContext)) + paramsBranch.Child(ag_format.Param(" Report", *inst.Report)) + paramsBranch.Child(ag_format.Param(" Signatures", *inst.Signatures)) + }) + + // Accounts of the instruction: + instructionBranch.Child("Accounts[len=6]").ParentFunc(func(accountsBranch ag_treeout.Branches) { + accountsBranch.Child(ag_format.Meta(" config", inst.AccountMetaSlice[0])) + accountsBranch.Child(ag_format.Meta(" chainState", inst.AccountMetaSlice[1])) + accountsBranch.Child(ag_format.Meta(" commitReport", inst.AccountMetaSlice[2])) + accountsBranch.Child(ag_format.Meta(" authority", inst.AccountMetaSlice[3])) + accountsBranch.Child(ag_format.Meta(" systemProgram", inst.AccountMetaSlice[4])) + accountsBranch.Child(ag_format.Meta("sysvarInstructions", inst.AccountMetaSlice[5])) + }) + }) + }) +} + +func (obj Commit) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { + // Serialize `ReportContext` param: + err = encoder.Encode(obj.ReportContext) + if err != nil { + return err + } + // Serialize `Report` param: + err = encoder.Encode(obj.Report) + if err != nil { + return err + } + // Serialize `Signatures` param: + err = encoder.Encode(obj.Signatures) + if err != nil { + return err + } + return nil +} +func (obj *Commit) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { + // Deserialize `ReportContext`: + err = decoder.Decode(&obj.ReportContext) + if err != nil { + return err + } + // Deserialize `Report`: + err = decoder.Decode(&obj.Report) + if err != nil { + return err + } + // Deserialize `Signatures`: + err = decoder.Decode(&obj.Signatures) + if err != nil { + return err + } + return nil +} + +// NewCommitInstruction declares a new Commit instruction with the provided parameters and accounts. +func NewCommitInstruction( + // Parameters: + reportContext [3][32]uint8, + report CommitInput, + signatures [][65]uint8, + // Accounts: + config ag_solanago.PublicKey, + chainState ag_solanago.PublicKey, + commitReport ag_solanago.PublicKey, + authority ag_solanago.PublicKey, + systemProgram ag_solanago.PublicKey, + sysvarInstructions ag_solanago.PublicKey) *Commit { + return NewCommitInstructionBuilder(). + SetReportContext(reportContext). + SetReport(report). + SetSignatures(signatures). + SetConfigAccount(config). + SetChainStateAccount(chainState). + SetCommitReportAccount(commitReport). + SetAuthorityAccount(authority). + SetSystemProgramAccount(systemProgram). + SetSysvarInstructionsAccount(sysvarInstructions) +} diff --git a/core/capabilities/ccip/ccipsolana/ccip_router/Commit_test.go b/core/capabilities/ccip/ccipsolana/ccip_router/Commit_test.go new file mode 100644 index 00000000000..fcaf33cc942 --- /dev/null +++ b/core/capabilities/ccip/ccipsolana/ccip_router/Commit_test.go @@ -0,0 +1,32 @@ +// Code generated by https://github.com/gagliardetto/anchor-go. DO NOT EDIT. + +package ccip_router + +import ( + "bytes" + ag_gofuzz "github.com/gagliardetto/gofuzz" + ag_require "github.com/stretchr/testify/require" + "strconv" + "testing" +) + +func TestEncodeDecode_Commit(t *testing.T) { + fu := ag_gofuzz.New().NilChance(0) + for i := 0; i < 1; i++ { + t.Run("Commit"+strconv.Itoa(i), func(t *testing.T) { + { + params := new(Commit) + fu.Fuzz(params) + params.AccountMetaSlice = nil + buf := new(bytes.Buffer) + err := encodeT(*params, buf) + ag_require.NoError(t, err) + got := new(Commit) + err = decodeT(got, buf.Bytes()) + got.AccountMetaSlice = nil + ag_require.NoError(t, err) + ag_require.Equal(t, params, got) + } + }) + } +} diff --git a/core/capabilities/ccip/ccipsolana/ccip_router/DisableChainSelector.go b/core/capabilities/ccip/ccipsolana/ccip_router/DisableChainSelector.go new file mode 100644 index 00000000000..772c3391061 --- /dev/null +++ b/core/capabilities/ccip/ccipsolana/ccip_router/DisableChainSelector.go @@ -0,0 +1,184 @@ +// Code generated by https://github.com/gagliardetto/anchor-go. DO NOT EDIT. + +package ccip_router + +import ( + "errors" + ag_binary "github.com/gagliardetto/binary" + ag_solanago "github.com/gagliardetto/solana-go" + ag_format "github.com/gagliardetto/solana-go/text/format" + ag_treeout "github.com/gagliardetto/treeout" +) + +// The Admin is the only one able to enable or disable the chain selector +type DisableChainSelector struct { + NewChainSelector *uint64 + + // [0] = [WRITE] chainState + // + // [1] = [] config + // + // [2] = [WRITE, SIGNER] authority + // + // [3] = [] systemProgram + ag_solanago.AccountMetaSlice `bin:"-" borsh_skip:"true"` +} + +// NewDisableChainSelectorInstructionBuilder creates a new `DisableChainSelector` instruction builder. +func NewDisableChainSelectorInstructionBuilder() *DisableChainSelector { + nd := &DisableChainSelector{ + AccountMetaSlice: make(ag_solanago.AccountMetaSlice, 4), + } + return nd +} + +// SetNewChainSelector sets the "newChainSelector" parameter. +func (inst *DisableChainSelector) SetNewChainSelector(newChainSelector uint64) *DisableChainSelector { + inst.NewChainSelector = &newChainSelector + return inst +} + +// SetChainStateAccount sets the "chainState" account. +func (inst *DisableChainSelector) SetChainStateAccount(chainState ag_solanago.PublicKey) *DisableChainSelector { + inst.AccountMetaSlice[0] = ag_solanago.Meta(chainState).WRITE() + return inst +} + +// GetChainStateAccount gets the "chainState" account. +func (inst *DisableChainSelector) GetChainStateAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[0] +} + +// SetConfigAccount sets the "config" account. +func (inst *DisableChainSelector) SetConfigAccount(config ag_solanago.PublicKey) *DisableChainSelector { + inst.AccountMetaSlice[1] = ag_solanago.Meta(config) + return inst +} + +// GetConfigAccount gets the "config" account. +func (inst *DisableChainSelector) GetConfigAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[1] +} + +// SetAuthorityAccount sets the "authority" account. +func (inst *DisableChainSelector) SetAuthorityAccount(authority ag_solanago.PublicKey) *DisableChainSelector { + inst.AccountMetaSlice[2] = ag_solanago.Meta(authority).WRITE().SIGNER() + return inst +} + +// GetAuthorityAccount gets the "authority" account. +func (inst *DisableChainSelector) GetAuthorityAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[2] +} + +// SetSystemProgramAccount sets the "systemProgram" account. +func (inst *DisableChainSelector) SetSystemProgramAccount(systemProgram ag_solanago.PublicKey) *DisableChainSelector { + inst.AccountMetaSlice[3] = ag_solanago.Meta(systemProgram) + return inst +} + +// GetSystemProgramAccount gets the "systemProgram" account. +func (inst *DisableChainSelector) GetSystemProgramAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[3] +} + +func (inst DisableChainSelector) Build() *Instruction { + return &Instruction{BaseVariant: ag_binary.BaseVariant{ + Impl: inst, + TypeID: Instruction_DisableChainSelector, + }} +} + +// ValidateAndBuild validates the instruction parameters and accounts; +// if there is a validation error, it returns the error. +// Otherwise, it builds and returns the instruction. +func (inst DisableChainSelector) ValidateAndBuild() (*Instruction, error) { + if err := inst.Validate(); err != nil { + return nil, err + } + return inst.Build(), nil +} + +func (inst *DisableChainSelector) Validate() error { + // Check whether all (required) parameters are set: + { + if inst.NewChainSelector == nil { + return errors.New("NewChainSelector parameter is not set") + } + } + + // Check whether all (required) accounts are set: + { + if inst.AccountMetaSlice[0] == nil { + return errors.New("accounts.ChainState is not set") + } + if inst.AccountMetaSlice[1] == nil { + return errors.New("accounts.Config is not set") + } + if inst.AccountMetaSlice[2] == nil { + return errors.New("accounts.Authority is not set") + } + if inst.AccountMetaSlice[3] == nil { + return errors.New("accounts.SystemProgram is not set") + } + } + return nil +} + +func (inst *DisableChainSelector) EncodeToTree(parent ag_treeout.Branches) { + parent.Child(ag_format.Program(ProgramName, ProgramID)). + // + ParentFunc(func(programBranch ag_treeout.Branches) { + programBranch.Child(ag_format.Instruction("DisableChainSelector")). + // + ParentFunc(func(instructionBranch ag_treeout.Branches) { + + // Parameters of the instruction: + instructionBranch.Child("Params[len=1]").ParentFunc(func(paramsBranch ag_treeout.Branches) { + paramsBranch.Child(ag_format.Param("NewChainSelector", *inst.NewChainSelector)) + }) + + // Accounts of the instruction: + instructionBranch.Child("Accounts[len=4]").ParentFunc(func(accountsBranch ag_treeout.Branches) { + accountsBranch.Child(ag_format.Meta(" chainState", inst.AccountMetaSlice[0])) + accountsBranch.Child(ag_format.Meta(" config", inst.AccountMetaSlice[1])) + accountsBranch.Child(ag_format.Meta(" authority", inst.AccountMetaSlice[2])) + accountsBranch.Child(ag_format.Meta("systemProgram", inst.AccountMetaSlice[3])) + }) + }) + }) +} + +func (obj DisableChainSelector) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { + // Serialize `NewChainSelector` param: + err = encoder.Encode(obj.NewChainSelector) + if err != nil { + return err + } + return nil +} +func (obj *DisableChainSelector) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { + // Deserialize `NewChainSelector`: + err = decoder.Decode(&obj.NewChainSelector) + if err != nil { + return err + } + return nil +} + +// NewDisableChainSelectorInstruction declares a new DisableChainSelector instruction with the provided parameters and accounts. +func NewDisableChainSelectorInstruction( + // Parameters: + newChainSelector uint64, + // Accounts: + chainState ag_solanago.PublicKey, + config ag_solanago.PublicKey, + authority ag_solanago.PublicKey, + systemProgram ag_solanago.PublicKey) *DisableChainSelector { + return NewDisableChainSelectorInstructionBuilder(). + SetNewChainSelector(newChainSelector). + SetChainStateAccount(chainState). + SetConfigAccount(config). + SetAuthorityAccount(authority). + SetSystemProgramAccount(systemProgram) +} diff --git a/core/capabilities/ccip/ccipsolana/ccip_router/DisableChainSelector_test.go b/core/capabilities/ccip/ccipsolana/ccip_router/DisableChainSelector_test.go new file mode 100644 index 00000000000..6d4d01c9feb --- /dev/null +++ b/core/capabilities/ccip/ccipsolana/ccip_router/DisableChainSelector_test.go @@ -0,0 +1,32 @@ +// Code generated by https://github.com/gagliardetto/anchor-go. DO NOT EDIT. + +package ccip_router + +import ( + "bytes" + ag_gofuzz "github.com/gagliardetto/gofuzz" + ag_require "github.com/stretchr/testify/require" + "strconv" + "testing" +) + +func TestEncodeDecode_DisableChainSelector(t *testing.T) { + fu := ag_gofuzz.New().NilChance(0) + for i := 0; i < 1; i++ { + t.Run("DisableChainSelector"+strconv.Itoa(i), func(t *testing.T) { + { + params := new(DisableChainSelector) + fu.Fuzz(params) + params.AccountMetaSlice = nil + buf := new(bytes.Buffer) + err := encodeT(*params, buf) + ag_require.NoError(t, err) + got := new(DisableChainSelector) + err = decodeT(got, buf.Bytes()) + got.AccountMetaSlice = nil + ag_require.NoError(t, err) + ag_require.Equal(t, params, got) + } + }) + } +} diff --git a/core/capabilities/ccip/ccipsolana/ccip_router/EnableChainSelector.go b/core/capabilities/ccip/ccipsolana/ccip_router/EnableChainSelector.go new file mode 100644 index 00000000000..b3b45bb7f91 --- /dev/null +++ b/core/capabilities/ccip/ccipsolana/ccip_router/EnableChainSelector.go @@ -0,0 +1,184 @@ +// Code generated by https://github.com/gagliardetto/anchor-go. DO NOT EDIT. + +package ccip_router + +import ( + "errors" + ag_binary "github.com/gagliardetto/binary" + ag_solanago "github.com/gagliardetto/solana-go" + ag_format "github.com/gagliardetto/solana-go/text/format" + ag_treeout "github.com/gagliardetto/treeout" +) + +// The Admin is the only one able to enable or disable the chain selector +type EnableChainSelector struct { + NewChainSelector *uint64 + + // [0] = [WRITE] chainState + // + // [1] = [] config + // + // [2] = [WRITE, SIGNER] authority + // + // [3] = [] systemProgram + ag_solanago.AccountMetaSlice `bin:"-" borsh_skip:"true"` +} + +// NewEnableChainSelectorInstructionBuilder creates a new `EnableChainSelector` instruction builder. +func NewEnableChainSelectorInstructionBuilder() *EnableChainSelector { + nd := &EnableChainSelector{ + AccountMetaSlice: make(ag_solanago.AccountMetaSlice, 4), + } + return nd +} + +// SetNewChainSelector sets the "newChainSelector" parameter. +func (inst *EnableChainSelector) SetNewChainSelector(newChainSelector uint64) *EnableChainSelector { + inst.NewChainSelector = &newChainSelector + return inst +} + +// SetChainStateAccount sets the "chainState" account. +func (inst *EnableChainSelector) SetChainStateAccount(chainState ag_solanago.PublicKey) *EnableChainSelector { + inst.AccountMetaSlice[0] = ag_solanago.Meta(chainState).WRITE() + return inst +} + +// GetChainStateAccount gets the "chainState" account. +func (inst *EnableChainSelector) GetChainStateAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[0] +} + +// SetConfigAccount sets the "config" account. +func (inst *EnableChainSelector) SetConfigAccount(config ag_solanago.PublicKey) *EnableChainSelector { + inst.AccountMetaSlice[1] = ag_solanago.Meta(config) + return inst +} + +// GetConfigAccount gets the "config" account. +func (inst *EnableChainSelector) GetConfigAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[1] +} + +// SetAuthorityAccount sets the "authority" account. +func (inst *EnableChainSelector) SetAuthorityAccount(authority ag_solanago.PublicKey) *EnableChainSelector { + inst.AccountMetaSlice[2] = ag_solanago.Meta(authority).WRITE().SIGNER() + return inst +} + +// GetAuthorityAccount gets the "authority" account. +func (inst *EnableChainSelector) GetAuthorityAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[2] +} + +// SetSystemProgramAccount sets the "systemProgram" account. +func (inst *EnableChainSelector) SetSystemProgramAccount(systemProgram ag_solanago.PublicKey) *EnableChainSelector { + inst.AccountMetaSlice[3] = ag_solanago.Meta(systemProgram) + return inst +} + +// GetSystemProgramAccount gets the "systemProgram" account. +func (inst *EnableChainSelector) GetSystemProgramAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[3] +} + +func (inst EnableChainSelector) Build() *Instruction { + return &Instruction{BaseVariant: ag_binary.BaseVariant{ + Impl: inst, + TypeID: Instruction_EnableChainSelector, + }} +} + +// ValidateAndBuild validates the instruction parameters and accounts; +// if there is a validation error, it returns the error. +// Otherwise, it builds and returns the instruction. +func (inst EnableChainSelector) ValidateAndBuild() (*Instruction, error) { + if err := inst.Validate(); err != nil { + return nil, err + } + return inst.Build(), nil +} + +func (inst *EnableChainSelector) Validate() error { + // Check whether all (required) parameters are set: + { + if inst.NewChainSelector == nil { + return errors.New("NewChainSelector parameter is not set") + } + } + + // Check whether all (required) accounts are set: + { + if inst.AccountMetaSlice[0] == nil { + return errors.New("accounts.ChainState is not set") + } + if inst.AccountMetaSlice[1] == nil { + return errors.New("accounts.Config is not set") + } + if inst.AccountMetaSlice[2] == nil { + return errors.New("accounts.Authority is not set") + } + if inst.AccountMetaSlice[3] == nil { + return errors.New("accounts.SystemProgram is not set") + } + } + return nil +} + +func (inst *EnableChainSelector) EncodeToTree(parent ag_treeout.Branches) { + parent.Child(ag_format.Program(ProgramName, ProgramID)). + // + ParentFunc(func(programBranch ag_treeout.Branches) { + programBranch.Child(ag_format.Instruction("EnableChainSelector")). + // + ParentFunc(func(instructionBranch ag_treeout.Branches) { + + // Parameters of the instruction: + instructionBranch.Child("Params[len=1]").ParentFunc(func(paramsBranch ag_treeout.Branches) { + paramsBranch.Child(ag_format.Param("NewChainSelector", *inst.NewChainSelector)) + }) + + // Accounts of the instruction: + instructionBranch.Child("Accounts[len=4]").ParentFunc(func(accountsBranch ag_treeout.Branches) { + accountsBranch.Child(ag_format.Meta(" chainState", inst.AccountMetaSlice[0])) + accountsBranch.Child(ag_format.Meta(" config", inst.AccountMetaSlice[1])) + accountsBranch.Child(ag_format.Meta(" authority", inst.AccountMetaSlice[2])) + accountsBranch.Child(ag_format.Meta("systemProgram", inst.AccountMetaSlice[3])) + }) + }) + }) +} + +func (obj EnableChainSelector) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { + // Serialize `NewChainSelector` param: + err = encoder.Encode(obj.NewChainSelector) + if err != nil { + return err + } + return nil +} +func (obj *EnableChainSelector) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { + // Deserialize `NewChainSelector`: + err = decoder.Decode(&obj.NewChainSelector) + if err != nil { + return err + } + return nil +} + +// NewEnableChainSelectorInstruction declares a new EnableChainSelector instruction with the provided parameters and accounts. +func NewEnableChainSelectorInstruction( + // Parameters: + newChainSelector uint64, + // Accounts: + chainState ag_solanago.PublicKey, + config ag_solanago.PublicKey, + authority ag_solanago.PublicKey, + systemProgram ag_solanago.PublicKey) *EnableChainSelector { + return NewEnableChainSelectorInstructionBuilder(). + SetNewChainSelector(newChainSelector). + SetChainStateAccount(chainState). + SetConfigAccount(config). + SetAuthorityAccount(authority). + SetSystemProgramAccount(systemProgram) +} diff --git a/core/capabilities/ccip/ccipsolana/ccip_router/EnableChainSelector_test.go b/core/capabilities/ccip/ccipsolana/ccip_router/EnableChainSelector_test.go new file mode 100644 index 00000000000..f14c09f534a --- /dev/null +++ b/core/capabilities/ccip/ccipsolana/ccip_router/EnableChainSelector_test.go @@ -0,0 +1,32 @@ +// Code generated by https://github.com/gagliardetto/anchor-go. DO NOT EDIT. + +package ccip_router + +import ( + "bytes" + ag_gofuzz "github.com/gagliardetto/gofuzz" + ag_require "github.com/stretchr/testify/require" + "strconv" + "testing" +) + +func TestEncodeDecode_EnableChainSelector(t *testing.T) { + fu := ag_gofuzz.New().NilChance(0) + for i := 0; i < 1; i++ { + t.Run("EnableChainSelector"+strconv.Itoa(i), func(t *testing.T) { + { + params := new(EnableChainSelector) + fu.Fuzz(params) + params.AccountMetaSlice = nil + buf := new(bytes.Buffer) + err := encodeT(*params, buf) + ag_require.NoError(t, err) + got := new(EnableChainSelector) + err = decodeT(got, buf.Bytes()) + got.AccountMetaSlice = nil + ag_require.NoError(t, err) + ag_require.Equal(t, params, got) + } + }) + } +} diff --git a/core/capabilities/ccip/ccipsolana/ccip_router/Execute.go b/core/capabilities/ccip/ccipsolana/ccip_router/Execute.go new file mode 100644 index 00000000000..5ed3628dd1f --- /dev/null +++ b/core/capabilities/ccip/ccipsolana/ccip_router/Execute.go @@ -0,0 +1,293 @@ +// Code generated by https://github.com/gagliardetto/anchor-go. DO NOT EDIT. + +package ccip_router + +import ( + "errors" + ag_binary "github.com/gagliardetto/binary" + ag_solanago "github.com/gagliardetto/solana-go" + ag_format "github.com/gagliardetto/solana-go/text/format" + ag_treeout "github.com/gagliardetto/treeout" +) + +// OFF RAMP FLOW +// +// The method name needs to be execute with Anchor encoding. +// +// This function is called by the OffChain when executing one Report to the Solana Router. +// In this Flow only one message is sent, the Execution Report. This is different as EVM does, +// this is because there is no try/catch mechanism to allow batch execution. +// This message validates that the Merkle Tree Proof of the given message is correct and is stored in the Commit Report Account. +// The message must be untouched to be executed. +// This message emits the event ExecutionStateChanged with the new state of the message. +// Finally, executes the CPI instruction to the receiver program in the ccip_receive message. +type Execute struct { + ExecutionReport *ExecutionReportSingleChain + ReportContext *[3][32]uint8 + + // [0] = [] config + // + // [1] = [] chainState + // + // [2] = [WRITE] commitReport + // + // [3] = [] externalExecutionConfig + // + // [4] = [WRITE, SIGNER] authority + // + // [5] = [] systemProgram + // + // [6] = [] sysvarInstructions + // + // [7] = [] tokenPoolsSigner + ag_solanago.AccountMetaSlice `bin:"-" borsh_skip:"true"` +} + +// NewExecuteInstructionBuilder creates a new `Execute` instruction builder. +func NewExecuteInstructionBuilder() *Execute { + nd := &Execute{ + AccountMetaSlice: make(ag_solanago.AccountMetaSlice, 8), + } + return nd +} + +// SetExecutionReport sets the "executionReport" parameter. +func (inst *Execute) SetExecutionReport(executionReport ExecutionReportSingleChain) *Execute { + inst.ExecutionReport = &executionReport + return inst +} + +// SetReportContext sets the "reportContext" parameter. +func (inst *Execute) SetReportContext(reportContext [3][32]uint8) *Execute { + inst.ReportContext = &reportContext + return inst +} + +// SetConfigAccount sets the "config" account. +func (inst *Execute) SetConfigAccount(config ag_solanago.PublicKey) *Execute { + inst.AccountMetaSlice[0] = ag_solanago.Meta(config) + return inst +} + +// GetConfigAccount gets the "config" account. +func (inst *Execute) GetConfigAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[0] +} + +// SetChainStateAccount sets the "chainState" account. +func (inst *Execute) SetChainStateAccount(chainState ag_solanago.PublicKey) *Execute { + inst.AccountMetaSlice[1] = ag_solanago.Meta(chainState) + return inst +} + +// GetChainStateAccount gets the "chainState" account. +func (inst *Execute) GetChainStateAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[1] +} + +// SetCommitReportAccount sets the "commitReport" account. +func (inst *Execute) SetCommitReportAccount(commitReport ag_solanago.PublicKey) *Execute { + inst.AccountMetaSlice[2] = ag_solanago.Meta(commitReport).WRITE() + return inst +} + +// GetCommitReportAccount gets the "commitReport" account. +func (inst *Execute) GetCommitReportAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[2] +} + +// SetExternalExecutionConfigAccount sets the "externalExecutionConfig" account. +func (inst *Execute) SetExternalExecutionConfigAccount(externalExecutionConfig ag_solanago.PublicKey) *Execute { + inst.AccountMetaSlice[3] = ag_solanago.Meta(externalExecutionConfig) + return inst +} + +// GetExternalExecutionConfigAccount gets the "externalExecutionConfig" account. +func (inst *Execute) GetExternalExecutionConfigAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[3] +} + +// SetAuthorityAccount sets the "authority" account. +func (inst *Execute) SetAuthorityAccount(authority ag_solanago.PublicKey) *Execute { + inst.AccountMetaSlice[4] = ag_solanago.Meta(authority).WRITE().SIGNER() + return inst +} + +// GetAuthorityAccount gets the "authority" account. +func (inst *Execute) GetAuthorityAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[4] +} + +// SetSystemProgramAccount sets the "systemProgram" account. +func (inst *Execute) SetSystemProgramAccount(systemProgram ag_solanago.PublicKey) *Execute { + inst.AccountMetaSlice[5] = ag_solanago.Meta(systemProgram) + return inst +} + +// GetSystemProgramAccount gets the "systemProgram" account. +func (inst *Execute) GetSystemProgramAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[5] +} + +// SetSysvarInstructionsAccount sets the "sysvarInstructions" account. +func (inst *Execute) SetSysvarInstructionsAccount(sysvarInstructions ag_solanago.PublicKey) *Execute { + inst.AccountMetaSlice[6] = ag_solanago.Meta(sysvarInstructions) + return inst +} + +// GetSysvarInstructionsAccount gets the "sysvarInstructions" account. +func (inst *Execute) GetSysvarInstructionsAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[6] +} + +// SetTokenPoolsSignerAccount sets the "tokenPoolsSigner" account. +func (inst *Execute) SetTokenPoolsSignerAccount(tokenPoolsSigner ag_solanago.PublicKey) *Execute { + inst.AccountMetaSlice[7] = ag_solanago.Meta(tokenPoolsSigner) + return inst +} + +// GetTokenPoolsSignerAccount gets the "tokenPoolsSigner" account. +func (inst *Execute) GetTokenPoolsSignerAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[7] +} + +func (inst Execute) Build() *Instruction { + return &Instruction{BaseVariant: ag_binary.BaseVariant{ + Impl: inst, + TypeID: Instruction_Execute, + }} +} + +// ValidateAndBuild validates the instruction parameters and accounts; +// if there is a validation error, it returns the error. +// Otherwise, it builds and returns the instruction. +func (inst Execute) ValidateAndBuild() (*Instruction, error) { + if err := inst.Validate(); err != nil { + return nil, err + } + return inst.Build(), nil +} + +func (inst *Execute) Validate() error { + // Check whether all (required) parameters are set: + { + if inst.ExecutionReport == nil { + return errors.New("ExecutionReport parameter is not set") + } + if inst.ReportContext == nil { + return errors.New("ReportContext parameter is not set") + } + } + + // Check whether all (required) accounts are set: + { + if inst.AccountMetaSlice[0] == nil { + return errors.New("accounts.Config is not set") + } + if inst.AccountMetaSlice[1] == nil { + return errors.New("accounts.ChainState is not set") + } + if inst.AccountMetaSlice[2] == nil { + return errors.New("accounts.CommitReport is not set") + } + if inst.AccountMetaSlice[3] == nil { + return errors.New("accounts.ExternalExecutionConfig is not set") + } + if inst.AccountMetaSlice[4] == nil { + return errors.New("accounts.Authority is not set") + } + if inst.AccountMetaSlice[5] == nil { + return errors.New("accounts.SystemProgram is not set") + } + if inst.AccountMetaSlice[6] == nil { + return errors.New("accounts.SysvarInstructions is not set") + } + if inst.AccountMetaSlice[7] == nil { + return errors.New("accounts.TokenPoolsSigner is not set") + } + } + return nil +} + +func (inst *Execute) EncodeToTree(parent ag_treeout.Branches) { + parent.Child(ag_format.Program(ProgramName, ProgramID)). + // + ParentFunc(func(programBranch ag_treeout.Branches) { + programBranch.Child(ag_format.Instruction("Execute")). + // + ParentFunc(func(instructionBranch ag_treeout.Branches) { + + // Parameters of the instruction: + instructionBranch.Child("Params[len=2]").ParentFunc(func(paramsBranch ag_treeout.Branches) { + paramsBranch.Child(ag_format.Param("ExecutionReport", *inst.ExecutionReport)) + paramsBranch.Child(ag_format.Param(" ReportContext", *inst.ReportContext)) + }) + + // Accounts of the instruction: + instructionBranch.Child("Accounts[len=8]").ParentFunc(func(accountsBranch ag_treeout.Branches) { + accountsBranch.Child(ag_format.Meta(" config", inst.AccountMetaSlice[0])) + accountsBranch.Child(ag_format.Meta(" chainState", inst.AccountMetaSlice[1])) + accountsBranch.Child(ag_format.Meta(" commitReport", inst.AccountMetaSlice[2])) + accountsBranch.Child(ag_format.Meta("externalExecutionConfig", inst.AccountMetaSlice[3])) + accountsBranch.Child(ag_format.Meta(" authority", inst.AccountMetaSlice[4])) + accountsBranch.Child(ag_format.Meta(" systemProgram", inst.AccountMetaSlice[5])) + accountsBranch.Child(ag_format.Meta(" sysvarInstructions", inst.AccountMetaSlice[6])) + accountsBranch.Child(ag_format.Meta(" tokenPoolsSigner", inst.AccountMetaSlice[7])) + }) + }) + }) +} + +func (obj Execute) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { + // Serialize `ExecutionReport` param: + err = encoder.Encode(obj.ExecutionReport) + if err != nil { + return err + } + // Serialize `ReportContext` param: + err = encoder.Encode(obj.ReportContext) + if err != nil { + return err + } + return nil +} +func (obj *Execute) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { + // Deserialize `ExecutionReport`: + err = decoder.Decode(&obj.ExecutionReport) + if err != nil { + return err + } + // Deserialize `ReportContext`: + err = decoder.Decode(&obj.ReportContext) + if err != nil { + return err + } + return nil +} + +// NewExecuteInstruction declares a new Execute instruction with the provided parameters and accounts. +func NewExecuteInstruction( + // Parameters: + executionReport ExecutionReportSingleChain, + reportContext [3][32]uint8, + // Accounts: + config ag_solanago.PublicKey, + chainState ag_solanago.PublicKey, + commitReport ag_solanago.PublicKey, + externalExecutionConfig ag_solanago.PublicKey, + authority ag_solanago.PublicKey, + systemProgram ag_solanago.PublicKey, + sysvarInstructions ag_solanago.PublicKey, + tokenPoolsSigner ag_solanago.PublicKey) *Execute { + return NewExecuteInstructionBuilder(). + SetExecutionReport(executionReport). + SetReportContext(reportContext). + SetConfigAccount(config). + SetChainStateAccount(chainState). + SetCommitReportAccount(commitReport). + SetExternalExecutionConfigAccount(externalExecutionConfig). + SetAuthorityAccount(authority). + SetSystemProgramAccount(systemProgram). + SetSysvarInstructionsAccount(sysvarInstructions). + SetTokenPoolsSignerAccount(tokenPoolsSigner) +} diff --git a/core/capabilities/ccip/ccipsolana/ccip_router/Execute_test.go b/core/capabilities/ccip/ccipsolana/ccip_router/Execute_test.go new file mode 100644 index 00000000000..5c0f4d7b7ff --- /dev/null +++ b/core/capabilities/ccip/ccipsolana/ccip_router/Execute_test.go @@ -0,0 +1,32 @@ +// Code generated by https://github.com/gagliardetto/anchor-go. DO NOT EDIT. + +package ccip_router + +import ( + "bytes" + ag_gofuzz "github.com/gagliardetto/gofuzz" + ag_require "github.com/stretchr/testify/require" + "strconv" + "testing" +) + +func TestEncodeDecode_Execute(t *testing.T) { + fu := ag_gofuzz.New().NilChance(0) + for i := 0; i < 1; i++ { + t.Run("Execute"+strconv.Itoa(i), func(t *testing.T) { + { + params := new(Execute) + fu.Fuzz(params) + params.AccountMetaSlice = nil + buf := new(bytes.Buffer) + err := encodeT(*params, buf) + ag_require.NoError(t, err) + got := new(Execute) + err = decodeT(got, buf.Bytes()) + got.AccountMetaSlice = nil + ag_require.NoError(t, err) + ag_require.Equal(t, params, got) + } + }) + } +} diff --git a/core/capabilities/ccip/ccipsolana/ccip_router/Initialize.go b/core/capabilities/ccip/ccipsolana/ccip_router/Initialize.go new file mode 100644 index 00000000000..ed65234f3e7 --- /dev/null +++ b/core/capabilities/ccip/ccipsolana/ccip_router/Initialize.go @@ -0,0 +1,310 @@ +// Code generated by https://github.com/gagliardetto/anchor-go. DO NOT EDIT. + +package ccip_router + +import ( + "errors" + ag_binary "github.com/gagliardetto/binary" + ag_solanago "github.com/gagliardetto/solana-go" + ag_format "github.com/gagliardetto/solana-go/text/format" + ag_treeout "github.com/gagliardetto/treeout" +) + +// The initialization is responsibility of Admin, nothing more than calling this method should be done first. +type Initialize struct { + SolanaChainSelector *uint64 + DefaultGasLimit *ag_binary.Uint128 + DefaultAllowOutOfOrderExecution *bool + EnableExecutionAfter *int64 + + // [0] = [WRITE] config + // + // [1] = [WRITE, SIGNER] authority + // + // [2] = [] systemProgram + // + // [3] = [] program + // + // [4] = [] programData + // + // [5] = [WRITE] externalExecutionConfig + // + // [6] = [WRITE] tokenPoolsSigner + ag_solanago.AccountMetaSlice `bin:"-" borsh_skip:"true"` +} + +// NewInitializeInstructionBuilder creates a new `Initialize` instruction builder. +func NewInitializeInstructionBuilder() *Initialize { + nd := &Initialize{ + AccountMetaSlice: make(ag_solanago.AccountMetaSlice, 7), + } + return nd +} + +// SetSolanaChainSelector sets the "solanaChainSelector" parameter. +func (inst *Initialize) SetSolanaChainSelector(solanaChainSelector uint64) *Initialize { + inst.SolanaChainSelector = &solanaChainSelector + return inst +} + +// SetDefaultGasLimit sets the "defaultGasLimit" parameter. +func (inst *Initialize) SetDefaultGasLimit(defaultGasLimit ag_binary.Uint128) *Initialize { + inst.DefaultGasLimit = &defaultGasLimit + return inst +} + +// SetDefaultAllowOutOfOrderExecution sets the "defaultAllowOutOfOrderExecution" parameter. +func (inst *Initialize) SetDefaultAllowOutOfOrderExecution(defaultAllowOutOfOrderExecution bool) *Initialize { + inst.DefaultAllowOutOfOrderExecution = &defaultAllowOutOfOrderExecution + return inst +} + +// SetEnableExecutionAfter sets the "enableExecutionAfter" parameter. +func (inst *Initialize) SetEnableExecutionAfter(enableExecutionAfter int64) *Initialize { + inst.EnableExecutionAfter = &enableExecutionAfter + return inst +} + +// SetConfigAccount sets the "config" account. +func (inst *Initialize) SetConfigAccount(config ag_solanago.PublicKey) *Initialize { + inst.AccountMetaSlice[0] = ag_solanago.Meta(config).WRITE() + return inst +} + +// GetConfigAccount gets the "config" account. +func (inst *Initialize) GetConfigAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[0] +} + +// SetAuthorityAccount sets the "authority" account. +func (inst *Initialize) SetAuthorityAccount(authority ag_solanago.PublicKey) *Initialize { + inst.AccountMetaSlice[1] = ag_solanago.Meta(authority).WRITE().SIGNER() + return inst +} + +// GetAuthorityAccount gets the "authority" account. +func (inst *Initialize) GetAuthorityAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[1] +} + +// SetSystemProgramAccount sets the "systemProgram" account. +func (inst *Initialize) SetSystemProgramAccount(systemProgram ag_solanago.PublicKey) *Initialize { + inst.AccountMetaSlice[2] = ag_solanago.Meta(systemProgram) + return inst +} + +// GetSystemProgramAccount gets the "systemProgram" account. +func (inst *Initialize) GetSystemProgramAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[2] +} + +// SetProgramAccount sets the "program" account. +func (inst *Initialize) SetProgramAccount(program ag_solanago.PublicKey) *Initialize { + inst.AccountMetaSlice[3] = ag_solanago.Meta(program) + return inst +} + +// GetProgramAccount gets the "program" account. +func (inst *Initialize) GetProgramAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[3] +} + +// SetProgramDataAccount sets the "programData" account. +func (inst *Initialize) SetProgramDataAccount(programData ag_solanago.PublicKey) *Initialize { + inst.AccountMetaSlice[4] = ag_solanago.Meta(programData) + return inst +} + +// GetProgramDataAccount gets the "programData" account. +func (inst *Initialize) GetProgramDataAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[4] +} + +// SetExternalExecutionConfigAccount sets the "externalExecutionConfig" account. +func (inst *Initialize) SetExternalExecutionConfigAccount(externalExecutionConfig ag_solanago.PublicKey) *Initialize { + inst.AccountMetaSlice[5] = ag_solanago.Meta(externalExecutionConfig).WRITE() + return inst +} + +// GetExternalExecutionConfigAccount gets the "externalExecutionConfig" account. +func (inst *Initialize) GetExternalExecutionConfigAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[5] +} + +// SetTokenPoolsSignerAccount sets the "tokenPoolsSigner" account. +func (inst *Initialize) SetTokenPoolsSignerAccount(tokenPoolsSigner ag_solanago.PublicKey) *Initialize { + inst.AccountMetaSlice[6] = ag_solanago.Meta(tokenPoolsSigner).WRITE() + return inst +} + +// GetTokenPoolsSignerAccount gets the "tokenPoolsSigner" account. +func (inst *Initialize) GetTokenPoolsSignerAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[6] +} + +func (inst Initialize) Build() *Instruction { + return &Instruction{BaseVariant: ag_binary.BaseVariant{ + Impl: inst, + TypeID: Instruction_Initialize, + }} +} + +// ValidateAndBuild validates the instruction parameters and accounts; +// if there is a validation error, it returns the error. +// Otherwise, it builds and returns the instruction. +func (inst Initialize) ValidateAndBuild() (*Instruction, error) { + if err := inst.Validate(); err != nil { + return nil, err + } + return inst.Build(), nil +} + +func (inst *Initialize) Validate() error { + // Check whether all (required) parameters are set: + { + if inst.SolanaChainSelector == nil { + return errors.New("SolanaChainSelector parameter is not set") + } + if inst.DefaultGasLimit == nil { + return errors.New("DefaultGasLimit parameter is not set") + } + if inst.DefaultAllowOutOfOrderExecution == nil { + return errors.New("DefaultAllowOutOfOrderExecution parameter is not set") + } + if inst.EnableExecutionAfter == nil { + return errors.New("EnableExecutionAfter parameter is not set") + } + } + + // Check whether all (required) accounts are set: + { + if inst.AccountMetaSlice[0] == nil { + return errors.New("accounts.Config is not set") + } + if inst.AccountMetaSlice[1] == nil { + return errors.New("accounts.Authority is not set") + } + if inst.AccountMetaSlice[2] == nil { + return errors.New("accounts.SystemProgram is not set") + } + if inst.AccountMetaSlice[3] == nil { + return errors.New("accounts.Program is not set") + } + if inst.AccountMetaSlice[4] == nil { + return errors.New("accounts.ProgramData is not set") + } + if inst.AccountMetaSlice[5] == nil { + return errors.New("accounts.ExternalExecutionConfig is not set") + } + if inst.AccountMetaSlice[6] == nil { + return errors.New("accounts.TokenPoolsSigner is not set") + } + } + return nil +} + +func (inst *Initialize) EncodeToTree(parent ag_treeout.Branches) { + parent.Child(ag_format.Program(ProgramName, ProgramID)). + // + ParentFunc(func(programBranch ag_treeout.Branches) { + programBranch.Child(ag_format.Instruction("Initialize")). + // + ParentFunc(func(instructionBranch ag_treeout.Branches) { + + // Parameters of the instruction: + instructionBranch.Child("Params[len=4]").ParentFunc(func(paramsBranch ag_treeout.Branches) { + paramsBranch.Child(ag_format.Param(" SolanaChainSelector", *inst.SolanaChainSelector)) + paramsBranch.Child(ag_format.Param(" DefaultGasLimit", *inst.DefaultGasLimit)) + paramsBranch.Child(ag_format.Param("DefaultAllowOutOfOrderExecution", *inst.DefaultAllowOutOfOrderExecution)) + paramsBranch.Child(ag_format.Param(" EnableExecutionAfter", *inst.EnableExecutionAfter)) + }) + + // Accounts of the instruction: + instructionBranch.Child("Accounts[len=7]").ParentFunc(func(accountsBranch ag_treeout.Branches) { + accountsBranch.Child(ag_format.Meta(" config", inst.AccountMetaSlice[0])) + accountsBranch.Child(ag_format.Meta(" authority", inst.AccountMetaSlice[1])) + accountsBranch.Child(ag_format.Meta(" systemProgram", inst.AccountMetaSlice[2])) + accountsBranch.Child(ag_format.Meta(" program", inst.AccountMetaSlice[3])) + accountsBranch.Child(ag_format.Meta(" programData", inst.AccountMetaSlice[4])) + accountsBranch.Child(ag_format.Meta("externalExecutionConfig", inst.AccountMetaSlice[5])) + accountsBranch.Child(ag_format.Meta(" tokenPoolsSigner", inst.AccountMetaSlice[6])) + }) + }) + }) +} + +func (obj Initialize) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { + // Serialize `SolanaChainSelector` param: + err = encoder.Encode(obj.SolanaChainSelector) + if err != nil { + return err + } + // Serialize `DefaultGasLimit` param: + err = encoder.Encode(obj.DefaultGasLimit) + if err != nil { + return err + } + // Serialize `DefaultAllowOutOfOrderExecution` param: + err = encoder.Encode(obj.DefaultAllowOutOfOrderExecution) + if err != nil { + return err + } + // Serialize `EnableExecutionAfter` param: + err = encoder.Encode(obj.EnableExecutionAfter) + if err != nil { + return err + } + return nil +} +func (obj *Initialize) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { + // Deserialize `SolanaChainSelector`: + err = decoder.Decode(&obj.SolanaChainSelector) + if err != nil { + return err + } + // Deserialize `DefaultGasLimit`: + err = decoder.Decode(&obj.DefaultGasLimit) + if err != nil { + return err + } + // Deserialize `DefaultAllowOutOfOrderExecution`: + err = decoder.Decode(&obj.DefaultAllowOutOfOrderExecution) + if err != nil { + return err + } + // Deserialize `EnableExecutionAfter`: + err = decoder.Decode(&obj.EnableExecutionAfter) + if err != nil { + return err + } + return nil +} + +// NewInitializeInstruction declares a new Initialize instruction with the provided parameters and accounts. +func NewInitializeInstruction( + // Parameters: + solanaChainSelector uint64, + defaultGasLimit ag_binary.Uint128, + defaultAllowOutOfOrderExecution bool, + enableExecutionAfter int64, + // Accounts: + config ag_solanago.PublicKey, + authority ag_solanago.PublicKey, + systemProgram ag_solanago.PublicKey, + program ag_solanago.PublicKey, + programData ag_solanago.PublicKey, + externalExecutionConfig ag_solanago.PublicKey, + tokenPoolsSigner ag_solanago.PublicKey) *Initialize { + return NewInitializeInstructionBuilder(). + SetSolanaChainSelector(solanaChainSelector). + SetDefaultGasLimit(defaultGasLimit). + SetDefaultAllowOutOfOrderExecution(defaultAllowOutOfOrderExecution). + SetEnableExecutionAfter(enableExecutionAfter). + SetConfigAccount(config). + SetAuthorityAccount(authority). + SetSystemProgramAccount(systemProgram). + SetProgramAccount(program). + SetProgramDataAccount(programData). + SetExternalExecutionConfigAccount(externalExecutionConfig). + SetTokenPoolsSignerAccount(tokenPoolsSigner) +} diff --git a/core/capabilities/ccip/ccipsolana/ccip_router/Initialize_test.go b/core/capabilities/ccip/ccipsolana/ccip_router/Initialize_test.go new file mode 100644 index 00000000000..51eed3384b8 --- /dev/null +++ b/core/capabilities/ccip/ccipsolana/ccip_router/Initialize_test.go @@ -0,0 +1,32 @@ +// Code generated by https://github.com/gagliardetto/anchor-go. DO NOT EDIT. + +package ccip_router + +import ( + "bytes" + ag_gofuzz "github.com/gagliardetto/gofuzz" + ag_require "github.com/stretchr/testify/require" + "strconv" + "testing" +) + +func TestEncodeDecode_Initialize(t *testing.T) { + fu := ag_gofuzz.New().NilChance(0) + for i := 0; i < 1; i++ { + t.Run("Initialize"+strconv.Itoa(i), func(t *testing.T) { + { + params := new(Initialize) + fu.Fuzz(params) + params.AccountMetaSlice = nil + buf := new(bytes.Buffer) + err := encodeT(*params, buf) + ag_require.NoError(t, err) + got := new(Initialize) + err = decodeT(got, buf.Bytes()) + got.AccountMetaSlice = nil + ag_require.NoError(t, err) + ag_require.Equal(t, params, got) + } + }) + } +} diff --git a/core/capabilities/ccip/ccipsolana/ccip_router/ManuallyExecute.go b/core/capabilities/ccip/ccipsolana/ccip_router/ManuallyExecute.go new file mode 100644 index 00000000000..7ec00306a8f --- /dev/null +++ b/core/capabilities/ccip/ccipsolana/ccip_router/ManuallyExecute.go @@ -0,0 +1,261 @@ +// Code generated by https://github.com/gagliardetto/anchor-go. DO NOT EDIT. + +package ccip_router + +import ( + "errors" + ag_binary "github.com/gagliardetto/binary" + ag_solanago "github.com/gagliardetto/solana-go" + ag_format "github.com/gagliardetto/solana-go/text/format" + ag_treeout "github.com/gagliardetto/treeout" +) + +// When a message is not being executed, then the user can trigger the execution manually. +// No verification over the transmitter, but the message needs to be in some commit report. +type ManuallyExecute struct { + ExecutionReport *ExecutionReportSingleChain + + // [0] = [] config + // + // [1] = [] chainState + // + // [2] = [WRITE] commitReport + // + // [3] = [] externalExecutionConfig + // + // [4] = [WRITE, SIGNER] authority + // + // [5] = [] systemProgram + // + // [6] = [] sysvarInstructions + // + // [7] = [] tokenPoolsSigner + ag_solanago.AccountMetaSlice `bin:"-" borsh_skip:"true"` +} + +// NewManuallyExecuteInstructionBuilder creates a new `ManuallyExecute` instruction builder. +func NewManuallyExecuteInstructionBuilder() *ManuallyExecute { + nd := &ManuallyExecute{ + AccountMetaSlice: make(ag_solanago.AccountMetaSlice, 8), + } + return nd +} + +// SetExecutionReport sets the "executionReport" parameter. +func (inst *ManuallyExecute) SetExecutionReport(executionReport ExecutionReportSingleChain) *ManuallyExecute { + inst.ExecutionReport = &executionReport + return inst +} + +// SetConfigAccount sets the "config" account. +func (inst *ManuallyExecute) SetConfigAccount(config ag_solanago.PublicKey) *ManuallyExecute { + inst.AccountMetaSlice[0] = ag_solanago.Meta(config) + return inst +} + +// GetConfigAccount gets the "config" account. +func (inst *ManuallyExecute) GetConfigAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[0] +} + +// SetChainStateAccount sets the "chainState" account. +func (inst *ManuallyExecute) SetChainStateAccount(chainState ag_solanago.PublicKey) *ManuallyExecute { + inst.AccountMetaSlice[1] = ag_solanago.Meta(chainState) + return inst +} + +// GetChainStateAccount gets the "chainState" account. +func (inst *ManuallyExecute) GetChainStateAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[1] +} + +// SetCommitReportAccount sets the "commitReport" account. +func (inst *ManuallyExecute) SetCommitReportAccount(commitReport ag_solanago.PublicKey) *ManuallyExecute { + inst.AccountMetaSlice[2] = ag_solanago.Meta(commitReport).WRITE() + return inst +} + +// GetCommitReportAccount gets the "commitReport" account. +func (inst *ManuallyExecute) GetCommitReportAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[2] +} + +// SetExternalExecutionConfigAccount sets the "externalExecutionConfig" account. +func (inst *ManuallyExecute) SetExternalExecutionConfigAccount(externalExecutionConfig ag_solanago.PublicKey) *ManuallyExecute { + inst.AccountMetaSlice[3] = ag_solanago.Meta(externalExecutionConfig) + return inst +} + +// GetExternalExecutionConfigAccount gets the "externalExecutionConfig" account. +func (inst *ManuallyExecute) GetExternalExecutionConfigAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[3] +} + +// SetAuthorityAccount sets the "authority" account. +func (inst *ManuallyExecute) SetAuthorityAccount(authority ag_solanago.PublicKey) *ManuallyExecute { + inst.AccountMetaSlice[4] = ag_solanago.Meta(authority).WRITE().SIGNER() + return inst +} + +// GetAuthorityAccount gets the "authority" account. +func (inst *ManuallyExecute) GetAuthorityAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[4] +} + +// SetSystemProgramAccount sets the "systemProgram" account. +func (inst *ManuallyExecute) SetSystemProgramAccount(systemProgram ag_solanago.PublicKey) *ManuallyExecute { + inst.AccountMetaSlice[5] = ag_solanago.Meta(systemProgram) + return inst +} + +// GetSystemProgramAccount gets the "systemProgram" account. +func (inst *ManuallyExecute) GetSystemProgramAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[5] +} + +// SetSysvarInstructionsAccount sets the "sysvarInstructions" account. +func (inst *ManuallyExecute) SetSysvarInstructionsAccount(sysvarInstructions ag_solanago.PublicKey) *ManuallyExecute { + inst.AccountMetaSlice[6] = ag_solanago.Meta(sysvarInstructions) + return inst +} + +// GetSysvarInstructionsAccount gets the "sysvarInstructions" account. +func (inst *ManuallyExecute) GetSysvarInstructionsAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[6] +} + +// SetTokenPoolsSignerAccount sets the "tokenPoolsSigner" account. +func (inst *ManuallyExecute) SetTokenPoolsSignerAccount(tokenPoolsSigner ag_solanago.PublicKey) *ManuallyExecute { + inst.AccountMetaSlice[7] = ag_solanago.Meta(tokenPoolsSigner) + return inst +} + +// GetTokenPoolsSignerAccount gets the "tokenPoolsSigner" account. +func (inst *ManuallyExecute) GetTokenPoolsSignerAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[7] +} + +func (inst ManuallyExecute) Build() *Instruction { + return &Instruction{BaseVariant: ag_binary.BaseVariant{ + Impl: inst, + TypeID: Instruction_ManuallyExecute, + }} +} + +// ValidateAndBuild validates the instruction parameters and accounts; +// if there is a validation error, it returns the error. +// Otherwise, it builds and returns the instruction. +func (inst ManuallyExecute) ValidateAndBuild() (*Instruction, error) { + if err := inst.Validate(); err != nil { + return nil, err + } + return inst.Build(), nil +} + +func (inst *ManuallyExecute) Validate() error { + // Check whether all (required) parameters are set: + { + if inst.ExecutionReport == nil { + return errors.New("ExecutionReport parameter is not set") + } + } + + // Check whether all (required) accounts are set: + { + if inst.AccountMetaSlice[0] == nil { + return errors.New("accounts.Config is not set") + } + if inst.AccountMetaSlice[1] == nil { + return errors.New("accounts.ChainState is not set") + } + if inst.AccountMetaSlice[2] == nil { + return errors.New("accounts.CommitReport is not set") + } + if inst.AccountMetaSlice[3] == nil { + return errors.New("accounts.ExternalExecutionConfig is not set") + } + if inst.AccountMetaSlice[4] == nil { + return errors.New("accounts.Authority is not set") + } + if inst.AccountMetaSlice[5] == nil { + return errors.New("accounts.SystemProgram is not set") + } + if inst.AccountMetaSlice[6] == nil { + return errors.New("accounts.SysvarInstructions is not set") + } + if inst.AccountMetaSlice[7] == nil { + return errors.New("accounts.TokenPoolsSigner is not set") + } + } + return nil +} + +func (inst *ManuallyExecute) EncodeToTree(parent ag_treeout.Branches) { + parent.Child(ag_format.Program(ProgramName, ProgramID)). + // + ParentFunc(func(programBranch ag_treeout.Branches) { + programBranch.Child(ag_format.Instruction("ManuallyExecute")). + // + ParentFunc(func(instructionBranch ag_treeout.Branches) { + + // Parameters of the instruction: + instructionBranch.Child("Params[len=1]").ParentFunc(func(paramsBranch ag_treeout.Branches) { + paramsBranch.Child(ag_format.Param("ExecutionReport", *inst.ExecutionReport)) + }) + + // Accounts of the instruction: + instructionBranch.Child("Accounts[len=8]").ParentFunc(func(accountsBranch ag_treeout.Branches) { + accountsBranch.Child(ag_format.Meta(" config", inst.AccountMetaSlice[0])) + accountsBranch.Child(ag_format.Meta(" chainState", inst.AccountMetaSlice[1])) + accountsBranch.Child(ag_format.Meta(" commitReport", inst.AccountMetaSlice[2])) + accountsBranch.Child(ag_format.Meta("externalExecutionConfig", inst.AccountMetaSlice[3])) + accountsBranch.Child(ag_format.Meta(" authority", inst.AccountMetaSlice[4])) + accountsBranch.Child(ag_format.Meta(" systemProgram", inst.AccountMetaSlice[5])) + accountsBranch.Child(ag_format.Meta(" sysvarInstructions", inst.AccountMetaSlice[6])) + accountsBranch.Child(ag_format.Meta(" tokenPoolsSigner", inst.AccountMetaSlice[7])) + }) + }) + }) +} + +func (obj ManuallyExecute) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { + // Serialize `ExecutionReport` param: + err = encoder.Encode(obj.ExecutionReport) + if err != nil { + return err + } + return nil +} +func (obj *ManuallyExecute) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { + // Deserialize `ExecutionReport`: + err = decoder.Decode(&obj.ExecutionReport) + if err != nil { + return err + } + return nil +} + +// NewManuallyExecuteInstruction declares a new ManuallyExecute instruction with the provided parameters and accounts. +func NewManuallyExecuteInstruction( + // Parameters: + executionReport ExecutionReportSingleChain, + // Accounts: + config ag_solanago.PublicKey, + chainState ag_solanago.PublicKey, + commitReport ag_solanago.PublicKey, + externalExecutionConfig ag_solanago.PublicKey, + authority ag_solanago.PublicKey, + systemProgram ag_solanago.PublicKey, + sysvarInstructions ag_solanago.PublicKey, + tokenPoolsSigner ag_solanago.PublicKey) *ManuallyExecute { + return NewManuallyExecuteInstructionBuilder(). + SetExecutionReport(executionReport). + SetConfigAccount(config). + SetChainStateAccount(chainState). + SetCommitReportAccount(commitReport). + SetExternalExecutionConfigAccount(externalExecutionConfig). + SetAuthorityAccount(authority). + SetSystemProgramAccount(systemProgram). + SetSysvarInstructionsAccount(sysvarInstructions). + SetTokenPoolsSignerAccount(tokenPoolsSigner) +} diff --git a/core/capabilities/ccip/ccipsolana/ccip_router/ManuallyExecute_test.go b/core/capabilities/ccip/ccipsolana/ccip_router/ManuallyExecute_test.go new file mode 100644 index 00000000000..38f8fe33c61 --- /dev/null +++ b/core/capabilities/ccip/ccipsolana/ccip_router/ManuallyExecute_test.go @@ -0,0 +1,32 @@ +// Code generated by https://github.com/gagliardetto/anchor-go. DO NOT EDIT. + +package ccip_router + +import ( + "bytes" + ag_gofuzz "github.com/gagliardetto/gofuzz" + ag_require "github.com/stretchr/testify/require" + "strconv" + "testing" +) + +func TestEncodeDecode_ManuallyExecute(t *testing.T) { + fu := ag_gofuzz.New().NilChance(0) + for i := 0; i < 1; i++ { + t.Run("ManuallyExecute"+strconv.Itoa(i), func(t *testing.T) { + { + params := new(ManuallyExecute) + fu.Fuzz(params) + params.AccountMetaSlice = nil + buf := new(bytes.Buffer) + err := encodeT(*params, buf) + ag_require.NoError(t, err) + got := new(ManuallyExecute) + err = decodeT(got, buf.Bytes()) + got.AccountMetaSlice = nil + ag_require.NoError(t, err) + ag_require.Equal(t, params, got) + } + }) + } +} diff --git a/core/capabilities/ccip/ccipsolana/ccip_router/RegisterTokenAdminRegistryViaGetCcipAdmin.go b/core/capabilities/ccip/ccipsolana/ccip_router/RegisterTokenAdminRegistryViaGetCcipAdmin.go new file mode 100644 index 00000000000..20ed495cdb4 --- /dev/null +++ b/core/capabilities/ccip/ccipsolana/ccip_router/RegisterTokenAdminRegistryViaGetCcipAdmin.go @@ -0,0 +1,207 @@ +// Code generated by https://github.com/gagliardetto/anchor-go. DO NOT EDIT. + +package ccip_router + +import ( + "errors" + ag_binary "github.com/gagliardetto/binary" + ag_solanago "github.com/gagliardetto/solana-go" + ag_format "github.com/gagliardetto/solana-go/text/format" + ag_treeout "github.com/gagliardetto/treeout" +) + +// The CCIP Admin or the Mint Authority of the Token can register the Token Admin Registry +type RegisterTokenAdminRegistryViaGetCcipAdmin struct { + Mint *ag_solanago.PublicKey + TokenAdminRegistryAdmin *ag_solanago.PublicKey + + // [0] = [] config + // + // [1] = [WRITE] tokenAdminRegistry + // + // [2] = [WRITE, SIGNER] authority + // + // [3] = [] systemProgram + ag_solanago.AccountMetaSlice `bin:"-" borsh_skip:"true"` +} + +// NewRegisterTokenAdminRegistryViaGetCcipAdminInstructionBuilder creates a new `RegisterTokenAdminRegistryViaGetCcipAdmin` instruction builder. +func NewRegisterTokenAdminRegistryViaGetCcipAdminInstructionBuilder() *RegisterTokenAdminRegistryViaGetCcipAdmin { + nd := &RegisterTokenAdminRegistryViaGetCcipAdmin{ + AccountMetaSlice: make(ag_solanago.AccountMetaSlice, 4), + } + return nd +} + +// SetMint sets the "mint" parameter. +func (inst *RegisterTokenAdminRegistryViaGetCcipAdmin) SetMint(mint ag_solanago.PublicKey) *RegisterTokenAdminRegistryViaGetCcipAdmin { + inst.Mint = &mint + return inst +} + +// SetTokenAdminRegistryAdmin sets the "tokenAdminRegistryAdmin" parameter. +func (inst *RegisterTokenAdminRegistryViaGetCcipAdmin) SetTokenAdminRegistryAdmin(tokenAdminRegistryAdmin ag_solanago.PublicKey) *RegisterTokenAdminRegistryViaGetCcipAdmin { + inst.TokenAdminRegistryAdmin = &tokenAdminRegistryAdmin + return inst +} + +// SetConfigAccount sets the "config" account. +func (inst *RegisterTokenAdminRegistryViaGetCcipAdmin) SetConfigAccount(config ag_solanago.PublicKey) *RegisterTokenAdminRegistryViaGetCcipAdmin { + inst.AccountMetaSlice[0] = ag_solanago.Meta(config) + return inst +} + +// GetConfigAccount gets the "config" account. +func (inst *RegisterTokenAdminRegistryViaGetCcipAdmin) GetConfigAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[0] +} + +// SetTokenAdminRegistryAccount sets the "tokenAdminRegistry" account. +func (inst *RegisterTokenAdminRegistryViaGetCcipAdmin) SetTokenAdminRegistryAccount(tokenAdminRegistry ag_solanago.PublicKey) *RegisterTokenAdminRegistryViaGetCcipAdmin { + inst.AccountMetaSlice[1] = ag_solanago.Meta(tokenAdminRegistry).WRITE() + return inst +} + +// GetTokenAdminRegistryAccount gets the "tokenAdminRegistry" account. +func (inst *RegisterTokenAdminRegistryViaGetCcipAdmin) GetTokenAdminRegistryAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[1] +} + +// SetAuthorityAccount sets the "authority" account. +func (inst *RegisterTokenAdminRegistryViaGetCcipAdmin) SetAuthorityAccount(authority ag_solanago.PublicKey) *RegisterTokenAdminRegistryViaGetCcipAdmin { + inst.AccountMetaSlice[2] = ag_solanago.Meta(authority).WRITE().SIGNER() + return inst +} + +// GetAuthorityAccount gets the "authority" account. +func (inst *RegisterTokenAdminRegistryViaGetCcipAdmin) GetAuthorityAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[2] +} + +// SetSystemProgramAccount sets the "systemProgram" account. +func (inst *RegisterTokenAdminRegistryViaGetCcipAdmin) SetSystemProgramAccount(systemProgram ag_solanago.PublicKey) *RegisterTokenAdminRegistryViaGetCcipAdmin { + inst.AccountMetaSlice[3] = ag_solanago.Meta(systemProgram) + return inst +} + +// GetSystemProgramAccount gets the "systemProgram" account. +func (inst *RegisterTokenAdminRegistryViaGetCcipAdmin) GetSystemProgramAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[3] +} + +func (inst RegisterTokenAdminRegistryViaGetCcipAdmin) Build() *Instruction { + return &Instruction{BaseVariant: ag_binary.BaseVariant{ + Impl: inst, + TypeID: Instruction_RegisterTokenAdminRegistryViaGetCcipAdmin, + }} +} + +// ValidateAndBuild validates the instruction parameters and accounts; +// if there is a validation error, it returns the error. +// Otherwise, it builds and returns the instruction. +func (inst RegisterTokenAdminRegistryViaGetCcipAdmin) ValidateAndBuild() (*Instruction, error) { + if err := inst.Validate(); err != nil { + return nil, err + } + return inst.Build(), nil +} + +func (inst *RegisterTokenAdminRegistryViaGetCcipAdmin) Validate() error { + // Check whether all (required) parameters are set: + { + if inst.Mint == nil { + return errors.New("Mint parameter is not set") + } + if inst.TokenAdminRegistryAdmin == nil { + return errors.New("TokenAdminRegistryAdmin parameter is not set") + } + } + + // Check whether all (required) accounts are set: + { + if inst.AccountMetaSlice[0] == nil { + return errors.New("accounts.Config is not set") + } + if inst.AccountMetaSlice[1] == nil { + return errors.New("accounts.TokenAdminRegistry is not set") + } + if inst.AccountMetaSlice[2] == nil { + return errors.New("accounts.Authority is not set") + } + if inst.AccountMetaSlice[3] == nil { + return errors.New("accounts.SystemProgram is not set") + } + } + return nil +} + +func (inst *RegisterTokenAdminRegistryViaGetCcipAdmin) EncodeToTree(parent ag_treeout.Branches) { + parent.Child(ag_format.Program(ProgramName, ProgramID)). + // + ParentFunc(func(programBranch ag_treeout.Branches) { + programBranch.Child(ag_format.Instruction("RegisterTokenAdminRegistryViaGetCcipAdmin")). + // + ParentFunc(func(instructionBranch ag_treeout.Branches) { + + // Parameters of the instruction: + instructionBranch.Child("Params[len=2]").ParentFunc(func(paramsBranch ag_treeout.Branches) { + paramsBranch.Child(ag_format.Param(" Mint", *inst.Mint)) + paramsBranch.Child(ag_format.Param("TokenAdminRegistryAdmin", *inst.TokenAdminRegistryAdmin)) + }) + + // Accounts of the instruction: + instructionBranch.Child("Accounts[len=4]").ParentFunc(func(accountsBranch ag_treeout.Branches) { + accountsBranch.Child(ag_format.Meta(" config", inst.AccountMetaSlice[0])) + accountsBranch.Child(ag_format.Meta("tokenAdminRegistry", inst.AccountMetaSlice[1])) + accountsBranch.Child(ag_format.Meta(" authority", inst.AccountMetaSlice[2])) + accountsBranch.Child(ag_format.Meta(" systemProgram", inst.AccountMetaSlice[3])) + }) + }) + }) +} + +func (obj RegisterTokenAdminRegistryViaGetCcipAdmin) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { + // Serialize `Mint` param: + err = encoder.Encode(obj.Mint) + if err != nil { + return err + } + // Serialize `TokenAdminRegistryAdmin` param: + err = encoder.Encode(obj.TokenAdminRegistryAdmin) + if err != nil { + return err + } + return nil +} +func (obj *RegisterTokenAdminRegistryViaGetCcipAdmin) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { + // Deserialize `Mint`: + err = decoder.Decode(&obj.Mint) + if err != nil { + return err + } + // Deserialize `TokenAdminRegistryAdmin`: + err = decoder.Decode(&obj.TokenAdminRegistryAdmin) + if err != nil { + return err + } + return nil +} + +// NewRegisterTokenAdminRegistryViaGetCcipAdminInstruction declares a new RegisterTokenAdminRegistryViaGetCcipAdmin instruction with the provided parameters and accounts. +func NewRegisterTokenAdminRegistryViaGetCcipAdminInstruction( + // Parameters: + mint ag_solanago.PublicKey, + tokenAdminRegistryAdmin ag_solanago.PublicKey, + // Accounts: + config ag_solanago.PublicKey, + tokenAdminRegistry ag_solanago.PublicKey, + authority ag_solanago.PublicKey, + systemProgram ag_solanago.PublicKey) *RegisterTokenAdminRegistryViaGetCcipAdmin { + return NewRegisterTokenAdminRegistryViaGetCcipAdminInstructionBuilder(). + SetMint(mint). + SetTokenAdminRegistryAdmin(tokenAdminRegistryAdmin). + SetConfigAccount(config). + SetTokenAdminRegistryAccount(tokenAdminRegistry). + SetAuthorityAccount(authority). + SetSystemProgramAccount(systemProgram) +} diff --git a/core/capabilities/ccip/ccipsolana/ccip_router/RegisterTokenAdminRegistryViaGetCcipAdmin_test.go b/core/capabilities/ccip/ccipsolana/ccip_router/RegisterTokenAdminRegistryViaGetCcipAdmin_test.go new file mode 100644 index 00000000000..29a2c212a49 --- /dev/null +++ b/core/capabilities/ccip/ccipsolana/ccip_router/RegisterTokenAdminRegistryViaGetCcipAdmin_test.go @@ -0,0 +1,32 @@ +// Code generated by https://github.com/gagliardetto/anchor-go. DO NOT EDIT. + +package ccip_router + +import ( + "bytes" + ag_gofuzz "github.com/gagliardetto/gofuzz" + ag_require "github.com/stretchr/testify/require" + "strconv" + "testing" +) + +func TestEncodeDecode_RegisterTokenAdminRegistryViaGetCcipAdmin(t *testing.T) { + fu := ag_gofuzz.New().NilChance(0) + for i := 0; i < 1; i++ { + t.Run("RegisterTokenAdminRegistryViaGetCcipAdmin"+strconv.Itoa(i), func(t *testing.T) { + { + params := new(RegisterTokenAdminRegistryViaGetCcipAdmin) + fu.Fuzz(params) + params.AccountMetaSlice = nil + buf := new(bytes.Buffer) + err := encodeT(*params, buf) + ag_require.NoError(t, err) + got := new(RegisterTokenAdminRegistryViaGetCcipAdmin) + err = decodeT(got, buf.Bytes()) + got.AccountMetaSlice = nil + ag_require.NoError(t, err) + ag_require.Equal(t, params, got) + } + }) + } +} diff --git a/core/capabilities/ccip/ccipsolana/ccip_router/RegisterTokenAdminRegistryViaOwner.go b/core/capabilities/ccip/ccipsolana/ccip_router/RegisterTokenAdminRegistryViaOwner.go new file mode 100644 index 00000000000..eb79b822606 --- /dev/null +++ b/core/capabilities/ccip/ccipsolana/ccip_router/RegisterTokenAdminRegistryViaOwner.go @@ -0,0 +1,155 @@ +// Code generated by https://github.com/gagliardetto/anchor-go. DO NOT EDIT. + +package ccip_router + +import ( + "errors" + ag_binary "github.com/gagliardetto/binary" + ag_solanago "github.com/gagliardetto/solana-go" + ag_format "github.com/gagliardetto/solana-go/text/format" + ag_treeout "github.com/gagliardetto/treeout" +) + +// The Token's mint_authority can register themselves to the Token Admin Registry +type RegisterTokenAdminRegistryViaOwner struct { + + // [0] = [WRITE] tokenAdminRegistry + // + // [1] = [WRITE] mint + // + // [2] = [WRITE, SIGNER] authority + // + // [3] = [] systemProgram + ag_solanago.AccountMetaSlice `bin:"-" borsh_skip:"true"` +} + +// NewRegisterTokenAdminRegistryViaOwnerInstructionBuilder creates a new `RegisterTokenAdminRegistryViaOwner` instruction builder. +func NewRegisterTokenAdminRegistryViaOwnerInstructionBuilder() *RegisterTokenAdminRegistryViaOwner { + nd := &RegisterTokenAdminRegistryViaOwner{ + AccountMetaSlice: make(ag_solanago.AccountMetaSlice, 4), + } + return nd +} + +// SetTokenAdminRegistryAccount sets the "tokenAdminRegistry" account. +func (inst *RegisterTokenAdminRegistryViaOwner) SetTokenAdminRegistryAccount(tokenAdminRegistry ag_solanago.PublicKey) *RegisterTokenAdminRegistryViaOwner { + inst.AccountMetaSlice[0] = ag_solanago.Meta(tokenAdminRegistry).WRITE() + return inst +} + +// GetTokenAdminRegistryAccount gets the "tokenAdminRegistry" account. +func (inst *RegisterTokenAdminRegistryViaOwner) GetTokenAdminRegistryAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[0] +} + +// SetMintAccount sets the "mint" account. +func (inst *RegisterTokenAdminRegistryViaOwner) SetMintAccount(mint ag_solanago.PublicKey) *RegisterTokenAdminRegistryViaOwner { + inst.AccountMetaSlice[1] = ag_solanago.Meta(mint).WRITE() + return inst +} + +// GetMintAccount gets the "mint" account. +func (inst *RegisterTokenAdminRegistryViaOwner) GetMintAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[1] +} + +// SetAuthorityAccount sets the "authority" account. +func (inst *RegisterTokenAdminRegistryViaOwner) SetAuthorityAccount(authority ag_solanago.PublicKey) *RegisterTokenAdminRegistryViaOwner { + inst.AccountMetaSlice[2] = ag_solanago.Meta(authority).WRITE().SIGNER() + return inst +} + +// GetAuthorityAccount gets the "authority" account. +func (inst *RegisterTokenAdminRegistryViaOwner) GetAuthorityAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[2] +} + +// SetSystemProgramAccount sets the "systemProgram" account. +func (inst *RegisterTokenAdminRegistryViaOwner) SetSystemProgramAccount(systemProgram ag_solanago.PublicKey) *RegisterTokenAdminRegistryViaOwner { + inst.AccountMetaSlice[3] = ag_solanago.Meta(systemProgram) + return inst +} + +// GetSystemProgramAccount gets the "systemProgram" account. +func (inst *RegisterTokenAdminRegistryViaOwner) GetSystemProgramAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[3] +} + +func (inst RegisterTokenAdminRegistryViaOwner) Build() *Instruction { + return &Instruction{BaseVariant: ag_binary.BaseVariant{ + Impl: inst, + TypeID: Instruction_RegisterTokenAdminRegistryViaOwner, + }} +} + +// ValidateAndBuild validates the instruction parameters and accounts; +// if there is a validation error, it returns the error. +// Otherwise, it builds and returns the instruction. +func (inst RegisterTokenAdminRegistryViaOwner) ValidateAndBuild() (*Instruction, error) { + if err := inst.Validate(); err != nil { + return nil, err + } + return inst.Build(), nil +} + +func (inst *RegisterTokenAdminRegistryViaOwner) Validate() error { + // Check whether all (required) accounts are set: + { + if inst.AccountMetaSlice[0] == nil { + return errors.New("accounts.TokenAdminRegistry is not set") + } + if inst.AccountMetaSlice[1] == nil { + return errors.New("accounts.Mint is not set") + } + if inst.AccountMetaSlice[2] == nil { + return errors.New("accounts.Authority is not set") + } + if inst.AccountMetaSlice[3] == nil { + return errors.New("accounts.SystemProgram is not set") + } + } + return nil +} + +func (inst *RegisterTokenAdminRegistryViaOwner) EncodeToTree(parent ag_treeout.Branches) { + parent.Child(ag_format.Program(ProgramName, ProgramID)). + // + ParentFunc(func(programBranch ag_treeout.Branches) { + programBranch.Child(ag_format.Instruction("RegisterTokenAdminRegistryViaOwner")). + // + ParentFunc(func(instructionBranch ag_treeout.Branches) { + + // Parameters of the instruction: + instructionBranch.Child("Params[len=0]").ParentFunc(func(paramsBranch ag_treeout.Branches) {}) + + // Accounts of the instruction: + instructionBranch.Child("Accounts[len=4]").ParentFunc(func(accountsBranch ag_treeout.Branches) { + accountsBranch.Child(ag_format.Meta("tokenAdminRegistry", inst.AccountMetaSlice[0])) + accountsBranch.Child(ag_format.Meta(" mint", inst.AccountMetaSlice[1])) + accountsBranch.Child(ag_format.Meta(" authority", inst.AccountMetaSlice[2])) + accountsBranch.Child(ag_format.Meta(" systemProgram", inst.AccountMetaSlice[3])) + }) + }) + }) +} + +func (obj RegisterTokenAdminRegistryViaOwner) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { + return nil +} +func (obj *RegisterTokenAdminRegistryViaOwner) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { + return nil +} + +// NewRegisterTokenAdminRegistryViaOwnerInstruction declares a new RegisterTokenAdminRegistryViaOwner instruction with the provided parameters and accounts. +func NewRegisterTokenAdminRegistryViaOwnerInstruction( + // Accounts: + tokenAdminRegistry ag_solanago.PublicKey, + mint ag_solanago.PublicKey, + authority ag_solanago.PublicKey, + systemProgram ag_solanago.PublicKey) *RegisterTokenAdminRegistryViaOwner { + return NewRegisterTokenAdminRegistryViaOwnerInstructionBuilder(). + SetTokenAdminRegistryAccount(tokenAdminRegistry). + SetMintAccount(mint). + SetAuthorityAccount(authority). + SetSystemProgramAccount(systemProgram) +} diff --git a/core/capabilities/ccip/ccipsolana/ccip_router/RegisterTokenAdminRegistryViaOwner_test.go b/core/capabilities/ccip/ccipsolana/ccip_router/RegisterTokenAdminRegistryViaOwner_test.go new file mode 100644 index 00000000000..ea293f88b2e --- /dev/null +++ b/core/capabilities/ccip/ccipsolana/ccip_router/RegisterTokenAdminRegistryViaOwner_test.go @@ -0,0 +1,32 @@ +// Code generated by https://github.com/gagliardetto/anchor-go. DO NOT EDIT. + +package ccip_router + +import ( + "bytes" + ag_gofuzz "github.com/gagliardetto/gofuzz" + ag_require "github.com/stretchr/testify/require" + "strconv" + "testing" +) + +func TestEncodeDecode_RegisterTokenAdminRegistryViaOwner(t *testing.T) { + fu := ag_gofuzz.New().NilChance(0) + for i := 0; i < 1; i++ { + t.Run("RegisterTokenAdminRegistryViaOwner"+strconv.Itoa(i), func(t *testing.T) { + { + params := new(RegisterTokenAdminRegistryViaOwner) + fu.Fuzz(params) + params.AccountMetaSlice = nil + buf := new(bytes.Buffer) + err := encodeT(*params, buf) + ag_require.NoError(t, err) + got := new(RegisterTokenAdminRegistryViaOwner) + err = decodeT(got, buf.Bytes()) + got.AccountMetaSlice = nil + ag_require.NoError(t, err) + ag_require.Equal(t, params, got) + } + }) + } +} diff --git a/core/capabilities/ccip/ccipsolana/ccip_router/SetOcrConfig.go b/core/capabilities/ccip/ccipsolana/ccip_router/SetOcrConfig.go new file mode 100644 index 00000000000..3a6420a6980 --- /dev/null +++ b/core/capabilities/ccip/ccipsolana/ccip_router/SetOcrConfig.go @@ -0,0 +1,215 @@ +// Code generated by https://github.com/gagliardetto/anchor-go. DO NOT EDIT. + +package ccip_router + +import ( + "errors" + ag_binary "github.com/gagliardetto/binary" + ag_solanago "github.com/gagliardetto/solana-go" + ag_format "github.com/gagliardetto/solana-go/text/format" + ag_treeout "github.com/gagliardetto/treeout" +) + +// SetOcrConfig is the `setOcrConfig` instruction. +type SetOcrConfig struct { + PluginType *uint8 + ConfigInfo *Ocr3ConfigInfo + Signers *[][20]uint8 + Transmitters *[]ag_solanago.PublicKey + + // [0] = [WRITE] config + // + // [1] = [SIGNER] authority + ag_solanago.AccountMetaSlice `bin:"-" borsh_skip:"true"` +} + +// NewSetOcrConfigInstructionBuilder creates a new `SetOcrConfig` instruction builder. +func NewSetOcrConfigInstructionBuilder() *SetOcrConfig { + nd := &SetOcrConfig{ + AccountMetaSlice: make(ag_solanago.AccountMetaSlice, 2), + } + return nd +} + +// SetPluginType sets the "pluginType" parameter. +func (inst *SetOcrConfig) SetPluginType(pluginType uint8) *SetOcrConfig { + inst.PluginType = &pluginType + return inst +} + +// SetConfigInfo sets the "configInfo" parameter. +func (inst *SetOcrConfig) SetConfigInfo(configInfo Ocr3ConfigInfo) *SetOcrConfig { + inst.ConfigInfo = &configInfo + return inst +} + +// SetSigners sets the "signers" parameter. +func (inst *SetOcrConfig) SetSigners(signers [][20]uint8) *SetOcrConfig { + inst.Signers = &signers + return inst +} + +// SetTransmitters sets the "transmitters" parameter. +func (inst *SetOcrConfig) SetTransmitters(transmitters []ag_solanago.PublicKey) *SetOcrConfig { + inst.Transmitters = &transmitters + return inst +} + +// SetConfigAccount sets the "config" account. +func (inst *SetOcrConfig) SetConfigAccount(config ag_solanago.PublicKey) *SetOcrConfig { + inst.AccountMetaSlice[0] = ag_solanago.Meta(config).WRITE() + return inst +} + +// GetConfigAccount gets the "config" account. +func (inst *SetOcrConfig) GetConfigAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[0] +} + +// SetAuthorityAccount sets the "authority" account. +func (inst *SetOcrConfig) SetAuthorityAccount(authority ag_solanago.PublicKey) *SetOcrConfig { + inst.AccountMetaSlice[1] = ag_solanago.Meta(authority).SIGNER() + return inst +} + +// GetAuthorityAccount gets the "authority" account. +func (inst *SetOcrConfig) GetAuthorityAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[1] +} + +func (inst SetOcrConfig) Build() *Instruction { + return &Instruction{BaseVariant: ag_binary.BaseVariant{ + Impl: inst, + TypeID: Instruction_SetOcrConfig, + }} +} + +// ValidateAndBuild validates the instruction parameters and accounts; +// if there is a validation error, it returns the error. +// Otherwise, it builds and returns the instruction. +func (inst SetOcrConfig) ValidateAndBuild() (*Instruction, error) { + if err := inst.Validate(); err != nil { + return nil, err + } + return inst.Build(), nil +} + +func (inst *SetOcrConfig) Validate() error { + // Check whether all (required) parameters are set: + { + if inst.PluginType == nil { + return errors.New("PluginType parameter is not set") + } + if inst.ConfigInfo == nil { + return errors.New("ConfigInfo parameter is not set") + } + if inst.Signers == nil { + return errors.New("Signers parameter is not set") + } + if inst.Transmitters == nil { + return errors.New("Transmitters parameter is not set") + } + } + + // Check whether all (required) accounts are set: + { + if inst.AccountMetaSlice[0] == nil { + return errors.New("accounts.Config is not set") + } + if inst.AccountMetaSlice[1] == nil { + return errors.New("accounts.Authority is not set") + } + } + return nil +} + +func (inst *SetOcrConfig) EncodeToTree(parent ag_treeout.Branches) { + parent.Child(ag_format.Program(ProgramName, ProgramID)). + // + ParentFunc(func(programBranch ag_treeout.Branches) { + programBranch.Child(ag_format.Instruction("SetOcrConfig")). + // + ParentFunc(func(instructionBranch ag_treeout.Branches) { + + // Parameters of the instruction: + instructionBranch.Child("Params[len=4]").ParentFunc(func(paramsBranch ag_treeout.Branches) { + paramsBranch.Child(ag_format.Param(" PluginType", *inst.PluginType)) + paramsBranch.Child(ag_format.Param(" ConfigInfo", *inst.ConfigInfo)) + paramsBranch.Child(ag_format.Param(" Signers", *inst.Signers)) + paramsBranch.Child(ag_format.Param("Transmitters", *inst.Transmitters)) + }) + + // Accounts of the instruction: + instructionBranch.Child("Accounts[len=2]").ParentFunc(func(accountsBranch ag_treeout.Branches) { + accountsBranch.Child(ag_format.Meta(" config", inst.AccountMetaSlice[0])) + accountsBranch.Child(ag_format.Meta("authority", inst.AccountMetaSlice[1])) + }) + }) + }) +} + +func (obj SetOcrConfig) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { + // Serialize `PluginType` param: + err = encoder.Encode(obj.PluginType) + if err != nil { + return err + } + // Serialize `ConfigInfo` param: + err = encoder.Encode(obj.ConfigInfo) + if err != nil { + return err + } + // Serialize `Signers` param: + err = encoder.Encode(obj.Signers) + if err != nil { + return err + } + // Serialize `Transmitters` param: + err = encoder.Encode(obj.Transmitters) + if err != nil { + return err + } + return nil +} +func (obj *SetOcrConfig) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { + // Deserialize `PluginType`: + err = decoder.Decode(&obj.PluginType) + if err != nil { + return err + } + // Deserialize `ConfigInfo`: + err = decoder.Decode(&obj.ConfigInfo) + if err != nil { + return err + } + // Deserialize `Signers`: + err = decoder.Decode(&obj.Signers) + if err != nil { + return err + } + // Deserialize `Transmitters`: + err = decoder.Decode(&obj.Transmitters) + if err != nil { + return err + } + return nil +} + +// NewSetOcrConfigInstruction declares a new SetOcrConfig instruction with the provided parameters and accounts. +func NewSetOcrConfigInstruction( + // Parameters: + pluginType uint8, + configInfo Ocr3ConfigInfo, + signers [][20]uint8, + transmitters []ag_solanago.PublicKey, + // Accounts: + config ag_solanago.PublicKey, + authority ag_solanago.PublicKey) *SetOcrConfig { + return NewSetOcrConfigInstructionBuilder(). + SetPluginType(pluginType). + SetConfigInfo(configInfo). + SetSigners(signers). + SetTransmitters(transmitters). + SetConfigAccount(config). + SetAuthorityAccount(authority) +} diff --git a/core/capabilities/ccip/ccipsolana/ccip_router/SetOcrConfig_test.go b/core/capabilities/ccip/ccipsolana/ccip_router/SetOcrConfig_test.go new file mode 100644 index 00000000000..88528fc48ea --- /dev/null +++ b/core/capabilities/ccip/ccipsolana/ccip_router/SetOcrConfig_test.go @@ -0,0 +1,32 @@ +// Code generated by https://github.com/gagliardetto/anchor-go. DO NOT EDIT. + +package ccip_router + +import ( + "bytes" + ag_gofuzz "github.com/gagliardetto/gofuzz" + ag_require "github.com/stretchr/testify/require" + "strconv" + "testing" +) + +func TestEncodeDecode_SetOcrConfig(t *testing.T) { + fu := ag_gofuzz.New().NilChance(0) + for i := 0; i < 1; i++ { + t.Run("SetOcrConfig"+strconv.Itoa(i), func(t *testing.T) { + { + params := new(SetOcrConfig) + fu.Fuzz(params) + params.AccountMetaSlice = nil + buf := new(bytes.Buffer) + err := encodeT(*params, buf) + ag_require.NoError(t, err) + got := new(SetOcrConfig) + err = decodeT(got, buf.Bytes()) + got.AccountMetaSlice = nil + ag_require.NoError(t, err) + ag_require.Equal(t, params, got) + } + }) + } +} diff --git a/core/capabilities/ccip/ccipsolana/ccip_router/SetPool.go b/core/capabilities/ccip/ccipsolana/ccip_router/SetPool.go new file mode 100644 index 00000000000..69cdc9ba5e1 --- /dev/null +++ b/core/capabilities/ccip/ccipsolana/ccip_router/SetPool.go @@ -0,0 +1,169 @@ +// Code generated by https://github.com/gagliardetto/anchor-go. DO NOT EDIT. + +package ccip_router + +import ( + "errors" + ag_binary "github.com/gagliardetto/binary" + ag_solanago "github.com/gagliardetto/solana-go" + ag_format "github.com/gagliardetto/solana-go/text/format" + ag_treeout "github.com/gagliardetto/treeout" +) + +// The administrator of the token can setup the token pool +type SetPool struct { + Mint *ag_solanago.PublicKey + PoolLookupTable *ag_solanago.PublicKey + + // [0] = [WRITE] tokenAdminRegistry + // + // [1] = [WRITE, SIGNER] authority + ag_solanago.AccountMetaSlice `bin:"-" borsh_skip:"true"` +} + +// NewSetPoolInstructionBuilder creates a new `SetPool` instruction builder. +func NewSetPoolInstructionBuilder() *SetPool { + nd := &SetPool{ + AccountMetaSlice: make(ag_solanago.AccountMetaSlice, 2), + } + return nd +} + +// SetMint sets the "mint" parameter. +func (inst *SetPool) SetMint(mint ag_solanago.PublicKey) *SetPool { + inst.Mint = &mint + return inst +} + +// SetPoolLookupTable sets the "poolLookupTable" parameter. +func (inst *SetPool) SetPoolLookupTable(poolLookupTable ag_solanago.PublicKey) *SetPool { + inst.PoolLookupTable = &poolLookupTable + return inst +} + +// SetTokenAdminRegistryAccount sets the "tokenAdminRegistry" account. +func (inst *SetPool) SetTokenAdminRegistryAccount(tokenAdminRegistry ag_solanago.PublicKey) *SetPool { + inst.AccountMetaSlice[0] = ag_solanago.Meta(tokenAdminRegistry).WRITE() + return inst +} + +// GetTokenAdminRegistryAccount gets the "tokenAdminRegistry" account. +func (inst *SetPool) GetTokenAdminRegistryAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[0] +} + +// SetAuthorityAccount sets the "authority" account. +func (inst *SetPool) SetAuthorityAccount(authority ag_solanago.PublicKey) *SetPool { + inst.AccountMetaSlice[1] = ag_solanago.Meta(authority).WRITE().SIGNER() + return inst +} + +// GetAuthorityAccount gets the "authority" account. +func (inst *SetPool) GetAuthorityAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[1] +} + +func (inst SetPool) Build() *Instruction { + return &Instruction{BaseVariant: ag_binary.BaseVariant{ + Impl: inst, + TypeID: Instruction_SetPool, + }} +} + +// ValidateAndBuild validates the instruction parameters and accounts; +// if there is a validation error, it returns the error. +// Otherwise, it builds and returns the instruction. +func (inst SetPool) ValidateAndBuild() (*Instruction, error) { + if err := inst.Validate(); err != nil { + return nil, err + } + return inst.Build(), nil +} + +func (inst *SetPool) Validate() error { + // Check whether all (required) parameters are set: + { + if inst.Mint == nil { + return errors.New("Mint parameter is not set") + } + if inst.PoolLookupTable == nil { + return errors.New("PoolLookupTable parameter is not set") + } + } + + // Check whether all (required) accounts are set: + { + if inst.AccountMetaSlice[0] == nil { + return errors.New("accounts.TokenAdminRegistry is not set") + } + if inst.AccountMetaSlice[1] == nil { + return errors.New("accounts.Authority is not set") + } + } + return nil +} + +func (inst *SetPool) EncodeToTree(parent ag_treeout.Branches) { + parent.Child(ag_format.Program(ProgramName, ProgramID)). + // + ParentFunc(func(programBranch ag_treeout.Branches) { + programBranch.Child(ag_format.Instruction("SetPool")). + // + ParentFunc(func(instructionBranch ag_treeout.Branches) { + + // Parameters of the instruction: + instructionBranch.Child("Params[len=2]").ParentFunc(func(paramsBranch ag_treeout.Branches) { + paramsBranch.Child(ag_format.Param(" Mint", *inst.Mint)) + paramsBranch.Child(ag_format.Param("PoolLookupTable", *inst.PoolLookupTable)) + }) + + // Accounts of the instruction: + instructionBranch.Child("Accounts[len=2]").ParentFunc(func(accountsBranch ag_treeout.Branches) { + accountsBranch.Child(ag_format.Meta("tokenAdminRegistry", inst.AccountMetaSlice[0])) + accountsBranch.Child(ag_format.Meta(" authority", inst.AccountMetaSlice[1])) + }) + }) + }) +} + +func (obj SetPool) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { + // Serialize `Mint` param: + err = encoder.Encode(obj.Mint) + if err != nil { + return err + } + // Serialize `PoolLookupTable` param: + err = encoder.Encode(obj.PoolLookupTable) + if err != nil { + return err + } + return nil +} +func (obj *SetPool) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { + // Deserialize `Mint`: + err = decoder.Decode(&obj.Mint) + if err != nil { + return err + } + // Deserialize `PoolLookupTable`: + err = decoder.Decode(&obj.PoolLookupTable) + if err != nil { + return err + } + return nil +} + +// NewSetPoolInstruction declares a new SetPool instruction with the provided parameters and accounts. +func NewSetPoolInstruction( + // Parameters: + mint ag_solanago.PublicKey, + poolLookupTable ag_solanago.PublicKey, + // Accounts: + tokenAdminRegistry ag_solanago.PublicKey, + authority ag_solanago.PublicKey) *SetPool { + return NewSetPoolInstructionBuilder(). + SetMint(mint). + SetPoolLookupTable(poolLookupTable). + SetTokenAdminRegistryAccount(tokenAdminRegistry). + SetAuthorityAccount(authority) +} diff --git a/core/capabilities/ccip/ccipsolana/ccip_router/SetPool_test.go b/core/capabilities/ccip/ccipsolana/ccip_router/SetPool_test.go new file mode 100644 index 00000000000..249513a25ba --- /dev/null +++ b/core/capabilities/ccip/ccipsolana/ccip_router/SetPool_test.go @@ -0,0 +1,32 @@ +// Code generated by https://github.com/gagliardetto/anchor-go. DO NOT EDIT. + +package ccip_router + +import ( + "bytes" + ag_gofuzz "github.com/gagliardetto/gofuzz" + ag_require "github.com/stretchr/testify/require" + "strconv" + "testing" +) + +func TestEncodeDecode_SetPool(t *testing.T) { + fu := ag_gofuzz.New().NilChance(0) + for i := 0; i < 1; i++ { + t.Run("SetPool"+strconv.Itoa(i), func(t *testing.T) { + { + params := new(SetPool) + fu.Fuzz(params) + params.AccountMetaSlice = nil + buf := new(bytes.Buffer) + err := encodeT(*params, buf) + ag_require.NoError(t, err) + got := new(SetPool) + err = decodeT(got, buf.Bytes()) + got.AccountMetaSlice = nil + ag_require.NoError(t, err) + ag_require.Equal(t, params, got) + } + }) + } +} diff --git a/core/capabilities/ccip/ccipsolana/ccip_router/SetTokenBilling.go b/core/capabilities/ccip/ccipsolana/ccip_router/SetTokenBilling.go new file mode 100644 index 00000000000..41f1bcd34a5 --- /dev/null +++ b/core/capabilities/ccip/ccipsolana/ccip_router/SetTokenBilling.go @@ -0,0 +1,230 @@ +// Code generated by https://github.com/gagliardetto/anchor-go. DO NOT EDIT. + +package ccip_router + +import ( + "errors" + ag_binary "github.com/gagliardetto/binary" + ag_solanago "github.com/gagliardetto/solana-go" + ag_format "github.com/gagliardetto/solana-go/text/format" + ag_treeout "github.com/gagliardetto/treeout" +) + +// SetTokenBilling is the `setTokenBilling` instruction. +type SetTokenBilling struct { + ChainSelector *uint64 + Mint *ag_solanago.PublicKey + Cfg *TokenBilling + + // [0] = [] config + // + // [1] = [WRITE] perChainPerTokenConfig + // + // [2] = [WRITE, SIGNER] authority + // + // [3] = [] systemProgram + ag_solanago.AccountMetaSlice `bin:"-" borsh_skip:"true"` +} + +// NewSetTokenBillingInstructionBuilder creates a new `SetTokenBilling` instruction builder. +func NewSetTokenBillingInstructionBuilder() *SetTokenBilling { + nd := &SetTokenBilling{ + AccountMetaSlice: make(ag_solanago.AccountMetaSlice, 4), + } + return nd +} + +// SetChainSelector sets the "chainSelector" parameter. +func (inst *SetTokenBilling) SetChainSelector(chainSelector uint64) *SetTokenBilling { + inst.ChainSelector = &chainSelector + return inst +} + +// SetMint sets the "mint" parameter. +func (inst *SetTokenBilling) SetMint(mint ag_solanago.PublicKey) *SetTokenBilling { + inst.Mint = &mint + return inst +} + +// SetCfg sets the "cfg" parameter. +func (inst *SetTokenBilling) SetCfg(cfg TokenBilling) *SetTokenBilling { + inst.Cfg = &cfg + return inst +} + +// SetConfigAccount sets the "config" account. +func (inst *SetTokenBilling) SetConfigAccount(config ag_solanago.PublicKey) *SetTokenBilling { + inst.AccountMetaSlice[0] = ag_solanago.Meta(config) + return inst +} + +// GetConfigAccount gets the "config" account. +func (inst *SetTokenBilling) GetConfigAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[0] +} + +// SetPerChainPerTokenConfigAccount sets the "perChainPerTokenConfig" account. +func (inst *SetTokenBilling) SetPerChainPerTokenConfigAccount(perChainPerTokenConfig ag_solanago.PublicKey) *SetTokenBilling { + inst.AccountMetaSlice[1] = ag_solanago.Meta(perChainPerTokenConfig).WRITE() + return inst +} + +// GetPerChainPerTokenConfigAccount gets the "perChainPerTokenConfig" account. +func (inst *SetTokenBilling) GetPerChainPerTokenConfigAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[1] +} + +// SetAuthorityAccount sets the "authority" account. +func (inst *SetTokenBilling) SetAuthorityAccount(authority ag_solanago.PublicKey) *SetTokenBilling { + inst.AccountMetaSlice[2] = ag_solanago.Meta(authority).WRITE().SIGNER() + return inst +} + +// GetAuthorityAccount gets the "authority" account. +func (inst *SetTokenBilling) GetAuthorityAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[2] +} + +// SetSystemProgramAccount sets the "systemProgram" account. +func (inst *SetTokenBilling) SetSystemProgramAccount(systemProgram ag_solanago.PublicKey) *SetTokenBilling { + inst.AccountMetaSlice[3] = ag_solanago.Meta(systemProgram) + return inst +} + +// GetSystemProgramAccount gets the "systemProgram" account. +func (inst *SetTokenBilling) GetSystemProgramAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[3] +} + +func (inst SetTokenBilling) Build() *Instruction { + return &Instruction{BaseVariant: ag_binary.BaseVariant{ + Impl: inst, + TypeID: Instruction_SetTokenBilling, + }} +} + +// ValidateAndBuild validates the instruction parameters and accounts; +// if there is a validation error, it returns the error. +// Otherwise, it builds and returns the instruction. +func (inst SetTokenBilling) ValidateAndBuild() (*Instruction, error) { + if err := inst.Validate(); err != nil { + return nil, err + } + return inst.Build(), nil +} + +func (inst *SetTokenBilling) Validate() error { + // Check whether all (required) parameters are set: + { + if inst.ChainSelector == nil { + return errors.New("ChainSelector parameter is not set") + } + if inst.Mint == nil { + return errors.New("Mint parameter is not set") + } + if inst.Cfg == nil { + return errors.New("Cfg parameter is not set") + } + } + + // Check whether all (required) accounts are set: + { + if inst.AccountMetaSlice[0] == nil { + return errors.New("accounts.Config is not set") + } + if inst.AccountMetaSlice[1] == nil { + return errors.New("accounts.PerChainPerTokenConfig is not set") + } + if inst.AccountMetaSlice[2] == nil { + return errors.New("accounts.Authority is not set") + } + if inst.AccountMetaSlice[3] == nil { + return errors.New("accounts.SystemProgram is not set") + } + } + return nil +} + +func (inst *SetTokenBilling) EncodeToTree(parent ag_treeout.Branches) { + parent.Child(ag_format.Program(ProgramName, ProgramID)). + // + ParentFunc(func(programBranch ag_treeout.Branches) { + programBranch.Child(ag_format.Instruction("SetTokenBilling")). + // + ParentFunc(func(instructionBranch ag_treeout.Branches) { + + // Parameters of the instruction: + instructionBranch.Child("Params[len=3]").ParentFunc(func(paramsBranch ag_treeout.Branches) { + paramsBranch.Child(ag_format.Param("ChainSelector", *inst.ChainSelector)) + paramsBranch.Child(ag_format.Param(" Mint", *inst.Mint)) + paramsBranch.Child(ag_format.Param(" Cfg", *inst.Cfg)) + }) + + // Accounts of the instruction: + instructionBranch.Child("Accounts[len=4]").ParentFunc(func(accountsBranch ag_treeout.Branches) { + accountsBranch.Child(ag_format.Meta(" config", inst.AccountMetaSlice[0])) + accountsBranch.Child(ag_format.Meta("perChainPerTokenConfig", inst.AccountMetaSlice[1])) + accountsBranch.Child(ag_format.Meta(" authority", inst.AccountMetaSlice[2])) + accountsBranch.Child(ag_format.Meta(" systemProgram", inst.AccountMetaSlice[3])) + }) + }) + }) +} + +func (obj SetTokenBilling) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { + // Serialize `ChainSelector` param: + err = encoder.Encode(obj.ChainSelector) + if err != nil { + return err + } + // Serialize `Mint` param: + err = encoder.Encode(obj.Mint) + if err != nil { + return err + } + // Serialize `Cfg` param: + err = encoder.Encode(obj.Cfg) + if err != nil { + return err + } + return nil +} +func (obj *SetTokenBilling) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { + // Deserialize `ChainSelector`: + err = decoder.Decode(&obj.ChainSelector) + if err != nil { + return err + } + // Deserialize `Mint`: + err = decoder.Decode(&obj.Mint) + if err != nil { + return err + } + // Deserialize `Cfg`: + err = decoder.Decode(&obj.Cfg) + if err != nil { + return err + } + return nil +} + +// NewSetTokenBillingInstruction declares a new SetTokenBilling instruction with the provided parameters and accounts. +func NewSetTokenBillingInstruction( + // Parameters: + chainSelector uint64, + mint ag_solanago.PublicKey, + cfg TokenBilling, + // Accounts: + config ag_solanago.PublicKey, + perChainPerTokenConfig ag_solanago.PublicKey, + authority ag_solanago.PublicKey, + systemProgram ag_solanago.PublicKey) *SetTokenBilling { + return NewSetTokenBillingInstructionBuilder(). + SetChainSelector(chainSelector). + SetMint(mint). + SetCfg(cfg). + SetConfigAccount(config). + SetPerChainPerTokenConfigAccount(perChainPerTokenConfig). + SetAuthorityAccount(authority). + SetSystemProgramAccount(systemProgram) +} diff --git a/core/capabilities/ccip/ccipsolana/ccip_router/SetTokenBilling_test.go b/core/capabilities/ccip/ccipsolana/ccip_router/SetTokenBilling_test.go new file mode 100644 index 00000000000..aff9d60f3d3 --- /dev/null +++ b/core/capabilities/ccip/ccipsolana/ccip_router/SetTokenBilling_test.go @@ -0,0 +1,32 @@ +// Code generated by https://github.com/gagliardetto/anchor-go. DO NOT EDIT. + +package ccip_router + +import ( + "bytes" + ag_gofuzz "github.com/gagliardetto/gofuzz" + ag_require "github.com/stretchr/testify/require" + "strconv" + "testing" +) + +func TestEncodeDecode_SetTokenBilling(t *testing.T) { + fu := ag_gofuzz.New().NilChance(0) + for i := 0; i < 1; i++ { + t.Run("SetTokenBilling"+strconv.Itoa(i), func(t *testing.T) { + { + params := new(SetTokenBilling) + fu.Fuzz(params) + params.AccountMetaSlice = nil + buf := new(bytes.Buffer) + err := encodeT(*params, buf) + ag_require.NoError(t, err) + got := new(SetTokenBilling) + err = decodeT(got, buf.Bytes()) + got.AccountMetaSlice = nil + ag_require.NoError(t, err) + ag_require.Equal(t, params, got) + } + }) + } +} diff --git a/core/capabilities/ccip/ccipsolana/ccip_router/TransferAdminRoleTokenAdminRegistry.go b/core/capabilities/ccip/ccipsolana/ccip_router/TransferAdminRoleTokenAdminRegistry.go new file mode 100644 index 00000000000..269a086456d --- /dev/null +++ b/core/capabilities/ccip/ccipsolana/ccip_router/TransferAdminRoleTokenAdminRegistry.go @@ -0,0 +1,169 @@ +// Code generated by https://github.com/gagliardetto/anchor-go. DO NOT EDIT. + +package ccip_router + +import ( + "errors" + ag_binary "github.com/gagliardetto/binary" + ag_solanago "github.com/gagliardetto/solana-go" + ag_format "github.com/gagliardetto/solana-go/text/format" + ag_treeout "github.com/gagliardetto/treeout" +) + +// The Admin can transfer the Admin Role of the Token Admin Registry +type TransferAdminRoleTokenAdminRegistry struct { + Mint *ag_solanago.PublicKey + NewAdmin *ag_solanago.PublicKey + + // [0] = [WRITE] tokenAdminRegistry + // + // [1] = [WRITE, SIGNER] authority + ag_solanago.AccountMetaSlice `bin:"-" borsh_skip:"true"` +} + +// NewTransferAdminRoleTokenAdminRegistryInstructionBuilder creates a new `TransferAdminRoleTokenAdminRegistry` instruction builder. +func NewTransferAdminRoleTokenAdminRegistryInstructionBuilder() *TransferAdminRoleTokenAdminRegistry { + nd := &TransferAdminRoleTokenAdminRegistry{ + AccountMetaSlice: make(ag_solanago.AccountMetaSlice, 2), + } + return nd +} + +// SetMint sets the "mint" parameter. +func (inst *TransferAdminRoleTokenAdminRegistry) SetMint(mint ag_solanago.PublicKey) *TransferAdminRoleTokenAdminRegistry { + inst.Mint = &mint + return inst +} + +// SetNewAdmin sets the "newAdmin" parameter. +func (inst *TransferAdminRoleTokenAdminRegistry) SetNewAdmin(newAdmin ag_solanago.PublicKey) *TransferAdminRoleTokenAdminRegistry { + inst.NewAdmin = &newAdmin + return inst +} + +// SetTokenAdminRegistryAccount sets the "tokenAdminRegistry" account. +func (inst *TransferAdminRoleTokenAdminRegistry) SetTokenAdminRegistryAccount(tokenAdminRegistry ag_solanago.PublicKey) *TransferAdminRoleTokenAdminRegistry { + inst.AccountMetaSlice[0] = ag_solanago.Meta(tokenAdminRegistry).WRITE() + return inst +} + +// GetTokenAdminRegistryAccount gets the "tokenAdminRegistry" account. +func (inst *TransferAdminRoleTokenAdminRegistry) GetTokenAdminRegistryAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[0] +} + +// SetAuthorityAccount sets the "authority" account. +func (inst *TransferAdminRoleTokenAdminRegistry) SetAuthorityAccount(authority ag_solanago.PublicKey) *TransferAdminRoleTokenAdminRegistry { + inst.AccountMetaSlice[1] = ag_solanago.Meta(authority).WRITE().SIGNER() + return inst +} + +// GetAuthorityAccount gets the "authority" account. +func (inst *TransferAdminRoleTokenAdminRegistry) GetAuthorityAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[1] +} + +func (inst TransferAdminRoleTokenAdminRegistry) Build() *Instruction { + return &Instruction{BaseVariant: ag_binary.BaseVariant{ + Impl: inst, + TypeID: Instruction_TransferAdminRoleTokenAdminRegistry, + }} +} + +// ValidateAndBuild validates the instruction parameters and accounts; +// if there is a validation error, it returns the error. +// Otherwise, it builds and returns the instruction. +func (inst TransferAdminRoleTokenAdminRegistry) ValidateAndBuild() (*Instruction, error) { + if err := inst.Validate(); err != nil { + return nil, err + } + return inst.Build(), nil +} + +func (inst *TransferAdminRoleTokenAdminRegistry) Validate() error { + // Check whether all (required) parameters are set: + { + if inst.Mint == nil { + return errors.New("Mint parameter is not set") + } + if inst.NewAdmin == nil { + return errors.New("NewAdmin parameter is not set") + } + } + + // Check whether all (required) accounts are set: + { + if inst.AccountMetaSlice[0] == nil { + return errors.New("accounts.TokenAdminRegistry is not set") + } + if inst.AccountMetaSlice[1] == nil { + return errors.New("accounts.Authority is not set") + } + } + return nil +} + +func (inst *TransferAdminRoleTokenAdminRegistry) EncodeToTree(parent ag_treeout.Branches) { + parent.Child(ag_format.Program(ProgramName, ProgramID)). + // + ParentFunc(func(programBranch ag_treeout.Branches) { + programBranch.Child(ag_format.Instruction("TransferAdminRoleTokenAdminRegistry")). + // + ParentFunc(func(instructionBranch ag_treeout.Branches) { + + // Parameters of the instruction: + instructionBranch.Child("Params[len=2]").ParentFunc(func(paramsBranch ag_treeout.Branches) { + paramsBranch.Child(ag_format.Param(" Mint", *inst.Mint)) + paramsBranch.Child(ag_format.Param("NewAdmin", *inst.NewAdmin)) + }) + + // Accounts of the instruction: + instructionBranch.Child("Accounts[len=2]").ParentFunc(func(accountsBranch ag_treeout.Branches) { + accountsBranch.Child(ag_format.Meta("tokenAdminRegistry", inst.AccountMetaSlice[0])) + accountsBranch.Child(ag_format.Meta(" authority", inst.AccountMetaSlice[1])) + }) + }) + }) +} + +func (obj TransferAdminRoleTokenAdminRegistry) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { + // Serialize `Mint` param: + err = encoder.Encode(obj.Mint) + if err != nil { + return err + } + // Serialize `NewAdmin` param: + err = encoder.Encode(obj.NewAdmin) + if err != nil { + return err + } + return nil +} +func (obj *TransferAdminRoleTokenAdminRegistry) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { + // Deserialize `Mint`: + err = decoder.Decode(&obj.Mint) + if err != nil { + return err + } + // Deserialize `NewAdmin`: + err = decoder.Decode(&obj.NewAdmin) + if err != nil { + return err + } + return nil +} + +// NewTransferAdminRoleTokenAdminRegistryInstruction declares a new TransferAdminRoleTokenAdminRegistry instruction with the provided parameters and accounts. +func NewTransferAdminRoleTokenAdminRegistryInstruction( + // Parameters: + mint ag_solanago.PublicKey, + newAdmin ag_solanago.PublicKey, + // Accounts: + tokenAdminRegistry ag_solanago.PublicKey, + authority ag_solanago.PublicKey) *TransferAdminRoleTokenAdminRegistry { + return NewTransferAdminRoleTokenAdminRegistryInstructionBuilder(). + SetMint(mint). + SetNewAdmin(newAdmin). + SetTokenAdminRegistryAccount(tokenAdminRegistry). + SetAuthorityAccount(authority) +} diff --git a/core/capabilities/ccip/ccipsolana/ccip_router/TransferAdminRoleTokenAdminRegistry_test.go b/core/capabilities/ccip/ccipsolana/ccip_router/TransferAdminRoleTokenAdminRegistry_test.go new file mode 100644 index 00000000000..e52c1a9983e --- /dev/null +++ b/core/capabilities/ccip/ccipsolana/ccip_router/TransferAdminRoleTokenAdminRegistry_test.go @@ -0,0 +1,32 @@ +// Code generated by https://github.com/gagliardetto/anchor-go. DO NOT EDIT. + +package ccip_router + +import ( + "bytes" + ag_gofuzz "github.com/gagliardetto/gofuzz" + ag_require "github.com/stretchr/testify/require" + "strconv" + "testing" +) + +func TestEncodeDecode_TransferAdminRoleTokenAdminRegistry(t *testing.T) { + fu := ag_gofuzz.New().NilChance(0) + for i := 0; i < 1; i++ { + t.Run("TransferAdminRoleTokenAdminRegistry"+strconv.Itoa(i), func(t *testing.T) { + { + params := new(TransferAdminRoleTokenAdminRegistry) + fu.Fuzz(params) + params.AccountMetaSlice = nil + buf := new(bytes.Buffer) + err := encodeT(*params, buf) + ag_require.NoError(t, err) + got := new(TransferAdminRoleTokenAdminRegistry) + err = decodeT(got, buf.Bytes()) + got.AccountMetaSlice = nil + ag_require.NoError(t, err) + ag_require.Equal(t, params, got) + } + }) + } +} diff --git a/core/capabilities/ccip/ccipsolana/ccip_router/TransferOwnership.go b/core/capabilities/ccip/ccipsolana/ccip_router/TransferOwnership.go new file mode 100644 index 00000000000..37a129be90c --- /dev/null +++ b/core/capabilities/ccip/ccipsolana/ccip_router/TransferOwnership.go @@ -0,0 +1,146 @@ +// Code generated by https://github.com/gagliardetto/anchor-go. DO NOT EDIT. + +package ccip_router + +import ( + "errors" + ag_binary "github.com/gagliardetto/binary" + ag_solanago "github.com/gagliardetto/solana-go" + ag_format "github.com/gagliardetto/solana-go/text/format" + ag_treeout "github.com/gagliardetto/treeout" +) + +// TransferOwnership is the `transferOwnership` instruction. +type TransferOwnership struct { + ProposedOwner *ag_solanago.PublicKey + + // [0] = [WRITE] config + // + // [1] = [SIGNER] authority + ag_solanago.AccountMetaSlice `bin:"-" borsh_skip:"true"` +} + +// NewTransferOwnershipInstructionBuilder creates a new `TransferOwnership` instruction builder. +func NewTransferOwnershipInstructionBuilder() *TransferOwnership { + nd := &TransferOwnership{ + AccountMetaSlice: make(ag_solanago.AccountMetaSlice, 2), + } + return nd +} + +// SetProposedOwner sets the "proposedOwner" parameter. +func (inst *TransferOwnership) SetProposedOwner(proposedOwner ag_solanago.PublicKey) *TransferOwnership { + inst.ProposedOwner = &proposedOwner + return inst +} + +// SetConfigAccount sets the "config" account. +func (inst *TransferOwnership) SetConfigAccount(config ag_solanago.PublicKey) *TransferOwnership { + inst.AccountMetaSlice[0] = ag_solanago.Meta(config).WRITE() + return inst +} + +// GetConfigAccount gets the "config" account. +func (inst *TransferOwnership) GetConfigAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[0] +} + +// SetAuthorityAccount sets the "authority" account. +func (inst *TransferOwnership) SetAuthorityAccount(authority ag_solanago.PublicKey) *TransferOwnership { + inst.AccountMetaSlice[1] = ag_solanago.Meta(authority).SIGNER() + return inst +} + +// GetAuthorityAccount gets the "authority" account. +func (inst *TransferOwnership) GetAuthorityAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[1] +} + +func (inst TransferOwnership) Build() *Instruction { + return &Instruction{BaseVariant: ag_binary.BaseVariant{ + Impl: inst, + TypeID: Instruction_TransferOwnership, + }} +} + +// ValidateAndBuild validates the instruction parameters and accounts; +// if there is a validation error, it returns the error. +// Otherwise, it builds and returns the instruction. +func (inst TransferOwnership) ValidateAndBuild() (*Instruction, error) { + if err := inst.Validate(); err != nil { + return nil, err + } + return inst.Build(), nil +} + +func (inst *TransferOwnership) Validate() error { + // Check whether all (required) parameters are set: + { + if inst.ProposedOwner == nil { + return errors.New("ProposedOwner parameter is not set") + } + } + + // Check whether all (required) accounts are set: + { + if inst.AccountMetaSlice[0] == nil { + return errors.New("accounts.Config is not set") + } + if inst.AccountMetaSlice[1] == nil { + return errors.New("accounts.Authority is not set") + } + } + return nil +} + +func (inst *TransferOwnership) EncodeToTree(parent ag_treeout.Branches) { + parent.Child(ag_format.Program(ProgramName, ProgramID)). + // + ParentFunc(func(programBranch ag_treeout.Branches) { + programBranch.Child(ag_format.Instruction("TransferOwnership")). + // + ParentFunc(func(instructionBranch ag_treeout.Branches) { + + // Parameters of the instruction: + instructionBranch.Child("Params[len=1]").ParentFunc(func(paramsBranch ag_treeout.Branches) { + paramsBranch.Child(ag_format.Param("ProposedOwner", *inst.ProposedOwner)) + }) + + // Accounts of the instruction: + instructionBranch.Child("Accounts[len=2]").ParentFunc(func(accountsBranch ag_treeout.Branches) { + accountsBranch.Child(ag_format.Meta(" config", inst.AccountMetaSlice[0])) + accountsBranch.Child(ag_format.Meta("authority", inst.AccountMetaSlice[1])) + }) + }) + }) +} + +func (obj TransferOwnership) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { + // Serialize `ProposedOwner` param: + err = encoder.Encode(obj.ProposedOwner) + if err != nil { + return err + } + return nil +} +func (obj *TransferOwnership) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { + // Deserialize `ProposedOwner`: + err = decoder.Decode(&obj.ProposedOwner) + if err != nil { + return err + } + return nil +} + +// NewTransferOwnershipInstruction declares a new TransferOwnership instruction with the provided parameters and accounts. +func NewTransferOwnershipInstruction( + // Parameters: + proposedOwner ag_solanago.PublicKey, + // Accounts: + config ag_solanago.PublicKey, + authority ag_solanago.PublicKey) *TransferOwnership { + return NewTransferOwnershipInstructionBuilder(). + SetProposedOwner(proposedOwner). + SetConfigAccount(config). + SetAuthorityAccount(authority) +} diff --git a/core/capabilities/ccip/ccipsolana/ccip_router/TransferOwnership_test.go b/core/capabilities/ccip/ccipsolana/ccip_router/TransferOwnership_test.go new file mode 100644 index 00000000000..38ea4ea34f1 --- /dev/null +++ b/core/capabilities/ccip/ccipsolana/ccip_router/TransferOwnership_test.go @@ -0,0 +1,32 @@ +// Code generated by https://github.com/gagliardetto/anchor-go. DO NOT EDIT. + +package ccip_router + +import ( + "bytes" + ag_gofuzz "github.com/gagliardetto/gofuzz" + ag_require "github.com/stretchr/testify/require" + "strconv" + "testing" +) + +func TestEncodeDecode_TransferOwnership(t *testing.T) { + fu := ag_gofuzz.New().NilChance(0) + for i := 0; i < 1; i++ { + t.Run("TransferOwnership"+strconv.Itoa(i), func(t *testing.T) { + { + params := new(TransferOwnership) + fu.Fuzz(params) + params.AccountMetaSlice = nil + buf := new(bytes.Buffer) + err := encodeT(*params, buf) + ag_require.NoError(t, err) + got := new(TransferOwnership) + err = decodeT(got, buf.Bytes()) + got.AccountMetaSlice = nil + ag_require.NoError(t, err) + ag_require.Equal(t, params, got) + } + }) + } +} diff --git a/core/capabilities/ccip/ccipsolana/ccip_router/UpdateDefaultAllowOutOfOrderExecution.go b/core/capabilities/ccip/ccipsolana/ccip_router/UpdateDefaultAllowOutOfOrderExecution.go new file mode 100644 index 00000000000..87e10696877 --- /dev/null +++ b/core/capabilities/ccip/ccipsolana/ccip_router/UpdateDefaultAllowOutOfOrderExecution.go @@ -0,0 +1,165 @@ +// Code generated by https://github.com/gagliardetto/anchor-go. DO NOT EDIT. + +package ccip_router + +import ( + "errors" + ag_binary "github.com/gagliardetto/binary" + ag_solanago "github.com/gagliardetto/solana-go" + ag_format "github.com/gagliardetto/solana-go/text/format" + ag_treeout "github.com/gagliardetto/treeout" +) + +// The Admin can update the configuration of the Router, in this case the Default Allow Out Of Order Execution (True/False) +type UpdateDefaultAllowOutOfOrderExecution struct { + NewAllowOutOfOrderExecution *bool + + // [0] = [WRITE] config + // + // [1] = [SIGNER] authority + // + // [2] = [] systemProgram + ag_solanago.AccountMetaSlice `bin:"-" borsh_skip:"true"` +} + +// NewUpdateDefaultAllowOutOfOrderExecutionInstructionBuilder creates a new `UpdateDefaultAllowOutOfOrderExecution` instruction builder. +func NewUpdateDefaultAllowOutOfOrderExecutionInstructionBuilder() *UpdateDefaultAllowOutOfOrderExecution { + nd := &UpdateDefaultAllowOutOfOrderExecution{ + AccountMetaSlice: make(ag_solanago.AccountMetaSlice, 3), + } + return nd +} + +// SetNewAllowOutOfOrderExecution sets the "newAllowOutOfOrderExecution" parameter. +func (inst *UpdateDefaultAllowOutOfOrderExecution) SetNewAllowOutOfOrderExecution(newAllowOutOfOrderExecution bool) *UpdateDefaultAllowOutOfOrderExecution { + inst.NewAllowOutOfOrderExecution = &newAllowOutOfOrderExecution + return inst +} + +// SetConfigAccount sets the "config" account. +func (inst *UpdateDefaultAllowOutOfOrderExecution) SetConfigAccount(config ag_solanago.PublicKey) *UpdateDefaultAllowOutOfOrderExecution { + inst.AccountMetaSlice[0] = ag_solanago.Meta(config).WRITE() + return inst +} + +// GetConfigAccount gets the "config" account. +func (inst *UpdateDefaultAllowOutOfOrderExecution) GetConfigAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[0] +} + +// SetAuthorityAccount sets the "authority" account. +func (inst *UpdateDefaultAllowOutOfOrderExecution) SetAuthorityAccount(authority ag_solanago.PublicKey) *UpdateDefaultAllowOutOfOrderExecution { + inst.AccountMetaSlice[1] = ag_solanago.Meta(authority).SIGNER() + return inst +} + +// GetAuthorityAccount gets the "authority" account. +func (inst *UpdateDefaultAllowOutOfOrderExecution) GetAuthorityAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[1] +} + +// SetSystemProgramAccount sets the "systemProgram" account. +func (inst *UpdateDefaultAllowOutOfOrderExecution) SetSystemProgramAccount(systemProgram ag_solanago.PublicKey) *UpdateDefaultAllowOutOfOrderExecution { + inst.AccountMetaSlice[2] = ag_solanago.Meta(systemProgram) + return inst +} + +// GetSystemProgramAccount gets the "systemProgram" account. +func (inst *UpdateDefaultAllowOutOfOrderExecution) GetSystemProgramAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[2] +} + +func (inst UpdateDefaultAllowOutOfOrderExecution) Build() *Instruction { + return &Instruction{BaseVariant: ag_binary.BaseVariant{ + Impl: inst, + TypeID: Instruction_UpdateDefaultAllowOutOfOrderExecution, + }} +} + +// ValidateAndBuild validates the instruction parameters and accounts; +// if there is a validation error, it returns the error. +// Otherwise, it builds and returns the instruction. +func (inst UpdateDefaultAllowOutOfOrderExecution) ValidateAndBuild() (*Instruction, error) { + if err := inst.Validate(); err != nil { + return nil, err + } + return inst.Build(), nil +} + +func (inst *UpdateDefaultAllowOutOfOrderExecution) Validate() error { + // Check whether all (required) parameters are set: + { + if inst.NewAllowOutOfOrderExecution == nil { + return errors.New("NewAllowOutOfOrderExecution parameter is not set") + } + } + + // Check whether all (required) accounts are set: + { + if inst.AccountMetaSlice[0] == nil { + return errors.New("accounts.Config is not set") + } + if inst.AccountMetaSlice[1] == nil { + return errors.New("accounts.Authority is not set") + } + if inst.AccountMetaSlice[2] == nil { + return errors.New("accounts.SystemProgram is not set") + } + } + return nil +} + +func (inst *UpdateDefaultAllowOutOfOrderExecution) EncodeToTree(parent ag_treeout.Branches) { + parent.Child(ag_format.Program(ProgramName, ProgramID)). + // + ParentFunc(func(programBranch ag_treeout.Branches) { + programBranch.Child(ag_format.Instruction("UpdateDefaultAllowOutOfOrderExecution")). + // + ParentFunc(func(instructionBranch ag_treeout.Branches) { + + // Parameters of the instruction: + instructionBranch.Child("Params[len=1]").ParentFunc(func(paramsBranch ag_treeout.Branches) { + paramsBranch.Child(ag_format.Param("NewAllowOutOfOrderExecution", *inst.NewAllowOutOfOrderExecution)) + }) + + // Accounts of the instruction: + instructionBranch.Child("Accounts[len=3]").ParentFunc(func(accountsBranch ag_treeout.Branches) { + accountsBranch.Child(ag_format.Meta(" config", inst.AccountMetaSlice[0])) + accountsBranch.Child(ag_format.Meta(" authority", inst.AccountMetaSlice[1])) + accountsBranch.Child(ag_format.Meta("systemProgram", inst.AccountMetaSlice[2])) + }) + }) + }) +} + +func (obj UpdateDefaultAllowOutOfOrderExecution) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { + // Serialize `NewAllowOutOfOrderExecution` param: + err = encoder.Encode(obj.NewAllowOutOfOrderExecution) + if err != nil { + return err + } + return nil +} +func (obj *UpdateDefaultAllowOutOfOrderExecution) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { + // Deserialize `NewAllowOutOfOrderExecution`: + err = decoder.Decode(&obj.NewAllowOutOfOrderExecution) + if err != nil { + return err + } + return nil +} + +// NewUpdateDefaultAllowOutOfOrderExecutionInstruction declares a new UpdateDefaultAllowOutOfOrderExecution instruction with the provided parameters and accounts. +func NewUpdateDefaultAllowOutOfOrderExecutionInstruction( + // Parameters: + newAllowOutOfOrderExecution bool, + // Accounts: + config ag_solanago.PublicKey, + authority ag_solanago.PublicKey, + systemProgram ag_solanago.PublicKey) *UpdateDefaultAllowOutOfOrderExecution { + return NewUpdateDefaultAllowOutOfOrderExecutionInstructionBuilder(). + SetNewAllowOutOfOrderExecution(newAllowOutOfOrderExecution). + SetConfigAccount(config). + SetAuthorityAccount(authority). + SetSystemProgramAccount(systemProgram) +} diff --git a/core/capabilities/ccip/ccipsolana/ccip_router/UpdateDefaultAllowOutOfOrderExecution_test.go b/core/capabilities/ccip/ccipsolana/ccip_router/UpdateDefaultAllowOutOfOrderExecution_test.go new file mode 100644 index 00000000000..70a0674748c --- /dev/null +++ b/core/capabilities/ccip/ccipsolana/ccip_router/UpdateDefaultAllowOutOfOrderExecution_test.go @@ -0,0 +1,32 @@ +// Code generated by https://github.com/gagliardetto/anchor-go. DO NOT EDIT. + +package ccip_router + +import ( + "bytes" + ag_gofuzz "github.com/gagliardetto/gofuzz" + ag_require "github.com/stretchr/testify/require" + "strconv" + "testing" +) + +func TestEncodeDecode_UpdateDefaultAllowOutOfOrderExecution(t *testing.T) { + fu := ag_gofuzz.New().NilChance(0) + for i := 0; i < 1; i++ { + t.Run("UpdateDefaultAllowOutOfOrderExecution"+strconv.Itoa(i), func(t *testing.T) { + { + params := new(UpdateDefaultAllowOutOfOrderExecution) + fu.Fuzz(params) + params.AccountMetaSlice = nil + buf := new(bytes.Buffer) + err := encodeT(*params, buf) + ag_require.NoError(t, err) + got := new(UpdateDefaultAllowOutOfOrderExecution) + err = decodeT(got, buf.Bytes()) + got.AccountMetaSlice = nil + ag_require.NoError(t, err) + ag_require.Equal(t, params, got) + } + }) + } +} diff --git a/core/capabilities/ccip/ccipsolana/ccip_router/UpdateDefaultGasLimit.go b/core/capabilities/ccip/ccipsolana/ccip_router/UpdateDefaultGasLimit.go new file mode 100644 index 00000000000..c1791685884 --- /dev/null +++ b/core/capabilities/ccip/ccipsolana/ccip_router/UpdateDefaultGasLimit.go @@ -0,0 +1,165 @@ +// Code generated by https://github.com/gagliardetto/anchor-go. DO NOT EDIT. + +package ccip_router + +import ( + "errors" + ag_binary "github.com/gagliardetto/binary" + ag_solanago "github.com/gagliardetto/solana-go" + ag_format "github.com/gagliardetto/solana-go/text/format" + ag_treeout "github.com/gagliardetto/treeout" +) + +// The Admin can update the configuration of the Router, in this case the Default Gas Limit +type UpdateDefaultGasLimit struct { + NewGasLimit *ag_binary.Uint128 + + // [0] = [WRITE] config + // + // [1] = [SIGNER] authority + // + // [2] = [] systemProgram + ag_solanago.AccountMetaSlice `bin:"-" borsh_skip:"true"` +} + +// NewUpdateDefaultGasLimitInstructionBuilder creates a new `UpdateDefaultGasLimit` instruction builder. +func NewUpdateDefaultGasLimitInstructionBuilder() *UpdateDefaultGasLimit { + nd := &UpdateDefaultGasLimit{ + AccountMetaSlice: make(ag_solanago.AccountMetaSlice, 3), + } + return nd +} + +// SetNewGasLimit sets the "newGasLimit" parameter. +func (inst *UpdateDefaultGasLimit) SetNewGasLimit(newGasLimit ag_binary.Uint128) *UpdateDefaultGasLimit { + inst.NewGasLimit = &newGasLimit + return inst +} + +// SetConfigAccount sets the "config" account. +func (inst *UpdateDefaultGasLimit) SetConfigAccount(config ag_solanago.PublicKey) *UpdateDefaultGasLimit { + inst.AccountMetaSlice[0] = ag_solanago.Meta(config).WRITE() + return inst +} + +// GetConfigAccount gets the "config" account. +func (inst *UpdateDefaultGasLimit) GetConfigAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[0] +} + +// SetAuthorityAccount sets the "authority" account. +func (inst *UpdateDefaultGasLimit) SetAuthorityAccount(authority ag_solanago.PublicKey) *UpdateDefaultGasLimit { + inst.AccountMetaSlice[1] = ag_solanago.Meta(authority).SIGNER() + return inst +} + +// GetAuthorityAccount gets the "authority" account. +func (inst *UpdateDefaultGasLimit) GetAuthorityAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[1] +} + +// SetSystemProgramAccount sets the "systemProgram" account. +func (inst *UpdateDefaultGasLimit) SetSystemProgramAccount(systemProgram ag_solanago.PublicKey) *UpdateDefaultGasLimit { + inst.AccountMetaSlice[2] = ag_solanago.Meta(systemProgram) + return inst +} + +// GetSystemProgramAccount gets the "systemProgram" account. +func (inst *UpdateDefaultGasLimit) GetSystemProgramAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[2] +} + +func (inst UpdateDefaultGasLimit) Build() *Instruction { + return &Instruction{BaseVariant: ag_binary.BaseVariant{ + Impl: inst, + TypeID: Instruction_UpdateDefaultGasLimit, + }} +} + +// ValidateAndBuild validates the instruction parameters and accounts; +// if there is a validation error, it returns the error. +// Otherwise, it builds and returns the instruction. +func (inst UpdateDefaultGasLimit) ValidateAndBuild() (*Instruction, error) { + if err := inst.Validate(); err != nil { + return nil, err + } + return inst.Build(), nil +} + +func (inst *UpdateDefaultGasLimit) Validate() error { + // Check whether all (required) parameters are set: + { + if inst.NewGasLimit == nil { + return errors.New("NewGasLimit parameter is not set") + } + } + + // Check whether all (required) accounts are set: + { + if inst.AccountMetaSlice[0] == nil { + return errors.New("accounts.Config is not set") + } + if inst.AccountMetaSlice[1] == nil { + return errors.New("accounts.Authority is not set") + } + if inst.AccountMetaSlice[2] == nil { + return errors.New("accounts.SystemProgram is not set") + } + } + return nil +} + +func (inst *UpdateDefaultGasLimit) EncodeToTree(parent ag_treeout.Branches) { + parent.Child(ag_format.Program(ProgramName, ProgramID)). + // + ParentFunc(func(programBranch ag_treeout.Branches) { + programBranch.Child(ag_format.Instruction("UpdateDefaultGasLimit")). + // + ParentFunc(func(instructionBranch ag_treeout.Branches) { + + // Parameters of the instruction: + instructionBranch.Child("Params[len=1]").ParentFunc(func(paramsBranch ag_treeout.Branches) { + paramsBranch.Child(ag_format.Param("NewGasLimit", *inst.NewGasLimit)) + }) + + // Accounts of the instruction: + instructionBranch.Child("Accounts[len=3]").ParentFunc(func(accountsBranch ag_treeout.Branches) { + accountsBranch.Child(ag_format.Meta(" config", inst.AccountMetaSlice[0])) + accountsBranch.Child(ag_format.Meta(" authority", inst.AccountMetaSlice[1])) + accountsBranch.Child(ag_format.Meta("systemProgram", inst.AccountMetaSlice[2])) + }) + }) + }) +} + +func (obj UpdateDefaultGasLimit) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { + // Serialize `NewGasLimit` param: + err = encoder.Encode(obj.NewGasLimit) + if err != nil { + return err + } + return nil +} +func (obj *UpdateDefaultGasLimit) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { + // Deserialize `NewGasLimit`: + err = decoder.Decode(&obj.NewGasLimit) + if err != nil { + return err + } + return nil +} + +// NewUpdateDefaultGasLimitInstruction declares a new UpdateDefaultGasLimit instruction with the provided parameters and accounts. +func NewUpdateDefaultGasLimitInstruction( + // Parameters: + newGasLimit ag_binary.Uint128, + // Accounts: + config ag_solanago.PublicKey, + authority ag_solanago.PublicKey, + systemProgram ag_solanago.PublicKey) *UpdateDefaultGasLimit { + return NewUpdateDefaultGasLimitInstructionBuilder(). + SetNewGasLimit(newGasLimit). + SetConfigAccount(config). + SetAuthorityAccount(authority). + SetSystemProgramAccount(systemProgram) +} diff --git a/core/capabilities/ccip/ccipsolana/ccip_router/UpdateDefaultGasLimit_test.go b/core/capabilities/ccip/ccipsolana/ccip_router/UpdateDefaultGasLimit_test.go new file mode 100644 index 00000000000..f323c69e6b8 --- /dev/null +++ b/core/capabilities/ccip/ccipsolana/ccip_router/UpdateDefaultGasLimit_test.go @@ -0,0 +1,32 @@ +// Code generated by https://github.com/gagliardetto/anchor-go. DO NOT EDIT. + +package ccip_router + +import ( + "bytes" + ag_gofuzz "github.com/gagliardetto/gofuzz" + ag_require "github.com/stretchr/testify/require" + "strconv" + "testing" +) + +func TestEncodeDecode_UpdateDefaultGasLimit(t *testing.T) { + fu := ag_gofuzz.New().NilChance(0) + for i := 0; i < 1; i++ { + t.Run("UpdateDefaultGasLimit"+strconv.Itoa(i), func(t *testing.T) { + { + params := new(UpdateDefaultGasLimit) + fu.Fuzz(params) + params.AccountMetaSlice = nil + buf := new(bytes.Buffer) + err := encodeT(*params, buf) + ag_require.NoError(t, err) + got := new(UpdateDefaultGasLimit) + err = decodeT(got, buf.Bytes()) + got.AccountMetaSlice = nil + ag_require.NoError(t, err) + ag_require.Equal(t, params, got) + } + }) + } +} diff --git a/core/capabilities/ccip/ccipsolana/ccip_router/UpdateEnableManualExecutionAfter.go b/core/capabilities/ccip/ccipsolana/ccip_router/UpdateEnableManualExecutionAfter.go new file mode 100644 index 00000000000..5adb9d10708 --- /dev/null +++ b/core/capabilities/ccip/ccipsolana/ccip_router/UpdateEnableManualExecutionAfter.go @@ -0,0 +1,165 @@ +// Code generated by https://github.com/gagliardetto/anchor-go. DO NOT EDIT. + +package ccip_router + +import ( + "errors" + ag_binary "github.com/gagliardetto/binary" + ag_solanago "github.com/gagliardetto/solana-go" + ag_format "github.com/gagliardetto/solana-go/text/format" + ag_treeout "github.com/gagliardetto/treeout" +) + +// The Admin can update the configuration of the Router, in this case the Enable Manual Execution After +type UpdateEnableManualExecutionAfter struct { + NewEnableManualExecutionAfter *int64 + + // [0] = [WRITE] config + // + // [1] = [SIGNER] authority + // + // [2] = [] systemProgram + ag_solanago.AccountMetaSlice `bin:"-" borsh_skip:"true"` +} + +// NewUpdateEnableManualExecutionAfterInstructionBuilder creates a new `UpdateEnableManualExecutionAfter` instruction builder. +func NewUpdateEnableManualExecutionAfterInstructionBuilder() *UpdateEnableManualExecutionAfter { + nd := &UpdateEnableManualExecutionAfter{ + AccountMetaSlice: make(ag_solanago.AccountMetaSlice, 3), + } + return nd +} + +// SetNewEnableManualExecutionAfter sets the "newEnableManualExecutionAfter" parameter. +func (inst *UpdateEnableManualExecutionAfter) SetNewEnableManualExecutionAfter(newEnableManualExecutionAfter int64) *UpdateEnableManualExecutionAfter { + inst.NewEnableManualExecutionAfter = &newEnableManualExecutionAfter + return inst +} + +// SetConfigAccount sets the "config" account. +func (inst *UpdateEnableManualExecutionAfter) SetConfigAccount(config ag_solanago.PublicKey) *UpdateEnableManualExecutionAfter { + inst.AccountMetaSlice[0] = ag_solanago.Meta(config).WRITE() + return inst +} + +// GetConfigAccount gets the "config" account. +func (inst *UpdateEnableManualExecutionAfter) GetConfigAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[0] +} + +// SetAuthorityAccount sets the "authority" account. +func (inst *UpdateEnableManualExecutionAfter) SetAuthorityAccount(authority ag_solanago.PublicKey) *UpdateEnableManualExecutionAfter { + inst.AccountMetaSlice[1] = ag_solanago.Meta(authority).SIGNER() + return inst +} + +// GetAuthorityAccount gets the "authority" account. +func (inst *UpdateEnableManualExecutionAfter) GetAuthorityAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[1] +} + +// SetSystemProgramAccount sets the "systemProgram" account. +func (inst *UpdateEnableManualExecutionAfter) SetSystemProgramAccount(systemProgram ag_solanago.PublicKey) *UpdateEnableManualExecutionAfter { + inst.AccountMetaSlice[2] = ag_solanago.Meta(systemProgram) + return inst +} + +// GetSystemProgramAccount gets the "systemProgram" account. +func (inst *UpdateEnableManualExecutionAfter) GetSystemProgramAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[2] +} + +func (inst UpdateEnableManualExecutionAfter) Build() *Instruction { + return &Instruction{BaseVariant: ag_binary.BaseVariant{ + Impl: inst, + TypeID: Instruction_UpdateEnableManualExecutionAfter, + }} +} + +// ValidateAndBuild validates the instruction parameters and accounts; +// if there is a validation error, it returns the error. +// Otherwise, it builds and returns the instruction. +func (inst UpdateEnableManualExecutionAfter) ValidateAndBuild() (*Instruction, error) { + if err := inst.Validate(); err != nil { + return nil, err + } + return inst.Build(), nil +} + +func (inst *UpdateEnableManualExecutionAfter) Validate() error { + // Check whether all (required) parameters are set: + { + if inst.NewEnableManualExecutionAfter == nil { + return errors.New("NewEnableManualExecutionAfter parameter is not set") + } + } + + // Check whether all (required) accounts are set: + { + if inst.AccountMetaSlice[0] == nil { + return errors.New("accounts.Config is not set") + } + if inst.AccountMetaSlice[1] == nil { + return errors.New("accounts.Authority is not set") + } + if inst.AccountMetaSlice[2] == nil { + return errors.New("accounts.SystemProgram is not set") + } + } + return nil +} + +func (inst *UpdateEnableManualExecutionAfter) EncodeToTree(parent ag_treeout.Branches) { + parent.Child(ag_format.Program(ProgramName, ProgramID)). + // + ParentFunc(func(programBranch ag_treeout.Branches) { + programBranch.Child(ag_format.Instruction("UpdateEnableManualExecutionAfter")). + // + ParentFunc(func(instructionBranch ag_treeout.Branches) { + + // Parameters of the instruction: + instructionBranch.Child("Params[len=1]").ParentFunc(func(paramsBranch ag_treeout.Branches) { + paramsBranch.Child(ag_format.Param("NewEnableManualExecutionAfter", *inst.NewEnableManualExecutionAfter)) + }) + + // Accounts of the instruction: + instructionBranch.Child("Accounts[len=3]").ParentFunc(func(accountsBranch ag_treeout.Branches) { + accountsBranch.Child(ag_format.Meta(" config", inst.AccountMetaSlice[0])) + accountsBranch.Child(ag_format.Meta(" authority", inst.AccountMetaSlice[1])) + accountsBranch.Child(ag_format.Meta("systemProgram", inst.AccountMetaSlice[2])) + }) + }) + }) +} + +func (obj UpdateEnableManualExecutionAfter) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { + // Serialize `NewEnableManualExecutionAfter` param: + err = encoder.Encode(obj.NewEnableManualExecutionAfter) + if err != nil { + return err + } + return nil +} +func (obj *UpdateEnableManualExecutionAfter) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { + // Deserialize `NewEnableManualExecutionAfter`: + err = decoder.Decode(&obj.NewEnableManualExecutionAfter) + if err != nil { + return err + } + return nil +} + +// NewUpdateEnableManualExecutionAfterInstruction declares a new UpdateEnableManualExecutionAfter instruction with the provided parameters and accounts. +func NewUpdateEnableManualExecutionAfterInstruction( + // Parameters: + newEnableManualExecutionAfter int64, + // Accounts: + config ag_solanago.PublicKey, + authority ag_solanago.PublicKey, + systemProgram ag_solanago.PublicKey) *UpdateEnableManualExecutionAfter { + return NewUpdateEnableManualExecutionAfterInstructionBuilder(). + SetNewEnableManualExecutionAfter(newEnableManualExecutionAfter). + SetConfigAccount(config). + SetAuthorityAccount(authority). + SetSystemProgramAccount(systemProgram) +} diff --git a/core/capabilities/ccip/ccipsolana/ccip_router/UpdateEnableManualExecutionAfter_test.go b/core/capabilities/ccip/ccipsolana/ccip_router/UpdateEnableManualExecutionAfter_test.go new file mode 100644 index 00000000000..cc37505f599 --- /dev/null +++ b/core/capabilities/ccip/ccipsolana/ccip_router/UpdateEnableManualExecutionAfter_test.go @@ -0,0 +1,32 @@ +// Code generated by https://github.com/gagliardetto/anchor-go. DO NOT EDIT. + +package ccip_router + +import ( + "bytes" + ag_gofuzz "github.com/gagliardetto/gofuzz" + ag_require "github.com/stretchr/testify/require" + "strconv" + "testing" +) + +func TestEncodeDecode_UpdateEnableManualExecutionAfter(t *testing.T) { + fu := ag_gofuzz.New().NilChance(0) + for i := 0; i < 1; i++ { + t.Run("UpdateEnableManualExecutionAfter"+strconv.Itoa(i), func(t *testing.T) { + { + params := new(UpdateEnableManualExecutionAfter) + fu.Fuzz(params) + params.AccountMetaSlice = nil + buf := new(bytes.Buffer) + err := encodeT(*params, buf) + ag_require.NoError(t, err) + got := new(UpdateEnableManualExecutionAfter) + err = decodeT(got, buf.Bytes()) + got.AccountMetaSlice = nil + ag_require.NoError(t, err) + ag_require.Equal(t, params, got) + } + }) + } +} diff --git a/core/capabilities/ccip/ccipsolana/ccip_router/UpdateSolanaChainSelector.go b/core/capabilities/ccip/ccipsolana/ccip_router/UpdateSolanaChainSelector.go new file mode 100644 index 00000000000..58796f4e381 --- /dev/null +++ b/core/capabilities/ccip/ccipsolana/ccip_router/UpdateSolanaChainSelector.go @@ -0,0 +1,165 @@ +// Code generated by https://github.com/gagliardetto/anchor-go. DO NOT EDIT. + +package ccip_router + +import ( + "errors" + ag_binary "github.com/gagliardetto/binary" + ag_solanago "github.com/gagliardetto/solana-go" + ag_format "github.com/gagliardetto/solana-go/text/format" + ag_treeout "github.com/gagliardetto/treeout" +) + +// The Admin can update the configuration of the Router, in this case the Solana Chain Selector +type UpdateSolanaChainSelector struct { + NewChainSelector *uint64 + + // [0] = [WRITE] config + // + // [1] = [SIGNER] authority + // + // [2] = [] systemProgram + ag_solanago.AccountMetaSlice `bin:"-" borsh_skip:"true"` +} + +// NewUpdateSolanaChainSelectorInstructionBuilder creates a new `UpdateSolanaChainSelector` instruction builder. +func NewUpdateSolanaChainSelectorInstructionBuilder() *UpdateSolanaChainSelector { + nd := &UpdateSolanaChainSelector{ + AccountMetaSlice: make(ag_solanago.AccountMetaSlice, 3), + } + return nd +} + +// SetNewChainSelector sets the "newChainSelector" parameter. +func (inst *UpdateSolanaChainSelector) SetNewChainSelector(newChainSelector uint64) *UpdateSolanaChainSelector { + inst.NewChainSelector = &newChainSelector + return inst +} + +// SetConfigAccount sets the "config" account. +func (inst *UpdateSolanaChainSelector) SetConfigAccount(config ag_solanago.PublicKey) *UpdateSolanaChainSelector { + inst.AccountMetaSlice[0] = ag_solanago.Meta(config).WRITE() + return inst +} + +// GetConfigAccount gets the "config" account. +func (inst *UpdateSolanaChainSelector) GetConfigAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[0] +} + +// SetAuthorityAccount sets the "authority" account. +func (inst *UpdateSolanaChainSelector) SetAuthorityAccount(authority ag_solanago.PublicKey) *UpdateSolanaChainSelector { + inst.AccountMetaSlice[1] = ag_solanago.Meta(authority).SIGNER() + return inst +} + +// GetAuthorityAccount gets the "authority" account. +func (inst *UpdateSolanaChainSelector) GetAuthorityAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[1] +} + +// SetSystemProgramAccount sets the "systemProgram" account. +func (inst *UpdateSolanaChainSelector) SetSystemProgramAccount(systemProgram ag_solanago.PublicKey) *UpdateSolanaChainSelector { + inst.AccountMetaSlice[2] = ag_solanago.Meta(systemProgram) + return inst +} + +// GetSystemProgramAccount gets the "systemProgram" account. +func (inst *UpdateSolanaChainSelector) GetSystemProgramAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[2] +} + +func (inst UpdateSolanaChainSelector) Build() *Instruction { + return &Instruction{BaseVariant: ag_binary.BaseVariant{ + Impl: inst, + TypeID: Instruction_UpdateSolanaChainSelector, + }} +} + +// ValidateAndBuild validates the instruction parameters and accounts; +// if there is a validation error, it returns the error. +// Otherwise, it builds and returns the instruction. +func (inst UpdateSolanaChainSelector) ValidateAndBuild() (*Instruction, error) { + if err := inst.Validate(); err != nil { + return nil, err + } + return inst.Build(), nil +} + +func (inst *UpdateSolanaChainSelector) Validate() error { + // Check whether all (required) parameters are set: + { + if inst.NewChainSelector == nil { + return errors.New("NewChainSelector parameter is not set") + } + } + + // Check whether all (required) accounts are set: + { + if inst.AccountMetaSlice[0] == nil { + return errors.New("accounts.Config is not set") + } + if inst.AccountMetaSlice[1] == nil { + return errors.New("accounts.Authority is not set") + } + if inst.AccountMetaSlice[2] == nil { + return errors.New("accounts.SystemProgram is not set") + } + } + return nil +} + +func (inst *UpdateSolanaChainSelector) EncodeToTree(parent ag_treeout.Branches) { + parent.Child(ag_format.Program(ProgramName, ProgramID)). + // + ParentFunc(func(programBranch ag_treeout.Branches) { + programBranch.Child(ag_format.Instruction("UpdateSolanaChainSelector")). + // + ParentFunc(func(instructionBranch ag_treeout.Branches) { + + // Parameters of the instruction: + instructionBranch.Child("Params[len=1]").ParentFunc(func(paramsBranch ag_treeout.Branches) { + paramsBranch.Child(ag_format.Param("NewChainSelector", *inst.NewChainSelector)) + }) + + // Accounts of the instruction: + instructionBranch.Child("Accounts[len=3]").ParentFunc(func(accountsBranch ag_treeout.Branches) { + accountsBranch.Child(ag_format.Meta(" config", inst.AccountMetaSlice[0])) + accountsBranch.Child(ag_format.Meta(" authority", inst.AccountMetaSlice[1])) + accountsBranch.Child(ag_format.Meta("systemProgram", inst.AccountMetaSlice[2])) + }) + }) + }) +} + +func (obj UpdateSolanaChainSelector) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { + // Serialize `NewChainSelector` param: + err = encoder.Encode(obj.NewChainSelector) + if err != nil { + return err + } + return nil +} +func (obj *UpdateSolanaChainSelector) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { + // Deserialize `NewChainSelector`: + err = decoder.Decode(&obj.NewChainSelector) + if err != nil { + return err + } + return nil +} + +// NewUpdateSolanaChainSelectorInstruction declares a new UpdateSolanaChainSelector instruction with the provided parameters and accounts. +func NewUpdateSolanaChainSelectorInstruction( + // Parameters: + newChainSelector uint64, + // Accounts: + config ag_solanago.PublicKey, + authority ag_solanago.PublicKey, + systemProgram ag_solanago.PublicKey) *UpdateSolanaChainSelector { + return NewUpdateSolanaChainSelectorInstructionBuilder(). + SetNewChainSelector(newChainSelector). + SetConfigAccount(config). + SetAuthorityAccount(authority). + SetSystemProgramAccount(systemProgram) +} diff --git a/core/capabilities/ccip/ccipsolana/ccip_router/UpdateSolanaChainSelector_test.go b/core/capabilities/ccip/ccipsolana/ccip_router/UpdateSolanaChainSelector_test.go new file mode 100644 index 00000000000..00901a4a9af --- /dev/null +++ b/core/capabilities/ccip/ccipsolana/ccip_router/UpdateSolanaChainSelector_test.go @@ -0,0 +1,32 @@ +// Code generated by https://github.com/gagliardetto/anchor-go. DO NOT EDIT. + +package ccip_router + +import ( + "bytes" + ag_gofuzz "github.com/gagliardetto/gofuzz" + ag_require "github.com/stretchr/testify/require" + "strconv" + "testing" +) + +func TestEncodeDecode_UpdateSolanaChainSelector(t *testing.T) { + fu := ag_gofuzz.New().NilChance(0) + for i := 0; i < 1; i++ { + t.Run("UpdateSolanaChainSelector"+strconv.Itoa(i), func(t *testing.T) { + { + params := new(UpdateSolanaChainSelector) + fu.Fuzz(params) + params.AccountMetaSlice = nil + buf := new(bytes.Buffer) + err := encodeT(*params, buf) + ag_require.NoError(t, err) + got := new(UpdateSolanaChainSelector) + err = decodeT(got, buf.Bytes()) + got.AccountMetaSlice = nil + ag_require.NoError(t, err) + ag_require.Equal(t, params, got) + } + }) + } +} diff --git a/core/capabilities/ccip/ccipsolana/ccip_router/accounts.go b/core/capabilities/ccip/ccipsolana/ccip_router/accounts.go new file mode 100644 index 00000000000..44c43c1d364 --- /dev/null +++ b/core/capabilities/ccip/ccipsolana/ccip_router/accounts.go @@ -0,0 +1,661 @@ +// Code generated by https://github.com/gagliardetto/anchor-go. DO NOT EDIT. + +package ccip_router + +import ( + "fmt" + ag_binary "github.com/gagliardetto/binary" + ag_solanago "github.com/gagliardetto/solana-go" +) + +type Config struct { + Version uint8 + DefaultAllowOutOfOrderExecution uint8 + Padding0 [6]uint8 + SolanaChainSelector uint64 + DefaultGasLimit ag_binary.Uint128 + Padding1 [8]uint8 + Owner ag_solanago.PublicKey + ProposedOwner ag_solanago.PublicKey + EnableManualExecutionAfter int64 + Padding2 [8]uint8 + Ocr3 [2]Ocr3Config +} + +var ConfigDiscriminator = [8]byte{155, 12, 170, 224, 30, 250, 204, 130} + +func (obj Config) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { + // Write account discriminator: + err = encoder.WriteBytes(ConfigDiscriminator[:], false) + if err != nil { + return err + } + // Serialize `Version` param: + err = encoder.Encode(obj.Version) + if err != nil { + return err + } + // Serialize `DefaultAllowOutOfOrderExecution` param: + err = encoder.Encode(obj.DefaultAllowOutOfOrderExecution) + if err != nil { + return err + } + // Serialize `Padding0` param: + err = encoder.Encode(obj.Padding0) + if err != nil { + return err + } + // Serialize `SolanaChainSelector` param: + err = encoder.Encode(obj.SolanaChainSelector) + if err != nil { + return err + } + // Serialize `DefaultGasLimit` param: + err = encoder.Encode(obj.DefaultGasLimit) + if err != nil { + return err + } + // Serialize `Padding1` param: + err = encoder.Encode(obj.Padding1) + if err != nil { + return err + } + // Serialize `Owner` param: + err = encoder.Encode(obj.Owner) + if err != nil { + return err + } + // Serialize `ProposedOwner` param: + err = encoder.Encode(obj.ProposedOwner) + if err != nil { + return err + } + // Serialize `EnableManualExecutionAfter` param: + err = encoder.Encode(obj.EnableManualExecutionAfter) + if err != nil { + return err + } + // Serialize `Padding2` param: + err = encoder.Encode(obj.Padding2) + if err != nil { + return err + } + // Serialize `Ocr3` param: + err = encoder.Encode(obj.Ocr3) + if err != nil { + return err + } + return nil +} + +func (obj *Config) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { + // Read and check account discriminator: + { + discriminator, err := decoder.ReadTypeID() + if err != nil { + return err + } + if !discriminator.Equal(ConfigDiscriminator[:]) { + return fmt.Errorf( + "wrong discriminator: wanted %s, got %s", + "[155 12 170 224 30 250 204 130]", + fmt.Sprint(discriminator[:])) + } + } + // Deserialize `Version`: + err = decoder.Decode(&obj.Version) + if err != nil { + return err + } + // Deserialize `DefaultAllowOutOfOrderExecution`: + err = decoder.Decode(&obj.DefaultAllowOutOfOrderExecution) + if err != nil { + return err + } + // Deserialize `Padding0`: + err = decoder.Decode(&obj.Padding0) + if err != nil { + return err + } + // Deserialize `SolanaChainSelector`: + err = decoder.Decode(&obj.SolanaChainSelector) + if err != nil { + return err + } + // Deserialize `DefaultGasLimit`: + err = decoder.Decode(&obj.DefaultGasLimit) + if err != nil { + return err + } + // Deserialize `Padding1`: + err = decoder.Decode(&obj.Padding1) + if err != nil { + return err + } + // Deserialize `Owner`: + err = decoder.Decode(&obj.Owner) + if err != nil { + return err + } + // Deserialize `ProposedOwner`: + err = decoder.Decode(&obj.ProposedOwner) + if err != nil { + return err + } + // Deserialize `EnableManualExecutionAfter`: + err = decoder.Decode(&obj.EnableManualExecutionAfter) + if err != nil { + return err + } + // Deserialize `Padding2`: + err = decoder.Decode(&obj.Padding2) + if err != nil { + return err + } + // Deserialize `Ocr3`: + err = decoder.Decode(&obj.Ocr3) + if err != nil { + return err + } + return nil +} + +type ChainState struct { + Version uint8 + SourceChainConfig SourceChainConfig + DestChainConfig DestChainConfig +} + +var ChainStateDiscriminator = [8]byte{130, 46, 94, 156, 79, 53, 170, 50} + +func (obj ChainState) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { + // Write account discriminator: + err = encoder.WriteBytes(ChainStateDiscriminator[:], false) + if err != nil { + return err + } + // Serialize `Version` param: + err = encoder.Encode(obj.Version) + if err != nil { + return err + } + // Serialize `SourceChainConfig` param: + err = encoder.Encode(obj.SourceChainConfig) + if err != nil { + return err + } + // Serialize `DestChainConfig` param: + err = encoder.Encode(obj.DestChainConfig) + if err != nil { + return err + } + return nil +} + +func (obj *ChainState) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { + // Read and check account discriminator: + { + discriminator, err := decoder.ReadTypeID() + if err != nil { + return err + } + if !discriminator.Equal(ChainStateDiscriminator[:]) { + return fmt.Errorf( + "wrong discriminator: wanted %s, got %s", + "[130 46 94 156 79 53 170 50]", + fmt.Sprint(discriminator[:])) + } + } + // Deserialize `Version`: + err = decoder.Decode(&obj.Version) + if err != nil { + return err + } + // Deserialize `SourceChainConfig`: + err = decoder.Decode(&obj.SourceChainConfig) + if err != nil { + return err + } + // Deserialize `DestChainConfig`: + err = decoder.Decode(&obj.DestChainConfig) + if err != nil { + return err + } + return nil +} + +type Nonce struct { + Version uint8 + Counter uint64 +} + +var NonceDiscriminator = [8]byte{143, 197, 147, 95, 106, 165, 50, 43} + +func (obj Nonce) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { + // Write account discriminator: + err = encoder.WriteBytes(NonceDiscriminator[:], false) + if err != nil { + return err + } + // Serialize `Version` param: + err = encoder.Encode(obj.Version) + if err != nil { + return err + } + // Serialize `Counter` param: + err = encoder.Encode(obj.Counter) + if err != nil { + return err + } + return nil +} + +func (obj *Nonce) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { + // Read and check account discriminator: + { + discriminator, err := decoder.ReadTypeID() + if err != nil { + return err + } + if !discriminator.Equal(NonceDiscriminator[:]) { + return fmt.Errorf( + "wrong discriminator: wanted %s, got %s", + "[143 197 147 95 106 165 50 43]", + fmt.Sprint(discriminator[:])) + } + } + // Deserialize `Version`: + err = decoder.Decode(&obj.Version) + if err != nil { + return err + } + // Deserialize `Counter`: + err = decoder.Decode(&obj.Counter) + if err != nil { + return err + } + return nil +} + +type ExternalExecutionConfig struct{} + +var ExternalExecutionConfigDiscriminator = [8]byte{159, 157, 150, 212, 168, 103, 117, 39} + +func (obj ExternalExecutionConfig) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { + // Write account discriminator: + err = encoder.WriteBytes(ExternalExecutionConfigDiscriminator[:], false) + if err != nil { + return err + } + return nil +} + +func (obj *ExternalExecutionConfig) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { + // Read and check account discriminator: + { + discriminator, err := decoder.ReadTypeID() + if err != nil { + return err + } + if !discriminator.Equal(ExternalExecutionConfigDiscriminator[:]) { + return fmt.Errorf( + "wrong discriminator: wanted %s, got %s", + "[159 157 150 212 168 103 117 39]", + fmt.Sprint(discriminator[:])) + } + } + return nil +} + +type CommitReport struct { + Version uint8 + Timestamp int64 + MinMsgNr uint64 + MaxMsgNr uint64 + ExecutionStates ag_binary.Uint128 +} + +var CommitReportDiscriminator = [8]byte{46, 231, 247, 231, 174, 68, 34, 26} + +func (obj CommitReport) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { + // Write account discriminator: + err = encoder.WriteBytes(CommitReportDiscriminator[:], false) + if err != nil { + return err + } + // Serialize `Version` param: + err = encoder.Encode(obj.Version) + if err != nil { + return err + } + // Serialize `Timestamp` param: + err = encoder.Encode(obj.Timestamp) + if err != nil { + return err + } + // Serialize `MinMsgNr` param: + err = encoder.Encode(obj.MinMsgNr) + if err != nil { + return err + } + // Serialize `MaxMsgNr` param: + err = encoder.Encode(obj.MaxMsgNr) + if err != nil { + return err + } + // Serialize `ExecutionStates` param: + err = encoder.Encode(obj.ExecutionStates) + if err != nil { + return err + } + return nil +} + +func (obj *CommitReport) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { + // Read and check account discriminator: + { + discriminator, err := decoder.ReadTypeID() + if err != nil { + return err + } + if !discriminator.Equal(CommitReportDiscriminator[:]) { + return fmt.Errorf( + "wrong discriminator: wanted %s, got %s", + "[46 231 247 231 174 68 34 26]", + fmt.Sprint(discriminator[:])) + } + } + // Deserialize `Version`: + err = decoder.Decode(&obj.Version) + if err != nil { + return err + } + // Deserialize `Timestamp`: + err = decoder.Decode(&obj.Timestamp) + if err != nil { + return err + } + // Deserialize `MinMsgNr`: + err = decoder.Decode(&obj.MinMsgNr) + if err != nil { + return err + } + // Deserialize `MaxMsgNr`: + err = decoder.Decode(&obj.MaxMsgNr) + if err != nil { + return err + } + // Deserialize `ExecutionStates`: + err = decoder.Decode(&obj.ExecutionStates) + if err != nil { + return err + } + return nil +} + +type PerChainPerTokenConfig struct { + Version uint8 + ChainSelector uint64 + Mint ag_solanago.PublicKey + Billing TokenBilling +} + +var PerChainPerTokenConfigDiscriminator = [8]byte{183, 88, 20, 99, 246, 46, 51, 230} + +func (obj PerChainPerTokenConfig) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { + // Write account discriminator: + err = encoder.WriteBytes(PerChainPerTokenConfigDiscriminator[:], false) + if err != nil { + return err + } + // Serialize `Version` param: + err = encoder.Encode(obj.Version) + if err != nil { + return err + } + // Serialize `ChainSelector` param: + err = encoder.Encode(obj.ChainSelector) + if err != nil { + return err + } + // Serialize `Mint` param: + err = encoder.Encode(obj.Mint) + if err != nil { + return err + } + // Serialize `Billing` param: + err = encoder.Encode(obj.Billing) + if err != nil { + return err + } + return nil +} + +func (obj *PerChainPerTokenConfig) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { + // Read and check account discriminator: + { + discriminator, err := decoder.ReadTypeID() + if err != nil { + return err + } + if !discriminator.Equal(PerChainPerTokenConfigDiscriminator[:]) { + return fmt.Errorf( + "wrong discriminator: wanted %s, got %s", + "[183 88 20 99 246 46 51 230]", + fmt.Sprint(discriminator[:])) + } + } + // Deserialize `Version`: + err = decoder.Decode(&obj.Version) + if err != nil { + return err + } + // Deserialize `ChainSelector`: + err = decoder.Decode(&obj.ChainSelector) + if err != nil { + return err + } + // Deserialize `Mint`: + err = decoder.Decode(&obj.Mint) + if err != nil { + return err + } + // Deserialize `Billing`: + err = decoder.Decode(&obj.Billing) + if err != nil { + return err + } + return nil +} + +type BillingTokenConfig struct { + Version uint8 + Enabled bool + UsdPerToken TimestampedPackedU224 + PremiumMultiplierWeiPerEth uint64 +} + +var BillingTokenConfigDiscriminator = [8]byte{191, 91, 1, 0, 93, 250, 239, 41} + +func (obj BillingTokenConfig) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { + // Write account discriminator: + err = encoder.WriteBytes(BillingTokenConfigDiscriminator[:], false) + if err != nil { + return err + } + // Serialize `Version` param: + err = encoder.Encode(obj.Version) + if err != nil { + return err + } + // Serialize `Enabled` param: + err = encoder.Encode(obj.Enabled) + if err != nil { + return err + } + // Serialize `UsdPerToken` param: + err = encoder.Encode(obj.UsdPerToken) + if err != nil { + return err + } + // Serialize `PremiumMultiplierWeiPerEth` param: + err = encoder.Encode(obj.PremiumMultiplierWeiPerEth) + if err != nil { + return err + } + return nil +} + +func (obj *BillingTokenConfig) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { + // Read and check account discriminator: + { + discriminator, err := decoder.ReadTypeID() + if err != nil { + return err + } + if !discriminator.Equal(BillingTokenConfigDiscriminator[:]) { + return fmt.Errorf( + "wrong discriminator: wanted %s, got %s", + "[191 91 1 0 93 250 239 41]", + fmt.Sprint(discriminator[:])) + } + } + // Deserialize `Version`: + err = decoder.Decode(&obj.Version) + if err != nil { + return err + } + // Deserialize `Enabled`: + err = decoder.Decode(&obj.Enabled) + if err != nil { + return err + } + // Deserialize `UsdPerToken`: + err = decoder.Decode(&obj.UsdPerToken) + if err != nil { + return err + } + // Deserialize `PremiumMultiplierWeiPerEth`: + err = decoder.Decode(&obj.PremiumMultiplierWeiPerEth) + if err != nil { + return err + } + return nil +} + +type TokenAdminRegistry struct { + Version uint8 + Administrator ag_solanago.PublicKey + PendingAdministrator *ag_solanago.PublicKey `bin:"optional"` + TokenPoolProgram *ag_solanago.PublicKey `bin:"optional"` +} + +var TokenAdminRegistryDiscriminator = [8]byte{70, 92, 207, 200, 76, 17, 57, 114} + +func (obj TokenAdminRegistry) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { + // Write account discriminator: + err = encoder.WriteBytes(TokenAdminRegistryDiscriminator[:], false) + if err != nil { + return err + } + // Serialize `Version` param: + err = encoder.Encode(obj.Version) + if err != nil { + return err + } + // Serialize `Administrator` param: + err = encoder.Encode(obj.Administrator) + if err != nil { + return err + } + // Serialize `PendingAdministrator` param (optional): + { + if obj.PendingAdministrator == nil { + err = encoder.WriteBool(false) + if err != nil { + return err + } + } else { + err = encoder.WriteBool(true) + if err != nil { + return err + } + err = encoder.Encode(obj.PendingAdministrator) + if err != nil { + return err + } + } + } + // Serialize `TokenPoolProgram` param (optional): + { + if obj.TokenPoolProgram == nil { + err = encoder.WriteBool(false) + if err != nil { + return err + } + } else { + err = encoder.WriteBool(true) + if err != nil { + return err + } + err = encoder.Encode(obj.TokenPoolProgram) + if err != nil { + return err + } + } + } + return nil +} + +func (obj *TokenAdminRegistry) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { + // Read and check account discriminator: + { + discriminator, err := decoder.ReadTypeID() + if err != nil { + return err + } + if !discriminator.Equal(TokenAdminRegistryDiscriminator[:]) { + return fmt.Errorf( + "wrong discriminator: wanted %s, got %s", + "[70 92 207 200 76 17 57 114]", + fmt.Sprint(discriminator[:])) + } + } + // Deserialize `Version`: + err = decoder.Decode(&obj.Version) + if err != nil { + return err + } + // Deserialize `Administrator`: + err = decoder.Decode(&obj.Administrator) + if err != nil { + return err + } + // Deserialize `PendingAdministrator` (optional): + { + ok, err := decoder.ReadBool() + if err != nil { + return err + } + if ok { + err = decoder.Decode(&obj.PendingAdministrator) + if err != nil { + return err + } + } + } + // Deserialize `TokenPoolProgram` (optional): + { + ok, err := decoder.ReadBool() + if err != nil { + return err + } + if ok { + err = decoder.Decode(&obj.TokenPoolProgram) + if err != nil { + return err + } + } + } + return nil +} diff --git a/core/capabilities/ccip/ccipsolana/ccip_router/instructions.go b/core/capabilities/ccip/ccipsolana/ccip_router/instructions.go new file mode 100644 index 00000000000..395e39da2ea --- /dev/null +++ b/core/capabilities/ccip/ccipsolana/ccip_router/instructions.go @@ -0,0 +1,304 @@ +// This is the Collapsed Router Program for CCIP. +// As it's upgradable persisting the same program id, there is no need to have an indirection of a Proxy Program. +// This Router handles both the OnRamp and OffRamp flow of the CCIP Messages. +// Code generated by https://github.com/gagliardetto/anchor-go. DO NOT EDIT. + +package ccip_router + +import ( + "bytes" + "fmt" + ag_spew "github.com/davecgh/go-spew/spew" + ag_binary "github.com/gagliardetto/binary" + ag_solanago "github.com/gagliardetto/solana-go" + ag_text "github.com/gagliardetto/solana-go/text" + ag_treeout "github.com/gagliardetto/treeout" +) + +var ProgramID ag_solanago.PublicKey + +func SetProgramID(pubkey ag_solanago.PublicKey) { + ProgramID = pubkey + ag_solanago.RegisterInstructionDecoder(ProgramID, registryDecodeInstruction) +} + +const ProgramName = "CcipRouter" + +func init() { + if !ProgramID.IsZero() { + ag_solanago.RegisterInstructionDecoder(ProgramID, registryDecodeInstruction) + } +} + +var ( + // The initialization is responsibility of Admin, nothing more than calling this method should be done first. + Instruction_Initialize = ag_binary.TypeID([8]byte{175, 175, 109, 31, 13, 152, 155, 237}) + + Instruction_TransferOwnership = ag_binary.TypeID([8]byte{65, 177, 215, 73, 53, 45, 99, 47}) + + Instruction_AcceptOwnership = ag_binary.TypeID([8]byte{172, 23, 43, 13, 238, 213, 85, 150}) + + // The Admin needs to add any new chain supported (this means both OnRamp and OffRamp). + Instruction_AddChainSelector = ag_binary.TypeID([8]byte{28, 60, 171, 0, 195, 113, 56, 7}) + + // The Admin is the only one able to enable or disable the chain selector + Instruction_DisableChainSelector = ag_binary.TypeID([8]byte{24, 245, 159, 178, 139, 200, 133, 218}) + + // The Admin is the only one able to enable or disable the chain selector + Instruction_EnableChainSelector = ag_binary.TypeID([8]byte{29, 175, 195, 14, 137, 66, 194, 25}) + + // The Admin can update the configuration of the Router, in this case the Solana Chain Selector + Instruction_UpdateSolanaChainSelector = ag_binary.TypeID([8]byte{128, 198, 143, 222, 43, 55, 119, 106}) + + // The Admin can update the configuration of the Router, in this case the Default Gas Limit + Instruction_UpdateDefaultGasLimit = ag_binary.TypeID([8]byte{201, 34, 231, 229, 247, 252, 77, 210}) + + // The Admin can update the configuration of the Router, in this case the Default Allow Out Of Order Execution (True/False) + Instruction_UpdateDefaultAllowOutOfOrderExecution = ag_binary.TypeID([8]byte{44, 54, 136, 71, 177, 17, 18, 241}) + + // The Admin can update the configuration of the Router, in this case the Enable Manual Execution After + Instruction_UpdateEnableManualExecutionAfter = ag_binary.TypeID([8]byte{157, 236, 73, 92, 84, 197, 152, 105}) + + // The CCIP Admin or the Mint Authority of the Token can register the Token Admin Registry + Instruction_RegisterTokenAdminRegistryViaGetCcipAdmin = ag_binary.TypeID([8]byte{46, 246, 21, 58, 175, 69, 40, 202}) + + // The Token's mint_authority can register themselves to the Token Admin Registry + Instruction_RegisterTokenAdminRegistryViaOwner = ag_binary.TypeID([8]byte{85, 191, 10, 113, 134, 138, 144, 16}) + + // The administrator of the token can setup the token pool + Instruction_SetPool = ag_binary.TypeID([8]byte{119, 30, 14, 180, 115, 225, 167, 238}) + + // The Admin can transfer the Admin Role of the Token Admin Registry + Instruction_TransferAdminRoleTokenAdminRegistry = ag_binary.TypeID([8]byte{178, 98, 203, 181, 203, 107, 106, 14}) + + // The Pending Admin can accept the Admin Role of the Token Admin Registry + Instruction_AcceptAdminRoleTokenAdminRegistry = ag_binary.TypeID([8]byte{106, 240, 16, 173, 137, 213, 163, 246}) + + Instruction_SetTokenBilling = ag_binary.TypeID([8]byte{225, 230, 37, 71, 131, 209, 54, 230}) + + Instruction_SetOcrConfig = ag_binary.TypeID([8]byte{4, 131, 107, 110, 250, 158, 244, 200}) + + // ON RAMP FLOW + // The method name needs to be ccip_send with Anchor encoding. + // This function is called by the CCIP Sender Contract (or final user) to send a message to the CCIP Router. + // The size limit of data is 256 bytes. + // The message is sent to the receiver on the destination chain selector. + // This message emits the event CCIPSendRequested with all the necessary data to be retrieved by the OffChain Code + Instruction_CcipSend = ag_binary.TypeID([8]byte{108, 216, 134, 191, 249, 234, 33, 84}) + + // OFF RAMP FLOW + // + // The method name needs to be commit with Anchor encoding. + // + // This function is called by the OffChain when committing one Report to the Solana Router. + // In this Flow only one report is sent, the Commit Report. This is different as EVM does, + // this is because here all the chain state is stored in one account per Merkle Tree Root. + // So, to avoid having to send a dynamic size array of accounts, in this message only one Commit Report Account is sent. + // This message validates the signatures of the report and stores the Merkle Root in the Commit Report Account. + // The Report must contain an interval of messages, and the min of them must be the next sequence number expected. + // The max size of the interval is 64. + // This message emits two events: CommitReportAccepted and Transmitted. + Instruction_Commit = ag_binary.TypeID([8]byte{223, 140, 142, 165, 229, 208, 156, 74}) + + // OFF RAMP FLOW + // + // The method name needs to be execute with Anchor encoding. + // + // This function is called by the OffChain when executing one Report to the Solana Router. + // In this Flow only one message is sent, the Execution Report. This is different as EVM does, + // this is because there is no try/catch mechanism to allow batch execution. + // This message validates that the Merkle Tree Proof of the given message is correct and is stored in the Commit Report Account. + // The message must be untouched to be executed. + // This message emits the event ExecutionStateChanged with the new state of the message. + // Finally, executes the CPI instruction to the receiver program in the ccip_receive message. + Instruction_Execute = ag_binary.TypeID([8]byte{130, 221, 242, 154, 13, 193, 189, 29}) + + // When a message is not being executed, then the user can trigger the execution manually. + // No verification over the transmitter, but the message needs to be in some commit report. + Instruction_ManuallyExecute = ag_binary.TypeID([8]byte{238, 219, 224, 11, 226, 248, 47, 192}) +) + +// InstructionIDToName returns the name of the instruction given its ID. +func InstructionIDToName(id ag_binary.TypeID) string { + switch id { + case Instruction_Initialize: + return "Initialize" + case Instruction_TransferOwnership: + return "TransferOwnership" + case Instruction_AcceptOwnership: + return "AcceptOwnership" + case Instruction_AddChainSelector: + return "AddChainSelector" + case Instruction_DisableChainSelector: + return "DisableChainSelector" + case Instruction_EnableChainSelector: + return "EnableChainSelector" + case Instruction_UpdateSolanaChainSelector: + return "UpdateSolanaChainSelector" + case Instruction_UpdateDefaultGasLimit: + return "UpdateDefaultGasLimit" + case Instruction_UpdateDefaultAllowOutOfOrderExecution: + return "UpdateDefaultAllowOutOfOrderExecution" + case Instruction_UpdateEnableManualExecutionAfter: + return "UpdateEnableManualExecutionAfter" + case Instruction_RegisterTokenAdminRegistryViaGetCcipAdmin: + return "RegisterTokenAdminRegistryViaGetCcipAdmin" + case Instruction_RegisterTokenAdminRegistryViaOwner: + return "RegisterTokenAdminRegistryViaOwner" + case Instruction_SetPool: + return "SetPool" + case Instruction_TransferAdminRoleTokenAdminRegistry: + return "TransferAdminRoleTokenAdminRegistry" + case Instruction_AcceptAdminRoleTokenAdminRegistry: + return "AcceptAdminRoleTokenAdminRegistry" + case Instruction_SetTokenBilling: + return "SetTokenBilling" + case Instruction_SetOcrConfig: + return "SetOcrConfig" + case Instruction_CcipSend: + return "CcipSend" + case Instruction_Commit: + return "Commit" + case Instruction_Execute: + return "Execute" + case Instruction_ManuallyExecute: + return "ManuallyExecute" + default: + return "" + } +} + +type Instruction struct { + ag_binary.BaseVariant +} + +func (inst *Instruction) EncodeToTree(parent ag_treeout.Branches) { + if enToTree, ok := inst.Impl.(ag_text.EncodableToTree); ok { + enToTree.EncodeToTree(parent) + } else { + parent.Child(ag_spew.Sdump(inst)) + } +} + +var InstructionImplDef = ag_binary.NewVariantDefinition( + ag_binary.AnchorTypeIDEncoding, + []ag_binary.VariantType{ + { + "initialize", (*Initialize)(nil), + }, + { + "transfer_ownership", (*TransferOwnership)(nil), + }, + { + "accept_ownership", (*AcceptOwnership)(nil), + }, + { + "add_chain_selector", (*AddChainSelector)(nil), + }, + { + "disable_chain_selector", (*DisableChainSelector)(nil), + }, + { + "enable_chain_selector", (*EnableChainSelector)(nil), + }, + { + "update_solana_chain_selector", (*UpdateSolanaChainSelector)(nil), + }, + { + "update_default_gas_limit", (*UpdateDefaultGasLimit)(nil), + }, + { + "update_default_allow_out_of_order_execution", (*UpdateDefaultAllowOutOfOrderExecution)(nil), + }, + { + "update_enable_manual_execution_after", (*UpdateEnableManualExecutionAfter)(nil), + }, + { + "register_token_admin_registry_via_get_ccip_admin", (*RegisterTokenAdminRegistryViaGetCcipAdmin)(nil), + }, + { + "register_token_admin_registry_via_owner", (*RegisterTokenAdminRegistryViaOwner)(nil), + }, + { + "set_pool", (*SetPool)(nil), + }, + { + "transfer_admin_role_token_admin_registry", (*TransferAdminRoleTokenAdminRegistry)(nil), + }, + { + "accept_admin_role_token_admin_registry", (*AcceptAdminRoleTokenAdminRegistry)(nil), + }, + { + "set_token_billing", (*SetTokenBilling)(nil), + }, + { + "set_ocr_config", (*SetOcrConfig)(nil), + }, + { + "ccip_send", (*CcipSend)(nil), + }, + { + "commit", (*Commit)(nil), + }, + { + "execute", (*Execute)(nil), + }, + { + "manually_execute", (*ManuallyExecute)(nil), + }, + }, +) + +func (inst *Instruction) ProgramID() ag_solanago.PublicKey { + return ProgramID +} + +func (inst *Instruction) Accounts() (out []*ag_solanago.AccountMeta) { + return inst.Impl.(ag_solanago.AccountsGettable).GetAccounts() +} + +func (inst *Instruction) Data() ([]byte, error) { + buf := new(bytes.Buffer) + if err := ag_binary.NewBorshEncoder(buf).Encode(inst); err != nil { + return nil, fmt.Errorf("unable to encode instruction: %w", err) + } + return buf.Bytes(), nil +} + +func (inst *Instruction) TextEncode(encoder *ag_text.Encoder, option *ag_text.Option) error { + return encoder.Encode(inst.Impl, option) +} + +func (inst *Instruction) UnmarshalWithDecoder(decoder *ag_binary.Decoder) error { + return inst.BaseVariant.UnmarshalBinaryVariant(decoder, InstructionImplDef) +} + +func (inst *Instruction) MarshalWithEncoder(encoder *ag_binary.Encoder) error { + err := encoder.WriteBytes(inst.TypeID.Bytes(), false) + if err != nil { + return fmt.Errorf("unable to write variant type: %w", err) + } + return encoder.Encode(inst.Impl) +} + +func registryDecodeInstruction(accounts []*ag_solanago.AccountMeta, data []byte) (interface{}, error) { + inst, err := DecodeInstruction(accounts, data) + if err != nil { + return nil, err + } + return inst, nil +} + +func DecodeInstruction(accounts []*ag_solanago.AccountMeta, data []byte) (*Instruction, error) { + inst := new(Instruction) + if err := ag_binary.NewBorshDecoder(data).Decode(inst); err != nil { + return nil, fmt.Errorf("unable to decode instruction: %w", err) + } + if v, ok := inst.Impl.(ag_solanago.AccountsSettable); ok { + err := v.SetAccounts(accounts) + if err != nil { + return nil, fmt.Errorf("unable to set accounts for instruction: %w", err) + } + } + return inst, nil +} diff --git a/core/capabilities/ccip/ccipsolana/ccip_router/testing_utils.go b/core/capabilities/ccip/ccipsolana/ccip_router/testing_utils.go new file mode 100644 index 00000000000..aaecdf49bad --- /dev/null +++ b/core/capabilities/ccip/ccipsolana/ccip_router/testing_utils.go @@ -0,0 +1,20 @@ +// Code generated by https://github.com/gagliardetto/anchor-go. DO NOT EDIT. + +package ccip_router + +import ( + "bytes" + "fmt" + ag_binary "github.com/gagliardetto/binary" +) + +func encodeT(data interface{}, buf *bytes.Buffer) error { + if err := ag_binary.NewBorshEncoder(buf).Encode(data); err != nil { + return fmt.Errorf("unable to encode instruction: %w", err) + } + return nil +} + +func decodeT(dst interface{}, data []byte) error { + return ag_binary.NewBorshDecoder(data).Decode(dst) +} diff --git a/core/capabilities/ccip/ccipsolana/ccip_router/types.go b/core/capabilities/ccip/ccipsolana/ccip_router/types.go new file mode 100644 index 00000000000..1c3167a1fcc --- /dev/null +++ b/core/capabilities/ccip/ccipsolana/ccip_router/types.go @@ -0,0 +1,1817 @@ +// Code generated by https://github.com/gagliardetto/anchor-go. DO NOT EDIT. + +package ccip_router + +import ( + ag_binary "github.com/gagliardetto/binary" + ag_solanago "github.com/gagliardetto/solana-go" +) + +type CommitInput struct { + PriceUpdates PriceUpdates + MerkleRoot MerkleRoot +} + +func (obj CommitInput) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { + // Serialize `PriceUpdates` param: + err = encoder.Encode(obj.PriceUpdates) + if err != nil { + return err + } + // Serialize `MerkleRoot` param: + err = encoder.Encode(obj.MerkleRoot) + if err != nil { + return err + } + return nil +} + +func (obj *CommitInput) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { + // Deserialize `PriceUpdates`: + err = decoder.Decode(&obj.PriceUpdates) + if err != nil { + return err + } + // Deserialize `MerkleRoot`: + err = decoder.Decode(&obj.MerkleRoot) + if err != nil { + return err + } + return nil +} + +type PriceUpdates struct { + TokenPriceUpdates []TokenPriceUpdate + GasPriceUpdates []GasPriceUpdate +} + +func (obj PriceUpdates) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { + // Serialize `TokenPriceUpdates` param: + err = encoder.Encode(obj.TokenPriceUpdates) + if err != nil { + return err + } + // Serialize `GasPriceUpdates` param: + err = encoder.Encode(obj.GasPriceUpdates) + if err != nil { + return err + } + return nil +} + +func (obj *PriceUpdates) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { + // Deserialize `TokenPriceUpdates`: + err = decoder.Decode(&obj.TokenPriceUpdates) + if err != nil { + return err + } + // Deserialize `GasPriceUpdates`: + err = decoder.Decode(&obj.GasPriceUpdates) + if err != nil { + return err + } + return nil +} + +type TokenPriceUpdate struct { + SourceToken ag_solanago.PublicKey + UsdPerToken [28]uint8 +} + +func (obj TokenPriceUpdate) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { + // Serialize `SourceToken` param: + err = encoder.Encode(obj.SourceToken) + if err != nil { + return err + } + // Serialize `UsdPerToken` param: + err = encoder.Encode(obj.UsdPerToken) + if err != nil { + return err + } + return nil +} + +func (obj *TokenPriceUpdate) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { + // Deserialize `SourceToken`: + err = decoder.Decode(&obj.SourceToken) + if err != nil { + return err + } + // Deserialize `UsdPerToken`: + err = decoder.Decode(&obj.UsdPerToken) + if err != nil { + return err + } + return nil +} + +type GasPriceUpdate struct { + DestChainSelector uint64 + UsdPerUnitGas [28]uint8 +} + +func (obj GasPriceUpdate) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { + // Serialize `DestChainSelector` param: + err = encoder.Encode(obj.DestChainSelector) + if err != nil { + return err + } + // Serialize `UsdPerUnitGas` param: + err = encoder.Encode(obj.UsdPerUnitGas) + if err != nil { + return err + } + return nil +} + +func (obj *GasPriceUpdate) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { + // Deserialize `DestChainSelector`: + err = decoder.Decode(&obj.DestChainSelector) + if err != nil { + return err + } + // Deserialize `UsdPerUnitGas`: + err = decoder.Decode(&obj.UsdPerUnitGas) + if err != nil { + return err + } + return nil +} + +type MerkleRoot struct { + SourceChainSelector uint64 + OnRampAddress []byte + MinSeqNr uint64 + MaxSeqNr uint64 + MerkleRoot [32]uint8 +} + +func (obj MerkleRoot) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { + // Serialize `SourceChainSelector` param: + err = encoder.Encode(obj.SourceChainSelector) + if err != nil { + return err + } + // Serialize `OnRampAddress` param: + err = encoder.Encode(obj.OnRampAddress) + if err != nil { + return err + } + // Serialize `MinSeqNr` param: + err = encoder.Encode(obj.MinSeqNr) + if err != nil { + return err + } + // Serialize `MaxSeqNr` param: + err = encoder.Encode(obj.MaxSeqNr) + if err != nil { + return err + } + // Serialize `MerkleRoot` param: + err = encoder.Encode(obj.MerkleRoot) + if err != nil { + return err + } + return nil +} + +func (obj *MerkleRoot) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { + // Deserialize `SourceChainSelector`: + err = decoder.Decode(&obj.SourceChainSelector) + if err != nil { + return err + } + // Deserialize `OnRampAddress`: + err = decoder.Decode(&obj.OnRampAddress) + if err != nil { + return err + } + // Deserialize `MinSeqNr`: + err = decoder.Decode(&obj.MinSeqNr) + if err != nil { + return err + } + // Deserialize `MaxSeqNr`: + err = decoder.Decode(&obj.MaxSeqNr) + if err != nil { + return err + } + // Deserialize `MerkleRoot`: + err = decoder.Decode(&obj.MerkleRoot) + if err != nil { + return err + } + return nil +} + +type Solana2AnyMessage struct { + Receiver []byte + Data []byte + TokenAmounts []SolanaTokenAmount + FeeToken ag_solanago.PublicKey + ExtraArgs ExtraArgsInput + TokenIndexes []byte +} + +func (obj Solana2AnyMessage) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { + // Serialize `Receiver` param: + err = encoder.Encode(obj.Receiver) + if err != nil { + return err + } + // Serialize `Data` param: + err = encoder.Encode(obj.Data) + if err != nil { + return err + } + // Serialize `TokenAmounts` param: + err = encoder.Encode(obj.TokenAmounts) + if err != nil { + return err + } + // Serialize `FeeToken` param: + err = encoder.Encode(obj.FeeToken) + if err != nil { + return err + } + // Serialize `ExtraArgs` param: + err = encoder.Encode(obj.ExtraArgs) + if err != nil { + return err + } + // Serialize `TokenIndexes` param: + err = encoder.Encode(obj.TokenIndexes) + if err != nil { + return err + } + return nil +} + +func (obj *Solana2AnyMessage) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { + // Deserialize `Receiver`: + err = decoder.Decode(&obj.Receiver) + if err != nil { + return err + } + // Deserialize `Data`: + err = decoder.Decode(&obj.Data) + if err != nil { + return err + } + // Deserialize `TokenAmounts`: + err = decoder.Decode(&obj.TokenAmounts) + if err != nil { + return err + } + // Deserialize `FeeToken`: + err = decoder.Decode(&obj.FeeToken) + if err != nil { + return err + } + // Deserialize `ExtraArgs`: + err = decoder.Decode(&obj.ExtraArgs) + if err != nil { + return err + } + // Deserialize `TokenIndexes`: + err = decoder.Decode(&obj.TokenIndexes) + if err != nil { + return err + } + return nil +} + +type SolanaTokenAmount struct { + Token ag_solanago.PublicKey + Amount uint64 +} + +func (obj SolanaTokenAmount) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { + // Serialize `Token` param: + err = encoder.Encode(obj.Token) + if err != nil { + return err + } + // Serialize `Amount` param: + err = encoder.Encode(obj.Amount) + if err != nil { + return err + } + return nil +} + +func (obj *SolanaTokenAmount) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { + // Deserialize `Token`: + err = decoder.Decode(&obj.Token) + if err != nil { + return err + } + // Deserialize `Amount`: + err = decoder.Decode(&obj.Amount) + if err != nil { + return err + } + return nil +} + +type ExtraArgsInput struct { + GasLimit *ag_binary.Uint128 `bin:"optional"` + AllowOutOfOrderExecution *bool `bin:"optional"` +} + +func (obj ExtraArgsInput) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { + // Serialize `GasLimit` param (optional): + { + if obj.GasLimit == nil { + err = encoder.WriteBool(false) + if err != nil { + return err + } + } else { + err = encoder.WriteBool(true) + if err != nil { + return err + } + err = encoder.Encode(obj.GasLimit) + if err != nil { + return err + } + } + } + // Serialize `AllowOutOfOrderExecution` param (optional): + { + if obj.AllowOutOfOrderExecution == nil { + err = encoder.WriteBool(false) + if err != nil { + return err + } + } else { + err = encoder.WriteBool(true) + if err != nil { + return err + } + err = encoder.Encode(obj.AllowOutOfOrderExecution) + if err != nil { + return err + } + } + } + return nil +} + +func (obj *ExtraArgsInput) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { + // Deserialize `GasLimit` (optional): + { + ok, err := decoder.ReadBool() + if err != nil { + return err + } + if ok { + err = decoder.Decode(&obj.GasLimit) + if err != nil { + return err + } + } + } + // Deserialize `AllowOutOfOrderExecution` (optional): + { + ok, err := decoder.ReadBool() + if err != nil { + return err + } + if ok { + err = decoder.Decode(&obj.AllowOutOfOrderExecution) + if err != nil { + return err + } + } + } + return nil +} + +type Any2SolanaMessage struct { + MessageId [32]uint8 + SourceChainSelector uint64 + Sender []byte + Data []byte + TokenAmounts []SolanaTokenAmount +} + +func (obj Any2SolanaMessage) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { + // Serialize `MessageId` param: + err = encoder.Encode(obj.MessageId) + if err != nil { + return err + } + // Serialize `SourceChainSelector` param: + err = encoder.Encode(obj.SourceChainSelector) + if err != nil { + return err + } + // Serialize `Sender` param: + err = encoder.Encode(obj.Sender) + if err != nil { + return err + } + // Serialize `Data` param: + err = encoder.Encode(obj.Data) + if err != nil { + return err + } + // Serialize `TokenAmounts` param: + err = encoder.Encode(obj.TokenAmounts) + if err != nil { + return err + } + return nil +} + +func (obj *Any2SolanaMessage) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { + // Deserialize `MessageId`: + err = decoder.Decode(&obj.MessageId) + if err != nil { + return err + } + // Deserialize `SourceChainSelector`: + err = decoder.Decode(&obj.SourceChainSelector) + if err != nil { + return err + } + // Deserialize `Sender`: + err = decoder.Decode(&obj.Sender) + if err != nil { + return err + } + // Deserialize `Data`: + err = decoder.Decode(&obj.Data) + if err != nil { + return err + } + // Deserialize `TokenAmounts`: + err = decoder.Decode(&obj.TokenAmounts) + if err != nil { + return err + } + return nil +} + +type RampMessageHeader struct { + MessageId [32]uint8 + SourceChainSelector uint64 + DestChainSelector uint64 + SequenceNumber uint64 + Nonce uint64 +} + +func (obj RampMessageHeader) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { + // Serialize `MessageId` param: + err = encoder.Encode(obj.MessageId) + if err != nil { + return err + } + // Serialize `SourceChainSelector` param: + err = encoder.Encode(obj.SourceChainSelector) + if err != nil { + return err + } + // Serialize `DestChainSelector` param: + err = encoder.Encode(obj.DestChainSelector) + if err != nil { + return err + } + // Serialize `SequenceNumber` param: + err = encoder.Encode(obj.SequenceNumber) + if err != nil { + return err + } + // Serialize `Nonce` param: + err = encoder.Encode(obj.Nonce) + if err != nil { + return err + } + return nil +} + +func (obj *RampMessageHeader) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { + // Deserialize `MessageId`: + err = decoder.Decode(&obj.MessageId) + if err != nil { + return err + } + // Deserialize `SourceChainSelector`: + err = decoder.Decode(&obj.SourceChainSelector) + if err != nil { + return err + } + // Deserialize `DestChainSelector`: + err = decoder.Decode(&obj.DestChainSelector) + if err != nil { + return err + } + // Deserialize `SequenceNumber`: + err = decoder.Decode(&obj.SequenceNumber) + if err != nil { + return err + } + // Deserialize `Nonce`: + err = decoder.Decode(&obj.Nonce) + if err != nil { + return err + } + return nil +} + +type ExecutionReportSingleChain struct { + SourceChainSelector uint64 + Message Any2SolanaRampMessage + OffchainTokenData [][]byte + Root [32]uint8 + Proofs [][32]uint8 + TokenIndexes []byte +} + +func (obj ExecutionReportSingleChain) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { + // Serialize `SourceChainSelector` param: + err = encoder.Encode(obj.SourceChainSelector) + if err != nil { + return err + } + // Serialize `Message` param: + err = encoder.Encode(obj.Message) + if err != nil { + return err + } + // Serialize `OffchainTokenData` param: + err = encoder.Encode(obj.OffchainTokenData) + if err != nil { + return err + } + // Serialize `Root` param: + err = encoder.Encode(obj.Root) + if err != nil { + return err + } + // Serialize `Proofs` param: + err = encoder.Encode(obj.Proofs) + if err != nil { + return err + } + // Serialize `TokenIndexes` param: + err = encoder.Encode(obj.TokenIndexes) + if err != nil { + return err + } + return nil +} + +func (obj *ExecutionReportSingleChain) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { + // Deserialize `SourceChainSelector`: + err = decoder.Decode(&obj.SourceChainSelector) + if err != nil { + return err + } + // Deserialize `Message`: + err = decoder.Decode(&obj.Message) + if err != nil { + return err + } + // Deserialize `OffchainTokenData`: + err = decoder.Decode(&obj.OffchainTokenData) + if err != nil { + return err + } + // Deserialize `Root`: + err = decoder.Decode(&obj.Root) + if err != nil { + return err + } + // Deserialize `Proofs`: + err = decoder.Decode(&obj.Proofs) + if err != nil { + return err + } + // Deserialize `TokenIndexes`: + err = decoder.Decode(&obj.TokenIndexes) + if err != nil { + return err + } + return nil +} + +type SolanaExtraArgs struct { + ComputeUnits uint32 + AllowOutOfOrderExecution bool +} + +func (obj SolanaExtraArgs) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { + // Serialize `ComputeUnits` param: + err = encoder.Encode(obj.ComputeUnits) + if err != nil { + return err + } + // Serialize `AllowOutOfOrderExecution` param: + err = encoder.Encode(obj.AllowOutOfOrderExecution) + if err != nil { + return err + } + return nil +} + +func (obj *SolanaExtraArgs) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { + // Deserialize `ComputeUnits`: + err = decoder.Decode(&obj.ComputeUnits) + if err != nil { + return err + } + // Deserialize `AllowOutOfOrderExecution`: + err = decoder.Decode(&obj.AllowOutOfOrderExecution) + if err != nil { + return err + } + return nil +} + +type EvmExtraArgs struct { + GasLimit ag_binary.Uint128 + AllowOutOfOrderExecution bool +} + +func (obj EvmExtraArgs) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { + // Serialize `GasLimit` param: + err = encoder.Encode(obj.GasLimit) + if err != nil { + return err + } + // Serialize `AllowOutOfOrderExecution` param: + err = encoder.Encode(obj.AllowOutOfOrderExecution) + if err != nil { + return err + } + return nil +} + +func (obj *EvmExtraArgs) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { + // Deserialize `GasLimit`: + err = decoder.Decode(&obj.GasLimit) + if err != nil { + return err + } + // Deserialize `AllowOutOfOrderExecution`: + err = decoder.Decode(&obj.AllowOutOfOrderExecution) + if err != nil { + return err + } + return nil +} + +type Any2SolanaRampMessage struct { + Header RampMessageHeader + Sender []byte + Data []byte + Receiver ag_solanago.PublicKey + TokenAmounts []Any2SolanaTokenTransfer + ExtraArgs SolanaExtraArgs +} + +func (obj Any2SolanaRampMessage) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { + // Serialize `Header` param: + err = encoder.Encode(obj.Header) + if err != nil { + return err + } + // Serialize `Sender` param: + err = encoder.Encode(obj.Sender) + if err != nil { + return err + } + // Serialize `Data` param: + err = encoder.Encode(obj.Data) + if err != nil { + return err + } + // Serialize `Receiver` param: + err = encoder.Encode(obj.Receiver) + if err != nil { + return err + } + // Serialize `TokenAmounts` param: + err = encoder.Encode(obj.TokenAmounts) + if err != nil { + return err + } + // Serialize `ExtraArgs` param: + err = encoder.Encode(obj.ExtraArgs) + if err != nil { + return err + } + return nil +} + +func (obj *Any2SolanaRampMessage) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { + // Deserialize `Header`: + err = decoder.Decode(&obj.Header) + if err != nil { + return err + } + // Deserialize `Sender`: + err = decoder.Decode(&obj.Sender) + if err != nil { + return err + } + // Deserialize `Data`: + err = decoder.Decode(&obj.Data) + if err != nil { + return err + } + // Deserialize `Receiver`: + err = decoder.Decode(&obj.Receiver) + if err != nil { + return err + } + // Deserialize `TokenAmounts`: + err = decoder.Decode(&obj.TokenAmounts) + if err != nil { + return err + } + // Deserialize `ExtraArgs`: + err = decoder.Decode(&obj.ExtraArgs) + if err != nil { + return err + } + return nil +} + +type Solana2AnyRampMessage struct { + Header RampMessageHeader + Sender ag_solanago.PublicKey + Data []byte + Receiver []byte + ExtraArgs EvmExtraArgs + FeeToken ag_solanago.PublicKey + TokenAmounts []Solana2AnyTokenTransfer +} + +func (obj Solana2AnyRampMessage) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { + // Serialize `Header` param: + err = encoder.Encode(obj.Header) + if err != nil { + return err + } + // Serialize `Sender` param: + err = encoder.Encode(obj.Sender) + if err != nil { + return err + } + // Serialize `Data` param: + err = encoder.Encode(obj.Data) + if err != nil { + return err + } + // Serialize `Receiver` param: + err = encoder.Encode(obj.Receiver) + if err != nil { + return err + } + // Serialize `ExtraArgs` param: + err = encoder.Encode(obj.ExtraArgs) + if err != nil { + return err + } + // Serialize `FeeToken` param: + err = encoder.Encode(obj.FeeToken) + if err != nil { + return err + } + // Serialize `TokenAmounts` param: + err = encoder.Encode(obj.TokenAmounts) + if err != nil { + return err + } + return nil +} + +func (obj *Solana2AnyRampMessage) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { + // Deserialize `Header`: + err = decoder.Decode(&obj.Header) + if err != nil { + return err + } + // Deserialize `Sender`: + err = decoder.Decode(&obj.Sender) + if err != nil { + return err + } + // Deserialize `Data`: + err = decoder.Decode(&obj.Data) + if err != nil { + return err + } + // Deserialize `Receiver`: + err = decoder.Decode(&obj.Receiver) + if err != nil { + return err + } + // Deserialize `ExtraArgs`: + err = decoder.Decode(&obj.ExtraArgs) + if err != nil { + return err + } + // Deserialize `FeeToken`: + err = decoder.Decode(&obj.FeeToken) + if err != nil { + return err + } + // Deserialize `TokenAmounts`: + err = decoder.Decode(&obj.TokenAmounts) + if err != nil { + return err + } + return nil +} + +type Solana2AnyTokenTransfer struct { + SourcePoolAddress ag_solanago.PublicKey + DestTokenAddress []byte + ExtraData []byte + Amount uint64 + DestExecData []byte +} + +func (obj Solana2AnyTokenTransfer) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { + // Serialize `SourcePoolAddress` param: + err = encoder.Encode(obj.SourcePoolAddress) + if err != nil { + return err + } + // Serialize `DestTokenAddress` param: + err = encoder.Encode(obj.DestTokenAddress) + if err != nil { + return err + } + // Serialize `ExtraData` param: + err = encoder.Encode(obj.ExtraData) + if err != nil { + return err + } + // Serialize `Amount` param: + err = encoder.Encode(obj.Amount) + if err != nil { + return err + } + // Serialize `DestExecData` param: + err = encoder.Encode(obj.DestExecData) + if err != nil { + return err + } + return nil +} + +func (obj *Solana2AnyTokenTransfer) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { + // Deserialize `SourcePoolAddress`: + err = decoder.Decode(&obj.SourcePoolAddress) + if err != nil { + return err + } + // Deserialize `DestTokenAddress`: + err = decoder.Decode(&obj.DestTokenAddress) + if err != nil { + return err + } + // Deserialize `ExtraData`: + err = decoder.Decode(&obj.ExtraData) + if err != nil { + return err + } + // Deserialize `Amount`: + err = decoder.Decode(&obj.Amount) + if err != nil { + return err + } + // Deserialize `DestExecData`: + err = decoder.Decode(&obj.DestExecData) + if err != nil { + return err + } + return nil +} + +type Any2SolanaTokenTransfer struct { + SourcePoolAddress []byte + DestTokenAddress ag_solanago.PublicKey + DestGasAmount uint32 + ExtraData []byte + Amount uint64 +} + +func (obj Any2SolanaTokenTransfer) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { + // Serialize `SourcePoolAddress` param: + err = encoder.Encode(obj.SourcePoolAddress) + if err != nil { + return err + } + // Serialize `DestTokenAddress` param: + err = encoder.Encode(obj.DestTokenAddress) + if err != nil { + return err + } + // Serialize `DestGasAmount` param: + err = encoder.Encode(obj.DestGasAmount) + if err != nil { + return err + } + // Serialize `ExtraData` param: + err = encoder.Encode(obj.ExtraData) + if err != nil { + return err + } + // Serialize `Amount` param: + err = encoder.Encode(obj.Amount) + if err != nil { + return err + } + return nil +} + +func (obj *Any2SolanaTokenTransfer) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { + // Deserialize `SourcePoolAddress`: + err = decoder.Decode(&obj.SourcePoolAddress) + if err != nil { + return err + } + // Deserialize `DestTokenAddress`: + err = decoder.Decode(&obj.DestTokenAddress) + if err != nil { + return err + } + // Deserialize `DestGasAmount`: + err = decoder.Decode(&obj.DestGasAmount) + if err != nil { + return err + } + // Deserialize `ExtraData`: + err = decoder.Decode(&obj.ExtraData) + if err != nil { + return err + } + // Deserialize `Amount`: + err = decoder.Decode(&obj.Amount) + if err != nil { + return err + } + return nil +} + +type LockOrBurnInV1 struct { + Receiver []byte + RemoteChainSelector uint64 + OriginalSender ag_solanago.PublicKey + Amount uint64 + LocalToken ag_solanago.PublicKey +} + +func (obj LockOrBurnInV1) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { + // Serialize `Receiver` param: + err = encoder.Encode(obj.Receiver) + if err != nil { + return err + } + // Serialize `RemoteChainSelector` param: + err = encoder.Encode(obj.RemoteChainSelector) + if err != nil { + return err + } + // Serialize `OriginalSender` param: + err = encoder.Encode(obj.OriginalSender) + if err != nil { + return err + } + // Serialize `Amount` param: + err = encoder.Encode(obj.Amount) + if err != nil { + return err + } + // Serialize `LocalToken` param: + err = encoder.Encode(obj.LocalToken) + if err != nil { + return err + } + return nil +} + +func (obj *LockOrBurnInV1) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { + // Deserialize `Receiver`: + err = decoder.Decode(&obj.Receiver) + if err != nil { + return err + } + // Deserialize `RemoteChainSelector`: + err = decoder.Decode(&obj.RemoteChainSelector) + if err != nil { + return err + } + // Deserialize `OriginalSender`: + err = decoder.Decode(&obj.OriginalSender) + if err != nil { + return err + } + // Deserialize `Amount`: + err = decoder.Decode(&obj.Amount) + if err != nil { + return err + } + // Deserialize `LocalToken`: + err = decoder.Decode(&obj.LocalToken) + if err != nil { + return err + } + return nil +} + +type ReleaseOrMintInV1 struct { + OriginalSender []byte + RemoteChainSelector uint64 + Receiver ag_solanago.PublicKey + Amount uint64 + LocalToken ag_solanago.PublicKey + + // @dev WARNING: sourcePoolAddress should be checked prior to any processing of funds. Make sure it matches the + // expected pool address for the given remoteChainSelector. + SourcePoolAddress []byte + SourcePoolData []byte + + // @dev WARNING: offchainTokenData is untrusted data. + OffchainTokenData []byte +} + +func (obj ReleaseOrMintInV1) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { + // Serialize `OriginalSender` param: + err = encoder.Encode(obj.OriginalSender) + if err != nil { + return err + } + // Serialize `RemoteChainSelector` param: + err = encoder.Encode(obj.RemoteChainSelector) + if err != nil { + return err + } + // Serialize `Receiver` param: + err = encoder.Encode(obj.Receiver) + if err != nil { + return err + } + // Serialize `Amount` param: + err = encoder.Encode(obj.Amount) + if err != nil { + return err + } + // Serialize `LocalToken` param: + err = encoder.Encode(obj.LocalToken) + if err != nil { + return err + } + // Serialize `SourcePoolAddress` param: + err = encoder.Encode(obj.SourcePoolAddress) + if err != nil { + return err + } + // Serialize `SourcePoolData` param: + err = encoder.Encode(obj.SourcePoolData) + if err != nil { + return err + } + // Serialize `OffchainTokenData` param: + err = encoder.Encode(obj.OffchainTokenData) + if err != nil { + return err + } + return nil +} + +func (obj *ReleaseOrMintInV1) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { + // Deserialize `OriginalSender`: + err = decoder.Decode(&obj.OriginalSender) + if err != nil { + return err + } + // Deserialize `RemoteChainSelector`: + err = decoder.Decode(&obj.RemoteChainSelector) + if err != nil { + return err + } + // Deserialize `Receiver`: + err = decoder.Decode(&obj.Receiver) + if err != nil { + return err + } + // Deserialize `Amount`: + err = decoder.Decode(&obj.Amount) + if err != nil { + return err + } + // Deserialize `LocalToken`: + err = decoder.Decode(&obj.LocalToken) + if err != nil { + return err + } + // Deserialize `SourcePoolAddress`: + err = decoder.Decode(&obj.SourcePoolAddress) + if err != nil { + return err + } + // Deserialize `SourcePoolData`: + err = decoder.Decode(&obj.SourcePoolData) + if err != nil { + return err + } + // Deserialize `OffchainTokenData`: + err = decoder.Decode(&obj.OffchainTokenData) + if err != nil { + return err + } + return nil +} + +type LockOrBurnOutV1 struct { + DestTokenAddress []byte + DestPoolData []byte +} + +func (obj LockOrBurnOutV1) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { + // Serialize `DestTokenAddress` param: + err = encoder.Encode(obj.DestTokenAddress) + if err != nil { + return err + } + // Serialize `DestPoolData` param: + err = encoder.Encode(obj.DestPoolData) + if err != nil { + return err + } + return nil +} + +func (obj *LockOrBurnOutV1) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { + // Deserialize `DestTokenAddress`: + err = decoder.Decode(&obj.DestTokenAddress) + if err != nil { + return err + } + // Deserialize `DestPoolData`: + err = decoder.Decode(&obj.DestPoolData) + if err != nil { + return err + } + return nil +} + +type ReleaseOrMintOutV1 struct { + DestinationAmount uint64 +} + +func (obj ReleaseOrMintOutV1) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { + // Serialize `DestinationAmount` param: + err = encoder.Encode(obj.DestinationAmount) + if err != nil { + return err + } + return nil +} + +func (obj *ReleaseOrMintOutV1) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { + // Deserialize `DestinationAmount`: + err = decoder.Decode(&obj.DestinationAmount) + if err != nil { + return err + } + return nil +} + +type Ocr3Config struct { + PluginType uint8 + ConfigInfo Ocr3ConfigInfo + Signers [16][20]uint8 + Transmitters [16][32]uint8 +} + +func (obj Ocr3Config) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { + // Serialize `PluginType` param: + err = encoder.Encode(obj.PluginType) + if err != nil { + return err + } + // Serialize `ConfigInfo` param: + err = encoder.Encode(obj.ConfigInfo) + if err != nil { + return err + } + // Serialize `Signers` param: + err = encoder.Encode(obj.Signers) + if err != nil { + return err + } + // Serialize `Transmitters` param: + err = encoder.Encode(obj.Transmitters) + if err != nil { + return err + } + return nil +} + +func (obj *Ocr3Config) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { + // Deserialize `PluginType`: + err = decoder.Decode(&obj.PluginType) + if err != nil { + return err + } + // Deserialize `ConfigInfo`: + err = decoder.Decode(&obj.ConfigInfo) + if err != nil { + return err + } + // Deserialize `Signers`: + err = decoder.Decode(&obj.Signers) + if err != nil { + return err + } + // Deserialize `Transmitters`: + err = decoder.Decode(&obj.Transmitters) + if err != nil { + return err + } + return nil +} + +type Ocr3ConfigInfo struct { + ConfigDigest [32]uint8 + F uint8 + N uint8 + IsSignatureVerificationEnabled uint8 +} + +func (obj Ocr3ConfigInfo) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { + // Serialize `ConfigDigest` param: + err = encoder.Encode(obj.ConfigDigest) + if err != nil { + return err + } + // Serialize `F` param: + err = encoder.Encode(obj.F) + if err != nil { + return err + } + // Serialize `N` param: + err = encoder.Encode(obj.N) + if err != nil { + return err + } + // Serialize `IsSignatureVerificationEnabled` param: + err = encoder.Encode(obj.IsSignatureVerificationEnabled) + if err != nil { + return err + } + return nil +} + +func (obj *Ocr3ConfigInfo) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { + // Deserialize `ConfigDigest`: + err = decoder.Decode(&obj.ConfigDigest) + if err != nil { + return err + } + // Deserialize `F`: + err = decoder.Decode(&obj.F) + if err != nil { + return err + } + // Deserialize `N`: + err = decoder.Decode(&obj.N) + if err != nil { + return err + } + // Deserialize `IsSignatureVerificationEnabled`: + err = decoder.Decode(&obj.IsSignatureVerificationEnabled) + if err != nil { + return err + } + return nil +} + +type SourceChainConfig struct { + IsEnabled bool + MinSeqNr uint64 + OnRamp []byte +} + +func (obj SourceChainConfig) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { + // Serialize `IsEnabled` param: + err = encoder.Encode(obj.IsEnabled) + if err != nil { + return err + } + // Serialize `MinSeqNr` param: + err = encoder.Encode(obj.MinSeqNr) + if err != nil { + return err + } + // Serialize `OnRamp` param: + err = encoder.Encode(obj.OnRamp) + if err != nil { + return err + } + return nil +} + +func (obj *SourceChainConfig) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { + // Deserialize `IsEnabled`: + err = decoder.Decode(&obj.IsEnabled) + if err != nil { + return err + } + // Deserialize `MinSeqNr`: + err = decoder.Decode(&obj.MinSeqNr) + if err != nil { + return err + } + // Deserialize `OnRamp`: + err = decoder.Decode(&obj.OnRamp) + if err != nil { + return err + } + return nil +} + +type DestChainConfig struct { + SequenceNumber uint64 + UsdPerUnitGas TimestampedPackedU224 + BillingConfig ChainBillingConfig +} + +func (obj DestChainConfig) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { + // Serialize `SequenceNumber` param: + err = encoder.Encode(obj.SequenceNumber) + if err != nil { + return err + } + // Serialize `UsdPerUnitGas` param: + err = encoder.Encode(obj.UsdPerUnitGas) + if err != nil { + return err + } + // Serialize `BillingConfig` param: + err = encoder.Encode(obj.BillingConfig) + if err != nil { + return err + } + return nil +} + +func (obj *DestChainConfig) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { + // Deserialize `SequenceNumber`: + err = decoder.Decode(&obj.SequenceNumber) + if err != nil { + return err + } + // Deserialize `UsdPerUnitGas`: + err = decoder.Decode(&obj.UsdPerUnitGas) + if err != nil { + return err + } + // Deserialize `BillingConfig`: + err = decoder.Decode(&obj.BillingConfig) + if err != nil { + return err + } + return nil +} + +type ChainBillingConfig struct { + IsEnabled bool + MaxNumberOfTokensPerMsg uint16 + MaxDataBytes uint32 + MaxPerMsgGasLimit uint32 + DestGasOverhead uint32 + DestGasPerPayloadByte uint16 + DestDataAvailabilityOverheadGas uint32 + DestGasPerDataAvailabilityByte uint16 + DestDataAvailabilityMultiplierBps uint16 + DefaultTokenFeeUsdcents uint16 + DefaultTokenDestGasOverhead uint32 + DefaultTxGasLimit uint32 + GasMultiplierWeiPerEth uint64 + NetworkFeeUsdcents uint32 + GasPriceStalenessThreshold uint32 + EnforceOutOfOrder bool + ChainFamilySelector [4]uint8 +} + +func (obj ChainBillingConfig) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { + // Serialize `IsEnabled` param: + err = encoder.Encode(obj.IsEnabled) + if err != nil { + return err + } + // Serialize `MaxNumberOfTokensPerMsg` param: + err = encoder.Encode(obj.MaxNumberOfTokensPerMsg) + if err != nil { + return err + } + // Serialize `MaxDataBytes` param: + err = encoder.Encode(obj.MaxDataBytes) + if err != nil { + return err + } + // Serialize `MaxPerMsgGasLimit` param: + err = encoder.Encode(obj.MaxPerMsgGasLimit) + if err != nil { + return err + } + // Serialize `DestGasOverhead` param: + err = encoder.Encode(obj.DestGasOverhead) + if err != nil { + return err + } + // Serialize `DestGasPerPayloadByte` param: + err = encoder.Encode(obj.DestGasPerPayloadByte) + if err != nil { + return err + } + // Serialize `DestDataAvailabilityOverheadGas` param: + err = encoder.Encode(obj.DestDataAvailabilityOverheadGas) + if err != nil { + return err + } + // Serialize `DestGasPerDataAvailabilityByte` param: + err = encoder.Encode(obj.DestGasPerDataAvailabilityByte) + if err != nil { + return err + } + // Serialize `DestDataAvailabilityMultiplierBps` param: + err = encoder.Encode(obj.DestDataAvailabilityMultiplierBps) + if err != nil { + return err + } + // Serialize `DefaultTokenFeeUsdcents` param: + err = encoder.Encode(obj.DefaultTokenFeeUsdcents) + if err != nil { + return err + } + // Serialize `DefaultTokenDestGasOverhead` param: + err = encoder.Encode(obj.DefaultTokenDestGasOverhead) + if err != nil { + return err + } + // Serialize `DefaultTxGasLimit` param: + err = encoder.Encode(obj.DefaultTxGasLimit) + if err != nil { + return err + } + // Serialize `GasMultiplierWeiPerEth` param: + err = encoder.Encode(obj.GasMultiplierWeiPerEth) + if err != nil { + return err + } + // Serialize `NetworkFeeUsdcents` param: + err = encoder.Encode(obj.NetworkFeeUsdcents) + if err != nil { + return err + } + // Serialize `GasPriceStalenessThreshold` param: + err = encoder.Encode(obj.GasPriceStalenessThreshold) + if err != nil { + return err + } + // Serialize `EnforceOutOfOrder` param: + err = encoder.Encode(obj.EnforceOutOfOrder) + if err != nil { + return err + } + // Serialize `ChainFamilySelector` param: + err = encoder.Encode(obj.ChainFamilySelector) + if err != nil { + return err + } + return nil +} + +func (obj *ChainBillingConfig) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { + // Deserialize `IsEnabled`: + err = decoder.Decode(&obj.IsEnabled) + if err != nil { + return err + } + // Deserialize `MaxNumberOfTokensPerMsg`: + err = decoder.Decode(&obj.MaxNumberOfTokensPerMsg) + if err != nil { + return err + } + // Deserialize `MaxDataBytes`: + err = decoder.Decode(&obj.MaxDataBytes) + if err != nil { + return err + } + // Deserialize `MaxPerMsgGasLimit`: + err = decoder.Decode(&obj.MaxPerMsgGasLimit) + if err != nil { + return err + } + // Deserialize `DestGasOverhead`: + err = decoder.Decode(&obj.DestGasOverhead) + if err != nil { + return err + } + // Deserialize `DestGasPerPayloadByte`: + err = decoder.Decode(&obj.DestGasPerPayloadByte) + if err != nil { + return err + } + // Deserialize `DestDataAvailabilityOverheadGas`: + err = decoder.Decode(&obj.DestDataAvailabilityOverheadGas) + if err != nil { + return err + } + // Deserialize `DestGasPerDataAvailabilityByte`: + err = decoder.Decode(&obj.DestGasPerDataAvailabilityByte) + if err != nil { + return err + } + // Deserialize `DestDataAvailabilityMultiplierBps`: + err = decoder.Decode(&obj.DestDataAvailabilityMultiplierBps) + if err != nil { + return err + } + // Deserialize `DefaultTokenFeeUsdcents`: + err = decoder.Decode(&obj.DefaultTokenFeeUsdcents) + if err != nil { + return err + } + // Deserialize `DefaultTokenDestGasOverhead`: + err = decoder.Decode(&obj.DefaultTokenDestGasOverhead) + if err != nil { + return err + } + // Deserialize `DefaultTxGasLimit`: + err = decoder.Decode(&obj.DefaultTxGasLimit) + if err != nil { + return err + } + // Deserialize `GasMultiplierWeiPerEth`: + err = decoder.Decode(&obj.GasMultiplierWeiPerEth) + if err != nil { + return err + } + // Deserialize `NetworkFeeUsdcents`: + err = decoder.Decode(&obj.NetworkFeeUsdcents) + if err != nil { + return err + } + // Deserialize `GasPriceStalenessThreshold`: + err = decoder.Decode(&obj.GasPriceStalenessThreshold) + if err != nil { + return err + } + // Deserialize `EnforceOutOfOrder`: + err = decoder.Decode(&obj.EnforceOutOfOrder) + if err != nil { + return err + } + // Deserialize `ChainFamilySelector`: + err = decoder.Decode(&obj.ChainFamilySelector) + if err != nil { + return err + } + return nil +} + +type TokenBilling struct { + MinFeeUsdcents uint32 + MaxFeeUsdcents uint32 + DeciBps uint16 + DestGasOverhead uint32 + DestBytesOverhead uint32 + IsEnabled bool +} + +func (obj TokenBilling) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { + // Serialize `MinFeeUsdcents` param: + err = encoder.Encode(obj.MinFeeUsdcents) + if err != nil { + return err + } + // Serialize `MaxFeeUsdcents` param: + err = encoder.Encode(obj.MaxFeeUsdcents) + if err != nil { + return err + } + // Serialize `DeciBps` param: + err = encoder.Encode(obj.DeciBps) + if err != nil { + return err + } + // Serialize `DestGasOverhead` param: + err = encoder.Encode(obj.DestGasOverhead) + if err != nil { + return err + } + // Serialize `DestBytesOverhead` param: + err = encoder.Encode(obj.DestBytesOverhead) + if err != nil { + return err + } + // Serialize `IsEnabled` param: + err = encoder.Encode(obj.IsEnabled) + if err != nil { + return err + } + return nil +} + +func (obj *TokenBilling) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { + // Deserialize `MinFeeUsdcents`: + err = decoder.Decode(&obj.MinFeeUsdcents) + if err != nil { + return err + } + // Deserialize `MaxFeeUsdcents`: + err = decoder.Decode(&obj.MaxFeeUsdcents) + if err != nil { + return err + } + // Deserialize `DeciBps`: + err = decoder.Decode(&obj.DeciBps) + if err != nil { + return err + } + // Deserialize `DestGasOverhead`: + err = decoder.Decode(&obj.DestGasOverhead) + if err != nil { + return err + } + // Deserialize `DestBytesOverhead`: + err = decoder.Decode(&obj.DestBytesOverhead) + if err != nil { + return err + } + // Deserialize `IsEnabled`: + err = decoder.Decode(&obj.IsEnabled) + if err != nil { + return err + } + return nil +} + +type TimestampedPackedU224 struct { + Value [28]uint8 + Timestamp uint32 +} + +func (obj TimestampedPackedU224) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { + // Serialize `Value` param: + err = encoder.Encode(obj.Value) + if err != nil { + return err + } + // Serialize `Timestamp` param: + err = encoder.Encode(obj.Timestamp) + if err != nil { + return err + } + return nil +} + +func (obj *TimestampedPackedU224) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { + // Deserialize `Value`: + err = decoder.Decode(&obj.Value) + if err != nil { + return err + } + // Deserialize `Timestamp`: + err = decoder.Decode(&obj.Timestamp) + if err != nil { + return err + } + return nil +} + +type OcrPluginType ag_binary.BorshEnum + +const ( + Commit_OcrPluginType OcrPluginType = iota + Execution_OcrPluginType +) + +func (value OcrPluginType) String() string { + switch value { + case Commit_OcrPluginType: + return "Commit" + case Execution_OcrPluginType: + return "Execution" + default: + return "" + } +} + +type MerkleError ag_binary.BorshEnum + +const ( + InvalidProof_MerkleError MerkleError = iota +) + +func (value MerkleError) String() string { + switch value { + case InvalidProof_MerkleError: + return "InvalidProof" + default: + return "" + } +} + +type MessageExecutionState ag_binary.BorshEnum + +const ( + Untouched_MessageExecutionState MessageExecutionState = iota + InProgress_MessageExecutionState + Success_MessageExecutionState + Failure_MessageExecutionState +) + +func (value MessageExecutionState) String() string { + switch value { + case Untouched_MessageExecutionState: + return "Untouched" + case InProgress_MessageExecutionState: + return "InProgress" + case Success_MessageExecutionState: + return "Success" + case Failure_MessageExecutionState: + return "Failure" + default: + return "" + } +} + +type CcipRouterError ag_binary.BorshEnum + +const ( + InvalidSequenceInterval_CcipRouterError CcipRouterError = iota + RootNotCommitted_CcipRouterError + ExistingMerkleRoot_CcipRouterError + Unauthorized_CcipRouterError + InvalidInputs_CcipRouterError + UnsupportedSourceChainSelector_CcipRouterError + UnsupportedDestinationChainSelector_CcipRouterError + InvalidProof_CcipRouterError + InvalidMessage_CcipRouterError + ReachedMaxSequenceNumber_CcipRouterError + ManualExecutionNotAllowed_CcipRouterError + InvalidInputsTokenIndices_CcipRouterError + InvalidInputsPoolAccounts_CcipRouterError + InvalidInputsTokenAccounts_CcipRouterError + InvalidInputsConfigAccounts_CcipRouterError + InvalidInputsTokenAmount_CcipRouterError + OfframpReleaseMintBalanceMismatch_CcipRouterError + OfframpInvalidDataLength_CcipRouterError +) + +func (value CcipRouterError) String() string { + switch value { + case InvalidSequenceInterval_CcipRouterError: + return "InvalidSequenceInterval" + case RootNotCommitted_CcipRouterError: + return "RootNotCommitted" + case ExistingMerkleRoot_CcipRouterError: + return "ExistingMerkleRoot" + case Unauthorized_CcipRouterError: + return "Unauthorized" + case InvalidInputs_CcipRouterError: + return "InvalidInputs" + case UnsupportedSourceChainSelector_CcipRouterError: + return "UnsupportedSourceChainSelector" + case UnsupportedDestinationChainSelector_CcipRouterError: + return "UnsupportedDestinationChainSelector" + case InvalidProof_CcipRouterError: + return "InvalidProof" + case InvalidMessage_CcipRouterError: + return "InvalidMessage" + case ReachedMaxSequenceNumber_CcipRouterError: + return "ReachedMaxSequenceNumber" + case ManualExecutionNotAllowed_CcipRouterError: + return "ManualExecutionNotAllowed" + case InvalidInputsTokenIndices_CcipRouterError: + return "InvalidInputsTokenIndices" + case InvalidInputsPoolAccounts_CcipRouterError: + return "InvalidInputsPoolAccounts" + case InvalidInputsTokenAccounts_CcipRouterError: + return "InvalidInputsTokenAccounts" + case InvalidInputsConfigAccounts_CcipRouterError: + return "InvalidInputsConfigAccounts" + case InvalidInputsTokenAmount_CcipRouterError: + return "InvalidInputsTokenAmount" + case OfframpReleaseMintBalanceMismatch_CcipRouterError: + return "OfframpReleaseMintBalanceMismatch" + case OfframpInvalidDataLength_CcipRouterError: + return "OfframpInvalidDataLength" + default: + return "" + } +} diff --git a/core/capabilities/ccip/ccipsolana/commitcodec.go b/core/capabilities/ccip/ccipsolana/commitcodec.go new file mode 100644 index 00000000000..711bb66068a --- /dev/null +++ b/core/capabilities/ccip/ccipsolana/commitcodec.go @@ -0,0 +1,144 @@ +package ccipsolana + +import ( + "bytes" + "context" + "errors" + "fmt" + + "github.com/gagliardetto/solana-go" + "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/ccipsolana/ccip_router" + + cciptypes "github.com/smartcontractkit/chainlink-ccip/pkg/types/ccipocr3" + + agbinary "github.com/gagliardetto/binary" +) + +// CommitPluginCodecV1 is a codec for encoding and decoding commit plugin reports. +// Compatible with: +// - "OffRamp 1.6.0-dev" +type CommitPluginCodecV1 struct{} + +func NewCommitPluginCodecV1() *CommitPluginCodecV1 { + return &CommitPluginCodecV1{} +} + +func (c *CommitPluginCodecV1) Encode(ctx context.Context, report cciptypes.CommitPluginReport) ([]byte, error) { + var buf bytes.Buffer + encoder := agbinary.NewBorshEncoder(&buf) + + mr := ccip_router.MerkleRoot{ + SourceChainSelector: uint64(report.MerkleRoots[0].ChainSel), + OnRampAddress: report.MerkleRoots[0].OnRampAddress, + MinSeqNr: uint64(report.MerkleRoots[0].SeqNumsRange.Start()), + MaxSeqNr: uint64(report.MerkleRoots[0].SeqNumsRange.End()), + MerkleRoot: report.MerkleRoots[0].MerkleRoot, + } + + tpu := make([]ccip_router.TokenPriceUpdate, 0, len(report.PriceUpdates.TokenPriceUpdates)) + for _, update := range report.PriceUpdates.TokenPriceUpdates { + b, err := update.Price.MarshalJSON() + if err != nil { + return nil, fmt.Errorf("error marshaling token price: %v", err) + } + + if len(b) > 28 { + return nil, errors.New("token price is too large") + } + + tpu = append(tpu, ccip_router.TokenPriceUpdate{ + SourceToken: solana.MPK(string(update.TokenID)), + UsdPerToken: [28]uint8(b), + }) + } + + gpu := make([]ccip_router.GasPriceUpdate, 0, len(report.PriceUpdates.GasPriceUpdates)) + for _, update := range report.PriceUpdates.GasPriceUpdates { + b, err := update.GasPrice.MarshalJSON() + if err != nil { + return nil, fmt.Errorf("error marshaling gas price update: %w", err) + } + + if len(b) > 28 { + return nil, errors.New("error marshaling gas price update: gas price is too large") + } + + gpu = append(gpu, ccip_router.GasPriceUpdate{ + DestChainSelector: uint64(update.ChainSel), + UsdPerUnitGas: [28]uint8(b), + }) + } + + commit := ccip_router.CommitInput{ + MerkleRoot: mr, + PriceUpdates: ccip_router.PriceUpdates{ + TokenPriceUpdates: tpu, + GasPriceUpdates: gpu, + }, + } + + err := commit.MarshalWithEncoder(encoder) + if err != nil { + return nil, err + } + + return buf.Bytes(), nil +} + +func (c *CommitPluginCodecV1) Decode(ctx context.Context, bytes []byte) (cciptypes.CommitPluginReport, error) { + decoder := agbinary.NewBorshDecoder(bytes) + commitReport := ccip_router.CommitInput{} + err := commitReport.UnmarshalWithDecoder(decoder) + if err != nil { + return cciptypes.CommitPluginReport{}, err + } + + merkleRoots := []cciptypes.MerkleRootChain{ + { + ChainSel: cciptypes.ChainSelector(commitReport.MerkleRoot.SourceChainSelector), + OnRampAddress: commitReport.MerkleRoot.OnRampAddress, + SeqNumsRange: cciptypes.NewSeqNumRange( + cciptypes.SeqNum(commitReport.MerkleRoot.MinSeqNr), + cciptypes.SeqNum(commitReport.MerkleRoot.MaxSeqNr), + ), + MerkleRoot: commitReport.MerkleRoot.MerkleRoot, + }, + } + + tokenPriceUpdates := make([]cciptypes.TokenPrice, 0, len(commitReport.PriceUpdates.TokenPriceUpdates)) + for _, update := range commitReport.PriceUpdates.TokenPriceUpdates { + price := cciptypes.BigInt{} + err = price.UnmarshalJSON(update.UsdPerToken[:]) + if err != nil { + return cciptypes.CommitPluginReport{}, err + } + tokenPriceUpdates = append(tokenPriceUpdates, cciptypes.TokenPrice{ + TokenID: cciptypes.UnknownEncodedAddress(update.SourceToken.String()), + Price: price, + }) + } + + gasPriceUpdates := make([]cciptypes.GasPriceChain, 0, len(commitReport.PriceUpdates.GasPriceUpdates)) + for _, update := range commitReport.PriceUpdates.GasPriceUpdates { + price := cciptypes.BigInt{} + err = price.UnmarshalJSON(update.UsdPerUnitGas[:]) + if err != nil { + return cciptypes.CommitPluginReport{}, err + } + gasPriceUpdates = append(gasPriceUpdates, cciptypes.GasPriceChain{ + GasPrice: price, + ChainSel: cciptypes.ChainSelector(update.DestChainSelector), + }) + } + + return cciptypes.CommitPluginReport{ + MerkleRoots: merkleRoots, + PriceUpdates: cciptypes.PriceUpdates{ + TokenPriceUpdates: tokenPriceUpdates, + GasPriceUpdates: gasPriceUpdates, + }, + }, nil +} + +// Ensure CommitPluginCodec implements the CommitPluginCodec interface +var _ cciptypes.CommitPluginCodec = (*CommitPluginCodecV1)(nil) From 71b06dcd7f112f33319f21a16d291b9f1a0701d4 Mon Sep 17 00:00:00 2001 From: Joe Huang Date: Tue, 19 Nov 2024 16:48:47 -0600 Subject: [PATCH 2/4] add solana commit codec, need to add test --- .../AcceptAdminRoleTokenAdminRegistry.go | 146 ++ .../AcceptAdminRoleTokenAdminRegistry_test.go | 32 + .../ccipsolana/ccip_router/AcceptOwnership.go | 117 ++ .../ccip_router/AcceptOwnership_test.go | 32 + .../ccip_router/AddChainSelector.go | 207 ++ .../ccip_router/AddChainSelector_test.go | 32 + .../ccip/ccipsolana/ccip_router/CcipSend.go | 250 +++ .../ccipsolana/ccip_router/CcipSend_test.go | 32 + .../ccip/ccipsolana/ccip_router/Commit.go | 279 +++ .../ccipsolana/ccip_router/Commit_test.go | 32 + .../ccip_router/DisableChainSelector.go | 184 ++ .../ccip_router/DisableChainSelector_test.go | 32 + .../ccip_router/EnableChainSelector.go | 184 ++ .../ccip_router/EnableChainSelector_test.go | 32 + .../ccip/ccipsolana/ccip_router/Execute.go | 293 +++ .../ccipsolana/ccip_router/Execute_test.go | 32 + .../ccip/ccipsolana/ccip_router/Initialize.go | 310 +++ .../ccipsolana/ccip_router/Initialize_test.go | 32 + .../ccipsolana/ccip_router/ManuallyExecute.go | 261 +++ .../ccip_router/ManuallyExecute_test.go | 32 + ...gisterTokenAdminRegistryViaGetCcipAdmin.go | 207 ++ ...rTokenAdminRegistryViaGetCcipAdmin_test.go | 32 + .../RegisterTokenAdminRegistryViaOwner.go | 155 ++ ...RegisterTokenAdminRegistryViaOwner_test.go | 32 + .../ccipsolana/ccip_router/SetOcrConfig.go | 215 ++ .../ccip_router/SetOcrConfig_test.go | 32 + .../ccip/ccipsolana/ccip_router/SetPool.go | 169 ++ .../ccipsolana/ccip_router/SetPool_test.go | 32 + .../ccipsolana/ccip_router/SetTokenBilling.go | 230 +++ .../ccip_router/SetTokenBilling_test.go | 32 + .../TransferAdminRoleTokenAdminRegistry.go | 169 ++ ...ransferAdminRoleTokenAdminRegistry_test.go | 32 + .../ccip_router/TransferOwnership.go | 146 ++ .../ccip_router/TransferOwnership_test.go | 32 + .../UpdateDefaultAllowOutOfOrderExecution.go | 165 ++ ...ateDefaultAllowOutOfOrderExecution_test.go | 32 + .../ccip_router/UpdateDefaultGasLimit.go | 165 ++ .../ccip_router/UpdateDefaultGasLimit_test.go | 32 + .../UpdateEnableManualExecutionAfter.go | 165 ++ .../UpdateEnableManualExecutionAfter_test.go | 32 + .../ccip_router/UpdateSolanaChainSelector.go | 165 ++ .../UpdateSolanaChainSelector_test.go | 32 + .../ccip/ccipsolana/ccip_router/accounts.go | 661 ++++++ .../ccipsolana/ccip_router/instructions.go | 304 +++ .../ccipsolana/ccip_router/testing_utils.go | 20 + .../ccip/ccipsolana/ccip_router/types.go | 1817 +++++++++++++++++ .../ccip/ccipsolana/commitcodec.go | 144 ++ 47 files changed, 7800 insertions(+) create mode 100644 core/capabilities/ccip/ccipsolana/ccip_router/AcceptAdminRoleTokenAdminRegistry.go create mode 100644 core/capabilities/ccip/ccipsolana/ccip_router/AcceptAdminRoleTokenAdminRegistry_test.go create mode 100644 core/capabilities/ccip/ccipsolana/ccip_router/AcceptOwnership.go create mode 100644 core/capabilities/ccip/ccipsolana/ccip_router/AcceptOwnership_test.go create mode 100644 core/capabilities/ccip/ccipsolana/ccip_router/AddChainSelector.go create mode 100644 core/capabilities/ccip/ccipsolana/ccip_router/AddChainSelector_test.go create mode 100644 core/capabilities/ccip/ccipsolana/ccip_router/CcipSend.go create mode 100644 core/capabilities/ccip/ccipsolana/ccip_router/CcipSend_test.go create mode 100644 core/capabilities/ccip/ccipsolana/ccip_router/Commit.go create mode 100644 core/capabilities/ccip/ccipsolana/ccip_router/Commit_test.go create mode 100644 core/capabilities/ccip/ccipsolana/ccip_router/DisableChainSelector.go create mode 100644 core/capabilities/ccip/ccipsolana/ccip_router/DisableChainSelector_test.go create mode 100644 core/capabilities/ccip/ccipsolana/ccip_router/EnableChainSelector.go create mode 100644 core/capabilities/ccip/ccipsolana/ccip_router/EnableChainSelector_test.go create mode 100644 core/capabilities/ccip/ccipsolana/ccip_router/Execute.go create mode 100644 core/capabilities/ccip/ccipsolana/ccip_router/Execute_test.go create mode 100644 core/capabilities/ccip/ccipsolana/ccip_router/Initialize.go create mode 100644 core/capabilities/ccip/ccipsolana/ccip_router/Initialize_test.go create mode 100644 core/capabilities/ccip/ccipsolana/ccip_router/ManuallyExecute.go create mode 100644 core/capabilities/ccip/ccipsolana/ccip_router/ManuallyExecute_test.go create mode 100644 core/capabilities/ccip/ccipsolana/ccip_router/RegisterTokenAdminRegistryViaGetCcipAdmin.go create mode 100644 core/capabilities/ccip/ccipsolana/ccip_router/RegisterTokenAdminRegistryViaGetCcipAdmin_test.go create mode 100644 core/capabilities/ccip/ccipsolana/ccip_router/RegisterTokenAdminRegistryViaOwner.go create mode 100644 core/capabilities/ccip/ccipsolana/ccip_router/RegisterTokenAdminRegistryViaOwner_test.go create mode 100644 core/capabilities/ccip/ccipsolana/ccip_router/SetOcrConfig.go create mode 100644 core/capabilities/ccip/ccipsolana/ccip_router/SetOcrConfig_test.go create mode 100644 core/capabilities/ccip/ccipsolana/ccip_router/SetPool.go create mode 100644 core/capabilities/ccip/ccipsolana/ccip_router/SetPool_test.go create mode 100644 core/capabilities/ccip/ccipsolana/ccip_router/SetTokenBilling.go create mode 100644 core/capabilities/ccip/ccipsolana/ccip_router/SetTokenBilling_test.go create mode 100644 core/capabilities/ccip/ccipsolana/ccip_router/TransferAdminRoleTokenAdminRegistry.go create mode 100644 core/capabilities/ccip/ccipsolana/ccip_router/TransferAdminRoleTokenAdminRegistry_test.go create mode 100644 core/capabilities/ccip/ccipsolana/ccip_router/TransferOwnership.go create mode 100644 core/capabilities/ccip/ccipsolana/ccip_router/TransferOwnership_test.go create mode 100644 core/capabilities/ccip/ccipsolana/ccip_router/UpdateDefaultAllowOutOfOrderExecution.go create mode 100644 core/capabilities/ccip/ccipsolana/ccip_router/UpdateDefaultAllowOutOfOrderExecution_test.go create mode 100644 core/capabilities/ccip/ccipsolana/ccip_router/UpdateDefaultGasLimit.go create mode 100644 core/capabilities/ccip/ccipsolana/ccip_router/UpdateDefaultGasLimit_test.go create mode 100644 core/capabilities/ccip/ccipsolana/ccip_router/UpdateEnableManualExecutionAfter.go create mode 100644 core/capabilities/ccip/ccipsolana/ccip_router/UpdateEnableManualExecutionAfter_test.go create mode 100644 core/capabilities/ccip/ccipsolana/ccip_router/UpdateSolanaChainSelector.go create mode 100644 core/capabilities/ccip/ccipsolana/ccip_router/UpdateSolanaChainSelector_test.go create mode 100644 core/capabilities/ccip/ccipsolana/ccip_router/accounts.go create mode 100644 core/capabilities/ccip/ccipsolana/ccip_router/instructions.go create mode 100644 core/capabilities/ccip/ccipsolana/ccip_router/testing_utils.go create mode 100644 core/capabilities/ccip/ccipsolana/ccip_router/types.go create mode 100644 core/capabilities/ccip/ccipsolana/commitcodec.go diff --git a/core/capabilities/ccip/ccipsolana/ccip_router/AcceptAdminRoleTokenAdminRegistry.go b/core/capabilities/ccip/ccipsolana/ccip_router/AcceptAdminRoleTokenAdminRegistry.go new file mode 100644 index 00000000000..6afa27007fe --- /dev/null +++ b/core/capabilities/ccip/ccipsolana/ccip_router/AcceptAdminRoleTokenAdminRegistry.go @@ -0,0 +1,146 @@ +// Code generated by https://github.com/gagliardetto/anchor-go. DO NOT EDIT. + +package ccip_router + +import ( + "errors" + ag_binary "github.com/gagliardetto/binary" + ag_solanago "github.com/gagliardetto/solana-go" + ag_format "github.com/gagliardetto/solana-go/text/format" + ag_treeout "github.com/gagliardetto/treeout" +) + +// The Pending Admin can accept the Admin Role of the Token Admin Registry +type AcceptAdminRoleTokenAdminRegistry struct { + Mint *ag_solanago.PublicKey + + // [0] = [WRITE] tokenAdminRegistry + // + // [1] = [WRITE, SIGNER] authority + ag_solanago.AccountMetaSlice `bin:"-" borsh_skip:"true"` +} + +// NewAcceptAdminRoleTokenAdminRegistryInstructionBuilder creates a new `AcceptAdminRoleTokenAdminRegistry` instruction builder. +func NewAcceptAdminRoleTokenAdminRegistryInstructionBuilder() *AcceptAdminRoleTokenAdminRegistry { + nd := &AcceptAdminRoleTokenAdminRegistry{ + AccountMetaSlice: make(ag_solanago.AccountMetaSlice, 2), + } + return nd +} + +// SetMint sets the "mint" parameter. +func (inst *AcceptAdminRoleTokenAdminRegistry) SetMint(mint ag_solanago.PublicKey) *AcceptAdminRoleTokenAdminRegistry { + inst.Mint = &mint + return inst +} + +// SetTokenAdminRegistryAccount sets the "tokenAdminRegistry" account. +func (inst *AcceptAdminRoleTokenAdminRegistry) SetTokenAdminRegistryAccount(tokenAdminRegistry ag_solanago.PublicKey) *AcceptAdminRoleTokenAdminRegistry { + inst.AccountMetaSlice[0] = ag_solanago.Meta(tokenAdminRegistry).WRITE() + return inst +} + +// GetTokenAdminRegistryAccount gets the "tokenAdminRegistry" account. +func (inst *AcceptAdminRoleTokenAdminRegistry) GetTokenAdminRegistryAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[0] +} + +// SetAuthorityAccount sets the "authority" account. +func (inst *AcceptAdminRoleTokenAdminRegistry) SetAuthorityAccount(authority ag_solanago.PublicKey) *AcceptAdminRoleTokenAdminRegistry { + inst.AccountMetaSlice[1] = ag_solanago.Meta(authority).WRITE().SIGNER() + return inst +} + +// GetAuthorityAccount gets the "authority" account. +func (inst *AcceptAdminRoleTokenAdminRegistry) GetAuthorityAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[1] +} + +func (inst AcceptAdminRoleTokenAdminRegistry) Build() *Instruction { + return &Instruction{BaseVariant: ag_binary.BaseVariant{ + Impl: inst, + TypeID: Instruction_AcceptAdminRoleTokenAdminRegistry, + }} +} + +// ValidateAndBuild validates the instruction parameters and accounts; +// if there is a validation error, it returns the error. +// Otherwise, it builds and returns the instruction. +func (inst AcceptAdminRoleTokenAdminRegistry) ValidateAndBuild() (*Instruction, error) { + if err := inst.Validate(); err != nil { + return nil, err + } + return inst.Build(), nil +} + +func (inst *AcceptAdminRoleTokenAdminRegistry) Validate() error { + // Check whether all (required) parameters are set: + { + if inst.Mint == nil { + return errors.New("Mint parameter is not set") + } + } + + // Check whether all (required) accounts are set: + { + if inst.AccountMetaSlice[0] == nil { + return errors.New("accounts.TokenAdminRegistry is not set") + } + if inst.AccountMetaSlice[1] == nil { + return errors.New("accounts.Authority is not set") + } + } + return nil +} + +func (inst *AcceptAdminRoleTokenAdminRegistry) EncodeToTree(parent ag_treeout.Branches) { + parent.Child(ag_format.Program(ProgramName, ProgramID)). + // + ParentFunc(func(programBranch ag_treeout.Branches) { + programBranch.Child(ag_format.Instruction("AcceptAdminRoleTokenAdminRegistry")). + // + ParentFunc(func(instructionBranch ag_treeout.Branches) { + + // Parameters of the instruction: + instructionBranch.Child("Params[len=1]").ParentFunc(func(paramsBranch ag_treeout.Branches) { + paramsBranch.Child(ag_format.Param("Mint", *inst.Mint)) + }) + + // Accounts of the instruction: + instructionBranch.Child("Accounts[len=2]").ParentFunc(func(accountsBranch ag_treeout.Branches) { + accountsBranch.Child(ag_format.Meta("tokenAdminRegistry", inst.AccountMetaSlice[0])) + accountsBranch.Child(ag_format.Meta(" authority", inst.AccountMetaSlice[1])) + }) + }) + }) +} + +func (obj AcceptAdminRoleTokenAdminRegistry) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { + // Serialize `Mint` param: + err = encoder.Encode(obj.Mint) + if err != nil { + return err + } + return nil +} +func (obj *AcceptAdminRoleTokenAdminRegistry) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { + // Deserialize `Mint`: + err = decoder.Decode(&obj.Mint) + if err != nil { + return err + } + return nil +} + +// NewAcceptAdminRoleTokenAdminRegistryInstruction declares a new AcceptAdminRoleTokenAdminRegistry instruction with the provided parameters and accounts. +func NewAcceptAdminRoleTokenAdminRegistryInstruction( + // Parameters: + mint ag_solanago.PublicKey, + // Accounts: + tokenAdminRegistry ag_solanago.PublicKey, + authority ag_solanago.PublicKey) *AcceptAdminRoleTokenAdminRegistry { + return NewAcceptAdminRoleTokenAdminRegistryInstructionBuilder(). + SetMint(mint). + SetTokenAdminRegistryAccount(tokenAdminRegistry). + SetAuthorityAccount(authority) +} diff --git a/core/capabilities/ccip/ccipsolana/ccip_router/AcceptAdminRoleTokenAdminRegistry_test.go b/core/capabilities/ccip/ccipsolana/ccip_router/AcceptAdminRoleTokenAdminRegistry_test.go new file mode 100644 index 00000000000..44baeb8e004 --- /dev/null +++ b/core/capabilities/ccip/ccipsolana/ccip_router/AcceptAdminRoleTokenAdminRegistry_test.go @@ -0,0 +1,32 @@ +// Code generated by https://github.com/gagliardetto/anchor-go. DO NOT EDIT. + +package ccip_router + +import ( + "bytes" + ag_gofuzz "github.com/gagliardetto/gofuzz" + ag_require "github.com/stretchr/testify/require" + "strconv" + "testing" +) + +func TestEncodeDecode_AcceptAdminRoleTokenAdminRegistry(t *testing.T) { + fu := ag_gofuzz.New().NilChance(0) + for i := 0; i < 1; i++ { + t.Run("AcceptAdminRoleTokenAdminRegistry"+strconv.Itoa(i), func(t *testing.T) { + { + params := new(AcceptAdminRoleTokenAdminRegistry) + fu.Fuzz(params) + params.AccountMetaSlice = nil + buf := new(bytes.Buffer) + err := encodeT(*params, buf) + ag_require.NoError(t, err) + got := new(AcceptAdminRoleTokenAdminRegistry) + err = decodeT(got, buf.Bytes()) + got.AccountMetaSlice = nil + ag_require.NoError(t, err) + ag_require.Equal(t, params, got) + } + }) + } +} diff --git a/core/capabilities/ccip/ccipsolana/ccip_router/AcceptOwnership.go b/core/capabilities/ccip/ccipsolana/ccip_router/AcceptOwnership.go new file mode 100644 index 00000000000..9354db59224 --- /dev/null +++ b/core/capabilities/ccip/ccipsolana/ccip_router/AcceptOwnership.go @@ -0,0 +1,117 @@ +// Code generated by https://github.com/gagliardetto/anchor-go. DO NOT EDIT. + +package ccip_router + +import ( + "errors" + ag_binary "github.com/gagliardetto/binary" + ag_solanago "github.com/gagliardetto/solana-go" + ag_format "github.com/gagliardetto/solana-go/text/format" + ag_treeout "github.com/gagliardetto/treeout" +) + +// AcceptOwnership is the `acceptOwnership` instruction. +type AcceptOwnership struct { + + // [0] = [WRITE] config + // + // [1] = [SIGNER] authority + ag_solanago.AccountMetaSlice `bin:"-" borsh_skip:"true"` +} + +// NewAcceptOwnershipInstructionBuilder creates a new `AcceptOwnership` instruction builder. +func NewAcceptOwnershipInstructionBuilder() *AcceptOwnership { + nd := &AcceptOwnership{ + AccountMetaSlice: make(ag_solanago.AccountMetaSlice, 2), + } + return nd +} + +// SetConfigAccount sets the "config" account. +func (inst *AcceptOwnership) SetConfigAccount(config ag_solanago.PublicKey) *AcceptOwnership { + inst.AccountMetaSlice[0] = ag_solanago.Meta(config).WRITE() + return inst +} + +// GetConfigAccount gets the "config" account. +func (inst *AcceptOwnership) GetConfigAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[0] +} + +// SetAuthorityAccount sets the "authority" account. +func (inst *AcceptOwnership) SetAuthorityAccount(authority ag_solanago.PublicKey) *AcceptOwnership { + inst.AccountMetaSlice[1] = ag_solanago.Meta(authority).SIGNER() + return inst +} + +// GetAuthorityAccount gets the "authority" account. +func (inst *AcceptOwnership) GetAuthorityAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[1] +} + +func (inst AcceptOwnership) Build() *Instruction { + return &Instruction{BaseVariant: ag_binary.BaseVariant{ + Impl: inst, + TypeID: Instruction_AcceptOwnership, + }} +} + +// ValidateAndBuild validates the instruction parameters and accounts; +// if there is a validation error, it returns the error. +// Otherwise, it builds and returns the instruction. +func (inst AcceptOwnership) ValidateAndBuild() (*Instruction, error) { + if err := inst.Validate(); err != nil { + return nil, err + } + return inst.Build(), nil +} + +func (inst *AcceptOwnership) Validate() error { + // Check whether all (required) accounts are set: + { + if inst.AccountMetaSlice[0] == nil { + return errors.New("accounts.Config is not set") + } + if inst.AccountMetaSlice[1] == nil { + return errors.New("accounts.Authority is not set") + } + } + return nil +} + +func (inst *AcceptOwnership) EncodeToTree(parent ag_treeout.Branches) { + parent.Child(ag_format.Program(ProgramName, ProgramID)). + // + ParentFunc(func(programBranch ag_treeout.Branches) { + programBranch.Child(ag_format.Instruction("AcceptOwnership")). + // + ParentFunc(func(instructionBranch ag_treeout.Branches) { + + // Parameters of the instruction: + instructionBranch.Child("Params[len=0]").ParentFunc(func(paramsBranch ag_treeout.Branches) {}) + + // Accounts of the instruction: + instructionBranch.Child("Accounts[len=2]").ParentFunc(func(accountsBranch ag_treeout.Branches) { + accountsBranch.Child(ag_format.Meta(" config", inst.AccountMetaSlice[0])) + accountsBranch.Child(ag_format.Meta("authority", inst.AccountMetaSlice[1])) + }) + }) + }) +} + +func (obj AcceptOwnership) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { + return nil +} +func (obj *AcceptOwnership) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { + return nil +} + +// NewAcceptOwnershipInstruction declares a new AcceptOwnership instruction with the provided parameters and accounts. +func NewAcceptOwnershipInstruction( + // Accounts: + config ag_solanago.PublicKey, + authority ag_solanago.PublicKey) *AcceptOwnership { + return NewAcceptOwnershipInstructionBuilder(). + SetConfigAccount(config). + SetAuthorityAccount(authority) +} diff --git a/core/capabilities/ccip/ccipsolana/ccip_router/AcceptOwnership_test.go b/core/capabilities/ccip/ccipsolana/ccip_router/AcceptOwnership_test.go new file mode 100644 index 00000000000..da475cd5d24 --- /dev/null +++ b/core/capabilities/ccip/ccipsolana/ccip_router/AcceptOwnership_test.go @@ -0,0 +1,32 @@ +// Code generated by https://github.com/gagliardetto/anchor-go. DO NOT EDIT. + +package ccip_router + +import ( + "bytes" + ag_gofuzz "github.com/gagliardetto/gofuzz" + ag_require "github.com/stretchr/testify/require" + "strconv" + "testing" +) + +func TestEncodeDecode_AcceptOwnership(t *testing.T) { + fu := ag_gofuzz.New().NilChance(0) + for i := 0; i < 1; i++ { + t.Run("AcceptOwnership"+strconv.Itoa(i), func(t *testing.T) { + { + params := new(AcceptOwnership) + fu.Fuzz(params) + params.AccountMetaSlice = nil + buf := new(bytes.Buffer) + err := encodeT(*params, buf) + ag_require.NoError(t, err) + got := new(AcceptOwnership) + err = decodeT(got, buf.Bytes()) + got.AccountMetaSlice = nil + ag_require.NoError(t, err) + ag_require.Equal(t, params, got) + } + }) + } +} diff --git a/core/capabilities/ccip/ccipsolana/ccip_router/AddChainSelector.go b/core/capabilities/ccip/ccipsolana/ccip_router/AddChainSelector.go new file mode 100644 index 00000000000..743d44c41e1 --- /dev/null +++ b/core/capabilities/ccip/ccipsolana/ccip_router/AddChainSelector.go @@ -0,0 +1,207 @@ +// Code generated by https://github.com/gagliardetto/anchor-go. DO NOT EDIT. + +package ccip_router + +import ( + "errors" + ag_binary "github.com/gagliardetto/binary" + ag_solanago "github.com/gagliardetto/solana-go" + ag_format "github.com/gagliardetto/solana-go/text/format" + ag_treeout "github.com/gagliardetto/treeout" +) + +// The Admin needs to add any new chain supported (this means both OnRamp and OffRamp). +type AddChainSelector struct { + NewChainSelector *uint64 + OnRampAddress *[]byte + + // [0] = [WRITE] chainState + // + // [1] = [] config + // + // [2] = [WRITE, SIGNER] authority + // + // [3] = [] systemProgram + ag_solanago.AccountMetaSlice `bin:"-" borsh_skip:"true"` +} + +// NewAddChainSelectorInstructionBuilder creates a new `AddChainSelector` instruction builder. +func NewAddChainSelectorInstructionBuilder() *AddChainSelector { + nd := &AddChainSelector{ + AccountMetaSlice: make(ag_solanago.AccountMetaSlice, 4), + } + return nd +} + +// SetNewChainSelector sets the "newChainSelector" parameter. +func (inst *AddChainSelector) SetNewChainSelector(newChainSelector uint64) *AddChainSelector { + inst.NewChainSelector = &newChainSelector + return inst +} + +// SetOnRampAddress sets the "onRampAddress" parameter. +func (inst *AddChainSelector) SetOnRampAddress(onRampAddress []byte) *AddChainSelector { + inst.OnRampAddress = &onRampAddress + return inst +} + +// SetChainStateAccount sets the "chainState" account. +func (inst *AddChainSelector) SetChainStateAccount(chainState ag_solanago.PublicKey) *AddChainSelector { + inst.AccountMetaSlice[0] = ag_solanago.Meta(chainState).WRITE() + return inst +} + +// GetChainStateAccount gets the "chainState" account. +func (inst *AddChainSelector) GetChainStateAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[0] +} + +// SetConfigAccount sets the "config" account. +func (inst *AddChainSelector) SetConfigAccount(config ag_solanago.PublicKey) *AddChainSelector { + inst.AccountMetaSlice[1] = ag_solanago.Meta(config) + return inst +} + +// GetConfigAccount gets the "config" account. +func (inst *AddChainSelector) GetConfigAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[1] +} + +// SetAuthorityAccount sets the "authority" account. +func (inst *AddChainSelector) SetAuthorityAccount(authority ag_solanago.PublicKey) *AddChainSelector { + inst.AccountMetaSlice[2] = ag_solanago.Meta(authority).WRITE().SIGNER() + return inst +} + +// GetAuthorityAccount gets the "authority" account. +func (inst *AddChainSelector) GetAuthorityAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[2] +} + +// SetSystemProgramAccount sets the "systemProgram" account. +func (inst *AddChainSelector) SetSystemProgramAccount(systemProgram ag_solanago.PublicKey) *AddChainSelector { + inst.AccountMetaSlice[3] = ag_solanago.Meta(systemProgram) + return inst +} + +// GetSystemProgramAccount gets the "systemProgram" account. +func (inst *AddChainSelector) GetSystemProgramAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[3] +} + +func (inst AddChainSelector) Build() *Instruction { + return &Instruction{BaseVariant: ag_binary.BaseVariant{ + Impl: inst, + TypeID: Instruction_AddChainSelector, + }} +} + +// ValidateAndBuild validates the instruction parameters and accounts; +// if there is a validation error, it returns the error. +// Otherwise, it builds and returns the instruction. +func (inst AddChainSelector) ValidateAndBuild() (*Instruction, error) { + if err := inst.Validate(); err != nil { + return nil, err + } + return inst.Build(), nil +} + +func (inst *AddChainSelector) Validate() error { + // Check whether all (required) parameters are set: + { + if inst.NewChainSelector == nil { + return errors.New("NewChainSelector parameter is not set") + } + if inst.OnRampAddress == nil { + return errors.New("OnRampAddress parameter is not set") + } + } + + // Check whether all (required) accounts are set: + { + if inst.AccountMetaSlice[0] == nil { + return errors.New("accounts.ChainState is not set") + } + if inst.AccountMetaSlice[1] == nil { + return errors.New("accounts.Config is not set") + } + if inst.AccountMetaSlice[2] == nil { + return errors.New("accounts.Authority is not set") + } + if inst.AccountMetaSlice[3] == nil { + return errors.New("accounts.SystemProgram is not set") + } + } + return nil +} + +func (inst *AddChainSelector) EncodeToTree(parent ag_treeout.Branches) { + parent.Child(ag_format.Program(ProgramName, ProgramID)). + // + ParentFunc(func(programBranch ag_treeout.Branches) { + programBranch.Child(ag_format.Instruction("AddChainSelector")). + // + ParentFunc(func(instructionBranch ag_treeout.Branches) { + + // Parameters of the instruction: + instructionBranch.Child("Params[len=2]").ParentFunc(func(paramsBranch ag_treeout.Branches) { + paramsBranch.Child(ag_format.Param("NewChainSelector", *inst.NewChainSelector)) + paramsBranch.Child(ag_format.Param(" OnRampAddress", *inst.OnRampAddress)) + }) + + // Accounts of the instruction: + instructionBranch.Child("Accounts[len=4]").ParentFunc(func(accountsBranch ag_treeout.Branches) { + accountsBranch.Child(ag_format.Meta(" chainState", inst.AccountMetaSlice[0])) + accountsBranch.Child(ag_format.Meta(" config", inst.AccountMetaSlice[1])) + accountsBranch.Child(ag_format.Meta(" authority", inst.AccountMetaSlice[2])) + accountsBranch.Child(ag_format.Meta("systemProgram", inst.AccountMetaSlice[3])) + }) + }) + }) +} + +func (obj AddChainSelector) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { + // Serialize `NewChainSelector` param: + err = encoder.Encode(obj.NewChainSelector) + if err != nil { + return err + } + // Serialize `OnRampAddress` param: + err = encoder.Encode(obj.OnRampAddress) + if err != nil { + return err + } + return nil +} +func (obj *AddChainSelector) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { + // Deserialize `NewChainSelector`: + err = decoder.Decode(&obj.NewChainSelector) + if err != nil { + return err + } + // Deserialize `OnRampAddress`: + err = decoder.Decode(&obj.OnRampAddress) + if err != nil { + return err + } + return nil +} + +// NewAddChainSelectorInstruction declares a new AddChainSelector instruction with the provided parameters and accounts. +func NewAddChainSelectorInstruction( + // Parameters: + newChainSelector uint64, + onRampAddress []byte, + // Accounts: + chainState ag_solanago.PublicKey, + config ag_solanago.PublicKey, + authority ag_solanago.PublicKey, + systemProgram ag_solanago.PublicKey) *AddChainSelector { + return NewAddChainSelectorInstructionBuilder(). + SetNewChainSelector(newChainSelector). + SetOnRampAddress(onRampAddress). + SetChainStateAccount(chainState). + SetConfigAccount(config). + SetAuthorityAccount(authority). + SetSystemProgramAccount(systemProgram) +} diff --git a/core/capabilities/ccip/ccipsolana/ccip_router/AddChainSelector_test.go b/core/capabilities/ccip/ccipsolana/ccip_router/AddChainSelector_test.go new file mode 100644 index 00000000000..8398360f7f6 --- /dev/null +++ b/core/capabilities/ccip/ccipsolana/ccip_router/AddChainSelector_test.go @@ -0,0 +1,32 @@ +// Code generated by https://github.com/gagliardetto/anchor-go. DO NOT EDIT. + +package ccip_router + +import ( + "bytes" + ag_gofuzz "github.com/gagliardetto/gofuzz" + ag_require "github.com/stretchr/testify/require" + "strconv" + "testing" +) + +func TestEncodeDecode_AddChainSelector(t *testing.T) { + fu := ag_gofuzz.New().NilChance(0) + for i := 0; i < 1; i++ { + t.Run("AddChainSelector"+strconv.Itoa(i), func(t *testing.T) { + { + params := new(AddChainSelector) + fu.Fuzz(params) + params.AccountMetaSlice = nil + buf := new(bytes.Buffer) + err := encodeT(*params, buf) + ag_require.NoError(t, err) + got := new(AddChainSelector) + err = decodeT(got, buf.Bytes()) + got.AccountMetaSlice = nil + ag_require.NoError(t, err) + ag_require.Equal(t, params, got) + } + }) + } +} diff --git a/core/capabilities/ccip/ccipsolana/ccip_router/CcipSend.go b/core/capabilities/ccip/ccipsolana/ccip_router/CcipSend.go new file mode 100644 index 00000000000..61cd343e929 --- /dev/null +++ b/core/capabilities/ccip/ccipsolana/ccip_router/CcipSend.go @@ -0,0 +1,250 @@ +// Code generated by https://github.com/gagliardetto/anchor-go. DO NOT EDIT. + +package ccip_router + +import ( + "errors" + ag_binary "github.com/gagliardetto/binary" + ag_solanago "github.com/gagliardetto/solana-go" + ag_format "github.com/gagliardetto/solana-go/text/format" + ag_treeout "github.com/gagliardetto/treeout" +) + +// ON RAMP FLOW +// The method name needs to be ccip_send with Anchor encoding. +// This function is called by the CCIP Sender Contract (or final user) to send a message to the CCIP Router. +// The size limit of data is 256 bytes. +// The message is sent to the receiver on the destination chain selector. +// This message emits the event CCIPSendRequested with all the necessary data to be retrieved by the OffChain Code +type CcipSend struct { + DestChainSelector *uint64 + Message *Solana2AnyMessage + + // [0] = [] config + // + // [1] = [WRITE] chainState + // + // [2] = [WRITE] nonce + // + // [3] = [WRITE, SIGNER] authority + // + // [4] = [] systemProgram + // + // [5] = [WRITE] tokenPoolsSigner + ag_solanago.AccountMetaSlice `bin:"-" borsh_skip:"true"` +} + +// NewCcipSendInstructionBuilder creates a new `CcipSend` instruction builder. +func NewCcipSendInstructionBuilder() *CcipSend { + nd := &CcipSend{ + AccountMetaSlice: make(ag_solanago.AccountMetaSlice, 6), + } + return nd +} + +// SetDestChainSelector sets the "destChainSelector" parameter. +func (inst *CcipSend) SetDestChainSelector(destChainSelector uint64) *CcipSend { + inst.DestChainSelector = &destChainSelector + return inst +} + +// SetMessage sets the "message" parameter. +func (inst *CcipSend) SetMessage(message Solana2AnyMessage) *CcipSend { + inst.Message = &message + return inst +} + +// SetConfigAccount sets the "config" account. +func (inst *CcipSend) SetConfigAccount(config ag_solanago.PublicKey) *CcipSend { + inst.AccountMetaSlice[0] = ag_solanago.Meta(config) + return inst +} + +// GetConfigAccount gets the "config" account. +func (inst *CcipSend) GetConfigAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[0] +} + +// SetChainStateAccount sets the "chainState" account. +func (inst *CcipSend) SetChainStateAccount(chainState ag_solanago.PublicKey) *CcipSend { + inst.AccountMetaSlice[1] = ag_solanago.Meta(chainState).WRITE() + return inst +} + +// GetChainStateAccount gets the "chainState" account. +func (inst *CcipSend) GetChainStateAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[1] +} + +// SetNonceAccount sets the "nonce" account. +func (inst *CcipSend) SetNonceAccount(nonce ag_solanago.PublicKey) *CcipSend { + inst.AccountMetaSlice[2] = ag_solanago.Meta(nonce).WRITE() + return inst +} + +// GetNonceAccount gets the "nonce" account. +func (inst *CcipSend) GetNonceAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[2] +} + +// SetAuthorityAccount sets the "authority" account. +func (inst *CcipSend) SetAuthorityAccount(authority ag_solanago.PublicKey) *CcipSend { + inst.AccountMetaSlice[3] = ag_solanago.Meta(authority).WRITE().SIGNER() + return inst +} + +// GetAuthorityAccount gets the "authority" account. +func (inst *CcipSend) GetAuthorityAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[3] +} + +// SetSystemProgramAccount sets the "systemProgram" account. +func (inst *CcipSend) SetSystemProgramAccount(systemProgram ag_solanago.PublicKey) *CcipSend { + inst.AccountMetaSlice[4] = ag_solanago.Meta(systemProgram) + return inst +} + +// GetSystemProgramAccount gets the "systemProgram" account. +func (inst *CcipSend) GetSystemProgramAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[4] +} + +// SetTokenPoolsSignerAccount sets the "tokenPoolsSigner" account. +func (inst *CcipSend) SetTokenPoolsSignerAccount(tokenPoolsSigner ag_solanago.PublicKey) *CcipSend { + inst.AccountMetaSlice[5] = ag_solanago.Meta(tokenPoolsSigner).WRITE() + return inst +} + +// GetTokenPoolsSignerAccount gets the "tokenPoolsSigner" account. +func (inst *CcipSend) GetTokenPoolsSignerAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[5] +} + +func (inst CcipSend) Build() *Instruction { + return &Instruction{BaseVariant: ag_binary.BaseVariant{ + Impl: inst, + TypeID: Instruction_CcipSend, + }} +} + +// ValidateAndBuild validates the instruction parameters and accounts; +// if there is a validation error, it returns the error. +// Otherwise, it builds and returns the instruction. +func (inst CcipSend) ValidateAndBuild() (*Instruction, error) { + if err := inst.Validate(); err != nil { + return nil, err + } + return inst.Build(), nil +} + +func (inst *CcipSend) Validate() error { + // Check whether all (required) parameters are set: + { + if inst.DestChainSelector == nil { + return errors.New("DestChainSelector parameter is not set") + } + if inst.Message == nil { + return errors.New("Message parameter is not set") + } + } + + // Check whether all (required) accounts are set: + { + if inst.AccountMetaSlice[0] == nil { + return errors.New("accounts.Config is not set") + } + if inst.AccountMetaSlice[1] == nil { + return errors.New("accounts.ChainState is not set") + } + if inst.AccountMetaSlice[2] == nil { + return errors.New("accounts.Nonce is not set") + } + if inst.AccountMetaSlice[3] == nil { + return errors.New("accounts.Authority is not set") + } + if inst.AccountMetaSlice[4] == nil { + return errors.New("accounts.SystemProgram is not set") + } + if inst.AccountMetaSlice[5] == nil { + return errors.New("accounts.TokenPoolsSigner is not set") + } + } + return nil +} + +func (inst *CcipSend) EncodeToTree(parent ag_treeout.Branches) { + parent.Child(ag_format.Program(ProgramName, ProgramID)). + // + ParentFunc(func(programBranch ag_treeout.Branches) { + programBranch.Child(ag_format.Instruction("CcipSend")). + // + ParentFunc(func(instructionBranch ag_treeout.Branches) { + + // Parameters of the instruction: + instructionBranch.Child("Params[len=2]").ParentFunc(func(paramsBranch ag_treeout.Branches) { + paramsBranch.Child(ag_format.Param("DestChainSelector", *inst.DestChainSelector)) + paramsBranch.Child(ag_format.Param(" Message", *inst.Message)) + }) + + // Accounts of the instruction: + instructionBranch.Child("Accounts[len=6]").ParentFunc(func(accountsBranch ag_treeout.Branches) { + accountsBranch.Child(ag_format.Meta(" config", inst.AccountMetaSlice[0])) + accountsBranch.Child(ag_format.Meta(" chainState", inst.AccountMetaSlice[1])) + accountsBranch.Child(ag_format.Meta(" nonce", inst.AccountMetaSlice[2])) + accountsBranch.Child(ag_format.Meta(" authority", inst.AccountMetaSlice[3])) + accountsBranch.Child(ag_format.Meta(" systemProgram", inst.AccountMetaSlice[4])) + accountsBranch.Child(ag_format.Meta("tokenPoolsSigner", inst.AccountMetaSlice[5])) + }) + }) + }) +} + +func (obj CcipSend) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { + // Serialize `DestChainSelector` param: + err = encoder.Encode(obj.DestChainSelector) + if err != nil { + return err + } + // Serialize `Message` param: + err = encoder.Encode(obj.Message) + if err != nil { + return err + } + return nil +} +func (obj *CcipSend) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { + // Deserialize `DestChainSelector`: + err = decoder.Decode(&obj.DestChainSelector) + if err != nil { + return err + } + // Deserialize `Message`: + err = decoder.Decode(&obj.Message) + if err != nil { + return err + } + return nil +} + +// NewCcipSendInstruction declares a new CcipSend instruction with the provided parameters and accounts. +func NewCcipSendInstruction( + // Parameters: + destChainSelector uint64, + message Solana2AnyMessage, + // Accounts: + config ag_solanago.PublicKey, + chainState ag_solanago.PublicKey, + nonce ag_solanago.PublicKey, + authority ag_solanago.PublicKey, + systemProgram ag_solanago.PublicKey, + tokenPoolsSigner ag_solanago.PublicKey) *CcipSend { + return NewCcipSendInstructionBuilder(). + SetDestChainSelector(destChainSelector). + SetMessage(message). + SetConfigAccount(config). + SetChainStateAccount(chainState). + SetNonceAccount(nonce). + SetAuthorityAccount(authority). + SetSystemProgramAccount(systemProgram). + SetTokenPoolsSignerAccount(tokenPoolsSigner) +} diff --git a/core/capabilities/ccip/ccipsolana/ccip_router/CcipSend_test.go b/core/capabilities/ccip/ccipsolana/ccip_router/CcipSend_test.go new file mode 100644 index 00000000000..a9f819342cb --- /dev/null +++ b/core/capabilities/ccip/ccipsolana/ccip_router/CcipSend_test.go @@ -0,0 +1,32 @@ +// Code generated by https://github.com/gagliardetto/anchor-go. DO NOT EDIT. + +package ccip_router + +import ( + "bytes" + ag_gofuzz "github.com/gagliardetto/gofuzz" + ag_require "github.com/stretchr/testify/require" + "strconv" + "testing" +) + +func TestEncodeDecode_CcipSend(t *testing.T) { + fu := ag_gofuzz.New().NilChance(0) + for i := 0; i < 1; i++ { + t.Run("CcipSend"+strconv.Itoa(i), func(t *testing.T) { + { + params := new(CcipSend) + fu.Fuzz(params) + params.AccountMetaSlice = nil + buf := new(bytes.Buffer) + err := encodeT(*params, buf) + ag_require.NoError(t, err) + got := new(CcipSend) + err = decodeT(got, buf.Bytes()) + got.AccountMetaSlice = nil + ag_require.NoError(t, err) + ag_require.Equal(t, params, got) + } + }) + } +} diff --git a/core/capabilities/ccip/ccipsolana/ccip_router/Commit.go b/core/capabilities/ccip/ccipsolana/ccip_router/Commit.go new file mode 100644 index 00000000000..898c086029b --- /dev/null +++ b/core/capabilities/ccip/ccipsolana/ccip_router/Commit.go @@ -0,0 +1,279 @@ +// Code generated by https://github.com/gagliardetto/anchor-go. DO NOT EDIT. + +package ccip_router + +import ( + "errors" + ag_binary "github.com/gagliardetto/binary" + ag_solanago "github.com/gagliardetto/solana-go" + ag_format "github.com/gagliardetto/solana-go/text/format" + ag_treeout "github.com/gagliardetto/treeout" +) + +// OFF RAMP FLOW +// +// The method name needs to be commit with Anchor encoding. +// +// This function is called by the OffChain when committing one Report to the Solana Router. +// In this Flow only one report is sent, the Commit Report. This is different as EVM does, +// this is because here all the chain state is stored in one account per Merkle Tree Root. +// So, to avoid having to send a dynamic size array of accounts, in this message only one Commit Report Account is sent. +// This message validates the signatures of the report and stores the Merkle Root in the Commit Report Account. +// The Report must contain an interval of messages, and the min of them must be the next sequence number expected. +// The max size of the interval is 64. +// This message emits two events: CommitReportAccepted and Transmitted. +type Commit struct { + ReportContext *[3][32]uint8 + Report *CommitInput + Signatures *[][65]uint8 + + // [0] = [] config + // + // [1] = [WRITE] chainState + // + // [2] = [WRITE] commitReport + // + // [3] = [WRITE, SIGNER] authority + // + // [4] = [] systemProgram + // + // [5] = [] sysvarInstructions + ag_solanago.AccountMetaSlice `bin:"-" borsh_skip:"true"` +} + +// NewCommitInstructionBuilder creates a new `Commit` instruction builder. +func NewCommitInstructionBuilder() *Commit { + nd := &Commit{ + AccountMetaSlice: make(ag_solanago.AccountMetaSlice, 6), + } + return nd +} + +// SetReportContext sets the "reportContext" parameter. +func (inst *Commit) SetReportContext(reportContext [3][32]uint8) *Commit { + inst.ReportContext = &reportContext + return inst +} + +// SetReport sets the "report" parameter. +func (inst *Commit) SetReport(report CommitInput) *Commit { + inst.Report = &report + return inst +} + +// SetSignatures sets the "signatures" parameter. +func (inst *Commit) SetSignatures(signatures [][65]uint8) *Commit { + inst.Signatures = &signatures + return inst +} + +// SetConfigAccount sets the "config" account. +func (inst *Commit) SetConfigAccount(config ag_solanago.PublicKey) *Commit { + inst.AccountMetaSlice[0] = ag_solanago.Meta(config) + return inst +} + +// GetConfigAccount gets the "config" account. +func (inst *Commit) GetConfigAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[0] +} + +// SetChainStateAccount sets the "chainState" account. +func (inst *Commit) SetChainStateAccount(chainState ag_solanago.PublicKey) *Commit { + inst.AccountMetaSlice[1] = ag_solanago.Meta(chainState).WRITE() + return inst +} + +// GetChainStateAccount gets the "chainState" account. +func (inst *Commit) GetChainStateAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[1] +} + +// SetCommitReportAccount sets the "commitReport" account. +func (inst *Commit) SetCommitReportAccount(commitReport ag_solanago.PublicKey) *Commit { + inst.AccountMetaSlice[2] = ag_solanago.Meta(commitReport).WRITE() + return inst +} + +// GetCommitReportAccount gets the "commitReport" account. +func (inst *Commit) GetCommitReportAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[2] +} + +// SetAuthorityAccount sets the "authority" account. +func (inst *Commit) SetAuthorityAccount(authority ag_solanago.PublicKey) *Commit { + inst.AccountMetaSlice[3] = ag_solanago.Meta(authority).WRITE().SIGNER() + return inst +} + +// GetAuthorityAccount gets the "authority" account. +func (inst *Commit) GetAuthorityAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[3] +} + +// SetSystemProgramAccount sets the "systemProgram" account. +func (inst *Commit) SetSystemProgramAccount(systemProgram ag_solanago.PublicKey) *Commit { + inst.AccountMetaSlice[4] = ag_solanago.Meta(systemProgram) + return inst +} + +// GetSystemProgramAccount gets the "systemProgram" account. +func (inst *Commit) GetSystemProgramAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[4] +} + +// SetSysvarInstructionsAccount sets the "sysvarInstructions" account. +func (inst *Commit) SetSysvarInstructionsAccount(sysvarInstructions ag_solanago.PublicKey) *Commit { + inst.AccountMetaSlice[5] = ag_solanago.Meta(sysvarInstructions) + return inst +} + +// GetSysvarInstructionsAccount gets the "sysvarInstructions" account. +func (inst *Commit) GetSysvarInstructionsAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[5] +} + +func (inst Commit) Build() *Instruction { + return &Instruction{BaseVariant: ag_binary.BaseVariant{ + Impl: inst, + TypeID: Instruction_Commit, + }} +} + +// ValidateAndBuild validates the instruction parameters and accounts; +// if there is a validation error, it returns the error. +// Otherwise, it builds and returns the instruction. +func (inst Commit) ValidateAndBuild() (*Instruction, error) { + if err := inst.Validate(); err != nil { + return nil, err + } + return inst.Build(), nil +} + +func (inst *Commit) Validate() error { + // Check whether all (required) parameters are set: + { + if inst.ReportContext == nil { + return errors.New("ReportContext parameter is not set") + } + if inst.Report == nil { + return errors.New("Report parameter is not set") + } + if inst.Signatures == nil { + return errors.New("Signatures parameter is not set") + } + } + + // Check whether all (required) accounts are set: + { + if inst.AccountMetaSlice[0] == nil { + return errors.New("accounts.Config is not set") + } + if inst.AccountMetaSlice[1] == nil { + return errors.New("accounts.ChainState is not set") + } + if inst.AccountMetaSlice[2] == nil { + return errors.New("accounts.CommitReport is not set") + } + if inst.AccountMetaSlice[3] == nil { + return errors.New("accounts.Authority is not set") + } + if inst.AccountMetaSlice[4] == nil { + return errors.New("accounts.SystemProgram is not set") + } + if inst.AccountMetaSlice[5] == nil { + return errors.New("accounts.SysvarInstructions is not set") + } + } + return nil +} + +func (inst *Commit) EncodeToTree(parent ag_treeout.Branches) { + parent.Child(ag_format.Program(ProgramName, ProgramID)). + // + ParentFunc(func(programBranch ag_treeout.Branches) { + programBranch.Child(ag_format.Instruction("Commit")). + // + ParentFunc(func(instructionBranch ag_treeout.Branches) { + + // Parameters of the instruction: + instructionBranch.Child("Params[len=3]").ParentFunc(func(paramsBranch ag_treeout.Branches) { + paramsBranch.Child(ag_format.Param("ReportContext", *inst.ReportContext)) + paramsBranch.Child(ag_format.Param(" Report", *inst.Report)) + paramsBranch.Child(ag_format.Param(" Signatures", *inst.Signatures)) + }) + + // Accounts of the instruction: + instructionBranch.Child("Accounts[len=6]").ParentFunc(func(accountsBranch ag_treeout.Branches) { + accountsBranch.Child(ag_format.Meta(" config", inst.AccountMetaSlice[0])) + accountsBranch.Child(ag_format.Meta(" chainState", inst.AccountMetaSlice[1])) + accountsBranch.Child(ag_format.Meta(" commitReport", inst.AccountMetaSlice[2])) + accountsBranch.Child(ag_format.Meta(" authority", inst.AccountMetaSlice[3])) + accountsBranch.Child(ag_format.Meta(" systemProgram", inst.AccountMetaSlice[4])) + accountsBranch.Child(ag_format.Meta("sysvarInstructions", inst.AccountMetaSlice[5])) + }) + }) + }) +} + +func (obj Commit) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { + // Serialize `ReportContext` param: + err = encoder.Encode(obj.ReportContext) + if err != nil { + return err + } + // Serialize `Report` param: + err = encoder.Encode(obj.Report) + if err != nil { + return err + } + // Serialize `Signatures` param: + err = encoder.Encode(obj.Signatures) + if err != nil { + return err + } + return nil +} +func (obj *Commit) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { + // Deserialize `ReportContext`: + err = decoder.Decode(&obj.ReportContext) + if err != nil { + return err + } + // Deserialize `Report`: + err = decoder.Decode(&obj.Report) + if err != nil { + return err + } + // Deserialize `Signatures`: + err = decoder.Decode(&obj.Signatures) + if err != nil { + return err + } + return nil +} + +// NewCommitInstruction declares a new Commit instruction with the provided parameters and accounts. +func NewCommitInstruction( + // Parameters: + reportContext [3][32]uint8, + report CommitInput, + signatures [][65]uint8, + // Accounts: + config ag_solanago.PublicKey, + chainState ag_solanago.PublicKey, + commitReport ag_solanago.PublicKey, + authority ag_solanago.PublicKey, + systemProgram ag_solanago.PublicKey, + sysvarInstructions ag_solanago.PublicKey) *Commit { + return NewCommitInstructionBuilder(). + SetReportContext(reportContext). + SetReport(report). + SetSignatures(signatures). + SetConfigAccount(config). + SetChainStateAccount(chainState). + SetCommitReportAccount(commitReport). + SetAuthorityAccount(authority). + SetSystemProgramAccount(systemProgram). + SetSysvarInstructionsAccount(sysvarInstructions) +} diff --git a/core/capabilities/ccip/ccipsolana/ccip_router/Commit_test.go b/core/capabilities/ccip/ccipsolana/ccip_router/Commit_test.go new file mode 100644 index 00000000000..fcaf33cc942 --- /dev/null +++ b/core/capabilities/ccip/ccipsolana/ccip_router/Commit_test.go @@ -0,0 +1,32 @@ +// Code generated by https://github.com/gagliardetto/anchor-go. DO NOT EDIT. + +package ccip_router + +import ( + "bytes" + ag_gofuzz "github.com/gagliardetto/gofuzz" + ag_require "github.com/stretchr/testify/require" + "strconv" + "testing" +) + +func TestEncodeDecode_Commit(t *testing.T) { + fu := ag_gofuzz.New().NilChance(0) + for i := 0; i < 1; i++ { + t.Run("Commit"+strconv.Itoa(i), func(t *testing.T) { + { + params := new(Commit) + fu.Fuzz(params) + params.AccountMetaSlice = nil + buf := new(bytes.Buffer) + err := encodeT(*params, buf) + ag_require.NoError(t, err) + got := new(Commit) + err = decodeT(got, buf.Bytes()) + got.AccountMetaSlice = nil + ag_require.NoError(t, err) + ag_require.Equal(t, params, got) + } + }) + } +} diff --git a/core/capabilities/ccip/ccipsolana/ccip_router/DisableChainSelector.go b/core/capabilities/ccip/ccipsolana/ccip_router/DisableChainSelector.go new file mode 100644 index 00000000000..772c3391061 --- /dev/null +++ b/core/capabilities/ccip/ccipsolana/ccip_router/DisableChainSelector.go @@ -0,0 +1,184 @@ +// Code generated by https://github.com/gagliardetto/anchor-go. DO NOT EDIT. + +package ccip_router + +import ( + "errors" + ag_binary "github.com/gagliardetto/binary" + ag_solanago "github.com/gagliardetto/solana-go" + ag_format "github.com/gagliardetto/solana-go/text/format" + ag_treeout "github.com/gagliardetto/treeout" +) + +// The Admin is the only one able to enable or disable the chain selector +type DisableChainSelector struct { + NewChainSelector *uint64 + + // [0] = [WRITE] chainState + // + // [1] = [] config + // + // [2] = [WRITE, SIGNER] authority + // + // [3] = [] systemProgram + ag_solanago.AccountMetaSlice `bin:"-" borsh_skip:"true"` +} + +// NewDisableChainSelectorInstructionBuilder creates a new `DisableChainSelector` instruction builder. +func NewDisableChainSelectorInstructionBuilder() *DisableChainSelector { + nd := &DisableChainSelector{ + AccountMetaSlice: make(ag_solanago.AccountMetaSlice, 4), + } + return nd +} + +// SetNewChainSelector sets the "newChainSelector" parameter. +func (inst *DisableChainSelector) SetNewChainSelector(newChainSelector uint64) *DisableChainSelector { + inst.NewChainSelector = &newChainSelector + return inst +} + +// SetChainStateAccount sets the "chainState" account. +func (inst *DisableChainSelector) SetChainStateAccount(chainState ag_solanago.PublicKey) *DisableChainSelector { + inst.AccountMetaSlice[0] = ag_solanago.Meta(chainState).WRITE() + return inst +} + +// GetChainStateAccount gets the "chainState" account. +func (inst *DisableChainSelector) GetChainStateAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[0] +} + +// SetConfigAccount sets the "config" account. +func (inst *DisableChainSelector) SetConfigAccount(config ag_solanago.PublicKey) *DisableChainSelector { + inst.AccountMetaSlice[1] = ag_solanago.Meta(config) + return inst +} + +// GetConfigAccount gets the "config" account. +func (inst *DisableChainSelector) GetConfigAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[1] +} + +// SetAuthorityAccount sets the "authority" account. +func (inst *DisableChainSelector) SetAuthorityAccount(authority ag_solanago.PublicKey) *DisableChainSelector { + inst.AccountMetaSlice[2] = ag_solanago.Meta(authority).WRITE().SIGNER() + return inst +} + +// GetAuthorityAccount gets the "authority" account. +func (inst *DisableChainSelector) GetAuthorityAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[2] +} + +// SetSystemProgramAccount sets the "systemProgram" account. +func (inst *DisableChainSelector) SetSystemProgramAccount(systemProgram ag_solanago.PublicKey) *DisableChainSelector { + inst.AccountMetaSlice[3] = ag_solanago.Meta(systemProgram) + return inst +} + +// GetSystemProgramAccount gets the "systemProgram" account. +func (inst *DisableChainSelector) GetSystemProgramAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[3] +} + +func (inst DisableChainSelector) Build() *Instruction { + return &Instruction{BaseVariant: ag_binary.BaseVariant{ + Impl: inst, + TypeID: Instruction_DisableChainSelector, + }} +} + +// ValidateAndBuild validates the instruction parameters and accounts; +// if there is a validation error, it returns the error. +// Otherwise, it builds and returns the instruction. +func (inst DisableChainSelector) ValidateAndBuild() (*Instruction, error) { + if err := inst.Validate(); err != nil { + return nil, err + } + return inst.Build(), nil +} + +func (inst *DisableChainSelector) Validate() error { + // Check whether all (required) parameters are set: + { + if inst.NewChainSelector == nil { + return errors.New("NewChainSelector parameter is not set") + } + } + + // Check whether all (required) accounts are set: + { + if inst.AccountMetaSlice[0] == nil { + return errors.New("accounts.ChainState is not set") + } + if inst.AccountMetaSlice[1] == nil { + return errors.New("accounts.Config is not set") + } + if inst.AccountMetaSlice[2] == nil { + return errors.New("accounts.Authority is not set") + } + if inst.AccountMetaSlice[3] == nil { + return errors.New("accounts.SystemProgram is not set") + } + } + return nil +} + +func (inst *DisableChainSelector) EncodeToTree(parent ag_treeout.Branches) { + parent.Child(ag_format.Program(ProgramName, ProgramID)). + // + ParentFunc(func(programBranch ag_treeout.Branches) { + programBranch.Child(ag_format.Instruction("DisableChainSelector")). + // + ParentFunc(func(instructionBranch ag_treeout.Branches) { + + // Parameters of the instruction: + instructionBranch.Child("Params[len=1]").ParentFunc(func(paramsBranch ag_treeout.Branches) { + paramsBranch.Child(ag_format.Param("NewChainSelector", *inst.NewChainSelector)) + }) + + // Accounts of the instruction: + instructionBranch.Child("Accounts[len=4]").ParentFunc(func(accountsBranch ag_treeout.Branches) { + accountsBranch.Child(ag_format.Meta(" chainState", inst.AccountMetaSlice[0])) + accountsBranch.Child(ag_format.Meta(" config", inst.AccountMetaSlice[1])) + accountsBranch.Child(ag_format.Meta(" authority", inst.AccountMetaSlice[2])) + accountsBranch.Child(ag_format.Meta("systemProgram", inst.AccountMetaSlice[3])) + }) + }) + }) +} + +func (obj DisableChainSelector) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { + // Serialize `NewChainSelector` param: + err = encoder.Encode(obj.NewChainSelector) + if err != nil { + return err + } + return nil +} +func (obj *DisableChainSelector) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { + // Deserialize `NewChainSelector`: + err = decoder.Decode(&obj.NewChainSelector) + if err != nil { + return err + } + return nil +} + +// NewDisableChainSelectorInstruction declares a new DisableChainSelector instruction with the provided parameters and accounts. +func NewDisableChainSelectorInstruction( + // Parameters: + newChainSelector uint64, + // Accounts: + chainState ag_solanago.PublicKey, + config ag_solanago.PublicKey, + authority ag_solanago.PublicKey, + systemProgram ag_solanago.PublicKey) *DisableChainSelector { + return NewDisableChainSelectorInstructionBuilder(). + SetNewChainSelector(newChainSelector). + SetChainStateAccount(chainState). + SetConfigAccount(config). + SetAuthorityAccount(authority). + SetSystemProgramAccount(systemProgram) +} diff --git a/core/capabilities/ccip/ccipsolana/ccip_router/DisableChainSelector_test.go b/core/capabilities/ccip/ccipsolana/ccip_router/DisableChainSelector_test.go new file mode 100644 index 00000000000..6d4d01c9feb --- /dev/null +++ b/core/capabilities/ccip/ccipsolana/ccip_router/DisableChainSelector_test.go @@ -0,0 +1,32 @@ +// Code generated by https://github.com/gagliardetto/anchor-go. DO NOT EDIT. + +package ccip_router + +import ( + "bytes" + ag_gofuzz "github.com/gagliardetto/gofuzz" + ag_require "github.com/stretchr/testify/require" + "strconv" + "testing" +) + +func TestEncodeDecode_DisableChainSelector(t *testing.T) { + fu := ag_gofuzz.New().NilChance(0) + for i := 0; i < 1; i++ { + t.Run("DisableChainSelector"+strconv.Itoa(i), func(t *testing.T) { + { + params := new(DisableChainSelector) + fu.Fuzz(params) + params.AccountMetaSlice = nil + buf := new(bytes.Buffer) + err := encodeT(*params, buf) + ag_require.NoError(t, err) + got := new(DisableChainSelector) + err = decodeT(got, buf.Bytes()) + got.AccountMetaSlice = nil + ag_require.NoError(t, err) + ag_require.Equal(t, params, got) + } + }) + } +} diff --git a/core/capabilities/ccip/ccipsolana/ccip_router/EnableChainSelector.go b/core/capabilities/ccip/ccipsolana/ccip_router/EnableChainSelector.go new file mode 100644 index 00000000000..b3b45bb7f91 --- /dev/null +++ b/core/capabilities/ccip/ccipsolana/ccip_router/EnableChainSelector.go @@ -0,0 +1,184 @@ +// Code generated by https://github.com/gagliardetto/anchor-go. DO NOT EDIT. + +package ccip_router + +import ( + "errors" + ag_binary "github.com/gagliardetto/binary" + ag_solanago "github.com/gagliardetto/solana-go" + ag_format "github.com/gagliardetto/solana-go/text/format" + ag_treeout "github.com/gagliardetto/treeout" +) + +// The Admin is the only one able to enable or disable the chain selector +type EnableChainSelector struct { + NewChainSelector *uint64 + + // [0] = [WRITE] chainState + // + // [1] = [] config + // + // [2] = [WRITE, SIGNER] authority + // + // [3] = [] systemProgram + ag_solanago.AccountMetaSlice `bin:"-" borsh_skip:"true"` +} + +// NewEnableChainSelectorInstructionBuilder creates a new `EnableChainSelector` instruction builder. +func NewEnableChainSelectorInstructionBuilder() *EnableChainSelector { + nd := &EnableChainSelector{ + AccountMetaSlice: make(ag_solanago.AccountMetaSlice, 4), + } + return nd +} + +// SetNewChainSelector sets the "newChainSelector" parameter. +func (inst *EnableChainSelector) SetNewChainSelector(newChainSelector uint64) *EnableChainSelector { + inst.NewChainSelector = &newChainSelector + return inst +} + +// SetChainStateAccount sets the "chainState" account. +func (inst *EnableChainSelector) SetChainStateAccount(chainState ag_solanago.PublicKey) *EnableChainSelector { + inst.AccountMetaSlice[0] = ag_solanago.Meta(chainState).WRITE() + return inst +} + +// GetChainStateAccount gets the "chainState" account. +func (inst *EnableChainSelector) GetChainStateAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[0] +} + +// SetConfigAccount sets the "config" account. +func (inst *EnableChainSelector) SetConfigAccount(config ag_solanago.PublicKey) *EnableChainSelector { + inst.AccountMetaSlice[1] = ag_solanago.Meta(config) + return inst +} + +// GetConfigAccount gets the "config" account. +func (inst *EnableChainSelector) GetConfigAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[1] +} + +// SetAuthorityAccount sets the "authority" account. +func (inst *EnableChainSelector) SetAuthorityAccount(authority ag_solanago.PublicKey) *EnableChainSelector { + inst.AccountMetaSlice[2] = ag_solanago.Meta(authority).WRITE().SIGNER() + return inst +} + +// GetAuthorityAccount gets the "authority" account. +func (inst *EnableChainSelector) GetAuthorityAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[2] +} + +// SetSystemProgramAccount sets the "systemProgram" account. +func (inst *EnableChainSelector) SetSystemProgramAccount(systemProgram ag_solanago.PublicKey) *EnableChainSelector { + inst.AccountMetaSlice[3] = ag_solanago.Meta(systemProgram) + return inst +} + +// GetSystemProgramAccount gets the "systemProgram" account. +func (inst *EnableChainSelector) GetSystemProgramAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[3] +} + +func (inst EnableChainSelector) Build() *Instruction { + return &Instruction{BaseVariant: ag_binary.BaseVariant{ + Impl: inst, + TypeID: Instruction_EnableChainSelector, + }} +} + +// ValidateAndBuild validates the instruction parameters and accounts; +// if there is a validation error, it returns the error. +// Otherwise, it builds and returns the instruction. +func (inst EnableChainSelector) ValidateAndBuild() (*Instruction, error) { + if err := inst.Validate(); err != nil { + return nil, err + } + return inst.Build(), nil +} + +func (inst *EnableChainSelector) Validate() error { + // Check whether all (required) parameters are set: + { + if inst.NewChainSelector == nil { + return errors.New("NewChainSelector parameter is not set") + } + } + + // Check whether all (required) accounts are set: + { + if inst.AccountMetaSlice[0] == nil { + return errors.New("accounts.ChainState is not set") + } + if inst.AccountMetaSlice[1] == nil { + return errors.New("accounts.Config is not set") + } + if inst.AccountMetaSlice[2] == nil { + return errors.New("accounts.Authority is not set") + } + if inst.AccountMetaSlice[3] == nil { + return errors.New("accounts.SystemProgram is not set") + } + } + return nil +} + +func (inst *EnableChainSelector) EncodeToTree(parent ag_treeout.Branches) { + parent.Child(ag_format.Program(ProgramName, ProgramID)). + // + ParentFunc(func(programBranch ag_treeout.Branches) { + programBranch.Child(ag_format.Instruction("EnableChainSelector")). + // + ParentFunc(func(instructionBranch ag_treeout.Branches) { + + // Parameters of the instruction: + instructionBranch.Child("Params[len=1]").ParentFunc(func(paramsBranch ag_treeout.Branches) { + paramsBranch.Child(ag_format.Param("NewChainSelector", *inst.NewChainSelector)) + }) + + // Accounts of the instruction: + instructionBranch.Child("Accounts[len=4]").ParentFunc(func(accountsBranch ag_treeout.Branches) { + accountsBranch.Child(ag_format.Meta(" chainState", inst.AccountMetaSlice[0])) + accountsBranch.Child(ag_format.Meta(" config", inst.AccountMetaSlice[1])) + accountsBranch.Child(ag_format.Meta(" authority", inst.AccountMetaSlice[2])) + accountsBranch.Child(ag_format.Meta("systemProgram", inst.AccountMetaSlice[3])) + }) + }) + }) +} + +func (obj EnableChainSelector) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { + // Serialize `NewChainSelector` param: + err = encoder.Encode(obj.NewChainSelector) + if err != nil { + return err + } + return nil +} +func (obj *EnableChainSelector) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { + // Deserialize `NewChainSelector`: + err = decoder.Decode(&obj.NewChainSelector) + if err != nil { + return err + } + return nil +} + +// NewEnableChainSelectorInstruction declares a new EnableChainSelector instruction with the provided parameters and accounts. +func NewEnableChainSelectorInstruction( + // Parameters: + newChainSelector uint64, + // Accounts: + chainState ag_solanago.PublicKey, + config ag_solanago.PublicKey, + authority ag_solanago.PublicKey, + systemProgram ag_solanago.PublicKey) *EnableChainSelector { + return NewEnableChainSelectorInstructionBuilder(). + SetNewChainSelector(newChainSelector). + SetChainStateAccount(chainState). + SetConfigAccount(config). + SetAuthorityAccount(authority). + SetSystemProgramAccount(systemProgram) +} diff --git a/core/capabilities/ccip/ccipsolana/ccip_router/EnableChainSelector_test.go b/core/capabilities/ccip/ccipsolana/ccip_router/EnableChainSelector_test.go new file mode 100644 index 00000000000..f14c09f534a --- /dev/null +++ b/core/capabilities/ccip/ccipsolana/ccip_router/EnableChainSelector_test.go @@ -0,0 +1,32 @@ +// Code generated by https://github.com/gagliardetto/anchor-go. DO NOT EDIT. + +package ccip_router + +import ( + "bytes" + ag_gofuzz "github.com/gagliardetto/gofuzz" + ag_require "github.com/stretchr/testify/require" + "strconv" + "testing" +) + +func TestEncodeDecode_EnableChainSelector(t *testing.T) { + fu := ag_gofuzz.New().NilChance(0) + for i := 0; i < 1; i++ { + t.Run("EnableChainSelector"+strconv.Itoa(i), func(t *testing.T) { + { + params := new(EnableChainSelector) + fu.Fuzz(params) + params.AccountMetaSlice = nil + buf := new(bytes.Buffer) + err := encodeT(*params, buf) + ag_require.NoError(t, err) + got := new(EnableChainSelector) + err = decodeT(got, buf.Bytes()) + got.AccountMetaSlice = nil + ag_require.NoError(t, err) + ag_require.Equal(t, params, got) + } + }) + } +} diff --git a/core/capabilities/ccip/ccipsolana/ccip_router/Execute.go b/core/capabilities/ccip/ccipsolana/ccip_router/Execute.go new file mode 100644 index 00000000000..5ed3628dd1f --- /dev/null +++ b/core/capabilities/ccip/ccipsolana/ccip_router/Execute.go @@ -0,0 +1,293 @@ +// Code generated by https://github.com/gagliardetto/anchor-go. DO NOT EDIT. + +package ccip_router + +import ( + "errors" + ag_binary "github.com/gagliardetto/binary" + ag_solanago "github.com/gagliardetto/solana-go" + ag_format "github.com/gagliardetto/solana-go/text/format" + ag_treeout "github.com/gagliardetto/treeout" +) + +// OFF RAMP FLOW +// +// The method name needs to be execute with Anchor encoding. +// +// This function is called by the OffChain when executing one Report to the Solana Router. +// In this Flow only one message is sent, the Execution Report. This is different as EVM does, +// this is because there is no try/catch mechanism to allow batch execution. +// This message validates that the Merkle Tree Proof of the given message is correct and is stored in the Commit Report Account. +// The message must be untouched to be executed. +// This message emits the event ExecutionStateChanged with the new state of the message. +// Finally, executes the CPI instruction to the receiver program in the ccip_receive message. +type Execute struct { + ExecutionReport *ExecutionReportSingleChain + ReportContext *[3][32]uint8 + + // [0] = [] config + // + // [1] = [] chainState + // + // [2] = [WRITE] commitReport + // + // [3] = [] externalExecutionConfig + // + // [4] = [WRITE, SIGNER] authority + // + // [5] = [] systemProgram + // + // [6] = [] sysvarInstructions + // + // [7] = [] tokenPoolsSigner + ag_solanago.AccountMetaSlice `bin:"-" borsh_skip:"true"` +} + +// NewExecuteInstructionBuilder creates a new `Execute` instruction builder. +func NewExecuteInstructionBuilder() *Execute { + nd := &Execute{ + AccountMetaSlice: make(ag_solanago.AccountMetaSlice, 8), + } + return nd +} + +// SetExecutionReport sets the "executionReport" parameter. +func (inst *Execute) SetExecutionReport(executionReport ExecutionReportSingleChain) *Execute { + inst.ExecutionReport = &executionReport + return inst +} + +// SetReportContext sets the "reportContext" parameter. +func (inst *Execute) SetReportContext(reportContext [3][32]uint8) *Execute { + inst.ReportContext = &reportContext + return inst +} + +// SetConfigAccount sets the "config" account. +func (inst *Execute) SetConfigAccount(config ag_solanago.PublicKey) *Execute { + inst.AccountMetaSlice[0] = ag_solanago.Meta(config) + return inst +} + +// GetConfigAccount gets the "config" account. +func (inst *Execute) GetConfigAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[0] +} + +// SetChainStateAccount sets the "chainState" account. +func (inst *Execute) SetChainStateAccount(chainState ag_solanago.PublicKey) *Execute { + inst.AccountMetaSlice[1] = ag_solanago.Meta(chainState) + return inst +} + +// GetChainStateAccount gets the "chainState" account. +func (inst *Execute) GetChainStateAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[1] +} + +// SetCommitReportAccount sets the "commitReport" account. +func (inst *Execute) SetCommitReportAccount(commitReport ag_solanago.PublicKey) *Execute { + inst.AccountMetaSlice[2] = ag_solanago.Meta(commitReport).WRITE() + return inst +} + +// GetCommitReportAccount gets the "commitReport" account. +func (inst *Execute) GetCommitReportAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[2] +} + +// SetExternalExecutionConfigAccount sets the "externalExecutionConfig" account. +func (inst *Execute) SetExternalExecutionConfigAccount(externalExecutionConfig ag_solanago.PublicKey) *Execute { + inst.AccountMetaSlice[3] = ag_solanago.Meta(externalExecutionConfig) + return inst +} + +// GetExternalExecutionConfigAccount gets the "externalExecutionConfig" account. +func (inst *Execute) GetExternalExecutionConfigAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[3] +} + +// SetAuthorityAccount sets the "authority" account. +func (inst *Execute) SetAuthorityAccount(authority ag_solanago.PublicKey) *Execute { + inst.AccountMetaSlice[4] = ag_solanago.Meta(authority).WRITE().SIGNER() + return inst +} + +// GetAuthorityAccount gets the "authority" account. +func (inst *Execute) GetAuthorityAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[4] +} + +// SetSystemProgramAccount sets the "systemProgram" account. +func (inst *Execute) SetSystemProgramAccount(systemProgram ag_solanago.PublicKey) *Execute { + inst.AccountMetaSlice[5] = ag_solanago.Meta(systemProgram) + return inst +} + +// GetSystemProgramAccount gets the "systemProgram" account. +func (inst *Execute) GetSystemProgramAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[5] +} + +// SetSysvarInstructionsAccount sets the "sysvarInstructions" account. +func (inst *Execute) SetSysvarInstructionsAccount(sysvarInstructions ag_solanago.PublicKey) *Execute { + inst.AccountMetaSlice[6] = ag_solanago.Meta(sysvarInstructions) + return inst +} + +// GetSysvarInstructionsAccount gets the "sysvarInstructions" account. +func (inst *Execute) GetSysvarInstructionsAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[6] +} + +// SetTokenPoolsSignerAccount sets the "tokenPoolsSigner" account. +func (inst *Execute) SetTokenPoolsSignerAccount(tokenPoolsSigner ag_solanago.PublicKey) *Execute { + inst.AccountMetaSlice[7] = ag_solanago.Meta(tokenPoolsSigner) + return inst +} + +// GetTokenPoolsSignerAccount gets the "tokenPoolsSigner" account. +func (inst *Execute) GetTokenPoolsSignerAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[7] +} + +func (inst Execute) Build() *Instruction { + return &Instruction{BaseVariant: ag_binary.BaseVariant{ + Impl: inst, + TypeID: Instruction_Execute, + }} +} + +// ValidateAndBuild validates the instruction parameters and accounts; +// if there is a validation error, it returns the error. +// Otherwise, it builds and returns the instruction. +func (inst Execute) ValidateAndBuild() (*Instruction, error) { + if err := inst.Validate(); err != nil { + return nil, err + } + return inst.Build(), nil +} + +func (inst *Execute) Validate() error { + // Check whether all (required) parameters are set: + { + if inst.ExecutionReport == nil { + return errors.New("ExecutionReport parameter is not set") + } + if inst.ReportContext == nil { + return errors.New("ReportContext parameter is not set") + } + } + + // Check whether all (required) accounts are set: + { + if inst.AccountMetaSlice[0] == nil { + return errors.New("accounts.Config is not set") + } + if inst.AccountMetaSlice[1] == nil { + return errors.New("accounts.ChainState is not set") + } + if inst.AccountMetaSlice[2] == nil { + return errors.New("accounts.CommitReport is not set") + } + if inst.AccountMetaSlice[3] == nil { + return errors.New("accounts.ExternalExecutionConfig is not set") + } + if inst.AccountMetaSlice[4] == nil { + return errors.New("accounts.Authority is not set") + } + if inst.AccountMetaSlice[5] == nil { + return errors.New("accounts.SystemProgram is not set") + } + if inst.AccountMetaSlice[6] == nil { + return errors.New("accounts.SysvarInstructions is not set") + } + if inst.AccountMetaSlice[7] == nil { + return errors.New("accounts.TokenPoolsSigner is not set") + } + } + return nil +} + +func (inst *Execute) EncodeToTree(parent ag_treeout.Branches) { + parent.Child(ag_format.Program(ProgramName, ProgramID)). + // + ParentFunc(func(programBranch ag_treeout.Branches) { + programBranch.Child(ag_format.Instruction("Execute")). + // + ParentFunc(func(instructionBranch ag_treeout.Branches) { + + // Parameters of the instruction: + instructionBranch.Child("Params[len=2]").ParentFunc(func(paramsBranch ag_treeout.Branches) { + paramsBranch.Child(ag_format.Param("ExecutionReport", *inst.ExecutionReport)) + paramsBranch.Child(ag_format.Param(" ReportContext", *inst.ReportContext)) + }) + + // Accounts of the instruction: + instructionBranch.Child("Accounts[len=8]").ParentFunc(func(accountsBranch ag_treeout.Branches) { + accountsBranch.Child(ag_format.Meta(" config", inst.AccountMetaSlice[0])) + accountsBranch.Child(ag_format.Meta(" chainState", inst.AccountMetaSlice[1])) + accountsBranch.Child(ag_format.Meta(" commitReport", inst.AccountMetaSlice[2])) + accountsBranch.Child(ag_format.Meta("externalExecutionConfig", inst.AccountMetaSlice[3])) + accountsBranch.Child(ag_format.Meta(" authority", inst.AccountMetaSlice[4])) + accountsBranch.Child(ag_format.Meta(" systemProgram", inst.AccountMetaSlice[5])) + accountsBranch.Child(ag_format.Meta(" sysvarInstructions", inst.AccountMetaSlice[6])) + accountsBranch.Child(ag_format.Meta(" tokenPoolsSigner", inst.AccountMetaSlice[7])) + }) + }) + }) +} + +func (obj Execute) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { + // Serialize `ExecutionReport` param: + err = encoder.Encode(obj.ExecutionReport) + if err != nil { + return err + } + // Serialize `ReportContext` param: + err = encoder.Encode(obj.ReportContext) + if err != nil { + return err + } + return nil +} +func (obj *Execute) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { + // Deserialize `ExecutionReport`: + err = decoder.Decode(&obj.ExecutionReport) + if err != nil { + return err + } + // Deserialize `ReportContext`: + err = decoder.Decode(&obj.ReportContext) + if err != nil { + return err + } + return nil +} + +// NewExecuteInstruction declares a new Execute instruction with the provided parameters and accounts. +func NewExecuteInstruction( + // Parameters: + executionReport ExecutionReportSingleChain, + reportContext [3][32]uint8, + // Accounts: + config ag_solanago.PublicKey, + chainState ag_solanago.PublicKey, + commitReport ag_solanago.PublicKey, + externalExecutionConfig ag_solanago.PublicKey, + authority ag_solanago.PublicKey, + systemProgram ag_solanago.PublicKey, + sysvarInstructions ag_solanago.PublicKey, + tokenPoolsSigner ag_solanago.PublicKey) *Execute { + return NewExecuteInstructionBuilder(). + SetExecutionReport(executionReport). + SetReportContext(reportContext). + SetConfigAccount(config). + SetChainStateAccount(chainState). + SetCommitReportAccount(commitReport). + SetExternalExecutionConfigAccount(externalExecutionConfig). + SetAuthorityAccount(authority). + SetSystemProgramAccount(systemProgram). + SetSysvarInstructionsAccount(sysvarInstructions). + SetTokenPoolsSignerAccount(tokenPoolsSigner) +} diff --git a/core/capabilities/ccip/ccipsolana/ccip_router/Execute_test.go b/core/capabilities/ccip/ccipsolana/ccip_router/Execute_test.go new file mode 100644 index 00000000000..5c0f4d7b7ff --- /dev/null +++ b/core/capabilities/ccip/ccipsolana/ccip_router/Execute_test.go @@ -0,0 +1,32 @@ +// Code generated by https://github.com/gagliardetto/anchor-go. DO NOT EDIT. + +package ccip_router + +import ( + "bytes" + ag_gofuzz "github.com/gagliardetto/gofuzz" + ag_require "github.com/stretchr/testify/require" + "strconv" + "testing" +) + +func TestEncodeDecode_Execute(t *testing.T) { + fu := ag_gofuzz.New().NilChance(0) + for i := 0; i < 1; i++ { + t.Run("Execute"+strconv.Itoa(i), func(t *testing.T) { + { + params := new(Execute) + fu.Fuzz(params) + params.AccountMetaSlice = nil + buf := new(bytes.Buffer) + err := encodeT(*params, buf) + ag_require.NoError(t, err) + got := new(Execute) + err = decodeT(got, buf.Bytes()) + got.AccountMetaSlice = nil + ag_require.NoError(t, err) + ag_require.Equal(t, params, got) + } + }) + } +} diff --git a/core/capabilities/ccip/ccipsolana/ccip_router/Initialize.go b/core/capabilities/ccip/ccipsolana/ccip_router/Initialize.go new file mode 100644 index 00000000000..ed65234f3e7 --- /dev/null +++ b/core/capabilities/ccip/ccipsolana/ccip_router/Initialize.go @@ -0,0 +1,310 @@ +// Code generated by https://github.com/gagliardetto/anchor-go. DO NOT EDIT. + +package ccip_router + +import ( + "errors" + ag_binary "github.com/gagliardetto/binary" + ag_solanago "github.com/gagliardetto/solana-go" + ag_format "github.com/gagliardetto/solana-go/text/format" + ag_treeout "github.com/gagliardetto/treeout" +) + +// The initialization is responsibility of Admin, nothing more than calling this method should be done first. +type Initialize struct { + SolanaChainSelector *uint64 + DefaultGasLimit *ag_binary.Uint128 + DefaultAllowOutOfOrderExecution *bool + EnableExecutionAfter *int64 + + // [0] = [WRITE] config + // + // [1] = [WRITE, SIGNER] authority + // + // [2] = [] systemProgram + // + // [3] = [] program + // + // [4] = [] programData + // + // [5] = [WRITE] externalExecutionConfig + // + // [6] = [WRITE] tokenPoolsSigner + ag_solanago.AccountMetaSlice `bin:"-" borsh_skip:"true"` +} + +// NewInitializeInstructionBuilder creates a new `Initialize` instruction builder. +func NewInitializeInstructionBuilder() *Initialize { + nd := &Initialize{ + AccountMetaSlice: make(ag_solanago.AccountMetaSlice, 7), + } + return nd +} + +// SetSolanaChainSelector sets the "solanaChainSelector" parameter. +func (inst *Initialize) SetSolanaChainSelector(solanaChainSelector uint64) *Initialize { + inst.SolanaChainSelector = &solanaChainSelector + return inst +} + +// SetDefaultGasLimit sets the "defaultGasLimit" parameter. +func (inst *Initialize) SetDefaultGasLimit(defaultGasLimit ag_binary.Uint128) *Initialize { + inst.DefaultGasLimit = &defaultGasLimit + return inst +} + +// SetDefaultAllowOutOfOrderExecution sets the "defaultAllowOutOfOrderExecution" parameter. +func (inst *Initialize) SetDefaultAllowOutOfOrderExecution(defaultAllowOutOfOrderExecution bool) *Initialize { + inst.DefaultAllowOutOfOrderExecution = &defaultAllowOutOfOrderExecution + return inst +} + +// SetEnableExecutionAfter sets the "enableExecutionAfter" parameter. +func (inst *Initialize) SetEnableExecutionAfter(enableExecutionAfter int64) *Initialize { + inst.EnableExecutionAfter = &enableExecutionAfter + return inst +} + +// SetConfigAccount sets the "config" account. +func (inst *Initialize) SetConfigAccount(config ag_solanago.PublicKey) *Initialize { + inst.AccountMetaSlice[0] = ag_solanago.Meta(config).WRITE() + return inst +} + +// GetConfigAccount gets the "config" account. +func (inst *Initialize) GetConfigAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[0] +} + +// SetAuthorityAccount sets the "authority" account. +func (inst *Initialize) SetAuthorityAccount(authority ag_solanago.PublicKey) *Initialize { + inst.AccountMetaSlice[1] = ag_solanago.Meta(authority).WRITE().SIGNER() + return inst +} + +// GetAuthorityAccount gets the "authority" account. +func (inst *Initialize) GetAuthorityAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[1] +} + +// SetSystemProgramAccount sets the "systemProgram" account. +func (inst *Initialize) SetSystemProgramAccount(systemProgram ag_solanago.PublicKey) *Initialize { + inst.AccountMetaSlice[2] = ag_solanago.Meta(systemProgram) + return inst +} + +// GetSystemProgramAccount gets the "systemProgram" account. +func (inst *Initialize) GetSystemProgramAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[2] +} + +// SetProgramAccount sets the "program" account. +func (inst *Initialize) SetProgramAccount(program ag_solanago.PublicKey) *Initialize { + inst.AccountMetaSlice[3] = ag_solanago.Meta(program) + return inst +} + +// GetProgramAccount gets the "program" account. +func (inst *Initialize) GetProgramAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[3] +} + +// SetProgramDataAccount sets the "programData" account. +func (inst *Initialize) SetProgramDataAccount(programData ag_solanago.PublicKey) *Initialize { + inst.AccountMetaSlice[4] = ag_solanago.Meta(programData) + return inst +} + +// GetProgramDataAccount gets the "programData" account. +func (inst *Initialize) GetProgramDataAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[4] +} + +// SetExternalExecutionConfigAccount sets the "externalExecutionConfig" account. +func (inst *Initialize) SetExternalExecutionConfigAccount(externalExecutionConfig ag_solanago.PublicKey) *Initialize { + inst.AccountMetaSlice[5] = ag_solanago.Meta(externalExecutionConfig).WRITE() + return inst +} + +// GetExternalExecutionConfigAccount gets the "externalExecutionConfig" account. +func (inst *Initialize) GetExternalExecutionConfigAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[5] +} + +// SetTokenPoolsSignerAccount sets the "tokenPoolsSigner" account. +func (inst *Initialize) SetTokenPoolsSignerAccount(tokenPoolsSigner ag_solanago.PublicKey) *Initialize { + inst.AccountMetaSlice[6] = ag_solanago.Meta(tokenPoolsSigner).WRITE() + return inst +} + +// GetTokenPoolsSignerAccount gets the "tokenPoolsSigner" account. +func (inst *Initialize) GetTokenPoolsSignerAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[6] +} + +func (inst Initialize) Build() *Instruction { + return &Instruction{BaseVariant: ag_binary.BaseVariant{ + Impl: inst, + TypeID: Instruction_Initialize, + }} +} + +// ValidateAndBuild validates the instruction parameters and accounts; +// if there is a validation error, it returns the error. +// Otherwise, it builds and returns the instruction. +func (inst Initialize) ValidateAndBuild() (*Instruction, error) { + if err := inst.Validate(); err != nil { + return nil, err + } + return inst.Build(), nil +} + +func (inst *Initialize) Validate() error { + // Check whether all (required) parameters are set: + { + if inst.SolanaChainSelector == nil { + return errors.New("SolanaChainSelector parameter is not set") + } + if inst.DefaultGasLimit == nil { + return errors.New("DefaultGasLimit parameter is not set") + } + if inst.DefaultAllowOutOfOrderExecution == nil { + return errors.New("DefaultAllowOutOfOrderExecution parameter is not set") + } + if inst.EnableExecutionAfter == nil { + return errors.New("EnableExecutionAfter parameter is not set") + } + } + + // Check whether all (required) accounts are set: + { + if inst.AccountMetaSlice[0] == nil { + return errors.New("accounts.Config is not set") + } + if inst.AccountMetaSlice[1] == nil { + return errors.New("accounts.Authority is not set") + } + if inst.AccountMetaSlice[2] == nil { + return errors.New("accounts.SystemProgram is not set") + } + if inst.AccountMetaSlice[3] == nil { + return errors.New("accounts.Program is not set") + } + if inst.AccountMetaSlice[4] == nil { + return errors.New("accounts.ProgramData is not set") + } + if inst.AccountMetaSlice[5] == nil { + return errors.New("accounts.ExternalExecutionConfig is not set") + } + if inst.AccountMetaSlice[6] == nil { + return errors.New("accounts.TokenPoolsSigner is not set") + } + } + return nil +} + +func (inst *Initialize) EncodeToTree(parent ag_treeout.Branches) { + parent.Child(ag_format.Program(ProgramName, ProgramID)). + // + ParentFunc(func(programBranch ag_treeout.Branches) { + programBranch.Child(ag_format.Instruction("Initialize")). + // + ParentFunc(func(instructionBranch ag_treeout.Branches) { + + // Parameters of the instruction: + instructionBranch.Child("Params[len=4]").ParentFunc(func(paramsBranch ag_treeout.Branches) { + paramsBranch.Child(ag_format.Param(" SolanaChainSelector", *inst.SolanaChainSelector)) + paramsBranch.Child(ag_format.Param(" DefaultGasLimit", *inst.DefaultGasLimit)) + paramsBranch.Child(ag_format.Param("DefaultAllowOutOfOrderExecution", *inst.DefaultAllowOutOfOrderExecution)) + paramsBranch.Child(ag_format.Param(" EnableExecutionAfter", *inst.EnableExecutionAfter)) + }) + + // Accounts of the instruction: + instructionBranch.Child("Accounts[len=7]").ParentFunc(func(accountsBranch ag_treeout.Branches) { + accountsBranch.Child(ag_format.Meta(" config", inst.AccountMetaSlice[0])) + accountsBranch.Child(ag_format.Meta(" authority", inst.AccountMetaSlice[1])) + accountsBranch.Child(ag_format.Meta(" systemProgram", inst.AccountMetaSlice[2])) + accountsBranch.Child(ag_format.Meta(" program", inst.AccountMetaSlice[3])) + accountsBranch.Child(ag_format.Meta(" programData", inst.AccountMetaSlice[4])) + accountsBranch.Child(ag_format.Meta("externalExecutionConfig", inst.AccountMetaSlice[5])) + accountsBranch.Child(ag_format.Meta(" tokenPoolsSigner", inst.AccountMetaSlice[6])) + }) + }) + }) +} + +func (obj Initialize) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { + // Serialize `SolanaChainSelector` param: + err = encoder.Encode(obj.SolanaChainSelector) + if err != nil { + return err + } + // Serialize `DefaultGasLimit` param: + err = encoder.Encode(obj.DefaultGasLimit) + if err != nil { + return err + } + // Serialize `DefaultAllowOutOfOrderExecution` param: + err = encoder.Encode(obj.DefaultAllowOutOfOrderExecution) + if err != nil { + return err + } + // Serialize `EnableExecutionAfter` param: + err = encoder.Encode(obj.EnableExecutionAfter) + if err != nil { + return err + } + return nil +} +func (obj *Initialize) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { + // Deserialize `SolanaChainSelector`: + err = decoder.Decode(&obj.SolanaChainSelector) + if err != nil { + return err + } + // Deserialize `DefaultGasLimit`: + err = decoder.Decode(&obj.DefaultGasLimit) + if err != nil { + return err + } + // Deserialize `DefaultAllowOutOfOrderExecution`: + err = decoder.Decode(&obj.DefaultAllowOutOfOrderExecution) + if err != nil { + return err + } + // Deserialize `EnableExecutionAfter`: + err = decoder.Decode(&obj.EnableExecutionAfter) + if err != nil { + return err + } + return nil +} + +// NewInitializeInstruction declares a new Initialize instruction with the provided parameters and accounts. +func NewInitializeInstruction( + // Parameters: + solanaChainSelector uint64, + defaultGasLimit ag_binary.Uint128, + defaultAllowOutOfOrderExecution bool, + enableExecutionAfter int64, + // Accounts: + config ag_solanago.PublicKey, + authority ag_solanago.PublicKey, + systemProgram ag_solanago.PublicKey, + program ag_solanago.PublicKey, + programData ag_solanago.PublicKey, + externalExecutionConfig ag_solanago.PublicKey, + tokenPoolsSigner ag_solanago.PublicKey) *Initialize { + return NewInitializeInstructionBuilder(). + SetSolanaChainSelector(solanaChainSelector). + SetDefaultGasLimit(defaultGasLimit). + SetDefaultAllowOutOfOrderExecution(defaultAllowOutOfOrderExecution). + SetEnableExecutionAfter(enableExecutionAfter). + SetConfigAccount(config). + SetAuthorityAccount(authority). + SetSystemProgramAccount(systemProgram). + SetProgramAccount(program). + SetProgramDataAccount(programData). + SetExternalExecutionConfigAccount(externalExecutionConfig). + SetTokenPoolsSignerAccount(tokenPoolsSigner) +} diff --git a/core/capabilities/ccip/ccipsolana/ccip_router/Initialize_test.go b/core/capabilities/ccip/ccipsolana/ccip_router/Initialize_test.go new file mode 100644 index 00000000000..51eed3384b8 --- /dev/null +++ b/core/capabilities/ccip/ccipsolana/ccip_router/Initialize_test.go @@ -0,0 +1,32 @@ +// Code generated by https://github.com/gagliardetto/anchor-go. DO NOT EDIT. + +package ccip_router + +import ( + "bytes" + ag_gofuzz "github.com/gagliardetto/gofuzz" + ag_require "github.com/stretchr/testify/require" + "strconv" + "testing" +) + +func TestEncodeDecode_Initialize(t *testing.T) { + fu := ag_gofuzz.New().NilChance(0) + for i := 0; i < 1; i++ { + t.Run("Initialize"+strconv.Itoa(i), func(t *testing.T) { + { + params := new(Initialize) + fu.Fuzz(params) + params.AccountMetaSlice = nil + buf := new(bytes.Buffer) + err := encodeT(*params, buf) + ag_require.NoError(t, err) + got := new(Initialize) + err = decodeT(got, buf.Bytes()) + got.AccountMetaSlice = nil + ag_require.NoError(t, err) + ag_require.Equal(t, params, got) + } + }) + } +} diff --git a/core/capabilities/ccip/ccipsolana/ccip_router/ManuallyExecute.go b/core/capabilities/ccip/ccipsolana/ccip_router/ManuallyExecute.go new file mode 100644 index 00000000000..7ec00306a8f --- /dev/null +++ b/core/capabilities/ccip/ccipsolana/ccip_router/ManuallyExecute.go @@ -0,0 +1,261 @@ +// Code generated by https://github.com/gagliardetto/anchor-go. DO NOT EDIT. + +package ccip_router + +import ( + "errors" + ag_binary "github.com/gagliardetto/binary" + ag_solanago "github.com/gagliardetto/solana-go" + ag_format "github.com/gagliardetto/solana-go/text/format" + ag_treeout "github.com/gagliardetto/treeout" +) + +// When a message is not being executed, then the user can trigger the execution manually. +// No verification over the transmitter, but the message needs to be in some commit report. +type ManuallyExecute struct { + ExecutionReport *ExecutionReportSingleChain + + // [0] = [] config + // + // [1] = [] chainState + // + // [2] = [WRITE] commitReport + // + // [3] = [] externalExecutionConfig + // + // [4] = [WRITE, SIGNER] authority + // + // [5] = [] systemProgram + // + // [6] = [] sysvarInstructions + // + // [7] = [] tokenPoolsSigner + ag_solanago.AccountMetaSlice `bin:"-" borsh_skip:"true"` +} + +// NewManuallyExecuteInstructionBuilder creates a new `ManuallyExecute` instruction builder. +func NewManuallyExecuteInstructionBuilder() *ManuallyExecute { + nd := &ManuallyExecute{ + AccountMetaSlice: make(ag_solanago.AccountMetaSlice, 8), + } + return nd +} + +// SetExecutionReport sets the "executionReport" parameter. +func (inst *ManuallyExecute) SetExecutionReport(executionReport ExecutionReportSingleChain) *ManuallyExecute { + inst.ExecutionReport = &executionReport + return inst +} + +// SetConfigAccount sets the "config" account. +func (inst *ManuallyExecute) SetConfigAccount(config ag_solanago.PublicKey) *ManuallyExecute { + inst.AccountMetaSlice[0] = ag_solanago.Meta(config) + return inst +} + +// GetConfigAccount gets the "config" account. +func (inst *ManuallyExecute) GetConfigAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[0] +} + +// SetChainStateAccount sets the "chainState" account. +func (inst *ManuallyExecute) SetChainStateAccount(chainState ag_solanago.PublicKey) *ManuallyExecute { + inst.AccountMetaSlice[1] = ag_solanago.Meta(chainState) + return inst +} + +// GetChainStateAccount gets the "chainState" account. +func (inst *ManuallyExecute) GetChainStateAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[1] +} + +// SetCommitReportAccount sets the "commitReport" account. +func (inst *ManuallyExecute) SetCommitReportAccount(commitReport ag_solanago.PublicKey) *ManuallyExecute { + inst.AccountMetaSlice[2] = ag_solanago.Meta(commitReport).WRITE() + return inst +} + +// GetCommitReportAccount gets the "commitReport" account. +func (inst *ManuallyExecute) GetCommitReportAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[2] +} + +// SetExternalExecutionConfigAccount sets the "externalExecutionConfig" account. +func (inst *ManuallyExecute) SetExternalExecutionConfigAccount(externalExecutionConfig ag_solanago.PublicKey) *ManuallyExecute { + inst.AccountMetaSlice[3] = ag_solanago.Meta(externalExecutionConfig) + return inst +} + +// GetExternalExecutionConfigAccount gets the "externalExecutionConfig" account. +func (inst *ManuallyExecute) GetExternalExecutionConfigAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[3] +} + +// SetAuthorityAccount sets the "authority" account. +func (inst *ManuallyExecute) SetAuthorityAccount(authority ag_solanago.PublicKey) *ManuallyExecute { + inst.AccountMetaSlice[4] = ag_solanago.Meta(authority).WRITE().SIGNER() + return inst +} + +// GetAuthorityAccount gets the "authority" account. +func (inst *ManuallyExecute) GetAuthorityAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[4] +} + +// SetSystemProgramAccount sets the "systemProgram" account. +func (inst *ManuallyExecute) SetSystemProgramAccount(systemProgram ag_solanago.PublicKey) *ManuallyExecute { + inst.AccountMetaSlice[5] = ag_solanago.Meta(systemProgram) + return inst +} + +// GetSystemProgramAccount gets the "systemProgram" account. +func (inst *ManuallyExecute) GetSystemProgramAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[5] +} + +// SetSysvarInstructionsAccount sets the "sysvarInstructions" account. +func (inst *ManuallyExecute) SetSysvarInstructionsAccount(sysvarInstructions ag_solanago.PublicKey) *ManuallyExecute { + inst.AccountMetaSlice[6] = ag_solanago.Meta(sysvarInstructions) + return inst +} + +// GetSysvarInstructionsAccount gets the "sysvarInstructions" account. +func (inst *ManuallyExecute) GetSysvarInstructionsAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[6] +} + +// SetTokenPoolsSignerAccount sets the "tokenPoolsSigner" account. +func (inst *ManuallyExecute) SetTokenPoolsSignerAccount(tokenPoolsSigner ag_solanago.PublicKey) *ManuallyExecute { + inst.AccountMetaSlice[7] = ag_solanago.Meta(tokenPoolsSigner) + return inst +} + +// GetTokenPoolsSignerAccount gets the "tokenPoolsSigner" account. +func (inst *ManuallyExecute) GetTokenPoolsSignerAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[7] +} + +func (inst ManuallyExecute) Build() *Instruction { + return &Instruction{BaseVariant: ag_binary.BaseVariant{ + Impl: inst, + TypeID: Instruction_ManuallyExecute, + }} +} + +// ValidateAndBuild validates the instruction parameters and accounts; +// if there is a validation error, it returns the error. +// Otherwise, it builds and returns the instruction. +func (inst ManuallyExecute) ValidateAndBuild() (*Instruction, error) { + if err := inst.Validate(); err != nil { + return nil, err + } + return inst.Build(), nil +} + +func (inst *ManuallyExecute) Validate() error { + // Check whether all (required) parameters are set: + { + if inst.ExecutionReport == nil { + return errors.New("ExecutionReport parameter is not set") + } + } + + // Check whether all (required) accounts are set: + { + if inst.AccountMetaSlice[0] == nil { + return errors.New("accounts.Config is not set") + } + if inst.AccountMetaSlice[1] == nil { + return errors.New("accounts.ChainState is not set") + } + if inst.AccountMetaSlice[2] == nil { + return errors.New("accounts.CommitReport is not set") + } + if inst.AccountMetaSlice[3] == nil { + return errors.New("accounts.ExternalExecutionConfig is not set") + } + if inst.AccountMetaSlice[4] == nil { + return errors.New("accounts.Authority is not set") + } + if inst.AccountMetaSlice[5] == nil { + return errors.New("accounts.SystemProgram is not set") + } + if inst.AccountMetaSlice[6] == nil { + return errors.New("accounts.SysvarInstructions is not set") + } + if inst.AccountMetaSlice[7] == nil { + return errors.New("accounts.TokenPoolsSigner is not set") + } + } + return nil +} + +func (inst *ManuallyExecute) EncodeToTree(parent ag_treeout.Branches) { + parent.Child(ag_format.Program(ProgramName, ProgramID)). + // + ParentFunc(func(programBranch ag_treeout.Branches) { + programBranch.Child(ag_format.Instruction("ManuallyExecute")). + // + ParentFunc(func(instructionBranch ag_treeout.Branches) { + + // Parameters of the instruction: + instructionBranch.Child("Params[len=1]").ParentFunc(func(paramsBranch ag_treeout.Branches) { + paramsBranch.Child(ag_format.Param("ExecutionReport", *inst.ExecutionReport)) + }) + + // Accounts of the instruction: + instructionBranch.Child("Accounts[len=8]").ParentFunc(func(accountsBranch ag_treeout.Branches) { + accountsBranch.Child(ag_format.Meta(" config", inst.AccountMetaSlice[0])) + accountsBranch.Child(ag_format.Meta(" chainState", inst.AccountMetaSlice[1])) + accountsBranch.Child(ag_format.Meta(" commitReport", inst.AccountMetaSlice[2])) + accountsBranch.Child(ag_format.Meta("externalExecutionConfig", inst.AccountMetaSlice[3])) + accountsBranch.Child(ag_format.Meta(" authority", inst.AccountMetaSlice[4])) + accountsBranch.Child(ag_format.Meta(" systemProgram", inst.AccountMetaSlice[5])) + accountsBranch.Child(ag_format.Meta(" sysvarInstructions", inst.AccountMetaSlice[6])) + accountsBranch.Child(ag_format.Meta(" tokenPoolsSigner", inst.AccountMetaSlice[7])) + }) + }) + }) +} + +func (obj ManuallyExecute) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { + // Serialize `ExecutionReport` param: + err = encoder.Encode(obj.ExecutionReport) + if err != nil { + return err + } + return nil +} +func (obj *ManuallyExecute) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { + // Deserialize `ExecutionReport`: + err = decoder.Decode(&obj.ExecutionReport) + if err != nil { + return err + } + return nil +} + +// NewManuallyExecuteInstruction declares a new ManuallyExecute instruction with the provided parameters and accounts. +func NewManuallyExecuteInstruction( + // Parameters: + executionReport ExecutionReportSingleChain, + // Accounts: + config ag_solanago.PublicKey, + chainState ag_solanago.PublicKey, + commitReport ag_solanago.PublicKey, + externalExecutionConfig ag_solanago.PublicKey, + authority ag_solanago.PublicKey, + systemProgram ag_solanago.PublicKey, + sysvarInstructions ag_solanago.PublicKey, + tokenPoolsSigner ag_solanago.PublicKey) *ManuallyExecute { + return NewManuallyExecuteInstructionBuilder(). + SetExecutionReport(executionReport). + SetConfigAccount(config). + SetChainStateAccount(chainState). + SetCommitReportAccount(commitReport). + SetExternalExecutionConfigAccount(externalExecutionConfig). + SetAuthorityAccount(authority). + SetSystemProgramAccount(systemProgram). + SetSysvarInstructionsAccount(sysvarInstructions). + SetTokenPoolsSignerAccount(tokenPoolsSigner) +} diff --git a/core/capabilities/ccip/ccipsolana/ccip_router/ManuallyExecute_test.go b/core/capabilities/ccip/ccipsolana/ccip_router/ManuallyExecute_test.go new file mode 100644 index 00000000000..38f8fe33c61 --- /dev/null +++ b/core/capabilities/ccip/ccipsolana/ccip_router/ManuallyExecute_test.go @@ -0,0 +1,32 @@ +// Code generated by https://github.com/gagliardetto/anchor-go. DO NOT EDIT. + +package ccip_router + +import ( + "bytes" + ag_gofuzz "github.com/gagliardetto/gofuzz" + ag_require "github.com/stretchr/testify/require" + "strconv" + "testing" +) + +func TestEncodeDecode_ManuallyExecute(t *testing.T) { + fu := ag_gofuzz.New().NilChance(0) + for i := 0; i < 1; i++ { + t.Run("ManuallyExecute"+strconv.Itoa(i), func(t *testing.T) { + { + params := new(ManuallyExecute) + fu.Fuzz(params) + params.AccountMetaSlice = nil + buf := new(bytes.Buffer) + err := encodeT(*params, buf) + ag_require.NoError(t, err) + got := new(ManuallyExecute) + err = decodeT(got, buf.Bytes()) + got.AccountMetaSlice = nil + ag_require.NoError(t, err) + ag_require.Equal(t, params, got) + } + }) + } +} diff --git a/core/capabilities/ccip/ccipsolana/ccip_router/RegisterTokenAdminRegistryViaGetCcipAdmin.go b/core/capabilities/ccip/ccipsolana/ccip_router/RegisterTokenAdminRegistryViaGetCcipAdmin.go new file mode 100644 index 00000000000..20ed495cdb4 --- /dev/null +++ b/core/capabilities/ccip/ccipsolana/ccip_router/RegisterTokenAdminRegistryViaGetCcipAdmin.go @@ -0,0 +1,207 @@ +// Code generated by https://github.com/gagliardetto/anchor-go. DO NOT EDIT. + +package ccip_router + +import ( + "errors" + ag_binary "github.com/gagliardetto/binary" + ag_solanago "github.com/gagliardetto/solana-go" + ag_format "github.com/gagliardetto/solana-go/text/format" + ag_treeout "github.com/gagliardetto/treeout" +) + +// The CCIP Admin or the Mint Authority of the Token can register the Token Admin Registry +type RegisterTokenAdminRegistryViaGetCcipAdmin struct { + Mint *ag_solanago.PublicKey + TokenAdminRegistryAdmin *ag_solanago.PublicKey + + // [0] = [] config + // + // [1] = [WRITE] tokenAdminRegistry + // + // [2] = [WRITE, SIGNER] authority + // + // [3] = [] systemProgram + ag_solanago.AccountMetaSlice `bin:"-" borsh_skip:"true"` +} + +// NewRegisterTokenAdminRegistryViaGetCcipAdminInstructionBuilder creates a new `RegisterTokenAdminRegistryViaGetCcipAdmin` instruction builder. +func NewRegisterTokenAdminRegistryViaGetCcipAdminInstructionBuilder() *RegisterTokenAdminRegistryViaGetCcipAdmin { + nd := &RegisterTokenAdminRegistryViaGetCcipAdmin{ + AccountMetaSlice: make(ag_solanago.AccountMetaSlice, 4), + } + return nd +} + +// SetMint sets the "mint" parameter. +func (inst *RegisterTokenAdminRegistryViaGetCcipAdmin) SetMint(mint ag_solanago.PublicKey) *RegisterTokenAdminRegistryViaGetCcipAdmin { + inst.Mint = &mint + return inst +} + +// SetTokenAdminRegistryAdmin sets the "tokenAdminRegistryAdmin" parameter. +func (inst *RegisterTokenAdminRegistryViaGetCcipAdmin) SetTokenAdminRegistryAdmin(tokenAdminRegistryAdmin ag_solanago.PublicKey) *RegisterTokenAdminRegistryViaGetCcipAdmin { + inst.TokenAdminRegistryAdmin = &tokenAdminRegistryAdmin + return inst +} + +// SetConfigAccount sets the "config" account. +func (inst *RegisterTokenAdminRegistryViaGetCcipAdmin) SetConfigAccount(config ag_solanago.PublicKey) *RegisterTokenAdminRegistryViaGetCcipAdmin { + inst.AccountMetaSlice[0] = ag_solanago.Meta(config) + return inst +} + +// GetConfigAccount gets the "config" account. +func (inst *RegisterTokenAdminRegistryViaGetCcipAdmin) GetConfigAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[0] +} + +// SetTokenAdminRegistryAccount sets the "tokenAdminRegistry" account. +func (inst *RegisterTokenAdminRegistryViaGetCcipAdmin) SetTokenAdminRegistryAccount(tokenAdminRegistry ag_solanago.PublicKey) *RegisterTokenAdminRegistryViaGetCcipAdmin { + inst.AccountMetaSlice[1] = ag_solanago.Meta(tokenAdminRegistry).WRITE() + return inst +} + +// GetTokenAdminRegistryAccount gets the "tokenAdminRegistry" account. +func (inst *RegisterTokenAdminRegistryViaGetCcipAdmin) GetTokenAdminRegistryAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[1] +} + +// SetAuthorityAccount sets the "authority" account. +func (inst *RegisterTokenAdminRegistryViaGetCcipAdmin) SetAuthorityAccount(authority ag_solanago.PublicKey) *RegisterTokenAdminRegistryViaGetCcipAdmin { + inst.AccountMetaSlice[2] = ag_solanago.Meta(authority).WRITE().SIGNER() + return inst +} + +// GetAuthorityAccount gets the "authority" account. +func (inst *RegisterTokenAdminRegistryViaGetCcipAdmin) GetAuthorityAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[2] +} + +// SetSystemProgramAccount sets the "systemProgram" account. +func (inst *RegisterTokenAdminRegistryViaGetCcipAdmin) SetSystemProgramAccount(systemProgram ag_solanago.PublicKey) *RegisterTokenAdminRegistryViaGetCcipAdmin { + inst.AccountMetaSlice[3] = ag_solanago.Meta(systemProgram) + return inst +} + +// GetSystemProgramAccount gets the "systemProgram" account. +func (inst *RegisterTokenAdminRegistryViaGetCcipAdmin) GetSystemProgramAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[3] +} + +func (inst RegisterTokenAdminRegistryViaGetCcipAdmin) Build() *Instruction { + return &Instruction{BaseVariant: ag_binary.BaseVariant{ + Impl: inst, + TypeID: Instruction_RegisterTokenAdminRegistryViaGetCcipAdmin, + }} +} + +// ValidateAndBuild validates the instruction parameters and accounts; +// if there is a validation error, it returns the error. +// Otherwise, it builds and returns the instruction. +func (inst RegisterTokenAdminRegistryViaGetCcipAdmin) ValidateAndBuild() (*Instruction, error) { + if err := inst.Validate(); err != nil { + return nil, err + } + return inst.Build(), nil +} + +func (inst *RegisterTokenAdminRegistryViaGetCcipAdmin) Validate() error { + // Check whether all (required) parameters are set: + { + if inst.Mint == nil { + return errors.New("Mint parameter is not set") + } + if inst.TokenAdminRegistryAdmin == nil { + return errors.New("TokenAdminRegistryAdmin parameter is not set") + } + } + + // Check whether all (required) accounts are set: + { + if inst.AccountMetaSlice[0] == nil { + return errors.New("accounts.Config is not set") + } + if inst.AccountMetaSlice[1] == nil { + return errors.New("accounts.TokenAdminRegistry is not set") + } + if inst.AccountMetaSlice[2] == nil { + return errors.New("accounts.Authority is not set") + } + if inst.AccountMetaSlice[3] == nil { + return errors.New("accounts.SystemProgram is not set") + } + } + return nil +} + +func (inst *RegisterTokenAdminRegistryViaGetCcipAdmin) EncodeToTree(parent ag_treeout.Branches) { + parent.Child(ag_format.Program(ProgramName, ProgramID)). + // + ParentFunc(func(programBranch ag_treeout.Branches) { + programBranch.Child(ag_format.Instruction("RegisterTokenAdminRegistryViaGetCcipAdmin")). + // + ParentFunc(func(instructionBranch ag_treeout.Branches) { + + // Parameters of the instruction: + instructionBranch.Child("Params[len=2]").ParentFunc(func(paramsBranch ag_treeout.Branches) { + paramsBranch.Child(ag_format.Param(" Mint", *inst.Mint)) + paramsBranch.Child(ag_format.Param("TokenAdminRegistryAdmin", *inst.TokenAdminRegistryAdmin)) + }) + + // Accounts of the instruction: + instructionBranch.Child("Accounts[len=4]").ParentFunc(func(accountsBranch ag_treeout.Branches) { + accountsBranch.Child(ag_format.Meta(" config", inst.AccountMetaSlice[0])) + accountsBranch.Child(ag_format.Meta("tokenAdminRegistry", inst.AccountMetaSlice[1])) + accountsBranch.Child(ag_format.Meta(" authority", inst.AccountMetaSlice[2])) + accountsBranch.Child(ag_format.Meta(" systemProgram", inst.AccountMetaSlice[3])) + }) + }) + }) +} + +func (obj RegisterTokenAdminRegistryViaGetCcipAdmin) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { + // Serialize `Mint` param: + err = encoder.Encode(obj.Mint) + if err != nil { + return err + } + // Serialize `TokenAdminRegistryAdmin` param: + err = encoder.Encode(obj.TokenAdminRegistryAdmin) + if err != nil { + return err + } + return nil +} +func (obj *RegisterTokenAdminRegistryViaGetCcipAdmin) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { + // Deserialize `Mint`: + err = decoder.Decode(&obj.Mint) + if err != nil { + return err + } + // Deserialize `TokenAdminRegistryAdmin`: + err = decoder.Decode(&obj.TokenAdminRegistryAdmin) + if err != nil { + return err + } + return nil +} + +// NewRegisterTokenAdminRegistryViaGetCcipAdminInstruction declares a new RegisterTokenAdminRegistryViaGetCcipAdmin instruction with the provided parameters and accounts. +func NewRegisterTokenAdminRegistryViaGetCcipAdminInstruction( + // Parameters: + mint ag_solanago.PublicKey, + tokenAdminRegistryAdmin ag_solanago.PublicKey, + // Accounts: + config ag_solanago.PublicKey, + tokenAdminRegistry ag_solanago.PublicKey, + authority ag_solanago.PublicKey, + systemProgram ag_solanago.PublicKey) *RegisterTokenAdminRegistryViaGetCcipAdmin { + return NewRegisterTokenAdminRegistryViaGetCcipAdminInstructionBuilder(). + SetMint(mint). + SetTokenAdminRegistryAdmin(tokenAdminRegistryAdmin). + SetConfigAccount(config). + SetTokenAdminRegistryAccount(tokenAdminRegistry). + SetAuthorityAccount(authority). + SetSystemProgramAccount(systemProgram) +} diff --git a/core/capabilities/ccip/ccipsolana/ccip_router/RegisterTokenAdminRegistryViaGetCcipAdmin_test.go b/core/capabilities/ccip/ccipsolana/ccip_router/RegisterTokenAdminRegistryViaGetCcipAdmin_test.go new file mode 100644 index 00000000000..29a2c212a49 --- /dev/null +++ b/core/capabilities/ccip/ccipsolana/ccip_router/RegisterTokenAdminRegistryViaGetCcipAdmin_test.go @@ -0,0 +1,32 @@ +// Code generated by https://github.com/gagliardetto/anchor-go. DO NOT EDIT. + +package ccip_router + +import ( + "bytes" + ag_gofuzz "github.com/gagliardetto/gofuzz" + ag_require "github.com/stretchr/testify/require" + "strconv" + "testing" +) + +func TestEncodeDecode_RegisterTokenAdminRegistryViaGetCcipAdmin(t *testing.T) { + fu := ag_gofuzz.New().NilChance(0) + for i := 0; i < 1; i++ { + t.Run("RegisterTokenAdminRegistryViaGetCcipAdmin"+strconv.Itoa(i), func(t *testing.T) { + { + params := new(RegisterTokenAdminRegistryViaGetCcipAdmin) + fu.Fuzz(params) + params.AccountMetaSlice = nil + buf := new(bytes.Buffer) + err := encodeT(*params, buf) + ag_require.NoError(t, err) + got := new(RegisterTokenAdminRegistryViaGetCcipAdmin) + err = decodeT(got, buf.Bytes()) + got.AccountMetaSlice = nil + ag_require.NoError(t, err) + ag_require.Equal(t, params, got) + } + }) + } +} diff --git a/core/capabilities/ccip/ccipsolana/ccip_router/RegisterTokenAdminRegistryViaOwner.go b/core/capabilities/ccip/ccipsolana/ccip_router/RegisterTokenAdminRegistryViaOwner.go new file mode 100644 index 00000000000..eb79b822606 --- /dev/null +++ b/core/capabilities/ccip/ccipsolana/ccip_router/RegisterTokenAdminRegistryViaOwner.go @@ -0,0 +1,155 @@ +// Code generated by https://github.com/gagliardetto/anchor-go. DO NOT EDIT. + +package ccip_router + +import ( + "errors" + ag_binary "github.com/gagliardetto/binary" + ag_solanago "github.com/gagliardetto/solana-go" + ag_format "github.com/gagliardetto/solana-go/text/format" + ag_treeout "github.com/gagliardetto/treeout" +) + +// The Token's mint_authority can register themselves to the Token Admin Registry +type RegisterTokenAdminRegistryViaOwner struct { + + // [0] = [WRITE] tokenAdminRegistry + // + // [1] = [WRITE] mint + // + // [2] = [WRITE, SIGNER] authority + // + // [3] = [] systemProgram + ag_solanago.AccountMetaSlice `bin:"-" borsh_skip:"true"` +} + +// NewRegisterTokenAdminRegistryViaOwnerInstructionBuilder creates a new `RegisterTokenAdminRegistryViaOwner` instruction builder. +func NewRegisterTokenAdminRegistryViaOwnerInstructionBuilder() *RegisterTokenAdminRegistryViaOwner { + nd := &RegisterTokenAdminRegistryViaOwner{ + AccountMetaSlice: make(ag_solanago.AccountMetaSlice, 4), + } + return nd +} + +// SetTokenAdminRegistryAccount sets the "tokenAdminRegistry" account. +func (inst *RegisterTokenAdminRegistryViaOwner) SetTokenAdminRegistryAccount(tokenAdminRegistry ag_solanago.PublicKey) *RegisterTokenAdminRegistryViaOwner { + inst.AccountMetaSlice[0] = ag_solanago.Meta(tokenAdminRegistry).WRITE() + return inst +} + +// GetTokenAdminRegistryAccount gets the "tokenAdminRegistry" account. +func (inst *RegisterTokenAdminRegistryViaOwner) GetTokenAdminRegistryAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[0] +} + +// SetMintAccount sets the "mint" account. +func (inst *RegisterTokenAdminRegistryViaOwner) SetMintAccount(mint ag_solanago.PublicKey) *RegisterTokenAdminRegistryViaOwner { + inst.AccountMetaSlice[1] = ag_solanago.Meta(mint).WRITE() + return inst +} + +// GetMintAccount gets the "mint" account. +func (inst *RegisterTokenAdminRegistryViaOwner) GetMintAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[1] +} + +// SetAuthorityAccount sets the "authority" account. +func (inst *RegisterTokenAdminRegistryViaOwner) SetAuthorityAccount(authority ag_solanago.PublicKey) *RegisterTokenAdminRegistryViaOwner { + inst.AccountMetaSlice[2] = ag_solanago.Meta(authority).WRITE().SIGNER() + return inst +} + +// GetAuthorityAccount gets the "authority" account. +func (inst *RegisterTokenAdminRegistryViaOwner) GetAuthorityAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[2] +} + +// SetSystemProgramAccount sets the "systemProgram" account. +func (inst *RegisterTokenAdminRegistryViaOwner) SetSystemProgramAccount(systemProgram ag_solanago.PublicKey) *RegisterTokenAdminRegistryViaOwner { + inst.AccountMetaSlice[3] = ag_solanago.Meta(systemProgram) + return inst +} + +// GetSystemProgramAccount gets the "systemProgram" account. +func (inst *RegisterTokenAdminRegistryViaOwner) GetSystemProgramAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[3] +} + +func (inst RegisterTokenAdminRegistryViaOwner) Build() *Instruction { + return &Instruction{BaseVariant: ag_binary.BaseVariant{ + Impl: inst, + TypeID: Instruction_RegisterTokenAdminRegistryViaOwner, + }} +} + +// ValidateAndBuild validates the instruction parameters and accounts; +// if there is a validation error, it returns the error. +// Otherwise, it builds and returns the instruction. +func (inst RegisterTokenAdminRegistryViaOwner) ValidateAndBuild() (*Instruction, error) { + if err := inst.Validate(); err != nil { + return nil, err + } + return inst.Build(), nil +} + +func (inst *RegisterTokenAdminRegistryViaOwner) Validate() error { + // Check whether all (required) accounts are set: + { + if inst.AccountMetaSlice[0] == nil { + return errors.New("accounts.TokenAdminRegistry is not set") + } + if inst.AccountMetaSlice[1] == nil { + return errors.New("accounts.Mint is not set") + } + if inst.AccountMetaSlice[2] == nil { + return errors.New("accounts.Authority is not set") + } + if inst.AccountMetaSlice[3] == nil { + return errors.New("accounts.SystemProgram is not set") + } + } + return nil +} + +func (inst *RegisterTokenAdminRegistryViaOwner) EncodeToTree(parent ag_treeout.Branches) { + parent.Child(ag_format.Program(ProgramName, ProgramID)). + // + ParentFunc(func(programBranch ag_treeout.Branches) { + programBranch.Child(ag_format.Instruction("RegisterTokenAdminRegistryViaOwner")). + // + ParentFunc(func(instructionBranch ag_treeout.Branches) { + + // Parameters of the instruction: + instructionBranch.Child("Params[len=0]").ParentFunc(func(paramsBranch ag_treeout.Branches) {}) + + // Accounts of the instruction: + instructionBranch.Child("Accounts[len=4]").ParentFunc(func(accountsBranch ag_treeout.Branches) { + accountsBranch.Child(ag_format.Meta("tokenAdminRegistry", inst.AccountMetaSlice[0])) + accountsBranch.Child(ag_format.Meta(" mint", inst.AccountMetaSlice[1])) + accountsBranch.Child(ag_format.Meta(" authority", inst.AccountMetaSlice[2])) + accountsBranch.Child(ag_format.Meta(" systemProgram", inst.AccountMetaSlice[3])) + }) + }) + }) +} + +func (obj RegisterTokenAdminRegistryViaOwner) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { + return nil +} +func (obj *RegisterTokenAdminRegistryViaOwner) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { + return nil +} + +// NewRegisterTokenAdminRegistryViaOwnerInstruction declares a new RegisterTokenAdminRegistryViaOwner instruction with the provided parameters and accounts. +func NewRegisterTokenAdminRegistryViaOwnerInstruction( + // Accounts: + tokenAdminRegistry ag_solanago.PublicKey, + mint ag_solanago.PublicKey, + authority ag_solanago.PublicKey, + systemProgram ag_solanago.PublicKey) *RegisterTokenAdminRegistryViaOwner { + return NewRegisterTokenAdminRegistryViaOwnerInstructionBuilder(). + SetTokenAdminRegistryAccount(tokenAdminRegistry). + SetMintAccount(mint). + SetAuthorityAccount(authority). + SetSystemProgramAccount(systemProgram) +} diff --git a/core/capabilities/ccip/ccipsolana/ccip_router/RegisterTokenAdminRegistryViaOwner_test.go b/core/capabilities/ccip/ccipsolana/ccip_router/RegisterTokenAdminRegistryViaOwner_test.go new file mode 100644 index 00000000000..ea293f88b2e --- /dev/null +++ b/core/capabilities/ccip/ccipsolana/ccip_router/RegisterTokenAdminRegistryViaOwner_test.go @@ -0,0 +1,32 @@ +// Code generated by https://github.com/gagliardetto/anchor-go. DO NOT EDIT. + +package ccip_router + +import ( + "bytes" + ag_gofuzz "github.com/gagliardetto/gofuzz" + ag_require "github.com/stretchr/testify/require" + "strconv" + "testing" +) + +func TestEncodeDecode_RegisterTokenAdminRegistryViaOwner(t *testing.T) { + fu := ag_gofuzz.New().NilChance(0) + for i := 0; i < 1; i++ { + t.Run("RegisterTokenAdminRegistryViaOwner"+strconv.Itoa(i), func(t *testing.T) { + { + params := new(RegisterTokenAdminRegistryViaOwner) + fu.Fuzz(params) + params.AccountMetaSlice = nil + buf := new(bytes.Buffer) + err := encodeT(*params, buf) + ag_require.NoError(t, err) + got := new(RegisterTokenAdminRegistryViaOwner) + err = decodeT(got, buf.Bytes()) + got.AccountMetaSlice = nil + ag_require.NoError(t, err) + ag_require.Equal(t, params, got) + } + }) + } +} diff --git a/core/capabilities/ccip/ccipsolana/ccip_router/SetOcrConfig.go b/core/capabilities/ccip/ccipsolana/ccip_router/SetOcrConfig.go new file mode 100644 index 00000000000..3a6420a6980 --- /dev/null +++ b/core/capabilities/ccip/ccipsolana/ccip_router/SetOcrConfig.go @@ -0,0 +1,215 @@ +// Code generated by https://github.com/gagliardetto/anchor-go. DO NOT EDIT. + +package ccip_router + +import ( + "errors" + ag_binary "github.com/gagliardetto/binary" + ag_solanago "github.com/gagliardetto/solana-go" + ag_format "github.com/gagliardetto/solana-go/text/format" + ag_treeout "github.com/gagliardetto/treeout" +) + +// SetOcrConfig is the `setOcrConfig` instruction. +type SetOcrConfig struct { + PluginType *uint8 + ConfigInfo *Ocr3ConfigInfo + Signers *[][20]uint8 + Transmitters *[]ag_solanago.PublicKey + + // [0] = [WRITE] config + // + // [1] = [SIGNER] authority + ag_solanago.AccountMetaSlice `bin:"-" borsh_skip:"true"` +} + +// NewSetOcrConfigInstructionBuilder creates a new `SetOcrConfig` instruction builder. +func NewSetOcrConfigInstructionBuilder() *SetOcrConfig { + nd := &SetOcrConfig{ + AccountMetaSlice: make(ag_solanago.AccountMetaSlice, 2), + } + return nd +} + +// SetPluginType sets the "pluginType" parameter. +func (inst *SetOcrConfig) SetPluginType(pluginType uint8) *SetOcrConfig { + inst.PluginType = &pluginType + return inst +} + +// SetConfigInfo sets the "configInfo" parameter. +func (inst *SetOcrConfig) SetConfigInfo(configInfo Ocr3ConfigInfo) *SetOcrConfig { + inst.ConfigInfo = &configInfo + return inst +} + +// SetSigners sets the "signers" parameter. +func (inst *SetOcrConfig) SetSigners(signers [][20]uint8) *SetOcrConfig { + inst.Signers = &signers + return inst +} + +// SetTransmitters sets the "transmitters" parameter. +func (inst *SetOcrConfig) SetTransmitters(transmitters []ag_solanago.PublicKey) *SetOcrConfig { + inst.Transmitters = &transmitters + return inst +} + +// SetConfigAccount sets the "config" account. +func (inst *SetOcrConfig) SetConfigAccount(config ag_solanago.PublicKey) *SetOcrConfig { + inst.AccountMetaSlice[0] = ag_solanago.Meta(config).WRITE() + return inst +} + +// GetConfigAccount gets the "config" account. +func (inst *SetOcrConfig) GetConfigAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[0] +} + +// SetAuthorityAccount sets the "authority" account. +func (inst *SetOcrConfig) SetAuthorityAccount(authority ag_solanago.PublicKey) *SetOcrConfig { + inst.AccountMetaSlice[1] = ag_solanago.Meta(authority).SIGNER() + return inst +} + +// GetAuthorityAccount gets the "authority" account. +func (inst *SetOcrConfig) GetAuthorityAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[1] +} + +func (inst SetOcrConfig) Build() *Instruction { + return &Instruction{BaseVariant: ag_binary.BaseVariant{ + Impl: inst, + TypeID: Instruction_SetOcrConfig, + }} +} + +// ValidateAndBuild validates the instruction parameters and accounts; +// if there is a validation error, it returns the error. +// Otherwise, it builds and returns the instruction. +func (inst SetOcrConfig) ValidateAndBuild() (*Instruction, error) { + if err := inst.Validate(); err != nil { + return nil, err + } + return inst.Build(), nil +} + +func (inst *SetOcrConfig) Validate() error { + // Check whether all (required) parameters are set: + { + if inst.PluginType == nil { + return errors.New("PluginType parameter is not set") + } + if inst.ConfigInfo == nil { + return errors.New("ConfigInfo parameter is not set") + } + if inst.Signers == nil { + return errors.New("Signers parameter is not set") + } + if inst.Transmitters == nil { + return errors.New("Transmitters parameter is not set") + } + } + + // Check whether all (required) accounts are set: + { + if inst.AccountMetaSlice[0] == nil { + return errors.New("accounts.Config is not set") + } + if inst.AccountMetaSlice[1] == nil { + return errors.New("accounts.Authority is not set") + } + } + return nil +} + +func (inst *SetOcrConfig) EncodeToTree(parent ag_treeout.Branches) { + parent.Child(ag_format.Program(ProgramName, ProgramID)). + // + ParentFunc(func(programBranch ag_treeout.Branches) { + programBranch.Child(ag_format.Instruction("SetOcrConfig")). + // + ParentFunc(func(instructionBranch ag_treeout.Branches) { + + // Parameters of the instruction: + instructionBranch.Child("Params[len=4]").ParentFunc(func(paramsBranch ag_treeout.Branches) { + paramsBranch.Child(ag_format.Param(" PluginType", *inst.PluginType)) + paramsBranch.Child(ag_format.Param(" ConfigInfo", *inst.ConfigInfo)) + paramsBranch.Child(ag_format.Param(" Signers", *inst.Signers)) + paramsBranch.Child(ag_format.Param("Transmitters", *inst.Transmitters)) + }) + + // Accounts of the instruction: + instructionBranch.Child("Accounts[len=2]").ParentFunc(func(accountsBranch ag_treeout.Branches) { + accountsBranch.Child(ag_format.Meta(" config", inst.AccountMetaSlice[0])) + accountsBranch.Child(ag_format.Meta("authority", inst.AccountMetaSlice[1])) + }) + }) + }) +} + +func (obj SetOcrConfig) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { + // Serialize `PluginType` param: + err = encoder.Encode(obj.PluginType) + if err != nil { + return err + } + // Serialize `ConfigInfo` param: + err = encoder.Encode(obj.ConfigInfo) + if err != nil { + return err + } + // Serialize `Signers` param: + err = encoder.Encode(obj.Signers) + if err != nil { + return err + } + // Serialize `Transmitters` param: + err = encoder.Encode(obj.Transmitters) + if err != nil { + return err + } + return nil +} +func (obj *SetOcrConfig) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { + // Deserialize `PluginType`: + err = decoder.Decode(&obj.PluginType) + if err != nil { + return err + } + // Deserialize `ConfigInfo`: + err = decoder.Decode(&obj.ConfigInfo) + if err != nil { + return err + } + // Deserialize `Signers`: + err = decoder.Decode(&obj.Signers) + if err != nil { + return err + } + // Deserialize `Transmitters`: + err = decoder.Decode(&obj.Transmitters) + if err != nil { + return err + } + return nil +} + +// NewSetOcrConfigInstruction declares a new SetOcrConfig instruction with the provided parameters and accounts. +func NewSetOcrConfigInstruction( + // Parameters: + pluginType uint8, + configInfo Ocr3ConfigInfo, + signers [][20]uint8, + transmitters []ag_solanago.PublicKey, + // Accounts: + config ag_solanago.PublicKey, + authority ag_solanago.PublicKey) *SetOcrConfig { + return NewSetOcrConfigInstructionBuilder(). + SetPluginType(pluginType). + SetConfigInfo(configInfo). + SetSigners(signers). + SetTransmitters(transmitters). + SetConfigAccount(config). + SetAuthorityAccount(authority) +} diff --git a/core/capabilities/ccip/ccipsolana/ccip_router/SetOcrConfig_test.go b/core/capabilities/ccip/ccipsolana/ccip_router/SetOcrConfig_test.go new file mode 100644 index 00000000000..88528fc48ea --- /dev/null +++ b/core/capabilities/ccip/ccipsolana/ccip_router/SetOcrConfig_test.go @@ -0,0 +1,32 @@ +// Code generated by https://github.com/gagliardetto/anchor-go. DO NOT EDIT. + +package ccip_router + +import ( + "bytes" + ag_gofuzz "github.com/gagliardetto/gofuzz" + ag_require "github.com/stretchr/testify/require" + "strconv" + "testing" +) + +func TestEncodeDecode_SetOcrConfig(t *testing.T) { + fu := ag_gofuzz.New().NilChance(0) + for i := 0; i < 1; i++ { + t.Run("SetOcrConfig"+strconv.Itoa(i), func(t *testing.T) { + { + params := new(SetOcrConfig) + fu.Fuzz(params) + params.AccountMetaSlice = nil + buf := new(bytes.Buffer) + err := encodeT(*params, buf) + ag_require.NoError(t, err) + got := new(SetOcrConfig) + err = decodeT(got, buf.Bytes()) + got.AccountMetaSlice = nil + ag_require.NoError(t, err) + ag_require.Equal(t, params, got) + } + }) + } +} diff --git a/core/capabilities/ccip/ccipsolana/ccip_router/SetPool.go b/core/capabilities/ccip/ccipsolana/ccip_router/SetPool.go new file mode 100644 index 00000000000..69cdc9ba5e1 --- /dev/null +++ b/core/capabilities/ccip/ccipsolana/ccip_router/SetPool.go @@ -0,0 +1,169 @@ +// Code generated by https://github.com/gagliardetto/anchor-go. DO NOT EDIT. + +package ccip_router + +import ( + "errors" + ag_binary "github.com/gagliardetto/binary" + ag_solanago "github.com/gagliardetto/solana-go" + ag_format "github.com/gagliardetto/solana-go/text/format" + ag_treeout "github.com/gagliardetto/treeout" +) + +// The administrator of the token can setup the token pool +type SetPool struct { + Mint *ag_solanago.PublicKey + PoolLookupTable *ag_solanago.PublicKey + + // [0] = [WRITE] tokenAdminRegistry + // + // [1] = [WRITE, SIGNER] authority + ag_solanago.AccountMetaSlice `bin:"-" borsh_skip:"true"` +} + +// NewSetPoolInstructionBuilder creates a new `SetPool` instruction builder. +func NewSetPoolInstructionBuilder() *SetPool { + nd := &SetPool{ + AccountMetaSlice: make(ag_solanago.AccountMetaSlice, 2), + } + return nd +} + +// SetMint sets the "mint" parameter. +func (inst *SetPool) SetMint(mint ag_solanago.PublicKey) *SetPool { + inst.Mint = &mint + return inst +} + +// SetPoolLookupTable sets the "poolLookupTable" parameter. +func (inst *SetPool) SetPoolLookupTable(poolLookupTable ag_solanago.PublicKey) *SetPool { + inst.PoolLookupTable = &poolLookupTable + return inst +} + +// SetTokenAdminRegistryAccount sets the "tokenAdminRegistry" account. +func (inst *SetPool) SetTokenAdminRegistryAccount(tokenAdminRegistry ag_solanago.PublicKey) *SetPool { + inst.AccountMetaSlice[0] = ag_solanago.Meta(tokenAdminRegistry).WRITE() + return inst +} + +// GetTokenAdminRegistryAccount gets the "tokenAdminRegistry" account. +func (inst *SetPool) GetTokenAdminRegistryAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[0] +} + +// SetAuthorityAccount sets the "authority" account. +func (inst *SetPool) SetAuthorityAccount(authority ag_solanago.PublicKey) *SetPool { + inst.AccountMetaSlice[1] = ag_solanago.Meta(authority).WRITE().SIGNER() + return inst +} + +// GetAuthorityAccount gets the "authority" account. +func (inst *SetPool) GetAuthorityAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[1] +} + +func (inst SetPool) Build() *Instruction { + return &Instruction{BaseVariant: ag_binary.BaseVariant{ + Impl: inst, + TypeID: Instruction_SetPool, + }} +} + +// ValidateAndBuild validates the instruction parameters and accounts; +// if there is a validation error, it returns the error. +// Otherwise, it builds and returns the instruction. +func (inst SetPool) ValidateAndBuild() (*Instruction, error) { + if err := inst.Validate(); err != nil { + return nil, err + } + return inst.Build(), nil +} + +func (inst *SetPool) Validate() error { + // Check whether all (required) parameters are set: + { + if inst.Mint == nil { + return errors.New("Mint parameter is not set") + } + if inst.PoolLookupTable == nil { + return errors.New("PoolLookupTable parameter is not set") + } + } + + // Check whether all (required) accounts are set: + { + if inst.AccountMetaSlice[0] == nil { + return errors.New("accounts.TokenAdminRegistry is not set") + } + if inst.AccountMetaSlice[1] == nil { + return errors.New("accounts.Authority is not set") + } + } + return nil +} + +func (inst *SetPool) EncodeToTree(parent ag_treeout.Branches) { + parent.Child(ag_format.Program(ProgramName, ProgramID)). + // + ParentFunc(func(programBranch ag_treeout.Branches) { + programBranch.Child(ag_format.Instruction("SetPool")). + // + ParentFunc(func(instructionBranch ag_treeout.Branches) { + + // Parameters of the instruction: + instructionBranch.Child("Params[len=2]").ParentFunc(func(paramsBranch ag_treeout.Branches) { + paramsBranch.Child(ag_format.Param(" Mint", *inst.Mint)) + paramsBranch.Child(ag_format.Param("PoolLookupTable", *inst.PoolLookupTable)) + }) + + // Accounts of the instruction: + instructionBranch.Child("Accounts[len=2]").ParentFunc(func(accountsBranch ag_treeout.Branches) { + accountsBranch.Child(ag_format.Meta("tokenAdminRegistry", inst.AccountMetaSlice[0])) + accountsBranch.Child(ag_format.Meta(" authority", inst.AccountMetaSlice[1])) + }) + }) + }) +} + +func (obj SetPool) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { + // Serialize `Mint` param: + err = encoder.Encode(obj.Mint) + if err != nil { + return err + } + // Serialize `PoolLookupTable` param: + err = encoder.Encode(obj.PoolLookupTable) + if err != nil { + return err + } + return nil +} +func (obj *SetPool) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { + // Deserialize `Mint`: + err = decoder.Decode(&obj.Mint) + if err != nil { + return err + } + // Deserialize `PoolLookupTable`: + err = decoder.Decode(&obj.PoolLookupTable) + if err != nil { + return err + } + return nil +} + +// NewSetPoolInstruction declares a new SetPool instruction with the provided parameters and accounts. +func NewSetPoolInstruction( + // Parameters: + mint ag_solanago.PublicKey, + poolLookupTable ag_solanago.PublicKey, + // Accounts: + tokenAdminRegistry ag_solanago.PublicKey, + authority ag_solanago.PublicKey) *SetPool { + return NewSetPoolInstructionBuilder(). + SetMint(mint). + SetPoolLookupTable(poolLookupTable). + SetTokenAdminRegistryAccount(tokenAdminRegistry). + SetAuthorityAccount(authority) +} diff --git a/core/capabilities/ccip/ccipsolana/ccip_router/SetPool_test.go b/core/capabilities/ccip/ccipsolana/ccip_router/SetPool_test.go new file mode 100644 index 00000000000..249513a25ba --- /dev/null +++ b/core/capabilities/ccip/ccipsolana/ccip_router/SetPool_test.go @@ -0,0 +1,32 @@ +// Code generated by https://github.com/gagliardetto/anchor-go. DO NOT EDIT. + +package ccip_router + +import ( + "bytes" + ag_gofuzz "github.com/gagliardetto/gofuzz" + ag_require "github.com/stretchr/testify/require" + "strconv" + "testing" +) + +func TestEncodeDecode_SetPool(t *testing.T) { + fu := ag_gofuzz.New().NilChance(0) + for i := 0; i < 1; i++ { + t.Run("SetPool"+strconv.Itoa(i), func(t *testing.T) { + { + params := new(SetPool) + fu.Fuzz(params) + params.AccountMetaSlice = nil + buf := new(bytes.Buffer) + err := encodeT(*params, buf) + ag_require.NoError(t, err) + got := new(SetPool) + err = decodeT(got, buf.Bytes()) + got.AccountMetaSlice = nil + ag_require.NoError(t, err) + ag_require.Equal(t, params, got) + } + }) + } +} diff --git a/core/capabilities/ccip/ccipsolana/ccip_router/SetTokenBilling.go b/core/capabilities/ccip/ccipsolana/ccip_router/SetTokenBilling.go new file mode 100644 index 00000000000..41f1bcd34a5 --- /dev/null +++ b/core/capabilities/ccip/ccipsolana/ccip_router/SetTokenBilling.go @@ -0,0 +1,230 @@ +// Code generated by https://github.com/gagliardetto/anchor-go. DO NOT EDIT. + +package ccip_router + +import ( + "errors" + ag_binary "github.com/gagliardetto/binary" + ag_solanago "github.com/gagliardetto/solana-go" + ag_format "github.com/gagliardetto/solana-go/text/format" + ag_treeout "github.com/gagliardetto/treeout" +) + +// SetTokenBilling is the `setTokenBilling` instruction. +type SetTokenBilling struct { + ChainSelector *uint64 + Mint *ag_solanago.PublicKey + Cfg *TokenBilling + + // [0] = [] config + // + // [1] = [WRITE] perChainPerTokenConfig + // + // [2] = [WRITE, SIGNER] authority + // + // [3] = [] systemProgram + ag_solanago.AccountMetaSlice `bin:"-" borsh_skip:"true"` +} + +// NewSetTokenBillingInstructionBuilder creates a new `SetTokenBilling` instruction builder. +func NewSetTokenBillingInstructionBuilder() *SetTokenBilling { + nd := &SetTokenBilling{ + AccountMetaSlice: make(ag_solanago.AccountMetaSlice, 4), + } + return nd +} + +// SetChainSelector sets the "chainSelector" parameter. +func (inst *SetTokenBilling) SetChainSelector(chainSelector uint64) *SetTokenBilling { + inst.ChainSelector = &chainSelector + return inst +} + +// SetMint sets the "mint" parameter. +func (inst *SetTokenBilling) SetMint(mint ag_solanago.PublicKey) *SetTokenBilling { + inst.Mint = &mint + return inst +} + +// SetCfg sets the "cfg" parameter. +func (inst *SetTokenBilling) SetCfg(cfg TokenBilling) *SetTokenBilling { + inst.Cfg = &cfg + return inst +} + +// SetConfigAccount sets the "config" account. +func (inst *SetTokenBilling) SetConfigAccount(config ag_solanago.PublicKey) *SetTokenBilling { + inst.AccountMetaSlice[0] = ag_solanago.Meta(config) + return inst +} + +// GetConfigAccount gets the "config" account. +func (inst *SetTokenBilling) GetConfigAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[0] +} + +// SetPerChainPerTokenConfigAccount sets the "perChainPerTokenConfig" account. +func (inst *SetTokenBilling) SetPerChainPerTokenConfigAccount(perChainPerTokenConfig ag_solanago.PublicKey) *SetTokenBilling { + inst.AccountMetaSlice[1] = ag_solanago.Meta(perChainPerTokenConfig).WRITE() + return inst +} + +// GetPerChainPerTokenConfigAccount gets the "perChainPerTokenConfig" account. +func (inst *SetTokenBilling) GetPerChainPerTokenConfigAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[1] +} + +// SetAuthorityAccount sets the "authority" account. +func (inst *SetTokenBilling) SetAuthorityAccount(authority ag_solanago.PublicKey) *SetTokenBilling { + inst.AccountMetaSlice[2] = ag_solanago.Meta(authority).WRITE().SIGNER() + return inst +} + +// GetAuthorityAccount gets the "authority" account. +func (inst *SetTokenBilling) GetAuthorityAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[2] +} + +// SetSystemProgramAccount sets the "systemProgram" account. +func (inst *SetTokenBilling) SetSystemProgramAccount(systemProgram ag_solanago.PublicKey) *SetTokenBilling { + inst.AccountMetaSlice[3] = ag_solanago.Meta(systemProgram) + return inst +} + +// GetSystemProgramAccount gets the "systemProgram" account. +func (inst *SetTokenBilling) GetSystemProgramAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[3] +} + +func (inst SetTokenBilling) Build() *Instruction { + return &Instruction{BaseVariant: ag_binary.BaseVariant{ + Impl: inst, + TypeID: Instruction_SetTokenBilling, + }} +} + +// ValidateAndBuild validates the instruction parameters and accounts; +// if there is a validation error, it returns the error. +// Otherwise, it builds and returns the instruction. +func (inst SetTokenBilling) ValidateAndBuild() (*Instruction, error) { + if err := inst.Validate(); err != nil { + return nil, err + } + return inst.Build(), nil +} + +func (inst *SetTokenBilling) Validate() error { + // Check whether all (required) parameters are set: + { + if inst.ChainSelector == nil { + return errors.New("ChainSelector parameter is not set") + } + if inst.Mint == nil { + return errors.New("Mint parameter is not set") + } + if inst.Cfg == nil { + return errors.New("Cfg parameter is not set") + } + } + + // Check whether all (required) accounts are set: + { + if inst.AccountMetaSlice[0] == nil { + return errors.New("accounts.Config is not set") + } + if inst.AccountMetaSlice[1] == nil { + return errors.New("accounts.PerChainPerTokenConfig is not set") + } + if inst.AccountMetaSlice[2] == nil { + return errors.New("accounts.Authority is not set") + } + if inst.AccountMetaSlice[3] == nil { + return errors.New("accounts.SystemProgram is not set") + } + } + return nil +} + +func (inst *SetTokenBilling) EncodeToTree(parent ag_treeout.Branches) { + parent.Child(ag_format.Program(ProgramName, ProgramID)). + // + ParentFunc(func(programBranch ag_treeout.Branches) { + programBranch.Child(ag_format.Instruction("SetTokenBilling")). + // + ParentFunc(func(instructionBranch ag_treeout.Branches) { + + // Parameters of the instruction: + instructionBranch.Child("Params[len=3]").ParentFunc(func(paramsBranch ag_treeout.Branches) { + paramsBranch.Child(ag_format.Param("ChainSelector", *inst.ChainSelector)) + paramsBranch.Child(ag_format.Param(" Mint", *inst.Mint)) + paramsBranch.Child(ag_format.Param(" Cfg", *inst.Cfg)) + }) + + // Accounts of the instruction: + instructionBranch.Child("Accounts[len=4]").ParentFunc(func(accountsBranch ag_treeout.Branches) { + accountsBranch.Child(ag_format.Meta(" config", inst.AccountMetaSlice[0])) + accountsBranch.Child(ag_format.Meta("perChainPerTokenConfig", inst.AccountMetaSlice[1])) + accountsBranch.Child(ag_format.Meta(" authority", inst.AccountMetaSlice[2])) + accountsBranch.Child(ag_format.Meta(" systemProgram", inst.AccountMetaSlice[3])) + }) + }) + }) +} + +func (obj SetTokenBilling) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { + // Serialize `ChainSelector` param: + err = encoder.Encode(obj.ChainSelector) + if err != nil { + return err + } + // Serialize `Mint` param: + err = encoder.Encode(obj.Mint) + if err != nil { + return err + } + // Serialize `Cfg` param: + err = encoder.Encode(obj.Cfg) + if err != nil { + return err + } + return nil +} +func (obj *SetTokenBilling) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { + // Deserialize `ChainSelector`: + err = decoder.Decode(&obj.ChainSelector) + if err != nil { + return err + } + // Deserialize `Mint`: + err = decoder.Decode(&obj.Mint) + if err != nil { + return err + } + // Deserialize `Cfg`: + err = decoder.Decode(&obj.Cfg) + if err != nil { + return err + } + return nil +} + +// NewSetTokenBillingInstruction declares a new SetTokenBilling instruction with the provided parameters and accounts. +func NewSetTokenBillingInstruction( + // Parameters: + chainSelector uint64, + mint ag_solanago.PublicKey, + cfg TokenBilling, + // Accounts: + config ag_solanago.PublicKey, + perChainPerTokenConfig ag_solanago.PublicKey, + authority ag_solanago.PublicKey, + systemProgram ag_solanago.PublicKey) *SetTokenBilling { + return NewSetTokenBillingInstructionBuilder(). + SetChainSelector(chainSelector). + SetMint(mint). + SetCfg(cfg). + SetConfigAccount(config). + SetPerChainPerTokenConfigAccount(perChainPerTokenConfig). + SetAuthorityAccount(authority). + SetSystemProgramAccount(systemProgram) +} diff --git a/core/capabilities/ccip/ccipsolana/ccip_router/SetTokenBilling_test.go b/core/capabilities/ccip/ccipsolana/ccip_router/SetTokenBilling_test.go new file mode 100644 index 00000000000..aff9d60f3d3 --- /dev/null +++ b/core/capabilities/ccip/ccipsolana/ccip_router/SetTokenBilling_test.go @@ -0,0 +1,32 @@ +// Code generated by https://github.com/gagliardetto/anchor-go. DO NOT EDIT. + +package ccip_router + +import ( + "bytes" + ag_gofuzz "github.com/gagliardetto/gofuzz" + ag_require "github.com/stretchr/testify/require" + "strconv" + "testing" +) + +func TestEncodeDecode_SetTokenBilling(t *testing.T) { + fu := ag_gofuzz.New().NilChance(0) + for i := 0; i < 1; i++ { + t.Run("SetTokenBilling"+strconv.Itoa(i), func(t *testing.T) { + { + params := new(SetTokenBilling) + fu.Fuzz(params) + params.AccountMetaSlice = nil + buf := new(bytes.Buffer) + err := encodeT(*params, buf) + ag_require.NoError(t, err) + got := new(SetTokenBilling) + err = decodeT(got, buf.Bytes()) + got.AccountMetaSlice = nil + ag_require.NoError(t, err) + ag_require.Equal(t, params, got) + } + }) + } +} diff --git a/core/capabilities/ccip/ccipsolana/ccip_router/TransferAdminRoleTokenAdminRegistry.go b/core/capabilities/ccip/ccipsolana/ccip_router/TransferAdminRoleTokenAdminRegistry.go new file mode 100644 index 00000000000..269a086456d --- /dev/null +++ b/core/capabilities/ccip/ccipsolana/ccip_router/TransferAdminRoleTokenAdminRegistry.go @@ -0,0 +1,169 @@ +// Code generated by https://github.com/gagliardetto/anchor-go. DO NOT EDIT. + +package ccip_router + +import ( + "errors" + ag_binary "github.com/gagliardetto/binary" + ag_solanago "github.com/gagliardetto/solana-go" + ag_format "github.com/gagliardetto/solana-go/text/format" + ag_treeout "github.com/gagliardetto/treeout" +) + +// The Admin can transfer the Admin Role of the Token Admin Registry +type TransferAdminRoleTokenAdminRegistry struct { + Mint *ag_solanago.PublicKey + NewAdmin *ag_solanago.PublicKey + + // [0] = [WRITE] tokenAdminRegistry + // + // [1] = [WRITE, SIGNER] authority + ag_solanago.AccountMetaSlice `bin:"-" borsh_skip:"true"` +} + +// NewTransferAdminRoleTokenAdminRegistryInstructionBuilder creates a new `TransferAdminRoleTokenAdminRegistry` instruction builder. +func NewTransferAdminRoleTokenAdminRegistryInstructionBuilder() *TransferAdminRoleTokenAdminRegistry { + nd := &TransferAdminRoleTokenAdminRegistry{ + AccountMetaSlice: make(ag_solanago.AccountMetaSlice, 2), + } + return nd +} + +// SetMint sets the "mint" parameter. +func (inst *TransferAdminRoleTokenAdminRegistry) SetMint(mint ag_solanago.PublicKey) *TransferAdminRoleTokenAdminRegistry { + inst.Mint = &mint + return inst +} + +// SetNewAdmin sets the "newAdmin" parameter. +func (inst *TransferAdminRoleTokenAdminRegistry) SetNewAdmin(newAdmin ag_solanago.PublicKey) *TransferAdminRoleTokenAdminRegistry { + inst.NewAdmin = &newAdmin + return inst +} + +// SetTokenAdminRegistryAccount sets the "tokenAdminRegistry" account. +func (inst *TransferAdminRoleTokenAdminRegistry) SetTokenAdminRegistryAccount(tokenAdminRegistry ag_solanago.PublicKey) *TransferAdminRoleTokenAdminRegistry { + inst.AccountMetaSlice[0] = ag_solanago.Meta(tokenAdminRegistry).WRITE() + return inst +} + +// GetTokenAdminRegistryAccount gets the "tokenAdminRegistry" account. +func (inst *TransferAdminRoleTokenAdminRegistry) GetTokenAdminRegistryAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[0] +} + +// SetAuthorityAccount sets the "authority" account. +func (inst *TransferAdminRoleTokenAdminRegistry) SetAuthorityAccount(authority ag_solanago.PublicKey) *TransferAdminRoleTokenAdminRegistry { + inst.AccountMetaSlice[1] = ag_solanago.Meta(authority).WRITE().SIGNER() + return inst +} + +// GetAuthorityAccount gets the "authority" account. +func (inst *TransferAdminRoleTokenAdminRegistry) GetAuthorityAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[1] +} + +func (inst TransferAdminRoleTokenAdminRegistry) Build() *Instruction { + return &Instruction{BaseVariant: ag_binary.BaseVariant{ + Impl: inst, + TypeID: Instruction_TransferAdminRoleTokenAdminRegistry, + }} +} + +// ValidateAndBuild validates the instruction parameters and accounts; +// if there is a validation error, it returns the error. +// Otherwise, it builds and returns the instruction. +func (inst TransferAdminRoleTokenAdminRegistry) ValidateAndBuild() (*Instruction, error) { + if err := inst.Validate(); err != nil { + return nil, err + } + return inst.Build(), nil +} + +func (inst *TransferAdminRoleTokenAdminRegistry) Validate() error { + // Check whether all (required) parameters are set: + { + if inst.Mint == nil { + return errors.New("Mint parameter is not set") + } + if inst.NewAdmin == nil { + return errors.New("NewAdmin parameter is not set") + } + } + + // Check whether all (required) accounts are set: + { + if inst.AccountMetaSlice[0] == nil { + return errors.New("accounts.TokenAdminRegistry is not set") + } + if inst.AccountMetaSlice[1] == nil { + return errors.New("accounts.Authority is not set") + } + } + return nil +} + +func (inst *TransferAdminRoleTokenAdminRegistry) EncodeToTree(parent ag_treeout.Branches) { + parent.Child(ag_format.Program(ProgramName, ProgramID)). + // + ParentFunc(func(programBranch ag_treeout.Branches) { + programBranch.Child(ag_format.Instruction("TransferAdminRoleTokenAdminRegistry")). + // + ParentFunc(func(instructionBranch ag_treeout.Branches) { + + // Parameters of the instruction: + instructionBranch.Child("Params[len=2]").ParentFunc(func(paramsBranch ag_treeout.Branches) { + paramsBranch.Child(ag_format.Param(" Mint", *inst.Mint)) + paramsBranch.Child(ag_format.Param("NewAdmin", *inst.NewAdmin)) + }) + + // Accounts of the instruction: + instructionBranch.Child("Accounts[len=2]").ParentFunc(func(accountsBranch ag_treeout.Branches) { + accountsBranch.Child(ag_format.Meta("tokenAdminRegistry", inst.AccountMetaSlice[0])) + accountsBranch.Child(ag_format.Meta(" authority", inst.AccountMetaSlice[1])) + }) + }) + }) +} + +func (obj TransferAdminRoleTokenAdminRegistry) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { + // Serialize `Mint` param: + err = encoder.Encode(obj.Mint) + if err != nil { + return err + } + // Serialize `NewAdmin` param: + err = encoder.Encode(obj.NewAdmin) + if err != nil { + return err + } + return nil +} +func (obj *TransferAdminRoleTokenAdminRegistry) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { + // Deserialize `Mint`: + err = decoder.Decode(&obj.Mint) + if err != nil { + return err + } + // Deserialize `NewAdmin`: + err = decoder.Decode(&obj.NewAdmin) + if err != nil { + return err + } + return nil +} + +// NewTransferAdminRoleTokenAdminRegistryInstruction declares a new TransferAdminRoleTokenAdminRegistry instruction with the provided parameters and accounts. +func NewTransferAdminRoleTokenAdminRegistryInstruction( + // Parameters: + mint ag_solanago.PublicKey, + newAdmin ag_solanago.PublicKey, + // Accounts: + tokenAdminRegistry ag_solanago.PublicKey, + authority ag_solanago.PublicKey) *TransferAdminRoleTokenAdminRegistry { + return NewTransferAdminRoleTokenAdminRegistryInstructionBuilder(). + SetMint(mint). + SetNewAdmin(newAdmin). + SetTokenAdminRegistryAccount(tokenAdminRegistry). + SetAuthorityAccount(authority) +} diff --git a/core/capabilities/ccip/ccipsolana/ccip_router/TransferAdminRoleTokenAdminRegistry_test.go b/core/capabilities/ccip/ccipsolana/ccip_router/TransferAdminRoleTokenAdminRegistry_test.go new file mode 100644 index 00000000000..e52c1a9983e --- /dev/null +++ b/core/capabilities/ccip/ccipsolana/ccip_router/TransferAdminRoleTokenAdminRegistry_test.go @@ -0,0 +1,32 @@ +// Code generated by https://github.com/gagliardetto/anchor-go. DO NOT EDIT. + +package ccip_router + +import ( + "bytes" + ag_gofuzz "github.com/gagliardetto/gofuzz" + ag_require "github.com/stretchr/testify/require" + "strconv" + "testing" +) + +func TestEncodeDecode_TransferAdminRoleTokenAdminRegistry(t *testing.T) { + fu := ag_gofuzz.New().NilChance(0) + for i := 0; i < 1; i++ { + t.Run("TransferAdminRoleTokenAdminRegistry"+strconv.Itoa(i), func(t *testing.T) { + { + params := new(TransferAdminRoleTokenAdminRegistry) + fu.Fuzz(params) + params.AccountMetaSlice = nil + buf := new(bytes.Buffer) + err := encodeT(*params, buf) + ag_require.NoError(t, err) + got := new(TransferAdminRoleTokenAdminRegistry) + err = decodeT(got, buf.Bytes()) + got.AccountMetaSlice = nil + ag_require.NoError(t, err) + ag_require.Equal(t, params, got) + } + }) + } +} diff --git a/core/capabilities/ccip/ccipsolana/ccip_router/TransferOwnership.go b/core/capabilities/ccip/ccipsolana/ccip_router/TransferOwnership.go new file mode 100644 index 00000000000..37a129be90c --- /dev/null +++ b/core/capabilities/ccip/ccipsolana/ccip_router/TransferOwnership.go @@ -0,0 +1,146 @@ +// Code generated by https://github.com/gagliardetto/anchor-go. DO NOT EDIT. + +package ccip_router + +import ( + "errors" + ag_binary "github.com/gagliardetto/binary" + ag_solanago "github.com/gagliardetto/solana-go" + ag_format "github.com/gagliardetto/solana-go/text/format" + ag_treeout "github.com/gagliardetto/treeout" +) + +// TransferOwnership is the `transferOwnership` instruction. +type TransferOwnership struct { + ProposedOwner *ag_solanago.PublicKey + + // [0] = [WRITE] config + // + // [1] = [SIGNER] authority + ag_solanago.AccountMetaSlice `bin:"-" borsh_skip:"true"` +} + +// NewTransferOwnershipInstructionBuilder creates a new `TransferOwnership` instruction builder. +func NewTransferOwnershipInstructionBuilder() *TransferOwnership { + nd := &TransferOwnership{ + AccountMetaSlice: make(ag_solanago.AccountMetaSlice, 2), + } + return nd +} + +// SetProposedOwner sets the "proposedOwner" parameter. +func (inst *TransferOwnership) SetProposedOwner(proposedOwner ag_solanago.PublicKey) *TransferOwnership { + inst.ProposedOwner = &proposedOwner + return inst +} + +// SetConfigAccount sets the "config" account. +func (inst *TransferOwnership) SetConfigAccount(config ag_solanago.PublicKey) *TransferOwnership { + inst.AccountMetaSlice[0] = ag_solanago.Meta(config).WRITE() + return inst +} + +// GetConfigAccount gets the "config" account. +func (inst *TransferOwnership) GetConfigAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[0] +} + +// SetAuthorityAccount sets the "authority" account. +func (inst *TransferOwnership) SetAuthorityAccount(authority ag_solanago.PublicKey) *TransferOwnership { + inst.AccountMetaSlice[1] = ag_solanago.Meta(authority).SIGNER() + return inst +} + +// GetAuthorityAccount gets the "authority" account. +func (inst *TransferOwnership) GetAuthorityAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[1] +} + +func (inst TransferOwnership) Build() *Instruction { + return &Instruction{BaseVariant: ag_binary.BaseVariant{ + Impl: inst, + TypeID: Instruction_TransferOwnership, + }} +} + +// ValidateAndBuild validates the instruction parameters and accounts; +// if there is a validation error, it returns the error. +// Otherwise, it builds and returns the instruction. +func (inst TransferOwnership) ValidateAndBuild() (*Instruction, error) { + if err := inst.Validate(); err != nil { + return nil, err + } + return inst.Build(), nil +} + +func (inst *TransferOwnership) Validate() error { + // Check whether all (required) parameters are set: + { + if inst.ProposedOwner == nil { + return errors.New("ProposedOwner parameter is not set") + } + } + + // Check whether all (required) accounts are set: + { + if inst.AccountMetaSlice[0] == nil { + return errors.New("accounts.Config is not set") + } + if inst.AccountMetaSlice[1] == nil { + return errors.New("accounts.Authority is not set") + } + } + return nil +} + +func (inst *TransferOwnership) EncodeToTree(parent ag_treeout.Branches) { + parent.Child(ag_format.Program(ProgramName, ProgramID)). + // + ParentFunc(func(programBranch ag_treeout.Branches) { + programBranch.Child(ag_format.Instruction("TransferOwnership")). + // + ParentFunc(func(instructionBranch ag_treeout.Branches) { + + // Parameters of the instruction: + instructionBranch.Child("Params[len=1]").ParentFunc(func(paramsBranch ag_treeout.Branches) { + paramsBranch.Child(ag_format.Param("ProposedOwner", *inst.ProposedOwner)) + }) + + // Accounts of the instruction: + instructionBranch.Child("Accounts[len=2]").ParentFunc(func(accountsBranch ag_treeout.Branches) { + accountsBranch.Child(ag_format.Meta(" config", inst.AccountMetaSlice[0])) + accountsBranch.Child(ag_format.Meta("authority", inst.AccountMetaSlice[1])) + }) + }) + }) +} + +func (obj TransferOwnership) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { + // Serialize `ProposedOwner` param: + err = encoder.Encode(obj.ProposedOwner) + if err != nil { + return err + } + return nil +} +func (obj *TransferOwnership) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { + // Deserialize `ProposedOwner`: + err = decoder.Decode(&obj.ProposedOwner) + if err != nil { + return err + } + return nil +} + +// NewTransferOwnershipInstruction declares a new TransferOwnership instruction with the provided parameters and accounts. +func NewTransferOwnershipInstruction( + // Parameters: + proposedOwner ag_solanago.PublicKey, + // Accounts: + config ag_solanago.PublicKey, + authority ag_solanago.PublicKey) *TransferOwnership { + return NewTransferOwnershipInstructionBuilder(). + SetProposedOwner(proposedOwner). + SetConfigAccount(config). + SetAuthorityAccount(authority) +} diff --git a/core/capabilities/ccip/ccipsolana/ccip_router/TransferOwnership_test.go b/core/capabilities/ccip/ccipsolana/ccip_router/TransferOwnership_test.go new file mode 100644 index 00000000000..38ea4ea34f1 --- /dev/null +++ b/core/capabilities/ccip/ccipsolana/ccip_router/TransferOwnership_test.go @@ -0,0 +1,32 @@ +// Code generated by https://github.com/gagliardetto/anchor-go. DO NOT EDIT. + +package ccip_router + +import ( + "bytes" + ag_gofuzz "github.com/gagliardetto/gofuzz" + ag_require "github.com/stretchr/testify/require" + "strconv" + "testing" +) + +func TestEncodeDecode_TransferOwnership(t *testing.T) { + fu := ag_gofuzz.New().NilChance(0) + for i := 0; i < 1; i++ { + t.Run("TransferOwnership"+strconv.Itoa(i), func(t *testing.T) { + { + params := new(TransferOwnership) + fu.Fuzz(params) + params.AccountMetaSlice = nil + buf := new(bytes.Buffer) + err := encodeT(*params, buf) + ag_require.NoError(t, err) + got := new(TransferOwnership) + err = decodeT(got, buf.Bytes()) + got.AccountMetaSlice = nil + ag_require.NoError(t, err) + ag_require.Equal(t, params, got) + } + }) + } +} diff --git a/core/capabilities/ccip/ccipsolana/ccip_router/UpdateDefaultAllowOutOfOrderExecution.go b/core/capabilities/ccip/ccipsolana/ccip_router/UpdateDefaultAllowOutOfOrderExecution.go new file mode 100644 index 00000000000..87e10696877 --- /dev/null +++ b/core/capabilities/ccip/ccipsolana/ccip_router/UpdateDefaultAllowOutOfOrderExecution.go @@ -0,0 +1,165 @@ +// Code generated by https://github.com/gagliardetto/anchor-go. DO NOT EDIT. + +package ccip_router + +import ( + "errors" + ag_binary "github.com/gagliardetto/binary" + ag_solanago "github.com/gagliardetto/solana-go" + ag_format "github.com/gagliardetto/solana-go/text/format" + ag_treeout "github.com/gagliardetto/treeout" +) + +// The Admin can update the configuration of the Router, in this case the Default Allow Out Of Order Execution (True/False) +type UpdateDefaultAllowOutOfOrderExecution struct { + NewAllowOutOfOrderExecution *bool + + // [0] = [WRITE] config + // + // [1] = [SIGNER] authority + // + // [2] = [] systemProgram + ag_solanago.AccountMetaSlice `bin:"-" borsh_skip:"true"` +} + +// NewUpdateDefaultAllowOutOfOrderExecutionInstructionBuilder creates a new `UpdateDefaultAllowOutOfOrderExecution` instruction builder. +func NewUpdateDefaultAllowOutOfOrderExecutionInstructionBuilder() *UpdateDefaultAllowOutOfOrderExecution { + nd := &UpdateDefaultAllowOutOfOrderExecution{ + AccountMetaSlice: make(ag_solanago.AccountMetaSlice, 3), + } + return nd +} + +// SetNewAllowOutOfOrderExecution sets the "newAllowOutOfOrderExecution" parameter. +func (inst *UpdateDefaultAllowOutOfOrderExecution) SetNewAllowOutOfOrderExecution(newAllowOutOfOrderExecution bool) *UpdateDefaultAllowOutOfOrderExecution { + inst.NewAllowOutOfOrderExecution = &newAllowOutOfOrderExecution + return inst +} + +// SetConfigAccount sets the "config" account. +func (inst *UpdateDefaultAllowOutOfOrderExecution) SetConfigAccount(config ag_solanago.PublicKey) *UpdateDefaultAllowOutOfOrderExecution { + inst.AccountMetaSlice[0] = ag_solanago.Meta(config).WRITE() + return inst +} + +// GetConfigAccount gets the "config" account. +func (inst *UpdateDefaultAllowOutOfOrderExecution) GetConfigAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[0] +} + +// SetAuthorityAccount sets the "authority" account. +func (inst *UpdateDefaultAllowOutOfOrderExecution) SetAuthorityAccount(authority ag_solanago.PublicKey) *UpdateDefaultAllowOutOfOrderExecution { + inst.AccountMetaSlice[1] = ag_solanago.Meta(authority).SIGNER() + return inst +} + +// GetAuthorityAccount gets the "authority" account. +func (inst *UpdateDefaultAllowOutOfOrderExecution) GetAuthorityAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[1] +} + +// SetSystemProgramAccount sets the "systemProgram" account. +func (inst *UpdateDefaultAllowOutOfOrderExecution) SetSystemProgramAccount(systemProgram ag_solanago.PublicKey) *UpdateDefaultAllowOutOfOrderExecution { + inst.AccountMetaSlice[2] = ag_solanago.Meta(systemProgram) + return inst +} + +// GetSystemProgramAccount gets the "systemProgram" account. +func (inst *UpdateDefaultAllowOutOfOrderExecution) GetSystemProgramAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[2] +} + +func (inst UpdateDefaultAllowOutOfOrderExecution) Build() *Instruction { + return &Instruction{BaseVariant: ag_binary.BaseVariant{ + Impl: inst, + TypeID: Instruction_UpdateDefaultAllowOutOfOrderExecution, + }} +} + +// ValidateAndBuild validates the instruction parameters and accounts; +// if there is a validation error, it returns the error. +// Otherwise, it builds and returns the instruction. +func (inst UpdateDefaultAllowOutOfOrderExecution) ValidateAndBuild() (*Instruction, error) { + if err := inst.Validate(); err != nil { + return nil, err + } + return inst.Build(), nil +} + +func (inst *UpdateDefaultAllowOutOfOrderExecution) Validate() error { + // Check whether all (required) parameters are set: + { + if inst.NewAllowOutOfOrderExecution == nil { + return errors.New("NewAllowOutOfOrderExecution parameter is not set") + } + } + + // Check whether all (required) accounts are set: + { + if inst.AccountMetaSlice[0] == nil { + return errors.New("accounts.Config is not set") + } + if inst.AccountMetaSlice[1] == nil { + return errors.New("accounts.Authority is not set") + } + if inst.AccountMetaSlice[2] == nil { + return errors.New("accounts.SystemProgram is not set") + } + } + return nil +} + +func (inst *UpdateDefaultAllowOutOfOrderExecution) EncodeToTree(parent ag_treeout.Branches) { + parent.Child(ag_format.Program(ProgramName, ProgramID)). + // + ParentFunc(func(programBranch ag_treeout.Branches) { + programBranch.Child(ag_format.Instruction("UpdateDefaultAllowOutOfOrderExecution")). + // + ParentFunc(func(instructionBranch ag_treeout.Branches) { + + // Parameters of the instruction: + instructionBranch.Child("Params[len=1]").ParentFunc(func(paramsBranch ag_treeout.Branches) { + paramsBranch.Child(ag_format.Param("NewAllowOutOfOrderExecution", *inst.NewAllowOutOfOrderExecution)) + }) + + // Accounts of the instruction: + instructionBranch.Child("Accounts[len=3]").ParentFunc(func(accountsBranch ag_treeout.Branches) { + accountsBranch.Child(ag_format.Meta(" config", inst.AccountMetaSlice[0])) + accountsBranch.Child(ag_format.Meta(" authority", inst.AccountMetaSlice[1])) + accountsBranch.Child(ag_format.Meta("systemProgram", inst.AccountMetaSlice[2])) + }) + }) + }) +} + +func (obj UpdateDefaultAllowOutOfOrderExecution) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { + // Serialize `NewAllowOutOfOrderExecution` param: + err = encoder.Encode(obj.NewAllowOutOfOrderExecution) + if err != nil { + return err + } + return nil +} +func (obj *UpdateDefaultAllowOutOfOrderExecution) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { + // Deserialize `NewAllowOutOfOrderExecution`: + err = decoder.Decode(&obj.NewAllowOutOfOrderExecution) + if err != nil { + return err + } + return nil +} + +// NewUpdateDefaultAllowOutOfOrderExecutionInstruction declares a new UpdateDefaultAllowOutOfOrderExecution instruction with the provided parameters and accounts. +func NewUpdateDefaultAllowOutOfOrderExecutionInstruction( + // Parameters: + newAllowOutOfOrderExecution bool, + // Accounts: + config ag_solanago.PublicKey, + authority ag_solanago.PublicKey, + systemProgram ag_solanago.PublicKey) *UpdateDefaultAllowOutOfOrderExecution { + return NewUpdateDefaultAllowOutOfOrderExecutionInstructionBuilder(). + SetNewAllowOutOfOrderExecution(newAllowOutOfOrderExecution). + SetConfigAccount(config). + SetAuthorityAccount(authority). + SetSystemProgramAccount(systemProgram) +} diff --git a/core/capabilities/ccip/ccipsolana/ccip_router/UpdateDefaultAllowOutOfOrderExecution_test.go b/core/capabilities/ccip/ccipsolana/ccip_router/UpdateDefaultAllowOutOfOrderExecution_test.go new file mode 100644 index 00000000000..70a0674748c --- /dev/null +++ b/core/capabilities/ccip/ccipsolana/ccip_router/UpdateDefaultAllowOutOfOrderExecution_test.go @@ -0,0 +1,32 @@ +// Code generated by https://github.com/gagliardetto/anchor-go. DO NOT EDIT. + +package ccip_router + +import ( + "bytes" + ag_gofuzz "github.com/gagliardetto/gofuzz" + ag_require "github.com/stretchr/testify/require" + "strconv" + "testing" +) + +func TestEncodeDecode_UpdateDefaultAllowOutOfOrderExecution(t *testing.T) { + fu := ag_gofuzz.New().NilChance(0) + for i := 0; i < 1; i++ { + t.Run("UpdateDefaultAllowOutOfOrderExecution"+strconv.Itoa(i), func(t *testing.T) { + { + params := new(UpdateDefaultAllowOutOfOrderExecution) + fu.Fuzz(params) + params.AccountMetaSlice = nil + buf := new(bytes.Buffer) + err := encodeT(*params, buf) + ag_require.NoError(t, err) + got := new(UpdateDefaultAllowOutOfOrderExecution) + err = decodeT(got, buf.Bytes()) + got.AccountMetaSlice = nil + ag_require.NoError(t, err) + ag_require.Equal(t, params, got) + } + }) + } +} diff --git a/core/capabilities/ccip/ccipsolana/ccip_router/UpdateDefaultGasLimit.go b/core/capabilities/ccip/ccipsolana/ccip_router/UpdateDefaultGasLimit.go new file mode 100644 index 00000000000..c1791685884 --- /dev/null +++ b/core/capabilities/ccip/ccipsolana/ccip_router/UpdateDefaultGasLimit.go @@ -0,0 +1,165 @@ +// Code generated by https://github.com/gagliardetto/anchor-go. DO NOT EDIT. + +package ccip_router + +import ( + "errors" + ag_binary "github.com/gagliardetto/binary" + ag_solanago "github.com/gagliardetto/solana-go" + ag_format "github.com/gagliardetto/solana-go/text/format" + ag_treeout "github.com/gagliardetto/treeout" +) + +// The Admin can update the configuration of the Router, in this case the Default Gas Limit +type UpdateDefaultGasLimit struct { + NewGasLimit *ag_binary.Uint128 + + // [0] = [WRITE] config + // + // [1] = [SIGNER] authority + // + // [2] = [] systemProgram + ag_solanago.AccountMetaSlice `bin:"-" borsh_skip:"true"` +} + +// NewUpdateDefaultGasLimitInstructionBuilder creates a new `UpdateDefaultGasLimit` instruction builder. +func NewUpdateDefaultGasLimitInstructionBuilder() *UpdateDefaultGasLimit { + nd := &UpdateDefaultGasLimit{ + AccountMetaSlice: make(ag_solanago.AccountMetaSlice, 3), + } + return nd +} + +// SetNewGasLimit sets the "newGasLimit" parameter. +func (inst *UpdateDefaultGasLimit) SetNewGasLimit(newGasLimit ag_binary.Uint128) *UpdateDefaultGasLimit { + inst.NewGasLimit = &newGasLimit + return inst +} + +// SetConfigAccount sets the "config" account. +func (inst *UpdateDefaultGasLimit) SetConfigAccount(config ag_solanago.PublicKey) *UpdateDefaultGasLimit { + inst.AccountMetaSlice[0] = ag_solanago.Meta(config).WRITE() + return inst +} + +// GetConfigAccount gets the "config" account. +func (inst *UpdateDefaultGasLimit) GetConfigAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[0] +} + +// SetAuthorityAccount sets the "authority" account. +func (inst *UpdateDefaultGasLimit) SetAuthorityAccount(authority ag_solanago.PublicKey) *UpdateDefaultGasLimit { + inst.AccountMetaSlice[1] = ag_solanago.Meta(authority).SIGNER() + return inst +} + +// GetAuthorityAccount gets the "authority" account. +func (inst *UpdateDefaultGasLimit) GetAuthorityAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[1] +} + +// SetSystemProgramAccount sets the "systemProgram" account. +func (inst *UpdateDefaultGasLimit) SetSystemProgramAccount(systemProgram ag_solanago.PublicKey) *UpdateDefaultGasLimit { + inst.AccountMetaSlice[2] = ag_solanago.Meta(systemProgram) + return inst +} + +// GetSystemProgramAccount gets the "systemProgram" account. +func (inst *UpdateDefaultGasLimit) GetSystemProgramAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[2] +} + +func (inst UpdateDefaultGasLimit) Build() *Instruction { + return &Instruction{BaseVariant: ag_binary.BaseVariant{ + Impl: inst, + TypeID: Instruction_UpdateDefaultGasLimit, + }} +} + +// ValidateAndBuild validates the instruction parameters and accounts; +// if there is a validation error, it returns the error. +// Otherwise, it builds and returns the instruction. +func (inst UpdateDefaultGasLimit) ValidateAndBuild() (*Instruction, error) { + if err := inst.Validate(); err != nil { + return nil, err + } + return inst.Build(), nil +} + +func (inst *UpdateDefaultGasLimit) Validate() error { + // Check whether all (required) parameters are set: + { + if inst.NewGasLimit == nil { + return errors.New("NewGasLimit parameter is not set") + } + } + + // Check whether all (required) accounts are set: + { + if inst.AccountMetaSlice[0] == nil { + return errors.New("accounts.Config is not set") + } + if inst.AccountMetaSlice[1] == nil { + return errors.New("accounts.Authority is not set") + } + if inst.AccountMetaSlice[2] == nil { + return errors.New("accounts.SystemProgram is not set") + } + } + return nil +} + +func (inst *UpdateDefaultGasLimit) EncodeToTree(parent ag_treeout.Branches) { + parent.Child(ag_format.Program(ProgramName, ProgramID)). + // + ParentFunc(func(programBranch ag_treeout.Branches) { + programBranch.Child(ag_format.Instruction("UpdateDefaultGasLimit")). + // + ParentFunc(func(instructionBranch ag_treeout.Branches) { + + // Parameters of the instruction: + instructionBranch.Child("Params[len=1]").ParentFunc(func(paramsBranch ag_treeout.Branches) { + paramsBranch.Child(ag_format.Param("NewGasLimit", *inst.NewGasLimit)) + }) + + // Accounts of the instruction: + instructionBranch.Child("Accounts[len=3]").ParentFunc(func(accountsBranch ag_treeout.Branches) { + accountsBranch.Child(ag_format.Meta(" config", inst.AccountMetaSlice[0])) + accountsBranch.Child(ag_format.Meta(" authority", inst.AccountMetaSlice[1])) + accountsBranch.Child(ag_format.Meta("systemProgram", inst.AccountMetaSlice[2])) + }) + }) + }) +} + +func (obj UpdateDefaultGasLimit) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { + // Serialize `NewGasLimit` param: + err = encoder.Encode(obj.NewGasLimit) + if err != nil { + return err + } + return nil +} +func (obj *UpdateDefaultGasLimit) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { + // Deserialize `NewGasLimit`: + err = decoder.Decode(&obj.NewGasLimit) + if err != nil { + return err + } + return nil +} + +// NewUpdateDefaultGasLimitInstruction declares a new UpdateDefaultGasLimit instruction with the provided parameters and accounts. +func NewUpdateDefaultGasLimitInstruction( + // Parameters: + newGasLimit ag_binary.Uint128, + // Accounts: + config ag_solanago.PublicKey, + authority ag_solanago.PublicKey, + systemProgram ag_solanago.PublicKey) *UpdateDefaultGasLimit { + return NewUpdateDefaultGasLimitInstructionBuilder(). + SetNewGasLimit(newGasLimit). + SetConfigAccount(config). + SetAuthorityAccount(authority). + SetSystemProgramAccount(systemProgram) +} diff --git a/core/capabilities/ccip/ccipsolana/ccip_router/UpdateDefaultGasLimit_test.go b/core/capabilities/ccip/ccipsolana/ccip_router/UpdateDefaultGasLimit_test.go new file mode 100644 index 00000000000..f323c69e6b8 --- /dev/null +++ b/core/capabilities/ccip/ccipsolana/ccip_router/UpdateDefaultGasLimit_test.go @@ -0,0 +1,32 @@ +// Code generated by https://github.com/gagliardetto/anchor-go. DO NOT EDIT. + +package ccip_router + +import ( + "bytes" + ag_gofuzz "github.com/gagliardetto/gofuzz" + ag_require "github.com/stretchr/testify/require" + "strconv" + "testing" +) + +func TestEncodeDecode_UpdateDefaultGasLimit(t *testing.T) { + fu := ag_gofuzz.New().NilChance(0) + for i := 0; i < 1; i++ { + t.Run("UpdateDefaultGasLimit"+strconv.Itoa(i), func(t *testing.T) { + { + params := new(UpdateDefaultGasLimit) + fu.Fuzz(params) + params.AccountMetaSlice = nil + buf := new(bytes.Buffer) + err := encodeT(*params, buf) + ag_require.NoError(t, err) + got := new(UpdateDefaultGasLimit) + err = decodeT(got, buf.Bytes()) + got.AccountMetaSlice = nil + ag_require.NoError(t, err) + ag_require.Equal(t, params, got) + } + }) + } +} diff --git a/core/capabilities/ccip/ccipsolana/ccip_router/UpdateEnableManualExecutionAfter.go b/core/capabilities/ccip/ccipsolana/ccip_router/UpdateEnableManualExecutionAfter.go new file mode 100644 index 00000000000..5adb9d10708 --- /dev/null +++ b/core/capabilities/ccip/ccipsolana/ccip_router/UpdateEnableManualExecutionAfter.go @@ -0,0 +1,165 @@ +// Code generated by https://github.com/gagliardetto/anchor-go. DO NOT EDIT. + +package ccip_router + +import ( + "errors" + ag_binary "github.com/gagliardetto/binary" + ag_solanago "github.com/gagliardetto/solana-go" + ag_format "github.com/gagliardetto/solana-go/text/format" + ag_treeout "github.com/gagliardetto/treeout" +) + +// The Admin can update the configuration of the Router, in this case the Enable Manual Execution After +type UpdateEnableManualExecutionAfter struct { + NewEnableManualExecutionAfter *int64 + + // [0] = [WRITE] config + // + // [1] = [SIGNER] authority + // + // [2] = [] systemProgram + ag_solanago.AccountMetaSlice `bin:"-" borsh_skip:"true"` +} + +// NewUpdateEnableManualExecutionAfterInstructionBuilder creates a new `UpdateEnableManualExecutionAfter` instruction builder. +func NewUpdateEnableManualExecutionAfterInstructionBuilder() *UpdateEnableManualExecutionAfter { + nd := &UpdateEnableManualExecutionAfter{ + AccountMetaSlice: make(ag_solanago.AccountMetaSlice, 3), + } + return nd +} + +// SetNewEnableManualExecutionAfter sets the "newEnableManualExecutionAfter" parameter. +func (inst *UpdateEnableManualExecutionAfter) SetNewEnableManualExecutionAfter(newEnableManualExecutionAfter int64) *UpdateEnableManualExecutionAfter { + inst.NewEnableManualExecutionAfter = &newEnableManualExecutionAfter + return inst +} + +// SetConfigAccount sets the "config" account. +func (inst *UpdateEnableManualExecutionAfter) SetConfigAccount(config ag_solanago.PublicKey) *UpdateEnableManualExecutionAfter { + inst.AccountMetaSlice[0] = ag_solanago.Meta(config).WRITE() + return inst +} + +// GetConfigAccount gets the "config" account. +func (inst *UpdateEnableManualExecutionAfter) GetConfigAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[0] +} + +// SetAuthorityAccount sets the "authority" account. +func (inst *UpdateEnableManualExecutionAfter) SetAuthorityAccount(authority ag_solanago.PublicKey) *UpdateEnableManualExecutionAfter { + inst.AccountMetaSlice[1] = ag_solanago.Meta(authority).SIGNER() + return inst +} + +// GetAuthorityAccount gets the "authority" account. +func (inst *UpdateEnableManualExecutionAfter) GetAuthorityAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[1] +} + +// SetSystemProgramAccount sets the "systemProgram" account. +func (inst *UpdateEnableManualExecutionAfter) SetSystemProgramAccount(systemProgram ag_solanago.PublicKey) *UpdateEnableManualExecutionAfter { + inst.AccountMetaSlice[2] = ag_solanago.Meta(systemProgram) + return inst +} + +// GetSystemProgramAccount gets the "systemProgram" account. +func (inst *UpdateEnableManualExecutionAfter) GetSystemProgramAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[2] +} + +func (inst UpdateEnableManualExecutionAfter) Build() *Instruction { + return &Instruction{BaseVariant: ag_binary.BaseVariant{ + Impl: inst, + TypeID: Instruction_UpdateEnableManualExecutionAfter, + }} +} + +// ValidateAndBuild validates the instruction parameters and accounts; +// if there is a validation error, it returns the error. +// Otherwise, it builds and returns the instruction. +func (inst UpdateEnableManualExecutionAfter) ValidateAndBuild() (*Instruction, error) { + if err := inst.Validate(); err != nil { + return nil, err + } + return inst.Build(), nil +} + +func (inst *UpdateEnableManualExecutionAfter) Validate() error { + // Check whether all (required) parameters are set: + { + if inst.NewEnableManualExecutionAfter == nil { + return errors.New("NewEnableManualExecutionAfter parameter is not set") + } + } + + // Check whether all (required) accounts are set: + { + if inst.AccountMetaSlice[0] == nil { + return errors.New("accounts.Config is not set") + } + if inst.AccountMetaSlice[1] == nil { + return errors.New("accounts.Authority is not set") + } + if inst.AccountMetaSlice[2] == nil { + return errors.New("accounts.SystemProgram is not set") + } + } + return nil +} + +func (inst *UpdateEnableManualExecutionAfter) EncodeToTree(parent ag_treeout.Branches) { + parent.Child(ag_format.Program(ProgramName, ProgramID)). + // + ParentFunc(func(programBranch ag_treeout.Branches) { + programBranch.Child(ag_format.Instruction("UpdateEnableManualExecutionAfter")). + // + ParentFunc(func(instructionBranch ag_treeout.Branches) { + + // Parameters of the instruction: + instructionBranch.Child("Params[len=1]").ParentFunc(func(paramsBranch ag_treeout.Branches) { + paramsBranch.Child(ag_format.Param("NewEnableManualExecutionAfter", *inst.NewEnableManualExecutionAfter)) + }) + + // Accounts of the instruction: + instructionBranch.Child("Accounts[len=3]").ParentFunc(func(accountsBranch ag_treeout.Branches) { + accountsBranch.Child(ag_format.Meta(" config", inst.AccountMetaSlice[0])) + accountsBranch.Child(ag_format.Meta(" authority", inst.AccountMetaSlice[1])) + accountsBranch.Child(ag_format.Meta("systemProgram", inst.AccountMetaSlice[2])) + }) + }) + }) +} + +func (obj UpdateEnableManualExecutionAfter) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { + // Serialize `NewEnableManualExecutionAfter` param: + err = encoder.Encode(obj.NewEnableManualExecutionAfter) + if err != nil { + return err + } + return nil +} +func (obj *UpdateEnableManualExecutionAfter) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { + // Deserialize `NewEnableManualExecutionAfter`: + err = decoder.Decode(&obj.NewEnableManualExecutionAfter) + if err != nil { + return err + } + return nil +} + +// NewUpdateEnableManualExecutionAfterInstruction declares a new UpdateEnableManualExecutionAfter instruction with the provided parameters and accounts. +func NewUpdateEnableManualExecutionAfterInstruction( + // Parameters: + newEnableManualExecutionAfter int64, + // Accounts: + config ag_solanago.PublicKey, + authority ag_solanago.PublicKey, + systemProgram ag_solanago.PublicKey) *UpdateEnableManualExecutionAfter { + return NewUpdateEnableManualExecutionAfterInstructionBuilder(). + SetNewEnableManualExecutionAfter(newEnableManualExecutionAfter). + SetConfigAccount(config). + SetAuthorityAccount(authority). + SetSystemProgramAccount(systemProgram) +} diff --git a/core/capabilities/ccip/ccipsolana/ccip_router/UpdateEnableManualExecutionAfter_test.go b/core/capabilities/ccip/ccipsolana/ccip_router/UpdateEnableManualExecutionAfter_test.go new file mode 100644 index 00000000000..cc37505f599 --- /dev/null +++ b/core/capabilities/ccip/ccipsolana/ccip_router/UpdateEnableManualExecutionAfter_test.go @@ -0,0 +1,32 @@ +// Code generated by https://github.com/gagliardetto/anchor-go. DO NOT EDIT. + +package ccip_router + +import ( + "bytes" + ag_gofuzz "github.com/gagliardetto/gofuzz" + ag_require "github.com/stretchr/testify/require" + "strconv" + "testing" +) + +func TestEncodeDecode_UpdateEnableManualExecutionAfter(t *testing.T) { + fu := ag_gofuzz.New().NilChance(0) + for i := 0; i < 1; i++ { + t.Run("UpdateEnableManualExecutionAfter"+strconv.Itoa(i), func(t *testing.T) { + { + params := new(UpdateEnableManualExecutionAfter) + fu.Fuzz(params) + params.AccountMetaSlice = nil + buf := new(bytes.Buffer) + err := encodeT(*params, buf) + ag_require.NoError(t, err) + got := new(UpdateEnableManualExecutionAfter) + err = decodeT(got, buf.Bytes()) + got.AccountMetaSlice = nil + ag_require.NoError(t, err) + ag_require.Equal(t, params, got) + } + }) + } +} diff --git a/core/capabilities/ccip/ccipsolana/ccip_router/UpdateSolanaChainSelector.go b/core/capabilities/ccip/ccipsolana/ccip_router/UpdateSolanaChainSelector.go new file mode 100644 index 00000000000..58796f4e381 --- /dev/null +++ b/core/capabilities/ccip/ccipsolana/ccip_router/UpdateSolanaChainSelector.go @@ -0,0 +1,165 @@ +// Code generated by https://github.com/gagliardetto/anchor-go. DO NOT EDIT. + +package ccip_router + +import ( + "errors" + ag_binary "github.com/gagliardetto/binary" + ag_solanago "github.com/gagliardetto/solana-go" + ag_format "github.com/gagliardetto/solana-go/text/format" + ag_treeout "github.com/gagliardetto/treeout" +) + +// The Admin can update the configuration of the Router, in this case the Solana Chain Selector +type UpdateSolanaChainSelector struct { + NewChainSelector *uint64 + + // [0] = [WRITE] config + // + // [1] = [SIGNER] authority + // + // [2] = [] systemProgram + ag_solanago.AccountMetaSlice `bin:"-" borsh_skip:"true"` +} + +// NewUpdateSolanaChainSelectorInstructionBuilder creates a new `UpdateSolanaChainSelector` instruction builder. +func NewUpdateSolanaChainSelectorInstructionBuilder() *UpdateSolanaChainSelector { + nd := &UpdateSolanaChainSelector{ + AccountMetaSlice: make(ag_solanago.AccountMetaSlice, 3), + } + return nd +} + +// SetNewChainSelector sets the "newChainSelector" parameter. +func (inst *UpdateSolanaChainSelector) SetNewChainSelector(newChainSelector uint64) *UpdateSolanaChainSelector { + inst.NewChainSelector = &newChainSelector + return inst +} + +// SetConfigAccount sets the "config" account. +func (inst *UpdateSolanaChainSelector) SetConfigAccount(config ag_solanago.PublicKey) *UpdateSolanaChainSelector { + inst.AccountMetaSlice[0] = ag_solanago.Meta(config).WRITE() + return inst +} + +// GetConfigAccount gets the "config" account. +func (inst *UpdateSolanaChainSelector) GetConfigAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[0] +} + +// SetAuthorityAccount sets the "authority" account. +func (inst *UpdateSolanaChainSelector) SetAuthorityAccount(authority ag_solanago.PublicKey) *UpdateSolanaChainSelector { + inst.AccountMetaSlice[1] = ag_solanago.Meta(authority).SIGNER() + return inst +} + +// GetAuthorityAccount gets the "authority" account. +func (inst *UpdateSolanaChainSelector) GetAuthorityAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[1] +} + +// SetSystemProgramAccount sets the "systemProgram" account. +func (inst *UpdateSolanaChainSelector) SetSystemProgramAccount(systemProgram ag_solanago.PublicKey) *UpdateSolanaChainSelector { + inst.AccountMetaSlice[2] = ag_solanago.Meta(systemProgram) + return inst +} + +// GetSystemProgramAccount gets the "systemProgram" account. +func (inst *UpdateSolanaChainSelector) GetSystemProgramAccount() *ag_solanago.AccountMeta { + return inst.AccountMetaSlice[2] +} + +func (inst UpdateSolanaChainSelector) Build() *Instruction { + return &Instruction{BaseVariant: ag_binary.BaseVariant{ + Impl: inst, + TypeID: Instruction_UpdateSolanaChainSelector, + }} +} + +// ValidateAndBuild validates the instruction parameters and accounts; +// if there is a validation error, it returns the error. +// Otherwise, it builds and returns the instruction. +func (inst UpdateSolanaChainSelector) ValidateAndBuild() (*Instruction, error) { + if err := inst.Validate(); err != nil { + return nil, err + } + return inst.Build(), nil +} + +func (inst *UpdateSolanaChainSelector) Validate() error { + // Check whether all (required) parameters are set: + { + if inst.NewChainSelector == nil { + return errors.New("NewChainSelector parameter is not set") + } + } + + // Check whether all (required) accounts are set: + { + if inst.AccountMetaSlice[0] == nil { + return errors.New("accounts.Config is not set") + } + if inst.AccountMetaSlice[1] == nil { + return errors.New("accounts.Authority is not set") + } + if inst.AccountMetaSlice[2] == nil { + return errors.New("accounts.SystemProgram is not set") + } + } + return nil +} + +func (inst *UpdateSolanaChainSelector) EncodeToTree(parent ag_treeout.Branches) { + parent.Child(ag_format.Program(ProgramName, ProgramID)). + // + ParentFunc(func(programBranch ag_treeout.Branches) { + programBranch.Child(ag_format.Instruction("UpdateSolanaChainSelector")). + // + ParentFunc(func(instructionBranch ag_treeout.Branches) { + + // Parameters of the instruction: + instructionBranch.Child("Params[len=1]").ParentFunc(func(paramsBranch ag_treeout.Branches) { + paramsBranch.Child(ag_format.Param("NewChainSelector", *inst.NewChainSelector)) + }) + + // Accounts of the instruction: + instructionBranch.Child("Accounts[len=3]").ParentFunc(func(accountsBranch ag_treeout.Branches) { + accountsBranch.Child(ag_format.Meta(" config", inst.AccountMetaSlice[0])) + accountsBranch.Child(ag_format.Meta(" authority", inst.AccountMetaSlice[1])) + accountsBranch.Child(ag_format.Meta("systemProgram", inst.AccountMetaSlice[2])) + }) + }) + }) +} + +func (obj UpdateSolanaChainSelector) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { + // Serialize `NewChainSelector` param: + err = encoder.Encode(obj.NewChainSelector) + if err != nil { + return err + } + return nil +} +func (obj *UpdateSolanaChainSelector) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { + // Deserialize `NewChainSelector`: + err = decoder.Decode(&obj.NewChainSelector) + if err != nil { + return err + } + return nil +} + +// NewUpdateSolanaChainSelectorInstruction declares a new UpdateSolanaChainSelector instruction with the provided parameters and accounts. +func NewUpdateSolanaChainSelectorInstruction( + // Parameters: + newChainSelector uint64, + // Accounts: + config ag_solanago.PublicKey, + authority ag_solanago.PublicKey, + systemProgram ag_solanago.PublicKey) *UpdateSolanaChainSelector { + return NewUpdateSolanaChainSelectorInstructionBuilder(). + SetNewChainSelector(newChainSelector). + SetConfigAccount(config). + SetAuthorityAccount(authority). + SetSystemProgramAccount(systemProgram) +} diff --git a/core/capabilities/ccip/ccipsolana/ccip_router/UpdateSolanaChainSelector_test.go b/core/capabilities/ccip/ccipsolana/ccip_router/UpdateSolanaChainSelector_test.go new file mode 100644 index 00000000000..00901a4a9af --- /dev/null +++ b/core/capabilities/ccip/ccipsolana/ccip_router/UpdateSolanaChainSelector_test.go @@ -0,0 +1,32 @@ +// Code generated by https://github.com/gagliardetto/anchor-go. DO NOT EDIT. + +package ccip_router + +import ( + "bytes" + ag_gofuzz "github.com/gagliardetto/gofuzz" + ag_require "github.com/stretchr/testify/require" + "strconv" + "testing" +) + +func TestEncodeDecode_UpdateSolanaChainSelector(t *testing.T) { + fu := ag_gofuzz.New().NilChance(0) + for i := 0; i < 1; i++ { + t.Run("UpdateSolanaChainSelector"+strconv.Itoa(i), func(t *testing.T) { + { + params := new(UpdateSolanaChainSelector) + fu.Fuzz(params) + params.AccountMetaSlice = nil + buf := new(bytes.Buffer) + err := encodeT(*params, buf) + ag_require.NoError(t, err) + got := new(UpdateSolanaChainSelector) + err = decodeT(got, buf.Bytes()) + got.AccountMetaSlice = nil + ag_require.NoError(t, err) + ag_require.Equal(t, params, got) + } + }) + } +} diff --git a/core/capabilities/ccip/ccipsolana/ccip_router/accounts.go b/core/capabilities/ccip/ccipsolana/ccip_router/accounts.go new file mode 100644 index 00000000000..44c43c1d364 --- /dev/null +++ b/core/capabilities/ccip/ccipsolana/ccip_router/accounts.go @@ -0,0 +1,661 @@ +// Code generated by https://github.com/gagliardetto/anchor-go. DO NOT EDIT. + +package ccip_router + +import ( + "fmt" + ag_binary "github.com/gagliardetto/binary" + ag_solanago "github.com/gagliardetto/solana-go" +) + +type Config struct { + Version uint8 + DefaultAllowOutOfOrderExecution uint8 + Padding0 [6]uint8 + SolanaChainSelector uint64 + DefaultGasLimit ag_binary.Uint128 + Padding1 [8]uint8 + Owner ag_solanago.PublicKey + ProposedOwner ag_solanago.PublicKey + EnableManualExecutionAfter int64 + Padding2 [8]uint8 + Ocr3 [2]Ocr3Config +} + +var ConfigDiscriminator = [8]byte{155, 12, 170, 224, 30, 250, 204, 130} + +func (obj Config) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { + // Write account discriminator: + err = encoder.WriteBytes(ConfigDiscriminator[:], false) + if err != nil { + return err + } + // Serialize `Version` param: + err = encoder.Encode(obj.Version) + if err != nil { + return err + } + // Serialize `DefaultAllowOutOfOrderExecution` param: + err = encoder.Encode(obj.DefaultAllowOutOfOrderExecution) + if err != nil { + return err + } + // Serialize `Padding0` param: + err = encoder.Encode(obj.Padding0) + if err != nil { + return err + } + // Serialize `SolanaChainSelector` param: + err = encoder.Encode(obj.SolanaChainSelector) + if err != nil { + return err + } + // Serialize `DefaultGasLimit` param: + err = encoder.Encode(obj.DefaultGasLimit) + if err != nil { + return err + } + // Serialize `Padding1` param: + err = encoder.Encode(obj.Padding1) + if err != nil { + return err + } + // Serialize `Owner` param: + err = encoder.Encode(obj.Owner) + if err != nil { + return err + } + // Serialize `ProposedOwner` param: + err = encoder.Encode(obj.ProposedOwner) + if err != nil { + return err + } + // Serialize `EnableManualExecutionAfter` param: + err = encoder.Encode(obj.EnableManualExecutionAfter) + if err != nil { + return err + } + // Serialize `Padding2` param: + err = encoder.Encode(obj.Padding2) + if err != nil { + return err + } + // Serialize `Ocr3` param: + err = encoder.Encode(obj.Ocr3) + if err != nil { + return err + } + return nil +} + +func (obj *Config) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { + // Read and check account discriminator: + { + discriminator, err := decoder.ReadTypeID() + if err != nil { + return err + } + if !discriminator.Equal(ConfigDiscriminator[:]) { + return fmt.Errorf( + "wrong discriminator: wanted %s, got %s", + "[155 12 170 224 30 250 204 130]", + fmt.Sprint(discriminator[:])) + } + } + // Deserialize `Version`: + err = decoder.Decode(&obj.Version) + if err != nil { + return err + } + // Deserialize `DefaultAllowOutOfOrderExecution`: + err = decoder.Decode(&obj.DefaultAllowOutOfOrderExecution) + if err != nil { + return err + } + // Deserialize `Padding0`: + err = decoder.Decode(&obj.Padding0) + if err != nil { + return err + } + // Deserialize `SolanaChainSelector`: + err = decoder.Decode(&obj.SolanaChainSelector) + if err != nil { + return err + } + // Deserialize `DefaultGasLimit`: + err = decoder.Decode(&obj.DefaultGasLimit) + if err != nil { + return err + } + // Deserialize `Padding1`: + err = decoder.Decode(&obj.Padding1) + if err != nil { + return err + } + // Deserialize `Owner`: + err = decoder.Decode(&obj.Owner) + if err != nil { + return err + } + // Deserialize `ProposedOwner`: + err = decoder.Decode(&obj.ProposedOwner) + if err != nil { + return err + } + // Deserialize `EnableManualExecutionAfter`: + err = decoder.Decode(&obj.EnableManualExecutionAfter) + if err != nil { + return err + } + // Deserialize `Padding2`: + err = decoder.Decode(&obj.Padding2) + if err != nil { + return err + } + // Deserialize `Ocr3`: + err = decoder.Decode(&obj.Ocr3) + if err != nil { + return err + } + return nil +} + +type ChainState struct { + Version uint8 + SourceChainConfig SourceChainConfig + DestChainConfig DestChainConfig +} + +var ChainStateDiscriminator = [8]byte{130, 46, 94, 156, 79, 53, 170, 50} + +func (obj ChainState) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { + // Write account discriminator: + err = encoder.WriteBytes(ChainStateDiscriminator[:], false) + if err != nil { + return err + } + // Serialize `Version` param: + err = encoder.Encode(obj.Version) + if err != nil { + return err + } + // Serialize `SourceChainConfig` param: + err = encoder.Encode(obj.SourceChainConfig) + if err != nil { + return err + } + // Serialize `DestChainConfig` param: + err = encoder.Encode(obj.DestChainConfig) + if err != nil { + return err + } + return nil +} + +func (obj *ChainState) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { + // Read and check account discriminator: + { + discriminator, err := decoder.ReadTypeID() + if err != nil { + return err + } + if !discriminator.Equal(ChainStateDiscriminator[:]) { + return fmt.Errorf( + "wrong discriminator: wanted %s, got %s", + "[130 46 94 156 79 53 170 50]", + fmt.Sprint(discriminator[:])) + } + } + // Deserialize `Version`: + err = decoder.Decode(&obj.Version) + if err != nil { + return err + } + // Deserialize `SourceChainConfig`: + err = decoder.Decode(&obj.SourceChainConfig) + if err != nil { + return err + } + // Deserialize `DestChainConfig`: + err = decoder.Decode(&obj.DestChainConfig) + if err != nil { + return err + } + return nil +} + +type Nonce struct { + Version uint8 + Counter uint64 +} + +var NonceDiscriminator = [8]byte{143, 197, 147, 95, 106, 165, 50, 43} + +func (obj Nonce) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { + // Write account discriminator: + err = encoder.WriteBytes(NonceDiscriminator[:], false) + if err != nil { + return err + } + // Serialize `Version` param: + err = encoder.Encode(obj.Version) + if err != nil { + return err + } + // Serialize `Counter` param: + err = encoder.Encode(obj.Counter) + if err != nil { + return err + } + return nil +} + +func (obj *Nonce) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { + // Read and check account discriminator: + { + discriminator, err := decoder.ReadTypeID() + if err != nil { + return err + } + if !discriminator.Equal(NonceDiscriminator[:]) { + return fmt.Errorf( + "wrong discriminator: wanted %s, got %s", + "[143 197 147 95 106 165 50 43]", + fmt.Sprint(discriminator[:])) + } + } + // Deserialize `Version`: + err = decoder.Decode(&obj.Version) + if err != nil { + return err + } + // Deserialize `Counter`: + err = decoder.Decode(&obj.Counter) + if err != nil { + return err + } + return nil +} + +type ExternalExecutionConfig struct{} + +var ExternalExecutionConfigDiscriminator = [8]byte{159, 157, 150, 212, 168, 103, 117, 39} + +func (obj ExternalExecutionConfig) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { + // Write account discriminator: + err = encoder.WriteBytes(ExternalExecutionConfigDiscriminator[:], false) + if err != nil { + return err + } + return nil +} + +func (obj *ExternalExecutionConfig) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { + // Read and check account discriminator: + { + discriminator, err := decoder.ReadTypeID() + if err != nil { + return err + } + if !discriminator.Equal(ExternalExecutionConfigDiscriminator[:]) { + return fmt.Errorf( + "wrong discriminator: wanted %s, got %s", + "[159 157 150 212 168 103 117 39]", + fmt.Sprint(discriminator[:])) + } + } + return nil +} + +type CommitReport struct { + Version uint8 + Timestamp int64 + MinMsgNr uint64 + MaxMsgNr uint64 + ExecutionStates ag_binary.Uint128 +} + +var CommitReportDiscriminator = [8]byte{46, 231, 247, 231, 174, 68, 34, 26} + +func (obj CommitReport) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { + // Write account discriminator: + err = encoder.WriteBytes(CommitReportDiscriminator[:], false) + if err != nil { + return err + } + // Serialize `Version` param: + err = encoder.Encode(obj.Version) + if err != nil { + return err + } + // Serialize `Timestamp` param: + err = encoder.Encode(obj.Timestamp) + if err != nil { + return err + } + // Serialize `MinMsgNr` param: + err = encoder.Encode(obj.MinMsgNr) + if err != nil { + return err + } + // Serialize `MaxMsgNr` param: + err = encoder.Encode(obj.MaxMsgNr) + if err != nil { + return err + } + // Serialize `ExecutionStates` param: + err = encoder.Encode(obj.ExecutionStates) + if err != nil { + return err + } + return nil +} + +func (obj *CommitReport) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { + // Read and check account discriminator: + { + discriminator, err := decoder.ReadTypeID() + if err != nil { + return err + } + if !discriminator.Equal(CommitReportDiscriminator[:]) { + return fmt.Errorf( + "wrong discriminator: wanted %s, got %s", + "[46 231 247 231 174 68 34 26]", + fmt.Sprint(discriminator[:])) + } + } + // Deserialize `Version`: + err = decoder.Decode(&obj.Version) + if err != nil { + return err + } + // Deserialize `Timestamp`: + err = decoder.Decode(&obj.Timestamp) + if err != nil { + return err + } + // Deserialize `MinMsgNr`: + err = decoder.Decode(&obj.MinMsgNr) + if err != nil { + return err + } + // Deserialize `MaxMsgNr`: + err = decoder.Decode(&obj.MaxMsgNr) + if err != nil { + return err + } + // Deserialize `ExecutionStates`: + err = decoder.Decode(&obj.ExecutionStates) + if err != nil { + return err + } + return nil +} + +type PerChainPerTokenConfig struct { + Version uint8 + ChainSelector uint64 + Mint ag_solanago.PublicKey + Billing TokenBilling +} + +var PerChainPerTokenConfigDiscriminator = [8]byte{183, 88, 20, 99, 246, 46, 51, 230} + +func (obj PerChainPerTokenConfig) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { + // Write account discriminator: + err = encoder.WriteBytes(PerChainPerTokenConfigDiscriminator[:], false) + if err != nil { + return err + } + // Serialize `Version` param: + err = encoder.Encode(obj.Version) + if err != nil { + return err + } + // Serialize `ChainSelector` param: + err = encoder.Encode(obj.ChainSelector) + if err != nil { + return err + } + // Serialize `Mint` param: + err = encoder.Encode(obj.Mint) + if err != nil { + return err + } + // Serialize `Billing` param: + err = encoder.Encode(obj.Billing) + if err != nil { + return err + } + return nil +} + +func (obj *PerChainPerTokenConfig) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { + // Read and check account discriminator: + { + discriminator, err := decoder.ReadTypeID() + if err != nil { + return err + } + if !discriminator.Equal(PerChainPerTokenConfigDiscriminator[:]) { + return fmt.Errorf( + "wrong discriminator: wanted %s, got %s", + "[183 88 20 99 246 46 51 230]", + fmt.Sprint(discriminator[:])) + } + } + // Deserialize `Version`: + err = decoder.Decode(&obj.Version) + if err != nil { + return err + } + // Deserialize `ChainSelector`: + err = decoder.Decode(&obj.ChainSelector) + if err != nil { + return err + } + // Deserialize `Mint`: + err = decoder.Decode(&obj.Mint) + if err != nil { + return err + } + // Deserialize `Billing`: + err = decoder.Decode(&obj.Billing) + if err != nil { + return err + } + return nil +} + +type BillingTokenConfig struct { + Version uint8 + Enabled bool + UsdPerToken TimestampedPackedU224 + PremiumMultiplierWeiPerEth uint64 +} + +var BillingTokenConfigDiscriminator = [8]byte{191, 91, 1, 0, 93, 250, 239, 41} + +func (obj BillingTokenConfig) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { + // Write account discriminator: + err = encoder.WriteBytes(BillingTokenConfigDiscriminator[:], false) + if err != nil { + return err + } + // Serialize `Version` param: + err = encoder.Encode(obj.Version) + if err != nil { + return err + } + // Serialize `Enabled` param: + err = encoder.Encode(obj.Enabled) + if err != nil { + return err + } + // Serialize `UsdPerToken` param: + err = encoder.Encode(obj.UsdPerToken) + if err != nil { + return err + } + // Serialize `PremiumMultiplierWeiPerEth` param: + err = encoder.Encode(obj.PremiumMultiplierWeiPerEth) + if err != nil { + return err + } + return nil +} + +func (obj *BillingTokenConfig) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { + // Read and check account discriminator: + { + discriminator, err := decoder.ReadTypeID() + if err != nil { + return err + } + if !discriminator.Equal(BillingTokenConfigDiscriminator[:]) { + return fmt.Errorf( + "wrong discriminator: wanted %s, got %s", + "[191 91 1 0 93 250 239 41]", + fmt.Sprint(discriminator[:])) + } + } + // Deserialize `Version`: + err = decoder.Decode(&obj.Version) + if err != nil { + return err + } + // Deserialize `Enabled`: + err = decoder.Decode(&obj.Enabled) + if err != nil { + return err + } + // Deserialize `UsdPerToken`: + err = decoder.Decode(&obj.UsdPerToken) + if err != nil { + return err + } + // Deserialize `PremiumMultiplierWeiPerEth`: + err = decoder.Decode(&obj.PremiumMultiplierWeiPerEth) + if err != nil { + return err + } + return nil +} + +type TokenAdminRegistry struct { + Version uint8 + Administrator ag_solanago.PublicKey + PendingAdministrator *ag_solanago.PublicKey `bin:"optional"` + TokenPoolProgram *ag_solanago.PublicKey `bin:"optional"` +} + +var TokenAdminRegistryDiscriminator = [8]byte{70, 92, 207, 200, 76, 17, 57, 114} + +func (obj TokenAdminRegistry) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { + // Write account discriminator: + err = encoder.WriteBytes(TokenAdminRegistryDiscriminator[:], false) + if err != nil { + return err + } + // Serialize `Version` param: + err = encoder.Encode(obj.Version) + if err != nil { + return err + } + // Serialize `Administrator` param: + err = encoder.Encode(obj.Administrator) + if err != nil { + return err + } + // Serialize `PendingAdministrator` param (optional): + { + if obj.PendingAdministrator == nil { + err = encoder.WriteBool(false) + if err != nil { + return err + } + } else { + err = encoder.WriteBool(true) + if err != nil { + return err + } + err = encoder.Encode(obj.PendingAdministrator) + if err != nil { + return err + } + } + } + // Serialize `TokenPoolProgram` param (optional): + { + if obj.TokenPoolProgram == nil { + err = encoder.WriteBool(false) + if err != nil { + return err + } + } else { + err = encoder.WriteBool(true) + if err != nil { + return err + } + err = encoder.Encode(obj.TokenPoolProgram) + if err != nil { + return err + } + } + } + return nil +} + +func (obj *TokenAdminRegistry) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { + // Read and check account discriminator: + { + discriminator, err := decoder.ReadTypeID() + if err != nil { + return err + } + if !discriminator.Equal(TokenAdminRegistryDiscriminator[:]) { + return fmt.Errorf( + "wrong discriminator: wanted %s, got %s", + "[70 92 207 200 76 17 57 114]", + fmt.Sprint(discriminator[:])) + } + } + // Deserialize `Version`: + err = decoder.Decode(&obj.Version) + if err != nil { + return err + } + // Deserialize `Administrator`: + err = decoder.Decode(&obj.Administrator) + if err != nil { + return err + } + // Deserialize `PendingAdministrator` (optional): + { + ok, err := decoder.ReadBool() + if err != nil { + return err + } + if ok { + err = decoder.Decode(&obj.PendingAdministrator) + if err != nil { + return err + } + } + } + // Deserialize `TokenPoolProgram` (optional): + { + ok, err := decoder.ReadBool() + if err != nil { + return err + } + if ok { + err = decoder.Decode(&obj.TokenPoolProgram) + if err != nil { + return err + } + } + } + return nil +} diff --git a/core/capabilities/ccip/ccipsolana/ccip_router/instructions.go b/core/capabilities/ccip/ccipsolana/ccip_router/instructions.go new file mode 100644 index 00000000000..395e39da2ea --- /dev/null +++ b/core/capabilities/ccip/ccipsolana/ccip_router/instructions.go @@ -0,0 +1,304 @@ +// This is the Collapsed Router Program for CCIP. +// As it's upgradable persisting the same program id, there is no need to have an indirection of a Proxy Program. +// This Router handles both the OnRamp and OffRamp flow of the CCIP Messages. +// Code generated by https://github.com/gagliardetto/anchor-go. DO NOT EDIT. + +package ccip_router + +import ( + "bytes" + "fmt" + ag_spew "github.com/davecgh/go-spew/spew" + ag_binary "github.com/gagliardetto/binary" + ag_solanago "github.com/gagliardetto/solana-go" + ag_text "github.com/gagliardetto/solana-go/text" + ag_treeout "github.com/gagliardetto/treeout" +) + +var ProgramID ag_solanago.PublicKey + +func SetProgramID(pubkey ag_solanago.PublicKey) { + ProgramID = pubkey + ag_solanago.RegisterInstructionDecoder(ProgramID, registryDecodeInstruction) +} + +const ProgramName = "CcipRouter" + +func init() { + if !ProgramID.IsZero() { + ag_solanago.RegisterInstructionDecoder(ProgramID, registryDecodeInstruction) + } +} + +var ( + // The initialization is responsibility of Admin, nothing more than calling this method should be done first. + Instruction_Initialize = ag_binary.TypeID([8]byte{175, 175, 109, 31, 13, 152, 155, 237}) + + Instruction_TransferOwnership = ag_binary.TypeID([8]byte{65, 177, 215, 73, 53, 45, 99, 47}) + + Instruction_AcceptOwnership = ag_binary.TypeID([8]byte{172, 23, 43, 13, 238, 213, 85, 150}) + + // The Admin needs to add any new chain supported (this means both OnRamp and OffRamp). + Instruction_AddChainSelector = ag_binary.TypeID([8]byte{28, 60, 171, 0, 195, 113, 56, 7}) + + // The Admin is the only one able to enable or disable the chain selector + Instruction_DisableChainSelector = ag_binary.TypeID([8]byte{24, 245, 159, 178, 139, 200, 133, 218}) + + // The Admin is the only one able to enable or disable the chain selector + Instruction_EnableChainSelector = ag_binary.TypeID([8]byte{29, 175, 195, 14, 137, 66, 194, 25}) + + // The Admin can update the configuration of the Router, in this case the Solana Chain Selector + Instruction_UpdateSolanaChainSelector = ag_binary.TypeID([8]byte{128, 198, 143, 222, 43, 55, 119, 106}) + + // The Admin can update the configuration of the Router, in this case the Default Gas Limit + Instruction_UpdateDefaultGasLimit = ag_binary.TypeID([8]byte{201, 34, 231, 229, 247, 252, 77, 210}) + + // The Admin can update the configuration of the Router, in this case the Default Allow Out Of Order Execution (True/False) + Instruction_UpdateDefaultAllowOutOfOrderExecution = ag_binary.TypeID([8]byte{44, 54, 136, 71, 177, 17, 18, 241}) + + // The Admin can update the configuration of the Router, in this case the Enable Manual Execution After + Instruction_UpdateEnableManualExecutionAfter = ag_binary.TypeID([8]byte{157, 236, 73, 92, 84, 197, 152, 105}) + + // The CCIP Admin or the Mint Authority of the Token can register the Token Admin Registry + Instruction_RegisterTokenAdminRegistryViaGetCcipAdmin = ag_binary.TypeID([8]byte{46, 246, 21, 58, 175, 69, 40, 202}) + + // The Token's mint_authority can register themselves to the Token Admin Registry + Instruction_RegisterTokenAdminRegistryViaOwner = ag_binary.TypeID([8]byte{85, 191, 10, 113, 134, 138, 144, 16}) + + // The administrator of the token can setup the token pool + Instruction_SetPool = ag_binary.TypeID([8]byte{119, 30, 14, 180, 115, 225, 167, 238}) + + // The Admin can transfer the Admin Role of the Token Admin Registry + Instruction_TransferAdminRoleTokenAdminRegistry = ag_binary.TypeID([8]byte{178, 98, 203, 181, 203, 107, 106, 14}) + + // The Pending Admin can accept the Admin Role of the Token Admin Registry + Instruction_AcceptAdminRoleTokenAdminRegistry = ag_binary.TypeID([8]byte{106, 240, 16, 173, 137, 213, 163, 246}) + + Instruction_SetTokenBilling = ag_binary.TypeID([8]byte{225, 230, 37, 71, 131, 209, 54, 230}) + + Instruction_SetOcrConfig = ag_binary.TypeID([8]byte{4, 131, 107, 110, 250, 158, 244, 200}) + + // ON RAMP FLOW + // The method name needs to be ccip_send with Anchor encoding. + // This function is called by the CCIP Sender Contract (or final user) to send a message to the CCIP Router. + // The size limit of data is 256 bytes. + // The message is sent to the receiver on the destination chain selector. + // This message emits the event CCIPSendRequested with all the necessary data to be retrieved by the OffChain Code + Instruction_CcipSend = ag_binary.TypeID([8]byte{108, 216, 134, 191, 249, 234, 33, 84}) + + // OFF RAMP FLOW + // + // The method name needs to be commit with Anchor encoding. + // + // This function is called by the OffChain when committing one Report to the Solana Router. + // In this Flow only one report is sent, the Commit Report. This is different as EVM does, + // this is because here all the chain state is stored in one account per Merkle Tree Root. + // So, to avoid having to send a dynamic size array of accounts, in this message only one Commit Report Account is sent. + // This message validates the signatures of the report and stores the Merkle Root in the Commit Report Account. + // The Report must contain an interval of messages, and the min of them must be the next sequence number expected. + // The max size of the interval is 64. + // This message emits two events: CommitReportAccepted and Transmitted. + Instruction_Commit = ag_binary.TypeID([8]byte{223, 140, 142, 165, 229, 208, 156, 74}) + + // OFF RAMP FLOW + // + // The method name needs to be execute with Anchor encoding. + // + // This function is called by the OffChain when executing one Report to the Solana Router. + // In this Flow only one message is sent, the Execution Report. This is different as EVM does, + // this is because there is no try/catch mechanism to allow batch execution. + // This message validates that the Merkle Tree Proof of the given message is correct and is stored in the Commit Report Account. + // The message must be untouched to be executed. + // This message emits the event ExecutionStateChanged with the new state of the message. + // Finally, executes the CPI instruction to the receiver program in the ccip_receive message. + Instruction_Execute = ag_binary.TypeID([8]byte{130, 221, 242, 154, 13, 193, 189, 29}) + + // When a message is not being executed, then the user can trigger the execution manually. + // No verification over the transmitter, but the message needs to be in some commit report. + Instruction_ManuallyExecute = ag_binary.TypeID([8]byte{238, 219, 224, 11, 226, 248, 47, 192}) +) + +// InstructionIDToName returns the name of the instruction given its ID. +func InstructionIDToName(id ag_binary.TypeID) string { + switch id { + case Instruction_Initialize: + return "Initialize" + case Instruction_TransferOwnership: + return "TransferOwnership" + case Instruction_AcceptOwnership: + return "AcceptOwnership" + case Instruction_AddChainSelector: + return "AddChainSelector" + case Instruction_DisableChainSelector: + return "DisableChainSelector" + case Instruction_EnableChainSelector: + return "EnableChainSelector" + case Instruction_UpdateSolanaChainSelector: + return "UpdateSolanaChainSelector" + case Instruction_UpdateDefaultGasLimit: + return "UpdateDefaultGasLimit" + case Instruction_UpdateDefaultAllowOutOfOrderExecution: + return "UpdateDefaultAllowOutOfOrderExecution" + case Instruction_UpdateEnableManualExecutionAfter: + return "UpdateEnableManualExecutionAfter" + case Instruction_RegisterTokenAdminRegistryViaGetCcipAdmin: + return "RegisterTokenAdminRegistryViaGetCcipAdmin" + case Instruction_RegisterTokenAdminRegistryViaOwner: + return "RegisterTokenAdminRegistryViaOwner" + case Instruction_SetPool: + return "SetPool" + case Instruction_TransferAdminRoleTokenAdminRegistry: + return "TransferAdminRoleTokenAdminRegistry" + case Instruction_AcceptAdminRoleTokenAdminRegistry: + return "AcceptAdminRoleTokenAdminRegistry" + case Instruction_SetTokenBilling: + return "SetTokenBilling" + case Instruction_SetOcrConfig: + return "SetOcrConfig" + case Instruction_CcipSend: + return "CcipSend" + case Instruction_Commit: + return "Commit" + case Instruction_Execute: + return "Execute" + case Instruction_ManuallyExecute: + return "ManuallyExecute" + default: + return "" + } +} + +type Instruction struct { + ag_binary.BaseVariant +} + +func (inst *Instruction) EncodeToTree(parent ag_treeout.Branches) { + if enToTree, ok := inst.Impl.(ag_text.EncodableToTree); ok { + enToTree.EncodeToTree(parent) + } else { + parent.Child(ag_spew.Sdump(inst)) + } +} + +var InstructionImplDef = ag_binary.NewVariantDefinition( + ag_binary.AnchorTypeIDEncoding, + []ag_binary.VariantType{ + { + "initialize", (*Initialize)(nil), + }, + { + "transfer_ownership", (*TransferOwnership)(nil), + }, + { + "accept_ownership", (*AcceptOwnership)(nil), + }, + { + "add_chain_selector", (*AddChainSelector)(nil), + }, + { + "disable_chain_selector", (*DisableChainSelector)(nil), + }, + { + "enable_chain_selector", (*EnableChainSelector)(nil), + }, + { + "update_solana_chain_selector", (*UpdateSolanaChainSelector)(nil), + }, + { + "update_default_gas_limit", (*UpdateDefaultGasLimit)(nil), + }, + { + "update_default_allow_out_of_order_execution", (*UpdateDefaultAllowOutOfOrderExecution)(nil), + }, + { + "update_enable_manual_execution_after", (*UpdateEnableManualExecutionAfter)(nil), + }, + { + "register_token_admin_registry_via_get_ccip_admin", (*RegisterTokenAdminRegistryViaGetCcipAdmin)(nil), + }, + { + "register_token_admin_registry_via_owner", (*RegisterTokenAdminRegistryViaOwner)(nil), + }, + { + "set_pool", (*SetPool)(nil), + }, + { + "transfer_admin_role_token_admin_registry", (*TransferAdminRoleTokenAdminRegistry)(nil), + }, + { + "accept_admin_role_token_admin_registry", (*AcceptAdminRoleTokenAdminRegistry)(nil), + }, + { + "set_token_billing", (*SetTokenBilling)(nil), + }, + { + "set_ocr_config", (*SetOcrConfig)(nil), + }, + { + "ccip_send", (*CcipSend)(nil), + }, + { + "commit", (*Commit)(nil), + }, + { + "execute", (*Execute)(nil), + }, + { + "manually_execute", (*ManuallyExecute)(nil), + }, + }, +) + +func (inst *Instruction) ProgramID() ag_solanago.PublicKey { + return ProgramID +} + +func (inst *Instruction) Accounts() (out []*ag_solanago.AccountMeta) { + return inst.Impl.(ag_solanago.AccountsGettable).GetAccounts() +} + +func (inst *Instruction) Data() ([]byte, error) { + buf := new(bytes.Buffer) + if err := ag_binary.NewBorshEncoder(buf).Encode(inst); err != nil { + return nil, fmt.Errorf("unable to encode instruction: %w", err) + } + return buf.Bytes(), nil +} + +func (inst *Instruction) TextEncode(encoder *ag_text.Encoder, option *ag_text.Option) error { + return encoder.Encode(inst.Impl, option) +} + +func (inst *Instruction) UnmarshalWithDecoder(decoder *ag_binary.Decoder) error { + return inst.BaseVariant.UnmarshalBinaryVariant(decoder, InstructionImplDef) +} + +func (inst *Instruction) MarshalWithEncoder(encoder *ag_binary.Encoder) error { + err := encoder.WriteBytes(inst.TypeID.Bytes(), false) + if err != nil { + return fmt.Errorf("unable to write variant type: %w", err) + } + return encoder.Encode(inst.Impl) +} + +func registryDecodeInstruction(accounts []*ag_solanago.AccountMeta, data []byte) (interface{}, error) { + inst, err := DecodeInstruction(accounts, data) + if err != nil { + return nil, err + } + return inst, nil +} + +func DecodeInstruction(accounts []*ag_solanago.AccountMeta, data []byte) (*Instruction, error) { + inst := new(Instruction) + if err := ag_binary.NewBorshDecoder(data).Decode(inst); err != nil { + return nil, fmt.Errorf("unable to decode instruction: %w", err) + } + if v, ok := inst.Impl.(ag_solanago.AccountsSettable); ok { + err := v.SetAccounts(accounts) + if err != nil { + return nil, fmt.Errorf("unable to set accounts for instruction: %w", err) + } + } + return inst, nil +} diff --git a/core/capabilities/ccip/ccipsolana/ccip_router/testing_utils.go b/core/capabilities/ccip/ccipsolana/ccip_router/testing_utils.go new file mode 100644 index 00000000000..aaecdf49bad --- /dev/null +++ b/core/capabilities/ccip/ccipsolana/ccip_router/testing_utils.go @@ -0,0 +1,20 @@ +// Code generated by https://github.com/gagliardetto/anchor-go. DO NOT EDIT. + +package ccip_router + +import ( + "bytes" + "fmt" + ag_binary "github.com/gagliardetto/binary" +) + +func encodeT(data interface{}, buf *bytes.Buffer) error { + if err := ag_binary.NewBorshEncoder(buf).Encode(data); err != nil { + return fmt.Errorf("unable to encode instruction: %w", err) + } + return nil +} + +func decodeT(dst interface{}, data []byte) error { + return ag_binary.NewBorshDecoder(data).Decode(dst) +} diff --git a/core/capabilities/ccip/ccipsolana/ccip_router/types.go b/core/capabilities/ccip/ccipsolana/ccip_router/types.go new file mode 100644 index 00000000000..1c3167a1fcc --- /dev/null +++ b/core/capabilities/ccip/ccipsolana/ccip_router/types.go @@ -0,0 +1,1817 @@ +// Code generated by https://github.com/gagliardetto/anchor-go. DO NOT EDIT. + +package ccip_router + +import ( + ag_binary "github.com/gagliardetto/binary" + ag_solanago "github.com/gagliardetto/solana-go" +) + +type CommitInput struct { + PriceUpdates PriceUpdates + MerkleRoot MerkleRoot +} + +func (obj CommitInput) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { + // Serialize `PriceUpdates` param: + err = encoder.Encode(obj.PriceUpdates) + if err != nil { + return err + } + // Serialize `MerkleRoot` param: + err = encoder.Encode(obj.MerkleRoot) + if err != nil { + return err + } + return nil +} + +func (obj *CommitInput) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { + // Deserialize `PriceUpdates`: + err = decoder.Decode(&obj.PriceUpdates) + if err != nil { + return err + } + // Deserialize `MerkleRoot`: + err = decoder.Decode(&obj.MerkleRoot) + if err != nil { + return err + } + return nil +} + +type PriceUpdates struct { + TokenPriceUpdates []TokenPriceUpdate + GasPriceUpdates []GasPriceUpdate +} + +func (obj PriceUpdates) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { + // Serialize `TokenPriceUpdates` param: + err = encoder.Encode(obj.TokenPriceUpdates) + if err != nil { + return err + } + // Serialize `GasPriceUpdates` param: + err = encoder.Encode(obj.GasPriceUpdates) + if err != nil { + return err + } + return nil +} + +func (obj *PriceUpdates) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { + // Deserialize `TokenPriceUpdates`: + err = decoder.Decode(&obj.TokenPriceUpdates) + if err != nil { + return err + } + // Deserialize `GasPriceUpdates`: + err = decoder.Decode(&obj.GasPriceUpdates) + if err != nil { + return err + } + return nil +} + +type TokenPriceUpdate struct { + SourceToken ag_solanago.PublicKey + UsdPerToken [28]uint8 +} + +func (obj TokenPriceUpdate) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { + // Serialize `SourceToken` param: + err = encoder.Encode(obj.SourceToken) + if err != nil { + return err + } + // Serialize `UsdPerToken` param: + err = encoder.Encode(obj.UsdPerToken) + if err != nil { + return err + } + return nil +} + +func (obj *TokenPriceUpdate) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { + // Deserialize `SourceToken`: + err = decoder.Decode(&obj.SourceToken) + if err != nil { + return err + } + // Deserialize `UsdPerToken`: + err = decoder.Decode(&obj.UsdPerToken) + if err != nil { + return err + } + return nil +} + +type GasPriceUpdate struct { + DestChainSelector uint64 + UsdPerUnitGas [28]uint8 +} + +func (obj GasPriceUpdate) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { + // Serialize `DestChainSelector` param: + err = encoder.Encode(obj.DestChainSelector) + if err != nil { + return err + } + // Serialize `UsdPerUnitGas` param: + err = encoder.Encode(obj.UsdPerUnitGas) + if err != nil { + return err + } + return nil +} + +func (obj *GasPriceUpdate) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { + // Deserialize `DestChainSelector`: + err = decoder.Decode(&obj.DestChainSelector) + if err != nil { + return err + } + // Deserialize `UsdPerUnitGas`: + err = decoder.Decode(&obj.UsdPerUnitGas) + if err != nil { + return err + } + return nil +} + +type MerkleRoot struct { + SourceChainSelector uint64 + OnRampAddress []byte + MinSeqNr uint64 + MaxSeqNr uint64 + MerkleRoot [32]uint8 +} + +func (obj MerkleRoot) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { + // Serialize `SourceChainSelector` param: + err = encoder.Encode(obj.SourceChainSelector) + if err != nil { + return err + } + // Serialize `OnRampAddress` param: + err = encoder.Encode(obj.OnRampAddress) + if err != nil { + return err + } + // Serialize `MinSeqNr` param: + err = encoder.Encode(obj.MinSeqNr) + if err != nil { + return err + } + // Serialize `MaxSeqNr` param: + err = encoder.Encode(obj.MaxSeqNr) + if err != nil { + return err + } + // Serialize `MerkleRoot` param: + err = encoder.Encode(obj.MerkleRoot) + if err != nil { + return err + } + return nil +} + +func (obj *MerkleRoot) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { + // Deserialize `SourceChainSelector`: + err = decoder.Decode(&obj.SourceChainSelector) + if err != nil { + return err + } + // Deserialize `OnRampAddress`: + err = decoder.Decode(&obj.OnRampAddress) + if err != nil { + return err + } + // Deserialize `MinSeqNr`: + err = decoder.Decode(&obj.MinSeqNr) + if err != nil { + return err + } + // Deserialize `MaxSeqNr`: + err = decoder.Decode(&obj.MaxSeqNr) + if err != nil { + return err + } + // Deserialize `MerkleRoot`: + err = decoder.Decode(&obj.MerkleRoot) + if err != nil { + return err + } + return nil +} + +type Solana2AnyMessage struct { + Receiver []byte + Data []byte + TokenAmounts []SolanaTokenAmount + FeeToken ag_solanago.PublicKey + ExtraArgs ExtraArgsInput + TokenIndexes []byte +} + +func (obj Solana2AnyMessage) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { + // Serialize `Receiver` param: + err = encoder.Encode(obj.Receiver) + if err != nil { + return err + } + // Serialize `Data` param: + err = encoder.Encode(obj.Data) + if err != nil { + return err + } + // Serialize `TokenAmounts` param: + err = encoder.Encode(obj.TokenAmounts) + if err != nil { + return err + } + // Serialize `FeeToken` param: + err = encoder.Encode(obj.FeeToken) + if err != nil { + return err + } + // Serialize `ExtraArgs` param: + err = encoder.Encode(obj.ExtraArgs) + if err != nil { + return err + } + // Serialize `TokenIndexes` param: + err = encoder.Encode(obj.TokenIndexes) + if err != nil { + return err + } + return nil +} + +func (obj *Solana2AnyMessage) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { + // Deserialize `Receiver`: + err = decoder.Decode(&obj.Receiver) + if err != nil { + return err + } + // Deserialize `Data`: + err = decoder.Decode(&obj.Data) + if err != nil { + return err + } + // Deserialize `TokenAmounts`: + err = decoder.Decode(&obj.TokenAmounts) + if err != nil { + return err + } + // Deserialize `FeeToken`: + err = decoder.Decode(&obj.FeeToken) + if err != nil { + return err + } + // Deserialize `ExtraArgs`: + err = decoder.Decode(&obj.ExtraArgs) + if err != nil { + return err + } + // Deserialize `TokenIndexes`: + err = decoder.Decode(&obj.TokenIndexes) + if err != nil { + return err + } + return nil +} + +type SolanaTokenAmount struct { + Token ag_solanago.PublicKey + Amount uint64 +} + +func (obj SolanaTokenAmount) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { + // Serialize `Token` param: + err = encoder.Encode(obj.Token) + if err != nil { + return err + } + // Serialize `Amount` param: + err = encoder.Encode(obj.Amount) + if err != nil { + return err + } + return nil +} + +func (obj *SolanaTokenAmount) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { + // Deserialize `Token`: + err = decoder.Decode(&obj.Token) + if err != nil { + return err + } + // Deserialize `Amount`: + err = decoder.Decode(&obj.Amount) + if err != nil { + return err + } + return nil +} + +type ExtraArgsInput struct { + GasLimit *ag_binary.Uint128 `bin:"optional"` + AllowOutOfOrderExecution *bool `bin:"optional"` +} + +func (obj ExtraArgsInput) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { + // Serialize `GasLimit` param (optional): + { + if obj.GasLimit == nil { + err = encoder.WriteBool(false) + if err != nil { + return err + } + } else { + err = encoder.WriteBool(true) + if err != nil { + return err + } + err = encoder.Encode(obj.GasLimit) + if err != nil { + return err + } + } + } + // Serialize `AllowOutOfOrderExecution` param (optional): + { + if obj.AllowOutOfOrderExecution == nil { + err = encoder.WriteBool(false) + if err != nil { + return err + } + } else { + err = encoder.WriteBool(true) + if err != nil { + return err + } + err = encoder.Encode(obj.AllowOutOfOrderExecution) + if err != nil { + return err + } + } + } + return nil +} + +func (obj *ExtraArgsInput) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { + // Deserialize `GasLimit` (optional): + { + ok, err := decoder.ReadBool() + if err != nil { + return err + } + if ok { + err = decoder.Decode(&obj.GasLimit) + if err != nil { + return err + } + } + } + // Deserialize `AllowOutOfOrderExecution` (optional): + { + ok, err := decoder.ReadBool() + if err != nil { + return err + } + if ok { + err = decoder.Decode(&obj.AllowOutOfOrderExecution) + if err != nil { + return err + } + } + } + return nil +} + +type Any2SolanaMessage struct { + MessageId [32]uint8 + SourceChainSelector uint64 + Sender []byte + Data []byte + TokenAmounts []SolanaTokenAmount +} + +func (obj Any2SolanaMessage) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { + // Serialize `MessageId` param: + err = encoder.Encode(obj.MessageId) + if err != nil { + return err + } + // Serialize `SourceChainSelector` param: + err = encoder.Encode(obj.SourceChainSelector) + if err != nil { + return err + } + // Serialize `Sender` param: + err = encoder.Encode(obj.Sender) + if err != nil { + return err + } + // Serialize `Data` param: + err = encoder.Encode(obj.Data) + if err != nil { + return err + } + // Serialize `TokenAmounts` param: + err = encoder.Encode(obj.TokenAmounts) + if err != nil { + return err + } + return nil +} + +func (obj *Any2SolanaMessage) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { + // Deserialize `MessageId`: + err = decoder.Decode(&obj.MessageId) + if err != nil { + return err + } + // Deserialize `SourceChainSelector`: + err = decoder.Decode(&obj.SourceChainSelector) + if err != nil { + return err + } + // Deserialize `Sender`: + err = decoder.Decode(&obj.Sender) + if err != nil { + return err + } + // Deserialize `Data`: + err = decoder.Decode(&obj.Data) + if err != nil { + return err + } + // Deserialize `TokenAmounts`: + err = decoder.Decode(&obj.TokenAmounts) + if err != nil { + return err + } + return nil +} + +type RampMessageHeader struct { + MessageId [32]uint8 + SourceChainSelector uint64 + DestChainSelector uint64 + SequenceNumber uint64 + Nonce uint64 +} + +func (obj RampMessageHeader) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { + // Serialize `MessageId` param: + err = encoder.Encode(obj.MessageId) + if err != nil { + return err + } + // Serialize `SourceChainSelector` param: + err = encoder.Encode(obj.SourceChainSelector) + if err != nil { + return err + } + // Serialize `DestChainSelector` param: + err = encoder.Encode(obj.DestChainSelector) + if err != nil { + return err + } + // Serialize `SequenceNumber` param: + err = encoder.Encode(obj.SequenceNumber) + if err != nil { + return err + } + // Serialize `Nonce` param: + err = encoder.Encode(obj.Nonce) + if err != nil { + return err + } + return nil +} + +func (obj *RampMessageHeader) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { + // Deserialize `MessageId`: + err = decoder.Decode(&obj.MessageId) + if err != nil { + return err + } + // Deserialize `SourceChainSelector`: + err = decoder.Decode(&obj.SourceChainSelector) + if err != nil { + return err + } + // Deserialize `DestChainSelector`: + err = decoder.Decode(&obj.DestChainSelector) + if err != nil { + return err + } + // Deserialize `SequenceNumber`: + err = decoder.Decode(&obj.SequenceNumber) + if err != nil { + return err + } + // Deserialize `Nonce`: + err = decoder.Decode(&obj.Nonce) + if err != nil { + return err + } + return nil +} + +type ExecutionReportSingleChain struct { + SourceChainSelector uint64 + Message Any2SolanaRampMessage + OffchainTokenData [][]byte + Root [32]uint8 + Proofs [][32]uint8 + TokenIndexes []byte +} + +func (obj ExecutionReportSingleChain) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { + // Serialize `SourceChainSelector` param: + err = encoder.Encode(obj.SourceChainSelector) + if err != nil { + return err + } + // Serialize `Message` param: + err = encoder.Encode(obj.Message) + if err != nil { + return err + } + // Serialize `OffchainTokenData` param: + err = encoder.Encode(obj.OffchainTokenData) + if err != nil { + return err + } + // Serialize `Root` param: + err = encoder.Encode(obj.Root) + if err != nil { + return err + } + // Serialize `Proofs` param: + err = encoder.Encode(obj.Proofs) + if err != nil { + return err + } + // Serialize `TokenIndexes` param: + err = encoder.Encode(obj.TokenIndexes) + if err != nil { + return err + } + return nil +} + +func (obj *ExecutionReportSingleChain) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { + // Deserialize `SourceChainSelector`: + err = decoder.Decode(&obj.SourceChainSelector) + if err != nil { + return err + } + // Deserialize `Message`: + err = decoder.Decode(&obj.Message) + if err != nil { + return err + } + // Deserialize `OffchainTokenData`: + err = decoder.Decode(&obj.OffchainTokenData) + if err != nil { + return err + } + // Deserialize `Root`: + err = decoder.Decode(&obj.Root) + if err != nil { + return err + } + // Deserialize `Proofs`: + err = decoder.Decode(&obj.Proofs) + if err != nil { + return err + } + // Deserialize `TokenIndexes`: + err = decoder.Decode(&obj.TokenIndexes) + if err != nil { + return err + } + return nil +} + +type SolanaExtraArgs struct { + ComputeUnits uint32 + AllowOutOfOrderExecution bool +} + +func (obj SolanaExtraArgs) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { + // Serialize `ComputeUnits` param: + err = encoder.Encode(obj.ComputeUnits) + if err != nil { + return err + } + // Serialize `AllowOutOfOrderExecution` param: + err = encoder.Encode(obj.AllowOutOfOrderExecution) + if err != nil { + return err + } + return nil +} + +func (obj *SolanaExtraArgs) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { + // Deserialize `ComputeUnits`: + err = decoder.Decode(&obj.ComputeUnits) + if err != nil { + return err + } + // Deserialize `AllowOutOfOrderExecution`: + err = decoder.Decode(&obj.AllowOutOfOrderExecution) + if err != nil { + return err + } + return nil +} + +type EvmExtraArgs struct { + GasLimit ag_binary.Uint128 + AllowOutOfOrderExecution bool +} + +func (obj EvmExtraArgs) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { + // Serialize `GasLimit` param: + err = encoder.Encode(obj.GasLimit) + if err != nil { + return err + } + // Serialize `AllowOutOfOrderExecution` param: + err = encoder.Encode(obj.AllowOutOfOrderExecution) + if err != nil { + return err + } + return nil +} + +func (obj *EvmExtraArgs) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { + // Deserialize `GasLimit`: + err = decoder.Decode(&obj.GasLimit) + if err != nil { + return err + } + // Deserialize `AllowOutOfOrderExecution`: + err = decoder.Decode(&obj.AllowOutOfOrderExecution) + if err != nil { + return err + } + return nil +} + +type Any2SolanaRampMessage struct { + Header RampMessageHeader + Sender []byte + Data []byte + Receiver ag_solanago.PublicKey + TokenAmounts []Any2SolanaTokenTransfer + ExtraArgs SolanaExtraArgs +} + +func (obj Any2SolanaRampMessage) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { + // Serialize `Header` param: + err = encoder.Encode(obj.Header) + if err != nil { + return err + } + // Serialize `Sender` param: + err = encoder.Encode(obj.Sender) + if err != nil { + return err + } + // Serialize `Data` param: + err = encoder.Encode(obj.Data) + if err != nil { + return err + } + // Serialize `Receiver` param: + err = encoder.Encode(obj.Receiver) + if err != nil { + return err + } + // Serialize `TokenAmounts` param: + err = encoder.Encode(obj.TokenAmounts) + if err != nil { + return err + } + // Serialize `ExtraArgs` param: + err = encoder.Encode(obj.ExtraArgs) + if err != nil { + return err + } + return nil +} + +func (obj *Any2SolanaRampMessage) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { + // Deserialize `Header`: + err = decoder.Decode(&obj.Header) + if err != nil { + return err + } + // Deserialize `Sender`: + err = decoder.Decode(&obj.Sender) + if err != nil { + return err + } + // Deserialize `Data`: + err = decoder.Decode(&obj.Data) + if err != nil { + return err + } + // Deserialize `Receiver`: + err = decoder.Decode(&obj.Receiver) + if err != nil { + return err + } + // Deserialize `TokenAmounts`: + err = decoder.Decode(&obj.TokenAmounts) + if err != nil { + return err + } + // Deserialize `ExtraArgs`: + err = decoder.Decode(&obj.ExtraArgs) + if err != nil { + return err + } + return nil +} + +type Solana2AnyRampMessage struct { + Header RampMessageHeader + Sender ag_solanago.PublicKey + Data []byte + Receiver []byte + ExtraArgs EvmExtraArgs + FeeToken ag_solanago.PublicKey + TokenAmounts []Solana2AnyTokenTransfer +} + +func (obj Solana2AnyRampMessage) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { + // Serialize `Header` param: + err = encoder.Encode(obj.Header) + if err != nil { + return err + } + // Serialize `Sender` param: + err = encoder.Encode(obj.Sender) + if err != nil { + return err + } + // Serialize `Data` param: + err = encoder.Encode(obj.Data) + if err != nil { + return err + } + // Serialize `Receiver` param: + err = encoder.Encode(obj.Receiver) + if err != nil { + return err + } + // Serialize `ExtraArgs` param: + err = encoder.Encode(obj.ExtraArgs) + if err != nil { + return err + } + // Serialize `FeeToken` param: + err = encoder.Encode(obj.FeeToken) + if err != nil { + return err + } + // Serialize `TokenAmounts` param: + err = encoder.Encode(obj.TokenAmounts) + if err != nil { + return err + } + return nil +} + +func (obj *Solana2AnyRampMessage) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { + // Deserialize `Header`: + err = decoder.Decode(&obj.Header) + if err != nil { + return err + } + // Deserialize `Sender`: + err = decoder.Decode(&obj.Sender) + if err != nil { + return err + } + // Deserialize `Data`: + err = decoder.Decode(&obj.Data) + if err != nil { + return err + } + // Deserialize `Receiver`: + err = decoder.Decode(&obj.Receiver) + if err != nil { + return err + } + // Deserialize `ExtraArgs`: + err = decoder.Decode(&obj.ExtraArgs) + if err != nil { + return err + } + // Deserialize `FeeToken`: + err = decoder.Decode(&obj.FeeToken) + if err != nil { + return err + } + // Deserialize `TokenAmounts`: + err = decoder.Decode(&obj.TokenAmounts) + if err != nil { + return err + } + return nil +} + +type Solana2AnyTokenTransfer struct { + SourcePoolAddress ag_solanago.PublicKey + DestTokenAddress []byte + ExtraData []byte + Amount uint64 + DestExecData []byte +} + +func (obj Solana2AnyTokenTransfer) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { + // Serialize `SourcePoolAddress` param: + err = encoder.Encode(obj.SourcePoolAddress) + if err != nil { + return err + } + // Serialize `DestTokenAddress` param: + err = encoder.Encode(obj.DestTokenAddress) + if err != nil { + return err + } + // Serialize `ExtraData` param: + err = encoder.Encode(obj.ExtraData) + if err != nil { + return err + } + // Serialize `Amount` param: + err = encoder.Encode(obj.Amount) + if err != nil { + return err + } + // Serialize `DestExecData` param: + err = encoder.Encode(obj.DestExecData) + if err != nil { + return err + } + return nil +} + +func (obj *Solana2AnyTokenTransfer) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { + // Deserialize `SourcePoolAddress`: + err = decoder.Decode(&obj.SourcePoolAddress) + if err != nil { + return err + } + // Deserialize `DestTokenAddress`: + err = decoder.Decode(&obj.DestTokenAddress) + if err != nil { + return err + } + // Deserialize `ExtraData`: + err = decoder.Decode(&obj.ExtraData) + if err != nil { + return err + } + // Deserialize `Amount`: + err = decoder.Decode(&obj.Amount) + if err != nil { + return err + } + // Deserialize `DestExecData`: + err = decoder.Decode(&obj.DestExecData) + if err != nil { + return err + } + return nil +} + +type Any2SolanaTokenTransfer struct { + SourcePoolAddress []byte + DestTokenAddress ag_solanago.PublicKey + DestGasAmount uint32 + ExtraData []byte + Amount uint64 +} + +func (obj Any2SolanaTokenTransfer) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { + // Serialize `SourcePoolAddress` param: + err = encoder.Encode(obj.SourcePoolAddress) + if err != nil { + return err + } + // Serialize `DestTokenAddress` param: + err = encoder.Encode(obj.DestTokenAddress) + if err != nil { + return err + } + // Serialize `DestGasAmount` param: + err = encoder.Encode(obj.DestGasAmount) + if err != nil { + return err + } + // Serialize `ExtraData` param: + err = encoder.Encode(obj.ExtraData) + if err != nil { + return err + } + // Serialize `Amount` param: + err = encoder.Encode(obj.Amount) + if err != nil { + return err + } + return nil +} + +func (obj *Any2SolanaTokenTransfer) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { + // Deserialize `SourcePoolAddress`: + err = decoder.Decode(&obj.SourcePoolAddress) + if err != nil { + return err + } + // Deserialize `DestTokenAddress`: + err = decoder.Decode(&obj.DestTokenAddress) + if err != nil { + return err + } + // Deserialize `DestGasAmount`: + err = decoder.Decode(&obj.DestGasAmount) + if err != nil { + return err + } + // Deserialize `ExtraData`: + err = decoder.Decode(&obj.ExtraData) + if err != nil { + return err + } + // Deserialize `Amount`: + err = decoder.Decode(&obj.Amount) + if err != nil { + return err + } + return nil +} + +type LockOrBurnInV1 struct { + Receiver []byte + RemoteChainSelector uint64 + OriginalSender ag_solanago.PublicKey + Amount uint64 + LocalToken ag_solanago.PublicKey +} + +func (obj LockOrBurnInV1) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { + // Serialize `Receiver` param: + err = encoder.Encode(obj.Receiver) + if err != nil { + return err + } + // Serialize `RemoteChainSelector` param: + err = encoder.Encode(obj.RemoteChainSelector) + if err != nil { + return err + } + // Serialize `OriginalSender` param: + err = encoder.Encode(obj.OriginalSender) + if err != nil { + return err + } + // Serialize `Amount` param: + err = encoder.Encode(obj.Amount) + if err != nil { + return err + } + // Serialize `LocalToken` param: + err = encoder.Encode(obj.LocalToken) + if err != nil { + return err + } + return nil +} + +func (obj *LockOrBurnInV1) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { + // Deserialize `Receiver`: + err = decoder.Decode(&obj.Receiver) + if err != nil { + return err + } + // Deserialize `RemoteChainSelector`: + err = decoder.Decode(&obj.RemoteChainSelector) + if err != nil { + return err + } + // Deserialize `OriginalSender`: + err = decoder.Decode(&obj.OriginalSender) + if err != nil { + return err + } + // Deserialize `Amount`: + err = decoder.Decode(&obj.Amount) + if err != nil { + return err + } + // Deserialize `LocalToken`: + err = decoder.Decode(&obj.LocalToken) + if err != nil { + return err + } + return nil +} + +type ReleaseOrMintInV1 struct { + OriginalSender []byte + RemoteChainSelector uint64 + Receiver ag_solanago.PublicKey + Amount uint64 + LocalToken ag_solanago.PublicKey + + // @dev WARNING: sourcePoolAddress should be checked prior to any processing of funds. Make sure it matches the + // expected pool address for the given remoteChainSelector. + SourcePoolAddress []byte + SourcePoolData []byte + + // @dev WARNING: offchainTokenData is untrusted data. + OffchainTokenData []byte +} + +func (obj ReleaseOrMintInV1) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { + // Serialize `OriginalSender` param: + err = encoder.Encode(obj.OriginalSender) + if err != nil { + return err + } + // Serialize `RemoteChainSelector` param: + err = encoder.Encode(obj.RemoteChainSelector) + if err != nil { + return err + } + // Serialize `Receiver` param: + err = encoder.Encode(obj.Receiver) + if err != nil { + return err + } + // Serialize `Amount` param: + err = encoder.Encode(obj.Amount) + if err != nil { + return err + } + // Serialize `LocalToken` param: + err = encoder.Encode(obj.LocalToken) + if err != nil { + return err + } + // Serialize `SourcePoolAddress` param: + err = encoder.Encode(obj.SourcePoolAddress) + if err != nil { + return err + } + // Serialize `SourcePoolData` param: + err = encoder.Encode(obj.SourcePoolData) + if err != nil { + return err + } + // Serialize `OffchainTokenData` param: + err = encoder.Encode(obj.OffchainTokenData) + if err != nil { + return err + } + return nil +} + +func (obj *ReleaseOrMintInV1) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { + // Deserialize `OriginalSender`: + err = decoder.Decode(&obj.OriginalSender) + if err != nil { + return err + } + // Deserialize `RemoteChainSelector`: + err = decoder.Decode(&obj.RemoteChainSelector) + if err != nil { + return err + } + // Deserialize `Receiver`: + err = decoder.Decode(&obj.Receiver) + if err != nil { + return err + } + // Deserialize `Amount`: + err = decoder.Decode(&obj.Amount) + if err != nil { + return err + } + // Deserialize `LocalToken`: + err = decoder.Decode(&obj.LocalToken) + if err != nil { + return err + } + // Deserialize `SourcePoolAddress`: + err = decoder.Decode(&obj.SourcePoolAddress) + if err != nil { + return err + } + // Deserialize `SourcePoolData`: + err = decoder.Decode(&obj.SourcePoolData) + if err != nil { + return err + } + // Deserialize `OffchainTokenData`: + err = decoder.Decode(&obj.OffchainTokenData) + if err != nil { + return err + } + return nil +} + +type LockOrBurnOutV1 struct { + DestTokenAddress []byte + DestPoolData []byte +} + +func (obj LockOrBurnOutV1) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { + // Serialize `DestTokenAddress` param: + err = encoder.Encode(obj.DestTokenAddress) + if err != nil { + return err + } + // Serialize `DestPoolData` param: + err = encoder.Encode(obj.DestPoolData) + if err != nil { + return err + } + return nil +} + +func (obj *LockOrBurnOutV1) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { + // Deserialize `DestTokenAddress`: + err = decoder.Decode(&obj.DestTokenAddress) + if err != nil { + return err + } + // Deserialize `DestPoolData`: + err = decoder.Decode(&obj.DestPoolData) + if err != nil { + return err + } + return nil +} + +type ReleaseOrMintOutV1 struct { + DestinationAmount uint64 +} + +func (obj ReleaseOrMintOutV1) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { + // Serialize `DestinationAmount` param: + err = encoder.Encode(obj.DestinationAmount) + if err != nil { + return err + } + return nil +} + +func (obj *ReleaseOrMintOutV1) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { + // Deserialize `DestinationAmount`: + err = decoder.Decode(&obj.DestinationAmount) + if err != nil { + return err + } + return nil +} + +type Ocr3Config struct { + PluginType uint8 + ConfigInfo Ocr3ConfigInfo + Signers [16][20]uint8 + Transmitters [16][32]uint8 +} + +func (obj Ocr3Config) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { + // Serialize `PluginType` param: + err = encoder.Encode(obj.PluginType) + if err != nil { + return err + } + // Serialize `ConfigInfo` param: + err = encoder.Encode(obj.ConfigInfo) + if err != nil { + return err + } + // Serialize `Signers` param: + err = encoder.Encode(obj.Signers) + if err != nil { + return err + } + // Serialize `Transmitters` param: + err = encoder.Encode(obj.Transmitters) + if err != nil { + return err + } + return nil +} + +func (obj *Ocr3Config) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { + // Deserialize `PluginType`: + err = decoder.Decode(&obj.PluginType) + if err != nil { + return err + } + // Deserialize `ConfigInfo`: + err = decoder.Decode(&obj.ConfigInfo) + if err != nil { + return err + } + // Deserialize `Signers`: + err = decoder.Decode(&obj.Signers) + if err != nil { + return err + } + // Deserialize `Transmitters`: + err = decoder.Decode(&obj.Transmitters) + if err != nil { + return err + } + return nil +} + +type Ocr3ConfigInfo struct { + ConfigDigest [32]uint8 + F uint8 + N uint8 + IsSignatureVerificationEnabled uint8 +} + +func (obj Ocr3ConfigInfo) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { + // Serialize `ConfigDigest` param: + err = encoder.Encode(obj.ConfigDigest) + if err != nil { + return err + } + // Serialize `F` param: + err = encoder.Encode(obj.F) + if err != nil { + return err + } + // Serialize `N` param: + err = encoder.Encode(obj.N) + if err != nil { + return err + } + // Serialize `IsSignatureVerificationEnabled` param: + err = encoder.Encode(obj.IsSignatureVerificationEnabled) + if err != nil { + return err + } + return nil +} + +func (obj *Ocr3ConfigInfo) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { + // Deserialize `ConfigDigest`: + err = decoder.Decode(&obj.ConfigDigest) + if err != nil { + return err + } + // Deserialize `F`: + err = decoder.Decode(&obj.F) + if err != nil { + return err + } + // Deserialize `N`: + err = decoder.Decode(&obj.N) + if err != nil { + return err + } + // Deserialize `IsSignatureVerificationEnabled`: + err = decoder.Decode(&obj.IsSignatureVerificationEnabled) + if err != nil { + return err + } + return nil +} + +type SourceChainConfig struct { + IsEnabled bool + MinSeqNr uint64 + OnRamp []byte +} + +func (obj SourceChainConfig) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { + // Serialize `IsEnabled` param: + err = encoder.Encode(obj.IsEnabled) + if err != nil { + return err + } + // Serialize `MinSeqNr` param: + err = encoder.Encode(obj.MinSeqNr) + if err != nil { + return err + } + // Serialize `OnRamp` param: + err = encoder.Encode(obj.OnRamp) + if err != nil { + return err + } + return nil +} + +func (obj *SourceChainConfig) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { + // Deserialize `IsEnabled`: + err = decoder.Decode(&obj.IsEnabled) + if err != nil { + return err + } + // Deserialize `MinSeqNr`: + err = decoder.Decode(&obj.MinSeqNr) + if err != nil { + return err + } + // Deserialize `OnRamp`: + err = decoder.Decode(&obj.OnRamp) + if err != nil { + return err + } + return nil +} + +type DestChainConfig struct { + SequenceNumber uint64 + UsdPerUnitGas TimestampedPackedU224 + BillingConfig ChainBillingConfig +} + +func (obj DestChainConfig) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { + // Serialize `SequenceNumber` param: + err = encoder.Encode(obj.SequenceNumber) + if err != nil { + return err + } + // Serialize `UsdPerUnitGas` param: + err = encoder.Encode(obj.UsdPerUnitGas) + if err != nil { + return err + } + // Serialize `BillingConfig` param: + err = encoder.Encode(obj.BillingConfig) + if err != nil { + return err + } + return nil +} + +func (obj *DestChainConfig) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { + // Deserialize `SequenceNumber`: + err = decoder.Decode(&obj.SequenceNumber) + if err != nil { + return err + } + // Deserialize `UsdPerUnitGas`: + err = decoder.Decode(&obj.UsdPerUnitGas) + if err != nil { + return err + } + // Deserialize `BillingConfig`: + err = decoder.Decode(&obj.BillingConfig) + if err != nil { + return err + } + return nil +} + +type ChainBillingConfig struct { + IsEnabled bool + MaxNumberOfTokensPerMsg uint16 + MaxDataBytes uint32 + MaxPerMsgGasLimit uint32 + DestGasOverhead uint32 + DestGasPerPayloadByte uint16 + DestDataAvailabilityOverheadGas uint32 + DestGasPerDataAvailabilityByte uint16 + DestDataAvailabilityMultiplierBps uint16 + DefaultTokenFeeUsdcents uint16 + DefaultTokenDestGasOverhead uint32 + DefaultTxGasLimit uint32 + GasMultiplierWeiPerEth uint64 + NetworkFeeUsdcents uint32 + GasPriceStalenessThreshold uint32 + EnforceOutOfOrder bool + ChainFamilySelector [4]uint8 +} + +func (obj ChainBillingConfig) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { + // Serialize `IsEnabled` param: + err = encoder.Encode(obj.IsEnabled) + if err != nil { + return err + } + // Serialize `MaxNumberOfTokensPerMsg` param: + err = encoder.Encode(obj.MaxNumberOfTokensPerMsg) + if err != nil { + return err + } + // Serialize `MaxDataBytes` param: + err = encoder.Encode(obj.MaxDataBytes) + if err != nil { + return err + } + // Serialize `MaxPerMsgGasLimit` param: + err = encoder.Encode(obj.MaxPerMsgGasLimit) + if err != nil { + return err + } + // Serialize `DestGasOverhead` param: + err = encoder.Encode(obj.DestGasOverhead) + if err != nil { + return err + } + // Serialize `DestGasPerPayloadByte` param: + err = encoder.Encode(obj.DestGasPerPayloadByte) + if err != nil { + return err + } + // Serialize `DestDataAvailabilityOverheadGas` param: + err = encoder.Encode(obj.DestDataAvailabilityOverheadGas) + if err != nil { + return err + } + // Serialize `DestGasPerDataAvailabilityByte` param: + err = encoder.Encode(obj.DestGasPerDataAvailabilityByte) + if err != nil { + return err + } + // Serialize `DestDataAvailabilityMultiplierBps` param: + err = encoder.Encode(obj.DestDataAvailabilityMultiplierBps) + if err != nil { + return err + } + // Serialize `DefaultTokenFeeUsdcents` param: + err = encoder.Encode(obj.DefaultTokenFeeUsdcents) + if err != nil { + return err + } + // Serialize `DefaultTokenDestGasOverhead` param: + err = encoder.Encode(obj.DefaultTokenDestGasOverhead) + if err != nil { + return err + } + // Serialize `DefaultTxGasLimit` param: + err = encoder.Encode(obj.DefaultTxGasLimit) + if err != nil { + return err + } + // Serialize `GasMultiplierWeiPerEth` param: + err = encoder.Encode(obj.GasMultiplierWeiPerEth) + if err != nil { + return err + } + // Serialize `NetworkFeeUsdcents` param: + err = encoder.Encode(obj.NetworkFeeUsdcents) + if err != nil { + return err + } + // Serialize `GasPriceStalenessThreshold` param: + err = encoder.Encode(obj.GasPriceStalenessThreshold) + if err != nil { + return err + } + // Serialize `EnforceOutOfOrder` param: + err = encoder.Encode(obj.EnforceOutOfOrder) + if err != nil { + return err + } + // Serialize `ChainFamilySelector` param: + err = encoder.Encode(obj.ChainFamilySelector) + if err != nil { + return err + } + return nil +} + +func (obj *ChainBillingConfig) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { + // Deserialize `IsEnabled`: + err = decoder.Decode(&obj.IsEnabled) + if err != nil { + return err + } + // Deserialize `MaxNumberOfTokensPerMsg`: + err = decoder.Decode(&obj.MaxNumberOfTokensPerMsg) + if err != nil { + return err + } + // Deserialize `MaxDataBytes`: + err = decoder.Decode(&obj.MaxDataBytes) + if err != nil { + return err + } + // Deserialize `MaxPerMsgGasLimit`: + err = decoder.Decode(&obj.MaxPerMsgGasLimit) + if err != nil { + return err + } + // Deserialize `DestGasOverhead`: + err = decoder.Decode(&obj.DestGasOverhead) + if err != nil { + return err + } + // Deserialize `DestGasPerPayloadByte`: + err = decoder.Decode(&obj.DestGasPerPayloadByte) + if err != nil { + return err + } + // Deserialize `DestDataAvailabilityOverheadGas`: + err = decoder.Decode(&obj.DestDataAvailabilityOverheadGas) + if err != nil { + return err + } + // Deserialize `DestGasPerDataAvailabilityByte`: + err = decoder.Decode(&obj.DestGasPerDataAvailabilityByte) + if err != nil { + return err + } + // Deserialize `DestDataAvailabilityMultiplierBps`: + err = decoder.Decode(&obj.DestDataAvailabilityMultiplierBps) + if err != nil { + return err + } + // Deserialize `DefaultTokenFeeUsdcents`: + err = decoder.Decode(&obj.DefaultTokenFeeUsdcents) + if err != nil { + return err + } + // Deserialize `DefaultTokenDestGasOverhead`: + err = decoder.Decode(&obj.DefaultTokenDestGasOverhead) + if err != nil { + return err + } + // Deserialize `DefaultTxGasLimit`: + err = decoder.Decode(&obj.DefaultTxGasLimit) + if err != nil { + return err + } + // Deserialize `GasMultiplierWeiPerEth`: + err = decoder.Decode(&obj.GasMultiplierWeiPerEth) + if err != nil { + return err + } + // Deserialize `NetworkFeeUsdcents`: + err = decoder.Decode(&obj.NetworkFeeUsdcents) + if err != nil { + return err + } + // Deserialize `GasPriceStalenessThreshold`: + err = decoder.Decode(&obj.GasPriceStalenessThreshold) + if err != nil { + return err + } + // Deserialize `EnforceOutOfOrder`: + err = decoder.Decode(&obj.EnforceOutOfOrder) + if err != nil { + return err + } + // Deserialize `ChainFamilySelector`: + err = decoder.Decode(&obj.ChainFamilySelector) + if err != nil { + return err + } + return nil +} + +type TokenBilling struct { + MinFeeUsdcents uint32 + MaxFeeUsdcents uint32 + DeciBps uint16 + DestGasOverhead uint32 + DestBytesOverhead uint32 + IsEnabled bool +} + +func (obj TokenBilling) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { + // Serialize `MinFeeUsdcents` param: + err = encoder.Encode(obj.MinFeeUsdcents) + if err != nil { + return err + } + // Serialize `MaxFeeUsdcents` param: + err = encoder.Encode(obj.MaxFeeUsdcents) + if err != nil { + return err + } + // Serialize `DeciBps` param: + err = encoder.Encode(obj.DeciBps) + if err != nil { + return err + } + // Serialize `DestGasOverhead` param: + err = encoder.Encode(obj.DestGasOverhead) + if err != nil { + return err + } + // Serialize `DestBytesOverhead` param: + err = encoder.Encode(obj.DestBytesOverhead) + if err != nil { + return err + } + // Serialize `IsEnabled` param: + err = encoder.Encode(obj.IsEnabled) + if err != nil { + return err + } + return nil +} + +func (obj *TokenBilling) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { + // Deserialize `MinFeeUsdcents`: + err = decoder.Decode(&obj.MinFeeUsdcents) + if err != nil { + return err + } + // Deserialize `MaxFeeUsdcents`: + err = decoder.Decode(&obj.MaxFeeUsdcents) + if err != nil { + return err + } + // Deserialize `DeciBps`: + err = decoder.Decode(&obj.DeciBps) + if err != nil { + return err + } + // Deserialize `DestGasOverhead`: + err = decoder.Decode(&obj.DestGasOverhead) + if err != nil { + return err + } + // Deserialize `DestBytesOverhead`: + err = decoder.Decode(&obj.DestBytesOverhead) + if err != nil { + return err + } + // Deserialize `IsEnabled`: + err = decoder.Decode(&obj.IsEnabled) + if err != nil { + return err + } + return nil +} + +type TimestampedPackedU224 struct { + Value [28]uint8 + Timestamp uint32 +} + +func (obj TimestampedPackedU224) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { + // Serialize `Value` param: + err = encoder.Encode(obj.Value) + if err != nil { + return err + } + // Serialize `Timestamp` param: + err = encoder.Encode(obj.Timestamp) + if err != nil { + return err + } + return nil +} + +func (obj *TimestampedPackedU224) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { + // Deserialize `Value`: + err = decoder.Decode(&obj.Value) + if err != nil { + return err + } + // Deserialize `Timestamp`: + err = decoder.Decode(&obj.Timestamp) + if err != nil { + return err + } + return nil +} + +type OcrPluginType ag_binary.BorshEnum + +const ( + Commit_OcrPluginType OcrPluginType = iota + Execution_OcrPluginType +) + +func (value OcrPluginType) String() string { + switch value { + case Commit_OcrPluginType: + return "Commit" + case Execution_OcrPluginType: + return "Execution" + default: + return "" + } +} + +type MerkleError ag_binary.BorshEnum + +const ( + InvalidProof_MerkleError MerkleError = iota +) + +func (value MerkleError) String() string { + switch value { + case InvalidProof_MerkleError: + return "InvalidProof" + default: + return "" + } +} + +type MessageExecutionState ag_binary.BorshEnum + +const ( + Untouched_MessageExecutionState MessageExecutionState = iota + InProgress_MessageExecutionState + Success_MessageExecutionState + Failure_MessageExecutionState +) + +func (value MessageExecutionState) String() string { + switch value { + case Untouched_MessageExecutionState: + return "Untouched" + case InProgress_MessageExecutionState: + return "InProgress" + case Success_MessageExecutionState: + return "Success" + case Failure_MessageExecutionState: + return "Failure" + default: + return "" + } +} + +type CcipRouterError ag_binary.BorshEnum + +const ( + InvalidSequenceInterval_CcipRouterError CcipRouterError = iota + RootNotCommitted_CcipRouterError + ExistingMerkleRoot_CcipRouterError + Unauthorized_CcipRouterError + InvalidInputs_CcipRouterError + UnsupportedSourceChainSelector_CcipRouterError + UnsupportedDestinationChainSelector_CcipRouterError + InvalidProof_CcipRouterError + InvalidMessage_CcipRouterError + ReachedMaxSequenceNumber_CcipRouterError + ManualExecutionNotAllowed_CcipRouterError + InvalidInputsTokenIndices_CcipRouterError + InvalidInputsPoolAccounts_CcipRouterError + InvalidInputsTokenAccounts_CcipRouterError + InvalidInputsConfigAccounts_CcipRouterError + InvalidInputsTokenAmount_CcipRouterError + OfframpReleaseMintBalanceMismatch_CcipRouterError + OfframpInvalidDataLength_CcipRouterError +) + +func (value CcipRouterError) String() string { + switch value { + case InvalidSequenceInterval_CcipRouterError: + return "InvalidSequenceInterval" + case RootNotCommitted_CcipRouterError: + return "RootNotCommitted" + case ExistingMerkleRoot_CcipRouterError: + return "ExistingMerkleRoot" + case Unauthorized_CcipRouterError: + return "Unauthorized" + case InvalidInputs_CcipRouterError: + return "InvalidInputs" + case UnsupportedSourceChainSelector_CcipRouterError: + return "UnsupportedSourceChainSelector" + case UnsupportedDestinationChainSelector_CcipRouterError: + return "UnsupportedDestinationChainSelector" + case InvalidProof_CcipRouterError: + return "InvalidProof" + case InvalidMessage_CcipRouterError: + return "InvalidMessage" + case ReachedMaxSequenceNumber_CcipRouterError: + return "ReachedMaxSequenceNumber" + case ManualExecutionNotAllowed_CcipRouterError: + return "ManualExecutionNotAllowed" + case InvalidInputsTokenIndices_CcipRouterError: + return "InvalidInputsTokenIndices" + case InvalidInputsPoolAccounts_CcipRouterError: + return "InvalidInputsPoolAccounts" + case InvalidInputsTokenAccounts_CcipRouterError: + return "InvalidInputsTokenAccounts" + case InvalidInputsConfigAccounts_CcipRouterError: + return "InvalidInputsConfigAccounts" + case InvalidInputsTokenAmount_CcipRouterError: + return "InvalidInputsTokenAmount" + case OfframpReleaseMintBalanceMismatch_CcipRouterError: + return "OfframpReleaseMintBalanceMismatch" + case OfframpInvalidDataLength_CcipRouterError: + return "OfframpInvalidDataLength" + default: + return "" + } +} diff --git a/core/capabilities/ccip/ccipsolana/commitcodec.go b/core/capabilities/ccip/ccipsolana/commitcodec.go new file mode 100644 index 00000000000..711bb66068a --- /dev/null +++ b/core/capabilities/ccip/ccipsolana/commitcodec.go @@ -0,0 +1,144 @@ +package ccipsolana + +import ( + "bytes" + "context" + "errors" + "fmt" + + "github.com/gagliardetto/solana-go" + "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/ccipsolana/ccip_router" + + cciptypes "github.com/smartcontractkit/chainlink-ccip/pkg/types/ccipocr3" + + agbinary "github.com/gagliardetto/binary" +) + +// CommitPluginCodecV1 is a codec for encoding and decoding commit plugin reports. +// Compatible with: +// - "OffRamp 1.6.0-dev" +type CommitPluginCodecV1 struct{} + +func NewCommitPluginCodecV1() *CommitPluginCodecV1 { + return &CommitPluginCodecV1{} +} + +func (c *CommitPluginCodecV1) Encode(ctx context.Context, report cciptypes.CommitPluginReport) ([]byte, error) { + var buf bytes.Buffer + encoder := agbinary.NewBorshEncoder(&buf) + + mr := ccip_router.MerkleRoot{ + SourceChainSelector: uint64(report.MerkleRoots[0].ChainSel), + OnRampAddress: report.MerkleRoots[0].OnRampAddress, + MinSeqNr: uint64(report.MerkleRoots[0].SeqNumsRange.Start()), + MaxSeqNr: uint64(report.MerkleRoots[0].SeqNumsRange.End()), + MerkleRoot: report.MerkleRoots[0].MerkleRoot, + } + + tpu := make([]ccip_router.TokenPriceUpdate, 0, len(report.PriceUpdates.TokenPriceUpdates)) + for _, update := range report.PriceUpdates.TokenPriceUpdates { + b, err := update.Price.MarshalJSON() + if err != nil { + return nil, fmt.Errorf("error marshaling token price: %v", err) + } + + if len(b) > 28 { + return nil, errors.New("token price is too large") + } + + tpu = append(tpu, ccip_router.TokenPriceUpdate{ + SourceToken: solana.MPK(string(update.TokenID)), + UsdPerToken: [28]uint8(b), + }) + } + + gpu := make([]ccip_router.GasPriceUpdate, 0, len(report.PriceUpdates.GasPriceUpdates)) + for _, update := range report.PriceUpdates.GasPriceUpdates { + b, err := update.GasPrice.MarshalJSON() + if err != nil { + return nil, fmt.Errorf("error marshaling gas price update: %w", err) + } + + if len(b) > 28 { + return nil, errors.New("error marshaling gas price update: gas price is too large") + } + + gpu = append(gpu, ccip_router.GasPriceUpdate{ + DestChainSelector: uint64(update.ChainSel), + UsdPerUnitGas: [28]uint8(b), + }) + } + + commit := ccip_router.CommitInput{ + MerkleRoot: mr, + PriceUpdates: ccip_router.PriceUpdates{ + TokenPriceUpdates: tpu, + GasPriceUpdates: gpu, + }, + } + + err := commit.MarshalWithEncoder(encoder) + if err != nil { + return nil, err + } + + return buf.Bytes(), nil +} + +func (c *CommitPluginCodecV1) Decode(ctx context.Context, bytes []byte) (cciptypes.CommitPluginReport, error) { + decoder := agbinary.NewBorshDecoder(bytes) + commitReport := ccip_router.CommitInput{} + err := commitReport.UnmarshalWithDecoder(decoder) + if err != nil { + return cciptypes.CommitPluginReport{}, err + } + + merkleRoots := []cciptypes.MerkleRootChain{ + { + ChainSel: cciptypes.ChainSelector(commitReport.MerkleRoot.SourceChainSelector), + OnRampAddress: commitReport.MerkleRoot.OnRampAddress, + SeqNumsRange: cciptypes.NewSeqNumRange( + cciptypes.SeqNum(commitReport.MerkleRoot.MinSeqNr), + cciptypes.SeqNum(commitReport.MerkleRoot.MaxSeqNr), + ), + MerkleRoot: commitReport.MerkleRoot.MerkleRoot, + }, + } + + tokenPriceUpdates := make([]cciptypes.TokenPrice, 0, len(commitReport.PriceUpdates.TokenPriceUpdates)) + for _, update := range commitReport.PriceUpdates.TokenPriceUpdates { + price := cciptypes.BigInt{} + err = price.UnmarshalJSON(update.UsdPerToken[:]) + if err != nil { + return cciptypes.CommitPluginReport{}, err + } + tokenPriceUpdates = append(tokenPriceUpdates, cciptypes.TokenPrice{ + TokenID: cciptypes.UnknownEncodedAddress(update.SourceToken.String()), + Price: price, + }) + } + + gasPriceUpdates := make([]cciptypes.GasPriceChain, 0, len(commitReport.PriceUpdates.GasPriceUpdates)) + for _, update := range commitReport.PriceUpdates.GasPriceUpdates { + price := cciptypes.BigInt{} + err = price.UnmarshalJSON(update.UsdPerUnitGas[:]) + if err != nil { + return cciptypes.CommitPluginReport{}, err + } + gasPriceUpdates = append(gasPriceUpdates, cciptypes.GasPriceChain{ + GasPrice: price, + ChainSel: cciptypes.ChainSelector(update.DestChainSelector), + }) + } + + return cciptypes.CommitPluginReport{ + MerkleRoots: merkleRoots, + PriceUpdates: cciptypes.PriceUpdates{ + TokenPriceUpdates: tokenPriceUpdates, + GasPriceUpdates: gasPriceUpdates, + }, + }, nil +} + +// Ensure CommitPluginCodec implements the CommitPluginCodec interface +var _ cciptypes.CommitPluginCodec = (*CommitPluginCodecV1)(nil) From c79a4064b5b5019a83f263b29fcd0d730e45cd37 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bla=C5=BE=20Hrastnik?= Date: Tue, 24 Dec 2024 15:42:39 +0900 Subject: [PATCH 3/4] ccipsolana: Import bindings --- .../AcceptAdminRoleTokenAdminRegistry.go | 146 -- .../AcceptAdminRoleTokenAdminRegistry_test.go | 32 - .../ccipsolana/ccip_router/AcceptOwnership.go | 117 -- .../ccip_router/AcceptOwnership_test.go | 32 - .../ccip_router/AddChainSelector.go | 207 -- .../ccip_router/AddChainSelector_test.go | 32 - .../ccip/ccipsolana/ccip_router/CcipSend.go | 250 --- .../ccipsolana/ccip_router/CcipSend_test.go | 32 - .../ccip/ccipsolana/ccip_router/Commit.go | 279 --- .../ccipsolana/ccip_router/Commit_test.go | 32 - .../ccip_router/DisableChainSelector.go | 184 -- .../ccip_router/DisableChainSelector_test.go | 32 - .../ccip_router/EnableChainSelector.go | 184 -- .../ccip_router/EnableChainSelector_test.go | 32 - .../ccip/ccipsolana/ccip_router/Execute.go | 293 --- .../ccipsolana/ccip_router/Execute_test.go | 32 - .../ccip/ccipsolana/ccip_router/Initialize.go | 310 --- .../ccipsolana/ccip_router/Initialize_test.go | 32 - .../ccipsolana/ccip_router/ManuallyExecute.go | 261 --- .../ccip_router/ManuallyExecute_test.go | 32 - ...gisterTokenAdminRegistryViaGetCcipAdmin.go | 207 -- ...rTokenAdminRegistryViaGetCcipAdmin_test.go | 32 - .../RegisterTokenAdminRegistryViaOwner.go | 155 -- ...RegisterTokenAdminRegistryViaOwner_test.go | 32 - .../ccipsolana/ccip_router/SetOcrConfig.go | 215 -- .../ccip_router/SetOcrConfig_test.go | 32 - .../ccip/ccipsolana/ccip_router/SetPool.go | 169 -- .../ccipsolana/ccip_router/SetPool_test.go | 32 - .../ccipsolana/ccip_router/SetTokenBilling.go | 230 --- .../ccip_router/SetTokenBilling_test.go | 32 - .../TransferAdminRoleTokenAdminRegistry.go | 169 -- ...ransferAdminRoleTokenAdminRegistry_test.go | 32 - .../ccip_router/TransferOwnership.go | 146 -- .../ccip_router/TransferOwnership_test.go | 32 - .../UpdateDefaultAllowOutOfOrderExecution.go | 165 -- ...ateDefaultAllowOutOfOrderExecution_test.go | 32 - .../ccip_router/UpdateDefaultGasLimit.go | 165 -- .../ccip_router/UpdateDefaultGasLimit_test.go | 32 - .../UpdateEnableManualExecutionAfter.go | 165 -- .../UpdateEnableManualExecutionAfter_test.go | 32 - .../ccip_router/UpdateSolanaChainSelector.go | 165 -- .../UpdateSolanaChainSelector_test.go | 32 - .../ccip/ccipsolana/ccip_router/accounts.go | 661 ------ .../ccipsolana/ccip_router/instructions.go | 304 --- .../ccipsolana/ccip_router/testing_utils.go | 20 - .../ccip/ccipsolana/ccip_router/types.go | 1817 ----------------- .../ccip/ccipsolana/commitcodec.go | 7 +- go.mod | 24 +- go.sum | 124 +- 49 files changed, 33 insertions(+), 7778 deletions(-) delete mode 100644 core/capabilities/ccip/ccipsolana/ccip_router/AcceptAdminRoleTokenAdminRegistry.go delete mode 100644 core/capabilities/ccip/ccipsolana/ccip_router/AcceptAdminRoleTokenAdminRegistry_test.go delete mode 100644 core/capabilities/ccip/ccipsolana/ccip_router/AcceptOwnership.go delete mode 100644 core/capabilities/ccip/ccipsolana/ccip_router/AcceptOwnership_test.go delete mode 100644 core/capabilities/ccip/ccipsolana/ccip_router/AddChainSelector.go delete mode 100644 core/capabilities/ccip/ccipsolana/ccip_router/AddChainSelector_test.go delete mode 100644 core/capabilities/ccip/ccipsolana/ccip_router/CcipSend.go delete mode 100644 core/capabilities/ccip/ccipsolana/ccip_router/CcipSend_test.go delete mode 100644 core/capabilities/ccip/ccipsolana/ccip_router/Commit.go delete mode 100644 core/capabilities/ccip/ccipsolana/ccip_router/Commit_test.go delete mode 100644 core/capabilities/ccip/ccipsolana/ccip_router/DisableChainSelector.go delete mode 100644 core/capabilities/ccip/ccipsolana/ccip_router/DisableChainSelector_test.go delete mode 100644 core/capabilities/ccip/ccipsolana/ccip_router/EnableChainSelector.go delete mode 100644 core/capabilities/ccip/ccipsolana/ccip_router/EnableChainSelector_test.go delete mode 100644 core/capabilities/ccip/ccipsolana/ccip_router/Execute.go delete mode 100644 core/capabilities/ccip/ccipsolana/ccip_router/Execute_test.go delete mode 100644 core/capabilities/ccip/ccipsolana/ccip_router/Initialize.go delete mode 100644 core/capabilities/ccip/ccipsolana/ccip_router/Initialize_test.go delete mode 100644 core/capabilities/ccip/ccipsolana/ccip_router/ManuallyExecute.go delete mode 100644 core/capabilities/ccip/ccipsolana/ccip_router/ManuallyExecute_test.go delete mode 100644 core/capabilities/ccip/ccipsolana/ccip_router/RegisterTokenAdminRegistryViaGetCcipAdmin.go delete mode 100644 core/capabilities/ccip/ccipsolana/ccip_router/RegisterTokenAdminRegistryViaGetCcipAdmin_test.go delete mode 100644 core/capabilities/ccip/ccipsolana/ccip_router/RegisterTokenAdminRegistryViaOwner.go delete mode 100644 core/capabilities/ccip/ccipsolana/ccip_router/RegisterTokenAdminRegistryViaOwner_test.go delete mode 100644 core/capabilities/ccip/ccipsolana/ccip_router/SetOcrConfig.go delete mode 100644 core/capabilities/ccip/ccipsolana/ccip_router/SetOcrConfig_test.go delete mode 100644 core/capabilities/ccip/ccipsolana/ccip_router/SetPool.go delete mode 100644 core/capabilities/ccip/ccipsolana/ccip_router/SetPool_test.go delete mode 100644 core/capabilities/ccip/ccipsolana/ccip_router/SetTokenBilling.go delete mode 100644 core/capabilities/ccip/ccipsolana/ccip_router/SetTokenBilling_test.go delete mode 100644 core/capabilities/ccip/ccipsolana/ccip_router/TransferAdminRoleTokenAdminRegistry.go delete mode 100644 core/capabilities/ccip/ccipsolana/ccip_router/TransferAdminRoleTokenAdminRegistry_test.go delete mode 100644 core/capabilities/ccip/ccipsolana/ccip_router/TransferOwnership.go delete mode 100644 core/capabilities/ccip/ccipsolana/ccip_router/TransferOwnership_test.go delete mode 100644 core/capabilities/ccip/ccipsolana/ccip_router/UpdateDefaultAllowOutOfOrderExecution.go delete mode 100644 core/capabilities/ccip/ccipsolana/ccip_router/UpdateDefaultAllowOutOfOrderExecution_test.go delete mode 100644 core/capabilities/ccip/ccipsolana/ccip_router/UpdateDefaultGasLimit.go delete mode 100644 core/capabilities/ccip/ccipsolana/ccip_router/UpdateDefaultGasLimit_test.go delete mode 100644 core/capabilities/ccip/ccipsolana/ccip_router/UpdateEnableManualExecutionAfter.go delete mode 100644 core/capabilities/ccip/ccipsolana/ccip_router/UpdateEnableManualExecutionAfter_test.go delete mode 100644 core/capabilities/ccip/ccipsolana/ccip_router/UpdateSolanaChainSelector.go delete mode 100644 core/capabilities/ccip/ccipsolana/ccip_router/UpdateSolanaChainSelector_test.go delete mode 100644 core/capabilities/ccip/ccipsolana/ccip_router/accounts.go delete mode 100644 core/capabilities/ccip/ccipsolana/ccip_router/instructions.go delete mode 100644 core/capabilities/ccip/ccipsolana/ccip_router/testing_utils.go delete mode 100644 core/capabilities/ccip/ccipsolana/ccip_router/types.go diff --git a/core/capabilities/ccip/ccipsolana/ccip_router/AcceptAdminRoleTokenAdminRegistry.go b/core/capabilities/ccip/ccipsolana/ccip_router/AcceptAdminRoleTokenAdminRegistry.go deleted file mode 100644 index 6afa27007fe..00000000000 --- a/core/capabilities/ccip/ccipsolana/ccip_router/AcceptAdminRoleTokenAdminRegistry.go +++ /dev/null @@ -1,146 +0,0 @@ -// Code generated by https://github.com/gagliardetto/anchor-go. DO NOT EDIT. - -package ccip_router - -import ( - "errors" - ag_binary "github.com/gagliardetto/binary" - ag_solanago "github.com/gagliardetto/solana-go" - ag_format "github.com/gagliardetto/solana-go/text/format" - ag_treeout "github.com/gagliardetto/treeout" -) - -// The Pending Admin can accept the Admin Role of the Token Admin Registry -type AcceptAdminRoleTokenAdminRegistry struct { - Mint *ag_solanago.PublicKey - - // [0] = [WRITE] tokenAdminRegistry - // - // [1] = [WRITE, SIGNER] authority - ag_solanago.AccountMetaSlice `bin:"-" borsh_skip:"true"` -} - -// NewAcceptAdminRoleTokenAdminRegistryInstructionBuilder creates a new `AcceptAdminRoleTokenAdminRegistry` instruction builder. -func NewAcceptAdminRoleTokenAdminRegistryInstructionBuilder() *AcceptAdminRoleTokenAdminRegistry { - nd := &AcceptAdminRoleTokenAdminRegistry{ - AccountMetaSlice: make(ag_solanago.AccountMetaSlice, 2), - } - return nd -} - -// SetMint sets the "mint" parameter. -func (inst *AcceptAdminRoleTokenAdminRegistry) SetMint(mint ag_solanago.PublicKey) *AcceptAdminRoleTokenAdminRegistry { - inst.Mint = &mint - return inst -} - -// SetTokenAdminRegistryAccount sets the "tokenAdminRegistry" account. -func (inst *AcceptAdminRoleTokenAdminRegistry) SetTokenAdminRegistryAccount(tokenAdminRegistry ag_solanago.PublicKey) *AcceptAdminRoleTokenAdminRegistry { - inst.AccountMetaSlice[0] = ag_solanago.Meta(tokenAdminRegistry).WRITE() - return inst -} - -// GetTokenAdminRegistryAccount gets the "tokenAdminRegistry" account. -func (inst *AcceptAdminRoleTokenAdminRegistry) GetTokenAdminRegistryAccount() *ag_solanago.AccountMeta { - return inst.AccountMetaSlice[0] -} - -// SetAuthorityAccount sets the "authority" account. -func (inst *AcceptAdminRoleTokenAdminRegistry) SetAuthorityAccount(authority ag_solanago.PublicKey) *AcceptAdminRoleTokenAdminRegistry { - inst.AccountMetaSlice[1] = ag_solanago.Meta(authority).WRITE().SIGNER() - return inst -} - -// GetAuthorityAccount gets the "authority" account. -func (inst *AcceptAdminRoleTokenAdminRegistry) GetAuthorityAccount() *ag_solanago.AccountMeta { - return inst.AccountMetaSlice[1] -} - -func (inst AcceptAdminRoleTokenAdminRegistry) Build() *Instruction { - return &Instruction{BaseVariant: ag_binary.BaseVariant{ - Impl: inst, - TypeID: Instruction_AcceptAdminRoleTokenAdminRegistry, - }} -} - -// ValidateAndBuild validates the instruction parameters and accounts; -// if there is a validation error, it returns the error. -// Otherwise, it builds and returns the instruction. -func (inst AcceptAdminRoleTokenAdminRegistry) ValidateAndBuild() (*Instruction, error) { - if err := inst.Validate(); err != nil { - return nil, err - } - return inst.Build(), nil -} - -func (inst *AcceptAdminRoleTokenAdminRegistry) Validate() error { - // Check whether all (required) parameters are set: - { - if inst.Mint == nil { - return errors.New("Mint parameter is not set") - } - } - - // Check whether all (required) accounts are set: - { - if inst.AccountMetaSlice[0] == nil { - return errors.New("accounts.TokenAdminRegistry is not set") - } - if inst.AccountMetaSlice[1] == nil { - return errors.New("accounts.Authority is not set") - } - } - return nil -} - -func (inst *AcceptAdminRoleTokenAdminRegistry) EncodeToTree(parent ag_treeout.Branches) { - parent.Child(ag_format.Program(ProgramName, ProgramID)). - // - ParentFunc(func(programBranch ag_treeout.Branches) { - programBranch.Child(ag_format.Instruction("AcceptAdminRoleTokenAdminRegistry")). - // - ParentFunc(func(instructionBranch ag_treeout.Branches) { - - // Parameters of the instruction: - instructionBranch.Child("Params[len=1]").ParentFunc(func(paramsBranch ag_treeout.Branches) { - paramsBranch.Child(ag_format.Param("Mint", *inst.Mint)) - }) - - // Accounts of the instruction: - instructionBranch.Child("Accounts[len=2]").ParentFunc(func(accountsBranch ag_treeout.Branches) { - accountsBranch.Child(ag_format.Meta("tokenAdminRegistry", inst.AccountMetaSlice[0])) - accountsBranch.Child(ag_format.Meta(" authority", inst.AccountMetaSlice[1])) - }) - }) - }) -} - -func (obj AcceptAdminRoleTokenAdminRegistry) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { - // Serialize `Mint` param: - err = encoder.Encode(obj.Mint) - if err != nil { - return err - } - return nil -} -func (obj *AcceptAdminRoleTokenAdminRegistry) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { - // Deserialize `Mint`: - err = decoder.Decode(&obj.Mint) - if err != nil { - return err - } - return nil -} - -// NewAcceptAdminRoleTokenAdminRegistryInstruction declares a new AcceptAdminRoleTokenAdminRegistry instruction with the provided parameters and accounts. -func NewAcceptAdminRoleTokenAdminRegistryInstruction( - // Parameters: - mint ag_solanago.PublicKey, - // Accounts: - tokenAdminRegistry ag_solanago.PublicKey, - authority ag_solanago.PublicKey) *AcceptAdminRoleTokenAdminRegistry { - return NewAcceptAdminRoleTokenAdminRegistryInstructionBuilder(). - SetMint(mint). - SetTokenAdminRegistryAccount(tokenAdminRegistry). - SetAuthorityAccount(authority) -} diff --git a/core/capabilities/ccip/ccipsolana/ccip_router/AcceptAdminRoleTokenAdminRegistry_test.go b/core/capabilities/ccip/ccipsolana/ccip_router/AcceptAdminRoleTokenAdminRegistry_test.go deleted file mode 100644 index 44baeb8e004..00000000000 --- a/core/capabilities/ccip/ccipsolana/ccip_router/AcceptAdminRoleTokenAdminRegistry_test.go +++ /dev/null @@ -1,32 +0,0 @@ -// Code generated by https://github.com/gagliardetto/anchor-go. DO NOT EDIT. - -package ccip_router - -import ( - "bytes" - ag_gofuzz "github.com/gagliardetto/gofuzz" - ag_require "github.com/stretchr/testify/require" - "strconv" - "testing" -) - -func TestEncodeDecode_AcceptAdminRoleTokenAdminRegistry(t *testing.T) { - fu := ag_gofuzz.New().NilChance(0) - for i := 0; i < 1; i++ { - t.Run("AcceptAdminRoleTokenAdminRegistry"+strconv.Itoa(i), func(t *testing.T) { - { - params := new(AcceptAdminRoleTokenAdminRegistry) - fu.Fuzz(params) - params.AccountMetaSlice = nil - buf := new(bytes.Buffer) - err := encodeT(*params, buf) - ag_require.NoError(t, err) - got := new(AcceptAdminRoleTokenAdminRegistry) - err = decodeT(got, buf.Bytes()) - got.AccountMetaSlice = nil - ag_require.NoError(t, err) - ag_require.Equal(t, params, got) - } - }) - } -} diff --git a/core/capabilities/ccip/ccipsolana/ccip_router/AcceptOwnership.go b/core/capabilities/ccip/ccipsolana/ccip_router/AcceptOwnership.go deleted file mode 100644 index 9354db59224..00000000000 --- a/core/capabilities/ccip/ccipsolana/ccip_router/AcceptOwnership.go +++ /dev/null @@ -1,117 +0,0 @@ -// Code generated by https://github.com/gagliardetto/anchor-go. DO NOT EDIT. - -package ccip_router - -import ( - "errors" - ag_binary "github.com/gagliardetto/binary" - ag_solanago "github.com/gagliardetto/solana-go" - ag_format "github.com/gagliardetto/solana-go/text/format" - ag_treeout "github.com/gagliardetto/treeout" -) - -// AcceptOwnership is the `acceptOwnership` instruction. -type AcceptOwnership struct { - - // [0] = [WRITE] config - // - // [1] = [SIGNER] authority - ag_solanago.AccountMetaSlice `bin:"-" borsh_skip:"true"` -} - -// NewAcceptOwnershipInstructionBuilder creates a new `AcceptOwnership` instruction builder. -func NewAcceptOwnershipInstructionBuilder() *AcceptOwnership { - nd := &AcceptOwnership{ - AccountMetaSlice: make(ag_solanago.AccountMetaSlice, 2), - } - return nd -} - -// SetConfigAccount sets the "config" account. -func (inst *AcceptOwnership) SetConfigAccount(config ag_solanago.PublicKey) *AcceptOwnership { - inst.AccountMetaSlice[0] = ag_solanago.Meta(config).WRITE() - return inst -} - -// GetConfigAccount gets the "config" account. -func (inst *AcceptOwnership) GetConfigAccount() *ag_solanago.AccountMeta { - return inst.AccountMetaSlice[0] -} - -// SetAuthorityAccount sets the "authority" account. -func (inst *AcceptOwnership) SetAuthorityAccount(authority ag_solanago.PublicKey) *AcceptOwnership { - inst.AccountMetaSlice[1] = ag_solanago.Meta(authority).SIGNER() - return inst -} - -// GetAuthorityAccount gets the "authority" account. -func (inst *AcceptOwnership) GetAuthorityAccount() *ag_solanago.AccountMeta { - return inst.AccountMetaSlice[1] -} - -func (inst AcceptOwnership) Build() *Instruction { - return &Instruction{BaseVariant: ag_binary.BaseVariant{ - Impl: inst, - TypeID: Instruction_AcceptOwnership, - }} -} - -// ValidateAndBuild validates the instruction parameters and accounts; -// if there is a validation error, it returns the error. -// Otherwise, it builds and returns the instruction. -func (inst AcceptOwnership) ValidateAndBuild() (*Instruction, error) { - if err := inst.Validate(); err != nil { - return nil, err - } - return inst.Build(), nil -} - -func (inst *AcceptOwnership) Validate() error { - // Check whether all (required) accounts are set: - { - if inst.AccountMetaSlice[0] == nil { - return errors.New("accounts.Config is not set") - } - if inst.AccountMetaSlice[1] == nil { - return errors.New("accounts.Authority is not set") - } - } - return nil -} - -func (inst *AcceptOwnership) EncodeToTree(parent ag_treeout.Branches) { - parent.Child(ag_format.Program(ProgramName, ProgramID)). - // - ParentFunc(func(programBranch ag_treeout.Branches) { - programBranch.Child(ag_format.Instruction("AcceptOwnership")). - // - ParentFunc(func(instructionBranch ag_treeout.Branches) { - - // Parameters of the instruction: - instructionBranch.Child("Params[len=0]").ParentFunc(func(paramsBranch ag_treeout.Branches) {}) - - // Accounts of the instruction: - instructionBranch.Child("Accounts[len=2]").ParentFunc(func(accountsBranch ag_treeout.Branches) { - accountsBranch.Child(ag_format.Meta(" config", inst.AccountMetaSlice[0])) - accountsBranch.Child(ag_format.Meta("authority", inst.AccountMetaSlice[1])) - }) - }) - }) -} - -func (obj AcceptOwnership) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { - return nil -} -func (obj *AcceptOwnership) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { - return nil -} - -// NewAcceptOwnershipInstruction declares a new AcceptOwnership instruction with the provided parameters and accounts. -func NewAcceptOwnershipInstruction( - // Accounts: - config ag_solanago.PublicKey, - authority ag_solanago.PublicKey) *AcceptOwnership { - return NewAcceptOwnershipInstructionBuilder(). - SetConfigAccount(config). - SetAuthorityAccount(authority) -} diff --git a/core/capabilities/ccip/ccipsolana/ccip_router/AcceptOwnership_test.go b/core/capabilities/ccip/ccipsolana/ccip_router/AcceptOwnership_test.go deleted file mode 100644 index da475cd5d24..00000000000 --- a/core/capabilities/ccip/ccipsolana/ccip_router/AcceptOwnership_test.go +++ /dev/null @@ -1,32 +0,0 @@ -// Code generated by https://github.com/gagliardetto/anchor-go. DO NOT EDIT. - -package ccip_router - -import ( - "bytes" - ag_gofuzz "github.com/gagliardetto/gofuzz" - ag_require "github.com/stretchr/testify/require" - "strconv" - "testing" -) - -func TestEncodeDecode_AcceptOwnership(t *testing.T) { - fu := ag_gofuzz.New().NilChance(0) - for i := 0; i < 1; i++ { - t.Run("AcceptOwnership"+strconv.Itoa(i), func(t *testing.T) { - { - params := new(AcceptOwnership) - fu.Fuzz(params) - params.AccountMetaSlice = nil - buf := new(bytes.Buffer) - err := encodeT(*params, buf) - ag_require.NoError(t, err) - got := new(AcceptOwnership) - err = decodeT(got, buf.Bytes()) - got.AccountMetaSlice = nil - ag_require.NoError(t, err) - ag_require.Equal(t, params, got) - } - }) - } -} diff --git a/core/capabilities/ccip/ccipsolana/ccip_router/AddChainSelector.go b/core/capabilities/ccip/ccipsolana/ccip_router/AddChainSelector.go deleted file mode 100644 index 743d44c41e1..00000000000 --- a/core/capabilities/ccip/ccipsolana/ccip_router/AddChainSelector.go +++ /dev/null @@ -1,207 +0,0 @@ -// Code generated by https://github.com/gagliardetto/anchor-go. DO NOT EDIT. - -package ccip_router - -import ( - "errors" - ag_binary "github.com/gagliardetto/binary" - ag_solanago "github.com/gagliardetto/solana-go" - ag_format "github.com/gagliardetto/solana-go/text/format" - ag_treeout "github.com/gagliardetto/treeout" -) - -// The Admin needs to add any new chain supported (this means both OnRamp and OffRamp). -type AddChainSelector struct { - NewChainSelector *uint64 - OnRampAddress *[]byte - - // [0] = [WRITE] chainState - // - // [1] = [] config - // - // [2] = [WRITE, SIGNER] authority - // - // [3] = [] systemProgram - ag_solanago.AccountMetaSlice `bin:"-" borsh_skip:"true"` -} - -// NewAddChainSelectorInstructionBuilder creates a new `AddChainSelector` instruction builder. -func NewAddChainSelectorInstructionBuilder() *AddChainSelector { - nd := &AddChainSelector{ - AccountMetaSlice: make(ag_solanago.AccountMetaSlice, 4), - } - return nd -} - -// SetNewChainSelector sets the "newChainSelector" parameter. -func (inst *AddChainSelector) SetNewChainSelector(newChainSelector uint64) *AddChainSelector { - inst.NewChainSelector = &newChainSelector - return inst -} - -// SetOnRampAddress sets the "onRampAddress" parameter. -func (inst *AddChainSelector) SetOnRampAddress(onRampAddress []byte) *AddChainSelector { - inst.OnRampAddress = &onRampAddress - return inst -} - -// SetChainStateAccount sets the "chainState" account. -func (inst *AddChainSelector) SetChainStateAccount(chainState ag_solanago.PublicKey) *AddChainSelector { - inst.AccountMetaSlice[0] = ag_solanago.Meta(chainState).WRITE() - return inst -} - -// GetChainStateAccount gets the "chainState" account. -func (inst *AddChainSelector) GetChainStateAccount() *ag_solanago.AccountMeta { - return inst.AccountMetaSlice[0] -} - -// SetConfigAccount sets the "config" account. -func (inst *AddChainSelector) SetConfigAccount(config ag_solanago.PublicKey) *AddChainSelector { - inst.AccountMetaSlice[1] = ag_solanago.Meta(config) - return inst -} - -// GetConfigAccount gets the "config" account. -func (inst *AddChainSelector) GetConfigAccount() *ag_solanago.AccountMeta { - return inst.AccountMetaSlice[1] -} - -// SetAuthorityAccount sets the "authority" account. -func (inst *AddChainSelector) SetAuthorityAccount(authority ag_solanago.PublicKey) *AddChainSelector { - inst.AccountMetaSlice[2] = ag_solanago.Meta(authority).WRITE().SIGNER() - return inst -} - -// GetAuthorityAccount gets the "authority" account. -func (inst *AddChainSelector) GetAuthorityAccount() *ag_solanago.AccountMeta { - return inst.AccountMetaSlice[2] -} - -// SetSystemProgramAccount sets the "systemProgram" account. -func (inst *AddChainSelector) SetSystemProgramAccount(systemProgram ag_solanago.PublicKey) *AddChainSelector { - inst.AccountMetaSlice[3] = ag_solanago.Meta(systemProgram) - return inst -} - -// GetSystemProgramAccount gets the "systemProgram" account. -func (inst *AddChainSelector) GetSystemProgramAccount() *ag_solanago.AccountMeta { - return inst.AccountMetaSlice[3] -} - -func (inst AddChainSelector) Build() *Instruction { - return &Instruction{BaseVariant: ag_binary.BaseVariant{ - Impl: inst, - TypeID: Instruction_AddChainSelector, - }} -} - -// ValidateAndBuild validates the instruction parameters and accounts; -// if there is a validation error, it returns the error. -// Otherwise, it builds and returns the instruction. -func (inst AddChainSelector) ValidateAndBuild() (*Instruction, error) { - if err := inst.Validate(); err != nil { - return nil, err - } - return inst.Build(), nil -} - -func (inst *AddChainSelector) Validate() error { - // Check whether all (required) parameters are set: - { - if inst.NewChainSelector == nil { - return errors.New("NewChainSelector parameter is not set") - } - if inst.OnRampAddress == nil { - return errors.New("OnRampAddress parameter is not set") - } - } - - // Check whether all (required) accounts are set: - { - if inst.AccountMetaSlice[0] == nil { - return errors.New("accounts.ChainState is not set") - } - if inst.AccountMetaSlice[1] == nil { - return errors.New("accounts.Config is not set") - } - if inst.AccountMetaSlice[2] == nil { - return errors.New("accounts.Authority is not set") - } - if inst.AccountMetaSlice[3] == nil { - return errors.New("accounts.SystemProgram is not set") - } - } - return nil -} - -func (inst *AddChainSelector) EncodeToTree(parent ag_treeout.Branches) { - parent.Child(ag_format.Program(ProgramName, ProgramID)). - // - ParentFunc(func(programBranch ag_treeout.Branches) { - programBranch.Child(ag_format.Instruction("AddChainSelector")). - // - ParentFunc(func(instructionBranch ag_treeout.Branches) { - - // Parameters of the instruction: - instructionBranch.Child("Params[len=2]").ParentFunc(func(paramsBranch ag_treeout.Branches) { - paramsBranch.Child(ag_format.Param("NewChainSelector", *inst.NewChainSelector)) - paramsBranch.Child(ag_format.Param(" OnRampAddress", *inst.OnRampAddress)) - }) - - // Accounts of the instruction: - instructionBranch.Child("Accounts[len=4]").ParentFunc(func(accountsBranch ag_treeout.Branches) { - accountsBranch.Child(ag_format.Meta(" chainState", inst.AccountMetaSlice[0])) - accountsBranch.Child(ag_format.Meta(" config", inst.AccountMetaSlice[1])) - accountsBranch.Child(ag_format.Meta(" authority", inst.AccountMetaSlice[2])) - accountsBranch.Child(ag_format.Meta("systemProgram", inst.AccountMetaSlice[3])) - }) - }) - }) -} - -func (obj AddChainSelector) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { - // Serialize `NewChainSelector` param: - err = encoder.Encode(obj.NewChainSelector) - if err != nil { - return err - } - // Serialize `OnRampAddress` param: - err = encoder.Encode(obj.OnRampAddress) - if err != nil { - return err - } - return nil -} -func (obj *AddChainSelector) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { - // Deserialize `NewChainSelector`: - err = decoder.Decode(&obj.NewChainSelector) - if err != nil { - return err - } - // Deserialize `OnRampAddress`: - err = decoder.Decode(&obj.OnRampAddress) - if err != nil { - return err - } - return nil -} - -// NewAddChainSelectorInstruction declares a new AddChainSelector instruction with the provided parameters and accounts. -func NewAddChainSelectorInstruction( - // Parameters: - newChainSelector uint64, - onRampAddress []byte, - // Accounts: - chainState ag_solanago.PublicKey, - config ag_solanago.PublicKey, - authority ag_solanago.PublicKey, - systemProgram ag_solanago.PublicKey) *AddChainSelector { - return NewAddChainSelectorInstructionBuilder(). - SetNewChainSelector(newChainSelector). - SetOnRampAddress(onRampAddress). - SetChainStateAccount(chainState). - SetConfigAccount(config). - SetAuthorityAccount(authority). - SetSystemProgramAccount(systemProgram) -} diff --git a/core/capabilities/ccip/ccipsolana/ccip_router/AddChainSelector_test.go b/core/capabilities/ccip/ccipsolana/ccip_router/AddChainSelector_test.go deleted file mode 100644 index 8398360f7f6..00000000000 --- a/core/capabilities/ccip/ccipsolana/ccip_router/AddChainSelector_test.go +++ /dev/null @@ -1,32 +0,0 @@ -// Code generated by https://github.com/gagliardetto/anchor-go. DO NOT EDIT. - -package ccip_router - -import ( - "bytes" - ag_gofuzz "github.com/gagliardetto/gofuzz" - ag_require "github.com/stretchr/testify/require" - "strconv" - "testing" -) - -func TestEncodeDecode_AddChainSelector(t *testing.T) { - fu := ag_gofuzz.New().NilChance(0) - for i := 0; i < 1; i++ { - t.Run("AddChainSelector"+strconv.Itoa(i), func(t *testing.T) { - { - params := new(AddChainSelector) - fu.Fuzz(params) - params.AccountMetaSlice = nil - buf := new(bytes.Buffer) - err := encodeT(*params, buf) - ag_require.NoError(t, err) - got := new(AddChainSelector) - err = decodeT(got, buf.Bytes()) - got.AccountMetaSlice = nil - ag_require.NoError(t, err) - ag_require.Equal(t, params, got) - } - }) - } -} diff --git a/core/capabilities/ccip/ccipsolana/ccip_router/CcipSend.go b/core/capabilities/ccip/ccipsolana/ccip_router/CcipSend.go deleted file mode 100644 index 61cd343e929..00000000000 --- a/core/capabilities/ccip/ccipsolana/ccip_router/CcipSend.go +++ /dev/null @@ -1,250 +0,0 @@ -// Code generated by https://github.com/gagliardetto/anchor-go. DO NOT EDIT. - -package ccip_router - -import ( - "errors" - ag_binary "github.com/gagliardetto/binary" - ag_solanago "github.com/gagliardetto/solana-go" - ag_format "github.com/gagliardetto/solana-go/text/format" - ag_treeout "github.com/gagliardetto/treeout" -) - -// ON RAMP FLOW -// The method name needs to be ccip_send with Anchor encoding. -// This function is called by the CCIP Sender Contract (or final user) to send a message to the CCIP Router. -// The size limit of data is 256 bytes. -// The message is sent to the receiver on the destination chain selector. -// This message emits the event CCIPSendRequested with all the necessary data to be retrieved by the OffChain Code -type CcipSend struct { - DestChainSelector *uint64 - Message *Solana2AnyMessage - - // [0] = [] config - // - // [1] = [WRITE] chainState - // - // [2] = [WRITE] nonce - // - // [3] = [WRITE, SIGNER] authority - // - // [4] = [] systemProgram - // - // [5] = [WRITE] tokenPoolsSigner - ag_solanago.AccountMetaSlice `bin:"-" borsh_skip:"true"` -} - -// NewCcipSendInstructionBuilder creates a new `CcipSend` instruction builder. -func NewCcipSendInstructionBuilder() *CcipSend { - nd := &CcipSend{ - AccountMetaSlice: make(ag_solanago.AccountMetaSlice, 6), - } - return nd -} - -// SetDestChainSelector sets the "destChainSelector" parameter. -func (inst *CcipSend) SetDestChainSelector(destChainSelector uint64) *CcipSend { - inst.DestChainSelector = &destChainSelector - return inst -} - -// SetMessage sets the "message" parameter. -func (inst *CcipSend) SetMessage(message Solana2AnyMessage) *CcipSend { - inst.Message = &message - return inst -} - -// SetConfigAccount sets the "config" account. -func (inst *CcipSend) SetConfigAccount(config ag_solanago.PublicKey) *CcipSend { - inst.AccountMetaSlice[0] = ag_solanago.Meta(config) - return inst -} - -// GetConfigAccount gets the "config" account. -func (inst *CcipSend) GetConfigAccount() *ag_solanago.AccountMeta { - return inst.AccountMetaSlice[0] -} - -// SetChainStateAccount sets the "chainState" account. -func (inst *CcipSend) SetChainStateAccount(chainState ag_solanago.PublicKey) *CcipSend { - inst.AccountMetaSlice[1] = ag_solanago.Meta(chainState).WRITE() - return inst -} - -// GetChainStateAccount gets the "chainState" account. -func (inst *CcipSend) GetChainStateAccount() *ag_solanago.AccountMeta { - return inst.AccountMetaSlice[1] -} - -// SetNonceAccount sets the "nonce" account. -func (inst *CcipSend) SetNonceAccount(nonce ag_solanago.PublicKey) *CcipSend { - inst.AccountMetaSlice[2] = ag_solanago.Meta(nonce).WRITE() - return inst -} - -// GetNonceAccount gets the "nonce" account. -func (inst *CcipSend) GetNonceAccount() *ag_solanago.AccountMeta { - return inst.AccountMetaSlice[2] -} - -// SetAuthorityAccount sets the "authority" account. -func (inst *CcipSend) SetAuthorityAccount(authority ag_solanago.PublicKey) *CcipSend { - inst.AccountMetaSlice[3] = ag_solanago.Meta(authority).WRITE().SIGNER() - return inst -} - -// GetAuthorityAccount gets the "authority" account. -func (inst *CcipSend) GetAuthorityAccount() *ag_solanago.AccountMeta { - return inst.AccountMetaSlice[3] -} - -// SetSystemProgramAccount sets the "systemProgram" account. -func (inst *CcipSend) SetSystemProgramAccount(systemProgram ag_solanago.PublicKey) *CcipSend { - inst.AccountMetaSlice[4] = ag_solanago.Meta(systemProgram) - return inst -} - -// GetSystemProgramAccount gets the "systemProgram" account. -func (inst *CcipSend) GetSystemProgramAccount() *ag_solanago.AccountMeta { - return inst.AccountMetaSlice[4] -} - -// SetTokenPoolsSignerAccount sets the "tokenPoolsSigner" account. -func (inst *CcipSend) SetTokenPoolsSignerAccount(tokenPoolsSigner ag_solanago.PublicKey) *CcipSend { - inst.AccountMetaSlice[5] = ag_solanago.Meta(tokenPoolsSigner).WRITE() - return inst -} - -// GetTokenPoolsSignerAccount gets the "tokenPoolsSigner" account. -func (inst *CcipSend) GetTokenPoolsSignerAccount() *ag_solanago.AccountMeta { - return inst.AccountMetaSlice[5] -} - -func (inst CcipSend) Build() *Instruction { - return &Instruction{BaseVariant: ag_binary.BaseVariant{ - Impl: inst, - TypeID: Instruction_CcipSend, - }} -} - -// ValidateAndBuild validates the instruction parameters and accounts; -// if there is a validation error, it returns the error. -// Otherwise, it builds and returns the instruction. -func (inst CcipSend) ValidateAndBuild() (*Instruction, error) { - if err := inst.Validate(); err != nil { - return nil, err - } - return inst.Build(), nil -} - -func (inst *CcipSend) Validate() error { - // Check whether all (required) parameters are set: - { - if inst.DestChainSelector == nil { - return errors.New("DestChainSelector parameter is not set") - } - if inst.Message == nil { - return errors.New("Message parameter is not set") - } - } - - // Check whether all (required) accounts are set: - { - if inst.AccountMetaSlice[0] == nil { - return errors.New("accounts.Config is not set") - } - if inst.AccountMetaSlice[1] == nil { - return errors.New("accounts.ChainState is not set") - } - if inst.AccountMetaSlice[2] == nil { - return errors.New("accounts.Nonce is not set") - } - if inst.AccountMetaSlice[3] == nil { - return errors.New("accounts.Authority is not set") - } - if inst.AccountMetaSlice[4] == nil { - return errors.New("accounts.SystemProgram is not set") - } - if inst.AccountMetaSlice[5] == nil { - return errors.New("accounts.TokenPoolsSigner is not set") - } - } - return nil -} - -func (inst *CcipSend) EncodeToTree(parent ag_treeout.Branches) { - parent.Child(ag_format.Program(ProgramName, ProgramID)). - // - ParentFunc(func(programBranch ag_treeout.Branches) { - programBranch.Child(ag_format.Instruction("CcipSend")). - // - ParentFunc(func(instructionBranch ag_treeout.Branches) { - - // Parameters of the instruction: - instructionBranch.Child("Params[len=2]").ParentFunc(func(paramsBranch ag_treeout.Branches) { - paramsBranch.Child(ag_format.Param("DestChainSelector", *inst.DestChainSelector)) - paramsBranch.Child(ag_format.Param(" Message", *inst.Message)) - }) - - // Accounts of the instruction: - instructionBranch.Child("Accounts[len=6]").ParentFunc(func(accountsBranch ag_treeout.Branches) { - accountsBranch.Child(ag_format.Meta(" config", inst.AccountMetaSlice[0])) - accountsBranch.Child(ag_format.Meta(" chainState", inst.AccountMetaSlice[1])) - accountsBranch.Child(ag_format.Meta(" nonce", inst.AccountMetaSlice[2])) - accountsBranch.Child(ag_format.Meta(" authority", inst.AccountMetaSlice[3])) - accountsBranch.Child(ag_format.Meta(" systemProgram", inst.AccountMetaSlice[4])) - accountsBranch.Child(ag_format.Meta("tokenPoolsSigner", inst.AccountMetaSlice[5])) - }) - }) - }) -} - -func (obj CcipSend) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { - // Serialize `DestChainSelector` param: - err = encoder.Encode(obj.DestChainSelector) - if err != nil { - return err - } - // Serialize `Message` param: - err = encoder.Encode(obj.Message) - if err != nil { - return err - } - return nil -} -func (obj *CcipSend) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { - // Deserialize `DestChainSelector`: - err = decoder.Decode(&obj.DestChainSelector) - if err != nil { - return err - } - // Deserialize `Message`: - err = decoder.Decode(&obj.Message) - if err != nil { - return err - } - return nil -} - -// NewCcipSendInstruction declares a new CcipSend instruction with the provided parameters and accounts. -func NewCcipSendInstruction( - // Parameters: - destChainSelector uint64, - message Solana2AnyMessage, - // Accounts: - config ag_solanago.PublicKey, - chainState ag_solanago.PublicKey, - nonce ag_solanago.PublicKey, - authority ag_solanago.PublicKey, - systemProgram ag_solanago.PublicKey, - tokenPoolsSigner ag_solanago.PublicKey) *CcipSend { - return NewCcipSendInstructionBuilder(). - SetDestChainSelector(destChainSelector). - SetMessage(message). - SetConfigAccount(config). - SetChainStateAccount(chainState). - SetNonceAccount(nonce). - SetAuthorityAccount(authority). - SetSystemProgramAccount(systemProgram). - SetTokenPoolsSignerAccount(tokenPoolsSigner) -} diff --git a/core/capabilities/ccip/ccipsolana/ccip_router/CcipSend_test.go b/core/capabilities/ccip/ccipsolana/ccip_router/CcipSend_test.go deleted file mode 100644 index a9f819342cb..00000000000 --- a/core/capabilities/ccip/ccipsolana/ccip_router/CcipSend_test.go +++ /dev/null @@ -1,32 +0,0 @@ -// Code generated by https://github.com/gagliardetto/anchor-go. DO NOT EDIT. - -package ccip_router - -import ( - "bytes" - ag_gofuzz "github.com/gagliardetto/gofuzz" - ag_require "github.com/stretchr/testify/require" - "strconv" - "testing" -) - -func TestEncodeDecode_CcipSend(t *testing.T) { - fu := ag_gofuzz.New().NilChance(0) - for i := 0; i < 1; i++ { - t.Run("CcipSend"+strconv.Itoa(i), func(t *testing.T) { - { - params := new(CcipSend) - fu.Fuzz(params) - params.AccountMetaSlice = nil - buf := new(bytes.Buffer) - err := encodeT(*params, buf) - ag_require.NoError(t, err) - got := new(CcipSend) - err = decodeT(got, buf.Bytes()) - got.AccountMetaSlice = nil - ag_require.NoError(t, err) - ag_require.Equal(t, params, got) - } - }) - } -} diff --git a/core/capabilities/ccip/ccipsolana/ccip_router/Commit.go b/core/capabilities/ccip/ccipsolana/ccip_router/Commit.go deleted file mode 100644 index 898c086029b..00000000000 --- a/core/capabilities/ccip/ccipsolana/ccip_router/Commit.go +++ /dev/null @@ -1,279 +0,0 @@ -// Code generated by https://github.com/gagliardetto/anchor-go. DO NOT EDIT. - -package ccip_router - -import ( - "errors" - ag_binary "github.com/gagliardetto/binary" - ag_solanago "github.com/gagliardetto/solana-go" - ag_format "github.com/gagliardetto/solana-go/text/format" - ag_treeout "github.com/gagliardetto/treeout" -) - -// OFF RAMP FLOW -// -// The method name needs to be commit with Anchor encoding. -// -// This function is called by the OffChain when committing one Report to the Solana Router. -// In this Flow only one report is sent, the Commit Report. This is different as EVM does, -// this is because here all the chain state is stored in one account per Merkle Tree Root. -// So, to avoid having to send a dynamic size array of accounts, in this message only one Commit Report Account is sent. -// This message validates the signatures of the report and stores the Merkle Root in the Commit Report Account. -// The Report must contain an interval of messages, and the min of them must be the next sequence number expected. -// The max size of the interval is 64. -// This message emits two events: CommitReportAccepted and Transmitted. -type Commit struct { - ReportContext *[3][32]uint8 - Report *CommitInput - Signatures *[][65]uint8 - - // [0] = [] config - // - // [1] = [WRITE] chainState - // - // [2] = [WRITE] commitReport - // - // [3] = [WRITE, SIGNER] authority - // - // [4] = [] systemProgram - // - // [5] = [] sysvarInstructions - ag_solanago.AccountMetaSlice `bin:"-" borsh_skip:"true"` -} - -// NewCommitInstructionBuilder creates a new `Commit` instruction builder. -func NewCommitInstructionBuilder() *Commit { - nd := &Commit{ - AccountMetaSlice: make(ag_solanago.AccountMetaSlice, 6), - } - return nd -} - -// SetReportContext sets the "reportContext" parameter. -func (inst *Commit) SetReportContext(reportContext [3][32]uint8) *Commit { - inst.ReportContext = &reportContext - return inst -} - -// SetReport sets the "report" parameter. -func (inst *Commit) SetReport(report CommitInput) *Commit { - inst.Report = &report - return inst -} - -// SetSignatures sets the "signatures" parameter. -func (inst *Commit) SetSignatures(signatures [][65]uint8) *Commit { - inst.Signatures = &signatures - return inst -} - -// SetConfigAccount sets the "config" account. -func (inst *Commit) SetConfigAccount(config ag_solanago.PublicKey) *Commit { - inst.AccountMetaSlice[0] = ag_solanago.Meta(config) - return inst -} - -// GetConfigAccount gets the "config" account. -func (inst *Commit) GetConfigAccount() *ag_solanago.AccountMeta { - return inst.AccountMetaSlice[0] -} - -// SetChainStateAccount sets the "chainState" account. -func (inst *Commit) SetChainStateAccount(chainState ag_solanago.PublicKey) *Commit { - inst.AccountMetaSlice[1] = ag_solanago.Meta(chainState).WRITE() - return inst -} - -// GetChainStateAccount gets the "chainState" account. -func (inst *Commit) GetChainStateAccount() *ag_solanago.AccountMeta { - return inst.AccountMetaSlice[1] -} - -// SetCommitReportAccount sets the "commitReport" account. -func (inst *Commit) SetCommitReportAccount(commitReport ag_solanago.PublicKey) *Commit { - inst.AccountMetaSlice[2] = ag_solanago.Meta(commitReport).WRITE() - return inst -} - -// GetCommitReportAccount gets the "commitReport" account. -func (inst *Commit) GetCommitReportAccount() *ag_solanago.AccountMeta { - return inst.AccountMetaSlice[2] -} - -// SetAuthorityAccount sets the "authority" account. -func (inst *Commit) SetAuthorityAccount(authority ag_solanago.PublicKey) *Commit { - inst.AccountMetaSlice[3] = ag_solanago.Meta(authority).WRITE().SIGNER() - return inst -} - -// GetAuthorityAccount gets the "authority" account. -func (inst *Commit) GetAuthorityAccount() *ag_solanago.AccountMeta { - return inst.AccountMetaSlice[3] -} - -// SetSystemProgramAccount sets the "systemProgram" account. -func (inst *Commit) SetSystemProgramAccount(systemProgram ag_solanago.PublicKey) *Commit { - inst.AccountMetaSlice[4] = ag_solanago.Meta(systemProgram) - return inst -} - -// GetSystemProgramAccount gets the "systemProgram" account. -func (inst *Commit) GetSystemProgramAccount() *ag_solanago.AccountMeta { - return inst.AccountMetaSlice[4] -} - -// SetSysvarInstructionsAccount sets the "sysvarInstructions" account. -func (inst *Commit) SetSysvarInstructionsAccount(sysvarInstructions ag_solanago.PublicKey) *Commit { - inst.AccountMetaSlice[5] = ag_solanago.Meta(sysvarInstructions) - return inst -} - -// GetSysvarInstructionsAccount gets the "sysvarInstructions" account. -func (inst *Commit) GetSysvarInstructionsAccount() *ag_solanago.AccountMeta { - return inst.AccountMetaSlice[5] -} - -func (inst Commit) Build() *Instruction { - return &Instruction{BaseVariant: ag_binary.BaseVariant{ - Impl: inst, - TypeID: Instruction_Commit, - }} -} - -// ValidateAndBuild validates the instruction parameters and accounts; -// if there is a validation error, it returns the error. -// Otherwise, it builds and returns the instruction. -func (inst Commit) ValidateAndBuild() (*Instruction, error) { - if err := inst.Validate(); err != nil { - return nil, err - } - return inst.Build(), nil -} - -func (inst *Commit) Validate() error { - // Check whether all (required) parameters are set: - { - if inst.ReportContext == nil { - return errors.New("ReportContext parameter is not set") - } - if inst.Report == nil { - return errors.New("Report parameter is not set") - } - if inst.Signatures == nil { - return errors.New("Signatures parameter is not set") - } - } - - // Check whether all (required) accounts are set: - { - if inst.AccountMetaSlice[0] == nil { - return errors.New("accounts.Config is not set") - } - if inst.AccountMetaSlice[1] == nil { - return errors.New("accounts.ChainState is not set") - } - if inst.AccountMetaSlice[2] == nil { - return errors.New("accounts.CommitReport is not set") - } - if inst.AccountMetaSlice[3] == nil { - return errors.New("accounts.Authority is not set") - } - if inst.AccountMetaSlice[4] == nil { - return errors.New("accounts.SystemProgram is not set") - } - if inst.AccountMetaSlice[5] == nil { - return errors.New("accounts.SysvarInstructions is not set") - } - } - return nil -} - -func (inst *Commit) EncodeToTree(parent ag_treeout.Branches) { - parent.Child(ag_format.Program(ProgramName, ProgramID)). - // - ParentFunc(func(programBranch ag_treeout.Branches) { - programBranch.Child(ag_format.Instruction("Commit")). - // - ParentFunc(func(instructionBranch ag_treeout.Branches) { - - // Parameters of the instruction: - instructionBranch.Child("Params[len=3]").ParentFunc(func(paramsBranch ag_treeout.Branches) { - paramsBranch.Child(ag_format.Param("ReportContext", *inst.ReportContext)) - paramsBranch.Child(ag_format.Param(" Report", *inst.Report)) - paramsBranch.Child(ag_format.Param(" Signatures", *inst.Signatures)) - }) - - // Accounts of the instruction: - instructionBranch.Child("Accounts[len=6]").ParentFunc(func(accountsBranch ag_treeout.Branches) { - accountsBranch.Child(ag_format.Meta(" config", inst.AccountMetaSlice[0])) - accountsBranch.Child(ag_format.Meta(" chainState", inst.AccountMetaSlice[1])) - accountsBranch.Child(ag_format.Meta(" commitReport", inst.AccountMetaSlice[2])) - accountsBranch.Child(ag_format.Meta(" authority", inst.AccountMetaSlice[3])) - accountsBranch.Child(ag_format.Meta(" systemProgram", inst.AccountMetaSlice[4])) - accountsBranch.Child(ag_format.Meta("sysvarInstructions", inst.AccountMetaSlice[5])) - }) - }) - }) -} - -func (obj Commit) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { - // Serialize `ReportContext` param: - err = encoder.Encode(obj.ReportContext) - if err != nil { - return err - } - // Serialize `Report` param: - err = encoder.Encode(obj.Report) - if err != nil { - return err - } - // Serialize `Signatures` param: - err = encoder.Encode(obj.Signatures) - if err != nil { - return err - } - return nil -} -func (obj *Commit) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { - // Deserialize `ReportContext`: - err = decoder.Decode(&obj.ReportContext) - if err != nil { - return err - } - // Deserialize `Report`: - err = decoder.Decode(&obj.Report) - if err != nil { - return err - } - // Deserialize `Signatures`: - err = decoder.Decode(&obj.Signatures) - if err != nil { - return err - } - return nil -} - -// NewCommitInstruction declares a new Commit instruction with the provided parameters and accounts. -func NewCommitInstruction( - // Parameters: - reportContext [3][32]uint8, - report CommitInput, - signatures [][65]uint8, - // Accounts: - config ag_solanago.PublicKey, - chainState ag_solanago.PublicKey, - commitReport ag_solanago.PublicKey, - authority ag_solanago.PublicKey, - systemProgram ag_solanago.PublicKey, - sysvarInstructions ag_solanago.PublicKey) *Commit { - return NewCommitInstructionBuilder(). - SetReportContext(reportContext). - SetReport(report). - SetSignatures(signatures). - SetConfigAccount(config). - SetChainStateAccount(chainState). - SetCommitReportAccount(commitReport). - SetAuthorityAccount(authority). - SetSystemProgramAccount(systemProgram). - SetSysvarInstructionsAccount(sysvarInstructions) -} diff --git a/core/capabilities/ccip/ccipsolana/ccip_router/Commit_test.go b/core/capabilities/ccip/ccipsolana/ccip_router/Commit_test.go deleted file mode 100644 index fcaf33cc942..00000000000 --- a/core/capabilities/ccip/ccipsolana/ccip_router/Commit_test.go +++ /dev/null @@ -1,32 +0,0 @@ -// Code generated by https://github.com/gagliardetto/anchor-go. DO NOT EDIT. - -package ccip_router - -import ( - "bytes" - ag_gofuzz "github.com/gagliardetto/gofuzz" - ag_require "github.com/stretchr/testify/require" - "strconv" - "testing" -) - -func TestEncodeDecode_Commit(t *testing.T) { - fu := ag_gofuzz.New().NilChance(0) - for i := 0; i < 1; i++ { - t.Run("Commit"+strconv.Itoa(i), func(t *testing.T) { - { - params := new(Commit) - fu.Fuzz(params) - params.AccountMetaSlice = nil - buf := new(bytes.Buffer) - err := encodeT(*params, buf) - ag_require.NoError(t, err) - got := new(Commit) - err = decodeT(got, buf.Bytes()) - got.AccountMetaSlice = nil - ag_require.NoError(t, err) - ag_require.Equal(t, params, got) - } - }) - } -} diff --git a/core/capabilities/ccip/ccipsolana/ccip_router/DisableChainSelector.go b/core/capabilities/ccip/ccipsolana/ccip_router/DisableChainSelector.go deleted file mode 100644 index 772c3391061..00000000000 --- a/core/capabilities/ccip/ccipsolana/ccip_router/DisableChainSelector.go +++ /dev/null @@ -1,184 +0,0 @@ -// Code generated by https://github.com/gagliardetto/anchor-go. DO NOT EDIT. - -package ccip_router - -import ( - "errors" - ag_binary "github.com/gagliardetto/binary" - ag_solanago "github.com/gagliardetto/solana-go" - ag_format "github.com/gagliardetto/solana-go/text/format" - ag_treeout "github.com/gagliardetto/treeout" -) - -// The Admin is the only one able to enable or disable the chain selector -type DisableChainSelector struct { - NewChainSelector *uint64 - - // [0] = [WRITE] chainState - // - // [1] = [] config - // - // [2] = [WRITE, SIGNER] authority - // - // [3] = [] systemProgram - ag_solanago.AccountMetaSlice `bin:"-" borsh_skip:"true"` -} - -// NewDisableChainSelectorInstructionBuilder creates a new `DisableChainSelector` instruction builder. -func NewDisableChainSelectorInstructionBuilder() *DisableChainSelector { - nd := &DisableChainSelector{ - AccountMetaSlice: make(ag_solanago.AccountMetaSlice, 4), - } - return nd -} - -// SetNewChainSelector sets the "newChainSelector" parameter. -func (inst *DisableChainSelector) SetNewChainSelector(newChainSelector uint64) *DisableChainSelector { - inst.NewChainSelector = &newChainSelector - return inst -} - -// SetChainStateAccount sets the "chainState" account. -func (inst *DisableChainSelector) SetChainStateAccount(chainState ag_solanago.PublicKey) *DisableChainSelector { - inst.AccountMetaSlice[0] = ag_solanago.Meta(chainState).WRITE() - return inst -} - -// GetChainStateAccount gets the "chainState" account. -func (inst *DisableChainSelector) GetChainStateAccount() *ag_solanago.AccountMeta { - return inst.AccountMetaSlice[0] -} - -// SetConfigAccount sets the "config" account. -func (inst *DisableChainSelector) SetConfigAccount(config ag_solanago.PublicKey) *DisableChainSelector { - inst.AccountMetaSlice[1] = ag_solanago.Meta(config) - return inst -} - -// GetConfigAccount gets the "config" account. -func (inst *DisableChainSelector) GetConfigAccount() *ag_solanago.AccountMeta { - return inst.AccountMetaSlice[1] -} - -// SetAuthorityAccount sets the "authority" account. -func (inst *DisableChainSelector) SetAuthorityAccount(authority ag_solanago.PublicKey) *DisableChainSelector { - inst.AccountMetaSlice[2] = ag_solanago.Meta(authority).WRITE().SIGNER() - return inst -} - -// GetAuthorityAccount gets the "authority" account. -func (inst *DisableChainSelector) GetAuthorityAccount() *ag_solanago.AccountMeta { - return inst.AccountMetaSlice[2] -} - -// SetSystemProgramAccount sets the "systemProgram" account. -func (inst *DisableChainSelector) SetSystemProgramAccount(systemProgram ag_solanago.PublicKey) *DisableChainSelector { - inst.AccountMetaSlice[3] = ag_solanago.Meta(systemProgram) - return inst -} - -// GetSystemProgramAccount gets the "systemProgram" account. -func (inst *DisableChainSelector) GetSystemProgramAccount() *ag_solanago.AccountMeta { - return inst.AccountMetaSlice[3] -} - -func (inst DisableChainSelector) Build() *Instruction { - return &Instruction{BaseVariant: ag_binary.BaseVariant{ - Impl: inst, - TypeID: Instruction_DisableChainSelector, - }} -} - -// ValidateAndBuild validates the instruction parameters and accounts; -// if there is a validation error, it returns the error. -// Otherwise, it builds and returns the instruction. -func (inst DisableChainSelector) ValidateAndBuild() (*Instruction, error) { - if err := inst.Validate(); err != nil { - return nil, err - } - return inst.Build(), nil -} - -func (inst *DisableChainSelector) Validate() error { - // Check whether all (required) parameters are set: - { - if inst.NewChainSelector == nil { - return errors.New("NewChainSelector parameter is not set") - } - } - - // Check whether all (required) accounts are set: - { - if inst.AccountMetaSlice[0] == nil { - return errors.New("accounts.ChainState is not set") - } - if inst.AccountMetaSlice[1] == nil { - return errors.New("accounts.Config is not set") - } - if inst.AccountMetaSlice[2] == nil { - return errors.New("accounts.Authority is not set") - } - if inst.AccountMetaSlice[3] == nil { - return errors.New("accounts.SystemProgram is not set") - } - } - return nil -} - -func (inst *DisableChainSelector) EncodeToTree(parent ag_treeout.Branches) { - parent.Child(ag_format.Program(ProgramName, ProgramID)). - // - ParentFunc(func(programBranch ag_treeout.Branches) { - programBranch.Child(ag_format.Instruction("DisableChainSelector")). - // - ParentFunc(func(instructionBranch ag_treeout.Branches) { - - // Parameters of the instruction: - instructionBranch.Child("Params[len=1]").ParentFunc(func(paramsBranch ag_treeout.Branches) { - paramsBranch.Child(ag_format.Param("NewChainSelector", *inst.NewChainSelector)) - }) - - // Accounts of the instruction: - instructionBranch.Child("Accounts[len=4]").ParentFunc(func(accountsBranch ag_treeout.Branches) { - accountsBranch.Child(ag_format.Meta(" chainState", inst.AccountMetaSlice[0])) - accountsBranch.Child(ag_format.Meta(" config", inst.AccountMetaSlice[1])) - accountsBranch.Child(ag_format.Meta(" authority", inst.AccountMetaSlice[2])) - accountsBranch.Child(ag_format.Meta("systemProgram", inst.AccountMetaSlice[3])) - }) - }) - }) -} - -func (obj DisableChainSelector) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { - // Serialize `NewChainSelector` param: - err = encoder.Encode(obj.NewChainSelector) - if err != nil { - return err - } - return nil -} -func (obj *DisableChainSelector) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { - // Deserialize `NewChainSelector`: - err = decoder.Decode(&obj.NewChainSelector) - if err != nil { - return err - } - return nil -} - -// NewDisableChainSelectorInstruction declares a new DisableChainSelector instruction with the provided parameters and accounts. -func NewDisableChainSelectorInstruction( - // Parameters: - newChainSelector uint64, - // Accounts: - chainState ag_solanago.PublicKey, - config ag_solanago.PublicKey, - authority ag_solanago.PublicKey, - systemProgram ag_solanago.PublicKey) *DisableChainSelector { - return NewDisableChainSelectorInstructionBuilder(). - SetNewChainSelector(newChainSelector). - SetChainStateAccount(chainState). - SetConfigAccount(config). - SetAuthorityAccount(authority). - SetSystemProgramAccount(systemProgram) -} diff --git a/core/capabilities/ccip/ccipsolana/ccip_router/DisableChainSelector_test.go b/core/capabilities/ccip/ccipsolana/ccip_router/DisableChainSelector_test.go deleted file mode 100644 index 6d4d01c9feb..00000000000 --- a/core/capabilities/ccip/ccipsolana/ccip_router/DisableChainSelector_test.go +++ /dev/null @@ -1,32 +0,0 @@ -// Code generated by https://github.com/gagliardetto/anchor-go. DO NOT EDIT. - -package ccip_router - -import ( - "bytes" - ag_gofuzz "github.com/gagliardetto/gofuzz" - ag_require "github.com/stretchr/testify/require" - "strconv" - "testing" -) - -func TestEncodeDecode_DisableChainSelector(t *testing.T) { - fu := ag_gofuzz.New().NilChance(0) - for i := 0; i < 1; i++ { - t.Run("DisableChainSelector"+strconv.Itoa(i), func(t *testing.T) { - { - params := new(DisableChainSelector) - fu.Fuzz(params) - params.AccountMetaSlice = nil - buf := new(bytes.Buffer) - err := encodeT(*params, buf) - ag_require.NoError(t, err) - got := new(DisableChainSelector) - err = decodeT(got, buf.Bytes()) - got.AccountMetaSlice = nil - ag_require.NoError(t, err) - ag_require.Equal(t, params, got) - } - }) - } -} diff --git a/core/capabilities/ccip/ccipsolana/ccip_router/EnableChainSelector.go b/core/capabilities/ccip/ccipsolana/ccip_router/EnableChainSelector.go deleted file mode 100644 index b3b45bb7f91..00000000000 --- a/core/capabilities/ccip/ccipsolana/ccip_router/EnableChainSelector.go +++ /dev/null @@ -1,184 +0,0 @@ -// Code generated by https://github.com/gagliardetto/anchor-go. DO NOT EDIT. - -package ccip_router - -import ( - "errors" - ag_binary "github.com/gagliardetto/binary" - ag_solanago "github.com/gagliardetto/solana-go" - ag_format "github.com/gagliardetto/solana-go/text/format" - ag_treeout "github.com/gagliardetto/treeout" -) - -// The Admin is the only one able to enable or disable the chain selector -type EnableChainSelector struct { - NewChainSelector *uint64 - - // [0] = [WRITE] chainState - // - // [1] = [] config - // - // [2] = [WRITE, SIGNER] authority - // - // [3] = [] systemProgram - ag_solanago.AccountMetaSlice `bin:"-" borsh_skip:"true"` -} - -// NewEnableChainSelectorInstructionBuilder creates a new `EnableChainSelector` instruction builder. -func NewEnableChainSelectorInstructionBuilder() *EnableChainSelector { - nd := &EnableChainSelector{ - AccountMetaSlice: make(ag_solanago.AccountMetaSlice, 4), - } - return nd -} - -// SetNewChainSelector sets the "newChainSelector" parameter. -func (inst *EnableChainSelector) SetNewChainSelector(newChainSelector uint64) *EnableChainSelector { - inst.NewChainSelector = &newChainSelector - return inst -} - -// SetChainStateAccount sets the "chainState" account. -func (inst *EnableChainSelector) SetChainStateAccount(chainState ag_solanago.PublicKey) *EnableChainSelector { - inst.AccountMetaSlice[0] = ag_solanago.Meta(chainState).WRITE() - return inst -} - -// GetChainStateAccount gets the "chainState" account. -func (inst *EnableChainSelector) GetChainStateAccount() *ag_solanago.AccountMeta { - return inst.AccountMetaSlice[0] -} - -// SetConfigAccount sets the "config" account. -func (inst *EnableChainSelector) SetConfigAccount(config ag_solanago.PublicKey) *EnableChainSelector { - inst.AccountMetaSlice[1] = ag_solanago.Meta(config) - return inst -} - -// GetConfigAccount gets the "config" account. -func (inst *EnableChainSelector) GetConfigAccount() *ag_solanago.AccountMeta { - return inst.AccountMetaSlice[1] -} - -// SetAuthorityAccount sets the "authority" account. -func (inst *EnableChainSelector) SetAuthorityAccount(authority ag_solanago.PublicKey) *EnableChainSelector { - inst.AccountMetaSlice[2] = ag_solanago.Meta(authority).WRITE().SIGNER() - return inst -} - -// GetAuthorityAccount gets the "authority" account. -func (inst *EnableChainSelector) GetAuthorityAccount() *ag_solanago.AccountMeta { - return inst.AccountMetaSlice[2] -} - -// SetSystemProgramAccount sets the "systemProgram" account. -func (inst *EnableChainSelector) SetSystemProgramAccount(systemProgram ag_solanago.PublicKey) *EnableChainSelector { - inst.AccountMetaSlice[3] = ag_solanago.Meta(systemProgram) - return inst -} - -// GetSystemProgramAccount gets the "systemProgram" account. -func (inst *EnableChainSelector) GetSystemProgramAccount() *ag_solanago.AccountMeta { - return inst.AccountMetaSlice[3] -} - -func (inst EnableChainSelector) Build() *Instruction { - return &Instruction{BaseVariant: ag_binary.BaseVariant{ - Impl: inst, - TypeID: Instruction_EnableChainSelector, - }} -} - -// ValidateAndBuild validates the instruction parameters and accounts; -// if there is a validation error, it returns the error. -// Otherwise, it builds and returns the instruction. -func (inst EnableChainSelector) ValidateAndBuild() (*Instruction, error) { - if err := inst.Validate(); err != nil { - return nil, err - } - return inst.Build(), nil -} - -func (inst *EnableChainSelector) Validate() error { - // Check whether all (required) parameters are set: - { - if inst.NewChainSelector == nil { - return errors.New("NewChainSelector parameter is not set") - } - } - - // Check whether all (required) accounts are set: - { - if inst.AccountMetaSlice[0] == nil { - return errors.New("accounts.ChainState is not set") - } - if inst.AccountMetaSlice[1] == nil { - return errors.New("accounts.Config is not set") - } - if inst.AccountMetaSlice[2] == nil { - return errors.New("accounts.Authority is not set") - } - if inst.AccountMetaSlice[3] == nil { - return errors.New("accounts.SystemProgram is not set") - } - } - return nil -} - -func (inst *EnableChainSelector) EncodeToTree(parent ag_treeout.Branches) { - parent.Child(ag_format.Program(ProgramName, ProgramID)). - // - ParentFunc(func(programBranch ag_treeout.Branches) { - programBranch.Child(ag_format.Instruction("EnableChainSelector")). - // - ParentFunc(func(instructionBranch ag_treeout.Branches) { - - // Parameters of the instruction: - instructionBranch.Child("Params[len=1]").ParentFunc(func(paramsBranch ag_treeout.Branches) { - paramsBranch.Child(ag_format.Param("NewChainSelector", *inst.NewChainSelector)) - }) - - // Accounts of the instruction: - instructionBranch.Child("Accounts[len=4]").ParentFunc(func(accountsBranch ag_treeout.Branches) { - accountsBranch.Child(ag_format.Meta(" chainState", inst.AccountMetaSlice[0])) - accountsBranch.Child(ag_format.Meta(" config", inst.AccountMetaSlice[1])) - accountsBranch.Child(ag_format.Meta(" authority", inst.AccountMetaSlice[2])) - accountsBranch.Child(ag_format.Meta("systemProgram", inst.AccountMetaSlice[3])) - }) - }) - }) -} - -func (obj EnableChainSelector) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { - // Serialize `NewChainSelector` param: - err = encoder.Encode(obj.NewChainSelector) - if err != nil { - return err - } - return nil -} -func (obj *EnableChainSelector) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { - // Deserialize `NewChainSelector`: - err = decoder.Decode(&obj.NewChainSelector) - if err != nil { - return err - } - return nil -} - -// NewEnableChainSelectorInstruction declares a new EnableChainSelector instruction with the provided parameters and accounts. -func NewEnableChainSelectorInstruction( - // Parameters: - newChainSelector uint64, - // Accounts: - chainState ag_solanago.PublicKey, - config ag_solanago.PublicKey, - authority ag_solanago.PublicKey, - systemProgram ag_solanago.PublicKey) *EnableChainSelector { - return NewEnableChainSelectorInstructionBuilder(). - SetNewChainSelector(newChainSelector). - SetChainStateAccount(chainState). - SetConfigAccount(config). - SetAuthorityAccount(authority). - SetSystemProgramAccount(systemProgram) -} diff --git a/core/capabilities/ccip/ccipsolana/ccip_router/EnableChainSelector_test.go b/core/capabilities/ccip/ccipsolana/ccip_router/EnableChainSelector_test.go deleted file mode 100644 index f14c09f534a..00000000000 --- a/core/capabilities/ccip/ccipsolana/ccip_router/EnableChainSelector_test.go +++ /dev/null @@ -1,32 +0,0 @@ -// Code generated by https://github.com/gagliardetto/anchor-go. DO NOT EDIT. - -package ccip_router - -import ( - "bytes" - ag_gofuzz "github.com/gagliardetto/gofuzz" - ag_require "github.com/stretchr/testify/require" - "strconv" - "testing" -) - -func TestEncodeDecode_EnableChainSelector(t *testing.T) { - fu := ag_gofuzz.New().NilChance(0) - for i := 0; i < 1; i++ { - t.Run("EnableChainSelector"+strconv.Itoa(i), func(t *testing.T) { - { - params := new(EnableChainSelector) - fu.Fuzz(params) - params.AccountMetaSlice = nil - buf := new(bytes.Buffer) - err := encodeT(*params, buf) - ag_require.NoError(t, err) - got := new(EnableChainSelector) - err = decodeT(got, buf.Bytes()) - got.AccountMetaSlice = nil - ag_require.NoError(t, err) - ag_require.Equal(t, params, got) - } - }) - } -} diff --git a/core/capabilities/ccip/ccipsolana/ccip_router/Execute.go b/core/capabilities/ccip/ccipsolana/ccip_router/Execute.go deleted file mode 100644 index 5ed3628dd1f..00000000000 --- a/core/capabilities/ccip/ccipsolana/ccip_router/Execute.go +++ /dev/null @@ -1,293 +0,0 @@ -// Code generated by https://github.com/gagliardetto/anchor-go. DO NOT EDIT. - -package ccip_router - -import ( - "errors" - ag_binary "github.com/gagliardetto/binary" - ag_solanago "github.com/gagliardetto/solana-go" - ag_format "github.com/gagliardetto/solana-go/text/format" - ag_treeout "github.com/gagliardetto/treeout" -) - -// OFF RAMP FLOW -// -// The method name needs to be execute with Anchor encoding. -// -// This function is called by the OffChain when executing one Report to the Solana Router. -// In this Flow only one message is sent, the Execution Report. This is different as EVM does, -// this is because there is no try/catch mechanism to allow batch execution. -// This message validates that the Merkle Tree Proof of the given message is correct and is stored in the Commit Report Account. -// The message must be untouched to be executed. -// This message emits the event ExecutionStateChanged with the new state of the message. -// Finally, executes the CPI instruction to the receiver program in the ccip_receive message. -type Execute struct { - ExecutionReport *ExecutionReportSingleChain - ReportContext *[3][32]uint8 - - // [0] = [] config - // - // [1] = [] chainState - // - // [2] = [WRITE] commitReport - // - // [3] = [] externalExecutionConfig - // - // [4] = [WRITE, SIGNER] authority - // - // [5] = [] systemProgram - // - // [6] = [] sysvarInstructions - // - // [7] = [] tokenPoolsSigner - ag_solanago.AccountMetaSlice `bin:"-" borsh_skip:"true"` -} - -// NewExecuteInstructionBuilder creates a new `Execute` instruction builder. -func NewExecuteInstructionBuilder() *Execute { - nd := &Execute{ - AccountMetaSlice: make(ag_solanago.AccountMetaSlice, 8), - } - return nd -} - -// SetExecutionReport sets the "executionReport" parameter. -func (inst *Execute) SetExecutionReport(executionReport ExecutionReportSingleChain) *Execute { - inst.ExecutionReport = &executionReport - return inst -} - -// SetReportContext sets the "reportContext" parameter. -func (inst *Execute) SetReportContext(reportContext [3][32]uint8) *Execute { - inst.ReportContext = &reportContext - return inst -} - -// SetConfigAccount sets the "config" account. -func (inst *Execute) SetConfigAccount(config ag_solanago.PublicKey) *Execute { - inst.AccountMetaSlice[0] = ag_solanago.Meta(config) - return inst -} - -// GetConfigAccount gets the "config" account. -func (inst *Execute) GetConfigAccount() *ag_solanago.AccountMeta { - return inst.AccountMetaSlice[0] -} - -// SetChainStateAccount sets the "chainState" account. -func (inst *Execute) SetChainStateAccount(chainState ag_solanago.PublicKey) *Execute { - inst.AccountMetaSlice[1] = ag_solanago.Meta(chainState) - return inst -} - -// GetChainStateAccount gets the "chainState" account. -func (inst *Execute) GetChainStateAccount() *ag_solanago.AccountMeta { - return inst.AccountMetaSlice[1] -} - -// SetCommitReportAccount sets the "commitReport" account. -func (inst *Execute) SetCommitReportAccount(commitReport ag_solanago.PublicKey) *Execute { - inst.AccountMetaSlice[2] = ag_solanago.Meta(commitReport).WRITE() - return inst -} - -// GetCommitReportAccount gets the "commitReport" account. -func (inst *Execute) GetCommitReportAccount() *ag_solanago.AccountMeta { - return inst.AccountMetaSlice[2] -} - -// SetExternalExecutionConfigAccount sets the "externalExecutionConfig" account. -func (inst *Execute) SetExternalExecutionConfigAccount(externalExecutionConfig ag_solanago.PublicKey) *Execute { - inst.AccountMetaSlice[3] = ag_solanago.Meta(externalExecutionConfig) - return inst -} - -// GetExternalExecutionConfigAccount gets the "externalExecutionConfig" account. -func (inst *Execute) GetExternalExecutionConfigAccount() *ag_solanago.AccountMeta { - return inst.AccountMetaSlice[3] -} - -// SetAuthorityAccount sets the "authority" account. -func (inst *Execute) SetAuthorityAccount(authority ag_solanago.PublicKey) *Execute { - inst.AccountMetaSlice[4] = ag_solanago.Meta(authority).WRITE().SIGNER() - return inst -} - -// GetAuthorityAccount gets the "authority" account. -func (inst *Execute) GetAuthorityAccount() *ag_solanago.AccountMeta { - return inst.AccountMetaSlice[4] -} - -// SetSystemProgramAccount sets the "systemProgram" account. -func (inst *Execute) SetSystemProgramAccount(systemProgram ag_solanago.PublicKey) *Execute { - inst.AccountMetaSlice[5] = ag_solanago.Meta(systemProgram) - return inst -} - -// GetSystemProgramAccount gets the "systemProgram" account. -func (inst *Execute) GetSystemProgramAccount() *ag_solanago.AccountMeta { - return inst.AccountMetaSlice[5] -} - -// SetSysvarInstructionsAccount sets the "sysvarInstructions" account. -func (inst *Execute) SetSysvarInstructionsAccount(sysvarInstructions ag_solanago.PublicKey) *Execute { - inst.AccountMetaSlice[6] = ag_solanago.Meta(sysvarInstructions) - return inst -} - -// GetSysvarInstructionsAccount gets the "sysvarInstructions" account. -func (inst *Execute) GetSysvarInstructionsAccount() *ag_solanago.AccountMeta { - return inst.AccountMetaSlice[6] -} - -// SetTokenPoolsSignerAccount sets the "tokenPoolsSigner" account. -func (inst *Execute) SetTokenPoolsSignerAccount(tokenPoolsSigner ag_solanago.PublicKey) *Execute { - inst.AccountMetaSlice[7] = ag_solanago.Meta(tokenPoolsSigner) - return inst -} - -// GetTokenPoolsSignerAccount gets the "tokenPoolsSigner" account. -func (inst *Execute) GetTokenPoolsSignerAccount() *ag_solanago.AccountMeta { - return inst.AccountMetaSlice[7] -} - -func (inst Execute) Build() *Instruction { - return &Instruction{BaseVariant: ag_binary.BaseVariant{ - Impl: inst, - TypeID: Instruction_Execute, - }} -} - -// ValidateAndBuild validates the instruction parameters and accounts; -// if there is a validation error, it returns the error. -// Otherwise, it builds and returns the instruction. -func (inst Execute) ValidateAndBuild() (*Instruction, error) { - if err := inst.Validate(); err != nil { - return nil, err - } - return inst.Build(), nil -} - -func (inst *Execute) Validate() error { - // Check whether all (required) parameters are set: - { - if inst.ExecutionReport == nil { - return errors.New("ExecutionReport parameter is not set") - } - if inst.ReportContext == nil { - return errors.New("ReportContext parameter is not set") - } - } - - // Check whether all (required) accounts are set: - { - if inst.AccountMetaSlice[0] == nil { - return errors.New("accounts.Config is not set") - } - if inst.AccountMetaSlice[1] == nil { - return errors.New("accounts.ChainState is not set") - } - if inst.AccountMetaSlice[2] == nil { - return errors.New("accounts.CommitReport is not set") - } - if inst.AccountMetaSlice[3] == nil { - return errors.New("accounts.ExternalExecutionConfig is not set") - } - if inst.AccountMetaSlice[4] == nil { - return errors.New("accounts.Authority is not set") - } - if inst.AccountMetaSlice[5] == nil { - return errors.New("accounts.SystemProgram is not set") - } - if inst.AccountMetaSlice[6] == nil { - return errors.New("accounts.SysvarInstructions is not set") - } - if inst.AccountMetaSlice[7] == nil { - return errors.New("accounts.TokenPoolsSigner is not set") - } - } - return nil -} - -func (inst *Execute) EncodeToTree(parent ag_treeout.Branches) { - parent.Child(ag_format.Program(ProgramName, ProgramID)). - // - ParentFunc(func(programBranch ag_treeout.Branches) { - programBranch.Child(ag_format.Instruction("Execute")). - // - ParentFunc(func(instructionBranch ag_treeout.Branches) { - - // Parameters of the instruction: - instructionBranch.Child("Params[len=2]").ParentFunc(func(paramsBranch ag_treeout.Branches) { - paramsBranch.Child(ag_format.Param("ExecutionReport", *inst.ExecutionReport)) - paramsBranch.Child(ag_format.Param(" ReportContext", *inst.ReportContext)) - }) - - // Accounts of the instruction: - instructionBranch.Child("Accounts[len=8]").ParentFunc(func(accountsBranch ag_treeout.Branches) { - accountsBranch.Child(ag_format.Meta(" config", inst.AccountMetaSlice[0])) - accountsBranch.Child(ag_format.Meta(" chainState", inst.AccountMetaSlice[1])) - accountsBranch.Child(ag_format.Meta(" commitReport", inst.AccountMetaSlice[2])) - accountsBranch.Child(ag_format.Meta("externalExecutionConfig", inst.AccountMetaSlice[3])) - accountsBranch.Child(ag_format.Meta(" authority", inst.AccountMetaSlice[4])) - accountsBranch.Child(ag_format.Meta(" systemProgram", inst.AccountMetaSlice[5])) - accountsBranch.Child(ag_format.Meta(" sysvarInstructions", inst.AccountMetaSlice[6])) - accountsBranch.Child(ag_format.Meta(" tokenPoolsSigner", inst.AccountMetaSlice[7])) - }) - }) - }) -} - -func (obj Execute) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { - // Serialize `ExecutionReport` param: - err = encoder.Encode(obj.ExecutionReport) - if err != nil { - return err - } - // Serialize `ReportContext` param: - err = encoder.Encode(obj.ReportContext) - if err != nil { - return err - } - return nil -} -func (obj *Execute) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { - // Deserialize `ExecutionReport`: - err = decoder.Decode(&obj.ExecutionReport) - if err != nil { - return err - } - // Deserialize `ReportContext`: - err = decoder.Decode(&obj.ReportContext) - if err != nil { - return err - } - return nil -} - -// NewExecuteInstruction declares a new Execute instruction with the provided parameters and accounts. -func NewExecuteInstruction( - // Parameters: - executionReport ExecutionReportSingleChain, - reportContext [3][32]uint8, - // Accounts: - config ag_solanago.PublicKey, - chainState ag_solanago.PublicKey, - commitReport ag_solanago.PublicKey, - externalExecutionConfig ag_solanago.PublicKey, - authority ag_solanago.PublicKey, - systemProgram ag_solanago.PublicKey, - sysvarInstructions ag_solanago.PublicKey, - tokenPoolsSigner ag_solanago.PublicKey) *Execute { - return NewExecuteInstructionBuilder(). - SetExecutionReport(executionReport). - SetReportContext(reportContext). - SetConfigAccount(config). - SetChainStateAccount(chainState). - SetCommitReportAccount(commitReport). - SetExternalExecutionConfigAccount(externalExecutionConfig). - SetAuthorityAccount(authority). - SetSystemProgramAccount(systemProgram). - SetSysvarInstructionsAccount(sysvarInstructions). - SetTokenPoolsSignerAccount(tokenPoolsSigner) -} diff --git a/core/capabilities/ccip/ccipsolana/ccip_router/Execute_test.go b/core/capabilities/ccip/ccipsolana/ccip_router/Execute_test.go deleted file mode 100644 index 5c0f4d7b7ff..00000000000 --- a/core/capabilities/ccip/ccipsolana/ccip_router/Execute_test.go +++ /dev/null @@ -1,32 +0,0 @@ -// Code generated by https://github.com/gagliardetto/anchor-go. DO NOT EDIT. - -package ccip_router - -import ( - "bytes" - ag_gofuzz "github.com/gagliardetto/gofuzz" - ag_require "github.com/stretchr/testify/require" - "strconv" - "testing" -) - -func TestEncodeDecode_Execute(t *testing.T) { - fu := ag_gofuzz.New().NilChance(0) - for i := 0; i < 1; i++ { - t.Run("Execute"+strconv.Itoa(i), func(t *testing.T) { - { - params := new(Execute) - fu.Fuzz(params) - params.AccountMetaSlice = nil - buf := new(bytes.Buffer) - err := encodeT(*params, buf) - ag_require.NoError(t, err) - got := new(Execute) - err = decodeT(got, buf.Bytes()) - got.AccountMetaSlice = nil - ag_require.NoError(t, err) - ag_require.Equal(t, params, got) - } - }) - } -} diff --git a/core/capabilities/ccip/ccipsolana/ccip_router/Initialize.go b/core/capabilities/ccip/ccipsolana/ccip_router/Initialize.go deleted file mode 100644 index ed65234f3e7..00000000000 --- a/core/capabilities/ccip/ccipsolana/ccip_router/Initialize.go +++ /dev/null @@ -1,310 +0,0 @@ -// Code generated by https://github.com/gagliardetto/anchor-go. DO NOT EDIT. - -package ccip_router - -import ( - "errors" - ag_binary "github.com/gagliardetto/binary" - ag_solanago "github.com/gagliardetto/solana-go" - ag_format "github.com/gagliardetto/solana-go/text/format" - ag_treeout "github.com/gagliardetto/treeout" -) - -// The initialization is responsibility of Admin, nothing more than calling this method should be done first. -type Initialize struct { - SolanaChainSelector *uint64 - DefaultGasLimit *ag_binary.Uint128 - DefaultAllowOutOfOrderExecution *bool - EnableExecutionAfter *int64 - - // [0] = [WRITE] config - // - // [1] = [WRITE, SIGNER] authority - // - // [2] = [] systemProgram - // - // [3] = [] program - // - // [4] = [] programData - // - // [5] = [WRITE] externalExecutionConfig - // - // [6] = [WRITE] tokenPoolsSigner - ag_solanago.AccountMetaSlice `bin:"-" borsh_skip:"true"` -} - -// NewInitializeInstructionBuilder creates a new `Initialize` instruction builder. -func NewInitializeInstructionBuilder() *Initialize { - nd := &Initialize{ - AccountMetaSlice: make(ag_solanago.AccountMetaSlice, 7), - } - return nd -} - -// SetSolanaChainSelector sets the "solanaChainSelector" parameter. -func (inst *Initialize) SetSolanaChainSelector(solanaChainSelector uint64) *Initialize { - inst.SolanaChainSelector = &solanaChainSelector - return inst -} - -// SetDefaultGasLimit sets the "defaultGasLimit" parameter. -func (inst *Initialize) SetDefaultGasLimit(defaultGasLimit ag_binary.Uint128) *Initialize { - inst.DefaultGasLimit = &defaultGasLimit - return inst -} - -// SetDefaultAllowOutOfOrderExecution sets the "defaultAllowOutOfOrderExecution" parameter. -func (inst *Initialize) SetDefaultAllowOutOfOrderExecution(defaultAllowOutOfOrderExecution bool) *Initialize { - inst.DefaultAllowOutOfOrderExecution = &defaultAllowOutOfOrderExecution - return inst -} - -// SetEnableExecutionAfter sets the "enableExecutionAfter" parameter. -func (inst *Initialize) SetEnableExecutionAfter(enableExecutionAfter int64) *Initialize { - inst.EnableExecutionAfter = &enableExecutionAfter - return inst -} - -// SetConfigAccount sets the "config" account. -func (inst *Initialize) SetConfigAccount(config ag_solanago.PublicKey) *Initialize { - inst.AccountMetaSlice[0] = ag_solanago.Meta(config).WRITE() - return inst -} - -// GetConfigAccount gets the "config" account. -func (inst *Initialize) GetConfigAccount() *ag_solanago.AccountMeta { - return inst.AccountMetaSlice[0] -} - -// SetAuthorityAccount sets the "authority" account. -func (inst *Initialize) SetAuthorityAccount(authority ag_solanago.PublicKey) *Initialize { - inst.AccountMetaSlice[1] = ag_solanago.Meta(authority).WRITE().SIGNER() - return inst -} - -// GetAuthorityAccount gets the "authority" account. -func (inst *Initialize) GetAuthorityAccount() *ag_solanago.AccountMeta { - return inst.AccountMetaSlice[1] -} - -// SetSystemProgramAccount sets the "systemProgram" account. -func (inst *Initialize) SetSystemProgramAccount(systemProgram ag_solanago.PublicKey) *Initialize { - inst.AccountMetaSlice[2] = ag_solanago.Meta(systemProgram) - return inst -} - -// GetSystemProgramAccount gets the "systemProgram" account. -func (inst *Initialize) GetSystemProgramAccount() *ag_solanago.AccountMeta { - return inst.AccountMetaSlice[2] -} - -// SetProgramAccount sets the "program" account. -func (inst *Initialize) SetProgramAccount(program ag_solanago.PublicKey) *Initialize { - inst.AccountMetaSlice[3] = ag_solanago.Meta(program) - return inst -} - -// GetProgramAccount gets the "program" account. -func (inst *Initialize) GetProgramAccount() *ag_solanago.AccountMeta { - return inst.AccountMetaSlice[3] -} - -// SetProgramDataAccount sets the "programData" account. -func (inst *Initialize) SetProgramDataAccount(programData ag_solanago.PublicKey) *Initialize { - inst.AccountMetaSlice[4] = ag_solanago.Meta(programData) - return inst -} - -// GetProgramDataAccount gets the "programData" account. -func (inst *Initialize) GetProgramDataAccount() *ag_solanago.AccountMeta { - return inst.AccountMetaSlice[4] -} - -// SetExternalExecutionConfigAccount sets the "externalExecutionConfig" account. -func (inst *Initialize) SetExternalExecutionConfigAccount(externalExecutionConfig ag_solanago.PublicKey) *Initialize { - inst.AccountMetaSlice[5] = ag_solanago.Meta(externalExecutionConfig).WRITE() - return inst -} - -// GetExternalExecutionConfigAccount gets the "externalExecutionConfig" account. -func (inst *Initialize) GetExternalExecutionConfigAccount() *ag_solanago.AccountMeta { - return inst.AccountMetaSlice[5] -} - -// SetTokenPoolsSignerAccount sets the "tokenPoolsSigner" account. -func (inst *Initialize) SetTokenPoolsSignerAccount(tokenPoolsSigner ag_solanago.PublicKey) *Initialize { - inst.AccountMetaSlice[6] = ag_solanago.Meta(tokenPoolsSigner).WRITE() - return inst -} - -// GetTokenPoolsSignerAccount gets the "tokenPoolsSigner" account. -func (inst *Initialize) GetTokenPoolsSignerAccount() *ag_solanago.AccountMeta { - return inst.AccountMetaSlice[6] -} - -func (inst Initialize) Build() *Instruction { - return &Instruction{BaseVariant: ag_binary.BaseVariant{ - Impl: inst, - TypeID: Instruction_Initialize, - }} -} - -// ValidateAndBuild validates the instruction parameters and accounts; -// if there is a validation error, it returns the error. -// Otherwise, it builds and returns the instruction. -func (inst Initialize) ValidateAndBuild() (*Instruction, error) { - if err := inst.Validate(); err != nil { - return nil, err - } - return inst.Build(), nil -} - -func (inst *Initialize) Validate() error { - // Check whether all (required) parameters are set: - { - if inst.SolanaChainSelector == nil { - return errors.New("SolanaChainSelector parameter is not set") - } - if inst.DefaultGasLimit == nil { - return errors.New("DefaultGasLimit parameter is not set") - } - if inst.DefaultAllowOutOfOrderExecution == nil { - return errors.New("DefaultAllowOutOfOrderExecution parameter is not set") - } - if inst.EnableExecutionAfter == nil { - return errors.New("EnableExecutionAfter parameter is not set") - } - } - - // Check whether all (required) accounts are set: - { - if inst.AccountMetaSlice[0] == nil { - return errors.New("accounts.Config is not set") - } - if inst.AccountMetaSlice[1] == nil { - return errors.New("accounts.Authority is not set") - } - if inst.AccountMetaSlice[2] == nil { - return errors.New("accounts.SystemProgram is not set") - } - if inst.AccountMetaSlice[3] == nil { - return errors.New("accounts.Program is not set") - } - if inst.AccountMetaSlice[4] == nil { - return errors.New("accounts.ProgramData is not set") - } - if inst.AccountMetaSlice[5] == nil { - return errors.New("accounts.ExternalExecutionConfig is not set") - } - if inst.AccountMetaSlice[6] == nil { - return errors.New("accounts.TokenPoolsSigner is not set") - } - } - return nil -} - -func (inst *Initialize) EncodeToTree(parent ag_treeout.Branches) { - parent.Child(ag_format.Program(ProgramName, ProgramID)). - // - ParentFunc(func(programBranch ag_treeout.Branches) { - programBranch.Child(ag_format.Instruction("Initialize")). - // - ParentFunc(func(instructionBranch ag_treeout.Branches) { - - // Parameters of the instruction: - instructionBranch.Child("Params[len=4]").ParentFunc(func(paramsBranch ag_treeout.Branches) { - paramsBranch.Child(ag_format.Param(" SolanaChainSelector", *inst.SolanaChainSelector)) - paramsBranch.Child(ag_format.Param(" DefaultGasLimit", *inst.DefaultGasLimit)) - paramsBranch.Child(ag_format.Param("DefaultAllowOutOfOrderExecution", *inst.DefaultAllowOutOfOrderExecution)) - paramsBranch.Child(ag_format.Param(" EnableExecutionAfter", *inst.EnableExecutionAfter)) - }) - - // Accounts of the instruction: - instructionBranch.Child("Accounts[len=7]").ParentFunc(func(accountsBranch ag_treeout.Branches) { - accountsBranch.Child(ag_format.Meta(" config", inst.AccountMetaSlice[0])) - accountsBranch.Child(ag_format.Meta(" authority", inst.AccountMetaSlice[1])) - accountsBranch.Child(ag_format.Meta(" systemProgram", inst.AccountMetaSlice[2])) - accountsBranch.Child(ag_format.Meta(" program", inst.AccountMetaSlice[3])) - accountsBranch.Child(ag_format.Meta(" programData", inst.AccountMetaSlice[4])) - accountsBranch.Child(ag_format.Meta("externalExecutionConfig", inst.AccountMetaSlice[5])) - accountsBranch.Child(ag_format.Meta(" tokenPoolsSigner", inst.AccountMetaSlice[6])) - }) - }) - }) -} - -func (obj Initialize) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { - // Serialize `SolanaChainSelector` param: - err = encoder.Encode(obj.SolanaChainSelector) - if err != nil { - return err - } - // Serialize `DefaultGasLimit` param: - err = encoder.Encode(obj.DefaultGasLimit) - if err != nil { - return err - } - // Serialize `DefaultAllowOutOfOrderExecution` param: - err = encoder.Encode(obj.DefaultAllowOutOfOrderExecution) - if err != nil { - return err - } - // Serialize `EnableExecutionAfter` param: - err = encoder.Encode(obj.EnableExecutionAfter) - if err != nil { - return err - } - return nil -} -func (obj *Initialize) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { - // Deserialize `SolanaChainSelector`: - err = decoder.Decode(&obj.SolanaChainSelector) - if err != nil { - return err - } - // Deserialize `DefaultGasLimit`: - err = decoder.Decode(&obj.DefaultGasLimit) - if err != nil { - return err - } - // Deserialize `DefaultAllowOutOfOrderExecution`: - err = decoder.Decode(&obj.DefaultAllowOutOfOrderExecution) - if err != nil { - return err - } - // Deserialize `EnableExecutionAfter`: - err = decoder.Decode(&obj.EnableExecutionAfter) - if err != nil { - return err - } - return nil -} - -// NewInitializeInstruction declares a new Initialize instruction with the provided parameters and accounts. -func NewInitializeInstruction( - // Parameters: - solanaChainSelector uint64, - defaultGasLimit ag_binary.Uint128, - defaultAllowOutOfOrderExecution bool, - enableExecutionAfter int64, - // Accounts: - config ag_solanago.PublicKey, - authority ag_solanago.PublicKey, - systemProgram ag_solanago.PublicKey, - program ag_solanago.PublicKey, - programData ag_solanago.PublicKey, - externalExecutionConfig ag_solanago.PublicKey, - tokenPoolsSigner ag_solanago.PublicKey) *Initialize { - return NewInitializeInstructionBuilder(). - SetSolanaChainSelector(solanaChainSelector). - SetDefaultGasLimit(defaultGasLimit). - SetDefaultAllowOutOfOrderExecution(defaultAllowOutOfOrderExecution). - SetEnableExecutionAfter(enableExecutionAfter). - SetConfigAccount(config). - SetAuthorityAccount(authority). - SetSystemProgramAccount(systemProgram). - SetProgramAccount(program). - SetProgramDataAccount(programData). - SetExternalExecutionConfigAccount(externalExecutionConfig). - SetTokenPoolsSignerAccount(tokenPoolsSigner) -} diff --git a/core/capabilities/ccip/ccipsolana/ccip_router/Initialize_test.go b/core/capabilities/ccip/ccipsolana/ccip_router/Initialize_test.go deleted file mode 100644 index 51eed3384b8..00000000000 --- a/core/capabilities/ccip/ccipsolana/ccip_router/Initialize_test.go +++ /dev/null @@ -1,32 +0,0 @@ -// Code generated by https://github.com/gagliardetto/anchor-go. DO NOT EDIT. - -package ccip_router - -import ( - "bytes" - ag_gofuzz "github.com/gagliardetto/gofuzz" - ag_require "github.com/stretchr/testify/require" - "strconv" - "testing" -) - -func TestEncodeDecode_Initialize(t *testing.T) { - fu := ag_gofuzz.New().NilChance(0) - for i := 0; i < 1; i++ { - t.Run("Initialize"+strconv.Itoa(i), func(t *testing.T) { - { - params := new(Initialize) - fu.Fuzz(params) - params.AccountMetaSlice = nil - buf := new(bytes.Buffer) - err := encodeT(*params, buf) - ag_require.NoError(t, err) - got := new(Initialize) - err = decodeT(got, buf.Bytes()) - got.AccountMetaSlice = nil - ag_require.NoError(t, err) - ag_require.Equal(t, params, got) - } - }) - } -} diff --git a/core/capabilities/ccip/ccipsolana/ccip_router/ManuallyExecute.go b/core/capabilities/ccip/ccipsolana/ccip_router/ManuallyExecute.go deleted file mode 100644 index 7ec00306a8f..00000000000 --- a/core/capabilities/ccip/ccipsolana/ccip_router/ManuallyExecute.go +++ /dev/null @@ -1,261 +0,0 @@ -// Code generated by https://github.com/gagliardetto/anchor-go. DO NOT EDIT. - -package ccip_router - -import ( - "errors" - ag_binary "github.com/gagliardetto/binary" - ag_solanago "github.com/gagliardetto/solana-go" - ag_format "github.com/gagliardetto/solana-go/text/format" - ag_treeout "github.com/gagliardetto/treeout" -) - -// When a message is not being executed, then the user can trigger the execution manually. -// No verification over the transmitter, but the message needs to be in some commit report. -type ManuallyExecute struct { - ExecutionReport *ExecutionReportSingleChain - - // [0] = [] config - // - // [1] = [] chainState - // - // [2] = [WRITE] commitReport - // - // [3] = [] externalExecutionConfig - // - // [4] = [WRITE, SIGNER] authority - // - // [5] = [] systemProgram - // - // [6] = [] sysvarInstructions - // - // [7] = [] tokenPoolsSigner - ag_solanago.AccountMetaSlice `bin:"-" borsh_skip:"true"` -} - -// NewManuallyExecuteInstructionBuilder creates a new `ManuallyExecute` instruction builder. -func NewManuallyExecuteInstructionBuilder() *ManuallyExecute { - nd := &ManuallyExecute{ - AccountMetaSlice: make(ag_solanago.AccountMetaSlice, 8), - } - return nd -} - -// SetExecutionReport sets the "executionReport" parameter. -func (inst *ManuallyExecute) SetExecutionReport(executionReport ExecutionReportSingleChain) *ManuallyExecute { - inst.ExecutionReport = &executionReport - return inst -} - -// SetConfigAccount sets the "config" account. -func (inst *ManuallyExecute) SetConfigAccount(config ag_solanago.PublicKey) *ManuallyExecute { - inst.AccountMetaSlice[0] = ag_solanago.Meta(config) - return inst -} - -// GetConfigAccount gets the "config" account. -func (inst *ManuallyExecute) GetConfigAccount() *ag_solanago.AccountMeta { - return inst.AccountMetaSlice[0] -} - -// SetChainStateAccount sets the "chainState" account. -func (inst *ManuallyExecute) SetChainStateAccount(chainState ag_solanago.PublicKey) *ManuallyExecute { - inst.AccountMetaSlice[1] = ag_solanago.Meta(chainState) - return inst -} - -// GetChainStateAccount gets the "chainState" account. -func (inst *ManuallyExecute) GetChainStateAccount() *ag_solanago.AccountMeta { - return inst.AccountMetaSlice[1] -} - -// SetCommitReportAccount sets the "commitReport" account. -func (inst *ManuallyExecute) SetCommitReportAccount(commitReport ag_solanago.PublicKey) *ManuallyExecute { - inst.AccountMetaSlice[2] = ag_solanago.Meta(commitReport).WRITE() - return inst -} - -// GetCommitReportAccount gets the "commitReport" account. -func (inst *ManuallyExecute) GetCommitReportAccount() *ag_solanago.AccountMeta { - return inst.AccountMetaSlice[2] -} - -// SetExternalExecutionConfigAccount sets the "externalExecutionConfig" account. -func (inst *ManuallyExecute) SetExternalExecutionConfigAccount(externalExecutionConfig ag_solanago.PublicKey) *ManuallyExecute { - inst.AccountMetaSlice[3] = ag_solanago.Meta(externalExecutionConfig) - return inst -} - -// GetExternalExecutionConfigAccount gets the "externalExecutionConfig" account. -func (inst *ManuallyExecute) GetExternalExecutionConfigAccount() *ag_solanago.AccountMeta { - return inst.AccountMetaSlice[3] -} - -// SetAuthorityAccount sets the "authority" account. -func (inst *ManuallyExecute) SetAuthorityAccount(authority ag_solanago.PublicKey) *ManuallyExecute { - inst.AccountMetaSlice[4] = ag_solanago.Meta(authority).WRITE().SIGNER() - return inst -} - -// GetAuthorityAccount gets the "authority" account. -func (inst *ManuallyExecute) GetAuthorityAccount() *ag_solanago.AccountMeta { - return inst.AccountMetaSlice[4] -} - -// SetSystemProgramAccount sets the "systemProgram" account. -func (inst *ManuallyExecute) SetSystemProgramAccount(systemProgram ag_solanago.PublicKey) *ManuallyExecute { - inst.AccountMetaSlice[5] = ag_solanago.Meta(systemProgram) - return inst -} - -// GetSystemProgramAccount gets the "systemProgram" account. -func (inst *ManuallyExecute) GetSystemProgramAccount() *ag_solanago.AccountMeta { - return inst.AccountMetaSlice[5] -} - -// SetSysvarInstructionsAccount sets the "sysvarInstructions" account. -func (inst *ManuallyExecute) SetSysvarInstructionsAccount(sysvarInstructions ag_solanago.PublicKey) *ManuallyExecute { - inst.AccountMetaSlice[6] = ag_solanago.Meta(sysvarInstructions) - return inst -} - -// GetSysvarInstructionsAccount gets the "sysvarInstructions" account. -func (inst *ManuallyExecute) GetSysvarInstructionsAccount() *ag_solanago.AccountMeta { - return inst.AccountMetaSlice[6] -} - -// SetTokenPoolsSignerAccount sets the "tokenPoolsSigner" account. -func (inst *ManuallyExecute) SetTokenPoolsSignerAccount(tokenPoolsSigner ag_solanago.PublicKey) *ManuallyExecute { - inst.AccountMetaSlice[7] = ag_solanago.Meta(tokenPoolsSigner) - return inst -} - -// GetTokenPoolsSignerAccount gets the "tokenPoolsSigner" account. -func (inst *ManuallyExecute) GetTokenPoolsSignerAccount() *ag_solanago.AccountMeta { - return inst.AccountMetaSlice[7] -} - -func (inst ManuallyExecute) Build() *Instruction { - return &Instruction{BaseVariant: ag_binary.BaseVariant{ - Impl: inst, - TypeID: Instruction_ManuallyExecute, - }} -} - -// ValidateAndBuild validates the instruction parameters and accounts; -// if there is a validation error, it returns the error. -// Otherwise, it builds and returns the instruction. -func (inst ManuallyExecute) ValidateAndBuild() (*Instruction, error) { - if err := inst.Validate(); err != nil { - return nil, err - } - return inst.Build(), nil -} - -func (inst *ManuallyExecute) Validate() error { - // Check whether all (required) parameters are set: - { - if inst.ExecutionReport == nil { - return errors.New("ExecutionReport parameter is not set") - } - } - - // Check whether all (required) accounts are set: - { - if inst.AccountMetaSlice[0] == nil { - return errors.New("accounts.Config is not set") - } - if inst.AccountMetaSlice[1] == nil { - return errors.New("accounts.ChainState is not set") - } - if inst.AccountMetaSlice[2] == nil { - return errors.New("accounts.CommitReport is not set") - } - if inst.AccountMetaSlice[3] == nil { - return errors.New("accounts.ExternalExecutionConfig is not set") - } - if inst.AccountMetaSlice[4] == nil { - return errors.New("accounts.Authority is not set") - } - if inst.AccountMetaSlice[5] == nil { - return errors.New("accounts.SystemProgram is not set") - } - if inst.AccountMetaSlice[6] == nil { - return errors.New("accounts.SysvarInstructions is not set") - } - if inst.AccountMetaSlice[7] == nil { - return errors.New("accounts.TokenPoolsSigner is not set") - } - } - return nil -} - -func (inst *ManuallyExecute) EncodeToTree(parent ag_treeout.Branches) { - parent.Child(ag_format.Program(ProgramName, ProgramID)). - // - ParentFunc(func(programBranch ag_treeout.Branches) { - programBranch.Child(ag_format.Instruction("ManuallyExecute")). - // - ParentFunc(func(instructionBranch ag_treeout.Branches) { - - // Parameters of the instruction: - instructionBranch.Child("Params[len=1]").ParentFunc(func(paramsBranch ag_treeout.Branches) { - paramsBranch.Child(ag_format.Param("ExecutionReport", *inst.ExecutionReport)) - }) - - // Accounts of the instruction: - instructionBranch.Child("Accounts[len=8]").ParentFunc(func(accountsBranch ag_treeout.Branches) { - accountsBranch.Child(ag_format.Meta(" config", inst.AccountMetaSlice[0])) - accountsBranch.Child(ag_format.Meta(" chainState", inst.AccountMetaSlice[1])) - accountsBranch.Child(ag_format.Meta(" commitReport", inst.AccountMetaSlice[2])) - accountsBranch.Child(ag_format.Meta("externalExecutionConfig", inst.AccountMetaSlice[3])) - accountsBranch.Child(ag_format.Meta(" authority", inst.AccountMetaSlice[4])) - accountsBranch.Child(ag_format.Meta(" systemProgram", inst.AccountMetaSlice[5])) - accountsBranch.Child(ag_format.Meta(" sysvarInstructions", inst.AccountMetaSlice[6])) - accountsBranch.Child(ag_format.Meta(" tokenPoolsSigner", inst.AccountMetaSlice[7])) - }) - }) - }) -} - -func (obj ManuallyExecute) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { - // Serialize `ExecutionReport` param: - err = encoder.Encode(obj.ExecutionReport) - if err != nil { - return err - } - return nil -} -func (obj *ManuallyExecute) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { - // Deserialize `ExecutionReport`: - err = decoder.Decode(&obj.ExecutionReport) - if err != nil { - return err - } - return nil -} - -// NewManuallyExecuteInstruction declares a new ManuallyExecute instruction with the provided parameters and accounts. -func NewManuallyExecuteInstruction( - // Parameters: - executionReport ExecutionReportSingleChain, - // Accounts: - config ag_solanago.PublicKey, - chainState ag_solanago.PublicKey, - commitReport ag_solanago.PublicKey, - externalExecutionConfig ag_solanago.PublicKey, - authority ag_solanago.PublicKey, - systemProgram ag_solanago.PublicKey, - sysvarInstructions ag_solanago.PublicKey, - tokenPoolsSigner ag_solanago.PublicKey) *ManuallyExecute { - return NewManuallyExecuteInstructionBuilder(). - SetExecutionReport(executionReport). - SetConfigAccount(config). - SetChainStateAccount(chainState). - SetCommitReportAccount(commitReport). - SetExternalExecutionConfigAccount(externalExecutionConfig). - SetAuthorityAccount(authority). - SetSystemProgramAccount(systemProgram). - SetSysvarInstructionsAccount(sysvarInstructions). - SetTokenPoolsSignerAccount(tokenPoolsSigner) -} diff --git a/core/capabilities/ccip/ccipsolana/ccip_router/ManuallyExecute_test.go b/core/capabilities/ccip/ccipsolana/ccip_router/ManuallyExecute_test.go deleted file mode 100644 index 38f8fe33c61..00000000000 --- a/core/capabilities/ccip/ccipsolana/ccip_router/ManuallyExecute_test.go +++ /dev/null @@ -1,32 +0,0 @@ -// Code generated by https://github.com/gagliardetto/anchor-go. DO NOT EDIT. - -package ccip_router - -import ( - "bytes" - ag_gofuzz "github.com/gagliardetto/gofuzz" - ag_require "github.com/stretchr/testify/require" - "strconv" - "testing" -) - -func TestEncodeDecode_ManuallyExecute(t *testing.T) { - fu := ag_gofuzz.New().NilChance(0) - for i := 0; i < 1; i++ { - t.Run("ManuallyExecute"+strconv.Itoa(i), func(t *testing.T) { - { - params := new(ManuallyExecute) - fu.Fuzz(params) - params.AccountMetaSlice = nil - buf := new(bytes.Buffer) - err := encodeT(*params, buf) - ag_require.NoError(t, err) - got := new(ManuallyExecute) - err = decodeT(got, buf.Bytes()) - got.AccountMetaSlice = nil - ag_require.NoError(t, err) - ag_require.Equal(t, params, got) - } - }) - } -} diff --git a/core/capabilities/ccip/ccipsolana/ccip_router/RegisterTokenAdminRegistryViaGetCcipAdmin.go b/core/capabilities/ccip/ccipsolana/ccip_router/RegisterTokenAdminRegistryViaGetCcipAdmin.go deleted file mode 100644 index 20ed495cdb4..00000000000 --- a/core/capabilities/ccip/ccipsolana/ccip_router/RegisterTokenAdminRegistryViaGetCcipAdmin.go +++ /dev/null @@ -1,207 +0,0 @@ -// Code generated by https://github.com/gagliardetto/anchor-go. DO NOT EDIT. - -package ccip_router - -import ( - "errors" - ag_binary "github.com/gagliardetto/binary" - ag_solanago "github.com/gagliardetto/solana-go" - ag_format "github.com/gagliardetto/solana-go/text/format" - ag_treeout "github.com/gagliardetto/treeout" -) - -// The CCIP Admin or the Mint Authority of the Token can register the Token Admin Registry -type RegisterTokenAdminRegistryViaGetCcipAdmin struct { - Mint *ag_solanago.PublicKey - TokenAdminRegistryAdmin *ag_solanago.PublicKey - - // [0] = [] config - // - // [1] = [WRITE] tokenAdminRegistry - // - // [2] = [WRITE, SIGNER] authority - // - // [3] = [] systemProgram - ag_solanago.AccountMetaSlice `bin:"-" borsh_skip:"true"` -} - -// NewRegisterTokenAdminRegistryViaGetCcipAdminInstructionBuilder creates a new `RegisterTokenAdminRegistryViaGetCcipAdmin` instruction builder. -func NewRegisterTokenAdminRegistryViaGetCcipAdminInstructionBuilder() *RegisterTokenAdminRegistryViaGetCcipAdmin { - nd := &RegisterTokenAdminRegistryViaGetCcipAdmin{ - AccountMetaSlice: make(ag_solanago.AccountMetaSlice, 4), - } - return nd -} - -// SetMint sets the "mint" parameter. -func (inst *RegisterTokenAdminRegistryViaGetCcipAdmin) SetMint(mint ag_solanago.PublicKey) *RegisterTokenAdminRegistryViaGetCcipAdmin { - inst.Mint = &mint - return inst -} - -// SetTokenAdminRegistryAdmin sets the "tokenAdminRegistryAdmin" parameter. -func (inst *RegisterTokenAdminRegistryViaGetCcipAdmin) SetTokenAdminRegistryAdmin(tokenAdminRegistryAdmin ag_solanago.PublicKey) *RegisterTokenAdminRegistryViaGetCcipAdmin { - inst.TokenAdminRegistryAdmin = &tokenAdminRegistryAdmin - return inst -} - -// SetConfigAccount sets the "config" account. -func (inst *RegisterTokenAdminRegistryViaGetCcipAdmin) SetConfigAccount(config ag_solanago.PublicKey) *RegisterTokenAdminRegistryViaGetCcipAdmin { - inst.AccountMetaSlice[0] = ag_solanago.Meta(config) - return inst -} - -// GetConfigAccount gets the "config" account. -func (inst *RegisterTokenAdminRegistryViaGetCcipAdmin) GetConfigAccount() *ag_solanago.AccountMeta { - return inst.AccountMetaSlice[0] -} - -// SetTokenAdminRegistryAccount sets the "tokenAdminRegistry" account. -func (inst *RegisterTokenAdminRegistryViaGetCcipAdmin) SetTokenAdminRegistryAccount(tokenAdminRegistry ag_solanago.PublicKey) *RegisterTokenAdminRegistryViaGetCcipAdmin { - inst.AccountMetaSlice[1] = ag_solanago.Meta(tokenAdminRegistry).WRITE() - return inst -} - -// GetTokenAdminRegistryAccount gets the "tokenAdminRegistry" account. -func (inst *RegisterTokenAdminRegistryViaGetCcipAdmin) GetTokenAdminRegistryAccount() *ag_solanago.AccountMeta { - return inst.AccountMetaSlice[1] -} - -// SetAuthorityAccount sets the "authority" account. -func (inst *RegisterTokenAdminRegistryViaGetCcipAdmin) SetAuthorityAccount(authority ag_solanago.PublicKey) *RegisterTokenAdminRegistryViaGetCcipAdmin { - inst.AccountMetaSlice[2] = ag_solanago.Meta(authority).WRITE().SIGNER() - return inst -} - -// GetAuthorityAccount gets the "authority" account. -func (inst *RegisterTokenAdminRegistryViaGetCcipAdmin) GetAuthorityAccount() *ag_solanago.AccountMeta { - return inst.AccountMetaSlice[2] -} - -// SetSystemProgramAccount sets the "systemProgram" account. -func (inst *RegisterTokenAdminRegistryViaGetCcipAdmin) SetSystemProgramAccount(systemProgram ag_solanago.PublicKey) *RegisterTokenAdminRegistryViaGetCcipAdmin { - inst.AccountMetaSlice[3] = ag_solanago.Meta(systemProgram) - return inst -} - -// GetSystemProgramAccount gets the "systemProgram" account. -func (inst *RegisterTokenAdminRegistryViaGetCcipAdmin) GetSystemProgramAccount() *ag_solanago.AccountMeta { - return inst.AccountMetaSlice[3] -} - -func (inst RegisterTokenAdminRegistryViaGetCcipAdmin) Build() *Instruction { - return &Instruction{BaseVariant: ag_binary.BaseVariant{ - Impl: inst, - TypeID: Instruction_RegisterTokenAdminRegistryViaGetCcipAdmin, - }} -} - -// ValidateAndBuild validates the instruction parameters and accounts; -// if there is a validation error, it returns the error. -// Otherwise, it builds and returns the instruction. -func (inst RegisterTokenAdminRegistryViaGetCcipAdmin) ValidateAndBuild() (*Instruction, error) { - if err := inst.Validate(); err != nil { - return nil, err - } - return inst.Build(), nil -} - -func (inst *RegisterTokenAdminRegistryViaGetCcipAdmin) Validate() error { - // Check whether all (required) parameters are set: - { - if inst.Mint == nil { - return errors.New("Mint parameter is not set") - } - if inst.TokenAdminRegistryAdmin == nil { - return errors.New("TokenAdminRegistryAdmin parameter is not set") - } - } - - // Check whether all (required) accounts are set: - { - if inst.AccountMetaSlice[0] == nil { - return errors.New("accounts.Config is not set") - } - if inst.AccountMetaSlice[1] == nil { - return errors.New("accounts.TokenAdminRegistry is not set") - } - if inst.AccountMetaSlice[2] == nil { - return errors.New("accounts.Authority is not set") - } - if inst.AccountMetaSlice[3] == nil { - return errors.New("accounts.SystemProgram is not set") - } - } - return nil -} - -func (inst *RegisterTokenAdminRegistryViaGetCcipAdmin) EncodeToTree(parent ag_treeout.Branches) { - parent.Child(ag_format.Program(ProgramName, ProgramID)). - // - ParentFunc(func(programBranch ag_treeout.Branches) { - programBranch.Child(ag_format.Instruction("RegisterTokenAdminRegistryViaGetCcipAdmin")). - // - ParentFunc(func(instructionBranch ag_treeout.Branches) { - - // Parameters of the instruction: - instructionBranch.Child("Params[len=2]").ParentFunc(func(paramsBranch ag_treeout.Branches) { - paramsBranch.Child(ag_format.Param(" Mint", *inst.Mint)) - paramsBranch.Child(ag_format.Param("TokenAdminRegistryAdmin", *inst.TokenAdminRegistryAdmin)) - }) - - // Accounts of the instruction: - instructionBranch.Child("Accounts[len=4]").ParentFunc(func(accountsBranch ag_treeout.Branches) { - accountsBranch.Child(ag_format.Meta(" config", inst.AccountMetaSlice[0])) - accountsBranch.Child(ag_format.Meta("tokenAdminRegistry", inst.AccountMetaSlice[1])) - accountsBranch.Child(ag_format.Meta(" authority", inst.AccountMetaSlice[2])) - accountsBranch.Child(ag_format.Meta(" systemProgram", inst.AccountMetaSlice[3])) - }) - }) - }) -} - -func (obj RegisterTokenAdminRegistryViaGetCcipAdmin) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { - // Serialize `Mint` param: - err = encoder.Encode(obj.Mint) - if err != nil { - return err - } - // Serialize `TokenAdminRegistryAdmin` param: - err = encoder.Encode(obj.TokenAdminRegistryAdmin) - if err != nil { - return err - } - return nil -} -func (obj *RegisterTokenAdminRegistryViaGetCcipAdmin) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { - // Deserialize `Mint`: - err = decoder.Decode(&obj.Mint) - if err != nil { - return err - } - // Deserialize `TokenAdminRegistryAdmin`: - err = decoder.Decode(&obj.TokenAdminRegistryAdmin) - if err != nil { - return err - } - return nil -} - -// NewRegisterTokenAdminRegistryViaGetCcipAdminInstruction declares a new RegisterTokenAdminRegistryViaGetCcipAdmin instruction with the provided parameters and accounts. -func NewRegisterTokenAdminRegistryViaGetCcipAdminInstruction( - // Parameters: - mint ag_solanago.PublicKey, - tokenAdminRegistryAdmin ag_solanago.PublicKey, - // Accounts: - config ag_solanago.PublicKey, - tokenAdminRegistry ag_solanago.PublicKey, - authority ag_solanago.PublicKey, - systemProgram ag_solanago.PublicKey) *RegisterTokenAdminRegistryViaGetCcipAdmin { - return NewRegisterTokenAdminRegistryViaGetCcipAdminInstructionBuilder(). - SetMint(mint). - SetTokenAdminRegistryAdmin(tokenAdminRegistryAdmin). - SetConfigAccount(config). - SetTokenAdminRegistryAccount(tokenAdminRegistry). - SetAuthorityAccount(authority). - SetSystemProgramAccount(systemProgram) -} diff --git a/core/capabilities/ccip/ccipsolana/ccip_router/RegisterTokenAdminRegistryViaGetCcipAdmin_test.go b/core/capabilities/ccip/ccipsolana/ccip_router/RegisterTokenAdminRegistryViaGetCcipAdmin_test.go deleted file mode 100644 index 29a2c212a49..00000000000 --- a/core/capabilities/ccip/ccipsolana/ccip_router/RegisterTokenAdminRegistryViaGetCcipAdmin_test.go +++ /dev/null @@ -1,32 +0,0 @@ -// Code generated by https://github.com/gagliardetto/anchor-go. DO NOT EDIT. - -package ccip_router - -import ( - "bytes" - ag_gofuzz "github.com/gagliardetto/gofuzz" - ag_require "github.com/stretchr/testify/require" - "strconv" - "testing" -) - -func TestEncodeDecode_RegisterTokenAdminRegistryViaGetCcipAdmin(t *testing.T) { - fu := ag_gofuzz.New().NilChance(0) - for i := 0; i < 1; i++ { - t.Run("RegisterTokenAdminRegistryViaGetCcipAdmin"+strconv.Itoa(i), func(t *testing.T) { - { - params := new(RegisterTokenAdminRegistryViaGetCcipAdmin) - fu.Fuzz(params) - params.AccountMetaSlice = nil - buf := new(bytes.Buffer) - err := encodeT(*params, buf) - ag_require.NoError(t, err) - got := new(RegisterTokenAdminRegistryViaGetCcipAdmin) - err = decodeT(got, buf.Bytes()) - got.AccountMetaSlice = nil - ag_require.NoError(t, err) - ag_require.Equal(t, params, got) - } - }) - } -} diff --git a/core/capabilities/ccip/ccipsolana/ccip_router/RegisterTokenAdminRegistryViaOwner.go b/core/capabilities/ccip/ccipsolana/ccip_router/RegisterTokenAdminRegistryViaOwner.go deleted file mode 100644 index eb79b822606..00000000000 --- a/core/capabilities/ccip/ccipsolana/ccip_router/RegisterTokenAdminRegistryViaOwner.go +++ /dev/null @@ -1,155 +0,0 @@ -// Code generated by https://github.com/gagliardetto/anchor-go. DO NOT EDIT. - -package ccip_router - -import ( - "errors" - ag_binary "github.com/gagliardetto/binary" - ag_solanago "github.com/gagliardetto/solana-go" - ag_format "github.com/gagliardetto/solana-go/text/format" - ag_treeout "github.com/gagliardetto/treeout" -) - -// The Token's mint_authority can register themselves to the Token Admin Registry -type RegisterTokenAdminRegistryViaOwner struct { - - // [0] = [WRITE] tokenAdminRegistry - // - // [1] = [WRITE] mint - // - // [2] = [WRITE, SIGNER] authority - // - // [3] = [] systemProgram - ag_solanago.AccountMetaSlice `bin:"-" borsh_skip:"true"` -} - -// NewRegisterTokenAdminRegistryViaOwnerInstructionBuilder creates a new `RegisterTokenAdminRegistryViaOwner` instruction builder. -func NewRegisterTokenAdminRegistryViaOwnerInstructionBuilder() *RegisterTokenAdminRegistryViaOwner { - nd := &RegisterTokenAdminRegistryViaOwner{ - AccountMetaSlice: make(ag_solanago.AccountMetaSlice, 4), - } - return nd -} - -// SetTokenAdminRegistryAccount sets the "tokenAdminRegistry" account. -func (inst *RegisterTokenAdminRegistryViaOwner) SetTokenAdminRegistryAccount(tokenAdminRegistry ag_solanago.PublicKey) *RegisterTokenAdminRegistryViaOwner { - inst.AccountMetaSlice[0] = ag_solanago.Meta(tokenAdminRegistry).WRITE() - return inst -} - -// GetTokenAdminRegistryAccount gets the "tokenAdminRegistry" account. -func (inst *RegisterTokenAdminRegistryViaOwner) GetTokenAdminRegistryAccount() *ag_solanago.AccountMeta { - return inst.AccountMetaSlice[0] -} - -// SetMintAccount sets the "mint" account. -func (inst *RegisterTokenAdminRegistryViaOwner) SetMintAccount(mint ag_solanago.PublicKey) *RegisterTokenAdminRegistryViaOwner { - inst.AccountMetaSlice[1] = ag_solanago.Meta(mint).WRITE() - return inst -} - -// GetMintAccount gets the "mint" account. -func (inst *RegisterTokenAdminRegistryViaOwner) GetMintAccount() *ag_solanago.AccountMeta { - return inst.AccountMetaSlice[1] -} - -// SetAuthorityAccount sets the "authority" account. -func (inst *RegisterTokenAdminRegistryViaOwner) SetAuthorityAccount(authority ag_solanago.PublicKey) *RegisterTokenAdminRegistryViaOwner { - inst.AccountMetaSlice[2] = ag_solanago.Meta(authority).WRITE().SIGNER() - return inst -} - -// GetAuthorityAccount gets the "authority" account. -func (inst *RegisterTokenAdminRegistryViaOwner) GetAuthorityAccount() *ag_solanago.AccountMeta { - return inst.AccountMetaSlice[2] -} - -// SetSystemProgramAccount sets the "systemProgram" account. -func (inst *RegisterTokenAdminRegistryViaOwner) SetSystemProgramAccount(systemProgram ag_solanago.PublicKey) *RegisterTokenAdminRegistryViaOwner { - inst.AccountMetaSlice[3] = ag_solanago.Meta(systemProgram) - return inst -} - -// GetSystemProgramAccount gets the "systemProgram" account. -func (inst *RegisterTokenAdminRegistryViaOwner) GetSystemProgramAccount() *ag_solanago.AccountMeta { - return inst.AccountMetaSlice[3] -} - -func (inst RegisterTokenAdminRegistryViaOwner) Build() *Instruction { - return &Instruction{BaseVariant: ag_binary.BaseVariant{ - Impl: inst, - TypeID: Instruction_RegisterTokenAdminRegistryViaOwner, - }} -} - -// ValidateAndBuild validates the instruction parameters and accounts; -// if there is a validation error, it returns the error. -// Otherwise, it builds and returns the instruction. -func (inst RegisterTokenAdminRegistryViaOwner) ValidateAndBuild() (*Instruction, error) { - if err := inst.Validate(); err != nil { - return nil, err - } - return inst.Build(), nil -} - -func (inst *RegisterTokenAdminRegistryViaOwner) Validate() error { - // Check whether all (required) accounts are set: - { - if inst.AccountMetaSlice[0] == nil { - return errors.New("accounts.TokenAdminRegistry is not set") - } - if inst.AccountMetaSlice[1] == nil { - return errors.New("accounts.Mint is not set") - } - if inst.AccountMetaSlice[2] == nil { - return errors.New("accounts.Authority is not set") - } - if inst.AccountMetaSlice[3] == nil { - return errors.New("accounts.SystemProgram is not set") - } - } - return nil -} - -func (inst *RegisterTokenAdminRegistryViaOwner) EncodeToTree(parent ag_treeout.Branches) { - parent.Child(ag_format.Program(ProgramName, ProgramID)). - // - ParentFunc(func(programBranch ag_treeout.Branches) { - programBranch.Child(ag_format.Instruction("RegisterTokenAdminRegistryViaOwner")). - // - ParentFunc(func(instructionBranch ag_treeout.Branches) { - - // Parameters of the instruction: - instructionBranch.Child("Params[len=0]").ParentFunc(func(paramsBranch ag_treeout.Branches) {}) - - // Accounts of the instruction: - instructionBranch.Child("Accounts[len=4]").ParentFunc(func(accountsBranch ag_treeout.Branches) { - accountsBranch.Child(ag_format.Meta("tokenAdminRegistry", inst.AccountMetaSlice[0])) - accountsBranch.Child(ag_format.Meta(" mint", inst.AccountMetaSlice[1])) - accountsBranch.Child(ag_format.Meta(" authority", inst.AccountMetaSlice[2])) - accountsBranch.Child(ag_format.Meta(" systemProgram", inst.AccountMetaSlice[3])) - }) - }) - }) -} - -func (obj RegisterTokenAdminRegistryViaOwner) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { - return nil -} -func (obj *RegisterTokenAdminRegistryViaOwner) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { - return nil -} - -// NewRegisterTokenAdminRegistryViaOwnerInstruction declares a new RegisterTokenAdminRegistryViaOwner instruction with the provided parameters and accounts. -func NewRegisterTokenAdminRegistryViaOwnerInstruction( - // Accounts: - tokenAdminRegistry ag_solanago.PublicKey, - mint ag_solanago.PublicKey, - authority ag_solanago.PublicKey, - systemProgram ag_solanago.PublicKey) *RegisterTokenAdminRegistryViaOwner { - return NewRegisterTokenAdminRegistryViaOwnerInstructionBuilder(). - SetTokenAdminRegistryAccount(tokenAdminRegistry). - SetMintAccount(mint). - SetAuthorityAccount(authority). - SetSystemProgramAccount(systemProgram) -} diff --git a/core/capabilities/ccip/ccipsolana/ccip_router/RegisterTokenAdminRegistryViaOwner_test.go b/core/capabilities/ccip/ccipsolana/ccip_router/RegisterTokenAdminRegistryViaOwner_test.go deleted file mode 100644 index ea293f88b2e..00000000000 --- a/core/capabilities/ccip/ccipsolana/ccip_router/RegisterTokenAdminRegistryViaOwner_test.go +++ /dev/null @@ -1,32 +0,0 @@ -// Code generated by https://github.com/gagliardetto/anchor-go. DO NOT EDIT. - -package ccip_router - -import ( - "bytes" - ag_gofuzz "github.com/gagliardetto/gofuzz" - ag_require "github.com/stretchr/testify/require" - "strconv" - "testing" -) - -func TestEncodeDecode_RegisterTokenAdminRegistryViaOwner(t *testing.T) { - fu := ag_gofuzz.New().NilChance(0) - for i := 0; i < 1; i++ { - t.Run("RegisterTokenAdminRegistryViaOwner"+strconv.Itoa(i), func(t *testing.T) { - { - params := new(RegisterTokenAdminRegistryViaOwner) - fu.Fuzz(params) - params.AccountMetaSlice = nil - buf := new(bytes.Buffer) - err := encodeT(*params, buf) - ag_require.NoError(t, err) - got := new(RegisterTokenAdminRegistryViaOwner) - err = decodeT(got, buf.Bytes()) - got.AccountMetaSlice = nil - ag_require.NoError(t, err) - ag_require.Equal(t, params, got) - } - }) - } -} diff --git a/core/capabilities/ccip/ccipsolana/ccip_router/SetOcrConfig.go b/core/capabilities/ccip/ccipsolana/ccip_router/SetOcrConfig.go deleted file mode 100644 index 3a6420a6980..00000000000 --- a/core/capabilities/ccip/ccipsolana/ccip_router/SetOcrConfig.go +++ /dev/null @@ -1,215 +0,0 @@ -// Code generated by https://github.com/gagliardetto/anchor-go. DO NOT EDIT. - -package ccip_router - -import ( - "errors" - ag_binary "github.com/gagliardetto/binary" - ag_solanago "github.com/gagliardetto/solana-go" - ag_format "github.com/gagliardetto/solana-go/text/format" - ag_treeout "github.com/gagliardetto/treeout" -) - -// SetOcrConfig is the `setOcrConfig` instruction. -type SetOcrConfig struct { - PluginType *uint8 - ConfigInfo *Ocr3ConfigInfo - Signers *[][20]uint8 - Transmitters *[]ag_solanago.PublicKey - - // [0] = [WRITE] config - // - // [1] = [SIGNER] authority - ag_solanago.AccountMetaSlice `bin:"-" borsh_skip:"true"` -} - -// NewSetOcrConfigInstructionBuilder creates a new `SetOcrConfig` instruction builder. -func NewSetOcrConfigInstructionBuilder() *SetOcrConfig { - nd := &SetOcrConfig{ - AccountMetaSlice: make(ag_solanago.AccountMetaSlice, 2), - } - return nd -} - -// SetPluginType sets the "pluginType" parameter. -func (inst *SetOcrConfig) SetPluginType(pluginType uint8) *SetOcrConfig { - inst.PluginType = &pluginType - return inst -} - -// SetConfigInfo sets the "configInfo" parameter. -func (inst *SetOcrConfig) SetConfigInfo(configInfo Ocr3ConfigInfo) *SetOcrConfig { - inst.ConfigInfo = &configInfo - return inst -} - -// SetSigners sets the "signers" parameter. -func (inst *SetOcrConfig) SetSigners(signers [][20]uint8) *SetOcrConfig { - inst.Signers = &signers - return inst -} - -// SetTransmitters sets the "transmitters" parameter. -func (inst *SetOcrConfig) SetTransmitters(transmitters []ag_solanago.PublicKey) *SetOcrConfig { - inst.Transmitters = &transmitters - return inst -} - -// SetConfigAccount sets the "config" account. -func (inst *SetOcrConfig) SetConfigAccount(config ag_solanago.PublicKey) *SetOcrConfig { - inst.AccountMetaSlice[0] = ag_solanago.Meta(config).WRITE() - return inst -} - -// GetConfigAccount gets the "config" account. -func (inst *SetOcrConfig) GetConfigAccount() *ag_solanago.AccountMeta { - return inst.AccountMetaSlice[0] -} - -// SetAuthorityAccount sets the "authority" account. -func (inst *SetOcrConfig) SetAuthorityAccount(authority ag_solanago.PublicKey) *SetOcrConfig { - inst.AccountMetaSlice[1] = ag_solanago.Meta(authority).SIGNER() - return inst -} - -// GetAuthorityAccount gets the "authority" account. -func (inst *SetOcrConfig) GetAuthorityAccount() *ag_solanago.AccountMeta { - return inst.AccountMetaSlice[1] -} - -func (inst SetOcrConfig) Build() *Instruction { - return &Instruction{BaseVariant: ag_binary.BaseVariant{ - Impl: inst, - TypeID: Instruction_SetOcrConfig, - }} -} - -// ValidateAndBuild validates the instruction parameters and accounts; -// if there is a validation error, it returns the error. -// Otherwise, it builds and returns the instruction. -func (inst SetOcrConfig) ValidateAndBuild() (*Instruction, error) { - if err := inst.Validate(); err != nil { - return nil, err - } - return inst.Build(), nil -} - -func (inst *SetOcrConfig) Validate() error { - // Check whether all (required) parameters are set: - { - if inst.PluginType == nil { - return errors.New("PluginType parameter is not set") - } - if inst.ConfigInfo == nil { - return errors.New("ConfigInfo parameter is not set") - } - if inst.Signers == nil { - return errors.New("Signers parameter is not set") - } - if inst.Transmitters == nil { - return errors.New("Transmitters parameter is not set") - } - } - - // Check whether all (required) accounts are set: - { - if inst.AccountMetaSlice[0] == nil { - return errors.New("accounts.Config is not set") - } - if inst.AccountMetaSlice[1] == nil { - return errors.New("accounts.Authority is not set") - } - } - return nil -} - -func (inst *SetOcrConfig) EncodeToTree(parent ag_treeout.Branches) { - parent.Child(ag_format.Program(ProgramName, ProgramID)). - // - ParentFunc(func(programBranch ag_treeout.Branches) { - programBranch.Child(ag_format.Instruction("SetOcrConfig")). - // - ParentFunc(func(instructionBranch ag_treeout.Branches) { - - // Parameters of the instruction: - instructionBranch.Child("Params[len=4]").ParentFunc(func(paramsBranch ag_treeout.Branches) { - paramsBranch.Child(ag_format.Param(" PluginType", *inst.PluginType)) - paramsBranch.Child(ag_format.Param(" ConfigInfo", *inst.ConfigInfo)) - paramsBranch.Child(ag_format.Param(" Signers", *inst.Signers)) - paramsBranch.Child(ag_format.Param("Transmitters", *inst.Transmitters)) - }) - - // Accounts of the instruction: - instructionBranch.Child("Accounts[len=2]").ParentFunc(func(accountsBranch ag_treeout.Branches) { - accountsBranch.Child(ag_format.Meta(" config", inst.AccountMetaSlice[0])) - accountsBranch.Child(ag_format.Meta("authority", inst.AccountMetaSlice[1])) - }) - }) - }) -} - -func (obj SetOcrConfig) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { - // Serialize `PluginType` param: - err = encoder.Encode(obj.PluginType) - if err != nil { - return err - } - // Serialize `ConfigInfo` param: - err = encoder.Encode(obj.ConfigInfo) - if err != nil { - return err - } - // Serialize `Signers` param: - err = encoder.Encode(obj.Signers) - if err != nil { - return err - } - // Serialize `Transmitters` param: - err = encoder.Encode(obj.Transmitters) - if err != nil { - return err - } - return nil -} -func (obj *SetOcrConfig) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { - // Deserialize `PluginType`: - err = decoder.Decode(&obj.PluginType) - if err != nil { - return err - } - // Deserialize `ConfigInfo`: - err = decoder.Decode(&obj.ConfigInfo) - if err != nil { - return err - } - // Deserialize `Signers`: - err = decoder.Decode(&obj.Signers) - if err != nil { - return err - } - // Deserialize `Transmitters`: - err = decoder.Decode(&obj.Transmitters) - if err != nil { - return err - } - return nil -} - -// NewSetOcrConfigInstruction declares a new SetOcrConfig instruction with the provided parameters and accounts. -func NewSetOcrConfigInstruction( - // Parameters: - pluginType uint8, - configInfo Ocr3ConfigInfo, - signers [][20]uint8, - transmitters []ag_solanago.PublicKey, - // Accounts: - config ag_solanago.PublicKey, - authority ag_solanago.PublicKey) *SetOcrConfig { - return NewSetOcrConfigInstructionBuilder(). - SetPluginType(pluginType). - SetConfigInfo(configInfo). - SetSigners(signers). - SetTransmitters(transmitters). - SetConfigAccount(config). - SetAuthorityAccount(authority) -} diff --git a/core/capabilities/ccip/ccipsolana/ccip_router/SetOcrConfig_test.go b/core/capabilities/ccip/ccipsolana/ccip_router/SetOcrConfig_test.go deleted file mode 100644 index 88528fc48ea..00000000000 --- a/core/capabilities/ccip/ccipsolana/ccip_router/SetOcrConfig_test.go +++ /dev/null @@ -1,32 +0,0 @@ -// Code generated by https://github.com/gagliardetto/anchor-go. DO NOT EDIT. - -package ccip_router - -import ( - "bytes" - ag_gofuzz "github.com/gagliardetto/gofuzz" - ag_require "github.com/stretchr/testify/require" - "strconv" - "testing" -) - -func TestEncodeDecode_SetOcrConfig(t *testing.T) { - fu := ag_gofuzz.New().NilChance(0) - for i := 0; i < 1; i++ { - t.Run("SetOcrConfig"+strconv.Itoa(i), func(t *testing.T) { - { - params := new(SetOcrConfig) - fu.Fuzz(params) - params.AccountMetaSlice = nil - buf := new(bytes.Buffer) - err := encodeT(*params, buf) - ag_require.NoError(t, err) - got := new(SetOcrConfig) - err = decodeT(got, buf.Bytes()) - got.AccountMetaSlice = nil - ag_require.NoError(t, err) - ag_require.Equal(t, params, got) - } - }) - } -} diff --git a/core/capabilities/ccip/ccipsolana/ccip_router/SetPool.go b/core/capabilities/ccip/ccipsolana/ccip_router/SetPool.go deleted file mode 100644 index 69cdc9ba5e1..00000000000 --- a/core/capabilities/ccip/ccipsolana/ccip_router/SetPool.go +++ /dev/null @@ -1,169 +0,0 @@ -// Code generated by https://github.com/gagliardetto/anchor-go. DO NOT EDIT. - -package ccip_router - -import ( - "errors" - ag_binary "github.com/gagliardetto/binary" - ag_solanago "github.com/gagliardetto/solana-go" - ag_format "github.com/gagliardetto/solana-go/text/format" - ag_treeout "github.com/gagliardetto/treeout" -) - -// The administrator of the token can setup the token pool -type SetPool struct { - Mint *ag_solanago.PublicKey - PoolLookupTable *ag_solanago.PublicKey - - // [0] = [WRITE] tokenAdminRegistry - // - // [1] = [WRITE, SIGNER] authority - ag_solanago.AccountMetaSlice `bin:"-" borsh_skip:"true"` -} - -// NewSetPoolInstructionBuilder creates a new `SetPool` instruction builder. -func NewSetPoolInstructionBuilder() *SetPool { - nd := &SetPool{ - AccountMetaSlice: make(ag_solanago.AccountMetaSlice, 2), - } - return nd -} - -// SetMint sets the "mint" parameter. -func (inst *SetPool) SetMint(mint ag_solanago.PublicKey) *SetPool { - inst.Mint = &mint - return inst -} - -// SetPoolLookupTable sets the "poolLookupTable" parameter. -func (inst *SetPool) SetPoolLookupTable(poolLookupTable ag_solanago.PublicKey) *SetPool { - inst.PoolLookupTable = &poolLookupTable - return inst -} - -// SetTokenAdminRegistryAccount sets the "tokenAdminRegistry" account. -func (inst *SetPool) SetTokenAdminRegistryAccount(tokenAdminRegistry ag_solanago.PublicKey) *SetPool { - inst.AccountMetaSlice[0] = ag_solanago.Meta(tokenAdminRegistry).WRITE() - return inst -} - -// GetTokenAdminRegistryAccount gets the "tokenAdminRegistry" account. -func (inst *SetPool) GetTokenAdminRegistryAccount() *ag_solanago.AccountMeta { - return inst.AccountMetaSlice[0] -} - -// SetAuthorityAccount sets the "authority" account. -func (inst *SetPool) SetAuthorityAccount(authority ag_solanago.PublicKey) *SetPool { - inst.AccountMetaSlice[1] = ag_solanago.Meta(authority).WRITE().SIGNER() - return inst -} - -// GetAuthorityAccount gets the "authority" account. -func (inst *SetPool) GetAuthorityAccount() *ag_solanago.AccountMeta { - return inst.AccountMetaSlice[1] -} - -func (inst SetPool) Build() *Instruction { - return &Instruction{BaseVariant: ag_binary.BaseVariant{ - Impl: inst, - TypeID: Instruction_SetPool, - }} -} - -// ValidateAndBuild validates the instruction parameters and accounts; -// if there is a validation error, it returns the error. -// Otherwise, it builds and returns the instruction. -func (inst SetPool) ValidateAndBuild() (*Instruction, error) { - if err := inst.Validate(); err != nil { - return nil, err - } - return inst.Build(), nil -} - -func (inst *SetPool) Validate() error { - // Check whether all (required) parameters are set: - { - if inst.Mint == nil { - return errors.New("Mint parameter is not set") - } - if inst.PoolLookupTable == nil { - return errors.New("PoolLookupTable parameter is not set") - } - } - - // Check whether all (required) accounts are set: - { - if inst.AccountMetaSlice[0] == nil { - return errors.New("accounts.TokenAdminRegistry is not set") - } - if inst.AccountMetaSlice[1] == nil { - return errors.New("accounts.Authority is not set") - } - } - return nil -} - -func (inst *SetPool) EncodeToTree(parent ag_treeout.Branches) { - parent.Child(ag_format.Program(ProgramName, ProgramID)). - // - ParentFunc(func(programBranch ag_treeout.Branches) { - programBranch.Child(ag_format.Instruction("SetPool")). - // - ParentFunc(func(instructionBranch ag_treeout.Branches) { - - // Parameters of the instruction: - instructionBranch.Child("Params[len=2]").ParentFunc(func(paramsBranch ag_treeout.Branches) { - paramsBranch.Child(ag_format.Param(" Mint", *inst.Mint)) - paramsBranch.Child(ag_format.Param("PoolLookupTable", *inst.PoolLookupTable)) - }) - - // Accounts of the instruction: - instructionBranch.Child("Accounts[len=2]").ParentFunc(func(accountsBranch ag_treeout.Branches) { - accountsBranch.Child(ag_format.Meta("tokenAdminRegistry", inst.AccountMetaSlice[0])) - accountsBranch.Child(ag_format.Meta(" authority", inst.AccountMetaSlice[1])) - }) - }) - }) -} - -func (obj SetPool) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { - // Serialize `Mint` param: - err = encoder.Encode(obj.Mint) - if err != nil { - return err - } - // Serialize `PoolLookupTable` param: - err = encoder.Encode(obj.PoolLookupTable) - if err != nil { - return err - } - return nil -} -func (obj *SetPool) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { - // Deserialize `Mint`: - err = decoder.Decode(&obj.Mint) - if err != nil { - return err - } - // Deserialize `PoolLookupTable`: - err = decoder.Decode(&obj.PoolLookupTable) - if err != nil { - return err - } - return nil -} - -// NewSetPoolInstruction declares a new SetPool instruction with the provided parameters and accounts. -func NewSetPoolInstruction( - // Parameters: - mint ag_solanago.PublicKey, - poolLookupTable ag_solanago.PublicKey, - // Accounts: - tokenAdminRegistry ag_solanago.PublicKey, - authority ag_solanago.PublicKey) *SetPool { - return NewSetPoolInstructionBuilder(). - SetMint(mint). - SetPoolLookupTable(poolLookupTable). - SetTokenAdminRegistryAccount(tokenAdminRegistry). - SetAuthorityAccount(authority) -} diff --git a/core/capabilities/ccip/ccipsolana/ccip_router/SetPool_test.go b/core/capabilities/ccip/ccipsolana/ccip_router/SetPool_test.go deleted file mode 100644 index 249513a25ba..00000000000 --- a/core/capabilities/ccip/ccipsolana/ccip_router/SetPool_test.go +++ /dev/null @@ -1,32 +0,0 @@ -// Code generated by https://github.com/gagliardetto/anchor-go. DO NOT EDIT. - -package ccip_router - -import ( - "bytes" - ag_gofuzz "github.com/gagliardetto/gofuzz" - ag_require "github.com/stretchr/testify/require" - "strconv" - "testing" -) - -func TestEncodeDecode_SetPool(t *testing.T) { - fu := ag_gofuzz.New().NilChance(0) - for i := 0; i < 1; i++ { - t.Run("SetPool"+strconv.Itoa(i), func(t *testing.T) { - { - params := new(SetPool) - fu.Fuzz(params) - params.AccountMetaSlice = nil - buf := new(bytes.Buffer) - err := encodeT(*params, buf) - ag_require.NoError(t, err) - got := new(SetPool) - err = decodeT(got, buf.Bytes()) - got.AccountMetaSlice = nil - ag_require.NoError(t, err) - ag_require.Equal(t, params, got) - } - }) - } -} diff --git a/core/capabilities/ccip/ccipsolana/ccip_router/SetTokenBilling.go b/core/capabilities/ccip/ccipsolana/ccip_router/SetTokenBilling.go deleted file mode 100644 index 41f1bcd34a5..00000000000 --- a/core/capabilities/ccip/ccipsolana/ccip_router/SetTokenBilling.go +++ /dev/null @@ -1,230 +0,0 @@ -// Code generated by https://github.com/gagliardetto/anchor-go. DO NOT EDIT. - -package ccip_router - -import ( - "errors" - ag_binary "github.com/gagliardetto/binary" - ag_solanago "github.com/gagliardetto/solana-go" - ag_format "github.com/gagliardetto/solana-go/text/format" - ag_treeout "github.com/gagliardetto/treeout" -) - -// SetTokenBilling is the `setTokenBilling` instruction. -type SetTokenBilling struct { - ChainSelector *uint64 - Mint *ag_solanago.PublicKey - Cfg *TokenBilling - - // [0] = [] config - // - // [1] = [WRITE] perChainPerTokenConfig - // - // [2] = [WRITE, SIGNER] authority - // - // [3] = [] systemProgram - ag_solanago.AccountMetaSlice `bin:"-" borsh_skip:"true"` -} - -// NewSetTokenBillingInstructionBuilder creates a new `SetTokenBilling` instruction builder. -func NewSetTokenBillingInstructionBuilder() *SetTokenBilling { - nd := &SetTokenBilling{ - AccountMetaSlice: make(ag_solanago.AccountMetaSlice, 4), - } - return nd -} - -// SetChainSelector sets the "chainSelector" parameter. -func (inst *SetTokenBilling) SetChainSelector(chainSelector uint64) *SetTokenBilling { - inst.ChainSelector = &chainSelector - return inst -} - -// SetMint sets the "mint" parameter. -func (inst *SetTokenBilling) SetMint(mint ag_solanago.PublicKey) *SetTokenBilling { - inst.Mint = &mint - return inst -} - -// SetCfg sets the "cfg" parameter. -func (inst *SetTokenBilling) SetCfg(cfg TokenBilling) *SetTokenBilling { - inst.Cfg = &cfg - return inst -} - -// SetConfigAccount sets the "config" account. -func (inst *SetTokenBilling) SetConfigAccount(config ag_solanago.PublicKey) *SetTokenBilling { - inst.AccountMetaSlice[0] = ag_solanago.Meta(config) - return inst -} - -// GetConfigAccount gets the "config" account. -func (inst *SetTokenBilling) GetConfigAccount() *ag_solanago.AccountMeta { - return inst.AccountMetaSlice[0] -} - -// SetPerChainPerTokenConfigAccount sets the "perChainPerTokenConfig" account. -func (inst *SetTokenBilling) SetPerChainPerTokenConfigAccount(perChainPerTokenConfig ag_solanago.PublicKey) *SetTokenBilling { - inst.AccountMetaSlice[1] = ag_solanago.Meta(perChainPerTokenConfig).WRITE() - return inst -} - -// GetPerChainPerTokenConfigAccount gets the "perChainPerTokenConfig" account. -func (inst *SetTokenBilling) GetPerChainPerTokenConfigAccount() *ag_solanago.AccountMeta { - return inst.AccountMetaSlice[1] -} - -// SetAuthorityAccount sets the "authority" account. -func (inst *SetTokenBilling) SetAuthorityAccount(authority ag_solanago.PublicKey) *SetTokenBilling { - inst.AccountMetaSlice[2] = ag_solanago.Meta(authority).WRITE().SIGNER() - return inst -} - -// GetAuthorityAccount gets the "authority" account. -func (inst *SetTokenBilling) GetAuthorityAccount() *ag_solanago.AccountMeta { - return inst.AccountMetaSlice[2] -} - -// SetSystemProgramAccount sets the "systemProgram" account. -func (inst *SetTokenBilling) SetSystemProgramAccount(systemProgram ag_solanago.PublicKey) *SetTokenBilling { - inst.AccountMetaSlice[3] = ag_solanago.Meta(systemProgram) - return inst -} - -// GetSystemProgramAccount gets the "systemProgram" account. -func (inst *SetTokenBilling) GetSystemProgramAccount() *ag_solanago.AccountMeta { - return inst.AccountMetaSlice[3] -} - -func (inst SetTokenBilling) Build() *Instruction { - return &Instruction{BaseVariant: ag_binary.BaseVariant{ - Impl: inst, - TypeID: Instruction_SetTokenBilling, - }} -} - -// ValidateAndBuild validates the instruction parameters and accounts; -// if there is a validation error, it returns the error. -// Otherwise, it builds and returns the instruction. -func (inst SetTokenBilling) ValidateAndBuild() (*Instruction, error) { - if err := inst.Validate(); err != nil { - return nil, err - } - return inst.Build(), nil -} - -func (inst *SetTokenBilling) Validate() error { - // Check whether all (required) parameters are set: - { - if inst.ChainSelector == nil { - return errors.New("ChainSelector parameter is not set") - } - if inst.Mint == nil { - return errors.New("Mint parameter is not set") - } - if inst.Cfg == nil { - return errors.New("Cfg parameter is not set") - } - } - - // Check whether all (required) accounts are set: - { - if inst.AccountMetaSlice[0] == nil { - return errors.New("accounts.Config is not set") - } - if inst.AccountMetaSlice[1] == nil { - return errors.New("accounts.PerChainPerTokenConfig is not set") - } - if inst.AccountMetaSlice[2] == nil { - return errors.New("accounts.Authority is not set") - } - if inst.AccountMetaSlice[3] == nil { - return errors.New("accounts.SystemProgram is not set") - } - } - return nil -} - -func (inst *SetTokenBilling) EncodeToTree(parent ag_treeout.Branches) { - parent.Child(ag_format.Program(ProgramName, ProgramID)). - // - ParentFunc(func(programBranch ag_treeout.Branches) { - programBranch.Child(ag_format.Instruction("SetTokenBilling")). - // - ParentFunc(func(instructionBranch ag_treeout.Branches) { - - // Parameters of the instruction: - instructionBranch.Child("Params[len=3]").ParentFunc(func(paramsBranch ag_treeout.Branches) { - paramsBranch.Child(ag_format.Param("ChainSelector", *inst.ChainSelector)) - paramsBranch.Child(ag_format.Param(" Mint", *inst.Mint)) - paramsBranch.Child(ag_format.Param(" Cfg", *inst.Cfg)) - }) - - // Accounts of the instruction: - instructionBranch.Child("Accounts[len=4]").ParentFunc(func(accountsBranch ag_treeout.Branches) { - accountsBranch.Child(ag_format.Meta(" config", inst.AccountMetaSlice[0])) - accountsBranch.Child(ag_format.Meta("perChainPerTokenConfig", inst.AccountMetaSlice[1])) - accountsBranch.Child(ag_format.Meta(" authority", inst.AccountMetaSlice[2])) - accountsBranch.Child(ag_format.Meta(" systemProgram", inst.AccountMetaSlice[3])) - }) - }) - }) -} - -func (obj SetTokenBilling) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { - // Serialize `ChainSelector` param: - err = encoder.Encode(obj.ChainSelector) - if err != nil { - return err - } - // Serialize `Mint` param: - err = encoder.Encode(obj.Mint) - if err != nil { - return err - } - // Serialize `Cfg` param: - err = encoder.Encode(obj.Cfg) - if err != nil { - return err - } - return nil -} -func (obj *SetTokenBilling) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { - // Deserialize `ChainSelector`: - err = decoder.Decode(&obj.ChainSelector) - if err != nil { - return err - } - // Deserialize `Mint`: - err = decoder.Decode(&obj.Mint) - if err != nil { - return err - } - // Deserialize `Cfg`: - err = decoder.Decode(&obj.Cfg) - if err != nil { - return err - } - return nil -} - -// NewSetTokenBillingInstruction declares a new SetTokenBilling instruction with the provided parameters and accounts. -func NewSetTokenBillingInstruction( - // Parameters: - chainSelector uint64, - mint ag_solanago.PublicKey, - cfg TokenBilling, - // Accounts: - config ag_solanago.PublicKey, - perChainPerTokenConfig ag_solanago.PublicKey, - authority ag_solanago.PublicKey, - systemProgram ag_solanago.PublicKey) *SetTokenBilling { - return NewSetTokenBillingInstructionBuilder(). - SetChainSelector(chainSelector). - SetMint(mint). - SetCfg(cfg). - SetConfigAccount(config). - SetPerChainPerTokenConfigAccount(perChainPerTokenConfig). - SetAuthorityAccount(authority). - SetSystemProgramAccount(systemProgram) -} diff --git a/core/capabilities/ccip/ccipsolana/ccip_router/SetTokenBilling_test.go b/core/capabilities/ccip/ccipsolana/ccip_router/SetTokenBilling_test.go deleted file mode 100644 index aff9d60f3d3..00000000000 --- a/core/capabilities/ccip/ccipsolana/ccip_router/SetTokenBilling_test.go +++ /dev/null @@ -1,32 +0,0 @@ -// Code generated by https://github.com/gagliardetto/anchor-go. DO NOT EDIT. - -package ccip_router - -import ( - "bytes" - ag_gofuzz "github.com/gagliardetto/gofuzz" - ag_require "github.com/stretchr/testify/require" - "strconv" - "testing" -) - -func TestEncodeDecode_SetTokenBilling(t *testing.T) { - fu := ag_gofuzz.New().NilChance(0) - for i := 0; i < 1; i++ { - t.Run("SetTokenBilling"+strconv.Itoa(i), func(t *testing.T) { - { - params := new(SetTokenBilling) - fu.Fuzz(params) - params.AccountMetaSlice = nil - buf := new(bytes.Buffer) - err := encodeT(*params, buf) - ag_require.NoError(t, err) - got := new(SetTokenBilling) - err = decodeT(got, buf.Bytes()) - got.AccountMetaSlice = nil - ag_require.NoError(t, err) - ag_require.Equal(t, params, got) - } - }) - } -} diff --git a/core/capabilities/ccip/ccipsolana/ccip_router/TransferAdminRoleTokenAdminRegistry.go b/core/capabilities/ccip/ccipsolana/ccip_router/TransferAdminRoleTokenAdminRegistry.go deleted file mode 100644 index 269a086456d..00000000000 --- a/core/capabilities/ccip/ccipsolana/ccip_router/TransferAdminRoleTokenAdminRegistry.go +++ /dev/null @@ -1,169 +0,0 @@ -// Code generated by https://github.com/gagliardetto/anchor-go. DO NOT EDIT. - -package ccip_router - -import ( - "errors" - ag_binary "github.com/gagliardetto/binary" - ag_solanago "github.com/gagliardetto/solana-go" - ag_format "github.com/gagliardetto/solana-go/text/format" - ag_treeout "github.com/gagliardetto/treeout" -) - -// The Admin can transfer the Admin Role of the Token Admin Registry -type TransferAdminRoleTokenAdminRegistry struct { - Mint *ag_solanago.PublicKey - NewAdmin *ag_solanago.PublicKey - - // [0] = [WRITE] tokenAdminRegistry - // - // [1] = [WRITE, SIGNER] authority - ag_solanago.AccountMetaSlice `bin:"-" borsh_skip:"true"` -} - -// NewTransferAdminRoleTokenAdminRegistryInstructionBuilder creates a new `TransferAdminRoleTokenAdminRegistry` instruction builder. -func NewTransferAdminRoleTokenAdminRegistryInstructionBuilder() *TransferAdminRoleTokenAdminRegistry { - nd := &TransferAdminRoleTokenAdminRegistry{ - AccountMetaSlice: make(ag_solanago.AccountMetaSlice, 2), - } - return nd -} - -// SetMint sets the "mint" parameter. -func (inst *TransferAdminRoleTokenAdminRegistry) SetMint(mint ag_solanago.PublicKey) *TransferAdminRoleTokenAdminRegistry { - inst.Mint = &mint - return inst -} - -// SetNewAdmin sets the "newAdmin" parameter. -func (inst *TransferAdminRoleTokenAdminRegistry) SetNewAdmin(newAdmin ag_solanago.PublicKey) *TransferAdminRoleTokenAdminRegistry { - inst.NewAdmin = &newAdmin - return inst -} - -// SetTokenAdminRegistryAccount sets the "tokenAdminRegistry" account. -func (inst *TransferAdminRoleTokenAdminRegistry) SetTokenAdminRegistryAccount(tokenAdminRegistry ag_solanago.PublicKey) *TransferAdminRoleTokenAdminRegistry { - inst.AccountMetaSlice[0] = ag_solanago.Meta(tokenAdminRegistry).WRITE() - return inst -} - -// GetTokenAdminRegistryAccount gets the "tokenAdminRegistry" account. -func (inst *TransferAdminRoleTokenAdminRegistry) GetTokenAdminRegistryAccount() *ag_solanago.AccountMeta { - return inst.AccountMetaSlice[0] -} - -// SetAuthorityAccount sets the "authority" account. -func (inst *TransferAdminRoleTokenAdminRegistry) SetAuthorityAccount(authority ag_solanago.PublicKey) *TransferAdminRoleTokenAdminRegistry { - inst.AccountMetaSlice[1] = ag_solanago.Meta(authority).WRITE().SIGNER() - return inst -} - -// GetAuthorityAccount gets the "authority" account. -func (inst *TransferAdminRoleTokenAdminRegistry) GetAuthorityAccount() *ag_solanago.AccountMeta { - return inst.AccountMetaSlice[1] -} - -func (inst TransferAdminRoleTokenAdminRegistry) Build() *Instruction { - return &Instruction{BaseVariant: ag_binary.BaseVariant{ - Impl: inst, - TypeID: Instruction_TransferAdminRoleTokenAdminRegistry, - }} -} - -// ValidateAndBuild validates the instruction parameters and accounts; -// if there is a validation error, it returns the error. -// Otherwise, it builds and returns the instruction. -func (inst TransferAdminRoleTokenAdminRegistry) ValidateAndBuild() (*Instruction, error) { - if err := inst.Validate(); err != nil { - return nil, err - } - return inst.Build(), nil -} - -func (inst *TransferAdminRoleTokenAdminRegistry) Validate() error { - // Check whether all (required) parameters are set: - { - if inst.Mint == nil { - return errors.New("Mint parameter is not set") - } - if inst.NewAdmin == nil { - return errors.New("NewAdmin parameter is not set") - } - } - - // Check whether all (required) accounts are set: - { - if inst.AccountMetaSlice[0] == nil { - return errors.New("accounts.TokenAdminRegistry is not set") - } - if inst.AccountMetaSlice[1] == nil { - return errors.New("accounts.Authority is not set") - } - } - return nil -} - -func (inst *TransferAdminRoleTokenAdminRegistry) EncodeToTree(parent ag_treeout.Branches) { - parent.Child(ag_format.Program(ProgramName, ProgramID)). - // - ParentFunc(func(programBranch ag_treeout.Branches) { - programBranch.Child(ag_format.Instruction("TransferAdminRoleTokenAdminRegistry")). - // - ParentFunc(func(instructionBranch ag_treeout.Branches) { - - // Parameters of the instruction: - instructionBranch.Child("Params[len=2]").ParentFunc(func(paramsBranch ag_treeout.Branches) { - paramsBranch.Child(ag_format.Param(" Mint", *inst.Mint)) - paramsBranch.Child(ag_format.Param("NewAdmin", *inst.NewAdmin)) - }) - - // Accounts of the instruction: - instructionBranch.Child("Accounts[len=2]").ParentFunc(func(accountsBranch ag_treeout.Branches) { - accountsBranch.Child(ag_format.Meta("tokenAdminRegistry", inst.AccountMetaSlice[0])) - accountsBranch.Child(ag_format.Meta(" authority", inst.AccountMetaSlice[1])) - }) - }) - }) -} - -func (obj TransferAdminRoleTokenAdminRegistry) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { - // Serialize `Mint` param: - err = encoder.Encode(obj.Mint) - if err != nil { - return err - } - // Serialize `NewAdmin` param: - err = encoder.Encode(obj.NewAdmin) - if err != nil { - return err - } - return nil -} -func (obj *TransferAdminRoleTokenAdminRegistry) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { - // Deserialize `Mint`: - err = decoder.Decode(&obj.Mint) - if err != nil { - return err - } - // Deserialize `NewAdmin`: - err = decoder.Decode(&obj.NewAdmin) - if err != nil { - return err - } - return nil -} - -// NewTransferAdminRoleTokenAdminRegistryInstruction declares a new TransferAdminRoleTokenAdminRegistry instruction with the provided parameters and accounts. -func NewTransferAdminRoleTokenAdminRegistryInstruction( - // Parameters: - mint ag_solanago.PublicKey, - newAdmin ag_solanago.PublicKey, - // Accounts: - tokenAdminRegistry ag_solanago.PublicKey, - authority ag_solanago.PublicKey) *TransferAdminRoleTokenAdminRegistry { - return NewTransferAdminRoleTokenAdminRegistryInstructionBuilder(). - SetMint(mint). - SetNewAdmin(newAdmin). - SetTokenAdminRegistryAccount(tokenAdminRegistry). - SetAuthorityAccount(authority) -} diff --git a/core/capabilities/ccip/ccipsolana/ccip_router/TransferAdminRoleTokenAdminRegistry_test.go b/core/capabilities/ccip/ccipsolana/ccip_router/TransferAdminRoleTokenAdminRegistry_test.go deleted file mode 100644 index e52c1a9983e..00000000000 --- a/core/capabilities/ccip/ccipsolana/ccip_router/TransferAdminRoleTokenAdminRegistry_test.go +++ /dev/null @@ -1,32 +0,0 @@ -// Code generated by https://github.com/gagliardetto/anchor-go. DO NOT EDIT. - -package ccip_router - -import ( - "bytes" - ag_gofuzz "github.com/gagliardetto/gofuzz" - ag_require "github.com/stretchr/testify/require" - "strconv" - "testing" -) - -func TestEncodeDecode_TransferAdminRoleTokenAdminRegistry(t *testing.T) { - fu := ag_gofuzz.New().NilChance(0) - for i := 0; i < 1; i++ { - t.Run("TransferAdminRoleTokenAdminRegistry"+strconv.Itoa(i), func(t *testing.T) { - { - params := new(TransferAdminRoleTokenAdminRegistry) - fu.Fuzz(params) - params.AccountMetaSlice = nil - buf := new(bytes.Buffer) - err := encodeT(*params, buf) - ag_require.NoError(t, err) - got := new(TransferAdminRoleTokenAdminRegistry) - err = decodeT(got, buf.Bytes()) - got.AccountMetaSlice = nil - ag_require.NoError(t, err) - ag_require.Equal(t, params, got) - } - }) - } -} diff --git a/core/capabilities/ccip/ccipsolana/ccip_router/TransferOwnership.go b/core/capabilities/ccip/ccipsolana/ccip_router/TransferOwnership.go deleted file mode 100644 index 37a129be90c..00000000000 --- a/core/capabilities/ccip/ccipsolana/ccip_router/TransferOwnership.go +++ /dev/null @@ -1,146 +0,0 @@ -// Code generated by https://github.com/gagliardetto/anchor-go. DO NOT EDIT. - -package ccip_router - -import ( - "errors" - ag_binary "github.com/gagliardetto/binary" - ag_solanago "github.com/gagliardetto/solana-go" - ag_format "github.com/gagliardetto/solana-go/text/format" - ag_treeout "github.com/gagliardetto/treeout" -) - -// TransferOwnership is the `transferOwnership` instruction. -type TransferOwnership struct { - ProposedOwner *ag_solanago.PublicKey - - // [0] = [WRITE] config - // - // [1] = [SIGNER] authority - ag_solanago.AccountMetaSlice `bin:"-" borsh_skip:"true"` -} - -// NewTransferOwnershipInstructionBuilder creates a new `TransferOwnership` instruction builder. -func NewTransferOwnershipInstructionBuilder() *TransferOwnership { - nd := &TransferOwnership{ - AccountMetaSlice: make(ag_solanago.AccountMetaSlice, 2), - } - return nd -} - -// SetProposedOwner sets the "proposedOwner" parameter. -func (inst *TransferOwnership) SetProposedOwner(proposedOwner ag_solanago.PublicKey) *TransferOwnership { - inst.ProposedOwner = &proposedOwner - return inst -} - -// SetConfigAccount sets the "config" account. -func (inst *TransferOwnership) SetConfigAccount(config ag_solanago.PublicKey) *TransferOwnership { - inst.AccountMetaSlice[0] = ag_solanago.Meta(config).WRITE() - return inst -} - -// GetConfigAccount gets the "config" account. -func (inst *TransferOwnership) GetConfigAccount() *ag_solanago.AccountMeta { - return inst.AccountMetaSlice[0] -} - -// SetAuthorityAccount sets the "authority" account. -func (inst *TransferOwnership) SetAuthorityAccount(authority ag_solanago.PublicKey) *TransferOwnership { - inst.AccountMetaSlice[1] = ag_solanago.Meta(authority).SIGNER() - return inst -} - -// GetAuthorityAccount gets the "authority" account. -func (inst *TransferOwnership) GetAuthorityAccount() *ag_solanago.AccountMeta { - return inst.AccountMetaSlice[1] -} - -func (inst TransferOwnership) Build() *Instruction { - return &Instruction{BaseVariant: ag_binary.BaseVariant{ - Impl: inst, - TypeID: Instruction_TransferOwnership, - }} -} - -// ValidateAndBuild validates the instruction parameters and accounts; -// if there is a validation error, it returns the error. -// Otherwise, it builds and returns the instruction. -func (inst TransferOwnership) ValidateAndBuild() (*Instruction, error) { - if err := inst.Validate(); err != nil { - return nil, err - } - return inst.Build(), nil -} - -func (inst *TransferOwnership) Validate() error { - // Check whether all (required) parameters are set: - { - if inst.ProposedOwner == nil { - return errors.New("ProposedOwner parameter is not set") - } - } - - // Check whether all (required) accounts are set: - { - if inst.AccountMetaSlice[0] == nil { - return errors.New("accounts.Config is not set") - } - if inst.AccountMetaSlice[1] == nil { - return errors.New("accounts.Authority is not set") - } - } - return nil -} - -func (inst *TransferOwnership) EncodeToTree(parent ag_treeout.Branches) { - parent.Child(ag_format.Program(ProgramName, ProgramID)). - // - ParentFunc(func(programBranch ag_treeout.Branches) { - programBranch.Child(ag_format.Instruction("TransferOwnership")). - // - ParentFunc(func(instructionBranch ag_treeout.Branches) { - - // Parameters of the instruction: - instructionBranch.Child("Params[len=1]").ParentFunc(func(paramsBranch ag_treeout.Branches) { - paramsBranch.Child(ag_format.Param("ProposedOwner", *inst.ProposedOwner)) - }) - - // Accounts of the instruction: - instructionBranch.Child("Accounts[len=2]").ParentFunc(func(accountsBranch ag_treeout.Branches) { - accountsBranch.Child(ag_format.Meta(" config", inst.AccountMetaSlice[0])) - accountsBranch.Child(ag_format.Meta("authority", inst.AccountMetaSlice[1])) - }) - }) - }) -} - -func (obj TransferOwnership) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { - // Serialize `ProposedOwner` param: - err = encoder.Encode(obj.ProposedOwner) - if err != nil { - return err - } - return nil -} -func (obj *TransferOwnership) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { - // Deserialize `ProposedOwner`: - err = decoder.Decode(&obj.ProposedOwner) - if err != nil { - return err - } - return nil -} - -// NewTransferOwnershipInstruction declares a new TransferOwnership instruction with the provided parameters and accounts. -func NewTransferOwnershipInstruction( - // Parameters: - proposedOwner ag_solanago.PublicKey, - // Accounts: - config ag_solanago.PublicKey, - authority ag_solanago.PublicKey) *TransferOwnership { - return NewTransferOwnershipInstructionBuilder(). - SetProposedOwner(proposedOwner). - SetConfigAccount(config). - SetAuthorityAccount(authority) -} diff --git a/core/capabilities/ccip/ccipsolana/ccip_router/TransferOwnership_test.go b/core/capabilities/ccip/ccipsolana/ccip_router/TransferOwnership_test.go deleted file mode 100644 index 38ea4ea34f1..00000000000 --- a/core/capabilities/ccip/ccipsolana/ccip_router/TransferOwnership_test.go +++ /dev/null @@ -1,32 +0,0 @@ -// Code generated by https://github.com/gagliardetto/anchor-go. DO NOT EDIT. - -package ccip_router - -import ( - "bytes" - ag_gofuzz "github.com/gagliardetto/gofuzz" - ag_require "github.com/stretchr/testify/require" - "strconv" - "testing" -) - -func TestEncodeDecode_TransferOwnership(t *testing.T) { - fu := ag_gofuzz.New().NilChance(0) - for i := 0; i < 1; i++ { - t.Run("TransferOwnership"+strconv.Itoa(i), func(t *testing.T) { - { - params := new(TransferOwnership) - fu.Fuzz(params) - params.AccountMetaSlice = nil - buf := new(bytes.Buffer) - err := encodeT(*params, buf) - ag_require.NoError(t, err) - got := new(TransferOwnership) - err = decodeT(got, buf.Bytes()) - got.AccountMetaSlice = nil - ag_require.NoError(t, err) - ag_require.Equal(t, params, got) - } - }) - } -} diff --git a/core/capabilities/ccip/ccipsolana/ccip_router/UpdateDefaultAllowOutOfOrderExecution.go b/core/capabilities/ccip/ccipsolana/ccip_router/UpdateDefaultAllowOutOfOrderExecution.go deleted file mode 100644 index 87e10696877..00000000000 --- a/core/capabilities/ccip/ccipsolana/ccip_router/UpdateDefaultAllowOutOfOrderExecution.go +++ /dev/null @@ -1,165 +0,0 @@ -// Code generated by https://github.com/gagliardetto/anchor-go. DO NOT EDIT. - -package ccip_router - -import ( - "errors" - ag_binary "github.com/gagliardetto/binary" - ag_solanago "github.com/gagliardetto/solana-go" - ag_format "github.com/gagliardetto/solana-go/text/format" - ag_treeout "github.com/gagliardetto/treeout" -) - -// The Admin can update the configuration of the Router, in this case the Default Allow Out Of Order Execution (True/False) -type UpdateDefaultAllowOutOfOrderExecution struct { - NewAllowOutOfOrderExecution *bool - - // [0] = [WRITE] config - // - // [1] = [SIGNER] authority - // - // [2] = [] systemProgram - ag_solanago.AccountMetaSlice `bin:"-" borsh_skip:"true"` -} - -// NewUpdateDefaultAllowOutOfOrderExecutionInstructionBuilder creates a new `UpdateDefaultAllowOutOfOrderExecution` instruction builder. -func NewUpdateDefaultAllowOutOfOrderExecutionInstructionBuilder() *UpdateDefaultAllowOutOfOrderExecution { - nd := &UpdateDefaultAllowOutOfOrderExecution{ - AccountMetaSlice: make(ag_solanago.AccountMetaSlice, 3), - } - return nd -} - -// SetNewAllowOutOfOrderExecution sets the "newAllowOutOfOrderExecution" parameter. -func (inst *UpdateDefaultAllowOutOfOrderExecution) SetNewAllowOutOfOrderExecution(newAllowOutOfOrderExecution bool) *UpdateDefaultAllowOutOfOrderExecution { - inst.NewAllowOutOfOrderExecution = &newAllowOutOfOrderExecution - return inst -} - -// SetConfigAccount sets the "config" account. -func (inst *UpdateDefaultAllowOutOfOrderExecution) SetConfigAccount(config ag_solanago.PublicKey) *UpdateDefaultAllowOutOfOrderExecution { - inst.AccountMetaSlice[0] = ag_solanago.Meta(config).WRITE() - return inst -} - -// GetConfigAccount gets the "config" account. -func (inst *UpdateDefaultAllowOutOfOrderExecution) GetConfigAccount() *ag_solanago.AccountMeta { - return inst.AccountMetaSlice[0] -} - -// SetAuthorityAccount sets the "authority" account. -func (inst *UpdateDefaultAllowOutOfOrderExecution) SetAuthorityAccount(authority ag_solanago.PublicKey) *UpdateDefaultAllowOutOfOrderExecution { - inst.AccountMetaSlice[1] = ag_solanago.Meta(authority).SIGNER() - return inst -} - -// GetAuthorityAccount gets the "authority" account. -func (inst *UpdateDefaultAllowOutOfOrderExecution) GetAuthorityAccount() *ag_solanago.AccountMeta { - return inst.AccountMetaSlice[1] -} - -// SetSystemProgramAccount sets the "systemProgram" account. -func (inst *UpdateDefaultAllowOutOfOrderExecution) SetSystemProgramAccount(systemProgram ag_solanago.PublicKey) *UpdateDefaultAllowOutOfOrderExecution { - inst.AccountMetaSlice[2] = ag_solanago.Meta(systemProgram) - return inst -} - -// GetSystemProgramAccount gets the "systemProgram" account. -func (inst *UpdateDefaultAllowOutOfOrderExecution) GetSystemProgramAccount() *ag_solanago.AccountMeta { - return inst.AccountMetaSlice[2] -} - -func (inst UpdateDefaultAllowOutOfOrderExecution) Build() *Instruction { - return &Instruction{BaseVariant: ag_binary.BaseVariant{ - Impl: inst, - TypeID: Instruction_UpdateDefaultAllowOutOfOrderExecution, - }} -} - -// ValidateAndBuild validates the instruction parameters and accounts; -// if there is a validation error, it returns the error. -// Otherwise, it builds and returns the instruction. -func (inst UpdateDefaultAllowOutOfOrderExecution) ValidateAndBuild() (*Instruction, error) { - if err := inst.Validate(); err != nil { - return nil, err - } - return inst.Build(), nil -} - -func (inst *UpdateDefaultAllowOutOfOrderExecution) Validate() error { - // Check whether all (required) parameters are set: - { - if inst.NewAllowOutOfOrderExecution == nil { - return errors.New("NewAllowOutOfOrderExecution parameter is not set") - } - } - - // Check whether all (required) accounts are set: - { - if inst.AccountMetaSlice[0] == nil { - return errors.New("accounts.Config is not set") - } - if inst.AccountMetaSlice[1] == nil { - return errors.New("accounts.Authority is not set") - } - if inst.AccountMetaSlice[2] == nil { - return errors.New("accounts.SystemProgram is not set") - } - } - return nil -} - -func (inst *UpdateDefaultAllowOutOfOrderExecution) EncodeToTree(parent ag_treeout.Branches) { - parent.Child(ag_format.Program(ProgramName, ProgramID)). - // - ParentFunc(func(programBranch ag_treeout.Branches) { - programBranch.Child(ag_format.Instruction("UpdateDefaultAllowOutOfOrderExecution")). - // - ParentFunc(func(instructionBranch ag_treeout.Branches) { - - // Parameters of the instruction: - instructionBranch.Child("Params[len=1]").ParentFunc(func(paramsBranch ag_treeout.Branches) { - paramsBranch.Child(ag_format.Param("NewAllowOutOfOrderExecution", *inst.NewAllowOutOfOrderExecution)) - }) - - // Accounts of the instruction: - instructionBranch.Child("Accounts[len=3]").ParentFunc(func(accountsBranch ag_treeout.Branches) { - accountsBranch.Child(ag_format.Meta(" config", inst.AccountMetaSlice[0])) - accountsBranch.Child(ag_format.Meta(" authority", inst.AccountMetaSlice[1])) - accountsBranch.Child(ag_format.Meta("systemProgram", inst.AccountMetaSlice[2])) - }) - }) - }) -} - -func (obj UpdateDefaultAllowOutOfOrderExecution) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { - // Serialize `NewAllowOutOfOrderExecution` param: - err = encoder.Encode(obj.NewAllowOutOfOrderExecution) - if err != nil { - return err - } - return nil -} -func (obj *UpdateDefaultAllowOutOfOrderExecution) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { - // Deserialize `NewAllowOutOfOrderExecution`: - err = decoder.Decode(&obj.NewAllowOutOfOrderExecution) - if err != nil { - return err - } - return nil -} - -// NewUpdateDefaultAllowOutOfOrderExecutionInstruction declares a new UpdateDefaultAllowOutOfOrderExecution instruction with the provided parameters and accounts. -func NewUpdateDefaultAllowOutOfOrderExecutionInstruction( - // Parameters: - newAllowOutOfOrderExecution bool, - // Accounts: - config ag_solanago.PublicKey, - authority ag_solanago.PublicKey, - systemProgram ag_solanago.PublicKey) *UpdateDefaultAllowOutOfOrderExecution { - return NewUpdateDefaultAllowOutOfOrderExecutionInstructionBuilder(). - SetNewAllowOutOfOrderExecution(newAllowOutOfOrderExecution). - SetConfigAccount(config). - SetAuthorityAccount(authority). - SetSystemProgramAccount(systemProgram) -} diff --git a/core/capabilities/ccip/ccipsolana/ccip_router/UpdateDefaultAllowOutOfOrderExecution_test.go b/core/capabilities/ccip/ccipsolana/ccip_router/UpdateDefaultAllowOutOfOrderExecution_test.go deleted file mode 100644 index 70a0674748c..00000000000 --- a/core/capabilities/ccip/ccipsolana/ccip_router/UpdateDefaultAllowOutOfOrderExecution_test.go +++ /dev/null @@ -1,32 +0,0 @@ -// Code generated by https://github.com/gagliardetto/anchor-go. DO NOT EDIT. - -package ccip_router - -import ( - "bytes" - ag_gofuzz "github.com/gagliardetto/gofuzz" - ag_require "github.com/stretchr/testify/require" - "strconv" - "testing" -) - -func TestEncodeDecode_UpdateDefaultAllowOutOfOrderExecution(t *testing.T) { - fu := ag_gofuzz.New().NilChance(0) - for i := 0; i < 1; i++ { - t.Run("UpdateDefaultAllowOutOfOrderExecution"+strconv.Itoa(i), func(t *testing.T) { - { - params := new(UpdateDefaultAllowOutOfOrderExecution) - fu.Fuzz(params) - params.AccountMetaSlice = nil - buf := new(bytes.Buffer) - err := encodeT(*params, buf) - ag_require.NoError(t, err) - got := new(UpdateDefaultAllowOutOfOrderExecution) - err = decodeT(got, buf.Bytes()) - got.AccountMetaSlice = nil - ag_require.NoError(t, err) - ag_require.Equal(t, params, got) - } - }) - } -} diff --git a/core/capabilities/ccip/ccipsolana/ccip_router/UpdateDefaultGasLimit.go b/core/capabilities/ccip/ccipsolana/ccip_router/UpdateDefaultGasLimit.go deleted file mode 100644 index c1791685884..00000000000 --- a/core/capabilities/ccip/ccipsolana/ccip_router/UpdateDefaultGasLimit.go +++ /dev/null @@ -1,165 +0,0 @@ -// Code generated by https://github.com/gagliardetto/anchor-go. DO NOT EDIT. - -package ccip_router - -import ( - "errors" - ag_binary "github.com/gagliardetto/binary" - ag_solanago "github.com/gagliardetto/solana-go" - ag_format "github.com/gagliardetto/solana-go/text/format" - ag_treeout "github.com/gagliardetto/treeout" -) - -// The Admin can update the configuration of the Router, in this case the Default Gas Limit -type UpdateDefaultGasLimit struct { - NewGasLimit *ag_binary.Uint128 - - // [0] = [WRITE] config - // - // [1] = [SIGNER] authority - // - // [2] = [] systemProgram - ag_solanago.AccountMetaSlice `bin:"-" borsh_skip:"true"` -} - -// NewUpdateDefaultGasLimitInstructionBuilder creates a new `UpdateDefaultGasLimit` instruction builder. -func NewUpdateDefaultGasLimitInstructionBuilder() *UpdateDefaultGasLimit { - nd := &UpdateDefaultGasLimit{ - AccountMetaSlice: make(ag_solanago.AccountMetaSlice, 3), - } - return nd -} - -// SetNewGasLimit sets the "newGasLimit" parameter. -func (inst *UpdateDefaultGasLimit) SetNewGasLimit(newGasLimit ag_binary.Uint128) *UpdateDefaultGasLimit { - inst.NewGasLimit = &newGasLimit - return inst -} - -// SetConfigAccount sets the "config" account. -func (inst *UpdateDefaultGasLimit) SetConfigAccount(config ag_solanago.PublicKey) *UpdateDefaultGasLimit { - inst.AccountMetaSlice[0] = ag_solanago.Meta(config).WRITE() - return inst -} - -// GetConfigAccount gets the "config" account. -func (inst *UpdateDefaultGasLimit) GetConfigAccount() *ag_solanago.AccountMeta { - return inst.AccountMetaSlice[0] -} - -// SetAuthorityAccount sets the "authority" account. -func (inst *UpdateDefaultGasLimit) SetAuthorityAccount(authority ag_solanago.PublicKey) *UpdateDefaultGasLimit { - inst.AccountMetaSlice[1] = ag_solanago.Meta(authority).SIGNER() - return inst -} - -// GetAuthorityAccount gets the "authority" account. -func (inst *UpdateDefaultGasLimit) GetAuthorityAccount() *ag_solanago.AccountMeta { - return inst.AccountMetaSlice[1] -} - -// SetSystemProgramAccount sets the "systemProgram" account. -func (inst *UpdateDefaultGasLimit) SetSystemProgramAccount(systemProgram ag_solanago.PublicKey) *UpdateDefaultGasLimit { - inst.AccountMetaSlice[2] = ag_solanago.Meta(systemProgram) - return inst -} - -// GetSystemProgramAccount gets the "systemProgram" account. -func (inst *UpdateDefaultGasLimit) GetSystemProgramAccount() *ag_solanago.AccountMeta { - return inst.AccountMetaSlice[2] -} - -func (inst UpdateDefaultGasLimit) Build() *Instruction { - return &Instruction{BaseVariant: ag_binary.BaseVariant{ - Impl: inst, - TypeID: Instruction_UpdateDefaultGasLimit, - }} -} - -// ValidateAndBuild validates the instruction parameters and accounts; -// if there is a validation error, it returns the error. -// Otherwise, it builds and returns the instruction. -func (inst UpdateDefaultGasLimit) ValidateAndBuild() (*Instruction, error) { - if err := inst.Validate(); err != nil { - return nil, err - } - return inst.Build(), nil -} - -func (inst *UpdateDefaultGasLimit) Validate() error { - // Check whether all (required) parameters are set: - { - if inst.NewGasLimit == nil { - return errors.New("NewGasLimit parameter is not set") - } - } - - // Check whether all (required) accounts are set: - { - if inst.AccountMetaSlice[0] == nil { - return errors.New("accounts.Config is not set") - } - if inst.AccountMetaSlice[1] == nil { - return errors.New("accounts.Authority is not set") - } - if inst.AccountMetaSlice[2] == nil { - return errors.New("accounts.SystemProgram is not set") - } - } - return nil -} - -func (inst *UpdateDefaultGasLimit) EncodeToTree(parent ag_treeout.Branches) { - parent.Child(ag_format.Program(ProgramName, ProgramID)). - // - ParentFunc(func(programBranch ag_treeout.Branches) { - programBranch.Child(ag_format.Instruction("UpdateDefaultGasLimit")). - // - ParentFunc(func(instructionBranch ag_treeout.Branches) { - - // Parameters of the instruction: - instructionBranch.Child("Params[len=1]").ParentFunc(func(paramsBranch ag_treeout.Branches) { - paramsBranch.Child(ag_format.Param("NewGasLimit", *inst.NewGasLimit)) - }) - - // Accounts of the instruction: - instructionBranch.Child("Accounts[len=3]").ParentFunc(func(accountsBranch ag_treeout.Branches) { - accountsBranch.Child(ag_format.Meta(" config", inst.AccountMetaSlice[0])) - accountsBranch.Child(ag_format.Meta(" authority", inst.AccountMetaSlice[1])) - accountsBranch.Child(ag_format.Meta("systemProgram", inst.AccountMetaSlice[2])) - }) - }) - }) -} - -func (obj UpdateDefaultGasLimit) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { - // Serialize `NewGasLimit` param: - err = encoder.Encode(obj.NewGasLimit) - if err != nil { - return err - } - return nil -} -func (obj *UpdateDefaultGasLimit) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { - // Deserialize `NewGasLimit`: - err = decoder.Decode(&obj.NewGasLimit) - if err != nil { - return err - } - return nil -} - -// NewUpdateDefaultGasLimitInstruction declares a new UpdateDefaultGasLimit instruction with the provided parameters and accounts. -func NewUpdateDefaultGasLimitInstruction( - // Parameters: - newGasLimit ag_binary.Uint128, - // Accounts: - config ag_solanago.PublicKey, - authority ag_solanago.PublicKey, - systemProgram ag_solanago.PublicKey) *UpdateDefaultGasLimit { - return NewUpdateDefaultGasLimitInstructionBuilder(). - SetNewGasLimit(newGasLimit). - SetConfigAccount(config). - SetAuthorityAccount(authority). - SetSystemProgramAccount(systemProgram) -} diff --git a/core/capabilities/ccip/ccipsolana/ccip_router/UpdateDefaultGasLimit_test.go b/core/capabilities/ccip/ccipsolana/ccip_router/UpdateDefaultGasLimit_test.go deleted file mode 100644 index f323c69e6b8..00000000000 --- a/core/capabilities/ccip/ccipsolana/ccip_router/UpdateDefaultGasLimit_test.go +++ /dev/null @@ -1,32 +0,0 @@ -// Code generated by https://github.com/gagliardetto/anchor-go. DO NOT EDIT. - -package ccip_router - -import ( - "bytes" - ag_gofuzz "github.com/gagliardetto/gofuzz" - ag_require "github.com/stretchr/testify/require" - "strconv" - "testing" -) - -func TestEncodeDecode_UpdateDefaultGasLimit(t *testing.T) { - fu := ag_gofuzz.New().NilChance(0) - for i := 0; i < 1; i++ { - t.Run("UpdateDefaultGasLimit"+strconv.Itoa(i), func(t *testing.T) { - { - params := new(UpdateDefaultGasLimit) - fu.Fuzz(params) - params.AccountMetaSlice = nil - buf := new(bytes.Buffer) - err := encodeT(*params, buf) - ag_require.NoError(t, err) - got := new(UpdateDefaultGasLimit) - err = decodeT(got, buf.Bytes()) - got.AccountMetaSlice = nil - ag_require.NoError(t, err) - ag_require.Equal(t, params, got) - } - }) - } -} diff --git a/core/capabilities/ccip/ccipsolana/ccip_router/UpdateEnableManualExecutionAfter.go b/core/capabilities/ccip/ccipsolana/ccip_router/UpdateEnableManualExecutionAfter.go deleted file mode 100644 index 5adb9d10708..00000000000 --- a/core/capabilities/ccip/ccipsolana/ccip_router/UpdateEnableManualExecutionAfter.go +++ /dev/null @@ -1,165 +0,0 @@ -// Code generated by https://github.com/gagliardetto/anchor-go. DO NOT EDIT. - -package ccip_router - -import ( - "errors" - ag_binary "github.com/gagliardetto/binary" - ag_solanago "github.com/gagliardetto/solana-go" - ag_format "github.com/gagliardetto/solana-go/text/format" - ag_treeout "github.com/gagliardetto/treeout" -) - -// The Admin can update the configuration of the Router, in this case the Enable Manual Execution After -type UpdateEnableManualExecutionAfter struct { - NewEnableManualExecutionAfter *int64 - - // [0] = [WRITE] config - // - // [1] = [SIGNER] authority - // - // [2] = [] systemProgram - ag_solanago.AccountMetaSlice `bin:"-" borsh_skip:"true"` -} - -// NewUpdateEnableManualExecutionAfterInstructionBuilder creates a new `UpdateEnableManualExecutionAfter` instruction builder. -func NewUpdateEnableManualExecutionAfterInstructionBuilder() *UpdateEnableManualExecutionAfter { - nd := &UpdateEnableManualExecutionAfter{ - AccountMetaSlice: make(ag_solanago.AccountMetaSlice, 3), - } - return nd -} - -// SetNewEnableManualExecutionAfter sets the "newEnableManualExecutionAfter" parameter. -func (inst *UpdateEnableManualExecutionAfter) SetNewEnableManualExecutionAfter(newEnableManualExecutionAfter int64) *UpdateEnableManualExecutionAfter { - inst.NewEnableManualExecutionAfter = &newEnableManualExecutionAfter - return inst -} - -// SetConfigAccount sets the "config" account. -func (inst *UpdateEnableManualExecutionAfter) SetConfigAccount(config ag_solanago.PublicKey) *UpdateEnableManualExecutionAfter { - inst.AccountMetaSlice[0] = ag_solanago.Meta(config).WRITE() - return inst -} - -// GetConfigAccount gets the "config" account. -func (inst *UpdateEnableManualExecutionAfter) GetConfigAccount() *ag_solanago.AccountMeta { - return inst.AccountMetaSlice[0] -} - -// SetAuthorityAccount sets the "authority" account. -func (inst *UpdateEnableManualExecutionAfter) SetAuthorityAccount(authority ag_solanago.PublicKey) *UpdateEnableManualExecutionAfter { - inst.AccountMetaSlice[1] = ag_solanago.Meta(authority).SIGNER() - return inst -} - -// GetAuthorityAccount gets the "authority" account. -func (inst *UpdateEnableManualExecutionAfter) GetAuthorityAccount() *ag_solanago.AccountMeta { - return inst.AccountMetaSlice[1] -} - -// SetSystemProgramAccount sets the "systemProgram" account. -func (inst *UpdateEnableManualExecutionAfter) SetSystemProgramAccount(systemProgram ag_solanago.PublicKey) *UpdateEnableManualExecutionAfter { - inst.AccountMetaSlice[2] = ag_solanago.Meta(systemProgram) - return inst -} - -// GetSystemProgramAccount gets the "systemProgram" account. -func (inst *UpdateEnableManualExecutionAfter) GetSystemProgramAccount() *ag_solanago.AccountMeta { - return inst.AccountMetaSlice[2] -} - -func (inst UpdateEnableManualExecutionAfter) Build() *Instruction { - return &Instruction{BaseVariant: ag_binary.BaseVariant{ - Impl: inst, - TypeID: Instruction_UpdateEnableManualExecutionAfter, - }} -} - -// ValidateAndBuild validates the instruction parameters and accounts; -// if there is a validation error, it returns the error. -// Otherwise, it builds and returns the instruction. -func (inst UpdateEnableManualExecutionAfter) ValidateAndBuild() (*Instruction, error) { - if err := inst.Validate(); err != nil { - return nil, err - } - return inst.Build(), nil -} - -func (inst *UpdateEnableManualExecutionAfter) Validate() error { - // Check whether all (required) parameters are set: - { - if inst.NewEnableManualExecutionAfter == nil { - return errors.New("NewEnableManualExecutionAfter parameter is not set") - } - } - - // Check whether all (required) accounts are set: - { - if inst.AccountMetaSlice[0] == nil { - return errors.New("accounts.Config is not set") - } - if inst.AccountMetaSlice[1] == nil { - return errors.New("accounts.Authority is not set") - } - if inst.AccountMetaSlice[2] == nil { - return errors.New("accounts.SystemProgram is not set") - } - } - return nil -} - -func (inst *UpdateEnableManualExecutionAfter) EncodeToTree(parent ag_treeout.Branches) { - parent.Child(ag_format.Program(ProgramName, ProgramID)). - // - ParentFunc(func(programBranch ag_treeout.Branches) { - programBranch.Child(ag_format.Instruction("UpdateEnableManualExecutionAfter")). - // - ParentFunc(func(instructionBranch ag_treeout.Branches) { - - // Parameters of the instruction: - instructionBranch.Child("Params[len=1]").ParentFunc(func(paramsBranch ag_treeout.Branches) { - paramsBranch.Child(ag_format.Param("NewEnableManualExecutionAfter", *inst.NewEnableManualExecutionAfter)) - }) - - // Accounts of the instruction: - instructionBranch.Child("Accounts[len=3]").ParentFunc(func(accountsBranch ag_treeout.Branches) { - accountsBranch.Child(ag_format.Meta(" config", inst.AccountMetaSlice[0])) - accountsBranch.Child(ag_format.Meta(" authority", inst.AccountMetaSlice[1])) - accountsBranch.Child(ag_format.Meta("systemProgram", inst.AccountMetaSlice[2])) - }) - }) - }) -} - -func (obj UpdateEnableManualExecutionAfter) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { - // Serialize `NewEnableManualExecutionAfter` param: - err = encoder.Encode(obj.NewEnableManualExecutionAfter) - if err != nil { - return err - } - return nil -} -func (obj *UpdateEnableManualExecutionAfter) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { - // Deserialize `NewEnableManualExecutionAfter`: - err = decoder.Decode(&obj.NewEnableManualExecutionAfter) - if err != nil { - return err - } - return nil -} - -// NewUpdateEnableManualExecutionAfterInstruction declares a new UpdateEnableManualExecutionAfter instruction with the provided parameters and accounts. -func NewUpdateEnableManualExecutionAfterInstruction( - // Parameters: - newEnableManualExecutionAfter int64, - // Accounts: - config ag_solanago.PublicKey, - authority ag_solanago.PublicKey, - systemProgram ag_solanago.PublicKey) *UpdateEnableManualExecutionAfter { - return NewUpdateEnableManualExecutionAfterInstructionBuilder(). - SetNewEnableManualExecutionAfter(newEnableManualExecutionAfter). - SetConfigAccount(config). - SetAuthorityAccount(authority). - SetSystemProgramAccount(systemProgram) -} diff --git a/core/capabilities/ccip/ccipsolana/ccip_router/UpdateEnableManualExecutionAfter_test.go b/core/capabilities/ccip/ccipsolana/ccip_router/UpdateEnableManualExecutionAfter_test.go deleted file mode 100644 index cc37505f599..00000000000 --- a/core/capabilities/ccip/ccipsolana/ccip_router/UpdateEnableManualExecutionAfter_test.go +++ /dev/null @@ -1,32 +0,0 @@ -// Code generated by https://github.com/gagliardetto/anchor-go. DO NOT EDIT. - -package ccip_router - -import ( - "bytes" - ag_gofuzz "github.com/gagliardetto/gofuzz" - ag_require "github.com/stretchr/testify/require" - "strconv" - "testing" -) - -func TestEncodeDecode_UpdateEnableManualExecutionAfter(t *testing.T) { - fu := ag_gofuzz.New().NilChance(0) - for i := 0; i < 1; i++ { - t.Run("UpdateEnableManualExecutionAfter"+strconv.Itoa(i), func(t *testing.T) { - { - params := new(UpdateEnableManualExecutionAfter) - fu.Fuzz(params) - params.AccountMetaSlice = nil - buf := new(bytes.Buffer) - err := encodeT(*params, buf) - ag_require.NoError(t, err) - got := new(UpdateEnableManualExecutionAfter) - err = decodeT(got, buf.Bytes()) - got.AccountMetaSlice = nil - ag_require.NoError(t, err) - ag_require.Equal(t, params, got) - } - }) - } -} diff --git a/core/capabilities/ccip/ccipsolana/ccip_router/UpdateSolanaChainSelector.go b/core/capabilities/ccip/ccipsolana/ccip_router/UpdateSolanaChainSelector.go deleted file mode 100644 index 58796f4e381..00000000000 --- a/core/capabilities/ccip/ccipsolana/ccip_router/UpdateSolanaChainSelector.go +++ /dev/null @@ -1,165 +0,0 @@ -// Code generated by https://github.com/gagliardetto/anchor-go. DO NOT EDIT. - -package ccip_router - -import ( - "errors" - ag_binary "github.com/gagliardetto/binary" - ag_solanago "github.com/gagliardetto/solana-go" - ag_format "github.com/gagliardetto/solana-go/text/format" - ag_treeout "github.com/gagliardetto/treeout" -) - -// The Admin can update the configuration of the Router, in this case the Solana Chain Selector -type UpdateSolanaChainSelector struct { - NewChainSelector *uint64 - - // [0] = [WRITE] config - // - // [1] = [SIGNER] authority - // - // [2] = [] systemProgram - ag_solanago.AccountMetaSlice `bin:"-" borsh_skip:"true"` -} - -// NewUpdateSolanaChainSelectorInstructionBuilder creates a new `UpdateSolanaChainSelector` instruction builder. -func NewUpdateSolanaChainSelectorInstructionBuilder() *UpdateSolanaChainSelector { - nd := &UpdateSolanaChainSelector{ - AccountMetaSlice: make(ag_solanago.AccountMetaSlice, 3), - } - return nd -} - -// SetNewChainSelector sets the "newChainSelector" parameter. -func (inst *UpdateSolanaChainSelector) SetNewChainSelector(newChainSelector uint64) *UpdateSolanaChainSelector { - inst.NewChainSelector = &newChainSelector - return inst -} - -// SetConfigAccount sets the "config" account. -func (inst *UpdateSolanaChainSelector) SetConfigAccount(config ag_solanago.PublicKey) *UpdateSolanaChainSelector { - inst.AccountMetaSlice[0] = ag_solanago.Meta(config).WRITE() - return inst -} - -// GetConfigAccount gets the "config" account. -func (inst *UpdateSolanaChainSelector) GetConfigAccount() *ag_solanago.AccountMeta { - return inst.AccountMetaSlice[0] -} - -// SetAuthorityAccount sets the "authority" account. -func (inst *UpdateSolanaChainSelector) SetAuthorityAccount(authority ag_solanago.PublicKey) *UpdateSolanaChainSelector { - inst.AccountMetaSlice[1] = ag_solanago.Meta(authority).SIGNER() - return inst -} - -// GetAuthorityAccount gets the "authority" account. -func (inst *UpdateSolanaChainSelector) GetAuthorityAccount() *ag_solanago.AccountMeta { - return inst.AccountMetaSlice[1] -} - -// SetSystemProgramAccount sets the "systemProgram" account. -func (inst *UpdateSolanaChainSelector) SetSystemProgramAccount(systemProgram ag_solanago.PublicKey) *UpdateSolanaChainSelector { - inst.AccountMetaSlice[2] = ag_solanago.Meta(systemProgram) - return inst -} - -// GetSystemProgramAccount gets the "systemProgram" account. -func (inst *UpdateSolanaChainSelector) GetSystemProgramAccount() *ag_solanago.AccountMeta { - return inst.AccountMetaSlice[2] -} - -func (inst UpdateSolanaChainSelector) Build() *Instruction { - return &Instruction{BaseVariant: ag_binary.BaseVariant{ - Impl: inst, - TypeID: Instruction_UpdateSolanaChainSelector, - }} -} - -// ValidateAndBuild validates the instruction parameters and accounts; -// if there is a validation error, it returns the error. -// Otherwise, it builds and returns the instruction. -func (inst UpdateSolanaChainSelector) ValidateAndBuild() (*Instruction, error) { - if err := inst.Validate(); err != nil { - return nil, err - } - return inst.Build(), nil -} - -func (inst *UpdateSolanaChainSelector) Validate() error { - // Check whether all (required) parameters are set: - { - if inst.NewChainSelector == nil { - return errors.New("NewChainSelector parameter is not set") - } - } - - // Check whether all (required) accounts are set: - { - if inst.AccountMetaSlice[0] == nil { - return errors.New("accounts.Config is not set") - } - if inst.AccountMetaSlice[1] == nil { - return errors.New("accounts.Authority is not set") - } - if inst.AccountMetaSlice[2] == nil { - return errors.New("accounts.SystemProgram is not set") - } - } - return nil -} - -func (inst *UpdateSolanaChainSelector) EncodeToTree(parent ag_treeout.Branches) { - parent.Child(ag_format.Program(ProgramName, ProgramID)). - // - ParentFunc(func(programBranch ag_treeout.Branches) { - programBranch.Child(ag_format.Instruction("UpdateSolanaChainSelector")). - // - ParentFunc(func(instructionBranch ag_treeout.Branches) { - - // Parameters of the instruction: - instructionBranch.Child("Params[len=1]").ParentFunc(func(paramsBranch ag_treeout.Branches) { - paramsBranch.Child(ag_format.Param("NewChainSelector", *inst.NewChainSelector)) - }) - - // Accounts of the instruction: - instructionBranch.Child("Accounts[len=3]").ParentFunc(func(accountsBranch ag_treeout.Branches) { - accountsBranch.Child(ag_format.Meta(" config", inst.AccountMetaSlice[0])) - accountsBranch.Child(ag_format.Meta(" authority", inst.AccountMetaSlice[1])) - accountsBranch.Child(ag_format.Meta("systemProgram", inst.AccountMetaSlice[2])) - }) - }) - }) -} - -func (obj UpdateSolanaChainSelector) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { - // Serialize `NewChainSelector` param: - err = encoder.Encode(obj.NewChainSelector) - if err != nil { - return err - } - return nil -} -func (obj *UpdateSolanaChainSelector) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { - // Deserialize `NewChainSelector`: - err = decoder.Decode(&obj.NewChainSelector) - if err != nil { - return err - } - return nil -} - -// NewUpdateSolanaChainSelectorInstruction declares a new UpdateSolanaChainSelector instruction with the provided parameters and accounts. -func NewUpdateSolanaChainSelectorInstruction( - // Parameters: - newChainSelector uint64, - // Accounts: - config ag_solanago.PublicKey, - authority ag_solanago.PublicKey, - systemProgram ag_solanago.PublicKey) *UpdateSolanaChainSelector { - return NewUpdateSolanaChainSelectorInstructionBuilder(). - SetNewChainSelector(newChainSelector). - SetConfigAccount(config). - SetAuthorityAccount(authority). - SetSystemProgramAccount(systemProgram) -} diff --git a/core/capabilities/ccip/ccipsolana/ccip_router/UpdateSolanaChainSelector_test.go b/core/capabilities/ccip/ccipsolana/ccip_router/UpdateSolanaChainSelector_test.go deleted file mode 100644 index 00901a4a9af..00000000000 --- a/core/capabilities/ccip/ccipsolana/ccip_router/UpdateSolanaChainSelector_test.go +++ /dev/null @@ -1,32 +0,0 @@ -// Code generated by https://github.com/gagliardetto/anchor-go. DO NOT EDIT. - -package ccip_router - -import ( - "bytes" - ag_gofuzz "github.com/gagliardetto/gofuzz" - ag_require "github.com/stretchr/testify/require" - "strconv" - "testing" -) - -func TestEncodeDecode_UpdateSolanaChainSelector(t *testing.T) { - fu := ag_gofuzz.New().NilChance(0) - for i := 0; i < 1; i++ { - t.Run("UpdateSolanaChainSelector"+strconv.Itoa(i), func(t *testing.T) { - { - params := new(UpdateSolanaChainSelector) - fu.Fuzz(params) - params.AccountMetaSlice = nil - buf := new(bytes.Buffer) - err := encodeT(*params, buf) - ag_require.NoError(t, err) - got := new(UpdateSolanaChainSelector) - err = decodeT(got, buf.Bytes()) - got.AccountMetaSlice = nil - ag_require.NoError(t, err) - ag_require.Equal(t, params, got) - } - }) - } -} diff --git a/core/capabilities/ccip/ccipsolana/ccip_router/accounts.go b/core/capabilities/ccip/ccipsolana/ccip_router/accounts.go deleted file mode 100644 index 44c43c1d364..00000000000 --- a/core/capabilities/ccip/ccipsolana/ccip_router/accounts.go +++ /dev/null @@ -1,661 +0,0 @@ -// Code generated by https://github.com/gagliardetto/anchor-go. DO NOT EDIT. - -package ccip_router - -import ( - "fmt" - ag_binary "github.com/gagliardetto/binary" - ag_solanago "github.com/gagliardetto/solana-go" -) - -type Config struct { - Version uint8 - DefaultAllowOutOfOrderExecution uint8 - Padding0 [6]uint8 - SolanaChainSelector uint64 - DefaultGasLimit ag_binary.Uint128 - Padding1 [8]uint8 - Owner ag_solanago.PublicKey - ProposedOwner ag_solanago.PublicKey - EnableManualExecutionAfter int64 - Padding2 [8]uint8 - Ocr3 [2]Ocr3Config -} - -var ConfigDiscriminator = [8]byte{155, 12, 170, 224, 30, 250, 204, 130} - -func (obj Config) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { - // Write account discriminator: - err = encoder.WriteBytes(ConfigDiscriminator[:], false) - if err != nil { - return err - } - // Serialize `Version` param: - err = encoder.Encode(obj.Version) - if err != nil { - return err - } - // Serialize `DefaultAllowOutOfOrderExecution` param: - err = encoder.Encode(obj.DefaultAllowOutOfOrderExecution) - if err != nil { - return err - } - // Serialize `Padding0` param: - err = encoder.Encode(obj.Padding0) - if err != nil { - return err - } - // Serialize `SolanaChainSelector` param: - err = encoder.Encode(obj.SolanaChainSelector) - if err != nil { - return err - } - // Serialize `DefaultGasLimit` param: - err = encoder.Encode(obj.DefaultGasLimit) - if err != nil { - return err - } - // Serialize `Padding1` param: - err = encoder.Encode(obj.Padding1) - if err != nil { - return err - } - // Serialize `Owner` param: - err = encoder.Encode(obj.Owner) - if err != nil { - return err - } - // Serialize `ProposedOwner` param: - err = encoder.Encode(obj.ProposedOwner) - if err != nil { - return err - } - // Serialize `EnableManualExecutionAfter` param: - err = encoder.Encode(obj.EnableManualExecutionAfter) - if err != nil { - return err - } - // Serialize `Padding2` param: - err = encoder.Encode(obj.Padding2) - if err != nil { - return err - } - // Serialize `Ocr3` param: - err = encoder.Encode(obj.Ocr3) - if err != nil { - return err - } - return nil -} - -func (obj *Config) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { - // Read and check account discriminator: - { - discriminator, err := decoder.ReadTypeID() - if err != nil { - return err - } - if !discriminator.Equal(ConfigDiscriminator[:]) { - return fmt.Errorf( - "wrong discriminator: wanted %s, got %s", - "[155 12 170 224 30 250 204 130]", - fmt.Sprint(discriminator[:])) - } - } - // Deserialize `Version`: - err = decoder.Decode(&obj.Version) - if err != nil { - return err - } - // Deserialize `DefaultAllowOutOfOrderExecution`: - err = decoder.Decode(&obj.DefaultAllowOutOfOrderExecution) - if err != nil { - return err - } - // Deserialize `Padding0`: - err = decoder.Decode(&obj.Padding0) - if err != nil { - return err - } - // Deserialize `SolanaChainSelector`: - err = decoder.Decode(&obj.SolanaChainSelector) - if err != nil { - return err - } - // Deserialize `DefaultGasLimit`: - err = decoder.Decode(&obj.DefaultGasLimit) - if err != nil { - return err - } - // Deserialize `Padding1`: - err = decoder.Decode(&obj.Padding1) - if err != nil { - return err - } - // Deserialize `Owner`: - err = decoder.Decode(&obj.Owner) - if err != nil { - return err - } - // Deserialize `ProposedOwner`: - err = decoder.Decode(&obj.ProposedOwner) - if err != nil { - return err - } - // Deserialize `EnableManualExecutionAfter`: - err = decoder.Decode(&obj.EnableManualExecutionAfter) - if err != nil { - return err - } - // Deserialize `Padding2`: - err = decoder.Decode(&obj.Padding2) - if err != nil { - return err - } - // Deserialize `Ocr3`: - err = decoder.Decode(&obj.Ocr3) - if err != nil { - return err - } - return nil -} - -type ChainState struct { - Version uint8 - SourceChainConfig SourceChainConfig - DestChainConfig DestChainConfig -} - -var ChainStateDiscriminator = [8]byte{130, 46, 94, 156, 79, 53, 170, 50} - -func (obj ChainState) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { - // Write account discriminator: - err = encoder.WriteBytes(ChainStateDiscriminator[:], false) - if err != nil { - return err - } - // Serialize `Version` param: - err = encoder.Encode(obj.Version) - if err != nil { - return err - } - // Serialize `SourceChainConfig` param: - err = encoder.Encode(obj.SourceChainConfig) - if err != nil { - return err - } - // Serialize `DestChainConfig` param: - err = encoder.Encode(obj.DestChainConfig) - if err != nil { - return err - } - return nil -} - -func (obj *ChainState) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { - // Read and check account discriminator: - { - discriminator, err := decoder.ReadTypeID() - if err != nil { - return err - } - if !discriminator.Equal(ChainStateDiscriminator[:]) { - return fmt.Errorf( - "wrong discriminator: wanted %s, got %s", - "[130 46 94 156 79 53 170 50]", - fmt.Sprint(discriminator[:])) - } - } - // Deserialize `Version`: - err = decoder.Decode(&obj.Version) - if err != nil { - return err - } - // Deserialize `SourceChainConfig`: - err = decoder.Decode(&obj.SourceChainConfig) - if err != nil { - return err - } - // Deserialize `DestChainConfig`: - err = decoder.Decode(&obj.DestChainConfig) - if err != nil { - return err - } - return nil -} - -type Nonce struct { - Version uint8 - Counter uint64 -} - -var NonceDiscriminator = [8]byte{143, 197, 147, 95, 106, 165, 50, 43} - -func (obj Nonce) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { - // Write account discriminator: - err = encoder.WriteBytes(NonceDiscriminator[:], false) - if err != nil { - return err - } - // Serialize `Version` param: - err = encoder.Encode(obj.Version) - if err != nil { - return err - } - // Serialize `Counter` param: - err = encoder.Encode(obj.Counter) - if err != nil { - return err - } - return nil -} - -func (obj *Nonce) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { - // Read and check account discriminator: - { - discriminator, err := decoder.ReadTypeID() - if err != nil { - return err - } - if !discriminator.Equal(NonceDiscriminator[:]) { - return fmt.Errorf( - "wrong discriminator: wanted %s, got %s", - "[143 197 147 95 106 165 50 43]", - fmt.Sprint(discriminator[:])) - } - } - // Deserialize `Version`: - err = decoder.Decode(&obj.Version) - if err != nil { - return err - } - // Deserialize `Counter`: - err = decoder.Decode(&obj.Counter) - if err != nil { - return err - } - return nil -} - -type ExternalExecutionConfig struct{} - -var ExternalExecutionConfigDiscriminator = [8]byte{159, 157, 150, 212, 168, 103, 117, 39} - -func (obj ExternalExecutionConfig) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { - // Write account discriminator: - err = encoder.WriteBytes(ExternalExecutionConfigDiscriminator[:], false) - if err != nil { - return err - } - return nil -} - -func (obj *ExternalExecutionConfig) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { - // Read and check account discriminator: - { - discriminator, err := decoder.ReadTypeID() - if err != nil { - return err - } - if !discriminator.Equal(ExternalExecutionConfigDiscriminator[:]) { - return fmt.Errorf( - "wrong discriminator: wanted %s, got %s", - "[159 157 150 212 168 103 117 39]", - fmt.Sprint(discriminator[:])) - } - } - return nil -} - -type CommitReport struct { - Version uint8 - Timestamp int64 - MinMsgNr uint64 - MaxMsgNr uint64 - ExecutionStates ag_binary.Uint128 -} - -var CommitReportDiscriminator = [8]byte{46, 231, 247, 231, 174, 68, 34, 26} - -func (obj CommitReport) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { - // Write account discriminator: - err = encoder.WriteBytes(CommitReportDiscriminator[:], false) - if err != nil { - return err - } - // Serialize `Version` param: - err = encoder.Encode(obj.Version) - if err != nil { - return err - } - // Serialize `Timestamp` param: - err = encoder.Encode(obj.Timestamp) - if err != nil { - return err - } - // Serialize `MinMsgNr` param: - err = encoder.Encode(obj.MinMsgNr) - if err != nil { - return err - } - // Serialize `MaxMsgNr` param: - err = encoder.Encode(obj.MaxMsgNr) - if err != nil { - return err - } - // Serialize `ExecutionStates` param: - err = encoder.Encode(obj.ExecutionStates) - if err != nil { - return err - } - return nil -} - -func (obj *CommitReport) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { - // Read and check account discriminator: - { - discriminator, err := decoder.ReadTypeID() - if err != nil { - return err - } - if !discriminator.Equal(CommitReportDiscriminator[:]) { - return fmt.Errorf( - "wrong discriminator: wanted %s, got %s", - "[46 231 247 231 174 68 34 26]", - fmt.Sprint(discriminator[:])) - } - } - // Deserialize `Version`: - err = decoder.Decode(&obj.Version) - if err != nil { - return err - } - // Deserialize `Timestamp`: - err = decoder.Decode(&obj.Timestamp) - if err != nil { - return err - } - // Deserialize `MinMsgNr`: - err = decoder.Decode(&obj.MinMsgNr) - if err != nil { - return err - } - // Deserialize `MaxMsgNr`: - err = decoder.Decode(&obj.MaxMsgNr) - if err != nil { - return err - } - // Deserialize `ExecutionStates`: - err = decoder.Decode(&obj.ExecutionStates) - if err != nil { - return err - } - return nil -} - -type PerChainPerTokenConfig struct { - Version uint8 - ChainSelector uint64 - Mint ag_solanago.PublicKey - Billing TokenBilling -} - -var PerChainPerTokenConfigDiscriminator = [8]byte{183, 88, 20, 99, 246, 46, 51, 230} - -func (obj PerChainPerTokenConfig) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { - // Write account discriminator: - err = encoder.WriteBytes(PerChainPerTokenConfigDiscriminator[:], false) - if err != nil { - return err - } - // Serialize `Version` param: - err = encoder.Encode(obj.Version) - if err != nil { - return err - } - // Serialize `ChainSelector` param: - err = encoder.Encode(obj.ChainSelector) - if err != nil { - return err - } - // Serialize `Mint` param: - err = encoder.Encode(obj.Mint) - if err != nil { - return err - } - // Serialize `Billing` param: - err = encoder.Encode(obj.Billing) - if err != nil { - return err - } - return nil -} - -func (obj *PerChainPerTokenConfig) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { - // Read and check account discriminator: - { - discriminator, err := decoder.ReadTypeID() - if err != nil { - return err - } - if !discriminator.Equal(PerChainPerTokenConfigDiscriminator[:]) { - return fmt.Errorf( - "wrong discriminator: wanted %s, got %s", - "[183 88 20 99 246 46 51 230]", - fmt.Sprint(discriminator[:])) - } - } - // Deserialize `Version`: - err = decoder.Decode(&obj.Version) - if err != nil { - return err - } - // Deserialize `ChainSelector`: - err = decoder.Decode(&obj.ChainSelector) - if err != nil { - return err - } - // Deserialize `Mint`: - err = decoder.Decode(&obj.Mint) - if err != nil { - return err - } - // Deserialize `Billing`: - err = decoder.Decode(&obj.Billing) - if err != nil { - return err - } - return nil -} - -type BillingTokenConfig struct { - Version uint8 - Enabled bool - UsdPerToken TimestampedPackedU224 - PremiumMultiplierWeiPerEth uint64 -} - -var BillingTokenConfigDiscriminator = [8]byte{191, 91, 1, 0, 93, 250, 239, 41} - -func (obj BillingTokenConfig) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { - // Write account discriminator: - err = encoder.WriteBytes(BillingTokenConfigDiscriminator[:], false) - if err != nil { - return err - } - // Serialize `Version` param: - err = encoder.Encode(obj.Version) - if err != nil { - return err - } - // Serialize `Enabled` param: - err = encoder.Encode(obj.Enabled) - if err != nil { - return err - } - // Serialize `UsdPerToken` param: - err = encoder.Encode(obj.UsdPerToken) - if err != nil { - return err - } - // Serialize `PremiumMultiplierWeiPerEth` param: - err = encoder.Encode(obj.PremiumMultiplierWeiPerEth) - if err != nil { - return err - } - return nil -} - -func (obj *BillingTokenConfig) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { - // Read and check account discriminator: - { - discriminator, err := decoder.ReadTypeID() - if err != nil { - return err - } - if !discriminator.Equal(BillingTokenConfigDiscriminator[:]) { - return fmt.Errorf( - "wrong discriminator: wanted %s, got %s", - "[191 91 1 0 93 250 239 41]", - fmt.Sprint(discriminator[:])) - } - } - // Deserialize `Version`: - err = decoder.Decode(&obj.Version) - if err != nil { - return err - } - // Deserialize `Enabled`: - err = decoder.Decode(&obj.Enabled) - if err != nil { - return err - } - // Deserialize `UsdPerToken`: - err = decoder.Decode(&obj.UsdPerToken) - if err != nil { - return err - } - // Deserialize `PremiumMultiplierWeiPerEth`: - err = decoder.Decode(&obj.PremiumMultiplierWeiPerEth) - if err != nil { - return err - } - return nil -} - -type TokenAdminRegistry struct { - Version uint8 - Administrator ag_solanago.PublicKey - PendingAdministrator *ag_solanago.PublicKey `bin:"optional"` - TokenPoolProgram *ag_solanago.PublicKey `bin:"optional"` -} - -var TokenAdminRegistryDiscriminator = [8]byte{70, 92, 207, 200, 76, 17, 57, 114} - -func (obj TokenAdminRegistry) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { - // Write account discriminator: - err = encoder.WriteBytes(TokenAdminRegistryDiscriminator[:], false) - if err != nil { - return err - } - // Serialize `Version` param: - err = encoder.Encode(obj.Version) - if err != nil { - return err - } - // Serialize `Administrator` param: - err = encoder.Encode(obj.Administrator) - if err != nil { - return err - } - // Serialize `PendingAdministrator` param (optional): - { - if obj.PendingAdministrator == nil { - err = encoder.WriteBool(false) - if err != nil { - return err - } - } else { - err = encoder.WriteBool(true) - if err != nil { - return err - } - err = encoder.Encode(obj.PendingAdministrator) - if err != nil { - return err - } - } - } - // Serialize `TokenPoolProgram` param (optional): - { - if obj.TokenPoolProgram == nil { - err = encoder.WriteBool(false) - if err != nil { - return err - } - } else { - err = encoder.WriteBool(true) - if err != nil { - return err - } - err = encoder.Encode(obj.TokenPoolProgram) - if err != nil { - return err - } - } - } - return nil -} - -func (obj *TokenAdminRegistry) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { - // Read and check account discriminator: - { - discriminator, err := decoder.ReadTypeID() - if err != nil { - return err - } - if !discriminator.Equal(TokenAdminRegistryDiscriminator[:]) { - return fmt.Errorf( - "wrong discriminator: wanted %s, got %s", - "[70 92 207 200 76 17 57 114]", - fmt.Sprint(discriminator[:])) - } - } - // Deserialize `Version`: - err = decoder.Decode(&obj.Version) - if err != nil { - return err - } - // Deserialize `Administrator`: - err = decoder.Decode(&obj.Administrator) - if err != nil { - return err - } - // Deserialize `PendingAdministrator` (optional): - { - ok, err := decoder.ReadBool() - if err != nil { - return err - } - if ok { - err = decoder.Decode(&obj.PendingAdministrator) - if err != nil { - return err - } - } - } - // Deserialize `TokenPoolProgram` (optional): - { - ok, err := decoder.ReadBool() - if err != nil { - return err - } - if ok { - err = decoder.Decode(&obj.TokenPoolProgram) - if err != nil { - return err - } - } - } - return nil -} diff --git a/core/capabilities/ccip/ccipsolana/ccip_router/instructions.go b/core/capabilities/ccip/ccipsolana/ccip_router/instructions.go deleted file mode 100644 index 395e39da2ea..00000000000 --- a/core/capabilities/ccip/ccipsolana/ccip_router/instructions.go +++ /dev/null @@ -1,304 +0,0 @@ -// This is the Collapsed Router Program for CCIP. -// As it's upgradable persisting the same program id, there is no need to have an indirection of a Proxy Program. -// This Router handles both the OnRamp and OffRamp flow of the CCIP Messages. -// Code generated by https://github.com/gagliardetto/anchor-go. DO NOT EDIT. - -package ccip_router - -import ( - "bytes" - "fmt" - ag_spew "github.com/davecgh/go-spew/spew" - ag_binary "github.com/gagliardetto/binary" - ag_solanago "github.com/gagliardetto/solana-go" - ag_text "github.com/gagliardetto/solana-go/text" - ag_treeout "github.com/gagliardetto/treeout" -) - -var ProgramID ag_solanago.PublicKey - -func SetProgramID(pubkey ag_solanago.PublicKey) { - ProgramID = pubkey - ag_solanago.RegisterInstructionDecoder(ProgramID, registryDecodeInstruction) -} - -const ProgramName = "CcipRouter" - -func init() { - if !ProgramID.IsZero() { - ag_solanago.RegisterInstructionDecoder(ProgramID, registryDecodeInstruction) - } -} - -var ( - // The initialization is responsibility of Admin, nothing more than calling this method should be done first. - Instruction_Initialize = ag_binary.TypeID([8]byte{175, 175, 109, 31, 13, 152, 155, 237}) - - Instruction_TransferOwnership = ag_binary.TypeID([8]byte{65, 177, 215, 73, 53, 45, 99, 47}) - - Instruction_AcceptOwnership = ag_binary.TypeID([8]byte{172, 23, 43, 13, 238, 213, 85, 150}) - - // The Admin needs to add any new chain supported (this means both OnRamp and OffRamp). - Instruction_AddChainSelector = ag_binary.TypeID([8]byte{28, 60, 171, 0, 195, 113, 56, 7}) - - // The Admin is the only one able to enable or disable the chain selector - Instruction_DisableChainSelector = ag_binary.TypeID([8]byte{24, 245, 159, 178, 139, 200, 133, 218}) - - // The Admin is the only one able to enable or disable the chain selector - Instruction_EnableChainSelector = ag_binary.TypeID([8]byte{29, 175, 195, 14, 137, 66, 194, 25}) - - // The Admin can update the configuration of the Router, in this case the Solana Chain Selector - Instruction_UpdateSolanaChainSelector = ag_binary.TypeID([8]byte{128, 198, 143, 222, 43, 55, 119, 106}) - - // The Admin can update the configuration of the Router, in this case the Default Gas Limit - Instruction_UpdateDefaultGasLimit = ag_binary.TypeID([8]byte{201, 34, 231, 229, 247, 252, 77, 210}) - - // The Admin can update the configuration of the Router, in this case the Default Allow Out Of Order Execution (True/False) - Instruction_UpdateDefaultAllowOutOfOrderExecution = ag_binary.TypeID([8]byte{44, 54, 136, 71, 177, 17, 18, 241}) - - // The Admin can update the configuration of the Router, in this case the Enable Manual Execution After - Instruction_UpdateEnableManualExecutionAfter = ag_binary.TypeID([8]byte{157, 236, 73, 92, 84, 197, 152, 105}) - - // The CCIP Admin or the Mint Authority of the Token can register the Token Admin Registry - Instruction_RegisterTokenAdminRegistryViaGetCcipAdmin = ag_binary.TypeID([8]byte{46, 246, 21, 58, 175, 69, 40, 202}) - - // The Token's mint_authority can register themselves to the Token Admin Registry - Instruction_RegisterTokenAdminRegistryViaOwner = ag_binary.TypeID([8]byte{85, 191, 10, 113, 134, 138, 144, 16}) - - // The administrator of the token can setup the token pool - Instruction_SetPool = ag_binary.TypeID([8]byte{119, 30, 14, 180, 115, 225, 167, 238}) - - // The Admin can transfer the Admin Role of the Token Admin Registry - Instruction_TransferAdminRoleTokenAdminRegistry = ag_binary.TypeID([8]byte{178, 98, 203, 181, 203, 107, 106, 14}) - - // The Pending Admin can accept the Admin Role of the Token Admin Registry - Instruction_AcceptAdminRoleTokenAdminRegistry = ag_binary.TypeID([8]byte{106, 240, 16, 173, 137, 213, 163, 246}) - - Instruction_SetTokenBilling = ag_binary.TypeID([8]byte{225, 230, 37, 71, 131, 209, 54, 230}) - - Instruction_SetOcrConfig = ag_binary.TypeID([8]byte{4, 131, 107, 110, 250, 158, 244, 200}) - - // ON RAMP FLOW - // The method name needs to be ccip_send with Anchor encoding. - // This function is called by the CCIP Sender Contract (or final user) to send a message to the CCIP Router. - // The size limit of data is 256 bytes. - // The message is sent to the receiver on the destination chain selector. - // This message emits the event CCIPSendRequested with all the necessary data to be retrieved by the OffChain Code - Instruction_CcipSend = ag_binary.TypeID([8]byte{108, 216, 134, 191, 249, 234, 33, 84}) - - // OFF RAMP FLOW - // - // The method name needs to be commit with Anchor encoding. - // - // This function is called by the OffChain when committing one Report to the Solana Router. - // In this Flow only one report is sent, the Commit Report. This is different as EVM does, - // this is because here all the chain state is stored in one account per Merkle Tree Root. - // So, to avoid having to send a dynamic size array of accounts, in this message only one Commit Report Account is sent. - // This message validates the signatures of the report and stores the Merkle Root in the Commit Report Account. - // The Report must contain an interval of messages, and the min of them must be the next sequence number expected. - // The max size of the interval is 64. - // This message emits two events: CommitReportAccepted and Transmitted. - Instruction_Commit = ag_binary.TypeID([8]byte{223, 140, 142, 165, 229, 208, 156, 74}) - - // OFF RAMP FLOW - // - // The method name needs to be execute with Anchor encoding. - // - // This function is called by the OffChain when executing one Report to the Solana Router. - // In this Flow only one message is sent, the Execution Report. This is different as EVM does, - // this is because there is no try/catch mechanism to allow batch execution. - // This message validates that the Merkle Tree Proof of the given message is correct and is stored in the Commit Report Account. - // The message must be untouched to be executed. - // This message emits the event ExecutionStateChanged with the new state of the message. - // Finally, executes the CPI instruction to the receiver program in the ccip_receive message. - Instruction_Execute = ag_binary.TypeID([8]byte{130, 221, 242, 154, 13, 193, 189, 29}) - - // When a message is not being executed, then the user can trigger the execution manually. - // No verification over the transmitter, but the message needs to be in some commit report. - Instruction_ManuallyExecute = ag_binary.TypeID([8]byte{238, 219, 224, 11, 226, 248, 47, 192}) -) - -// InstructionIDToName returns the name of the instruction given its ID. -func InstructionIDToName(id ag_binary.TypeID) string { - switch id { - case Instruction_Initialize: - return "Initialize" - case Instruction_TransferOwnership: - return "TransferOwnership" - case Instruction_AcceptOwnership: - return "AcceptOwnership" - case Instruction_AddChainSelector: - return "AddChainSelector" - case Instruction_DisableChainSelector: - return "DisableChainSelector" - case Instruction_EnableChainSelector: - return "EnableChainSelector" - case Instruction_UpdateSolanaChainSelector: - return "UpdateSolanaChainSelector" - case Instruction_UpdateDefaultGasLimit: - return "UpdateDefaultGasLimit" - case Instruction_UpdateDefaultAllowOutOfOrderExecution: - return "UpdateDefaultAllowOutOfOrderExecution" - case Instruction_UpdateEnableManualExecutionAfter: - return "UpdateEnableManualExecutionAfter" - case Instruction_RegisterTokenAdminRegistryViaGetCcipAdmin: - return "RegisterTokenAdminRegistryViaGetCcipAdmin" - case Instruction_RegisterTokenAdminRegistryViaOwner: - return "RegisterTokenAdminRegistryViaOwner" - case Instruction_SetPool: - return "SetPool" - case Instruction_TransferAdminRoleTokenAdminRegistry: - return "TransferAdminRoleTokenAdminRegistry" - case Instruction_AcceptAdminRoleTokenAdminRegistry: - return "AcceptAdminRoleTokenAdminRegistry" - case Instruction_SetTokenBilling: - return "SetTokenBilling" - case Instruction_SetOcrConfig: - return "SetOcrConfig" - case Instruction_CcipSend: - return "CcipSend" - case Instruction_Commit: - return "Commit" - case Instruction_Execute: - return "Execute" - case Instruction_ManuallyExecute: - return "ManuallyExecute" - default: - return "" - } -} - -type Instruction struct { - ag_binary.BaseVariant -} - -func (inst *Instruction) EncodeToTree(parent ag_treeout.Branches) { - if enToTree, ok := inst.Impl.(ag_text.EncodableToTree); ok { - enToTree.EncodeToTree(parent) - } else { - parent.Child(ag_spew.Sdump(inst)) - } -} - -var InstructionImplDef = ag_binary.NewVariantDefinition( - ag_binary.AnchorTypeIDEncoding, - []ag_binary.VariantType{ - { - "initialize", (*Initialize)(nil), - }, - { - "transfer_ownership", (*TransferOwnership)(nil), - }, - { - "accept_ownership", (*AcceptOwnership)(nil), - }, - { - "add_chain_selector", (*AddChainSelector)(nil), - }, - { - "disable_chain_selector", (*DisableChainSelector)(nil), - }, - { - "enable_chain_selector", (*EnableChainSelector)(nil), - }, - { - "update_solana_chain_selector", (*UpdateSolanaChainSelector)(nil), - }, - { - "update_default_gas_limit", (*UpdateDefaultGasLimit)(nil), - }, - { - "update_default_allow_out_of_order_execution", (*UpdateDefaultAllowOutOfOrderExecution)(nil), - }, - { - "update_enable_manual_execution_after", (*UpdateEnableManualExecutionAfter)(nil), - }, - { - "register_token_admin_registry_via_get_ccip_admin", (*RegisterTokenAdminRegistryViaGetCcipAdmin)(nil), - }, - { - "register_token_admin_registry_via_owner", (*RegisterTokenAdminRegistryViaOwner)(nil), - }, - { - "set_pool", (*SetPool)(nil), - }, - { - "transfer_admin_role_token_admin_registry", (*TransferAdminRoleTokenAdminRegistry)(nil), - }, - { - "accept_admin_role_token_admin_registry", (*AcceptAdminRoleTokenAdminRegistry)(nil), - }, - { - "set_token_billing", (*SetTokenBilling)(nil), - }, - { - "set_ocr_config", (*SetOcrConfig)(nil), - }, - { - "ccip_send", (*CcipSend)(nil), - }, - { - "commit", (*Commit)(nil), - }, - { - "execute", (*Execute)(nil), - }, - { - "manually_execute", (*ManuallyExecute)(nil), - }, - }, -) - -func (inst *Instruction) ProgramID() ag_solanago.PublicKey { - return ProgramID -} - -func (inst *Instruction) Accounts() (out []*ag_solanago.AccountMeta) { - return inst.Impl.(ag_solanago.AccountsGettable).GetAccounts() -} - -func (inst *Instruction) Data() ([]byte, error) { - buf := new(bytes.Buffer) - if err := ag_binary.NewBorshEncoder(buf).Encode(inst); err != nil { - return nil, fmt.Errorf("unable to encode instruction: %w", err) - } - return buf.Bytes(), nil -} - -func (inst *Instruction) TextEncode(encoder *ag_text.Encoder, option *ag_text.Option) error { - return encoder.Encode(inst.Impl, option) -} - -func (inst *Instruction) UnmarshalWithDecoder(decoder *ag_binary.Decoder) error { - return inst.BaseVariant.UnmarshalBinaryVariant(decoder, InstructionImplDef) -} - -func (inst *Instruction) MarshalWithEncoder(encoder *ag_binary.Encoder) error { - err := encoder.WriteBytes(inst.TypeID.Bytes(), false) - if err != nil { - return fmt.Errorf("unable to write variant type: %w", err) - } - return encoder.Encode(inst.Impl) -} - -func registryDecodeInstruction(accounts []*ag_solanago.AccountMeta, data []byte) (interface{}, error) { - inst, err := DecodeInstruction(accounts, data) - if err != nil { - return nil, err - } - return inst, nil -} - -func DecodeInstruction(accounts []*ag_solanago.AccountMeta, data []byte) (*Instruction, error) { - inst := new(Instruction) - if err := ag_binary.NewBorshDecoder(data).Decode(inst); err != nil { - return nil, fmt.Errorf("unable to decode instruction: %w", err) - } - if v, ok := inst.Impl.(ag_solanago.AccountsSettable); ok { - err := v.SetAccounts(accounts) - if err != nil { - return nil, fmt.Errorf("unable to set accounts for instruction: %w", err) - } - } - return inst, nil -} diff --git a/core/capabilities/ccip/ccipsolana/ccip_router/testing_utils.go b/core/capabilities/ccip/ccipsolana/ccip_router/testing_utils.go deleted file mode 100644 index aaecdf49bad..00000000000 --- a/core/capabilities/ccip/ccipsolana/ccip_router/testing_utils.go +++ /dev/null @@ -1,20 +0,0 @@ -// Code generated by https://github.com/gagliardetto/anchor-go. DO NOT EDIT. - -package ccip_router - -import ( - "bytes" - "fmt" - ag_binary "github.com/gagliardetto/binary" -) - -func encodeT(data interface{}, buf *bytes.Buffer) error { - if err := ag_binary.NewBorshEncoder(buf).Encode(data); err != nil { - return fmt.Errorf("unable to encode instruction: %w", err) - } - return nil -} - -func decodeT(dst interface{}, data []byte) error { - return ag_binary.NewBorshDecoder(data).Decode(dst) -} diff --git a/core/capabilities/ccip/ccipsolana/ccip_router/types.go b/core/capabilities/ccip/ccipsolana/ccip_router/types.go deleted file mode 100644 index 1c3167a1fcc..00000000000 --- a/core/capabilities/ccip/ccipsolana/ccip_router/types.go +++ /dev/null @@ -1,1817 +0,0 @@ -// Code generated by https://github.com/gagliardetto/anchor-go. DO NOT EDIT. - -package ccip_router - -import ( - ag_binary "github.com/gagliardetto/binary" - ag_solanago "github.com/gagliardetto/solana-go" -) - -type CommitInput struct { - PriceUpdates PriceUpdates - MerkleRoot MerkleRoot -} - -func (obj CommitInput) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { - // Serialize `PriceUpdates` param: - err = encoder.Encode(obj.PriceUpdates) - if err != nil { - return err - } - // Serialize `MerkleRoot` param: - err = encoder.Encode(obj.MerkleRoot) - if err != nil { - return err - } - return nil -} - -func (obj *CommitInput) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { - // Deserialize `PriceUpdates`: - err = decoder.Decode(&obj.PriceUpdates) - if err != nil { - return err - } - // Deserialize `MerkleRoot`: - err = decoder.Decode(&obj.MerkleRoot) - if err != nil { - return err - } - return nil -} - -type PriceUpdates struct { - TokenPriceUpdates []TokenPriceUpdate - GasPriceUpdates []GasPriceUpdate -} - -func (obj PriceUpdates) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { - // Serialize `TokenPriceUpdates` param: - err = encoder.Encode(obj.TokenPriceUpdates) - if err != nil { - return err - } - // Serialize `GasPriceUpdates` param: - err = encoder.Encode(obj.GasPriceUpdates) - if err != nil { - return err - } - return nil -} - -func (obj *PriceUpdates) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { - // Deserialize `TokenPriceUpdates`: - err = decoder.Decode(&obj.TokenPriceUpdates) - if err != nil { - return err - } - // Deserialize `GasPriceUpdates`: - err = decoder.Decode(&obj.GasPriceUpdates) - if err != nil { - return err - } - return nil -} - -type TokenPriceUpdate struct { - SourceToken ag_solanago.PublicKey - UsdPerToken [28]uint8 -} - -func (obj TokenPriceUpdate) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { - // Serialize `SourceToken` param: - err = encoder.Encode(obj.SourceToken) - if err != nil { - return err - } - // Serialize `UsdPerToken` param: - err = encoder.Encode(obj.UsdPerToken) - if err != nil { - return err - } - return nil -} - -func (obj *TokenPriceUpdate) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { - // Deserialize `SourceToken`: - err = decoder.Decode(&obj.SourceToken) - if err != nil { - return err - } - // Deserialize `UsdPerToken`: - err = decoder.Decode(&obj.UsdPerToken) - if err != nil { - return err - } - return nil -} - -type GasPriceUpdate struct { - DestChainSelector uint64 - UsdPerUnitGas [28]uint8 -} - -func (obj GasPriceUpdate) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { - // Serialize `DestChainSelector` param: - err = encoder.Encode(obj.DestChainSelector) - if err != nil { - return err - } - // Serialize `UsdPerUnitGas` param: - err = encoder.Encode(obj.UsdPerUnitGas) - if err != nil { - return err - } - return nil -} - -func (obj *GasPriceUpdate) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { - // Deserialize `DestChainSelector`: - err = decoder.Decode(&obj.DestChainSelector) - if err != nil { - return err - } - // Deserialize `UsdPerUnitGas`: - err = decoder.Decode(&obj.UsdPerUnitGas) - if err != nil { - return err - } - return nil -} - -type MerkleRoot struct { - SourceChainSelector uint64 - OnRampAddress []byte - MinSeqNr uint64 - MaxSeqNr uint64 - MerkleRoot [32]uint8 -} - -func (obj MerkleRoot) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { - // Serialize `SourceChainSelector` param: - err = encoder.Encode(obj.SourceChainSelector) - if err != nil { - return err - } - // Serialize `OnRampAddress` param: - err = encoder.Encode(obj.OnRampAddress) - if err != nil { - return err - } - // Serialize `MinSeqNr` param: - err = encoder.Encode(obj.MinSeqNr) - if err != nil { - return err - } - // Serialize `MaxSeqNr` param: - err = encoder.Encode(obj.MaxSeqNr) - if err != nil { - return err - } - // Serialize `MerkleRoot` param: - err = encoder.Encode(obj.MerkleRoot) - if err != nil { - return err - } - return nil -} - -func (obj *MerkleRoot) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { - // Deserialize `SourceChainSelector`: - err = decoder.Decode(&obj.SourceChainSelector) - if err != nil { - return err - } - // Deserialize `OnRampAddress`: - err = decoder.Decode(&obj.OnRampAddress) - if err != nil { - return err - } - // Deserialize `MinSeqNr`: - err = decoder.Decode(&obj.MinSeqNr) - if err != nil { - return err - } - // Deserialize `MaxSeqNr`: - err = decoder.Decode(&obj.MaxSeqNr) - if err != nil { - return err - } - // Deserialize `MerkleRoot`: - err = decoder.Decode(&obj.MerkleRoot) - if err != nil { - return err - } - return nil -} - -type Solana2AnyMessage struct { - Receiver []byte - Data []byte - TokenAmounts []SolanaTokenAmount - FeeToken ag_solanago.PublicKey - ExtraArgs ExtraArgsInput - TokenIndexes []byte -} - -func (obj Solana2AnyMessage) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { - // Serialize `Receiver` param: - err = encoder.Encode(obj.Receiver) - if err != nil { - return err - } - // Serialize `Data` param: - err = encoder.Encode(obj.Data) - if err != nil { - return err - } - // Serialize `TokenAmounts` param: - err = encoder.Encode(obj.TokenAmounts) - if err != nil { - return err - } - // Serialize `FeeToken` param: - err = encoder.Encode(obj.FeeToken) - if err != nil { - return err - } - // Serialize `ExtraArgs` param: - err = encoder.Encode(obj.ExtraArgs) - if err != nil { - return err - } - // Serialize `TokenIndexes` param: - err = encoder.Encode(obj.TokenIndexes) - if err != nil { - return err - } - return nil -} - -func (obj *Solana2AnyMessage) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { - // Deserialize `Receiver`: - err = decoder.Decode(&obj.Receiver) - if err != nil { - return err - } - // Deserialize `Data`: - err = decoder.Decode(&obj.Data) - if err != nil { - return err - } - // Deserialize `TokenAmounts`: - err = decoder.Decode(&obj.TokenAmounts) - if err != nil { - return err - } - // Deserialize `FeeToken`: - err = decoder.Decode(&obj.FeeToken) - if err != nil { - return err - } - // Deserialize `ExtraArgs`: - err = decoder.Decode(&obj.ExtraArgs) - if err != nil { - return err - } - // Deserialize `TokenIndexes`: - err = decoder.Decode(&obj.TokenIndexes) - if err != nil { - return err - } - return nil -} - -type SolanaTokenAmount struct { - Token ag_solanago.PublicKey - Amount uint64 -} - -func (obj SolanaTokenAmount) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { - // Serialize `Token` param: - err = encoder.Encode(obj.Token) - if err != nil { - return err - } - // Serialize `Amount` param: - err = encoder.Encode(obj.Amount) - if err != nil { - return err - } - return nil -} - -func (obj *SolanaTokenAmount) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { - // Deserialize `Token`: - err = decoder.Decode(&obj.Token) - if err != nil { - return err - } - // Deserialize `Amount`: - err = decoder.Decode(&obj.Amount) - if err != nil { - return err - } - return nil -} - -type ExtraArgsInput struct { - GasLimit *ag_binary.Uint128 `bin:"optional"` - AllowOutOfOrderExecution *bool `bin:"optional"` -} - -func (obj ExtraArgsInput) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { - // Serialize `GasLimit` param (optional): - { - if obj.GasLimit == nil { - err = encoder.WriteBool(false) - if err != nil { - return err - } - } else { - err = encoder.WriteBool(true) - if err != nil { - return err - } - err = encoder.Encode(obj.GasLimit) - if err != nil { - return err - } - } - } - // Serialize `AllowOutOfOrderExecution` param (optional): - { - if obj.AllowOutOfOrderExecution == nil { - err = encoder.WriteBool(false) - if err != nil { - return err - } - } else { - err = encoder.WriteBool(true) - if err != nil { - return err - } - err = encoder.Encode(obj.AllowOutOfOrderExecution) - if err != nil { - return err - } - } - } - return nil -} - -func (obj *ExtraArgsInput) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { - // Deserialize `GasLimit` (optional): - { - ok, err := decoder.ReadBool() - if err != nil { - return err - } - if ok { - err = decoder.Decode(&obj.GasLimit) - if err != nil { - return err - } - } - } - // Deserialize `AllowOutOfOrderExecution` (optional): - { - ok, err := decoder.ReadBool() - if err != nil { - return err - } - if ok { - err = decoder.Decode(&obj.AllowOutOfOrderExecution) - if err != nil { - return err - } - } - } - return nil -} - -type Any2SolanaMessage struct { - MessageId [32]uint8 - SourceChainSelector uint64 - Sender []byte - Data []byte - TokenAmounts []SolanaTokenAmount -} - -func (obj Any2SolanaMessage) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { - // Serialize `MessageId` param: - err = encoder.Encode(obj.MessageId) - if err != nil { - return err - } - // Serialize `SourceChainSelector` param: - err = encoder.Encode(obj.SourceChainSelector) - if err != nil { - return err - } - // Serialize `Sender` param: - err = encoder.Encode(obj.Sender) - if err != nil { - return err - } - // Serialize `Data` param: - err = encoder.Encode(obj.Data) - if err != nil { - return err - } - // Serialize `TokenAmounts` param: - err = encoder.Encode(obj.TokenAmounts) - if err != nil { - return err - } - return nil -} - -func (obj *Any2SolanaMessage) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { - // Deserialize `MessageId`: - err = decoder.Decode(&obj.MessageId) - if err != nil { - return err - } - // Deserialize `SourceChainSelector`: - err = decoder.Decode(&obj.SourceChainSelector) - if err != nil { - return err - } - // Deserialize `Sender`: - err = decoder.Decode(&obj.Sender) - if err != nil { - return err - } - // Deserialize `Data`: - err = decoder.Decode(&obj.Data) - if err != nil { - return err - } - // Deserialize `TokenAmounts`: - err = decoder.Decode(&obj.TokenAmounts) - if err != nil { - return err - } - return nil -} - -type RampMessageHeader struct { - MessageId [32]uint8 - SourceChainSelector uint64 - DestChainSelector uint64 - SequenceNumber uint64 - Nonce uint64 -} - -func (obj RampMessageHeader) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { - // Serialize `MessageId` param: - err = encoder.Encode(obj.MessageId) - if err != nil { - return err - } - // Serialize `SourceChainSelector` param: - err = encoder.Encode(obj.SourceChainSelector) - if err != nil { - return err - } - // Serialize `DestChainSelector` param: - err = encoder.Encode(obj.DestChainSelector) - if err != nil { - return err - } - // Serialize `SequenceNumber` param: - err = encoder.Encode(obj.SequenceNumber) - if err != nil { - return err - } - // Serialize `Nonce` param: - err = encoder.Encode(obj.Nonce) - if err != nil { - return err - } - return nil -} - -func (obj *RampMessageHeader) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { - // Deserialize `MessageId`: - err = decoder.Decode(&obj.MessageId) - if err != nil { - return err - } - // Deserialize `SourceChainSelector`: - err = decoder.Decode(&obj.SourceChainSelector) - if err != nil { - return err - } - // Deserialize `DestChainSelector`: - err = decoder.Decode(&obj.DestChainSelector) - if err != nil { - return err - } - // Deserialize `SequenceNumber`: - err = decoder.Decode(&obj.SequenceNumber) - if err != nil { - return err - } - // Deserialize `Nonce`: - err = decoder.Decode(&obj.Nonce) - if err != nil { - return err - } - return nil -} - -type ExecutionReportSingleChain struct { - SourceChainSelector uint64 - Message Any2SolanaRampMessage - OffchainTokenData [][]byte - Root [32]uint8 - Proofs [][32]uint8 - TokenIndexes []byte -} - -func (obj ExecutionReportSingleChain) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { - // Serialize `SourceChainSelector` param: - err = encoder.Encode(obj.SourceChainSelector) - if err != nil { - return err - } - // Serialize `Message` param: - err = encoder.Encode(obj.Message) - if err != nil { - return err - } - // Serialize `OffchainTokenData` param: - err = encoder.Encode(obj.OffchainTokenData) - if err != nil { - return err - } - // Serialize `Root` param: - err = encoder.Encode(obj.Root) - if err != nil { - return err - } - // Serialize `Proofs` param: - err = encoder.Encode(obj.Proofs) - if err != nil { - return err - } - // Serialize `TokenIndexes` param: - err = encoder.Encode(obj.TokenIndexes) - if err != nil { - return err - } - return nil -} - -func (obj *ExecutionReportSingleChain) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { - // Deserialize `SourceChainSelector`: - err = decoder.Decode(&obj.SourceChainSelector) - if err != nil { - return err - } - // Deserialize `Message`: - err = decoder.Decode(&obj.Message) - if err != nil { - return err - } - // Deserialize `OffchainTokenData`: - err = decoder.Decode(&obj.OffchainTokenData) - if err != nil { - return err - } - // Deserialize `Root`: - err = decoder.Decode(&obj.Root) - if err != nil { - return err - } - // Deserialize `Proofs`: - err = decoder.Decode(&obj.Proofs) - if err != nil { - return err - } - // Deserialize `TokenIndexes`: - err = decoder.Decode(&obj.TokenIndexes) - if err != nil { - return err - } - return nil -} - -type SolanaExtraArgs struct { - ComputeUnits uint32 - AllowOutOfOrderExecution bool -} - -func (obj SolanaExtraArgs) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { - // Serialize `ComputeUnits` param: - err = encoder.Encode(obj.ComputeUnits) - if err != nil { - return err - } - // Serialize `AllowOutOfOrderExecution` param: - err = encoder.Encode(obj.AllowOutOfOrderExecution) - if err != nil { - return err - } - return nil -} - -func (obj *SolanaExtraArgs) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { - // Deserialize `ComputeUnits`: - err = decoder.Decode(&obj.ComputeUnits) - if err != nil { - return err - } - // Deserialize `AllowOutOfOrderExecution`: - err = decoder.Decode(&obj.AllowOutOfOrderExecution) - if err != nil { - return err - } - return nil -} - -type EvmExtraArgs struct { - GasLimit ag_binary.Uint128 - AllowOutOfOrderExecution bool -} - -func (obj EvmExtraArgs) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { - // Serialize `GasLimit` param: - err = encoder.Encode(obj.GasLimit) - if err != nil { - return err - } - // Serialize `AllowOutOfOrderExecution` param: - err = encoder.Encode(obj.AllowOutOfOrderExecution) - if err != nil { - return err - } - return nil -} - -func (obj *EvmExtraArgs) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { - // Deserialize `GasLimit`: - err = decoder.Decode(&obj.GasLimit) - if err != nil { - return err - } - // Deserialize `AllowOutOfOrderExecution`: - err = decoder.Decode(&obj.AllowOutOfOrderExecution) - if err != nil { - return err - } - return nil -} - -type Any2SolanaRampMessage struct { - Header RampMessageHeader - Sender []byte - Data []byte - Receiver ag_solanago.PublicKey - TokenAmounts []Any2SolanaTokenTransfer - ExtraArgs SolanaExtraArgs -} - -func (obj Any2SolanaRampMessage) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { - // Serialize `Header` param: - err = encoder.Encode(obj.Header) - if err != nil { - return err - } - // Serialize `Sender` param: - err = encoder.Encode(obj.Sender) - if err != nil { - return err - } - // Serialize `Data` param: - err = encoder.Encode(obj.Data) - if err != nil { - return err - } - // Serialize `Receiver` param: - err = encoder.Encode(obj.Receiver) - if err != nil { - return err - } - // Serialize `TokenAmounts` param: - err = encoder.Encode(obj.TokenAmounts) - if err != nil { - return err - } - // Serialize `ExtraArgs` param: - err = encoder.Encode(obj.ExtraArgs) - if err != nil { - return err - } - return nil -} - -func (obj *Any2SolanaRampMessage) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { - // Deserialize `Header`: - err = decoder.Decode(&obj.Header) - if err != nil { - return err - } - // Deserialize `Sender`: - err = decoder.Decode(&obj.Sender) - if err != nil { - return err - } - // Deserialize `Data`: - err = decoder.Decode(&obj.Data) - if err != nil { - return err - } - // Deserialize `Receiver`: - err = decoder.Decode(&obj.Receiver) - if err != nil { - return err - } - // Deserialize `TokenAmounts`: - err = decoder.Decode(&obj.TokenAmounts) - if err != nil { - return err - } - // Deserialize `ExtraArgs`: - err = decoder.Decode(&obj.ExtraArgs) - if err != nil { - return err - } - return nil -} - -type Solana2AnyRampMessage struct { - Header RampMessageHeader - Sender ag_solanago.PublicKey - Data []byte - Receiver []byte - ExtraArgs EvmExtraArgs - FeeToken ag_solanago.PublicKey - TokenAmounts []Solana2AnyTokenTransfer -} - -func (obj Solana2AnyRampMessage) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { - // Serialize `Header` param: - err = encoder.Encode(obj.Header) - if err != nil { - return err - } - // Serialize `Sender` param: - err = encoder.Encode(obj.Sender) - if err != nil { - return err - } - // Serialize `Data` param: - err = encoder.Encode(obj.Data) - if err != nil { - return err - } - // Serialize `Receiver` param: - err = encoder.Encode(obj.Receiver) - if err != nil { - return err - } - // Serialize `ExtraArgs` param: - err = encoder.Encode(obj.ExtraArgs) - if err != nil { - return err - } - // Serialize `FeeToken` param: - err = encoder.Encode(obj.FeeToken) - if err != nil { - return err - } - // Serialize `TokenAmounts` param: - err = encoder.Encode(obj.TokenAmounts) - if err != nil { - return err - } - return nil -} - -func (obj *Solana2AnyRampMessage) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { - // Deserialize `Header`: - err = decoder.Decode(&obj.Header) - if err != nil { - return err - } - // Deserialize `Sender`: - err = decoder.Decode(&obj.Sender) - if err != nil { - return err - } - // Deserialize `Data`: - err = decoder.Decode(&obj.Data) - if err != nil { - return err - } - // Deserialize `Receiver`: - err = decoder.Decode(&obj.Receiver) - if err != nil { - return err - } - // Deserialize `ExtraArgs`: - err = decoder.Decode(&obj.ExtraArgs) - if err != nil { - return err - } - // Deserialize `FeeToken`: - err = decoder.Decode(&obj.FeeToken) - if err != nil { - return err - } - // Deserialize `TokenAmounts`: - err = decoder.Decode(&obj.TokenAmounts) - if err != nil { - return err - } - return nil -} - -type Solana2AnyTokenTransfer struct { - SourcePoolAddress ag_solanago.PublicKey - DestTokenAddress []byte - ExtraData []byte - Amount uint64 - DestExecData []byte -} - -func (obj Solana2AnyTokenTransfer) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { - // Serialize `SourcePoolAddress` param: - err = encoder.Encode(obj.SourcePoolAddress) - if err != nil { - return err - } - // Serialize `DestTokenAddress` param: - err = encoder.Encode(obj.DestTokenAddress) - if err != nil { - return err - } - // Serialize `ExtraData` param: - err = encoder.Encode(obj.ExtraData) - if err != nil { - return err - } - // Serialize `Amount` param: - err = encoder.Encode(obj.Amount) - if err != nil { - return err - } - // Serialize `DestExecData` param: - err = encoder.Encode(obj.DestExecData) - if err != nil { - return err - } - return nil -} - -func (obj *Solana2AnyTokenTransfer) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { - // Deserialize `SourcePoolAddress`: - err = decoder.Decode(&obj.SourcePoolAddress) - if err != nil { - return err - } - // Deserialize `DestTokenAddress`: - err = decoder.Decode(&obj.DestTokenAddress) - if err != nil { - return err - } - // Deserialize `ExtraData`: - err = decoder.Decode(&obj.ExtraData) - if err != nil { - return err - } - // Deserialize `Amount`: - err = decoder.Decode(&obj.Amount) - if err != nil { - return err - } - // Deserialize `DestExecData`: - err = decoder.Decode(&obj.DestExecData) - if err != nil { - return err - } - return nil -} - -type Any2SolanaTokenTransfer struct { - SourcePoolAddress []byte - DestTokenAddress ag_solanago.PublicKey - DestGasAmount uint32 - ExtraData []byte - Amount uint64 -} - -func (obj Any2SolanaTokenTransfer) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { - // Serialize `SourcePoolAddress` param: - err = encoder.Encode(obj.SourcePoolAddress) - if err != nil { - return err - } - // Serialize `DestTokenAddress` param: - err = encoder.Encode(obj.DestTokenAddress) - if err != nil { - return err - } - // Serialize `DestGasAmount` param: - err = encoder.Encode(obj.DestGasAmount) - if err != nil { - return err - } - // Serialize `ExtraData` param: - err = encoder.Encode(obj.ExtraData) - if err != nil { - return err - } - // Serialize `Amount` param: - err = encoder.Encode(obj.Amount) - if err != nil { - return err - } - return nil -} - -func (obj *Any2SolanaTokenTransfer) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { - // Deserialize `SourcePoolAddress`: - err = decoder.Decode(&obj.SourcePoolAddress) - if err != nil { - return err - } - // Deserialize `DestTokenAddress`: - err = decoder.Decode(&obj.DestTokenAddress) - if err != nil { - return err - } - // Deserialize `DestGasAmount`: - err = decoder.Decode(&obj.DestGasAmount) - if err != nil { - return err - } - // Deserialize `ExtraData`: - err = decoder.Decode(&obj.ExtraData) - if err != nil { - return err - } - // Deserialize `Amount`: - err = decoder.Decode(&obj.Amount) - if err != nil { - return err - } - return nil -} - -type LockOrBurnInV1 struct { - Receiver []byte - RemoteChainSelector uint64 - OriginalSender ag_solanago.PublicKey - Amount uint64 - LocalToken ag_solanago.PublicKey -} - -func (obj LockOrBurnInV1) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { - // Serialize `Receiver` param: - err = encoder.Encode(obj.Receiver) - if err != nil { - return err - } - // Serialize `RemoteChainSelector` param: - err = encoder.Encode(obj.RemoteChainSelector) - if err != nil { - return err - } - // Serialize `OriginalSender` param: - err = encoder.Encode(obj.OriginalSender) - if err != nil { - return err - } - // Serialize `Amount` param: - err = encoder.Encode(obj.Amount) - if err != nil { - return err - } - // Serialize `LocalToken` param: - err = encoder.Encode(obj.LocalToken) - if err != nil { - return err - } - return nil -} - -func (obj *LockOrBurnInV1) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { - // Deserialize `Receiver`: - err = decoder.Decode(&obj.Receiver) - if err != nil { - return err - } - // Deserialize `RemoteChainSelector`: - err = decoder.Decode(&obj.RemoteChainSelector) - if err != nil { - return err - } - // Deserialize `OriginalSender`: - err = decoder.Decode(&obj.OriginalSender) - if err != nil { - return err - } - // Deserialize `Amount`: - err = decoder.Decode(&obj.Amount) - if err != nil { - return err - } - // Deserialize `LocalToken`: - err = decoder.Decode(&obj.LocalToken) - if err != nil { - return err - } - return nil -} - -type ReleaseOrMintInV1 struct { - OriginalSender []byte - RemoteChainSelector uint64 - Receiver ag_solanago.PublicKey - Amount uint64 - LocalToken ag_solanago.PublicKey - - // @dev WARNING: sourcePoolAddress should be checked prior to any processing of funds. Make sure it matches the - // expected pool address for the given remoteChainSelector. - SourcePoolAddress []byte - SourcePoolData []byte - - // @dev WARNING: offchainTokenData is untrusted data. - OffchainTokenData []byte -} - -func (obj ReleaseOrMintInV1) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { - // Serialize `OriginalSender` param: - err = encoder.Encode(obj.OriginalSender) - if err != nil { - return err - } - // Serialize `RemoteChainSelector` param: - err = encoder.Encode(obj.RemoteChainSelector) - if err != nil { - return err - } - // Serialize `Receiver` param: - err = encoder.Encode(obj.Receiver) - if err != nil { - return err - } - // Serialize `Amount` param: - err = encoder.Encode(obj.Amount) - if err != nil { - return err - } - // Serialize `LocalToken` param: - err = encoder.Encode(obj.LocalToken) - if err != nil { - return err - } - // Serialize `SourcePoolAddress` param: - err = encoder.Encode(obj.SourcePoolAddress) - if err != nil { - return err - } - // Serialize `SourcePoolData` param: - err = encoder.Encode(obj.SourcePoolData) - if err != nil { - return err - } - // Serialize `OffchainTokenData` param: - err = encoder.Encode(obj.OffchainTokenData) - if err != nil { - return err - } - return nil -} - -func (obj *ReleaseOrMintInV1) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { - // Deserialize `OriginalSender`: - err = decoder.Decode(&obj.OriginalSender) - if err != nil { - return err - } - // Deserialize `RemoteChainSelector`: - err = decoder.Decode(&obj.RemoteChainSelector) - if err != nil { - return err - } - // Deserialize `Receiver`: - err = decoder.Decode(&obj.Receiver) - if err != nil { - return err - } - // Deserialize `Amount`: - err = decoder.Decode(&obj.Amount) - if err != nil { - return err - } - // Deserialize `LocalToken`: - err = decoder.Decode(&obj.LocalToken) - if err != nil { - return err - } - // Deserialize `SourcePoolAddress`: - err = decoder.Decode(&obj.SourcePoolAddress) - if err != nil { - return err - } - // Deserialize `SourcePoolData`: - err = decoder.Decode(&obj.SourcePoolData) - if err != nil { - return err - } - // Deserialize `OffchainTokenData`: - err = decoder.Decode(&obj.OffchainTokenData) - if err != nil { - return err - } - return nil -} - -type LockOrBurnOutV1 struct { - DestTokenAddress []byte - DestPoolData []byte -} - -func (obj LockOrBurnOutV1) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { - // Serialize `DestTokenAddress` param: - err = encoder.Encode(obj.DestTokenAddress) - if err != nil { - return err - } - // Serialize `DestPoolData` param: - err = encoder.Encode(obj.DestPoolData) - if err != nil { - return err - } - return nil -} - -func (obj *LockOrBurnOutV1) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { - // Deserialize `DestTokenAddress`: - err = decoder.Decode(&obj.DestTokenAddress) - if err != nil { - return err - } - // Deserialize `DestPoolData`: - err = decoder.Decode(&obj.DestPoolData) - if err != nil { - return err - } - return nil -} - -type ReleaseOrMintOutV1 struct { - DestinationAmount uint64 -} - -func (obj ReleaseOrMintOutV1) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { - // Serialize `DestinationAmount` param: - err = encoder.Encode(obj.DestinationAmount) - if err != nil { - return err - } - return nil -} - -func (obj *ReleaseOrMintOutV1) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { - // Deserialize `DestinationAmount`: - err = decoder.Decode(&obj.DestinationAmount) - if err != nil { - return err - } - return nil -} - -type Ocr3Config struct { - PluginType uint8 - ConfigInfo Ocr3ConfigInfo - Signers [16][20]uint8 - Transmitters [16][32]uint8 -} - -func (obj Ocr3Config) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { - // Serialize `PluginType` param: - err = encoder.Encode(obj.PluginType) - if err != nil { - return err - } - // Serialize `ConfigInfo` param: - err = encoder.Encode(obj.ConfigInfo) - if err != nil { - return err - } - // Serialize `Signers` param: - err = encoder.Encode(obj.Signers) - if err != nil { - return err - } - // Serialize `Transmitters` param: - err = encoder.Encode(obj.Transmitters) - if err != nil { - return err - } - return nil -} - -func (obj *Ocr3Config) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { - // Deserialize `PluginType`: - err = decoder.Decode(&obj.PluginType) - if err != nil { - return err - } - // Deserialize `ConfigInfo`: - err = decoder.Decode(&obj.ConfigInfo) - if err != nil { - return err - } - // Deserialize `Signers`: - err = decoder.Decode(&obj.Signers) - if err != nil { - return err - } - // Deserialize `Transmitters`: - err = decoder.Decode(&obj.Transmitters) - if err != nil { - return err - } - return nil -} - -type Ocr3ConfigInfo struct { - ConfigDigest [32]uint8 - F uint8 - N uint8 - IsSignatureVerificationEnabled uint8 -} - -func (obj Ocr3ConfigInfo) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { - // Serialize `ConfigDigest` param: - err = encoder.Encode(obj.ConfigDigest) - if err != nil { - return err - } - // Serialize `F` param: - err = encoder.Encode(obj.F) - if err != nil { - return err - } - // Serialize `N` param: - err = encoder.Encode(obj.N) - if err != nil { - return err - } - // Serialize `IsSignatureVerificationEnabled` param: - err = encoder.Encode(obj.IsSignatureVerificationEnabled) - if err != nil { - return err - } - return nil -} - -func (obj *Ocr3ConfigInfo) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { - // Deserialize `ConfigDigest`: - err = decoder.Decode(&obj.ConfigDigest) - if err != nil { - return err - } - // Deserialize `F`: - err = decoder.Decode(&obj.F) - if err != nil { - return err - } - // Deserialize `N`: - err = decoder.Decode(&obj.N) - if err != nil { - return err - } - // Deserialize `IsSignatureVerificationEnabled`: - err = decoder.Decode(&obj.IsSignatureVerificationEnabled) - if err != nil { - return err - } - return nil -} - -type SourceChainConfig struct { - IsEnabled bool - MinSeqNr uint64 - OnRamp []byte -} - -func (obj SourceChainConfig) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { - // Serialize `IsEnabled` param: - err = encoder.Encode(obj.IsEnabled) - if err != nil { - return err - } - // Serialize `MinSeqNr` param: - err = encoder.Encode(obj.MinSeqNr) - if err != nil { - return err - } - // Serialize `OnRamp` param: - err = encoder.Encode(obj.OnRamp) - if err != nil { - return err - } - return nil -} - -func (obj *SourceChainConfig) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { - // Deserialize `IsEnabled`: - err = decoder.Decode(&obj.IsEnabled) - if err != nil { - return err - } - // Deserialize `MinSeqNr`: - err = decoder.Decode(&obj.MinSeqNr) - if err != nil { - return err - } - // Deserialize `OnRamp`: - err = decoder.Decode(&obj.OnRamp) - if err != nil { - return err - } - return nil -} - -type DestChainConfig struct { - SequenceNumber uint64 - UsdPerUnitGas TimestampedPackedU224 - BillingConfig ChainBillingConfig -} - -func (obj DestChainConfig) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { - // Serialize `SequenceNumber` param: - err = encoder.Encode(obj.SequenceNumber) - if err != nil { - return err - } - // Serialize `UsdPerUnitGas` param: - err = encoder.Encode(obj.UsdPerUnitGas) - if err != nil { - return err - } - // Serialize `BillingConfig` param: - err = encoder.Encode(obj.BillingConfig) - if err != nil { - return err - } - return nil -} - -func (obj *DestChainConfig) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { - // Deserialize `SequenceNumber`: - err = decoder.Decode(&obj.SequenceNumber) - if err != nil { - return err - } - // Deserialize `UsdPerUnitGas`: - err = decoder.Decode(&obj.UsdPerUnitGas) - if err != nil { - return err - } - // Deserialize `BillingConfig`: - err = decoder.Decode(&obj.BillingConfig) - if err != nil { - return err - } - return nil -} - -type ChainBillingConfig struct { - IsEnabled bool - MaxNumberOfTokensPerMsg uint16 - MaxDataBytes uint32 - MaxPerMsgGasLimit uint32 - DestGasOverhead uint32 - DestGasPerPayloadByte uint16 - DestDataAvailabilityOverheadGas uint32 - DestGasPerDataAvailabilityByte uint16 - DestDataAvailabilityMultiplierBps uint16 - DefaultTokenFeeUsdcents uint16 - DefaultTokenDestGasOverhead uint32 - DefaultTxGasLimit uint32 - GasMultiplierWeiPerEth uint64 - NetworkFeeUsdcents uint32 - GasPriceStalenessThreshold uint32 - EnforceOutOfOrder bool - ChainFamilySelector [4]uint8 -} - -func (obj ChainBillingConfig) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { - // Serialize `IsEnabled` param: - err = encoder.Encode(obj.IsEnabled) - if err != nil { - return err - } - // Serialize `MaxNumberOfTokensPerMsg` param: - err = encoder.Encode(obj.MaxNumberOfTokensPerMsg) - if err != nil { - return err - } - // Serialize `MaxDataBytes` param: - err = encoder.Encode(obj.MaxDataBytes) - if err != nil { - return err - } - // Serialize `MaxPerMsgGasLimit` param: - err = encoder.Encode(obj.MaxPerMsgGasLimit) - if err != nil { - return err - } - // Serialize `DestGasOverhead` param: - err = encoder.Encode(obj.DestGasOverhead) - if err != nil { - return err - } - // Serialize `DestGasPerPayloadByte` param: - err = encoder.Encode(obj.DestGasPerPayloadByte) - if err != nil { - return err - } - // Serialize `DestDataAvailabilityOverheadGas` param: - err = encoder.Encode(obj.DestDataAvailabilityOverheadGas) - if err != nil { - return err - } - // Serialize `DestGasPerDataAvailabilityByte` param: - err = encoder.Encode(obj.DestGasPerDataAvailabilityByte) - if err != nil { - return err - } - // Serialize `DestDataAvailabilityMultiplierBps` param: - err = encoder.Encode(obj.DestDataAvailabilityMultiplierBps) - if err != nil { - return err - } - // Serialize `DefaultTokenFeeUsdcents` param: - err = encoder.Encode(obj.DefaultTokenFeeUsdcents) - if err != nil { - return err - } - // Serialize `DefaultTokenDestGasOverhead` param: - err = encoder.Encode(obj.DefaultTokenDestGasOverhead) - if err != nil { - return err - } - // Serialize `DefaultTxGasLimit` param: - err = encoder.Encode(obj.DefaultTxGasLimit) - if err != nil { - return err - } - // Serialize `GasMultiplierWeiPerEth` param: - err = encoder.Encode(obj.GasMultiplierWeiPerEth) - if err != nil { - return err - } - // Serialize `NetworkFeeUsdcents` param: - err = encoder.Encode(obj.NetworkFeeUsdcents) - if err != nil { - return err - } - // Serialize `GasPriceStalenessThreshold` param: - err = encoder.Encode(obj.GasPriceStalenessThreshold) - if err != nil { - return err - } - // Serialize `EnforceOutOfOrder` param: - err = encoder.Encode(obj.EnforceOutOfOrder) - if err != nil { - return err - } - // Serialize `ChainFamilySelector` param: - err = encoder.Encode(obj.ChainFamilySelector) - if err != nil { - return err - } - return nil -} - -func (obj *ChainBillingConfig) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { - // Deserialize `IsEnabled`: - err = decoder.Decode(&obj.IsEnabled) - if err != nil { - return err - } - // Deserialize `MaxNumberOfTokensPerMsg`: - err = decoder.Decode(&obj.MaxNumberOfTokensPerMsg) - if err != nil { - return err - } - // Deserialize `MaxDataBytes`: - err = decoder.Decode(&obj.MaxDataBytes) - if err != nil { - return err - } - // Deserialize `MaxPerMsgGasLimit`: - err = decoder.Decode(&obj.MaxPerMsgGasLimit) - if err != nil { - return err - } - // Deserialize `DestGasOverhead`: - err = decoder.Decode(&obj.DestGasOverhead) - if err != nil { - return err - } - // Deserialize `DestGasPerPayloadByte`: - err = decoder.Decode(&obj.DestGasPerPayloadByte) - if err != nil { - return err - } - // Deserialize `DestDataAvailabilityOverheadGas`: - err = decoder.Decode(&obj.DestDataAvailabilityOverheadGas) - if err != nil { - return err - } - // Deserialize `DestGasPerDataAvailabilityByte`: - err = decoder.Decode(&obj.DestGasPerDataAvailabilityByte) - if err != nil { - return err - } - // Deserialize `DestDataAvailabilityMultiplierBps`: - err = decoder.Decode(&obj.DestDataAvailabilityMultiplierBps) - if err != nil { - return err - } - // Deserialize `DefaultTokenFeeUsdcents`: - err = decoder.Decode(&obj.DefaultTokenFeeUsdcents) - if err != nil { - return err - } - // Deserialize `DefaultTokenDestGasOverhead`: - err = decoder.Decode(&obj.DefaultTokenDestGasOverhead) - if err != nil { - return err - } - // Deserialize `DefaultTxGasLimit`: - err = decoder.Decode(&obj.DefaultTxGasLimit) - if err != nil { - return err - } - // Deserialize `GasMultiplierWeiPerEth`: - err = decoder.Decode(&obj.GasMultiplierWeiPerEth) - if err != nil { - return err - } - // Deserialize `NetworkFeeUsdcents`: - err = decoder.Decode(&obj.NetworkFeeUsdcents) - if err != nil { - return err - } - // Deserialize `GasPriceStalenessThreshold`: - err = decoder.Decode(&obj.GasPriceStalenessThreshold) - if err != nil { - return err - } - // Deserialize `EnforceOutOfOrder`: - err = decoder.Decode(&obj.EnforceOutOfOrder) - if err != nil { - return err - } - // Deserialize `ChainFamilySelector`: - err = decoder.Decode(&obj.ChainFamilySelector) - if err != nil { - return err - } - return nil -} - -type TokenBilling struct { - MinFeeUsdcents uint32 - MaxFeeUsdcents uint32 - DeciBps uint16 - DestGasOverhead uint32 - DestBytesOverhead uint32 - IsEnabled bool -} - -func (obj TokenBilling) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { - // Serialize `MinFeeUsdcents` param: - err = encoder.Encode(obj.MinFeeUsdcents) - if err != nil { - return err - } - // Serialize `MaxFeeUsdcents` param: - err = encoder.Encode(obj.MaxFeeUsdcents) - if err != nil { - return err - } - // Serialize `DeciBps` param: - err = encoder.Encode(obj.DeciBps) - if err != nil { - return err - } - // Serialize `DestGasOverhead` param: - err = encoder.Encode(obj.DestGasOverhead) - if err != nil { - return err - } - // Serialize `DestBytesOverhead` param: - err = encoder.Encode(obj.DestBytesOverhead) - if err != nil { - return err - } - // Serialize `IsEnabled` param: - err = encoder.Encode(obj.IsEnabled) - if err != nil { - return err - } - return nil -} - -func (obj *TokenBilling) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { - // Deserialize `MinFeeUsdcents`: - err = decoder.Decode(&obj.MinFeeUsdcents) - if err != nil { - return err - } - // Deserialize `MaxFeeUsdcents`: - err = decoder.Decode(&obj.MaxFeeUsdcents) - if err != nil { - return err - } - // Deserialize `DeciBps`: - err = decoder.Decode(&obj.DeciBps) - if err != nil { - return err - } - // Deserialize `DestGasOverhead`: - err = decoder.Decode(&obj.DestGasOverhead) - if err != nil { - return err - } - // Deserialize `DestBytesOverhead`: - err = decoder.Decode(&obj.DestBytesOverhead) - if err != nil { - return err - } - // Deserialize `IsEnabled`: - err = decoder.Decode(&obj.IsEnabled) - if err != nil { - return err - } - return nil -} - -type TimestampedPackedU224 struct { - Value [28]uint8 - Timestamp uint32 -} - -func (obj TimestampedPackedU224) MarshalWithEncoder(encoder *ag_binary.Encoder) (err error) { - // Serialize `Value` param: - err = encoder.Encode(obj.Value) - if err != nil { - return err - } - // Serialize `Timestamp` param: - err = encoder.Encode(obj.Timestamp) - if err != nil { - return err - } - return nil -} - -func (obj *TimestampedPackedU224) UnmarshalWithDecoder(decoder *ag_binary.Decoder) (err error) { - // Deserialize `Value`: - err = decoder.Decode(&obj.Value) - if err != nil { - return err - } - // Deserialize `Timestamp`: - err = decoder.Decode(&obj.Timestamp) - if err != nil { - return err - } - return nil -} - -type OcrPluginType ag_binary.BorshEnum - -const ( - Commit_OcrPluginType OcrPluginType = iota - Execution_OcrPluginType -) - -func (value OcrPluginType) String() string { - switch value { - case Commit_OcrPluginType: - return "Commit" - case Execution_OcrPluginType: - return "Execution" - default: - return "" - } -} - -type MerkleError ag_binary.BorshEnum - -const ( - InvalidProof_MerkleError MerkleError = iota -) - -func (value MerkleError) String() string { - switch value { - case InvalidProof_MerkleError: - return "InvalidProof" - default: - return "" - } -} - -type MessageExecutionState ag_binary.BorshEnum - -const ( - Untouched_MessageExecutionState MessageExecutionState = iota - InProgress_MessageExecutionState - Success_MessageExecutionState - Failure_MessageExecutionState -) - -func (value MessageExecutionState) String() string { - switch value { - case Untouched_MessageExecutionState: - return "Untouched" - case InProgress_MessageExecutionState: - return "InProgress" - case Success_MessageExecutionState: - return "Success" - case Failure_MessageExecutionState: - return "Failure" - default: - return "" - } -} - -type CcipRouterError ag_binary.BorshEnum - -const ( - InvalidSequenceInterval_CcipRouterError CcipRouterError = iota - RootNotCommitted_CcipRouterError - ExistingMerkleRoot_CcipRouterError - Unauthorized_CcipRouterError - InvalidInputs_CcipRouterError - UnsupportedSourceChainSelector_CcipRouterError - UnsupportedDestinationChainSelector_CcipRouterError - InvalidProof_CcipRouterError - InvalidMessage_CcipRouterError - ReachedMaxSequenceNumber_CcipRouterError - ManualExecutionNotAllowed_CcipRouterError - InvalidInputsTokenIndices_CcipRouterError - InvalidInputsPoolAccounts_CcipRouterError - InvalidInputsTokenAccounts_CcipRouterError - InvalidInputsConfigAccounts_CcipRouterError - InvalidInputsTokenAmount_CcipRouterError - OfframpReleaseMintBalanceMismatch_CcipRouterError - OfframpInvalidDataLength_CcipRouterError -) - -func (value CcipRouterError) String() string { - switch value { - case InvalidSequenceInterval_CcipRouterError: - return "InvalidSequenceInterval" - case RootNotCommitted_CcipRouterError: - return "RootNotCommitted" - case ExistingMerkleRoot_CcipRouterError: - return "ExistingMerkleRoot" - case Unauthorized_CcipRouterError: - return "Unauthorized" - case InvalidInputs_CcipRouterError: - return "InvalidInputs" - case UnsupportedSourceChainSelector_CcipRouterError: - return "UnsupportedSourceChainSelector" - case UnsupportedDestinationChainSelector_CcipRouterError: - return "UnsupportedDestinationChainSelector" - case InvalidProof_CcipRouterError: - return "InvalidProof" - case InvalidMessage_CcipRouterError: - return "InvalidMessage" - case ReachedMaxSequenceNumber_CcipRouterError: - return "ReachedMaxSequenceNumber" - case ManualExecutionNotAllowed_CcipRouterError: - return "ManualExecutionNotAllowed" - case InvalidInputsTokenIndices_CcipRouterError: - return "InvalidInputsTokenIndices" - case InvalidInputsPoolAccounts_CcipRouterError: - return "InvalidInputsPoolAccounts" - case InvalidInputsTokenAccounts_CcipRouterError: - return "InvalidInputsTokenAccounts" - case InvalidInputsConfigAccounts_CcipRouterError: - return "InvalidInputsConfigAccounts" - case InvalidInputsTokenAmount_CcipRouterError: - return "InvalidInputsTokenAmount" - case OfframpReleaseMintBalanceMismatch_CcipRouterError: - return "OfframpReleaseMintBalanceMismatch" - case OfframpInvalidDataLength_CcipRouterError: - return "OfframpInvalidDataLength" - default: - return "" - } -} diff --git a/core/capabilities/ccip/ccipsolana/commitcodec.go b/core/capabilities/ccip/ccipsolana/commitcodec.go index 711bb66068a..425cc7bdea8 100644 --- a/core/capabilities/ccip/ccipsolana/commitcodec.go +++ b/core/capabilities/ccip/ccipsolana/commitcodec.go @@ -6,12 +6,11 @@ import ( "errors" "fmt" + agbinary "github.com/gagliardetto/binary" "github.com/gagliardetto/solana-go" - "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/ccipsolana/ccip_router" + "github.com/smartcontractkit/chainlink-ccip/chains/solana/gobindings/ccip_router" cciptypes "github.com/smartcontractkit/chainlink-ccip/pkg/types/ccipocr3" - - agbinary "github.com/gagliardetto/binary" ) // CommitPluginCodecV1 is a codec for encoding and decoding commit plugin reports. @@ -39,7 +38,7 @@ func (c *CommitPluginCodecV1) Encode(ctx context.Context, report cciptypes.Commi for _, update := range report.PriceUpdates.TokenPriceUpdates { b, err := update.Price.MarshalJSON() if err != nil { - return nil, fmt.Errorf("error marshaling token price: %v", err) + return nil, fmt.Errorf("error marshaling token price: %w", err) } if len(b) > 28 { diff --git a/go.mod b/go.mod index 4bfc5964ff7..f3e76d0be9b 100644 --- a/go.mod +++ b/go.mod @@ -23,7 +23,8 @@ require ( github.com/ethereum/go-ethereum v1.14.11 github.com/fatih/color v1.17.0 github.com/fxamacker/cbor/v2 v2.7.0 - github.com/gagliardetto/solana-go v1.8.4 + github.com/gagliardetto/binary v0.8.0 + github.com/gagliardetto/solana-go v1.12.0 github.com/getsentry/sentry-go v0.27.0 github.com/gin-contrib/cors v1.7.2 github.com/gin-contrib/expvar v0.0.1 @@ -79,6 +80,7 @@ require ( github.com/smartcontractkit/chain-selectors v1.0.34 github.com/smartcontractkit/chainlink-automation v0.8.1 github.com/smartcontractkit/chainlink-ccip v0.0.0-20241218114855-f74219171000 + github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20241223194433-f25773de7c0e github.com/smartcontractkit/chainlink-common v0.4.1-0.20241217120918-bbe318cd0760 github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241202195413-82468150ac1e github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20241216163550-fa030d178ba3 @@ -91,7 +93,7 @@ require ( github.com/smartcontractkit/tdh2/go/tdh2 v0.0.0-20241009055228-33d0c0bf38de github.com/smartcontractkit/wsrpc v0.8.3 github.com/spf13/cast v1.6.0 - github.com/stretchr/testify v1.9.0 + github.com/stretchr/testify v1.10.0 github.com/test-go/testify v1.1.4 github.com/theodesp/go-heaps v0.0.0-20190520121037-88e35354fe0a github.com/tidwall/gjson v1.17.0 @@ -111,13 +113,13 @@ require ( go.uber.org/multierr v1.11.0 go.uber.org/zap v1.27.0 golang.org/x/crypto v0.31.0 - golang.org/x/exp v0.0.0-20241009180824-f66d83c29e7c - golang.org/x/mod v0.21.0 + golang.org/x/exp v0.0.0-20241210194714-1829a127f884 + golang.org/x/mod v0.22.0 golang.org/x/sync v0.10.0 golang.org/x/term v0.27.0 golang.org/x/text v0.21.0 golang.org/x/time v0.7.0 - golang.org/x/tools v0.26.0 + golang.org/x/tools v0.28.0 gonum.org/v1/gonum v0.15.1 google.golang.org/grpc v1.67.1 google.golang.org/protobuf v1.35.1 @@ -130,7 +132,6 @@ require ( cel.dev/expr v0.17.0 // indirect cloud.google.com/go/auth v0.9.9 // indirect cloud.google.com/go/storage v1.45.0 // indirect - contrib.go.opencensus.io/exporter/stackdriver v0.13.5 // indirect cosmossdk.io/api v0.3.1 // indirect cosmossdk.io/core v0.5.1 // indirect cosmossdk.io/depinject v1.0.0-alpha.4 // indirect @@ -191,8 +192,7 @@ require ( github.com/crate-crypto/go-kzg-4844 v1.0.0 // indirect github.com/danieljoos/wincred v1.1.2 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect - github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 // indirect - github.com/dfuse-io/logging v0.0.0-20210109005628-b97a57253f70 // indirect + github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 // indirect github.com/dgraph-io/badger/v2 v2.2007.4 // indirect github.com/dgraph-io/ristretto v0.1.1 // indirect github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13 // indirect @@ -204,7 +204,6 @@ require ( github.com/ethereum/go-verkle v0.1.1-0.20240829091221-dffa7562dbe9 // indirect github.com/fsnotify/fsnotify v1.7.0 // indirect github.com/gabriel-vasile/mimetype v1.4.3 // indirect - github.com/gagliardetto/binary v0.7.7 // indirect github.com/gagliardetto/treeout v0.1.4 // indirect github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08 // indirect github.com/gedex/inflector v0.0.0-20170307190818-16278e9db813 // indirect @@ -230,7 +229,6 @@ require ( github.com/golang-jwt/jwt/v4 v4.5.0 // indirect github.com/golang-jwt/jwt/v5 v5.2.1 // indirect github.com/golang/glog v1.2.2 // indirect - github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/golang/protobuf v1.5.4 // indirect github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb // indirect github.com/google/btree v1.1.2 // indirect @@ -328,13 +326,12 @@ require ( github.com/spf13/pflag v1.0.5 // indirect github.com/spf13/viper v1.19.0 // indirect github.com/status-im/keycard-go v0.2.0 // indirect - github.com/streamingfast/logging v0.0.0-20220405224725-2755dab2ce75 // indirect + github.com/streamingfast/logging v0.0.0-20230608130331-f22c91403091 // indirect github.com/stretchr/objx v0.5.2 // indirect github.com/subosito/gotenv v1.6.0 // indirect github.com/supranational/blst v0.3.13 // indirect github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d // indirect github.com/tendermint/go-amino v0.16.0 // indirect - github.com/teris-io/shortid v0.0.0-20201117134242-e59966efd125 // indirect github.com/tidwall/btree v1.6.0 // indirect github.com/tidwall/match v1.1.1 // indirect github.com/tidwall/pretty v1.2.1 // indirect @@ -354,7 +351,6 @@ require ( go.dedis.ch/protobuf v1.0.11 // indirect go.etcd.io/bbolt v1.3.9 // indirect go.mongodb.org/mongo-driver v1.15.0 // indirect - go.opencensus.io v0.24.0 // indirect go.opentelemetry.io/contrib/detectors/gcp v1.31.0 // indirect go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.56.0 // indirect go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.56.0 // indirect @@ -374,7 +370,7 @@ require ( go.opentelemetry.io/proto/otlp v1.3.1 // indirect go.uber.org/ratelimit v0.3.1 // indirect golang.org/x/arch v0.11.0 // indirect - golang.org/x/net v0.30.0 // indirect + golang.org/x/net v0.32.0 // indirect golang.org/x/sys v0.28.0 // indirect golang.org/x/xerrors v0.0.0-20240903120638-7835f813f4da // indirect google.golang.org/api v0.202.0 // indirect diff --git a/go.sum b/go.sum index c6f5b4a29e8..0c9654d1fb5 100644 --- a/go.sum +++ b/go.sum @@ -3,7 +3,6 @@ cel.dev/expr v0.17.0/go.mod h1:HCwbrn+qQoHPXgfz6cl2J0hDybnX2N1sQQkl9EggXx8= cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= -cloud.google.com/go v0.43.0/go.mod h1:BOSR3VbTLkk6FDC/TcffxP4NF/FFBGA5ku+jvKOP7pg= cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= @@ -54,10 +53,6 @@ cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RX cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= cloud.google.com/go/storage v1.45.0 h1:5av0QcIVj77t+44mV4gffFC/LscFRUhto6UBMB5SimM= cloud.google.com/go/storage v1.45.0/go.mod h1:wpPblkIuMP5jCB/E48Pz9zIo2S/zD8g+ITmxKkPCITE= -contrib.go.opencensus.io/exporter/stackdriver v0.12.6/go.mod h1:8x999/OcIPy5ivx/wDiV7Gx4D+VUPODf0mWRGRc5kSk= -contrib.go.opencensus.io/exporter/stackdriver v0.13.4/go.mod h1:aXENhDJ1Y4lIg4EUaVTwzvYETVNZk10Pu26tevFKLUc= -contrib.go.opencensus.io/exporter/stackdriver v0.13.5 h1:TNaexHK16gPUoc7uzELKOU7JULqccn1NDuqUxmxSqfo= -contrib.go.opencensus.io/exporter/stackdriver v0.13.5/go.mod h1:aXENhDJ1Y4lIg4EUaVTwzvYETVNZk10Pu26tevFKLUc= cosmossdk.io/api v0.3.1 h1:NNiOclKRR0AOlO4KIqeaG6PS6kswOMhHD0ir0SscNXE= cosmossdk.io/api v0.3.1/go.mod h1:DfHfMkiNA2Uhy8fj0JJlOCYOBp4eWUUJ1te5zBGNyIw= cosmossdk.io/core v0.5.1 h1:vQVtFrIYOQJDV3f7rw4pjjVqc1id4+mE0L9hHP66pyI= @@ -73,7 +68,6 @@ cosmossdk.io/math v1.3.0/go.mod h1:vnRTxewy+M7BtXBNFybkuhSH4WfedVAAnERHgVFhp3k= cosmossdk.io/tools/rosetta v0.2.1 h1:ddOMatOH+pbxWbrGJKRAawdBkPYLfKXutK9IETnjYxw= cosmossdk.io/tools/rosetta v0.2.1/go.mod h1:Pqdc1FdvkNV3LcNIkYWt2RQY6IP1ge6YWZk8MhhO9Hw= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= -filippo.io/edwards25519 v1.0.0-rc.1/go.mod h1:N1IkdkCkiLB6tki+MYJoSx2JTY9NUlxZE7eHn5EwJns= filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 h1:/vQbFIOMbk2FiG/kXiLl8BRyzTWDw7gX/Hz7Dd5eDMs= @@ -100,8 +94,6 @@ github.com/DataDog/zstd v1.5.2 h1:vUG4lAyuPCXO0TLbXvPv7EB7cNK1QV/luu55UHLrrn8= github.com/DataDog/zstd v1.5.2/go.mod h1:g4AWEaM3yOg3HYfnJ3YIawPnVdXJh9QME85blwSAmyw= github.com/Depado/ginprom v1.8.0 h1:zaaibRLNI1dMiiuj1MKzatm8qrcHzikMlCc1anqOdyo= github.com/Depado/ginprom v1.8.0/go.mod h1:XBaKzeNBqPF4vxJpNLincSQZeMDnZp1tIbU0FU0UKgg= -github.com/GeertJohan/go.incremental v1.0.0/go.mod h1:6fAjUhbVuX1KcMD3c8TEgVUqmo4seqhv0i0kdATSkM0= -github.com/GeertJohan/go.rice v1.0.0/go.mod h1:eH6gbSOAUv07dQuZVnBmoDP8mgsM1rtixis4Tib9if0= github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.24.3 h1:cb3br57K508pQEFgBxn9GDhPS9HefpyMPK1RzmtMNzk= github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.24.3/go.mod h1:itPGVDKf9cC/ov4MdvJ2QZ0khw4bfoo9jzwTJlaxy2k= github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.48.3 h1:xir5X8TS8UBVPWg2jHL+cSTf0jZgqYQSA54TscSt1/0= @@ -133,7 +125,6 @@ github.com/VividCortex/gohistogram v1.0.0 h1:6+hBz+qvs0JOrrNhhmR7lFxo5sINxBCGXrd github.com/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/4+TcAqDqk/vUH7g= github.com/XSAM/otelsql v0.27.0 h1:i9xtxtdcqXV768a5C6SoT/RkG+ue3JTOgkYInzlTOqs= github.com/XSAM/otelsql v0.27.0/go.mod h1:0mFB3TvLa7NCuhm/2nU7/b2wEtsczkj8Rey8ygO7V+A= -github.com/akavel/rsrc v0.8.0/go.mod h1:uLoCtb9J+EyAqh+26kdrTgmzRBFPGOolLWKpdxkKq+c= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= @@ -143,7 +134,6 @@ github.com/alexbrainman/sspi v0.0.0-20210105120005-909beea2cc74/go.mod h1:cEWa1L github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM= github.com/allegro/bigcache v1.2.1 h1:hg1sY1raCwic3Vnsvje6TT7/pnZba83LeFck5NrFKSc= github.com/allegro/bigcache v1.2.1/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM= -github.com/andres-erbsen/clock v0.0.0-20160526145045-9e14626cd129/go.mod h1:rFgpPQZYZ8vdbc+48xibu8ALc3yeyd64IhHS+PU6Yyg= github.com/andybalholm/brotli v1.1.1 h1:PR2pgnyFznKEugtsUo0xLdDop5SKXd5Qf5ysW+7XdTA= github.com/andybalholm/brotli v1.1.1/go.mod h1:05ib4cKhjx3OQYUY22hTVd34Bc8upXjOLL2rKwwZBoA= github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= @@ -163,8 +153,6 @@ github.com/atombender/go-jsonschema v0.16.1-0.20240916205339-a74cd4e2851c h1:cxQ github.com/atombender/go-jsonschema v0.16.1-0.20240916205339-a74cd4e2851c/go.mod h1:3XzxudkrYVUvbduN/uI2fl4lSrMSzU0+3RCu2mpnfx8= github.com/avast/retry-go/v4 v4.6.0 h1:K9xNA+KeB8HHc2aWFuLb25Offp+0iVRXEvFx8IinRJA= github.com/avast/retry-go/v4 v4.6.0/go.mod h1:gvWlPhBVsvBbLkVGDg/KwvBv0bEkCOLRRSHKIr2PyOE= -github.com/aws/aws-sdk-go v1.22.1/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= -github.com/aws/aws-sdk-go v1.23.20/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= github.com/aws/aws-sdk-go v1.54.19 h1:tyWV+07jagrNiCcGRzRhdtVjQs7Vy41NwsuOcl0IbVI= github.com/aws/aws-sdk-go v1.54.19/go.mod h1:eRwEWoyTWFMVYVQzKMNHWP5/RV4xIUGMQfXQHfHkpNU= github.com/bahlo/generic-list-go v0.2.0 h1:5sz/EEAK+ls5wF+NeqDpk5+iNdMDXrh3z3nPnH1Wvgk= @@ -183,7 +171,6 @@ github.com/bgentry/speakeasy v0.1.1-0.20220910012023-760eaf8b6816 h1:41iFGWnSlI2 github.com/bgentry/speakeasy v0.1.1-0.20220910012023-760eaf8b6816/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= github.com/bits-and-blooms/bitset v1.13.0 h1:bAQ9OPNFYbGHV6Nez0tmNI0RiEu7/hxlYJRUA0wFAVE= github.com/bits-and-blooms/bitset v1.13.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8= -github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84= github.com/bketelsen/crypt v0.0.4/go.mod h1:aI6NrJ0pMGgvZKL1iVgXLnfIFJtfV+bKCoqOes/6LfM= github.com/blendle/zapdriver v1.3.1 h1:C3dydBOWYRiOk+B8X9IVZ5IOe+7cl+tGOexN4QqHfpE= github.com/blendle/zapdriver v1.3.1/go.mod h1:mdXfREi6u5MArG4j9fewC+FGnXaBR+T4Ox4J2u4eHCc= @@ -268,9 +255,7 @@ github.com/consensys/gnark-crypto v0.12.1 h1:lHH39WuuFgVHONRl3J0LRBtuYdQTumFSDtJ github.com/consensys/gnark-crypto v0.12.1/go.mod h1:v2Gy7L/4ZRosZ7Ivs+9SfUDr0f5UlG+EM5t7MPHiLuY= github.com/containerd/continuity v0.4.3 h1:6HVkalIp+2u1ZLH1J/pYX2oBVXlJZvh1X1A7bEZ9Su8= github.com/containerd/continuity v0.4.3/go.mod h1:F6PTNCKepoxEaXLQp3wDAjygEnImnZ/7o4JzpodfroQ= -github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= -github.com/coreos/etcd v3.3.13+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk= github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= @@ -278,7 +263,6 @@ github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7 github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= -github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= github.com/cosmos/btcutil v1.0.5 h1:t+ZFcX77LpKtDBhjucvnOH8C2l2ioGsBNEQ3jef8xFk= github.com/cosmos/btcutil v1.0.5/go.mod h1:IyB7iuqZMJlthe2tkIFL33xPyzbFYP0XVdS8P5lUPis= github.com/cosmos/cosmos-proto v1.0.0-beta.5 h1:eNcayDLpip+zVLRLYafhzLvQlSmyab+RC5W7ZfmxJLA= @@ -315,7 +299,6 @@ github.com/creachadair/taskgroup v0.4.2 h1:jsBLdAJE42asreGss2xZGZ8fJra7WtwnHWeJF github.com/creachadair/taskgroup v0.4.2/go.mod h1:qiXUOSrbwAY3u0JPGTzObbE3yf9hcXHDKBZ2ZjpCbgM= github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= -github.com/daaku/go.zipexe v1.0.0/go.mod h1:z8IiR6TsVLEYKwXAoE/I+8ys/sDkgTzSL0CLnGVd57E= github.com/danieljoos/wincred v1.1.2 h1:QLdCxFs1/Yl4zduvBdcHB8goaYk9RARS2SgLLRuAyr0= github.com/danieljoos/wincred v1.1.2/go.mod h1:GijpziifJoIBfYh+S7BbkdUTU4LfM+QnGqR5Vl2tAx0= github.com/danielkov/gin-helmet v0.0.0-20171108135313-1387e224435e h1:5jVSh2l/ho6ajWhSPNN84eHEdq3dp0T7+f6r3Tc6hsk= @@ -329,23 +312,18 @@ github.com/deckarep/golang-set/v2 v2.6.0 h1:XfcQbWM1LlMB8BsJ8N9vW5ehnnPVIw0je80N github.com/deckarep/golang-set/v2 v2.6.0/go.mod h1:VAky9rY/yGXJOLEDv3OMci+7wtDpOF4IN+y82NBOac4= github.com/decred/dcrd/crypto/blake256 v1.0.1 h1:7PltbUIQB7u/FfZ39+DGa/ShuMyJ5ilcvdfma9wOH6Y= github.com/decred/dcrd/crypto/blake256 v1.0.1/go.mod h1:2OfgNZ5wDpcsFmHmCK5gZTPcCXqlm2ArzUIkw9czNJo= -github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 h1:8UrgZ3GkP4i/CLijOJx79Yu+etlyjdBU4sfcs2WYQMs= -github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0/go.mod h1:v57UDF4pDQJcEfFUCRop3lJL149eHGSe9Jvczhzjo/0= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 h1:rpfIENRNNilwHwZeG5+P150SMrnNEcHYvcCuK6dPZSg= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0/go.mod h1:v57UDF4pDQJcEfFUCRop3lJL149eHGSe9Jvczhzjo/0= github.com/desertbit/timer v0.0.0-20180107155436-c41aec40b27f h1:U5y3Y5UE0w7amNe7Z5G/twsBW0KEalRQXZzf8ufSh9I= github.com/desertbit/timer v0.0.0-20180107155436-c41aec40b27f/go.mod h1:xH/i4TFMt8koVQZ6WFms69WAsDWr2XsYL3Hkl7jkoLE= -github.com/dfuse-io/logging v0.0.0-20201110202154-26697de88c79/go.mod h1:V+ED4kT/t/lKtH99JQmKIb0v9WL3VaYkJ36CfHlVECI= -github.com/dfuse-io/logging v0.0.0-20210109005628-b97a57253f70 h1:CuJS05R9jmNlUK8GOxrEELPbfXm0EuGh/30LjkjN5vo= -github.com/dfuse-io/logging v0.0.0-20210109005628-b97a57253f70/go.mod h1:EoK/8RFbMEteaCaz89uessDTnCWjbbcr+DXcBh4el5o= github.com/dgraph-io/badger/v2 v2.2007.4 h1:TRWBQg8UrlUhaFdco01nO2uXwzKS7zd+HVdwV/GHc4o= github.com/dgraph-io/badger/v2 v2.2007.4/go.mod h1:vSw/ax2qojzbN6eXHIx6KPKtCSHJN/Uz0X0VPruTIhk= github.com/dgraph-io/ristretto v0.0.3-0.20200630154024-f66de99634de/go.mod h1:KPxhHT9ZxKefz+PCeOGsrHpl1qZ7i70dGTu2u+Ahh6E= github.com/dgraph-io/ristretto v0.1.1 h1:6CWw5tJNgpegArSHpNHJKldNeq03FQCwYvfMVWajOK8= github.com/dgraph-io/ristretto v0.1.1/go.mod h1:S1GPSBCYCIhmVNfcth17y2zZtQT6wzkzgwUve0VDWWA= -github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13 h1:fAjc9m62+UWV/WAFKLNi6ZS0675eEUC9y3AlwSbQu1Y= github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= -github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= github.com/docker/distribution v2.8.2+incompatible h1:T3de5rq0dB1j30rp0sA2rER+m322EBzniBPB6ZIzuh8= github.com/docker/distribution v2.8.2+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= @@ -379,7 +357,6 @@ github.com/ethereum/go-ethereum v1.14.11/go.mod h1:+l/fr42Mma+xBnhefL/+z11/hcmJ2 github.com/ethereum/go-verkle v0.1.1-0.20240829091221-dffa7562dbe9 h1:8NfxH2iXvJ60YRB8ChToFTUzl8awsc3cJ8CbLjGIl/A= github.com/ethereum/go-verkle v0.1.1-0.20240829091221-dffa7562dbe9/go.mod h1:M3b90YRnzqKyyzBEWJGqj8Qff4IDeXnzFw0P9bFw3uk= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= -github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU= github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= github.com/fatih/color v1.17.0 h1:GlRw1BRJxkpqUCBKzKOw098ed57fEsKeNjpTe3cSjK4= github.com/fatih/color v1.17.0/go.mod h1:YZ7TlrGPkiz6ku9fK3TLD/pl3CpsiFyu8N92HLgmosI= @@ -398,12 +375,12 @@ github.com/fxamacker/cbor/v2 v2.7.0 h1:iM5WgngdRBanHcxugY4JySA0nk1wZorNOpTgCMedv github.com/fxamacker/cbor/v2 v2.7.0/go.mod h1:pxXPTn3joSm21Gbwsv0w9OSA2y1HFR9qXEeXQVeNoDQ= github.com/gabriel-vasile/mimetype v1.4.3 h1:in2uUcidCuFcDKtdcBxlR0rJ1+fsokWf+uqxgUFjbI0= github.com/gabriel-vasile/mimetype v1.4.3/go.mod h1:d8uq/6HKRL6CGdk+aubisF/M5GcPfT7nKyLpA0lbSSk= -github.com/gagliardetto/binary v0.7.7 h1:QZpT38+sgoPg+TIQjH94sLbl/vX+nlIRA37pEyOsjfY= -github.com/gagliardetto/binary v0.7.7/go.mod h1:mUuay5LL8wFVnIlecHakSZMvcdqfs+CsotR5n77kyjM= +github.com/gagliardetto/binary v0.8.0 h1:U9ahc45v9HW0d15LoN++vIXSJyqR/pWw8DDlhd7zvxg= +github.com/gagliardetto/binary v0.8.0/go.mod h1:2tfj51g5o9dnvsc+fL3Jxr22MuWzYXwx9wEoN0XQ7/c= github.com/gagliardetto/gofuzz v1.2.2 h1:XL/8qDMzcgvR4+CyRQW9UGdwPRPMHVJfqQ/uMvSUuQw= github.com/gagliardetto/gofuzz v1.2.2/go.mod h1:bkH/3hYLZrMLbfYWA0pWzXmi5TTRZnu4pMGZBkqMKvY= -github.com/gagliardetto/solana-go v1.8.4 h1:vmD/JmTlonyXGy39bAo0inMhmbdAwV7rXZtLDMZeodE= -github.com/gagliardetto/solana-go v1.8.4/go.mod h1:i+7aAyNDTHG0jK8GZIBSI4OVvDqkt2Qx+LklYclRNG8= +github.com/gagliardetto/solana-go v1.12.0 h1:rzsbilDPj6p+/DOPXBMLhwMZeBgeRuXjm5zQFCoXgsg= +github.com/gagliardetto/solana-go v1.12.0/go.mod h1:l/qqqIN6qJJPtxW/G1PF4JtcE3Zg2vD2EliZrr9Gn5k= github.com/gagliardetto/treeout v0.1.4 h1:ozeYerrLCmCubo1TcIjFiOWTTGteOOHND1twdFpgwaw= github.com/gagliardetto/treeout v0.1.4/go.mod h1:loUefvXTrlRG5rYmJmExNryyBRh8f89VZhmMOyCyqok= github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08 h1:f6D9Hr8xV8uYKlyuj8XIruxlh9WjVjdh1gIicAS7ays= @@ -507,7 +484,6 @@ github.com/golang-jwt/jwt/v5 v5.2.1/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVI github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/glog v1.2.2 h1:1+mZ9upx1Dh6FmUTFR1naJ77miKiXgALjWOZ3NVFPmY= github.com/golang/glog v1.2.2/go.mod h1:6AhwSGph0fcJtXVM/PEHPqZlFeoLxhs7/t5UDAwmO+w= -github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= @@ -543,7 +519,6 @@ github.com/golang/protobuf v1.5.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= -github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb h1:PBC98N2aIaM3XXiurYmW7fx4GZkL8feAMVq7nEjURHk= @@ -618,12 +593,10 @@ github.com/gorilla/handlers v1.5.1 h1:9lRY6j8DEeeBT10CvO9hGW0gmky0BprnvDI5vfhUHH github.com/gorilla/handlers v1.5.1/go.mod h1:t8XrUpc4KVXb7HGyJ4/cEnwQiaxrX/hz1Zv/4g96P1Q= github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI= github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= -github.com/gorilla/rpc v1.2.0/go.mod h1:V4h9r+4sF5HnzqbwIez0fKSpANP0zlYd3qR7p36jkTQ= github.com/gorilla/securecookie v1.1.2 h1:YCIWL56dvtr73r6715mJs5ZvhtnY73hBvEF8kXD8ePA= github.com/gorilla/securecookie v1.1.2/go.mod h1:NfCASbcHqRSY+3a8tlWJwsQap2VX5pwzwo4h3eOamfo= github.com/gorilla/sessions v1.2.2 h1:lqzMYz6bOfvn2WriPUjNByzeXIlVzURcPmgMczkmTjY= github.com/gorilla/sessions v1.2.2/go.mod h1:ePLdVu+jbEgHH+KWw8I1z2wqd0BAdAQh/8LRvBeoNcQ= -github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY= github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY= github.com/grafana/pyroscope-go v1.1.2 h1:7vCfdORYQMCxIzI3NlYAs3FcBP760+gWuYWOyiVyYx8= @@ -634,15 +607,12 @@ github.com/graph-gophers/dataloader v5.0.0+incompatible h1:R+yjsbrNq1Mo3aPG+Z/EK github.com/graph-gophers/dataloader v5.0.0+incompatible/go.mod h1:jk4jk0c5ZISbKaMe8WsVopGB5/15GvGHMdMdPtwlRp4= github.com/graph-gophers/graphql-go v1.5.0 h1:fDqblo50TEpD0LY7RXk/LFVYEVqo3+tXMNMPSVXA1yc= github.com/graph-gophers/graphql-go v1.5.0/go.mod h1:YtmJZDLbF1YYNrlNAuiO5zAStUWc3XZT07iGsVqe1Os= -github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 h1:+9834+KizmvFV7pXQGSXQTsaWhq2GjuNUt0aUU0YBYw= github.com/grpc-ecosystem/go-grpc-middleware v1.3.0/go.mod h1:z0ButlSOZa5vEBq9m2m2hlwIgKw+rp3sdCBRoJY+30Y= github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.0.1 h1:qnpSQwGEnkcRpTqNOIR6bJbR0gAorgP9CSALpRcKoAA= github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.0.1/go.mod h1:lXGCsh6c22WGtjr+qGHj1otzZpV/1kwTMAqkwZsnWRU= github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.1.0 h1:pRhl55Yx1eC7BZ1N+BBWwnKaMyD8uC+34TLdndZMAKk= github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.1.0/go.mod h1:XKMd7iuf/RGPSMJ/U4HP0zS2Z9Fh8Ps9a+6X26m/tmI= -github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= -github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= github.com/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4M0+kPpLofRdBo= github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= github.com/grpc-ecosystem/grpc-gateway/v2 v2.22.0 h1:asbCHRVmodnJTuQ3qamDwqVOIjwqUPTYmYuemVOx+Ys= @@ -695,7 +665,6 @@ github.com/hashicorp/go-version v1.6.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09 github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/hashicorp/golang-lru v0.5.3/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= github.com/hashicorp/golang-lru v0.6.0 h1:uL2shRDx7RTrOrTCUZEGP/wJUFiUI8QT6E7z5o8jga4= github.com/hashicorp/golang-lru v0.6.0/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k= @@ -789,10 +758,8 @@ github.com/jackc/puddle v0.0.0-20190608224051-11cab39313c9/go.mod h1:m4B5Dj62Y0f github.com/jackc/puddle v1.1.3/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= github.com/jackpal/go-nat-pmp v1.0.2 h1:KzKSgb7qkJvOUTqYl9/Hg/me3pWgBmERKrTGD7BdWus= github.com/jackpal/go-nat-pmp v1.0.2/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc= -github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jhump/protoreflect v1.15.1 h1:HUMERORf3I3ZdX05WaQ6MIpd/NJ434hTp5YiKgfCL6c= github.com/jhump/protoreflect v1.15.1/go.mod h1:jD/2GMKKE6OqX8qTjhADU1e6DShO+gavG9e0Q693nKo= -github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg= github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= github.com/jmhodges/levigo v1.0.0 h1:q5EC36kV79HWeTBWsod3mG11EgStG3qArTKcvlksN1U= @@ -801,7 +768,6 @@ github.com/jmoiron/sqlx v1.4.0 h1:1PLqN7S1UYp5t4SrVVnt4nUVNemrDAtxlulVe+Qgm3o= github.com/jmoiron/sqlx v1.4.0/go.mod h1:ZrZ7UsYB/weZdl2Bxg6jCRO9c3YHl8r3ahlKmRT4JLY= github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0= github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4= -github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= github.com/jonboulle/clockwork v0.4.0 h1:p4Cf1aMWXnXAUh8lVfewRBx1zaTSYKrKMF2g3ST4RZ4= github.com/jonboulle/clockwork v0.4.0/go.mod h1:xgRqUGwRcjKCO1vbZUEtSLrqKoPSsUpK7fnezOII0kc= github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= @@ -822,7 +788,6 @@ github.com/klauspost/asmfmt v1.3.2 h1:4Ri7ox3EwapiOjCki+hw14RyKk201CN4rzyCJRFLpK github.com/klauspost/asmfmt v1.3.2/go.mod h1:AG8TuvYojzulgDAMCnYn50l/5QV3Bs/tp6j0HLHbNSE= github.com/klauspost/compress v1.11.4/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= github.com/klauspost/compress v1.12.3/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg= -github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= github.com/klauspost/compress v1.17.11 h1:In6xLpyWOi1+C7tXUUWv2ot1QvBjxevKAaI6IXrJmUc= github.com/klauspost/compress v1.17.11/go.mod h1:pMDklpSncoRMuLFrf1W9Ss9KT+0rH90U12bZKk7uwG0= github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= @@ -864,7 +829,6 @@ github.com/logrusorgru/aurora v2.0.3+incompatible h1:tOpm7WcpBTn4fjmVfgpQq0EfczG github.com/logrusorgru/aurora v2.0.3+incompatible/go.mod h1:7rIyQOR62GCctdiQpZ/zOJlFyk6y+94wXzv6RNZgaR4= github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I= github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= -github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/magiconair/properties v1.8.5/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= @@ -878,7 +842,6 @@ github.com/marcboeker/go-duckdb v1.8.3 h1:ZkYwiIZhbYsT6MmJsZ3UPTHrTZccDdM4ztoqSl github.com/marcboeker/go-duckdb v1.8.3/go.mod h1:C9bYRE1dPYb1hhfu/SSomm78B0FXmNgRvv6YBW/Hooc= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ= -github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= @@ -887,8 +850,6 @@ github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovk github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= -github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= -github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= @@ -948,7 +909,6 @@ github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lN github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= -github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc= github.com/mostynb/zstdpool-freelist v0.0.0-20201229113212-927304c0c3b1 h1:mPMvm6X6tf4w8y7j9YIt6V9jfWhL6QlbEc7CCmeQlWk= github.com/mostynb/zstdpool-freelist v0.0.0-20201229113212-927304c0c3b1/go.mod h1:ye2e/VUEtE2BHE+G/QcKkcLQVAEJoYRFj5VUOQatCRE= github.com/mr-tron/base58 v1.2.0 h1:T/HDJBh4ZCPbU39/+c3rRvE0uKBQlU27+QI8LJ4t64o= @@ -963,7 +923,6 @@ github.com/ncruces/go-strftime v0.1.9/go.mod h1:Fwc5htZGVVkseilnfgOVb9mKy6w1naJm github.com/neelance/astrewrite v0.0.0-20160511093645-99348263ae86/go.mod h1:kHJEU3ofeGjhHklVoIGuVj85JJwZ6kWPaJwCIxgnFmo= github.com/neelance/sourcemap v0.0.0-20200213170602-2833bce08e4c/go.mod h1:Qr6/a/Q4r9LP1IltGz7tA7iOK1WonHEYhu1HRBA7ZiM= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= -github.com/nkovacs/streamquote v0.0.0-20170412213628-49af9bddb229/go.mod h1:0aYXnNPJ8l7uZxf45rWW1a/uME32OF0rhiYGNQ2oF2E= github.com/nsf/jsondiff v0.0.0-20230430225905-43f6cf3098c1 h1:dOYG7LS/WK00RWZc8XGgcUTlTxpp3mKhdR2Q9z9HbXM= github.com/nsf/jsondiff v0.0.0-20230430225905-43f6cf3098c1/go.mod h1:mpRZBD8SJ55OIICQ3iWH0Yz3cjzA61JdqMLoWXeB2+8= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= @@ -971,7 +930,6 @@ github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= github.com/oklog/run v1.1.0 h1:GEenZ1cK0+q0+wsJew9qUg/DyD8k3JzYsZAi5gYi2mA= github.com/oklog/run v1.1.0/go.mod h1:sVPdnTZT1zYwAJeCMu2Th4T21pA3FPOQRfWjQlk7DVU= -github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= @@ -1036,7 +994,6 @@ github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:Om github.com/pressly/goose/v3 v3.21.1 h1:5SSAKKWej8LVVzNLuT6KIvP1eFDuPvxa+B6H0w78buQ= github.com/pressly/goose/v3 v3.21.1/go.mod h1:sqthmzV8PitchEkjecFJII//l43dLOCzfWh8pHEe+vE= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= -github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= github.com/prometheus/client_golang v1.20.5 h1:cxppBPuYhUnsO6yo/aoRol4L7q7UFfdm+bR9r+8l63Y= @@ -1047,21 +1004,17 @@ github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1: github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E= github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= -github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= -github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4= github.com/prometheus/common v0.60.0 h1:+V9PAREWNvJMAuJ1x1BaWl9dewMW4YrHZQbx0sJNllA= github.com/prometheus/common v0.60.0/go.mod h1:h0LYf1R1deLSKtD4Vdg8gy4RuOvENW2J/h19V5NADQw= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= -github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc= github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk= github.com/prometheus/prometheus v0.54.1 h1:vKuwQNjnYN2/mDoWfHXDhAsz/68q/dQDb+YbcEqU7MQ= github.com/prometheus/prometheus v0.54.1/go.mod h1:xlLByHhk2g3ycakQGrMaU8K7OySZx98BzeCR99991NY= -github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= github.com/rakyll/statik v0.1.7 h1:OF3QCZUuyPxuGEP7B4ypUa7sB/iHtqOTDYZXGM8KOdQ= github.com/rakyll/statik v0.1.7/go.mod h1:AlZONWzMtEnMs7W4e/1LURLiI49pIMmp6V9Unghqrcc= github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 h1:N/ElC8H3+5XpJzTSTfLsJV/mx9Q9g7kxmchpfZyxgzM= @@ -1075,7 +1028,6 @@ github.com/rivo/uniseg v0.4.4 h1:8TfxU8dW6PdqD27gjM8MVNuicgxIjxpm4K7x4jp8sis= github.com/rivo/uniseg v0.4.4/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs= github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro= -github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= @@ -1139,6 +1091,8 @@ github.com/smartcontractkit/chainlink-automation v0.8.1 h1:sTc9LKpBvcKPc1JDYAmgB github.com/smartcontractkit/chainlink-automation v0.8.1/go.mod h1:Iij36PvWZ6blrdC5A/nrQUBuf3MH3JvsBB9sSyc9W08= github.com/smartcontractkit/chainlink-ccip v0.0.0-20241218114855-f74219171000 h1:6Zzr/R1j6P7bbvcUlt5WUIbItvrrGdGzIsiAzQezcwo= github.com/smartcontractkit/chainlink-ccip v0.0.0-20241218114855-f74219171000/go.mod h1:ncjd6mPZSRlelEqH/2KeLE1pU3UlqzBSn8RYkEoECzY= +github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20241223194433-f25773de7c0e h1:aZ9IMSlI3qxelcNqhkOIwK7Z8I5HpCmWvAeOdFzCKwE= +github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20241223194433-f25773de7c0e/go.mod h1:Bmwq4lNb5tE47sydN0TKetcLEGbgl+VxHEWp4S0LI60= github.com/smartcontractkit/chainlink-common v0.4.1-0.20241217120918-bbe318cd0760 h1:lB5A3TP0zOVuu1n0kEm6d8/o/4Knh6HLvsU/GChk+sI= github.com/smartcontractkit/chainlink-common v0.4.1-0.20241217120918-bbe318cd0760/go.mod h1:yti7e1+G9hhkYhj+L5sVUULn9Bn3bBL5/AxaNqdJ5YQ= github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241202195413-82468150ac1e h1:PRoeby6ZlTuTkv2f+7tVU4+zboTfRzI+beECynF4JQ0= @@ -1167,7 +1121,6 @@ github.com/smarty/assertions v1.15.0/go.mod h1:yABtdzeQs6l1brC900WlRNwj6ZR55d7B+ github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/smartystreets/goconvey v1.8.1/go.mod h1:+/u4qLyY6x1jReYOp7GOM2FSt8aP9CzCZL03bI28W60= -github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo= github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= @@ -1182,7 +1135,6 @@ github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkU github.com/spf13/cast v1.6.0 h1:GEiTHELF+vaR5dhz3VqZfFSzZjYbgeKDpBxQVS4GYJ0= github.com/spf13/cast v1.6.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo= github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU= -github.com/spf13/cobra v1.1.1/go.mod h1:WnodtKOvamDL/PwE2M4iKs8aMDBZ5Q5klgD3qfVJQMI= github.com/spf13/cobra v1.2.1/go.mod h1:ExllRjgxM/piMAM+3tAZvg8fsklGAf3tPfi+i8t68Nk= github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM= github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y= @@ -1192,15 +1144,13 @@ github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnIn github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= -github.com/spf13/viper v1.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg= -github.com/spf13/viper v1.7.1/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg= github.com/spf13/viper v1.8.1/go.mod h1:o0Pch8wJ9BVSWGQMbra6iw0oQ5oktSIBaujf1rJH9Ns= github.com/spf13/viper v1.19.0 h1:RWq5SEjt8o25SROyN3z2OrDB9l7RPd3lwTWU8EcEdcI= github.com/spf13/viper v1.19.0/go.mod h1:GQUN9bilAbhU/jgc1bKs99f/suXKeUMct8Adx5+Ntkg= github.com/status-im/keycard-go v0.2.0 h1:QDLFswOQu1r5jsycloeQh3bVU8n/NatHHaZobtDnDzA= github.com/status-im/keycard-go v0.2.0/go.mod h1:wlp8ZLbsmrF6g6WjugPAx+IzoLrkdf9+mHxBEeo3Hbg= -github.com/streamingfast/logging v0.0.0-20220405224725-2755dab2ce75 h1:ZqpS7rAhhKD7S7DnrpEdrnW1/gZcv82ytpMviovkli4= -github.com/streamingfast/logging v0.0.0-20220405224725-2755dab2ce75/go.mod h1:VlduQ80JcGJSargkRU4Sg9Xo63wZD/l8A5NC/Uo1/uU= +github.com/streamingfast/logging v0.0.0-20230608130331-f22c91403091 h1:RN5mrigyirb8anBEtdjtHFIufXdacyTi6i4KBfeNXeo= +github.com/streamingfast/logging v0.0.0-20230608130331-f22c91403091/go.mod h1:VlduQ80JcGJSargkRU4Sg9Xo63wZD/l8A5NC/Uo1/uU= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= @@ -1220,8 +1170,9 @@ github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1F github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= -github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= +github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8= github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= @@ -1231,21 +1182,16 @@ github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d h1:vfofYNRScrDd github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d/go.mod h1:RRCYJbIwD5jmqPI9XoAFR0OcDxqUctll6zUj/+B4S48= github.com/tendermint/go-amino v0.16.0 h1:GyhmgQKvqF82e2oZeuMSp9JTN0N09emoSZlb2lyGa2E= github.com/tendermint/go-amino v0.16.0/go.mod h1:TQU0M1i/ImAo+tYpZi73AU3V/dKeCoMC9Sphe2ZwGME= -github.com/teris-io/shortid v0.0.0-20171029131806-771a37caa5cf/go.mod h1:M8agBzgqHIhgj7wEn9/0hJUZcrvt9VY+Ln+S1I5Mha0= -github.com/teris-io/shortid v0.0.0-20201117134242-e59966efd125 h1:3SNcvBmEPE1YlB1JpVZouslJpI3GBNoiqW7+wb0Rz7w= -github.com/teris-io/shortid v0.0.0-20201117134242-e59966efd125/go.mod h1:M8agBzgqHIhgj7wEn9/0hJUZcrvt9VY+Ln+S1I5Mha0= github.com/test-go/testify v1.1.4 h1:Tf9lntrKUMHiXQ07qBScBTSA0dhYQlu83hswqelv1iE= github.com/test-go/testify v1.1.4/go.mod h1:rH7cfJo/47vWGdi4GPj16x3/t1xGOj2YxzmNQzk2ghU= github.com/theodesp/go-heaps v0.0.0-20190520121037-88e35354fe0a h1:YuO+afVc3eqrjiCUizNCxI53bl/BnPiVwXqLzqYTqgU= github.com/theodesp/go-heaps v0.0.0-20190520121037-88e35354fe0a/go.mod h1:/sfW47zCZp9FrtGcWyo1VjbgDaodxX9ovZvgLb/MxaA= github.com/tidwall/btree v1.6.0 h1:LDZfKfQIBHGHWSwckhXI0RPSXzlo+KYdjK7FWSqOzzg= github.com/tidwall/btree v1.6.0/go.mod h1:twD9XRA5jj9VUQGELzDO4HPQTNJsoWWfYEL+EUQ2cKY= -github.com/tidwall/gjson v1.9.3/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= github.com/tidwall/gjson v1.17.0 h1:/Jocvlh98kcTfpN2+JzGQWQcqrPQwDrVEMApx/M5ZwM= github.com/tidwall/gjson v1.17.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA= github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM= -github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= github.com/tidwall/pretty v1.2.1 h1:qjsOFOWWQl+N3RsoF5/ssm1pHmJJwhjlSbZ51I6wMl4= github.com/tidwall/pretty v1.2.1/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= @@ -1253,7 +1199,6 @@ github.com/tklauser/go-sysconf v0.3.12 h1:0QaGUFOdQaIVdPgfITYzaTegZvdCjmYO52cSFA github.com/tklauser/go-sysconf v0.3.12/go.mod h1:Ho14jnntGE1fpdOqQEEaiKRpvIavV0hSfmBq8nJbHYI= github.com/tklauser/numcpus v0.6.1 h1:ng9scYS7az0Bk4OZLvrNXNSAO2Pxr1XXRAPyjhIx+Fk= github.com/tklauser/numcpus v0.6.1/go.mod h1:1XfjsgE2zo8GVw7POkMbHENHzVg3GzmoZ9fESEdAacY= -github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM= github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI= github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08= @@ -1279,24 +1224,17 @@ github.com/urfave/cli v1.22.14 h1:ebbhrRiGK2i4naQJr+1Xj92HXZCrK7MsyTS/ob3HnAk= github.com/urfave/cli v1.22.14/go.mod h1:X0eDS6pD6Exaclxm99NJ3FiCDRED7vIHpx2mDOHLvkA= github.com/urfave/cli/v2 v2.25.7 h1:VAzn5oq403l5pHjc4OhD54+XGO9cdKVL/7lDjF+iKUs= github.com/urfave/cli/v2 v2.25.7/go.mod h1:8qnjx1vcq5s2/wpsqoZFndg2CE5tNFyrTvS6SinrnYQ= -github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= github.com/valyala/fastjson v1.4.1 h1:hrltpHpIpkaxll8QltMU8c3QZ5+qIiCL8yKqPFJI/yE= github.com/valyala/fastjson v1.4.1/go.mod h1:nV6MsjxL2IMJQUoHDIrjEI7oLyeqK6aBD7EFWPsvP8o= -github.com/valyala/fasttemplate v1.0.1/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPUpymEIMZ47gx8= github.com/wk8/go-ordered-map/v2 v2.1.8 h1:5h/BUHu93oj4gIdvHHHGsScSTMijfx5PeYkE/fJgbpc= github.com/wk8/go-ordered-map/v2 v2.1.8/go.mod h1:5nJHM5DyteebpVlHnWMV0rPz6Zp7+xBAnxjb1X5vnTw= github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM= github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg= -github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI= -github.com/xdg-go/scram v1.1.1/go.mod h1:RaEWvsqvNKKvBPvcKeFjrG2cJqOkHTiyTpzz23ni57g= -github.com/xdg-go/stringprep v1.0.3/go.mod h1:W3f5j4i+9rC0kuIEJL0ky1VpHXQU3ocBgklLGvcBnW8= -github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 h1:bAn7/zixMGCfxrRTfdpNzjtPYqr8smhKouy9mxVdGPU= github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673/go.mod h1:N3UwUGtsrSj3ccvlPHLoLsHnpR27oXr4ZE984MbSER8= github.com/xyproto/randomstring v1.0.5 h1:YtlWPoRdgMu3NZtP45drfy1GKoojuR7hmRcnhZqKjWU= github.com/xyproto/randomstring v1.0.5/go.mod h1:rgmS5DeNXLivK7YprL0pY+lTuhNQW3iGxZ18UQApw/E= -github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d/go.mod h1:rHwXgn7JulP+udvsHwJoVG1YGAP6VLg4y9I5dyZdqmA= github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= @@ -1324,18 +1262,15 @@ go.dedis.ch/protobuf v1.0.5/go.mod h1:eIV4wicvi6JK0q/QnfIEGeSFNG0ZeB24kzut5+HaRL go.dedis.ch/protobuf v1.0.7/go.mod h1:pv5ysfkDX/EawiPqcW3ikOxsL5t+BqnV6xHSmE79KI4= go.dedis.ch/protobuf v1.0.11 h1:FTYVIEzY/bfl37lu3pR4lIj+F9Vp1jE8oh91VmxKgLo= go.dedis.ch/protobuf v1.0.11/go.mod h1:97QR256dnkimeNdfmURz0wAMNVbd1VmLXhG1CrTYrJ4= -go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.etcd.io/bbolt v1.3.9 h1:8x7aARPEXiXbHmtUwAIv7eV2fQFHrLLavdiJ3uzJXoI= go.etcd.io/bbolt v1.3.9/go.mod h1:zaO32+Ti0PK1ivdPtgMESzuzL2VPoIG1PCQNvOdo/dE= go.etcd.io/etcd/api/v3 v3.5.0/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs= go.etcd.io/etcd/client/pkg/v3 v3.5.0/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g= go.etcd.io/etcd/client/v2 v2.305.0/go.mod h1:h9puh54ZTgAKtEbut2oe9P4L/oqKCVB6xsXlzd7alYQ= -go.mongodb.org/mongo-driver v1.11.0/go.mod h1:s7p5vEtfbeR1gYi6pnj3c3/urpbLv2T5Sfd6Rp2HBB8= go.mongodb.org/mongo-driver v1.15.0 h1:rJCKC8eEliewXjZGf0ddURtl7tTVy1TK3bfl0gkUSLc= go.mongodb.org/mongo-driver v1.15.0/go.mod h1:Vzb0Mk/pa7e6cWw85R4F/endUC3u0U9jGcNU603k65c= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= -go.opencensus.io v0.22.1/go.mod h1:Ap50jQcDJrx6rB6VgeeFPtuPIf3wMRvRfrfYDO6+BmA= go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= @@ -1407,15 +1342,12 @@ go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKY go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= -go.uber.org/ratelimit v0.2.0/go.mod h1:YYBV4e4naJvhpitQrWJu1vCpgB7CboMe0qhltKt6mUg= go.uber.org/ratelimit v0.3.1 h1:K4qVE+byfv/B3tC+4nYWP7v/6SimcO7HzHekoMNBma0= go.uber.org/ratelimit v0.3.1/go.mod h1:6euWsTB6U/Nb3X++xEUXA8ciPJvr19Q/0h1+oDcJhRk= go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA= go.uber.org/zap v1.9.1/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= -go.uber.org/zap v1.14.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= -go.uber.org/zap v1.16.0/go.mod h1:MA8QOfq0BHJwdXa996Y4dYkAqRKB8/1K1QMMZVaNZjQ= go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo= go.uber.org/zap v1.21.0/go.mod h1:wjWOCqI0f2ZZrJF/UufIOkiC8ii6tm1iqIsLo76RfJw= go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= @@ -1442,7 +1374,6 @@ golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5y golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20220214200702-86341886e292/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.3.0/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4= golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc= golang.org/x/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U= @@ -1457,8 +1388,8 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0 golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= -golang.org/x/exp v0.0.0-20241009180824-f66d83c29e7c h1:7dEasQXItcW1xKJ2+gg5VOiBnqWrJc+rq0DPKyvvdbY= -golang.org/x/exp v0.0.0-20241009180824-f66d83c29e7c/go.mod h1:NQtJDoLvd6faHhE7m4T/1IY708gDefGGjR/iUW8yQQ8= +golang.org/x/exp v0.0.0-20241210194714-1829a127f884 h1:Y/Mj/94zIQQGHVSv1tTtQBDaQaJe62U9bkDZKKyhPCU= +golang.org/x/exp v0.0.0-20241210194714-1829a127f884/go.mod h1:qj5a5QZpwLU2NLQudwIN5koi3beDhSAlJwa67PuM98c= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= @@ -1487,15 +1418,14 @@ golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.9.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/mod v0.21.0 h1:vvrHzRwRfVKSiLrG+d4FMl/Qi4ukBCE6kZlTUkDYRT0= -golang.org/x/mod v0.21.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY= +golang.org/x/mod v0.22.0 h1:D4nJWe9zXqHOmWqj4VMOJhvzj7bEZg4wEYa759z1pH4= +golang.org/x/mod v0.22.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= @@ -1508,7 +1438,6 @@ golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= @@ -1542,8 +1471,8 @@ golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= -golang.org/x/net v0.30.0 h1:AcW1SDZMkb8IpzCdQUaIq2sP4sZ4zw+55h6ynffypl4= -golang.org/x/net v0.30.0/go.mod h1:2wGyMJ5iFasEhkwi13ChkO/t1ECNC4X4eBKkVFyYFlU= +golang.org/x/net v0.32.0 h1:ZqPmj8Kzc+Y6e0+skZsuACbx+wzMgo5MQsJh9Qd6aYI= +golang.org/x/net v0.32.0/go.mod h1:CwU0IoeOlnQQWJ6ioyFrfRuomB8GKF6KbYXZVyeXNfs= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -1578,7 +1507,6 @@ golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190124100055-b90733256f2e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -1594,7 +1522,6 @@ golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190804053845-51ab0e2deafa/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -1660,7 +1587,6 @@ golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA= golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.0.0-20201210144234-2321bbc49cbf/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= @@ -1707,7 +1633,6 @@ golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgw golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20190823170909-c4a336ef6a2f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191010075000-0337d82405ff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= @@ -1717,7 +1642,6 @@ golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtn golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191216052735-49a3e744a425/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200103221440-774c71fcf114/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= @@ -1753,8 +1677,8 @@ golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= golang.org/x/tools v0.7.0/go.mod h1:4pg6aUX35JBAogB10C9AtvVL+qowtN4pT3CGSQex14s= -golang.org/x/tools v0.26.0 h1:v/60pFQmzmT9ExmjDv2gGIfi3OqfKoEP6I5+umXlbnQ= -golang.org/x/tools v0.26.0/go.mod h1:TPVVj70c7JJ3WCazhD8OdXcZg/og+b9+tH/KxylGwH0= +golang.org/x/tools v0.28.0 h1:WuB6qZ4RPCQo5aP3WdKZS7i595EdWqWR8vqJTlwTVK8= +golang.org/x/tools v0.28.0/go.mod h1:dcIOrVd3mfQKTgrDVQHqCPMWy6lnhfhtX3hLXYVLfRw= golang.org/x/xerrors v0.0.0-20190410155217-1f06c39b4373/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20190513163551-3ee3066db522/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -1770,7 +1694,6 @@ google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEt google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= -google.golang.org/api v0.10.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= @@ -1795,7 +1718,6 @@ google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9Ywl google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= -google.golang.org/appengine v1.6.2/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= @@ -1805,7 +1727,6 @@ google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRn google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190716160619-c506a9f90610/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= @@ -1854,9 +1775,7 @@ google.golang.org/genproto/googleapis/rpc v0.0.0-20241021214115-324edc3d5d38/go. google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= -google.golang.org/grpc v1.22.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= -google.golang.org/grpc v1.23.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= @@ -1908,16 +1827,13 @@ gopkg.in/guregu/null.v2 v2.1.2/go.mod h1:XORrx8tyS5ZDcyUboCIxQtta/Aujk/6pfWrn9Xe gopkg.in/guregu/null.v4 v4.0.0 h1:1Wm3S1WEA2I26Kq+6vcW+w0gcDo44YKYD7YIEJNHDjg= gopkg.in/guregu/null.v4 v4.0.0/go.mod h1:YoQhUrADuG3i9WqesrCmpNRwm1ypAgSHYqoOcTu/JrI= gopkg.in/inconshreveable/log15.v2 v2.0.0-20180818164646-67afb5ed74ec/go.mod h1:aPpfJ7XW+gOuirDoZ8gHhLh3kZ1B08FtV2bbmy7Jv3s= -gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/ini.v1 v1.62.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/natefinch/lumberjack.v2 v2.2.1 h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST95x9zc= gopkg.in/natefinch/lumberjack.v2 v2.2.1/go.mod h1:YD8tP3GAjkrDg1eZH7EGmyESg/lsYskCTPBJVb9jqSc= -gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= -gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= From 5cab81f8a1714a73085261379cde50bda6d52fa7 Mon Sep 17 00:00:00 2001 From: Joe Huang Date: Mon, 30 Dec 2024 11:06:49 -0600 Subject: [PATCH 4/4] Revert "merge" This reverts commit d44ab93413aaf1cfb7b2ffdc5e1b97b1edd609aa, reversing changes made to a62a32145a8e5f8ae68ef1caff766e53fd867380. --- .changeset/afraid-houses-learn.md | 5 - .changeset/beige-geckos-explode.md | 5 - .changeset/big-camels-report.md | 5 - .changeset/brave-cooks-itch.md | 5 - .changeset/breezy-kings-clean.md | 5 - .changeset/bright-keys-whisper.md | 5 - .changeset/chilled-papayas-swim.md | 5 - .changeset/chilled-suits-do.md | 5 - .changeset/chilly-stingrays-press.md | 5 - .changeset/clean-files-beg.md | 5 - .changeset/cool-penguins-raise.md | 5 - .changeset/dull-readers-rush.md | 5 - .changeset/eight-tigers-march.md | 5 - .changeset/eighty-geckos-switch.md | 5 - .changeset/five-gifts-end.md | 5 - .changeset/forty-foxes-rescue.md | 5 - .changeset/fuzzy-hairs-appear.md | 5 - .changeset/fuzzy-yaks-deny.md | 5 - .changeset/giant-eels-jump.md | 5 - .changeset/great-peaches-walk.md | 5 - .changeset/hot-islands-dress.md | 5 - .changeset/kind-parents-jump.md | 11 - .changeset/large-fishes-enjoy.md | 5 - .changeset/late-doors-battle.md | 5 - .changeset/late-seals-battle.md | 5 - .changeset/late-windows-clean.md | 11 - .changeset/light-trains-chew.md | 5 - .changeset/many-crews-wave.md | 5 - .changeset/mean-dots-move.md | 5 - .changeset/mean-knives-knock.md | 5 - .changeset/mean-ravens-stare.md | 5 - .changeset/metal-houses-approve.md | 5 - .changeset/popular-rules-live.md | 5 - .changeset/shaggy-carpets-deliver.md | 5 - .changeset/shiny-owls-destroy.md | 6 - .changeset/silver-avocados-buy.md | 5 - .changeset/six-coins-mix.md | 5 - .changeset/sixty-queens-wait.md | 5 - .changeset/sour-hairs-cross.md | 5 - .changeset/spotty-knives-smile.md | 5 - .changeset/spotty-seals-give.md | 5 - .changeset/thin-cats-try.md | 5 - .changeset/three-mayflies-learn.md | 5 - .changeset/tiny-kangaroos-switch.md | 5 - .changeset/tricky-clouds-move.md | 5 - .changeset/wet-bags-clean.md | 5 - .changeset/wild-cats-think.md | 5 - .github/CODEOWNERS | 13 +- .github/actions/golangci-lint/action.yml | 60 +- .../goreleaser-build-sign-publish/action.yml | 18 - .../goreleaser-build-sign-publish/release.js | 5 +- .../actions/setup-ci-core-tests/action.yml | 61 - .github/actions/setup-go/action.yml | 15 +- .github/actions/version-file-bump/action.yml | 2 +- .github/e2e-tests.yml | 269 +- .github/integration-in-memory-tests.yml | 83 - .../scripts/map-affected-files-to-modules.sh | 60 - .../workflows/automation-benchmark-tests.yml | 7 +- .github/workflows/automation-load-tests.yml | 9 +- .../workflows/automation-ondemand-tests.yml | 9 +- .../workflows/build-publish-develop-pr.yml | 131 +- .github/workflows/build-publish.yml | 44 +- .github/workflows/ccip-chaos-tests.yml | 10 +- .github/workflows/ccip-load-tests.yml | 10 +- .github/workflows/changeset.yml | 45 - .github/workflows/ci-core-partial.yml | 288 -- .github/workflows/ci-core.yml | 191 +- .github/workflows/ci-scripts.yml | 41 + .../workflows/client-compatibility-tests.yml | 3 + .github/workflows/crib-integration-test.yml | 10 +- .github/workflows/delete-caches.yml | 4 - .github/workflows/find-new-flaky-tests.yml | 566 +++ .github/workflows/flakeguard-nightly.yml | 25 - .github/workflows/flakeguard.yml | 573 --- .github/workflows/integration-chaos-tests.yml | 47 +- .../workflows/integration-in-memory-tests.yml | 145 - .github/workflows/integration-tests.yml | 64 +- .github/workflows/on-demand-ocr-soak-test.yml | 9 +- .../on-demand-vrfv2-performance-test.yml | 2 +- .../workflows/on-demand-vrfv2-smoke-tests.yml | 2 +- .../on-demand-vrfv2plus-performance-test.yml | 2 +- .../on-demand-vrfv2plus-smoke-tests.yml | 2 +- ...emand.yml => run-find-new-flaky-tests.yml} | 34 +- .github/workflows/run-nightly-e2e-tests.yml | 2 +- .../run-nightly-flaky-test-detector.yml | 22 + .github/workflows/run-selected-e2e-tests.yml | 2 +- .../workflows/solidity-foundry-artifacts.yml | 1 + .github/workflows/solidity-foundry.yml | 11 +- .github/workflows/solidity-hardhat.yml | 2 +- ...ceability.yml => solidity-tracability.yml} | 2 +- .github/workflows/solidity.yml | 24 +- .gitignore | 3 +- .golangci.yml | 5 +- .mockery.yaml | 12 +- .tool-versions | 5 +- GNUmakefile | 20 +- README.md | 2 +- ccip/config/evm/Avalanche_Fuji.toml | 5 +- ccip/config/evm/Avalanche_Mainnet.toml | 5 +- ccip/config/evm/Lens_Sepolia.toml | 34 - common/client/multi_node.go | 4 +- common/client/multi_node_test.go | 4 +- common/client/node_lifecycle.go | 39 +- common/client/node_lifecycle_test.go | 46 +- common/client/transaction_sender.go | 237 +- common/client/transaction_sender_test.go | 209 +- common/txmgr/broadcaster.go | 2 +- common/txmgr/confirmer.go | 709 +++- common/txmgr/tracker.go | 2 +- common/txmgr/txmgr.go | 1 - common/txmgr/types/config.go | 7 + common/txmgr/types/finalizer.go | 5 - common/txmgr/types/mocks/tx_store.go | 462 ++- common/txmgr/types/tx.go | 9 - common/txmgr/types/tx_store.go | 30 +- contracts/.changeset/bright-jokes-kiss.md | 10 - contracts/.changeset/chilly-rockets-share.md | 10 - contracts/.changeset/cold-geckos-yawn.md | 10 - contracts/.changeset/early-cups-relax.md | 9 - contracts/.changeset/eighty-cycles-film.md | 10 - contracts/.changeset/fluffy-eels-tan.md | 10 - contracts/.changeset/hot-pandas-carry.md | 10 - contracts/.changeset/mean-masks-poke.md | 10 - contracts/.changeset/modern-mayflies-give.md | 10 - contracts/.changeset/new-elephants-behave.md | 5 - contracts/.changeset/ninety-lions-complain.md | 5 - contracts/.changeset/perfect-bears-clean.md | 5 - contracts/.changeset/rude-badgers-tickle.md | 5 - contracts/.changeset/small-countries-flow.md | 5 - contracts/.changeset/tame-cycles-ring.md | 10 - contracts/.changeset/tender-lemons-punch.md | 9 - contracts/.changeset/thirty-rules-rule.md | 10 - contracts/.changeset/three-dogs-return.md | 5 - contracts/.changeset/violet-lamps-pump.md | 10 - contracts/.changeset/wet-eyes-accept.md | 7 - contracts/.changeset/yellow-mugs-explode.md | 9 - contracts/.changeset/young-bats-rhyme.md | 10 - contracts/.solhintignore-test | 1 + contracts/GNUmakefile | 4 +- contracts/README.md | 10 +- contracts/foundry.toml | 19 +- contracts/gas-snapshots/ccip.gas-snapshot | 1153 ++++-- contracts/gas-snapshots/l2ep.gas-snapshot | 255 +- .../liquiditymanager.gas-snapshot | 12 +- .../gas-snapshots/llo-feeds.gas-snapshot | 4 +- contracts/gas-snapshots/shared.gas-snapshot | 211 +- contracts/gas-snapshots/workflow.gas-snapshot | 64 - contracts/scripts/lcov_prune | 2 +- contracts/scripts/native_solc_compile_all | 2 +- .../scripts/native_solc_compile_all_ccip | 13 +- .../scripts/native_solc_compile_all_shared | 2 - .../native_solc_compile_all_transmission | 40 + contracts/src/v0.8/ccip/FeeQuoter.sol | 47 +- contracts/src/v0.8/ccip/LICENSE-MIT.md | 21 + .../v0.8/ccip/MultiAggregateRateLimiter.sol | 2 +- contracts/src/v0.8/ccip/NonceManager.sol | 8 +- contracts/src/v0.8/ccip/Router.sol | 2 +- .../ccip/applications/EtherSenderReceiver.sol | 2 +- .../src/v0.8/ccip/capability/CCIPHome.sol | 21 +- .../v0.8/ccip/interfaces/IEVM2AnyOnRamp.sol | 4 +- .../ccip/libraries/ERC165CheckerReverting.sol | 65 - .../src/v0.8/ccip/libraries/Internal.sol | 26 +- contracts/src/v0.8/ccip/ocr/MultiOCR3Base.sol | 5 +- contracts/src/v0.8/ccip/offRamp/OffRamp.sol | 48 +- contracts/src/v0.8/ccip/onRamp/OnRamp.sol | 2 +- .../v0.8/ccip/pools/BurnFromMintTokenPool.sol | 7 +- .../src/v0.8/ccip/pools/BurnMintTokenPool.sol | 7 +- .../ccip/pools/BurnMintTokenPoolAbstract.sol | 17 +- .../ccip/pools/BurnWithFromMintTokenPool.sol | 7 +- .../v0.8/ccip/pools/LockReleaseTokenPool.sol | 22 +- contracts/src/v0.8/ccip/pools/TokenPool.sol | 367 +- .../BurnMintWithLockReleaseFlagTokenPool.sol | 5 +- .../USDC/HybridLockReleaseUSDCTokenPool.sol | 2 +- .../ccip/pools/USDC/USDCBridgeMigrator.sol | 2 +- .../v0.8/ccip/pools/USDC/USDCTokenPool.sol | 8 +- contracts/src/v0.8/ccip/rmn/ARMProxy.sol | 2 +- contracts/src/v0.8/ccip/rmn/RMNHome.sol | 4 +- contracts/src/v0.8/ccip/rmn/RMNRemote.sol | 49 +- contracts/src/v0.8/ccip/test/BaseTest.t.sol | 73 +- .../src/v0.8/ccip/test/NonceManager.t.sol | 568 +++ ...nceManager.applyPreviousRampsUpdates.t.sol | 154 - .../NonceManager.getInboundNonce.t.sol | 253 -- ...eManager.getIncrementedOutboundNonce.t.sol | 61 - .../NonceManager.getOutboundNonce.t.sol | 102 - contracts/src/v0.8/ccip/test/TokenSetup.t.sol | 34 +- contracts/src/v0.8/ccip/test/WETH9.sol | 2 +- .../DefensiveExample/DefensiveExample.t.sol | 2 +- .../EtherSenderReceiverTest.ccipSend.t.sol | 14 +- ...rSenderReceiverTest.validateFeeToken.t.sol | 2 +- .../ImmutableExample/ImmutableExample.t.sol | 2 +- .../PingPong/PingPong.ccipReceive.t.sol | 4 +- .../PingPong/PingPong.setCounterpart.t.sol | 2 +- .../PingPong.setCounterpartAddress.t.sol | 2 +- ...PingPong.setCounterpartChainSelector.t.sol | 2 +- .../PingPong.setOutOfOrderExecution.t.sol | 4 +- .../PingPong/PingPong.setPaused.t.sol | 4 +- .../PingPong/PingPong.startPingPong.t.sol | 6 +- .../PingPong/PingPongDappSetup.t.sol | 2 +- .../ccip/test/attacks/OnRamp/FacadeClient.sol | 2 +- .../OnRamp/OnRampTokenPoolReentrancy.t.sol | 14 +- .../OnRamp/ReentrantMaliciousTokenPool.sol | 4 +- .../CCIPHome.applyChainConfigUpdates.t.sol | 20 +- .../CCIPHome.beforeCapabilityConfigSet.t.sol | 12 +- .../CCIPHome/CCIPHome.constructor.t.sol | 6 +- .../CCIPHome/CCIPHome.getAllConfigs.t.sol | 4 +- .../CCIPHome.getCapabilityConfiguration.t.sol | 4 +- .../CCIPHome/CCIPHome.getConfigDigests.t.sol | 4 +- ...Home.promoteCandidateAndRevokeActive.t.sol | 10 +- .../CCIPHome/CCIPHome.revokeCandidate.t.sol | 10 +- .../CCIPHome/CCIPHome.setCandidate.t.sol | 8 +- .../CCIPHome/CCIPHome.supportsInterface.t.sol | 4 +- .../CCIPHome/CCIPHome.validateConfig.t.sol | 36 +- .../CCIPHome/CCIPHomeTestSetup.t.sol | 2 +- .../src/v0.8/ccip/test/e2e/End2End.t.sol | 36 +- ...eeQuoter.applyDestChainConfigUpdates.t.sol | 14 +- .../FeeQuoter.applyFeeTokensUpdates.t.sol | 6 +- ...plyPremiumMultiplierWeiPerEthUpdates.t.sol | 8 +- ...r.applyTokenTransferFeeConfigUpdates.t.sol | 8 +- .../feeQuoter/FeeQuoter.constructor.t.sol | 10 +- .../FeeQuoter.convertTokenAmount.t.sol | 6 +- .../FeeQuoter.getDataAvailabilityCost.t.sol | 8 +- .../FeeQuoter.getTokenAndGasPrices.t.sol | 12 +- .../feeQuoter/FeeQuoter.getTokenPrice.t.sol | 16 +- .../feeQuoter/FeeQuoter.getTokenPrices.t.sol | 4 +- .../FeeQuoter.getTokenTransferCost.t.sol | 20 +- .../feeQuoter/FeeQuoter.getValidatedFee.t.sol | 44 +- .../FeeQuoter.getValidatedTokenPrice.t.sol | 30 +- .../test/feeQuoter/FeeQuoter.onReport.t.sol | 86 +- ...FeeQuoter.parseEVMExtraArgsFromBytes.t.sol | 14 +- .../FeeQuoter.processMessageArgs.t.sol | 28 +- .../FeeQuoter.supportsInterface.t.sol | 18 - .../feeQuoter/FeeQuoter.updatePrices.t.sol | 12 +- .../FeeQuoter.updateTokenPriceFeeds.t.sol | 12 +- .../FeeQuoter.validateDestFamilyAddress.t.sol | 12 +- .../ccip/test/feeQuoter/FeeQuoterSetup.t.sol | 16 +- .../test/helpers/BurnMintERC677Helper.sol | 2 +- .../test/helpers/BurnMintMultiTokenPool.sol | 2 +- .../v0.8/ccip/test/helpers/CCIPHomeHelper.sol | 2 +- .../ccip/test/helpers/CCIPReaderTester.sol | 16 +- .../ccip/test/helpers/ERC20RebasingHelper.sol | 2 +- .../test/helpers/EVM2EVMOffRampHelper.sol | 2 +- .../helpers/EtherSenderReceiverHelper.sol | 2 +- .../ccip/test/helpers/FeeQuoterHelper.sol | 2 +- .../ccip/test/helpers/IgnoreContractSize.sol | 2 +- .../MaybeRevertingBurnMintTokenPool.sol | 13 +- .../v0.8/ccip/test/helpers/MerkleHelper.sol | 2 +- .../test/helpers/MessageInterceptorHelper.sol | 2 +- .../MultiAggregateRateLimiterHelper.sol | 2 +- .../ccip/test/helpers/MultiOCR3Helper.sol | 8 +- .../v0.8/ccip/test/helpers/MultiTokenPool.sol | 2 +- .../v0.8/ccip/test/helpers/OffRampHelper.sol | 2 +- .../v0.8/ccip/test/helpers/OnRampHelper.sol | 2 +- .../ccip/test/helpers/RateLimiterHelper.sol | 2 +- .../v0.8/ccip/test/helpers/ReportCodec.sol | 2 +- .../ccip/test/helpers/TokenPoolHelper.sol | 30 +- .../ccip/test/helpers/USDCReaderTester.sol | 2 +- .../ccip/test/helpers/USDCTokenPoolHelper.sol | 2 +- .../helpers/receivers/ConformingReceiver.sol | 2 +- .../receivers/MaybeRevertMessageReceiver.sol | 2 +- .../MaybeRevertMessageReceiverNo165.sol | 2 +- .../helpers/receivers/ReentrancyAbuser.sol | 2 +- ...Reverting.supportsInterfaceReverting.t.sol | 44 - .../test/libraries/MerkleMultiProof.t.sol | 6 +- .../ccip/test/libraries/RateLimiter.t.sol | 30 +- .../test/mocks/MockE2EUSDCTokenMessenger.sol | 2 +- .../test/mocks/MockE2EUSDCTransmitter.sol | 6 +- .../src/v0.8/ccip/test/mocks/MockRMN.sol | 61 + .../src/v0.8/ccip/test/mocks/MockRouter.sol | 15 +- .../test/mocks/MockUSDCTokenMessenger.sol | 2 +- .../ccip/test/mocks/test/MockRouterTest.t.sol | 31 +- .../MultiOCR3Base.setOCR3Configs.t.sol | 40 +- .../MultiOCR3Base.transmit.t.sol | 66 +- .../MultiOCR3Base/MultiOCR3BaseSetup.t.sol | 4 +- .../OffRamp/OffRamp.afterOC3ConfigSet.t.sol | 5 +- ...ffRamp.applySourceChainConfigUpdates.t.sol | 22 +- .../OffRamp/OffRamp.batchExecute.t.sol | 18 +- .../offRamp/OffRamp/OffRamp.ccipReceive.t.sol | 2 +- .../test/offRamp/OffRamp/OffRamp.commit.t.sol | 49 +- .../offRamp/OffRamp/OffRamp.constructor.t.sol | 23 +- .../offRamp/OffRamp/OffRamp.execute.t.sol | 34 +- .../OffRamp.executeSingleMessage.t.sol | 43 +- .../OffRamp/OffRamp.executeSingleReport.t.sol | 53 +- .../OffRamp/OffRamp.getExecutionState.t.sol | 8 +- .../OffRamp/OffRamp.manuallyExecute.t.sol | 36 +- .../OffRamp.releaseOrMintSingleToken.t.sol | 28 +- .../OffRamp/OffRamp.releaseOrMintTokens.t.sol | 22 +- .../OffRamp/OffRamp.setDynamicConfig.t.sol | 10 +- .../OffRamp/OffRamp.trialExecute.t.sol | 34 +- .../test/offRamp/OffRamp/OffRampSetup.t.sol | 31 +- .../OnRamp.applyDestChainConfigUpdates.t.sol | 10 +- .../onRamp/OnRamp/OnRamp.constructor.t.sol | 14 +- .../OnRamp/OnRamp.forwardFromRouter.t.sol | 89 +- .../test/onRamp/OnRamp/OnRamp.getFee.t.sol | 14 +- .../OnRamp/OnRamp.getSupportedTokens.t.sol | 4 +- .../onRamp/OnRamp/OnRamp.getTokenPool.t.sol | 4 +- .../OnRamp/OnRamp.setDynamicConfig.t.sol | 14 +- .../OnRamp/OnRamp.withdrawFeeTokens.t.sol | 4 +- .../ccip/test/onRamp/OnRamp/OnRampSetup.t.sol | 8 +- .../BurnFromMintTokenPool.lockOrBurn.t.sol | 39 +- .../BurnFromMintTokenPoolSetup.t.sol | 8 +- .../BurnMintTokenPool/BurnMintSetup.t.sol | 26 +- .../BurnMintTokenPool.lockOrBurn.t.sol | 42 +- .../BurnMintTokenPool.releaseOrMint.t.sol | 28 +- ...hLockReleaseFlagTokenPool.lockOrBurn.t.sol | 18 +- ...BurnWithFromMintTokenPool.lockOrBurn.t.sol | 45 +- ...kReleaseTokenPool.canAcceptLiquidity.t.sol | 9 +- .../LockReleaseTokenPool.lockOrBurn.t.sol | 10 +- ...ockReleaseTokenPool.provideLiquidity.t.sol | 11 +- .../LockReleaseTokenPool.releaseOrMint.t.sol | 36 +- .../LockReleaseTokenPool.setRebalancer.t.sol | 6 +- ...ckReleaseTokenPool.supportsInterface.t.sol | 4 +- ...ckReleaseTokenPool.transferLiquidity.t.sol | 11 +- ...ReleaseTokenPool.withdrawalLiquidity.t.sol | 6 +- .../LockReleaseTokenPoolSetup.t.sol | 34 +- .../TokenPool/TokenPool.addRemotePool.t.sol | 165 - .../TokenPool.applyAllowListUpdates.t.sol | 14 +- .../TokenPool.applyChainUpdates.t.sol | 218 +- .../TokenPool.calculateLocalAmount.t.sol | 101 - .../TokenPool/TokenPool.constructor.t.sol | 40 +- .../TokenPool/TokenPool.getAllowList.t.sol | 4 +- .../TokenPool.getAllowListEnabled.t.sol | 4 +- .../TokenPool/TokenPool.getRemotePool.t.sol | 26 +- .../TokenPool/TokenPool.onlyOffRamp.t.sol | 54 +- .../TokenPool/TokenPool.onlyOnRamp.t.sol | 54 +- .../TokenPool.parseRemoteDecimals.t.sol | 36 - .../TokenPool.removeRemotePool.t.sol | 61 - .../TokenPool.setChainRateLimiterConfig.t.sol | 37 +- ...TokenPool.setChainRateLimiterConfigs.t.sol | 128 - .../TokenPool.setRateLimitAdmin.t.sol | 6 +- .../TokenPool/TokenPool.setRemotePool.t.sol | 51 + .../pools/TokenPool/TokenPool.setRouter.t.sol | 14 +- .../test/pools/TokenPool/TokenPoolSetup.t.sol | 33 +- .../TokenPoolWithAllowListSetup.t.sol | 6 +- ...dLockReleaseUSDCTokenPool.lockOrBurn.t.sol | 144 +- ...ckReleaseUSDCTokenPool.releaseOrMint.t.sol | 135 +- ...leaseUSDCTokenPool.transferLiquidity.t.sol | 138 +- .../HybridLockReleaseUSDCTokenPoolSetup.t.sol | 43 - .../USDCBridgeMigrator.burnLockedUSDC.t.sol | 138 +- ...idgeMigrator.cancelMigrationProposal.t.sol | 140 +- ...BridgeMigrator.excludeTokensFromBurn.t.sol | 138 +- .../USDCBridgeMigrator.proposeMigration.t.sol | 138 +- .../USDCBridgeMigrator.provideLiquidity.t.sol | 139 +- .../USDCBridgeMigrator.releaseOrMint.t.sol | 135 +- ...igrator.updateChainSelectorMechanism.t.sol | 137 +- .../USDCBridgeMigratorSetup.t.sol | 22 - .../v0.8/ccip/test/pools/USDC/USDCSetup.t.sol | 114 - .../USDCTokenPool.lockOrBurn.t.sol | 15 +- .../USDCTokenPool.releaseOrMint.t.sol | 8 +- .../USDCTokenPool.setDomains.t.sol | 6 +- .../USDCTokenPool.supportsInterface.t.sol | 4 +- .../USDCTokenPool.validateMessage.t.sol | 4 +- .../USDCTokenPool/USDCTokenPoolSetup.t.sol | 109 +- .../MultiAggregateRateLimiterSetup.t.sol | 9 +- ...imiter_applyRateLimiterConfigUpdates.t.sol | 28 +- ...ultiAggregateRateLimiter_constructor.t.sol | 6 +- ...iAggregateRateLimiter_getTokenBucket.t.sol | 8 +- ...tiAggregateRateLimiter_getTokenValue.t.sol | 6 +- ...ggregateRateLimiter_onInboundMessage.t.sol | 20 +- ...gregateRateLimiter_onOutboundMessage.t.sol | 22 +- ...ltiAggregateRateLimiter_setFeeQuoter.t.sol | 8 +- ...ateRateLimiter_updateRateLimitTokens.t.sol | 18 +- .../test/rmn/ArmProxy/ARMProxyTestSetup.t.sol | 2 +- .../test/rmn/ArmProxy/ArmPorxy.setARM.t.sol | 2 +- .../rmn/ArmProxy/ArmProxy.constructor.t.sol | 2 +- .../test/rmn/ArmProxy/ArmProxy.isCursed.t.sol | 37 +- .../RMNHome/RMNHome.getConfigDigests.t.sol | 4 +- ...Home.promoteCandidateAndRevokeActive.t.sol | 10 +- .../rmn/RMNHome/RMNHome.revokeCandidate.t.sol | 10 +- .../rmn/RMNHome/RMNHome.setCandidate.t.sol | 8 +- .../RMNHome/RMNHome.setDynamicConfig.t.sol | 10 +- ...NHome.validateStaticAndDynamicConfig.t.sol | 14 +- .../test/rmn/RMNHome/RMNHomeTestSetup.t.sol | 2 +- .../rmn/RMNRemote/RMNRemote.constructor.t.sol | 10 +- .../test/rmn/RMNRemote/RMNRemote.curse.t.sol | 8 +- .../RMNRemote.globalAndLegacyCurses.t.sol | 29 + .../RMNRemote/RMNRemote.globalCurses.t.sol | 21 - .../rmn/RMNRemote/RMNRemote.isBlessed.t.sol | 34 - .../rmn/RMNRemote/RMNRemote.setConfig.t.sol | 12 +- .../rmn/RMNRemote/RMNRemote.uncurse.t.sol | 8 +- .../RMNRemote.verifywithConfigNotSet.t.sol | 4 +- .../RMNRemote.verifywithConfigSet.t.sol | 34 +- .../test/rmn/RMNRemote/RMNRemoteSetup.t.sol | 21 +- .../Router/Router.applyRampUpdates.t.sol | 44 +- .../test/router/Router/Router.ccipSend.t.sol | 23 +- .../router/Router/Router.constructor.t.sol | 4 +- .../router/Router/Router.getArmProxy.t.sol | 8 +- .../test/router/Router/Router.getFee.t.sol | 6 +- .../Router/Router.getSupportedTokens.t.sol | 4 +- .../router/Router/Router.recoverTokens.t.sol | 12 +- .../router/Router/Router.routeMessage.t.sol | 33 +- .../Router/Router.setWrappedNative.t.sol | 4 +- .../ccip/test/router/Router/RouterSetup.t.sol | 50 + .../BurnMintERC20Setup.t.sol | 2 +- .../FactoryBurnMintERC20.approve.t.sol | 6 +- .../FactoryBurnMintERC20.burn.t.sol | 10 +- .../FactoryBurnMintERC20.burnFrom.t.sol | 10 +- .../FactoryBurnMintERC20.burnFromAlias.t.sol | 10 +- .../FactoryBurnMintERC20.constructor.t.sol | 4 +- ...actoryBurnMintERC20.decreaseApproval.t.sol | 4 +- .../FactoryBurnMintERC20.getCCIPAdmin.t.sol | 6 +- ...yBurnMintERC20.grantMintAndBurnRoles.t.sol | 4 +- .../FactoryBurnMintERC20.grantRole.t.sol | 8 +- ...actoryBurnMintERC20.increaseApproval.t.sol | 4 +- .../FactoryBurnMintERC20.mint.t.sol | 8 +- ...ctoryBurnMintERC20.supportsInterface.t.sol | 4 +- .../FactoryBurnMintERC20.transfer.t.sol | 6 +- ...egistryModuleOwnerCustom.constructor.t.sol | 2 +- ...om.registerAccessControlDefaultAdmin.t.sol | 4 +- ...rCustom.registerAdminViaGetCCIPAdmin.t.sol | 4 +- ...uleOwnerCustom.registerAdminViaOwner.t.sol | 4 +- .../TokenAdminRegistry.acceptAdminRole.t.sol | 4 +- ...TokenAdminRegistry.addRegistryModule.t.sol | 4 +- ...AdminRegistry.getAllConfiguredTokens.t.sol | 2 +- .../TokenAdminRegistry.getPool.t.sol | 2 +- .../TokenAdminRegistry.getPools.t.sol | 2 +- .../TokenAdminRegistry.isAdministrator.t.sol | 2 +- ...enAdminRegistry.proposeAdministrator.t.sol | 12 +- ...enAdminRegistry.removeRegistryModule.t.sol | 4 +- .../TokenAdminRegistry.setPool.t.sol | 8 +- ...TokenAdminRegistry.transferAdminRole.t.sol | 4 +- .../TokenPoolFactory.constructor.t.sol | 4 +- .../TokenPoolFactory.createTokenPool.t.sol | 211 +- .../TokenPoolFactorySetup.t.sol | 2 +- .../RegistryModuleOwnerCustom.sol | 2 +- .../tokenAdminRegistry/TokenAdminRegistry.sol | 2 +- .../TokenPoolFactory/FactoryBurnMintERC20.sol | 2 +- .../TokenPoolFactory/TokenPoolFactory.sol | 50 +- contracts/src/v0.8/keystone/BalanceReader.sol | 14 - .../v0.8/keystone/KeystoneFeedsConsumer.sol | 4 +- .../KeystoneFeedsPermissionHandler.sol | 12 +- .../src/v0.8/keystone/KeystoneForwarder.sol | 20 +- .../v0.8/keystone/interfaces/IReceiver.sol | 5 +- .../test/mocks/MaliciousReportReceiver.sol | 2 +- .../test/mocks/MaliciousRevertingReceiver.sol | 2 +- .../src/v0.8/keystone/test/mocks/Receiver.sol | 4 +- contracts/src/v0.8/l2ep/README.md | 3 +- .../CrossDomainDelegateForwarder.sol | 0 .../l2ep/{ => dev}/CrossDomainForwarder.sol | 0 .../l2ep/{ => dev}/CrossDomainOwnable.sol | 2 +- contracts/src/v0.8/l2ep/{ => dev}/Flags.sol | 6 +- .../arbitrum/ArbitrumCrossDomainForwarder.sol | 6 +- .../arbitrum/ArbitrumCrossDomainGovernor.sol | 4 +- .../arbitrum/ArbitrumSequencerUptimeFeed.sol | 12 +- .../{ => dev}/arbitrum/ArbitrumValidator.sol | 14 +- .../interfaces/IArbitrumDelayedInbox.sol | 2 +- .../interfaces/ICrossDomainOwnable.sol | 0 .../interfaces/IDelegateForwarder.sol | 0 .../v0.8/l2ep/{ => dev}/interfaces/IFlags.sol | 0 .../l2ep/{ => dev}/interfaces/IForwarder.sol | 0 .../interfaces/ISequencerUptimeFeed.sol | 0 .../optimism/OptimismCrossDomainForwarder.sol | 6 +- .../optimism/OptimismCrossDomainGovernor.sol | 4 +- .../optimism/OptimismSequencerUptimeFeed.sol | 2 +- .../{ => dev}/optimism/OptimismValidator.sol | 2 +- .../scroll/ScrollCrossDomainForwarder.sol | 4 +- .../scroll/ScrollCrossDomainGovernor.sol | 4 +- .../scroll/ScrollSequencerUptimeFeed.sol | 2 +- .../l2ep/{ => dev}/scroll/ScrollValidator.sol | 2 +- .../shared}/BaseSequencerUptimeFeed.sol | 29 +- .../{base => dev/shared}/BaseValidator.sol | 8 +- .../zksync/ZKSyncSequencerUptimeFeed.sol | 4 +- .../l2ep/{ => dev}/zksync/ZKSyncValidator.sol | 2 +- .../mocks/MockBaseSequencerUptimeFeed.sol | 25 - .../l2ep/test/mocks/MockBaseValidator.sol | 23 - .../ArbitrumCrossDomainForwarder.t.sol | 2 +- .../ArbitrumCrossDomainGovernor.t.sol | 2 +- .../ArbitrumSequencerUptimeFeed.t.sol | 4 +- .../v1_0_0/arbitrum/ArbitrumValidator.t.sol | 4 +- .../OptimismCrossDomainForwarder.t.sol | 2 +- .../OptimismCrossDomainGovernor.t.sol | 2 +- .../OptimismSequencerUptimeFeed.t.sol | 304 +- .../v1_0_0/optimism/OptimismValidator.t.sol | 30 +- .../scroll/ScrollCrossDomainForwarder.t.sol | 8 +- .../scroll/ScrollCrossDomainGovernor.t.sol | 13 +- .../scroll/ScrollSequencerUptimeFeed.t.sol | 312 +- .../test/v1_0_0/scroll/ScrollValidator.t.sol | 43 +- .../shared/BaseSequencerUptimeFeed.t.sol | 377 -- .../test/v1_0_0/shared/BaseValidator.t.sol | 57 - .../zksync/ZKSyncSequencerUptimeFeed.t.sol | 295 +- .../test/v1_0_0/zksync/ZKSyncValidator.t.sol | 54 +- .../test/LiquidityManager.t.sol | 14 +- .../test/LiquidityManagerBaseTest.t.sol | 1 - .../v0.5.0/configuration/Configurator.sol | 1 - .../ConfiguratorSetStagingConfigTest.t.sol | 13 - .../BurnMintERC20/BurnMintERC20.approve.t.sol | 31 - .../BurnMintERC20/BurnMintERC20.burn.t.sol | 56 - .../BurnMintERC20.burnFrom.t.sol | 58 - .../BurnMintERC20.burnFromAlias.t.sol | 58 - .../BurnMintERC20.ccipGetAdmin.t.sol | 22 - .../BurnMintERC20.constructor.t.sol | 27 - .../BurnMintERC20.grantMintAndBurnRoles.t.sol | 24 - .../BurnMintERC20/BurnMintERC20.mint.t.sol | 61 - .../BurnMintERC20.supportsInterface.t.sol | 17 - .../BurnMintERC20.transfer.t.sol | 24 - .../BurnMintERC20/BurnMintERC20Setup.t.sol | 26 - .../v0.8/shared/token/ERC20/BurnMintERC20.sol | 162 - .../transmission/dev/ERC-4337/Paymaster.sol | 134 + .../v0.8/transmission/dev/ERC-4337/SCA.sol | 73 + .../transmission/dev/ERC-4337/SCALibrary.sol | 48 + .../ERC-4337/SmartContractAccountFactory.sol | 33 + .../transmission/dev/testhelpers/Greeter.sol | 15 + .../SmartContractAccountHelper.sol | 78 + .../src/v0.8/transmission/test/BaseTest.t.sol | 17 + .../transmission/test/EIP_712_1014_4337.t.sol | 365 ++ .../vendor/entrypoint/core/EntryPoint.sol | 861 ++++ .../v0.8/vendor/entrypoint/core/Helpers.sol | 68 + .../vendor/entrypoint/core/SenderCreator.sol | 28 + .../vendor/entrypoint/core/StakeManager.sol | 124 + .../vendor/entrypoint/interfaces/IAccount.sol | 34 + .../entrypoint/interfaces/IAggregator.sol | 36 + .../entrypoint/interfaces/IEntryPoint.sol | 197 + .../entrypoint/interfaces/IPaymaster.sol | 51 + .../entrypoint/interfaces/IStakeManager.sol | 104 + .../entrypoint/interfaces/UserOperation.sol | 84 + .../src/v0.8/vendor/entrypoint/utils/Exec.sol | 70 + .../src/v0.8/vendor/forge-std/src/Vm.sol | 142 +- .../multicall/ebd8b64/src/Multicall3.sol | 216 - .../v0.8/workflow/dev/WorkflowRegistry.sol | 86 +- .../workflow/dev/WorkflowRegistryManager.sol | 30 +- .../src/v0.8/workflow/mocks/MockContract.sol | 4 - .../mocks/MockWorkflowRegistryContract.sol | 8 - .../WorkflowRegistry.activateWorkflow.t.sol | 6 - .../WorkflowRegistry.activateWorkflow.tree | 6 +- .../WorkflowRegistry.deleteWorkflow.t.sol | 8 - .../WorkflowRegistry.deleteWorkflow.tree | 4 +- .../WorkflowRegistry.getAllAllowedDONs.t.sol | 12 - .../WorkflowRegistry.getAllAllowedDONs.tree | 6 +- ...owRegistry.getAllAuthorizedAddresses.t.sol | 14 +- ...lowRegistry.getAllAuthorizedAddresses.tree | 6 +- ...WorkflowRegistry.getWorkflowMetadata.t.sol | 20 - .../WorkflowRegistry.getWorkflowMetadata.tree | 6 +- ...egistry.getWorkflowMetadataListByDON.t.sol | 33 +- ...Registry.getWorkflowMetadataListByDON.tree | 6 +- ...istry.getWorkflowMetadataListByOwner.t.sol | 81 +- ...gistry.getWorkflowMetadataListByOwner.tree | 8 +- .../WorkflowRegistry.lockRegistry.t.sol | 23 - .../WorkflowRegistry.lockRegistry.tree | 6 - .../WorkflowRegistry.pauseWorkflow.t.sol | 16 - .../WorkflowRegistry.pauseWorkflow.tree | 8 +- .../WorkflowRegistry.registerWorkflow.t.sol | 31 +- .../WorkflowRegistry.registerWorkflow.tree | 2 - .../WorkflowRegistry.unlockRegistry.t.sol | 30 - .../WorkflowRegistry.unlockRegistry.tree | 6 - .../WorkflowRegistry.updateAllowedDONs.t.sol | 6 +- ...owRegistry.updateAuthorizedAddresses.t.sol | 6 +- .../WorkflowRegistry.updateWorkflow.t.sol | 40 +- .../WorkflowRegistry.updateWorkflow.tree | 2 - .../WorkflowRegistrySetup.t.sol | 4 +- ...kflowRegistryManager.activateVersion.t.sol | 81 +- ...rkflowRegistryManager.activateVersion.tree | 4 +- .../WorkflowRegistryManager.addVersion.t.sol | 103 +- .../WorkflowRegistryManager.addVersion.tree | 19 +- ...flowRegistryManager.getActiveVersion.t.sol | 14 +- ...gistryManager.getActiveVersionNumber.t.sol | 18 - ...egistryManager.getActiveVersionNumber.tree | 5 - ...rkflowRegistryManager.getAllVersions.t.sol | 46 +- ...flowRegistryManager.getLatestVersion.t.sol | 14 +- ...kflowRegistryManager.getLatestVersion.tree | 2 +- ...gistryManager.getLatestVersionNumber.t.sol | 18 - ...egistryManager.getLatestVersionNumber.tree | 5 - .../WorkflowRegistryManager.getVersion.t.sol | 13 +- ...flowRegistryManager.getVersionNumber.t.sol | 26 + ...flowRegistryManager.getVersionNumber.tree} | 2 +- ...ionNumberByContractAddressAndChainID.t.sol | 31 - .../WorkflowRegistryManagerSetup.t.sol | 24 +- .../ccipreader/ccipreader_test.go | 608 +++ .../integrationhelpers/integration_helpers.go | 26 +- .../usdcreader/usdcreader_test.go | 190 +- .../ccip/ccipevm/encodingUtilsAbi.json | 1 - core/capabilities/ccip/ccipevm/rmncrypto.go | 7 +- .../ccip/ccipsolana/commitcodec.go | 7 +- core/capabilities/ccip/common/common_test.go | 2 +- .../ccip/configs/evm/contract_reader.go | 27 +- core/capabilities/ccip/delegate.go | 5 +- core/capabilities/ccip/launcher/deployment.go | 1 - core/capabilities/ccip/launcher/diff_test.go | 2 +- core/capabilities/ccip/launcher/launcher.go | 3 +- .../ccip/ocrimpls/contract_transmitter.go | 119 +- .../ocrimpls/contract_transmitter_test.go | 26 +- core/capabilities/ccip/ocrimpls/keyring.go | 51 +- .../ccip/oraclecreator/bootstrap.go | 3 +- .../capabilities/ccip/oraclecreator/plugin.go | 97 +- core/capabilities/compute/cache.go | 11 +- core/capabilities/compute/cache_test.go | 9 - core/capabilities/compute/compute.go | 19 +- core/capabilities/compute/compute_test.go | 2 - .../compute/test/fetch/cmd/main.go | 7 +- .../compute/test/simple/cmd/main.go | 7 +- core/capabilities/don_notifier.go | 43 - core/capabilities/don_notifier_test.go | 49 - .../framework/capabilities_registry.go | 2 +- .../integration_tests/framework/don.go | 2 +- .../integration_tests/framework/peer.go | 2 +- .../keystone/contracts_setup.go | 4 +- .../keystone/keystone_test.go | 2 +- .../integration_tests/keystone/setup.go | 4 +- core/capabilities/launcher.go | 40 +- core/capabilities/launcher_test.go | 16 +- core/capabilities/registry.go | 15 - .../remote/aggregation/default_mode.go | 58 - .../remote/aggregation/default_mode_test.go | 51 - core/capabilities/remote/dispatcher.go | 28 +- core/capabilities/remote/dispatcher_test.go | 30 +- core/capabilities/remote/executable/client.go | 63 +- .../remote/executable/client_test.go | 84 +- .../remote/executable/endtoend_test.go | 196 +- .../executable/request/client_request.go | 50 +- .../executable/request/client_request_test.go | 177 +- .../executable/request/server_request.go | 55 +- .../executable/request/server_request_test.go | 109 +- core/capabilities/remote/executable/server.go | 32 +- .../remote/executable/server_test.go | 139 + .../{messagecache => }/message_cache.go | 17 +- .../{messagecache => }/message_cache_test.go | 32 +- core/capabilities/remote/trigger_publisher.go | 34 +- .../capabilities/remote/trigger_subscriber.go | 30 +- .../remote/trigger_subscriber_test.go | 1 + .../remote/types/mocks/dispatcher.go | 34 +- core/capabilities/remote/types/types.go | 14 +- core/capabilities/remote/utils.go | 59 +- core/capabilities/remote/utils_test.go | 77 +- .../targets/mocks/chain_writer.go | 435 ++ .../targets/mocks/contract_writer.go | 435 -- core/capabilities/targets/write_target.go | 23 +- .../capabilities/targets/write_target_test.go | 52 +- .../capabilities/triggers/logevent/trigger.go | 5 - .../webapi/outgoing_connector_handler.go | 58 +- .../webapi/outgoing_connector_handler_test.go | 135 - core/capabilities/webapi/target/target.go | 14 +- .../capabilities/webapi/target/target_test.go | 2 +- core/capabilities/webapi/trigger/trigger.go | 7 - core/chainlink.Dockerfile | 4 +- core/chains/evm/client/chain_client.go | 22 +- core/chains/evm/client/errors.go | 17 +- core/chains/evm/client/errors_test.go | 16 - core/chains/evm/client/rpc_client.go | 33 +- core/chains/evm/client/rpc_client_test.go | 3 +- .../evm/client/simulated_backend_client.go | 6 +- .../evm/config/chain_scoped_transactions.go | 4 - core/chains/evm/config/config.go | 1 - core/chains/evm/config/config_test.go | 13 +- core/chains/evm/config/toml/config.go | 4 - core/chains/evm/config/toml/defaults.go | 1 + .../config/toml/defaults/Avalanche_Fuji.toml | 5 +- .../toml/defaults/Avalanche_Mainnet.toml | 5 +- .../evm/config/toml/defaults/BOB_Mainnet.toml | 27 - .../evm/config/toml/defaults/BOB_Testnet.toml | 27 - .../toml/defaults/Berachain_Testnet.toml | 19 - .../toml/defaults/Bsquared_Mainnet.toml | 27 - .../toml/defaults/Bsquared_Testnet.toml | 27 - .../config/toml/defaults/Ronin_Mainnet.toml | 11 - .../config/toml/defaults/Ronin_Saigon.toml | 11 - .../toml/defaults/Unichain_Testnet.toml | 30 - .../toml/defaults/Worldchain_Mainnet.toml | 27 - .../toml/defaults/Worldchain_Testnet.toml | 27 - .../evm/config/toml/defaults/fallback.toml | 1 - .../config/toml/defaults/zkSync_Mainnet.toml | 3 - .../config/toml/defaults/zkSync_Sepolia.toml | 3 - core/chains/evm/gas/models.go | 1 - core/chains/evm/gas/rollups/l1_oracle.go | 1 - core/chains/evm/label/label.go | 1 + core/chains/evm/logpoller/helper_test.go | 8 - core/chains/evm/logpoller/log_poller.go | 10 +- core/chains/evm/logpoller/log_poller_test.go | 9 +- core/chains/evm/txmgr/builder.go | 11 +- core/chains/evm/txmgr/client.go | 8 +- core/chains/evm/txmgr/config.go | 1 + core/chains/evm/txmgr/confirmer_test.go | 2360 +++++++++-- core/chains/evm/txmgr/evm_tx_store.go | 419 +- core/chains/evm/txmgr/evm_tx_store_test.go | 510 +-- core/chains/evm/txmgr/finalizer.go | 459 +-- core/chains/evm/txmgr/finalizer_test.go | 941 +---- core/chains/evm/txmgr/mocks/evm_tx_store.go | 694 ++-- core/chains/evm/txmgr/nonce_tracker.go | 2 - core/chains/evm/txmgr/txmgr_test.go | 13 + core/chains/legacyevm/chain.go | 22 +- core/chains/legacyevm/evm_txm.go | 37 +- core/cmd/admin_commands.go | 1 - core/cmd/app.go | 25 +- core/cmd/chains_commands.go | 62 +- core/cmd/chains_commands_test.go | 81 - core/cmd/cosmos_chains_commands.go | 48 + core/cmd/cosmos_chains_commands_test.go | 33 + core/cmd/cosmos_node_commands.go | 44 + core/cmd/cosmos_node_commands_test.go | 71 + core/cmd/evm_chains_commands.go | 48 + core/cmd/evm_chains_commands_test.go | 38 + core/cmd/evm_node_commands.go | 44 + core/cmd/evm_node_commands_test.go | 94 + core/cmd/node_commands_test.go | 290 -- core/cmd/nodes_commands.go | 69 +- core/cmd/shell.go | 28 +- core/cmd/shell_local.go | 31 +- core/cmd/shell_local_test.go | 10 +- core/cmd/shell_remote_test.go | 30 + core/cmd/shell_test.go | 29 +- core/cmd/solana_chains_commands.go | 48 + core/cmd/solana_chains_commands_test.go | 32 + core/cmd/solana_node_commands.go | 44 + core/cmd/solana_node_commands_test.go | 88 + core/cmd/starknet_chains_commands.go | 48 + core/cmd/starknet_node_commands.go | 44 + core/cmd/starknet_node_commands_test.go | 88 + core/config/app_config.go | 1 + core/config/capabilities_config.go | 8 - core/config/database_config.go | 4 +- core/config/docs/chains-evm.toml | 2 - core/config/docs/chains-solana.toml | 3 - core/config/docs/core.toml | 12 - core/config/docs/defaults.go | 5 +- core/config/mercury_config.go | 1 - core/config/toml/types.go | 31 +- .../ccip/deployment_test/deployment_test.go | 9 +- .../burn_from_mint_token_pool.go | 338 +- .../burn_mint_token_pool.go | 338 +- .../burn_with_from_mint_token_pool.go | 338 +- .../ccip/generated/ccip_config/ccip_config.go | 1126 +++++ .../ccip/generated/ccip_home/ccip_home.go | 28 +- .../ccip_reader_tester/ccip_reader_tester.go | 42 +- .../ether_sender_receiver.go | 2 +- .../ccip/generated/fee_quoter/fee_quoter.go | 28 +- .../lock_release_token_pool.go | 338 +- .../maybe_revert_message_receiver.go | 2 +- .../message_hasher/message_hasher.go | 2 +- .../mock_usdc_token_messenger.go | 2 +- .../mock_usdc_token_transmitter.go | 2 +- .../mock_v3_aggregator_contract.go | 2 +- .../multi_aggregate_rate_limiter.go | 2 +- .../multi_ocr3_helper/multi_ocr3_helper.go | 20 +- .../generated/nonce_manager/nonce_manager.go | 2 +- .../ccip/generated/offramp/offramp.go | 31 +- .../ccip/generated/onramp/onramp.go | 2 +- .../ping_pong_demo/ping_pong_demo.go | 2 +- .../registry_module_owner_custom.go | 2 +- .../generated/report_codec/report_codec.go | 2 +- .../ccip/generated/rmn_home/rmn_home.go | 2 +- .../rmn_proxy_contract/rmn_proxy_contract.go | 2 +- .../ccip/generated/rmn_remote/rmn_remote.go | 51 +- .../ccip/generated/router/router.go | 2 +- .../token_admin_registry.go | 2 +- .../ccip/generated/token_pool/token_pool.go | 332 +- .../usdc_reader_tester/usdc_reader_tester.go | 2 +- .../usdc_token_pool/usdc_token_pool.go | 334 +- .../ccip/generated/weth9/weth9.go | 2 +- ...rapper-dependency-versions-do-not-edit.txt | 62 +- core/gethwrappers/ccip/go_generate.go | 62 +- .../ccip/mocks/fee_quoter_interface.go | 57 - core/gethwrappers/go_generate.go | 1 + core/gethwrappers/go_generate_test.go | 5 +- .../capabilities_registry.go | 2352 ----------- .../feeds_consumer_1_0_0/feeds_consumer.go | 756 ---- .../generated/forwarder_1_0_0/forwarder.go | 1337 ------ .../ocr3_capability_1_0_0/ocr3_capability.go | 946 ----- .../generated/configurator/configurator.go | 2 +- .../exposed_configurator.go | 2 +- ...rapper-dependency-versions-do-not-edit.txt | 4 +- .../burn_mint_erc20/burn_mint_erc20.go | 1639 -------- .../shared/generated/multicall3/multicall3.go | 525 --- ...rapper-dependency-versions-do-not-edit.txt | 2 - core/gethwrappers/shared/go_generate.go | 2 - .../generated/entry_point/entry_point.go | 1871 +++++++++ .../greeter_wrapper/greeter_wrapper.go | 216 + .../paymaster_wrapper/paymaster_wrapper.go | 719 ++++ .../generated/sca_wrapper/sca_wrapper.go | 292 ++ .../smart_contract_account_factory.go | 333 ++ .../smart_contract_account_helper.go | 322 ++ ...rapper-dependency-versions-do-not-edit.txt | 9 + core/gethwrappers/transmission/go_generate.go | 11 + .../workflow_registry_wrapper.go | 48 +- ...rapper-dependency-versions-do-not-edit.txt | 2 +- core/internal/cltest/cltest.go | 12 +- core/internal/cltest/mocks.go | 7 +- core/internal/features/features_test.go | 52 +- .../features/ocr2/features_ocr2_helper.go | 705 ---- .../ocr2/features_ocr2_plugin_test.go | 14 + .../features/ocr2/features_ocr2_test.go | 709 +++- .../ocr2/plugins/features_ocr2_plugin_test.go | 16 - .../internal/features/ocr2/plugins/plugins.go | 3 - .../testutils/configtest/general_config.go | 6 +- core/internal/testutils/pgtest/pgtest.go | 19 +- core/internal/testutils/pgtest/txdb.go | 509 +++ core/internal/testutils/testutils.go | 14 +- core/logger/null_logger.go | 1 + core/platform/monitoring.go | 16 +- core/scripts/chaincli/README.md | 2 +- core/scripts/chaincli/handler/handler.go | 2 +- core/scripts/go.mod | 218 +- core/scripts/go.sum | 593 ++- core/scripts/keystone/README.md | 2 +- .../keystone/src/01_deploy_contracts_cmd.go | 8 +- ...deploy_initialize_capabilities_registry.go | 259 +- core/scripts/keystone/src/88_gen_jobspecs.go | 4 +- .../keystone/src/88_gen_ocr3_config.go | 7 +- core/scripts/keystone/src/99_fetch_keys.go | 10 +- core/services/chainlink/application.go | 72 +- .../services/chainlink/config_capabilities.go | 26 - core/services/chainlink/config_database.go | 8 +- .../chainlink/config_database_test.go | 39 +- core/services/chainlink/config_mercury.go | 4 - core/services/chainlink/config_test.go | 11 - .../mocks/relayer_chain_interoperators.go | 3 +- .../chainlink/relayer_chain_interoperators.go | 12 +- core/services/chainlink/relayer_factory.go | 12 +- .../testdata/config-empty-effective.toml | 6 - .../chainlink/testdata/config-full.toml | 8 - .../config-multi-chain-effective.toml | 11 - core/services/feeds/models.go | 4 - core/services/feeds/models_test.go | 5 - core/services/feeds/service.go | 60 +- core/services/feeds/service_test.go | 690 +--- .../fluxmonitorv2/flux_monitor_test.go | 2 +- .../fluxmonitorv2/integrations_test.go | 12 +- core/services/gateway/connector/connector.go | 47 +- .../connector/mocks/gateway_connector.go | 200 +- .../gateway/handlers/capabilities/handler.go | 12 +- core/services/gateway/network/httpclient.go | 2 +- core/services/job/job_orm_test.go | 55 +- core/services/job/mocks/orm.go | 57 - core/services/job/models.go | 25 +- core/services/job/models_test.go | 2 + core/services/job/orm.go | 39 +- .../job/testdata/wasm/test_workflow_spec.go | 10 +- core/services/keystore/keys/csakey/key_v2.go | 10 +- .../keystore/keys/keystest/keystest.go | 15 + .../keystore/keys/ocr2key/evm_keyring.go | 2 +- .../keystore/keys/ocr2key/evm_keyring_test.go | 64 - .../keystore/keys/ocr2key/key_bundle.go | 2 + .../keystore/keys/ocrkey/key_bundle.go | 259 ++ .../keystore/keys/ocrkey/key_bundle_test.go | 102 + .../keystore/keys/ocrkey/key_v2_test.go | 38 - ...y_test.go => off_chan_private_key_test.go} | 4 +- core/services/keystore/keys/solkey/key.go | 4 +- .../services/keystore/keys/workflowkey/key.go | 16 - core/services/keystore/keystoretest.go | 1 - core/services/keystore/mocks/workflow.go | 474 --- core/services/keystore/models.go | 17 - core/services/keystore/workflow_test.go | 35 - core/services/llo/bm/dummy_transmitter.go | 10 +- .../llo/channel_definition_cache_factory.go | 2 + .../channel_definition_cache_factory_test.go | 58 - core/services/llo/codecs.go | 5 +- core/services/llo/codecs_test.go | 3 +- core/services/llo/data_source.go | 76 +- core/services/llo/delegate.go | 39 +- core/services/llo/evm/fees_test.go | 10 - core/services/llo/evm/report_codec.go | 54 + .../llo/evm/report_codec_premium_legacy.go | 68 +- .../evm/report_codec_premium_legacy_test.go | 31 +- core/services/llo/keyring.go | 20 +- core/services/llo/keyring_test.go | 9 +- core/services/llo/mercurytransmitter/orm.go | 4 +- core/services/llo/mercurytransmitter/queue.go | 13 +- .../services/llo/mercurytransmitter/server.go | 253 +- .../llo/mercurytransmitter/transmitter.go | 81 +- .../mercurytransmitter/transmitter_test.go | 14 +- .../llo/onchain_channel_definition_cache.go | 107 +- .../onchain_channel_definition_cache_test.go | 47 +- ...gin_scoped_retirement_report_cache_test.go | 19 - .../llo/static_channel_definitions_cache.go | 3 +- core/services/llo/suppressed_logger.go | 51 - core/services/llo/telemetry.go | 16 +- core/services/llo/transmitter.go | 19 +- core/services/ocr/database.go | 2 +- core/services/ocr2/database.go | 2 +- core/services/ocr2/delegate.go | 23 +- .../plugins/ccip/ccipexec/gashelpers_test.go | 6 + .../plugins/ccip/clo_ccip_integration_test.go | 2 - .../plugins/ccip/integration_legacy_test.go | 594 +++ .../ocr2/plugins/ccip/integration_test.go | 2 - .../ocr2/plugins/ccip/metrics_test.go | 3 - .../ocr2/plugins/ccip/observations_test.go | 9 - .../ccip/testhelpers/ccip_contracts.go | 51 +- .../ccip/testhelpers/integration/chainlink.go | 7 +- .../ccip/testhelpers/integration/jobspec.go | 25 - .../ccip/testhelpers/simulated_backend.go | 2 +- .../testhelpers_1_4_0/ccip_contracts_1_4_0.go | 1620 ++++++++ .../testhelpers_1_4_0/chainlink.go | 1053 +++++ .../testhelpers_1_4_0/config_1_4_0.go | 75 + .../v1/internal/testutils.go | 4 +- .../ocr2/plugins/generic/relayerset_test.go | 2 +- .../ocr2/plugins/llo/config/config.go | 2 + .../services/ocr2/plugins/llo/helpers_test.go | 1 - .../ocr2/plugins/llo/integration_test.go | 68 +- core/services/ocr2/plugins/mercury/plugin.go | 89 +- .../ocr2/plugins/mercury/plugin_test.go | 133 +- .../plugins/ocr2keeper/integration_test.go | 8 +- core/services/ocr2/validate/validate.go | 4 +- core/services/ocr3/promwrapper/factory.go | 54 - .../services/ocr3/promwrapper/factory_test.go | 43 - core/services/ocr3/promwrapper/plugin.go | 154 - core/services/ocr3/promwrapper/plugin_test.go | 196 - core/services/ocr3/promwrapper/types.go | 65 - core/services/ocrcommon/adapters.go | 2 +- core/services/ocrcommon/telemetry.go | 4 + core/services/ocrcommon/telemetry_test.go | 31 +- core/services/pg/connection.go | 12 +- core/services/pg/connection_test.go | 10 +- core/services/pg/locked_db.go | 5 +- core/services/pipeline/runner.go | 26 +- .../services/registrysyncer/local_registry.go | 2 +- core/services/registrysyncer/orm.go | 2 +- core/services/registrysyncer/orm_test.go | 2 +- core/services/registrysyncer/syncer.go | 3 +- core/services/registrysyncer/syncer_test.go | 2 +- core/services/relay/dummy/relayer.go | 2 +- .../relay/evm/bindings/chain_reader_tester.go | 2 +- core/services/relay/evm/cap_encoder.go | 58 +- core/services/relay/evm/cap_encoder_test.go | 72 - .../evm/capabilities/testutils/backend.go | 2 +- .../workflows/syncer/workflow_syncer_test.go | 726 ---- .../relay/evm/chain_components_test.go | 30 +- core/services/relay/evm/chain_reader.go | 51 +- ...n_reader_historical_client_wrapper_test.go | 3 +- core/services/relay/evm/chain_writer.go | 2 +- .../chain_writer_historical_wrapper_test.go | 9 +- core/services/relay/evm/codec/codec_test.go | 9 +- core/services/relay/evm/commit_provider.go | 4 +- core/services/relay/evm/evm.go | 61 +- .../evm/evmtesting/bindings_test_adapter.go | 25 +- .../chain_components_interface_tester.go | 7 +- .../relay/evm/evmtesting/run_tests.go | 2 +- core/services/relay/evm/llo/config_poller.go | 60 +- .../relay/evm/llo/config_poller_test.go | 35 +- .../relay/evm/llo/should_retire_cache.go | 60 +- .../relay/evm/llo/should_retire_cache_test.go | 3 +- core/services/relay/evm/llo_provider.go | 2 + .../services/relay/evm/mercury/transmitter.go | 11 +- .../v1/reportcodec/report_codec_test.go | 2 +- .../relay/evm/ocr3_capability_provider.go | 2 +- core/services/relay/evm/read/batch.go | 74 +- core/services/relay/evm/read/errors.go | 80 +- core/services/relay/evm/read/event.go | 4 +- core/services/relay/evm/read/method.go | 20 +- .../services/relay/evm/read/multieventtype.go | 216 - .../relay/evm/read/multieventtype_test.go | 119 - .../statuschecker/txm_status_checker_test.go | 5 +- core/services/relay/evm/write_target.go | 4 +- core/services/relay/evm/write_target_test.go | 2 +- core/services/relay/relay.go | 2 +- .../services/transmission/integration_test.go | 495 +++ core/services/transmission/signature.go | 19 + .../vrf_v08_solidity_crosscheck_test.go | 51 + .../vrf/v2/integration_helpers_test.go | 10 +- .../vrf/v2/integration_v2_plus_test.go | 8 +- .../v2/integration_v2_reverted_txns_test.go | 5 +- core/services/vrf/v2/integration_v2_test.go | 59 +- .../vrf/v2/listener_v2_log_listener_test.go | 35 +- core/services/workflows/delegate.go | 13 +- core/services/workflows/engine.go | 128 +- core/services/workflows/engine_test.go | 17 +- core/services/workflows/models.go | 6 +- core/services/workflows/monitoring.go | 233 +- core/services/workflows/monitoring_test.go | 5 +- core/services/workflows/store/store_db.go | 16 +- .../workflows/syncer/engine_registry.go | 76 - core/services/workflows/syncer/fetcher.go | 108 - .../services/workflows/syncer/fetcher_test.go | 114 - core/services/workflows/syncer/handler.go | 715 ---- .../services/workflows/syncer/handler_test.go | 992 ----- core/services/workflows/syncer/mocks/orm.go | 789 ---- core/services/workflows/syncer/orm.go | 429 -- core/services/workflows/syncer/orm_test.go | 456 -- .../workflows/syncer/workflow_registry.go | 574 +-- .../services/workflows/test/break/cmd/main.go | 7 +- core/services/workflows/test/wasm/cmd/main.go | 7 +- core/store/dialects/dialects.go | 18 + core/store/migrate/migrate.go | 2 + .../migrations/0036_external_job_id.go | 3 + .../migrations/0054_remove_legacy_pipeline.go | 2 + .../migrate/migrations/0056_multichain.go | 2 + ...d_not_null_to_evm_chain_id_in_job_specs.go | 2 + .../migrations/0259_add_workflow_secrets.sql | 42 - .../0260_add_status_workflow_spec.sql | 9 - .../0261_remove_unique_constraint_secrets.sql | 10 - .../migrations/0262_add_solana_schema.sql | 72 - core/utils/big_math/big_math.go | 1 + core/utils/crypto/keccak_256.go | 16 - core/utils/files.go | 1 + core/utils/matches/matches.go | 21 - core/utils/testutils/heavyweight/orm.go | 11 +- core/utils/utils.go | 2 + core/web/assets/index.html | 2 +- core/web/assets/index.html.gz | Bin 420 -> 421 bytes ...61321d.js => main.57f94389bc8271642420.js} | 4 +- ....js.gz => main.57f94389bc8271642420.js.gz} | Bin 1198171 -> 1197396 bytes core/web/chains_controller.go | 62 +- core/web/chains_controller_test.go | 586 --- core/web/cosmos_chains_controller.go | 17 + core/web/cosmos_chains_controller_test.go | 193 + core/web/cosmos_nodes_controller.go | 18 + core/web/cosmos_transfer_controller.go | 4 +- core/web/evm_chains_controller.go | 19 + core/web/evm_chains_controller_test.go | 215 + core/web/evm_nodes_controller.go | 14 + core/web/middleware.go | 24 +- core/web/nodes_controller.go | 42 +- core/web/presenters/chain.go | 37 - core/web/presenters/cosmos_chain.go | 45 + core/web/presenters/evm_chain.go | 43 + core/web/presenters/job.go | 2 - core/web/presenters/jsonapi.go | 4 +- core/web/presenters/node_test.go | 58 +- core/web/presenters/p2p_key_test.go | 5 +- core/web/presenters/solana_chain.go | 45 + core/web/presenters/starknet_chain.go | 45 + core/web/resolver/spec.go | 18 +- core/web/resolver/spec_test.go | 97 - .../testdata/config-empty-effective.toml | 6 - core/web/resolver/testdata/config-full.toml | 8 - .../config-multi-chain-effective.toml | 11 - core/web/router.go | 43 +- core/web/schema/type/spec.graphql | 3 +- core/web/solana_chains_controller.go | 17 + core/web/solana_chains_controller_test.go | 216 + core/web/solana_nodes_controller.go | 17 + core/web/solana_transfer_controller.go | 2 - core/web/starknet_chains_controller.go | 17 + core/web/starknet_nodes_controller.go | 17 + core/web/testutils/mock_relayer.go | 2 +- deployment/.golangci.yml | 107 +- deployment/.mockery.yaml | 13 - deployment/README.md | 26 +- deployment/address_book.go | 78 +- deployment/address_book_test.go | 41 +- deployment/ccip/active_candidate.go | 139 + deployment/ccip/add_lane.go | 138 + deployment/ccip/add_lane_test.go | 154 + .../ccip/changeset/accept_ownership_test.go | 126 - deployment/ccip/changeset/active_candidate.go | 97 + .../ccip/changeset/active_candidate_test.go | 247 ++ deployment/ccip/changeset/add_chain.go | 144 + deployment/ccip/changeset/add_chain_test.go | 240 ++ deployment/ccip/changeset/cs_add_lane_test.go | 124 - deployment/ccip/changeset/cs_ccip_home.go | 1212 ------ .../ccip/changeset/cs_ccip_home_test.go | 529 --- .../ccip/changeset/cs_chain_contracts.go | 1129 ----- .../ccip/changeset/cs_chain_contracts_test.go | 364 -- deployment/ccip/changeset/cs_deploy_chain.go | 402 -- .../ccip/changeset/cs_deploy_chain_test.go | 116 - deployment/ccip/changeset/cs_home_chain.go | 418 -- .../ccip/changeset/cs_home_chain_test.go | 173 - deployment/ccip/changeset/cs_jobspec_test.go | 36 - deployment/ccip/changeset/cs_prerequisites.go | 433 -- .../ccip/changeset/cs_update_rmn_config.go | 588 --- .../changeset/cs_update_rmn_config_test.go | 306 -- deployment/ccip/changeset/home_chain.go | 73 + deployment/ccip/changeset/home_chain_test.go | 63 + deployment/ccip/changeset/initial_deploy.go | 30 + .../ccip/changeset/initial_deploy_test.go | 103 + .../changeset/internal/deploy_home_chain.go | 349 -- deployment/ccip/changeset/prerequisites.go | 58 + ...quisites_test.go => prerequisites_test.go} | 10 +- .../changeset/save_existing.go | 9 +- .../ccip/changeset/save_existing_test.go | 23 +- deployment/ccip/changeset/solana_state.go | 6 - deployment/ccip/changeset/state_test.go | 15 - deployment/ccip/changeset/test_environment.go | 612 --- deployment/ccip/changeset/test_helpers.go | 1259 ------ deployment/ccip/changeset/v1_5/cs_jobspec.go | 149 - .../ccip/changeset/v1_5/cs_lane_contracts.go | 288 -- .../ccip/changeset/v1_5/cs_ocr2_config.go | 329 -- deployment/ccip/changeset/v1_5/e2e_test.go | 56 - .../ccip/changeset/v1_5/test_helpers.go | 384 -- deployment/ccip/changeset/view.go | 3 +- deployment/ccip/changeset/view_test.go | 14 - deployment/ccip/consts.go | 11 + deployment/ccip/deploy.go | 851 ++++ deployment/ccip/deploy_home_chain.go | 1085 +++++ deployment/ccip/deploy_test.go | 86 + .../ccip/{changeset/cs_jobspec.go => jobs.go} | 34 +- deployment/ccip/ownership.go | 37 + deployment/ccip/propose.go | 247 ++ deployment/ccip/{changeset => }/state.go | 451 +- .../ccip/{changeset => }/test_assertions.go | 277 +- deployment/ccip/test_helpers.go | 797 ++++ .../ccip/{changeset => }/test_params.go | 4 +- .../ccip/{changeset => }/test_usdc_helpers.go | 135 +- deployment/ccip/{changeset => }/token_info.go | 19 +- deployment/ccip/view/types/contract_state.go | 33 + deployment/ccip/view/v1_2/price_registry.go | 45 - .../ccip/view/v1_2/price_registry_test.go | 38 - deployment/ccip/view/v1_5/offramp.go | 40 - deployment/ccip/view/v1_5/offramp_test.go | 60 - deployment/ccip/view/v1_5/onramp.go | 39 - deployment/ccip/view/v1_5/onramp_test.go | 71 - deployment/ccip/view/v1_5/rmn.go | 31 - deployment/ccip/view/v1_5/rmn_test.go | 53 - deployment/ccip/view/v1_6/capreg.go | 45 + deployment/ccip/view/v1_6/ccip_home.go | 85 - deployment/ccip/view/v1_6/ccip_home_test.go | 40 - deployment/ccip/view/v1_6/rmnhome.go | 214 - deployment/ccip/view/view.go | 35 +- .../common/changeset/deploy_link_token.go | 59 - .../changeset/deploy_link_token_test.go | 35 - .../changeset/deploy_mcms_with_timelock.go | 39 - .../example/add_mint_burners_link.go | 70 - .../example/add_mint_burners_link_test.go | 50 - .../common/changeset/example/link_transfer.go | 239 -- .../changeset/example/link_transfer_test.go | 373 -- .../common/changeset/example/mint_link.go | 43 - .../changeset/example/mint_link_test.go | 58 - deployment/common/changeset/internal/mcms.go | 172 - .../common/changeset/internal/mcms_test.go | 49 - .../common/changeset/save_existing_test.go | 54 - .../common/changeset/set_config_mcms.go | 209 - .../common/changeset/set_config_mcms_test.go | 313 -- deployment/common/changeset/state.go | 227 - deployment/common/changeset/test_helpers.go | 99 - .../transfer_to_mcms_with_timelock.go | 274 -- .../transfer_to_mcms_with_timelock_test.go | 215 - .../common/proposalutils/mcms_helpers.go | 275 -- .../common/proposalutils/mcms_test_helpers.go | 92 - deployment/common/proposalutils/propose.go | 88 - deployment/common/types/types.go | 91 - deployment/common/view/nops.go | 20 +- .../common/view/types/contract_state.go | 6 +- deployment/common/view/v1_0/capreg.go | 125 +- deployment/common/view/v1_0/capreg_test.go | 5 +- deployment/common/view/v1_0/link_token.go | 58 - .../common/view/v1_0/link_token_test.go | 53 - deployment/common/view/v1_0/mcms.go | 164 - .../common/view/v1_0/static_link_token.go | 40 - .../view/v1_0/static_link_token_test.go | 32 - deployment/environment.go | 178 +- deployment/environment/clo/don_nodeset.go | 67 + .../environment/clo/don_nodeset_test.go | 104 + deployment/environment/clo/models/models.go | 28 + .../environment/clo/models/models_gen.go | 3653 +++++++++++++++++ .../environment/clo/offchain_client_impl.go | 265 ++ .../clo/offchain_client_impl_test.go | 677 +++ .../clo/testdata/keystone_nops.json | 3162 ++++++++++++++ deployment/environment/clo/utils.go | 101 + deployment/environment/clo/utils_test.go | 168 + deployment/environment/crib/ccip_deployer.go | 225 - deployment/environment/crib/data.go | 81 - deployment/environment/crib/env.go | 45 - deployment/environment/crib/env_test.go | 18 - .../ccip-v2-scripts-address-book.json | 1 - .../ccip-v2-scripts-chains-details.json | 24 - .../ccip-v2-scripts-nodes-details.json | 1 - deployment/environment/crib/types.go | 39 - deployment/environment/devenv/.sample.env | 6 - deployment/environment/devenv/README.md | 12 +- deployment/environment/devenv/chain.go | 88 +- deployment/environment/devenv/don.go | 116 +- deployment/environment/devenv/environment.go | 28 +- deployment/environment/devenv/jd.go | 34 +- deployment/environment/devenv/rmn.go | 12 +- deployment/environment/devenv/rmn_config.go | 2 +- deployment/environment/memory/chain.go | 58 +- deployment/environment/memory/environment.go | 74 +- deployment/environment/memory/job_client.go | 45 +- deployment/environment/memory/node.go | 6 - deployment/environment/memory/node_test.go | 3 +- .../environment/web/sdk/client/client.go | 22 +- deployment/environment_test.go | 91 - deployment/evm_kmsclient.go | 19 - deployment/go.mod | 56 +- deployment/go.sum | 209 +- deployment/helpers.go | 62 +- .../internal => }/capability_definitions.go | 4 +- deployment/keystone/capability_management.go | 70 + .../capability_registry_deployer.go | 13 +- .../keystone/changeset/accept_ownership.go | 49 - .../changeset/accept_ownership_test.go | 72 - .../keystone/changeset/addrbook_utils.go | 113 - .../append_node_capabilities_test.go | 134 - ...bilities.go => append_node_capbilities.go} | 47 +- deployment/keystone/changeset/compatiblity.go | 95 - .../keystone/changeset/configure_contracts.go | 22 +- .../keystone/changeset/deploy_consumer.go | 31 - .../changeset/deploy_consumer_test.go | 40 - .../keystone/changeset/deploy_forwarder.go | 118 +- .../changeset/deploy_forwarder_test.go | 130 +- deployment/keystone/changeset/deploy_ocr3.go | 98 +- .../keystone/changeset/deploy_ocr3_test.go | 103 - .../keystone/changeset/deploy_registry.go | 15 +- .../changeset/deploy_registry_test.go | 1 - .../internal/append_node_capabilities.go | 36 +- .../internal/append_node_capabilities_test.go | 4 +- .../internal/capability_management.go | 92 - .../changeset/internal/consumer_deployer.go | 55 - .../changeset/internal/contract_set.go | 115 - .../changeset/internal/forwarder_deployer.go | 101 - .../changeset/internal/ocr3config_test.go | 179 - .../keystone/changeset/internal/test/utils.go | 105 +- .../internal/testdata/testnet_wf_view.json | 262 -- .../keystone/changeset/internal/types.go | 348 -- .../keystone/changeset/internal/types_test.go | 78 - .../keystone/changeset/internal/update_don.go | 63 +- .../changeset/internal/update_don_test.go | 145 +- .../internal/update_node_capabilities.go | 18 +- .../internal/update_node_capabilities_test.go | 20 +- .../changeset/internal/update_nodes.go | 77 +- .../changeset/internal/update_nodes_test.go | 63 +- deployment/keystone/changeset/test/helpers.go | 391 -- .../keystone/changeset/test/helpers_test.go | 34 - deployment/keystone/changeset/types.go | 43 + deployment/keystone/changeset/update_don.go | 95 +- .../keystone/changeset/update_don_test.go | 159 - .../changeset/update_node_capabilities.go | 95 +- .../update_node_capabilities_test.go | 208 - deployment/keystone/changeset/update_nodes.go | 86 +- .../keystone/changeset/update_nodes_test.go | 139 - deployment/keystone/changeset/view.go | 13 +- deployment/keystone/changeset/view_test.go | 3 +- .../changeset/workflowregistry/deploy.go | 25 - .../changeset/workflowregistry/deploy_test.go | 38 - .../changeset/workflowregistry/setup_test.go | 54 - .../changeset/workflowregistry/strategies.go | 85 - .../workflowregistry/update_allowed_dons.go | 80 - .../update_allowed_dons_test.go | 110 - .../update_authorized_addresses.go | 105 - .../update_authorized_addresses_test.go | 113 - .../workflow_registry_deployer.go | 76 - deployment/keystone/contract_set.go | 93 + .../{changeset/internal => }/deploy.go | 755 ++-- deployment/keystone/deploy_test.go | 439 ++ deployment/keystone/deprecated.go | 127 - deployment/keystone/forwarder_deployer.go | 50 + .../{changeset/internal => }/ocr3_deployer.go | 13 +- .../{changeset/internal => }/ocr3config.go | 165 +- .../{changeset/internal => }/state.go | 41 +- .../test/changeset/capability_registry.go | 88 - .../changeset/capability_registry_test.go | 46 - .../testdata/capability_registry_view.json | 455 -- deployment/keystone/testdata/asset_nodes.json | 978 +++++ .../keystone/testdata/chain_writer_nodes.json | 1447 +++++++ deployment/keystone/testdata/ocr3config.json | 27 + .../keystone/testdata/workflow_nodes.json | 1107 +++++ deployment/keystone/types.go | 429 ++ deployment/keystone/types_test.go | 402 ++ deployment/mocks/offchain_client_mock.go | 1375 ------- deployment/multiclient.go | 27 +- deployment/multiclient_test.go | 24 +- deployment/solana_chain.go | 5 - docs/CONFIG.md | 1657 ++------ flake.lock | 30 +- go.mod | 100 +- go.sum | 447 +- integration-tests/.golangci.yml | 107 +- integration-tests/.tool-versions | 4 +- integration-tests/actions/actions.go | 32 +- .../actions/automationv2/actions.go | 8 +- integration-tests/actions/ccip_helpers.go | 45 - integration-tests/actions/keeper_helpers.go | 15 +- integration-tests/actions/ocr2_helpers.go | 45 +- integration-tests/actions/refund.go | 4 - .../actions/vrf/vrfv2plus/setup_steps.go | 2 +- .../benchmark/automation_test.go | 14 +- .../ccip-tests/actions/ccip_helpers.go | 35 +- .../ccip-tests/actions/reorg_helpers.go | 6 +- .../ccip-tests/contracts/contract_deployer.go | 35 +- .../ccip-tests/contracts/contract_models.go | 19 +- .../ccip-tests/load/ccip_loadgen.go | 2 +- .../ccip-tests/smoke/ccip_test.go | 45 +- .../ccip-tests/testconfig/README.md | 26 + .../ccip-tests/testconfig/global.go | 119 +- .../testconfig/tomls/ccip-default.toml | 13 +- .../testconfig/tomls/contract-version1.4.toml | 13 + .../ccip-tests/testsetups/ccip.go | 22 +- .../ccip-tests/testsetups/test_env.go | 2 + .../testsetups}/test_helpers.go | 525 +-- .../ccip-tests/types/config/node/core.go | 4 - integration-tests/ccip-tests/utils/common.go | 5 - .../chaos/automation_chaos_test.go | 9 - integration-tests/chaos/ocr_chaos_test.go | 11 +- .../contracts/ccipreader_test.go | 1576 ------- .../ethereum_contracts_automation.go | 12 +- integration-tests/crib/README.md | 2 +- integration-tests/docker/test_env/cl_node.go | 14 +- integration-tests/docker/test_env/test_env.go | 14 +- .../docker/test_env/test_env_builder.go | 196 +- integration-tests/example.env | 2 - integration-tests/go.mod | 83 +- integration-tests/go.sum | 281 +- .../automationv2_1/automationv2_1_test.go | 9 - integration-tests/load/functions/gateway.go | 4 - .../load/functions/gateway_gun.go | 32 +- integration-tests/load/functions/setup.go | 12 +- integration-tests/load/go.mod | 173 +- integration-tests/load/go.sum | 257 +- integration-tests/load/vrfv2/gun.go | 10 +- integration-tests/load/vrfv2plus/gun.go | 9 +- .../smoke/ccip/ccip_batching_test.go | 534 --- .../smoke/ccip/ccip_fee_boosting_test.go | 281 -- .../smoke/ccip/ccip_fees_test.go | 458 --- .../smoke/ccip/ccip_gas_price_updates_test.go | 125 - .../smoke/ccip/ccip_legacy_test.go | 51 - .../ccip/ccip_message_limitations_test.go | 186 - .../smoke/ccip/ccip_ooo_execution_test.go | 270 -- integration-tests/smoke/ccip/ccip_rmn_test.go | 693 ---- .../ccip/ccip_token_price_updates_test.go | 150 - .../smoke/ccip/ccip_token_transfer_test.go | 219 - .../smoke/ccip/ccip_usdc_test.go | 258 -- .../smoke/{ccip => }/ccip_messaging_test.go | 110 +- integration-tests/smoke/ccip_rmn_test.go | 459 +++ integration-tests/smoke/ccip_test.go | 272 ++ integration-tests/smoke/ccip_usdc_test.go | 283 ++ integration-tests/smoke/fee_boosting_test.go | 158 + .../smoke/forwarders_ocr2_test.go | 5 +- integration-tests/smoke/log_poller_test.go | 15 +- integration-tests/smoke/ocr2_test.go | 180 +- integration-tests/smoke/vrfv2_test.go | 25 +- integration-tests/smoke/vrfv2plus_test.go | 36 +- .../testconfig/automation/example.toml | 8 + integration-tests/testconfig/ccip/ccip.toml | 90 +- integration-tests/testconfig/ccip/config.go | 111 +- .../ccip/overrides/sepolia_avax_binance.toml | 4 + integration-tests/testconfig/default.toml | 15 +- .../testconfig/forwarder_ocr/example.toml | 27 + .../testconfig/forwarder_ocr2/example.toml | 27 + .../testconfig/functions/example.toml | 8 + .../testconfig/keeper/example.toml | 8 + .../testconfig/log_poller/example.toml | 8 + .../testconfig/node/example.toml | 8 + integration-tests/testconfig/ocr/example.toml | 27 + .../testconfig/ocr2/example.toml | 27 + integration-tests/testconfig/testconfig.go | 21 + .../testconfig/testconfig_utils.go | 13 +- .../testconfig/vrfv2/example.toml | 8 + .../testconfig/vrfv2plus/example.toml | 8 + integration-tests/testreporters/keeper.go | 13 +- .../testreporters/keeper_benchmark.go | 12 +- .../testsetups/automation_benchmark.go | 9 +- integration-tests/testsetups/ocr.go | 277 +- integration-tests/types/config/node/core.go | 25 +- .../universal/log_poller/helpers.go | 20 +- integration-tests/utils/pgtest/pgtest.go | 20 - internal/testdb/testdb.go | 6 +- operator_ui/TAG | 2 +- plugins/chainlink.Dockerfile | 16 +- plugins/registrar.go | 2 +- pnpm-lock.yaml | 227 +- shell.nix | 2 +- testdata/scripts/chains/cosmos/help.txtar | 4 +- .../scripts/chains/cosmos/list/help.txtar | 2 +- testdata/scripts/chains/evm/help.txtar | 4 +- testdata/scripts/chains/evm/list/help.txtar | 2 +- testdata/scripts/chains/help.txtar | 9 +- testdata/scripts/chains/solana/help.txtar | 4 +- .../scripts/chains/solana/list/help.txtar | 2 +- testdata/scripts/chains/starknet/help.txtar | 4 +- .../scripts/chains/starknet/list/help.txtar | 2 +- .../scripts/config/merge_raw_configs.txtar | 6 - testdata/scripts/help-all/help-all.txtar | 36 +- testdata/scripts/node/validate/default.txtar | 6 - .../node/validate/defaults-override.txtar | 7 - .../disk-based-logging-disabled.txtar | 7 - .../validate/disk-based-logging-no-dir.txtar | 7 - .../node/validate/disk-based-logging.txtar | 7 - .../node/validate/invalid-ocr-p2p.txtar | 6 - testdata/scripts/node/validate/invalid.txtar | 7 - testdata/scripts/node/validate/valid.txtar | 7 - testdata/scripts/node/validate/warnings.txtar | 6 - testdata/scripts/nodes/cosmos/help.txtar | 4 +- testdata/scripts/nodes/cosmos/list/help.txtar | 2 +- testdata/scripts/nodes/cosmos/list/list.txtar | 55 - testdata/scripts/nodes/evm/help.txtar | 4 +- testdata/scripts/nodes/evm/list/help.txtar | 2 +- testdata/scripts/nodes/evm/list/list.txtar | 63 - testdata/scripts/nodes/help.txtar | 9 +- testdata/scripts/nodes/solana/help.txtar | 4 +- testdata/scripts/nodes/solana/list/help.txtar | 2 +- testdata/scripts/nodes/solana/list/list.txtar | 57 - testdata/scripts/nodes/starknet/help.txtar | 4 +- .../scripts/nodes/starknet/list/help.txtar | 2 +- .../scripts/nodes/starknet/list/list.txtar | 55 - tools/bin/go_core_ccip_deployment_tests | 20 +- tools/bin/go_core_fuzz | 2 +- tools/bin/go_core_race_tests | 16 +- tools/bin/go_core_scripts_tests | 36 - tools/bin/go_core_tests | 18 +- tools/bin/go_core_tests_integration | 16 +- tools/bin/goreleaser_utils | 4 +- tools/gomod-local-update/README.md | 41 - .../cmd/gomod-local-update/main.go | 48 - .../internal/updater/config.go | 69 - .../internal/updater/config_test.go | 177 - .../internal/updater/errors.go | 11 - .../internal/updater/system_operator.go | 34 - .../internal/updater/updater.go | 253 -- .../internal/updater/updater_test.go | 320 -- 1383 files changed, 53223 insertions(+), 70069 deletions(-) delete mode 100644 .changeset/afraid-houses-learn.md delete mode 100644 .changeset/beige-geckos-explode.md delete mode 100644 .changeset/big-camels-report.md delete mode 100644 .changeset/brave-cooks-itch.md delete mode 100644 .changeset/breezy-kings-clean.md delete mode 100644 .changeset/bright-keys-whisper.md delete mode 100644 .changeset/chilled-papayas-swim.md delete mode 100644 .changeset/chilled-suits-do.md delete mode 100644 .changeset/chilly-stingrays-press.md delete mode 100644 .changeset/clean-files-beg.md delete mode 100644 .changeset/cool-penguins-raise.md delete mode 100644 .changeset/dull-readers-rush.md delete mode 100644 .changeset/eight-tigers-march.md delete mode 100644 .changeset/eighty-geckos-switch.md delete mode 100644 .changeset/five-gifts-end.md delete mode 100644 .changeset/forty-foxes-rescue.md delete mode 100644 .changeset/fuzzy-hairs-appear.md delete mode 100644 .changeset/fuzzy-yaks-deny.md delete mode 100644 .changeset/giant-eels-jump.md delete mode 100644 .changeset/great-peaches-walk.md delete mode 100644 .changeset/hot-islands-dress.md delete mode 100644 .changeset/kind-parents-jump.md delete mode 100644 .changeset/large-fishes-enjoy.md delete mode 100644 .changeset/late-doors-battle.md delete mode 100644 .changeset/late-seals-battle.md delete mode 100644 .changeset/late-windows-clean.md delete mode 100644 .changeset/light-trains-chew.md delete mode 100644 .changeset/many-crews-wave.md delete mode 100644 .changeset/mean-dots-move.md delete mode 100644 .changeset/mean-knives-knock.md delete mode 100644 .changeset/mean-ravens-stare.md delete mode 100644 .changeset/metal-houses-approve.md delete mode 100644 .changeset/popular-rules-live.md delete mode 100644 .changeset/shaggy-carpets-deliver.md delete mode 100644 .changeset/shiny-owls-destroy.md delete mode 100644 .changeset/silver-avocados-buy.md delete mode 100644 .changeset/six-coins-mix.md delete mode 100644 .changeset/sixty-queens-wait.md delete mode 100644 .changeset/sour-hairs-cross.md delete mode 100644 .changeset/spotty-knives-smile.md delete mode 100644 .changeset/spotty-seals-give.md delete mode 100644 .changeset/thin-cats-try.md delete mode 100644 .changeset/three-mayflies-learn.md delete mode 100644 .changeset/tiny-kangaroos-switch.md delete mode 100644 .changeset/tricky-clouds-move.md delete mode 100644 .changeset/wet-bags-clean.md delete mode 100644 .changeset/wild-cats-think.md delete mode 100644 .github/actions/setup-ci-core-tests/action.yml delete mode 100644 .github/integration-in-memory-tests.yml delete mode 100755 .github/scripts/map-affected-files-to-modules.sh delete mode 100644 .github/workflows/ci-core-partial.yml create mode 100644 .github/workflows/ci-scripts.yml create mode 100644 .github/workflows/find-new-flaky-tests.yml delete mode 100644 .github/workflows/flakeguard-nightly.yml delete mode 100644 .github/workflows/flakeguard.yml delete mode 100644 .github/workflows/integration-in-memory-tests.yml rename .github/workflows/{flakeguard-on-demand.yml => run-find-new-flaky-tests.yml} (64%) create mode 100644 .github/workflows/run-nightly-flaky-test-detector.yml rename .github/workflows/{solidity-traceability.yml => solidity-tracability.yml} (99%) delete mode 100644 ccip/config/evm/Lens_Sepolia.toml delete mode 100644 contracts/.changeset/bright-jokes-kiss.md delete mode 100644 contracts/.changeset/chilly-rockets-share.md delete mode 100644 contracts/.changeset/cold-geckos-yawn.md delete mode 100644 contracts/.changeset/early-cups-relax.md delete mode 100644 contracts/.changeset/eighty-cycles-film.md delete mode 100644 contracts/.changeset/fluffy-eels-tan.md delete mode 100644 contracts/.changeset/hot-pandas-carry.md delete mode 100644 contracts/.changeset/mean-masks-poke.md delete mode 100644 contracts/.changeset/modern-mayflies-give.md delete mode 100644 contracts/.changeset/new-elephants-behave.md delete mode 100644 contracts/.changeset/ninety-lions-complain.md delete mode 100644 contracts/.changeset/perfect-bears-clean.md delete mode 100644 contracts/.changeset/rude-badgers-tickle.md delete mode 100644 contracts/.changeset/small-countries-flow.md delete mode 100644 contracts/.changeset/tame-cycles-ring.md delete mode 100644 contracts/.changeset/tender-lemons-punch.md delete mode 100644 contracts/.changeset/thirty-rules-rule.md delete mode 100644 contracts/.changeset/three-dogs-return.md delete mode 100644 contracts/.changeset/violet-lamps-pump.md delete mode 100644 contracts/.changeset/wet-eyes-accept.md delete mode 100644 contracts/.changeset/yellow-mugs-explode.md delete mode 100644 contracts/.changeset/young-bats-rhyme.md delete mode 100644 contracts/gas-snapshots/workflow.gas-snapshot create mode 100755 contracts/scripts/native_solc_compile_all_transmission create mode 100644 contracts/src/v0.8/ccip/LICENSE-MIT.md delete mode 100644 contracts/src/v0.8/ccip/libraries/ERC165CheckerReverting.sol create mode 100644 contracts/src/v0.8/ccip/test/NonceManager.t.sol delete mode 100644 contracts/src/v0.8/ccip/test/NonceManager/NonceManager.applyPreviousRampsUpdates.t.sol delete mode 100644 contracts/src/v0.8/ccip/test/NonceManager/NonceManager.getInboundNonce.t.sol delete mode 100644 contracts/src/v0.8/ccip/test/NonceManager/NonceManager.getIncrementedOutboundNonce.t.sol delete mode 100644 contracts/src/v0.8/ccip/test/NonceManager/NonceManager.getOutboundNonce.t.sol delete mode 100644 contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.supportsInterface.t.sol delete mode 100644 contracts/src/v0.8/ccip/test/libraries/ERC165CheckerReverting.supportsInterfaceReverting.t.sol create mode 100644 contracts/src/v0.8/ccip/test/mocks/MockRMN.sol delete mode 100644 contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPool.addRemotePool.t.sol delete mode 100644 contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPool.calculateLocalAmount.t.sol delete mode 100644 contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPool.parseRemoteDecimals.t.sol delete mode 100644 contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPool.removeRemotePool.t.sol delete mode 100644 contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPool.setChainRateLimiterConfigs.t.sol create mode 100644 contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPool.setRemotePool.t.sol delete mode 100644 contracts/src/v0.8/ccip/test/pools/USDC/HybridLockReleaseUSDCTokenPool/HybridLockReleaseUSDCTokenPoolSetup.t.sol delete mode 100644 contracts/src/v0.8/ccip/test/pools/USDC/USDCBridgeMigrator/USDCBridgeMigratorSetup.t.sol delete mode 100644 contracts/src/v0.8/ccip/test/pools/USDC/USDCSetup.t.sol create mode 100644 contracts/src/v0.8/ccip/test/rmn/RMNRemote/RMNRemote.globalAndLegacyCurses.t.sol delete mode 100644 contracts/src/v0.8/ccip/test/rmn/RMNRemote/RMNRemote.globalCurses.t.sol delete mode 100644 contracts/src/v0.8/ccip/test/rmn/RMNRemote/RMNRemote.isBlessed.t.sol create mode 100644 contracts/src/v0.8/ccip/test/router/Router/RouterSetup.t.sol delete mode 100644 contracts/src/v0.8/keystone/BalanceReader.sol rename contracts/src/v0.8/l2ep/{ => dev}/CrossDomainDelegateForwarder.sol (100%) rename contracts/src/v0.8/l2ep/{ => dev}/CrossDomainForwarder.sol (100%) rename contracts/src/v0.8/l2ep/{ => dev}/CrossDomainOwnable.sol (96%) rename contracts/src/v0.8/l2ep/{ => dev}/Flags.sol (95%) rename contracts/src/v0.8/l2ep/{ => dev}/arbitrum/ArbitrumCrossDomainForwarder.sol (89%) rename contracts/src/v0.8/l2ep/{ => dev}/arbitrum/ArbitrumCrossDomainGovernor.sol (93%) rename contracts/src/v0.8/l2ep/{ => dev}/arbitrum/ArbitrumSequencerUptimeFeed.sol (94%) rename contracts/src/v0.8/l2ep/{ => dev}/arbitrum/ArbitrumValidator.sol (95%) rename contracts/src/v0.8/l2ep/{ => dev}/interfaces/IArbitrumDelayedInbox.sol (84%) rename contracts/src/v0.8/l2ep/{ => dev}/interfaces/ICrossDomainOwnable.sol (100%) rename contracts/src/v0.8/l2ep/{ => dev}/interfaces/IDelegateForwarder.sol (100%) rename contracts/src/v0.8/l2ep/{ => dev}/interfaces/IFlags.sol (100%) rename contracts/src/v0.8/l2ep/{ => dev}/interfaces/IForwarder.sol (100%) rename contracts/src/v0.8/l2ep/{ => dev}/interfaces/ISequencerUptimeFeed.sol (100%) rename contracts/src/v0.8/l2ep/{ => dev}/optimism/OptimismCrossDomainForwarder.sol (91%) rename contracts/src/v0.8/l2ep/{ => dev}/optimism/OptimismCrossDomainGovernor.sol (91%) rename contracts/src/v0.8/l2ep/{ => dev}/optimism/OptimismSequencerUptimeFeed.sol (94%) rename contracts/src/v0.8/l2ep/{ => dev}/optimism/OptimismValidator.sol (97%) rename contracts/src/v0.8/l2ep/{ => dev}/scroll/ScrollCrossDomainForwarder.sol (94%) rename contracts/src/v0.8/l2ep/{ => dev}/scroll/ScrollCrossDomainGovernor.sol (96%) rename contracts/src/v0.8/l2ep/{ => dev}/scroll/ScrollSequencerUptimeFeed.sol (94%) rename contracts/src/v0.8/l2ep/{ => dev}/scroll/ScrollValidator.sol (97%) rename contracts/src/v0.8/l2ep/{base => dev/shared}/BaseSequencerUptimeFeed.sol (88%) rename contracts/src/v0.8/l2ep/{base => dev/shared}/BaseValidator.sol (84%) rename contracts/src/v0.8/l2ep/{ => dev}/zksync/ZKSyncSequencerUptimeFeed.sol (82%) rename contracts/src/v0.8/l2ep/{ => dev}/zksync/ZKSyncValidator.sol (98%) delete mode 100644 contracts/src/v0.8/l2ep/test/mocks/MockBaseSequencerUptimeFeed.sol delete mode 100644 contracts/src/v0.8/l2ep/test/mocks/MockBaseValidator.sol delete mode 100644 contracts/src/v0.8/l2ep/test/v1_0_0/shared/BaseSequencerUptimeFeed.t.sol delete mode 100644 contracts/src/v0.8/l2ep/test/v1_0_0/shared/BaseValidator.t.sol delete mode 100644 contracts/src/v0.8/shared/test/token/ERC20/BurnMintERC20/BurnMintERC20.approve.t.sol delete mode 100644 contracts/src/v0.8/shared/test/token/ERC20/BurnMintERC20/BurnMintERC20.burn.t.sol delete mode 100644 contracts/src/v0.8/shared/test/token/ERC20/BurnMintERC20/BurnMintERC20.burnFrom.t.sol delete mode 100644 contracts/src/v0.8/shared/test/token/ERC20/BurnMintERC20/BurnMintERC20.burnFromAlias.t.sol delete mode 100644 contracts/src/v0.8/shared/test/token/ERC20/BurnMintERC20/BurnMintERC20.ccipGetAdmin.t.sol delete mode 100644 contracts/src/v0.8/shared/test/token/ERC20/BurnMintERC20/BurnMintERC20.constructor.t.sol delete mode 100644 contracts/src/v0.8/shared/test/token/ERC20/BurnMintERC20/BurnMintERC20.grantMintAndBurnRoles.t.sol delete mode 100644 contracts/src/v0.8/shared/test/token/ERC20/BurnMintERC20/BurnMintERC20.mint.t.sol delete mode 100644 contracts/src/v0.8/shared/test/token/ERC20/BurnMintERC20/BurnMintERC20.supportsInterface.t.sol delete mode 100644 contracts/src/v0.8/shared/test/token/ERC20/BurnMintERC20/BurnMintERC20.transfer.t.sol delete mode 100644 contracts/src/v0.8/shared/test/token/ERC20/BurnMintERC20/BurnMintERC20Setup.t.sol delete mode 100644 contracts/src/v0.8/shared/token/ERC20/BurnMintERC20.sol create mode 100644 contracts/src/v0.8/transmission/dev/ERC-4337/Paymaster.sol create mode 100644 contracts/src/v0.8/transmission/dev/ERC-4337/SCA.sol create mode 100644 contracts/src/v0.8/transmission/dev/ERC-4337/SCALibrary.sol create mode 100644 contracts/src/v0.8/transmission/dev/ERC-4337/SmartContractAccountFactory.sol create mode 100644 contracts/src/v0.8/transmission/dev/testhelpers/Greeter.sol create mode 100644 contracts/src/v0.8/transmission/dev/testhelpers/SmartContractAccountHelper.sol create mode 100644 contracts/src/v0.8/transmission/test/BaseTest.t.sol create mode 100644 contracts/src/v0.8/transmission/test/EIP_712_1014_4337.t.sol create mode 100644 contracts/src/v0.8/vendor/entrypoint/core/EntryPoint.sol create mode 100644 contracts/src/v0.8/vendor/entrypoint/core/Helpers.sol create mode 100644 contracts/src/v0.8/vendor/entrypoint/core/SenderCreator.sol create mode 100644 contracts/src/v0.8/vendor/entrypoint/core/StakeManager.sol create mode 100644 contracts/src/v0.8/vendor/entrypoint/interfaces/IAccount.sol create mode 100644 contracts/src/v0.8/vendor/entrypoint/interfaces/IAggregator.sol create mode 100644 contracts/src/v0.8/vendor/entrypoint/interfaces/IEntryPoint.sol create mode 100644 contracts/src/v0.8/vendor/entrypoint/interfaces/IPaymaster.sol create mode 100644 contracts/src/v0.8/vendor/entrypoint/interfaces/IStakeManager.sol create mode 100644 contracts/src/v0.8/vendor/entrypoint/interfaces/UserOperation.sol create mode 100644 contracts/src/v0.8/vendor/entrypoint/utils/Exec.sol delete mode 100644 contracts/src/v0.8/vendor/multicall/ebd8b64/src/Multicall3.sol delete mode 100644 contracts/src/v0.8/workflow/mocks/MockContract.sol delete mode 100644 contracts/src/v0.8/workflow/mocks/MockWorkflowRegistryContract.sol delete mode 100644 contracts/src/v0.8/workflow/test/WorkflowRegistry/WorkflowRegistry.lockRegistry.t.sol delete mode 100644 contracts/src/v0.8/workflow/test/WorkflowRegistry/WorkflowRegistry.lockRegistry.tree delete mode 100644 contracts/src/v0.8/workflow/test/WorkflowRegistry/WorkflowRegistry.unlockRegistry.t.sol delete mode 100644 contracts/src/v0.8/workflow/test/WorkflowRegistry/WorkflowRegistry.unlockRegistry.tree delete mode 100644 contracts/src/v0.8/workflow/test/WorkflowRegistryManager/WorkflowRegistryManager.getActiveVersionNumber.t.sol delete mode 100644 contracts/src/v0.8/workflow/test/WorkflowRegistryManager/WorkflowRegistryManager.getActiveVersionNumber.tree delete mode 100644 contracts/src/v0.8/workflow/test/WorkflowRegistryManager/WorkflowRegistryManager.getLatestVersionNumber.t.sol delete mode 100644 contracts/src/v0.8/workflow/test/WorkflowRegistryManager/WorkflowRegistryManager.getLatestVersionNumber.tree create mode 100644 contracts/src/v0.8/workflow/test/WorkflowRegistryManager/WorkflowRegistryManager.getVersionNumber.t.sol rename contracts/src/v0.8/workflow/test/WorkflowRegistryManager/{WorkflowRegistryManager.getVersionNumberByContractAddressAndChainID.tree => WorkflowRegistryManager.getVersionNumber.tree} (87%) delete mode 100644 contracts/src/v0.8/workflow/test/WorkflowRegistryManager/WorkflowRegistryManager.getVersionNumberByContractAddressAndChainID.t.sol create mode 100644 core/capabilities/ccip/ccip_integration_tests/ccipreader/ccipreader_test.go delete mode 100644 core/capabilities/ccip/ccipevm/encodingUtilsAbi.json delete mode 100644 core/capabilities/don_notifier.go delete mode 100644 core/capabilities/don_notifier_test.go delete mode 100644 core/capabilities/remote/aggregation/default_mode.go delete mode 100644 core/capabilities/remote/aggregation/default_mode_test.go rename core/capabilities/remote/{messagecache => }/message_cache.go (81%) rename core/capabilities/remote/{messagecache => }/message_cache_test.go (59%) create mode 100644 core/capabilities/targets/mocks/chain_writer.go delete mode 100644 core/capabilities/targets/mocks/contract_writer.go delete mode 100644 core/capabilities/webapi/outgoing_connector_handler_test.go delete mode 100644 core/chains/evm/config/toml/defaults/BOB_Mainnet.toml delete mode 100644 core/chains/evm/config/toml/defaults/BOB_Testnet.toml delete mode 100644 core/chains/evm/config/toml/defaults/Berachain_Testnet.toml delete mode 100644 core/chains/evm/config/toml/defaults/Bsquared_Mainnet.toml delete mode 100644 core/chains/evm/config/toml/defaults/Bsquared_Testnet.toml delete mode 100644 core/chains/evm/config/toml/defaults/Ronin_Mainnet.toml delete mode 100644 core/chains/evm/config/toml/defaults/Ronin_Saigon.toml delete mode 100644 core/chains/evm/config/toml/defaults/Unichain_Testnet.toml delete mode 100644 core/chains/evm/config/toml/defaults/Worldchain_Mainnet.toml delete mode 100644 core/chains/evm/config/toml/defaults/Worldchain_Testnet.toml delete mode 100644 core/cmd/chains_commands_test.go create mode 100644 core/cmd/cosmos_chains_commands.go create mode 100644 core/cmd/cosmos_chains_commands_test.go create mode 100644 core/cmd/cosmos_node_commands.go create mode 100644 core/cmd/cosmos_node_commands_test.go create mode 100644 core/cmd/evm_chains_commands.go create mode 100644 core/cmd/evm_chains_commands_test.go create mode 100644 core/cmd/evm_node_commands.go create mode 100644 core/cmd/evm_node_commands_test.go delete mode 100644 core/cmd/node_commands_test.go create mode 100644 core/cmd/solana_chains_commands.go create mode 100644 core/cmd/solana_chains_commands_test.go create mode 100644 core/cmd/solana_node_commands.go create mode 100644 core/cmd/solana_node_commands_test.go create mode 100644 core/cmd/starknet_chains_commands.go create mode 100644 core/cmd/starknet_node_commands.go create mode 100644 core/cmd/starknet_node_commands_test.go create mode 100644 core/gethwrappers/ccip/generated/ccip_config/ccip_config.go delete mode 100644 core/gethwrappers/keystone/generated/capabilities_registry_1_1_0/capabilities_registry.go delete mode 100644 core/gethwrappers/keystone/generated/feeds_consumer_1_0_0/feeds_consumer.go delete mode 100644 core/gethwrappers/keystone/generated/forwarder_1_0_0/forwarder.go delete mode 100644 core/gethwrappers/keystone/generated/ocr3_capability_1_0_0/ocr3_capability.go delete mode 100644 core/gethwrappers/shared/generated/burn_mint_erc20/burn_mint_erc20.go delete mode 100644 core/gethwrappers/shared/generated/multicall3/multicall3.go create mode 100644 core/gethwrappers/transmission/generated/entry_point/entry_point.go create mode 100644 core/gethwrappers/transmission/generated/greeter_wrapper/greeter_wrapper.go create mode 100644 core/gethwrappers/transmission/generated/paymaster_wrapper/paymaster_wrapper.go create mode 100644 core/gethwrappers/transmission/generated/sca_wrapper/sca_wrapper.go create mode 100644 core/gethwrappers/transmission/generated/smart_contract_account_factory/smart_contract_account_factory.go create mode 100644 core/gethwrappers/transmission/generated/smart_contract_account_helper/smart_contract_account_helper.go create mode 100644 core/gethwrappers/transmission/generation/generated-wrapper-dependency-versions-do-not-edit.txt create mode 100644 core/gethwrappers/transmission/go_generate.go delete mode 100644 core/internal/features/ocr2/features_ocr2_helper.go create mode 100644 core/internal/features/ocr2/features_ocr2_plugin_test.go delete mode 100644 core/internal/features/ocr2/plugins/features_ocr2_plugin_test.go delete mode 100644 core/internal/features/ocr2/plugins/plugins.go create mode 100644 core/internal/testutils/pgtest/txdb.go create mode 100644 core/services/keystore/keys/keystest/keystest.go create mode 100644 core/services/keystore/keys/ocrkey/key_bundle.go create mode 100644 core/services/keystore/keys/ocrkey/key_bundle_test.go delete mode 100644 core/services/keystore/keys/ocrkey/key_v2_test.go rename core/services/keystore/keys/ocrkey/{off_chain_private_key_test.go => off_chan_private_key_test.go} (77%) delete mode 100644 core/services/keystore/mocks/workflow.go delete mode 100644 core/services/llo/channel_definition_cache_factory_test.go create mode 100644 core/services/llo/evm/report_codec.go delete mode 100644 core/services/llo/suppressed_logger.go create mode 100644 core/services/ocr2/plugins/ccip/integration_legacy_test.go create mode 100644 core/services/ocr2/plugins/ccip/testhelpers/testhelpers_1_4_0/ccip_contracts_1_4_0.go create mode 100644 core/services/ocr2/plugins/ccip/testhelpers/testhelpers_1_4_0/chainlink.go create mode 100644 core/services/ocr2/plugins/ccip/testhelpers/testhelpers_1_4_0/config_1_4_0.go delete mode 100644 core/services/ocr3/promwrapper/factory.go delete mode 100644 core/services/ocr3/promwrapper/factory_test.go delete mode 100644 core/services/ocr3/promwrapper/plugin.go delete mode 100644 core/services/ocr3/promwrapper/plugin_test.go delete mode 100644 core/services/ocr3/promwrapper/types.go delete mode 100644 core/services/relay/evm/capabilities/workflows/syncer/workflow_syncer_test.go delete mode 100644 core/services/relay/evm/read/multieventtype.go delete mode 100644 core/services/relay/evm/read/multieventtype_test.go create mode 100644 core/services/transmission/integration_test.go create mode 100644 core/services/transmission/signature.go delete mode 100644 core/services/workflows/syncer/engine_registry.go delete mode 100644 core/services/workflows/syncer/fetcher.go delete mode 100644 core/services/workflows/syncer/fetcher_test.go delete mode 100644 core/services/workflows/syncer/handler.go delete mode 100644 core/services/workflows/syncer/handler_test.go delete mode 100644 core/services/workflows/syncer/mocks/orm.go delete mode 100644 core/services/workflows/syncer/orm.go delete mode 100644 core/services/workflows/syncer/orm_test.go create mode 100644 core/store/dialects/dialects.go delete mode 100644 core/store/migrate/migrations/0259_add_workflow_secrets.sql delete mode 100644 core/store/migrate/migrations/0260_add_status_workflow_spec.sql delete mode 100644 core/store/migrate/migrations/0261_remove_unique_constraint_secrets.sql delete mode 100644 core/store/migrate/migrations/0262_add_solana_schema.sql delete mode 100644 core/utils/crypto/keccak_256.go delete mode 100644 core/utils/matches/matches.go rename core/web/assets/{main.008c37495ba29761321d.js => main.57f94389bc8271642420.js} (90%) rename core/web/assets/{main.008c37495ba29761321d.js.gz => main.57f94389bc8271642420.js.gz} (86%) delete mode 100644 core/web/chains_controller_test.go create mode 100644 core/web/cosmos_chains_controller.go create mode 100644 core/web/cosmos_chains_controller_test.go create mode 100644 core/web/cosmos_nodes_controller.go create mode 100644 core/web/evm_chains_controller.go create mode 100644 core/web/evm_chains_controller_test.go create mode 100644 core/web/evm_nodes_controller.go create mode 100644 core/web/presenters/cosmos_chain.go create mode 100644 core/web/presenters/evm_chain.go create mode 100644 core/web/presenters/solana_chain.go create mode 100644 core/web/presenters/starknet_chain.go create mode 100644 core/web/solana_chains_controller.go create mode 100644 core/web/solana_chains_controller_test.go create mode 100644 core/web/solana_nodes_controller.go create mode 100644 core/web/starknet_chains_controller.go create mode 100644 core/web/starknet_nodes_controller.go delete mode 100644 deployment/.mockery.yaml create mode 100644 deployment/ccip/active_candidate.go create mode 100644 deployment/ccip/add_lane.go create mode 100644 deployment/ccip/add_lane_test.go delete mode 100644 deployment/ccip/changeset/accept_ownership_test.go create mode 100644 deployment/ccip/changeset/active_candidate.go create mode 100644 deployment/ccip/changeset/active_candidate_test.go create mode 100644 deployment/ccip/changeset/add_chain.go create mode 100644 deployment/ccip/changeset/add_chain_test.go delete mode 100644 deployment/ccip/changeset/cs_add_lane_test.go delete mode 100644 deployment/ccip/changeset/cs_ccip_home.go delete mode 100644 deployment/ccip/changeset/cs_ccip_home_test.go delete mode 100644 deployment/ccip/changeset/cs_chain_contracts.go delete mode 100644 deployment/ccip/changeset/cs_chain_contracts_test.go delete mode 100644 deployment/ccip/changeset/cs_deploy_chain.go delete mode 100644 deployment/ccip/changeset/cs_deploy_chain_test.go delete mode 100644 deployment/ccip/changeset/cs_home_chain.go delete mode 100644 deployment/ccip/changeset/cs_home_chain_test.go delete mode 100644 deployment/ccip/changeset/cs_jobspec_test.go delete mode 100644 deployment/ccip/changeset/cs_prerequisites.go delete mode 100644 deployment/ccip/changeset/cs_update_rmn_config.go delete mode 100644 deployment/ccip/changeset/cs_update_rmn_config_test.go create mode 100644 deployment/ccip/changeset/home_chain.go create mode 100644 deployment/ccip/changeset/home_chain_test.go create mode 100644 deployment/ccip/changeset/initial_deploy.go create mode 100644 deployment/ccip/changeset/initial_deploy_test.go delete mode 100644 deployment/ccip/changeset/internal/deploy_home_chain.go create mode 100644 deployment/ccip/changeset/prerequisites.go rename deployment/ccip/changeset/{cs_prerequisites_test.go => prerequisites_test.go} (81%) rename deployment/{common => ccip}/changeset/save_existing.go (88%) delete mode 100644 deployment/ccip/changeset/solana_state.go delete mode 100644 deployment/ccip/changeset/state_test.go delete mode 100644 deployment/ccip/changeset/test_environment.go delete mode 100644 deployment/ccip/changeset/test_helpers.go delete mode 100644 deployment/ccip/changeset/v1_5/cs_jobspec.go delete mode 100644 deployment/ccip/changeset/v1_5/cs_lane_contracts.go delete mode 100644 deployment/ccip/changeset/v1_5/cs_ocr2_config.go delete mode 100644 deployment/ccip/changeset/v1_5/e2e_test.go delete mode 100644 deployment/ccip/changeset/v1_5/test_helpers.go delete mode 100644 deployment/ccip/changeset/view_test.go create mode 100644 deployment/ccip/consts.go create mode 100644 deployment/ccip/deploy.go create mode 100644 deployment/ccip/deploy_home_chain.go create mode 100644 deployment/ccip/deploy_test.go rename deployment/ccip/{changeset/cs_jobspec.go => jobs.go} (60%) create mode 100644 deployment/ccip/ownership.go create mode 100644 deployment/ccip/propose.go rename deployment/ccip/{changeset => }/state.go (51%) rename deployment/ccip/{changeset => }/test_assertions.go (57%) create mode 100644 deployment/ccip/test_helpers.go rename deployment/ccip/{changeset => }/test_params.go (92%) rename deployment/ccip/{changeset => }/test_usdc_helpers.go (66%) rename deployment/ccip/{changeset => }/token_info.go (88%) create mode 100644 deployment/ccip/view/types/contract_state.go delete mode 100644 deployment/ccip/view/v1_2/price_registry.go delete mode 100644 deployment/ccip/view/v1_2/price_registry_test.go delete mode 100644 deployment/ccip/view/v1_5/offramp.go delete mode 100644 deployment/ccip/view/v1_5/offramp_test.go delete mode 100644 deployment/ccip/view/v1_5/onramp.go delete mode 100644 deployment/ccip/view/v1_5/onramp_test.go delete mode 100644 deployment/ccip/view/v1_5/rmn.go delete mode 100644 deployment/ccip/view/v1_5/rmn_test.go create mode 100644 deployment/ccip/view/v1_6/capreg.go delete mode 100644 deployment/ccip/view/v1_6/ccip_home.go delete mode 100644 deployment/ccip/view/v1_6/ccip_home_test.go delete mode 100644 deployment/ccip/view/v1_6/rmnhome.go delete mode 100644 deployment/common/changeset/deploy_link_token.go delete mode 100644 deployment/common/changeset/deploy_link_token_test.go delete mode 100644 deployment/common/changeset/deploy_mcms_with_timelock.go delete mode 100644 deployment/common/changeset/example/add_mint_burners_link.go delete mode 100644 deployment/common/changeset/example/add_mint_burners_link_test.go delete mode 100644 deployment/common/changeset/example/link_transfer.go delete mode 100644 deployment/common/changeset/example/link_transfer_test.go delete mode 100644 deployment/common/changeset/example/mint_link.go delete mode 100644 deployment/common/changeset/example/mint_link_test.go delete mode 100644 deployment/common/changeset/internal/mcms.go delete mode 100644 deployment/common/changeset/internal/mcms_test.go delete mode 100644 deployment/common/changeset/save_existing_test.go delete mode 100644 deployment/common/changeset/set_config_mcms.go delete mode 100644 deployment/common/changeset/set_config_mcms_test.go delete mode 100644 deployment/common/changeset/state.go delete mode 100644 deployment/common/changeset/test_helpers.go delete mode 100644 deployment/common/changeset/transfer_to_mcms_with_timelock.go delete mode 100644 deployment/common/changeset/transfer_to_mcms_with_timelock_test.go delete mode 100644 deployment/common/proposalutils/mcms_helpers.go delete mode 100644 deployment/common/proposalutils/mcms_test_helpers.go delete mode 100644 deployment/common/proposalutils/propose.go delete mode 100644 deployment/common/types/types.go delete mode 100644 deployment/common/view/v1_0/link_token.go delete mode 100644 deployment/common/view/v1_0/link_token_test.go delete mode 100644 deployment/common/view/v1_0/mcms.go delete mode 100644 deployment/common/view/v1_0/static_link_token.go delete mode 100644 deployment/common/view/v1_0/static_link_token_test.go create mode 100644 deployment/environment/clo/don_nodeset.go create mode 100644 deployment/environment/clo/don_nodeset_test.go create mode 100644 deployment/environment/clo/models/models.go create mode 100644 deployment/environment/clo/models/models_gen.go create mode 100644 deployment/environment/clo/offchain_client_impl.go create mode 100644 deployment/environment/clo/offchain_client_impl_test.go create mode 100644 deployment/environment/clo/testdata/keystone_nops.json create mode 100644 deployment/environment/clo/utils.go create mode 100644 deployment/environment/clo/utils_test.go delete mode 100644 deployment/environment/crib/ccip_deployer.go delete mode 100644 deployment/environment/crib/data.go delete mode 100644 deployment/environment/crib/env.go delete mode 100644 deployment/environment/crib/env_test.go delete mode 100644 deployment/environment/crib/testdata/lanes-deployed-state/ccip-v2-scripts-address-book.json delete mode 100644 deployment/environment/crib/testdata/lanes-deployed-state/ccip-v2-scripts-chains-details.json delete mode 100644 deployment/environment/crib/testdata/lanes-deployed-state/ccip-v2-scripts-nodes-details.json delete mode 100644 deployment/environment/crib/types.go delete mode 100644 deployment/environment_test.go rename deployment/keystone/{changeset/internal => }/capability_definitions.go (93%) create mode 100644 deployment/keystone/capability_management.go rename deployment/keystone/{changeset/internal => }/capability_registry_deployer.go (90%) delete mode 100644 deployment/keystone/changeset/accept_ownership.go delete mode 100644 deployment/keystone/changeset/accept_ownership_test.go delete mode 100644 deployment/keystone/changeset/addrbook_utils.go delete mode 100644 deployment/keystone/changeset/append_node_capabilities_test.go rename deployment/keystone/changeset/{append_node_capabilities.go => append_node_capbilities.go} (55%) delete mode 100644 deployment/keystone/changeset/compatiblity.go delete mode 100644 deployment/keystone/changeset/deploy_consumer.go delete mode 100644 deployment/keystone/changeset/deploy_consumer_test.go delete mode 100644 deployment/keystone/changeset/internal/capability_management.go delete mode 100644 deployment/keystone/changeset/internal/consumer_deployer.go delete mode 100644 deployment/keystone/changeset/internal/contract_set.go delete mode 100644 deployment/keystone/changeset/internal/forwarder_deployer.go delete mode 100644 deployment/keystone/changeset/internal/ocr3config_test.go delete mode 100644 deployment/keystone/changeset/internal/testdata/testnet_wf_view.json delete mode 100644 deployment/keystone/changeset/internal/types.go delete mode 100644 deployment/keystone/changeset/internal/types_test.go delete mode 100644 deployment/keystone/changeset/test/helpers.go delete mode 100644 deployment/keystone/changeset/test/helpers_test.go create mode 100644 deployment/keystone/changeset/types.go delete mode 100644 deployment/keystone/changeset/update_don_test.go delete mode 100644 deployment/keystone/changeset/update_node_capabilities_test.go delete mode 100644 deployment/keystone/changeset/update_nodes_test.go delete mode 100644 deployment/keystone/changeset/workflowregistry/deploy.go delete mode 100644 deployment/keystone/changeset/workflowregistry/deploy_test.go delete mode 100644 deployment/keystone/changeset/workflowregistry/setup_test.go delete mode 100644 deployment/keystone/changeset/workflowregistry/strategies.go delete mode 100644 deployment/keystone/changeset/workflowregistry/update_allowed_dons.go delete mode 100644 deployment/keystone/changeset/workflowregistry/update_allowed_dons_test.go delete mode 100644 deployment/keystone/changeset/workflowregistry/update_authorized_addresses.go delete mode 100644 deployment/keystone/changeset/workflowregistry/update_authorized_addresses_test.go delete mode 100644 deployment/keystone/changeset/workflowregistry/workflow_registry_deployer.go create mode 100644 deployment/keystone/contract_set.go rename deployment/keystone/{changeset/internal => }/deploy.go (53%) create mode 100644 deployment/keystone/deploy_test.go delete mode 100644 deployment/keystone/deprecated.go create mode 100644 deployment/keystone/forwarder_deployer.go rename deployment/keystone/{changeset/internal => }/ocr3_deployer.go (82%) rename deployment/keystone/{changeset/internal => }/ocr3config.go (57%) rename deployment/keystone/{changeset/internal => }/state.go (64%) delete mode 100644 deployment/keystone/test/changeset/capability_registry.go delete mode 100644 deployment/keystone/test/changeset/capability_registry_test.go delete mode 100644 deployment/keystone/test/changeset/testdata/capability_registry_view.json create mode 100644 deployment/keystone/testdata/asset_nodes.json create mode 100644 deployment/keystone/testdata/chain_writer_nodes.json create mode 100644 deployment/keystone/testdata/ocr3config.json create mode 100644 deployment/keystone/testdata/workflow_nodes.json create mode 100644 deployment/keystone/types.go create mode 100644 deployment/keystone/types_test.go delete mode 100644 deployment/mocks/offchain_client_mock.go delete mode 100644 deployment/solana_chain.go delete mode 100644 integration-tests/actions/ccip_helpers.go create mode 100644 integration-tests/ccip-tests/testconfig/tomls/contract-version1.4.toml rename integration-tests/{testsetups/ccip => ccip-tests/testsetups}/test_helpers.go (53%) delete mode 100644 integration-tests/contracts/ccipreader_test.go delete mode 100644 integration-tests/smoke/ccip/ccip_batching_test.go delete mode 100644 integration-tests/smoke/ccip/ccip_fee_boosting_test.go delete mode 100644 integration-tests/smoke/ccip/ccip_fees_test.go delete mode 100644 integration-tests/smoke/ccip/ccip_gas_price_updates_test.go delete mode 100644 integration-tests/smoke/ccip/ccip_legacy_test.go delete mode 100644 integration-tests/smoke/ccip/ccip_message_limitations_test.go delete mode 100644 integration-tests/smoke/ccip/ccip_ooo_execution_test.go delete mode 100644 integration-tests/smoke/ccip/ccip_rmn_test.go delete mode 100644 integration-tests/smoke/ccip/ccip_token_price_updates_test.go delete mode 100644 integration-tests/smoke/ccip/ccip_token_transfer_test.go delete mode 100644 integration-tests/smoke/ccip/ccip_usdc_test.go rename integration-tests/smoke/{ccip => }/ccip_messaging_test.go (74%) create mode 100644 integration-tests/smoke/ccip_rmn_test.go create mode 100644 integration-tests/smoke/ccip_test.go create mode 100644 integration-tests/smoke/ccip_usdc_test.go create mode 100644 integration-tests/smoke/fee_boosting_test.go delete mode 100644 integration-tests/utils/pgtest/pgtest.go delete mode 100644 testdata/scripts/nodes/cosmos/list/list.txtar delete mode 100644 testdata/scripts/nodes/evm/list/list.txtar delete mode 100644 testdata/scripts/nodes/solana/list/list.txtar delete mode 100644 testdata/scripts/nodes/starknet/list/list.txtar delete mode 100755 tools/bin/go_core_scripts_tests delete mode 100644 tools/gomod-local-update/README.md delete mode 100644 tools/gomod-local-update/cmd/gomod-local-update/main.go delete mode 100644 tools/gomod-local-update/internal/updater/config.go delete mode 100644 tools/gomod-local-update/internal/updater/config_test.go delete mode 100644 tools/gomod-local-update/internal/updater/errors.go delete mode 100644 tools/gomod-local-update/internal/updater/system_operator.go delete mode 100644 tools/gomod-local-update/internal/updater/updater.go delete mode 100644 tools/gomod-local-update/internal/updater/updater_test.go diff --git a/.changeset/afraid-houses-learn.md b/.changeset/afraid-houses-learn.md deleted file mode 100644 index 3d161965bae..00000000000 --- a/.changeset/afraid-houses-learn.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -#updated use real contracts in ccipreader_tests where possible diff --git a/.changeset/beige-geckos-explode.md b/.changeset/beige-geckos-explode.md deleted file mode 100644 index 9f06a9c989b..00000000000 --- a/.changeset/beige-geckos-explode.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": minor ---- - -#updated Gracefully fail if CL_DATABASE_URL is not set. diff --git a/.changeset/big-camels-report.md b/.changeset/big-camels-report.md deleted file mode 100644 index f81f66b9138..00000000000 --- a/.changeset/big-camels-report.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -#bugfix fix non-idempotent loopp registry.Register diff --git a/.changeset/brave-cooks-itch.md b/.changeset/brave-cooks-itch.md deleted file mode 100644 index 1ed3dd7e117..00000000000 --- a/.changeset/brave-cooks-itch.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": minor ---- - -#updated feat(job-distributor): support tron chain type on sync diff --git a/.changeset/breezy-kings-clean.md b/.changeset/breezy-kings-clean.md deleted file mode 100644 index b72a0689019..00000000000 --- a/.changeset/breezy-kings-clean.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -Potential bug introduced from chain selector refactor, not causing issue now since only EVM is used, but need to fix #bugfix diff --git a/.changeset/bright-keys-whisper.md b/.changeset/bright-keys-whisper.md deleted file mode 100644 index 16bf56b2ac9..00000000000 --- a/.changeset/bright-keys-whisper.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -allow different decimals on different chains for token pools diff --git a/.changeset/chilled-papayas-swim.md b/.changeset/chilled-papayas-swim.md deleted file mode 100644 index e2f2b536514..00000000000 --- a/.changeset/chilled-papayas-swim.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": minor ---- - -#removed Remove duplicated testing util for p2p_key only. diff --git a/.changeset/chilled-suits-do.md b/.changeset/chilled-suits-do.md deleted file mode 100644 index 611fe95d159..00000000000 --- a/.changeset/chilled-suits-do.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -Updated the Solana TXM compute unit limit estimation feature to use the max 1.4M compute unit limit for simulation and enable SigVerify #updated diff --git a/.changeset/chilly-stingrays-press.md b/.changeset/chilly-stingrays-press.md deleted file mode 100644 index 1fe2e80f2b0..00000000000 --- a/.changeset/chilly-stingrays-press.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -Removing ccip-tests/\* dependencies and moving ccip tests under a directory in smoke diff --git a/.changeset/clean-files-beg.md b/.changeset/clean-files-beg.md deleted file mode 100644 index 1357a044cb0..00000000000 --- a/.changeset/clean-files-beg.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -Adding OCR3 promwrapper to LLO #internal diff --git a/.changeset/cool-penguins-raise.md b/.changeset/cool-penguins-raise.md deleted file mode 100644 index c47839be310..00000000000 --- a/.changeset/cool-penguins-raise.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": minor ---- - -#updated Remove custom ed25519 private to public key conversion. diff --git a/.changeset/dull-readers-rush.md b/.changeset/dull-readers-rush.md deleted file mode 100644 index 3b6f2ae8758..00000000000 --- a/.changeset/dull-readers-rush.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -Reporting number of OCR3 instances running using promwrapper #internal diff --git a/.changeset/eight-tigers-march.md b/.changeset/eight-tigers-march.md deleted file mode 100644 index 611628f2ef6..00000000000 --- a/.changeset/eight-tigers-march.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -#added Adding 5 chains (B^2, BoB, Berachain, Unichain, Worldchain configs) diff --git a/.changeset/eighty-geckos-switch.md b/.changeset/eighty-geckos-switch.md deleted file mode 100644 index b67dfb0ec79..00000000000 --- a/.changeset/eighty-geckos-switch.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -Reduce PriceMin on Avalanche to 1 gwei #nops diff --git a/.changeset/five-gifts-end.md b/.changeset/five-gifts-end.md deleted file mode 100644 index dd13fda476d..00000000000 --- a/.changeset/five-gifts-end.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -#added stream job delete capability diff --git a/.changeset/forty-foxes-rescue.md b/.changeset/forty-foxes-rescue.md deleted file mode 100644 index 9456ebe5e36..00000000000 --- a/.changeset/forty-foxes-rescue.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": minor ---- - -#removed Remove unused ocr1 key files. diff --git a/.changeset/fuzzy-hairs-appear.md b/.changeset/fuzzy-hairs-appear.md deleted file mode 100644 index a4797462546..00000000000 --- a/.changeset/fuzzy-hairs-appear.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -Prometheus observability layer added to OCR3 Reporting Plugins #internal diff --git a/.changeset/fuzzy-yaks-deny.md b/.changeset/fuzzy-yaks-deny.md deleted file mode 100644 index 6de0c8d096c..00000000000 --- a/.changeset/fuzzy-yaks-deny.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -#added Lens Sepolia config diff --git a/.changeset/giant-eels-jump.md b/.changeset/giant-eels-jump.md deleted file mode 100644 index 5ab8ca875ca..00000000000 --- a/.changeset/giant-eels-jump.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -Add error handling for Arbitrum RPC server timeouts. #added diff --git a/.changeset/great-peaches-walk.md b/.changeset/great-peaches-walk.md deleted file mode 100644 index 30e7446bb0c..00000000000 --- a/.changeset/great-peaches-walk.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -fix reported evm node states diff --git a/.changeset/hot-islands-dress.md b/.changeset/hot-islands-dress.md deleted file mode 100644 index 82e34ecf42b..00000000000 --- a/.changeset/hot-islands-dress.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -#internal refactor: inject ocr secrets via env instead of config diff --git a/.changeset/kind-parents-jump.md b/.changeset/kind-parents-jump.md deleted file mode 100644 index e633f1af1fe..00000000000 --- a/.changeset/kind-parents-jump.md +++ /dev/null @@ -1,11 +0,0 @@ ---- -"chainlink": patch ---- - -Add two new metrics for monitoring LLO transmitter health #added - -`llo_mercurytransmitter_concurrent_transmit_gauge` -Gauge that measures the number of transmit threads currently waiting on a remote transmit call. You may wish to alert if this exceeds some number for a given period of time, or if it ever reaches its max. - -`llo_mercurytransmitter_concurrent_delete_gauge` -Gauge that measures the number of delete threads currently waiting on a delete call to the DB. You may wish to alert if this exceeds some number for a given period of time, or if it ever reaches its max. diff --git a/.changeset/large-fishes-enjoy.md b/.changeset/large-fishes-enjoy.md deleted file mode 100644 index 201267e8b64..00000000000 --- a/.changeset/large-fishes-enjoy.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": minor ---- - -Fix logic for mapping affected files in CI that affects golangci-lint execution diff --git a/.changeset/late-doors-battle.md b/.changeset/late-doors-battle.md deleted file mode 100644 index 8ec64b9048e..00000000000 --- a/.changeset/late-doors-battle.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -Fix TransactionSender go routine leak. #bugfix diff --git a/.changeset/late-seals-battle.md b/.changeset/late-seals-battle.md deleted file mode 100644 index 194aa4f380e..00000000000 --- a/.changeset/late-seals-battle.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": minor ---- - -Update deployment address book to support non-evm chains diff --git a/.changeset/late-windows-clean.md b/.changeset/late-windows-clean.md deleted file mode 100644 index 261747efa6c..00000000000 --- a/.changeset/late-windows-clean.md +++ /dev/null @@ -1,11 +0,0 @@ ---- -"chainlink": minor ---- - -#internal Updated the TXM confirmation logic to use the mined transaction count to identify re-org'd or confirmed transactions. - -- Confirmer uses the mined transaction count to determine if transactions have been re-org'd or confirmed. -- Confirmer no longer sets transaction states to `confirmed_missing_receipt`. This state is maintained in queries for backwards compatibility. -- Finalizer now responsible for fetching and storing receipts for confirmed transactions. -- Finalizer now responsible for resuming pending task runs. -- Finalizer now responsible for marking old transactions without receipts broadcasted before the finalized head as fatal. diff --git a/.changeset/light-trains-chew.md b/.changeset/light-trains-chew.md deleted file mode 100644 index edbb5a7f7bc..00000000000 --- a/.changeset/light-trains-chew.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": minor ---- - -Refactor chain ID logic in plugin to be chain agnostic #added diff --git a/.changeset/many-crews-wave.md b/.changeset/many-crews-wave.md deleted file mode 100644 index 328a00e2f48..00000000000 --- a/.changeset/many-crews-wave.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -#internal refactor update nodes changeset to support mcms diff --git a/.changeset/mean-dots-move.md b/.changeset/mean-dots-move.md deleted file mode 100644 index 1169d8379e9..00000000000 --- a/.changeset/mean-dots-move.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -Add config var Mercury.Transmitter.TransmitConcurrency #added diff --git a/.changeset/mean-knives-knock.md b/.changeset/mean-knives-knock.md deleted file mode 100644 index e04ba4d083f..00000000000 --- a/.changeset/mean-knives-knock.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": minor ---- - -#updated chainconfig: show chain type next to key bundle id in UI diff --git a/.changeset/mean-ravens-stare.md b/.changeset/mean-ravens-stare.md deleted file mode 100644 index 6b481ae4520..00000000000 --- a/.changeset/mean-ravens-stare.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -#internal add versioned geth wrappers for keystone prod contracts diff --git a/.changeset/metal-houses-approve.md b/.changeset/metal-houses-approve.md deleted file mode 100644 index 6768c50767e..00000000000 --- a/.changeset/metal-houses-approve.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": minor ---- - -Added TxExpirationRebroadcast feature and config for Solana TXM. #added diff --git a/.changeset/popular-rules-live.md b/.changeset/popular-rules-live.md deleted file mode 100644 index 2d996a28dc2..00000000000 --- a/.changeset/popular-rules-live.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -Fixes a race condition with the Finalizer when clearing txs #bugfix diff --git a/.changeset/shaggy-carpets-deliver.md b/.changeset/shaggy-carpets-deliver.md deleted file mode 100644 index 676ad2fb861..00000000000 --- a/.changeset/shaggy-carpets-deliver.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": minor ---- - -#removed dead transmission tests diff --git a/.changeset/shiny-owls-destroy.md b/.changeset/shiny-owls-destroy.md deleted file mode 100644 index d132d6dbff8..00000000000 --- a/.changeset/shiny-owls-destroy.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -"chainlink": patch ---- - -Logging improvements for LLO -#internal diff --git a/.changeset/silver-avocados-buy.md b/.changeset/silver-avocados-buy.md deleted file mode 100644 index 6b636ee267d..00000000000 --- a/.changeset/silver-avocados-buy.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -Update MultiNode with latest changes and bug fixes. Fixes an issue that caused nodes to go OutOfSync incorrectly, and also fixed context handling for sending transactions. #internal #bugfix diff --git a/.changeset/six-coins-mix.md b/.changeset/six-coins-mix.md deleted file mode 100644 index 2877aa3012a..00000000000 --- a/.changeset/six-coins-mix.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -#bugfix fix: duplicate chain id in chain config dialog diff --git a/.changeset/sixty-queens-wait.md b/.changeset/sixty-queens-wait.md deleted file mode 100644 index cd9fc9ea65c..00000000000 --- a/.changeset/sixty-queens-wait.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": minor ---- - -#updated chain config: allow chain id and account address to be manually provided when no selections are available diff --git a/.changeset/sour-hairs-cross.md b/.changeset/sour-hairs-cross.md deleted file mode 100644 index fa12a38b5be..00000000000 --- a/.changeset/sour-hairs-cross.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -#internal depreciate keystone deployment library diff --git a/.changeset/spotty-knives-smile.md b/.changeset/spotty-knives-smile.md deleted file mode 100644 index 8389b72414c..00000000000 --- a/.changeset/spotty-knives-smile.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -Increase GasLimit for Automation on ZKsync to 6M #nops diff --git a/.changeset/spotty-seals-give.md b/.changeset/spotty-seals-give.md deleted file mode 100644 index 1e3874a783f..00000000000 --- a/.changeset/spotty-seals-give.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -Switching CCIP to observed ChainReader for HomeChainReader #internal diff --git a/.changeset/thin-cats-try.md b/.changeset/thin-cats-try.md deleted file mode 100644 index e7934fe279a..00000000000 --- a/.changeset/thin-cats-try.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": minor ---- - -Add support for Mercury LLO streams to feeds service. #added diff --git a/.changeset/three-mayflies-learn.md b/.changeset/three-mayflies-learn.md deleted file mode 100644 index 1ea4fad3924..00000000000 --- a/.changeset/three-mayflies-learn.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": minor ---- - -#updated Update few incorrect occurences of the password for notreal@fakeemail.ch. diff --git a/.changeset/tiny-kangaroos-switch.md b/.changeset/tiny-kangaroos-switch.md deleted file mode 100644 index 000f5b6bde5..00000000000 --- a/.changeset/tiny-kangaroos-switch.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -Added new fatal error cases for transactions to the Solana TXM. #added diff --git a/.changeset/tricky-clouds-move.md b/.changeset/tricky-clouds-move.md deleted file mode 100644 index 8cb50dbb048..00000000000 --- a/.changeset/tricky-clouds-move.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -Updated Solana TXM to store prebroadcast transaction errors caught upfront by simulation. Refactored error parsing to more easily introduce new error cases. Optimized storing finalized and errored transaction to minimize memory usage. #updated diff --git a/.changeset/wet-bags-clean.md b/.changeset/wet-bags-clean.md deleted file mode 100644 index 53da05426c9..00000000000 --- a/.changeset/wet-bags-clean.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": minor ---- - -Change ChainWriter naming to ContractWriter to consolidate Relayer chain interfaces #internal diff --git a/.changeset/wild-cats-think.md b/.changeset/wild-cats-think.md deleted file mode 100644 index f56f41b242c..00000000000 --- a/.changeset/wild-cats-think.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": minor ---- - -Added the `EVM.Transactions.Enabled` config to enable or disable the transaction manager. #added diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 9f19d52b7ea..210709443be 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -13,7 +13,7 @@ # Services /core/services/directrequest @smartcontractkit/foundations -/core/services/feeds @smartcontractkit/deployment-automation @eutopian @smartcontractkit/core +/core/services/feeds @smartcontractkit/deployment-automation @eutopian @yevshev @smartcontractkit/core /core/services/synchronization/telem @smartcontractkit/realtime @smartcontractkit/core /core/capabilities/ @smartcontractkit/keystone @smartcontractkit/capabilities-team /core/capabilities/ccip @smartcontractkit/ccip-offchain @@ -133,15 +133,16 @@ core/scripts/gateway @smartcontractkit/dev-services # Tests /integration-tests/ @smartcontractkit/test-tooling-team @smartcontractkit/core -/integration-tests/ccip-tests @smartcontractkit/ccip-offchain @smartcontractkit/core @smartcontractkit/ccip +/integration-tests/ccip-tests @smartcontractkit/ccip-offchain @smartcontractkit/core /integration-tests/**/*keeper* @smartcontractkit/dev-services @smartcontractkit/core /integration-tests/**/*automation* @smartcontractkit/dev-services @smartcontractkit/core -/integration-tests/**/*ccip* @smartcontractkit/ccip-offchain @smartcontractkit/core @smartcontractkit/ccip +/integration-tests/**/*ccip* @smartcontractkit/ccip-offchain @smartcontractkit/core # Deployment tooling -/deployment @smartcontractkit/ccip @smartcontractkit/keystone @smartcontractkit/core @smartcontractkit/deployment-automation -/deployment/ccip @smartcontractkit/ccip @smartcontractkit/core @smartcontractkit/deployment-automation -/deployment/keystone @smartcontractkit/keystone @smartcontractkit/core @smartcontractkit/deployment-automation +# Initially the common structures owned by CCIP +/deployment @smartcontractkit/ccip @smartcontractkit/keystone @smartcontractkit/core +/deployment/ccip @smartcontractkit/ccip @smartcontractkit/core +/deployment/keystone @smartcontractkit/keystone @smartcontractkit/core # TODO: As more products add their deployment logic here, add the team as an owner # CI/CD diff --git a/.github/actions/golangci-lint/action.yml b/.github/actions/golangci-lint/action.yml index 22a35682c2d..20ad2689deb 100644 --- a/.github/actions/golangci-lint/action.yml +++ b/.github/actions/golangci-lint/action.yml @@ -27,13 +27,11 @@ runs: if: github.event_name == 'merge_group' with: fetch-depth: 0 - - name: Checkout repo uses: actions/checkout@v4.2.1 if: github.event_name != 'merge_group' with: fetch-depth: 1 - - name: Setup Go uses: ./.github/actions/setup-go with: @@ -41,66 +39,38 @@ runs: cache-version: ${{ inputs.cache-version }} go-version-file: ${{ inputs.go-version-file }} go-module-file: ${{ inputs.go-module-file }} - - name: Touching core/web/assets/index.html shell: bash run: mkdir -p core/web/assets && touch core/web/assets/index.html - - - name: Set Golangci-lint working directory + - name: Build binary + working-directory: ${{ inputs.go-directory }} + shell: bash + run: go build ./... + - name: Set golangci-lint working directory shell: bash id: set-working-directory # XXX: Don't use `.` default working directory here due to issues with the golangci-lint-action. run: | if [ "${{ inputs.go-directory }}" == "." ]; then - echo "golangci-lint-working-directory=" >> $GITHUB_OUTPUT + echo "golangci-lint-working-directory=" | tee -a $GITHUB_OUTPUT else - echo "golangci-lint-working-directory=${{ inputs.go-directory }}/" >> $GITHUB_OUTPUT + echo "golangci-lint-working-directory=${{ inputs.go-directory }}" | tee -a $GITHUB_OUTPUT fi - - - name: Golangci-lint + - name: golangci-lint uses: golangci/golangci-lint-action@38e1018663fa5173f3968ea0777460d3de38f256 # v5.3.0 with: - version: v1.62.2 + version: v1.61.0 only-new-issues: true args: --out-format colored-line-number,checkstyle:golangci-lint-report.xml working-directory: ${{ steps.set-working-directory.outputs.golangci-lint-working-directory }} - - - name: Print Golangci-lint report results + - name: Print lint report artifact if: failure() shell: bash - run: cat ./${{ steps.set-working-directory.outputs.golangci-lint-working-directory }}golangci-lint-report.xml - - # Get a valid name for the upload-artifact step. - # Avoid error: `The artifact name is not valid: ///` caused by `/`. - # Remove trailing `/` from the directory name: `core/scripts/` -> `core/scripts`. - # Replace remaining `/` with `-`: `core/scripts` -> `core-scripts`. - # Assign `root` if the directory name is empty (ref: step.id: set-working-directory). - - name: Get valid suffix for artifact name - if: always() - id: suffix - shell: bash - run: | - go_directory=${{ steps.set-working-directory.outputs.golangci-lint-working-directory }} - echo "Validating if directory name '$go_directory' is empty or has slashes" - - if [[ $go_directory == *\/* ]]; then - suffix=$(echo "$go_directory" | sed 's:\/$::' | tr '/' '-') - echo "Directory name with slashes '$go_directory' updated to a valid artifact suffix '$suffix'" - elif [[ $go_directory == "" ]]; then - suffix="root" - echo "Root directory (empty string) updated to a valid artifact suffix '$suffix'" - else - suffix="$go_directory" - echo "Directory name is valid for the artifact suffix: '$suffix'" - fi - - echo "suffix=${suffix}" >> $GITHUB_OUTPUT - - - name: Store Golangci-lint report artifact + run: cat ${{ inputs.go-directory }}/golangci-lint-report.xml + - name: Store lint report artifact if: always() uses: actions/upload-artifact@v4.4.3 with: - # Use a unique suffix for each lint report artifact to avoid duplication errors - name: golangci-lint-report-${{ steps.suffix.outputs.suffix }} - # N/B: value may be empty (no slash) OR `///` (with slash tat the end) - path: ./${{ steps.set-working-directory.outputs.golangci-lint-working-directory }}golangci-lint-report.xml + name: golangci-lint-report + path: ${{ inputs.go-directory }}/golangci-lint-report.xml + retention-days: 7 diff --git a/.github/actions/goreleaser-build-sign-publish/action.yml b/.github/actions/goreleaser-build-sign-publish/action.yml index e2472f7eaa4..c57bff91488 100644 --- a/.github/actions/goreleaser-build-sign-publish/action.yml +++ b/.github/actions/goreleaser-build-sign-publish/action.yml @@ -26,36 +26,19 @@ inputs: description: "The goreleaser configuration yaml" default: ".goreleaser.yaml" required: false - # other inputs - enable-debug: - description: | - Enable debug information for the run (true/false). This includes - buildkit debug information, and goreleaser debug, etc. - required: false - default: "${{ runner.debug == '1' }}" - runs: using: composite steps: - # We need QEMU to test the cross architecture builds after they're built. name: Set up QEMU uses: docker/setup-qemu-action@49b3bc8e6bdd4a60e6116a5414239cba5943d3cf # v3.2.0 - - name: Setup docker buildx uses: docker/setup-buildx-action@c47758b77c9736f4b2ef4073d4d51994fabfe349 # v3.7.0 - with: - buildkitd-flags: ${{ inputs.enable-debug == 'true' && '--debug' || '' }} - # v0.16.0 until grpc fix is released - # see: https://github.com/docker/buildx/issues/2789#issuecomment-2487981922 - driver-opts: | - image=moby/buildkit:v0.16.0 - - name: Set up Go uses: ./.github/actions/setup-go with: go-version-file: 'go.mod' only-modules: 'true' - - name: Setup goreleaser uses: goreleaser/goreleaser-action@9ed2f89a662bf1735a48bc8557fd212fa902bebf # v6.1.0 with: @@ -82,7 +65,6 @@ runs: IMAGE_TAG: ${{ inputs.docker-image-tag }} GORELEASER_KEY: ${{ inputs.goreleaser-key }} GITHUB_TOKEN: ${{ github.token }} - DEBUG: ${{ inputs.enable-debug }} run: | # https://github.com/orgs/community/discussions/24950 ${GITHUB_ACTION_PATH}/release.js diff --git a/.github/actions/goreleaser-build-sign-publish/release.js b/.github/actions/goreleaser-build-sign-publish/release.js index cd0521c991e..0dbd58ca6cf 100755 --- a/.github/actions/goreleaser-build-sign-publish/release.js +++ b/.github/actions/goreleaser-build-sign-publish/release.js @@ -168,7 +168,6 @@ function extractDockerImages(artifacts) { function constructGoreleaserCommand(releaseType, version, goreleaserConfig) { const flags = []; - const debugFlag = (process.env.DEBUG == 'true') ? '--verbose' : ''; checkReleaseType(releaseType); @@ -193,9 +192,9 @@ function constructGoreleaserCommand(releaseType, version, goreleaserConfig) { const flagsStr = flags.join(" "); if (releaseType === "merge") { - return `CHAINLINK_VERSION=${version} goreleaser ${debugFlag} ${subCmd} ${flagsStr}`; + return `CHAINLINK_VERSION=${version} goreleaser ${subCmd} ${flagsStr}`; } else { - return `CHAINLINK_VERSION=${version} goreleaser ${debugFlag} ${subCmd} --config ${goreleaserConfig} ${flagsStr}`; + return `CHAINLINK_VERSION=${version} goreleaser ${subCmd} --config ${goreleaserConfig} ${flagsStr}`; } } diff --git a/.github/actions/setup-ci-core-tests/action.yml b/.github/actions/setup-ci-core-tests/action.yml deleted file mode 100644 index a2cf3f4103c..00000000000 --- a/.github/actions/setup-ci-core-tests/action.yml +++ /dev/null @@ -1,61 +0,0 @@ -name: Setup CI Core Tests -description: | - Shared setup steps for ci-core. - Note: Other actions should not be called from this action. There is - weird behavior when nesting reusable actions. -inputs: - - go-mod-download-directory: - description: | - The directory to run go mod download in. If not provided, it will not run go mod download. - required: false - default: "" - - db-url: - description: | - The expected database URL - required: true - -runs: - using: composite - steps: - - name: Touching core/web/assets/index.html - shell: bash - run: mkdir -p core/web/assets && touch core/web/assets/index.html - - - name: Download Go vendor packages - shell: bash - run: go mod download - - - name: Go Mod Download (optional) - if: ${{ inputs.go-mod-download-directory != '' }} - shell: bash - working-directory: ${{ inputs.go-mod-download-directory }} - run: go mod download - - - name: Build binary - shell: bash - run: go build -o chainlink.test . - - - name: Setup DB - shell: bash - run: ./chainlink.test local db preparetest - env: - CL_DATABASE_URL: ${{ inputs.db-url }} - - - name: Install LOOP Plugins - shell: bash - run: | - pushd $(go list -m -f "{{.Dir}}" github.com/smartcontractkit/chainlink-feeds) - go install ./cmd/chainlink-feeds - popd - pushd $(go list -m -f "{{.Dir}}" github.com/smartcontractkit/chainlink-data-streams) - go install ./mercury/cmd/chainlink-mercury - popd - pushd $(go list -m -f "{{.Dir}}" github.com/smartcontractkit/chainlink-solana) - go install ./pkg/solana/cmd/chainlink-solana - popd - pushd $(go list -m -f "{{.Dir}}" github.com/smartcontractkit/chainlink-starknet/relayer) - go install ./pkg/chainlink/cmd/chainlink-starknet - popd - diff --git a/.github/actions/setup-go/action.yml b/.github/actions/setup-go/action.yml index e1b15c2b183..b5519fbad0e 100644 --- a/.github/actions/setup-go/action.yml +++ b/.github/actions/setup-go/action.yml @@ -29,24 +29,11 @@ inputs: runs: using: composite steps: - - name: Get Go Version - shell: bash - id: go-version - run: | - version=$(sed -ne '/^toolchain /s/^toolchain go//p' ${{ inputs.go-version-file }}) - if [ -z "$version" ]; then - version=$(sed -ne '/^go /s/^go //p' ${{ inputs.go-version-file }}) - echo "Toolchain version not found in ${{ inputs.go-version-file }}, using go directive instead." - fi - echo "Go Version: $version" - echo "version=$version" >> "$GITHUB_OUTPUT" - - name: Set up Go uses: actions/setup-go@v5.0.2 with: - go-version: ${{ steps.go-version.outputs.version }} + go-version-file: ${{ inputs.go-version-file }} cache: false - check-latest: true - name: Get branch name if: ${{ inputs.only-modules == 'false' }} diff --git a/.github/actions/version-file-bump/action.yml b/.github/actions/version-file-bump/action.yml index 17bdc71a716..eb8d5c17426 100644 --- a/.github/actions/version-file-bump/action.yml +++ b/.github/actions/version-file-bump/action.yml @@ -1,5 +1,5 @@ name: version-file-bump -description: "Ensure that the package.json version field has been bumped since the last release." +description: "Ensure that the VERSION file has been bumped since the last release." inputs: github-token: description: "Github access token" diff --git a/.github/e2e-tests.yml b/.github/e2e-tests.yml index 142c7733533..912d7f01f89 100644 --- a/.github/e2e-tests.yml +++ b/.github/e2e-tests.yml @@ -10,7 +10,7 @@ runner-test-matrix: # START: OCR tests # Example of 1 runner for all tests in integration-tests/smoke/ocr_test.go - - id: smoke/ocr_test.go:* + - id: smoke/ocr_test.go:* path: integration-tests/smoke/ocr_test.go test_env_type: docker runs_on: ubuntu-latest @@ -27,7 +27,7 @@ runner-test-matrix: runs_on: ubuntu-latest test_cmd: cd integration-tests/ && go test soak/ocr_test.go -v -test.run ^TestOCRv1Soak$ -test.parallel=1 -timeout 900h -count=1 -json test_cmd_opts: 2>&1 | tee /tmp/gotest.log | gotestloghelper -ci -singlepackage -hidepassingtests=false - test_secrets_required: true + test_secrets_required: true test_env_vars: TEST_SUITE: soak @@ -60,7 +60,7 @@ runner-test-matrix: test_config_override_path: integration-tests/testconfig/ocr2/overrides/base_sepolia_quick_smoke_test.toml test_secrets_required: true test_env_vars: - TEST_SUITE: soak + TEST_SUITE: soak - id: soak/ocr_test.go:TestForwarderOCRv1Soak path: integration-tests/soak/ocr_test.go @@ -79,7 +79,7 @@ runner-test-matrix: test_secrets_required: true test_env_vars: TEST_SUITE: soak - + - id: soak/ocr_test.go:TestOCRSoak_GethReorgBelowFinality_FinalityTagDisabled path: integration-tests/soak/ocr_test.go test_env_type: k8s-remote-runner @@ -87,7 +87,7 @@ runner-test-matrix: test_cmd: cd integration-tests/ && go test soak/ocr_test.go -v -test.run TestOCRSoak_GethReorgBelowFinality_FinalityTagDisabled -test.parallel=1 -timeout 900h -count=1 -json test_secrets_required: true test_env_vars: - TEST_SUITE: soak + TEST_SUITE: soak - id: soak/ocr_test.go:TestOCRSoak_GethReorgBelowFinality_FinalityTagEnabled path: integration-tests/soak/ocr_test.go @@ -96,7 +96,7 @@ runner-test-matrix: test_cmd: cd integration-tests/ && go test soak/ocr_test.go -v -test.run ^TestOCRSoak_GethReorgBelowFinality_FinalityTagEnabled$ -test.parallel=1 -timeout 900h -count=1 -json test_secrets_required: true test_env_vars: - TEST_SUITE: soak + TEST_SUITE: soak - id: soak/ocr_test.go:TestOCRSoak_GasSpike path: integration-tests/soak/ocr_test.go @@ -105,7 +105,7 @@ runner-test-matrix: test_cmd: cd integration-tests/ && go test soak/ocr_test.go -v -test.run ^TestOCRSoak_GasSpike$ -test.parallel=1 -timeout 900h -count=1 -json test_secrets_required: true test_env_vars: - TEST_SUITE: soak + TEST_SUITE: soak - id: soak/ocr_test.go:TestOCRSoak_ChangeBlockGasLimit path: integration-tests/soak/ocr_test.go @@ -114,7 +114,7 @@ runner-test-matrix: test_cmd: cd integration-tests/ && go test soak/ocr_test.go -v -test.run ^TestOCRSoak_ChangeBlockGasLimit$ -test.parallel=1 -timeout 900h -count=1 -json test_secrets_required: true test_env_vars: - TEST_SUITE: soak + TEST_SUITE: soak - id: soak/ocr_test.go:TestOCRSoak_RPCDownForAllCLNodes path: integration-tests/soak/ocr_test.go @@ -123,7 +123,7 @@ runner-test-matrix: test_cmd: cd integration-tests/ && go test soak/ocr_test.go -v -test.run ^TestOCRSoak_RPCDownForAllCLNodes$ -test.parallel=1 -timeout 900h -count=1 -json test_secrets_required: true test_env_vars: - TEST_SUITE: soak + TEST_SUITE: soak - id: soak/ocr_test.go:TestOCRSoak_RPCDownForHalfCLNodes path: integration-tests/soak/ocr_test.go @@ -132,7 +132,7 @@ runner-test-matrix: test_cmd: cd integration-tests/ && go test soak/ocr_test.go -v -test.run ^TestOCRSoak_RPCDownForHalfCLNodes$ -test.parallel=1 -timeout 900h -count=1 -json test_secrets_required: true test_env_vars: - TEST_SUITE: soak + TEST_SUITE: soak - id: smoke/forwarder_ocr_test.go:* path: integration-tests/smoke/forwarder_ocr_test.go @@ -168,7 +168,7 @@ runner-test-matrix: pyroscope_env: ci-smoke-ocr2-evm-simulated test_env_vars: E2E_TEST_CHAINLINK_VERSION: '{{ env.DEFAULT_CHAINLINK_PLUGINS_VERSION }}' # This is the chainlink version that has the plugins - + - id: smoke/ocr2_test.go:*-plugins path: integration-tests/smoke/ocr2_test.go test_env_type: docker @@ -193,12 +193,11 @@ runner-test-matrix: test_cmd: cd integration-tests/chaos && DETACH_RUNNER=false go test -test.run "^TestOCRChaos$" -v -test.parallel=10 -timeout 60m -count=1 -json test_env_vars: TEST_SUITE: chaos - CHAINLINK_USER_TEAM: Foundations # END: OCR tests # START: Automation tests - + - id: smoke/automation_test.go:^TestAutomationBasic/registry_2_0|TestAutomationBasic/registry_2_1_conditional|TestAutomationBasic/registry_2_1_logtrigger$ path: integration-tests/smoke/automation_test.go test_env_type: docker @@ -274,7 +273,7 @@ runner-test-matrix: - Merge Queue E2E Core Tests - Nightly E2E Tests test_cmd: cd integration-tests/smoke && go test -test.run "^TestAutomationBasic/registry_2_3_with_mercury_v03_link|TestAutomationBasic/registry_2_3_with_logtrigger_and_mercury_v02_link$" -test.parallel=2 -timeout 30m -count=1 -json - pyroscope_env: ci-smoke-automation-evm-simulated + pyroscope_env: ci-smoke-automation-evm-simulated - id: smoke/automation_test.go:^TestSetUpkeepTriggerConfig$ path: integration-tests/smoke/automation_test.go @@ -285,7 +284,7 @@ runner-test-matrix: - Merge Queue E2E Core Tests - Nightly E2E Tests test_cmd: cd integration-tests/smoke && go test -test.run ^TestSetUpkeepTriggerConfig$ -test.parallel=2 -timeout 30m -count=1 -json - pyroscope_env: ci-smoke-automation-evm-simulated + pyroscope_env: ci-smoke-automation-evm-simulated - id: smoke/automation_test.go:^TestAutomationAddFunds$ path: integration-tests/smoke/automation_test.go @@ -296,7 +295,7 @@ runner-test-matrix: - Merge Queue E2E Core Tests - Nightly E2E Tests test_cmd: cd integration-tests/smoke && go test -test.run ^TestAutomationAddFunds$ -test.parallel=3 -timeout 30m -count=1 -json - pyroscope_env: ci-smoke-automation-evm-simulated + pyroscope_env: ci-smoke-automation-evm-simulated - id: smoke/automation_test.go:^TestAutomationPauseUnPause$ path: integration-tests/smoke/automation_test.go @@ -307,7 +306,7 @@ runner-test-matrix: - Merge Queue E2E Core Tests - Nightly E2E Tests test_cmd: cd integration-tests/smoke && go test -test.run ^TestAutomationPauseUnPause$ -test.parallel=3 -timeout 30m -count=1 -json - pyroscope_env: ci-smoke-automation-evm-simulated + pyroscope_env: ci-smoke-automation-evm-simulated - id: smoke/automation_test.go:^TestAutomationRegisterUpkeep$ path: integration-tests/smoke/automation_test.go @@ -318,7 +317,7 @@ runner-test-matrix: - Merge Queue E2E Core Tests - Nightly E2E Tests test_cmd: cd integration-tests/smoke && go test -test.run ^TestAutomationRegisterUpkeep$ -test.parallel=3 -timeout 30m -count=1 -json - pyroscope_env: ci-smoke-automation-evm-simulated + pyroscope_env: ci-smoke-automation-evm-simulated - id: smoke/automation_test.go:^TestAutomationPauseRegistry$ path: integration-tests/smoke/automation_test.go @@ -329,7 +328,7 @@ runner-test-matrix: - Merge Queue E2E Core Tests - Nightly E2E Tests test_cmd: cd integration-tests/smoke && go test -test.run ^TestAutomationPauseRegistry$ -test.parallel=3 -timeout 30m -count=1 -json - pyroscope_env: ci-smoke-automation-evm-simulated + pyroscope_env: ci-smoke-automation-evm-simulated - id: smoke/automation_test.go:^TestAutomationKeeperNodesDown$ path: integration-tests/smoke/automation_test.go @@ -340,7 +339,7 @@ runner-test-matrix: - Merge Queue E2E Core Tests - Nightly E2E Tests test_cmd: cd integration-tests/smoke && go test -test.run ^TestAutomationKeeperNodesDown$ -test.parallel=3 -timeout 30m -count=1 -json - pyroscope_env: ci-smoke-automation-evm-simulated + pyroscope_env: ci-smoke-automation-evm-simulated - id: smoke/automation_test.go:^TestAutomationPerformSimulation$ path: integration-tests/smoke/automation_test.go @@ -351,7 +350,7 @@ runner-test-matrix: - Merge Queue E2E Core Tests - Nightly E2E Tests test_cmd: cd integration-tests/smoke && go test -test.run ^TestAutomationPerformSimulation$ -test.parallel=3 -timeout 30m -count=1 -json - pyroscope_env: ci-smoke-automation-evm-simulated + pyroscope_env: ci-smoke-automation-evm-simulated - id: smoke/automation_test.go:^TestAutomationCheckPerformGasLimit$ path: integration-tests/smoke/automation_test.go @@ -362,7 +361,7 @@ runner-test-matrix: - Merge Queue E2E Core Tests - Nightly E2E Tests test_cmd: cd integration-tests/smoke && go test -test.run ^TestAutomationCheckPerformGasLimit$ -test.parallel=3 -timeout 30m -count=1 -json - pyroscope_env: ci-smoke-automation-evm-simulated + pyroscope_env: ci-smoke-automation-evm-simulated - id: smoke/automation_test.go:^TestUpdateCheckData$ path: integration-tests/smoke/automation_test.go @@ -373,7 +372,7 @@ runner-test-matrix: - Merge Queue E2E Core Tests - Nightly E2E Tests test_cmd: cd integration-tests/smoke && go test -test.run ^TestUpdateCheckData$ -test.parallel=3 -timeout 30m -count=1 -json - pyroscope_env: ci-smoke-automation-evm-simulated + pyroscope_env: ci-smoke-automation-evm-simulated - id: smoke/automation_test.go:^TestSetOffchainConfigWithMaxGasPrice$ path: integration-tests/smoke/automation_test.go @@ -384,7 +383,7 @@ runner-test-matrix: - Merge Queue E2E Core Tests - Nightly E2E Tests test_cmd: cd integration-tests/smoke && go test -test.run ^TestSetOffchainConfigWithMaxGasPrice$ -test.parallel=2 -timeout 30m -count=1 -json - pyroscope_env: ci-smoke-automation-evm-simulated + pyroscope_env: ci-smoke-automation-evm-simulated - id: smoke/keeper_test.go:^TestKeeperBasicSmoke$ path: integration-tests/smoke/keeper_test.go @@ -394,7 +393,7 @@ runner-test-matrix: - Merge Queue E2E Core Tests - Nightly E2E Tests test_cmd: cd integration-tests/smoke && go test -test.run ^TestKeeperBasicSmoke$ -test.parallel=3 -timeout 30m -count=1 -json - pyroscope_env: ci-smoke-keeper-evm-simulated + pyroscope_env: ci-smoke-keeper-evm-simulated - id: smoke/keeper_test.go:^TestKeeperBlockCountPerTurn$ path: integration-tests/smoke/keeper_test.go @@ -404,7 +403,7 @@ runner-test-matrix: - Merge Queue E2E Core Tests - Nightly E2E Tests test_cmd: cd integration-tests/smoke && go test -test.run ^TestKeeperBlockCountPerTurn$ -test.parallel=3 -timeout 30m -count=1 -json - pyroscope_env: ci-smoke-keeper-evm-simulated + pyroscope_env: ci-smoke-keeper-evm-simulated - id: smoke/keeper_test.go:^TestKeeperSimulation$ path: integration-tests/smoke/keeper_test.go @@ -414,7 +413,7 @@ runner-test-matrix: - Merge Queue E2E Core Tests - Nightly E2E Tests test_cmd: cd integration-tests/smoke && go test -test.run ^TestKeeperSimulation$ -test.parallel=2 -timeout 30m -count=1 -json - pyroscope_env: ci-smoke-keeper-evm-simulated + pyroscope_env: ci-smoke-keeper-evm-simulated - id: smoke/keeper_test.go:^TestKeeperCheckPerformGasLimit$ path: integration-tests/smoke/keeper_test.go @@ -424,7 +423,7 @@ runner-test-matrix: - Merge Queue E2E Core Tests - Nightly E2E Tests test_cmd: cd integration-tests/smoke && go test -test.run ^TestKeeperCheckPerformGasLimit$ -test.parallel=2 -timeout 30m -count=1 -json - pyroscope_env: ci-smoke-keeper-evm-simulated + pyroscope_env: ci-smoke-keeper-evm-simulated - id: smoke/keeper_test.go:^TestKeeperRegisterUpkeep$ path: integration-tests/smoke/keeper_test.go @@ -434,7 +433,7 @@ runner-test-matrix: - Merge Queue E2E Core Tests - Nightly E2E Tests test_cmd: cd integration-tests/smoke && go test -test.run ^TestKeeperRegisterUpkeep$ -test.parallel=3 -timeout 30m -count=1 -json - pyroscope_env: ci-smoke-keeper-evm-simulated + pyroscope_env: ci-smoke-keeper-evm-simulated - id: smoke/keeper_test.go:^TestKeeperAddFunds$ path: integration-tests/smoke/keeper_test.go @@ -444,7 +443,7 @@ runner-test-matrix: - Merge Queue E2E Core Tests - Nightly E2E Tests test_cmd: cd integration-tests/smoke && go test -test.run ^TestKeeperAddFunds$ -test.parallel=3 -timeout 30m -count=1 -json - pyroscope_env: ci-smoke-keeper-evm-simulated + pyroscope_env: ci-smoke-keeper-evm-simulated - id: smoke/keeper_test.go:^TestKeeperRemove$ path: integration-tests/smoke/keeper_test.go @@ -454,8 +453,8 @@ runner-test-matrix: - Merge Queue E2E Core Tests - Nightly E2E Tests test_cmd: cd integration-tests/smoke && go test -test.run ^TestKeeperRemove$ -test.parallel=3 -timeout 30m -count=1 -json - pyroscope_env: ci-smoke-keeper-evm-simulated - + pyroscope_env: ci-smoke-keeper-evm-simulated + - id: smoke/keeper_test.go:^TestKeeperPauseRegistry$ path: integration-tests/smoke/keeper_test.go test_env_type: docker @@ -464,7 +463,7 @@ runner-test-matrix: - Merge Queue E2E Core Tests - Nightly E2E Tests test_cmd: cd integration-tests/smoke && go test -test.run ^TestKeeperPauseRegistry$ -test.parallel=2 -timeout 30m -count=1 -json - pyroscope_env: ci-smoke-keeper-evm-simulated + pyroscope_env: ci-smoke-keeper-evm-simulated - id: smoke/keeper_test.go:^TestKeeperMigrateRegistry$ path: integration-tests/smoke/keeper_test.go @@ -474,7 +473,7 @@ runner-test-matrix: - Merge Queue E2E Core Tests - Nightly E2E Tests test_cmd: cd integration-tests/smoke && go test -test.run ^TestKeeperMigrateRegistry$ -test.parallel=1 -timeout 30m -count=1 -json - pyroscope_env: ci-smoke-keeper-evm-simulated + pyroscope_env: ci-smoke-keeper-evm-simulated - id: smoke/keeper_test.go:^TestKeeperNodeDown$ path: integration-tests/smoke/keeper_test.go @@ -484,7 +483,7 @@ runner-test-matrix: - Merge Queue E2E Core Tests - Nightly E2E Tests test_cmd: cd integration-tests/smoke && go test -test.run ^TestKeeperNodeDown$ -test.parallel=3 -timeout 30m -count=1 -json - pyroscope_env: ci-smoke-keeper-evm-simulated + pyroscope_env: ci-smoke-keeper-evm-simulated - id: smoke/keeper_test.go:^TestKeeperPauseUnPauseUpkeep$ path: integration-tests/smoke/keeper_test.go @@ -494,7 +493,7 @@ runner-test-matrix: - Merge Queue E2E Core Tests - Nightly E2E Tests test_cmd: cd integration-tests/smoke && go test -test.run ^TestKeeperPauseUnPauseUpkeep$ -test.parallel=1 -timeout 30m -count=1 -json - pyroscope_env: ci-smoke-keeper-evm-simulated + pyroscope_env: ci-smoke-keeper-evm-simulated - id: smoke/keeper_test.go:^TestKeeperUpdateCheckData$ path: integration-tests/smoke/keeper_test.go @@ -504,7 +503,7 @@ runner-test-matrix: - Merge Queue E2E Core Tests - Nightly E2E Tests test_cmd: cd integration-tests/smoke && go test -test.run ^TestKeeperUpdateCheckData$ -test.parallel=1 -timeout 30m -count=1 -json - pyroscope_env: ci-smoke-keeper-evm-simulated + pyroscope_env: ci-smoke-keeper-evm-simulated - id: smoke/keeper_test.go:^TestKeeperJobReplacement$ path: integration-tests/smoke/keeper_test.go @@ -514,7 +513,7 @@ runner-test-matrix: - Merge Queue E2E Core Tests - Nightly E2E Tests test_cmd: cd integration-tests/smoke && go test -test.run ^TestKeeperJobReplacement$ -test.parallel=1 -timeout 30m -count=1 -json - pyroscope_env: ci-smoke-keeper-evm-simulated + pyroscope_env: ci-smoke-keeper-evm-simulated - id: load/automationv2_1/automationv2_1_test.go:TestLogTrigger path: integration-tests/load/automationv2_1/automationv2_1_test.go @@ -547,7 +546,7 @@ runner-test-matrix: test_env_type: docker runs_on: ubuntu22.04-8cores-32GB triggers: - - Automation Nightly Tests + - Automation Nightly Tests test_cmd: cd integration-tests/smoke && go test -test.run ^TestAutomationNodeUpgrade/registry_2_1 -test.parallel=5 -timeout 60m -count=1 -json test_env_vars: E2E_TEST_CHAINLINK_IMAGE: public.ecr.aws/chainlink/chainlink @@ -625,7 +624,6 @@ runner-test-matrix: pyroscope_env: ci-automation-on-demand-chaos test_env_vars: TEST_SUITE: chaos - CHAINLINK_USER_TEAM: Automation - id: benchmark/automation_test.go:TestAutomationBenchmark path: integration-tests/benchmark/automation_test.go @@ -678,7 +676,7 @@ runner-test-matrix: test_env_vars: TEST_TYPE: Smoke triggers: - - On Demand VRFV2 Plus Performance Test + - On Demand VRFV2 Plus Performance Test - id: load/vrfv2plus/vrfv2plus_test.go:^TestVRFV2PlusBHSPerformance$Smoke path: integration-tests/load/vrfv2plus/vrfv2plus_test.go @@ -690,7 +688,7 @@ runner-test-matrix: test_env_vars: TEST_TYPE: Smoke triggers: - - On Demand VRFV2 Plus Performance Test + - On Demand VRFV2 Plus Performance Test - id: load/vrfv2/vrfv2_test.go:^TestVRFV2Performance$Smoke path: integration-tests/load/vrfv2/vrfv2_test.go @@ -700,9 +698,9 @@ runner-test-matrix: test_config_override_required: true test_secrets_required: true test_env_vars: - TEST_TYPE: Smoke + TEST_TYPE: Smoke triggers: - - On Demand VRFV2 Performance Test + - On Demand VRFV2 Performance Test - id: load/vrfv2/vrfv2_test.go:^TestVRFV2PlusBHSPerformance$Smoke path: integration-tests/load/vrfv2/vrfv2_test.go @@ -894,7 +892,7 @@ runner-test-matrix: - Merge Queue E2E Core Tests - Nightly E2E Tests test_cmd: cd integration-tests/ && go test smoke/flux_test.go -timeout 30m -count=1 -json - pyroscope_env: ci-smoke-flux-evm-simulated + pyroscope_env: ci-smoke-flux-evm-simulated - id: smoke/reorg_above_finality_test.go:* path: integration-tests/smoke/reorg_above_finality_test.go @@ -906,7 +904,7 @@ runner-test-matrix: - Nightly E2E Tests test_cmd: cd integration-tests/ && go test smoke/reorg_above_finality_test.go -timeout 30m -count=1 -json pyroscope_env: ci-smoke-reorg-above-finality-evm-simulated - + - id: migration/upgrade_version_test.go:* path: integration-tests/migration/upgrade_version_test.go test_env_type: docker @@ -937,167 +935,79 @@ runner-test-matrix: # START: CCIPv1.6 tests - - id: smoke/ccip/ccip_token_price_updates_test.go:* - path: integration-tests/smoke/ccip/ccip_token_price_updates_test.go + - id: smoke/ccip_test.go:* + path: integration-tests/smoke/ccip_test.go test_env_type: docker runs_on: ubuntu-latest triggers: - PR E2E Core Tests + - Merge Queue E2E Core Tests - Nightly E2E Tests - test_cmd: cd integration-tests/smoke/ccip && go test ccip_token_price_updates_test.go -timeout 18m -test.parallel=1 -count=1 -json + test_cmd: cd integration-tests/ && go test smoke/ccip_test.go -timeout 12m -test.parallel=2 -count=1 -json pyroscope_env: ci-smoke-ccipv1_6-evm-simulated test_env_vars: E2E_TEST_SELECTED_NETWORK: SIMULATED_1,SIMULATED_2 - E2E_JD_VERSION: 0.6.0 - CCIP_V16_TEST_ENV: docker - - - id: smoke/ccip/ccip_gas_price_updates_test.go:* - path: integration-tests/smoke/ccip/ccip_gas_price_updates_test.go + E2E_JD_VERSION: 0.4.0 + + - id: smoke/ccip_messaging_test.go:* + path: integration-tests/smoke/ccip_messaging_test.go test_env_type: docker runs_on: ubuntu-latest triggers: - PR E2E Core Tests + - Merge Queue E2E Core Tests - Nightly E2E Tests - test_cmd: cd integration-tests/smoke/ccip && go test ccip_gas_price_updates_test.go -timeout 18m -test.parallel=1 -count=1 -json - pyroscope_env: ci-smoke-ccipv1_6-evm-simulated - test_env_vars: - E2E_TEST_SELECTED_NETWORK: SIMULATED_1,SIMULATED_2 - E2E_JD_VERSION: 0.6.0 - CCIP_V16_TEST_ENV: docker - - - id: smoke/ccip/ccip_rmn_test.go:^TestRMN_TwoMessagesOnTwoLanesIncludingBatching$ - path: integration-tests/smoke/ccip/ccip_rmn_test.go - test_env_type: docker - runs_on: ubuntu20.04-8cores-32GB - triggers: - - PR E2E Core Tests - - Nightly E2E Tests - test_cmd: cd integration-tests/smoke/ccip && go test -test.run ^TestRMN_TwoMessagesOnTwoLanesIncludingBatching$ -timeout 12m -test.parallel=1 -count=1 -json - pyroscope_env: ci-smoke-ccipv1_6-evm-simulated - test_env_vars: - E2E_TEST_SELECTED_NETWORK: SIMULATED_1,SIMULATED_2 - E2E_JD_VERSION: 0.6.0 - E2E_RMN_RAGEPROXY_VERSION: 678509b - E2E_RMN_AFN2PROXY_VERSION: 678509b - CCIP_V16_TEST_ENV: docker - - - id: smoke/ccip/ccip_rmn_test.go:^TestRMN_MultipleMessagesOnOneLaneNoWaitForExec$ - path: integration-tests/smoke/ccip/ccip_rmn_test.go - test_env_type: docker - runs_on: ubuntu20.04-8cores-32GB - triggers: - - PR E2E Core Tests - - Nightly E2E Tests - test_cmd: cd integration-tests/smoke/ccip && go test -test.run ^TestRMN_MultipleMessagesOnOneLaneNoWaitForExec$ -timeout 12m -test.parallel=1 -count=1 -json - pyroscope_env: ci-smoke-ccipv1_6-evm-simulated - test_env_vars: - E2E_TEST_SELECTED_NETWORK: SIMULATED_1,SIMULATED_2 - E2E_JD_VERSION: 0.6.0 - E2E_RMN_RAGEPROXY_VERSION: 678509b - E2E_RMN_AFN2PROXY_VERSION: 678509b - CCIP_V16_TEST_ENV: docker - - - id: smoke/ccip/ccip_rmn_test.go:^TestRMN_NotEnoughObservers$ - path: integration-tests/smoke/ccip/ccip_rmn_test.go - test_env_type: docker - runs_on: ubuntu20.04-8cores-32GB - triggers: - - PR E2E Core Tests - - Nightly E2E Tests - test_cmd: cd integration-tests/smoke/ccip && go test -test.run ^TestRMN_NotEnoughObservers$ -timeout 12m -test.parallel=1 -count=1 -json + test_cmd: cd integration-tests/ && go test smoke/ccip_messaging_test.go -timeout 12m -test.parallel=1 -count=1 -json pyroscope_env: ci-smoke-ccipv1_6-evm-simulated test_env_vars: E2E_TEST_SELECTED_NETWORK: SIMULATED_1,SIMULATED_2 - E2E_JD_VERSION: 0.6.0 - E2E_RMN_RAGEPROXY_VERSION: 678509b - E2E_RMN_AFN2PROXY_VERSION: 678509b - CCIP_V16_TEST_ENV: docker + E2E_JD_VERSION: 0.4.0 - - id: smoke/ccip/ccip_rmn_test.go:^TestRMN_DifferentSigners$ - path: integration-tests/smoke/ccip/ccip_rmn_test.go + - id: smoke/ccip_usdc_test.go:* + path: integration-tests/smoke/ccip_usdc_test.go test_env_type: docker - runs_on: ubuntu20.04-8cores-32GB + runs_on: ubuntu-latest triggers: - PR E2E Core Tests + - Merge Queue E2E Core Tests - Nightly E2E Tests - test_cmd: cd integration-tests/smoke/ccip && go test -test.run ^TestRMN_DifferentSigners$ -timeout 12m -test.parallel=1 -count=1 -json + test_cmd: cd integration-tests/ && go test smoke/ccip_usdc_test.go -timeout 12m -test.parallel=1 -count=1 -json pyroscope_env: ci-smoke-ccipv1_6-evm-simulated test_env_vars: E2E_TEST_SELECTED_NETWORK: SIMULATED_1,SIMULATED_2 - E2E_JD_VERSION: 0.6.0 - E2E_RMN_RAGEPROXY_VERSION: 678509b - E2E_RMN_AFN2PROXY_VERSION: 678509b - CCIP_V16_TEST_ENV: docker + E2E_JD_VERSION: 0.4.0 - - id: smoke/ccip/ccip_rmn_test.go:^TestRMN_NotEnoughSigners$ - path: integration-tests/smoke/ccip/ccip_rmn_test.go + - id: smoke/fee_boosting_test.go:* + path: integration-tests/smoke/fee_boosting_test.go test_env_type: docker - runs_on: ubuntu20.04-8cores-32GB + runs_on: ubuntu-latest triggers: - PR E2E Core Tests + - Merge Queue E2E Core Tests - Nightly E2E Tests - test_cmd: cd integration-tests/smoke/ccip && go test -test.run ^TestRMN_NotEnoughSigners$ -timeout 12m -test.parallel=1 -count=1 -json + test_cmd: cd integration-tests/ && go test smoke/fee_boosting_test.go -timeout 15m -test.parallel=1 -count=1 -json pyroscope_env: ci-smoke-ccipv1_6-evm-simulated test_env_vars: E2E_TEST_SELECTED_NETWORK: SIMULATED_1,SIMULATED_2 - E2E_JD_VERSION: 0.6.0 - E2E_RMN_RAGEPROXY_VERSION: 678509b - E2E_RMN_AFN2PROXY_VERSION: 678509b - CCIP_V16_TEST_ENV: docker + E2E_JD_VERSION: 0.4.0 - - id: smoke/ccip/ccip_rmn_test.go:^TestRMN_DifferentRmnNodesForDifferentChains$ - path: integration-tests/smoke/ccip/ccip_rmn_test.go - test_env_type: docker - runs_on: ubuntu20.04-8cores-32GB - triggers: - - PR E2E Core Tests - - Nightly E2E Tests - test_cmd: cd integration-tests/smoke/ccip && go test -test.run ^TestRMN_DifferentRmnNodesForDifferentChains$ -timeout 12m -test.parallel=1 -count=1 -json - pyroscope_env: ci-smoke-ccipv1_6-evm-simulated - test_env_vars: - E2E_TEST_SELECTED_NETWORK: SIMULATED_1,SIMULATED_2 - E2E_JD_VERSION: 0.6.0 - E2E_RMN_RAGEPROXY_VERSION: 678509b - E2E_RMN_AFN2PROXY_VERSION: 678509b - CCIP_V16_TEST_ENV: docker + # END: CCIPv1.6 tests - - id: smoke/ccip/ccip_rmn_test.go:^TestRMN_TwoMessagesOneSourceChainCursed$ - path: integration-tests/smoke/ccip/ccip_rmn_test.go - test_env_type: docker - runs_on: ubuntu20.04-8cores-32GB - triggers: - - PR E2E Core Tests - - Nightly E2E Tests - test_cmd: cd integration-tests/smoke/ccip && go test -test.run ^TestRMN_TwoMessagesOneSourceChainCursed$ -timeout 12m -test.parallel=1 -count=1 -json - pyroscope_env: ci-smoke-ccipv1_6-evm-simulated - test_env_vars: - E2E_TEST_SELECTED_NETWORK: SIMULATED_1,SIMULATED_2 - E2E_JD_VERSION: 0.6.0 - E2E_RMN_RAGEPROXY_VERSION: 678509b - E2E_RMN_AFN2PROXY_VERSION: 678509b - CCIP_V16_TEST_ENV: docker + # START: CCIP tests - - id: smoke/ccip/ccip_rmn_test.go:^TestRMN_GlobalCurseTwoMessagesOnTwoLanes$ - path: integration-tests/smoke/ccip/ccip_rmn_test.go + - id: ccip-smoke + path: integration-tests/ccip-tests/smoke/ccip_test.go test_env_type: docker - runs_on: ubuntu20.04-8cores-32GB + runs_on: ubuntu-latest triggers: - - PR E2E Core Tests + - PR E2E CCIP Tests + - Merge Queue E2E CCIP Tests - Nightly E2E Tests - test_cmd: cd integration-tests/smoke/ccip && go test -test.run ^TestRMN_GlobalCurseTwoMessagesOnTwoLanes$ -timeout 12m -test.parallel=1 -count=1 -json - pyroscope_env: ci-smoke-ccipv1_6-evm-simulated + test_cmd: cd integration-tests/ccip-tests/smoke && go test ccip_test.go -test.run ^TestSmokeCCIPForBidirectionalLane$ -timeout 30m -count=1 -test.parallel=1 -json test_env_vars: E2E_TEST_SELECTED_NETWORK: SIMULATED_1,SIMULATED_2 - E2E_JD_VERSION: 0.6.0 - E2E_RMN_RAGEPROXY_VERSION: 678509b - E2E_RMN_AFN2PROXY_VERSION: 678509b - CCIP_V16_TEST_ENV: docker - # END: CCIPv1.6 tests - - # START: CCIP tests - - - id: ccip-smoke + - id: ccip-smoke-1.4-pools path: integration-tests/ccip-tests/smoke/ccip_test.go test_env_type: docker runs_on: ubuntu-latest @@ -1108,8 +1018,8 @@ runner-test-matrix: test_cmd: cd integration-tests/ccip-tests/smoke && go test ccip_test.go -test.run ^TestSmokeCCIPForBidirectionalLane$ -timeout 30m -count=1 -test.parallel=1 -json test_env_vars: E2E_TEST_SELECTED_NETWORK: SIMULATED_1,SIMULATED_2 - CHAINLINK_USER_TEAM: CCIP - + test_config_override_path: integration-tests/ccip-tests/testconfig/tomls/contract-version1.4.toml + - id: ccip-smoke-usdc path: integration-tests/ccip-tests/smoke/ccip_test.go test_env_type: docker @@ -1121,7 +1031,6 @@ runner-test-matrix: test_cmd: cd integration-tests/ccip-tests/smoke && go test ccip_test.go -test.run ^TestSmokeCCIPForBidirectionalLane$ -timeout 30m -count=1 -test.parallel=1 -json test_env_vars: E2E_TEST_SELECTED_NETWORK: SIMULATED_1,SIMULATED_2 - CHAINLINK_USER_TEAM: CCIP test_config_override_path: integration-tests/ccip-tests/testconfig/tomls/usdc_mock_deployment.toml - id: ccip-smoke-db-compatibility @@ -1135,7 +1044,6 @@ runner-test-matrix: test_cmd: cd integration-tests/ccip-tests/smoke && go test ccip_test.go -test.run ^TestSmokeCCIPForBidirectionalLane$ -timeout 30m -count=1 -test.parallel=1 -json test_env_vars: E2E_TEST_SELECTED_NETWORK: SIMULATED_1,SIMULATED_2 - CHAINLINK_USER_TEAM: CCIP test_config_override_path: integration-tests/ccip-tests/testconfig/tomls/db-compatibility.toml - id: ccip-smoke-leader-lane @@ -1162,7 +1070,6 @@ runner-test-matrix: test_cmd: cd integration-tests/ccip-tests/smoke && go test ccip_test.go -test.run ^TestSmokeCCIPTokenPoolRateLimits$ -timeout 30m -count=1 -test.parallel=1 -json test_env_vars: E2E_TEST_SELECTED_NETWORK: SIMULATED_1,SIMULATED_2 - CHAINLINK_USER_TEAM: CCIP - id: ccip-tests/smoke/ccip_test.go:^TestSmokeCCIPMulticall$ path: integration-tests/ccip-tests/smoke/ccip_test.go @@ -1175,7 +1082,6 @@ runner-test-matrix: test_cmd: cd integration-tests/ccip-tests/smoke && go test ccip_test.go -test.run ^TestSmokeCCIPMulticall$ -timeout 30m -count=1 -test.parallel=1 -json test_env_vars: E2E_TEST_SELECTED_NETWORK: SIMULATED_1,SIMULATED_2 - CHAINLINK_USER_TEAM: CCIP - id: ccip-tests/smoke/ccip_test.go:^TestSmokeCCIPManuallyExecuteAfterExecutionFailingDueToInsufficientGas$ path: integration-tests/ccip-tests/smoke/ccip_test.go @@ -1188,7 +1094,6 @@ runner-test-matrix: test_cmd: cd integration-tests/ccip-tests/smoke && go test ccip_test.go -test.run ^TestSmokeCCIPManuallyExecuteAfterExecutionFailingDueToInsufficientGas$ -timeout 30m -count=1 -test.parallel=1 -json test_env_vars: E2E_TEST_SELECTED_NETWORK: SIMULATED_1,SIMULATED_2 - CHAINLINK_USER_TEAM: CCIP - id: ccip-tests/smoke/ccip_test.go:^TestSmokeCCIPOnRampLimits$ path: integration-tests/ccip-tests/smoke/ccip_test.go @@ -1201,7 +1106,6 @@ runner-test-matrix: test_cmd: cd integration-tests/ccip-tests/smoke && go test ccip_test.go -test.run ^TestSmokeCCIPOnRampLimits$ -timeout 30m -count=1 -test.parallel=1 -json test_env_vars: E2E_TEST_SELECTED_NETWORK: SIMULATED_1,SIMULATED_2 - CHAINLINK_USER_TEAM: CCIP - id: ccip-tests/smoke/ccip_test.go:^TestSmokeCCIPOffRampCapacityLimit$ path: integration-tests/ccip-tests/smoke/ccip_test.go @@ -1211,8 +1115,7 @@ runner-test-matrix: - Nightly E2E Tests test_cmd: cd integration-tests/ccip-tests/smoke && go test ccip_test.go -test.run ^TestSmokeCCIPOffRampCapacityLimit$ -timeout 30m -count=1 -test.parallel=1 -json test_env_vars: - E2E_TEST_SELECTED_NETWORK: SIMULATED_1,SIMULATED_2 - CHAINLINK_USER_TEAM: CCIP + E2E_TEST_SELECTED_NETWORK: SIMULATED_1,SIMULATED_2 - id: ccip-tests/smoke/ccip_test.go:^TestSmokeCCIPOffRampAggRateLimit$ path: integration-tests/ccip-tests/smoke/ccip_test.go @@ -1223,7 +1126,6 @@ runner-test-matrix: test_cmd: cd integration-tests/ccip-tests/smoke && go test ccip_test.go -test.run ^TestSmokeCCIPOffRampAggRateLimit$ -timeout 30m -count=1 -test.parallel=1 -json test_env_vars: E2E_TEST_SELECTED_NETWORK: SIMULATED_1,SIMULATED_2 - CHAINLINK_USER_TEAM: CCIP - id: ccip-tests/smoke/ccip_test.go:^TestSmokeCCIPReorgBelowFinality$ path: integration-tests/ccip-tests/smoke/ccip_test.go @@ -1236,7 +1138,6 @@ runner-test-matrix: test_cmd: cd integration-tests/ccip-tests/smoke && go test ccip_test.go -test.run ^TestSmokeCCIPReorgBelowFinality$ -timeout 30m -count=1 -test.parallel=1 -json test_env_vars: E2E_TEST_SELECTED_NETWORK: SIMULATED_1,SIMULATED_2 - CHAINLINK_USER_TEAM: CCIP test_config_override_path: integration-tests/ccip-tests/testconfig/tomls/ccip-reorg.toml - id: ccip-tests/smoke/ccip_test.go:^TestSmokeCCIPReorgAboveFinalityAtDestination$ @@ -1250,7 +1151,6 @@ runner-test-matrix: test_cmd: cd integration-tests/ccip-tests/smoke && go test ccip_test.go -test.run ^TestSmokeCCIPReorgAboveFinalityAtDestination$ -timeout 30m -count=1 -test.parallel=1 -json test_env_vars: E2E_TEST_SELECTED_NETWORK: SIMULATED_1,SIMULATED_2 - CHAINLINK_USER_TEAM: CCIP test_config_override_path: integration-tests/ccip-tests/testconfig/tomls/ccip-reorg.toml - id: ccip-tests/smoke/ccip_test.go:^TestSmokeCCIPReorgAboveFinalityAtSource$ @@ -1264,7 +1164,6 @@ runner-test-matrix: test_cmd: cd integration-tests/ccip-tests/smoke && go test ccip_test.go -test.run ^TestSmokeCCIPReorgAboveFinalityAtSource$ -timeout 30m -count=1 -test.parallel=1 -json test_env_vars: E2E_TEST_SELECTED_NETWORK: SIMULATED_1,SIMULATED_2 - CHAINLINK_USER_TEAM: CCIP test_config_override_path: integration-tests/ccip-tests/testconfig/tomls/ccip-reorg.toml - id: integration-tests/ccip-tests/load/ccip_test.go:TestLoadCCIPStableRPS @@ -1276,8 +1175,8 @@ runner-test-matrix: TEST_SUITE: ccip-load E2E_TEST_GRAFANA_DASHBOARD_URL: "/d/6vjVx-1V8/ccip-long-running-tests" triggers: - - E2E CCIP Load Tests - test_artifacts_on_failure: + - E2E CCIP Load Tests + test_artifacts_on_failure: - ./integration-tests/load/logs/payload_ccip.json # Enable when CCIP-2277 is resolved @@ -1291,8 +1190,8 @@ runner-test-matrix: # test_env_vars: # E2E_TEST_GRAFANA_DASHBOARD_URL: "/d/6vjVx-1V8/ccip-long-running-tests" # triggers: - # - E2E CCIP Load Tests - # test_artifacts_on_failure: + # - E2E CCIP Load Tests + # test_artifacts_on_failure: # - ./integration-tests/load/logs/payload_ccip.json - id: ccip-tests/chaos/ccip_test.go @@ -1320,5 +1219,5 @@ runner-test-matrix: TEST_TRIGGERED_BY: ccip-cron-chaos-eth TEST_LOG_LEVEL: debug E2E_TEST_GRAFANA_DASHBOARD_URL: /d/6vjVx-1V8/ccip-long-running-tests - + # END: CCIP tests diff --git a/.github/integration-in-memory-tests.yml b/.github/integration-in-memory-tests.yml deleted file mode 100644 index 9550d74f21f..00000000000 --- a/.github/integration-in-memory-tests.yml +++ /dev/null @@ -1,83 +0,0 @@ -# This file specifies the GitHub runner for each in-memory integration test and is utilized by .github/workflows/integration-in-memory-tests.yml CI workflow. -# -# Each entry in this file includes the following: -# - The GitHub runner (runs_on field) that will execute tests. -# - The tests that will be run by the runner. -# - The triggers (e.g., PR Integration CCIP Tests) that should trigger these tests. -# -runner-test-matrix: - # START: CCIPv1.6 tests - - - id: smoke/ccip/ccip_fees_test.go:* - path: integration-tests/smoke/ccip/ccip_fees_test.go - test_env_type: in-memory - runs_on: ubuntu-latest - triggers: - - PR Integration CCIP Tests - test_cmd: cd integration-tests/smoke/ccip && go test ccip_fees_test.go -timeout 12m -test.parallel=2 -count=1 -json - - - id: smoke/ccip/ccip_messaging_test.go:* - path: integration-tests/smoke/ccip/ccip_messaging_test.go - test_env_type: in-memory - runs_on: ubuntu-latest - triggers: - - PR Integration CCIP Tests - test_cmd: cd integration-tests/smoke/ccip && go test ccip_messaging_test.go -timeout 12m -test.parallel=2 -count=1 -json - - - id: smoke/ccip/ccip_message_limitations_test.go:* - path: integration-tests/smoke/ccip/ccip_message_limitations_test.go - test_env_type: in-memory - runs_on: ubuntu-latest - triggers: - - PR Integration CCIP Tests - test_cmd: cd integration-tests/smoke/ccip && go test -run "Test_CCIPMessageLimitations" -timeout 12m -test.parallel=2 -count=1 -json - - - id: smoke/ccip/ccip_fee_boosting_test.go:* - path: integration-tests/smoke/ccip/ccip_fee_boosting_test.go - test_env_type: in-memory - runs_on: ubuntu-latest - triggers: - - PR Integration CCIP Tests - test_cmd: cd integration-tests/smoke/ccip && go test ccip_fee_boosting_test.go -timeout 12m -test.parallel=2 -count=1 -json - - - id: smoke/ccip/ccip_batching_test.go:* - path: integration-tests/smoke/ccip/ccip_batching_test.go - test_env_type: in-memory - runs_on: ubuntu-latest - triggers: - - PR Integration CCIP Tests - test_cmd: cd integration-tests/smoke/ccip && go test ccip_batching_test.go -timeout 12m -test.parallel=2 -count=1 -json - - - id: contracts/ccipreader_test.go:* - path: integration-tests/contracts/ccipreader_test.go - test_env_type: in-memory - runs_on: ubuntu-latest - triggers: - - PR Integration CCIP Tests - test_cmd: cd integration-tests/contracts && go test ccipreader_test.go -timeout 5m -test.parallel=1 -count=1 -json - - - id: smoke/ccip/ccip_usdc_test.go:* - path: integration-tests/smoke/ccip/ccip_usdc_test.go - test_env_type: in-memory - runs_on: ubuntu-latest - triggers: - - PR Integration CCIP Tests - test_cmd: cd integration-tests/smoke/ccip && go test ccip_usdc_test.go -timeout 18m -test.parallel=1 -count=1 -json - - - id: smoke/ccip/ccip_ooo_execution_test.go:* - path: integration-tests/smoke/ccip/ccip_ooo_execution_test.go - test_env_type: in-memory - runs_on: ubuntu-latest - triggers: - - PR Integration CCIP Tests - test_cmd: cd integration-tests/ && go test smoke/ccip/ccip_ooo_execution_test.go -timeout 16m -test.parallel=1 -count=1 -json - - - id: smoke/ccip/ccip_token_transfer_test.go:* - path: integration-tests/smoke/ccip/ccip_token_transfer_test.go - test_env_type: in-memory - runs_on: ubuntu-latest - triggers: - - PR Integration CCIP Tests - test_cmd: cd integration-tests/ && go test smoke/ccip/ccip_token_transfer_test.go -timeout 16m -test.parallel=1 -count=1 -json - - # END: CCIP tests diff --git a/.github/scripts/map-affected-files-to-modules.sh b/.github/scripts/map-affected-files-to-modules.sh deleted file mode 100755 index 34f058529cf..00000000000 --- a/.github/scripts/map-affected-files-to-modules.sh +++ /dev/null @@ -1,60 +0,0 @@ -#!/bin/bash -set -e - -# This script: -# 1. Finds all modules. -# 2. Maps changed files (passed as a param) to found modules. -# 3. Prints out the affected modules. -# 4. Output the result (as JSON) to a GitHub Actions environment variable. - -# Get the list of changed files as parameter (from JSON array) -changed_files=$(echo "$1" | jq -r '.[]') -echo "Changed files: $changed_files" - -# 1. Find all modules in the repository, -# - Strip the leading './' from the path -# (necessary for comparison, affected files do not have leading './') -modules=$(find . -name 'go.mod' -exec dirname {} \; | sed 's|^./||' | uniq) -echo "Found modules: $modules" - -# Use a Bash associative array to track unique modules -declare -A unique_modules - -for path_to_file in $changed_files; do - echo "Resolving a module affected by a file: '$path_to_file'" - # the flag that indicates if the path matches any module - is_path_in_modules=false - for module in $modules; do - echo "Validating against module: '$module'" - # if a module's name matches with a file path - # add it, to the affected modules array, skipping the root (`.`) - if [[ $module != "." && $path_to_file =~ ^$module* ]]; then - echo -e "File '$path_to_file' mapped to the module '$module'\n" - unique_modules["$module"]="$module" - is_path_in_modules=true - break - fi - done - # if no matched module default to root module - if [[ $is_path_in_modules == false ]]; then - echo "File '$path_to_file' did not match any module, defaulting to root '.'" - unique_modules["."]="." - is_path_in_modules=false - fi - is_path_in_modules=false -done - -# if the path is empty (for any reason), it will not get to the loop, -# so if the unique_modules array is empty, default to the root module -if [[ ${#unique_modules[@]} -eq 0 ]]; then - echo "No files were changed, defaulting to the root module '.'" - unique_modules["."]="." -fi - -# Convert keys (module names) of the associative array to an indexed array -affected_modules=("${!unique_modules[@]}") -echo "Affected modules: ${affected_modules[@]}" - -# Convert bash array to a JSON array for GitHub Actions -json_array=$(printf '%s\n' "${affected_modules[@]}" | jq -R . | jq -s . | jq -c) -echo "module_names=$json_array" >> "$GITHUB_OUTPUT" diff --git a/.github/workflows/automation-benchmark-tests.yml b/.github/workflows/automation-benchmark-tests.yml index 3a826f523a0..9a4a127dede 100644 --- a/.github/workflows/automation-benchmark-tests.yml +++ b/.github/workflows/automation-benchmark-tests.yml @@ -20,22 +20,17 @@ on: required: true default: benchmark type: string - team: - description: Team to run the tests for (e.g. BIX, CCIP) - required: true - type: string jobs: run-e2e-tests-workflow: name: Run E2E Tests - uses: smartcontractkit/.github/.github/workflows/run-e2e-tests.yml@0d4a2b2b009c87b5c366d0b97f7a8d7de2f60760 + uses: smartcontractkit/.github/.github/workflows/run-e2e-tests.yml@5412507526722a7b1c5d719fa686eed5a1bc4035 # ctf-run-tests@0.2.0 with: test_path: .github/e2e-tests.yml test_ids: '${{ inputs.testType }}/automation_test.go:TestAutomationBenchmark' test_config_override_path: ${{ inputs.test_config_override_path }} SLACK_USER: ${{ inputs.slackMemberID }} SLACK_CHANNEL: C03KJ5S7KEK - team: ${{ inputs.team }} secrets: QA_AWS_REGION: ${{ secrets.QA_AWS_REGION }} QA_AWS_ROLE_TO_ASSUME: ${{ secrets.QA_AWS_ROLE_TO_ASSUME }} diff --git a/.github/workflows/automation-load-tests.yml b/.github/workflows/automation-load-tests.yml index c11e353a7db..24c7017ee9a 100644 --- a/.github/workflows/automation-load-tests.yml +++ b/.github/workflows/automation-load-tests.yml @@ -14,23 +14,18 @@ on: description: Notifies test results (Not your @) required: true default: U02Q14G80TY - type: string - team: - description: Team to run the tests for (e.g. BIX, CCIP) - required: true - type: string + type: string jobs: run-e2e-tests-workflow: name: Run E2E Tests - uses: smartcontractkit/.github/.github/workflows/run-e2e-tests.yml@0d4a2b2b009c87b5c366d0b97f7a8d7de2f60760 + uses: smartcontractkit/.github/.github/workflows/run-e2e-tests.yml@5412507526722a7b1c5d719fa686eed5a1bc4035 # ctf-run-tests@0.2.0 with: test_path: .github/e2e-tests.yml test_ids: 'load/automationv2_1/automationv2_1_test.go:TestLogTrigger' test_config_override_path: ${{ inputs.test_config_override_path }} SLACK_USER: ${{ inputs.slackMemberID }} SLACK_CHANNEL: C03KJ5S7KEK - team: ${{ inputs.team }} secrets: QA_AWS_REGION: ${{ secrets.QA_AWS_REGION }} QA_AWS_ROLE_TO_ASSUME: ${{ secrets.QA_AWS_ROLE_TO_ASSUME }} diff --git a/.github/workflows/automation-ondemand-tests.yml b/.github/workflows/automation-ondemand-tests.yml index eef02dcddb2..c72715bf9db 100644 --- a/.github/workflows/automation-ondemand-tests.yml +++ b/.github/workflows/automation-ondemand-tests.yml @@ -38,11 +38,7 @@ on: with_existing_remote_runner_version: description: 'Tag of the existing remote runner version to use (Leave empty to build from head/ref)' required: false - type: string - team: - description: Team to run the tests for (e.g. BIX, CCIP) - required: true - type: string + type: string jobs: # Set tests to run based on the workflow inputs @@ -157,7 +153,7 @@ jobs: call-run-e2e-tests-workflow: name: Run E2E Tests needs: set-tests-to-run - uses: smartcontractkit/.github/.github/workflows/run-e2e-tests.yml@0d4a2b2b009c87b5c366d0b97f7a8d7de2f60760 + uses: smartcontractkit/.github/.github/workflows/run-e2e-tests.yml@5412507526722a7b1c5d719fa686eed5a1bc4035 # ctf-run-tests@0.2.0 with: test_path: .github/e2e-tests.yml test_list: ${{ needs.set-tests-to-run.outputs.test_list }} @@ -165,7 +161,6 @@ jobs: with_existing_remote_runner_version: ${{ github.event.inputs.with_existing_remote_runner_version }} test_log_upload_on_failure: true test_log_upload_retention_days: 7 - team: ${{ inputs.team }} secrets: QA_AWS_REGION: ${{ secrets.QA_AWS_REGION }} QA_AWS_ROLE_TO_ASSUME: ${{ secrets.QA_AWS_ROLE_TO_ASSUME }} diff --git a/.github/workflows/build-publish-develop-pr.yml b/.github/workflows/build-publish-develop-pr.yml index 92d9e0445a6..68075422adf 100644 --- a/.github/workflows/build-publish-develop-pr.yml +++ b/.github/workflows/build-publish-develop-pr.yml @@ -2,9 +2,9 @@ name: "Build and Publish GoReleaser" on: pull_request: - # The default types are opened, synchronize, and reopened - # See https://docs.github.com/en/actions/writing-workflows/choosing-when-your-workflow-runs/events-that-trigger-workflows#pull_request - # We add a label trigger too, since when the build-publish label is added to a PR, we want to build and publish + # The default types are opened, synchronize, and reopened + # See https://docs.github.com/en/actions/writing-workflows/choosing-when-your-workflow-runs/events-that-trigger-workflows#pull_request + # We add a label trigger too, since when the build-publish label is added to a PR, we want to build and publish types: - opened - synchronize @@ -28,41 +28,49 @@ env: # a commit is pushed to develop before merge is run. CHECKOUT_REF: ${{ github.event.inputs.git_ref || github.sha }} + jobs: - image-tag: + merge: runs-on: ubuntu-latest - outputs: - image-tag: ${{ steps.get-image-tag.outputs.image-tag }} - release-type: ${{ steps.get-image-tag.outputs.release-type }} + needs: [split, image-tag] + if: ${{ needs.image-tag.outputs.release-type == 'nightly' }} + permissions: + id-token: write + contents: read steps: - name: Checkout repository uses: actions/checkout@v4.2.1 with: ref: ${{ env.CHECKOUT_REF }} - - name: Get image tag - id: get-image-tag - run: | - short_sha=$(git rev-parse --short HEAD) - echo "release-type=snapshot" | tee -a $GITHUB_OUTPUT - if [[ ${{ github.event_name }} == 'push' ]]; then - echo "image-tag=develop" | tee -a $GITHUB_OUTPUT - echo "release-type=nightly" | tee -a $GITHUB_OUTPUT - elif [[ ${{ github.event_name }} == 'workflow_dispatch' ]]; then - echo "image-tag=${short_sha}" | tee -a $GITHUB_OUTPUT - if [[ "${{ inputs.build-publish }}" == 'false' ]]; then - echo "release-type=snapshot" | tee -a $GITHUB_OUTPUT - else - echo "release-type=nightly" | tee -a $GITHUB_OUTPUT - fi - else - if [[ ${{ github.event_name }} == "pull_request" ]]; then - echo "image-tag=pr-${{ github.event.number }}-${short_sha}" | tee -a $GITHUB_OUTPUT - if [[ ${{ contains(github.event.pull_request.labels.*.name, 'build-publish') }} == "true" ]]; then - echo "release-type=nightly" | tee -a $GITHUB_OUTPUT - fi - fi - fi + - name: Configure aws credentials + uses: aws-actions/configure-aws-credentials@e3dd6a429d7300a6a4c196c26e071d42e0343502 # v4.0.2 + with: + role-to-assume: ${{ secrets.AWS_OIDC_IAM_ROLE_BUILD_PUBLISH_DEVELOP_PR }} + aws-region: ${{ secrets.AWS_REGION }} + mask-aws-account-id: true + role-session-name: "merge" + + - uses: actions/cache/restore@v4.1.1 + with: + path: dist/linux_amd64_v1 + key: chainlink-amd64-${{ github.sha }} + fail-on-cache-miss: true + + - uses: actions/cache/restore@v4.1.1 + with: + path: dist/linux_arm64_v8.0 + key: chainlink-arm64-${{ github.sha }} + fail-on-cache-miss: true + + - name: Merge images for both architectures + uses: ./.github/actions/goreleaser-build-sign-publish + with: + docker-registry: ${{ secrets.AWS_SDLC_ECR_HOSTNAME }} + docker-image-tag: ${{ needs.image-tag.outputs.image-tag }} + goreleaser-release-type: "merge" + goreleaser-config: .goreleaser.develop.yaml + goreleaser-key: ${{ secrets.GORELEASER_KEY }} split: name: "split-${{ matrix.goarch }}" @@ -105,7 +113,7 @@ jobs: - name: Build images for ${{ matrix.goarch }} uses: ./.github/actions/goreleaser-build-sign-publish - if: github.event_name == 'workflow_dispatch' || steps.cache.outputs.cache-hit != 'true' + if: steps.cache.outputs.cache-hit != 'true' with: docker-registry: ${{ secrets.AWS_SDLC_ECR_HOSTNAME }} docker-image-tag: ${{ needs.image-tag.outputs.image-tag }} @@ -113,44 +121,37 @@ jobs: goreleaser-config: .goreleaser.develop.yaml goreleaser-key: ${{ secrets.GORELEASER_KEY }} - merge: + image-tag: runs-on: ubuntu-latest - needs: [split, image-tag] - if: ${{ needs.image-tag.outputs.release-type == 'nightly' }} - permissions: - id-token: write - contents: read + outputs: + image-tag: ${{ steps.get-image-tag.outputs.image-tag }} + release-type: ${{ steps.get-image-tag.outputs.release-type }} steps: - name: Checkout repository uses: actions/checkout@v4.2.1 with: ref: ${{ env.CHECKOUT_REF }} - - name: Configure aws credentials - uses: aws-actions/configure-aws-credentials@e3dd6a429d7300a6a4c196c26e071d42e0343502 # v4.0.2 - with: - role-to-assume: ${{ secrets.AWS_OIDC_IAM_ROLE_BUILD_PUBLISH_DEVELOP_PR }} - aws-region: ${{ secrets.AWS_REGION }} - mask-aws-account-id: true - role-session-name: "merge" - - - uses: actions/cache/restore@v4.1.1 - with: - path: dist/linux_amd64_v1 - key: chainlink-amd64-${{ github.sha }} - fail-on-cache-miss: true - - - uses: actions/cache/restore@v4.1.1 - with: - path: dist/linux_arm64_v8.0 - key: chainlink-arm64-${{ github.sha }} - fail-on-cache-miss: true - - - name: Merge images for both architectures - uses: ./.github/actions/goreleaser-build-sign-publish - with: - docker-registry: ${{ secrets.AWS_SDLC_ECR_HOSTNAME }} - docker-image-tag: ${{ needs.image-tag.outputs.image-tag }} - goreleaser-release-type: "merge" - goreleaser-config: .goreleaser.develop.yaml - goreleaser-key: ${{ secrets.GORELEASER_KEY }} + - name: Get image tag + id: get-image-tag + run: | + short_sha=$(git rev-parse --short HEAD) + echo "release-type=snapshot" | tee -a $GITHUB_OUTPUT + if [[ ${{ github.event_name }} == 'push' ]]; then + echo "image-tag=develop" | tee -a $GITHUB_OUTPUT + echo "release-type=nightly" | tee -a $GITHUB_OUTPUT + elif [[ ${{ github.event_name }} == 'workflow_dispatch' ]]; then + echo "image-tag=${short_sha}" | tee -a $GITHUB_OUTPUT + if [[ "${{ inputs.build-publish }}" == 'false' ]]; then + echo "release-type=snapshot" | tee -a $GITHUB_OUTPUT + else + echo "release-type=nightly" | tee -a $GITHUB_OUTPUT + fi + else + if [[ ${{ github.event_name }} == "pull_request" ]]; then + echo "image-tag=pr-${{ github.event.number }}-${short_sha}" | tee -a $GITHUB_OUTPUT + if [[ ${{ contains(github.event.pull_request.labels.*.name, 'build-publish') }} == "true" ]]; then + echo "release-type=nightly" | tee -a $GITHUB_OUTPUT + fi + fi + fi diff --git a/.github/workflows/build-publish.yml b/.github/workflows/build-publish.yml index 2889ee5e5ea..3d7e925dba0 100644 --- a/.github/workflows/build-publish.yml +++ b/.github/workflows/build-publish.yml @@ -7,48 +7,18 @@ on: env: ECR_HOSTNAME: public.ecr.aws + ECR_IMAGE_NAME: chainlink/chainlink jobs: checks: name: "Checks" runs-on: ubuntu-20.04 - outputs: - git-tag-type: ${{ steps.check-git-tag-type.outputs.git-tag-type }} - ecr-image-name: ${{ steps.check-git-tag-type.outputs.ecr-image-name }} steps: - name: Checkout repository uses: actions/checkout@v4.2.1 - - name: Check git tag type - id: check-git-tag-type - shell: bash - env: - GIT_TAG: ${{ github.ref_name}} - run: | - # Check if git tag is related to CCIP - # Should match: - # v1.0.0-ccip1.0.0-beta.1 - # v1.0.0-ccip1.0.0-rc.0 - # v1.0.0-ccip1.0.0 - if [[ $GIT_TAG =~ ^v[0-9]+\.[0-9]+\.[0-9]+-ccip[0-9]+\.[0-9]+\.[0-9]+(-((beta|rc)\.[0-9]+))?$ ]]; then - echo "git-tag-type=ccip" | tee -a "$GITHUB_OUTPUT" - echo "ecr-image-name=chainlink/ccip" | tee -a "$GITHUB_OUTPUT" - else - echo "git-tag-type=core" | tee -a "$GITHUB_OUTPUT" - echo "ecr-image-name=chainlink/chainlink" | tee -a "$GITHUB_OUTPUT" - fi - - name: Fail if CCIP release has wrong version - if: ${{ steps.check-git-tag-type.outputs.git-tag-type == 'ccip' }} - run: | - version=$(jq -r '.version' ./package.json) - echo "Package version: $version" - echo "Git tag type: ${{ steps.check-git-tag-type.outputs.git-tag-type }}" - if [[ $version != *"-ccip"* ]]; then - echo "Error: Version '$version' does not match required CCIP format." - exit 1 - fi - name: Check for VERSION file bump on tags - # Avoids checking VERSION file bump on forks or from CCIP releases. - if: ${{ github.repository == 'smartcontractkit/chainlink' && steps.check-git-tag-type.outputs.git-tag-type == 'core' }} + # Avoids checking VERSION file bump on forks. + if: ${{ github.repository == 'smartcontractkit/chainlink' }} uses: ./.github/actions/version-file-bump with: github-token: ${{ secrets.GITHUB_TOKEN }} @@ -77,7 +47,7 @@ jobs: aws-role-duration-seconds: ${{ secrets.AWS_ROLE_DURATION_SECONDS }} aws-region: ${{ secrets.AWS_REGION }} ecr-hostname: ${{ env.ECR_HOSTNAME }} - ecr-image-name: ${{ needs.checks.outputs.ecr-image-name }} + ecr-image-name: ${{ env.ECR_IMAGE_NAME }} dockerhub_username: ${{ secrets.DOCKERHUB_READONLY_USERNAME }} dockerhub_password: ${{ secrets.DOCKERHUB_READONLY_PASSWORD }} sign-images: true @@ -87,13 +57,13 @@ jobs: uses: actions/attest-build-provenance@6149ea5740be74af77f260b9db67e633f6b0a9a1 # v1.4.2 with: subject-digest: ${{ steps.build-sign-publish.outputs.docker-image-digest }} - subject-name: ${{ env.ECR_HOSTNAME }}/${{ needs.checks.outputs.ecr-image-name }} + subject-name: ${{ env.ECR_HOSTNAME }}/${{ env.ECR_IMAGE_NAME }} push-to-registry: true # Notify Slack channel for new git tags. slack-notify: if: github.ref_type == 'tag' - needs: [checks, build-sign-publish-chainlink] + needs: [build-sign-publish-chainlink] runs-on: ubuntu-24.04 environment: build-publish steps: @@ -121,7 +91,7 @@ jobs: format( '{0}/{1}:{2}', env.ECR_HOSTNAME, - needs.checks.outputs.ecr-image-name, + env.ECR_IMAGE_NAME, needs.build-sign-publish-chainlink.outputs.docker-image-tag ) || '' }} diff --git a/.github/workflows/ccip-chaos-tests.yml b/.github/workflows/ccip-chaos-tests.yml index 51e6c6f027a..14754ee5283 100644 --- a/.github/workflows/ccip-chaos-tests.yml +++ b/.github/workflows/ccip-chaos-tests.yml @@ -6,12 +6,6 @@ on: # types: [ completed ] # branches: [ develop ] workflow_dispatch: - inputs: - team: - description: Team to run the tests for (e.g. BIX, CCIP) - required: true - default: "ccip" - type: string # Only run 1 of this workflow at a time per PR concurrency: @@ -21,8 +15,7 @@ concurrency: jobs: run-e2e-tests-workflow: name: Run E2E Tests - uses: smartcontractkit/.github/.github/workflows/run-e2e-tests.yml@0d4a2b2b009c87b5c366d0b97f7a8d7de2f60760 - with: + uses: smartcontractkit/.github/.github/workflows/run-e2e-tests.yml@5412507526722a7b1c5d719fa686eed5a1bc4035 # ctf-run-tests@0.2.0 test_path: .github/e2e-tests.yml chainlink_version: ${{ github.sha }} require_chainlink_image_versions_in_qa_ecr: ${{ github.sha }} @@ -31,7 +24,6 @@ jobs: slack_notification_after_tests: on_failure slack_notification_after_tests_channel_id: '#ccip-testing' slack_notification_after_tests_name: CCIP Chaos E2E Tests - team: ${{ inputs.team }} secrets: QA_AWS_REGION: ${{ secrets.QA_AWS_REGION }} QA_AWS_ROLE_TO_ASSUME: ${{ secrets.QA_AWS_ROLE_TO_ASSUME }} diff --git a/.github/workflows/ccip-load-tests.yml b/.github/workflows/ccip-load-tests.yml index d1733147443..4f5b7ac509c 100644 --- a/.github/workflows/ccip-load-tests.yml +++ b/.github/workflows/ccip-load-tests.yml @@ -21,12 +21,7 @@ on: chainlink_version: description: Chainlink image version to use. Commit sha if not provided required: false - type: string - team: - description: Team to run the tests for (e.g. BIX, CCIP) - required: true - default: "ccip" - type: string + type: string # Only run 1 of this workflow at a time per PR concurrency: @@ -36,7 +31,7 @@ concurrency: jobs: run-e2e-tests-workflow: name: Run E2E Tests - uses: smartcontractkit/.github/.github/workflows/run-e2e-tests.yml@0d4a2b2b009c87b5c366d0b97f7a8d7de2f60760 + uses: smartcontractkit/.github/.github/workflows/run-e2e-tests.yml@5412507526722a7b1c5d719fa686eed5a1bc4035 # ctf-run-tests@0.2.0 with: test_path: .github/e2e-tests.yml test_trigger: E2E CCIP Load Tests @@ -46,7 +41,6 @@ jobs: slack_notification_after_tests_channel_id: '#ccip-testing' slack_notification_after_tests_name: CCIP E2E Load Tests test_image_suites: ccip-load - team: ${{ inputs.team }} secrets: QA_AWS_REGION: ${{ secrets.QA_AWS_REGION }} QA_AWS_ROLE_TO_ASSUME: ${{ secrets.QA_AWS_ROLE_TO_ASSUME }} diff --git a/.github/workflows/changeset.yml b/.github/workflows/changeset.yml index d6d269326c7..19d17ddb588 100644 --- a/.github/workflows/changeset.yml +++ b/.github/workflows/changeset.yml @@ -162,48 +162,3 @@ jobs: run: | echo "Please include at least one tag in the core changeset file" exit 1 - - contracts-changeset: - name: Contracts Changeset Checker - runs-on: ubuntu-latest - steps: - - name: Checkout repository - uses: actions/checkout@v4.2.1 - with: - fetch-depth: 0 - - - uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2 - id: files-changed - with: - predicate-quantifier: every - list-files: shell - filters: | - contracts-changeset: - - added|modified: 'contracts/.changeset/*.md' - - - name: Setup node - uses: ./.github/actions/setup-nodejs - if: ${{ steps.files-changed.outputs.contracts-changeset == 'true' }} - - - name: Install base dependencies - if: ${{ steps.files-changed.outputs.contracts-changeset == 'true' }} - run: pnpm i - - - name: Validate changeset files - if: ${{ steps.files-changed.outputs.contracts-changeset == 'true' }} - working-directory: contracts - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - run: | - pnpm changeset version - - - name: Comment Failure - if: ${{ failure() && steps.files-changed.outputs.contracts-changeset == 'true' }} - uses: thollander/actions-comment-pull-request@fabd468d3a1a0b97feee5f6b9e499eab0dd903f6 # v2.5.0 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - with: - message: | - It appears that the changeset file you've added or modified in `contracts/.changeset` is not valid. - Please delete the file and run `pnpm changeset` in the contracts directory. - diff --git a/.github/workflows/ci-core-partial.yml b/.github/workflows/ci-core-partial.yml deleted file mode 100644 index b652ca51a62..00000000000 --- a/.github/workflows/ci-core-partial.yml +++ /dev/null @@ -1,288 +0,0 @@ -name: Experimental Test Optimization - -on: - push: - branches: - - develop - # - "release/*" - # merge_group: - pull_request: - schedule: - - cron: "0 1 * * *" - -env: - # We explicitly have this env var not be "CL_DATABASE_URL" to avoid having it be used by core related tests - # when they should not be using it, while still allowing us to DRY up the setup - DB_URL: postgresql://postgres:postgres@localhost:5432/chainlink_test?sslmode=disable - -jobs: - filter: - name: Detect Changes - permissions: - pull-requests: read - outputs: - should-run-all-tests: ${{ steps.match-some.outputs.test-data == 'true' }} - should-collect-coverage: ${{ github.event_name == 'schedule' }} - runs-on: ubuntu-latest - steps: - - name: Checkout the repo - uses: actions/checkout@v4.2.1 - with: - repository: smartcontractkit/chainlink - - uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2 - id: match-some - with: - # "if any changed file matches one or more of the conditions" (https://github.com/dorny/paths-filter/issues/225) - predicate-quantifier: some - # test-data - any changes to any testdata files/paths - filters: | - test-data: - - '**/testdata/**' - - run-unit-tests: - name: Tests (${{ matrix.type.test-suite }}) - needs: filter - runs-on: ubuntu22.04-32cores-128GB - permissions: - id-token: write - contents: write - actions: write - strategy: - fail-fast: false - matrix: - type: - - test-suite: "core" - module-directory: "./" - build-flags: "-tags=integration" - - test-suite: "ccip-deployment" - module-directory: "./deployment" - steps: - - name: Checkout the repo - uses: actions/checkout@v4.2.1 - - - name: Setup NodeJS - uses: ./.github/actions/setup-nodejs - with: - prod: "true" - - - name: Setup Go - uses: ./.github/actions/setup-go - with: - build-cache-version: ${{ matrix.type.test-suite }} - restore-build-cache-only: "false" - - - name: Setup Solana - uses: ./.github/actions/setup-solana - - - name: Setup wasmd - uses: ./.github/actions/setup-wasmd - - - name: Setup Postgres - uses: ./.github/actions/setup-postgres - - - name: Setup CI Core Environment - uses: ./.github/actions/setup-ci-core-tests - with: - db-url: ${{ env.DB_URL }} - go-mod-download-directory: ${{ matrix.type.test-suite == 'ccip-deployment' && matrix.type.module-directory || '' }} - - - name: Build Tests - uses: smartcontractkit/.github/apps/go-conditional-tests@57f99fbea73056c490c766d50ef582a13ec4f3bb # go-conditional-tests@0.2.0 - timeout-minutes: 10 - with: - pipeline-step: "build" - build-concurrency: "32" - collect-coverage: ${{ needs.filter.outputs.should-collect-coverage }} - test-suite: ${{ matrix.type.test-suite }} - module-directory: ${{ matrix.type.module-directory }} - github-token: ${{ secrets.GITHUB_TOKEN }} - build-flags: ${{ matrix.type.build-flags }} - - - name: Run Tests - uses: smartcontractkit/.github/apps/go-conditional-tests@57f99fbea73056c490c766d50ef582a13ec4f3bb # go-conditional-tests@0.2.0 - timeout-minutes: 15 - env: - CL_DATABASE_URL: ${{ env.DB_URL }} - with: - pipeline-step: "run" - run-concurrency: "16" - run-all-tests: ${{ needs.filter.outputs.should-run-all-tests }} - collect-coverage: ${{ needs.filter.outputs.should-collect-coverage }} - test-suite: ${{ matrix.type.test-suite }} - module-directory: ${{ matrix.type.module-directory }} - github-token: ${{ secrets.GITHUB_TOKEN }} - - - name: Update Test Index - uses: smartcontractkit/.github/apps/go-conditional-tests@57f99fbea73056c490c766d50ef582a13ec4f3bb # go-conditional-tests@0.2.0 - with: - pipeline-step: "update" - collect-coverage: ${{ needs.filter.outputs.should-collect-coverage }} - test-suite: ${{ matrix.type.test-suite }} - github-token: ${{ secrets.GITHUB_TOKEN }} - - - name: Print postgres logs - if: ${{ always() }} - run: docker compose logs postgres | tee ../../../postgres_logs.txt - working-directory: ./.github/actions/setup-postgres - - scan: - name: SonarQube Scan - needs: [run-unit-tests, filter] - if: ${{ needs.filter.outputs.should-collect-coverage == 'true' }} - runs-on: ubuntu-latest - steps: - - name: Checkout the repo - uses: actions/checkout@v4.2.1 - with: - # fetches all history for all tags and branches to provide more metadata for sonar reports - fetch-depth: 0 - - - name: Download all workflow run artifacts - uses: actions/download-artifact@v4.1.8 - with: - path: coverage - pattern: coverage-* - merge-multiple: true - - - name: Check and Set SonarQube Report Paths - shell: bash - run: | - ARGS="" - sonarqube_coverage_report_paths=$(find ./coverage -name '*.cover.out' | paste -sd "," -) - - # TODO uncomment when linting in enabled - # Check and assign paths for lint reports - # if [ -d "golangci-lint-report" ]; then - # sonarqube_lint_report_paths=$(find golangci-lint-report -name 'golangci-lint-report.xml' | paste -sd "," -) - # else - # sonarqube_lint_report_paths="" - # fi - # if [[ -z "$sonarqube_lint_report_paths" ]]; then - # echo "::warning::No lint report paths found, will not pass to sonarqube" - # else - # echo "Found lint report paths: $sonarqube_lint_report_paths" - # ARGS="$ARGS -Dsonar.go.golangci-lint.reportPaths=$sonarqube_lint_report_paths" - # fi - - if [[ -z "$sonarqube_coverage_report_paths" ]]; then - echo "::warning::No coverage report paths found, will not pass to sonarqube" - else - echo "Found coverage report paths: $sonarqube_coverage_report_paths" - ARGS="$ARGS -Dsonar.go.coverage.reportPaths=$sonarqube_coverage_report_paths" - fi - - echo "Final SONARQUBE_ARGS: $ARGS" - echo "SONARQUBE_ARGS=$ARGS" >> $GITHUB_ENV - - - name: SonarQube Scan - if: ${{ env.SONARQUBE_ARGS != '' }} - uses: sonarsource/sonarqube-scan-action@aecaf43ae57e412bd97d70ef9ce6076e672fe0a9 # v2.3.0 - with: - args: ${{ env.SONARQUBE_ARGS }} - env: - SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} - SONAR_HOST_URL: ${{ secrets.SONAR_HOST_URL }} - SONAR_SCANNER_OPTS: "-Xms6g -Xmx8g" - - run-fuzz-tests: - name: Tests (fuzz) - runs-on: ubuntu22.04-32cores-128GB - if: ${{ github.event_name == 'schedule' }} - steps: - - name: Checkout the repo - uses: actions/checkout@v4.2.1 - - - name: Setup Go - uses: ./.github/actions/setup-go - with: - build-cache-version: "fuzz" - restore-build-cache-only: "true" - - - name: Setup Solana - uses: ./.github/actions/setup-solana - - - name: Setup wasmd - uses: ./.github/actions/setup-wasmd - - - name: Setup Postgres - uses: ./.github/actions/setup-postgres - - - name: Setup CI Core Environment - uses: ./.github/actions/setup-ci-core-tests - with: - db-url: ${{ env.DB_URL }} - - - name: Increase Timeouts - if: ${{ github.event_name == 'schedule'}} - run: | - echo "FUZZ_TIMEOUT_MINUTES=10">> $GITHUB_ENV - - - name: Run Fuzz Tests - env: - OUTPUT_FILE: ./output.txt - CL_DATABASE_URL: ${{ env.DB_URL }} - run: ./tools/bin/go_core_fuzz ./... - - - name: Print postgres logs - if: ${{ always() }} - run: docker compose logs postgres | tee ../../../postgres_logs.txt - working-directory: ./.github/actions/setup-postgres - - run-race-tests: - name: Tests (race) - runs-on: ubuntu22.04-32cores-128GB - if: ${{ github.event_name == 'schedule' }} - steps: - - name: Checkout the repo - uses: actions/checkout@v4.2.1 - - - name: Setup Go - uses: ./.github/actions/setup-go - with: - build-cache-version: "race" - restore-build-cache-only: "true" - - - name: Setup Solana - uses: ./.github/actions/setup-solana - - - name: Setup wasmd - uses: ./.github/actions/setup-wasmd - - - name: Setup Postgres - uses: ./.github/actions/setup-postgres - - - name: Setup CI Core Environment - uses: ./.github/actions/setup-ci-core-tests - with: - db-url: ${{ env.DB_URL }} - - - name: Increase Timeouts - if: ${{ github.event_name == 'schedule'}} - run: | - echo "TIMEOUT=10m" >> $GITHUB_ENV - echo "COUNT=50" >> $GITHUB_ENV - - - name: Run Race Tests - env: - OUTPUT_FILE: ./output.txt - CL_DATABASE_URL: ${{ env.DB_URL }} - run: ./tools/bin/go_core_race_tests ./... - - - name: Print Races - id: print-races - if: ${{ failure() }} - run: | - find race.* | xargs cat > race.txt - if [[ -s race.txt ]]; then - cat race.txt - echo "post_to_slack=true" >> $GITHUB_OUTPUT - else - echo "post_to_slack=false" >> $GITHUB_OUTPUT - fi - echo "github.event_name: ${{ github.event_name }}" - echo "github.ref: ${{ github.ref }}" - - - name: Print postgres logs - if: ${{ always() }} - run: docker compose logs postgres | tee ../../../postgres_logs.txt - working-directory: ./.github/actions/setup-postgres diff --git a/.github/workflows/ci-core.yml b/.github/workflows/ci-core.yml index cf9d525a846..48977cee35e 100644 --- a/.github/workflows/ci-core.yml +++ b/.github/workflows/ci-core.yml @@ -33,9 +33,7 @@ jobs: permissions: pull-requests: read outputs: - affected-packages: ${{ steps.resolved-modules.outputs.module_names }} deployment-changes: ${{ steps.match-some.outputs.deployment == 'true' }} - scripts-changes: ${{ steps.match-some.outputs.scripts == 'true' }} should-run-ci-core: ${{ steps.match-some.outputs.core-ci == 'true' || steps.match-every.outputs.non-ignored == 'true' || github.event_name == 'workflow_dispatch' || github.event_name == 'schedule' }} should-run-golangci: ${{ steps.match-some.outputs.golang-ci == 'true' || steps.match-every.outputs.non-ignored == 'true' || github.event_name == 'workflow_dispatch' }} runs-on: ubuntu-latest @@ -49,8 +47,7 @@ jobs: with: # "if any changed file matches one or more of the conditions" (https://github.com/dorny/paths-filter/issues/225) predicate-quantifier: some - # deployment - any changes to files in the `deployments/` - # scripts - any changes to files in the `core/scripts/` + # deployment - any changes to files in `deployments/` # core-ci - any changes that could affect this workflow definition # golang-ci - any changes that could affect the linting result filters: | @@ -63,8 +60,6 @@ jobs: - '.golangci.yml' - '.github/workflows/ci-core.yml' - '.github/actions/**' - scripts: - - 'core/scripts/**' - uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2 id: match-every with: @@ -72,18 +67,14 @@ jobs: predicate-quantifier: every # non-integration-tests - only changes made outside of the `integration-tests` directory # non-ignored - only changes except for the negated ones - # all - changes in any directory # - This is opt-in on purpose. To be safe, new files are assumed to have an affect on CI Core unless listed here specifically. - # Enable listing of files matching each filter. - # Paths to files will be available in `${FILTER_NAME}_files` output variable. - # Paths will be formatted as JSON array - list-files: json filters: | non-integration-tests: - '**' - '!integration-tests/**' non-ignored: - '**' + - '!docs/**' - '!integration-tests/**' - '!tools/secrets/**' - '!tools/goreleaser-config/**' @@ -100,39 +91,24 @@ jobs: - '!nix-darwin-shell-hook.sh' - '!LICENSE' - '!.github/**' - all: - - '**' - - - name: Resolve affected files to affected modules - id: resolved-modules - shell: bash - run: | - # Ensure the step uses `with.list-files: json` to get the list of files in JSON format - bash ./.github/scripts/map-affected-files-to-modules.sh '${{ steps.match-every.outputs.all_files }}' - + golangci: - name: GolangCI Lint - needs: [filter, run-frequency] - # We don't directly merge dependabot PRs to not waste the resources. + # We don't directly merge dependabot PRs, so let's not waste the resources if: ${{ (github.event_name == 'pull_request' || github.event_name == 'schedule') && github.actor != 'dependabot[bot]' }} + name: lint permissions: - # To annotate code in the PR. + # For golangci-lint-actions to annotate code in the PR. checks: write contents: read # For golangci-lint-action's `only-new-issues` option. pull-requests: read runs-on: ubuntu-24.04-8cores-32GB-ARM - strategy: - fail-fast: false - matrix: - modules: ${{ fromJson(needs.filter.outputs.affected-packages) }} + needs: [filter, run-frequency] steps: - - name: Checkout - uses: actions/checkout@v4.2.1 - - name: Golang Lint (${{ matrix.modules }}) + - uses: actions/checkout@v4.2.1 + - name: Golang Lint uses: ./.github/actions/golangci-lint - with: - go-directory: ${{ matrix.modules }} + if: ${{ needs.filter.outputs.should-run-golangci == 'true' }} - name: Notify Slack if: ${{ failure() && needs.run-frequency.outputs.one-per-day-frequency == 'true' }} uses: slackapi/slack-github-action@6c661ce58804a1a20f6dc5fbee7f0381b469e001 # v1.25.0 @@ -141,22 +117,6 @@ jobs: with: channel-id: "#team-core" slack-message: "golangci-lint failed: \n${{ format('https://github.com/{0}/actions/runs/{1}', github.repository, github.run_id) }}" - - # Fails if any golangci-lint matrix jobs fails and silently succeeds otherwise - # Consolidates golangci-lint matrix job results under one required `lint` check - # Inclusive check: all (new) modules are analyzed, but no need to enable "required" checks for each one - golangci-matrix-results-validation: - name: lint - needs: [golangci] - # We don't directly merge dependabot PRs to not waste the resources. - if: ${{ (github.event_name == 'pull_request' || github.event_name == 'schedule') && github.actor != 'dependabot[bot]' }} - runs-on: ubuntu-latest - steps: - - name: Check Golangci-lint Matrix Results - if: ${{ needs.golangci.result != 'success' }} - run: | - echo "At least one 'GolangCI Lint' matrix job failed. Check the failed lint jobs." - exit 1 core: env: @@ -176,11 +136,11 @@ jobs: - cmd: go_core_ccip_deployment_tests os: ubuntu22.04-32cores-128GB printResults: true - - cmd: go_core_fuzz - os: ubuntu22.04-8cores-32GB - cmd: go_core_race_tests # use 64cores for certain scheduled runs only os: ${{ needs.run-frequency.outputs.two-per-day-frequency == 'true' && 'ubuntu-latest-64cores-256GB' || 'ubuntu-latest-32cores-128GB' }} + - cmd: go_core_fuzz + os: ubuntu22.04-8cores-32GB name: Core Tests (${{ matrix.type.cmd }}) # We don't directly merge dependabot PRs, so let's not waste the resources if: ${{ github.actor != 'dependabot[bot]' }} @@ -271,14 +231,26 @@ jobs: echo "COUNT=50" >> $GITHUB_ENV echo "FUZZ_TIMEOUT_MINUTES=10">> $GITHUB_ENV + - name: Install gotestloghelper + if: ${{ needs.filter.outputs.should-run-ci-core == 'true' }} + run: go install github.com/smartcontractkit/chainlink-testing-framework/tools/gotestloghelper@v1.50.0 + - name: Run tests if: ${{ needs.filter.outputs.should-run-ci-core == 'true' }} id: run-tests env: OUTPUT_FILE: ./output.txt + USE_TEE: false CL_DATABASE_URL: ${{ env.DB_URL }} run: ./tools/bin/${{ matrix.type.cmd }} ./... + - name: Print Filtered Test Results + if: ${{ failure() && needs.filter.outputs.should-run-ci-core == 'true' && steps.run-tests.conclusion == 'failure' }} + run: | + if [[ "${{ matrix.type.printResults }}" == "true" ]]; then + cat output.txt | gotestloghelper -ci + fi + - name: Print Races id: print-races if: ${{ failure() && matrix.type.cmd == 'go_core_race_tests' && needs.filter.outputs.should-run-ci-core == 'true' }} @@ -325,38 +297,8 @@ jobs: channel-id: "#topic-data-races" slack-message: "Race tests failed: \n${{ format('https://github.com/{0}/actions/runs/{1}', github.repository, github.run_id) }}" - core-scripts-tests: - name: test-scripts - needs: [filter] - runs-on: ubuntu-latest - if: ${{ github.event_name == 'schedule' || needs.filter.outputs.scripts-changes == 'true' }} - steps: - - name: Checkout - uses: actions/checkout@v4.2.1 - - - name: Setup Go - uses: ./.github/actions/setup-go - with: - go-version-file: core/scripts/go.mod - go-module-file: core/scripts/go.sum - - - name: Run Tests - env: - OUTPUT_FILE: ./output.txt - run: ./tools/bin/go_core_scripts_tests ./... - - - name: Store test report artifacts - if: ${{ always() && needs.filter.outputs.should-run-ci-core == 'true' }} - uses: actions/upload-artifact@v4.4.3 - with: - name: go_core_scripts_tests_logs - path: | - ./output.txt - ./coverage.txt - retention-days: 7 - detect-flakey-tests: - needs: [filter, core, core-scripts-tests] + needs: [filter, core] name: Flakey Test Detection runs-on: ubuntu-latest if: always() && (github.event_name == 'schedule' || github.event_name == 'workflow_dispatch') @@ -445,8 +387,8 @@ jobs: scan: name: SonarQube Scan - needs: [golangci, core, core-scripts-tests] - if: ${{ always() && github.actor != 'dependabot[bot]' }} + needs: [core, run-frequency] + if: ${{ always() && needs.run-frequency.outputs.four-per-day-frequency == 'true' && github.actor != 'dependabot[bot]' }} runs-on: ubuntu-latest steps: - name: Checkout the repo @@ -454,60 +396,36 @@ jobs: with: fetch-depth: 0 # fetches all history for all tags and branches to provide more metadata for sonar reports - - name: Download all workflow artifacts + - name: Download all workflow run artifacts uses: actions/download-artifact@v4.1.8 - name: Check and Set SonarQube Report Paths shell: bash run: | # Check and assign paths for coverage/test reports in go_core_tests_logs - core_artifact="go_core_tests_logs" - if [ -d "$core_artifact" ]; then - echo "Found $core_artifact" - sonarqube_coverage_report_paths=$(find "$core_artifact" -name coverage.txt | paste -sd "," -) - sonarqube_tests_report_paths=$(find "$core_artifact" -name output.txt | paste -sd "," -) - echo "Coverage report paths: $sonarqube_coverage_report_paths" - echo "Tests report paths: $sonarqube_tests_report_paths" + if [ -d "go_core_tests_logs" ]; then + sonarqube_coverage_report_paths=$(find go_core_tests_logs -name coverage.txt | paste -sd "," -) + sonarqube_tests_report_paths=$(find go_core_tests_logs -name output.txt | paste -sd "," -) else - echo "Did not find $core_artifact" sonarqube_coverage_report_paths="" sonarqube_tests_report_paths="" fi # Check and assign paths for coverage/test reports in go_core_tests_integration_logs - integration_tests_artifact="go_core_tests_integration_logs" - if [ -d "$integration_tests_artifact" ]; then - echo "Found $integration_tests_artifact" - integration_coverage_paths=$(find "$integration_tests_artifact" -name coverage.txt | paste -sd "," -) - integration_tests_paths=$(find "$integration_tests_artifact" -name output.txt | paste -sd "," -) - + if [ -d "go_core_tests_integration_logs" ]; then + integration_coverage_paths=$(find go_core_tests_integration_logs -name coverage.txt | paste -sd "," -) + integration_tests_paths=$(find go_core_tests_integration_logs -name output.txt | paste -sd "," -) # Append to existing paths if they are set, otherwise assign directly sonarqube_coverage_report_paths="${sonarqube_coverage_report_paths:+$sonarqube_coverage_report_paths,}$integration_coverage_paths" sonarqube_tests_report_paths="${sonarqube_tests_report_paths:+$sonarqube_tests_report_paths,}$integration_tests_paths" fi - # Check and assign paths for coverage/test reports in go_core_scripts_tests_logs - scripts_tests_artifact="go_core_scripts_tests_logs" - if [ -d "$scripts_tests_artifact" ]; then - echo "Found $scripts_tests_artifact" - scripts_coverage_paths=$(find "$scripts_tests_artifact" -name coverage.txt | paste -sd "," -) - scripts_tests_paths=$(find "$scripts_tests_artifact" -name output.txt | paste -sd "," -) - - # Append to existing paths if they are set, otherwise assign directly - sonarqube_coverage_report_paths="${sonarqube_coverage_report_paths:+$sonarqube_coverage_report_paths,}$scripts_coverage_paths" - sonarqube_tests_report_paths="${sonarqube_tests_report_paths:+$sonarqube_tests_report_paths,}$scripts_tests_paths" - fi - # Check and assign paths for lint reports - # To find reports in the folders named differently (because of the matrix strategy), - # We need to loop through the artifacts. It allows usage of RegExp folders (skipped if not found). - for golang_lint_artifact in golangci-lint-report* - do - echo "Found golangci-lint-report artifacts" - sonarqube_lint_report_paths=$(find -type f -name 'golangci-lint-report.xml' -printf "%p,") - echo "Lint report paths: $sonarqube_lint_report_paths" - break - done + if [ -d "golangci-lint-report" ]; then + sonarqube_lint_report_paths=$(find golangci-lint-report -name golangci-lint-report.xml | paste -sd "," -) + else + sonarqube_lint_report_paths="" + fi ARGS="" if [[ -z "$sonarqube_tests_report_paths" ]]; then @@ -545,28 +463,25 @@ jobs: SONAR_SCANNER_OPTS: "-Xms6g -Xmx8g" trigger-flaky-test-detection-for-root-project: - name: Flakeguard Root Project - uses: ./.github/workflows/flakeguard.yml + name: Find New Flaky Tests In Chainlink Project + uses: ./.github/workflows/find-new-flaky-tests.yml if: ${{ github.event_name == 'pull_request' }} with: repoUrl: 'https://github.com/smartcontractkit/chainlink' projectPath: '.' baseRef: ${{ github.base_ref }} headRef: ${{ github.head_ref }} - maxPassRatio: '1.0' + runThreshold: '0.99' findByTestFilesDiff: true findByAffectedPackages: false slackNotificationAfterTestsChannelId: 'C07TRF65CNS' #flaky-test-detector-notifications - extraArgs: '{ "skipped_tests": "TestChainComponents", "run_with_race": "true", "print_failed_tests": "true", "test_repeat_count": "3", "omit_test_outputs_on_success": "true" }' + extraArgs: '{ "skipped_tests": "TestChainComponents", "run_with_race": "true", "print_failed_tests": "true", "test_repeat_count": "3", "min_pass_ratio": "0.01" }' secrets: SLACK_BOT_TOKEN: ${{ secrets.QA_SLACK_API_KEY }} - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - FLAKEGUARD_SPLUNK_ENDPOINT: ${{ secrets.FLAKEGUARD_SPLUNK_ENDPOINT }} - FLAKEGUARD_SPLUNK_HEC: ${{ secrets.FLAKEGUARD_SPLUNK_HEC }} trigger-flaky-test-detection-for-deployment-project: - name: Flakeguard Deployment Project - uses: ./.github/workflows/flakeguard.yml + name: Find New Flaky Tests In Deployment Project + uses: ./.github/workflows/find-new-flaky-tests.yml needs: [filter] if: ${{ github.event_name == 'pull_request' && needs.filter.outputs.deployment-changes == 'true'}} with: @@ -574,17 +489,13 @@ jobs: projectPath: 'deployment' baseRef: ${{ github.base_ref }} headRef: ${{ github.head_ref }} - maxPassRatio: '1.0' + runThreshold: '0.99' findByTestFilesDiff: true findByAffectedPackages: false slackNotificationAfterTestsChannelId: 'C07TRF65CNS' #flaky-test-detector-notifications - extraArgs: '{ "skipped_tests": "TestAddLane", "run_with_race": "true", "print_failed_tests": "true", "test_repeat_count": "3", "omit_test_outputs_on_success": "true" }' + extraArgs: '{ "skipped_tests": "TestAddLane", "run_with_race": "true", "print_failed_tests": "true", "test_repeat_count": "3", "min_pass_ratio": "0.01" }' secrets: SLACK_BOT_TOKEN: ${{ secrets.QA_SLACK_API_KEY }} - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - FLAKEGUARD_SPLUNK_ENDPOINT: ${{ secrets.FLAKEGUARD_SPLUNK_ENDPOINT }} - FLAKEGUARD_SPLUNK_HEC: ${{ secrets.FLAKEGUARD_SPLUNK_HEC }} - clean: name: Clean Go Tidy & Generate @@ -615,14 +526,10 @@ jobs: make rm-mocked make generate - name: Ensure clean after generate - run: | - git add --all - git diff --stat --cached --exit-code + run: git diff --stat --exit-code - run: make gomodtidy - name: Ensure clean after tidy - run: | - git add --all - git diff --minimal --cached --exit-code + run: git diff --minimal --exit-code run-frequency: name: Scheduled Run Frequency diff --git a/.github/workflows/ci-scripts.yml b/.github/workflows/ci-scripts.yml new file mode 100644 index 00000000000..5683641f26b --- /dev/null +++ b/.github/workflows/ci-scripts.yml @@ -0,0 +1,41 @@ +name: CI Scripts + +on: + merge_group: + pull_request: + +jobs: + lint-scripts: + # We don't directly merge dependabot PRs, so let's not waste the resources + if: ${{ (github.event_name == 'pull_request' || github.event_name == 'schedule') && github.actor != 'dependabot[bot]' }} + runs-on: ubuntu-latest + permissions: + # For golangci-lint-actions to annotate code in the PR. + checks: write + contents: read + # For golangci-lint-action's `only-new-issues` option. + pull-requests: read + steps: + - uses: actions/checkout@v4.2.1 + - name: Golang Lint + uses: ./.github/actions/golangci-lint + with: + id: scripts + name: lint-scripts + go-directory: core/scripts + go-version-file: core/scripts/go.mod + go-module-file: core/scripts/go.sum + + test-scripts: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4.2.1 + - name: Setup Go + uses: ./.github/actions/setup-go + with: + go-version-file: core/scripts/go.mod + go-module-file: core/scripts/go.sum + - name: Run Tests + shell: bash + working-directory: core/scripts + run: go test ./... diff --git a/.github/workflows/client-compatibility-tests.yml b/.github/workflows/client-compatibility-tests.yml index 5f986ccf16c..03c5b893cca 100644 --- a/.github/workflows/client-compatibility-tests.yml +++ b/.github/workflows/client-compatibility-tests.yml @@ -668,6 +668,9 @@ jobs: E2E_TEST_PYROSCOPE_KEY: ${{ secrets.QA_PYROSCOPE_KEY }} E2E_TEST_PYROSCOPE_ENVIRONMENT: ci-client-compatability-${{ matrix.eth_client }}-testnet E2E_TEST_PYROSCOPE_ENABLED: "true" + E2E_TEST_LOGGING_RUN_ID: ${{ github.run_id }} + E2E_TEST_LOG_COLLECT: ${{ vars.TEST_LOG_COLLECT }} + E2E_TEST_LOG_STREAM_LOG_TARGETS: ${{ vars.LOGSTREAM_LOG_TARGETS }} E2E_TEST_PRIVATE_ETHEREUM_EXECUTION_LAYER: ${{ matrix.evm_node.eth_implementation || 'geth' }} E2E_TEST_PRIVATE_ETHEREUM_ETHEREUM_VERSION: auto_fill # Auto fill the version based on the docker image E2E_TEST_PRIVATE_ETHEREUM_CUSTOM_DOCKER_IMAGE: ${{ matrix.evm_node.docker_image }} diff --git a/.github/workflows/crib-integration-test.yml b/.github/workflows/crib-integration-test.yml index a6f995d57ba..7caa1432297 100644 --- a/.github/workflows/crib-integration-test.yml +++ b/.github/workflows/crib-integration-test.yml @@ -76,18 +76,16 @@ jobs: echo $GITHUB_WORKSPACE - name: Deploy and validate CRIB Environment for Core - uses: smartcontractkit/.github/actions/crib-deploy-environment@815e0d550527897746e889441407926d7e28169c # crib-deploy-environment@7.4.0 + uses: smartcontractkit/.github/actions/crib-deploy-environment@a4058228b4b9b6e30bb0e2b883e3b4f0cd447970 # crib-deploy-environment@2.1.0 id: deploy-crib with: github-token: ${{ steps.token.outputs.access-token }} - aws-ecr-private-registry: ${{ secrets.AWS_ACCOUNT_ID_PROD }} + api-gateway-host: ${{ secrets.AWS_API_GW_HOST_K8S_STAGE }} aws-region: ${{ secrets.AWS_REGION }} aws-role-arn: ${{ secrets.AWS_OIDC_CRIB_ROLE_ARN_STAGE }} + ecr-private-registry: ${{ secrets.AWS_ACCOUNT_ID_PROD }} ingress-base-domain: ${{ secrets.INGRESS_BASE_DOMAIN_STAGE }} - k8s-api-endpoint: ${{ secrets.GAP_HOST_K8S_STAGE }} k8s-cluster-name: ${{ secrets.AWS_K8S_CLUSTER_NAME_STAGE }} - chainlink-team: releng - chainlink-product: crib command: "core-dev-simulated-core-ocr1" crib-alert-slack-webhook: ${{ secrets.CRIB_ALERT_SLACK_WEBHOOK }} product-image: ${{ secrets.AWS_SDLC_ECR_HOSTNAME }}/chainlink @@ -96,7 +94,7 @@ jobs: - name: Set up Go uses: ./.github/actions/setup-go with: - go-version-file: "go.mod" + go-version-file: 'go.mod' - name: Run CRIB integration test working-directory: integration-tests/crib env: diff --git a/.github/workflows/delete-caches.yml b/.github/workflows/delete-caches.yml index 64b9e799665..aaba0dda623 100644 --- a/.github/workflows/delete-caches.yml +++ b/.github/workflows/delete-caches.yml @@ -24,14 +24,10 @@ jobs: uses: actions/checkout@v4.1.2 - name: Setup gh-actions-cache extension - env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: gh extension install actions/gh-actions-cache - name: Retrieve Trunk SHA id: get-sha - env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | SHA=$(gh pr view -R $REPO $PR_NUMBER --json mergeCommit --jq .mergeCommit.oid) echo "sha=$SHA" >> $GITHUB_OUTPUT diff --git a/.github/workflows/find-new-flaky-tests.yml b/.github/workflows/find-new-flaky-tests.yml new file mode 100644 index 00000000000..363305af468 --- /dev/null +++ b/.github/workflows/find-new-flaky-tests.yml @@ -0,0 +1,566 @@ +name: Find Flaky Tests + +on: + workflow_call: + inputs: + repoUrl: + required: true + type: string + description: 'The URL of the repository to compare changes for detecting flaky tests.' + projectPath: + required: true + type: string + description: 'The path to the project to run the flaky test detection.' + default: '.' + baseRef: + required: true + type: string + description: 'The base reference or branch to compare changes for detecting flaky tests.' + headRef: + required: false + type: string + description: 'The head reference or branch to compare changes for detecting flaky tests. Default is the current branch.' + runAllTests: + required: false + type: boolean + description: 'Run all tests in the project.' + default: false + runThreshold: + required: false + type: string + description: 'The threshold for the number of times a test can fail before being considered flaky.' + default: '0.9' + findByTestFilesDiff: + required: false + type: boolean + description: 'Find new or updated test packages by comparing test files diff.' + default: true + findByAffectedPackages: + required: false + type: boolean + description: 'Find new or updated test packages by comparing affected packages.' + default: true + slackNotificationAfterTestsChannelId: + description: "Slack channel ID to send the notification to for failed tests." + required: false + type: string + extraArgs: + required: false + type: string + default: '{}' + description: 'JSON of extra arguments for the workflow.' + secrets: + SLACK_BOT_TOKEN: + required: false + +env: + GIT_HEAD_REF: ${{ inputs.headRef || github.ref }} + SKIPPED_TESTS: ${{ fromJson(inputs.extraArgs)['skipped_tests'] || '' }} # Comma separated list of test names to skip running in the flaky detector. Related issue: TT-1823 + DEFAULT_MAX_RUNNER_COUNT: ${{ fromJson(inputs.extraArgs)['default_max_runner_count'] || '8' }} # The default maximum number of GitHub runners to use for parallel test execution. + ALL_TESTS_RUNNER_COUNT: ${{ fromJson(inputs.extraArgs)['all_tests_runner_count'] || '2' }} # The number of GitHub runners to use when running all tests `runAllTests=true`. + TEST_REPEAT_COUNT: ${{ fromJson(inputs.extraArgs)['test_repeat_count'] || '5' }} # The number of times each runner should run a test to detect flaky tests. + RUN_WITH_RACE: ${{ fromJson(inputs.extraArgs)['run_with_race'] || 'true' }} # Whether to run tests with -race flag. + ALL_TESTS_RUNNER: ${{ fromJson(inputs.extraArgs)['all_tests_runner'] || 'ubuntu22.04-32cores-128GB' }} # The runner to use for running all tests. + DEFAULT_RUNNER: 'ubuntu-latest' # The default runner to use for running tests. + UPLOAD_ALL_TEST_RESULTS: ${{ fromJson(inputs.extraArgs)['upload_all_test_results'] || 'false' }} # Whether to upload all test results as artifacts. + PRINT_FAILED_TESTS: ${{ fromJson(inputs.extraArgs)['print_failed_tests'] || 'false' }} # Whether to print failed tests in the GitHub console. + MIN_PASS_RATIO: ${{ fromJson(inputs.extraArgs)['min_pass_ratio'] || '0.001' }} # The minimum pass ratio for a test to be considered as flaky. Used to distinguish between tests that are truly flaky (with inconsistent results) and those that are consistently failing. Set to 0 if you want to consider all failed tests as flaky. + +jobs: + get-tests: + name: Get Tests To Run + runs-on: ubuntu-latest + outputs: + matrix: ${{ steps.split-packages.outputs.matrix }} + workflow_id: ${{ steps.gen_id.outputs.workflow_id }} + changed_test_files: ${{ steps.find-changed-test-files.outputs.test_files }} + affected_test_packages: ${{ steps.get-tests.outputs.packages }} + git_head_sha: ${{ steps.get_commit_sha.outputs.git_head_sha }} + git_head_short_sha: ${{ steps.get_commit_sha.outputs.git_head_short_sha }} + steps: + - name: Checkout repository + uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 + with: + fetch-depth: 0 + ref: ${{ env.GIT_HEAD_REF }} + + - name: Get commit SHA + id: get_commit_sha + run: | + git_head_sha=$(git rev-parse HEAD) + git_head_short_sha=$(git rev-parse --short HEAD) + echo "git_head_sha=$git_head_sha" >> $GITHUB_OUTPUT + echo "git_head_short_sha=$git_head_short_sha" >> $GITHUB_OUTPUT + + - name: Set up Go 1.21.9 + uses: actions/setup-go@v5.0.2 + with: + go-version: '1.21.9' + cache: false + + - name: Install flakeguard + shell: bash + run: go install github.com/smartcontractkit/chainlink-testing-framework/tools/flakeguard@9c9821d6013f4838eb26970c2eef594f4d25398b + + - name: Find new or updated test packages + if: ${{ inputs.runAllTests == false }} + id: get-tests + shell: bash + env: + # Needed to run go test -list + CL_DATABASE_URL: postgresql://postgres@localhost:5432/chainlink_test?sslmode=disable + run: | + PATH=$PATH:$(go env GOPATH)/bin + export PATH + + PACKAGES=$(flakeguard find --find-by-test-files-diff=${{ inputs.findByTestFilesDiff }} --find-by-affected-packages=${{ inputs.findByAffectedPackages }} --base-ref=origin/${{ inputs.baseRef }} --project-path=${{ inputs.projectPath }}) + echo $PACKAGES + echo "packages=$PACKAGES" >> $GITHUB_OUTPUT + + - name: Find changed test files + if: ${{ inputs.runAllTests == false }} + id: find-changed-test-files + shell: bash + env: + # Needed to run go test -list + CL_DATABASE_URL: postgresql://postgres@localhost:5432/chainlink_test?sslmode=disable + run: | + PATH=$PATH:$(go env GOPATH)/bin + export PATH + + TEST_FILES=$(flakeguard find --only-show-changed-test-files=true --base-ref=origin/${{ inputs.baseRef }} --project-path=${{ inputs.projectPath }}) + echo $TEST_FILES + echo "test_files=$TEST_FILES" >> $GITHUB_OUTPUT + + - name: Split test packages into groups + id: split-packages + shell: bash + run: | + if [[ "${{ inputs.runAllTests }}" == "true" ]]; then + # Use ALL_TESTS_RUNNER for a specified number of groups, each with "./..." to run all tests + ALL_TESTS_RUNNER_COUNT=${{ env.ALL_TESTS_RUNNER_COUNT }} + + # Create the JSON array dynamically based on ALL_TESTS_RUNNER_COUNT + json_groups=$(jq -nc --argjson count "$ALL_TESTS_RUNNER_COUNT" \ + '[range(0; $count) | { "testPackages": "./...", "runs_on": "'"${{ env.ALL_TESTS_RUNNER }}"'" }]') + + echo "$json_groups" + echo "matrix<> $GITHUB_OUTPUT + echo "$json_groups" >> $GITHUB_OUTPUT + echo "EOF" >> $GITHUB_OUTPUT + exit 0 + fi + + PACKAGES=(${{ steps.get-tests.outputs.packages }}) + DESIRED_GROUP_COUNT=$((${{ env.DEFAULT_MAX_RUNNER_COUNT }})) + TOTAL_PACKAGES=${#PACKAGES[@]} + + # Number of groups should be no more than the number of packages + MAX_GROUP_COUNT=$(($TOTAL_PACKAGES < $DESIRED_GROUP_COUNT ? $TOTAL_PACKAGES : $DESIRED_GROUP_COUNT)) + BASE_GROUP_SIZE=$(($TOTAL_PACKAGES / $MAX_GROUP_COUNT)) + EXTRA=$(($TOTAL_PACKAGES % $MAX_GROUP_COUNT)) + + groups=() + + current_index=0 + for (( i=0; i < $MAX_GROUP_COUNT; i++ )); do + # Determine the number of packages for the current group + group_size=$BASE_GROUP_SIZE + if [[ $i -lt $EXTRA ]]; then + group_size=$(($group_size + 1)) + fi + + # Extract the packages for the current group + if [[ $group_size -gt 0 ]]; then + group=("${PACKAGES[@]:current_index:group_size}") + groups+=("{\"testPackages\":\"$(IFS=,; echo "${group[*]}")\", \"runs_on\":\"${{ env.DEFAULT_RUNNER }}\"}") + current_index=$(($current_index + $group_size)) + fi + done + + # Convert groups array into a JSON array + json_groups=$(printf '%s\n' "${groups[@]}" | jq -s .) + echo "$json_groups" + echo "matrix<> $GITHUB_OUTPUT + echo "$json_groups" >> $GITHUB_OUTPUT + echo "EOF" >> $GITHUB_OUTPUT + + - name: Generate random workflow id + id: gen_id + shell: bash + run: echo "workflow_id=$(uuidgen)" >> "$GITHUB_OUTPUT" + + run-tests: + name: Run Tests + needs: get-tests + runs-on: ${{ matrix.runs_on }} + if: ${{ needs.get-tests.outputs.matrix != '' && needs.get-tests.outputs.matrix != '[]' }} + timeout-minutes: 90 + strategy: + fail-fast: false + matrix: + include: ${{ fromJson(needs.get-tests.outputs.matrix) }} + env: + DB_URL: postgresql://postgres:postgres@localhost:5432/chainlink_test?sslmode=disable + steps: + - name: Checkout repository + uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 + with: + ref: ${{ env.GIT_HEAD_REF }} + + - name: Setup NodeJS + uses: ./.github/actions/setup-nodejs + with: + prod: "true" + - name: Setup Go + uses: ./.github/actions/setup-go + with: + restore-build-cache-only: "true" + - name: Setup Solana + uses: ./.github/actions/setup-solana + - name: Setup wasmd + uses: ./.github/actions/setup-wasmd + - name: Setup Postgres + uses: ./.github/actions/setup-postgres + - name: Touching core/web/assets/index.html + run: mkdir -p core/web/assets && touch core/web/assets/index.html + - name: Download Go vendor packages + run: go mod download + - name: Build binary + run: go build -o chainlink.test . + - name: Setup DB + run: ./chainlink.test local db preparetest + env: + CL_DATABASE_URL: ${{ env.DB_URL }} + - name: Install LOOP Plugins + run: | + pushd $(go list -m -f "{{.Dir}}" github.com/smartcontractkit/chainlink-feeds) + go install ./cmd/chainlink-feeds + popd + pushd $(go list -m -f "{{.Dir}}" github.com/smartcontractkit/chainlink-data-streams) + go install ./mercury/cmd/chainlink-mercury + popd + pushd $(go list -m -f "{{.Dir}}" github.com/smartcontractkit/chainlink-solana) + go install ./pkg/solana/cmd/chainlink-solana + popd + pushd $(go list -m -f "{{.Dir}}" github.com/smartcontractkit/chainlink-starknet/relayer) + go install ./pkg/chainlink/cmd/chainlink-starknet + popd + + - name: Go mod tidy + shell: bash + run: | + cd ${{ inputs.projectPath }} + go mod tidy + + - name: Generate random id + id: gen_id + run: echo "id=$(uuidgen)" >> "$GITHUB_OUTPUT" + + - name: Install flakeguard + shell: bash + run: go install github.com/smartcontractkit/chainlink-testing-framework/tools/flakeguard@9c9821d6013f4838eb26970c2eef594f4d25398b + + - name: Run tests with flakeguard + shell: bash + run: flakeguard run --project-path=${{ inputs.projectPath }} --test-packages=${{ matrix.testPackages }} --run-count=${{ env.TEST_REPEAT_COUNT }} --min-pass-ratio=${{ env.MIN_PASS_RATIO }} --threshold=${{ inputs.runThreshold }} --race=${{ env.RUN_WITH_RACE }} --skip-tests=${{ env.SKIPPED_TESTS }} --print-failed-tests=${{ env.PRINT_FAILED_TESTS }} --output-json=test-result.json + env: + CL_DATABASE_URL: ${{ env.DB_URL }} + + - name: Upload test result as artifact + if: always() + uses: actions/upload-artifact@v4.4.3 + with: + name: test-result-${{ needs.get-tests.outputs.workflow_id }}-${{ steps.gen_id.outputs.id }} + path: test-result.json + retention-days: 1 + + report: + needs: [get-tests, run-tests] + if: always() + name: Report + runs-on: ubuntu-latest + outputs: + test_results: ${{ steps.set_test_results.outputs.results }} + steps: + - name: Set Pretty Project Path + id: set_project_path_pretty + run: | + if [ "${{ inputs.projectPath }}" = "." ]; then + echo "path=github.com/${{ github.repository }}" >> $GITHUB_OUTPUT + else + echo "path=github.com/${{ github.repository }}/${{ inputs.projectPath }}" >> $GITHUB_OUTPUT + fi + + - name: Download all test result artifacts + uses: actions/download-artifact@v4.1.8 + with: + path: test_results + pattern: + test-result-${{ needs.get-tests.outputs.workflow_id }}-* + + - name: Install flakeguard + shell: bash + run: go install github.com/smartcontractkit/chainlink-testing-framework/tools/flakeguard@9c9821d6013f4838eb26970c2eef594f4d25398b + + - name: Set combined test results + id: set_test_results + shell: bash + run: | + set -e # Exit immediately if a command exits with a non-zero status. + if [ -d "test_results" ]; then + cd test_results + ls -R . + + # Fix flakeguard binary path + PATH=$PATH:$(go env GOPATH)/bin + export PATH + + # Use flakeguard aggregate-all to aggregate test results + flakeguard aggregate-all --results-path . --output-results ../all_tests.json + + # Count all tests + ALL_TESTS_COUNT=$(jq 'length' ../all_tests.json) + echo "All tests count: $ALL_TESTS_COUNT" + echo "all_tests_count=$ALL_TESTS_COUNT" >> "$GITHUB_OUTPUT" + + # Use flakeguard aggregate-failed to filter and output failed tests based on PassRatio threshold + flakeguard aggregate-failed --threshold "${{ inputs.runThreshold }}" --min-pass-ratio=${{ env.MIN_PASS_RATIO }} --results-path . --output-results ../failed_tests.json --output-logs ../failed_test_logs.json + + # Count failed tests + if [ -f "../failed_tests.json" ]; then + FAILED_TESTS_COUNT=$(jq 'length' ../failed_tests.json) + else + FAILED_TESTS_COUNT=0 + fi + echo "Failed tests count: $FAILED_TESTS_COUNT" + echo "failed_tests_count=$FAILED_TESTS_COUNT" >> "$GITHUB_OUTPUT" + else + echo "No test results directory found." + echo "all_tests_count=0" >> "$GITHUB_OUTPUT" + echo "failed_tests_count=0" >> "$GITHUB_OUTPUT" + fi + + - name: Calculate Flakiness Threshold Percentage + id: calculate_threshold + run: | + threshold_percentage=$(echo '${{ inputs.runThreshold }}' | awk '{printf "%.0f", $1 * 100}') + echo "threshold_percentage=$threshold_percentage" >> $GITHUB_OUTPUT + + - name: Upload Failed Test Results as Artifact + if: ${{ fromJson(steps.set_test_results.outputs.failed_tests_count) > 0 }} + uses: actions/upload-artifact@v4.4.3 + with: + path: failed_tests.json + name: failed-test-results.json + retention-days: 7 + + - name: Upload Failed Test Logs as Artifact + if: ${{ fromJson(steps.set_test_results.outputs.failed_tests_count) > 0 }} + uses: actions/upload-artifact@v4.4.3 + with: + path: failed_test_logs.json + name: failed-test-logs.json + retention-days: 7 + + - name: Upload All Test Results as Artifact + if: ${{ fromJson(steps.set_test_results.outputs.all_tests_count) > 0 && env.UPLOAD_ALL_TEST_RESULTS == 'true' }} + uses: actions/upload-artifact@v4.4.3 + with: + path: all_tests.json + name: all-test-results.json + retention-days: 7 + + - name: Create ASCII table with failed test results + if: ${{ fromJson(steps.set_test_results.outputs.failed_tests_count) > 0 }} + shell: bash + run: | + jq -r '["TestPackage", "TestName", "PassRatio", "RunCount", "Skipped"], ["---------", "---------", "---------", "---------", "---------"], (.[] | [.TestPackage, .TestName, .PassRatioPercentage, .Runs, .Skipped]) | @tsv' failed_tests.json | column -t -s$'\t' > failed_tests_ascii.txt + cat failed_tests_ascii.txt + + - name: Create ASCII table with all test results + if: ${{ fromJson(steps.set_test_results.outputs.all_tests_count) > 0 }} + shell: bash + run: | + jq -r '["TestPackage", "TestName", "PassRatio", "RunCount", "Skipped"], ["---------", "---------", "---------", "---------", "---------"], (.[] | [.TestPackage, .TestName, .PassRatioPercentage, .Runs, .Skipped]) | @tsv' all_tests.json | column -t -s$'\t' > all_tests_ascii.txt + cat all_tests_ascii.txt + + - name: Create GitHub Summary (General) + run: | + echo "## Flaky Test Detection Report for ${{ steps.set_project_path_pretty.outputs.path }} Project" >> $GITHUB_STEP_SUMMARY + + - name: Create GitHub Summary (Comparative Test Analysis) + if: ${{ inputs.runAllTests == false }} + run: | + echo "### Comparative Test Analysis" >> $GITHUB_STEP_SUMMARY + echo "Checked changes between \`${{ inputs.baseRef }}\` and \`${{ env.GIT_HEAD_REF }}\`. See all changes [here](${{ inputs.repoUrl }}/compare/${{ inputs.baseRef }}...${{ needs.get-tests.outputs.git_head_sha }}#files_bucket)." >> $GITHUB_STEP_SUMMARY + + - name: Create GitHub Summary (All Tests) + if: ${{ inputs.runAllTests == 'true' }} + run: | + echo "### Running All Tests" >> $GITHUB_STEP_SUMMARY + echo "All tests are being executed as \`runAllTests\` is set to true." >> $GITHUB_STEP_SUMMARY + + - name: Append Changed Test Files to GitHub Summary + if: ${{ needs.get-tests.outputs.changed_test_files != '' && inputs.findByTestFilesDiff && !inputs.findByAffectedPackages }} + run: | + echo "### Changed Test Files" >> $GITHUB_STEP_SUMMARY + echo '```' >> $GITHUB_STEP_SUMMARY + IFS=' ' read -ra ADDR <<< "${{ needs.get-tests.outputs.changed_test_files }}" + for file in "${ADDR[@]}"; do + echo "$file" >> $GITHUB_STEP_SUMMARY + done + echo '```' >> $GITHUB_STEP_SUMMARY + + - name: Append Affected Test Packages to GitHub Summary + if: ${{ needs.get-tests.outputs.affected_test_packages != '' }} + run: | + echo "### Affected Test Packages" >> $GITHUB_STEP_SUMMARY + echo '```' >> $GITHUB_STEP_SUMMARY + IFS=' ' read -ra ADDR <<< "${{ needs.get-tests.outputs.affected_test_packages }}" + for package in "${ADDR[@]}"; do + echo "$package" >> $GITHUB_STEP_SUMMARY + done + echo '```' >> $GITHUB_STEP_SUMMARY + + - name: Read Failed Tests File + if: ${{ fromJson(steps.set_test_results.outputs.failed_tests_count) > 0 }} + id: read_failed_tests + run: | + file_content=$(cat failed_tests_ascii.txt) + echo "failed_tests_content<> $GITHUB_OUTPUT + echo "$file_content" >> $GITHUB_OUTPUT + echo "EOF" >> $GITHUB_OUTPUT + + - name: Calculate Test Repeat Count + id: calculate_test_repeat_count + shell: bash + run: | + # Convert environment variables to integers + ALL_TESTS_RUNNER_COUNT=${{ env.ALL_TESTS_RUNNER_COUNT }} + TEST_REPEAT_COUNT=${{ env.TEST_REPEAT_COUNT }} + + # If runAllTests input is true, multiply the number of runners by the test repeat count as each runner runs all tests + # Otherwise, use the test repeat count as each runner runs unique tests + if [[ "${{ inputs.runAllTests }}" == "true" ]]; then + test_repeat_count=$(( ALL_TESTS_RUNNER_COUNT * TEST_REPEAT_COUNT )) + else + test_repeat_count=$TEST_REPEAT_COUNT + fi + echo "test_repeat_count=$test_repeat_count" >> $GITHUB_OUTPUT + + - name: Append Flaky Tests to GitHub Summary + if: ${{ fromJson(steps.set_test_results.outputs.failed_tests_count) > 0 }} + run: | + threshold_percentage=$(echo "${{ inputs.runThreshold }}" | awk '{printf "%.2f", $1 * 100}') + min_pass_ratio_percentage=$(echo "${{ env.MIN_PASS_RATIO }}" | awk '{printf "%.2f", $1 * 100}') + echo "### Flaky Tests :x:" >> $GITHUB_STEP_SUMMARY + echo "Ran ${{ steps.set_test_results.outputs.all_tests_count }} unique tests ${{ steps.calculate_test_repeat_count.outputs.test_repeat_count }} times. Below are the tests identified as flaky, with a pass ratio lower than the ${threshold_percentage}% threshold:" >> $GITHUB_STEP_SUMMARY + echo '```' >> $GITHUB_STEP_SUMMARY + cat failed_tests_ascii.txt >> $GITHUB_STEP_SUMMARY + echo '```' >> $GITHUB_STEP_SUMMARY + echo "For detailed logs of the failed tests, please refer to the failed-test-results.json and failed-test-logs.json files in the Artifacts section at the bottom of the page. failed-test-logs.json contains all outputs from failed tests." >> $GITHUB_STEP_SUMMARY + + - name: Append Success Note if No Flaky Tests Found + if: ${{ fromJson(steps.set_test_results.outputs.all_tests_count) > 0 && fromJson(steps.set_test_results.outputs.failed_tests_count) == 0 }} + run: | + echo "### No Flaky Tests Found! :white_check_mark:" >> $GITHUB_STEP_SUMMARY + echo "Ran \`${{ steps.set_test_results.outputs.all_tests_count }}\` unique tests ${{ steps.calculate_test_repeat_count.outputs.test_repeat_count }} times and found no flakes." >> $GITHUB_STEP_SUMMARY + + - name: Append Additional Info to GitHub Summary + if: ${{ fromJson(steps.set_test_results.outputs.all_tests_count) > 0 }} + run: | + echo "### Settings" >> $GITHUB_STEP_SUMMARY + threshold_percentage=$(echo "${{ inputs.runThreshold }}" | awk '{printf "%.2f", $1 * 100}') + min_pass_ratio_percentage=$(echo "${{ env.MIN_PASS_RATIO }}" | awk '{printf "%.2f", $1 * 100}') + echo "| **Setting** | **Value** |" >> $GITHUB_STEP_SUMMARY + echo "|-------------------------|------------|" >> $GITHUB_STEP_SUMMARY + echo "| Go Project | ${{ steps.set_project_path_pretty.outputs.path }} |" >> $GITHUB_STEP_SUMMARY + echo "| Minimum Pass Ratio | ${min_pass_ratio_percentage}% |" >> $GITHUB_STEP_SUMMARY + echo "| Flakiness Threshold | ${threshold_percentage}% |" >> $GITHUB_STEP_SUMMARY + echo "| Test Run Count | ${{ steps.calculate_test_repeat_count.outputs.test_repeat_count }} |" >> $GITHUB_STEP_SUMMARY + echo "| Race Detection | ${{ env.RUN_WITH_RACE }} |" >> $GITHUB_STEP_SUMMARY + echo "| Excluded Tests | ${{ env.SKIPPED_TESTS }} |" >> $GITHUB_STEP_SUMMARY + + - name: Append No Tests Found Message to GitHub Summary + if: ${{ fromJson(steps.set_test_results.outputs.all_tests_count) == 0 }} + run: | + echo "### No Tests To Execute" >> $GITHUB_STEP_SUMMARY + echo "No updated or new Go tests found for ${{ steps.set_project_path_pretty.outputs.path }} project. The flaky detector will not run." >> $GITHUB_STEP_SUMMARY + + - name: Post comment on PR if flaky tests found + if: ${{ fromJson(steps.set_test_results.outputs.failed_tests_count) > 0 && github.event_name == 'pull_request' }} + uses: actions/github-script@v7 + env: + MESSAGE_BODY_1: '### Flaky Test Detector for `${{ steps.set_project_path_pretty.outputs.path }}` project has failed :x:' + MESSAGE_BODY_2: 'Ran new or updated tests between `${{ inputs.baseRef }}` and ${{ needs.get-tests.outputs.git_head_sha }} (`${{ env.GIT_HEAD_REF }}`).' + MESSAGE_BODY_3: ${{ format('[View Flaky Detector Details]({0}/{1}/actions/runs/{2}) | [Compare Changes]({3}/compare/{4}...{5}#files_bucket)', github.server_url, github.repository, github.run_id, inputs.repoUrl, github.base_ref, needs.get-tests.outputs.git_head_sha) }} + MESSAGE_BODY_4: '#### Flaky Tests' + MESSAGE_BODY_5: 'Ran ${{ steps.set_test_results.outputs.all_tests_count }} unique tests. Below are the tests identified as flaky, with a pass ratio lower than the ${{ steps.calculate_threshold.outputs.threshold_percentage }}% threshold:' + MESSAGE_BODY_6: '```' + MESSAGE_BODY_7: '${{ steps.read_failed_tests.outputs.failed_tests_content }}' + MESSAGE_BODY_8: '```' + with: + script: | + const prNumber = context.payload.pull_request.number; + + const commentBody = `${process.env.MESSAGE_BODY_1} + + ${process.env.MESSAGE_BODY_2} + + ${process.env.MESSAGE_BODY_3} + + ${process.env.MESSAGE_BODY_4} + + ${process.env.MESSAGE_BODY_5} + + ${process.env.MESSAGE_BODY_6} + ${process.env.MESSAGE_BODY_7} + ${process.env.MESSAGE_BODY_8}`; + + await github.rest.issues.createComment({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: prNumber, + body: commentBody + }); + + - name: Send Slack message + uses: slackapi/slack-github-action@6c661ce58804a1a20f6dc5fbee7f0381b469e001 # v1.25.0 + if: ${{ inputs.slackNotificationAfterTestsChannelId != '' && fromJson(steps.set_test_results.outputs.all_tests_count) > 0 }} + id: slack + env: + SLACK_BOT_TOKEN: ${{ secrets.SLACK_BOT_TOKEN }} + with: + channel-id: ${{ inputs.slackNotificationAfterTestsChannelId }} + payload: | + { + "attachments": [ + { + "color": "${{ contains(join(needs.*.result, ','), 'failure') && '#C62828' || contains(join(needs.*.result, ','), 'cancelled') && '#FFA000' || '2E7D32' }}", + "blocks": [ + { + "type": "section", + "text": { + "type": "mrkdwn", + "text": "Flaky Test Detector for `${{ steps.set_project_path_pretty.outputs.path }}` project - ${{ contains(join(needs.*.result, ','), 'failure') && 'Failed :x:' || contains(join(needs.*.result, ','), 'cancelled') && 'Was cancelled :warning:' || 'Passed :white_check_mark:' }}" + } + }, + { + "type": "section", + "text": { + "type": "mrkdwn", + "text": "Ran changed tests between `${{ inputs.baseRef }}` and `${{ needs.get-tests.outputs.git_head_short_sha }}` (`${{ env.GIT_HEAD_REF }}`)." + } + }, + { + "type": "section", + "text": { + "type": "mrkdwn", + "text": "${{ format('<{0}/{1}/actions/runs/{2}|View Flaky Detector Details> | <{3}/compare/{4}...{5}#files_bucket|Compare Changes>{6}', github.server_url, github.repository, github.run_id, inputs.repoUrl, inputs.baseRef, needs.get-tests.outputs.git_head_sha, github.event_name == 'pull_request' && format(' | <{0}|View PR>', github.event.pull_request.html_url) || '') }}" + } + } + ] + } + ] + } diff --git a/.github/workflows/flakeguard-nightly.yml b/.github/workflows/flakeguard-nightly.yml deleted file mode 100644 index 025cca6d0a0..00000000000 --- a/.github/workflows/flakeguard-nightly.yml +++ /dev/null @@ -1,25 +0,0 @@ -name: Flakeguard Nightly - -on: - schedule: - # Run every night at 3:00 AM UTC - - cron: '0 3 * * *' - workflow_dispatch: - -jobs: - trigger-flaky-test-detection: - name: Find Flaky Tests - uses: ./.github/workflows/flakeguard.yml - with: - repoUrl: 'https://github.com/smartcontractkit/chainlink' - headRef: 'develop' - projectPath: '.' - maxPassRatio: '1.0' - runAllTests: true - extraArgs: '{ "skipped_tests": "TestChainComponents", "test_repeat_count": "5", "all_tests_runner": "ubuntu22.04-32cores-128GB", "all_tests_runner_count": "3", "run_with_race": "false" }' - slackNotificationAfterTestsChannelId: 'C07TRF65CNS' #flaky-test-detector-notifications - secrets: - SLACK_BOT_TOKEN: ${{ secrets.QA_SLACK_API_KEY }} - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - FLAKEGUARD_SPLUNK_ENDPOINT: ${{ secrets.FLAKEGUARD_SPLUNK_ENDPOINT }} - FLAKEGUARD_SPLUNK_HEC: ${{ secrets.FLAKEGUARD_SPLUNK_HEC }} diff --git a/.github/workflows/flakeguard.yml b/.github/workflows/flakeguard.yml deleted file mode 100644 index 93f380606b0..00000000000 --- a/.github/workflows/flakeguard.yml +++ /dev/null @@ -1,573 +0,0 @@ -name: Flakeguard - -on: - workflow_call: - inputs: - repoUrl: - required: true - type: string - default: 'https://github.com/smartcontractkit/chainlink' - description: 'The URL of the repository to compare changes for detecting flaky tests.' - projectPath: - required: true - type: string - description: 'The path to the project to run the flaky test detection.' - default: '.' - baseRef: - required: false - type: string - description: 'The base reference or branch to compare changes for detecting flaky tests. Set only when running diffs between branches. E.g. (develop)' - headRef: - required: false - type: string - description: 'The head reference or branch to compare changes for detecting flaky tests. Default is the current branch. E.g. (develop)' - runAllTests: - required: false - type: boolean - description: 'Run all tests in the project.' - default: false - maxPassRatio: - required: false - type: string - description: 'The maximum (non-inclusive) pass ratio threshold for a test to be considered a failure. Any tests below this pass rate will be considered flaky.' - default: '1.0' - findByTestFilesDiff: - required: false - type: boolean - description: 'Find new or updated test packages by comparing test files diff.' - default: true - findByAffectedPackages: - required: false - type: boolean - description: 'Find new or updated test packages by comparing affected packages.' - default: true - slackNotificationAfterTestsChannelId: - description: "Slack channel ID to send the notification to for failed tests." - required: false - type: string - extraArgs: - required: false - type: string - default: '{}' - description: 'JSON of extra arguments for the workflow.' - secrets: - SLACK_BOT_TOKEN: - required: false - GH_TOKEN: - required: true - FLAKEGUARD_SPLUNK_ENDPOINT: - description: "The Splunk HTTP Event Collector (HEC) endpoint." - required: true - FLAKEGUARD_SPLUNK_HEC: - description: "The Splunk HTTP Event Collector (HEC) token." - required: true - -env: - GIT_BASE_REF: ${{ inputs.baseRef }} - GIT_HEAD_REF: ${{ inputs.headRef || github.ref }} - SKIPPED_TESTS: ${{ fromJSON(inputs.extraArgs)['skipped_tests'] || '' }} # Comma separated list of test names to skip running in the flaky detector. Related issue: TT-1823 - DEFAULT_MAX_RUNNER_COUNT: ${{ fromJSON(inputs.extraArgs)['default_max_runner_count'] || '8' }} # The default maximum number of GitHub runners to use for parallel test execution. - ALL_TESTS_RUNNER_COUNT: ${{ fromJSON(inputs.extraArgs)['all_tests_runner_count'] || '2' }} # The number of GitHub runners to use when running all tests `runAllTests=true`. - TEST_REPEAT_COUNT: ${{ fromJSON(inputs.extraArgs)['test_repeat_count'] || '5' }} # The number of times each runner should run a test to detect flaky tests. - RUN_WITH_RACE: ${{ fromJSON(inputs.extraArgs)['run_with_race'] || 'true' }} # Whether to run tests with -race flag. - RUN_WITH_SHUFFLE: ${{ fromJSON(inputs.extraArgs)['run_with_shuffle'] || 'false' }} # Whether to run tests with -shuffle flag. - SHUFFLE_SEED: ${{ fromJSON(inputs.extraArgs)['shuffle_seed'] || '999' }} # The seed to use when -shuffle flag is enabled. Requires RUN_WITH_SHUFFLE to be true. - ALL_TESTS_RUNNER: ${{ fromJSON(inputs.extraArgs)['all_tests_runner'] || 'ubuntu22.04-32cores-128GB' }} # The runner to use for running all tests. - DEFAULT_RUNNER: 'ubuntu-latest' # The default runner to use for running tests. - UPLOAD_ALL_TEST_RESULTS: ${{ fromJSON(inputs.extraArgs)['upload_all_test_results'] || 'false' }} # Whether to upload all test results as artifacts. - OMIT_TEST_OUTPUTS_ON_SUCCESS: ${{ fromJSON(inputs.extraArgs)['omit_test_outputs_on_success'] || 'true' }} - -jobs: - get-tests: - name: Get Tests To Run - runs-on: ubuntu-latest - outputs: - matrix: ${{ steps.split-packages.outputs.matrix }} - workflow_id: ${{ steps.gen_id.outputs.workflow_id }} - changed_test_files: ${{ steps.find-changed-test-files.outputs.test_files }} - affected_test_packages: ${{ steps.get-tests.outputs.packages }} - git_head_sha: ${{ steps.get_commit_sha.outputs.git_head_sha }} - git_head_short_sha: ${{ steps.get_commit_sha.outputs.git_head_short_sha }} - git_base_sha: ${{ steps.get_commit_sha.outputs.git_base_sha }} - steps: - - name: Checkout repository - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 - with: - fetch-depth: 0 - ref: ${{ env.GIT_HEAD_REF }} - - - name: Get SHA - id: get_commit_sha - run: | - # Resolve HEAD SHA - git_head_sha=$(git rev-parse HEAD) - git_head_short_sha=$(git rev-parse --short HEAD) - echo "git_head_sha=$git_head_sha" >> $GITHUB_OUTPUT - echo "git_head_short_sha=$git_head_short_sha" >> $GITHUB_OUTPUT - - # Print HEAD SHAs to the console - echo "HEAD SHA: $git_head_sha" - echo "HEAD Short SHA: $git_head_short_sha" - - # Conditionally resolve BASE SHA - if [ -n "${{ env.GIT_BASE_REF }}" ]; then - git fetch origin ${{ env.GIT_BASE_REF }} --quiet - - git_base_sha=$(git rev-parse origin/${{ env.GIT_BASE_REF }}) - echo "git_base_sha=$git_base_sha" >> $GITHUB_OUTPUT - - # Print BASE SHA to the console - echo "BASE SHA: $git_base_sha" - else - echo "BASE SHA not provided." - echo "git_base_sha=" >> $GITHUB_OUTPUT - fi - - - name: Setup Go - uses: ./.github/actions/setup-go - with: - restore-build-cache-only: "true" - - - name: Install flakeguard - if: ${{ inputs.runAllTests == false }} - shell: bash - run: go install github.com/smartcontractkit/chainlink-testing-framework/tools/flakeguard@7c45cff27ac6b0d4244754660661cdbfcfaf2f9e # flakguard@0.1.0 - - - name: Find new or updated test packages - if: ${{ inputs.runAllTests == false }} - id: get-tests - shell: bash - env: - # Needed to run go test -list - CL_DATABASE_URL: postgresql://postgres@localhost:5432/chainlink_test?sslmode=disable - run: | - PATH=$PATH:$(go env GOPATH)/bin - export PATH - - PACKAGES=$(flakeguard find --find-by-test-files-diff=${{ inputs.findByTestFilesDiff }} --find-by-affected-packages=${{ inputs.findByAffectedPackages }} --base-ref=origin/${{ env.GIT_BASE_REF }} --project-path=${{ inputs.projectPath }}) - echo $PACKAGES - echo "packages=$PACKAGES" >> $GITHUB_OUTPUT - - - name: Find changed test files - if: ${{ inputs.runAllTests == false }} - id: find-changed-test-files - shell: bash - env: - # Needed to run go test -list - CL_DATABASE_URL: postgresql://postgres@localhost:5432/chainlink_test?sslmode=disable - run: | - PATH=$PATH:$(go env GOPATH)/bin - export PATH - - TEST_FILES=$(flakeguard find --only-show-changed-test-files=true --base-ref=origin/${{ env.GIT_BASE_REF }} --project-path=${{ inputs.projectPath }}) - echo $TEST_FILES - echo "test_files=$TEST_FILES" >> $GITHUB_OUTPUT - - - name: Split test packages into groups - id: split-packages - shell: bash - run: | - if [[ "${{ inputs.runAllTests }}" == "true" ]]; then - # Use ALL_TESTS_RUNNER for a specified number of groups, each with "./..." to run all tests - ALL_TESTS_RUNNER_COUNT=${{ env.ALL_TESTS_RUNNER_COUNT }} - - # Create the JSON array dynamically based on ALL_TESTS_RUNNER_COUNT - json_groups=$(jq -nc --argjson count "$ALL_TESTS_RUNNER_COUNT" \ - '[range(0; $count) | { "testPackages": "./...", "runs_on": "'"${{ env.ALL_TESTS_RUNNER }}"'" }]') - - echo "$json_groups" - echo "matrix<> $GITHUB_OUTPUT - echo "$json_groups" >> $GITHUB_OUTPUT - echo "EOF" >> $GITHUB_OUTPUT - exit 0 - fi - - PACKAGES=(${{ steps.get-tests.outputs.packages }}) - DESIRED_GROUP_COUNT=$((${{ env.DEFAULT_MAX_RUNNER_COUNT }})) - TOTAL_PACKAGES=${#PACKAGES[@]} - - # Number of groups should be no more than the number of packages - MAX_GROUP_COUNT=$(($TOTAL_PACKAGES < $DESIRED_GROUP_COUNT ? $TOTAL_PACKAGES : $DESIRED_GROUP_COUNT)) - BASE_GROUP_SIZE=$(($TOTAL_PACKAGES / $MAX_GROUP_COUNT)) - EXTRA=$(($TOTAL_PACKAGES % $MAX_GROUP_COUNT)) - - groups=() - - current_index=0 - for (( i=0; i < $MAX_GROUP_COUNT; i++ )); do - # Determine the number of packages for the current group - group_size=$BASE_GROUP_SIZE - if [[ $i -lt $EXTRA ]]; then - group_size=$(($group_size + 1)) - fi - - # Extract the packages for the current group - if [[ $group_size -gt 0 ]]; then - group=("${PACKAGES[@]:current_index:group_size}") - groups+=("{\"testPackages\":\"$(IFS=,; echo "${group[*]}")\", \"runs_on\":\"${{ env.DEFAULT_RUNNER }}\"}") - current_index=$(($current_index + $group_size)) - fi - done - - # Convert groups array into a JSON array - json_groups=$(printf '%s\n' "${groups[@]}" | jq -s .) - echo "$json_groups" - echo "matrix<> $GITHUB_OUTPUT - echo "$json_groups" >> $GITHUB_OUTPUT - echo "EOF" >> $GITHUB_OUTPUT - - - name: Generate random workflow id - id: gen_id - shell: bash - run: echo "workflow_id=$(uuidgen)" >> "$GITHUB_OUTPUT" - - run-tests: - name: Run Tests - needs: get-tests - runs-on: ${{ matrix.runs_on }} - if: ${{ needs.get-tests.outputs.matrix != '' && needs.get-tests.outputs.matrix != '[]' }} - timeout-minutes: 180 - strategy: - fail-fast: false - matrix: - include: ${{ fromJSON(needs.get-tests.outputs.matrix) }} - env: - DB_URL: postgresql://postgres:postgres@localhost:5432/chainlink_test?sslmode=disable - steps: - - name: Checkout repository - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 - with: - ref: ${{ env.GIT_HEAD_REF }} - - - name: Setup NodeJS - uses: ./.github/actions/setup-nodejs - with: - prod: "true" - - name: Setup Go - uses: ./.github/actions/setup-go - with: - restore-build-cache-only: "true" - - name: Setup Solana - uses: ./.github/actions/setup-solana - - name: Setup wasmd - uses: ./.github/actions/setup-wasmd - - name: Setup Postgres - uses: ./.github/actions/setup-postgres - - name: Touching core/web/assets/index.html - run: mkdir -p core/web/assets && touch core/web/assets/index.html - - name: Download Go vendor packages - run: go mod download - - name: Build binary - run: go build -o chainlink.test . - - name: Setup DB - run: ./chainlink.test local db preparetest - env: - CL_DATABASE_URL: ${{ env.DB_URL }} - - name: Install LOOP Plugins - run: | - pushd $(go list -m -f "{{.Dir}}" github.com/smartcontractkit/chainlink-feeds) - go install ./cmd/chainlink-feeds - popd - pushd $(go list -m -f "{{.Dir}}" github.com/smartcontractkit/chainlink-data-streams) - go install ./mercury/cmd/chainlink-mercury - popd - pushd $(go list -m -f "{{.Dir}}" github.com/smartcontractkit/chainlink-solana) - go install ./pkg/solana/cmd/chainlink-solana - popd - pushd $(go list -m -f "{{.Dir}}" github.com/smartcontractkit/chainlink-starknet/relayer) - go install ./pkg/chainlink/cmd/chainlink-starknet - popd - - - name: Go mod tidy - shell: bash - run: | - cd ${{ inputs.projectPath }} - go mod tidy - - - name: Generate random id - id: gen_id - run: echo "id=$(uuidgen)" >> "$GITHUB_OUTPUT" - - - name: Install flakeguard - shell: bash - run: go install github.com/smartcontractkit/chainlink-testing-framework/tools/flakeguard@7c45cff27ac6b0d4244754660661cdbfcfaf2f9e # flakguard@0.1.0 - - - name: Run tests with flakeguard - shell: bash - run: flakeguard run --project-path=${{ inputs.projectPath }} --test-packages=${{ matrix.testPackages }} --run-count=${{ env.TEST_REPEAT_COUNT }} --max-pass-ratio=${{ inputs.maxPassRatio }} --race=${{ env.RUN_WITH_RACE }} --shuffle=${{ env.RUN_WITH_SHUFFLE }} --shuffle-seed=${{ env.SHUFFLE_SEED }} --skip-tests=${{ env.SKIPPED_TESTS }} --output-json=test-result.json --omit-test-outputs-on-success=${{ env.OMIT_TEST_OUTPUTS_ON_SUCCESS }} - env: - CL_DATABASE_URL: ${{ env.DB_URL }} - - - name: Upload test result as artifact - if: always() - uses: actions/upload-artifact@v4.4.3 - with: - name: test-result-${{ needs.get-tests.outputs.workflow_id }}-${{ steps.gen_id.outputs.id }} - path: test-result.json - retention-days: 1 - - report: - needs: [get-tests, run-tests] - if: always() - name: Report - runs-on: ubuntu-latest - outputs: - test_results: ${{ steps.results.outputs.results }} - steps: - - name: Checkout repository - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 - with: - ref: ${{ env.GIT_HEAD_REF }} - - name: Setup Go - uses: ./.github/actions/setup-go - with: - restore-build-cache-only: "true" - - - name: Set Pretty Project Path - id: set_project_path_pretty - run: | - if [ "${{ inputs.projectPath }}" = "." ]; then - echo "path=github.com/${{ github.repository }}" >> $GITHUB_OUTPUT - else - echo "path=github.com/${{ github.repository }}/${{ inputs.projectPath }}" >> $GITHUB_OUTPUT - fi - - - name: Download all test result artifacts - uses: actions/download-artifact@v4.1.8 - with: - path: ci_test_results - pattern: - test-result-${{ needs.get-tests.outputs.workflow_id }}-* - - - name: Install flakeguard - shell: bash - run: go install github.com/smartcontractkit/chainlink-testing-framework/tools/flakeguard@7c45cff27ac6b0d4244754660661cdbfcfaf2f9e # flakguard@0.1.0 - - - name: Aggregate Flakeguard Results - id: results - shell: bash - run: | - set -e # Exit immediately if a command exits with a non-zero status. - - # Create test results folder if it doesn't exist - mkdir -p ci_test_results - - # Fix flakeguard binary path - PATH=$PATH:$(go env GOPATH)/bin - export PATH - - # Aggregate Flakeguard test results - flakeguard aggregate-results \ - --results-path ./ci_test_results \ - --output-path ./flakeguard-report \ - --repo-path "${{ github.workspace }}" \ - --codeowners-path "${{ github.workspace }}/.github/CODEOWNERS" \ - --max-pass-ratio "${{ inputs.maxPassRatio }}" \ - --repo-url "${{ inputs.repoUrl }}" \ - --base-sha "${{ needs.get-tests.outputs.git_base_sha }}" \ - --head-sha "${{ needs.get-tests.outputs.git_head_sha }}" \ - --github-workflow-name "${{ github.workflow }}" \ - --github-workflow-run-url "${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}" \ - --splunk-url "${{ secrets.FLAKEGUARD_SPLUNK_ENDPOINT }}" \ - --splunk-token "${{ secrets.FLAKEGUARD_SPLUNK_HEC }}" \ - --splunk-event "${{ github.event }}" - - # Print out the summary file - echo -e "\nFlakeguard Summary:" - jq . ./flakeguard-report/all-test-summary.json - - # Read the summary from the generated report - summary=$(jq -c '.' ./flakeguard-report/all-test-summary.json) - echo "summary=$summary" >> $GITHUB_OUTPUT - - - name: Upload All Test Results as Artifact - if: ${{ (success() || failure()) && fromJSON(steps.results.outputs.summary).total_tests > 0 }} - uses: actions/upload-artifact@v4.4.3 - with: - path: ./flakeguard-report/all-test-results.json - name: all-test-results.json - retention-days: 90 - - - name: Upload Failed Test Results as Artifact - if: ${{ (success() || failure()) && fromJSON(steps.results.outputs.summary).failed_runs > 0 }} - uses: actions/upload-artifact@v4.4.3 - with: - path: ./flakeguard-report/failed-test-results.json - name: failed-test-results.json - retention-days: 90 - - - name: Upload Failed Test Results With Logs as Artifact - if: ${{ (success() || failure()) && fromJSON(steps.results.outputs.summary).failed_runs > 0 }} - uses: actions/upload-artifact@v4.4.3 - with: - path: ./flakeguard-report/failed-test-results-with-logs.json - name: failed-test-results-with-logs.json - retention-days: 90 - - - name: Generate Flakeguard Reports - shell: bash - if: success() || failure() - env: - GITHUB_TOKEN: ${{ secrets.GH_TOKEN }} - run: | - set -e # Exit immediately if a command exits with a non-zero status. - - # Fix flakeguard binary path - PATH=$PATH:$(go env GOPATH)/bin - export PATH - - # Check if the event is a pull request - if [ "${{ github.event_name }}" = "pull_request" ]; then - flakeguard generate-report \ - --aggregated-results-path ./flakeguard-report/all-test-results.json \ - --summary-path ./flakeguard-report/all-test-summary.json \ - --output-path ./flakeguard-report \ - --github-repository "${{ github.repository }}" \ - --github-run-id "${{ github.run_id }}" \ - --failed-tests-artifact-name "failed-test-results-with-logs.json" \ - --generate-pr-comment \ - --base-branch "${{ github.event.pull_request.base.ref }}" \ - --current-branch "${{ github.head_ref }}" \ - --current-commit-sha "${{ github.event.pull_request.head.sha }}" \ - --repo-url "https://github.com/${{ github.repository }}" \ - --action-run-id "${{ github.run_id }}" \ - --max-pass-ratio "${{ inputs.maxPassRatio }}" - else - flakeguard generate-report \ - --aggregated-results-path ./flakeguard-report/all-test-results.json \ - --summary-path ./flakeguard-report/all-test-summary.json \ - --output-path ./flakeguard-report \ - --github-repository "${{ github.repository }}" \ - --github-run-id "${{ github.run_id }}" \ - --failed-tests-artifact-name "failed-test-results-with-logs.json" \ - --base-branch "${{ github.event.pull_request.base.ref }}" \ - --current-branch "${{ github.head_ref }}" \ - --current-commit-sha "${{ github.event.pull_request.head.sha }}" \ - --repo-url "https://github.com/${{ github.repository }}" \ - --action-run-id "${{ github.run_id }}" \ - --max-pass-ratio "${{ inputs.maxPassRatio }}" - fi - - - name: Add Github Summary - if: (success() || failure()) - run: | - FILE_SIZE=$(wc -c < ./flakeguard-report/all-test-summary.md) - echo "File size: $FILE_SIZE bytes" - SIZE_LIMIT=$((1024 * 1024)) - - if [ "$FILE_SIZE" -le "$SIZE_LIMIT" ]; then - cat ./flakeguard-report/all-test-summary.md >> $GITHUB_STEP_SUMMARY - else - echo "**We found flaky tests, so many flaky tests that the summary is too large for github actions step summaries!**" >> $GITHUB_STEP_SUMMARY - echo "**Please see logs, or the attached `all-test-summary.md` artifact**" >> $GITHUB_STEP_SUMMARY - cat ./flakeguard-report/all-test-summary.md - fi - - - name: Post comment on PR if flaky tests found - if: ${{ (success() || failure()) && fromJSON(steps.results.outputs.summary).flaky_tests > 0 && github.event_name == 'pull_request' }} - uses: actions/github-script@v7 - continue-on-error: true - with: - script: | - const fs = require('fs'); - const prNumber = context.payload.pull_request.number; - const commentBody = fs.readFileSync('./flakeguard-report/all-test-pr-comment.md', 'utf8'); - - await github.rest.issues.createComment({ - owner: context.repo.owner, - repo: context.repo.repo, - issue_number: prNumber, - body: commentBody - }); - - - name: Send Slack message for failed tests - if: ${{ (success() || failure()) && inputs.slackNotificationAfterTestsChannelId != '' && fromJSON(steps.results.outputs.summary).flaky_tests > 0 }} - uses: slackapi/slack-github-action@6c661ce58804a1a20f6dc5fbee7f0381b469e001 # v1.25.0 - env: - SLACK_BOT_TOKEN: ${{ secrets.SLACK_BOT_TOKEN }} - with: - channel-id: ${{ inputs.slackNotificationAfterTestsChannelId }} - payload: | - { - "attachments": [ - { - "color": "#C62828", - "blocks": [ - { - "type": "section", - "text": { - "type": "mrkdwn", - "text": "Flaky Test Detector for `${{ steps.set_project_path_pretty.outputs.path }}` project - ${{ contains(join(needs.*.result, ','), 'failure') && 'Failed :x:' || contains(join(needs.*.result, ','), 'cancelled') && 'Was cancelled :warning:' || 'Passed :white_check_mark:' }}" - } - }, - { - "type": "section", - "text": { - "type": "mrkdwn", - "text": "${{ inputs.runAllTests == true && format('Ran all tests for `{0}` branch.', env.GIT_HEAD_REF) || format('Ran changed tests between `{0}` and `{1}` (`{2}`).', env.GIT_BASE_REF, needs.get-tests.outputs.git_head_short_sha, env.GIT_HEAD_REF) }}" - } - }, - { - "type": "section", - "fields": [ - { - "type": "mrkdwn", - "text": "Total Flaky Tests: ${{ fromJSON(steps.results.outputs.summary).flaky_tests }}" - }, - { - "type": "mrkdwn", - "text": "Flaky Tests Ratio: ${{ fromJSON(steps.results.outputs.summary).flaky_test_ratio }}" - } - ] - }, - { - "type": "section", - "text": { - "type": "mrkdwn", - "text": "${{ format('<{0}/{1}/actions/runs/{2}|View Flaky Detector Details> | <{3}/compare/{4}...{5}#files_bucket|Compare Changes>{6}', github.server_url, github.repository, github.run_id, inputs.repoUrl, env.GIT_BASE_REF, needs.get-tests.outputs.git_head_sha, github.event_name == 'pull_request' && format(' | <{0}|View PR>', github.event.pull_request.html_url) || '') }}" - } - } - ] - } - ] - } - - - name: Send general Slack message - uses: slackapi/slack-github-action@6c661ce58804a1a20f6dc5fbee7f0381b469e001 # v1.25.0 - if: ${{ (success() || failure()) && inputs.slackNotificationAfterTestsChannelId != '' && fromJSON(steps.results.outputs.summary).flaky_tests == 0 && fromJSON(steps.results.outputs.summary).total_tests > 0 }} - id: slack - env: - SLACK_BOT_TOKEN: ${{ secrets.SLACK_BOT_TOKEN }} - with: - channel-id: ${{ inputs.slackNotificationAfterTestsChannelId }} - payload: | - { - "attachments": [ - { - "color": "${{ contains(join(needs.*.result, ','), 'failure') && '#C62828' || contains(join(needs.*.result, ','), 'cancelled') && '#FFA000' || '2E7D32' }}", - "blocks": [ - { - "type": "section", - "text": { - "type": "mrkdwn", - "text": "Flaky Test Detector for `${{ steps.set_project_path_pretty.outputs.path }}` project - ${{ contains(join(needs.*.result, ','), 'failure') && 'Failed :x:' || contains(join(needs.*.result, ','), 'cancelled') && 'Was cancelled :warning:' || 'Passed :white_check_mark:' }}" - } - }, - { - "type": "section", - "text": { - "type": "mrkdwn", - "text": "${{ inputs.runAllTests == true && format('Ran all tests for `{0}` branch.', env.GIT_HEAD_REF) || format('Ran changed tests between `{0}` and `{1}` (`{2}`).', env.GIT_BASE_REF, needs.get-tests.outputs.git_head_short_sha, env.GIT_HEAD_REF) }}" - } - }, - { - "type": "section", - "text": { - "type": "mrkdwn", - "text": "${{ inputs.runAllTests == true && format('<{0}/{1}/actions/runs/{2}|View Flaky Detector Details>', github.server_url, github.repository, github.run_id) || format('<{0}/{1}/actions/runs/{2}|View Flaky Detector Details> | <{3}/compare/{4}...{5}#files_bucket|Compare Changes>{6}', github.server_url, github.repository, github.run_id, inputs.repoUrl, inputs.baseRef, needs.get-tests.outputs.git_head_sha, github.event_name == 'pull_request' && format(' | <{0}|View PR>', github.event.pull_request.html_url) || '') }}" - } - } - ] - } - ] - } diff --git a/.github/workflows/integration-chaos-tests.yml b/.github/workflows/integration-chaos-tests.yml index c9f7f2661ec..314e54a1ab8 100644 --- a/.github/workflows/integration-chaos-tests.yml +++ b/.github/workflows/integration-chaos-tests.yml @@ -6,49 +6,11 @@ on: tags: - "*" workflow_dispatch: - inputs: - team: - description: Team to run the tests for (e.g. BIX, CCIP) - required: true - type: string jobs: - run-e2e-tests-workflow-dispatch: - name: Run E2E Tests (Workflow Dispatch) - uses: smartcontractkit/.github/.github/workflows/run-e2e-tests.yml@0d4a2b2b009c87b5c366d0b97f7a8d7de2f60760 - if: github.event_name == 'workflow_dispatch' - with: - test_path: .github/e2e-tests.yml - chainlink_version: ${{ github.sha }} - require_chainlink_image_versions_in_qa_ecr: ${{ github.sha }} - test_trigger: E2E Chaos Tests - test_log_level: debug - team: ${{ inputs.team }} - secrets: - QA_AWS_REGION: ${{ secrets.QA_AWS_REGION }} - QA_AWS_ROLE_TO_ASSUME: ${{ secrets.QA_AWS_ROLE_TO_ASSUME }} - QA_AWS_ACCOUNT_NUMBER: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }} - PROD_AWS_ACCOUNT_NUMBER: ${{ secrets.AWS_ACCOUNT_ID_PROD }} - QA_PYROSCOPE_INSTANCE: ${{ secrets.QA_PYROSCOPE_INSTANCE }} - QA_PYROSCOPE_KEY: ${{ secrets.QA_PYROSCOPE_KEY }} - QA_KUBECONFIG: ${{ secrets.QA_KUBECONFIG }} - GRAFANA_INTERNAL_TENANT_ID: ${{ secrets.GRAFANA_INTERNAL_TENANT_ID }} - GRAFANA_INTERNAL_BASIC_AUTH: ${{ secrets.GRAFANA_INTERNAL_BASIC_AUTH }} - GRAFANA_INTERNAL_HOST: ${{ secrets.GRAFANA_INTERNAL_HOST }} - GRAFANA_INTERNAL_URL_SHORTENER_TOKEN: ${{ secrets.GRAFANA_INTERNAL_URL_SHORTENER_TOKEN }} - LOKI_TENANT_ID: ${{ secrets.LOKI_TENANT_ID }} - LOKI_URL: ${{ secrets.LOKI_URL }} - LOKI_BASIC_AUTH: ${{ secrets.LOKI_BASIC_AUTH }} - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - AWS_REGION: ${{ secrets.QA_AWS_REGION }} - AWS_OIDC_IAM_ROLE_VALIDATION_PROD_ARN: ${{ secrets.AWS_OIDC_IAM_ROLE_VALIDATION_PROD_ARN }} - AWS_API_GW_HOST_GRAFANA: ${{ secrets.AWS_API_GW_HOST_GRAFANA }} - SLACK_BOT_TOKEN: ${{ secrets.QA_SLACK_API_KEY }} - run-e2e-tests-workflow: - name: Run E2E Tests (Push and Sechedule) - uses: smartcontractkit/.github/.github/workflows/run-e2e-tests.yml@0d4a2b2b009c87b5c366d0b97f7a8d7de2f60760 - if: github.event_name != 'workflow_dispatch' + name: Run E2E Tests + uses: smartcontractkit/.github/.github/workflows/run-e2e-tests.yml@5412507526722a7b1c5d719fa686eed5a1bc4035 # ctf-run-tests@0.2.0 with: test_path: .github/e2e-tests.yml chainlink_version: ${{ github.sha }} @@ -70,9 +32,8 @@ jobs: LOKI_TENANT_ID: ${{ secrets.LOKI_TENANT_ID }} LOKI_URL: ${{ secrets.LOKI_URL }} LOKI_BASIC_AUTH: ${{ secrets.LOKI_BASIC_AUTH }} - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} AWS_REGION: ${{ secrets.QA_AWS_REGION }} AWS_OIDC_IAM_ROLE_VALIDATION_PROD_ARN: ${{ secrets.AWS_OIDC_IAM_ROLE_VALIDATION_PROD_ARN }} - AWS_API_GW_HOST_GRAFANA: ${{ secrets.AWS_API_GW_HOST_GRAFANA }} + AWS_API_GW_HOST_GRAFANA: ${{ secrets.AWS_API_GW_HOST_GRAFANA }} SLACK_BOT_TOKEN: ${{ secrets.QA_SLACK_API_KEY }} - diff --git a/.github/workflows/integration-in-memory-tests.yml b/.github/workflows/integration-in-memory-tests.yml deleted file mode 100644 index 341d66f641e..00000000000 --- a/.github/workflows/integration-in-memory-tests.yml +++ /dev/null @@ -1,145 +0,0 @@ -# -# Workflow to run in-memory integration tests -# Test matrix is defined in .github/integration-in-memory-tests.yml -# -name: Integration In-Memory Tests -run-name: Integration In-Memory Tests -on: - merge_group: - pull_request: - push: - tags: - - "*" - workflow_dispatch: - inputs: - cl_ref: - description: 'The ref to checkout, defaults to the calling branch' - required: false - type: string - -# Only run 1 of this workflow at a time per PR -concurrency: - group: ${{ github.ref }}-${{ github.repository }}-${{ github.event_name }}--integration-tests - cancel-in-progress: true - -jobs: - changes: - environment: integration - name: Check Paths That Require Tests To Run - runs-on: ubuntu-latest - # We don't directly merge dependabot PRs, so let's not waste the resources - if: github.actor != 'dependabot[bot]' - steps: - - name: Checkout the repo - uses: actions/checkout@v4.2.1 - with: - repository: smartcontractkit/chainlink - ref: ${{ inputs.cl_ref }} - - uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2 - id: changes - with: - filters: | - github_ci_changes: - - '.github/workflows/integration-tests.yml' - - '.github/workflows/integration-in-memory-tests.yml' - - '.github/integration-in-memory-tests.yml' - core_changes: - - '**/*.go' - - '**/*go.sum' - - '**/*go.mod' - - '**/*Dockerfile' - - 'core/**/migrations/*.sql' - - 'core/**/config/**/*.toml' - - 'integration-tests/**/*.toml' - ccip_changes: - - '**/*ccip*' - - '**/*ccip*/**' - - name: Ignore Filter On Workflow Dispatch - if: ${{ github.event_name == 'workflow_dispatch' }} - id: ignore-filter - run: echo "changes=true" >> $GITHUB_OUTPUT - outputs: - github_ci_changes: ${{ steps.ignore-filter.outputs.changes || steps.changes.outputs.github_ci_changes }} - core_changes: ${{ steps.ignore-filter.outputs.changes || steps.changes.outputs.core_changes }} - ccip_changes: ${{ steps.ignore-filter.outputs.changes || steps.changes.outputs.ccip_changes }} - - run-ccip-integration-tests-for-pr: - name: Run CCIP integration Tests For PR - permissions: - actions: read - checks: write - pull-requests: write - id-token: write - contents: read - needs: changes - if: github.event_name == 'pull_request' && ( needs.changes.outputs.ccip_changes == 'true' || needs.changes.outputs.core_changes == 'true' || needs.changes.outputs.github_ci_changes == 'true') - uses: smartcontractkit/.github/.github/workflows/run-integration-tests.yml@0632b5652dd5eb03bfa87e23a2b3e2911484fe59 - with: - workflow_name: Run CCIP Integration Tests For PR - test_path: .github/integration-in-memory-tests.yml - test_trigger: PR Integration CCIP Tests - secrets: - QA_AWS_REGION: ${{ secrets.QA_AWS_REGION }} - QA_AWS_ROLE_TO_ASSUME: ${{ secrets.QA_AWS_ROLE_TO_ASSUME }} - QA_AWS_ACCOUNT_NUMBER: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }} - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - SLACK_BOT_TOKEN: ${{ secrets.QA_SLACK_API_KEY }} - - run-ccip-integration-tests-for-merge-queue: - name: Run CCIP Integration Tests For Merge Queue - permissions: - actions: read - checks: write - pull-requests: write - id-token: write - contents: read - needs: changes - if: github.event_name == 'merge_group' && ( needs.changes.outputs.ccip_changes == 'true' || needs.changes.outputs.core_changes == 'true' || needs.changes.outputs.github_ci_changes == 'true') - uses: smartcontractkit/.github/.github/workflows/run-integration-tests.yml@0632b5652dd5eb03bfa87e23a2b3e2911484fe59 - with: - workflow_name: Run CCIP Integration Tests For Merge Queue - test_path: .github/integration-in-memory-tests.yml - test_trigger: Merge Queue Integration CCIP Tests - slack_notification_after_tests: on_failure - slack_notification_after_tests_channel_id: "#ccip-testing" - slack_notification_after_tests_name: CCIP integration Tests In Merge Queue - secrets: - QA_AWS_REGION: ${{ secrets.QA_AWS_REGION }} - QA_AWS_ROLE_TO_ASSUME: ${{ secrets.QA_AWS_ROLE_TO_ASSUME }} - QA_AWS_ACCOUNT_NUMBER: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }} - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - SLACK_BOT_TOKEN: ${{ secrets.QA_SLACK_API_KEY }} - - check-integration-test-results: - if: always() - name: Integration Tests - runs-on: ubuntu-latest - needs: [run-ccip-integration-tests-for-pr,run-ccip-integration-tests-for-merge-queue] - steps: - - name: Fail the job if ccip tests in PR not successful - if: always() && needs.run-ccip-integration-tests-for-pr.result == 'failure' - run: exit 1 - - - name: Fail the job if ccip tests in merge queue not successful - if: always() && needs.run-ccip-integration-tests-for-merge-queue.result == 'failure' - run: exit 1 - - cleanup: - name: Clean up integration environment deployments - if: always() - needs: [run-ccip-integration-tests-for-pr, run-ccip-integration-tests-for-merge-queue] - runs-on: ubuntu-latest - steps: - - name: Checkout repo - if: ${{ github.event_name == 'pull_request' }} - uses: actions/checkout@v4.2.1 - with: - repository: smartcontractkit/chainlink - ref: ${{ inputs.cl_ref }} - - - name: 🧼 Clean up Environment - if: ${{ github.event_name == 'pull_request' }} - uses: ./.github/actions/delete-deployments - with: - environment: integration - ref: ${{ github.head_ref }} # See https://github.com/github/docs/issues/15319#issuecomment-1476705663 \ No newline at end of file diff --git a/.github/workflows/integration-tests.yml b/.github/workflows/integration-tests.yml index e79956cc253..08383aed12d 100644 --- a/.github/workflows/integration-tests.yml +++ b/.github/workflows/integration-tests.yml @@ -1,5 +1,3 @@ -# N/B: ci-core, which runs on PRs, will trigger linting for affected directories/modules -# no need to run lint twice name: Integration Tests run-name: Integration Tests ${{ inputs.distinct_run_name && inputs.distinct_run_name || '' }} on: @@ -118,6 +116,47 @@ jobs: core_changes: ${{ steps.ignore-filter.outputs.changes || steps.changes.outputs.core_changes }} ccip_changes: ${{ steps.ignore-filter.outputs.changes || steps.changes.outputs.ccip_changes }} + lint-integration-tests: + name: Lint ${{ matrix.project.name }} + runs-on: ubuntu-24.04-8cores-32GB-ARM + # We don't directly merge dependabot PRs, so let's not waste the resources + if: github.actor != 'dependabot[bot]' + strategy: + matrix: + project: + - name: integration-tests + id: e2e-tests + path: ./integration-tests + cache_id: e2e-tests + - name: load + id: load + path: ./integration-tests/load + cache_id: load + steps: + - name: Checkout the repo + uses: actions/checkout@v4.2.1 + with: + repository: smartcontractkit/chainlink + ref: ${{ inputs.cl_ref }} + - name: Setup Go + uses: smartcontractkit/.github/actions/ctf-setup-go@b0d756c57fcdbcff187e74166562a029fdd5d1b9 # ctf-setup-go@0.0.0 + with: + test_download_vendor_packages_command: cd ${{ matrix.project.path }} && go mod download + go_mod_path: ${{ matrix.project.path }}/go.mod + cache_key_id: ${{ matrix.project.cache_id }} + cache_restore_only: "true" + - name: Lint Go + uses: golangci/golangci-lint-action@3cfe3a4abbb849e10058ce4af15d205b6da42804 # v4.0.0 + with: + version: v1.59.1 + # We already cache these directories in setup-go + skip-pkg-cache: true + skip-build-cache: true + # only-new-issues is only applicable to PRs, otherwise it is always set to false + only-new-issues: false # disabled for PRs due to unreliability + args: --out-format colored-line-number,checkstyle:golangci-lint-report.xml + working-directory: ${{ matrix.project.path }} + build-chainlink: environment: integration permissions: @@ -132,7 +171,6 @@ jobs: - name: (plugins) dockerfile: plugins/chainlink.Dockerfile tag-suffix: -plugins - name: Build Chainlink Image ${{ matrix.image.name }} runs-on: ubuntu22.04-8cores-32GB needs: [changes, enforce-ctf-version] @@ -172,7 +210,7 @@ jobs: contents: read needs: [build-chainlink, changes] if: github.event_name == 'pull_request' && ( needs.changes.outputs.core_changes == 'true' || needs.changes.outputs.github_ci_changes == 'true') - uses: smartcontractkit/.github/.github/workflows/run-e2e-tests.yml@0632b5652dd5eb03bfa87e23a2b3e2911484fe59 + uses: smartcontractkit/.github/.github/workflows/run-e2e-tests.yml@5412507526722a7b1c5d719fa686eed5a1bc4035 # ctf-run-tests@0.2.0 with: workflow_name: Run Core E2E Tests For PR chainlink_version: ${{ inputs.evm-ref || github.sha }} @@ -213,7 +251,7 @@ jobs: contents: read needs: [build-chainlink, changes] if: github.event_name == 'merge_group' && ( needs.changes.outputs.core_changes == 'true' || needs.changes.outputs.github_ci_changes == 'true') - uses: smartcontractkit/.github/.github/workflows/run-e2e-tests.yml@0632b5652dd5eb03bfa87e23a2b3e2911484fe59 + uses: smartcontractkit/.github/.github/workflows/run-e2e-tests.yml@5412507526722a7b1c5d719fa686eed5a1bc4035 # ctf-run-tests@0.2.0 with: workflow_name: Run Core E2E Tests For Merge Queue chainlink_version: ${{ inputs.evm-ref || github.sha }} @@ -258,7 +296,7 @@ jobs: contents: read needs: [build-chainlink, changes] if: github.event_name == 'pull_request' && (needs.changes.outputs.ccip_changes == 'true' || needs.changes.outputs.github_ci_changes == 'true') - uses: smartcontractkit/.github/.github/workflows/run-e2e-tests.yml@0632b5652dd5eb03bfa87e23a2b3e2911484fe59 + uses: smartcontractkit/.github/.github/workflows/run-e2e-tests.yml@5412507526722a7b1c5d719fa686eed5a1bc4035 # ctf-run-tests@0.2.0 with: workflow_name: Run CCIP E2E Tests For PR chainlink_version: ${{ inputs.evm-ref || github.sha }} @@ -268,7 +306,6 @@ jobs: upload_cl_node_coverage_artifact: true upload_cl_node_coverage_artifact_prefix: cl_node_coverage_data_ enable_otel_traces_for_ocr2_plugins: ${{ contains(join(github.event.pull_request.labels.*.name, ' '), 'enable tracing') }} - team: "CCIP" secrets: QA_AWS_REGION: ${{ secrets.QA_AWS_REGION }} QA_AWS_ROLE_TO_ASSUME: ${{ secrets.QA_AWS_ROLE_TO_ASSUME }} @@ -300,7 +337,7 @@ jobs: contents: read needs: [build-chainlink, changes] if: github.event_name == 'merge_group' && (needs.changes.outputs.ccip_changes == 'true' || needs.changes.outputs.github_ci_changes == 'true') - uses: smartcontractkit/.github/.github/workflows/run-e2e-tests.yml@0632b5652dd5eb03bfa87e23a2b3e2911484fe59 + uses: smartcontractkit/.github/.github/workflows/run-e2e-tests.yml@5412507526722a7b1c5d719fa686eed5a1bc4035 # ctf-run-tests@0.2.0 with: workflow_name: Run CCIP E2E Tests For Merge Queue chainlink_version: ${{ inputs.evm-ref || github.sha }} @@ -310,7 +347,6 @@ jobs: upload_cl_node_coverage_artifact: true upload_cl_node_coverage_artifact_prefix: cl_node_coverage_data_ enable_otel_traces_for_ocr2_plugins: ${{ contains(join(github.event.pull_request.labels.*.name, ' '), 'enable tracing') }} - team: "CCIP" secrets: QA_AWS_REGION: ${{ secrets.QA_AWS_REGION }} QA_AWS_ROLE_TO_ASSUME: ${{ secrets.QA_AWS_ROLE_TO_ASSUME }} @@ -336,7 +372,7 @@ jobs: if: always() name: ETH Smoke Tests runs-on: ubuntu-latest - needs: [run-core-e2e-tests-for-pr, run-ccip-e2e-tests-for-pr, run-core-e2e-tests-for-merge-queue, run-ccip-e2e-tests-for-merge-queue] + needs: [lint-integration-tests, run-core-e2e-tests-for-pr, run-ccip-e2e-tests-for-pr, run-core-e2e-tests-for-merge-queue, run-ccip-e2e-tests-for-merge-queue] steps: - name: Check Core test results id: check_core_results @@ -344,7 +380,7 @@ jobs: results='${{ needs.run-core-e2e-tests-for-pr.outputs.test_results }}' echo "Core test results:" echo "$results" | jq . - + node_migration_tests_failed=$(echo $results | jq '[.[] | select(.id == "integration-tests/migration/upgrade_version_test.go:*" ) | select(.result != "success")] | length > 0') echo "node_migration_tests_failed=$node_migration_tests_failed" >> $GITHUB_OUTPUT @@ -376,6 +412,10 @@ jobs: if: always() && needs.run-core-e2e-tests-for-merge-queue.result == 'failure' run: exit 1 + - name: Fail the job if lint not successful + if: always() && needs.lint-integration-tests.result == 'failure' + run: exit 1 + cleanup: name: Clean up integration environment deployments if: always() @@ -552,7 +592,6 @@ jobs: ] env: CONTRACT_ARTIFACTS_PATH: contracts/target/deploy - GOTOOLCHAIN: auto steps: - name: Checkout the repo if: (needs.changes.outputs.core_changes == 'true' || github.event_name == 'workflow_dispatch') && needs.solana-test-image-exists.outputs.exists == 'false' @@ -688,7 +727,6 @@ jobs: env: E2E_TEST_CHAINLINK_IMAGE: ${{ env.CHAINLINK_IMAGE }} E2E_TEST_SOLANA_SECRET: thisisatestingonlysecret - CHAINLINK_USER_TEAM: "BIX" - name: Upload Coverage Data uses: actions/upload-artifact@v4.4.3 diff --git a/.github/workflows/on-demand-ocr-soak-test.yml b/.github/workflows/on-demand-ocr-soak-test.yml index a9a8c3c2a2f..ac97d3c6355 100644 --- a/.github/workflows/on-demand-ocr-soak-test.yml +++ b/.github/workflows/on-demand-ocr-soak-test.yml @@ -34,23 +34,18 @@ on: slackMemberID: description: Slack Member ID (Not your @) required: true - default: U01A2B2C3D4 - team: - description: Team to run the tests for (e.g. BIX, CCIP) - required: true - type: string + default: U01A2B2C3D4 jobs: run-e2e-tests-workflow: name: Run E2E Tests - uses: smartcontractkit/.github/.github/workflows/run-e2e-tests.yml@0d4a2b2b009c87b5c366d0b97f7a8d7de2f60760 + uses: smartcontractkit/.github/.github/workflows/run-e2e-tests.yml@5412507526722a7b1c5d719fa686eed5a1bc4035 # ctf-run-tests@0.2.0 with: test_path: .github/e2e-tests.yml test_ids: ${{ inputs.testToRun}} test_config_override_path: ${{ inputs.test_config_override_path }} chainlink_version: ${{ inputs.chainlink_version }} SLACK_USER: ${{ inputs.slackMemberID }} - team: ${{ inputs.team }} secrets: QA_AWS_REGION: ${{ secrets.QA_AWS_REGION }} QA_AWS_ROLE_TO_ASSUME: ${{ secrets.QA_AWS_ROLE_TO_ASSUME }} diff --git a/.github/workflows/on-demand-vrfv2-performance-test.yml b/.github/workflows/on-demand-vrfv2-performance-test.yml index f9aeaa0fa1f..aadef377718 100644 --- a/.github/workflows/on-demand-vrfv2-performance-test.yml +++ b/.github/workflows/on-demand-vrfv2-performance-test.yml @@ -67,7 +67,7 @@ jobs: run-e2e-tests-workflow: name: Run E2E Tests needs: set-tests-to-run - uses: smartcontractkit/.github/.github/workflows/run-e2e-tests.yml@0632b5652dd5eb03bfa87e23a2b3e2911484fe59 + uses: smartcontractkit/.github/.github/workflows/run-e2e-tests.yml@5412507526722a7b1c5d719fa686eed5a1bc4035 # ctf-run-tests@0.2.0 with: custom_test_list_json: ${{ needs.set-tests-to-run.outputs.test_list }} chainlink_version: ${{ inputs.chainlink_version }} diff --git a/.github/workflows/on-demand-vrfv2-smoke-tests.yml b/.github/workflows/on-demand-vrfv2-smoke-tests.yml index ad616dea744..4ebc38a8081 100644 --- a/.github/workflows/on-demand-vrfv2-smoke-tests.yml +++ b/.github/workflows/on-demand-vrfv2-smoke-tests.yml @@ -70,7 +70,7 @@ jobs: run-e2e-tests-workflow: name: Run E2E Tests needs: set-tests-to-run - uses: smartcontractkit/.github/.github/workflows/run-e2e-tests.yml@0632b5652dd5eb03bfa87e23a2b3e2911484fe59 + uses: smartcontractkit/.github/.github/workflows/run-e2e-tests.yml@5412507526722a7b1c5d719fa686eed5a1bc4035 # ctf-run-tests@0.2.0 with: custom_test_list_json: ${{ needs.set-tests-to-run.outputs.test_list }} chainlink_version: ${{ inputs.chainlink_version }} diff --git a/.github/workflows/on-demand-vrfv2plus-performance-test.yml b/.github/workflows/on-demand-vrfv2plus-performance-test.yml index b3a820e25a0..f6d120ac178 100644 --- a/.github/workflows/on-demand-vrfv2plus-performance-test.yml +++ b/.github/workflows/on-demand-vrfv2plus-performance-test.yml @@ -67,7 +67,7 @@ jobs: run-e2e-tests-workflow: name: Run E2E Tests needs: set-tests-to-run - uses: smartcontractkit/.github/.github/workflows/run-e2e-tests.yml@0632b5652dd5eb03bfa87e23a2b3e2911484fe59 + uses: smartcontractkit/.github/.github/workflows/run-e2e-tests.yml@5412507526722a7b1c5d719fa686eed5a1bc4035 # ctf-run-tests@0.2.0 with: custom_test_list_json: ${{ needs.set-tests-to-run.outputs.test_list }} chainlink_version: ${{ inputs.chainlink_version }} diff --git a/.github/workflows/on-demand-vrfv2plus-smoke-tests.yml b/.github/workflows/on-demand-vrfv2plus-smoke-tests.yml index 8561034b103..af26c527988 100644 --- a/.github/workflows/on-demand-vrfv2plus-smoke-tests.yml +++ b/.github/workflows/on-demand-vrfv2plus-smoke-tests.yml @@ -70,7 +70,7 @@ jobs: run-e2e-tests-workflow: name: Run E2E Tests needs: set-tests-to-run - uses: smartcontractkit/.github/.github/workflows/run-e2e-tests.yml@0632b5652dd5eb03bfa87e23a2b3e2911484fe59 + uses: smartcontractkit/.github/.github/workflows/run-e2e-tests.yml@5412507526722a7b1c5d719fa686eed5a1bc4035 # ctf-run-tests@0.2.0 with: custom_test_list_json: ${{ needs.set-tests-to-run.outputs.test_list }} chainlink_version: ${{ inputs.chainlink_version }} diff --git a/.github/workflows/flakeguard-on-demand.yml b/.github/workflows/run-find-new-flaky-tests.yml similarity index 64% rename from .github/workflows/flakeguard-on-demand.yml rename to .github/workflows/run-find-new-flaky-tests.yml index f6df40616f7..d1318719349 100644 --- a/.github/workflows/flakeguard-on-demand.yml +++ b/.github/workflows/run-find-new-flaky-tests.yml @@ -1,4 +1,4 @@ -name: Flakeguard On Demand +name: Find Flaky Tests on: workflow_dispatch: @@ -14,23 +14,24 @@ on: description: 'The path to the project to run the flaky test detection.' default: '.' baseRef: - required: false + required: true type: string - description: 'The base reference or branch to compare changes for detecting flaky tests. Set only when running diffs between branches. E.g. (develop)' + description: 'The base reference or branch to compare changes for detecting flaky tests.' + default: 'origin/develop' headRef: required: false type: string - description: 'The head reference or branch to compare changes for detecting flaky tests. Default is the current branch. E.g. (develop)' + description: 'The head reference or branch to compare changes for detecting flaky tests. Default is the current branch.' runAllTests: required: false type: boolean description: 'Run all tests in the project.' - default: true - maxPassRatio: + default: false + runThreshold: required: false type: string - description: 'The maximum (non-inclusive) pass ratio threshold for a test to be considered a failure. Any tests below this pass rate will be considered flaky.' - default: '1.0' + description: 'The threshold for the number of times a test can fail before being considered flaky.' + default: '0.8' findByTestFilesDiff: required: false type: boolean @@ -40,7 +41,7 @@ on: required: false type: boolean description: 'Find new or updated test packages by comparing affected packages.' - default: false + default: true slack_notification_after_tests_channel_id: description: "Slack channel ID to send the notification to for failed tests." required: false @@ -48,26 +49,23 @@ on: extraArgs: required: false type: string - default: '{ "skipped_tests": "TestChainComponents", "test_repeat_count": "5", "all_tests_runner": "ubuntu22.04-32cores-128GB", "all_tests_runner_count": "3", "run_with_race": "false" }' - description: 'JSON of extra arguments for the workflow.' + default: '{}' + description: 'JSON of extra arguments for the workflow.' jobs: trigger-flaky-test-detection: name: Find Flaky Tests - uses: ./.github/workflows/flakeguard.yml + uses: ./.github/workflows/find-new-flaky-tests.yml with: repoUrl: ${{ inputs.repoUrl }} baseRef: ${{ inputs.baseRef }} projectPath: ${{ inputs.projectPath }} headRef: ${{ inputs.headRef }} - maxPassRatio: ${{ inputs.maxPassRatio }} + runThreshold: ${{ inputs.runThreshold }} runAllTests: ${{ inputs.runAllTests }} findByTestFilesDiff: ${{ inputs.findByTestFilesDiff }} findByAffectedPackages: ${{ inputs.findByAffectedPackages }} - slackNotificationAfterTestsChannelId: ${{ inputs.slack_notification_after_tests_channel_id || 'C07TRF65CNS' }} #flaky-test-detector-notifications + slackNotificationAfterTestsChannelId: ${{ inputs.slack_notification_after_tests_channel_id }} extraArgs: ${{ inputs.extraArgs }} secrets: - SLACK_BOT_TOKEN: ${{ secrets.QA_SLACK_API_KEY }} - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - FLAKEGUARD_SPLUNK_ENDPOINT: ${{ secrets.FLAKEGUARD_SPLUNK_ENDPOINT }} - FLAKEGUARD_SPLUNK_HEC: ${{ secrets.FLAKEGUARD_SPLUNK_HEC }} + SLACK_BOT_TOKEN: ${{ secrets.QA_SLACK_API_KEY }} \ No newline at end of file diff --git a/.github/workflows/run-nightly-e2e-tests.yml b/.github/workflows/run-nightly-e2e-tests.yml index 712fb088181..eba1108f89f 100644 --- a/.github/workflows/run-nightly-e2e-tests.yml +++ b/.github/workflows/run-nightly-e2e-tests.yml @@ -20,7 +20,7 @@ on: jobs: call-run-e2e-tests-workflow: name: Run E2E Tests - uses: smartcontractkit/.github/.github/workflows/run-e2e-tests.yml@0632b5652dd5eb03bfa87e23a2b3e2911484fe59 + uses: smartcontractkit/.github/.github/workflows/run-e2e-tests.yml@5412507526722a7b1c5d719fa686eed5a1bc4035 # ctf-run-tests@0.2.0 with: chainlink_version: ${{ inputs.chainlink_version || 'develop' }} test_path: .github/e2e-tests.yml diff --git a/.github/workflows/run-nightly-flaky-test-detector.yml b/.github/workflows/run-nightly-flaky-test-detector.yml new file mode 100644 index 00000000000..1c5dc72d4a3 --- /dev/null +++ b/.github/workflows/run-nightly-flaky-test-detector.yml @@ -0,0 +1,22 @@ +name: Run Nightly Flaky Test Detector + +on: + schedule: + # Run every night at 3:00 AM UTC + - cron: '0 3 * * *' + workflow_dispatch: # Allows manual trigger for debugging + +jobs: + trigger-flaky-test-detection: + name: Find Flaky Tests + uses: ./.github/workflows/find-new-flaky-tests.yml + with: + repoUrl: 'https://github.com/smartcontractkit/chainlink' + baseRef: 'origin/develop' + projectPath: '.' + runThreshold: '1' + runAllTests: true + extraArgs: '{ "skipped_tests": "TestChainComponents", "test_repeat_count": "5", "all_tests_runner": "ubuntu22.04-32cores-128GB", "all_tests_runner_count": "3", "min_pass_ratio": "0", "run_with_race": "false" }' + secrets: + SLACK_BOT_TOKEN: ${{ secrets.QA_SLACK_API_KEY }} + \ No newline at end of file diff --git a/.github/workflows/run-selected-e2e-tests.yml b/.github/workflows/run-selected-e2e-tests.yml index e95ce1cef19..0e7c97c67fc 100644 --- a/.github/workflows/run-selected-e2e-tests.yml +++ b/.github/workflows/run-selected-e2e-tests.yml @@ -35,7 +35,7 @@ run-name: ${{ inputs.workflow_run_name }} jobs: call-run-e2e-tests-workflow: name: Run E2E Tests - uses: smartcontractkit/.github/.github/workflows/run-e2e-tests.yml@0632b5652dd5eb03bfa87e23a2b3e2911484fe59 + uses: smartcontractkit/.github/.github/workflows/run-e2e-tests.yml@5412507526722a7b1c5d719fa686eed5a1bc4035 # ctf-run-tests@0.2.0 with: chainlink_version: ${{ github.event.inputs.chainlink_version }} test_path: .github/e2e-tests.yml diff --git a/.github/workflows/solidity-foundry-artifacts.yml b/.github/workflows/solidity-foundry-artifacts.yml index dbf31a4b442..5a971f65174 100644 --- a/.github/workflows/solidity-foundry-artifacts.yml +++ b/.github/workflows/solidity-foundry-artifacts.yml @@ -16,6 +16,7 @@ on: - "llo-feeds" - "operatorforwarder" - "shared" + - "transmission" - "vrf" - "workflow" commit_to_use: diff --git a/.github/workflows/solidity-foundry.yml b/.github/workflows/solidity-foundry.yml index 5c6889beaf8..efbdd77ccb5 100644 --- a/.github/workflows/solidity-foundry.yml +++ b/.github/workflows/solidity-foundry.yml @@ -30,16 +30,17 @@ jobs: cat < matrix.json [ { "name": "automation", "setup": { "run-coverage": false, "min-coverage": 98.5, "run-gas-snapshot": false, "run-forge-fmt": false }}, - { "name": "ccip", "setup": { "run-coverage": true, "min-coverage": 98.8, "extra-coverage-params": "--no-match-path='*End2End*'", "run-gas-snapshot": true, "run-forge-fmt": true }}, + { "name": "ccip", "setup": { "run-coverage": true, "min-coverage": 98.8, "run-gas-snapshot": true, "run-forge-fmt": true }}, { "name": "functions", "setup": { "run-coverage": false, "min-coverage": 98.5, "run-gas-snapshot": true, "run-forge-fmt": false }}, { "name": "keystone", "setup": { "run-coverage": true, "min-coverage": 72.8, "run-gas-snapshot": false, "run-forge-fmt": false }}, - { "name": "l2ep", "setup": { "run-coverage": true, "min-coverage": 65.0, "run-gas-snapshot": true, "run-forge-fmt": false }}, - { "name": "liquiditymanager", "setup": { "run-coverage": true, "min-coverage": 40, "run-gas-snapshot": true, "run-forge-fmt": false }}, + { "name": "l2ep", "setup": { "run-coverage": true, "min-coverage": 61.0, "run-gas-snapshot": true, "run-forge-fmt": false }}, + { "name": "liquiditymanager", "setup": { "run-coverage": true, "min-coverage": 46.3, "run-gas-snapshot": true, "run-forge-fmt": false }}, { "name": "llo-feeds", "setup": { "run-coverage": true, "min-coverage": 49.3, "run-gas-snapshot": true, "run-forge-fmt": false }}, { "name": "operatorforwarder", "setup": { "run-coverage": true, "min-coverage": 55.7, "run-gas-snapshot": true, "run-forge-fmt": false }}, { "name": "shared", "setup": { "run-coverage": true, "extra-coverage-params": "--no-match-path='*CallWithExactGas*' --ir-minimum", "min-coverage": 32.6, "run-gas-snapshot": true, "run-forge-fmt": false }}, + { "name": "transmission", "setup": { "run-coverage": true, "min-coverage": 61.5, "run-gas-snapshot": true, "run-forge-fmt": false }}, { "name": "vrf", "setup": { "run-coverage": false, "min-coverage": 98.5, "run-gas-snapshot": false, "run-forge-fmt": false }}, - { "name": "workflow", "setup": { "run-coverage": true, "extra-coverage-params": "--ir-minimum", "min-coverage": 96.0, "run-gas-snapshot": true, "run-forge-fmt": true }} + { "name": "workflow", "setup": { "run-coverage": true, "extra-coverage-params": "--ir-minimum", "min-coverage": 65.0, "run-gas-snapshot": false, "run-forge-fmt": true }} ] EOF @@ -111,6 +112,8 @@ jobs: - 'contracts/src/v0.8/mocks/**/*.sol' - 'contracts/src/v0.8/tests/**/*.sol' - 'contracts/src/v0.8/vendor/**/*.sol' + transmission: + - 'contracts/src/v0.8/transmission/**/*.sol' workflow: - 'contracts/src/v0.8/workflow/**/*.sol' diff --git a/.github/workflows/solidity-hardhat.yml b/.github/workflows/solidity-hardhat.yml index 6f27f8ca2f8..7283e17e13f 100644 --- a/.github/workflows/solidity-hardhat.yml +++ b/.github/workflows/solidity-hardhat.yml @@ -25,7 +25,7 @@ jobs: with: filters: | src: - - 'contracts/src/!(v0.8/(ccip|functions|keystone|l2ep|liquiditymanager|llo-feeds|vrf|workflow)/**)/**/*' + - 'contracts/src/!(v0.8/(ccip|functions|keystone|l2ep|liquiditymanager|llo-feeds|transmission|vrf|workflow)/**)/**/*' - 'contracts/test/**/*' - 'contracts/package.json' - 'contracts/pnpm-lock.yaml' diff --git a/.github/workflows/solidity-traceability.yml b/.github/workflows/solidity-tracability.yml similarity index 99% rename from .github/workflows/solidity-traceability.yml rename to .github/workflows/solidity-tracability.yml index caa233ea8bb..f0b1166807f 100644 --- a/.github/workflows/solidity-traceability.yml +++ b/.github/workflows/solidity-tracability.yml @@ -1,5 +1,5 @@ # This workflow handles the enforcement of code Traceability via changesets and jira issue linking for our Solidity codebase. -name: Solidity Traceability +name: Solidity Tracability on: merge_group: diff --git a/.github/workflows/solidity.yml b/.github/workflows/solidity.yml index 605b3f2e325..fb826b0f185 100644 --- a/.github/workflows/solidity.yml +++ b/.github/workflows/solidity.yml @@ -76,44 +76,28 @@ jobs: steps: - name: Checkout the repo uses: actions/checkout@v4.2.1 - with: - path: chainlink - - name: Checkout diff-so-fancy uses: actions/checkout@v4.2.1 with: repository: so-fancy/diff-so-fancy ref: a673cb4d2707f64d92b86498a2f5f71c8e2643d5 # v1.4.3 path: diff-so-fancy - - name: Install diff-so-fancy run: echo "$GITHUB_WORKSPACE/diff-so-fancy" >> $GITHUB_PATH - - name: Setup NodeJS - uses: ./chainlink/.github/actions/setup-nodejs + uses: ./.github/actions/setup-nodejs with: - base-path: "chainlink" prod: "true" - - name: Setup Go - uses: ./chainlink/.github/actions/setup-go - with: - go-version-file: "chainlink/go.mod" - + uses: ./.github/actions/setup-go - name: Run native compile and generate wrappers - working-directory: ./chainlink/contracts run: make wrappers-all - + working-directory: ./contracts - name: Verify local solc binaries - working-directory: chainlink run: ./tools/ci/check_solc_hashes - - name: Check if Go solidity wrappers are updated if: ${{ needs.changes.outputs.changes == 'true' }} - working-directory: chainlink - run: | - git add --all - git diff --minimal --color --cached --exit-code | diff-so-fancy + run: git diff --minimal --color --exit-code | diff-so-fancy # The if statements for steps after checkout repo is a workaround for # passing required check for PRs that don't have filtered changes. diff --git a/.gitignore b/.gitignore index af19562c928..34d25ebb472 100644 --- a/.gitignore +++ b/.gitignore @@ -48,8 +48,9 @@ cl_backup_*.tar.gz # Test artifacts core/cmd/TestClient_ImportExportP2PKeyBundle_test_key.json +output.txt race.* -*output.txt +golangci-lint-output.txt /golangci-lint/ .covdata core/services/job/testdata/wasm/testmodule.wasm diff --git a/.golangci.yml b/.golangci.yml index 63b061c2951..ca8cf4dade5 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -1,6 +1,5 @@ run: - timeout: 15m - allow-parallel-runners: true + timeout: 15m0s linters: enable: - containedctx @@ -97,7 +96,7 @@ linters-settings: - name: waitgroup-by-value - name: unconditional-recursion - name: struct-tag - - name: string-format + # - name: string-format - name: string-of-int - name: range-val-address - name: range-val-in-closure diff --git a/.mockery.yaml b/.mockery.yaml index 5777ca1da92..711d70f59e9 100644 --- a/.mockery.yaml +++ b/.mockery.yaml @@ -234,7 +234,6 @@ packages: config: filename: starknet.go VRF: - Workflow: github.com/smartcontractkit/chainlink/v2/core/services/ocr: interfaces: OCRContractTrackerDB: @@ -348,7 +347,7 @@ packages: Codec: config: dir: core/services/relay/evm/mocks - ContractWriter: + ChainWriter: github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/evm_2_evm_onramp: config: dir: core/gethwrappers/ccip/mocks/ @@ -580,15 +579,6 @@ packages: github.com/smartcontractkit/chainlink/v2/core/services/registrysyncer: interfaces: ORM: - github.com/smartcontractkit/chainlink/v2/core/services/workflows/syncer: - interfaces: - ORM: - Handler: - config: - mockname: "Mock{{ .InterfaceName }}" - filename: handler_mock.go - inpackage: true - dir: "{{ .InterfaceDir }}" github.com/smartcontractkit/chainlink/v2/core/capabilities/targets: interfaces: ContractValueGetter: \ No newline at end of file diff --git a/.tool-versions b/.tool-versions index bdf11a7ed21..70b6d01ce14 100644 --- a/.tool-versions +++ b/.tool-versions @@ -1,10 +1,9 @@ -golang 1.23.3 +golang 1.22.8 mockery 2.46.3 nodejs 20.13.1 pnpm 9.4.0 postgres 15.1 helm 3.10.3 -golangci-lint 1.62.2 +golangci-lint 1.61.0 protoc 25.1 python 3.10.5 -act 0.2.30 diff --git a/GNUmakefile b/GNUmakefile index 08324b1fec4..592183923e2 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -4,7 +4,6 @@ COMMIT_SHA ?= $(shell git rev-parse HEAD) VERSION = $(shell jq -r '.version' package.json) GO_LDFLAGS := $(shell tools/bin/ldflags) GOFLAGS = -ldflags "$(GO_LDFLAGS)" -GCFLAGS = -gcflags "$(GO_GCFLAGS)" .PHONY: install install: install-chainlink-autoinstall ## Install chainlink and all its dependencies. @@ -39,7 +38,7 @@ docs: ## Install and run pkgsite to view Go docs .PHONY: install-chainlink install-chainlink: operator-ui ## Install the chainlink binary. - go install $(GCFLAGS) $(GOFLAGS) . + go install $(GOFLAGS) . .PHONY: install-chainlink-cover install-chainlink-cover: operator-ui ## Install the chainlink binary with cover flag. @@ -98,7 +97,7 @@ abigen: ## Build & install abigen. .PHONY: generate generate: abigen codecgen mockery protoc gomods ## Execute all go:generate commands. gomods -w go generate -x ./... - find . -type f -name .mockery.yaml -execdir mockery \; ## Execute mockery for all .mockery.yaml files + mockery .PHONY: rm-mocked rm-mocked: @@ -134,16 +133,17 @@ testdb-force: ## Prepares the test database, drops any pesky user connections th testdb-user-only: ## Prepares the test database with user only. go run . local db preparetest --user-only +# Format for CI +.PHONY: presubmit +presubmit: ## Format go files and imports. + goimports -w . + gofmt -w . + go mod tidy + .PHONY: gomods gomods: ## Install gomods go install github.com/jmank88/gomods@v0.1.4 -.PHONY: gomodslocalupdate -gomodslocalupdate: gomods ## Run gomod-local-update - go install ./tools/gomod-local-update/cmd/gomod-local-update - gomods -w gomod-local-update - gomods tidy - .PHONY: mockery mockery: $(mockery) ## Install mockery. go install github.com/vektra/mockery/v2@v2.46.3 @@ -174,7 +174,7 @@ config-docs: ## Generate core node configuration documentation .PHONY: golangci-lint golangci-lint: ## Run golangci-lint for all issues. [ -d "./golangci-lint" ] || mkdir ./golangci-lint && \ - docker run --rm -v $(shell pwd):/app -w /app golangci/golangci-lint:v1.62.2 golangci-lint run --max-issues-per-linter 0 --max-same-issues 0 | tee ./golangci-lint/$(shell date +%Y-%m-%d_%H:%M:%S).txt + docker run --rm -v $(shell pwd):/app -w /app golangci/golangci-lint:v1.61.0 golangci-lint run --max-issues-per-linter 0 --max-same-issues 0 | tee ./golangci-lint/$(shell date +%Y-%m-%d_%H:%M:%S).txt .PHONY: modgraph modgraph: diff --git a/README.md b/README.md index 2dc51e9cf0d..e7c21c1e094 100644 --- a/README.md +++ b/README.md @@ -32,7 +32,7 @@ regarding Chainlink social accounts, news, and networking. ## Build Chainlink -1. [Install Go 1.23](https://golang.org/doc/install), and add your GOPATH's [bin directory to your PATH](https://golang.org/doc/code.html#GOPATH) +1. [Install Go 1.22](https://golang.org/doc/install), and add your GOPATH's [bin directory to your PATH](https://golang.org/doc/code.html#GOPATH) - Example Path for macOS `export PATH=$GOPATH/bin:$PATH` & `export GOPATH=/Users/$USER/go` 2. Install [NodeJS v20](https://nodejs.org/en/download/package-manager/) & [pnpm v9 via npm](https://pnpm.io/installation#using-npm). - It might be easier long term to use [nvm](https://nodejs.org/en/download/package-manager/#nvm) to switch between node versions for different projects. For example, assuming $NODE_VERSION was set to a valid version of NodeJS, you could run: `nvm install $NODE_VERSION && nvm use $NODE_VERSION` diff --git a/ccip/config/evm/Avalanche_Fuji.toml b/ccip/config/evm/Avalanche_Fuji.toml index 7df1d26a336..91b8bf6bab8 100644 --- a/ccip/config/evm/Avalanche_Fuji.toml +++ b/ccip/config/evm/Avalanche_Fuji.toml @@ -10,8 +10,9 @@ RPCBlockQueryDelay = 2 NoNewFinalizedHeadsThreshold = '1m' [GasEstimator] -PriceMin = '1 gwei' -PriceDefault = '1 gwei' +PriceDefault = '25 gwei' +PriceMax = '115792089237316195423570985008687907853269984665.640564039457584007913129639935 tether' +PriceMin = '25 gwei' [GasEstimator.BlockHistory] BlockHistorySize = 24 diff --git a/ccip/config/evm/Avalanche_Mainnet.toml b/ccip/config/evm/Avalanche_Mainnet.toml index 341ae5478b3..f51af60098d 100644 --- a/ccip/config/evm/Avalanche_Mainnet.toml +++ b/ccip/config/evm/Avalanche_Mainnet.toml @@ -10,8 +10,9 @@ RPCBlockQueryDelay = 2 NoNewFinalizedHeadsThreshold = '1m' [GasEstimator] -PriceMin = '1 gwei' -PriceDefault = '1 gwei' +PriceDefault = '25 gwei' +PriceMax = '115792089237316195423570985008687907853269984665.640564039457584007913129639935 tether' +PriceMin = '25 gwei' [GasEstimator.BlockHistory] # Average block time of 2s diff --git a/ccip/config/evm/Lens_Sepolia.toml b/ccip/config/evm/Lens_Sepolia.toml deleted file mode 100644 index 3f41f2eeeae..00000000000 --- a/ccip/config/evm/Lens_Sepolia.toml +++ /dev/null @@ -1,34 +0,0 @@ -ChainID = "37111" -ChainType = "zksync" -# finality depth for this chain is very inconsistent due to low network traffic. in testing blocks every ~1-2minutes were seen -# confirmed this value with product -FinalityDepth = 40 -FinalityTagEnabled = false -# block rate is dynamic, have seen block times as low as 1s -LogPollInterval = "5s" -# sufficient time for RPC to be labelled out of sync -NoNewHeadsThreshold = "10m" - -[GasEstimator] -EIP1559DynamicFees = false -# limit default set for zk based chains -LimitDefault = 2_500_000_000 -# value given by ds&a -FeeCapDefault = "2000 gwei" -# estimators typically estimated with min of 75 with median of 86 -PriceDefault = "70 gwei" -PriceMax = "2000 gwei" -PriceMin = "70 gwei" -# bump gas aggressively to avoid high amounts of transmit errors -BumpThreshold = 1 -BumpPercent = 40 - -[GasEstimator.DAOracle] -OracleType = 'zksync' - -[Transactions] -ResendAfterThreshold = '7m0s' - -[HeadTracker] -# l1 batching is done every 8hrs with low network activity setting this value to a rough calculation of ~1tx / 2min * 8hrs -HistoryDepth = 250 \ No newline at end of file diff --git a/common/client/multi_node.go b/common/client/multi_node.go index b946fb8fc2a..5ac595161af 100644 --- a/common/client/multi_node.go +++ b/common/client/multi_node.go @@ -131,10 +131,10 @@ func (c *MultiNode[CHAIN_ID, RPC]) DoAll(ctx context.Context, do func(ctx contex func (c *MultiNode[CHAIN_ID, RPC]) NodeStates() map[string]string { states := map[string]string{} for _, n := range c.primaryNodes { - states[n.Name()] = n.State().String() + states[n.String()] = n.State().String() } for _, n := range c.sendOnlyNodes { - states[n.Name()] = n.State().String() + states[n.String()] = n.State().String() } return states } diff --git a/common/client/multi_node_test.go b/common/client/multi_node_test.go index c1636881dd3..f8fdd4261b2 100644 --- a/common/client/multi_node_test.go +++ b/common/client/multi_node_test.go @@ -308,13 +308,13 @@ func TestMultiNode_CheckLease(t *testing.T) { for name, state := range nodes { node := newMockNode[types.ID, multiNodeRPCClient](t) node.On("State").Return(state).Once() - node.On("Name").Return(name).Once() + node.On("String").Return(name).Once() opts.nodes = append(opts.nodes, node) sendOnly := newMockSendOnlyNode[types.ID, multiNodeRPCClient](t) sendOnlyName := "send_only_" + name sendOnly.On("State").Return(state).Once() - sendOnly.On("Name").Return(sendOnlyName).Once() + sendOnly.On("String").Return(sendOnlyName).Once() opts.sendonlys = append(opts.sendonlys, sendOnly) expectedResult[name] = state.String() diff --git a/common/client/node_lifecycle.go b/common/client/node_lifecycle.go index 6ec6a598eb2..ce508a43dde 100644 --- a/common/client/node_lifecycle.go +++ b/common/client/node_lifecycle.go @@ -7,6 +7,8 @@ import ( "math/big" "time" + "github.com/smartcontractkit/chainlink/v2/common/types" + "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/promauto" @@ -15,7 +17,6 @@ import ( bigmath "github.com/smartcontractkit/chainlink-common/pkg/utils/big_math" iutils "github.com/smartcontractkit/chainlink/v2/common/internal/utils" - "github.com/smartcontractkit/chainlink/v2/common/types" ) var ( @@ -131,7 +132,6 @@ func (n *node[CHAIN_ID, HEAD, RPC]) aliveLoop() { } } - // Get the latest chain info to use as local highest localHighestChainInfo, _ := n.rpc.GetInterceptedChainInfo() var pollFailures uint32 @@ -168,8 +168,10 @@ func (n *node[CHAIN_ID, HEAD, RPC]) aliveLoop() { n.declareUnreachable() return } - if outOfSync, liveNodes := n.isOutOfSyncWithPool(); outOfSync { + _, latestChainInfo := n.StateAndLatest() + if outOfSync, liveNodes := n.isOutOfSyncWithPool(latestChainInfo); outOfSync { // note: there must be another live node for us to be out of sync + lggr.Errorw("RPC endpoint has fallen behind", "blockNumber", latestChainInfo.BlockNumber, "totalDifficulty", latestChainInfo.TotalDifficulty, "nodeState", n.getCachedState()) if liveNodes < 2 { lggr.Criticalf("RPC endpoint has fallen behind; %s %s", msgCannotDisable, msgDegradedState) continue @@ -308,9 +310,9 @@ func (n *node[CHAIN_ID, HEAD, RPC]) onNewFinalizedHead(lggr logger.SugaredLogger } latestFinalizedBN := latestFinalized.BlockNumber() - lggr.Debugw("Got latest finalized head", "latestFinalized", latestFinalized) + lggr.Tracew("Got latest finalized head", "latestFinalized", latestFinalized) if latestFinalizedBN <= chainInfo.FinalizedBlockNumber { - lggr.Debugw("Ignoring previously seen finalized block number") + lggr.Tracew("Ignoring previously seen finalized block number") return false } @@ -326,10 +328,10 @@ func (n *node[CHAIN_ID, HEAD, RPC]) onNewHead(lggr logger.SugaredLogger, chainIn } promPoolRPCNodeNumSeenBlocks.WithLabelValues(n.chainID.String(), n.name).Inc() - lggr.Debugw("Got head", "head", head) + lggr.Tracew("Got head", "head", head) lggr = lggr.With("latestReceivedBlockNumber", chainInfo.BlockNumber, "blockNumber", head.BlockNumber(), "nodeState", n.getCachedState()) if head.BlockNumber() <= chainInfo.BlockNumber { - lggr.Debugw("Ignoring previously seen block number") + lggr.Tracew("Ignoring previously seen block number") return false } @@ -356,7 +358,7 @@ const ( // isOutOfSyncWithPool returns outOfSync true if num or td is more than SyncThresold behind the best node. // Always returns outOfSync false for SyncThreshold 0. // liveNodes is only included when outOfSync is true. -func (n *node[CHAIN_ID, HEAD, RPC]) isOutOfSyncWithPool() (outOfSync bool, liveNodes int) { +func (n *node[CHAIN_ID, HEAD, RPC]) isOutOfSyncWithPool(localState ChainInfo) (outOfSync bool, liveNodes int) { if n.poolInfoProvider == nil { n.lfcLog.Warn("skipping sync state against the pool - should only occur in tests") return // skip for tests @@ -367,22 +369,16 @@ func (n *node[CHAIN_ID, HEAD, RPC]) isOutOfSyncWithPool() (outOfSync bool, liveN } // Check against best node ln, ci := n.poolInfoProvider.LatestChainInfo() - localChainInfo, _ := n.rpc.GetInterceptedChainInfo() mode := n.nodePoolCfg.SelectionMode() switch mode { case NodeSelectionModeHighestHead, NodeSelectionModeRoundRobin, NodeSelectionModePriorityLevel: - outOfSync = localChainInfo.BlockNumber < ci.BlockNumber-int64(threshold) + return localState.BlockNumber < ci.BlockNumber-int64(threshold), ln case NodeSelectionModeTotalDifficulty: bigThreshold := big.NewInt(int64(threshold)) - outOfSync = localChainInfo.TotalDifficulty.Cmp(bigmath.Sub(ci.TotalDifficulty, bigThreshold)) < 0 + return localState.TotalDifficulty.Cmp(bigmath.Sub(ci.TotalDifficulty, bigThreshold)) < 0, ln default: panic("unrecognized NodeSelectionMode: " + mode) } - - if outOfSync && n.getCachedState() == nodeStateAlive { - n.lfcLog.Errorw("RPC endpoint has fallen behind", "blockNumber", localChainInfo.BlockNumber, "bestLatestBlockNumber", ci.BlockNumber, "totalDifficulty", localChainInfo.TotalDifficulty) - } - return outOfSync, ln } // outOfSyncLoop takes an OutOfSync node and waits until isOutOfSync returns false to go back to live status @@ -468,7 +464,7 @@ func (n *node[CHAIN_ID, HEAD, RPC]) outOfSyncLoop(syncIssues syncStatus) { // received a new head - clear NoNewHead flag syncIssues &= ^syncStatusNoNewHead - if outOfSync, _ := n.isOutOfSyncWithPool(); !outOfSync { + if outOfSync, _ := n.isOutOfSyncWithPool(localHighestChainInfo); !outOfSync { // we caught up with the pool - clear NotInSyncWithPool flag syncIssues &= ^syncStatusNotInSyncWithPool } else { @@ -519,12 +515,7 @@ func (n *node[CHAIN_ID, HEAD, RPC]) outOfSyncLoop(syncIssues syncStatus) { finalizedHeadsSub.ResetTimer(noNewFinalizedBlocksTimeoutThreshold) } - var highestSeen ChainInfo - if n.poolInfoProvider != nil { - highestSeen = n.poolInfoProvider.HighestUserObservations() - } - - lggr.Debugw(msgReceivedFinalizedBlock, "blockNumber", latestFinalized.BlockNumber(), "poolHighestBlockNumber", highestSeen.FinalizedBlockNumber, "syncIssues", syncIssues) + lggr.Debugw(msgReceivedFinalizedBlock, "blockNumber", latestFinalized.BlockNumber(), "syncIssues", syncIssues) case err := <-finalizedHeadsSub.Errors: lggr.Errorw("Finalized head subscription was terminated", "err", err) n.declareUnreachable() @@ -657,7 +648,7 @@ func (n *node[CHAIN_ID, HEAD, RPC]) syncingLoop() { case nodeStateClosed: return default: - panic(fmt.Sprintf("syncingLoop can only run for node in NodeStateSyncing state, got: %s", state)) + panic(fmt.Sprintf("syncingLoop can only run for node in nodeStateSyncing state, got: %s", state)) } } diff --git a/common/client/node_lifecycle_test.go b/common/client/node_lifecycle_test.go index 39c39e318ef..e510e0a308a 100644 --- a/common/client/node_lifecycle_test.go +++ b/common/client/node_lifecycle_test.go @@ -224,7 +224,7 @@ func TestUnit_NodeLifecycle_aliveLoop(t *testing.T) { poolInfo.On("LatestChainInfo").Return(10, ChainInfo{ BlockNumber: syncThreshold + mostRecentBlock + 1, TotalDifficulty: big.NewInt(10), - }) + }).Once() node.SetPoolChainInfoProvider(poolInfo) // tries to redial in outOfSync rpc.On("Dial", mock.Anything).Return(errors.New("failed to dial")).Run(func(_ mock.Arguments) { @@ -259,7 +259,7 @@ func TestUnit_NodeLifecycle_aliveLoop(t *testing.T) { poolInfo.On("LatestChainInfo").Return(1, ChainInfo{ BlockNumber: syncThreshold + mostRecentBlock + 1, TotalDifficulty: big.NewInt(10), - }) + }).Once() node.SetPoolChainInfoProvider(poolInfo) node.declareAlive() tests.AssertLogEventually(t, observedLogs, fmt.Sprintf("RPC endpoint has fallen behind; %s %s", msgCannotDisable, msgDegradedState)) @@ -288,7 +288,7 @@ func TestUnit_NodeLifecycle_aliveLoop(t *testing.T) { t.Run("when no new heads received for threshold, transitions to out of sync", func(t *testing.T) { t.Parallel() rpc := newMockRPCClient[types.ID, Head](t) - rpc.On("GetInterceptedChainInfo").Return(ChainInfo{}, ChainInfo{}) + rpc.On("GetInterceptedChainInfo").Return(ChainInfo{}, ChainInfo{}).Once() node := newSubscribedNode(t, testNodeOpts{ config: testNodeConfig{}, chainConfig: clientMocks.ChainConfig{ @@ -312,7 +312,7 @@ func TestUnit_NodeLifecycle_aliveLoop(t *testing.T) { t.Run("when no new heads received for threshold but we are the last live node, forcibly stays alive", func(t *testing.T) { t.Parallel() rpc := newMockRPCClient[types.ID, Head](t) - rpc.On("GetInterceptedChainInfo").Return(ChainInfo{}, ChainInfo{}) + rpc.On("GetInterceptedChainInfo").Return(ChainInfo{}, ChainInfo{}).Once() lggr, observedLogs := logger.TestObserved(t, zap.DebugLevel) node := newSubscribedNode(t, testNodeOpts{ config: testNodeConfig{}, @@ -693,25 +693,15 @@ func TestUnit_NodeLifecycle_outOfSyncLoop(t *testing.T) { t.Run("if fail to get chainID, transitions to unreachable", func(t *testing.T) { t.Parallel() rpc := newMockRPCClient[types.ID, Head](t) - chainID := types.RandomID() node := newAliveNode(t, testNodeOpts{ - rpc: rpc, - chainID: chainID, + rpc: rpc, }) defer func() { assert.NoError(t, node.close()) }() - rpc.On("ChainID", mock.Anything).Return(chainID, nil) // for out-of-sync rpc.On("Dial", mock.Anything).Return(nil).Once() // for unreachable rpc.On("Dial", mock.Anything).Return(errors.New("failed to dial")).Maybe() - sub := mocks.NewSubscription(t) - errChan := make(chan error, 1) - errChan <- errors.New("subscription was terminate") - sub.On("Err").Return((<-chan error)(errChan)) - sub.On("Unsubscribe").Once() - rpc.On("SubscribeToHeads", mock.Anything).Return(make(<-chan Head), sub, nil) - rpc.On("GetInterceptedChainInfo").Return(ChainInfo{}, ChainInfo{}) expectedError := errors.New("failed to get chain ID") // might be called multiple times @@ -1035,7 +1025,7 @@ func TestUnit_NodeLifecycle_outOfSyncLoop(t *testing.T) { sub.On("Err").Return((<-chan error)(errChan)) sub.On("Unsubscribe").Once() rpc.On("SubscribeToFinalizedHeads", mock.Anything).Return(make(<-chan Head), sub, nil).Once() - rpc.On("GetInterceptedChainInfo").Return(ChainInfo{}, ChainInfo{}) + rpc.On("GetInterceptedChainInfo").Return(ChainInfo{}, ChainInfo{}).Once() // unreachable rpc.On("Dial", mock.Anything).Return(errors.New("failed to redial")).Maybe() @@ -1066,7 +1056,7 @@ func TestUnit_NodeLifecycle_outOfSyncLoop(t *testing.T) { rpc.On("SubscribeToFinalizedHeads", mock.Anything).Run(func(args mock.Arguments) { close(ch) }).Return((<-chan Head)(ch), sub, nil).Once() - rpc.On("GetInterceptedChainInfo").Return(ChainInfo{}, ChainInfo{}) + rpc.On("GetInterceptedChainInfo").Return(ChainInfo{}, ChainInfo{}).Once() // unreachable rpc.On("Dial", mock.Anything).Return(errors.New("failed to redial")).Maybe() node.declareOutOfSync(syncStatusNoNewHead) @@ -1092,7 +1082,7 @@ func TestUnit_NodeLifecycle_outOfSyncLoop(t *testing.T) { defer func() { assert.NoError(t, node.close()) }() const highestBlock = 13 - rpc.On("GetInterceptedChainInfo").Return(ChainInfo{FinalizedBlockNumber: highestBlock}, ChainInfo{FinalizedBlockNumber: highestBlock}) + rpc.On("GetInterceptedChainInfo").Return(ChainInfo{}, ChainInfo{FinalizedBlockNumber: highestBlock}).Once() outOfSyncSubscription := mocks.NewSubscription(t) outOfSyncSubscription.On("Err").Return((<-chan error)(nil)) @@ -1129,7 +1119,7 @@ func TestUnit_NodeLifecycle_outOfSyncLoop(t *testing.T) { defer func() { assert.NoError(t, node.close()) }() const highestBlock = 13 - rpc.On("GetInterceptedChainInfo").Return(ChainInfo{}, ChainInfo{FinalizedBlockNumber: highestBlock}) + rpc.On("GetInterceptedChainInfo").Return(ChainInfo{}, ChainInfo{FinalizedBlockNumber: highestBlock}).Once() outOfSyncSubscription := mocks.NewSubscription(t) outOfSyncSubscription.On("Err").Return((<-chan error)(nil)) @@ -1592,7 +1582,7 @@ func TestUnit_NodeLifecycle_outOfSyncWithPool(t *testing.T) { t.Parallel() t.Run("skip if nLiveNodes is not configured", func(t *testing.T) { node := newTestNode(t, testNodeOpts{}) - outOfSync, liveNodes := node.isOutOfSyncWithPool() + outOfSync, liveNodes := node.isOutOfSyncWithPool(ChainInfo{}) assert.Equal(t, false, outOfSync) assert.Equal(t, 0, liveNodes) }) @@ -1600,7 +1590,7 @@ func TestUnit_NodeLifecycle_outOfSyncWithPool(t *testing.T) { node := newTestNode(t, testNodeOpts{}) poolInfo := newMockPoolChainInfoProvider(t) node.SetPoolChainInfoProvider(poolInfo) - outOfSync, liveNodes := node.isOutOfSyncWithPool() + outOfSync, liveNodes := node.isOutOfSyncWithPool(ChainInfo{}) assert.Equal(t, false, outOfSync) assert.Equal(t, 0, liveNodes) }) @@ -1612,7 +1602,7 @@ func TestUnit_NodeLifecycle_outOfSyncWithPool(t *testing.T) { poolInfo.On("LatestChainInfo").Return(1, ChainInfo{}).Once() node.SetPoolChainInfoProvider(poolInfo) assert.Panics(t, func() { - _, _ = node.isOutOfSyncWithPool() + _, _ = node.isOutOfSyncWithPool(ChainInfo{}) }) }) t.Run("block height selection mode", func(t *testing.T) { @@ -1663,11 +1653,7 @@ func TestUnit_NodeLifecycle_outOfSyncWithPool(t *testing.T) { for _, td := range []int64{totalDifficulty - syncThreshold - 1, totalDifficulty - syncThreshold, totalDifficulty, totalDifficulty + 1} { for _, testCase := range testCases { t.Run(fmt.Sprintf("%s: SelectionModeVal: %s: total difficulty: %d", testCase.name, selectionMode, td), func(t *testing.T) { - chainInfo := ChainInfo{BlockNumber: testCase.blockNumber, TotalDifficulty: big.NewInt(td)} - rpc := newMockRPCClient[types.ID, Head](t) - rpc.On("GetInterceptedChainInfo").Return(chainInfo, ChainInfo{}).Once() - node.rpc = rpc - outOfSync, liveNodes := node.isOutOfSyncWithPool() + outOfSync, liveNodes := node.isOutOfSyncWithPool(ChainInfo{BlockNumber: testCase.blockNumber, TotalDifficulty: big.NewInt(td)}) assert.Equal(t, nodesNum, liveNodes) assert.Equal(t, testCase.outOfSync, outOfSync) }) @@ -1723,11 +1709,7 @@ func TestUnit_NodeLifecycle_outOfSyncWithPool(t *testing.T) { for _, hb := range []int64{highestBlock - syncThreshold - 1, highestBlock - syncThreshold, highestBlock, highestBlock + 1} { for _, testCase := range testCases { t.Run(fmt.Sprintf("%s: SelectionModeVal: %s: highest block: %d", testCase.name, NodeSelectionModeTotalDifficulty, hb), func(t *testing.T) { - chainInfo := ChainInfo{BlockNumber: hb, TotalDifficulty: big.NewInt(testCase.totalDifficulty)} - rpc := newMockRPCClient[types.ID, Head](t) - rpc.On("GetInterceptedChainInfo").Return(chainInfo, ChainInfo{}).Once() - node.rpc = rpc - outOfSync, liveNodes := node.isOutOfSyncWithPool() + outOfSync, liveNodes := node.isOutOfSyncWithPool(ChainInfo{BlockNumber: hb, TotalDifficulty: big.NewInt(testCase.totalDifficulty)}) assert.Equal(t, nodesNum, liveNodes) assert.Equal(t, testCase.outOfSync, outOfSync) }) diff --git a/common/client/transaction_sender.go b/common/client/transaction_sender.go index 5f58682142f..9365a82b290 100644 --- a/common/client/transaction_sender.go +++ b/common/client/transaction_sender.go @@ -3,6 +3,7 @@ package client import ( "context" "errors" + "fmt" "math" "slices" "sync" @@ -13,7 +14,6 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink-common/pkg/services" - "github.com/smartcontractkit/chainlink/v2/common/types" ) @@ -25,48 +25,52 @@ var ( }, []string{"network", "chainId", "invariant"}) ) -type SendTxResult interface { - Code() SendTxReturnCode - Error() error +// TxErrorClassifier - defines interface of a function that transforms raw RPC error into the SendTxReturnCode enum +// (e.g. Successful, Fatal, Retryable, etc.) +type TxErrorClassifier[TX any] func(tx TX, err error) SendTxReturnCode + +type sendTxResult struct { + Err error + ResultCode SendTxReturnCode } const sendTxQuorum = 0.7 // SendTxRPCClient - defines interface of an RPC used by TransactionSender to broadcast transaction -type SendTxRPCClient[TX any, RESULT SendTxResult] interface { +type SendTxRPCClient[TX any] interface { // SendTransaction errors returned should include name or other unique identifier of the RPC - SendTransaction(ctx context.Context, tx TX) RESULT + SendTransaction(ctx context.Context, tx TX) error } -func NewTransactionSender[TX any, RESULT SendTxResult, CHAIN_ID types.ID, RPC SendTxRPCClient[TX, RESULT]]( +func NewTransactionSender[TX any, CHAIN_ID types.ID, RPC SendTxRPCClient[TX]]( lggr logger.Logger, chainID CHAIN_ID, chainFamily string, multiNode *MultiNode[CHAIN_ID, RPC], - newResult func(err error) RESULT, + txErrorClassifier TxErrorClassifier[TX], sendTxSoftTimeout time.Duration, -) *TransactionSender[TX, RESULT, CHAIN_ID, RPC] { +) *TransactionSender[TX, CHAIN_ID, RPC] { if sendTxSoftTimeout == 0 { sendTxSoftTimeout = QueryTimeout / 2 } - return &TransactionSender[TX, RESULT, CHAIN_ID, RPC]{ + return &TransactionSender[TX, CHAIN_ID, RPC]{ chainID: chainID, chainFamily: chainFamily, lggr: logger.Sugared(lggr).Named("TransactionSender").With("chainID", chainID.String()), multiNode: multiNode, - newResult: newResult, + txErrorClassifier: txErrorClassifier, sendTxSoftTimeout: sendTxSoftTimeout, chStop: make(services.StopChan), } } -type TransactionSender[TX any, RESULT SendTxResult, CHAIN_ID types.ID, RPC SendTxRPCClient[TX, RESULT]] struct { +type TransactionSender[TX any, CHAIN_ID types.ID, RPC SendTxRPCClient[TX]] struct { services.StateMachine chainID CHAIN_ID chainFamily string lggr logger.SugaredLogger multiNode *MultiNode[CHAIN_ID, RPC] - newResult func(err error) RESULT + txErrorClassifier TxErrorClassifier[TX] sendTxSoftTimeout time.Duration // defines max waiting time from first response til responses evaluation wg sync.WaitGroup // waits for all reporting goroutines to finish @@ -91,155 +95,131 @@ type TransactionSender[TX any, RESULT SendTxResult, CHAIN_ID types.ID, RPC SendT // * If there is at least one terminal error - returns terminal error // * If there is both success and terminal error - returns success and reports invariant violation // * Otherwise, returns any (effectively random) of the errors. -func (txSender *TransactionSender[TX, RESULT, CHAIN_ID, RPC]) SendTransaction(ctx context.Context, tx TX) RESULT { - var result RESULT - ctx, cancel := txSender.chStop.Ctx(ctx) - defer cancel() - if !txSender.IfStarted(func() { - txResults := make(chan RESULT) - txResultsToReport := make(chan RESULT) - primaryNodeWg := sync.WaitGroup{} - - healthyNodesNum := 0 - err := txSender.multiNode.DoAll(ctx, func(ctx context.Context, rpc RPC, isSendOnly bool) { - if isSendOnly { - txSender.wg.Add(1) - go func(ctx context.Context) { - defer txSender.wg.Done() - // Send-only nodes' results are ignored as they tend to return false-positive responses. - // Broadcast to them is necessary to speed up the propagation of TX in the network. - _ = txSender.broadcastTxAsync(ctx, rpc, tx) - }(ctx) - return - } +func (txSender *TransactionSender[TX, CHAIN_ID, RPC]) SendTransaction(ctx context.Context, tx TX) (SendTxReturnCode, error) { + txResults := make(chan sendTxResult) + txResultsToReport := make(chan sendTxResult) + primaryNodeWg := sync.WaitGroup{} - // Primary Nodes - healthyNodesNum++ - primaryNodeWg.Add(1) - go func(ctx context.Context) { - // Broadcasting transaction and results reporting for invariant detection are background jobs that must be detached from - // callers cancellation. - // Results reporting to SendTransaction caller must respect caller's context to avoid goroutine leak. - defer primaryNodeWg.Done() - r := txSender.broadcastTxAsync(ctx, rpc, tx) - select { - case <-ctx.Done(): - txSender.lggr.Debugw("Failed to send tx results", "err", ctx.Err()) - return - case txResults <- r: - } - - ctx, cancel := txSender.chStop.Ctx(context.WithoutCancel(ctx)) - defer cancel() - select { - case <-ctx.Done(): - txSender.lggr.Debugw("Failed to send tx results to report", "err", ctx.Err()) - return - case txResultsToReport <- r: - } - }(ctx) - }) - - // This needs to be done in parallel so the reporting knows when it's done (when the channel is closed) - txSender.wg.Add(1) - go func() { - defer txSender.wg.Done() - primaryNodeWg.Wait() - close(txResultsToReport) - close(txResults) - }() + if txSender.State() != "Started" { + return Retryable, errors.New("TransactionSender not started") + } - if err != nil { - result = txSender.newResult(err) + healthyNodesNum := 0 + err := txSender.multiNode.DoAll(ctx, func(ctx context.Context, rpc RPC, isSendOnly bool) { + if isSendOnly { + txSender.wg.Add(1) + go func() { + defer txSender.wg.Done() + // Send-only nodes' results are ignored as they tend to return false-positive responses. + // Broadcast to them is necessary to speed up the propagation of TX in the network. + _ = txSender.broadcastTxAsync(ctx, rpc, tx) + }() return } - if healthyNodesNum == 0 { - result = txSender.newResult(ErroringNodeError) - return - } + // Primary Nodes + healthyNodesNum++ + primaryNodeWg.Add(1) + go func() { + defer primaryNodeWg.Done() + result := txSender.broadcastTxAsync(ctx, rpc, tx) + select { + case <-ctx.Done(): + return + case txResults <- result: + } - txSender.wg.Add(1) - go txSender.reportSendTxAnomalies(tx, txResultsToReport) + select { + case <-ctx.Done(): + return + case txResultsToReport <- result: + } + }() + }) - result = txSender.collectTxResults(ctx, tx, healthyNodesNum, txResults) - }) { - result = txSender.newResult(errors.New("TransactionSender not started")) + // This needs to be done in parallel so the reporting knows when it's done (when the channel is closed) + txSender.wg.Add(1) + go func() { + defer txSender.wg.Done() + primaryNodeWg.Wait() + close(txResultsToReport) + close(txResults) + }() + + if err != nil { + return Retryable, err } - return result + txSender.wg.Add(1) + go txSender.reportSendTxAnomalies(tx, txResultsToReport) + + return txSender.collectTxResults(ctx, tx, healthyNodesNum, txResults) } -func (txSender *TransactionSender[TX, RESULT, CHAIN_ID, RPC]) broadcastTxAsync(ctx context.Context, rpc RPC, tx TX) RESULT { - // broadcast is a background job, so always detach from caller's cancellation - ctx, cancel := txSender.chStop.Ctx(context.WithoutCancel(ctx)) - defer cancel() - result := rpc.SendTransaction(ctx, tx) - txSender.lggr.Debugw("Node sent transaction", "tx", tx, "err", result.Error()) - if !slices.Contains(sendTxSuccessfulCodes, result.Code()) && ctx.Err() == nil { - txSender.lggr.Warnw("RPC returned error", "tx", tx, "err", result.Error()) +func (txSender *TransactionSender[TX, CHAIN_ID, RPC]) broadcastTxAsync(ctx context.Context, rpc RPC, tx TX) sendTxResult { + txErr := rpc.SendTransaction(ctx, tx) + txSender.lggr.Debugw("Node sent transaction", "tx", tx, "err", txErr) + resultCode := txSender.txErrorClassifier(tx, txErr) + if !slices.Contains(sendTxSuccessfulCodes, resultCode) { + txSender.lggr.Warnw("RPC returned error", "tx", tx, "err", txErr) } - return result + return sendTxResult{Err: txErr, ResultCode: resultCode} } -func (txSender *TransactionSender[TX, RESULT, CHAIN_ID, RPC]) reportSendTxAnomalies(tx TX, txResults <-chan RESULT) { +func (txSender *TransactionSender[TX, CHAIN_ID, RPC]) reportSendTxAnomalies(tx TX, txResults <-chan sendTxResult) { defer txSender.wg.Done() - resultsByCode := sendTxResults[RESULT]{} + resultsByCode := sendTxResults{} // txResults eventually will be closed for txResult := range txResults { - resultsByCode[txResult.Code()] = append(resultsByCode[txResult.Code()], txResult) + resultsByCode[txResult.ResultCode] = append(resultsByCode[txResult.ResultCode], txResult.Err) } - select { - case <-txSender.chStop: - // it's ok to receive no results if txSender is closing. Return early to prevent false reporting of invariant violation. - if len(resultsByCode) == 0 { - return - } - default: - } - - _, criticalErr := aggregateTxResults[RESULT](resultsByCode) + _, _, criticalErr := aggregateTxResults(resultsByCode) if criticalErr != nil { txSender.lggr.Criticalw("observed invariant violation on SendTransaction", "tx", tx, "resultsByCode", resultsByCode, "err", criticalErr) PromMultiNodeInvariantViolations.WithLabelValues(txSender.chainFamily, txSender.chainID.String(), criticalErr.Error()).Inc() } } -type sendTxResults[RESULT any] map[SendTxReturnCode][]RESULT +type sendTxResults map[SendTxReturnCode][]error -func aggregateTxResults[RESULT any](resultsByCode sendTxResults[RESULT]) (result RESULT, criticalErr error) { - severeErrors, hasSevereErrors := findFirstIn(resultsByCode, sendTxSevereErrors) - successResults, hasSuccess := findFirstIn(resultsByCode, sendTxSuccessfulCodes) +func aggregateTxResults(resultsByCode sendTxResults) (returnCode SendTxReturnCode, txResult error, err error) { + severeCode, severeErrors, hasSevereErrors := findFirstIn(resultsByCode, sendTxSevereErrors) + successCode, successResults, hasSuccess := findFirstIn(resultsByCode, sendTxSuccessfulCodes) if hasSuccess { // We assume that primary node would never report false positive txResult for a transaction. // Thus, if such case occurs it's probably due to misconfiguration or a bug and requires manual intervention. if hasSevereErrors { const errMsg = "found contradictions in nodes replies on SendTransaction: got success and severe error" // return success, since at least 1 node has accepted our broadcasted Tx, and thus it can now be included onchain - return successResults[0], errors.New(errMsg) + return successCode, successResults[0], errors.New(errMsg) } // other errors are temporary - we are safe to return success - return successResults[0], nil + return successCode, successResults[0], nil } if hasSevereErrors { - return severeErrors[0], nil + return severeCode, severeErrors[0], nil } // return temporary error - for _, r := range resultsByCode { - return r[0], nil + for code, result := range resultsByCode { + return code, result[0], nil } - criticalErr = errors.New("expected at least one response on SendTransaction") - return result, criticalErr + err = fmt.Errorf("expected at least one response on SendTransaction") + return Retryable, err, err } -func (txSender *TransactionSender[TX, RESULT, CHAIN_ID, RPC]) collectTxResults(ctx context.Context, tx TX, healthyNodesNum int, txResults <-chan RESULT) RESULT { +func (txSender *TransactionSender[TX, CHAIN_ID, RPC]) collectTxResults(ctx context.Context, tx TX, healthyNodesNum int, txResults <-chan sendTxResult) (SendTxReturnCode, error) { + if healthyNodesNum == 0 { + return Retryable, ErroringNodeError + } + ctx, cancel := txSender.chStop.Ctx(ctx) + defer cancel() requiredResults := int(math.Ceil(float64(healthyNodesNum) * sendTxQuorum)) - errorsByCode := sendTxResults[RESULT]{} + errorsByCode := sendTxResults{} var softTimeoutChan <-chan time.Time var resultsCount int loop: @@ -247,11 +227,11 @@ loop: select { case <-ctx.Done(): txSender.lggr.Debugw("Failed to collect of the results before context was done", "tx", tx, "errorsByCode", errorsByCode) - return txSender.newResult(ctx.Err()) - case r := <-txResults: - errorsByCode[r.Code()] = append(errorsByCode[r.Code()], r) + return Retryable, ctx.Err() + case result := <-txResults: + errorsByCode[result.ResultCode] = append(errorsByCode[result.ResultCode], result.Err) resultsCount++ - if slices.Contains(sendTxSuccessfulCodes, r.Code()) || resultsCount >= requiredResults { + if slices.Contains(sendTxSuccessfulCodes, result.ResultCode) || resultsCount >= requiredResults { break loop } case <-softTimeoutChan: @@ -269,20 +249,18 @@ loop: } // ignore critical error as it's reported in reportSendTxAnomalies - result, _ := aggregateTxResults(errorsByCode) - txSender.lggr.Debugw("Collected results", "errorsByCode", errorsByCode, "result", result) - return result + returnCode, result, _ := aggregateTxResults(errorsByCode) + return returnCode, result } -func (txSender *TransactionSender[TX, RESULT, CHAIN_ID, RPC]) Start(ctx context.Context) error { +func (txSender *TransactionSender[TX, CHAIN_ID, RPC]) Start(ctx context.Context) error { return txSender.StartOnce("TransactionSender", func() error { return nil }) } -func (txSender *TransactionSender[TX, RESULT, CHAIN_ID, RPC]) Close() error { +func (txSender *TransactionSender[TX, CHAIN_ID, RPC]) Close() error { return txSender.StopOnce("TransactionSender", func() error { - txSender.lggr.Debug("Closing TransactionSender") close(txSender.chStop) txSender.wg.Wait() return nil @@ -290,12 +268,13 @@ func (txSender *TransactionSender[TX, RESULT, CHAIN_ID, RPC]) Close() error { } // findFirstIn - returns the first existing key and value for the slice of keys -func findFirstIn[K comparable, V any](set map[K]V, keys []K) (V, bool) { +func findFirstIn[K comparable, V any](set map[K]V, keys []K) (K, V, bool) { for _, k := range keys { if v, ok := set[k]; ok { - return v, true + return k, v, true } } + var zeroK K var zeroV V - return zeroV, false + return zeroK, zeroV, false } diff --git a/common/client/transaction_sender_test.go b/common/client/transaction_sender_test.go index 14dc0799a6a..3844a4536ff 100644 --- a/common/client/transaction_sender_test.go +++ b/common/client/transaction_sender_test.go @@ -14,14 +14,11 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink-common/pkg/services/servicetest" "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" - "github.com/smartcontractkit/chainlink/v2/common/types" ) -type TestSendTxRPCClient SendTxRPCClient[any, *sendTxResult] - type sendTxMultiNode struct { - *MultiNode[types.ID, TestSendTxRPCClient] + *MultiNode[types.ID, SendTxRPCClient[any]] } type sendTxRPC struct { @@ -29,51 +26,29 @@ type sendTxRPC struct { sendTxErr error } -type sendTxResult struct { - err error - code SendTxReturnCode -} - -var _ SendTxResult = (*sendTxResult)(nil) - -func NewSendTxResult(err error) *sendTxResult { - result := &sendTxResult{ - err: err, - } - return result -} - -func (r *sendTxResult) Error() error { - return r.err -} - -func (r *sendTxResult) Code() SendTxReturnCode { - return r.code -} - -var _ TestSendTxRPCClient = (*sendTxRPC)(nil) +var _ SendTxRPCClient[any] = (*sendTxRPC)(nil) func newSendTxRPC(sendTxErr error, sendTxRun func(args mock.Arguments)) *sendTxRPC { return &sendTxRPC{sendTxErr: sendTxErr, sendTxRun: sendTxRun} } -func (rpc *sendTxRPC) SendTransaction(ctx context.Context, _ any) *sendTxResult { +func (rpc *sendTxRPC) SendTransaction(ctx context.Context, _ any) error { if rpc.sendTxRun != nil { rpc.sendTxRun(mock.Arguments{ctx}) } - return &sendTxResult{err: rpc.sendTxErr, code: classifySendTxError(nil, rpc.sendTxErr)} + return rpc.sendTxErr } // newTestTransactionSender returns a sendTxMultiNode and TransactionSender. // Only the TransactionSender is run via Start/Close. func newTestTransactionSender(t *testing.T, chainID types.ID, lggr logger.Logger, - nodes []Node[types.ID, TestSendTxRPCClient], - sendOnlyNodes []SendOnlyNode[types.ID, TestSendTxRPCClient], -) (*sendTxMultiNode, *TransactionSender[any, *sendTxResult, types.ID, TestSendTxRPCClient]) { - mn := sendTxMultiNode{NewMultiNode[types.ID, TestSendTxRPCClient]( + nodes []Node[types.ID, SendTxRPCClient[any]], + sendOnlyNodes []SendOnlyNode[types.ID, SendTxRPCClient[any]], +) (*sendTxMultiNode, *TransactionSender[any, types.ID, SendTxRPCClient[any]]) { + mn := sendTxMultiNode{NewMultiNode[types.ID, SendTxRPCClient[any]]( lggr, NodeSelectionModeRoundRobin, 0, nodes, sendOnlyNodes, chainID, "chainFamily", 0)} - txSender := NewTransactionSender[any, *sendTxResult, types.ID, TestSendTxRPCClient](lggr, chainID, mn.chainFamily, mn.MultiNode, NewSendTxResult, tests.TestInterval) + txSender := NewTransactionSender[any, types.ID, SendTxRPCClient[any]](lggr, chainID, mn.chainFamily, mn.MultiNode, classifySendTxError, tests.TestInterval) servicetest.Run(t, txSender) return &mn, txSender } @@ -88,9 +63,9 @@ func classifySendTxError(_ any, err error) SendTxReturnCode { func TestTransactionSender_SendTransaction(t *testing.T) { t.Parallel() - newNodeWithState := func(t *testing.T, state nodeState, txErr error, sendTxRun func(args mock.Arguments)) *mockNode[types.ID, TestSendTxRPCClient] { + newNodeWithState := func(t *testing.T, state nodeState, txErr error, sendTxRun func(args mock.Arguments)) *mockNode[types.ID, SendTxRPCClient[any]] { rpc := newSendTxRPC(txErr, sendTxRun) - node := newMockNode[types.ID, TestSendTxRPCClient](t) + node := newMockNode[types.ID, SendTxRPCClient[any]](t) node.On("String").Return("node name").Maybe() node.On("RPC").Return(rpc).Maybe() node.On("State").Return(state).Maybe() @@ -100,15 +75,15 @@ func TestTransactionSender_SendTransaction(t *testing.T) { return node } - newNode := func(t *testing.T, txErr error, sendTxRun func(args mock.Arguments)) *mockNode[types.ID, TestSendTxRPCClient] { + newNode := func(t *testing.T, txErr error, sendTxRun func(args mock.Arguments)) *mockNode[types.ID, SendTxRPCClient[any]] { return newNodeWithState(t, nodeStateAlive, txErr, sendTxRun) } t.Run("Fails if there is no nodes available", func(t *testing.T) { lggr := logger.Test(t) _, txSender := newTestTransactionSender(t, types.RandomID(), lggr, nil, nil) - result := txSender.SendTransaction(tests.Context(t), nil) - assert.EqualError(t, result.Error(), ErroringNodeError.Error()) + _, err := txSender.SendTransaction(tests.Context(t), nil) + assert.ErrorIs(t, err, ErroringNodeError) }) t.Run("Transaction failure happy path", func(t *testing.T) { @@ -117,12 +92,12 @@ func TestTransactionSender_SendTransaction(t *testing.T) { lggr, observedLogs := logger.TestObserved(t, zap.DebugLevel) _, txSender := newTestTransactionSender(t, types.RandomID(), lggr, - []Node[types.ID, TestSendTxRPCClient]{mainNode}, - []SendOnlyNode[types.ID, TestSendTxRPCClient]{newNode(t, errors.New("unexpected error"), nil)}) + []Node[types.ID, SendTxRPCClient[any]]{mainNode}, + []SendOnlyNode[types.ID, SendTxRPCClient[any]]{newNode(t, errors.New("unexpected error"), nil)}) - result := txSender.SendTransaction(tests.Context(t), nil) - require.ErrorIs(t, result.Error(), expectedError) - require.Equal(t, Fatal, result.Code()) + result, sendErr := txSender.SendTransaction(tests.Context(t), nil) + require.ErrorIs(t, sendErr, expectedError) + require.Equal(t, Fatal, result) tests.AssertLogCountEventually(t, observedLogs, "Node sent transaction", 2) tests.AssertLogCountEventually(t, observedLogs, "RPC returned error", 2) }) @@ -132,12 +107,12 @@ func TestTransactionSender_SendTransaction(t *testing.T) { lggr, observedLogs := logger.TestObserved(t, zap.DebugLevel) _, txSender := newTestTransactionSender(t, types.RandomID(), lggr, - []Node[types.ID, TestSendTxRPCClient]{mainNode}, - []SendOnlyNode[types.ID, TestSendTxRPCClient]{newNode(t, errors.New("unexpected error"), nil)}) + []Node[types.ID, SendTxRPCClient[any]]{mainNode}, + []SendOnlyNode[types.ID, SendTxRPCClient[any]]{newNode(t, errors.New("unexpected error"), nil)}) - result := txSender.SendTransaction(tests.Context(t), nil) - require.NoError(t, result.Error()) - require.Equal(t, Successful, result.Code()) + result, sendErr := txSender.SendTransaction(tests.Context(t), nil) + require.NoError(t, sendErr) + require.Equal(t, Successful, result) tests.AssertLogCountEventually(t, observedLogs, "Node sent transaction", 2) tests.AssertLogCountEventually(t, observedLogs, "RPC returned error", 1) }) @@ -154,12 +129,12 @@ func TestTransactionSender_SendTransaction(t *testing.T) { lggr := logger.Test(t) _, txSender := newTestTransactionSender(t, types.RandomID(), lggr, - []Node[types.ID, TestSendTxRPCClient]{mainNode}, nil) + []Node[types.ID, SendTxRPCClient[any]]{mainNode}, nil) requestContext, cancel := context.WithCancel(tests.Context(t)) cancel() - result := txSender.SendTransaction(requestContext, nil) - require.EqualError(t, result.Error(), "context canceled") + _, sendErr := txSender.SendTransaction(requestContext, nil) + require.EqualError(t, sendErr, "context canceled") }) t.Run("Soft timeout stops results collection", func(t *testing.T) { @@ -177,9 +152,9 @@ func TestTransactionSender_SendTransaction(t *testing.T) { lggr := logger.Test(t) - _, txSender := newTestTransactionSender(t, chainID, lggr, []Node[types.ID, TestSendTxRPCClient]{fastNode, slowNode}, nil) - result := txSender.SendTransaction(tests.Context(t), nil) - require.EqualError(t, result.Error(), expectedError.Error()) + _, txSender := newTestTransactionSender(t, chainID, lggr, []Node[types.ID, SendTxRPCClient[any]]{fastNode, slowNode}, nil) + _, sendErr := txSender.SendTransaction(tests.Context(t), nil) + require.ErrorIs(t, sendErr, expectedError) }) t.Run("Returns success without waiting for the rest of the nodes", func(t *testing.T) { chainID := types.RandomID() @@ -195,14 +170,14 @@ func TestTransactionSender_SendTransaction(t *testing.T) { // block caller til end of the test <-testContext.Done() }) - lggr, _ := logger.TestObserved(t, zap.WarnLevel) + lggr := logger.Test(t) _, txSender := newTestTransactionSender(t, chainID, lggr, - []Node[types.ID, TestSendTxRPCClient]{fastNode, slowNode}, - []SendOnlyNode[types.ID, TestSendTxRPCClient]{slowSendOnly}) + []Node[types.ID, SendTxRPCClient[any]]{fastNode, slowNode}, + []SendOnlyNode[types.ID, SendTxRPCClient[any]]{slowSendOnly}) - result := txSender.SendTransaction(tests.Context(t), nil) - require.NoError(t, result.Error()) - require.Equal(t, Successful, result.Code()) + rtnCode, err := txSender.SendTransaction(tests.Context(t), nil) + require.NoError(t, err) + require.Equal(t, Successful, rtnCode) }) t.Run("Fails when multinode is closed", func(t *testing.T) { chainID := types.RandomID() @@ -222,16 +197,14 @@ func TestTransactionSender_SendTransaction(t *testing.T) { }) slowSendOnly.On("ConfiguredChainID").Return(chainID).Maybe() - lggr, _ := logger.TestObserved(t, zap.DebugLevel) - - mn, txSender := newTestTransactionSender(t, chainID, lggr, - []Node[types.ID, TestSendTxRPCClient]{fastNode, slowNode}, - []SendOnlyNode[types.ID, TestSendTxRPCClient]{slowSendOnly}) + mn, txSender := newTestTransactionSender(t, chainID, logger.Test(t), + []Node[types.ID, SendTxRPCClient[any]]{fastNode, slowNode}, + []SendOnlyNode[types.ID, SendTxRPCClient[any]]{slowSendOnly}) require.NoError(t, mn.Start(tests.Context(t))) require.NoError(t, mn.Close()) - result := txSender.SendTransaction(tests.Context(t), nil) - require.EqualError(t, result.Error(), "service is stopped") + _, err := txSender.SendTransaction(tests.Context(t), nil) + require.ErrorContains(t, err, "service is stopped") }) t.Run("Fails when closed", func(t *testing.T) { chainID := types.RandomID() @@ -248,16 +221,17 @@ func TestTransactionSender_SendTransaction(t *testing.T) { <-testContext.Done() }) - var txSender *TransactionSender[any, *sendTxResult, types.ID, TestSendTxRPCClient] + var txSender *TransactionSender[any, types.ID, SendTxRPCClient[any]] t.Cleanup(func() { // after txSender.Close() - result := txSender.SendTransaction(tests.Context(t), nil) - assert.EqualError(t, result.err, "TransactionSender not started") + _, err := txSender.SendTransaction(tests.Context(t), nil) + assert.EqualError(t, err, "TransactionSender not started") }) _, txSender = newTestTransactionSender(t, chainID, logger.Test(t), - []Node[types.ID, TestSendTxRPCClient]{fastNode, slowNode}, - []SendOnlyNode[types.ID, TestSendTxRPCClient]{slowSendOnly}) + []Node[types.ID, SendTxRPCClient[any]]{fastNode, slowNode}, + []SendOnlyNode[types.ID, SendTxRPCClient[any]]{slowSendOnly}) + }) t.Run("Returns error if there is no healthy primary nodes", func(t *testing.T) { chainID := types.RandomID() @@ -267,11 +241,11 @@ func TestTransactionSender_SendTransaction(t *testing.T) { lggr := logger.Test(t) _, txSender := newTestTransactionSender(t, chainID, lggr, - []Node[types.ID, TestSendTxRPCClient]{primary}, - []SendOnlyNode[types.ID, TestSendTxRPCClient]{sendOnly}) + []Node[types.ID, SendTxRPCClient[any]]{primary}, + []SendOnlyNode[types.ID, SendTxRPCClient[any]]{sendOnly}) - result := txSender.SendTransaction(tests.Context(t), nil) - assert.EqualError(t, result.Error(), ErroringNodeError.Error()) + _, sendErr := txSender.SendTransaction(tests.Context(t), nil) + assert.EqualError(t, sendErr, ErroringNodeError.Error()) }) t.Run("Transaction success even if one of the nodes is unhealthy", func(t *testing.T) { @@ -286,33 +260,12 @@ func TestTransactionSender_SendTransaction(t *testing.T) { lggr := logger.Test(t) _, txSender := newTestTransactionSender(t, chainID, lggr, - []Node[types.ID, TestSendTxRPCClient]{mainNode, unhealthyNode}, - []SendOnlyNode[types.ID, TestSendTxRPCClient]{unhealthySendOnlyNode}) + []Node[types.ID, SendTxRPCClient[any]]{mainNode, unhealthyNode}, + []SendOnlyNode[types.ID, SendTxRPCClient[any]]{unhealthySendOnlyNode}) - result := txSender.SendTransaction(tests.Context(t), nil) - require.NoError(t, result.Error()) - require.Equal(t, Successful, result.Code()) - }) - t.Run("All background jobs stop even if RPC returns result after soft timeout", func(t *testing.T) { - chainID := types.RandomID() - expectedError := errors.New("transaction failed") - fastNode := newNode(t, expectedError, nil) - - // hold reply from the node till SendTransaction returns result - sendTxContext, sendTxCancel := context.WithCancel(tests.Context(t)) - slowNode := newNode(t, errors.New("transaction failed"), func(_ mock.Arguments) { - <-sendTxContext.Done() - }) - - lggr := logger.Test(t) - - _, txSender := newTestTransactionSender(t, chainID, lggr, []Node[types.ID, TestSendTxRPCClient]{fastNode, slowNode}, nil) - result := txSender.SendTransaction(sendTxContext, nil) - sendTxCancel() - require.EqualError(t, result.Error(), expectedError.Error()) - // TxSender should stop all background go routines after SendTransaction is done and before test is done. - // Otherwise, it signals that we have a goroutine leak. - txSender.wg.Wait() + returnCode, sendErr := txSender.SendTransaction(tests.Context(t), nil) + require.NoError(t, sendErr) + require.Equal(t, Successful, returnCode) }) } @@ -328,62 +281,64 @@ func TestTransactionSender_SendTransaction_aggregateTxResults(t *testing.T) { Name string ExpectedTxResult string ExpectedCriticalErr string - ResultsByCode sendTxResults[*sendTxResult] + ResultsByCode sendTxResults }{ { Name: "Returns success and logs critical error on success and Fatal", ExpectedTxResult: "success", ExpectedCriticalErr: "found contradictions in nodes replies on SendTransaction: got success and severe error", - ResultsByCode: sendTxResults[*sendTxResult]{ - Successful: {NewSendTxResult(errors.New("success"))}, - Fatal: {NewSendTxResult(errors.New("fatal"))}, + ResultsByCode: sendTxResults{ + Successful: {errors.New("success")}, + Fatal: {errors.New("fatal")}, }, }, { Name: "Returns TransactionAlreadyKnown and logs critical error on TransactionAlreadyKnown and Fatal", ExpectedTxResult: "tx_already_known", ExpectedCriticalErr: "found contradictions in nodes replies on SendTransaction: got success and severe error", - ResultsByCode: sendTxResults[*sendTxResult]{ - TransactionAlreadyKnown: {NewSendTxResult(errors.New("tx_already_known"))}, - Unsupported: {NewSendTxResult(errors.New("unsupported"))}, + ResultsByCode: sendTxResults{ + TransactionAlreadyKnown: {errors.New("tx_already_known")}, + Unsupported: {errors.New("unsupported")}, }, }, { Name: "Prefers sever error to temporary", ExpectedTxResult: "underpriced", ExpectedCriticalErr: "", - ResultsByCode: sendTxResults[*sendTxResult]{ - Retryable: {NewSendTxResult(errors.New("retryable"))}, - Underpriced: {NewSendTxResult(errors.New("underpriced"))}, + ResultsByCode: sendTxResults{ + Retryable: {errors.New("retryable")}, + Underpriced: {errors.New("underpriced")}, }, }, { Name: "Returns temporary error", ExpectedTxResult: "retryable", ExpectedCriticalErr: "", - ResultsByCode: sendTxResults[*sendTxResult]{ - Retryable: {NewSendTxResult(errors.New("retryable"))}, + ResultsByCode: sendTxResults{ + Retryable: {errors.New("retryable")}, }, }, { Name: "Insufficient funds is treated as error", - ExpectedTxResult: "insufficientFunds", + ExpectedTxResult: "", ExpectedCriticalErr: "", - ResultsByCode: sendTxResults[*sendTxResult]{ - InsufficientFunds: {NewSendTxResult(errors.New("insufficientFunds"))}, + ResultsByCode: sendTxResults{ + Successful: {nil}, + InsufficientFunds: {errors.New("insufficientFunds")}, }, }, { Name: "Logs critical error on empty ResultsByCode", + ExpectedTxResult: "expected at least one response on SendTransaction", ExpectedCriticalErr: "expected at least one response on SendTransaction", - ResultsByCode: sendTxResults[*sendTxResult]{}, + ResultsByCode: sendTxResults{}, }, { Name: "Zk terminally stuck", ExpectedTxResult: "not enough keccak counters to continue the execution", ExpectedCriticalErr: "", - ResultsByCode: sendTxResults[*sendTxResult]{ - TerminallyStuck: {NewSendTxResult(errors.New("not enough keccak counters to continue the execution"))}, + ResultsByCode: sendTxResults{ + TerminallyStuck: {errors.New("not enough keccak counters to continue the execution")}, }, }, } @@ -394,18 +349,20 @@ func TestTransactionSender_SendTransaction_aggregateTxResults(t *testing.T) { } t.Run(testCase.Name, func(t *testing.T) { - txResult, err := aggregateTxResults(testCase.ResultsByCode) - if testCase.ExpectedTxResult != "" { - require.EqualError(t, txResult.Error(), testCase.ExpectedTxResult) + _, txResult, err := aggregateTxResults(testCase.ResultsByCode) + if testCase.ExpectedTxResult == "" { + assert.NoError(t, err) + } else { + assert.EqualError(t, txResult, testCase.ExpectedTxResult) } logger.Sugared(logger.Test(t)).Info("Map: " + fmt.Sprint(testCase.ResultsByCode)) logger.Sugared(logger.Test(t)).Criticalw("observed invariant violation on SendTransaction", "resultsByCode", testCase.ResultsByCode, "err", err) if testCase.ExpectedCriticalErr == "" { - require.NoError(t, err) + assert.NoError(t, err) } else { - require.EqualError(t, err, testCase.ExpectedCriticalErr) + assert.EqualError(t, err, testCase.ExpectedCriticalErr) } }) } diff --git a/common/txmgr/broadcaster.go b/common/txmgr/broadcaster.go index 14e959c39ae..2a234ab3340 100644 --- a/common/txmgr/broadcaster.go +++ b/common/txmgr/broadcaster.go @@ -769,7 +769,7 @@ func (eb *Broadcaster[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) save } } } - return eb.txStore.UpdateTxFatalErrorAndDeleteAttempts(ctx, etx) + return eb.txStore.UpdateTxFatalError(ctx, etx) } func observeTimeUntilBroadcast[CHAIN_ID types.ID](chainID CHAIN_ID, createdAt, broadcastAt time.Time) { diff --git a/common/txmgr/confirmer.go b/common/txmgr/confirmer.go index 7c5ba798cf2..e6fd5b61f68 100644 --- a/common/txmgr/confirmer.go +++ b/common/txmgr/confirmer.go @@ -7,6 +7,7 @@ import ( "errors" "fmt" "sort" + "strconv" "sync" "time" @@ -33,6 +34,14 @@ const ( // processHeadTimeout represents a sanity limit on how long ProcessHead // should take to complete processHeadTimeout = 10 * time.Minute + + // logAfterNConsecutiveBlocksChainTooShort logs a warning if we go at least + // this many consecutive blocks with a re-org protection chain that is too + // short + // + // we don't log every time because on startup it can be lower, only if it + // persists does it indicate a serious problem + logAfterNConsecutiveBlocksChainTooShort = 10 ) var ( @@ -49,6 +58,22 @@ var ( Name: "tx_manager_num_confirmed_transactions", Help: "Total number of confirmed transactions. Note that this can err to be too high since transactions are counted on each confirmation, which can happen multiple times per transaction in the case of re-orgs", }, []string{"chainID"}) + promNumSuccessfulTxs = promauto.NewCounterVec(prometheus.CounterOpts{ + Name: "tx_manager_num_successful_transactions", + Help: "Total number of successful transactions. Note that this can err to be too high since transactions are counted on each confirmation, which can happen multiple times per transaction in the case of re-orgs", + }, []string{"chainID"}) + promRevertedTxCount = promauto.NewCounterVec(prometheus.CounterOpts{ + Name: "tx_manager_num_tx_reverted", + Help: "Number of times a transaction reverted on-chain. Note that this can err to be too high since transactions are counted on each confirmation, which can happen multiple times per transaction in the case of re-orgs", + }, []string{"chainID"}) + promFwdTxCount = promauto.NewCounterVec(prometheus.CounterOpts{ + Name: "tx_manager_fwd_tx_count", + Help: "The number of forwarded transaction attempts labeled by status", + }, []string{"chainID", "successful"}) + promTxAttemptCount = promauto.NewGaugeVec(prometheus.GaugeOpts{ + Name: "tx_manager_tx_attempt_count", + Help: "The number of transaction attempts that are currently being processed by the transaction manager", + }, []string{"chainID"}) promTimeUntilTxConfirmed = promauto.NewHistogramVec(prometheus.HistogramOpts{ Name: "tx_manager_time_until_tx_confirmed", Help: "The amount of time elapsed from a transaction being broadcast to being included in a block.", @@ -78,11 +103,15 @@ var ( }, []string{"chainID"}) ) +type confirmerHeadTracker[HEAD types.Head[BLOCK_HASH], BLOCK_HASH types.Hashable] interface { + LatestAndFinalizedBlock(ctx context.Context) (latest, finalized HEAD, err error) +} + // Confirmer is a broad service which performs four different tasks in sequence on every new longest chain // Step 1: Mark that all currently pending transaction attempts were broadcast before this block -// Step 2: Check pending transactions for confirmation and confirmed transactions for re-org -// Step 3: Check if any pending transaction is stuck in the mempool. If so, mark for purge. -// Step 4: See if any transactions have exceeded the gas bumping block threshold and, if so, bump them +// Step 2: Check pending transactions for receipts +// Step 3: See if any transactions have exceeded the gas bumping block threshold and, if so, bump them +// Step 4: Check confirmed transactions to make sure they are still in the longest chain (reorg protection) type Confirmer[ CHAIN_ID types.ID, HEAD types.Head[BLOCK_HASH], @@ -100,6 +129,7 @@ type Confirmer[ txmgrtypes.TxAttemptBuilder[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE] stuckTxDetector txmgrtypes.StuckTxDetector[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE] resumeCallback ResumeCallback + chainConfig txmgrtypes.ConfirmerChainConfig feeConfig txmgrtypes.ConfirmerFeeConfig txConfig txmgrtypes.ConfirmerTransactionsConfig dbConfig txmgrtypes.ConfirmerDatabaseConfig @@ -108,12 +138,15 @@ type Confirmer[ ks txmgrtypes.KeyStore[ADDR, CHAIN_ID, SEQ] enabledAddresses []ADDR - mb *mailbox.Mailbox[HEAD] - stopCh services.StopChan - wg sync.WaitGroup - initSync sync.Mutex - isStarted bool - isReceiptNil func(R) bool + mb *mailbox.Mailbox[HEAD] + stopCh services.StopChan + wg sync.WaitGroup + initSync sync.Mutex + isStarted bool + nConsecutiveBlocksChainTooShort int + isReceiptNil func(R) bool + + headTracker confirmerHeadTracker[HEAD, BLOCK_HASH] } func NewConfirmer[ @@ -128,6 +161,7 @@ func NewConfirmer[ ]( txStore txmgrtypes.TxStore[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE], client txmgrtypes.TxmClient[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, R, SEQ, FEE], + chainConfig txmgrtypes.ConfirmerChainConfig, feeConfig txmgrtypes.ConfirmerFeeConfig, txConfig txmgrtypes.ConfirmerTransactionsConfig, dbConfig txmgrtypes.ConfirmerDatabaseConfig, @@ -136,6 +170,7 @@ func NewConfirmer[ lggr logger.Logger, isReceiptNil func(R) bool, stuckTxDetector txmgrtypes.StuckTxDetector[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], + headTracker confirmerHeadTracker[HEAD, BLOCK_HASH], ) *Confirmer[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, R, SEQ, FEE] { lggr = logger.Named(lggr, "Confirmer") return &Confirmer[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, R, SEQ, FEE]{ @@ -144,6 +179,7 @@ func NewConfirmer[ client: client, TxAttemptBuilder: txAttemptBuilder, resumeCallback: nil, + chainConfig: chainConfig, feeConfig: feeConfig, txConfig: txConfig, dbConfig: dbConfig, @@ -152,6 +188,7 @@ func NewConfirmer[ mb: mailbox.NewSingle[HEAD](), isReceiptNil: isReceiptNil, stuckTxDetector: stuckTxDetector, + headTracker: headTracker, } } @@ -257,146 +294,178 @@ func (ec *Confirmer[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) Pro // NOTE: This SHOULD NOT be run concurrently or it could behave badly func (ec *Confirmer[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) processHead(ctx context.Context, head types.Head[BLOCK_HASH]) error { + mark := time.Now() + ec.lggr.Debugw("processHead start", "headNum", head.BlockNumber(), "id", "confirmer") - mark := time.Now() if err := ec.txStore.SetBroadcastBeforeBlockNum(ctx, head.BlockNumber(), ec.chainID); err != nil { - return err + return fmt.Errorf("SetBroadcastBeforeBlockNum failed: %w", err) + } + if err := ec.CheckConfirmedMissingReceipt(ctx); err != nil { + return fmt.Errorf("CheckConfirmedMissingReceipt failed: %w", err) } - ec.lggr.Debugw("Finished SetBroadcastBeforeBlockNum", "headNum", head.BlockNumber(), "time", time.Since(mark), "id", "confirmer") - mark = time.Now() - if err := ec.CheckForConfirmation(ctx, head); err != nil { - return err + _, latestFinalizedHead, err := ec.headTracker.LatestAndFinalizedBlock(ctx) + if err != nil { + return fmt.Errorf("failed to retrieve latest finalized head: %w", err) + } + + if !latestFinalizedHead.IsValid() { + return fmt.Errorf("latest finalized head is not valid") + } + + if latestFinalizedHead.BlockNumber() > head.BlockNumber() { + ec.lggr.Debugw("processHead received old block", "latestFinalizedHead", latestFinalizedHead.BlockNumber(), "headNum", head.BlockNumber(), "time", time.Since(mark), "id", "confirmer") + } + + if err := ec.CheckForReceipts(ctx, head.BlockNumber(), latestFinalizedHead.BlockNumber()); err != nil { + return fmt.Errorf("CheckForReceipts failed: %w", err) } - ec.lggr.Debugw("Finished CheckForConfirmation", "headNum", head.BlockNumber(), "time", time.Since(mark), "id", "confirmer") + ec.lggr.Debugw("Finished CheckForReceipts", "headNum", head.BlockNumber(), "time", time.Since(mark), "id", "confirmer") mark = time.Now() + if err := ec.ProcessStuckTransactions(ctx, head.BlockNumber()); err != nil { - return err + return fmt.Errorf("ProcessStuckTransactions failed: %w", err) } - ec.lggr.Debugw("Finished ProcessStuckTransactions", "headNum", head.BlockNumber(), "time", time.Since(mark), "id", "confirmer") + ec.lggr.Debugw("Finished ProcessStuckTransactions", "headNum", head.BlockNumber(), "time", time.Since(mark), "id", "confirmer") mark = time.Now() + if err := ec.RebroadcastWhereNecessary(ctx, head.BlockNumber()); err != nil { - return err + return fmt.Errorf("RebroadcastWhereNecessary failed: %w", err) } + ec.lggr.Debugw("Finished RebroadcastWhereNecessary", "headNum", head.BlockNumber(), "time", time.Since(mark), "id", "confirmer") + mark = time.Now() + + if err := ec.EnsureConfirmedTransactionsInLongestChain(ctx, head); err != nil { + return fmt.Errorf("EnsureConfirmedTransactionsInLongestChain failed: %w", err) + } + + ec.lggr.Debugw("Finished EnsureConfirmedTransactionsInLongestChain", "headNum", head.BlockNumber(), "time", time.Since(mark), "id", "confirmer") + + if ec.resumeCallback != nil { + mark = time.Now() + if err := ec.ResumePendingTaskRuns(ctx, head.BlockNumber(), latestFinalizedHead.BlockNumber()); err != nil { + return fmt.Errorf("ResumePendingTaskRuns failed: %w", err) + } + + ec.lggr.Debugw("Finished ResumePendingTaskRuns", "headNum", head.BlockNumber(), "time", time.Since(mark), "id", "confirmer") + } + ec.lggr.Debugw("processHead finish", "headNum", head.BlockNumber(), "id", "confirmer") return nil } -// CheckForConfirmation fetches the mined transaction count for each enabled address and marks transactions with a lower sequence as confirmed and ones with equal or higher sequence as unconfirmed -func (ec *Confirmer[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) CheckForConfirmation(ctx context.Context, head types.Head[BLOCK_HASH]) error { - var errorList []error - for _, fromAddress := range ec.enabledAddresses { - minedTxCount, err := ec.client.SequenceAt(ctx, fromAddress, nil) - if err != nil { - errorList = append(errorList, fmt.Errorf("unable to fetch mined transaction count for address %s: %w", fromAddress.String(), err)) - continue - } - reorgTxs, includedTxs, err := ec.txStore.FindReorgOrIncludedTxs(ctx, fromAddress, minedTxCount, ec.chainID) - if err != nil { - errorList = append(errorList, fmt.Errorf("failed to find re-org'd or included transactions based on the mined transaction count %d: %w", minedTxCount.Int64(), err)) - continue - } - // If re-org'd transactions are identified, process them and mark them for rebroadcast - err = ec.ProcessReorgTxs(ctx, reorgTxs, head) - if err != nil { - errorList = append(errorList, fmt.Errorf("failed to process re-org'd transactions: %w", err)) - continue +// CheckConfirmedMissingReceipt will attempt to re-send any transaction in the +// state of "confirmed_missing_receipt". If we get back any type of senderror +// other than "sequence too low" it means that this transaction isn't actually +// confirmed and needs to be put back into "unconfirmed" state, so that it can enter +// the gas bumping cycle. This is necessary in rare cases (e.g. Polygon) where +// network conditions are extremely hostile. +// +// For example, assume the following scenario: +// +// 0. We are connected to multiple primary nodes via load balancer +// 1. We send a transaction, it is confirmed and, we get a receipt +// 2. A new head comes in from RPC node 1 indicating that this transaction was re-org'd, so we put it back into unconfirmed state +// 3. We re-send that transaction to a RPC node 2 **which hasn't caught up to this re-org yet** +// 4. RPC node 2 still has an old view of the chain, so it returns us "sequence too low" indicating "no problem this transaction is already mined" +// 5. Now the transaction is marked "confirmed_missing_receipt" but the latest chain does not actually include it +// 6. Now we are reliant on the Resender to propagate it, and this transaction will not be gas bumped, so in the event of gas spikes it could languish or even be evicted from the mempool and hold up the queue +// 7. Even if/when RPC node 2 catches up, the transaction is still stuck in state "confirmed_missing_receipt" +// +// This scenario might sound unlikely but has been observed to happen multiple times in the wild on Polygon. +func (ec *Confirmer[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) CheckConfirmedMissingReceipt(ctx context.Context) (err error) { + attempts, err := ec.txStore.FindTxAttemptsConfirmedMissingReceipt(ctx, ec.chainID) + if err != nil { + return err + } + if len(attempts) == 0 { + return nil + } + ec.lggr.Infow(fmt.Sprintf("Found %d transactions confirmed_missing_receipt. The RPC node did not give us a receipt for these transactions even though it should have been mined. This could be due to using the wallet with an external account, or if the primary node is not synced or not propagating transactions properly", len(attempts)), "attempts", attempts) + txCodes, txErrs, broadcastTime, txIDs, err := ec.client.BatchSendTransactions(ctx, attempts, int(ec.chainConfig.RPCDefaultBatchSize()), ec.lggr) + // update broadcast times before checking additional errors + if len(txIDs) > 0 { + if updateErr := ec.txStore.UpdateBroadcastAts(ctx, broadcastTime, txIDs); updateErr != nil { + err = fmt.Errorf("%w: failed to update broadcast time: %w", err, updateErr) } - // If unconfirmed transactions are identified as included, process them and mark them as confirmed or terminally stuck (if purge attempt exists) - err = ec.ProcessIncludedTxs(ctx, includedTxs, head) - if err != nil { - errorList = append(errorList, fmt.Errorf("failed to process confirmed transactions: %w", err)) - continue + } + if err != nil { + ec.lggr.Debugw("Batch sending transactions failed", "err", err) + } + var txIDsToUnconfirm []int64 + for idx, txErr := range txErrs { + // Add to Unconfirm array, all tx where error wasn't TransactionAlreadyKnown. + if txErr != nil { + if txCodes[idx] == client.TransactionAlreadyKnown { + continue + } } + + txIDsToUnconfirm = append(txIDsToUnconfirm, attempts[idx].TxID) } - if len(errorList) > 0 { - return errors.Join(errorList...) + err = ec.txStore.UpdateTxsUnconfirmed(ctx, txIDsToUnconfirm) + + if err != nil { + return err } - return nil + return } -func (ec *Confirmer[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) ProcessReorgTxs(ctx context.Context, reorgTxs []*txmgrtypes.Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], head types.Head[BLOCK_HASH]) error { - if len(reorgTxs) == 0 { +// CheckForReceipts finds attempts that are still pending and checks to see if a receipt is present for the given block number. +func (ec *Confirmer[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) CheckForReceipts(ctx context.Context, blockNum int64, latestFinalizedBlockNum int64) error { + attempts, err := ec.txStore.FindTxAttemptsRequiringReceiptFetch(ctx, ec.chainID) + if err != nil { + return fmt.Errorf("FindTxAttemptsRequiringReceiptFetch failed: %w", err) + } + if len(attempts) == 0 { return nil } - etxIDs := make([]int64, 0, len(reorgTxs)) - attemptIDs := make([]int64, 0, len(reorgTxs)) - for _, etx := range reorgTxs { - if len(etx.TxAttempts) == 0 { - return fmt.Errorf("invariant violation: expected tx %v to have at least one attempt", etx.ID) - } - - // Rebroadcast the one with the highest gas price - attempt := etx.TxAttempts[0] - logValues := []interface{}{ - "txhash", attempt.Hash.String(), - "currentBlockNum", head.BlockNumber(), - "currentBlockHash", head.BlockHash().String(), - "txID", etx.ID, - "attemptID", attempt.ID, - "nReceipts", len(attempt.Receipts), - "attemptState", attempt.State, - "id", "confirmer", - } + ec.lggr.Debugw(fmt.Sprintf("Fetching receipts for %v transaction attempts", len(attempts)), "blockNum", blockNum) - if len(attempt.Receipts) > 0 && attempt.Receipts[0] != nil { - receipt := attempt.Receipts[0] - logValues = append(logValues, - "replacementBlockHashAtConfirmedHeight", head.HashAtHeight(receipt.GetBlockNumber().Int64()), - "confirmedInBlockNum", receipt.GetBlockNumber(), - "confirmedInBlockHash", receipt.GetBlockHash(), - "confirmedInTxIndex", receipt.GetTransactionIndex(), - ) - } + attemptsByAddress := make(map[ADDR][]txmgrtypes.TxAttempt[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) + for _, att := range attempts { + attemptsByAddress[att.Tx.FromAddress] = append(attemptsByAddress[att.Tx.FromAddress], att) + } - if etx.State == TxFinalized { - ec.lggr.AssumptionViolationw(fmt.Sprintf("Re-org detected for finalized transaction. This should never happen. Rebroadcasting transaction %s which may have been re-org'd out of the main chain", attempt.Hash.String()), logValues...) - } else { - ec.lggr.Infow(fmt.Sprintf("Re-org detected. Rebroadcasting transaction %s which may have been re-org'd out of the main chain", attempt.Hash.String()), logValues...) + for from, attempts := range attemptsByAddress { + minedSequence, err := ec.getMinedSequenceForAddress(ctx, from) + if err != nil { + return fmt.Errorf("unable to fetch pending sequence for address: %v: %w", from, err) } - etxIDs = append(etxIDs, etx.ID) - attemptIDs = append(attemptIDs, attempt.ID) - } + // separateLikelyConfirmedAttempts is used as an optimisation: there is + // no point trying to fetch receipts for attempts with a sequence higher + // than the highest sequence the RPC node thinks it has seen + likelyConfirmed := ec.separateLikelyConfirmedAttempts(from, attempts, minedSequence) + likelyConfirmedCount := len(likelyConfirmed) + if likelyConfirmedCount > 0 { + likelyUnconfirmedCount := len(attempts) - likelyConfirmedCount - // Mark transactions as unconfirmed, mark attempts as in-progress, and delete receipts since they do not apply to the new chain - // This may revert some fatal error transactions to unconfirmed if terminally stuck transactions purge attempts get re-org'd - return ec.txStore.UpdateTxsForRebroadcast(ctx, etxIDs, attemptIDs) -} + ec.lggr.Debugf("Fetching and saving %v likely confirmed receipts. Skipping checking the others (%v)", + likelyConfirmedCount, likelyUnconfirmedCount) -func (ec *Confirmer[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) ProcessIncludedTxs(ctx context.Context, includedTxs []*txmgrtypes.Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], head types.Head[BLOCK_HASH]) error { - if len(includedTxs) == 0 { - return nil - } - // Add newly confirmed transactions to the prom metric - promNumConfirmedTxs.WithLabelValues(ec.chainID.String()).Add(float64(len(includedTxs))) - - purgeTxIDs := make([]int64, 0, len(includedTxs)) - confirmedTxIDs := make([]int64, 0, len(includedTxs)) - for _, tx := range includedTxs { - // If any attempt in the transaction is marked for purge, the transaction was terminally stuck and should be marked as fatal error - if tx.HasPurgeAttempt() { - // Setting the purged block num here is ok since we have confirmation the tx has been included - ec.stuckTxDetector.SetPurgeBlockNum(tx.FromAddress, head.BlockNumber()) - purgeTxIDs = append(purgeTxIDs, tx.ID) - continue + start := time.Now() + err = ec.fetchAndSaveReceipts(ctx, likelyConfirmed, blockNum) + if err != nil { + return fmt.Errorf("unable to fetch and save receipts for likely confirmed txs, for address: %v: %w", from, err) + } + ec.lggr.Debugw(fmt.Sprintf("Fetching and saving %v likely confirmed receipts done", likelyConfirmedCount), + "time", time.Since(start)) } - confirmedTxIDs = append(confirmedTxIDs, tx.ID) - observeUntilTxConfirmed(ec.chainID, tx.TxAttempts, head) } - // Mark the transactions included on-chain with a purge attempt as fatal error with the terminally stuck error message - if err := ec.txStore.UpdateTxFatalError(ctx, purgeTxIDs, ec.stuckTxDetector.StuckTxFatalError()); err != nil { - return fmt.Errorf("failed to update terminally stuck transactions: %w", err) + + if err := ec.txStore.MarkAllConfirmedMissingReceipt(ctx, ec.chainID); err != nil { + return fmt.Errorf("unable to mark txes as 'confirmed_missing_receipt': %w", err) } - // Mark the transactions included on-chain as confirmed - if err := ec.txStore.UpdateTxConfirmed(ctx, confirmedTxIDs); err != nil { - return fmt.Errorf("failed to update confirmed transactions: %w", err) + + if err := ec.txStore.MarkOldTxesMissingReceiptAsErrored(ctx, blockNum, latestFinalizedBlockNum, ec.chainID); err != nil { + return fmt.Errorf("unable to confirm buried unconfirmed txes': %w", err) } return nil } @@ -459,6 +528,103 @@ func (ec *Confirmer[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) Pro return errors.Join(errorList...) } +func (ec *Confirmer[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) separateLikelyConfirmedAttempts(from ADDR, attempts []txmgrtypes.TxAttempt[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], minedSequence SEQ) []txmgrtypes.TxAttempt[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE] { + if len(attempts) == 0 { + return attempts + } + + firstAttemptSequence := *attempts[len(attempts)-1].Tx.Sequence + lastAttemptSequence := *attempts[0].Tx.Sequence + latestMinedSequence := minedSequence.Int64() - 1 // this can be -1 if a transaction has never been mined on this account + ec.lggr.Debugw(fmt.Sprintf("There are %d attempts from address %s, mined transaction count is %d (latest mined sequence is %d) and for the attempts' sequences: first = %d, last = %d", + len(attempts), from, minedSequence.Int64(), latestMinedSequence, firstAttemptSequence.Int64(), lastAttemptSequence.Int64()), "nAttempts", len(attempts), "fromAddress", from, "minedSequence", minedSequence, "latestMinedSequence", latestMinedSequence, "firstAttemptSequence", firstAttemptSequence, "lastAttemptSequence", lastAttemptSequence) + + likelyConfirmed := attempts + // attempts are ordered by sequence ASC + for i := 0; i < len(attempts); i++ { + // If the attempt sequence is lower or equal to the latestBlockSequence + // it must have been confirmed, we just didn't get a receipt yet + // + // Examples: + // 3 transactions confirmed, highest has sequence 2 + // 5 total attempts, highest has sequence 4 + // minedSequence=3 + // likelyConfirmed will be attempts[0:3] which gives the first 3 transactions, as expected + if (*attempts[i].Tx.Sequence).Int64() > minedSequence.Int64() { + ec.lggr.Debugf("Marking attempts as likely confirmed just before index %v, at sequence: %v", i, *attempts[i].Tx.Sequence) + likelyConfirmed = attempts[0:i] + break + } + } + + if len(likelyConfirmed) == 0 { + ec.lggr.Debug("There are no likely confirmed attempts - so will skip checking any") + } + + return likelyConfirmed +} + +func (ec *Confirmer[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) fetchAndSaveReceipts(ctx context.Context, attempts []txmgrtypes.TxAttempt[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], blockNum int64) error { + promTxAttemptCount.WithLabelValues(ec.chainID.String()).Set(float64(len(attempts))) + + batchSize := int(ec.chainConfig.RPCDefaultBatchSize()) + if batchSize == 0 { + batchSize = len(attempts) + } + var allReceipts []R + for i := 0; i < len(attempts); i += batchSize { + j := i + batchSize + if j > len(attempts) { + j = len(attempts) + } + + ec.lggr.Debugw(fmt.Sprintf("Batch fetching receipts at indexes %d until (excluded) %d", i, j), "blockNum", blockNum) + + batch := attempts[i:j] + + receipts, err := ec.batchFetchReceipts(ctx, batch, blockNum) + if err != nil { + return fmt.Errorf("batchFetchReceipts failed: %w", err) + } + validReceipts, purgeReceipts := ec.separateValidAndPurgeAttemptReceipts(receipts, batch) + // Saves the receipts and mark the associated transactions as Confirmed + if err := ec.txStore.SaveFetchedReceipts(ctx, validReceipts, TxConfirmed, nil, ec.chainID); err != nil { + return fmt.Errorf("saveFetchedReceipts failed: %w", err) + } + // Save the receipts but mark the associated transactions as Fatal Error since the original transaction was purged + stuckTxFatalErrMsg := ec.stuckTxDetector.StuckTxFatalError() + if err := ec.txStore.SaveFetchedReceipts(ctx, purgeReceipts, TxFatalError, &stuckTxFatalErrMsg, ec.chainID); err != nil { + return fmt.Errorf("saveFetchedReceipts failed: %w", err) + } + promNumConfirmedTxs.WithLabelValues(ec.chainID.String()).Add(float64(len(receipts))) + + allReceipts = append(allReceipts, receipts...) + } + + observeUntilTxConfirmed(ec.chainID, attempts, allReceipts) + + return nil +} + +func (ec *Confirmer[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) separateValidAndPurgeAttemptReceipts(receipts []R, attempts []txmgrtypes.TxAttempt[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) (valid []R, purge []R) { + receiptMap := make(map[TX_HASH]R) + for _, receipt := range receipts { + receiptMap[receipt.GetTxHash()] = receipt + } + for _, attempt := range attempts { + if receipt, ok := receiptMap[attempt.Hash]; ok { + if attempt.IsPurgeAttempt { + // Setting the purged block num here is ok since we have confirmation the tx has been purged with the receipt + ec.stuckTxDetector.SetPurgeBlockNum(attempt.Tx.FromAddress, receipt.GetBlockNumber().Int64()) + purge = append(purge, receipt) + } else { + valid = append(valid, receipt) + } + } + } + return +} + func (ec *Confirmer[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) resumeFailedTaskRuns(ctx context.Context, etx txmgrtypes.Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) error { if !etx.PipelineTaskRunID.Valid || ec.resumeCallback == nil || !etx.SignalCallback || etx.CallbackCompleted { return nil @@ -470,13 +636,113 @@ func (ec *Confirmer[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) res return fmt.Errorf("failed to resume pipeline: %w", err) } else { // Mark tx as having completed callback - if err := ec.txStore.UpdateTxCallbackCompleted(ctx, etx.PipelineTaskRunID.UUID, ec.chainID); err != nil { + if err = ec.txStore.UpdateTxCallbackCompleted(ctx, etx.PipelineTaskRunID.UUID, ec.chainID); err != nil { return err } } return nil } +func (ec *Confirmer[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) getMinedSequenceForAddress(ctx context.Context, from ADDR) (SEQ, error) { + return ec.client.SequenceAt(ctx, from, nil) +} + +// Note this function will increment promRevertedTxCount upon receiving +// a reverted transaction receipt. Should only be called with unconfirmed attempts. +func (ec *Confirmer[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) batchFetchReceipts(ctx context.Context, attempts []txmgrtypes.TxAttempt[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], blockNum int64) (receipts []R, err error) { + // Metadata is required to determine whether a tx is forwarded or not. + if ec.txConfig.ForwardersEnabled() { + err = ec.txStore.PreloadTxes(ctx, attempts) + if err != nil { + return nil, fmt.Errorf("Confirmer#batchFetchReceipts error loading txs for attempts: %w", err) + } + } + + lggr := ec.lggr.Named("BatchFetchReceipts").With("blockNum", blockNum) + + txReceipts, txErrs, err := ec.client.BatchGetReceipts(ctx, attempts) + if err != nil { + return nil, err + } + + for i := range txReceipts { + attempt := attempts[i] + receipt := txReceipts[i] + err := txErrs[i] + + l := attempt.Tx.GetLogger(lggr).With("txHash", attempt.Hash.String(), "txAttemptID", attempt.ID, + "txID", attempt.TxID, "err", err, "sequence", attempt.Tx.Sequence, + ) + + if err != nil { + l.Error("FetchReceipt failed") + continue + } + + if ec.isReceiptNil(receipt) { + // NOTE: This should never happen, but it seems safer to check + // regardless to avoid a potential panic + l.AssumptionViolation("got nil receipt") + continue + } + + if receipt.IsZero() { + l.Debug("Still waiting for receipt") + continue + } + + l = l.With("blockHash", receipt.GetBlockHash().String(), "status", receipt.GetStatus(), "transactionIndex", receipt.GetTransactionIndex()) + + if receipt.IsUnmined() { + l.Debug("Got receipt for transaction but it's still in the mempool and not included in a block yet") + continue + } + + l.Debugw("Got receipt for transaction", "blockNumber", receipt.GetBlockNumber(), "feeUsed", receipt.GetFeeUsed()) + + if receipt.GetTxHash().String() != attempt.Hash.String() { + l.Errorf("Invariant violation, expected receipt with hash %s to have same hash as attempt with hash %s", receipt.GetTxHash().String(), attempt.Hash.String()) + continue + } + + if receipt.GetBlockNumber() == nil { + l.Error("Invariant violation, receipt was missing block number") + continue + } + + if receipt.GetStatus() == 0 { + if receipt.GetRevertReason() != nil { + l.Warnw("transaction reverted on-chain", "hash", receipt.GetTxHash(), "revertReason", *receipt.GetRevertReason()) + } else { + rpcError, errExtract := ec.client.CallContract(ctx, attempt, receipt.GetBlockNumber()) + if errExtract == nil { + l.Warnw("transaction reverted on-chain", "hash", receipt.GetTxHash(), "rpcError", rpcError.String()) + } else { + l.Warnw("transaction reverted on-chain unable to extract revert reason", "hash", receipt.GetTxHash(), "err", err) + } + } + // This might increment more than once e.g. in case of re-orgs going back and forth we might re-fetch the same receipt + promRevertedTxCount.WithLabelValues(ec.chainID.String()).Add(1) + } else { + promNumSuccessfulTxs.WithLabelValues(ec.chainID.String()).Add(1) + } + + // This is only recording forwarded tx that were mined and have a status. + // Counters are prone to being inaccurate due to re-orgs. + if ec.txConfig.ForwardersEnabled() { + meta, metaErr := attempt.Tx.GetMeta() + if metaErr == nil && meta != nil && meta.FwdrDestAddress != nil { + // promFwdTxCount takes two labels, chainId and a boolean of whether a tx was successful or not. + promFwdTxCount.WithLabelValues(ec.chainID.String(), strconv.FormatBool(receipt.GetStatus() != 0)).Add(1) + } + } + + receipts = append(receipts, receipt) + } + + return +} + // RebroadcastWhereNecessary bumps gas or resends transactions that were previously out-of-funds func (ec *Confirmer[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) RebroadcastWhereNecessary(ctx context.Context, blockHeight int64) error { var wg sync.WaitGroup @@ -780,7 +1046,7 @@ func (ec *Confirmer[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) han // Mark confirmed_missing_receipt and wait for the next cycle to try to get a receipt lggr.Debugw("Sequence already used", "txAttemptID", attempt.ID, "txHash", attempt.Hash.String()) timeout := ec.dbConfig.DefaultQueryTimeout() - return ec.txStore.SaveConfirmedAttempt(ctx, timeout, &attempt, now) + return ec.txStore.SaveConfirmedMissingReceiptAttempt(ctx, timeout, &attempt, now) case client.InsufficientFunds: timeout := ec.dbConfig.DefaultQueryTimeout() return ec.txStore.SaveInsufficientFundsAttempt(ctx, timeout, &attempt, now) @@ -800,6 +1066,139 @@ func (ec *Confirmer[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) han } } +// EnsureConfirmedTransactionsInLongestChain finds all confirmed txes up to the earliest head +// of the given chain and ensures that every one has a receipt with a block hash that is +// in the given chain. +// +// If any of the confirmed transactions does not have a receipt in the chain, it has been +// re-org'd out and will be rebroadcast. +func (ec *Confirmer[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) EnsureConfirmedTransactionsInLongestChain(ctx context.Context, head types.Head[BLOCK_HASH]) error { + logArgs := []interface{}{ + "chainLength", head.ChainLength(), + } + + // Here, we rely on the finalized block provided in the chain instead of the one + // provided via a dedicated method to avoid the false warning of the chain being + // too short. When `FinalityTagBypass = true,` HeadTracker tracks `finality depth + // + history depth` to prevent excessive CPU usage. Thus, the provided chain may + // be shorter than the chain from the latest to the latest finalized, marked with + // a tag. A proper fix of this issue and complete switch to finality tag support + // will be introduced in BCFR-620 + latestFinalized := head.LatestFinalizedHead() + if latestFinalized == nil || !latestFinalized.IsValid() { + if ec.nConsecutiveBlocksChainTooShort > logAfterNConsecutiveBlocksChainTooShort { + warnMsg := "Chain length supplied for re-org detection was shorter than the depth from the latest head to the finalized head. Re-org protection is not working properly. This could indicate a problem with the remote RPC endpoint, a compatibility issue with a particular blockchain, a bug with this particular blockchain, heads table being truncated too early, remote node out of sync, or something else. If this happens a lot please raise a bug with the Chainlink team including a log output sample and details of the chain and RPC endpoint you are using." + ec.lggr.Warnw(warnMsg, append(logArgs, "nConsecutiveBlocksChainTooShort", ec.nConsecutiveBlocksChainTooShort)...) + } else { + logMsg := "Chain length supplied for re-org detection was shorter than the depth from the latest head to the finalized head" + ec.lggr.Debugw(logMsg, append(logArgs, "nConsecutiveBlocksChainTooShort", ec.nConsecutiveBlocksChainTooShort)...) + } + ec.nConsecutiveBlocksChainTooShort++ + } else { + ec.nConsecutiveBlocksChainTooShort = 0 + } + etxs, err := ec.txStore.FindTransactionsConfirmedInBlockRange(ctx, head.BlockNumber(), head.EarliestHeadInChain().BlockNumber(), ec.chainID) + if err != nil { + return fmt.Errorf("findTransactionsConfirmedInBlockRange failed: %w", err) + } + + for _, etx := range etxs { + if !hasReceiptInLongestChain(*etx, head) { + if err := ec.markForRebroadcast(ctx, *etx, head); err != nil { + return fmt.Errorf("markForRebroadcast failed for etx %v: %w", etx.ID, err) + } + } + } + + // It is safe to process separate keys concurrently + // NOTE: This design will block one key if another takes a really long time to execute + var wg sync.WaitGroup + errors := []error{} + var errMu sync.Mutex + wg.Add(len(ec.enabledAddresses)) + for _, address := range ec.enabledAddresses { + go func(fromAddress ADDR) { + if err := ec.handleAnyInProgressAttempts(ctx, fromAddress, head.BlockNumber()); err != nil { + errMu.Lock() + errors = append(errors, err) + errMu.Unlock() + ec.lggr.Errorw("Error in handleAnyInProgressAttempts", "err", err, "fromAddress", fromAddress) + } + + wg.Done() + }(address) + } + + wg.Wait() + + return multierr.Combine(errors...) +} + +func hasReceiptInLongestChain[ + CHAIN_ID types.ID, + ADDR types.Hashable, + TX_HASH, BLOCK_HASH types.Hashable, + SEQ types.Sequence, + FEE feetypes.Fee, +](etx txmgrtypes.Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], head types.Head[BLOCK_HASH]) bool { + for { + for _, attempt := range etx.TxAttempts { + for _, receipt := range attempt.Receipts { + if receipt.GetBlockHash().String() == head.BlockHash().String() && receipt.GetBlockNumber().Int64() == head.BlockNumber() { + return true + } + } + } + + head = head.GetParent() + if head == nil { + return false + } + } +} + +func (ec *Confirmer[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) markForRebroadcast(ctx context.Context, etx txmgrtypes.Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], head types.Head[BLOCK_HASH]) error { + if len(etx.TxAttempts) == 0 { + return fmt.Errorf("invariant violation: expected tx %v to have at least one attempt", etx.ID) + } + + // Rebroadcast the one with the highest gas price + attempt := etx.TxAttempts[0] + var receipt txmgrtypes.ChainReceipt[TX_HASH, BLOCK_HASH] + if len(attempt.Receipts) > 0 { + receipt = attempt.Receipts[0] + } + + logValues := []interface{}{ + "txhash", attempt.Hash.String(), + "currentBlockNum", head.BlockNumber(), + "currentBlockHash", head.BlockHash().String(), + "txID", etx.ID, + "attemptID", attempt.ID, + "nReceipts", len(attempt.Receipts), + "id", "confirmer", + } + + // nil check on receipt interface + if receipt != nil { + logValues = append(logValues, + "replacementBlockHashAtConfirmedHeight", head.HashAtHeight(receipt.GetBlockNumber().Int64()), + "confirmedInBlockNum", receipt.GetBlockNumber(), + "confirmedInBlockHash", receipt.GetBlockHash(), + "confirmedInTxIndex", receipt.GetTransactionIndex(), + ) + } + + ec.lggr.Infow(fmt.Sprintf("Re-org detected. Rebroadcasting transaction %s which may have been re-org'd out of the main chain", attempt.Hash.String()), logValues...) + + // Put it back in progress and delete all receipts (they do not apply to the new chain) + if err := ec.txStore.UpdateTxForRebroadcast(ctx, etx, attempt); err != nil { + return fmt.Errorf("markForRebroadcast failed: %w", err) + } + + return nil +} + // ForceRebroadcast sends a transaction for every sequence in the given sequence range at the given gas price. // If an tx exists for this sequence, we re-send the existing tx with the supplied parameters. // If an tx doesn't exist for this sequence, we send a zero transaction. @@ -860,38 +1259,80 @@ func (ec *Confirmer[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) sen return txhash, nil } +// ResumePendingTaskRuns issues callbacks to task runs that are pending waiting for receipts +func (ec *Confirmer[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) ResumePendingTaskRuns(ctx context.Context, latest, finalized int64) error { + receiptsPlus, err := ec.txStore.FindTxesPendingCallback(ctx, latest, finalized, ec.chainID) + + if err != nil { + return err + } + + if len(receiptsPlus) > 0 { + ec.lggr.Debugf("Resuming %d task runs pending receipt", len(receiptsPlus)) + } else { + ec.lggr.Debug("No task runs to resume") + } + for _, data := range receiptsPlus { + var taskErr error + var output interface{} + if data.FailOnRevert && data.Receipt.GetStatus() == 0 { + taskErr = fmt.Errorf("transaction %s reverted on-chain", data.Receipt.GetTxHash()) + } else { + output = data.Receipt + } + + ec.lggr.Debugw("Callback: resuming tx with receipt", "output", output, "taskErr", taskErr, "pipelineTaskRunID", data.ID) + if err := ec.resumeCallback(ctx, data.ID, output, taskErr); err != nil { + return fmt.Errorf("failed to resume suspended pipeline run: %w", err) + } + // Mark tx as having completed callback + if err := ec.txStore.UpdateTxCallbackCompleted(ctx, data.ID, ec.chainID); err != nil { + return err + } + } + + return nil +} + // observeUntilTxConfirmed observes the promBlocksUntilTxConfirmed metric for each confirmed // transaction. func observeUntilTxConfirmed[ CHAIN_ID types.ID, ADDR types.Hashable, TX_HASH, BLOCK_HASH types.Hashable, + R txmgrtypes.ChainReceipt[TX_HASH, BLOCK_HASH], SEQ types.Sequence, FEE feetypes.Fee, -](chainID CHAIN_ID, attempts []txmgrtypes.TxAttempt[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], head types.Head[BLOCK_HASH]) { +](chainID CHAIN_ID, attempts []txmgrtypes.TxAttempt[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], receipts []R) { for _, attempt := range attempts { - // We estimate the time until confirmation by subtracting from the time the tx (not the attempt) - // was created. We want to measure the amount of time taken from when a transaction is created - // via e.g Txm.CreateTransaction to when it is confirmed on-chain, regardless of how many attempts - // were needed to achieve this. - duration := time.Since(attempt.Tx.CreatedAt) - promTimeUntilTxConfirmed. - WithLabelValues(chainID.String()). - Observe(float64(duration)) - - // Since a tx can have many attempts, we take the number of blocks to confirm as the block number - // of the receipt minus the block number of the first ever broadcast for this transaction. - broadcastBefore := iutils.MinFunc(attempt.Tx.TxAttempts, func(attempt txmgrtypes.TxAttempt[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) int64 { - if attempt.BroadcastBeforeBlockNum != nil { - return *attempt.BroadcastBeforeBlockNum + for _, r := range receipts { + if attempt.Hash.String() != r.GetTxHash().String() { + continue } - return 0 - }) - if broadcastBefore > 0 { - blocksElapsed := head.BlockNumber() - broadcastBefore - promBlocksUntilTxConfirmed. + + // We estimate the time until confirmation by subtracting from the time the tx (not the attempt) + // was created. We want to measure the amount of time taken from when a transaction is created + // via e.g Txm.CreateTransaction to when it is confirmed on-chain, regardless of how many attempts + // were needed to achieve this. + duration := time.Since(attempt.Tx.CreatedAt) + promTimeUntilTxConfirmed. WithLabelValues(chainID.String()). - Observe(float64(blocksElapsed)) + Observe(float64(duration)) + + // Since a tx can have many attempts, we take the number of blocks to confirm as the block number + // of the receipt minus the block number of the first ever broadcast for this transaction. + broadcastBefore := iutils.MinFunc(attempt.Tx.TxAttempts, func(attempt txmgrtypes.TxAttempt[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) int64 { + if attempt.BroadcastBeforeBlockNum != nil { + return *attempt.BroadcastBeforeBlockNum + } + return 0 + }) + if broadcastBefore > 0 { + blocksElapsed := r.GetBlockNumber().Int64() - broadcastBefore + promBlocksUntilTxConfirmed. + WithLabelValues(chainID.String()). + Observe(float64(blocksElapsed)) + } } } } diff --git a/common/txmgr/tracker.go b/common/txmgr/tracker.go index 408ae62173a..a7236472710 100644 --- a/common/txmgr/tracker.go +++ b/common/txmgr/tracker.go @@ -304,7 +304,7 @@ func (tr *Tracker[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) markTxFatal // Set state to TxInProgress so the tracker can attempt to mark it as fatal tx.State = TxInProgress - if err := tr.txStore.UpdateTxFatalErrorAndDeleteAttempts(ctx, tx); err != nil { + if err := tr.txStore.UpdateTxFatalError(ctx, tx); err != nil { return fmt.Errorf("failed to mark tx %v as abandoned: %w", tx.ID, err) } return nil diff --git a/common/txmgr/txmgr.go b/common/txmgr/txmgr.go index 3776f62254c..28d505e5e05 100644 --- a/common/txmgr/txmgr.go +++ b/common/txmgr/txmgr.go @@ -118,7 +118,6 @@ func (b *Txm[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) RegisterRe b.resumeCallback = fn b.broadcaster.SetResumeCallback(fn) b.confirmer.SetResumeCallback(fn) - b.finalizer.SetResumeCallback(fn) } // NewTxm creates a new Txm with the given configuration. diff --git a/common/txmgr/types/config.go b/common/txmgr/types/config.go index 1ab334b3a48..8b11a45d11d 100644 --- a/common/txmgr/types/config.go +++ b/common/txmgr/types/config.go @@ -4,6 +4,7 @@ import "time" type TransactionManagerChainConfig interface { BroadcasterChainConfig + ConfirmerChainConfig } type TransactionManagerFeeConfig interface { @@ -45,6 +46,12 @@ type ConfirmerFeeConfig interface { // from gas.Config BumpThreshold() uint64 MaxFeePrice() string // logging value + BumpPercent() uint16 +} + +type ConfirmerChainConfig interface { + RPCDefaultBatchSize() uint32 + FinalityDepth() uint32 } type ConfirmerDatabaseConfig interface { diff --git a/common/txmgr/types/finalizer.go b/common/txmgr/types/finalizer.go index 4ed25111faa..be3c897d0e2 100644 --- a/common/txmgr/types/finalizer.go +++ b/common/txmgr/types/finalizer.go @@ -1,10 +1,6 @@ package types import ( - "context" - - "github.com/google/uuid" - "github.com/smartcontractkit/chainlink-common/pkg/services" "github.com/smartcontractkit/chainlink/v2/common/types" ) @@ -13,5 +9,4 @@ type Finalizer[BLOCK_HASH types.Hashable, HEAD types.Head[BLOCK_HASH]] interface // interfaces for running the underlying estimator services.Service DeliverLatestHead(head HEAD) bool - SetResumeCallback(callback func(ctx context.Context, id uuid.UUID, result interface{}, err error) error) } diff --git a/common/txmgr/types/mocks/tx_store.go b/common/txmgr/types/mocks/tx_store.go index b75ee69302a..8dc816e9bec 100644 --- a/common/txmgr/types/mocks/tx_store.go +++ b/common/txmgr/types/mocks/tx_store.go @@ -555,9 +555,9 @@ func (_c *TxStore_FindEarliestUnconfirmedTxAttemptBlock_Call[ADDR, CHAIN_ID, TX_ return _c } -// FindLatestSequence provides a mock function with given fields: ctx, fromAddress, chainID -func (_m *TxStore[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) FindLatestSequence(ctx context.Context, fromAddress ADDR, chainID CHAIN_ID) (SEQ, error) { - ret := _m.Called(ctx, fromAddress, chainID) +// FindLatestSequence provides a mock function with given fields: ctx, fromAddress, chainId +func (_m *TxStore[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) FindLatestSequence(ctx context.Context, fromAddress ADDR, chainId CHAIN_ID) (SEQ, error) { + ret := _m.Called(ctx, fromAddress, chainId) if len(ret) == 0 { panic("no return value specified for FindLatestSequence") @@ -566,16 +566,16 @@ func (_m *TxStore[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) FindLatestS var r0 SEQ var r1 error if rf, ok := ret.Get(0).(func(context.Context, ADDR, CHAIN_ID) (SEQ, error)); ok { - return rf(ctx, fromAddress, chainID) + return rf(ctx, fromAddress, chainId) } if rf, ok := ret.Get(0).(func(context.Context, ADDR, CHAIN_ID) SEQ); ok { - r0 = rf(ctx, fromAddress, chainID) + r0 = rf(ctx, fromAddress, chainId) } else { r0 = ret.Get(0).(SEQ) } if rf, ok := ret.Get(1).(func(context.Context, ADDR, CHAIN_ID) error); ok { - r1 = rf(ctx, fromAddress, chainID) + r1 = rf(ctx, fromAddress, chainId) } else { r1 = ret.Error(1) } @@ -591,12 +591,12 @@ type TxStore_FindLatestSequence_Call[ADDR types.Hashable, CHAIN_ID types.ID, TX_ // FindLatestSequence is a helper method to define mock.On call // - ctx context.Context // - fromAddress ADDR -// - chainID CHAIN_ID -func (_e *TxStore_Expecter[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) FindLatestSequence(ctx interface{}, fromAddress interface{}, chainID interface{}) *TxStore_FindLatestSequence_Call[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE] { - return &TxStore_FindLatestSequence_Call[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]{Call: _e.mock.On("FindLatestSequence", ctx, fromAddress, chainID)} +// - chainId CHAIN_ID +func (_e *TxStore_Expecter[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) FindLatestSequence(ctx interface{}, fromAddress interface{}, chainId interface{}) *TxStore_FindLatestSequence_Call[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE] { + return &TxStore_FindLatestSequence_Call[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]{Call: _e.mock.On("FindLatestSequence", ctx, fromAddress, chainId)} } -func (_c *TxStore_FindLatestSequence_Call[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) Run(run func(ctx context.Context, fromAddress ADDR, chainID CHAIN_ID)) *TxStore_FindLatestSequence_Call[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE] { +func (_c *TxStore_FindLatestSequence_Call[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) Run(run func(ctx context.Context, fromAddress ADDR, chainId CHAIN_ID)) *TxStore_FindLatestSequence_Call[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE] { _c.Call.Run(func(args mock.Arguments) { run(args[0].(context.Context), args[1].(ADDR), args[2].(CHAIN_ID)) }) @@ -673,72 +673,63 @@ func (_c *TxStore_FindNextUnstartedTransactionFromAddress_Call[ADDR, CHAIN_ID, T return _c } -// FindReorgOrIncludedTxs provides a mock function with given fields: ctx, fromAddress, nonce, chainID -func (_m *TxStore[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) FindReorgOrIncludedTxs(ctx context.Context, fromAddress ADDR, nonce SEQ, chainID CHAIN_ID) ([]*txmgrtypes.Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], []*txmgrtypes.Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], error) { - ret := _m.Called(ctx, fromAddress, nonce, chainID) +// FindTransactionsConfirmedInBlockRange provides a mock function with given fields: ctx, highBlockNumber, lowBlockNumber, chainID +func (_m *TxStore[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) FindTransactionsConfirmedInBlockRange(ctx context.Context, highBlockNumber int64, lowBlockNumber int64, chainID CHAIN_ID) ([]*txmgrtypes.Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], error) { + ret := _m.Called(ctx, highBlockNumber, lowBlockNumber, chainID) if len(ret) == 0 { - panic("no return value specified for FindReorgOrIncludedTxs") + panic("no return value specified for FindTransactionsConfirmedInBlockRange") } var r0 []*txmgrtypes.Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE] - var r1 []*txmgrtypes.Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE] - var r2 error - if rf, ok := ret.Get(0).(func(context.Context, ADDR, SEQ, CHAIN_ID) ([]*txmgrtypes.Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], []*txmgrtypes.Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], error)); ok { - return rf(ctx, fromAddress, nonce, chainID) + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, int64, int64, CHAIN_ID) ([]*txmgrtypes.Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], error)); ok { + return rf(ctx, highBlockNumber, lowBlockNumber, chainID) } - if rf, ok := ret.Get(0).(func(context.Context, ADDR, SEQ, CHAIN_ID) []*txmgrtypes.Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]); ok { - r0 = rf(ctx, fromAddress, nonce, chainID) + if rf, ok := ret.Get(0).(func(context.Context, int64, int64, CHAIN_ID) []*txmgrtypes.Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]); ok { + r0 = rf(ctx, highBlockNumber, lowBlockNumber, chainID) } else { if ret.Get(0) != nil { r0 = ret.Get(0).([]*txmgrtypes.Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) } } - if rf, ok := ret.Get(1).(func(context.Context, ADDR, SEQ, CHAIN_ID) []*txmgrtypes.Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]); ok { - r1 = rf(ctx, fromAddress, nonce, chainID) - } else { - if ret.Get(1) != nil { - r1 = ret.Get(1).([]*txmgrtypes.Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) - } - } - - if rf, ok := ret.Get(2).(func(context.Context, ADDR, SEQ, CHAIN_ID) error); ok { - r2 = rf(ctx, fromAddress, nonce, chainID) + if rf, ok := ret.Get(1).(func(context.Context, int64, int64, CHAIN_ID) error); ok { + r1 = rf(ctx, highBlockNumber, lowBlockNumber, chainID) } else { - r2 = ret.Error(2) + r1 = ret.Error(1) } - return r0, r1, r2 + return r0, r1 } -// TxStore_FindReorgOrIncludedTxs_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'FindReorgOrIncludedTxs' -type TxStore_FindReorgOrIncludedTxs_Call[ADDR types.Hashable, CHAIN_ID types.ID, TX_HASH types.Hashable, BLOCK_HASH types.Hashable, R txmgrtypes.ChainReceipt[TX_HASH, BLOCK_HASH], SEQ types.Sequence, FEE feetypes.Fee] struct { +// TxStore_FindTransactionsConfirmedInBlockRange_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'FindTransactionsConfirmedInBlockRange' +type TxStore_FindTransactionsConfirmedInBlockRange_Call[ADDR types.Hashable, CHAIN_ID types.ID, TX_HASH types.Hashable, BLOCK_HASH types.Hashable, R txmgrtypes.ChainReceipt[TX_HASH, BLOCK_HASH], SEQ types.Sequence, FEE feetypes.Fee] struct { *mock.Call } -// FindReorgOrIncludedTxs is a helper method to define mock.On call +// FindTransactionsConfirmedInBlockRange is a helper method to define mock.On call // - ctx context.Context -// - fromAddress ADDR -// - nonce SEQ +// - highBlockNumber int64 +// - lowBlockNumber int64 // - chainID CHAIN_ID -func (_e *TxStore_Expecter[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) FindReorgOrIncludedTxs(ctx interface{}, fromAddress interface{}, nonce interface{}, chainID interface{}) *TxStore_FindReorgOrIncludedTxs_Call[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE] { - return &TxStore_FindReorgOrIncludedTxs_Call[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]{Call: _e.mock.On("FindReorgOrIncludedTxs", ctx, fromAddress, nonce, chainID)} +func (_e *TxStore_Expecter[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) FindTransactionsConfirmedInBlockRange(ctx interface{}, highBlockNumber interface{}, lowBlockNumber interface{}, chainID interface{}) *TxStore_FindTransactionsConfirmedInBlockRange_Call[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE] { + return &TxStore_FindTransactionsConfirmedInBlockRange_Call[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]{Call: _e.mock.On("FindTransactionsConfirmedInBlockRange", ctx, highBlockNumber, lowBlockNumber, chainID)} } -func (_c *TxStore_FindReorgOrIncludedTxs_Call[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) Run(run func(ctx context.Context, fromAddress ADDR, nonce SEQ, chainID CHAIN_ID)) *TxStore_FindReorgOrIncludedTxs_Call[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE] { +func (_c *TxStore_FindTransactionsConfirmedInBlockRange_Call[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) Run(run func(ctx context.Context, highBlockNumber int64, lowBlockNumber int64, chainID CHAIN_ID)) *TxStore_FindTransactionsConfirmedInBlockRange_Call[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE] { _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context), args[1].(ADDR), args[2].(SEQ), args[3].(CHAIN_ID)) + run(args[0].(context.Context), args[1].(int64), args[2].(int64), args[3].(CHAIN_ID)) }) return _c } -func (_c *TxStore_FindReorgOrIncludedTxs_Call[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) Return(reorgTx []*txmgrtypes.Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], includedTxs []*txmgrtypes.Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], err error) *TxStore_FindReorgOrIncludedTxs_Call[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE] { - _c.Call.Return(reorgTx, includedTxs, err) +func (_c *TxStore_FindTransactionsConfirmedInBlockRange_Call[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) Return(etxs []*txmgrtypes.Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], err error) *TxStore_FindTransactionsConfirmedInBlockRange_Call[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE] { + _c.Call.Return(etxs, err) return _c } -func (_c *TxStore_FindReorgOrIncludedTxs_Call[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) RunAndReturn(run func(context.Context, ADDR, SEQ, CHAIN_ID) ([]*txmgrtypes.Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], []*txmgrtypes.Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], error)) *TxStore_FindReorgOrIncludedTxs_Call[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE] { +func (_c *TxStore_FindTransactionsConfirmedInBlockRange_Call[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) RunAndReturn(run func(context.Context, int64, int64, CHAIN_ID) ([]*txmgrtypes.Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], error)) *TxStore_FindTransactionsConfirmedInBlockRange_Call[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE] { _c.Call.Return(run) return _c } @@ -802,6 +793,65 @@ func (_c *TxStore_FindTxAttemptsConfirmedMissingReceipt_Call[ADDR, CHAIN_ID, TX_ return _c } +// FindTxAttemptsRequiringReceiptFetch provides a mock function with given fields: ctx, chainID +func (_m *TxStore[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) FindTxAttemptsRequiringReceiptFetch(ctx context.Context, chainID CHAIN_ID) ([]txmgrtypes.TxAttempt[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], error) { + ret := _m.Called(ctx, chainID) + + if len(ret) == 0 { + panic("no return value specified for FindTxAttemptsRequiringReceiptFetch") + } + + var r0 []txmgrtypes.TxAttempt[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE] + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, CHAIN_ID) ([]txmgrtypes.TxAttempt[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], error)); ok { + return rf(ctx, chainID) + } + if rf, ok := ret.Get(0).(func(context.Context, CHAIN_ID) []txmgrtypes.TxAttempt[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]); ok { + r0 = rf(ctx, chainID) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]txmgrtypes.TxAttempt[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, CHAIN_ID) error); ok { + r1 = rf(ctx, chainID) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// TxStore_FindTxAttemptsRequiringReceiptFetch_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'FindTxAttemptsRequiringReceiptFetch' +type TxStore_FindTxAttemptsRequiringReceiptFetch_Call[ADDR types.Hashable, CHAIN_ID types.ID, TX_HASH types.Hashable, BLOCK_HASH types.Hashable, R txmgrtypes.ChainReceipt[TX_HASH, BLOCK_HASH], SEQ types.Sequence, FEE feetypes.Fee] struct { + *mock.Call +} + +// FindTxAttemptsRequiringReceiptFetch is a helper method to define mock.On call +// - ctx context.Context +// - chainID CHAIN_ID +func (_e *TxStore_Expecter[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) FindTxAttemptsRequiringReceiptFetch(ctx interface{}, chainID interface{}) *TxStore_FindTxAttemptsRequiringReceiptFetch_Call[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE] { + return &TxStore_FindTxAttemptsRequiringReceiptFetch_Call[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]{Call: _e.mock.On("FindTxAttemptsRequiringReceiptFetch", ctx, chainID)} +} + +func (_c *TxStore_FindTxAttemptsRequiringReceiptFetch_Call[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) Run(run func(ctx context.Context, chainID CHAIN_ID)) *TxStore_FindTxAttemptsRequiringReceiptFetch_Call[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE] { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(CHAIN_ID)) + }) + return _c +} + +func (_c *TxStore_FindTxAttemptsRequiringReceiptFetch_Call[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) Return(attempts []txmgrtypes.TxAttempt[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], err error) *TxStore_FindTxAttemptsRequiringReceiptFetch_Call[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE] { + _c.Call.Return(attempts, err) + return _c +} + +func (_c *TxStore_FindTxAttemptsRequiringReceiptFetch_Call[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) RunAndReturn(run func(context.Context, CHAIN_ID) ([]txmgrtypes.TxAttempt[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], error)) *TxStore_FindTxAttemptsRequiringReceiptFetch_Call[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE] { + _c.Call.Return(run) + return _c +} + // FindTxAttemptsRequiringResend provides a mock function with given fields: ctx, olderThan, maxInFlightTransactions, chainID, address func (_m *TxStore[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) FindTxAttemptsRequiringResend(ctx context.Context, olderThan time.Time, maxInFlightTransactions uint32, chainID CHAIN_ID, address ADDR) ([]txmgrtypes.TxAttempt[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], error) { ret := _m.Called(ctx, olderThan, maxInFlightTransactions, chainID, address) @@ -1758,6 +1808,102 @@ func (_c *TxStore_LoadTxAttempts_Call[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SE return _c } +// MarkAllConfirmedMissingReceipt provides a mock function with given fields: ctx, chainID +func (_m *TxStore[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) MarkAllConfirmedMissingReceipt(ctx context.Context, chainID CHAIN_ID) error { + ret := _m.Called(ctx, chainID) + + if len(ret) == 0 { + panic("no return value specified for MarkAllConfirmedMissingReceipt") + } + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context, CHAIN_ID) error); ok { + r0 = rf(ctx, chainID) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// TxStore_MarkAllConfirmedMissingReceipt_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'MarkAllConfirmedMissingReceipt' +type TxStore_MarkAllConfirmedMissingReceipt_Call[ADDR types.Hashable, CHAIN_ID types.ID, TX_HASH types.Hashable, BLOCK_HASH types.Hashable, R txmgrtypes.ChainReceipt[TX_HASH, BLOCK_HASH], SEQ types.Sequence, FEE feetypes.Fee] struct { + *mock.Call +} + +// MarkAllConfirmedMissingReceipt is a helper method to define mock.On call +// - ctx context.Context +// - chainID CHAIN_ID +func (_e *TxStore_Expecter[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) MarkAllConfirmedMissingReceipt(ctx interface{}, chainID interface{}) *TxStore_MarkAllConfirmedMissingReceipt_Call[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE] { + return &TxStore_MarkAllConfirmedMissingReceipt_Call[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]{Call: _e.mock.On("MarkAllConfirmedMissingReceipt", ctx, chainID)} +} + +func (_c *TxStore_MarkAllConfirmedMissingReceipt_Call[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) Run(run func(ctx context.Context, chainID CHAIN_ID)) *TxStore_MarkAllConfirmedMissingReceipt_Call[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE] { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(CHAIN_ID)) + }) + return _c +} + +func (_c *TxStore_MarkAllConfirmedMissingReceipt_Call[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) Return(err error) *TxStore_MarkAllConfirmedMissingReceipt_Call[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE] { + _c.Call.Return(err) + return _c +} + +func (_c *TxStore_MarkAllConfirmedMissingReceipt_Call[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) RunAndReturn(run func(context.Context, CHAIN_ID) error) *TxStore_MarkAllConfirmedMissingReceipt_Call[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE] { + _c.Call.Return(run) + return _c +} + +// MarkOldTxesMissingReceiptAsErrored provides a mock function with given fields: ctx, blockNum, latestFinalizedBlockNum, chainID +func (_m *TxStore[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) MarkOldTxesMissingReceiptAsErrored(ctx context.Context, blockNum int64, latestFinalizedBlockNum int64, chainID CHAIN_ID) error { + ret := _m.Called(ctx, blockNum, latestFinalizedBlockNum, chainID) + + if len(ret) == 0 { + panic("no return value specified for MarkOldTxesMissingReceiptAsErrored") + } + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context, int64, int64, CHAIN_ID) error); ok { + r0 = rf(ctx, blockNum, latestFinalizedBlockNum, chainID) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// TxStore_MarkOldTxesMissingReceiptAsErrored_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'MarkOldTxesMissingReceiptAsErrored' +type TxStore_MarkOldTxesMissingReceiptAsErrored_Call[ADDR types.Hashable, CHAIN_ID types.ID, TX_HASH types.Hashable, BLOCK_HASH types.Hashable, R txmgrtypes.ChainReceipt[TX_HASH, BLOCK_HASH], SEQ types.Sequence, FEE feetypes.Fee] struct { + *mock.Call +} + +// MarkOldTxesMissingReceiptAsErrored is a helper method to define mock.On call +// - ctx context.Context +// - blockNum int64 +// - latestFinalizedBlockNum int64 +// - chainID CHAIN_ID +func (_e *TxStore_Expecter[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) MarkOldTxesMissingReceiptAsErrored(ctx interface{}, blockNum interface{}, latestFinalizedBlockNum interface{}, chainID interface{}) *TxStore_MarkOldTxesMissingReceiptAsErrored_Call[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE] { + return &TxStore_MarkOldTxesMissingReceiptAsErrored_Call[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]{Call: _e.mock.On("MarkOldTxesMissingReceiptAsErrored", ctx, blockNum, latestFinalizedBlockNum, chainID)} +} + +func (_c *TxStore_MarkOldTxesMissingReceiptAsErrored_Call[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) Run(run func(ctx context.Context, blockNum int64, latestFinalizedBlockNum int64, chainID CHAIN_ID)) *TxStore_MarkOldTxesMissingReceiptAsErrored_Call[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE] { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(int64), args[2].(int64), args[3].(CHAIN_ID)) + }) + return _c +} + +func (_c *TxStore_MarkOldTxesMissingReceiptAsErrored_Call[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) Return(_a0 error) *TxStore_MarkOldTxesMissingReceiptAsErrored_Call[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE] { + _c.Call.Return(_a0) + return _c +} + +func (_c *TxStore_MarkOldTxesMissingReceiptAsErrored_Call[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) RunAndReturn(run func(context.Context, int64, int64, CHAIN_ID) error) *TxStore_MarkOldTxesMissingReceiptAsErrored_Call[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE] { + _c.Call.Return(run) + return _c +} + // PreloadTxes provides a mock function with given fields: ctx, attempts func (_m *TxStore[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) PreloadTxes(ctx context.Context, attempts []txmgrtypes.TxAttempt[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) error { ret := _m.Called(ctx, attempts) @@ -1913,12 +2059,12 @@ func (_c *TxStore_ReapTxHistory_Call[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ return _c } -// SaveConfirmedAttempt provides a mock function with given fields: ctx, timeout, attempt, broadcastAt -func (_m *TxStore[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) SaveConfirmedAttempt(ctx context.Context, timeout time.Duration, attempt *txmgrtypes.TxAttempt[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], broadcastAt time.Time) error { +// SaveConfirmedMissingReceiptAttempt provides a mock function with given fields: ctx, timeout, attempt, broadcastAt +func (_m *TxStore[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) SaveConfirmedMissingReceiptAttempt(ctx context.Context, timeout time.Duration, attempt *txmgrtypes.TxAttempt[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], broadcastAt time.Time) error { ret := _m.Called(ctx, timeout, attempt, broadcastAt) if len(ret) == 0 { - panic("no return value specified for SaveConfirmedAttempt") + panic("no return value specified for SaveConfirmedMissingReceiptAttempt") } var r0 error @@ -1931,48 +2077,48 @@ func (_m *TxStore[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) SaveConfirm return r0 } -// TxStore_SaveConfirmedAttempt_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'SaveConfirmedAttempt' -type TxStore_SaveConfirmedAttempt_Call[ADDR types.Hashable, CHAIN_ID types.ID, TX_HASH types.Hashable, BLOCK_HASH types.Hashable, R txmgrtypes.ChainReceipt[TX_HASH, BLOCK_HASH], SEQ types.Sequence, FEE feetypes.Fee] struct { +// TxStore_SaveConfirmedMissingReceiptAttempt_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'SaveConfirmedMissingReceiptAttempt' +type TxStore_SaveConfirmedMissingReceiptAttempt_Call[ADDR types.Hashable, CHAIN_ID types.ID, TX_HASH types.Hashable, BLOCK_HASH types.Hashable, R txmgrtypes.ChainReceipt[TX_HASH, BLOCK_HASH], SEQ types.Sequence, FEE feetypes.Fee] struct { *mock.Call } -// SaveConfirmedAttempt is a helper method to define mock.On call +// SaveConfirmedMissingReceiptAttempt is a helper method to define mock.On call // - ctx context.Context // - timeout time.Duration // - attempt *txmgrtypes.TxAttempt[CHAIN_ID,ADDR,TX_HASH,BLOCK_HASH,SEQ,FEE] // - broadcastAt time.Time -func (_e *TxStore_Expecter[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) SaveConfirmedAttempt(ctx interface{}, timeout interface{}, attempt interface{}, broadcastAt interface{}) *TxStore_SaveConfirmedAttempt_Call[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE] { - return &TxStore_SaveConfirmedAttempt_Call[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]{Call: _e.mock.On("SaveConfirmedAttempt", ctx, timeout, attempt, broadcastAt)} +func (_e *TxStore_Expecter[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) SaveConfirmedMissingReceiptAttempt(ctx interface{}, timeout interface{}, attempt interface{}, broadcastAt interface{}) *TxStore_SaveConfirmedMissingReceiptAttempt_Call[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE] { + return &TxStore_SaveConfirmedMissingReceiptAttempt_Call[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]{Call: _e.mock.On("SaveConfirmedMissingReceiptAttempt", ctx, timeout, attempt, broadcastAt)} } -func (_c *TxStore_SaveConfirmedAttempt_Call[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) Run(run func(ctx context.Context, timeout time.Duration, attempt *txmgrtypes.TxAttempt[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], broadcastAt time.Time)) *TxStore_SaveConfirmedAttempt_Call[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE] { +func (_c *TxStore_SaveConfirmedMissingReceiptAttempt_Call[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) Run(run func(ctx context.Context, timeout time.Duration, attempt *txmgrtypes.TxAttempt[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], broadcastAt time.Time)) *TxStore_SaveConfirmedMissingReceiptAttempt_Call[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE] { _c.Call.Run(func(args mock.Arguments) { run(args[0].(context.Context), args[1].(time.Duration), args[2].(*txmgrtypes.TxAttempt[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]), args[3].(time.Time)) }) return _c } -func (_c *TxStore_SaveConfirmedAttempt_Call[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) Return(_a0 error) *TxStore_SaveConfirmedAttempt_Call[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE] { +func (_c *TxStore_SaveConfirmedMissingReceiptAttempt_Call[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) Return(_a0 error) *TxStore_SaveConfirmedMissingReceiptAttempt_Call[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE] { _c.Call.Return(_a0) return _c } -func (_c *TxStore_SaveConfirmedAttempt_Call[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) RunAndReturn(run func(context.Context, time.Duration, *txmgrtypes.TxAttempt[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], time.Time) error) *TxStore_SaveConfirmedAttempt_Call[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE] { +func (_c *TxStore_SaveConfirmedMissingReceiptAttempt_Call[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) RunAndReturn(run func(context.Context, time.Duration, *txmgrtypes.TxAttempt[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], time.Time) error) *TxStore_SaveConfirmedMissingReceiptAttempt_Call[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE] { _c.Call.Return(run) return _c } -// SaveFetchedReceipts provides a mock function with given fields: ctx, r -func (_m *TxStore[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) SaveFetchedReceipts(ctx context.Context, r []R) error { - ret := _m.Called(ctx, r) +// SaveFetchedReceipts provides a mock function with given fields: ctx, r, state, errorMsg, chainID +func (_m *TxStore[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) SaveFetchedReceipts(ctx context.Context, r []R, state txmgrtypes.TxState, errorMsg *string, chainID CHAIN_ID) error { + ret := _m.Called(ctx, r, state, errorMsg, chainID) if len(ret) == 0 { panic("no return value specified for SaveFetchedReceipts") } var r0 error - if rf, ok := ret.Get(0).(func(context.Context, []R) error); ok { - r0 = rf(ctx, r) + if rf, ok := ret.Get(0).(func(context.Context, []R, txmgrtypes.TxState, *string, CHAIN_ID) error); ok { + r0 = rf(ctx, r, state, errorMsg, chainID) } else { r0 = ret.Error(0) } @@ -1988,13 +2134,16 @@ type TxStore_SaveFetchedReceipts_Call[ADDR types.Hashable, CHAIN_ID types.ID, TX // SaveFetchedReceipts is a helper method to define mock.On call // - ctx context.Context // - r []R -func (_e *TxStore_Expecter[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) SaveFetchedReceipts(ctx interface{}, r interface{}) *TxStore_SaveFetchedReceipts_Call[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE] { - return &TxStore_SaveFetchedReceipts_Call[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]{Call: _e.mock.On("SaveFetchedReceipts", ctx, r)} +// - state txmgrtypes.TxState +// - errorMsg *string +// - chainID CHAIN_ID +func (_e *TxStore_Expecter[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) SaveFetchedReceipts(ctx interface{}, r interface{}, state interface{}, errorMsg interface{}, chainID interface{}) *TxStore_SaveFetchedReceipts_Call[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE] { + return &TxStore_SaveFetchedReceipts_Call[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]{Call: _e.mock.On("SaveFetchedReceipts", ctx, r, state, errorMsg, chainID)} } -func (_c *TxStore_SaveFetchedReceipts_Call[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) Run(run func(ctx context.Context, r []R)) *TxStore_SaveFetchedReceipts_Call[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE] { +func (_c *TxStore_SaveFetchedReceipts_Call[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) Run(run func(ctx context.Context, r []R, state txmgrtypes.TxState, errorMsg *string, chainID CHAIN_ID)) *TxStore_SaveFetchedReceipts_Call[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE] { _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context), args[1].([]R)) + run(args[0].(context.Context), args[1].([]R), args[2].(txmgrtypes.TxState), args[3].(*string), args[4].(CHAIN_ID)) }) return _c } @@ -2004,7 +2153,7 @@ func (_c *TxStore_SaveFetchedReceipts_Call[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, return _c } -func (_c *TxStore_SaveFetchedReceipts_Call[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) RunAndReturn(run func(context.Context, []R) error) *TxStore_SaveFetchedReceipts_Call[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE] { +func (_c *TxStore_SaveFetchedReceipts_Call[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) RunAndReturn(run func(context.Context, []R, txmgrtypes.TxState, *string, CHAIN_ID) error) *TxStore_SaveFetchedReceipts_Call[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE] { _c.Call.Return(run) return _c } @@ -2347,9 +2496,9 @@ func (_c *TxStore_UpdateTxAttemptInProgressToBroadcast_Call[ADDR, CHAIN_ID, TX_H return _c } -// UpdateTxCallbackCompleted provides a mock function with given fields: ctx, pipelineTaskRunRid, chainID -func (_m *TxStore[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) UpdateTxCallbackCompleted(ctx context.Context, pipelineTaskRunRid uuid.UUID, chainID CHAIN_ID) error { - ret := _m.Called(ctx, pipelineTaskRunRid, chainID) +// UpdateTxCallbackCompleted provides a mock function with given fields: ctx, pipelineTaskRunRid, chainId +func (_m *TxStore[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) UpdateTxCallbackCompleted(ctx context.Context, pipelineTaskRunRid uuid.UUID, chainId CHAIN_ID) error { + ret := _m.Called(ctx, pipelineTaskRunRid, chainId) if len(ret) == 0 { panic("no return value specified for UpdateTxCallbackCompleted") @@ -2357,7 +2506,7 @@ func (_m *TxStore[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) UpdateTxCal var r0 error if rf, ok := ret.Get(0).(func(context.Context, uuid.UUID, CHAIN_ID) error); ok { - r0 = rf(ctx, pipelineTaskRunRid, chainID) + r0 = rf(ctx, pipelineTaskRunRid, chainId) } else { r0 = ret.Error(0) } @@ -2373,12 +2522,12 @@ type TxStore_UpdateTxCallbackCompleted_Call[ADDR types.Hashable, CHAIN_ID types. // UpdateTxCallbackCompleted is a helper method to define mock.On call // - ctx context.Context // - pipelineTaskRunRid uuid.UUID -// - chainID CHAIN_ID -func (_e *TxStore_Expecter[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) UpdateTxCallbackCompleted(ctx interface{}, pipelineTaskRunRid interface{}, chainID interface{}) *TxStore_UpdateTxCallbackCompleted_Call[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE] { - return &TxStore_UpdateTxCallbackCompleted_Call[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]{Call: _e.mock.On("UpdateTxCallbackCompleted", ctx, pipelineTaskRunRid, chainID)} +// - chainId CHAIN_ID +func (_e *TxStore_Expecter[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) UpdateTxCallbackCompleted(ctx interface{}, pipelineTaskRunRid interface{}, chainId interface{}) *TxStore_UpdateTxCallbackCompleted_Call[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE] { + return &TxStore_UpdateTxCallbackCompleted_Call[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]{Call: _e.mock.On("UpdateTxCallbackCompleted", ctx, pipelineTaskRunRid, chainId)} } -func (_c *TxStore_UpdateTxCallbackCompleted_Call[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) Run(run func(ctx context.Context, pipelineTaskRunRid uuid.UUID, chainID CHAIN_ID)) *TxStore_UpdateTxCallbackCompleted_Call[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE] { +func (_c *TxStore_UpdateTxCallbackCompleted_Call[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) Run(run func(ctx context.Context, pipelineTaskRunRid uuid.UUID, chainId CHAIN_ID)) *TxStore_UpdateTxCallbackCompleted_Call[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE] { _c.Call.Run(func(args mock.Arguments) { run(args[0].(context.Context), args[1].(uuid.UUID), args[2].(CHAIN_ID)) }) @@ -2395,64 +2544,17 @@ func (_c *TxStore_UpdateTxCallbackCompleted_Call[ADDR, CHAIN_ID, TX_HASH, BLOCK_ return _c } -// UpdateTxConfirmed provides a mock function with given fields: ctx, etxIDs -func (_m *TxStore[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) UpdateTxConfirmed(ctx context.Context, etxIDs []int64) error { - ret := _m.Called(ctx, etxIDs) - - if len(ret) == 0 { - panic("no return value specified for UpdateTxConfirmed") - } - - var r0 error - if rf, ok := ret.Get(0).(func(context.Context, []int64) error); ok { - r0 = rf(ctx, etxIDs) - } else { - r0 = ret.Error(0) - } - - return r0 -} - -// TxStore_UpdateTxConfirmed_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'UpdateTxConfirmed' -type TxStore_UpdateTxConfirmed_Call[ADDR types.Hashable, CHAIN_ID types.ID, TX_HASH types.Hashable, BLOCK_HASH types.Hashable, R txmgrtypes.ChainReceipt[TX_HASH, BLOCK_HASH], SEQ types.Sequence, FEE feetypes.Fee] struct { - *mock.Call -} - -// UpdateTxConfirmed is a helper method to define mock.On call -// - ctx context.Context -// - etxIDs []int64 -func (_e *TxStore_Expecter[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) UpdateTxConfirmed(ctx interface{}, etxIDs interface{}) *TxStore_UpdateTxConfirmed_Call[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE] { - return &TxStore_UpdateTxConfirmed_Call[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]{Call: _e.mock.On("UpdateTxConfirmed", ctx, etxIDs)} -} - -func (_c *TxStore_UpdateTxConfirmed_Call[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) Run(run func(ctx context.Context, etxIDs []int64)) *TxStore_UpdateTxConfirmed_Call[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE] { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context), args[1].([]int64)) - }) - return _c -} - -func (_c *TxStore_UpdateTxConfirmed_Call[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) Return(_a0 error) *TxStore_UpdateTxConfirmed_Call[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE] { - _c.Call.Return(_a0) - return _c -} - -func (_c *TxStore_UpdateTxConfirmed_Call[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) RunAndReturn(run func(context.Context, []int64) error) *TxStore_UpdateTxConfirmed_Call[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE] { - _c.Call.Return(run) - return _c -} - -// UpdateTxFatalError provides a mock function with given fields: ctx, etxIDs, errMsg -func (_m *TxStore[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) UpdateTxFatalError(ctx context.Context, etxIDs []int64, errMsg string) error { - ret := _m.Called(ctx, etxIDs, errMsg) +// UpdateTxFatalError provides a mock function with given fields: ctx, etx +func (_m *TxStore[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) UpdateTxFatalError(ctx context.Context, etx *txmgrtypes.Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) error { + ret := _m.Called(ctx, etx) if len(ret) == 0 { panic("no return value specified for UpdateTxFatalError") } var r0 error - if rf, ok := ret.Get(0).(func(context.Context, []int64, string) error); ok { - r0 = rf(ctx, etxIDs, errMsg) + if rf, ok := ret.Get(0).(func(context.Context, *txmgrtypes.Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) error); ok { + r0 = rf(ctx, etx) } else { r0 = ret.Error(0) } @@ -2467,15 +2569,14 @@ type TxStore_UpdateTxFatalError_Call[ADDR types.Hashable, CHAIN_ID types.ID, TX_ // UpdateTxFatalError is a helper method to define mock.On call // - ctx context.Context -// - etxIDs []int64 -// - errMsg string -func (_e *TxStore_Expecter[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) UpdateTxFatalError(ctx interface{}, etxIDs interface{}, errMsg interface{}) *TxStore_UpdateTxFatalError_Call[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE] { - return &TxStore_UpdateTxFatalError_Call[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]{Call: _e.mock.On("UpdateTxFatalError", ctx, etxIDs, errMsg)} +// - etx *txmgrtypes.Tx[CHAIN_ID,ADDR,TX_HASH,BLOCK_HASH,SEQ,FEE] +func (_e *TxStore_Expecter[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) UpdateTxFatalError(ctx interface{}, etx interface{}) *TxStore_UpdateTxFatalError_Call[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE] { + return &TxStore_UpdateTxFatalError_Call[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]{Call: _e.mock.On("UpdateTxFatalError", ctx, etx)} } -func (_c *TxStore_UpdateTxFatalError_Call[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) Run(run func(ctx context.Context, etxIDs []int64, errMsg string)) *TxStore_UpdateTxFatalError_Call[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE] { +func (_c *TxStore_UpdateTxFatalError_Call[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) Run(run func(ctx context.Context, etx *txmgrtypes.Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE])) *TxStore_UpdateTxFatalError_Call[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE] { _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context), args[1].([]int64), args[2].(string)) + run(args[0].(context.Context), args[1].(*txmgrtypes.Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE])) }) return _c } @@ -2485,22 +2586,22 @@ func (_c *TxStore_UpdateTxFatalError_Call[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R return _c } -func (_c *TxStore_UpdateTxFatalError_Call[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) RunAndReturn(run func(context.Context, []int64, string) error) *TxStore_UpdateTxFatalError_Call[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE] { +func (_c *TxStore_UpdateTxFatalError_Call[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) RunAndReturn(run func(context.Context, *txmgrtypes.Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) error) *TxStore_UpdateTxFatalError_Call[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE] { _c.Call.Return(run) return _c } -// UpdateTxFatalErrorAndDeleteAttempts provides a mock function with given fields: ctx, etx -func (_m *TxStore[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) UpdateTxFatalErrorAndDeleteAttempts(ctx context.Context, etx *txmgrtypes.Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) error { - ret := _m.Called(ctx, etx) +// UpdateTxForRebroadcast provides a mock function with given fields: ctx, etx, etxAttempt +func (_m *TxStore[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) UpdateTxForRebroadcast(ctx context.Context, etx txmgrtypes.Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], etxAttempt txmgrtypes.TxAttempt[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) error { + ret := _m.Called(ctx, etx, etxAttempt) if len(ret) == 0 { - panic("no return value specified for UpdateTxFatalErrorAndDeleteAttempts") + panic("no return value specified for UpdateTxForRebroadcast") } var r0 error - if rf, ok := ret.Get(0).(func(context.Context, *txmgrtypes.Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) error); ok { - r0 = rf(ctx, etx) + if rf, ok := ret.Get(0).(func(context.Context, txmgrtypes.Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], txmgrtypes.TxAttempt[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) error); ok { + r0 = rf(ctx, etx, etxAttempt) } else { r0 = ret.Error(0) } @@ -2508,31 +2609,32 @@ func (_m *TxStore[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) UpdateTxFat return r0 } -// TxStore_UpdateTxFatalErrorAndDeleteAttempts_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'UpdateTxFatalErrorAndDeleteAttempts' -type TxStore_UpdateTxFatalErrorAndDeleteAttempts_Call[ADDR types.Hashable, CHAIN_ID types.ID, TX_HASH types.Hashable, BLOCK_HASH types.Hashable, R txmgrtypes.ChainReceipt[TX_HASH, BLOCK_HASH], SEQ types.Sequence, FEE feetypes.Fee] struct { +// TxStore_UpdateTxForRebroadcast_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'UpdateTxForRebroadcast' +type TxStore_UpdateTxForRebroadcast_Call[ADDR types.Hashable, CHAIN_ID types.ID, TX_HASH types.Hashable, BLOCK_HASH types.Hashable, R txmgrtypes.ChainReceipt[TX_HASH, BLOCK_HASH], SEQ types.Sequence, FEE feetypes.Fee] struct { *mock.Call } -// UpdateTxFatalErrorAndDeleteAttempts is a helper method to define mock.On call +// UpdateTxForRebroadcast is a helper method to define mock.On call // - ctx context.Context -// - etx *txmgrtypes.Tx[CHAIN_ID,ADDR,TX_HASH,BLOCK_HASH,SEQ,FEE] -func (_e *TxStore_Expecter[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) UpdateTxFatalErrorAndDeleteAttempts(ctx interface{}, etx interface{}) *TxStore_UpdateTxFatalErrorAndDeleteAttempts_Call[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE] { - return &TxStore_UpdateTxFatalErrorAndDeleteAttempts_Call[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]{Call: _e.mock.On("UpdateTxFatalErrorAndDeleteAttempts", ctx, etx)} +// - etx txmgrtypes.Tx[CHAIN_ID,ADDR,TX_HASH,BLOCK_HASH,SEQ,FEE] +// - etxAttempt txmgrtypes.TxAttempt[CHAIN_ID,ADDR,TX_HASH,BLOCK_HASH,SEQ,FEE] +func (_e *TxStore_Expecter[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) UpdateTxForRebroadcast(ctx interface{}, etx interface{}, etxAttempt interface{}) *TxStore_UpdateTxForRebroadcast_Call[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE] { + return &TxStore_UpdateTxForRebroadcast_Call[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]{Call: _e.mock.On("UpdateTxForRebroadcast", ctx, etx, etxAttempt)} } -func (_c *TxStore_UpdateTxFatalErrorAndDeleteAttempts_Call[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) Run(run func(ctx context.Context, etx *txmgrtypes.Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE])) *TxStore_UpdateTxFatalErrorAndDeleteAttempts_Call[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE] { +func (_c *TxStore_UpdateTxForRebroadcast_Call[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) Run(run func(ctx context.Context, etx txmgrtypes.Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], etxAttempt txmgrtypes.TxAttempt[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE])) *TxStore_UpdateTxForRebroadcast_Call[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE] { _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context), args[1].(*txmgrtypes.Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE])) + run(args[0].(context.Context), args[1].(txmgrtypes.Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]), args[2].(txmgrtypes.TxAttempt[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE])) }) return _c } -func (_c *TxStore_UpdateTxFatalErrorAndDeleteAttempts_Call[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) Return(_a0 error) *TxStore_UpdateTxFatalErrorAndDeleteAttempts_Call[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE] { +func (_c *TxStore_UpdateTxForRebroadcast_Call[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) Return(_a0 error) *TxStore_UpdateTxForRebroadcast_Call[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE] { _c.Call.Return(_a0) return _c } -func (_c *TxStore_UpdateTxFatalErrorAndDeleteAttempts_Call[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) RunAndReturn(run func(context.Context, *txmgrtypes.Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) error) *TxStore_UpdateTxFatalErrorAndDeleteAttempts_Call[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE] { +func (_c *TxStore_UpdateTxForRebroadcast_Call[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) RunAndReturn(run func(context.Context, txmgrtypes.Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], txmgrtypes.TxAttempt[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) error) *TxStore_UpdateTxForRebroadcast_Call[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE] { _c.Call.Return(run) return _c } @@ -2585,57 +2687,9 @@ func (_c *TxStore_UpdateTxUnstartedToInProgress_Call[ADDR, CHAIN_ID, TX_HASH, BL return _c } -// UpdateTxsForRebroadcast provides a mock function with given fields: ctx, etxIDs, attemptIDs -func (_m *TxStore[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) UpdateTxsForRebroadcast(ctx context.Context, etxIDs []int64, attemptIDs []int64) error { - ret := _m.Called(ctx, etxIDs, attemptIDs) - - if len(ret) == 0 { - panic("no return value specified for UpdateTxsForRebroadcast") - } - - var r0 error - if rf, ok := ret.Get(0).(func(context.Context, []int64, []int64) error); ok { - r0 = rf(ctx, etxIDs, attemptIDs) - } else { - r0 = ret.Error(0) - } - - return r0 -} - -// TxStore_UpdateTxsForRebroadcast_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'UpdateTxsForRebroadcast' -type TxStore_UpdateTxsForRebroadcast_Call[ADDR types.Hashable, CHAIN_ID types.ID, TX_HASH types.Hashable, BLOCK_HASH types.Hashable, R txmgrtypes.ChainReceipt[TX_HASH, BLOCK_HASH], SEQ types.Sequence, FEE feetypes.Fee] struct { - *mock.Call -} - -// UpdateTxsForRebroadcast is a helper method to define mock.On call -// - ctx context.Context -// - etxIDs []int64 -// - attemptIDs []int64 -func (_e *TxStore_Expecter[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) UpdateTxsForRebroadcast(ctx interface{}, etxIDs interface{}, attemptIDs interface{}) *TxStore_UpdateTxsForRebroadcast_Call[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE] { - return &TxStore_UpdateTxsForRebroadcast_Call[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]{Call: _e.mock.On("UpdateTxsForRebroadcast", ctx, etxIDs, attemptIDs)} -} - -func (_c *TxStore_UpdateTxsForRebroadcast_Call[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) Run(run func(ctx context.Context, etxIDs []int64, attemptIDs []int64)) *TxStore_UpdateTxsForRebroadcast_Call[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE] { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context), args[1].([]int64), args[2].([]int64)) - }) - return _c -} - -func (_c *TxStore_UpdateTxsForRebroadcast_Call[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) Return(_a0 error) *TxStore_UpdateTxsForRebroadcast_Call[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE] { - _c.Call.Return(_a0) - return _c -} - -func (_c *TxStore_UpdateTxsForRebroadcast_Call[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) RunAndReturn(run func(context.Context, []int64, []int64) error) *TxStore_UpdateTxsForRebroadcast_Call[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE] { - _c.Call.Return(run) - return _c -} - -// UpdateTxsUnconfirmed provides a mock function with given fields: ctx, etxIDs -func (_m *TxStore[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) UpdateTxsUnconfirmed(ctx context.Context, etxIDs []int64) error { - ret := _m.Called(ctx, etxIDs) +// UpdateTxsUnconfirmed provides a mock function with given fields: ctx, ids +func (_m *TxStore[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) UpdateTxsUnconfirmed(ctx context.Context, ids []int64) error { + ret := _m.Called(ctx, ids) if len(ret) == 0 { panic("no return value specified for UpdateTxsUnconfirmed") @@ -2643,7 +2697,7 @@ func (_m *TxStore[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) UpdateTxsUn var r0 error if rf, ok := ret.Get(0).(func(context.Context, []int64) error); ok { - r0 = rf(ctx, etxIDs) + r0 = rf(ctx, ids) } else { r0 = ret.Error(0) } @@ -2658,12 +2712,12 @@ type TxStore_UpdateTxsUnconfirmed_Call[ADDR types.Hashable, CHAIN_ID types.ID, T // UpdateTxsUnconfirmed is a helper method to define mock.On call // - ctx context.Context -// - etxIDs []int64 -func (_e *TxStore_Expecter[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) UpdateTxsUnconfirmed(ctx interface{}, etxIDs interface{}) *TxStore_UpdateTxsUnconfirmed_Call[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE] { - return &TxStore_UpdateTxsUnconfirmed_Call[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]{Call: _e.mock.On("UpdateTxsUnconfirmed", ctx, etxIDs)} +// - ids []int64 +func (_e *TxStore_Expecter[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) UpdateTxsUnconfirmed(ctx interface{}, ids interface{}) *TxStore_UpdateTxsUnconfirmed_Call[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE] { + return &TxStore_UpdateTxsUnconfirmed_Call[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]{Call: _e.mock.On("UpdateTxsUnconfirmed", ctx, ids)} } -func (_c *TxStore_UpdateTxsUnconfirmed_Call[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) Run(run func(ctx context.Context, etxIDs []int64)) *TxStore_UpdateTxsUnconfirmed_Call[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE] { +func (_c *TxStore_UpdateTxsUnconfirmed_Call[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) Run(run func(ctx context.Context, ids []int64)) *TxStore_UpdateTxsUnconfirmed_Call[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE] { _c.Call.Run(func(args mock.Arguments) { run(args[0].(context.Context), args[1].([]int64)) }) diff --git a/common/txmgr/types/tx.go b/common/txmgr/types/tx.go index b0bc2ca7025..f04047a36c1 100644 --- a/common/txmgr/types/tx.go +++ b/common/txmgr/types/tx.go @@ -342,15 +342,6 @@ func (e *Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) GetChecker() (Transm return t, nil } -func (e *Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) HasPurgeAttempt() bool { - for _, attempt := range e.TxAttempts { - if attempt.IsPurgeAttempt { - return true - } - } - return false -} - // Provides error classification to external components in a chain agnostic way // Only exposes the error types that could be set in the transaction error field type ErrorClassifier interface { diff --git a/common/txmgr/types/tx_store.go b/common/txmgr/types/tx_store.go index d685a6c5ce7..668b8db2049 100644 --- a/common/txmgr/types/tx_store.go +++ b/common/txmgr/types/tx_store.go @@ -36,8 +36,8 @@ type TxStore[ // Find confirmed txes beyond the minConfirmations param that require callback but have not yet been signaled FindTxesPendingCallback(ctx context.Context, latest, finalized int64, chainID CHAIN_ID) (receiptsPlus []ReceiptPlus[R], err error) // Update tx to mark that its callback has been signaled - UpdateTxCallbackCompleted(ctx context.Context, pipelineTaskRunRid uuid.UUID, chainID CHAIN_ID) error - SaveFetchedReceipts(ctx context.Context, r []R) error + UpdateTxCallbackCompleted(ctx context.Context, pipelineTaskRunRid uuid.UUID, chainId CHAIN_ID) error + SaveFetchedReceipts(ctx context.Context, r []R, state TxState, errorMsg *string, chainID CHAIN_ID) error // additional methods for tx store management CheckTxQueueCapacity(ctx context.Context, fromAddress ADDR, maxQueuedTransactions uint64, chainID CHAIN_ID) (err error) @@ -68,12 +68,11 @@ type TransactionStore[ CountUnstartedTransactions(ctx context.Context, fromAddress ADDR, chainID CHAIN_ID) (count uint32, err error) CreateTransaction(ctx context.Context, txRequest TxRequest[ADDR, TX_HASH], chainID CHAIN_ID) (tx Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], err error) DeleteInProgressAttempt(ctx context.Context, attempt TxAttempt[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) error - FindLatestSequence(ctx context.Context, fromAddress ADDR, chainID CHAIN_ID) (SEQ, error) - // FindReorgOrIncludedTxs returns either a list of re-org'd transactions or included transactions based on the provided sequence - FindReorgOrIncludedTxs(ctx context.Context, fromAddress ADDR, nonce SEQ, chainID CHAIN_ID) (reorgTx []*Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], includedTxs []*Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], err error) + FindLatestSequence(ctx context.Context, fromAddress ADDR, chainId CHAIN_ID) (SEQ, error) FindTxsRequiringGasBump(ctx context.Context, address ADDR, blockNum, gasBumpThreshold, depth int64, chainID CHAIN_ID) (etxs []*Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], err error) FindTxsRequiringResubmissionDueToInsufficientFunds(ctx context.Context, address ADDR, chainID CHAIN_ID) (etxs []*Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], err error) FindTxAttemptsConfirmedMissingReceipt(ctx context.Context, chainID CHAIN_ID) (attempts []TxAttempt[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], err error) + FindTxAttemptsRequiringReceiptFetch(ctx context.Context, chainID CHAIN_ID) (attempts []TxAttempt[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], err error) FindTxAttemptsRequiringResend(ctx context.Context, olderThan time.Time, maxInFlightTransactions uint32, chainID CHAIN_ID, address ADDR) (attempts []TxAttempt[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], err error) // Search for Tx using the idempotencyKey and chainID FindTxWithIdempotencyKey(ctx context.Context, idempotencyKey string, chainID CHAIN_ID) (tx *Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], err error) @@ -81,6 +80,8 @@ type TransactionStore[ FindTxWithSequence(ctx context.Context, fromAddress ADDR, seq SEQ) (etx *Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], err error) FindNextUnstartedTransactionFromAddress(ctx context.Context, fromAddress ADDR, chainID CHAIN_ID) (*Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], error) + // FindTransactionsConfirmedInBlockRange retrieves tx with attempts and partial receipt values for optimization purpose + FindTransactionsConfirmedInBlockRange(ctx context.Context, highBlockNumber, lowBlockNumber int64, chainID CHAIN_ID) (etxs []*Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], err error) FindEarliestUnconfirmedBroadcastTime(ctx context.Context, chainID CHAIN_ID) (null.Time, error) FindEarliestUnconfirmedTxAttemptBlock(ctx context.Context, chainID CHAIN_ID) (null.Int, error) GetTxInProgress(ctx context.Context, fromAddress ADDR) (etx *Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], err error) @@ -89,8 +90,10 @@ type TransactionStore[ GetTxByID(ctx context.Context, id int64) (tx *Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], err error) HasInProgressTransaction(ctx context.Context, account ADDR, chainID CHAIN_ID) (exists bool, err error) LoadTxAttempts(ctx context.Context, etx *Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) error + MarkAllConfirmedMissingReceipt(ctx context.Context, chainID CHAIN_ID) (err error) + MarkOldTxesMissingReceiptAsErrored(ctx context.Context, blockNum int64, latestFinalizedBlockNum int64, chainID CHAIN_ID) error PreloadTxes(ctx context.Context, attempts []TxAttempt[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) error - SaveConfirmedAttempt(ctx context.Context, timeout time.Duration, attempt *TxAttempt[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], broadcastAt time.Time) error + SaveConfirmedMissingReceiptAttempt(ctx context.Context, timeout time.Duration, attempt *TxAttempt[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], broadcastAt time.Time) error SaveInProgressAttempt(ctx context.Context, attempt *TxAttempt[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) error SaveInsufficientFundsAttempt(ctx context.Context, timeout time.Duration, attempt *TxAttempt[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], broadcastAt time.Time) error SaveReplacementInProgressAttempt(ctx context.Context, oldAttempt TxAttempt[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], replacementAttempt *TxAttempt[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) error @@ -98,17 +101,12 @@ type TransactionStore[ SetBroadcastBeforeBlockNum(ctx context.Context, blockNum int64, chainID CHAIN_ID) error UpdateBroadcastAts(ctx context.Context, now time.Time, etxIDs []int64) error UpdateTxAttemptInProgressToBroadcast(ctx context.Context, etx *Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], attempt TxAttempt[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], NewAttemptState TxAttemptState) error - // UpdateTxCallbackCompleted updates tx to mark that its callback has been signaled - UpdateTxCallbackCompleted(ctx context.Context, pipelineTaskRunRid uuid.UUID, chainID CHAIN_ID) error - // UpdateTxConfirmed updates transaction states to confirmed - UpdateTxConfirmed(ctx context.Context, etxIDs []int64) error - // UpdateTxFatalErrorAndDeleteAttempts updates transaction states to fatal error, deletes attempts, and clears broadcast info and sequence - UpdateTxFatalErrorAndDeleteAttempts(ctx context.Context, etx *Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) error - // UpdateTxFatalError updates transaction states to fatal error with error message - UpdateTxFatalError(ctx context.Context, etxIDs []int64, errMsg string) error - UpdateTxsForRebroadcast(ctx context.Context, etxIDs []int64, attemptIDs []int64) error - UpdateTxsUnconfirmed(ctx context.Context, etxIDs []int64) error + // Update tx to mark that its callback has been signaled + UpdateTxCallbackCompleted(ctx context.Context, pipelineTaskRunRid uuid.UUID, chainId CHAIN_ID) error + UpdateTxsUnconfirmed(ctx context.Context, ids []int64) error UpdateTxUnstartedToInProgress(ctx context.Context, etx *Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], attempt *TxAttempt[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) error + UpdateTxFatalError(ctx context.Context, etx *Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) error + UpdateTxForRebroadcast(ctx context.Context, etx Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], etxAttempt TxAttempt[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) error } type TxHistoryReaper[CHAIN_ID types.ID] interface { diff --git a/contracts/.changeset/bright-jokes-kiss.md b/contracts/.changeset/bright-jokes-kiss.md deleted file mode 100644 index 9aac95d84c9..00000000000 --- a/contracts/.changeset/bright-jokes-kiss.md +++ /dev/null @@ -1,10 +0,0 @@ ---- -'@chainlink/contracts': patch ---- - -add legacy fallback to RMN - - -PR issue: CCIP-4261 - -Solidity Review issue: CCIP-3966 \ No newline at end of file diff --git a/contracts/.changeset/chilly-rockets-share.md b/contracts/.changeset/chilly-rockets-share.md deleted file mode 100644 index ef5d3e454d7..00000000000 --- a/contracts/.changeset/chilly-rockets-share.md +++ /dev/null @@ -1,10 +0,0 @@ ---- -'@chainlink/contracts': patch ---- - -Moves all audited L2EP contracts out from dev directory - - -PR issue: SHIP-3191 - -Solidity Review issue: SHIP-4050 \ No newline at end of file diff --git a/contracts/.changeset/cold-geckos-yawn.md b/contracts/.changeset/cold-geckos-yawn.md deleted file mode 100644 index e7677f1282e..00000000000 --- a/contracts/.changeset/cold-geckos-yawn.md +++ /dev/null @@ -1,10 +0,0 @@ ---- -'@chainlink/contracts': minor ---- - -Remove dead transmission code - - -PR issue: CM-661 - -Solidity Review issue: CM-662 \ No newline at end of file diff --git a/contracts/.changeset/early-cups-relax.md b/contracts/.changeset/early-cups-relax.md deleted file mode 100644 index 1ec6aaba0b7..00000000000 --- a/contracts/.changeset/early-cups-relax.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -'@chainlink/contracts': minor ---- - -#internal Account for tokenTransferBytesOverhead in exec cost - -PR issue: CCIP-4646 - -Solidity Review issue: CCIP-3966 \ No newline at end of file diff --git a/contracts/.changeset/eighty-cycles-film.md b/contracts/.changeset/eighty-cycles-film.md deleted file mode 100644 index 6cd56afa80a..00000000000 --- a/contracts/.changeset/eighty-cycles-film.md +++ /dev/null @@ -1,10 +0,0 @@ ---- -'@chainlink/contracts': patch ---- - -remove legacy curse check from RMNRemote isCursed() method #bugfix - - -PR issue: CCIP-4476 - -Solidity Review issue: CCIP-3966 \ No newline at end of file diff --git a/contracts/.changeset/fluffy-eels-tan.md b/contracts/.changeset/fluffy-eels-tan.md deleted file mode 100644 index 967e7e2f72d..00000000000 --- a/contracts/.changeset/fluffy-eels-tan.md +++ /dev/null @@ -1,10 +0,0 @@ ---- -'@chainlink/contracts': patch ---- - -Add token address to TokenHandlingError - - -PR issue: CCIP-4174 - -Solidity Review issue: CCIP-3966 \ No newline at end of file diff --git a/contracts/.changeset/hot-pandas-carry.md b/contracts/.changeset/hot-pandas-carry.md deleted file mode 100644 index 8042cd82da6..00000000000 --- a/contracts/.changeset/hot-pandas-carry.md +++ /dev/null @@ -1,10 +0,0 @@ ---- -'@chainlink/contracts': minor ---- - -Add a new contract, BurnMintERC20, which is basically just our ERC677 implementation without the transferAndCall function. #internal - - -PR issue: CCIP-4130 - -Solidity Review issue: CCIP-3966 \ No newline at end of file diff --git a/contracts/.changeset/mean-masks-poke.md b/contracts/.changeset/mean-masks-poke.md deleted file mode 100644 index 00d8434e226..00000000000 --- a/contracts/.changeset/mean-masks-poke.md +++ /dev/null @@ -1,10 +0,0 @@ ---- -'@chainlink/contracts': patch ---- - -#added new function to CCIPReaderTester getLatestPriceSequenceNumber - - -PR issue: CCIP-4239 - -Solidity Review issue: CCIP-3966 \ No newline at end of file diff --git a/contracts/.changeset/modern-mayflies-give.md b/contracts/.changeset/modern-mayflies-give.md deleted file mode 100644 index c54f69e8489..00000000000 --- a/contracts/.changeset/modern-mayflies-give.md +++ /dev/null @@ -1,10 +0,0 @@ ---- -'@chainlink/contracts': patch ---- - -allow multiple remote pools per chain selector - - -PR issue: CCIP-4269 - -Solidity Review issue: CCIP-3966 \ No newline at end of file diff --git a/contracts/.changeset/new-elephants-behave.md b/contracts/.changeset/new-elephants-behave.md deleted file mode 100644 index 29f3c248afc..00000000000 --- a/contracts/.changeset/new-elephants-behave.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@chainlink/contracts': patch ---- - -fix test naming diff --git a/contracts/.changeset/ninety-lions-complain.md b/contracts/.changeset/ninety-lions-complain.md deleted file mode 100644 index 32c81e46eee..00000000000 --- a/contracts/.changeset/ninety-lions-complain.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@chainlink/contracts': patch ---- - -Update token pool factory to support new token pool design with arbitrary decimals #bugfix diff --git a/contracts/.changeset/perfect-bears-clean.md b/contracts/.changeset/perfect-bears-clean.md deleted file mode 100644 index 0f8284037f5..00000000000 --- a/contracts/.changeset/perfect-bears-clean.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@chainlink/contracts': patch ---- - -Add BalanceReader contract for native balance reads through a contract diff --git a/contracts/.changeset/rude-badgers-tickle.md b/contracts/.changeset/rude-badgers-tickle.md deleted file mode 100644 index 4dddf8d430e..00000000000 --- a/contracts/.changeset/rude-badgers-tickle.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@chainlink/contracts': patch ---- - -reduce length of reportContext in OCR3 diff --git a/contracts/.changeset/small-countries-flow.md b/contracts/.changeset/small-countries-flow.md deleted file mode 100644 index 953102874bc..00000000000 --- a/contracts/.changeset/small-countries-flow.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@chainlink/contracts': patch ---- - -Modify TokenPool.sol function setChainRateLimiterConfig to now accept an array of configs and set sequentially. Requested by front-end. PR issue CCIP-4329 #bugfix diff --git a/contracts/.changeset/tame-cycles-ring.md b/contracts/.changeset/tame-cycles-ring.md deleted file mode 100644 index 31fb56ce133..00000000000 --- a/contracts/.changeset/tame-cycles-ring.md +++ /dev/null @@ -1,10 +0,0 @@ ---- -'@chainlink/contracts': patch ---- - -enable via-ir in CCIP compilation - - -PR issue: CCIP-4656 - -Solidity Review issue: CCIP-3966 \ No newline at end of file diff --git a/contracts/.changeset/tender-lemons-punch.md b/contracts/.changeset/tender-lemons-punch.md deleted file mode 100644 index cac2e7ea0cf..00000000000 --- a/contracts/.changeset/tender-lemons-punch.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -'@chainlink/contracts': minor ---- - -#internal Add supportsInterface to FeeQuoter for Keystone - -PR issue: CCIP-4359 - -Solidity Review issue: CCIP-3966 \ No newline at end of file diff --git a/contracts/.changeset/thirty-rules-rule.md b/contracts/.changeset/thirty-rules-rule.md deleted file mode 100644 index 1c69192981c..00000000000 --- a/contracts/.changeset/thirty-rules-rule.md +++ /dev/null @@ -1,10 +0,0 @@ ---- -'@chainlink/contracts': patch ---- - -[L2EP] Refactor tests and fix file exclusion for coverage - - -PR issue: SHIP-3521 - -Solidity Review issue: SHIP-4050 \ No newline at end of file diff --git a/contracts/.changeset/three-dogs-return.md b/contracts/.changeset/three-dogs-return.md deleted file mode 100644 index c0b4a48f7f6..00000000000 --- a/contracts/.changeset/three-dogs-return.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@chainlink/contracts': patch ---- - -extra validation on decimal logic in token pools diff --git a/contracts/.changeset/violet-lamps-pump.md b/contracts/.changeset/violet-lamps-pump.md deleted file mode 100644 index 4b180df24cd..00000000000 --- a/contracts/.changeset/violet-lamps-pump.md +++ /dev/null @@ -1,10 +0,0 @@ ---- -'@chainlink/contracts': patch ---- - -Create a new version of the ERC165Checker library which checks for sufficient gas before making an external call to prevent message delivery issues. #bugfix - - -PR issue: CCIP-4659 - -Solidity Review issue: CCIP-3966 \ No newline at end of file diff --git a/contracts/.changeset/wet-eyes-accept.md b/contracts/.changeset/wet-eyes-accept.md deleted file mode 100644 index ea783366220..00000000000 --- a/contracts/.changeset/wet-eyes-accept.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -'@chainlink/contracts': patch ---- - -Refactor MockCCIPRouter to support EVMExtraArgsV2 - -PR issue : CCIP-4288 diff --git a/contracts/.changeset/yellow-mugs-explode.md b/contracts/.changeset/yellow-mugs-explode.md deleted file mode 100644 index bd488e559ef..00000000000 --- a/contracts/.changeset/yellow-mugs-explode.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -'@chainlink/contracts': minor ---- - -#internal make gas for call exact check immutable - -PR issue: CCIP-4477 - -Solidity Review issue: CCIP-3966 \ No newline at end of file diff --git a/contracts/.changeset/young-bats-rhyme.md b/contracts/.changeset/young-bats-rhyme.md deleted file mode 100644 index e68a646b78e..00000000000 --- a/contracts/.changeset/young-bats-rhyme.md +++ /dev/null @@ -1,10 +0,0 @@ ---- -'@chainlink/contracts': patch ---- - -add getChainConfig to ccipHome - - -PR issue: CCIP-4517 - -Solidity Review issue: CCIP-3966 \ No newline at end of file diff --git a/contracts/.solhintignore-test b/contracts/.solhintignore-test index 137ba9998c7..acaca4fe1e4 100644 --- a/contracts/.solhintignore-test +++ b/contracts/.solhintignore-test @@ -4,6 +4,7 @@ ./src/v0.8/tests ./src/v0.8/llo-feeds/ ./src/v0.8/automation/ +./src/v0.8/transmission/ ./src/v0.8/l2ep/ ./src/v0.8/shared/ ./src/v0.8/operatorforwarder/ diff --git a/contracts/GNUmakefile b/contracts/GNUmakefile index 7361754ee0b..a12e7d2075c 100644 --- a/contracts/GNUmakefile +++ b/contracts/GNUmakefile @@ -1,6 +1,6 @@ # ALL_FOUNDRY_PRODUCTS contains a list of all products that have a foundry # profile defined and use the Foundry snapshots. -ALL_FOUNDRY_PRODUCTS = ccip functions keystone l2ep liquiditymanager llo-feeds operatorforwarder shared workflow +ALL_FOUNDRY_PRODUCTS = ccip functions keystone l2ep liquiditymanager llo-feeds operatorforwarder shared transmission workflow # To make a snapshot for a specific product, either set the `FOUNDRY_PROFILE` env var # or call the target with `FOUNDRY_PROFILE=product` @@ -43,7 +43,7 @@ mockery: $(mockery) ## Install mockery. .PHONY: foundry foundry: ## Install foundry. - foundryup --version nightly-aa69ed1e46dd61fbf9d73399396a4db4dd527431 + foundryup --version nightly-3ff3d0562215bca620e07c5c4c154eec8da0f04b .PHONY: foundry-refresh foundry-refresh: foundry diff --git a/contracts/README.md b/contracts/README.md index f87f196e5dc..182891ceef7 100644 --- a/contracts/README.md +++ b/contracts/README.md @@ -24,7 +24,7 @@ $ npm install @chainlink/contracts --save The solidity smart contracts themselves can be imported via the `src` directory of `@chainlink/contracts`: ```solidity -import {AutomationCompatibleInterface} from '@chainlink/contracts/src/v0.8/AutomationCompatibleInterface.sol'; +import '@chainlink/contracts/src/v0.8/AutomationCompatibleInterface.sol'; ``` ## Local Development @@ -42,7 +42,7 @@ $ pnpm test ## Contributing -Please adhere to the [Solidity Style Guide](https://github.com/smartcontractkit/chainlink/blob/develop/contracts/STYLE.md). +Please try to adhere to [Solidity Style Guide](https://github.com/smartcontractkit/chainlink/blob/develop/contracts/STYLE.md). Contributions are welcome! Please refer to [Chainlink's contributing guidelines](https://github.com/smartcontractkit/chainlink/blob/develop/docs/CONTRIBUTING.md) for detailed @@ -70,6 +70,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 Most of the contracts are licensed under the [MIT](https://choosealicense.com/licenses/mit/) license. An exception to this is the ccip folder, which defaults to be licensed under the [BUSL-1.1](./src/v0.8/ccip/LICENSE.md) license, however, there are a few exceptions -- `src/v0.8/ccip/applications/*` is licensed under the [MIT](https://choosealicense.com/licenses/mit/) license -- `src/v0.8/ccip/interfaces/*` is licensed under the [MIT](https://choosealicense.com/licenses/mit/) license -- `src/v0.8/ccip/libraries/{Client.sol, Internal.sol}` is licensed under the [MIT](https://choosealicense.com/licenses/mit/) license \ No newline at end of file +- `src/v0.8/ccip/applications/*` is licensed under the [MIT](./src/v0.8/ccip/LICENSE-MIT.md) license +- `src/v0.8/ccip/interfaces/*` is licensed under the [MIT](./src/v0.8/ccip/LICENSE-MIT.md) license +- `src/v0.8/ccip/libraries/{Client.sol, Internal.sol}` is licensed under the [MIT](./src/v0.8/ccip/LICENSE-MIT.md) license \ No newline at end of file diff --git a/contracts/foundry.toml b/contracts/foundry.toml index 7fe77e08c07..45272ad3f17 100644 --- a/contracts/foundry.toml +++ b/contracts/foundry.toml @@ -22,23 +22,12 @@ multiline_func_header = "params_first" sort_imports = true single_line_statement_blocks = "preserve" -# This profile should be used for testing CCIP locally and in CI. [profile.ccip] -solc_version = '0.8.26' +solc_version = '0.8.24' src = 'src/v0.8/ccip' test = 'src/v0.8/ccip/test' -evm_version = 'paris' optimizer_runs = 500 - -# This profile should be used prior to any release to ensure the tests are passing with via-ir enabled. Enabling via-ir -# locally or in CI will slow down the compilation process, so it is not recommended to use it for everyday development. -[profile.ccip-viair] -solc_version = '0.8.26' -src = 'src/v0.8/ccip' -test = 'src/v0.8/ccip/test' evm_version = 'paris' -optimizer_runs = 800 -via_ir = true [profile.functions] solc_version = '0.8.19' @@ -96,6 +85,12 @@ solc_version = '0.8.19' src = 'src/v0.8/operatorforwarder' test = 'src/v0.8/operatorforwarder/test' +[profile.transmission] +optimizer_runs = 1_000_000 +solc_version = '0.8.19' +src = 'src/v0.8/transmission' +test = 'src/v0.8/transmission/test' + [profile.workflow] optimizer_runs = 1_000_000 solc_version = '0.8.24' diff --git a/contracts/gas-snapshots/ccip.gas-snapshot b/contracts/gas-snapshots/ccip.gas-snapshot index 0c81de75a01..54b9cdf22d7 100644 --- a/contracts/gas-snapshots/ccip.gas-snapshot +++ b/contracts/gas-snapshots/ccip.gas-snapshot @@ -1,406 +1,757 @@ -ARMProxy_constructor:test_Constructor() (gas: 302031) -ARMProxy_isCursed:test_IsCursed_GlobalCurseSubject() (gas: 89809) +ARMProxy_constructor:test_Constructor() (gas: 302231) +ARMProxy_isCursed:test_IsCursed_Success() (gas: 47209) +ARMProxy_isCursed:test_call_ARMCallEmptyContract_Revert() (gas: 19412) +ARMProxy_isCursed:test_isCursed_RevertReasonForwarded_Revert() (gas: 45210) ARMProxy_setARM:test_SetARM() (gas: 16599) ARMProxy_setARM:test_SetARMzero() (gas: 11275) -BurnFromMintTokenPool_lockOrBurn:test_PoolBurn() (gas: 238950) -BurnFromMintTokenPool_lockOrBurn:test_setup() (gas: 24178) -BurnMintTokenPool_lockOrBurn:test_PoolBurn() (gas: 236872) -BurnMintTokenPool_lockOrBurn:test_Setup() (gas: 17819) -BurnMintTokenPool_releaseOrMint:test_PoolMint() (gas: 102527) -BurnMintWithLockReleaseFlagTokenPool_lockOrBurn:test_LockOrBurn_CorrectReturnData() (gas: 237292) -BurnWithFromMintTokenPool_lockOrBurn:test_PoolBurn() (gas: 239012) -BurnWithFromMintTokenPool_lockOrBurn:test_Setup() (gas: 24169) -CCIPClientExample_sanity:test_ImmutableExamples() (gas: 2072849) -CCIPHome__validateConfig:test__validateConfig() (gas: 300016) -CCIPHome__validateConfig:test__validateConfigLessTransmittersThanSigners() (gas: 332965) -CCIPHome__validateConfig:test__validateConfigSmallerFChain() (gas: 459322) -CCIPHome_applyChainConfigUpdates:test_applyChainConfigUpdates_addChainConfigs() (gas: 350127) -CCIPHome_applyChainConfigUpdates:test_applyChainConfigUpdates_removeChainConfigs() (gas: 282241) -CCIPHome_applyChainConfigUpdates:test_getPaginatedCCIPHomes() (gas: 373692) -CCIPHome_beforeCapabilityConfigSet:test_beforeCapabilityConfigSet() (gas: 1455733) -CCIPHome_constructor:test_constructor() (gas: 3547489) -CCIPHome_getAllConfigs:test_getAllConfigs() (gas: 2772793) -CCIPHome_getCapabilityConfiguration:test_getCapabilityConfiguration() (gas: 9073) -CCIPHome_getConfigDigests:test_getConfigDigests() (gas: 2547587) -CCIPHome_promoteCandidateAndRevokeActive:test_promoteCandidateAndRevokeActive_multiplePlugins() (gas: 5113791) -CCIPHome_revokeCandidate:test_revokeCandidate() (gas: 30647) -CCIPHome_setCandidate:test_setCandidate() (gas: 1365392) -CCIPHome_supportsInterface:test_supportsInterface() (gas: 9885) -DefensiveExampleTest:test_HappyPath() (gas: 200517) -DefensiveExampleTest:test_Recovery() (gas: 424996) -E2E:test_E2E_3MessagesMMultiOffRampSuccess_gas() (gas: 1490237) -ERC165CheckerReverting_supportsInterfaceReverting:test__supportsInterfaceReverting() (gas: 10445) -EtherSenderReceiverTest_ccipReceive:test_ccipReceive_fallbackToWethTransfer() (gas: 96964) -EtherSenderReceiverTest_ccipReceive:test_ccipReceive_happyPath() (gas: 49797) -EtherSenderReceiverTest_ccipReceive:test_ccipReceive_wrongToken() (gas: 17460) -EtherSenderReceiverTest_ccipReceive:test_ccipReceive_wrongTokenAmount() (gas: 15748) -EtherSenderReceiverTest_ccipSend:test_ccipSend_feeToken() (gas: 145087) -EtherSenderReceiverTest_ccipSend:test_ccipSend_native() (gas: 80451) -EtherSenderReceiverTest_ccipSend:test_ccipSend_nativeExcess() (gas: 80616) -EtherSenderReceiverTest_ccipSend:test_ccipSend_weth() (gas: 96167) -EtherSenderReceiverTest_constructor:test_constructor() (gas: 17582) -EtherSenderReceiverTest_getFee:test_getFee() (gas: 27482) -EtherSenderReceiverTest_validateFeeToken:test_validateFeeToken_valid_feeToken() (gas: 16700) -EtherSenderReceiverTest_validateFeeToken:test_validateFeeToken_valid_native() (gas: 16611) -EtherSenderReceiverTest_validatedMessage:test_validatedMessage_dataOverwrittenToMsgSender() (gas: 25455) -EtherSenderReceiverTest_validatedMessage:test_validatedMessage_emptyDataOverwrittenToMsgSender() (gas: 25372) -EtherSenderReceiverTest_validatedMessage:test_validatedMessage_invalidTokenAmounts() (gas: 17955) -EtherSenderReceiverTest_validatedMessage:test_validatedMessage_tokenOverwrittenToWeth() (gas: 25327) -EtherSenderReceiverTest_validatedMessage:test_validatedMessage_validMessage_extraArgs() (gas: 26347) -FactoryBurnMintERC20_approve:test_Approve() (gas: 55786) -FactoryBurnMintERC20_burn:test_BasicBurn() (gas: 172448) -FactoryBurnMintERC20_burnFrom:test_BurnFrom() (gas: 58290) -FactoryBurnMintERC20_burnFromAlias:test_BurnFrom() (gas: 58264) -FactoryBurnMintERC20_constructor:test_Constructor() (gas: 1450297) -FactoryBurnMintERC20_decreaseApproval:test_DecreaseApproval() (gas: 31420) -FactoryBurnMintERC20_getCCIPAdmin:test_getCCIPAdmin() (gas: 12740) -FactoryBurnMintERC20_getCCIPAdmin:test_setCCIPAdmin() (gas: 23852) -FactoryBurnMintERC20_grantMintAndBurnRoles:test_GrantMintAndBurnRoles() (gas: 121216) -FactoryBurnMintERC20_grantRole:test_GrantBurnAccess() (gas: 53386) -FactoryBurnMintERC20_grantRole:test_GrantMany() (gas: 961708) -FactoryBurnMintERC20_grantRole:test_GrantMintAccess() (gas: 94181) -FactoryBurnMintERC20_increaseApproval:test_IncreaseApproval() (gas: 44421) -FactoryBurnMintERC20_mint:test_BasicMint() (gas: 149826) -FactoryBurnMintERC20_supportsInterface:test_SupportsInterface() (gas: 11539) -FactoryBurnMintERC20_transfer:test_Transfer() (gas: 42505) -FeeQuoter_applyDestChainConfigUpdates:test_applyDestChainConfigUpdates() (gas: 141541) -FeeQuoter_applyDestChainConfigUpdates:test_applyDestChainConfigUpdatesZeroInput() (gas: 12536) -FeeQuoter_applyFeeTokensUpdates:test_ApplyFeeTokensUpdates() (gas: 162691) -FeeQuoter_applyPremiumMultiplierWeiPerEthUpdates:test_applyPremiumMultiplierWeiPerEthUpdatesMultipleTokens() (gas: 54793) -FeeQuoter_applyPremiumMultiplierWeiPerEthUpdates:test_applyPremiumMultiplierWeiPerEthUpdatesSingleToken() (gas: 45276) -FeeQuoter_applyPremiumMultiplierWeiPerEthUpdates:test_applyPremiumMultiplierWeiPerEthUpdatesZeroInput() (gas: 12380) -FeeQuoter_applyTokenTransferFeeConfigUpdates:test_ApplyTokenTransferFeeConfig() (gas: 88736) -FeeQuoter_applyTokenTransferFeeConfigUpdates:test_ApplyTokenTransferFeeZeroInput() (gas: 13218) -FeeQuoter_constructor:test_Setup() (gas: 5039899) -FeeQuoter_convertTokenAmount:test_ConvertTokenAmount() (gas: 68417) -FeeQuoter_getDataAvailabilityCost:test_EmptyMessageCalculatesDataAvailabilityCost() (gas: 96377) -FeeQuoter_getDataAvailabilityCost:test_SimpleMessageCalculatesDataAvailabilityCost() (gas: 21075) -FeeQuoter_getDataAvailabilityCost:test_SimpleMessageCalculatesDataAvailabilityCostUnsupportedDestChainSelector() (gas: 14836) -FeeQuoter_getTokenAndGasPrices:test_GetFeeTokenAndGasPrices() (gas: 73123) -FeeQuoter_getTokenAndGasPrices:test_StalenessCheckDisabled() (gas: 111926) -FeeQuoter_getTokenAndGasPrices:test_ZeroGasPrice() (gas: 109013) -FeeQuoter_getTokenPrice:test_GetTokenPriceFromFeed() (gas: 68180) -FeeQuoter_getTokenPrice:test_GetTokenPrice_LocalMoreRecent() (gas: 33568) -FeeQuoter_getTokenPrices:test_GetTokenPrices() (gas: 78534) -FeeQuoter_getTokenTransferCost:test_CustomTokenBpsFee() (gas: 37322) -FeeQuoter_getTokenTransferCost:test_FeeTokenBpsFee() (gas: 35101) -FeeQuoter_getTokenTransferCost:test_LargeTokenTransferChargesMaxFeeAndGas() (gas: 28149) -FeeQuoter_getTokenTransferCost:test_MixedTokenTransferFee() (gas: 96077) -FeeQuoter_getTokenTransferCost:test_NoTokenTransferChargesZeroFee() (gas: 20587) -FeeQuoter_getTokenTransferCost:test_SmallTokenTransferChargesMinFeeAndGas() (gas: 27978) -FeeQuoter_getTokenTransferCost:test_ZeroAmountTokenTransferChargesMinFeeAndGas() (gas: 27979) -FeeQuoter_getTokenTransferCost:test_ZeroFeeConfigChargesMinFee() (gas: 40537) -FeeQuoter_getTokenTransferCost:test_getTokenTransferCost_selfServeUsesDefaults() (gas: 29706) -FeeQuoter_getValidatedFee:test_EmptyMessage() (gas: 83608) -FeeQuoter_getValidatedFee:test_HighGasMessage() (gas: 240058) -FeeQuoter_getValidatedFee:test_MessageWithDataAndTokenTransfer() (gas: 143671) -FeeQuoter_getValidatedFee:test_SingleTokenMessage() (gas: 115178) -FeeQuoter_getValidatedFee:test_ZeroDataAvailabilityMultiplier() (gas: 63919) -FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPrice() (gas: 58905) -FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeed() (gas: 65115) -FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedErc20Above18Decimals() (gas: 1897724) -FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedErc20Below18Decimals() (gas: 1897766) -FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedFeedAt0Decimals() (gas: 1877822) -FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedFeedAt18Decimals() (gas: 1897564) -FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedFlippedDecimals() (gas: 1897700) -FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedMaxInt224Value() (gas: 1897534) -FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedOverStalenessPeriod() (gas: 65233) -FeeQuoter_getValidatedTokenPrice:test_StaleFeeToken() (gas: 61854) -FeeQuoter_onReport:test_OnReport_SkipPriceUpdateWhenStaleUpdateReceived() (gas: 52631) -FeeQuoter_onReport:test_onReport() (gas: 89096) -FeeQuoter_onReport:test_onReport_withKeystoneForwarderContract() (gas: 122724) -FeeQuoter_parseEVMExtraArgsFromBytes:test_EVMExtraArgsDefault() (gas: 17207) -FeeQuoter_parseEVMExtraArgsFromBytes:test_EVMExtraArgsV1() (gas: 18283) -FeeQuoter_parseEVMExtraArgsFromBytes:test_EVMExtraArgsV2() (gas: 18391) -FeeQuoter_processMessageArgs:test_processMessageArgs_WitEVMExtraArgsV2() (gas: 28669) -FeeQuoter_processMessageArgs:test_processMessageArgs_WithConvertedTokenAmount() (gas: 30001) -FeeQuoter_processMessageArgs:test_processMessageArgs_WithCorrectPoolReturnData() (gas: 76624) -FeeQuoter_processMessageArgs:test_processMessageArgs_WithEVMExtraArgsV1() (gas: 28300) -FeeQuoter_processMessageArgs:test_processMessageArgs_WithEmptyEVMExtraArgs() (gas: 26158) -FeeQuoter_processMessageArgs:test_processMessageArgs_WithLinkTokenAmount() (gas: 19641) -FeeQuoter_supportsInterface:test_SupportsInterface() (gas: 13264) -FeeQuoter_updatePrices:test_OnlyGasPrice() (gas: 23912) -FeeQuoter_updatePrices:test_OnlyTokenPrice() (gas: 28761) -FeeQuoter_updatePrices:test_UpdatableByAuthorizedCaller() (gas: 74821) -FeeQuoter_updatePrices:test_UpdateMultiplePrices() (gas: 146024) -FeeQuoter_updateTokenPriceFeeds:test_FeedNotUpdated() (gas: 52517) -FeeQuoter_updateTokenPriceFeeds:test_FeedUnset() (gas: 66506) -FeeQuoter_updateTokenPriceFeeds:test_MultipleFeedUpdate() (gas: 93647) -FeeQuoter_updateTokenPriceFeeds:test_SingleFeedUpdate() (gas: 53215) -FeeQuoter_updateTokenPriceFeeds:test_ZeroFeeds() (gas: 12471) -FeeQuoter_validateDestFamilyAddress:test_ValidEVMAddress() (gas: 6789) -FeeQuoter_validateDestFamilyAddress:test_ValidNonEVMAddress() (gas: 6514) -HybridLockReleaseUSDCTokenPool_TransferLiquidity:test_transferLiquidity() (gas: 167013) -HybridLockReleaseUSDCTokenPool_lockOrBurn:test_PrimaryMechanism() (gas: 130356) -HybridLockReleaseUSDCTokenPool_lockOrBurn:test_onLockReleaseMechanism() (gas: 140104) -HybridLockReleaseUSDCTokenPool_lockOrBurn:test_onLockReleaseMechanism_thenSwitchToPrimary() (gas: 202967) -HybridLockReleaseUSDCTokenPool_releaseOrMint:test_OnLockReleaseMechanism() (gas: 206218) -HybridLockReleaseUSDCTokenPool_releaseOrMint:test_incomingMessageWithPrimaryMechanism() (gas: 260387) -LockReleaseTokenPool_canAcceptLiquidity:test_CanAcceptLiquidity() (gas: 3222607) -LockReleaseTokenPool_lockOrBurn:test_LockOrBurnWithAllowList() (gas: 72828) -LockReleaseTokenPool_releaseOrMint:test_ReleaseOrMint() (gas: 217898) -LockReleaseTokenPool_setRebalancer:test_SetRebalancer() (gas: 18183) -LockReleaseTokenPool_supportsInterface:test_SupportsInterface() (gas: 10251) -LockReleaseTokenPool_transferLiquidity:test_transferLiquidity() (gas: 83263) +BurnFromMintTokenPool_lockOrBurn:test_ChainNotAllowed_Revert() (gas: 28962) +BurnFromMintTokenPool_lockOrBurn:test_PoolBurnRevertNotHealthy_Revert() (gas: 55341) +BurnFromMintTokenPool_lockOrBurn:test_PoolBurn_Success() (gas: 244152) +BurnFromMintTokenPool_lockOrBurn:test_setup_Success() (gas: 24187) +BurnMintTokenPool_lockOrBurn:test_ChainNotAllowed_Revert() (gas: 27681) +BurnMintTokenPool_lockOrBurn:test_PoolBurnRevertNotHealthy_Revert() (gas: 55341) +BurnMintTokenPool_lockOrBurn:test_PoolBurn_Success() (gas: 242036) +BurnMintTokenPool_lockOrBurn:test_Setup_Success() (gas: 17873) +BurnMintTokenPool_releaseOrMint:test_ChainNotAllowed_Revert() (gas: 28903) +BurnMintTokenPool_releaseOrMint:test_PoolMintNotHealthy_Revert() (gas: 56355) +BurnMintTokenPool_releaseOrMint:test_PoolMint_Success() (gas: 112556) +BurnMintWithLockReleaseFlagTokenPool_lockOrBurn:test_LockOrBurn_CorrectReturnData_Success() (gas: 242665) +BurnWithFromMintTokenPool_lockOrBurn:test_ChainNotAllowed_Revert() (gas: 28962) +BurnWithFromMintTokenPool_lockOrBurn:test_PoolBurnRevertNotHealthy_Revert() (gas: 55341) +BurnWithFromMintTokenPool_lockOrBurn:test_PoolBurn_Success() (gas: 244179) +BurnWithFromMintTokenPool_lockOrBurn:test_Setup_Success() (gas: 24211) +CCIPClientExample_sanity:test_ImmutableExamples_Success() (gas: 2076527) +CCIPHome__validateConfig:test__validateConfigLessTransmittersThanSigners_Success() (gas: 332619) +CCIPHome__validateConfig:test__validateConfigSmallerFChain_Success() (gas: 458568) +CCIPHome__validateConfig:test__validateConfig_ABIEncodedAddress_OfframpAddressCannotBeZero_Reverts() (gas: 289191) +CCIPHome__validateConfig:test__validateConfig_ABIEncodedAddress_RMNHomeAddressCannotBeZero_Reverts() (gas: 289486) +CCIPHome__validateConfig:test__validateConfig_ChainSelectorNotFound_Reverts() (gas: 292216) +CCIPHome__validateConfig:test__validateConfig_ChainSelectorNotSet_Reverts() (gas: 288824) +CCIPHome__validateConfig:test__validateConfig_FChainTooHigh_Reverts() (gas: 336363) +CCIPHome__validateConfig:test__validateConfig_FMustBePositive_Reverts() (gas: 290590) +CCIPHome__validateConfig:test__validateConfig_FTooHigh_Reverts() (gas: 290055) +CCIPHome__validateConfig:test__validateConfig_NotEnoughTransmittersEmptyAddresses_Reverts() (gas: 308646) +CCIPHome__validateConfig:test__validateConfig_NotEnoughTransmitters_Reverts() (gas: 1191231) +CCIPHome__validateConfig:test__validateConfig_OfframpAddressCannotBeZero_Reverts() (gas: 288918) +CCIPHome__validateConfig:test__validateConfig_RMNHomeAddressCannotBeZero_Reverts() (gas: 289112) +CCIPHome__validateConfig:test__validateConfig_Success() (gas: 299797) +CCIPHome__validateConfig:test__validateConfig_TooManySigners_Reverts() (gas: 773105) +CCIPHome__validateConfig:test__validateConfig_ZeroP2PId_Reverts() (gas: 293455) +CCIPHome__validateConfig:test__validateConfig_ZeroSignerKey_Reverts() (gas: 293503) +CCIPHome_applyChainConfigUpdates:test__applyChainConfigUpdates_FChainNotPositive_Reverts() (gas: 187738) +CCIPHome_applyChainConfigUpdates:test_applyChainConfigUpdates_addChainConfigs_Success() (gas: 349623) +CCIPHome_applyChainConfigUpdates:test_applyChainConfigUpdates_nodeNotInRegistry_Reverts() (gas: 18065) +CCIPHome_applyChainConfigUpdates:test_applyChainConfigUpdates_removeChainConfigs_Success() (gas: 272742) +CCIPHome_applyChainConfigUpdates:test_applyChainConfigUpdates_selectorNotFound_Reverts() (gas: 14952) +CCIPHome_applyChainConfigUpdates:test_getPaginatedCCIPHomes_Success() (gas: 372561) +CCIPHome_beforeCapabilityConfigSet:test_beforeCapabilityConfigSet_DONIdMismatch_reverts() (gas: 38098) +CCIPHome_beforeCapabilityConfigSet:test_beforeCapabilityConfigSet_InnerCallReverts_reverts() (gas: 11827) +CCIPHome_beforeCapabilityConfigSet:test_beforeCapabilityConfigSet_InvalidSelector_reverts() (gas: 11015) +CCIPHome_beforeCapabilityConfigSet:test_beforeCapabilityConfigSet_OnlyCapabilitiesRegistryCanCall_reverts() (gas: 37072) +CCIPHome_beforeCapabilityConfigSet:test_beforeCapabilityConfigSet_success() (gas: 1455716) +CCIPHome_constructor:test_constructor_CapabilitiesRegistryAddressZero_reverts() (gas: 63767) +CCIPHome_constructor:test_constructor_success() (gas: 3455841) +CCIPHome_getAllConfigs:test_getAllConfigs_success() (gas: 2773000) +CCIPHome_getCapabilityConfiguration:test_getCapabilityConfiguration_success() (gas: 9138) +CCIPHome_getConfigDigests:test_getConfigDigests_success() (gas: 2547397) +CCIPHome_promoteCandidateAndRevokeActive:test_promoteCandidateAndRevokeActive_CanOnlySelfCall_reverts() (gas: 9087) +CCIPHome_promoteCandidateAndRevokeActive:test_promoteCandidateAndRevokeActive_ConfigDigestMismatch_reverts() (gas: 23005) +CCIPHome_promoteCandidateAndRevokeActive:test_promoteCandidateAndRevokeActive_NoOpStateTransitionNotAllowed_reverts() (gas: 8817) +CCIPHome_promoteCandidateAndRevokeActive:test_promoteCandidateAndRevokeActive_multiplePlugins_success() (gas: 5113570) +CCIPHome_revokeCandidate:test_revokeCandidate_CanOnlySelfCall_reverts() (gas: 9068) +CCIPHome_revokeCandidate:test_revokeCandidate_ConfigDigestMismatch_reverts() (gas: 19105) +CCIPHome_revokeCandidate:test_revokeCandidate_RevokingZeroDigestNotAllowed_reverts() (gas: 8817) +CCIPHome_revokeCandidate:test_revokeCandidate_success() (gas: 30674) +CCIPHome_setCandidate:test_setCandidate_CanOnlySelfCall_reverts() (gas: 29383) +CCIPHome_setCandidate:test_setCandidate_ConfigDigestMismatch_reverts() (gas: 1395154) +CCIPHome_setCandidate:test_setCandidate_success() (gas: 1365439) +CCIPHome_supportsInterface:test_supportsInterface_success() (gas: 9885) +DefensiveExampleTest:test_HappyPath_Success() (gas: 200473) +DefensiveExampleTest:test_Recovery() (gas: 424876) +E2E:test_E2E_3MessagesMMultiOffRampSuccess_gas() (gas: 1519829) +EtherSenderReceiverTest_ccipReceive:test_ccipReceive_fallbackToWethTransfer() (gas: 96980) +EtherSenderReceiverTest_ccipReceive:test_ccipReceive_happyPath() (gas: 49812) +EtherSenderReceiverTest_ccipReceive:test_ccipReceive_wrongToken() (gas: 17479) +EtherSenderReceiverTest_ccipReceive:test_ccipReceive_wrongTokenAmount() (gas: 15753) +EtherSenderReceiverTest_ccipSend:test_ccipSend_reverts_insufficientFee_feeToken() (gas: 99953) +EtherSenderReceiverTest_ccipSend:test_ccipSend_reverts_insufficientFee_native() (gas: 76182) +EtherSenderReceiverTest_ccipSend:test_ccipSend_reverts_insufficientFee_weth() (gas: 99974) +EtherSenderReceiverTest_ccipSend:test_ccipSend_success_feeToken() (gas: 145007) +EtherSenderReceiverTest_ccipSend:test_ccipSend_success_native() (gas: 80439) +EtherSenderReceiverTest_ccipSend:test_ccipSend_success_nativeExcess() (gas: 80604) +EtherSenderReceiverTest_ccipSend:test_ccipSend_success_weth() (gas: 96107) +EtherSenderReceiverTest_constructor:test_constructor() (gas: 17575) +EtherSenderReceiverTest_getFee:test_getFee() (gas: 27456) +EtherSenderReceiverTest_validateFeeToken:test_validateFeeToken_reverts_feeToken_tokenAmountNotEqualToMsgValue() (gas: 20355) +EtherSenderReceiverTest_validateFeeToken:test_validateFeeToken_valid_feeToken() (gas: 16682) +EtherSenderReceiverTest_validateFeeToken:test_validateFeeToken_valid_native() (gas: 16615) +EtherSenderReceiverTest_validatedMessage:test_validatedMessage_dataOverwrittenToMsgSender() (gas: 25456) +EtherSenderReceiverTest_validatedMessage:test_validatedMessage_emptyDataOverwrittenToMsgSender() (gas: 25373) +EtherSenderReceiverTest_validatedMessage:test_validatedMessage_invalidTokenAmounts() (gas: 17969) +EtherSenderReceiverTest_validatedMessage:test_validatedMessage_tokenOverwrittenToWeth() (gas: 25328) +EtherSenderReceiverTest_validatedMessage:test_validatedMessage_validMessage_extraArgs() (gas: 26348) +FactoryBurnMintERC20_approve:test_Approve_Success() (gas: 55819) +FactoryBurnMintERC20_approve:test_InvalidAddress_Reverts() (gas: 10703) +FactoryBurnMintERC20_burn:test_BasicBurn_Success() (gas: 172464) +FactoryBurnMintERC20_burn:test_BurnFromZeroAddress_Reverts() (gas: 47338) +FactoryBurnMintERC20_burn:test_ExceedsBalance_Reverts() (gas: 22005) +FactoryBurnMintERC20_burn:test_SenderNotBurner_Reverts() (gas: 13520) +FactoryBurnMintERC20_burnFrom:test_BurnFrom_Success() (gas: 58274) +FactoryBurnMintERC20_burnFrom:test_ExceedsBalance_Reverts() (gas: 36191) +FactoryBurnMintERC20_burnFrom:test_InsufficientAllowance_Reverts() (gas: 22113) +FactoryBurnMintERC20_burnFrom:test_SenderNotBurner_Reverts() (gas: 13487) +FactoryBurnMintERC20_burnFromAlias:test_BurnFrom_Success() (gas: 58248) +FactoryBurnMintERC20_burnFromAlias:test_ExceedsBalance_Reverts() (gas: 36155) +FactoryBurnMintERC20_burnFromAlias:test_InsufficientAllowance_Reverts() (gas: 22068) +FactoryBurnMintERC20_burnFromAlias:test_SenderNotBurner_Reverts() (gas: 13442) +FactoryBurnMintERC20_constructor:test_Constructor_Success() (gas: 1450638) +FactoryBurnMintERC20_decreaseApproval:test_DecreaseApproval_Success() (gas: 31419) +FactoryBurnMintERC20_getCCIPAdmin:test_getCCIPAdmin_Success() (gas: 12717) +FactoryBurnMintERC20_getCCIPAdmin:test_setCCIPAdmin_Success() (gas: 23874) +FactoryBurnMintERC20_grantMintAndBurnRoles:test_GrantMintAndBurnRoles_Success() (gas: 121194) +FactoryBurnMintERC20_grantRole:test_GrantBurnAccess_Success() (gas: 53403) +FactoryBurnMintERC20_grantRole:test_GrantMany_Success() (gas: 961486) +FactoryBurnMintERC20_grantRole:test_GrantMintAccess_Success() (gas: 94165) +FactoryBurnMintERC20_increaseApproval:test_IncreaseApproval_Success() (gas: 44398) +FactoryBurnMintERC20_mint:test_BasicMint_Success() (gas: 149804) +FactoryBurnMintERC20_mint:test_MaxSupplyExceeded_Reverts() (gas: 50679) +FactoryBurnMintERC20_mint:test_SenderNotMinter_Reverts() (gas: 11405) +FactoryBurnMintERC20_supportsInterface:test_SupportsInterface_Success() (gas: 11538) +FactoryBurnMintERC20_transfer:test_InvalidAddress_Reverts() (gas: 10701) +FactoryBurnMintERC20_transfer:test_Transfer_Success() (gas: 42482) +FeeQuoter_applyDestChainConfigUpdates:test_InvalidChainFamilySelector_Revert() (gas: 16824) +FeeQuoter_applyDestChainConfigUpdates:test_InvalidDestChainConfigDestChainSelectorEqZero_Revert() (gas: 16737) +FeeQuoter_applyDestChainConfigUpdates:test_applyDestChainConfigUpdatesDefaultTxGasLimitEqZero_Revert() (gas: 16791) +FeeQuoter_applyDestChainConfigUpdates:test_applyDestChainConfigUpdatesDefaultTxGasLimitGtMaxPerMessageGasLimit_Revert() (gas: 41195) +FeeQuoter_applyDestChainConfigUpdates:test_applyDestChainConfigUpdatesZeroInput_Success() (gas: 12541) +FeeQuoter_applyDestChainConfigUpdates:test_applyDestChainConfigUpdates_Success() (gas: 140643) +FeeQuoter_applyFeeTokensUpdates:test_ApplyFeeTokensUpdates_Success() (gas: 162508) +FeeQuoter_applyFeeTokensUpdates:test_OnlyCallableByOwner_Revert() (gas: 12241) +FeeQuoter_applyPremiumMultiplierWeiPerEthUpdates:test_OnlyCallableByOwnerOrAdmin_Revert() (gas: 11564) +FeeQuoter_applyPremiumMultiplierWeiPerEthUpdates:test_applyPremiumMultiplierWeiPerEthUpdatesMultipleTokens_Success() (gas: 54904) +FeeQuoter_applyPremiumMultiplierWeiPerEthUpdates:test_applyPremiumMultiplierWeiPerEthUpdatesSingleToken_Success() (gas: 45323) +FeeQuoter_applyPremiumMultiplierWeiPerEthUpdates:test_applyPremiumMultiplierWeiPerEthUpdatesZeroInput() (gas: 12456) +FeeQuoter_applyTokenTransferFeeConfigUpdates:test_ApplyTokenTransferFeeConfig_Success() (gas: 88930) +FeeQuoter_applyTokenTransferFeeConfigUpdates:test_ApplyTokenTransferFeeZeroInput() (gas: 13324) +FeeQuoter_applyTokenTransferFeeConfigUpdates:test_InvalidDestBytesOverhead_Revert() (gas: 17413) +FeeQuoter_applyTokenTransferFeeConfigUpdates:test_OnlyCallableByOwnerOrAdmin_Revert() (gas: 12327) +FeeQuoter_constructor:test_InvalidLinkTokenEqZeroAddress_Revert() (gas: 106573) +FeeQuoter_constructor:test_InvalidMaxFeeJuelsPerMsg_Revert() (gas: 110923) +FeeQuoter_constructor:test_InvalidStalenessThreshold_Revert() (gas: 110998) +FeeQuoter_constructor:test_Setup_Success() (gas: 4974931) +FeeQuoter_convertTokenAmount:test_ConvertTokenAmount_Success() (gas: 68416) +FeeQuoter_convertTokenAmount:test_LinkTokenNotSupported_Revert() (gas: 29300) +FeeQuoter_getDataAvailabilityCost:test_EmptyMessageCalculatesDataAvailabilityCost_Success() (gas: 96323) +FeeQuoter_getDataAvailabilityCost:test_SimpleMessageCalculatesDataAvailabilityCostUnsupportedDestChainSelector_Success() (gas: 14835) +FeeQuoter_getDataAvailabilityCost:test_SimpleMessageCalculatesDataAvailabilityCost_Success() (gas: 20944) +FeeQuoter_getTokenAndGasPrices:test_GetFeeTokenAndGasPrices_Success() (gas: 73071) +FeeQuoter_getTokenAndGasPrices:test_StaleGasPrice_Revert() (gas: 26476) +FeeQuoter_getTokenAndGasPrices:test_StalenessCheckDisabled_Success() (gas: 112021) +FeeQuoter_getTokenAndGasPrices:test_UnsupportedChain_Revert() (gas: 16184) +FeeQuoter_getTokenAndGasPrices:test_ZeroGasPrice_Success() (gas: 109131) +FeeQuoter_getTokenPrice:test_GetTokenPriceFromFeed_Success() (gas: 68015) +FeeQuoter_getTokenPrice:test_GetTokenPrice_LocalMoreRecent_Success() (gas: 33463) +FeeQuoter_getTokenPrices:test_GetTokenPrices_Success() (gas: 78498) +FeeQuoter_getTokenTransferCost:test_CustomTokenBpsFee_Success() (gas: 37372) +FeeQuoter_getTokenTransferCost:test_FeeTokenBpsFee_Success() (gas: 35151) +FeeQuoter_getTokenTransferCost:test_LargeTokenTransferChargesMaxFeeAndGas_Success() (gas: 28241) +FeeQuoter_getTokenTransferCost:test_MixedTokenTransferFee_Success() (gas: 96218) +FeeQuoter_getTokenTransferCost:test_NoTokenTransferChargesZeroFee_Success() (gas: 20702) +FeeQuoter_getTokenTransferCost:test_SmallTokenTransferChargesMinFeeAndGas_Success() (gas: 28049) +FeeQuoter_getTokenTransferCost:test_ZeroAmountTokenTransferChargesMinFeeAndGas_Success() (gas: 28094) +FeeQuoter_getTokenTransferCost:test_ZeroFeeConfigChargesMinFee_Success() (gas: 40887) +FeeQuoter_getTokenTransferCost:test_getTokenTransferCost_selfServeUsesDefaults_Success() (gas: 29801) +FeeQuoter_getValidatedFee:test_DestinationChainNotEnabled_Revert() (gas: 18465) +FeeQuoter_getValidatedFee:test_EmptyMessage_Success() (gas: 83208) +FeeQuoter_getValidatedFee:test_EnforceOutOfOrder_Revert() (gas: 53548) +FeeQuoter_getValidatedFee:test_HighGasMessage_Success() (gas: 239604) +FeeQuoter_getValidatedFee:test_InvalidEVMAddress_Revert() (gas: 22668) +FeeQuoter_getValidatedFee:test_MessageGasLimitTooHigh_Revert() (gas: 29966) +FeeQuoter_getValidatedFee:test_MessageTooLarge_Revert() (gas: 100417) +FeeQuoter_getValidatedFee:test_MessageWithDataAndTokenTransfer_Success() (gas: 143112) +FeeQuoter_getValidatedFee:test_NotAFeeToken_Revert() (gas: 21280) +FeeQuoter_getValidatedFee:test_SingleTokenMessage_Success() (gas: 114464) +FeeQuoter_getValidatedFee:test_TooManyTokens_Revert() (gas: 23495) +FeeQuoter_getValidatedFee:test_ZeroDataAvailabilityMultiplier_Success() (gas: 63843) +FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedErc20Above18Decimals_Success() (gas: 1960306) +FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedErc20Below18Decimals_Success() (gas: 1960264) +FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedFeedAt0Decimals_Success() (gas: 1940383) +FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedFeedAt18Decimals_Success() (gas: 1960038) +FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedFlippedDecimals_Success() (gas: 1960242) +FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedMaxInt224Value_Success() (gas: 1960054) +FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedOverStalenessPeriod_Success() (gas: 65210) +FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeed_Success() (gas: 65090) +FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPrice_Success() (gas: 58872) +FeeQuoter_getValidatedTokenPrice:test_OverflowFeedPrice_Revert() (gas: 1959680) +FeeQuoter_getValidatedTokenPrice:test_StaleFeeToken_Success() (gas: 61821) +FeeQuoter_getValidatedTokenPrice:test_TokenNotSupportedFeed_Revert() (gas: 116926) +FeeQuoter_getValidatedTokenPrice:test_TokenNotSupported_Revert() (gas: 14160) +FeeQuoter_getValidatedTokenPrice:test_UnderflowFeedPrice_Revert() (gas: 1958357) +FeeQuoter_onReport:test_OnReport_StaleUpdate_SkipPriceUpdate_Success() (gas: 43936) +FeeQuoter_onReport:test_onReport_InvalidForwarder_Reverts() (gas: 23657) +FeeQuoter_onReport:test_onReport_Success() (gas: 80700) +FeeQuoter_onReport:test_onReport_TokenNotSupported_Revert() (gas: 23024) +FeeQuoter_onReport:test_onReport_UnsupportedToken_Reverts() (gas: 27202) +FeeQuoter_parseEVMExtraArgsFromBytes:test_EVMExtraArgsDefault_Success() (gas: 17448) +FeeQuoter_parseEVMExtraArgsFromBytes:test_EVMExtraArgsEnforceOutOfOrder_Revert() (gas: 21620) +FeeQuoter_parseEVMExtraArgsFromBytes:test_EVMExtraArgsGasLimitTooHigh_Revert() (gas: 18680) +FeeQuoter_parseEVMExtraArgsFromBytes:test_EVMExtraArgsInvalidExtraArgsTag_Revert() (gas: 18220) +FeeQuoter_parseEVMExtraArgsFromBytes:test_EVMExtraArgsV1_Success() (gas: 18534) +FeeQuoter_parseEVMExtraArgsFromBytes:test_EVMExtraArgsV2_Success() (gas: 18657) +FeeQuoter_processMessageArgs:test_applyTokensTransferFeeConfigUpdates_InvalidFeeRange_Revert() (gas: 21454) +FeeQuoter_processMessageArgs:test_processMessageArgs_InvalidEVMAddressDestToken_Revert() (gas: 44795) +FeeQuoter_processMessageArgs:test_processMessageArgs_InvalidExtraArgs_Revert() (gas: 19986) +FeeQuoter_processMessageArgs:test_processMessageArgs_MalformedEVMExtraArgs_Revert() (gas: 20383) +FeeQuoter_processMessageArgs:test_processMessageArgs_MessageFeeTooHigh_Revert() (gas: 17954) +FeeQuoter_processMessageArgs:test_processMessageArgs_SourceTokenDataTooLarge_Revert() (gas: 123115) +FeeQuoter_processMessageArgs:test_processMessageArgs_TokenAmountArraysMismatching_Revert() (gas: 42124) +FeeQuoter_processMessageArgs:test_processMessageArgs_WitEVMExtraArgsV2_Success() (gas: 28658) +FeeQuoter_processMessageArgs:test_processMessageArgs_WithConvertedTokenAmount_Success() (gas: 29999) +FeeQuoter_processMessageArgs:test_processMessageArgs_WithCorrectPoolReturnData_Success() (gas: 76173) +FeeQuoter_processMessageArgs:test_processMessageArgs_WithEVMExtraArgsV1_Success() (gas: 28256) +FeeQuoter_processMessageArgs:test_processMessageArgs_WithEmptyEVMExtraArgs_Success() (gas: 26115) +FeeQuoter_processMessageArgs:test_processMessageArgs_WithLinkTokenAmount_Success() (gas: 19573) +FeeQuoter_updatePrices:test_OnlyCallableByUpdater_Revert() (gas: 12176) +FeeQuoter_updatePrices:test_OnlyGasPrice_Success() (gas: 23917) +FeeQuoter_updatePrices:test_OnlyTokenPrice_Success() (gas: 28604) +FeeQuoter_updatePrices:test_UpdatableByAuthorizedCaller_Success() (gas: 74711) +FeeQuoter_updatePrices:test_UpdateMultiplePrices_Success() (gas: 145804) +FeeQuoter_updateTokenPriceFeeds:test_FeedNotUpdated() (gas: 52421) +FeeQuoter_updateTokenPriceFeeds:test_FeedUnset_Success() (gas: 66335) +FeeQuoter_updateTokenPriceFeeds:test_FeedUpdatedByNonOwner_Revert() (gas: 20124) +FeeQuoter_updateTokenPriceFeeds:test_MultipleFeedUpdate_Success() (gas: 93475) +FeeQuoter_updateTokenPriceFeeds:test_SingleFeedUpdate_Success() (gas: 53098) +FeeQuoter_updateTokenPriceFeeds:test_ZeroFeeds_Success() (gas: 12431) +FeeQuoter_validateDestFamilyAddress:test_InvalidEVMAddressEncodePacked_Revert() (gas: 10688) +FeeQuoter_validateDestFamilyAddress:test_InvalidEVMAddressPrecompiles_Revert() (gas: 4035395) +FeeQuoter_validateDestFamilyAddress:test_InvalidEVMAddress_Revert() (gas: 10884) +FeeQuoter_validateDestFamilyAddress:test_ValidEVMAddress_Success() (gas: 6819) +FeeQuoter_validateDestFamilyAddress:test_ValidNonEVMAddress_Success() (gas: 6545) +HybridLockReleaseUSDCTokenPool_TransferLiquidity:test_cannotTransferLiquidityDuringPendingMigration_Revert() (gas: 176969) +HybridLockReleaseUSDCTokenPool_TransferLiquidity:test_transferLiquidity_Success() (gas: 167002) +HybridLockReleaseUSDCTokenPool_lockOrBurn:test_PrimaryMechanism_Success() (gas: 135921) +HybridLockReleaseUSDCTokenPool_lockOrBurn:test_WhileMigrationPause_Revert() (gas: 109740) +HybridLockReleaseUSDCTokenPool_lockOrBurn:test_onLockReleaseMechanism_Success() (gas: 147013) +HybridLockReleaseUSDCTokenPool_lockOrBurn:test_onLockReleaseMechanism_thenswitchToPrimary_Success() (gas: 209245) +HybridLockReleaseUSDCTokenPool_releaseOrMint:test_OnLockReleaseMechanism_Success() (gas: 216909) +HybridLockReleaseUSDCTokenPool_releaseOrMint:test_WhileMigrationPause_Revert() (gas: 113472) +HybridLockReleaseUSDCTokenPool_releaseOrMint:test_incomingMessageWithPrimaryMechanism() (gas: 268981) +LockReleaseTokenPool_canAcceptLiquidity:test_CanAcceptLiquidity_Success() (gas: 2788658) +LockReleaseTokenPool_lockOrBurn:test_LockOrBurnWithAllowList_Revert() (gas: 30088) +LockReleaseTokenPool_lockOrBurn:test_LockOrBurnWithAllowList_Success() (gas: 80282) +LockReleaseTokenPool_lockOrBurn:test_PoolBurnRevertNotHealthy_Revert() (gas: 59690) +LockReleaseTokenPool_provideLiquidity:test_LiquidityNotAccepted_Revert() (gas: 2785053) +LockReleaseTokenPool_provideLiquidity:test_Unauthorized_Revert() (gas: 11489) +LockReleaseTokenPool_releaseOrMint:test_ChainNotAllowed_Revert() (gas: 72956) +LockReleaseTokenPool_releaseOrMint:test_PoolMintNotHealthy_Revert() (gas: 56476) +LockReleaseTokenPool_releaseOrMint:test_ReleaseOrMint_Success() (gas: 225734) +LockReleaseTokenPool_setRebalancer:test_SetRebalancer_Revert() (gas: 10981) +LockReleaseTokenPool_setRebalancer:test_SetRebalancer_Success() (gas: 18160) +LockReleaseTokenPool_supportsInterface:test_SupportsInterface_Success() (gas: 10250) +LockReleaseTokenPool_transferLiquidity:test_transferLiquidity_Success() (gas: 83267) +LockReleaseTokenPool_transferLiquidity:test_transferLiquidity_transferTooMuch_Revert() (gas: 56013) +LockReleaseTokenPool_withdrawalLiquidity:test_InsufficientLiquidity_Revert() (gas: 60182) +LockReleaseTokenPool_withdrawalLiquidity:test_Unauthorized_Revert() (gas: 11486) MerkleMultiProofTest:test_CVE_2023_34459() (gas: 5456) -MerkleMultiProofTest:test_MerkleRoot256() (gas: 396915) -MerkleMultiProofTest:test_MerkleRootSingleLeaf() (gas: 3684) +MerkleMultiProofTest:test_EmptyLeaf_Revert() (gas: 3563) +MerkleMultiProofTest:test_MerkleRoot256() (gas: 394891) +MerkleMultiProofTest:test_MerkleRootSingleLeaf_Success() (gas: 3661) MerkleMultiProofTest:test_SpecSync_gas() (gas: 34152) -MockRouterTest:test_ccipSendWithEVMExtraArgsV1() (gas: 110081) -MockRouterTest:test_ccipSendWithEVMExtraArgsV2() (gas: 132594) -MockRouterTest:test_ccipSendWithLinkFeeTokenAndValidMsgValue() (gas: 126679) -MockRouterTest:test_ccipSendWithSufficientNativeFeeTokens() (gas: 44038) -MultiAggregateRateLimiter_applyRateLimiterConfigUpdates:test_MultipleConfigs() (gas: 317373) -MultiAggregateRateLimiter_applyRateLimiterConfigUpdates:test_MultipleConfigsBothLanes() (gas: 134278) -MultiAggregateRateLimiter_applyRateLimiterConfigUpdates:test_SingleConfig() (gas: 76755) -MultiAggregateRateLimiter_applyRateLimiterConfigUpdates:test_SingleConfigOutbound() (gas: 76797) -MultiAggregateRateLimiter_applyRateLimiterConfigUpdates:test_UpdateExistingConfig() (gas: 54084) -MultiAggregateRateLimiter_applyRateLimiterConfigUpdates:test_UpdateExistingConfigWithNoDifference() (gas: 38924) -MultiAggregateRateLimiter_applyRateLimiterConfigUpdates:test_ZeroConfigs() (gas: 12505) -MultiAggregateRateLimiter_constructor:test_Constructor() (gas: 2102740) -MultiAggregateRateLimiter_constructor:test_ConstructorNoAuthorizedCallers() (gas: 1986594) -MultiAggregateRateLimiter_getTokenBucket:test_GetTokenBucket() (gas: 30888) -MultiAggregateRateLimiter_getTokenBucket:test_Refill() (gas: 48378) -MultiAggregateRateLimiter_getTokenValue:test_GetTokenValue() (gas: 17616) -MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithDifferentTokensOnDifferentChains() (gas: 211462) -MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithDisabledRateLimitToken() (gas: 58832) -MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithNoTokens() (gas: 17918) -MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithRateLimitDisabled() (gas: 45460) -MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithRateLimitReset() (gas: 77765) -MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithTokens() (gas: 50967) -MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithTokensOnDifferentChains() (gas: 310077) -MultiAggregateRateLimiter_onOutboundMessage:test_RateLimitValueDifferentLanes() (gas: 51611) -MultiAggregateRateLimiter_onOutboundMessage:test_ValidateMessageWithNoTokens() (gas: 19379) -MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageWithDifferentTokensOnDifferentChains() (gas: 211014) -MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageWithDisabledRateLimitToken() (gas: 60544) -MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageWithRateLimitDisabled() (gas: 47112) -MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageWithRateLimitReset() (gas: 78506) -MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageWithTokens() (gas: 52677) -MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageWithTokensOnDifferentChains() (gas: 309835) -MultiAggregateRateLimiter_setFeeQuoter:test_Owner() (gas: 19146) -MultiAggregateRateLimiter_updateRateLimitTokens:test_UpdateRateLimitTokensMultipleChains() (gas: 281364) -MultiAggregateRateLimiter_updateRateLimitTokens:test_UpdateRateLimitTokensSingleChain() (gas: 255770) -MultiAggregateRateLimiter_updateRateLimitTokens:test_UpdateRateLimitTokens_AddsAndRemoves() (gas: 205543) -MultiAggregateRateLimiter_updateRateLimitTokens:test_UpdateRateLimitTokens_RemoveNonExistentToken() (gas: 29151) -MultiOCR3Base_setOCR3Configs:test_SetConfigIgnoreSigners() (gas: 512335) -MultiOCR3Base_setOCR3Configs:test_SetConfigWithSigners() (gas: 829238) -MultiOCR3Base_setOCR3Configs:test_SetConfigWithSignersMismatchingTransmitters() (gas: 680660) -MultiOCR3Base_setOCR3Configs:test_SetConfigWithoutSigners() (gas: 457485) -MultiOCR3Base_setOCR3Configs:test_SetConfigsZeroInput() (gas: 12437) -MultiOCR3Base_setOCR3Configs:test_SetMultipleConfigs() (gas: 2142785) -MultiOCR3Base_setOCR3Configs:test_UpdateConfigSigners() (gas: 861909) -MultiOCR3Base_setOCR3Configs:test_UpdateConfigTransmittersWithoutSigners() (gas: 476109) -MultiOCR3Base_transmit:test_TransmitSigners_gas() (gas: 33559) -MultiOCR3Base_transmit:test_TransmitWithoutSignatureVerification_gas() (gas: 18638) -NonceManager_applyPreviousRampsUpdates:test_MultipleRampsUpdates() (gas: 123595) -NonceManager_applyPreviousRampsUpdates:test_PreviousRampAlreadySet_overrideAllowed() (gas: 45935) -NonceManager_applyPreviousRampsUpdates:test_SingleRampUpdate() (gas: 66937) -NonceManager_applyPreviousRampsUpdates:test_ZeroInput() (gas: 12145) -NonceManager_getInboundNonce:test_getInboundNonce_NoPrevOffRampForChain() (gas: 178906) -NonceManager_getInboundNonce:test_getInboundNonce_Upgraded() (gas: 146095) -NonceManager_getInboundNonce:test_getInboundNonce_UpgradedNonceNewSenderStartsAtZero() (gas: 182376) -NonceManager_getInboundNonce:test_getInboundNonce_UpgradedNonceStartsAtV1Nonce() (gas: 245089) -NonceManager_getInboundNonce:test_getInboundNonce_UpgradedOffRampNonceSkipsIfMsgInFlight() (gas: 213735) -NonceManager_getInboundNonce:test_getInboundNonce_UpgradedSenderNoncesReadsPreviousRamp() (gas: 60418) -NonceManager_getIncrementedOutboundNonce:test_getIncrementedOutboundNonce() (gas: 37974) -NonceManager_getIncrementedOutboundNonce:test_incrementInboundNonce() (gas: 38746) -NonceManager_getIncrementedOutboundNonce:test_incrementInboundNonce_SkippedIncorrectNonce() (gas: 23739) -NonceManager_getIncrementedOutboundNonce:test_incrementNoncesInboundAndOutbound() (gas: 71886) -NonceManager_getOutboundNonce:test_getOutboundNonce_Upgrade() (gas: 105254) -NonceManager_getOutboundNonce:test_getOutboundNonce_UpgradeNonceNewSenderStartsAtZero() (gas: 166086) -NonceManager_getOutboundNonce:test_getOutboundNonce_UpgradeNonceStartsAtV1Nonce() (gas: 195806) -NonceManager_getOutboundNonce:test_getOutboundNonce_UpgradeSenderNoncesReadsPreviousRamp() (gas: 140101) -OffRamp_applySourceChainConfigUpdates:test_AddMultipleChains() (gas: 626140) -OffRamp_applySourceChainConfigUpdates:test_AddNewChain() (gas: 166441) -OffRamp_applySourceChainConfigUpdates:test_ApplyZeroUpdates() (gas: 16671) -OffRamp_applySourceChainConfigUpdates:test_ReplaceExistingChain() (gas: 180998) -OffRamp_applySourceChainConfigUpdates:test_ReplaceExistingChainOnRamp() (gas: 168513) -OffRamp_applySourceChainConfigUpdates:test_allowNonOnRampUpdateAfterLaneIsUsed() (gas: 284861) -OffRamp_batchExecute:test_MultipleReportsDifferentChains() (gas: 326028) -OffRamp_batchExecute:test_MultipleReportsDifferentChainsSkipCursedChain() (gas: 170852) -OffRamp_batchExecute:test_MultipleReportsSameChain() (gas: 269327) -OffRamp_batchExecute:test_MultipleReportsSkipDuplicate() (gas: 161811) -OffRamp_batchExecute:test_SingleReport() (gas: 149617) -OffRamp_batchExecute:test_Unhealthy() (gas: 533326) -OffRamp_commit:test_OnlyGasPriceUpdates() (gas: 112973) -OffRamp_commit:test_OnlyTokenPriceUpdates() (gas: 112927) -OffRamp_commit:test_PriceSequenceNumberCleared() (gas: 355397) -OffRamp_commit:test_ReportAndPriceUpdate() (gas: 164209) -OffRamp_commit:test_ReportOnlyRootSuccess_gas() (gas: 141051) -OffRamp_commit:test_RootWithRMNDisabled() (gas: 153873) -OffRamp_commit:test_StaleReportWithRoot() (gas: 232101) -OffRamp_commit:test_ValidPriceUpdateThenStaleReportWithRoot() (gas: 206722) -OffRamp_constructor:test_Constructor() (gas: 6269512) -OffRamp_execute:test_LargeBatch() (gas: 3373860) -OffRamp_execute:test_MultipleReports() (gas: 291458) -OffRamp_execute:test_MultipleReportsWithPartialValidationFailures() (gas: 364776) -OffRamp_execute:test_SingleReport() (gas: 168850) -OffRamp_executeSingleMessage:test_executeSingleMessage_NoTokens() (gas: 51610) -OffRamp_executeSingleMessage:test_executeSingleMessage_NonContract() (gas: 20514) -OffRamp_executeSingleMessage:test_executeSingleMessage_NonContractWithTokens() (gas: 230418) -OffRamp_executeSingleMessage:test_executeSingleMessage_WithMessageInterceptor() (gas: 87465) -OffRamp_executeSingleMessage:test_executeSingleMessage_WithTokens() (gas: 259935) -OffRamp_executeSingleReport:test_InvalidSourcePoolAddress() (gas: 455358) -OffRamp_executeSingleReport:test_ReceiverError() (gas: 180797) -OffRamp_executeSingleReport:test_SingleMessageNoTokens() (gas: 205270) -OffRamp_executeSingleReport:test_SingleMessageNoTokensOtherChain() (gas: 241357) -OffRamp_executeSingleReport:test_SingleMessageNoTokensUnordered() (gas: 185263) -OffRamp_executeSingleReport:test_SingleMessageToNonCCIPReceiver() (gas: 243920) -OffRamp_executeSingleReport:test_SingleMessagesNoTokensSuccess_gas() (gas: 134656) -OffRamp_executeSingleReport:test_SkippedIncorrectNonce() (gas: 58298) -OffRamp_executeSingleReport:test_SkippedIncorrectNonceStillExecutes() (gas: 392394) -OffRamp_executeSingleReport:test_TwoMessagesWithTokensAndGE() (gas: 562427) -OffRamp_executeSingleReport:test_TwoMessagesWithTokensSuccess_gas() (gas: 510808) -OffRamp_executeSingleReport:test_Unhealthy() (gas: 528949) -OffRamp_executeSingleReport:test_WithCurseOnAnotherSourceChain() (gas: 439299) -OffRamp_executeSingleReport:test__execute_SkippedAlreadyExecutedMessage() (gas: 158038) -OffRamp_executeSingleReport:test__execute_SkippedAlreadyExecutedMessageUnordered() (gas: 128422) -OffRamp_getExecutionState:test_FillExecutionState() (gas: 3955662) -OffRamp_getExecutionState:test_GetDifferentChainExecutionState() (gas: 121311) -OffRamp_getExecutionState:test_GetExecutionState() (gas: 90102) -OffRamp_manuallyExecute:test_manuallyExecute() (gas: 212368) -OffRamp_manuallyExecute:test_manuallyExecute_DoesNotRevertIfUntouched() (gas: 165742) -OffRamp_manuallyExecute:test_manuallyExecute_LowGasLimit() (gas: 479145) -OffRamp_manuallyExecute:test_manuallyExecute_ReentrancyFails() (gas: 2229662) -OffRamp_manuallyExecute:test_manuallyExecute_WithGasOverride() (gas: 212918) -OffRamp_manuallyExecute:test_manuallyExecute_WithMultiReportGasOverride() (gas: 732218) -OffRamp_manuallyExecute:test_manuallyExecute_WithPartialMessages() (gas: 337015) -OffRamp_releaseOrMintSingleToken:test__releaseOrMintSingleToken() (gas: 94629) -OffRamp_releaseOrMintTokens:test_releaseOrMintTokens() (gas: 161157) -OffRamp_releaseOrMintTokens:test_releaseOrMintTokens_WithGasOverride() (gas: 163023) -OffRamp_releaseOrMintTokens:test_releaseOrMintTokens_destDenominatedDecimals() (gas: 174276) -OffRamp_setDynamicConfig:test_SetDynamicConfig() (gas: 25442) -OffRamp_setDynamicConfig:test_SetDynamicConfigWithInterceptor() (gas: 47493) -OffRamp_trialExecute:test_trialExecute() (gas: 263635) -OffRamp_trialExecute:test_trialExecute_RateLimitError() (gas: 120721) -OffRamp_trialExecute:test_trialExecute_TokenHandlingErrorIsCaught() (gas: 132031) -OffRamp_trialExecute:test_trialExecute_TokenPoolIsNotAContract() (gas: 281380) -OnRampTokenPoolReentrancy:test_OnRampTokenPoolReentrancy() (gas: 244294) -OnRamp_applyAllowlistUpdates:test_applyAllowlistUpdates() (gas: 325979) -OnRamp_applyAllowlistUpdates:test_applyAllowlistUpdates_InvalidAllowListRequestDisabledAllowListWithAdds() (gas: 17190) -OnRamp_applyDestChainConfigUpdates:test_ApplyDestChainConfigUpdates() (gas: 65874) -OnRamp_constructor:test_Constructor() (gas: 2672129) -OnRamp_forwardFromRouter:test_ForwardFromRouter() (gas: 145362) -OnRamp_forwardFromRouter:test_ForwardFromRouterExtraArgsV2() (gas: 146196) -OnRamp_forwardFromRouter:test_ForwardFromRouterExtraArgsV2AllowOutOfOrderTrue() (gas: 115375) -OnRamp_forwardFromRouter:test_ForwardFromRouterSuccessCustomExtraArgs() (gas: 145760) -OnRamp_forwardFromRouter:test_ForwardFromRouterSuccessEmptyExtraArgs() (gas: 144036) -OnRamp_forwardFromRouter:test_ForwardFromRouterSuccessLegacyExtraArgs() (gas: 146001) -OnRamp_forwardFromRouter:test_ForwardFromRouter_ConfigurableSourceRouter() (gas: 140639) -OnRamp_forwardFromRouter:test_ShouldIncrementNonceOnlyOnOrdered() (gas: 186473) -OnRamp_forwardFromRouter:test_ShouldIncrementSeqNumAndNonce() (gas: 212828) -OnRamp_forwardFromRouter:test_ShouldStoreLinkFees() (gas: 147007) -OnRamp_forwardFromRouter:test_forwardFromRouter_WithInterception() (gas: 274726) -OnRamp_getFee:test_EmptyMessage() (gas: 99005) -OnRamp_getFee:test_GetFeeOfZeroForTokenMessage() (gas: 86961) -OnRamp_getFee:test_SingleTokenMessage() (gas: 114125) -OnRamp_getTokenPool:test_GetTokenPool() (gas: 35382) -OnRamp_setDynamicConfig:test_setDynamicConfig() (gas: 56650) -OnRamp_withdrawFeeTokens:test_WithdrawFeeTokens() (gas: 125835) -PingPong_ccipReceive:test_CcipReceive() (gas: 165845) -PingPong_setOutOfOrderExecution:test_OutOfOrderExecution() (gas: 20350) -PingPong_setPaused:test_Pausing() (gas: 17738) -PingPong_startPingPong:test_StartPingPong_With_OOO() (gas: 144996) -PingPong_startPingPong:test_StartPingPong_With_Sequenced_Ordered() (gas: 170649) -RMNHome_getConfigDigests:test_getConfigDigests() (gas: 1081176) -RMNHome_promoteCandidateAndRevokeActive:test_promoteCandidateAndRevokeActive() (gas: 1086556) -RMNHome_revokeCandidate:test_revokeCandidate() (gas: 28085) -RMNHome_setCandidate:test_setCandidate() (gas: 590250) -RMNHome_setDynamicConfig:test_setDynamicConfig() (gas: 105498) -RMNRemote_constructor:test_constructor() (gas: 8410) -RMNRemote_curse:test_curse() (gas: 149422) -RMNRemote_global_curses:test_isCursed_globalCurseSubject() (gas: 71707) -RMNRemote_isBlessed:test_isBlessed() (gas: 17588) -RMNRemote_setConfig:test_setConfig_addSigner_removeSigner() (gas: 994169) -RMNRemote_uncurse:test_uncurse() (gas: 40136) -RMNRemote_verify_withConfigSet:test_verify() (gas: 86470) -RateLimiter_constructor:test_Constructor() (gas: 19820) -RateLimiter_consume:test_ConsumeAggregateValue() (gas: 31633) -RateLimiter_consume:test_ConsumeTokens() (gas: 20369) -RateLimiter_consume:test_ConsumeUnlimited() (gas: 40923) -RateLimiter_consume:test_Refill() (gas: 37562) -RateLimiter_currentTokenBucketState:test_CurrentTokenBucketState() (gas: 39126) -RateLimiter_currentTokenBucketState:test_Refill() (gas: 47182) -RateLimiter_setTokenBucketConfig:test_SetRateLimiterConfig() (gas: 38645) -RegistryModuleOwnerCustom_registerAccessControlDefaultAdmin:test_registerAccessControlDefaultAdmin() (gas: 130641) -RegistryModuleOwnerCustom_registerAdminViaGetCCIPAdmin:test_registerAdminViaGetCCIPAdmin() (gas: 130136) -RegistryModuleOwnerCustom_registerAdminViaOwner:test_registerAdminViaOwner() (gas: 129941) -Router_applyRampUpdates:test_applyRampUpdates_OffRampUpdatesWithRouting() (gas: 10413055) -Router_applyRampUpdates:test_applyRampUpdates_OnRampDisable() (gas: 56445) -Router_ccipSend:test_CCIPSendLinkFeeNoTokenSuccess_gas() (gas: 124459) -Router_ccipSend:test_CCIPSendLinkFeeOneTokenSuccess_gas() (gas: 211890) -Router_ccipSend:test_InvalidMsgValue() (gas: 27856) -Router_ccipSend:test_NativeFeeToken() (gas: 184996) -Router_ccipSend:test_NativeFeeTokenInsufficientValue() (gas: 62458) -Router_ccipSend:test_NativeFeeTokenOverpay() (gas: 186413) -Router_ccipSend:test_NativeFeeTokenZeroValue() (gas: 54550) -Router_ccipSend:test_NonLinkFeeToken() (gas: 219583) -Router_ccipSend:test_WrappedNativeFeeToken() (gas: 187235) -Router_ccipSend:test_ccipSend_nativeFeeNoTokenSuccess_gas() (gas: 133616) -Router_ccipSend:test_ccipSend_nativeFeeOneTokenSuccess_gas() (gas: 221091) -Router_constructor:test_Constructor() (gas: 13148) +MockRouterTest:test_ccipSendWithInsufficientNativeTokens_Revert() (gas: 34081) +MockRouterTest:test_ccipSendWithInvalidMsgValue_Revert() (gas: 60886) +MockRouterTest:test_ccipSendWithLinkFeeTokenAndValidMsgValue_Success() (gas: 126575) +MockRouterTest:test_ccipSendWithLinkFeeTokenbutInsufficientAllowance_Revert() (gas: 63499) +MockRouterTest:test_ccipSendWithSufficientNativeFeeTokens_Success() (gas: 44056) +MultiAggregateRateLimiter_applyRateLimiterConfigUpdates:test_ConfigRateMoreThanCapacity_Revert() (gas: 16554) +MultiAggregateRateLimiter_applyRateLimiterConfigUpdates:test_ConfigRateZero_Revert() (gas: 16634) +MultiAggregateRateLimiter_applyRateLimiterConfigUpdates:test_DiableConfigCapacityNonZero_Revert() (gas: 16585) +MultiAggregateRateLimiter_applyRateLimiterConfigUpdates:test_DisableConfigRateNonZero_Revert() (gas: 16571) +MultiAggregateRateLimiter_applyRateLimiterConfigUpdates:test_MultipleConfigsBothLanes_Success() (gas: 133973) +MultiAggregateRateLimiter_applyRateLimiterConfigUpdates:test_MultipleConfigs_Success() (gas: 316663) +MultiAggregateRateLimiter_applyRateLimiterConfigUpdates:test_OnlyCallableByOwner_Revert() (gas: 17490) +MultiAggregateRateLimiter_applyRateLimiterConfigUpdates:test_SingleConfigOutbound_Success() (gas: 76620) +MultiAggregateRateLimiter_applyRateLimiterConfigUpdates:test_SingleConfig_Success() (gas: 76603) +MultiAggregateRateLimiter_applyRateLimiterConfigUpdates:test_UpdateExistingConfigWithNoDifference_Success() (gas: 38739) +MultiAggregateRateLimiter_applyRateLimiterConfigUpdates:test_UpdateExistingConfig_Success() (gas: 53937) +MultiAggregateRateLimiter_applyRateLimiterConfigUpdates:test_ZeroChainSelector_Revert() (gas: 17154) +MultiAggregateRateLimiter_applyRateLimiterConfigUpdates:test_ZeroConfigs_Success() (gas: 12481) +MultiAggregateRateLimiter_constructor:test_ConstructorNoAuthorizedCallers_Success() (gas: 1977286) +MultiAggregateRateLimiter_constructor:test_Constructor_Success() (gas: 2093583) +MultiAggregateRateLimiter_getTokenBucket:test_GetTokenBucket_Success() (gas: 30794) +MultiAggregateRateLimiter_getTokenBucket:test_Refill_Success() (gas: 48169) +MultiAggregateRateLimiter_getTokenBucket:test_TimeUnderflow_Revert() (gas: 15907) +MultiAggregateRateLimiter_getTokenValue:test_GetTokenValue_Success() (gas: 17602) +MultiAggregateRateLimiter_getTokenValue:test_NoTokenPrice_Reverts() (gas: 21630) +MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageFromUnauthorizedCaller_Revert() (gas: 14636) +MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithDifferentTokensOnDifferentChains_Success() (gas: 210571) +MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithDisabledRateLimitToken_Success() (gas: 58451) +MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithNoTokens_Success() (gas: 17791) +MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithRateLimitDisabled_Success() (gas: 45202) +MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithRateLimitExceeded_Revert() (gas: 46470) +MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithRateLimitReset_Success() (gas: 76911) +MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithTokensOnDifferentChains_Success() (gas: 308951) +MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithTokens_Success() (gas: 50636) +MultiAggregateRateLimiter_onOutboundMessage:test_RateLimitValueDifferentLanes_Success() (gas: 51287) +MultiAggregateRateLimiter_onOutboundMessage:test_ValidateMessageWithNoTokens_Success() (gas: 19375) +MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageFromUnauthorizedCaller_Revert() (gas: 15914) +MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageWithDifferentTokensOnDifferentChains_Success() (gas: 210291) +MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageWithDisabledRateLimitToken_Success() (gas: 60244) +MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageWithRateLimitDisabled_Success() (gas: 47025) +MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageWithRateLimitExceeded_Revert() (gas: 48261) +MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageWithRateLimitReset_Success() (gas: 77918) +MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageWithTokensOnDifferentChains_Success() (gas: 308897) +MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageWithTokens_Success() (gas: 52406) +MultiAggregateRateLimiter_setFeeQuoter:test_OnlyOwner_Revert() (gas: 10967) +MultiAggregateRateLimiter_setFeeQuoter:test_Owner_Success() (gas: 19190) +MultiAggregateRateLimiter_setFeeQuoter:test_ZeroAddress_Revert() (gas: 10642) +MultiAggregateRateLimiter_updateRateLimitTokens:test_NonOwner_Revert() (gas: 18518) +MultiAggregateRateLimiter_updateRateLimitTokens:test_UpdateRateLimitTokensMultipleChains_Success() (gas: 281000) +MultiAggregateRateLimiter_updateRateLimitTokens:test_UpdateRateLimitTokensSingleChain_Success() (gas: 255391) +MultiAggregateRateLimiter_updateRateLimitTokens:test_UpdateRateLimitTokens_AddsAndRemoves_Success() (gas: 205169) +MultiAggregateRateLimiter_updateRateLimitTokens:test_UpdateRateLimitTokens_RemoveNonExistentToken_Success() (gas: 29012) +MultiAggregateRateLimiter_updateRateLimitTokens:test_ZeroDestToken_AbiEncoded_Revert() (gas: 14001) +MultiAggregateRateLimiter_updateRateLimitTokens:test_ZeroDestToken_Revert() (gas: 18365) +MultiAggregateRateLimiter_updateRateLimitTokens:test_ZeroSourceToken_Revert() (gas: 18294) +MultiOCR3Base_setOCR3Configs:test_FMustBePositive_Revert() (gas: 59441) +MultiOCR3Base_setOCR3Configs:test_FTooHigh_Revert() (gas: 44190) +MultiOCR3Base_setOCR3Configs:test_MoreTransmittersThanSigners_Revert() (gas: 104844) +MultiOCR3Base_setOCR3Configs:test_NoTransmitters_Revert() (gas: 18908) +MultiOCR3Base_setOCR3Configs:test_RepeatSignerAddress_Revert() (gas: 283842) +MultiOCR3Base_setOCR3Configs:test_RepeatTransmitterAddress_Revert() (gas: 422489) +MultiOCR3Base_setOCR3Configs:test_SetConfigIgnoreSigners_Success() (gas: 512288) +MultiOCR3Base_setOCR3Configs:test_SetConfigWithSignersMismatchingTransmitters_Success() (gas: 680609) +MultiOCR3Base_setOCR3Configs:test_SetConfigWithSigners_Success() (gas: 829200) +MultiOCR3Base_setOCR3Configs:test_SetConfigWithoutSigners_Success() (gas: 457530) +MultiOCR3Base_setOCR3Configs:test_SetConfigsZeroInput_Success() (gas: 12436) +MultiOCR3Base_setOCR3Configs:test_SetMultipleConfigs_Success() (gas: 2142528) +MultiOCR3Base_setOCR3Configs:test_SignerCannotBeZeroAddress_Revert() (gas: 141905) +MultiOCR3Base_setOCR3Configs:test_StaticConfigChange_Revert() (gas: 807791) +MultiOCR3Base_setOCR3Configs:test_TooManySigners_Revert() (gas: 158911) +MultiOCR3Base_setOCR3Configs:test_TooManyTransmitters_Revert() (gas: 112357) +MultiOCR3Base_setOCR3Configs:test_TransmitterCannotBeZeroAddress_Revert() (gas: 254293) +MultiOCR3Base_setOCR3Configs:test_UpdateConfigSigners_Success() (gas: 861787) +MultiOCR3Base_setOCR3Configs:test_UpdateConfigTransmittersWithoutSigners_Success() (gas: 476186) +MultiOCR3Base_transmit:test_ConfigDigestMismatch_Revert() (gas: 42957) +MultiOCR3Base_transmit:test_ForkedChain_Revert() (gas: 48640) +MultiOCR3Base_transmit:test_InsufficientSignatures_Revert() (gas: 77185) +MultiOCR3Base_transmit:test_NonUniqueSignature_Revert() (gas: 65925) +MultiOCR3Base_transmit:test_SignatureOutOfRegistration_Revert() (gas: 33494) +MultiOCR3Base_transmit:test_TooManySignatures_Revert() (gas: 79889) +MultiOCR3Base_transmit:test_TransmitSigners_gas_Success() (gas: 33686) +MultiOCR3Base_transmit:test_TransmitWithExtraCalldataArgs_Revert() (gas: 47188) +MultiOCR3Base_transmit:test_TransmitWithLessCalldataArgs_Revert() (gas: 25711) +MultiOCR3Base_transmit:test_TransmitWithoutSignatureVerification_gas_Success() (gas: 18722) +MultiOCR3Base_transmit:test_UnAuthorizedTransmitter_Revert() (gas: 24299) +MultiOCR3Base_transmit:test_UnauthorizedSigner_Revert() (gas: 61298) +MultiOCR3Base_transmit:test_UnconfiguredPlugin_Revert() (gas: 39952) +MultiOCR3Base_transmit:test_ZeroSignatures_Revert() (gas: 33026) +NonceManager_NonceIncrementation:test_getIncrementedOutboundNonce_Success() (gas: 37956) +NonceManager_NonceIncrementation:test_incrementInboundNonce_Skip() (gas: 23706) +NonceManager_NonceIncrementation:test_incrementInboundNonce_Success() (gas: 38778) +NonceManager_NonceIncrementation:test_incrementNoncesInboundAndOutbound_Success() (gas: 71901) +NonceManager_OffRampUpgrade:test_NoPrevOffRampForChain_Success() (gas: 185739) +NonceManager_OffRampUpgrade:test_UpgradedNonceNewSenderStartsAtZero_Success() (gas: 189192) +NonceManager_OffRampUpgrade:test_UpgradedNonceStartsAtV1Nonce_Success() (gas: 252176) +NonceManager_OffRampUpgrade:test_UpgradedOffRampNonceSkipsIfMsgInFlight_Success() (gas: 220541) +NonceManager_OffRampUpgrade:test_UpgradedSenderNoncesReadsPreviousRamp_Success() (gas: 60497) +NonceManager_OffRampUpgrade:test_Upgraded_Success() (gas: 152904) +NonceManager_OnRampUpgrade:test_UpgradeNonceNewSenderStartsAtZero_Success() (gas: 166101) +NonceManager_OnRampUpgrade:test_UpgradeNonceStartsAtV1Nonce_Success() (gas: 195828) +NonceManager_OnRampUpgrade:test_UpgradeSenderNoncesReadsPreviousRamp_Success() (gas: 139098) +NonceManager_OnRampUpgrade:test_Upgrade_Success() (gas: 105168) +NonceManager_applyPreviousRampsUpdates:test_MultipleRampsUpdates_success() (gas: 123604) +NonceManager_applyPreviousRampsUpdates:test_PreviousRampAlreadySetOffRamp_Revert() (gas: 43403) +NonceManager_applyPreviousRampsUpdates:test_PreviousRampAlreadySetOnRampAndOffRamp_Revert() (gas: 64752) +NonceManager_applyPreviousRampsUpdates:test_PreviousRampAlreadySetOnRamp_Revert() (gas: 43245) +NonceManager_applyPreviousRampsUpdates:test_PreviousRampAlreadySet_overrideAllowed_success() (gas: 45941) +NonceManager_applyPreviousRampsUpdates:test_SingleRampUpdate_success() (gas: 66889) +NonceManager_applyPreviousRampsUpdates:test_ZeroInput_success() (gas: 12213) +NonceManager_typeAndVersion:test_typeAndVersion() (gas: 9705) +OffRamp_afterOC3ConfigSet:test_afterOCR3ConfigSet_SignatureVerificationDisabled_Revert() (gas: 5880050) +OffRamp_applySourceChainConfigUpdates:test_AddMultipleChains_Success() (gas: 626160) +OffRamp_applySourceChainConfigUpdates:test_AddNewChain_Success() (gas: 166527) +OffRamp_applySourceChainConfigUpdates:test_ApplyZeroUpdates_Success() (gas: 16719) +OffRamp_applySourceChainConfigUpdates:test_InvalidOnRampUpdate_Revert() (gas: 274713) +OffRamp_applySourceChainConfigUpdates:test_ReplaceExistingChainOnRamp_Success() (gas: 168604) +OffRamp_applySourceChainConfigUpdates:test_ReplaceExistingChain_Success() (gas: 181059) +OffRamp_applySourceChainConfigUpdates:test_RouterAddress_Revert() (gas: 13441) +OffRamp_applySourceChainConfigUpdates:test_ZeroOnRampAddress_Revert() (gas: 72724) +OffRamp_applySourceChainConfigUpdates:test_ZeroSourceChainSelector_Revert() (gas: 15519) +OffRamp_applySourceChainConfigUpdates:test_allowNonOnRampUpdateAfterLaneIsUsed_success() (gas: 285041) +OffRamp_batchExecute:test_MultipleReportsDifferentChainsSkipCursedChain_Success() (gas: 177349) +OffRamp_batchExecute:test_MultipleReportsDifferentChains_Success() (gas: 333175) +OffRamp_batchExecute:test_MultipleReportsSameChain_Success() (gas: 276441) +OffRamp_batchExecute:test_MultipleReportsSkipDuplicate_Success() (gas: 168334) +OffRamp_batchExecute:test_OutOfBoundsGasLimitsAccess_Revert() (gas: 187853) +OffRamp_batchExecute:test_SingleReport_Success() (gas: 156369) +OffRamp_batchExecute:test_Unhealthy_Success() (gas: 553439) +OffRamp_batchExecute:test_ZeroReports_Revert() (gas: 10600) +OffRamp_commit:test_CommitOnRampMismatch_Revert() (gas: 92744) +OffRamp_commit:test_FailedRMNVerification_Reverts() (gas: 63432) +OffRamp_commit:test_InvalidIntervalMinLargerThanMax_Revert() (gas: 69993) +OffRamp_commit:test_InvalidInterval_Revert() (gas: 66119) +OffRamp_commit:test_InvalidRootRevert() (gas: 65214) +OffRamp_commit:test_NoConfigWithOtherConfigPresent_Revert() (gas: 6641148) +OffRamp_commit:test_NoConfig_Revert() (gas: 6224566) +OffRamp_commit:test_OnlyGasPriceUpdates_Success() (gas: 112985) +OffRamp_commit:test_OnlyPriceUpdateStaleReport_Revert() (gas: 121175) +OffRamp_commit:test_OnlyTokenPriceUpdates_Success() (gas: 112917) +OffRamp_commit:test_PriceSequenceNumberCleared_Success() (gas: 355254) +OffRamp_commit:test_ReportAndPriceUpdate_Success() (gas: 164263) +OffRamp_commit:test_ReportOnlyRootSuccess_gas() (gas: 141269) +OffRamp_commit:test_RootAlreadyCommitted_Revert() (gas: 148268) +OffRamp_commit:test_RootWithRMNDisabled_success() (gas: 153986) +OffRamp_commit:test_SourceChainNotEnabled_Revert() (gas: 61681) +OffRamp_commit:test_StaleReportWithRoot_Success() (gas: 232354) +OffRamp_commit:test_UnauthorizedTransmitter_Revert() (gas: 125230) +OffRamp_commit:test_Unhealthy_Revert() (gas: 60482) +OffRamp_commit:test_ValidPriceUpdateThenStaleReportWithRoot_Success() (gas: 206800) +OffRamp_commit:test_ZeroEpochAndRound_Revert() (gas: 53621) +OffRamp_constructor:test_Constructor_Success() (gas: 6186663) +OffRamp_constructor:test_SourceChainSelector_Revert() (gas: 136575) +OffRamp_constructor:test_ZeroChainSelector_Revert() (gas: 103612) +OffRamp_constructor:test_ZeroNonceManager_Revert() (gas: 101461) +OffRamp_constructor:test_ZeroOnRampAddress_Revert() (gas: 162055) +OffRamp_constructor:test_ZeroRMNRemote_Revert() (gas: 101378) +OffRamp_constructor:test_ZeroTokenAdminRegistry_Revert() (gas: 101382) +OffRamp_execute:test_IncorrectArrayType_Revert() (gas: 17639) +OffRamp_execute:test_LargeBatch_Success() (gas: 3374933) +OffRamp_execute:test_MultipleReportsWithPartialValidationFailures_Success() (gas: 371025) +OffRamp_execute:test_MultipleReports_Success() (gas: 298564) +OffRamp_execute:test_NoConfigWithOtherConfigPresent_Revert() (gas: 7049279) +OffRamp_execute:test_NoConfig_Revert() (gas: 6273749) +OffRamp_execute:test_NonArray_Revert() (gas: 27643) +OffRamp_execute:test_SingleReport_Success() (gas: 175627) +OffRamp_execute:test_UnauthorizedTransmitter_Revert() (gas: 147783) +OffRamp_execute:test_WrongConfigWithSigners_Revert() (gas: 6940958) +OffRamp_execute:test_ZeroReports_Revert() (gas: 17361) +OffRamp_executeSingleMessage:test_MessageSender_Revert() (gas: 18533) +OffRamp_executeSingleMessage:test_NonContractWithTokens_Success() (gas: 244171) +OffRamp_executeSingleMessage:test_NonContract_Success() (gas: 20363) +OffRamp_executeSingleMessage:test_TokenHandlingError_Revert() (gas: 205647) +OffRamp_executeSingleMessage:test_ZeroGasDONExecution_Revert() (gas: 48880) +OffRamp_executeSingleMessage:test_executeSingleMessage_NoTokens_Success() (gas: 56102) +OffRamp_executeSingleMessage:test_executeSingleMessage_WithFailingValidationNoRouterCall_Revert() (gas: 212824) +OffRamp_executeSingleMessage:test_executeSingleMessage_WithFailingValidation_Revert() (gas: 85495) +OffRamp_executeSingleMessage:test_executeSingleMessage_WithTokens_Success() (gas: 274279) +OffRamp_executeSingleMessage:test_executeSingleMessage_WithVInterception_Success() (gas: 91918) +OffRamp_executeSingleReport:test_DisabledSourceChain_Revert() (gas: 28666) +OffRamp_executeSingleReport:test_EmptyReport_Revert() (gas: 15584) +OffRamp_executeSingleReport:test_InvalidSourcePoolAddress_Success() (gas: 481487) +OffRamp_executeSingleReport:test_ManualExecutionNotYetEnabled_Revert() (gas: 48303) +OffRamp_executeSingleReport:test_MismatchingDestChainSelector_Revert() (gas: 34108) +OffRamp_executeSingleReport:test_NonExistingSourceChain_Revert() (gas: 28831) +OffRamp_executeSingleReport:test_ReceiverError_Success() (gas: 187607) +OffRamp_executeSingleReport:test_RetryFailedMessageWithoutManualExecution_Revert() (gas: 197746) +OffRamp_executeSingleReport:test_RootNotCommitted_Revert() (gas: 40694) +OffRamp_executeSingleReport:test_RouterYULCall_Revert() (gas: 404953) +OffRamp_executeSingleReport:test_SingleMessageNoTokensOtherChain_Success() (gas: 248622) +OffRamp_executeSingleReport:test_SingleMessageNoTokensUnordered_Success() (gas: 192288) +OffRamp_executeSingleReport:test_SingleMessageNoTokens_Success() (gas: 212314) +OffRamp_executeSingleReport:test_SingleMessageToNonCCIPReceiver_Success() (gas: 243661) +OffRamp_executeSingleReport:test_SingleMessagesNoTokensSuccess_gas() (gas: 141439) +OffRamp_executeSingleReport:test_SkippedIncorrectNonceStillExecutes_Success() (gas: 408713) +OffRamp_executeSingleReport:test_SkippedIncorrectNonce_Success() (gas: 58249) +OffRamp_executeSingleReport:test_TokenDataMismatch_Revert() (gas: 73816) +OffRamp_executeSingleReport:test_TwoMessagesWithTokensAndGE_Success() (gas: 582570) +OffRamp_executeSingleReport:test_TwoMessagesWithTokensSuccess_gas() (gas: 531121) +OffRamp_executeSingleReport:test_UnexpectedTokenData_Revert() (gas: 26755) +OffRamp_executeSingleReport:test_UnhealthySingleChainCurse_Revert() (gas: 549145) +OffRamp_executeSingleReport:test_Unhealthy_Success() (gas: 549092) +OffRamp_executeSingleReport:test_WithCurseOnAnotherSourceChain_Success() (gas: 460234) +OffRamp_executeSingleReport:test__execute_SkippedAlreadyExecutedMessageUnordered_Success() (gas: 135167) +OffRamp_executeSingleReport:test__execute_SkippedAlreadyExecutedMessage_Success() (gas: 164806) +OffRamp_getExecutionState:test_FillExecutionState_Success() (gas: 3888846) +OffRamp_getExecutionState:test_GetDifferentChainExecutionState_Success() (gas: 121048) +OffRamp_getExecutionState:test_GetExecutionState_Success() (gas: 89561) +OffRamp_manuallyExecute:test_ManualExecGasLimitMismatchSingleReport_Revert() (gas: 81178) +OffRamp_manuallyExecute:test_manuallyExecute_DestinationGasAmountCountMismatch_Revert() (gas: 74108) +OffRamp_manuallyExecute:test_manuallyExecute_DoesNotRevertIfUntouched_Success() (gas: 172480) +OffRamp_manuallyExecute:test_manuallyExecute_FailedTx_Revert() (gas: 212935) +OffRamp_manuallyExecute:test_manuallyExecute_ForkedChain_Revert() (gas: 27166) +OffRamp_manuallyExecute:test_manuallyExecute_GasLimitMismatchMultipleReports_Revert() (gas: 164939) +OffRamp_manuallyExecute:test_manuallyExecute_InvalidReceiverExecutionGasLimit_Revert() (gas: 27703) +OffRamp_manuallyExecute:test_manuallyExecute_InvalidTokenGasOverride_Revert() (gas: 55274) +OffRamp_manuallyExecute:test_manuallyExecute_LowGasLimit_Success() (gas: 489352) +OffRamp_manuallyExecute:test_manuallyExecute_MultipleReportsWithSingleCursedLane_Revert() (gas: 314370) +OffRamp_manuallyExecute:test_manuallyExecute_ReentrancyFails_Success() (gas: 2227706) +OffRamp_manuallyExecute:test_manuallyExecute_SourceChainSelectorMismatch_Revert() (gas: 165133) +OffRamp_manuallyExecute:test_manuallyExecute_Success() (gas: 225844) +OffRamp_manuallyExecute:test_manuallyExecute_WithGasOverride_Success() (gas: 226384) +OffRamp_manuallyExecute:test_manuallyExecute_WithMultiReportGasOverride_Success() (gas: 773426) +OffRamp_manuallyExecute:test_manuallyExecute_WithPartialMessages_Success() (gas: 344159) +OffRamp_releaseOrMintSingleToken:test__releaseOrMintSingleToken_NotACompatiblePool_Revert() (gas: 37654) +OffRamp_releaseOrMintSingleToken:test__releaseOrMintSingleToken_Success() (gas: 104625) +OffRamp_releaseOrMintSingleToken:test__releaseOrMintSingleToken_TokenHandlingError_transfer_Revert() (gas: 83092) +OffRamp_releaseOrMintSingleToken:test_releaseOrMintToken_InvalidDataLength_Revert() (gas: 36812) +OffRamp_releaseOrMintSingleToken:test_releaseOrMintToken_ReleaseOrMintBalanceMismatch_Revert() (gas: 94670) +OffRamp_releaseOrMintSingleToken:test_releaseOrMintToken_TokenHandlingError_BalanceOf_Revert() (gas: 37323) +OffRamp_releaseOrMintSingleToken:test_releaseOrMintToken_skip_ReleaseOrMintBalanceMismatch_if_pool_Revert() (gas: 86760) +OffRamp_releaseOrMintTokens:test_TokenHandlingError_Reverts() (gas: 162933) +OffRamp_releaseOrMintTokens:test__releaseOrMintTokens_PoolIsNotAPool_Reverts() (gas: 23836) +OffRamp_releaseOrMintTokens:test_releaseOrMintTokens_InvalidDataLengthReturnData_Revert() (gas: 62844) +OffRamp_releaseOrMintTokens:test_releaseOrMintTokens_PoolDoesNotSupportDest_Reverts() (gas: 80014) +OffRamp_releaseOrMintTokens:test_releaseOrMintTokens_Success() (gas: 174989) +OffRamp_releaseOrMintTokens:test_releaseOrMintTokens_WithGasOverride_Success() (gas: 176901) +OffRamp_releaseOrMintTokens:test_releaseOrMintTokens_destDenominatedDecimals_Success() (gas: 188167) +OffRamp_setDynamicConfig:test_FeeQuoterZeroAddress_Revert() (gas: 11509) +OffRamp_setDynamicConfig:test_NonOwner_Revert() (gas: 14019) +OffRamp_setDynamicConfig:test_SetDynamicConfigWithInterceptor_Success() (gas: 47579) +OffRamp_setDynamicConfig:test_SetDynamicConfig_Success() (gas: 25552) +OffRamp_trialExecute:test_RateLimitError_Success() (gas: 219928) +OffRamp_trialExecute:test_TokenHandlingErrorIsCaught_Success() (gas: 228561) +OffRamp_trialExecute:test_TokenPoolIsNotAContract_Success() (gas: 295602) +OffRamp_trialExecute:test_trialExecute_Success() (gas: 278032) +OnRampTokenPoolReentrancy:test_OnRampTokenPoolReentrancy_Success() (gas: 251573) +OnRamp_applyAllowlistUpdates:test_applyAllowlistUpdates_InvalidAllowListRequestDisabledAllowListWithAdds() (gas: 17227) +OnRamp_applyAllowlistUpdates:test_applyAllowlistUpdates_Revert() (gas: 67101) +OnRamp_applyAllowlistUpdates:test_applyAllowlistUpdates_Success() (gas: 325983) +OnRamp_applyDestChainConfigUpdates:test_ApplyDestChainConfigUpdates_Success() (gas: 65892) +OnRamp_applyDestChainConfigUpdates:test_ApplyDestChainConfigUpdates_WithInvalidChainSelector_Revert() (gas: 12902) +OnRamp_constructor:test_Constructor_EnableAllowList_ForwardFromRouter_Reverts() (gas: 2569362) +OnRamp_constructor:test_Constructor_InvalidConfigChainSelectorEqZero_Revert() (gas: 95148) +OnRamp_constructor:test_Constructor_InvalidConfigNonceManagerEqAddressZero_Revert() (gas: 93090) +OnRamp_constructor:test_Constructor_InvalidConfigRMNProxyEqAddressZero_Revert() (gas: 98066) +OnRamp_constructor:test_Constructor_InvalidConfigTokenAdminRegistryEqAddressZero_Revert() (gas: 93146) +OnRamp_constructor:test_Constructor_Success() (gas: 2647459) +OnRamp_forwardFromRouter:test_ForwardFromRouterExtraArgsV2AllowOutOfOrderTrue_Success() (gas: 115376) +OnRamp_forwardFromRouter:test_ForwardFromRouterExtraArgsV2_Success() (gas: 146244) +OnRamp_forwardFromRouter:test_ForwardFromRouterSuccessCustomExtraArgs() (gas: 145819) +OnRamp_forwardFromRouter:test_ForwardFromRouterSuccessEmptyExtraArgs() (gas: 144024) +OnRamp_forwardFromRouter:test_ForwardFromRouterSuccessLegacyExtraArgs() (gas: 146016) +OnRamp_forwardFromRouter:test_ForwardFromRouter_Success() (gas: 145414) +OnRamp_forwardFromRouter:test_ForwardFromRouter_Success_ConfigurableSourceRouter() (gas: 140697) +OnRamp_forwardFromRouter:test_InvalidExtraArgsTag_Revert() (gas: 38504) +OnRamp_forwardFromRouter:test_MessageInterceptionError_Revert() (gas: 143100) +OnRamp_forwardFromRouter:test_MesssageFeeTooHigh_Revert() (gas: 36589) +OnRamp_forwardFromRouter:test_MultiCannotSendZeroTokens_Revert() (gas: 36493) +OnRamp_forwardFromRouter:test_OriginalSender_Revert() (gas: 18290) +OnRamp_forwardFromRouter:test_Paused_Revert() (gas: 38412) +OnRamp_forwardFromRouter:test_Permissions_Revert() (gas: 23629) +OnRamp_forwardFromRouter:test_ShouldIncrementNonceOnlyOnOrdered_Success() (gas: 186583) +OnRamp_forwardFromRouter:test_ShouldIncrementSeqNumAndNonce_Success() (gas: 213012) +OnRamp_forwardFromRouter:test_ShouldStoreLinkFees() (gas: 146992) +OnRamp_forwardFromRouter:test_ShouldStoreNonLinkFees() (gas: 161181) +OnRamp_forwardFromRouter:test_SourceTokenDataTooLarge_Revert() (gas: 3576260) +OnRamp_forwardFromRouter:test_UnAllowedOriginalSender_Revert() (gas: 24015) +OnRamp_forwardFromRouter:test_UnsupportedToken_Revert() (gas: 75832) +OnRamp_forwardFromRouter:test_forwardFromRouter_UnsupportedToken_Revert() (gas: 38588) +OnRamp_forwardFromRouter:test_forwardFromRouter_WithInterception_Success() (gas: 280344) +OnRamp_getFee:test_EmptyMessage_Success() (gas: 98692) +OnRamp_getFee:test_EnforceOutOfOrder_Revert() (gas: 65453) +OnRamp_getFee:test_GetFeeOfZeroForTokenMessage_Success() (gas: 87185) +OnRamp_getFee:test_NotAFeeTokenButPricedToken_Revert() (gas: 35166) +OnRamp_getFee:test_SingleTokenMessage_Success() (gas: 113865) +OnRamp_getFee:test_Unhealthy_Revert() (gas: 17040) +OnRamp_getSupportedTokens:test_GetSupportedTokens_Revert() (gas: 10565) +OnRamp_getTokenPool:test_GetTokenPool_Success() (gas: 35405) +OnRamp_setDynamicConfig:test_setDynamicConfig_InvalidConfigFeeAggregatorEqAddressZero_Revert() (gas: 11535) +OnRamp_setDynamicConfig:test_setDynamicConfig_InvalidConfigFeeQuoterEqAddressZero_Revert() (gas: 13194) +OnRamp_setDynamicConfig:test_setDynamicConfig_InvalidConfigInvalidConfig_Revert() (gas: 11499) +OnRamp_setDynamicConfig:test_setDynamicConfig_InvalidConfigOnlyOwner_Revert() (gas: 11938) +OnRamp_setDynamicConfig:test_setDynamicConfig_InvalidConfigReentrancyGuardEnteredEqTrue_Revert() (gas: 13264) +OnRamp_setDynamicConfig:test_setDynamicConfig_Success() (gas: 56440) +OnRamp_withdrawFeeTokens:test_WithdrawFeeTokens_Success() (gas: 125867) +PingPong_ccipReceive:test_CcipReceive_Success() (gas: 172841) +PingPong_setOutOfOrderExecution:test_OutOfOrderExecution_Success() (gas: 20283) +PingPong_setPaused:test_Pausing_Success() (gas: 17738) +PingPong_startPingPong:test_StartPingPong_With_OOO_Success() (gas: 151954) +PingPong_startPingPong:test_StartPingPong_With_Sequenced_Ordered_Success() (gas: 177569) +RMNHome_getConfigDigests:test_getConfigDigests_success() (gas: 1079685) +RMNHome_promoteCandidateAndRevokeActive:test_promoteCandidateAndRevokeActive_ConfigDigestMismatch_reverts() (gas: 23879) +RMNHome_promoteCandidateAndRevokeActive:test_promoteCandidateAndRevokeActive_NoOpStateTransitionNotAllowed_reverts() (gas: 10597) +RMNHome_promoteCandidateAndRevokeActive:test_promoteCandidateAndRevokeActive_OnlyOwner_reverts() (gas: 10843) +RMNHome_promoteCandidateAndRevokeActive:test_promoteCandidateAndRevokeActive_success() (gas: 1085033) +RMNHome_revokeCandidate:test_revokeCandidate_ConfigDigestMismatch_reverts() (gas: 19041) +RMNHome_revokeCandidate:test_revokeCandidate_OnlyOwner_reverts() (gas: 10889) +RMNHome_revokeCandidate:test_revokeCandidate_RevokingZeroDigestNotAllowed_reverts() (gas: 10628) +RMNHome_revokeCandidate:test_revokeCandidate_success() (gas: 28147) +RMNHome_setCandidate:test_setCandidate_ConfigDigestMismatch_reverts() (gas: 597564) +RMNHome_setCandidate:test_setCandidate_OnlyOwner_reverts() (gas: 15071) +RMNHome_setCandidate:test_setCandidate_success() (gas: 589330) +RMNHome_setDynamicConfig:test_setDynamicConfig_DigestNotFound_reverts() (gas: 30186) +RMNHome_setDynamicConfig:test_setDynamicConfig_MinObserversTooHigh_reverts() (gas: 18854) +RMNHome_setDynamicConfig:test_setDynamicConfig_OnlyOwner_reverts() (gas: 14009) +RMNHome_setDynamicConfig:test_setDynamicConfig_success() (gas: 104862) +RMNHome_validateStaticAndDynamicConfig:test_validateStaticAndDynamicConfig_DuplicateOffchainPublicKey_reverts() (gas: 18850) +RMNHome_validateStaticAndDynamicConfig:test_validateStaticAndDynamicConfig_DuplicatePeerId_reverts() (gas: 18710) +RMNHome_validateStaticAndDynamicConfig:test_validateStaticAndDynamicConfig_DuplicateSourceChain_reverts() (gas: 20387) +RMNHome_validateStaticAndDynamicConfig:test_validateStaticAndDynamicConfig_NotEnoughObservers_reverts() (gas: 21405) +RMNHome_validateStaticAndDynamicConfig:test_validateStaticAndDynamicConfig_OutOfBoundsNodesLength_reverts() (gas: 137318) +RMNHome_validateStaticAndDynamicConfig:test_validateStaticAndDynamicConfig_OutOfBoundsObserverNodeIndex_reverts() (gas: 20522) +RMNRemote_constructor:test_constructor_success() (gas: 8334) +RMNRemote_constructor:test_constructor_zeroChainSelector_reverts() (gas: 59184) +RMNRemote_curse:test_curse_AlreadyCursed_duplicateSubject_reverts() (gas: 154479) +RMNRemote_curse:test_curse_calledByNonOwner_reverts() (gas: 18712) +RMNRemote_curse:test_curse_success() (gas: 149431) +RMNRemote_global_and_legacy_curses:test_global_and_legacy_curses_success() (gas: 133512) +RMNRemote_setConfig:test_setConfig_ZeroValueNotAllowed_revert() (gas: 37971) +RMNRemote_setConfig:test_setConfig_addSigner_removeSigner_success() (gas: 993448) +RMNRemote_setConfig:test_setConfig_duplicateOnChainPublicKey_reverts() (gas: 323540) +RMNRemote_setConfig:test_setConfig_invalidSignerOrder_reverts() (gas: 80201) +RMNRemote_setConfig:test_setConfig_notEnoughSigners_reverts() (gas: 54232) +RMNRemote_uncurse:test_uncurse_NotCursed_duplicatedUncurseSubject_reverts() (gas: 51993) +RMNRemote_uncurse:test_uncurse_calledByNonOwner_reverts() (gas: 18682) +RMNRemote_uncurse:test_uncurse_success() (gas: 40171) +RMNRemote_verify_withConfigNotSet:test_verify_reverts() (gas: 13578) +RMNRemote_verify_withConfigSet:test_verify_InvalidSignature_reverts() (gas: 96449) +RMNRemote_verify_withConfigSet:test_verify_OutOfOrderSignatures_duplicateSignature_reverts() (gas: 94267) +RMNRemote_verify_withConfigSet:test_verify_OutOfOrderSignatures_not_sorted_reverts() (gas: 101330) +RMNRemote_verify_withConfigSet:test_verify_ThresholdNotMet_reverts() (gas: 304634) +RMNRemote_verify_withConfigSet:test_verify_UnexpectedSigner_reverts() (gas: 428126) +RMNRemote_verify_withConfigSet:test_verify_success() (gas: 86159) +RateLimiter_constructor:test_Constructor_Success() (gas: 19806) +RateLimiter_consume:test_AggregateValueMaxCapacityExceeded_Revert() (gas: 16042) +RateLimiter_consume:test_AggregateValueRateLimitReached_Revert() (gas: 22435) +RateLimiter_consume:test_ConsumeAggregateValue_Success() (gas: 31495) +RateLimiter_consume:test_ConsumeTokens_Success() (gas: 20403) +RateLimiter_consume:test_ConsumeUnlimited_Success() (gas: 40693) +RateLimiter_consume:test_ConsumingMoreThanUint128_Revert() (gas: 15800) +RateLimiter_consume:test_RateLimitReachedOverConsecutiveBlocks_Revert() (gas: 25781) +RateLimiter_consume:test_Refill_Success() (gas: 37447) +RateLimiter_consume:test_TokenMaxCapacityExceeded_Revert() (gas: 18388) +RateLimiter_consume:test_TokenRateLimitReached_Revert() (gas: 24930) +RateLimiter_currentTokenBucketState:test_CurrentTokenBucketState_Success() (gas: 38947) +RateLimiter_currentTokenBucketState:test_Refill_Success() (gas: 46852) +RateLimiter_setTokenBucketConfig:test_SetRateLimiterConfig_Success() (gas: 38509) +RegistryModuleOwnerCustom_constructor:test_constructor_Revert() (gas: 36107) +RegistryModuleOwnerCustom_registerAccessControlDefaultAdmin:test_registerAccessControlDefaultAdmin_Revert() (gas: 20200) +RegistryModuleOwnerCustom_registerAccessControlDefaultAdmin:test_registerAccessControlDefaultAdmin_Success() (gas: 130631) +RegistryModuleOwnerCustom_registerAdminViaGetCCIPAdmin:test_registerAdminViaGetCCIPAdmin_Revert() (gas: 19797) +RegistryModuleOwnerCustom_registerAdminViaGetCCIPAdmin:test_registerAdminViaGetCCIPAdmin_Success() (gas: 130126) +RegistryModuleOwnerCustom_registerAdminViaOwner:test_registerAdminViaOwner_Revert() (gas: 19602) +RegistryModuleOwnerCustom_registerAdminViaOwner:test_registerAdminViaOwner_Success() (gas: 129930) +Router_applyRampUpdates:test_OffRampMismatch_Revert() (gas: 89591) +Router_applyRampUpdates:test_OffRampUpdatesWithRouting() (gas: 10750087) +Router_applyRampUpdates:test_OnRampDisable() (gas: 56445) +Router_applyRampUpdates:test_OnlyOwner_Revert() (gas: 12414) +Router_ccipSend:test_CCIPSendLinkFeeNoTokenSuccess_gas() (gas: 131413) +Router_ccipSend:test_CCIPSendLinkFeeOneTokenSuccess_gas() (gas: 221240) +Router_ccipSend:test_FeeTokenAmountTooLow_Revert() (gas: 71841) +Router_ccipSend:test_InvalidMsgValue() (gas: 32411) +Router_ccipSend:test_NativeFeeTokenInsufficientValue() (gas: 69524) +Router_ccipSend:test_NativeFeeTokenOverpay_Success() (gas: 193296) +Router_ccipSend:test_NativeFeeTokenZeroValue() (gas: 61550) +Router_ccipSend:test_NativeFeeToken_Success() (gas: 191900) +Router_ccipSend:test_NonLinkFeeToken_Success() (gas: 226532) +Router_ccipSend:test_UnsupportedDestinationChain_Revert() (gas: 25056) +Router_ccipSend:test_WhenNotHealthy_Revert() (gas: 45056) +Router_ccipSend:test_WrappedNativeFeeToken_Success() (gas: 194209) +Router_ccipSend:test_ccipSend_nativeFeeNoTokenSuccess_gas() (gas: 140674) +Router_ccipSend:test_ccipSend_nativeFeeOneTokenSuccess_gas() (gas: 230436) +Router_constructor:test_Constructor_Success() (gas: 13222) Router_getArmProxy:test_getArmProxy() (gas: 10573) -Router_getFee:test_GetFeeSupportedChain() (gas: 52021) -Router_recoverTokens:test_RecoverTokens() (gas: 52668) -Router_routeMessage:test_routeMessage_AutoExec() (gas: 38071) -Router_routeMessage:test_routeMessage_ExecutionEvent() (gas: 153593) -Router_routeMessage:test_routeMessage_ManualExec() (gas: 31120) -TokenAdminRegistry_acceptAdminRole:test_acceptAdminRole() (gas: 44236) -TokenAdminRegistry_addRegistryModule:test_addRegistryModule() (gas: 67093) -TokenAdminRegistry_getAllConfiguredTokens:test_getAllConfiguredTokens_outOfBounds() (gas: 11363) -TokenAdminRegistry_getPool:test_getPool() (gas: 17679) -TokenAdminRegistry_getPools:test_getPools() (gas: 40271) -TokenAdminRegistry_isAdministrator:test_isAdministrator() (gas: 106335) -TokenAdminRegistry_proposeAdministrator:test_proposeAdministrator_module() (gas: 113043) -TokenAdminRegistry_proposeAdministrator:test_proposeAdministrator_owner() (gas: 107992) -TokenAdminRegistry_proposeAdministrator:test_proposeAdministrator_reRegisterWhileUnclaimed() (gas: 116200) -TokenAdminRegistry_removeRegistryModule:test_removeRegistryModule() (gas: 54757) -TokenAdminRegistry_setPool:test_setPool() (gas: 36207) -TokenAdminRegistry_setPool:test_setPool_ZeroAddressRemovesPool() (gas: 30852) -TokenAdminRegistry_transferAdminRole:test_transferAdminRole() (gas: 49558) -TokenPoolFactory_createTokenPool:test_createTokenPoolLockRelease_ExistingToken_predict() (gas: 12646379) -TokenPoolFactory_createTokenPool:test_createTokenPool_BurnFromMintTokenPool() (gas: 6526762) -TokenPoolFactory_createTokenPool:test_createTokenPool_ExistingRemoteToken_AndPredictPool() (gas: 13480657) -TokenPoolFactory_createTokenPool:test_createTokenPool_RemoteTokenHasDifferentDecimals() (gas: 13488141) -TokenPoolFactory_createTokenPool:test_createTokenPool_WithNoExistingRemoteContracts_predict() (gas: 13819502) -TokenPoolFactory_createTokenPool:test_createTokenPool_WithNoExistingTokenOnRemoteChain() (gas: 6315855) -TokenPoolFactory_createTokenPool:test_createTokenPool_WithRemoteTokenAndRemotePool() (gas: 6523352) -TokenPoolWithAllowList_applyAllowListUpdates:test_SetAllowList() (gas: 178482) -TokenPoolWithAllowList_applyAllowListUpdates:test_SetAllowListSkipsZero() (gas: 23580) -TokenPoolWithAllowList_getAllowList:test_GetAllowList() (gas: 23908) -TokenPoolWithAllowList_getAllowListEnabled:test_GetAllowListEnabled() (gas: 8386) -TokenPoolWithAllowList_setRouter:test_SetRouter() (gas: 24994) -TokenPool_addRemotePool:test_addRemotePool() (gas: 157121) -TokenPool_addRemotePool:test_addRemotePool_MultipleActive() (gas: 453937) -TokenPool_applyChainUpdates:test_applyChainUpdates() (gas: 592354) -TokenPool_applyChainUpdates:test_applyChainUpdates_UpdatesRemotePoolHashes() (gas: 1077690) -TokenPool_calculateLocalAmount:test_calculateLocalAmount() (gas: 93680) -TokenPool_constructor:test_constructor() (gas: 21930) -TokenPool_constructor:test_constructor_DecimalCallFails() (gas: 2836717) -TokenPool_getRemotePool:test_getRemotePools() (gas: 330476) -TokenPool_onlyOffRamp:test_onlyOffRamp() (gas: 94348) -TokenPool_onlyOnRamp:test_onlyOnRamp() (gas: 49257) -TokenPool_parseRemoteDecimals:test_parseRemoteDecimals() (gas: 14030) -TokenPool_parseRemoteDecimals:test_parseRemoteDecimals_NoDecimalsDefaultsToLocalDecimals() (gas: 9705) -TokenPool_removeRemotePool:test_removeRemotePool() (gas: 188402) -TokenPool_setRateLimitAdmin:test_SetRateLimitAdmin() (gas: 37630) -USDCBridgeMigrator_BurnLockedUSDC:test_PrimaryMechanism() (gas: 130520) -USDCBridgeMigrator_BurnLockedUSDC:test_lockOrBurn_then_BurnInCCTPMigration() (gas: 303986) -USDCBridgeMigrator_BurnLockedUSDC:test_onLockReleaseMechanism() (gas: 140171) -USDCBridgeMigrator_BurnLockedUSDC:test_onLockReleaseMechanism_thenSwitchToPrimary() (gas: 203330) -USDCBridgeMigrator_cancelMigrationProposal:test_cancelExistingCCTPMigrationProposal() (gas: 56117) -USDCBridgeMigrator_provideLiquidity:test_PrimaryMechanism() (gas: 130538) -USDCBridgeMigrator_provideLiquidity:test_lockOrBurn_then_BurnInCCTPMigration() (gas: 303986) -USDCBridgeMigrator_provideLiquidity:test_onLockReleaseMechanism() (gas: 140260) -USDCBridgeMigrator_provideLiquidity:test_onLockReleaseMechanism_thenSwitchToPrimary() (gas: 203331) -USDCBridgeMigrator_releaseOrMint:test_OnLockReleaseMechanism() (gas: 206251) -USDCBridgeMigrator_releaseOrMint:test_incomingMessageWithPrimaryMechanism() (gas: 260440) -USDCBridgeMigrator_releaseOrMint:test_unstickManualTxAfterMigration_destChain() (gas: 142763) -USDCBridgeMigrator_releaseOrMint:test_unstickManualTxAfterMigration_homeChain() (gas: 505520) -USDCBridgeMigrator_updateChainSelectorMechanism:test_PrimaryMechanism() (gas: 130520) -USDCBridgeMigrator_updateChainSelectorMechanism:test_lockOrBurn_then_BurnInCCTPMigration() (gas: 303968) -USDCBridgeMigrator_updateChainSelectorMechanism:test_onLockReleaseMechanism() (gas: 140260) -USDCBridgeMigrator_updateChainSelectorMechanism:test_onLockReleaseMechanism_thenSwitchToPrimary() (gas: 203312) -USDCTokenPool_lockOrBurn:test_LockOrBurn() (gas: 128094) -USDCTokenPool_releaseOrMint:test_ReleaseOrMintRealTx() (gas: 260189) -USDCTokenPool_supportsInterface:test_SupportsInterface() (gas: 10108) \ No newline at end of file +Router_getFee:test_GetFeeSupportedChain_Success() (gas: 51934) +Router_getFee:test_UnsupportedDestinationChain_Revert() (gas: 17385) +Router_getSupportedTokens:test_GetSupportedTokens_Revert() (gas: 10565) +Router_recoverTokens:test_RecoverTokensInvalidRecipient_Revert() (gas: 11410) +Router_recoverTokens:test_RecoverTokensNoFunds_Revert() (gas: 20199) +Router_recoverTokens:test_RecoverTokensNonOwner_Revert() (gas: 11236) +Router_recoverTokens:test_RecoverTokensValueReceiver_Revert() (gas: 349502) +Router_recoverTokens:test_RecoverTokens_Success() (gas: 52640) +Router_routeMessage:test_routeMessage_AutoExec_Success() (gas: 43213) +Router_routeMessage:test_routeMessage_ExecutionEvent_Success() (gas: 159418) +Router_routeMessage:test_routeMessage_ManualExec_Success() (gas: 35723) +Router_routeMessage:test_routeMessage_OnlyOffRamp_Revert() (gas: 25376) +Router_routeMessage:test_routeMessage_WhenNotHealthy_Revert() (gas: 44812) +Router_setWrappedNative:test_OnlyOwner_Revert() (gas: 11030) +TokenAdminRegistry_acceptAdminRole:test_acceptAdminRole_OnlyPendingAdministrator_Revert() (gas: 51433) +TokenAdminRegistry_acceptAdminRole:test_acceptAdminRole_Success() (gas: 44189) +TokenAdminRegistry_addRegistryModule:test_addRegistryModule_OnlyOwner_Revert() (gas: 12662) +TokenAdminRegistry_addRegistryModule:test_addRegistryModule_Success() (gas: 67155) +TokenAdminRegistry_getAllConfiguredTokens:test_getAllConfiguredTokens_outOfBounds_Success() (gas: 11395) +TokenAdminRegistry_getPool:test_getPool_Success() (gas: 17701) +TokenAdminRegistry_getPools:test_getPools_Success() (gas: 40331) +TokenAdminRegistry_isAdministrator:test_isAdministrator_Success() (gas: 106315) +TokenAdminRegistry_proposeAdministrator:test_proposeAdministrator_AlreadyRegistered_Revert() (gas: 104412) +TokenAdminRegistry_proposeAdministrator:test_proposeAdministrator_OnlyRegistryModule_Revert() (gas: 15643) +TokenAdminRegistry_proposeAdministrator:test_proposeAdministrator_ZeroAddress_Revert() (gas: 15177) +TokenAdminRegistry_proposeAdministrator:test_proposeAdministrator_module_Success() (gas: 113094) +TokenAdminRegistry_proposeAdministrator:test_proposeAdministrator_owner_Success() (gas: 108031) +TokenAdminRegistry_proposeAdministrator:test_proposeAdministrator_reRegisterWhileUnclaimed_Success() (gas: 116216) +TokenAdminRegistry_removeRegistryModule:test_removeRegistryModule_OnlyOwner_Revert() (gas: 12651) +TokenAdminRegistry_removeRegistryModule:test_removeRegistryModule_Success() (gas: 54735) +TokenAdminRegistry_setPool:test_setPool_InvalidTokenPoolToken_Revert() (gas: 19316) +TokenAdminRegistry_setPool:test_setPool_OnlyAdministrator_Revert() (gas: 18170) +TokenAdminRegistry_setPool:test_setPool_Success() (gas: 36267) +TokenAdminRegistry_setPool:test_setPool_ZeroAddressRemovesPool_Success() (gas: 30875) +TokenAdminRegistry_transferAdminRole:test_transferAdminRole_OnlyAdministrator_Revert() (gas: 18202) +TokenAdminRegistry_transferAdminRole:test_transferAdminRole_Success() (gas: 49592) +TokenPoolFactory_constructor:test_constructor_Revert() (gas: 1039441) +TokenPoolFactory_createTokenPool:test_createTokenPoolLockRelease_ExistingToken_predict_Success() (gas: 11591871) +TokenPoolFactory_createTokenPool:test_createTokenPool_BurnFromMintTokenPool_Success() (gas: 5848479) +TokenPoolFactory_createTokenPool:test_createTokenPool_ExistingRemoteToken_AndPredictPool_Success() (gas: 12227675) +TokenPoolFactory_createTokenPool:test_createTokenPool_WithNoExistingRemoteContracts_predict_Success() (gas: 12564436) +TokenPoolFactory_createTokenPool:test_createTokenPool_WithNoExistingTokenOnRemoteChain_Success() (gas: 5701824) +TokenPoolFactory_createTokenPool:test_createTokenPool_WithRemoteTokenAndRemotePool_Success() (gas: 5845002) +TokenPoolWithAllowList_applyAllowListUpdates:test_AllowListNotEnabled_Revert() (gas: 1944108) +TokenPoolWithAllowList_applyAllowListUpdates:test_OnlyOwner_Revert() (gas: 12119) +TokenPoolWithAllowList_applyAllowListUpdates:test_SetAllowListSkipsZero_Success() (gas: 23567) +TokenPoolWithAllowList_applyAllowListUpdates:test_SetAllowList_Success() (gas: 178398) +TokenPoolWithAllowList_getAllowList:test_GetAllowList_Success() (gas: 23929) +TokenPoolWithAllowList_getAllowListEnabled:test_GetAllowListEnabled_Success() (gas: 8408) +TokenPoolWithAllowList_setRouter:test_SetRouter_Success() (gas: 25005) +TokenPool_applyChainUpdates:test_applyChainUpdates_DisabledNonZeroRateLimit_Revert() (gas: 271914) +TokenPool_applyChainUpdates:test_applyChainUpdates_InvalidRateLimitRate_Revert() (gas: 543487) +TokenPool_applyChainUpdates:test_applyChainUpdates_NonExistentChain_Revert() (gas: 18706) +TokenPool_applyChainUpdates:test_applyChainUpdates_OnlyCallableByOwner_Revert() (gas: 11425) +TokenPool_applyChainUpdates:test_applyChainUpdates_Success() (gas: 480305) +TokenPool_applyChainUpdates:test_applyChainUpdates_ZeroAddressNotAllowed_Revert() (gas: 157716) +TokenPool_constructor:test_ZeroAddressNotAllowed_Revert() (gas: 70445) +TokenPool_constructor:test_immutableFields_Success() (gas: 20718) +TokenPool_getRemotePool:test_getRemotePool_Success() (gas: 274610) +TokenPool_onlyOffRamp:test_CallerIsNotARampOnRouter_Revert() (gas: 277555) +TokenPool_onlyOffRamp:test_ChainNotAllowed_Revert() (gas: 290432) +TokenPool_onlyOffRamp:test_onlyOffRamp_Success() (gas: 350358) +TokenPool_onlyOnRamp:test_CallerIsNotARampOnRouter_Revert() (gas: 277250) +TokenPool_onlyOnRamp:test_ChainNotAllowed_Revert() (gas: 254443) +TokenPool_onlyOnRamp:test_onlyOnRamp_Success() (gas: 305359) +TokenPool_setChainRateLimiterConfig:test_NonExistentChain_Revert() (gas: 17203) +TokenPool_setChainRateLimiterConfig:test_OnlyOwnerOrRateLimitAdmin_Revert() (gas: 15330) +TokenPool_setRateLimitAdmin:test_SetRateLimitAdmin_Revert() (gas: 11024) +TokenPool_setRateLimitAdmin:test_SetRateLimitAdmin_Success() (gas: 37584) +TokenPool_setRemotePool:test_setRemotePool_NonExistentChain_Reverts() (gas: 15796) +TokenPool_setRemotePool:test_setRemotePool_OnlyOwner_Reverts() (gas: 13285) +TokenPool_setRemotePool:test_setRemotePool_Success() (gas: 282581) +USDCBridgeMigrator_BurnLockedUSDC:test_PrimaryMechanism_Success() (gas: 135930) +USDCBridgeMigrator_BurnLockedUSDC:test_WhileMigrationPause_Revert() (gas: 109773) +USDCBridgeMigrator_BurnLockedUSDC:test_invalidPermissions_Revert() (gas: 39343) +USDCBridgeMigrator_BurnLockedUSDC:test_lockOrBurn_then_BurnInCCTPMigration_Success() (gas: 309779) +USDCBridgeMigrator_BurnLockedUSDC:test_onLockReleaseMechanism_Success() (gas: 147037) +USDCBridgeMigrator_BurnLockedUSDC:test_onLockReleaseMechanism_thenswitchToPrimary_Success() (gas: 209263) +USDCBridgeMigrator_cancelMigrationProposal:test_cancelExistingCCTPMigrationProposal_Success() (gas: 56190) +USDCBridgeMigrator_cancelMigrationProposal:test_cannotCancelANonExistentMigrationProposal_Revert() (gas: 12691) +USDCBridgeMigrator_excludeTokensFromBurn:test_excludeTokensWhenNoMigrationProposalPending_Revert() (gas: 13579) +USDCBridgeMigrator_proposeMigration:test_ChainNotUsingLockRelease_Revert() (gas: 15765) +USDCBridgeMigrator_provideLiquidity:test_PrimaryMechanism_Success() (gas: 135912) +USDCBridgeMigrator_provideLiquidity:test_WhileMigrationPause_Revert() (gas: 109795) +USDCBridgeMigrator_provideLiquidity:test_cannotModifyLiquidityWithoutPermissions_Revert() (gas: 13378) +USDCBridgeMigrator_provideLiquidity:test_cannotProvideLiquidityWhenMigrationProposalPending_Revert() (gas: 67436) +USDCBridgeMigrator_provideLiquidity:test_cannotProvideLiquidity_AfterMigration_Revert() (gas: 313619) +USDCBridgeMigrator_provideLiquidity:test_invalidPermissions_Revert() (gas: 39343) +USDCBridgeMigrator_provideLiquidity:test_lockOrBurn_then_BurnInCCTPMigration_Success() (gas: 309779) +USDCBridgeMigrator_provideLiquidity:test_onLockReleaseMechanism_Success() (gas: 147082) +USDCBridgeMigrator_provideLiquidity:test_onLockReleaseMechanism_thenswitchToPrimary_Success() (gas: 209299) +USDCBridgeMigrator_releaseOrMint:test_OnLockReleaseMechanism_Success() (gas: 216942) +USDCBridgeMigrator_releaseOrMint:test_WhileMigrationPause_Revert() (gas: 113505) +USDCBridgeMigrator_releaseOrMint:test_incomingMessageWithPrimaryMechanism() (gas: 269034) +USDCBridgeMigrator_releaseOrMint:test_unstickManualTxAfterMigration_destChain_Success() (gas: 156071) +USDCBridgeMigrator_releaseOrMint:test_unstickManualTxAfterMigration_homeChain_Success() (gas: 516094) +USDCBridgeMigrator_updateChainSelectorMechanism:test_PrimaryMechanism_Success() (gas: 135930) +USDCBridgeMigrator_updateChainSelectorMechanism:test_WhileMigrationPause_Revert() (gas: 109773) +USDCBridgeMigrator_updateChainSelectorMechanism:test_cannotRevertChainMechanism_afterMigration_Revert() (gas: 313216) +USDCBridgeMigrator_updateChainSelectorMechanism:test_invalidPermissions_Revert() (gas: 39321) +USDCBridgeMigrator_updateChainSelectorMechanism:test_lockOrBurn_then_BurnInCCTPMigration_Success() (gas: 309779) +USDCBridgeMigrator_updateChainSelectorMechanism:test_onLockReleaseMechanism_Success() (gas: 147037) +USDCBridgeMigrator_updateChainSelectorMechanism:test_onLockReleaseMechanism_thenswitchToPrimary_Success() (gas: 209263) +USDCTokenPool__validateMessage:test_ValidateInvalidMessage_Revert() (gas: 25854) +USDCTokenPool_lockOrBurn:test_CallerIsNotARampOnRouter_Revert() (gas: 35526) +USDCTokenPool_lockOrBurn:test_LockOrBurnWithAllowList_Revert() (gas: 30257) +USDCTokenPool_lockOrBurn:test_LockOrBurn_Success() (gas: 133488) +USDCTokenPool_lockOrBurn:test_UnknownDomain_Revert() (gas: 478302) +USDCTokenPool_releaseOrMint:test_ReleaseOrMintRealTx_Success() (gas: 268748) +USDCTokenPool_releaseOrMint:test_TokenMaxCapacityExceeded_Revert() (gas: 51026) +USDCTokenPool_releaseOrMint:test_UnlockingUSDCFailed_Revert() (gas: 99033) +USDCTokenPool_setDomains:test_InvalidDomain_Revert() (gas: 66437) +USDCTokenPool_setDomains:test_OnlyOwner_Revert() (gas: 11314) +USDCTokenPool_supportsInterface:test_SupportsInterface_Success() (gas: 10107) \ No newline at end of file diff --git a/contracts/gas-snapshots/l2ep.gas-snapshot b/contracts/gas-snapshots/l2ep.gas-snapshot index 7caca346f48..e9e5a42878b 100644 --- a/contracts/gas-snapshots/l2ep.gas-snapshot +++ b/contracts/gas-snapshots/l2ep.gas-snapshot @@ -1,113 +1,142 @@ -ArbitrumCrossDomainForwarder_AcceptL1Ownership:test_CallableByPendingL1Owner() (gas: 37567) -ArbitrumCrossDomainForwarder_AcceptL1Ownership:test_NotCallableByNonPendingOwners() (gas: 12954) -ArbitrumCrossDomainForwarder_Constructor:test_InitialState() (gas: 22111) -ArbitrumCrossDomainForwarder_Forward:test_Forward() (gas: 47818) -ArbitrumCrossDomainForwarder_Forward:test_ForwardRevert() (gas: 22147) -ArbitrumCrossDomainForwarder_Forward:test_NotCallableByUnknownAddress() (gas: 16083) -ArbitrumCrossDomainForwarder_TransferL1Ownership:test_CallableByL1Owner() (gas: 41439) -ArbitrumCrossDomainForwarder_TransferL1Ownership:test_CallableByL1OwnerOrZeroAddress() (gas: 19274) -ArbitrumCrossDomainForwarder_TransferL1Ownership:test_NotCallableByL2Owner() (gas: 18644) -ArbitrumCrossDomainForwarder_TransferL1Ownership:test_NotCallableByNonOwners() (gas: 13232) -ArbitrumCrossDomainGovernor_AcceptL1Ownership:test_CallableByPendingL1Owner() (gas: 37567) -ArbitrumCrossDomainGovernor_AcceptL1Ownership:test_NotCallableByNonPendingOwners() (gas: 12954) -ArbitrumCrossDomainGovernor_Constructor:test_InitialState() (gas: 22134) -ArbitrumCrossDomainGovernor_Forward:test_CallableByL2Owner() (gas: 49953) -ArbitrumCrossDomainGovernor_Forward:test_Forward() (gas: 47869) -ArbitrumCrossDomainGovernor_Forward:test_ForwardRevert() (gas: 24268) -ArbitrumCrossDomainGovernor_Forward:test_NotCallableByUnknownAddress() (gas: 18216) -ArbitrumCrossDomainGovernor_ForwardDelegate:test_BubbleUpRevert() (gas: 19338) -ArbitrumCrossDomainGovernor_ForwardDelegate:test_CallableByCrossDomainMessengerAddressOrL1Owner() (gas: 60787) -ArbitrumCrossDomainGovernor_ForwardDelegate:test_CallableByL2Owner() (gas: 62915) -ArbitrumCrossDomainGovernor_ForwardDelegate:test_NotCallableByUnknownAddress() (gas: 18271) -ArbitrumCrossDomainGovernor_ForwardDelegate:test_RevertsBatchWhenOneCallFails() (gas: 64276) -ArbitrumCrossDomainGovernor_TransferL1Ownership:test_CallableByL1Owner() (gas: 41439) -ArbitrumCrossDomainGovernor_TransferL1Ownership:test_CallableByL1OwnerOrZeroAddress() (gas: 19274) -ArbitrumCrossDomainGovernor_TransferL1Ownership:test_NotCallableByL2Owner() (gas: 18644) -ArbitrumCrossDomainGovernor_TransferL1Ownership:test_NotCallableByNonOwners() (gas: 13232) -ArbitrumSequencerUptimeFeed_AggregatorV3Interface:test_AggregatorV3Interface() (gas: 104766) -ArbitrumSequencerUptimeFeed_AggregatorV3Interface:test_Return0WhenRoundDoesNotExistYet() (gas: 19945) -ArbitrumSequencerUptimeFeed_Constants:test_InitialState() (gas: 8492) -ArbitrumSequencerUptimeFeed_ProtectReadsOnAggregatorV2V3InterfaceFunctions:test_AggregatorV2V3InterfaceAllowReadsIfConsumingContractIsWhitelisted() (gas: 592246) -ArbitrumSequencerUptimeFeed_ProtectReadsOnAggregatorV2V3InterfaceFunctions:test_AggregatorV2V3InterfaceDisallowReadsIfConsumingContractIsNotWhitelisted() (gas: 562331) -ArbitrumSequencerUptimeFeed_UpdateStatus:test_IgnoreOutOfOrderUpdates() (gas: 99593) -ArbitrumSequencerUptimeFeed_UpdateStatus:test_RevertIfNotL2CrossDomainMessengerAddr() (gas: 15442) -ArbitrumSequencerUptimeFeed_UpdateStatus:test_UpdateStatusWhenStatusChangeAndNoTimeChange() (gas: 114527) -ArbitrumSequencerUptimeFeed_UpdateStatus:test_UpdateStatusWhenStatusChangeAndTimeChange() (gas: 114610) -ArbitrumValidator_Validate:test_PostSequencerOffline() (gas: 69009) -BaseSequencerUptimeFeed_AggregatorV3Interface:test_AggregatorV3Interface_ReturnsValidData() (gas: 69197) -BaseSequencerUptimeFeed_AggregatorV3Interface:test_getAnswer_ReturnsValidAnswer() (gas: 57300) -BaseSequencerUptimeFeed_AggregatorV3Interface:test_getTimestamp_ReturnsValidTimestamp() (gas: 57151) -BaseSequencerUptimeFeed_Constructor:test_Constructor_InitialState() (gas: 22050) -BaseSequencerUptimeFeed_ProtectReadsOnAggregatorV2V3InterfaceFunctions:test_ProtectReads_AllowWhen_Whitelisted() (gas: 589517) -BaseSequencerUptimeFeed_ProtectReadsOnAggregatorV2V3InterfaceFunctions:test_ProtectReads_DisallowWhen_NotWhitelisted() (gas: 562342) -BaseSequencerUptimeFeed_UpdateStatus:test_updateStatus_IgnoreOutOfOrderUpdates() (gas: 69490) -BaseSequencerUptimeFeed_UpdateStatus:test_updateStatus_UpdateWhen_NoStatusChangeSameTimestamp() (gas: 77166) -BaseSequencerUptimeFeed_UpdateStatus:test_updateStatus_UpdateWhen_StatusChangeAndNoTimeChange() (gas: 96021) -BaseSequencerUptimeFeed_UpdateStatus:test_updateStatus_UpdateWhen_StatusChangeAndTimeChange() (gas: 96100) -BaseSequencerUptimeFeed_transferL1Sender:test_transferL1Sender_CorrectlyTransfersL1Sender() (gas: 1479310) -BaseValidator_GetAndSetGasLimit:test_GetAndSetGasLimit_CorrectlyHandlesGasLimit() (gas: 20119) -OptimismCrossDomainForwarder_AcceptL1Ownership:test_CallableByPendingL1Owner() (gas: 47110) -OptimismCrossDomainForwarder_AcceptL1Ownership:test_NotCallableByNonPendingOwners() (gas: 22135) -OptimismCrossDomainForwarder_Constructor:test_InitialState() (gas: 21947) -OptimismCrossDomainForwarder_Forward:test_Forward() (gas: 58213) -OptimismCrossDomainForwarder_Forward:test_ForwardRevert() (gas: 32533) -OptimismCrossDomainForwarder_Forward:test_NotCallableByUnknownAddress() (gas: 13895) -OptimismCrossDomainForwarder_TransferL1Ownership:test_CallableByL1Owner() (gas: 48912) -OptimismCrossDomainForwarder_TransferL1Ownership:test_CallableByL1OwnerOrZeroAddress() (gas: 28733) -OptimismCrossDomainForwarder_TransferL1Ownership:test_NotCallableByL2Owner() (gas: 16456) -OptimismCrossDomainForwarder_TransferL1Ownership:test_NotCallableByNonOwners() (gas: 11044) -OptimismCrossDomainGovernor_AcceptL1Ownership:test_CallableByPendingL1Owner() (gas: 47110) -OptimismCrossDomainGovernor_AcceptL1Ownership:test_NotCallableByNonPendingOwners() (gas: 22135) -OptimismCrossDomainGovernor_Constructor:test_InitialState() (gas: 21970) -OptimismCrossDomainGovernor_Forward:test_CallableByL2Owner() (gas: 47797) -OptimismCrossDomainGovernor_Forward:test_Forward() (gas: 58284) -OptimismCrossDomainGovernor_Forward:test_ForwardRevert() (gas: 32569) -OptimismCrossDomainGovernor_Forward:test_NotCallableByUnknownAddress() (gas: 16031) -OptimismCrossDomainGovernor_ForwardDelegate:test_BubbleUpRevert() (gas: 29128) -OptimismCrossDomainGovernor_ForwardDelegate:test_CallableByCrossDomainMessengerAddressOrL1Owner() (gas: 72836) -OptimismCrossDomainGovernor_ForwardDelegate:test_CallableByL2Owner() (gas: 72841) -OptimismCrossDomainGovernor_ForwardDelegate:test_NotCallableByUnknownAddress() (gas: 16086) -OptimismCrossDomainGovernor_ForwardDelegate:test_RevertsBatchWhenOneCallFails() (gas: 76045) -OptimismCrossDomainGovernor_TransferL1Ownership:test_CallableByL1Owner() (gas: 48912) -OptimismCrossDomainGovernor_TransferL1Ownership:test_CallableByL1OwnerOrZeroAddress() (gas: 28733) -OptimismCrossDomainGovernor_TransferL1Ownership:test_NotCallableByL2Owner() (gas: 16456) -OptimismCrossDomainGovernor_TransferL1Ownership:test_NotCallableByNonOwners() (gas: 11044) -OptimismSequencerUptimeFeed_Constructor:test_Constructor_InitialState() (gas: 1530881) -OptimismSequencerUptimeFeed_ValidateSender:test_ValidateSender_UpdateStatusWhen_StatusChangeAndNoTimeChange() (gas: 17874) -OptimismValidator_Validate:test_Validate_PostSequencerOffline() (gas: 74773) -OptimismValidator_Validate:test_Validate_PostSequencerStatus_NoStatusChange() (gas: 74788) -ScrollCrossDomainForwarder_AcceptL1Ownership:test_CallableByPendingL1Owner() (gas: 47196) -ScrollCrossDomainForwarder_AcceptL1Ownership:test_NotCallableByNonPendingOwners() (gas: 22185) -ScrollCrossDomainForwarder_Constructor:test_InitialState() (gas: 21623) -ScrollCrossDomainForwarder_Forward:test_Forward() (gas: 58277) -ScrollCrossDomainForwarder_Forward:test_ForwardRevert() (gas: 32589) -ScrollCrossDomainForwarder_Forward:test_NotCallableByUnknownAddress() (gas: 13895) -ScrollCrossDomainForwarder_TransferL1Ownership:test_CallableByL1Owner() (gas: 48975) -ScrollCrossDomainForwarder_TransferL1Ownership:test_CallableByL1OwnerOrZeroAddress() (gas: 28791) -ScrollCrossDomainForwarder_TransferL1Ownership:test_NotCallableByL2Owner() (gas: 16456) -ScrollCrossDomainForwarder_TransferL1Ownership:test_NotCallableByNonOwners() (gas: 11044) -ScrollCrossDomainGovernor_AcceptL1Ownership:test_CallableByPendingL1Owner() (gas: 47196) -ScrollCrossDomainGovernor_AcceptL1Ownership:test_NotCallableByNonPendingOwners() (gas: 22185) -ScrollCrossDomainGovernor_Constructor:test_InitialState() (gas: 21646) -ScrollCrossDomainGovernor_Forward:test_CallableByL2Owner() (gas: 47792) -ScrollCrossDomainGovernor_Forward:test_Forward() (gas: 58343) -ScrollCrossDomainGovernor_Forward:test_ForwardRevert() (gas: 32622) -ScrollCrossDomainGovernor_Forward:test_NotCallableByUnknownAddress() (gas: 16028) -ScrollCrossDomainGovernor_ForwardDelegate:test_BubbleUpRevert() (gas: 29186) -ScrollCrossDomainGovernor_ForwardDelegate:test_CallableByCrossDomainMessengerAddressOrL1Owner() (gas: 72900) -ScrollCrossDomainGovernor_ForwardDelegate:test_CallableByL2Owner() (gas: 72905) -ScrollCrossDomainGovernor_ForwardDelegate:test_NotCallableByUnknownAddress() (gas: 16083) -ScrollCrossDomainGovernor_ForwardDelegate:test_RevertsBatchWhenOneCallFails() (gas: 76110) -ScrollCrossDomainGovernor_TransferL1Ownership:test_CallableByL1Owner() (gas: 48975) -ScrollCrossDomainGovernor_TransferL1Ownership:test_CallableByL1OwnerOrZeroAddress() (gas: 28791) -ScrollCrossDomainGovernor_TransferL1Ownership:test_NotCallableByL2Owner() (gas: 16456) -ScrollCrossDomainGovernor_TransferL1Ownership:test_NotCallableByNonOwners() (gas: 11044) -ScrollSequencerUptimeFeed_Constructor:test_Constructor_InitialState_WhenValidL2XDomainMessenger() (gas: 1511902) -ScrollSequencerUptimeFeed_ValidateSender:test_ValidateSender_UpdateStatusWhen_StatusChangeAndNoTimeChange() (gas: 17864) -ScrollValidator_Validate:test_Validate_PostSequencerOffline() (gas: 78317) -ScrollValidator_Validate:test_Validate_PostSequencerStatus_NoStatusChange() (gas: 78338) -ZKSyncSequencerUptimeFeed_ValidateSender:test_ValidateSender_SuccessWhen_SenderIsValid() (gas: 12611) -ZKSyncValidator_GetChainId:test_GetChainId_CorrectlyGetsTheChainId() (gas: 8369) -ZKSyncValidator_GetSetL2GasPerPubdataByteLimit:test_GetSetL2GasPerPubdataByteLimit_CorrectlyHandlesGasPerPubdataByteLimit() (gas: 18918) -ZKSyncValidator_Validate:test_Validate_PostSequencerOffline() (gas: 52208) -ZKSyncValidator_Validate:test_Validate_PostSequencerStatus_NoStatusChange() (gas: 52280) \ No newline at end of file +ArbitrumCrossDomainForwarder_AcceptL1Ownership:test_CallableByPendingL1Owner() (gas: 37586) +ArbitrumCrossDomainForwarder_AcceptL1Ownership:test_NotCallableByNonPendingOwners() (gas: 12963) +ArbitrumCrossDomainForwarder_Constructor:test_InitialState() (gas: 22141) +ArbitrumCrossDomainForwarder_Forward:test_Forward() (gas: 47867) +ArbitrumCrossDomainForwarder_Forward:test_ForwardRevert() (gas: 22174) +ArbitrumCrossDomainForwarder_Forward:test_NotCallableByUnknownAddress() (gas: 16099) +ArbitrumCrossDomainForwarder_TransferL1Ownership:test_CallableByL1Owner() (gas: 41453) +ArbitrumCrossDomainForwarder_TransferL1Ownership:test_CallableByL1OwnerOrZeroAddress() (gas: 19290) +ArbitrumCrossDomainForwarder_TransferL1Ownership:test_NotCallableByL2Owner() (gas: 18659) +ArbitrumCrossDomainForwarder_TransferL1Ownership:test_NotCallableByNonOwners() (gas: 13242) +ArbitrumCrossDomainGovernor_AcceptL1Ownership:test_CallableByPendingL1Owner() (gas: 37586) +ArbitrumCrossDomainGovernor_AcceptL1Ownership:test_NotCallableByNonPendingOwners() (gas: 12963) +ArbitrumCrossDomainGovernor_Constructor:test_InitialState() (gas: 22164) +ArbitrumCrossDomainGovernor_Forward:test_CallableByL2Owner() (gas: 50003) +ArbitrumCrossDomainGovernor_Forward:test_Forward() (gas: 47918) +ArbitrumCrossDomainGovernor_Forward:test_ForwardRevert() (gas: 24296) +ArbitrumCrossDomainGovernor_Forward:test_NotCallableByUnknownAddress() (gas: 18233) +ArbitrumCrossDomainGovernor_ForwardDelegate:test_BubbleUpRevert() (gas: 19361) +ArbitrumCrossDomainGovernor_ForwardDelegate:test_CallableByCrossDomainMessengerAddressOrL1Owner() (gas: 60874) +ArbitrumCrossDomainGovernor_ForwardDelegate:test_CallableByL2Owner() (gas: 63003) +ArbitrumCrossDomainGovernor_ForwardDelegate:test_NotCallableByUnknownAddress() (gas: 18288) +ArbitrumCrossDomainGovernor_ForwardDelegate:test_RevertsBatchWhenOneCallFails() (gas: 64368) +ArbitrumCrossDomainGovernor_TransferL1Ownership:test_CallableByL1Owner() (gas: 41453) +ArbitrumCrossDomainGovernor_TransferL1Ownership:test_CallableByL1OwnerOrZeroAddress() (gas: 19290) +ArbitrumCrossDomainGovernor_TransferL1Ownership:test_NotCallableByL2Owner() (gas: 18659) +ArbitrumCrossDomainGovernor_TransferL1Ownership:test_NotCallableByNonOwners() (gas: 13242) +ArbitrumSequencerUptimeFeed_AggregatorV3Interface:test_AggregatorV3Interface() (gas: 104880) +ArbitrumSequencerUptimeFeed_AggregatorV3Interface:test_Return0WhenRoundDoesNotExistYet() (gas: 19973) +ArbitrumSequencerUptimeFeed_Constants:test_InitialState() (gas: 8496) +ArbitrumSequencerUptimeFeed_ProtectReadsOnAggregatorV2V3InterfaceFunctions:test_AggregatorV2V3InterfaceAllowReadsIfConsumingContractIsWhitelisted() (gas: 604370) +ArbitrumSequencerUptimeFeed_ProtectReadsOnAggregatorV2V3InterfaceFunctions:test_AggregatorV2V3InterfaceDisallowReadsIfConsumingContractIsNotWhitelisted() (gas: 574432) +ArbitrumSequencerUptimeFeed_UpdateStatus:test_IgnoreOutOfOrderUpdates() (gas: 99663) +ArbitrumSequencerUptimeFeed_UpdateStatus:test_RevertIfNotL2CrossDomainMessengerAddr() (gas: 15453) +ArbitrumSequencerUptimeFeed_UpdateStatus:test_UpdateStatusWhenStatusChangeAndNoTimeChange() (gas: 114637) +ArbitrumSequencerUptimeFeed_UpdateStatus:test_UpdateStatusWhenStatusChangeAndTimeChange() (gas: 114720) +ArbitrumValidator_Validate:test_PostSequencerOffline() (gas: 69068) +OptimismCrossDomainForwarder_AcceptL1Ownership:test_CallableByPendingL1Owner() (gas: 47162) +OptimismCrossDomainForwarder_AcceptL1Ownership:test_NotCallableByNonPendingOwners() (gas: 22163) +OptimismCrossDomainForwarder_Constructor:test_InitialState() (gas: 21976) +OptimismCrossDomainForwarder_Forward:test_Forward() (gas: 58281) +OptimismCrossDomainForwarder_Forward:test_ForwardRevert() (gas: 32583) +OptimismCrossDomainForwarder_Forward:test_NotCallableByUnknownAddress() (gas: 13910) +OptimismCrossDomainForwarder_TransferL1Ownership:test_CallableByL1Owner() (gas: 48945) +OptimismCrossDomainForwarder_TransferL1Ownership:test_CallableByL1OwnerOrZeroAddress() (gas: 28768) +OptimismCrossDomainForwarder_TransferL1Ownership:test_NotCallableByL2Owner() (gas: 16470) +OptimismCrossDomainForwarder_TransferL1Ownership:test_NotCallableByNonOwners() (gas: 11053) +OptimismCrossDomainGovernor_AcceptL1Ownership:test_CallableByPendingL1Owner() (gas: 47162) +OptimismCrossDomainGovernor_AcceptL1Ownership:test_NotCallableByNonPendingOwners() (gas: 22163) +OptimismCrossDomainGovernor_Constructor:test_InitialState() (gas: 21999) +OptimismCrossDomainGovernor_Forward:test_CallableByL2Owner() (gas: 47846) +OptimismCrossDomainGovernor_Forward:test_Forward() (gas: 58352) +OptimismCrossDomainGovernor_Forward:test_ForwardRevert() (gas: 32619) +OptimismCrossDomainGovernor_Forward:test_NotCallableByUnknownAddress() (gas: 16047) +OptimismCrossDomainGovernor_ForwardDelegate:test_BubbleUpRevert() (gas: 29170) +OptimismCrossDomainGovernor_ForwardDelegate:test_CallableByCrossDomainMessengerAddressOrL1Owner() (gas: 72942) +OptimismCrossDomainGovernor_ForwardDelegate:test_CallableByL2Owner() (gas: 72947) +OptimismCrossDomainGovernor_ForwardDelegate:test_NotCallableByUnknownAddress() (gas: 16102) +OptimismCrossDomainGovernor_ForwardDelegate:test_RevertsBatchWhenOneCallFails() (gas: 76156) +OptimismCrossDomainGovernor_TransferL1Ownership:test_CallableByL1Owner() (gas: 48945) +OptimismCrossDomainGovernor_TransferL1Ownership:test_CallableByL1OwnerOrZeroAddress() (gas: 28768) +OptimismCrossDomainGovernor_TransferL1Ownership:test_NotCallableByL2Owner() (gas: 16470) +OptimismCrossDomainGovernor_TransferL1Ownership:test_NotCallableByNonOwners() (gas: 11053) +OptimismSequencerUptimeFeed_AggregatorV3Interface:test_AggregatorV3Interface() (gas: 72382) +OptimismSequencerUptimeFeed_AggregatorV3Interface:test_RevertGetAnswerWhenRoundDoesNotExistYet() (gas: 17653) +OptimismSequencerUptimeFeed_AggregatorV3Interface:test_RevertGetRoundDataWhenRoundDoesNotExistYet() (gas: 17893) +OptimismSequencerUptimeFeed_AggregatorV3Interface:test_RevertGetTimestampWhenRoundDoesNotExistYet() (gas: 17642) +OptimismSequencerUptimeFeed_Constructor:test_InitialState() (gas: 22028) +OptimismSequencerUptimeFeed_ProtectReadsOnAggregatorV2V3InterfaceFunctions:test_AggregatorV2V3InterfaceAllowReadsIfConsumingContractIsWhitelisted() (gas: 601594) +OptimismSequencerUptimeFeed_ProtectReadsOnAggregatorV2V3InterfaceFunctions:test_AggregatorV2V3InterfaceDisallowReadsIfConsumingContractIsNotWhitelisted() (gas: 574437) +OptimismSequencerUptimeFeed_UpdateStatus:test_IgnoreOutOfOrderUpdates() (gas: 67861) +OptimismSequencerUptimeFeed_UpdateStatus:test_RevertIfNotL2CrossDomainMessengerAddr() (gas: 13118) +OptimismSequencerUptimeFeed_UpdateStatus:test_RevertIfNotL2CrossDomainMessengerAddrAndNotL1SenderAddr() (gas: 23536) +OptimismSequencerUptimeFeed_UpdateStatus:test_UpdateStatusWhenNoChange() (gas: 77316) +OptimismSequencerUptimeFeed_UpdateStatus:test_UpdateStatusWhenStatusChangeAndNoTimeChange() (gas: 96170) +OptimismSequencerUptimeFeed_UpdateStatus:test_UpdateStatusWhenStatusChangeAndTimeChange() (gas: 96253) +OptimismValidator_SetGasLimit:test_CorrectlyUpdatesTheGasLimit() (gas: 18649) +OptimismValidator_Validate:test_PostSequencerOffline() (gas: 74813) +OptimismValidator_Validate:test_PostSequencerStatusWhenThereIsNotStatusChange() (gas: 74847) +OptimismValidator_Validate:test_RevertsIfCalledByAnAccountWithNoAccess() (gas: 15571) +ScrollCrossDomainForwarder_AcceptL1Ownership:test_CallableByPendingL1Owner() (gas: 47252) +ScrollCrossDomainForwarder_AcceptL1Ownership:test_NotCallableByNonPendingOwners() (gas: 22215) +ScrollCrossDomainForwarder_Constructor:test_InitialState() (gas: 21652) +ScrollCrossDomainForwarder_Forward:test_Forward() (gas: 58348) +ScrollCrossDomainForwarder_Forward:test_ForwardRevert() (gas: 32641) +ScrollCrossDomainForwarder_Forward:test_NotCallableByUnknownAddress() (gas: 13910) +ScrollCrossDomainForwarder_TransferL1Ownership:test_CallableByL1Owner() (gas: 49011) +ScrollCrossDomainForwarder_TransferL1Ownership:test_CallableByL1OwnerOrZeroAddress() (gas: 28828) +ScrollCrossDomainForwarder_TransferL1Ownership:test_NotCallableByL2Owner() (gas: 16470) +ScrollCrossDomainForwarder_TransferL1Ownership:test_NotCallableByNonOwners() (gas: 11053) +ScrollCrossDomainGovernor_AcceptL1Ownership:test_CallableByPendingL1Owner() (gas: 47252) +ScrollCrossDomainGovernor_AcceptL1Ownership:test_NotCallableByNonPendingOwners() (gas: 22215) +ScrollCrossDomainGovernor_Constructor:test_InitialState() (gas: 21675) +ScrollCrossDomainGovernor_Forward:test_CallableByL2Owner() (gas: 47841) +ScrollCrossDomainGovernor_Forward:test_Forward() (gas: 58414) +ScrollCrossDomainGovernor_Forward:test_ForwardRevert() (gas: 32674) +ScrollCrossDomainGovernor_Forward:test_NotCallableByUnknownAddress() (gas: 16044) +ScrollCrossDomainGovernor_ForwardDelegate:test_BubbleUpRevert() (gas: 29231) +ScrollCrossDomainGovernor_ForwardDelegate:test_CallableByCrossDomainMessengerAddressOrL1Owner() (gas: 73009) +ScrollCrossDomainGovernor_ForwardDelegate:test_CallableByL2Owner() (gas: 73014) +ScrollCrossDomainGovernor_ForwardDelegate:test_NotCallableByUnknownAddress() (gas: 16099) +ScrollCrossDomainGovernor_ForwardDelegate:test_RevertsBatchWhenOneCallFails() (gas: 76224) +ScrollCrossDomainGovernor_TransferL1Ownership:test_CallableByL1Owner() (gas: 49011) +ScrollCrossDomainGovernor_TransferL1Ownership:test_CallableByL1OwnerOrZeroAddress() (gas: 28828) +ScrollCrossDomainGovernor_TransferL1Ownership:test_NotCallableByL2Owner() (gas: 16470) +ScrollCrossDomainGovernor_TransferL1Ownership:test_NotCallableByNonOwners() (gas: 11053) +ScrollSequencerUptimeFeed_AggregatorV3Interface:test_AggregatorV3Interface() (gas: 72405) +ScrollSequencerUptimeFeed_AggregatorV3Interface:test_RevertGetAnswerWhenRoundDoesNotExistYet() (gas: 17653) +ScrollSequencerUptimeFeed_AggregatorV3Interface:test_RevertGetRoundDataWhenRoundDoesNotExistYet() (gas: 17893) +ScrollSequencerUptimeFeed_AggregatorV3Interface:test_RevertGetTimestampWhenRoundDoesNotExistYet() (gas: 17642) +ScrollSequencerUptimeFeed_Constructor:test_InitialState() (gas: 173913) +ScrollSequencerUptimeFeed_ProtectReadsOnAggregatorV2V3InterfaceFunctions:test_AggregatorV2V3InterfaceAllowReadsIfConsumingContractIsWhitelisted() (gas: 601594) +ScrollSequencerUptimeFeed_ProtectReadsOnAggregatorV2V3InterfaceFunctions:test_AggregatorV2V3InterfaceDisallowReadsIfConsumingContractIsNotWhitelisted() (gas: 574437) +ScrollSequencerUptimeFeed_UpdateStatus:test_IgnoreOutOfOrderUpdates() (gas: 67907) +ScrollSequencerUptimeFeed_UpdateStatus:test_RevertIfNotL2CrossDomainMessengerAddr() (gas: 13118) +ScrollSequencerUptimeFeed_UpdateStatus:test_RevertIfNotL2CrossDomainMessengerAddrAndNotL1SenderAddr() (gas: 23536) +ScrollSequencerUptimeFeed_UpdateStatus:test_UpdateStatusWhenNoChange() (gas: 77362) +ScrollSequencerUptimeFeed_UpdateStatus:test_UpdateStatusWhenStatusChangeAndNoTimeChange() (gas: 96216) +ScrollSequencerUptimeFeed_UpdateStatus:test_UpdateStatusWhenStatusChangeAndTimeChange() (gas: 96299) +ScrollValidator_SetGasLimit:test_CorrectlyUpdatesTheGasLimit() (gas: 18783) +ScrollValidator_Validate:test_PostSequencerOffline() (gas: 78349) +ScrollValidator_Validate:test_PostSequencerStatusWhenThereIsNotStatusChange() (gas: 78389) +ScrollValidator_Validate:test_RevertsIfCalledByAnAccountWithNoAccess() (gas: 15571) +ZKSyncSequencerUptimeFeed_AggregatorV3Interface:test_AggregatorV3Interface() (gas: 67184) +ZKSyncSequencerUptimeFeed_AggregatorV3Interface:test_RevertGetAnswerWhenRoundDoesNotExistYet() (gas: 17653) +ZKSyncSequencerUptimeFeed_AggregatorV3Interface:test_RevertGetRoundDataWhenRoundDoesNotExistYet() (gas: 17893) +ZKSyncSequencerUptimeFeed_AggregatorV3Interface:test_RevertGetTimestampWhenRoundDoesNotExistYet() (gas: 17642) +ZKSyncSequencerUptimeFeed_Constructor:test_InitialState() (gas: 22032) +ZKSyncSequencerUptimeFeed_ProtectReadsOnAggregatorV2V3InterfaceFunctions:test_AggregatorV2V3InterfaceAllowReadsIfConsumingContractIsWhitelisted() (gas: 601614) +ZKSyncSequencerUptimeFeed_ProtectReadsOnAggregatorV2V3InterfaceFunctions:test_AggregatorV2V3InterfaceDisallowReadsIfConsumingContractIsNotWhitelisted() (gas: 574443) +ZKSyncSequencerUptimeFeed_UpdateStatus:test_IgnoreOutOfOrderUpdates() (gas: 61936) +ZKSyncSequencerUptimeFeed_UpdateStatus:test_RevertIfNotL2CrossDomainMessengerAddr() (gas: 13064) +ZKSyncSequencerUptimeFeed_UpdateStatus:test_UpdateStatusWhenNoChange() (gas: 71428) +ZKSyncSequencerUptimeFeed_UpdateStatus:test_UpdateStatusWhenStatusChangeAndNoTimeChange() (gas: 90253) +ZKSyncSequencerUptimeFeed_UpdateStatus:test_UpdateStatusWhenStatusChangeAndTimeChange() (gas: 90336) +ZKSyncValidator_Constructor:test_ConstructingRevertedWithInvalidChainId() (gas: 103748) +ZKSyncValidator_Constructor:test_ConstructingRevertedWithZeroL1BridgeAddress() (gas: 81463) +ZKSyncValidator_Constructor:test_ConstructingRevertedWithZeroL2UpdateFeedAddress() (gas: 81475) +ZKSyncValidator_GetChainId:test_CorrectlyGetsTheChainId() (gas: 8350) +ZKSyncValidator_GetSetL2GasPerPubdataByteLimit:test_CorrectlyGetsAndUpdatesTheGasPerPubdataByteLimit() (gas: 18909) +ZKSyncValidator_Validate:test_PostSequencerOffline() (gas: 52260) +ZKSyncValidator_Validate:test_PostSequencerStatusWhenThereIsNotStatusChange() (gas: 52327) +ZKSyncValidator_Validate:test_RevertsIfCalledByAnAccountWithNoAccess() (gas: 15638) \ No newline at end of file diff --git a/contracts/gas-snapshots/liquiditymanager.gas-snapshot b/contracts/gas-snapshots/liquiditymanager.gas-snapshot index bc545b69d38..435e79b002e 100644 --- a/contracts/gas-snapshots/liquiditymanager.gas-snapshot +++ b/contracts/gas-snapshots/liquiditymanager.gas-snapshot @@ -3,14 +3,14 @@ LiquidityManager_addLiquidity:test_addLiquiditySuccess() (gas: 279198) LiquidityManager_rebalanceLiquidity:test_InsufficientLiquidityReverts() (gas: 206764) LiquidityManager_rebalanceLiquidity:test_InvalidRemoteChainReverts() (gas: 192374) LiquidityManager_rebalanceLiquidity:test_rebalanceBetweenPoolsSuccess() (gas: 9141798) -LiquidityManager_rebalanceLiquidity:test_rebalanceBetweenPoolsSuccess_AlreadyFinalized() (gas: 9435757) -LiquidityManager_rebalanceLiquidity:test_rebalanceBetweenPools_MultiStageFinalization() (gas: 9430897) -LiquidityManager_rebalanceLiquidity:test_rebalanceBetweenPools_NativeRewrap() (gas: 9360730) -LiquidityManager_rebalanceLiquidity:test_rebalanceLiquiditySuccess() (gas: 382928) +LiquidityManager_rebalanceLiquidity:test_rebalanceBetweenPoolsSuccess_AlreadyFinalized() (gas: 8942122) +LiquidityManager_rebalanceLiquidity:test_rebalanceBetweenPools_MultiStageFinalization() (gas: 8937262) +LiquidityManager_rebalanceLiquidity:test_rebalanceBetweenPools_NativeRewrap() (gas: 8865000) +LiquidityManager_rebalanceLiquidity:test_rebalanceLiquiditySuccess() (gas: 382946) LiquidityManager_receive:test_receive_success() (gas: 21182) LiquidityManager_removeLiquidity:test_InsufficientLiquidityReverts() (gas: 184959) LiquidityManager_removeLiquidity:test_OnlyFinanceRoleReverts() (gas: 10872) -LiquidityManager_removeLiquidity:test_removeLiquiditySuccess() (gas: 236361) +LiquidityManager_removeLiquidity:test_removeLiquiditySuccess() (gas: 236379) LiquidityManager_setCrossChainRebalancer:test_OnlyOwnerReverts() (gas: 17005) LiquidityManager_setCrossChainRebalancer:test_ZeroAddressReverts() (gas: 21669) LiquidityManager_setCrossChainRebalancer:test_ZeroChainSelectorReverts() (gas: 13099) @@ -19,7 +19,7 @@ LiquidityManager_setFinanceRole:test_OnlyOwnerReverts() (gas: 10987) LiquidityManager_setFinanceRole:test_setFinanceRoleSuccess() (gas: 21836) LiquidityManager_setLocalLiquidityContainer:test_OnlyOwnerReverts() (gas: 11030) LiquidityManager_setLocalLiquidityContainer:test_ReverstWhen_CalledWithTheZeroAddress() (gas: 10621) -LiquidityManager_setLocalLiquidityContainer:test_setLocalLiquidityContainerSuccess() (gas: 3976150) +LiquidityManager_setLocalLiquidityContainer:test_setLocalLiquidityContainerSuccess() (gas: 3479905) LiquidityManager_setMinimumLiquidity:test_OnlyOwnerReverts() (gas: 10925) LiquidityManager_setMinimumLiquidity:test_setMinimumLiquiditySuccess() (gas: 36389) LiquidityManager_withdrawERC20:test_withdrawERC20Reverts() (gas: 180396) diff --git a/contracts/gas-snapshots/llo-feeds.gas-snapshot b/contracts/gas-snapshots/llo-feeds.gas-snapshot index 44d08f26645..99f2fcc3430 100644 --- a/contracts/gas-snapshots/llo-feeds.gas-snapshot +++ b/contracts/gas-snapshots/llo-feeds.gas-snapshot @@ -35,11 +35,11 @@ ConfiguratorSetProductionConfigTest:test_revertsIfNotEnoughSigners() (gas: 95951 ConfiguratorSetProductionConfigTest:test_revertsIfOnchainConfigIsInvalid() (gas: 60885) ConfiguratorSetProductionConfigTest:test_revertsIfSetWithTooManySigners() (gas: 107412) ConfiguratorSetProductionConfigTest:test_supportsHigherVersionsIgnoringExcessOnchainConfig() (gas: 125099) -ConfiguratorSetStagingConfigTest:test_correctlyUpdatesTheConfig() (gas: 266041) +ConfiguratorSetStagingConfigTest:test_correctlyUpdatesTheConfig() (gas: 265921) ConfiguratorSetStagingConfigTest:test_revertsIfCalledByNonOwner() (gas: 266528) ConfiguratorSetStagingConfigTest:test_revertsIfFaultToleranceIsZero() (gas: 264142) ConfiguratorSetStagingConfigTest:test_revertsIfNotEnoughSigners() (gas: 95920) -ConfiguratorSetStagingConfigTest:test_revertsIfOnchainConfigIsInvalid() (gas: 85217) +ConfiguratorSetStagingConfigTest:test_revertsIfOnchainConfigIsInvalid() (gas: 67763) ConfiguratorSetStagingConfigTest:test_revertsIfSetWithTooManySigners() (gas: 107392) ConfiguratorTest:testSupportsInterface() (gas: 8367) ConfiguratorTest:testTypeAndVersion() (gas: 9683) diff --git a/contracts/gas-snapshots/shared.gas-snapshot b/contracts/gas-snapshots/shared.gas-snapshot index 54475701734..755a2c6aaa5 100644 --- a/contracts/gas-snapshots/shared.gas-snapshot +++ b/contracts/gas-snapshots/shared.gas-snapshot @@ -1,111 +1,100 @@ -AuthorizedCallers_applyAuthorizedCallerUpdates:test_AddAndRemove_Success() (gas: 124848) -AuthorizedCallers_applyAuthorizedCallerUpdates:test_OnlyAdd_Success() (gas: 132793) -AuthorizedCallers_applyAuthorizedCallerUpdates:test_OnlyCallableByOwner_Revert() (gas: 12218) -AuthorizedCallers_applyAuthorizedCallerUpdates:test_OnlyRemove_Success() (gas: 44833) -AuthorizedCallers_applyAuthorizedCallerUpdates:test_RemoveThenAdd_Success() (gas: 56901) -AuthorizedCallers_applyAuthorizedCallerUpdates:test_SkipRemove_Success() (gas: 31911) -AuthorizedCallers_applyAuthorizedCallerUpdates:test_ZeroAddressNotAllowed_Revert() (gas: 64612) -AuthorizedCallers_constructor:test_ZeroAddressNotAllowed_Revert() (gas: 64589) -AuthorizedCallers_constructor:test_constructor_Success() (gas: 663486) -BurnMintERC20_approve:test_approve() (gas: 57609) -BurnMintERC20_burn:test_BasicBurn() (gas: 153528) -BurnMintERC20_burnFrom:test_BurnFrom() (gas: 57965) -BurnMintERC20_burnFromAlias:test_burn() (gas: 58009) -BurnMintERC20_constructor:test_Constructor() (gas: 1680059) -BurnMintERC20_getCCIPAdmin:test_getCCIPAdmin() (gas: 10544) -BurnMintERC20_getCCIPAdmin:test_setCCIPAdmin() (gas: 21562) -BurnMintERC20_grantMintAndBurnRoles:test_GrantMintAndBurnRoles() (gas: 79089) -BurnMintERC20_mint:test_mint() (gas: 101815) -BurnMintERC20_supportsInterface:test_SupportsInterface() (gas: 11202) -BurnMintERC20_transfer:test_transfer() (gas: 42318) -BurnMintERC677_approve:testApproveSuccess() (gas: 55477) -BurnMintERC677_approve:testInvalidAddressReverts() (gas: 10653) -BurnMintERC677_burn:testBasicBurnSuccess() (gas: 172022) -BurnMintERC677_burn:testBurnFromZeroAddressReverts() (gas: 47166) -BurnMintERC677_burn:testExceedsBalanceReverts() (gas: 21816) -BurnMintERC677_burn:testSenderNotBurnerReverts() (gas: 13346) -BurnMintERC677_burnFrom:testBurnFromSuccess() (gas: 57928) -BurnMintERC677_burnFrom:testExceedsBalanceReverts() (gas: 35838) -BurnMintERC677_burnFrom:testInsufficientAllowanceReverts() (gas: 21824) -BurnMintERC677_burnFrom:testSenderNotBurnerReverts() (gas: 13346) -BurnMintERC677_burnFromAlias:testBurnFromSuccess() (gas: 57955) -BurnMintERC677_burnFromAlias:testExceedsBalanceReverts() (gas: 35854) -BurnMintERC677_burnFromAlias:testInsufficientAllowanceReverts() (gas: 21844) -BurnMintERC677_burnFromAlias:testSenderNotBurnerReverts() (gas: 13366) -BurnMintERC677_constructor:testConstructorSuccess() (gas: 1651040) -BurnMintERC677_decreaseApproval:testDecreaseApprovalSuccess() (gas: 31049) -BurnMintERC677_grantMintAndBurnRoles:testGrantMintAndBurnRolesSuccess() (gas: 121279) -BurnMintERC677_grantRole:testGrantBurnAccessSuccess() (gas: 53402) -BurnMintERC677_grantRole:testGrantManySuccess() (gas: 937593) -BurnMintERC677_grantRole:testGrantMintAccessSuccess() (gas: 94280) -BurnMintERC677_increaseApproval:testIncreaseApprovalSuccess() (gas: 44052) -BurnMintERC677_mint:testBasicMintSuccess() (gas: 149664) -BurnMintERC677_mint:testMaxSupplyExceededReverts() (gas: 50323) -BurnMintERC677_mint:testSenderNotMinterReverts() (gas: 11182) -BurnMintERC677_supportsInterface:testConstructorSuccess() (gas: 12455) -BurnMintERC677_transfer:testInvalidAddressReverts() (gas: 10629) -BurnMintERC677_transfer:testTransferSuccess() (gas: 42279) -CallWithExactGas__callWithExactGas:test_CallWithExactGasReceiverErrorSuccess() (gas: 65883) -CallWithExactGas__callWithExactGas:test_CallWithExactGasSafeReturnDataExactGas() (gas: 18293) -CallWithExactGas__callWithExactGas:test_NoContractReverts() (gas: 11544) -CallWithExactGas__callWithExactGas:test_NoGasForCallExactCheckReverts() (gas: 15760) -CallWithExactGas__callWithExactGas:test_NotEnoughGasForCallReverts() (gas: 16210) -CallWithExactGas__callWithExactGasEvenIfTargetIsNoContract:test_CallWithExactGasEvenIfTargetIsNoContractExactGasSuccess() (gas: 20033) -CallWithExactGas__callWithExactGasEvenIfTargetIsNoContract:test_CallWithExactGasEvenIfTargetIsNoContractReceiverErrorSuccess() (gas: 66394) -CallWithExactGas__callWithExactGasEvenIfTargetIsNoContract:test_NoContractSuccess() (gas: 12942) -CallWithExactGas__callWithExactGasEvenIfTargetIsNoContract:test_NoGasForCallExactCheckReturnFalseSuccess() (gas: 12984) -CallWithExactGas__callWithExactGasEvenIfTargetIsNoContract:test_NotEnoughGasForCallReturnsFalseSuccess() (gas: 13293) -CallWithExactGas__callWithExactGasSafeReturnData:test_CallWithExactGasSafeReturnDataExactGas() (gas: 20287) -CallWithExactGas__callWithExactGasSafeReturnData:test_NoContractReverts() (gas: 13915) -CallWithExactGas__callWithExactGasSafeReturnData:test_NoGasForCallExactCheckReverts() (gas: 16108) -CallWithExactGas__callWithExactGasSafeReturnData:test_NotEnoughGasForCallReverts() (gas: 16513) -CallWithExactGas__callWithExactGasSafeReturnData:test_callWithExactGasSafeReturnData_ThrowOOGError_Revert() (gas: 36713) -EnumerableMapAddresses_at:testAtSuccess() (gas: 95055) -EnumerableMapAddresses_at:testBytes32AtSuccess() (gas: 94828) -EnumerableMapAddresses_at:testBytesAtSuccess() (gas: 96507) -EnumerableMapAddresses_contains:testBytes32ContainsSuccess() (gas: 93503) -EnumerableMapAddresses_contains:testBytesContainsSuccess() (gas: 93974) -EnumerableMapAddresses_contains:testContainsSuccess() (gas: 93678) -EnumerableMapAddresses_get:testBytes32GetSuccess() (gas: 94238) -EnumerableMapAddresses_get:testBytesGetSuccess() (gas: 95919) -EnumerableMapAddresses_get:testGetSuccess() (gas: 94409) -EnumerableMapAddresses_get_errorMessage:testBytesGetErrorMessageSuccess() (gas: 95852) -EnumerableMapAddresses_get_errorMessage:testGetErrorMessageSuccess() (gas: 94467) -EnumerableMapAddresses_length:testBytes32LengthSuccess() (gas: 72418) -EnumerableMapAddresses_length:testBytesLengthSuccess() (gas: 73035) -EnumerableMapAddresses_length:testLengthSuccess() (gas: 72592) -EnumerableMapAddresses_remove:testBytes32RemoveSuccess() (gas: 73432) -EnumerableMapAddresses_remove:testBytesRemoveSuccess() (gas: 74216) -EnumerableMapAddresses_remove:testRemoveSuccess() (gas: 73651) -EnumerableMapAddresses_set:testBytes32SetSuccess() (gas: 94475) -EnumerableMapAddresses_set:testBytesSetSuccess() (gas: 95405) -EnumerableMapAddresses_set:testSetSuccess() (gas: 94638) -EnumerableMapAddresses_tryGet:testBytes32TryGetSuccess() (gas: 94602) -EnumerableMapAddresses_tryGet:testBytesTryGetSuccess() (gas: 96316) -EnumerableMapAddresses_tryGet:testTryGetSuccess() (gas: 94869) -OpStackBurnMintERC677_constructor:testConstructorSuccess() (gas: 1721342) -OpStackBurnMintERC677_interfaceCompatibility:testBurnCompatibility() (gas: 291244) -OpStackBurnMintERC677_interfaceCompatibility:testMintCompatibility() (gas: 137917) -OpStackBurnMintERC677_interfaceCompatibility:testStaticFunctionsCompatibility() (gas: 13773) -OpStackBurnMintERC677_supportsInterface:testConstructorSuccess() (gas: 12728) -Ownable2Step_acceptOwnership:test_acceptOwnership_MustBeProposedOwner_reverts() (gas: 10353) -Ownable2Step_acceptOwnership:test_acceptOwnership_success() (gas: 31070) -Ownable2Step_constructor:test_constructor_OwnerCannotBeZero_reverts() (gas: 35924) -Ownable2Step_constructor:test_constructor_success() (gas: 10424) -Ownable2Step_onlyOwner:test_onlyOwner_OnlyCallableByOwner_reverts() (gas: 10746) -Ownable2Step_onlyOwner:test_onlyOwner_success() (gas: 7503) -Ownable2Step_transferOwnership:test_transferOwnership_CannotTransferToSelf_reverts() (gas: 10494) -Ownable2Step_transferOwnership:test_transferOwnership_success() (gas: 30124) -SortedSetValidationUtil_CheckIsValidUniqueSubsetTest:test__checkIsValidUniqueSubset_EmptySubset_Reverts() (gas: 5191) -SortedSetValidationUtil_CheckIsValidUniqueSubsetTest:test__checkIsValidUniqueSubset_EmptySuperset_Reverts() (gas: 4522) -SortedSetValidationUtil_CheckIsValidUniqueSubsetTest:test__checkIsValidUniqueSubset_HasDuplicates_Reverts() (gas: 7738) -SortedSetValidationUtil_CheckIsValidUniqueSubsetTest:test__checkIsValidUniqueSubset_NotASubset_Reverts() (gas: 11700) -SortedSetValidationUtil_CheckIsValidUniqueSubsetTest:test__checkIsValidUniqueSubset_SingleElementSubset() (gas: 3908) -SortedSetValidationUtil_CheckIsValidUniqueSubsetTest:test__checkIsValidUniqueSubset_SingleElementSubsetAndSuperset_Equal() (gas: 1459) -SortedSetValidationUtil_CheckIsValidUniqueSubsetTest:test__checkIsValidUniqueSubset_SingleElementSubsetAndSuperset_NotEqual_Reverts() (gas: 6149) -SortedSetValidationUtil_CheckIsValidUniqueSubsetTest:test__checkIsValidUniqueSubset_SubsetEqualsSuperset_NoRevert() (gas: 7830) -SortedSetValidationUtil_CheckIsValidUniqueSubsetTest:test__checkIsValidUniqueSubset_SubsetLargerThanSuperset_Reverts() (gas: 15363) -SortedSetValidationUtil_CheckIsValidUniqueSubsetTest:test__checkIsValidUniqueSubset_SupersetHasDuplicates_Reverts() (gas: 8767) -SortedSetValidationUtil_CheckIsValidUniqueSubsetTest:test__checkIsValidUniqueSubset_UnsortedSubset_Reverts() (gas: 7106) -SortedSetValidationUtil_CheckIsValidUniqueSubsetTest:test__checkIsValidUniqueSubset_UnsortedSuperset_Reverts() (gas: 8947) -SortedSetValidationUtil_CheckIsValidUniqueSubsetTest:test__checkIsValidUniqueSubset_ValidSubset_Success() (gas: 5653) \ No newline at end of file +AuthorizedCallers_applyAuthorizedCallerUpdates:test_AddAndRemove_Success() (gas: 124942) +AuthorizedCallers_applyAuthorizedCallerUpdates:test_OnlyAdd_Success() (gas: 132869) +AuthorizedCallers_applyAuthorizedCallerUpdates:test_OnlyCallableByOwner_Revert() (gas: 12238) +AuthorizedCallers_applyAuthorizedCallerUpdates:test_OnlyRemove_Success() (gas: 44907) +AuthorizedCallers_applyAuthorizedCallerUpdates:test_RemoveThenAdd_Success() (gas: 56991) +AuthorizedCallers_applyAuthorizedCallerUpdates:test_SkipRemove_Success() (gas: 31961) +AuthorizedCallers_applyAuthorizedCallerUpdates:test_ZeroAddressNotAllowed_Revert() (gas: 64413) +AuthorizedCallers_constructor:test_ZeroAddressNotAllowed_Revert() (gas: 64390) +AuthorizedCallers_constructor:test_constructor_Success() (gas: 674931) +BurnMintERC677_approve:testApproveSuccess() (gas: 55512) +BurnMintERC677_approve:testInvalidAddressReverts() (gas: 10663) +BurnMintERC677_burn:testBasicBurnSuccess() (gas: 172100) +BurnMintERC677_burn:testBurnFromZeroAddressReverts() (gas: 47201) +BurnMintERC677_burn:testExceedsBalanceReverts() (gas: 21841) +BurnMintERC677_burn:testSenderNotBurnerReverts() (gas: 13359) +BurnMintERC677_burnFrom:testBurnFromSuccess() (gas: 57959) +BurnMintERC677_burnFrom:testExceedsBalanceReverts() (gas: 35864) +BurnMintERC677_burnFrom:testInsufficientAllowanceReverts() (gas: 21849) +BurnMintERC677_burnFrom:testSenderNotBurnerReverts() (gas: 13359) +BurnMintERC677_burnFromAlias:testBurnFromSuccess() (gas: 57985) +BurnMintERC677_burnFromAlias:testExceedsBalanceReverts() (gas: 35880) +BurnMintERC677_burnFromAlias:testInsufficientAllowanceReverts() (gas: 21869) +BurnMintERC677_burnFromAlias:testSenderNotBurnerReverts() (gas: 13379) +BurnMintERC677_constructor:testConstructorSuccess() (gas: 1672812) +BurnMintERC677_decreaseApproval:testDecreaseApprovalSuccess() (gas: 31069) +BurnMintERC677_grantMintAndBurnRoles:testGrantMintAndBurnRolesSuccess() (gas: 121324) +BurnMintERC677_grantRole:testGrantBurnAccessSuccess() (gas: 53442) +BurnMintERC677_grantRole:testGrantManySuccess() (gas: 937759) +BurnMintERC677_grantRole:testGrantMintAccessSuccess() (gas: 94323) +BurnMintERC677_increaseApproval:testIncreaseApprovalSuccess() (gas: 44076) +BurnMintERC677_mint:testBasicMintSuccess() (gas: 149699) +BurnMintERC677_mint:testMaxSupplyExceededReverts() (gas: 50363) +BurnMintERC677_mint:testSenderNotMinterReverts() (gas: 11195) +BurnMintERC677_supportsInterface:testConstructorSuccess() (gas: 12476) +BurnMintERC677_transfer:testInvalidAddressReverts() (gas: 10639) +BurnMintERC677_transfer:testTransferSuccess() (gas: 42299) +CallWithExactGas__callWithExactGas:test_CallWithExactGasReceiverErrorSuccess() (gas: 65949) +CallWithExactGas__callWithExactGas:test_CallWithExactGasSafeReturnDataExactGas() (gas: 18324) +CallWithExactGas__callWithExactGas:test_NoContractReverts() (gas: 11559) +CallWithExactGas__callWithExactGas:test_NoGasForCallExactCheckReverts() (gas: 15788) +CallWithExactGas__callWithExactGas:test_NotEnoughGasForCallReverts() (gas: 16241) +CallWithExactGas__callWithExactGasEvenIfTargetIsNoContract:test_CallWithExactGasEvenIfTargetIsNoContractExactGasSuccess() (gas: 20073) +CallWithExactGas__callWithExactGasEvenIfTargetIsNoContract:test_CallWithExactGasEvenIfTargetIsNoContractReceiverErrorSuccess() (gas: 66461) +CallWithExactGas__callWithExactGasEvenIfTargetIsNoContract:test_NoContractSuccess() (gas: 12962) +CallWithExactGas__callWithExactGasEvenIfTargetIsNoContract:test_NoGasForCallExactCheckReturnFalseSuccess() (gas: 13005) +CallWithExactGas__callWithExactGasEvenIfTargetIsNoContract:test_NotEnoughGasForCallReturnsFalseSuccess() (gas: 13317) +CallWithExactGas__callWithExactGasSafeReturnData:test_CallWithExactGasSafeReturnDataExactGas() (gas: 20331) +CallWithExactGas__callWithExactGasSafeReturnData:test_NoContractReverts() (gas: 13939) +CallWithExactGas__callWithExactGasSafeReturnData:test_NoGasForCallExactCheckReverts() (gas: 16139) +CallWithExactGas__callWithExactGasSafeReturnData:test_NotEnoughGasForCallReverts() (gas: 16547) +CallWithExactGas__callWithExactGasSafeReturnData:test_callWithExactGasSafeReturnData_ThrowOOGError_Revert() (gas: 36755) +EnumerableMapAddresses_at:testAtSuccess() (gas: 95086) +EnumerableMapAddresses_at:testBytes32AtSuccess() (gas: 94855) +EnumerableMapAddresses_at:testBytesAtSuccess() (gas: 96542) +EnumerableMapAddresses_contains:testBytes32ContainsSuccess() (gas: 93518) +EnumerableMapAddresses_contains:testBytesContainsSuccess() (gas: 93990) +EnumerableMapAddresses_contains:testContainsSuccess() (gas: 93696) +EnumerableMapAddresses_get:testBytes32GetSuccess() (gas: 94256) +EnumerableMapAddresses_get:testBytesGetSuccess() (gas: 95945) +EnumerableMapAddresses_get:testGetSuccess() (gas: 94431) +EnumerableMapAddresses_get_errorMessage:testBytesGetErrorMessageSuccess() (gas: 95878) +EnumerableMapAddresses_get_errorMessage:testGetErrorMessageSuccess() (gas: 94489) +EnumerableMapAddresses_length:testBytes32LengthSuccess() (gas: 72445) +EnumerableMapAddresses_length:testBytesLengthSuccess() (gas: 73064) +EnumerableMapAddresses_length:testLengthSuccess() (gas: 72623) +EnumerableMapAddresses_remove:testBytes32RemoveSuccess() (gas: 73462) +EnumerableMapAddresses_remove:testBytesRemoveSuccess() (gas: 74249) +EnumerableMapAddresses_remove:testRemoveSuccess() (gas: 73686) +EnumerableMapAddresses_set:testBytes32SetSuccess() (gas: 94496) +EnumerableMapAddresses_set:testBytesSetSuccess() (gas: 95428) +EnumerableMapAddresses_set:testSetSuccess() (gas: 94663) +EnumerableMapAddresses_tryGet:testBytes32TryGetSuccess() (gas: 94622) +EnumerableMapAddresses_tryGet:testBytesTryGetSuccess() (gas: 96345) +EnumerableMapAddresses_tryGet:testTryGetSuccess() (gas: 94893) +OpStackBurnMintERC677_constructor:testConstructorSuccess() (gas: 1743682) +OpStackBurnMintERC677_interfaceCompatibility:testBurnCompatibility() (gas: 291483) +OpStackBurnMintERC677_interfaceCompatibility:testMintCompatibility() (gas: 137957) +OpStackBurnMintERC677_interfaceCompatibility:testStaticFunctionsCompatibility() (gas: 13781) +OpStackBurnMintERC677_supportsInterface:testConstructorSuccess() (gas: 12752) +Ownable2Step_acceptOwnership:test_acceptOwnership_MustBeProposedOwner_reverts() (gas: 10360) +Ownable2Step_acceptOwnership:test_acceptOwnership_success() (gas: 31088) +Ownable2Step_constructor:test_constructor_OwnerCannotBeZero_reverts() (gas: 35858) +Ownable2Step_constructor:test_constructor_success() (gas: 10428) +Ownable2Step_onlyOwner:test_onlyOwner_OnlyCallableByOwner_reverts() (gas: 10754) +Ownable2Step_onlyOwner:test_onlyOwner_success() (gas: 7506) +Ownable2Step_transferOwnership:test_transferOwnership_CannotTransferToSelf_reverts() (gas: 10501) +Ownable2Step_transferOwnership:test_transferOwnership_success() (gas: 30140) +SortedSetValidationUtil_CheckIsValidUniqueSubsetTest:test__checkIsValidUniqueSubset_EmptySubset_Reverts() (gas: 5208) +SortedSetValidationUtil_CheckIsValidUniqueSubsetTest:test__checkIsValidUniqueSubset_EmptySuperset_Reverts() (gas: 4535) +SortedSetValidationUtil_CheckIsValidUniqueSubsetTest:test__checkIsValidUniqueSubset_HasDuplicates_Reverts() (gas: 7761) +SortedSetValidationUtil_CheckIsValidUniqueSubsetTest:test__checkIsValidUniqueSubset_NotASubset_Reverts() (gas: 11733) +SortedSetValidationUtil_CheckIsValidUniqueSubsetTest:test__checkIsValidUniqueSubset_SingleElementSubset() (gas: 3922) +SortedSetValidationUtil_CheckIsValidUniqueSubsetTest:test__checkIsValidUniqueSubset_SingleElementSubsetAndSuperset_Equal() (gas: 1464) +SortedSetValidationUtil_CheckIsValidUniqueSubsetTest:test__checkIsValidUniqueSubset_SingleElementSubsetAndSuperset_NotEqual_Reverts() (gas: 6172) +SortedSetValidationUtil_CheckIsValidUniqueSubsetTest:test__checkIsValidUniqueSubset_SubsetEqualsSuperset_NoRevert() (gas: 7859) +SortedSetValidationUtil_CheckIsValidUniqueSubsetTest:test__checkIsValidUniqueSubset_SubsetLargerThanSuperset_Reverts() (gas: 15410) +SortedSetValidationUtil_CheckIsValidUniqueSubsetTest:test__checkIsValidUniqueSubset_SupersetHasDuplicates_Reverts() (gas: 8790) +SortedSetValidationUtil_CheckIsValidUniqueSubsetTest:test__checkIsValidUniqueSubset_UnsortedSubset_Reverts() (gas: 7128) +SortedSetValidationUtil_CheckIsValidUniqueSubsetTest:test__checkIsValidUniqueSubset_UnsortedSuperset_Reverts() (gas: 8970) +SortedSetValidationUtil_CheckIsValidUniqueSubsetTest:test__checkIsValidUniqueSubset_ValidSubset_Success() (gas: 5671) \ No newline at end of file diff --git a/contracts/gas-snapshots/workflow.gas-snapshot b/contracts/gas-snapshots/workflow.gas-snapshot deleted file mode 100644 index bdfd2b24aec..00000000000 --- a/contracts/gas-snapshots/workflow.gas-snapshot +++ /dev/null @@ -1,64 +0,0 @@ -WorkflowRegistryManager_activateVersion:test_WhenTheVersionNumberIsNotActive_AndWhenThereAreNoActiveVersions() (gas: 528769) -WorkflowRegistryManager_addVersion:test_WhenAutoActivateIsFalse() (gas: 265551) -WorkflowRegistryManager_addVersion:test_WhenAutoActivateIsTrue() (gas: 270596) -WorkflowRegistryManager_getActiveVersion:test_WhenAnActiveVersionExists() (gas: 287760) -WorkflowRegistryManager_getActiveVersion:test_WhenNoActiveVersionIsAvailable() (gas: 13258) -WorkflowRegistryManager_getActiveVersionNumber:test_WhenAnActiveVersionExists() (gas: 283885) -WorkflowRegistryManager_getActiveVersionNumber:test_WhenNoActiveVersionIsAvailable() (gas: 10698) -WorkflowRegistryManager_getAllVersions:test_WhenLimitExceedsMaximumPaginationLimit() (gas: 54503) -WorkflowRegistryManager_getAllVersions:test_WhenRequestingWithInvalidStartIndex() (gas: 11338) -WorkflowRegistryManager_getAllVersions:test_WhenRequestingWithValidStartIndexAndLimitWithinBounds() (gas: 40398) -WorkflowRegistryManager_getLatestVersion:test_WhenNoVersionsHaveBeenRegistered() (gas: 12984) -WorkflowRegistryManager_getLatestVersion:test_WhenVersionsHaveBeenRegistered() (gas: 287791) -WorkflowRegistryManager_getLatestVersionNumber:test_WhenNoVersionsHaveBeenRegistered() (gas: 10637) -WorkflowRegistryManager_getLatestVersionNumber:test_WhenVersionsHaveBeenRegistered() (gas: 284134) -WorkflowRegistryManager_getVersion:test_WhenVersionNumberIsNotRegistered() (gas: 13785) -WorkflowRegistryManager_getVersion:test_WhenVersionNumberIsRegistered() (gas: 288169) -WorkflowRegistryManager_getVersionNumberByContractAddressAndChainID:test_WhenAVersionIsRegisteredForTheContractAddressAndChainIDCombination() (gas: 285022) -WorkflowRegistryManager_getVersionNumberByContractAddressAndChainID:test_WhenNoVersionIsRegisteredForTheContractAddressAndChainIDCombination() (gas: 286634) -WorkflowRegistryManager_getVersionNumberByContractAddressAndChainID:test_WhenTheContractAddressIsInvalid() (gas: 284604) -WorkflowRegistry_activateWorkflow:test_WhenTheCallerIsAnAuthorizedAddress() (gas: 517416) -WorkflowRegistry_deleteWorkflow:test_WhenTheCallerIsAnAuthorizedAddress_AndTheDonIDIsAllowed() (gas: 422157) -WorkflowRegistry_deleteWorkflow:test_WhenTheCallerIsAnAuthorizedAddress_AndTheDonIDIsNotAllowed() (gas: 439960) -WorkflowRegistry_getAllAllowedDONs:test_WhenTheRegistryIsLocked() (gas: 47473) -WorkflowRegistry_getAllAllowedDONs:test_WhenTheSetOfAllowedDONsIsEmpty() (gas: 25780) -WorkflowRegistry_getAllAllowedDONs:test_WhenThereAreMultipleAllowedDONs() (gas: 75437) -WorkflowRegistry_getAllAllowedDONs:test_WhenThereIsASingleAllowedDON() (gas: 16590) -WorkflowRegistry_getAllAuthorizedAddresses:test_WhenTheRegistryIsLocked() (gas: 47740) -WorkflowRegistry_getAllAuthorizedAddresses:test_WhenTheSetOfAuthorizedAddressesIsEmpty() (gas: 26152) -WorkflowRegistry_getAllAuthorizedAddresses:test_WhenThereAreMultipleAuthorizedAddresses() (gas: 78270) -WorkflowRegistry_getAllAuthorizedAddresses:test_WhenThereIsASingleAuthorizedAddress() (gas: 16832) -WorkflowRegistry_getWorkflowMetadata:test_WhenTheRegistryIsLocked() (gas: 541532) -WorkflowRegistry_getWorkflowMetadata:test_WhenTheWorkflowDoesNotExist() (gas: 17543) -WorkflowRegistry_getWorkflowMetadata:test_WhenTheWorkflowExistsWithTheOwnerAndName() (gas: 512388) -WorkflowRegistry_getWorkflowMetadataListByDON:test_WhenLimitExceedsTotalWorkflows() (gas: 128146) -WorkflowRegistry_getWorkflowMetadataListByDON:test_WhenLimitIsEqualToTotalWorkflows() (gas: 128035) -WorkflowRegistry_getWorkflowMetadataListByDON:test_WhenLimitIsLessThanTotalWorkflows() (gas: 90141) -WorkflowRegistry_getWorkflowMetadataListByDON:test_WhenStartIs0() (gas: 128075) -WorkflowRegistry_getWorkflowMetadataListByDON:test_WhenStartIsGreaterThan0() (gas: 90098) -WorkflowRegistry_getWorkflowMetadataListByDON:test_WhenStartIsGreaterThanOrEqualToTotalWorkflows() (gas: 13476) -WorkflowRegistry_getWorkflowMetadataListByDON:test_WhenTheDONHasNoWorkflows() (gas: 13410) -WorkflowRegistry_getWorkflowMetadataListByDON:test_WhenTheRegistryIsLocked() (gas: 158899) -WorkflowRegistry_getWorkflowMetadataListByOwner:test_WhenLimitExceedsTotalWorkflows() (gas: 135174) -WorkflowRegistry_getWorkflowMetadataListByOwner:test_WhenLimitIsEqualToTotalWorkflows() (gas: 135073) -WorkflowRegistry_getWorkflowMetadataListByOwner:test_WhenLimitIsLessThanTotalWorkflows() (gas: 95635) -WorkflowRegistry_getWorkflowMetadataListByOwner:test_WhenStartIs0() (gas: 135113) -WorkflowRegistry_getWorkflowMetadataListByOwner:test_WhenStartIsGreaterThan0() (gas: 95592) -WorkflowRegistry_getWorkflowMetadataListByOwner:test_WhenStartIsGreaterThanOrEqualToTotalWorkflows() (gas: 13764) -WorkflowRegistry_getWorkflowMetadataListByOwner:test_WhenTheOwnerHasNoWorkflows() (gas: 14006) -WorkflowRegistry_getWorkflowMetadataListByOwner:test_WhenTheRegistryIsLocked() (gas: 165968) -WorkflowRegistry_lockRegistry:test_WhenTheCallerIsTheContractOwner() (gas: 38758) -WorkflowRegistry_pauseWorkflow:test_WhenTheDonIDIsAllowed_AndTheCallerIsAnAuthorizedAddress() (gas: 517380) -WorkflowRegistry_pauseWorkflow:test_WhenTheDonIDIsAllowed_AndTheCallerIsAnUnauthorizedAddress() (gas: 525183) -WorkflowRegistry_pauseWorkflow:test_WhenTheDonIDIsNotAllowed_AndTheCallerIsAnAuthorizedAddress() (gas: 524942) -WorkflowRegistry_pauseWorkflow:test_WhenTheDonIDIsNotAllowed_AndTheCallerIsAnUnauthorizedAddress() (gas: 529353) -WorkflowRegistry_registerWorkflow:test_WhenTheWorkflowInputsAreAllValid() (gas: 572178) -WorkflowRegistry_requestForceUpdateSecrets:test_WhenTheCallerIsAnAuthorizedAddress_AndTheWorkflowIsInAnAllowedDON() (gas: 936016) -WorkflowRegistry_requestForceUpdateSecrets:test_WhenTheCallerIsAnAuthorizedAddress_AndTheWorkflowIsNotInAnAllowedDON() (gas: 510784) -WorkflowRegistry_requestForceUpdateSecrets:test_WhenTheCallerIsNotAnAuthorizedAddress() (gas: 509138) -WorkflowRegistry_unlockRegistry:test_WhenTheCallerIsTheContractOwner() (gas: 30325) -WorkflowRegistry_updateAllowedDONs:test_WhenTheBoolInputIsFalse() (gas: 29739) -WorkflowRegistry_updateAllowedDONs:test_WhenTheBoolInputIsTrue() (gas: 170296) -WorkflowRegistry_updateAuthorizedAddresses:test_WhenTheBoolInputIsFalse() (gas: 30278) -WorkflowRegistry_updateAuthorizedAddresses:test_WhenTheBoolInputIsTrue() (gas: 175515) -WorkflowRegistry_updateWorkflow:test_WhenTheWorkflowInputsAreAllValid() (gas: 515666) diff --git a/contracts/scripts/lcov_prune b/contracts/scripts/lcov_prune index 9d5d592c646..0f16715cb2e 100755 --- a/contracts/scripts/lcov_prune +++ b/contracts/scripts/lcov_prune @@ -30,7 +30,7 @@ exclusion_list_ccip=( "src/v0.8/ConfirmedOwnerWithProposal.sol" "src/v0.8/tests/MockV3Aggregator.sol" "src/v0.8/ccip/applications/CCIPClientExample.sol" - "src/v0.8/keystone/*" + "src/v0.8/ccip/pools/BurnWithFromMintTokenPool.sol" ) exclusion_list_shared=( diff --git a/contracts/scripts/native_solc_compile_all b/contracts/scripts/native_solc_compile_all index 42abac3c6b3..090d8c8a07b 100755 --- a/contracts/scripts/native_solc_compile_all +++ b/contracts/scripts/native_solc_compile_all @@ -12,7 +12,7 @@ python3 -m pip install --require-hashes -r $SCRIPTPATH/requirements.txt # 6 and 7 are legacy contracts, for each other product we have a native_solc_compile_all_$product script # These scripts can be run individually, or all together with this script. # To add new CL products, simply write a native_solc_compile_all_$product script and add it to the list below. -for product in automation events_mock feeds functions keystone llo-feeds logpoller operatorforwarder shared vrf ccip liquiditymanager workflow +for product in automation events_mock feeds functions keystone llo-feeds logpoller operatorforwarder shared transmission vrf ccip liquiditymanager workflow do $SCRIPTPATH/native_solc_compile_all_$product done diff --git a/contracts/scripts/native_solc_compile_all_ccip b/contracts/scripts/native_solc_compile_all_ccip index bfa35108a91..5d5b8f73115 100755 --- a/contracts/scripts/native_solc_compile_all_ccip +++ b/contracts/scripts/native_solc_compile_all_ccip @@ -6,10 +6,9 @@ echo " ┌─────────────────────── echo " │ Compiling CCIP contracts... │" echo " └──────────────────────────────────────────────┘" -SOLC_VERSION="0.8.26" -OPTIMIZE_RUNS=80000 -# This has to match the value in the `ccip-viair` foundry profile. -OPTIMIZE_RUNS_OFFRAMP=800 +SOLC_VERSION="0.8.24" +OPTIMIZE_RUNS=26000 +OPTIMIZE_RUNS_OFFRAMP=500 SCRIPTPATH="$( cd "$(dirname "$0")" >/dev/null 2>&1 ; pwd -P )" @@ -33,7 +32,7 @@ compileContract () { ;; esac - solc --overwrite --via-ir --optimize --optimize-runs $optimize_runs --metadata-hash none \ + solc --overwrite --optimize --optimize-runs $optimize_runs --metadata-hash none \ -o "$ROOT"/contracts/solc/v$SOLC_VERSION/"$contract" \ --abi --bin --allow-paths "$ROOT"/contracts/src/v0.8 \ --bin-runtime --hashes --metadata --metadata-literal --combined-json abi,hashes,metadata,srcmap,srcmap-runtime \ @@ -41,6 +40,9 @@ compileContract () { "$ROOT"/contracts/src/v0.8/"$1" } + +# Solc produces and overwrites intermediary contracts. +# Contracts should be ordered in reverse-import-complexity-order to minimize overwrite risks. compileContract ccip/offRamp/OffRamp.sol compileContract ccip/FeeQuoter.sol compileContract ccip/onRamp/OnRamp.sol @@ -56,7 +58,6 @@ compileContract ccip/tokenAdminRegistry/RegistryModuleOwnerCustom.sol compileContract ccip/capability/CCIPHome.sol compileContract ccip/NonceManager.sol compileContract shared/token/ERC677/BurnMintERC677.sol -compileContract shared/token/ERC20/BurnMintERC20.sol # Pools diff --git a/contracts/scripts/native_solc_compile_all_shared b/contracts/scripts/native_solc_compile_all_shared index 841f94354e3..c72e30b42d3 100755 --- a/contracts/scripts/native_solc_compile_all_shared +++ b/contracts/scripts/native_solc_compile_all_shared @@ -30,8 +30,6 @@ compileContract () { compileContract shared/token/ERC677/BurnMintERC677.sol compileContract shared/token/ERC677/LinkToken.sol -compileContract shared/token/ERC20/BurnMintERC20.sol compileContract shared/mocks/WERC20Mock.sol compileContract vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/ERC20.sol compileContract shared/test/helpers/ChainReaderTester.sol -compileContract vendor/multicall/ebd8b64/src/Multicall3.sol diff --git a/contracts/scripts/native_solc_compile_all_transmission b/contracts/scripts/native_solc_compile_all_transmission new file mode 100755 index 00000000000..9650a2b27d3 --- /dev/null +++ b/contracts/scripts/native_solc_compile_all_transmission @@ -0,0 +1,40 @@ +#!/usr/bin/env bash + +set -e + +echo " ┌──────────────────────────────────────────────┐" +echo " │ Compiling Transmission contracts... │" +echo " └──────────────────────────────────────────────┘" + +SOLC_VERSION="0.8.19" +OPTIMIZE_RUNS=1000000 + +SCRIPTPATH="$( cd "$(dirname "$0")" >/dev/null 2>&1 ; pwd -P )" +ROOT="$( cd "$(dirname "$0")" >/dev/null 2>&1 ; cd ../../ && pwd -P )" +python3 -m pip install --require-hashes -r "$SCRIPTPATH"/requirements.txt + +solc-select install $SOLC_VERSION +solc-select use $SOLC_VERSION +export SOLC_VERSION=$SOLC_VERSION + +compileContract () { + local contract + contract=$(basename "$1" ".sol") + + solc --overwrite --optimize --optimize-runs $OPTIMIZE_RUNS --metadata-hash none \ + -o "$ROOT"/contracts/solc/v$SOLC_VERSION/"$contract" \ + --abi --bin --allow-paths "$ROOT"/contracts/src/v0.8\ + "$ROOT"/contracts/src/v0.8/"$1" +} + +# Contracts +compileContract transmission/dev/ERC-4337/SCA.sol +compileContract transmission/dev/ERC-4337/Paymaster.sol +compileContract transmission/dev/ERC-4337/SmartContractAccountFactory.sol + +# Testhelpers +compileContract transmission/dev/testhelpers/SmartContractAccountHelper.sol +compileContract transmission/dev/testhelpers/Greeter.sol + +# Vendor +compileContract vendor/entrypoint/core/EntryPoint.sol diff --git a/contracts/src/v0.8/ccip/FeeQuoter.sol b/contracts/src/v0.8/ccip/FeeQuoter.sol index 8275999af9e..d8a04e359b1 100644 --- a/contracts/src/v0.8/ccip/FeeQuoter.sol +++ b/contracts/src/v0.8/ccip/FeeQuoter.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import {IReceiver} from "../keystone/interfaces/IReceiver.sol"; import {ITypeAndVersion} from "../shared/interfaces/ITypeAndVersion.sol"; @@ -15,7 +15,6 @@ import {Internal} from "./libraries/Internal.sol"; import {Pool} from "./libraries/Pool.sol"; import {USDPriceWith18Decimals} from "./libraries/USDPriceWith18Decimals.sol"; -import {IERC165} from "../vendor/openzeppelin-solidity/v5.0.2/contracts/interfaces/IERC165.sol"; import {EnumerableSet} from "../vendor/openzeppelin-solidity/v5.0.2/contracts/utils/structs/EnumerableSet.sol"; /// @notice The FeeQuoter contract responsibility is to: @@ -103,12 +102,12 @@ contract FeeQuoter is AuthorizedCallers, IFeeQuoter, ITypeAndVersion, IReceiver, // The following three properties are defaults, they can be overridden by setting the TokenTransferFeeConfig for a token. uint16 defaultTokenFeeUSDCents; // │ Default token fee charged per token transfer. uint32 defaultTokenDestGasOverhead; // ──────╯ Default gas charged to execute a token transfer on the destination chain. - uint32 defaultTxGasLimit; //──────────╮ Default gas limit for a tx. - uint64 gasMultiplierWeiPerEth; // │ Multiplier for gas costs, 1e18 based so 11e17 = 10% extra cost. - uint32 networkFeeUSDCents; // │ Flat network fee to charge for messages, multiples of 0.01 USD. - uint32 gasPriceStalenessThreshold; // │ The amount of time a gas price can be stale before it is considered invalid (0 means disabled). - bool enforceOutOfOrder; // │ Whether to enforce the allowOutOfOrderExecution extraArg value to be true. - bytes4 chainFamilySelector; // ───────╯ Selector that identifies the destination chain's family. Used to determine the correct validations to perform for the dest chain. + uint32 defaultTxGasLimit; //─────────────────╮ Default gas limit for a tx. + uint64 gasMultiplierWeiPerEth; // │ Multiplier for gas costs, 1e18 based so 11e17 = 10% extra cost. + uint32 networkFeeUSDCents; // │ Flat network fee to charge for messages, multiples of 0.01 USD. + uint32 gasPriceStalenessThreshold; // │ The amount of time a gas price can be stale before it is considered invalid (0 means disabled). + bool enforceOutOfOrder; // │ Whether to enforce the allowOutOfOrderExecution extraArg value to be true. + bytes4 chainFamilySelector; // ──────────────╯ Selector that identifies the destination chain's family. Used to determine the correct validations to perform for the dest chain. } /// @dev Struct to hold the configs and its destination chain selector. Same as DestChainConfig but with the @@ -121,13 +120,13 @@ contract FeeQuoter is AuthorizedCallers, IFeeQuoter, ITypeAndVersion, IReceiver, /// @dev Struct with transfer fee configuration for token transfers. struct TokenTransferFeeConfig { - uint32 minFeeUSDCents; // ───╮ Minimum fee to charge per token transfer, multiples of 0.01 USD. - uint32 maxFeeUSDCents; // │ Maximum fee to charge per token transfer, multiples of 0.01 USD. - uint16 deciBps; // │ Basis points charged on token transfers, multiples of 0.1bps, or 1e-5. - uint32 destGasOverhead; // │ Gas charged to execute the token transfer on the destination chain. - // │ Data availability bytes that are returned from the source pool and sent to the dest - uint32 destBytesOverhead; // │ pool. Must be >= Pool.CCIP_LOCK_OR_BURN_V1_RET_BYTES. Set as multiple of 32 bytes. - bool isEnabled; // ──────────╯ Whether this token has custom transfer fees. + uint32 minFeeUSDCents; // ────╮ Minimum fee to charge per token transfer, multiples of 0.01 USD. + uint32 maxFeeUSDCents; // │ Maximum fee to charge per token transfer, multiples of 0.01 USD. + uint16 deciBps; // │ Basis points charged on token transfers, multiples of 0.1bps, or 1e-5. + uint32 destGasOverhead; // │ Gas charged to execute the token transfer on the destination chain. + // │ Extra data availability bytes that are returned from the source pool and sent to + uint32 destBytesOverhead; // │ the destination pool. Must be >= Pool.CCIP_LOCK_OR_BURN_V1_RET_BYTES. + bool isEnabled; // ───────────╯ Whether this token has custom transfer fees. } /// @dev Struct with token transfer fee configurations for a token, same as TokenTransferFeeConfig but with the token @@ -494,14 +493,6 @@ contract FeeQuoter is AuthorizedCallers, IFeeQuoter, ITypeAndVersion, IReceiver, } } - /// @notice Signals which version of the pool interface is supported - function supportsInterface( - bytes4 interfaceId - ) public pure override returns (bool) { - return interfaceId == type(IReceiver).interfaceId || interfaceId == type(IFeeQuoter).interfaceId - || interfaceId == type(ITypeAndVersion).interfaceId || interfaceId == type(IERC165).interfaceId; - } - /// @inheritdoc IReceiver /// @notice Handles the report containing price feeds and updates the internal price storage. /// @dev This function is called to process incoming price feed data. @@ -517,7 +508,6 @@ contract FeeQuoter is AuthorizedCallers, IFeeQuoter, ITypeAndVersion, IReceiver, for (uint256 i = 0; i < feeds.length; ++i) { TokenPriceFeedConfig memory feedConfig = s_usdPriceFeedsPerToken[feeds[i].token]; - // If the token is not enabled we revert the entire report as that indicates some type of misconfiguration. if (!feedConfig.isEnabled) { revert TokenNotSupported(feeds[i].token); } @@ -600,8 +590,7 @@ contract FeeQuoter is AuthorizedCallers, IFeeQuoter, ITypeAndVersion, IReceiver, // fee logic for other chains should be implemented in the future. uint256 executionCost = uint112(packedGasPrice) * ( - destChainConfig.destGasOverhead - + ((message.data.length + tokenTransferBytesOverhead) * destChainConfig.destGasPerPayloadByte) + tokenTransferGas + destChainConfig.destGasOverhead + (message.data.length * destChainConfig.destGasPerPayloadByte) + tokenTransferGas + _parseEVMExtraArgsFromBytes(message.extraArgs, destChainConfig).gasLimit ) * destChainConfig.gasMultiplierWeiPerEth; @@ -712,8 +701,6 @@ contract FeeQuoter is AuthorizedCallers, IFeeQuoter, ITypeAndVersion, IReceiver, continue; } - // In the case where bpsFeeUSDWei, minFeeUSDWei, and maxFeeUSDWei are all 0, we skip the fee. This is intended - // to allow for a fee of 0 to be set. tokenTransferFeeUSDWei += bpsFeeUSDWei; } @@ -867,9 +854,7 @@ contract FeeQuoter is AuthorizedCallers, IFeeQuoter, ITypeAndVersion, IReceiver, if (evmExtraArgs.gasLimit > uint256(destChainConfig.maxPerMsgGasLimit)) revert MessageGasLimitTooHigh(); - // If the chain enforces out of order execution, the extra args must allow it, otherwise revert. We cannot assume - // the user intended to use OOO on any chain that requires it as it may lead to unexpected behavior. Therefore we - // revert instead of assuming the user intended to use OOO. + // If the chain enforces out of order execution, the extra args must allow it, otherwise revert. if (destChainConfig.enforceOutOfOrder && !evmExtraArgs.allowOutOfOrderExecution) { revert ExtraArgOutOfOrderExecutionMustBeTrue(); } diff --git a/contracts/src/v0.8/ccip/LICENSE-MIT.md b/contracts/src/v0.8/ccip/LICENSE-MIT.md new file mode 100644 index 00000000000..812debd8e9b --- /dev/null +++ b/contracts/src/v0.8/ccip/LICENSE-MIT.md @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2018 SmartContract ChainLink, Ltd. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. \ No newline at end of file diff --git a/contracts/src/v0.8/ccip/MultiAggregateRateLimiter.sol b/contracts/src/v0.8/ccip/MultiAggregateRateLimiter.sol index fc553e4939c..4ec67b409d6 100644 --- a/contracts/src/v0.8/ccip/MultiAggregateRateLimiter.sol +++ b/contracts/src/v0.8/ccip/MultiAggregateRateLimiter.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import {ITypeAndVersion} from "../shared/interfaces/ITypeAndVersion.sol"; import {IFeeQuoter} from "./interfaces/IFeeQuoter.sol"; diff --git a/contracts/src/v0.8/ccip/NonceManager.sol b/contracts/src/v0.8/ccip/NonceManager.sol index d8569658fcc..f95380b23b2 100644 --- a/contracts/src/v0.8/ccip/NonceManager.sol +++ b/contracts/src/v0.8/ccip/NonceManager.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import {ITypeAndVersion} from "../shared/interfaces/ITypeAndVersion.sol"; import {IEVM2AnyOnRamp} from "./interfaces/IEVM2AnyOnRamp.sol"; @@ -33,9 +33,9 @@ contract NonceManager is INonceManager, AuthorizedCallers, ITypeAndVersion { /// @dev The previous on/off ramps per chain selector. mapping(uint64 chainSelector => PreviousRamps previousRamps) private s_previousRamps; - /// @dev The current outbound nonce per sender used on the onRamp. + /// @dev The current outbound nonce per sender used on the onramp. mapping(uint64 destChainSelector => mapping(address sender => uint64 outboundNonce)) private s_outboundNonces; - /// @dev The current inbound nonce per sender used on the offRamp. + /// @dev The current inbound nonce per sender used on the offramp. /// Eventually in sync with the outbound nonce in the remote source chain NonceManager, used to enforce that messages /// are executed in the same order they are sent (assuming they are DON). mapping(uint64 sourceChainSelector => mapping(bytes sender => uint64 inboundNonce)) private s_inboundNonces; @@ -71,8 +71,6 @@ contract NonceManager is INonceManager, AuthorizedCallers, ITypeAndVersion { if (outboundNonce == 0) { address prevOnRamp = s_previousRamps[destChainSelector].prevOnRamp; if (prevOnRamp != address(0)) { - // This gets the current nonce for a sender, not the already incremented nonce like getIncrementedOutboundNonce - // would return. return IEVM2AnyOnRamp(prevOnRamp).getSenderNonce(sender); } } diff --git a/contracts/src/v0.8/ccip/Router.sol b/contracts/src/v0.8/ccip/Router.sol index a3f9e409f72..150ba00f39d 100644 --- a/contracts/src/v0.8/ccip/Router.sol +++ b/contracts/src/v0.8/ccip/Router.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import {ITypeAndVersion} from "../shared/interfaces/ITypeAndVersion.sol"; import {IAny2EVMMessageReceiver} from "./interfaces/IAny2EVMMessageReceiver.sol"; diff --git a/contracts/src/v0.8/ccip/applications/EtherSenderReceiver.sol b/contracts/src/v0.8/ccip/applications/EtherSenderReceiver.sol index ca72079ec4e..8a07792782b 100644 --- a/contracts/src/v0.8/ccip/applications/EtherSenderReceiver.sol +++ b/contracts/src/v0.8/ccip/applications/EtherSenderReceiver.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import {ITypeAndVersion} from "../../shared/interfaces/ITypeAndVersion.sol"; diff --git a/contracts/src/v0.8/ccip/capability/CCIPHome.sol b/contracts/src/v0.8/ccip/capability/CCIPHome.sol index 174b2e3d83b..7a425566c33 100644 --- a/contracts/src/v0.8/ccip/capability/CCIPHome.sol +++ b/contracts/src/v0.8/ccip/capability/CCIPHome.sol @@ -1,7 +1,8 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import {ICapabilityConfiguration} from "../../keystone/interfaces/ICapabilityConfiguration.sol"; + import {INodeInfoProvider} from "../../keystone/interfaces/INodeInfoProvider.sol"; import {ITypeAndVersion} from "../../shared/interfaces/ITypeAndVersion.sol"; @@ -61,7 +62,7 @@ import {EnumerableSet} from "../../vendor/openzeppelin-solidity/v5.0.2/contracts /// │ Active │ revokeCandidate │ Candidate │◄───────────┐ /// │ [1,0] │◄───────────────────┤ [1,1] │────────────┘ /// │ ├───────────────────►│ │ -/// └─────────────┘ setCandidate └─────────────┘ +/// └─────────────┘ setSecondary └─────────────┘ /// contract CCIPHome is Ownable2StepMsgSender, ITypeAndVersion, ICapabilityConfiguration, IERC165 { using EnumerableSet for EnumerableSet.UintSet; @@ -110,7 +111,7 @@ contract CCIPHome is Ownable2StepMsgSender, ITypeAndVersion, ICapabilityConfigur uint64 chainSelector; // │ The (remote) chain that the configuration is for. uint8 FRoleDON; // │ The "big F" parameter for the role DON. uint64 offchainConfigVersion; // ──────╯ The version of the exec offchain configuration. - bytes offrampAddress; // The remote chain offRamp address. + bytes offrampAddress; // The remote chain offramp address. bytes rmnHomeAddress; // The home chain RMN home address. OCR3Node[] nodes; // Keys & IDs of nodes part of the role DON. bytes offchainConfig; // The offchain configuration for the OCR3 plugin. Protobuf encoded. @@ -240,9 +241,10 @@ contract CCIPHome is Ownable2StepMsgSender, ITypeAndVersion, ICapabilityConfigur } /// @inheritdoc ICapabilityConfiguration - /// @dev This function is not used in the CCIPHome contract but the interface requires it to be implemented. + /// @dev The CCIP capability will fetch the configuration needed directly from this contract. + /// The offchain syncer will call this function, so its important that it doesn't revert. function getCapabilityConfiguration( - uint32 + uint32 /* donId */ ) external pure override returns (bytes memory configuration) { return bytes(""); } @@ -531,15 +533,6 @@ contract CCIPHome is Ownable2StepMsgSender, ITypeAndVersion, ICapabilityConfigur return s_remoteChainSelectors.length(); } - /// @notice Returns the chain configuration for a given chain selector. - /// @param chainSelector The chain selector. - /// @return chainConfig The chain configuration. - function getChainConfig( - uint64 chainSelector - ) external view returns (ChainConfig memory) { - return s_chainConfigurations[chainSelector]; - } - /// @notice Returns all the chain configurations. /// @param pageIndex The page index. /// @param pageSize The page size. diff --git a/contracts/src/v0.8/ccip/interfaces/IEVM2AnyOnRamp.sol b/contracts/src/v0.8/ccip/interfaces/IEVM2AnyOnRamp.sol index e40b186dda4..2d27bd3a25c 100644 --- a/contracts/src/v0.8/ccip/interfaces/IEVM2AnyOnRamp.sol +++ b/contracts/src/v0.8/ccip/interfaces/IEVM2AnyOnRamp.sol @@ -8,9 +8,9 @@ interface IEVM2AnyOnRamp is IEVM2AnyOnRampClient { /// @return the next sequence number to be used. function getExpectedNextSequenceNumber() external view returns (uint64); - /// @notice Get the current nonce for a given sender. + /// @notice Get the next nonce for a given sender. /// @param sender The sender to get the nonce for. - /// @return nonce The current nonce for the sender. + /// @return nonce The next nonce for the sender. function getSenderNonce( address sender ) external view returns (uint64 nonce); diff --git a/contracts/src/v0.8/ccip/libraries/ERC165CheckerReverting.sol b/contracts/src/v0.8/ccip/libraries/ERC165CheckerReverting.sol deleted file mode 100644 index 574b6d1501a..00000000000 --- a/contracts/src/v0.8/ccip/libraries/ERC165CheckerReverting.sol +++ /dev/null @@ -1,65 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -import {IERC165} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/utils/introspection/IERC165.sol"; - -/// @notice Library used to query support of an interface declared via {IERC165}. -/// @dev These functions return the actual result of the query: they do not `revert` if an interface is not supported. -library ERC165CheckerReverting { - error InsufficientGasForStaticCall(); - - // As per the EIP-165 spec, no interface should ever match 0xffffffff. - bytes4 private constant INTERFACE_ID_INVALID = 0xffffffff; - - /// @dev 30k gas is required to make the staticcall. Under the 63/64 rule this means that 30,477 gas must be available - /// to ensure that at least 30k is forwarded. Checking for at least 31,000 ensures that after additional - /// operations are performed there is still >= 30,477 gas remaining. - /// 30,000 = ((30,477 * 63) / 64) - uint256 private constant MINIMUM_GAS_REQUIREMENT = 31_000; - - /// @notice Returns true if `account` supports a defined interface. - /// @dev The function must support both the interfaceId and interfaces specified by ERC165 generally as per the standard. - /// @param account the contract to be queried for support. - /// @param interfaceId the interface being checked for support. - /// @return true if the contract at account indicates support of the interface with, false otherwise. - function _supportsInterfaceReverting(address account, bytes4 interfaceId) internal view returns (bool) { - // As a gas optimization, short circuit return false if interfaceId is not supported, as it is most likely interfaceId - // to be unsupported by the target. - return _supportsERC165InterfaceUncheckedReverting(account, interfaceId) - && !_supportsERC165InterfaceUncheckedReverting(account, INTERFACE_ID_INVALID) - && _supportsERC165InterfaceUncheckedReverting(account, type(IERC165).interfaceId); - } - - /// @notice Query if a contract implements an interface, does not check ERC165 support - /// @param account The address of the contract to query for support of an interface - /// @param interfaceId The interface identifier, as specified in ERC-165 - /// @return true if the contract at account indicates support of the interface with - /// identifier interfaceId, false otherwise - /// @dev Assumes that account contains a contract that supports ERC165, otherwise - /// the behavior of this method is undefined. This precondition can be checked. - /// @dev Function will only revert if the minimum gas requirement is not met before the staticcall is performed. - function _supportsERC165InterfaceUncheckedReverting(address account, bytes4 interfaceId) internal view returns (bool) { - bytes memory encodedParams = abi.encodeWithSelector(IERC165.supportsInterface.selector, interfaceId); - - bool success; - uint256 returnSize; - uint256 returnValue; - - bytes4 notEnoughGasSelector = InsufficientGasForStaticCall.selector; - - assembly { - // The EVM does not return a specific error code if a revert is due to OOG. This check ensures that - // the message will not throw an OOG error by requiring that the amount of gas for the following - // staticcall exists before invoking it. - if lt(gas(), MINIMUM_GAS_REQUIREMENT) { - mstore(0x0, notEnoughGasSelector) - revert(0x0, 0x4) - } - - success := staticcall(30000, account, add(encodedParams, 0x20), mload(encodedParams), 0x00, 0x20) - returnSize := returndatasize() - returnValue := mload(0x00) - } - return success && returnSize >= 0x20 && returnValue > 0; - } -} diff --git a/contracts/src/v0.8/ccip/libraries/Internal.sol b/contracts/src/v0.8/ccip/libraries/Internal.sol index 25d923ee1ed..5f2f8a6c472 100644 --- a/contracts/src/v0.8/ccip/libraries/Internal.sol +++ b/contracts/src/v0.8/ccip/libraries/Internal.sol @@ -3,14 +3,14 @@ pragma solidity ^0.8.4; import {MerkleMultiProof} from "../libraries/MerkleMultiProof.sol"; -/// @notice Library for CCIP internal definitions common to multiple contracts. -/// @dev The following is a non-exhaustive list of "known issues" for CCIP: -/// - We could implement yield claiming for Blast. This is not worth the custom code path on non-blast chains. -/// - uint32 is used for timestamps, which will overflow in 2106. This is not a concern for the current use case, as we -/// expect to have migrated to a new version by then. +// Library for CCIP internal definitions common to multiple contracts. library Internal { error InvalidEVMAddress(bytes encodedAddress); + /// @dev The minimum amount of gas to perform the call with exact gas. + /// We include this in the offramp so that we can redeploy to adjust it should a hardfork change the gas costs of + /// relevant opcodes in callWithExactGas. + uint16 internal constant GAS_FOR_CALL_EXACT_CHECK = 5_000; /// @dev We limit return data to a selector plus 4 words. This is to avoid malicious contracts from returning /// large amounts of data and causing repeated out-of-gas scenarios. uint16 internal constant MAX_RET_BYTES = 4 + 4 * 32; @@ -40,8 +40,8 @@ library Internal { /// @notice A timestamped uint224 value that can contain several tightly packed fields. struct TimestampedPackedUint224 { - uint224 value; // ────╮ Value in uint224, packed. - uint32 timestamp; // ─╯ Timestamp of the most recent price update. + uint224 value; // ──────╮ Value in uint224, packed. + uint32 timestamp; // ───╯ Timestamp of the most recent price update. } /// @dev Gas price is stored in 112-bit unsigned int. uint224 can pack 2 prices. @@ -196,10 +196,10 @@ library Internal { /// The messageId is not expected to match hash(message), since it may originate from another ramp family. struct RampMessageHeader { bytes32 messageId; // Unique identifier for the message, generated with the source chain's encoding scheme (i.e. not necessarily abi.encoded). - uint64 sourceChainSelector; // ─╮ the chain selector of the source chain, note: not chainId. - uint64 destChainSelector; // │ the chain selector of the destination chain, note: not chainId. - uint64 sequenceNumber; // │ sequence number, not unique across lanes. - uint64 nonce; // ───────────────╯ nonce for this lane for this sender, not unique across senders/lanes. + uint64 sourceChainSelector; // ──╮ the chain selector of the source chain, note: not chainId. + uint64 destChainSelector; // │ the chain selector of the destination chain, note: not chainId. + uint64 sequenceNumber; // │ sequence number, not unique across lanes. + uint64 nonce; // ────────────────╯ nonce for this lane for this sender, not unique across senders/lanes. } struct EVM2AnyTokenTransfer { @@ -224,7 +224,7 @@ library Internal { // be relied upon by the destination pool to validate the source pool. bytes sourcePoolAddress; address destTokenAddress; // ─╮ Address of destination token - uint32 destGasAmount; // ─────╯ The amount of gas available for the releaseOrMint and transfer calls on the offRamp. + uint32 destGasAmount; //──────╯ The amount of gas available for the releaseOrMint and transfer calls on the offRamp. // Optional pool data to be transferred to the destination chain. Be default this is capped at // CCIP_LOCK_OR_BURN_V1_RET_BYTES bytes. If more data is required, the TokenTransferFeeConfig.destBytesOverhead // has to be set for the specific token. @@ -268,7 +268,7 @@ library Internal { // solhint-disable-next-line gas-struct-packing struct MerkleRoot { uint64 sourceChainSelector; // Remote source chain selector that the Merkle Root is scoped to - bytes onRampAddress; // Generic onRamp address, to support arbitrary sources; for EVM, use abi.encode + bytes onRampAddress; // Generic onramp address, to support arbitrary sources; for EVM, use abi.encode uint64 minSeqNr; // ─────────╮ Minimum sequence number, inclusive uint64 maxSeqNr; // ─────────╯ Maximum sequence number, inclusive bytes32 merkleRoot; // Merkle root covering the interval & source chain messages diff --git a/contracts/src/v0.8/ccip/ocr/MultiOCR3Base.sol b/contracts/src/v0.8/ccip/ocr/MultiOCR3Base.sol index b6741f78fbe..5d8cc7f69d1 100644 --- a/contracts/src/v0.8/ccip/ocr/MultiOCR3Base.sol +++ b/contracts/src/v0.8/ccip/ocr/MultiOCR3Base.sol @@ -101,7 +101,7 @@ abstract contract MultiOCR3Base is ITypeAndVersion, Ownable2StepMsgSender { /// @notice Constant length component for transmit functions with no signatures. /// The signatures are expected to match transmitPlugin(reportContext, report). uint16 private constant TRANSMIT_MSGDATA_CONSTANT_LENGTH_COMPONENT_NO_SIGNATURES = 4 // function selector. - + 2 * 32 // 2 words containing reportContext. + + 3 * 32 // 3 words containing reportContext. + 32 // word containing start location of abiencoded report value. + 32; // word containing length of report. @@ -230,7 +230,7 @@ abstract contract MultiOCR3Base is ITypeAndVersion, Ownable2StepMsgSender { uint8 ocrPluginType, // NOTE: If these parameters are changed, expectedMsgDataLength and/or TRANSMIT_MSGDATA_CONSTANT_LENGTH_COMPONENT // need to be changed accordingly. - bytes32[2] calldata reportContext, + bytes32[3] calldata reportContext, bytes calldata report, bytes32[] memory rs, bytes32[] memory ss, @@ -239,6 +239,7 @@ abstract contract MultiOCR3Base is ITypeAndVersion, Ownable2StepMsgSender { // reportContext consists of: // reportContext[0]: ConfigDigest. // reportContext[1]: 24 byte padding, 8 byte sequence number. + // reportContext[2]: ExtraHash. ConfigInfo memory configInfo = s_ocrConfigs[ocrPluginType].configInfo; bytes32 configDigest = reportContext[0]; diff --git a/contracts/src/v0.8/ccip/offRamp/OffRamp.sol b/contracts/src/v0.8/ccip/offRamp/OffRamp.sol index 2b6f075bc7a..80873175039 100644 --- a/contracts/src/v0.8/ccip/offRamp/OffRamp.sol +++ b/contracts/src/v0.8/ccip/offRamp/OffRamp.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import {ITypeAndVersion} from "../../shared/interfaces/ITypeAndVersion.sol"; import {IAny2EVMMessageReceiver} from "../interfaces/IAny2EVMMessageReceiver.sol"; @@ -13,13 +13,13 @@ import {ITokenAdminRegistry} from "../interfaces/ITokenAdminRegistry.sol"; import {CallWithExactGas} from "../../shared/call/CallWithExactGas.sol"; import {Client} from "../libraries/Client.sol"; -import {ERC165CheckerReverting} from "../libraries/ERC165CheckerReverting.sol"; import {Internal} from "../libraries/Internal.sol"; import {MerkleMultiProof} from "../libraries/MerkleMultiProof.sol"; import {Pool} from "../libraries/Pool.sol"; import {MultiOCR3Base} from "../ocr/MultiOCR3Base.sol"; import {IERC20} from "../../vendor/openzeppelin-solidity/v5.0.2/contracts/token/ERC20/IERC20.sol"; +import {ERC165Checker} from "../../vendor/openzeppelin-solidity/v5.0.2/contracts/utils/introspection/ERC165Checker.sol"; import {EnumerableSet} from "../../vendor/openzeppelin-solidity/v5.0.2/contracts/utils/structs/EnumerableSet.sol"; /// @notice OffRamp enables OCR networks to execute multiple messages in an OffRamp in a single transaction. @@ -28,7 +28,7 @@ import {EnumerableSet} from "../../vendor/openzeppelin-solidity/v5.0.2/contracts /// @dev MultiOCR3Base is used to store multiple OCR configs for the OffRamp. The execution plugin type has to be /// configured without signature verification, and the commit plugin type with verification. contract OffRamp is ITypeAndVersion, MultiOCR3Base { - using ERC165CheckerReverting for address; + using ERC165Checker for address; using EnumerableSet for EnumerableSet.UintSet; error ZeroChainSelectorNotAllowed(); @@ -48,7 +48,7 @@ contract OffRamp is ITypeAndVersion, MultiOCR3Base { error InvalidRoot(); error CanOnlySelfCall(); error ReceiverError(bytes err); - error TokenHandlingError(address target, bytes err); + error TokenHandlingError(bytes err); error ReleaseOrMintBalanceMismatch(uint256 amountReleased, uint256 balancePre, uint256 balancePost); error EmptyReport(uint64 sourceChainSelector); error EmptyBatch(); @@ -92,9 +92,8 @@ contract OffRamp is ITypeAndVersion, MultiOCR3Base { /// @dev RMN depends on this struct, if changing, please notify the RMN maintainers. // solhint-disable-next-line gas-struct-packing struct StaticConfig { - uint64 chainSelector; // ───────╮ Destination chainSelector - uint16 gasForCallExactCheck; // | Gas for call exact check - IRMNRemote rmnRemote; // ───────╯ RMN Verification Contract + uint64 chainSelector; // ────╮ Destination chainSelector + IRMNRemote rmnRemote; // ────╯ RMN Verification Contract address tokenAdminRegistry; // Token admin registry address address nonceManager; // Nonce manager address } @@ -152,10 +151,6 @@ contract OffRamp is ITypeAndVersion, MultiOCR3Base { address internal immutable i_tokenAdminRegistry; /// @dev The address of the nonce manager. address internal immutable i_nonceManager; - /// @dev The minimum amount of gas to perform the call with exact gas. - /// We include this in the offramp so that we can redeploy to adjust it should a hardfork change the gas costs of - /// relevant opcodes in callWithExactGas. - uint16 internal immutable i_gasForCallExactCheck; // DYNAMIC CONFIG DynamicConfig internal s_dynamicConfig; @@ -198,7 +193,6 @@ contract OffRamp is ITypeAndVersion, MultiOCR3Base { i_rmnRemote = staticConfig.rmnRemote; i_tokenAdminRegistry = staticConfig.tokenAdminRegistry; i_nonceManager = staticConfig.nonceManager; - i_gasForCallExactCheck = staticConfig.gasForCallExactCheck; emit StaticConfigSet(staticConfig); _setDynamicConfig(dynamicConfig); @@ -328,7 +322,7 @@ contract OffRamp is ITypeAndVersion, MultiOCR3Base { /// @notice Transmit function for execution reports. The function takes no signatures, and expects the exec plugin /// type to be configured with no signatures. /// @param report serialized execution report. - function execute(bytes32[2] calldata reportContext, bytes calldata report) external { + function execute(bytes32[3] calldata reportContext, bytes calldata report) external { _batchExecute(abi.decode(report, (Internal.ExecutionReport[])), new GasLimitOverride[][](0)); bytes32[] memory emptySigs = new bytes32[](0); @@ -362,8 +356,6 @@ contract OffRamp is ITypeAndVersion, MultiOCR3Base { /// @param manualExecGasExecOverrides An array of gas limits to use for manual execution. /// @dev If called from the DON, this array is always empty. /// @dev If called from manual execution, this array is always same length as messages. - /// @dev This function can fully revert in some cases, reverting potentially valid other reports with it. The reasons - /// for these reverts are so severe that we prefer to revert the entire batch instead of silently failing. function _executeSingleReport( Internal.ExecutionReport memory report, GasLimitOverride[] memory manualExecGasExecOverrides @@ -585,8 +577,6 @@ contract OffRamp is ITypeAndVersion, MultiOCR3Base { destTokenAmounts: destTokenAmounts }); - // The main message interceptor is the aggregate rate limiter, but we also allow for a custom interceptor. This is - // why we always have to call into the contract when it's enabled, even when there are no tokens in the message. address messageInterceptor = s_dynamicConfig.messageInterceptor; if (messageInterceptor != address(0)) { try IMessageInterceptor(messageInterceptor).onInboundMessage(any2EvmMessage) {} @@ -604,17 +594,14 @@ contract OffRamp is ITypeAndVersion, MultiOCR3Base { // 3. If the receiver is a contract but it does not support the IAny2EVMMessageReceiver interface. // // The ordering of these checks is important, as the first check is the cheapest to execute. - // - // To prevent message delivery bypass issues, a modified version of the ERC165Checker is used - // which checks for sufficient gas before making the external call. if ( (message.data.length == 0 && message.gasLimit == 0) || message.receiver.code.length == 0 - || !message.receiver._supportsInterfaceReverting(type(IAny2EVMMessageReceiver).interfaceId) + || !message.receiver.supportsInterface(type(IAny2EVMMessageReceiver).interfaceId) ) return; (bool success, bytes memory returnData,) = s_sourceChainConfigs[message.header.sourceChainSelector] .router - .routeMessage(any2EvmMessage, i_gasForCallExactCheck, message.gasLimit, message.receiver); + .routeMessage(any2EvmMessage, Internal.GAS_FOR_CALL_EXACT_CHECK, message.gasLimit, message.receiver); // If CCIP receiver execution is not successful, revert the call including token transfers. if (!success) revert ReceiverError(returnData); } @@ -650,7 +637,7 @@ contract OffRamp is ITypeAndVersion, MultiOCR3Base { // This is done to prevent a pool from reverting the entire transaction if it doesn't support the interface. // The call gets a max or 30k gas per instance, of which there are three. This means offchain gas estimations should // account for 90k gas overhead due to the interface check. - if (localPoolAddress == address(0) || !localPoolAddress._supportsInterfaceReverting(Pool.CCIP_POOL_V1)) { + if (localPoolAddress == address(0) || !localPoolAddress.supportsInterface(Pool.CCIP_POOL_V1)) { revert NotACompatiblePool(localPoolAddress); } @@ -678,12 +665,12 @@ contract OffRamp is ITypeAndVersion, MultiOCR3Base { ), localPoolAddress, gasLeft, - i_gasForCallExactCheck, + 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(localPoolAddress, returnData); + if (!success) revert TokenHandlingError(returnData); // If the call was successful, the returnData should be the amount released or minted denominated in the local // token's decimals. @@ -718,9 +705,13 @@ contract OffRamp is ITypeAndVersion, MultiOCR3Base { uint256 gasLimit ) internal returns (uint256 balance, uint256 gasLeft) { (bool success, bytes memory returnData, uint256 gasUsed) = CallWithExactGas._callWithExactGasSafeReturnData( - abi.encodeCall(IERC20.balanceOf, (receiver)), token, gasLimit, i_gasForCallExactCheck, Internal.MAX_RET_BYTES + abi.encodeCall(IERC20.balanceOf, (receiver)), + token, + gasLimit, + Internal.GAS_FOR_CALL_EXACT_CHECK, + Internal.MAX_RET_BYTES ); - if (!success) revert TokenHandlingError(token, returnData); + if (!success) revert TokenHandlingError(returnData); // If the call was successful, the returnData should contain only the balance. if (returnData.length != Internal.MAX_BALANCE_OF_RET_BYTES) { @@ -782,7 +773,7 @@ contract OffRamp is ITypeAndVersion, MultiOCR3Base { /// price updates is submitted, we are OK to revert to preserve the invariant that we always revert on invalid /// sequence number ranges. If that happens, prices will be updated in later rounds. function commit( - bytes32[2] calldata reportContext, + bytes32[3] calldata reportContext, bytes calldata report, bytes32[] calldata rs, bytes32[] calldata ss, @@ -915,7 +906,6 @@ contract OffRamp is ITypeAndVersion, MultiOCR3Base { function getStaticConfig() external view returns (StaticConfig memory) { return StaticConfig({ chainSelector: i_chainSelector, - gasForCallExactCheck: i_gasForCallExactCheck, rmnRemote: i_rmnRemote, tokenAdminRegistry: i_tokenAdminRegistry, nonceManager: i_nonceManager diff --git a/contracts/src/v0.8/ccip/onRamp/OnRamp.sol b/contracts/src/v0.8/ccip/onRamp/OnRamp.sol index fb0cbedd5e7..e988b17ad82 100644 --- a/contracts/src/v0.8/ccip/onRamp/OnRamp.sol +++ b/contracts/src/v0.8/ccip/onRamp/OnRamp.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import {ITypeAndVersion} from "../../shared/interfaces/ITypeAndVersion.sol"; import {IEVM2AnyOnRampClient} from "../interfaces/IEVM2AnyOnRampClient.sol"; diff --git a/contracts/src/v0.8/ccip/pools/BurnFromMintTokenPool.sol b/contracts/src/v0.8/ccip/pools/BurnFromMintTokenPool.sol index c42ca75f66d..1ba13a49745 100644 --- a/contracts/src/v0.8/ccip/pools/BurnFromMintTokenPool.sol +++ b/contracts/src/v0.8/ccip/pools/BurnFromMintTokenPool.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import {ITypeAndVersion} from "../../shared/interfaces/ITypeAndVersion.sol"; import {IBurnMintERC20} from "../../shared/token/ERC20/IBurnMintERC20.sol"; @@ -18,15 +18,14 @@ import {SafeERC20} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/tok contract BurnFromMintTokenPool is BurnMintTokenPoolAbstract, ITypeAndVersion { using SafeERC20 for IBurnMintERC20; - string public constant override typeAndVersion = "BurnFromMintTokenPool 1.5.1"; + string public constant override typeAndVersion = "BurnFromMintTokenPool 1.5.0"; constructor( IBurnMintERC20 token, - uint8 localTokenDecimals, address[] memory allowlist, address rmnProxy, address router - ) TokenPool(token, localTokenDecimals, allowlist, rmnProxy, router) { + ) TokenPool(token, allowlist, rmnProxy, router) { // Some tokens allow burning from the sender without approval, but not all do. // To be safe, we approve the pool to burn from the pool. token.safeIncreaseAllowance(address(this), type(uint256).max); diff --git a/contracts/src/v0.8/ccip/pools/BurnMintTokenPool.sol b/contracts/src/v0.8/ccip/pools/BurnMintTokenPool.sol index d1d6577b105..33026cf0053 100644 --- a/contracts/src/v0.8/ccip/pools/BurnMintTokenPool.sol +++ b/contracts/src/v0.8/ccip/pools/BurnMintTokenPool.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import {ITypeAndVersion} from "../../shared/interfaces/ITypeAndVersion.sol"; import {IBurnMintERC20} from "../../shared/token/ERC20/IBurnMintERC20.sol"; @@ -14,15 +14,14 @@ import {TokenPool} from "./TokenPool.sol"; /// If that is expected, please make sure the token's burner/minter roles are adjustable. /// @dev This contract is a variant of BurnMintTokenPool that uses `burn(amount)`. contract BurnMintTokenPool is BurnMintTokenPoolAbstract, ITypeAndVersion { - string public constant override typeAndVersion = "BurnMintTokenPool 1.5.1"; + string public constant override typeAndVersion = "BurnMintTokenPool 1.5.0"; constructor( IBurnMintERC20 token, - uint8 localTokenDecimals, address[] memory allowlist, address rmnProxy, address router - ) TokenPool(token, localTokenDecimals, allowlist, rmnProxy, router) {} + ) TokenPool(token, allowlist, rmnProxy, router) {} /// @inheritdoc BurnMintTokenPoolAbstract function _burn( diff --git a/contracts/src/v0.8/ccip/pools/BurnMintTokenPoolAbstract.sol b/contracts/src/v0.8/ccip/pools/BurnMintTokenPoolAbstract.sol index 91472a5f5c8..6d743ed4a9e 100644 --- a/contracts/src/v0.8/ccip/pools/BurnMintTokenPoolAbstract.sol +++ b/contracts/src/v0.8/ccip/pools/BurnMintTokenPoolAbstract.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import {IBurnMintERC20} from "../../shared/token/ERC20/IBurnMintERC20.sol"; @@ -25,10 +25,7 @@ abstract contract BurnMintTokenPoolAbstract is TokenPool { emit Burned(msg.sender, lockOrBurnIn.amount); - return Pool.LockOrBurnOutV1({ - destTokenAddress: getRemoteToken(lockOrBurnIn.remoteChainSelector), - destPoolData: _encodeLocalDecimals() - }); + return Pool.LockOrBurnOutV1({destTokenAddress: getRemoteToken(lockOrBurnIn.remoteChainSelector), destPoolData: ""}); } /// @notice Mint tokens from the pool to the recipient @@ -38,15 +35,11 @@ abstract contract BurnMintTokenPoolAbstract is TokenPool { ) external virtual override returns (Pool.ReleaseOrMintOutV1 memory) { _validateReleaseOrMint(releaseOrMintIn); - // Calculate the local amount - uint256 localAmount = - _calculateLocalAmount(releaseOrMintIn.amount, _parseRemoteDecimals(releaseOrMintIn.sourcePoolData)); - // Mint to the receiver - IBurnMintERC20(address(i_token)).mint(releaseOrMintIn.receiver, localAmount); + IBurnMintERC20(address(i_token)).mint(releaseOrMintIn.receiver, releaseOrMintIn.amount); - emit Minted(msg.sender, releaseOrMintIn.receiver, localAmount); + emit Minted(msg.sender, releaseOrMintIn.receiver, releaseOrMintIn.amount); - return Pool.ReleaseOrMintOutV1({destinationAmount: localAmount}); + return Pool.ReleaseOrMintOutV1({destinationAmount: releaseOrMintIn.amount}); } } diff --git a/contracts/src/v0.8/ccip/pools/BurnWithFromMintTokenPool.sol b/contracts/src/v0.8/ccip/pools/BurnWithFromMintTokenPool.sol index 3659c638dd5..37541bb8277 100644 --- a/contracts/src/v0.8/ccip/pools/BurnWithFromMintTokenPool.sol +++ b/contracts/src/v0.8/ccip/pools/BurnWithFromMintTokenPool.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import {ITypeAndVersion} from "../../shared/interfaces/ITypeAndVersion.sol"; import {IBurnMintERC20} from "../../shared/token/ERC20/IBurnMintERC20.sol"; @@ -20,11 +20,10 @@ contract BurnWithFromMintTokenPool is BurnMintTokenPoolAbstract, ITypeAndVersion constructor( IBurnMintERC20 token, - uint8 localTokenDecimals, address[] memory allowlist, address rmnProxy, address router - ) TokenPool(token, localTokenDecimals, allowlist, rmnProxy, router) { + ) TokenPool(token, allowlist, rmnProxy, router) { // Some tokens allow burning from the sender without approval, but not all do. // To be safe, we approve the pool to burn from the pool. token.safeIncreaseAllowance(address(this), type(uint256).max); @@ -38,6 +37,6 @@ contract BurnWithFromMintTokenPool is BurnMintTokenPoolAbstract, ITypeAndVersion } function typeAndVersion() external pure virtual override returns (string memory) { - return "BurnWithFromMintTokenPool 1.5.1"; + return "BurnWithFromMintTokenPool 1.5.0"; } } diff --git a/contracts/src/v0.8/ccip/pools/LockReleaseTokenPool.sol b/contracts/src/v0.8/ccip/pools/LockReleaseTokenPool.sol index 54977a95758..98c20df30c1 100644 --- a/contracts/src/v0.8/ccip/pools/LockReleaseTokenPool.sol +++ b/contracts/src/v0.8/ccip/pools/LockReleaseTokenPool.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import {ILiquidityContainer} from "../../liquiditymanager/interfaces/ILiquidityContainer.sol"; import {ITypeAndVersion} from "../../shared/interfaces/ITypeAndVersion.sol"; @@ -23,7 +23,7 @@ contract LockReleaseTokenPool is TokenPool, ILiquidityContainer, ITypeAndVersion event LiquidityTransferred(address indexed from, uint256 amount); - string public constant override typeAndVersion = "LockReleaseTokenPool 1.5.1"; + string public constant override typeAndVersion = "LockReleaseTokenPool 1.5.0"; /// @dev Whether or not the pool accepts liquidity. /// External liquidity is not required when there is one canonical token deployed to a chain, @@ -35,12 +35,11 @@ contract LockReleaseTokenPool is TokenPool, ILiquidityContainer, ITypeAndVersion constructor( IERC20 token, - uint8 localTokenDecimals, address[] memory allowlist, address rmnProxy, bool acceptLiquidity, address router - ) TokenPool(token, localTokenDecimals, allowlist, rmnProxy, router) { + ) TokenPool(token, allowlist, rmnProxy, router) { i_acceptLiquidity = acceptLiquidity; } @@ -53,10 +52,7 @@ contract LockReleaseTokenPool is TokenPool, ILiquidityContainer, ITypeAndVersion emit Locked(msg.sender, lockOrBurnIn.amount); - return Pool.LockOrBurnOutV1({ - destTokenAddress: getRemoteToken(lockOrBurnIn.remoteChainSelector), - destPoolData: _encodeLocalDecimals() - }); + return Pool.LockOrBurnOutV1({destTokenAddress: getRemoteToken(lockOrBurnIn.remoteChainSelector), destPoolData: ""}); } /// @notice Release tokens from the pool to the recipient @@ -66,16 +62,12 @@ contract LockReleaseTokenPool is TokenPool, ILiquidityContainer, ITypeAndVersion ) external virtual override returns (Pool.ReleaseOrMintOutV1 memory) { _validateReleaseOrMint(releaseOrMintIn); - // Calculate the local amount - uint256 localAmount = - _calculateLocalAmount(releaseOrMintIn.amount, _parseRemoteDecimals(releaseOrMintIn.sourcePoolData)); - // Release to the recipient - getToken().safeTransfer(releaseOrMintIn.receiver, localAmount); + getToken().safeTransfer(releaseOrMintIn.receiver, releaseOrMintIn.amount); - emit Released(msg.sender, releaseOrMintIn.receiver, localAmount); + emit Released(msg.sender, releaseOrMintIn.receiver, releaseOrMintIn.amount); - return Pool.ReleaseOrMintOutV1({destinationAmount: localAmount}); + return Pool.ReleaseOrMintOutV1({destinationAmount: releaseOrMintIn.amount}); } /// @inheritdoc IERC165 diff --git a/contracts/src/v0.8/ccip/pools/TokenPool.sol b/contracts/src/v0.8/ccip/pools/TokenPool.sol index 47a2ebad238..ac54d93af25 100644 --- a/contracts/src/v0.8/ccip/pools/TokenPool.sol +++ b/contracts/src/v0.8/ccip/pools/TokenPool.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import {IPoolV1} from "../interfaces/IPool.sol"; import {IRMN} from "../interfaces/IRMN.sol"; @@ -10,30 +10,13 @@ import {Pool} from "../libraries/Pool.sol"; import {RateLimiter} from "../libraries/RateLimiter.sol"; import {IERC20} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; -import {IERC20Metadata} from - "../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/extensions/IERC20Metadata.sol"; import {IERC165} from "../../vendor/openzeppelin-solidity/v5.0.2/contracts/utils/introspection/IERC165.sol"; import {EnumerableSet} from "../../vendor/openzeppelin-solidity/v5.0.2/contracts/utils/structs/EnumerableSet.sol"; /// @notice Base abstract class with common functions for all token pools. /// A token pool serves as isolated place for holding tokens and token specific logic /// that may execute as tokens move across the bridge. -/// @dev This pool supports different decimals on different chains but using this feature could impact the total number -/// of tokens in circulation. Since all of the tokens are locked/burned on the source, and a rounded amount is -/// minted/released on the destination, the number of tokens minted/released could be less than the number of tokens -/// burned/locked. This is because the source chain does not know about the destination token decimals. This is not a -/// problem if the decimals are the same on both chains. -/// -/// Example: -/// Assume there is a token with 6 decimals on chain A and 3 decimals on chain B. -/// - 1.234567 tokens are burned on chain A. -/// - 1.234 tokens are minted on chain B. -/// When sending the 1.234 tokens back to chain A, you will receive 1.234000 tokens on chain A, effectively losing -/// 0.000567 tokens. -/// In the case of a burnMint pool on chain A, these funds are burned in the pool on chain A. -/// In the case of a lockRelease pool on chain A, these funds accumulate in the pool on chain A. abstract contract TokenPool is IPoolV1, Ownable2StepMsgSender { - using EnumerableSet for EnumerableSet.Bytes32Set; using EnumerableSet for EnumerableSet.AddressSet; using EnumerableSet for EnumerableSet.UintSet; using RateLimiter for RateLimiter.TokenBucket; @@ -49,12 +32,6 @@ abstract contract TokenPool is IPoolV1, Ownable2StepMsgSender { error InvalidSourcePoolAddress(bytes sourcePoolAddress); error InvalidToken(address token); error Unauthorized(address caller); - error PoolAlreadyAdded(uint64 remoteChainSelector, bytes remotePoolAddress); - error InvalidRemotePoolForChain(uint64 remoteChainSelector, bytes remotePoolAddress); - error InvalidRemoteChainDecimals(bytes sourcePoolData); - error MismatchedArrayLengths(); - error OverflowDetected(uint8 remoteDecimals, uint8 localDecimals, uint256 remoteAmount); - error InvalidDecimalArgs(uint8 expected, uint8 actual); event Locked(address indexed sender, uint256 amount); event Burned(address indexed sender, uint256 amount); @@ -72,17 +49,17 @@ abstract contract TokenPool is IPoolV1, Ownable2StepMsgSender { RateLimiter.Config inboundRateLimiterConfig ); event ChainRemoved(uint64 remoteChainSelector); - event RemotePoolAdded(uint64 indexed remoteChainSelector, bytes remotePoolAddress); - event RemotePoolRemoved(uint64 indexed remoteChainSelector, bytes remotePoolAddress); + event RemotePoolSet(uint64 indexed remoteChainSelector, bytes previousPoolAddress, bytes remotePoolAddress); event AllowListAdd(address sender); event AllowListRemove(address sender); event RouterUpdated(address oldRouter, address newRouter); event RateLimitAdminSet(address rateLimitAdmin); struct ChainUpdate { - uint64 remoteChainSelector; // Remote chain selector - bytes[] remotePoolAddresses; // Address of the remote pool, ABI encoded in the case of a remote EVM chain. - bytes remoteTokenAddress; // Address of the remote token, ABI encoded in the case of a remote EVM chain. + uint64 remoteChainSelector; // ──╮ Remote chain selector + bool allowed; // ────────────────╯ Whether the chain should be enabled + bytes remotePoolAddress; // Address of the remote pool, ABI encoded in the case of a remote EVM chain. + bytes remoteTokenAddress; // Address of the remote token, ABI encoded in the case of a remote EVM chain. RateLimiter.Config outboundRateLimiterConfig; // Outbound rate limited config, meaning the rate limits for all of the onRamps for the given chain RateLimiter.Config inboundRateLimiterConfig; // Inbound rate limited config, meaning the rate limits for all of the offRamps for the given chain } @@ -90,22 +67,20 @@ abstract contract TokenPool is IPoolV1, Ownable2StepMsgSender { struct RemoteChainConfig { RateLimiter.TokenBucket outboundRateLimiterConfig; // Outbound rate limited config, meaning the rate limits for all of the onRamps for the given chain RateLimiter.TokenBucket inboundRateLimiterConfig; // Inbound rate limited config, meaning the rate limits for all of the offRamps for the given chain + bytes remotePoolAddress; // Address of the remote pool, ABI encoded in the case of a remote EVM chain. bytes remoteTokenAddress; // Address of the remote token, ABI encoded in the case of a remote EVM chain. - EnumerableSet.Bytes32Set remotePools; // Set of remote pool hashes, ABI encoded in the case of a remote EVM chain. } - /// @dev The bridgeable token that is managed by this pool. Pools could support multiple tokens at the same time if - /// required, but this implementation only supports one token. + /// @dev The bridgeable token that is managed by this pool. IERC20 internal immutable i_token; - /// @dev The number of decimals of the token managed by this pool. - uint8 internal immutable i_tokenDecimals; /// @dev The address of the RMN proxy address internal immutable i_rmnProxy; /// @dev The immutable flag that indicates if the pool is access-controlled. bool internal immutable i_allowlistEnabled; /// @dev A set of addresses allowed to trigger lockOrBurn as original senders. /// Only takes effect if i_allowlistEnabled is true. - /// This can be used to ensure only token-issuer specified addresses can move tokens. + /// This can be used to ensure only token-issuer specified addresses can + /// move tokens. EnumerableSet.AddressSet internal s_allowlist; /// @dev The address of the router IRouter internal s_router; @@ -114,28 +89,14 @@ abstract contract TokenPool is IPoolV1, Ownable2StepMsgSender { /// @dev The chain selectors are in uint256 format because of the EnumerableSet implementation. EnumerableSet.UintSet internal s_remoteChainSelectors; mapping(uint64 remoteChainSelector => RemoteChainConfig) internal s_remoteChainConfigs; - /// @notice A mapping of hashed pool addresses to their unhashed form. This is used to be able to find the actually - /// configured pools and not just their hashed versions. - mapping(bytes32 poolAddressHash => bytes poolAddress) internal s_remotePoolAddresses; /// @notice The address of the rate limiter admin. /// @dev Can be address(0) if none is configured. address internal s_rateLimitAdmin; - constructor(IERC20 token, uint8 localTokenDecimals, address[] memory allowlist, address rmnProxy, address router) { + constructor(IERC20 token, address[] memory allowlist, address rmnProxy, address router) { if (address(token) == address(0) || router == address(0) || rmnProxy == address(0)) revert ZeroAddressNotAllowed(); i_token = token; i_rmnProxy = rmnProxy; - - try IERC20Metadata(address(token)).decimals() returns (uint8 actualTokenDecimals) { - if (localTokenDecimals != actualTokenDecimals) { - revert InvalidDecimalArgs(localTokenDecimals, actualTokenDecimals); - } - } catch { - // The decimals function doesn't exist, which is possible since it's optional in the ERC20 spec. We skip the check and - // assume the supplied token decimals are correct. - } - i_tokenDecimals = localTokenDecimals; - s_router = IRouter(router); // Pool can be set as permissioned or permissionless at deployment time only to save hot-path gas. @@ -145,6 +106,12 @@ abstract contract TokenPool is IPoolV1, Ownable2StepMsgSender { } } + /// @notice Get RMN proxy address + /// @return rmnProxy Address of RMN proxy + function getRmnProxy() public view returns (address rmnProxy) { + return i_rmnProxy; + } + /// @inheritdoc IPoolV1 function isSupportedToken( address token @@ -158,12 +125,6 @@ abstract contract TokenPool is IPoolV1, Ownable2StepMsgSender { return i_token; } - /// @notice Get RMN proxy address - /// @return rmnProxy Address of RMN proxy - function getRmnProxy() public view returns (address rmnProxy) { - return i_rmnProxy; - } - /// @notice Gets the pool's Router /// @return router The pool's Router function getRouter() public view returns (address router) { @@ -204,7 +165,7 @@ abstract contract TokenPool is IPoolV1, Ownable2StepMsgSender { /// @dev This function should always be called before executing a lock or burn. Not doing so would allow /// for various exploits. function _validateLockOrBurn( - Pool.LockOrBurnInV1 calldata lockOrBurnIn + Pool.LockOrBurnInV1 memory lockOrBurnIn ) internal { if (!isSupportedToken(lockOrBurnIn.localToken)) revert InvalidToken(lockOrBurnIn.localToken); if (IRMN(i_rmnProxy).isCursed(bytes16(uint128(lockOrBurnIn.remoteChainSelector)))) revert CursedByRMN(); @@ -224,83 +185,23 @@ abstract contract TokenPool is IPoolV1, Ownable2StepMsgSender { /// @dev This function should always be called before executing a release or mint. Not doing so would allow /// for various exploits. function _validateReleaseOrMint( - Pool.ReleaseOrMintInV1 calldata releaseOrMintIn + Pool.ReleaseOrMintInV1 memory releaseOrMintIn ) internal { if (!isSupportedToken(releaseOrMintIn.localToken)) revert InvalidToken(releaseOrMintIn.localToken); if (IRMN(i_rmnProxy).isCursed(bytes16(uint128(releaseOrMintIn.remoteChainSelector)))) revert CursedByRMN(); _onlyOffRamp(releaseOrMintIn.remoteChainSelector); // Validates that the source pool address is configured on this pool. - if (!isRemotePool(releaseOrMintIn.remoteChainSelector, releaseOrMintIn.sourcePoolAddress)) { + bytes memory configuredRemotePool = getRemotePool(releaseOrMintIn.remoteChainSelector); + if ( + configuredRemotePool.length == 0 + || keccak256(releaseOrMintIn.sourcePoolAddress) != keccak256(configuredRemotePool) + ) { revert InvalidSourcePoolAddress(releaseOrMintIn.sourcePoolAddress); } - _consumeInboundRateLimit(releaseOrMintIn.remoteChainSelector, releaseOrMintIn.amount); } - // ================================================================ - // │ Token decimals │ - // ================================================================ - - /// @notice Gets the IERC20 token decimals on the local chain. - function getTokenDecimals() public view virtual returns (uint8 decimals) { - return i_tokenDecimals; - } - - function _encodeLocalDecimals() internal view virtual returns (bytes memory) { - return abi.encode(i_tokenDecimals); - } - - function _parseRemoteDecimals( - bytes memory sourcePoolData - ) internal view virtual returns (uint8) { - // Fallback to the local token decimals if the source pool data is empty. This allows for backwards compatibility. - if (sourcePoolData.length == 0) { - return i_tokenDecimals; - } - if (sourcePoolData.length != 32) { - revert InvalidRemoteChainDecimals(sourcePoolData); - } - uint256 remoteDecimals = abi.decode(sourcePoolData, (uint256)); - if (remoteDecimals > type(uint8).max) { - revert InvalidRemoteChainDecimals(sourcePoolData); - } - return uint8(remoteDecimals); - } - - /// @notice Calculates the local amount based on the remote amount and decimals. - /// @param remoteAmount The amount on the remote chain. - /// @param remoteDecimals The decimals of the token on the remote chain. - /// @return The local amount. - /// @dev This function protects against overflows. If there is a transaction that hits the overflow check, it is - /// probably incorrect as that means the amount cannot be represented on this chain. If the local decimals have been - /// wrongly configured, the token issuer could redeploy the pool with the correct decimals and manually re-execute the - /// CCIP tx to fix the issue. - function _calculateLocalAmount(uint256 remoteAmount, uint8 remoteDecimals) internal view virtual returns (uint256) { - if (remoteDecimals == i_tokenDecimals) { - return remoteAmount; - } - if (remoteDecimals > i_tokenDecimals) { - uint8 decimalsDiff = remoteDecimals - i_tokenDecimals; - if (decimalsDiff > 77) { - // This is a safety check to prevent overflow in the next calculation. - revert OverflowDetected(remoteDecimals, i_tokenDecimals, remoteAmount); - } - // Solidity rounds down so there is no risk of minting more tokens than the remote chain sent. - return remoteAmount / (10 ** decimalsDiff); - } - - // This is a safety check to prevent overflow in the next calculation. - // More than 77 would never fit in a uint256 and would cause an overflow. We also check if the resulting amount - // would overflow. - uint8 diffDecimals = i_tokenDecimals - remoteDecimals; - if (diffDecimals > 77 || remoteAmount > type(uint256).max / (10 ** diffDecimals)) { - revert OverflowDetected(remoteDecimals, i_tokenDecimals, remoteAmount); - } - - return remoteAmount * (10 ** diffDecimals); - } - // ================================================================ // │ Chain permissions │ // ================================================================ @@ -308,24 +209,10 @@ abstract contract TokenPool is IPoolV1, Ownable2StepMsgSender { /// @notice Gets the pool address on the remote chain. /// @param remoteChainSelector Remote chain selector. /// @dev To support non-evm chains, this value is encoded into bytes - function getRemotePools( + function getRemotePool( uint64 remoteChainSelector - ) public view returns (bytes[] memory) { - bytes32[] memory remotePoolHashes = s_remoteChainConfigs[remoteChainSelector].remotePools.values(); - - bytes[] memory remotePools = new bytes[](remotePoolHashes.length); - for (uint256 i = 0; i < remotePoolHashes.length; ++i) { - remotePools[i] = s_remotePoolAddresses[remotePoolHashes[i]]; - } - - return remotePools; - } - - /// @notice Checks if the pool address is configured on the remote chain. - /// @param remoteChainSelector Remote chain selector. - /// @param remotePoolAddress The address of the remote pool. - function isRemotePool(uint64 remoteChainSelector, bytes calldata remotePoolAddress) public view returns (bool) { - return s_remoteChainConfigs[remoteChainSelector].remotePools.contains(keccak256(remotePoolAddress)); + ) public view returns (bytes memory) { + return s_remoteChainConfigs[remoteChainSelector].remotePoolAddress; } /// @notice Gets the token address on the remote chain. @@ -337,28 +224,16 @@ abstract contract TokenPool is IPoolV1, Ownable2StepMsgSender { return s_remoteChainConfigs[remoteChainSelector].remoteTokenAddress; } - /// @notice Adds a remote pool for a given chain selector. This could be due to a pool being upgraded on the remote - /// chain. We don't simply want to replace the old pool as there could still be valid inflight messages from the old - /// pool. This function allows for multiple pools to be added for a single chain selector. - /// @param remoteChainSelector The remote chain selector for which the remote pool address is being added. - /// @param remotePoolAddress The address of the new remote pool. - function addRemotePool(uint64 remoteChainSelector, bytes calldata remotePoolAddress) external onlyOwner { - if (!isSupportedChain(remoteChainSelector)) revert NonExistentChain(remoteChainSelector); - - _setRemotePool(remoteChainSelector, remotePoolAddress); - } - - /// @notice Removes the remote pool address for a given chain selector. - /// @dev All inflight txs from the remote pool will be rejected after it is removed. To ensure no loss of funds, there - /// should be no inflight txs from the given pool. - function removeRemotePool(uint64 remoteChainSelector, bytes calldata remotePoolAddress) external onlyOwner { + /// @notice Sets the remote pool address for a given chain selector. + /// @param remoteChainSelector The remote chain selector for which the remote pool address is being set. + /// @param remotePoolAddress The address of the remote pool. + function setRemotePool(uint64 remoteChainSelector, bytes calldata remotePoolAddress) external onlyOwner { if (!isSupportedChain(remoteChainSelector)) revert NonExistentChain(remoteChainSelector); - if (!s_remoteChainConfigs[remoteChainSelector].remotePools.remove(keccak256(remotePoolAddress))) { - revert InvalidRemotePoolForChain(remoteChainSelector, remotePoolAddress); - } + bytes memory prevAddress = s_remoteChainConfigs[remoteChainSelector].remotePoolAddress; + s_remoteChainConfigs[remoteChainSelector].remotePoolAddress = remotePoolAddress; - emit RemotePoolRemoved(remoteChainSelector, remotePoolAddress); + emit RemotePoolSet(remoteChainSelector, prevAddress, remotePoolAddress); } /// @inheritdoc IPoolV1 @@ -382,120 +257,69 @@ abstract contract TokenPool is IPoolV1, Ownable2StepMsgSender { /// @notice Sets the permissions for a list of chains selectors. Actual senders for these chains /// need to be allowed on the Router to interact with this pool. - /// @param remoteChainSelectorsToRemove A list of chain selectors to remove. - /// @param chainsToAdd A list of chains and their new permission status & rate limits. Rate limits - /// are only used when the chain is being added through `allowed` being true. /// @dev Only callable by the owner + /// @param chains A list of chains and their new permission status & rate limits. Rate limits + /// are only used when the chain is being added through `allowed` being true. function applyChainUpdates( - uint64[] calldata remoteChainSelectorsToRemove, - ChainUpdate[] calldata chainsToAdd + ChainUpdate[] calldata chains ) external virtual onlyOwner { - for (uint256 i = 0; i < remoteChainSelectorsToRemove.length; ++i) { - uint64 remoteChainSelectorToRemove = remoteChainSelectorsToRemove[i]; - // If the chain doesn't exist, revert - if (!s_remoteChainSelectors.remove(remoteChainSelectorToRemove)) { - revert NonExistentChain(remoteChainSelectorToRemove); - } - - // Remove all remote pool hashes for the chain - bytes32[] memory remotePools = s_remoteChainConfigs[remoteChainSelectorToRemove].remotePools.values(); - for (uint256 j = 0; j < remotePools.length; ++j) { - s_remoteChainConfigs[remoteChainSelectorToRemove].remotePools.remove(remotePools[j]); - } - - delete s_remoteChainConfigs[remoteChainSelectorToRemove]; - - emit ChainRemoved(remoteChainSelectorToRemove); - } - - for (uint256 i = 0; i < chainsToAdd.length; ++i) { - ChainUpdate memory newChain = chainsToAdd[i]; - RateLimiter._validateTokenBucketConfig(newChain.outboundRateLimiterConfig, false); - RateLimiter._validateTokenBucketConfig(newChain.inboundRateLimiterConfig, false); - - if (newChain.remoteTokenAddress.length == 0) { - revert ZeroAddressNotAllowed(); - } - - // If the chain already exists, revert - if (!s_remoteChainSelectors.add(newChain.remoteChainSelector)) { - revert ChainAlreadyExists(newChain.remoteChainSelector); - } - - RemoteChainConfig storage remoteChainConfig = s_remoteChainConfigs[newChain.remoteChainSelector]; - - remoteChainConfig.outboundRateLimiterConfig = RateLimiter.TokenBucket({ - rate: newChain.outboundRateLimiterConfig.rate, - capacity: newChain.outboundRateLimiterConfig.capacity, - tokens: newChain.outboundRateLimiterConfig.capacity, - lastUpdated: uint32(block.timestamp), - isEnabled: newChain.outboundRateLimiterConfig.isEnabled - }); - remoteChainConfig.inboundRateLimiterConfig = RateLimiter.TokenBucket({ - rate: newChain.inboundRateLimiterConfig.rate, - capacity: newChain.inboundRateLimiterConfig.capacity, - tokens: newChain.inboundRateLimiterConfig.capacity, - lastUpdated: uint32(block.timestamp), - isEnabled: newChain.inboundRateLimiterConfig.isEnabled - }); - remoteChainConfig.remoteTokenAddress = newChain.remoteTokenAddress; - - for (uint256 j = 0; j < newChain.remotePoolAddresses.length; ++j) { - _setRemotePool(newChain.remoteChainSelector, newChain.remotePoolAddresses[j]); + for (uint256 i = 0; i < chains.length; ++i) { + ChainUpdate memory update = chains[i]; + RateLimiter._validateTokenBucketConfig(update.outboundRateLimiterConfig, !update.allowed); + RateLimiter._validateTokenBucketConfig(update.inboundRateLimiterConfig, !update.allowed); + + if (update.allowed) { + // If the chain already exists, revert + if (!s_remoteChainSelectors.add(update.remoteChainSelector)) { + revert ChainAlreadyExists(update.remoteChainSelector); + } + + if (update.remotePoolAddress.length == 0 || update.remoteTokenAddress.length == 0) { + revert ZeroAddressNotAllowed(); + } + + s_remoteChainConfigs[update.remoteChainSelector] = RemoteChainConfig({ + outboundRateLimiterConfig: RateLimiter.TokenBucket({ + rate: update.outboundRateLimiterConfig.rate, + capacity: update.outboundRateLimiterConfig.capacity, + tokens: update.outboundRateLimiterConfig.capacity, + lastUpdated: uint32(block.timestamp), + isEnabled: update.outboundRateLimiterConfig.isEnabled + }), + inboundRateLimiterConfig: RateLimiter.TokenBucket({ + rate: update.inboundRateLimiterConfig.rate, + capacity: update.inboundRateLimiterConfig.capacity, + tokens: update.inboundRateLimiterConfig.capacity, + lastUpdated: uint32(block.timestamp), + isEnabled: update.inboundRateLimiterConfig.isEnabled + }), + remotePoolAddress: update.remotePoolAddress, + remoteTokenAddress: update.remoteTokenAddress + }); + + emit ChainAdded( + update.remoteChainSelector, + update.remoteTokenAddress, + update.outboundRateLimiterConfig, + update.inboundRateLimiterConfig + ); + } else { + // If the chain doesn't exist, revert + if (!s_remoteChainSelectors.remove(update.remoteChainSelector)) { + revert NonExistentChain(update.remoteChainSelector); + } + + delete s_remoteChainConfigs[update.remoteChainSelector]; + + emit ChainRemoved(update.remoteChainSelector); } - - emit ChainAdded( - newChain.remoteChainSelector, - newChain.remoteTokenAddress, - newChain.outboundRateLimiterConfig, - newChain.inboundRateLimiterConfig - ); - } - } - - /// @notice Adds a pool address to the allowed remote token pools for a particular chain. - /// @param remoteChainSelector The remote chain selector for which the remote pool address is being added. - /// @param remotePoolAddress The address of the new remote pool. - function _setRemotePool(uint64 remoteChainSelector, bytes memory remotePoolAddress) internal { - if (remotePoolAddress.length == 0) { - revert ZeroAddressNotAllowed(); - } - - bytes32 poolHash = keccak256(remotePoolAddress); - - // Check if the pool already exists. - if (!s_remoteChainConfigs[remoteChainSelector].remotePools.add(poolHash)) { - revert PoolAlreadyAdded(remoteChainSelector, remotePoolAddress); } - - // Add the pool to the mapping to be able to un-hash it later. - s_remotePoolAddresses[poolHash] = remotePoolAddress; - - emit RemotePoolAdded(remoteChainSelector, remotePoolAddress); } // ================================================================ // │ Rate limiting │ // ================================================================ - /// @dev The inbound rate limits should be slightly higher than the outbound rate limits. This is because many chains - /// finalize blocks in batches. CCIP also commits messages in batches: the commit plugin bundles multiple messages in - /// a single merkle root. - /// Imagine the following scenario. - /// - Chain A has an inbound and outbound rate limit of 100 tokens capacity and 1 token per second refill rate. - /// - Chain B has an inbound and outbound rate limit of 100 tokens capacity and 1 token per second refill rate. - /// - /// At time 0: - /// - Chain A sends 100 tokens to Chain B. - /// At time 5: - /// - Chain A sends 5 tokens to Chain B. - /// At time 6: - /// The epoch that contains blocks [0-5] is finalized. - /// Both transactions will be included in the same merkle root and become executable at the same time. This means - /// the token pool on chain B requires a capacity of 105 to successfully execute both messages at the same time. - /// The exact additional capacity required depends on the refill rate and the size of the source chain epochs and the - /// CCIP round time. For simplicity, a 5-10% buffer should be sufficient in most cases. - /// @notice Sets the rate limiter admin address. /// @dev Only callable by the owner. /// @param rateLimitAdmin The new rate limiter admin address. @@ -537,25 +361,6 @@ abstract contract TokenPool is IPoolV1, Ownable2StepMsgSender { return s_remoteChainConfigs[remoteChainSelector].inboundRateLimiterConfig._currentTokenBucketState(); } - /// @notice Sets multiple chain rate limiter configs. - /// @param remoteChainSelectors The remote chain selector for which the rate limits apply. - /// @param outboundConfigs The new outbound rate limiter config, meaning the onRamp rate limits for the given chain. - /// @param inboundConfigs The new inbound rate limiter config, meaning the offRamp rate limits for the given chain. - function setChainRateLimiterConfigs( - uint64[] calldata remoteChainSelectors, - RateLimiter.Config[] calldata outboundConfigs, - RateLimiter.Config[] calldata inboundConfigs - ) external { - if (msg.sender != s_rateLimitAdmin && msg.sender != owner()) revert Unauthorized(msg.sender); - if (remoteChainSelectors.length != outboundConfigs.length || remoteChainSelectors.length != inboundConfigs.length) { - revert MismatchedArrayLengths(); - } - - for (uint256 i = 0; i < remoteChainSelectors.length; ++i) { - _setRateLimitConfig(remoteChainSelectors[i], outboundConfigs[i], inboundConfigs[i]); - } - } - /// @notice Sets the chain rate limiter config. /// @param remoteChainSelector The remote chain selector for which the rate limits apply. /// @param outboundConfig The new outbound rate limiter config, meaning the onRamp rate limits for the given chain. diff --git a/contracts/src/v0.8/ccip/pools/USDC/BurnMintWithLockReleaseFlagTokenPool.sol b/contracts/src/v0.8/ccip/pools/USDC/BurnMintWithLockReleaseFlagTokenPool.sol index 6b46dfacca6..fd54387620f 100644 --- a/contracts/src/v0.8/ccip/pools/USDC/BurnMintWithLockReleaseFlagTokenPool.sol +++ b/contracts/src/v0.8/ccip/pools/USDC/BurnMintWithLockReleaseFlagTokenPool.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import {IBurnMintERC20} from "../../../shared/token/ERC20/IBurnMintERC20.sol"; @@ -15,11 +15,10 @@ import {LOCK_RELEASE_FLAG} from "./HybridLockReleaseUSDCTokenPool.sol"; contract BurnMintWithLockReleaseFlagTokenPool is BurnMintTokenPool { constructor( IBurnMintERC20 token, - uint8 localTokenDecimals, address[] memory allowlist, address rmnProxy, address router - ) BurnMintTokenPool(token, localTokenDecimals, allowlist, rmnProxy, router) {} + ) BurnMintTokenPool(token, allowlist, rmnProxy, router) {} /// @notice Burn the token in the pool /// @dev The _validateLockOrBurn check is an essential security check diff --git a/contracts/src/v0.8/ccip/pools/USDC/HybridLockReleaseUSDCTokenPool.sol b/contracts/src/v0.8/ccip/pools/USDC/HybridLockReleaseUSDCTokenPool.sol index 89e609fcc5e..264b1230c7c 100644 --- a/contracts/src/v0.8/ccip/pools/USDC/HybridLockReleaseUSDCTokenPool.sol +++ b/contracts/src/v0.8/ccip/pools/USDC/HybridLockReleaseUSDCTokenPool.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import {ILiquidityContainer} from "../../../liquiditymanager/interfaces/ILiquidityContainer.sol"; import {ITokenMessenger} from "../USDC/ITokenMessenger.sol"; diff --git a/contracts/src/v0.8/ccip/pools/USDC/USDCBridgeMigrator.sol b/contracts/src/v0.8/ccip/pools/USDC/USDCBridgeMigrator.sol index a8ad7052110..1dcecac8b2f 100644 --- a/contracts/src/v0.8/ccip/pools/USDC/USDCBridgeMigrator.sol +++ b/contracts/src/v0.8/ccip/pools/USDC/USDCBridgeMigrator.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import {Ownable2StepMsgSender} from "../../../shared/access/Ownable2StepMsgSender.sol"; import {IBurnMintERC20} from "../../../shared/token/ERC20/IBurnMintERC20.sol"; diff --git a/contracts/src/v0.8/ccip/pools/USDC/USDCTokenPool.sol b/contracts/src/v0.8/ccip/pools/USDC/USDCTokenPool.sol index 524f8f47f70..addfe06da0b 100644 --- a/contracts/src/v0.8/ccip/pools/USDC/USDCTokenPool.sol +++ b/contracts/src/v0.8/ccip/pools/USDC/USDCTokenPool.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import {ITypeAndVersion} from "../../../shared/interfaces/ITypeAndVersion.sol"; import {IMessageTransmitter} from "./IMessageTransmitter.sol"; @@ -50,7 +50,7 @@ contract USDCTokenPool is TokenPool, ITypeAndVersion { uint32 sourceDomain; } - string public constant override typeAndVersion = "USDCTokenPool 1.5.1"; + string public constant override typeAndVersion = "USDCTokenPool 1.5.0"; // We restrict to the first version. New pool may be required for subsequent versions. uint32 public constant SUPPORTED_USDC_VERSION = 0; @@ -78,7 +78,7 @@ contract USDCTokenPool is TokenPool, ITypeAndVersion { address[] memory allowlist, address rmnProxy, address router - ) TokenPool(token, 6, allowlist, rmnProxy, router) { + ) TokenPool(token, allowlist, rmnProxy, router) { if (address(tokenMessenger) == address(0)) revert InvalidConfig(); IMessageTransmitter transmitter = IMessageTransmitter(tokenMessenger.localMessageTransmitter()); uint32 transmitterVersion = transmitter.version(); @@ -126,7 +126,7 @@ contract USDCTokenPool is TokenPool, ITypeAndVersion { /// @notice Mint tokens from the pool to the recipient /// * sourceTokenData is part of the verified message and passed directly from - /// the offRamp so it is guaranteed to be what the lockOrBurn pool released on the + /// the offramp so it is guaranteed to be what the lockOrBurn pool released on the /// source chain. It contains (nonce, sourceDomain) which is guaranteed by CCTP /// to be unique. /// * offchainTokenData is untrusted (can be supplied by manual execution), but we assert diff --git a/contracts/src/v0.8/ccip/rmn/ARMProxy.sol b/contracts/src/v0.8/ccip/rmn/ARMProxy.sol index 31b52101b81..964582686be 100644 --- a/contracts/src/v0.8/ccip/rmn/ARMProxy.sol +++ b/contracts/src/v0.8/ccip/rmn/ARMProxy.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import {ITypeAndVersion} from "../../shared/interfaces/ITypeAndVersion.sol"; diff --git a/contracts/src/v0.8/ccip/rmn/RMNHome.sol b/contracts/src/v0.8/ccip/rmn/RMNHome.sol index 4fd01a7115b..684dc3e994e 100644 --- a/contracts/src/v0.8/ccip/rmn/RMNHome.sol +++ b/contracts/src/v0.8/ccip/rmn/RMNHome.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import {ITypeAndVersion} from "../../shared/interfaces/ITypeAndVersion.sol"; @@ -54,7 +54,7 @@ import {Ownable2StepMsgSender} from "../../shared/access/Ownable2StepMsgSender.s /// │ Active │ revokeCandidate │ Candidate │◄───────────┐ /// │ [1,0] │◄───────────────────┤ [1,1] │────────────┘ /// │ ├───────────────────►│ │ -/// └─────────────┘ setCandidate └─────────────┘ +/// └─────────────┘ setSecondary └─────────────┘ /// contract RMNHome is Ownable2StepMsgSender, ITypeAndVersion { event ConfigSet(bytes32 indexed configDigest, uint32 version, StaticConfig staticConfig, DynamicConfig dynamicConfig); diff --git a/contracts/src/v0.8/ccip/rmn/RMNRemote.sol b/contracts/src/v0.8/ccip/rmn/RMNRemote.sol index 4f96e2bc8f2..5faa1d720e7 100644 --- a/contracts/src/v0.8/ccip/rmn/RMNRemote.sol +++ b/contracts/src/v0.8/ccip/rmn/RMNRemote.sol @@ -1,24 +1,25 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import {ITypeAndVersion} from "../../shared/interfaces/ITypeAndVersion.sol"; -import {IRMN} from "../interfaces/IRMN.sol"; import {IRMNRemote} from "../interfaces/IRMNRemote.sol"; import {Ownable2StepMsgSender} from "../../shared/access/Ownable2StepMsgSender.sol"; import {EnumerableSet} from "../../shared/enumerable/EnumerableSetWithBytes16.sol"; import {Internal} from "../libraries/Internal.sol"; +/// @dev An active curse on this subject will cause isCursed() to return true. Use this subject if there is an issue +/// with a remote chain, for which there exists a legacy lane contract deployed on the same chain as this RMN contract +/// is deployed, relying on isCursed(). +bytes16 constant LEGACY_CURSE_SUBJECT = 0x01000000000000000000000000000000; + /// @dev An active curse on this subject will cause isCursed() and isCursed(bytes16) to return true. Use this subject /// for issues affecting all of CCIP chains, or pertaining to the chain that this contract is deployed on, instead of /// using the local chain selector as a subject. bytes16 constant GLOBAL_CURSE_SUBJECT = 0x01000000000000000000000000000001; /// @notice This contract supports verification of RMN reports for any Any2EVM OffRamp. -/// @dev This contract implements both the new IRMNRemote interface and the legacy IRMN interface. This is to allow for -/// a seamless migration from the legacy RMN contract to this one. The only function that has been dropped in the newer -/// interface is `isBlessed`. For the `isBlessed` function, this contract relays the call to the legacy RMN contract. -contract RMNRemote is Ownable2StepMsgSender, ITypeAndVersion, IRMNRemote, IRMN { +contract RMNRemote is Ownable2StepMsgSender, ITypeAndVersion, IRMNRemote { using EnumerableSet for EnumerableSet.Bytes16Set; error AlreadyCursed(bytes16 subject); @@ -32,7 +33,6 @@ contract RMNRemote is Ownable2StepMsgSender, ITypeAndVersion, IRMNRemote, IRMN { error ThresholdNotMet(); error UnexpectedSigner(); error ZeroValueNotAllowed(); - error IsBlessedNotAvailable(); event ConfigSet(uint32 indexed version, Config config); event Cursed(bytes16[] subjects); @@ -67,7 +67,6 @@ contract RMNRemote is Ownable2StepMsgSender, ITypeAndVersion, IRMNRemote, IRMN { string public constant override typeAndVersion = "RMNRemote 1.6.0-dev"; uint64 internal immutable i_localChainSelector; - IRMN internal immutable i_legacyRMN; Config private s_config; uint32 private s_configCount; @@ -81,11 +80,11 @@ contract RMNRemote is Ownable2StepMsgSender, ITypeAndVersion, IRMNRemote, IRMN { mapping(address signer => bool exists) private s_signers; // for more gas efficient verify. /// @param localChainSelector the chain selector of the chain this contract is deployed to. - constructor(uint64 localChainSelector, IRMN legacyRMN) { + constructor( + uint64 localChainSelector + ) { if (localChainSelector == 0) revert ZeroValueNotAllowed(); i_localChainSelector = localChainSelector; - - i_legacyRMN = legacyRMN; } // ================================================================ @@ -94,7 +93,7 @@ contract RMNRemote is Ownable2StepMsgSender, ITypeAndVersion, IRMNRemote, IRMN { /// @inheritdoc IRMNRemote function verify( - address offRampAddress, + address offrampAddress, Internal.MerkleRoot[] calldata merkleRoots, Signature[] calldata signatures ) external view { @@ -110,7 +109,7 @@ contract RMNRemote is Ownable2StepMsgSender, ITypeAndVersion, IRMNRemote, IRMN { destChainId: block.chainid, destChainSelector: i_localChainSelector, rmnRemoteContractAddress: address(this), - offrampAddress: offRampAddress, + offrampAddress: offrampAddress, rmnHomeContractConfigDigest: s_config.rmnHomeContractConfigDigest, merkleRoots: merkleRoots }) @@ -249,19 +248,19 @@ contract RMNRemote is Ownable2StepMsgSender, ITypeAndVersion, IRMNRemote, IRMN { } /// @inheritdoc IRMNRemote - function isCursed() external view override(IRMN, IRMNRemote) returns (bool) { + function isCursed() external view returns (bool) { // There are zero curses under normal circumstances, which means it's cheaper to check for the absence of curses. - // than to check the subject list for the global curse subject. + // than to check the subject list twice, as we have to check for both the legacy and global curse subjects. if (s_cursedSubjects.length() == 0) { return false; } - return s_cursedSubjects.contains(GLOBAL_CURSE_SUBJECT); + return s_cursedSubjects.contains(LEGACY_CURSE_SUBJECT) || s_cursedSubjects.contains(GLOBAL_CURSE_SUBJECT); } /// @inheritdoc IRMNRemote function isCursed( bytes16 subject - ) external view override(IRMN, IRMNRemote) returns (bool) { + ) external view returns (bool) { // There are zero curses under normal circumstances, which means it's cheaper to check for the absence of curses. // than to check the subject list twice, as we have to check for both the given and global curse subjects. if (s_cursedSubjects.length() == 0) { @@ -269,20 +268,4 @@ contract RMNRemote is Ownable2StepMsgSender, ITypeAndVersion, IRMNRemote, IRMN { } return s_cursedSubjects.contains(subject) || s_cursedSubjects.contains(GLOBAL_CURSE_SUBJECT); } - - // ================================================================ - // │ Legacy pass through │ - // ================================================================ - - /// @inheritdoc IRMN - /// @dev This function is only expected to be used for messages from CCIP versions below 1.6. - function isBlessed( - TaggedRoot calldata taggedRoot - ) external view returns (bool) { - if (i_legacyRMN == IRMN(address(0))) { - revert IsBlessedNotAvailable(); - } - - return i_legacyRMN.isBlessed(taggedRoot); - } } diff --git a/contracts/src/v0.8/ccip/test/BaseTest.t.sol b/contracts/src/v0.8/ccip/test/BaseTest.t.sol index 1d30a8f589f..2770f0fb4d6 100644 --- a/contracts/src/v0.8/ccip/test/BaseTest.t.sol +++ b/contracts/src/v0.8/ccip/test/BaseTest.t.sol @@ -1,39 +1,53 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; // Imports to any non-library are not allowed due to the significant cascading // compile time increase they cause when imported into this base test. -import {IRMNRemote} from "../interfaces/IRMNRemote.sol"; -import {Router} from "../Router.sol"; +import {IRMNRemote} from "../interfaces/IRMNRemote.sol"; import {Internal} from "../libraries/Internal.sol"; import {RateLimiter} from "../libraries/RateLimiter.sol"; -import {WETH9} from "./WETH9.sol"; - +import {MockRMN} from "./mocks/MockRMN.sol"; import {Test} from "forge-std/Test.sol"; contract BaseTest is Test { + // Addresses address internal constant OWNER = 0x00007e64E1fB0C487F25dd6D3601ff6aF8d32e4e; address internal constant STRANGER = address(999999); - // Timing - uint256 internal constant BLOCK_TIME = 1234567890; - uint32 internal constant TWELVE_HOURS = 60 * 60 * 12; + address internal constant USER_1 = address(1); // Message info uint64 internal constant SOURCE_CHAIN_SELECTOR = 1; uint64 internal constant DEST_CHAIN_SELECTOR = 2; uint32 internal constant GAS_LIMIT = 200_000; + // Timing + uint256 internal constant BLOCK_TIME = 1234567890; + uint32 internal constant TWELVE_HOURS = 60 * 60 * 12; + + // Onramp + uint96 internal constant MAX_MSG_FEES_JUELS = 1_000e18; + uint32 internal constant DEST_GAS_OVERHEAD = 300_000; + uint16 internal constant DEST_GAS_PER_PAYLOAD_BYTE = 16; + + uint16 internal constant DEFAULT_TOKEN_FEE_USD_CENTS = 50; uint32 internal constant DEFAULT_TOKEN_DEST_GAS_OVERHEAD = 90_000; - uint8 internal constant DEFAULT_TOKEN_DECIMALS = 18; - uint16 internal constant GAS_FOR_CALL_EXACT_CHECK = 5_000; + uint32 internal constant DEFAULT_TOKEN_BYTES_OVERHEAD = 32; bool private s_baseTestInitialized; + // OffRamp + uint32 internal constant MAX_DATA_SIZE = 30_000; + uint16 internal constant MAX_TOKENS_LENGTH = 5; + uint16 internal constant GAS_FOR_CALL_EXACT_CHECK = 5000; + uint32 internal constant MAX_GAS_LIMIT = 4_000_000; + + MockRMN internal s_mockRMN; IRMNRemote internal s_mockRMNRemote; - Router internal s_sourceRouter; - Router internal s_destRouter; + + // nonce for pseudo-random number generation, not to be exposed to test suites + uint256 private s_randNonce; function setUp() public virtual { // BaseTest.setUp is often called multiple times from tests' setUp due to inheritance. @@ -49,18 +63,19 @@ contract BaseTest is Test { // Set the block time to a constant known value vm.warp(BLOCK_TIME); - // setup RMNRemote + // setup mock RMN & RMNRemote + s_mockRMN = new MockRMN(); s_mockRMNRemote = IRMNRemote(makeAddr("MOCK RMN REMOTE")); vm.etch(address(s_mockRMNRemote), bytes("fake bytecode")); vm.mockCall(address(s_mockRMNRemote), abi.encodeWithSelector(IRMNRemote.verify.selector), bytes("")); - vm.mockCall(address(s_mockRMNRemote), abi.encodeWithSignature("isCursed()"), abi.encode(false)); + _setMockRMNGlobalCurse(false); vm.mockCall(address(s_mockRMNRemote), abi.encodeWithSignature("isCursed(bytes16)"), abi.encode(false)); // no curses by defaule + } - s_sourceRouter = new Router(address(new WETH9()), address(s_mockRMNRemote)); - vm.label(address(s_sourceRouter), "sourceRouter"); - // Deploy a destination router - s_destRouter = new Router(address(new WETH9()), address(s_mockRMNRemote)); - vm.label(address(s_destRouter), "destRouter"); + function _setMockRMNGlobalCurse( + bool isCursed + ) internal { + vm.mockCall(address(s_mockRMNRemote), abi.encodeWithSignature("isCursed()"), abi.encode(isCursed)); } function _setMockRMNChainCurse(uint64 chainSelector, bool isCursed) internal { @@ -92,12 +107,18 @@ contract BaseTest is Test { return priceUpdates; } - function _generateSourceTokenData() internal pure returns (Internal.SourceTokenData memory) { - return Internal.SourceTokenData({ - sourcePoolAddress: abi.encode(address(12312412312)), - destTokenAddress: abi.encode(address(9809808909)), - extraData: "", - destGasAmount: DEFAULT_TOKEN_DEST_GAS_OVERHEAD - }); + /// @dev returns a pseudo-random bytes32 + function _randomBytes32() internal returns (bytes32) { + return keccak256(abi.encodePacked(++s_randNonce)); + } + + /// @dev returns a pseudo-random number + function _randomNum() internal returns (uint256) { + return uint256(_randomBytes32()); + } + + /// @dev returns a pseudo-random address + function _randomAddress() internal returns (address) { + return address(uint160(_randomNum())); } } diff --git a/contracts/src/v0.8/ccip/test/NonceManager.t.sol b/contracts/src/v0.8/ccip/test/NonceManager.t.sol new file mode 100644 index 00000000000..b5c3ee6bd99 --- /dev/null +++ b/contracts/src/v0.8/ccip/test/NonceManager.t.sol @@ -0,0 +1,568 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.24; + +import {IEVM2AnyOnRamp} from "../interfaces/IEVM2AnyOnRamp.sol"; + +import {NonceManager} from "../NonceManager.sol"; +import {Client} from "../libraries/Client.sol"; +import {Internal} from "../libraries/Internal.sol"; +import {OffRamp} from "../offRamp/OffRamp.sol"; +import {OnRamp} from "../onRamp/OnRamp.sol"; +import {BaseTest} from "./BaseTest.t.sol"; +import {EVM2EVMOffRampHelper} from "./helpers/EVM2EVMOffRampHelper.sol"; +import {OnRampHelper} from "./helpers/OnRampHelper.sol"; +import {OffRampSetup} from "./offRamp/OffRamp/OffRampSetup.t.sol"; +import {OnRampSetup} from "./onRamp/OnRamp/OnRampSetup.t.sol"; + +import {Test} from "forge-std/Test.sol"; + +contract NonceManager_typeAndVersion is Test { + NonceManager private s_nonceManager; + + function setUp() public { + s_nonceManager = new NonceManager(new address[](0)); + } + + function test_typeAndVersion() public view { + assertEq(s_nonceManager.typeAndVersion(), "NonceManager 1.6.0-dev"); + } +} + +contract NonceManager_NonceIncrementation is BaseTest { + NonceManager private s_nonceManager; + + function setUp() public override { + address[] memory authorizedCallers = new address[](1); + authorizedCallers[0] = address(this); + s_nonceManager = new NonceManager(authorizedCallers); + } + + function test_getIncrementedOutboundNonce_Success() public { + address sender = address(this); + + assertEq(s_nonceManager.getOutboundNonce(DEST_CHAIN_SELECTOR, sender), 0); + + uint64 outboundNonce = s_nonceManager.getIncrementedOutboundNonce(DEST_CHAIN_SELECTOR, sender); + assertEq(outboundNonce, 1); + } + + function test_incrementInboundNonce_Success() public { + address sender = address(this); + + s_nonceManager.incrementInboundNonce(SOURCE_CHAIN_SELECTOR, 1, abi.encode(sender)); + + assertEq(s_nonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR, abi.encode(sender)), 1); + } + + function test_incrementInboundNonce_Skip() public { + address sender = address(this); + uint64 expectedNonce = 2; + + vm.expectEmit(); + emit NonceManager.SkippedIncorrectNonce(SOURCE_CHAIN_SELECTOR, expectedNonce, abi.encode(sender)); + + s_nonceManager.incrementInboundNonce(SOURCE_CHAIN_SELECTOR, expectedNonce, abi.encode(sender)); + + assertEq(s_nonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR, abi.encode(sender)), 0); + } + + function test_incrementNoncesInboundAndOutbound_Success() public { + address sender = address(this); + + assertEq(s_nonceManager.getOutboundNonce(DEST_CHAIN_SELECTOR, sender), 0); + uint64 outboundNonce = s_nonceManager.getIncrementedOutboundNonce(DEST_CHAIN_SELECTOR, sender); + assertEq(outboundNonce, 1); + + // Inbound nonce unchanged + assertEq(s_nonceManager.getInboundNonce(DEST_CHAIN_SELECTOR, abi.encode(sender)), 0); + + s_nonceManager.incrementInboundNonce(DEST_CHAIN_SELECTOR, 1, abi.encode(sender)); + assertEq(s_nonceManager.getInboundNonce(DEST_CHAIN_SELECTOR, abi.encode(sender)), 1); + + // Outbound nonce unchanged + assertEq(s_nonceManager.getOutboundNonce(DEST_CHAIN_SELECTOR, sender), 1); + } +} + +contract NonceManager_applyPreviousRampsUpdates is OnRampSetup { + function test_SingleRampUpdate_success() public { + address prevOnRamp = makeAddr("prevOnRamp"); + address prevOffRamp = makeAddr("prevOffRamp"); + NonceManager.PreviousRampsArgs[] memory previousRamps = new NonceManager.PreviousRampsArgs[](1); + previousRamps[0] = NonceManager.PreviousRampsArgs({ + remoteChainSelector: DEST_CHAIN_SELECTOR, + prevRamps: NonceManager.PreviousRamps(prevOnRamp, prevOffRamp), + overrideExistingRamps: false + }); + + vm.expectEmit(); + emit NonceManager.PreviousRampsUpdated(DEST_CHAIN_SELECTOR, previousRamps[0].prevRamps); + + s_outboundNonceManager.applyPreviousRampsUpdates(previousRamps); + + _assertPreviousRampsEqual(s_outboundNonceManager.getPreviousRamps(DEST_CHAIN_SELECTOR), previousRamps[0].prevRamps); + } + + function test_MultipleRampsUpdates_success() public { + address prevOnRamp1 = makeAddr("prevOnRamp1"); + address prevOnRamp2 = makeAddr("prevOnRamp2"); + address prevOffRamp1 = makeAddr("prevOffRamp1"); + address prevOffRamp2 = makeAddr("prevOffRamp2"); + NonceManager.PreviousRampsArgs[] memory previousRamps = new NonceManager.PreviousRampsArgs[](2); + previousRamps[0] = NonceManager.PreviousRampsArgs({ + remoteChainSelector: DEST_CHAIN_SELECTOR, + prevRamps: NonceManager.PreviousRamps(prevOnRamp1, prevOffRamp1), + overrideExistingRamps: false + }); + previousRamps[1] = NonceManager.PreviousRampsArgs({ + remoteChainSelector: DEST_CHAIN_SELECTOR + 1, + prevRamps: NonceManager.PreviousRamps(prevOnRamp2, prevOffRamp2), + overrideExistingRamps: false + }); + + vm.expectEmit(); + emit NonceManager.PreviousRampsUpdated(DEST_CHAIN_SELECTOR, previousRamps[0].prevRamps); + vm.expectEmit(); + emit NonceManager.PreviousRampsUpdated(DEST_CHAIN_SELECTOR + 1, previousRamps[1].prevRamps); + + s_outboundNonceManager.applyPreviousRampsUpdates(previousRamps); + + _assertPreviousRampsEqual(s_outboundNonceManager.getPreviousRamps(DEST_CHAIN_SELECTOR), previousRamps[0].prevRamps); + _assertPreviousRampsEqual( + s_outboundNonceManager.getPreviousRamps(DEST_CHAIN_SELECTOR + 1), previousRamps[1].prevRamps + ); + } + + function test_PreviousRampAlreadySet_overrideAllowed_success() public { + NonceManager.PreviousRampsArgs[] memory previousRamps = new NonceManager.PreviousRampsArgs[](1); + address prevOffRamp = makeAddr("prevOffRamp"); + previousRamps[0] = NonceManager.PreviousRampsArgs({ + remoteChainSelector: DEST_CHAIN_SELECTOR, + prevRamps: NonceManager.PreviousRamps(address(0), prevOffRamp), + overrideExistingRamps: true + }); + + s_outboundNonceManager.applyPreviousRampsUpdates(previousRamps); + + previousRamps[0] = NonceManager.PreviousRampsArgs({ + remoteChainSelector: DEST_CHAIN_SELECTOR, + prevRamps: NonceManager.PreviousRamps(address(0), prevOffRamp), + overrideExistingRamps: true + }); + + s_outboundNonceManager.applyPreviousRampsUpdates(previousRamps); + } + + function test_ZeroInput_success() public { + vm.recordLogs(); + s_outboundNonceManager.applyPreviousRampsUpdates(new NonceManager.PreviousRampsArgs[](0)); + + assertEq(vm.getRecordedLogs().length, 0); + } + + function test_PreviousRampAlreadySetOnRamp_Revert() public { + NonceManager.PreviousRampsArgs[] memory previousRamps = new NonceManager.PreviousRampsArgs[](1); + address prevOnRamp = makeAddr("prevOnRamp"); + previousRamps[0] = NonceManager.PreviousRampsArgs({ + remoteChainSelector: DEST_CHAIN_SELECTOR, + prevRamps: NonceManager.PreviousRamps(prevOnRamp, address(0)), + overrideExistingRamps: false + }); + + s_outboundNonceManager.applyPreviousRampsUpdates(previousRamps); + + previousRamps[0] = NonceManager.PreviousRampsArgs({ + remoteChainSelector: DEST_CHAIN_SELECTOR, + prevRamps: NonceManager.PreviousRamps(prevOnRamp, address(0)), + overrideExistingRamps: false + }); + + vm.expectRevert(NonceManager.PreviousRampAlreadySet.selector); + s_outboundNonceManager.applyPreviousRampsUpdates(previousRamps); + } + + function test_PreviousRampAlreadySetOffRamp_Revert() public { + NonceManager.PreviousRampsArgs[] memory previousRamps = new NonceManager.PreviousRampsArgs[](1); + address prevOffRamp = makeAddr("prevOffRamp"); + previousRamps[0] = NonceManager.PreviousRampsArgs({ + remoteChainSelector: DEST_CHAIN_SELECTOR, + prevRamps: NonceManager.PreviousRamps(address(0), prevOffRamp), + overrideExistingRamps: false + }); + + s_outboundNonceManager.applyPreviousRampsUpdates(previousRamps); + + previousRamps[0] = NonceManager.PreviousRampsArgs({ + remoteChainSelector: DEST_CHAIN_SELECTOR, + prevRamps: NonceManager.PreviousRamps(address(0), prevOffRamp), + overrideExistingRamps: false + }); + + vm.expectRevert(NonceManager.PreviousRampAlreadySet.selector); + s_outboundNonceManager.applyPreviousRampsUpdates(previousRamps); + } + + function test_PreviousRampAlreadySetOnRampAndOffRamp_Revert() public { + NonceManager.PreviousRampsArgs[] memory previousRamps = new NonceManager.PreviousRampsArgs[](1); + address prevOnRamp = makeAddr("prevOnRamp"); + address prevOffRamp = makeAddr("prevOffRamp"); + previousRamps[0] = NonceManager.PreviousRampsArgs({ + remoteChainSelector: DEST_CHAIN_SELECTOR, + prevRamps: NonceManager.PreviousRamps(prevOnRamp, prevOffRamp), + overrideExistingRamps: false + }); + + s_outboundNonceManager.applyPreviousRampsUpdates(previousRamps); + + previousRamps[0] = NonceManager.PreviousRampsArgs({ + remoteChainSelector: DEST_CHAIN_SELECTOR, + prevRamps: NonceManager.PreviousRamps(prevOnRamp, prevOffRamp), + overrideExistingRamps: false + }); + + vm.expectRevert(NonceManager.PreviousRampAlreadySet.selector); + s_outboundNonceManager.applyPreviousRampsUpdates(previousRamps); + } + + function _assertPreviousRampsEqual( + NonceManager.PreviousRamps memory a, + NonceManager.PreviousRamps memory b + ) internal pure { + assertEq(a.prevOnRamp, b.prevOnRamp); + assertEq(a.prevOffRamp, b.prevOffRamp); + } +} + +contract NonceManager_OnRampUpgrade is OnRampSetup { + uint256 internal constant FEE_AMOUNT = 1234567890; + OnRampHelper internal s_prevOnRamp; + + function setUp() public virtual override { + super.setUp(); + + (s_prevOnRamp,) = _deployOnRamp( + SOURCE_CHAIN_SELECTOR, s_sourceRouter, address(s_outboundNonceManager), address(s_tokenAdminRegistry) + ); + + // Since the previous onRamp is not a 1.5 ramp it doesn't have the getSenderNonce function. We mock it to return 0 + vm.mockCall(address(s_prevOnRamp), abi.encodeWithSelector(IEVM2AnyOnRamp.getSenderNonce.selector), abi.encode(0)); + + NonceManager.PreviousRampsArgs[] memory previousRamps = new NonceManager.PreviousRampsArgs[](1); + previousRamps[0] = NonceManager.PreviousRampsArgs({ + remoteChainSelector: DEST_CHAIN_SELECTOR, + prevRamps: NonceManager.PreviousRamps(address(s_prevOnRamp), address(0)), + overrideExistingRamps: false + }); + s_outboundNonceManager.applyPreviousRampsUpdates(previousRamps); + + (s_onRamp, s_metadataHash) = _deployOnRamp( + SOURCE_CHAIN_SELECTOR, s_sourceRouter, address(s_outboundNonceManager), address(s_tokenAdminRegistry) + ); + + vm.startPrank(address(s_sourceRouter)); + } + + function test_Upgrade_Success() public { + Client.EVM2AnyMessage memory message = _generateEmptyMessage(); + + vm.expectEmit(); + emit OnRamp.CCIPMessageSent(DEST_CHAIN_SELECTOR, 1, _messageToEvent(message, 1, 1, FEE_AMOUNT, OWNER)); + + s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, FEE_AMOUNT, OWNER); + } + + function test_UpgradeSenderNoncesReadsPreviousRamp_Success() public { + Client.EVM2AnyMessage memory message = _generateEmptyMessage(); + uint64 startNonce = s_outboundNonceManager.getOutboundNonce(DEST_CHAIN_SELECTOR, OWNER); + + for (uint64 i = 1; i < 4; ++i) { + s_prevOnRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, 0, OWNER); + + assertEq(startNonce + i, s_outboundNonceManager.getOutboundNonce(DEST_CHAIN_SELECTOR, OWNER)); + } + } + + function test_UpgradeNonceStartsAtV1Nonce_Success() public { + Client.EVM2AnyMessage memory message = _generateEmptyMessage(); + + uint64 startNonce = s_outboundNonceManager.getOutboundNonce(DEST_CHAIN_SELECTOR, OWNER); + + // send 1 message from previous onramp + s_prevOnRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, FEE_AMOUNT, OWNER); + + assertEq(startNonce + 1, s_outboundNonceManager.getOutboundNonce(DEST_CHAIN_SELECTOR, OWNER)); + + // new onramp nonce should start from 2, while sequence number start from 1 + vm.expectEmit(); + emit OnRamp.CCIPMessageSent(DEST_CHAIN_SELECTOR, 1, _messageToEvent(message, 1, startNonce + 2, FEE_AMOUNT, OWNER)); + s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, FEE_AMOUNT, OWNER); + + assertEq(startNonce + 2, s_outboundNonceManager.getOutboundNonce(DEST_CHAIN_SELECTOR, OWNER)); + + // after another send, nonce should be 3, and sequence number be 2 + vm.expectEmit(); + emit OnRamp.CCIPMessageSent(DEST_CHAIN_SELECTOR, 2, _messageToEvent(message, 2, startNonce + 3, FEE_AMOUNT, OWNER)); + s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, FEE_AMOUNT, OWNER); + + assertEq(startNonce + 3, s_outboundNonceManager.getOutboundNonce(DEST_CHAIN_SELECTOR, OWNER)); + } + + function test_UpgradeNonceNewSenderStartsAtZero_Success() public { + Client.EVM2AnyMessage memory message = _generateEmptyMessage(); + + // send 1 message from previous onramp from OWNER + s_prevOnRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, FEE_AMOUNT, OWNER); + + address newSender = address(1234567); + // new onramp nonce should start from 1 for new sender + vm.expectEmit(); + emit OnRamp.CCIPMessageSent(DEST_CHAIN_SELECTOR, 1, _messageToEvent(message, 1, 1, FEE_AMOUNT, newSender)); + + s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, FEE_AMOUNT, newSender); + } +} + +contract NonceManager_OffRampUpgrade is OffRampSetup { + EVM2EVMOffRampHelper internal s_prevOffRamp; + + address internal constant SINGLE_LANE_ON_RAMP_ADDRESS_1 = abi.decode(ON_RAMP_ADDRESS_1, (address)); + address internal constant SINGLE_LANE_ON_RAMP_ADDRESS_2 = abi.decode(ON_RAMP_ADDRESS_2, (address)); + address internal constant SINGLE_LANE_ON_RAMP_ADDRESS_3 = abi.decode(ON_RAMP_ADDRESS_3, (address)); + + function setUp() public virtual override { + super.setUp(); + + s_prevOffRamp = new EVM2EVMOffRampHelper(); + + NonceManager.PreviousRampsArgs[] memory previousRamps = new NonceManager.PreviousRampsArgs[](1); + previousRamps[0] = NonceManager.PreviousRampsArgs({ + remoteChainSelector: SOURCE_CHAIN_SELECTOR_1, + prevRamps: NonceManager.PreviousRamps(address(0), address(s_prevOffRamp)), + overrideExistingRamps: false + }); + + s_inboundNonceManager.applyPreviousRampsUpdates(previousRamps); + + OffRamp.SourceChainConfigArgs[] memory sourceChainConfigs = new OffRamp.SourceChainConfigArgs[](3); + sourceChainConfigs[0] = OffRamp.SourceChainConfigArgs({ + router: s_destRouter, + sourceChainSelector: SOURCE_CHAIN_SELECTOR_1, + isEnabled: true, + onRamp: ON_RAMP_ADDRESS_1 + }); + sourceChainConfigs[1] = OffRamp.SourceChainConfigArgs({ + router: s_destRouter, + sourceChainSelector: SOURCE_CHAIN_SELECTOR_2, + isEnabled: true, + onRamp: ON_RAMP_ADDRESS_2 + }); + sourceChainConfigs[2] = OffRamp.SourceChainConfigArgs({ + router: s_destRouter, + sourceChainSelector: SOURCE_CHAIN_SELECTOR_3, + isEnabled: true, + onRamp: ON_RAMP_ADDRESS_3 + }); + + _setupMultipleOffRampsFromConfigs(sourceChainConfigs); + + s_offRamp.setVerifyOverrideResult(SOURCE_CHAIN_SELECTOR_1, 1); + s_offRamp.setVerifyOverrideResult(SOURCE_CHAIN_SELECTOR_3, 1); + } + + function test_Upgraded_Success() public { + Internal.Any2EVMRampMessage[] memory messages = + _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); + + vm.recordLogs(); + s_offRamp.executeSingleReport( + _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), new OffRamp.GasLimitOverride[](0) + ); + _assertExecutionStateChangedEventLogs( + SOURCE_CHAIN_SELECTOR_1, + messages[0].header.sequenceNumber, + messages[0].header.messageId, + _hashMessage(messages[0], ON_RAMP_ADDRESS_1), + Internal.MessageExecutionState.SUCCESS, + "" + ); + } + + function test_NoPrevOffRampForChain_Success() public { + address[] memory senders = new address[](1); + senders[0] = OWNER; + + uint64 startNonceChain3 = s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_3, abi.encode(senders[0])); + s_prevOffRamp.execute(senders); + + // Nonce unchanged for chain 3 + assertEq(startNonceChain3, s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_3, abi.encode(senders[0]))); + + Internal.Any2EVMRampMessage[] memory messagesChain3 = + _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_3, ON_RAMP_ADDRESS_3); + + vm.recordLogs(); + + s_offRamp.executeSingleReport( + _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_3, messagesChain3), new OffRamp.GasLimitOverride[](0) + ); + _assertExecutionStateChangedEventLogs( + SOURCE_CHAIN_SELECTOR_3, + messagesChain3[0].header.sequenceNumber, + messagesChain3[0].header.messageId, + _hashMessage(messagesChain3[0], ON_RAMP_ADDRESS_3), + Internal.MessageExecutionState.SUCCESS, + "" + ); + + assertEq( + startNonceChain3 + 1, s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_3, messagesChain3[0].sender) + ); + } + + function test_UpgradedSenderNoncesReadsPreviousRamp_Success() public { + address[] memory senders = new address[](1); + senders[0] = OWNER; + + uint64 startNonce = s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, abi.encode(senders[0])); + + for (uint64 i = 1; i < 4; ++i) { + s_prevOffRamp.execute(senders); + + assertEq(startNonce + i, s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, abi.encode(senders[0]))); + } + } + + function test_UpgradedNonceStartsAtV1Nonce_Success() public { + address[] memory senders = new address[](1); + senders[0] = OWNER; + + uint64 startNonce = s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, abi.encode(senders[0])); + s_prevOffRamp.execute(senders); + + assertEq(startNonce + 1, s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, abi.encode(senders[0]))); + + Internal.Any2EVMRampMessage[] memory messagesMultiRamp = + _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); + + messagesMultiRamp[0].header.nonce++; + messagesMultiRamp[0].header.messageId = _hashMessage(messagesMultiRamp[0], ON_RAMP_ADDRESS_1); + + vm.recordLogs(); + + s_offRamp.executeSingleReport( + _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messagesMultiRamp), new OffRamp.GasLimitOverride[](0) + ); + + _assertExecutionStateChangedEventLogs( + SOURCE_CHAIN_SELECTOR_1, + messagesMultiRamp[0].header.sequenceNumber, + messagesMultiRamp[0].header.messageId, + _hashMessage(messagesMultiRamp[0], ON_RAMP_ADDRESS_1), + Internal.MessageExecutionState.SUCCESS, + "" + ); + + assertEq( + startNonce + 2, s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, messagesMultiRamp[0].sender) + ); + + messagesMultiRamp[0].header.nonce++; + messagesMultiRamp[0].header.sequenceNumber++; + messagesMultiRamp[0].header.messageId = _hashMessage(messagesMultiRamp[0], ON_RAMP_ADDRESS_1); + + vm.recordLogs(); + s_offRamp.executeSingleReport( + _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messagesMultiRamp), new OffRamp.GasLimitOverride[](0) + ); + _assertExecutionStateChangedEventLogs( + SOURCE_CHAIN_SELECTOR_1, + messagesMultiRamp[0].header.sequenceNumber, + messagesMultiRamp[0].header.messageId, + _hashMessage(messagesMultiRamp[0], ON_RAMP_ADDRESS_1), + Internal.MessageExecutionState.SUCCESS, + "" + ); + + assertEq( + startNonce + 3, s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, messagesMultiRamp[0].sender) + ); + } + + function test_UpgradedNonceNewSenderStartsAtZero_Success() public { + address[] memory senders = new address[](1); + senders[0] = OWNER; + + s_prevOffRamp.execute(senders); + + Internal.Any2EVMRampMessage[] memory messagesMultiRamp = + _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); + + bytes memory newSender = abi.encode(address(1234567)); + messagesMultiRamp[0].sender = newSender; + messagesMultiRamp[0].header.messageId = _hashMessage(messagesMultiRamp[0], ON_RAMP_ADDRESS_1); + + // new sender nonce in new offramp should go from 0 -> 1 + assertEq(s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, newSender), 0); + vm.recordLogs(); + s_offRamp.executeSingleReport( + _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messagesMultiRamp), new OffRamp.GasLimitOverride[](0) + ); + _assertExecutionStateChangedEventLogs( + SOURCE_CHAIN_SELECTOR_1, + messagesMultiRamp[0].header.sequenceNumber, + messagesMultiRamp[0].header.messageId, + _hashMessage(messagesMultiRamp[0], ON_RAMP_ADDRESS_1), + Internal.MessageExecutionState.SUCCESS, + "" + ); + assertEq(s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, newSender), 1); + } + + function test_UpgradedOffRampNonceSkipsIfMsgInFlight_Success() public { + Internal.Any2EVMRampMessage[] memory messages = + _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); + + address newSender = address(1234567); + messages[0].sender = abi.encode(newSender); + messages[0].header.nonce = 2; + messages[0].header.messageId = _hashMessage(messages[0], ON_RAMP_ADDRESS_1); + + uint64 startNonce = s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, messages[0].sender); + + // new offramp sees msg nonce higher than senderNonce + // it waits for previous offramp to execute + vm.expectEmit(); + emit NonceManager.SkippedIncorrectNonce(SOURCE_CHAIN_SELECTOR_1, messages[0].header.nonce, messages[0].sender); + s_offRamp.executeSingleReport( + _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), new OffRamp.GasLimitOverride[](0) + ); + assertEq(startNonce, s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, messages[0].sender)); + + address[] memory senders = new address[](1); + senders[0] = newSender; + + // previous offramp executes msg and increases nonce + s_prevOffRamp.execute(senders); + assertEq(startNonce + 1, s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, abi.encode(senders[0]))); + + messages[0].header.nonce = 2; + messages[0].header.messageId = _hashMessage(messages[0], ON_RAMP_ADDRESS_1); + + // new offramp is able to execute + vm.recordLogs(); + s_offRamp.executeSingleReport( + _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), new OffRamp.GasLimitOverride[](0) + ); + + _assertExecutionStateChangedEventLogs( + SOURCE_CHAIN_SELECTOR_1, + messages[0].header.sequenceNumber, + messages[0].header.messageId, + _hashMessage(messages[0], ON_RAMP_ADDRESS_1), + Internal.MessageExecutionState.SUCCESS, + "" + ); + + assertEq(startNonce + 2, s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, messages[0].sender)); + } +} diff --git a/contracts/src/v0.8/ccip/test/NonceManager/NonceManager.applyPreviousRampsUpdates.t.sol b/contracts/src/v0.8/ccip/test/NonceManager/NonceManager.applyPreviousRampsUpdates.t.sol deleted file mode 100644 index 765ab3ad5b1..00000000000 --- a/contracts/src/v0.8/ccip/test/NonceManager/NonceManager.applyPreviousRampsUpdates.t.sol +++ /dev/null @@ -1,154 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; - -import {NonceManager} from "../../NonceManager.sol"; -import {OnRampSetup} from "../onRamp/OnRamp/OnRampSetup.t.sol"; - -contract NonceManager_applyPreviousRampsUpdates is OnRampSetup { - function test_SingleRampUpdate() public { - address prevOnRamp = makeAddr("prevOnRamp"); - address prevOffRamp = makeAddr("prevOffRamp"); - NonceManager.PreviousRampsArgs[] memory previousRamps = new NonceManager.PreviousRampsArgs[](1); - previousRamps[0] = NonceManager.PreviousRampsArgs({ - remoteChainSelector: DEST_CHAIN_SELECTOR, - prevRamps: NonceManager.PreviousRamps(prevOnRamp, prevOffRamp), - overrideExistingRamps: false - }); - - vm.expectEmit(); - emit NonceManager.PreviousRampsUpdated(DEST_CHAIN_SELECTOR, previousRamps[0].prevRamps); - - s_outboundNonceManager.applyPreviousRampsUpdates(previousRamps); - - _assertPreviousRampsEqual(s_outboundNonceManager.getPreviousRamps(DEST_CHAIN_SELECTOR), previousRamps[0].prevRamps); - } - - function test_MultipleRampsUpdates() public { - address prevOnRamp1 = makeAddr("prevOnRamp1"); - address prevOnRamp2 = makeAddr("prevOnRamp2"); - address prevOffRamp1 = makeAddr("prevOffRamp1"); - address prevOffRamp2 = makeAddr("prevOffRamp2"); - NonceManager.PreviousRampsArgs[] memory previousRamps = new NonceManager.PreviousRampsArgs[](2); - previousRamps[0] = NonceManager.PreviousRampsArgs({ - remoteChainSelector: DEST_CHAIN_SELECTOR, - prevRamps: NonceManager.PreviousRamps(prevOnRamp1, prevOffRamp1), - overrideExistingRamps: false - }); - previousRamps[1] = NonceManager.PreviousRampsArgs({ - remoteChainSelector: DEST_CHAIN_SELECTOR + 1, - prevRamps: NonceManager.PreviousRamps(prevOnRamp2, prevOffRamp2), - overrideExistingRamps: false - }); - - vm.expectEmit(); - emit NonceManager.PreviousRampsUpdated(DEST_CHAIN_SELECTOR, previousRamps[0].prevRamps); - vm.expectEmit(); - emit NonceManager.PreviousRampsUpdated(DEST_CHAIN_SELECTOR + 1, previousRamps[1].prevRamps); - - s_outboundNonceManager.applyPreviousRampsUpdates(previousRamps); - - _assertPreviousRampsEqual(s_outboundNonceManager.getPreviousRamps(DEST_CHAIN_SELECTOR), previousRamps[0].prevRamps); - _assertPreviousRampsEqual( - s_outboundNonceManager.getPreviousRamps(DEST_CHAIN_SELECTOR + 1), previousRamps[1].prevRamps - ); - } - - function test_PreviousRampAlreadySet_overrideAllowed() public { - NonceManager.PreviousRampsArgs[] memory previousRamps = new NonceManager.PreviousRampsArgs[](1); - address prevOffRamp = makeAddr("prevOffRamp"); - previousRamps[0] = NonceManager.PreviousRampsArgs({ - remoteChainSelector: DEST_CHAIN_SELECTOR, - prevRamps: NonceManager.PreviousRamps(address(0), prevOffRamp), - overrideExistingRamps: true - }); - - s_outboundNonceManager.applyPreviousRampsUpdates(previousRamps); - - previousRamps[0] = NonceManager.PreviousRampsArgs({ - remoteChainSelector: DEST_CHAIN_SELECTOR, - prevRamps: NonceManager.PreviousRamps(address(0), prevOffRamp), - overrideExistingRamps: true - }); - - s_outboundNonceManager.applyPreviousRampsUpdates(previousRamps); - } - - function test_ZeroInput() public { - vm.recordLogs(); - s_outboundNonceManager.applyPreviousRampsUpdates(new NonceManager.PreviousRampsArgs[](0)); - - assertEq(vm.getRecordedLogs().length, 0); - } - - function test_RevertWhen_applyPreviousRampsUpdatesWhen_PreviousRampAlreadySetOnRamp() public { - NonceManager.PreviousRampsArgs[] memory previousRamps = new NonceManager.PreviousRampsArgs[](1); - address prevOnRamp = makeAddr("prevOnRamp"); - previousRamps[0] = NonceManager.PreviousRampsArgs({ - remoteChainSelector: DEST_CHAIN_SELECTOR, - prevRamps: NonceManager.PreviousRamps(prevOnRamp, address(0)), - overrideExistingRamps: false - }); - - s_outboundNonceManager.applyPreviousRampsUpdates(previousRamps); - - previousRamps[0] = NonceManager.PreviousRampsArgs({ - remoteChainSelector: DEST_CHAIN_SELECTOR, - prevRamps: NonceManager.PreviousRamps(prevOnRamp, address(0)), - overrideExistingRamps: false - }); - - vm.expectRevert(NonceManager.PreviousRampAlreadySet.selector); - s_outboundNonceManager.applyPreviousRampsUpdates(previousRamps); - } - - function test_RevertWhen_applyPreviousRampsUpdatesWhen_PreviousRampAlreadySetOffRamp() public { - NonceManager.PreviousRampsArgs[] memory previousRamps = new NonceManager.PreviousRampsArgs[](1); - address prevOffRamp = makeAddr("prevOffRamp"); - previousRamps[0] = NonceManager.PreviousRampsArgs({ - remoteChainSelector: DEST_CHAIN_SELECTOR, - prevRamps: NonceManager.PreviousRamps(address(0), prevOffRamp), - overrideExistingRamps: false - }); - - s_outboundNonceManager.applyPreviousRampsUpdates(previousRamps); - - previousRamps[0] = NonceManager.PreviousRampsArgs({ - remoteChainSelector: DEST_CHAIN_SELECTOR, - prevRamps: NonceManager.PreviousRamps(address(0), prevOffRamp), - overrideExistingRamps: false - }); - - vm.expectRevert(NonceManager.PreviousRampAlreadySet.selector); - s_outboundNonceManager.applyPreviousRampsUpdates(previousRamps); - } - - function test_RevertWhen_applyPreviousRampsUpdatesWhen_PreviousRampAlreadySetOnRampAndOffRamp_Revert() public { - NonceManager.PreviousRampsArgs[] memory previousRamps = new NonceManager.PreviousRampsArgs[](1); - address prevOnRamp = makeAddr("prevOnRamp"); - address prevOffRamp = makeAddr("prevOffRamp"); - previousRamps[0] = NonceManager.PreviousRampsArgs({ - remoteChainSelector: DEST_CHAIN_SELECTOR, - prevRamps: NonceManager.PreviousRamps(prevOnRamp, prevOffRamp), - overrideExistingRamps: false - }); - - s_outboundNonceManager.applyPreviousRampsUpdates(previousRamps); - - previousRamps[0] = NonceManager.PreviousRampsArgs({ - remoteChainSelector: DEST_CHAIN_SELECTOR, - prevRamps: NonceManager.PreviousRamps(prevOnRamp, prevOffRamp), - overrideExistingRamps: false - }); - - vm.expectRevert(NonceManager.PreviousRampAlreadySet.selector); - s_outboundNonceManager.applyPreviousRampsUpdates(previousRamps); - } - - function _assertPreviousRampsEqual( - NonceManager.PreviousRamps memory a, - NonceManager.PreviousRamps memory b - ) internal pure { - assertEq(a.prevOnRamp, b.prevOnRamp); - assertEq(a.prevOffRamp, b.prevOffRamp); - } -} diff --git a/contracts/src/v0.8/ccip/test/NonceManager/NonceManager.getInboundNonce.t.sol b/contracts/src/v0.8/ccip/test/NonceManager/NonceManager.getInboundNonce.t.sol deleted file mode 100644 index d70382bab5a..00000000000 --- a/contracts/src/v0.8/ccip/test/NonceManager/NonceManager.getInboundNonce.t.sol +++ /dev/null @@ -1,253 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; - -import {NonceManager} from "../../NonceManager.sol"; -import {Internal} from "../../libraries/Internal.sol"; -import {OffRamp} from "../../offRamp/OffRamp.sol"; -import {EVM2EVMOffRampHelper} from "../helpers/EVM2EVMOffRampHelper.sol"; -import {OffRampSetup} from "../offRamp/OffRamp/OffRampSetup.t.sol"; - -contract NonceManager_getInboundNonce is OffRampSetup { - EVM2EVMOffRampHelper internal s_prevOffRamp; - - address internal constant SINGLE_LANE_ON_RAMP_ADDRESS_1 = abi.decode(ON_RAMP_ADDRESS_1, (address)); - address internal constant SINGLE_LANE_ON_RAMP_ADDRESS_2 = abi.decode(ON_RAMP_ADDRESS_2, (address)); - address internal constant SINGLE_LANE_ON_RAMP_ADDRESS_3 = abi.decode(ON_RAMP_ADDRESS_3, (address)); - - function setUp() public virtual override { - super.setUp(); - - s_prevOffRamp = new EVM2EVMOffRampHelper(); - - NonceManager.PreviousRampsArgs[] memory previousRamps = new NonceManager.PreviousRampsArgs[](1); - previousRamps[0] = NonceManager.PreviousRampsArgs({ - remoteChainSelector: SOURCE_CHAIN_SELECTOR_1, - prevRamps: NonceManager.PreviousRamps(address(0), address(s_prevOffRamp)), - overrideExistingRamps: false - }); - - s_inboundNonceManager.applyPreviousRampsUpdates(previousRamps); - - OffRamp.SourceChainConfigArgs[] memory sourceChainConfigs = new OffRamp.SourceChainConfigArgs[](3); - sourceChainConfigs[0] = OffRamp.SourceChainConfigArgs({ - router: s_destRouter, - sourceChainSelector: SOURCE_CHAIN_SELECTOR_1, - isEnabled: true, - onRamp: ON_RAMP_ADDRESS_1 - }); - sourceChainConfigs[1] = OffRamp.SourceChainConfigArgs({ - router: s_destRouter, - sourceChainSelector: SOURCE_CHAIN_SELECTOR_2, - isEnabled: true, - onRamp: ON_RAMP_ADDRESS_2 - }); - sourceChainConfigs[2] = OffRamp.SourceChainConfigArgs({ - router: s_destRouter, - sourceChainSelector: SOURCE_CHAIN_SELECTOR_3, - isEnabled: true, - onRamp: ON_RAMP_ADDRESS_3 - }); - - _setupMultipleOffRampsFromConfigs(sourceChainConfigs); - - s_offRamp.setVerifyOverrideResult(SOURCE_CHAIN_SELECTOR_1, 1); - s_offRamp.setVerifyOverrideResult(SOURCE_CHAIN_SELECTOR_3, 1); - } - - function test_getInboundNonce_Upgraded() public { - Internal.Any2EVMRampMessage[] memory messages = - _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); - - vm.recordLogs(); - s_offRamp.executeSingleReport( - _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), new OffRamp.GasLimitOverride[](0) - ); - _assertExecutionStateChangedEventLogs( - SOURCE_CHAIN_SELECTOR_1, - messages[0].header.sequenceNumber, - messages[0].header.messageId, - _hashMessage(messages[0], ON_RAMP_ADDRESS_1), - Internal.MessageExecutionState.SUCCESS, - "" - ); - } - - function test_getInboundNonce_NoPrevOffRampForChain() public { - address[] memory senders = new address[](1); - senders[0] = OWNER; - - uint64 startNonceChain3 = s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_3, abi.encode(senders[0])); - s_prevOffRamp.execute(senders); - - // Nonce unchanged for chain 3 - assertEq(startNonceChain3, s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_3, abi.encode(senders[0]))); - - Internal.Any2EVMRampMessage[] memory messagesChain3 = - _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_3, ON_RAMP_ADDRESS_3); - - vm.recordLogs(); - - s_offRamp.executeSingleReport( - _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_3, messagesChain3), new OffRamp.GasLimitOverride[](0) - ); - _assertExecutionStateChangedEventLogs( - SOURCE_CHAIN_SELECTOR_3, - messagesChain3[0].header.sequenceNumber, - messagesChain3[0].header.messageId, - _hashMessage(messagesChain3[0], ON_RAMP_ADDRESS_3), - Internal.MessageExecutionState.SUCCESS, - "" - ); - - assertEq( - startNonceChain3 + 1, s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_3, messagesChain3[0].sender) - ); - } - - function test_getInboundNonce_UpgradedSenderNoncesReadsPreviousRamp() public { - address[] memory senders = new address[](1); - senders[0] = OWNER; - - uint64 startNonce = s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, abi.encode(senders[0])); - - for (uint64 i = 1; i < 4; ++i) { - s_prevOffRamp.execute(senders); - - assertEq(startNonce + i, s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, abi.encode(senders[0]))); - } - } - - function test_getInboundNonce_UpgradedNonceStartsAtV1Nonce() public { - address[] memory senders = new address[](1); - senders[0] = OWNER; - - uint64 startNonce = s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, abi.encode(senders[0])); - s_prevOffRamp.execute(senders); - - assertEq(startNonce + 1, s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, abi.encode(senders[0]))); - - Internal.Any2EVMRampMessage[] memory messagesMultiRamp = - _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); - - messagesMultiRamp[0].header.nonce++; - messagesMultiRamp[0].header.messageId = _hashMessage(messagesMultiRamp[0], ON_RAMP_ADDRESS_1); - - vm.recordLogs(); - - s_offRamp.executeSingleReport( - _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messagesMultiRamp), new OffRamp.GasLimitOverride[](0) - ); - - _assertExecutionStateChangedEventLogs( - SOURCE_CHAIN_SELECTOR_1, - messagesMultiRamp[0].header.sequenceNumber, - messagesMultiRamp[0].header.messageId, - _hashMessage(messagesMultiRamp[0], ON_RAMP_ADDRESS_1), - Internal.MessageExecutionState.SUCCESS, - "" - ); - - assertEq( - startNonce + 2, s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, messagesMultiRamp[0].sender) - ); - - messagesMultiRamp[0].header.nonce++; - messagesMultiRamp[0].header.sequenceNumber++; - messagesMultiRamp[0].header.messageId = _hashMessage(messagesMultiRamp[0], ON_RAMP_ADDRESS_1); - - vm.recordLogs(); - s_offRamp.executeSingleReport( - _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messagesMultiRamp), new OffRamp.GasLimitOverride[](0) - ); - _assertExecutionStateChangedEventLogs( - SOURCE_CHAIN_SELECTOR_1, - messagesMultiRamp[0].header.sequenceNumber, - messagesMultiRamp[0].header.messageId, - _hashMessage(messagesMultiRamp[0], ON_RAMP_ADDRESS_1), - Internal.MessageExecutionState.SUCCESS, - "" - ); - - assertEq( - startNonce + 3, s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, messagesMultiRamp[0].sender) - ); - } - - function test_getInboundNonce_UpgradedNonceNewSenderStartsAtZero() public { - address[] memory senders = new address[](1); - senders[0] = OWNER; - - s_prevOffRamp.execute(senders); - - Internal.Any2EVMRampMessage[] memory messagesMultiRamp = - _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); - - bytes memory newSender = abi.encode(address(1234567)); - messagesMultiRamp[0].sender = newSender; - messagesMultiRamp[0].header.messageId = _hashMessage(messagesMultiRamp[0], ON_RAMP_ADDRESS_1); - - // new sender nonce in new offRamp should go from 0 -> 1 - assertEq(s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, newSender), 0); - vm.recordLogs(); - s_offRamp.executeSingleReport( - _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messagesMultiRamp), new OffRamp.GasLimitOverride[](0) - ); - _assertExecutionStateChangedEventLogs( - SOURCE_CHAIN_SELECTOR_1, - messagesMultiRamp[0].header.sequenceNumber, - messagesMultiRamp[0].header.messageId, - _hashMessage(messagesMultiRamp[0], ON_RAMP_ADDRESS_1), - Internal.MessageExecutionState.SUCCESS, - "" - ); - assertEq(s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, newSender), 1); - } - - function test_getInboundNonce_UpgradedOffRampNonceSkipsIfMsgInFlight() public { - Internal.Any2EVMRampMessage[] memory messages = - _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); - - address newSender = address(1234567); - messages[0].sender = abi.encode(newSender); - messages[0].header.nonce = 2; - messages[0].header.messageId = _hashMessage(messages[0], ON_RAMP_ADDRESS_1); - - uint64 startNonce = s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, messages[0].sender); - - // new offRamp sees msg nonce higher than senderNonce - // it waits for previous offRamp to execute - vm.expectEmit(); - emit NonceManager.SkippedIncorrectNonce(SOURCE_CHAIN_SELECTOR_1, messages[0].header.nonce, messages[0].sender); - s_offRamp.executeSingleReport( - _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), new OffRamp.GasLimitOverride[](0) - ); - assertEq(startNonce, s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, messages[0].sender)); - - address[] memory senders = new address[](1); - senders[0] = newSender; - - // previous offRamp executes msg and increases nonce - s_prevOffRamp.execute(senders); - assertEq(startNonce + 1, s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, abi.encode(senders[0]))); - - messages[0].header.nonce = 2; - messages[0].header.messageId = _hashMessage(messages[0], ON_RAMP_ADDRESS_1); - - // new offRamp is able to execute - vm.recordLogs(); - s_offRamp.executeSingleReport( - _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), new OffRamp.GasLimitOverride[](0) - ); - - _assertExecutionStateChangedEventLogs( - SOURCE_CHAIN_SELECTOR_1, - messages[0].header.sequenceNumber, - messages[0].header.messageId, - _hashMessage(messages[0], ON_RAMP_ADDRESS_1), - Internal.MessageExecutionState.SUCCESS, - "" - ); - - assertEq(startNonce + 2, s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, messages[0].sender)); - } -} diff --git a/contracts/src/v0.8/ccip/test/NonceManager/NonceManager.getIncrementedOutboundNonce.t.sol b/contracts/src/v0.8/ccip/test/NonceManager/NonceManager.getIncrementedOutboundNonce.t.sol deleted file mode 100644 index 253a756e444..00000000000 --- a/contracts/src/v0.8/ccip/test/NonceManager/NonceManager.getIncrementedOutboundNonce.t.sol +++ /dev/null @@ -1,61 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; - -import {NonceManager} from "../../NonceManager.sol"; -import {BaseTest} from "../BaseTest.t.sol"; - -contract NonceManager_getIncrementedOutboundNonce is BaseTest { - NonceManager private s_nonceManager; - - function setUp() public override { - address[] memory authorizedCallers = new address[](1); - authorizedCallers[0] = address(this); - s_nonceManager = new NonceManager(authorizedCallers); - } - - function test_getIncrementedOutboundNonce() public { - address sender = address(this); - - assertEq(s_nonceManager.getOutboundNonce(DEST_CHAIN_SELECTOR, sender), 0); - - uint64 outboundNonce = s_nonceManager.getIncrementedOutboundNonce(DEST_CHAIN_SELECTOR, sender); - assertEq(outboundNonce, 1); - } - - function test_incrementInboundNonce() public { - address sender = address(this); - - s_nonceManager.incrementInboundNonce(SOURCE_CHAIN_SELECTOR, 1, abi.encode(sender)); - - assertEq(s_nonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR, abi.encode(sender)), 1); - } - - function test_incrementInboundNonce_SkippedIncorrectNonce() public { - address sender = address(this); - uint64 expectedNonce = 2; - - vm.expectEmit(); - emit NonceManager.SkippedIncorrectNonce(SOURCE_CHAIN_SELECTOR, expectedNonce, abi.encode(sender)); - - s_nonceManager.incrementInboundNonce(SOURCE_CHAIN_SELECTOR, expectedNonce, abi.encode(sender)); - - assertEq(s_nonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR, abi.encode(sender)), 0); - } - - function test_incrementNoncesInboundAndOutbound() public { - address sender = address(this); - - assertEq(s_nonceManager.getOutboundNonce(DEST_CHAIN_SELECTOR, sender), 0); - uint64 outboundNonce = s_nonceManager.getIncrementedOutboundNonce(DEST_CHAIN_SELECTOR, sender); - assertEq(outboundNonce, 1); - - // Inbound nonce unchanged - assertEq(s_nonceManager.getInboundNonce(DEST_CHAIN_SELECTOR, abi.encode(sender)), 0); - - s_nonceManager.incrementInboundNonce(DEST_CHAIN_SELECTOR, 1, abi.encode(sender)); - assertEq(s_nonceManager.getInboundNonce(DEST_CHAIN_SELECTOR, abi.encode(sender)), 1); - - // Outbound nonce unchanged - assertEq(s_nonceManager.getOutboundNonce(DEST_CHAIN_SELECTOR, sender), 1); - } -} diff --git a/contracts/src/v0.8/ccip/test/NonceManager/NonceManager.getOutboundNonce.t.sol b/contracts/src/v0.8/ccip/test/NonceManager/NonceManager.getOutboundNonce.t.sol deleted file mode 100644 index e1e2fe3d41e..00000000000 --- a/contracts/src/v0.8/ccip/test/NonceManager/NonceManager.getOutboundNonce.t.sol +++ /dev/null @@ -1,102 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; - -import {IEVM2AnyOnRamp} from "../../interfaces/IEVM2AnyOnRamp.sol"; - -import {NonceManager} from "../../NonceManager.sol"; -import {Client} from "../../libraries/Client.sol"; -import {OnRamp} from "../../onRamp/OnRamp.sol"; -import {OnRampHelper} from "../helpers/OnRampHelper.sol"; -import {OnRampSetup} from "../onRamp/OnRamp/OnRampSetup.t.sol"; - -contract NonceManager_getOutboundNonce is OnRampSetup { - uint256 internal constant FEE_AMOUNT = 1234567890; - OnRampHelper internal s_prevOnRamp; - - function setUp() public virtual override { - super.setUp(); - - (s_prevOnRamp,) = _deployOnRamp( - SOURCE_CHAIN_SELECTOR, s_sourceRouter, address(s_outboundNonceManager), address(s_tokenAdminRegistry) - ); - - // Since the previous onRamp is not a 1.5 ramp it doesn't have the getSenderNonce function. We mock it to return 0 - vm.mockCall(address(s_prevOnRamp), abi.encodeWithSelector(IEVM2AnyOnRamp.getSenderNonce.selector), abi.encode(0)); - - NonceManager.PreviousRampsArgs[] memory previousRamps = new NonceManager.PreviousRampsArgs[](1); - previousRamps[0] = NonceManager.PreviousRampsArgs({ - remoteChainSelector: DEST_CHAIN_SELECTOR, - prevRamps: NonceManager.PreviousRamps(address(s_prevOnRamp), address(0)), - overrideExistingRamps: false - }); - s_outboundNonceManager.applyPreviousRampsUpdates(previousRamps); - - (s_onRamp, s_metadataHash) = _deployOnRamp( - SOURCE_CHAIN_SELECTOR, s_sourceRouter, address(s_outboundNonceManager), address(s_tokenAdminRegistry) - ); - - vm.startPrank(address(s_sourceRouter)); - } - - function test_getOutboundNonce_Upgrade() public { - Client.EVM2AnyMessage memory message = _generateEmptyMessage(); - - vm.expectEmit(); - emit OnRamp.CCIPMessageSent(DEST_CHAIN_SELECTOR, 1, _messageToEvent(message, 1, 1, FEE_AMOUNT, OWNER)); - - s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, FEE_AMOUNT, OWNER); - } - - function test_getOutboundNonce_UpgradeSenderNoncesReadsPreviousRamp() public { - Client.EVM2AnyMessage memory message = _generateEmptyMessage(); - uint64 startNonce = s_outboundNonceManager.getOutboundNonce(DEST_CHAIN_SELECTOR, OWNER); - uint64 prevRampNextOutboundNonce = IEVM2AnyOnRamp(address(s_prevOnRamp)).getSenderNonce(OWNER); - - assertEq(startNonce, prevRampNextOutboundNonce); - - for (uint64 i = 1; i < 4; ++i) { - s_prevOnRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, 0, OWNER); - - assertEq(startNonce + i, s_outboundNonceManager.getOutboundNonce(DEST_CHAIN_SELECTOR, OWNER)); - } - } - - function test_getOutboundNonce_UpgradeNonceStartsAtV1Nonce() public { - Client.EVM2AnyMessage memory message = _generateEmptyMessage(); - - uint64 startNonce = s_outboundNonceManager.getOutboundNonce(DEST_CHAIN_SELECTOR, OWNER); - - // send 1 message from previous onRamp - s_prevOnRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, FEE_AMOUNT, OWNER); - - assertEq(startNonce + 1, s_outboundNonceManager.getOutboundNonce(DEST_CHAIN_SELECTOR, OWNER)); - - // new onRamp nonce should start from 2, while sequence number start from 1 - vm.expectEmit(); - emit OnRamp.CCIPMessageSent(DEST_CHAIN_SELECTOR, 1, _messageToEvent(message, 1, startNonce + 2, FEE_AMOUNT, OWNER)); - s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, FEE_AMOUNT, OWNER); - - assertEq(startNonce + 2, s_outboundNonceManager.getOutboundNonce(DEST_CHAIN_SELECTOR, OWNER)); - - // after another send, nonce should be 3, and sequence number be 2 - vm.expectEmit(); - emit OnRamp.CCIPMessageSent(DEST_CHAIN_SELECTOR, 2, _messageToEvent(message, 2, startNonce + 3, FEE_AMOUNT, OWNER)); - s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, FEE_AMOUNT, OWNER); - - assertEq(startNonce + 3, s_outboundNonceManager.getOutboundNonce(DEST_CHAIN_SELECTOR, OWNER)); - } - - function test_getOutboundNonce_UpgradeNonceNewSenderStartsAtZero() public { - Client.EVM2AnyMessage memory message = _generateEmptyMessage(); - - // send 1 message from previous onRamp from OWNER - s_prevOnRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, FEE_AMOUNT, OWNER); - - address newSender = address(1234567); - // new onRamp nonce should start from 1 for new sender - vm.expectEmit(); - emit OnRamp.CCIPMessageSent(DEST_CHAIN_SELECTOR, 1, _messageToEvent(message, 1, 1, FEE_AMOUNT, newSender)); - - s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, FEE_AMOUNT, newSender); - } -} diff --git a/contracts/src/v0.8/ccip/test/TokenSetup.t.sol b/contracts/src/v0.8/ccip/test/TokenSetup.t.sol index f32b0cea940..2077bc94deb 100644 --- a/contracts/src/v0.8/ccip/test/TokenSetup.t.sol +++ b/contracts/src/v0.8/ccip/test/TokenSetup.t.sol @@ -1,17 +1,17 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; -import {BurnMintERC20} from "../../shared/token/ERC20/BurnMintERC20.sol"; +import {BurnMintERC677} from "../../shared/token/ERC677/BurnMintERC677.sol"; import {BurnMintTokenPool} from "../pools/BurnMintTokenPool.sol"; import {LockReleaseTokenPool} from "../pools/LockReleaseTokenPool.sol"; import {TokenPool} from "../pools/TokenPool.sol"; import {TokenAdminRegistry} from "../tokenAdminRegistry/TokenAdminRegistry.sol"; -import {BaseTest} from "./BaseTest.t.sol"; import {MaybeRevertingBurnMintTokenPool} from "./helpers/MaybeRevertingBurnMintTokenPool.sol"; +import {RouterSetup} from "./router/Router/RouterSetup.t.sol"; import {IERC20} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; -contract TokenSetup is BaseTest { +contract TokenSetup is RouterSetup { address[] internal s_sourceTokens; address[] internal s_destTokens; @@ -26,14 +26,14 @@ contract TokenSetup is BaseTest { mapping(address sourceToken => address destToken) internal s_destTokenBySourceToken; function _deploySourceToken(string memory tokenName, uint256 dealAmount, uint8 decimals) internal returns (address) { - BurnMintERC20 token = new BurnMintERC20(tokenName, tokenName, decimals, 0, 0); + BurnMintERC677 token = new BurnMintERC677(tokenName, tokenName, decimals, 0); s_sourceTokens.push(address(token)); deal(address(token), OWNER, dealAmount); return address(token); } function _deployDestToken(string memory tokenName, uint256 dealAmount) internal returns (address) { - BurnMintERC20 token = new BurnMintERC20(tokenName, tokenName, 18, 0, 0); + BurnMintERC677 token = new BurnMintERC677(tokenName, tokenName, 18, 0); s_destTokens.push(address(token)); deal(address(token), OWNER, dealAmount); return address(token); @@ -45,9 +45,8 @@ contract TokenSetup is BaseTest { router = address(s_destRouter); } - LockReleaseTokenPool pool = new LockReleaseTokenPool( - IERC20(token), DEFAULT_TOKEN_DECIMALS, new address[](0), address(s_mockRMNRemote), true, router - ); + LockReleaseTokenPool pool = + new LockReleaseTokenPool(IERC20(token), new address[](0), address(s_mockRMN), true, router); if (isSourcePool) { s_sourcePoolByToken[address(token)] = address(pool); @@ -63,10 +62,9 @@ contract TokenSetup is BaseTest { router = address(s_destRouter); } - BurnMintTokenPool pool = new MaybeRevertingBurnMintTokenPool( - BurnMintERC20(token), DEFAULT_TOKEN_DECIMALS, new address[](0), address(s_mockRMNRemote), router - ); - BurnMintERC20(token).grantMintAndBurnRoles(address(pool)); + BurnMintTokenPool pool = + new MaybeRevertingBurnMintTokenPool(BurnMintERC677(token), new address[](0), address(s_mockRMN), router); + BurnMintERC677(token).grantMintAndBurnRoles(address(pool)); if (isSourcePool) { s_sourcePoolByToken[address(token)] = address(pool); @@ -77,7 +75,7 @@ contract TokenSetup is BaseTest { } function setUp() public virtual override { - super.setUp(); + RouterSetup.setUp(); bool isSetup = s_sourceTokens.length != 0; if (isSetup) { @@ -152,18 +150,16 @@ contract TokenSetup is BaseTest { tokenAdminRegistry.setPool(token, pool); - bytes[] memory remotePoolAddresses = new bytes[](1); - remotePoolAddresses[0] = abi.encode(remotePoolAddress); - TokenPool.ChainUpdate[] memory chainUpdates = new TokenPool.ChainUpdate[](1); chainUpdates[0] = TokenPool.ChainUpdate({ remoteChainSelector: remoteChainSelector, - remotePoolAddresses: remotePoolAddresses, + remotePoolAddress: abi.encode(remotePoolAddress), remoteTokenAddress: abi.encode(remoteToken), + allowed: true, outboundRateLimiterConfig: _getOutboundRateLimiterConfig(), inboundRateLimiterConfig: _getInboundRateLimiterConfig() }); - TokenPool(pool).applyChainUpdates(new uint64[](0), chainUpdates); + TokenPool(pool).applyChainUpdates(chainUpdates); } } diff --git a/contracts/src/v0.8/ccip/test/WETH9.sol b/contracts/src/v0.8/ccip/test/WETH9.sol index 0ac79d413dd..bfd2b5f022f 100644 --- a/contracts/src/v0.8/ccip/test/WETH9.sol +++ b/contracts/src/v0.8/ccip/test/WETH9.sol @@ -14,7 +14,7 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -pragma solidity ^0.8.24; +pragma solidity 0.8.24; // solhint-disable contract WETH9 { diff --git a/contracts/src/v0.8/ccip/test/applications/DefensiveExample/DefensiveExample.t.sol b/contracts/src/v0.8/ccip/test/applications/DefensiveExample/DefensiveExample.t.sol index 1817476c134..ddaadbac801 100644 --- a/contracts/src/v0.8/ccip/test/applications/DefensiveExample/DefensiveExample.t.sol +++ b/contracts/src/v0.8/ccip/test/applications/DefensiveExample/DefensiveExample.t.sol @@ -68,7 +68,7 @@ contract DefensiveExampleTest is OnRampSetup { assertEq(IERC20(token).balanceOf(address(s_receiver)), receiverBalancePre - amount); } - function test_HappyPath() public { + function test_HappyPath_Success() public { bytes32 messageId = keccak256("messageId"); address token = address(s_destFeeToken); uint256 amount = 111333333777; diff --git a/contracts/src/v0.8/ccip/test/applications/EtherSenderReceiver/EtherSenderReceiverTest.ccipSend.t.sol b/contracts/src/v0.8/ccip/test/applications/EtherSenderReceiver/EtherSenderReceiverTest.ccipSend.t.sol index 5f91841ab6e..dea42f36098 100644 --- a/contracts/src/v0.8/ccip/test/applications/EtherSenderReceiver/EtherSenderReceiverTest.ccipSend.t.sol +++ b/contracts/src/v0.8/ccip/test/applications/EtherSenderReceiver/EtherSenderReceiverTest.ccipSend.t.sol @@ -99,7 +99,7 @@ contract EtherSenderReceiverTest_ccipSend is EtherSenderReceiverTestSetup { } } - function test_RevertWhen_ccipSends_insufficientFee_weth() public { + function test_ccipSend_reverts_insufficientFee_weth() public { Client.EVMTokenAmount[] memory tokenAmounts = new Client.EVMTokenAmount[](1); tokenAmounts[0] = Client.EVMTokenAmount({ token: address(0), // callers may not specify this. @@ -127,7 +127,7 @@ contract EtherSenderReceiverTest_ccipSend is EtherSenderReceiverTestSetup { s_etherSenderReceiver.ccipSend{value: AMOUNT}(DESTINATION_CHAIN_SELECTOR, message); } - function test_RevertWhen_ccipSends_insufficientFee_feeToken() public { + function test_ccipSend_reverts_insufficientFee_feeToken() public { Client.EVMTokenAmount[] memory tokenAmounts = new Client.EVMTokenAmount[](1); tokenAmounts[0] = Client.EVMTokenAmount({ token: address(0), // callers may not specify this. @@ -155,7 +155,7 @@ contract EtherSenderReceiverTest_ccipSend is EtherSenderReceiverTestSetup { s_etherSenderReceiver.ccipSend{value: AMOUNT}(DESTINATION_CHAIN_SELECTOR, message); } - function test_RevertWhen_ccipSends_insufficientFee_native() public { + function test_ccipSend_reverts_insufficientFee_native() public { Client.EVMTokenAmount[] memory tokenAmounts = new Client.EVMTokenAmount[](1); tokenAmounts[0] = Client.EVMTokenAmount({ token: address(0), // callers may not specify this. @@ -181,7 +181,7 @@ contract EtherSenderReceiverTest_ccipSend is EtherSenderReceiverTestSetup { s_etherSenderReceiver.ccipSend{value: AMOUNT + FEE_WEI - 1}(DESTINATION_CHAIN_SELECTOR, message); } - function test_ccipSend_nativeExcess() public { + function test_ccipSend_success_nativeExcess() public { Client.EVMTokenAmount[] memory tokenAmounts = new Client.EVMTokenAmount[](1); tokenAmounts[0] = Client.EVMTokenAmount({ token: address(0), // callers may not specify this. @@ -218,7 +218,7 @@ contract EtherSenderReceiverTest_ccipSend is EtherSenderReceiverTestSetup { assertEq(actualMsgId, expectedMsgId, "message id must be correct"); } - function test_ccipSend_native() public { + function test_ccipSend_success_native() public { Client.EVMTokenAmount[] memory tokenAmounts = new Client.EVMTokenAmount[](1); tokenAmounts[0] = Client.EVMTokenAmount({ token: address(0), // callers may not specify this. @@ -251,7 +251,7 @@ contract EtherSenderReceiverTest_ccipSend is EtherSenderReceiverTestSetup { assertEq(actualMsgId, expectedMsgId, "message id must be correct"); } - function test_ccipSend_feeToken() public { + function test_ccipSend_success_feeToken() public { Client.EVMTokenAmount[] memory tokenAmounts = new Client.EVMTokenAmount[](1); tokenAmounts[0] = Client.EVMTokenAmount({ token: address(0), // callers may not specify this. @@ -287,7 +287,7 @@ contract EtherSenderReceiverTest_ccipSend is EtherSenderReceiverTestSetup { assertEq(routerAllowance, FEE_JUELS, "router allowance must be feeJuels"); } - function test_ccipSend_weth() public { + function test_ccipSend_success_weth() public { Client.EVMTokenAmount[] memory tokenAmounts = new Client.EVMTokenAmount[](1); tokenAmounts[0] = Client.EVMTokenAmount({ token: address(0), // callers may not specify this. diff --git a/contracts/src/v0.8/ccip/test/applications/EtherSenderReceiver/EtherSenderReceiverTest.validateFeeToken.t.sol b/contracts/src/v0.8/ccip/test/applications/EtherSenderReceiver/EtherSenderReceiverTest.validateFeeToken.t.sol index 29da1a1e068..ae24ca3deae 100644 --- a/contracts/src/v0.8/ccip/test/applications/EtherSenderReceiver/EtherSenderReceiverTest.validateFeeToken.t.sol +++ b/contracts/src/v0.8/ccip/test/applications/EtherSenderReceiver/EtherSenderReceiverTest.validateFeeToken.t.sol @@ -36,7 +36,7 @@ contract EtherSenderReceiverTest_validateFeeToken is EtherSenderReceiverTestSetu s_etherSenderReceiver.validateFeeToken{value: AMOUNT}(message); } - function test_RevertWhen_validateFeeTokens_feeToken_tokenAmountNotEqualToMsgValue() public { + function test_validateFeeToken_reverts_feeToken_tokenAmountNotEqualToMsgValue() public { Client.EVMTokenAmount[] memory tokenAmount = new Client.EVMTokenAmount[](1); tokenAmount[0] = Client.EVMTokenAmount({token: address(s_weth), amount: AMOUNT}); Client.EVM2AnyMessage memory message = Client.EVM2AnyMessage({ diff --git a/contracts/src/v0.8/ccip/test/applications/ImmutableExample/ImmutableExample.t.sol b/contracts/src/v0.8/ccip/test/applications/ImmutableExample/ImmutableExample.t.sol index 8cb2cdd97d9..2eb9b736ad4 100644 --- a/contracts/src/v0.8/ccip/test/applications/ImmutableExample/ImmutableExample.t.sol +++ b/contracts/src/v0.8/ccip/test/applications/ImmutableExample/ImmutableExample.t.sol @@ -11,7 +11,7 @@ import {ERC165Checker} from "../../../../vendor/openzeppelin-solidity/v5.0.2/contracts/utils/introspection/ERC165Checker.sol"; contract CCIPClientExample_sanity is OnRampSetup { - function test_ImmutableExamples() public { + function test_ImmutableExamples_Success() public { CCIPClientExample exampleContract = new CCIPClientExample(s_sourceRouter, IERC20(s_sourceFeeToken)); deal(address(exampleContract), 100 ether); deal(s_sourceFeeToken, address(exampleContract), 100 ether); diff --git a/contracts/src/v0.8/ccip/test/applications/PingPong/PingPong.ccipReceive.t.sol b/contracts/src/v0.8/ccip/test/applications/PingPong/PingPong.ccipReceive.t.sol index 75d642defac..a7559b6dea2 100644 --- a/contracts/src/v0.8/ccip/test/applications/PingPong/PingPong.ccipReceive.t.sol +++ b/contracts/src/v0.8/ccip/test/applications/PingPong/PingPong.ccipReceive.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import {PingPongDemo} from "../../../applications/PingPongDemo.sol"; import {Client} from "../../../libraries/Client.sol"; @@ -7,7 +7,7 @@ import {Client} from "../../../libraries/Client.sol"; import {PingPongDappSetup} from "./PingPongDappSetup.t.sol"; contract PingPong_ccipReceive is PingPongDappSetup { - function test_CcipReceive() public { + function test_CcipReceive_Success() public { Client.EVMTokenAmount[] memory tokenAmounts = new Client.EVMTokenAmount[](0); uint256 pingPongNumber = 5; diff --git a/contracts/src/v0.8/ccip/test/applications/PingPong/PingPong.setCounterpart.t.sol b/contracts/src/v0.8/ccip/test/applications/PingPong/PingPong.setCounterpart.t.sol index e9c4135dead..8db2e75c5d7 100644 --- a/contracts/src/v0.8/ccip/test/applications/PingPong/PingPong.setCounterpart.t.sol +++ b/contracts/src/v0.8/ccip/test/applications/PingPong/PingPong.setCounterpart.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import {PingPongDappSetup} from "./PingPongDappSetup.t.sol"; diff --git a/contracts/src/v0.8/ccip/test/applications/PingPong/PingPong.setCounterpartAddress.t.sol b/contracts/src/v0.8/ccip/test/applications/PingPong/PingPong.setCounterpartAddress.t.sol index 43f123bbf6c..0e5587dac5f 100644 --- a/contracts/src/v0.8/ccip/test/applications/PingPong/PingPong.setCounterpartAddress.t.sol +++ b/contracts/src/v0.8/ccip/test/applications/PingPong/PingPong.setCounterpartAddress.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import {PingPongDappSetup} from "./PingPongDappSetup.t.sol"; diff --git a/contracts/src/v0.8/ccip/test/applications/PingPong/PingPong.setCounterpartChainSelector.t.sol b/contracts/src/v0.8/ccip/test/applications/PingPong/PingPong.setCounterpartChainSelector.t.sol index 3702c002e73..a7d148089bc 100644 --- a/contracts/src/v0.8/ccip/test/applications/PingPong/PingPong.setCounterpartChainSelector.t.sol +++ b/contracts/src/v0.8/ccip/test/applications/PingPong/PingPong.setCounterpartChainSelector.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import {PingPongDappSetup} from "./PingPongDappSetup.t.sol"; diff --git a/contracts/src/v0.8/ccip/test/applications/PingPong/PingPong.setOutOfOrderExecution.t.sol b/contracts/src/v0.8/ccip/test/applications/PingPong/PingPong.setOutOfOrderExecution.t.sol index 2929153db8e..0e09e67f7cb 100644 --- a/contracts/src/v0.8/ccip/test/applications/PingPong/PingPong.setOutOfOrderExecution.t.sol +++ b/contracts/src/v0.8/ccip/test/applications/PingPong/PingPong.setOutOfOrderExecution.t.sol @@ -1,11 +1,11 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import {PingPongDemo} from "../../../applications/PingPongDemo.sol"; import {PingPongDappSetup} from "./PingPongDappSetup.t.sol"; contract PingPong_setOutOfOrderExecution is PingPongDappSetup { - function test_OutOfOrderExecution() public { + function test_OutOfOrderExecution_Success() public { assertFalse(s_pingPong.getOutOfOrderExecution()); vm.expectEmit(); diff --git a/contracts/src/v0.8/ccip/test/applications/PingPong/PingPong.setPaused.t.sol b/contracts/src/v0.8/ccip/test/applications/PingPong/PingPong.setPaused.t.sol index 645cbe6b81d..82cd22199ec 100644 --- a/contracts/src/v0.8/ccip/test/applications/PingPong/PingPong.setPaused.t.sol +++ b/contracts/src/v0.8/ccip/test/applications/PingPong/PingPong.setPaused.t.sol @@ -1,10 +1,10 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import {PingPongDappSetup} from "./PingPongDappSetup.t.sol"; contract PingPong_setPaused is PingPongDappSetup { - function test_Pausing() public { + function test_Pausing_Success() public { assertFalse(s_pingPong.isPaused()); s_pingPong.setPaused(true); diff --git a/contracts/src/v0.8/ccip/test/applications/PingPong/PingPong.startPingPong.t.sol b/contracts/src/v0.8/ccip/test/applications/PingPong/PingPong.startPingPong.t.sol index 6dccdca6b38..d9dfc980154 100644 --- a/contracts/src/v0.8/ccip/test/applications/PingPong/PingPong.startPingPong.t.sol +++ b/contracts/src/v0.8/ccip/test/applications/PingPong/PingPong.startPingPong.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import {PingPongDemo} from "../../../applications/PingPongDemo.sol"; import {Internal} from "../../../libraries/Internal.sol"; @@ -10,11 +10,11 @@ import {PingPongDappSetup} from "./PingPongDappSetup.t.sol"; contract PingPong_startPingPong is PingPongDappSetup { uint256 internal s_pingPongNumber = 1; - function test_StartPingPong_With_Sequenced_Ordered() public { + function test_StartPingPong_With_Sequenced_Ordered_Success() public { _assertPingPongSuccess(); } - function test_StartPingPong_With_OOO() public { + function test_StartPingPong_With_OOO_Success() public { s_pingPong.setOutOfOrderExecution(true); _assertPingPongSuccess(); diff --git a/contracts/src/v0.8/ccip/test/applications/PingPong/PingPongDappSetup.t.sol b/contracts/src/v0.8/ccip/test/applications/PingPong/PingPongDappSetup.t.sol index 64f52f16b1c..8c009a0660d 100644 --- a/contracts/src/v0.8/ccip/test/applications/PingPong/PingPongDappSetup.t.sol +++ b/contracts/src/v0.8/ccip/test/applications/PingPong/PingPongDappSetup.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import {PingPongDemo} from "../../../applications/PingPongDemo.sol"; import {OnRampSetup} from "../../onRamp/OnRamp/OnRampSetup.t.sol"; diff --git a/contracts/src/v0.8/ccip/test/attacks/OnRamp/FacadeClient.sol b/contracts/src/v0.8/ccip/test/attacks/OnRamp/FacadeClient.sol index e8623c74e8a..8947a27df1d 100644 --- a/contracts/src/v0.8/ccip/test/attacks/OnRamp/FacadeClient.sol +++ b/contracts/src/v0.8/ccip/test/attacks/OnRamp/FacadeClient.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import {IRouterClient} from "../../../interfaces/IRouterClient.sol"; diff --git a/contracts/src/v0.8/ccip/test/attacks/OnRamp/OnRampTokenPoolReentrancy.t.sol b/contracts/src/v0.8/ccip/test/attacks/OnRamp/OnRampTokenPoolReentrancy.t.sol index 271e10e7561..cd3baf1747a 100644 --- a/contracts/src/v0.8/ccip/test/attacks/OnRamp/OnRampTokenPoolReentrancy.t.sol +++ b/contracts/src/v0.8/ccip/test/attacks/OnRamp/OnRampTokenPoolReentrancy.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import {Client} from "../../../libraries/Client.sol"; import {OnRamp} from "../../../onRamp/OnRamp.sol"; @@ -29,21 +29,19 @@ contract OnRampTokenPoolReentrancy is OnRampSetup { new FacadeClient(address(s_sourceRouter), DEST_CHAIN_SELECTOR, s_sourceToken, s_feeToken, i_receiver); s_maliciousTokenPool = new ReentrantMaliciousTokenPool( - address(s_facadeClient), s_sourceToken, address(s_mockRMNRemote), address(s_sourceRouter) + address(s_facadeClient), s_sourceToken, address(s_mockRMN), address(s_sourceRouter) ); - bytes[] memory remotePoolAddresses = new bytes[](1); - remotePoolAddresses[0] = abi.encode(s_destPoolBySourceToken[s_sourceTokens[0]]); - TokenPool.ChainUpdate[] memory chainUpdates = new TokenPool.ChainUpdate[](1); chainUpdates[0] = TokenPool.ChainUpdate({ remoteChainSelector: DEST_CHAIN_SELECTOR, - remotePoolAddresses: remotePoolAddresses, + remotePoolAddress: abi.encode(s_destPoolBySourceToken[s_sourceTokens[0]]), remoteTokenAddress: abi.encode(s_destTokens[0]), + allowed: true, outboundRateLimiterConfig: _getOutboundRateLimiterConfig(), inboundRateLimiterConfig: _getInboundRateLimiterConfig() }); - s_maliciousTokenPool.applyChainUpdates(new uint64[](0), chainUpdates); + s_maliciousTokenPool.applyChainUpdates(chainUpdates); s_sourcePoolByToken[address(s_sourceToken)] = address(s_maliciousTokenPool); s_tokenAdminRegistry.setPool(address(s_sourceToken), address(s_maliciousTokenPool)); @@ -59,7 +57,7 @@ contract OnRampTokenPoolReentrancy is OnRampSetup { /// (reenter)-> Facade -> 2nd call to ccipSend /// In this case, Facade's second call would produce an EVM2Any msg with a lower sequence number. /// The issue was fixed by implementing a reentrancy guard in OnRamp. - function test_OnRampTokenPoolReentrancy() public { + function test_OnRampTokenPoolReentrancy_Success() public { uint256 amount = 1; Client.EVMTokenAmount[] memory tokenAmounts = new Client.EVMTokenAmount[](1); diff --git a/contracts/src/v0.8/ccip/test/attacks/OnRamp/ReentrantMaliciousTokenPool.sol b/contracts/src/v0.8/ccip/test/attacks/OnRamp/ReentrantMaliciousTokenPool.sol index 3a7af8af506..f50f233e737 100644 --- a/contracts/src/v0.8/ccip/test/attacks/OnRamp/ReentrantMaliciousTokenPool.sol +++ b/contracts/src/v0.8/ccip/test/attacks/OnRamp/ReentrantMaliciousTokenPool.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import {Pool} from "../../../libraries/Pool.sol"; import {TokenPool} from "../../../pools/TokenPool.sol"; @@ -17,7 +17,7 @@ contract ReentrantMaliciousTokenPool is TokenPool { IERC20 token, address rmnProxy, address router - ) TokenPool(token, 18, new address[](0), rmnProxy, router) { + ) TokenPool(token, new address[](0), rmnProxy, router) { i_facade = facade; } diff --git a/contracts/src/v0.8/ccip/test/capability/CCIPHome/CCIPHome.applyChainConfigUpdates.t.sol b/contracts/src/v0.8/ccip/test/capability/CCIPHome/CCIPHome.applyChainConfigUpdates.t.sol index 2547ac3010d..1d2c3a70895 100644 --- a/contracts/src/v0.8/ccip/test/capability/CCIPHome/CCIPHome.applyChainConfigUpdates.t.sol +++ b/contracts/src/v0.8/ccip/test/capability/CCIPHome/CCIPHome.applyChainConfigUpdates.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import {INodeInfoProvider} from "../../../../keystone/interfaces/INodeInfoProvider.sol"; @@ -13,7 +13,7 @@ contract CCIPHome_applyChainConfigUpdates is CCIPHomeTestSetup { s_ccipHome = new CCIPHomeHelper(CAPABILITIES_REGISTRY); } - function test_applyChainConfigUpdates_addChainConfigs() public { + function test_applyChainConfigUpdates_addChainConfigs_Success() public { bytes32[] memory chainReaders = new bytes32[](1); chainReaders[0] = keccak256(abi.encode(1)); CCIPHome.ChainConfigArgs[] memory adds = new CCIPHome.ChainConfigArgs[](2); @@ -54,7 +54,7 @@ contract CCIPHome_applyChainConfigUpdates is CCIPHomeTestSetup { assertEq(s_ccipHome.getNumChainConfigurations(), 2, "total chain configs must be 2"); } - function test_getPaginatedCCIPHomes() public { + function test_getPaginatedCCIPHomes_Success() public { bytes32[] memory chainReaders = new bytes32[](1); chainReaders[0] = keccak256(abi.encode(1)); CCIPHome.ChainConfigArgs[] memory adds = new CCIPHome.ChainConfigArgs[](2); @@ -106,10 +106,9 @@ contract CCIPHome_applyChainConfigUpdates is CCIPHomeTestSetup { assertEq(configs.length, 0, "chain configs length must be 0"); } - function test_applyChainConfigUpdates_removeChainConfigs() public { + function test_applyChainConfigUpdates_removeChainConfigs_Success() public { bytes32[] memory chainReaders = new bytes32[](1); chainReaders[0] = keccak256(abi.encode(1)); - CCIPHome.ChainConfigArgs[] memory adds = new CCIPHome.ChainConfigArgs[](2); adds[0] = CCIPHome.ChainConfigArgs({ chainSelector: 1, @@ -131,7 +130,6 @@ contract CCIPHome_applyChainConfigUpdates is CCIPHomeTestSetup { workflowDONId: uint32(1), capabilitiesDONIds: new uint256[](0) }); - vm.mockCall( CAPABILITIES_REGISTRY, abi.encodeWithSelector(INodeInfoProvider.getNodesByP2PIds.selector, chainReaders), @@ -142,14 +140,10 @@ contract CCIPHome_applyChainConfigUpdates is CCIPHomeTestSetup { emit CCIPHome.ChainConfigSet(1, adds[0].chainConfig); vm.expectEmit(); emit CCIPHome.ChainConfigSet(2, adds[1].chainConfig); - s_ccipHome.applyChainConfigUpdates(new uint64[](0), adds); assertEq(s_ccipHome.getNumChainConfigurations(), 2, "total chain configs must be 2"); - assertEq(s_ccipHome.getChainConfig(adds[0].chainSelector).config, adds[0].chainConfig.config); - assertEq(s_ccipHome.getChainConfig(adds[1].chainSelector).config, adds[1].chainConfig.config); - uint64[] memory removes = new uint64[](1); removes[0] = uint64(1); @@ -162,7 +156,7 @@ contract CCIPHome_applyChainConfigUpdates is CCIPHomeTestSetup { // Reverts. - function test_RevertWhen_applyChainConfigUpdates_selectorNotFound() public { + function test_applyChainConfigUpdates_selectorNotFound_Reverts() public { uint64[] memory removes = new uint64[](1); removes[0] = uint64(1); @@ -170,7 +164,7 @@ contract CCIPHome_applyChainConfigUpdates is CCIPHomeTestSetup { s_ccipHome.applyChainConfigUpdates(removes, new CCIPHome.ChainConfigArgs[](0)); } - function test_RevertWhen_applyChainConfigUpdates_nodeNotInRegistry() public { + function test_applyChainConfigUpdates_nodeNotInRegistry_Reverts() public { bytes32[] memory chainReaders = new bytes32[](1); chainReaders[0] = keccak256(abi.encode(1)); CCIPHome.ChainConfigArgs[] memory adds = new CCIPHome.ChainConfigArgs[](1); @@ -189,7 +183,7 @@ contract CCIPHome_applyChainConfigUpdates is CCIPHomeTestSetup { s_ccipHome.applyChainConfigUpdates(new uint64[](0), adds); } - function test_RevertWhen__applyChainConfigUpdates_FChainNotPositive() public { + function test__applyChainConfigUpdates_FChainNotPositive_Reverts() public { bytes32[] memory chainReaders = new bytes32[](1); chainReaders[0] = keccak256(abi.encode(1)); CCIPHome.ChainConfigArgs[] memory adds = new CCIPHome.ChainConfigArgs[](2); diff --git a/contracts/src/v0.8/ccip/test/capability/CCIPHome/CCIPHome.beforeCapabilityConfigSet.t.sol b/contracts/src/v0.8/ccip/test/capability/CCIPHome/CCIPHome.beforeCapabilityConfigSet.t.sol index 540c9d71e04..090c8336c48 100644 --- a/contracts/src/v0.8/ccip/test/capability/CCIPHome/CCIPHome.beforeCapabilityConfigSet.t.sol +++ b/contracts/src/v0.8/ccip/test/capability/CCIPHome/CCIPHome.beforeCapabilityConfigSet.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import {CCIPHome} from "../../../capability/CCIPHome.sol"; import {Internal} from "../../../libraries/Internal.sol"; @@ -13,7 +13,7 @@ contract CCIPHome_beforeCapabilityConfigSet is CCIPHomeTestSetup { vm.startPrank(address(CAPABILITIES_REGISTRY)); } - function test_beforeCapabilityConfigSet() public { + function test_beforeCapabilityConfigSet_success() public { // first set a config bytes memory callData = abi.encodeCall( CCIPHome.setCandidate, @@ -61,7 +61,7 @@ contract CCIPHome_beforeCapabilityConfigSet is CCIPHomeTestSetup { assertEq(activeDigest, newCandidateDigest); } - function test_RevertWhen_beforeCapabilityConfigSet_OnlyCapabilitiesRegistryCanCall() public { + function test_beforeCapabilityConfigSet_OnlyCapabilitiesRegistryCanCall_reverts() public { bytes memory callData = abi.encodeCall( CCIPHome.setCandidate, (DEFAULT_DON_ID, DEFAULT_PLUGIN_TYPE, _getBaseConfig(Internal.OCRPluginType.Commit), ZERO_DIGEST) @@ -74,14 +74,14 @@ contract CCIPHome_beforeCapabilityConfigSet is CCIPHomeTestSetup { s_ccipHome.beforeCapabilityConfigSet(new bytes32[](0), callData, 0, DEFAULT_DON_ID); } - function test_RevertWhen_beforeCapabilityConfigSet_InvalidSelector() public { + function test_beforeCapabilityConfigSet_InvalidSelector_reverts() public { bytes memory callData = abi.encodeCall(CCIPHome.getConfigDigests, (DEFAULT_DON_ID, DEFAULT_PLUGIN_TYPE)); vm.expectRevert(abi.encodeWithSelector(CCIPHome.InvalidSelector.selector, CCIPHome.getConfigDigests.selector)); s_ccipHome.beforeCapabilityConfigSet(new bytes32[](0), callData, 0, DEFAULT_DON_ID); } - function test_RevertWhen_beforeCapabilityConfigSet_DONIdMismatch() public { + function test_beforeCapabilityConfigSet_DONIdMismatch_reverts() public { uint32 wrongDonId = DEFAULT_DON_ID + 1; bytes memory callData = abi.encodeCall( @@ -93,7 +93,7 @@ contract CCIPHome_beforeCapabilityConfigSet is CCIPHomeTestSetup { s_ccipHome.beforeCapabilityConfigSet(new bytes32[](0), callData, 0, wrongDonId); } - function test_RevertWhen_beforeCapabilityConfigSet_InnerCallReverts() public { + function test_beforeCapabilityConfigSet_InnerCallReverts_reverts() public { bytes memory callData = abi.encodeCall(CCIPHome.revokeCandidate, (DEFAULT_DON_ID, DEFAULT_PLUGIN_TYPE, ZERO_DIGEST)); vm.expectRevert(CCIPHome.RevokingZeroDigestNotAllowed.selector); diff --git a/contracts/src/v0.8/ccip/test/capability/CCIPHome/CCIPHome.constructor.t.sol b/contracts/src/v0.8/ccip/test/capability/CCIPHome/CCIPHome.constructor.t.sol index 18e8c700992..f4c1a777f3d 100644 --- a/contracts/src/v0.8/ccip/test/capability/CCIPHome/CCIPHome.constructor.t.sol +++ b/contracts/src/v0.8/ccip/test/capability/CCIPHome/CCIPHome.constructor.t.sol @@ -1,17 +1,17 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import {CCIPHome} from "../../../capability/CCIPHome.sol"; import {CCIPHomeTestSetup} from "./CCIPHomeTestSetup.t.sol"; contract CCIPHome_constructor is CCIPHomeTestSetup { - function test_constructor() public { + function test_constructor_success() public { CCIPHome ccipHome = new CCIPHome(CAPABILITIES_REGISTRY); assertEq(address(ccipHome.getCapabilityRegistry()), CAPABILITIES_REGISTRY); } - function test_RevertWhen_constructor_CapabilitiesRegistryAddressZero() public { + function test_constructor_CapabilitiesRegistryAddressZero_reverts() public { vm.expectRevert(CCIPHome.ZeroAddressNotAllowed.selector); new CCIPHome(address(0)); } diff --git a/contracts/src/v0.8/ccip/test/capability/CCIPHome/CCIPHome.getAllConfigs.t.sol b/contracts/src/v0.8/ccip/test/capability/CCIPHome/CCIPHome.getAllConfigs.t.sol index c14b54d294e..277819e1179 100644 --- a/contracts/src/v0.8/ccip/test/capability/CCIPHome/CCIPHome.getAllConfigs.t.sol +++ b/contracts/src/v0.8/ccip/test/capability/CCIPHome/CCIPHome.getAllConfigs.t.sol @@ -1,12 +1,12 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import {CCIPHome} from "../../../capability/CCIPHome.sol"; import {Internal} from "../../../libraries/Internal.sol"; import {CCIPHomeTestSetup} from "./CCIPHomeTestSetup.t.sol"; contract CCIPHome_getAllConfigs is CCIPHomeTestSetup { - function test_getAllConfigs() public { + function test_getAllConfigs_success() public { CCIPHome.OCR3Config memory config = _getBaseConfig(Internal.OCRPluginType.Commit); bytes32 firstDigest = s_ccipHome.setCandidate(DEFAULT_DON_ID, DEFAULT_PLUGIN_TYPE, config, ZERO_DIGEST); diff --git a/contracts/src/v0.8/ccip/test/capability/CCIPHome/CCIPHome.getCapabilityConfiguration.t.sol b/contracts/src/v0.8/ccip/test/capability/CCIPHome/CCIPHome.getCapabilityConfiguration.t.sol index d4a6e150bae..ea65e111f0d 100644 --- a/contracts/src/v0.8/ccip/test/capability/CCIPHome/CCIPHome.getCapabilityConfiguration.t.sol +++ b/contracts/src/v0.8/ccip/test/capability/CCIPHome/CCIPHome.getCapabilityConfiguration.t.sol @@ -1,10 +1,10 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import {CCIPHomeTestSetup} from "./CCIPHomeTestSetup.t.sol"; contract CCIPHome_getCapabilityConfiguration is CCIPHomeTestSetup { - function test_getCapabilityConfiguration() public view { + function test_getCapabilityConfiguration_success() public view { bytes memory config = s_ccipHome.getCapabilityConfiguration(DEFAULT_DON_ID); assertEq(config.length, 0); } diff --git a/contracts/src/v0.8/ccip/test/capability/CCIPHome/CCIPHome.getConfigDigests.t.sol b/contracts/src/v0.8/ccip/test/capability/CCIPHome/CCIPHome.getConfigDigests.t.sol index e239d04d341..8cca6b12589 100644 --- a/contracts/src/v0.8/ccip/test/capability/CCIPHome/CCIPHome.getConfigDigests.t.sol +++ b/contracts/src/v0.8/ccip/test/capability/CCIPHome/CCIPHome.getConfigDigests.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import {CCIPHome} from "../../../capability/CCIPHome.sol"; import {Internal} from "../../../libraries/Internal.sol"; @@ -7,7 +7,7 @@ import {Internal} from "../../../libraries/Internal.sol"; import {CCIPHomeTestSetup} from "./CCIPHomeTestSetup.t.sol"; contract CCIPHome_getConfigDigests is CCIPHomeTestSetup { - function test_getConfigDigests() public { + function test_getConfigDigests_success() public { (bytes32 activeDigest, bytes32 candidateDigest) = s_ccipHome.getConfigDigests(DEFAULT_DON_ID, DEFAULT_PLUGIN_TYPE); assertEq(activeDigest, ZERO_DIGEST); assertEq(candidateDigest, ZERO_DIGEST); diff --git a/contracts/src/v0.8/ccip/test/capability/CCIPHome/CCIPHome.promoteCandidateAndRevokeActive.t.sol b/contracts/src/v0.8/ccip/test/capability/CCIPHome/CCIPHome.promoteCandidateAndRevokeActive.t.sol index cfa653754b0..09f25750ac3 100644 --- a/contracts/src/v0.8/ccip/test/capability/CCIPHome/CCIPHome.promoteCandidateAndRevokeActive.t.sol +++ b/contracts/src/v0.8/ccip/test/capability/CCIPHome/CCIPHome.promoteCandidateAndRevokeActive.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import {CCIPHome} from "../../../capability/CCIPHome.sol"; import {Internal} from "../../../libraries/Internal.sol"; @@ -7,7 +7,7 @@ import {Internal} from "../../../libraries/Internal.sol"; import {CCIPHomeTestSetup} from "./CCIPHomeTestSetup.t.sol"; contract CCIPHome_promoteCandidateAndRevokeActive is CCIPHomeTestSetup { - function test_promoteCandidateAndRevokeActive_multiplePlugins() public { + function test_promoteCandidateAndRevokeActive_multiplePlugins_success() public { promoteCandidateAndRevokeActive(Internal.OCRPluginType.Commit); promoteCandidateAndRevokeActive(Internal.OCRPluginType.Execution); @@ -57,12 +57,12 @@ contract CCIPHome_promoteCandidateAndRevokeActive is CCIPHomeTestSetup { assertEq(keccak256(abi.encode(activeConfig.config)), keccak256(abi.encode(config))); } - function test_RevertWhen_promoteCandidateAndRevokeActive_NoOpStateTransitionNotAllowed() public { + function test_promoteCandidateAndRevokeActive_NoOpStateTransitionNotAllowed_reverts() public { vm.expectRevert(CCIPHome.NoOpStateTransitionNotAllowed.selector); s_ccipHome.promoteCandidateAndRevokeActive(DEFAULT_DON_ID, DEFAULT_PLUGIN_TYPE, ZERO_DIGEST, ZERO_DIGEST); } - function test_RevertWhen_promoteCandidateAndRevokeActive_ConfigDigestMismatch() public { + function test_promoteCandidateAndRevokeActive_ConfigDigestMismatch_reverts() public { (bytes32 priorActiveDigest, bytes32 priorCandidateDigest) = s_ccipHome.getConfigDigests(DEFAULT_DON_ID, DEFAULT_PLUGIN_TYPE); bytes32 wrongActiveDigest = keccak256("wrongActiveDigest"); @@ -84,7 +84,7 @@ contract CCIPHome_promoteCandidateAndRevokeActive is CCIPHomeTestSetup { ); } - function test_RevertWhen_promoteCandidateAndRevokeActive_CanOnlySelfCall() public { + function test_promoteCandidateAndRevokeActive_CanOnlySelfCall_reverts() public { vm.stopPrank(); vm.expectRevert(CCIPHome.CanOnlySelfCall.selector); diff --git a/contracts/src/v0.8/ccip/test/capability/CCIPHome/CCIPHome.revokeCandidate.t.sol b/contracts/src/v0.8/ccip/test/capability/CCIPHome/CCIPHome.revokeCandidate.t.sol index 719b8989b1c..b2793727d59 100644 --- a/contracts/src/v0.8/ccip/test/capability/CCIPHome/CCIPHome.revokeCandidate.t.sol +++ b/contracts/src/v0.8/ccip/test/capability/CCIPHome/CCIPHome.revokeCandidate.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import {CCIPHome} from "../../../capability/CCIPHome.sol"; import {Internal} from "../../../libraries/Internal.sol"; @@ -18,7 +18,7 @@ contract CCIPHome_revokeCandidate is CCIPHomeTestSetup { s_ccipHome.setCandidate(DEFAULT_DON_ID, DEFAULT_PLUGIN_TYPE, config, ZERO_DIGEST); } - function test_revokeCandidate() public { + function test_revokeCandidate_success() public { (bytes32 priorActiveDigest, bytes32 priorCandidateDigest) = s_ccipHome.getConfigDigests(DEFAULT_DON_ID, DEFAULT_PLUGIN_TYPE); @@ -42,7 +42,7 @@ contract CCIPHome_revokeCandidate is CCIPHomeTestSetup { assertTrue(candidateDigest != priorCandidateDigest); } - function test_RevertWhen_revokeCandidate_ConfigDigestMismatch() public { + function test_revokeCandidate_ConfigDigestMismatch_reverts() public { (, bytes32 priorCandidateDigest) = s_ccipHome.getConfigDigests(DEFAULT_DON_ID, DEFAULT_PLUGIN_TYPE); bytes32 wrongDigest = keccak256("wrong_digest"); @@ -50,12 +50,12 @@ contract CCIPHome_revokeCandidate is CCIPHomeTestSetup { s_ccipHome.revokeCandidate(DEFAULT_DON_ID, DEFAULT_PLUGIN_TYPE, wrongDigest); } - function test_RevertWhen_revokeCandidate_RevokingZeroDigestNotAllowed() public { + function test_revokeCandidate_RevokingZeroDigestNotAllowed_reverts() public { vm.expectRevert(CCIPHome.RevokingZeroDigestNotAllowed.selector); s_ccipHome.revokeCandidate(DEFAULT_DON_ID, DEFAULT_PLUGIN_TYPE, ZERO_DIGEST); } - function test_RevertWhen_revokeCandidate_CanOnlySelfCall() public { + function test_revokeCandidate_CanOnlySelfCall_reverts() public { vm.startPrank(address(0)); vm.expectRevert(CCIPHome.CanOnlySelfCall.selector); diff --git a/contracts/src/v0.8/ccip/test/capability/CCIPHome/CCIPHome.setCandidate.t.sol b/contracts/src/v0.8/ccip/test/capability/CCIPHome/CCIPHome.setCandidate.t.sol index be0ae1df243..49f365b22cd 100644 --- a/contracts/src/v0.8/ccip/test/capability/CCIPHome/CCIPHome.setCandidate.t.sol +++ b/contracts/src/v0.8/ccip/test/capability/CCIPHome/CCIPHome.setCandidate.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import {CCIPHome} from "../../../capability/CCIPHome.sol"; import {Internal} from "../../../libraries/Internal.sol"; @@ -7,7 +7,7 @@ import {Internal} from "../../../libraries/Internal.sol"; import {CCIPHomeTestSetup} from "./CCIPHomeTestSetup.t.sol"; contract CCIPHome_setCandidate is CCIPHomeTestSetup { - function test_setCandidate() public { + function test_setCandidate_success() public { CCIPHome.OCR3Config memory config = _getBaseConfig(Internal.OCRPluginType.Commit); CCIPHome.VersionedConfig memory versionedConfig = CCIPHome.VersionedConfig({version: 1, config: config, configDigest: ZERO_DIGEST}); @@ -28,7 +28,7 @@ contract CCIPHome_setCandidate is CCIPHomeTestSetup { assertEq(keccak256(abi.encode(storedVersionedConfig.config)), keccak256(abi.encode(versionedConfig.config))); } - function test_RevertWhen_setCandidate_ConfigDigestMismatch() public { + function test_setCandidate_ConfigDigestMismatch_reverts() public { CCIPHome.OCR3Config memory config = _getBaseConfig(Internal.OCRPluginType.Commit); bytes32 digest = s_ccipHome.setCandidate(DEFAULT_DON_ID, DEFAULT_PLUGIN_TYPE, config, ZERO_DIGEST); @@ -42,7 +42,7 @@ contract CCIPHome_setCandidate is CCIPHomeTestSetup { s_ccipHome.setCandidate(DEFAULT_DON_ID, DEFAULT_PLUGIN_TYPE, config, digest); } - function test_RevertWhen_setCandidate_CanOnlySelfCall() public { + function test_setCandidate_CanOnlySelfCall_reverts() public { vm.stopPrank(); vm.expectRevert(CCIPHome.CanOnlySelfCall.selector); diff --git a/contracts/src/v0.8/ccip/test/capability/CCIPHome/CCIPHome.supportsInterface.t.sol b/contracts/src/v0.8/ccip/test/capability/CCIPHome/CCIPHome.supportsInterface.t.sol index 88cefdadb66..c67f007f735 100644 --- a/contracts/src/v0.8/ccip/test/capability/CCIPHome/CCIPHome.supportsInterface.t.sol +++ b/contracts/src/v0.8/ccip/test/capability/CCIPHome/CCIPHome.supportsInterface.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import {ICapabilityConfiguration} from "../../../../keystone/interfaces/ICapabilityConfiguration.sol"; @@ -7,7 +7,7 @@ import {IERC165} from "../../../../vendor/openzeppelin-solidity/v5.0.2/contracts import {CCIPHomeTestSetup} from "./CCIPHomeTestSetup.t.sol"; contract CCIPHome_supportsInterface is CCIPHomeTestSetup { - function test_supportsInterface() public view { + function test_supportsInterface_success() public view { assertTrue(s_ccipHome.supportsInterface(type(IERC165).interfaceId)); assertTrue(s_ccipHome.supportsInterface(type(ICapabilityConfiguration).interfaceId)); } diff --git a/contracts/src/v0.8/ccip/test/capability/CCIPHome/CCIPHome.validateConfig.t.sol b/contracts/src/v0.8/ccip/test/capability/CCIPHome/CCIPHome.validateConfig.t.sol index 4591e9b37bc..13c1a0610d7 100644 --- a/contracts/src/v0.8/ccip/test/capability/CCIPHome/CCIPHome.validateConfig.t.sol +++ b/contracts/src/v0.8/ccip/test/capability/CCIPHome/CCIPHome.validateConfig.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import {INodeInfoProvider} from "../../../../keystone/interfaces/INodeInfoProvider.sol"; @@ -96,11 +96,11 @@ contract CCIPHome__validateConfig is CCIPHomeTestSetup { // Successes. - function test__validateConfig() public { + function test__validateConfig_Success() public { s_ccipHome.validateConfig(_getCorrectOCR3Config()); } - function test__validateConfigLessTransmittersThanSigners() public { + function test__validateConfigLessTransmittersThanSigners_Success() public { // fChain is 1, so there should be at least 4 transmitters. CCIPHome.OCR3Config memory config = _getCorrectOCR3Config(5, 1); config.nodes[1].transmitterKey = bytes(""); @@ -108,7 +108,7 @@ contract CCIPHome__validateConfig is CCIPHomeTestSetup { s_ccipHome.validateConfig(config); } - function test__validateConfigSmallerFChain() public { + function test__validateConfigSmallerFChain_Success() public { CCIPHome.OCR3Config memory config = _getCorrectOCR3Config(11, 3); // Set fChain to 2 @@ -119,7 +119,7 @@ contract CCIPHome__validateConfig is CCIPHomeTestSetup { // Reverts - function test_RevertWhen__validateConfig_ChainSelectorNotSet() public { + function test__validateConfig_ChainSelectorNotSet_Reverts() public { CCIPHome.OCR3Config memory config = _getCorrectOCR3Config(); config.chainSelector = 0; // invalid @@ -127,7 +127,7 @@ contract CCIPHome__validateConfig is CCIPHomeTestSetup { s_ccipHome.validateConfig(config); } - function test_RevertWhen__validateConfig_OfframpAddressCannotBeZero() public { + function test__validateConfig_OfframpAddressCannotBeZero_Reverts() public { CCIPHome.OCR3Config memory config = _getCorrectOCR3Config(); config.offrampAddress = ""; // invalid @@ -135,7 +135,7 @@ contract CCIPHome__validateConfig is CCIPHomeTestSetup { s_ccipHome.validateConfig(config); } - function test_RevertWhen__validateConfig_ABIEncodedAddress_OfframpAddressCannotBeZero() public { + function test__validateConfig_ABIEncodedAddress_OfframpAddressCannotBeZero_Reverts() public { CCIPHome.OCR3Config memory config = _getCorrectOCR3Config(); config.offrampAddress = abi.encode(address(0)); // invalid @@ -143,7 +143,7 @@ contract CCIPHome__validateConfig is CCIPHomeTestSetup { s_ccipHome.validateConfig(config); } - function test_RevertWhen__validateConfig_RMNHomeAddressCannotBeZero() public { + function test__validateConfig_RMNHomeAddressCannotBeZero_Reverts() public { CCIPHome.OCR3Config memory config = _getCorrectOCR3Config(); config.rmnHomeAddress = ""; // invalid @@ -151,7 +151,7 @@ contract CCIPHome__validateConfig is CCIPHomeTestSetup { s_ccipHome.validateConfig(config); } - function test_RevertWhen__validateConfig_ABIEncodedAddress_RMNHomeAddressCannotBeZero() public { + function test__validateConfig_ABIEncodedAddress_RMNHomeAddressCannotBeZero_Reverts() public { CCIPHome.OCR3Config memory config = _getCorrectOCR3Config(); config.rmnHomeAddress = abi.encode(address(0)); // invalid @@ -159,7 +159,7 @@ contract CCIPHome__validateConfig is CCIPHomeTestSetup { s_ccipHome.validateConfig(config); } - function test_RevertWhen__validateConfig_ChainSelectorNotFound() public { + function test__validateConfig_ChainSelectorNotFound_Reverts() public { CCIPHome.OCR3Config memory config = _getCorrectOCR3Config(); config.chainSelector = 2; // not set @@ -167,7 +167,7 @@ contract CCIPHome__validateConfig is CCIPHomeTestSetup { s_ccipHome.validateConfig(config); } - function test_RevertWhen__validateConfig_NotEnoughTransmitters() public { + function test__validateConfig_NotEnoughTransmitters_Reverts() public { CCIPHome.OCR3Config memory config = _getCorrectOCR3Config(); uint256 numberOfTransmitters = 3; @@ -185,7 +185,7 @@ contract CCIPHome__validateConfig is CCIPHomeTestSetup { s_ccipHome.validateConfig(config); } - function test_RevertWhen__validateConfig_NotEnoughTransmittersEmptyAddresses() public { + function test__validateConfig_NotEnoughTransmittersEmptyAddresses_Reverts() public { CCIPHome.OCR3Config memory config = _getCorrectOCR3Config(); config.nodes[0].transmitterKey = bytes(""); @@ -201,7 +201,7 @@ contract CCIPHome__validateConfig is CCIPHomeTestSetup { s_ccipHome.validateConfig(config); } - function test_RevertWhen__validateConfig_TooManySigners() public { + function test__validateConfig_TooManySigners_Reverts() public { CCIPHome.OCR3Config memory config = _getCorrectOCR3Config(); config.nodes = new CCIPHome.OCR3Node[](257); @@ -209,7 +209,7 @@ contract CCIPHome__validateConfig is CCIPHomeTestSetup { s_ccipHome.validateConfig(config); } - function test_RevertWhen__validateConfig_FChainTooHigh() public { + function test__validateConfig_FChainTooHigh_Reverts() public { CCIPHome.OCR3Config memory config = _getCorrectOCR3Config(); config.FRoleDON = 2; // too low @@ -220,7 +220,7 @@ contract CCIPHome__validateConfig is CCIPHomeTestSetup { s_ccipHome.validateConfig(config); } - function test_RevertWhen__validateConfig_FMustBePositive() public { + function test__validateConfig_FMustBePositive_Reverts() public { CCIPHome.OCR3Config memory config = _getCorrectOCR3Config(); config.FRoleDON = 0; // not positive @@ -228,7 +228,7 @@ contract CCIPHome__validateConfig is CCIPHomeTestSetup { s_ccipHome.validateConfig(config); } - function test_RevertWhen__validateConfig_FTooHigh() public { + function test__validateConfig_FTooHigh_Reverts() public { CCIPHome.OCR3Config memory config = _getCorrectOCR3Config(); config.FRoleDON = 2; // too high @@ -236,7 +236,7 @@ contract CCIPHome__validateConfig is CCIPHomeTestSetup { s_ccipHome.validateConfig(config); } - function test_RevertWhen__validateConfig_ZeroP2PId() public { + function test__validateConfig_ZeroP2PId_Reverts() public { CCIPHome.OCR3Config memory config = _getCorrectOCR3Config(); config.nodes[1].p2pId = bytes32(0); @@ -244,7 +244,7 @@ contract CCIPHome__validateConfig is CCIPHomeTestSetup { s_ccipHome.validateConfig(config); } - function test_RevertWhen__validateConfig_ZeroSignerKey() public { + function test__validateConfig_ZeroSignerKey_Reverts() public { CCIPHome.OCR3Config memory config = _getCorrectOCR3Config(); config.nodes[2].signerKey = bytes(""); diff --git a/contracts/src/v0.8/ccip/test/capability/CCIPHome/CCIPHomeTestSetup.t.sol b/contracts/src/v0.8/ccip/test/capability/CCIPHome/CCIPHomeTestSetup.t.sol index 33012aa71eb..a06f50a01cf 100644 --- a/contracts/src/v0.8/ccip/test/capability/CCIPHome/CCIPHomeTestSetup.t.sol +++ b/contracts/src/v0.8/ccip/test/capability/CCIPHome/CCIPHomeTestSetup.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import {INodeInfoProvider} from "../../../../keystone/interfaces/INodeInfoProvider.sol"; diff --git a/contracts/src/v0.8/ccip/test/e2e/End2End.t.sol b/contracts/src/v0.8/ccip/test/e2e/End2End.t.sol index 9851f09e9a5..77dd57a2d08 100644 --- a/contracts/src/v0.8/ccip/test/e2e/End2End.t.sol +++ b/contracts/src/v0.8/ccip/test/e2e/End2End.t.sol @@ -1,6 +1,7 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; +import {IRMN} from "../../interfaces/IRMN.sol"; import {IRMNRemote} from "../../interfaces/IRMNRemote.sol"; import {AuthorizedCallers} from "../../../shared/access/AuthorizedCallers.sol"; @@ -44,7 +45,7 @@ contract E2E is OnRampSetup, OffRampSetup { OffRampSetup.setUp(); // Deploy new source router for the new source chain - s_sourceRouter2 = new Router(s_sourceRouter.getWrappedNative(), address(s_mockRMNRemote)); + s_sourceRouter2 = new Router(s_sourceRouter.getWrappedNative(), address(s_mockRMN)); // Deploy new TokenAdminRegistry for the new source chain s_tokenAdminRegistry2 = new TokenAdminRegistry(); @@ -53,14 +54,7 @@ contract E2E is OnRampSetup, OffRampSetup { for (uint256 i = 0; i < s_sourceTokens.length; ++i) { address token = s_sourceTokens[i]; address pool = address( - new LockReleaseTokenPool( - IERC20(token), - DEFAULT_TOKEN_DECIMALS, - new address[](0), - address(s_mockRMNRemote), - true, - address(s_sourceRouter2) - ) + new LockReleaseTokenPool(IERC20(token), new address[](0), address(s_mockRMN), true, address(s_sourceRouter2)) ); s_sourcePoolByDestPool[s_destPoolBySourceToken[token]] = pool; @@ -82,7 +76,7 @@ contract E2E is OnRampSetup, OffRampSetup { s_nonceManager2 = new NonceManager(new address[](0)); ( - // Deploy the new source chain onRamp + // Deploy the new source chain onramp // Outsource to shared helper function with OnRampSetup s_onRamp2, s_metadataHash2 @@ -101,10 +95,10 @@ contract E2E is OnRampSetup, OffRampSetup { onRampUpdates[0] = Router.OnRamp({destChainSelector: DEST_CHAIN_SELECTOR, onRamp: address(s_onRamp2)}); s_sourceRouter2.applyRampUpdates(onRampUpdates, new Router.OffRamp[](0), new Router.OffRamp[](0)); - // Deploy offRamp + // Deploy offramp _deployOffRamp(s_mockRMNRemote, s_inboundNonceManager); - // Enable source chains on offRamp + // Enable source chains on offramp OffRamp.SourceChainConfigArgs[] memory sourceChainConfigs = new OffRamp.SourceChainConfigArgs[](2); sourceChainConfigs[0] = OffRamp.SourceChainConfigArgs({ router: s_destRouter, @@ -166,7 +160,7 @@ contract E2E is OnRampSetup, OffRampSetup { merkleRoots[0] = MerkleHelper.getMerkleRoot(hashedMessages1); merkleRoots[1] = MerkleHelper.getMerkleRoot(hashedMessages2); - // TODO make these real sigs + // TODO make these real sigs :) IRMNRemote.Signature[] memory rmnSignatures = new IRMNRemote.Signature[](0); Internal.MerkleRoot[] memory roots = new Internal.MerkleRoot[](2); @@ -195,6 +189,9 @@ contract E2E is OnRampSetup, OffRampSetup { // Scoped to RMN and verify to reduce stack pressure { + s_mockRMN.setTaggedRootBlessed(IRMN.TaggedRoot({commitStore: address(s_offRamp), root: merkleRoots[0]}), true); + s_mockRMN.setTaggedRootBlessed(IRMN.TaggedRoot({commitStore: address(s_offRamp), root: merkleRoots[1]}), true); + bytes32[] memory proofs = new bytes32[](0); bytes32[] memory hashedLeaves = new bytes32[](1); hashedLeaves[0] = merkleRoots[0]; @@ -265,7 +262,16 @@ contract E2E is OnRampSetup, OffRampSetup { message.receiver = abi.encode(address(s_receiver)); Internal.EVM2AnyRampMessage memory msgEvent = _messageToEvent( - message, sourceChainSelector, expectedSeqNum, nonce, feeAmount, feeAmount, OWNER, metadataHash, tokenAdminRegistry + message, + sourceChainSelector, + DEST_CHAIN_SELECTOR, + expectedSeqNum, + nonce, + feeAmount, + feeAmount, + OWNER, + metadataHash, + tokenAdminRegistry ); vm.expectEmit(); diff --git a/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.applyDestChainConfigUpdates.t.sol b/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.applyDestChainConfigUpdates.t.sol index c598eedc0d1..b663151a96c 100644 --- a/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.applyDestChainConfigUpdates.t.sol +++ b/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.applyDestChainConfigUpdates.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import {FeeQuoter} from "../../FeeQuoter.sol"; import {Internal} from "../../libraries/Internal.sol"; @@ -38,7 +38,7 @@ contract FeeQuoter_applyDestChainConfigUpdates is FeeQuoterSetup { ); } - function test_applyDestChainConfigUpdates() public { + function test_applyDestChainConfigUpdates_Success() public { FeeQuoter.DestChainConfigArgs[] memory destChainConfigArgs = new FeeQuoter.DestChainConfigArgs[](2); destChainConfigArgs[0] = _generateFeeQuoterDestChainConfigArgs()[0]; destChainConfigArgs[0].destChainConfig.isEnabled = false; @@ -61,7 +61,7 @@ contract FeeQuoter_applyDestChainConfigUpdates is FeeQuoterSetup { _assertFeeQuoterDestChainConfigsEqual(destChainConfigArgs[1].destChainConfig, gotDestChainConfig1); } - function test_applyDestChainConfigUpdatesZeroInput() public { + function test_applyDestChainConfigUpdatesZeroInput_Success() public { FeeQuoter.DestChainConfigArgs[] memory destChainConfigArgs = new FeeQuoter.DestChainConfigArgs[](0); vm.recordLogs(); @@ -72,7 +72,7 @@ contract FeeQuoter_applyDestChainConfigUpdates is FeeQuoterSetup { // Reverts - function test_RevertWhen_applyDestChainConfigUpdatesDefaultTxGasLimitEqZero() public { + function test_applyDestChainConfigUpdatesDefaultTxGasLimitEqZero_Revert() public { FeeQuoter.DestChainConfigArgs[] memory destChainConfigArgs = _generateFeeQuoterDestChainConfigArgs(); FeeQuoter.DestChainConfigArgs memory destChainConfigArg = destChainConfigArgs[0]; @@ -83,7 +83,7 @@ contract FeeQuoter_applyDestChainConfigUpdates is FeeQuoterSetup { s_feeQuoter.applyDestChainConfigUpdates(destChainConfigArgs); } - function test_RevertWhen_applyDestChainConfigUpdatesDefaultTxGasLimitGtMaxPerMessageGasLimit() public { + function test_applyDestChainConfigUpdatesDefaultTxGasLimitGtMaxPerMessageGasLimit_Revert() public { FeeQuoter.DestChainConfigArgs[] memory destChainConfigArgs = _generateFeeQuoterDestChainConfigArgs(); FeeQuoter.DestChainConfigArgs memory destChainConfigArg = destChainConfigArgs[0]; @@ -99,7 +99,7 @@ contract FeeQuoter_applyDestChainConfigUpdates is FeeQuoterSetup { s_feeQuoter.applyDestChainConfigUpdates(destChainConfigArgs); } - function test_RevertWhen_InvalidDestChainConfigDestChainSelectorEqZero() public { + function test_InvalidDestChainConfigDestChainSelectorEqZero_Revert() public { FeeQuoter.DestChainConfigArgs[] memory destChainConfigArgs = _generateFeeQuoterDestChainConfigArgs(); FeeQuoter.DestChainConfigArgs memory destChainConfigArg = destChainConfigArgs[0]; @@ -110,7 +110,7 @@ contract FeeQuoter_applyDestChainConfigUpdates is FeeQuoterSetup { s_feeQuoter.applyDestChainConfigUpdates(destChainConfigArgs); } - function test_RevertWhen_InvalidChainFamilySelector() public { + function test_InvalidChainFamilySelector_Revert() public { FeeQuoter.DestChainConfigArgs[] memory destChainConfigArgs = _generateFeeQuoterDestChainConfigArgs(); FeeQuoter.DestChainConfigArgs memory destChainConfigArg = destChainConfigArgs[0]; diff --git a/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.applyFeeTokensUpdates.t.sol b/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.applyFeeTokensUpdates.t.sol index b2412df3d6b..a32e50bb3e4 100644 --- a/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.applyFeeTokensUpdates.t.sol +++ b/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.applyFeeTokensUpdates.t.sol @@ -1,12 +1,12 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import {Ownable2Step} from "../../../shared/access/Ownable2Step.sol"; import {FeeQuoter} from "../../FeeQuoter.sol"; import {FeeQuoterSetup} from "./FeeQuoterSetup.t.sol"; contract FeeQuoter_applyFeeTokensUpdates is FeeQuoterSetup { - function test_ApplyFeeTokensUpdates() public { + function test_ApplyFeeTokensUpdates_Success() public { address[] memory feeTokens = new address[](1); feeTokens[0] = s_sourceTokens[1]; @@ -48,7 +48,7 @@ contract FeeQuoter_applyFeeTokensUpdates is FeeQuoterSetup { s_feeQuoter.applyFeeTokensUpdates(feeTokens, feeTokens); } - function test_RevertWhen_OnlyCallableByOwner() public { + function test_OnlyCallableByOwner_Revert() public { vm.startPrank(STRANGER); vm.expectRevert(Ownable2Step.OnlyCallableByOwner.selector); diff --git a/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.applyPremiumMultiplierWeiPerEthUpdates.t.sol b/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.applyPremiumMultiplierWeiPerEthUpdates.t.sol index 3eaa8436932..67b1ed9ae92 100644 --- a/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.applyPremiumMultiplierWeiPerEthUpdates.t.sol +++ b/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.applyPremiumMultiplierWeiPerEthUpdates.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import {Ownable2Step} from "../../../shared/access/Ownable2Step.sol"; import {FeeQuoter} from "../../FeeQuoter.sol"; @@ -26,7 +26,7 @@ contract FeeQuoter_applyPremiumMultiplierWeiPerEthUpdates is FeeQuoterSetup { ); } - function test_applyPremiumMultiplierWeiPerEthUpdatesSingleToken() public { + function test_applyPremiumMultiplierWeiPerEthUpdatesSingleToken_Success() public { FeeQuoter.PremiumMultiplierWeiPerEthArgs[] memory premiumMultiplierWeiPerEthArgs = new FeeQuoter.PremiumMultiplierWeiPerEthArgs[](1); premiumMultiplierWeiPerEthArgs[0] = s_feeQuoterPremiumMultiplierWeiPerEthArgs[0]; @@ -45,7 +45,7 @@ contract FeeQuoter_applyPremiumMultiplierWeiPerEthUpdates is FeeQuoterSetup { ); } - function test_applyPremiumMultiplierWeiPerEthUpdatesMultipleTokens() public { + function test_applyPremiumMultiplierWeiPerEthUpdatesMultipleTokens_Success() public { FeeQuoter.PremiumMultiplierWeiPerEthArgs[] memory premiumMultiplierWeiPerEthArgs = new FeeQuoter.PremiumMultiplierWeiPerEthArgs[](2); premiumMultiplierWeiPerEthArgs[0] = s_feeQuoterPremiumMultiplierWeiPerEthArgs[0]; @@ -82,7 +82,7 @@ contract FeeQuoter_applyPremiumMultiplierWeiPerEthUpdates is FeeQuoterSetup { // Reverts - function test_RevertWhen_OnlyCallableByOwnerOrAdmin() public { + function test_OnlyCallableByOwnerOrAdmin_Revert() public { FeeQuoter.PremiumMultiplierWeiPerEthArgs[] memory premiumMultiplierWeiPerEthArgs; vm.startPrank(STRANGER); diff --git a/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.applyTokenTransferFeeConfigUpdates.t.sol b/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.applyTokenTransferFeeConfigUpdates.t.sol index 2acdd1ed0d0..711374a2441 100644 --- a/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.applyTokenTransferFeeConfigUpdates.t.sol +++ b/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.applyTokenTransferFeeConfigUpdates.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import {Ownable2Step} from "../../../shared/access/Ownable2Step.sol"; import {FeeQuoter} from "../../FeeQuoter.sol"; @@ -59,7 +59,7 @@ contract FeeQuoter_applyTokenTransferFeeConfigUpdates is FeeQuoterSetup { } } - function test_ApplyTokenTransferFeeConfig() public { + function test_ApplyTokenTransferFeeConfig_Success() public { FeeQuoter.TokenTransferFeeConfigArgs[] memory tokenTransferFeeConfigArgs = _generateTokenTransferFeeConfigArgs(1, 2); tokenTransferFeeConfigArgs[0].destChainSelector = DEST_CHAIN_SELECTOR; tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[0].token = address(5); @@ -152,7 +152,7 @@ contract FeeQuoter_applyTokenTransferFeeConfigUpdates is FeeQuoterSetup { // Reverts - function test_RevertWhen_OnlyCallableByOwnerOrAdmin() public { + function test_OnlyCallableByOwnerOrAdmin_Revert() public { vm.startPrank(STRANGER); FeeQuoter.TokenTransferFeeConfigArgs[] memory tokenTransferFeeConfigArgs; @@ -163,7 +163,7 @@ contract FeeQuoter_applyTokenTransferFeeConfigUpdates is FeeQuoterSetup { ); } - function test_RevertWhen_InvalidDestBytesOverhead() public { + function test_InvalidDestBytesOverhead_Revert() public { FeeQuoter.TokenTransferFeeConfigArgs[] memory tokenTransferFeeConfigArgs = _generateTokenTransferFeeConfigArgs(1, 1); tokenTransferFeeConfigArgs[0].destChainSelector = DEST_CHAIN_SELECTOR; tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[0].token = address(5); diff --git a/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.constructor.t.sol b/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.constructor.t.sol index e77e52dd25e..c2d36bee96d 100644 --- a/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.constructor.t.sol +++ b/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.constructor.t.sol @@ -1,12 +1,12 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import {FeeQuoter} from "../../FeeQuoter.sol"; import {FeeQuoterHelper} from "../helpers/FeeQuoterHelper.sol"; import {FeeQuoterSetup} from "./FeeQuoterSetup.t.sol"; contract FeeQuoter_constructor is FeeQuoterSetup { - function test_Setup() public virtual { + function test_Setup_Success() public virtual { address[] memory priceUpdaters = new address[](2); priceUpdaters[0] = STRANGER; priceUpdaters[1] = OWNER; @@ -78,7 +78,7 @@ contract FeeQuoter_constructor is FeeQuoterSetup { } } - function test_RevertWhen_InvalidStalenessThreshold() public { + function test_InvalidStalenessThreshold_Revert() public { FeeQuoter.StaticConfig memory staticConfig = FeeQuoter.StaticConfig({ linkToken: s_sourceTokens[0], maxFeeJuelsPerMsg: MAX_MSG_FEES_JUELS, @@ -98,7 +98,7 @@ contract FeeQuoter_constructor is FeeQuoterSetup { ); } - function test_RevertWhen_InvalidLinkTokenEqZeroAddress() public { + function test_InvalidLinkTokenEqZeroAddress_Revert() public { FeeQuoter.StaticConfig memory staticConfig = FeeQuoter.StaticConfig({ linkToken: address(0), maxFeeJuelsPerMsg: MAX_MSG_FEES_JUELS, @@ -118,7 +118,7 @@ contract FeeQuoter_constructor is FeeQuoterSetup { ); } - function test_RevertWhen_InvalidMaxFeeJuelsPerMsg() public { + function test_InvalidMaxFeeJuelsPerMsg_Revert() public { FeeQuoter.StaticConfig memory staticConfig = FeeQuoter.StaticConfig({ linkToken: s_sourceTokens[0], maxFeeJuelsPerMsg: 0, diff --git a/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.convertTokenAmount.t.sol b/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.convertTokenAmount.t.sol index 2d6864b4957..33e941cfbe3 100644 --- a/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.convertTokenAmount.t.sol +++ b/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.convertTokenAmount.t.sol @@ -1,12 +1,12 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import {FeeQuoter} from "../../FeeQuoter.sol"; import {Internal} from "../../libraries/Internal.sol"; import {FeeQuoterSetup} from "./FeeQuoterSetup.t.sol"; contract FeeQuoter_convertTokenAmount is FeeQuoterSetup { - function test_ConvertTokenAmount() public view { + function test_ConvertTokenAmount_Success() public view { Internal.PriceUpdates memory initialPriceUpdates = abi.decode(s_encodedInitialPriceUpdates, (Internal.PriceUpdates)); uint256 amount = 3e16; uint256 conversionRate = (uint256(initialPriceUpdates.tokenPriceUpdates[2].usdPerToken) * 1e18) @@ -50,7 +50,7 @@ contract FeeQuoter_convertTokenAmount is FeeQuoterSetup { // Reverts - function test_RevertWhen_LinkTokenNotSupported() public { + function test_LinkTokenNotSupported_Revert() public { vm.expectRevert(abi.encodeWithSelector(FeeQuoter.TokenNotSupported.selector, DUMMY_CONTRACT_ADDRESS)); s_feeQuoter.convertTokenAmount(DUMMY_CONTRACT_ADDRESS, 3e16, s_sourceTokens[0]); diff --git a/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.getDataAvailabilityCost.t.sol b/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.getDataAvailabilityCost.t.sol index 1d28e8ed756..6f2566ac754 100644 --- a/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.getDataAvailabilityCost.t.sol +++ b/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.getDataAvailabilityCost.t.sol @@ -1,12 +1,12 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import {FeeQuoter} from "../../FeeQuoter.sol"; import {Internal} from "../../libraries/Internal.sol"; import {FeeQuoterSetup} from "./FeeQuoterSetup.t.sol"; contract FeeQuoter_getDataAvailabilityCost is FeeQuoterSetup { - function test_EmptyMessageCalculatesDataAvailabilityCost() public { + function test_EmptyMessageCalculatesDataAvailabilityCost_Success() public { uint256 dataAvailabilityCostUSD = s_feeQuoter.getDataAvailabilityCost(DEST_CHAIN_SELECTOR, USD_PER_DATA_AVAILABILITY_GAS, 0, 0, 0); @@ -42,7 +42,7 @@ contract FeeQuoter_getDataAvailabilityCost is FeeQuoterSetup { assertFalse(dataAvailabilityCostUSD == dataAvailabilityCostUSD2); } - function test_SimpleMessageCalculatesDataAvailabilityCost() public view { + function test_SimpleMessageCalculatesDataAvailabilityCost_Success() public view { uint256 dataAvailabilityCostUSD = s_feeQuoter.getDataAvailabilityCost(DEST_CHAIN_SELECTOR, USD_PER_DATA_AVAILABILITY_GAS, 100, 5, 50); @@ -58,7 +58,7 @@ contract FeeQuoter_getDataAvailabilityCost is FeeQuoterSetup { assertEq(expectedDataAvailabilityCostUSD, dataAvailabilityCostUSD); } - function test_SimpleMessageCalculatesDataAvailabilityCostUnsupportedDestChainSelector() public view { + function test_SimpleMessageCalculatesDataAvailabilityCostUnsupportedDestChainSelector_Success() public view { uint256 dataAvailabilityCostUSD = s_feeQuoter.getDataAvailabilityCost(0, USD_PER_DATA_AVAILABILITY_GAS, 100, 5, 50); assertEq(dataAvailabilityCostUSD, 0); diff --git a/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.getTokenAndGasPrices.t.sol b/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.getTokenAndGasPrices.t.sol index d7919293759..18ccf5efa79 100644 --- a/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.getTokenAndGasPrices.t.sol +++ b/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.getTokenAndGasPrices.t.sol @@ -1,12 +1,12 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import {FeeQuoter} from "../../FeeQuoter.sol"; import {Internal} from "../../libraries/Internal.sol"; import {FeeQuoterSetup} from "./FeeQuoterSetup.t.sol"; contract FeeQuoter_getTokenAndGasPrices is FeeQuoterSetup { - function test_GetFeeTokenAndGasPrices() public view { + function test_GetFeeTokenAndGasPrices_Success() public view { (uint224 feeTokenPrice, uint224 gasPrice) = s_feeQuoter.getTokenAndGasPrices(s_sourceFeeToken, DEST_CHAIN_SELECTOR); Internal.PriceUpdates memory priceUpdates = abi.decode(s_encodedInitialPriceUpdates, (Internal.PriceUpdates)); @@ -15,7 +15,7 @@ contract FeeQuoter_getTokenAndGasPrices is FeeQuoterSetup { assertEq(gasPrice, priceUpdates.gasPriceUpdates[0].usdPerUnitGas); } - function test_StalenessCheckDisabled() public { + function test_StalenessCheckDisabled_Success() public { uint64 neverStaleChainSelector = 345678; FeeQuoter.DestChainConfigArgs[] memory destChainConfigArgs = _generateFeeQuoterDestChainConfigArgs(); destChainConfigArgs[0].destChainSelector = neverStaleChainSelector; @@ -38,7 +38,7 @@ contract FeeQuoter_getTokenAndGasPrices is FeeQuoterSetup { assertEq(gasPrice, 999); } - function test_ZeroGasPrice() public { + function test_ZeroGasPrice_Success() public { uint64 zeroGasDestChainSelector = 345678; FeeQuoter.DestChainConfigArgs[] memory destChainConfigArgs = _generateFeeQuoterDestChainConfigArgs(); destChainConfigArgs[0].destChainSelector = zeroGasDestChainSelector; @@ -56,12 +56,12 @@ contract FeeQuoter_getTokenAndGasPrices is FeeQuoterSetup { assertEq(gasPrice, 0); } - function test_RevertWhen_UnsupportedChain() public { + function test_UnsupportedChain_Revert() public { vm.expectRevert(abi.encodeWithSelector(FeeQuoter.DestinationChainNotEnabled.selector, DEST_CHAIN_SELECTOR + 1)); s_feeQuoter.getTokenAndGasPrices(s_sourceTokens[0], DEST_CHAIN_SELECTOR + 1); } - function test_RevertWhen_StaleGasPrice() public { + function test_StaleGasPrice_Revert() public { uint256 diff = TWELVE_HOURS + 1; vm.warp(block.timestamp + diff); vm.expectRevert(abi.encodeWithSelector(FeeQuoter.StaleGasPrice.selector, DEST_CHAIN_SELECTOR, TWELVE_HOURS, diff)); diff --git a/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.getTokenPrice.t.sol b/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.getTokenPrice.t.sol index a06e4cbebf8..c00e750d27f 100644 --- a/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.getTokenPrice.t.sol +++ b/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.getTokenPrice.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import {MockV3Aggregator} from "../../../tests/MockV3Aggregator.sol"; import {FeeQuoter} from "../../FeeQuoter.sol"; @@ -7,8 +7,8 @@ import {Internal} from "../../libraries/Internal.sol"; import {FeeQuoterSetup} from "./FeeQuoterSetup.t.sol"; contract FeeQuoter_getTokenPrice is FeeQuoterSetup { - function test_GetTokenPriceFromFeed() public { - uint32 originalTimestampValue = uint32(block.timestamp); + function test_GetTokenPriceFromFeed_Success() public { + uint256 originalTimestampValue = block.timestamp; // Above staleness threshold vm.warp(originalTimestampValue + s_feeQuoter.getStaticConfig().tokenPriceStalenessThreshold + 1); @@ -24,16 +24,16 @@ contract FeeQuoter_getTokenPrice is FeeQuoterSetup { assertEq(tokenPriceAnswer.timestamp, uint32(originalTimestampValue)); } - function test_GetTokenPrice_LocalMoreRecent() public { - uint32 originalTimestampValue = uint32(block.timestamp); - uint224 usdPerToken = 1e18; + function test_GetTokenPrice_LocalMoreRecent_Success() public { + uint256 originalTimestampValue = block.timestamp; Internal.PriceUpdates memory update = Internal.PriceUpdates({ tokenPriceUpdates: new Internal.TokenPriceUpdate[](1), gasPriceUpdates: new Internal.GasPriceUpdate[](0) }); - update.tokenPriceUpdates[0] = Internal.TokenPriceUpdate({sourceToken: s_sourceTokens[0], usdPerToken: usdPerToken}); + update.tokenPriceUpdates[0] = + Internal.TokenPriceUpdate({sourceToken: s_sourceTokens[0], usdPerToken: uint32(originalTimestampValue + 5)}); vm.expectEmit(); emit FeeQuoter.UsdPerTokenUpdated( @@ -48,6 +48,6 @@ contract FeeQuoter_getTokenPrice is FeeQuoterSetup { //Assert that the returned price is the local price, not the oracle price assertEq(tokenPriceAnswer.value, update.tokenPriceUpdates[0].usdPerToken); - assertEq(tokenPriceAnswer.timestamp, originalTimestampValue); + assertEq(tokenPriceAnswer.timestamp, uint32(originalTimestampValue)); } } diff --git a/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.getTokenPrices.t.sol b/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.getTokenPrices.t.sol index 89edbddee38..63f936332fd 100644 --- a/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.getTokenPrices.t.sol +++ b/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.getTokenPrices.t.sol @@ -1,11 +1,11 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import {Internal} from "../../libraries/Internal.sol"; import {FeeQuoterSetup} from "./FeeQuoterSetup.t.sol"; contract FeeQuoter_getTokenPrices is FeeQuoterSetup { - function test_GetTokenPrices() public view { + function test_GetTokenPrices_Success() public view { Internal.PriceUpdates memory priceUpdates = abi.decode(s_encodedInitialPriceUpdates, (Internal.PriceUpdates)); address[] memory tokens = new address[](3); diff --git a/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.getTokenTransferCost.t.sol b/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.getTokenTransferCost.t.sol index 76298b7c838..9f0aa9440b8 100644 --- a/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.getTokenTransferCost.t.sol +++ b/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.getTokenTransferCost.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import {FeeQuoter} from "../../FeeQuoter.sol"; import {Client} from "../../libraries/Client.sol"; @@ -12,7 +12,7 @@ contract FeeQuoter_getTokenTransferCost is FeeQuoterFeeSetup { address internal s_selfServeTokenDefaultPricing = makeAddr("self-serve-token-default-pricing"); - function test_NoTokenTransferChargesZeroFee() public view { + function test_NoTokenTransferChargesZeroFee_Success() public view { Client.EVM2AnyMessage memory message = _generateEmptyMessage(); (uint256 feeUSDWei, uint32 destGasOverhead, uint32 destBytesOverhead) = s_feeQuoter.getTokenTransferCost(DEST_CHAIN_SELECTOR, message.feeToken, s_feeTokenPrice, message.tokenAmounts); @@ -22,7 +22,7 @@ contract FeeQuoter_getTokenTransferCost is FeeQuoterFeeSetup { assertEq(0, destBytesOverhead); } - function test_getTokenTransferCost_selfServeUsesDefaults() public view { + function test_getTokenTransferCost_selfServeUsesDefaults_Success() public view { Client.EVM2AnyMessage memory message = _generateSingleTokenMessage(s_selfServeTokenDefaultPricing, 1000); // Get config to assert it isn't set @@ -40,7 +40,7 @@ contract FeeQuoter_getTokenTransferCost is FeeQuoterFeeSetup { assertEq(DEFAULT_TOKEN_BYTES_OVERHEAD, destBytesOverhead); } - function test_SmallTokenTransferChargesMinFeeAndGas() public view { + function test_SmallTokenTransferChargesMinFeeAndGas_Success() public view { Client.EVM2AnyMessage memory message = _generateSingleTokenMessage(s_sourceFeeToken, 1000); FeeQuoter.TokenTransferFeeConfig memory transferFeeConfig = s_feeQuoter.getTokenTransferFeeConfig(DEST_CHAIN_SELECTOR, message.tokenAmounts[0].token); @@ -53,7 +53,7 @@ contract FeeQuoter_getTokenTransferCost is FeeQuoterFeeSetup { assertEq(transferFeeConfig.destBytesOverhead, destBytesOverhead); } - function test_ZeroAmountTokenTransferChargesMinFeeAndGas() public view { + function test_ZeroAmountTokenTransferChargesMinFeeAndGas_Success() public view { Client.EVM2AnyMessage memory message = _generateSingleTokenMessage(s_sourceFeeToken, 0); FeeQuoter.TokenTransferFeeConfig memory transferFeeConfig = s_feeQuoter.getTokenTransferFeeConfig(DEST_CHAIN_SELECTOR, message.tokenAmounts[0].token); @@ -66,7 +66,7 @@ contract FeeQuoter_getTokenTransferCost is FeeQuoterFeeSetup { assertEq(transferFeeConfig.destBytesOverhead, destBytesOverhead); } - function test_LargeTokenTransferChargesMaxFeeAndGas() public view { + function test_LargeTokenTransferChargesMaxFeeAndGas_Success() public view { Client.EVM2AnyMessage memory message = _generateSingleTokenMessage(s_sourceFeeToken, 1e36); FeeQuoter.TokenTransferFeeConfig memory transferFeeConfig = s_feeQuoter.getTokenTransferFeeConfig(DEST_CHAIN_SELECTOR, message.tokenAmounts[0].token); @@ -79,7 +79,7 @@ contract FeeQuoter_getTokenTransferCost is FeeQuoterFeeSetup { assertEq(transferFeeConfig.destBytesOverhead, destBytesOverhead); } - function test_FeeTokenBpsFee() public view { + function test_FeeTokenBpsFee_Success() public view { uint256 tokenAmount = 10000e18; Client.EVM2AnyMessage memory message = _generateSingleTokenMessage(s_sourceFeeToken, tokenAmount); @@ -99,7 +99,7 @@ contract FeeQuoter_getTokenTransferCost is FeeQuoterFeeSetup { assertEq(transferFeeConfig.destBytesOverhead, destBytesOverhead); } - function test_CustomTokenBpsFee() public view { + function test_CustomTokenBpsFee_Success() public view { uint256 tokenAmount = 200000e18; Client.EVM2AnyMessage memory message = Client.EVM2AnyMessage({ @@ -127,7 +127,7 @@ contract FeeQuoter_getTokenTransferCost is FeeQuoterFeeSetup { assertEq(transferFeeConfig.destBytesOverhead, destBytesOverhead); } - function test_ZeroFeeConfigChargesMinFee() public { + function test_ZeroFeeConfigChargesMinFee_Success() public { FeeQuoter.TokenTransferFeeConfigArgs[] memory tokenTransferFeeConfigArgs = _generateTokenTransferFeeConfigArgs(1, 1); tokenTransferFeeConfigArgs[0].destChainSelector = DEST_CHAIN_SELECTOR; tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[0].token = s_sourceFeeToken; @@ -185,7 +185,7 @@ contract FeeQuoter_getTokenTransferCost is FeeQuoterFeeSetup { assertEq(bytesOverheadMultiple, bytesOverheadSingle * transfers); } - function test_MixedTokenTransferFee() public view { + function test_MixedTokenTransferFee_Success() public view { address[3] memory testTokens = [s_sourceFeeToken, s_sourceRouter.getWrappedNative(), CUSTOM_TOKEN]; uint224[3] memory tokenPrices = [s_feeTokenPrice, s_wrappedTokenPrice, CUSTOM_TOKEN_PRICE]; FeeQuoter.TokenTransferFeeConfig[3] memory tokenTransferFeeConfigs = [ diff --git a/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.getValidatedFee.t.sol b/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.getValidatedFee.t.sol index 54832a30783..1f76f3120ae 100644 --- a/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.getValidatedFee.t.sol +++ b/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.getValidatedFee.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import {FeeQuoter} from "../../FeeQuoter.sol"; import {Client} from "../../libraries/Client.sol"; @@ -11,7 +11,7 @@ import {FeeQuoterFeeSetup} from "./FeeQuoterSetup.t.sol"; contract FeeQuoter_getValidatedFee is FeeQuoterFeeSetup { using USDPriceWith18Decimals for uint224; - function test_EmptyMessage() public view { + function test_EmptyMessage_Success() public view { address[2] memory testTokens = [s_sourceFeeToken, s_sourceRouter.getWrappedNative()]; uint224[2] memory feeTokenPrices = [s_feeTokenPrice, s_wrappedTokenPrice]; @@ -35,7 +35,7 @@ contract FeeQuoter_getValidatedFee is FeeQuoterFeeSetup { } } - function test_ZeroDataAvailabilityMultiplier() public { + function test_ZeroDataAvailabilityMultiplier_Success() public { FeeQuoter.DestChainConfigArgs[] memory destChainConfigArgs = new FeeQuoter.DestChainConfigArgs[](1); FeeQuoter.DestChainConfig memory destChainConfig = s_feeQuoter.getDestChainConfig(DEST_CHAIN_SELECTOR); destChainConfigArgs[0] = @@ -56,7 +56,7 @@ contract FeeQuoter_getValidatedFee is FeeQuoterFeeSetup { assertEq(totalPriceInFeeToken, feeAmount); } - function test_HighGasMessage() public view { + function test_HighGasMessage_Success() public view { address[2] memory testTokens = [s_sourceFeeToken, s_sourceRouter.getWrappedNative()]; uint224[2] memory feeTokenPrices = [s_feeTokenPrice, s_wrappedTokenPrice]; @@ -87,7 +87,7 @@ contract FeeQuoter_getValidatedFee is FeeQuoterFeeSetup { } } - function test_SingleTokenMessage() public view { + function test_SingleTokenMessage_Success() public view { address[2] memory testTokens = [s_sourceFeeToken, s_sourceRouter.getWrappedNative()]; uint224[2] memory feeTokenPrices = [s_feeTokenPrice, s_wrappedTokenPrice]; @@ -103,7 +103,7 @@ contract FeeQuoter_getValidatedFee is FeeQuoterFeeSetup { uint256 feeAmount = s_feeQuoter.getValidatedFee(DEST_CHAIN_SELECTOR, message); - uint256 gasUsed = GAS_LIMIT + DEST_GAS_OVERHEAD + tokenBytesOverhead * DEST_GAS_PER_PAYLOAD_BYTE + uint256 gasUsed = GAS_LIMIT + DEST_GAS_OVERHEAD + s_feeQuoter.getTokenTransferFeeConfig(DEST_CHAIN_SELECTOR, message.tokenAmounts[0].token).destGasOverhead; uint256 gasFeeUSD = (gasUsed * destChainConfig.gasMultiplierWeiPerEth * USD_PER_GAS); (uint256 transferFeeUSD,,) = @@ -122,7 +122,7 @@ contract FeeQuoter_getValidatedFee is FeeQuoterFeeSetup { } } - function test_MessageWithDataAndTokenTransfer() public view { + function test_MessageWithDataAndTokenTransfer_Success() public view { address[2] memory testTokens = [s_sourceFeeToken, s_sourceRouter.getWrappedNative()]; uint224[2] memory feeTokenPrices = [s_feeTokenPrice, s_wrappedTokenPrice]; @@ -152,20 +152,12 @@ contract FeeQuoter_getValidatedFee is FeeQuoterFeeSetup { tokenBytesOverhead += destBytesOverhead == 0 ? uint32(Pool.CCIP_LOCK_OR_BURN_V1_RET_BYTES) : destBytesOverhead; } - (uint256 transferFeeUSD,, uint256 tokenTransferBytesOverhead) = + uint256 gasUsed = + customGasLimit + DEST_GAS_OVERHEAD + message.data.length * DEST_GAS_PER_PAYLOAD_BYTE + tokenGasOverhead; + uint256 gasFeeUSD = (gasUsed * destChainConfig.gasMultiplierWeiPerEth * USD_PER_GAS); + (uint256 transferFeeUSD,,) = s_feeQuoter.getTokenTransferCost(DEST_CHAIN_SELECTOR, message.feeToken, feeTokenPrices[i], message.tokenAmounts); - - uint256 gasFeeUSD; - - { - uint256 gasUsed = customGasLimit + DEST_GAS_OVERHEAD - + (message.data.length + tokenTransferBytesOverhead) * DEST_GAS_PER_PAYLOAD_BYTE + tokenGasOverhead; - - gasFeeUSD = (gasUsed * destChainConfig.gasMultiplierWeiPerEth * USD_PER_GAS); - } - uint256 messageFeeUSD = (transferFeeUSD * premiumMultiplierWeiPerEth); - uint256 dataAvailabilityFeeUSD = s_feeQuoter.getDataAvailabilityCost( DEST_CHAIN_SELECTOR, USD_PER_DATA_AVAILABILITY_GAS, @@ -203,12 +195,12 @@ contract FeeQuoter_getValidatedFee is FeeQuoterFeeSetup { // Reverts - function test_RevertWhen_DestinationChainNotEnabled() public { + function test_DestinationChainNotEnabled_Revert() public { vm.expectRevert(abi.encodeWithSelector(FeeQuoter.DestinationChainNotEnabled.selector, DEST_CHAIN_SELECTOR + 1)); s_feeQuoter.getValidatedFee(DEST_CHAIN_SELECTOR + 1, _generateEmptyMessage()); } - function test_RevertWhen_EnforceOutOfOrder() public { + function test_EnforceOutOfOrder_Revert() public { // Update config to enforce allowOutOfOrderExecution = true. vm.stopPrank(); vm.startPrank(OWNER); @@ -226,7 +218,7 @@ contract FeeQuoter_getValidatedFee is FeeQuoterFeeSetup { s_feeQuoter.getValidatedFee(DEST_CHAIN_SELECTOR, message); } - function test_RevertWhen_MessageTooLarge() public { + function test_MessageTooLarge_Revert() public { Client.EVM2AnyMessage memory message = _generateEmptyMessage(); message.data = new bytes(MAX_DATA_SIZE + 1); vm.expectRevert(abi.encodeWithSelector(FeeQuoter.MessageTooLarge.selector, MAX_DATA_SIZE, message.data.length)); @@ -234,7 +226,7 @@ contract FeeQuoter_getValidatedFee is FeeQuoterFeeSetup { s_feeQuoter.getValidatedFee(DEST_CHAIN_SELECTOR, message); } - function test_RevertWhen_TooManyTokens() public { + function test_TooManyTokens_Revert() public { Client.EVM2AnyMessage memory message = _generateEmptyMessage(); uint256 tooMany = MAX_TOKENS_LENGTH + 1; message.tokenAmounts = new Client.EVMTokenAmount[](tooMany); @@ -243,14 +235,14 @@ contract FeeQuoter_getValidatedFee is FeeQuoterFeeSetup { } // Asserts gasLimit must be <=maxGasLimit - function test_RevertWhen_MessageGasLimitTooHigh() public { + function test_MessageGasLimitTooHigh_Revert() public { Client.EVM2AnyMessage memory message = _generateEmptyMessage(); message.extraArgs = Client._argsToBytes(Client.EVMExtraArgsV1({gasLimit: MAX_GAS_LIMIT + 1})); vm.expectRevert(abi.encodeWithSelector(FeeQuoter.MessageGasLimitTooHigh.selector)); s_feeQuoter.getValidatedFee(DEST_CHAIN_SELECTOR, message); } - function test_RevertWhen_NotAFeeToken() public { + function test_NotAFeeToken_Revert() public { address notAFeeToken = address(0x111111); Client.EVM2AnyMessage memory message = _generateSingleTokenMessage(notAFeeToken, 1); message.feeToken = notAFeeToken; @@ -260,7 +252,7 @@ contract FeeQuoter_getValidatedFee is FeeQuoterFeeSetup { s_feeQuoter.getValidatedFee(DEST_CHAIN_SELECTOR, message); } - function test_RevertWhen_InvalidEVMAddress() public { + function test_InvalidEVMAddress_Revert() public { Client.EVM2AnyMessage memory message = _generateEmptyMessage(); message.receiver = abi.encode(type(uint208).max); diff --git a/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.getValidatedTokenPrice.t.sol b/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.getValidatedTokenPrice.t.sol index d43cc5a6799..6d508bc9116 100644 --- a/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.getValidatedTokenPrice.t.sol +++ b/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.getValidatedTokenPrice.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import {MockV3Aggregator} from "../../../tests/MockV3Aggregator.sol"; import {FeeQuoter} from "../../FeeQuoter.sol"; @@ -7,7 +7,7 @@ import {Internal} from "../../libraries/Internal.sol"; import {FeeQuoterSetup} from "./FeeQuoterSetup.t.sol"; contract FeeQuoter_getValidatedTokenPrice is FeeQuoterSetup { - function test_GetValidatedTokenPrice() public view { + function test_GetValidatedTokenPrice_Success() public view { Internal.PriceUpdates memory priceUpdates = abi.decode(s_encodedInitialPriceUpdates, (Internal.PriceUpdates)); address token = priceUpdates.tokenPriceUpdates[0].sourceToken; @@ -16,7 +16,7 @@ contract FeeQuoter_getValidatedTokenPrice is FeeQuoterSetup { assertEq(priceUpdates.tokenPriceUpdates[0].usdPerToken, tokenPrice); } - function test_GetValidatedTokenPriceFromFeed() public { + function test_GetValidatedTokenPriceFromFeed_Success() public { uint256 originalTimestampValue = block.timestamp; // Right below staleness threshold @@ -29,7 +29,7 @@ contract FeeQuoter_getValidatedTokenPrice is FeeQuoterSetup { assertEq(tokenPriceAnswer, uint224(1e18)); } - function test_GetValidatedTokenPriceFromFeedOverStalenessPeriod() public { + function test_GetValidatedTokenPriceFromFeedOverStalenessPeriod_Success() public { uint256 originalTimestampValue = block.timestamp; // Right above staleness threshold @@ -42,7 +42,7 @@ contract FeeQuoter_getValidatedTokenPrice is FeeQuoterSetup { assertEq(tokenPriceAnswer, uint224(1e18)); } - function test_GetValidatedTokenPriceFromFeedMaxInt224Value() public { + function test_GetValidatedTokenPriceFromFeedMaxInt224Value_Success() public { address tokenAddress = _deploySourceToken("testToken", 0, 18); address feedAddress = _deployTokenPriceDataFeed(tokenAddress, 18, int256(uint256(type(uint224).max))); @@ -56,7 +56,7 @@ contract FeeQuoter_getValidatedTokenPrice is FeeQuoterSetup { assertEq(tokenPriceAnswer, uint224(type(uint224).max)); } - function test_GetValidatedTokenPriceFromFeedErc20Below18Decimals() public { + function test_GetValidatedTokenPriceFromFeedErc20Below18Decimals_Success() public { address tokenAddress = _deploySourceToken("testToken", 0, 6); address feedAddress = _deployTokenPriceDataFeed(tokenAddress, 8, 1e8); @@ -70,7 +70,7 @@ contract FeeQuoter_getValidatedTokenPrice is FeeQuoterSetup { assertEq(tokenPriceAnswer, uint224(1e30)); } - function test_GetValidatedTokenPriceFromFeedErc20Above18Decimals() public { + function test_GetValidatedTokenPriceFromFeedErc20Above18Decimals_Success() public { address tokenAddress = _deploySourceToken("testToken", 0, 24); address feedAddress = _deployTokenPriceDataFeed(tokenAddress, 8, 1e8); @@ -84,7 +84,7 @@ contract FeeQuoter_getValidatedTokenPrice is FeeQuoterSetup { assertEq(tokenPriceAnswer, uint224(1e12)); } - function test_GetValidatedTokenPriceFromFeedFeedAt18Decimals() public { + function test_GetValidatedTokenPriceFromFeedFeedAt18Decimals_Success() public { address tokenAddress = _deploySourceToken("testToken", 0, 18); address feedAddress = _deployTokenPriceDataFeed(tokenAddress, 18, 1e18); @@ -98,7 +98,7 @@ contract FeeQuoter_getValidatedTokenPrice is FeeQuoterSetup { assertEq(tokenPriceAnswer, uint224(1e18)); } - function test_GetValidatedTokenPriceFromFeedFeedAt0Decimals() public { + function test_GetValidatedTokenPriceFromFeedFeedAt0Decimals_Success() public { address tokenAddress = _deploySourceToken("testToken", 0, 0); address feedAddress = _deployTokenPriceDataFeed(tokenAddress, 0, 1e31); @@ -112,7 +112,7 @@ contract FeeQuoter_getValidatedTokenPrice is FeeQuoterSetup { assertEq(tokenPriceAnswer, uint224(1e67)); } - function test_GetValidatedTokenPriceFromFeedFlippedDecimals() public { + function test_GetValidatedTokenPriceFromFeedFlippedDecimals_Success() public { address tokenAddress = _deploySourceToken("testToken", 0, 20); address feedAddress = _deployTokenPriceDataFeed(tokenAddress, 20, 1e18); @@ -126,7 +126,7 @@ contract FeeQuoter_getValidatedTokenPrice is FeeQuoterSetup { assertEq(tokenPriceAnswer, uint224(1e14)); } - function test_StaleFeeToken() public { + function test_StaleFeeToken_Success() public { vm.warp(block.timestamp + TWELVE_HOURS + 1); Internal.PriceUpdates memory priceUpdates = abi.decode(s_encodedInitialPriceUpdates, (Internal.PriceUpdates)); @@ -139,7 +139,7 @@ contract FeeQuoter_getValidatedTokenPrice is FeeQuoterSetup { // Reverts - function test_RevertWhen_OverflowFeedPrice() public { + function test_OverflowFeedPrice_Revert() public { address tokenAddress = _deploySourceToken("testToken", 0, 18); address feedAddress = _deployTokenPriceDataFeed(tokenAddress, 18, int256(uint256(type(uint224).max) + 1)); @@ -151,7 +151,7 @@ contract FeeQuoter_getValidatedTokenPrice is FeeQuoterSetup { s_feeQuoter.getValidatedTokenPrice(tokenAddress); } - function test_RevertWhen_UnderflowFeedPrice() public { + function test_UnderflowFeedPrice_Revert() public { address tokenAddress = _deploySourceToken("testToken", 0, 18); address feedAddress = _deployTokenPriceDataFeed(tokenAddress, 18, -1); @@ -163,12 +163,12 @@ contract FeeQuoter_getValidatedTokenPrice is FeeQuoterSetup { s_feeQuoter.getValidatedTokenPrice(tokenAddress); } - function test_RevertWhen_TokenNotSupported() public { + function test_TokenNotSupported_Revert() public { vm.expectRevert(abi.encodeWithSelector(FeeQuoter.TokenNotSupported.selector, DUMMY_CONTRACT_ADDRESS)); s_feeQuoter.getValidatedTokenPrice(DUMMY_CONTRACT_ADDRESS); } - function test_RevertWhen_TokenNotSupportedFeed() public { + function test_TokenNotSupportedFeed_Revert() public { address sourceToken = _initialiseSingleTokenPriceFeed(); MockV3Aggregator(s_dataFeedByToken[sourceToken]).updateAnswer(0); Internal.PriceUpdates memory priceUpdates = Internal.PriceUpdates({ diff --git a/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.onReport.t.sol b/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.onReport.t.sol index dd132e43b22..aba4e178865 100644 --- a/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.onReport.t.sol +++ b/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.onReport.t.sol @@ -1,43 +1,31 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import {KeystoneFeedsPermissionHandler} from "../../../keystone/KeystoneFeedsPermissionHandler.sol"; - -import {KeystoneForwarder} from "../../../keystone/KeystoneForwarder.sol"; import {FeeQuoter} from "../../FeeQuoter.sol"; import {FeeQuoterSetup} from "./FeeQuoterSetup.t.sol"; contract FeeQuoter_onReport is FeeQuoterSetup { - bytes32 internal constant EXECUTION_ID = hex"6d795f657865637574696f6e5f69640000000000000000000000000000000000"; - address internal constant TRANSMITTER = address(50); - bytes32 internal constant WORKFLOW_ID_1 = hex"6d795f6964000000000000000000000000000000000000000000000000000000"; - address internal constant WORKFLOW_OWNER_1 = address(51); - bytes10 internal constant WORKFLOW_NAME_1 = hex"000000000000DEADBEEF"; - bytes2 internal constant REPORT_NAME_1 = hex"0001"; + address internal constant FORWARDER_1 = address(0x1); + address internal constant WORKFLOW_OWNER_1 = address(0x3); + bytes10 internal constant WORKFLOW_NAME_1 = "workflow1"; + bytes2 internal constant REPORT_NAME_1 = "01"; address internal s_onReportTestToken1; address internal s_onReportTestToken2; - bytes public encodedPermissionsMetadata; - KeystoneForwarder internal s_forwarder; function setUp() public virtual override { super.setUp(); - - s_forwarder = new KeystoneForwarder(); - s_onReportTestToken1 = s_sourceTokens[0]; s_onReportTestToken2 = _deploySourceToken("onReportTestToken2", 0, 20); KeystoneFeedsPermissionHandler.Permission[] memory permissions = new KeystoneFeedsPermissionHandler.Permission[](1); permissions[0] = KeystoneFeedsPermissionHandler.Permission({ - forwarder: address(s_forwarder), + forwarder: FORWARDER_1, workflowOwner: WORKFLOW_OWNER_1, workflowName: WORKFLOW_NAME_1, reportName: REPORT_NAME_1, isAllowed: true }); - - encodedPermissionsMetadata = abi.encodePacked(WORKFLOW_ID_1, WORKFLOW_NAME_1, WORKFLOW_OWNER_1, REPORT_NAME_1); - FeeQuoter.TokenPriceFeedUpdate[] memory tokenPriceFeeds = new FeeQuoter.TokenPriceFeedUpdate[](2); tokenPriceFeeds[0] = FeeQuoter.TokenPriceFeedUpdate({ sourceToken: s_onReportTestToken1, @@ -51,7 +39,10 @@ contract FeeQuoter_onReport is FeeQuoterSetup { s_feeQuoter.updateTokenPriceFeeds(tokenPriceFeeds); } - function test_onReport() public { + function test_onReport_Success() public { + bytes memory encodedPermissionsMetadata = + abi.encodePacked(keccak256(abi.encode("workflowCID")), WORKFLOW_NAME_1, WORKFLOW_OWNER_1, REPORT_NAME_1); + FeeQuoter.ReceivedCCIPFeedReport[] memory report = new FeeQuoter.ReceivedCCIPFeedReport[](2); report[0] = FeeQuoter.ReceivedCCIPFeedReport({token: s_onReportTestToken1, price: 4e18, timestamp: uint32(block.timestamp)}); @@ -65,7 +56,7 @@ contract FeeQuoter_onReport is FeeQuoterSetup { vm.expectEmit(); emit FeeQuoter.UsdPerTokenUpdated(s_onReportTestToken2, expectedStoredToken2Price, block.timestamp); - changePrank(address(s_forwarder)); + changePrank(FORWARDER_1); s_feeQuoter.onReport(encodedPermissionsMetadata, abi.encode(report)); vm.assertEq(s_feeQuoter.getTokenPrice(report[0].token).value, expectedStoredToken1Price); @@ -75,34 +66,11 @@ contract FeeQuoter_onReport is FeeQuoterSetup { vm.assertEq(s_feeQuoter.getTokenPrice(report[1].token).timestamp, report[1].timestamp); } - function test_onReport_withKeystoneForwarderContract() public { - FeeQuoter.ReceivedCCIPFeedReport[] memory priceReportRaw = new FeeQuoter.ReceivedCCIPFeedReport[](2); - priceReportRaw[0] = - FeeQuoter.ReceivedCCIPFeedReport({token: s_onReportTestToken1, price: 4e18, timestamp: uint32(block.timestamp)}); - priceReportRaw[1] = - FeeQuoter.ReceivedCCIPFeedReport({token: s_onReportTestToken2, price: 4e18, timestamp: uint32(block.timestamp)}); - - uint224 expectedStoredToken1Price = s_feeQuoter.calculateRebasedValue(18, 18, priceReportRaw[0].price); - uint224 expectedStoredToken2Price = s_feeQuoter.calculateRebasedValue(18, 20, priceReportRaw[1].price); - - vm.expectEmit(); - emit FeeQuoter.UsdPerTokenUpdated(s_onReportTestToken1, expectedStoredToken1Price, block.timestamp); - vm.expectEmit(); - emit FeeQuoter.UsdPerTokenUpdated(s_onReportTestToken2, expectedStoredToken2Price, block.timestamp); + function test_OnReport_StaleUpdate_SkipPriceUpdate_Success() public { + //Creating a correct report + bytes memory encodedPermissionsMetadata = + abi.encodePacked(keccak256(abi.encode("workflowCID")), WORKFLOW_NAME_1, WORKFLOW_OWNER_1, REPORT_NAME_1); - changePrank(address(s_forwarder)); - s_forwarder.route( - EXECUTION_ID, TRANSMITTER, address(s_feeQuoter), encodedPermissionsMetadata, abi.encode(priceReportRaw) - ); - - vm.assertEq(s_feeQuoter.getTokenPrice(priceReportRaw[0].token).value, expectedStoredToken1Price); - vm.assertEq(s_feeQuoter.getTokenPrice(priceReportRaw[0].token).timestamp, priceReportRaw[0].timestamp); - - vm.assertEq(s_feeQuoter.getTokenPrice(priceReportRaw[1].token).value, expectedStoredToken2Price); - vm.assertEq(s_feeQuoter.getTokenPrice(priceReportRaw[1].token).timestamp, priceReportRaw[1].timestamp); - } - - function test_OnReport_SkipPriceUpdateWhenStaleUpdateReceived() public { FeeQuoter.ReceivedCCIPFeedReport[] memory report = new FeeQuoter.ReceivedCCIPFeedReport[](1); report[0] = FeeQuoter.ReceivedCCIPFeedReport({token: s_onReportTestToken1, price: 4e18, timestamp: uint32(block.timestamp)}); @@ -112,7 +80,7 @@ contract FeeQuoter_onReport is FeeQuoterSetup { vm.expectEmit(); emit FeeQuoter.UsdPerTokenUpdated(s_onReportTestToken1, expectedStoredTokenPrice, block.timestamp); - changePrank(address(s_forwarder)); + changePrank(FORWARDER_1); //setting the correct price and time with the correct report s_feeQuoter.onReport(encodedPermissionsMetadata, abi.encode(report)); @@ -132,18 +100,22 @@ contract FeeQuoter_onReport is FeeQuoterSetup { assertEq(vm.getRecordedLogs().length, 0); } - function test_RevertWhen_onReportWhen_TokenNotSupported() public { + function test_onReport_TokenNotSupported_Revert() public { + bytes memory encodedPermissionsMetadata = + abi.encodePacked(keccak256(abi.encode("workflowCID")), WORKFLOW_NAME_1, WORKFLOW_OWNER_1, REPORT_NAME_1); FeeQuoter.ReceivedCCIPFeedReport[] memory report = new FeeQuoter.ReceivedCCIPFeedReport[](1); report[0] = FeeQuoter.ReceivedCCIPFeedReport({token: s_sourceTokens[1], price: 4e18, timestamp: uint32(block.timestamp)}); // Revert due to token config not being set with the isEnabled flag vm.expectRevert(abi.encodeWithSelector(FeeQuoter.TokenNotSupported.selector, s_sourceTokens[1])); - changePrank(address(s_forwarder)); + vm.startPrank(FORWARDER_1); s_feeQuoter.onReport(encodedPermissionsMetadata, abi.encode(report)); } - function test_RevertWhen_onReportWhen_InvalidForwarder() public { + function test_onReport_InvalidForwarder_Reverts() public { + bytes memory encodedPermissionsMetadata = + abi.encodePacked(keccak256(abi.encode("workflowCID")), WORKFLOW_NAME_1, WORKFLOW_OWNER_1, REPORT_NAME_1); FeeQuoter.ReceivedCCIPFeedReport[] memory report = new FeeQuoter.ReceivedCCIPFeedReport[](1); report[0] = FeeQuoter.ReceivedCCIPFeedReport({token: s_sourceTokens[0], price: 4e18, timestamp: uint32(block.timestamp)}); @@ -160,4 +132,16 @@ contract FeeQuoter_onReport is FeeQuoterSetup { changePrank(STRANGER); s_feeQuoter.onReport(encodedPermissionsMetadata, abi.encode(report)); } + + function test_onReport_UnsupportedToken_Reverts() public { + bytes memory encodedPermissionsMetadata = + abi.encodePacked(keccak256(abi.encode("workflowCID")), WORKFLOW_NAME_1, WORKFLOW_OWNER_1, REPORT_NAME_1); + FeeQuoter.ReceivedCCIPFeedReport[] memory report = new FeeQuoter.ReceivedCCIPFeedReport[](1); + report[0] = + FeeQuoter.ReceivedCCIPFeedReport({token: s_sourceTokens[1], price: 4e18, timestamp: uint32(block.timestamp)}); + + vm.expectRevert(abi.encodeWithSelector(FeeQuoter.TokenNotSupported.selector, s_sourceTokens[1])); + changePrank(FORWARDER_1); + s_feeQuoter.onReport(encodedPermissionsMetadata, abi.encode(report)); + } } diff --git a/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.parseEVMExtraArgsFromBytes.t.sol b/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.parseEVMExtraArgsFromBytes.t.sol index 874bd20cbf8..8f4e3f954ca 100644 --- a/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.parseEVMExtraArgsFromBytes.t.sol +++ b/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.parseEVMExtraArgsFromBytes.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import {FeeQuoter} from "../../FeeQuoter.sol"; import {Client} from "../../libraries/Client.sol"; @@ -13,7 +13,7 @@ contract FeeQuoter_parseEVMExtraArgsFromBytes is FeeQuoterSetup { s_destChainConfig = _generateFeeQuoterDestChainConfigArgs()[0].destChainConfig; } - function test_EVMExtraArgsV1() public view { + function test_EVMExtraArgsV1_Success() public view { Client.EVMExtraArgsV1 memory inputArgs = Client.EVMExtraArgsV1({gasLimit: GAS_LIMIT}); bytes memory inputExtraArgs = Client._argsToBytes(inputArgs); Client.EVMExtraArgsV2 memory expectedOutputArgs = @@ -25,7 +25,7 @@ contract FeeQuoter_parseEVMExtraArgsFromBytes is FeeQuoterSetup { ); } - function test_EVMExtraArgsV2() public view { + function test_EVMExtraArgsV2_Success() public view { Client.EVMExtraArgsV2 memory inputArgs = Client.EVMExtraArgsV2({gasLimit: GAS_LIMIT, allowOutOfOrderExecution: true}); bytes memory inputExtraArgs = Client._argsToBytes(inputArgs); @@ -35,7 +35,7 @@ contract FeeQuoter_parseEVMExtraArgsFromBytes is FeeQuoterSetup { ); } - function test_EVMExtraArgsDefault() public view { + function test_EVMExtraArgsDefault_Success() public view { Client.EVMExtraArgsV2 memory expectedOutputArgs = Client.EVMExtraArgsV2({gasLimit: s_destChainConfig.defaultTxGasLimit, allowOutOfOrderExecution: false}); @@ -46,7 +46,7 @@ contract FeeQuoter_parseEVMExtraArgsFromBytes is FeeQuoterSetup { // Reverts - function test_RevertWhen_EVMExtraArgsInvalidExtraArgsTag() public { + function test_EVMExtraArgsInvalidExtraArgsTag_Revert() public { Client.EVMExtraArgsV2 memory inputArgs = Client.EVMExtraArgsV2({gasLimit: GAS_LIMIT, allowOutOfOrderExecution: true}); bytes memory inputExtraArgs = Client._argsToBytes(inputArgs); @@ -57,7 +57,7 @@ contract FeeQuoter_parseEVMExtraArgsFromBytes is FeeQuoterSetup { s_feeQuoter.parseEVMExtraArgsFromBytes(inputExtraArgs, s_destChainConfig); } - function test_RevertWhen_EVMExtraArgsEnforceOutOfOrder() public { + function test_EVMExtraArgsEnforceOutOfOrder_Revert() public { Client.EVMExtraArgsV2 memory inputArgs = Client.EVMExtraArgsV2({gasLimit: GAS_LIMIT, allowOutOfOrderExecution: false}); bytes memory inputExtraArgs = Client._argsToBytes(inputArgs); @@ -67,7 +67,7 @@ contract FeeQuoter_parseEVMExtraArgsFromBytes is FeeQuoterSetup { s_feeQuoter.parseEVMExtraArgsFromBytes(inputExtraArgs, s_destChainConfig); } - function test_RevertWhen_EVMExtraArgsGasLimitTooHigh() public { + function test_EVMExtraArgsGasLimitTooHigh_Revert() public { Client.EVMExtraArgsV2 memory inputArgs = Client.EVMExtraArgsV2({gasLimit: s_destChainConfig.maxPerMsgGasLimit + 1, allowOutOfOrderExecution: true}); bytes memory inputExtraArgs = Client._argsToBytes(inputArgs); diff --git a/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.processMessageArgs.t.sol b/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.processMessageArgs.t.sol index 5041ddef667..65baa576ead 100644 --- a/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.processMessageArgs.t.sol +++ b/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.processMessageArgs.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import {FeeQuoter} from "../../FeeQuoter.sol"; import {Client} from "../../libraries/Client.sol"; @@ -15,7 +15,7 @@ contract FeeQuoter_processMessageArgs is FeeQuoterFeeSetup { super.setUp(); } - function test_processMessageArgs_WithLinkTokenAmount() public view { + function test_processMessageArgs_WithLinkTokenAmount_Success() public view { ( uint256 msgFeeJuels, /* bool isOutOfOrderExecution */ @@ -36,7 +36,7 @@ contract FeeQuoter_processMessageArgs is FeeQuoterFeeSetup { assertEq(msgFeeJuels, MAX_MSG_FEES_JUELS); } - function test_processMessageArgs_WithConvertedTokenAmount() public view { + function test_processMessageArgs_WithConvertedTokenAmount_Success() public view { address feeToken = s_sourceTokens[1]; uint256 feeTokenAmount = 10_000 gwei; uint256 expectedConvertedAmount = s_feeQuoter.convertTokenAmount(feeToken, feeTokenAmount, s_sourceTokens[0]); @@ -60,7 +60,7 @@ contract FeeQuoter_processMessageArgs is FeeQuoterFeeSetup { assertEq(msgFeeJuels, expectedConvertedAmount); } - function test_processMessageArgs_WithEmptyEVMExtraArgs() public view { + function test_processMessageArgs_WithEmptyEVMExtraArgs_Success() public view { ( /* uint256 msgFeeJuels */ , @@ -80,7 +80,7 @@ contract FeeQuoter_processMessageArgs is FeeQuoterFeeSetup { assertEq(convertedExtraArgs, Client._argsToBytes(s_feeQuoter.parseEVMExtraArgsFromBytes("", DEST_CHAIN_SELECTOR))); } - function test_processMessageArgs_WithEVMExtraArgsV1() public view { + function test_processMessageArgs_WithEVMExtraArgsV1_Success() public view { bytes memory extraArgs = Client._argsToBytes(Client.EVMExtraArgsV1({gasLimit: 1000})); ( @@ -104,7 +104,7 @@ contract FeeQuoter_processMessageArgs is FeeQuoterFeeSetup { ); } - function test_processMessageArgs_WitEVMExtraArgsV2() public view { + function test_processMessageArgs_WitEVMExtraArgsV2_Success() public view { bytes memory extraArgs = Client._argsToBytes(Client.EVMExtraArgsV2({gasLimit: 0, allowOutOfOrderExecution: true})); ( @@ -130,7 +130,7 @@ contract FeeQuoter_processMessageArgs is FeeQuoterFeeSetup { // Reverts - function test_RevertWhen_processMessageArgs_MessageFeeTooHigh() public { + function test_processMessageArgs_MessageFeeTooHigh_Revert() public { vm.expectRevert( abi.encodeWithSelector(FeeQuoter.MessageFeeTooHigh.selector, MAX_MSG_FEES_JUELS + 1, MAX_MSG_FEES_JUELS) ); @@ -145,7 +145,7 @@ contract FeeQuoter_processMessageArgs is FeeQuoterFeeSetup { ); } - function test_RevertWhen_processMessageArgs_InvalidExtraArgs() public { + function test_processMessageArgs_InvalidExtraArgs_Revert() public { vm.expectRevert(FeeQuoter.InvalidExtraArgsTag.selector); s_feeQuoter.processMessageArgs( @@ -158,7 +158,7 @@ contract FeeQuoter_processMessageArgs is FeeQuoterFeeSetup { ); } - function test_RevertWhen_processMessageArgs_MalformedEVMExtraArgs() public { + function test_processMessageArgs_MalformedEVMExtraArgs_Revert() public { // abi.decode error vm.expectRevert(); @@ -172,7 +172,7 @@ contract FeeQuoter_processMessageArgs is FeeQuoterFeeSetup { ); } - function test_processMessageArgs_WithCorrectPoolReturnData() public view { + function test_processMessageArgs_WithCorrectPoolReturnData_Success() public view { Client.EVMTokenAmount[] memory sourceTokenAmounts = new Client.EVMTokenAmount[](2); sourceTokenAmounts[0].amount = 1e18; sourceTokenAmounts[0].token = s_sourceTokens[0]; @@ -199,7 +199,7 @@ contract FeeQuoter_processMessageArgs is FeeQuoterFeeSetup { } } - function test_RevertWhen_processMessageArgs_TokenAmountArraysMismatching() public { + function test_processMessageArgs_TokenAmountArraysMismatching_Revert() public { Client.EVMTokenAmount[] memory sourceTokenAmounts = new Client.EVMTokenAmount[](2); sourceTokenAmounts[0].amount = 1e18; sourceTokenAmounts[0].token = s_sourceTokens[0]; @@ -220,7 +220,7 @@ contract FeeQuoter_processMessageArgs is FeeQuoterFeeSetup { ); } - function test_RevertWhen_applyTokensTransferFeeConfigUpdates_InvalidFeeRange() public { + function test_applyTokensTransferFeeConfigUpdates_InvalidFeeRange_Revert() public { address sourceETH = s_sourceTokens[1]; // Set token config to allow larger data @@ -243,7 +243,7 @@ contract FeeQuoter_processMessageArgs is FeeQuoterFeeSetup { ); } - function test_RevertWhen_processMessageArgs_SourceTokenDataTooLarge() public { + function test_processMessageArgs_SourceTokenDataTooLarge_Revert() public { address sourceETH = s_sourceTokens[1]; Client.EVMTokenAmount[] memory sourceTokenAmounts = new Client.EVMTokenAmount[](1); @@ -300,7 +300,7 @@ contract FeeQuoter_processMessageArgs is FeeQuoterFeeSetup { ); } - function test_RevertWhen_processMessageArgs_InvalidEVMAddressDestToken() public { + function test_processMessageArgs_InvalidEVMAddressDestToken_Revert() public { bytes memory nonEvmAddress = abi.encode(type(uint208).max); Client.EVMTokenAmount[] memory sourceTokenAmounts = new Client.EVMTokenAmount[](1); diff --git a/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.supportsInterface.t.sol b/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.supportsInterface.t.sol deleted file mode 100644 index 35712d9bfcf..00000000000 --- a/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.supportsInterface.t.sol +++ /dev/null @@ -1,18 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; - -import {IReceiver} from "../../../keystone/interfaces/IReceiver.sol"; -import {ITypeAndVersion} from "../../../shared/interfaces/ITypeAndVersion.sol"; - -import {IERC165} from "../../../vendor/openzeppelin-solidity/v5.0.2/contracts/interfaces/IERC165.sol"; -import {IFeeQuoter} from "../../interfaces/IFeeQuoter.sol"; -import {FeeQuoterSetup} from "./FeeQuoterSetup.t.sol"; - -contract FeeQuoter_supportsInterface is FeeQuoterSetup { - function test_SupportsInterface() public view { - assertTrue(s_feeQuoter.supportsInterface(type(IReceiver).interfaceId)); - assertTrue(s_feeQuoter.supportsInterface(type(ITypeAndVersion).interfaceId)); - assertTrue(s_feeQuoter.supportsInterface(type(IFeeQuoter).interfaceId)); - assertTrue(s_feeQuoter.supportsInterface(type(IERC165).interfaceId)); - } -} diff --git a/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.updatePrices.t.sol b/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.updatePrices.t.sol index 6f463af248b..d40ac7d33ad 100644 --- a/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.updatePrices.t.sol +++ b/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.updatePrices.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import {AuthorizedCallers} from "../../../shared/access/AuthorizedCallers.sol"; import {FeeQuoter} from "../../FeeQuoter.sol"; @@ -7,7 +7,7 @@ import {Internal} from "../../libraries/Internal.sol"; import {FeeQuoterSetup} from "./FeeQuoterSetup.t.sol"; contract FeeQuoter_updatePrices is FeeQuoterSetup { - function test_OnlyTokenPrice() public { + function test_OnlyTokenPrice_Success() public { Internal.PriceUpdates memory update = Internal.PriceUpdates({ tokenPriceUpdates: new Internal.TokenPriceUpdate[](1), gasPriceUpdates: new Internal.GasPriceUpdate[](0) @@ -24,7 +24,7 @@ contract FeeQuoter_updatePrices is FeeQuoterSetup { assertEq(s_feeQuoter.getTokenPrice(s_sourceTokens[0]).value, update.tokenPriceUpdates[0].usdPerToken); } - function test_OnlyGasPrice() public { + function test_OnlyGasPrice_Success() public { Internal.PriceUpdates memory update = Internal.PriceUpdates({ tokenPriceUpdates: new Internal.TokenPriceUpdate[](0), gasPriceUpdates: new Internal.GasPriceUpdate[](1) @@ -44,7 +44,7 @@ contract FeeQuoter_updatePrices is FeeQuoterSetup { ); } - function test_UpdateMultiplePrices() public { + function test_UpdateMultiplePrices_Success() public { Internal.TokenPriceUpdate[] memory tokenPriceUpdates = new Internal.TokenPriceUpdate[](3); tokenPriceUpdates[0] = Internal.TokenPriceUpdate({sourceToken: s_sourceTokens[0], usdPerToken: 4e18}); tokenPriceUpdates[1] = Internal.TokenPriceUpdate({sourceToken: s_sourceTokens[1], usdPerToken: 1800e18}); @@ -86,7 +86,7 @@ contract FeeQuoter_updatePrices is FeeQuoterSetup { } } - function test_UpdatableByAuthorizedCaller() public { + function test_UpdatableByAuthorizedCaller_Success() public { Internal.PriceUpdates memory priceUpdates = Internal.PriceUpdates({ tokenPriceUpdates: new Internal.TokenPriceUpdate[](1), gasPriceUpdates: new Internal.GasPriceUpdate[](0) @@ -127,7 +127,7 @@ contract FeeQuoter_updatePrices is FeeQuoterSetup { // Reverts - function test_RevertWhen_OnlyCallableByUpdater() public { + function test_OnlyCallableByUpdater_Revert() public { Internal.PriceUpdates memory priceUpdates = Internal.PriceUpdates({ tokenPriceUpdates: new Internal.TokenPriceUpdate[](0), gasPriceUpdates: new Internal.GasPriceUpdate[](0) diff --git a/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.updateTokenPriceFeeds.t.sol b/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.updateTokenPriceFeeds.t.sol index 2ee95e4f513..9341fab121b 100644 --- a/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.updateTokenPriceFeeds.t.sol +++ b/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.updateTokenPriceFeeds.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import {Ownable2Step} from "../../../shared/access/Ownable2Step.sol"; import {FeeQuoter} from "../../FeeQuoter.sol"; @@ -9,7 +9,7 @@ import {FeeQuoterSetup} from "./FeeQuoterSetup.t.sol"; import {Vm} from "forge-std/Vm.sol"; contract FeeQuoter_updateTokenPriceFeeds is FeeQuoterSetup { - function test_ZeroFeeds() public { + function test_ZeroFeeds_Success() public { Vm.Log[] memory logEntries = vm.getRecordedLogs(); FeeQuoter.TokenPriceFeedUpdate[] memory tokenPriceFeedUpdates = new FeeQuoter.TokenPriceFeedUpdate[](0); @@ -20,7 +20,7 @@ contract FeeQuoter_updateTokenPriceFeeds is FeeQuoterSetup { assertEq(logEntries.length, 0); } - function test_SingleFeedUpdate() public { + function test_SingleFeedUpdate_Success() public { FeeQuoter.TokenPriceFeedUpdate[] memory tokenPriceFeedUpdates = new FeeQuoter.TokenPriceFeedUpdate[](1); tokenPriceFeedUpdates[0] = _getSingleTokenPriceFeedUpdateStruct(s_sourceTokens[0], s_dataFeedByToken[s_sourceTokens[0]], 18); @@ -37,7 +37,7 @@ contract FeeQuoter_updateTokenPriceFeeds is FeeQuoterSetup { ); } - function test_MultipleFeedUpdate() public { + function test_MultipleFeedUpdate_Success() public { FeeQuoter.TokenPriceFeedUpdate[] memory tokenPriceFeedUpdates = new FeeQuoter.TokenPriceFeedUpdate[](2); for (uint256 i = 0; i < 2; ++i) { @@ -62,7 +62,7 @@ contract FeeQuoter_updateTokenPriceFeeds is FeeQuoterSetup { ); } - function test_FeedUnset() public { + function test_FeedUnset_Success() public { Internal.TimestampedPackedUint224 memory priceQueryInitial = s_feeQuoter.getTokenPrice(s_sourceTokens[0]); assertFalse(priceQueryInitial.value == 0); assertFalse(priceQueryInitial.timestamp == 0); @@ -106,7 +106,7 @@ contract FeeQuoter_updateTokenPriceFeeds is FeeQuoterSetup { // Reverts - function test_RevertWhen_FeedUpdatedByNonOwner() public { + function test_FeedUpdatedByNonOwner_Revert() public { FeeQuoter.TokenPriceFeedUpdate[] memory tokenPriceFeedUpdates = new FeeQuoter.TokenPriceFeedUpdate[](1); tokenPriceFeedUpdates[0] = _getSingleTokenPriceFeedUpdateStruct(s_sourceTokens[0], s_dataFeedByToken[s_sourceTokens[0]], 18); diff --git a/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.validateDestFamilyAddress.t.sol b/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.validateDestFamilyAddress.t.sol index d11d8baddef..761cb7546a9 100644 --- a/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.validateDestFamilyAddress.t.sol +++ b/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.validateDestFamilyAddress.t.sol @@ -1,34 +1,34 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import {Internal} from "../../libraries/Internal.sol"; import {FeeQuoterSetup} from "./FeeQuoterSetup.t.sol"; contract FeeQuoter_validateDestFamilyAddress is FeeQuoterSetup { - function test_ValidEVMAddress() public view { + function test_ValidEVMAddress_Success() public view { bytes memory encodedAddress = abi.encode(address(10000)); s_feeQuoter.validateDestFamilyAddress(Internal.CHAIN_FAMILY_SELECTOR_EVM, encodedAddress); } - function test_ValidNonEVMAddress() public view { + function test_ValidNonEVMAddress_Success() public view { s_feeQuoter.validateDestFamilyAddress(bytes4(uint32(1)), abi.encode(type(uint208).max)); } // Reverts - function test_RevertWhen_InvalidEVMAddress() public { + function test_InvalidEVMAddress_Revert() public { bytes memory invalidAddress = abi.encode(type(uint208).max); vm.expectRevert(abi.encodeWithSelector(Internal.InvalidEVMAddress.selector, invalidAddress)); s_feeQuoter.validateDestFamilyAddress(Internal.CHAIN_FAMILY_SELECTOR_EVM, invalidAddress); } - function test_RevertWhen_InvalidEVMAddressEncodePacked() public { + function test_InvalidEVMAddressEncodePacked_Revert() public { bytes memory invalidAddress = abi.encodePacked(address(234)); vm.expectRevert(abi.encodeWithSelector(Internal.InvalidEVMAddress.selector, invalidAddress)); s_feeQuoter.validateDestFamilyAddress(Internal.CHAIN_FAMILY_SELECTOR_EVM, invalidAddress); } - function test_RevertWhen_InvalidEVMAddressPrecompiles() public { + function test_InvalidEVMAddressPrecompiles_Revert() public { for (uint160 i = 0; i < Internal.PRECOMPILE_SPACE; ++i) { bytes memory invalidAddress = abi.encode(address(i)); vm.expectRevert(abi.encodeWithSelector(Internal.InvalidEVMAddress.selector, invalidAddress)); diff --git a/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoterSetup.t.sol b/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoterSetup.t.sol index 7864d4080a2..a6551c554e6 100644 --- a/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoterSetup.t.sol +++ b/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoterSetup.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import {MockV3Aggregator} from "../../../tests/MockV3Aggregator.sol"; import {FeeQuoter} from "../../FeeQuoter.sol"; @@ -17,18 +17,6 @@ contract FeeQuoterSetup is TokenSetup { address internal constant CUSTOM_TOKEN = address(12345); address internal constant CUSTOM_TOKEN_2 = address(bytes20(keccak256("CUSTOM_TOKEN_2"))); - uint32 internal constant MAX_DATA_SIZE = 30_000; - uint16 internal constant MAX_TOKENS_LENGTH = 5; - uint32 internal constant MAX_GAS_LIMIT = 4_000_000; - - // OnRamp - uint96 internal constant MAX_MSG_FEES_JUELS = 1_000e18; - uint32 internal constant DEST_GAS_OVERHEAD = 300_000; - uint16 internal constant DEST_GAS_PER_PAYLOAD_BYTE = 16; - - uint16 internal constant DEFAULT_TOKEN_FEE_USD_CENTS = 50; - uint32 internal constant DEFAULT_TOKEN_BYTES_OVERHEAD = 32; - // Use 16 gas per data availability byte in our tests. // This is an overestimation in OP stack, it ignores 4 gas per 0 byte rule. // Arbitrum on the other hand, does always use 16 gas per data availability byte. @@ -374,7 +362,7 @@ contract FeeQuoterFeeSetup is FeeQuoterSetup { return Internal.EVM2AnyTokenTransfer({ sourcePoolAddress: tokenAdminRegistry.getTokenConfig(tokenAmount.token).tokenPool, destTokenAddress: abi.encode(destToken), - extraData: abi.encode(18), + extraData: "", amount: tokenAmount.amount, destExecData: abi.encode(expectedDestGasAmount) }); diff --git a/contracts/src/v0.8/ccip/test/helpers/BurnMintERC677Helper.sol b/contracts/src/v0.8/ccip/test/helpers/BurnMintERC677Helper.sol index 7775b777cf5..c3f95a7e067 100644 --- a/contracts/src/v0.8/ccip/test/helpers/BurnMintERC677Helper.sol +++ b/contracts/src/v0.8/ccip/test/helpers/BurnMintERC677Helper.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import {BurnMintERC677} from "../../../shared/token/ERC677/BurnMintERC677.sol"; import {IGetCCIPAdmin} from "../../interfaces/IGetCCIPAdmin.sol"; diff --git a/contracts/src/v0.8/ccip/test/helpers/BurnMintMultiTokenPool.sol b/contracts/src/v0.8/ccip/test/helpers/BurnMintMultiTokenPool.sol index 6b842ede7f2..bb1d4c9af36 100644 --- a/contracts/src/v0.8/ccip/test/helpers/BurnMintMultiTokenPool.sol +++ b/contracts/src/v0.8/ccip/test/helpers/BurnMintMultiTokenPool.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import {IBurnMintERC20} from "../../../shared/token/ERC20/IBurnMintERC20.sol"; diff --git a/contracts/src/v0.8/ccip/test/helpers/CCIPHomeHelper.sol b/contracts/src/v0.8/ccip/test/helpers/CCIPHomeHelper.sol index 3f8dc595f4d..0bc97c7aa5b 100644 --- a/contracts/src/v0.8/ccip/test/helpers/CCIPHomeHelper.sol +++ b/contracts/src/v0.8/ccip/test/helpers/CCIPHomeHelper.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import {CCIPHome} from "../../capability/CCIPHome.sol"; diff --git a/contracts/src/v0.8/ccip/test/helpers/CCIPReaderTester.sol b/contracts/src/v0.8/ccip/test/helpers/CCIPReaderTester.sol index 236797f87f0..38838f6acb2 100644 --- a/contracts/src/v0.8/ccip/test/helpers/CCIPReaderTester.sol +++ b/contracts/src/v0.8/ccip/test/helpers/CCIPReaderTester.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import {Internal} from "../../libraries/Internal.sol"; import {OffRamp} from "../../offRamp/OffRamp.sol"; @@ -10,7 +10,6 @@ contract CCIPReaderTester { mapping(uint64 sourceChainSelector => OffRamp.SourceChainConfig sourceChainConfig) internal s_sourceChainConfigs; mapping(uint64 destChainSelector => uint64 sequenceNumber) internal s_destChainSeqNrs; mapping(uint64 sourceChainSelector => mapping(bytes sender => uint64 nonce)) internal s_senderNonce; - uint64 private s_latestPriceSequenceNumber; /// @notice Gets the next sequence number to be used in the onRamp /// @param destChainSelector The destination chain selector @@ -53,19 +52,6 @@ contract CCIPReaderTester { s_sourceChainConfigs[sourceChainSelector] = sourceChainConfig; } - /// @notice sets the sequence number of the last price update. - function setLatestPriceSequenceNumber( - uint64 seqNr - ) external { - s_latestPriceSequenceNumber = seqNr; - } - - /// @notice Returns the sequence number of the last price update. - /// @return sequenceNumber The latest price update sequence number. - function getLatestPriceSequenceNumber() external view returns (uint64) { - return s_latestPriceSequenceNumber; - } - function emitCCIPMessageSent(uint64 destChainSelector, Internal.EVM2AnyRampMessage memory message) external { emit OnRamp.CCIPMessageSent(destChainSelector, message.header.sequenceNumber, message); } diff --git a/contracts/src/v0.8/ccip/test/helpers/ERC20RebasingHelper.sol b/contracts/src/v0.8/ccip/test/helpers/ERC20RebasingHelper.sol index 874a84ad127..617d39af5c4 100644 --- a/contracts/src/v0.8/ccip/test/helpers/ERC20RebasingHelper.sol +++ b/contracts/src/v0.8/ccip/test/helpers/ERC20RebasingHelper.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import {ERC20} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/ERC20.sol"; diff --git a/contracts/src/v0.8/ccip/test/helpers/EVM2EVMOffRampHelper.sol b/contracts/src/v0.8/ccip/test/helpers/EVM2EVMOffRampHelper.sol index 079cf36c4a3..9f4ca68d84a 100644 --- a/contracts/src/v0.8/ccip/test/helpers/EVM2EVMOffRampHelper.sol +++ b/contracts/src/v0.8/ccip/test/helpers/EVM2EVMOffRampHelper.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; contract EVM2EVMOffRampHelper { uint64 public s_nonce; diff --git a/contracts/src/v0.8/ccip/test/helpers/EtherSenderReceiverHelper.sol b/contracts/src/v0.8/ccip/test/helpers/EtherSenderReceiverHelper.sol index 197b262671f..e357645bcb2 100644 --- a/contracts/src/v0.8/ccip/test/helpers/EtherSenderReceiverHelper.sol +++ b/contracts/src/v0.8/ccip/test/helpers/EtherSenderReceiverHelper.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import {EtherSenderReceiver} from "../../applications/EtherSenderReceiver.sol"; import {Client} from "../../libraries/Client.sol"; diff --git a/contracts/src/v0.8/ccip/test/helpers/FeeQuoterHelper.sol b/contracts/src/v0.8/ccip/test/helpers/FeeQuoterHelper.sol index ff8f9b6c042..e392ba05589 100644 --- a/contracts/src/v0.8/ccip/test/helpers/FeeQuoterHelper.sol +++ b/contracts/src/v0.8/ccip/test/helpers/FeeQuoterHelper.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import {FeeQuoter} from "../../FeeQuoter.sol"; import {Client} from "../../libraries/Client.sol"; diff --git a/contracts/src/v0.8/ccip/test/helpers/IgnoreContractSize.sol b/contracts/src/v0.8/ccip/test/helpers/IgnoreContractSize.sol index d9fca95b696..b30124069f2 100644 --- a/contracts/src/v0.8/ccip/test/helpers/IgnoreContractSize.sol +++ b/contracts/src/v0.8/ccip/test/helpers/IgnoreContractSize.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; contract IgnoreContractSize { // test contracts are excluded from forge build --sizes by default diff --git a/contracts/src/v0.8/ccip/test/helpers/MaybeRevertingBurnMintTokenPool.sol b/contracts/src/v0.8/ccip/test/helpers/MaybeRevertingBurnMintTokenPool.sol index 058398e4c08..23e13aaa8bb 100644 --- a/contracts/src/v0.8/ccip/test/helpers/MaybeRevertingBurnMintTokenPool.sol +++ b/contracts/src/v0.8/ccip/test/helpers/MaybeRevertingBurnMintTokenPool.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import {IBurnMintERC20} from "../../../shared/token/ERC20/IBurnMintERC20.sol"; @@ -13,11 +13,10 @@ contract MaybeRevertingBurnMintTokenPool is BurnMintTokenPool { constructor( IBurnMintERC20 token, - uint8 localTokenDecimals, address[] memory allowlist, address rmnProxy, address router - ) BurnMintTokenPool(token, localTokenDecimals, allowlist, rmnProxy, router) {} + ) BurnMintTokenPool(token, allowlist, rmnProxy, router) {} function setShouldRevert( bytes calldata revertReason @@ -53,7 +52,7 @@ contract MaybeRevertingBurnMintTokenPool is BurnMintTokenPool { emit Burned(msg.sender, lockOrBurnIn.amount); return Pool.LockOrBurnOutV1({ destTokenAddress: getRemoteToken(lockOrBurnIn.remoteChainSelector), - destPoolData: s_sourceTokenData.length == 0 ? _encodeLocalDecimals() : s_sourceTokenData + destPoolData: s_sourceTokenData }); } @@ -69,11 +68,7 @@ contract MaybeRevertingBurnMintTokenPool is BurnMintTokenPool { revert(add(32, revertReason), mload(revertReason)) } } - // Calculate the local amount - uint256 localAmount = - _calculateLocalAmount(releaseOrMintIn.amount, _parseRemoteDecimals(releaseOrMintIn.sourcePoolData)); - - uint256 amount = localAmount * s_releaseOrMintMultiplier; + uint256 amount = releaseOrMintIn.amount * s_releaseOrMintMultiplier; IBurnMintERC20(address(i_token)).mint(releaseOrMintIn.receiver, amount); emit Minted(msg.sender, releaseOrMintIn.receiver, amount); diff --git a/contracts/src/v0.8/ccip/test/helpers/MerkleHelper.sol b/contracts/src/v0.8/ccip/test/helpers/MerkleHelper.sol index e6854e42187..3893d082b6a 100644 --- a/contracts/src/v0.8/ccip/test/helpers/MerkleHelper.sol +++ b/contracts/src/v0.8/ccip/test/helpers/MerkleHelper.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import {MerkleMultiProof} from "../../libraries/MerkleMultiProof.sol"; diff --git a/contracts/src/v0.8/ccip/test/helpers/MessageInterceptorHelper.sol b/contracts/src/v0.8/ccip/test/helpers/MessageInterceptorHelper.sol index 049e1fdb676..80cdf61602b 100644 --- a/contracts/src/v0.8/ccip/test/helpers/MessageInterceptorHelper.sol +++ b/contracts/src/v0.8/ccip/test/helpers/MessageInterceptorHelper.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import {IMessageInterceptor} from "../../interfaces/IMessageInterceptor.sol"; import {Client} from "../../libraries/Client.sol"; diff --git a/contracts/src/v0.8/ccip/test/helpers/MultiAggregateRateLimiterHelper.sol b/contracts/src/v0.8/ccip/test/helpers/MultiAggregateRateLimiterHelper.sol index fc7040fbe1e..7c2e6cc8c24 100644 --- a/contracts/src/v0.8/ccip/test/helpers/MultiAggregateRateLimiterHelper.sol +++ b/contracts/src/v0.8/ccip/test/helpers/MultiAggregateRateLimiterHelper.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import {MultiAggregateRateLimiter} from "../../MultiAggregateRateLimiter.sol"; import {Client} from "../../libraries/Client.sol"; diff --git a/contracts/src/v0.8/ccip/test/helpers/MultiOCR3Helper.sol b/contracts/src/v0.8/ccip/test/helpers/MultiOCR3Helper.sol index 6fbd5295c39..e760b79935d 100644 --- a/contracts/src/v0.8/ccip/test/helpers/MultiOCR3Helper.sol +++ b/contracts/src/v0.8/ccip/test/helpers/MultiOCR3Helper.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import {MultiOCR3Base} from "../../ocr/MultiOCR3Base.sol"; @@ -7,7 +7,7 @@ contract MultiOCR3Helper is MultiOCR3Base { event AfterConfigSet(uint8 ocrPluginType); /// @dev OCR plugin type used for transmit. - /// Defined in storage since it cannot be passed as calldata due to strict transmit checks + /// Defined in storage since it cannot be passed as calldata due to strict transmit checks uint8 internal s_transmitOcrPluginType; function setTransmitOcrPluginType( @@ -18,7 +18,7 @@ contract MultiOCR3Helper is MultiOCR3Base { /// @dev transmit function with signatures function transmitWithSignatures( - bytes32[2] calldata reportContext, + bytes32[3] calldata reportContext, bytes calldata report, bytes32[] calldata rs, bytes32[] calldata ss, @@ -28,7 +28,7 @@ contract MultiOCR3Helper is MultiOCR3Base { } /// @dev transmit function with no signatures - function transmitWithoutSignatures(bytes32[2] calldata reportContext, bytes calldata report) external { + function transmitWithoutSignatures(bytes32[3] calldata reportContext, bytes calldata report) external { bytes32[] memory emptySigs = new bytes32[](0); _transmit(s_transmitOcrPluginType, reportContext, report, emptySigs, emptySigs, bytes32("")); } diff --git a/contracts/src/v0.8/ccip/test/helpers/MultiTokenPool.sol b/contracts/src/v0.8/ccip/test/helpers/MultiTokenPool.sol index 697d490b288..c8243d50bd7 100644 --- a/contracts/src/v0.8/ccip/test/helpers/MultiTokenPool.sol +++ b/contracts/src/v0.8/ccip/test/helpers/MultiTokenPool.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import {IPoolV1} from "../../interfaces/IPool.sol"; import {IRMN} from "../../interfaces/IRMN.sol"; diff --git a/contracts/src/v0.8/ccip/test/helpers/OffRampHelper.sol b/contracts/src/v0.8/ccip/test/helpers/OffRampHelper.sol index c315c2e53d4..40f7ccb5914 100644 --- a/contracts/src/v0.8/ccip/test/helpers/OffRampHelper.sol +++ b/contracts/src/v0.8/ccip/test/helpers/OffRampHelper.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import {EnumerableSet} from "../../../vendor/openzeppelin-solidity/v5.0.2/contracts/utils/structs/EnumerableSet.sol"; import {Client} from "../../libraries/Client.sol"; diff --git a/contracts/src/v0.8/ccip/test/helpers/OnRampHelper.sol b/contracts/src/v0.8/ccip/test/helpers/OnRampHelper.sol index d9f049718df..d315a58fc5d 100644 --- a/contracts/src/v0.8/ccip/test/helpers/OnRampHelper.sol +++ b/contracts/src/v0.8/ccip/test/helpers/OnRampHelper.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import {OnRamp} from "../../onRamp/OnRamp.sol"; import {IgnoreContractSize} from "./IgnoreContractSize.sol"; diff --git a/contracts/src/v0.8/ccip/test/helpers/RateLimiterHelper.sol b/contracts/src/v0.8/ccip/test/helpers/RateLimiterHelper.sol index 9cf4d467416..6cd1c18705a 100644 --- a/contracts/src/v0.8/ccip/test/helpers/RateLimiterHelper.sol +++ b/contracts/src/v0.8/ccip/test/helpers/RateLimiterHelper.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import {RateLimiter} from "../../libraries/RateLimiter.sol"; diff --git a/contracts/src/v0.8/ccip/test/helpers/ReportCodec.sol b/contracts/src/v0.8/ccip/test/helpers/ReportCodec.sol index b29cd28b1d5..41e4a95b060 100644 --- a/contracts/src/v0.8/ccip/test/helpers/ReportCodec.sol +++ b/contracts/src/v0.8/ccip/test/helpers/ReportCodec.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import {Internal} from "../../libraries/Internal.sol"; import {OffRamp} from "../../offRamp/OffRamp.sol"; diff --git a/contracts/src/v0.8/ccip/test/helpers/TokenPoolHelper.sol b/contracts/src/v0.8/ccip/test/helpers/TokenPoolHelper.sol index d6a34608136..75f6b1b85df 100644 --- a/contracts/src/v0.8/ccip/test/helpers/TokenPoolHelper.sol +++ b/contracts/src/v0.8/ccip/test/helpers/TokenPoolHelper.sol @@ -1,53 +1,31 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import {Pool} from "../../libraries/Pool.sol"; import {TokenPool} from "../../pools/TokenPool.sol"; import {IERC20} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; -import {EnumerableSet} from "../../../vendor/openzeppelin-solidity/v5.0.2/contracts/utils/structs/EnumerableSet.sol"; contract TokenPoolHelper is TokenPool { - using EnumerableSet for EnumerableSet.Bytes32Set; - constructor( IERC20 token, - uint8 localTokenDecimals, address[] memory allowlist, address rmnProxy, address router - ) TokenPool(token, localTokenDecimals, allowlist, rmnProxy, router) {} + ) TokenPool(token, allowlist, rmnProxy, router) {} function lockOrBurn( Pool.LockOrBurnInV1 calldata lockOrBurnIn - ) external override returns (Pool.LockOrBurnOutV1 memory) { - _validateLockOrBurn(lockOrBurnIn); - + ) external view override returns (Pool.LockOrBurnOutV1 memory) { return Pool.LockOrBurnOutV1({destTokenAddress: getRemoteToken(lockOrBurnIn.remoteChainSelector), destPoolData: ""}); } function releaseOrMint( Pool.ReleaseOrMintInV1 calldata releaseOrMintIn - ) external override returns (Pool.ReleaseOrMintOutV1 memory) { - _validateReleaseOrMint(releaseOrMintIn); - + ) external pure override returns (Pool.ReleaseOrMintOutV1 memory) { return Pool.ReleaseOrMintOutV1({destinationAmount: releaseOrMintIn.amount}); } - function encodeLocalDecimals() external view returns (bytes memory) { - return _encodeLocalDecimals(); - } - - function parseRemoteDecimals( - bytes memory sourcePoolData - ) external view returns (uint256) { - return _parseRemoteDecimals(sourcePoolData); - } - - function calculateLocalAmount(uint256 remoteAmount, uint8 remoteDecimals) external view returns (uint256) { - return _calculateLocalAmount(remoteAmount, remoteDecimals); - } - function onlyOnRampModifier( uint64 remoteChainSelector ) external view { diff --git a/contracts/src/v0.8/ccip/test/helpers/USDCReaderTester.sol b/contracts/src/v0.8/ccip/test/helpers/USDCReaderTester.sol index f958f1fbf8b..d1baa22de1b 100644 --- a/contracts/src/v0.8/ccip/test/helpers/USDCReaderTester.sol +++ b/contracts/src/v0.8/ccip/test/helpers/USDCReaderTester.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; contract USDCReaderTester { event MessageSent(bytes); diff --git a/contracts/src/v0.8/ccip/test/helpers/USDCTokenPoolHelper.sol b/contracts/src/v0.8/ccip/test/helpers/USDCTokenPoolHelper.sol index 0996fb5bd7b..7a3400588a8 100644 --- a/contracts/src/v0.8/ccip/test/helpers/USDCTokenPoolHelper.sol +++ b/contracts/src/v0.8/ccip/test/helpers/USDCTokenPoolHelper.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import {IBurnMintERC20} from "../../../shared/token/ERC20/IBurnMintERC20.sol"; diff --git a/contracts/src/v0.8/ccip/test/helpers/receivers/ConformingReceiver.sol b/contracts/src/v0.8/ccip/test/helpers/receivers/ConformingReceiver.sol index 3fee88c6b5e..d4102da0752 100644 --- a/contracts/src/v0.8/ccip/test/helpers/receivers/ConformingReceiver.sol +++ b/contracts/src/v0.8/ccip/test/helpers/receivers/ConformingReceiver.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import {CCIPReceiver} from "../../../applications/CCIPReceiver.sol"; import {Client} from "../../../libraries/Client.sol"; diff --git a/contracts/src/v0.8/ccip/test/helpers/receivers/MaybeRevertMessageReceiver.sol b/contracts/src/v0.8/ccip/test/helpers/receivers/MaybeRevertMessageReceiver.sol index 91a697ac318..b40b2c34431 100644 --- a/contracts/src/v0.8/ccip/test/helpers/receivers/MaybeRevertMessageReceiver.sol +++ b/contracts/src/v0.8/ccip/test/helpers/receivers/MaybeRevertMessageReceiver.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import {IAny2EVMMessageReceiver} from "../../../interfaces/IAny2EVMMessageReceiver.sol"; import {Client} from "../../../libraries/Client.sol"; diff --git a/contracts/src/v0.8/ccip/test/helpers/receivers/MaybeRevertMessageReceiverNo165.sol b/contracts/src/v0.8/ccip/test/helpers/receivers/MaybeRevertMessageReceiverNo165.sol index 9f5030666af..07e5ac8544f 100644 --- a/contracts/src/v0.8/ccip/test/helpers/receivers/MaybeRevertMessageReceiverNo165.sol +++ b/contracts/src/v0.8/ccip/test/helpers/receivers/MaybeRevertMessageReceiverNo165.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import {IAny2EVMMessageReceiver} from "../../../interfaces/IAny2EVMMessageReceiver.sol"; diff --git a/contracts/src/v0.8/ccip/test/helpers/receivers/ReentrancyAbuser.sol b/contracts/src/v0.8/ccip/test/helpers/receivers/ReentrancyAbuser.sol index 64f14632c26..b8aeeb027ae 100644 --- a/contracts/src/v0.8/ccip/test/helpers/receivers/ReentrancyAbuser.sol +++ b/contracts/src/v0.8/ccip/test/helpers/receivers/ReentrancyAbuser.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import {CCIPReceiver} from "../../../applications/CCIPReceiver.sol"; import {Client} from "../../../libraries/Client.sol"; diff --git a/contracts/src/v0.8/ccip/test/libraries/ERC165CheckerReverting.supportsInterfaceReverting.t.sol b/contracts/src/v0.8/ccip/test/libraries/ERC165CheckerReverting.supportsInterfaceReverting.t.sol deleted file mode 100644 index 9a63e37ef86..00000000000 --- a/contracts/src/v0.8/ccip/test/libraries/ERC165CheckerReverting.supportsInterfaceReverting.t.sol +++ /dev/null @@ -1,44 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; - -import {IAny2EVMMessageReceiver} from "../../interfaces/IAny2EVMMessageReceiver.sol"; - -import {ERC165CheckerReverting} from "../../libraries/ERC165CheckerReverting.sol"; -import {MaybeRevertMessageReceiver} from "../helpers/receivers/MaybeRevertMessageReceiver.sol"; - -import {Test} from "forge-std/Test.sol"; - -contract ERC165CheckerReverting_supportsInterfaceReverting is Test { - using ERC165CheckerReverting for address; - - address internal s_receiver; - - bytes4 internal constant EXAMPLE_INTERFACE_ID = 0xdeadbeef; - - error InsufficientGasForStaticCall(); - - constructor() { - s_receiver = address(new MaybeRevertMessageReceiver(false)); - } - - function test__supportsInterfaceReverting() public view { - assertTrue(s_receiver._supportsInterfaceReverting(type(IAny2EVMMessageReceiver).interfaceId)); - } - - // Reverts - - function test__supportsInterfaceReverting_RevertWhen_NotEnoughGasForSupportsInterface() public { - vm.expectRevert(InsufficientGasForStaticCall.selector); - - // Library calls cannot be called with gas limit overrides, so a public function must be exposed - // instead which can proxy the call to the library. - - // The gas limit was chosen so that after overhead, <31k would remain to trigger the error. - this.invokeERC165Checker{gas: 33_000}(); - } - - // Meant to test the call with a manual gas limit override - function invokeERC165Checker() external view { - s_receiver._supportsInterfaceReverting(EXAMPLE_INTERFACE_ID); - } -} diff --git a/contracts/src/v0.8/ccip/test/libraries/MerkleMultiProof.t.sol b/contracts/src/v0.8/ccip/test/libraries/MerkleMultiProof.t.sol index 6a287ce7369..4f03f3e6f55 100644 --- a/contracts/src/v0.8/ccip/test/libraries/MerkleMultiProof.t.sol +++ b/contracts/src/v0.8/ccip/test/libraries/MerkleMultiProof.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import {MerkleMultiProof} from "../../libraries/MerkleMultiProof.sol"; import {MerkleHelper} from "../helpers/MerkleHelper.sol"; @@ -160,14 +160,14 @@ contract MerkleMultiProofTest is Test { assertEq(MerkleMultiProof._merkleRoot(leaves, proofs, 7), finalResult); } - function test_MerkleRootSingleLeaf() public pure { + function test_MerkleRootSingleLeaf_Success() public pure { bytes32[] memory leaves = new bytes32[](1); leaves[0] = "root"; bytes32[] memory proofs = new bytes32[](0); assertEq(MerkleMultiProof._merkleRoot(leaves, proofs, 0), leaves[0]); } - function test_RevertWhen_EmptyLeaf() public { + function test_EmptyLeaf_Revert() public { bytes32[] memory leaves = new bytes32[](0); bytes32[] memory proofs = new bytes32[](0); diff --git a/contracts/src/v0.8/ccip/test/libraries/RateLimiter.t.sol b/contracts/src/v0.8/ccip/test/libraries/RateLimiter.t.sol index 24ffaa72b26..da6a6f9ada7 100644 --- a/contracts/src/v0.8/ccip/test/libraries/RateLimiter.t.sol +++ b/contracts/src/v0.8/ccip/test/libraries/RateLimiter.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import {RateLimiter} from "../../libraries/RateLimiter.sol"; import {RateLimiterHelper} from "../helpers/RateLimiterHelper.sol"; @@ -18,7 +18,7 @@ contract RateLimiterSetup is Test { } contract RateLimiter_constructor is RateLimiterSetup { - function test_Constructor() public view { + function test_Constructor_Success() public view { RateLimiter.TokenBucket memory rateLimiter = s_helper.getRateLimiter(); assertEq(s_config.rate, rateLimiter.rate); assertEq(s_config.capacity, rateLimiter.capacity); @@ -29,7 +29,7 @@ contract RateLimiter_constructor is RateLimiterSetup { } contract RateLimiter_setTokenBucketConfig is RateLimiterSetup { - function test_SetRateLimiterConfig() public { + function test_SetRateLimiterConfig_Success() public { RateLimiter.TokenBucket memory rateLimiter = s_helper.getRateLimiter(); assertEq(s_config.rate, rateLimiter.rate); assertEq(s_config.capacity, rateLimiter.capacity); @@ -52,7 +52,7 @@ contract RateLimiter_setTokenBucketConfig is RateLimiterSetup { } contract RateLimiter_currentTokenBucketState is RateLimiterSetup { - function test_CurrentTokenBucketState() public { + function test_CurrentTokenBucketState_Success() public { RateLimiter.TokenBucket memory bucket = s_helper.currentTokenBucketState(); assertEq(s_config.rate, bucket.rate); assertEq(s_config.capacity, bucket.capacity); @@ -72,7 +72,7 @@ contract RateLimiter_currentTokenBucketState is RateLimiterSetup { assertEq(BLOCK_TIME, bucket.lastUpdated); } - function test_Refill() public { + function test_Refill_Success() public { RateLimiter.TokenBucket memory bucket = s_helper.currentTokenBucketState(); assertEq(s_config.rate, bucket.rate); assertEq(s_config.capacity, bucket.capacity); @@ -109,7 +109,7 @@ contract RateLimiter_currentTokenBucketState is RateLimiterSetup { contract RateLimiter_consume is RateLimiterSetup { address internal s_token = address(100); - function test_ConsumeAggregateValue() public { + function test_ConsumeAggregateValue_Success() public { RateLimiter.TokenBucket memory rateLimiter = s_helper.getRateLimiter(); assertEq(s_config.rate, rateLimiter.rate); assertEq(s_config.capacity, rateLimiter.capacity); @@ -132,7 +132,7 @@ contract RateLimiter_consume is RateLimiterSetup { assertEq(BLOCK_TIME, rateLimiter.lastUpdated); } - function test_ConsumeTokens() public { + function test_ConsumeTokens_Success() public { uint256 requestTokens = 50; vm.expectEmit(); @@ -141,7 +141,7 @@ contract RateLimiter_consume is RateLimiterSetup { s_helper.consume(requestTokens, s_token); } - function test_Refill() public { + function test_Refill_Success() public { uint256 requestTokens = 50; vm.expectEmit(); @@ -172,7 +172,7 @@ contract RateLimiter_consume is RateLimiterSetup { assertEq(BLOCK_TIME + warpTime, rateLimiter.lastUpdated); } - function test_ConsumeUnlimited() public { + function test_ConsumeUnlimited_Success() public { s_helper.consume(0, address(0)); RateLimiter.TokenBucket memory rateLimiter = s_helper.getRateLimiter(); @@ -204,7 +204,7 @@ contract RateLimiter_consume is RateLimiterSetup { // Reverts - function test_RevertWhen_AggregateValueMaxCapacityExceeded() public { + function test_AggregateValueMaxCapacityExceeded_Revert() public { RateLimiter.TokenBucket memory rateLimiter = s_helper.getRateLimiter(); vm.expectRevert( @@ -215,7 +215,7 @@ contract RateLimiter_consume is RateLimiterSetup { s_helper.consume(rateLimiter.capacity + 1, address(0)); } - function test_RevertWhen_TokenMaxCapacityExceeded() public { + function test_TokenMaxCapacityExceeded_Revert() public { RateLimiter.TokenBucket memory rateLimiter = s_helper.getRateLimiter(); vm.expectRevert( @@ -226,7 +226,7 @@ contract RateLimiter_consume is RateLimiterSetup { s_helper.consume(rateLimiter.capacity + 1, s_token); } - function test_RevertWhen_ConsumingMoreThanUint128() public { + function test_ConsumingMoreThanUint128_Revert() public { RateLimiter.TokenBucket memory rateLimiter = s_helper.getRateLimiter(); uint256 request = uint256(type(uint128).max) + 1; @@ -237,7 +237,7 @@ contract RateLimiter_consume is RateLimiterSetup { s_helper.consume(request, address(0)); } - function test_RevertWhen_AggregateValueRateLimitReached() public { + function test_AggregateValueRateLimitReached_Revert() public { RateLimiter.TokenBucket memory rateLimiter = s_helper.getRateLimiter(); uint256 overLimit = 20; @@ -256,7 +256,7 @@ contract RateLimiter_consume is RateLimiterSetup { s_helper.consume(requestTokens2, address(0)); } - function test_RevertWhen_TokenRateLimitReached() public { + function test_TokenRateLimitReached_Revert() public { RateLimiter.TokenBucket memory rateLimiter = s_helper.getRateLimiter(); uint256 overLimit = 20; @@ -275,7 +275,7 @@ contract RateLimiter_consume is RateLimiterSetup { s_helper.consume(requestTokens2, s_token); } - function test_RevertWhen_RateLimitReachedOverConsecutiveBlocks() public { + function test_RateLimitReachedOverConsecutiveBlocks_Revert() public { uint256 initBlockTime = BLOCK_TIME + 10000; vm.warp(initBlockTime); diff --git a/contracts/src/v0.8/ccip/test/mocks/MockE2EUSDCTokenMessenger.sol b/contracts/src/v0.8/ccip/test/mocks/MockE2EUSDCTokenMessenger.sol index dc814a3578e..c142cb89477 100644 --- a/contracts/src/v0.8/ccip/test/mocks/MockE2EUSDCTokenMessenger.sol +++ b/contracts/src/v0.8/ccip/test/mocks/MockE2EUSDCTokenMessenger.sol @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import {IBurnMintERC20} from "../../../shared/token/ERC20/IBurnMintERC20.sol"; import {ITokenMessenger} from "../../pools/USDC/ITokenMessenger.sol"; diff --git a/contracts/src/v0.8/ccip/test/mocks/MockE2EUSDCTransmitter.sol b/contracts/src/v0.8/ccip/test/mocks/MockE2EUSDCTransmitter.sol index 880bd146c90..4ed47b5607e 100644 --- a/contracts/src/v0.8/ccip/test/mocks/MockE2EUSDCTransmitter.sol +++ b/contracts/src/v0.8/ccip/test/mocks/MockE2EUSDCTransmitter.sol @@ -17,7 +17,7 @@ pragma solidity ^0.8.0; import {IMessageTransmitterWithRelay} from "./interfaces/IMessageTransmitterWithRelay.sol"; -import {BurnMintERC20} from "../../../shared/token/ERC20/BurnMintERC20.sol"; +import {BurnMintERC677} from "../../../shared/token/ERC677/BurnMintERC677.sol"; // solhint-disable contract MockE2EUSDCTransmitter is IMessageTransmitterWithRelay { @@ -28,7 +28,7 @@ contract MockE2EUSDCTransmitter is IMessageTransmitterWithRelay { // Next available nonce from this source domain uint64 public nextAvailableNonce; - BurnMintERC20 internal immutable i_token; + BurnMintERC677 internal immutable i_token; /** * @notice Emitted when a new message is dispatched @@ -41,7 +41,7 @@ contract MockE2EUSDCTransmitter is IMessageTransmitterWithRelay { i_localDomain = _localDomain; s_shouldSucceed = true; - i_token = BurnMintERC20(token); + i_token = BurnMintERC677(token); } /// @param message The original message on the source chain diff --git a/contracts/src/v0.8/ccip/test/mocks/MockRMN.sol b/contracts/src/v0.8/ccip/test/mocks/MockRMN.sol new file mode 100644 index 00000000000..435c6697632 --- /dev/null +++ b/contracts/src/v0.8/ccip/test/mocks/MockRMN.sol @@ -0,0 +1,61 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.24; + +import {IRMN} from "../../interfaces/IRMN.sol"; + +/// @notice WARNING: This contract is to be only used for testing, all methods are unprotected. +contract MockRMN is IRMN { + error CustomError(bytes err); + + bytes private s_isCursedRevert; + + bool private s_globalCursed; + mapping(bytes16 subject => bool cursed) private s_cursedBySubject; + mapping(address commitStore => mapping(bytes32 root => bool blessed)) private s_blessedByRoot; + + function setTaggedRootBlessed(IRMN.TaggedRoot calldata taggedRoot, bool blessed) external { + s_blessedByRoot[taggedRoot.commitStore][taggedRoot.root] = blessed; + } + + function setGlobalCursed( + bool cursed + ) external { + s_globalCursed = cursed; + } + + function setChainCursed(uint64 chainSelector, bool cursed) external { + s_cursedBySubject[bytes16(uint128(chainSelector))] = cursed; + } + + /// @notice Setting a revert error with length of 0 will disable reverts + /// @dev Useful to test revert handling of ARMProxy + function setIsCursedRevert( + bytes calldata revertErr + ) external { + s_isCursedRevert = revertErr; + } + + // IRMN implementation follows + + function isCursed() external view returns (bool) { + if (s_isCursedRevert.length > 0) { + revert CustomError(s_isCursedRevert); + } + return s_globalCursed; + } + + function isCursed( + bytes16 subject + ) external view returns (bool) { + if (s_isCursedRevert.length > 0) { + revert CustomError(s_isCursedRevert); + } + return s_globalCursed || s_cursedBySubject[subject]; + } + + function isBlessed( + IRMN.TaggedRoot calldata taggedRoot + ) external view returns (bool) { + return s_blessedByRoot[taggedRoot.commitStore][taggedRoot.root]; + } +} diff --git a/contracts/src/v0.8/ccip/test/mocks/MockRouter.sol b/contracts/src/v0.8/ccip/test/mocks/MockRouter.sol index 3ded9fd78f0..0abe4fdb7e5 100644 --- a/contracts/src/v0.8/ccip/test/mocks/MockRouter.sol +++ b/contracts/src/v0.8/ccip/test/mocks/MockRouter.sol @@ -121,19 +121,12 @@ contract MockCCIPRouter is IRouter, IRouterClient { function _fromBytes( bytes calldata extraArgs - ) internal pure returns (Client.EVMExtraArgsV2 memory) { + ) internal pure returns (Client.EVMExtraArgsV1 memory) { if (extraArgs.length == 0) { - return Client.EVMExtraArgsV2({gasLimit: DEFAULT_GAS_LIMIT, allowOutOfOrderExecution: false}); + return Client.EVMExtraArgsV1({gasLimit: DEFAULT_GAS_LIMIT}); } - - bytes4 extraArgsTag = bytes4(extraArgs); - if (extraArgsTag == Client.EVM_EXTRA_ARGS_V2_TAG) { - return abi.decode(extraArgs[4:], (Client.EVMExtraArgsV2)); - } else if (extraArgsTag == Client.EVM_EXTRA_ARGS_V1_TAG) { - return Client.EVMExtraArgsV2({gasLimit: abi.decode(extraArgs[4:], (uint256)), allowOutOfOrderExecution: false}); - } - - revert InvalidExtraArgsTag(); + if (bytes4(extraArgs) != Client.EVM_EXTRA_ARGS_V1_TAG) revert InvalidExtraArgsTag(); + return abi.decode(extraArgs[4:], (Client.EVMExtraArgsV1)); } /// @notice Always returns true to make sure this check can be performed on any chain. diff --git a/contracts/src/v0.8/ccip/test/mocks/MockUSDCTokenMessenger.sol b/contracts/src/v0.8/ccip/test/mocks/MockUSDCTokenMessenger.sol index f198835c236..562a9f467ff 100644 --- a/contracts/src/v0.8/ccip/test/mocks/MockUSDCTokenMessenger.sol +++ b/contracts/src/v0.8/ccip/test/mocks/MockUSDCTokenMessenger.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import {IBurnMintERC20} from "../../../shared/token/ERC20/IBurnMintERC20.sol"; import {ITokenMessenger} from "../../pools/USDC/ITokenMessenger.sol"; diff --git a/contracts/src/v0.8/ccip/test/mocks/test/MockRouterTest.t.sol b/contracts/src/v0.8/ccip/test/mocks/test/MockRouterTest.t.sol index 11371d71f95..cd0aabf1776 100644 --- a/contracts/src/v0.8/ccip/test/mocks/test/MockRouterTest.t.sol +++ b/contracts/src/v0.8/ccip/test/mocks/test/MockRouterTest.t.sol @@ -1,6 +1,7 @@ pragma solidity ^0.8.0; import {Client} from "../../../libraries/Client.sol"; + import {TokenSetup} from "../../TokenSetup.t.sol"; import {IRouterClient, MockCCIPRouter} from "../MockRouter.sol"; @@ -30,32 +31,32 @@ contract MockRouterTest is TokenSetup { s_sourceFeeToken = _deploySourceToken("sLINK", type(uint256).max, 18); } - function test_RevertWhen_ccipSendWithInsufficientNativeTokens() public { + function test_ccipSendWithInsufficientNativeTokens_Revert() public { //Should revert because did not include sufficient eth to pay for fees vm.expectRevert(IRouterClient.InsufficientFeeTokenAmount.selector); mockRouter.ccipSend(MOCK_CHAIN_SELECTOR, message); } - function test_ccipSendWithSufficientNativeFeeTokens() public { + function test_ccipSendWithSufficientNativeFeeTokens_Success() public { //ccipSend with sufficient native tokens for fees mockRouter.ccipSend{value: 0.1 ether}(MOCK_CHAIN_SELECTOR, message); } - function test_RevertWhen_ccipSendWithInvalidMsgValue() public { + function test_ccipSendWithInvalidMsgValue_Revert() public { message.feeToken = address(1); //Set to non native-token fees vm.expectRevert(IRouterClient.InvalidMsgValue.selector); mockRouter.ccipSend{value: 0.1 ether}(MOCK_CHAIN_SELECTOR, message); } - function test_RevertWhen_ccipSendWithLinkFeeTokenbutInsufficientAllowance() public { + function test_ccipSendWithLinkFeeTokenbutInsufficientAllowance_Revert() public { message.feeToken = s_sourceFeeToken; vm.expectRevert(bytes("ERC20: insufficient allowance")); mockRouter.ccipSend(MOCK_CHAIN_SELECTOR, message); } - function test_ccipSendWithLinkFeeTokenAndValidMsgValue() public { + function test_ccipSendWithLinkFeeTokenAndValidMsgValue_Success() public { message.feeToken = s_sourceFeeToken; vm.startPrank(OWNER, OWNER); @@ -64,24 +65,4 @@ contract MockRouterTest is TokenSetup { mockRouter.ccipSend(MOCK_CHAIN_SELECTOR, message); } - - function test_ccipSendWithEVMExtraArgsV1() public { - Client.EVMExtraArgsV1 memory extraArgs = Client.EVMExtraArgsV1({gasLimit: 500_000}); - message.extraArgs = Client._argsToBytes(extraArgs); - mockRouter.ccipSend{value: 0.1 ether}(MOCK_CHAIN_SELECTOR, message); - } - - function test_ccipSendWithEVMExtraArgsV2() public { - Client.EVMExtraArgsV2 memory extraArgs = Client.EVMExtraArgsV2({gasLimit: 500_000, allowOutOfOrderExecution: true}); - message.extraArgs = Client._argsToBytes(extraArgs); - mockRouter.ccipSend{value: 0.1 ether}(MOCK_CHAIN_SELECTOR, message); - } - - function test_RevertWhen_ccipSendWithInvalidEVMExtraArgs() public { - uint256 gasLimit = 500_000; - bytes4 invalidExtraArgsTag = bytes4(keccak256("CCIP EVMExtraArgsInvalid")); - message.extraArgs = abi.encodeWithSelector(invalidExtraArgsTag, gasLimit); - vm.expectRevert(MockCCIPRouter.InvalidExtraArgsTag.selector); - mockRouter.ccipSend{value: 0.1 ether}(MOCK_CHAIN_SELECTOR, message); - } } diff --git a/contracts/src/v0.8/ccip/test/ocr/MultiOCR3Base/MultiOCR3Base.setOCR3Configs.t.sol b/contracts/src/v0.8/ccip/test/ocr/MultiOCR3Base/MultiOCR3Base.setOCR3Configs.t.sol index 36593790409..c70a8666654 100644 --- a/contracts/src/v0.8/ccip/test/ocr/MultiOCR3Base/MultiOCR3Base.setOCR3Configs.t.sol +++ b/contracts/src/v0.8/ccip/test/ocr/MultiOCR3Base/MultiOCR3Base.setOCR3Configs.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import {MultiOCR3Base} from "../../../ocr/MultiOCR3Base.sol"; import {MultiOCR3Helper} from "../../helpers/MultiOCR3Helper.sol"; @@ -8,7 +8,7 @@ import {MultiOCR3BaseSetup} from "./MultiOCR3BaseSetup.t.sol"; import {Vm} from "forge-std/Vm.sol"; contract MultiOCR3Base_setOCR3Configs is MultiOCR3BaseSetup { - function test_SetConfigsZeroInput() public { + function test_SetConfigsZeroInput_Success() public { vm.recordLogs(); s_multiOCR3.setOCR3Configs(new MultiOCR3Base.OCRConfigArgs[](0)); @@ -17,7 +17,7 @@ contract MultiOCR3Base_setOCR3Configs is MultiOCR3BaseSetup { assertEq(logEntries.length, 0); } - function test_SetConfigWithSigners() public { + function test_SetConfigWithSigners_Success() public { uint8 F = 2; _assertOCRConfigUnconfigured(s_multiOCR3.latestConfigDetails(0)); @@ -59,7 +59,7 @@ contract MultiOCR3Base_setOCR3Configs is MultiOCR3BaseSetup { _assertOCRConfigEquality(s_multiOCR3.latestConfigDetails(0), expectedConfig); } - function test_SetConfigWithSignersMismatchingTransmitters() public { + function test_SetConfigWithSignersMismatchingTransmitters_Success() public { uint8 F = 2; _assertOCRConfigUnconfigured(s_multiOCR3.latestConfigDetails(0)); @@ -101,7 +101,7 @@ contract MultiOCR3Base_setOCR3Configs is MultiOCR3BaseSetup { _assertOCRConfigEquality(s_multiOCR3.latestConfigDetails(0), expectedConfig); } - function test_SetConfigWithoutSigners() public { + function test_SetConfigWithoutSigners_Success() public { uint8 F = 1; address[] memory signers = new address[](0); @@ -144,7 +144,7 @@ contract MultiOCR3Base_setOCR3Configs is MultiOCR3BaseSetup { _assertOCRConfigEquality(s_multiOCR3.latestConfigDetails(0), expectedConfig); } - function test_SetConfigIgnoreSigners() public { + function test_SetConfigIgnoreSigners_Success() public { uint8 F = 1; _assertOCRConfigUnconfigured(s_multiOCR3.latestConfigDetails(0)); @@ -192,7 +192,7 @@ contract MultiOCR3Base_setOCR3Configs is MultiOCR3BaseSetup { } } - function test_SetMultipleConfigs() public { + function test_SetMultipleConfigs_Success() public { _assertOCRConfigUnconfigured(s_multiOCR3.latestConfigDetails(0)); _assertOCRConfigUnconfigured(s_multiOCR3.latestConfigDetails(1)); _assertOCRConfigUnconfigured(s_multiOCR3.latestConfigDetails(2)); @@ -321,7 +321,7 @@ contract MultiOCR3Base_setOCR3Configs is MultiOCR3BaseSetup { _assertOCRConfigEquality(s_multiOCR3.latestConfigDetails(ocrConfig.ocrPluginType), expectedConfig); } - function test_UpdateConfigTransmittersWithoutSigners() public { + function test_UpdateConfigTransmittersWithoutSigners_Success() public { _assertOCRConfigUnconfigured(s_multiOCR3.latestConfigDetails(0)); MultiOCR3Base.OCRConfigArgs[] memory ocrConfigs = new MultiOCR3Base.OCRConfigArgs[](1); @@ -380,7 +380,7 @@ contract MultiOCR3Base_setOCR3Configs is MultiOCR3BaseSetup { } } - function test_UpdateConfigSigners() public { + function test_UpdateConfigSigners_Success() public { _assertOCRConfigUnconfigured(s_multiOCR3.latestConfigDetails(0)); MultiOCR3Base.OCRConfigArgs[] memory ocrConfigs = new MultiOCR3Base.OCRConfigArgs[](1); @@ -450,7 +450,7 @@ contract MultiOCR3Base_setOCR3Configs is MultiOCR3BaseSetup { // Reverts - function test_RevertWhen_RepeatTransmitterAddress() public { + function test_RepeatTransmitterAddress_Revert() public { address[] memory signers = s_validSigners; address[] memory transmitters = s_validTransmitters; transmitters[0] = signers[0]; @@ -473,7 +473,7 @@ contract MultiOCR3Base_setOCR3Configs is MultiOCR3BaseSetup { s_multiOCR3.setOCR3Configs(ocrConfigs); } - function test_RevertWhen_RepeatSignerAddress() public { + function test_RepeatSignerAddress_Revert() public { address[] memory signers = s_validSigners; address[] memory transmitters = s_validTransmitters; signers[1] = signers[0]; @@ -496,7 +496,7 @@ contract MultiOCR3Base_setOCR3Configs is MultiOCR3BaseSetup { s_multiOCR3.setOCR3Configs(ocrConfigs); } - function test_RevertWhen_SignerCannotBeZeroAddress() public { + function test_SignerCannotBeZeroAddress_Revert() public { uint8 F = 1; address[] memory signers = new address[](3 * F + 1); address[] memory transmitters = new address[](3 * F + 1); @@ -521,7 +521,7 @@ contract MultiOCR3Base_setOCR3Configs is MultiOCR3BaseSetup { s_multiOCR3.setOCR3Configs(ocrConfigs); } - function test_RevertWhen_TransmitterCannotBeZeroAddress() public { + function test_TransmitterCannotBeZeroAddress_Revert() public { uint8 F = 1; address[] memory signers = new address[](3 * F + 1); address[] memory transmitters = new address[](3 * F + 1); @@ -546,7 +546,7 @@ contract MultiOCR3Base_setOCR3Configs is MultiOCR3BaseSetup { s_multiOCR3.setOCR3Configs(ocrConfigs); } - function test_RevertWhen_StaticConfigChange() public { + function test_StaticConfigChange_Revert() public { uint8 F = 1; _assertOCRConfigUnconfigured(s_multiOCR3.latestConfigDetails(0)); @@ -569,7 +569,7 @@ contract MultiOCR3Base_setOCR3Configs is MultiOCR3BaseSetup { s_multiOCR3.setOCR3Configs(ocrConfigs); } - function test_RevertWhen_FTooHigh() public { + function test_FTooHigh_Revert() public { address[] memory signers = new address[](0); address[] memory transmitters = new address[](1); @@ -589,7 +589,7 @@ contract MultiOCR3Base_setOCR3Configs is MultiOCR3BaseSetup { s_multiOCR3.setOCR3Configs(ocrConfigs); } - function test_RevertWhen_FMustBePositive() public { + function test_FMustBePositive_Revert() public { MultiOCR3Base.OCRConfigArgs[] memory ocrConfigs = new MultiOCR3Base.OCRConfigArgs[](1); ocrConfigs[0] = MultiOCR3Base.OCRConfigArgs({ ocrPluginType: 0, @@ -608,7 +608,7 @@ contract MultiOCR3Base_setOCR3Configs is MultiOCR3BaseSetup { s_multiOCR3.setOCR3Configs(ocrConfigs); } - function test_RevertWhen_NoTransmitters() public { + function test_NoTransmitters_Revert() public { address[] memory signers = new address[](0); address[] memory transmitters = new address[](0); @@ -628,7 +628,7 @@ contract MultiOCR3Base_setOCR3Configs is MultiOCR3BaseSetup { s_multiOCR3.setOCR3Configs(ocrConfigs); } - function test_RevertWhen_TooManyTransmitters() public { + function test_TooManyTransmitters_Revert() public { address[] memory signers = new address[](0); address[] memory transmitters = new address[](257); @@ -650,7 +650,7 @@ contract MultiOCR3Base_setOCR3Configs is MultiOCR3BaseSetup { s_multiOCR3.setOCR3Configs(ocrConfigs); } - function test_RevertWhen_TooManySigners() public { + function test_TooManySigners_Revert() public { address[] memory signers = new address[](257); MultiOCR3Base.OCRConfigArgs[] memory ocrConfigs = new MultiOCR3Base.OCRConfigArgs[](1); @@ -671,7 +671,7 @@ contract MultiOCR3Base_setOCR3Configs is MultiOCR3BaseSetup { s_multiOCR3.setOCR3Configs(ocrConfigs); } - function test_RevertWhen_MoreTransmittersThanSigners() public { + function test_MoreTransmittersThanSigners_Revert() public { MultiOCR3Base.OCRConfigArgs[] memory ocrConfigs = new MultiOCR3Base.OCRConfigArgs[](1); ocrConfigs[0] = MultiOCR3Base.OCRConfigArgs({ ocrPluginType: 0, diff --git a/contracts/src/v0.8/ccip/test/ocr/MultiOCR3Base/MultiOCR3Base.transmit.t.sol b/contracts/src/v0.8/ccip/test/ocr/MultiOCR3Base/MultiOCR3Base.transmit.t.sol index ef75fdaf807..c6d948a70c2 100644 --- a/contracts/src/v0.8/ccip/test/ocr/MultiOCR3Base/MultiOCR3Base.transmit.t.sol +++ b/contracts/src/v0.8/ccip/test/ocr/MultiOCR3Base/MultiOCR3Base.transmit.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import {MultiOCR3Base} from "../../../ocr/MultiOCR3Base.sol"; import {MultiOCR3BaseSetup} from "./MultiOCR3BaseSetup.t.sol"; @@ -45,9 +45,9 @@ contract MultiOCR3Base_transmit is MultiOCR3BaseSetup { s_multiOCR3.setOCR3Configs(ocrConfigs); } - function test_TransmitSigners_gas() public { + function test_TransmitSigners_gas_Success() public { vm.pauseGasMetering(); - bytes32[2] memory reportContext = [s_configDigest1, s_configDigest1]; + bytes32[3] memory reportContext = [s_configDigest1, s_configDigest1, s_configDigest1]; // F = 2, need 2 signatures (bytes32[] memory rs, bytes32[] memory ss,, bytes32 rawVs) = @@ -63,9 +63,9 @@ contract MultiOCR3Base_transmit is MultiOCR3BaseSetup { s_multiOCR3.transmitWithSignatures(reportContext, REPORT, rs, ss, rawVs); } - function test_TransmitWithoutSignatureVerification_gas() public { + function test_TransmitWithoutSignatureVerification_gas_Success() public { vm.pauseGasMetering(); - bytes32[2] memory reportContext = [s_configDigest3, s_configDigest3]; + bytes32[3] memory reportContext = [s_configDigest3, s_configDigest3, s_configDigest3]; s_multiOCR3.setTransmitOcrPluginType(2); @@ -115,7 +115,7 @@ contract MultiOCR3Base_transmit is MultiOCR3BaseSetup { // Randomise picked transmitter with random offset vm.startPrank(transmitters[randomAddressOffset % signersLength]); - bytes32[2] memory reportContext = [s_configDigest1, s_configDigest1]; + bytes32[3] memory reportContext = [s_configDigest1, s_configDigest1, s_configDigest1]; // condition: matches signature expectation for transmit uint8 numSignatures = F + 1; @@ -137,15 +137,15 @@ contract MultiOCR3Base_transmit is MultiOCR3BaseSetup { } // Reverts - function test_RevertWhen_ForkedChain() public { - bytes32[2] memory reportContext = [s_configDigest1, s_configDigest1]; + function test_ForkedChain_Revert() public { + bytes32[3] memory reportContext = [s_configDigest1, s_configDigest1, s_configDigest1]; (bytes32[] memory rs, bytes32[] memory ss,, bytes32 rawVs) = _getSignaturesForDigest(s_validSignerKeys, REPORT, reportContext, 2); s_multiOCR3.setTransmitOcrPluginType(0); - uint256 chain1 = uint200(block.chainid); + uint256 chain1 = block.chainid; uint256 chain2 = chain1 + 1; vm.chainId(chain2); vm.expectRevert(abi.encodeWithSelector(MultiOCR3Base.ForkedChain.selector, chain1, chain2)); @@ -154,8 +154,8 @@ contract MultiOCR3Base_transmit is MultiOCR3BaseSetup { s_multiOCR3.transmitWithSignatures(reportContext, REPORT, rs, ss, rawVs); } - function test_RevertWhen_ZeroSignatures() public { - bytes32[2] memory reportContext = [s_configDigest1, s_configDigest1]; + function test_ZeroSignatures_Revert() public { + bytes32[3] memory reportContext = [s_configDigest1, s_configDigest1, s_configDigest1]; s_multiOCR3.setTransmitOcrPluginType(0); @@ -164,8 +164,8 @@ contract MultiOCR3Base_transmit is MultiOCR3BaseSetup { s_multiOCR3.transmitWithSignatures(reportContext, REPORT, new bytes32[](0), new bytes32[](0), bytes32("")); } - function test_RevertWhen_TooManySignatures() public { - bytes32[2] memory reportContext = [s_configDigest1, s_configDigest1]; + function test_TooManySignatures_Revert() public { + bytes32[3] memory reportContext = [s_configDigest1, s_configDigest1, s_configDigest1]; // 1 signature too many (bytes32[] memory rs, bytes32[] memory ss,, bytes32 rawVs) = @@ -178,8 +178,8 @@ contract MultiOCR3Base_transmit is MultiOCR3BaseSetup { s_multiOCR3.transmitWithSignatures(reportContext, REPORT, rs, ss, rawVs); } - function test_RevertWhen_InsufficientSignatures() public { - bytes32[2] memory reportContext = [s_configDigest1, s_configDigest1]; + function test_InsufficientSignatures_Revert() public { + bytes32[3] memory reportContext = [s_configDigest1, s_configDigest1, s_configDigest1]; // Missing 1 signature for unique report (bytes32[] memory rs, bytes32[] memory ss,, bytes32 rawVs) = @@ -192,9 +192,9 @@ contract MultiOCR3Base_transmit is MultiOCR3BaseSetup { s_multiOCR3.transmitWithSignatures(reportContext, REPORT, rs, ss, rawVs); } - function test_RevertWhen_ConfigDigestMismatch() public { + function test_ConfigDigestMismatch_Revert() public { bytes32 configDigest; - bytes32[2] memory reportContext = [configDigest, configDigest]; + bytes32[3] memory reportContext = [configDigest, configDigest, configDigest]; (,,, bytes32 rawVs) = _getSignaturesForDigest(s_validSignerKeys, REPORT, reportContext, 2); @@ -204,8 +204,8 @@ contract MultiOCR3Base_transmit is MultiOCR3BaseSetup { s_multiOCR3.transmitWithSignatures(reportContext, REPORT, new bytes32[](0), new bytes32[](0), rawVs); } - function test_RevertWhen_SignatureOutOfRegistration() public { - bytes32[2] memory reportContext = [s_configDigest1, s_configDigest1]; + function test_SignatureOutOfRegistration_Revert() public { + bytes32[3] memory reportContext = [s_configDigest1, s_configDigest1, s_configDigest1]; bytes32[] memory rs = new bytes32[](2); bytes32[] memory ss = new bytes32[](1); @@ -217,8 +217,8 @@ contract MultiOCR3Base_transmit is MultiOCR3BaseSetup { s_multiOCR3.transmitWithSignatures(reportContext, REPORT, rs, ss, bytes32("")); } - function test_RevertWhen_UnAuthorizedTransmitter() public { - bytes32[2] memory reportContext = [s_configDigest1, s_configDigest1]; + function test_UnAuthorizedTransmitter_Revert() public { + bytes32[3] memory reportContext = [s_configDigest1, s_configDigest1, s_configDigest1]; bytes32[] memory rs = new bytes32[](2); bytes32[] memory ss = new bytes32[](2); @@ -228,8 +228,8 @@ contract MultiOCR3Base_transmit is MultiOCR3BaseSetup { s_multiOCR3.transmitWithSignatures(reportContext, REPORT, rs, ss, bytes32("")); } - function test_RevertWhen_NonUniqueSignature() public { - bytes32[2] memory reportContext = [s_configDigest1, s_configDigest1]; + function test_NonUniqueSignature_Revert() public { + bytes32[3] memory reportContext = [s_configDigest1, s_configDigest1, s_configDigest1]; (bytes32[] memory rs, bytes32[] memory ss, uint8[] memory vs, bytes32 rawVs) = _getSignaturesForDigest(s_validSignerKeys, REPORT, reportContext, 2); @@ -246,8 +246,8 @@ contract MultiOCR3Base_transmit is MultiOCR3BaseSetup { s_multiOCR3.transmitWithSignatures(reportContext, REPORT, rs, ss, rawVs); } - function test_RevertWhen_UnauthorizedSigner() public { - bytes32[2] memory reportContext = [s_configDigest1, s_configDigest1]; + function test_UnauthorizedSigner_Revert() public { + bytes32[3] memory reportContext = [s_configDigest1, s_configDigest1, s_configDigest1]; (bytes32[] memory rs, bytes32[] memory ss,, bytes32 rawVs) = _getSignaturesForDigest(s_validSignerKeys, REPORT, reportContext, 2); @@ -262,9 +262,9 @@ contract MultiOCR3Base_transmit is MultiOCR3BaseSetup { s_multiOCR3.transmitWithSignatures(reportContext, REPORT, rs, ss, rawVs); } - function test_RevertWhen_UnconfiguredPlugin() public { + function test_UnconfiguredPlugin_Revert() public { bytes32 configDigest; - bytes32[2] memory reportContext = [configDigest, configDigest]; + bytes32[3] memory reportContext = [configDigest, configDigest, configDigest]; s_multiOCR3.setTransmitOcrPluginType(42); @@ -272,8 +272,8 @@ contract MultiOCR3Base_transmit is MultiOCR3BaseSetup { s_multiOCR3.transmitWithoutSignatures(reportContext, REPORT); } - function test_RevertWhen_TransmitWithLessCalldataArgs() public { - bytes32[2] memory reportContext = [s_configDigest1, s_configDigest1]; + function test_TransmitWithLessCalldataArgs_Revert() public { + bytes32[3] memory reportContext = [s_configDigest1, s_configDigest1, s_configDigest1]; s_multiOCR3.setTransmitOcrPluginType(0); @@ -281,7 +281,7 @@ contract MultiOCR3Base_transmit is MultiOCR3BaseSetup { vm.startPrank(s_validTransmitters[1]); // report length + function selector + report length + abiencoded location of report value + report context words - uint256 receivedLength = REPORT.length + 4 + 4 * 32; + uint256 receivedLength = REPORT.length + 4 + 5 * 32; vm.expectRevert( abi.encodeWithSelector( MultiOCR3Base.WrongMessageLength.selector, @@ -293,8 +293,8 @@ contract MultiOCR3Base_transmit is MultiOCR3BaseSetup { s_multiOCR3.transmitWithoutSignatures(reportContext, REPORT); } - function test_RevertWhen_TransmitWithExtraCalldataArgs() public { - bytes32[2] memory reportContext = [s_configDigest1, s_configDigest1]; + function test_TransmitWithExtraCalldataArgs_Revert() public { + bytes32[3] memory reportContext = [s_configDigest1, s_configDigest1, s_configDigest1]; bytes32[] memory rs = new bytes32[](2); bytes32[] memory ss = new bytes32[](2); @@ -305,7 +305,7 @@ contract MultiOCR3Base_transmit is MultiOCR3BaseSetup { // dynamic length + function selector + report length + abiencoded location of report value + report context words // rawVs value, lengths of rs, ss, and start locations of rs & ss -> 5 words - uint256 receivedLength = REPORT.length + 4 + (4 * 32) + (5 * 32) + (2 * 32) + (2 * 32); + uint256 receivedLength = REPORT.length + 4 + (5 * 32) + (5 * 32) + (2 * 32) + (2 * 32); vm.expectRevert( abi.encodeWithSelector( MultiOCR3Base.WrongMessageLength.selector, diff --git a/contracts/src/v0.8/ccip/test/ocr/MultiOCR3Base/MultiOCR3BaseSetup.t.sol b/contracts/src/v0.8/ccip/test/ocr/MultiOCR3Base/MultiOCR3BaseSetup.t.sol index d6325e27806..f949017d588 100644 --- a/contracts/src/v0.8/ccip/test/ocr/MultiOCR3Base/MultiOCR3BaseSetup.t.sol +++ b/contracts/src/v0.8/ccip/test/ocr/MultiOCR3Base/MultiOCR3BaseSetup.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import {MultiOCR3Base} from "../../../ocr/MultiOCR3Base.sol"; import {BaseTest} from "../../BaseTest.t.sol"; @@ -95,7 +95,7 @@ contract MultiOCR3BaseSetup is BaseTest { function _getSignaturesForDigest( uint256[] memory signerPrivateKeys, bytes memory report, - bytes32[2] memory reportContext, + bytes32[3] memory reportContext, uint8 signatureCount ) internal pure returns (bytes32[] memory rs, bytes32[] memory ss, uint8[] memory vs, bytes32 rawVs) { rs = new bytes32[](signatureCount); diff --git a/contracts/src/v0.8/ccip/test/offRamp/OffRamp/OffRamp.afterOC3ConfigSet.t.sol b/contracts/src/v0.8/ccip/test/offRamp/OffRamp/OffRamp.afterOC3ConfigSet.t.sol index 9d610473277..91694dbcb05 100644 --- a/contracts/src/v0.8/ccip/test/offRamp/OffRamp/OffRamp.afterOC3ConfigSet.t.sol +++ b/contracts/src/v0.8/ccip/test/offRamp/OffRamp/OffRamp.afterOC3ConfigSet.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import {Internal} from "../../../libraries/Internal.sol"; import {MultiOCR3Base} from "../../../ocr/MultiOCR3Base.sol"; @@ -8,11 +8,10 @@ import {OffRampHelper} from "../../helpers/OffRampHelper.sol"; import {OffRampSetup} from "./OffRampSetup.t.sol"; contract OffRamp_afterOC3ConfigSet is OffRampSetup { - function test_RevertWhen_afterOCR3ConfigSet_SignatureVerificationDisabled() public { + function test_afterOCR3ConfigSet_SignatureVerificationDisabled_Revert() public { s_offRamp = new OffRampHelper( OffRamp.StaticConfig({ chainSelector: DEST_CHAIN_SELECTOR, - gasForCallExactCheck: GAS_FOR_CALL_EXACT_CHECK, rmnRemote: s_mockRMNRemote, tokenAdminRegistry: address(s_tokenAdminRegistry), nonceManager: address(s_inboundNonceManager) diff --git a/contracts/src/v0.8/ccip/test/offRamp/OffRamp/OffRamp.applySourceChainConfigUpdates.t.sol b/contracts/src/v0.8/ccip/test/offRamp/OffRamp/OffRamp.applySourceChainConfigUpdates.t.sol index c2e1ddbce3f..84c522108ae 100644 --- a/contracts/src/v0.8/ccip/test/offRamp/OffRamp/OffRamp.applySourceChainConfigUpdates.t.sol +++ b/contracts/src/v0.8/ccip/test/offRamp/OffRamp/OffRamp.applySourceChainConfigUpdates.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import {IRouter} from "../../../interfaces/IRouter.sol"; @@ -10,7 +10,7 @@ import {OffRampSetup} from "./OffRampSetup.t.sol"; import {Vm} from "forge-std/Vm.sol"; contract OffRamp_applySourceChainConfigUpdates is OffRampSetup { - function test_ApplyZeroUpdates() public { + function test_ApplyZeroUpdates_Success() public { OffRamp.SourceChainConfigArgs[] memory sourceChainConfigs = new OffRamp.SourceChainConfigArgs[](0); vm.recordLogs(); @@ -23,7 +23,7 @@ contract OffRamp_applySourceChainConfigUpdates is OffRampSetup { assertEq(s_offRamp.getSourceChainSelectors().length, 0); } - function test_AddNewChain() public { + function test_AddNewChain_Success() public { OffRamp.SourceChainConfigArgs[] memory sourceChainConfigs = new OffRamp.SourceChainConfigArgs[](1); sourceChainConfigs[0] = OffRamp.SourceChainConfigArgs({ router: s_destRouter, @@ -46,7 +46,7 @@ contract OffRamp_applySourceChainConfigUpdates is OffRampSetup { _assertSourceChainConfigEquality(s_offRamp.getSourceChainConfig(SOURCE_CHAIN_SELECTOR_1), expectedSourceChainConfig); } - function test_ReplaceExistingChain() public { + function test_ReplaceExistingChain_Success() public { OffRamp.SourceChainConfigArgs[] memory sourceChainConfigs = new OffRamp.SourceChainConfigArgs[](1); sourceChainConfigs[0] = OffRamp.SourceChainConfigArgs({ router: s_destRouter, @@ -77,7 +77,7 @@ contract OffRamp_applySourceChainConfigUpdates is OffRampSetup { assertEq(resultSourceChainSelectors.length, 1); } - function test_AddMultipleChains() public { + function test_AddMultipleChains_Success() public { OffRamp.SourceChainConfigArgs[] memory sourceChainConfigs = new OffRamp.SourceChainConfigArgs[](3); sourceChainConfigs[0] = OffRamp.SourceChainConfigArgs({ router: s_destRouter, @@ -171,7 +171,7 @@ contract OffRamp_applySourceChainConfigUpdates is OffRampSetup { ); } - function test_ReplaceExistingChainOnRamp() public { + function test_ReplaceExistingChainOnRamp_Success() public { OffRamp.SourceChainConfigArgs[] memory sourceChainConfigs = new OffRamp.SourceChainConfigArgs[](1); sourceChainConfigs[0] = OffRamp.SourceChainConfigArgs({ router: s_destRouter, @@ -192,7 +192,7 @@ contract OffRamp_applySourceChainConfigUpdates is OffRampSetup { s_offRamp.applySourceChainConfigUpdates(sourceChainConfigs); } - function test_allowNonOnRampUpdateAfterLaneIsUsed() public { + function test_allowNonOnRampUpdateAfterLaneIsUsed_success() public { OffRamp.SourceChainConfigArgs[] memory sourceChainConfigs = new OffRamp.SourceChainConfigArgs[](1); sourceChainConfigs[0] = OffRamp.SourceChainConfigArgs({ router: s_destRouter, @@ -233,7 +233,7 @@ contract OffRamp_applySourceChainConfigUpdates is OffRampSetup { // Reverts - function test_RevertWhen_ZeroOnRampAddress() public { + function test_ZeroOnRampAddress_Revert() public { OffRamp.SourceChainConfigArgs[] memory sourceChainConfigs = new OffRamp.SourceChainConfigArgs[](1); sourceChainConfigs[0] = OffRamp.SourceChainConfigArgs({ router: s_destRouter, @@ -250,7 +250,7 @@ contract OffRamp_applySourceChainConfigUpdates is OffRampSetup { s_offRamp.applySourceChainConfigUpdates(sourceChainConfigs); } - function test_RevertWhen_RouterAddress() public { + function test_RouterAddress_Revert() public { OffRamp.SourceChainConfigArgs[] memory sourceChainConfigs = new OffRamp.SourceChainConfigArgs[](1); sourceChainConfigs[0] = OffRamp.SourceChainConfigArgs({ router: IRouter(address(0)), @@ -263,7 +263,7 @@ contract OffRamp_applySourceChainConfigUpdates is OffRampSetup { s_offRamp.applySourceChainConfigUpdates(sourceChainConfigs); } - function test_RevertWhen_ZeroSourceChainSelector() public { + function test_ZeroSourceChainSelector_Revert() public { OffRamp.SourceChainConfigArgs[] memory sourceChainConfigs = new OffRamp.SourceChainConfigArgs[](1); sourceChainConfigs[0] = OffRamp.SourceChainConfigArgs({ router: s_destRouter, @@ -276,7 +276,7 @@ contract OffRamp_applySourceChainConfigUpdates is OffRampSetup { s_offRamp.applySourceChainConfigUpdates(sourceChainConfigs); } - function test_RevertWhen_InvalidOnRampUpdate() public { + function test_InvalidOnRampUpdate_Revert() public { OffRamp.SourceChainConfigArgs[] memory sourceChainConfigs = new OffRamp.SourceChainConfigArgs[](1); sourceChainConfigs[0] = OffRamp.SourceChainConfigArgs({ router: s_destRouter, diff --git a/contracts/src/v0.8/ccip/test/offRamp/OffRamp/OffRamp.batchExecute.t.sol b/contracts/src/v0.8/ccip/test/offRamp/OffRamp/OffRamp.batchExecute.t.sol index a170b21623c..aef54612945 100644 --- a/contracts/src/v0.8/ccip/test/offRamp/OffRamp/OffRamp.batchExecute.t.sol +++ b/contracts/src/v0.8/ccip/test/offRamp/OffRamp/OffRamp.batchExecute.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import {Internal} from "../../../libraries/Internal.sol"; import {OffRamp} from "../../../offRamp/OffRamp.sol"; @@ -15,7 +15,7 @@ contract OffRamp_batchExecute is OffRampSetup { s_offRamp.setVerifyOverrideResult(SOURCE_CHAIN_SELECTOR_3, 1); } - function test_SingleReport() public { + function test_SingleReport_Success() public { Internal.Any2EVMRampMessage[] memory messages = _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); @@ -37,7 +37,7 @@ contract OffRamp_batchExecute is OffRampSetup { assertGt(s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, messages[0].sender), nonceBefore); } - function test_MultipleReportsSameChain() public { + function test_MultipleReportsSameChain_Success() public { Internal.Any2EVMRampMessage[] memory messages1 = new Internal.Any2EVMRampMessage[](2); Internal.Any2EVMRampMessage[] memory messages2 = new Internal.Any2EVMRampMessage[](1); @@ -87,7 +87,7 @@ contract OffRamp_batchExecute is OffRampSetup { assertGt(s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, messages1[0].sender), nonceBefore); } - function test_MultipleReportsDifferentChains() public { + function test_MultipleReportsDifferentChains_Success() public { Internal.Any2EVMRampMessage[] memory messages1 = new Internal.Any2EVMRampMessage[](2); Internal.Any2EVMRampMessage[] memory messages2 = new Internal.Any2EVMRampMessage[](1); @@ -143,7 +143,7 @@ contract OffRamp_batchExecute is OffRampSetup { assertGt(nonceChain3, 0); } - function test_MultipleReportsDifferentChainsSkipCursedChain() public { + function test_MultipleReportsDifferentChainsSkipCursedChain_Success() public { _setMockRMNChainCurse(SOURCE_CHAIN_SELECTOR_1, true); Internal.Any2EVMRampMessage[] memory messages1 = new Internal.Any2EVMRampMessage[](2); @@ -182,7 +182,7 @@ contract OffRamp_batchExecute is OffRampSetup { } } - function test_MultipleReportsSkipDuplicate() public { + function test_MultipleReportsSkipDuplicate_Success() public { Internal.Any2EVMRampMessage[] memory messages = _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); @@ -205,7 +205,7 @@ contract OffRamp_batchExecute is OffRampSetup { ); } - function test_Unhealthy() public { + function test_Unhealthy_Success() public { _setMockRMNChainCurse(SOURCE_CHAIN_SELECTOR_1, true); vm.expectEmit(); emit OffRamp.SkippedReportExecution(SOURCE_CHAIN_SELECTOR_1); @@ -230,12 +230,12 @@ contract OffRamp_batchExecute is OffRampSetup { } // Reverts - function test_RevertWhen_ZeroReports() public { + function test_ZeroReports_Revert() public { vm.expectRevert(OffRamp.EmptyBatch.selector); s_offRamp.batchExecute(new Internal.ExecutionReport[](0), new OffRamp.GasLimitOverride[][](1)); } - function test_RevertWhen_OutOfBoundsGasLimitsAccess() public { + function test_OutOfBoundsGasLimitsAccess_Revert() public { Internal.Any2EVMRampMessage[] memory messages1 = new Internal.Any2EVMRampMessage[](2); Internal.Any2EVMRampMessage[] memory messages2 = new Internal.Any2EVMRampMessage[](1); diff --git a/contracts/src/v0.8/ccip/test/offRamp/OffRamp/OffRamp.ccipReceive.t.sol b/contracts/src/v0.8/ccip/test/offRamp/OffRamp/OffRamp.ccipReceive.t.sol index 320193f78a2..c05d8ec476a 100644 --- a/contracts/src/v0.8/ccip/test/offRamp/OffRamp/OffRamp.ccipReceive.t.sol +++ b/contracts/src/v0.8/ccip/test/offRamp/OffRamp/OffRamp.ccipReceive.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import {Client} from "../../../libraries/Client.sol"; import {OffRampSetup} from "./OffRampSetup.t.sol"; diff --git a/contracts/src/v0.8/ccip/test/offRamp/OffRamp/OffRamp.commit.t.sol b/contracts/src/v0.8/ccip/test/offRamp/OffRamp/OffRamp.commit.t.sol index f0611f8c5fc..a942b98cc1e 100644 --- a/contracts/src/v0.8/ccip/test/offRamp/OffRamp/OffRamp.commit.t.sol +++ b/contracts/src/v0.8/ccip/test/offRamp/OffRamp/OffRamp.commit.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import {IFeeQuoter} from "../../../interfaces/IFeeQuoter.sol"; import {IRMNRemote} from "../../../interfaces/IRMNRemote.sol"; @@ -20,7 +20,7 @@ contract OffRamp_commit is OffRampSetup { s_latestSequenceNumber = uint64(uint256(s_configDigestCommit)); } - function test_ReportAndPriceUpdate() public { + function test_ReportAndPriceUpdate_Success() public { OffRamp.CommitReport memory commitReport = _constructCommitReport(); vm.expectEmit(); @@ -64,7 +64,7 @@ contract OffRamp_commit is OffRampSetup { assertEq(block.timestamp, s_offRamp.getMerkleRoot(SOURCE_CHAIN_SELECTOR_1, root)); } - function test_RootWithRMNDisabled() public { + function test_RootWithRMNDisabled_success() public { // force RMN verification to fail vm.mockCallRevert(address(s_mockRMNRemote), abi.encodeWithSelector(IRMNRemote.verify.selector), bytes("")); @@ -101,7 +101,7 @@ contract OffRamp_commit is OffRampSetup { assertEq(block.timestamp, s_offRamp.getMerkleRoot(SOURCE_CHAIN_SELECTOR_1, root)); } - function test_StaleReportWithRoot() public { + function test_StaleReportWithRoot_Success() public { uint64 maxSeq = 12; uint224 tokenStartPrice = IFeeQuoter(s_offRamp.getDynamicConfig().feeQuoter).getTokenPrice(s_sourceFeeToken).value; @@ -144,7 +144,7 @@ contract OffRamp_commit is OffRampSetup { assertEq(tokenStartPrice, IFeeQuoter(s_offRamp.getDynamicConfig().feeQuoter).getTokenPrice(s_sourceFeeToken).value); } - function test_OnlyTokenPriceUpdates() public { + function test_OnlyTokenPriceUpdates_Success() public { // force RMN verification to fail vm.mockCallRevert(address(s_mockRMNRemote), abi.encodeWithSelector(IRMNRemote.verify.selector), bytes("")); @@ -166,7 +166,7 @@ contract OffRamp_commit is OffRampSetup { assertEq(s_latestSequenceNumber, s_offRamp.getLatestPriceSequenceNumber()); } - function test_OnlyGasPriceUpdates() public { + function test_OnlyGasPriceUpdates_Success() public { // force RMN verification to fail vm.mockCallRevert(address(s_mockRMNRemote), abi.encodeWithSelector(IRMNRemote.verify.selector), bytes("")); @@ -187,7 +187,7 @@ contract OffRamp_commit is OffRampSetup { assertEq(s_latestSequenceNumber, s_offRamp.getLatestPriceSequenceNumber()); } - function test_PriceSequenceNumberCleared() public { + function test_PriceSequenceNumberCleared_Success() public { Internal.MerkleRoot[] memory roots = new Internal.MerkleRoot[](0); OffRamp.CommitReport memory commitReport = OffRamp.CommitReport({ priceUpdates: _getSingleTokenPriceUpdateStruct(s_sourceFeeToken, 4e18), @@ -236,7 +236,7 @@ contract OffRamp_commit is OffRampSetup { _commit(commitReport, s_latestSequenceNumber); } - function test_ValidPriceUpdateThenStaleReportWithRoot() public { + function test_ValidPriceUpdateThenStaleReportWithRoot_Success() public { uint64 maxSeq = 12; uint224 tokenPrice1 = 4e18; uint224 tokenPrice2 = 5e18; @@ -282,10 +282,11 @@ contract OffRamp_commit is OffRampSetup { // Reverts - function test_RevertWhen_UnauthorizedTransmitter() public { + function test_UnauthorizedTransmitter_Revert() public { OffRamp.CommitReport memory commitReport = _constructCommitReport(); - bytes32[2] memory reportContext = [s_configDigestCommit, bytes32(uint256(s_latestSequenceNumber))]; + 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, F + 1); @@ -294,12 +295,12 @@ contract OffRamp_commit is OffRampSetup { s_offRamp.commit(reportContext, abi.encode(commitReport), rs, ss, rawVs); } - function test_RevertWhen_NoConfig() public { + function test_NoConfig_Revert() public { _redeployOffRampWithNoOCRConfigs(); OffRamp.CommitReport memory commitReport = _constructCommitReport(); - bytes32[2] memory reportContext = [bytes32(""), s_configDigestCommit]; + bytes32[3] memory reportContext = [bytes32(""), s_configDigestCommit, s_configDigestCommit]; (bytes32[] memory rs, bytes32[] memory ss,, bytes32 rawVs) = _getSignaturesForDigest(s_validSignerKeys, abi.encode(commitReport), reportContext, F + 1); @@ -308,7 +309,7 @@ contract OffRamp_commit is OffRampSetup { s_offRamp.commit(reportContext, abi.encode(commitReport), rs, ss, rawVs); } - function test_RevertWhen_NoConfigWithOtherConfigPresent() public { + function test_NoConfigWithOtherConfigPresent_Revert() public { _redeployOffRampWithNoOCRConfigs(); MultiOCR3Base.OCRConfigArgs[] memory ocrConfigs = new MultiOCR3Base.OCRConfigArgs[](1); @@ -324,7 +325,7 @@ contract OffRamp_commit is OffRampSetup { OffRamp.CommitReport memory commitReport = _constructCommitReport(); - bytes32[2] memory reportContext = [bytes32(""), s_configDigestCommit]; + bytes32[3] memory reportContext = [bytes32(""), s_configDigestCommit, s_configDigestCommit]; (bytes32[] memory rs, bytes32[] memory ss,, bytes32 rawVs) = _getSignaturesForDigest(s_validSignerKeys, abi.encode(commitReport), reportContext, F + 1); @@ -333,7 +334,7 @@ contract OffRamp_commit is OffRampSetup { s_offRamp.commit(reportContext, abi.encode(commitReport), rs, ss, rawVs); } - function test_RevertWhen_FailedRMNVerifications() public { + function test_FailedRMNVerification_Reverts() public { // force RMN verification to fail vm.mockCallRevert(address(s_mockRMNRemote), abi.encodeWithSelector(IRMNRemote.verify.selector), bytes("")); @@ -342,7 +343,7 @@ contract OffRamp_commit is OffRampSetup { _commit(commitReport, s_latestSequenceNumber); } - function test_RevertWhen_Unhealthy() public { + function test_Unhealthy_Revert() public { _setMockRMNChainCurse(SOURCE_CHAIN_SELECTOR_1, true); Internal.MerkleRoot[] memory roots = new Internal.MerkleRoot[](1); roots[0] = Internal.MerkleRoot({ @@ -360,7 +361,7 @@ contract OffRamp_commit is OffRampSetup { _commit(commitReport, s_latestSequenceNumber); } - function test_RevertWhen_InvalidRoot() public { + function test_InvalidRootRevert() public { Internal.MerkleRoot[] memory roots = new Internal.MerkleRoot[](1); roots[0] = Internal.MerkleRoot({ sourceChainSelector: SOURCE_CHAIN_SELECTOR_1, @@ -376,7 +377,7 @@ contract OffRamp_commit is OffRampSetup { _commit(commitReport, s_latestSequenceNumber); } - function test_RevertWhen_InvalidInterval() public { + function test_InvalidInterval_Revert() public { Internal.MerkleRoot[] memory roots = new Internal.MerkleRoot[](1); roots[0] = Internal.MerkleRoot({ sourceChainSelector: SOURCE_CHAIN_SELECTOR_1, @@ -396,7 +397,7 @@ contract OffRamp_commit is OffRampSetup { _commit(commitReport, s_latestSequenceNumber); } - function test_RevertWhen_InvalidIntervalMinLargerThanMax() public { + function test_InvalidIntervalMinLargerThanMax_Revert() public { s_offRamp.getSourceChainConfig(SOURCE_CHAIN_SELECTOR); Internal.MerkleRoot[] memory roots = new Internal.MerkleRoot[](1); roots[0] = Internal.MerkleRoot({ @@ -417,7 +418,7 @@ contract OffRamp_commit is OffRampSetup { _commit(commitReport, s_latestSequenceNumber); } - function test_RevertWhen_ZeroEpochAndRound() public { + function test_ZeroEpochAndRound_Revert() public { Internal.MerkleRoot[] memory roots = new Internal.MerkleRoot[](0); OffRamp.CommitReport memory commitReport = OffRamp.CommitReport({ priceUpdates: _getSingleTokenPriceUpdateStruct(s_sourceFeeToken, 4e18), @@ -429,7 +430,7 @@ contract OffRamp_commit is OffRampSetup { _commit(commitReport, 0); } - function test_RevertWhen_OnlyPriceUpdateStaleReport() public { + function test_OnlyPriceUpdateStaleReport_Revert() public { Internal.MerkleRoot[] memory roots = new Internal.MerkleRoot[](0); OffRamp.CommitReport memory commitReport = OffRamp.CommitReport({ priceUpdates: _getSingleTokenPriceUpdateStruct(s_sourceFeeToken, 4e18), @@ -445,7 +446,7 @@ contract OffRamp_commit is OffRampSetup { _commit(commitReport, s_latestSequenceNumber); } - function test_RevertWhen_SourceChainNotEnabled() public { + function test_SourceChainNotEnabled_Revert() public { Internal.MerkleRoot[] memory roots = new Internal.MerkleRoot[](1); roots[0] = Internal.MerkleRoot({ sourceChainSelector: 0, @@ -462,7 +463,7 @@ contract OffRamp_commit is OffRampSetup { _commit(commitReport, s_latestSequenceNumber); } - function test_RevertWhen_RootAlreadyCommitted() public { + function test_RootAlreadyCommitted_Revert() public { Internal.MerkleRoot[] memory roots = new Internal.MerkleRoot[](1); roots[0] = Internal.MerkleRoot({ sourceChainSelector: SOURCE_CHAIN_SELECTOR_1, @@ -484,7 +485,7 @@ contract OffRamp_commit is OffRampSetup { _commit(commitReport, ++s_latestSequenceNumber); } - function test_RevertWhen_CommitOnRampMismatch() public { + function test_CommitOnRampMismatch_Revert() public { OffRamp.CommitReport memory commitReport = _constructCommitReport(); commitReport.merkleRoots[0].onRampAddress = ON_RAMP_ADDRESS_2; diff --git a/contracts/src/v0.8/ccip/test/offRamp/OffRamp/OffRamp.constructor.t.sol b/contracts/src/v0.8/ccip/test/offRamp/OffRamp/OffRamp.constructor.t.sol index 49ba54dab7e..bd7bb94344c 100644 --- a/contracts/src/v0.8/ccip/test/offRamp/OffRamp/OffRamp.constructor.t.sol +++ b/contracts/src/v0.8/ccip/test/offRamp/OffRamp/OffRamp.constructor.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import {IRMNRemote} from "../../../interfaces/IRMNRemote.sol"; @@ -10,10 +10,9 @@ import {OffRampHelper} from "../../helpers/OffRampHelper.sol"; import {OffRampSetup} from "./OffRampSetup.t.sol"; contract OffRamp_constructor is OffRampSetup { - function test_Constructor() public { + function test_Constructor_Success() public { OffRamp.StaticConfig memory staticConfig = OffRamp.StaticConfig({ chainSelector: DEST_CHAIN_SELECTOR, - gasForCallExactCheck: GAS_FOR_CALL_EXACT_CHECK, rmnRemote: s_mockRMNRemote, tokenAdminRegistry: address(s_tokenAdminRegistry), nonceManager: address(s_inboundNonceManager) @@ -126,7 +125,7 @@ contract OffRamp_constructor is OffRampSetup { } // Revert - function test_RevertWhen_ZeroOnRampAddress() public { + function test_ZeroOnRampAddress_Revert() public { uint64[] memory sourceChainSelectors = new uint64[](1); sourceChainSelectors[0] = SOURCE_CHAIN_SELECTOR_1; @@ -143,7 +142,6 @@ contract OffRamp_constructor is OffRampSetup { s_offRamp = new OffRampHelper( OffRamp.StaticConfig({ chainSelector: DEST_CHAIN_SELECTOR, - gasForCallExactCheck: GAS_FOR_CALL_EXACT_CHECK, rmnRemote: s_mockRMNRemote, tokenAdminRegistry: address(s_tokenAdminRegistry), nonceManager: address(s_inboundNonceManager) @@ -153,7 +151,7 @@ contract OffRamp_constructor is OffRampSetup { ); } - function test_RevertWhen_SourceChainSelector() public { + function test_SourceChainSelector_Revert() public { uint64[] memory sourceChainSelectors = new uint64[](1); sourceChainSelectors[0] = SOURCE_CHAIN_SELECTOR_1; @@ -170,7 +168,6 @@ contract OffRamp_constructor is OffRampSetup { s_offRamp = new OffRampHelper( OffRamp.StaticConfig({ chainSelector: DEST_CHAIN_SELECTOR, - gasForCallExactCheck: GAS_FOR_CALL_EXACT_CHECK, rmnRemote: s_mockRMNRemote, tokenAdminRegistry: address(s_tokenAdminRegistry), nonceManager: address(s_inboundNonceManager) @@ -180,7 +177,7 @@ contract OffRamp_constructor is OffRampSetup { ); } - function test_RevertWhen_ZeroRMNRemote() public { + function test_ZeroRMNRemote_Revert() public { uint64[] memory sourceChainSelectors = new uint64[](1); sourceChainSelectors[0] = SOURCE_CHAIN_SELECTOR_1; @@ -191,7 +188,6 @@ contract OffRamp_constructor is OffRampSetup { s_offRamp = new OffRampHelper( OffRamp.StaticConfig({ chainSelector: DEST_CHAIN_SELECTOR, - gasForCallExactCheck: GAS_FOR_CALL_EXACT_CHECK, rmnRemote: IRMNRemote(address(0)), tokenAdminRegistry: address(s_tokenAdminRegistry), nonceManager: address(s_inboundNonceManager) @@ -201,7 +197,7 @@ contract OffRamp_constructor is OffRampSetup { ); } - function test_RevertWhen_ZeroChainSelector() public { + function test_ZeroChainSelector_Revert() public { uint64[] memory sourceChainSelectors = new uint64[](1); sourceChainSelectors[0] = SOURCE_CHAIN_SELECTOR_1; @@ -212,7 +208,6 @@ contract OffRamp_constructor is OffRampSetup { s_offRamp = new OffRampHelper( OffRamp.StaticConfig({ chainSelector: 0, - gasForCallExactCheck: GAS_FOR_CALL_EXACT_CHECK, rmnRemote: s_mockRMNRemote, tokenAdminRegistry: address(s_tokenAdminRegistry), nonceManager: address(s_inboundNonceManager) @@ -222,7 +217,7 @@ contract OffRamp_constructor is OffRampSetup { ); } - function test_RevertWhen_ZeroTokenAdminRegistry() public { + function test_ZeroTokenAdminRegistry_Revert() public { uint64[] memory sourceChainSelectors = new uint64[](1); sourceChainSelectors[0] = SOURCE_CHAIN_SELECTOR_1; @@ -233,7 +228,6 @@ contract OffRamp_constructor is OffRampSetup { s_offRamp = new OffRampHelper( OffRamp.StaticConfig({ chainSelector: DEST_CHAIN_SELECTOR, - gasForCallExactCheck: GAS_FOR_CALL_EXACT_CHECK, rmnRemote: s_mockRMNRemote, tokenAdminRegistry: address(0), nonceManager: address(s_inboundNonceManager) @@ -243,7 +237,7 @@ contract OffRamp_constructor is OffRampSetup { ); } - function test_RevertWhen_ZeroNonceManager() public { + function test_ZeroNonceManager_Revert() public { uint64[] memory sourceChainSelectors = new uint64[](1); sourceChainSelectors[0] = SOURCE_CHAIN_SELECTOR_1; @@ -254,7 +248,6 @@ contract OffRamp_constructor is OffRampSetup { s_offRamp = new OffRampHelper( OffRamp.StaticConfig({ chainSelector: DEST_CHAIN_SELECTOR, - gasForCallExactCheck: GAS_FOR_CALL_EXACT_CHECK, rmnRemote: s_mockRMNRemote, tokenAdminRegistry: address(s_tokenAdminRegistry), nonceManager: address(0) diff --git a/contracts/src/v0.8/ccip/test/offRamp/OffRamp/OffRamp.execute.t.sol b/contracts/src/v0.8/ccip/test/offRamp/OffRamp/OffRamp.execute.t.sol index 8d9b91143bb..9fd2499ef28 100644 --- a/contracts/src/v0.8/ccip/test/offRamp/OffRamp/OffRamp.execute.t.sol +++ b/contracts/src/v0.8/ccip/test/offRamp/OffRamp/OffRamp.execute.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import {IMessageInterceptor} from "../../../interfaces/IMessageInterceptor.sol"; @@ -18,7 +18,7 @@ contract OffRamp_execute is OffRampSetup { } // Asserts that execute completes - function test_SingleReport() public { + function test_SingleReport_Success() public { Internal.Any2EVMRampMessage[] memory messages = _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); Internal.ExecutionReport[] memory reports = _generateBatchReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages); @@ -42,7 +42,7 @@ contract OffRamp_execute is OffRampSetup { ); } - function test_MultipleReports() public { + function test_MultipleReports_Success() public { Internal.Any2EVMRampMessage[] memory messages1 = new Internal.Any2EVMRampMessage[](2); Internal.Any2EVMRampMessage[] memory messages2 = new Internal.Any2EVMRampMessage[](1); @@ -95,7 +95,7 @@ contract OffRamp_execute is OffRampSetup { ); } - function test_LargeBatch() public { + function test_LargeBatch_Success() public { Internal.ExecutionReport[] memory reports = new Internal.ExecutionReport[](10); for (uint64 i = 0; i < reports.length; ++i) { Internal.Any2EVMRampMessage[] memory messages = new Internal.Any2EVMRampMessage[](3); @@ -131,7 +131,7 @@ contract OffRamp_execute is OffRampSetup { } } - function test_MultipleReportsWithPartialValidationFailures() public { + function test_MultipleReportsWithPartialValidationFailures_Success() public { _enableInboundMessageInterceptor(); Internal.Any2EVMRampMessage[] memory messages1 = new Internal.Any2EVMRampMessage[](2); @@ -197,8 +197,8 @@ contract OffRamp_execute is OffRampSetup { // Reverts - function test_RevertWhen_UnauthorizedTransmitter() public { - bytes32[2] memory reportContext = [s_configDigestExec, s_configDigestExec]; + function test_UnauthorizedTransmitter_Revert() public { + bytes32[3] memory reportContext = [s_configDigestExec, s_configDigestExec, s_configDigestExec]; Internal.Any2EVMRampMessage[] memory messages = _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); @@ -208,7 +208,7 @@ contract OffRamp_execute is OffRampSetup { s_offRamp.execute(reportContext, abi.encode(reports)); } - function test_RevertWhen_NoConfig() public { + function test_NoConfig_Revert() public { _redeployOffRampWithNoOCRConfigs(); s_offRamp.setVerifyOverrideResult(SOURCE_CHAIN_SELECTOR_1, 1); @@ -216,14 +216,14 @@ contract OffRamp_execute is OffRampSetup { _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); Internal.ExecutionReport[] memory reports = _generateBatchReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages); - bytes32[2] memory reportContext = [bytes32(""), s_configDigestExec]; + 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)); } - function test_RevertWhen_NoConfigWithOtherConfigPresent() public { + function test_NoConfigWithOtherConfigPresent_Revert() public { _redeployOffRampWithNoOCRConfigs(); s_offRamp.setVerifyOverrideResult(SOURCE_CHAIN_SELECTOR_1, 1); @@ -242,14 +242,14 @@ contract OffRamp_execute is OffRampSetup { _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); Internal.ExecutionReport[] memory reports = _generateBatchReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages); - bytes32[2] memory reportContext = [bytes32(""), s_configDigestExec]; + 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)); } - function test_RevertWhen_WrongConfigWithSigners() public { + function test_WrongConfigWithSigners_Revert() public { _redeployOffRampWithNoOCRConfigs(); s_offRamp.setVerifyOverrideResult(SOURCE_CHAIN_SELECTOR_1, 1); @@ -269,15 +269,15 @@ contract OffRamp_execute is OffRampSetup { s_offRamp.setOCR3Configs(ocrConfigs); } - function test_RevertWhen_ZeroReports() public { + function test_ZeroReports_Revert() public { Internal.ExecutionReport[] memory reports = new Internal.ExecutionReport[](0); vm.expectRevert(OffRamp.EmptyBatch.selector); _execute(reports); } - function test_RevertWhen_IncorrectArrayType() public { - bytes32[2] memory reportContext = [s_configDigestExec, s_configDigestExec]; + function test_IncorrectArrayType_Revert() public { + bytes32[3] memory reportContext = [s_configDigestExec, s_configDigestExec, s_configDigestExec]; uint256[] memory wrongData = new uint256[](2); wrongData[0] = 1; @@ -287,8 +287,8 @@ contract OffRamp_execute is OffRampSetup { s_offRamp.execute(reportContext, abi.encode(wrongData)); } - function test_RevertWhen_NonArray() public { - bytes32[2] memory reportContext = [s_configDigestExec, s_configDigestExec]; + function test_NonArray_Revert() public { + bytes32[3] memory reportContext = [s_configDigestExec, s_configDigestExec, s_configDigestExec]; Internal.Any2EVMRampMessage[] memory messages = _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); diff --git a/contracts/src/v0.8/ccip/test/offRamp/OffRamp/OffRamp.executeSingleMessage.t.sol b/contracts/src/v0.8/ccip/test/offRamp/OffRamp/OffRamp.executeSingleMessage.t.sol index 40535ad4f7f..45fa18930d9 100644 --- a/contracts/src/v0.8/ccip/test/offRamp/OffRamp/OffRamp.executeSingleMessage.t.sol +++ b/contracts/src/v0.8/ccip/test/offRamp/OffRamp/OffRamp.executeSingleMessage.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import {IMessageInterceptor} from "../../../interfaces/IMessageInterceptor.sol"; import {IRouter} from "../../../interfaces/IRouter.sol"; @@ -20,7 +20,7 @@ contract OffRamp_executeSingleMessage is OffRampSetup { vm.startPrank(address(s_offRamp)); } - function test_executeSingleMessage_NoTokens() public { + function test_executeSingleMessage_NoTokens_Success() public { Internal.Any2EVMRampMessage memory message = _generateAny2EVMMessageNoTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1, 1); @@ -36,7 +36,7 @@ contract OffRamp_executeSingleMessage is OffRampSetup { abi.encodeWithSelector( IRouter.routeMessage.selector, expectedAny2EvmMessage, - GAS_FOR_CALL_EXACT_CHECK, + Internal.GAS_FOR_CALL_EXACT_CHECK, message.gasLimit, message.receiver ) @@ -44,7 +44,7 @@ contract OffRamp_executeSingleMessage is OffRampSetup { s_offRamp.executeSingleMessage(message, new bytes[](message.tokenAmounts.length), new uint32[](0)); } - function test_executeSingleMessage_WithTokens() public { + function test_executeSingleMessage_WithTokens_Success() public { Internal.Any2EVMRampMessage memory message = _generateMessagesWithTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1)[0]; bytes[] memory offchainTokenData = new bytes[](message.tokenAmounts.length); @@ -69,7 +69,7 @@ contract OffRamp_executeSingleMessage is OffRampSetup { s_offRamp.executeSingleMessage(message, offchainTokenData, new uint32[](0)); } - function test_executeSingleMessage_WithMessageInterceptor() public { + function test_executeSingleMessage_WithVInterception_Success() public { vm.stopPrank(); vm.startPrank(OWNER); _enableInboundMessageInterceptor(); @@ -79,47 +79,46 @@ contract OffRamp_executeSingleMessage is OffRampSetup { s_offRamp.executeSingleMessage(message, new bytes[](message.tokenAmounts.length), new uint32[](0)); } - function test_executeSingleMessage_NonContract() public { + function test_NonContract_Success() public { Internal.Any2EVMRampMessage memory message = _generateAny2EVMMessageNoTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1, 1); message.receiver = STRANGER; s_offRamp.executeSingleMessage(message, new bytes[](message.tokenAmounts.length), new uint32[](0)); } - function test_executeSingleMessage_NonContractWithTokens() public { + function test_NonContractWithTokens_Success() public { uint256[] memory amounts = new uint256[](2); amounts[0] = 1000; amounts[1] = 50; - - Internal.Any2EVMRampMessage memory message = - _generateAny2EVMMessageWithTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1, 1, amounts); - - message.receiver = STRANGER; - vm.expectEmit(); emit TokenPool.Released(address(s_offRamp), STRANGER, amounts[0]); vm.expectEmit(); emit TokenPool.Minted(address(s_offRamp), STRANGER, amounts[1]); - + Internal.Any2EVMRampMessage memory message = + _generateAny2EVMMessageWithTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1, 1, amounts); + message.receiver = STRANGER; s_offRamp.executeSingleMessage(message, new bytes[](message.tokenAmounts.length), new uint32[](0)); } // Reverts - function test_RevertWhen_executeSingleMessageWhen_TokenHandlingError() public { - Internal.Any2EVMRampMessage memory message = _generateAny2EVMMessageWithMaybeRevertingSingleToken(1, 50); - address destPool = s_destPoolByToken[message.tokenAmounts[0].destTokenAddress]; + function test_TokenHandlingError_Revert() public { + uint256[] memory amounts = new uint256[](2); + amounts[0] = 1000; + amounts[1] = 50; bytes memory errorMessage = "Random token pool issue"; + Internal.Any2EVMRampMessage memory message = + _generateAny2EVMMessageWithTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1, 1, amounts); s_maybeRevertingPool.setShouldRevert(errorMessage); - vm.expectRevert(abi.encodeWithSelector(OffRamp.TokenHandlingError.selector, destPool, errorMessage)); + vm.expectRevert(abi.encodeWithSelector(OffRamp.TokenHandlingError.selector, errorMessage)); s_offRamp.executeSingleMessage(message, new bytes[](message.tokenAmounts.length), new uint32[](0)); } - function test_RevertWhen_executeSingleMessageWhen_ZeroGasDONExecution() public { + function test_ZeroGasDONExecution_Revert() public { Internal.Any2EVMRampMessage memory message = _generateAny2EVMMessageNoTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1, 1); message.gasLimit = 0; @@ -129,7 +128,7 @@ contract OffRamp_executeSingleMessage is OffRampSetup { s_offRamp.executeSingleMessage(message, new bytes[](message.tokenAmounts.length), new uint32[](0)); } - function test_RevertWhen_executeSingleMessageWhen_MessageSender() public { + function test_MessageSender_Revert() public { vm.stopPrank(); Internal.Any2EVMRampMessage memory message = _generateAny2EVMMessageNoTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1, 1); @@ -137,7 +136,7 @@ contract OffRamp_executeSingleMessage is OffRampSetup { s_offRamp.executeSingleMessage(message, new bytes[](message.tokenAmounts.length), new uint32[](0)); } - function test_RevertWhen_executeSingleMessageWhen_MessageValidationError() public { + function test_executeSingleMessage_WithFailingValidation_Revert() public { vm.stopPrank(); vm.startPrank(OWNER); _enableInboundMessageInterceptor(); @@ -154,7 +153,7 @@ contract OffRamp_executeSingleMessage is OffRampSetup { s_offRamp.executeSingleMessage(message, new bytes[](message.tokenAmounts.length), new uint32[](0)); } - function test_RevertWhen_executeSingleMessageWhen_WithFailingValidationNoRouterCall() public { + function test_executeSingleMessage_WithFailingValidationNoRouterCall_Revert() public { vm.stopPrank(); vm.startPrank(OWNER); _enableInboundMessageInterceptor(); diff --git a/contracts/src/v0.8/ccip/test/offRamp/OffRamp/OffRamp.executeSingleReport.t.sol b/contracts/src/v0.8/ccip/test/offRamp/OffRamp/OffRamp.executeSingleReport.t.sol index d5bb32a8a12..4894cd2544c 100644 --- a/contracts/src/v0.8/ccip/test/offRamp/OffRamp/OffRamp.executeSingleReport.t.sol +++ b/contracts/src/v0.8/ccip/test/offRamp/OffRamp/OffRamp.executeSingleReport.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import {CallWithExactGas} from "../../../../shared/call/CallWithExactGas.sol"; import {NonceManager} from "../../../NonceManager.sol"; @@ -22,7 +22,7 @@ contract OffRamp_executeSingleReport is OffRampSetup { s_offRamp.setVerifyOverrideResult(SOURCE_CHAIN_SELECTOR_3, 1); } - function test_SingleMessageNoTokens() public { + function test_SingleMessageNoTokens_Success() public { Internal.Any2EVMRampMessage[] memory messages = _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); @@ -59,7 +59,7 @@ contract OffRamp_executeSingleReport is OffRampSetup { assertGt(s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, messages[0].sender), nonceBefore); } - function test_SingleMessageNoTokensUnordered() public { + function test_SingleMessageNoTokensUnordered_Success() public { Internal.Any2EVMRampMessage[] memory messages = _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); messages[0].header.nonce = 0; @@ -110,7 +110,7 @@ contract OffRamp_executeSingleReport is OffRampSetup { ); } - function test_SingleMessageNoTokensOtherChain() public { + function test_SingleMessageNoTokensOtherChain_Success() public { Internal.Any2EVMRampMessage[] memory messagesChain1 = _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); s_offRamp.executeSingleReport( @@ -133,7 +133,7 @@ contract OffRamp_executeSingleReport is OffRampSetup { assertEq(s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, messagesChain1[0].sender), nonceChain1); } - function test_ReceiverError() public { + function test_ReceiverError_Success() public { Internal.Any2EVMRampMessage[] memory messages = _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); @@ -165,7 +165,7 @@ contract OffRamp_executeSingleReport is OffRampSetup { assertEq(uint64(1), s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, abi.encode(OWNER))); } - function test_SkippedIncorrectNonce() public { + function test_SkippedIncorrectNonce_Success() public { Internal.Any2EVMRampMessage[] memory messages = _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); @@ -182,7 +182,7 @@ contract OffRamp_executeSingleReport is OffRampSetup { ); } - function test_SkippedIncorrectNonceStillExecutes() public { + function test_SkippedIncorrectNonceStillExecutes_Success() public { Internal.Any2EVMRampMessage[] memory messages = _generateMessagesWithTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); @@ -206,7 +206,7 @@ contract OffRamp_executeSingleReport is OffRampSetup { ); } - function test__execute_SkippedAlreadyExecutedMessage() public { + function test__execute_SkippedAlreadyExecutedMessage_Success() public { Internal.Any2EVMRampMessage[] memory messages = _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); @@ -231,7 +231,7 @@ contract OffRamp_executeSingleReport is OffRampSetup { ); } - function test__execute_SkippedAlreadyExecutedMessageUnordered() public { + function test__execute_SkippedAlreadyExecutedMessageUnordered_Success() public { Internal.Any2EVMRampMessage[] memory messages = _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); messages[0].header.nonce = 0; @@ -260,7 +260,7 @@ contract OffRamp_executeSingleReport is OffRampSetup { // Send a message to a contract that does not implement the CCIPReceiver interface // This should execute successfully. - function test_SingleMessageToNonCCIPReceiver() public { + function test_SingleMessageToNonCCIPReceiver_Success() public { Internal.Any2EVMRampMessage[] memory messages = _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); MaybeRevertMessageReceiverNo165 newReceiver = new MaybeRevertMessageReceiverNo165(true); @@ -337,7 +337,7 @@ contract OffRamp_executeSingleReport is OffRampSetup { ); } - function test_TwoMessagesWithTokensAndGE() public { + function test_TwoMessagesWithTokensAndGE_Success() public { Internal.Any2EVMRampMessage[] memory messages = _generateMessagesWithTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); // Set message 1 to use another receiver to simulate more fair gas costs @@ -425,7 +425,7 @@ contract OffRamp_executeSingleReport is OffRampSetup { ); } - function test_InvalidSourcePoolAddress() public { + function test_InvalidSourcePoolAddress_Success() public { address fakePoolAddress = address(0x0000000000333333); Internal.Any2EVMRampMessage[] memory messages = @@ -435,8 +435,6 @@ contract OffRamp_executeSingleReport is OffRampSetup { messages[0].header.messageId = _hashMessage(messages[0], ON_RAMP_ADDRESS_1); messages[1].header.messageId = _hashMessage(messages[1], ON_RAMP_ADDRESS_1); - address destPool = s_destPoolByToken[messages[0].tokenAmounts[0].destTokenAddress]; - vm.recordLogs(); s_offRamp.executeSingleReport( @@ -450,13 +448,12 @@ contract OffRamp_executeSingleReport is OffRampSetup { Internal.MessageExecutionState.FAILURE, abi.encodeWithSelector( OffRamp.TokenHandlingError.selector, - destPool, abi.encodeWithSelector(TokenPool.InvalidSourcePoolAddress.selector, abi.encode(fakePoolAddress)) ) ); } - function test_WithCurseOnAnotherSourceChain() public { + function test_WithCurseOnAnotherSourceChain_Success() public { _setMockRMNChainCurse(SOURCE_CHAIN_SELECTOR_2, true); s_offRamp.executeSingleReport( _generateReportFromMessages( @@ -466,7 +463,7 @@ contract OffRamp_executeSingleReport is OffRampSetup { ); } - function test_Unhealthy() public { + function test_Unhealthy_Success() public { _setMockRMNChainCurse(SOURCE_CHAIN_SELECTOR_1, true); vm.expectEmit(); @@ -492,7 +489,7 @@ contract OffRamp_executeSingleReport is OffRampSetup { // Reverts - function test_RevertWhen_MismatchingDestChainSelector() public { + function test_MismatchingDestChainSelector_Revert() public { Internal.Any2EVMRampMessage[] memory messages = _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_3, ON_RAMP_ADDRESS_3); messages[0].header.destChainSelector = DEST_CHAIN_SELECTOR + 1; @@ -505,7 +502,7 @@ contract OffRamp_executeSingleReport is OffRampSetup { s_offRamp.executeSingleReport(executionReport, new OffRamp.GasLimitOverride[](0)); } - function test_RevertWhen_UnhealthySingleChainCurse() public { + function test_UnhealthySingleChainCurse_Revert() public { _setMockRMNChainCurse(SOURCE_CHAIN_SELECTOR_1, true); vm.expectEmit(); emit OffRamp.SkippedReportExecution(SOURCE_CHAIN_SELECTOR_1); @@ -527,7 +524,7 @@ contract OffRamp_executeSingleReport is OffRampSetup { _assertNoEmit(OffRamp.SkippedReportExecution.selector); } - function test_RevertWhen_UnexpectedTokenData() public { + function test_UnexpectedTokenData_Revert() public { Internal.ExecutionReport memory report = _generateReportFromMessages( SOURCE_CHAIN_SELECTOR_1, _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1) ); @@ -538,7 +535,7 @@ contract OffRamp_executeSingleReport is OffRampSetup { s_offRamp.executeSingleReport(report, new OffRamp.GasLimitOverride[](0)); } - function test_RevertWhen_EmptyReport() public { + function test_EmptyReport_Revert() public { vm.expectRevert(abi.encodeWithSelector(OffRamp.EmptyReport.selector, SOURCE_CHAIN_SELECTOR_1)); s_offRamp.executeSingleReport( @@ -553,7 +550,7 @@ contract OffRamp_executeSingleReport is OffRampSetup { ); } - function test_RevertWhen_RootNotCommitted() public { + function test_RootNotCommitted_Revert() public { s_offRamp.setVerifyOverrideResult(SOURCE_CHAIN_SELECTOR_1, 0); vm.expectRevert(abi.encodeWithSelector(OffRamp.RootNotCommitted.selector, SOURCE_CHAIN_SELECTOR_1)); @@ -564,7 +561,7 @@ contract OffRamp_executeSingleReport is OffRampSetup { ); } - function test_RevertWhen_ManualExecutionNotYetEnabled() public { + function test_ManualExecutionNotYetEnabled_Revert() public { s_offRamp.setVerifyOverrideResult(SOURCE_CHAIN_SELECTOR_1, BLOCK_TIME); vm.expectRevert(abi.encodeWithSelector(OffRamp.ManualExecutionNotYetEnabled.selector, SOURCE_CHAIN_SELECTOR_1)); @@ -576,7 +573,7 @@ contract OffRamp_executeSingleReport is OffRampSetup { ); } - function test_RevertWhen_NonExistingSourceChain() public { + function test_NonExistingSourceChain_Revert() public { uint64 newSourceChainSelector = SOURCE_CHAIN_SELECTOR_1 + 1; bytes memory newOnRamp = abi.encode(ON_RAMP_ADDRESS, 1); @@ -588,7 +585,7 @@ contract OffRamp_executeSingleReport is OffRampSetup { ); } - function test_RevertWhen_DisabledSourceChain() public { + function test_DisabledSourceChain_Revert() public { Internal.Any2EVMRampMessage[] memory messages = _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_2, ON_RAMP_ADDRESS_2); @@ -598,7 +595,7 @@ contract OffRamp_executeSingleReport is OffRampSetup { ); } - function test_RevertWhen_TokenDataMismatch() public { + function test_TokenDataMismatch_Revert() public { Internal.Any2EVMRampMessage[] memory messages = _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); Internal.ExecutionReport memory report = _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages); @@ -613,7 +610,7 @@ contract OffRamp_executeSingleReport is OffRampSetup { s_offRamp.executeSingleReport(report, new OffRamp.GasLimitOverride[](0)); } - function test_RevertWhen_RouterYULCall() public { + function test_RouterYULCall_Revert() public { Internal.Any2EVMRampMessage[] memory messages = _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); @@ -636,7 +633,7 @@ contract OffRamp_executeSingleReport is OffRampSetup { ); } - function test_RevertWhen_RetryFailedMessageWithoutManualExecution() public { + function test_RetryFailedMessageWithoutManualExecution_Revert() public { Internal.Any2EVMRampMessage[] memory messages = _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); diff --git a/contracts/src/v0.8/ccip/test/offRamp/OffRamp/OffRamp.getExecutionState.t.sol b/contracts/src/v0.8/ccip/test/offRamp/OffRamp/OffRamp.getExecutionState.t.sol index 96261f5f0b3..ac9cfe86cd9 100644 --- a/contracts/src/v0.8/ccip/test/offRamp/OffRamp/OffRamp.getExecutionState.t.sol +++ b/contracts/src/v0.8/ccip/test/offRamp/OffRamp/OffRamp.getExecutionState.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import {Internal} from "../../../libraries/Internal.sol"; import {OffRampSetup} from "./OffRampSetup.t.sol"; @@ -32,7 +32,7 @@ contract OffRamp_getExecutionState is OffRampSetup { } } - function test_GetExecutionState() public { + function test_GetExecutionState_Success() public { s_offRamp.setExecutionStateHelper(SOURCE_CHAIN_SELECTOR_1, 0, Internal.MessageExecutionState.FAILURE); assertEq(s_offRamp.getExecutionStateBitMap(SOURCE_CHAIN_SELECTOR_1, 0), 3); @@ -72,7 +72,7 @@ contract OffRamp_getExecutionState is OffRampSetup { ); } - function test_GetDifferentChainExecutionState() public { + function test_GetDifferentChainExecutionState_Success() public { s_offRamp.setExecutionStateHelper(SOURCE_CHAIN_SELECTOR_1, 0, Internal.MessageExecutionState.FAILURE); assertEq(s_offRamp.getExecutionStateBitMap(SOURCE_CHAIN_SELECTOR_1, 0), 3); assertEq(s_offRamp.getExecutionStateBitMap(SOURCE_CHAIN_SELECTOR_1 + 1, 0), 0); @@ -119,7 +119,7 @@ contract OffRamp_getExecutionState is OffRampSetup { ); } - function test_FillExecutionState() public { + function test_FillExecutionState_Success() public { for (uint64 i = 0; i < 384; ++i) { s_offRamp.setExecutionStateHelper(SOURCE_CHAIN_SELECTOR_1, i, Internal.MessageExecutionState.FAILURE); } diff --git a/contracts/src/v0.8/ccip/test/offRamp/OffRamp/OffRamp.manuallyExecute.t.sol b/contracts/src/v0.8/ccip/test/offRamp/OffRamp/OffRamp.manuallyExecute.t.sol index d2406a0e40b..0422053bdd7 100644 --- a/contracts/src/v0.8/ccip/test/offRamp/OffRamp/OffRamp.manuallyExecute.t.sol +++ b/contracts/src/v0.8/ccip/test/offRamp/OffRamp/OffRamp.manuallyExecute.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import {Internal} from "../../../libraries/Internal.sol"; import {MultiOCR3Base} from "../../../ocr/MultiOCR3Base.sol"; @@ -23,7 +23,7 @@ contract OffRamp_manuallyExecute is OffRampSetup { s_offRamp.setVerifyOverrideResult(SOURCE_CHAIN_SELECTOR_3, 1); } - function test_manuallyExecute() public { + function test_manuallyExecute_Success() public { Internal.Any2EVMRampMessage[] memory messages = _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); messages[0].receiver = address(s_reverting_receiver); @@ -49,7 +49,7 @@ contract OffRamp_manuallyExecute is OffRampSetup { ); } - function test_manuallyExecute_WithGasOverride() public { + function test_manuallyExecute_WithGasOverride_Success() public { Internal.Any2EVMRampMessage[] memory messages = _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); messages[0].receiver = address(s_reverting_receiver); @@ -75,7 +75,7 @@ contract OffRamp_manuallyExecute is OffRampSetup { ); } - function test_manuallyExecute_DoesNotRevertIfUntouched() public { + function test_manuallyExecute_DoesNotRevertIfUntouched_Success() public { Internal.Any2EVMRampMessage[] memory messages = _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); messages[0].receiver = address(s_reverting_receiver); @@ -108,7 +108,7 @@ contract OffRamp_manuallyExecute is OffRampSetup { ); } - function test_manuallyExecute_WithMultiReportGasOverride() public { + function test_manuallyExecute_WithMultiReportGasOverride_Success() public { Internal.Any2EVMRampMessage[] memory messages1 = new Internal.Any2EVMRampMessage[](3); Internal.Any2EVMRampMessage[] memory messages2 = new Internal.Any2EVMRampMessage[](2); @@ -174,7 +174,7 @@ contract OffRamp_manuallyExecute is OffRampSetup { } } - function test_manuallyExecute_WithPartialMessages() public { + function test_manuallyExecute_WithPartialMessages_Success() public { Internal.Any2EVMRampMessage[] memory messages = new Internal.Any2EVMRampMessage[](3); for (uint64 i = 0; i < 3; ++i) { @@ -246,7 +246,7 @@ contract OffRamp_manuallyExecute is OffRampSetup { ); } - function test_manuallyExecute_LowGasLimit() public { + function test_manuallyExecute_LowGasLimit_Success() public { Internal.Any2EVMRampMessage[] memory messages = _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); messages[0].gasLimit = 1; @@ -287,12 +287,12 @@ contract OffRamp_manuallyExecute is OffRampSetup { // Reverts - function test_RevertWhen_manuallyExecute_ForkedChain() public { + function test_manuallyExecute_ForkedChain_Revert() public { Internal.Any2EVMRampMessage[] memory messages = _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); Internal.ExecutionReport[] memory reports = _generateBatchReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages); - uint256 chain1 = uint200(block.chainid); + uint256 chain1 = block.chainid; uint256 chain2 = chain1 + 1; vm.chainId(chain2); vm.expectRevert(abi.encodeWithSelector(MultiOCR3Base.ForkedChain.selector, chain1, chain2)); @@ -303,7 +303,7 @@ contract OffRamp_manuallyExecute is OffRampSetup { s_offRamp.manuallyExecute(reports, gasLimitOverrides); } - function test_RevertWhen_ManualExecGasLimitMismatchSingleReport() public { + function test_ManualExecGasLimitMismatchSingleReport_Revert() public { Internal.Any2EVMRampMessage[] memory messages = new Internal.Any2EVMRampMessage[](2); messages[0] = _generateAny2EVMMessageNoTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1, 1); messages[1] = _generateAny2EVMMessageNoTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1, 2); @@ -333,7 +333,7 @@ contract OffRamp_manuallyExecute is OffRampSetup { s_offRamp.manuallyExecute(reports, gasLimitOverrides); } - function test_RevertWhen_manuallyExecute_GasLimitMismatchMultipleReports() public { + function test_manuallyExecute_GasLimitMismatchMultipleReports_Revert() public { Internal.Any2EVMRampMessage[] memory messages1 = new Internal.Any2EVMRampMessage[](2); Internal.Any2EVMRampMessage[] memory messages2 = new Internal.Any2EVMRampMessage[](1); @@ -376,7 +376,7 @@ contract OffRamp_manuallyExecute is OffRampSetup { s_offRamp.manuallyExecute(reports, gasLimitOverrides); } - function test_RevertWhen_manuallyExecute_InvalidReceiverExecutionGasLimit() public { + function test_manuallyExecute_InvalidReceiverExecutionGasLimit_Revert() public { Internal.Any2EVMRampMessage[] memory messages = _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); @@ -395,7 +395,7 @@ contract OffRamp_manuallyExecute is OffRampSetup { s_offRamp.manuallyExecute(_generateBatchReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), gasLimitOverrides); } - function test_RevertWhen_manuallyExecute_DestinationGasAmountCountMismatch() public { + function test_manuallyExecute_DestinationGasAmountCountMismatch_Revert() public { uint256[] memory amounts = new uint256[](2); amounts[0] = 1000; amounts[1] = 1000; @@ -418,7 +418,7 @@ contract OffRamp_manuallyExecute is OffRampSetup { s_offRamp.manuallyExecute(_generateBatchReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), gasLimitOverrides); } - function test_RevertWhen_manuallyExecute_InvalidTokenGasOverride() public { + function test_manuallyExecute_InvalidTokenGasOverride_Revert() public { uint256[] memory amounts = new uint256[](2); amounts[0] = 1000; amounts[1] = 1000; @@ -444,7 +444,7 @@ contract OffRamp_manuallyExecute is OffRampSetup { s_offRamp.manuallyExecute(_generateBatchReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), gasLimitOverrides); } - function test_RevertWhen_manuallyExecute_FailedTx() public { + function test_manuallyExecute_FailedTx_Revert() public { Internal.Any2EVMRampMessage[] memory messages = _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); @@ -473,7 +473,7 @@ contract OffRamp_manuallyExecute is OffRampSetup { s_offRamp.manuallyExecute(_generateBatchReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), gasLimitOverrides); } - function test_manuallyExecute_ReentrancyFails() public { + function test_manuallyExecute_ReentrancyFails_Success() public { uint256 tokenAmount = 1e9; IERC20 tokenToAbuse = IERC20(s_destFeeToken); @@ -531,7 +531,7 @@ contract OffRamp_manuallyExecute is OffRampSetup { assertEq(tokenToAbuse.balanceOf(address(receiver)), balancePre + tokenAmount); } - function test_RevertWhen_manuallyExecute_MultipleReportsWithSingleCursedLane() public { + function test_manuallyExecute_MultipleReportsWithSingleCursedLane_Revert() public { Internal.Any2EVMRampMessage[] memory messages1 = new Internal.Any2EVMRampMessage[](3); Internal.Any2EVMRampMessage[] memory messages2 = new Internal.Any2EVMRampMessage[](2); @@ -562,7 +562,7 @@ contract OffRamp_manuallyExecute is OffRampSetup { s_offRamp.manuallyExecute(reports, gasLimitOverrides); } - function test_RevertWhen_manuallyExecute_SourceChainSelectorMismatch() public { + function test_manuallyExecute_SourceChainSelectorMismatch_Revert() public { Internal.Any2EVMRampMessage[] memory messages1 = new Internal.Any2EVMRampMessage[](1); Internal.Any2EVMRampMessage[] memory messages2 = new Internal.Any2EVMRampMessage[](1); messages1[0] = _generateAny2EVMMessageNoTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1, 1); diff --git a/contracts/src/v0.8/ccip/test/offRamp/OffRamp/OffRamp.releaseOrMintSingleToken.t.sol b/contracts/src/v0.8/ccip/test/offRamp/OffRamp/OffRamp.releaseOrMintSingleToken.t.sol index c30cdeb4d93..72999fad42f 100644 --- a/contracts/src/v0.8/ccip/test/offRamp/OffRamp/OffRamp.releaseOrMintSingleToken.t.sol +++ b/contracts/src/v0.8/ccip/test/offRamp/OffRamp/OffRamp.releaseOrMintSingleToken.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import {ITokenAdminRegistry} from "../../../interfaces/ITokenAdminRegistry.sol"; @@ -17,7 +17,7 @@ contract OffRamp_releaseOrMintSingleToken is OffRampSetup { _setupMultipleOffRamps(); } - function test__releaseOrMintSingleToken() public { + function test__releaseOrMintSingleToken_Success() public { uint256 amount = 123123; address token = s_sourceTokens[0]; bytes memory originalSender = abi.encode(OWNER); @@ -56,7 +56,7 @@ contract OffRamp_releaseOrMintSingleToken is OffRampSetup { assertEq(startingBalance + amount, dstToken1.balanceOf(OWNER)); } - function test_RevertWhen_releaseOrMintToken_InvalidDataLength() public { + function test_releaseOrMintToken_InvalidDataLength_Revert() public { uint256 amount = 123123; address token = s_sourceTokens[0]; @@ -78,14 +78,13 @@ contract OffRamp_releaseOrMintSingleToken is OffRampSetup { s_offRamp.releaseOrMintSingleToken(tokenAmount, abi.encode(OWNER), OWNER, SOURCE_CHAIN_SELECTOR, ""); } - function test_RevertWhen_releaseOrMintTokenWhen_TokenHandlingError_BalanceOf() public { + function test_releaseOrMintToken_TokenHandlingError_BalanceOf_Revert() public { uint256 amount = 123123; address token = s_sourceTokens[0]; - address destTokenAddress = s_destTokenBySourceToken[token]; Internal.Any2EVMTokenTransfer memory tokenAmount = Internal.Any2EVMTokenTransfer({ sourcePoolAddress: abi.encode(s_sourcePoolByToken[token]), - destTokenAddress: destTokenAddress, + destTokenAddress: s_destTokenBySourceToken[token], extraData: "", amount: amount, destGasAmount: DEFAULT_TOKEN_DEST_GAS_OVERHEAD @@ -94,14 +93,16 @@ contract OffRamp_releaseOrMintSingleToken is OffRampSetup { bytes memory revertData = "failed to balanceOf"; // Mock the call so returns 2 slots of data - vm.mockCallRevert(destTokenAddress, abi.encodeWithSelector(IERC20.balanceOf.selector, OWNER), revertData); + vm.mockCallRevert( + s_destTokenBySourceToken[token], abi.encodeWithSelector(IERC20.balanceOf.selector, OWNER), revertData + ); - vm.expectRevert(abi.encodeWithSelector(OffRamp.TokenHandlingError.selector, destTokenAddress, revertData)); + vm.expectRevert(abi.encodeWithSelector(OffRamp.TokenHandlingError.selector, revertData)); s_offRamp.releaseOrMintSingleToken(tokenAmount, abi.encode(OWNER), OWNER, SOURCE_CHAIN_SELECTOR, ""); } - function test_RevertWhen_releaseOrMintToken_ReleaseOrMintBalanceMismatch() public { + function test_releaseOrMintToken_ReleaseOrMintBalanceMismatch_Revert() public { uint256 amount = 123123; address token = s_sourceTokens[0]; uint256 mockedStaticBalance = 50000; @@ -129,7 +130,7 @@ contract OffRamp_releaseOrMintSingleToken is OffRampSetup { s_offRamp.releaseOrMintSingleToken(tokenAmount, abi.encode(OWNER), OWNER, SOURCE_CHAIN_SELECTOR, ""); } - function test_RevertWhen_releaseOrMintToken_skip_ReleaseOrMintBalanceMismatch_if_pool() public { + function test_releaseOrMintToken_skip_ReleaseOrMintBalanceMismatch_if_pool_Revert() public { uint256 amount = 123123; address token = s_sourceTokens[0]; uint256 mockedStaticBalance = 50000; @@ -154,7 +155,7 @@ contract OffRamp_releaseOrMintSingleToken is OffRampSetup { ); } - function test_RevertWhen__releaseOrMintSingleToken_NotACompatiblePool() public { + function test__releaseOrMintSingleToken_NotACompatiblePool_Revert() public { uint256 amount = 123123; address token = s_sourceTokens[0]; address destToken = s_destTokenBySourceToken[token]; @@ -197,14 +198,13 @@ contract OffRamp_releaseOrMintSingleToken is OffRampSetup { s_offRamp.releaseOrMintSingleToken(tokenAmount, originalSender, OWNER, SOURCE_CHAIN_SELECTOR_1, offchainTokenData); } - function test_RevertWhen_releaseOrMintSingleTokenWhen_TokenHandlingError_transfer() public { + function test__releaseOrMintSingleToken_TokenHandlingError_transfer_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")); - address destPool = s_destPoolByToken[destToken]; Internal.Any2EVMTokenTransfer memory tokenAmount = Internal.Any2EVMTokenTransfer({ sourcePoolAddress: abi.encode(s_sourcePoolByToken[token]), @@ -218,7 +218,7 @@ contract OffRamp_releaseOrMintSingleToken is OffRampSetup { vm.mockCallRevert(destToken, abi.encodeWithSelector(IERC20.transfer.selector, receiver, amount), revertData); - vm.expectRevert(abi.encodeWithSelector(OffRamp.TokenHandlingError.selector, destPool, revertData)); + vm.expectRevert(abi.encodeWithSelector(OffRamp.TokenHandlingError.selector, revertData)); s_offRamp.releaseOrMintSingleToken( tokenAmount, originalSender, receiver, SOURCE_CHAIN_SELECTOR_1, offchainTokenData ); diff --git a/contracts/src/v0.8/ccip/test/offRamp/OffRamp/OffRamp.releaseOrMintTokens.t.sol b/contracts/src/v0.8/ccip/test/offRamp/OffRamp/OffRamp.releaseOrMintTokens.t.sol index 07cf730c9d6..74594f7031d 100644 --- a/contracts/src/v0.8/ccip/test/offRamp/OffRamp/OffRamp.releaseOrMintTokens.t.sol +++ b/contracts/src/v0.8/ccip/test/offRamp/OffRamp/OffRamp.releaseOrMintTokens.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import {CallWithExactGas} from "../../../../shared/call/CallWithExactGas.sol"; import {Client} from "../../../libraries/Client.sol"; @@ -18,7 +18,7 @@ contract OffRamp_releaseOrMintTokens is OffRampSetup { _setupMultipleOffRamps(); } - function test_releaseOrMintTokens() public { + function test_releaseOrMintTokens_Success() public { Client.EVMTokenAmount[] memory srcTokenAmounts = _getCastedSourceEVMTokenAmountsWithZeroAmounts(); IERC20 dstToken1 = IERC20(s_destFeeToken); uint256 startingBalance = dstToken1.balanceOf(OWNER); @@ -54,7 +54,7 @@ contract OffRamp_releaseOrMintTokens is OffRampSetup { assertEq(startingBalance + amount1, dstToken1.balanceOf(OWNER)); } - function test_releaseOrMintTokens_WithGasOverride() public { + function test_releaseOrMintTokens_WithGasOverride_Success() public { Client.EVMTokenAmount[] memory srcTokenAmounts = _getCastedSourceEVMTokenAmountsWithZeroAmounts(); IERC20 dstToken1 = IERC20(s_destFeeToken); uint256 startingBalance = dstToken1.balanceOf(OWNER); @@ -94,7 +94,7 @@ contract OffRamp_releaseOrMintTokens is OffRampSetup { assertEq(startingBalance + amount1, dstToken1.balanceOf(OWNER)); } - function test_releaseOrMintTokens_destDenominatedDecimals() public { + function test_releaseOrMintTokens_destDenominatedDecimals_Success() public { Client.EVMTokenAmount[] memory srcTokenAmounts = _getCastedSourceEVMTokenAmountsWithZeroAmounts(); uint256 amount = 100; uint256 destinationDenominationMultiplier = 1000; @@ -118,15 +118,13 @@ contract OffRamp_releaseOrMintTokens is OffRampSetup { // Revert - function test_RevertWhen_releaseOrMintTokensWhen_TokenHandlingError() public { + function test_TokenHandlingError_Reverts() public { Client.EVMTokenAmount[] memory srcTokenAmounts = _getCastedSourceEVMTokenAmountsWithZeroAmounts(); bytes memory unknownError = bytes("unknown error"); s_maybeRevertingPool.setShouldRevert(unknownError); - vm.expectRevert( - abi.encodeWithSelector(OffRamp.TokenHandlingError.selector, address(s_maybeRevertingPool), unknownError) - ); + vm.expectRevert(abi.encodeWithSelector(OffRamp.TokenHandlingError.selector, unknownError)); s_offRamp.releaseOrMintTokens( _getDefaultSourceTokenData(srcTokenAmounts), @@ -138,7 +136,7 @@ contract OffRamp_releaseOrMintTokens is OffRampSetup { ); } - function test_RevertWhen_releaseOrMintTokensWhenInvalidDataLengthReturnData() public { + function test_releaseOrMintTokens_InvalidDataLengthReturnData_Revert() public { uint256 amount = 100; Client.EVMTokenAmount[] memory srcTokenAmounts = _getCastedSourceEVMTokenAmountsWithZeroAmounts(); srcTokenAmounts[0].amount = amount; @@ -172,7 +170,7 @@ contract OffRamp_releaseOrMintTokens is OffRampSetup { ); } - function test_RevertWhen_releaseOrMintTokensWhen_PoolIsNotAPool() public { + function test__releaseOrMintTokens_PoolIsNotAPool_Reverts() public { // The offRamp is a contract, but not a pool address fakePoolAddress = address(s_offRamp); @@ -191,7 +189,7 @@ contract OffRamp_releaseOrMintTokens is OffRampSetup { ); } - function test_RevertWhen_releaseOrMintTokensWhenPoolDoesNotSupportDest() public { + function test_releaseOrMintTokens_PoolDoesNotSupportDest_Reverts() public { Client.EVMTokenAmount[] memory srcTokenAmounts = _getCastedSourceEVMTokenAmountsWithZeroAmounts(); uint256 amount1 = 100; srcTokenAmounts[0].amount = amount1; @@ -226,7 +224,7 @@ contract OffRamp_releaseOrMintTokens is OffRampSetup { /// forge-config: default.fuzz.runs = 32 /// forge-config: ccip.fuzz.runs = 1024 // Uint256 gives a good range of values to test, both inside and outside of the eth address space. - function testFuzz_releaseOrMintTokens_AnyRevertIsCaught( + function testFuzz__releaseOrMintTokens_AnyRevertIsCaught_Success( address destPool ) public { // Input 447301751254033913445893214690834296930546521452, which is 0x4E59B44847B379578588920CA78FBF26C0B4956C diff --git a/contracts/src/v0.8/ccip/test/offRamp/OffRamp/OffRamp.setDynamicConfig.t.sol b/contracts/src/v0.8/ccip/test/offRamp/OffRamp/OffRamp.setDynamicConfig.t.sol index 93857ecfc07..384d9b446aa 100644 --- a/contracts/src/v0.8/ccip/test/offRamp/OffRamp/OffRamp.setDynamicConfig.t.sol +++ b/contracts/src/v0.8/ccip/test/offRamp/OffRamp/OffRamp.setDynamicConfig.t.sol @@ -1,12 +1,12 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import {Ownable2Step} from "../../../../shared/access/Ownable2Step.sol"; import {OffRamp} from "../../../offRamp/OffRamp.sol"; import {OffRampSetup} from "./OffRampSetup.t.sol"; contract OffRamp_setDynamicConfig is OffRampSetup { - function test_SetDynamicConfig() public { + function test_SetDynamicConfig_Success() public { OffRamp.DynamicConfig memory dynamicConfig = _generateDynamicOffRampConfig(address(s_feeQuoter)); vm.expectEmit(); @@ -18,7 +18,7 @@ contract OffRamp_setDynamicConfig is OffRampSetup { _assertSameConfig(dynamicConfig, newConfig); } - function test_SetDynamicConfigWithInterceptor() public { + function test_SetDynamicConfigWithInterceptor_Success() public { OffRamp.DynamicConfig memory dynamicConfig = _generateDynamicOffRampConfig(address(s_feeQuoter)); dynamicConfig.messageInterceptor = address(s_inboundMessageInterceptor); @@ -33,7 +33,7 @@ contract OffRamp_setDynamicConfig is OffRampSetup { // Reverts - function test_RevertWhen_NonOwner() public { + function test_NonOwner_Revert() public { vm.startPrank(STRANGER); OffRamp.DynamicConfig memory dynamicConfig = _generateDynamicOffRampConfig(address(s_feeQuoter)); @@ -42,7 +42,7 @@ contract OffRamp_setDynamicConfig is OffRampSetup { s_offRamp.setDynamicConfig(dynamicConfig); } - function test_RevertWhen_FeeQuoterZeroAddress() public { + function test_FeeQuoterZeroAddress_Revert() public { OffRamp.DynamicConfig memory dynamicConfig = _generateDynamicOffRampConfig(address(0)); vm.expectRevert(OffRamp.ZeroAddressNotAllowed.selector); diff --git a/contracts/src/v0.8/ccip/test/offRamp/OffRamp/OffRamp.trialExecute.t.sol b/contracts/src/v0.8/ccip/test/offRamp/OffRamp/OffRamp.trialExecute.t.sol index 1acb4c4ee0a..8e944b91ab3 100644 --- a/contracts/src/v0.8/ccip/test/offRamp/OffRamp/OffRamp.trialExecute.t.sol +++ b/contracts/src/v0.8/ccip/test/offRamp/OffRamp/OffRamp.trialExecute.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import {Internal} from "../../../libraries/Internal.sol"; import {RateLimiter} from "../../../libraries/RateLimiter.sol"; @@ -14,19 +14,18 @@ contract OffRamp_trialExecute is OffRampSetup { _setupMultipleOffRamps(); } - function test_trialExecute() public { + function test_trialExecute_Success() public { uint256[] memory amounts = new uint256[](2); amounts[0] = 1000; amounts[1] = 50; + Internal.Any2EVMRampMessage memory message = _generateAny2EVMMessageWithTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1, 1, amounts); IERC20 dstToken0 = IERC20(s_destTokens[0]); - uint256 startingBalance = dstToken0.balanceOf(message.receiver); (Internal.MessageExecutionState newState, bytes memory err) = s_offRamp.trialExecute(message, new bytes[](message.tokenAmounts.length), new uint32[](0)); - assertEq(uint256(Internal.MessageExecutionState.SUCCESS), uint256(newState)); assertEq("", err); @@ -34,41 +33,48 @@ contract OffRamp_trialExecute is OffRampSetup { assertEq(startingBalance + amounts[0], dstToken0.balanceOf(message.receiver)); } - function test_trialExecute_TokenHandlingErrorIsCaught() public { - Internal.Any2EVMRampMessage memory message = _generateAny2EVMMessageWithMaybeRevertingSingleToken(1, 10); - address destPool = s_destPoolByToken[message.tokenAmounts[0].destTokenAddress]; + function test_TokenHandlingErrorIsCaught_Success() public { + uint256[] memory amounts = new uint256[](2); + amounts[0] = 1000; + amounts[1] = 50; IERC20 dstToken0 = IERC20(s_destTokens[0]); uint256 startingBalance = dstToken0.balanceOf(OWNER); bytes memory errorMessage = "Random token pool issue"; + + Internal.Any2EVMRampMessage memory message = + _generateAny2EVMMessageWithTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1, 1, amounts); s_maybeRevertingPool.setShouldRevert(errorMessage); (Internal.MessageExecutionState newState, bytes memory err) = s_offRamp.trialExecute(message, new bytes[](message.tokenAmounts.length), new uint32[](0)); assertEq(uint256(Internal.MessageExecutionState.FAILURE), uint256(newState)); - assertEq(abi.encodeWithSelector(OffRamp.TokenHandlingError.selector, destPool, errorMessage), err); + assertEq(abi.encodeWithSelector(OffRamp.TokenHandlingError.selector, errorMessage), err); // Expect the balance to remain the same assertEq(startingBalance, dstToken0.balanceOf(OWNER)); } - function test_trialExecute_RateLimitError() public { - Internal.Any2EVMRampMessage memory message = _generateAny2EVMMessageWithMaybeRevertingSingleToken(1, 10); - address destPool = s_destPoolByToken[message.tokenAmounts[0].destTokenAddress]; + function test_RateLimitError_Success() public { + uint256[] memory amounts = new uint256[](2); + amounts[0] = 1000; + amounts[1] = 50; bytes memory errorMessage = abi.encodeWithSelector(RateLimiter.BucketOverfilled.selector); + + Internal.Any2EVMRampMessage memory message = + _generateAny2EVMMessageWithTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1, 1, amounts); s_maybeRevertingPool.setShouldRevert(errorMessage); (Internal.MessageExecutionState newState, bytes memory err) = s_offRamp.trialExecute(message, new bytes[](message.tokenAmounts.length), new uint32[](0)); - assertEq(uint256(Internal.MessageExecutionState.FAILURE), uint256(newState)); - assertEq(abi.encodeWithSelector(OffRamp.TokenHandlingError.selector, destPool, errorMessage), err); + assertEq(abi.encodeWithSelector(OffRamp.TokenHandlingError.selector, errorMessage), err); } // TODO test actual pool exists but isn't compatible instead of just no pool - function test_trialExecute_TokenPoolIsNotAContract() public { + function test_TokenPoolIsNotAContract_Success() public { uint256[] memory amounts = new uint256[](2); amounts[0] = 10000; Internal.Any2EVMRampMessage memory message = diff --git a/contracts/src/v0.8/ccip/test/offRamp/OffRamp/OffRampSetup.t.sol b/contracts/src/v0.8/ccip/test/offRamp/OffRamp/OffRampSetup.t.sol index daf496c9d75..8e33f05c61d 100644 --- a/contracts/src/v0.8/ccip/test/offRamp/OffRamp/OffRampSetup.t.sol +++ b/contracts/src/v0.8/ccip/test/offRamp/OffRamp/OffRampSetup.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import {IAny2EVMMessageReceiver} from "../../../interfaces/IAny2EVMMessageReceiver.sol"; import {IRMNRemote} from "../../../interfaces/IRMNRemote.sol"; @@ -70,7 +70,6 @@ contract OffRampSetup is FeeQuoterSetup, MultiOCR3BaseSetup { OffRamp.StaticConfig({ chainSelector: DEST_CHAIN_SELECTOR, rmnRemote: rmnRemote, - gasForCallExactCheck: GAS_FOR_CALL_EXACT_CHECK, tokenAdminRegistry: address(s_tokenAdminRegistry), nonceManager: address(nonceManager) }), @@ -195,36 +194,25 @@ contract OffRampSetup is FeeQuoterSetup, MultiOCR3BaseSetup { return _generateAny2EVMMessage(sourceChainSelector, onRamp, sequenceNumber, tokenAmounts, false); } - function _generateAny2EVMMessageWithMaybeRevertingSingleToken( - uint64 sequenceNumber, - uint256 amount - ) internal view returns (Internal.Any2EVMRampMessage memory) { - Client.EVMTokenAmount[] memory tokenAmounts = new Client.EVMTokenAmount[](1); - tokenAmounts[0].token = s_sourceTokens[1]; - tokenAmounts[0].amount = amount; - - return _generateAny2EVMMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1, sequenceNumber, tokenAmounts, false); - } - function _generateAny2EVMMessage( uint64 sourceChainSelector, bytes memory onRamp, uint64 sequenceNumber, - Client.EVMTokenAmount[] memory sourceTokenAmounts, + Client.EVMTokenAmount[] memory tokenAmounts, bool allowOutOfOrderExecution ) internal view returns (Internal.Any2EVMRampMessage memory) { bytes memory data = abi.encode(0); Internal.Any2EVMTokenTransfer[] memory any2EVMTokenTransfer = - new Internal.Any2EVMTokenTransfer[](sourceTokenAmounts.length); + new Internal.Any2EVMTokenTransfer[](tokenAmounts.length); // Correctly set the TokenDataPayload for each token. Tokens have to be set up in the TokenSetup. - for (uint256 i = 0; i < sourceTokenAmounts.length; ++i) { + for (uint256 i = 0; i < tokenAmounts.length; ++i) { any2EVMTokenTransfer[i] = Internal.Any2EVMTokenTransfer({ - sourcePoolAddress: abi.encode(s_sourcePoolByToken[sourceTokenAmounts[i].token]), - destTokenAddress: s_destTokenBySourceToken[sourceTokenAmounts[i].token], + sourcePoolAddress: abi.encode(s_sourcePoolByToken[tokenAmounts[i].token]), + destTokenAddress: s_destTokenBySourceToken[tokenAmounts[i].token], extraData: "", - amount: sourceTokenAmounts[i].amount, + amount: tokenAmounts[i].amount, destGasAmount: DEFAULT_TOKEN_DEST_GAS_OVERHEAD }); } @@ -349,7 +337,6 @@ contract OffRampSetup is FeeQuoterSetup, MultiOCR3BaseSetup { s_offRamp = new OffRampHelper( OffRamp.StaticConfig({ chainSelector: DEST_CHAIN_SELECTOR, - gasForCallExactCheck: GAS_FOR_CALL_EXACT_CHECK, rmnRemote: s_mockRMNRemote, tokenAdminRegistry: address(s_tokenAdminRegistry), nonceManager: address(s_inboundNonceManager) @@ -373,7 +360,7 @@ contract OffRampSetup is FeeQuoterSetup, MultiOCR3BaseSetup { } function _commit(OffRamp.CommitReport memory commitReport, uint64 sequenceNumber) internal { - bytes32[2] memory reportContext = [s_configDigestCommit, bytes32(uint256(sequenceNumber))]; + 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, F + 1); @@ -385,7 +372,7 @@ contract OffRampSetup is FeeQuoterSetup, MultiOCR3BaseSetup { function _execute( Internal.ExecutionReport[] memory reports ) internal { - bytes32[2] memory reportContext = [s_configDigestExec, s_configDigestExec]; + 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/contracts/src/v0.8/ccip/test/onRamp/OnRamp/OnRamp.applyDestChainConfigUpdates.t.sol b/contracts/src/v0.8/ccip/test/onRamp/OnRamp/OnRamp.applyDestChainConfigUpdates.t.sol index ff385104f9b..2b99fd423be 100644 --- a/contracts/src/v0.8/ccip/test/onRamp/OnRamp/OnRamp.applyDestChainConfigUpdates.t.sol +++ b/contracts/src/v0.8/ccip/test/onRamp/OnRamp/OnRamp.applyDestChainConfigUpdates.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import {IRouter} from "../../../interfaces/IRouter.sol"; @@ -7,7 +7,7 @@ import {OnRamp} from "../../../onRamp/OnRamp.sol"; import {OnRampSetup} from "./OnRampSetup.t.sol"; contract OnRamp_applyDestChainConfigUpdates is OnRampSetup { - function test_ApplyDestChainConfigUpdates() external { + function test_ApplyDestChainConfigUpdates_Success() external { OnRamp.DestChainConfigArgs[] memory configArgs = new OnRamp.DestChainConfigArgs[](1); configArgs[0].destChainSelector = DEST_CHAIN_SELECTOR; @@ -53,7 +53,7 @@ contract OnRamp_applyDestChainConfigUpdates is OnRampSetup { assertEq(numLogs, vm.getRecordedLogs().length); // indicates no changes made } - function test_RevertWhen_ApplyDestChainConfigUpdates_WithInvalidChainSelector() external { + function test_ApplyDestChainConfigUpdates_WithInvalidChainSelector_Revert() external { OnRamp.DestChainConfigArgs[] memory configArgs = new OnRamp.DestChainConfigArgs[](1); configArgs[0].destChainSelector = 0; // invalid vm.expectRevert(abi.encodeWithSelector(OnRamp.InvalidDestChainConfig.selector, 0)); @@ -62,7 +62,7 @@ contract OnRamp_applyDestChainConfigUpdates is OnRampSetup { } contract OnRamp_applyAllowlistUpdates is OnRampSetup { - function test_applyAllowlistUpdates() public { + function test_applyAllowlistUpdates_Success() public { OnRamp.DestChainConfigArgs[] memory configArgs = new OnRamp.DestChainConfigArgs[](2); configArgs[0] = OnRamp.DestChainConfigArgs({ destChainSelector: DEST_CHAIN_SELECTOR, @@ -162,7 +162,7 @@ contract OnRamp_applyAllowlistUpdates is OnRampSetup { assertTrue(isActive); } - function test_RevertWhen_applyAllowlistUpdates() public { + function test_applyAllowlistUpdates_Revert() public { OnRamp.DestChainConfigArgs[] memory configArgs = new OnRamp.DestChainConfigArgs[](2); configArgs[0] = OnRamp.DestChainConfigArgs({ destChainSelector: DEST_CHAIN_SELECTOR, diff --git a/contracts/src/v0.8/ccip/test/onRamp/OnRamp/OnRamp.constructor.t.sol b/contracts/src/v0.8/ccip/test/onRamp/OnRamp/OnRamp.constructor.t.sol index 70153562e54..1e31a2a1377 100644 --- a/contracts/src/v0.8/ccip/test/onRamp/OnRamp/OnRamp.constructor.t.sol +++ b/contracts/src/v0.8/ccip/test/onRamp/OnRamp/OnRamp.constructor.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import {IRMNRemote} from "../../../interfaces/IRMNRemote.sol"; import {IRouter} from "../../../interfaces/IRouter.sol"; @@ -10,7 +10,7 @@ import {OnRampHelper} from "../../helpers/OnRampHelper.sol"; import {OnRampSetup} from "./OnRampSetup.t.sol"; contract OnRamp_constructor is OnRampSetup { - function test_Constructor() public { + function test_Constructor_Success() public { OnRamp.StaticConfig memory staticConfig = OnRamp.StaticConfig({ chainSelector: SOURCE_CHAIN_SELECTOR, rmnRemote: s_mockRMNRemote, @@ -41,7 +41,7 @@ contract OnRamp_constructor is OnRampSetup { assertEq(1, s_onRamp.getExpectedNextSequenceNumber(DEST_CHAIN_SELECTOR)); } - function test_RevertWhen_Constructor_EnableAllowList_ForwardFromRouter() public { + function test_Constructor_EnableAllowList_ForwardFromRouter_Reverts() public { OnRamp.StaticConfig memory staticConfig = OnRamp.StaticConfig({ chainSelector: SOURCE_CHAIN_SELECTOR, rmnRemote: s_mockRMNRemote, @@ -74,7 +74,7 @@ contract OnRamp_constructor is OnRampSetup { tempOnRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, 0, OWNER); } - function test_RevertWhen_Constructor_InvalidConfigChainSelectorEqZero() public { + function test_Constructor_InvalidConfigChainSelectorEqZero_Revert() public { vm.expectRevert(OnRamp.InvalidConfig.selector); new OnRampHelper( OnRamp.StaticConfig({ @@ -88,7 +88,7 @@ contract OnRamp_constructor is OnRampSetup { ); } - function test_RevertWhen_Constructor_InvalidConfigRMNProxyEqAddressZero() public { + function test_Constructor_InvalidConfigRMNProxyEqAddressZero_Revert() public { vm.expectRevert(OnRamp.InvalidConfig.selector); s_onRamp = new OnRampHelper( OnRamp.StaticConfig({ @@ -102,7 +102,7 @@ contract OnRamp_constructor is OnRampSetup { ); } - function test_RevertWhen_Constructor_InvalidConfigNonceManagerEqAddressZero() public { + function test_Constructor_InvalidConfigNonceManagerEqAddressZero_Revert() public { vm.expectRevert(OnRamp.InvalidConfig.selector); new OnRampHelper( OnRamp.StaticConfig({ @@ -116,7 +116,7 @@ contract OnRamp_constructor is OnRampSetup { ); } - function test_RevertWhen_Constructor_InvalidConfigTokenAdminRegistryEqAddressZero() public { + function test_Constructor_InvalidConfigTokenAdminRegistryEqAddressZero_Revert() public { vm.expectRevert(OnRamp.InvalidConfig.selector); new OnRampHelper( OnRamp.StaticConfig({ diff --git a/contracts/src/v0.8/ccip/test/onRamp/OnRamp/OnRamp.forwardFromRouter.t.sol b/contracts/src/v0.8/ccip/test/onRamp/OnRamp/OnRamp.forwardFromRouter.t.sol index 8168cff7e1c..764cd44df22 100644 --- a/contracts/src/v0.8/ccip/test/onRamp/OnRamp/OnRamp.forwardFromRouter.t.sol +++ b/contracts/src/v0.8/ccip/test/onRamp/OnRamp/OnRamp.forwardFromRouter.t.sol @@ -1,10 +1,10 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import {IMessageInterceptor} from "../../../interfaces/IMessageInterceptor.sol"; import {IRouter} from "../../../interfaces/IRouter.sol"; -import {BurnMintERC20} from "../../../../shared/token/ERC20/BurnMintERC20.sol"; +import {BurnMintERC677} from "../../../../shared/token/ERC677/BurnMintERC677.sol"; import {FeeQuoter} from "../../../FeeQuoter.sol"; import {Client} from "../../../libraries/Client.sol"; import {Internal} from "../../../libraries/Internal.sol"; @@ -68,7 +68,7 @@ contract OnRamp_forwardFromRouter is OnRampSetup { s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, feeAmount, OWNER); } - function test_ForwardFromRouter_ConfigurableSourceRouter() public { + function test_ForwardFromRouter_Success_ConfigurableSourceRouter() public { Client.EVM2AnyMessage memory message = _generateEmptyMessage(); message.extraArgs = Client._argsToBytes(Client.EVMExtraArgsV1({gasLimit: GAS_LIMIT * 2})); uint256 feeAmount = 1234567890; @@ -117,7 +117,7 @@ contract OnRamp_forwardFromRouter is OnRampSetup { s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, feeAmount, OWNER); } - function test_ForwardFromRouter() public { + function test_ForwardFromRouter_Success() public { Client.EVM2AnyMessage memory message = _generateEmptyMessage(); uint256 feeAmount = 1234567890; @@ -129,7 +129,7 @@ contract OnRamp_forwardFromRouter is OnRampSetup { s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, feeAmount, OWNER); } - function test_ForwardFromRouterExtraArgsV2() public { + function test_ForwardFromRouterExtraArgsV2_Success() public { Client.EVM2AnyMessage memory message = _generateEmptyMessage(); message.extraArgs = abi.encodeWithSelector( Client.EVM_EXTRA_ARGS_V2_TAG, Client.EVMExtraArgsV2({gasLimit: GAS_LIMIT * 2, allowOutOfOrderExecution: false}) @@ -143,7 +143,7 @@ contract OnRamp_forwardFromRouter is OnRampSetup { s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, feeAmount, OWNER); } - function test_ForwardFromRouterExtraArgsV2AllowOutOfOrderTrue() public { + function test_ForwardFromRouterExtraArgsV2AllowOutOfOrderTrue_Success() public { Client.EVM2AnyMessage memory message = _generateEmptyMessage(); message.extraArgs = abi.encodeWithSelector( Client.EVM_EXTRA_ARGS_V2_TAG, Client.EVMExtraArgsV2({gasLimit: GAS_LIMIT * 2, allowOutOfOrderExecution: true}) @@ -157,7 +157,7 @@ contract OnRamp_forwardFromRouter is OnRampSetup { s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, feeAmount, OWNER); } - function test_ShouldIncrementSeqNumAndNonce() public { + function test_ShouldIncrementSeqNumAndNonce_Success() public { Client.EVM2AnyMessage memory message = _generateEmptyMessage(); for (uint64 i = 1; i < 4; ++i) { @@ -176,7 +176,7 @@ contract OnRamp_forwardFromRouter is OnRampSetup { } } - function test_ShouldIncrementNonceOnlyOnOrdered() public { + function test_ShouldIncrementNonceOnlyOnOrdered_Success() public { Client.EVM2AnyMessage memory message = _generateEmptyMessage(); message.extraArgs = abi.encodeWithSelector( Client.EVM_EXTRA_ARGS_V2_TAG, Client.EVMExtraArgsV2({gasLimit: GAS_LIMIT * 2, allowOutOfOrderExecution: true}) @@ -212,7 +212,32 @@ contract OnRamp_forwardFromRouter is OnRampSetup { assertEq(IERC20(s_sourceFeeToken).balanceOf(address(s_onRamp)), feeAmount); } + function test_ShouldStoreNonLinkFees() public { + Client.EVM2AnyMessage memory message = _generateEmptyMessage(); + message.feeToken = s_sourceTokens[1]; + + uint256 feeAmount = 1234567890; + IERC20(s_sourceTokens[1]).transferFrom(OWNER, address(s_onRamp), feeAmount); + + // Calculate conversion done by prices contract + uint256 feeTokenPrice = s_feeQuoter.getTokenPrice(s_sourceTokens[1]).value; + uint256 linkTokenPrice = s_feeQuoter.getTokenPrice(s_sourceFeeToken).value; + uint256 conversionRate = (feeTokenPrice * 1e18) / linkTokenPrice; + uint256 expectedJuels = (feeAmount * conversionRate) / 1e18; + + vm.expectEmit(); + emit OnRamp.CCIPMessageSent(DEST_CHAIN_SELECTOR, 1, _messageToEvent(message, 1, 1, feeAmount, expectedJuels, OWNER)); + + s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, feeAmount, OWNER); + + assertEq(IERC20(s_sourceTokens[1]).balanceOf(address(s_onRamp)), feeAmount); + } + // Make sure any valid sender, receiver and feeAmount can be handled. + // @TODO Temporarily setting lower fuzz run as 256 triggers snapshot gas off by 1 error. + // https://github.com/foundry-rs/foundry/issues/5689 + /// forge-dynamicConfig: default.fuzz.runs = 32 + /// forge-dynamicConfig: ccip.fuzz.runs = 32 function testFuzz_ForwardFromRouter_Success(address originalSender, address receiver, uint96 feeTokenAmount) public { // To avoid RouterMustSetOriginalSender vm.assume(originalSender != address(0)); @@ -225,13 +250,14 @@ contract OnRamp_forwardFromRouter is OnRampSetup { destinationChainSelectors[0] = uint64(DEST_CHAIN_SELECTOR); address[] memory addAllowedList = new address[](1); addAllowedList[0] = originalSender; - OnRamp.AllowlistConfigArgs[] memory applyAllowlistConfigArgsItems = new OnRamp.AllowlistConfigArgs[](1); - applyAllowlistConfigArgsItems[0] = OnRamp.AllowlistConfigArgs({ + OnRamp.AllowlistConfigArgs memory allowlistConfigArgs = OnRamp.AllowlistConfigArgs({ allowlistEnabled: true, destChainSelector: DEST_CHAIN_SELECTOR, addedAllowlistedSenders: addAllowedList, removedAllowlistedSenders: new address[](0) }); + OnRamp.AllowlistConfigArgs[] memory applyAllowlistConfigArgsItems = new OnRamp.AllowlistConfigArgs[](1); + applyAllowlistConfigArgsItems[0] = allowlistConfigArgs; s_onRamp.applyAllowlistUpdates(applyAllowlistConfigArgsItems); vm.stopPrank(); @@ -245,6 +271,9 @@ contract OnRamp_forwardFromRouter is OnRampSetup { Internal.EVM2AnyRampMessage memory expectedEvent = _messageToEvent(message, 1, 1, feeTokenAmount, originalSender); + vm.expectEmit(); + emit OnRamp.CCIPMessageSent(DEST_CHAIN_SELECTOR, expectedEvent.header.sequenceNumber, expectedEvent); + // Assert the message Id is correct assertEq( expectedEvent.header.messageId, @@ -252,7 +281,7 @@ contract OnRamp_forwardFromRouter is OnRampSetup { ); } - function test_forwardFromRouter_WithInterception() public { + function test_forwardFromRouter_WithInterception_Success() public { _enableOutboundMessageInterceptor(); Client.EVM2AnyMessage memory message = _generateEmptyMessage(); @@ -272,7 +301,7 @@ contract OnRamp_forwardFromRouter is OnRampSetup { // Reverts - function test_RevertWhen_Paused() public { + function test_Paused_Revert() public { // We pause by disabling the whitelist vm.stopPrank(); vm.startPrank(OWNER); @@ -281,7 +310,7 @@ contract OnRamp_forwardFromRouter is OnRampSetup { s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, _generateEmptyMessage(), 0, OWNER); } - function test_RevertWhen_InvalidExtraArgsTag() public { + function test_InvalidExtraArgsTag_Revert() public { Client.EVM2AnyMessage memory message = _generateEmptyMessage(); message.extraArgs = bytes("bad args"); @@ -290,26 +319,26 @@ contract OnRamp_forwardFromRouter is OnRampSetup { s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, 0, OWNER); } - function test_RevertWhen_Permissions() public { + function test_Permissions_Revert() public { vm.stopPrank(); vm.startPrank(OWNER); vm.expectRevert(OnRamp.MustBeCalledByRouter.selector); s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, _generateEmptyMessage(), 0, OWNER); } - function test_RevertWhen_OriginalSender() public { + function test_OriginalSender_Revert() public { vm.expectRevert(OnRamp.RouterMustSetOriginalSender.selector); s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, _generateEmptyMessage(), 0, address(0)); } - function test_RevertWhen_UnAllowedOriginalSender() public { + function test_UnAllowedOriginalSender_Revert() public { vm.stopPrank(); vm.startPrank(STRANGER); vm.expectRevert(abi.encodeWithSelector(OnRamp.SenderNotAllowed.selector, STRANGER)); s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, _generateEmptyMessage(), 0, STRANGER); } - function test_RevertWhen_MessageInterceptionError() public { + function test_MessageInterceptionError_Revert() public { _enableOutboundMessageInterceptor(); Client.EVM2AnyMessage memory message = _generateEmptyMessage(); @@ -328,7 +357,7 @@ contract OnRamp_forwardFromRouter is OnRampSetup { s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, feeAmount, OWNER); } - function test_RevertWhen_MultiCannotSendZeroTokens() public { + function test_MultiCannotSendZeroTokens_Revert() public { Client.EVM2AnyMessage memory message = _generateEmptyMessage(); message.tokenAmounts = new Client.EVMTokenAmount[](1); message.tokenAmounts[0].amount = 0; @@ -337,7 +366,7 @@ contract OnRamp_forwardFromRouter is OnRampSetup { s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, 0, OWNER); } - function test_RevertWhen_UnsupportedToken() public { + function test_UnsupportedToken_Revert() public { address wrongToken = address(1); Client.EVM2AnyMessage memory message = _generateEmptyMessage(); @@ -360,7 +389,7 @@ contract OnRamp_forwardFromRouter is OnRampSetup { s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, 0, OWNER); } - function test_RevertWhen_forwardFromRouter_UnsupportedToken() public { + function test_forwardFromRouter_UnsupportedToken_Revert() public { Client.EVM2AnyMessage memory message = _generateEmptyMessage(); message.tokenAmounts = new Client.EVMTokenAmount[](1); message.tokenAmounts[0].amount = 1; @@ -371,7 +400,7 @@ contract OnRamp_forwardFromRouter is OnRampSetup { s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, 0, OWNER); } - function test_RevertWhen_MessageFeeTooHigh() public { + function test_MesssageFeeTooHigh_Revert() public { Client.EVM2AnyMessage memory message = _generateEmptyMessage(); vm.expectRevert( @@ -381,37 +410,31 @@ contract OnRamp_forwardFromRouter is OnRampSetup { s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, MAX_MSG_FEES_JUELS + 1, OWNER); } - function test_RevertWhen_SourceTokenDataTooLarge() public { + function test_SourceTokenDataTooLarge_Revert() public { address sourceETH = s_sourceTokens[1]; vm.stopPrank(); vm.startPrank(OWNER); MaybeRevertingBurnMintTokenPool newPool = new MaybeRevertingBurnMintTokenPool( - BurnMintERC20(sourceETH), - DEFAULT_TOKEN_DECIMALS, - new address[](0), - address(s_mockRMNRemote), - address(s_sourceRouter) + BurnMintERC677(sourceETH), new address[](0), address(s_mockRMNRemote), address(s_sourceRouter) ); - BurnMintERC20(sourceETH).grantMintAndBurnRoles(address(newPool)); + BurnMintERC677(sourceETH).grantMintAndBurnRoles(address(newPool)); deal(address(sourceETH), address(newPool), type(uint256).max); // Add TokenPool to OnRamp s_tokenAdminRegistry.setPool(sourceETH, address(newPool)); // Allow chain in TokenPool - bytes[] memory remotePoolAddresses = new bytes[](1); - remotePoolAddresses[0] = abi.encode(s_destTokenPool); - TokenPool.ChainUpdate[] memory chainUpdates = new TokenPool.ChainUpdate[](1); chainUpdates[0] = TokenPool.ChainUpdate({ remoteChainSelector: DEST_CHAIN_SELECTOR, - remotePoolAddresses: remotePoolAddresses, + remotePoolAddress: abi.encode(s_destTokenPool), remoteTokenAddress: abi.encode(s_destToken), + allowed: true, outboundRateLimiterConfig: _getOutboundRateLimiterConfig(), inboundRateLimiterConfig: _getInboundRateLimiterConfig() }); - newPool.applyChainUpdates(new uint64[](0), chainUpdates); + newPool.applyChainUpdates(chainUpdates); Client.EVM2AnyMessage memory message = _generateSingleTokenMessage(address(sourceETH), 1000); diff --git a/contracts/src/v0.8/ccip/test/onRamp/OnRamp/OnRamp.getFee.t.sol b/contracts/src/v0.8/ccip/test/onRamp/OnRamp/OnRamp.getFee.t.sol index 33e4a90cd5d..63a4c0c322e 100644 --- a/contracts/src/v0.8/ccip/test/onRamp/OnRamp/OnRamp.getFee.t.sol +++ b/contracts/src/v0.8/ccip/test/onRamp/OnRamp/OnRamp.getFee.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import {FeeQuoter} from "../../../FeeQuoter.sol"; import {Client} from "../../../libraries/Client.sol"; @@ -10,7 +10,7 @@ import {OnRampSetup} from "./OnRampSetup.t.sol"; contract OnRamp_getFee is OnRampSetup { using USDPriceWith18Decimals for uint224; - function test_EmptyMessage() public view { + function test_EmptyMessage_Success() public view { address[2] memory testTokens = [s_sourceFeeToken, s_sourceRouter.getWrappedNative()]; uint224[2] memory feeTokenPrices = [s_feeTokenPrice, s_wrappedTokenPrice]; @@ -25,7 +25,7 @@ contract OnRamp_getFee is OnRampSetup { } } - function test_SingleTokenMessage() public view { + function test_SingleTokenMessage_Success() public view { address[2] memory testTokens = [s_sourceFeeToken, s_sourceRouter.getWrappedNative()]; uint224[2] memory feeTokenPrices = [s_feeTokenPrice, s_wrappedTokenPrice]; @@ -41,7 +41,7 @@ contract OnRamp_getFee is OnRampSetup { } } - function test_GetFeeOfZeroForTokenMessage() public { + function test_GetFeeOfZeroForTokenMessage_Success() public { Client.EVM2AnyMessage memory message = _generateEmptyMessage(); uint256 feeAmount = s_onRamp.getFee(DEST_CHAIN_SELECTOR, message); @@ -63,13 +63,13 @@ contract OnRamp_getFee is OnRampSetup { // Reverts - function test_RevertWhen_Unhealthy() public { + function test_Unhealthy_Revert() public { _setMockRMNChainCurse(DEST_CHAIN_SELECTOR, true); vm.expectRevert(abi.encodeWithSelector(OnRamp.CursedByRMN.selector, DEST_CHAIN_SELECTOR)); s_onRamp.getFee(DEST_CHAIN_SELECTOR, _generateEmptyMessage()); } - function test_RevertWhen_EnforceOutOfOrder() public { + function test_EnforceOutOfOrder_Revert() public { // Update dynamic config to enforce allowOutOfOrderExecution = true. vm.stopPrank(); vm.startPrank(OWNER); @@ -87,7 +87,7 @@ contract OnRamp_getFee is OnRampSetup { s_onRamp.getFee(DEST_CHAIN_SELECTOR, message); } - function test_RevertWhen_NotAFeeTokenButPricedToken() public { + function test_NotAFeeTokenButPricedToken_Revert() public { Client.EVM2AnyMessage memory message = _generateEmptyMessage(); message.feeToken = s_sourceTokens[1]; diff --git a/contracts/src/v0.8/ccip/test/onRamp/OnRamp/OnRamp.getSupportedTokens.t.sol b/contracts/src/v0.8/ccip/test/onRamp/OnRamp/OnRamp.getSupportedTokens.t.sol index 551b36a67f7..c04f3cf3d51 100644 --- a/contracts/src/v0.8/ccip/test/onRamp/OnRamp/OnRamp.getSupportedTokens.t.sol +++ b/contracts/src/v0.8/ccip/test/onRamp/OnRamp/OnRamp.getSupportedTokens.t.sol @@ -1,11 +1,11 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import {OnRamp} from "../../../onRamp/OnRamp.sol"; import {OnRampSetup} from "./OnRampSetup.t.sol"; contract OnRamp_getSupportedTokens is OnRampSetup { - function test_RevertWhen_GetSupportedTokens() public { + function test_GetSupportedTokens_Revert() public { vm.expectRevert(OnRamp.GetSupportedTokensFunctionalityRemovedCheckAdminRegistry.selector); s_onRamp.getSupportedTokens(DEST_CHAIN_SELECTOR); } diff --git a/contracts/src/v0.8/ccip/test/onRamp/OnRamp/OnRamp.getTokenPool.t.sol b/contracts/src/v0.8/ccip/test/onRamp/OnRamp/OnRamp.getTokenPool.t.sol index 2b3856eea5f..8612ce86e36 100644 --- a/contracts/src/v0.8/ccip/test/onRamp/OnRamp/OnRamp.getTokenPool.t.sol +++ b/contracts/src/v0.8/ccip/test/onRamp/OnRamp/OnRamp.getTokenPool.t.sol @@ -1,12 +1,12 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import {OnRampSetup} from "./OnRampSetup.t.sol"; import {IERC20} from "../../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; contract OnRamp_getTokenPool is OnRampSetup { - function test_GetTokenPool() public view { + function test_GetTokenPool_Success() public view { assertEq( s_sourcePoolByToken[s_sourceTokens[0]], address(s_onRamp.getPoolBySourceToken(DEST_CHAIN_SELECTOR, IERC20(s_sourceTokens[0]))) diff --git a/contracts/src/v0.8/ccip/test/onRamp/OnRamp/OnRamp.setDynamicConfig.t.sol b/contracts/src/v0.8/ccip/test/onRamp/OnRamp/OnRamp.setDynamicConfig.t.sol index 10839968dbe..057ed0a79dd 100644 --- a/contracts/src/v0.8/ccip/test/onRamp/OnRamp/OnRamp.setDynamicConfig.t.sol +++ b/contracts/src/v0.8/ccip/test/onRamp/OnRamp/OnRamp.setDynamicConfig.t.sol @@ -1,12 +1,12 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import {Ownable2Step} from "../../../../shared/access/Ownable2Step.sol"; import {OnRamp} from "../../../onRamp/OnRamp.sol"; import {OnRampSetup} from "./OnRampSetup.t.sol"; contract OnRamp_setDynamicConfig is OnRampSetup { - function test_setDynamicConfig() public { + function test_setDynamicConfig_Success() public { OnRamp.StaticConfig memory staticConfig = s_onRamp.getStaticConfig(); OnRamp.DynamicConfig memory newConfig = OnRamp.DynamicConfig({ feeQuoter: address(23423), @@ -27,7 +27,7 @@ contract OnRamp_setDynamicConfig is OnRampSetup { // Reverts - function test_RevertWhen_setDynamicConfig_InvalidConfigFeeQuoterEqAddressZero() public { + function test_setDynamicConfig_InvalidConfigFeeQuoterEqAddressZero_Revert() public { OnRamp.DynamicConfig memory newConfig = OnRamp.DynamicConfig({ feeQuoter: address(0), reentrancyGuardEntered: false, @@ -40,7 +40,7 @@ contract OnRamp_setDynamicConfig is OnRampSetup { s_onRamp.setDynamicConfig(newConfig); } - function test_RevertWhen_setDynamicConfig_InvalidConfigInvalidConfig() public { + function test_setDynamicConfig_InvalidConfigInvalidConfig_Revert() public { OnRamp.DynamicConfig memory newConfig = OnRamp.DynamicConfig({ feeQuoter: address(23423), reentrancyGuardEntered: false, @@ -55,7 +55,7 @@ contract OnRamp_setDynamicConfig is OnRampSetup { s_onRamp.setDynamicConfig(newConfig); } - function test_RevertWhen_setDynamicConfig_InvalidConfigFeeAggregatorEqAddressZero() public { + function test_setDynamicConfig_InvalidConfigFeeAggregatorEqAddressZero_Revert() public { OnRamp.DynamicConfig memory newConfig = OnRamp.DynamicConfig({ feeQuoter: address(23423), reentrancyGuardEntered: false, @@ -68,13 +68,13 @@ contract OnRamp_setDynamicConfig is OnRampSetup { s_onRamp.setDynamicConfig(newConfig); } - function test_RevertWhen_setDynamicConfig_InvalidConfigOnlyOwner() public { + function test_setDynamicConfig_InvalidConfigOnlyOwner_Revert() public { vm.startPrank(STRANGER); vm.expectRevert(Ownable2Step.OnlyCallableByOwner.selector); s_onRamp.setDynamicConfig(_generateDynamicOnRampConfig(address(2))); } - function test_RevertWhen_setDynamicConfig_InvalidConfigReentrancyGuardEnteredEqTrue() public { + function test_setDynamicConfig_InvalidConfigReentrancyGuardEnteredEqTrue_Revert() public { OnRamp.DynamicConfig memory newConfig = OnRamp.DynamicConfig({ feeQuoter: address(23423), reentrancyGuardEntered: true, diff --git a/contracts/src/v0.8/ccip/test/onRamp/OnRamp/OnRamp.withdrawFeeTokens.t.sol b/contracts/src/v0.8/ccip/test/onRamp/OnRamp/OnRamp.withdrawFeeTokens.t.sol index 16b1246e90c..2af7242150a 100644 --- a/contracts/src/v0.8/ccip/test/onRamp/OnRamp/OnRamp.withdrawFeeTokens.t.sol +++ b/contracts/src/v0.8/ccip/test/onRamp/OnRamp/OnRamp.withdrawFeeTokens.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import {Client} from "../../../libraries/Client.sol"; import {OnRamp} from "../../../onRamp/OnRamp.sol"; @@ -57,7 +57,7 @@ contract OnRamp_withdrawFeeTokens is OnRampSetup { } } - function test_WithdrawFeeTokens() public { + function test_WithdrawFeeTokens_Success() public { vm.expectEmit(); emit OnRamp.FeeTokenWithdrawn(FEE_AGGREGATOR, s_sourceFeeToken, s_nopFees[s_sourceFeeToken]); diff --git a/contracts/src/v0.8/ccip/test/onRamp/OnRamp/OnRampSetup.t.sol b/contracts/src/v0.8/ccip/test/onRamp/OnRamp/OnRampSetup.t.sol index e310a733bc6..ead9e7088ce 100644 --- a/contracts/src/v0.8/ccip/test/onRamp/OnRamp/OnRampSetup.t.sol +++ b/contracts/src/v0.8/ccip/test/onRamp/OnRamp/OnRampSetup.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import {IRouter} from "../../../interfaces/IRouter.sol"; @@ -75,6 +75,7 @@ contract OnRampSetup is FeeQuoterFeeSetup { return _messageToEvent( message, SOURCE_CHAIN_SELECTOR, + DEST_CHAIN_SELECTOR, seqNum, nonce, feeTokenAmount, @@ -88,6 +89,7 @@ contract OnRampSetup is FeeQuoterFeeSetup { function _messageToEvent( Client.EVM2AnyMessage memory message, uint64 sourceChainSelector, + uint64 destChainSelector, uint64 seqNum, uint64 nonce, uint256 feeTokenAmount, @@ -97,13 +99,13 @@ contract OnRampSetup is FeeQuoterFeeSetup { TokenAdminRegistry tokenAdminRegistry ) internal view returns (Internal.EVM2AnyRampMessage memory) { Client.EVMExtraArgsV2 memory extraArgs = - s_feeQuoter.parseEVMExtraArgsFromBytes(message.extraArgs, DEST_CHAIN_SELECTOR); + s_feeQuoter.parseEVMExtraArgsFromBytes(message.extraArgs, destChainSelector); Internal.EVM2AnyRampMessage memory messageEvent = Internal.EVM2AnyRampMessage({ header: Internal.RampMessageHeader({ messageId: "", sourceChainSelector: sourceChainSelector, - destChainSelector: DEST_CHAIN_SELECTOR, + destChainSelector: destChainSelector, sequenceNumber: seqNum, nonce: extraArgs.allowOutOfOrderExecution ? 0 : nonce }), diff --git a/contracts/src/v0.8/ccip/test/pools/BurnFromMintTokenPool/BurnFromMintTokenPool.lockOrBurn.t.sol b/contracts/src/v0.8/ccip/test/pools/BurnFromMintTokenPool/BurnFromMintTokenPool.lockOrBurn.t.sol index bbdbd6c83ba..5074d573e2f 100644 --- a/contracts/src/v0.8/ccip/test/pools/BurnFromMintTokenPool/BurnFromMintTokenPool.lockOrBurn.t.sol +++ b/contracts/src/v0.8/ccip/test/pools/BurnFromMintTokenPool/BurnFromMintTokenPool.lockOrBurn.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import {Pool} from "../../../libraries/Pool.sol"; import {RateLimiter} from "../../../libraries/RateLimiter.sol"; @@ -9,19 +9,19 @@ import {BurnFromMintTokenPoolSetup} from "./BurnFromMintTokenPoolSetup.t.sol"; import {IERC20} from "../../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; contract BurnFromMintTokenPool_lockOrBurn is BurnFromMintTokenPoolSetup { - function test_setup() public view { - assertEq(address(s_burnMintERC20), address(s_pool.getToken())); - assertEq(address(s_mockRMNRemote), s_pool.getRmnProxy()); + function test_setup_Success() public view { + assertEq(address(s_burnMintERC677), address(s_pool.getToken())); + assertEq(address(s_mockRMN), s_pool.getRmnProxy()); assertEq(false, s_pool.getAllowListEnabled()); - assertEq(type(uint256).max, s_burnMintERC20.allowance(address(s_pool), address(s_pool))); - assertEq("BurnFromMintTokenPool 1.5.1", s_pool.typeAndVersion()); + assertEq(type(uint256).max, s_burnMintERC677.allowance(address(s_pool), address(s_pool))); + assertEq("BurnFromMintTokenPool 1.5.0", s_pool.typeAndVersion()); } - function test_PoolBurn() public { + function test_PoolBurn_Success() public { uint256 burnAmount = 20_000e18; - deal(address(s_burnMintERC20), address(s_pool), burnAmount); - assertEq(s_burnMintERC20.balanceOf(address(s_pool)), burnAmount); + deal(address(s_burnMintERC677), address(s_pool), burnAmount); + assertEq(s_burnMintERC677.balanceOf(address(s_pool)), burnAmount); vm.startPrank(s_burnMintOnRamp); @@ -35,7 +35,7 @@ contract BurnFromMintTokenPool_lockOrBurn is BurnFromMintTokenPoolSetup { emit TokenPool.Burned(address(s_burnMintOnRamp), burnAmount); bytes4 expectedSignature = bytes4(keccak256("burnFrom(address,uint256)")); - vm.expectCall(address(s_burnMintERC20), abi.encodeWithSelector(expectedSignature, address(s_pool), burnAmount)); + vm.expectCall(address(s_burnMintERC677), abi.encodeWithSelector(expectedSignature, address(s_pool), burnAmount)); s_pool.lockOrBurn( Pool.LockOrBurnInV1({ @@ -43,18 +43,17 @@ contract BurnFromMintTokenPool_lockOrBurn is BurnFromMintTokenPoolSetup { receiver: bytes(""), amount: burnAmount, remoteChainSelector: DEST_CHAIN_SELECTOR, - localToken: address(s_burnMintERC20) + localToken: address(s_burnMintERC677) }) ); - assertEq(s_burnMintERC20.balanceOf(address(s_pool)), 0); + assertEq(s_burnMintERC677.balanceOf(address(s_pool)), 0); } // Should not burn tokens if cursed. - function test_RevertWhen_PoolBurnRevertNotHealthy() public { - vm.mockCall(address(s_mockRMNRemote), abi.encodeWithSignature("isCursed(bytes16)"), abi.encode(true)); - - uint256 before = s_burnMintERC20.balanceOf(address(s_pool)); + function test_PoolBurnRevertNotHealthy_Revert() public { + s_mockRMN.setGlobalCursed(true); + uint256 before = s_burnMintERC677.balanceOf(address(s_pool)); vm.startPrank(s_burnMintOnRamp); vm.expectRevert(TokenPool.CursedByRMN.selector); @@ -64,14 +63,14 @@ contract BurnFromMintTokenPool_lockOrBurn is BurnFromMintTokenPoolSetup { receiver: bytes(""), amount: 1e5, remoteChainSelector: DEST_CHAIN_SELECTOR, - localToken: address(s_burnMintERC20) + localToken: address(s_burnMintERC677) }) ); - assertEq(s_burnMintERC20.balanceOf(address(s_pool)), before); + assertEq(s_burnMintERC677.balanceOf(address(s_pool)), before); } - function test_RevertWhen_ChainNotAllowed() public { + function test_ChainNotAllowed_Revert() public { uint64 wrongChainSelector = 8838833; vm.expectRevert(abi.encodeWithSelector(TokenPool.ChainNotAllowed.selector, wrongChainSelector)); s_pool.releaseOrMint( @@ -79,7 +78,7 @@ contract BurnFromMintTokenPool_lockOrBurn is BurnFromMintTokenPoolSetup { originalSender: bytes(""), receiver: OWNER, amount: 1, - localToken: address(s_burnMintERC20), + localToken: address(s_burnMintERC677), remoteChainSelector: wrongChainSelector, sourcePoolAddress: _generateSourceTokenData().sourcePoolAddress, sourcePoolData: _generateSourceTokenData().extraData, diff --git a/contracts/src/v0.8/ccip/test/pools/BurnFromMintTokenPool/BurnFromMintTokenPoolSetup.t.sol b/contracts/src/v0.8/ccip/test/pools/BurnFromMintTokenPool/BurnFromMintTokenPoolSetup.t.sol index cf11f467579..d743550b153 100644 --- a/contracts/src/v0.8/ccip/test/pools/BurnFromMintTokenPool/BurnFromMintTokenPoolSetup.t.sol +++ b/contracts/src/v0.8/ccip/test/pools/BurnFromMintTokenPool/BurnFromMintTokenPoolSetup.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import {BurnFromMintTokenPool} from "../../../pools/BurnFromMintTokenPool.sol"; import {BurnMintSetup} from "../BurnMintTokenPool/BurnMintSetup.t.sol"; @@ -10,10 +10,8 @@ contract BurnFromMintTokenPoolSetup is BurnMintSetup { function setUp() public virtual override { BurnMintSetup.setUp(); - s_pool = new BurnFromMintTokenPool( - s_burnMintERC20, DEFAULT_TOKEN_DECIMALS, new address[](0), address(s_mockRMNRemote), address(s_sourceRouter) - ); - s_burnMintERC20.grantMintAndBurnRoles(address(s_pool)); + s_pool = new BurnFromMintTokenPool(s_burnMintERC677, new address[](0), address(s_mockRMN), address(s_sourceRouter)); + s_burnMintERC677.grantMintAndBurnRoles(address(s_pool)); _applyChainUpdates(address(s_pool)); } diff --git a/contracts/src/v0.8/ccip/test/pools/BurnMintTokenPool/BurnMintSetup.t.sol b/contracts/src/v0.8/ccip/test/pools/BurnMintTokenPool/BurnMintSetup.t.sol index 175f5aaece4..767ebfc9bfc 100644 --- a/contracts/src/v0.8/ccip/test/pools/BurnMintTokenPool/BurnMintSetup.t.sol +++ b/contracts/src/v0.8/ccip/test/pools/BurnMintTokenPool/BurnMintSetup.t.sol @@ -1,14 +1,14 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; -import {BurnMintERC20} from "../../../../shared/token/ERC20/BurnMintERC20.sol"; +import {BurnMintERC677} from "../../../../shared/token/ERC677/BurnMintERC677.sol"; import {Router} from "../../../Router.sol"; import {BurnMintTokenPool} from "../../../pools/BurnMintTokenPool.sol"; import {TokenPool} from "../../../pools/TokenPool.sol"; -import {BaseTest} from "../../BaseTest.t.sol"; +import {RouterSetup} from "../../router/Router/RouterSetup.t.sol"; -contract BurnMintSetup is BaseTest { - BurnMintERC20 internal s_burnMintERC20; +contract BurnMintSetup is RouterSetup { + BurnMintERC677 internal s_burnMintERC677; address internal s_burnMintOffRamp = makeAddr("burn_mint_offRamp"); address internal s_burnMintOnRamp = makeAddr("burn_mint_onRamp"); @@ -16,27 +16,25 @@ contract BurnMintSetup is BaseTest { address internal s_remoteToken = makeAddr("remote_token"); function setUp() public virtual override { - super.setUp(); + RouterSetup.setUp(); - s_burnMintERC20 = new BurnMintERC20("Chainlink Token", "LINK", 18, 0, 0); + s_burnMintERC677 = new BurnMintERC677("Chainlink Token", "LINK", 18, 0); } function _applyChainUpdates( address pool ) internal { - bytes[] memory remotePoolAddresses = new bytes[](1); - remotePoolAddresses[0] = abi.encode(s_remoteBurnMintPool); - - TokenPool.ChainUpdate[] memory chainsToAdd = new TokenPool.ChainUpdate[](1); - chainsToAdd[0] = TokenPool.ChainUpdate({ + TokenPool.ChainUpdate[] memory chains = new TokenPool.ChainUpdate[](1); + chains[0] = TokenPool.ChainUpdate({ remoteChainSelector: DEST_CHAIN_SELECTOR, - remotePoolAddresses: remotePoolAddresses, + remotePoolAddress: abi.encode(s_remoteBurnMintPool), remoteTokenAddress: abi.encode(s_remoteToken), + allowed: true, outboundRateLimiterConfig: _getOutboundRateLimiterConfig(), inboundRateLimiterConfig: _getInboundRateLimiterConfig() }); - BurnMintTokenPool(pool).applyChainUpdates(new uint64[](0), chainsToAdd); + BurnMintTokenPool(pool).applyChainUpdates(chains); Router.OnRamp[] memory onRampUpdates = new Router.OnRamp[](1); onRampUpdates[0] = Router.OnRamp({destChainSelector: DEST_CHAIN_SELECTOR, onRamp: s_burnMintOnRamp}); diff --git a/contracts/src/v0.8/ccip/test/pools/BurnMintTokenPool/BurnMintTokenPool.lockOrBurn.t.sol b/contracts/src/v0.8/ccip/test/pools/BurnMintTokenPool/BurnMintTokenPool.lockOrBurn.t.sol index 7b19f2881d6..4c520af27b6 100644 --- a/contracts/src/v0.8/ccip/test/pools/BurnMintTokenPool/BurnMintTokenPool.lockOrBurn.t.sol +++ b/contracts/src/v0.8/ccip/test/pools/BurnMintTokenPool/BurnMintTokenPool.lockOrBurn.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import {Pool} from "../../../libraries/Pool.sol"; import {RateLimiter} from "../../../libraries/RateLimiter.sol"; @@ -15,28 +15,26 @@ contract BurnMintTokenPoolSetup is BurnMintSetup { function setUp() public virtual override { BurnMintSetup.setUp(); - s_pool = new BurnMintTokenPool( - s_burnMintERC20, DEFAULT_TOKEN_DECIMALS, new address[](0), address(s_mockRMNRemote), address(s_sourceRouter) - ); - s_burnMintERC20.grantMintAndBurnRoles(address(s_pool)); + s_pool = new BurnMintTokenPool(s_burnMintERC677, new address[](0), address(s_mockRMN), address(s_sourceRouter)); + s_burnMintERC677.grantMintAndBurnRoles(address(s_pool)); _applyChainUpdates(address(s_pool)); } } contract BurnMintTokenPool_lockOrBurn is BurnMintTokenPoolSetup { - function test_Setup() public view { - assertEq(address(s_burnMintERC20), address(s_pool.getToken())); - assertEq(address(s_mockRMNRemote), s_pool.getRmnProxy()); + function test_Setup_Success() public view { + assertEq(address(s_burnMintERC677), address(s_pool.getToken())); + assertEq(address(s_mockRMN), s_pool.getRmnProxy()); assertEq(false, s_pool.getAllowListEnabled()); - assertEq("BurnMintTokenPool 1.5.1", s_pool.typeAndVersion()); + assertEq("BurnMintTokenPool 1.5.0", s_pool.typeAndVersion()); } - function test_PoolBurn() public { + function test_PoolBurn_Success() public { uint256 burnAmount = 20_000e18; - deal(address(s_burnMintERC20), address(s_pool), burnAmount); - assertEq(s_burnMintERC20.balanceOf(address(s_pool)), burnAmount); + deal(address(s_burnMintERC677), address(s_pool), burnAmount); + assertEq(s_burnMintERC677.balanceOf(address(s_pool)), burnAmount); vm.startPrank(s_burnMintOnRamp); @@ -50,7 +48,7 @@ contract BurnMintTokenPool_lockOrBurn is BurnMintTokenPoolSetup { emit TokenPool.Burned(address(s_burnMintOnRamp), burnAmount); bytes4 expectedSignature = bytes4(keccak256("burn(uint256)")); - vm.expectCall(address(s_burnMintERC20), abi.encodeWithSelector(expectedSignature, burnAmount)); + vm.expectCall(address(s_burnMintERC677), abi.encodeWithSelector(expectedSignature, burnAmount)); s_pool.lockOrBurn( Pool.LockOrBurnInV1({ @@ -58,17 +56,17 @@ contract BurnMintTokenPool_lockOrBurn is BurnMintTokenPoolSetup { receiver: bytes(""), amount: burnAmount, remoteChainSelector: DEST_CHAIN_SELECTOR, - localToken: address(s_burnMintERC20) + localToken: address(s_burnMintERC677) }) ); - assertEq(s_burnMintERC20.balanceOf(address(s_pool)), 0); + assertEq(s_burnMintERC677.balanceOf(address(s_pool)), 0); } // Should not burn tokens if cursed. - function test_RevertWhen_PoolBurnRevertNotHealthy() public { - vm.mockCall(address(s_mockRMNRemote), abi.encodeWithSignature("isCursed(bytes16)"), abi.encode(true)); - uint256 before = s_burnMintERC20.balanceOf(address(s_pool)); + function test_PoolBurnRevertNotHealthy_Revert() public { + s_mockRMN.setGlobalCursed(true); + uint256 before = s_burnMintERC677.balanceOf(address(s_pool)); vm.startPrank(s_burnMintOnRamp); vm.expectRevert(TokenPool.CursedByRMN.selector); @@ -78,14 +76,14 @@ contract BurnMintTokenPool_lockOrBurn is BurnMintTokenPoolSetup { receiver: bytes(""), amount: 1e5, remoteChainSelector: DEST_CHAIN_SELECTOR, - localToken: address(s_burnMintERC20) + localToken: address(s_burnMintERC677) }) ); - assertEq(s_burnMintERC20.balanceOf(address(s_pool)), before); + assertEq(s_burnMintERC677.balanceOf(address(s_pool)), before); } - function test_RevertWhen_ChainNotAllowed() public { + function test_ChainNotAllowed_Revert() public { uint64 wrongChainSelector = 8838833; vm.expectRevert(abi.encodeWithSelector(TokenPool.ChainNotAllowed.selector, wrongChainSelector)); @@ -95,7 +93,7 @@ contract BurnMintTokenPool_lockOrBurn is BurnMintTokenPoolSetup { receiver: bytes(""), amount: 1, remoteChainSelector: wrongChainSelector, - localToken: address(s_burnMintERC20) + localToken: address(s_burnMintERC677) }) ); } diff --git a/contracts/src/v0.8/ccip/test/pools/BurnMintTokenPool/BurnMintTokenPool.releaseOrMint.t.sol b/contracts/src/v0.8/ccip/test/pools/BurnMintTokenPool/BurnMintTokenPool.releaseOrMint.t.sol index 88b96b1fef7..e16d4c7b59d 100644 --- a/contracts/src/v0.8/ccip/test/pools/BurnMintTokenPool/BurnMintTokenPool.releaseOrMint.t.sol +++ b/contracts/src/v0.8/ccip/test/pools/BurnMintTokenPool/BurnMintTokenPool.releaseOrMint.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import {Pool} from "../../../libraries/Pool.sol"; import {BurnMintTokenPool} from "../../../pools/BurnMintTokenPool.sol"; @@ -14,17 +14,15 @@ contract BurnMintTokenPoolSetup is BurnMintSetup { function setUp() public virtual override { BurnMintSetup.setUp(); - s_pool = new BurnMintTokenPool( - s_burnMintERC20, DEFAULT_TOKEN_DECIMALS, new address[](0), address(s_mockRMNRemote), address(s_sourceRouter) - ); - s_burnMintERC20.grantMintAndBurnRoles(address(s_pool)); + s_pool = new BurnMintTokenPool(s_burnMintERC677, new address[](0), address(s_mockRMN), address(s_sourceRouter)); + s_burnMintERC677.grantMintAndBurnRoles(address(s_pool)); _applyChainUpdates(address(s_pool)); } } contract BurnMintTokenPool_releaseOrMint is BurnMintTokenPoolSetup { - function test_PoolMint() public { + function test_PoolMint_Success() public { uint256 amount = 1e19; address receiver = makeAddr("receiver_address"); @@ -38,7 +36,7 @@ contract BurnMintTokenPool_releaseOrMint is BurnMintTokenPoolSetup { originalSender: bytes(""), receiver: receiver, amount: amount, - localToken: address(s_burnMintERC20), + localToken: address(s_burnMintERC677), remoteChainSelector: DEST_CHAIN_SELECTOR, sourcePoolAddress: abi.encode(s_remoteBurnMintPool), sourcePoolData: "", @@ -46,13 +44,13 @@ contract BurnMintTokenPool_releaseOrMint is BurnMintTokenPoolSetup { }) ); - assertEq(s_burnMintERC20.balanceOf(receiver), amount); + assertEq(s_burnMintERC677.balanceOf(receiver), amount); } - function test_RevertWhen_PoolMintNotHealthy() public { + function test_PoolMintNotHealthy_Revert() public { // Should not mint tokens if cursed. - vm.mockCall(address(s_mockRMNRemote), abi.encodeWithSignature("isCursed(bytes16)"), abi.encode(true)); - uint256 before = s_burnMintERC20.balanceOf(OWNER); + s_mockRMN.setGlobalCursed(true); + uint256 before = s_burnMintERC677.balanceOf(OWNER); vm.startPrank(s_burnMintOffRamp); vm.expectRevert(TokenPool.CursedByRMN.selector); @@ -61,7 +59,7 @@ contract BurnMintTokenPool_releaseOrMint is BurnMintTokenPoolSetup { originalSender: bytes(""), receiver: OWNER, amount: 1e5, - localToken: address(s_burnMintERC20), + localToken: address(s_burnMintERC677), remoteChainSelector: DEST_CHAIN_SELECTOR, sourcePoolAddress: _generateSourceTokenData().sourcePoolAddress, sourcePoolData: _generateSourceTokenData().extraData, @@ -69,10 +67,10 @@ contract BurnMintTokenPool_releaseOrMint is BurnMintTokenPoolSetup { }) ); - assertEq(s_burnMintERC20.balanceOf(OWNER), before); + assertEq(s_burnMintERC677.balanceOf(OWNER), before); } - function test_RevertWhen_ChainNotAllowed() public { + function test_ChainNotAllowed_Revert() public { uint64 wrongChainSelector = 8838833; vm.expectRevert(abi.encodeWithSelector(TokenPool.ChainNotAllowed.selector, wrongChainSelector)); @@ -81,7 +79,7 @@ contract BurnMintTokenPool_releaseOrMint is BurnMintTokenPoolSetup { originalSender: bytes(""), receiver: OWNER, amount: 1, - localToken: address(s_burnMintERC20), + localToken: address(s_burnMintERC677), remoteChainSelector: wrongChainSelector, sourcePoolAddress: _generateSourceTokenData().sourcePoolAddress, sourcePoolData: _generateSourceTokenData().extraData, diff --git a/contracts/src/v0.8/ccip/test/pools/BurnMintWithLockReleaseFlagTokenPool/BurnMintWithLockReleaseFlagTokenPool.lockOrBurn.t.sol b/contracts/src/v0.8/ccip/test/pools/BurnMintWithLockReleaseFlagTokenPool/BurnMintWithLockReleaseFlagTokenPool.lockOrBurn.t.sol index bc8de71d209..7392dc1ce83 100644 --- a/contracts/src/v0.8/ccip/test/pools/BurnMintWithLockReleaseFlagTokenPool/BurnMintWithLockReleaseFlagTokenPool.lockOrBurn.t.sol +++ b/contracts/src/v0.8/ccip/test/pools/BurnMintWithLockReleaseFlagTokenPool/BurnMintWithLockReleaseFlagTokenPool.lockOrBurn.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import {Pool} from "../../../libraries/Pool.sol"; import {RateLimiter} from "../../../libraries/RateLimiter.sol"; @@ -18,20 +18,20 @@ contract BurnMintWithLockReleaseFlagTokenPoolSetup is BurnMintSetup { BurnMintSetup.setUp(); s_pool = new BurnMintWithLockReleaseFlagTokenPool( - s_burnMintERC20, DEFAULT_TOKEN_DECIMALS, new address[](0), address(s_mockRMNRemote), address(s_sourceRouter) + s_burnMintERC677, new address[](0), address(s_mockRMN), address(s_sourceRouter) ); - s_burnMintERC20.grantMintAndBurnRoles(address(s_pool)); + s_burnMintERC677.grantMintAndBurnRoles(address(s_pool)); _applyChainUpdates(address(s_pool)); } } contract BurnMintWithLockReleaseFlagTokenPool_lockOrBurn is BurnMintWithLockReleaseFlagTokenPoolSetup { - function test_LockOrBurn_CorrectReturnData() public { + function test_LockOrBurn_CorrectReturnData_Success() public { uint256 burnAmount = 20_000e18; - deal(address(s_burnMintERC20), address(s_pool), burnAmount); - assertEq(s_burnMintERC20.balanceOf(address(s_pool)), burnAmount); + deal(address(s_burnMintERC677), address(s_pool), burnAmount); + assertEq(s_burnMintERC677.balanceOf(address(s_pool)), burnAmount); vm.startPrank(s_burnMintOnRamp); @@ -45,7 +45,7 @@ contract BurnMintWithLockReleaseFlagTokenPool_lockOrBurn is BurnMintWithLockRele emit TokenPool.Burned(address(s_burnMintOnRamp), burnAmount); bytes4 expectedSignature = bytes4(keccak256("burn(uint256)")); - vm.expectCall(address(s_burnMintERC20), abi.encodeWithSelector(expectedSignature, burnAmount)); + vm.expectCall(address(s_burnMintERC677), abi.encodeWithSelector(expectedSignature, burnAmount)); Pool.LockOrBurnOutV1 memory lockOrBurnOut = s_pool.lockOrBurn( Pool.LockOrBurnInV1({ @@ -53,11 +53,11 @@ contract BurnMintWithLockReleaseFlagTokenPool_lockOrBurn is BurnMintWithLockRele receiver: bytes(""), amount: burnAmount, remoteChainSelector: DEST_CHAIN_SELECTOR, - localToken: address(s_burnMintERC20) + localToken: address(s_burnMintERC677) }) ); - assertEq(s_burnMintERC20.balanceOf(address(s_pool)), 0); + assertEq(s_burnMintERC677.balanceOf(address(s_pool)), 0); assertEq(bytes4(lockOrBurnOut.destPoolData), LOCK_RELEASE_FLAG); } diff --git a/contracts/src/v0.8/ccip/test/pools/BurnWithFromMintTokenPool/BurnWithFromMintTokenPool.lockOrBurn.t.sol b/contracts/src/v0.8/ccip/test/pools/BurnWithFromMintTokenPool/BurnWithFromMintTokenPool.lockOrBurn.t.sol index 477f9e86430..7595bf76c69 100644 --- a/contracts/src/v0.8/ccip/test/pools/BurnWithFromMintTokenPool/BurnWithFromMintTokenPool.lockOrBurn.t.sol +++ b/contracts/src/v0.8/ccip/test/pools/BurnWithFromMintTokenPool/BurnWithFromMintTokenPool.lockOrBurn.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import {Pool} from "../../../libraries/Pool.sol"; import {RateLimiter} from "../../../libraries/RateLimiter.sol"; @@ -15,29 +15,28 @@ contract BurnWithFromMintTokenPoolSetup is BurnMintSetup { function setUp() public virtual override { BurnMintSetup.setUp(); - s_pool = new BurnWithFromMintTokenPool( - s_burnMintERC20, DEFAULT_TOKEN_DECIMALS, new address[](0), address(s_mockRMNRemote), address(s_sourceRouter) - ); - s_burnMintERC20.grantMintAndBurnRoles(address(s_pool)); + s_pool = + new BurnWithFromMintTokenPool(s_burnMintERC677, new address[](0), address(s_mockRMN), address(s_sourceRouter)); + s_burnMintERC677.grantMintAndBurnRoles(address(s_pool)); _applyChainUpdates(address(s_pool)); } } contract BurnWithFromMintTokenPool_lockOrBurn is BurnWithFromMintTokenPoolSetup { - function test_Setup() public view { - assertEq(address(s_burnMintERC20), address(s_pool.getToken())); - assertEq(address(s_mockRMNRemote), s_pool.getRmnProxy()); + function test_Setup_Success() public view { + assertEq(address(s_burnMintERC677), address(s_pool.getToken())); + assertEq(address(s_mockRMN), s_pool.getRmnProxy()); assertEq(false, s_pool.getAllowListEnabled()); - assertEq(type(uint256).max, s_burnMintERC20.allowance(address(s_pool), address(s_pool))); - assertEq("BurnWithFromMintTokenPool 1.5.1", s_pool.typeAndVersion()); + assertEq(type(uint256).max, s_burnMintERC677.allowance(address(s_pool), address(s_pool))); + assertEq("BurnWithFromMintTokenPool 1.5.0", s_pool.typeAndVersion()); } - function test_PoolBurn() public { + function test_PoolBurn_Success() public { uint256 burnAmount = 20_000e18; - deal(address(s_burnMintERC20), address(s_pool), burnAmount); - assertEq(s_burnMintERC20.balanceOf(address(s_pool)), burnAmount); + deal(address(s_burnMintERC677), address(s_pool), burnAmount); + assertEq(s_burnMintERC677.balanceOf(address(s_pool)), burnAmount); vm.startPrank(s_burnMintOnRamp); @@ -51,7 +50,7 @@ contract BurnWithFromMintTokenPool_lockOrBurn is BurnWithFromMintTokenPoolSetup emit TokenPool.Burned(address(s_burnMintOnRamp), burnAmount); bytes4 expectedSignature = bytes4(keccak256("burn(address,uint256)")); - vm.expectCall(address(s_burnMintERC20), abi.encodeWithSelector(expectedSignature, address(s_pool), burnAmount)); + vm.expectCall(address(s_burnMintERC677), abi.encodeWithSelector(expectedSignature, address(s_pool), burnAmount)); s_pool.lockOrBurn( Pool.LockOrBurnInV1({ @@ -59,17 +58,17 @@ contract BurnWithFromMintTokenPool_lockOrBurn is BurnWithFromMintTokenPoolSetup receiver: bytes(""), amount: burnAmount, remoteChainSelector: DEST_CHAIN_SELECTOR, - localToken: address(s_burnMintERC20) + localToken: address(s_burnMintERC677) }) ); - assertEq(s_burnMintERC20.balanceOf(address(s_pool)), 0); + assertEq(s_burnMintERC677.balanceOf(address(s_pool)), 0); } // Should not burn tokens if cursed. - function test_RevertWhen_PoolBurnRevertNotHealthy() public { - vm.mockCall(address(s_mockRMNRemote), abi.encodeWithSignature("isCursed(bytes16)"), abi.encode(true)); - uint256 before = s_burnMintERC20.balanceOf(address(s_pool)); + function test_PoolBurnRevertNotHealthy_Revert() public { + s_mockRMN.setGlobalCursed(true); + uint256 before = s_burnMintERC677.balanceOf(address(s_pool)); vm.startPrank(s_burnMintOnRamp); vm.expectRevert(TokenPool.CursedByRMN.selector); @@ -79,14 +78,14 @@ contract BurnWithFromMintTokenPool_lockOrBurn is BurnWithFromMintTokenPoolSetup receiver: bytes(""), amount: 1e5, remoteChainSelector: DEST_CHAIN_SELECTOR, - localToken: address(s_burnMintERC20) + localToken: address(s_burnMintERC677) }) ); - assertEq(s_burnMintERC20.balanceOf(address(s_pool)), before); + assertEq(s_burnMintERC677.balanceOf(address(s_pool)), before); } - function test_RevertWhen_ChainNotAllowed() public { + function test_ChainNotAllowed_Revert() public { uint64 wrongChainSelector = 8838833; vm.expectRevert(abi.encodeWithSelector(TokenPool.ChainNotAllowed.selector, wrongChainSelector)); s_pool.releaseOrMint( @@ -94,7 +93,7 @@ contract BurnWithFromMintTokenPool_lockOrBurn is BurnWithFromMintTokenPoolSetup originalSender: bytes(""), receiver: OWNER, amount: 1, - localToken: address(s_burnMintERC20), + localToken: address(s_burnMintERC677), remoteChainSelector: wrongChainSelector, sourcePoolAddress: _generateSourceTokenData().sourcePoolAddress, sourcePoolData: _generateSourceTokenData().extraData, diff --git a/contracts/src/v0.8/ccip/test/pools/LockReleaseTokenPool/LockReleaseTokenPool.canAcceptLiquidity.t.sol b/contracts/src/v0.8/ccip/test/pools/LockReleaseTokenPool/LockReleaseTokenPool.canAcceptLiquidity.t.sol index e4bebbf1820..9a124572f96 100644 --- a/contracts/src/v0.8/ccip/test/pools/LockReleaseTokenPool/LockReleaseTokenPool.canAcceptLiquidity.t.sol +++ b/contracts/src/v0.8/ccip/test/pools/LockReleaseTokenPool/LockReleaseTokenPool.canAcceptLiquidity.t.sol @@ -1,16 +1,15 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import {LockReleaseTokenPool} from "../../../pools/LockReleaseTokenPool.sol"; import {LockReleaseTokenPoolSetup} from "./LockReleaseTokenPoolSetup.t.sol"; contract LockReleaseTokenPool_canAcceptLiquidity is LockReleaseTokenPoolSetup { - function test_CanAcceptLiquidity() public { + function test_CanAcceptLiquidity_Success() public { assertEq(true, s_lockReleaseTokenPool.canAcceptLiquidity()); - s_lockReleaseTokenPool = new LockReleaseTokenPool( - s_token, DEFAULT_TOKEN_DECIMALS, new address[](0), address(s_mockRMNRemote), false, address(s_sourceRouter) - ); + s_lockReleaseTokenPool = + new LockReleaseTokenPool(s_token, new address[](0), address(s_mockRMN), false, address(s_sourceRouter)); assertEq(false, s_lockReleaseTokenPool.canAcceptLiquidity()); } } diff --git a/contracts/src/v0.8/ccip/test/pools/LockReleaseTokenPool/LockReleaseTokenPool.lockOrBurn.t.sol b/contracts/src/v0.8/ccip/test/pools/LockReleaseTokenPool/LockReleaseTokenPool.lockOrBurn.t.sol index 490f848f7af..7c87fbcc95d 100644 --- a/contracts/src/v0.8/ccip/test/pools/LockReleaseTokenPool/LockReleaseTokenPool.lockOrBurn.t.sol +++ b/contracts/src/v0.8/ccip/test/pools/LockReleaseTokenPool/LockReleaseTokenPool.lockOrBurn.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import {Pool} from "../../../libraries/Pool.sol"; import {RateLimiter} from "../../../libraries/RateLimiter.sol"; @@ -30,7 +30,7 @@ contract LockReleaseTokenPool_lockOrBurn is LockReleaseTokenPoolSetup { ); } - function test_LockOrBurnWithAllowList() public { + function test_LockOrBurnWithAllowList_Success() public { uint256 amount = 100; vm.startPrank(s_allowedOnRamp); @@ -63,7 +63,7 @@ contract LockReleaseTokenPool_lockOrBurn is LockReleaseTokenPoolSetup { ); } - function test_RevertWhen_LockOrBurnWithAllowList() public { + function test_LockOrBurnWithAllowList_Revert() public { vm.startPrank(s_allowedOnRamp); vm.expectRevert(abi.encodeWithSelector(TokenPool.SenderNotAllowed.selector, STRANGER)); @@ -79,9 +79,9 @@ contract LockReleaseTokenPool_lockOrBurn is LockReleaseTokenPoolSetup { ); } - function test_RevertWhen_PoolBurnRevertNotHealthy() public { + function test_PoolBurnRevertNotHealthy_Revert() public { // Should not burn tokens if cursed. - vm.mockCall(address(s_mockRMNRemote), abi.encodeWithSignature("isCursed(bytes16)"), abi.encode(true)); + s_mockRMN.setGlobalCursed(true); uint256 before = s_token.balanceOf(address(s_lockReleaseTokenPoolWithAllowList)); vm.startPrank(s_allowedOnRamp); diff --git a/contracts/src/v0.8/ccip/test/pools/LockReleaseTokenPool/LockReleaseTokenPool.provideLiquidity.t.sol b/contracts/src/v0.8/ccip/test/pools/LockReleaseTokenPool/LockReleaseTokenPool.provideLiquidity.t.sol index 88724f89abb..f402750eb19 100644 --- a/contracts/src/v0.8/ccip/test/pools/LockReleaseTokenPool/LockReleaseTokenPool.provideLiquidity.t.sol +++ b/contracts/src/v0.8/ccip/test/pools/LockReleaseTokenPool/LockReleaseTokenPool.provideLiquidity.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import {LockReleaseTokenPool} from "../../../pools/LockReleaseTokenPool.sol"; @@ -21,7 +21,7 @@ contract LockReleaseTokenPool_provideLiquidity is LockReleaseTokenPoolSetup { // Reverts - function test_RevertWhen_Unauthorized() public { + function test_Unauthorized_Revert() public { vm.startPrank(STRANGER); vm.expectRevert(abi.encodeWithSelector(TokenPool.Unauthorized.selector, STRANGER)); @@ -36,10 +36,9 @@ contract LockReleaseTokenPool_provideLiquidity is LockReleaseTokenPoolSetup { s_lockReleaseTokenPool.provideLiquidity(amount); } - function test_RevertWhen_LiquidityNotAccepted() public { - s_lockReleaseTokenPool = new LockReleaseTokenPool( - s_token, DEFAULT_TOKEN_DECIMALS, new address[](0), address(s_mockRMNRemote), false, address(s_sourceRouter) - ); + function test_LiquidityNotAccepted_Revert() public { + s_lockReleaseTokenPool = + new LockReleaseTokenPool(s_token, new address[](0), address(s_mockRMN), false, address(s_sourceRouter)); vm.expectRevert(LockReleaseTokenPool.LiquidityNotAccepted.selector); s_lockReleaseTokenPool.provideLiquidity(1); diff --git a/contracts/src/v0.8/ccip/test/pools/LockReleaseTokenPool/LockReleaseTokenPool.releaseOrMint.t.sol b/contracts/src/v0.8/ccip/test/pools/LockReleaseTokenPool/LockReleaseTokenPool.releaseOrMint.t.sol index 9ef5130370a..b20b19fe973 100644 --- a/contracts/src/v0.8/ccip/test/pools/LockReleaseTokenPool/LockReleaseTokenPool.releaseOrMint.t.sol +++ b/contracts/src/v0.8/ccip/test/pools/LockReleaseTokenPool/LockReleaseTokenPool.releaseOrMint.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import {Pool} from "../../../libraries/Pool.sol"; import {RateLimiter} from "../../../libraries/RateLimiter.sol"; @@ -10,24 +10,21 @@ import {LockReleaseTokenPoolSetup} from "./LockReleaseTokenPoolSetup.t.sol"; contract LockReleaseTokenPool_releaseOrMint is LockReleaseTokenPoolSetup { function setUp() public virtual override { LockReleaseTokenPoolSetup.setUp(); - - bytes[] memory remotePoolAddresses = new bytes[](1); - remotePoolAddresses[0] = abi.encode(s_sourcePoolAddress); - TokenPool.ChainUpdate[] memory chainUpdate = new TokenPool.ChainUpdate[](1); chainUpdate[0] = TokenPool.ChainUpdate({ remoteChainSelector: SOURCE_CHAIN_SELECTOR, - remotePoolAddresses: remotePoolAddresses, + remotePoolAddress: abi.encode(s_sourcePoolAddress), remoteTokenAddress: abi.encode(address(2)), + allowed: true, outboundRateLimiterConfig: _getOutboundRateLimiterConfig(), inboundRateLimiterConfig: _getInboundRateLimiterConfig() }); - s_lockReleaseTokenPool.applyChainUpdates(new uint64[](0), chainUpdate); - s_lockReleaseTokenPoolWithAllowList.applyChainUpdates(new uint64[](0), chainUpdate); + s_lockReleaseTokenPool.applyChainUpdates(chainUpdate); + s_lockReleaseTokenPoolWithAllowList.applyChainUpdates(chainUpdate); } - function test_ReleaseOrMint() public { + function test_ReleaseOrMint_Success() public { vm.startPrank(s_allowedOffRamp); uint256 amount = 100; @@ -93,11 +90,20 @@ contract LockReleaseTokenPool_releaseOrMint is LockReleaseTokenPoolSetup { ); } - function test_RevertWhen_ChainNotAllowed() public { - uint64[] memory chainsToRemove = new uint64[](1); - chainsToRemove[0] = SOURCE_CHAIN_SELECTOR; + function test_ChainNotAllowed_Revert() public { + address notAllowedRemotePoolAddress = address(1); + + TokenPool.ChainUpdate[] memory chainUpdate = new TokenPool.ChainUpdate[](1); + chainUpdate[0] = TokenPool.ChainUpdate({ + remoteChainSelector: SOURCE_CHAIN_SELECTOR, + remotePoolAddress: abi.encode(notAllowedRemotePoolAddress), + remoteTokenAddress: abi.encode(address(2)), + allowed: false, + outboundRateLimiterConfig: RateLimiter.Config({isEnabled: false, capacity: 0, rate: 0}), + inboundRateLimiterConfig: RateLimiter.Config({isEnabled: false, capacity: 0, rate: 0}) + }); - s_lockReleaseTokenPool.applyChainUpdates(chainsToRemove, new TokenPool.ChainUpdate[](0)); + s_lockReleaseTokenPool.applyChainUpdates(chainUpdate); vm.startPrank(s_allowedOffRamp); @@ -116,9 +122,9 @@ contract LockReleaseTokenPool_releaseOrMint is LockReleaseTokenPoolSetup { ); } - function test_RevertWhen_PoolMintNotHealthy() public { + function test_PoolMintNotHealthy_Revert() public { // Should not mint tokens if cursed. - vm.mockCall(address(s_mockRMNRemote), abi.encodeWithSignature("isCursed(bytes16)"), abi.encode(true)); + s_mockRMN.setGlobalCursed(true); uint256 before = s_token.balanceOf(OWNER); vm.startPrank(s_allowedOffRamp); vm.expectRevert(TokenPool.CursedByRMN.selector); diff --git a/contracts/src/v0.8/ccip/test/pools/LockReleaseTokenPool/LockReleaseTokenPool.setRebalancer.t.sol b/contracts/src/v0.8/ccip/test/pools/LockReleaseTokenPool/LockReleaseTokenPool.setRebalancer.t.sol index 055bbf3c55d..25286c1a376 100644 --- a/contracts/src/v0.8/ccip/test/pools/LockReleaseTokenPool/LockReleaseTokenPool.setRebalancer.t.sol +++ b/contracts/src/v0.8/ccip/test/pools/LockReleaseTokenPool/LockReleaseTokenPool.setRebalancer.t.sol @@ -1,17 +1,17 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import {Ownable2Step} from "../../../../shared/access/Ownable2Step.sol"; import {LockReleaseTokenPoolSetup} from "./LockReleaseTokenPoolSetup.t.sol"; contract LockReleaseTokenPool_setRebalancer is LockReleaseTokenPoolSetup { - function test_SetRebalancer() public { + function test_SetRebalancer_Success() public { assertEq(address(s_lockReleaseTokenPool.getRebalancer()), OWNER); s_lockReleaseTokenPool.setRebalancer(STRANGER); assertEq(address(s_lockReleaseTokenPool.getRebalancer()), STRANGER); } - function test_RevertWhen_SetRebalancer() public { + function test_SetRebalancer_Revert() public { vm.startPrank(STRANGER); vm.expectRevert(Ownable2Step.OnlyCallableByOwner.selector); diff --git a/contracts/src/v0.8/ccip/test/pools/LockReleaseTokenPool/LockReleaseTokenPool.supportsInterface.t.sol b/contracts/src/v0.8/ccip/test/pools/LockReleaseTokenPool/LockReleaseTokenPool.supportsInterface.t.sol index 000ece21f35..9a08fc38c96 100644 --- a/contracts/src/v0.8/ccip/test/pools/LockReleaseTokenPool/LockReleaseTokenPool.supportsInterface.t.sol +++ b/contracts/src/v0.8/ccip/test/pools/LockReleaseTokenPool/LockReleaseTokenPool.supportsInterface.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import {IPoolV1} from "../../../interfaces/IPool.sol"; @@ -8,7 +8,7 @@ import {LockReleaseTokenPoolSetup} from "./LockReleaseTokenPoolSetup.t.sol"; import {IERC165} from "../../../../vendor/openzeppelin-solidity/v5.0.2/contracts/utils/introspection/IERC165.sol"; contract LockReleaseTokenPool_supportsInterface is LockReleaseTokenPoolSetup { - function test_SupportsInterface() public view { + function test_SupportsInterface_Success() public view { assertTrue(s_lockReleaseTokenPool.supportsInterface(type(IPoolV1).interfaceId)); assertTrue(s_lockReleaseTokenPool.supportsInterface(type(IERC165).interfaceId)); } diff --git a/contracts/src/v0.8/ccip/test/pools/LockReleaseTokenPool/LockReleaseTokenPool.transferLiquidity.t.sol b/contracts/src/v0.8/ccip/test/pools/LockReleaseTokenPool/LockReleaseTokenPool.transferLiquidity.t.sol index 7eca1f95067..bd2636dbb98 100644 --- a/contracts/src/v0.8/ccip/test/pools/LockReleaseTokenPool/LockReleaseTokenPool.transferLiquidity.t.sol +++ b/contracts/src/v0.8/ccip/test/pools/LockReleaseTokenPool/LockReleaseTokenPool.transferLiquidity.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import {LockReleaseTokenPool} from "../../../pools/LockReleaseTokenPool.sol"; import {LockReleaseTokenPoolSetup} from "./LockReleaseTokenPoolSetup.t.sol"; @@ -11,14 +11,13 @@ contract LockReleaseTokenPool_transferLiquidity is LockReleaseTokenPoolSetup { function setUp() public virtual override { super.setUp(); - s_oldLockReleaseTokenPool = new LockReleaseTokenPool( - s_token, DEFAULT_TOKEN_DECIMALS, new address[](0), address(s_mockRMNRemote), true, address(s_sourceRouter) - ); + s_oldLockReleaseTokenPool = + new LockReleaseTokenPool(s_token, new address[](0), address(s_mockRMN), true, address(s_sourceRouter)); deal(address(s_token), address(s_oldLockReleaseTokenPool), s_amount); } - function test_transferLiquidity() public { + function test_transferLiquidity_Success() public { uint256 balancePre = s_token.balanceOf(address(s_lockReleaseTokenPool)); s_oldLockReleaseTokenPool.setRebalancer(address(s_lockReleaseTokenPool)); @@ -31,7 +30,7 @@ contract LockReleaseTokenPool_transferLiquidity is LockReleaseTokenPoolSetup { assertEq(s_token.balanceOf(address(s_lockReleaseTokenPool)), balancePre + s_amount); } - function test_RevertWhen_transferLiquidity_transferTooMuch() public { + function test_transferLiquidity_transferTooMuch_Revert() public { uint256 balancePre = s_token.balanceOf(address(s_lockReleaseTokenPool)); s_oldLockReleaseTokenPool.setRebalancer(address(s_lockReleaseTokenPool)); diff --git a/contracts/src/v0.8/ccip/test/pools/LockReleaseTokenPool/LockReleaseTokenPool.withdrawalLiquidity.t.sol b/contracts/src/v0.8/ccip/test/pools/LockReleaseTokenPool/LockReleaseTokenPool.withdrawalLiquidity.t.sol index df21bc36fab..29b6ef6c7f8 100644 --- a/contracts/src/v0.8/ccip/test/pools/LockReleaseTokenPool/LockReleaseTokenPool.withdrawalLiquidity.t.sol +++ b/contracts/src/v0.8/ccip/test/pools/LockReleaseTokenPool/LockReleaseTokenPool.withdrawalLiquidity.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import {LockReleaseTokenPool} from "../../../pools/LockReleaseTokenPool.sol"; @@ -20,14 +20,14 @@ contract LockReleaseTokenPool_withdrawalLiquidity is LockReleaseTokenPoolSetup { } // Reverts - function test_RevertWhen_Unauthorized() public { + function test_Unauthorized_Revert() public { vm.startPrank(STRANGER); vm.expectRevert(abi.encodeWithSelector(TokenPool.Unauthorized.selector, STRANGER)); s_lockReleaseTokenPool.withdrawLiquidity(1); } - function test_RevertWhen_InsufficientLiquidity() public { + function test_InsufficientLiquidity_Revert() public { uint256 maxUint256 = 2 ** 256 - 1; s_token.approve(address(s_lockReleaseTokenPool), maxUint256); s_lockReleaseTokenPool.provideLiquidity(maxUint256); diff --git a/contracts/src/v0.8/ccip/test/pools/LockReleaseTokenPool/LockReleaseTokenPoolSetup.t.sol b/contracts/src/v0.8/ccip/test/pools/LockReleaseTokenPool/LockReleaseTokenPoolSetup.t.sol index 8fc7a84ecbb..fa62df99828 100644 --- a/contracts/src/v0.8/ccip/test/pools/LockReleaseTokenPool/LockReleaseTokenPoolSetup.t.sol +++ b/contracts/src/v0.8/ccip/test/pools/LockReleaseTokenPool/LockReleaseTokenPoolSetup.t.sol @@ -1,15 +1,15 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; -import {BurnMintERC20} from "../../../../shared/token/ERC20/BurnMintERC20.sol"; +import {BurnMintERC677} from "../../../../shared/token/ERC677/BurnMintERC677.sol"; import {Router} from "../../../Router.sol"; import {LockReleaseTokenPool} from "../../../pools/LockReleaseTokenPool.sol"; import {TokenPool} from "../../../pools/TokenPool.sol"; -import {BaseTest} from "../../BaseTest.t.sol"; import {IERC20} from "../../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; +import {RouterSetup} from "../../router/Router/RouterSetup.t.sol"; -contract LockReleaseTokenPoolSetup is BaseTest { +contract LockReleaseTokenPoolSetup is RouterSetup { IERC20 internal s_token; LockReleaseTokenPool internal s_lockReleaseTokenPool; LockReleaseTokenPool internal s_lockReleaseTokenPoolWithAllowList; @@ -22,33 +22,29 @@ contract LockReleaseTokenPoolSetup is BaseTest { address internal s_sourcePoolAddress = address(53852352095); function setUp() public virtual override { - super.setUp(); - s_token = new BurnMintERC20("LINK", "LNK", 18, 0, 0); + RouterSetup.setUp(); + s_token = new BurnMintERC677("LINK", "LNK", 18, 0); deal(address(s_token), OWNER, type(uint256).max); - s_lockReleaseTokenPool = new LockReleaseTokenPool( - s_token, DEFAULT_TOKEN_DECIMALS, new address[](0), address(s_mockRMNRemote), true, address(s_sourceRouter) - ); + s_lockReleaseTokenPool = + new LockReleaseTokenPool(s_token, new address[](0), address(s_mockRMN), true, address(s_sourceRouter)); - s_allowedList.push(vm.randomAddress()); + s_allowedList.push(USER_1); s_allowedList.push(OWNER); - s_lockReleaseTokenPoolWithAllowList = new LockReleaseTokenPool( - s_token, DEFAULT_TOKEN_DECIMALS, s_allowedList, address(s_mockRMNRemote), true, address(s_sourceRouter) - ); - - bytes[] memory remotePoolAddresses = new bytes[](1); - remotePoolAddresses[0] = abi.encode(s_destPoolAddress); + s_lockReleaseTokenPoolWithAllowList = + new LockReleaseTokenPool(s_token, s_allowedList, address(s_mockRMN), true, address(s_sourceRouter)); TokenPool.ChainUpdate[] memory chainUpdate = new TokenPool.ChainUpdate[](1); chainUpdate[0] = TokenPool.ChainUpdate({ remoteChainSelector: DEST_CHAIN_SELECTOR, - remotePoolAddresses: remotePoolAddresses, + remotePoolAddress: abi.encode(s_destPoolAddress), remoteTokenAddress: abi.encode(address(2)), + allowed: true, outboundRateLimiterConfig: _getOutboundRateLimiterConfig(), inboundRateLimiterConfig: _getInboundRateLimiterConfig() }); - s_lockReleaseTokenPool.applyChainUpdates(new uint64[](0), chainUpdate); - s_lockReleaseTokenPoolWithAllowList.applyChainUpdates(new uint64[](0), chainUpdate); + s_lockReleaseTokenPool.applyChainUpdates(chainUpdate); + s_lockReleaseTokenPoolWithAllowList.applyChainUpdates(chainUpdate); s_lockReleaseTokenPool.setRebalancer(OWNER); Router.OnRamp[] memory onRampUpdates = new Router.OnRamp[](1); diff --git a/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPool.addRemotePool.t.sol b/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPool.addRemotePool.t.sol deleted file mode 100644 index 5a2e84f5c98..00000000000 --- a/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPool.addRemotePool.t.sol +++ /dev/null @@ -1,165 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; - -import {Router} from "../../../Router.sol"; -import {Pool} from "../../../libraries/Pool.sol"; -import {TokenPool} from "../../../pools/TokenPool.sol"; -import {TokenPoolSetup} from "./TokenPoolSetup.t.sol"; - -contract TokenPool_addRemotePool is TokenPoolSetup { - function test_addRemotePool() public { - // Use a longer data type to ensure it also works for non-evm - bytes memory remotePool = abi.encode(makeAddr("non-evm-1"), makeAddr("non-evm-2")); - - vm.startPrank(OWNER); - - vm.expectEmit(); - emit TokenPool.RemotePoolAdded(DEST_CHAIN_SELECTOR, remotePool); - - s_tokenPool.addRemotePool(DEST_CHAIN_SELECTOR, remotePool); - - bytes[] memory remotePools = s_tokenPool.getRemotePools(DEST_CHAIN_SELECTOR); - - assertEq(remotePools.length, 2); - assertEq(remotePools[0], abi.encode(s_initialRemotePool)); - assertEq(remotePools[1], remotePool); - } - - function test_addRemotePool_MultipleActive() public { - bytes[] memory remotePools = new bytes[](3); - remotePools[0] = abi.encode(makeAddr("remotePool1")); - remotePools[1] = abi.encode(makeAddr("remotePool2")); - remotePools[2] = abi.encode(makeAddr("remotePool3")); - - address fakeOffRamp = makeAddr("fakeOffRamp"); - - vm.mockCall( - address(s_sourceRouter), abi.encodeCall(Router.isOffRamp, (DEST_CHAIN_SELECTOR, fakeOffRamp)), abi.encode(true) - ); - - vm.startPrank(fakeOffRamp); - - vm.expectRevert(abi.encodeWithSelector(TokenPool.InvalidSourcePoolAddress.selector, remotePools[0])); - s_tokenPool.releaseOrMint(_getReleaseOrMintInV1(remotePools[0])); - - // There's already one pool setup through the test setup - assertEq(s_tokenPool.getRemotePools(DEST_CHAIN_SELECTOR).length, 1); - - vm.startPrank(OWNER); - s_tokenPool.addRemotePool(DEST_CHAIN_SELECTOR, remotePools[0]); - - vm.startPrank(fakeOffRamp); - s_tokenPool.releaseOrMint(_getReleaseOrMintInV1(remotePools[0])); - - // Adding an additional pool does not remove the previous one - vm.startPrank(OWNER); - s_tokenPool.addRemotePool(DEST_CHAIN_SELECTOR, remotePools[1]); - - // Both should now work - assertEq(s_tokenPool.getRemotePools(DEST_CHAIN_SELECTOR).length, 3); - vm.startPrank(fakeOffRamp); - s_tokenPool.releaseOrMint(_getReleaseOrMintInV1(remotePools[0])); - s_tokenPool.releaseOrMint(_getReleaseOrMintInV1(remotePools[1])); - - // Adding a third pool, and removing the first one - vm.startPrank(OWNER); - s_tokenPool.addRemotePool(DEST_CHAIN_SELECTOR, remotePools[2]); - assertEq(s_tokenPool.getRemotePools(DEST_CHAIN_SELECTOR).length, 4); - s_tokenPool.removeRemotePool(DEST_CHAIN_SELECTOR, remotePools[0]); - assertEq(s_tokenPool.getRemotePools(DEST_CHAIN_SELECTOR).length, 3); - - // Only the last two should work - vm.startPrank(fakeOffRamp); - vm.expectRevert(abi.encodeWithSelector(TokenPool.InvalidSourcePoolAddress.selector, remotePools[0])); - s_tokenPool.releaseOrMint(_getReleaseOrMintInV1(remotePools[0])); - s_tokenPool.releaseOrMint(_getReleaseOrMintInV1(remotePools[1])); - s_tokenPool.releaseOrMint(_getReleaseOrMintInV1(remotePools[2])); - - // Removing the chain removes all associated pool hashes - vm.startPrank(OWNER); - - uint64[] memory chainSelectorsToRemove = new uint64[](1); - chainSelectorsToRemove[0] = DEST_CHAIN_SELECTOR; - s_tokenPool.applyChainUpdates(chainSelectorsToRemove, new TokenPool.ChainUpdate[](0)); - - assertEq(s_tokenPool.getRemotePools(DEST_CHAIN_SELECTOR).length, 0); - - vm.expectRevert(abi.encodeWithSelector(TokenPool.ChainNotAllowed.selector, DEST_CHAIN_SELECTOR)); - s_tokenPool.releaseOrMint(_getReleaseOrMintInV1(remotePools[0])); - vm.expectRevert(abi.encodeWithSelector(TokenPool.ChainNotAllowed.selector, DEST_CHAIN_SELECTOR)); - s_tokenPool.releaseOrMint(_getReleaseOrMintInV1(remotePools[1])); - vm.expectRevert(abi.encodeWithSelector(TokenPool.ChainNotAllowed.selector, DEST_CHAIN_SELECTOR)); - s_tokenPool.releaseOrMint(_getReleaseOrMintInV1(remotePools[2])); - - // Adding the chain back should NOT allow the previous pools to work again - TokenPool.ChainUpdate[] memory chainUpdate = new TokenPool.ChainUpdate[](1); - chainUpdate[0] = TokenPool.ChainUpdate({ - remoteChainSelector: DEST_CHAIN_SELECTOR, - remotePoolAddresses: new bytes[](0), - remoteTokenAddress: abi.encode(s_initialRemoteToken), - outboundRateLimiterConfig: _getOutboundRateLimiterConfig(), - inboundRateLimiterConfig: _getInboundRateLimiterConfig() - }); - - vm.startPrank(OWNER); - s_tokenPool.applyChainUpdates(new uint64[](0), chainUpdate); - - vm.startPrank(fakeOffRamp); - vm.expectRevert(abi.encodeWithSelector(TokenPool.InvalidSourcePoolAddress.selector, remotePools[0])); - s_tokenPool.releaseOrMint(_getReleaseOrMintInV1(remotePools[0])); - vm.expectRevert(abi.encodeWithSelector(TokenPool.InvalidSourcePoolAddress.selector, remotePools[1])); - s_tokenPool.releaseOrMint(_getReleaseOrMintInV1(remotePools[1])); - vm.expectRevert(abi.encodeWithSelector(TokenPool.InvalidSourcePoolAddress.selector, remotePools[2])); - s_tokenPool.releaseOrMint(_getReleaseOrMintInV1(remotePools[2])); - } - - function _getReleaseOrMintInV1( - bytes memory sourcePoolAddress - ) internal view returns (Pool.ReleaseOrMintInV1 memory) { - return Pool.ReleaseOrMintInV1({ - originalSender: abi.encode(OWNER), - remoteChainSelector: DEST_CHAIN_SELECTOR, - receiver: OWNER, - amount: 1000, - localToken: address(s_token), - sourcePoolAddress: sourcePoolAddress, - sourcePoolData: "", - offchainTokenData: "" - }); - } - - // Reverts - - function test_RevertWhen_NonExistentChain() public { - uint64 chainSelector = DEST_CHAIN_SELECTOR + 1; - bytes memory remotePool = abi.encode(type(uint256).max); - - vm.expectRevert(abi.encodeWithSelector(TokenPool.NonExistentChain.selector, chainSelector)); - - s_tokenPool.addRemotePool(chainSelector, remotePool); - } - - function test_RevertWhen_ZeroLengthAddressNotAllowed() public { - bytes memory remotePool = ""; - - vm.expectRevert(abi.encodeWithSelector(TokenPool.ZeroAddressNotAllowed.selector)); - - s_tokenPool.addRemotePool(DEST_CHAIN_SELECTOR, remotePool); - } - - function test_RevertWhen_PoolAlreadyAdded() public { - uint64 chainSelector = DEST_CHAIN_SELECTOR; - - bytes memory remotePool = abi.encode(type(uint256).max); - - vm.expectEmit(); - emit TokenPool.RemotePoolAdded(chainSelector, remotePool); - - s_tokenPool.addRemotePool(chainSelector, remotePool); - - vm.expectRevert(abi.encodeWithSelector(TokenPool.PoolAlreadyAdded.selector, chainSelector, remotePool)); - - // Attempt to add the same pool again but revert - s_tokenPool.addRemotePool(chainSelector, remotePool); - } -} diff --git a/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPool.applyAllowListUpdates.t.sol b/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPool.applyAllowListUpdates.t.sol index 95d498430dc..2862b8c71ae 100644 --- a/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPool.applyAllowListUpdates.t.sol +++ b/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPool.applyAllowListUpdates.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import {Ownable2Step} from "../../../../shared/access/Ownable2Step.sol"; import {TokenPool} from "../../../pools/TokenPool.sol"; @@ -8,7 +8,7 @@ import {TokenPoolHelper} from "../../helpers/TokenPoolHelper.sol"; import {TokenPoolWithAllowListSetup} from "./TokenPoolWithAllowListSetup.t.sol"; contract TokenPoolWithAllowList_applyAllowListUpdates is TokenPoolWithAllowListSetup { - function test_SetAllowList() public { + function test_SetAllowList_Success() public { address[] memory newAddresses = new address[](2); newAddresses[0] = address(1); newAddresses[1] = address(2); @@ -60,7 +60,7 @@ contract TokenPoolWithAllowList_applyAllowListUpdates is TokenPoolWithAllowListS assertEq(0, setAddresses.length); } - function test_SetAllowListSkipsZero() public { + function test_SetAllowListSkipsZero_Success() public { uint256 setAddressesLength = s_tokenPool.getAllowList().length; address[] memory newAddresses = new address[](1); @@ -74,17 +74,15 @@ contract TokenPoolWithAllowList_applyAllowListUpdates is TokenPoolWithAllowListS // Reverts - function test_RevertWhen_OnlyOwner() public { + function test_OnlyOwner_Revert() public { vm.stopPrank(); vm.expectRevert(Ownable2Step.OnlyCallableByOwner.selector); address[] memory newAddresses = new address[](2); s_tokenPool.applyAllowListUpdates(new address[](0), newAddresses); } - function test_RevertWhen_AllowListNotEnabled() public { - s_tokenPool = new TokenPoolHelper( - s_token, DEFAULT_TOKEN_DECIMALS, new address[](0), address(s_mockRMNRemote), address(s_sourceRouter) - ); + function test_AllowListNotEnabled_Revert() public { + s_tokenPool = new TokenPoolHelper(s_token, new address[](0), address(s_mockRMN), address(s_sourceRouter)); vm.expectRevert(TokenPool.AllowListNotEnabled.selector); diff --git a/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPool.applyChainUpdates.t.sol b/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPool.applyChainUpdates.t.sol index e26cf766362..a24fa3d0e8a 100644 --- a/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPool.applyChainUpdates.t.sol +++ b/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPool.applyChainUpdates.t.sol @@ -1,35 +1,18 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import {Ownable2Step} from "../../../../shared/access/Ownable2Step.sol"; -import {BurnMintERC677} from "../../../../shared/token/ERC677/BurnMintERC677.sol"; import {RateLimiter} from "../../../libraries/RateLimiter.sol"; import {TokenPool} from "../../../pools/TokenPool.sol"; -import {BaseTest} from "../../BaseTest.t.sol"; -import {TokenPoolHelper} from "../../helpers/TokenPoolHelper.sol"; - -import {IERC20} from "../../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; - -contract TokenPool_applyChainUpdates is BaseTest { - IERC20 internal s_token; - TokenPoolHelper internal s_tokenPool; - - function setUp() public virtual override { - super.setUp(); - s_token = new BurnMintERC677("LINK", "LNK", 18, 0); - deal(address(s_token), OWNER, type(uint256).max); - - s_tokenPool = new TokenPoolHelper( - s_token, DEFAULT_TOKEN_DECIMALS, new address[](0), address(s_mockRMNRemote), address(s_sourceRouter) - ); - } +import {TokenPoolSetup} from "./TokenPoolSetup.t.sol"; +contract TokenPool_applyChainUpdates is TokenPoolSetup { function assertState( TokenPool.ChainUpdate[] memory chainUpdates ) public view { uint64[] memory chainSelectors = s_tokenPool.getSupportedChains(); - for (uint256 i = 0; i < chainUpdates.length; ++i) { - assertEq(chainUpdates[i].remoteChainSelector, chainSelectors[i], "Chain selector mismatch"); + for (uint256 i = 0; i < chainUpdates.length; i++) { + assertEq(chainUpdates[i].remoteChainSelector, chainSelectors[i]); } for (uint256 i = 0; i < chainUpdates.length; ++i) { @@ -47,14 +30,14 @@ contract TokenPool_applyChainUpdates is BaseTest { } } - function test_applyChainUpdates() public { + function test_applyChainUpdates_Success() public { RateLimiter.Config memory outboundRateLimit1 = RateLimiter.Config({isEnabled: true, capacity: 100e28, rate: 1e18}); RateLimiter.Config memory inboundRateLimit1 = RateLimiter.Config({isEnabled: true, capacity: 100e29, rate: 1e19}); RateLimiter.Config memory outboundRateLimit2 = RateLimiter.Config({isEnabled: true, capacity: 100e26, rate: 1e16}); RateLimiter.Config memory inboundRateLimit2 = RateLimiter.Config({isEnabled: true, capacity: 100e27, rate: 1e17}); // EVM chain, which uses the 160 bit evm address space - uint64 evmChainSelector = 1789142; + uint64 evmChainSelector = 1; bytes memory evmRemotePool = abi.encode(makeAddr("evm_remote_pool")); bytes memory evmRemoteToken = abi.encode(makeAddr("evm_remote_token")); @@ -63,24 +46,20 @@ contract TokenPool_applyChainUpdates is BaseTest { bytes memory nonEvmRemotePool = abi.encode(keccak256("non_evm_remote_pool")); bytes memory nonEvmRemoteToken = abi.encode(keccak256("non_evm_remote_token")); - bytes[] memory evmRemotePools = new bytes[](1); - evmRemotePools[0] = evmRemotePool; - - bytes[] memory nonEvmRemotePools = new bytes[](1); - nonEvmRemotePools[0] = nonEvmRemotePool; - TokenPool.ChainUpdate[] memory chainUpdates = new TokenPool.ChainUpdate[](2); chainUpdates[0] = TokenPool.ChainUpdate({ remoteChainSelector: evmChainSelector, - remotePoolAddresses: evmRemotePools, + remotePoolAddress: evmRemotePool, remoteTokenAddress: evmRemoteToken, + allowed: true, outboundRateLimiterConfig: outboundRateLimit1, inboundRateLimiterConfig: inboundRateLimit1 }); chainUpdates[1] = TokenPool.ChainUpdate({ remoteChainSelector: nonEvmChainSelector, - remotePoolAddresses: nonEvmRemotePools, + remotePoolAddress: nonEvmRemotePool, remoteTokenAddress: nonEvmRemoteToken, + allowed: true, outboundRateLimiterConfig: outboundRateLimit2, inboundRateLimiterConfig: inboundRateLimit2 }); @@ -100,28 +79,33 @@ contract TokenPool_applyChainUpdates is BaseTest { chainUpdates[1].outboundRateLimiterConfig, chainUpdates[1].inboundRateLimiterConfig ); - s_tokenPool.applyChainUpdates(new uint64[](0), chainUpdates); + s_tokenPool.applyChainUpdates(chainUpdates); // on1: rateLimit1, on2: rateLimit2, off1: rateLimit1, off2: rateLimit3 assertState(chainUpdates); // Removing an non-existent chain should revert + TokenPool.ChainUpdate[] memory chainRemoves = new TokenPool.ChainUpdate[](1); uint64 strangerChainSelector = 120938; - - uint64[] memory chainRemoves = new uint64[](1); - chainRemoves[0] = strangerChainSelector; - + chainRemoves[0] = TokenPool.ChainUpdate({ + remoteChainSelector: strangerChainSelector, + remotePoolAddress: evmRemotePool, + remoteTokenAddress: evmRemoteToken, + allowed: false, + outboundRateLimiterConfig: RateLimiter.Config({isEnabled: false, capacity: 0, rate: 0}), + inboundRateLimiterConfig: RateLimiter.Config({isEnabled: false, capacity: 0, rate: 0}) + }); vm.expectRevert(abi.encodeWithSelector(TokenPool.NonExistentChain.selector, strangerChainSelector)); - s_tokenPool.applyChainUpdates(chainRemoves, new TokenPool.ChainUpdate[](0)); + s_tokenPool.applyChainUpdates(chainRemoves); // State remains assertState(chainUpdates); // Can remove a chain - chainRemoves[0] = evmChainSelector; + chainRemoves[0].remoteChainSelector = evmChainSelector; vm.expectEmit(); - emit TokenPool.ChainRemoved(chainRemoves[0]); + emit TokenPool.ChainRemoved(chainRemoves[0].remoteChainSelector); - s_tokenPool.applyChainUpdates(chainRemoves, new TokenPool.ChainUpdate[](0)); + s_tokenPool.applyChainUpdates(chainRemoves); // State updated, only chain 2 remains TokenPool.ChainUpdate[] memory singleChainConfigured = new TokenPool.ChainUpdate[](1); @@ -132,124 +116,94 @@ contract TokenPool_applyChainUpdates is BaseTest { vm.expectRevert( abi.encodeWithSelector(TokenPool.ChainAlreadyExists.selector, singleChainConfigured[0].remoteChainSelector) ); - s_tokenPool.applyChainUpdates(new uint64[](0), singleChainConfigured); - } - - function test_applyChainUpdates_UpdatesRemotePoolHashes() public { - assertEq(s_tokenPool.getRemotePools(DEST_CHAIN_SELECTOR).length, 0); - - uint64 selector1 = 789; - uint64 selector2 = 123; - uint64 selector3 = 456; - - bytes memory pool1 = abi.encode(makeAddr("pool1")); - bytes memory pool2 = abi.encode(makeAddr("pool2")); - bytes memory pool3 = abi.encode(makeAddr("pool3")); - - TokenPool.ChainUpdate[] memory chainUpdates = new TokenPool.ChainUpdate[](3); - chainUpdates[0] = TokenPool.ChainUpdate({ - remoteChainSelector: selector1, - remotePoolAddresses: new bytes[](0), - remoteTokenAddress: pool1, - outboundRateLimiterConfig: _getOutboundRateLimiterConfig(), - inboundRateLimiterConfig: _getInboundRateLimiterConfig() - }); - chainUpdates[1] = TokenPool.ChainUpdate({ - remoteChainSelector: selector2, - remotePoolAddresses: new bytes[](0), - remoteTokenAddress: pool2, - outboundRateLimiterConfig: _getOutboundRateLimiterConfig(), - inboundRateLimiterConfig: _getInboundRateLimiterConfig() - }); - chainUpdates[2] = TokenPool.ChainUpdate({ - remoteChainSelector: selector3, - remotePoolAddresses: new bytes[](0), - remoteTokenAddress: pool3, - outboundRateLimiterConfig: _getOutboundRateLimiterConfig(), - inboundRateLimiterConfig: _getInboundRateLimiterConfig() - }); - - s_tokenPool.applyChainUpdates(new uint64[](0), chainUpdates); - - // This adds 3 for the first chain, 2 for the second, and 1 for the third for a total of 6. - for (uint256 i = 0; i < chainUpdates.length; ++i) { - for (uint256 j = i; j < chainUpdates.length; ++j) { - s_tokenPool.addRemotePool(chainUpdates[i].remoteChainSelector, abi.encode(i, j)); - } - assertEq(s_tokenPool.getRemotePools(chainUpdates[i].remoteChainSelector).length, 3 - i); - } - - // Removing a chain should remove all associated pool hashes - uint64[] memory chainRemoves = new uint64[](1); - chainRemoves[0] = selector1; - - s_tokenPool.applyChainUpdates(chainRemoves, new TokenPool.ChainUpdate[](0)); - - assertEq(s_tokenPool.getRemotePools(selector1).length, 0); - - chainRemoves[0] = selector2; - - s_tokenPool.applyChainUpdates(chainRemoves, new TokenPool.ChainUpdate[](0)); - - assertEq(s_tokenPool.getRemotePools(selector2).length, 0); - - // The above deletions should not have affected the third chain - assertEq(s_tokenPool.getRemotePools(selector3).length, 1); + s_tokenPool.applyChainUpdates(singleChainConfigured); } // Reverts - function test_RevertWhen_applyChainUpdates_OnlyCallableByOwner() public { + function test_applyChainUpdates_OnlyCallableByOwner_Revert() public { vm.startPrank(STRANGER); vm.expectRevert(Ownable2Step.OnlyCallableByOwner.selector); - s_tokenPool.applyChainUpdates(new uint64[](0), new TokenPool.ChainUpdate[](0)); + s_tokenPool.applyChainUpdates(new TokenPool.ChainUpdate[](0)); } - function test_RevertWhen_applyChainUpdates_ZeroAddressNotAllowed() public { - bytes[] memory remotePoolAddresses = new bytes[](1); - remotePoolAddresses[0] = ""; - + function test_applyChainUpdates_ZeroAddressNotAllowed_Revert() public { TokenPool.ChainUpdate[] memory chainUpdates = new TokenPool.ChainUpdate[](1); chainUpdates[0] = TokenPool.ChainUpdate({ remoteChainSelector: 1, - remotePoolAddresses: remotePoolAddresses, + remotePoolAddress: "", remoteTokenAddress: abi.encode(address(2)), + allowed: true, outboundRateLimiterConfig: RateLimiter.Config({isEnabled: true, capacity: 100e28, rate: 1e18}), inboundRateLimiterConfig: RateLimiter.Config({isEnabled: true, capacity: 100e28, rate: 1e18}) }); vm.expectRevert(TokenPool.ZeroAddressNotAllowed.selector); - s_tokenPool.applyChainUpdates(new uint64[](0), chainUpdates); + s_tokenPool.applyChainUpdates(chainUpdates); chainUpdates = new TokenPool.ChainUpdate[](1); chainUpdates[0] = TokenPool.ChainUpdate({ remoteChainSelector: 1, - remotePoolAddresses: new bytes[](0), + remotePoolAddress: abi.encode(address(2)), remoteTokenAddress: "", + allowed: true, outboundRateLimiterConfig: RateLimiter.Config({isEnabled: true, capacity: 100e28, rate: 1e18}), inboundRateLimiterConfig: RateLimiter.Config({isEnabled: true, capacity: 100e28, rate: 1e18}) }); vm.expectRevert(TokenPool.ZeroAddressNotAllowed.selector); - s_tokenPool.applyChainUpdates(new uint64[](0), chainUpdates); + s_tokenPool.applyChainUpdates(chainUpdates); } - function test_RevertWhen_applyChainUpdates_NonExistentChain() public { - uint64[] memory chainRemoves = new uint64[](1); - chainRemoves[0] = 1; + function test_applyChainUpdates_DisabledNonZeroRateLimit_Revert() public { + RateLimiter.Config memory outboundRateLimit = RateLimiter.Config({isEnabled: true, capacity: 100e28, rate: 1e18}); + RateLimiter.Config memory inboundRateLimit = RateLimiter.Config({isEnabled: true, capacity: 100e22, rate: 1e12}); + TokenPool.ChainUpdate[] memory chainUpdates = new TokenPool.ChainUpdate[](1); + chainUpdates[0] = TokenPool.ChainUpdate({ + remoteChainSelector: 1, + remotePoolAddress: abi.encode(address(1)), + remoteTokenAddress: abi.encode(address(2)), + allowed: true, + outboundRateLimiterConfig: outboundRateLimit, + inboundRateLimiterConfig: inboundRateLimit + }); + + s_tokenPool.applyChainUpdates(chainUpdates); - vm.expectRevert(abi.encodeWithSelector(TokenPool.NonExistentChain.selector, chainRemoves[0])); - s_tokenPool.applyChainUpdates(chainRemoves, new TokenPool.ChainUpdate[](0)); + chainUpdates[0].allowed = false; + chainUpdates[0].outboundRateLimiterConfig = RateLimiter.Config({isEnabled: false, capacity: 10, rate: 1}); + chainUpdates[0].inboundRateLimiterConfig = RateLimiter.Config({isEnabled: false, capacity: 10, rate: 1}); + + vm.expectRevert( + abi.encodeWithSelector(RateLimiter.DisabledNonZeroRateLimit.selector, chainUpdates[0].outboundRateLimiterConfig) + ); + s_tokenPool.applyChainUpdates(chainUpdates); } - function test_RevertWhen_applyChainUpdates_InvalidRateLimitRate() public { - uint64 unusedChainSelector = 2 ** 64 - 1; + function test_applyChainUpdates_NonExistentChain_Revert() public { + RateLimiter.Config memory outboundRateLimit = RateLimiter.Config({isEnabled: false, capacity: 0, rate: 0}); + RateLimiter.Config memory inboundRateLimit = RateLimiter.Config({isEnabled: false, capacity: 0, rate: 0}); + TokenPool.ChainUpdate[] memory chainUpdates = new TokenPool.ChainUpdate[](1); + chainUpdates[0] = TokenPool.ChainUpdate({ + remoteChainSelector: 1, + remotePoolAddress: abi.encode(address(1)), + remoteTokenAddress: abi.encode(address(2)), + allowed: false, + outboundRateLimiterConfig: outboundRateLimit, + inboundRateLimiterConfig: inboundRateLimit + }); + vm.expectRevert(abi.encodeWithSelector(TokenPool.NonExistentChain.selector, chainUpdates[0].remoteChainSelector)); + s_tokenPool.applyChainUpdates(chainUpdates); + } + + function test_applyChainUpdates_InvalidRateLimitRate_Revert() public { TokenPool.ChainUpdate[] memory chainUpdates = new TokenPool.ChainUpdate[](1); chainUpdates[0] = TokenPool.ChainUpdate({ - remoteChainSelector: unusedChainSelector, - remotePoolAddresses: new bytes[](0), + remoteChainSelector: 1, + remotePoolAddress: abi.encode(address(1)), remoteTokenAddress: abi.encode(address(2)), + allowed: true, outboundRateLimiterConfig: RateLimiter.Config({isEnabled: true, capacity: 0, rate: 0}), inboundRateLimiterConfig: RateLimiter.Config({isEnabled: true, capacity: 100e22, rate: 1e12}) }); @@ -259,28 +213,28 @@ contract TokenPool_applyChainUpdates is BaseTest { vm.expectRevert( abi.encodeWithSelector(RateLimiter.InvalidRateLimitRate.selector, chainUpdates[0].outboundRateLimiterConfig) ); - s_tokenPool.applyChainUpdates(new uint64[](0), chainUpdates); + s_tokenPool.applyChainUpdates(chainUpdates); chainUpdates[0].outboundRateLimiterConfig.rate = 100; vm.expectRevert( abi.encodeWithSelector(RateLimiter.InvalidRateLimitRate.selector, chainUpdates[0].outboundRateLimiterConfig) ); - s_tokenPool.applyChainUpdates(new uint64[](0), chainUpdates); + s_tokenPool.applyChainUpdates(chainUpdates); chainUpdates[0].outboundRateLimiterConfig.capacity = 100; vm.expectRevert( abi.encodeWithSelector(RateLimiter.InvalidRateLimitRate.selector, chainUpdates[0].outboundRateLimiterConfig) ); - s_tokenPool.applyChainUpdates(new uint64[](0), chainUpdates); + s_tokenPool.applyChainUpdates(chainUpdates); chainUpdates[0].outboundRateLimiterConfig.capacity = 101; - s_tokenPool.applyChainUpdates(new uint64[](0), chainUpdates); + s_tokenPool.applyChainUpdates(chainUpdates); // Change the chain selector as adding the same one would revert - chainUpdates[0].remoteChainSelector = unusedChainSelector - 1; + chainUpdates[0].remoteChainSelector = 2; // Inbound @@ -290,24 +244,24 @@ contract TokenPool_applyChainUpdates is BaseTest { vm.expectRevert( abi.encodeWithSelector(RateLimiter.InvalidRateLimitRate.selector, chainUpdates[0].inboundRateLimiterConfig) ); - s_tokenPool.applyChainUpdates(new uint64[](0), chainUpdates); + s_tokenPool.applyChainUpdates(chainUpdates); chainUpdates[0].inboundRateLimiterConfig.rate = 100; vm.expectRevert( abi.encodeWithSelector(RateLimiter.InvalidRateLimitRate.selector, chainUpdates[0].inboundRateLimiterConfig) ); - s_tokenPool.applyChainUpdates(new uint64[](0), chainUpdates); + s_tokenPool.applyChainUpdates(chainUpdates); chainUpdates[0].inboundRateLimiterConfig.capacity = 100; vm.expectRevert( abi.encodeWithSelector(RateLimiter.InvalidRateLimitRate.selector, chainUpdates[0].inboundRateLimiterConfig) ); - s_tokenPool.applyChainUpdates(new uint64[](0), chainUpdates); + s_tokenPool.applyChainUpdates(chainUpdates); chainUpdates[0].inboundRateLimiterConfig.capacity = 101; - s_tokenPool.applyChainUpdates(new uint64[](0), chainUpdates); + s_tokenPool.applyChainUpdates(chainUpdates); } } diff --git a/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPool.calculateLocalAmount.t.sol b/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPool.calculateLocalAmount.t.sol deleted file mode 100644 index 8faf2303524..00000000000 --- a/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPool.calculateLocalAmount.t.sol +++ /dev/null @@ -1,101 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; - -import {TokenPool} from "../../../pools/TokenPool.sol"; -import {TokenPoolHelper} from "../../helpers/TokenPoolHelper.sol"; -import {TokenPoolSetup} from "./TokenPoolSetup.t.sol"; - -import {IERC20Metadata} from - "../../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/extensions/IERC20Metadata.sol"; - -contract TokenPool_calculateLocalAmount is TokenPoolSetup { - function test_calculateLocalAmount() public view { - uint8 localDecimals = s_tokenPool.getTokenDecimals(); - uint256 remoteAmount = 123e18; - - // Zero decimals should return amount * 10^localDecimals - assertEq(s_tokenPool.calculateLocalAmount(remoteAmount, 0), remoteAmount * 10 ** localDecimals); - - // Equal decimals should return the same amount - assertEq(s_tokenPool.calculateLocalAmount(remoteAmount, localDecimals), remoteAmount); - - // Remote amount with more decimals should return less local amount - uint256 expectedAmount = remoteAmount; - for (uint8 remoteDecimals = localDecimals + 1; remoteDecimals < 36; ++remoteDecimals) { - expectedAmount /= 10; - assertEq(s_tokenPool.calculateLocalAmount(remoteAmount, remoteDecimals), expectedAmount); - } - - // Remote amount with less decimals should return more local amount - expectedAmount = remoteAmount; - for (uint8 remoteDecimals = localDecimals - 1; remoteDecimals > 0; --remoteDecimals) { - expectedAmount *= 10; - assertEq(s_tokenPool.calculateLocalAmount(remoteAmount, remoteDecimals), expectedAmount); - } - } - - // Reverts - - function test_RevertWhen_calculateLocalAmountWhen_LowRemoteDecimalsOverflows() public { - uint8 remoteDecimals = 0; - uint8 localDecimals = 78; - uint256 remoteAmount = 1; - - vm.mockCall(address(s_token), abi.encodeWithSelector(IERC20Metadata.decimals.selector), abi.encode(localDecimals)); - - s_tokenPool = - new TokenPoolHelper(s_token, localDecimals, new address[](0), address(s_mockRMNRemote), address(s_sourceRouter)); - - vm.expectRevert( - abi.encodeWithSelector(TokenPool.OverflowDetected.selector, remoteDecimals, localDecimals, remoteAmount) - ); - - s_tokenPool.calculateLocalAmount(remoteAmount, remoteDecimals); - } - - function test_RevertWhen_calculateLocalAmountWhen_HighLocalDecimalsOverflows() public { - uint8 remoteDecimals = 18; - uint8 localDecimals = 18 + 78; - uint256 remoteAmount = 1; - - vm.mockCall(address(s_token), abi.encodeWithSelector(IERC20Metadata.decimals.selector), abi.encode(localDecimals)); - - s_tokenPool = - new TokenPoolHelper(s_token, localDecimals, new address[](0), address(s_mockRMNRemote), address(s_sourceRouter)); - - vm.expectRevert( - abi.encodeWithSelector(TokenPool.OverflowDetected.selector, remoteDecimals, localDecimals, remoteAmount) - ); - - s_tokenPool.calculateLocalAmount(remoteAmount, remoteDecimals); - } - - function test_RevertWhen_calculateLocalAmountWhen_HighRemoteDecimalsOverflows() public { - uint8 remoteDecimals = 18 + 78; - uint8 localDecimals = 18; - uint256 remoteAmount = 1; - - vm.expectRevert( - abi.encodeWithSelector(TokenPool.OverflowDetected.selector, remoteDecimals, localDecimals, remoteAmount) - ); - - s_tokenPool.calculateLocalAmount(remoteAmount, remoteDecimals); - } - - function test_RevertWhen_calculateLocalAmountWhen_HighAmountOverflows() public { - uint8 remoteDecimals = 18; - uint8 localDecimals = 18 + 28; - uint256 remoteAmount = 1e50; - - vm.mockCall(address(s_token), abi.encodeWithSelector(IERC20Metadata.decimals.selector), abi.encode(localDecimals)); - - s_tokenPool = - new TokenPoolHelper(s_token, localDecimals, new address[](0), address(s_mockRMNRemote), address(s_sourceRouter)); - - vm.expectRevert( - abi.encodeWithSelector(TokenPool.OverflowDetected.selector, remoteDecimals, localDecimals, remoteAmount) - ); - - s_tokenPool.calculateLocalAmount(remoteAmount, remoteDecimals); - } -} diff --git a/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPool.constructor.t.sol b/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPool.constructor.t.sol index 28c13582c6f..cfa0d5b9394 100644 --- a/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPool.constructor.t.sol +++ b/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPool.constructor.t.sol @@ -1,52 +1,24 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import {TokenPool} from "../../../pools/TokenPool.sol"; import {TokenPoolHelper} from "../../helpers/TokenPoolHelper.sol"; import {TokenPoolSetup} from "./TokenPoolSetup.t.sol"; import {IERC20} from "../../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; -import {IERC20Metadata} from - "../../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/extensions/IERC20Metadata.sol"; contract TokenPool_constructor is TokenPoolSetup { - function test_constructor() public view { + function test_immutableFields_Success() public view { assertEq(address(s_token), address(s_tokenPool.getToken())); - assertEq(address(s_mockRMNRemote), s_tokenPool.getRmnProxy()); - assertFalse(s_tokenPool.getAllowListEnabled()); + assertEq(address(s_mockRMN), s_tokenPool.getRmnProxy()); + assertEq(false, s_tokenPool.getAllowListEnabled()); assertEq(address(s_sourceRouter), s_tokenPool.getRouter()); - assertEq(DEFAULT_TOKEN_DECIMALS, s_tokenPool.getTokenDecimals()); - } - - function test_constructor_DecimalCallFails() public { - uint8 decimals = 255; - - vm.mockCallRevert(address(s_token), abi.encodeWithSelector(IERC20Metadata.decimals.selector), "decimals fails"); - - s_tokenPool = - new TokenPoolHelper(s_token, decimals, new address[](0), address(s_mockRMNRemote), address(s_sourceRouter)); - - assertEq(s_tokenPool.getTokenDecimals(), decimals); } // Reverts - - function test_RevertWhen_constructorWhen_ZeroAddressNotAllowed() public { + function test_ZeroAddressNotAllowed_Revert() public { vm.expectRevert(TokenPool.ZeroAddressNotAllowed.selector); - s_tokenPool = new TokenPoolHelper( - IERC20(address(0)), DEFAULT_TOKEN_DECIMALS, new address[](0), address(s_mockRMNRemote), address(s_sourceRouter) - ); - } - - function test_RevertWhen_constructorWhen_InvalidDecimalArgs() public { - uint8 invalidDecimals = DEFAULT_TOKEN_DECIMALS + 1; - - vm.expectRevert( - abi.encodeWithSelector(TokenPool.InvalidDecimalArgs.selector, invalidDecimals, DEFAULT_TOKEN_DECIMALS) - ); - - s_tokenPool = - new TokenPoolHelper(s_token, invalidDecimals, new address[](0), address(s_mockRMNRemote), address(s_sourceRouter)); + s_tokenPool = new TokenPoolHelper(IERC20(address(0)), new address[](0), address(s_mockRMN), address(s_sourceRouter)); } } diff --git a/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPool.getAllowList.t.sol b/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPool.getAllowList.t.sol index ea9bbf5d068..8d4256d3479 100644 --- a/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPool.getAllowList.t.sol +++ b/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPool.getAllowList.t.sol @@ -1,10 +1,10 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import {TokenPoolWithAllowListSetup} from "./TokenPoolWithAllowListSetup.t.sol"; contract TokenPoolWithAllowList_getAllowList is TokenPoolWithAllowListSetup { - function test_GetAllowList() public view { + function test_GetAllowList_Success() public view { address[] memory setAddresses = s_tokenPool.getAllowList(); assertEq(2, setAddresses.length); assertEq(s_allowedSenders[0], setAddresses[0]); diff --git a/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPool.getAllowListEnabled.t.sol b/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPool.getAllowListEnabled.t.sol index b710433f785..2a36a846999 100644 --- a/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPool.getAllowListEnabled.t.sol +++ b/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPool.getAllowListEnabled.t.sol @@ -1,10 +1,10 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import {TokenPoolWithAllowListSetup} from "./TokenPoolWithAllowListSetup.t.sol"; contract TokenPoolWithAllowList_getAllowListEnabled is TokenPoolWithAllowListSetup { - function test_GetAllowListEnabled() public view { + function test_GetAllowListEnabled_Success() public view { assertTrue(s_tokenPool.getAllowListEnabled()); } } diff --git a/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPool.getRemotePool.t.sol b/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPool.getRemotePool.t.sol index dc570781d81..a3acd8f2690 100644 --- a/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPool.getRemotePool.t.sol +++ b/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPool.getRemotePool.t.sol @@ -1,33 +1,29 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import {TokenPool} from "../../../pools/TokenPool.sol"; import {TokenPoolSetup} from "./TokenPoolSetup.t.sol"; contract TokenPool_getRemotePool is TokenPoolSetup { - function test_getRemotePools() public { - uint64 chainSelector = DEST_CHAIN_SELECTOR + 1; - bytes memory remotePool = abi.encode(makeAddr("remotePool")); - bytes memory remoteToken = abi.encode(makeAddr("remoteToken")); + function test_getRemotePool_Success() public { + uint64 chainSelector = 123124; + address remotePool = makeAddr("remotePool"); + address remoteToken = makeAddr("remoteToken"); // Zero indicates nothing is set - assertEq(0, s_tokenPool.getRemotePools(chainSelector).length); - - bytes[] memory remotePoolAddresses = new bytes[](1); - remotePoolAddresses[0] = remotePool; + assertEq(0, s_tokenPool.getRemotePool(chainSelector).length); TokenPool.ChainUpdate[] memory chainUpdates = new TokenPool.ChainUpdate[](1); chainUpdates[0] = TokenPool.ChainUpdate({ remoteChainSelector: chainSelector, - remotePoolAddresses: remotePoolAddresses, - remoteTokenAddress: remoteToken, + remotePoolAddress: abi.encode(remotePool), + remoteTokenAddress: abi.encode(remoteToken), + allowed: true, outboundRateLimiterConfig: _getOutboundRateLimiterConfig(), inboundRateLimiterConfig: _getInboundRateLimiterConfig() }); - s_tokenPool.applyChainUpdates(new uint64[](0), chainUpdates); + s_tokenPool.applyChainUpdates(chainUpdates); - bytes[] memory remotePools = s_tokenPool.getRemotePools(chainSelector); - assertEq(1, remotePools.length); - assertEq(remotePool, remotePools[0]); + assertEq(remotePool, abi.decode(s_tokenPool.getRemotePool(chainSelector), (address))); } } diff --git a/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPool.onlyOffRamp.t.sol b/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPool.onlyOffRamp.t.sol index 7f972010754..c514b343d62 100644 --- a/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPool.onlyOffRamp.t.sol +++ b/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPool.onlyOffRamp.t.sol @@ -1,15 +1,27 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import {Router} from "../../../Router.sol"; +import {RateLimiter} from "../../../libraries/RateLimiter.sol"; import {TokenPool} from "../../../pools/TokenPool.sol"; import {TokenPoolSetup} from "./TokenPoolSetup.t.sol"; contract TokenPool_onlyOffRamp is TokenPoolSetup { - function test_onlyOffRamp() public { - uint64 chainSelector = DEST_CHAIN_SELECTOR; + function test_onlyOffRamp_Success() public { + uint64 chainSelector = 13377; address offRamp = makeAddr("onRamp"); + TokenPool.ChainUpdate[] memory chainUpdate = new TokenPool.ChainUpdate[](1); + chainUpdate[0] = TokenPool.ChainUpdate({ + remoteChainSelector: chainSelector, + remotePoolAddress: abi.encode(address(1)), + remoteTokenAddress: abi.encode(address(2)), + allowed: true, + outboundRateLimiterConfig: _getOutboundRateLimiterConfig(), + inboundRateLimiterConfig: _getInboundRateLimiterConfig() + }); + s_tokenPool.applyChainUpdates(chainUpdate); + Router.OffRamp[] memory offRampUpdates = new Router.OffRamp[](1); offRampUpdates[0] = Router.OffRamp({sourceChainSelector: chainSelector, offRamp: offRamp}); s_sourceRouter.applyRampUpdates(new Router.OnRamp[](0), new Router.OffRamp[](0), offRampUpdates); @@ -19,8 +31,8 @@ contract TokenPool_onlyOffRamp is TokenPoolSetup { s_tokenPool.onlyOffRampModifier(chainSelector); } - function test_RevertWhen_ChainNotAllowed() public { - uint64 chainSelector = DEST_CHAIN_SELECTOR + 1; + function test_ChainNotAllowed_Revert() public { + uint64 chainSelector = 13377; address offRamp = makeAddr("onRamp"); vm.startPrank(offRamp); @@ -33,12 +45,13 @@ contract TokenPool_onlyOffRamp is TokenPoolSetup { TokenPool.ChainUpdate[] memory chainUpdate = new TokenPool.ChainUpdate[](1); chainUpdate[0] = TokenPool.ChainUpdate({ remoteChainSelector: chainSelector, - remotePoolAddresses: new bytes[](0), + remotePoolAddress: abi.encode(address(1)), remoteTokenAddress: abi.encode(address(2)), + allowed: true, outboundRateLimiterConfig: _getOutboundRateLimiterConfig(), inboundRateLimiterConfig: _getInboundRateLimiterConfig() }); - s_tokenPool.applyChainUpdates(new uint64[](0), chainUpdate); + s_tokenPool.applyChainUpdates(chainUpdate); Router.OffRamp[] memory offRampUpdates = new Router.OffRamp[](1); offRampUpdates[0] = Router.OffRamp({sourceChainSelector: chainSelector, offRamp: offRamp}); @@ -48,11 +61,17 @@ contract TokenPool_onlyOffRamp is TokenPoolSetup { // Should succeed now that we've added the chain s_tokenPool.onlyOffRampModifier(chainSelector); - uint64[] memory chainsToRemove = new uint64[](1); - chainsToRemove[0] = chainSelector; + chainUpdate[0] = TokenPool.ChainUpdate({ + remoteChainSelector: chainSelector, + remotePoolAddress: abi.encode(address(1)), + remoteTokenAddress: abi.encode(address(2)), + allowed: false, + outboundRateLimiterConfig: RateLimiter.Config({isEnabled: false, capacity: 0, rate: 0}), + inboundRateLimiterConfig: RateLimiter.Config({isEnabled: false, capacity: 0, rate: 0}) + }); vm.startPrank(OWNER); - s_tokenPool.applyChainUpdates(chainsToRemove, new TokenPool.ChainUpdate[](0)); + s_tokenPool.applyChainUpdates(chainUpdate); vm.startPrank(offRamp); @@ -60,10 +79,21 @@ contract TokenPool_onlyOffRamp is TokenPoolSetup { s_tokenPool.onlyOffRampModifier(chainSelector); } - function test_RevertWhen_CallerIsNotARampOnRouter() public { - uint64 chainSelector = DEST_CHAIN_SELECTOR; + function test_CallerIsNotARampOnRouter_Revert() public { + uint64 chainSelector = 13377; address offRamp = makeAddr("offRamp"); + TokenPool.ChainUpdate[] memory chainUpdate = new TokenPool.ChainUpdate[](1); + chainUpdate[0] = TokenPool.ChainUpdate({ + remoteChainSelector: chainSelector, + remotePoolAddress: abi.encode(address(1)), + remoteTokenAddress: abi.encode(address(2)), + allowed: true, + outboundRateLimiterConfig: _getOutboundRateLimiterConfig(), + inboundRateLimiterConfig: _getInboundRateLimiterConfig() + }); + s_tokenPool.applyChainUpdates(chainUpdate); + vm.startPrank(offRamp); vm.expectRevert(abi.encodeWithSelector(TokenPool.CallerIsNotARampOnRouter.selector, offRamp)); diff --git a/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPool.onlyOnRamp.t.sol b/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPool.onlyOnRamp.t.sol index 970228c424f..5e3e6e31c12 100644 --- a/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPool.onlyOnRamp.t.sol +++ b/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPool.onlyOnRamp.t.sol @@ -1,15 +1,27 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import {Router} from "../../../Router.sol"; +import {RateLimiter} from "../../../libraries/RateLimiter.sol"; import {TokenPool} from "../../../pools/TokenPool.sol"; import {TokenPoolSetup} from "./TokenPoolSetup.t.sol"; contract TokenPool_onlyOnRamp is TokenPoolSetup { - function test_onlyOnRamp() public { - uint64 chainSelector = DEST_CHAIN_SELECTOR; + function test_onlyOnRamp_Success() public { + uint64 chainSelector = 13377; address onRamp = makeAddr("onRamp"); + TokenPool.ChainUpdate[] memory chainUpdate = new TokenPool.ChainUpdate[](1); + chainUpdate[0] = TokenPool.ChainUpdate({ + remoteChainSelector: chainSelector, + remotePoolAddress: abi.encode(address(1)), + remoteTokenAddress: abi.encode(address(2)), + allowed: true, + outboundRateLimiterConfig: _getOutboundRateLimiterConfig(), + inboundRateLimiterConfig: _getInboundRateLimiterConfig() + }); + s_tokenPool.applyChainUpdates(chainUpdate); + Router.OnRamp[] memory onRampUpdates = new Router.OnRamp[](1); onRampUpdates[0] = Router.OnRamp({destChainSelector: chainSelector, onRamp: onRamp}); s_sourceRouter.applyRampUpdates(onRampUpdates, new Router.OffRamp[](0), new Router.OffRamp[](0)); @@ -19,8 +31,8 @@ contract TokenPool_onlyOnRamp is TokenPoolSetup { s_tokenPool.onlyOnRampModifier(chainSelector); } - function test_RevertWhen_ChainNotAllowed() public { - uint64 chainSelector = DEST_CHAIN_SELECTOR + 1; + function test_ChainNotAllowed_Revert() public { + uint64 chainSelector = 13377; address onRamp = makeAddr("onRamp"); vm.startPrank(onRamp); @@ -33,12 +45,13 @@ contract TokenPool_onlyOnRamp is TokenPoolSetup { TokenPool.ChainUpdate[] memory chainUpdate = new TokenPool.ChainUpdate[](1); chainUpdate[0] = TokenPool.ChainUpdate({ remoteChainSelector: chainSelector, - remotePoolAddresses: new bytes[](0), + remotePoolAddress: abi.encode(address(1)), remoteTokenAddress: abi.encode(address(2)), + allowed: true, outboundRateLimiterConfig: _getOutboundRateLimiterConfig(), inboundRateLimiterConfig: _getInboundRateLimiterConfig() }); - s_tokenPool.applyChainUpdates(new uint64[](0), chainUpdate); + s_tokenPool.applyChainUpdates(chainUpdate); Router.OnRamp[] memory onRampUpdates = new Router.OnRamp[](1); onRampUpdates[0] = Router.OnRamp({destChainSelector: chainSelector, onRamp: onRamp}); @@ -48,11 +61,17 @@ contract TokenPool_onlyOnRamp is TokenPoolSetup { // Should succeed now that we've added the chain s_tokenPool.onlyOnRampModifier(chainSelector); - uint64[] memory chainsToRemove = new uint64[](1); - chainsToRemove[0] = chainSelector; + chainUpdate[0] = TokenPool.ChainUpdate({ + remoteChainSelector: chainSelector, + remotePoolAddress: abi.encode(address(1)), + remoteTokenAddress: abi.encode(address(2)), + allowed: false, + outboundRateLimiterConfig: RateLimiter.Config({isEnabled: false, capacity: 0, rate: 0}), + inboundRateLimiterConfig: RateLimiter.Config({isEnabled: false, capacity: 0, rate: 0}) + }); vm.startPrank(OWNER); - s_tokenPool.applyChainUpdates(chainsToRemove, new TokenPool.ChainUpdate[](0)); + s_tokenPool.applyChainUpdates(chainUpdate); vm.startPrank(onRamp); @@ -60,10 +79,21 @@ contract TokenPool_onlyOnRamp is TokenPoolSetup { s_tokenPool.onlyOffRampModifier(chainSelector); } - function test_RevertWhen_CallerIsNotARampOnRouter() public { - uint64 chainSelector = DEST_CHAIN_SELECTOR; + function test_CallerIsNotARampOnRouter_Revert() public { + uint64 chainSelector = 13377; address onRamp = makeAddr("onRamp"); + TokenPool.ChainUpdate[] memory chainUpdate = new TokenPool.ChainUpdate[](1); + chainUpdate[0] = TokenPool.ChainUpdate({ + remoteChainSelector: chainSelector, + remotePoolAddress: abi.encode(address(1)), + remoteTokenAddress: abi.encode(address(2)), + allowed: true, + outboundRateLimiterConfig: _getOutboundRateLimiterConfig(), + inboundRateLimiterConfig: _getInboundRateLimiterConfig() + }); + s_tokenPool.applyChainUpdates(chainUpdate); + vm.startPrank(onRamp); vm.expectRevert(abi.encodeWithSelector(TokenPool.CallerIsNotARampOnRouter.selector, onRamp)); diff --git a/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPool.parseRemoteDecimals.t.sol b/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPool.parseRemoteDecimals.t.sol deleted file mode 100644 index 49b40fc5c60..00000000000 --- a/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPool.parseRemoteDecimals.t.sol +++ /dev/null @@ -1,36 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; - -import {TokenPool} from "../../../pools/TokenPool.sol"; -import {TokenPoolSetup} from "./TokenPoolSetup.t.sol"; - -contract TokenPool_parseRemoteDecimals is TokenPoolSetup { - function test_parseRemoteDecimals() public view { - uint256 remoteDecimals = 12; - bytes memory encodedDecimals = abi.encode(remoteDecimals); - - assertEq(s_tokenPool.parseRemoteDecimals(encodedDecimals), remoteDecimals); - - assertEq(s_tokenPool.parseRemoteDecimals(s_tokenPool.encodeLocalDecimals()), s_tokenPool.getTokenDecimals()); - } - - function test_parseRemoteDecimals_NoDecimalsDefaultsToLocalDecimals() public view { - assertEq(s_tokenPool.parseRemoteDecimals(""), s_tokenPool.getTokenDecimals()); - } - - function test_RevertWhen_parseRemoteDecimalsWhen_InvalidRemoteChainDecimals_DigitTooLarge() public { - bytes memory encodedDecimals = abi.encode(uint256(256)); - - vm.expectRevert(abi.encodeWithSelector(TokenPool.InvalidRemoteChainDecimals.selector, encodedDecimals)); - - s_tokenPool.parseRemoteDecimals(encodedDecimals); - } - - function test_RevertWhen_parseRemoteDecimalsWhen_InvalidRemoteChainDecimals_WrongType() public { - bytes memory encodedDecimals = abi.encode(uint256(256), "wrong type"); - - vm.expectRevert(abi.encodeWithSelector(TokenPool.InvalidRemoteChainDecimals.selector, encodedDecimals)); - - s_tokenPool.parseRemoteDecimals(encodedDecimals); - } -} diff --git a/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPool.removeRemotePool.t.sol b/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPool.removeRemotePool.t.sol deleted file mode 100644 index ac50a34b8ca..00000000000 --- a/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPool.removeRemotePool.t.sol +++ /dev/null @@ -1,61 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; - -import {TokenPool} from "../../../pools/TokenPool.sol"; -import {TokenPoolSetup} from "./TokenPoolSetup.t.sol"; - -contract TokenPool_removeRemotePool is TokenPoolSetup { - function test_removeRemotePool() public { - uint64 chainSelector = DEST_CHAIN_SELECTOR; - // Use a longer data type to ensure it also works for non-evm - bytes memory remotePool = abi.encode(makeAddr("non-evm-1"), makeAddr("non-evm-2")); - - vm.expectEmit(); - emit TokenPool.RemotePoolAdded(chainSelector, remotePool); - - // Add the remote pool properly so that it can be removed - s_tokenPool.addRemotePool(chainSelector, remotePool); - - bytes[] memory remotePools = s_tokenPool.getRemotePools(chainSelector); - assertEq(remotePools.length, 2); - assertEq(remotePools[0], abi.encode(s_initialRemotePool)); - assertEq(remotePools[1], remotePool); - - vm.expectEmit(); - emit TokenPool.RemotePoolRemoved(chainSelector, remotePool); - - s_tokenPool.removeRemotePool(chainSelector, remotePool); - - remotePools = s_tokenPool.getRemotePools(chainSelector); - assertEq(remotePools.length, 1); - assertEq(remotePools[0], abi.encode(s_initialRemotePool)); - - // Assert that it can be added after it has been removed - s_tokenPool.addRemotePool(chainSelector, remotePool); - - remotePools = s_tokenPool.getRemotePools(chainSelector); - assertEq(remotePools.length, 2); - assertEq(remotePools[0], abi.encode(s_initialRemotePool)); - assertEq(remotePools[1], remotePool); - } - - // Reverts - - function test_RevertWhen_NonExistentChain() public { - uint64 chainSelector = DEST_CHAIN_SELECTOR + 1; - bytes memory remotePool = abi.encode(type(uint256).max); - - vm.expectRevert(abi.encodeWithSelector(TokenPool.NonExistentChain.selector, chainSelector)); - - s_tokenPool.removeRemotePool(chainSelector, remotePool); - } - - function test_RevertWhen_InvalidRemotePoolForChain() public { - uint64 chainSelector = DEST_CHAIN_SELECTOR; - bytes memory remotePool = abi.encode(type(uint256).max); - - vm.expectRevert(abi.encodeWithSelector(TokenPool.InvalidRemotePoolForChain.selector, chainSelector, remotePool)); - - s_tokenPool.removeRemotePool(chainSelector, remotePool); - } -} diff --git a/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPool.setChainRateLimiterConfig.t.sol b/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPool.setChainRateLimiterConfig.t.sol index afb8a649a07..e44dc96f1a8 100644 --- a/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPool.setChainRateLimiterConfig.t.sol +++ b/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPool.setChainRateLimiterConfig.t.sol @@ -1,11 +1,28 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import {RateLimiter} from "../../../libraries/RateLimiter.sol"; import {TokenPool} from "../../../pools/TokenPool.sol"; import {TokenPoolSetup} from "./TokenPoolSetup.t.sol"; contract TokenPool_setChainRateLimiterConfig is TokenPoolSetup { + uint64 internal s_remoteChainSelector; + + function setUp() public virtual override { + TokenPoolSetup.setUp(); + TokenPool.ChainUpdate[] memory chainUpdates = new TokenPool.ChainUpdate[](1); + s_remoteChainSelector = 123124; + chainUpdates[0] = TokenPool.ChainUpdate({ + remoteChainSelector: s_remoteChainSelector, + remotePoolAddress: abi.encode(address(2)), + remoteTokenAddress: abi.encode(address(3)), + allowed: true, + outboundRateLimiterConfig: _getOutboundRateLimiterConfig(), + inboundRateLimiterConfig: _getInboundRateLimiterConfig() + }); + s_tokenPool.applyChainUpdates(chainUpdates); + } + function testFuzz_SetChainRateLimiterConfig_Success(uint128 capacity, uint128 rate, uint32 newTime) public { // Cap the lower bound to 4 so 4/2 is still >= 2 vm.assume(capacity >= 4); @@ -15,8 +32,8 @@ contract TokenPool_setChainRateLimiterConfig is TokenPoolSetup { newTime = uint32(bound(newTime, block.timestamp + 1, type(uint32).max)); vm.warp(newTime); - uint256 oldOutboundTokens = s_tokenPool.getCurrentOutboundRateLimiterState(DEST_CHAIN_SELECTOR).tokens; - uint256 oldInboundTokens = s_tokenPool.getCurrentInboundRateLimiterState(DEST_CHAIN_SELECTOR).tokens; + uint256 oldOutboundTokens = s_tokenPool.getCurrentOutboundRateLimiterState(s_remoteChainSelector).tokens; + uint256 oldInboundTokens = s_tokenPool.getCurrentInboundRateLimiterState(s_remoteChainSelector).tokens; RateLimiter.Config memory newOutboundConfig = RateLimiter.Config({isEnabled: true, capacity: capacity, rate: rate}); RateLimiter.Config memory newInboundConfig = @@ -27,13 +44,13 @@ contract TokenPool_setChainRateLimiterConfig is TokenPoolSetup { vm.expectEmit(); emit RateLimiter.ConfigChanged(newInboundConfig); vm.expectEmit(); - emit TokenPool.ChainConfigured(DEST_CHAIN_SELECTOR, newOutboundConfig, newInboundConfig); + emit TokenPool.ChainConfigured(s_remoteChainSelector, newOutboundConfig, newInboundConfig); - s_tokenPool.setChainRateLimiterConfig(DEST_CHAIN_SELECTOR, newOutboundConfig, newInboundConfig); + s_tokenPool.setChainRateLimiterConfig(s_remoteChainSelector, newOutboundConfig, newInboundConfig); uint256 expectedTokens = RateLimiter._min(newOutboundConfig.capacity, oldOutboundTokens); - RateLimiter.TokenBucket memory bucket = s_tokenPool.getCurrentOutboundRateLimiterState(DEST_CHAIN_SELECTOR); + RateLimiter.TokenBucket memory bucket = s_tokenPool.getCurrentOutboundRateLimiterState(s_remoteChainSelector); assertEq(bucket.capacity, newOutboundConfig.capacity); assertEq(bucket.rate, newOutboundConfig.rate); assertEq(bucket.tokens, expectedTokens); @@ -41,7 +58,7 @@ contract TokenPool_setChainRateLimiterConfig is TokenPoolSetup { expectedTokens = RateLimiter._min(newInboundConfig.capacity, oldInboundTokens); - bucket = s_tokenPool.getCurrentInboundRateLimiterState(DEST_CHAIN_SELECTOR); + bucket = s_tokenPool.getCurrentInboundRateLimiterState(s_remoteChainSelector); assertEq(bucket.capacity, newInboundConfig.capacity); assertEq(bucket.rate, newInboundConfig.rate); assertEq(bucket.tokens, expectedTokens); @@ -50,16 +67,16 @@ contract TokenPool_setChainRateLimiterConfig is TokenPoolSetup { // Reverts - function test_RevertWhen_OnlyOwnerOrRateLimitAdmin() public { + function test_OnlyOwnerOrRateLimitAdmin_Revert() public { vm.startPrank(STRANGER); vm.expectRevert(abi.encodeWithSelector(TokenPool.Unauthorized.selector, STRANGER)); s_tokenPool.setChainRateLimiterConfig( - DEST_CHAIN_SELECTOR, _getOutboundRateLimiterConfig(), _getInboundRateLimiterConfig() + s_remoteChainSelector, _getOutboundRateLimiterConfig(), _getInboundRateLimiterConfig() ); } - function test_RevertWhen_NonExistentChain() public { + function test_NonExistentChain_Revert() public { uint64 wrongChainSelector = 9084102894; vm.expectRevert(abi.encodeWithSelector(TokenPool.NonExistentChain.selector, wrongChainSelector)); diff --git a/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPool.setChainRateLimiterConfigs.t.sol b/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPool.setChainRateLimiterConfigs.t.sol deleted file mode 100644 index 27e01fd5921..00000000000 --- a/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPool.setChainRateLimiterConfigs.t.sol +++ /dev/null @@ -1,128 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; - -import {RateLimiter} from "../../../libraries/RateLimiter.sol"; -import {TokenPool} from "../../../pools/TokenPool.sol"; -import {TokenPoolSetup} from "./TokenPoolSetup.t.sol"; - -contract TokenPool_setChainRateLimiterConfigs is TokenPoolSetup { - uint64 internal s_remoteChainSelector; - - function setUp() public virtual override { - TokenPoolSetup.setUp(); - - bytes[] memory remotePoolAddresses = new bytes[](1); - remotePoolAddresses[0] = abi.encode(address(2)); - - TokenPool.ChainUpdate[] memory chainUpdates = new TokenPool.ChainUpdate[](1); - s_remoteChainSelector = 123124; - chainUpdates[0] = TokenPool.ChainUpdate({ - remoteChainSelector: s_remoteChainSelector, - remotePoolAddresses: remotePoolAddresses, - remoteTokenAddress: abi.encode(address(3)), - outboundRateLimiterConfig: _getOutboundRateLimiterConfig(), - inboundRateLimiterConfig: _getInboundRateLimiterConfig() - }); - s_tokenPool.applyChainUpdates(new uint64[](0), chainUpdates); - } - - function testFuzz_SetChainRateLimiterConfigs_Success(uint128 capacity, uint128 rate, uint32 newTime) public { - // Cap the lower bound to 4 so 4/2 is still >= 2 - vm.assume(capacity >= 4); - // Cap the lower bound to 2 so 2/2 is still >= 1 - rate = uint128(bound(rate, 2, capacity - 2)); - // Bucket updates only work on increasing time - newTime = uint32(bound(newTime, block.timestamp + 1, type(uint32).max)); - vm.warp(newTime); - - uint256 oldOutboundTokens = s_tokenPool.getCurrentOutboundRateLimiterState(DEST_CHAIN_SELECTOR).tokens; - uint256 oldInboundTokens = s_tokenPool.getCurrentInboundRateLimiterState(DEST_CHAIN_SELECTOR).tokens; - - RateLimiter.Config memory newOutboundConfig = RateLimiter.Config({isEnabled: true, capacity: capacity, rate: rate}); - RateLimiter.Config memory newInboundConfig = - RateLimiter.Config({isEnabled: true, capacity: capacity / 2, rate: rate / 2}); - - uint64[] memory chainSelectors = new uint64[](1); - chainSelectors[0] = DEST_CHAIN_SELECTOR; - - RateLimiter.Config[] memory newOutboundConfigs = new RateLimiter.Config[](1); - newOutboundConfigs[0] = newOutboundConfig; - - RateLimiter.Config[] memory newInboundConfigs = new RateLimiter.Config[](1); - newInboundConfigs[0] = newInboundConfig; - - vm.expectEmit(); - emit RateLimiter.ConfigChanged(newOutboundConfig); - vm.expectEmit(); - emit RateLimiter.ConfigChanged(newInboundConfig); - vm.expectEmit(); - emit TokenPool.ChainConfigured(DEST_CHAIN_SELECTOR, newOutboundConfig, newInboundConfig); - - s_tokenPool.setChainRateLimiterConfigs(chainSelectors, newOutboundConfigs, newInboundConfigs); - - uint256 expectedTokens = RateLimiter._min(newOutboundConfig.capacity, oldOutboundTokens); - - RateLimiter.TokenBucket memory bucket = s_tokenPool.getCurrentOutboundRateLimiterState(DEST_CHAIN_SELECTOR); - assertEq(bucket.capacity, newOutboundConfig.capacity); - assertEq(bucket.rate, newOutboundConfig.rate); - assertEq(bucket.tokens, expectedTokens); - assertEq(bucket.lastUpdated, newTime); - - expectedTokens = RateLimiter._min(newInboundConfig.capacity, oldInboundTokens); - - bucket = s_tokenPool.getCurrentInboundRateLimiterState(DEST_CHAIN_SELECTOR); - assertEq(bucket.capacity, newInboundConfig.capacity); - assertEq(bucket.rate, newInboundConfig.rate); - assertEq(bucket.tokens, expectedTokens); - assertEq(bucket.lastUpdated, newTime); - } - - // Reverts - - function test_RevertWhen_OnlyOwnerOrRateLimitAdmin() public { - uint64[] memory chainSelectors = new uint64[](1); - chainSelectors[0] = DEST_CHAIN_SELECTOR; - - RateLimiter.Config[] memory newOutboundConfigs = new RateLimiter.Config[](1); - newOutboundConfigs[0] = _getOutboundRateLimiterConfig(); - - RateLimiter.Config[] memory newInboundConfigs = new RateLimiter.Config[](1); - newInboundConfigs[0] = _getInboundRateLimiterConfig(); - - vm.startPrank(STRANGER); - - vm.expectRevert(abi.encodeWithSelector(TokenPool.Unauthorized.selector, STRANGER)); - s_tokenPool.setChainRateLimiterConfigs(chainSelectors, newOutboundConfigs, newInboundConfigs); - } - - function test_RevertWhen_NonExistentChain() public { - uint64 wrongChainSelector = 9084102894; - - uint64[] memory chainSelectors = new uint64[](1); - chainSelectors[0] = wrongChainSelector; - - RateLimiter.Config[] memory newOutboundConfigs = new RateLimiter.Config[](1); - RateLimiter.Config[] memory newInboundConfigs = new RateLimiter.Config[](1); - - vm.expectRevert(abi.encodeWithSelector(TokenPool.NonExistentChain.selector, wrongChainSelector)); - s_tokenPool.setChainRateLimiterConfigs(chainSelectors, newOutboundConfigs, newInboundConfigs); - } - - function test_RevertWhen_MismatchedArrayLengths() public { - uint64[] memory chainSelectors = new uint64[](1); - - RateLimiter.Config[] memory newOutboundConfigs = new RateLimiter.Config[](1); - RateLimiter.Config[] memory newInboundConfigs = new RateLimiter.Config[](2); - - // test mismatched array lengths between rate limiters - vm.expectRevert(abi.encodeWithSelector(TokenPool.MismatchedArrayLengths.selector)); - s_tokenPool.setChainRateLimiterConfigs(chainSelectors, newOutboundConfigs, newInboundConfigs); - - newInboundConfigs = new RateLimiter.Config[](1); - chainSelectors = new uint64[](2); - - // test mismatched array lengths between chain selectors and rate limiters - vm.expectRevert(abi.encodeWithSelector(TokenPool.MismatchedArrayLengths.selector)); - s_tokenPool.setChainRateLimiterConfigs(chainSelectors, newOutboundConfigs, newInboundConfigs); - } -} diff --git a/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPool.setRateLimitAdmin.t.sol b/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPool.setRateLimitAdmin.t.sol index 0d6622f859a..7c57741cf42 100644 --- a/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPool.setRateLimitAdmin.t.sol +++ b/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPool.setRateLimitAdmin.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import {Ownable2Step} from "../../../../shared/access/Ownable2Step.sol"; @@ -7,7 +7,7 @@ import {TokenPool} from "../../../pools/TokenPool.sol"; import {TokenPoolSetup} from "./TokenPoolSetup.t.sol"; contract TokenPool_setRateLimitAdmin is TokenPoolSetup { - function test_SetRateLimitAdmin() public { + function test_SetRateLimitAdmin_Success() public { assertEq(address(0), s_tokenPool.getRateLimitAdmin()); vm.expectEmit(); emit TokenPool.RateLimitAdminSet(OWNER); @@ -17,7 +17,7 @@ contract TokenPool_setRateLimitAdmin is TokenPoolSetup { // Reverts - function test_RevertWhen_SetRateLimitAdmin() public { + function test_SetRateLimitAdmin_Revert() public { vm.startPrank(STRANGER); vm.expectRevert(Ownable2Step.OnlyCallableByOwner.selector); diff --git a/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPool.setRemotePool.t.sol b/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPool.setRemotePool.t.sol new file mode 100644 index 00000000000..d305e131793 --- /dev/null +++ b/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPool.setRemotePool.t.sol @@ -0,0 +1,51 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.24; + +import {Ownable2Step} from "../../../../shared/access/Ownable2Step.sol"; +import {TokenPool} from "../../../pools/TokenPool.sol"; +import {TokenPoolSetup} from "./TokenPoolSetup.t.sol"; + +contract TokenPool_setRemotePool is TokenPoolSetup { + function test_setRemotePool_Success() public { + uint64 chainSelector = DEST_CHAIN_SELECTOR; + address initialPool = makeAddr("remotePool"); + address remoteToken = makeAddr("remoteToken"); + // The new pool is a non-evm pool, as it doesn't fit in the normal 160 bits + bytes memory newPool = abi.encode(type(uint256).max); + + TokenPool.ChainUpdate[] memory chainUpdates = new TokenPool.ChainUpdate[](1); + chainUpdates[0] = TokenPool.ChainUpdate({ + remoteChainSelector: chainSelector, + remotePoolAddress: abi.encode(initialPool), + remoteTokenAddress: abi.encode(remoteToken), + allowed: true, + outboundRateLimiterConfig: _getOutboundRateLimiterConfig(), + inboundRateLimiterConfig: _getInboundRateLimiterConfig() + }); + s_tokenPool.applyChainUpdates(chainUpdates); + + vm.expectEmit(); + emit TokenPool.RemotePoolSet(chainSelector, abi.encode(initialPool), newPool); + + s_tokenPool.setRemotePool(chainSelector, newPool); + + assertEq(keccak256(newPool), keccak256(s_tokenPool.getRemotePool(chainSelector))); + } + + // Reverts + + function test_setRemotePool_NonExistentChain_Reverts() public { + uint64 chainSelector = 123124; + bytes memory remotePool = abi.encode(makeAddr("remotePool")); + + vm.expectRevert(abi.encodeWithSelector(TokenPool.NonExistentChain.selector, chainSelector)); + s_tokenPool.setRemotePool(chainSelector, remotePool); + } + + function test_setRemotePool_OnlyOwner_Reverts() public { + vm.startPrank(STRANGER); + + vm.expectRevert(Ownable2Step.OnlyCallableByOwner.selector); + s_tokenPool.setRemotePool(123124, abi.encode(makeAddr("remotePool"))); + } +} diff --git a/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPool.setRouter.t.sol b/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPool.setRouter.t.sol index 37108e3899b..288b7f7081d 100644 --- a/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPool.setRouter.t.sol +++ b/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPool.setRouter.t.sol @@ -1,11 +1,11 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import {TokenPool} from "../../../pools/TokenPool.sol"; import {TokenPoolWithAllowListSetup} from "./TokenPoolWithAllowListSetup.t.sol"; contract TokenPoolWithAllowList_setRouter is TokenPoolWithAllowListSetup { - function test_SetRouter() public { + function test_SetRouter_Success() public { assertEq(address(s_sourceRouter), s_tokenPool.getRouter()); address newRouter = makeAddr("newRouter"); @@ -17,14 +17,4 @@ contract TokenPoolWithAllowList_setRouter is TokenPoolWithAllowListSetup { assertEq(newRouter, s_tokenPool.getRouter()); } - - // Reverts - - function test_RevertWhen_ZeroAddressNotAllowed() public { - address newRouter = address(0); - - vm.expectRevert(TokenPool.ZeroAddressNotAllowed.selector); - - s_tokenPool.setRouter(newRouter); - } } diff --git a/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPoolSetup.t.sol b/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPoolSetup.t.sol index 0fb44fba024..3d97f0c17c3 100644 --- a/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPoolSetup.t.sol +++ b/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPoolSetup.t.sol @@ -1,40 +1,21 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; -import {BurnMintERC20} from "../../../../shared/token/ERC20/BurnMintERC20.sol"; -import {TokenPool} from "../../../pools/TokenPool.sol"; -import {BaseTest} from "../../BaseTest.t.sol"; +import {BurnMintERC677} from "../../../../shared/token/ERC677/BurnMintERC677.sol"; import {TokenPoolHelper} from "../../helpers/TokenPoolHelper.sol"; +import {RouterSetup} from "../../router/Router/RouterSetup.t.sol"; import {IERC20} from "../../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; -contract TokenPoolSetup is BaseTest { +contract TokenPoolSetup is RouterSetup { IERC20 internal s_token; TokenPoolHelper internal s_tokenPool; - address internal s_initialRemotePool = makeAddr("initialRemotePool"); - address internal s_initialRemoteToken = makeAddr("initialRemoteToken"); - function setUp() public virtual override { - super.setUp(); - s_token = new BurnMintERC20("LINK", "LNK", 18, 0, 0); + RouterSetup.setUp(); + s_token = new BurnMintERC677("LINK", "LNK", 18, 0); deal(address(s_token), OWNER, type(uint256).max); - s_tokenPool = new TokenPoolHelper( - s_token, DEFAULT_TOKEN_DECIMALS, new address[](0), address(s_mockRMNRemote), address(s_sourceRouter) - ); - - bytes[] memory remotePoolAddresses = new bytes[](1); - remotePoolAddresses[0] = abi.encode(s_initialRemotePool); - - TokenPool.ChainUpdate[] memory chainUpdate = new TokenPool.ChainUpdate[](1); - chainUpdate[0] = TokenPool.ChainUpdate({ - remoteChainSelector: DEST_CHAIN_SELECTOR, - remotePoolAddresses: remotePoolAddresses, - remoteTokenAddress: abi.encode(s_initialRemoteToken), - outboundRateLimiterConfig: _getOutboundRateLimiterConfig(), - inboundRateLimiterConfig: _getInboundRateLimiterConfig() - }); - s_tokenPool.applyChainUpdates(new uint64[](0), chainUpdate); + s_tokenPool = new TokenPoolHelper(s_token, new address[](0), address(s_mockRMN), address(s_sourceRouter)); } } diff --git a/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPoolWithAllowListSetup.t.sol b/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPoolWithAllowListSetup.t.sol index f69b004d548..d441c11c352 100644 --- a/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPoolWithAllowListSetup.t.sol +++ b/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPoolWithAllowListSetup.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import {TokenPoolHelper} from "../../helpers/TokenPoolHelper.sol"; import {TokenPoolSetup} from "./TokenPoolSetup.t.sol"; @@ -13,8 +13,6 @@ contract TokenPoolWithAllowListSetup is TokenPoolSetup { s_allowedSenders.push(STRANGER); s_allowedSenders.push(OWNER); - s_tokenPool = new TokenPoolHelper( - s_token, DEFAULT_TOKEN_DECIMALS, s_allowedSenders, address(s_mockRMNRemote), address(s_sourceRouter) - ); + s_tokenPool = new TokenPoolHelper(s_token, s_allowedSenders, address(s_mockRMN), address(s_sourceRouter)); } } diff --git a/contracts/src/v0.8/ccip/test/pools/USDC/HybridLockReleaseUSDCTokenPool/HybridLockReleaseUSDCTokenPool.lockOrBurn.t.sol b/contracts/src/v0.8/ccip/test/pools/USDC/HybridLockReleaseUSDCTokenPool/HybridLockReleaseUSDCTokenPool.lockOrBurn.t.sol index 51556b63d17..b3ee31deade 100644 --- a/contracts/src/v0.8/ccip/test/pools/USDC/HybridLockReleaseUSDCTokenPool/HybridLockReleaseUSDCTokenPool.lockOrBurn.t.sol +++ b/contracts/src/v0.8/ccip/test/pools/USDC/HybridLockReleaseUSDCTokenPool/HybridLockReleaseUSDCTokenPool.lockOrBurn.t.sol @@ -1,17 +1,143 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; +import {IBurnMintERC20} from "../../../../../shared/token/ERC20/IBurnMintERC20.sol"; import {ITokenMessenger} from "../../../../pools/USDC/ITokenMessenger.sol"; +import {BurnMintERC677} from "../../../../../shared/token/ERC677/BurnMintERC677.sol"; +import {Router} from "../../../../Router.sol"; import {Pool} from "../../../../libraries/Pool.sol"; import {RateLimiter} from "../../../../libraries/RateLimiter.sol"; + import {TokenPool} from "../../../../pools/TokenPool.sol"; import {HybridLockReleaseUSDCTokenPool} from "../../../../pools/USDC/HybridLockReleaseUSDCTokenPool.sol"; import {USDCTokenPool} from "../../../../pools/USDC/USDCTokenPool.sol"; -import {HybridLockReleaseUSDCTokenPoolSetup} from "./HybridLockReleaseUSDCTokenPoolSetup.t.sol"; +import {BaseTest} from "../../../BaseTest.t.sol"; +import {MockE2EUSDCTransmitter} from "../../../mocks/MockE2EUSDCTransmitter.sol"; +import {MockUSDCTokenMessenger} from "../../../mocks/MockUSDCTokenMessenger.sol"; + +contract USDCTokenPoolSetup is BaseTest { + IBurnMintERC20 internal s_token; + MockUSDCTokenMessenger internal s_mockUSDC; + MockE2EUSDCTransmitter internal s_mockUSDCTransmitter; + uint32 internal constant USDC_DEST_TOKEN_GAS = 150_000; + + struct USDCMessage { + uint32 version; + uint32 sourceDomain; + uint32 destinationDomain; + uint64 nonce; + bytes32 sender; + bytes32 recipient; + bytes32 destinationCaller; + bytes messageBody; + } + + uint32 internal constant SOURCE_DOMAIN_IDENTIFIER = 0x02020202; + uint32 internal constant DEST_DOMAIN_IDENTIFIER = 0; + + bytes32 internal constant SOURCE_CHAIN_TOKEN_SENDER = bytes32(uint256(uint160(0x01111111221))); + address internal constant SOURCE_CHAIN_USDC_POOL = address(0x23789765456789); + address internal constant DEST_CHAIN_USDC_POOL = address(0x987384873458734); + address internal constant DEST_CHAIN_USDC_TOKEN = address(0x23598918358198766); + + address internal s_routerAllowedOnRamp = address(3456); + address internal s_routerAllowedOffRamp = address(234); + Router internal s_router; + + HybridLockReleaseUSDCTokenPool internal s_usdcTokenPool; + HybridLockReleaseUSDCTokenPool internal s_usdcTokenPoolTransferLiquidity; + address[] internal s_allowedList; + + function setUp() public virtual override { + BaseTest.setUp(); + BurnMintERC677 usdcToken = new BurnMintERC677("LINK", "LNK", 18, 0); + s_token = usdcToken; + deal(address(s_token), OWNER, type(uint256).max); + _setUpRamps(); + + s_mockUSDCTransmitter = new MockE2EUSDCTransmitter(0, DEST_DOMAIN_IDENTIFIER, address(s_token)); + s_mockUSDC = new MockUSDCTokenMessenger(0, address(s_mockUSDCTransmitter)); + + usdcToken.grantMintAndBurnRoles(address(s_mockUSDCTransmitter)); + + s_usdcTokenPool = + new HybridLockReleaseUSDCTokenPool(s_mockUSDC, s_token, new address[](0), address(s_mockRMN), address(s_router)); + + s_usdcTokenPoolTransferLiquidity = + new HybridLockReleaseUSDCTokenPool(s_mockUSDC, s_token, new address[](0), address(s_mockRMN), address(s_router)); + + usdcToken.grantMintAndBurnRoles(address(s_mockUSDC)); + usdcToken.grantMintAndBurnRoles(address(s_usdcTokenPool)); + + TokenPool.ChainUpdate[] memory chainUpdates = new TokenPool.ChainUpdate[](2); + chainUpdates[0] = TokenPool.ChainUpdate({ + remoteChainSelector: SOURCE_CHAIN_SELECTOR, + remotePoolAddress: abi.encode(SOURCE_CHAIN_USDC_POOL), + remoteTokenAddress: abi.encode(address(s_token)), + allowed: true, + outboundRateLimiterConfig: _getOutboundRateLimiterConfig(), + inboundRateLimiterConfig: _getInboundRateLimiterConfig() + }); + chainUpdates[1] = TokenPool.ChainUpdate({ + remoteChainSelector: DEST_CHAIN_SELECTOR, + remotePoolAddress: abi.encode(DEST_CHAIN_USDC_POOL), + remoteTokenAddress: abi.encode(DEST_CHAIN_USDC_TOKEN), + allowed: true, + outboundRateLimiterConfig: _getOutboundRateLimiterConfig(), + inboundRateLimiterConfig: _getInboundRateLimiterConfig() + }); + + s_usdcTokenPool.applyChainUpdates(chainUpdates); + + USDCTokenPool.DomainUpdate[] memory domains = new USDCTokenPool.DomainUpdate[](1); + domains[0] = USDCTokenPool.DomainUpdate({ + destChainSelector: DEST_CHAIN_SELECTOR, + domainIdentifier: 9999, + allowedCaller: keccak256("allowedCaller"), + enabled: true + }); + + s_usdcTokenPool.setDomains(domains); + + vm.expectEmit(); + emit HybridLockReleaseUSDCTokenPool.LiquidityProviderSet(address(0), OWNER, DEST_CHAIN_SELECTOR); + + s_usdcTokenPool.setLiquidityProvider(DEST_CHAIN_SELECTOR, OWNER); + s_usdcTokenPool.setLiquidityProvider(SOURCE_CHAIN_SELECTOR, OWNER); + } + + function _setUpRamps() internal { + s_router = new Router(address(s_token), address(s_mockRMN)); + + Router.OnRamp[] memory onRampUpdates = new Router.OnRamp[](1); + onRampUpdates[0] = Router.OnRamp({destChainSelector: DEST_CHAIN_SELECTOR, onRamp: s_routerAllowedOnRamp}); + Router.OffRamp[] memory offRampUpdates = new Router.OffRamp[](1); + address[] memory offRamps = new address[](1); + offRamps[0] = s_routerAllowedOffRamp; + offRampUpdates[0] = Router.OffRamp({sourceChainSelector: SOURCE_CHAIN_SELECTOR, offRamp: offRamps[0]}); + + s_router.applyRampUpdates(onRampUpdates, new Router.OffRamp[](0), offRampUpdates); + } + + function _generateUSDCMessage( + USDCMessage memory usdcMessage + ) internal pure returns (bytes memory) { + return abi.encodePacked( + usdcMessage.version, + usdcMessage.sourceDomain, + usdcMessage.destinationDomain, + usdcMessage.nonce, + usdcMessage.sender, + usdcMessage.recipient, + usdcMessage.destinationCaller, + usdcMessage.messageBody + ); + } +} -contract HybridLockReleaseUSDCTokenPool_lockOrBurn is HybridLockReleaseUSDCTokenPoolSetup { - function test_onLockReleaseMechanism() public { +contract HybridLockReleaseUSDCTokenPool_lockOrBurn is USDCTokenPoolSetup { + function test_onLockReleaseMechanism_Success() public { bytes32 receiver = bytes32(uint256(uint160(STRANGER))); // Mark the destination chain as supporting CCTP, so use L/R instead. @@ -47,7 +173,7 @@ contract HybridLockReleaseUSDCTokenPool_lockOrBurn is HybridLockReleaseUSDCToken assertEq(s_token.balanceOf(address(s_usdcTokenPool)), amount, "Incorrect token amount in the tokenPool"); } - function test_PrimaryMechanism() public { + function test_PrimaryMechanism_Success() public { bytes32 receiver = bytes32(uint256(uint160(STRANGER))); uint256 amount = 1; @@ -91,9 +217,9 @@ contract HybridLockReleaseUSDCTokenPool_lockOrBurn is HybridLockReleaseUSDCToken assertEq(s_mockUSDC.s_nonce() - 1, nonce); } - function test_onLockReleaseMechanism_thenSwitchToPrimary() public { + function test_onLockReleaseMechanism_thenswitchToPrimary_Success() public { // Test Enabling the LR mechanism and sending an outgoing message - test_PrimaryMechanism(); + test_PrimaryMechanism_Success(); // Disable the LR mechanism so that primary CCTP is used and then attempt to send a message uint64[] memory destChainRemoves = new uint64[](1); @@ -107,10 +233,10 @@ contract HybridLockReleaseUSDCTokenPool_lockOrBurn is HybridLockReleaseUSDCToken s_usdcTokenPool.updateChainSelectorMechanisms(destChainRemoves, new uint64[](0)); // Send an outgoing message - test_PrimaryMechanism(); + test_PrimaryMechanism_Success(); } - function test_RevertWhen_WhileMigrationPause() public { + function test_WhileMigrationPause_Revert() public { // Mark the destination chain as supporting CCTP, so use L/R instead. uint64[] memory destChainAdds = new uint64[](1); destChainAdds[0] = DEST_CHAIN_SELECTOR; diff --git a/contracts/src/v0.8/ccip/test/pools/USDC/HybridLockReleaseUSDCTokenPool/HybridLockReleaseUSDCTokenPool.releaseOrMint.t.sol b/contracts/src/v0.8/ccip/test/pools/USDC/HybridLockReleaseUSDCTokenPool/HybridLockReleaseUSDCTokenPool.releaseOrMint.t.sol index f528ea2586a..305991aa38f 100644 --- a/contracts/src/v0.8/ccip/test/pools/USDC/HybridLockReleaseUSDCTokenPool/HybridLockReleaseUSDCTokenPool.releaseOrMint.t.sol +++ b/contracts/src/v0.8/ccip/test/pools/USDC/HybridLockReleaseUSDCTokenPool/HybridLockReleaseUSDCTokenPool.releaseOrMint.t.sol @@ -1,6 +1,10 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; +import {IBurnMintERC20} from "../../../../../shared/token/ERC20/IBurnMintERC20.sol"; + +import {BurnMintERC677} from "../../../../../shared/token/ERC677/BurnMintERC677.sol"; +import {Router} from "../../../../Router.sol"; import {Internal} from "../../../../libraries/Internal.sol"; import {Pool} from "../../../../libraries/Pool.sol"; import {TokenPool} from "../../../../pools/TokenPool.sol"; @@ -8,11 +12,132 @@ import {HybridLockReleaseUSDCTokenPool} from "../../../../pools/USDC/HybridLockR import {LOCK_RELEASE_FLAG} from "../../../../pools/USDC/HybridLockReleaseUSDCTokenPool.sol"; import {USDCBridgeMigrator} from "../../../../pools/USDC/USDCBridgeMigrator.sol"; import {USDCTokenPool} from "../../../../pools/USDC/USDCTokenPool.sol"; +import {BaseTest} from "../../../BaseTest.t.sol"; import {MockE2EUSDCTransmitter} from "../../../mocks/MockE2EUSDCTransmitter.sol"; -import {HybridLockReleaseUSDCTokenPoolSetup} from "./HybridLockReleaseUSDCTokenPoolSetup.t.sol"; +import {MockUSDCTokenMessenger} from "../../../mocks/MockUSDCTokenMessenger.sol"; + +contract USDCTokenPoolSetup is BaseTest { + IBurnMintERC20 internal s_token; + MockUSDCTokenMessenger internal s_mockUSDC; + MockE2EUSDCTransmitter internal s_mockUSDCTransmitter; + uint32 internal constant USDC_DEST_TOKEN_GAS = 150_000; + + struct USDCMessage { + uint32 version; + uint32 sourceDomain; + uint32 destinationDomain; + uint64 nonce; + bytes32 sender; + bytes32 recipient; + bytes32 destinationCaller; + bytes messageBody; + } + + uint32 internal constant SOURCE_DOMAIN_IDENTIFIER = 0x02020202; + uint32 internal constant DEST_DOMAIN_IDENTIFIER = 0; + + bytes32 internal constant SOURCE_CHAIN_TOKEN_SENDER = bytes32(uint256(uint160(0x01111111221))); + address internal constant SOURCE_CHAIN_USDC_POOL = address(0x23789765456789); + address internal constant DEST_CHAIN_USDC_POOL = address(0x987384873458734); + address internal constant DEST_CHAIN_USDC_TOKEN = address(0x23598918358198766); + + address internal s_routerAllowedOnRamp = address(3456); + address internal s_routerAllowedOffRamp = address(234); + Router internal s_router; + + HybridLockReleaseUSDCTokenPool internal s_usdcTokenPool; + HybridLockReleaseUSDCTokenPool internal s_usdcTokenPoolTransferLiquidity; + address[] internal s_allowedList; + + function setUp() public virtual override { + BaseTest.setUp(); + BurnMintERC677 usdcToken = new BurnMintERC677("LINK", "LNK", 18, 0); + s_token = usdcToken; + deal(address(s_token), OWNER, type(uint256).max); + _setUpRamps(); + + s_mockUSDCTransmitter = new MockE2EUSDCTransmitter(0, DEST_DOMAIN_IDENTIFIER, address(s_token)); + s_mockUSDC = new MockUSDCTokenMessenger(0, address(s_mockUSDCTransmitter)); + + usdcToken.grantMintAndBurnRoles(address(s_mockUSDCTransmitter)); + + s_usdcTokenPool = + new HybridLockReleaseUSDCTokenPool(s_mockUSDC, s_token, new address[](0), address(s_mockRMN), address(s_router)); + + s_usdcTokenPoolTransferLiquidity = + new HybridLockReleaseUSDCTokenPool(s_mockUSDC, s_token, new address[](0), address(s_mockRMN), address(s_router)); + + usdcToken.grantMintAndBurnRoles(address(s_mockUSDC)); + usdcToken.grantMintAndBurnRoles(address(s_usdcTokenPool)); + + TokenPool.ChainUpdate[] memory chainUpdates = new TokenPool.ChainUpdate[](2); + chainUpdates[0] = TokenPool.ChainUpdate({ + remoteChainSelector: SOURCE_CHAIN_SELECTOR, + remotePoolAddress: abi.encode(SOURCE_CHAIN_USDC_POOL), + remoteTokenAddress: abi.encode(address(s_token)), + allowed: true, + outboundRateLimiterConfig: _getOutboundRateLimiterConfig(), + inboundRateLimiterConfig: _getInboundRateLimiterConfig() + }); + chainUpdates[1] = TokenPool.ChainUpdate({ + remoteChainSelector: DEST_CHAIN_SELECTOR, + remotePoolAddress: abi.encode(DEST_CHAIN_USDC_POOL), + remoteTokenAddress: abi.encode(DEST_CHAIN_USDC_TOKEN), + allowed: true, + outboundRateLimiterConfig: _getOutboundRateLimiterConfig(), + inboundRateLimiterConfig: _getInboundRateLimiterConfig() + }); + + s_usdcTokenPool.applyChainUpdates(chainUpdates); + + USDCTokenPool.DomainUpdate[] memory domains = new USDCTokenPool.DomainUpdate[](1); + domains[0] = USDCTokenPool.DomainUpdate({ + destChainSelector: DEST_CHAIN_SELECTOR, + domainIdentifier: 9999, + allowedCaller: keccak256("allowedCaller"), + enabled: true + }); + + s_usdcTokenPool.setDomains(domains); + + vm.expectEmit(); + emit HybridLockReleaseUSDCTokenPool.LiquidityProviderSet(address(0), OWNER, DEST_CHAIN_SELECTOR); + + s_usdcTokenPool.setLiquidityProvider(DEST_CHAIN_SELECTOR, OWNER); + s_usdcTokenPool.setLiquidityProvider(SOURCE_CHAIN_SELECTOR, OWNER); + } + + function _setUpRamps() internal { + s_router = new Router(address(s_token), address(s_mockRMN)); + + Router.OnRamp[] memory onRampUpdates = new Router.OnRamp[](1); + onRampUpdates[0] = Router.OnRamp({destChainSelector: DEST_CHAIN_SELECTOR, onRamp: s_routerAllowedOnRamp}); + Router.OffRamp[] memory offRampUpdates = new Router.OffRamp[](1); + address[] memory offRamps = new address[](1); + offRamps[0] = s_routerAllowedOffRamp; + offRampUpdates[0] = Router.OffRamp({sourceChainSelector: SOURCE_CHAIN_SELECTOR, offRamp: offRamps[0]}); + + s_router.applyRampUpdates(onRampUpdates, new Router.OffRamp[](0), offRampUpdates); + } + + function _generateUSDCMessage( + USDCMessage memory usdcMessage + ) internal pure returns (bytes memory) { + return abi.encodePacked( + usdcMessage.version, + usdcMessage.sourceDomain, + usdcMessage.destinationDomain, + usdcMessage.nonce, + usdcMessage.sender, + usdcMessage.recipient, + usdcMessage.destinationCaller, + usdcMessage.messageBody + ); + } +} -contract HybridLockReleaseUSDCTokenPool_releaseOrMint is HybridLockReleaseUSDCTokenPoolSetup { - function test_OnLockReleaseMechanism() public { +contract HybridLockReleaseUSDCTokenPool_releaseOrMint is USDCTokenPoolSetup { + function test_OnLockReleaseMechanism_Success() public { address recipient = address(1234); // Designate the SOURCE_CHAIN as not using native-USDC, and so the L/R mechanism must be used instead @@ -120,7 +245,7 @@ contract HybridLockReleaseUSDCTokenPool_releaseOrMint is HybridLockReleaseUSDCTo ); } - function test_RevertWhen_WhileMigrationPause() public { + function test_WhileMigrationPause_Revert() public { address recipient = address(1234); // Designate the SOURCE_CHAIN as not using native-USDC, and so the L/R mechanism must be used instead diff --git a/contracts/src/v0.8/ccip/test/pools/USDC/HybridLockReleaseUSDCTokenPool/HybridLockReleaseUSDCTokenPool.transferLiquidity.t.sol b/contracts/src/v0.8/ccip/test/pools/USDC/HybridLockReleaseUSDCTokenPool/HybridLockReleaseUSDCTokenPool.transferLiquidity.t.sol index d0600d26b88..07eeadf486a 100644 --- a/contracts/src/v0.8/ccip/test/pools/USDC/HybridLockReleaseUSDCTokenPool/HybridLockReleaseUSDCTokenPool.transferLiquidity.t.sol +++ b/contracts/src/v0.8/ccip/test/pools/USDC/HybridLockReleaseUSDCTokenPool/HybridLockReleaseUSDCTokenPool.transferLiquidity.t.sol @@ -1,13 +1,141 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import {ILiquidityContainer} from "../../../../../liquiditymanager/interfaces/ILiquidityContainer.sol"; +import {IBurnMintERC20} from "../../../../../shared/token/ERC20/IBurnMintERC20.sol"; +import {BurnMintERC677} from "../../../../../shared/token/ERC677/BurnMintERC677.sol"; +import {Router} from "../../../../Router.sol"; + +import {TokenPool} from "../../../../pools/TokenPool.sol"; import {HybridLockReleaseUSDCTokenPool} from "../../../../pools/USDC/HybridLockReleaseUSDCTokenPool.sol"; -import {HybridLockReleaseUSDCTokenPoolSetup} from "./HybridLockReleaseUSDCTokenPoolSetup.t.sol"; +import {USDCTokenPool} from "../../../../pools/USDC/USDCTokenPool.sol"; +import {BaseTest} from "../../../BaseTest.t.sol"; +import {MockE2EUSDCTransmitter} from "../../../mocks/MockE2EUSDCTransmitter.sol"; +import {MockUSDCTokenMessenger} from "../../../mocks/MockUSDCTokenMessenger.sol"; + +contract USDCTokenPoolSetup is BaseTest { + IBurnMintERC20 internal s_token; + MockUSDCTokenMessenger internal s_mockUSDC; + MockE2EUSDCTransmitter internal s_mockUSDCTransmitter; + uint32 internal constant USDC_DEST_TOKEN_GAS = 150_000; + + struct USDCMessage { + uint32 version; + uint32 sourceDomain; + uint32 destinationDomain; + uint64 nonce; + bytes32 sender; + bytes32 recipient; + bytes32 destinationCaller; + bytes messageBody; + } + + uint32 internal constant SOURCE_DOMAIN_IDENTIFIER = 0x02020202; + uint32 internal constant DEST_DOMAIN_IDENTIFIER = 0; + + bytes32 internal constant SOURCE_CHAIN_TOKEN_SENDER = bytes32(uint256(uint160(0x01111111221))); + address internal constant SOURCE_CHAIN_USDC_POOL = address(0x23789765456789); + address internal constant DEST_CHAIN_USDC_POOL = address(0x987384873458734); + address internal constant DEST_CHAIN_USDC_TOKEN = address(0x23598918358198766); + + address internal s_routerAllowedOnRamp = address(3456); + address internal s_routerAllowedOffRamp = address(234); + Router internal s_router; + + HybridLockReleaseUSDCTokenPool internal s_usdcTokenPool; + HybridLockReleaseUSDCTokenPool internal s_usdcTokenPoolTransferLiquidity; + address[] internal s_allowedList; + + function setUp() public virtual override { + BaseTest.setUp(); + BurnMintERC677 usdcToken = new BurnMintERC677("LINK", "LNK", 18, 0); + s_token = usdcToken; + deal(address(s_token), OWNER, type(uint256).max); + _setUpRamps(); + + s_mockUSDCTransmitter = new MockE2EUSDCTransmitter(0, DEST_DOMAIN_IDENTIFIER, address(s_token)); + s_mockUSDC = new MockUSDCTokenMessenger(0, address(s_mockUSDCTransmitter)); + + usdcToken.grantMintAndBurnRoles(address(s_mockUSDCTransmitter)); + + s_usdcTokenPool = + new HybridLockReleaseUSDCTokenPool(s_mockUSDC, s_token, new address[](0), address(s_mockRMN), address(s_router)); + + s_usdcTokenPoolTransferLiquidity = + new HybridLockReleaseUSDCTokenPool(s_mockUSDC, s_token, new address[](0), address(s_mockRMN), address(s_router)); + + usdcToken.grantMintAndBurnRoles(address(s_mockUSDC)); + usdcToken.grantMintAndBurnRoles(address(s_usdcTokenPool)); + + TokenPool.ChainUpdate[] memory chainUpdates = new TokenPool.ChainUpdate[](2); + chainUpdates[0] = TokenPool.ChainUpdate({ + remoteChainSelector: SOURCE_CHAIN_SELECTOR, + remotePoolAddress: abi.encode(SOURCE_CHAIN_USDC_POOL), + remoteTokenAddress: abi.encode(address(s_token)), + allowed: true, + outboundRateLimiterConfig: _getOutboundRateLimiterConfig(), + inboundRateLimiterConfig: _getInboundRateLimiterConfig() + }); + chainUpdates[1] = TokenPool.ChainUpdate({ + remoteChainSelector: DEST_CHAIN_SELECTOR, + remotePoolAddress: abi.encode(DEST_CHAIN_USDC_POOL), + remoteTokenAddress: abi.encode(DEST_CHAIN_USDC_TOKEN), + allowed: true, + outboundRateLimiterConfig: _getOutboundRateLimiterConfig(), + inboundRateLimiterConfig: _getInboundRateLimiterConfig() + }); + + s_usdcTokenPool.applyChainUpdates(chainUpdates); + + USDCTokenPool.DomainUpdate[] memory domains = new USDCTokenPool.DomainUpdate[](1); + domains[0] = USDCTokenPool.DomainUpdate({ + destChainSelector: DEST_CHAIN_SELECTOR, + domainIdentifier: 9999, + allowedCaller: keccak256("allowedCaller"), + enabled: true + }); + + s_usdcTokenPool.setDomains(domains); + + vm.expectEmit(); + emit HybridLockReleaseUSDCTokenPool.LiquidityProviderSet(address(0), OWNER, DEST_CHAIN_SELECTOR); + + s_usdcTokenPool.setLiquidityProvider(DEST_CHAIN_SELECTOR, OWNER); + s_usdcTokenPool.setLiquidityProvider(SOURCE_CHAIN_SELECTOR, OWNER); + } + + function _setUpRamps() internal { + s_router = new Router(address(s_token), address(s_mockRMN)); + + Router.OnRamp[] memory onRampUpdates = new Router.OnRamp[](1); + onRampUpdates[0] = Router.OnRamp({destChainSelector: DEST_CHAIN_SELECTOR, onRamp: s_routerAllowedOnRamp}); + Router.OffRamp[] memory offRampUpdates = new Router.OffRamp[](1); + address[] memory offRamps = new address[](1); + offRamps[0] = s_routerAllowedOffRamp; + offRampUpdates[0] = Router.OffRamp({sourceChainSelector: SOURCE_CHAIN_SELECTOR, offRamp: offRamps[0]}); + + s_router.applyRampUpdates(onRampUpdates, new Router.OffRamp[](0), offRampUpdates); + } + + function _generateUSDCMessage( + USDCMessage memory usdcMessage + ) internal pure returns (bytes memory) { + return abi.encodePacked( + usdcMessage.version, + usdcMessage.sourceDomain, + usdcMessage.destinationDomain, + usdcMessage.nonce, + usdcMessage.sender, + usdcMessage.recipient, + usdcMessage.destinationCaller, + usdcMessage.messageBody + ); + } +} -contract HybridLockReleaseUSDCTokenPool_TransferLiquidity is HybridLockReleaseUSDCTokenPoolSetup { - function test_transferLiquidity() public { +contract HybridLockReleaseUSDCTokenPool_TransferLiquidity is USDCTokenPoolSetup { + function test_transferLiquidity_Success() public { // Set as the OWNER so we can provide liquidity vm.startPrank(OWNER); @@ -63,7 +191,7 @@ contract HybridLockReleaseUSDCTokenPool_TransferLiquidity is HybridLockReleaseUS ); } - function test_RevertWhen_cannotTransferLiquidityDuringPendingMigration() public { + function test_cannotTransferLiquidityDuringPendingMigration_Revert() public { // Set as the OWNER so we can provide liquidity vm.startPrank(OWNER); diff --git a/contracts/src/v0.8/ccip/test/pools/USDC/HybridLockReleaseUSDCTokenPool/HybridLockReleaseUSDCTokenPoolSetup.t.sol b/contracts/src/v0.8/ccip/test/pools/USDC/HybridLockReleaseUSDCTokenPool/HybridLockReleaseUSDCTokenPoolSetup.t.sol deleted file mode 100644 index 13262fa6472..00000000000 --- a/contracts/src/v0.8/ccip/test/pools/USDC/HybridLockReleaseUSDCTokenPool/HybridLockReleaseUSDCTokenPoolSetup.t.sol +++ /dev/null @@ -1,43 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; - -import {BurnMintERC677} from "../../../../../shared/token/ERC677/BurnMintERC677.sol"; - -import {HybridLockReleaseUSDCTokenPool} from "../../../../pools/USDC/HybridLockReleaseUSDCTokenPool.sol"; -import {USDCTokenPool} from "../../../../pools/USDC/USDCTokenPool.sol"; -import {USDCSetup} from "../USDCSetup.t.sol"; - -contract HybridLockReleaseUSDCTokenPoolSetup is USDCSetup { - HybridLockReleaseUSDCTokenPool internal s_usdcTokenPool; - HybridLockReleaseUSDCTokenPool internal s_usdcTokenPoolTransferLiquidity; - address[] internal s_allowedList; - - function setUp() public virtual override { - super.setUp(); - - s_usdcTokenPool = new HybridLockReleaseUSDCTokenPool( - s_mockUSDC, s_token, new address[](0), address(s_mockRMNRemote), address(s_router) - ); - - s_usdcTokenPoolTransferLiquidity = new HybridLockReleaseUSDCTokenPool( - s_mockUSDC, s_token, new address[](0), address(s_mockRMNRemote), address(s_router) - ); - - BurnMintERC677(address(s_token)).grantMintAndBurnRoles(address(s_usdcTokenPool)); - - _poolApplyChainUpdates(address(s_usdcTokenPool)); - - USDCTokenPool.DomainUpdate[] memory domains = new USDCTokenPool.DomainUpdate[](1); - domains[0] = USDCTokenPool.DomainUpdate({ - destChainSelector: DEST_CHAIN_SELECTOR, - domainIdentifier: 9999, - allowedCaller: keccak256("allowedCaller"), - enabled: true - }); - - s_usdcTokenPool.setDomains(domains); - - s_usdcTokenPool.setLiquidityProvider(DEST_CHAIN_SELECTOR, OWNER); - s_usdcTokenPool.setLiquidityProvider(SOURCE_CHAIN_SELECTOR, OWNER); - } -} diff --git a/contracts/src/v0.8/ccip/test/pools/USDC/USDCBridgeMigrator/USDCBridgeMigrator.burnLockedUSDC.t.sol b/contracts/src/v0.8/ccip/test/pools/USDC/USDCBridgeMigrator/USDCBridgeMigrator.burnLockedUSDC.t.sol index 59055fe4978..b95d821bb88 100644 --- a/contracts/src/v0.8/ccip/test/pools/USDC/USDCBridgeMigrator/USDCBridgeMigrator.burnLockedUSDC.t.sol +++ b/contracts/src/v0.8/ccip/test/pools/USDC/USDCBridgeMigrator/USDCBridgeMigrator.burnLockedUSDC.t.sol @@ -1,14 +1,144 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; +import {IBurnMintERC20} from "../../../../../shared/token/ERC20/IBurnMintERC20.sol"; + +import {BurnMintERC677} from "../../../../../shared/token/ERC677/BurnMintERC677.sol"; +import {Router} from "../../../../Router.sol"; import {Pool} from "../../../../libraries/Pool.sol"; + import {TokenPool} from "../../../../pools/TokenPool.sol"; +import {HybridLockReleaseUSDCTokenPool} from "../../../../pools/USDC/HybridLockReleaseUSDCTokenPool.sol"; import {USDCBridgeMigrator} from "../../../../pools/USDC/USDCBridgeMigrator.sol"; +import {USDCTokenPool} from "../../../../pools/USDC/USDCTokenPool.sol"; +import {BaseTest} from "../../../BaseTest.t.sol"; +import {MockE2EUSDCTransmitter} from "../../../mocks/MockE2EUSDCTransmitter.sol"; +import {MockUSDCTokenMessenger} from "../../../mocks/MockUSDCTokenMessenger.sol"; import {HybridLockReleaseUSDCTokenPool_lockOrBurn} from "../HybridLockReleaseUSDCTokenPool/HybridLockReleaseUSDCTokenPool.lockOrBurn.t.sol"; +contract USDCTokenPoolSetup is BaseTest { + IBurnMintERC20 internal s_token; + MockUSDCTokenMessenger internal s_mockUSDC; + MockE2EUSDCTransmitter internal s_mockUSDCTransmitter; + uint32 internal constant USDC_DEST_TOKEN_GAS = 150_000; + + struct USDCMessage { + uint32 version; + uint32 sourceDomain; + uint32 destinationDomain; + uint64 nonce; + bytes32 sender; + bytes32 recipient; + bytes32 destinationCaller; + bytes messageBody; + } + + uint32 internal constant SOURCE_DOMAIN_IDENTIFIER = 0x02020202; + uint32 internal constant DEST_DOMAIN_IDENTIFIER = 0; + + bytes32 internal constant SOURCE_CHAIN_TOKEN_SENDER = bytes32(uint256(uint160(0x01111111221))); + address internal constant SOURCE_CHAIN_USDC_POOL = address(0x23789765456789); + address internal constant DEST_CHAIN_USDC_POOL = address(0x987384873458734); + address internal constant DEST_CHAIN_USDC_TOKEN = address(0x23598918358198766); + + address internal s_routerAllowedOnRamp = address(3456); + address internal s_routerAllowedOffRamp = address(234); + Router internal s_router; + + HybridLockReleaseUSDCTokenPool internal s_usdcTokenPool; + HybridLockReleaseUSDCTokenPool internal s_usdcTokenPoolTransferLiquidity; + address[] internal s_allowedList; + + function setUp() public virtual override { + BaseTest.setUp(); + BurnMintERC677 usdcToken = new BurnMintERC677("LINK", "LNK", 18, 0); + s_token = usdcToken; + deal(address(s_token), OWNER, type(uint256).max); + _setUpRamps(); + + s_mockUSDCTransmitter = new MockE2EUSDCTransmitter(0, DEST_DOMAIN_IDENTIFIER, address(s_token)); + s_mockUSDC = new MockUSDCTokenMessenger(0, address(s_mockUSDCTransmitter)); + + usdcToken.grantMintAndBurnRoles(address(s_mockUSDCTransmitter)); + + s_usdcTokenPool = + new HybridLockReleaseUSDCTokenPool(s_mockUSDC, s_token, new address[](0), address(s_mockRMN), address(s_router)); + + s_usdcTokenPoolTransferLiquidity = + new HybridLockReleaseUSDCTokenPool(s_mockUSDC, s_token, new address[](0), address(s_mockRMN), address(s_router)); + + usdcToken.grantMintAndBurnRoles(address(s_mockUSDC)); + usdcToken.grantMintAndBurnRoles(address(s_usdcTokenPool)); + + TokenPool.ChainUpdate[] memory chainUpdates = new TokenPool.ChainUpdate[](2); + chainUpdates[0] = TokenPool.ChainUpdate({ + remoteChainSelector: SOURCE_CHAIN_SELECTOR, + remotePoolAddress: abi.encode(SOURCE_CHAIN_USDC_POOL), + remoteTokenAddress: abi.encode(address(s_token)), + allowed: true, + outboundRateLimiterConfig: _getOutboundRateLimiterConfig(), + inboundRateLimiterConfig: _getInboundRateLimiterConfig() + }); + chainUpdates[1] = TokenPool.ChainUpdate({ + remoteChainSelector: DEST_CHAIN_SELECTOR, + remotePoolAddress: abi.encode(DEST_CHAIN_USDC_POOL), + remoteTokenAddress: abi.encode(DEST_CHAIN_USDC_TOKEN), + allowed: true, + outboundRateLimiterConfig: _getOutboundRateLimiterConfig(), + inboundRateLimiterConfig: _getInboundRateLimiterConfig() + }); + + s_usdcTokenPool.applyChainUpdates(chainUpdates); + + USDCTokenPool.DomainUpdate[] memory domains = new USDCTokenPool.DomainUpdate[](1); + domains[0] = USDCTokenPool.DomainUpdate({ + destChainSelector: DEST_CHAIN_SELECTOR, + domainIdentifier: 9999, + allowedCaller: keccak256("allowedCaller"), + enabled: true + }); + + s_usdcTokenPool.setDomains(domains); + + vm.expectEmit(); + emit HybridLockReleaseUSDCTokenPool.LiquidityProviderSet(address(0), OWNER, DEST_CHAIN_SELECTOR); + + s_usdcTokenPool.setLiquidityProvider(DEST_CHAIN_SELECTOR, OWNER); + s_usdcTokenPool.setLiquidityProvider(SOURCE_CHAIN_SELECTOR, OWNER); + } + + function _setUpRamps() internal { + s_router = new Router(address(s_token), address(s_mockRMN)); + + Router.OnRamp[] memory onRampUpdates = new Router.OnRamp[](1); + onRampUpdates[0] = Router.OnRamp({destChainSelector: DEST_CHAIN_SELECTOR, onRamp: s_routerAllowedOnRamp}); + Router.OffRamp[] memory offRampUpdates = new Router.OffRamp[](1); + address[] memory offRamps = new address[](1); + offRamps[0] = s_routerAllowedOffRamp; + offRampUpdates[0] = Router.OffRamp({sourceChainSelector: SOURCE_CHAIN_SELECTOR, offRamp: offRamps[0]}); + + s_router.applyRampUpdates(onRampUpdates, new Router.OffRamp[](0), offRampUpdates); + } + + function _generateUSDCMessage( + USDCMessage memory usdcMessage + ) internal pure returns (bytes memory) { + return abi.encodePacked( + usdcMessage.version, + usdcMessage.sourceDomain, + usdcMessage.destinationDomain, + usdcMessage.nonce, + usdcMessage.sender, + usdcMessage.recipient, + usdcMessage.destinationCaller, + usdcMessage.messageBody + ); + } +} + contract USDCBridgeMigrator_BurnLockedUSDC is HybridLockReleaseUSDCTokenPool_lockOrBurn { - function test_lockOrBurn_then_BurnInCCTPMigration() public { + function test_lockOrBurn_then_BurnInCCTPMigration_Success() public { bytes32 receiver = bytes32(uint256(uint160(STRANGER))); address CIRCLE = makeAddr("CIRCLE CCTP Migrator"); @@ -96,10 +226,10 @@ contract USDCBridgeMigrator_BurnLockedUSDC is HybridLockReleaseUSDCTokenPool_loc s_usdcTokenPool.shouldUseLockRelease(DEST_CHAIN_SELECTOR), "Lock/Release mech should be disabled after a burn" ); - test_PrimaryMechanism(); + test_PrimaryMechanism_Success(); } - function test_RevertWhen_invalidPermissions() public { + function test_invalidPermissions_Revert() public { address CIRCLE = makeAddr("CIRCLE"); vm.startPrank(OWNER); diff --git a/contracts/src/v0.8/ccip/test/pools/USDC/USDCBridgeMigrator/USDCBridgeMigrator.cancelMigrationProposal.t.sol b/contracts/src/v0.8/ccip/test/pools/USDC/USDCBridgeMigrator/USDCBridgeMigrator.cancelMigrationProposal.t.sol index 40df069d80e..513361f096c 100644 --- a/contracts/src/v0.8/ccip/test/pools/USDC/USDCBridgeMigrator/USDCBridgeMigrator.cancelMigrationProposal.t.sol +++ b/contracts/src/v0.8/ccip/test/pools/USDC/USDCBridgeMigrator/USDCBridgeMigrator.cancelMigrationProposal.t.sol @@ -1,11 +1,141 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; +import {IBurnMintERC20} from "../../../../../shared/token/ERC20/IBurnMintERC20.sol"; + +import {BurnMintERC677} from "../../../../../shared/token/ERC677/BurnMintERC677.sol"; +import {Router} from "../../../../Router.sol"; + +import {TokenPool} from "../../../../pools/TokenPool.sol"; +import {HybridLockReleaseUSDCTokenPool} from "../../../../pools/USDC/HybridLockReleaseUSDCTokenPool.sol"; import {USDCBridgeMigrator} from "../../../../pools/USDC/USDCBridgeMigrator.sol"; -import {HybridLockReleaseUSDCTokenPoolSetup} from "./USDCBridgeMigratorSetup.t.sol"; +import {USDCTokenPool} from "../../../../pools/USDC/USDCTokenPool.sol"; +import {BaseTest} from "../../../BaseTest.t.sol"; +import {MockE2EUSDCTransmitter} from "../../../mocks/MockE2EUSDCTransmitter.sol"; +import {MockUSDCTokenMessenger} from "../../../mocks/MockUSDCTokenMessenger.sol"; + +contract USDCTokenPoolSetup is BaseTest { + IBurnMintERC20 internal s_token; + MockUSDCTokenMessenger internal s_mockUSDC; + MockE2EUSDCTransmitter internal s_mockUSDCTransmitter; + uint32 internal constant USDC_DEST_TOKEN_GAS = 150_000; + + struct USDCMessage { + uint32 version; + uint32 sourceDomain; + uint32 destinationDomain; + uint64 nonce; + bytes32 sender; + bytes32 recipient; + bytes32 destinationCaller; + bytes messageBody; + } + + uint32 internal constant SOURCE_DOMAIN_IDENTIFIER = 0x02020202; + uint32 internal constant DEST_DOMAIN_IDENTIFIER = 0; + + bytes32 internal constant SOURCE_CHAIN_TOKEN_SENDER = bytes32(uint256(uint160(0x01111111221))); + address internal constant SOURCE_CHAIN_USDC_POOL = address(0x23789765456789); + address internal constant DEST_CHAIN_USDC_POOL = address(0x987384873458734); + address internal constant DEST_CHAIN_USDC_TOKEN = address(0x23598918358198766); + + address internal s_routerAllowedOnRamp = address(3456); + address internal s_routerAllowedOffRamp = address(234); + Router internal s_router; + + HybridLockReleaseUSDCTokenPool internal s_usdcTokenPool; + HybridLockReleaseUSDCTokenPool internal s_usdcTokenPoolTransferLiquidity; + address[] internal s_allowedList; + + function setUp() public virtual override { + BaseTest.setUp(); + BurnMintERC677 usdcToken = new BurnMintERC677("LINK", "LNK", 18, 0); + s_token = usdcToken; + deal(address(s_token), OWNER, type(uint256).max); + _setUpRamps(); + + s_mockUSDCTransmitter = new MockE2EUSDCTransmitter(0, DEST_DOMAIN_IDENTIFIER, address(s_token)); + s_mockUSDC = new MockUSDCTokenMessenger(0, address(s_mockUSDCTransmitter)); + + usdcToken.grantMintAndBurnRoles(address(s_mockUSDCTransmitter)); + + s_usdcTokenPool = + new HybridLockReleaseUSDCTokenPool(s_mockUSDC, s_token, new address[](0), address(s_mockRMN), address(s_router)); + + s_usdcTokenPoolTransferLiquidity = + new HybridLockReleaseUSDCTokenPool(s_mockUSDC, s_token, new address[](0), address(s_mockRMN), address(s_router)); + + usdcToken.grantMintAndBurnRoles(address(s_mockUSDC)); + usdcToken.grantMintAndBurnRoles(address(s_usdcTokenPool)); + + TokenPool.ChainUpdate[] memory chainUpdates = new TokenPool.ChainUpdate[](2); + chainUpdates[0] = TokenPool.ChainUpdate({ + remoteChainSelector: SOURCE_CHAIN_SELECTOR, + remotePoolAddress: abi.encode(SOURCE_CHAIN_USDC_POOL), + remoteTokenAddress: abi.encode(address(s_token)), + allowed: true, + outboundRateLimiterConfig: _getOutboundRateLimiterConfig(), + inboundRateLimiterConfig: _getInboundRateLimiterConfig() + }); + chainUpdates[1] = TokenPool.ChainUpdate({ + remoteChainSelector: DEST_CHAIN_SELECTOR, + remotePoolAddress: abi.encode(DEST_CHAIN_USDC_POOL), + remoteTokenAddress: abi.encode(DEST_CHAIN_USDC_TOKEN), + allowed: true, + outboundRateLimiterConfig: _getOutboundRateLimiterConfig(), + inboundRateLimiterConfig: _getInboundRateLimiterConfig() + }); + + s_usdcTokenPool.applyChainUpdates(chainUpdates); + + USDCTokenPool.DomainUpdate[] memory domains = new USDCTokenPool.DomainUpdate[](1); + domains[0] = USDCTokenPool.DomainUpdate({ + destChainSelector: DEST_CHAIN_SELECTOR, + domainIdentifier: 9999, + allowedCaller: keccak256("allowedCaller"), + enabled: true + }); + + s_usdcTokenPool.setDomains(domains); + + vm.expectEmit(); + emit HybridLockReleaseUSDCTokenPool.LiquidityProviderSet(address(0), OWNER, DEST_CHAIN_SELECTOR); + + s_usdcTokenPool.setLiquidityProvider(DEST_CHAIN_SELECTOR, OWNER); + s_usdcTokenPool.setLiquidityProvider(SOURCE_CHAIN_SELECTOR, OWNER); + } + + function _setUpRamps() internal { + s_router = new Router(address(s_token), address(s_mockRMN)); + + Router.OnRamp[] memory onRampUpdates = new Router.OnRamp[](1); + onRampUpdates[0] = Router.OnRamp({destChainSelector: DEST_CHAIN_SELECTOR, onRamp: s_routerAllowedOnRamp}); + Router.OffRamp[] memory offRampUpdates = new Router.OffRamp[](1); + address[] memory offRamps = new address[](1); + offRamps[0] = s_routerAllowedOffRamp; + offRampUpdates[0] = Router.OffRamp({sourceChainSelector: SOURCE_CHAIN_SELECTOR, offRamp: offRamps[0]}); + + s_router.applyRampUpdates(onRampUpdates, new Router.OffRamp[](0), offRampUpdates); + } + + function _generateUSDCMessage( + USDCMessage memory usdcMessage + ) internal pure returns (bytes memory) { + return abi.encodePacked( + usdcMessage.version, + usdcMessage.sourceDomain, + usdcMessage.destinationDomain, + usdcMessage.nonce, + usdcMessage.sender, + usdcMessage.recipient, + usdcMessage.destinationCaller, + usdcMessage.messageBody + ); + } +} -contract USDCBridgeMigrator_cancelMigrationProposal is HybridLockReleaseUSDCTokenPoolSetup { - function test_cancelExistingCCTPMigrationProposal() public { +contract USDCBridgeMigrator_cancelMigrationProposal is USDCTokenPoolSetup { + function test_cancelExistingCCTPMigrationProposal_Success() public { vm.startPrank(OWNER); // Mark the destination chain as supporting CCTP, so use L/R instead. @@ -40,7 +170,7 @@ contract USDCBridgeMigrator_cancelMigrationProposal is HybridLockReleaseUSDCToke s_usdcTokenPool.cancelExistingCCTPMigrationProposal(); } - function test_RevertWhen_cannotCancelANonExistentMigrationProposal() public { + function test_cannotCancelANonExistentMigrationProposal_Revert() public { vm.expectRevert(USDCBridgeMigrator.NoMigrationProposalPending.selector); // Proposal to migrate doesn't exist, and so the chain selector is zero, and therefore should revert diff --git a/contracts/src/v0.8/ccip/test/pools/USDC/USDCBridgeMigrator/USDCBridgeMigrator.excludeTokensFromBurn.t.sol b/contracts/src/v0.8/ccip/test/pools/USDC/USDCBridgeMigrator/USDCBridgeMigrator.excludeTokensFromBurn.t.sol index 441de21d0a2..11cffd0e03d 100644 --- a/contracts/src/v0.8/ccip/test/pools/USDC/USDCBridgeMigrator/USDCBridgeMigrator.excludeTokensFromBurn.t.sol +++ b/contracts/src/v0.8/ccip/test/pools/USDC/USDCBridgeMigrator/USDCBridgeMigrator.excludeTokensFromBurn.t.sol @@ -1,11 +1,141 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; +import {IBurnMintERC20} from "../../../../../shared/token/ERC20/IBurnMintERC20.sol"; + +import {BurnMintERC677} from "../../../../../shared/token/ERC677/BurnMintERC677.sol"; +import {Router} from "../../../../Router.sol"; + +import {TokenPool} from "../../../../pools/TokenPool.sol"; +import {HybridLockReleaseUSDCTokenPool} from "../../../../pools/USDC/HybridLockReleaseUSDCTokenPool.sol"; import {USDCBridgeMigrator} from "../../../../pools/USDC/USDCBridgeMigrator.sol"; -import {HybridLockReleaseUSDCTokenPoolSetup} from "./USDCBridgeMigratorSetup.t.sol"; +import {USDCTokenPool} from "../../../../pools/USDC/USDCTokenPool.sol"; +import {BaseTest} from "../../../BaseTest.t.sol"; +import {MockE2EUSDCTransmitter} from "../../../mocks/MockE2EUSDCTransmitter.sol"; +import {MockUSDCTokenMessenger} from "../../../mocks/MockUSDCTokenMessenger.sol"; + +contract USDCTokenPoolSetup is BaseTest { + IBurnMintERC20 internal s_token; + MockUSDCTokenMessenger internal s_mockUSDC; + MockE2EUSDCTransmitter internal s_mockUSDCTransmitter; + uint32 internal constant USDC_DEST_TOKEN_GAS = 150_000; + + struct USDCMessage { + uint32 version; + uint32 sourceDomain; + uint32 destinationDomain; + uint64 nonce; + bytes32 sender; + bytes32 recipient; + bytes32 destinationCaller; + bytes messageBody; + } + + uint32 internal constant SOURCE_DOMAIN_IDENTIFIER = 0x02020202; + uint32 internal constant DEST_DOMAIN_IDENTIFIER = 0; + + bytes32 internal constant SOURCE_CHAIN_TOKEN_SENDER = bytes32(uint256(uint160(0x01111111221))); + address internal constant SOURCE_CHAIN_USDC_POOL = address(0x23789765456789); + address internal constant DEST_CHAIN_USDC_POOL = address(0x987384873458734); + address internal constant DEST_CHAIN_USDC_TOKEN = address(0x23598918358198766); + + address internal s_routerAllowedOnRamp = address(3456); + address internal s_routerAllowedOffRamp = address(234); + Router internal s_router; + + HybridLockReleaseUSDCTokenPool internal s_usdcTokenPool; + HybridLockReleaseUSDCTokenPool internal s_usdcTokenPoolTransferLiquidity; + address[] internal s_allowedList; + + function setUp() public virtual override { + BaseTest.setUp(); + BurnMintERC677 usdcToken = new BurnMintERC677("LINK", "LNK", 18, 0); + s_token = usdcToken; + deal(address(s_token), OWNER, type(uint256).max); + _setUpRamps(); + + s_mockUSDCTransmitter = new MockE2EUSDCTransmitter(0, DEST_DOMAIN_IDENTIFIER, address(s_token)); + s_mockUSDC = new MockUSDCTokenMessenger(0, address(s_mockUSDCTransmitter)); + + usdcToken.grantMintAndBurnRoles(address(s_mockUSDCTransmitter)); + + s_usdcTokenPool = + new HybridLockReleaseUSDCTokenPool(s_mockUSDC, s_token, new address[](0), address(s_mockRMN), address(s_router)); + + s_usdcTokenPoolTransferLiquidity = + new HybridLockReleaseUSDCTokenPool(s_mockUSDC, s_token, new address[](0), address(s_mockRMN), address(s_router)); + + usdcToken.grantMintAndBurnRoles(address(s_mockUSDC)); + usdcToken.grantMintAndBurnRoles(address(s_usdcTokenPool)); + + TokenPool.ChainUpdate[] memory chainUpdates = new TokenPool.ChainUpdate[](2); + chainUpdates[0] = TokenPool.ChainUpdate({ + remoteChainSelector: SOURCE_CHAIN_SELECTOR, + remotePoolAddress: abi.encode(SOURCE_CHAIN_USDC_POOL), + remoteTokenAddress: abi.encode(address(s_token)), + allowed: true, + outboundRateLimiterConfig: _getOutboundRateLimiterConfig(), + inboundRateLimiterConfig: _getInboundRateLimiterConfig() + }); + chainUpdates[1] = TokenPool.ChainUpdate({ + remoteChainSelector: DEST_CHAIN_SELECTOR, + remotePoolAddress: abi.encode(DEST_CHAIN_USDC_POOL), + remoteTokenAddress: abi.encode(DEST_CHAIN_USDC_TOKEN), + allowed: true, + outboundRateLimiterConfig: _getOutboundRateLimiterConfig(), + inboundRateLimiterConfig: _getInboundRateLimiterConfig() + }); + + s_usdcTokenPool.applyChainUpdates(chainUpdates); + + USDCTokenPool.DomainUpdate[] memory domains = new USDCTokenPool.DomainUpdate[](1); + domains[0] = USDCTokenPool.DomainUpdate({ + destChainSelector: DEST_CHAIN_SELECTOR, + domainIdentifier: 9999, + allowedCaller: keccak256("allowedCaller"), + enabled: true + }); + + s_usdcTokenPool.setDomains(domains); + + vm.expectEmit(); + emit HybridLockReleaseUSDCTokenPool.LiquidityProviderSet(address(0), OWNER, DEST_CHAIN_SELECTOR); + + s_usdcTokenPool.setLiquidityProvider(DEST_CHAIN_SELECTOR, OWNER); + s_usdcTokenPool.setLiquidityProvider(SOURCE_CHAIN_SELECTOR, OWNER); + } + + function _setUpRamps() internal { + s_router = new Router(address(s_token), address(s_mockRMN)); + + Router.OnRamp[] memory onRampUpdates = new Router.OnRamp[](1); + onRampUpdates[0] = Router.OnRamp({destChainSelector: DEST_CHAIN_SELECTOR, onRamp: s_routerAllowedOnRamp}); + Router.OffRamp[] memory offRampUpdates = new Router.OffRamp[](1); + address[] memory offRamps = new address[](1); + offRamps[0] = s_routerAllowedOffRamp; + offRampUpdates[0] = Router.OffRamp({sourceChainSelector: SOURCE_CHAIN_SELECTOR, offRamp: offRamps[0]}); + + s_router.applyRampUpdates(onRampUpdates, new Router.OffRamp[](0), offRampUpdates); + } + + function _generateUSDCMessage( + USDCMessage memory usdcMessage + ) internal pure returns (bytes memory) { + return abi.encodePacked( + usdcMessage.version, + usdcMessage.sourceDomain, + usdcMessage.destinationDomain, + usdcMessage.nonce, + usdcMessage.sender, + usdcMessage.recipient, + usdcMessage.destinationCaller, + usdcMessage.messageBody + ); + } +} -contract USDCBridgeMigrator_excludeTokensFromBurn is HybridLockReleaseUSDCTokenPoolSetup { - function test_RevertWhen_excludeTokensWhenNoMigrationProposalPending() public { +contract USDCBridgeMigrator_excludeTokensFromBurn is USDCTokenPoolSetup { + function test_excludeTokensWhenNoMigrationProposalPending_Revert() public { vm.expectRevert(abi.encodeWithSelector(USDCBridgeMigrator.NoMigrationProposalPending.selector)); vm.startPrank(OWNER); diff --git a/contracts/src/v0.8/ccip/test/pools/USDC/USDCBridgeMigrator/USDCBridgeMigrator.proposeMigration.t.sol b/contracts/src/v0.8/ccip/test/pools/USDC/USDCBridgeMigrator/USDCBridgeMigrator.proposeMigration.t.sol index b7c2b46820f..d445cbac896 100644 --- a/contracts/src/v0.8/ccip/test/pools/USDC/USDCBridgeMigrator/USDCBridgeMigrator.proposeMigration.t.sol +++ b/contracts/src/v0.8/ccip/test/pools/USDC/USDCBridgeMigrator/USDCBridgeMigrator.proposeMigration.t.sol @@ -1,11 +1,141 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; +import {IBurnMintERC20} from "../../../../../shared/token/ERC20/IBurnMintERC20.sol"; + +import {BurnMintERC677} from "../../../../../shared/token/ERC677/BurnMintERC677.sol"; +import {Router} from "../../../../Router.sol"; + +import {TokenPool} from "../../../../pools/TokenPool.sol"; +import {HybridLockReleaseUSDCTokenPool} from "../../../../pools/USDC/HybridLockReleaseUSDCTokenPool.sol"; import {USDCBridgeMigrator} from "../../../../pools/USDC/USDCBridgeMigrator.sol"; -import {HybridLockReleaseUSDCTokenPoolSetup} from "./USDCBridgeMigratorSetup.t.sol"; +import {USDCTokenPool} from "../../../../pools/USDC/USDCTokenPool.sol"; +import {BaseTest} from "../../../BaseTest.t.sol"; +import {MockE2EUSDCTransmitter} from "../../../mocks/MockE2EUSDCTransmitter.sol"; +import {MockUSDCTokenMessenger} from "../../../mocks/MockUSDCTokenMessenger.sol"; + +contract USDCTokenPoolSetup is BaseTest { + IBurnMintERC20 internal s_token; + MockUSDCTokenMessenger internal s_mockUSDC; + MockE2EUSDCTransmitter internal s_mockUSDCTransmitter; + uint32 internal constant USDC_DEST_TOKEN_GAS = 150_000; + + struct USDCMessage { + uint32 version; + uint32 sourceDomain; + uint32 destinationDomain; + uint64 nonce; + bytes32 sender; + bytes32 recipient; + bytes32 destinationCaller; + bytes messageBody; + } + + uint32 internal constant SOURCE_DOMAIN_IDENTIFIER = 0x02020202; + uint32 internal constant DEST_DOMAIN_IDENTIFIER = 0; + + bytes32 internal constant SOURCE_CHAIN_TOKEN_SENDER = bytes32(uint256(uint160(0x01111111221))); + address internal constant SOURCE_CHAIN_USDC_POOL = address(0x23789765456789); + address internal constant DEST_CHAIN_USDC_POOL = address(0x987384873458734); + address internal constant DEST_CHAIN_USDC_TOKEN = address(0x23598918358198766); + + address internal s_routerAllowedOnRamp = address(3456); + address internal s_routerAllowedOffRamp = address(234); + Router internal s_router; + + HybridLockReleaseUSDCTokenPool internal s_usdcTokenPool; + HybridLockReleaseUSDCTokenPool internal s_usdcTokenPoolTransferLiquidity; + address[] internal s_allowedList; + + function setUp() public virtual override { + BaseTest.setUp(); + BurnMintERC677 usdcToken = new BurnMintERC677("LINK", "LNK", 18, 0); + s_token = usdcToken; + deal(address(s_token), OWNER, type(uint256).max); + _setUpRamps(); + + s_mockUSDCTransmitter = new MockE2EUSDCTransmitter(0, DEST_DOMAIN_IDENTIFIER, address(s_token)); + s_mockUSDC = new MockUSDCTokenMessenger(0, address(s_mockUSDCTransmitter)); + + usdcToken.grantMintAndBurnRoles(address(s_mockUSDCTransmitter)); + + s_usdcTokenPool = + new HybridLockReleaseUSDCTokenPool(s_mockUSDC, s_token, new address[](0), address(s_mockRMN), address(s_router)); + + s_usdcTokenPoolTransferLiquidity = + new HybridLockReleaseUSDCTokenPool(s_mockUSDC, s_token, new address[](0), address(s_mockRMN), address(s_router)); + + usdcToken.grantMintAndBurnRoles(address(s_mockUSDC)); + usdcToken.grantMintAndBurnRoles(address(s_usdcTokenPool)); + + TokenPool.ChainUpdate[] memory chainUpdates = new TokenPool.ChainUpdate[](2); + chainUpdates[0] = TokenPool.ChainUpdate({ + remoteChainSelector: SOURCE_CHAIN_SELECTOR, + remotePoolAddress: abi.encode(SOURCE_CHAIN_USDC_POOL), + remoteTokenAddress: abi.encode(address(s_token)), + allowed: true, + outboundRateLimiterConfig: _getOutboundRateLimiterConfig(), + inboundRateLimiterConfig: _getInboundRateLimiterConfig() + }); + chainUpdates[1] = TokenPool.ChainUpdate({ + remoteChainSelector: DEST_CHAIN_SELECTOR, + remotePoolAddress: abi.encode(DEST_CHAIN_USDC_POOL), + remoteTokenAddress: abi.encode(DEST_CHAIN_USDC_TOKEN), + allowed: true, + outboundRateLimiterConfig: _getOutboundRateLimiterConfig(), + inboundRateLimiterConfig: _getInboundRateLimiterConfig() + }); + + s_usdcTokenPool.applyChainUpdates(chainUpdates); + + USDCTokenPool.DomainUpdate[] memory domains = new USDCTokenPool.DomainUpdate[](1); + domains[0] = USDCTokenPool.DomainUpdate({ + destChainSelector: DEST_CHAIN_SELECTOR, + domainIdentifier: 9999, + allowedCaller: keccak256("allowedCaller"), + enabled: true + }); + + s_usdcTokenPool.setDomains(domains); + + vm.expectEmit(); + emit HybridLockReleaseUSDCTokenPool.LiquidityProviderSet(address(0), OWNER, DEST_CHAIN_SELECTOR); + + s_usdcTokenPool.setLiquidityProvider(DEST_CHAIN_SELECTOR, OWNER); + s_usdcTokenPool.setLiquidityProvider(SOURCE_CHAIN_SELECTOR, OWNER); + } + + function _setUpRamps() internal { + s_router = new Router(address(s_token), address(s_mockRMN)); + + Router.OnRamp[] memory onRampUpdates = new Router.OnRamp[](1); + onRampUpdates[0] = Router.OnRamp({destChainSelector: DEST_CHAIN_SELECTOR, onRamp: s_routerAllowedOnRamp}); + Router.OffRamp[] memory offRampUpdates = new Router.OffRamp[](1); + address[] memory offRamps = new address[](1); + offRamps[0] = s_routerAllowedOffRamp; + offRampUpdates[0] = Router.OffRamp({sourceChainSelector: SOURCE_CHAIN_SELECTOR, offRamp: offRamps[0]}); + + s_router.applyRampUpdates(onRampUpdates, new Router.OffRamp[](0), offRampUpdates); + } + + function _generateUSDCMessage( + USDCMessage memory usdcMessage + ) internal pure returns (bytes memory) { + return abi.encodePacked( + usdcMessage.version, + usdcMessage.sourceDomain, + usdcMessage.destinationDomain, + usdcMessage.nonce, + usdcMessage.sender, + usdcMessage.recipient, + usdcMessage.destinationCaller, + usdcMessage.messageBody + ); + } +} -contract USDCBridgeMigrator_proposeMigration is HybridLockReleaseUSDCTokenPoolSetup { - function test_RevertWhen_ChainNotUsingLockRelease() public { +contract USDCBridgeMigrator_proposeMigration is USDCTokenPoolSetup { + function test_ChainNotUsingLockRelease_Revert() public { vm.expectRevert(abi.encodeWithSelector(USDCBridgeMigrator.InvalidChainSelector.selector)); vm.startPrank(OWNER); diff --git a/contracts/src/v0.8/ccip/test/pools/USDC/USDCBridgeMigrator/USDCBridgeMigrator.provideLiquidity.t.sol b/contracts/src/v0.8/ccip/test/pools/USDC/USDCBridgeMigrator/USDCBridgeMigrator.provideLiquidity.t.sol index 5163f23f97f..a94cd4df348 100644 --- a/contracts/src/v0.8/ccip/test/pools/USDC/USDCBridgeMigrator/USDCBridgeMigrator.provideLiquidity.t.sol +++ b/contracts/src/v0.8/ccip/test/pools/USDC/USDCBridgeMigrator/USDCBridgeMigrator.provideLiquidity.t.sol @@ -1,12 +1,141 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; + +import {IBurnMintERC20} from "../../../../../shared/token/ERC20/IBurnMintERC20.sol"; + +import {BurnMintERC677} from "../../../../../shared/token/ERC677/BurnMintERC677.sol"; +import {Router} from "../../../../Router.sol"; import {TokenPool} from "../../../../pools/TokenPool.sol"; import {HybridLockReleaseUSDCTokenPool} from "../../../../pools/USDC/HybridLockReleaseUSDCTokenPool.sol"; +import {USDCTokenPool} from "../../../../pools/USDC/USDCTokenPool.sol"; +import {BaseTest} from "../../../BaseTest.t.sol"; +import {MockE2EUSDCTransmitter} from "../../../mocks/MockE2EUSDCTransmitter.sol"; +import {MockUSDCTokenMessenger} from "../../../mocks/MockUSDCTokenMessenger.sol"; import {USDCBridgeMigrator_BurnLockedUSDC} from "./USDCBridgeMigrator.burnLockedUSDC.t.sol"; +contract USDCTokenPoolSetup is BaseTest { + IBurnMintERC20 internal s_token; + MockUSDCTokenMessenger internal s_mockUSDC; + MockE2EUSDCTransmitter internal s_mockUSDCTransmitter; + uint32 internal constant USDC_DEST_TOKEN_GAS = 150_000; + + struct USDCMessage { + uint32 version; + uint32 sourceDomain; + uint32 destinationDomain; + uint64 nonce; + bytes32 sender; + bytes32 recipient; + bytes32 destinationCaller; + bytes messageBody; + } + + uint32 internal constant SOURCE_DOMAIN_IDENTIFIER = 0x02020202; + uint32 internal constant DEST_DOMAIN_IDENTIFIER = 0; + + bytes32 internal constant SOURCE_CHAIN_TOKEN_SENDER = bytes32(uint256(uint160(0x01111111221))); + address internal constant SOURCE_CHAIN_USDC_POOL = address(0x23789765456789); + address internal constant DEST_CHAIN_USDC_POOL = address(0x987384873458734); + address internal constant DEST_CHAIN_USDC_TOKEN = address(0x23598918358198766); + + address internal s_routerAllowedOnRamp = address(3456); + address internal s_routerAllowedOffRamp = address(234); + Router internal s_router; + + HybridLockReleaseUSDCTokenPool internal s_usdcTokenPool; + HybridLockReleaseUSDCTokenPool internal s_usdcTokenPoolTransferLiquidity; + address[] internal s_allowedList; + + function setUp() public virtual override { + BaseTest.setUp(); + BurnMintERC677 usdcToken = new BurnMintERC677("LINK", "LNK", 18, 0); + s_token = usdcToken; + deal(address(s_token), OWNER, type(uint256).max); + _setUpRamps(); + + s_mockUSDCTransmitter = new MockE2EUSDCTransmitter(0, DEST_DOMAIN_IDENTIFIER, address(s_token)); + s_mockUSDC = new MockUSDCTokenMessenger(0, address(s_mockUSDCTransmitter)); + + usdcToken.grantMintAndBurnRoles(address(s_mockUSDCTransmitter)); + + s_usdcTokenPool = + new HybridLockReleaseUSDCTokenPool(s_mockUSDC, s_token, new address[](0), address(s_mockRMN), address(s_router)); + + s_usdcTokenPoolTransferLiquidity = + new HybridLockReleaseUSDCTokenPool(s_mockUSDC, s_token, new address[](0), address(s_mockRMN), address(s_router)); + + usdcToken.grantMintAndBurnRoles(address(s_mockUSDC)); + usdcToken.grantMintAndBurnRoles(address(s_usdcTokenPool)); + + TokenPool.ChainUpdate[] memory chainUpdates = new TokenPool.ChainUpdate[](2); + chainUpdates[0] = TokenPool.ChainUpdate({ + remoteChainSelector: SOURCE_CHAIN_SELECTOR, + remotePoolAddress: abi.encode(SOURCE_CHAIN_USDC_POOL), + remoteTokenAddress: abi.encode(address(s_token)), + allowed: true, + outboundRateLimiterConfig: _getOutboundRateLimiterConfig(), + inboundRateLimiterConfig: _getInboundRateLimiterConfig() + }); + chainUpdates[1] = TokenPool.ChainUpdate({ + remoteChainSelector: DEST_CHAIN_SELECTOR, + remotePoolAddress: abi.encode(DEST_CHAIN_USDC_POOL), + remoteTokenAddress: abi.encode(DEST_CHAIN_USDC_TOKEN), + allowed: true, + outboundRateLimiterConfig: _getOutboundRateLimiterConfig(), + inboundRateLimiterConfig: _getInboundRateLimiterConfig() + }); + + s_usdcTokenPool.applyChainUpdates(chainUpdates); + + USDCTokenPool.DomainUpdate[] memory domains = new USDCTokenPool.DomainUpdate[](1); + domains[0] = USDCTokenPool.DomainUpdate({ + destChainSelector: DEST_CHAIN_SELECTOR, + domainIdentifier: 9999, + allowedCaller: keccak256("allowedCaller"), + enabled: true + }); + + s_usdcTokenPool.setDomains(domains); + + vm.expectEmit(); + emit HybridLockReleaseUSDCTokenPool.LiquidityProviderSet(address(0), OWNER, DEST_CHAIN_SELECTOR); + + s_usdcTokenPool.setLiquidityProvider(DEST_CHAIN_SELECTOR, OWNER); + s_usdcTokenPool.setLiquidityProvider(SOURCE_CHAIN_SELECTOR, OWNER); + } + + function _setUpRamps() internal { + s_router = new Router(address(s_token), address(s_mockRMN)); + + Router.OnRamp[] memory onRampUpdates = new Router.OnRamp[](1); + onRampUpdates[0] = Router.OnRamp({destChainSelector: DEST_CHAIN_SELECTOR, onRamp: s_routerAllowedOnRamp}); + Router.OffRamp[] memory offRampUpdates = new Router.OffRamp[](1); + address[] memory offRamps = new address[](1); + offRamps[0] = s_routerAllowedOffRamp; + offRampUpdates[0] = Router.OffRamp({sourceChainSelector: SOURCE_CHAIN_SELECTOR, offRamp: offRamps[0]}); + + s_router.applyRampUpdates(onRampUpdates, new Router.OffRamp[](0), offRampUpdates); + } + + function _generateUSDCMessage( + USDCMessage memory usdcMessage + ) internal pure returns (bytes memory) { + return abi.encodePacked( + usdcMessage.version, + usdcMessage.sourceDomain, + usdcMessage.destinationDomain, + usdcMessage.nonce, + usdcMessage.sender, + usdcMessage.recipient, + usdcMessage.destinationCaller, + usdcMessage.messageBody + ); + } +} + contract USDCBridgeMigrator_provideLiquidity is USDCBridgeMigrator_BurnLockedUSDC { - function test_RevertWhen_cannotModifyLiquidityWithoutPermissions() public { + function test_cannotModifyLiquidityWithoutPermissions_Revert() public { address randomAddr = makeAddr("RANDOM"); vm.startPrank(randomAddr); @@ -17,8 +146,8 @@ contract USDCBridgeMigrator_provideLiquidity is USDCBridgeMigrator_BurnLockedUSD s_usdcTokenPool.provideLiquidity(DEST_CHAIN_SELECTOR, 1e6); } - function test_RevertWhen_cannotProvideLiquidity_AfterMigration() public { - test_lockOrBurn_then_BurnInCCTPMigration(); + function test_cannotProvideLiquidity_AfterMigration_Revert() public { + test_lockOrBurn_then_BurnInCCTPMigration_Success(); vm.startPrank(OWNER); @@ -31,7 +160,7 @@ contract USDCBridgeMigrator_provideLiquidity is USDCBridgeMigrator_BurnLockedUSD s_usdcTokenPool.provideLiquidity(DEST_CHAIN_SELECTOR, 1e6); } - function test_RevertWhen_cannotProvideLiquidityWhenMigrationProposalPending() public { + function test_cannotProvideLiquidityWhenMigrationProposalPending_Revert() public { vm.startPrank(OWNER); // Mark the destination chain as supporting CCTP, so use L/R instead. diff --git a/contracts/src/v0.8/ccip/test/pools/USDC/USDCBridgeMigrator/USDCBridgeMigrator.releaseOrMint.t.sol b/contracts/src/v0.8/ccip/test/pools/USDC/USDCBridgeMigrator/USDCBridgeMigrator.releaseOrMint.t.sol index 46861d614b6..9976adf64ea 100644 --- a/contracts/src/v0.8/ccip/test/pools/USDC/USDCBridgeMigrator/USDCBridgeMigrator.releaseOrMint.t.sol +++ b/contracts/src/v0.8/ccip/test/pools/USDC/USDCBridgeMigrator/USDCBridgeMigrator.releaseOrMint.t.sol @@ -1,17 +1,146 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; +import {IBurnMintERC20} from "../../../../../shared/token/ERC20/IBurnMintERC20.sol"; + +import {BurnMintERC677} from "../../../../../shared/token/ERC677/BurnMintERC677.sol"; +import {Router} from "../../../../Router.sol"; import {Internal} from "../../../../libraries/Internal.sol"; import {Pool} from "../../../../libraries/Pool.sol"; + import {TokenPool} from "../../../../pools/TokenPool.sol"; +import {HybridLockReleaseUSDCTokenPool} from "../../../../pools/USDC/HybridLockReleaseUSDCTokenPool.sol"; import {LOCK_RELEASE_FLAG} from "../../../../pools/USDC/HybridLockReleaseUSDCTokenPool.sol"; import {USDCBridgeMigrator} from "../../../../pools/USDC/USDCBridgeMigrator.sol"; import {USDCTokenPool} from "../../../../pools/USDC/USDCTokenPool.sol"; +import {BaseTest} from "../../../BaseTest.t.sol"; +import {MockE2EUSDCTransmitter} from "../../../mocks/MockE2EUSDCTransmitter.sol"; +import {MockUSDCTokenMessenger} from "../../../mocks/MockUSDCTokenMessenger.sol"; import {HybridLockReleaseUSDCTokenPool_releaseOrMint} from "../HybridLockReleaseUSDCTokenPool/HybridLockReleaseUSDCTokenPool.releaseOrMint.t.sol"; +contract USDCTokenPoolSetup is BaseTest { + IBurnMintERC20 internal s_token; + MockUSDCTokenMessenger internal s_mockUSDC; + MockE2EUSDCTransmitter internal s_mockUSDCTransmitter; + uint32 internal constant USDC_DEST_TOKEN_GAS = 150_000; + + struct USDCMessage { + uint32 version; + uint32 sourceDomain; + uint32 destinationDomain; + uint64 nonce; + bytes32 sender; + bytes32 recipient; + bytes32 destinationCaller; + bytes messageBody; + } + + uint32 internal constant SOURCE_DOMAIN_IDENTIFIER = 0x02020202; + uint32 internal constant DEST_DOMAIN_IDENTIFIER = 0; + + bytes32 internal constant SOURCE_CHAIN_TOKEN_SENDER = bytes32(uint256(uint160(0x01111111221))); + address internal constant SOURCE_CHAIN_USDC_POOL = address(0x23789765456789); + address internal constant DEST_CHAIN_USDC_POOL = address(0x987384873458734); + address internal constant DEST_CHAIN_USDC_TOKEN = address(0x23598918358198766); + + address internal s_routerAllowedOnRamp = address(3456); + address internal s_routerAllowedOffRamp = address(234); + Router internal s_router; + + HybridLockReleaseUSDCTokenPool internal s_usdcTokenPool; + HybridLockReleaseUSDCTokenPool internal s_usdcTokenPoolTransferLiquidity; + address[] internal s_allowedList; + + function setUp() public virtual override { + BaseTest.setUp(); + BurnMintERC677 usdcToken = new BurnMintERC677("LINK", "LNK", 18, 0); + s_token = usdcToken; + deal(address(s_token), OWNER, type(uint256).max); + _setUpRamps(); + + s_mockUSDCTransmitter = new MockE2EUSDCTransmitter(0, DEST_DOMAIN_IDENTIFIER, address(s_token)); + s_mockUSDC = new MockUSDCTokenMessenger(0, address(s_mockUSDCTransmitter)); + + usdcToken.grantMintAndBurnRoles(address(s_mockUSDCTransmitter)); + + s_usdcTokenPool = + new HybridLockReleaseUSDCTokenPool(s_mockUSDC, s_token, new address[](0), address(s_mockRMN), address(s_router)); + + s_usdcTokenPoolTransferLiquidity = + new HybridLockReleaseUSDCTokenPool(s_mockUSDC, s_token, new address[](0), address(s_mockRMN), address(s_router)); + + usdcToken.grantMintAndBurnRoles(address(s_mockUSDC)); + usdcToken.grantMintAndBurnRoles(address(s_usdcTokenPool)); + + TokenPool.ChainUpdate[] memory chainUpdates = new TokenPool.ChainUpdate[](2); + chainUpdates[0] = TokenPool.ChainUpdate({ + remoteChainSelector: SOURCE_CHAIN_SELECTOR, + remotePoolAddress: abi.encode(SOURCE_CHAIN_USDC_POOL), + remoteTokenAddress: abi.encode(address(s_token)), + allowed: true, + outboundRateLimiterConfig: _getOutboundRateLimiterConfig(), + inboundRateLimiterConfig: _getInboundRateLimiterConfig() + }); + chainUpdates[1] = TokenPool.ChainUpdate({ + remoteChainSelector: DEST_CHAIN_SELECTOR, + remotePoolAddress: abi.encode(DEST_CHAIN_USDC_POOL), + remoteTokenAddress: abi.encode(DEST_CHAIN_USDC_TOKEN), + allowed: true, + outboundRateLimiterConfig: _getOutboundRateLimiterConfig(), + inboundRateLimiterConfig: _getInboundRateLimiterConfig() + }); + + s_usdcTokenPool.applyChainUpdates(chainUpdates); + + USDCTokenPool.DomainUpdate[] memory domains = new USDCTokenPool.DomainUpdate[](1); + domains[0] = USDCTokenPool.DomainUpdate({ + destChainSelector: DEST_CHAIN_SELECTOR, + domainIdentifier: 9999, + allowedCaller: keccak256("allowedCaller"), + enabled: true + }); + + s_usdcTokenPool.setDomains(domains); + + vm.expectEmit(); + emit HybridLockReleaseUSDCTokenPool.LiquidityProviderSet(address(0), OWNER, DEST_CHAIN_SELECTOR); + + s_usdcTokenPool.setLiquidityProvider(DEST_CHAIN_SELECTOR, OWNER); + s_usdcTokenPool.setLiquidityProvider(SOURCE_CHAIN_SELECTOR, OWNER); + } + + function _setUpRamps() internal { + s_router = new Router(address(s_token), address(s_mockRMN)); + + Router.OnRamp[] memory onRampUpdates = new Router.OnRamp[](1); + onRampUpdates[0] = Router.OnRamp({destChainSelector: DEST_CHAIN_SELECTOR, onRamp: s_routerAllowedOnRamp}); + Router.OffRamp[] memory offRampUpdates = new Router.OffRamp[](1); + address[] memory offRamps = new address[](1); + offRamps[0] = s_routerAllowedOffRamp; + offRampUpdates[0] = Router.OffRamp({sourceChainSelector: SOURCE_CHAIN_SELECTOR, offRamp: offRamps[0]}); + + s_router.applyRampUpdates(onRampUpdates, new Router.OffRamp[](0), offRampUpdates); + } + + function _generateUSDCMessage( + USDCMessage memory usdcMessage + ) internal pure returns (bytes memory) { + return abi.encodePacked( + usdcMessage.version, + usdcMessage.sourceDomain, + usdcMessage.destinationDomain, + usdcMessage.nonce, + usdcMessage.sender, + usdcMessage.recipient, + usdcMessage.destinationCaller, + usdcMessage.messageBody + ); + } +} + contract USDCBridgeMigrator_releaseOrMint is HybridLockReleaseUSDCTokenPool_releaseOrMint { - function test_unstickManualTxAfterMigration_destChain() public { + function test_unstickManualTxAfterMigration_destChain_Success() public { address recipient = address(1234); // Test the edge case where a tx is stuck in the manual tx queue and the destination chain is the one that // should process is after a migration. I.E the message will have the Lock-Release flag set in the OffChainData, @@ -83,7 +212,7 @@ contract USDCBridgeMigrator_releaseOrMint is HybridLockReleaseUSDCTokenPool_rele ); } - function test_unstickManualTxAfterMigration_homeChain() public { + function test_unstickManualTxAfterMigration_homeChain_Success() public { address CIRCLE = makeAddr("CIRCLE"); address recipient = address(1234); diff --git a/contracts/src/v0.8/ccip/test/pools/USDC/USDCBridgeMigrator/USDCBridgeMigrator.updateChainSelectorMechanism.t.sol b/contracts/src/v0.8/ccip/test/pools/USDC/USDCBridgeMigrator/USDCBridgeMigrator.updateChainSelectorMechanism.t.sol index 160c09f7431..da3e15bc8ad 100644 --- a/contracts/src/v0.8/ccip/test/pools/USDC/USDCBridgeMigrator/USDCBridgeMigrator.updateChainSelectorMechanism.t.sol +++ b/contracts/src/v0.8/ccip/test/pools/USDC/USDCBridgeMigrator/USDCBridgeMigrator.updateChainSelectorMechanism.t.sol @@ -1,13 +1,142 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; -import {HybridLockReleaseUSDCTokenPool} from "../../../../pools/USDC/HybridLockReleaseUSDCTokenPool.sol"; +import {IBurnMintERC20} from "../../../../../shared/token/ERC20/IBurnMintERC20.sol"; + +import {BurnMintERC677} from "../../../../../shared/token/ERC677/BurnMintERC677.sol"; +import {Router} from "../../../../Router.sol"; +import {TokenPool} from "../../../../pools/TokenPool.sol"; +import {HybridLockReleaseUSDCTokenPool} from "../../../../pools/USDC/HybridLockReleaseUSDCTokenPool.sol"; +import {USDCTokenPool} from "../../../../pools/USDC/USDCTokenPool.sol"; +import {BaseTest} from "../../../BaseTest.t.sol"; +import {MockE2EUSDCTransmitter} from "../../../mocks/MockE2EUSDCTransmitter.sol"; +import {MockUSDCTokenMessenger} from "../../../mocks/MockUSDCTokenMessenger.sol"; import {USDCBridgeMigrator_BurnLockedUSDC} from "./USDCBridgeMigrator.burnLockedUSDC.t.sol"; +contract USDCTokenPoolSetup is BaseTest { + IBurnMintERC20 internal s_token; + MockUSDCTokenMessenger internal s_mockUSDC; + MockE2EUSDCTransmitter internal s_mockUSDCTransmitter; + uint32 internal constant USDC_DEST_TOKEN_GAS = 150_000; + + struct USDCMessage { + uint32 version; + uint32 sourceDomain; + uint32 destinationDomain; + uint64 nonce; + bytes32 sender; + bytes32 recipient; + bytes32 destinationCaller; + bytes messageBody; + } + + uint32 internal constant SOURCE_DOMAIN_IDENTIFIER = 0x02020202; + uint32 internal constant DEST_DOMAIN_IDENTIFIER = 0; + + bytes32 internal constant SOURCE_CHAIN_TOKEN_SENDER = bytes32(uint256(uint160(0x01111111221))); + address internal constant SOURCE_CHAIN_USDC_POOL = address(0x23789765456789); + address internal constant DEST_CHAIN_USDC_POOL = address(0x987384873458734); + address internal constant DEST_CHAIN_USDC_TOKEN = address(0x23598918358198766); + + address internal s_routerAllowedOnRamp = address(3456); + address internal s_routerAllowedOffRamp = address(234); + Router internal s_router; + + HybridLockReleaseUSDCTokenPool internal s_usdcTokenPool; + HybridLockReleaseUSDCTokenPool internal s_usdcTokenPoolTransferLiquidity; + address[] internal s_allowedList; + + function setUp() public virtual override { + BaseTest.setUp(); + BurnMintERC677 usdcToken = new BurnMintERC677("LINK", "LNK", 18, 0); + s_token = usdcToken; + deal(address(s_token), OWNER, type(uint256).max); + _setUpRamps(); + + s_mockUSDCTransmitter = new MockE2EUSDCTransmitter(0, DEST_DOMAIN_IDENTIFIER, address(s_token)); + s_mockUSDC = new MockUSDCTokenMessenger(0, address(s_mockUSDCTransmitter)); + + usdcToken.grantMintAndBurnRoles(address(s_mockUSDCTransmitter)); + + s_usdcTokenPool = + new HybridLockReleaseUSDCTokenPool(s_mockUSDC, s_token, new address[](0), address(s_mockRMN), address(s_router)); + + s_usdcTokenPoolTransferLiquidity = + new HybridLockReleaseUSDCTokenPool(s_mockUSDC, s_token, new address[](0), address(s_mockRMN), address(s_router)); + + usdcToken.grantMintAndBurnRoles(address(s_mockUSDC)); + usdcToken.grantMintAndBurnRoles(address(s_usdcTokenPool)); + + TokenPool.ChainUpdate[] memory chainUpdates = new TokenPool.ChainUpdate[](2); + chainUpdates[0] = TokenPool.ChainUpdate({ + remoteChainSelector: SOURCE_CHAIN_SELECTOR, + remotePoolAddress: abi.encode(SOURCE_CHAIN_USDC_POOL), + remoteTokenAddress: abi.encode(address(s_token)), + allowed: true, + outboundRateLimiterConfig: _getOutboundRateLimiterConfig(), + inboundRateLimiterConfig: _getInboundRateLimiterConfig() + }); + chainUpdates[1] = TokenPool.ChainUpdate({ + remoteChainSelector: DEST_CHAIN_SELECTOR, + remotePoolAddress: abi.encode(DEST_CHAIN_USDC_POOL), + remoteTokenAddress: abi.encode(DEST_CHAIN_USDC_TOKEN), + allowed: true, + outboundRateLimiterConfig: _getOutboundRateLimiterConfig(), + inboundRateLimiterConfig: _getInboundRateLimiterConfig() + }); + + s_usdcTokenPool.applyChainUpdates(chainUpdates); + + USDCTokenPool.DomainUpdate[] memory domains = new USDCTokenPool.DomainUpdate[](1); + domains[0] = USDCTokenPool.DomainUpdate({ + destChainSelector: DEST_CHAIN_SELECTOR, + domainIdentifier: 9999, + allowedCaller: keccak256("allowedCaller"), + enabled: true + }); + + s_usdcTokenPool.setDomains(domains); + + vm.expectEmit(); + emit HybridLockReleaseUSDCTokenPool.LiquidityProviderSet(address(0), OWNER, DEST_CHAIN_SELECTOR); + + s_usdcTokenPool.setLiquidityProvider(DEST_CHAIN_SELECTOR, OWNER); + s_usdcTokenPool.setLiquidityProvider(SOURCE_CHAIN_SELECTOR, OWNER); + } + + function _setUpRamps() internal { + s_router = new Router(address(s_token), address(s_mockRMN)); + + Router.OnRamp[] memory onRampUpdates = new Router.OnRamp[](1); + onRampUpdates[0] = Router.OnRamp({destChainSelector: DEST_CHAIN_SELECTOR, onRamp: s_routerAllowedOnRamp}); + Router.OffRamp[] memory offRampUpdates = new Router.OffRamp[](1); + address[] memory offRamps = new address[](1); + offRamps[0] = s_routerAllowedOffRamp; + offRampUpdates[0] = Router.OffRamp({sourceChainSelector: SOURCE_CHAIN_SELECTOR, offRamp: offRamps[0]}); + + s_router.applyRampUpdates(onRampUpdates, new Router.OffRamp[](0), offRampUpdates); + } + + function _generateUSDCMessage( + USDCMessage memory usdcMessage + ) internal pure returns (bytes memory) { + return abi.encodePacked( + usdcMessage.version, + usdcMessage.sourceDomain, + usdcMessage.destinationDomain, + usdcMessage.nonce, + usdcMessage.sender, + usdcMessage.recipient, + usdcMessage.destinationCaller, + usdcMessage.messageBody + ); + } +} + contract USDCBridgeMigrator_updateChainSelectorMechanism is USDCBridgeMigrator_BurnLockedUSDC { - function test_RevertWhen_cannotRevertChainMechanism_afterMigration() public { - test_lockOrBurn_then_BurnInCCTPMigration(); + function test_cannotRevertChainMechanism_afterMigration_Revert() public { + test_lockOrBurn_then_BurnInCCTPMigration_Success(); vm.startPrank(OWNER); diff --git a/contracts/src/v0.8/ccip/test/pools/USDC/USDCBridgeMigrator/USDCBridgeMigratorSetup.t.sol b/contracts/src/v0.8/ccip/test/pools/USDC/USDCBridgeMigrator/USDCBridgeMigratorSetup.t.sol deleted file mode 100644 index bf9af4c66ad..00000000000 --- a/contracts/src/v0.8/ccip/test/pools/USDC/USDCBridgeMigrator/USDCBridgeMigratorSetup.t.sol +++ /dev/null @@ -1,22 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; - -import {HybridLockReleaseUSDCTokenPool} from "../../../../pools/USDC/HybridLockReleaseUSDCTokenPool.sol"; -import {USDCSetup} from "../USDCSetup.t.sol"; - -contract HybridLockReleaseUSDCTokenPoolSetup is USDCSetup { - HybridLockReleaseUSDCTokenPool internal s_usdcTokenPool; - HybridLockReleaseUSDCTokenPool internal s_usdcTokenPoolTransferLiquidity; - - function setUp() public virtual override { - super.setUp(); - - s_usdcTokenPool = new HybridLockReleaseUSDCTokenPool( - s_mockUSDC, s_token, new address[](0), address(s_mockRMNRemote), address(s_router) - ); - - s_usdcTokenPoolTransferLiquidity = new HybridLockReleaseUSDCTokenPool( - s_mockUSDC, s_token, new address[](0), address(s_mockRMNRemote), address(s_router) - ); - } -} diff --git a/contracts/src/v0.8/ccip/test/pools/USDC/USDCSetup.t.sol b/contracts/src/v0.8/ccip/test/pools/USDC/USDCSetup.t.sol deleted file mode 100644 index e000999cb30..00000000000 --- a/contracts/src/v0.8/ccip/test/pools/USDC/USDCSetup.t.sol +++ /dev/null @@ -1,114 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; - -import {IBurnMintERC20} from "../../../../shared/token/ERC20/IBurnMintERC20.sol"; - -import {BurnMintERC677} from "../../../../shared/token/ERC677/BurnMintERC677.sol"; -import {Router} from "../../../Router.sol"; -import {TokenPool} from "../../../pools/TokenPool.sol"; - -import {BaseTest} from "../../BaseTest.t.sol"; -import {MockE2EUSDCTransmitter} from "../../mocks/MockE2EUSDCTransmitter.sol"; -import {MockUSDCTokenMessenger} from "../../mocks/MockUSDCTokenMessenger.sol"; - -contract USDCSetup is BaseTest { - struct USDCMessage { - uint32 version; - uint32 sourceDomain; - uint32 destinationDomain; - uint64 nonce; - bytes32 sender; - bytes32 recipient; - bytes32 destinationCaller; - bytes messageBody; - } - - uint32 internal constant USDC_DEST_TOKEN_GAS = 180_000; - uint32 internal constant SOURCE_DOMAIN_IDENTIFIER = 0x02020202; - uint32 internal constant DEST_DOMAIN_IDENTIFIER = 0; - - bytes32 internal constant SOURCE_CHAIN_TOKEN_SENDER = bytes32(uint256(uint160(0x01111111221))); - address internal constant SOURCE_CHAIN_USDC_POOL = address(0x23789765456789); - address internal constant DEST_CHAIN_USDC_POOL = address(0x987384873458734); - address internal constant DEST_CHAIN_USDC_TOKEN = address(0x23598918358198766); - - MockUSDCTokenMessenger internal s_mockUSDC; - MockE2EUSDCTransmitter internal s_mockUSDCTransmitter; - - address internal s_routerAllowedOnRamp = address(3456); - address internal s_routerAllowedOffRamp = address(234); - Router internal s_router; - - IBurnMintERC20 internal s_token; - - function setUp() public virtual override { - super.setUp(); - BurnMintERC677 usdcToken = new BurnMintERC677("USD Coin", "USDC", 6, 0); - s_token = usdcToken; - - deal(address(s_token), OWNER, type(uint256).max); - _setUpRamps(); - - s_mockUSDCTransmitter = new MockE2EUSDCTransmitter(0, DEST_DOMAIN_IDENTIFIER, address(s_token)); - s_mockUSDC = new MockUSDCTokenMessenger(0, address(s_mockUSDCTransmitter)); - - usdcToken.grantMintAndBurnRoles(address(s_mockUSDCTransmitter)); - usdcToken.grantMintAndBurnRoles(address(s_mockUSDC)); - } - - function _poolApplyChainUpdates( - address pool - ) internal { - bytes[] memory sourcePoolAddresses = new bytes[](1); - sourcePoolAddresses[0] = abi.encode(SOURCE_CHAIN_USDC_POOL); - - bytes[] memory destPoolAddresses = new bytes[](1); - destPoolAddresses[0] = abi.encode(DEST_CHAIN_USDC_POOL); - - TokenPool.ChainUpdate[] memory chainUpdates = new TokenPool.ChainUpdate[](2); - chainUpdates[0] = TokenPool.ChainUpdate({ - remoteChainSelector: SOURCE_CHAIN_SELECTOR, - remotePoolAddresses: sourcePoolAddresses, - remoteTokenAddress: abi.encode(address(s_token)), - outboundRateLimiterConfig: _getOutboundRateLimiterConfig(), - inboundRateLimiterConfig: _getInboundRateLimiterConfig() - }); - chainUpdates[1] = TokenPool.ChainUpdate({ - remoteChainSelector: DEST_CHAIN_SELECTOR, - remotePoolAddresses: destPoolAddresses, - remoteTokenAddress: abi.encode(DEST_CHAIN_USDC_TOKEN), - outboundRateLimiterConfig: _getOutboundRateLimiterConfig(), - inboundRateLimiterConfig: _getInboundRateLimiterConfig() - }); - - TokenPool(pool).applyChainUpdates(new uint64[](0), chainUpdates); - } - - function _setUpRamps() internal { - s_router = new Router(address(s_token), address(s_mockRMNRemote)); - - Router.OnRamp[] memory onRampUpdates = new Router.OnRamp[](1); - onRampUpdates[0] = Router.OnRamp({destChainSelector: DEST_CHAIN_SELECTOR, onRamp: s_routerAllowedOnRamp}); - Router.OffRamp[] memory offRampUpdates = new Router.OffRamp[](1); - address[] memory offRamps = new address[](1); - offRamps[0] = s_routerAllowedOffRamp; - offRampUpdates[0] = Router.OffRamp({sourceChainSelector: SOURCE_CHAIN_SELECTOR, offRamp: offRamps[0]}); - - s_router.applyRampUpdates(onRampUpdates, new Router.OffRamp[](0), offRampUpdates); - } - - function _generateUSDCMessage( - USDCMessage memory usdcMessage - ) internal pure returns (bytes memory) { - return abi.encodePacked( - usdcMessage.version, - usdcMessage.sourceDomain, - usdcMessage.destinationDomain, - usdcMessage.nonce, - usdcMessage.sender, - usdcMessage.recipient, - usdcMessage.destinationCaller, - usdcMessage.messageBody - ); - } -} diff --git a/contracts/src/v0.8/ccip/test/pools/USDC/USDCTokenPool/USDCTokenPool.lockOrBurn.t.sol b/contracts/src/v0.8/ccip/test/pools/USDC/USDCTokenPool/USDCTokenPool.lockOrBurn.t.sol index 484c795b375..9be60c97218 100644 --- a/contracts/src/v0.8/ccip/test/pools/USDC/USDCTokenPool/USDCTokenPool.lockOrBurn.t.sol +++ b/contracts/src/v0.8/ccip/test/pools/USDC/USDCTokenPool/USDCTokenPool.lockOrBurn.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import {ITokenMessenger} from "../../../../pools/USDC/ITokenMessenger.sol"; @@ -12,7 +12,7 @@ import {USDCTokenPoolSetup} from "./USDCTokenPoolSetup.t.sol"; contract USDCTokenPool_lockOrBurn is USDCTokenPoolSetup { // Base test case, included for PR gas comparisons as fuzz tests are excluded from forge snapshot due to being flaky. - function test_LockOrBurn() public { + function test_LockOrBurn_Success() public { bytes32 receiver = bytes32(uint256(uint160(STRANGER))); uint256 amount = 1; s_token.transfer(address(s_usdcTokenPool), amount); @@ -132,7 +132,7 @@ contract USDCTokenPool_lockOrBurn is USDCTokenPoolSetup { } // Reverts - function test_RevertWhen_UnknownDomain() public { + function test_UnknownDomain_Revert() public { uint64 wrongDomain = DEST_CHAIN_SELECTOR + 1; // We need to setup the wrong chainSelector so it reaches the domain check Router.OnRamp[] memory onRampUpdates = new Router.OnRamp[](1); @@ -142,13 +142,14 @@ contract USDCTokenPool_lockOrBurn is USDCTokenPoolSetup { TokenPool.ChainUpdate[] memory chainUpdates = new TokenPool.ChainUpdate[](1); chainUpdates[0] = TokenPool.ChainUpdate({ remoteChainSelector: wrongDomain, - remotePoolAddresses: new bytes[](0), + remotePoolAddress: abi.encode(address(1)), remoteTokenAddress: abi.encode(address(2)), + allowed: true, outboundRateLimiterConfig: _getOutboundRateLimiterConfig(), inboundRateLimiterConfig: _getInboundRateLimiterConfig() }); - s_usdcTokenPool.applyChainUpdates(new uint64[](0), chainUpdates); + s_usdcTokenPool.applyChainUpdates(chainUpdates); uint256 amount = 1000; vm.startPrank(s_routerAllowedOnRamp); @@ -168,7 +169,7 @@ contract USDCTokenPool_lockOrBurn is USDCTokenPoolSetup { ); } - function test_RevertWhen_CallerIsNotARampOnRouter() public { + function test_CallerIsNotARampOnRouter_Revert() public { vm.expectRevert(abi.encodeWithSelector(TokenPool.CallerIsNotARampOnRouter.selector, OWNER)); s_usdcTokenPool.lockOrBurn( @@ -182,7 +183,7 @@ contract USDCTokenPool_lockOrBurn is USDCTokenPoolSetup { ); } - function test_RevertWhen_LockOrBurnWithAllowList() public { + function test_LockOrBurnWithAllowList_Revert() public { vm.startPrank(s_routerAllowedOnRamp); vm.expectRevert(abi.encodeWithSelector(TokenPool.SenderNotAllowed.selector, STRANGER)); diff --git a/contracts/src/v0.8/ccip/test/pools/USDC/USDCTokenPool/USDCTokenPool.releaseOrMint.t.sol b/contracts/src/v0.8/ccip/test/pools/USDC/USDCTokenPool/USDCTokenPool.releaseOrMint.t.sol index 0dfe1dc4925..4499c748a6b 100644 --- a/contracts/src/v0.8/ccip/test/pools/USDC/USDCTokenPool/USDCTokenPool.releaseOrMint.t.sol +++ b/contracts/src/v0.8/ccip/test/pools/USDC/USDCTokenPool/USDCTokenPool.releaseOrMint.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import {Internal} from "../../../../libraries/Internal.sol"; import {Pool} from "../../../../libraries/Pool.sol"; @@ -84,7 +84,7 @@ contract USDCTokenPool_releaseOrMint is USDCTokenPoolSetup { } // https://etherscan.io/tx/0xac9f501fe0b76df1f07a22e1db30929fd12524bc7068d74012dff948632f0883 - function test_ReleaseOrMintRealTx() public { + function test_ReleaseOrMintRealTx_Success() public { bytes memory encodedUsdcMessage = hex"000000000000000300000000000000000000127a00000000000000000000000019330d10d9cc8751218eaf51e8885d058642e08a000000000000000000000000bd3fa81b58ba92a82136038b25adec7066af3155000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000af88d065e77c8cc2239327c5edb3a432268e58310000000000000000000000004af08f56978be7dce2d1be3c65c005b41e79401c000000000000000000000000000000000000000000000000000000002057ff7a0000000000000000000000003a23f943181408eac424116af7b7790c94cb97a50000000000000000000000000000000000000000000000000000000000000000000000000000008274119237535fd659626b090f87e365ff89ebc7096bb32e8b0e85f155626b73ae7c4bb2485c184b7cc3cf7909045487890b104efb62ae74a73e32901bdcec91df1bb9ee08ccb014fcbcfe77b74d1263fd4e0b0e8de05d6c9a5913554364abfd5ea768b222f50c715908183905d74044bb2b97527c7e70ae7983c443a603557cac3b1c000000000000000000000000000000000000000000000000000000000000"; bytes memory attestation = bytes("attestation bytes"); @@ -127,7 +127,7 @@ contract USDCTokenPool_releaseOrMint is USDCTokenPoolSetup { } // Reverts - function test_RevertWhen_UnlockingUSDCFailed() public { + function test_UnlockingUSDCFailed_Revert() public { vm.startPrank(s_routerAllowedOffRamp); s_mockUSDCTransmitter.setShouldSucceed(false); @@ -179,7 +179,7 @@ contract USDCTokenPool_releaseOrMint is USDCTokenPoolSetup { ); } - function test_RevertWhen_TokenMaxCapacityExceeded() public { + function test_TokenMaxCapacityExceeded_Revert() public { uint256 capacity = _getInboundRateLimiterConfig().capacity; uint256 amount = 10 * capacity; address recipient = address(1); diff --git a/contracts/src/v0.8/ccip/test/pools/USDC/USDCTokenPool/USDCTokenPool.setDomains.t.sol b/contracts/src/v0.8/ccip/test/pools/USDC/USDCTokenPool/USDCTokenPool.setDomains.t.sol index 0d4ff379dd7..7fcb75fdf3f 100644 --- a/contracts/src/v0.8/ccip/test/pools/USDC/USDCTokenPool/USDCTokenPool.setDomains.t.sol +++ b/contracts/src/v0.8/ccip/test/pools/USDC/USDCTokenPool/USDCTokenPool.setDomains.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import {Ownable2Step} from "../../../../../shared/access/Ownable2Step.sol"; import {USDCTokenPool} from "../../../../pools/USDC/USDCTokenPool.sol"; @@ -47,7 +47,7 @@ contract USDCTokenPool_setDomains is USDCTokenPoolSetup { // Reverts - function test_RevertWhen_OnlyOwner() public { + function test_OnlyOwner_Revert() public { USDCTokenPool.DomainUpdate[] memory domainUpdates = new USDCTokenPool.DomainUpdate[](0); vm.startPrank(STRANGER); @@ -56,7 +56,7 @@ contract USDCTokenPool_setDomains is USDCTokenPoolSetup { s_usdcTokenPool.setDomains(domainUpdates); } - function test_RevertWhen_InvalidDomain() public { + function test_InvalidDomain_Revert() public { bytes32 validCaller = bytes32(uint256(25)); // Ensure valid domain works USDCTokenPool.DomainUpdate[] memory domainUpdates = new USDCTokenPool.DomainUpdate[](1); diff --git a/contracts/src/v0.8/ccip/test/pools/USDC/USDCTokenPool/USDCTokenPool.supportsInterface.t.sol b/contracts/src/v0.8/ccip/test/pools/USDC/USDCTokenPool/USDCTokenPool.supportsInterface.t.sol index 304791ae2e6..05ac5f08136 100644 --- a/contracts/src/v0.8/ccip/test/pools/USDC/USDCTokenPool/USDCTokenPool.supportsInterface.t.sol +++ b/contracts/src/v0.8/ccip/test/pools/USDC/USDCTokenPool/USDCTokenPool.supportsInterface.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import {IPoolV1} from "../../../../interfaces/IPool.sol"; import {USDCTokenPoolSetup} from "./USDCTokenPoolSetup.t.sol"; @@ -7,7 +7,7 @@ import {USDCTokenPoolSetup} from "./USDCTokenPoolSetup.t.sol"; import {IERC165} from "../../../../../vendor/openzeppelin-solidity/v5.0.2/contracts/utils/introspection/IERC165.sol"; contract USDCTokenPool_supportsInterface is USDCTokenPoolSetup { - function test_SupportsInterface() public view { + function test_SupportsInterface_Success() public view { assertTrue(s_usdcTokenPool.supportsInterface(type(IPoolV1).interfaceId)); assertTrue(s_usdcTokenPool.supportsInterface(type(IERC165).interfaceId)); } diff --git a/contracts/src/v0.8/ccip/test/pools/USDC/USDCTokenPool/USDCTokenPool.validateMessage.t.sol b/contracts/src/v0.8/ccip/test/pools/USDC/USDCTokenPool/USDCTokenPool.validateMessage.t.sol index deaee56c7c7..975368c38b9 100644 --- a/contracts/src/v0.8/ccip/test/pools/USDC/USDCTokenPool/USDCTokenPool.validateMessage.t.sol +++ b/contracts/src/v0.8/ccip/test/pools/USDC/USDCTokenPool/USDCTokenPool.validateMessage.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import {USDCTokenPool} from "../../../../pools/USDC/USDCTokenPool.sol"; import {USDCTokenPoolSetup} from "./USDCTokenPoolSetup.t.sol"; @@ -28,7 +28,7 @@ contract USDCTokenPool__validateMessage is USDCTokenPoolSetup { // Reverts - function test_RevertWhen_ValidateInvalidMessage() public { + function test_ValidateInvalidMessage_Revert() public { USDCMessage memory usdcMessage = USDCMessage({ version: 0, sourceDomain: 1553252, diff --git a/contracts/src/v0.8/ccip/test/pools/USDC/USDCTokenPool/USDCTokenPoolSetup.t.sol b/contracts/src/v0.8/ccip/test/pools/USDC/USDCTokenPool/USDCTokenPoolSetup.t.sol index 0166fe4b645..614da422bb4 100644 --- a/contracts/src/v0.8/ccip/test/pools/USDC/USDCTokenPool/USDCTokenPoolSetup.t.sol +++ b/contracts/src/v0.8/ccip/test/pools/USDC/USDCTokenPool/USDCTokenPoolSetup.t.sol @@ -1,27 +1,90 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; +import {IBurnMintERC20} from "../../../../../shared/token/ERC20/IBurnMintERC20.sol"; + +import {BurnMintERC677} from "../../../../../shared/token/ERC677/BurnMintERC677.sol"; +import {Router} from "../../../../Router.sol"; +import {TokenPool} from "../../../../pools/TokenPool.sol"; import {USDCTokenPool} from "../../../../pools/USDC/USDCTokenPool.sol"; +import {BaseTest} from "../../../BaseTest.t.sol"; import {USDCTokenPoolHelper} from "../../../helpers/USDCTokenPoolHelper.sol"; -import {USDCSetup} from "../USDCSetup.t.sol"; +import {MockE2EUSDCTransmitter} from "../../../mocks/MockE2EUSDCTransmitter.sol"; +import {MockUSDCTokenMessenger} from "../../../mocks/MockUSDCTokenMessenger.sol"; + +contract USDCTokenPoolSetup is BaseTest { + IBurnMintERC20 internal s_token; + MockUSDCTokenMessenger internal s_mockUSDC; + MockE2EUSDCTransmitter internal s_mockUSDCTransmitter; + uint32 internal constant USDC_DEST_TOKEN_GAS = 150_000; + + struct USDCMessage { + uint32 version; + uint32 sourceDomain; + uint32 destinationDomain; + uint64 nonce; + bytes32 sender; + bytes32 recipient; + bytes32 destinationCaller; + bytes messageBody; + } + + uint32 internal constant SOURCE_DOMAIN_IDENTIFIER = 0x02020202; + uint32 internal constant DEST_DOMAIN_IDENTIFIER = 0; + + bytes32 internal constant SOURCE_CHAIN_TOKEN_SENDER = bytes32(uint256(uint160(0x01111111221))); + address internal constant SOURCE_CHAIN_USDC_POOL = address(0x23789765456789); + address internal constant DEST_CHAIN_USDC_POOL = address(0x987384873458734); + address internal constant DEST_CHAIN_USDC_TOKEN = address(0x23598918358198766); + + address internal s_routerAllowedOnRamp = address(3456); + address internal s_routerAllowedOffRamp = address(234); + Router internal s_router; -contract USDCTokenPoolSetup is USDCSetup { USDCTokenPoolHelper internal s_usdcTokenPool; USDCTokenPoolHelper internal s_usdcTokenPoolWithAllowList; address[] internal s_allowedList; function setUp() public virtual override { - super.setUp(); + BaseTest.setUp(); + BurnMintERC677 usdcToken = new BurnMintERC677("LINK", "LNK", 18, 0); + s_token = usdcToken; + deal(address(s_token), OWNER, type(uint256).max); + _setUpRamps(); + + s_mockUSDCTransmitter = new MockE2EUSDCTransmitter(0, DEST_DOMAIN_IDENTIFIER, address(s_token)); + s_mockUSDC = new MockUSDCTokenMessenger(0, address(s_mockUSDCTransmitter)); + + usdcToken.grantMintAndBurnRoles(address(s_mockUSDCTransmitter)); s_usdcTokenPool = - new USDCTokenPoolHelper(s_mockUSDC, s_token, new address[](0), address(s_mockRMNRemote), address(s_router)); + new USDCTokenPoolHelper(s_mockUSDC, s_token, new address[](0), address(s_mockRMN), address(s_router)); + usdcToken.grantMintAndBurnRoles(address(s_mockUSDC)); - s_allowedList.push(vm.randomAddress()); + s_allowedList.push(USER_1); s_usdcTokenPoolWithAllowList = - new USDCTokenPoolHelper(s_mockUSDC, s_token, s_allowedList, address(s_mockRMNRemote), address(s_router)); + new USDCTokenPoolHelper(s_mockUSDC, s_token, s_allowedList, address(s_mockRMN), address(s_router)); - _poolApplyChainUpdates(address(s_usdcTokenPool)); - _poolApplyChainUpdates(address(s_usdcTokenPoolWithAllowList)); + TokenPool.ChainUpdate[] memory chainUpdates = new TokenPool.ChainUpdate[](2); + chainUpdates[0] = TokenPool.ChainUpdate({ + remoteChainSelector: SOURCE_CHAIN_SELECTOR, + remotePoolAddress: abi.encode(SOURCE_CHAIN_USDC_POOL), + remoteTokenAddress: abi.encode(address(s_token)), + allowed: true, + outboundRateLimiterConfig: _getOutboundRateLimiterConfig(), + inboundRateLimiterConfig: _getInboundRateLimiterConfig() + }); + chainUpdates[1] = TokenPool.ChainUpdate({ + remoteChainSelector: DEST_CHAIN_SELECTOR, + remotePoolAddress: abi.encode(DEST_CHAIN_USDC_POOL), + remoteTokenAddress: abi.encode(DEST_CHAIN_USDC_TOKEN), + allowed: true, + outboundRateLimiterConfig: _getOutboundRateLimiterConfig(), + inboundRateLimiterConfig: _getInboundRateLimiterConfig() + }); + + s_usdcTokenPool.applyChainUpdates(chainUpdates); + s_usdcTokenPoolWithAllowList.applyChainUpdates(chainUpdates); USDCTokenPool.DomainUpdate[] memory domains = new USDCTokenPool.DomainUpdate[](1); domains[0] = USDCTokenPool.DomainUpdate({ @@ -34,4 +97,32 @@ contract USDCTokenPoolSetup is USDCSetup { s_usdcTokenPool.setDomains(domains); s_usdcTokenPoolWithAllowList.setDomains(domains); } + + function _setUpRamps() internal { + s_router = new Router(address(s_token), address(s_mockRMN)); + + Router.OnRamp[] memory onRampUpdates = new Router.OnRamp[](1); + onRampUpdates[0] = Router.OnRamp({destChainSelector: DEST_CHAIN_SELECTOR, onRamp: s_routerAllowedOnRamp}); + Router.OffRamp[] memory offRampUpdates = new Router.OffRamp[](1); + address[] memory offRamps = new address[](1); + offRamps[0] = s_routerAllowedOffRamp; + offRampUpdates[0] = Router.OffRamp({sourceChainSelector: SOURCE_CHAIN_SELECTOR, offRamp: offRamps[0]}); + + s_router.applyRampUpdates(onRampUpdates, new Router.OffRamp[](0), offRampUpdates); + } + + function _generateUSDCMessage( + USDCMessage memory usdcMessage + ) internal pure returns (bytes memory) { + return abi.encodePacked( + usdcMessage.version, + usdcMessage.sourceDomain, + usdcMessage.destinationDomain, + usdcMessage.nonce, + usdcMessage.sender, + usdcMessage.recipient, + usdcMessage.destinationCaller, + usdcMessage.messageBody + ); + } } diff --git a/contracts/src/v0.8/ccip/test/rateLimiter/MutiAggregateRateLimiter/MultiAggregateRateLimiterSetup.t.sol b/contracts/src/v0.8/ccip/test/rateLimiter/MutiAggregateRateLimiter/MultiAggregateRateLimiterSetup.t.sol index 73dbeff1bf4..d3e87f5faa4 100644 --- a/contracts/src/v0.8/ccip/test/rateLimiter/MutiAggregateRateLimiter/MultiAggregateRateLimiterSetup.t.sol +++ b/contracts/src/v0.8/ccip/test/rateLimiter/MutiAggregateRateLimiter/MultiAggregateRateLimiterSetup.t.sol @@ -1,14 +1,16 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import {MultiAggregateRateLimiter} from "../../../MultiAggregateRateLimiter.sol"; import {Client} from "../../../libraries/Client.sol"; import {Internal} from "../../../libraries/Internal.sol"; import {RateLimiter} from "../../../libraries/RateLimiter.sol"; +import {BaseTest} from "../../BaseTest.t.sol"; + import {FeeQuoterSetup} from "../../feeQuoter/FeeQuoterSetup.t.sol"; import {MultiAggregateRateLimiterHelper} from "../../helpers/MultiAggregateRateLimiterHelper.sol"; -contract MultiAggregateRateLimiterSetup is FeeQuoterSetup { +contract MultiAggregateRateLimiterSetup is BaseTest, FeeQuoterSetup { MultiAggregateRateLimiterHelper internal s_rateLimiter; address internal constant TOKEN = 0x21118E64E1fB0c487F25Dd6d3601FF6af8D32E4e; @@ -25,7 +27,8 @@ contract MultiAggregateRateLimiterSetup is FeeQuoterSetup { address[] internal s_authorizedCallers; - function setUp() public virtual override { + function setUp() public virtual override(BaseTest, FeeQuoterSetup) { + BaseTest.setUp(); FeeQuoterSetup.setUp(); Internal.PriceUpdates memory priceUpdates = _getSingleTokenPriceUpdateStruct(TOKEN, TOKEN_PRICE); diff --git a/contracts/src/v0.8/ccip/test/rateLimiter/MutiAggregateRateLimiter/MultiAggregateRateLimiter_applyRateLimiterConfigUpdates.t.sol b/contracts/src/v0.8/ccip/test/rateLimiter/MutiAggregateRateLimiter/MultiAggregateRateLimiter_applyRateLimiterConfigUpdates.t.sol index 78f2101b852..306be6b5956 100644 --- a/contracts/src/v0.8/ccip/test/rateLimiter/MutiAggregateRateLimiter/MultiAggregateRateLimiter_applyRateLimiterConfigUpdates.t.sol +++ b/contracts/src/v0.8/ccip/test/rateLimiter/MutiAggregateRateLimiter/MultiAggregateRateLimiter_applyRateLimiterConfigUpdates.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import {Ownable2Step} from "../../../../shared/access/Ownable2Step.sol"; import {MultiAggregateRateLimiter} from "../../../MultiAggregateRateLimiter.sol"; @@ -9,7 +9,7 @@ import {MultiAggregateRateLimiterSetup} from "./MultiAggregateRateLimiterSetup.t import {Vm} from "forge-std/Vm.sol"; contract MultiAggregateRateLimiter_applyRateLimiterConfigUpdates is MultiAggregateRateLimiterSetup { - function test_ZeroConfigs() public { + function test_ZeroConfigs_Success() public { MultiAggregateRateLimiter.RateLimiterConfigArgs[] memory configUpdates = new MultiAggregateRateLimiter.RateLimiterConfigArgs[](0); @@ -20,7 +20,7 @@ contract MultiAggregateRateLimiter_applyRateLimiterConfigUpdates is MultiAggrega assertEq(logEntries.length, 0); } - function test_SingleConfig() public { + function test_SingleConfig_Success() public { MultiAggregateRateLimiter.RateLimiterConfigArgs[] memory configUpdates = new MultiAggregateRateLimiter.RateLimiterConfigArgs[](1); configUpdates[0] = MultiAggregateRateLimiter.RateLimiterConfigArgs({ @@ -46,7 +46,7 @@ contract MultiAggregateRateLimiter_applyRateLimiterConfigUpdates is MultiAggrega assertEq(BLOCK_TIME, bucket1.lastUpdated); } - function test_SingleConfigOutbound() public { + function test_SingleConfigOutbound_Success() public { MultiAggregateRateLimiter.RateLimiterConfigArgs[] memory configUpdates = new MultiAggregateRateLimiter.RateLimiterConfigArgs[](1); configUpdates[0] = MultiAggregateRateLimiter.RateLimiterConfigArgs({ @@ -72,7 +72,7 @@ contract MultiAggregateRateLimiter_applyRateLimiterConfigUpdates is MultiAggrega assertEq(BLOCK_TIME, bucket1.lastUpdated); } - function test_MultipleConfigs() public { + function test_MultipleConfigs_Success() public { MultiAggregateRateLimiter.RateLimiterConfigArgs[] memory configUpdates = new MultiAggregateRateLimiter.RateLimiterConfigArgs[](5); @@ -103,7 +103,7 @@ contract MultiAggregateRateLimiter_applyRateLimiterConfigUpdates is MultiAggrega } } - function test_MultipleConfigsBothLanes() public { + function test_MultipleConfigsBothLanes_Success() public { MultiAggregateRateLimiter.RateLimiterConfigArgs[] memory configUpdates = new MultiAggregateRateLimiter.RateLimiterConfigArgs[](2); @@ -134,7 +134,7 @@ contract MultiAggregateRateLimiter_applyRateLimiterConfigUpdates is MultiAggrega } } - function test_UpdateExistingConfig() public { + function test_UpdateExistingConfig_Success() public { MultiAggregateRateLimiter.RateLimiterConfigArgs[] memory configUpdates = new MultiAggregateRateLimiter.RateLimiterConfigArgs[](1); configUpdates[0] = MultiAggregateRateLimiter.RateLimiterConfigArgs({ @@ -170,7 +170,7 @@ contract MultiAggregateRateLimiter_applyRateLimiterConfigUpdates is MultiAggrega ); } - function test_UpdateExistingConfigWithNoDifference() public { + function test_UpdateExistingConfigWithNoDifference_Success() public { MultiAggregateRateLimiter.RateLimiterConfigArgs[] memory configUpdates = new MultiAggregateRateLimiter.RateLimiterConfigArgs[](1); configUpdates[0] = MultiAggregateRateLimiter.RateLimiterConfigArgs({ @@ -198,7 +198,7 @@ contract MultiAggregateRateLimiter_applyRateLimiterConfigUpdates is MultiAggrega } // Reverts - function test_RevertWhen_ZeroChainSelector() public { + function test_ZeroChainSelector_Revert() public { MultiAggregateRateLimiter.RateLimiterConfigArgs[] memory configUpdates = new MultiAggregateRateLimiter.RateLimiterConfigArgs[](1); configUpdates[0] = MultiAggregateRateLimiter.RateLimiterConfigArgs({ @@ -211,7 +211,7 @@ contract MultiAggregateRateLimiter_applyRateLimiterConfigUpdates is MultiAggrega s_rateLimiter.applyRateLimiterConfigUpdates(configUpdates); } - function test_RevertWhen_OnlyCallableByOwner() public { + function test_OnlyCallableByOwner_Revert() public { MultiAggregateRateLimiter.RateLimiterConfigArgs[] memory configUpdates = new MultiAggregateRateLimiter.RateLimiterConfigArgs[](1); configUpdates[0] = MultiAggregateRateLimiter.RateLimiterConfigArgs({ @@ -225,7 +225,7 @@ contract MultiAggregateRateLimiter_applyRateLimiterConfigUpdates is MultiAggrega s_rateLimiter.applyRateLimiterConfigUpdates(configUpdates); } - function test_RevertWhen_ConfigRateMoreThanCapacity() public { + function test_ConfigRateMoreThanCapacity_Revert() public { MultiAggregateRateLimiter.RateLimiterConfigArgs[] memory configUpdates = new MultiAggregateRateLimiter.RateLimiterConfigArgs[](1); configUpdates[0] = MultiAggregateRateLimiter.RateLimiterConfigArgs({ @@ -240,7 +240,7 @@ contract MultiAggregateRateLimiter_applyRateLimiterConfigUpdates is MultiAggrega s_rateLimiter.applyRateLimiterConfigUpdates(configUpdates); } - function test_RevertWhen_ConfigRateZero() public { + function test_ConfigRateZero_Revert() public { MultiAggregateRateLimiter.RateLimiterConfigArgs[] memory configUpdates = new MultiAggregateRateLimiter.RateLimiterConfigArgs[](1); configUpdates[0] = MultiAggregateRateLimiter.RateLimiterConfigArgs({ @@ -255,7 +255,7 @@ contract MultiAggregateRateLimiter_applyRateLimiterConfigUpdates is MultiAggrega s_rateLimiter.applyRateLimiterConfigUpdates(configUpdates); } - function test_RevertWhen_DisableConfigRateNonZero() public { + function test_DisableConfigRateNonZero_Revert() public { MultiAggregateRateLimiter.RateLimiterConfigArgs[] memory configUpdates = new MultiAggregateRateLimiter.RateLimiterConfigArgs[](1); configUpdates[0] = MultiAggregateRateLimiter.RateLimiterConfigArgs({ @@ -270,7 +270,7 @@ contract MultiAggregateRateLimiter_applyRateLimiterConfigUpdates is MultiAggrega s_rateLimiter.applyRateLimiterConfigUpdates(configUpdates); } - function test_RevertWhen_DiableConfigCapacityNonZero() public { + function test_DiableConfigCapacityNonZero_Revert() public { MultiAggregateRateLimiter.RateLimiterConfigArgs[] memory configUpdates = new MultiAggregateRateLimiter.RateLimiterConfigArgs[](1); configUpdates[0] = MultiAggregateRateLimiter.RateLimiterConfigArgs({ diff --git a/contracts/src/v0.8/ccip/test/rateLimiter/MutiAggregateRateLimiter/MultiAggregateRateLimiter_constructor.t.sol b/contracts/src/v0.8/ccip/test/rateLimiter/MutiAggregateRateLimiter/MultiAggregateRateLimiter_constructor.t.sol index c9ea2bce69a..0f858a79a56 100644 --- a/contracts/src/v0.8/ccip/test/rateLimiter/MutiAggregateRateLimiter/MultiAggregateRateLimiter_constructor.t.sol +++ b/contracts/src/v0.8/ccip/test/rateLimiter/MutiAggregateRateLimiter/MultiAggregateRateLimiter_constructor.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import {MultiAggregateRateLimiter} from "../../../MultiAggregateRateLimiter.sol"; import {MultiAggregateRateLimiterHelper} from "../../helpers/MultiAggregateRateLimiterHelper.sol"; @@ -7,7 +7,7 @@ import {MultiAggregateRateLimiterSetup} from "./MultiAggregateRateLimiterSetup.t import {Vm} from "forge-std/Vm.sol"; contract MultiAggregateRateLimiter_constructor is MultiAggregateRateLimiterSetup { - function test_ConstructorNoAuthorizedCallers() public { + function test_ConstructorNoAuthorizedCallers_Success() public { address[] memory authorizedCallers = new address[](0); vm.recordLogs(); @@ -21,7 +21,7 @@ contract MultiAggregateRateLimiter_constructor is MultiAggregateRateLimiterSetup assertEq(address(s_feeQuoter), s_rateLimiter.getFeeQuoter()); } - function test_Constructor() public { + function test_Constructor_Success() public { address[] memory authorizedCallers = new address[](2); authorizedCallers[0] = MOCK_OFFRAMP; authorizedCallers[1] = MOCK_ONRAMP; diff --git a/contracts/src/v0.8/ccip/test/rateLimiter/MutiAggregateRateLimiter/MultiAggregateRateLimiter_getTokenBucket.t.sol b/contracts/src/v0.8/ccip/test/rateLimiter/MutiAggregateRateLimiter/MultiAggregateRateLimiter_getTokenBucket.t.sol index dabf1b60c9a..bfb5da07da3 100644 --- a/contracts/src/v0.8/ccip/test/rateLimiter/MutiAggregateRateLimiter/MultiAggregateRateLimiter_getTokenBucket.t.sol +++ b/contracts/src/v0.8/ccip/test/rateLimiter/MutiAggregateRateLimiter/MultiAggregateRateLimiter_getTokenBucket.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import {MultiAggregateRateLimiter} from "../../../MultiAggregateRateLimiter.sol"; import {RateLimiter} from "../../../libraries/RateLimiter.sol"; @@ -8,7 +8,7 @@ import {MultiAggregateRateLimiterSetup} from "./MultiAggregateRateLimiterSetup.t import {stdError} from "forge-std/Test.sol"; contract MultiAggregateRateLimiter_getTokenBucket is MultiAggregateRateLimiterSetup { - function test_GetTokenBucket() public view { + function test_GetTokenBucket_Success() public view { RateLimiter.TokenBucket memory bucketInbound = s_rateLimiter.currentRateLimiterState(CHAIN_SELECTOR_1, false); _assertConfigWithTokenBucketEquality(s_rateLimiterConfig1, bucketInbound); assertEq(BLOCK_TIME, bucketInbound.lastUpdated); @@ -18,7 +18,7 @@ contract MultiAggregateRateLimiter_getTokenBucket is MultiAggregateRateLimiterSe assertEq(BLOCK_TIME, bucketOutbound.lastUpdated); } - function test_Refill() public { + function test_Refill_Success() public { s_rateLimiterConfig1.capacity = s_rateLimiterConfig1.capacity * 2; MultiAggregateRateLimiter.RateLimiterConfigArgs[] memory configUpdates = @@ -57,7 +57,7 @@ contract MultiAggregateRateLimiter_getTokenBucket is MultiAggregateRateLimiterSe // Reverts - function test_RevertWhen_TimeUnderflow() public { + function test_TimeUnderflow_Revert() public { vm.warp(BLOCK_TIME - 1); vm.expectRevert(stdError.arithmeticError); diff --git a/contracts/src/v0.8/ccip/test/rateLimiter/MutiAggregateRateLimiter/MultiAggregateRateLimiter_getTokenValue.t.sol b/contracts/src/v0.8/ccip/test/rateLimiter/MutiAggregateRateLimiter/MultiAggregateRateLimiter_getTokenValue.t.sol index a70c28ec875..9b4448339e8 100644 --- a/contracts/src/v0.8/ccip/test/rateLimiter/MutiAggregateRateLimiter/MultiAggregateRateLimiter_getTokenValue.t.sol +++ b/contracts/src/v0.8/ccip/test/rateLimiter/MutiAggregateRateLimiter/MultiAggregateRateLimiter_getTokenValue.t.sol @@ -1,12 +1,12 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import {MultiAggregateRateLimiter} from "../../../MultiAggregateRateLimiter.sol"; import {Client} from "../../../libraries/Client.sol"; import {MultiAggregateRateLimiterSetup} from "./MultiAggregateRateLimiterSetup.t.sol"; contract MultiAggregateRateLimiter_getTokenValue is MultiAggregateRateLimiterSetup { - function test_GetTokenValue() public view { + function test_GetTokenValue_Success() public view { uint256 numberOfTokens = 10; Client.EVMTokenAmount memory tokenAmount = Client.EVMTokenAmount({token: TOKEN, amount: 10}); uint256 value = s_rateLimiter.getTokenValue(tokenAmount); @@ -14,7 +14,7 @@ contract MultiAggregateRateLimiter_getTokenValue is MultiAggregateRateLimiterSet } // Reverts - function test_RevertWhen_NoTokenPrices() public { + function test_NoTokenPrice_Reverts() public { address tokenWithNoPrice = makeAddr("Token with no price"); Client.EVMTokenAmount memory tokenAmount = Client.EVMTokenAmount({token: tokenWithNoPrice, amount: 10}); diff --git a/contracts/src/v0.8/ccip/test/rateLimiter/MutiAggregateRateLimiter/MultiAggregateRateLimiter_onInboundMessage.t.sol b/contracts/src/v0.8/ccip/test/rateLimiter/MutiAggregateRateLimiter/MultiAggregateRateLimiter_onInboundMessage.t.sol index 48f7ec88a42..8697dae871e 100644 --- a/contracts/src/v0.8/ccip/test/rateLimiter/MutiAggregateRateLimiter/MultiAggregateRateLimiter_onInboundMessage.t.sol +++ b/contracts/src/v0.8/ccip/test/rateLimiter/MutiAggregateRateLimiter/MultiAggregateRateLimiter_onInboundMessage.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import {AuthorizedCallers} from "../../../../shared/access/AuthorizedCallers.sol"; import {MultiAggregateRateLimiter} from "../../../MultiAggregateRateLimiter.sol"; @@ -34,7 +34,7 @@ contract MultiAggregateRateLimiter_onInboundMessage is MultiAggregateRateLimiter s_rateLimiter.updateRateLimitTokens(new MultiAggregateRateLimiter.LocalRateLimitToken[](0), tokensToAdd); } - function test_ValidateMessageWithNoTokens() public { + function test_ValidateMessageWithNoTokens_Success() public { vm.startPrank(MOCK_OFFRAMP); vm.recordLogs(); @@ -45,7 +45,7 @@ contract MultiAggregateRateLimiter_onInboundMessage is MultiAggregateRateLimiter assertEq(logEntries.length, 0); } - function test_ValidateMessageWithTokens() public { + function test_ValidateMessageWithTokens_Success() public { vm.startPrank(MOCK_OFFRAMP); Client.EVMTokenAmount[] memory tokenAmounts = new Client.EVMTokenAmount[](2); @@ -59,7 +59,7 @@ contract MultiAggregateRateLimiter_onInboundMessage is MultiAggregateRateLimiter s_rateLimiter.onInboundMessage(_generateAny2EVMMessage(CHAIN_SELECTOR_1, tokenAmounts)); } - function test_ValidateMessageWithDisabledRateLimitToken() public { + function test_ValidateMessageWithDisabledRateLimitToken_Success() public { MultiAggregateRateLimiter.LocalRateLimitToken[] memory removes = new MultiAggregateRateLimiter.LocalRateLimitToken[](1); removes[0] = MultiAggregateRateLimiter.LocalRateLimitToken({ @@ -80,7 +80,7 @@ contract MultiAggregateRateLimiter_onInboundMessage is MultiAggregateRateLimiter s_rateLimiter.onInboundMessage(_generateAny2EVMMessage(CHAIN_SELECTOR_1, tokenAmounts)); } - function test_ValidateMessageWithRateLimitDisabled() public { + function test_ValidateMessageWithRateLimitDisabled_Success() public { MultiAggregateRateLimiter.RateLimiterConfigArgs[] memory configUpdates = new MultiAggregateRateLimiter.RateLimiterConfigArgs[](1); configUpdates[0] = MultiAggregateRateLimiter.RateLimiterConfigArgs({ @@ -104,7 +104,7 @@ contract MultiAggregateRateLimiter_onInboundMessage is MultiAggregateRateLimiter assertEq(logEntries.length, 0); } - function test_ValidateMessageWithTokensOnDifferentChains() public { + function test_ValidateMessageWithTokensOnDifferentChains_Success() public { MultiAggregateRateLimiter.RateLimitTokenArgs[] memory tokensToAdd = new MultiAggregateRateLimiter.RateLimitTokenArgs[](s_sourceTokens.length); for (uint224 i = 0; i < s_sourceTokens.length; ++i) { @@ -152,7 +152,7 @@ contract MultiAggregateRateLimiter_onInboundMessage is MultiAggregateRateLimiter assertEq(bucketChain2.capacity - totalValue, bucketChain2.tokens); } - function test_ValidateMessageWithDifferentTokensOnDifferentChains() public { + function test_ValidateMessageWithDifferentTokensOnDifferentChains_Success() public { MultiAggregateRateLimiter.RateLimitTokenArgs[] memory tokensToAdd = new MultiAggregateRateLimiter.RateLimitTokenArgs[](1); @@ -203,7 +203,7 @@ contract MultiAggregateRateLimiter_onInboundMessage is MultiAggregateRateLimiter assertEq(bucketChain2.capacity - totalValue2, bucketChain2.tokens); } - function test_ValidateMessageWithRateLimitReset() public { + function test_ValidateMessageWithRateLimitReset_Success() public { vm.startPrank(MOCK_OFFRAMP); Client.EVMTokenAmount[] memory tokenAmounts = new Client.EVMTokenAmount[](2); @@ -228,7 +228,7 @@ contract MultiAggregateRateLimiter_onInboundMessage is MultiAggregateRateLimiter // Reverts - function test_RevertWhen_ValidateMessageWithRateLimitExceeded() public { + function test_ValidateMessageWithRateLimitExceeded_Revert() public { vm.startPrank(MOCK_OFFRAMP); Client.EVMTokenAmount[] memory tokenAmounts = new Client.EVMTokenAmount[](2); @@ -240,7 +240,7 @@ contract MultiAggregateRateLimiter_onInboundMessage is MultiAggregateRateLimiter s_rateLimiter.onInboundMessage(_generateAny2EVMMessage(CHAIN_SELECTOR_1, tokenAmounts)); } - function test_RevertWhen_ValidateMessageFromUnauthorizedCaller() public { + function test_ValidateMessageFromUnauthorizedCaller_Revert() public { vm.startPrank(STRANGER); vm.expectRevert(abi.encodeWithSelector(AuthorizedCallers.UnauthorizedCaller.selector, STRANGER)); diff --git a/contracts/src/v0.8/ccip/test/rateLimiter/MutiAggregateRateLimiter/MultiAggregateRateLimiter_onOutboundMessage.t.sol b/contracts/src/v0.8/ccip/test/rateLimiter/MutiAggregateRateLimiter/MultiAggregateRateLimiter_onOutboundMessage.t.sol index 7886a77f5b6..9d20e203619 100644 --- a/contracts/src/v0.8/ccip/test/rateLimiter/MutiAggregateRateLimiter/MultiAggregateRateLimiter_onOutboundMessage.t.sol +++ b/contracts/src/v0.8/ccip/test/rateLimiter/MutiAggregateRateLimiter/MultiAggregateRateLimiter_onOutboundMessage.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import {AuthorizedCallers} from "../../../../shared/access/AuthorizedCallers.sol"; import {MultiAggregateRateLimiter} from "../../../MultiAggregateRateLimiter.sol"; @@ -31,7 +31,7 @@ contract MultiAggregateRateLimiter_onOutboundMessage is MultiAggregateRateLimite s_rateLimiter.updateRateLimitTokens(new MultiAggregateRateLimiter.LocalRateLimitToken[](0), tokensToAdd); } - function test_ValidateMessageWithNoTokens() public { + function test_ValidateMessageWithNoTokens_Success() public { vm.startPrank(MOCK_ONRAMP); vm.recordLogs(); @@ -41,7 +41,7 @@ contract MultiAggregateRateLimiter_onOutboundMessage is MultiAggregateRateLimite assertEq(vm.getRecordedLogs().length, 0); } - function test_onOutboundMessage_ValidateMessageWithTokens() public { + function test_onOutboundMessage_ValidateMessageWithTokens_Success() public { vm.startPrank(MOCK_ONRAMP); Client.EVMTokenAmount[] memory tokenAmounts = new Client.EVMTokenAmount[](2); @@ -55,7 +55,7 @@ contract MultiAggregateRateLimiter_onOutboundMessage is MultiAggregateRateLimite s_rateLimiter.onOutboundMessage(CHAIN_SELECTOR_1, _generateEVM2AnyMessage(tokenAmounts)); } - function test_onOutboundMessage_ValidateMessageWithDisabledRateLimitToken() public { + function test_onOutboundMessage_ValidateMessageWithDisabledRateLimitToken_Success() public { MultiAggregateRateLimiter.LocalRateLimitToken[] memory removes = new MultiAggregateRateLimiter.LocalRateLimitToken[](1); removes[0] = MultiAggregateRateLimiter.LocalRateLimitToken({ @@ -76,7 +76,7 @@ contract MultiAggregateRateLimiter_onOutboundMessage is MultiAggregateRateLimite s_rateLimiter.onOutboundMessage(CHAIN_SELECTOR_1, _generateEVM2AnyMessage(tokenAmounts)); } - function test_onOutboundMessage_ValidateMessageWithRateLimitDisabled() public { + function test_onOutboundMessage_ValidateMessageWithRateLimitDisabled_Success() public { MultiAggregateRateLimiter.RateLimiterConfigArgs[] memory configUpdates = new MultiAggregateRateLimiter.RateLimiterConfigArgs[](1); configUpdates[0] = MultiAggregateRateLimiter.RateLimiterConfigArgs({ @@ -99,7 +99,7 @@ contract MultiAggregateRateLimiter_onOutboundMessage is MultiAggregateRateLimite assertEq(vm.getRecordedLogs().length, 0); } - function test_onOutboundMessage_ValidateMessageWithTokensOnDifferentChains() public { + function test_onOutboundMessage_ValidateMessageWithTokensOnDifferentChains_Success() public { MultiAggregateRateLimiter.RateLimitTokenArgs[] memory tokensToAdd = new MultiAggregateRateLimiter.RateLimitTokenArgs[](s_sourceTokens.length); for (uint224 i = 0; i < s_sourceTokens.length; ++i) { @@ -147,7 +147,7 @@ contract MultiAggregateRateLimiter_onOutboundMessage is MultiAggregateRateLimite assertEq(bucketChain2.capacity - totalValue, bucketChain2.tokens); } - function test_onOutboundMessage_ValidateMessageWithDifferentTokensOnDifferentChains() public { + function test_onOutboundMessage_ValidateMessageWithDifferentTokensOnDifferentChains_Success() public { MultiAggregateRateLimiter.RateLimitTokenArgs[] memory tokensToAdd = new MultiAggregateRateLimiter.RateLimitTokenArgs[](1); @@ -198,7 +198,7 @@ contract MultiAggregateRateLimiter_onOutboundMessage is MultiAggregateRateLimite assertEq(bucketChain2.capacity - totalValue2, bucketChain2.tokens); } - function test_onOutboundMessage_ValidateMessageWithRateLimitReset() public { + function test_onOutboundMessage_ValidateMessageWithRateLimitReset_Success() public { vm.startPrank(MOCK_ONRAMP); Client.EVMTokenAmount[] memory tokenAmounts = new Client.EVMTokenAmount[](2); @@ -221,7 +221,7 @@ contract MultiAggregateRateLimiter_onOutboundMessage is MultiAggregateRateLimite s_rateLimiter.onOutboundMessage(CHAIN_SELECTOR_1, _generateEVM2AnyMessage(tokenAmounts)); } - function test_RateLimitValueDifferentLanes() public { + function test_RateLimitValueDifferentLanes_Success() public { vm.pauseGasMetering(); // start from blocktime that does not equal rate limiter init timestamp vm.warp(BLOCK_TIME + 1); @@ -266,7 +266,7 @@ contract MultiAggregateRateLimiter_onOutboundMessage is MultiAggregateRateLimite // Reverts - function test_RevertWhen_onOutboundMessage_ValidateMessageWithRateLimitExceeded() public { + function test_onOutboundMessage_ValidateMessageWithRateLimitExceeded_Revert() public { vm.startPrank(MOCK_OFFRAMP); Client.EVMTokenAmount[] memory tokenAmounts = new Client.EVMTokenAmount[](2); @@ -278,7 +278,7 @@ contract MultiAggregateRateLimiter_onOutboundMessage is MultiAggregateRateLimite s_rateLimiter.onOutboundMessage(CHAIN_SELECTOR_1, _generateEVM2AnyMessage(tokenAmounts)); } - function test_RevertWhen_onOutboundMessage_ValidateMessageFromUnauthorizedCaller() public { + function test_onOutboundMessage_ValidateMessageFromUnauthorizedCaller_Revert() public { vm.startPrank(STRANGER); vm.expectRevert(abi.encodeWithSelector(AuthorizedCallers.UnauthorizedCaller.selector, STRANGER)); diff --git a/contracts/src/v0.8/ccip/test/rateLimiter/MutiAggregateRateLimiter/MultiAggregateRateLimiter_setFeeQuoter.t.sol b/contracts/src/v0.8/ccip/test/rateLimiter/MutiAggregateRateLimiter/MultiAggregateRateLimiter_setFeeQuoter.t.sol index 77968339685..39412a65045 100644 --- a/contracts/src/v0.8/ccip/test/rateLimiter/MutiAggregateRateLimiter/MultiAggregateRateLimiter_setFeeQuoter.t.sol +++ b/contracts/src/v0.8/ccip/test/rateLimiter/MutiAggregateRateLimiter/MultiAggregateRateLimiter_setFeeQuoter.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import {AuthorizedCallers} from "../../../../shared/access/AuthorizedCallers.sol"; import {Ownable2Step} from "../../../../shared/access/Ownable2Step.sol"; @@ -7,7 +7,7 @@ import {MultiAggregateRateLimiter} from "../../../MultiAggregateRateLimiter.sol" import {MultiAggregateRateLimiterSetup} from "./MultiAggregateRateLimiterSetup.t.sol"; contract MultiAggregateRateLimiter_setFeeQuoter is MultiAggregateRateLimiterSetup { - function test_Owner() public { + function test_Owner_Success() public { address newAddress = address(42); vm.expectEmit(); @@ -19,14 +19,14 @@ contract MultiAggregateRateLimiter_setFeeQuoter is MultiAggregateRateLimiterSetu // Reverts - function test_RevertWhen_OnlyOwner() public { + function test_OnlyOwner_Revert() public { vm.startPrank(STRANGER); vm.expectRevert(Ownable2Step.OnlyCallableByOwner.selector); s_rateLimiter.setFeeQuoter(STRANGER); } - function test_RevertWhen_ZeroAddress() public { + function test_ZeroAddress_Revert() public { vm.expectRevert(AuthorizedCallers.ZeroAddressNotAllowed.selector); s_rateLimiter.setFeeQuoter(address(0)); } diff --git a/contracts/src/v0.8/ccip/test/rateLimiter/MutiAggregateRateLimiter/MultiAggregateRateLimiter_updateRateLimitTokens.t.sol b/contracts/src/v0.8/ccip/test/rateLimiter/MutiAggregateRateLimiter/MultiAggregateRateLimiter_updateRateLimitTokens.t.sol index 85c9495c05e..2125983ed70 100644 --- a/contracts/src/v0.8/ccip/test/rateLimiter/MutiAggregateRateLimiter/MultiAggregateRateLimiter_updateRateLimitTokens.t.sol +++ b/contracts/src/v0.8/ccip/test/rateLimiter/MutiAggregateRateLimiter/MultiAggregateRateLimiter_updateRateLimitTokens.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import {AuthorizedCallers} from "../../../../shared/access/AuthorizedCallers.sol"; import {Ownable2Step} from "../../../../shared/access/Ownable2Step.sol"; @@ -24,7 +24,7 @@ contract MultiAggregateRateLimiter_updateRateLimitTokens is MultiAggregateRateLi s_rateLimiter.updateRateLimitTokens(removes, new MultiAggregateRateLimiter.RateLimitTokenArgs[](0)); } - function test_UpdateRateLimitTokensSingleChain() public { + function test_UpdateRateLimitTokensSingleChain_Success() public { MultiAggregateRateLimiter.RateLimitTokenArgs[] memory adds = new MultiAggregateRateLimiter.RateLimitTokenArgs[](2); adds[0] = MultiAggregateRateLimiter.RateLimitTokenArgs({ localTokenArgs: MultiAggregateRateLimiter.LocalRateLimitToken({ @@ -61,7 +61,7 @@ contract MultiAggregateRateLimiter_updateRateLimitTokens is MultiAggregateRateLi } } - function test_UpdateRateLimitTokensMultipleChains() public { + function test_UpdateRateLimitTokensMultipleChains_Success() public { MultiAggregateRateLimiter.RateLimitTokenArgs[] memory adds = new MultiAggregateRateLimiter.RateLimitTokenArgs[](2); adds[0] = MultiAggregateRateLimiter.RateLimitTokenArgs({ localTokenArgs: MultiAggregateRateLimiter.LocalRateLimitToken({ @@ -104,7 +104,7 @@ contract MultiAggregateRateLimiter_updateRateLimitTokens is MultiAggregateRateLi assertEq(remoteTokensChain2[0], adds[1].remoteToken); } - function test_UpdateRateLimitTokens_AddsAndRemoves() public { + function test_UpdateRateLimitTokens_AddsAndRemoves_Success() public { MultiAggregateRateLimiter.RateLimitTokenArgs[] memory adds = new MultiAggregateRateLimiter.RateLimitTokenArgs[](2); adds[0] = MultiAggregateRateLimiter.RateLimitTokenArgs({ localTokenArgs: MultiAggregateRateLimiter.LocalRateLimitToken({ @@ -150,7 +150,7 @@ contract MultiAggregateRateLimiter_updateRateLimitTokens is MultiAggregateRateLi assertEq(adds[1].localTokenArgs.localToken, localTokens[0]); } - function test_UpdateRateLimitTokens_RemoveNonExistentToken() public { + function test_UpdateRateLimitTokens_RemoveNonExistentToken_Success() public { MultiAggregateRateLimiter.RateLimitTokenArgs[] memory adds = new MultiAggregateRateLimiter.RateLimitTokenArgs[](0); MultiAggregateRateLimiter.LocalRateLimitToken[] memory removes = @@ -175,7 +175,7 @@ contract MultiAggregateRateLimiter_updateRateLimitTokens is MultiAggregateRateLi // Reverts - function test_RevertWhen_ZeroSourceToken() public { + function test_ZeroSourceToken_Revert() public { MultiAggregateRateLimiter.RateLimitTokenArgs[] memory adds = new MultiAggregateRateLimiter.RateLimitTokenArgs[](1); adds[0] = MultiAggregateRateLimiter.RateLimitTokenArgs({ localTokenArgs: MultiAggregateRateLimiter.LocalRateLimitToken({ @@ -189,7 +189,7 @@ contract MultiAggregateRateLimiter_updateRateLimitTokens is MultiAggregateRateLi s_rateLimiter.updateRateLimitTokens(new MultiAggregateRateLimiter.LocalRateLimitToken[](0), adds); } - function test_RevertWhen_ZeroDestToken() public { + function test_ZeroDestToken_Revert() public { MultiAggregateRateLimiter.RateLimitTokenArgs[] memory adds = new MultiAggregateRateLimiter.RateLimitTokenArgs[](1); adds[0] = MultiAggregateRateLimiter.RateLimitTokenArgs({ localTokenArgs: MultiAggregateRateLimiter.LocalRateLimitToken({ @@ -203,7 +203,7 @@ contract MultiAggregateRateLimiter_updateRateLimitTokens is MultiAggregateRateLi s_rateLimiter.updateRateLimitTokens(new MultiAggregateRateLimiter.LocalRateLimitToken[](0), adds); } - function test_RevertWhen_ZeroDestToken_AbiEncoded() public { + function test_ZeroDestToken_AbiEncoded_Revert() public { MultiAggregateRateLimiter.RateLimitTokenArgs[] memory adds = new MultiAggregateRateLimiter.RateLimitTokenArgs[](1); adds[0] = MultiAggregateRateLimiter.RateLimitTokenArgs({ localTokenArgs: MultiAggregateRateLimiter.LocalRateLimitToken({ @@ -217,7 +217,7 @@ contract MultiAggregateRateLimiter_updateRateLimitTokens is MultiAggregateRateLi s_rateLimiter.updateRateLimitTokens(new MultiAggregateRateLimiter.LocalRateLimitToken[](0), adds); } - function test_RevertWhen_NonOwner() public { + function test_NonOwner_Revert() public { MultiAggregateRateLimiter.RateLimitTokenArgs[] memory adds = new MultiAggregateRateLimiter.RateLimitTokenArgs[](4); vm.startPrank(STRANGER); diff --git a/contracts/src/v0.8/ccip/test/rmn/ArmProxy/ARMProxyTestSetup.t.sol b/contracts/src/v0.8/ccip/test/rmn/ArmProxy/ARMProxyTestSetup.t.sol index 1b3c49cf8a6..6a98d726d63 100644 --- a/contracts/src/v0.8/ccip/test/rmn/ArmProxy/ARMProxyTestSetup.t.sol +++ b/contracts/src/v0.8/ccip/test/rmn/ArmProxy/ARMProxyTestSetup.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import {ARMProxy} from "../../../rmn/ARMProxy.sol"; import {Test} from "forge-std/Test.sol"; diff --git a/contracts/src/v0.8/ccip/test/rmn/ArmProxy/ArmPorxy.setARM.t.sol b/contracts/src/v0.8/ccip/test/rmn/ArmProxy/ArmPorxy.setARM.t.sol index 33421ef30ad..88e613c06da 100644 --- a/contracts/src/v0.8/ccip/test/rmn/ArmProxy/ArmPorxy.setARM.t.sol +++ b/contracts/src/v0.8/ccip/test/rmn/ArmProxy/ArmPorxy.setARM.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import {ARMProxy} from "../../../rmn/ARMProxy.sol"; diff --git a/contracts/src/v0.8/ccip/test/rmn/ArmProxy/ArmProxy.constructor.t.sol b/contracts/src/v0.8/ccip/test/rmn/ArmProxy/ArmProxy.constructor.t.sol index a3848bbfdbc..778a9d4086c 100644 --- a/contracts/src/v0.8/ccip/test/rmn/ArmProxy/ArmProxy.constructor.t.sol +++ b/contracts/src/v0.8/ccip/test/rmn/ArmProxy/ArmProxy.constructor.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import {ARMProxy} from "../../../rmn/ARMProxy.sol"; import {ARMProxyTestSetup} from "./ARMProxyTestSetup.t.sol"; diff --git a/contracts/src/v0.8/ccip/test/rmn/ArmProxy/ArmProxy.isCursed.t.sol b/contracts/src/v0.8/ccip/test/rmn/ArmProxy/ArmProxy.isCursed.t.sol index 83a087f34f2..fdc6fce0cf4 100644 --- a/contracts/src/v0.8/ccip/test/rmn/ArmProxy/ArmProxy.isCursed.t.sol +++ b/contracts/src/v0.8/ccip/test/rmn/ArmProxy/ArmProxy.isCursed.t.sol @@ -1,45 +1,42 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import {IRMN} from "../../../interfaces/IRMN.sol"; import {ARMProxy} from "../../../rmn/ARMProxy.sol"; -import {GLOBAL_CURSE_SUBJECT, RMNRemote} from "../../../rmn/RMNRemote.sol"; +import {MockRMN} from "../../mocks/MockRMN.sol"; + import {ARMProxyTestSetup} from "./ARMProxyTestSetup.t.sol"; contract ARMProxy_isCursed is ARMProxyTestSetup { - RMNRemote internal s_mockRMNRemote; + MockRMN internal s_mockRMN; function setUp() public virtual override { super.setUp(); - s_mockRMNRemote = new RMNRemote(1, IRMN(address(0))); - s_armProxy = new ARMProxy(address(s_mockRMNRemote)); + s_mockRMN = new MockRMN(); + s_armProxy = new ARMProxy(address(s_mockRMN)); } - function test_IsCursed_GlobalCurseSubject() public { + function test_IsCursed_Success() public { + s_armProxy.setARM(address(s_mockRMN)); assertFalse(IRMN(address(s_armProxy)).isCursed()); - - s_mockRMNRemote.curse(GLOBAL_CURSE_SUBJECT); - vm.assertTrue(IRMN(address(s_armProxy)).isCursed()); + s_mockRMN.setGlobalCursed(true); + assertTrue(IRMN(address(s_armProxy)).isCursed()); } - error CustomError(bytes err); - - function test_isCursed_RevertWhen_isCursedReasonForwarded() public { + function test_isCursed_RevertReasonForwarded_Revert() public { bytes memory err = bytes("revert"); - vm.mockCallRevert( - address(s_mockRMNRemote), abi.encodeWithSignature("isCursed()"), abi.encodeWithSelector(CustomError.selector, err) - ); - - s_armProxy.setARM(address(s_mockRMNRemote)); - vm.expectRevert(abi.encodeWithSelector(CustomError.selector, err)); + s_mockRMN.setIsCursedRevert(err); + s_armProxy.setARM(address(s_mockRMN)); + vm.expectRevert(abi.encodeWithSelector(MockRMN.CustomError.selector, err)); IRMN(address(s_armProxy)).isCursed(); } - function test_RevertWhen_call_ARMCallEmptyContract() public { + function test_call_ARMCallEmptyContract_Revert() public { s_armProxy.setARM(EMPTY_ADDRESS); // No code at address 1, should revert. vm.expectRevert(); - (bool success,) = address(s_armProxy).call(new bytes(0)); + bytes memory b = new bytes(0); + (bool success,) = address(s_armProxy).call(b); success; } } diff --git a/contracts/src/v0.8/ccip/test/rmn/RMNHome/RMNHome.getConfigDigests.t.sol b/contracts/src/v0.8/ccip/test/rmn/RMNHome/RMNHome.getConfigDigests.t.sol index f17a7d27311..b339bb183e7 100644 --- a/contracts/src/v0.8/ccip/test/rmn/RMNHome/RMNHome.getConfigDigests.t.sol +++ b/contracts/src/v0.8/ccip/test/rmn/RMNHome/RMNHome.getConfigDigests.t.sol @@ -1,10 +1,10 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import {RMNHomeTestSetup} from "./RMNHomeTestSetup.t.sol"; contract RMNHome_getConfigDigests is RMNHomeTestSetup { - function test_getConfigDigests() public { + function test_getConfigDigests_success() public { (bytes32 activeDigest, bytes32 candidateDigest) = s_rmnHome.getConfigDigests(); assertEq(activeDigest, ZERO_DIGEST); assertEq(candidateDigest, ZERO_DIGEST); diff --git a/contracts/src/v0.8/ccip/test/rmn/RMNHome/RMNHome.promoteCandidateAndRevokeActive.t.sol b/contracts/src/v0.8/ccip/test/rmn/RMNHome/RMNHome.promoteCandidateAndRevokeActive.t.sol index f45d63ffeb0..6d99ed1cfaa 100644 --- a/contracts/src/v0.8/ccip/test/rmn/RMNHome/RMNHome.promoteCandidateAndRevokeActive.t.sol +++ b/contracts/src/v0.8/ccip/test/rmn/RMNHome/RMNHome.promoteCandidateAndRevokeActive.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import {Ownable2Step} from "../../../../shared/access/Ownable2Step.sol"; import {RMNHome} from "../../../rmn/RMNHome.sol"; @@ -7,7 +7,7 @@ import {RMNHome} from "../../../rmn/RMNHome.sol"; import {RMNHomeTestSetup} from "./RMNHomeTestSetup.t.sol"; contract RMNHome_promoteCandidateAndRevokeActive is RMNHomeTestSetup { - function test_promoteCandidateAndRevokeActive() public { + function test_promoteCandidateAndRevokeActive_success() public { Config memory config = _getBaseConfig(); bytes32 firstConfigToPromote = s_rmnHome.setCandidate(config.staticConfig, config.dynamicConfig, ZERO_DIGEST); @@ -43,12 +43,12 @@ contract RMNHome_promoteCandidateAndRevokeActive is RMNHomeTestSetup { assertEq(candidateConfig.configDigest, ZERO_DIGEST); } - function test_RevertWhen_promoteCandidateAndRevokeActive_NoOpStateTransitionNotAllowed() public { + function test_promoteCandidateAndRevokeActive_NoOpStateTransitionNotAllowed_reverts() public { vm.expectRevert(RMNHome.NoOpStateTransitionNotAllowed.selector); s_rmnHome.promoteCandidateAndRevokeActive(ZERO_DIGEST, ZERO_DIGEST); } - function test_RevertWhen_promoteCandidateAndRevokeActive_ConfigDigestMismatch() public { + function test_promoteCandidateAndRevokeActive_ConfigDigestMismatch_reverts() public { (bytes32 priorActiveDigest, bytes32 priorCandidateDigest) = s_rmnHome.getConfigDigests(); bytes32 wrongActiveDigest = keccak256("wrongActiveDigest"); bytes32 wrongCandidateDigest = keccak256("wrongCandidateDigest"); @@ -63,7 +63,7 @@ contract RMNHome_promoteCandidateAndRevokeActive is RMNHomeTestSetup { s_rmnHome.promoteCandidateAndRevokeActive(priorCandidateDigest, wrongActiveDigest); } - function test_RevertWhen_promoteCandidateAndRevokeActive_OnlyOwner() public { + function test_promoteCandidateAndRevokeActive_OnlyOwner_reverts() public { vm.startPrank(address(0)); vm.expectRevert(Ownable2Step.OnlyCallableByOwner.selector); diff --git a/contracts/src/v0.8/ccip/test/rmn/RMNHome/RMNHome.revokeCandidate.t.sol b/contracts/src/v0.8/ccip/test/rmn/RMNHome/RMNHome.revokeCandidate.t.sol index 3bb925fd105..a486bd193ff 100644 --- a/contracts/src/v0.8/ccip/test/rmn/RMNHome/RMNHome.revokeCandidate.t.sol +++ b/contracts/src/v0.8/ccip/test/rmn/RMNHome/RMNHome.revokeCandidate.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import {Ownable2Step} from "../../../../shared/access/Ownable2Step.sol"; import {RMNHome} from "../../../rmn/RMNHome.sol"; @@ -17,7 +17,7 @@ contract RMNHome_revokeCandidate is RMNHomeTestSetup { s_rmnHome.setCandidate(config.staticConfig, config.dynamicConfig, ZERO_DIGEST); } - function test_revokeCandidate() public { + function test_revokeCandidate_success() public { (bytes32 priorActiveDigest, bytes32 priorCandidateDigest) = s_rmnHome.getConfigDigests(); vm.expectEmit(); @@ -39,7 +39,7 @@ contract RMNHome_revokeCandidate is RMNHomeTestSetup { assertTrue(candidateDigest != priorCandidateDigest); } - function test_RevertWhen_revokeCandidate_ConfigDigestMismatch() public { + function test_revokeCandidate_ConfigDigestMismatch_reverts() public { (, bytes32 priorCandidateDigest) = s_rmnHome.getConfigDigests(); bytes32 wrongDigest = keccak256("wrong_digest"); @@ -47,12 +47,12 @@ contract RMNHome_revokeCandidate is RMNHomeTestSetup { s_rmnHome.revokeCandidate(wrongDigest); } - function test_RevertWhen_revokeCandidate_RevokingZeroDigestNotAllowed() public { + function test_revokeCandidate_RevokingZeroDigestNotAllowed_reverts() public { vm.expectRevert(RMNHome.RevokingZeroDigestNotAllowed.selector); s_rmnHome.revokeCandidate(ZERO_DIGEST); } - function test_RevertWhen_revokeCandidate_OnlyOwner() public { + function test_revokeCandidate_OnlyOwner_reverts() public { vm.startPrank(address(0)); vm.expectRevert(Ownable2Step.OnlyCallableByOwner.selector); diff --git a/contracts/src/v0.8/ccip/test/rmn/RMNHome/RMNHome.setCandidate.t.sol b/contracts/src/v0.8/ccip/test/rmn/RMNHome/RMNHome.setCandidate.t.sol index 502f1b5a0b8..6fae7a90552 100644 --- a/contracts/src/v0.8/ccip/test/rmn/RMNHome/RMNHome.setCandidate.t.sol +++ b/contracts/src/v0.8/ccip/test/rmn/RMNHome/RMNHome.setCandidate.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import {Ownable2Step} from "../../../../shared/access/Ownable2Step.sol"; import {RMNHome} from "../../../rmn/RMNHome.sol"; @@ -7,7 +7,7 @@ import {RMNHome} from "../../../rmn/RMNHome.sol"; import {RMNHomeTestSetup} from "./RMNHomeTestSetup.t.sol"; contract RMNHome_setCandidate is RMNHomeTestSetup { - function test_setCandidate() public { + function test_setCandidate_success() public { Config memory config = _getBaseConfig(); RMNHome.VersionedConfig memory versionedConfig = RMNHome.VersionedConfig({ version: 1, @@ -49,7 +49,7 @@ contract RMNHome_setCandidate is RMNHomeTestSetup { assertEq(storedStaticConfig.offchainConfig, versionedConfig.staticConfig.offchainConfig); } - function test_RevertWhen_setCandidate_ConfigDigestMismatch() public { + function test_setCandidate_ConfigDigestMismatch_reverts() public { Config memory config = _getBaseConfig(); bytes32 digest = s_rmnHome.setCandidate(config.staticConfig, config.dynamicConfig, ZERO_DIGEST); @@ -63,7 +63,7 @@ contract RMNHome_setCandidate is RMNHomeTestSetup { s_rmnHome.setCandidate(config.staticConfig, config.dynamicConfig, digest); } - function test_RevertWhen_setCandidate_OnlyOwner() public { + function test_setCandidate_OnlyOwner_reverts() public { Config memory config = _getBaseConfig(); vm.startPrank(address(0)); diff --git a/contracts/src/v0.8/ccip/test/rmn/RMNHome/RMNHome.setDynamicConfig.t.sol b/contracts/src/v0.8/ccip/test/rmn/RMNHome/RMNHome.setDynamicConfig.t.sol index a0c1f376390..048a6ef226e 100644 --- a/contracts/src/v0.8/ccip/test/rmn/RMNHome/RMNHome.setDynamicConfig.t.sol +++ b/contracts/src/v0.8/ccip/test/rmn/RMNHome/RMNHome.setDynamicConfig.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import {Ownable2Step} from "../../../../shared/access/Ownable2Step.sol"; import {RMNHome} from "../../../rmn/RMNHome.sol"; @@ -12,7 +12,7 @@ contract RMNHome_setDynamicConfig is RMNHomeTestSetup { s_rmnHome.setCandidate(config.staticConfig, config.dynamicConfig, ZERO_DIGEST); } - function test_setDynamicConfig() public { + function test_setDynamicConfig_success() public { (bytes32 priorActiveDigest,) = s_rmnHome.getConfigDigests(); Config memory config = _getBaseConfig(); @@ -36,7 +36,7 @@ contract RMNHome_setDynamicConfig is RMNHomeTestSetup { } // Asserts the validation function is being called - function test_RevertWhen_setDynamicConfig_MinObserversTooHigh() public { + function test_setDynamicConfig_MinObserversTooHigh_reverts() public { Config memory config = _getBaseConfig(); config.dynamicConfig.sourceChains[0].f++; @@ -44,7 +44,7 @@ contract RMNHome_setDynamicConfig is RMNHomeTestSetup { s_rmnHome.setDynamicConfig(config.dynamicConfig, ZERO_DIGEST); } - function test_RevertWhen_setDynamicConfig_DigestNotFound() public { + function test_setDynamicConfig_DigestNotFound_reverts() public { // Zero always reverts vm.expectRevert(abi.encodeWithSelector(RMNHome.DigestNotFound.selector, ZERO_DIGEST)); s_rmnHome.setDynamicConfig(_getBaseConfig().dynamicConfig, ZERO_DIGEST); @@ -55,7 +55,7 @@ contract RMNHome_setDynamicConfig is RMNHomeTestSetup { s_rmnHome.setDynamicConfig(_getBaseConfig().dynamicConfig, nonExistentDigest); } - function test_RevertWhen_setDynamicConfig_OnlyOwner() public { + function test_setDynamicConfig_OnlyOwner_reverts() public { Config memory config = _getBaseConfig(); vm.startPrank(address(0)); diff --git a/contracts/src/v0.8/ccip/test/rmn/RMNHome/RMNHome.validateStaticAndDynamicConfig.t.sol b/contracts/src/v0.8/ccip/test/rmn/RMNHome/RMNHome.validateStaticAndDynamicConfig.t.sol index c719ae4f73b..2aa7b1a5100 100644 --- a/contracts/src/v0.8/ccip/test/rmn/RMNHome/RMNHome.validateStaticAndDynamicConfig.t.sol +++ b/contracts/src/v0.8/ccip/test/rmn/RMNHome/RMNHome.validateStaticAndDynamicConfig.t.sol @@ -1,12 +1,12 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import {RMNHome} from "../../../rmn/RMNHome.sol"; import {RMNHomeTestSetup} from "./RMNHomeTestSetup.t.sol"; contract RMNHome_validateStaticAndDynamicConfig is RMNHomeTestSetup { - function test_RevertWhen_validateStaticAndDynamicConfig_OutOfBoundsNodesLength() public { + function test_validateStaticAndDynamicConfig_OutOfBoundsNodesLength_reverts() public { Config memory config = _getBaseConfig(); config.staticConfig.nodes = new RMNHome.Node[](257); @@ -14,7 +14,7 @@ contract RMNHome_validateStaticAndDynamicConfig is RMNHomeTestSetup { s_rmnHome.setCandidate(config.staticConfig, config.dynamicConfig, ZERO_DIGEST); } - function test_RevertWhen_validateStaticAndDynamicConfig_DuplicatePeerId() public { + function test_validateStaticAndDynamicConfig_DuplicatePeerId_reverts() public { Config memory config = _getBaseConfig(); config.staticConfig.nodes[1].peerId = config.staticConfig.nodes[0].peerId; @@ -22,7 +22,7 @@ contract RMNHome_validateStaticAndDynamicConfig is RMNHomeTestSetup { s_rmnHome.setCandidate(config.staticConfig, config.dynamicConfig, ZERO_DIGEST); } - function test_RevertWhen_validateStaticAndDynamicConfig_DuplicateOffchainPublicKey() public { + function test_validateStaticAndDynamicConfig_DuplicateOffchainPublicKey_reverts() public { Config memory config = _getBaseConfig(); config.staticConfig.nodes[1].offchainPublicKey = config.staticConfig.nodes[0].offchainPublicKey; @@ -30,7 +30,7 @@ contract RMNHome_validateStaticAndDynamicConfig is RMNHomeTestSetup { s_rmnHome.setCandidate(config.staticConfig, config.dynamicConfig, ZERO_DIGEST); } - function test_RevertWhen_validateStaticAndDynamicConfig_DuplicateSourceChain() public { + function test_validateStaticAndDynamicConfig_DuplicateSourceChain_reverts() public { Config memory config = _getBaseConfig(); config.dynamicConfig.sourceChains[1].chainSelector = config.dynamicConfig.sourceChains[0].chainSelector; @@ -38,7 +38,7 @@ contract RMNHome_validateStaticAndDynamicConfig is RMNHomeTestSetup { s_rmnHome.setCandidate(config.staticConfig, config.dynamicConfig, ZERO_DIGEST); } - function test_RevertWhen_validateStaticAndDynamicConfig_OutOfBoundsObserverNodeIndex() public { + function test_validateStaticAndDynamicConfig_OutOfBoundsObserverNodeIndex_reverts() public { Config memory config = _getBaseConfig(); config.dynamicConfig.sourceChains[0].observerNodesBitmap = 1 << config.staticConfig.nodes.length; @@ -46,7 +46,7 @@ contract RMNHome_validateStaticAndDynamicConfig is RMNHomeTestSetup { s_rmnHome.setCandidate(config.staticConfig, config.dynamicConfig, ZERO_DIGEST); } - function test_RevertWhen_validateStaticAndDynamicConfig_NotEnoughObservers() public { + function test_validateStaticAndDynamicConfig_NotEnoughObservers_reverts() public { Config memory config = _getBaseConfig(); config.dynamicConfig.sourceChains[0].f++; diff --git a/contracts/src/v0.8/ccip/test/rmn/RMNHome/RMNHomeTestSetup.t.sol b/contracts/src/v0.8/ccip/test/rmn/RMNHome/RMNHomeTestSetup.t.sol index 1d7f5a0571d..6bb76c29ba7 100644 --- a/contracts/src/v0.8/ccip/test/rmn/RMNHome/RMNHomeTestSetup.t.sol +++ b/contracts/src/v0.8/ccip/test/rmn/RMNHome/RMNHomeTestSetup.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import {RMNHome} from "../../../rmn/RMNHome.sol"; import {Test} from "forge-std/Test.sol"; diff --git a/contracts/src/v0.8/ccip/test/rmn/RMNRemote/RMNRemote.constructor.t.sol b/contracts/src/v0.8/ccip/test/rmn/RMNRemote/RMNRemote.constructor.t.sol index 8c2b0157800..1cc9d9addb7 100644 --- a/contracts/src/v0.8/ccip/test/rmn/RMNRemote/RMNRemote.constructor.t.sol +++ b/contracts/src/v0.8/ccip/test/rmn/RMNRemote/RMNRemote.constructor.t.sol @@ -1,10 +1,16 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; +import {RMNRemote} from "../../../rmn/RMNRemote.sol"; import {RMNRemoteSetup} from "./RMNRemoteSetup.t.sol"; contract RMNRemote_constructor is RMNRemoteSetup { - function test_constructor() public view { + function test_constructor_success() public view { assertEq(s_rmnRemote.getLocalChainSelector(), 1); } + + function test_constructor_zeroChainSelector_reverts() public { + vm.expectRevert(RMNRemote.ZeroValueNotAllowed.selector); + new RMNRemote(0); + } } diff --git a/contracts/src/v0.8/ccip/test/rmn/RMNRemote/RMNRemote.curse.t.sol b/contracts/src/v0.8/ccip/test/rmn/RMNRemote/RMNRemote.curse.t.sol index 4c3d6bd3fb1..e1af2ab4e6b 100644 --- a/contracts/src/v0.8/ccip/test/rmn/RMNRemote/RMNRemote.curse.t.sol +++ b/contracts/src/v0.8/ccip/test/rmn/RMNRemote/RMNRemote.curse.t.sol @@ -1,12 +1,12 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import {Ownable2Step} from "../../../../shared/access/Ownable2Step.sol"; import {RMNRemote} from "../../../rmn/RMNRemote.sol"; import {RMNRemoteSetup} from "./RMNRemoteSetup.t.sol"; contract RMNRemote_curse is RMNRemoteSetup { - function test_curse() public { + function test_curse_success() public { vm.expectEmit(); emit RMNRemote.Cursed(s_curseSubjects); @@ -19,14 +19,14 @@ contract RMNRemote_curse is RMNRemoteSetup { assertFalse(s_rmnRemote.isCursed(bytes16(keccak256("subject 3")))); } - function test_RevertWhen_curse_AlreadyCursed_duplicateSubject() public { + function test_curse_AlreadyCursed_duplicateSubject_reverts() public { s_curseSubjects.push(CURSE_SUBJ_1); vm.expectRevert(abi.encodeWithSelector(RMNRemote.AlreadyCursed.selector, CURSE_SUBJ_1)); s_rmnRemote.curse(s_curseSubjects); } - function test_RevertWhen_curse_calledByNonOwner() public { + function test_curse_calledByNonOwner_reverts() public { vm.expectRevert(Ownable2Step.OnlyCallableByOwner.selector); vm.stopPrank(); vm.prank(STRANGER); diff --git a/contracts/src/v0.8/ccip/test/rmn/RMNRemote/RMNRemote.globalAndLegacyCurses.t.sol b/contracts/src/v0.8/ccip/test/rmn/RMNRemote/RMNRemote.globalAndLegacyCurses.t.sol new file mode 100644 index 00000000000..da6677678fe --- /dev/null +++ b/contracts/src/v0.8/ccip/test/rmn/RMNRemote/RMNRemote.globalAndLegacyCurses.t.sol @@ -0,0 +1,29 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.24; + +import {GLOBAL_CURSE_SUBJECT, LEGACY_CURSE_SUBJECT} from "../../../rmn/RMNRemote.sol"; +import {RMNRemoteSetup} from "./RMNRemoteSetup.t.sol"; + +contract RMNRemote_global_and_legacy_curses is RMNRemoteSetup { + function test_global_and_legacy_curses_success() public { + bytes16 randSubject = bytes16(keccak256("random subject")); + assertFalse(s_rmnRemote.isCursed()); + assertFalse(s_rmnRemote.isCursed(randSubject)); + + s_rmnRemote.curse(GLOBAL_CURSE_SUBJECT); + assertTrue(s_rmnRemote.isCursed()); + assertTrue(s_rmnRemote.isCursed(randSubject)); + + s_rmnRemote.uncurse(GLOBAL_CURSE_SUBJECT); + assertFalse(s_rmnRemote.isCursed()); + assertFalse(s_rmnRemote.isCursed(randSubject)); + + s_rmnRemote.curse(LEGACY_CURSE_SUBJECT); + assertTrue(s_rmnRemote.isCursed()); + assertFalse(s_rmnRemote.isCursed(randSubject)); // legacy curse doesn't affect specific subjects + + s_rmnRemote.uncurse(LEGACY_CURSE_SUBJECT); + assertFalse(s_rmnRemote.isCursed()); + assertFalse(s_rmnRemote.isCursed(randSubject)); + } +} diff --git a/contracts/src/v0.8/ccip/test/rmn/RMNRemote/RMNRemote.globalCurses.t.sol b/contracts/src/v0.8/ccip/test/rmn/RMNRemote/RMNRemote.globalCurses.t.sol deleted file mode 100644 index 3732095ea9d..00000000000 --- a/contracts/src/v0.8/ccip/test/rmn/RMNRemote/RMNRemote.globalCurses.t.sol +++ /dev/null @@ -1,21 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; - -import {GLOBAL_CURSE_SUBJECT} from "../../../rmn/RMNRemote.sol"; -import {RMNRemoteSetup} from "./RMNRemoteSetup.t.sol"; - -contract RMNRemote_global_curses is RMNRemoteSetup { - function test_isCursed_globalCurseSubject() public { - bytes16 randSubject = bytes16(keccak256("random subject")); - assertFalse(s_rmnRemote.isCursed()); - assertFalse(s_rmnRemote.isCursed(randSubject)); - - s_rmnRemote.curse(GLOBAL_CURSE_SUBJECT); - assertTrue(s_rmnRemote.isCursed()); - assertTrue(s_rmnRemote.isCursed(randSubject)); - - s_rmnRemote.uncurse(GLOBAL_CURSE_SUBJECT); - assertFalse(s_rmnRemote.isCursed()); - assertFalse(s_rmnRemote.isCursed(randSubject)); - } -} diff --git a/contracts/src/v0.8/ccip/test/rmn/RMNRemote/RMNRemote.isBlessed.t.sol b/contracts/src/v0.8/ccip/test/rmn/RMNRemote/RMNRemote.isBlessed.t.sol deleted file mode 100644 index d013f9edf0b..00000000000 --- a/contracts/src/v0.8/ccip/test/rmn/RMNRemote/RMNRemote.isBlessed.t.sol +++ /dev/null @@ -1,34 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; - -import {IRMN} from "../../../interfaces/IRMN.sol"; - -import {RMNRemote} from "../../../rmn/RMNRemote.sol"; -import {RMNRemoteSetup} from "./RMNRemoteSetup.t.sol"; - -contract RMNRemote_isBlessed is RMNRemoteSetup { - function test_isBlessed() public { - IRMN.TaggedRoot memory taggedRoot = IRMN.TaggedRoot({root: keccak256("root"), commitStore: makeAddr("commitStore")}); - - vm.mockCall( - address(s_legacyRMN), abi.encodeWithSelector(s_legacyRMN.isBlessed.selector, taggedRoot), abi.encode(true) - ); - - assertTrue(s_rmnRemote.isBlessed(taggedRoot)); - - vm.mockCall( - address(s_legacyRMN), abi.encodeWithSelector(s_legacyRMN.isBlessed.selector, taggedRoot), abi.encode(false) - ); - - assertFalse(s_rmnRemote.isBlessed(taggedRoot)); - } - - function test_RevertWhen_isBlessedWhen_IsBlessedNotAvailable() public { - IRMN.TaggedRoot memory taggedRoot = IRMN.TaggedRoot({root: keccak256("root"), commitStore: makeAddr("commitStore")}); - - s_rmnRemote = new RMNRemote(100, IRMN(address(0))); - - vm.expectRevert(RMNRemote.IsBlessedNotAvailable.selector); - s_rmnRemote.isBlessed(taggedRoot); - } -} diff --git a/contracts/src/v0.8/ccip/test/rmn/RMNRemote/RMNRemote.setConfig.t.sol b/contracts/src/v0.8/ccip/test/rmn/RMNRemote/RMNRemote.setConfig.t.sol index 80bbddbfc03..0805871955d 100644 --- a/contracts/src/v0.8/ccip/test/rmn/RMNRemote/RMNRemote.setConfig.t.sol +++ b/contracts/src/v0.8/ccip/test/rmn/RMNRemote/RMNRemote.setConfig.t.sol @@ -1,11 +1,11 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import {RMNRemote} from "../../../rmn/RMNRemote.sol"; import {RMNRemoteSetup} from "./RMNRemoteSetup.t.sol"; contract RMNRemote_setConfig is RMNRemoteSetup { - function test_RevertWhen_setConfig_ZeroValueNotAllowed() public { + function test_setConfig_ZeroValueNotAllowed_revert() public { RMNRemote.Config memory config = RMNRemote.Config({rmnHomeContractConfigDigest: bytes32(0), signers: s_signers, f: 1}); @@ -14,7 +14,7 @@ contract RMNRemote_setConfig is RMNRemoteSetup { s_rmnRemote.setConfig(config); } - function test_setConfig_addSigner_removeSigner() public { + function test_setConfig_addSigner_removeSigner_success() public { uint32 currentConfigVersion = 0; uint256 numSigners = s_signers.length; RMNRemote.Config memory config = @@ -56,7 +56,7 @@ contract RMNRemote_setConfig is RMNRemoteSetup { assertEq(version, currentConfigVersion); } - function test_RevertWhen_setConfig_invalidSignerOrder() public { + function test_setConfig_invalidSignerOrder_reverts() public { s_signers.push(RMNRemote.Signer({onchainPublicKey: address(4), nodeIndex: 0})); RMNRemote.Config memory config = RMNRemote.Config({rmnHomeContractConfigDigest: _randomBytes32(), signers: s_signers, f: 1}); @@ -65,7 +65,7 @@ contract RMNRemote_setConfig is RMNRemoteSetup { s_rmnRemote.setConfig(config); } - function test_RevertWhen_setConfig_notEnoughSigners() public { + function test_setConfig_notEnoughSigners_reverts() public { RMNRemote.Config memory config = RMNRemote.Config({ rmnHomeContractConfigDigest: _randomBytes32(), signers: s_signers, @@ -76,7 +76,7 @@ contract RMNRemote_setConfig is RMNRemoteSetup { s_rmnRemote.setConfig(config); } - function test_RevertWhen_setConfig_duplicateOnChainPublicKey() public { + function test_setConfig_duplicateOnChainPublicKey_reverts() public { s_signers.push(RMNRemote.Signer({onchainPublicKey: s_signerWallets[0].addr, nodeIndex: uint64(s_signers.length)})); RMNRemote.Config memory config = RMNRemote.Config({rmnHomeContractConfigDigest: _randomBytes32(), signers: s_signers, f: 1}); diff --git a/contracts/src/v0.8/ccip/test/rmn/RMNRemote/RMNRemote.uncurse.t.sol b/contracts/src/v0.8/ccip/test/rmn/RMNRemote/RMNRemote.uncurse.t.sol index 5f537f3d7fc..ad784a8cb30 100644 --- a/contracts/src/v0.8/ccip/test/rmn/RMNRemote/RMNRemote.uncurse.t.sol +++ b/contracts/src/v0.8/ccip/test/rmn/RMNRemote/RMNRemote.uncurse.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import {Ownable2Step} from "../../../../shared/access/Ownable2Step.sol"; import {RMNRemote} from "../../../rmn/RMNRemote.sol"; @@ -11,7 +11,7 @@ contract RMNRemote_uncurse is RMNRemoteSetup { s_rmnRemote.curse(s_curseSubjects); } - function test_uncurse() public { + function test_uncurse_success() public { vm.expectEmit(); emit RMNRemote.Uncursed(s_curseSubjects); @@ -22,14 +22,14 @@ contract RMNRemote_uncurse is RMNRemoteSetup { assertFalse(s_rmnRemote.isCursed(CURSE_SUBJ_2)); } - function test_RevertWhen_uncurse_NotCursed_duplicatedUncurseSubject() public { + function test_uncurse_NotCursed_duplicatedUncurseSubject_reverts() public { s_curseSubjects.push(CURSE_SUBJ_1); vm.expectRevert(abi.encodeWithSelector(RMNRemote.NotCursed.selector, CURSE_SUBJ_1)); s_rmnRemote.uncurse(s_curseSubjects); } - function test_RevertWhen_uncurse_calledByNonOwner() public { + function test_uncurse_calledByNonOwner_reverts() public { vm.expectRevert(Ownable2Step.OnlyCallableByOwner.selector); vm.stopPrank(); vm.prank(STRANGER); diff --git a/contracts/src/v0.8/ccip/test/rmn/RMNRemote/RMNRemote.verifywithConfigNotSet.t.sol b/contracts/src/v0.8/ccip/test/rmn/RMNRemote/RMNRemote.verifywithConfigNotSet.t.sol index f48d87ef620..bba4e8e6a0d 100644 --- a/contracts/src/v0.8/ccip/test/rmn/RMNRemote/RMNRemote.verifywithConfigNotSet.t.sol +++ b/contracts/src/v0.8/ccip/test/rmn/RMNRemote/RMNRemote.verifywithConfigNotSet.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import {IRMNRemote} from "../../../interfaces/IRMNRemote.sol"; @@ -8,7 +8,7 @@ import {RMNRemote} from "../../../rmn/RMNRemote.sol"; import {RMNRemoteSetup} from "./RMNRemoteSetup.t.sol"; contract RMNRemote_verify_withConfigNotSet is RMNRemoteSetup { - function test_RevertWhen_verifys() public { + function test_verify_reverts() public { Internal.MerkleRoot[] memory merkleRoots = new Internal.MerkleRoot[](0); IRMNRemote.Signature[] memory signatures = new IRMNRemote.Signature[](0); diff --git a/contracts/src/v0.8/ccip/test/rmn/RMNRemote/RMNRemote.verifywithConfigSet.t.sol b/contracts/src/v0.8/ccip/test/rmn/RMNRemote/RMNRemote.verifywithConfigSet.t.sol index 3884493106d..1ba9de9d039 100644 --- a/contracts/src/v0.8/ccip/test/rmn/RMNRemote/RMNRemote.verifywithConfigSet.t.sol +++ b/contracts/src/v0.8/ccip/test/rmn/RMNRemote/RMNRemote.verifywithConfigSet.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import {IRMNRemote} from "../../../interfaces/IRMNRemote.sol"; import {RMNRemote} from "../../../rmn/RMNRemote.sol"; @@ -8,44 +8,48 @@ import {RMNRemoteSetup} from "./RMNRemoteSetup.t.sol"; contract RMNRemote_verify_withConfigSet is RMNRemoteSetup { function setUp() public override { super.setUp(); - RMNRemote.Config memory config = RMNRemote.Config({rmnHomeContractConfigDigest: _randomBytes32(), signers: s_signers, f: 3}); s_rmnRemote.setConfig(config); _generatePayloadAndSigs(2, 4); } - function test_verify() public view { + function test_verify_success() public view { s_rmnRemote.verify(OFF_RAMP_ADDRESS, s_merkleRoots, s_signatures); } - function test_verify_RevertWhen_InvalidSignature() public { - s_signatures[s_signatures.length - 1].r = 0x0; + function test_verify_InvalidSignature_reverts() public { + IRMNRemote.Signature memory sig = s_signatures[s_signatures.length - 1]; + sig.r = _randomBytes32(); + s_signatures.pop(); + s_signatures.push(sig); vm.expectRevert(RMNRemote.InvalidSignature.selector); - s_rmnRemote.verify(OFF_RAMP_ADDRESS, s_merkleRoots, s_signatures); } - function test_verify_RevertWhen_OutOfOrderSignatures_not_sorted() public { + function test_verify_OutOfOrderSignatures_not_sorted_reverts() public { IRMNRemote.Signature memory sig1 = s_signatures[s_signatures.length - 1]; - IRMNRemote.Signature memory sig2 = s_signatures[s_signatures.length - 2]; - - s_signatures[s_signatures.length - 1] = sig2; - s_signatures[s_signatures.length - 2] = sig1; + s_signatures.pop(); + IRMNRemote.Signature memory sig2 = s_signatures[s_signatures.length - 1]; + s_signatures.pop(); + s_signatures.push(sig1); + s_signatures.push(sig2); vm.expectRevert(RMNRemote.OutOfOrderSignatures.selector); s_rmnRemote.verify(OFF_RAMP_ADDRESS, s_merkleRoots, s_signatures); } - function test_verify_RevertWhen_OutOfOrderSignatures_duplicateSignature() public { - s_signatures[s_signatures.length - 1] = s_signatures[s_signatures.length - 2]; + function test_verify_OutOfOrderSignatures_duplicateSignature_reverts() public { + IRMNRemote.Signature memory sig = s_signatures[s_signatures.length - 2]; + s_signatures.pop(); + s_signatures.push(sig); vm.expectRevert(RMNRemote.OutOfOrderSignatures.selector); s_rmnRemote.verify(OFF_RAMP_ADDRESS, s_merkleRoots, s_signatures); } - function test_verify_RevertWhen_UnexpectedSigner() public { + function test_verify_UnexpectedSigner_reverts() public { _setupSigners(4); // create new signers that aren't configured on RMNRemote _generatePayloadAndSigs(2, 4); @@ -53,7 +57,7 @@ contract RMNRemote_verify_withConfigSet is RMNRemoteSetup { s_rmnRemote.verify(OFF_RAMP_ADDRESS, s_merkleRoots, s_signatures); } - function test_verify_RevertWhen_ThresholdNotMet() public { + function test_verify_ThresholdNotMet_reverts() public { RMNRemote.Config memory config = RMNRemote.Config({rmnHomeContractConfigDigest: _randomBytes32(), signers: s_signers, f: 2}); // 3 = f+1 sigs required s_rmnRemote.setConfig(config); diff --git a/contracts/src/v0.8/ccip/test/rmn/RMNRemote/RMNRemoteSetup.t.sol b/contracts/src/v0.8/ccip/test/rmn/RMNRemote/RMNRemoteSetup.t.sol index 3c3ecd7a62b..b32dcd98a1a 100644 --- a/contracts/src/v0.8/ccip/test/rmn/RMNRemote/RMNRemoteSetup.t.sol +++ b/contracts/src/v0.8/ccip/test/rmn/RMNRemote/RMNRemoteSetup.t.sol @@ -1,9 +1,7 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; -import {IRMN} from "../../../interfaces/IRMN.sol"; import {IRMNRemote} from "../../../interfaces/IRMNRemote.sol"; - import {Internal} from "../../../libraries/Internal.sol"; import {RMNRemote} from "../../../rmn/RMNRemote.sol"; import {BaseTest} from "../../BaseTest.t.sol"; @@ -23,11 +21,9 @@ contract RMNRemoteSetup is BaseTest { bytes16 internal constant CURSE_SUBJ_2 = bytes16(keccak256("subject 2")); bytes16[] internal s_curseSubjects; - IRMN internal s_legacyRMN = IRMN(makeAddr("legacyRMN")); - function setUp() public virtual override { super.setUp(); - s_rmnRemote = new RMNRemote(1, s_legacyRMN); + s_rmnRemote = new RMNRemote(1); OFF_RAMP_ADDRESS = makeAddr("OFF RAMP"); s_curseSubjects = [CURSE_SUBJ_1, CURSE_SUBJ_2]; @@ -49,7 +45,7 @@ contract RMNRemoteSetup is BaseTest { } for (uint256 i = 0; i < numSigners; ++i) { - s_signerWallets.push(vm.createWallet(vm.randomUint())); + s_signerWallets.push(vm.createWallet(_randomNum())); } _sort(s_signerWallets); @@ -84,11 +80,11 @@ contract RMNRemoteSetup is BaseTest { /// @notice generates a random dest lane update function _generateRandomDestLaneUpdate() private returns (Internal.MerkleRoot memory) { - uint64 minSeqNum = uint32(vm.randomUint()); + uint64 minSeqNum = uint32(_randomNum()); uint64 maxSeqNum = minSeqNum + 100; return Internal.MerkleRoot({ - sourceChainSelector: uint64(vm.randomUint()), - onRampAddress: abi.encode(vm.randomAddress()), + sourceChainSelector: uint64(_randomNum()), + onRampAddress: abi.encode(_randomAddress()), minSeqNr: minSeqNum, maxSeqNr: maxSeqNum, merkleRoot: _randomBytes32() @@ -147,9 +143,4 @@ contract RMNRemoteSetup is BaseTest { } } } - - /// @dev returns a pseudo-random bytes32 - function _randomBytes32() internal returns (bytes32) { - return bytes32(vm.randomUint()); - } } diff --git a/contracts/src/v0.8/ccip/test/router/Router/Router.applyRampUpdates.t.sol b/contracts/src/v0.8/ccip/test/router/Router/Router.applyRampUpdates.t.sol index 4284c854466..9b46741f96d 100644 --- a/contracts/src/v0.8/ccip/test/router/Router/Router.applyRampUpdates.t.sol +++ b/contracts/src/v0.8/ccip/test/router/Router/Router.applyRampUpdates.t.sol @@ -1,18 +1,18 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; +import {Router} from "../../../Router.sol"; import {IAny2EVMMessageReceiver} from "../../../interfaces/IAny2EVMMessageReceiver.sol"; import {IRouter} from "../../../interfaces/IRouter.sol"; - -import {Router} from "../../../Router.sol"; import {Client} from "../../../libraries/Client.sol"; -import {BaseTest} from "../../BaseTest.t.sol"; + import {MaybeRevertMessageReceiver} from "../../helpers/receivers/MaybeRevertMessageReceiver.sol"; +import {RouterSetup} from "./RouterSetup.t.sol"; -contract Router_applyRampUpdates is BaseTest { +contract Router_applyRampUpdates is RouterSetup { MaybeRevertMessageReceiver internal s_receiver; - function setUp() public virtual override { + function setUp() public virtual override(RouterSetup) { super.setUp(); s_receiver = new MaybeRevertMessageReceiver(false); } @@ -22,14 +22,7 @@ contract Router_applyRampUpdates is BaseTest { ) internal { vm.startPrank(offRamp.offRamp); - Client.Any2EVMMessage memory message = Client.Any2EVMMessage({ - messageId: bytes32("a"), - sourceChainSelector: offRamp.sourceChainSelector, - sender: bytes("a"), - data: bytes("a"), - destTokenAmounts: new Client.EVMTokenAmount[](0) - }); - + Client.Any2EVMMessage memory message = _generateReceiverMessage(offRamp.sourceChainSelector); vm.expectCall(address(s_receiver), abi.encodeWithSelector(IAny2EVMMessageReceiver.ccipReceive.selector, message)); s_sourceRouter.routeMessage(message, GAS_FOR_CALL_EXACT_CHECK, 100_000, address(s_receiver)); } @@ -41,20 +34,11 @@ contract Router_applyRampUpdates is BaseTest { vm.expectRevert(IRouter.OnlyOffRamp.selector); s_sourceRouter.routeMessage( - Client.Any2EVMMessage({ - messageId: bytes32("a"), - sourceChainSelector: offRamp.sourceChainSelector, - sender: bytes("a"), - data: bytes("a"), - destTokenAmounts: new Client.EVMTokenAmount[](0) - }), - GAS_FOR_CALL_EXACT_CHECK, - 100_000, - address(s_receiver) + _generateReceiverMessage(offRamp.sourceChainSelector), GAS_FOR_CALL_EXACT_CHECK, 100_000, address(s_receiver) ); } - function testFuzz_applyRampUpdates_OffRampUpdates( + function testFuzz_OffRampUpdates( address[20] memory offRampsInput ) public { Router.OffRamp[] memory offRamps = new Router.OffRamp[](20); @@ -88,7 +72,7 @@ contract Router_applyRampUpdates is BaseTest { } } - function test_applyRampUpdates_OffRampUpdatesWithRouting() public { + function test_OffRampUpdatesWithRouting() public { // Explicitly construct chain selectors and ramp addresses so we have ramp uniqueness for the various test scenarios. uint256 numberOfSelectors = 10; uint64[] memory sourceChainSelectors = new uint64[](numberOfSelectors); @@ -235,7 +219,7 @@ contract Router_applyRampUpdates is BaseTest { } } - function testFuzz_applyRampUpdates_OnRampUpdates( + function testFuzz_OnRampUpdates( Router.OnRamp[] memory onRamps ) public { // Test adding onRamps @@ -260,7 +244,7 @@ contract Router_applyRampUpdates is BaseTest { } } - function test_applyRampUpdates_OnRampDisable() public { + function test_OnRampDisable() public { // Add onRamp Router.OnRamp[] memory onRampUpdates = new Router.OnRamp[](1); Router.OffRamp[] memory offRampUpdates = new Router.OffRamp[](0); @@ -283,7 +267,7 @@ contract Router_applyRampUpdates is BaseTest { assertTrue(s_sourceRouter.isChainSupported(DEST_CHAIN_SELECTOR)); } - function test_RevertWhen_applyRampUpdatesWhen_OnlyOwner() public { + function test_OnlyOwner_Revert() public { vm.stopPrank(); vm.expectRevert("Only callable by owner"); Router.OnRamp[] memory onRampUpdates = new Router.OnRamp[](0); @@ -291,7 +275,7 @@ contract Router_applyRampUpdates is BaseTest { s_sourceRouter.applyRampUpdates(onRampUpdates, offRampUpdates, offRampUpdates); } - function test_RevertWhen_applyRampUpdatesWhen_OffRampMismatch() public { + function test_OffRampMismatch_Revert() public { address offRamp = address(uint160(2)); Router.OnRamp[] memory onRampUpdates = new Router.OnRamp[](0); diff --git a/contracts/src/v0.8/ccip/test/router/Router/Router.ccipSend.t.sol b/contracts/src/v0.8/ccip/test/router/Router/Router.ccipSend.t.sol index bf7b8f59353..c44a94d8d3d 100644 --- a/contracts/src/v0.8/ccip/test/router/Router/Router.ccipSend.t.sol +++ b/contracts/src/v0.8/ccip/test/router/Router/Router.ccipSend.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import {IERC20} from "../../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; @@ -138,7 +138,7 @@ contract Router_ccipSend is OnRampSetup { vm.resumeGasMetering(); } - function test_NonLinkFeeToken() public { + function test_NonLinkFeeToken_Success() public { address[] memory feeTokens = new address[](1); feeTokens[0] = s_sourceTokens[1]; s_feeQuoter.applyFeeTokensUpdates(new address[](0), feeTokens); @@ -149,7 +149,7 @@ contract Router_ccipSend is OnRampSetup { s_sourceRouter.ccipSend(DEST_CHAIN_SELECTOR, message); } - function test_NativeFeeToken() public { + function test_NativeFeeToken_Success() public { Client.EVM2AnyMessage memory message = _generateEmptyMessage(); message.feeToken = address(0); // Raw native uint256 nativeQuote = s_sourceRouter.getFee(DEST_CHAIN_SELECTOR, message); @@ -158,7 +158,7 @@ contract Router_ccipSend is OnRampSetup { s_sourceRouter.ccipSend{value: nativeQuote}(DEST_CHAIN_SELECTOR, message); } - function test_NativeFeeTokenOverpay() public { + function test_NativeFeeTokenOverpay_Success() public { Client.EVM2AnyMessage memory message = _generateEmptyMessage(); message.feeToken = address(0); // Raw native uint256 nativeQuote = s_sourceRouter.getFee(DEST_CHAIN_SELECTOR, message); @@ -170,7 +170,7 @@ contract Router_ccipSend is OnRampSetup { assertEq(address(s_sourceRouter).balance, 0); } - function test_WrappedNativeFeeToken() public { + function test_WrappedNativeFeeToken_Success() public { Client.EVM2AnyMessage memory message = _generateEmptyMessage(); message.feeToken = s_sourceRouter.getWrappedNative(); uint256 nativeQuote = s_sourceRouter.getFee(DEST_CHAIN_SELECTOR, message); @@ -184,15 +184,14 @@ contract Router_ccipSend is OnRampSetup { // Reverts - function test_RevertWhen_WhenNotHealthy() public { - vm.mockCall(address(s_mockRMNRemote), abi.encodeWithSignature("isCursed()"), abi.encode(true)); - + function test_WhenNotHealthy_Revert() public { + Client.EVM2AnyMessage memory message = _generateEmptyMessage(); + s_mockRMN.setGlobalCursed(true); vm.expectRevert(Router.BadARMSignal.selector); - - s_sourceRouter.ccipSend(DEST_CHAIN_SELECTOR, _generateEmptyMessage()); + s_sourceRouter.ccipSend(DEST_CHAIN_SELECTOR, message); } - function test_RevertWhen_UnsupportedDestinationChain() public { + function test_UnsupportedDestinationChain_Revert() public { Client.EVM2AnyMessage memory message = _generateEmptyMessage(); uint64 wrongChain = DEST_CHAIN_SELECTOR + 1; @@ -201,7 +200,7 @@ contract Router_ccipSend is OnRampSetup { s_sourceRouter.ccipSend(wrongChain, message); } - function test_RevertWhen_FeeTokenAmountTooLow() public { + function test_FeeTokenAmountTooLow_Revert() public { Client.EVM2AnyMessage memory message = _generateEmptyMessage(); IERC20(s_sourceTokens[0]).approve(address(s_sourceRouter), 0); diff --git a/contracts/src/v0.8/ccip/test/router/Router/Router.constructor.t.sol b/contracts/src/v0.8/ccip/test/router/Router/Router.constructor.t.sol index 6ac1d483729..a7dd90fc5e5 100644 --- a/contracts/src/v0.8/ccip/test/router/Router/Router.constructor.t.sol +++ b/contracts/src/v0.8/ccip/test/router/Router/Router.constructor.t.sol @@ -1,10 +1,10 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import {OnRampSetup} from "../../onRamp/OnRamp/OnRampSetup.t.sol"; contract Router_constructor is OnRampSetup { - function test_Constructor() public view { + function test_Constructor_Success() public view { assertEq("Router 1.2.0", s_sourceRouter.typeAndVersion()); assertEq(OWNER, s_sourceRouter.owner()); } diff --git a/contracts/src/v0.8/ccip/test/router/Router/Router.getArmProxy.t.sol b/contracts/src/v0.8/ccip/test/router/Router/Router.getArmProxy.t.sol index 3bc57e56291..a88e4c6b543 100644 --- a/contracts/src/v0.8/ccip/test/router/Router/Router.getArmProxy.t.sol +++ b/contracts/src/v0.8/ccip/test/router/Router/Router.getArmProxy.t.sol @@ -1,10 +1,10 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; -import {BaseTest} from "../../BaseTest.t.sol"; +import {RouterSetup} from "./RouterSetup.t.sol"; -contract Router_getArmProxy is BaseTest { +contract Router_getArmProxy is RouterSetup { function test_getArmProxy() public view { - assertEq(s_sourceRouter.getArmProxy(), address(s_mockRMNRemote)); + assertEq(s_sourceRouter.getArmProxy(), address(s_mockRMN)); } } diff --git a/contracts/src/v0.8/ccip/test/router/Router/Router.getFee.t.sol b/contracts/src/v0.8/ccip/test/router/Router/Router.getFee.t.sol index f800b6a269c..9cb2249bf6b 100644 --- a/contracts/src/v0.8/ccip/test/router/Router/Router.getFee.t.sol +++ b/contracts/src/v0.8/ccip/test/router/Router/Router.getFee.t.sol @@ -1,19 +1,19 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import {IRouterClient} from "../../../interfaces/IRouterClient.sol"; import {Client} from "../../../libraries/Client.sol"; import {OnRampSetup} from "../../onRamp/OnRamp/OnRampSetup.t.sol"; contract Router_getFee is OnRampSetup { - function test_GetFeeSupportedChain() public view { + function test_GetFeeSupportedChain_Success() public view { Client.EVM2AnyMessage memory message = _generateEmptyMessage(); uint256 expectedFee = s_sourceRouter.getFee(DEST_CHAIN_SELECTOR, message); assertGt(expectedFee, 10e9); } // Reverts - function test_RevertWhen_UnsupportedDestinationChain() public { + function test_UnsupportedDestinationChain_Revert() public { Client.EVM2AnyMessage memory message = _generateEmptyMessage(); vm.expectRevert(abi.encodeWithSelector(IRouterClient.UnsupportedDestinationChain.selector, 999)); diff --git a/contracts/src/v0.8/ccip/test/router/Router/Router.getSupportedTokens.t.sol b/contracts/src/v0.8/ccip/test/router/Router/Router.getSupportedTokens.t.sol index d13acceff3c..734f1f35ca5 100644 --- a/contracts/src/v0.8/ccip/test/router/Router/Router.getSupportedTokens.t.sol +++ b/contracts/src/v0.8/ccip/test/router/Router/Router.getSupportedTokens.t.sol @@ -1,11 +1,11 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import {OnRamp} from "../../../onRamp/OnRamp.sol"; import {OnRampSetup} from "../../onRamp/OnRamp/OnRampSetup.t.sol"; contract Router_getSupportedTokens is OnRampSetup { - function test_RevertWhen_GetSupportedTokens() public { + function test_GetSupportedTokens_Revert() public { vm.expectRevert(OnRamp.GetSupportedTokensFunctionalityRemovedCheckAdminRegistry.selector); s_onRamp.getSupportedTokens(DEST_CHAIN_SELECTOR); } diff --git a/contracts/src/v0.8/ccip/test/router/Router/Router.recoverTokens.t.sol b/contracts/src/v0.8/ccip/test/router/Router/Router.recoverTokens.t.sol index 4d9c7928fc9..3eb76b52d1b 100644 --- a/contracts/src/v0.8/ccip/test/router/Router/Router.recoverTokens.t.sol +++ b/contracts/src/v0.8/ccip/test/router/Router/Router.recoverTokens.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import {IERC20} from "../../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; @@ -9,7 +9,7 @@ import {MaybeRevertMessageReceiver} from "../../helpers/receivers/MaybeRevertMes import {OnRampSetup} from "../../onRamp/OnRamp/OnRampSetup.t.sol"; contract Router_recoverTokens is OnRampSetup { - function test_RecoverTokens() public { + function test_RecoverTokens_Success() public { // Assert we can recover sourceToken IERC20 token = IERC20(s_sourceTokens[0]); uint256 balanceBefore = token.balanceOf(OWNER); @@ -28,25 +28,25 @@ contract Router_recoverTokens is OnRampSetup { assertEq(address(s_sourceRouter).balance, 0); } - function test_RevertWhen_RecoverTokensNonOwner() public { + function test_RecoverTokensNonOwner_Revert() public { // Reverts if not owner vm.startPrank(STRANGER); vm.expectRevert("Only callable by owner"); s_sourceRouter.recoverTokens(address(0), STRANGER, 1); } - function test_RevertWhen_RecoverTokensInvalidRecipient() public { + function test_RecoverTokensInvalidRecipient_Revert() public { vm.expectRevert(abi.encodeWithSelector(Router.InvalidRecipientAddress.selector, address(0))); s_sourceRouter.recoverTokens(address(0), address(0), 1); } - function test_RevertWhen_RecoverTokensNoFunds() public { + function test_RecoverTokensNoFunds_Revert() public { // Reverts if no funds present vm.expectRevert(); s_sourceRouter.recoverTokens(address(0), OWNER, 10); } - function test_RevertWhen_RecoverTokensValueReceiver() public { + function test_RecoverTokensValueReceiver_Revert() public { MaybeRevertMessageReceiver revertingValueReceiver = new MaybeRevertMessageReceiver(true); deal(address(s_sourceRouter), 10); diff --git a/contracts/src/v0.8/ccip/test/router/Router/Router.routeMessage.t.sol b/contracts/src/v0.8/ccip/test/router/Router/Router.routeMessage.t.sol index 26b629dd30e..8fca851fa4a 100644 --- a/contracts/src/v0.8/ccip/test/router/Router/Router.routeMessage.t.sol +++ b/contracts/src/v0.8/ccip/test/router/Router/Router.routeMessage.t.sol @@ -1,11 +1,11 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; +import {Router} from "../../../Router.sol"; import {IAny2EVMMessageReceiver} from "../../../interfaces/IAny2EVMMessageReceiver.sol"; import {IRouter} from "../../../interfaces/IRouter.sol"; - -import {Router} from "../../../Router.sol"; import {Client} from "../../../libraries/Client.sol"; + import {MaybeRevertMessageReceiver} from "../../helpers/receivers/MaybeRevertMessageReceiver.sol"; import {OffRampSetup} from "../../offRamp/OffRamp/OffRampSetup.t.sol"; @@ -21,20 +21,7 @@ contract Router_routeMessage is OffRampSetup { return ((gasleft() - 2 * (16 * callDataLength + GAS_FOR_CALL_EXACT_CHECK)) * 62) / 64; } - function _generateReceiverMessage( - uint64 chainSelector - ) internal pure returns (Client.Any2EVMMessage memory) { - Client.EVMTokenAmount[] memory ta = new Client.EVMTokenAmount[](0); - return Client.Any2EVMMessage({ - messageId: bytes32("a"), - sourceChainSelector: chainSelector, - sender: bytes("a"), - data: bytes("a"), - destTokenAmounts: ta - }); - } - - function test_routeMessage_ManualExec() public { + function test_routeMessage_ManualExec_Success() public { Client.Any2EVMMessage memory message = _generateReceiverMessage(SOURCE_CHAIN_SELECTOR); // Manuel execution cannot run out of gas @@ -49,7 +36,7 @@ contract Router_routeMessage is OffRampSetup { assertGt(gasUsed, 3_000); } - function test_routeMessage_ExecutionEvent() public { + function test_routeMessage_ExecutionEvent_Success() public { Client.Any2EVMMessage memory message = _generateReceiverMessage(SOURCE_CHAIN_SELECTOR); // Should revert with reason bytes memory realError1 = new bytes(2); @@ -74,7 +61,7 @@ contract Router_routeMessage is OffRampSetup { assertFalse(success); assertEq(abi.encodeWithSelector(MaybeRevertMessageReceiver.CustomError.selector, realError1), retData); - assertGt(gasUsed, 2850); + assertGt(gasUsed, 3_000); // Reason is truncated // Over the MAX_RET_BYTES limit (including offset and length word since we have a dynamic values), should be ignored @@ -178,7 +165,7 @@ contract Router_routeMessage is OffRampSetup { assertEq(expectedRetData, retData); } - function test_routeMessage_AutoExec() public { + function test_routeMessage_AutoExec_Success() public { (bool success,,) = s_destRouter.routeMessage( _generateReceiverMessage(SOURCE_CHAIN_SELECTOR), GAS_FOR_CALL_EXACT_CHECK, 100_000, address(s_receiver) ); @@ -194,7 +181,7 @@ contract Router_routeMessage is OffRampSetup { } // Reverts - function test_RevertWhen_routeMessage_OnlyOffRamp() public { + function test_routeMessage_OnlyOffRamp_Revert() public { vm.stopPrank(); vm.startPrank(STRANGER); @@ -204,8 +191,8 @@ contract Router_routeMessage is OffRampSetup { ); } - function test_RevertWhen_routeMessage_WhenNotHealthy() public { - vm.mockCall(address(s_mockRMNRemote), abi.encodeWithSignature("isCursed()"), abi.encode(true)); + function test_routeMessage_WhenNotHealthy_Revert() public { + s_mockRMN.setGlobalCursed(true); vm.expectRevert(Router.BadARMSignal.selector); s_destRouter.routeMessage( _generateReceiverMessage(SOURCE_CHAIN_SELECTOR), GAS_FOR_CALL_EXACT_CHECK, 100_000, address(s_receiver) diff --git a/contracts/src/v0.8/ccip/test/router/Router/Router.setWrappedNative.t.sol b/contracts/src/v0.8/ccip/test/router/Router/Router.setWrappedNative.t.sol index 62cab30b5d0..a23d98e4eaa 100644 --- a/contracts/src/v0.8/ccip/test/router/Router/Router.setWrappedNative.t.sol +++ b/contracts/src/v0.8/ccip/test/router/Router/Router.setWrappedNative.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import {OnRampSetup} from "../../onRamp/OnRamp/OnRampSetup.t.sol"; @@ -12,7 +12,7 @@ contract Router_setWrappedNative is OnRampSetup { } // Reverts - function test_RevertWhen_OnlyOwner() public { + function test_OnlyOwner_Revert() public { vm.stopPrank(); vm.expectRevert("Only callable by owner"); s_sourceRouter.setWrappedNative(address(1)); diff --git a/contracts/src/v0.8/ccip/test/router/Router/RouterSetup.t.sol b/contracts/src/v0.8/ccip/test/router/Router/RouterSetup.t.sol new file mode 100644 index 00000000000..4a977db6c23 --- /dev/null +++ b/contracts/src/v0.8/ccip/test/router/Router/RouterSetup.t.sol @@ -0,0 +1,50 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.24; + +import {Router} from "../../../Router.sol"; +import {Client} from "../../../libraries/Client.sol"; +import {Internal} from "../../../libraries/Internal.sol"; +import {BaseTest} from "../../BaseTest.t.sol"; +import {WETH9} from "../../WETH9.sol"; + +contract RouterSetup is BaseTest { + Router internal s_sourceRouter; + Router internal s_destRouter; + + function setUp() public virtual override { + BaseTest.setUp(); + + if (address(s_sourceRouter) == address(0)) { + WETH9 weth = new WETH9(); + s_sourceRouter = new Router(address(weth), address(s_mockRMN)); + vm.label(address(s_sourceRouter), "sourceRouter"); + } + if (address(s_destRouter) == address(0)) { + WETH9 weth = new WETH9(); + s_destRouter = new Router(address(weth), address(s_mockRMN)); + vm.label(address(s_destRouter), "destRouter"); + } + } + + function _generateReceiverMessage( + uint64 chainSelector + ) internal pure returns (Client.Any2EVMMessage memory) { + Client.EVMTokenAmount[] memory ta = new Client.EVMTokenAmount[](0); + return Client.Any2EVMMessage({ + messageId: bytes32("a"), + sourceChainSelector: chainSelector, + sender: bytes("a"), + data: bytes("a"), + destTokenAmounts: ta + }); + } + + function _generateSourceTokenData() internal pure returns (Internal.SourceTokenData memory) { + return Internal.SourceTokenData({ + sourcePoolAddress: abi.encode(address(12312412312)), + destTokenAddress: abi.encode(address(9809808909)), + extraData: "", + destGasAmount: DEFAULT_TOKEN_DEST_GAS_OVERHEAD + }); + } +} diff --git a/contracts/src/v0.8/ccip/test/tokenAdminRegistry/FactoryBurnMintERC20/BurnMintERC20Setup.t.sol b/contracts/src/v0.8/ccip/test/tokenAdminRegistry/FactoryBurnMintERC20/BurnMintERC20Setup.t.sol index f5ad827db45..098d5e4601e 100644 --- a/contracts/src/v0.8/ccip/test/tokenAdminRegistry/FactoryBurnMintERC20/BurnMintERC20Setup.t.sol +++ b/contracts/src/v0.8/ccip/test/tokenAdminRegistry/FactoryBurnMintERC20/BurnMintERC20Setup.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import {FactoryBurnMintERC20} from "../../../tokenAdminRegistry/TokenPoolFactory/FactoryBurnMintERC20.sol"; import {BaseTest} from "../../BaseTest.t.sol"; diff --git a/contracts/src/v0.8/ccip/test/tokenAdminRegistry/FactoryBurnMintERC20/FactoryBurnMintERC20.approve.t.sol b/contracts/src/v0.8/ccip/test/tokenAdminRegistry/FactoryBurnMintERC20/FactoryBurnMintERC20.approve.t.sol index 4117bba4f6e..9ba6da0186d 100644 --- a/contracts/src/v0.8/ccip/test/tokenAdminRegistry/FactoryBurnMintERC20/FactoryBurnMintERC20.approve.t.sol +++ b/contracts/src/v0.8/ccip/test/tokenAdminRegistry/FactoryBurnMintERC20/FactoryBurnMintERC20.approve.t.sol @@ -1,10 +1,10 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import {BurnMintERC20Setup} from "./BurnMintERC20Setup.t.sol"; contract FactoryBurnMintERC20_approve is BurnMintERC20Setup { - function test_Approve() public { + function test_Approve_Success() public { uint256 balancePre = s_burnMintERC20.balanceOf(STRANGER); uint256 sendingAmount = s_amount / 2; @@ -19,7 +19,7 @@ contract FactoryBurnMintERC20_approve is BurnMintERC20Setup { // Reverts - function test_RevertWhen_InvalidAddresss() public { + function test_InvalidAddress_Reverts() public { vm.expectRevert(); s_burnMintERC20.approve(address(s_burnMintERC20), s_amount); diff --git a/contracts/src/v0.8/ccip/test/tokenAdminRegistry/FactoryBurnMintERC20/FactoryBurnMintERC20.burn.t.sol b/contracts/src/v0.8/ccip/test/tokenAdminRegistry/FactoryBurnMintERC20/FactoryBurnMintERC20.burn.t.sol index 8ca692a4069..5f6e7ee4d04 100644 --- a/contracts/src/v0.8/ccip/test/tokenAdminRegistry/FactoryBurnMintERC20/FactoryBurnMintERC20.burn.t.sol +++ b/contracts/src/v0.8/ccip/test/tokenAdminRegistry/FactoryBurnMintERC20/FactoryBurnMintERC20.burn.t.sol @@ -1,12 +1,12 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import {IERC20} from "../../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; import {FactoryBurnMintERC20} from "../../../tokenAdminRegistry/TokenPoolFactory/FactoryBurnMintERC20.sol"; import {BurnMintERC20Setup} from "./BurnMintERC20Setup.t.sol"; contract FactoryBurnMintERC20_burn is BurnMintERC20Setup { - function test_BasicBurn() public { + function test_BasicBurn_Success() public { s_burnMintERC20.grantBurnRole(OWNER); deal(address(s_burnMintERC20), OWNER, s_amount); @@ -20,13 +20,13 @@ contract FactoryBurnMintERC20_burn is BurnMintERC20Setup { // Revert - function test_RevertWhen_SenderNotBurners() public { + function test_SenderNotBurner_Reverts() public { vm.expectRevert(abi.encodeWithSelector(FactoryBurnMintERC20.SenderNotBurner.selector, OWNER)); s_burnMintERC20.burnFrom(STRANGER, s_amount); } - function test_RevertWhen_ExceedsBalances() public { + function test_ExceedsBalance_Reverts() public { changePrank(s_mockPool); vm.expectRevert("ERC20: burn amount exceeds balance"); @@ -34,7 +34,7 @@ contract FactoryBurnMintERC20_burn is BurnMintERC20Setup { s_burnMintERC20.burn(s_amount * 2); } - function test_RevertWhen_BurnFromZeroAddresss() public { + function test_BurnFromZeroAddress_Reverts() public { s_burnMintERC20.grantBurnRole(address(0)); changePrank(address(0)); diff --git a/contracts/src/v0.8/ccip/test/tokenAdminRegistry/FactoryBurnMintERC20/FactoryBurnMintERC20.burnFrom.t.sol b/contracts/src/v0.8/ccip/test/tokenAdminRegistry/FactoryBurnMintERC20/FactoryBurnMintERC20.burnFrom.t.sol index 4549ca01dbe..e2dcaf28563 100644 --- a/contracts/src/v0.8/ccip/test/tokenAdminRegistry/FactoryBurnMintERC20/FactoryBurnMintERC20.burnFrom.t.sol +++ b/contracts/src/v0.8/ccip/test/tokenAdminRegistry/FactoryBurnMintERC20/FactoryBurnMintERC20.burnFrom.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import {FactoryBurnMintERC20} from "../../../tokenAdminRegistry/TokenPoolFactory/FactoryBurnMintERC20.sol"; import {BurnMintERC20Setup} from "./BurnMintERC20Setup.t.sol"; @@ -9,7 +9,7 @@ contract FactoryBurnMintERC20_burnFrom is BurnMintERC20Setup { BurnMintERC20Setup.setUp(); } - function test_BurnFrom() public { + function test_BurnFrom_Success() public { s_burnMintERC20.approve(s_mockPool, s_amount); changePrank(s_mockPool); @@ -21,13 +21,13 @@ contract FactoryBurnMintERC20_burnFrom is BurnMintERC20Setup { // Reverts - function test_RevertWhen_SenderNotBurners() public { + function test_SenderNotBurner_Reverts() public { vm.expectRevert(abi.encodeWithSelector(FactoryBurnMintERC20.SenderNotBurner.selector, OWNER)); s_burnMintERC20.burnFrom(OWNER, s_amount); } - function test_RevertWhen_InsufficientAllowances() public { + function test_InsufficientAllowance_Reverts() public { changePrank(s_mockPool); vm.expectRevert("ERC20: insufficient allowance"); @@ -35,7 +35,7 @@ contract FactoryBurnMintERC20_burnFrom is BurnMintERC20Setup { s_burnMintERC20.burnFrom(OWNER, s_amount); } - function test_RevertWhen_ExceedsBalances() public { + function test_ExceedsBalance_Reverts() public { s_burnMintERC20.approve(s_mockPool, s_amount * 2); changePrank(s_mockPool); diff --git a/contracts/src/v0.8/ccip/test/tokenAdminRegistry/FactoryBurnMintERC20/FactoryBurnMintERC20.burnFromAlias.t.sol b/contracts/src/v0.8/ccip/test/tokenAdminRegistry/FactoryBurnMintERC20/FactoryBurnMintERC20.burnFromAlias.t.sol index c71f6142b2d..0d46f1d54a5 100644 --- a/contracts/src/v0.8/ccip/test/tokenAdminRegistry/FactoryBurnMintERC20/FactoryBurnMintERC20.burnFromAlias.t.sol +++ b/contracts/src/v0.8/ccip/test/tokenAdminRegistry/FactoryBurnMintERC20/FactoryBurnMintERC20.burnFromAlias.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import {FactoryBurnMintERC20} from "../../../tokenAdminRegistry/TokenPoolFactory/FactoryBurnMintERC20.sol"; import {BurnMintERC20Setup} from "./BurnMintERC20Setup.t.sol"; @@ -9,7 +9,7 @@ contract FactoryBurnMintERC20_burnFromAlias is BurnMintERC20Setup { BurnMintERC20Setup.setUp(); } - function test_BurnFrom() public { + function test_BurnFrom_Success() public { s_burnMintERC20.approve(s_mockPool, s_amount); changePrank(s_mockPool); @@ -21,13 +21,13 @@ contract FactoryBurnMintERC20_burnFromAlias is BurnMintERC20Setup { // Reverts - function test_RevertWhen_SenderNotBurners() public { + function test_SenderNotBurner_Reverts() public { vm.expectRevert(abi.encodeWithSelector(FactoryBurnMintERC20.SenderNotBurner.selector, OWNER)); s_burnMintERC20.burn(OWNER, s_amount); } - function test_RevertWhen_InsufficientAllowances() public { + function test_InsufficientAllowance_Reverts() public { changePrank(s_mockPool); vm.expectRevert("ERC20: insufficient allowance"); @@ -35,7 +35,7 @@ contract FactoryBurnMintERC20_burnFromAlias is BurnMintERC20Setup { s_burnMintERC20.burn(OWNER, s_amount); } - function test_RevertWhen_ExceedsBalances() public { + function test_ExceedsBalance_Reverts() public { s_burnMintERC20.approve(s_mockPool, s_amount * 2); changePrank(s_mockPool); diff --git a/contracts/src/v0.8/ccip/test/tokenAdminRegistry/FactoryBurnMintERC20/FactoryBurnMintERC20.constructor.t.sol b/contracts/src/v0.8/ccip/test/tokenAdminRegistry/FactoryBurnMintERC20/FactoryBurnMintERC20.constructor.t.sol index a5f65a903c0..f1ee0866abe 100644 --- a/contracts/src/v0.8/ccip/test/tokenAdminRegistry/FactoryBurnMintERC20/FactoryBurnMintERC20.constructor.t.sol +++ b/contracts/src/v0.8/ccip/test/tokenAdminRegistry/FactoryBurnMintERC20/FactoryBurnMintERC20.constructor.t.sol @@ -1,11 +1,11 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import {FactoryBurnMintERC20} from "../../../tokenAdminRegistry/TokenPoolFactory/FactoryBurnMintERC20.sol"; import {BurnMintERC20Setup} from "./BurnMintERC20Setup.t.sol"; contract FactoryBurnMintERC20_constructor is BurnMintERC20Setup { - function test_Constructor() public { + function test_Constructor_Success() public { string memory name = "Chainlink token v2"; string memory symbol = "LINK2"; uint8 decimals = 19; diff --git a/contracts/src/v0.8/ccip/test/tokenAdminRegistry/FactoryBurnMintERC20/FactoryBurnMintERC20.decreaseApproval.t.sol b/contracts/src/v0.8/ccip/test/tokenAdminRegistry/FactoryBurnMintERC20/FactoryBurnMintERC20.decreaseApproval.t.sol index fbd64b5858e..aa621a998ed 100644 --- a/contracts/src/v0.8/ccip/test/tokenAdminRegistry/FactoryBurnMintERC20/FactoryBurnMintERC20.decreaseApproval.t.sol +++ b/contracts/src/v0.8/ccip/test/tokenAdminRegistry/FactoryBurnMintERC20/FactoryBurnMintERC20.decreaseApproval.t.sol @@ -1,10 +1,10 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import {BurnMintERC20Setup} from "./BurnMintERC20Setup.t.sol"; contract FactoryBurnMintERC20_decreaseApproval is BurnMintERC20Setup { - function test_DecreaseApproval() public { + function test_DecreaseApproval_Success() public { s_burnMintERC20.approve(s_mockPool, s_amount); uint256 allowance = s_burnMintERC20.allowance(OWNER, s_mockPool); assertEq(allowance, s_amount); diff --git a/contracts/src/v0.8/ccip/test/tokenAdminRegistry/FactoryBurnMintERC20/FactoryBurnMintERC20.getCCIPAdmin.t.sol b/contracts/src/v0.8/ccip/test/tokenAdminRegistry/FactoryBurnMintERC20/FactoryBurnMintERC20.getCCIPAdmin.t.sol index 2e30bc2a557..fc6a81a712b 100644 --- a/contracts/src/v0.8/ccip/test/tokenAdminRegistry/FactoryBurnMintERC20/FactoryBurnMintERC20.getCCIPAdmin.t.sol +++ b/contracts/src/v0.8/ccip/test/tokenAdminRegistry/FactoryBurnMintERC20/FactoryBurnMintERC20.getCCIPAdmin.t.sol @@ -1,15 +1,15 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import {FactoryBurnMintERC20} from "../../../tokenAdminRegistry/TokenPoolFactory/FactoryBurnMintERC20.sol"; import {BurnMintERC20Setup} from "./BurnMintERC20Setup.t.sol"; contract FactoryBurnMintERC20_getCCIPAdmin is BurnMintERC20Setup { - function test_getCCIPAdmin() public view { + function test_getCCIPAdmin_Success() public view { assertEq(s_alice, s_burnMintERC20.getCCIPAdmin()); } - function test_setCCIPAdmin() public { + function test_setCCIPAdmin_Success() public { address newAdmin = makeAddr("newAdmin"); vm.expectEmit(); diff --git a/contracts/src/v0.8/ccip/test/tokenAdminRegistry/FactoryBurnMintERC20/FactoryBurnMintERC20.grantMintAndBurnRoles.t.sol b/contracts/src/v0.8/ccip/test/tokenAdminRegistry/FactoryBurnMintERC20/FactoryBurnMintERC20.grantMintAndBurnRoles.t.sol index 0e55271cab3..aaa967edc15 100644 --- a/contracts/src/v0.8/ccip/test/tokenAdminRegistry/FactoryBurnMintERC20/FactoryBurnMintERC20.grantMintAndBurnRoles.t.sol +++ b/contracts/src/v0.8/ccip/test/tokenAdminRegistry/FactoryBurnMintERC20/FactoryBurnMintERC20.grantMintAndBurnRoles.t.sol @@ -1,11 +1,11 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import {FactoryBurnMintERC20} from "../../../tokenAdminRegistry/TokenPoolFactory/FactoryBurnMintERC20.sol"; import {BurnMintERC20Setup} from "./BurnMintERC20Setup.t.sol"; contract FactoryBurnMintERC20_grantMintAndBurnRoles is BurnMintERC20Setup { - function test_GrantMintAndBurnRoles() public { + function test_GrantMintAndBurnRoles_Success() public { assertFalse(s_burnMintERC20.isMinter(STRANGER)); assertFalse(s_burnMintERC20.isBurner(STRANGER)); diff --git a/contracts/src/v0.8/ccip/test/tokenAdminRegistry/FactoryBurnMintERC20/FactoryBurnMintERC20.grantRole.t.sol b/contracts/src/v0.8/ccip/test/tokenAdminRegistry/FactoryBurnMintERC20/FactoryBurnMintERC20.grantRole.t.sol index 473c143cbd5..a06b52ac338 100644 --- a/contracts/src/v0.8/ccip/test/tokenAdminRegistry/FactoryBurnMintERC20/FactoryBurnMintERC20.grantRole.t.sol +++ b/contracts/src/v0.8/ccip/test/tokenAdminRegistry/FactoryBurnMintERC20/FactoryBurnMintERC20.grantRole.t.sol @@ -1,11 +1,11 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import {FactoryBurnMintERC20} from "../../../tokenAdminRegistry/TokenPoolFactory/FactoryBurnMintERC20.sol"; import {BurnMintERC20Setup} from "./BurnMintERC20Setup.t.sol"; contract FactoryBurnMintERC20_grantRole is BurnMintERC20Setup { - function test_GrantMintAccess() public { + function test_GrantMintAccess_Success() public { assertFalse(s_burnMintERC20.isMinter(STRANGER)); vm.expectEmit(); @@ -23,7 +23,7 @@ contract FactoryBurnMintERC20_grantRole is BurnMintERC20Setup { assertFalse(s_burnMintERC20.isMinter(STRANGER)); } - function test_GrantBurnAccess() public { + function test_GrantBurnAccess_Success() public { assertFalse(s_burnMintERC20.isBurner(STRANGER)); vm.expectEmit(); @@ -41,7 +41,7 @@ contract FactoryBurnMintERC20_grantRole is BurnMintERC20Setup { assertFalse(s_burnMintERC20.isBurner(STRANGER)); } - function test_GrantMany() public { + function test_GrantMany_Success() public { // Since alice was already granted mint and burn roles in the setup, we will revoke them // and then grant them again for the purposes of the test s_burnMintERC20.revokeMintRole(s_alice); diff --git a/contracts/src/v0.8/ccip/test/tokenAdminRegistry/FactoryBurnMintERC20/FactoryBurnMintERC20.increaseApproval.t.sol b/contracts/src/v0.8/ccip/test/tokenAdminRegistry/FactoryBurnMintERC20/FactoryBurnMintERC20.increaseApproval.t.sol index b0782470691..e93cc2a71e6 100644 --- a/contracts/src/v0.8/ccip/test/tokenAdminRegistry/FactoryBurnMintERC20/FactoryBurnMintERC20.increaseApproval.t.sol +++ b/contracts/src/v0.8/ccip/test/tokenAdminRegistry/FactoryBurnMintERC20/FactoryBurnMintERC20.increaseApproval.t.sol @@ -1,10 +1,10 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import {BurnMintERC20Setup} from "./BurnMintERC20Setup.t.sol"; contract FactoryBurnMintERC20_increaseApproval is BurnMintERC20Setup { - function test_IncreaseApproval() public { + function test_IncreaseApproval_Success() public { s_burnMintERC20.approve(s_mockPool, s_amount); uint256 allowance = s_burnMintERC20.allowance(OWNER, s_mockPool); assertEq(allowance, s_amount); diff --git a/contracts/src/v0.8/ccip/test/tokenAdminRegistry/FactoryBurnMintERC20/FactoryBurnMintERC20.mint.t.sol b/contracts/src/v0.8/ccip/test/tokenAdminRegistry/FactoryBurnMintERC20/FactoryBurnMintERC20.mint.t.sol index 59c4145f27b..b22783a3c75 100644 --- a/contracts/src/v0.8/ccip/test/tokenAdminRegistry/FactoryBurnMintERC20/FactoryBurnMintERC20.mint.t.sol +++ b/contracts/src/v0.8/ccip/test/tokenAdminRegistry/FactoryBurnMintERC20/FactoryBurnMintERC20.mint.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import {FactoryBurnMintERC20} from "../../../tokenAdminRegistry/TokenPoolFactory/FactoryBurnMintERC20.sol"; @@ -7,7 +7,7 @@ import {IERC20} from "../../../../vendor/openzeppelin-solidity/v4.8.3/contracts/ import {BurnMintERC20Setup} from "./BurnMintERC20Setup.t.sol"; contract FactoryBurnMintERC20_mint is BurnMintERC20Setup { - function test_BasicMint() public { + function test_BasicMint_Success() public { uint256 balancePre = s_burnMintERC20.balanceOf(OWNER); s_burnMintERC20.grantMintAndBurnRoles(OWNER); @@ -22,12 +22,12 @@ contract FactoryBurnMintERC20_mint is BurnMintERC20Setup { // Revert - function test_RevertWhen_SenderNotMinters() public { + function test_SenderNotMinter_Reverts() public { vm.expectRevert(abi.encodeWithSelector(FactoryBurnMintERC20.SenderNotMinter.selector, OWNER)); s_burnMintERC20.mint(STRANGER, 1e18); } - function test_RevertWhen_MaxSupplyExceededs() public { + function test_MaxSupplyExceeded_Reverts() public { changePrank(s_mockPool); // Mint max supply diff --git a/contracts/src/v0.8/ccip/test/tokenAdminRegistry/FactoryBurnMintERC20/FactoryBurnMintERC20.supportsInterface.t.sol b/contracts/src/v0.8/ccip/test/tokenAdminRegistry/FactoryBurnMintERC20/FactoryBurnMintERC20.supportsInterface.t.sol index 0070a943cec..bdf3c3e7ae3 100644 --- a/contracts/src/v0.8/ccip/test/tokenAdminRegistry/FactoryBurnMintERC20/FactoryBurnMintERC20.supportsInterface.t.sol +++ b/contracts/src/v0.8/ccip/test/tokenAdminRegistry/FactoryBurnMintERC20/FactoryBurnMintERC20.supportsInterface.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import {IBurnMintERC20} from "../../../../shared/token/ERC20/IBurnMintERC20.sol"; import {IERC20} from "../../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; @@ -7,7 +7,7 @@ import {IERC165} from "../../../../vendor/openzeppelin-solidity/v4.8.3/contracts import {BurnMintERC20Setup} from "./BurnMintERC20Setup.t.sol"; contract FactoryBurnMintERC20_supportsInterface is BurnMintERC20Setup { - function test_SupportsInterface() public view { + function test_SupportsInterface_Success() public view { assertTrue(s_burnMintERC20.supportsInterface(type(IERC20).interfaceId)); assertTrue(s_burnMintERC20.supportsInterface(type(IBurnMintERC20).interfaceId)); assertTrue(s_burnMintERC20.supportsInterface(type(IERC165).interfaceId)); diff --git a/contracts/src/v0.8/ccip/test/tokenAdminRegistry/FactoryBurnMintERC20/FactoryBurnMintERC20.transfer.t.sol b/contracts/src/v0.8/ccip/test/tokenAdminRegistry/FactoryBurnMintERC20/FactoryBurnMintERC20.transfer.t.sol index cf93e9f0b95..333d50d333e 100644 --- a/contracts/src/v0.8/ccip/test/tokenAdminRegistry/FactoryBurnMintERC20/FactoryBurnMintERC20.transfer.t.sol +++ b/contracts/src/v0.8/ccip/test/tokenAdminRegistry/FactoryBurnMintERC20/FactoryBurnMintERC20.transfer.t.sol @@ -1,10 +1,10 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import {BurnMintERC20Setup} from "./BurnMintERC20Setup.t.sol"; contract FactoryBurnMintERC20_transfer is BurnMintERC20Setup { - function test_Transfer() public { + function test_Transfer_Success() public { uint256 balancePre = s_burnMintERC20.balanceOf(STRANGER); uint256 sendingAmount = s_amount / 2; @@ -15,7 +15,7 @@ contract FactoryBurnMintERC20_transfer is BurnMintERC20Setup { // Reverts - function test_RevertWhen_InvalidAddresss() public { + function test_InvalidAddress_Reverts() public { vm.expectRevert(); s_burnMintERC20.transfer(address(s_burnMintERC20), s_amount); diff --git a/contracts/src/v0.8/ccip/test/tokenAdminRegistry/RegistryModuleOwnerCustom/RegistryModuleOwnerCustom.constructor.t.sol b/contracts/src/v0.8/ccip/test/tokenAdminRegistry/RegistryModuleOwnerCustom/RegistryModuleOwnerCustom.constructor.t.sol index 64b58b2d4dd..22bf54e633b 100644 --- a/contracts/src/v0.8/ccip/test/tokenAdminRegistry/RegistryModuleOwnerCustom/RegistryModuleOwnerCustom.constructor.t.sol +++ b/contracts/src/v0.8/ccip/test/tokenAdminRegistry/RegistryModuleOwnerCustom/RegistryModuleOwnerCustom.constructor.t.sol @@ -5,7 +5,7 @@ import {RegistryModuleOwnerCustom} from "../../../tokenAdminRegistry/RegistryMod import {RegistryModuleOwnerCustomSetup} from "./RegistryModuleOwnerCustomSetup.t.sol"; contract RegistryModuleOwnerCustom_constructor is RegistryModuleOwnerCustomSetup { - function test_RevertWhen_constructor() public { + function test_constructor_Revert() public { vm.expectRevert(abi.encodeWithSelector(RegistryModuleOwnerCustom.AddressZero.selector)); new RegistryModuleOwnerCustom(address(0)); diff --git a/contracts/src/v0.8/ccip/test/tokenAdminRegistry/RegistryModuleOwnerCustom/RegistryModuleOwnerCustom.registerAccessControlDefaultAdmin.t.sol b/contracts/src/v0.8/ccip/test/tokenAdminRegistry/RegistryModuleOwnerCustom/RegistryModuleOwnerCustom.registerAccessControlDefaultAdmin.t.sol index 6660962b0cf..5bf1c0aee34 100644 --- a/contracts/src/v0.8/ccip/test/tokenAdminRegistry/RegistryModuleOwnerCustom/RegistryModuleOwnerCustom.registerAccessControlDefaultAdmin.t.sol +++ b/contracts/src/v0.8/ccip/test/tokenAdminRegistry/RegistryModuleOwnerCustom/RegistryModuleOwnerCustom.registerAccessControlDefaultAdmin.t.sol @@ -23,7 +23,7 @@ contract RegistryModuleOwnerCustom_registerAccessControlDefaultAdmin is Registry s_token = address(new AccessController(OWNER)); } - function test_registerAccessControlDefaultAdmin() public { + function test_registerAccessControlDefaultAdmin_Success() public { assertEq(s_tokenAdminRegistry.getTokenConfig(s_token).administrator, address(0)); bytes32 defaultAdminRole = AccessController(s_token).DEFAULT_ADMIN_ROLE(); @@ -43,7 +43,7 @@ contract RegistryModuleOwnerCustom_registerAccessControlDefaultAdmin is Registry assertEq(s_tokenAdminRegistry.getTokenConfig(s_token).pendingAdministrator, OWNER); } - function test_RevertWhen_registerAccessControlDefaultAdmin() public { + function test_registerAccessControlDefaultAdmin_Revert() public { bytes32 defaultAdminRole = AccessController(s_token).DEFAULT_ADMIN_ROLE(); address wrongSender = makeAddr("Not_expected_owner"); diff --git a/contracts/src/v0.8/ccip/test/tokenAdminRegistry/RegistryModuleOwnerCustom/RegistryModuleOwnerCustom.registerAdminViaGetCCIPAdmin.t.sol b/contracts/src/v0.8/ccip/test/tokenAdminRegistry/RegistryModuleOwnerCustom/RegistryModuleOwnerCustom.registerAdminViaGetCCIPAdmin.t.sol index 8646d918afe..5e3c6545417 100644 --- a/contracts/src/v0.8/ccip/test/tokenAdminRegistry/RegistryModuleOwnerCustom/RegistryModuleOwnerCustom.registerAdminViaGetCCIPAdmin.t.sol +++ b/contracts/src/v0.8/ccip/test/tokenAdminRegistry/RegistryModuleOwnerCustom/RegistryModuleOwnerCustom.registerAdminViaGetCCIPAdmin.t.sol @@ -9,7 +9,7 @@ import {TokenAdminRegistry} from "../../../tokenAdminRegistry/TokenAdminRegistry import {RegistryModuleOwnerCustomSetup} from "./RegistryModuleOwnerCustomSetup.t.sol"; contract RegistryModuleOwnerCustom_registerAdminViaGetCCIPAdmin is RegistryModuleOwnerCustomSetup { - function test_registerAdminViaGetCCIPAdmin() public { + function test_registerAdminViaGetCCIPAdmin_Success() public { assertEq(s_tokenAdminRegistry.getTokenConfig(s_token).administrator, address(0)); address expectedOwner = IGetCCIPAdmin(s_token).getCCIPAdmin(); @@ -29,7 +29,7 @@ contract RegistryModuleOwnerCustom_registerAdminViaGetCCIPAdmin is RegistryModul assertEq(s_tokenAdminRegistry.getTokenConfig(s_token).pendingAdministrator, OWNER); } - function test_RevertWhen_registerAdminViaGetCCIPAdmin() public { + function test_registerAdminViaGetCCIPAdmin_Revert() public { address expectedOwner = IGetCCIPAdmin(s_token).getCCIPAdmin(); vm.startPrank(makeAddr("Not_expected_owner")); diff --git a/contracts/src/v0.8/ccip/test/tokenAdminRegistry/RegistryModuleOwnerCustom/RegistryModuleOwnerCustom.registerAdminViaOwner.t.sol b/contracts/src/v0.8/ccip/test/tokenAdminRegistry/RegistryModuleOwnerCustom/RegistryModuleOwnerCustom.registerAdminViaOwner.t.sol index 6fcee1b039e..b4e1a5e4577 100644 --- a/contracts/src/v0.8/ccip/test/tokenAdminRegistry/RegistryModuleOwnerCustom/RegistryModuleOwnerCustom.registerAdminViaOwner.t.sol +++ b/contracts/src/v0.8/ccip/test/tokenAdminRegistry/RegistryModuleOwnerCustom/RegistryModuleOwnerCustom.registerAdminViaOwner.t.sol @@ -9,7 +9,7 @@ import {TokenAdminRegistry} from "../../../tokenAdminRegistry/TokenAdminRegistry import {RegistryModuleOwnerCustomSetup} from "./RegistryModuleOwnerCustomSetup.t.sol"; contract RegistryModuleOwnerCustom_registerAdminViaOwner is RegistryModuleOwnerCustomSetup { - function test_registerAdminViaOwner() public { + function test_registerAdminViaOwner_Success() public { assertEq(s_tokenAdminRegistry.getTokenConfig(s_token).administrator, address(0)); address expectedOwner = IOwner(s_token).owner(); @@ -29,7 +29,7 @@ contract RegistryModuleOwnerCustom_registerAdminViaOwner is RegistryModuleOwnerC assertEq(s_tokenAdminRegistry.getTokenConfig(s_token).pendingAdministrator, OWNER); } - function test_RevertWhen_registerAdminViaOwner() public { + function test_registerAdminViaOwner_Revert() public { address expectedOwner = IOwner(s_token).owner(); vm.startPrank(makeAddr("Not_expected_owner")); diff --git a/contracts/src/v0.8/ccip/test/tokenAdminRegistry/TokenAdminRegistry/TokenAdminRegistry.acceptAdminRole.t.sol b/contracts/src/v0.8/ccip/test/tokenAdminRegistry/TokenAdminRegistry/TokenAdminRegistry.acceptAdminRole.t.sol index 05c3ac77893..069159b8938 100644 --- a/contracts/src/v0.8/ccip/test/tokenAdminRegistry/TokenAdminRegistry/TokenAdminRegistry.acceptAdminRole.t.sol +++ b/contracts/src/v0.8/ccip/test/tokenAdminRegistry/TokenAdminRegistry/TokenAdminRegistry.acceptAdminRole.t.sol @@ -5,7 +5,7 @@ import {TokenAdminRegistry} from "../../../tokenAdminRegistry/TokenAdminRegistry import {TokenAdminRegistrySetup} from "./TokenAdminRegistrySetup.t.sol"; contract TokenAdminRegistry_acceptAdminRole is TokenAdminRegistrySetup { - function test_acceptAdminRole() public { + function test_acceptAdminRole_Success() public { address token = s_sourceTokens[0]; address currentAdmin = s_tokenAdminRegistry.getTokenConfig(token).administrator; @@ -36,7 +36,7 @@ contract TokenAdminRegistry_acceptAdminRole is TokenAdminRegistrySetup { assertEq(config.administrator, newAdmin); } - function test_RevertWhen_acceptAdminRole_OnlyPendingAdministrator() public { + function test_acceptAdminRole_OnlyPendingAdministrator_Revert() public { address token = s_sourceTokens[0]; address currentAdmin = s_tokenAdminRegistry.getTokenConfig(token).administrator; address newAdmin = makeAddr("newAdmin"); diff --git a/contracts/src/v0.8/ccip/test/tokenAdminRegistry/TokenAdminRegistry/TokenAdminRegistry.addRegistryModule.t.sol b/contracts/src/v0.8/ccip/test/tokenAdminRegistry/TokenAdminRegistry/TokenAdminRegistry.addRegistryModule.t.sol index 9e21cd3e193..9874ceb72bc 100644 --- a/contracts/src/v0.8/ccip/test/tokenAdminRegistry/TokenAdminRegistry/TokenAdminRegistry.addRegistryModule.t.sol +++ b/contracts/src/v0.8/ccip/test/tokenAdminRegistry/TokenAdminRegistry/TokenAdminRegistry.addRegistryModule.t.sol @@ -5,7 +5,7 @@ import {Ownable2Step} from "../../../../shared/access/Ownable2Step.sol"; import {TokenAdminRegistrySetup} from "./TokenAdminRegistrySetup.t.sol"; contract TokenAdminRegistry_addRegistryModule is TokenAdminRegistrySetup { - function test_addRegistryModule() public { + function test_addRegistryModule_Success() public { address newModule = makeAddr("newModule"); s_tokenAdminRegistry.addRegistryModule(newModule); @@ -19,7 +19,7 @@ contract TokenAdminRegistry_addRegistryModule is TokenAdminRegistrySetup { vm.assertEq(vm.getRecordedLogs().length, 0); } - function test_RevertWhen_addRegistryModule_OnlyOwner() public { + function test_addRegistryModule_OnlyOwner_Revert() public { address newModule = makeAddr("newModule"); vm.stopPrank(); diff --git a/contracts/src/v0.8/ccip/test/tokenAdminRegistry/TokenAdminRegistry/TokenAdminRegistry.getAllConfiguredTokens.t.sol b/contracts/src/v0.8/ccip/test/tokenAdminRegistry/TokenAdminRegistry/TokenAdminRegistry.getAllConfiguredTokens.t.sol index 9d42bcc8b2f..6e16f27eca7 100644 --- a/contracts/src/v0.8/ccip/test/tokenAdminRegistry/TokenAdminRegistry/TokenAdminRegistry.getAllConfiguredTokens.t.sol +++ b/contracts/src/v0.8/ccip/test/tokenAdminRegistry/TokenAdminRegistry/TokenAdminRegistry.getAllConfiguredTokens.t.sol @@ -28,7 +28,7 @@ contract TokenAdminRegistry_getAllConfiguredTokens is TokenAdminRegistrySetup { } } - function test_getAllConfiguredTokens_outOfBounds() public view { + function test_getAllConfiguredTokens_outOfBounds_Success() public view { address[] memory tokens = s_tokenAdminRegistry.getAllConfiguredTokens(type(uint64).max, 10); assertEq(tokens.length, 0); } diff --git a/contracts/src/v0.8/ccip/test/tokenAdminRegistry/TokenAdminRegistry/TokenAdminRegistry.getPool.t.sol b/contracts/src/v0.8/ccip/test/tokenAdminRegistry/TokenAdminRegistry/TokenAdminRegistry.getPool.t.sol index 12288ae365c..297e3c3143a 100644 --- a/contracts/src/v0.8/ccip/test/tokenAdminRegistry/TokenAdminRegistry/TokenAdminRegistry.getPool.t.sol +++ b/contracts/src/v0.8/ccip/test/tokenAdminRegistry/TokenAdminRegistry/TokenAdminRegistry.getPool.t.sol @@ -4,7 +4,7 @@ pragma solidity ^0.8.0; import {TokenAdminRegistrySetup} from "./TokenAdminRegistrySetup.t.sol"; contract TokenAdminRegistry_getPool is TokenAdminRegistrySetup { - function test_getPool() public view { + function test_getPool_Success() public view { address got = s_tokenAdminRegistry.getPool(s_sourceTokens[0]); assertEq(got, s_sourcePoolByToken[s_sourceTokens[0]]); } diff --git a/contracts/src/v0.8/ccip/test/tokenAdminRegistry/TokenAdminRegistry/TokenAdminRegistry.getPools.t.sol b/contracts/src/v0.8/ccip/test/tokenAdminRegistry/TokenAdminRegistry/TokenAdminRegistry.getPools.t.sol index 194adc447b9..7c673ee5be6 100644 --- a/contracts/src/v0.8/ccip/test/tokenAdminRegistry/TokenAdminRegistry/TokenAdminRegistry.getPools.t.sol +++ b/contracts/src/v0.8/ccip/test/tokenAdminRegistry/TokenAdminRegistry/TokenAdminRegistry.getPools.t.sol @@ -4,7 +4,7 @@ pragma solidity ^0.8.0; import {TokenAdminRegistrySetup} from "./TokenAdminRegistrySetup.t.sol"; contract TokenAdminRegistry_getPools is TokenAdminRegistrySetup { - function test_getPools() public { + function test_getPools_Success() public { address[] memory tokens = new address[](1); tokens[0] = s_sourceTokens[0]; diff --git a/contracts/src/v0.8/ccip/test/tokenAdminRegistry/TokenAdminRegistry/TokenAdminRegistry.isAdministrator.t.sol b/contracts/src/v0.8/ccip/test/tokenAdminRegistry/TokenAdminRegistry/TokenAdminRegistry.isAdministrator.t.sol index e94a0654a7e..00555ba3ff2 100644 --- a/contracts/src/v0.8/ccip/test/tokenAdminRegistry/TokenAdminRegistry/TokenAdminRegistry.isAdministrator.t.sol +++ b/contracts/src/v0.8/ccip/test/tokenAdminRegistry/TokenAdminRegistry/TokenAdminRegistry.isAdministrator.t.sol @@ -4,7 +4,7 @@ pragma solidity ^0.8.0; import {TokenAdminRegistrySetup} from "./TokenAdminRegistrySetup.t.sol"; contract TokenAdminRegistry_isAdministrator is TokenAdminRegistrySetup { - function test_isAdministrator() public { + function test_isAdministrator_Success() public { address newAdmin = makeAddr("newAdmin"); address newToken = makeAddr("newToken"); assertFalse(s_tokenAdminRegistry.isAdministrator(newToken, newAdmin)); diff --git a/contracts/src/v0.8/ccip/test/tokenAdminRegistry/TokenAdminRegistry/TokenAdminRegistry.proposeAdministrator.t.sol b/contracts/src/v0.8/ccip/test/tokenAdminRegistry/TokenAdminRegistry/TokenAdminRegistry.proposeAdministrator.t.sol index 3d2fc0dafee..6f3ac4449c6 100644 --- a/contracts/src/v0.8/ccip/test/tokenAdminRegistry/TokenAdminRegistry/TokenAdminRegistry.proposeAdministrator.t.sol +++ b/contracts/src/v0.8/ccip/test/tokenAdminRegistry/TokenAdminRegistry/TokenAdminRegistry.proposeAdministrator.t.sol @@ -5,7 +5,7 @@ import {TokenAdminRegistry} from "../../../tokenAdminRegistry/TokenAdminRegistry import {TokenAdminRegistrySetup} from "./TokenAdminRegistrySetup.t.sol"; contract TokenAdminRegistry_proposeAdministrator is TokenAdminRegistrySetup { - function test_proposeAdministrator_module() public { + function test_proposeAdministrator_module_Success() public { vm.startPrank(s_registryModule); address newAdmin = makeAddr("newAdmin"); address newToken = makeAddr("newToken"); @@ -25,7 +25,7 @@ contract TokenAdminRegistry_proposeAdministrator is TokenAdminRegistrySetup { assertTrue(s_tokenAdminRegistry.isAdministrator(newToken, newAdmin)); } - function test_proposeAdministrator_owner() public { + function test_proposeAdministrator_owner_Success() public { address newAdmin = makeAddr("newAdmin"); address newToken = makeAddr("newToken"); @@ -42,7 +42,7 @@ contract TokenAdminRegistry_proposeAdministrator is TokenAdminRegistrySetup { assertTrue(s_tokenAdminRegistry.isAdministrator(newToken, newAdmin)); } - function test_proposeAdministrator_reRegisterWhileUnclaimed() public { + function test_proposeAdministrator_reRegisterWhileUnclaimed_Success() public { address newAdmin = makeAddr("wrongAddress"); address newToken = makeAddr("newToken"); @@ -87,7 +87,7 @@ contract TokenAdminRegistry_proposeAdministrator is TokenAdminRegistrySetup { } } - function test_RevertWhen_proposeAdministrator_OnlyRegistryModule() public { + function test_proposeAdministrator_OnlyRegistryModule_Revert() public { address newToken = makeAddr("newToken"); vm.stopPrank(); @@ -95,14 +95,14 @@ contract TokenAdminRegistry_proposeAdministrator is TokenAdminRegistrySetup { s_tokenAdminRegistry.proposeAdministrator(newToken, OWNER); } - function test_RevertWhen_proposeAdministrator_ZeroAddress() public { + function test_proposeAdministrator_ZeroAddress_Revert() public { address newToken = makeAddr("newToken"); vm.expectRevert(abi.encodeWithSelector(TokenAdminRegistry.ZeroAddress.selector)); s_tokenAdminRegistry.proposeAdministrator(newToken, address(0)); } - function test_RevertWhen_proposeAdministrator_AlreadyRegistered() public { + function test_proposeAdministrator_AlreadyRegistered_Revert() public { address newAdmin = makeAddr("newAdmin"); address newToken = makeAddr("newToken"); diff --git a/contracts/src/v0.8/ccip/test/tokenAdminRegistry/TokenAdminRegistry/TokenAdminRegistry.removeRegistryModule.t.sol b/contracts/src/v0.8/ccip/test/tokenAdminRegistry/TokenAdminRegistry/TokenAdminRegistry.removeRegistryModule.t.sol index 5f5141eb3f3..d5fde7ad5d5 100644 --- a/contracts/src/v0.8/ccip/test/tokenAdminRegistry/TokenAdminRegistry/TokenAdminRegistry.removeRegistryModule.t.sol +++ b/contracts/src/v0.8/ccip/test/tokenAdminRegistry/TokenAdminRegistry/TokenAdminRegistry.removeRegistryModule.t.sol @@ -6,7 +6,7 @@ import {TokenAdminRegistry} from "../../../tokenAdminRegistry/TokenAdminRegistry import {TokenAdminRegistrySetup} from "./TokenAdminRegistrySetup.t.sol"; contract TokenAdminRegistry_removeRegistryModule is TokenAdminRegistrySetup { - function test_removeRegistryModule() public { + function test_removeRegistryModule_Success() public { address newModule = makeAddr("newModule"); s_tokenAdminRegistry.addRegistryModule(newModule); @@ -27,7 +27,7 @@ contract TokenAdminRegistry_removeRegistryModule is TokenAdminRegistrySetup { vm.assertEq(vm.getRecordedLogs().length, 0); } - function test_RevertWhen_removeRegistryModule_OnlyOwner() public { + function test_removeRegistryModule_OnlyOwner_Revert() public { address newModule = makeAddr("newModule"); vm.stopPrank(); diff --git a/contracts/src/v0.8/ccip/test/tokenAdminRegistry/TokenAdminRegistry/TokenAdminRegistry.setPool.t.sol b/contracts/src/v0.8/ccip/test/tokenAdminRegistry/TokenAdminRegistry/TokenAdminRegistry.setPool.t.sol index 589b882dc21..51119ce30bb 100644 --- a/contracts/src/v0.8/ccip/test/tokenAdminRegistry/TokenAdminRegistry/TokenAdminRegistry.setPool.t.sol +++ b/contracts/src/v0.8/ccip/test/tokenAdminRegistry/TokenAdminRegistry/TokenAdminRegistry.setPool.t.sol @@ -6,7 +6,7 @@ import {TokenAdminRegistry} from "../../../tokenAdminRegistry/TokenAdminRegistry import {TokenAdminRegistrySetup} from "./TokenAdminRegistrySetup.t.sol"; contract TokenAdminRegistry_setPool is TokenAdminRegistrySetup { - function test_setPool() public { + function test_setPool_Success() public { address pool = makeAddr("pool"); vm.mockCall(pool, abi.encodeWithSelector(IPoolV1.isSupportedToken.selector), abi.encode(true)); @@ -24,7 +24,7 @@ contract TokenAdminRegistry_setPool is TokenAdminRegistrySetup { vm.assertEq(vm.getRecordedLogs().length, 0); } - function test_setPool_ZeroAddressRemovesPool() public { + function test_setPool_ZeroAddressRemovesPool_Success() public { address pool = makeAddr("pool"); vm.mockCall(pool, abi.encodeWithSelector(IPoolV1.isSupportedToken.selector), abi.encode(true)); s_tokenAdminRegistry.setPool(s_sourceTokens[0], pool); @@ -39,7 +39,7 @@ contract TokenAdminRegistry_setPool is TokenAdminRegistrySetup { assertEq(s_tokenAdminRegistry.getPool(s_sourceTokens[0]), address(0)); } - function test_RevertWhen_setPool_InvalidTokenPoolToken() public { + function test_setPool_InvalidTokenPoolToken_Revert() public { address pool = makeAddr("pool"); vm.mockCall(pool, abi.encodeWithSelector(IPoolV1.isSupportedToken.selector), abi.encode(false)); @@ -47,7 +47,7 @@ contract TokenAdminRegistry_setPool is TokenAdminRegistrySetup { s_tokenAdminRegistry.setPool(s_sourceTokens[0], pool); } - function test_RevertWhen_setPool_OnlyAdministrator() public { + function test_setPool_OnlyAdministrator_Revert() public { vm.stopPrank(); vm.expectRevert( diff --git a/contracts/src/v0.8/ccip/test/tokenAdminRegistry/TokenAdminRegistry/TokenAdminRegistry.transferAdminRole.t.sol b/contracts/src/v0.8/ccip/test/tokenAdminRegistry/TokenAdminRegistry/TokenAdminRegistry.transferAdminRole.t.sol index 7d0916c8093..07a10b083af 100644 --- a/contracts/src/v0.8/ccip/test/tokenAdminRegistry/TokenAdminRegistry/TokenAdminRegistry.transferAdminRole.t.sol +++ b/contracts/src/v0.8/ccip/test/tokenAdminRegistry/TokenAdminRegistry/TokenAdminRegistry.transferAdminRole.t.sol @@ -5,7 +5,7 @@ import {TokenAdminRegistry} from "../../../tokenAdminRegistry/TokenAdminRegistry import {TokenAdminRegistrySetup} from "./TokenAdminRegistrySetup.t.sol"; contract TokenAdminRegistry_transferAdminRole is TokenAdminRegistrySetup { - function test_transferAdminRole() public { + function test_transferAdminRole_Success() public { address token = s_sourceTokens[0]; address currentAdmin = s_tokenAdminRegistry.getTokenConfig(token).administrator; @@ -23,7 +23,7 @@ contract TokenAdminRegistry_transferAdminRole is TokenAdminRegistrySetup { assertEq(config.administrator, currentAdmin); } - function test_RevertWhen_transferAdminRole_OnlyAdministrator() public { + function test_transferAdminRole_OnlyAdministrator_Revert() public { vm.stopPrank(); vm.expectRevert( diff --git a/contracts/src/v0.8/ccip/test/tokenAdminRegistry/TokenPoolFactory/TokenPoolFactory.constructor.t.sol b/contracts/src/v0.8/ccip/test/tokenAdminRegistry/TokenPoolFactory/TokenPoolFactory.constructor.t.sol index 5aa79d3d164..fbba0ccbb06 100644 --- a/contracts/src/v0.8/ccip/test/tokenAdminRegistry/TokenPoolFactory/TokenPoolFactory.constructor.t.sol +++ b/contracts/src/v0.8/ccip/test/tokenAdminRegistry/TokenPoolFactory/TokenPoolFactory.constructor.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import {ITokenAdminRegistry} from "../../../interfaces/ITokenAdminRegistry.sol"; @@ -12,7 +12,7 @@ import {TokenPoolFactorySetup} from "./TokenPoolFactorySetup.t.sol"; contract TokenPoolFactory_constructor is TokenPoolFactorySetup { using Create2 for bytes32; - function test_RevertWhen_constructor() public { + function test_constructor_Revert() public { // Revert cause the tokenAdminRegistry is address(0) vm.expectRevert(TokenPoolFactory.InvalidZeroAddress.selector); new TokenPoolFactory(ITokenAdminRegistry(address(0)), RegistryModuleOwnerCustom(address(0)), address(0), address(0)); diff --git a/contracts/src/v0.8/ccip/test/tokenAdminRegistry/TokenPoolFactory/TokenPoolFactory.createTokenPool.t.sol b/contracts/src/v0.8/ccip/test/tokenAdminRegistry/TokenPoolFactory/TokenPoolFactory.createTokenPool.t.sol index 260f5322659..63106f20044 100644 --- a/contracts/src/v0.8/ccip/test/tokenAdminRegistry/TokenPoolFactory/TokenPoolFactory.createTokenPool.t.sol +++ b/contracts/src/v0.8/ccip/test/tokenAdminRegistry/TokenPoolFactory/TokenPoolFactory.createTokenPool.t.sol @@ -1,12 +1,11 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; - -import {IBurnMintERC20} from "../../../../shared/token/ERC20/IBurnMintERC20.sol"; -import {IOwner} from "../../../interfaces/IOwner.sol"; +pragma solidity 0.8.24; import {Ownable2Step} from "../../../../shared/access/Ownable2Step.sol"; +import {IBurnMintERC20} from "../../../../shared/token/ERC20/IBurnMintERC20.sol"; -import {Router} from "../../../Router.sol"; +import {Create2} from "../../../../vendor/openzeppelin-solidity/v5.0.2/contracts/utils/Create2.sol"; +import {IOwner} from "../../../interfaces/IOwner.sol"; import {RateLimiter} from "../../../libraries/RateLimiter.sol"; import {BurnFromMintTokenPool} from "../../../pools/BurnFromMintTokenPool.sol"; import {BurnMintTokenPool} from "../../../pools/BurnMintTokenPool.sol"; @@ -18,27 +17,10 @@ import {FactoryBurnMintERC20} from "../../../tokenAdminRegistry/TokenPoolFactory import {TokenPoolFactory} from "../../../tokenAdminRegistry/TokenPoolFactory/TokenPoolFactory.sol"; import {TokenPoolFactorySetup} from "./TokenPoolFactorySetup.t.sol"; -import {IERC20Metadata} from - "../../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/extensions/IERC20Metadata.sol"; -import {Create2} from "../../../../vendor/openzeppelin-solidity/v5.0.2/contracts/utils/Create2.sol"; - contract TokenPoolFactory_createTokenPool is TokenPoolFactorySetup { using Create2 for bytes32; - uint8 private constant LOCAL_TOKEN_DECIMALS = 18; - uint8 private constant REMOTE_TOKEN_DECIMALS = 6; - - address internal s_burnMintOffRamp = makeAddr("burn_mint_offRamp"); - - function setUp() public override { - TokenPoolFactorySetup.setUp(); - - Router.OffRamp[] memory offRampUpdates = new Router.OffRamp[](1); - offRampUpdates[0] = Router.OffRamp({sourceChainSelector: DEST_CHAIN_SELECTOR, offRamp: s_burnMintOffRamp}); - s_sourceRouter.applyRampUpdates(new Router.OnRamp[](0), new Router.OffRamp[](0), offRampUpdates); - } - - function test_createTokenPool_WithNoExistingTokenOnRemoteChain() public { + function test_createTokenPool_WithNoExistingTokenOnRemoteChain_Success() public { vm.startPrank(OWNER); bytes32 dynamicSalt = keccak256(abi.encodePacked(FAKE_SALT, OWNER)); @@ -47,8 +29,7 @@ contract TokenPoolFactory_createTokenPool is TokenPoolFactorySetup { Create2.computeAddress(dynamicSalt, keccak256(s_tokenInitCode), address(s_tokenPoolFactory)); // Create the constructor params for the predicted pool - bytes memory poolCreationParams = - abi.encode(predictedTokenAddress, LOCAL_TOKEN_DECIMALS, new address[](0), s_rmnProxy, s_sourceRouter); + bytes memory poolCreationParams = abi.encode(predictedTokenAddress, new address[](0), s_rmnProxy, s_sourceRouter); // Predict the address of the pool before we make the tx by using the init code and the params bytes memory predictedPoolInitCode = abi.encodePacked(s_poolInitCode, poolCreationParams); @@ -57,7 +38,7 @@ contract TokenPoolFactory_createTokenPool is TokenPoolFactorySetup { dynamicSalt.computeAddress(keccak256(predictedPoolInitCode), address(s_tokenPoolFactory)); (address tokenAddress, address poolAddress) = s_tokenPoolFactory.deployTokenAndTokenPool( - new TokenPoolFactory.RemoteTokenPoolInfo[](0), LOCAL_TOKEN_DECIMALS, s_tokenInitCode, s_poolInitCode, FAKE_SALT + new TokenPoolFactory.RemoteTokenPoolInfo[](0), s_tokenInitCode, s_poolInitCode, FAKE_SALT ); assertNotEq(address(0), tokenAddress, "Token Address should not be 0"); @@ -75,7 +56,7 @@ contract TokenPoolFactory_createTokenPool is TokenPoolFactorySetup { assertEq(IOwner(poolAddress).owner(), OWNER, "Token should be owned by the owner"); } - function test_createTokenPool_WithNoExistingRemoteContracts_predict() public { + function test_createTokenPool_WithNoExistingRemoteContracts_predict_Success() public { vm.startPrank(OWNER); bytes32 dynamicSalt = keccak256(abi.encodePacked(FAKE_SALT, OWNER)); @@ -89,9 +70,8 @@ contract TokenPoolFactory_createTokenPool is TokenPoolFactorySetup { newTokenAdminRegistry.addRegistryModule(address(newRegistryModule)); - TokenPoolFactory.RemoteChainConfig memory remoteChainConfig = TokenPoolFactory.RemoteChainConfig( - address(newTokenPoolFactory), address(s_destRouter), address(s_rmnProxy), LOCAL_TOKEN_DECIMALS - ); + TokenPoolFactory.RemoteChainConfig memory remoteChainConfig = + TokenPoolFactory.RemoteChainConfig(address(newTokenPoolFactory), address(s_destRouter), address(s_rmnProxy)); // Create an array of remote pools where nothing exists yet, but we want to predict the address for // the new pool and token on DEST_CHAIN_SELECTOR @@ -117,7 +97,6 @@ contract TokenPoolFactory_createTokenPool is TokenPoolFactorySetup { // deployed token pool using the available getter functions (address tokenAddress, address poolAddress) = s_tokenPoolFactory.deployTokenAndTokenPool( remoteTokenPools, // No existing remote pools - LOCAL_TOKEN_DECIMALS, // 18 decimal token s_tokenInitCode, // Token Init Code s_poolInitCode, // Pool Init Code FAKE_SALT // Salt @@ -135,7 +114,7 @@ contract TokenPoolFactory_createTokenPool is TokenPoolFactorySetup { // The predictedTokenAddress is NOT abi-encoded since the raw evm-address // is used in the constructor params bytes memory predictedPoolCreationParams = - abi.encode(predictedTokenAddress, LOCAL_TOKEN_DECIMALS, new address[](0), s_rmnProxy, address(s_destRouter)); + abi.encode(predictedTokenAddress, new address[](0), s_rmnProxy, address(s_destRouter)); // Take the init code and concat the destination params to it, the initCode shouldn't change bytes memory predictedPoolInitCode = abi.encodePacked(s_poolInitCode, predictedPoolCreationParams); @@ -147,7 +126,7 @@ contract TokenPoolFactory_createTokenPool is TokenPoolFactorySetup { // Assert that the address set for the remote pool is the same as the predicted address assertEq( abi.encode(predictedPoolAddress), - TokenPool(poolAddress).getRemotePools(DEST_CHAIN_SELECTOR)[0], + TokenPool(poolAddress).getRemotePool(DEST_CHAIN_SELECTOR), "Pool Address should have been predicted" ); } @@ -155,11 +134,11 @@ contract TokenPoolFactory_createTokenPool is TokenPoolFactorySetup { // On the new token pool factory, representing a destination chain, // deploy a new token and a new pool (address newTokenAddress, address newPoolAddress) = newTokenPoolFactory.deployTokenAndTokenPool( - new TokenPoolFactory.RemoteTokenPoolInfo[](0), LOCAL_TOKEN_DECIMALS, s_tokenInitCode, s_poolInitCode, FAKE_SALT + new TokenPoolFactory.RemoteTokenPoolInfo[](0), s_tokenInitCode, s_poolInitCode, FAKE_SALT ); assertEq( - TokenPool(poolAddress).getRemotePools(DEST_CHAIN_SELECTOR)[0], + TokenPool(poolAddress).getRemotePool(DEST_CHAIN_SELECTOR), abi.encode(newPoolAddress), "New Pool Address should have been deployed correctly" ); @@ -204,7 +183,7 @@ contract TokenPoolFactory_createTokenPool is TokenPoolFactorySetup { assertEq(IOwner(poolAddress).owner(), OWNER, "Pool should be controlled by the OWNER"); } - function test_createTokenPool_ExistingRemoteToken_AndPredictPool() public { + function test_createTokenPool_ExistingRemoteToken_AndPredictPool_Success() public { vm.startPrank(OWNER); bytes32 dynamicSalt = keccak256(abi.encodePacked(FAKE_SALT, OWNER)); @@ -221,9 +200,8 @@ contract TokenPoolFactory_createTokenPool is TokenPoolFactorySetup { newTokenAdminRegistry.addRegistryModule(address(newRegistryModule)); - TokenPoolFactory.RemoteChainConfig memory remoteChainConfig = TokenPoolFactory.RemoteChainConfig( - address(newTokenPoolFactory), address(s_destRouter), address(s_rmnProxy), LOCAL_TOKEN_DECIMALS - ); + TokenPoolFactory.RemoteChainConfig memory remoteChainConfig = + TokenPoolFactory.RemoteChainConfig(address(newTokenPoolFactory), address(s_destRouter), address(s_rmnProxy)); // Create an array of remote pools where nothing exists yet, but we want to predict the address for // the new pool and token on DEST_CHAIN_SELECTOR @@ -244,9 +222,8 @@ contract TokenPoolFactory_createTokenPool is TokenPoolFactorySetup { // Since the remote chain information was provided, we should be able to get the information from the newly // deployed token pool using the available getter functions - (address tokenAddress, address poolAddress) = s_tokenPoolFactory.deployTokenAndTokenPool( - remoteTokenPools, LOCAL_TOKEN_DECIMALS, s_tokenInitCode, s_poolInitCode, FAKE_SALT - ); + (address tokenAddress, address poolAddress) = + s_tokenPoolFactory.deployTokenAndTokenPool(remoteTokenPools, s_tokenInitCode, s_poolInitCode, FAKE_SALT); assertEq(address(TokenPool(poolAddress).getToken()), tokenAddress, "Token Address should have been set locally"); @@ -261,7 +238,7 @@ contract TokenPoolFactory_createTokenPool is TokenPoolFactorySetup { // The predictedTokenAddress is NOT abi-encoded since the raw evm-address // is used in the constructor params bytes memory predictedPoolCreationParams = - abi.encode(address(newRemoteToken), LOCAL_TOKEN_DECIMALS, new address[](0), s_rmnProxy, address(s_destRouter)); + abi.encode(address(newRemoteToken), new address[](0), s_rmnProxy, address(s_destRouter)); // Take the init code and concat the destination params to it, the initCode shouldn't change bytes memory predictedPoolInitCode = abi.encodePacked(s_poolInitCode, predictedPoolCreationParams); @@ -273,7 +250,7 @@ contract TokenPoolFactory_createTokenPool is TokenPoolFactorySetup { // Assert that the address set for the remote pool is the same as the predicted address assertEq( abi.encode(predictedPoolAddress), - TokenPool(poolAddress).getRemotePools(DEST_CHAIN_SELECTOR)[0], + TokenPool(poolAddress).getRemotePool(DEST_CHAIN_SELECTOR), "Pool Address should have been predicted" ); @@ -281,7 +258,6 @@ contract TokenPoolFactory_createTokenPool is TokenPoolFactorySetup { // deploy a new token and a new pool address newPoolAddress = newTokenPoolFactory.deployTokenPoolWithExistingToken( address(newRemoteToken), - LOCAL_TOKEN_DECIMALS, new TokenPoolFactory.RemoteTokenPoolInfo[](0), s_poolInitCode, FAKE_SALT, @@ -295,13 +271,13 @@ contract TokenPoolFactory_createTokenPool is TokenPoolFactorySetup { ); assertEq( - TokenPool(poolAddress).getRemotePools(DEST_CHAIN_SELECTOR)[0], + TokenPool(poolAddress).getRemotePool(DEST_CHAIN_SELECTOR), abi.encode(newPoolAddress), "New Pool Address should have been deployed correctly" ); } - function test_createTokenPool_WithRemoteTokenAndRemotePool() public { + function test_createTokenPool_WithRemoteTokenAndRemotePool_Success() public { vm.startPrank(OWNER); bytes memory RANDOM_TOKEN_ADDRESS = abi.encode(makeAddr("RANDOM_TOKEN")); @@ -314,16 +290,15 @@ contract TokenPoolFactory_createTokenPool is TokenPoolFactorySetup { DEST_CHAIN_SELECTOR, // remoteChainSelector RANDOM_POOL_ADDRESS, // remotePoolAddress type(BurnMintTokenPool).creationCode, // remotePoolInitCode - TokenPoolFactory.RemoteChainConfig(address(0), address(0), address(0), 0), // remoteChainConfig + TokenPoolFactory.RemoteChainConfig(address(0), address(0), address(0)), // remoteChainConfig TokenPoolFactory.PoolType.BURN_MINT, // poolType RANDOM_TOKEN_ADDRESS, // remoteTokenAddress "", // remoteTokenInitCode RateLimiter.Config(false, 0, 0) // rateLimiterConfig ); - (address tokenAddress, address poolAddress) = s_tokenPoolFactory.deployTokenAndTokenPool( - remoteTokenPools, LOCAL_TOKEN_DECIMALS, s_tokenInitCode, s_poolInitCode, FAKE_SALT - ); + (address tokenAddress, address poolAddress) = + s_tokenPoolFactory.deployTokenAndTokenPool(remoteTokenPools, s_tokenInitCode, s_poolInitCode, FAKE_SALT); assertNotEq(address(0), tokenAddress, "Token Address should not be 0"); assertNotEq(address(0), poolAddress, "Pool Address should not be 0"); @@ -339,7 +314,7 @@ contract TokenPoolFactory_createTokenPool is TokenPoolFactorySetup { ); assertEq( - TokenPool(poolAddress).getRemotePools(DEST_CHAIN_SELECTOR)[0], + TokenPool(poolAddress).getRemotePool(DEST_CHAIN_SELECTOR), RANDOM_POOL_ADDRESS, "Remote Pool Address should have been set" ); @@ -351,7 +326,7 @@ contract TokenPoolFactory_createTokenPool is TokenPoolFactorySetup { assertEq(IOwner(poolAddress).owner(), OWNER, "Token should be owned by the owner"); } - function test_createTokenPoolLockRelease_ExistingToken_predict() public { + function test_createTokenPoolLockRelease_ExistingToken_predict_Success() public { vm.startPrank(OWNER); // We have to create a new factory, registry module, and token admin registry to simulate the other chain @@ -364,9 +339,8 @@ contract TokenPoolFactory_createTokenPool is TokenPoolFactorySetup { newTokenAdminRegistry.addRegistryModule(address(newRegistryModule)); - TokenPoolFactory.RemoteChainConfig memory remoteChainConfig = TokenPoolFactory.RemoteChainConfig( - address(newTokenPoolFactory), address(s_destRouter), address(s_rmnProxy), LOCAL_TOKEN_DECIMALS - ); + TokenPoolFactory.RemoteChainConfig memory remoteChainConfig = + TokenPoolFactory.RemoteChainConfig(address(newTokenPoolFactory), address(s_destRouter), address(s_rmnProxy)); FactoryBurnMintERC20 newLocalToken = new FactoryBurnMintERC20("TestToken", "TEST", 18, type(uint256).max, PREMINT_AMOUNT, OWNER); @@ -395,7 +369,6 @@ contract TokenPoolFactory_createTokenPool is TokenPoolFactorySetup { // deployed token pool using the available getter functions address poolAddress = s_tokenPoolFactory.deployTokenPoolWithExistingToken( address(newLocalToken), - LOCAL_TOKEN_DECIMALS, remoteTokenPools, type(LockReleaseTokenPool).creationCode, FAKE_SALT, @@ -404,7 +377,7 @@ contract TokenPoolFactory_createTokenPool is TokenPoolFactorySetup { // Check that the pool was correctly deployed on the local chain first - // Accept the ownership which was transferred + // Accept the ownership which was transfered Ownable2Step(poolAddress).acceptOwnership(); // Ensure that the remote Token was set to the one we predicted @@ -420,7 +393,6 @@ contract TokenPoolFactory_createTokenPool is TokenPoolFactorySetup { // Deploy the Lock-Release Token Pool on the destination chain with the existing remote token (address newPoolAddress) = newTokenPoolFactory.deployTokenPoolWithExistingToken( address(newRemoteToken), - LOCAL_TOKEN_DECIMALS, new TokenPoolFactory.RemoteTokenPoolInfo[](0), // No existing remote pools type(LockReleaseTokenPool).creationCode, // Pool Init Code FAKE_SALT, // Salt @@ -428,7 +400,7 @@ contract TokenPoolFactory_createTokenPool is TokenPoolFactorySetup { ); assertEq( - LockReleaseTokenPool(poolAddress).getRemotePools(DEST_CHAIN_SELECTOR)[0], + LockReleaseTokenPool(poolAddress).getRemotePool(DEST_CHAIN_SELECTOR), abi.encode(newPoolAddress), "New Pool Address should have been deployed correctly" ); @@ -446,7 +418,7 @@ contract TokenPoolFactory_createTokenPool is TokenPoolFactorySetup { ); } - function test_createTokenPool_BurnFromMintTokenPool() public { + function test_createTokenPool_BurnFromMintTokenPool_Success() public { vm.startPrank(OWNER); bytes memory RANDOM_TOKEN_ADDRESS = abi.encode(makeAddr("RANDOM_TOKEN")); @@ -459,16 +431,15 @@ contract TokenPoolFactory_createTokenPool is TokenPoolFactorySetup { DEST_CHAIN_SELECTOR, // remoteChainSelector RANDOM_POOL_ADDRESS, // remotePoolAddress type(BurnFromMintTokenPool).creationCode, // remotePoolInitCode - TokenPoolFactory.RemoteChainConfig(address(0), address(0), address(0), 0), // remoteChainConfig + TokenPoolFactory.RemoteChainConfig(address(0), address(0), address(0)), // remoteChainConfig TokenPoolFactory.PoolType.BURN_MINT, // poolType RANDOM_TOKEN_ADDRESS, // remoteTokenAddress "", // remoteTokenInitCode RateLimiter.Config(false, 0, 0) // rateLimiterConfig ); - (address tokenAddress, address poolAddress) = s_tokenPoolFactory.deployTokenAndTokenPool( - remoteTokenPools, LOCAL_TOKEN_DECIMALS, s_tokenInitCode, s_poolInitCode, FAKE_SALT - ); + (address tokenAddress, address poolAddress) = + s_tokenPoolFactory.deployTokenAndTokenPool(remoteTokenPools, s_tokenInitCode, s_poolInitCode, FAKE_SALT); assertNotEq(address(0), tokenAddress, "Token Address should not be 0"); assertNotEq(address(0), poolAddress, "Pool Address should not be 0"); @@ -484,7 +455,7 @@ contract TokenPoolFactory_createTokenPool is TokenPoolFactorySetup { ); assertEq( - TokenPool(poolAddress).getRemotePools(DEST_CHAIN_SELECTOR)[0], + TokenPool(poolAddress).getRemotePool(DEST_CHAIN_SELECTOR), RANDOM_POOL_ADDRESS, "Remote Pool Address should have been set" ); @@ -495,112 +466,4 @@ contract TokenPoolFactory_createTokenPool is TokenPoolFactorySetup { assertEq(IOwner(poolAddress).owner(), OWNER, "Token should be owned by the owner"); } - - function test_createTokenPool_RemoteTokenHasDifferentDecimals() public { - vm.startPrank(OWNER); - bytes32 dynamicSalt = keccak256(abi.encodePacked(FAKE_SALT, OWNER)); - - // Deploy the "remote" token which has a different decimal value than the local token - FactoryBurnMintERC20 newRemoteToken = - new FactoryBurnMintERC20("TestToken", "TT", 6, type(uint256).max, PREMINT_AMOUNT, OWNER); - - // We have to create a new factory, registry module, and token admin registry to simulate the other chain - TokenAdminRegistry newTokenAdminRegistry = new TokenAdminRegistry(); - RegistryModuleOwnerCustom newRegistryModule = new RegistryModuleOwnerCustom(address(newTokenAdminRegistry)); - - // We want to deploy a new factory and Owner Module. - TokenPoolFactory newTokenPoolFactory = - new TokenPoolFactory(newTokenAdminRegistry, newRegistryModule, s_rmnProxy, address(s_destRouter)); - - newTokenAdminRegistry.addRegistryModule(address(newRegistryModule)); - - TokenPoolFactory.RemoteChainConfig memory remoteChainConfig = TokenPoolFactory.RemoteChainConfig( - address(newTokenPoolFactory), address(s_destRouter), address(s_rmnProxy), REMOTE_TOKEN_DECIMALS - ); - - // Create an array of remote pools where nothing exists yet, but we want to predict the address for - // the new pool and token on DEST_CHAIN_SELECTOR - TokenPoolFactory.RemoteTokenPoolInfo[] memory remoteTokenPools = new TokenPoolFactory.RemoteTokenPoolInfo[](1); - - // The only field that matters is DEST_CHAIN_SELECTOR because we dont want any existing token pool or token - // on the remote chain - remoteTokenPools[0] = TokenPoolFactory.RemoteTokenPoolInfo( - DEST_CHAIN_SELECTOR, // remoteChainSelector - "", // remotePoolAddress - type(BurnMintTokenPool).creationCode, // remotePoolInitCode - remoteChainConfig, // remoteChainConfig - TokenPoolFactory.PoolType.BURN_MINT, // poolType - abi.encode(address(newRemoteToken)), // remoteTokenAddress - s_tokenInitCode, // remoteTokenInitCode - RateLimiter.Config(false, 0, 0) // rateLimiterConfig - ); - - // Since the remote chain information was provided, we should be able to get the information from the newly - // deployed token pool using the available getter functions - (address tokenAddress, address poolAddress) = s_tokenPoolFactory.deployTokenAndTokenPool( - remoteTokenPools, LOCAL_TOKEN_DECIMALS, s_tokenInitCode, s_poolInitCode, FAKE_SALT - ); - - assertEq(address(TokenPool(poolAddress).getToken()), tokenAddress, "Token Address should have been set locally"); - - // Ensure that the remote Token was set to the one we predicted - assertEq( - abi.encode(address(newRemoteToken)), - TokenPool(poolAddress).getRemoteToken(DEST_CHAIN_SELECTOR), - "Token Address should have been predicted" - ); - - // Create the constructor params for the predicted pool - // The predictedTokenAddress is NOT abi-encoded since the raw evm-address - // is used in the constructor params - bytes memory predictedPoolCreationParams = - abi.encode(address(newRemoteToken), REMOTE_TOKEN_DECIMALS, new address[](0), s_rmnProxy, address(s_destRouter)); - - // Take the init code and concat the destination params to it, the initCode shouldn't change - bytes memory predictedPoolInitCode = abi.encodePacked(s_poolInitCode, predictedPoolCreationParams); - - // Predict the address of the pool on the DESTINATION chain - address predictedPoolAddress = - dynamicSalt.computeAddress(keccak256(predictedPoolInitCode), address(newTokenPoolFactory)); - - // Assert that the address set for the remote pool is the same as the predicted address - assertEq( - abi.encode(predictedPoolAddress), - TokenPool(poolAddress).getRemotePools(DEST_CHAIN_SELECTOR)[0], - "Pool Address should have been predicted" - ); - - // On the new token pool factory, representing a destination chain, - // deploy a new token and a new pool - address newPoolAddress = newTokenPoolFactory.deployTokenPoolWithExistingToken( - address(newRemoteToken), - REMOTE_TOKEN_DECIMALS, - new TokenPoolFactory.RemoteTokenPoolInfo[](0), - s_poolInitCode, - FAKE_SALT, - TokenPoolFactory.PoolType.BURN_MINT - ); - - assertEq( - abi.encode(newRemoteToken), - TokenPool(poolAddress).getRemoteToken(DEST_CHAIN_SELECTOR), - "Remote Token Address should have been set correctly" - ); - - assertEq( - TokenPool(poolAddress).getRemotePools(DEST_CHAIN_SELECTOR)[0], - abi.encode(newPoolAddress), - "New Pool Address should have been deployed correctly" - ); - - assertEq(TokenPool(poolAddress).getTokenDecimals(), LOCAL_TOKEN_DECIMALS, "Local token pool should use 18 decimals"); - - // Assert the local token has 18 decimals - assertEq(IERC20Metadata(tokenAddress).decimals(), LOCAL_TOKEN_DECIMALS, "Token Decimals should be 18"); - - // Check configs on the remote pool and remote token decimals - assertEq(TokenPool(newPoolAddress).getTokenDecimals(), REMOTE_TOKEN_DECIMALS, "Token Decimals should be 6"); - assertEq(address(TokenPool(newPoolAddress).getToken()), address(newRemoteToken), "Token Address should be set"); - assertEq(IERC20Metadata(newRemoteToken).decimals(), REMOTE_TOKEN_DECIMALS, "Token Decimals should be 6"); - } } diff --git a/contracts/src/v0.8/ccip/test/tokenAdminRegistry/TokenPoolFactory/TokenPoolFactorySetup.t.sol b/contracts/src/v0.8/ccip/test/tokenAdminRegistry/TokenPoolFactory/TokenPoolFactorySetup.t.sol index ee280dbdf76..9f78ceb9439 100644 --- a/contracts/src/v0.8/ccip/test/tokenAdminRegistry/TokenPoolFactory/TokenPoolFactorySetup.t.sol +++ b/contracts/src/v0.8/ccip/test/tokenAdminRegistry/TokenPoolFactory/TokenPoolFactorySetup.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import {Create2} from "../../../../vendor/openzeppelin-solidity/v5.0.2/contracts/utils/Create2.sol"; import {BurnMintTokenPool} from "../../../pools/BurnMintTokenPool.sol"; diff --git a/contracts/src/v0.8/ccip/tokenAdminRegistry/RegistryModuleOwnerCustom.sol b/contracts/src/v0.8/ccip/tokenAdminRegistry/RegistryModuleOwnerCustom.sol index 23014ccfc73..4392fa8c56f 100644 --- a/contracts/src/v0.8/ccip/tokenAdminRegistry/RegistryModuleOwnerCustom.sol +++ b/contracts/src/v0.8/ccip/tokenAdminRegistry/RegistryModuleOwnerCustom.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import {ITypeAndVersion} from "../../shared/interfaces/ITypeAndVersion.sol"; import {IGetCCIPAdmin} from "../interfaces/IGetCCIPAdmin.sol"; diff --git a/contracts/src/v0.8/ccip/tokenAdminRegistry/TokenAdminRegistry.sol b/contracts/src/v0.8/ccip/tokenAdminRegistry/TokenAdminRegistry.sol index 6aa3950ec6b..725bde0fbdf 100644 --- a/contracts/src/v0.8/ccip/tokenAdminRegistry/TokenAdminRegistry.sol +++ b/contracts/src/v0.8/ccip/tokenAdminRegistry/TokenAdminRegistry.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import {ITypeAndVersion} from "../../shared/interfaces/ITypeAndVersion.sol"; import {IPoolV1} from "../interfaces/IPool.sol"; diff --git a/contracts/src/v0.8/ccip/tokenAdminRegistry/TokenPoolFactory/FactoryBurnMintERC20.sol b/contracts/src/v0.8/ccip/tokenAdminRegistry/TokenPoolFactory/FactoryBurnMintERC20.sol index 97cbdb32e83..6fdba0f9b1f 100644 --- a/contracts/src/v0.8/ccip/tokenAdminRegistry/TokenPoolFactory/FactoryBurnMintERC20.sol +++ b/contracts/src/v0.8/ccip/tokenAdminRegistry/TokenPoolFactory/FactoryBurnMintERC20.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import {IGetCCIPAdmin} from "../../../ccip/interfaces/IGetCCIPAdmin.sol"; import {IOwnable} from "../../../shared/interfaces/IOwnable.sol"; diff --git a/contracts/src/v0.8/ccip/tokenAdminRegistry/TokenPoolFactory/TokenPoolFactory.sol b/contracts/src/v0.8/ccip/tokenAdminRegistry/TokenPoolFactory/TokenPoolFactory.sol index 8e036076b15..4939b19b80c 100644 --- a/contracts/src/v0.8/ccip/tokenAdminRegistry/TokenPoolFactory/TokenPoolFactory.sol +++ b/contracts/src/v0.8/ccip/tokenAdminRegistry/TokenPoolFactory/TokenPoolFactory.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; import {IOwnable} from "../../../shared/interfaces/IOwnable.sol"; import {ITypeAndVersion} from "../../../shared/interfaces/ITypeAndVersion.sol"; @@ -37,8 +37,8 @@ contract TokenPoolFactory is ITypeAndVersion { // will be predicted bytes remotePoolInitCode; // Remote pool creation code if it needs to be deployed, without constructor params // appended to the end. - RemoteChainConfig remoteChainConfig; // The addresses of the remote RMNProxy, Router, factory, and token - // decimals which are needed for determining the remote address + RemoteChainConfig remoteChainConfig; // The addresses of the remote RMNProxy, Router, and factory for determining + // the remote address PoolType poolType; // The type of pool to deploy, either Burn/Mint or Lock/Release bytes remoteTokenAddress; // EVM address for remote token. If empty, the address will be predicted bytes remoteTokenInitCode; // The init code to be deployed on the remote chain and includes constructor params @@ -50,10 +50,9 @@ contract TokenPoolFactory is ITypeAndVersion { address remotePoolFactory; // The factory contract on the remote chain which will make the deployment address remoteRouter; // The router on the remote chain address remoteRMNProxy; // The RMNProxy contract on the remote chain - uint8 remoteTokenDecimals; // The number of decimals for the token on the remote chain } - string public constant typeAndVersion = "TokenPoolFactory 1.5.1"; + string public constant typeAndVersion = "TokenPoolFactory 1.7.0-dev"; ITokenAdminRegistry private immutable i_tokenAdminRegistry; RegistryModuleOwnerCustom private immutable i_registryModuleOwnerCustom; @@ -93,8 +92,6 @@ contract TokenPoolFactory is ITypeAndVersion { /// to the msg.sender, but must be accepted in a separate transaction due to 2-step ownership transfer. /// @param remoteTokenPools An array of remote token pools info to be used in the pool's applyChainUpdates function /// or to be predicted if the pool has not been deployed yet on the remote chain - /// @param localTokenDecimals The amount of decimals to be used in the new token. Since decimals() is not part of the - /// the ERC20 standard, and thus cannot be certain to exist, the amount must be supplied via user input. /// @param tokenInitCode The creation code for the token, which includes the constructor parameters already appended /// @param tokenPoolInitCode The creation code for the token pool, without the constructor parameters appended /// @param salt The salt to be used in the create2 deployment of the token and token pool to ensure a unique address @@ -102,7 +99,6 @@ contract TokenPoolFactory is ITypeAndVersion { /// @return pool The address of the token pool that was deployed function deployTokenAndTokenPool( RemoteTokenPoolInfo[] calldata remoteTokenPools, - uint8 localTokenDecimals, bytes memory tokenInitCode, bytes calldata tokenPoolInitCode, bytes32 salt @@ -115,8 +111,7 @@ contract TokenPoolFactory is ITypeAndVersion { address token = Create2.deploy(0, salt, tokenInitCode); // Deploy the token pool - address pool = - _createTokenPool(token, localTokenDecimals, remoteTokenPools, tokenPoolInitCode, salt, PoolType.BURN_MINT); + address pool = _createTokenPool(token, remoteTokenPools, tokenPoolInitCode, salt, PoolType.BURN_MINT); // Grant the mint and burn roles to the pool for the token FactoryBurnMintERC20(token).grantMintAndBurnRoles(pool); @@ -136,15 +131,12 @@ contract TokenPoolFactory is ITypeAndVersion { /// tokenAdminRegistry manually /// @dev since the token already exists, the owner must grant the mint and burn roles to the pool manually /// @param token The address of the existing token to be used in the token pool - /// @param localTokenDecimals The amount of decimals used in the existing token. Since decimals() is not part of the - /// the ERC20 standard, and thus cannot be certain to exist, the amount must be supplied via user input. /// @param remoteTokenPools An array of remote token pools info to be used in the pool's applyChainUpdates function /// @param tokenPoolInitCode The creation code for the token pool /// @param salt The salt to be used in the create2 deployment of the token pool /// @return poolAddress The address of the token pool that was deployed function deployTokenPoolWithExistingToken( address token, - uint8 localTokenDecimals, RemoteTokenPoolInfo[] calldata remoteTokenPools, bytes calldata tokenPoolInitCode, bytes32 salt, @@ -155,7 +147,7 @@ contract TokenPoolFactory is ITypeAndVersion { salt = keccak256(abi.encodePacked(salt, msg.sender)); // create the token pool and return the address - return _createTokenPool(token, localTokenDecimals, remoteTokenPools, tokenPoolInitCode, salt, poolType); + return _createTokenPool(token, remoteTokenPools, tokenPoolInitCode, salt, poolType); } // ================================================================ @@ -170,7 +162,6 @@ contract TokenPoolFactory is ITypeAndVersion { /// @return poolAddress The address of the token pool that was deployed function _createTokenPool( address token, - uint8 localTokenDecimals, RemoteTokenPoolInfo[] calldata remoteTokenPools, bytes calldata tokenPoolInitCode, bytes32 salt, @@ -212,12 +203,10 @@ contract TokenPoolFactory is ITypeAndVersion { abi.encode(salt.computeAddress(remotePoolInitcodeHash, remoteTokenPool.remoteChainConfig.remotePoolFactory)); } - bytes[] memory remotePoolAddresses = new bytes[](1); - remotePoolAddresses[0] = remoteTokenPool.remotePoolAddress; - chainUpdates[i] = TokenPool.ChainUpdate({ remoteChainSelector: remoteTokenPool.remoteChainSelector, - remotePoolAddresses: remotePoolAddresses, + allowed: true, + remotePoolAddress: remoteTokenPool.remotePoolAddress, remoteTokenAddress: remoteTokenPool.remoteTokenAddress, outboundRateLimiterConfig: remoteTokenPool.rateLimiterConfig, inboundRateLimiterConfig: remoteTokenPool.rateLimiterConfig @@ -227,18 +216,18 @@ contract TokenPoolFactory is ITypeAndVersion { // Construct the initArgs for the token pool using the immutable contracts for CCIP on the local chain bytes memory tokenPoolInitArgs; if (poolType == PoolType.BURN_MINT) { - tokenPoolInitArgs = abi.encode(token, localTokenDecimals, new address[](0), i_rmnProxy, i_ccipRouter); + tokenPoolInitArgs = abi.encode(token, new address[](0), i_rmnProxy, i_ccipRouter); } else if (poolType == PoolType.LOCK_RELEASE) { // Lock/Release pools have an additional boolean constructor parameter that must be accounted for, acceptLiquidity, // which is set to true by default in this case. Users wishing to set it to false must deploy the pool manually. - tokenPoolInitArgs = abi.encode(token, localTokenDecimals, new address[](0), i_rmnProxy, true, i_ccipRouter); + tokenPoolInitArgs = abi.encode(token, new address[](0), i_rmnProxy, true, i_ccipRouter); } // Construct the deployment code from the initCode and the initArgs and then deploy address poolAddress = Create2.deploy(0, salt, abi.encodePacked(tokenPoolInitCode, tokenPoolInitArgs)); // Apply the chain updates to the token pool - TokenPool(poolAddress).applyChainUpdates(new uint64[](0), chainUpdates); + TokenPool(poolAddress).applyChainUpdates(chainUpdates); // Begin the 2 step ownership transfer of the token pool to the msg.sender. IOwnable(poolAddress).transferOwnership(address(msg.sender)); // 2 step ownership transfer @@ -265,13 +254,9 @@ contract TokenPoolFactory is ITypeAndVersion { return keccak256( abi.encodePacked( initCode, - // constructor(address token, uint8 localTokenDecimals, address[] allowlist, address rmnProxy, address router) + // constructor(address token, address[] allowlist, address rmnProxy, address router) abi.encode( - remoteTokenAddress, - remoteChainConfig.remoteTokenDecimals, - new address[](0), - remoteChainConfig.remoteRMNProxy, - remoteChainConfig.remoteRouter + remoteTokenAddress, new address[](0), remoteChainConfig.remoteRMNProxy, remoteChainConfig.remoteRouter ) ) ); @@ -280,14 +265,9 @@ contract TokenPoolFactory is ITypeAndVersion { return keccak256( abi.encodePacked( initCode, - // constructor(address token, uint8 localTokenDecimals, address[] allowList, address rmnProxy, bool acceptLiquidity, address router) + // constructor(address token, address[] allowList, address rmnProxy, bool acceptLiquidity, address router) abi.encode( - remoteTokenAddress, - remoteChainConfig.remoteTokenDecimals, - new address[](0), - remoteChainConfig.remoteRMNProxy, - true, - remoteChainConfig.remoteRouter + remoteTokenAddress, new address[](0), remoteChainConfig.remoteRMNProxy, true, remoteChainConfig.remoteRouter ) ) ); diff --git a/contracts/src/v0.8/keystone/BalanceReader.sol b/contracts/src/v0.8/keystone/BalanceReader.sol deleted file mode 100644 index 2efd6a84605..00000000000 --- a/contracts/src/v0.8/keystone/BalanceReader.sol +++ /dev/null @@ -1,14 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.24; - -/// @notice BalanceReader is used to read native currency balances from one or more accounts -/// using a contract method instead of an RPC "eth_getBalance" call. -contract BalanceReader { - function getNativeBalances(address[] memory addresses) public view returns (uint256[] memory) { - uint256[] memory balances = new uint256[](addresses.length); - for (uint256 i = 0; i < addresses.length; ++i) { - balances[i] = addresses[i].balance; - } - return balances; - } -} diff --git a/contracts/src/v0.8/keystone/KeystoneFeedsConsumer.sol b/contracts/src/v0.8/keystone/KeystoneFeedsConsumer.sol index 2f57a00bf04..447c979d405 100644 --- a/contracts/src/v0.8/keystone/KeystoneFeedsConsumer.sol +++ b/contracts/src/v0.8/keystone/KeystoneFeedsConsumer.sol @@ -7,7 +7,7 @@ import {OwnerIsCreator} from "../shared/access/OwnerIsCreator.sol"; import {IERC165} from "../vendor/openzeppelin-solidity/v4.8.3/contracts/interfaces/IERC165.sol"; -contract KeystoneFeedsConsumer is IReceiver, OwnerIsCreator { +contract KeystoneFeedsConsumer is IReceiver, OwnerIsCreator, IERC165 { event FeedReceived(bytes32 indexed feedId, uint224 price, uint32 timestamp); error UnauthorizedSender(address sender); @@ -101,7 +101,7 @@ contract KeystoneFeedsConsumer is IReceiver, OwnerIsCreator { return (report.Price, report.Timestamp); } - function supportsInterface(bytes4 interfaceId) public pure override returns (bool) { + function supportsInterface(bytes4 interfaceId) public pure returns (bool) { return interfaceId == type(IReceiver).interfaceId || interfaceId == type(IERC165).interfaceId; } } diff --git a/contracts/src/v0.8/keystone/KeystoneFeedsPermissionHandler.sol b/contracts/src/v0.8/keystone/KeystoneFeedsPermissionHandler.sol index 36b520bb3d1..708fdc8e692 100644 --- a/contracts/src/v0.8/keystone/KeystoneFeedsPermissionHandler.sol +++ b/contracts/src/v0.8/keystone/KeystoneFeedsPermissionHandler.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.8.19; +pragma solidity 0.8.24; import {Ownable2StepMsgSender} from "../shared/access/Ownable2StepMsgSender.sol"; @@ -10,11 +10,11 @@ abstract contract KeystoneFeedsPermissionHandler is Ownable2StepMsgSender { /// @notice Holds the details for permissions of a report /// @dev Workflow names and report names are stored as bytes to optimize for gas efficiency. struct Permission { - address forwarder; // ─────╮ The address of the forwarder (20 bytes) - bytes10 workflowName; // │ The name of the workflow in bytes10 - bytes2 reportName; // ─────╯ The name of the report in bytes2 - address workflowOwner; // ─╮ The address of the workflow owner (20 bytes) - bool isAllowed; // ────────╯ Whether the report is allowed or not (1 byte) + address forwarder; // ──────╮ The address of the forwarder (20 bytes) + bytes10 workflowName; // │ The name of the workflow in bytes10 + bytes2 reportName; // ──────╯ The name of the report in bytes2 + address workflowOwner; // ──╮ The address of the workflow owner (20 bytes) + bool isAllowed; // ─────────╯ Whether the report is allowed or not (1 byte) } /// @notice Event emitted when report permissions are set diff --git a/contracts/src/v0.8/keystone/KeystoneForwarder.sol b/contracts/src/v0.8/keystone/KeystoneForwarder.sol index 5807f042593..4a8660c4c32 100644 --- a/contracts/src/v0.8/keystone/KeystoneForwarder.sol +++ b/contracts/src/v0.8/keystone/KeystoneForwarder.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.8.19; +pragma solidity 0.8.24; import {IReceiver} from "./interfaces/IReceiver.sol"; import {IRouter} from "./interfaces/IRouter.sol"; @@ -316,15 +316,15 @@ contract KeystoneForwarder is OwnerIsCreator, ITypeAndVersion, IRouter { bytes memory rawReport ) internal pure returns (bytes32 workflowExecutionId, uint64 configId, bytes2 reportId) { // (first 32 bytes of memory contain length of the report) - // version offset 32, size 1 - // workflow_execution_id offset 33, size 32 - // timestamp offset 65, size 4 - // don_id offset 69, size 4 - // don_config_version, offset 73, size 4 - // workflow_cid offset 77, size 32 - // workflow_name offset 109, size 10 - // workflow_owner offset 119, size 20 - // report_id offset 139, size 2 + // version // offset 32, size 1 + // workflow_execution_id // offset 33, size 32 + // timestamp // offset 65, size 4 + // don_id // offset 69, size 4 + // don_config_version, // offset 73, size 4 + // workflow_cid // offset 77, size 32 + // workflow_name // offset 109, size 10 + // workflow_owner // offset 119, size 20 + // report_id // offset 139, size 2 assembly { workflowExecutionId := mload(add(rawReport, 33)) // shift right by 24 bytes to get the combined don_id and don_config_version diff --git a/contracts/src/v0.8/keystone/interfaces/IReceiver.sol b/contracts/src/v0.8/keystone/interfaces/IReceiver.sol index b18e35d6b5f..9afa1d340a3 100644 --- a/contracts/src/v0.8/keystone/interfaces/IReceiver.sol +++ b/contracts/src/v0.8/keystone/interfaces/IReceiver.sol @@ -1,11 +1,8 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; -import {IERC165} from "../../vendor/openzeppelin-solidity/v5.0.2/contracts/utils/introspection/IERC165.sol"; - /// @title IReceiver - receives keystone reports -/// @notice Implementations must support the IReceiver interface through ERC165. -interface IReceiver is IERC165 { +interface IReceiver { /// @notice Handles incoming keystone reports. /// @dev If this function call reverts, it can be retried with a higher gas /// limit. The receiver is responsible for discarding stale reports. diff --git a/contracts/src/v0.8/keystone/test/mocks/MaliciousReportReceiver.sol b/contracts/src/v0.8/keystone/test/mocks/MaliciousReportReceiver.sol index 71fb731d0ad..8f039b5f0ce 100644 --- a/contracts/src/v0.8/keystone/test/mocks/MaliciousReportReceiver.sol +++ b/contracts/src/v0.8/keystone/test/mocks/MaliciousReportReceiver.sol @@ -4,7 +4,7 @@ pragma solidity 0.8.24; import {IERC165} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/interfaces/IERC165.sol"; import {IReceiver} from "../../interfaces/IReceiver.sol"; -contract MaliciousReportReceiver is IReceiver { +contract MaliciousReportReceiver is IReceiver, IERC165 { event MessageReceived(bytes metadata, bytes[] mercuryReports); bytes public latestReport; diff --git a/contracts/src/v0.8/keystone/test/mocks/MaliciousRevertingReceiver.sol b/contracts/src/v0.8/keystone/test/mocks/MaliciousRevertingReceiver.sol index c749b50dafe..f45e95afb2c 100644 --- a/contracts/src/v0.8/keystone/test/mocks/MaliciousRevertingReceiver.sol +++ b/contracts/src/v0.8/keystone/test/mocks/MaliciousRevertingReceiver.sol @@ -6,7 +6,7 @@ import {IReceiver} from "../../interfaces/IReceiver.sol"; /// A malicious receiver that uses max allowed for ERC165 checks and consumes all gas in `onReport()` /// Causes parent Forwarder contract to revert if it doesn't handle gas tracking accurately -contract MaliciousRevertingReceiver is IReceiver { +contract MaliciousRevertingReceiver is IReceiver, IERC165 { function onReport(bytes calldata, bytes calldata) external view override { // consumes about 63/64 of all gas available uint256 targetGasRemaining = 200; diff --git a/contracts/src/v0.8/keystone/test/mocks/Receiver.sol b/contracts/src/v0.8/keystone/test/mocks/Receiver.sol index 0604a145c6b..d4005950ade 100644 --- a/contracts/src/v0.8/keystone/test/mocks/Receiver.sol +++ b/contracts/src/v0.8/keystone/test/mocks/Receiver.sol @@ -4,7 +4,7 @@ pragma solidity 0.8.24; import {IERC165} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/interfaces/IERC165.sol"; import {IReceiver} from "../../interfaces/IReceiver.sol"; -contract Receiver is IReceiver { +contract Receiver is IReceiver, IERC165 { event MessageReceived(bytes metadata, bytes[] mercuryReports); bytes public latestReport; @@ -18,7 +18,7 @@ contract Receiver is IReceiver { emit MessageReceived(metadata, mercuryReports); } - function supportsInterface(bytes4 interfaceId) public pure override returns (bool) { + function supportsInterface(bytes4 interfaceId) public pure returns (bool) { return interfaceId == type(IReceiver).interfaceId || interfaceId == type(IERC165).interfaceId; } } diff --git a/contracts/src/v0.8/l2ep/README.md b/contracts/src/v0.8/l2ep/README.md index 83eb6fe9372..21a537c4fe7 100644 --- a/contracts/src/v0.8/l2ep/README.md +++ b/contracts/src/v0.8/l2ep/README.md @@ -11,8 +11,7 @@ Emergency Protocol (L2EP) contracts. It is organized as follows: ## The `/dev` Folder -The `/dev` folder contains contracts that has not yet been audited. -The root folder contains subfolders for each chain that +The `/dev` folder contains subfolders for each chain that has an L2EP solution implemented for it (e.g. `/scroll`, `/arbitrum`, `/optimism`). It also contains a subfolder named `/interfaces`, which stores shared interface types between all the supported diff --git a/contracts/src/v0.8/l2ep/CrossDomainDelegateForwarder.sol b/contracts/src/v0.8/l2ep/dev/CrossDomainDelegateForwarder.sol similarity index 100% rename from contracts/src/v0.8/l2ep/CrossDomainDelegateForwarder.sol rename to contracts/src/v0.8/l2ep/dev/CrossDomainDelegateForwarder.sol diff --git a/contracts/src/v0.8/l2ep/CrossDomainForwarder.sol b/contracts/src/v0.8/l2ep/dev/CrossDomainForwarder.sol similarity index 100% rename from contracts/src/v0.8/l2ep/CrossDomainForwarder.sol rename to contracts/src/v0.8/l2ep/dev/CrossDomainForwarder.sol diff --git a/contracts/src/v0.8/l2ep/CrossDomainOwnable.sol b/contracts/src/v0.8/l2ep/dev/CrossDomainOwnable.sol similarity index 96% rename from contracts/src/v0.8/l2ep/CrossDomainOwnable.sol rename to contracts/src/v0.8/l2ep/dev/CrossDomainOwnable.sol index 7e1c0d1adb9..c85762b6fca 100644 --- a/contracts/src/v0.8/l2ep/CrossDomainOwnable.sol +++ b/contracts/src/v0.8/l2ep/dev/CrossDomainOwnable.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; -import {ConfirmedOwner} from "../shared/access/ConfirmedOwner.sol"; +import {ConfirmedOwner} from "../../shared/access/ConfirmedOwner.sol"; import {ICrossDomainOwnable} from "./interfaces/ICrossDomainOwnable.sol"; /** diff --git a/contracts/src/v0.8/l2ep/Flags.sol b/contracts/src/v0.8/l2ep/dev/Flags.sol similarity index 95% rename from contracts/src/v0.8/l2ep/Flags.sol rename to contracts/src/v0.8/l2ep/dev/Flags.sol index 2ac35be4ce7..2dc030d7d59 100644 --- a/contracts/src/v0.8/l2ep/Flags.sol +++ b/contracts/src/v0.8/l2ep/dev/Flags.sol @@ -1,9 +1,9 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.24; -import {SimpleReadAccessController} from "../shared/access/SimpleReadAccessController.sol"; -import {AccessControllerInterface} from "../shared/interfaces/AccessControllerInterface.sol"; -import {ITypeAndVersion} from "../shared/interfaces/ITypeAndVersion.sol"; +import {SimpleReadAccessController} from "../../shared/access/SimpleReadAccessController.sol"; +import {AccessControllerInterface} from "../../shared/interfaces/AccessControllerInterface.sol"; +import {ITypeAndVersion} from "../../shared/interfaces/ITypeAndVersion.sol"; /* dev dependencies - to be re/moved after audit */ import {IFlags} from "./interfaces/IFlags.sol"; diff --git a/contracts/src/v0.8/l2ep/arbitrum/ArbitrumCrossDomainForwarder.sol b/contracts/src/v0.8/l2ep/dev/arbitrum/ArbitrumCrossDomainForwarder.sol similarity index 89% rename from contracts/src/v0.8/l2ep/arbitrum/ArbitrumCrossDomainForwarder.sol rename to contracts/src/v0.8/l2ep/dev/arbitrum/ArbitrumCrossDomainForwarder.sol index e3ef117d23e..0db657ee71c 100644 --- a/contracts/src/v0.8/l2ep/arbitrum/ArbitrumCrossDomainForwarder.sol +++ b/contracts/src/v0.8/l2ep/dev/arbitrum/ArbitrumCrossDomainForwarder.sol @@ -1,15 +1,15 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.24; -import {ITypeAndVersion} from "../../shared/interfaces/ITypeAndVersion.sol"; +import {ITypeAndVersion} from "../../../shared/interfaces/ITypeAndVersion.sol"; // solhint-disable-next-line no-unused-import import {IForwarder} from "../interfaces/IForwarder.sol"; import {CrossDomainForwarder} from "../CrossDomainForwarder.sol"; import {CrossDomainOwnable} from "../CrossDomainOwnable.sol"; -import {AddressAliasHelper} from "../../vendor/arb-bridge-eth/v0.8.0-custom/contracts/libraries/AddressAliasHelper.sol"; -import {Address} from "../../vendor/openzeppelin-solidity/v4.7.3/contracts/utils/Address.sol"; +import {AddressAliasHelper} from "../../../vendor/arb-bridge-eth/v0.8.0-custom/contracts/libraries/AddressAliasHelper.sol"; +import {Address} from "../../../vendor/openzeppelin-solidity/v4.7.3/contracts/utils/Address.sol"; /** * @title ArbitrumCrossDomainForwarder - L1 xDomain account representation diff --git a/contracts/src/v0.8/l2ep/arbitrum/ArbitrumCrossDomainGovernor.sol b/contracts/src/v0.8/l2ep/dev/arbitrum/ArbitrumCrossDomainGovernor.sol similarity index 93% rename from contracts/src/v0.8/l2ep/arbitrum/ArbitrumCrossDomainGovernor.sol rename to contracts/src/v0.8/l2ep/dev/arbitrum/ArbitrumCrossDomainGovernor.sol index f5ed8d7a9d2..60d9cc52666 100644 --- a/contracts/src/v0.8/l2ep/arbitrum/ArbitrumCrossDomainGovernor.sol +++ b/contracts/src/v0.8/l2ep/dev/arbitrum/ArbitrumCrossDomainGovernor.sol @@ -2,14 +2,14 @@ pragma solidity ^0.8.0; // solhint-disable-next-line no-unused-import -import {ITypeAndVersion} from "../../shared/interfaces/ITypeAndVersion.sol"; +import {ITypeAndVersion} from "../../../shared/interfaces/ITypeAndVersion.sol"; // solhint-disable-next-line no-unused-import import {IForwarder} from "../interfaces/IForwarder.sol"; import {IDelegateForwarder} from "../interfaces/IDelegateForwarder.sol"; import {ArbitrumCrossDomainForwarder} from "./ArbitrumCrossDomainForwarder.sol"; -import {Address} from "../../vendor/openzeppelin-solidity/v4.7.3/contracts/utils/Address.sol"; +import {Address} from "../../../vendor/openzeppelin-solidity/v4.7.3/contracts/utils/Address.sol"; /** * @title ArbitrumCrossDomainGovernor - L1 xDomain account representation (with delegatecall support) for Arbitrum diff --git a/contracts/src/v0.8/l2ep/arbitrum/ArbitrumSequencerUptimeFeed.sol b/contracts/src/v0.8/l2ep/dev/arbitrum/ArbitrumSequencerUptimeFeed.sol similarity index 94% rename from contracts/src/v0.8/l2ep/arbitrum/ArbitrumSequencerUptimeFeed.sol rename to contracts/src/v0.8/l2ep/dev/arbitrum/ArbitrumSequencerUptimeFeed.sol index 1ba6b9b54b3..678bef3a853 100644 --- a/contracts/src/v0.8/l2ep/arbitrum/ArbitrumSequencerUptimeFeed.sol +++ b/contracts/src/v0.8/l2ep/dev/arbitrum/ArbitrumSequencerUptimeFeed.sol @@ -1,14 +1,14 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.24; -import {AddressAliasHelper} from "../../vendor/arb-bridge-eth/v0.8.0-custom/contracts/libraries/AddressAliasHelper.sol"; -import {AggregatorInterface} from "../../shared/interfaces/AggregatorInterface.sol"; -import {AggregatorV3Interface} from "../../shared/interfaces/AggregatorV3Interface.sol"; -import {AggregatorV2V3Interface} from "../../shared/interfaces/AggregatorV2V3Interface.sol"; -import {ITypeAndVersion} from "../../shared/interfaces/ITypeAndVersion.sol"; +import {AddressAliasHelper} from "../../../vendor/arb-bridge-eth/v0.8.0-custom/contracts/libraries/AddressAliasHelper.sol"; +import {AggregatorInterface} from "../../../shared/interfaces/AggregatorInterface.sol"; +import {AggregatorV3Interface} from "../../../shared/interfaces/AggregatorV3Interface.sol"; +import {AggregatorV2V3Interface} from "../../../shared/interfaces/AggregatorV2V3Interface.sol"; +import {ITypeAndVersion} from "../../../shared/interfaces/ITypeAndVersion.sol"; import {IFlags} from "../interfaces/IFlags.sol"; import {ISequencerUptimeFeed} from "../interfaces/ISequencerUptimeFeed.sol"; -import {SimpleReadAccessController} from "../../shared/access/SimpleReadAccessController.sol"; +import {SimpleReadAccessController} from "../../../shared/access/SimpleReadAccessController.sol"; /** * @title ArbitrumSequencerUptimeFeed - L2 sequencer uptime status aggregator diff --git a/contracts/src/v0.8/l2ep/arbitrum/ArbitrumValidator.sol b/contracts/src/v0.8/l2ep/dev/arbitrum/ArbitrumValidator.sol similarity index 95% rename from contracts/src/v0.8/l2ep/arbitrum/ArbitrumValidator.sol rename to contracts/src/v0.8/l2ep/dev/arbitrum/ArbitrumValidator.sol index 3d30f38981c..05f9349eb62 100644 --- a/contracts/src/v0.8/l2ep/arbitrum/ArbitrumValidator.sol +++ b/contracts/src/v0.8/l2ep/dev/arbitrum/ArbitrumValidator.sol @@ -1,17 +1,17 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.24; -import {AggregatorValidatorInterface} from "../../shared/interfaces/AggregatorValidatorInterface.sol"; -import {ITypeAndVersion} from "../../shared/interfaces/ITypeAndVersion.sol"; -import {AccessControllerInterface} from "../../shared/interfaces/AccessControllerInterface.sol"; -import {SimpleWriteAccessController} from "../../shared/access/SimpleWriteAccessController.sol"; +import {AggregatorValidatorInterface} from "../../../shared/interfaces/AggregatorValidatorInterface.sol"; +import {ITypeAndVersion} from "../../../shared/interfaces/ITypeAndVersion.sol"; +import {AccessControllerInterface} from "../../../shared/interfaces/AccessControllerInterface.sol"; +import {SimpleWriteAccessController} from "../../../shared/access/SimpleWriteAccessController.sol"; /* ./dev dependencies - to be moved from ./dev after audit */ import {ISequencerUptimeFeed} from "../interfaces/ISequencerUptimeFeed.sol"; import {IArbitrumDelayedInbox} from "../interfaces/IArbitrumDelayedInbox.sol"; -import {AddressAliasHelper} from "../../vendor/arb-bridge-eth/v0.8.0-custom/contracts/libraries/AddressAliasHelper.sol"; -import {ArbSys} from "../../vendor/@arbitrum/nitro-contracts/src/precompiles/ArbSys.sol"; -import {Address} from "../../vendor/openzeppelin-solidity/v4.7.3/contracts/utils/Address.sol"; +import {AddressAliasHelper} from "../../../vendor/arb-bridge-eth/v0.8.0-custom/contracts/libraries/AddressAliasHelper.sol"; +import {ArbSys} from "../../../vendor/@arbitrum/nitro-contracts/src/precompiles/ArbSys.sol"; +import {Address} from "../../../vendor/openzeppelin-solidity/v4.7.3/contracts/utils/Address.sol"; /** * @title ArbitrumValidator - makes xDomain L2 Flags contract call (using L2 xDomain Forwarder contract) diff --git a/contracts/src/v0.8/l2ep/interfaces/IArbitrumDelayedInbox.sol b/contracts/src/v0.8/l2ep/dev/interfaces/IArbitrumDelayedInbox.sol similarity index 84% rename from contracts/src/v0.8/l2ep/interfaces/IArbitrumDelayedInbox.sol rename to contracts/src/v0.8/l2ep/dev/interfaces/IArbitrumDelayedInbox.sol index 802ec06b168..e18efd65ad2 100644 --- a/contracts/src/v0.8/l2ep/interfaces/IArbitrumDelayedInbox.sol +++ b/contracts/src/v0.8/l2ep/dev/interfaces/IArbitrumDelayedInbox.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; -import {IInbox} from "../../vendor/arb-bridge-eth/v0.8.0-custom/contracts/bridge/interfaces/IInbox.sol"; +import {IInbox} from "../../../vendor/arb-bridge-eth/v0.8.0-custom/contracts/bridge/interfaces/IInbox.sol"; /** * @notice This interface extends Arbitrum's IInbox interface to include diff --git a/contracts/src/v0.8/l2ep/interfaces/ICrossDomainOwnable.sol b/contracts/src/v0.8/l2ep/dev/interfaces/ICrossDomainOwnable.sol similarity index 100% rename from contracts/src/v0.8/l2ep/interfaces/ICrossDomainOwnable.sol rename to contracts/src/v0.8/l2ep/dev/interfaces/ICrossDomainOwnable.sol diff --git a/contracts/src/v0.8/l2ep/interfaces/IDelegateForwarder.sol b/contracts/src/v0.8/l2ep/dev/interfaces/IDelegateForwarder.sol similarity index 100% rename from contracts/src/v0.8/l2ep/interfaces/IDelegateForwarder.sol rename to contracts/src/v0.8/l2ep/dev/interfaces/IDelegateForwarder.sol diff --git a/contracts/src/v0.8/l2ep/interfaces/IFlags.sol b/contracts/src/v0.8/l2ep/dev/interfaces/IFlags.sol similarity index 100% rename from contracts/src/v0.8/l2ep/interfaces/IFlags.sol rename to contracts/src/v0.8/l2ep/dev/interfaces/IFlags.sol diff --git a/contracts/src/v0.8/l2ep/interfaces/IForwarder.sol b/contracts/src/v0.8/l2ep/dev/interfaces/IForwarder.sol similarity index 100% rename from contracts/src/v0.8/l2ep/interfaces/IForwarder.sol rename to contracts/src/v0.8/l2ep/dev/interfaces/IForwarder.sol diff --git a/contracts/src/v0.8/l2ep/interfaces/ISequencerUptimeFeed.sol b/contracts/src/v0.8/l2ep/dev/interfaces/ISequencerUptimeFeed.sol similarity index 100% rename from contracts/src/v0.8/l2ep/interfaces/ISequencerUptimeFeed.sol rename to contracts/src/v0.8/l2ep/dev/interfaces/ISequencerUptimeFeed.sol diff --git a/contracts/src/v0.8/l2ep/optimism/OptimismCrossDomainForwarder.sol b/contracts/src/v0.8/l2ep/dev/optimism/OptimismCrossDomainForwarder.sol similarity index 91% rename from contracts/src/v0.8/l2ep/optimism/OptimismCrossDomainForwarder.sol rename to contracts/src/v0.8/l2ep/dev/optimism/OptimismCrossDomainForwarder.sol index f2b4fafc32d..1d037886960 100644 --- a/contracts/src/v0.8/l2ep/optimism/OptimismCrossDomainForwarder.sol +++ b/contracts/src/v0.8/l2ep/dev/optimism/OptimismCrossDomainForwarder.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.24; -import {ITypeAndVersion} from "../../shared/interfaces/ITypeAndVersion.sol"; +import {ITypeAndVersion} from "../../../shared/interfaces/ITypeAndVersion.sol"; // solhint-disable-next-line no-unused-import import {IForwarder} from "../interfaces/IForwarder.sol"; @@ -9,8 +9,8 @@ import {IForwarder} from "../interfaces/IForwarder.sol"; import {CrossDomainForwarder} from "../CrossDomainForwarder.sol"; import {CrossDomainOwnable} from "../CrossDomainOwnable.sol"; -import {iOVM_CrossDomainMessenger} from "../../vendor/@eth-optimism/contracts/v0.4.7/contracts/optimistic-ethereum/iOVM/bridge/messaging/iOVM_CrossDomainMessenger.sol"; -import {Address} from "../../vendor/openzeppelin-solidity/v4.7.3/contracts/utils/Address.sol"; +import {iOVM_CrossDomainMessenger} from "../../../vendor/@eth-optimism/contracts/v0.4.7/contracts/optimistic-ethereum/iOVM/bridge/messaging/iOVM_CrossDomainMessenger.sol"; +import {Address} from "../../../vendor/openzeppelin-solidity/v4.7.3/contracts/utils/Address.sol"; /** * @title OptimismCrossDomainForwarder - L1 xDomain account representation diff --git a/contracts/src/v0.8/l2ep/optimism/OptimismCrossDomainGovernor.sol b/contracts/src/v0.8/l2ep/dev/optimism/OptimismCrossDomainGovernor.sol similarity index 91% rename from contracts/src/v0.8/l2ep/optimism/OptimismCrossDomainGovernor.sol rename to contracts/src/v0.8/l2ep/dev/optimism/OptimismCrossDomainGovernor.sol index 61bed5a6903..6a41bd98f03 100644 --- a/contracts/src/v0.8/l2ep/optimism/OptimismCrossDomainGovernor.sol +++ b/contracts/src/v0.8/l2ep/dev/optimism/OptimismCrossDomainGovernor.sol @@ -7,8 +7,8 @@ import {IForwarder} from "../interfaces/IForwarder.sol"; import {OptimismCrossDomainForwarder} from "./OptimismCrossDomainForwarder.sol"; -import {iOVM_CrossDomainMessenger} from "../../vendor/@eth-optimism/contracts/v0.4.7/contracts/optimistic-ethereum/iOVM/bridge/messaging/iOVM_CrossDomainMessenger.sol"; -import {Address} from "../../vendor/openzeppelin-solidity/v4.7.3/contracts/utils/Address.sol"; +import {iOVM_CrossDomainMessenger} from "../../../vendor/@eth-optimism/contracts/v0.4.7/contracts/optimistic-ethereum/iOVM/bridge/messaging/iOVM_CrossDomainMessenger.sol"; +import {Address} from "../../../vendor/openzeppelin-solidity/v4.7.3/contracts/utils/Address.sol"; /** * @title OptimismCrossDomainGovernor - L1 xDomain account representation (with delegatecall support) for Optimism diff --git a/contracts/src/v0.8/l2ep/optimism/OptimismSequencerUptimeFeed.sol b/contracts/src/v0.8/l2ep/dev/optimism/OptimismSequencerUptimeFeed.sol similarity index 94% rename from contracts/src/v0.8/l2ep/optimism/OptimismSequencerUptimeFeed.sol rename to contracts/src/v0.8/l2ep/dev/optimism/OptimismSequencerUptimeFeed.sol index b160fe46155..0e6f9c52f22 100644 --- a/contracts/src/v0.8/l2ep/optimism/OptimismSequencerUptimeFeed.sol +++ b/contracts/src/v0.8/l2ep/dev/optimism/OptimismSequencerUptimeFeed.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.19; -import {BaseSequencerUptimeFeed} from "../base/BaseSequencerUptimeFeed.sol"; +import {BaseSequencerUptimeFeed} from "../shared/BaseSequencerUptimeFeed.sol"; import {IL2CrossDomainMessenger} from "@eth-optimism/contracts/L2/messaging/IL2CrossDomainMessenger.sol"; diff --git a/contracts/src/v0.8/l2ep/optimism/OptimismValidator.sol b/contracts/src/v0.8/l2ep/dev/optimism/OptimismValidator.sol similarity index 97% rename from contracts/src/v0.8/l2ep/optimism/OptimismValidator.sol rename to contracts/src/v0.8/l2ep/dev/optimism/OptimismValidator.sol index 97c202dcd88..cf5222f017e 100644 --- a/contracts/src/v0.8/l2ep/optimism/OptimismValidator.sol +++ b/contracts/src/v0.8/l2ep/dev/optimism/OptimismValidator.sol @@ -3,7 +3,7 @@ pragma solidity ^0.8.19; import {ISequencerUptimeFeed} from "./../interfaces/ISequencerUptimeFeed.sol"; -import {BaseValidator} from "../base/BaseValidator.sol"; +import {BaseValidator} from "../shared/BaseValidator.sol"; import {IL1CrossDomainMessenger} from "@eth-optimism/contracts/L1/messaging/IL1CrossDomainMessenger.sol"; diff --git a/contracts/src/v0.8/l2ep/scroll/ScrollCrossDomainForwarder.sol b/contracts/src/v0.8/l2ep/dev/scroll/ScrollCrossDomainForwarder.sol similarity index 94% rename from contracts/src/v0.8/l2ep/scroll/ScrollCrossDomainForwarder.sol rename to contracts/src/v0.8/l2ep/dev/scroll/ScrollCrossDomainForwarder.sol index 35e8b4827d3..c70bc794afb 100644 --- a/contracts/src/v0.8/l2ep/scroll/ScrollCrossDomainForwarder.sol +++ b/contracts/src/v0.8/l2ep/dev/scroll/ScrollCrossDomainForwarder.sol @@ -1,14 +1,14 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.24; -import {ITypeAndVersion} from "../../shared/interfaces/ITypeAndVersion.sol"; +import {ITypeAndVersion} from "../../../shared/interfaces/ITypeAndVersion.sol"; import {IForwarder} from "../interfaces/IForwarder.sol"; import {CrossDomainForwarder} from "../CrossDomainForwarder.sol"; import {CrossDomainOwnable} from "../CrossDomainOwnable.sol"; import {IScrollMessenger} from "@scroll-tech/contracts/libraries/IScrollMessenger.sol"; -import {Address} from "../../vendor/openzeppelin-solidity/v4.7.3/contracts/utils/Address.sol"; +import {Address} from "../../../vendor/openzeppelin-solidity/v4.7.3/contracts/utils/Address.sol"; /// @title ScrollCrossDomainForwarder - L1 xDomain account representation /// @notice L2 Contract which receives messages from a specific L1 address and transparently forwards them to the destination. diff --git a/contracts/src/v0.8/l2ep/scroll/ScrollCrossDomainGovernor.sol b/contracts/src/v0.8/l2ep/dev/scroll/ScrollCrossDomainGovernor.sol similarity index 96% rename from contracts/src/v0.8/l2ep/scroll/ScrollCrossDomainGovernor.sol rename to contracts/src/v0.8/l2ep/dev/scroll/ScrollCrossDomainGovernor.sol index 7170cc2e491..dae621e9b08 100644 --- a/contracts/src/v0.8/l2ep/scroll/ScrollCrossDomainGovernor.sol +++ b/contracts/src/v0.8/l2ep/dev/scroll/ScrollCrossDomainGovernor.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.24; -import {ITypeAndVersion} from "../../shared/interfaces/ITypeAndVersion.sol"; +import {ITypeAndVersion} from "../../../shared/interfaces/ITypeAndVersion.sol"; import {IDelegateForwarder} from "../interfaces/IDelegateForwarder.sol"; // solhint-disable-next-line no-unused-import import {IForwarder} from "../interfaces/IForwarder.sol"; @@ -10,7 +10,7 @@ import {CrossDomainForwarder} from "../CrossDomainForwarder.sol"; import {CrossDomainOwnable} from "../CrossDomainOwnable.sol"; import {IScrollMessenger} from "@scroll-tech/contracts/libraries/IScrollMessenger.sol"; -import {Address} from "../../vendor/openzeppelin-solidity/v4.7.3/contracts/utils/Address.sol"; +import {Address} from "../../../vendor/openzeppelin-solidity/v4.7.3/contracts/utils/Address.sol"; /// @title ScrollCrossDomainGovernor - L1 xDomain account representation (with delegatecall support) for Scroll /// @notice L2 Contract which receives messages from a specific L1 address and transparently forwards them to the destination. diff --git a/contracts/src/v0.8/l2ep/scroll/ScrollSequencerUptimeFeed.sol b/contracts/src/v0.8/l2ep/dev/scroll/ScrollSequencerUptimeFeed.sol similarity index 94% rename from contracts/src/v0.8/l2ep/scroll/ScrollSequencerUptimeFeed.sol rename to contracts/src/v0.8/l2ep/dev/scroll/ScrollSequencerUptimeFeed.sol index 9c0c22290f2..40f2941aa69 100644 --- a/contracts/src/v0.8/l2ep/scroll/ScrollSequencerUptimeFeed.sol +++ b/contracts/src/v0.8/l2ep/dev/scroll/ScrollSequencerUptimeFeed.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.24; -import {BaseSequencerUptimeFeed} from "../base/BaseSequencerUptimeFeed.sol"; +import {BaseSequencerUptimeFeed} from "../shared/BaseSequencerUptimeFeed.sol"; import {IL2ScrollMessenger} from "@scroll-tech/contracts/L2/IL2ScrollMessenger.sol"; diff --git a/contracts/src/v0.8/l2ep/scroll/ScrollValidator.sol b/contracts/src/v0.8/l2ep/dev/scroll/ScrollValidator.sol similarity index 97% rename from contracts/src/v0.8/l2ep/scroll/ScrollValidator.sol rename to contracts/src/v0.8/l2ep/dev/scroll/ScrollValidator.sol index 0eda14d0adc..b009c80fdfd 100644 --- a/contracts/src/v0.8/l2ep/scroll/ScrollValidator.sol +++ b/contracts/src/v0.8/l2ep/dev/scroll/ScrollValidator.sol @@ -3,7 +3,7 @@ pragma solidity 0.8.24; import {ISequencerUptimeFeed} from "../interfaces/ISequencerUptimeFeed.sol"; -import {BaseValidator} from "../base/BaseValidator.sol"; +import {BaseValidator} from "../shared/BaseValidator.sol"; import {IL1MessageQueue} from "@scroll-tech/contracts/L1/rollup/IL1MessageQueue.sol"; import {IL1ScrollMessenger} from "@scroll-tech/contracts/L1/IL1ScrollMessenger.sol"; diff --git a/contracts/src/v0.8/l2ep/base/BaseSequencerUptimeFeed.sol b/contracts/src/v0.8/l2ep/dev/shared/BaseSequencerUptimeFeed.sol similarity index 88% rename from contracts/src/v0.8/l2ep/base/BaseSequencerUptimeFeed.sol rename to contracts/src/v0.8/l2ep/dev/shared/BaseSequencerUptimeFeed.sol index 81fcb11ca95..15c20504569 100644 --- a/contracts/src/v0.8/l2ep/base/BaseSequencerUptimeFeed.sol +++ b/contracts/src/v0.8/l2ep/dev/shared/BaseSequencerUptimeFeed.sol @@ -1,13 +1,13 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.19; -import {ITypeAndVersion} from "../../shared/interfaces/ITypeAndVersion.sol"; -import {AggregatorInterface} from "../../shared/interfaces/AggregatorInterface.sol"; -import {AggregatorV3Interface} from "../../shared/interfaces/AggregatorV3Interface.sol"; -import {AggregatorV2V3Interface} from "../../shared/interfaces/AggregatorV2V3Interface.sol"; +import {ITypeAndVersion} from "../../../shared/interfaces/ITypeAndVersion.sol"; +import {AggregatorInterface} from "../../../shared/interfaces/AggregatorInterface.sol"; +import {AggregatorV3Interface} from "../../../shared/interfaces/AggregatorV3Interface.sol"; +import {AggregatorV2V3Interface} from "../../../shared/interfaces/AggregatorV2V3Interface.sol"; import {ISequencerUptimeFeed} from "./../interfaces/ISequencerUptimeFeed.sol"; -import {SimpleReadAccessController} from "../../shared/access/SimpleReadAccessController.sol"; +import {SimpleReadAccessController} from "../../../shared/access/SimpleReadAccessController.sol"; /// @title L2 sequencer uptime status aggregator /// @notice L2 contract that receives status updates from a specific L1 address, @@ -59,7 +59,7 @@ abstract contract BaseSequencerUptimeFeed is /// @param l1SenderAddress Address of the L1 contract that is permissioned to call this contract /// @param initialStatus The initial status of the feed constructor(address l1SenderAddress, bool initialStatus) { - // We need to allow l1SenderAddress to be zero because this contract is deployed first + // We neet to allow l1SenderAddress to be zero because this contract is deployed first // After deploying the validator contract, this contract will be updated with the correct L1 sender address _setL1Sender(l1SenderAddress); @@ -81,9 +81,9 @@ abstract contract BaseSequencerUptimeFeed is /// @notice Set the allowed L1 sender for this contract to a new L1 sender /// @dev Can be disabled by setting the L1 sender as `address(0)`. Accessible only by owner. - /// @param newSender new L1 sender that will be allowed to call `updateStatus` on this contract - function transferL1Sender(address newSender) external virtual onlyOwner { - _setL1Sender(newSender); + /// @param to new L1 sender that will be allowed to call `updateStatus` on this contract + function transferL1Sender(address to) external virtual onlyOwner { + _setL1Sender(to); } /// @notice internal method that stores the L1 sender @@ -164,10 +164,13 @@ abstract contract BaseSequencerUptimeFeed is return s_rounds[uint80(roundId)].startedAt; } - /// @notice Record a new status and timestamp if it has changed since the last round. - /// @dev This function will revert if not called from `l1Sender` via the L1->L2 messenger. - /// @param status Sequencer status - /// @param timestamp Block timestamp of status update + /** + * @notice Record a new status and timestamp if it has changed since the last round. + * @dev This function will revert if not called from `l1Sender` via the L1->L2 messenger. + * + * @param status Sequencer status + * @param timestamp Block timestamp of status update + */ function updateStatus(bool status, uint64 timestamp) external override { _validateSender(s_l1Sender); diff --git a/contracts/src/v0.8/l2ep/base/BaseValidator.sol b/contracts/src/v0.8/l2ep/dev/shared/BaseValidator.sol similarity index 84% rename from contracts/src/v0.8/l2ep/base/BaseValidator.sol rename to contracts/src/v0.8/l2ep/dev/shared/BaseValidator.sol index 4f9c6912a00..33df388972f 100644 --- a/contracts/src/v0.8/l2ep/base/BaseValidator.sol +++ b/contracts/src/v0.8/l2ep/dev/shared/BaseValidator.sol @@ -1,10 +1,10 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.19; -import {AggregatorValidatorInterface} from "../../shared/interfaces/AggregatorValidatorInterface.sol"; -import {ITypeAndVersion} from "../../shared/interfaces/ITypeAndVersion.sol"; +import {AggregatorValidatorInterface} from "../../../shared/interfaces/AggregatorValidatorInterface.sol"; +import {ITypeAndVersion} from "../../../shared/interfaces/ITypeAndVersion.sol"; -import {SimpleWriteAccessController} from "../../shared/access/SimpleWriteAccessController.sol"; +import {SimpleWriteAccessController} from "../../../shared/access/SimpleWriteAccessController.sol"; abstract contract BaseValidator is SimpleWriteAccessController, AggregatorValidatorInterface, ITypeAndVersion { /// @notice emitted when gas cost to spend on L2 is updated @@ -24,7 +24,7 @@ abstract contract BaseValidator is SimpleWriteAccessController, AggregatorValida uint32 internal s_gasLimit; /// @param l1CrossDomainMessengerAddress address the L1CrossDomainMessenger contract address - /// @param l2UptimeFeedAddr the address of the L2 SequencerUptimeFeed contract address + /// @param l2UptimeFeedAddr the address of the SequencerUptimeFeed contract address /// @param gasLimit the gasLimit to use for sending a message from L1 to L2 constructor(address l1CrossDomainMessengerAddress, address l2UptimeFeedAddr, uint32 gasLimit) { if (l1CrossDomainMessengerAddress == address(0)) { diff --git a/contracts/src/v0.8/l2ep/zksync/ZKSyncSequencerUptimeFeed.sol b/contracts/src/v0.8/l2ep/dev/zksync/ZKSyncSequencerUptimeFeed.sol similarity index 82% rename from contracts/src/v0.8/l2ep/zksync/ZKSyncSequencerUptimeFeed.sol rename to contracts/src/v0.8/l2ep/dev/zksync/ZKSyncSequencerUptimeFeed.sol index e464cc7407d..0074a0277d1 100644 --- a/contracts/src/v0.8/l2ep/zksync/ZKSyncSequencerUptimeFeed.sol +++ b/contracts/src/v0.8/l2ep/dev/zksync/ZKSyncSequencerUptimeFeed.sol @@ -1,9 +1,9 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.19; -import {BaseSequencerUptimeFeed} from "../base/BaseSequencerUptimeFeed.sol"; +import {BaseSequencerUptimeFeed} from "../shared/BaseSequencerUptimeFeed.sol"; -import {AddressAliasHelper} from "../../vendor/arb-bridge-eth/v0.8.0-custom/contracts/libraries/AddressAliasHelper.sol"; +import {AddressAliasHelper} from "../../../vendor/arb-bridge-eth/v0.8.0-custom/contracts/libraries/AddressAliasHelper.sol"; /// @title ZKSyncSequencerUptimeFeed - L2 sequencer uptime status aggregator /// @notice L2 contract that receives status updates from a specific L1 address, diff --git a/contracts/src/v0.8/l2ep/zksync/ZKSyncValidator.sol b/contracts/src/v0.8/l2ep/dev/zksync/ZKSyncValidator.sol similarity index 98% rename from contracts/src/v0.8/l2ep/zksync/ZKSyncValidator.sol rename to contracts/src/v0.8/l2ep/dev/zksync/ZKSyncValidator.sol index 39ba0cd839a..10f68ce286d 100644 --- a/contracts/src/v0.8/l2ep/zksync/ZKSyncValidator.sol +++ b/contracts/src/v0.8/l2ep/dev/zksync/ZKSyncValidator.sol @@ -3,7 +3,7 @@ pragma solidity ^0.8.19; import {ISequencerUptimeFeed} from "./../interfaces/ISequencerUptimeFeed.sol"; -import {BaseValidator} from "../base/BaseValidator.sol"; +import {BaseValidator} from "../shared/BaseValidator.sol"; import {IBridgehub, L2TransactionRequestDirect} from "@zksync/contracts/l1-contracts/contracts/bridgehub/IBridgehub.sol"; diff --git a/contracts/src/v0.8/l2ep/test/mocks/MockBaseSequencerUptimeFeed.sol b/contracts/src/v0.8/l2ep/test/mocks/MockBaseSequencerUptimeFeed.sol deleted file mode 100644 index 50d852faa45..00000000000 --- a/contracts/src/v0.8/l2ep/test/mocks/MockBaseSequencerUptimeFeed.sol +++ /dev/null @@ -1,25 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.24; - -import {BaseSequencerUptimeFeed} from "../../base/BaseSequencerUptimeFeed.sol"; - -contract MockBaseSequencerUptimeFeed is BaseSequencerUptimeFeed { - string public constant override typeAndVersion = "MockSequencerUptimeFeed 1.1.0-dev"; - - /// @dev this will be used for internal testing - bool private s_validateSenderShouldPass; - - constructor( - address l1SenderAddress, - bool initialStatus, - bool validateSenderShouldPass - ) BaseSequencerUptimeFeed(l1SenderAddress, initialStatus) { - s_validateSenderShouldPass = validateSenderShouldPass; - } - - function _validateSender(address /* l1Sender */) internal view override { - if (!s_validateSenderShouldPass) { - revert InvalidSender(); - } - } -} diff --git a/contracts/src/v0.8/l2ep/test/mocks/MockBaseValidator.sol b/contracts/src/v0.8/l2ep/test/mocks/MockBaseValidator.sol deleted file mode 100644 index d23efb48656..00000000000 --- a/contracts/src/v0.8/l2ep/test/mocks/MockBaseValidator.sol +++ /dev/null @@ -1,23 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.24; - -import {BaseValidator} from "../../base/BaseValidator.sol"; - -contract MockBaseValidator is BaseValidator { - string public constant override typeAndVersion = "MockValidator 1.1.0-dev"; - - constructor( - address l1CrossDomainMessengerAddress, - address l2UptimeFeedAddr, - uint32 gasLimit - ) BaseValidator(l1CrossDomainMessengerAddress, l2UptimeFeedAddr, gasLimit) {} - - function validate( - uint256 /* previousRoundId */, - int256 /* previousAnswer */, - uint256 /* currentRoundId */, - int256 /* currentAnswer */ - ) external view override checkAccess returns (bool) { - return true; - } -} diff --git a/contracts/src/v0.8/l2ep/test/v1_0_0/arbitrum/ArbitrumCrossDomainForwarder.t.sol b/contracts/src/v0.8/l2ep/test/v1_0_0/arbitrum/ArbitrumCrossDomainForwarder.t.sol index e0a76a2b37a..cff9b953e2e 100644 --- a/contracts/src/v0.8/l2ep/test/v1_0_0/arbitrum/ArbitrumCrossDomainForwarder.t.sol +++ b/contracts/src/v0.8/l2ep/test/v1_0_0/arbitrum/ArbitrumCrossDomainForwarder.t.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.24; -import {ArbitrumCrossDomainForwarder} from "../../../arbitrum/ArbitrumCrossDomainForwarder.sol"; +import {ArbitrumCrossDomainForwarder} from "../../../dev/arbitrum/ArbitrumCrossDomainForwarder.sol"; import {Greeter} from "../../../../tests/Greeter.sol"; import {L2EPTest} from "../L2EPTest.t.sol"; diff --git a/contracts/src/v0.8/l2ep/test/v1_0_0/arbitrum/ArbitrumCrossDomainGovernor.t.sol b/contracts/src/v0.8/l2ep/test/v1_0_0/arbitrum/ArbitrumCrossDomainGovernor.t.sol index 746da3d1cef..610f49f16c4 100644 --- a/contracts/src/v0.8/l2ep/test/v1_0_0/arbitrum/ArbitrumCrossDomainGovernor.t.sol +++ b/contracts/src/v0.8/l2ep/test/v1_0_0/arbitrum/ArbitrumCrossDomainGovernor.t.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.24; -import {ArbitrumCrossDomainGovernor} from "../../../arbitrum/ArbitrumCrossDomainGovernor.sol"; +import {ArbitrumCrossDomainGovernor} from "../../../dev/arbitrum/ArbitrumCrossDomainGovernor.sol"; import {Greeter} from "../../../../tests/Greeter.sol"; import {L2EPTest} from "../L2EPTest.t.sol"; diff --git a/contracts/src/v0.8/l2ep/test/v1_0_0/arbitrum/ArbitrumSequencerUptimeFeed.t.sol b/contracts/src/v0.8/l2ep/test/v1_0_0/arbitrum/ArbitrumSequencerUptimeFeed.t.sol index deaa81977b7..e308ead3432 100644 --- a/contracts/src/v0.8/l2ep/test/v1_0_0/arbitrum/ArbitrumSequencerUptimeFeed.t.sol +++ b/contracts/src/v0.8/l2ep/test/v1_0_0/arbitrum/ArbitrumSequencerUptimeFeed.t.sol @@ -2,10 +2,10 @@ pragma solidity 0.8.24; import {SimpleWriteAccessController} from "../../../../shared/access/SimpleWriteAccessController.sol"; -import {ArbitrumSequencerUptimeFeed} from "../../../arbitrum/ArbitrumSequencerUptimeFeed.sol"; +import {ArbitrumSequencerUptimeFeed} from "../../../dev/arbitrum/ArbitrumSequencerUptimeFeed.sol"; import {MockAggregatorV2V3} from "../../mocks/MockAggregatorV2V3.sol"; import {FeedConsumer} from "../../../../tests/FeedConsumer.sol"; -import {Flags} from "../../../Flags.sol"; +import {Flags} from "../../../dev/Flags.sol"; import {L2EPTest} from "../L2EPTest.t.sol"; contract ArbitrumSequencerUptimeFeedTest is L2EPTest { diff --git a/contracts/src/v0.8/l2ep/test/v1_0_0/arbitrum/ArbitrumValidator.t.sol b/contracts/src/v0.8/l2ep/test/v1_0_0/arbitrum/ArbitrumValidator.t.sol index 95278e644b1..ab872991749 100644 --- a/contracts/src/v0.8/l2ep/test/v1_0_0/arbitrum/ArbitrumValidator.t.sol +++ b/contracts/src/v0.8/l2ep/test/v1_0_0/arbitrum/ArbitrumValidator.t.sol @@ -4,8 +4,8 @@ pragma solidity 0.8.24; import {AccessControllerInterface} from "../../../../shared/interfaces/AccessControllerInterface.sol"; import {SimpleWriteAccessController} from "../../../../shared/access/SimpleWriteAccessController.sol"; -import {ArbitrumSequencerUptimeFeed} from "../../../arbitrum/ArbitrumSequencerUptimeFeed.sol"; -import {ArbitrumValidator} from "../../../arbitrum/ArbitrumValidator.sol"; +import {ArbitrumSequencerUptimeFeed} from "../../../dev/arbitrum/ArbitrumSequencerUptimeFeed.sol"; +import {ArbitrumValidator} from "../../../dev/arbitrum/ArbitrumValidator.sol"; import {MockArbitrumInbox} from "../../../../tests/MockArbitrumInbox.sol"; import {MockAggregatorV2V3} from "../../mocks/MockAggregatorV2V3.sol"; import {L2EPTest} from "../L2EPTest.t.sol"; diff --git a/contracts/src/v0.8/l2ep/test/v1_0_0/optimism/OptimismCrossDomainForwarder.t.sol b/contracts/src/v0.8/l2ep/test/v1_0_0/optimism/OptimismCrossDomainForwarder.t.sol index 28d70fa35a5..c0e82ab8d5e 100644 --- a/contracts/src/v0.8/l2ep/test/v1_0_0/optimism/OptimismCrossDomainForwarder.t.sol +++ b/contracts/src/v0.8/l2ep/test/v1_0_0/optimism/OptimismCrossDomainForwarder.t.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.24; -import {OptimismCrossDomainForwarder} from "../../../optimism/OptimismCrossDomainForwarder.sol"; +import {OptimismCrossDomainForwarder} from "../../../dev/optimism/OptimismCrossDomainForwarder.sol"; import {MockOVMCrossDomainMessenger} from "../../mocks/optimism/MockOVMCrossDomainMessenger.sol"; import {Greeter} from "../../../../tests/Greeter.sol"; import {L2EPTest} from "../L2EPTest.t.sol"; diff --git a/contracts/src/v0.8/l2ep/test/v1_0_0/optimism/OptimismCrossDomainGovernor.t.sol b/contracts/src/v0.8/l2ep/test/v1_0_0/optimism/OptimismCrossDomainGovernor.t.sol index 57f79124512..8f8fb9d7e7c 100644 --- a/contracts/src/v0.8/l2ep/test/v1_0_0/optimism/OptimismCrossDomainGovernor.t.sol +++ b/contracts/src/v0.8/l2ep/test/v1_0_0/optimism/OptimismCrossDomainGovernor.t.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.24; -import {OptimismCrossDomainGovernor} from "../../../optimism/OptimismCrossDomainGovernor.sol"; +import {OptimismCrossDomainGovernor} from "../../../dev/optimism/OptimismCrossDomainGovernor.sol"; import {MockOVMCrossDomainMessenger} from "../../mocks/optimism/MockOVMCrossDomainMessenger.sol"; import {Greeter} from "../../../../tests/Greeter.sol"; import {L2EPTest} from "../L2EPTest.t.sol"; diff --git a/contracts/src/v0.8/l2ep/test/v1_0_0/optimism/OptimismSequencerUptimeFeed.t.sol b/contracts/src/v0.8/l2ep/test/v1_0_0/optimism/OptimismSequencerUptimeFeed.t.sol index 34010c313e8..eec9657ac14 100644 --- a/contracts/src/v0.8/l2ep/test/v1_0_0/optimism/OptimismSequencerUptimeFeed.t.sol +++ b/contracts/src/v0.8/l2ep/test/v1_0_0/optimism/OptimismSequencerUptimeFeed.t.sol @@ -3,37 +3,31 @@ pragma solidity 0.8.24; import {MockOptimismL1CrossDomainMessenger} from "../../../../tests/MockOptimismL1CrossDomainMessenger.sol"; import {MockOptimismL2CrossDomainMessenger} from "../../../../tests/MockOptimismL2CrossDomainMessenger.sol"; -import {OptimismSequencerUptimeFeed} from "../../../optimism/OptimismSequencerUptimeFeed.sol"; -import {BaseSequencerUptimeFeed} from "../../../base/BaseSequencerUptimeFeed.sol"; +import {OptimismSequencerUptimeFeed} from "../../../dev/optimism/OptimismSequencerUptimeFeed.sol"; +import {BaseSequencerUptimeFeed} from "../../../dev/shared/BaseSequencerUptimeFeed.sol"; +import {FeedConsumer} from "../../../../tests/FeedConsumer.sol"; import {L2EPTest} from "../L2EPTest.t.sol"; -contract OptimismSequencerUptimeFeed_TestWrapper is OptimismSequencerUptimeFeed { - constructor( - address l1SenderAddress, - address l2CrossDomainMessengerAddr, - bool initialStatus - ) OptimismSequencerUptimeFeed(l1SenderAddress, l2CrossDomainMessengerAddr, initialStatus) {} - - /// @notice Exposes the internal `_validateSender` function for testing - function validateSenderTestWrapper(address l1Sender) external view { - super._validateSender(l1Sender); - } -} - -contract OptimismSequencerUptimeFeed_Setup is L2EPTest { - event AnswerUpdated(int256 indexed current, uint256 indexed roundId, uint256 updatedAt); +contract OptimismSequencerUptimeFeedTest is L2EPTest { + /// Constants + uint256 internal constant GAS_USED_DEVIATION = 100; /// L2EP contracts MockOptimismL1CrossDomainMessenger internal s_mockOptimismL1CrossDomainMessenger; MockOptimismL2CrossDomainMessenger internal s_mockOptimismL2CrossDomainMessenger; - OptimismSequencerUptimeFeed_TestWrapper internal s_optimismSequencerUptimeFeed; + OptimismSequencerUptimeFeed internal s_optimismSequencerUptimeFeed; + + /// Events + event UpdateIgnored(bool latestStatus, uint64 latestTimestamp, bool incomingStatus, uint64 incomingTimestamp); + event AnswerUpdated(int256 indexed current, uint256 indexed roundId, uint256 updatedAt); + event RoundUpdated(int256 status, uint64 updatedAt); /// Setup function setUp() public { - // Deploy contracts + // Deploys contracts s_mockOptimismL1CrossDomainMessenger = new MockOptimismL1CrossDomainMessenger(); s_mockOptimismL2CrossDomainMessenger = new MockOptimismL2CrossDomainMessenger(); - s_optimismSequencerUptimeFeed = new OptimismSequencerUptimeFeed_TestWrapper( + s_optimismSequencerUptimeFeed = new OptimismSequencerUptimeFeed( s_l1OwnerAddr, address(s_mockOptimismL2CrossDomainMessenger), false @@ -44,14 +38,12 @@ contract OptimismSequencerUptimeFeed_Setup is L2EPTest { } } -contract OptimismSequencerUptimeFeed_Constructor is OptimismSequencerUptimeFeed_Setup { - /// @notice Tests the initial state of the contract - function test_Constructor_InitialState() public { +contract OptimismSequencerUptimeFeed_Constructor is OptimismSequencerUptimeFeedTest { + /// @notice it should have been deployed with the correct initial state + function test_InitialState() public { // Sets msg.sender and tx.origin to a valid address vm.startPrank(s_l1OwnerAddr, s_l1OwnerAddr); - new OptimismSequencerUptimeFeed_TestWrapper(s_l1OwnerAddr, address(s_mockOptimismL2CrossDomainMessenger), false); - // Checks L1 sender address actualL1Addr = s_optimismSequencerUptimeFeed.l1Sender(); assertEq(actualL1Addr, s_l1OwnerAddr); @@ -63,33 +55,267 @@ contract OptimismSequencerUptimeFeed_Constructor is OptimismSequencerUptimeFeed_ } } -contract OptimismSequencerUptimeFeed_ValidateSender is OptimismSequencerUptimeFeed_Setup { - /// @notice Reverts if called by an address that is not the L2 Cross Domain Messenger - function test_ValidateSender_RevertWhen_SenderIsNotL2CrossDomainMessengerAddr() public { - address l2MessengerAddr = address(s_mockOptimismL2CrossDomainMessenger); - // Sets msg.sender to a different address - vm.startPrank(s_strangerAddr, l2MessengerAddr); +contract OptimismSequencerUptimeFeed_UpdateStatus is OptimismSequencerUptimeFeedTest { + /// @notice it should revert if called by an address that is not the L2 Cross Domain Messenger + function test_RevertIfNotL2CrossDomainMessengerAddr() public { + // Sets msg.sender and tx.origin to an unauthorized address + vm.startPrank(s_strangerAddr, s_strangerAddr); + // Tries to update the status from an unauthorized account vm.expectRevert(BaseSequencerUptimeFeed.InvalidSender.selector); - s_optimismSequencerUptimeFeed.validateSenderTestWrapper(s_l1OwnerAddr); + s_optimismSequencerUptimeFeed.updateStatus(true, uint64(1)); } - /// @notice Reverts if the L1 sender address is not the L1 Cross Domain Messenger Sender - function test_ValidateSender_RevertWhen_L1CrossDomainMessengerAddrIsNotL1SenderAddr() public { + /// @notice it should revert if called by an address that is not the L2 Cross Domain Messenger and is not the L1 sender + function test_RevertIfNotL2CrossDomainMessengerAddrAndNotL1SenderAddr() public { // Sets msg.sender and tx.origin to an unauthorized address + vm.startPrank(s_strangerAddr, s_strangerAddr); + + // Sets mock sender in mock L2 messenger contract + s_mockOptimismL2CrossDomainMessenger.setSender(s_strangerAddr); + + // Tries to update the status from an unauthorized account + vm.expectRevert(BaseSequencerUptimeFeed.InvalidSender.selector); + s_optimismSequencerUptimeFeed.updateStatus(true, uint64(1)); + } + + /// @notice it should update status when status has not changed and incoming timestamp is the same as latest + function test_UpdateStatusWhenNoChange() public { + // Sets msg.sender and tx.origin to a valid address address l2MessengerAddr = address(s_mockOptimismL2CrossDomainMessenger); vm.startPrank(l2MessengerAddr, l2MessengerAddr); - vm.expectRevert(BaseSequencerUptimeFeed.InvalidSender.selector); - s_optimismSequencerUptimeFeed.validateSenderTestWrapper(s_strangerAddr); + // Fetches the latest timestamp + uint256 timestamp = s_optimismSequencerUptimeFeed.latestTimestamp(); + + // Submits a status update + vm.expectEmit(); + emit AnswerUpdated(1, 2, timestamp); + s_optimismSequencerUptimeFeed.updateStatus(true, uint64(timestamp)); + assertEq(s_optimismSequencerUptimeFeed.latestAnswer(), 1); + assertEq(s_optimismSequencerUptimeFeed.latestTimestamp(), uint64(timestamp)); + + // Stores the current round data before updating it + ( + uint80 roundIdBeforeUpdate, + int256 answerBeforeUpdate, + uint256 startedAtBeforeUpdate, + , + uint80 answeredInRoundBeforeUpdate + ) = s_optimismSequencerUptimeFeed.latestRoundData(); + + // Submit another status update with the same status + vm.expectEmit(); + emit RoundUpdated(1, uint64(block.timestamp)); + s_optimismSequencerUptimeFeed.updateStatus(true, uint64(timestamp + 200)); + assertEq(s_optimismSequencerUptimeFeed.latestAnswer(), 1); + assertEq(s_optimismSequencerUptimeFeed.latestTimestamp(), uint64(timestamp)); + + // Stores the current round data after updating it + ( + uint80 roundIdAfterUpdate, + int256 answerAfterUpdate, + uint256 startedAtAfterUpdate, + uint256 updatedAtAfterUpdate, + uint80 answeredInRoundAfterUpdate + ) = s_optimismSequencerUptimeFeed.latestRoundData(); + + // Verifies the latest round data has been properly updated + assertEq(roundIdAfterUpdate, roundIdBeforeUpdate); + assertEq(answerAfterUpdate, answerBeforeUpdate); + assertEq(startedAtAfterUpdate, startedAtBeforeUpdate); + assertEq(answeredInRoundAfterUpdate, answeredInRoundBeforeUpdate); + assertEq(updatedAtAfterUpdate, block.timestamp); + } + + /// @notice it should update status when status has changed and incoming timestamp is newer than the latest + function test_UpdateStatusWhenStatusChangeAndTimeChange() public { + // Sets msg.sender and tx.origin to a valid address + address l2MessengerAddr = address(s_mockOptimismL2CrossDomainMessenger); + vm.startPrank(l2MessengerAddr, l2MessengerAddr); + + // Submits a status update + uint256 timestamp = s_optimismSequencerUptimeFeed.latestTimestamp(); + vm.expectEmit(); + emit AnswerUpdated(1, 2, timestamp); + s_optimismSequencerUptimeFeed.updateStatus(true, uint64(timestamp)); + assertEq(s_optimismSequencerUptimeFeed.latestAnswer(), 1); + assertEq(s_optimismSequencerUptimeFeed.latestTimestamp(), uint64(timestamp)); + + // Submit another status update, different status, newer timestamp should update + timestamp = timestamp + 200; + vm.expectEmit(); + emit AnswerUpdated(0, 3, timestamp); + s_optimismSequencerUptimeFeed.updateStatus(false, uint64(timestamp)); + assertEq(s_optimismSequencerUptimeFeed.latestAnswer(), 0); + assertEq(s_optimismSequencerUptimeFeed.latestTimestamp(), uint64(timestamp)); + } + + /// @notice it should update status when status has changed and incoming timestamp is the same as latest + function test_UpdateStatusWhenStatusChangeAndNoTimeChange() public { + // Sets msg.sender and tx.origin to a valid address + address l2MessengerAddr = address(s_mockOptimismL2CrossDomainMessenger); + vm.startPrank(l2MessengerAddr, l2MessengerAddr); + + // Fetches the latest timestamp + uint256 timestamp = s_optimismSequencerUptimeFeed.latestTimestamp(); + + // Submits a status update + vm.expectEmit(); + emit AnswerUpdated(1, 2, timestamp); + s_optimismSequencerUptimeFeed.updateStatus(true, uint64(timestamp)); + assertEq(s_optimismSequencerUptimeFeed.latestAnswer(), 1); + assertEq(s_optimismSequencerUptimeFeed.latestTimestamp(), uint64(timestamp)); + + // Submit another status update, different status, same timestamp should update + vm.expectEmit(); + emit AnswerUpdated(0, 3, timestamp); + s_optimismSequencerUptimeFeed.updateStatus(false, uint64(timestamp)); + assertEq(s_optimismSequencerUptimeFeed.latestAnswer(), 0); + assertEq(s_optimismSequencerUptimeFeed.latestTimestamp(), uint64(timestamp)); + } + + /// @notice it should ignore out-of-order updates + function test_IgnoreOutOfOrderUpdates() public { + // Sets msg.sender and tx.origin to a valid address + address l2MessengerAddr = address(s_mockOptimismL2CrossDomainMessenger); + vm.startPrank(l2MessengerAddr, l2MessengerAddr); + + // Submits a status update + uint256 timestamp = s_optimismSequencerUptimeFeed.latestTimestamp() + 10000; + vm.expectEmit(); + emit AnswerUpdated(1, 2, timestamp); + s_optimismSequencerUptimeFeed.updateStatus(true, uint64(timestamp)); + assertEq(s_optimismSequencerUptimeFeed.latestAnswer(), 1); + assertEq(s_optimismSequencerUptimeFeed.latestTimestamp(), uint64(timestamp)); + + // Update with different status, but stale timestamp, should be ignored + timestamp = timestamp - 1000; + vm.expectEmit(false, false, false, false); + emit UpdateIgnored(true, 0, true, 0); // arguments are dummy values + // TODO: how can we check that an AnswerUpdated event was NOT emitted + s_optimismSequencerUptimeFeed.updateStatus(false, uint64(timestamp)); } +} - /// @notice Updates status when status has changed and incoming timestamp is the same as the latest - function test_ValidateSender_UpdateStatusWhen_StatusChangeAndNoTimeChange() public { +contract OptimismSequencerUptimeFeed_AggregatorV3Interface is OptimismSequencerUptimeFeedTest { + /// @notice it should return valid answer from getRoundData and latestRoundData + function test_AggregatorV3Interface() public { // Sets msg.sender and tx.origin to a valid address address l2MessengerAddr = address(s_mockOptimismL2CrossDomainMessenger); vm.startPrank(l2MessengerAddr, l2MessengerAddr); - s_optimismSequencerUptimeFeed.validateSenderTestWrapper(s_l1OwnerAddr); + // Defines helper variables + uint80 roundId; + int256 answer; + uint256 startedAt; + uint256 updatedAt; + uint80 answeredInRound; + + // Checks initial state + (roundId, answer, startedAt, updatedAt, answeredInRound) = s_optimismSequencerUptimeFeed.latestRoundData(); + assertEq(roundId, 1); + assertEq(answer, 0); + assertEq(answeredInRound, roundId); + assertEq(startedAt, updatedAt); + + // Submits status update with different status and newer timestamp, should update + uint256 timestamp = startedAt + 1000; + s_optimismSequencerUptimeFeed.updateStatus(true, uint64(timestamp)); + (roundId, answer, startedAt, updatedAt, answeredInRound) = s_optimismSequencerUptimeFeed.getRoundData(2); + assertEq(roundId, 2); + assertEq(answer, 1); + assertEq(answeredInRound, roundId); + assertEq(startedAt, timestamp); + assertLe(updatedAt, startedAt); + + // Saves round 2 data + uint80 roundId2 = roundId; + int256 answer2 = answer; + uint256 startedAt2 = startedAt; + uint256 updatedAt2 = updatedAt; + uint80 answeredInRound2 = answeredInRound; + + // Checks that last round is still returning the correct data + (roundId, answer, startedAt, updatedAt, answeredInRound) = s_optimismSequencerUptimeFeed.getRoundData(1); + assertEq(roundId, 1); + assertEq(answer, 0); + assertEq(answeredInRound, roundId); + assertEq(startedAt, updatedAt); + + // Assert latestRoundData corresponds to latest round id + (roundId, answer, startedAt, updatedAt, answeredInRound) = s_optimismSequencerUptimeFeed.latestRoundData(); + assertEq(roundId2, roundId); + assertEq(answer2, answer); + assertEq(startedAt2, startedAt); + assertEq(updatedAt2, updatedAt); + assertEq(answeredInRound2, answeredInRound); + } + + /// @notice it should revert from #getRoundData when round does not yet exist (future roundId) + function test_RevertGetRoundDataWhenRoundDoesNotExistYet() public { + // Sets msg.sender and tx.origin to a valid address + vm.startPrank(s_l1OwnerAddr, s_l1OwnerAddr); + + // Gets data from a round that has not happened yet + vm.expectRevert(BaseSequencerUptimeFeed.NoDataPresent.selector); + s_optimismSequencerUptimeFeed.getRoundData(2); + } + + /// @notice it should revert from #getAnswer when round does not yet exist (future roundId) + function test_RevertGetAnswerWhenRoundDoesNotExistYet() public { + // Sets msg.sender and tx.origin to a valid address + vm.startPrank(s_l1OwnerAddr, s_l1OwnerAddr); + + // Gets data from a round that has not happened yet + vm.expectRevert(BaseSequencerUptimeFeed.NoDataPresent.selector); + s_optimismSequencerUptimeFeed.getAnswer(2); + } + + /// @notice it should revert from #getTimestamp when round does not yet exist (future roundId) + function test_RevertGetTimestampWhenRoundDoesNotExistYet() public { + // Sets msg.sender and tx.origin to a valid address + vm.startPrank(s_l1OwnerAddr, s_l1OwnerAddr); + + // Gets data from a round that has not happened yet + vm.expectRevert(BaseSequencerUptimeFeed.NoDataPresent.selector); + s_optimismSequencerUptimeFeed.getTimestamp(2); + } +} + +contract OptimismSequencerUptimeFeed_ProtectReadsOnAggregatorV2V3InterfaceFunctions is OptimismSequencerUptimeFeedTest { + /// @notice it should disallow reads on AggregatorV2V3Interface functions when consuming contract is not whitelisted + function test_AggregatorV2V3InterfaceDisallowReadsIfConsumingContractIsNotWhitelisted() public { + // Deploys a FeedConsumer contract + FeedConsumer feedConsumer = new FeedConsumer(address(s_optimismSequencerUptimeFeed)); + + // Sanity - consumer is not whitelisted + assertEq(s_optimismSequencerUptimeFeed.checkEnabled(), true); + assertEq(s_optimismSequencerUptimeFeed.hasAccess(address(feedConsumer), abi.encode("")), false); + + // Asserts reads are not possible from consuming contract + vm.expectRevert("No access"); + feedConsumer.latestAnswer(); + vm.expectRevert("No access"); + feedConsumer.latestRoundData(); + } + + /// @notice it should allow reads on AggregatorV2V3Interface functions when consuming contract is whitelisted + function test_AggregatorV2V3InterfaceAllowReadsIfConsumingContractIsWhitelisted() public { + // Deploys a FeedConsumer contract + FeedConsumer feedConsumer = new FeedConsumer(address(s_optimismSequencerUptimeFeed)); + + // Whitelist consumer + s_optimismSequencerUptimeFeed.addAccess(address(feedConsumer)); + + // Sanity - consumer is whitelisted + assertEq(s_optimismSequencerUptimeFeed.checkEnabled(), true); + assertEq(s_optimismSequencerUptimeFeed.hasAccess(address(feedConsumer), abi.encode("")), true); + + // Asserts reads are possible from consuming contract + (uint80 roundId, int256 answer, , , ) = feedConsumer.latestRoundData(); + assertEq(feedConsumer.latestAnswer(), 0); + assertEq(roundId, 1); + assertEq(answer, 0); } } diff --git a/contracts/src/v0.8/l2ep/test/v1_0_0/optimism/OptimismValidator.t.sol b/contracts/src/v0.8/l2ep/test/v1_0_0/optimism/OptimismValidator.t.sol index 48ff1f7778d..59395bf5d8b 100644 --- a/contracts/src/v0.8/l2ep/test/v1_0_0/optimism/OptimismValidator.t.sol +++ b/contracts/src/v0.8/l2ep/test/v1_0_0/optimism/OptimismValidator.t.sol @@ -1,15 +1,15 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.24; -import {ISequencerUptimeFeed} from "../../../interfaces/ISequencerUptimeFeed.sol"; +import {ISequencerUptimeFeed} from "../../../dev/interfaces/ISequencerUptimeFeed.sol"; import {MockOptimismL1CrossDomainMessenger} from "../../../../tests/MockOptimismL1CrossDomainMessenger.sol"; import {MockOptimismL2CrossDomainMessenger} from "../../../../tests/MockOptimismL2CrossDomainMessenger.sol"; -import {OptimismSequencerUptimeFeed} from "../../../optimism/OptimismSequencerUptimeFeed.sol"; -import {OptimismValidator} from "../../../optimism/OptimismValidator.sol"; +import {OptimismSequencerUptimeFeed} from "../../../dev/optimism/OptimismSequencerUptimeFeed.sol"; +import {OptimismValidator} from "../../../dev/optimism/OptimismValidator.sol"; import {L2EPTest} from "../L2EPTest.t.sol"; -contract OptimismValidator_Setup is L2EPTest { +contract OptimismValidatorTest is L2EPTest { /// Helper constants address internal constant L2_SEQ_STATUS_RECORDER_ADDRESS = 0x491B1dDA0A8fa069bbC1125133A975BF4e85a91b; uint32 internal constant INIT_GAS_LIMIT = 1900000; @@ -42,16 +42,26 @@ contract OptimismValidator_Setup is L2EPTest { } } -contract OptimismValidator_Validate is OptimismValidator_Setup { +contract OptimismValidator_SetGasLimit is OptimismValidatorTest { + /// @notice it correctly updates the gas limit + function test_CorrectlyUpdatesTheGasLimit() public { + uint32 newGasLimit = 2000000; + assertEq(s_optimismValidator.getGasLimit(), INIT_GAS_LIMIT); + s_optimismValidator.setGasLimit(newGasLimit); + assertEq(s_optimismValidator.getGasLimit(), newGasLimit); + } +} + +contract OptimismValidator_Validate is OptimismValidatorTest { /// @notice it reverts if called by account with no access - function test_Validate_RevertWhen_CalledByAccountWithNoAccess() public { + function test_RevertsIfCalledByAnAccountWithNoAccess() public { vm.startPrank(s_strangerAddr); vm.expectRevert("No access"); s_optimismValidator.validate(0, 0, 1, 1); } - /// @notice it posts sequencer status when there is no status change - function test_Validate_PostSequencerStatus_NoStatusChange() public { + /// @notice it posts sequencer status when there is not status change + function test_PostSequencerStatusWhenThereIsNotStatusChange() public { // Gives access to the s_eoaValidator s_optimismValidator.addAccess(s_eoaValidator); @@ -74,8 +84,8 @@ contract OptimismValidator_Validate is OptimismValidator_Setup { s_optimismValidator.validate(0, 0, 0, 0); } - /// @notice it posts sequencer offline - function test_Validate_PostSequencerOffline() public { + /// @notice it post sequencer offline + function test_PostSequencerOffline() public { // Gives access to the s_eoaValidator s_optimismValidator.addAccess(s_eoaValidator); diff --git a/contracts/src/v0.8/l2ep/test/v1_0_0/scroll/ScrollCrossDomainForwarder.t.sol b/contracts/src/v0.8/l2ep/test/v1_0_0/scroll/ScrollCrossDomainForwarder.t.sol index 0025c6b9937..e34e84f4006 100644 --- a/contracts/src/v0.8/l2ep/test/v1_0_0/scroll/ScrollCrossDomainForwarder.t.sol +++ b/contracts/src/v0.8/l2ep/test/v1_0_0/scroll/ScrollCrossDomainForwarder.t.sol @@ -2,7 +2,7 @@ pragma solidity 0.8.24; import {MockScrollCrossDomainMessenger} from "../../mocks/scroll/MockScrollCrossDomainMessenger.sol"; -import {ScrollCrossDomainForwarder} from "../../../scroll/ScrollCrossDomainForwarder.sol"; +import {ScrollCrossDomainForwarder} from "../../../dev/scroll/ScrollCrossDomainForwarder.sol"; import {Greeter} from "../../../../tests/Greeter.sol"; import {L2EPTest} from "../L2EPTest.t.sol"; @@ -54,6 +54,7 @@ contract ScrollCrossDomainForwarder_Forward is ScrollCrossDomainForwarderTest { /// @notice it should be callable by crossdomain messenger address / L1 owner function test_Forward() public { + // Sets msg.sender and tx.origin vm.startPrank(s_strangerAddr); // Defines the cross domain message to send @@ -73,6 +74,7 @@ contract ScrollCrossDomainForwarder_Forward is ScrollCrossDomainForwarderTest { /// @notice it should revert when contract call reverts function test_ForwardRevert() public { + // Sets msg.sender and tx.origin vm.startPrank(s_strangerAddr); // Sends an invalid message @@ -104,6 +106,7 @@ contract ScrollCrossDomainForwarder_TransferL1Ownership is ScrollCrossDomainForw /// @notice it should be callable by current L1 owner function test_CallableByL1Owner() public { + // Sets msg.sender and tx.origin vm.startPrank(s_strangerAddr); // Defines the cross domain message to send @@ -121,6 +124,7 @@ contract ScrollCrossDomainForwarder_TransferL1Ownership is ScrollCrossDomainForw /// @notice it should be callable by current L1 owner to zero address function test_CallableByL1OwnerOrZeroAddress() public { + // Sets msg.sender and tx.origin vm.startPrank(s_strangerAddr); // Defines the cross domain message to send @@ -140,6 +144,7 @@ contract ScrollCrossDomainForwarder_TransferL1Ownership is ScrollCrossDomainForw contract ScrollCrossDomainForwarder_AcceptL1Ownership is ScrollCrossDomainForwarderTest { /// @notice it should not be callable by non pending-owners function test_NotCallableByNonPendingOwners() public { + // Sets msg.sender and tx.origin vm.startPrank(s_strangerAddr); // Sends the message @@ -154,6 +159,7 @@ contract ScrollCrossDomainForwarder_AcceptL1Ownership is ScrollCrossDomainForwar /// @notice it should be callable by pending L1 owner function test_CallableByPendingL1Owner() public { + // Sets msg.sender and tx.origin vm.startPrank(s_strangerAddr); // Request ownership transfer diff --git a/contracts/src/v0.8/l2ep/test/v1_0_0/scroll/ScrollCrossDomainGovernor.t.sol b/contracts/src/v0.8/l2ep/test/v1_0_0/scroll/ScrollCrossDomainGovernor.t.sol index a2523e5feb6..8c3d56d1560 100644 --- a/contracts/src/v0.8/l2ep/test/v1_0_0/scroll/ScrollCrossDomainGovernor.t.sol +++ b/contracts/src/v0.8/l2ep/test/v1_0_0/scroll/ScrollCrossDomainGovernor.t.sol @@ -2,7 +2,7 @@ pragma solidity 0.8.24; import {MockScrollCrossDomainMessenger} from "../../mocks/scroll/MockScrollCrossDomainMessenger.sol"; -import {ScrollCrossDomainGovernor} from "../../../scroll/ScrollCrossDomainGovernor.sol"; +import {ScrollCrossDomainGovernor} from "../../../dev/scroll/ScrollCrossDomainGovernor.sol"; import {Greeter} from "../../../../tests/Greeter.sol"; import {L2EPTest} from "../L2EPTest.t.sol"; @@ -58,6 +58,7 @@ contract ScrollCrossDomainGovernor_Forward is ScrollCrossDomainGovernorTest { /// @notice it should be callable by crossdomain messenger address / L1 owner function test_Forward() public { + // Sets msg.sender and tx.origin vm.startPrank(s_strangerAddr); // Defines the cross domain message to send @@ -77,6 +78,7 @@ contract ScrollCrossDomainGovernor_Forward is ScrollCrossDomainGovernorTest { /// @notice it should revert when contract call reverts function test_ForwardRevert() public { + // Sets msg.sender and tx.origin vm.startPrank(s_strangerAddr); // Sends an invalid message @@ -91,6 +93,7 @@ contract ScrollCrossDomainGovernor_Forward is ScrollCrossDomainGovernorTest { /// @notice it should be callable by L2 owner function test_CallableByL2Owner() public { + // Sets msg.sender and tx.origin vm.startPrank(s_l1OwnerAddr); // Defines the cross domain message to send @@ -117,6 +120,7 @@ contract ScrollCrossDomainGovernor_ForwardDelegate is ScrollCrossDomainGovernorT /// @notice it should be callable by crossdomain messenger address / L1 owner function test_CallableByCrossDomainMessengerAddressOrL1Owner() public { + // Sets msg.sender and tx.origin vm.startPrank(s_strangerAddr); // Sends the message @@ -137,6 +141,7 @@ contract ScrollCrossDomainGovernor_ForwardDelegate is ScrollCrossDomainGovernorT /// @notice it should be callable by L2 owner function test_CallableByL2Owner() public { + // Sets msg.sender and tx.origin vm.startPrank(s_l1OwnerAddr); // Sends the message @@ -157,6 +162,7 @@ contract ScrollCrossDomainGovernor_ForwardDelegate is ScrollCrossDomainGovernorT /// @notice it should revert batch when one call fails function test_RevertsBatchWhenOneCallFails() public { + // Sets msg.sender and tx.origin vm.startPrank(s_strangerAddr); // Sends an invalid message (empty transaction data is not allowed) @@ -178,6 +184,7 @@ contract ScrollCrossDomainGovernor_ForwardDelegate is ScrollCrossDomainGovernorT /// @notice it should bubble up revert when contract call reverts function test_BubbleUpRevert() public { + // Sets msg.sender and tx.origin vm.startPrank(s_strangerAddr); // Sends an invalid message (empty transaction data is not allowed) @@ -213,6 +220,7 @@ contract ScrollCrossDomainGovernor_TransferL1Ownership is ScrollCrossDomainGover /// @notice it should be callable by current L1 owner function test_CallableByL1Owner() public { + // Sets msg.sender and tx.origin vm.startPrank(s_strangerAddr); // Defines the cross domain message to send @@ -230,6 +238,7 @@ contract ScrollCrossDomainGovernor_TransferL1Ownership is ScrollCrossDomainGover /// @notice it should be callable by current L1 owner to zero address function test_CallableByL1OwnerOrZeroAddress() public { + // Sets msg.sender and tx.origin vm.startPrank(s_strangerAddr); // Defines the cross domain message to send @@ -249,6 +258,7 @@ contract ScrollCrossDomainGovernor_TransferL1Ownership is ScrollCrossDomainGover contract ScrollCrossDomainGovernor_AcceptL1Ownership is ScrollCrossDomainGovernorTest { /// @notice it should not be callable by non pending-owners function test_NotCallableByNonPendingOwners() public { + // Sets msg.sender and tx.origin vm.startPrank(s_strangerAddr); // Sends the message @@ -263,6 +273,7 @@ contract ScrollCrossDomainGovernor_AcceptL1Ownership is ScrollCrossDomainGoverno /// @notice it should be callable by pending L1 owner function test_CallableByPendingL1Owner() public { + // Sets msg.sender and tx.origin vm.startPrank(s_strangerAddr); // Request ownership transfer diff --git a/contracts/src/v0.8/l2ep/test/v1_0_0/scroll/ScrollSequencerUptimeFeed.t.sol b/contracts/src/v0.8/l2ep/test/v1_0_0/scroll/ScrollSequencerUptimeFeed.t.sol index 1ad4bfd8119..0968c69415f 100644 --- a/contracts/src/v0.8/l2ep/test/v1_0_0/scroll/ScrollSequencerUptimeFeed.t.sol +++ b/contracts/src/v0.8/l2ep/test/v1_0_0/scroll/ScrollSequencerUptimeFeed.t.sol @@ -3,31 +3,19 @@ pragma solidity 0.8.24; import {MockScrollL1CrossDomainMessenger} from "../../mocks/scroll/MockScrollL1CrossDomainMessenger.sol"; import {MockScrollL2CrossDomainMessenger} from "../../mocks/scroll/MockScrollL2CrossDomainMessenger.sol"; -import {ScrollSequencerUptimeFeed} from "../../../scroll/ScrollSequencerUptimeFeed.sol"; -import {BaseSequencerUptimeFeed} from "../../../base/BaseSequencerUptimeFeed.sol"; +import {ScrollSequencerUptimeFeed} from "../../../dev/scroll/ScrollSequencerUptimeFeed.sol"; +import {BaseSequencerUptimeFeed} from "../../../dev/shared/BaseSequencerUptimeFeed.sol"; +import {FeedConsumer} from "../../../../tests/FeedConsumer.sol"; import {L2EPTest} from "../L2EPTest.t.sol"; -contract ScrollSequencerUptimeFeedTestWrapper is ScrollSequencerUptimeFeed { - constructor( - address l1SenderAddress, - address l2CrossDomainMessengerAddr, - bool initialStatus - ) ScrollSequencerUptimeFeed(l1SenderAddress, l2CrossDomainMessengerAddr, initialStatus) {} - - /// @notice It exposes the internal _validateSender function for testing - function validateSenderTestWrapper(address l1Sender) external view { - super._validateSender(l1Sender); - } -} - -contract ScrollSequencerUptimeFeed_Setup is L2EPTest { +contract ScrollSequencerUptimeFeedTest is L2EPTest { /// Constants uint256 internal constant GAS_USED_DEVIATION = 100; /// L2EP contracts MockScrollL1CrossDomainMessenger internal s_mockScrollL1CrossDomainMessenger; MockScrollL2CrossDomainMessenger internal s_mockScrollL2CrossDomainMessenger; - ScrollSequencerUptimeFeedTestWrapper internal s_scrollSequencerUptimeFeed; + ScrollSequencerUptimeFeed internal s_scrollSequencerUptimeFeed; /// Events event UpdateIgnored(bool latestStatus, uint64 latestTimestamp, bool incomingStatus, uint64 incomingTimestamp); @@ -39,7 +27,7 @@ contract ScrollSequencerUptimeFeed_Setup is L2EPTest { // Deploys contracts s_mockScrollL1CrossDomainMessenger = new MockScrollL1CrossDomainMessenger(); s_mockScrollL2CrossDomainMessenger = new MockScrollL2CrossDomainMessenger(); - s_scrollSequencerUptimeFeed = new ScrollSequencerUptimeFeedTestWrapper( + s_scrollSequencerUptimeFeed = new ScrollSequencerUptimeFeed( s_l1OwnerAddr, address(s_mockScrollL2CrossDomainMessenger), false @@ -50,13 +38,14 @@ contract ScrollSequencerUptimeFeed_Setup is L2EPTest { } } -contract ScrollSequencerUptimeFeed_Constructor is ScrollSequencerUptimeFeed_Setup { - /// @notice Reverts when L2 Cross Domain Messenger address is invalid - function test_Constructor_RevertWhen_InvalidL2XDomainMessenger() public { +contract ScrollSequencerUptimeFeed_Constructor is ScrollSequencerUptimeFeedTest { + /// @notice it should have been deployed with the correct initial state + function test_InitialState() public { // L2 cross domain messenger address must not be the zero address vm.expectRevert(ScrollSequencerUptimeFeed.ZeroAddress.selector); new ScrollSequencerUptimeFeed(s_l1OwnerAddr, address(0), false); + // Sets msg.sender and tx.origin to a valid address vm.startPrank(s_l1OwnerAddr, s_l1OwnerAddr); // Checks L1 sender @@ -68,50 +57,269 @@ contract ScrollSequencerUptimeFeed_Constructor is ScrollSequencerUptimeFeed_Setu assertEq(roundId, 1); assertEq(answer, 0); } +} - /// @notice Tests initial state with valid L2 Cross Domain Messenger - function test_Constructor_InitialState_WhenValidL2XDomainMessenger() public { - vm.startPrank(s_l1OwnerAddr, s_l1OwnerAddr); - ScrollSequencerUptimeFeed scrollSequencerUptimeFeed = new ScrollSequencerUptimeFeed( - s_l1OwnerAddr, - address(s_mockScrollL2CrossDomainMessenger), - false - ); - - // Checks L1 sender - address actualL1Addr = scrollSequencerUptimeFeed.l1Sender(); - assertEq(actualL1Addr, s_l1OwnerAddr); +contract ScrollSequencerUptimeFeed_UpdateStatus is ScrollSequencerUptimeFeedTest { + /// @notice it should revert if called by an address that is not the L2 Cross Domain Messenger + function test_RevertIfNotL2CrossDomainMessengerAddr() public { + // Sets msg.sender and tx.origin to an unauthorized address + vm.startPrank(s_strangerAddr, s_strangerAddr); - // Checks latest round data - (uint80 roundId, int256 answer, , , ) = scrollSequencerUptimeFeed.latestRoundData(); - assertEq(roundId, 1); - assertEq(answer, 0); + // Tries to update the status from an unauthorized account + vm.expectRevert(BaseSequencerUptimeFeed.InvalidSender.selector); + s_scrollSequencerUptimeFeed.updateStatus(true, uint64(1)); } -} -contract ScrollSequencerUptimeFeed_ValidateSender is ScrollSequencerUptimeFeed_Setup { - /// @notice Reverts when sender is not L2 Cross Domain Messenger address - function test_ValidateSender_RevertWhen_SenderIsNotL2CrossDomainMessengerAddr() public { - vm.startPrank(s_strangerAddr); + /// @notice it should revert if called by an address that is not the L2 Cross Domain Messenger and is not the L1 sender + function test_RevertIfNotL2CrossDomainMessengerAddrAndNotL1SenderAddr() public { + // Sets msg.sender and tx.origin to an unauthorized address + vm.startPrank(s_strangerAddr, s_strangerAddr); + + // Sets mock sender in mock L2 messenger contract + s_mockScrollL2CrossDomainMessenger.setSender(s_strangerAddr); + // Tries to update the status from an unauthorized account vm.expectRevert(BaseSequencerUptimeFeed.InvalidSender.selector); - s_scrollSequencerUptimeFeed.validateSenderTestWrapper(s_l1OwnerAddr); + s_scrollSequencerUptimeFeed.updateStatus(true, uint64(1)); } - /// @notice Reverts when L1 Cross Domain Messenger address is not L1 sender address - function test_ValidateSender_RevertWhen_L1CrossDomainMessengerAddrIsNotL1SenderAddr() public { + /// @notice it should update status when status has not changed and incoming timestamp is the same as latest + function test_UpdateStatusWhenNoChange() public { + // Sets msg.sender and tx.origin to a valid address address l2MessengerAddr = address(s_mockScrollL2CrossDomainMessenger); - vm.startPrank(l2MessengerAddr); + vm.startPrank(l2MessengerAddr, l2MessengerAddr); - vm.expectRevert(BaseSequencerUptimeFeed.InvalidSender.selector); - s_scrollSequencerUptimeFeed.validateSenderTestWrapper(s_strangerAddr); + // Fetches the latest timestamp + uint256 timestamp = s_scrollSequencerUptimeFeed.latestTimestamp(); + + // Submits a status update + vm.expectEmit(); + emit AnswerUpdated(1, 2, timestamp); + s_scrollSequencerUptimeFeed.updateStatus(true, uint64(timestamp)); + assertEq(s_scrollSequencerUptimeFeed.latestAnswer(), 1); + assertEq(s_scrollSequencerUptimeFeed.latestTimestamp(), uint64(timestamp)); + + // Stores the current round data before updating it + ( + uint80 roundIdBeforeUpdate, + int256 answerBeforeUpdate, + uint256 startedAtBeforeUpdate, + , + uint80 answeredInRoundBeforeUpdate + ) = s_scrollSequencerUptimeFeed.latestRoundData(); + + // Submit another status update with the same status + vm.expectEmit(); + emit RoundUpdated(1, uint64(block.timestamp)); + s_scrollSequencerUptimeFeed.updateStatus(true, uint64(timestamp + 200)); + assertEq(s_scrollSequencerUptimeFeed.latestAnswer(), 1); + assertEq(s_scrollSequencerUptimeFeed.latestTimestamp(), uint64(timestamp)); + + // Stores the current round data after updating it + ( + uint80 roundIdAfterUpdate, + int256 answerAfterUpdate, + uint256 startedAtAfterUpdate, + uint256 updatedAtAfterUpdate, + uint80 answeredInRoundAfterUpdate + ) = s_scrollSequencerUptimeFeed.latestRoundData(); + + // Verifies the latest round data has been properly updated + assertEq(roundIdAfterUpdate, roundIdBeforeUpdate); + assertEq(answerAfterUpdate, answerBeforeUpdate); + assertEq(startedAtAfterUpdate, startedAtBeforeUpdate); + assertEq(answeredInRoundAfterUpdate, answeredInRoundBeforeUpdate); + assertEq(updatedAtAfterUpdate, block.timestamp); + } + + /// @notice it should update status when status has changed and incoming timestamp is newer than the latest + function test_UpdateStatusWhenStatusChangeAndTimeChange() public { + // Sets msg.sender and tx.origin to a valid address + address l2MessengerAddr = address(s_mockScrollL2CrossDomainMessenger); + vm.startPrank(l2MessengerAddr, l2MessengerAddr); + + // Submits a status update + uint256 timestamp = s_scrollSequencerUptimeFeed.latestTimestamp(); + vm.expectEmit(); + emit AnswerUpdated(1, 2, timestamp); + s_scrollSequencerUptimeFeed.updateStatus(true, uint64(timestamp)); + assertEq(s_scrollSequencerUptimeFeed.latestAnswer(), 1); + assertEq(s_scrollSequencerUptimeFeed.latestTimestamp(), uint64(timestamp)); + + // Submit another status update, different status, newer timestamp should update + timestamp = timestamp + 200; + vm.expectEmit(); + emit AnswerUpdated(0, 3, timestamp); + s_scrollSequencerUptimeFeed.updateStatus(false, uint64(timestamp)); + assertEq(s_scrollSequencerUptimeFeed.latestAnswer(), 0); + assertEq(s_scrollSequencerUptimeFeed.latestTimestamp(), uint64(timestamp)); + } + + /// @notice it should update status when status has changed and incoming timestamp is the same as latest + function test_UpdateStatusWhenStatusChangeAndNoTimeChange() public { + // Sets msg.sender and tx.origin to a valid address + address l2MessengerAddr = address(s_mockScrollL2CrossDomainMessenger); + vm.startPrank(l2MessengerAddr, l2MessengerAddr); + + // Fetches the latest timestamp + uint256 timestamp = s_scrollSequencerUptimeFeed.latestTimestamp(); + + // Submits a status update + vm.expectEmit(); + emit AnswerUpdated(1, 2, timestamp); + s_scrollSequencerUptimeFeed.updateStatus(true, uint64(timestamp)); + assertEq(s_scrollSequencerUptimeFeed.latestAnswer(), 1); + assertEq(s_scrollSequencerUptimeFeed.latestTimestamp(), uint64(timestamp)); + + // Submit another status update, different status, same timestamp should update + vm.expectEmit(); + emit AnswerUpdated(0, 3, timestamp); + s_scrollSequencerUptimeFeed.updateStatus(false, uint64(timestamp)); + assertEq(s_scrollSequencerUptimeFeed.latestAnswer(), 0); + assertEq(s_scrollSequencerUptimeFeed.latestTimestamp(), uint64(timestamp)); + } + + /// @notice it should ignore out-of-order updates + function test_IgnoreOutOfOrderUpdates() public { + // Sets msg.sender and tx.origin to a valid address + address l2MessengerAddr = address(s_mockScrollL2CrossDomainMessenger); + vm.startPrank(l2MessengerAddr, l2MessengerAddr); + + // Submits a status update + uint256 timestamp = s_scrollSequencerUptimeFeed.latestTimestamp() + 10000; + vm.expectEmit(); + emit AnswerUpdated(1, 2, timestamp); + s_scrollSequencerUptimeFeed.updateStatus(true, uint64(timestamp)); + assertEq(s_scrollSequencerUptimeFeed.latestAnswer(), 1); + assertEq(s_scrollSequencerUptimeFeed.latestTimestamp(), uint64(timestamp)); + + // Update with different status, but stale timestamp, should be ignored + timestamp = timestamp - 1000; + vm.expectEmit(false, false, false, false); + emit UpdateIgnored(true, 0, true, 0); // arguments are dummy values + // TODO: how can we check that an AnswerUpdated event was NOT emitted + s_scrollSequencerUptimeFeed.updateStatus(false, uint64(timestamp)); } +} - /// @notice Updates status when status changes and incoming timestamp is the same as latest - function test_ValidateSender_UpdateStatusWhen_StatusChangeAndNoTimeChange() public { +contract ScrollSequencerUptimeFeed_AggregatorV3Interface is ScrollSequencerUptimeFeedTest { + /// @notice it should return valid answer from getRoundData and latestRoundData + function test_AggregatorV3Interface() public { + // Sets msg.sender and tx.origin to a valid address address l2MessengerAddr = address(s_mockScrollL2CrossDomainMessenger); - vm.startPrank(l2MessengerAddr); + vm.startPrank(l2MessengerAddr, l2MessengerAddr); + + // Defines helper variables + uint80 roundId; + int256 answer; + uint256 startedAt; + uint256 updatedAt; + uint80 answeredInRound; + + // Checks initial state + (roundId, answer, startedAt, updatedAt, answeredInRound) = s_scrollSequencerUptimeFeed.latestRoundData(); + assertEq(roundId, 1); + assertEq(answer, 0); + assertEq(answeredInRound, roundId); + assertEq(startedAt, updatedAt); + + // Submits status update with different status and newer timestamp, should update + uint256 timestamp = startedAt + 1000; + s_scrollSequencerUptimeFeed.updateStatus(true, uint64(timestamp)); + (roundId, answer, startedAt, updatedAt, answeredInRound) = s_scrollSequencerUptimeFeed.getRoundData(2); + assertEq(roundId, 2); + assertEq(answer, 1); + assertEq(answeredInRound, roundId); + assertEq(startedAt, timestamp); + assertLe(updatedAt, startedAt); + + // Saves round 2 data + uint80 roundId2 = roundId; + int256 answer2 = answer; + uint256 startedAt2 = startedAt; + uint256 updatedAt2 = updatedAt; + uint80 answeredInRound2 = answeredInRound; + + // Checks that last round is still returning the correct data + (roundId, answer, startedAt, updatedAt, answeredInRound) = s_scrollSequencerUptimeFeed.getRoundData(1); + assertEq(roundId, 1); + assertEq(answer, 0); + assertEq(answeredInRound, roundId); + assertEq(startedAt, updatedAt); + + // Assert latestRoundData corresponds to latest round id + (roundId, answer, startedAt, updatedAt, answeredInRound) = s_scrollSequencerUptimeFeed.latestRoundData(); + assertEq(roundId2, roundId); + assertEq(answer2, answer); + assertEq(startedAt2, startedAt); + assertEq(updatedAt2, updatedAt); + assertEq(answeredInRound2, answeredInRound); + } + + /// @notice it should revert from #getRoundData when round does not yet exist (future roundId) + function test_RevertGetRoundDataWhenRoundDoesNotExistYet() public { + // Sets msg.sender and tx.origin to a valid address + vm.startPrank(s_l1OwnerAddr, s_l1OwnerAddr); + + // Gets data from a round that has not happened yet + vm.expectRevert(BaseSequencerUptimeFeed.NoDataPresent.selector); + s_scrollSequencerUptimeFeed.getRoundData(2); + } + + /// @notice it should revert from #getAnswer when round does not yet exist (future roundId) + function test_RevertGetAnswerWhenRoundDoesNotExistYet() public { + // Sets msg.sender and tx.origin to a valid address + vm.startPrank(s_l1OwnerAddr, s_l1OwnerAddr); + + // Gets data from a round that has not happened yet + vm.expectRevert(BaseSequencerUptimeFeed.NoDataPresent.selector); + s_scrollSequencerUptimeFeed.getAnswer(2); + } + + /// @notice it should revert from #getTimestamp when round does not yet exist (future roundId) + function test_RevertGetTimestampWhenRoundDoesNotExistYet() public { + // Sets msg.sender and tx.origin to a valid address + vm.startPrank(s_l1OwnerAddr, s_l1OwnerAddr); + + // Gets data from a round that has not happened yet + vm.expectRevert(BaseSequencerUptimeFeed.NoDataPresent.selector); + s_scrollSequencerUptimeFeed.getTimestamp(2); + } +} - s_scrollSequencerUptimeFeed.validateSenderTestWrapper(s_l1OwnerAddr); +contract ScrollSequencerUptimeFeed_ProtectReadsOnAggregatorV2V3InterfaceFunctions is ScrollSequencerUptimeFeedTest { + /// @notice it should disallow reads on AggregatorV2V3Interface functions when consuming contract is not whitelisted + function test_AggregatorV2V3InterfaceDisallowReadsIfConsumingContractIsNotWhitelisted() public { + // Deploys a FeedConsumer contract + FeedConsumer feedConsumer = new FeedConsumer(address(s_scrollSequencerUptimeFeed)); + + // Sanity - consumer is not whitelisted + assertEq(s_scrollSequencerUptimeFeed.checkEnabled(), true); + assertEq(s_scrollSequencerUptimeFeed.hasAccess(address(feedConsumer), abi.encode("")), false); + + // Asserts reads are not possible from consuming contract + vm.expectRevert("No access"); + feedConsumer.latestAnswer(); + vm.expectRevert("No access"); + feedConsumer.latestRoundData(); + } + + /// @notice it should allow reads on AggregatorV2V3Interface functions when consuming contract is whitelisted + function test_AggregatorV2V3InterfaceAllowReadsIfConsumingContractIsWhitelisted() public { + // Deploys a FeedConsumer contract + FeedConsumer feedConsumer = new FeedConsumer(address(s_scrollSequencerUptimeFeed)); + + // Whitelist consumer + s_scrollSequencerUptimeFeed.addAccess(address(feedConsumer)); + + // Sanity - consumer is whitelisted + assertEq(s_scrollSequencerUptimeFeed.checkEnabled(), true); + assertEq(s_scrollSequencerUptimeFeed.hasAccess(address(feedConsumer), abi.encode("")), true); + + // Asserts reads are possible from consuming contract + (uint80 roundId, int256 answer, , , ) = feedConsumer.latestRoundData(); + assertEq(feedConsumer.latestAnswer(), 0); + assertEq(roundId, 1); + assertEq(answer, 0); } } diff --git a/contracts/src/v0.8/l2ep/test/v1_0_0/scroll/ScrollValidator.t.sol b/contracts/src/v0.8/l2ep/test/v1_0_0/scroll/ScrollValidator.t.sol index b7708889100..3d5298d5184 100644 --- a/contracts/src/v0.8/l2ep/test/v1_0_0/scroll/ScrollValidator.t.sol +++ b/contracts/src/v0.8/l2ep/test/v1_0_0/scroll/ScrollValidator.t.sol @@ -1,18 +1,18 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.24; -import {ISequencerUptimeFeed} from "../../../interfaces/ISequencerUptimeFeed.sol"; +import {ISequencerUptimeFeed} from "../../../dev/interfaces/ISequencerUptimeFeed.sol"; import {MockScrollL1CrossDomainMessenger} from "../../mocks/scroll/MockScrollL1CrossDomainMessenger.sol"; import {MockScrollL2CrossDomainMessenger} from "../../mocks/scroll/MockScrollL2CrossDomainMessenger.sol"; import {MockScrollL1MessageQueue} from "../../mocks/scroll/MockScrollL1MessageQueue.sol"; -import {ScrollSequencerUptimeFeed} from "../../../scroll/ScrollSequencerUptimeFeed.sol"; -import {ScrollValidator} from "../../../scroll/ScrollValidator.sol"; +import {ScrollSequencerUptimeFeed} from "../../../dev/scroll/ScrollSequencerUptimeFeed.sol"; +import {ScrollValidator} from "../../../dev/scroll/ScrollValidator.sol"; import {L2EPTest} from "../L2EPTest.t.sol"; -contract ScrollValidator_Setup is L2EPTest { +contract ScrollValidatorTest is L2EPTest { /// Helper constants - address internal immutable L2_SEQ_STATUS_RECORDER_ADDRESS = makeAddr("L2_SEQ_STATUS_RECORDER_ADDRESS"); + address internal constant L2_SEQ_STATUS_RECORDER_ADDRESS = 0x491B1dDA0A8fa069bbC1125133A975BF4e85a91b; uint32 internal constant INIT_GAS_LIMIT = 1900000; /// L2EP contracts @@ -53,31 +53,26 @@ contract ScrollValidator_Setup is L2EPTest { } } -contract ScrollValidator_Constructor is ScrollValidator_Setup { - /// @notice Reverts when L1 message queue address is invalid - function test_Constructor_RevertWhen_InvalidL1MessageQueueAddress() public { - vm.startPrank(s_l1OwnerAddr); - - vm.expectRevert("Invalid L1 message queue address"); - new ScrollValidator( - address(s_mockScrollL1CrossDomainMessenger), - address(s_scrollSequencerUptimeFeed), - address(0), - INIT_GAS_LIMIT - ); +contract ScrollValidator_SetGasLimit is ScrollValidatorTest { + /// @notice it correctly updates the gas limit + function test_CorrectlyUpdatesTheGasLimit() public { + uint32 newGasLimit = 2000000; + assertEq(s_scrollValidator.getGasLimit(), INIT_GAS_LIMIT); + s_scrollValidator.setGasLimit(newGasLimit); + assertEq(s_scrollValidator.getGasLimit(), newGasLimit); } } -contract ScrollValidator_Validate is ScrollValidator_Setup { - /// @notice Reverts if called by an account with no access - function test_Validate_RevertWhen_CalledByAccountWithNoAccess() public { +contract ScrollValidator_Validate is ScrollValidatorTest { + /// @notice it reverts if called by account with no access + function test_RevertsIfCalledByAnAccountWithNoAccess() public { vm.startPrank(s_strangerAddr); vm.expectRevert("No access"); s_scrollValidator.validate(0, 0, 1, 1); } - /// @notice Posts sequencer status when there is no status change - function test_Validate_PostSequencerStatus_NoStatusChange() public { + /// @notice it posts sequencer status when there is not status change + function test_PostSequencerStatusWhenThereIsNotStatusChange() public { // Gives access to the s_eoaValidator s_scrollValidator.addAccess(s_eoaValidator); @@ -101,8 +96,8 @@ contract ScrollValidator_Validate is ScrollValidator_Setup { s_scrollValidator.validate(0, 0, 0, 0); } - /// @notice Posts sequencer offline status - function test_Validate_PostSequencerOffline() public { + /// @notice it post sequencer offline + function test_PostSequencerOffline() public { // Gives access to the s_eoaValidator s_scrollValidator.addAccess(s_eoaValidator); diff --git a/contracts/src/v0.8/l2ep/test/v1_0_0/shared/BaseSequencerUptimeFeed.t.sol b/contracts/src/v0.8/l2ep/test/v1_0_0/shared/BaseSequencerUptimeFeed.t.sol deleted file mode 100644 index 20553e33bab..00000000000 --- a/contracts/src/v0.8/l2ep/test/v1_0_0/shared/BaseSequencerUptimeFeed.t.sol +++ /dev/null @@ -1,377 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.24; - -import {Vm} from "forge-std/Test.sol"; -import {AddressAliasHelper} from "../../../../vendor/arb-bridge-eth/v0.8.0-custom/contracts/libraries/AddressAliasHelper.sol"; -import {BaseSequencerUptimeFeed} from "../../../base/BaseSequencerUptimeFeed.sol"; -import {MockBaseSequencerUptimeFeed} from "../../../test/mocks/MockBaseSequencerUptimeFeed.sol"; -import {FeedConsumer} from "../../../../tests/FeedConsumer.sol"; -import {L2EPTest} from "../L2EPTest.t.sol"; - -contract BaseSequencerUptimeFeed_Setup is L2EPTest { - /// Helper Variables - address internal s_aliasedL1OwnerAddress = AddressAliasHelper.applyL1ToL2Alias(s_l1OwnerAddr); - - /// L2EP contracts - BaseSequencerUptimeFeed internal s_sequencerUptimeFeed; - - /// Events - event UpdateIgnored(bool latestStatus, uint64 latestTimestamp, bool incomingStatus, uint64 incomingTimestamp); - event AnswerUpdated(int256 indexed current, uint256 indexed roundId, uint256 updatedAt); - event RoundUpdated(int256 status, uint64 updatedAt); - event L1SenderTransferred(address indexed from, address indexed to); - - /// Setup - function setUp() public { - // Deploys contracts - s_sequencerUptimeFeed = new MockBaseSequencerUptimeFeed(s_l1OwnerAddr, false, true); - } -} - -contract BaseSequencerUptimeFeed_Constructor is BaseSequencerUptimeFeed_Setup { - /// @notice Tests initial state of the contract - function test_Constructor_InitialState() public { - // Sets msg.sender and tx.origin to a valid address - vm.startPrank(s_l1OwnerAddr, s_l1OwnerAddr); - - // Checks L1 sender - address actualL1Addr = s_sequencerUptimeFeed.l1Sender(); - assertEq(actualL1Addr, s_l1OwnerAddr); - - // Checks latest round data - (uint80 roundId, int256 answer, , , ) = s_sequencerUptimeFeed.latestRoundData(); - assertEq(roundId, 1); - assertEq(answer, 0); - } -} - -contract BaseSequencerUptimeFeed_transferL1Sender is BaseSequencerUptimeFeed_Setup { - /// @notice Tests transferring L1 sender - function test_transferL1Sender_CorrectlyTransfersL1Sender() public { - address initialSender = address(0); - address newSender = makeAddr("newSender"); - - // Sets msg.sender and tx.origin to a valid address - vm.startPrank(s_l1OwnerAddr, s_l1OwnerAddr); - - MockBaseSequencerUptimeFeed sequencerUptimeFeed = new MockBaseSequencerUptimeFeed(initialSender, false, true); - - assertEq(sequencerUptimeFeed.l1Sender(), initialSender); - - // Transfers the L1 sender - vm.expectEmit(); - emit L1SenderTransferred(initialSender, newSender); - sequencerUptimeFeed.transferL1Sender(newSender); - assertEq(sequencerUptimeFeed.l1Sender(), newSender); - - vm.recordLogs(); - // Transfers to the same L1 sender should not emit an event - sequencerUptimeFeed.transferL1Sender(newSender); - assertEq(vm.getRecordedLogs().length, 0); - } - - /// @notice Reverts if called by an unauthorized account - function test_transferL1Sender_RevertWhen_CalledByUnauthorizedAccount() public { - address newSender = makeAddr("newSender"); - - // Sets msg.sender and tx.origin to an unauthorized address - vm.startPrank(s_strangerAddr, s_strangerAddr); - - vm.expectRevert("Only callable by owner"); - s_sequencerUptimeFeed.transferL1Sender(newSender); - } -} - -contract BaseSequencerUptimeFeed_UpdateStatus is BaseSequencerUptimeFeed_Setup { - /// @notice Reverts if called by an unauthorized account - function test_updateStatus_RevertWhen_NotL2CrossDomainMessengerAddr() public { - // Sets msg.sender and tx.origin to an unauthorized address - vm.startPrank(s_strangerAddr, s_strangerAddr); - - BaseSequencerUptimeFeed s_sequencerUptimeFeedFailSenderCheck = new MockBaseSequencerUptimeFeed( - s_l1OwnerAddr, - false, - false - ); - - // Tries to update the status from an unauthorized account - vm.expectRevert(BaseSequencerUptimeFeed.InvalidSender.selector); - s_sequencerUptimeFeedFailSenderCheck.updateStatus(true, uint64(1)); - } - - /// @notice Updates status when status has not changed and incoming timestamp is the same as latest - function test_updateStatus_UpdateWhen_NoStatusChangeSameTimestamp() public { - // Sets msg.sender and tx.origin to a valid address - vm.startPrank(s_aliasedL1OwnerAddress, s_aliasedL1OwnerAddress); - - // Fetches the latest timestamp - uint256 timestamp = s_sequencerUptimeFeed.latestTimestamp(); - - // Submits a status update - vm.expectEmit(); - emit AnswerUpdated(1, 2, timestamp); - s_sequencerUptimeFeed.updateStatus(true, uint64(timestamp)); - assertEq(s_sequencerUptimeFeed.latestAnswer(), 1); - assertEq(s_sequencerUptimeFeed.latestRound(), 2); - assertEq(s_sequencerUptimeFeed.latestTimestamp(), uint64(timestamp)); - - // Stores the current round data before updating it - ( - uint80 roundIdBeforeUpdate, - int256 answerBeforeUpdate, - uint256 startedAtBeforeUpdate, - , - uint80 answeredInRoundBeforeUpdate - ) = s_sequencerUptimeFeed.latestRoundData(); - - // Submit another status update with the same status - vm.expectEmit(); - emit RoundUpdated(1, uint64(block.timestamp)); - s_sequencerUptimeFeed.updateStatus(true, uint64(timestamp + 200)); - assertEq(s_sequencerUptimeFeed.latestAnswer(), 1); - assertEq(s_sequencerUptimeFeed.latestRound(), 2); - assertEq(s_sequencerUptimeFeed.latestTimestamp(), uint64(timestamp)); - - // Stores the current round data after updating it - ( - uint80 roundIdAfterUpdate, - int256 answerAfterUpdate, - uint256 startedAtAfterUpdate, - uint256 updatedAtAfterUpdate, - uint80 answeredInRoundAfterUpdate - ) = s_sequencerUptimeFeed.latestRoundData(); - - // Verifies the latest round data has been properly updated - assertEq(roundIdAfterUpdate, roundIdBeforeUpdate); - assertEq(answerAfterUpdate, answerBeforeUpdate); - assertEq(startedAtAfterUpdate, startedAtBeforeUpdate); - assertEq(answeredInRoundAfterUpdate, answeredInRoundBeforeUpdate); - assertEq(updatedAtAfterUpdate, block.timestamp); - } - - /// @notice Updates status when status has changed and incoming timestamp is newer than the latest - function test_updateStatus_UpdateWhen_StatusChangeAndTimeChange() public { - // Sets msg.sender and tx.origin to a valid address - vm.startPrank(s_aliasedL1OwnerAddress, s_aliasedL1OwnerAddress); - - // Submits a status update - uint256 timestamp = s_sequencerUptimeFeed.latestTimestamp(); - vm.expectEmit(); - emit AnswerUpdated(1, 2, timestamp); - s_sequencerUptimeFeed.updateStatus(true, uint64(timestamp)); - assertEq(s_sequencerUptimeFeed.latestAnswer(), 1); - assertEq(s_sequencerUptimeFeed.latestRound(), 2); - assertEq(s_sequencerUptimeFeed.latestTimestamp(), uint64(timestamp)); - - // Submit another status update, different status, newer timestamp should update - timestamp = timestamp + 200; - vm.expectEmit(); - emit AnswerUpdated(0, 3, timestamp); - s_sequencerUptimeFeed.updateStatus(false, uint64(timestamp)); - assertEq(s_sequencerUptimeFeed.latestAnswer(), 0); - assertEq(s_sequencerUptimeFeed.latestRound(), 3); - assertEq(s_sequencerUptimeFeed.latestTimestamp(), uint64(timestamp)); - } - - /// @notice Updates status when status has changed and incoming timestamp is the same as latest - function test_updateStatus_UpdateWhen_StatusChangeAndNoTimeChange() public { - // Sets msg.sender and tx.origin to a valid address - vm.startPrank(s_aliasedL1OwnerAddress, s_aliasedL1OwnerAddress); - - // Fetches the latest timestamp - uint256 timestamp = s_sequencerUptimeFeed.latestTimestamp(); - - // Submits a status update - vm.expectEmit(); - emit AnswerUpdated(1, 2, timestamp); - s_sequencerUptimeFeed.updateStatus(true, uint64(timestamp)); - assertEq(s_sequencerUptimeFeed.latestAnswer(), 1); - assertEq(s_sequencerUptimeFeed.latestRound(), 2); - assertEq(s_sequencerUptimeFeed.latestTimestamp(), uint64(timestamp)); - - // Submit another status update, different status, same timestamp should update - vm.expectEmit(); - emit AnswerUpdated(0, 3, timestamp); - s_sequencerUptimeFeed.updateStatus(false, uint64(timestamp)); - assertEq(s_sequencerUptimeFeed.latestAnswer(), 0); - assertEq(s_sequencerUptimeFeed.latestRound(), 3); - assertEq(s_sequencerUptimeFeed.latestTimestamp(), uint64(timestamp)); - } - - /// @notice Ignores out-of-order updates - function test_updateStatus_IgnoreOutOfOrderUpdates() public { - // Sets msg.sender and tx.origin to a valid address - vm.startPrank(s_aliasedL1OwnerAddress, s_aliasedL1OwnerAddress); - - // Submits a status update - uint256 timestamp = s_sequencerUptimeFeed.latestTimestamp() + 10000; - vm.expectEmit(); - emit AnswerUpdated(1, 2, timestamp); - s_sequencerUptimeFeed.updateStatus(true, uint64(timestamp)); - assertEq(s_sequencerUptimeFeed.latestAnswer(), 1); - assertEq(s_sequencerUptimeFeed.latestRound(), 2); - assertEq(s_sequencerUptimeFeed.latestTimestamp(), uint64(timestamp)); - - // Update with different status, but stale timestamp, should be ignored - timestamp = timestamp - 1000; - vm.expectEmit(false, false, false, false); - emit UpdateIgnored(true, 0, true, 0); // arguments are dummy values - - vm.recordLogs(); - - // Tries to update with stale timestamp - s_sequencerUptimeFeed.updateStatus(false, uint64(timestamp)); - - Vm.Log[] memory entries = vm.getRecordedLogs(); - - assertEq(entries.length, 1); - assertEq(entries[0].topics[0], keccak256("UpdateIgnored(bool,uint64,bool,uint64)")); - } -} - -contract BaseSequencerUptimeFeed_AggregatorV3Interface is BaseSequencerUptimeFeed_Setup { - /// @notice Returns valid answer from getRoundData and latestRoundData - function test_AggregatorV3Interface_ReturnsValidData() public { - // Sets msg.sender and tx.origin to a valid address - vm.startPrank(s_aliasedL1OwnerAddress, s_aliasedL1OwnerAddress); - - // Defines helper variables - uint80 roundId; - int256 answer; - uint256 startedAt; - uint256 updatedAt; - uint80 answeredInRound; - - // Checks initial state - (roundId, answer, startedAt, updatedAt, answeredInRound) = s_sequencerUptimeFeed.latestRoundData(); - assertEq(roundId, 1); - assertEq(answer, 0); - assertEq(answeredInRound, roundId); - assertEq(startedAt, updatedAt); - - // Submits status update with different status and newer timestamp, should update - uint256 timestamp = startedAt + 1000; - s_sequencerUptimeFeed.updateStatus(true, uint64(timestamp)); - (roundId, answer, startedAt, updatedAt, answeredInRound) = s_sequencerUptimeFeed.getRoundData(2); - assertEq(roundId, 2); - assertEq(answer, 1); - assertEq(answeredInRound, roundId); - assertEq(startedAt, timestamp); - assertLe(updatedAt, startedAt); - - // Saves round 2 data - uint80 roundId2 = roundId; - int256 answer2 = answer; - uint256 startedAt2 = startedAt; - uint256 updatedAt2 = updatedAt; - uint80 answeredInRound2 = answeredInRound; - - // Checks that last round is still returning the correct data - (roundId, answer, startedAt, updatedAt, answeredInRound) = s_sequencerUptimeFeed.getRoundData(1); - assertEq(roundId, 1); - assertEq(answer, 0); - assertEq(answeredInRound, roundId); - assertEq(startedAt, updatedAt); - - // Assert latestRoundData corresponds to latest round id - (roundId, answer, startedAt, updatedAt, answeredInRound) = s_sequencerUptimeFeed.latestRoundData(); - assertEq(roundId2, roundId); - assertEq(answer2, answer); - assertEq(startedAt2, startedAt); - assertEq(updatedAt2, updatedAt); - assertEq(answeredInRound2, answeredInRound); - } - - /// @notice Reverts when getRoundData is called for a round that does not exist yet - function test_getRoundData_RevertWhen_RoundDoesNotExist() public { - // Sets msg.sender and tx.origin to a valid address - vm.startPrank(s_l1OwnerAddr, s_l1OwnerAddr); - - // Gets data from a round that has not happened yet - vm.expectRevert(BaseSequencerUptimeFeed.NoDataPresent.selector); - s_sequencerUptimeFeed.getRoundData(2); - } - - /// @notice Returns the getAnswer for the latest round - function test_getAnswer_ReturnsValidAnswer() public { - // Sets msg.sender and tx.origin to a valid address - vm.startPrank(s_aliasedL1OwnerAddress, s_aliasedL1OwnerAddress); - - uint256 startedAt; - (, , startedAt, , ) = s_sequencerUptimeFeed.latestRoundData(); - - s_sequencerUptimeFeed.updateStatus(true, uint64(startedAt + 1000)); - - assertEq(0, s_sequencerUptimeFeed.getAnswer(1)); - } - - /// @notice Reverts when getAnswer is called for a round that does not exist yet - function test_getAnswer_RevertWhen_RoundDoesNotExist() public { - // Sets msg.sender and tx.origin to a valid address - vm.startPrank(s_l1OwnerAddr, s_l1OwnerAddr); - - // Gets data from a round that has not happened yet - vm.expectRevert(BaseSequencerUptimeFeed.NoDataPresent.selector); - s_sequencerUptimeFeed.getAnswer(2); - } - - /// @notice Returns the getTimestamp for the latest round - function test_getTimestamp_ReturnsValidTimestamp() public { - // Sets msg.sender and tx.origin to a valid address - vm.startPrank(s_aliasedL1OwnerAddress, s_aliasedL1OwnerAddress); - - uint256 startedAt; - (, , startedAt, , ) = s_sequencerUptimeFeed.latestRoundData(); - - s_sequencerUptimeFeed.updateStatus(true, uint64(startedAt + 1000)); - - assertEq(startedAt, s_sequencerUptimeFeed.getTimestamp(1)); - } - - /// @notice Reverts when getTimestamp is called for a round that does not exist yet - function test_getTimestamp_RevertWhen_RoundDoesNotExist() public { - // Sets msg.sender and tx.origin to a valid address - vm.startPrank(s_l1OwnerAddr, s_l1OwnerAddr); - - // Gets data from a round that has not happened yet - vm.expectRevert(BaseSequencerUptimeFeed.NoDataPresent.selector); - s_sequencerUptimeFeed.getTimestamp(2); - } -} - -contract BaseSequencerUptimeFeed_ProtectReadsOnAggregatorV2V3InterfaceFunctions is BaseSequencerUptimeFeed_Setup { - /// @notice Disallows reads on AggregatorV2V3Interface functions when consuming contract is not whitelisted - function test_ProtectReads_DisallowWhen_NotWhitelisted() public { - // Deploys a FeedConsumer contract - FeedConsumer feedConsumer = new FeedConsumer(address(s_sequencerUptimeFeed)); - - // Sanity - consumer is not whitelisted - assertEq(s_sequencerUptimeFeed.checkEnabled(), true); - assertEq(s_sequencerUptimeFeed.hasAccess(address(feedConsumer), abi.encode("")), false); - - // Asserts reads are not possible from consuming contract - vm.expectRevert("No access"); - feedConsumer.latestAnswer(); - vm.expectRevert("No access"); - feedConsumer.latestRoundData(); - } - - /// @notice Allows reads on AggregatorV2V3Interface functions when consuming contract is whitelisted - function test_ProtectReads_AllowWhen_Whitelisted() public { - // Deploys a FeedConsumer contract - FeedConsumer feedConsumer = new FeedConsumer(address(s_sequencerUptimeFeed)); - - // Whitelist consumer - s_sequencerUptimeFeed.addAccess(address(feedConsumer)); - - // Sanity - consumer is whitelisted - assertEq(s_sequencerUptimeFeed.checkEnabled(), true); - assertEq(s_sequencerUptimeFeed.hasAccess(address(feedConsumer), abi.encode("")), true); - - // Asserts reads are possible from consuming contract - (uint80 roundId, int256 answer, , , ) = feedConsumer.latestRoundData(); - assertEq(feedConsumer.latestAnswer(), 0); - assertEq(roundId, 1); - assertEq(answer, 0); - } -} diff --git a/contracts/src/v0.8/l2ep/test/v1_0_0/shared/BaseValidator.t.sol b/contracts/src/v0.8/l2ep/test/v1_0_0/shared/BaseValidator.t.sol deleted file mode 100644 index 4b0868c71b3..00000000000 --- a/contracts/src/v0.8/l2ep/test/v1_0_0/shared/BaseValidator.t.sol +++ /dev/null @@ -1,57 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.24; - -import {BaseValidator} from "../../../base/BaseValidator.sol"; -import {MockBaseValidator} from "../../mocks/MockBaseValidator.sol"; -import {L2EPTest} from "../L2EPTest.t.sol"; - -contract BaseValidator_Setup is L2EPTest { - address internal immutable L2_SEQ_STATUS_RECORDER_ADDRESS = makeAddr("L2_SEQ_STATUS_RECORDER_ADDRESS"); - address internal immutable DUMMY_L1_XDOMAIN_MSNGR_ADDR = makeAddr("DUMMY_L1_XDOMAIN_MSNGR_ADDR"); - address internal immutable DUMMY_L2_UPTIME_FEED_ADDR = makeAddr("DUMMY_L2_UPTIME_FEED_ADDR"); - uint32 internal constant INIT_GAS_LIMIT = 1900000; - - BaseValidator internal s_baseValidator; - - /// Fake event that will get emitted when `requestL2TransactionDirect` is called - /// Definition is taken from MockZKSyncL1Bridge - event SentMessage(address indexed sender, bytes message); - - /// Setup - function setUp() public { - s_baseValidator = new MockBaseValidator( - DUMMY_L1_XDOMAIN_MSNGR_ADDR, - L2_SEQ_STATUS_RECORDER_ADDRESS, - INIT_GAS_LIMIT - ); - } -} - -contract BaseValidator_Constructor is BaseValidator_Setup { - /// @notice Reverts when L1 bridge address is zero - function test_Constructor_RevertWhen_L1BridgeAddressIsZero() public { - vm.expectRevert(BaseValidator.L1CrossDomainMessengerAddressZero.selector); - new MockBaseValidator(address(0), DUMMY_L2_UPTIME_FEED_ADDR, INIT_GAS_LIMIT); - } - - /// @notice Reverts when L2 Uptime feed address is zero - function test_Constructor_RevertWhen_L2UptimeFeedAddressIsZero() public { - vm.expectRevert(BaseValidator.L2UptimeFeedAddrZero.selector); - new MockBaseValidator(DUMMY_L1_XDOMAIN_MSNGR_ADDR, address(0), INIT_GAS_LIMIT); - } -} - -contract BaseValidator_GetAndSetGasLimit is BaseValidator_Setup { - /// @notice Verifies the correct retrieval and update of the gas limit - function test_GetAndSetGasLimit_CorrectlyHandlesGasLimit() public { - assertEq(s_baseValidator.getGasLimit(), INIT_GAS_LIMIT); - - uint32 newGasLimit = INIT_GAS_LIMIT + 1; - - vm.expectEmit(); - emit BaseValidator.GasLimitUpdated(newGasLimit); - s_baseValidator.setGasLimit(newGasLimit); - - assertEq(s_baseValidator.getGasLimit(), newGasLimit); - } -} diff --git a/contracts/src/v0.8/l2ep/test/v1_0_0/zksync/ZKSyncSequencerUptimeFeed.t.sol b/contracts/src/v0.8/l2ep/test/v1_0_0/zksync/ZKSyncSequencerUptimeFeed.t.sol index 8e9c387c875..6d90b3973e9 100644 --- a/contracts/src/v0.8/l2ep/test/v1_0_0/zksync/ZKSyncSequencerUptimeFeed.t.sol +++ b/contracts/src/v0.8/l2ep/test/v1_0_0/zksync/ZKSyncSequencerUptimeFeed.t.sol @@ -2,51 +2,290 @@ pragma solidity ^0.8.24; import {AddressAliasHelper} from "../../../../vendor/arb-bridge-eth/v0.8.0-custom/contracts/libraries/AddressAliasHelper.sol"; -import {ZKSyncSequencerUptimeFeed} from "../../../zksync/ZKSyncSequencerUptimeFeed.sol"; -import {BaseSequencerUptimeFeed} from "../../../base/BaseSequencerUptimeFeed.sol"; +import {ZKSyncSequencerUptimeFeed} from "../../../dev/zksync/ZKSyncSequencerUptimeFeed.sol"; +import {BaseSequencerUptimeFeed} from "../../../dev/shared/BaseSequencerUptimeFeed.sol"; +import {FeedConsumer} from "../../../../tests/FeedConsumer.sol"; import {L2EPTest} from "../L2EPTest.t.sol"; -contract ZKSyncSequencerUptimeFeed_TestWrapper is ZKSyncSequencerUptimeFeed { - constructor(address l1SenderAddress, bool initialStatus) ZKSyncSequencerUptimeFeed(l1SenderAddress, initialStatus) {} - - /// @notice Exposes the internal _validateSender function for testing - function validateSenderTestWrapper(address l1Sender) external view { - super._validateSender(l1Sender); - } -} - -contract ZKSyncSequencerUptimeFeed_Setup is L2EPTest { +contract ZKSyncSequencerUptimeFeedTest is L2EPTest { /// Helper Variables - address internal l1SenderAddress = address(5); - address internal s_aliasedL1SenderAddress = AddressAliasHelper.applyL1ToL2Alias(l1SenderAddress); + address internal s_aliasedL1OwnerAddress = AddressAliasHelper.applyL1ToL2Alias(s_l1OwnerAddr); /// L2EP contracts - ZKSyncSequencerUptimeFeed_TestWrapper internal s_zksyncSequencerUptimeFeed; + ZKSyncSequencerUptimeFeed internal s_zksyncSequencerUptimeFeed; + + /// Events + event UpdateIgnored(bool latestStatus, uint64 latestTimestamp, bool incomingStatus, uint64 incomingTimestamp); + event AnswerUpdated(int256 indexed current, uint256 indexed roundId, uint256 updatedAt); + event RoundUpdated(int256 status, uint64 updatedAt); /// Setup function setUp() public { // Deploys contracts - s_zksyncSequencerUptimeFeed = new ZKSyncSequencerUptimeFeed_TestWrapper(l1SenderAddress, false); + s_zksyncSequencerUptimeFeed = new ZKSyncSequencerUptimeFeed(s_l1OwnerAddr, false); + } +} + +contract ZKSyncSequencerUptimeFeed_Constructor is ZKSyncSequencerUptimeFeedTest { + /// @notice it should have been deployed with the correct initial state + function test_InitialState() public { + // Sets msg.sender and tx.origin to a valid address + vm.startPrank(s_l1OwnerAddr, s_l1OwnerAddr); + + // Checks L1 sender + address actualL1Addr = s_zksyncSequencerUptimeFeed.l1Sender(); + assertEq(actualL1Addr, s_l1OwnerAddr); + + // Checks latest round data + (uint80 roundId, int256 answer, , , ) = s_zksyncSequencerUptimeFeed.latestRoundData(); + assertEq(roundId, 1); + assertEq(answer, 0); } } -contract ZKSyncSequencerUptimeFeed_ValidateSender is ZKSyncSequencerUptimeFeed_Setup { - /// @notice Reverts when pass is not valid - function test_ValidateSender_RevertWhen_PassIsNotValid() public { - // Sets msg.sender and tx.origin to an authorized address - vm.startPrank(s_aliasedL1SenderAddress, s_aliasedL1SenderAddress); +contract ZKSyncSequencerUptimeFeed_UpdateStatus is ZKSyncSequencerUptimeFeedTest { + /// @notice it should revert if called by an unauthorized account + function test_RevertIfNotL2CrossDomainMessengerAddr() public { + // Sets msg.sender and tx.origin to an unauthorized address + vm.startPrank(s_strangerAddr, s_strangerAddr); // Tries to update the status from an unauthorized account vm.expectRevert(BaseSequencerUptimeFeed.InvalidSender.selector); - s_zksyncSequencerUptimeFeed.validateSenderTestWrapper(address(6)); + s_zksyncSequencerUptimeFeed.updateStatus(true, uint64(1)); + } + + /// @notice it should update status when status has not changed and incoming timestamp is the same as latest + function test_UpdateStatusWhenNoChange() public { + // Sets msg.sender and tx.origin to a valid address + vm.startPrank(s_aliasedL1OwnerAddress, s_aliasedL1OwnerAddress); + + // Fetches the latest timestamp + uint256 timestamp = s_zksyncSequencerUptimeFeed.latestTimestamp(); + + // Submits a status update + vm.expectEmit(); + emit AnswerUpdated(1, 2, timestamp); + s_zksyncSequencerUptimeFeed.updateStatus(true, uint64(timestamp)); + assertEq(s_zksyncSequencerUptimeFeed.latestAnswer(), 1); + assertEq(s_zksyncSequencerUptimeFeed.latestTimestamp(), uint64(timestamp)); + + // Stores the current round data before updating it + ( + uint80 roundIdBeforeUpdate, + int256 answerBeforeUpdate, + uint256 startedAtBeforeUpdate, + , + uint80 answeredInRoundBeforeUpdate + ) = s_zksyncSequencerUptimeFeed.latestRoundData(); + + // Submit another status update with the same status + vm.expectEmit(); + emit RoundUpdated(1, uint64(block.timestamp)); + s_zksyncSequencerUptimeFeed.updateStatus(true, uint64(timestamp + 200)); + assertEq(s_zksyncSequencerUptimeFeed.latestAnswer(), 1); + assertEq(s_zksyncSequencerUptimeFeed.latestTimestamp(), uint64(timestamp)); + + // Stores the current round data after updating it + ( + uint80 roundIdAfterUpdate, + int256 answerAfterUpdate, + uint256 startedAtAfterUpdate, + uint256 updatedAtAfterUpdate, + uint80 answeredInRoundAfterUpdate + ) = s_zksyncSequencerUptimeFeed.latestRoundData(); + + // Verifies the latest round data has been properly updated + assertEq(roundIdAfterUpdate, roundIdBeforeUpdate); + assertEq(answerAfterUpdate, answerBeforeUpdate); + assertEq(startedAtAfterUpdate, startedAtBeforeUpdate); + assertEq(answeredInRoundAfterUpdate, answeredInRoundBeforeUpdate); + assertEq(updatedAtAfterUpdate, block.timestamp); + } + + /// @notice it should update status when status has changed and incoming timestamp is newer than the latest + function test_UpdateStatusWhenStatusChangeAndTimeChange() public { + // Sets msg.sender and tx.origin to a valid address + vm.startPrank(s_aliasedL1OwnerAddress, s_aliasedL1OwnerAddress); + + // Submits a status update + uint256 timestamp = s_zksyncSequencerUptimeFeed.latestTimestamp(); + vm.expectEmit(); + emit AnswerUpdated(1, 2, timestamp); + s_zksyncSequencerUptimeFeed.updateStatus(true, uint64(timestamp)); + assertEq(s_zksyncSequencerUptimeFeed.latestAnswer(), 1); + assertEq(s_zksyncSequencerUptimeFeed.latestTimestamp(), uint64(timestamp)); + + // Submit another status update, different status, newer timestamp should update + timestamp = timestamp + 200; + vm.expectEmit(); + emit AnswerUpdated(0, 3, timestamp); + s_zksyncSequencerUptimeFeed.updateStatus(false, uint64(timestamp)); + assertEq(s_zksyncSequencerUptimeFeed.latestAnswer(), 0); + assertEq(s_zksyncSequencerUptimeFeed.latestTimestamp(), uint64(timestamp)); + } + + /// @notice it should update status when status has changed and incoming timestamp is the same as latest + function test_UpdateStatusWhenStatusChangeAndNoTimeChange() public { + // Sets msg.sender and tx.origin to a valid address + vm.startPrank(s_aliasedL1OwnerAddress, s_aliasedL1OwnerAddress); + + // Fetches the latest timestamp + uint256 timestamp = s_zksyncSequencerUptimeFeed.latestTimestamp(); + + // Submits a status update + vm.expectEmit(); + emit AnswerUpdated(1, 2, timestamp); + s_zksyncSequencerUptimeFeed.updateStatus(true, uint64(timestamp)); + assertEq(s_zksyncSequencerUptimeFeed.latestAnswer(), 1); + assertEq(s_zksyncSequencerUptimeFeed.latestTimestamp(), uint64(timestamp)); + + // Submit another status update, different status, same timestamp should update + vm.expectEmit(); + emit AnswerUpdated(0, 3, timestamp); + s_zksyncSequencerUptimeFeed.updateStatus(false, uint64(timestamp)); + assertEq(s_zksyncSequencerUptimeFeed.latestAnswer(), 0); + assertEq(s_zksyncSequencerUptimeFeed.latestTimestamp(), uint64(timestamp)); + } + + /// @notice it should ignore out-of-order updates + function test_IgnoreOutOfOrderUpdates() public { + // Sets msg.sender and tx.origin to a valid address + vm.startPrank(s_aliasedL1OwnerAddress, s_aliasedL1OwnerAddress); + + // Submits a status update + uint256 timestamp = s_zksyncSequencerUptimeFeed.latestTimestamp() + 10000; + vm.expectEmit(); + emit AnswerUpdated(1, 2, timestamp); + s_zksyncSequencerUptimeFeed.updateStatus(true, uint64(timestamp)); + assertEq(s_zksyncSequencerUptimeFeed.latestAnswer(), 1); + assertEq(s_zksyncSequencerUptimeFeed.latestTimestamp(), uint64(timestamp)); + + // Update with different status, but stale timestamp, should be ignored + timestamp = timestamp - 1000; + vm.expectEmit(false, false, false, false); + emit UpdateIgnored(true, 0, true, 0); // arguments are dummy values + // TODO: how can we check that an AnswerUpdated event was NOT emitted + s_zksyncSequencerUptimeFeed.updateStatus(false, uint64(timestamp)); + } +} + +contract ZKSyncSequencerUptimeFeed_AggregatorV3Interface is ZKSyncSequencerUptimeFeedTest { + /// @notice it should return valid answer from getRoundData and latestRoundData + function test_AggregatorV3Interface() public { + // Sets msg.sender and tx.origin to a valid address + vm.startPrank(s_aliasedL1OwnerAddress, s_aliasedL1OwnerAddress); + + // Defines helper variables + uint80 roundId; + int256 answer; + uint256 startedAt; + uint256 updatedAt; + uint80 answeredInRound; + + // Checks initial state + (roundId, answer, startedAt, updatedAt, answeredInRound) = s_zksyncSequencerUptimeFeed.latestRoundData(); + assertEq(roundId, 1); + assertEq(answer, 0); + assertEq(answeredInRound, roundId); + assertEq(startedAt, updatedAt); + + // Submits status update with different status and newer timestamp, should update + uint256 timestamp = startedAt + 1000; + s_zksyncSequencerUptimeFeed.updateStatus(true, uint64(timestamp)); + (roundId, answer, startedAt, updatedAt, answeredInRound) = s_zksyncSequencerUptimeFeed.getRoundData(2); + assertEq(roundId, 2); + assertEq(answer, 1); + assertEq(answeredInRound, roundId); + assertEq(startedAt, timestamp); + assertLe(updatedAt, startedAt); + + // Saves round 2 data + uint80 roundId2 = roundId; + int256 answer2 = answer; + uint256 startedAt2 = startedAt; + uint256 updatedAt2 = updatedAt; + uint80 answeredInRound2 = answeredInRound; + + // Checks that last round is still returning the correct data + (roundId, answer, startedAt, updatedAt, answeredInRound) = s_zksyncSequencerUptimeFeed.getRoundData(1); + assertEq(roundId, 1); + assertEq(answer, 0); + assertEq(answeredInRound, roundId); + assertEq(startedAt, updatedAt); + + // Assert latestRoundData corresponds to latest round id + (roundId, answer, startedAt, updatedAt, answeredInRound) = s_zksyncSequencerUptimeFeed.latestRoundData(); + assertEq(roundId2, roundId); + assertEq(answer2, answer); + assertEq(startedAt2, startedAt); + assertEq(updatedAt2, updatedAt); + assertEq(answeredInRound2, answeredInRound); + } + + /// @notice it should revert from #getRoundData when round does not yet exist (future roundId) + function test_RevertGetRoundDataWhenRoundDoesNotExistYet() public { + // Sets msg.sender and tx.origin to a valid address + vm.startPrank(s_l1OwnerAddr, s_l1OwnerAddr); + + // Gets data from a round that has not happened yet + vm.expectRevert(BaseSequencerUptimeFeed.NoDataPresent.selector); + s_zksyncSequencerUptimeFeed.getRoundData(2); + } + + /// @notice it should revert from #getAnswer when round does not yet exist (future roundId) + function test_RevertGetAnswerWhenRoundDoesNotExistYet() public { + // Sets msg.sender and tx.origin to a valid address + vm.startPrank(s_l1OwnerAddr, s_l1OwnerAddr); + + // Gets data from a round that has not happened yet + vm.expectRevert(BaseSequencerUptimeFeed.NoDataPresent.selector); + s_zksyncSequencerUptimeFeed.getAnswer(2); + } + + /// @notice it should revert from #getTimestamp when round does not yet exist (future roundId) + function test_RevertGetTimestampWhenRoundDoesNotExistYet() public { + // Sets msg.sender and tx.origin to a valid address + vm.startPrank(s_l1OwnerAddr, s_l1OwnerAddr); + + // Gets data from a round that has not happened yet + vm.expectRevert(BaseSequencerUptimeFeed.NoDataPresent.selector); + s_zksyncSequencerUptimeFeed.getTimestamp(2); } +} + +contract ZKSyncSequencerUptimeFeed_ProtectReadsOnAggregatorV2V3InterfaceFunctions is ZKSyncSequencerUptimeFeedTest { + /// @notice it should disallow reads on AggregatorV2V3Interface functions when consuming contract is not whitelisted + function test_AggregatorV2V3InterfaceDisallowReadsIfConsumingContractIsNotWhitelisted() public { + // Deploys a FeedConsumer contract + FeedConsumer feedConsumer = new FeedConsumer(address(s_zksyncSequencerUptimeFeed)); + + // Sanity - consumer is not whitelisted + assertEq(s_zksyncSequencerUptimeFeed.checkEnabled(), true); + assertEq(s_zksyncSequencerUptimeFeed.hasAccess(address(feedConsumer), abi.encode("")), false); + + // Asserts reads are not possible from consuming contract + vm.expectRevert("No access"); + feedConsumer.latestAnswer(); + vm.expectRevert("No access"); + feedConsumer.latestRoundData(); + } + + /// @notice it should allow reads on AggregatorV2V3Interface functions when consuming contract is whitelisted + function test_AggregatorV2V3InterfaceAllowReadsIfConsumingContractIsWhitelisted() public { + // Deploys a FeedConsumer contract + FeedConsumer feedConsumer = new FeedConsumer(address(s_zksyncSequencerUptimeFeed)); + + // Whitelist consumer + s_zksyncSequencerUptimeFeed.addAccess(address(feedConsumer)); - /// @notice Passes when sender is valid - function test_ValidateSender_SuccessWhen_SenderIsValid() public { - // Sets msg.sender and tx.origin to an authorized address - vm.startPrank(s_aliasedL1SenderAddress, s_aliasedL1SenderAddress); + // Sanity - consumer is whitelisted + assertEq(s_zksyncSequencerUptimeFeed.checkEnabled(), true); + assertEq(s_zksyncSequencerUptimeFeed.hasAccess(address(feedConsumer), abi.encode("")), true); - // Tries to update the status from an authorized account - s_zksyncSequencerUptimeFeed.validateSenderTestWrapper(l1SenderAddress); + // Asserts reads are possible from consuming contract + (uint80 roundId, int256 answer, , , ) = feedConsumer.latestRoundData(); + assertEq(feedConsumer.latestAnswer(), 0); + assertEq(roundId, 1); + assertEq(answer, 0); } } diff --git a/contracts/src/v0.8/l2ep/test/v1_0_0/zksync/ZKSyncValidator.t.sol b/contracts/src/v0.8/l2ep/test/v1_0_0/zksync/ZKSyncValidator.t.sol index e36a2732c27..0bea147c8cd 100644 --- a/contracts/src/v0.8/l2ep/test/v1_0_0/zksync/ZKSyncValidator.t.sol +++ b/contracts/src/v0.8/l2ep/test/v1_0_0/zksync/ZKSyncValidator.t.sol @@ -2,15 +2,15 @@ pragma solidity ^0.8.24; import {MockBridgehub} from "../../mocks/zksync/MockZKSyncL1Bridge.sol"; -import {ISequencerUptimeFeed} from "../../../interfaces/ISequencerUptimeFeed.sol"; -import {ZKSyncValidator} from "../../../zksync/ZKSyncValidator.sol"; -import {BaseValidator} from "../../../base/BaseValidator.sol"; +import {ISequencerUptimeFeed} from "../../../dev/interfaces/ISequencerUptimeFeed.sol"; +import {ZKSyncValidator} from "../../../dev/zksync/ZKSyncValidator.sol"; +import {BaseValidator} from "../../../dev/shared/BaseValidator.sol"; import {L2EPTest} from "../L2EPTest.t.sol"; -contract ZKSyncValidator_Setup is L2EPTest { - address internal immutable L2_SEQ_STATUS_RECORDER_ADDRESS = makeAddr("L2_SEQ_STATUS_RECORDER_ADDRESS"); - address internal immutable DUMMY_L1_XDOMAIN_MSNGR_ADDR = makeAddr("DUMMY_L1_XDOMAIN_MSNGR_ADDR"); - address internal immutable DUMMY_L2_UPTIME_FEED_ADDR = makeAddr("DUMMY_L2_UPTIME_FEED_ADDR"); +contract ZKSyncValidatorTest is L2EPTest { + address internal constant L2_SEQ_STATUS_RECORDER_ADDRESS = address(0x491B1dDA0A8fa069bbC1125133A975BF4e85a91b); + address internal constant DUMMY_L1_XDOMAIN_MSNGR_ADDR = address(0xa04Fc18f012B1a5A8231c7Ee4b916Dd6dbd271b6); + address internal constant DUMMY_L2_UPTIME_FEED_ADDR = address(0xFe31891940A2e5f04B76eD8bD1038E44127d1512); uint32 internal constant INIT_GAS_PER_PUBDATA_BYTE_LIMIT = 800; uint32 internal constant INIT_GAS_LIMIT = 1900000; uint32 internal constant MAIN_NET_CHAIN_ID = 300; @@ -38,9 +38,9 @@ contract ZKSyncValidator_Setup is L2EPTest { } } -contract ZKSyncValidator_Constructor is ZKSyncValidator_Setup { - /// @notice Reverts when chain ID is invalid - function test_Constructor_RevertWhen_ChainIdIsInvalid() public { +contract ZKSyncValidator_Constructor is ZKSyncValidatorTest { + /// @notice it correctly validates that the chain id is valid + function test_ConstructingRevertedWithInvalidChainId() public { vm.expectRevert(ZKSyncValidator.InvalidChainID.selector); new ZKSyncValidator( DUMMY_L1_XDOMAIN_MSNGR_ADDR, @@ -51,8 +51,8 @@ contract ZKSyncValidator_Constructor is ZKSyncValidator_Setup { ); } - /// @notice Reverts when L1 bridge address is zero - function test_Constructor_RevertWhen_L1BridgeAddressIsZero() public { + /// @notice it correctly validates that the L1 bridge address is not zero + function test_ConstructingRevertedWithZeroL1BridgeAddress() public { vm.expectRevert(BaseValidator.L1CrossDomainMessengerAddressZero.selector); new ZKSyncValidator( address(0), @@ -63,8 +63,8 @@ contract ZKSyncValidator_Constructor is ZKSyncValidator_Setup { ); } - /// @notice Reverts when L2 update feed address is zero - function test_Constructor_RevertWhen_L2UpdateFeedAddressIsZero() public { + /// @notice it correctly validates that the L2 Uptime feed address is not zero + function test_ConstructingRevertedWithZeroL2UpdateFeedAddress() public { vm.expectRevert(BaseValidator.L2UptimeFeedAddrZero.selector); new ZKSyncValidator( DUMMY_L1_XDOMAIN_MSNGR_ADDR, @@ -76,9 +76,9 @@ contract ZKSyncValidator_Constructor is ZKSyncValidator_Setup { } } -contract ZKSyncValidator_GetSetL2GasPerPubdataByteLimit is ZKSyncValidator_Setup { - /// @notice Correctly gets and updates the gas per pubdata byte limit - function test_GetSetL2GasPerPubdataByteLimit_CorrectlyHandlesGasPerPubdataByteLimit() public { +contract ZKSyncValidator_GetSetL2GasPerPubdataByteLimit is ZKSyncValidatorTest { + /// @notice it correctly updates the gas limit per pubdata byte + function test_CorrectlyGetsAndUpdatesTheGasPerPubdataByteLimit() public { assertEq(s_zksyncValidator.getL2GasPerPubdataByteLimit(), INIT_GAS_PER_PUBDATA_BYTE_LIMIT); uint32 newGasPerPubDataByteLimit = 2000000; @@ -87,23 +87,23 @@ contract ZKSyncValidator_GetSetL2GasPerPubdataByteLimit is ZKSyncValidator_Setup } } -contract ZKSyncValidator_GetChainId is ZKSyncValidator_Setup { - /// @notice Correctly gets the chain ID - function test_GetChainId_CorrectlyGetsTheChainId() public view { +contract ZKSyncValidator_GetChainId is ZKSyncValidatorTest { + /// @notice it correctly gets the chain id + function test_CorrectlyGetsTheChainId() public { assertEq(s_zksyncValidator.getChainId(), MAIN_NET_CHAIN_ID); } } -contract ZKSyncValidator_Validate is ZKSyncValidator_Setup { - /// @notice Reverts if called by an account with no access - function test_Validate_RevertWhen_CalledByAccountWithNoAccess() public { +contract ZKSyncValidator_Validate is ZKSyncValidatorTest { + /// @notice it reverts if called by account with no access + function test_RevertsIfCalledByAnAccountWithNoAccess() public { vm.startPrank(s_strangerAddr); vm.expectRevert("No access"); s_zksyncValidator.validate(0, 0, 1, 1); } - /// @notice Posts sequencer status when there is no status change - function test_Validate_PostSequencerStatus_NoStatusChange() public { + /// @notice it posts sequencer status when there is not status change + function test_PostSequencerStatusWhenThereIsNotStatusChange() public { // Gives access to the s_eoaValidator s_zksyncValidator.addAccess(s_eoaValidator); @@ -126,8 +126,8 @@ contract ZKSyncValidator_Validate is ZKSyncValidator_Setup { s_zksyncValidator.validate(0, 0, 0, 0); } - /// @notice Posts sequencer offline status - function test_Validate_PostSequencerOffline() public { + /// @notice it post sequencer offline + function test_PostSequencerOffline() public { // Gives access to the s_eoaValidator s_zksyncValidator.addAccess(s_eoaValidator); diff --git a/contracts/src/v0.8/liquiditymanager/test/LiquidityManager.t.sol b/contracts/src/v0.8/liquiditymanager/test/LiquidityManager.t.sol index 088e36c4f0e..73c9ba74455 100644 --- a/contracts/src/v0.8/liquiditymanager/test/LiquidityManager.t.sol +++ b/contracts/src/v0.8/liquiditymanager/test/LiquidityManager.t.sol @@ -57,14 +57,7 @@ contract LiquidityManagerSetup is LiquidityManagerBaseTest { LiquidityManagerBaseTest.setUp(); s_bridgeAdapter = new MockL1BridgeAdapter(s_l1Token, false); - s_lockReleaseTokenPool = new LockReleaseTokenPool( - s_l1Token, - DEFAULT_TOKEN_DECIMALS, - new address[](0), - address(1), - true, - address(123) - ); + s_lockReleaseTokenPool = new LockReleaseTokenPool(s_l1Token, new address[](0), address(1), true, address(123)); s_liquidityManager = new LiquidityManagerHelper( s_l1Token, i_localChainSelector, @@ -78,7 +71,6 @@ contract LiquidityManagerSetup is LiquidityManagerBaseTest { s_wethBridgeAdapter = new MockL1BridgeAdapter(IERC20(address(s_l1Weth)), true); s_wethLockReleaseTokenPool = new LockReleaseTokenPool( IERC20(address(s_l1Weth)), - DEFAULT_TOKEN_DECIMALS, new address[](0), address(1), true, @@ -280,7 +272,6 @@ contract LiquidityManager_rebalanceLiquidity is LiquidityManagerSetup { MockL1BridgeAdapter remoteBridgeAdapter = new MockL1BridgeAdapter(s_l2Token, false); LockReleaseTokenPool remotePool = new LockReleaseTokenPool( s_l2Token, - DEFAULT_TOKEN_DECIMALS, new address[](0), address(1), true, @@ -410,7 +401,6 @@ contract LiquidityManager_rebalanceLiquidity is LiquidityManagerSetup { MockL1BridgeAdapter remoteBridgeAdapter = new MockL1BridgeAdapter(s_l2Token, false); LockReleaseTokenPool remotePool = new LockReleaseTokenPool( s_l2Token, - DEFAULT_TOKEN_DECIMALS, new address[](0), address(1), true, @@ -532,7 +522,6 @@ contract LiquidityManager_rebalanceLiquidity is LiquidityManagerSetup { MockL1BridgeAdapter remoteBridgeAdapter = new MockL1BridgeAdapter(IERC20(address(s_l2Weth)), true); LockReleaseTokenPool remotePool = new LockReleaseTokenPool( IERC20(address(s_l2Weth)), - DEFAULT_TOKEN_DECIMALS, new address[](0), address(1), true, @@ -828,7 +817,6 @@ contract LiquidityManager_setLocalLiquidityContainer is LiquidityManagerSetup { function test_setLocalLiquidityContainerSuccess() external { LockReleaseTokenPool newPool = new LockReleaseTokenPool( s_l1Token, - DEFAULT_TOKEN_DECIMALS, new address[](0), address(1), true, diff --git a/contracts/src/v0.8/liquiditymanager/test/LiquidityManagerBaseTest.t.sol b/contracts/src/v0.8/liquiditymanager/test/LiquidityManagerBaseTest.t.sol index 48492699473..128a03f255a 100644 --- a/contracts/src/v0.8/liquiditymanager/test/LiquidityManagerBaseTest.t.sol +++ b/contracts/src/v0.8/liquiditymanager/test/LiquidityManagerBaseTest.t.sol @@ -25,7 +25,6 @@ contract LiquidityManagerBaseTest is Test { address internal constant FINANCE = address(0x00000fffffffffffffffffffff); address internal constant OWNER = address(0x00000078772732723782873283); address internal constant STRANGER = address(0x00000999999911111111222222); - uint8 internal constant DEFAULT_TOKEN_DECIMALS = 18; function setUp() public virtual { s_l1Token = new ERC20("l1", "L1"); diff --git a/contracts/src/v0.8/llo-feeds/v0.5.0/configuration/Configurator.sol b/contracts/src/v0.8/llo-feeds/v0.5.0/configuration/Configurator.sol index c946b3e2508..96be15fd6be 100644 --- a/contracts/src/v0.8/llo-feeds/v0.5.0/configuration/Configurator.sol +++ b/contracts/src/v0.8/llo-feeds/v0.5.0/configuration/Configurator.sol @@ -161,7 +161,6 @@ contract Configurator is IConfigurator, ConfirmedOwner, TypeAndVersionInterface, ConfigurationState memory configurationState = s_configurationStates[configId]; if ( - predecessorConfigDigest == bytes32(0) || predecessorConfigDigest != s_configurationStates[configId].configDigest[configurationState.isGreenProduction ? 1 : 0] ) revert InvalidPredecessorConfigDigest(predecessorConfigDigest); diff --git a/contracts/src/v0.8/llo-feeds/v0.5.0/configuration/test/configurator/ConfiguratorSetStagingConfigTest.t.sol b/contracts/src/v0.8/llo-feeds/v0.5.0/configuration/test/configurator/ConfiguratorSetStagingConfigTest.t.sol index cab35c4500e..4487ece16e1 100644 --- a/contracts/src/v0.8/llo-feeds/v0.5.0/configuration/test/configurator/ConfiguratorSetStagingConfigTest.t.sol +++ b/contracts/src/v0.8/llo-feeds/v0.5.0/configuration/test/configurator/ConfiguratorSetStagingConfigTest.t.sol @@ -115,19 +115,6 @@ contract ConfiguratorSetStagingConfigTest is BaseTest { OFFCHAIN_CONFIG_VERSION, offchainConfig ); - - onchainConfig = abi.encode(uint256(1), uint256(0)); - - vm.expectRevert(abi.encodeWithSelector(Configurator.InvalidPredecessorConfigDigest.selector, uint256(0))); - s_configurator.setStagingConfig( - CONFIG_ID_1, - signers, - offchainTransmitters, - f, - onchainConfig, - OFFCHAIN_CONFIG_VERSION, - offchainConfig - ); } function test_correctlyUpdatesTheConfig() public { diff --git a/contracts/src/v0.8/shared/test/token/ERC20/BurnMintERC20/BurnMintERC20.approve.t.sol b/contracts/src/v0.8/shared/test/token/ERC20/BurnMintERC20/BurnMintERC20.approve.t.sol deleted file mode 100644 index d328eec8436..00000000000 --- a/contracts/src/v0.8/shared/test/token/ERC20/BurnMintERC20/BurnMintERC20.approve.t.sol +++ /dev/null @@ -1,31 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.24; - -import {BurnMintERC20Setup} from "./BurnMintERC20Setup.t.sol"; -import {BurnMintERC20} from "../../../../token/ERC20/BurnMintERC20.sol"; - -contract BurnMintERC20_approve is BurnMintERC20Setup { - function test_approve() public { - uint256 balancePre = s_burnMintERC20.balanceOf(STRANGER); - uint256 sendingAmount = s_amount / 2; - - s_burnMintERC20.approve(STRANGER, sendingAmount); - - uint256 ownerBalancePre = s_burnMintERC20.balanceOf(OWNER); - - changePrank(STRANGER); - - s_burnMintERC20.transferFrom(OWNER, STRANGER, sendingAmount); - - assertEq(sendingAmount + balancePre, s_burnMintERC20.balanceOf(STRANGER)); - assertEq(ownerBalancePre - sendingAmount, s_burnMintERC20.balanceOf(OWNER)); - } - - // Reverts - - function test_approve_RevertWhen_InvalidAddress() public { - vm.expectRevert(abi.encodeWithSelector(BurnMintERC20.InvalidRecipient.selector, address(s_burnMintERC20))); - - s_burnMintERC20.approve(address(s_burnMintERC20), s_amount); - } -} diff --git a/contracts/src/v0.8/shared/test/token/ERC20/BurnMintERC20/BurnMintERC20.burn.t.sol b/contracts/src/v0.8/shared/test/token/ERC20/BurnMintERC20/BurnMintERC20.burn.t.sol deleted file mode 100644 index 75fa6e73372..00000000000 --- a/contracts/src/v0.8/shared/test/token/ERC20/BurnMintERC20/BurnMintERC20.burn.t.sol +++ /dev/null @@ -1,56 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.24; - -import {BurnMintERC20} from "../../../../token/ERC20/BurnMintERC20.sol"; -import {BurnMintERC20Setup} from "./BurnMintERC20Setup.t.sol"; - -import {IERC20} from "../../../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; -import {Strings} from "../../../../../vendor/openzeppelin-solidity/v4.8.3/contracts/utils/Strings.sol"; - -contract BurnMintERC20_burn is BurnMintERC20Setup { - function test_BasicBurn() public { - s_burnMintERC20.grantRole(s_burnMintERC20.BURNER_ROLE(), OWNER); - deal(address(s_burnMintERC20), OWNER, s_amount); - - vm.expectEmit(); - emit IERC20.Transfer(OWNER, address(0), s_amount); - - s_burnMintERC20.burn(s_amount); - - assertEq(0, s_burnMintERC20.balanceOf(OWNER)); - } - - // Revert - - function test_burn_RevertWhen_SenderNotBurner() public { - // OZ Access Control v4.8.3 inherited by BurnMintERC20 does not use custom errors, but the revert message is still useful - // and should be checked - vm.expectRevert( - abi.encodePacked( - "AccessControl: account ", - Strings.toHexString(OWNER), - " is missing role ", - Strings.toHexString(uint256(s_burnMintERC20.BURNER_ROLE()), 32) - ) - ); - - s_burnMintERC20.burnFrom(STRANGER, s_amount); - } - - function test_burn_RevertWhen_ExceedsBalance() public { - changePrank(s_mockPool); - - vm.expectRevert("ERC20: burn amount exceeds balance"); - - s_burnMintERC20.burn(s_amount * 2); - } - - function test_burn_RevertWhen_BurnFromZeroAddress() public { - s_burnMintERC20.grantRole(s_burnMintERC20.BURNER_ROLE(), address(0)); - changePrank(address(0)); - - vm.expectRevert("ERC20: burn from the zero address"); - - s_burnMintERC20.burn(0); - } -} diff --git a/contracts/src/v0.8/shared/test/token/ERC20/BurnMintERC20/BurnMintERC20.burnFrom.t.sol b/contracts/src/v0.8/shared/test/token/ERC20/BurnMintERC20/BurnMintERC20.burnFrom.t.sol deleted file mode 100644 index b32d42a86e5..00000000000 --- a/contracts/src/v0.8/shared/test/token/ERC20/BurnMintERC20/BurnMintERC20.burnFrom.t.sol +++ /dev/null @@ -1,58 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.24; - -import {BurnMintERC20} from "../../../../token/ERC20/BurnMintERC20.sol"; -import {BurnMintERC20Setup} from "./BurnMintERC20Setup.t.sol"; - -import {Strings} from "../../../../../vendor/openzeppelin-solidity/v4.8.3/contracts/utils/Strings.sol"; - -contract BurnMintERC20_burnFrom is BurnMintERC20Setup { - function setUp() public virtual override { - BurnMintERC20Setup.setUp(); - } - - function test_BurnFrom() public { - s_burnMintERC20.approve(s_mockPool, s_amount); - - changePrank(s_mockPool); - - s_burnMintERC20.burnFrom(OWNER, s_amount); - - assertEq(0, s_burnMintERC20.balanceOf(OWNER)); - } - - // Reverts - - function test_burnFrom_RevertWhen_SenderNotBurner() public { - // OZ Access Control v4.8.3 inherited by BurnMintERC20 does not use custom errors, but the revert message is still useful - // and should be checked - vm.expectRevert( - abi.encodePacked( - "AccessControl: account ", - Strings.toHexString(OWNER), - " is missing role ", - Strings.toHexString(uint256(s_burnMintERC20.BURNER_ROLE()), 32) - ) - ); - - s_burnMintERC20.burnFrom(OWNER, s_amount); - } - - function test_burnFrom_RevertWhen_InsufficientAllowance() public { - changePrank(s_mockPool); - - vm.expectRevert("ERC20: insufficient allowance"); - - s_burnMintERC20.burnFrom(OWNER, s_amount); - } - - function test_burnFrom_RevertWhen_ExceedsBalance() public { - s_burnMintERC20.approve(s_mockPool, s_amount * 2); - - changePrank(s_mockPool); - - vm.expectRevert("ERC20: burn amount exceeds balance"); - - s_burnMintERC20.burnFrom(OWNER, s_amount * 2); - } -} diff --git a/contracts/src/v0.8/shared/test/token/ERC20/BurnMintERC20/BurnMintERC20.burnFromAlias.t.sol b/contracts/src/v0.8/shared/test/token/ERC20/BurnMintERC20/BurnMintERC20.burnFromAlias.t.sol deleted file mode 100644 index d619968b8f1..00000000000 --- a/contracts/src/v0.8/shared/test/token/ERC20/BurnMintERC20/BurnMintERC20.burnFromAlias.t.sol +++ /dev/null @@ -1,58 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.24; - -import {BurnMintERC20} from "../../../../token/ERC20/BurnMintERC20.sol"; -import {BurnMintERC20Setup} from "./BurnMintERC20Setup.t.sol"; - -import {Strings} from "../../../../../vendor/openzeppelin-solidity/v4.8.3/contracts/utils/Strings.sol"; - -contract BurnMintERC20_burnFromAlias is BurnMintERC20Setup { - function setUp() public virtual override { - BurnMintERC20Setup.setUp(); - } - - function test_burn() public { - s_burnMintERC20.approve(s_mockPool, s_amount); - - changePrank(s_mockPool); - - s_burnMintERC20.burn(OWNER, s_amount); - - assertEq(0, s_burnMintERC20.balanceOf(OWNER)); - } - - // Reverts - - function test_burn_RevertWhen_SenderNotBurner() public { - // OZ Access Control v4.8.3 inherited by BurnMintERC20 does not use custom errors, but the revert message is still useful - // and should be checked - vm.expectRevert( - abi.encodePacked( - "AccessControl: account ", - Strings.toHexString(OWNER), - " is missing role ", - Strings.toHexString(uint256(s_burnMintERC20.BURNER_ROLE()), 32) - ) - ); - - s_burnMintERC20.burn(OWNER, s_amount); - } - - function test_burn_RevertWhen_InsufficientAllowance() public { - changePrank(s_mockPool); - - vm.expectRevert("ERC20: insufficient allowance"); - - s_burnMintERC20.burn(OWNER, s_amount); - } - - function test_burn_RevertWhen_ExceedsBalance() public { - s_burnMintERC20.approve(s_mockPool, s_amount * 2); - - changePrank(s_mockPool); - - vm.expectRevert("ERC20: burn amount exceeds balance"); - - s_burnMintERC20.burn(OWNER, s_amount * 2); - } -} diff --git a/contracts/src/v0.8/shared/test/token/ERC20/BurnMintERC20/BurnMintERC20.ccipGetAdmin.t.sol b/contracts/src/v0.8/shared/test/token/ERC20/BurnMintERC20/BurnMintERC20.ccipGetAdmin.t.sol deleted file mode 100644 index 25b9fa8f2df..00000000000 --- a/contracts/src/v0.8/shared/test/token/ERC20/BurnMintERC20/BurnMintERC20.ccipGetAdmin.t.sol +++ /dev/null @@ -1,22 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.24; - -import {BurnMintERC20} from "../../../../token/ERC20/BurnMintERC20.sol"; -import {BurnMintERC20Setup} from "./BurnMintERC20Setup.t.sol"; - -contract BurnMintERC20_getCCIPAdmin is BurnMintERC20Setup { - function test_getCCIPAdmin() public view { - assertEq(OWNER, s_burnMintERC20.getCCIPAdmin()); - } - - function test_setCCIPAdmin() public { - address newAdmin = makeAddr("newAdmin"); - - vm.expectEmit(); - emit BurnMintERC20.CCIPAdminTransferred(OWNER, newAdmin); - - s_burnMintERC20.setCCIPAdmin(newAdmin); - - assertEq(newAdmin, s_burnMintERC20.getCCIPAdmin()); - } -} diff --git a/contracts/src/v0.8/shared/test/token/ERC20/BurnMintERC20/BurnMintERC20.constructor.t.sol b/contracts/src/v0.8/shared/test/token/ERC20/BurnMintERC20/BurnMintERC20.constructor.t.sol deleted file mode 100644 index b5de63b9b31..00000000000 --- a/contracts/src/v0.8/shared/test/token/ERC20/BurnMintERC20/BurnMintERC20.constructor.t.sol +++ /dev/null @@ -1,27 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.24; - -import {BurnMintERC20Setup} from "./BurnMintERC20Setup.t.sol"; -import {BurnMintERC20} from "../../../../token/ERC20/BurnMintERC20.sol"; - -contract BurnMintERC20_constructor is BurnMintERC20Setup { - function test_Constructor() public { - vm.startPrank(s_alice); - - string memory name = "Chainlink token v2"; - string memory symbol = "LINK2"; - uint8 decimals = 19; - uint256 maxSupply = 1e33; - - s_burnMintERC20 = new BurnMintERC20(name, symbol, decimals, maxSupply, 1e18); - - assertEq(name, s_burnMintERC20.name()); - assertEq(symbol, s_burnMintERC20.symbol()); - assertEq(decimals, s_burnMintERC20.decimals()); - assertEq(maxSupply, s_burnMintERC20.maxSupply()); - - assertTrue(s_burnMintERC20.hasRole(s_burnMintERC20.DEFAULT_ADMIN_ROLE(), s_alice)); - assertEq(s_burnMintERC20.balanceOf(s_alice), 1e18); - assertEq(s_burnMintERC20.totalSupply(), 1e18); - } -} diff --git a/contracts/src/v0.8/shared/test/token/ERC20/BurnMintERC20/BurnMintERC20.grantMintAndBurnRoles.t.sol b/contracts/src/v0.8/shared/test/token/ERC20/BurnMintERC20/BurnMintERC20.grantMintAndBurnRoles.t.sol deleted file mode 100644 index 7a31d2aa078..00000000000 --- a/contracts/src/v0.8/shared/test/token/ERC20/BurnMintERC20/BurnMintERC20.grantMintAndBurnRoles.t.sol +++ /dev/null @@ -1,24 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.24; - -import {BurnMintERC20} from "../../../../token/ERC20/BurnMintERC20.sol"; -import {BurnMintERC20Setup} from "./BurnMintERC20Setup.t.sol"; - -import {IAccessControl} from "../../../../../vendor/openzeppelin-solidity/v4.8.3/contracts/access/IAccessControl.sol"; - -contract BurnMintERC20_grantMintAndBurnRoles is BurnMintERC20Setup { - function test_GrantMintAndBurnRoles() public { - assertFalse(s_burnMintERC20.hasRole(s_burnMintERC20.MINTER_ROLE(), STRANGER)); - assertFalse(s_burnMintERC20.hasRole(s_burnMintERC20.BURNER_ROLE(), STRANGER)); - - vm.expectEmit(); - emit IAccessControl.RoleGranted(s_burnMintERC20.MINTER_ROLE(), STRANGER, OWNER); - vm.expectEmit(); - emit IAccessControl.RoleGranted(s_burnMintERC20.BURNER_ROLE(), STRANGER, OWNER); - - s_burnMintERC20.grantMintAndBurnRoles(STRANGER); - - assertTrue(s_burnMintERC20.hasRole(s_burnMintERC20.MINTER_ROLE(), STRANGER)); - assertTrue(s_burnMintERC20.hasRole(s_burnMintERC20.BURNER_ROLE(), STRANGER)); - } -} diff --git a/contracts/src/v0.8/shared/test/token/ERC20/BurnMintERC20/BurnMintERC20.mint.t.sol b/contracts/src/v0.8/shared/test/token/ERC20/BurnMintERC20/BurnMintERC20.mint.t.sol deleted file mode 100644 index fd97b80fa60..00000000000 --- a/contracts/src/v0.8/shared/test/token/ERC20/BurnMintERC20/BurnMintERC20.mint.t.sol +++ /dev/null @@ -1,61 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.24; - -import {BurnMintERC20} from "../../../../token/ERC20/BurnMintERC20.sol"; -import {BurnMintERC20Setup} from "./BurnMintERC20Setup.t.sol"; - -import {IERC20} from "../../../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; -import {Strings} from "../../../../../vendor/openzeppelin-solidity/v4.8.3/contracts/utils/Strings.sol"; - -contract BurnMintERC20_mint is BurnMintERC20Setup { - function test_mint() public { - uint256 balancePre = s_burnMintERC20.balanceOf(OWNER); - - s_burnMintERC20.grantMintAndBurnRoles(OWNER); - - vm.expectEmit(); - emit IERC20.Transfer(address(0), OWNER, s_amount); - - s_burnMintERC20.mint(OWNER, s_amount); - - assertEq(balancePre + s_amount, s_burnMintERC20.balanceOf(OWNER)); - } - - // Revert - - function test_mint_RevertWhen_SenderNotMinter() public { - vm.startPrank(STRANGER); - - // OZ Access Control v4.8.3 inherited by BurnMintERC20 does not use custom errors, but the revert message is still useful - // and should be checked - vm.expectRevert( - abi.encodePacked( - "AccessControl: account ", - Strings.toHexString(STRANGER), - " is missing role ", - Strings.toHexString(uint256(s_burnMintERC20.MINTER_ROLE()), 32) - ) - ); - - s_burnMintERC20.mint(STRANGER, 1e18); - } - - function test_mint_RevertWhen_MaxSupplyExceeded() public { - changePrank(s_mockPool); - - // Mint max supply - s_burnMintERC20.mint(OWNER, s_burnMintERC20.maxSupply()); - - vm.expectRevert(abi.encodeWithSelector(BurnMintERC20.MaxSupplyExceeded.selector, s_burnMintERC20.maxSupply() + 1)); - - // Attempt to mint 1 more than max supply - s_burnMintERC20.mint(OWNER, 1); - } - - function test_mint_RevertWhen_InvalidRecipient() public { - s_burnMintERC20.grantMintAndBurnRoles(OWNER); - - vm.expectRevert(abi.encodeWithSelector(BurnMintERC20.InvalidRecipient.selector, address(s_burnMintERC20))); - s_burnMintERC20.mint(address(s_burnMintERC20), 1e18); - } -} diff --git a/contracts/src/v0.8/shared/test/token/ERC20/BurnMintERC20/BurnMintERC20.supportsInterface.t.sol b/contracts/src/v0.8/shared/test/token/ERC20/BurnMintERC20/BurnMintERC20.supportsInterface.t.sol deleted file mode 100644 index aa495d047ed..00000000000 --- a/contracts/src/v0.8/shared/test/token/ERC20/BurnMintERC20/BurnMintERC20.supportsInterface.t.sol +++ /dev/null @@ -1,17 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.24; - -import {IBurnMintERC20} from "../../../../../shared/token/ERC20/IBurnMintERC20.sol"; - -import {BurnMintERC20Setup} from "./BurnMintERC20Setup.t.sol"; - -import {IERC20} from "../../../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; -import {IERC165} from "../../../../../vendor/openzeppelin-solidity/v4.8.3/contracts/utils/introspection/IERC165.sol"; - -contract BurnMintERC20_supportsInterface is BurnMintERC20Setup { - function test_SupportsInterface() public view { - assertTrue(s_burnMintERC20.supportsInterface(type(IERC20).interfaceId)); - assertTrue(s_burnMintERC20.supportsInterface(type(IBurnMintERC20).interfaceId)); - assertTrue(s_burnMintERC20.supportsInterface(type(IERC165).interfaceId)); - } -} diff --git a/contracts/src/v0.8/shared/test/token/ERC20/BurnMintERC20/BurnMintERC20.transfer.t.sol b/contracts/src/v0.8/shared/test/token/ERC20/BurnMintERC20/BurnMintERC20.transfer.t.sol deleted file mode 100644 index 6d21e507478..00000000000 --- a/contracts/src/v0.8/shared/test/token/ERC20/BurnMintERC20/BurnMintERC20.transfer.t.sol +++ /dev/null @@ -1,24 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.24; - -import {BurnMintERC20Setup} from "./BurnMintERC20Setup.t.sol"; -import {BurnMintERC20} from "../../../../token/ERC20/BurnMintERC20.sol"; - -contract BurnMintERC20_transfer is BurnMintERC20Setup { - function test_transfer() public { - uint256 balancePre = s_burnMintERC20.balanceOf(STRANGER); - uint256 sendingAmount = s_amount / 2; - - s_burnMintERC20.transfer(STRANGER, sendingAmount); - - assertEq(sendingAmount + balancePre, s_burnMintERC20.balanceOf(STRANGER)); - } - - // Reverts - - function test_transfer_RevertWhen_InvalidAddress() public { - vm.expectRevert(abi.encodeWithSelector(BurnMintERC20.InvalidRecipient.selector, address(s_burnMintERC20))); - - s_burnMintERC20.transfer(address(s_burnMintERC20), s_amount); - } -} diff --git a/contracts/src/v0.8/shared/test/token/ERC20/BurnMintERC20/BurnMintERC20Setup.t.sol b/contracts/src/v0.8/shared/test/token/ERC20/BurnMintERC20/BurnMintERC20Setup.t.sol deleted file mode 100644 index 4ba1bd410e3..00000000000 --- a/contracts/src/v0.8/shared/test/token/ERC20/BurnMintERC20/BurnMintERC20Setup.t.sol +++ /dev/null @@ -1,26 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.24; - -import {BurnMintERC20} from "../../../../token/ERC20/BurnMintERC20.sol"; -import {BaseTest} from "../../../BaseTest.t.sol"; - -contract BurnMintERC20Setup is BaseTest { - BurnMintERC20 internal s_burnMintERC20; - - address internal s_mockPool = makeAddr("s_mockPool"); - uint256 internal s_amount = 1e18; - - address internal s_alice; - - function setUp() public virtual override { - BaseTest.setUp(); - - s_alice = makeAddr("alice"); - - s_burnMintERC20 = new BurnMintERC20("Chainlink Token", "LINK", 18, 1e27, 0); - - // Set s_mockPool to be a burner and minter - s_burnMintERC20.grantMintAndBurnRoles(s_mockPool); - deal(address(s_burnMintERC20), OWNER, s_amount); - } -} diff --git a/contracts/src/v0.8/shared/token/ERC20/BurnMintERC20.sol b/contracts/src/v0.8/shared/token/ERC20/BurnMintERC20.sol deleted file mode 100644 index ea11dc08798..00000000000 --- a/contracts/src/v0.8/shared/token/ERC20/BurnMintERC20.sol +++ /dev/null @@ -1,162 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.4; - -import {IGetCCIPAdmin} from "../../../ccip/interfaces/IGetCCIPAdmin.sol"; -import {IBurnMintERC20} from "../../../shared/token/ERC20/IBurnMintERC20.sol"; - -import {AccessControl} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/access/AccessControl.sol"; -import {IAccessControl} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/access/IAccessControl.sol"; -import {ERC20} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/ERC20.sol"; -import {IERC20} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; -import {ERC20Burnable} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/extensions/ERC20Burnable.sol"; -import {IERC165} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/utils/introspection/IERC165.sol"; - -/// @notice A basic ERC20 compatible token contract with burn and minting roles. -/// @dev The total supply can be limited during deployment. -contract BurnMintERC20 is IBurnMintERC20, IGetCCIPAdmin, IERC165, ERC20Burnable, AccessControl { - error MaxSupplyExceeded(uint256 supplyAfterMint); - error InvalidRecipient(address recipient); - - event CCIPAdminTransferred(address indexed previousAdmin, address indexed newAdmin); - - /// @dev The number of decimals for the token - uint8 internal immutable i_decimals; - - /// @dev The maximum supply of the token, 0 if unlimited - uint256 internal immutable i_maxSupply; - - /// @dev the CCIPAdmin can be used to register with the CCIP token admin registry, but has no other special powers, - /// and can only be transferred by the owner. - address internal s_ccipAdmin; - - bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE"); - bytes32 public constant BURNER_ROLE = keccak256("BURNER_ROLE"); - - /// @dev the underscores in parameter names are used to suppress compiler warnings about shadowing ERC20 functions - constructor( - string memory name, - string memory symbol, - uint8 decimals_, - uint256 maxSupply_, - uint256 preMint - ) ERC20(name, symbol) { - i_decimals = decimals_; - i_maxSupply = maxSupply_; - - s_ccipAdmin = msg.sender; - - // Mint the initial supply to the new Owner, saving gas by not calling if the mint amount is zero - if (preMint != 0) _mint(msg.sender, preMint); - - // Set up the owner as the initial minter and burner - _grantRole(DEFAULT_ADMIN_ROLE, msg.sender); - } - - /// @inheritdoc IERC165 - function supportsInterface(bytes4 interfaceId) public pure virtual override(AccessControl, IERC165) returns (bool) { - return - interfaceId == type(IERC20).interfaceId || - interfaceId == type(IBurnMintERC20).interfaceId || - interfaceId == type(IERC165).interfaceId || - interfaceId == type(IAccessControl).interfaceId || - interfaceId == type(IGetCCIPAdmin).interfaceId; - } - - // ================================================================ - // │ ERC20 │ - // ================================================================ - - /// @dev Returns the number of decimals used in its user representation. - function decimals() public view virtual override returns (uint8) { - return i_decimals; - } - - /// @dev Returns the max supply of the token, 0 if unlimited. - function maxSupply() public view virtual returns (uint256) { - return i_maxSupply; - } - - /// @dev Uses OZ ERC20 _transfer to disallow sending to address(0). - /// @dev Disallows sending to address(this) - function _transfer(address from, address to, uint256 amount) internal virtual override { - if (to == address(this)) revert InvalidRecipient(to); - - super._transfer(from, to, amount); - } - - /// @dev Uses OZ ERC20 _approve to disallow approving for address(0). - /// @dev Disallows approving for address(this) - function _approve(address owner, address spender, uint256 amount) internal virtual override { - if (spender == address(this)) revert InvalidRecipient(spender); - - super._approve(owner, spender, amount); - } - - // ================================================================ - // │ Burning & minting │ - // ================================================================ - - /// @inheritdoc ERC20Burnable - /// @dev Uses OZ ERC20 _burn to disallow burning from address(0). - /// @dev Decreases the total supply. - function burn(uint256 amount) public override(IBurnMintERC20, ERC20Burnable) onlyRole(BURNER_ROLE) { - super.burn(amount); - } - - /// @inheritdoc IBurnMintERC20 - /// @dev Alias for BurnFrom for compatibility with the older naming convention. - /// @dev Uses burnFrom for all validation & logic. - function burn(address account, uint256 amount) public virtual override { - burnFrom(account, amount); - } - - /// @inheritdoc ERC20Burnable - /// @dev Uses OZ ERC20 _burn to disallow burning from address(0). - /// @dev Decreases the total supply. - function burnFrom( - address account, - uint256 amount - ) public override(IBurnMintERC20, ERC20Burnable) onlyRole(BURNER_ROLE) { - super.burnFrom(account, amount); - } - - /// @inheritdoc IBurnMintERC20 - /// @dev Uses OZ ERC20 _mint to disallow minting to address(0). - /// @dev Disallows minting to address(this) - /// @dev Increases the total supply. - function mint(address account, uint256 amount) external override onlyRole(MINTER_ROLE) { - if (account == address(this)) revert InvalidRecipient(account); - if (i_maxSupply != 0 && totalSupply() + amount > i_maxSupply) revert MaxSupplyExceeded(totalSupply() + amount); - - _mint(account, amount); - } - - // ================================================================ - // │ Roles │ - // ================================================================ - - /// @notice grants both mint and burn roles to `burnAndMinter`. - /// @dev calls public functions so this function does not require - /// access controls. This is handled in the inner functions. - function grantMintAndBurnRoles(address burnAndMinter) external { - grantRole(MINTER_ROLE, burnAndMinter); - grantRole(BURNER_ROLE, burnAndMinter); - } - - /// @notice Returns the current CCIPAdmin - function getCCIPAdmin() external view returns (address) { - return s_ccipAdmin; - } - - /// @notice Transfers the CCIPAdmin role to a new address - /// @dev only the owner can call this function, NOT the current ccipAdmin, and 1-step ownership transfer is used. - /// @param newAdmin The address to transfer the CCIPAdmin role to. Setting to address(0) is a valid way to revoke - /// the role - function setCCIPAdmin(address newAdmin) external onlyRole(DEFAULT_ADMIN_ROLE) { - address currentAdmin = s_ccipAdmin; - - s_ccipAdmin = newAdmin; - - emit CCIPAdminTransferred(currentAdmin, newAdmin); - } -} diff --git a/contracts/src/v0.8/transmission/dev/ERC-4337/Paymaster.sol b/contracts/src/v0.8/transmission/dev/ERC-4337/Paymaster.sol new file mode 100644 index 00000000000..932d35006c4 --- /dev/null +++ b/contracts/src/v0.8/transmission/dev/ERC-4337/Paymaster.sol @@ -0,0 +1,134 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.19; + +import {IPaymaster} from "../../../vendor/entrypoint/interfaces/IPaymaster.sol"; +import {SCALibrary} from "./SCALibrary.sol"; +import {LinkTokenInterface} from "../../../shared/interfaces/LinkTokenInterface.sol"; +import {AggregatorV3Interface} from "../../../shared/interfaces/AggregatorV3Interface.sol"; +import {ConfirmedOwner} from "../../../shared/access/ConfirmedOwner.sol"; +import {UserOperation} from "../../../vendor/entrypoint/interfaces/UserOperation.sol"; +import {_packValidationData} from "../../../vendor/entrypoint/core/Helpers.sol"; + +/// @dev LINK token paymaster implementation. +/// TODO: more documentation. +contract Paymaster is IPaymaster, ConfirmedOwner { + error OnlyCallableFromLink(); + error InvalidCalldata(); + error Unauthorized(address sender, address validator); + error UserOperationAlreadyTried(bytes32 userOpHash); + error InsufficientFunds(uint256 juelsNeeded, uint256 subscriptionBalance); + + LinkTokenInterface public immutable i_linkToken; + AggregatorV3Interface public immutable i_linkEthFeed; + address public immutable i_entryPoint; + + struct Config { + uint32 stalenessSeconds; + int256 fallbackWeiPerUnitLink; + } + Config public s_config; + + mapping(bytes32 => bool) internal s_userOpHashMapping; + mapping(address => uint256) internal s_subscriptions; + + constructor( + LinkTokenInterface linkToken, + AggregatorV3Interface linkEthFeed, + address entryPoint + ) ConfirmedOwner(msg.sender) { + i_linkToken = linkToken; + i_linkEthFeed = linkEthFeed; + i_entryPoint = entryPoint; + } + + function setConfig(uint32 stalenessSeconds, int256 fallbackWeiPerUnitLink) external onlyOwner { + s_config = Config({stalenessSeconds: stalenessSeconds, fallbackWeiPerUnitLink: fallbackWeiPerUnitLink}); + } + + function onTokenTransfer(address /* _sender */, uint256 _amount, bytes calldata _data) external { + if (msg.sender != address(i_linkToken)) { + revert OnlyCallableFromLink(); + } + if (_data.length != 32) { + revert InvalidCalldata(); + } + + address subscription = abi.decode(_data, (address)); + s_subscriptions[subscription] += _amount; + } + + function validatePaymasterUserOp( + UserOperation calldata userOp, + bytes32 userOpHash, + uint256 maxCost + ) external returns (bytes memory context, uint256 validationData) { + if (msg.sender != i_entryPoint) { + revert Unauthorized(msg.sender, i_entryPoint); + } + if (s_userOpHashMapping[userOpHash]) { + revert UserOperationAlreadyTried(userOpHash); + } + + uint256 extraCostJuels = _handleExtraCostJuels(userOp); + uint256 costJuels = _getCostJuels(maxCost) + extraCostJuels; + if (s_subscriptions[userOp.sender] < costJuels) { + revert InsufficientFunds(costJuels, s_subscriptions[userOp.sender]); + } + + s_userOpHashMapping[userOpHash] = true; + return (abi.encode(userOp.sender, extraCostJuels), _packValidationData(false, 0, 0)); // success + } + + /// @dev Calculates any extra LINK cost for the user operation, based on the funding type passed to the + /// @dev paymaster. Handles funding the LINK token funding described in the user operation. + /// TODO: add logic for subscription top-up. + function _handleExtraCostJuels(UserOperation calldata userOp) internal returns (uint256 extraCost) { + if (userOp.paymasterAndData.length == 20) { + return 0; // no extra data, stop here + } + + uint8 paymentType = uint8(userOp.paymasterAndData[20]); + + // For direct funding, use top-up logic. + if (paymentType == uint8(SCALibrary.LinkPaymentType.DIRECT_FUNDING)) { + SCALibrary.DirectFundingData memory directFundingData = abi.decode( + userOp.paymasterAndData[21:], + (SCALibrary.DirectFundingData) + ); + if ( + directFundingData.topupThreshold != 0 && + i_linkToken.balanceOf(directFundingData.recipient) < directFundingData.topupThreshold + ) { + i_linkToken.transfer(directFundingData.recipient, directFundingData.topupAmount); + extraCost = directFundingData.topupAmount; + } + } + return extraCost; + } + + /// @dev Deducts user subscription balance after execution. + function postOp(PostOpMode /* mode */, bytes calldata context, uint256 actualGasCost) external { + if (msg.sender != i_entryPoint) { + revert Unauthorized(msg.sender, i_entryPoint); + } + (address sender, uint256 extraCostJuels) = abi.decode(context, (address, uint256)); + s_subscriptions[sender] -= (_getCostJuels(actualGasCost) + extraCostJuels); + } + + function _getCostJuels(uint256 costWei) internal view returns (uint256 costJuels) { + costJuels = (1e18 * costWei) / uint256(_getFeedData()); + return costJuels; + } + + function _getFeedData() internal view returns (int256) { + uint32 stalenessSeconds = s_config.stalenessSeconds; + bool staleFallback = stalenessSeconds > 0; + uint256 timestamp; + int256 weiPerUnitLink; + (, weiPerUnitLink, , timestamp, ) = i_linkEthFeed.latestRoundData(); + if (staleFallback && stalenessSeconds < block.timestamp - timestamp) { + weiPerUnitLink = s_config.fallbackWeiPerUnitLink; + } + return weiPerUnitLink; + } +} diff --git a/contracts/src/v0.8/transmission/dev/ERC-4337/SCA.sol b/contracts/src/v0.8/transmission/dev/ERC-4337/SCA.sol new file mode 100644 index 00000000000..589c55f5b3b --- /dev/null +++ b/contracts/src/v0.8/transmission/dev/ERC-4337/SCA.sol @@ -0,0 +1,73 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.19; + +import {IAccount} from "../../../vendor/entrypoint/interfaces/IAccount.sol"; +import {SCALibrary} from "./SCALibrary.sol"; +import {UserOperation} from "../../../vendor/entrypoint/interfaces/UserOperation.sol"; +import {_packValidationData} from "../../../vendor/entrypoint/core/Helpers.sol"; + +/// @dev Smart Contract Account, a contract deployed for a single user and that allows +/// @dev them to invoke meta-transactions. +/// TODO: Consider making the Smart Contract Account upgradeable. +contract SCA is IAccount { + uint256 public s_nonce; + address public immutable i_owner; + address public immutable i_entryPoint; + + error IncorrectNonce(uint256 currentNonce, uint256 nonceGiven); + error NotAuthorized(address sender); + error BadFormatOrOOG(); + error TransactionExpired(uint256 deadline, uint256 currentTimestamp); + error InvalidSignature(bytes32 operationHash, address owner); + + // Assign the owner of this contract upon deployment. + constructor(address owner, address entryPoint) { + i_owner = owner; + i_entryPoint = entryPoint; + } + + /// @dev Validates the user operation via a signature check. + /// TODO: Utilize a "validAfter" for a tx to be only valid _after_ a certain time. + function validateUserOp( + UserOperation calldata userOp, + bytes32 userOpHash, + uint256 /* missingAccountFunds - unused in favor of paymaster */ + ) external returns (uint256 validationData) { + if (userOp.nonce != s_nonce) { + // Revert for non-signature errors. + revert IncorrectNonce(s_nonce, userOp.nonce); + } + + // Verify signature on hash. + bytes32 fullHash = SCALibrary._getUserOpFullHash(userOpHash, address(this)); + bytes memory signature = userOp.signature; + if (SCALibrary._recoverSignature(signature, fullHash) != i_owner) { + return _packValidationData(true, 0, 0); // signature error + } + s_nonce++; + + // Unpack deadline, return successful signature. + (, , uint48 deadline, ) = abi.decode(userOp.callData[4:], (address, uint256, uint48, bytes)); + return _packValidationData(false, deadline, 0); + } + + /// @dev Execute a transaction on behalf of the owner. This function can only + /// @dev be called by the EntryPoint contract, and assumes that `validateUserOp` has succeeded. + function executeTransactionFromEntryPoint(address to, uint256 value, uint48 deadline, bytes calldata data) external { + if (msg.sender != i_entryPoint) { + revert NotAuthorized(msg.sender); + } + if (deadline != 0 && block.timestamp > deadline) { + revert TransactionExpired(deadline, block.timestamp); + } + + // Execute transaction. Bubble up an error if found. + (bool success, bytes memory returnData) = to.call{value: value}(data); + if (!success) { + if (returnData.length == 0) revert BadFormatOrOOG(); + assembly { + revert(add(32, returnData), mload(returnData)) + } + } + } +} diff --git a/contracts/src/v0.8/transmission/dev/ERC-4337/SCALibrary.sol b/contracts/src/v0.8/transmission/dev/ERC-4337/SCALibrary.sol new file mode 100644 index 00000000000..095a3428ef4 --- /dev/null +++ b/contracts/src/v0.8/transmission/dev/ERC-4337/SCALibrary.sol @@ -0,0 +1,48 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.19; + +library SCALibrary { + // keccak256("EIP712Domain(uint256 chainId, address verifyingContract)"); + bytes32 internal constant DOMAIN_SEPARATOR = hex"1c7d3b72b37a35523e273aaadd7b4cd66f618bb81429ab053412d51f50ccea61"; + + // keccak256("executeTransactionFromEntryPoint(address to, uint256 value, bytes calldata data)"); + bytes32 internal constant TYPEHASH = hex"4750045d47fce615521b32cee713ff8db50147e98aec5ca94926b52651ca3fa0"; + + enum LinkPaymentType { + DIRECT_FUNDING, + SUBSCRIPTION // TODO: implement + } + + struct DirectFundingData { + address recipient; // recipient of the top-up + uint256 topupThreshold; // set to zero to disable auto-topup + uint256 topupAmount; + } + + function _getUserOpFullHash(bytes32 userOpHash, address scaAddress) internal view returns (bytes32 fullHash) { + bytes32 hashOfEncoding = keccak256(abi.encode(SCALibrary.TYPEHASH, userOpHash)); + fullHash = keccak256( + abi.encodePacked( + bytes1(0x19), + bytes1(0x01), + SCALibrary.DOMAIN_SEPARATOR, + block.chainid, + scaAddress, + hashOfEncoding + ) + ); + return fullHash; + } + + function _recoverSignature(bytes memory signature, bytes32 fullHash) internal pure returns (address) { + bytes32 r; + bytes32 s; + assembly { + r := mload(add(signature, 0x20)) + s := mload(add(signature, 0x40)) + } + uint8 v = uint8(signature[64]); + + return ecrecover(fullHash, v + 27, r, s); + } +} diff --git a/contracts/src/v0.8/transmission/dev/ERC-4337/SmartContractAccountFactory.sol b/contracts/src/v0.8/transmission/dev/ERC-4337/SmartContractAccountFactory.sol new file mode 100644 index 00000000000..f27c8e15cf6 --- /dev/null +++ b/contracts/src/v0.8/transmission/dev/ERC-4337/SmartContractAccountFactory.sol @@ -0,0 +1,33 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.19; + +contract SmartContractAccountFactory { + event ContractCreated(address scaAddress); + + error DeploymentFailed(); + + /// @dev Use create2 to deploy a new Smart Contract Account. + /// @dev See EIP-1014 for more on CREATE2. + /// TODO: Return the address of the Smart Contract Account even if it is already + /// deployed. + function deploySmartContractAccount( + bytes32 abiEncodedOwnerAddress, + bytes memory initCode + ) external payable returns (address scaAddress) { + assembly { + scaAddress := create2( + 0, // value - left at zero here + add(0x20, initCode), // initialization bytecode + mload(initCode), // length of initialization bytecode + abiEncodedOwnerAddress // user-defined nonce to ensure unique SCA addresses + ) + } + if (scaAddress == address(0)) { + revert DeploymentFailed(); + } + + emit ContractCreated(scaAddress); + + return scaAddress; + } +} diff --git a/contracts/src/v0.8/transmission/dev/testhelpers/Greeter.sol b/contracts/src/v0.8/transmission/dev/testhelpers/Greeter.sol new file mode 100644 index 00000000000..5851c86581e --- /dev/null +++ b/contracts/src/v0.8/transmission/dev/testhelpers/Greeter.sol @@ -0,0 +1,15 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.19; + +/// @dev Ownerless greeter contract. +contract Greeter { + string private s_greeting; + + function setGreeting(string memory greeting) external { + s_greeting = greeting; + } + + function getGreeting() external view returns (string memory) { + return s_greeting; + } +} diff --git a/contracts/src/v0.8/transmission/dev/testhelpers/SmartContractAccountHelper.sol b/contracts/src/v0.8/transmission/dev/testhelpers/SmartContractAccountHelper.sol new file mode 100644 index 00000000000..b080484d8cc --- /dev/null +++ b/contracts/src/v0.8/transmission/dev/testhelpers/SmartContractAccountHelper.sol @@ -0,0 +1,78 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.19; + +import {SCA} from "../ERC-4337/SCA.sol"; +import {SmartContractAccountFactory} from "../ERC-4337/SmartContractAccountFactory.sol"; +import {SCALibrary} from "../ERC-4337/SCALibrary.sol"; + +library SmartContractAccountHelper { + bytes internal constant INITIALIZE_CODE = type(SCA).creationCode; + + function getFullEndTxEncoding( + address endContract, + uint256 value, + uint256 deadline, + bytes memory data + ) public view returns (bytes memory encoding) { + encoding = bytes.concat( + SCA.executeTransactionFromEntryPoint.selector, + abi.encode(endContract, value, block.timestamp + deadline, data) + ); + return encoding; + } + + function getFullHashForSigning(bytes32 userOpHash, address scaAddress) public view returns (bytes32) { + return SCALibrary._getUserOpFullHash(userOpHash, scaAddress); + } + + function getSCAInitCodeWithConstructor( + address owner, + address entryPoint + ) public pure returns (bytes memory initCode) { + initCode = bytes.concat(INITIALIZE_CODE, abi.encode(owner, entryPoint)); + return initCode; + } + + function getInitCode( + address factory, + address owner, + address entryPoint + ) external pure returns (bytes memory initCode) { + bytes32 salt = bytes32(uint256(uint160(owner)) << 96); + bytes memory initializeCodeWithConstructor = bytes.concat(INITIALIZE_CODE, abi.encode(owner, entryPoint)); + initCode = bytes.concat( + bytes20(address(factory)), + abi.encodeWithSelector( + SmartContractAccountFactory.deploySmartContractAccount.selector, + salt, + initializeCodeWithConstructor + ) + ); + return initCode; + } + + /// @dev Computes the smart contract address that results from a CREATE2 operation, per EIP-1014. + function calculateSmartContractAccountAddress( + address owner, + address entryPoint, + address factory + ) external pure returns (address) { + bytes32 salt = bytes32(uint256(uint160(owner)) << 96); + bytes memory initializeCodeWithConstructor = bytes.concat(INITIALIZE_CODE, abi.encode(owner, entryPoint)); + bytes32 initializeCodeHash = keccak256(initializeCodeWithConstructor); + return address(uint160(uint256(keccak256(abi.encodePacked(hex"ff", address(factory), salt, initializeCodeHash))))); + } + + function getAbiEncodedDirectRequestData( + address recipient, + uint256 topupThreshold, + uint256 topupAmount + ) external pure returns (bytes memory) { + SCALibrary.DirectFundingData memory data = SCALibrary.DirectFundingData({ + recipient: recipient, + topupThreshold: topupThreshold, + topupAmount: topupAmount + }); + return abi.encode(data); + } +} diff --git a/contracts/src/v0.8/transmission/test/BaseTest.t.sol b/contracts/src/v0.8/transmission/test/BaseTest.t.sol new file mode 100644 index 00000000000..4da698d1740 --- /dev/null +++ b/contracts/src/v0.8/transmission/test/BaseTest.t.sol @@ -0,0 +1,17 @@ +pragma solidity ^0.8.0; + +import {Test} from "forge-std/Test.sol"; + +contract BaseTest is Test { + bool private s_baseTestInitialized; + address internal constant OWNER = 0x00007e64E1fB0C487F25dd6D3601ff6aF8d32e4e; + + function setUp() public virtual { + // BaseTest.setUp is often called multiple times from tests' setUp due to inheritance. + if (s_baseTestInitialized) return; + s_baseTestInitialized = true; + + // Set msg.sender to OWNER until changePrank or stopPrank is called + vm.startPrank(OWNER); + } +} diff --git a/contracts/src/v0.8/transmission/test/EIP_712_1014_4337.t.sol b/contracts/src/v0.8/transmission/test/EIP_712_1014_4337.t.sol new file mode 100644 index 00000000000..fdfe190de26 --- /dev/null +++ b/contracts/src/v0.8/transmission/test/EIP_712_1014_4337.t.sol @@ -0,0 +1,365 @@ +pragma solidity 0.8.19; + +import "../../shared/interfaces/LinkTokenInterface.sol"; + +import "./BaseTest.t.sol"; +import "../dev/ERC-4337/SmartContractAccountFactory.sol"; +import "../dev/testhelpers/SmartContractAccountHelper.sol"; +import "../dev/ERC-4337/SCA.sol"; +import "../dev/testhelpers/Greeter.sol"; +import "../dev/ERC-4337/Paymaster.sol"; +import "../../transmission/dev/ERC-4337/SCALibrary.sol"; +import "../../mocks/MockLinkToken.sol"; +import "../../tests/MockV3Aggregator.sol"; +import "../../vrf/mocks/VRFCoordinatorMock.sol"; +import "../../vrf/testhelpers/VRFConsumer.sol"; + +import "../../vendor/entrypoint/interfaces/UserOperation.sol"; +import "../../vendor/entrypoint/core/EntryPoint.sol"; +import "../../vendor/entrypoint/interfaces/IEntryPoint.sol"; + +/*--------------------------------------------------------------------------------------------------------------------+ +| EIP 712 + 1014 + 4337 | +| ________________ | +| This implementation allows for meta-transactions to be signed by end-users and posted on-chain by executors. It | +| utilizes the following components: | +| - EIP-712: The method by which meta-transactions are authorized. | +| - EIP-1014: The method by which the Smart Contract Account is generated. | +| - EIP-4337: The method by which meta-transactions are executed. | +| | +| The below tests illustrate end-user flows for interacting with this meta-transaction system. For users with | +| existing Smart Contract Accounts (SCAs), they simply sign off on the operation, after which the executor | +| invokes the EntryPoint that authorizes the operation on the end-user's SCA, and then execute the transaction | +| as the SCA. For users without existing SCAs, EIP-1014 ensures that the address of an SCA can be known in advance, | +| so users can sign-off on transactions that will be executed by a not-yet-deployed SCA. The EntryPoint contract | +| takes advantage of this functionality and allows for the SCA to be created in the same user operation that invokes | +| it, and the end-user signs off on this creation-and-execution flow. After the initial creation-and-execution, the | +| SCA is reused for future transactions. | +| | +| End-Dapps/protocols do not need to be EIP-2771-compliant or accommodate any other kind of transaction standard. | +| They can be interacted with out-of-the-box through the SCA, which acts in place of the user's EOA as their | +| immutable identity. | +| | +-+---------------------------------------------------------------------------------------------------------------------*/ + +contract EIP_712_1014_4337 is BaseTest { + event RandomnessRequest(address indexed sender, bytes32 indexed keyHash, uint256 indexed seed, uint256 fee); + + address internal constant LINK_WHALE = 0xD883a6A1C22fC4AbFE938a5aDF9B2Cc31b1BF18B; + address internal ENTRY_POINT; + + Greeter greeter; + EntryPoint entryPoint; + MockV3Aggregator linkEthFeed; + + // Randomly generated private/public key pair. + uint256 END_USER_PKEY = uint256(bytes32(hex"99d518dbfea4b4ec301390f7e26d53d711fa1ca0c1a6e4cbed89617d4c578a8e")); + address END_USER = 0xB6708257D4E1bf0b8C144793fc2Ff3193C737ed1; + + function setUp() public override { + BaseTest.setUp(); + // Fund user accounts; + vm.deal(END_USER, 10_000 ether); + vm.deal(LINK_WHALE, 10_000 ether); + + // Impersonate a LINK whale. + changePrank(LINK_WHALE); + + // Create simple greeter contract. + greeter = new Greeter(); + assertEq("", greeter.getGreeting()); + + // Create entry point contract. + entryPoint = new EntryPoint(); + ENTRY_POINT = address(entryPoint); + + // Deploy link/eth feed. + linkEthFeed = new MockV3Aggregator(18, 5000000000000000); // .005 ETH + } + + /// @dev Test case for user that already has a Smart Contract Account. + /// @dev EntryPoint.sol should use the existing SCA to execute the meta transaction. + function testEIP712EIP4337WithExistingSmartContractAccount() public { + // Pre-calculate user smart contract account address. + SmartContractAccountFactory factory = new SmartContractAccountFactory(); + address toDeployAddress = SmartContractAccountHelper.calculateSmartContractAccountAddress( + END_USER, + ENTRY_POINT, + address(factory) + ); + + // Deploy the end-contract. + bytes32 salt = bytes32(uint256(uint160(END_USER)) << 96); + bytes memory fullInitializeCode = SmartContractAccountHelper.getSCAInitCodeWithConstructor(END_USER, ENTRY_POINT); + factory.deploySmartContractAccount(salt, fullInitializeCode); + changePrank(END_USER); + + // Ensure a correct deployment and a functioning end-contract. + uint256 contractCodeSize; + assembly { + contractCodeSize := extcodesize(toDeployAddress) + } + assertTrue(contractCodeSize > 0); + assertEq(END_USER, SCA(toDeployAddress).i_owner()); + + // Create the calldata for a setGreeting call. + string memory greeting = "hi"; + bytes memory encodedGreetingCall = bytes.concat(Greeter.setGreeting.selector, abi.encode(greeting)); // abi.encodeWithSelector equivalent + + // Produce the final full end-tx encoding, to be used as calldata in the user operation. + bytes memory fullEncoding = SmartContractAccountHelper.getFullEndTxEncoding( + address(greeter), + uint256(0), + 0, + encodedGreetingCall + ); + + // Construct the user operation. + UserOperation memory op = UserOperation({ + sender: toDeployAddress, + nonce: 0, + initCode: "", + callData: fullEncoding, + callGasLimit: 1_000_000, + verificationGasLimit: 1_000_000, + preVerificationGas: 10_000, + maxFeePerGas: 100, + maxPriorityFeePerGas: 200, + paymasterAndData: "", + signature: "" + }); + + // Sign user operation. + bytes32 userOpHash = entryPoint.getUserOpHash(op); + bytes32 fullHash = SCALibrary._getUserOpFullHash(userOpHash, toDeployAddress); + (uint8 v, bytes32 r, bytes32 s) = vm.sign(END_USER_PKEY, fullHash); + op.signature = abi.encodePacked(r, s, v - 27); + + // Deposit funds for the transaction. + entryPoint.depositTo{value: 10 ether}(toDeployAddress); + + // Execute the user operation. + UserOperation[] memory operations = new UserOperation[](1); + operations[0] = op; + entryPoint.handleOps(operations, payable(END_USER)); + + // Assert that the greeting was set. + assertEq("hi", Greeter(greeter).getGreeting()); + assertEq(SCA(toDeployAddress).s_nonce(), uint256(1)); + } + + /// @dev Test case for fresh user, EntryPoint.sol should generate a + /// @dev Smart Contract Account for them and execute the meta transaction. + function testEIP712EIP4337AndCreateSmartContractAccount() public { + // Pre-calculate user smart contract account address. + SmartContractAccountFactory factory = new SmartContractAccountFactory(); + address toDeployAddress = SmartContractAccountHelper.calculateSmartContractAccountAddress( + END_USER, + ENTRY_POINT, + address(factory) + ); + + // Construct initCode byte array. + bytes memory fullInitializeCode = SmartContractAccountHelper.getInitCode(address(factory), END_USER, ENTRY_POINT); + + // Create the calldata for a setGreeting call. + string memory greeting = "bye"; + bytes memory encodedGreetingCall = bytes.concat(Greeter.setGreeting.selector, abi.encode(greeting)); + + // Produce the final full end-tx encoding, to be used as calldata in the user operation. + bytes memory fullEncoding = SmartContractAccountHelper.getFullEndTxEncoding( + address(greeter), + uint256(0), + 0, + encodedGreetingCall + ); + + // Construct the user operation. + UserOperation memory op = UserOperation({ + sender: toDeployAddress, + nonce: 0, + initCode: fullInitializeCode, + callData: fullEncoding, + callGasLimit: 1_000_000, + verificationGasLimit: 1_000_000, + preVerificationGas: 10_000, + maxFeePerGas: 100, + maxPriorityFeePerGas: 200, + paymasterAndData: "", + signature: "" + }); + + // Sign user operation. + bytes32 userOpHash = entryPoint.getUserOpHash(op); + bytes32 fullHash = SCALibrary._getUserOpFullHash(userOpHash, toDeployAddress); + (uint8 v, bytes32 r, bytes32 s) = vm.sign(END_USER_PKEY, fullHash); + op.signature = abi.encodePacked(r, s, v - 27); + + // Deposit funds for the transaction. + entryPoint.depositTo{value: 10 ether}(toDeployAddress); + + // Execute the user operation. + UserOperation[] memory operations = new UserOperation[](1); + operations[0] = op; + entryPoint.handleOps(operations, payable(END_USER)); + + // Assert that the greeting was set. + assertEq("bye", Greeter(greeter).getGreeting()); + assertEq(SCA(toDeployAddress).s_nonce(), uint256(1)); + assertEq(SCA(toDeployAddress).i_owner(), END_USER); + } + + /// @dev Test case for a user executing a setGreeting with a LINK token paymaster. + function testEIP712EIP4337AndCreateSmartContractAccountWithPaymaster() public { + // Pre-calculate user smart contract account address. + SmartContractAccountFactory factory = new SmartContractAccountFactory(); + address toDeployAddress = SmartContractAccountHelper.calculateSmartContractAccountAddress( + END_USER, + ENTRY_POINT, + address(factory) + ); + + // Construct initCode byte array. + bytes memory fullInitializeCode = SmartContractAccountHelper.getInitCode(address(factory), END_USER, ENTRY_POINT); + + // Create the calldata for a setGreeting call. + string memory greeting = "good day"; + bytes memory encodedGreetingCall = bytes.concat(Greeter.setGreeting.selector, abi.encode(greeting)); + + // Produce the final full end-tx encoding, to be used as calldata in the user operation. + bytes memory fullEncoding = SmartContractAccountHelper.getFullEndTxEncoding( + address(greeter), + uint256(0), + 0, + encodedGreetingCall + ); + + // Create Link token, and deposit into paymaster. + MockLinkToken linkToken = new MockLinkToken(); + Paymaster paymaster = new Paymaster(LinkTokenInterface(address(linkToken)), linkEthFeed, ENTRY_POINT); + linkToken.transferAndCall(address(paymaster), 1000 ether, abi.encode(address(toDeployAddress))); + + // Construct the user opeartion. + UserOperation memory op = UserOperation({ + sender: toDeployAddress, + nonce: 0, + initCode: fullInitializeCode, + callData: fullEncoding, + callGasLimit: 1_000_000, + verificationGasLimit: 1_500_000, + preVerificationGas: 10_000, + maxFeePerGas: 100, + maxPriorityFeePerGas: 200, + paymasterAndData: abi.encodePacked(address(paymaster)), + signature: "" + }); + + // Sign user operation. + bytes32 userOpHash = entryPoint.getUserOpHash(op); + bytes32 fullHash = SCALibrary._getUserOpFullHash(userOpHash, toDeployAddress); + (uint8 v, bytes32 r, bytes32 s) = vm.sign(END_USER_PKEY, fullHash); + op.signature = abi.encodePacked(r, s, v - 27); + + // Deposit funds for the transaction. + entryPoint.depositTo{value: 10 ether}(address(paymaster)); + + // Execute the user operation. + UserOperation[] memory operations = new UserOperation[](1); + operations[0] = op; + entryPoint.handleOps(operations, payable(END_USER)); + + // Assert that the greeting was set. + assertEq("good day", Greeter(greeter).getGreeting()); + assertEq(SCA(toDeployAddress).s_nonce(), uint256(1)); + } + + /// @dev Test case for a VRF Request via LINK token paymaster and an SCA. + function testEIP712EIP4337AndCreateSmartContractAccountWithPaymasterForVRFRequest() public { + // Pre-calculate user smart contract account address. + SmartContractAccountFactory factory = new SmartContractAccountFactory(); + address toDeployAddress = SmartContractAccountHelper.calculateSmartContractAccountAddress( + END_USER, + ENTRY_POINT, + address(factory) + ); + + // Construct initCode byte array. + bytes memory fullInitializeCode = SmartContractAccountHelper.getInitCode(address(factory), END_USER, ENTRY_POINT); + + // Create the calldata for a VRF request. + bytes32 keyhash = bytes32(uint256(123)); + uint256 fee = 1 ether; + bytes memory encodedVRFRequestCallData = bytes.concat( + VRFConsumer.doRequestRandomness.selector, + abi.encode(keyhash, fee) + ); + + // Create the VRF Contracts + MockLinkToken linkToken = new MockLinkToken(); + VRFCoordinatorMock vrfCoordinator = new VRFCoordinatorMock(address(linkToken)); + VRFConsumer vrfConsumer = new VRFConsumer(address(vrfCoordinator), address(linkToken)); + + // Produce the final full end-tx encoding, to be used as calldata in the user operation. + bytes memory fullEncoding = SmartContractAccountHelper.getFullEndTxEncoding( + address(vrfConsumer), // end-contract + uint256(0), // value + 0, // timeout (seconds) + encodedVRFRequestCallData + ); + + // Create Link token, and deposit into paymaster. + Paymaster paymaster = new Paymaster(LinkTokenInterface(address(linkToken)), linkEthFeed, ENTRY_POINT); + linkToken.transferAndCall(address(paymaster), 1000 ether, abi.encode(address(toDeployAddress))); + + // Construct direct funding data. + SCALibrary.DirectFundingData memory directFundingData = SCALibrary.DirectFundingData({ + recipient: address(vrfConsumer), + topupThreshold: 1, + topupAmount: 10 ether + }); + + // Construct the user operation. + UserOperation memory op = UserOperation({ + sender: toDeployAddress, + nonce: 0, + initCode: fullInitializeCode, + callData: fullEncoding, + callGasLimit: 200_000, + verificationGasLimit: 1_000_000, + preVerificationGas: 10_000, + maxFeePerGas: 10, + maxPriorityFeePerGas: 10, + paymasterAndData: abi.encodePacked(address(paymaster), uint8(0), abi.encode(directFundingData)), + signature: "" + }); + + // Sign user operation. + bytes32 fullHash = SCALibrary._getUserOpFullHash(entryPoint.getUserOpHash(op), toDeployAddress); + op.signature = getSignature(fullHash); + + // Deposit funds for the transaction. + entryPoint.depositTo{value: 10 ether}(address(paymaster)); + + // Assert correct log is emitted for the end-contract vrf request. + vm.expectEmit(true, true, true, true); + emit RandomnessRequest( + address(vrfConsumer), + keyhash, + 0, // seed - we use a zero seed + fee + ); + + // Execute the user operation. + UserOperation[] memory operations = new UserOperation[](1); + operations[0] = op; + + // Execute user operation and ensure correct outcome. + entryPoint.handleOps(operations, payable(END_USER)); + assertEq(SCA(toDeployAddress).s_nonce(), uint256(1)); + } + + function getSignature(bytes32 h) internal view returns (bytes memory) { + (uint8 v, bytes32 r, bytes32 s) = vm.sign(END_USER_PKEY, h); + return abi.encodePacked(r, s, v - 27); + } +} diff --git a/contracts/src/v0.8/vendor/entrypoint/core/EntryPoint.sol b/contracts/src/v0.8/vendor/entrypoint/core/EntryPoint.sol new file mode 100644 index 00000000000..86a34b07bf7 --- /dev/null +++ b/contracts/src/v0.8/vendor/entrypoint/core/EntryPoint.sol @@ -0,0 +1,861 @@ +/** + ** Account-Abstraction (EIP-4337) singleton EntryPoint implementation. + ** Only one instance required on each chain. + **/ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity ^0.8.12; + +/* solhint-disable avoid-low-level-calls */ +/* solhint-disable no-inline-assembly */ + +import "../interfaces/IAccount.sol"; +import "../interfaces/IPaymaster.sol"; +import "../interfaces/IEntryPoint.sol"; + +import "../utils/Exec.sol"; +import "./StakeManager.sol"; +import "./SenderCreator.sol"; +import "./Helpers.sol"; + +contract EntryPoint is IEntryPoint, StakeManager { + using UserOperationLib for UserOperation; + + SenderCreator private immutable senderCreator = new SenderCreator(); + + // internal value used during simulation: need to query aggregator. + address private constant SIMULATE_FIND_AGGREGATOR = address(1); + + // marker for inner call revert on out of gas + bytes32 private constant INNER_OUT_OF_GAS = hex"deaddead"; + + uint256 private constant REVERT_REASON_MAX_LEN = 2048; + + /** + * for simulation purposes, validateUserOp (and validatePaymasterUserOp) must return this value + * in case of signature failure, instead of revert. + */ + uint256 public constant SIG_VALIDATION_FAILED = 1; + + /** + * compensate the caller's beneficiary address with the collected fees of all UserOperations. + * @param beneficiary the address to receive the fees + * @param amount amount to transfer. + */ + function _compensate(address payable beneficiary, uint256 amount) internal { + require(beneficiary != address(0), "AA90 invalid beneficiary"); + (bool success, ) = beneficiary.call{value: amount}(""); + require(success, "AA91 failed send to beneficiary"); + } + + /** + * execute a user op + * @param opIndex index into the opInfo array + * @param userOp the userOp to execute + * @param opInfo the opInfo filled by validatePrepayment for this userOp. + * @return collected the total amount this userOp paid. + */ + function _executeUserOp( + uint256 opIndex, + UserOperation calldata userOp, + UserOpInfo memory opInfo + ) private returns (uint256 collected) { + uint256 preGas = gasleft(); + bytes memory context = getMemoryBytesFromOffset(opInfo.contextOffset); + + try this.innerHandleOp(userOp.callData, opInfo, context) returns ( + uint256 _actualGasCost + ) { + collected = _actualGasCost; + } catch { + bytes32 innerRevertCode; + assembly { + returndatacopy(0, 0, 32) + innerRevertCode := mload(0) + } + // handleOps was called with gas limit too low. abort entire bundle. + if (innerRevertCode == INNER_OUT_OF_GAS) { + //report paymaster, since if it is not deliberately caused by the bundler, + // it must be a revert caused by paymaster. + revert FailedOp(opIndex, "AA95 out of gas"); + } + + uint256 actualGas = preGas - gasleft() + opInfo.preOpGas; + collected = _handlePostOp( + opIndex, + IPaymaster.PostOpMode.postOpReverted, + opInfo, + context, + actualGas + ); + } + } + + /** + * Execute a batch of UserOperations. + * no signature aggregator is used. + * if any account requires an aggregator (that is, it returned an aggregator when + * performing simulateValidation), then handleAggregatedOps() must be used instead. + * @param ops the operations to execute + * @param beneficiary the address to receive the fees + */ + function handleOps( + UserOperation[] calldata ops, + address payable beneficiary + ) public { + uint256 opslen = ops.length; + UserOpInfo[] memory opInfos = new UserOpInfo[](opslen); + + unchecked { + for (uint256 i = 0; i < opslen; i++) { + UserOpInfo memory opInfo = opInfos[i]; + ( + uint256 validationData, + uint256 pmValidationData + ) = _validatePrepayment(i, ops[i], opInfo); + _validateAccountAndPaymasterValidationData( + i, + validationData, + pmValidationData, + address(0) + ); + } + + uint256 collected = 0; + + for (uint256 i = 0; i < opslen; i++) { + collected += _executeUserOp(i, ops[i], opInfos[i]); + } + + _compensate(beneficiary, collected); + } //unchecked + } + + /** + * Execute a batch of UserOperation with Aggregators + * @param opsPerAggregator the operations to execute, grouped by aggregator (or address(0) for no-aggregator accounts) + * @param beneficiary the address to receive the fees + */ + function handleAggregatedOps( + UserOpsPerAggregator[] calldata opsPerAggregator, + address payable beneficiary + ) public { + uint256 opasLen = opsPerAggregator.length; + uint256 totalOps = 0; + for (uint256 i = 0; i < opasLen; i++) { + UserOpsPerAggregator calldata opa = opsPerAggregator[i]; + UserOperation[] calldata ops = opa.userOps; + IAggregator aggregator = opa.aggregator; + + //address(1) is special marker of "signature error" + require( + address(aggregator) != address(1), + "AA96 invalid aggregator" + ); + + if (address(aggregator) != address(0)) { + // solhint-disable-next-line no-empty-blocks + try aggregator.validateSignatures(ops, opa.signature) {} catch { + revert SignatureValidationFailed(address(aggregator)); + } + } + + totalOps += ops.length; + } + + UserOpInfo[] memory opInfos = new UserOpInfo[](totalOps); + + uint256 opIndex = 0; + for (uint256 a = 0; a < opasLen; a++) { + UserOpsPerAggregator calldata opa = opsPerAggregator[a]; + UserOperation[] calldata ops = opa.userOps; + IAggregator aggregator = opa.aggregator; + + uint256 opslen = ops.length; + for (uint256 i = 0; i < opslen; i++) { + UserOpInfo memory opInfo = opInfos[opIndex]; + ( + uint256 validationData, + uint256 paymasterValidationData + ) = _validatePrepayment(opIndex, ops[i], opInfo); + _validateAccountAndPaymasterValidationData( + i, + validationData, + paymasterValidationData, + address(aggregator) + ); + opIndex++; + } + } + + uint256 collected = 0; + opIndex = 0; + for (uint256 a = 0; a < opasLen; a++) { + UserOpsPerAggregator calldata opa = opsPerAggregator[a]; + emit SignatureAggregatorChanged(address(opa.aggregator)); + UserOperation[] calldata ops = opa.userOps; + uint256 opslen = ops.length; + + for (uint256 i = 0; i < opslen; i++) { + collected += _executeUserOp(opIndex, ops[i], opInfos[opIndex]); + opIndex++; + } + } + emit SignatureAggregatorChanged(address(0)); + + _compensate(beneficiary, collected); + } + + /// @inheritdoc IEntryPoint + function simulateHandleOp( + UserOperation calldata op, + address target, + bytes calldata targetCallData + ) external override { + UserOpInfo memory opInfo; + _simulationOnlyValidations(op); + ( + uint256 validationData, + uint256 paymasterValidationData + ) = _validatePrepayment(0, op, opInfo); + ValidationData memory data = _intersectTimeRange( + validationData, + paymasterValidationData + ); + + numberMarker(); + uint256 paid = _executeUserOp(0, op, opInfo); + numberMarker(); + bool targetSuccess; + bytes memory targetResult; + if (target != address(0)) { + (targetSuccess, targetResult) = target.call(targetCallData); + } + revert ExecutionResult( + opInfo.preOpGas, + paid, + data.validAfter, + data.validUntil, + targetSuccess, + targetResult + ); + } + + // A memory copy of UserOp static fields only. + // Excluding: callData, initCode and signature. Replacing paymasterAndData with paymaster. + struct MemoryUserOp { + address sender; + uint256 nonce; + uint256 callGasLimit; + uint256 verificationGasLimit; + uint256 preVerificationGas; + address paymaster; + uint256 maxFeePerGas; + uint256 maxPriorityFeePerGas; + } + + struct UserOpInfo { + MemoryUserOp mUserOp; + bytes32 userOpHash; + uint256 prefund; + uint256 contextOffset; + uint256 preOpGas; + } + + /** + * inner function to handle a UserOperation. + * Must be declared "external" to open a call context, but it can only be called by handleOps. + */ + function innerHandleOp( + bytes memory callData, + UserOpInfo memory opInfo, + bytes calldata context + ) external returns (uint256 actualGasCost) { + uint256 preGas = gasleft(); + require(msg.sender == address(this), "AA92 internal call only"); + MemoryUserOp memory mUserOp = opInfo.mUserOp; + + uint256 callGasLimit = mUserOp.callGasLimit; + unchecked { + // handleOps was called with gas limit too low. abort entire bundle. + if ( + gasleft() < callGasLimit + mUserOp.verificationGasLimit + 5000 + ) { + assembly { + mstore(0, INNER_OUT_OF_GAS) + revert(0, 32) + } + } + } + + IPaymaster.PostOpMode mode = IPaymaster.PostOpMode.opSucceeded; + if (callData.length > 0) { + bool success = Exec.call(mUserOp.sender, 0, callData, callGasLimit); + if (!success) { + bytes memory result = Exec.getReturnData(REVERT_REASON_MAX_LEN); + if (result.length > 0) { + emit UserOperationRevertReason( + opInfo.userOpHash, + mUserOp.sender, + mUserOp.nonce, + result + ); + } + mode = IPaymaster.PostOpMode.opReverted; + } + } + + unchecked { + uint256 actualGas = preGas - gasleft() + opInfo.preOpGas; + //note: opIndex is ignored (relevant only if mode==postOpReverted, which is only possible outside of innerHandleOp) + return _handlePostOp(0, mode, opInfo, context, actualGas); + } + } + + /** + * generate a request Id - unique identifier for this request. + * the request ID is a hash over the content of the userOp (except the signature), the entrypoint and the chainid. + */ + function getUserOpHash(UserOperation calldata userOp) + public + view + returns (bytes32) + { + return + keccak256(abi.encode(userOp.hash(), address(this), block.chainid)); + } + + /** + * copy general fields from userOp into the memory opInfo structure. + */ + function _copyUserOpToMemory( + UserOperation calldata userOp, + MemoryUserOp memory mUserOp + ) internal pure { + mUserOp.sender = userOp.sender; + mUserOp.nonce = userOp.nonce; + mUserOp.callGasLimit = userOp.callGasLimit; + mUserOp.verificationGasLimit = userOp.verificationGasLimit; + mUserOp.preVerificationGas = userOp.preVerificationGas; + mUserOp.maxFeePerGas = userOp.maxFeePerGas; + mUserOp.maxPriorityFeePerGas = userOp.maxPriorityFeePerGas; + bytes calldata paymasterAndData = userOp.paymasterAndData; + if (paymasterAndData.length > 0) { + require( + paymasterAndData.length >= 20, + "AA93 invalid paymasterAndData" + ); + mUserOp.paymaster = address(bytes20(paymasterAndData[:20])); + } else { + mUserOp.paymaster = address(0); + } + } + + /** + * Simulate a call to account.validateUserOp and paymaster.validatePaymasterUserOp. + * @dev this method always revert. Successful result is ValidationResult error. other errors are failures. + * @dev The node must also verify it doesn't use banned opcodes, and that it doesn't reference storage outside the account's data. + * @param userOp the user operation to validate. + */ + function simulateValidation(UserOperation calldata userOp) external { + UserOpInfo memory outOpInfo; + + _simulationOnlyValidations(userOp); + ( + uint256 validationData, + uint256 paymasterValidationData + ) = _validatePrepayment(0, userOp, outOpInfo); + StakeInfo memory paymasterInfo = _getStakeInfo( + outOpInfo.mUserOp.paymaster + ); + StakeInfo memory senderInfo = _getStakeInfo(outOpInfo.mUserOp.sender); + StakeInfo memory factoryInfo; + { + bytes calldata initCode = userOp.initCode; + address factory = initCode.length >= 20 + ? address(bytes20(initCode[0:20])) + : address(0); + factoryInfo = _getStakeInfo(factory); + } + + ValidationData memory data = _intersectTimeRange( + validationData, + paymasterValidationData + ); + address aggregator = data.aggregator; + bool sigFailed = aggregator == address(1); + ReturnInfo memory returnInfo = ReturnInfo( + outOpInfo.preOpGas, + outOpInfo.prefund, + sigFailed, + data.validAfter, + data.validUntil, + getMemoryBytesFromOffset(outOpInfo.contextOffset) + ); + + if (aggregator != address(0) && aggregator != address(1)) { + AggregatorStakeInfo memory aggregatorInfo = AggregatorStakeInfo( + aggregator, + _getStakeInfo(aggregator) + ); + revert ValidationResultWithAggregation( + returnInfo, + senderInfo, + factoryInfo, + paymasterInfo, + aggregatorInfo + ); + } + revert ValidationResult( + returnInfo, + senderInfo, + factoryInfo, + paymasterInfo + ); + } + + function _getRequiredPrefund(MemoryUserOp memory mUserOp) + internal + pure + returns (uint256 requiredPrefund) + { + unchecked { + //when using a Paymaster, the verificationGasLimit is used also to as a limit for the postOp call. + // our security model might call postOp eventually twice + uint256 mul = mUserOp.paymaster != address(0) ? 3 : 1; + uint256 requiredGas = mUserOp.callGasLimit + + mUserOp.verificationGasLimit * + mul + + mUserOp.preVerificationGas; + + requiredPrefund = requiredGas * mUserOp.maxFeePerGas; + } + } + + // create the sender's contract if needed. + function _createSenderIfNeeded( + uint256 opIndex, + UserOpInfo memory opInfo, + bytes calldata initCode + ) internal { + if (initCode.length != 0) { + address sender = opInfo.mUserOp.sender; + if (sender.code.length != 0) + revert FailedOp(opIndex, "AA10 sender already constructed"); + address sender1 = senderCreator.createSender{ + gas: opInfo.mUserOp.verificationGasLimit + }(initCode); + if (sender1 == address(0)) + revert FailedOp(opIndex, "AA13 initCode failed or OOG"); + if (sender1 != sender) + revert FailedOp(opIndex, "AA14 initCode must return sender"); + if (sender1.code.length == 0) + revert FailedOp(opIndex, "AA15 initCode must create sender"); + address factory = address(bytes20(initCode[0:20])); + emit AccountDeployed( + opInfo.userOpHash, + sender, + factory, + opInfo.mUserOp.paymaster + ); + } + } + + /** + * Get counterfactual sender address. + * Calculate the sender contract address that will be generated by the initCode and salt in the UserOperation. + * this method always revert, and returns the address in SenderAddressResult error + * @param initCode the constructor code to be passed into the UserOperation. + */ + function getSenderAddress(bytes calldata initCode) public { + revert SenderAddressResult(senderCreator.createSender(initCode)); + } + + function _simulationOnlyValidations(UserOperation calldata userOp) + internal + view + { + // solhint-disable-next-line no-empty-blocks + try + this._validateSenderAndPaymaster( + userOp.initCode, + userOp.sender, + userOp.paymasterAndData + ) + {} catch Error(string memory revertReason) { + if (bytes(revertReason).length != 0) { + revert FailedOp(0, revertReason); + } + } + } + + /** + * Called only during simulation. + * This function always reverts to prevent warm/cold storage differentiation in simulation vs execution. + */ + function _validateSenderAndPaymaster( + bytes calldata initCode, + address sender, + bytes calldata paymasterAndData + ) external view { + if (initCode.length == 0 && sender.code.length == 0) { + // it would revert anyway. but give a meaningful message + revert("AA20 account not deployed"); + } + if (paymasterAndData.length >= 20) { + address paymaster = address(bytes20(paymasterAndData[0:20])); + if (paymaster.code.length == 0) { + // it would revert anyway. but give a meaningful message + revert("AA30 paymaster not deployed"); + } + } + // always revert + revert(""); + } + + /** + * call account.validateUserOp. + * revert (with FailedOp) in case validateUserOp reverts, or account didn't send required prefund. + * decrement account's deposit if needed + */ + function _validateAccountPrepayment( + uint256 opIndex, + UserOperation calldata op, + UserOpInfo memory opInfo, + uint256 requiredPrefund + ) + internal + returns ( + uint256 gasUsedByValidateAccountPrepayment, + uint256 validationData + ) + { + unchecked { + uint256 preGas = gasleft(); + MemoryUserOp memory mUserOp = opInfo.mUserOp; + address sender = mUserOp.sender; + _createSenderIfNeeded(opIndex, opInfo, op.initCode); + address paymaster = mUserOp.paymaster; + numberMarker(); + uint256 missingAccountFunds = 0; + if (paymaster == address(0)) { + uint256 bal = balanceOf(sender); + missingAccountFunds = bal > requiredPrefund + ? 0 + : requiredPrefund - bal; + } + try + IAccount(sender).validateUserOp{ + gas: mUserOp.verificationGasLimit + }(op, opInfo.userOpHash, missingAccountFunds) + returns (uint256 _validationData) { + validationData = _validationData; + } catch Error(string memory revertReason) { + revert FailedOp( + opIndex, + string.concat("AA23 reverted: ", revertReason) + ); + } catch { + revert FailedOp(opIndex, "AA23 reverted (or OOG)"); + } + if (paymaster == address(0)) { + DepositInfo storage senderInfo = deposits[sender]; + uint256 deposit = senderInfo.deposit; + if (requiredPrefund > deposit) { + revert FailedOp(opIndex, "AA21 didn't pay prefund"); + } + senderInfo.deposit = uint112(deposit - requiredPrefund); + } + gasUsedByValidateAccountPrepayment = preGas - gasleft(); + } + } + + /** + * In case the request has a paymaster: + * Validate paymaster has enough deposit. + * Call paymaster.validatePaymasterUserOp. + * Revert with proper FailedOp in case paymaster reverts. + * Decrement paymaster's deposit + */ + function _validatePaymasterPrepayment( + uint256 opIndex, + UserOperation calldata op, + UserOpInfo memory opInfo, + uint256 requiredPreFund, + uint256 gasUsedByValidateAccountPrepayment + ) internal returns (bytes memory context, uint256 validationData) { + unchecked { + MemoryUserOp memory mUserOp = opInfo.mUserOp; + uint256 verificationGasLimit = mUserOp.verificationGasLimit; + require( + verificationGasLimit > gasUsedByValidateAccountPrepayment, + "AA41 too little verificationGas" + ); + uint256 gas = verificationGasLimit - + gasUsedByValidateAccountPrepayment; + + address paymaster = mUserOp.paymaster; + DepositInfo storage paymasterInfo = deposits[paymaster]; + uint256 deposit = paymasterInfo.deposit; + if (deposit < requiredPreFund) { + revert FailedOp(opIndex, "AA31 paymaster deposit too low"); + } + paymasterInfo.deposit = uint112(deposit - requiredPreFund); + try + IPaymaster(paymaster).validatePaymasterUserOp{gas: gas}( + op, + opInfo.userOpHash, + requiredPreFund + ) + returns (bytes memory _context, uint256 _validationData) { + context = _context; + validationData = _validationData; + } catch Error(string memory revertReason) { + revert FailedOp( + opIndex, + string.concat("AA33 reverted: ", revertReason) + ); + } catch { + revert FailedOp(opIndex, "AA33 reverted (or OOG)"); + } + } + } + + /** + * revert if either account validationData or paymaster validationData is expired + */ + function _validateAccountAndPaymasterValidationData( + uint256 opIndex, + uint256 validationData, + uint256 paymasterValidationData, + address expectedAggregator + ) internal view { + (address aggregator, bool outOfTimeRange) = _getValidationData( + validationData + ); + if (expectedAggregator != aggregator) { + revert FailedOp(opIndex, "AA24 signature error"); + } + if (outOfTimeRange) { + revert FailedOp(opIndex, "AA22 expired or not due"); + } + //pmAggregator is not a real signature aggregator: we don't have logic to handle it as address. + // non-zero address means that the paymaster fails due to some signature check (which is ok only during estimation) + address pmAggregator; + (pmAggregator, outOfTimeRange) = _getValidationData( + paymasterValidationData + ); + if (pmAggregator != address(0)) { + revert FailedOp(opIndex, "AA34 signature error"); + } + if (outOfTimeRange) { + revert FailedOp(opIndex, "AA32 paymaster expired or not due"); + } + } + + function _getValidationData(uint256 validationData) + internal + view + returns (address aggregator, bool outOfTimeRange) + { + if (validationData == 0) { + return (address(0), false); + } + ValidationData memory data = _parseValidationData(validationData); + // solhint-disable-next-line not-rely-on-time + outOfTimeRange = + block.timestamp > data.validUntil || + block.timestamp < data.validAfter; + aggregator = data.aggregator; + } + + /** + * validate account and paymaster (if defined). + * also make sure total validation doesn't exceed verificationGasLimit + * this method is called off-chain (simulateValidation()) and on-chain (from handleOps) + * @param opIndex the index of this userOp into the "opInfos" array + * @param userOp the userOp to validate + */ + function _validatePrepayment( + uint256 opIndex, + UserOperation calldata userOp, + UserOpInfo memory outOpInfo + ) + private + returns (uint256 validationData, uint256 paymasterValidationData) + { + uint256 preGas = gasleft(); + MemoryUserOp memory mUserOp = outOpInfo.mUserOp; + _copyUserOpToMemory(userOp, mUserOp); + outOpInfo.userOpHash = getUserOpHash(userOp); + + // validate all numeric values in userOp are well below 128 bit, so they can safely be added + // and multiplied without causing overflow + uint256 maxGasValues = mUserOp.preVerificationGas | + mUserOp.verificationGasLimit | + mUserOp.callGasLimit | + userOp.maxFeePerGas | + userOp.maxPriorityFeePerGas; + require(maxGasValues <= type(uint120).max, "AA94 gas values overflow"); + + uint256 gasUsedByValidateAccountPrepayment; + uint256 requiredPreFund = _getRequiredPrefund(mUserOp); + ( + gasUsedByValidateAccountPrepayment, + validationData + ) = _validateAccountPrepayment( + opIndex, + userOp, + outOpInfo, + requiredPreFund + ); + //a "marker" where account opcode validation is done and paymaster opcode validation is about to start + // (used only by off-chain simulateValidation) + numberMarker(); + + bytes memory context; + if (mUserOp.paymaster != address(0)) { + (context, paymasterValidationData) = _validatePaymasterPrepayment( + opIndex, + userOp, + outOpInfo, + requiredPreFund, + gasUsedByValidateAccountPrepayment + ); + } + unchecked { + uint256 gasUsed = preGas - gasleft(); + + if (userOp.verificationGasLimit < gasUsed) { + revert FailedOp(opIndex, "AA40 over verificationGasLimit"); + } + outOpInfo.prefund = requiredPreFund; + outOpInfo.contextOffset = getOffsetOfMemoryBytes(context); + outOpInfo.preOpGas = preGas - gasleft() + userOp.preVerificationGas; + } + } + + /** + * process post-operation. + * called just after the callData is executed. + * if a paymaster is defined and its validation returned a non-empty context, its postOp is called. + * the excess amount is refunded to the account (or paymaster - if it was used in the request) + * @param opIndex index in the batch + * @param mode - whether is called from innerHandleOp, or outside (postOpReverted) + * @param opInfo userOp fields and info collected during validation + * @param context the context returned in validatePaymasterUserOp + * @param actualGas the gas used so far by this user operation + */ + function _handlePostOp( + uint256 opIndex, + IPaymaster.PostOpMode mode, + UserOpInfo memory opInfo, + bytes memory context, + uint256 actualGas + ) private returns (uint256 actualGasCost) { + uint256 preGas = gasleft(); + unchecked { + address refundAddress; + MemoryUserOp memory mUserOp = opInfo.mUserOp; + uint256 gasPrice = getUserOpGasPrice(mUserOp); + + address paymaster = mUserOp.paymaster; + if (paymaster == address(0)) { + refundAddress = mUserOp.sender; + } else { + refundAddress = paymaster; + if (context.length > 0) { + actualGasCost = actualGas * gasPrice; + if (mode != IPaymaster.PostOpMode.postOpReverted) { + IPaymaster(paymaster).postOp{ + gas: mUserOp.verificationGasLimit + }(mode, context, actualGasCost); + } else { + // solhint-disable-next-line no-empty-blocks + try + IPaymaster(paymaster).postOp{ + gas: mUserOp.verificationGasLimit + }(mode, context, actualGasCost) + {} catch Error(string memory reason) { + revert FailedOp( + opIndex, + string.concat("AA50 postOp reverted: ", reason) + ); + } catch { + revert FailedOp(opIndex, "AA50 postOp revert"); + } + } + } + } + actualGas += preGas - gasleft(); + actualGasCost = actualGas * gasPrice; + if (opInfo.prefund < actualGasCost) { + revert FailedOp(opIndex, "AA51 prefund below actualGasCost"); + } + uint256 refund = opInfo.prefund - actualGasCost; + _incrementDeposit(refundAddress, refund); + bool success = mode == IPaymaster.PostOpMode.opSucceeded; + emit UserOperationEvent( + opInfo.userOpHash, + mUserOp.sender, + mUserOp.paymaster, + mUserOp.nonce, + success, + actualGasCost, + actualGas + ); + } // unchecked + } + + /** + * the gas price this UserOp agrees to pay. + * relayer/block builder might submit the TX with higher priorityFee, but the user should not + */ + function getUserOpGasPrice(MemoryUserOp memory mUserOp) + internal + view + returns (uint256) + { + unchecked { + uint256 maxFeePerGas = mUserOp.maxFeePerGas; + uint256 maxPriorityFeePerGas = mUserOp.maxPriorityFeePerGas; + if (maxFeePerGas == maxPriorityFeePerGas) { + //legacy mode (for networks that don't support basefee opcode) + return maxFeePerGas; + } + return min(maxFeePerGas, maxPriorityFeePerGas + block.basefee); + } + } + + function min(uint256 a, uint256 b) internal pure returns (uint256) { + return a < b ? a : b; + } + + function getOffsetOfMemoryBytes(bytes memory data) + internal + pure + returns (uint256 offset) + { + assembly { + offset := data + } + } + + function getMemoryBytesFromOffset(uint256 offset) + internal + pure + returns (bytes memory data) + { + assembly { + data := offset + } + } + + //place the NUMBER opcode in the code. + // this is used as a marker during simulation, as this OP is completely banned from the simulated code of the + // account and paymaster. + function numberMarker() internal view { + assembly { + mstore(0, number()) + } + } +} diff --git a/contracts/src/v0.8/vendor/entrypoint/core/Helpers.sol b/contracts/src/v0.8/vendor/entrypoint/core/Helpers.sol new file mode 100644 index 00000000000..71a6dc3d16b --- /dev/null +++ b/contracts/src/v0.8/vendor/entrypoint/core/Helpers.sol @@ -0,0 +1,68 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity ^0.8.12; + +/** + * returned data from validateUserOp. + * validateUserOp returns a uint256, with is created by `_packedValidationData` and parsed by `_parseValidationData` + * @param aggregator - address(0) - the account validated the signature by itself. + * address(1) - the account failed to validate the signature. + * otherwise - this is an address of a signature aggregator that must be used to validate the signature. + * @param validAfter - this UserOp is valid only after this timestamp. + * @param validaUntil - this UserOp is valid only up to this timestamp. + */ +struct ValidationData { + address aggregator; + uint48 validAfter; + uint48 validUntil; +} + +//extract sigFailed, validAfter, validUntil. +// also convert zero validUntil to type(uint48).max +function _parseValidationData(uint validationData) pure returns (ValidationData memory data) { + address aggregator = address(uint160(validationData)); + uint48 validUntil = uint48(validationData >> 160); + if (validUntil == 0) { + validUntil = type(uint48).max; + } + uint48 validAfter = uint48(validationData >> (48 + 160)); + return ValidationData(aggregator, validAfter, validUntil); +} + +// intersect account and paymaster ranges. +function _intersectTimeRange( + uint256 validationData, + uint256 paymasterValidationData +) pure returns (ValidationData memory) { + ValidationData memory accountValidationData = _parseValidationData(validationData); + ValidationData memory pmValidationData = _parseValidationData(paymasterValidationData); + address aggregator = accountValidationData.aggregator; + if (aggregator == address(0)) { + aggregator = pmValidationData.aggregator; + } + uint48 validAfter = accountValidationData.validAfter; + uint48 validUntil = accountValidationData.validUntil; + uint48 pmValidAfter = pmValidationData.validAfter; + uint48 pmValidUntil = pmValidationData.validUntil; + + if (validAfter < pmValidAfter) validAfter = pmValidAfter; + if (validUntil > pmValidUntil) validUntil = pmValidUntil; + return ValidationData(aggregator, validAfter, validUntil); +} + +/** + * helper to pack the return value for validateUserOp + * @param data - the ValidationData to pack + */ +function _packValidationData(ValidationData memory data) pure returns (uint256) { + return uint160(data.aggregator) | (uint256(data.validUntil) << 160) | (uint256(data.validAfter) << (160 + 48)); +} + +/** + * helper to pack the return value for validateUserOp, when not using an aggregator + * @param sigFailed - true for signature failure, false for success + * @param validUntil last timestamp this UserOperation is valid (or zero for infinite) + * @param validAfter first timestamp this UserOperation is valid + */ +function _packValidationData(bool sigFailed, uint48 validUntil, uint48 validAfter) pure returns (uint256) { + return (sigFailed ? 1 : 0) | (uint256(validUntil) << 160) | (uint256(validAfter) << (160 + 48)); +} diff --git a/contracts/src/v0.8/vendor/entrypoint/core/SenderCreator.sol b/contracts/src/v0.8/vendor/entrypoint/core/SenderCreator.sol new file mode 100644 index 00000000000..36fad7b91f1 --- /dev/null +++ b/contracts/src/v0.8/vendor/entrypoint/core/SenderCreator.sol @@ -0,0 +1,28 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity ^0.8.12; + +/** + * helper contract for EntryPoint, to call userOp.initCode from a "neutral" address, + * which is explicitly not the entryPoint itself. + */ +contract SenderCreator { + + /** + * call the "initCode" factory to create and return the sender account address + * @param initCode the initCode value from a UserOp. contains 20 bytes of factory address, followed by calldata + * @return sender the returned address of the created account, or zero address on failure. + */ + function createSender(bytes calldata initCode) external returns (address sender) { + address factory = address(bytes20(initCode[0 : 20])); + bytes memory initCallData = initCode[20 :]; + bool success; + /* solhint-disable no-inline-assembly */ + assembly { + success := call(gas(), factory, 0, add(initCallData, 0x20), mload(initCallData), 0, 32) + sender := mload(0) + } + if (!success) { + sender = address(0); + } + } +} diff --git a/contracts/src/v0.8/vendor/entrypoint/core/StakeManager.sol b/contracts/src/v0.8/vendor/entrypoint/core/StakeManager.sol new file mode 100644 index 00000000000..e5ca2b97dd4 --- /dev/null +++ b/contracts/src/v0.8/vendor/entrypoint/core/StakeManager.sol @@ -0,0 +1,124 @@ +// SPDX-License-Identifier: GPL-3.0-only +pragma solidity ^0.8.12; + +import "../interfaces/IStakeManager.sol"; + +/* solhint-disable avoid-low-level-calls */ +/* solhint-disable not-rely-on-time */ +/** + * manage deposits and stakes. + * deposit is just a balance used to pay for UserOperations (either by a paymaster or an account) + * stake is value locked for at least "unstakeDelay" by a paymaster. + */ +abstract contract StakeManager is IStakeManager { + + /// maps paymaster to their deposits and stakes + mapping(address => DepositInfo) public deposits; + + /// @inheritdoc IStakeManager + function getDepositInfo(address account) public view returns (DepositInfo memory info) { + return deposits[account]; + } + + // internal method to return just the stake info + function _getStakeInfo(address addr) internal view returns (StakeInfo memory info) { + DepositInfo storage depositInfo = deposits[addr]; + info.stake = depositInfo.stake; + info.unstakeDelaySec = depositInfo.unstakeDelaySec; + } + + /// return the deposit (for gas payment) of the account + function balanceOf(address account) public view returns (uint256) { + return deposits[account].deposit; + } + + receive() external payable { + depositTo(msg.sender); + } + + function _incrementDeposit(address account, uint256 amount) internal { + DepositInfo storage info = deposits[account]; + uint256 newAmount = info.deposit + amount; + require(newAmount <= type(uint112).max, "deposit overflow"); + info.deposit = uint112(newAmount); + } + + /** + * add to the deposit of the given account + */ + function depositTo(address account) public payable { + _incrementDeposit(account, msg.value); + DepositInfo storage info = deposits[account]; + emit Deposited(account, info.deposit); + } + + /** + * add to the account's stake - amount and delay + * any pending unstake is first cancelled. + * @param unstakeDelaySec the new lock duration before the deposit can be withdrawn. + */ + function addStake(uint32 unstakeDelaySec) public payable { + DepositInfo storage info = deposits[msg.sender]; + require(unstakeDelaySec > 0, "must specify unstake delay"); + require(unstakeDelaySec >= info.unstakeDelaySec, "cannot decrease unstake time"); + uint256 stake = info.stake + msg.value; + require(stake > 0, "no stake specified"); + require(stake <= type(uint112).max, "stake overflow"); + deposits[msg.sender] = DepositInfo( + info.deposit, + true, + uint112(stake), + unstakeDelaySec, + 0 + ); + emit StakeLocked(msg.sender, stake, unstakeDelaySec); + } + + /** + * attempt to unlock the stake. + * the value can be withdrawn (using withdrawStake) after the unstake delay. + */ + function unlockStake() external { + DepositInfo storage info = deposits[msg.sender]; + require(info.unstakeDelaySec != 0, "not staked"); + require(info.staked, "already unstaking"); + uint48 withdrawTime = uint48(block.timestamp) + info.unstakeDelaySec; + info.withdrawTime = withdrawTime; + info.staked = false; + emit StakeUnlocked(msg.sender, withdrawTime); + } + + + /** + * withdraw from the (unlocked) stake. + * must first call unlockStake and wait for the unstakeDelay to pass + * @param withdrawAddress the address to send withdrawn value. + */ + function withdrawStake(address payable withdrawAddress) external { + DepositInfo storage info = deposits[msg.sender]; + uint256 stake = info.stake; + require(stake > 0, "No stake to withdraw"); + require(info.withdrawTime > 0, "must call unlockStake() first"); + require(info.withdrawTime <= block.timestamp, "Stake withdrawal is not due"); + info.unstakeDelaySec = 0; + info.withdrawTime = 0; + info.stake = 0; + emit StakeWithdrawn(msg.sender, withdrawAddress, stake); + (bool success,) = withdrawAddress.call{value : stake}(""); + require(success, "failed to withdraw stake"); + } + + /** + * withdraw from the deposit. + * @param withdrawAddress the address to send withdrawn value. + * @param withdrawAmount the amount to withdraw. + */ + function withdrawTo(address payable withdrawAddress, uint256 withdrawAmount) external { + DepositInfo storage info = deposits[msg.sender]; + require(withdrawAmount <= info.deposit, "Withdraw amount too large"); + info.deposit = uint112(info.deposit - withdrawAmount); + emit Withdrawn(msg.sender, withdrawAddress, withdrawAmount); + (bool success,) = withdrawAddress.call{value : withdrawAmount}(""); + require(success, "failed to withdraw"); + } +} diff --git a/contracts/src/v0.8/vendor/entrypoint/interfaces/IAccount.sol b/contracts/src/v0.8/vendor/entrypoint/interfaces/IAccount.sol new file mode 100644 index 00000000000..1600de3d71e --- /dev/null +++ b/contracts/src/v0.8/vendor/entrypoint/interfaces/IAccount.sol @@ -0,0 +1,34 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity ^0.8.12; + +import "./UserOperation.sol"; + +interface IAccount { + + /** + * Validate user's signature and nonce + * the entryPoint will make the call to the recipient only if this validation call returns successfully. + * signature failure should be reported by returning SIG_VALIDATION_FAILED (1). + * This allows making a "simulation call" without a valid signature + * Other failures (e.g. nonce mismatch, or invalid signature format) should still revert to signal failure. + * + * @dev Must validate caller is the entryPoint. + * Must validate the signature and nonce + * @param userOp the operation that is about to be executed. + * @param userOpHash hash of the user's request data. can be used as the basis for signature. + * @param missingAccountFunds missing funds on the account's deposit in the entrypoint. + * This is the minimum amount to transfer to the sender(entryPoint) to be able to make the call. + * The excess is left as a deposit in the entrypoint, for future calls. + * can be withdrawn anytime using "entryPoint.withdrawTo()" + * In case there is a paymaster in the request (or the current deposit is high enough), this value will be zero. + * @return validationData packaged ValidationData structure. use `_packValidationData` and `_unpackValidationData` to encode and decode + * <20-byte> sigAuthorizer - 0 for valid signature, 1 to mark signature failure, + * otherwise, an address of an "authorizer" contract. + * <6-byte> validUntil - last timestamp this operation is valid. 0 for "indefinite" + * <6-byte> validAfter - first timestamp this operation is valid + * If an account doesn't use time-range, it is enough to return SIG_VALIDATION_FAILED value (1) for signature failure. + * Note that the validation code cannot use block.timestamp (or block.number) directly. + */ + function validateUserOp(UserOperation calldata userOp, bytes32 userOpHash, uint256 missingAccountFunds) + external returns (uint256 validationData); +} diff --git a/contracts/src/v0.8/vendor/entrypoint/interfaces/IAggregator.sol b/contracts/src/v0.8/vendor/entrypoint/interfaces/IAggregator.sol new file mode 100644 index 00000000000..086c6f32241 --- /dev/null +++ b/contracts/src/v0.8/vendor/entrypoint/interfaces/IAggregator.sol @@ -0,0 +1,36 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity ^0.8.12; + +import "./UserOperation.sol"; + +/** + * Aggregated Signatures validator. + */ +interface IAggregator { + + /** + * validate aggregated signature. + * revert if the aggregated signature does not match the given list of operations. + */ + function validateSignatures(UserOperation[] calldata userOps, bytes calldata signature) external view; + + /** + * validate signature of a single userOp + * This method is should be called by bundler after EntryPoint.simulateValidation() returns (reverts) with ValidationResultWithAggregation + * First it validates the signature over the userOp. Then it returns data to be used when creating the handleOps. + * @param userOp the userOperation received from the user. + * @return sigForUserOp the value to put into the signature field of the userOp when calling handleOps. + * (usually empty, unless account and aggregator support some kind of "multisig" + */ + function validateUserOpSignature(UserOperation calldata userOp) + external view returns (bytes memory sigForUserOp); + + /** + * aggregate multiple signatures into a single value. + * This method is called off-chain to calculate the signature to pass with handleOps() + * bundler MAY use optimized custom code perform this aggregation + * @param userOps array of UserOperations to collect the signatures from. + * @return aggregatedSignature the aggregated signature + */ + function aggregateSignatures(UserOperation[] calldata userOps) external view returns (bytes memory aggregatedSignature); +} diff --git a/contracts/src/v0.8/vendor/entrypoint/interfaces/IEntryPoint.sol b/contracts/src/v0.8/vendor/entrypoint/interfaces/IEntryPoint.sol new file mode 100644 index 00000000000..22bb1b7a6e7 --- /dev/null +++ b/contracts/src/v0.8/vendor/entrypoint/interfaces/IEntryPoint.sol @@ -0,0 +1,197 @@ +/** + ** Account-Abstraction (EIP-4337) singleton EntryPoint implementation. + ** Only one instance required on each chain. + **/ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity ^0.8.12; + +/* solhint-disable avoid-low-level-calls */ +/* solhint-disable no-inline-assembly */ +/* solhint-disable reason-string */ + +import "./UserOperation.sol"; +import "./IStakeManager.sol"; +import "./IAggregator.sol"; + +interface IEntryPoint is IStakeManager { + + /*** + * An event emitted after each successful request + * @param userOpHash - unique identifier for the request (hash its entire content, except signature). + * @param sender - the account that generates this request. + * @param paymaster - if non-null, the paymaster that pays for this request. + * @param nonce - the nonce value from the request. + * @param success - true if the sender transaction succeeded, false if reverted. + * @param actualGasCost - actual amount paid (by account or paymaster) for this UserOperation. + * @param actualGasUsed - total gas used by this UserOperation (including preVerification, creation, validation and execution). + */ + event UserOperationEvent(bytes32 indexed userOpHash, address indexed sender, address indexed paymaster, uint256 nonce, bool success, uint256 actualGasCost, uint256 actualGasUsed); + + /** + * account "sender" was deployed. + * @param userOpHash the userOp that deployed this account. UserOperationEvent will follow. + * @param sender the account that is deployed + * @param factory the factory used to deploy this account (in the initCode) + * @param paymaster the paymaster used by this UserOp + */ + event AccountDeployed(bytes32 indexed userOpHash, address indexed sender, address factory, address paymaster); + + /** + * An event emitted if the UserOperation "callData" reverted with non-zero length + * @param userOpHash the request unique identifier. + * @param sender the sender of this request + * @param nonce the nonce used in the request + * @param revertReason - the return bytes from the (reverted) call to "callData". + */ + event UserOperationRevertReason(bytes32 indexed userOpHash, address indexed sender, uint256 nonce, bytes revertReason); + + /** + * signature aggregator used by the following UserOperationEvents within this bundle. + */ + event SignatureAggregatorChanged(address indexed aggregator); + + /** + * a custom revert error of handleOps, to identify the offending op. + * NOTE: if simulateValidation passes successfully, there should be no reason for handleOps to fail on it. + * @param opIndex - index into the array of ops to the failed one (in simulateValidation, this is always zero) + * @param reason - revert reason + * The string starts with a unique code "AAmn", where "m" is "1" for factory, "2" for account and "3" for paymaster issues, + * so a failure can be attributed to the correct entity. + * Should be caught in off-chain handleOps simulation and not happen on-chain. + * Useful for mitigating DoS attempts against batchers or for troubleshooting of factory/account/paymaster reverts. + */ + error FailedOp(uint256 opIndex, string reason); + + /** + * error case when a signature aggregator fails to verify the aggregated signature it had created. + */ + error SignatureValidationFailed(address aggregator); + + /** + * Successful result from simulateValidation. + * @param returnInfo gas and time-range returned values + * @param senderInfo stake information about the sender + * @param factoryInfo stake information about the factory (if any) + * @param paymasterInfo stake information about the paymaster (if any) + */ + error ValidationResult(ReturnInfo returnInfo, + StakeInfo senderInfo, StakeInfo factoryInfo, StakeInfo paymasterInfo); + + /** + * Successful result from simulateValidation, if the account returns a signature aggregator + * @param returnInfo gas and time-range returned values + * @param senderInfo stake information about the sender + * @param factoryInfo stake information about the factory (if any) + * @param paymasterInfo stake information about the paymaster (if any) + * @param aggregatorInfo signature aggregation info (if the account requires signature aggregator) + * bundler MUST use it to verify the signature, or reject the UserOperation + */ + error ValidationResultWithAggregation(ReturnInfo returnInfo, + StakeInfo senderInfo, StakeInfo factoryInfo, StakeInfo paymasterInfo, + AggregatorStakeInfo aggregatorInfo); + + /** + * return value of getSenderAddress + */ + error SenderAddressResult(address sender); + + /** + * return value of simulateHandleOp + */ + error ExecutionResult(uint256 preOpGas, uint256 paid, uint48 validAfter, uint48 validUntil, bool targetSuccess, bytes targetResult); + + //UserOps handled, per aggregator + struct UserOpsPerAggregator { + UserOperation[] userOps; + + // aggregator address + IAggregator aggregator; + // aggregated signature + bytes signature; + } + + /** + * Execute a batch of UserOperation. + * no signature aggregator is used. + * if any account requires an aggregator (that is, it returned an aggregator when + * performing simulateValidation), then handleAggregatedOps() must be used instead. + * @param ops the operations to execute + * @param beneficiary the address to receive the fees + */ + function handleOps(UserOperation[] calldata ops, address payable beneficiary) external; + + /** + * Execute a batch of UserOperation with Aggregators + * @param opsPerAggregator the operations to execute, grouped by aggregator (or address(0) for no-aggregator accounts) + * @param beneficiary the address to receive the fees + */ + function handleAggregatedOps( + UserOpsPerAggregator[] calldata opsPerAggregator, + address payable beneficiary + ) external; + + /** + * generate a request Id - unique identifier for this request. + * the request ID is a hash over the content of the userOp (except the signature), the entrypoint and the chainid. + */ + function getUserOpHash(UserOperation calldata userOp) external view returns (bytes32); + + /** + * Simulate a call to account.validateUserOp and paymaster.validatePaymasterUserOp. + * @dev this method always revert. Successful result is ValidationResult error. other errors are failures. + * @dev The node must also verify it doesn't use banned opcodes, and that it doesn't reference storage outside the account's data. + * @param userOp the user operation to validate. + */ + function simulateValidation(UserOperation calldata userOp) external; + + /** + * gas and return values during simulation + * @param preOpGas the gas used for validation (including preValidationGas) + * @param prefund the required prefund for this operation + * @param sigFailed validateUserOp's (or paymaster's) signature check failed + * @param validAfter - first timestamp this UserOp is valid (merging account and paymaster time-range) + * @param validUntil - last timestamp this UserOp is valid (merging account and paymaster time-range) + * @param paymasterContext returned by validatePaymasterUserOp (to be passed into postOp) + */ + struct ReturnInfo { + uint256 preOpGas; + uint256 prefund; + bool sigFailed; + uint48 validAfter; + uint48 validUntil; + bytes paymasterContext; + } + + /** + * returned aggregated signature info. + * the aggregator returned by the account, and its current stake. + */ + struct AggregatorStakeInfo { + address aggregator; + StakeInfo stakeInfo; + } + + /** + * Get counterfactual sender address. + * Calculate the sender contract address that will be generated by the initCode and salt in the UserOperation. + * this method always revert, and returns the address in SenderAddressResult error + * @param initCode the constructor code to be passed into the UserOperation. + */ + function getSenderAddress(bytes memory initCode) external; + + + /** + * simulate full execution of a UserOperation (including both validation and target execution) + * this method will always revert with "ExecutionResult". + * it performs full validation of the UserOperation, but ignores signature error. + * an optional target address is called after the userop succeeds, and its value is returned + * (before the entire call is reverted) + * Note that in order to collect the the success/failure of the target call, it must be executed + * with trace enabled to track the emitted events. + * @param op the UserOperation to simulate + * @param target if nonzero, a target address to call after userop simulation. If called, the targetSuccess and targetResult + * are set to the return from that call. + * @param targetCallData callData to pass to target address + */ + function simulateHandleOp(UserOperation calldata op, address target, bytes calldata targetCallData) external; +} diff --git a/contracts/src/v0.8/vendor/entrypoint/interfaces/IPaymaster.sol b/contracts/src/v0.8/vendor/entrypoint/interfaces/IPaymaster.sol new file mode 100644 index 00000000000..af50367acfc --- /dev/null +++ b/contracts/src/v0.8/vendor/entrypoint/interfaces/IPaymaster.sol @@ -0,0 +1,51 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity ^0.8.12; + +import "./UserOperation.sol"; + +/** + * the interface exposed by a paymaster contract, who agrees to pay the gas for user's operations. + * a paymaster must hold a stake to cover the required entrypoint stake and also the gas for the transaction. + */ +interface IPaymaster { + + enum PostOpMode { + opSucceeded, // user op succeeded + opReverted, // user op reverted. still has to pay for gas. + postOpReverted //user op succeeded, but caused postOp to revert. Now it's a 2nd call, after user's op was deliberately reverted. + } + + /** + * payment validation: check if paymaster agrees to pay. + * Must verify sender is the entryPoint. + * Revert to reject this request. + * Note that bundlers will reject this method if it changes the state, unless the paymaster is trusted (whitelisted) + * The paymaster pre-pays using its deposit, and receive back a refund after the postOp method returns. + * @param userOp the user operation + * @param userOpHash hash of the user's request data. + * @param maxCost the maximum cost of this transaction (based on maximum gas and gas price from userOp) + * @return context value to send to a postOp + * zero length to signify postOp is not required. + * @return validationData signature and time-range of this operation, encoded the same as the return value of validateUserOperation + * <20-byte> sigAuthorizer - 0 for valid signature, 1 to mark signature failure, + * otherwise, an address of an "authorizer" contract. + * <6-byte> validUntil - last timestamp this operation is valid. 0 for "indefinite" + * <6-byte> validAfter - first timestamp this operation is valid + * Note that the validation code cannot use block.timestamp (or block.number) directly. + */ + function validatePaymasterUserOp(UserOperation calldata userOp, bytes32 userOpHash, uint256 maxCost) + external returns (bytes memory context, uint256 validationData); + + /** + * post-operation handler. + * Must verify sender is the entryPoint + * @param mode enum with the following options: + * opSucceeded - user operation succeeded. + * opReverted - user op reverted. still has to pay for gas. + * postOpReverted - user op succeeded, but caused postOp (in mode=opSucceeded) to revert. + * Now this is the 2nd call, after user's op was deliberately reverted. + * @param context - the context value returned by validatePaymasterUserOp + * @param actualGasCost - actual gas used so far (without this postOp call). + */ + function postOp(PostOpMode mode, bytes calldata context, uint256 actualGasCost) external; +} diff --git a/contracts/src/v0.8/vendor/entrypoint/interfaces/IStakeManager.sol b/contracts/src/v0.8/vendor/entrypoint/interfaces/IStakeManager.sol new file mode 100644 index 00000000000..c19c1bab88b --- /dev/null +++ b/contracts/src/v0.8/vendor/entrypoint/interfaces/IStakeManager.sol @@ -0,0 +1,104 @@ +// SPDX-License-Identifier: GPL-3.0-only +pragma solidity ^0.8.12; + +/** + * manage deposits and stakes. + * deposit is just a balance used to pay for UserOperations (either by a paymaster or an account) + * stake is value locked for at least "unstakeDelay" by the staked entity. + */ +interface IStakeManager { + + event Deposited( + address indexed account, + uint256 totalDeposit + ); + + event Withdrawn( + address indexed account, + address withdrawAddress, + uint256 amount + ); + + /// Emitted when stake or unstake delay are modified + event StakeLocked( + address indexed account, + uint256 totalStaked, + uint256 unstakeDelaySec + ); + + /// Emitted once a stake is scheduled for withdrawal + event StakeUnlocked( + address indexed account, + uint256 withdrawTime + ); + + event StakeWithdrawn( + address indexed account, + address withdrawAddress, + uint256 amount + ); + + /** + * @param deposit the entity's deposit + * @param staked true if this entity is staked. + * @param stake actual amount of ether staked for this entity. + * @param unstakeDelaySec minimum delay to withdraw the stake. + * @param withdrawTime - first block timestamp where 'withdrawStake' will be callable, or zero if already locked + * @dev sizes were chosen so that (deposit,staked, stake) fit into one cell (used during handleOps) + * and the rest fit into a 2nd cell. + * 112 bit allows for 10^15 eth + * 48 bit for full timestamp + * 32 bit allows 150 years for unstake delay + */ + struct DepositInfo { + uint112 deposit; + bool staked; + uint112 stake; + uint32 unstakeDelaySec; + uint48 withdrawTime; + } + + //API struct used by getStakeInfo and simulateValidation + struct StakeInfo { + uint256 stake; + uint256 unstakeDelaySec; + } + + /// @return info - full deposit information of given account + function getDepositInfo(address account) external view returns (DepositInfo memory info); + + /// @return the deposit (for gas payment) of the account + function balanceOf(address account) external view returns (uint256); + + /** + * add to the deposit of the given account + */ + function depositTo(address account) external payable; + + /** + * add to the account's stake - amount and delay + * any pending unstake is first cancelled. + * @param _unstakeDelaySec the new lock duration before the deposit can be withdrawn. + */ + function addStake(uint32 _unstakeDelaySec) external payable; + + /** + * attempt to unlock the stake. + * the value can be withdrawn (using withdrawStake) after the unstake delay. + */ + function unlockStake() external; + + /** + * withdraw from the (unlocked) stake. + * must first call unlockStake and wait for the unstakeDelay to pass + * @param withdrawAddress the address to send withdrawn value. + */ + function withdrawStake(address payable withdrawAddress) external; + + /** + * withdraw from the deposit. + * @param withdrawAddress the address to send withdrawn value. + * @param withdrawAmount the amount to withdraw. + */ + function withdrawTo(address payable withdrawAddress, uint256 withdrawAmount) external; +} diff --git a/contracts/src/v0.8/vendor/entrypoint/interfaces/UserOperation.sol b/contracts/src/v0.8/vendor/entrypoint/interfaces/UserOperation.sol new file mode 100644 index 00000000000..dfff42791f3 --- /dev/null +++ b/contracts/src/v0.8/vendor/entrypoint/interfaces/UserOperation.sol @@ -0,0 +1,84 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity ^0.8.12; + +/* solhint-disable no-inline-assembly */ + + /** + * User Operation struct + * @param sender the sender account of this request. + * @param nonce unique value the sender uses to verify it is not a replay. + * @param initCode if set, the account contract will be created by this constructor/ + * @param callData the method call to execute on this account. + * @param callGasLimit the gas limit passed to the callData method call. + * @param verificationGasLimit gas used for validateUserOp and validatePaymasterUserOp. + * @param preVerificationGas gas not calculated by the handleOps method, but added to the gas paid. Covers batch overhead. + * @param maxFeePerGas same as EIP-1559 gas parameter. + * @param maxPriorityFeePerGas same as EIP-1559 gas parameter. + * @param paymasterAndData if set, this field holds the paymaster address and paymaster-specific data. the paymaster will pay for the transaction instead of the sender. + * @param signature sender-verified signature over the entire request, the EntryPoint address and the chain ID. + */ + struct UserOperation { + + address sender; + uint256 nonce; + bytes initCode; + bytes callData; + uint256 callGasLimit; + uint256 verificationGasLimit; + uint256 preVerificationGas; + uint256 maxFeePerGas; + uint256 maxPriorityFeePerGas; + bytes paymasterAndData; + bytes signature; + } + +/** + * Utility functions helpful when working with UserOperation structs. + */ +library UserOperationLib { + + function getSender(UserOperation calldata userOp) internal pure returns (address) { + address data; + //read sender from userOp, which is first userOp member (saves 800 gas...) + assembly {data := calldataload(userOp)} + return address(uint160(data)); + } + + //relayer/block builder might submit the TX with higher priorityFee, but the user should not + // pay above what he signed for. + function gasPrice(UserOperation calldata userOp) internal view returns (uint256) { + unchecked { + uint256 maxFeePerGas = userOp.maxFeePerGas; + uint256 maxPriorityFeePerGas = userOp.maxPriorityFeePerGas; + if (maxFeePerGas == maxPriorityFeePerGas) { + //legacy mode (for networks that don't support basefee opcode) + return maxFeePerGas; + } + return min(maxFeePerGas, maxPriorityFeePerGas + block.basefee); + } + } + + function pack(UserOperation calldata userOp) internal pure returns (bytes memory ret) { + //lighter signature scheme. must match UserOp.ts#packUserOp + bytes calldata sig = userOp.signature; + // copy directly the userOp from calldata up to (but not including) the signature. + // this encoding depends on the ABI encoding of calldata, but is much lighter to copy + // than referencing each field separately. + assembly { + let ofs := userOp + let len := sub(sub(sig.offset, ofs), 32) + ret := mload(0x40) + mstore(0x40, add(ret, add(len, 32))) + mstore(ret, len) + calldatacopy(add(ret, 32), ofs, len) + } + } + + function hash(UserOperation calldata userOp) internal pure returns (bytes32) { + return keccak256(pack(userOp)); + } + + function min(uint256 a, uint256 b) internal pure returns (uint256) { + return a < b ? a : b; + } +} diff --git a/contracts/src/v0.8/vendor/entrypoint/utils/Exec.sol b/contracts/src/v0.8/vendor/entrypoint/utils/Exec.sol new file mode 100644 index 00000000000..69d653d938a --- /dev/null +++ b/contracts/src/v0.8/vendor/entrypoint/utils/Exec.sol @@ -0,0 +1,70 @@ +// SPDX-License-Identifier: LGPL-3.0-only +pragma solidity >=0.7.5 <0.9.0; + +// solhint-disable no-inline-assembly + +/** + * Utility functions helpful when making different kinds of contract calls in Solidity. + */ +library Exec { + + function call( + address to, + uint256 value, + bytes memory data, + uint256 txGas + ) internal returns (bool success) { + assembly { + success := call(txGas, to, value, add(data, 0x20), mload(data), 0, 0) + } + } + + function staticcall( + address to, + bytes memory data, + uint256 txGas + ) internal view returns (bool success) { + assembly { + success := staticcall(txGas, to, add(data, 0x20), mload(data), 0, 0) + } + } + + function delegateCall( + address to, + bytes memory data, + uint256 txGas + ) internal returns (bool success) { + assembly { + success := delegatecall(txGas, to, add(data, 0x20), mload(data), 0, 0) + } + } + + // get returned data from last call or calldelegate + function getReturnData(uint256 maxLen) internal pure returns (bytes memory returnData) { + assembly { + let len := returndatasize() + if gt(len, maxLen) { + len := maxLen + } + let ptr := mload(0x40) + mstore(0x40, add(ptr, add(len, 0x20))) + mstore(ptr, len) + returndatacopy(add(ptr, 0x20), 0, len) + returnData := ptr + } + } + + // revert with explicit byte array (probably reverted info from call) + function revertWithData(bytes memory returnData) internal pure { + assembly { + revert(add(returnData, 32), mload(returnData)) + } + } + + function callAndRevert(address to, bytes memory data, uint256 maxLen) internal { + bool success = call(to,0,data,gasleft()); + if (!success) { + revertWithData(getReturnData(maxLen)); + } + } +} diff --git a/contracts/src/v0.8/vendor/forge-std/src/Vm.sol b/contracts/src/v0.8/vendor/forge-std/src/Vm.sol index 0f2dc50ff70..591508c097a 100644 --- a/contracts/src/v0.8/vendor/forge-std/src/Vm.sol +++ b/contracts/src/v0.8/vendor/forge-std/src/Vm.sol @@ -243,27 +243,6 @@ interface VmSafe { uint64 gasRemaining; } - /// The result of the `stopDebugTraceRecording` call - struct DebugStep { - // The stack before executing the step of the run. - // stack\[0\] represents the top of the stack. - // and only stack data relevant to the opcode execution is contained. - uint256[] stack; - // The memory input data before executing the step of the run. - // only input data relevant to the opcode execution is contained. - // e.g. for MLOAD, it will have memory\[offset:offset+32\] copied here. - // the offset value can be get by the stack data. - bytes memoryInput; - // The opcode that was accessed. - uint8 opcode; - // The call depth of the step. - uint64 depth; - // Whether the call end up with out of gas error. - bool isOutOfGas; - // The contract address where the opcode is running - address contractAddr; - } - // ======== Crypto ======== /// Derives a private key from the name, labels the account with that name, and returns the wallet. @@ -306,23 +285,6 @@ interface VmSafe { /// Adds a private key to the local forge wallet and returns the address. function rememberKey(uint256 privateKey) external returns (address keyAddr); - /// Derive a set number of wallets from a mnemonic at the derivation path `m/44'/60'/0'/0/{0..count}`. - /// - /// The respective private keys are saved to the local forge wallet for later use and their addresses are returned. - function rememberKeys(string calldata mnemonic, string calldata derivationPath, uint32 count) - external - returns (address[] memory keyAddrs); - - /// Derive a set number of wallets from a mnemonic in the specified language at the derivation path `m/44'/60'/0'/0/{0..count}`. - /// - /// The respective private keys are saved to the local forge wallet for later use and their addresses are returned. - function rememberKeys( - string calldata mnemonic, - string calldata derivationPath, - string calldata language, - uint32 count - ) external returns (address[] memory keyAddrs); - /// Signs data with a `Wallet`. /// Returns a compact signature (`r`, `vs`) as per EIP-2098, where `vs` encodes both the /// signature's `s` value, and the recovery id `v` in a single bytes32. @@ -582,7 +544,7 @@ interface VmSafe { /// Gets all the recorded logs. function getRecordedLogs() external returns (Log[] memory logs); - /// Gets the gas used in the last call from the callee perspective. + /// Gets the gas used in the last call. function lastCallGas() external view returns (Gas memory gas); /// Loads a storage slot from an address. @@ -611,9 +573,6 @@ interface VmSafe { external returns (bytes memory data); - /// Records the debug trace during the run. - function startDebugTraceRecording() external; - /// Starts recording all map SSTOREs for later retrieval. function startMappingRecording() external; @@ -621,9 +580,6 @@ interface VmSafe { /// along with the context of the calls function startStateDiffRecording() external; - /// Stop debug trace recording and returns the recorded debug trace. - function stopAndReturnDebugTraceRecording() external returns (DebugStep[] memory step); - /// Returns an ordered array of all account accesses from a `vm.startStateDiffRecording` session. function stopAndReturnStateDiff() external returns (AccountAccess[] memory accountAccesses); @@ -975,9 +931,6 @@ interface VmSafe { /// provided as the sender that can later be signed and sent onchain. function broadcast(uint256 privateKey) external; - /// Returns addresses of available unlocked wallets in the script environment. - function getScriptWallets() external returns (address[] memory wallets); - /// Has all subsequent calls (at this call depth only) create transactions that can later be signed and sent onchain. /// Broadcasting address is determined by checking the following in order: /// 1. If `--sender` argument was provided, that address is used. @@ -996,9 +949,6 @@ interface VmSafe { /// Stops collecting onchain transactions. function stopBroadcast() external; - /// Returns addresses of available unlocked wallets in the script environment. - function getWallets() external returns (address[] memory wallets); - // ======== String ======== /// Returns the index of the first occurrence of a `key` in an `input` string. @@ -1497,10 +1447,10 @@ interface VmSafe { function assumeNoRevert() external pure; /// Writes a breakpoint to jump to in the debugger. - function breakpoint(string calldata char) external pure; + function breakpoint(string calldata char) external; /// Writes a conditional breakpoint to jump to in the debugger. - function breakpoint(string calldata char, bool value) external pure; + function breakpoint(string calldata char, bool value) external; /// Returns the Foundry version. /// Format: ++ @@ -1642,22 +1592,16 @@ interface VmSafe { /// Returns a random `address`. function randomAddress() external returns (address); - /// Returns a random `bool`. + /// Returns an random `bool`. function randomBool() external view returns (bool); - /// Returns a random byte array value of the given length. + /// Returns an random byte array value of the given length. function randomBytes(uint256 len) external view returns (bytes memory); - /// Returns a random fixed-size byte array of length 4. - function randomBytes4() external view returns (bytes4); - - /// Returns a random fixed-size byte array of length 8. - function randomBytes8() external view returns (bytes8); - - /// Returns a random `int256` value. + /// Returns an random `int256` value. function randomInt() external view returns (int256); - /// Returns a random `int256` value of given bits. + /// Returns an random `int256` value of given bits. function randomInt(uint256 bits) external view returns (int256); /// Returns a random uint256 value. @@ -1666,7 +1610,7 @@ interface VmSafe { /// Returns random uint256 value between the provided range (=min..=max). function randomUint(uint256 min, uint256 max) external returns (uint256); - /// Returns a random `uint256` value of given bits. + /// Returns an random `uint256` value of given bits. function randomUint(uint256 bits) external view returns (uint256); /// Unpauses collection of call traces. @@ -1713,9 +1657,6 @@ interface Vm is VmSafe { /// Clears all mocked calls. function clearMockedCalls() external; - /// Clones a source account code, state, balance and nonce to a target account and updates in-memory EVM state. - function cloneAccount(address source, address target) external; - /// Sets `block.coinbase`. function coinbase(address newCoinbase) external; @@ -1746,10 +1687,10 @@ interface Vm is VmSafe { /// Takes the snapshot ID to delete. /// Returns `true` if the snapshot was successfully deleted. /// Returns `false` if the snapshot does not exist. - function deleteStateSnapshot(uint256 snapshotId) external returns (bool success); + function deleteSnapshot(uint256 snapshotId) external returns (bool success); /// Removes _all_ snapshots previously created by `snapshot`. - function deleteStateSnapshots() external; + function deleteSnapshots() external; /// Sets `block.difficulty`. /// Not available on EVM versions from Paris onwards. Use `prevrandao` instead. @@ -1773,7 +1714,7 @@ interface Vm is VmSafe { /// Returns true if the account is marked as persistent. function isPersistent(address account) external view returns (bool persistent); - /// Load a genesis JSON file's `allocs` into the in-memory EVM state. + /// Load a genesis JSON file's `allocs` into the in-memory revm state. function loadAllocs(string calldata pathToAllocsJson) external; /// Marks that the account(s) should use persistent storage across fork swaps in a multifork setup @@ -1806,12 +1747,6 @@ interface Vm is VmSafe { /// Calldata match takes precedence over `msg.value` in case of ambiguity. function mockCall(address callee, uint256 msgValue, bytes calldata data, bytes calldata returnData) external; - /// Mocks multiple calls to an address, returning specified data for each call. - function mockCalls(address callee, bytes calldata data, bytes[] calldata returnData) external; - - /// Mocks multiple calls to an address with a specific `msg.value`, returning specified data for each call. - function mockCalls(address callee, uint256 msgValue, bytes calldata data, bytes[] calldata returnData) external; - /// Whenever a call is made to `callee` with calldata `data`, this cheatcode instead calls /// `target` with the same calldata. This functionality is similar to a delegate call made to /// `target` contract from `callee`. @@ -1846,14 +1781,14 @@ interface Vm is VmSafe { /// Takes the snapshot ID to revert to. /// Returns `true` if the snapshot was successfully reverted. /// Returns `false` if the snapshot does not exist. - /// **Note:** This does not automatically delete the snapshot. To delete the snapshot use `deleteStateSnapshot`. - function revertToState(uint256 snapshotId) external returns (bool success); + /// **Note:** This does not automatically delete the snapshot. To delete the snapshot use `deleteSnapshot`. + function revertTo(uint256 snapshotId) external returns (bool success); /// Revert the state of the EVM to a previous snapshot and automatically deletes the snapshots /// Takes the snapshot ID to revert to. /// Returns `true` if the snapshot was successfully reverted and deleted. /// Returns `false` if the snapshot does not exist. - function revertToStateAndDelete(uint256 snapshotId) external returns (bool success); + function revertToAndDelete(uint256 snapshotId) external returns (bool success); /// Revokes persistent status from the address, previously added via `makePersistent`. function revokePersistent(address account) external; @@ -1891,23 +1826,10 @@ interface Vm is VmSafe { /// Sets the nonce of an account to an arbitrary value. function setNonceUnsafe(address account, uint64 newNonce) external; - /// Snapshot capture the gas usage of the last call by name from the callee perspective. - function snapshotGasLastCall(string calldata name) external returns (uint256 gasUsed); - - /// Snapshot capture the gas usage of the last call by name in a group from the callee perspective. - function snapshotGasLastCall(string calldata group, string calldata name) external returns (uint256 gasUsed); - /// Snapshot the current state of the evm. /// Returns the ID of the snapshot that was created. - /// To revert a snapshot use `revertToState`. - function snapshotState() external returns (uint256 snapshotId); - - /// Snapshot capture an arbitrary numerical value by name. - /// The group name is derived from the contract name. - function snapshotValue(string calldata name, uint256 value) external; - - /// Snapshot capture an arbitrary numerical value by name in a group. - function snapshotValue(string calldata group, string calldata name, uint256 value) external; + /// To revert a snapshot use `revertTo`. + function snapshot() external returns (uint256 snapshotId); /// Sets all subsequent calls' `msg.sender` to be the input address until `stopPrank` is called. function startPrank(address msgSender) external; @@ -1915,26 +1837,9 @@ interface Vm is VmSafe { /// Sets all subsequent calls' `msg.sender` to be the input address until `stopPrank` is called, and the `tx.origin` to be the second input. function startPrank(address msgSender, address txOrigin) external; - /// Start a snapshot capture of the current gas usage by name. - /// The group name is derived from the contract name. - function startSnapshotGas(string calldata name) external; - - /// Start a snapshot capture of the current gas usage by name in a group. - function startSnapshotGas(string calldata group, string calldata name) external; - /// Resets subsequent calls' `msg.sender` to be `address(this)`. function stopPrank() external; - /// Stop the snapshot capture of the current gas by latest snapshot name, capturing the gas used since the start. - function stopSnapshotGas() external returns (uint256 gasUsed); - - /// Stop the snapshot capture of the current gas usage by name, capturing the gas used since the start. - /// The group name is derived from the contract name. - function stopSnapshotGas(string calldata name) external returns (uint256 gasUsed); - - /// Stop the snapshot capture of the current gas usage by name in a group, capturing the gas used since the start. - function stopSnapshotGas(string calldata group, string calldata name) external returns (uint256 gasUsed); - /// Stores a value to an address' storage slot. function store(address target, bytes32 slot, bytes32 value) external; @@ -1950,21 +1855,6 @@ interface Vm is VmSafe { /// Sets `block.timestamp`. function warp(uint256 newTimestamp) external; - /// `deleteSnapshot` is being deprecated in favor of `deleteStateSnapshot`. It will be removed in future versions. - function deleteSnapshot(uint256 snapshotId) external returns (bool success); - - /// `deleteSnapshots` is being deprecated in favor of `deleteStateSnapshots`. It will be removed in future versions. - function deleteSnapshots() external; - - /// `revertToAndDelete` is being deprecated in favor of `revertToStateAndDelete`. It will be removed in future versions. - function revertToAndDelete(uint256 snapshotId) external returns (bool success); - - /// `revertTo` is being deprecated in favor of `revertToState`. It will be removed in future versions. - function revertTo(uint256 snapshotId) external returns (bool success); - - /// `snapshot` is being deprecated in favor of `snapshotState`. It will be removed in future versions. - function snapshot() external returns (uint256 snapshotId); - // ======== Testing ======== /// Expect a call to an address with the specified `msg.value` and calldata, and a *minimum* amount of gas. diff --git a/contracts/src/v0.8/vendor/multicall/ebd8b64/src/Multicall3.sol b/contracts/src/v0.8/vendor/multicall/ebd8b64/src/Multicall3.sol deleted file mode 100644 index 81c9ff681d8..00000000000 --- a/contracts/src/v0.8/vendor/multicall/ebd8b64/src/Multicall3.sol +++ /dev/null @@ -1,216 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.12; - -/// @title Multicall3 -/// @notice Aggregate results from multiple function calls -/// @dev Multicall & Multicall2 backwards-compatible -/// @dev Aggregate methods are marked `payable` to save 24 gas per call -/// @author Michael Elliot -/// @author Joshua Levine -/// @author Nick Johnson -/// @author Andreas Bigger -/// @author Matt Solomon -contract Multicall3 { - struct Call { - address target; - bytes callData; - } - - struct Call3 { - address target; - bool allowFailure; - bytes callData; - } - - struct Call3Value { - address target; - bool allowFailure; - uint256 value; - bytes callData; - } - - struct Result { - bool success; - bytes returnData; - } - - /// @notice Backwards-compatible call aggregation with Multicall - /// @param calls An array of Call structs - /// @return blockNumber The block number where the calls were executed - /// @return returnData An array of bytes containing the responses - function aggregate(Call[] calldata calls) public payable returns (uint256 blockNumber, bytes[] memory returnData) { - blockNumber = block.number; - uint256 length = calls.length; - returnData = new bytes[](length); - Call calldata call; - for (uint256 i = 0; i < length;) { - bool success; - call = calls[i]; - (success, returnData[i]) = call.target.call(call.callData); - require(success, "Multicall3: call failed"); - unchecked { ++i; } - } - } - - /// @notice Backwards-compatible with Multicall2 - /// @notice Aggregate calls without requiring success - /// @param requireSuccess If true, require all calls to succeed - /// @param calls An array of Call structs - /// @return returnData An array of Result structs - function tryAggregate(bool requireSuccess, Call[] calldata calls) public payable returns (Result[] memory returnData) { - uint256 length = calls.length; - returnData = new Result[](length); - Call calldata call; - for (uint256 i = 0; i < length;) { - Result memory result = returnData[i]; - call = calls[i]; - (result.success, result.returnData) = call.target.call(call.callData); - if (requireSuccess) require(result.success, "Multicall3: call failed"); - unchecked { ++i; } - } - } - - /// @notice Backwards-compatible with Multicall2 - /// @notice Aggregate calls and allow failures using tryAggregate - /// @param calls An array of Call structs - /// @return blockNumber The block number where the calls were executed - /// @return blockHash The hash of the block where the calls were executed - /// @return returnData An array of Result structs - function tryBlockAndAggregate(bool requireSuccess, Call[] calldata calls) public payable returns (uint256 blockNumber, bytes32 blockHash, Result[] memory returnData) { - blockNumber = block.number; - blockHash = blockhash(block.number); - returnData = tryAggregate(requireSuccess, calls); - } - - /// @notice Backwards-compatible with Multicall2 - /// @notice Aggregate calls and allow failures using tryAggregate - /// @param calls An array of Call structs - /// @return blockNumber The block number where the calls were executed - /// @return blockHash The hash of the block where the calls were executed - /// @return returnData An array of Result structs - function blockAndAggregate(Call[] calldata calls) public payable returns (uint256 blockNumber, bytes32 blockHash, Result[] memory returnData) { - (blockNumber, blockHash, returnData) = tryBlockAndAggregate(true, calls); - } - - /// @notice Aggregate calls, ensuring each returns success if required - /// @param calls An array of Call3 structs - /// @return returnData An array of Result structs - function aggregate3(Call3[] calldata calls) public payable returns (Result[] memory returnData) { - uint256 length = calls.length; - returnData = new Result[](length); - Call3 calldata calli; - for (uint256 i = 0; i < length;) { - Result memory result = returnData[i]; - calli = calls[i]; - (result.success, result.returnData) = calli.target.call(calli.callData); - assembly { - // Revert if the call fails and failure is not allowed - // `allowFailure := calldataload(add(calli, 0x20))` and `success := mload(result)` - if iszero(or(calldataload(add(calli, 0x20)), mload(result))) { - // set "Error(string)" signature: bytes32(bytes4(keccak256("Error(string)"))) - mstore(0x00, 0x08c379a000000000000000000000000000000000000000000000000000000000) - // set data offset - mstore(0x04, 0x0000000000000000000000000000000000000000000000000000000000000020) - // set length of revert string - mstore(0x24, 0x0000000000000000000000000000000000000000000000000000000000000017) - // set revert string: bytes32(abi.encodePacked("Multicall3: call failed")) - mstore(0x44, 0x4d756c746963616c6c333a2063616c6c206661696c6564000000000000000000) - revert(0x00, 0x64) - } - } - unchecked { ++i; } - } - } - - /// @notice Aggregate calls with a msg value - /// @notice Reverts if msg.value is less than the sum of the call values - /// @param calls An array of Call3Value structs - /// @return returnData An array of Result structs - function aggregate3Value(Call3Value[] calldata calls) public payable returns (Result[] memory returnData) { - uint256 valAccumulator; - uint256 length = calls.length; - returnData = new Result[](length); - Call3Value calldata calli; - for (uint256 i = 0; i < length;) { - Result memory result = returnData[i]; - calli = calls[i]; - uint256 val = calli.value; - // Humanity will be a Type V Kardashev Civilization before this overflows - andreas - // ~ 10^25 Wei in existence << ~ 10^76 size uint fits in a uint256 - unchecked { valAccumulator += val; } - (result.success, result.returnData) = calli.target.call{value: val}(calli.callData); - assembly { - // Revert if the call fails and failure is not allowed - // `allowFailure := calldataload(add(calli, 0x20))` and `success := mload(result)` - if iszero(or(calldataload(add(calli, 0x20)), mload(result))) { - // set "Error(string)" signature: bytes32(bytes4(keccak256("Error(string)"))) - mstore(0x00, 0x08c379a000000000000000000000000000000000000000000000000000000000) - // set data offset - mstore(0x04, 0x0000000000000000000000000000000000000000000000000000000000000020) - // set length of revert string - mstore(0x24, 0x0000000000000000000000000000000000000000000000000000000000000017) - // set revert string: bytes32(abi.encodePacked("Multicall3: call failed")) - mstore(0x44, 0x4d756c746963616c6c333a2063616c6c206661696c6564000000000000000000) - revert(0x00, 0x84) - } - } - unchecked { ++i; } - } - // Finally, make sure the msg.value = SUM(call[0...i].value) - require(msg.value == valAccumulator, "Multicall3: value mismatch"); - } - - /// @notice Returns the block hash for the given block number - /// @param blockNumber The block number - function getBlockHash(uint256 blockNumber) public view returns (bytes32 blockHash) { - blockHash = blockhash(blockNumber); - } - - /// @notice Returns the block number - function getBlockNumber() public view returns (uint256 blockNumber) { - blockNumber = block.number; - } - - /// @notice Returns the block coinbase - function getCurrentBlockCoinbase() public view returns (address coinbase) { - coinbase = block.coinbase; - } - - /// @notice Returns the block difficulty - function getCurrentBlockDifficulty() public view returns (uint256 difficulty) { - difficulty = block.difficulty; - } - - /// @notice Returns the block gas limit - function getCurrentBlockGasLimit() public view returns (uint256 gaslimit) { - gaslimit = block.gaslimit; - } - - /// @notice Returns the block timestamp - function getCurrentBlockTimestamp() public view returns (uint256 timestamp) { - timestamp = block.timestamp; - } - - /// @notice Returns the (ETH) balance of a given address - function getEthBalance(address addr) public view returns (uint256 balance) { - balance = addr.balance; - } - - /// @notice Returns the block hash of the last block - function getLastBlockHash() public view returns (bytes32 blockHash) { - unchecked { - blockHash = blockhash(block.number - 1); - } - } - - /// @notice Gets the base fee of the given block - /// @notice Can revert if the BASEFEE opcode is not implemented by the given chain - function getBasefee() public view returns (uint256 basefee) { - basefee = block.basefee; - } - - /// @notice Returns the chain id - function getChainId() public view returns (uint256 chainid) { - chainid = block.chainid; - } -} diff --git a/contracts/src/v0.8/workflow/dev/WorkflowRegistry.sol b/contracts/src/v0.8/workflow/dev/WorkflowRegistry.sol index 2454374b2fb..b0b6a120f86 100644 --- a/contracts/src/v0.8/workflow/dev/WorkflowRegistry.sol +++ b/contracts/src/v0.8/workflow/dev/WorkflowRegistry.sol @@ -43,8 +43,6 @@ contract WorkflowRegistry is Ownable2StepMsgSender, ITypeAndVersion { /// @dev Mapping to track workflows by secretsURL hash (owner + secretsURL). /// This is used to find all workflows that have the same secretsURL when a force secrets update event is requested. mapping(bytes32 secretsURLHash => EnumerableSet.Bytes32Set workflowKeys) private s_secretsHashToWorkflows; - /// @dev Keep track of all workflowIDs to ensure uniqueness. - mapping(bytes32 workflowID => bool inUse) private s_workflowIDs; /// @dev List of all authorized EOAs/contracts allowed to access this contract's state functions. All view functions are open access. EnumerableSet.AddressSet private s_authorizedAddresses; @@ -85,8 +83,8 @@ contract WorkflowRegistry is Ownable2StepMsgSender, ITypeAndVersion { bytes32 indexed workflowID, address indexed workflowOwner, uint32 indexed donID, string workflowName ); event WorkflowForceUpdateSecretsRequestedV1(address indexed owner, bytes32 secretsURLHash, string workflowName); - event RegistryLockedV1(address lockedBy); - event RegistryUnlockedV1(address unlockedBy); + event RegistryLockedV1(address indexed lockedBy); + event RegistryUnlockedV1(address indexed unlockedBy); error AddressNotAuthorized(address caller); error CallerIsNotWorkflowOwner(address caller); @@ -205,15 +203,13 @@ contract WorkflowRegistry is Ownable2StepMsgSender, ITypeAndVersion { ) external registryNotLocked { _validatePermissions(donID, msg.sender); _validateWorkflowName(bytes(workflowName).length); - _validateWorkflowURLs(bytes(binaryURL).length, bytes(configURL).length, bytes(secretsURL).length); + _validateWorkflowMetadata(workflowID, bytes(binaryURL).length, bytes(configURL).length, bytes(secretsURL).length); bytes32 workflowKey = computeHashKey(msg.sender, workflowName); if (s_workflows[workflowKey].owner != address(0)) { revert WorkflowAlreadyRegistered(); } - _requireUniqueWorkflowID(workflowID); - // Create new workflow entry s_workflows[workflowKey] = WorkflowMetadata({ workflowID: workflowID, @@ -276,7 +272,7 @@ contract WorkflowRegistry is Ownable2StepMsgSender, ITypeAndVersion { string calldata configURL, string calldata secretsURL ) external registryNotLocked { - _validateWorkflowURLs(bytes(binaryURL).length, bytes(configURL).length, bytes(secretsURL).length); + _validateWorkflowMetadata(newWorkflowID, bytes(binaryURL).length, bytes(configURL).length, bytes(secretsURL).length); WorkflowMetadata storage workflow = _getWorkflowFromStorage(msg.sender, workflowKey); @@ -299,12 +295,6 @@ contract WorkflowRegistry is Ownable2StepMsgSender, ITypeAndVersion { revert WorkflowContentNotUpdated(); } - // Ensure the new workflowID is unique - _requireUniqueWorkflowID(newWorkflowID); - - // Free the old workflowID - s_workflowIDs[currentWorkflowID] = false; - // Update all fields that have changed and the relevant sets workflow.workflowID = newWorkflowID; if (!sameBinaryURL) { @@ -316,7 +306,7 @@ contract WorkflowRegistry is Ownable2StepMsgSender, ITypeAndVersion { if (!sameSecretsURL) { // Remove the old secrets hash if secretsURL is not empty if (bytes(workflow.secretsURL).length > 0) { - // Using keccak256 instead of computeHashKey as currentSecretsURL is memory + // Using keccak256 instead of _computeOwnerAndStringFieldHashKey as currentSecretsURL is memory bytes32 oldSecretsHash = keccak256(abi.encodePacked(msg.sender, workflow.secretsURL)); s_secretsHashToWorkflows[oldSecretsHash].remove(workflowKey); } @@ -388,34 +378,34 @@ contract WorkflowRegistry is Ownable2StepMsgSender, ITypeAndVersion { function deleteWorkflow( bytes32 workflowKey ) external registryNotLocked { + address sender = msg.sender; + // Retrieve workflow metadata from storage - WorkflowMetadata storage workflow = _getWorkflowFromStorage(msg.sender, workflowKey); + WorkflowMetadata storage workflow = _getWorkflowFromStorage(sender, workflowKey); + uint32 donID = workflow.donID; // Only checking access for the caller instead of using _validatePermissions so that even if the DON was removed from the // allowed list, the workflow can still be deleted. - if (!s_authorizedAddresses.contains(msg.sender)) { - revert AddressNotAuthorized(msg.sender); + if (!s_authorizedAddresses.contains(sender)) { + revert AddressNotAuthorized(sender); } - // Release the workflowID for reuse - s_workflowIDs[workflow.workflowID] = false; - // Remove the workflow from the owner and DON mappings - s_ownerWorkflowKeys[msg.sender].remove(workflowKey); - s_donWorkflowKeys[workflow.donID].remove(workflowKey); + s_ownerWorkflowKeys[sender].remove(workflowKey); + s_donWorkflowKeys[donID].remove(workflowKey); // Remove the workflow from the secrets hash set if secretsURL is not empty if (bytes(workflow.secretsURL).length > 0) { - // Using keccak256 instead of computeHashKey as secretsURL is storage ref - bytes32 secretsHash = keccak256(abi.encodePacked(msg.sender, workflow.secretsURL)); + // Using keccak256 instead of _computeOwnerAndStringFieldHashKey as secretsURL is storage ref + bytes32 secretsHash = keccak256(abi.encodePacked(sender, workflow.secretsURL)); s_secretsHashToWorkflows[secretsHash].remove(workflowKey); } - // Emit an event indicating the workflow has been deleted. We need to do this before deleting the workflow from storage. - emit WorkflowDeletedV1(workflow.workflowID, msg.sender, workflow.donID, workflow.workflowName); - // Delete the workflow metadata from storage delete s_workflows[workflowKey]; + + // Emit an event indicating the workflow has been deleted + emit WorkflowDeletedV1(workflow.workflowID, sender, donID, workflow.workflowName); } /// @notice Requests a force update for workflows that share the same secrets URL. @@ -440,8 +430,10 @@ contract WorkflowRegistry is Ownable2StepMsgSender, ITypeAndVersion { function requestForceUpdateSecrets( string calldata secretsURL ) external registryNotLocked { + address sender = msg.sender; + // Use secretsURL and sender hash key to get the mapping key - bytes32 secretsHash = computeHashKey(msg.sender, secretsURL); + bytes32 secretsHash = computeHashKey(sender, secretsURL); // Retrieve all workflow keys associated with the given secrets hash EnumerableSet.Bytes32Set storage workflowKeys = s_secretsHashToWorkflows[secretsHash]; @@ -457,8 +449,8 @@ contract WorkflowRegistry is Ownable2StepMsgSender, ITypeAndVersion { bytes32 workflowKey = workflowKeys.at(i); WorkflowMetadata storage workflow = s_workflows[workflowKey]; - if (s_allowedDONs.contains(workflow.donID) && s_authorizedAddresses.contains(msg.sender)) { - emit WorkflowForceUpdateSecretsRequestedV1(msg.sender, secretsHash, workflow.workflowName); + if (s_allowedDONs.contains(workflow.donID) && s_authorizedAddresses.contains(sender)) { + emit WorkflowForceUpdateSecretsRequestedV1(sender, secretsHash, workflow.workflowName); } } } @@ -480,8 +472,10 @@ contract WorkflowRegistry is Ownable2StepMsgSender, ITypeAndVersion { /// @param workflowKey The unique identifier for the workflow. /// @param newStatus The new status to set for the workflow (either `Paused` or `Active`). function _updateWorkflowStatus(bytes32 workflowKey, WorkflowStatus newStatus) internal { + address sender = msg.sender; + // Retrieve workflow metadata once - WorkflowMetadata storage workflow = _getWorkflowFromStorage(msg.sender, workflowKey); + WorkflowMetadata storage workflow = _getWorkflowFromStorage(sender, workflowKey); uint32 donID = workflow.donID; // Avoid unnecessary storage writes if already in the desired status @@ -491,7 +485,7 @@ contract WorkflowRegistry is Ownable2StepMsgSender, ITypeAndVersion { // Check if the DON ID is allowed when activating a workflow if (newStatus == WorkflowStatus.ACTIVE) { - _validatePermissions(donID, msg.sender); + _validatePermissions(donID, sender); } // Update the workflow status @@ -499,9 +493,9 @@ contract WorkflowRegistry is Ownable2StepMsgSender, ITypeAndVersion { // Emit the appropriate event based on newStatus if (newStatus == WorkflowStatus.PAUSED) { - emit WorkflowPausedV1(workflow.workflowID, msg.sender, donID, workflow.workflowName); + emit WorkflowPausedV1(workflow.workflowID, sender, donID, workflow.workflowName); } else if (newStatus == WorkflowStatus.ACTIVE) { - emit WorkflowActivatedV1(workflow.workflowID, msg.sender, donID, workflow.workflowName); + emit WorkflowActivatedV1(workflow.workflowID, sender, donID, workflow.workflowName); } } @@ -521,20 +515,6 @@ contract WorkflowRegistry is Ownable2StepMsgSender, ITypeAndVersion { return workflow; } - /// @notice Ensures the given workflowID is unique and marks it as used. - /// @param workflowID The workflowID to validate and consume. - function _requireUniqueWorkflowID( - bytes32 workflowID - ) internal { - if (workflowID == bytes32(0)) revert InvalidWorkflowID(); - - if (s_workflowIDs[workflowID]) { - revert WorkflowIDAlreadyExists(); - } - - s_workflowIDs[workflowID] = true; - } - // ================================================================ // | Workflow Queries | // ================================================================ @@ -663,12 +643,16 @@ contract WorkflowRegistry is Ownable2StepMsgSender, ITypeAndVersion { // | Validation | // ================================================================ - /// @dev Internal function to validate the urls for a workflow. - function _validateWorkflowURLs( + /// @dev Internal function to validate the metadata for a workflow. + /// @param workflowID The unique identifier for the workflow. + function _validateWorkflowMetadata( + bytes32 workflowID, uint256 binaryURLLength, uint256 configURLLength, uint256 secretsURLLength ) internal pure { + if (workflowID == bytes32(0)) revert InvalidWorkflowID(); + if (binaryURLLength > MAX_URL_LENGTH) { revert URLTooLong(binaryURLLength, MAX_URL_LENGTH); } diff --git a/contracts/src/v0.8/workflow/dev/WorkflowRegistryManager.sol b/contracts/src/v0.8/workflow/dev/WorkflowRegistryManager.sol index 818d4a1a8ae..8c760707ee2 100644 --- a/contracts/src/v0.8/workflow/dev/WorkflowRegistryManager.sol +++ b/contracts/src/v0.8/workflow/dev/WorkflowRegistryManager.sol @@ -26,10 +26,6 @@ contract WorkflowRegistryManager is Ownable2StepMsgSender, ITypeAndVersion { /// indexing strategy to avoid off-by-one errors. mapping(uint32 versionNumber => Version versionInfo) private s_versions; - /// @notice Maps a combination of address and chain ID to the version number. - /// @dev This mapping allows for lookup of the version number for a given address and chain ID. - mapping(bytes32 => uint32) private s_versionNumberByAddressAndChainID; - /// @notice The version number of the currently active WorkflowRegistry. /// @dev Initialized to 0 to indicate no active version. Updated when a version is activated. uint32 private s_activeVersionNumber = 0; @@ -38,18 +34,21 @@ contract WorkflowRegistryManager is Ownable2StepMsgSender, ITypeAndVersion { /// @dev Incremented each time a new version is added. Useful for iterating over all registered versions. uint32 private s_latestVersionNumber = 0; + /// @notice Maps a combination of address and chain ID to the version number. + /// @dev This mapping allows for lookup of the version number for a given address and chain ID. + mapping(bytes32 => uint32) private s_versionNumberByAddressAndChainID; + // Errors error InvalidContractAddress(address invalidAddress); error InvalidContractType(address invalidAddress); error NoActiveVersionAvailable(); error NoVersionsRegistered(); error VersionNotRegistered(uint32 versionNumber); - error VersionAlreadyActive(uint32 versionNumber); // Events event VersionAdded(address indexed contractAddress, uint64 chainID, uint32 deployedAt, uint32 version); - event VersionActivated(address indexed contractAddress, uint64 chainID, uint32 version); - event VersionDeactivated(address indexed contractAddress, uint64 chainID, uint32 version); + event VersionActivated(address indexed contractAddress, uint64 chainID, uint32 indexed version); + event VersionDeactivated(address indexed contractAddress, uint64 chainID, uint32 indexed version); // ================================================================ // | Manage Versions | @@ -111,11 +110,6 @@ contract WorkflowRegistryManager is Ownable2StepMsgSender, ITypeAndVersion { // Cache the current active version number to reduce storage reads uint32 currentActiveVersionNumber = s_activeVersionNumber; - // Check that the version number is not the same as the current active version number - if (currentActiveVersionNumber == versionNumber) { - revert VersionAlreadyActive(versionNumber); - } - // Emit deactivation event if there is an active version if (currentActiveVersionNumber != 0) { Version memory currentActive = s_versions[currentActiveVersionNumber]; @@ -184,10 +178,7 @@ contract WorkflowRegistryManager is Ownable2StepMsgSender, ITypeAndVersion { /// @param contractAddress The address of the WorkflowRegistry contract. /// @param chainID The chain ID of the network where the WorkflowRegistry is deployed. /// @return versionNumber The version number associated with the given contract address and chain ID. - function getVersionNumberByContractAddressAndChainID( - address contractAddress, - uint64 chainID - ) external view returns (uint32 versionNumber) { + function getVersionNumber(address contractAddress, uint64 chainID) external view returns (uint32 versionNumber) { _validateContractAddress(contractAddress); bytes32 key = keccak256(abi.encodePacked(contractAddress, chainID)); @@ -210,10 +201,10 @@ contract WorkflowRegistryManager is Ownable2StepMsgSender, ITypeAndVersion { /// @notice Retrieves the details of the latest registered WorkflowRegistry version. /// @return A `Version` struct containing the details of the latest version. - /// @custom:throws NoVersionsRegistered if no versions have been registered. + /// @custom:throws NoActiveVersionAvailable if no versions have been registered. function getLatestVersion() external view returns (Version memory) { uint32 latestVersionNumber = s_latestVersionNumber; - if (latestVersionNumber == 0) revert NoVersionsRegistered(); + if (latestVersionNumber == 0) revert NoActiveVersionAvailable(); return s_versions[latestVersionNumber]; } @@ -255,9 +246,6 @@ contract WorkflowRegistryManager is Ownable2StepMsgSender, ITypeAndVersion { } } - /// @dev Validates that a given contract address is non-zero and contains code. - /// @param _addr The address of the contract to validate. - /// @custom:throws InvalidContractAddress if the address is zero or contains no code. function _validateContractAddress( address _addr ) internal view { diff --git a/contracts/src/v0.8/workflow/mocks/MockContract.sol b/contracts/src/v0.8/workflow/mocks/MockContract.sol deleted file mode 100644 index 667e05daeae..00000000000 --- a/contracts/src/v0.8/workflow/mocks/MockContract.sol +++ /dev/null @@ -1,4 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.24; - -contract MockContract {} diff --git a/contracts/src/v0.8/workflow/mocks/MockWorkflowRegistryContract.sol b/contracts/src/v0.8/workflow/mocks/MockWorkflowRegistryContract.sol deleted file mode 100644 index 8a8c9c7de08..00000000000 --- a/contracts/src/v0.8/workflow/mocks/MockWorkflowRegistryContract.sol +++ /dev/null @@ -1,8 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.24; - -import {ITypeAndVersion} from "../../shared/interfaces/ITypeAndVersion.sol"; - -contract MockWorkflowRegistryContract is ITypeAndVersion { - string public constant override typeAndVersion = "MockWorkflowRegistryContract 1.0.0"; -} diff --git a/contracts/src/v0.8/workflow/test/WorkflowRegistry/WorkflowRegistry.activateWorkflow.t.sol b/contracts/src/v0.8/workflow/test/WorkflowRegistry/WorkflowRegistry.activateWorkflow.t.sol index 3b2bc854325..47858774e0d 100644 --- a/contracts/src/v0.8/workflow/test/WorkflowRegistry/WorkflowRegistry.activateWorkflow.t.sol +++ b/contracts/src/v0.8/workflow/test/WorkflowRegistry/WorkflowRegistry.activateWorkflow.t.sol @@ -104,12 +104,6 @@ contract WorkflowRegistry_activateWorkflow is WorkflowRegistrySetup { s_validSecretsURL ); - // It should emit {WorkflowActivatedV1} when the workflow is activated. - vm.expectEmit(); - emit WorkflowRegistry.WorkflowActivatedV1( - s_validWorkflowID, s_authorizedAddress, s_allowedDonID, s_validWorkflowName - ); - // Activate the workflow. vm.prank(s_authorizedAddress); s_registry.activateWorkflow(s_validWorkflowKey); diff --git a/contracts/src/v0.8/workflow/test/WorkflowRegistry/WorkflowRegistry.activateWorkflow.tree b/contracts/src/v0.8/workflow/test/WorkflowRegistry/WorkflowRegistry.activateWorkflow.tree index 4765b5abbe5..3d71d5844db 100644 --- a/contracts/src/v0.8/workflow/test/WorkflowRegistry/WorkflowRegistry.activateWorkflow.tree +++ b/contracts/src/v0.8/workflow/test/WorkflowRegistry/WorkflowRegistry.activateWorkflow.tree @@ -5,13 +5,13 @@ WorkflowRegistry.activateWorkflow ├── when the caller is not the workflow owner │ └── it should revert └── when the caller is the workflow owner - ├── when the workflow is already active + ├── when the workflow is already paused │ └── it should revert └── when the workflow is paused ├── when the donID is not allowed │ └── it should revert └── when the donID is allowed - ├── when the caller is not an authorized address + └── when the caller is not an authorized address │ └── it should revert └── when the caller is an authorized address - └── it should activate the workflow and emit {WorkflowActivatedV1} + └── it should activate the workflow diff --git a/contracts/src/v0.8/workflow/test/WorkflowRegistry/WorkflowRegistry.deleteWorkflow.t.sol b/contracts/src/v0.8/workflow/test/WorkflowRegistry/WorkflowRegistry.deleteWorkflow.t.sol index 974a3590f03..bbc4c7bb33a 100644 --- a/contracts/src/v0.8/workflow/test/WorkflowRegistry/WorkflowRegistry.deleteWorkflow.t.sol +++ b/contracts/src/v0.8/workflow/test/WorkflowRegistry/WorkflowRegistry.deleteWorkflow.t.sol @@ -57,10 +57,6 @@ contract WorkflowRegistry_deleteWorkflow is WorkflowRegistrySetup { s_registry.getWorkflowMetadata(s_authorizedAddress, s_validWorkflowName); assertEq(workflow.workflowName, s_validWorkflowName); - // It should emit {WorkflowDeletedV1} when the workflow is deleted. - vm.expectEmit(); - emit WorkflowRegistry.WorkflowDeletedV1(s_validWorkflowID, s_authorizedAddress, s_allowedDonID, s_validWorkflowName); - // Delete the workflow. vm.prank(s_authorizedAddress); s_registry.deleteWorkflow(s_validWorkflowKey); @@ -83,10 +79,6 @@ contract WorkflowRegistry_deleteWorkflow is WorkflowRegistrySetup { // Remove the DON from the allowed DONs list. _removeDONFromAllowedDONs(s_allowedDonID); - // It should emit {WorkflowDeletedV1} when the workflow is deleted. - vm.expectEmit(); - emit WorkflowRegistry.WorkflowDeletedV1(s_validWorkflowID, s_authorizedAddress, s_allowedDonID, s_validWorkflowName); - // Delete the workflow. vm.prank(s_authorizedAddress); s_registry.deleteWorkflow(s_validWorkflowKey); diff --git a/contracts/src/v0.8/workflow/test/WorkflowRegistry/WorkflowRegistry.deleteWorkflow.tree b/contracts/src/v0.8/workflow/test/WorkflowRegistry/WorkflowRegistry.deleteWorkflow.tree index 4f6fd289b18..510906137b9 100644 --- a/contracts/src/v0.8/workflow/test/WorkflowRegistry/WorkflowRegistry.deleteWorkflow.tree +++ b/contracts/src/v0.8/workflow/test/WorkflowRegistry/WorkflowRegistry.deleteWorkflow.tree @@ -8,5 +8,5 @@ WorkflowRegistry.deleteWorkflow ├── when the caller is not an authorized address │ └── it should revert └── when the caller is an authorized address - ├── it should delete the workflow if the donID is not allowed and emit {WorkflowDeletedV1} - └── it should delete the workflow if the donID is allowed and emit {WorkflowDeletedV1} + ├── it should delete the workflow if the donID is not allowed + └── it should delete the workflow if the donID is allowed diff --git a/contracts/src/v0.8/workflow/test/WorkflowRegistry/WorkflowRegistry.getAllAllowedDONs.t.sol b/contracts/src/v0.8/workflow/test/WorkflowRegistry/WorkflowRegistry.getAllAllowedDONs.t.sol index 7fdb2462f39..d6c76d369c0 100644 --- a/contracts/src/v0.8/workflow/test/WorkflowRegistry/WorkflowRegistry.getAllAllowedDONs.t.sol +++ b/contracts/src/v0.8/workflow/test/WorkflowRegistry/WorkflowRegistry.getAllAllowedDONs.t.sol @@ -31,16 +31,4 @@ contract WorkflowRegistry_getAllAllowedDONs is WorkflowRegistrySetup { assertEq(allowedDONs[0], s_allowedDonID); assertEq(allowedDONs[1], allowedDonID2); } - - function test_WhenTheRegistryIsLocked() external { - // Lock the registry - vm.prank(s_owner); - s_registry.lockRegistry(); - - // It should behave the same as when the registry is not locked - vm.prank(s_stranger); - uint32[] memory allowedDONs = s_registry.getAllAllowedDONs(); - assertEq(allowedDONs.length, 1); - assertEq(allowedDONs[0], s_allowedDonID); - } } diff --git a/contracts/src/v0.8/workflow/test/WorkflowRegistry/WorkflowRegistry.getAllAllowedDONs.tree b/contracts/src/v0.8/workflow/test/WorkflowRegistry/WorkflowRegistry.getAllAllowedDONs.tree index a6b649a8c98..5e0d4e8d550 100644 --- a/contracts/src/v0.8/workflow/test/WorkflowRegistry/WorkflowRegistry.getAllAllowedDONs.tree +++ b/contracts/src/v0.8/workflow/test/WorkflowRegistry/WorkflowRegistry.getAllAllowedDONs.tree @@ -3,7 +3,5 @@ WorkflowRegistry.getAllAllowedDONs │ └── it should return an empty array ├── when there is a single allowed DON │ └── it should return an array with one element -├── when there are multiple allowed DONs -│ └── it should return an array with all the allowed DONs -└── when the registry is locked - └── it should behave the same as when the registry is not locked +└── when there are multiple allowed DONs + └── it should return an array with all the allowed DONs diff --git a/contracts/src/v0.8/workflow/test/WorkflowRegistry/WorkflowRegistry.getAllAuthorizedAddresses.t.sol b/contracts/src/v0.8/workflow/test/WorkflowRegistry/WorkflowRegistry.getAllAuthorizedAddresses.t.sol index edaef531f77..0b47da3938c 100644 --- a/contracts/src/v0.8/workflow/test/WorkflowRegistry/WorkflowRegistry.getAllAuthorizedAddresses.t.sol +++ b/contracts/src/v0.8/workflow/test/WorkflowRegistry/WorkflowRegistry.getAllAuthorizedAddresses.t.sol @@ -3,7 +3,7 @@ pragma solidity 0.8.24; import {WorkflowRegistrySetup} from "./WorkflowRegistrySetup.t.sol"; -contract WorkflowRegistry_getAllAuthorizedAddresses is WorkflowRegistrySetup { +contract WorkflowRegistrygetAllAuthorizedAddresses is WorkflowRegistrySetup { function test_WhenTheSetOfAuthorizedAddressesIsEmpty() external { // Remove the authorized address added in the setup _removeAddressFromAuthorizedAddresses(s_authorizedAddress); @@ -28,16 +28,4 @@ contract WorkflowRegistry_getAllAuthorizedAddresses is WorkflowRegistrySetup { assertEq(authorizedAddresses[0], s_authorizedAddress); assertEq(authorizedAddresses[1], s_unauthorizedAddress); } - - function test_WhenTheRegistryIsLocked() external { - // Lock the registry - vm.prank(s_owner); - s_registry.lockRegistry(); - - // It should behave the same as when the registry is not locked - vm.prank(s_stranger); - address[] memory authorizedAddresses = s_registry.getAllAuthorizedAddresses(); - assertEq(authorizedAddresses.length, 1); - assertEq(authorizedAddresses[0], s_authorizedAddress); - } } diff --git a/contracts/src/v0.8/workflow/test/WorkflowRegistry/WorkflowRegistry.getAllAuthorizedAddresses.tree b/contracts/src/v0.8/workflow/test/WorkflowRegistry/WorkflowRegistry.getAllAuthorizedAddresses.tree index d4908dbd7ec..86821d2f83e 100644 --- a/contracts/src/v0.8/workflow/test/WorkflowRegistry/WorkflowRegistry.getAllAuthorizedAddresses.tree +++ b/contracts/src/v0.8/workflow/test/WorkflowRegistry/WorkflowRegistry.getAllAuthorizedAddresses.tree @@ -3,7 +3,5 @@ WorkflowRegistry.getAllAuthorizedAddresses │ └── it should return an empty array ├── when there is a single authorized address │ └── it should return an array with one element -├── when there are multiple authorized addresses -│ └── it should return an array with all the authorized addresses -└── when the registry is locked - └── it should behave the same as when the registry is not locked +└── when there are multiple authorized addresses + └── it should return an array with all the authorized addresses diff --git a/contracts/src/v0.8/workflow/test/WorkflowRegistry/WorkflowRegistry.getWorkflowMetadata.t.sol b/contracts/src/v0.8/workflow/test/WorkflowRegistry/WorkflowRegistry.getWorkflowMetadata.t.sol index 5bc78feb0f2..3cd092676be 100644 --- a/contracts/src/v0.8/workflow/test/WorkflowRegistry/WorkflowRegistry.getWorkflowMetadata.t.sol +++ b/contracts/src/v0.8/workflow/test/WorkflowRegistry/WorkflowRegistry.getWorkflowMetadata.t.sol @@ -22,24 +22,4 @@ contract WorkflowRegistry_getWorkflowMetadata is WorkflowRegistrySetup { vm.expectRevert(WorkflowRegistry.WorkflowDoesNotExist.selector); s_registry.getWorkflowMetadata(s_authorizedAddress, "RandomWorkflowName"); } - - function test_WhenTheRegistryIsLocked() external { - // Register a workflow - _registerValidWorkflow(); - - // Lock the registry - vm.prank(s_owner); - s_registry.lockRegistry(); - - // It should behave the same as when the registry is not locked - vm.prank(s_stranger); - WorkflowRegistry.WorkflowMetadata memory metadata = - s_registry.getWorkflowMetadata(s_authorizedAddress, s_validWorkflowName); - - assertEq(metadata.workflowName, s_validWorkflowName); - assertEq(metadata.workflowID, s_validWorkflowID); - assertEq(metadata.binaryURL, s_validBinaryURL); - assertEq(metadata.configURL, s_validConfigURL); - assertEq(metadata.secretsURL, s_validSecretsURL); - } } diff --git a/contracts/src/v0.8/workflow/test/WorkflowRegistry/WorkflowRegistry.getWorkflowMetadata.tree b/contracts/src/v0.8/workflow/test/WorkflowRegistry/WorkflowRegistry.getWorkflowMetadata.tree index 215a2a4329f..f723f720528 100644 --- a/contracts/src/v0.8/workflow/test/WorkflowRegistry/WorkflowRegistry.getWorkflowMetadata.tree +++ b/contracts/src/v0.8/workflow/test/WorkflowRegistry/WorkflowRegistry.getWorkflowMetadata.tree @@ -1,7 +1,5 @@ WorkflowRegistry.getWorkflowMetadata ├── when the workflow exists with the owner and name │ └── it returns the correct metadata -├── when the workflow does not exist -│ └── it reverts with WorkflowDoesNotExist -└── when the registry is locked - └── it should behave the same as when the registry is not locked +└── when the workflow does not exist + └── it reverts with WorkflowDoesNotExist diff --git a/contracts/src/v0.8/workflow/test/WorkflowRegistry/WorkflowRegistry.getWorkflowMetadataListByDON.t.sol b/contracts/src/v0.8/workflow/test/WorkflowRegistry/WorkflowRegistry.getWorkflowMetadataListByDON.t.sol index dbe0b23e5f0..14b3c96a07d 100644 --- a/contracts/src/v0.8/workflow/test/WorkflowRegistry/WorkflowRegistry.getWorkflowMetadataListByDON.t.sol +++ b/contracts/src/v0.8/workflow/test/WorkflowRegistry/WorkflowRegistry.getWorkflowMetadataListByDON.t.sol @@ -6,7 +6,8 @@ import {WorkflowRegistryWithFixture} from "./WorkflowRegistryWithFixture.t.sol"; contract WorkflowRegistry_getWorkflowMetadataListByDON is WorkflowRegistryWithFixture { function test_WhenStartIs0() external view { - WorkflowRegistry.WorkflowMetadata[] memory workflows = s_registry.getWorkflowMetadataListByDON(s_allowedDonID, 0, 0); + WorkflowRegistry.WorkflowMetadata[] memory workflows = + s_registry.getWorkflowMetadataListByDON(s_allowedDonID, 0, 10); assertEq(workflows.length, 3); assertEq(workflows[0].workflowName, s_workflowName1); @@ -122,34 +123,4 @@ contract WorkflowRegistry_getWorkflowMetadataListByDON is WorkflowRegistryWithFi assertEq(workflows.length, 0); } - - function test_WhenTheRegistryIsLocked() external { - // Lock the registry - vm.prank(s_owner); - s_registry.lockRegistry(); - - // It should behave the same as when the registry is not locked - vm.prank(s_stranger); - WorkflowRegistry.WorkflowMetadata[] memory workflows = - s_registry.getWorkflowMetadataListByDON(s_allowedDonID, 0, 10); - - assertEq(workflows.length, 3); - assertEq(workflows[0].workflowName, s_workflowName1); - assertEq(workflows[0].workflowID, s_workflowID1); - assertEq(workflows[0].binaryURL, s_binaryURL1); - assertEq(workflows[0].configURL, s_configURL1); - assertEq(workflows[0].secretsURL, s_secretsURL1); - - assertEq(workflows[1].workflowName, s_workflowName2); - assertEq(workflows[1].workflowID, s_workflowID2); - assertEq(workflows[1].binaryURL, s_binaryURL2); - assertEq(workflows[1].configURL, s_configURL2); - assertEq(workflows[1].secretsURL, s_secretsURL2); - - assertEq(workflows[2].workflowName, s_workflowName3); - assertEq(workflows[2].workflowID, s_workflowID3); - assertEq(workflows[2].binaryURL, s_binaryURL3); - assertEq(workflows[2].configURL, s_configURL3); - assertEq(workflows[2].secretsURL, s_secretsURL3); - } } diff --git a/contracts/src/v0.8/workflow/test/WorkflowRegistry/WorkflowRegistry.getWorkflowMetadataListByDON.tree b/contracts/src/v0.8/workflow/test/WorkflowRegistry/WorkflowRegistry.getWorkflowMetadataListByDON.tree index 0fe6fab8b81..1fd6b160b51 100644 --- a/contracts/src/v0.8/workflow/test/WorkflowRegistry/WorkflowRegistry.getWorkflowMetadataListByDON.tree +++ b/contracts/src/v0.8/workflow/test/WorkflowRegistry/WorkflowRegistry.getWorkflowMetadataListByDON.tree @@ -12,7 +12,5 @@ WorkflowRegistry.getWorkflowMetadataListByDON │ └── it returns the correct metadata list ├── when the DON has no workflows │ └── it returns an empty list -├── when start is greater than or equal to total workflows -│ └── it returns an empty list -└── when the registry is locked - └── it should behave the same as when the registry is not locked +└── when start is greater than or equal to total workflows + └── it returns an empty list diff --git a/contracts/src/v0.8/workflow/test/WorkflowRegistry/WorkflowRegistry.getWorkflowMetadataListByOwner.t.sol b/contracts/src/v0.8/workflow/test/WorkflowRegistry/WorkflowRegistry.getWorkflowMetadataListByOwner.t.sol index ceeddca969b..7eea75d0a02 100644 --- a/contracts/src/v0.8/workflow/test/WorkflowRegistry/WorkflowRegistry.getWorkflowMetadataListByOwner.t.sol +++ b/contracts/src/v0.8/workflow/test/WorkflowRegistry/WorkflowRegistry.getWorkflowMetadataListByOwner.t.sol @@ -5,33 +5,24 @@ import {WorkflowRegistry} from "../../dev/WorkflowRegistry.sol"; import {WorkflowRegistryWithFixture} from "./WorkflowRegistryWithFixture.t.sol"; contract WorkflowRegistry_getWorkflowMetadataListByOwner is WorkflowRegistryWithFixture { - function test_WhenStartIs0() external view { + function test_WhenStartIs0_AndLimitIs0() external view { WorkflowRegistry.WorkflowMetadata[] memory workflows = s_registry.getWorkflowMetadataListByOwner(s_authorizedAddress, 0, 0); assertEq(workflows.length, 3); assertEq(workflows[0].workflowName, s_workflowName1); - assertEq(workflows[0].owner, s_authorizedAddress); - assertEq(workflows[0].donID, s_allowedDonID); - assertTrue(workflows[0].status == WorkflowRegistry.WorkflowStatus.ACTIVE); assertEq(workflows[0].workflowID, s_workflowID1); assertEq(workflows[0].binaryURL, s_binaryURL1); assertEq(workflows[0].configURL, s_configURL1); assertEq(workflows[0].secretsURL, s_secretsURL1); assertEq(workflows[1].workflowName, s_workflowName2); - assertEq(workflows[1].owner, s_authorizedAddress); - assertEq(workflows[1].donID, s_allowedDonID); - assertTrue(workflows[1].status == WorkflowRegistry.WorkflowStatus.ACTIVE); assertEq(workflows[1].workflowID, s_workflowID2); assertEq(workflows[1].binaryURL, s_binaryURL2); assertEq(workflows[1].configURL, s_configURL2); assertEq(workflows[1].secretsURL, s_secretsURL2); assertEq(workflows[2].workflowName, s_workflowName3); - assertEq(workflows[2].owner, s_authorizedAddress); - assertEq(workflows[2].donID, s_allowedDonID); - assertTrue(workflows[2].status == WorkflowRegistry.WorkflowStatus.ACTIVE); assertEq(workflows[2].workflowID, s_workflowID3); assertEq(workflows[2].binaryURL, s_binaryURL3); assertEq(workflows[2].configURL, s_configURL3); @@ -44,18 +35,12 @@ contract WorkflowRegistry_getWorkflowMetadataListByOwner is WorkflowRegistryWith assertEq(workflows.length, 2); assertEq(workflows[0].workflowName, s_workflowName2); - assertEq(workflows[0].owner, s_authorizedAddress); - assertEq(workflows[0].donID, s_allowedDonID); - assertTrue(workflows[0].status == WorkflowRegistry.WorkflowStatus.ACTIVE); assertEq(workflows[0].workflowID, s_workflowID2); assertEq(workflows[0].binaryURL, s_binaryURL2); assertEq(workflows[0].configURL, s_configURL2); assertEq(workflows[0].secretsURL, s_secretsURL2); assertEq(workflows[1].workflowName, s_workflowName3); - assertEq(workflows[1].owner, s_authorizedAddress); - assertEq(workflows[1].donID, s_allowedDonID); - assertTrue(workflows[1].status == WorkflowRegistry.WorkflowStatus.ACTIVE); assertEq(workflows[1].workflowID, s_workflowID3); assertEq(workflows[1].binaryURL, s_binaryURL3); assertEq(workflows[1].configURL, s_configURL3); @@ -69,18 +54,12 @@ contract WorkflowRegistry_getWorkflowMetadataListByOwner is WorkflowRegistryWith assertEq(workflows.length, 2); assertEq(workflows[0].workflowName, s_workflowName1); assertEq(workflows[0].workflowID, s_workflowID1); - assertEq(workflows[0].owner, s_authorizedAddress); - assertEq(workflows[0].donID, s_allowedDonID); - assertTrue(workflows[0].status == WorkflowRegistry.WorkflowStatus.ACTIVE); assertEq(workflows[0].binaryURL, s_binaryURL1); assertEq(workflows[0].configURL, s_configURL1); assertEq(workflows[0].secretsURL, s_secretsURL1); assertEq(workflows[1].workflowName, s_workflowName2); assertEq(workflows[1].workflowID, s_workflowID2); - assertEq(workflows[1].owner, s_authorizedAddress); - assertEq(workflows[1].donID, s_allowedDonID); - assertTrue(workflows[1].status == WorkflowRegistry.WorkflowStatus.ACTIVE); assertEq(workflows[1].binaryURL, s_binaryURL2); assertEq(workflows[1].configURL, s_configURL2); assertEq(workflows[1].secretsURL, s_secretsURL2); @@ -92,27 +71,18 @@ contract WorkflowRegistry_getWorkflowMetadataListByOwner is WorkflowRegistryWith assertEq(workflows.length, 3); assertEq(workflows[0].workflowName, s_workflowName1); - assertEq(workflows[0].owner, s_authorizedAddress); - assertEq(workflows[0].donID, s_allowedDonID); - assertTrue(workflows[0].status == WorkflowRegistry.WorkflowStatus.ACTIVE); assertEq(workflows[0].workflowID, s_workflowID1); assertEq(workflows[0].binaryURL, s_binaryURL1); assertEq(workflows[0].configURL, s_configURL1); assertEq(workflows[0].secretsURL, s_secretsURL1); assertEq(workflows[1].workflowName, s_workflowName2); - assertEq(workflows[1].owner, s_authorizedAddress); - assertEq(workflows[1].donID, s_allowedDonID); - assertTrue(workflows[1].status == WorkflowRegistry.WorkflowStatus.ACTIVE); assertEq(workflows[1].workflowID, s_workflowID2); assertEq(workflows[1].binaryURL, s_binaryURL2); assertEq(workflows[1].configURL, s_configURL2); assertEq(workflows[1].secretsURL, s_secretsURL2); assertEq(workflows[2].workflowName, s_workflowName3); - assertEq(workflows[2].owner, s_authorizedAddress); - assertEq(workflows[2].donID, s_allowedDonID); - assertTrue(workflows[2].status == WorkflowRegistry.WorkflowStatus.ACTIVE); assertEq(workflows[2].workflowID, s_workflowID3); assertEq(workflows[2].binaryURL, s_binaryURL3); assertEq(workflows[2].configURL, s_configURL3); @@ -125,27 +95,18 @@ contract WorkflowRegistry_getWorkflowMetadataListByOwner is WorkflowRegistryWith assertEq(workflows.length, 3); assertEq(workflows[0].workflowName, s_workflowName1); - assertEq(workflows[0].owner, s_authorizedAddress); - assertEq(workflows[0].donID, s_allowedDonID); - assertTrue(workflows[0].status == WorkflowRegistry.WorkflowStatus.ACTIVE); assertEq(workflows[0].workflowID, s_workflowID1); assertEq(workflows[0].binaryURL, s_binaryURL1); assertEq(workflows[0].configURL, s_configURL1); assertEq(workflows[0].secretsURL, s_secretsURL1); assertEq(workflows[1].workflowName, s_workflowName2); - assertEq(workflows[1].owner, s_authorizedAddress); - assertEq(workflows[1].donID, s_allowedDonID); - assertTrue(workflows[1].status == WorkflowRegistry.WorkflowStatus.ACTIVE); assertEq(workflows[1].workflowID, s_workflowID2); assertEq(workflows[1].binaryURL, s_binaryURL2); assertEq(workflows[1].configURL, s_configURL2); assertEq(workflows[1].secretsURL, s_secretsURL2); assertEq(workflows[2].workflowName, s_workflowName3); - assertEq(workflows[2].owner, s_authorizedAddress); - assertEq(workflows[2].donID, s_allowedDonID); - assertTrue(workflows[2].status == WorkflowRegistry.WorkflowStatus.ACTIVE); assertEq(workflows[2].workflowID, s_workflowID3); assertEq(workflows[2].binaryURL, s_binaryURL3); assertEq(workflows[2].configURL, s_configURL3); @@ -155,6 +116,7 @@ contract WorkflowRegistry_getWorkflowMetadataListByOwner is WorkflowRegistryWith function test_WhenTheOwnerHasNoWorkflows() external view { WorkflowRegistry.WorkflowMetadata[] memory workflows = s_registry.getWorkflowMetadataListByOwner(s_unauthorizedAddress, 0, 10); + assertEq(workflows.length, 0); } @@ -164,43 +126,4 @@ contract WorkflowRegistry_getWorkflowMetadataListByOwner is WorkflowRegistryWith assertEq(workflows.length, 0); } - - function test_WhenTheRegistryIsLocked() external { - // Lock the registry - vm.prank(s_owner); - s_registry.lockRegistry(); - - // It should behave the same as when the registry is not locked - vm.prank(s_stranger); - WorkflowRegistry.WorkflowMetadata[] memory workflows = - s_registry.getWorkflowMetadataListByOwner(s_authorizedAddress, 0, 0); - - assertEq(workflows.length, 3); - assertEq(workflows[0].workflowName, s_workflowName1); - assertEq(workflows[0].owner, s_authorizedAddress); - assertEq(workflows[0].donID, s_allowedDonID); - assertTrue(workflows[0].status == WorkflowRegistry.WorkflowStatus.ACTIVE); - assertEq(workflows[0].workflowID, s_workflowID1); - assertEq(workflows[0].binaryURL, s_binaryURL1); - assertEq(workflows[0].configURL, s_configURL1); - assertEq(workflows[0].secretsURL, s_secretsURL1); - - assertEq(workflows[1].workflowName, s_workflowName2); - assertEq(workflows[1].owner, s_authorizedAddress); - assertEq(workflows[1].donID, s_allowedDonID); - assertTrue(workflows[1].status == WorkflowRegistry.WorkflowStatus.ACTIVE); - assertEq(workflows[1].workflowID, s_workflowID2); - assertEq(workflows[1].binaryURL, s_binaryURL2); - assertEq(workflows[1].configURL, s_configURL2); - assertEq(workflows[1].secretsURL, s_secretsURL2); - - assertEq(workflows[2].workflowName, s_workflowName3); - assertEq(workflows[2].owner, s_authorizedAddress); - assertEq(workflows[2].donID, s_allowedDonID); - assertTrue(workflows[2].status == WorkflowRegistry.WorkflowStatus.ACTIVE); - assertEq(workflows[2].workflowID, s_workflowID3); - assertEq(workflows[2].binaryURL, s_binaryURL3); - assertEq(workflows[2].configURL, s_configURL3); - assertEq(workflows[2].secretsURL, s_secretsURL3); - } } diff --git a/contracts/src/v0.8/workflow/test/WorkflowRegistry/WorkflowRegistry.getWorkflowMetadataListByOwner.tree b/contracts/src/v0.8/workflow/test/WorkflowRegistry/WorkflowRegistry.getWorkflowMetadataListByOwner.tree index ab076425542..c2333473f39 100644 --- a/contracts/src/v0.8/workflow/test/WorkflowRegistry/WorkflowRegistry.getWorkflowMetadataListByOwner.tree +++ b/contracts/src/v0.8/workflow/test/WorkflowRegistry/WorkflowRegistry.getWorkflowMetadataListByOwner.tree @@ -2,7 +2,7 @@ WorkflowRegistry.getWorkflowMetadataListByOwner ├── when the owner has workflows │ ├── when start is 0 │ │ └── it returns the correct metadata list -│ ├── when start is greater than 0 +│ ├── when start is greater than 0 and limit exceeds total │ │ └── it returns the correct metadata list │ ├── when limit is less than total workflows │ │ └── it returns the correct metadata list @@ -12,7 +12,5 @@ WorkflowRegistry.getWorkflowMetadataListByOwner │ └── it returns the correct metadata list ├── when the owner has no workflows │ └── it returns an empty list -├── when start is greater than or equal to total workflows -│ └── it returns an empty list -└── when the registry is locked - └── it should behave the same as when the registry is not locked +└── when start is greater than or equal to total workflows + └── it returns an empty list diff --git a/contracts/src/v0.8/workflow/test/WorkflowRegistry/WorkflowRegistry.lockRegistry.t.sol b/contracts/src/v0.8/workflow/test/WorkflowRegistry/WorkflowRegistry.lockRegistry.t.sol deleted file mode 100644 index 5c93c56acee..00000000000 --- a/contracts/src/v0.8/workflow/test/WorkflowRegistry/WorkflowRegistry.lockRegistry.t.sol +++ /dev/null @@ -1,23 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity 0.8.24; - -import {Ownable2Step} from "../../../shared/access/Ownable2Step.sol"; -import {WorkflowRegistry} from "../../dev/WorkflowRegistry.sol"; -import {WorkflowRegistrySetup} from "./WorkflowRegistrySetup.t.sol"; - -contract WorkflowRegistry_lockRegistry is WorkflowRegistrySetup { - function test_RevertWhen_TheCallerIsNotTheContractOwner() external { - vm.expectRevert(Ownable2Step.OnlyCallableByOwner.selector); - s_registry.lockRegistry(); - } - - function test_WhenTheCallerIsTheContractOwner() external { - vm.expectEmit(true, true, false, false); - emit WorkflowRegistry.RegistryLockedV1(s_owner); - - vm.prank(s_owner); - s_registry.lockRegistry(); - - assertTrue(s_registry.isRegistryLocked()); - } -} diff --git a/contracts/src/v0.8/workflow/test/WorkflowRegistry/WorkflowRegistry.lockRegistry.tree b/contracts/src/v0.8/workflow/test/WorkflowRegistry/WorkflowRegistry.lockRegistry.tree deleted file mode 100644 index 8079c114e50..00000000000 --- a/contracts/src/v0.8/workflow/test/WorkflowRegistry/WorkflowRegistry.lockRegistry.tree +++ /dev/null @@ -1,6 +0,0 @@ -WorkflowRegistry.lockRegistry -├── when the caller is not the contract owner -│ └── it should revert -└── when the caller is the contract owner - ├── it should lock the registry - └── it should emit {RegistryLockedV1} diff --git a/contracts/src/v0.8/workflow/test/WorkflowRegistry/WorkflowRegistry.pauseWorkflow.t.sol b/contracts/src/v0.8/workflow/test/WorkflowRegistry/WorkflowRegistry.pauseWorkflow.t.sol index 1271808e85f..a6ef679998a 100644 --- a/contracts/src/v0.8/workflow/test/WorkflowRegistry/WorkflowRegistry.pauseWorkflow.t.sol +++ b/contracts/src/v0.8/workflow/test/WorkflowRegistry/WorkflowRegistry.pauseWorkflow.t.sol @@ -57,10 +57,6 @@ contract WorkflowRegistry_pauseWorkflow is WorkflowRegistrySetup { _removeDONFromAllowedDONs(s_allowedDonID); - // It should emit {WorkflowPausedV1} when the workflow is paused. - vm.expectEmit(); - emit WorkflowRegistry.WorkflowPausedV1(s_validWorkflowID, s_authorizedAddress, s_allowedDonID, s_validWorkflowName); - // Pause the workflow. vm.prank(s_authorizedAddress); s_registry.pauseWorkflow(s_validWorkflowKey); @@ -80,10 +76,6 @@ contract WorkflowRegistry_pauseWorkflow is WorkflowRegistrySetup { _removeAddressFromAuthorizedAddresses(s_authorizedAddress); _removeDONFromAllowedDONs(s_allowedDonID); - // It should emit {WorkflowPausedV1} when the workflow is paused. - vm.expectEmit(); - emit WorkflowRegistry.WorkflowPausedV1(s_validWorkflowID, s_authorizedAddress, s_allowedDonID, s_validWorkflowName); - // Pause the workflow. vm.prank(s_authorizedAddress); s_registry.pauseWorkflow(s_validWorkflowKey); @@ -101,10 +93,6 @@ contract WorkflowRegistry_pauseWorkflow is WorkflowRegistrySetup { _removeAddressFromAuthorizedAddresses(s_authorizedAddress); - // It should emit {WorkflowPausedV1} when the workflow is paused. - vm.expectEmit(); - emit WorkflowRegistry.WorkflowPausedV1(s_validWorkflowID, s_authorizedAddress, s_allowedDonID, s_validWorkflowName); - // Pause the workflow. vm.prank(s_authorizedAddress); s_registry.pauseWorkflow(s_validWorkflowKey); @@ -120,10 +108,6 @@ contract WorkflowRegistry_pauseWorkflow is WorkflowRegistrySetup { // Register a workflow first. _registerValidWorkflow(); - // It should emit {WorkflowPausedV1} when the workflow is paused. - vm.expectEmit(); - emit WorkflowRegistry.WorkflowPausedV1(s_validWorkflowID, s_authorizedAddress, s_allowedDonID, s_validWorkflowName); - // Pause the workflow. vm.prank(s_authorizedAddress); s_registry.pauseWorkflow(s_validWorkflowKey); diff --git a/contracts/src/v0.8/workflow/test/WorkflowRegistry/WorkflowRegistry.pauseWorkflow.tree b/contracts/src/v0.8/workflow/test/WorkflowRegistry/WorkflowRegistry.pauseWorkflow.tree index cbb75d0295c..2cd2361b702 100644 --- a/contracts/src/v0.8/workflow/test/WorkflowRegistry/WorkflowRegistry.pauseWorkflow.tree +++ b/contracts/src/v0.8/workflow/test/WorkflowRegistry/WorkflowRegistry.pauseWorkflow.tree @@ -9,8 +9,8 @@ WorkflowRegistry.pauseWorkflow │ └── it should revert └── when the workflow is active ├── when the donID is not allowed - │ ├── it should pause the workflow for an authorized address and emit {WorkflowPausedV1} - │ └── it should pause the workflow for an unauthorized address and emit {WorkflowPausedV1} + │ ├── it should pause the workflow for an authorized address + │ └── it should pause the workflow for an unauthorized address └── when the donID is allowed - ├── it should pause the workflow for an authorized address and emit {WorkflowPausedV1} - └── it should pause the workflow for an unauthorized address and emit {WorkflowPausedV1} + ├── it should pause the workflow for an authorized address + └── it should pause the workflow for an unauthorized address diff --git a/contracts/src/v0.8/workflow/test/WorkflowRegistry/WorkflowRegistry.registerWorkflow.t.sol b/contracts/src/v0.8/workflow/test/WorkflowRegistry/WorkflowRegistry.registerWorkflow.t.sol index 859437196cd..a6852b868dc 100644 --- a/contracts/src/v0.8/workflow/test/WorkflowRegistry/WorkflowRegistry.registerWorkflow.t.sol +++ b/contracts/src/v0.8/workflow/test/WorkflowRegistry/WorkflowRegistry.registerWorkflow.t.sol @@ -138,35 +138,6 @@ contract WorkflowRegistry_registerWorkflow is WorkflowRegistrySetup { ); } - // whenTheCallerIsAnAuthorizedAddress whenTheRegistryIsNotLocked whenTheDonIDIsAllowed - function test_RevertWhen_TheWorkflowIDIsAlreadyInUsedByAnotherWorkflow() external { - vm.startPrank(s_authorizedAddress); - - // Register a valid workflow first - s_registry.registerWorkflow( - s_validWorkflowName, - s_validWorkflowID, - s_allowedDonID, - WorkflowRegistry.WorkflowStatus.ACTIVE, - s_validBinaryURL, - s_validConfigURL, - s_validSecretsURL - ); - - vm.expectRevert(WorkflowRegistry.WorkflowIDAlreadyExists.selector); - s_registry.registerWorkflow( - "ValidWorkflow2", - s_validWorkflowID, - s_allowedDonID, - WorkflowRegistry.WorkflowStatus.ACTIVE, - s_validBinaryURL, - s_validConfigURL, - s_validSecretsURL - ); - - vm.stopPrank(); - } - // whenTheCallerIsAnAuthorizedAddress whenTheRegistryIsNotLocked whenTheDonIDIsAllowed function test_RevertWhen_TheWorkflowNameIsAlreadyUsedByTheOwner() external { vm.startPrank(s_authorizedAddress); @@ -202,7 +173,7 @@ contract WorkflowRegistry_registerWorkflow is WorkflowRegistrySetup { vm.startPrank(s_authorizedAddress); // it should emit {WorkflowRegisteredV1} - vm.expectEmit(); + vm.expectEmit(true, true, true, true); emit WorkflowRegistry.WorkflowRegisteredV1( s_validWorkflowID, s_authorizedAddress, diff --git a/contracts/src/v0.8/workflow/test/WorkflowRegistry/WorkflowRegistry.registerWorkflow.tree b/contracts/src/v0.8/workflow/test/WorkflowRegistry/WorkflowRegistry.registerWorkflow.tree index eabbf58d464..75cdf940575 100644 --- a/contracts/src/v0.8/workflow/test/WorkflowRegistry/WorkflowRegistry.registerWorkflow.tree +++ b/contracts/src/v0.8/workflow/test/WorkflowRegistry/WorkflowRegistry.registerWorkflow.tree @@ -18,8 +18,6 @@ WorkflowRegistry.registerWorkflow │ └── it should revert ├── when the workflowID is invalid │ └── it should revert - ├── when the workflowID is already in used by another workflow - │ └── it should revert ├── when the workflow name is already used by the owner │ └── it should revert └── when the workflow inputs are all valid diff --git a/contracts/src/v0.8/workflow/test/WorkflowRegistry/WorkflowRegistry.unlockRegistry.t.sol b/contracts/src/v0.8/workflow/test/WorkflowRegistry/WorkflowRegistry.unlockRegistry.t.sol deleted file mode 100644 index 1cb2eb6429d..00000000000 --- a/contracts/src/v0.8/workflow/test/WorkflowRegistry/WorkflowRegistry.unlockRegistry.t.sol +++ /dev/null @@ -1,30 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity 0.8.24; - -import {Ownable2Step} from "../../../shared/access/Ownable2Step.sol"; -import {WorkflowRegistry} from "../../dev/WorkflowRegistry.sol"; -import {WorkflowRegistrySetup} from "./WorkflowRegistrySetup.t.sol"; - -contract WorkflowRegistry_unlockRegistry is WorkflowRegistrySetup { - function test_RevertWhen_TheCallerIsNotTheContractOwner() external { - vm.expectRevert(Ownable2Step.OnlyCallableByOwner.selector); - s_registry.unlockRegistry(); - } - - function test_WhenTheCallerIsTheContractOwner() external { - // Lock the registry first - vm.startPrank(s_owner); - s_registry.lockRegistry(); - - assertTrue(s_registry.isRegistryLocked()); - - // Unlock the registry - vm.expectEmit(true, true, false, false); - emit WorkflowRegistry.RegistryUnlockedV1(s_owner); - - s_registry.unlockRegistry(); - - assertFalse(s_registry.isRegistryLocked()); - vm.stopPrank(); - } -} diff --git a/contracts/src/v0.8/workflow/test/WorkflowRegistry/WorkflowRegistry.unlockRegistry.tree b/contracts/src/v0.8/workflow/test/WorkflowRegistry/WorkflowRegistry.unlockRegistry.tree deleted file mode 100644 index c280b441a57..00000000000 --- a/contracts/src/v0.8/workflow/test/WorkflowRegistry/WorkflowRegistry.unlockRegistry.tree +++ /dev/null @@ -1,6 +0,0 @@ -WorkflowRegistry.unlockRegistry -├── when the caller is not the contract owner -│ └── it should revert -└── when the caller is the contract owner - ├── it should unlock the registry - └── it should emit {RegistryUnlockedV1} diff --git a/contracts/src/v0.8/workflow/test/WorkflowRegistry/WorkflowRegistry.updateAllowedDONs.t.sol b/contracts/src/v0.8/workflow/test/WorkflowRegistry/WorkflowRegistry.updateAllowedDONs.t.sol index bbf048909b5..63204fb8f96 100644 --- a/contracts/src/v0.8/workflow/test/WorkflowRegistry/WorkflowRegistry.updateAllowedDONs.t.sol +++ b/contracts/src/v0.8/workflow/test/WorkflowRegistry/WorkflowRegistry.updateAllowedDONs.t.sol @@ -7,7 +7,7 @@ import {WorkflowRegistrySetup} from "./WorkflowRegistrySetup.t.sol"; contract WorkflowRegistry_updateAllowedDONs is WorkflowRegistrySetup { function test_RevertWhen_TheCallerIsNotTheOwner() external { - vm.prank(s_stranger); + vm.prank(s_nonOwner); vm.expectRevert(Ownable2Step.OnlyCallableByOwner.selector); s_registry.updateAllowedDONs(new uint32[](0), true); @@ -36,7 +36,7 @@ contract WorkflowRegistry_updateAllowedDONs is WorkflowRegistrySetup { assertEq(allowedDONs.length, 1); // Expect the event to be emitted - vm.expectEmit(); + vm.expectEmit(true, true, true, true); emit WorkflowRegistry.AllowedDONsUpdatedV1(donIDsToAdd, true); // Call the function as the owner @@ -58,7 +58,7 @@ contract WorkflowRegistry_updateAllowedDONs is WorkflowRegistrySetup { assertEq(allowedDONs.length, 1); // Expect the event to be emitted - vm.expectEmit(); + vm.expectEmit(true, true, true, true); emit WorkflowRegistry.AllowedDONsUpdatedV1(donIDsToRemove, false); // Call the function as the owner diff --git a/contracts/src/v0.8/workflow/test/WorkflowRegistry/WorkflowRegistry.updateAuthorizedAddresses.t.sol b/contracts/src/v0.8/workflow/test/WorkflowRegistry/WorkflowRegistry.updateAuthorizedAddresses.t.sol index 01a3ded2c19..ac9e9b94bea 100644 --- a/contracts/src/v0.8/workflow/test/WorkflowRegistry/WorkflowRegistry.updateAuthorizedAddresses.t.sol +++ b/contracts/src/v0.8/workflow/test/WorkflowRegistry/WorkflowRegistry.updateAuthorizedAddresses.t.sol @@ -7,7 +7,7 @@ import {WorkflowRegistrySetup} from "./WorkflowRegistrySetup.t.sol"; contract WorkflowRegistry_updateAuthorizedAddresses is WorkflowRegistrySetup { function test_RevertWhen_TheCallerIsNotTheOwner() external { - vm.prank(s_stranger); + vm.prank(s_nonOwner); vm.expectRevert(Ownable2Step.OnlyCallableByOwner.selector); s_registry.updateAuthorizedAddresses(new address[](0), true); @@ -36,7 +36,7 @@ contract WorkflowRegistry_updateAuthorizedAddresses is WorkflowRegistrySetup { assertEq(authorizedAddresses.length, 1); // Expect the event to be emitted - vm.expectEmit(); + vm.expectEmit(true, true, true, true); emit WorkflowRegistry.AuthorizedAddressesUpdatedV1(addressesToAdd, true); // Call the function as the owner @@ -58,7 +58,7 @@ contract WorkflowRegistry_updateAuthorizedAddresses is WorkflowRegistrySetup { assertEq(authorizedAddresses.length, 1); // Expect the event to be emitted - vm.expectEmit(); + vm.expectEmit(true, true, true, true); emit WorkflowRegistry.AuthorizedAddressesUpdatedV1(addressesToRemove, false); // Call the function as the owner diff --git a/contracts/src/v0.8/workflow/test/WorkflowRegistry/WorkflowRegistry.updateWorkflow.t.sol b/contracts/src/v0.8/workflow/test/WorkflowRegistry/WorkflowRegistry.updateWorkflow.t.sol index 4082874a91e..ff59989fe93 100644 --- a/contracts/src/v0.8/workflow/test/WorkflowRegistry/WorkflowRegistry.updateWorkflow.t.sol +++ b/contracts/src/v0.8/workflow/test/WorkflowRegistry/WorkflowRegistry.updateWorkflow.t.sol @@ -7,8 +7,6 @@ import {WorkflowRegistrySetup} from "./WorkflowRegistrySetup.t.sol"; contract WorkflowRegistry_updateWorkflow is WorkflowRegistrySetup { bytes32 private s_newValidWorkflowID = keccak256("newValidWorkflowID"); string private s_newValidSecretsURL = "https://example.com/new-secrets"; - string private s_newValidConfigURL = "https://example.com/new-config"; - string private s_newValidBinaryURL = "https://example.com/new-binary"; function test_RevertWhen_TheCallerIsNotAnAuthorizedAddress() external { // Register the workflow first as an authorized address. @@ -158,32 +156,6 @@ contract WorkflowRegistry_updateWorkflow is WorkflowRegistrySetup { s_registry.updateWorkflow(s_validWorkflowKey, bytes32(0), s_validBinaryURL, s_validConfigURL, s_newValidSecretsURL); } - // whenTheCallerIsAnAuthorizedAddress whenTheRegistryIsNotLocked whenTheDonIDIsAllowed whenTheCallerIsTheWorkflowOwner - function test_RevertWhen_TheWorkflowIDIsAlreadyInUsedByAnotherWorkflow() external { - // Register a workflow first - _registerValidWorkflow(); - - // Register another workflow with another workflow ID - vm.startPrank(s_authorizedAddress); - s_registry.registerWorkflow( - "ValidWorkflow2", - s_newValidWorkflowID, - s_allowedDonID, - WorkflowRegistry.WorkflowStatus.ACTIVE, - s_validBinaryURL, - s_validConfigURL, - s_validSecretsURL - ); - - // Update the workflow with a workflow ID that is already in use by another workflow. - vm.expectRevert(WorkflowRegistry.WorkflowIDAlreadyExists.selector); - s_registry.updateWorkflow( - s_validWorkflowKey, s_newValidWorkflowID, s_validBinaryURL, s_validConfigURL, s_newValidSecretsURL - ); - - vm.stopPrank(); - } - // whenTheCallerIsAnAuthorizedAddress whenTheRegistryIsNotLocked whenTheDonIDIsAllowed whenTheCallerIsTheWorkflowOwner function test_WhenTheWorkflowInputsAreAllValid() external { // Register a workflow first. @@ -191,21 +163,21 @@ contract WorkflowRegistry_updateWorkflow is WorkflowRegistrySetup { // Update the workflow. // It should emit {WorkflowUpdatedV1}. - vm.expectEmit(); + vm.expectEmit(true, true, true, true); emit WorkflowRegistry.WorkflowUpdatedV1( s_validWorkflowID, s_authorizedAddress, s_allowedDonID, s_newValidWorkflowID, s_validWorkflowName, - s_newValidBinaryURL, - s_newValidConfigURL, + s_validBinaryURL, + s_validConfigURL, s_newValidSecretsURL ); vm.startPrank(s_authorizedAddress); s_registry.updateWorkflow( - s_validWorkflowKey, s_newValidWorkflowID, s_newValidBinaryURL, s_newValidConfigURL, s_newValidSecretsURL + s_validWorkflowKey, s_newValidWorkflowID, s_validBinaryURL, s_validConfigURL, s_newValidSecretsURL ); // It should update the workflow in s_workflows with the new values @@ -215,8 +187,8 @@ contract WorkflowRegistry_updateWorkflow is WorkflowRegistrySetup { assertEq(workflow.donID, s_allowedDonID); assertEq(workflow.workflowName, s_validWorkflowName); assertEq(workflow.workflowID, s_newValidWorkflowID); - assertEq(workflow.binaryURL, s_newValidBinaryURL); - assertEq(workflow.configURL, s_newValidConfigURL); + assertEq(workflow.binaryURL, s_validBinaryURL); + assertEq(workflow.configURL, s_validConfigURL); assertEq(workflow.secretsURL, s_newValidSecretsURL); assertTrue(workflow.status == WorkflowRegistry.WorkflowStatus.ACTIVE); diff --git a/contracts/src/v0.8/workflow/test/WorkflowRegistry/WorkflowRegistry.updateWorkflow.tree b/contracts/src/v0.8/workflow/test/WorkflowRegistry/WorkflowRegistry.updateWorkflow.tree index 9b8243a8672..0d4da7cb32e 100644 --- a/contracts/src/v0.8/workflow/test/WorkflowRegistry/WorkflowRegistry.updateWorkflow.tree +++ b/contracts/src/v0.8/workflow/test/WorkflowRegistry/WorkflowRegistry.updateWorkflow.tree @@ -25,8 +25,6 @@ WorkflowRegistry.updateWorkflow │ └── it should revert ├── when the workflowID is invalid │ └── it should revert - ├── when the workflowID is already in used by another workflow - │ └── it should revert └── when the workflow inputs are all valid ├── it should update the existing workflow in s_workflows with the new values ├── it should emit {WorkflowUpdatedV1} diff --git a/contracts/src/v0.8/workflow/test/WorkflowRegistry/WorkflowRegistrySetup.t.sol b/contracts/src/v0.8/workflow/test/WorkflowRegistry/WorkflowRegistrySetup.t.sol index b263b1cb79a..c1a44e43c8e 100644 --- a/contracts/src/v0.8/workflow/test/WorkflowRegistry/WorkflowRegistrySetup.t.sol +++ b/contracts/src/v0.8/workflow/test/WorkflowRegistry/WorkflowRegistrySetup.t.sol @@ -7,7 +7,7 @@ import {Test} from "forge-std/Test.sol"; contract WorkflowRegistrySetup is Test { WorkflowRegistry internal s_registry; address internal s_owner; - address internal s_stranger; + address internal s_nonOwner; address internal s_authorizedAddress; address internal s_unauthorizedAddress; uint32 internal s_allowedDonID; @@ -23,7 +23,7 @@ contract WorkflowRegistrySetup is Test { function setUp() public virtual { s_owner = makeAddr("owner"); - s_stranger = makeAddr("nonOwner"); + s_nonOwner = makeAddr("nonOwner"); s_authorizedAddress = makeAddr("authorizedAddress"); s_unauthorizedAddress = makeAddr("unauthorizedAddress"); s_allowedDonID = 1; diff --git a/contracts/src/v0.8/workflow/test/WorkflowRegistryManager/WorkflowRegistryManager.activateVersion.t.sol b/contracts/src/v0.8/workflow/test/WorkflowRegistryManager/WorkflowRegistryManager.activateVersion.t.sol index a4c4975c3d4..555d26e065f 100644 --- a/contracts/src/v0.8/workflow/test/WorkflowRegistryManager/WorkflowRegistryManager.activateVersion.t.sol +++ b/contracts/src/v0.8/workflow/test/WorkflowRegistryManager/WorkflowRegistryManager.activateVersion.t.sol @@ -1,92 +1,33 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.24; -import {Ownable2Step} from "../../../shared/access/Ownable2Step.sol"; -import {WorkflowRegistryManager} from "../../dev/WorkflowRegistryManager.sol"; import {WorkflowRegistryManagerSetup} from "./WorkflowRegistryManagerSetup.t.sol"; -import {Vm} from "forge-std/Vm.sol"; + +import {Ownable2Step} from "../../../shared/access/Ownable2Step.sol"; contract WorkflowRegistryManager_activateVersion is WorkflowRegistryManagerSetup { function test_RevertWhen_TheCallerIsNotTheOwner() external { // it should revert - vm.prank(s_stranger); + vm.prank(s_nonOwner); vm.expectRevert(Ownable2Step.OnlyCallableByOwner.selector); - s_registryManager.activateVersion(2); + s_registryManager.activateVersion(s_versionNumber); } // whenTheCallerIsTheOwner function test_RevertWhen_TheVersionNumberDoesNotExist() external { // it should revert - vm.prank(s_owner); - vm.expectRevert(abi.encodeWithSelector(WorkflowRegistryManager.VersionNotRegistered.selector, 5)); - s_registryManager.activateVersion(5); } // whenTheCallerIsTheOwner whenTheVersionNumberExists function test_RevertWhen_TheVersionNumberIsAlreadyActive() external { - // Deploy a mock registry and add that to the registry manager - _deployMockRegistryAndAddVersion(true); - - // Get the latest version number - uint32 versionNumber = s_registryManager.getLatestVersionNumber(); - - // Activate the same version - vm.prank(s_owner); - vm.expectRevert(abi.encodeWithSelector(WorkflowRegistryManager.VersionAlreadyActive.selector, versionNumber)); - s_registryManager.activateVersion(versionNumber); + // it should revert } - function test_WhenTheVersionNumberIsNotActive_AndWhenThereAreNoActiveVersions() external { - // Deploy a mock registry and add but not activate it. - _deployMockRegistryAndAddVersion(false); - - // Get the latest version number, which should be 1. - uint32 versionNumber = s_registryManager.getLatestVersionNumber(); - assertEq(versionNumber, 1); - - // Start recording logs to check that VersionDeactivated is not emitted. - vm.recordLogs(); - - // Since there are no existing active versions, this should only activate the version and emit VersionActivated - vm.expectEmit(true, true, false, true); - emit WorkflowRegistryManager.VersionActivated(address(s_mockWorkflowRegistryContract), s_chainID, versionNumber); - - // Activate the version - vm.prank(s_owner); - s_registryManager.activateVersion(versionNumber); - - // Retrieve the recorded logs. - Vm.Log[] memory entries = vm.getRecordedLogs(); - - // Event signature hash for WorkflowForceUpdateSecretsRequestedV1. - bytes32 eventSignature = keccak256("VersionDeactivated(string,address,string)"); - - // Iterate through the logs to ensure VersionDeactivatedV1 was not emitted. - bool deactivateEventEmitted = false; - for (uint256 i = 0; i < entries.length; ++i) { - if (entries[i].topics[0] == eventSignature) { - deactivateEventEmitted = true; - break; - } - } - - // Assert that the event was not emitted. - assertFalse(deactivateEventEmitted); - - // Deploy another mock registry. - _deployMockRegistryAndAddVersion(false); - - // Get the latest version number, which should now be 2. - uint32 newVersionNumber = s_registryManager.getLatestVersionNumber(); - assertEq(newVersionNumber, 2); - - // It should now emit both VersionActivated and VersionDeactivated. - vm.expectEmit(true, true, false, true); - emit WorkflowRegistryManager.VersionActivated(address(s_mockWorkflowRegistryContract), s_chainID, newVersionNumber); - emit WorkflowRegistryManager.VersionDeactivated(address(s_mockWorkflowRegistryContract), s_chainID, versionNumber); - - // Activate the version - vm.prank(s_owner); - s_registryManager.activateVersion(newVersionNumber); + function test_WhenTheVersionNumberIsNotActive() external { + // it should deactivate the current active version (if any) + // it should activate the specified version and update s_activeVersionNumber + // it should add the version to s_versionNumberByAddressAndChainID + // it should emit VersionDeactivatedV1 (if a previous version was active) + // it should emit VersionActivatedV1 } } diff --git a/contracts/src/v0.8/workflow/test/WorkflowRegistryManager/WorkflowRegistryManager.activateVersion.tree b/contracts/src/v0.8/workflow/test/WorkflowRegistryManager/WorkflowRegistryManager.activateVersion.tree index cee39a0db69..eb95a4e794c 100644 --- a/contracts/src/v0.8/workflow/test/WorkflowRegistryManager/WorkflowRegistryManager.activateVersion.tree +++ b/contracts/src/v0.8/workflow/test/WorkflowRegistryManager/WorkflowRegistryManager.activateVersion.tree @@ -11,5 +11,5 @@ WorkflowRegistryManager.activateVersion ├── it should deactivate the current active version (if any) ├── it should activate the specified version and update s_activeVersionNumber ├── it should add the version to s_versionNumberByAddressAndChainID - ├── it should emit VersionDeactivated (if a previous version was active) - └── it should emit VersionActivated + ├── it should emit VersionDeactivatedV1 (if a previous version was active) + └── it should emit VersionActivatedV1 diff --git a/contracts/src/v0.8/workflow/test/WorkflowRegistryManager/WorkflowRegistryManager.addVersion.t.sol b/contracts/src/v0.8/workflow/test/WorkflowRegistryManager/WorkflowRegistryManager.addVersion.t.sol index 218ac44eaa6..940b15dfd54 100644 --- a/contracts/src/v0.8/workflow/test/WorkflowRegistryManager/WorkflowRegistryManager.addVersion.t.sol +++ b/contracts/src/v0.8/workflow/test/WorkflowRegistryManager/WorkflowRegistryManager.addVersion.t.sol @@ -1,103 +1,32 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.24; -import {Ownable2Step} from "../../../shared/access/Ownable2Step.sol"; -import {WorkflowRegistryManager} from "../../dev/WorkflowRegistryManager.sol"; -import {MockContract} from "../../mocks/MockContract.sol"; -import {MockWorkflowRegistryContract} from "../../mocks/MockWorkflowRegistryContract.sol"; -import {WorkflowRegistryManagerSetup} from "./WorkflowRegistryManagerSetup.t.sol"; - -contract WorkflowRegistryManager_addVersion is WorkflowRegistryManagerSetup { +contract WorkflowRegistryManageraddVersion { function test_RevertWhen_TheCallerIsNotTheOwner() external { - // Deploy the MockWorkflowRegistryContract contract - vm.prank(s_owner); - MockWorkflowRegistryContract mockContract = new MockWorkflowRegistryContract(); - - // Add it as a non owner - vm.prank(s_stranger); - vm.expectRevert(Ownable2Step.OnlyCallableByOwner.selector); - s_registryManager.addVersion(address(mockContract), s_chainID, s_deployedAt, true); + // it should revert } - // whenTheCallerIsTheOwner - function test_RevertWhen_TheContractAddressIsInvalid() external { - // Deploy a random contract - MockContract mockContract = new MockContract(); - - // Add it to the WorkflowRegistryManager - vm.prank(s_owner); - vm.expectRevert(abi.encodeWithSelector(WorkflowRegistryManager.InvalidContractType.selector, address(mockContract))); - s_registryManager.addVersion(address(mockContract), s_chainID, s_deployedAt, true); + modifier whenTheCallerIsTheOwner() { + _; } - // whenTheCallerIsTheOwner - function test_RevertWhen_TheContractAddressIsValid() external { - // Add a 0 address to the WorkflowRegistryManager - vm.prank(s_owner); - vm.expectRevert(abi.encodeWithSelector(WorkflowRegistryManager.InvalidContractAddress.selector, address(0))); - s_registryManager.addVersion(address(0), s_chainID, s_deployedAt, true); + function test_RevertWhen_TheContractAddressIsInvalid() external whenTheCallerIsTheOwner { + // it should revert } - // whenTheCallerIsTheOwner whenTheContractAddressIsValid - function test_RevertWhen_TheContractTypeIsInvalid() external { - // Deploy a random contract - MockContract mockContract = new MockContract(); - - // Add it to the WorkflowRegistryManager - vm.prank(s_owner); - vm.expectRevert(abi.encodeWithSelector(WorkflowRegistryManager.InvalidContractType.selector, address(mockContract))); - s_registryManager.addVersion(address(mockContract), s_chainID, s_deployedAt, true); + modifier whenTheContractAddressIsValid() { + _; } - // whenTheCallerIsTheOwner whenTheContractAddressIsValid whenTheContractTypeIsValid - function test_WhenAutoActivateIsTrue() external { - // Get the latest version number, which should revert. - vm.expectRevert(WorkflowRegistryManager.NoVersionsRegistered.selector); - s_registryManager.getLatestVersionNumber(); - - // Deploy a MockWorkflowRegistryContract contract - MockWorkflowRegistryContract mockWfrContract = new MockWorkflowRegistryContract(); - - // Expect both VersionAdded and VersionActivated events to be emitted. - vm.expectEmit(true, true, false, true); - emit WorkflowRegistryManager.VersionAdded(address(mockWfrContract), s_chainID, s_deployedAt, 1); - emit WorkflowRegistryManager.VersionActivated(address(mockWfrContract), s_chainID, 1); - - // Add the MockWorkflowRegistryContract to the WorkflowRegistryManager - vm.prank(s_owner); - s_registryManager.addVersion(address(mockWfrContract), s_chainID, s_deployedAt, true); - - // Get the latest version number again, which should be 1. - uint32 versionNumber = s_registryManager.getLatestVersionNumber(); - assertEq(versionNumber, 1); - - // Get the latest active version number, which should also be 1. - uint32 activeVersionNumber = s_registryManager.getActiveVersionNumber(); - assertEq(activeVersionNumber, 1); + function test_WhenAutoActivateIsTrue() external whenTheCallerIsTheOwner whenTheContractAddressIsValid { + // it should deactivate any currently active version + // it should activate the new version + // it should emit VersionAddedV1 after adding the version to s_versions + // it should emit VersionActivatedV1 } - // whenTheCallerIsTheOwner whenTheContractAddressIsValid whenTheContractTypeIsValid - function test_WhenAutoActivateIsFalse() external { - // Get the latest version number, which should revert. - vm.expectRevert(WorkflowRegistryManager.NoVersionsRegistered.selector); - s_registryManager.getLatestVersionNumber(); - - // Deploy a MockWorkflowRegistryContract contract - MockWorkflowRegistryContract mockWfrContract = new MockWorkflowRegistryContract(); - - vm.expectEmit(true, true, false, true); - emit WorkflowRegistryManager.VersionAdded(address(mockWfrContract), s_chainID, s_deployedAt, 1); - - // Add the MockWorkflowRegistryContract to the WorkflowRegistryManager - vm.prank(s_owner); - s_registryManager.addVersion(address(mockWfrContract), s_chainID, s_deployedAt, false); - - // Get the latest version number again, which should be 1. - uint32 versionNumber = s_registryManager.getLatestVersionNumber(); - assertEq(versionNumber, 1); - - // Get the latest active version number, which should revert. - vm.expectRevert(WorkflowRegistryManager.NoActiveVersionAvailable.selector); - s_registryManager.getActiveVersionNumber(); + function test_WhenAutoActivateIsFalse() external whenTheCallerIsTheOwner whenTheContractAddressIsValid { + // it should not activate the new version + // it should emit VersionAddedV1 after adding the version to s_versions } } diff --git a/contracts/src/v0.8/workflow/test/WorkflowRegistryManager/WorkflowRegistryManager.addVersion.tree b/contracts/src/v0.8/workflow/test/WorkflowRegistryManager/WorkflowRegistryManager.addVersion.tree index 5e1c22b7840..553db81dbe0 100644 --- a/contracts/src/v0.8/workflow/test/WorkflowRegistryManager/WorkflowRegistryManager.addVersion.tree +++ b/contracts/src/v0.8/workflow/test/WorkflowRegistryManager/WorkflowRegistryManager.addVersion.tree @@ -5,14 +5,11 @@ WorkflowRegistryManager.addVersion ├── when the contract address is invalid │ └── it should revert └── when the contract address is valid - ├── when the contract type is invalid - │ └── it should revert - └── when the contract type is valid - ├── when autoActivate is true - │ ├── it should deactivate any currently active version - │ ├── it should activate the new version - │ ├── it should emit VersionAdded after adding the version to s_versions - │ └── it should emit VersionActivated - └── when autoActivate is false - ├── it should not activate the new version - └── it should emit VersionAdded after adding the version to s_versions + ├── when autoActivate is true + │ ├── it should deactivate any currently active version + │ ├── it should activate the new version + │ ├── it should emit VersionAddedV1 after adding the version to s_versions + │ └── it should emit VersionActivatedV1 + └── when autoActivate is false + ├── it should not activate the new version + └── it should emit VersionAddedV1 after adding the version to s_versions diff --git a/contracts/src/v0.8/workflow/test/WorkflowRegistryManager/WorkflowRegistryManager.getActiveVersion.t.sol b/contracts/src/v0.8/workflow/test/WorkflowRegistryManager/WorkflowRegistryManager.getActiveVersion.t.sol index 92d59346032..f20fafd5c95 100644 --- a/contracts/src/v0.8/workflow/test/WorkflowRegistryManager/WorkflowRegistryManager.getActiveVersion.t.sol +++ b/contracts/src/v0.8/workflow/test/WorkflowRegistryManager/WorkflowRegistryManager.getActiveVersion.t.sol @@ -1,20 +1,12 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.24; -import {WorkflowRegistryManager} from "../../dev/WorkflowRegistryManager.sol"; -import {WorkflowRegistryManagerSetup} from "./WorkflowRegistryManagerSetup.t.sol"; - -contract WorkflowRegistryManager_getActiveVersion is WorkflowRegistryManagerSetup { +contract WorkflowRegistryManagergetActiveVersion { function test_WhenNoActiveVersionIsAvailable() external { - vm.expectRevert(WorkflowRegistryManager.NoActiveVersionAvailable.selector); - s_registryManager.getActiveVersion(); + // it should revert with NoActiveVersionAvailable } function test_WhenAnActiveVersionExists() external { - _deployMockRegistryAndAddVersion(true); - WorkflowRegistryManager.Version memory activeVersion = s_registryManager.getActiveVersion(); - assertEq(activeVersion.contractAddress, address(s_mockWorkflowRegistryContract)); - assertEq(activeVersion.chainID, s_chainID); - assertEq(activeVersion.deployedAt, s_deployedAt); + // it should return the active version details } } diff --git a/contracts/src/v0.8/workflow/test/WorkflowRegistryManager/WorkflowRegistryManager.getActiveVersionNumber.t.sol b/contracts/src/v0.8/workflow/test/WorkflowRegistryManager/WorkflowRegistryManager.getActiveVersionNumber.t.sol deleted file mode 100644 index 4167dcc803a..00000000000 --- a/contracts/src/v0.8/workflow/test/WorkflowRegistryManager/WorkflowRegistryManager.getActiveVersionNumber.t.sol +++ /dev/null @@ -1,18 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.24; - -import {WorkflowRegistryManager} from "../../dev/WorkflowRegistryManager.sol"; -import {WorkflowRegistryManagerSetup} from "./WorkflowRegistryManagerSetup.t.sol"; - -contract WorkflowRegistryManager_getActiveVersionNumber is WorkflowRegistryManagerSetup { - function test_WhenNoActiveVersionIsAvailable() external { - vm.expectRevert(WorkflowRegistryManager.NoActiveVersionAvailable.selector); - s_registryManager.getActiveVersionNumber(); - } - - function test_WhenAnActiveVersionExists() external { - _deployMockRegistryAndAddVersion(true); - uint32 activeVersionNumber = s_registryManager.getActiveVersionNumber(); - assertEq(activeVersionNumber, 1); - } -} diff --git a/contracts/src/v0.8/workflow/test/WorkflowRegistryManager/WorkflowRegistryManager.getActiveVersionNumber.tree b/contracts/src/v0.8/workflow/test/WorkflowRegistryManager/WorkflowRegistryManager.getActiveVersionNumber.tree deleted file mode 100644 index 7f6fb062eec..00000000000 --- a/contracts/src/v0.8/workflow/test/WorkflowRegistryManager/WorkflowRegistryManager.getActiveVersionNumber.tree +++ /dev/null @@ -1,5 +0,0 @@ -WorkflowRegistryManager.getActiveVersion -├── when no active version is available -│ └── it should revert with NoActiveVersionAvailable -└── when an active version exists - └── it should return the active version number diff --git a/contracts/src/v0.8/workflow/test/WorkflowRegistryManager/WorkflowRegistryManager.getAllVersions.t.sol b/contracts/src/v0.8/workflow/test/WorkflowRegistryManager/WorkflowRegistryManager.getAllVersions.t.sol index ccdfacb474f..9719d21711a 100644 --- a/contracts/src/v0.8/workflow/test/WorkflowRegistryManager/WorkflowRegistryManager.getAllVersions.t.sol +++ b/contracts/src/v0.8/workflow/test/WorkflowRegistryManager/WorkflowRegistryManager.getAllVersions.t.sol @@ -1,50 +1,16 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.24; -import {WorkflowRegistryManager} from "../../dev/WorkflowRegistryManager.sol"; - -import {MockWorkflowRegistryContract} from "../../mocks/MockWorkflowRegistryContract.sol"; -import {WorkflowRegistryManagerSetup} from "./WorkflowRegistryManagerSetup.t.sol"; - -contract WorkflowRegistryManager_getAllVersions is WorkflowRegistryManagerSetup { - MockWorkflowRegistryContract internal s_mockContract1; - MockWorkflowRegistryContract internal s_mockContract2; - MockWorkflowRegistryContract internal s_mockContract3; - - function setUp() public override { - super.setUp(); - // Add 3 versions - s_mockContract1 = new MockWorkflowRegistryContract(); - s_mockContract2 = new MockWorkflowRegistryContract(); - s_mockContract3 = new MockWorkflowRegistryContract(); - - vm.startPrank(s_owner); - s_registryManager.addVersion(address(s_mockContract1), s_chainID, s_deployedAt, true); - s_registryManager.addVersion(address(s_mockContract2), s_chainID, s_deployedAt, false); - s_registryManager.addVersion(address(s_mockContract3), s_chainID, s_deployedAt, true); - vm.stopPrank(); - } - - function test_WhenRequestingWithInvalidStartIndex() external view { - // It should return an empty array. - WorkflowRegistryManager.Version[] memory versions = s_registryManager.getAllVersions(10, 1); - assertEq(versions.length, 0); +contract WorkflowRegistryManagergetAllVersions { + function test_WhenRequestingWithInvalidStartIndex() external { + // it should return an empty array } - function test_WhenRequestingWithValidStartIndexAndLimitWithinBounds() external view { - // It should return the correct versions based on pagination. - WorkflowRegistryManager.Version[] memory versions = s_registryManager.getAllVersions(1, 2); - assertEq(versions.length, 2); - assertEq(versions[0].contractAddress, address(s_mockContract1)); - assertEq(versions[1].contractAddress, address(s_mockContract2)); + function test_WhenRequestingWithValidStartIndexAndLimitWithinBounds() external { + // it should return the correct versions based on pagination } - function test_WhenLimitExceedsMaximumPaginationLimit() external view { + function test_WhenLimitExceedsMaximumPaginationLimit() external { // it should return results up to MAX_PAGINATION_LIMIT - WorkflowRegistryManager.Version[] memory versions = s_registryManager.getAllVersions(1, 200); - assertEq(versions.length, 3); - assertEq(versions[0].contractAddress, address(s_mockContract1)); - assertEq(versions[1].contractAddress, address(s_mockContract2)); - assertEq(versions[2].contractAddress, address(s_mockContract3)); } } diff --git a/contracts/src/v0.8/workflow/test/WorkflowRegistryManager/WorkflowRegistryManager.getLatestVersion.t.sol b/contracts/src/v0.8/workflow/test/WorkflowRegistryManager/WorkflowRegistryManager.getLatestVersion.t.sol index 9ca2347d8a6..7c38eb6f8a7 100644 --- a/contracts/src/v0.8/workflow/test/WorkflowRegistryManager/WorkflowRegistryManager.getLatestVersion.t.sol +++ b/contracts/src/v0.8/workflow/test/WorkflowRegistryManager/WorkflowRegistryManager.getLatestVersion.t.sol @@ -1,22 +1,12 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.24; -import {WorkflowRegistryManager} from "../../dev/WorkflowRegistryManager.sol"; -import {WorkflowRegistryManagerSetup} from "./WorkflowRegistryManagerSetup.t.sol"; - -contract WorkflowRegistryManager_getLatestVersion is WorkflowRegistryManagerSetup { +contract WorkflowRegistryManagergetLatestVersion { function test_WhenNoVersionsHaveBeenRegistered() external { - // it should revert with NoVersionsRegistered - vm.expectRevert(WorkflowRegistryManager.NoVersionsRegistered.selector); - s_registryManager.getLatestVersion(); + // it should revert with NoActiveVersionAvailable } function test_WhenVersionsHaveBeenRegistered() external { // it should return the latest registered version details - _deployMockRegistryAndAddVersion(true); - WorkflowRegistryManager.Version memory version = s_registryManager.getLatestVersion(); - assertEq(version.contractAddress, address(s_mockWorkflowRegistryContract)); - assertEq(version.chainID, s_chainID); - assertEq(version.deployedAt, s_deployedAt); } } diff --git a/contracts/src/v0.8/workflow/test/WorkflowRegistryManager/WorkflowRegistryManager.getLatestVersion.tree b/contracts/src/v0.8/workflow/test/WorkflowRegistryManager/WorkflowRegistryManager.getLatestVersion.tree index d5d674f3d93..42012a0962f 100644 --- a/contracts/src/v0.8/workflow/test/WorkflowRegistryManager/WorkflowRegistryManager.getLatestVersion.tree +++ b/contracts/src/v0.8/workflow/test/WorkflowRegistryManager/WorkflowRegistryManager.getLatestVersion.tree @@ -1,5 +1,5 @@ WorkflowRegistryManager.getLatestVersion ├── when no versions have been registered -│ └── it should revert with NoVersionsRegistered +│ └── it should revert with NoActiveVersionAvailable └── when versions have been registered └── it should return the latest registered version details diff --git a/contracts/src/v0.8/workflow/test/WorkflowRegistryManager/WorkflowRegistryManager.getLatestVersionNumber.t.sol b/contracts/src/v0.8/workflow/test/WorkflowRegistryManager/WorkflowRegistryManager.getLatestVersionNumber.t.sol deleted file mode 100644 index 4ac9afc6ea6..00000000000 --- a/contracts/src/v0.8/workflow/test/WorkflowRegistryManager/WorkflowRegistryManager.getLatestVersionNumber.t.sol +++ /dev/null @@ -1,18 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.24; - -import {WorkflowRegistryManager} from "../../dev/WorkflowRegistryManager.sol"; -import {WorkflowRegistryManagerSetup} from "./WorkflowRegistryManagerSetup.t.sol"; - -contract WorkflowRegistryManager_getLatestVersionNumber is WorkflowRegistryManagerSetup { - function test_WhenNoVersionsHaveBeenRegistered() external { - vm.expectRevert(WorkflowRegistryManager.NoVersionsRegistered.selector); - s_registryManager.getLatestVersionNumber(); - } - - function test_WhenVersionsHaveBeenRegistered() external { - _deployMockRegistryAndAddVersion(true); - uint32 latestVersionNumber = s_registryManager.getLatestVersionNumber(); - assertEq(latestVersionNumber, 1); - } -} diff --git a/contracts/src/v0.8/workflow/test/WorkflowRegistryManager/WorkflowRegistryManager.getLatestVersionNumber.tree b/contracts/src/v0.8/workflow/test/WorkflowRegistryManager/WorkflowRegistryManager.getLatestVersionNumber.tree deleted file mode 100644 index 6207f82f5be..00000000000 --- a/contracts/src/v0.8/workflow/test/WorkflowRegistryManager/WorkflowRegistryManager.getLatestVersionNumber.tree +++ /dev/null @@ -1,5 +0,0 @@ -WorkflowRegistryManager.getLatestVersionNumber -├── when no versions have been registered -│ └── it should revert with NoVersionsRegistered -└── when versions have been registered - └── it should return the latest registered version number diff --git a/contracts/src/v0.8/workflow/test/WorkflowRegistryManager/WorkflowRegistryManager.getVersion.t.sol b/contracts/src/v0.8/workflow/test/WorkflowRegistryManager/WorkflowRegistryManager.getVersion.t.sol index 1c8ea44408f..54b12211ca7 100644 --- a/contracts/src/v0.8/workflow/test/WorkflowRegistryManager/WorkflowRegistryManager.getVersion.t.sol +++ b/contracts/src/v0.8/workflow/test/WorkflowRegistryManager/WorkflowRegistryManager.getVersion.t.sol @@ -1,23 +1,12 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.24; -import {WorkflowRegistryManagerSetup} from "./WorkflowRegistryManagerSetup.t.sol"; -// import {MockWorkflowRegistryContract} from "../../mocks/MockWorkflowRegistryContract.sol"; -import {WorkflowRegistryManager} from "../../dev/WorkflowRegistryManager.sol"; - -contract WorkflowRegistryManager_getVersion is WorkflowRegistryManagerSetup { +contract WorkflowRegistryManagergetVersion { function test_WhenVersionNumberIsNotRegistered() external { // it should revert with VersionNotRegistered - vm.expectRevert(abi.encodeWithSelector(WorkflowRegistryManager.VersionNotRegistered.selector, 1)); - s_registryManager.getVersion(1); } function test_WhenVersionNumberIsRegistered() external { // it should return the correct version details - _deployMockRegistryAndAddVersion(true); - WorkflowRegistryManager.Version memory version = s_registryManager.getVersion(1); - assertEq(version.contractAddress, address(s_mockWorkflowRegistryContract)); - assertEq(version.chainID, s_chainID); - assertEq(version.deployedAt, s_deployedAt); } } diff --git a/contracts/src/v0.8/workflow/test/WorkflowRegistryManager/WorkflowRegistryManager.getVersionNumber.t.sol b/contracts/src/v0.8/workflow/test/WorkflowRegistryManager/WorkflowRegistryManager.getVersionNumber.t.sol new file mode 100644 index 00000000000..05ed4c43fda --- /dev/null +++ b/contracts/src/v0.8/workflow/test/WorkflowRegistryManager/WorkflowRegistryManager.getVersionNumber.t.sol @@ -0,0 +1,26 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.24; + +contract WorkflowRegistryManagergetVersionNumber { + function test_WhenTheContractAddressIsInvalid() external { + // it should revert with InvalidContractAddress + } + + modifier whenTheContractAddressIsValid() { + _; + } + + function test_WhenNoVersionIsRegisteredForTheContractAddressAndChainIDCombination() + external + whenTheContractAddressIsValid + { + // it should revert with NoVersionsRegistered + } + + function test_WhenAVersionIsRegisteredForTheContractAddressAndChainIDCombination() + external + whenTheContractAddressIsValid + { + // it should return the correct version number + } +} diff --git a/contracts/src/v0.8/workflow/test/WorkflowRegistryManager/WorkflowRegistryManager.getVersionNumberByContractAddressAndChainID.tree b/contracts/src/v0.8/workflow/test/WorkflowRegistryManager/WorkflowRegistryManager.getVersionNumber.tree similarity index 87% rename from contracts/src/v0.8/workflow/test/WorkflowRegistryManager/WorkflowRegistryManager.getVersionNumberByContractAddressAndChainID.tree rename to contracts/src/v0.8/workflow/test/WorkflowRegistryManager/WorkflowRegistryManager.getVersionNumber.tree index 09c06911ce3..361e6192724 100644 --- a/contracts/src/v0.8/workflow/test/WorkflowRegistryManager/WorkflowRegistryManager.getVersionNumberByContractAddressAndChainID.tree +++ b/contracts/src/v0.8/workflow/test/WorkflowRegistryManager/WorkflowRegistryManager.getVersionNumber.tree @@ -1,4 +1,4 @@ -WorkflowRegistryManager.getVersionNumberByContractAddressAndChainID +WorkflowRegistryManager.getVersionNumber ├── when the contractAddress is invalid │ └── it should revert with InvalidContractAddress └── when the contractAddress is valid diff --git a/contracts/src/v0.8/workflow/test/WorkflowRegistryManager/WorkflowRegistryManager.getVersionNumberByContractAddressAndChainID.t.sol b/contracts/src/v0.8/workflow/test/WorkflowRegistryManager/WorkflowRegistryManager.getVersionNumberByContractAddressAndChainID.t.sol deleted file mode 100644 index a16ad878fc8..00000000000 --- a/contracts/src/v0.8/workflow/test/WorkflowRegistryManager/WorkflowRegistryManager.getVersionNumberByContractAddressAndChainID.t.sol +++ /dev/null @@ -1,31 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.24; - -import {WorkflowRegistryManager} from "../../dev/WorkflowRegistryManager.sol"; -import {WorkflowRegistryManagerSetup} from "./WorkflowRegistryManagerSetup.t.sol"; - -contract WorkflowRegistryManager_getVersionNumberByContractAddressAndChainID is WorkflowRegistryManagerSetup { - function test_WhenTheContractAddressIsInvalid() external { - // It should revert with InvalidContractAddress - _deployMockRegistryAndAddVersion(true); - vm.expectRevert(abi.encodeWithSelector(WorkflowRegistryManager.InvalidContractAddress.selector, address(0))); - s_registryManager.getVersionNumberByContractAddressAndChainID(address(0), s_chainID); - } - - // whenTheContractAddressIsValid - function test_WhenNoVersionIsRegisteredForTheContractAddressAndChainIDCombination() external { - // It should revert with NoVersionsRegistered. - _deployMockRegistryAndAddVersion(true); - vm.expectRevert(WorkflowRegistryManager.NoVersionsRegistered.selector); - s_registryManager.getVersionNumberByContractAddressAndChainID(address(s_mockWorkflowRegistryContract), 20); - } - - // whenTheContractAddressIsValid - function test_WhenAVersionIsRegisteredForTheContractAddressAndChainIDCombination() external { - // It should return the correct version number. - _deployMockRegistryAndAddVersion(true); - uint32 versionNumber = - s_registryManager.getVersionNumberByContractAddressAndChainID(address(s_mockWorkflowRegistryContract), s_chainID); - assertEq(versionNumber, 1); - } -} diff --git a/contracts/src/v0.8/workflow/test/WorkflowRegistryManager/WorkflowRegistryManagerSetup.t.sol b/contracts/src/v0.8/workflow/test/WorkflowRegistryManager/WorkflowRegistryManagerSetup.t.sol index 4e271aa5591..c9e4a84da81 100644 --- a/contracts/src/v0.8/workflow/test/WorkflowRegistryManager/WorkflowRegistryManagerSetup.t.sol +++ b/contracts/src/v0.8/workflow/test/WorkflowRegistryManager/WorkflowRegistryManagerSetup.t.sol @@ -2,39 +2,27 @@ pragma solidity 0.8.24; import {WorkflowRegistryManager} from "../../dev/WorkflowRegistryManager.sol"; -import {MockWorkflowRegistryContract} from "../../mocks/MockWorkflowRegistryContract.sol"; import {Test} from "forge-std/Test.sol"; contract WorkflowRegistryManagerSetup is Test { WorkflowRegistryManager internal s_registryManager; - MockWorkflowRegistryContract internal s_mockWorkflowRegistryContract; address internal s_owner; - address internal s_stranger; - address internal s_invalidContractAddress; + address internal s_nonOwner; + address internal s_contractAddress; uint64 internal s_chainID; + uint32 internal s_versionNumber; uint32 internal s_deployedAt; function setUp() public virtual { s_owner = makeAddr("owner"); - s_stranger = makeAddr("nonOwner"); - s_invalidContractAddress = makeAddr("contractAddress"); + s_nonOwner = makeAddr("nonOwner"); + s_contractAddress = makeAddr("contractAddress"); s_chainID = 1; + s_versionNumber = 1; s_deployedAt = uint32(block.timestamp); // Deploy the WorkflowRegistryManager contract vm.prank(s_owner); s_registryManager = new WorkflowRegistryManager(); } - - // Helper function to deploy the MockWorkflowRegistryContract and add it to the WorkflowRegistryManager - function _deployMockRegistryAndAddVersion( - bool activate - ) internal { - // Deploy the MockWorkflowRegistryContract contract - s_mockWorkflowRegistryContract = new MockWorkflowRegistryContract(); - - // Add the MockWorkflowRegistryContract to the WorkflowRegistryManager - vm.prank(s_owner); - s_registryManager.addVersion(address(s_mockWorkflowRegistryContract), s_chainID, s_deployedAt, activate); - } } diff --git a/core/capabilities/ccip/ccip_integration_tests/ccipreader/ccipreader_test.go b/core/capabilities/ccip/ccip_integration_tests/ccipreader/ccipreader_test.go new file mode 100644 index 00000000000..150a51f93fb --- /dev/null +++ b/core/capabilities/ccip/ccip_integration_tests/ccipreader/ccipreader_test.go @@ -0,0 +1,608 @@ +package ccipreader + +import ( + "context" + "math/big" + "sort" + "testing" + "time" + + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + ethtypes "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/crypto" + "github.com/ethereum/go-ethereum/ethclient/simulated" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "go.uber.org/zap/zapcore" + "golang.org/x/exp/maps" + + cciptypes "github.com/smartcontractkit/chainlink-ccip/pkg/types/ccipocr3" + "github.com/smartcontractkit/chainlink-common/pkg/codec" + "github.com/smartcontractkit/chainlink-common/pkg/types" + "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" + + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/headtracker" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/ccip_reader_tester" + "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" + "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest" + "github.com/smartcontractkit/chainlink/v2/core/logger" + "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm" + evmtypes "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/types" + + readermocks "github.com/smartcontractkit/chainlink-ccip/mocks/pkg/contractreader" + "github.com/smartcontractkit/chainlink-ccip/pkg/consts" + "github.com/smartcontractkit/chainlink-ccip/pkg/contractreader" + ccipreaderpkg "github.com/smartcontractkit/chainlink-ccip/pkg/reader" + "github.com/smartcontractkit/chainlink-ccip/plugintypes" +) + +const ( + chainS1 = cciptypes.ChainSelector(1) + chainS2 = cciptypes.ChainSelector(2) + chainS3 = cciptypes.ChainSelector(3) + chainD = cciptypes.ChainSelector(4) +) + +func TestCCIPReader_CommitReportsGTETimestamp(t *testing.T) { + ctx := testutils.Context(t) + + cfg := evmtypes.ChainReaderConfig{ + Contracts: map[string]evmtypes.ChainContractReader{ + consts.ContractNameOffRamp: { + ContractPollingFilter: evmtypes.ContractPollingFilter{ + GenericEventNames: []string{consts.EventNameCommitReportAccepted}, + }, + ContractABI: ccip_reader_tester.CCIPReaderTesterABI, + Configs: map[string]*evmtypes.ChainReaderDefinition{ + consts.EventNameCommitReportAccepted: { + ChainSpecificName: consts.EventNameCommitReportAccepted, + ReadType: evmtypes.Event, + }, + }, + }, + }, + } + + onRampAddress := utils.RandomAddress() + s := testSetup(ctx, t, chainD, chainD, nil, cfg, map[cciptypes.ChainSelector][]types.BoundContract{ + chainS1: { + { + Address: onRampAddress.Hex(), + Name: consts.ContractNameOnRamp, + }, + }, + }) + + tokenA := common.HexToAddress("123") + const numReports = 5 + + var firstReportTs uint64 + for i := 0; i < numReports; i++ { + _, err := s.contract.EmitCommitReportAccepted(s.auth, ccip_reader_tester.OffRampCommitReport{ + PriceUpdates: ccip_reader_tester.InternalPriceUpdates{ + TokenPriceUpdates: []ccip_reader_tester.InternalTokenPriceUpdate{ + { + SourceToken: tokenA, + UsdPerToken: big.NewInt(1000), + }, + }, + GasPriceUpdates: []ccip_reader_tester.InternalGasPriceUpdate{ + { + DestChainSelector: uint64(chainD), + UsdPerUnitGas: big.NewInt(90), + }, + }, + }, + MerkleRoots: []ccip_reader_tester.InternalMerkleRoot{ + { + SourceChainSelector: uint64(chainS1), + MinSeqNr: 10, + MaxSeqNr: 20, + MerkleRoot: [32]byte{uint8(i) + 1}, //nolint:gosec // this won't overflow + OnRampAddress: common.LeftPadBytes(onRampAddress.Bytes(), 32), + }, + }, + RmnSignatures: []ccip_reader_tester.IRMNRemoteSignature{ + { + R: [32]byte{1}, + S: [32]byte{2}, + }, + { + R: [32]byte{3}, + S: [32]byte{4}, + }, + }, + }) + assert.NoError(t, err) + bh := s.sb.Commit() + b, err := s.sb.Client().BlockByHash(ctx, bh) + require.NoError(t, err) + if firstReportTs == 0 { + firstReportTs = b.Time() + } + } + + // Need to replay as sometimes the logs are not picked up by the log poller (?) + // Maybe another situation where chain reader doesn't register filters as expected. + require.NoError(t, s.lp.Replay(ctx, 1)) + + var reports []plugintypes.CommitPluginReportWithMeta + var err error + require.Eventually(t, func() bool { + reports, err = s.reader.CommitReportsGTETimestamp( + ctx, + chainD, + // Skips first report + //nolint:gosec // this won't overflow + time.Unix(int64(firstReportTs)+1, 0), + 10, + ) + require.NoError(t, err) + return len(reports) == numReports-1 + }, tests.WaitTimeout(t), 50*time.Millisecond) + + assert.Len(t, reports, numReports-1) + assert.Len(t, reports[0].Report.MerkleRoots, 1) + assert.Equal(t, chainS1, reports[0].Report.MerkleRoots[0].ChainSel) + assert.Equal(t, onRampAddress.Bytes(), []byte(reports[0].Report.MerkleRoots[0].OnRampAddress)) + assert.Equal(t, cciptypes.SeqNum(10), reports[0].Report.MerkleRoots[0].SeqNumsRange.Start()) + assert.Equal(t, cciptypes.SeqNum(20), reports[0].Report.MerkleRoots[0].SeqNumsRange.End()) + assert.Equal(t, "0x0200000000000000000000000000000000000000000000000000000000000000", + reports[0].Report.MerkleRoots[0].MerkleRoot.String()) + assert.Equal(t, tokenA.String(), string(reports[0].Report.PriceUpdates.TokenPriceUpdates[0].TokenID)) + assert.Equal(t, uint64(1000), reports[0].Report.PriceUpdates.TokenPriceUpdates[0].Price.Uint64()) + assert.Equal(t, chainD, reports[0].Report.PriceUpdates.GasPriceUpdates[0].ChainSel) + assert.Equal(t, uint64(90), reports[0].Report.PriceUpdates.GasPriceUpdates[0].GasPrice.Uint64()) +} + +func TestCCIPReader_ExecutedMessageRanges(t *testing.T) { + ctx := testutils.Context(t) + cfg := evmtypes.ChainReaderConfig{ + Contracts: map[string]evmtypes.ChainContractReader{ + consts.ContractNameOffRamp: { + ContractPollingFilter: evmtypes.ContractPollingFilter{ + GenericEventNames: []string{consts.EventNameExecutionStateChanged}, + }, + ContractABI: ccip_reader_tester.CCIPReaderTesterABI, + Configs: map[string]*evmtypes.ChainReaderDefinition{ + consts.EventNameExecutionStateChanged: { + ChainSpecificName: consts.EventNameExecutionStateChanged, + ReadType: evmtypes.Event, + EventDefinitions: &evmtypes.EventDefinitions{ + GenericTopicNames: map[string]string{ + "sourceChainSelector": consts.EventAttributeSourceChain, + "sequenceNumber": consts.EventAttributeSequenceNumber, + }, + GenericDataWordDetails: map[string]evmtypes.DataWordDetail{ + consts.EventAttributeState: { + Name: "state", + }, + }, + }, + }, + }, + }, + }, + } + + s := testSetup(ctx, t, chainD, chainD, nil, cfg, nil) + + _, err := s.contract.EmitExecutionStateChanged( + s.auth, + uint64(chainS1), + 14, + cciptypes.Bytes32{1, 0, 0, 1}, + cciptypes.Bytes32{1, 0, 0, 1, 1, 0, 0, 1}, + 1, + []byte{1, 2, 3, 4}, + big.NewInt(250_000), + ) + assert.NoError(t, err) + s.sb.Commit() + + _, err = s.contract.EmitExecutionStateChanged( + s.auth, + uint64(chainS1), + 15, + cciptypes.Bytes32{1, 0, 0, 2}, + cciptypes.Bytes32{1, 0, 0, 2, 1, 0, 0, 2}, + 1, + []byte{1, 2, 3, 4, 5}, + big.NewInt(350_000), + ) + assert.NoError(t, err) + s.sb.Commit() + + // Need to replay as sometimes the logs are not picked up by the log poller (?) + // Maybe another situation where chain reader doesn't register filters as expected. + require.NoError(t, s.lp.Replay(ctx, 1)) + + var executedRanges []cciptypes.SeqNumRange + require.Eventually(t, func() bool { + executedRanges, err = s.reader.ExecutedMessageRanges( + ctx, + chainS1, + chainD, + cciptypes.NewSeqNumRange(14, 15), + ) + require.NoError(t, err) + return len(executedRanges) == 2 + }, testutils.WaitTimeout(t), 50*time.Millisecond) + + assert.Equal(t, cciptypes.SeqNum(14), executedRanges[0].Start()) + assert.Equal(t, cciptypes.SeqNum(14), executedRanges[0].End()) + + assert.Equal(t, cciptypes.SeqNum(15), executedRanges[1].Start()) + assert.Equal(t, cciptypes.SeqNum(15), executedRanges[1].End()) +} + +func TestCCIPReader_MsgsBetweenSeqNums(t *testing.T) { + ctx := testutils.Context(t) + + cfg := evmtypes.ChainReaderConfig{ + Contracts: map[string]evmtypes.ChainContractReader{ + consts.ContractNameOnRamp: { + ContractPollingFilter: evmtypes.ContractPollingFilter{ + GenericEventNames: []string{consts.EventNameCCIPMessageSent}, + }, + ContractABI: ccip_reader_tester.CCIPReaderTesterABI, + Configs: map[string]*evmtypes.ChainReaderDefinition{ + consts.EventNameCCIPMessageSent: { + ChainSpecificName: "CCIPMessageSent", + ReadType: evmtypes.Event, + EventDefinitions: &evmtypes.EventDefinitions{ + GenericDataWordDetails: map[string]evmtypes.DataWordDetail{ + consts.EventAttributeSourceChain: {Name: "message.header.sourceChainSelector"}, + consts.EventAttributeDestChain: {Name: "message.header.destChainSelector"}, + consts.EventAttributeSequenceNumber: {Name: "message.header.sequenceNumber"}, + }, + }, + OutputModifications: codec.ModifiersConfig{ + &codec.WrapperModifierConfig{Fields: map[string]string{ + "Message.FeeTokenAmount": "Int", + "Message.FeeValueJuels": "Int", + "Message.TokenAmounts.Amount": "Int", + }}, + }, + }, + }, + }, + }, + } + + s := testSetup(ctx, t, chainS1, chainD, nil, cfg, nil) + + _, err := s.contract.EmitCCIPMessageSent(s.auth, uint64(chainD), ccip_reader_tester.InternalEVM2AnyRampMessage{ + Header: ccip_reader_tester.InternalRampMessageHeader{ + MessageId: [32]byte{1, 0, 0, 0, 0}, + SourceChainSelector: uint64(chainS1), + DestChainSelector: uint64(chainD), + SequenceNumber: 10, + }, + Sender: utils.RandomAddress(), + Data: make([]byte, 0), + Receiver: utils.RandomAddress().Bytes(), + ExtraArgs: make([]byte, 0), + FeeToken: utils.RandomAddress(), + FeeTokenAmount: big.NewInt(1), + FeeValueJuels: big.NewInt(2), + TokenAmounts: []ccip_reader_tester.InternalEVM2AnyTokenTransfer{{Amount: big.NewInt(1)}, {Amount: big.NewInt(2)}}, + }) + assert.NoError(t, err) + + _, err = s.contract.EmitCCIPMessageSent(s.auth, uint64(chainD), ccip_reader_tester.InternalEVM2AnyRampMessage{ + Header: ccip_reader_tester.InternalRampMessageHeader{ + MessageId: [32]byte{1, 0, 0, 0, 1}, + SourceChainSelector: uint64(chainS1), + DestChainSelector: uint64(chainD), + SequenceNumber: 15, + }, + Sender: utils.RandomAddress(), + Data: make([]byte, 0), + Receiver: utils.RandomAddress().Bytes(), + ExtraArgs: make([]byte, 0), + FeeToken: utils.RandomAddress(), + FeeTokenAmount: big.NewInt(3), + FeeValueJuels: big.NewInt(4), + TokenAmounts: []ccip_reader_tester.InternalEVM2AnyTokenTransfer{{Amount: big.NewInt(3)}, {Amount: big.NewInt(4)}}, + }) + assert.NoError(t, err) + + s.sb.Commit() + + // Need to replay as sometimes the logs are not picked up by the log poller (?) + // Maybe another situation where chain reader doesn't register filters as expected. + require.NoError(t, s.lp.Replay(ctx, 1)) + + var msgs []cciptypes.Message + require.Eventually(t, func() bool { + msgs, err = s.reader.MsgsBetweenSeqNums( + ctx, + chainS1, + cciptypes.NewSeqNumRange(5, 20), + ) + require.NoError(t, err) + return len(msgs) == 2 + }, tests.WaitTimeout(t), 100*time.Millisecond) + + require.Len(t, msgs, 2) + // sort to ensure ascending order of sequence numbers. + sort.Slice(msgs, func(i, j int) bool { + return msgs[i].Header.SequenceNumber < msgs[j].Header.SequenceNumber + }) + require.Equal(t, cciptypes.SeqNum(10), msgs[0].Header.SequenceNumber) + require.Equal(t, big.NewInt(1), msgs[0].FeeTokenAmount.Int) + require.Equal(t, big.NewInt(2), msgs[0].FeeValueJuels.Int) + require.Equal(t, int64(1), msgs[0].TokenAmounts[0].Amount.Int64()) + require.Equal(t, int64(2), msgs[0].TokenAmounts[1].Amount.Int64()) + + require.Equal(t, cciptypes.SeqNum(15), msgs[1].Header.SequenceNumber) + require.Equal(t, big.NewInt(3), msgs[1].FeeTokenAmount.Int) + require.Equal(t, big.NewInt(4), msgs[1].FeeValueJuels.Int) + require.Equal(t, int64(3), msgs[1].TokenAmounts[0].Amount.Int64()) + require.Equal(t, int64(4), msgs[1].TokenAmounts[1].Amount.Int64()) + + for _, msg := range msgs { + require.Equal(t, chainS1, msg.Header.SourceChainSelector) + require.Equal(t, chainD, msg.Header.DestChainSelector) + } +} + +func TestCCIPReader_NextSeqNum(t *testing.T) { + ctx := testutils.Context(t) + + onChainSeqNums := map[cciptypes.ChainSelector]cciptypes.SeqNum{ + chainS1: 10, + chainS2: 20, + chainS3: 30, + } + + cfg := evmtypes.ChainReaderConfig{ + Contracts: map[string]evmtypes.ChainContractReader{ + consts.ContractNameOffRamp: { + ContractABI: ccip_reader_tester.CCIPReaderTesterABI, + Configs: map[string]*evmtypes.ChainReaderDefinition{ + consts.MethodNameGetSourceChainConfig: { + ChainSpecificName: "getSourceChainConfig", + ReadType: evmtypes.Method, + }, + }, + }, + }, + } + + s := testSetup(ctx, t, chainD, chainD, onChainSeqNums, cfg, nil) + + seqNums, err := s.reader.NextSeqNum(ctx, []cciptypes.ChainSelector{chainS1, chainS2, chainS3}) + assert.NoError(t, err) + assert.Len(t, seqNums, 3) + assert.Equal(t, cciptypes.SeqNum(10), seqNums[0]) + assert.Equal(t, cciptypes.SeqNum(20), seqNums[1]) + assert.Equal(t, cciptypes.SeqNum(30), seqNums[2]) +} + +func TestCCIPReader_GetExpectedNextSequenceNumber(t *testing.T) { + ctx := testutils.Context(t) + + cfg := evmtypes.ChainReaderConfig{ + Contracts: map[string]evmtypes.ChainContractReader{ + consts.ContractNameOnRamp: { + ContractABI: ccip_reader_tester.CCIPReaderTesterABI, + Configs: map[string]*evmtypes.ChainReaderDefinition{ + consts.MethodNameGetExpectedNextSequenceNumber: { + ChainSpecificName: "getExpectedNextSequenceNumber", + ReadType: evmtypes.Method, + }, + }, + }, + }, + } + + s := testSetup(ctx, t, chainS1, chainD, nil, cfg, nil) + + _, err := s.contract.SetDestChainSeqNr(s.auth, uint64(chainD), 10) + require.NoError(t, err) + s.sb.Commit() + + seqNum, err := s.reader.GetExpectedNextSequenceNumber(ctx, chainS1, chainD) + require.NoError(t, err) + require.Equal(t, cciptypes.SeqNum(10)+1, seqNum) + + _, err = s.contract.SetDestChainSeqNr(s.auth, uint64(chainD), 25) + require.NoError(t, err) + s.sb.Commit() + + seqNum, err = s.reader.GetExpectedNextSequenceNumber(ctx, chainS1, chainD) + require.NoError(t, err) + require.Equal(t, cciptypes.SeqNum(25)+1, seqNum) +} + +func TestCCIPReader_Nonces(t *testing.T) { + ctx := testutils.Context(t) + var nonces = map[cciptypes.ChainSelector]map[common.Address]uint64{ + chainS1: { + utils.RandomAddress(): 10, + utils.RandomAddress(): 20, + }, + chainS2: { + utils.RandomAddress(): 30, + utils.RandomAddress(): 40, + }, + chainS3: { + utils.RandomAddress(): 50, + utils.RandomAddress(): 60, + }, + } + + cfg := evmtypes.ChainReaderConfig{ + Contracts: map[string]evmtypes.ChainContractReader{ + consts.ContractNameNonceManager: { + ContractABI: ccip_reader_tester.CCIPReaderTesterABI, + Configs: map[string]*evmtypes.ChainReaderDefinition{ + consts.MethodNameGetInboundNonce: { + ChainSpecificName: "getInboundNonce", + ReadType: evmtypes.Method, + }, + }, + }, + }, + } + + s := testSetup(ctx, t, chainD, chainD, nil, cfg, nil) + + // Add some nonces. + for chain, addrs := range nonces { + for addr, nonce := range addrs { + _, err := s.contract.SetInboundNonce(s.auth, uint64(chain), nonce, common.LeftPadBytes(addr.Bytes(), 32)) + assert.NoError(t, err) + } + } + s.sb.Commit() + + for sourceChain, addrs := range nonces { + var addrQuery []string + for addr := range addrs { + addrQuery = append(addrQuery, addr.String()) + } + addrQuery = append(addrQuery, utils.RandomAddress().String()) + + results, err := s.reader.Nonces(ctx, sourceChain, chainD, addrQuery) + assert.NoError(t, err) + assert.Len(t, results, len(addrQuery)) + for addr, nonce := range addrs { + assert.Equal(t, nonce, results[addr.String()]) + } + } +} + +func testSetup( + ctx context.Context, + t *testing.T, + readerChain, + destChain cciptypes.ChainSelector, + onChainSeqNums map[cciptypes.ChainSelector]cciptypes.SeqNum, + cfg evmtypes.ChainReaderConfig, + otherBindings map[cciptypes.ChainSelector][]types.BoundContract, +) *testSetupData { + const chainID = 1337 + + // Generate a new key pair for the simulated account + privateKey, err := crypto.GenerateKey() + assert.NoError(t, err) + // Set up the genesis account with balance + blnc, ok := big.NewInt(0).SetString("999999999999999999999999999999999999", 10) + assert.True(t, ok) + alloc := map[common.Address]ethtypes.Account{crypto.PubkeyToAddress(privateKey.PublicKey): {Balance: blnc}} + simulatedBackend := simulated.NewBackend(alloc, simulated.WithBlockGasLimit(0)) + // Create a transactor + + auth, err := bind.NewKeyedTransactorWithChainID(privateKey, big.NewInt(chainID)) + assert.NoError(t, err) + auth.GasLimit = uint64(0) + + // Deploy the contract + address, _, _, err := ccip_reader_tester.DeployCCIPReaderTester(auth, simulatedBackend.Client()) + assert.NoError(t, err) + simulatedBackend.Commit() + + // Setup contract client + contract, err := ccip_reader_tester.NewCCIPReaderTester(address, simulatedBackend.Client()) + assert.NoError(t, err) + + lggr := logger.TestLogger(t) + lggr.SetLogLevel(zapcore.ErrorLevel) + db := pgtest.NewSqlxDB(t) + lpOpts := logpoller.Opts{ + PollPeriod: time.Millisecond, + FinalityDepth: 0, + BackfillBatchSize: 10, + RpcBatchSize: 10, + KeepFinalizedBlocksDepth: 100000, + } + cl := client.NewSimulatedBackendClient(t, simulatedBackend, big.NewInt(0).SetUint64(uint64(readerChain))) + headTracker := headtracker.NewSimulatedHeadTracker(cl, lpOpts.UseFinalityTag, lpOpts.FinalityDepth) + lp := logpoller.NewLogPoller(logpoller.NewORM(big.NewInt(0).SetUint64(uint64(readerChain)), db, lggr), + cl, + lggr, + headTracker, + lpOpts, + ) + assert.NoError(t, lp.Start(ctx)) + + for sourceChain, seqNum := range onChainSeqNums { + _, err1 := contract.SetSourceChainConfig(auth, uint64(sourceChain), ccip_reader_tester.OffRampSourceChainConfig{ + IsEnabled: true, + MinSeqNr: uint64(seqNum), + OnRamp: utils.RandomAddress().Bytes(), + }) + assert.NoError(t, err1) + simulatedBackend.Commit() + scc, err1 := contract.GetSourceChainConfig(&bind.CallOpts{Context: ctx}, uint64(sourceChain)) + assert.NoError(t, err1) + assert.Equal(t, seqNum, cciptypes.SeqNum(scc.MinSeqNr)) + } + + contractNames := maps.Keys(cfg.Contracts) + assert.Len(t, contractNames, 1, "test setup assumes there is only one contract") + + cr, err := evm.NewChainReaderService(ctx, lggr, lp, headTracker, cl, cfg) + require.NoError(t, err) + + extendedCr := contractreader.NewExtendedContractReader(cr) + err = extendedCr.Bind(ctx, []types.BoundContract{ + { + Address: address.String(), + Name: contractNames[0], + }, + }) + require.NoError(t, err) + var otherCrs = make(map[cciptypes.ChainSelector]contractreader.Extended) + for chain, bindings := range otherBindings { + m := readermocks.NewMockContractReaderFacade(t) + m.EXPECT().Bind(ctx, bindings).Return(nil) + ecr := contractreader.NewExtendedContractReader(m) + err = ecr.Bind(ctx, bindings) + require.NoError(t, err) + otherCrs[chain] = ecr + } + + err = cr.Start(ctx) + require.NoError(t, err) + + contractReaders := map[cciptypes.ChainSelector]contractreader.Extended{readerChain: extendedCr} + for chain, cr := range otherCrs { + contractReaders[chain] = cr + } + contractWriters := make(map[cciptypes.ChainSelector]types.ChainWriter) + reader := ccipreaderpkg.NewCCIPReaderWithExtendedContractReaders(ctx, lggr, contractReaders, contractWriters, destChain, nil) + + t.Cleanup(func() { + require.NoError(t, cr.Close()) + require.NoError(t, lp.Close()) + require.NoError(t, db.Close()) + }) + + return &testSetupData{ + contractAddr: address, + contract: contract, + sb: simulatedBackend, + auth: auth, + lp: lp, + cl: cl, + reader: reader, + } +} + +type testSetupData struct { + contractAddr common.Address + contract *ccip_reader_tester.CCIPReaderTester + sb *simulated.Backend + auth *bind.TransactOpts + lp logpoller.LogPoller + cl client.Client + reader ccipreaderpkg.CCIPReader +} diff --git a/core/capabilities/ccip/ccip_integration_tests/integrationhelpers/integration_helpers.go b/core/capabilities/ccip/ccip_integration_tests/integrationhelpers/integration_helpers.go index 4d636af7406..13d2b8f4d5c 100644 --- a/core/capabilities/ccip/ccip_integration_tests/integrationhelpers/integration_helpers.go +++ b/core/capabilities/ccip/ccip_integration_tests/integrationhelpers/integration_helpers.go @@ -8,7 +8,6 @@ import ( "fmt" "math/big" "sort" - "strconv" "testing" "time" @@ -33,7 +32,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/headtracker" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller" - kcr "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry_1_1_0" + kcr "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest" "github.com/smartcontractkit/chainlink/v2/core/logger" @@ -138,7 +137,7 @@ func NewTestUniverse(ctx context.Context, t *testing.T, lggr logger.Logger) Test t.Cleanup(func() { require.NoError(t, lp.Close()) }) cr := NewReader(t, lp, headTracker, cl, ccAddress, configsevm.HomeChainReaderConfigRaw) - hcr := NewHomeChainReader(t, cr, ccAddress, strconv.Itoa(chainID)) + hcr := NewHomeChainReader(t, cr, ccAddress) return TestUniverse{ Transactor: transactor, Backend: backend, @@ -238,22 +237,11 @@ func (t *TestUniverse) AddCapability(p2pIDs [][32]byte) { } } -func NewHomeChainReader( - t *testing.T, - cr types.ContractReader, - ccAddress common.Address, - chainID string, -) ccipreader.HomeChain { - hcr := ccipreader.NewObservedHomeChainReader( - cr, - logger.TestLogger(t), - 50*time.Millisecond, - types.BoundContract{ - Address: ccAddress.String(), - Name: consts.ContractNameCCIPConfig, - }, - chainID, - ) +func NewHomeChainReader(t *testing.T, cr types.ContractReader, ccAddress common.Address) ccipreader.HomeChain { + hcr := ccipreader.NewHomeChainReader(cr, logger.TestLogger(t), 50*time.Millisecond, types.BoundContract{ + Address: ccAddress.String(), + Name: consts.ContractNameCCIPConfig, + }) require.NoError(t, hcr.Start(testutils.Context(t))) t.Cleanup(func() { require.NoError(t, hcr.Close()) }) diff --git a/core/capabilities/ccip/ccip_integration_tests/usdcreader/usdcreader_test.go b/core/capabilities/ccip/ccip_integration_tests/usdcreader/usdcreader_test.go index efa4f193ed9..2d5846f24af 100644 --- a/core/capabilities/ccip/ccip_integration_tests/usdcreader/usdcreader_test.go +++ b/core/capabilities/ccip/ccip_integration_tests/usdcreader/usdcreader_test.go @@ -2,7 +2,6 @@ package usdcreader import ( "context" - "encoding/binary" "math/big" "testing" "time" @@ -12,17 +11,13 @@ import ( gethtypes "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/ethclient/simulated" - "github.com/jmoiron/sqlx" + "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "go.uber.org/zap/zapcore" sel "github.com/smartcontractkit/chain-selectors" - "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller" - ubig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" - "github.com/smartcontractkit/chainlink/v2/core/utils/testutils/heavyweight" - "github.com/smartcontractkit/chainlink-ccip/pkg/contractreader" "github.com/smartcontractkit/chainlink-ccip/pkg/reader" cciptypes "github.com/smartcontractkit/chainlink-ccip/pkg/types/ccipocr3" @@ -32,6 +27,7 @@ import ( evmconfig "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/configs/evm" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/headtracker" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/usdc_reader_tester" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" @@ -41,8 +37,6 @@ import ( evmtypes "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/types" ) -const ChainID = 1337 - func Test_USDCReader_MessageHashes(t *testing.T) { finalityDepth := 5 @@ -54,7 +48,7 @@ func Test_USDCReader_MessageHashes(t *testing.T) { polygonChain := cciptypes.ChainSelector(sel.POLYGON_MAINNET.Selector) polygonDomainCCTP := reader.CCTPDestDomains[uint64(polygonChain)] - ts := testSetup(ctx, t, ethereumChain, evmconfig.USDCReaderConfig, finalityDepth, false) + ts := testSetup(ctx, t, ethereumChain, evmconfig.USDCReaderConfig, finalityDepth) usdcReader, err := reader.NewUSDCMessageReader( ctx, @@ -208,154 +202,6 @@ func Test_USDCReader_MessageHashes(t *testing.T) { } } -// Benchmark Results: -// Benchmark_MessageHashes/Small_Dataset-14 3723 272421 ns/op 126949 B/op 2508 allocs/op -// Benchmark_MessageHashes/Medium_Dataset-14 196 6164706 ns/op 1501435 B/op 20274 allocs/op -// Benchmark_MessageHashes/Large_Dataset-14 7 163930268 ns/op 37193160 B/op 463954 allocs/op -// -// Notes: -// - Small dataset processes 3,723 iterations with 126KB memory usage per iteration. -// - Medium dataset processes 196 iterations with 1.5MB memory usage per iteration. -// - Large dataset processes only 7 iterations with ~37MB memory usage per iteration. -func Benchmark_MessageHashes(b *testing.B) { - finalityDepth := 5 - - // Adding a new parameter: tokenCount - testCases := []struct { - name string - msgCount int - startNonce int64 - tokenCount int - }{ - {"Small_Dataset", 100, 1, 5}, - {"Medium_Dataset", 10_000, 1, 10}, - {"Large_Dataset", 100_000, 1, 50}, - } - - for _, tc := range testCases { - b.Run(tc.name, func(b *testing.B) { - ctx := testutils.Context(b) - sourceChain := cciptypes.ChainSelector(sel.ETHEREUM_MAINNET_OPTIMISM_1.Selector) - sourceDomainCCTP := reader.CCTPDestDomains[uint64(sourceChain)] - destChain := cciptypes.ChainSelector(sel.AVALANCHE_MAINNET.Selector) - destDomainCCTP := reader.CCTPDestDomains[uint64(destChain)] - - ts := testSetup(ctx, b, sourceChain, evmconfig.USDCReaderConfig, finalityDepth, true) - - usdcReader, err := reader.NewUSDCMessageReader( - ctx, - logger.TestLogger(b), - map[cciptypes.ChainSelector]pluginconfig.USDCCCTPTokenConfig{ - sourceChain: { - SourceMessageTransmitterAddr: ts.contractAddr.String(), - }, - }, - map[cciptypes.ChainSelector]contractreader.ContractReaderFacade{ - sourceChain: ts.reader, - }) - require.NoError(b, err) - - // Populate the database with the specified number of logs - populateDatabase(b, ts, sourceChain, sourceDomainCCTP, destDomainCCTP, tc.startNonce, tc.msgCount, finalityDepth) - - // Create a map of tokens to query for, with the specified tokenCount - tokens := make(map[reader.MessageTokenID]cciptypes.RampTokenAmount) - for i := 1; i <= tc.tokenCount; i++ { - //nolint:gosec // disable G115 - tokens[reader.NewMessageTokenID(cciptypes.SeqNum(i), 1)] = cciptypes.RampTokenAmount{ - ExtraData: reader.NewSourceTokenDataPayload(uint64(tc.startNonce)+uint64(i), sourceDomainCCTP).ToBytes(), - } - } - - b.ResetTimer() - - for i := 0; i < b.N; i++ { - hashes, err := usdcReader.MessageHashes(ctx, sourceChain, destChain, tokens) - require.NoError(b, err) - require.Len(b, hashes, tc.tokenCount) // Ensure the number of matches is as expected - } - }) - } -} - -func populateDatabase(b *testing.B, - testEnv *testSetupData, - source cciptypes.ChainSelector, - sourceDomainCCTP uint32, - destDomainCCTP uint32, - startNonce int64, - numOfMessages int, - finalityDepth int) { - ctx := testutils.Context(b) - - abi, err := usdc_reader_tester.USDCReaderTesterMetaData.GetAbi() - require.NoError(b, err) - - var logs []logpoller.Log - messageSentEventSig := abi.Events["MessageSent"].ID - require.NoError(b, err) - messageTransmitterAddress := testEnv.contractAddr - - for i := 0; i < numOfMessages; i++ { - // Create topics array with just the event signature - topics := [][]byte{ - messageSentEventSig[:], // Topic[0] is event signature - } - - // Create log entry - logs = append(logs, logpoller.Log{ - EvmChainId: ubig.New(new(big.Int).SetUint64(uint64(source))), - LogIndex: int64(i + 1), - BlockHash: utils.NewHash(), - BlockNumber: int64(i + 1), - BlockTimestamp: time.Now(), - EventSig: messageSentEventSig, - Topics: topics, - Address: messageTransmitterAddress, - TxHash: utils.NewHash(), - Data: createMessageSentLogPollerData(startNonce, i, sourceDomainCCTP, destDomainCCTP), - CreatedAt: time.Now(), - }) - } - - require.NoError(b, testEnv.orm.InsertLogs(ctx, logs)) - require.NoError(b, testEnv.orm.InsertBlock(ctx, utils.RandomHash(), int64(numOfMessages+finalityDepth), time.Now(), int64(numOfMessages+finalityDepth))) -} - -func createMessageSentLogPollerData(startNonce int64, i int, sourceDomainCCTP uint32, destDomainCCTP uint32) []byte { - nonce := int(startNonce) + i - - var buf []byte - - buf = binary.BigEndian.AppendUint32(buf, reader.CCTPMessageVersion) - - buf = binary.BigEndian.AppendUint32(buf, sourceDomainCCTP) - - buf = binary.BigEndian.AppendUint32(buf, destDomainCCTP) - // #nosec G115 - buf = binary.BigEndian.AppendUint64(buf, uint64(nonce)) - - senderBytes := [12]byte{} - buf = append(buf, senderBytes[:]...) - - var message [32]byte - copy(message[:], buf) - - data := make([]byte, 0) - - offsetBytes := make([]byte, 32) - binary.BigEndian.PutUint64(offsetBytes[24:], 32) - data = append(data, offsetBytes...) - - lengthBytes := make([]byte, 32) - binary.BigEndian.PutUint64(lengthBytes[24:], uint64(len(message))) - data = append(data, lengthBytes...) - - data = append(data, message[:]...) - return data -} - -// we might want to use batching (evm/batching or evm/batching) but might be slow func emitMessageSent(t *testing.T, testEnv *testSetupData, source, dest uint32, nonce uint64) { payload := utils.RandomBytes32() _, err := testEnv.contract.EmitMessageSent( @@ -373,18 +219,21 @@ func emitMessageSent(t *testing.T, testEnv *testSetupData, source, dest uint32, testEnv.sb.Commit() } -func testSetup(ctx context.Context, t testing.TB, readerChain cciptypes.ChainSelector, cfg evmtypes.ChainReaderConfig, depth int, useHeavyDB bool) *testSetupData { +func testSetup(ctx context.Context, t *testing.T, readerChain cciptypes.ChainSelector, cfg evmtypes.ChainReaderConfig, depth int) *testSetupData { + const chainID = 1337 + // Generate a new key pair for the simulated account privateKey, err := crypto.GenerateKey() - require.NoError(t, err) + assert.NoError(t, err) // Set up the genesis account with balance blnc, ok := big.NewInt(0).SetString("999999999999999999999999999999999999", 10) assert.True(t, ok) alloc := map[common.Address]gethtypes.Account{crypto.PubkeyToAddress(privateKey.PublicKey): {Balance: blnc}} simulatedBackend := simulated.NewBackend(alloc, simulated.WithBlockGasLimit(0)) // Create a transactor - auth, err := bind.NewKeyedTransactorWithChainID(privateKey, big.NewInt(ChainID)) - require.NoError(t, err) + + auth, err := bind.NewKeyedTransactorWithChainID(privateKey, big.NewInt(chainID)) + assert.NoError(t, err) auth.GasLimit = uint64(0) address, _, _, err := usdc_reader_tester.DeployUSDCReaderTester( @@ -399,15 +248,7 @@ func testSetup(ctx context.Context, t testing.TB, readerChain cciptypes.ChainSel lggr := logger.TestLogger(t) lggr.SetLogLevel(zapcore.ErrorLevel) - - // Parameterize database selection - var db *sqlx.DB - if useHeavyDB { - _, db = heavyweight.FullTestDBV2(t, nil) // Use heavyweight database for benchmarks - } else { - db = pgtest.NewSqlxDB(t) // Use simple in-memory DB for tests - } - + db := pgtest.NewSqlxDB(t) lpOpts := logpoller.Opts{ PollPeriod: time.Millisecond, FinalityDepth: int64(depth), @@ -417,10 +258,7 @@ func testSetup(ctx context.Context, t testing.TB, readerChain cciptypes.ChainSel } cl := client.NewSimulatedBackendClient(t, simulatedBackend, big.NewInt(0).SetUint64(uint64(readerChain))) headTracker := headtracker.NewSimulatedHeadTracker(cl, lpOpts.UseFinalityTag, lpOpts.FinalityDepth) - orm := logpoller.NewORM(big.NewInt(0).SetUint64(uint64(readerChain)), db, lggr) - - lp := logpoller.NewLogPoller( - orm, + lp := logpoller.NewLogPoller(logpoller.NewORM(big.NewInt(0).SetUint64(uint64(readerChain)), db, lggr), cl, lggr, headTracker, @@ -447,8 +285,6 @@ func testSetup(ctx context.Context, t testing.TB, readerChain cciptypes.ChainSel auth: auth, cl: cl, reader: cr, - orm: orm, - db: db, lp: lp, } } @@ -460,7 +296,5 @@ type testSetupData struct { auth *bind.TransactOpts cl client.Client reader types.ContractReader - orm logpoller.ORM - db *sqlx.DB lp logpoller.LogPoller } diff --git a/core/capabilities/ccip/ccipevm/encodingUtilsAbi.json b/core/capabilities/ccip/ccipevm/encodingUtilsAbi.json deleted file mode 100644 index 4ebb363bffe..00000000000 --- a/core/capabilities/ccip/ccipevm/encodingUtilsAbi.json +++ /dev/null @@ -1 +0,0 @@ -[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"DoNotDeploy","type":"error"},{"inputs":[{"internalType":"bytes32","name":"rmnReportVersion","type":"bytes32"},{"components":[{"internalType":"uint256","name":"destChainId","type":"uint256"},{"internalType":"uint64","name":"destChainSelector","type":"uint64"},{"internalType":"address","name":"rmnRemoteContractAddress","type":"address"},{"internalType":"address","name":"offrampAddress","type":"address"},{"internalType":"bytes32","name":"rmnHomeContractConfigDigest","type":"bytes32"},{"components":[{"internalType":"uint64","name":"sourceChainSelector","type":"uint64"},{"internalType":"bytes","name":"onRampAddress","type":"bytes"},{"internalType":"uint64","name":"minSeqNr","type":"uint64"},{"internalType":"uint64","name":"maxSeqNr","type":"uint64"},{"internalType":"bytes32","name":"merkleRoot","type":"bytes32"}],"internalType":"struct Internal.MerkleRoot[]","name":"destLaneUpdates","type":"tuple[]"}],"internalType":"struct RMNRemote.Report","name":"rmnReport","type":"tuple"}],"name":"_rmnReport","outputs":[],"stateMutability":"nonpayable","type":"function"}] \ No newline at end of file diff --git a/core/capabilities/ccip/ccipevm/rmncrypto.go b/core/capabilities/ccip/ccipevm/rmncrypto.go index 37b909dabe2..1b97f5cc3bb 100644 --- a/core/capabilities/ccip/ccipevm/rmncrypto.go +++ b/core/capabilities/ccip/ccipevm/rmncrypto.go @@ -3,7 +3,6 @@ package ccipevm import ( "bytes" "context" - _ "embed" "errors" "fmt" "math/big" @@ -19,10 +18,8 @@ import ( // encodingUtilsAbi is the ABI for the EncodingUtils contract. // Should be imported when gethwrappers are moved from ccip repo to core. -// -//go:embed encodingUtilsAbi.json -var encodingUtilsAbiRaw string - +// nolint:lll +const encodingUtilsAbiRaw = `[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"DoNotDeploy","type":"error"},{"inputs":[{"internalType":"bytes32","name":"rmnReportVersion","type":"bytes32"},{"components":[{"internalType":"uint256","name":"destChainId","type":"uint256"},{"internalType":"uint64","name":"destChainSelector","type":"uint64"},{"internalType":"address","name":"rmnRemoteContractAddress","type":"address"},{"internalType":"address","name":"offrampAddress","type":"address"},{"internalType":"bytes32","name":"rmnHomeContractConfigDigest","type":"bytes32"},{"components":[{"internalType":"uint64","name":"sourceChainSelector","type":"uint64"},{"internalType":"bytes","name":"onRampAddress","type":"bytes"},{"internalType":"uint64","name":"minSeqNr","type":"uint64"},{"internalType":"uint64","name":"maxSeqNr","type":"uint64"},{"internalType":"bytes32","name":"merkleRoot","type":"bytes32"}],"internalType":"struct Internal.MerkleRoot[]","name":"destLaneUpdates","type":"tuple[]"}],"internalType":"struct RMNRemote.Report","name":"rmnReport","type":"tuple"}],"name":"_rmnReport","outputs":[],"stateMutability":"nonpayable","type":"function"}]` const addressEncodeAbiRaw = `[{"name":"method","type":"function","inputs":[{"name": "", "type": "address"}]}]` var ( diff --git a/core/capabilities/ccip/ccipsolana/commitcodec.go b/core/capabilities/ccip/ccipsolana/commitcodec.go index 425cc7bdea8..711bb66068a 100644 --- a/core/capabilities/ccip/ccipsolana/commitcodec.go +++ b/core/capabilities/ccip/ccipsolana/commitcodec.go @@ -6,11 +6,12 @@ import ( "errors" "fmt" - agbinary "github.com/gagliardetto/binary" "github.com/gagliardetto/solana-go" + "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/ccipsolana/ccip_router" - "github.com/smartcontractkit/chainlink-ccip/chains/solana/gobindings/ccip_router" cciptypes "github.com/smartcontractkit/chainlink-ccip/pkg/types/ccipocr3" + + agbinary "github.com/gagliardetto/binary" ) // CommitPluginCodecV1 is a codec for encoding and decoding commit plugin reports. @@ -38,7 +39,7 @@ func (c *CommitPluginCodecV1) Encode(ctx context.Context, report cciptypes.Commi for _, update := range report.PriceUpdates.TokenPriceUpdates { b, err := update.Price.MarshalJSON() if err != nil { - return nil, fmt.Errorf("error marshaling token price: %w", err) + return nil, fmt.Errorf("error marshaling token price: %v", err) } if len(b) > 28 { diff --git a/core/capabilities/ccip/common/common_test.go b/core/capabilities/ccip/common/common_test.go index 156499021fa..a7484a83ad9 100644 --- a/core/capabilities/ccip/common/common_test.go +++ b/core/capabilities/ccip/common/common_test.go @@ -11,7 +11,7 @@ import ( "github.com/stretchr/testify/require" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" - kcr "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry_1_1_0" + kcr "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" ) diff --git a/core/capabilities/ccip/configs/evm/contract_reader.go b/core/capabilities/ccip/configs/evm/contract_reader.go index ca973380a04..dc0f257c713 100644 --- a/core/capabilities/ccip/configs/evm/contract_reader.go +++ b/core/capabilities/ccip/configs/evm/contract_reader.go @@ -21,7 +21,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/rmn_remote" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/router" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/aggregator_v3_interface" - kcr "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry_1_1_0" + kcr "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry" evmrelaytypes "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/types" ) @@ -89,10 +89,6 @@ var DestReaderConfig = evmrelaytypes.ChainReaderConfig{ ChainSpecificName: mustGetMethodName("getAllSourceChainConfigs", offrampABI), ReadType: evmrelaytypes.Method, }, - consts.MethodNameOffRampLatestConfigDetails: { - ChainSpecificName: mustGetMethodName("latestConfigDetails", offrampABI), - ReadType: evmrelaytypes.Method, - }, consts.EventNameCommitReportAccepted: { ChainSpecificName: mustGetEventName(consts.EventNameCommitReportAccepted, offrampABI), ReadType: evmrelaytypes.Event, @@ -183,10 +179,6 @@ var DestReaderConfig = evmrelaytypes.ChainReaderConfig{ ChainSpecificName: mustGetMethodName("getReportDigestHeader", rmnRemoteABI), ReadType: evmrelaytypes.Method, }, - consts.MethodNameGetCursedSubjects: { - ChainSpecificName: mustGetMethodName("getCursedSubjects", rmnRemoteABI), - ReadType: evmrelaytypes.Method, - }, }, }, consts.ContractNameRMNProxy: { @@ -294,23 +286,6 @@ var SourceReaderConfig = evmrelaytypes.ChainReaderConfig{ }, }, }, - consts.ContractNameRMNRemote: { - ContractABI: rmn_remote.RMNRemoteABI, - Configs: map[string]*evmrelaytypes.ChainReaderDefinition{ - consts.MethodNameGetVersionedConfig: { - ChainSpecificName: mustGetMethodName("getVersionedConfig", rmnRemoteABI), - ReadType: evmrelaytypes.Method, - }, - consts.MethodNameGetReportDigestHeader: { - ChainSpecificName: mustGetMethodName("getReportDigestHeader", rmnRemoteABI), - ReadType: evmrelaytypes.Method, - }, - consts.MethodNameGetCursedSubjects: { - ChainSpecificName: mustGetMethodName("getCursedSubjects", rmnRemoteABI), - ReadType: evmrelaytypes.Method, - }, - }, - }, }, } diff --git a/core/capabilities/ccip/delegate.go b/core/capabilities/ccip/delegate.go index 536622978f6..09e3769627e 100644 --- a/core/capabilities/ccip/delegate.go +++ b/core/capabilities/ccip/delegate.go @@ -35,7 +35,7 @@ import ( cctypes "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/types" "github.com/smartcontractkit/chainlink/v2/core/config" - kcr "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry_1_1_0" + kcr "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry" "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/job" "github.com/smartcontractkit/chainlink/v2/core/services/keystore" @@ -167,12 +167,11 @@ func (d *Delegate) ServicesForSpec(ctx context.Context, spec job.Job) (services return nil, fmt.Errorf("failed to get home chain contract reader: %w", err) } - hcr := ccipreaderpkg.NewObservedHomeChainReader( + hcr := ccipreaderpkg.NewHomeChainReader( homeChainContractReader, d.lggr.Named("HomeChainReader"), 100*time.Millisecond, ccipConfigBinding, - d.capabilityConfig.ExternalRegistry().ChainID(), ) // get the chain selector for the home chain diff --git a/core/capabilities/ccip/launcher/deployment.go b/core/capabilities/ccip/launcher/deployment.go index c2d59a19cf2..870c0409494 100644 --- a/core/capabilities/ccip/launcher/deployment.go +++ b/core/capabilities/ccip/launcher/deployment.go @@ -2,7 +2,6 @@ package launcher import ( "fmt" - mapset "github.com/deckarep/golang-set/v2" ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types" "golang.org/x/exp/maps" diff --git a/core/capabilities/ccip/launcher/diff_test.go b/core/capabilities/ccip/launcher/diff_test.go index 1c049a0e3d1..a098bf816ab 100644 --- a/core/capabilities/ccip/launcher/diff_test.go +++ b/core/capabilities/ccip/launcher/diff_test.go @@ -9,7 +9,7 @@ import ( "github.com/stretchr/testify/require" - kcr "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry_1_1_0" + kcr "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/p2pkey" "github.com/smartcontractkit/chainlink/v2/core/services/p2p/types" "github.com/smartcontractkit/chainlink/v2/core/services/registrysyncer" diff --git a/core/capabilities/ccip/launcher/launcher.go b/core/capabilities/ccip/launcher/launcher.go index 5e4aef934a0..76a6c204058 100644 --- a/core/capabilities/ccip/launcher/launcher.go +++ b/core/capabilities/ccip/launcher/launcher.go @@ -23,7 +23,7 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/services" - kcr "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry_1_1_0" + kcr "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry" ) var ( @@ -294,6 +294,7 @@ func (l *launcher) processRemoved(removed map[registrysyncer.DonID]registrysynce if err := p.CloseAll(); err != nil { return fmt.Errorf("failed to shutdown oracles for CCIP DON %d: %w", id, err) + } // after a successful shutdown we can safely remove the DON deployment from the map. diff --git a/core/capabilities/ccip/ocrimpls/contract_transmitter.go b/core/capabilities/ccip/ocrimpls/contract_transmitter.go index 478bdaed3ad..d3ca35bbe83 100644 --- a/core/capabilities/ccip/ocrimpls/contract_transmitter.go +++ b/core/capabilities/ccip/ocrimpls/contract_transmitter.go @@ -7,93 +7,56 @@ import ( "math/big" "github.com/google/uuid" - "github.com/smartcontractkit/libocr/offchainreporting2/chains/evmutil" "github.com/smartcontractkit/libocr/offchainreporting2plus/ocr3types" ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types" "github.com/smartcontractkit/chainlink-ccip/pkg/consts" - "github.com/smartcontractkit/chainlink-ccip/pkg/types/ccipocr3" commontypes "github.com/smartcontractkit/chainlink-common/pkg/types" - "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/ocr2key" ) -type ToCalldataFunc func( - rawReportCtx [2][32]byte, - report ocr3types.ReportWithInfo[[]byte], - rs, ss [][32]byte, - vs [32]byte, -) (any, error) - -func ToCommitCalldata( - rawReportCtx [2][32]byte, - report ocr3types.ReportWithInfo[[]byte], - rs, ss [][32]byte, - vs [32]byte, -) (any, error) { +type ToCalldataFunc func(rawReportCtx [3][32]byte, report []byte, rs, ss [][32]byte, vs [32]byte) any + +func ToCommitCalldata(rawReportCtx [3][32]byte, report []byte, rs, ss [][32]byte, vs [32]byte) any { // Note that the name of the struct field is very important, since the encoder used // by the chainwriter uses mapstructure, which will use the struct field name to map // to the argument name in the function call. // If, for whatever reason, we want to change the field name, make sure to add a `mapstructure:""` tag // for that field. - - // WARNING: Be careful if you change the data types. - // Using a different type e.g. `type Foo [32]byte` instead of `[32]byte` - // will trigger undefined chainWriter behavior, e.g. transactions submitted with wrong arguments. return struct { - ReportContext [2][32]byte + ReportContext [3][32]byte Report []byte Rs [][32]byte Ss [][32]byte RawVs [32]byte }{ ReportContext: rawReportCtx, - Report: report.Report, + Report: report, Rs: rs, Ss: ss, RawVs: vs, - }, nil + } } -func ToExecCalldata( - rawReportCtx [2][32]byte, - report ocr3types.ReportWithInfo[[]byte], - _, _ [][32]byte, - _ [32]byte, -) (any, error) { +func ToExecCalldata(rawReportCtx [3][32]byte, report []byte, _, _ [][32]byte, _ [32]byte) any { // Note that the name of the struct field is very important, since the encoder used // by the chainwriter uses mapstructure, which will use the struct field name to map // to the argument name in the function call. // If, for whatever reason, we want to change the field name, make sure to add a `mapstructure:""` tag // for that field. - - // WARNING: Be careful if you change the data types. - // Using a different type e.g. `type Foo [32]byte` instead of `[32]byte` - // will trigger undefined chainWriter behavior, e.g. transactions submitted with wrong arguments. - var info ccipocr3.ExecuteReportInfo - if len(report.Info) != 0 { - var err error - info, err = ccipocr3.DecodeExecuteReportInfo(report.Info) - if err != nil { - return nil, err - } - } - return struct { - ReportContext [2][32]byte + ReportContext [3][32]byte Report []byte - Info ccipocr3.ExecuteReportInfo }{ ReportContext: rawReportCtx, - Report: report.Report, - Info: info, - }, nil + Report: report, + } } -var _ ocr3types.ContractTransmitter[[]byte] = &commitTransmitter{} +var _ ocr3types.ContractTransmitter[[]byte] = &commitTransmitter[[]byte]{} -type commitTransmitter struct { - cw commontypes.ContractWriter +type commitTransmitter[RI any] struct { + cw commontypes.ChainWriter fromAccount ocrtypes.Account contractName string method string @@ -101,15 +64,15 @@ type commitTransmitter struct { toCalldataFn ToCalldataFunc } -func XXXNewContractTransmitterTestsOnly( - cw commontypes.ContractWriter, +func XXXNewContractTransmitterTestsOnly[RI any]( + cw commontypes.ChainWriter, fromAccount ocrtypes.Account, contractName string, method string, offrampAddress string, toCalldataFn ToCalldataFunc, -) ocr3types.ContractTransmitter[[]byte] { - return &commitTransmitter{ +) ocr3types.ContractTransmitter[RI] { + return &commitTransmitter[RI]{ cw: cw, fromAccount: fromAccount, contractName: contractName, @@ -119,12 +82,12 @@ func XXXNewContractTransmitterTestsOnly( } } -func NewCommitContractTransmitter( - cw commontypes.ContractWriter, +func NewCommitContractTransmitter[RI any]( + cw commontypes.ChainWriter, fromAccount ocrtypes.Account, offrampAddress string, -) ocr3types.ContractTransmitter[[]byte] { - return &commitTransmitter{ +) ocr3types.ContractTransmitter[RI] { + return &commitTransmitter[RI]{ cw: cw, fromAccount: fromAccount, contractName: consts.ContractNameOffRamp, @@ -134,12 +97,12 @@ func NewCommitContractTransmitter( } } -func NewExecContractTransmitter( - cw commontypes.ContractWriter, +func NewExecContractTransmitter[RI any]( + cw commontypes.ChainWriter, fromAccount ocrtypes.Account, offrampAddress string, -) ocr3types.ContractTransmitter[[]byte] { - return &commitTransmitter{ +) ocr3types.ContractTransmitter[RI] { + return &commitTransmitter[RI]{ cw: cw, fromAccount: fromAccount, contractName: consts.ContractNameOffRamp, @@ -150,16 +113,16 @@ func NewExecContractTransmitter( } // FromAccount implements ocr3types.ContractTransmitter. -func (c *commitTransmitter) FromAccount(context.Context) (ocrtypes.Account, error) { +func (c *commitTransmitter[RI]) FromAccount(context.Context) (ocrtypes.Account, error) { return c.fromAccount, nil } // Transmit implements ocr3types.ContractTransmitter. -func (c *commitTransmitter) Transmit( +func (c *commitTransmitter[RI]) Transmit( ctx context.Context, configDigest ocrtypes.ConfigDigest, seqNr uint64, - reportWithInfo ocr3types.ReportWithInfo[[]byte], + reportWithInfo ocr3types.ReportWithInfo[RI], sigs []ocrtypes.AttributedOnchainSignature, ) error { var rs [][32]byte @@ -181,17 +144,29 @@ func (c *commitTransmitter) Transmit( // report ctx for OCR3 consists of the following // reportContext[0]: ConfigDigest // reportContext[1]: 24 byte padding, 8 byte sequence number - rawReportCtx := ocr2key.RawReportContext3(configDigest, seqNr) + // reportContext[2]: unused + // convert seqNum, which is a uint64, into a uint32 epoch and uint8 round + // while this does truncate the sequence number, it is not a problem because + // it still gives us 2^40 - 1 possible sequence numbers. + // assuming a sequence number is generated every second, this gives us + // 1099511627775 seconds, or approximately 34,865 years, before we run out + // of sequence numbers. + epoch, round := uint64ToUint32AndUint8(seqNr) + rawReportCtx := evmutil.RawReportContext(ocrtypes.ReportContext{ + ReportTimestamp: ocrtypes.ReportTimestamp{ + ConfigDigest: configDigest, + Epoch: epoch, + Round: round, + }, + // ExtraData not used in OCR3 + }) if c.toCalldataFn == nil { return errors.New("toCalldataFn is nil") } // chain writer takes in the raw calldata and packs it on its own. - args, err := c.toCalldataFn(rawReportCtx, reportWithInfo, rs, ss, vs) - if err != nil { - return fmt.Errorf("failed to generate call data: %w", err) - } + args := c.toCalldataFn(rawReportCtx, reportWithInfo.Report, rs, ss, vs) // TODO: no meta fields yet, what should we add? // probably whats in the info part of the report? @@ -207,3 +182,7 @@ func (c *commitTransmitter) Transmit( return nil } + +func uint64ToUint32AndUint8(x uint64) (uint32, uint8) { + return uint32(x >> 32), uint8(x) +} diff --git a/core/capabilities/ccip/ocrimpls/contract_transmitter_test.go b/core/capabilities/ccip/ocrimpls/contract_transmitter_test.go index 5e237ccbee0..d9979a02e40 100644 --- a/core/capabilities/ccip/ocrimpls/contract_transmitter_test.go +++ b/core/capabilities/ccip/ocrimpls/contract_transmitter_test.go @@ -103,7 +103,7 @@ func testTransmitter( report []byte, ) { ctx := tests.Context(t) - uni := newTestUniverse(t, nil) + uni := newTestUniverse[[]byte](t, nil) c, err := uni.wrapper.LatestConfigDetails(nil, pluginType) require.NoError(t, err, "failed to get latest config details") @@ -159,12 +159,12 @@ func testTransmitter( // wait for receipt to be written to the db require.Eventually(t, func() bool { - uni.backend.Commit() - var count uint32 - err := uni.db.GetContext(testutils.Context(t), &count, `SELECT count(*) as cnt FROM evm.receipts LIMIT 1`) - require.NoError(t, err) - if count == 1 { - t.Log("tx receipt found in db") + rows, err := uni.db.QueryContext(testutils.Context(t), `SELECT count(*) as cnt FROM evm.receipts LIMIT 1`) + require.NoError(t, err, "failed to query receipts") + defer rows.Close() + var count int + for rows.Next() { + require.NoError(t, rows.Scan(&count), "failed to scan") } return count == 1 }, testutils.WaitTimeout(t), 2*time.Second) @@ -199,7 +199,7 @@ type keyringsAndSigners[RI any] struct { signers []common.Address } -func newTestUniverse(t *testing.T, ks *keyringsAndSigners[[]byte]) *testUniverse[[]byte] { +func newTestUniverse[RI any](t *testing.T, ks *keyringsAndSigners[RI]) *testUniverse[RI] { t.Helper() db := pgtest.NewSqlxDB(t) @@ -233,7 +233,7 @@ func newTestUniverse(t *testing.T, ks *keyringsAndSigners[[]byte]) *testUniverse // create the oracle identities for setConfig // need to create at least 4 identities otherwise setConfig will fail var ( - keyrings []ocr3types.OnchainKeyring[[]byte] + keyrings []ocr3types.OnchainKeyring[RI] signers []common.Address ) if ks != nil { @@ -243,7 +243,7 @@ func newTestUniverse(t *testing.T, ks *keyringsAndSigners[[]byte]) *testUniverse for i := 0; i < 4; i++ { kb, err2 := ocr2key.New(kschaintype.EVM) require.NoError(t, err2, "failed to create key") - kr := ocrimpls.NewOnchainKeyring[[]byte](kb, logger.TestLogger(t)) + kr := ocrimpls.NewOnchainKeyring[RI](kb, logger.TestLogger(t)) signers = append(signers, common.BytesToAddress(kr.PublicKey())) keyrings = append(keyrings, kr) } @@ -309,7 +309,7 @@ func newTestUniverse(t *testing.T, ks *keyringsAndSigners[[]byte]) *testUniverse require.NoError(t, chainWriter.Start(testutils.Context(t)), "failed to start chain writer") t.Cleanup(func() { require.NoError(t, chainWriter.Close()) }) - transmitterWithSigs := ocrimpls.XXXNewContractTransmitterTestsOnly( + transmitterWithSigs := ocrimpls.XXXNewContractTransmitterTestsOnly[RI]( chainWriter, ocrtypes.Account(transmitters[0].Hex()), contractName, @@ -317,7 +317,7 @@ func newTestUniverse(t *testing.T, ks *keyringsAndSigners[[]byte]) *testUniverse ocr3HelperAddr.Hex(), ocrimpls.ToCommitCalldata, ) - transmitterWithoutSigs := ocrimpls.XXXNewContractTransmitterTestsOnly( + transmitterWithoutSigs := ocrimpls.XXXNewContractTransmitterTestsOnly[RI]( chainWriter, ocrtypes.Account(transmitters[0].Hex()), contractName, @@ -326,7 +326,7 @@ func newTestUniverse(t *testing.T, ks *keyringsAndSigners[[]byte]) *testUniverse ocrimpls.ToExecCalldata, ) - return &testUniverse[[]byte]{ + return &testUniverse[RI]{ simClient: simClient, backend: backend, deployer: owner, diff --git a/core/capabilities/ccip/ocrimpls/keyring.go b/core/capabilities/ccip/ocrimpls/keyring.go index cd753810341..4b15c75b09a 100644 --- a/core/capabilities/ccip/ocrimpls/keyring.go +++ b/core/capabilities/ccip/ocrimpls/keyring.go @@ -6,26 +6,16 @@ import ( "github.com/smartcontractkit/libocr/offchainreporting2plus/types" "github.com/smartcontractkit/chainlink/v2/core/logger" - "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/ocr2key" ) -// OCR3SignerVerifierExtra is an extension of OCR3SignerVerifier that -// also exposes the public key and max signature length which are required by the ocr3Keyring adapter. -type OCR3SignerVerifierExtra interface { - ocr2key.OCR3SignerVerifier - PublicKey() types.OnchainPublicKey - MaxSignatureLength() int -} - var _ ocr3types.OnchainKeyring[[]byte] = &ocr3Keyring[[]byte]{} -// ocr3Keyring is an adapter that exposes ocr3 onchain keyring. type ocr3Keyring[RI any] struct { - core OCR3SignerVerifierExtra + core types.OnchainKeyring lggr logger.Logger } -func NewOnchainKeyring[RI any](keyring OCR3SignerVerifierExtra, lggr logger.Logger) *ocr3Keyring[RI] { +func NewOnchainKeyring[RI any](keyring types.OnchainKeyring, lggr logger.Logger) *ocr3Keyring[RI] { return &ocr3Keyring[RI]{ core: keyring, lggr: lggr.Named("OCR3Keyring"), @@ -41,20 +31,31 @@ func (w *ocr3Keyring[RI]) MaxSignatureLength() int { } func (w *ocr3Keyring[RI]) Sign(configDigest types.ConfigDigest, seqNr uint64, r ocr3types.ReportWithInfo[RI]) (signature []byte, err error) { - w.lggr.Debugw( - "signing report", - "configDigest", configDigest.Hex(), - "seqNr", seqNr, - "report", hexutil.Encode(r.Report), - ) - return w.core.Sign3(configDigest, seqNr, r.Report) + epoch, round := uint64ToUint32AndUint8(seqNr) + rCtx := types.ReportContext{ + ReportTimestamp: types.ReportTimestamp{ + ConfigDigest: configDigest, + Epoch: epoch, + Round: round, + }, + } + + w.lggr.Debugw("signing report", "configDigest", configDigest.Hex(), "seqNr", seqNr, "report", hexutil.Encode(r.Report)) + + return w.core.Sign(rCtx, r.Report) } func (w *ocr3Keyring[RI]) Verify(key types.OnchainPublicKey, configDigest types.ConfigDigest, seqNr uint64, r ocr3types.ReportWithInfo[RI], signature []byte) bool { - w.lggr.Debugw("verifying report", - "configDigest", configDigest.Hex(), - "seqNr", seqNr, - "report", hexutil.Encode(r.Report), - ) - return w.core.Verify3(key, configDigest, seqNr, r.Report, signature) + epoch, round := uint64ToUint32AndUint8(seqNr) + rCtx := types.ReportContext{ + ReportTimestamp: types.ReportTimestamp{ + ConfigDigest: configDigest, + Epoch: epoch, + Round: round, + }, + } + + w.lggr.Debugw("verifying report", "configDigest", configDigest.Hex(), "seqNr", seqNr, "report", hexutil.Encode(r.Report)) + + return w.core.Verify(key, rCtx, r.Report, signature) } diff --git a/core/capabilities/ccip/oraclecreator/bootstrap.go b/core/capabilities/ccip/oraclecreator/bootstrap.go index 8dfe3e99ffb..632ac789c8e 100644 --- a/core/capabilities/ccip/oraclecreator/bootstrap.go +++ b/core/capabilities/ccip/oraclecreator/bootstrap.go @@ -27,9 +27,8 @@ import ( ccipreaderpkg "github.com/smartcontractkit/chainlink-ccip/pkg/reader" cciptypes "github.com/smartcontractkit/chainlink-ccip/pkg/types/ccipocr3" - "github.com/smartcontractkit/chainlink-common/pkg/types" - "github.com/smartcontractkit/chainlink-ccip/pkg/peergroup" + "github.com/smartcontractkit/chainlink-common/pkg/types" "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/ocrimpls" cctypes "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/types" diff --git a/core/capabilities/ccip/oraclecreator/plugin.go b/core/capabilities/ccip/oraclecreator/plugin.go index d4c5596aeaf..573d1dd0cac 100644 --- a/core/capabilities/ccip/oraclecreator/plugin.go +++ b/core/capabilities/ccip/oraclecreator/plugin.go @@ -22,7 +22,6 @@ import ( cctypes "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/types" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/toml" - "github.com/smartcontractkit/chainlink/v2/core/services/ocr3/promwrapper" "github.com/smartcontractkit/libocr/commontypes" libocr3 "github.com/smartcontractkit/libocr/offchainreporting2plus" @@ -44,6 +43,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/services/job" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/ocr2key" "github.com/smartcontractkit/chainlink/v2/core/services/ocrcommon" + "github.com/smartcontractkit/chainlink/v2/core/services/relay" evmrelaytypes "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/types" "github.com/smartcontractkit/chainlink/v2/core/services/synchronization" "github.com/smartcontractkit/chainlink/v2/core/services/telemetry" @@ -117,17 +117,15 @@ func (i *pluginOracleCreator) Type() cctypes.OracleType { // Create implements types.OracleCreator. func (i *pluginOracleCreator) Create(ctx context.Context, donID uint32, config cctypes.OCR3ConfigWithMeta) (cctypes.CCIPOracle, error) { pluginType := cctypes.PluginType(config.Config.PluginType) - chainSelector := uint64(config.Config.ChainSelector) - destChainFamily, err := chainsel.GetSelectorFamily(chainSelector) - if err != nil { - return nil, fmt.Errorf("failed to get chain family from selector %d: %w", config.Config.ChainSelector, err) - } - destChainID, err := chainsel.GetChainIDFromSelector(chainSelector) + // Assuming that the chain selector is referring to an evm chain for now. + // TODO: add an api that returns chain family. + destChainID, err := chainsel.ChainIdFromSelector(uint64(config.Config.ChainSelector)) if err != nil { - return nil, fmt.Errorf("failed to get chain ID from selector %d: %w", chainSelector, err) + return nil, fmt.Errorf("failed to get chain ID from selector %d: %w", config.Config.ChainSelector, err) } - destRelayID := types.NewRelayID(destChainFamily, destChainID) + destChainFamily := relay.NetworkEVM + destRelayID := types.NewRelayID(destChainFamily, fmt.Sprintf("%d", destChainID)) configTracker := ocrimpls.NewConfigTracker(config) publicConfig, err := configTracker.PublicConfig() @@ -141,7 +139,6 @@ func (i *pluginOracleCreator) Create(ctx context.Context, donID uint32, config c pluginType, config, publicConfig, - destChainFamily, ) if err != nil { return nil, fmt.Errorf("failed to create readers and writers: %w", err) @@ -223,19 +220,13 @@ func (i *pluginOracleCreator) createFactoryAndTransmitter( config cctypes.OCR3ConfigWithMeta, destRelayID types.RelayID, contractReaders map[cciptypes.ChainSelector]types.ContractReader, - chainWriters map[cciptypes.ChainSelector]types.ContractWriter, - destChainWriter types.ContractWriter, + chainWriters map[cciptypes.ChainSelector]types.ChainWriter, + destChainWriter types.ChainWriter, destFromAccounts []string, publicConfig ocr3confighelper.PublicConfig, ) (ocr3types.ReportingPluginFactory[[]byte], ocr3types.ContractTransmitter[[]byte], error) { var factory ocr3types.ReportingPluginFactory[[]byte] var transmitter ocr3types.ContractTransmitter[[]byte] - - chainID, err := chainsel.GetChainIDFromSelector(uint64(config.Config.ChainSelector)) - if err != nil { - return nil, nil, fmt.Errorf("unsupported chain selector %d %w", config.Config.ChainSelector, err) - } - if config.Config.PluginType == uint8(cctypes.PluginTypeCCIPCommit) { if !i.peerWrapper.IsStarted() { return nil, nil, fmt.Errorf("peer wrapper is not started") @@ -270,8 +261,7 @@ func (i *pluginOracleCreator) createFactoryAndTransmitter( rmnPeerClient, rmnCrypto, ) - factory = promwrapper.NewReportingPluginFactory[[]byte](factory, i.lggr, chainID, "CCIPCommit") - transmitter = ocrimpls.NewCommitContractTransmitter(destChainWriter, + transmitter = ocrimpls.NewCommitContractTransmitter[[]byte](destChainWriter, ocrtypes.Account(destFromAccounts[0]), hexutil.Encode(config.Config.OfframpAddress), // TODO: this works for evm only, how about non-evm? ) @@ -291,8 +281,7 @@ func (i *pluginOracleCreator) createFactoryAndTransmitter( contractReaders, chainWriters, ) - factory = promwrapper.NewReportingPluginFactory[[]byte](factory, i.lggr, chainID, "CCIPExec") - transmitter = ocrimpls.NewExecContractTransmitter(destChainWriter, + transmitter = ocrimpls.NewExecContractTransmitter[[]byte](destChainWriter, ocrtypes.Account(destFromAccounts[0]), hexutil.Encode(config.Config.OfframpAddress), // TODO: this works for evm only, how about non-evm? ) @@ -304,14 +293,13 @@ func (i *pluginOracleCreator) createFactoryAndTransmitter( func (i *pluginOracleCreator) createReadersAndWriters( ctx context.Context, - destChainID string, + destChainID uint64, pluginType cctypes.PluginType, config cctypes.OCR3ConfigWithMeta, publicCfg ocr3confighelper.PublicConfig, - destChainFamily string, ) ( map[cciptypes.ChainSelector]types.ContractReader, - map[cciptypes.ChainSelector]types.ContractWriter, + map[cciptypes.ChainSelector]types.ChainWriter, error, ) { ofc, err := decodeAndValidateOffchainConfig(pluginType, publicCfg) @@ -334,16 +322,19 @@ func (i *pluginOracleCreator) createReadersAndWriters( } contractReaders := make(map[cciptypes.ChainSelector]types.ContractReader) - chainWriters := make(map[cciptypes.ChainSelector]types.ContractWriter) + chainWriters := make(map[cciptypes.ChainSelector]types.ChainWriter) for relayID, relayer := range i.relayers { - chainID := relayID.ChainID - relayChainFamily := relayID.Network - chainSelector, err1 := i.getChainSelector(chainID, relayChainFamily) + chainID, ok := new(big.Int).SetString(relayID.ChainID, 10) + if !ok { + return nil, nil, fmt.Errorf("error parsing chain ID, expected big int: %s", relayID.ChainID) + } + + chainSelector, err1 := i.getChainSelector(chainID.Uint64()) if err1 != nil { - return nil, nil, fmt.Errorf("failed to get chain selector from chain ID %s: %w", chainID, err1) + return nil, nil, fmt.Errorf("failed to get chain selector from chain ID %s: %w", chainID.String(), err1) } - chainReaderConfig, err1 := getChainReaderConfig(i.lggr, chainID, destChainID, homeChainID, ofc, chainSelector) + chainReaderConfig, err1 := getChainReaderConfig(i.lggr, chainID.Uint64(), destChainID, homeChainID, ofc, chainSelector) if err1 != nil { return nil, nil, fmt.Errorf("failed to get chain reader config: %w", err1) } @@ -353,7 +344,7 @@ func (i *pluginOracleCreator) createReadersAndWriters( return nil, nil, err1 } - if chainID == destChainID && destChainFamily == relayChainFamily { + if chainID.Uint64() == destChainID { offrampAddressHex := common.BytesToAddress(config.Config.OfframpAddress).Hex() err2 := cr.Bind(ctx, []types.BoundContract{ { @@ -362,12 +353,12 @@ func (i *pluginOracleCreator) createReadersAndWriters( }, }) if err2 != nil { - return nil, nil, fmt.Errorf("failed to bind chain reader for dest chain %s's offramp at %s: %w", chainID, offrampAddressHex, err) + return nil, nil, fmt.Errorf("failed to bind chain reader for dest chain %s's offramp at %s: %w", chainID.String(), offrampAddressHex, err) } } if err2 := cr.Start(ctx); err2 != nil { - return nil, nil, fmt.Errorf("failed to start contract reader for chain %s: %w", chainID, err2) + return nil, nil, fmt.Errorf("failed to start contract reader for chain %s: %w", chainID.String(), err2) } cw, err1 := createChainWriter( @@ -375,14 +366,13 @@ func (i *pluginOracleCreator) createReadersAndWriters( chainID, relayer, i.transmitters, - execBatchGasLimit, - relayChainFamily) + execBatchGasLimit) if err1 != nil { return nil, nil, err1 } if err4 := cw.Start(ctx); err4 != nil { - return nil, nil, fmt.Errorf("failed to start chain writer for chain %s: %w", chainID, err4) + return nil, nil, fmt.Errorf("failed to start chain writer for chain %s: %w", chainID.String(), err4) } contractReaders[chainSelector] = cr @@ -421,27 +411,27 @@ func decodeAndValidateOffchainConfig( return ofc, nil } -func (i *pluginOracleCreator) getChainSelector(chainID string, chainFamily string) (cciptypes.ChainSelector, error) { - chainDetails, err := chainsel.GetChainDetailsByChainIDAndFamily(chainID, chainFamily) - if err != nil { - return 0, fmt.Errorf("failed to get chain selector from chain ID %s and family %s", chainID, chainFamily) +func (i *pluginOracleCreator) getChainSelector(chainID uint64) (cciptypes.ChainSelector, error) { + chainSelector, ok := chainsel.EvmChainIdToChainSelector()[chainID] + if !ok { + return 0, fmt.Errorf("failed to get chain selector from chain ID %d", chainID) } - return cciptypes.ChainSelector(chainDetails.ChainSelector), nil + return cciptypes.ChainSelector(chainSelector), nil } -func (i *pluginOracleCreator) getChainID(chainSelector cciptypes.ChainSelector) (string, error) { - chainID, err := chainsel.GetChainIDFromSelector(uint64(chainSelector)) +func (i *pluginOracleCreator) getChainID(chainSelector cciptypes.ChainSelector) (uint64, error) { + chainID, err := chainsel.ChainIdFromSelector(uint64(chainSelector)) if err != nil { - return "", fmt.Errorf("failed to get chain ID from chain selector %d: %w", chainSelector, err) + return 0, fmt.Errorf("failed to get chain ID from chain selector %d: %w", chainSelector, err) } return chainID, nil } func getChainReaderConfig( lggr logger.Logger, - chainID string, - destChainID string, - homeChainID string, + chainID uint64, + destChainID uint64, + homeChainID uint64, ofc offChainConfig, chainSelector cciptypes.ChainSelector, ) ([]byte, error) { @@ -485,14 +475,13 @@ func isUSDCEnabled(ofc offChainConfig) bool { func createChainWriter( ctx context.Context, - chainID string, + chainID *big.Int, relayer loop.Relayer, transmitters map[types.RelayID][]string, execBatchGasLimit uint64, - chainFamily string, -) (types.ContractWriter, error) { +) (types.ChainWriter, error) { var fromAddress common.Address - transmitter, ok := transmitters[types.NewRelayID(chainFamily, chainID)] + transmitter, ok := transmitters[types.NewRelayID(relay.NetworkEVM, chainID.String())] if ok { // TODO: remove EVM-specific stuff fromAddress = common.HexToAddress(transmitter[0]) @@ -512,9 +501,9 @@ func createChainWriter( return nil, fmt.Errorf("failed to marshal chain writer config: %w", err) } - cw, err := relayer.NewContractWriter(ctx, chainWriterConfig) + cw, err := relayer.NewChainWriter(ctx, chainWriterConfig) if err != nil { - return nil, fmt.Errorf("failed to create chain writer for chain %s: %w", chainID, err) + return nil, fmt.Errorf("failed to create chain writer for chain %s: %w", chainID.String(), err) } return cw, nil diff --git a/core/capabilities/compute/cache.go b/core/capabilities/compute/cache.go index dbcc42c1606..7b7cd78aaab 100644 --- a/core/capabilities/compute/cache.go +++ b/core/capabilities/compute/cache.go @@ -38,9 +38,8 @@ type moduleCache struct { timeout time.Duration evictAfterSize int - clock clockwork.Clock - reapTicker <-chan time.Time - onReaper chan struct{} + clock clockwork.Clock + onReaper chan struct{} } func newModuleCache(clock clockwork.Clock, tick, timeout time.Duration, evictAfterSize int) *moduleCache { @@ -50,7 +49,6 @@ func newModuleCache(clock clockwork.Clock, tick, timeout time.Duration, evictAft timeout: timeout, evictAfterSize: evictAfterSize, clock: clock, - reapTicker: clock.NewTicker(tick).Chan(), stopChan: make(chan struct{}), } } @@ -69,9 +67,10 @@ func (mc *moduleCache) close() { } func (mc *moduleCache) reapLoop() { + ticker := mc.clock.NewTicker(mc.tickInterval) for { select { - case <-mc.reapTicker: + case <-ticker.Chan(): mc.evictOlderThan(mc.timeout) if mc.onReaper != nil { mc.onReaper <- struct{}{} @@ -85,7 +84,7 @@ func (mc *moduleCache) reapLoop() { func (mc *moduleCache) add(id string, mod *module) { mc.mu.Lock() defer mc.mu.Unlock() - mod.lastFetchedAt = mc.clock.Now() + mod.lastFetchedAt = time.Now() mc.m[id] = mod moduleCacheAddition.Inc() } diff --git a/core/capabilities/compute/cache_test.go b/core/capabilities/compute/cache_test.go index ad075f493b5..3b38cc23001 100644 --- a/core/capabilities/compute/cache_test.go +++ b/core/capabilities/compute/cache_test.go @@ -20,17 +20,14 @@ const ( binaryCmd = "core/capabilities/compute/test/simple/cmd" ) -// Verify that cache evicts an expired module. func TestCache(t *testing.T) { t.Parallel() clock := clockwork.NewFakeClock() tick := 1 * time.Second timeout := 1 * time.Second - reapTicker := make(chan time.Time) cache := newModuleCache(clock, tick, timeout, 0) cache.onReaper = make(chan struct{}, 1) - cache.reapTicker = reapTicker cache.start() defer cache.close() @@ -53,24 +50,20 @@ func TestCache(t *testing.T) { assert.Equal(t, got, mod) clock.Advance(15 * time.Second) - reapTicker <- time.Now() <-cache.onReaper _, ok = cache.get(id) assert.False(t, ok) } -// Verify that an expired module is not evicted because evictAfterSize is 1 func TestCache_EvictAfterSize(t *testing.T) { t.Parallel() ctx := tests.Context(t) clock := clockwork.NewFakeClock() tick := 1 * time.Second timeout := 1 * time.Second - reapTicker := make(chan time.Time) cache := newModuleCache(clock, tick, timeout, 1) cache.onReaper = make(chan struct{}, 1) - cache.reapTicker = reapTicker cache.start() defer cache.close() @@ -86,7 +79,6 @@ func TestCache_EvictAfterSize(t *testing.T) { module: hmod, } cache.add(id, mod) - assert.Len(t, cache.m, 1) got, ok := cache.get(id) assert.True(t, ok) @@ -94,7 +86,6 @@ func TestCache_EvictAfterSize(t *testing.T) { assert.Equal(t, got, mod) clock.Advance(15 * time.Second) - reapTicker <- time.Now() select { case <-ctx.Done(): return diff --git a/core/capabilities/compute/compute.go b/core/capabilities/compute/compute.go index 2ba5daefaa6..7b11072b161 100644 --- a/core/capabilities/compute/compute.go +++ b/core/capabilities/compute/compute.go @@ -34,7 +34,7 @@ import ( ) const ( - CapabilityIDCompute = "custom-compute@1.0.0" + CapabilityIDCompute = "custom_compute@1.0.0" binaryKey = "binary" configKey = "config" @@ -273,19 +273,9 @@ func (c *Compute) worker(ctx context.Context) { } func (c *Compute) Close() error { - ctx, cancel := context.WithTimeout(context.Background(), time.Second) - defer cancel() - c.modules.close() close(c.stopCh) - - err := c.registry.Remove(ctx, CapabilityIDCompute) - if err != nil { - return err - } - c.wg.Wait() - return nil } @@ -318,13 +308,18 @@ func (c *Compute) createFetcher() func(ctx context.Context, req *wasmpb.FetchReq headersReq[k] = v.String() } - resp, err := c.outgoingConnectorHandler.HandleSingleNodeRequest(ctx, messageID, ghcapabilities.Request{ + payloadBytes, err := json.Marshal(ghcapabilities.Request{ URL: req.Url, Method: req.Method, Headers: headersReq, Body: req.Body, TimeoutMs: req.TimeoutMs, }) + if err != nil { + return nil, fmt.Errorf("failed to marshal fetch request: %w", err) + } + + resp, err := c.outgoingConnectorHandler.HandleSingleNodeRequest(ctx, messageID, payloadBytes) if err != nil { return nil, err } diff --git a/core/capabilities/compute/compute_test.go b/core/capabilities/compute/compute_test.go index 3e5f501fa61..c4146b7408e 100644 --- a/core/capabilities/compute/compute_test.go +++ b/core/capabilities/compute/compute_test.go @@ -14,7 +14,6 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/capabilities" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/wasmtest" "github.com/smartcontractkit/chainlink/v2/core/logger" - "github.com/smartcontractkit/chainlink/v2/core/utils/matches" cappkg "github.com/smartcontractkit/chainlink-common/pkg/capabilities" "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" @@ -189,7 +188,6 @@ func TestComputeFetch(t *testing.T) { th := setup(t, defaultConfig) th.connector.EXPECT().DonID().Return("don-id") - th.connector.EXPECT().AwaitConnection(matches.AnyContext, "gateway1").Return(nil) th.connector.EXPECT().GatewayIDs().Return([]string{"gateway1", "gateway2"}) msgID := strings.Join([]string{ diff --git a/core/capabilities/compute/test/fetch/cmd/main.go b/core/capabilities/compute/test/fetch/cmd/main.go index 44c6fb64601..bc45b426005 100644 --- a/core/capabilities/compute/test/fetch/cmd/main.go +++ b/core/capabilities/compute/test/fetch/cmd/main.go @@ -12,7 +12,12 @@ import ( ) func BuildWorkflow(config []byte) *sdk.WorkflowSpecFactory { - workflow := sdk.NewWorkflowSpecFactory() + workflow := sdk.NewWorkflowSpecFactory( + sdk.NewWorkflowParams{ + Name: "tester", + Owner: "ryan", + }, + ) triggerCfg := basictrigger.TriggerConfig{Name: "trigger", Number: 100} trigger := triggerCfg.New(workflow) diff --git a/core/capabilities/compute/test/simple/cmd/main.go b/core/capabilities/compute/test/simple/cmd/main.go index 92e4e52ef77..4ddacebe30b 100644 --- a/core/capabilities/compute/test/simple/cmd/main.go +++ b/core/capabilities/compute/test/simple/cmd/main.go @@ -10,7 +10,12 @@ import ( ) func BuildWorkflow(config []byte) *sdk.WorkflowSpecFactory { - workflow := sdk.NewWorkflowSpecFactory() + workflow := sdk.NewWorkflowSpecFactory( + sdk.NewWorkflowParams{ + Name: "tester", + Owner: "ryan", + }, + ) triggerCfg := basictrigger.TriggerConfig{Name: "trigger", Number: 100} trigger := triggerCfg.New(workflow) diff --git a/core/capabilities/don_notifier.go b/core/capabilities/don_notifier.go deleted file mode 100644 index 4edb38d3661..00000000000 --- a/core/capabilities/don_notifier.go +++ /dev/null @@ -1,43 +0,0 @@ -package capabilities - -import ( - "context" - "sync" - - "github.com/smartcontractkit/chainlink-common/pkg/capabilities" -) - -type DonNotifier struct { - mu sync.Mutex - don capabilities.DON - notified bool - ch chan struct{} -} - -func NewDonNotifier() *DonNotifier { - return &DonNotifier{ - ch: make(chan struct{}), - } -} - -func (n *DonNotifier) NotifyDonSet(don capabilities.DON) { - n.mu.Lock() - defer n.mu.Unlock() - if !n.notified { - n.don = don - n.notified = true - close(n.ch) - } -} - -func (n *DonNotifier) WaitForDon(ctx context.Context) (capabilities.DON, error) { - select { - case <-ctx.Done(): - return capabilities.DON{}, ctx.Err() - case <-n.ch: - } - <-n.ch - n.mu.Lock() - defer n.mu.Unlock() - return n.don, nil -} diff --git a/core/capabilities/don_notifier_test.go b/core/capabilities/don_notifier_test.go deleted file mode 100644 index f37931259ba..00000000000 --- a/core/capabilities/don_notifier_test.go +++ /dev/null @@ -1,49 +0,0 @@ -package capabilities_test - -import ( - "context" - "testing" - "time" - - "github.com/stretchr/testify/require" - - commoncap "github.com/smartcontractkit/chainlink-common/pkg/capabilities" - - "github.com/stretchr/testify/assert" - - "github.com/smartcontractkit/chainlink/v2/core/capabilities" -) - -func TestDonNotifier_WaitForDon(t *testing.T) { - notifier := capabilities.NewDonNotifier() - don := commoncap.DON{ - ID: 1, - } - - go func() { - time.Sleep(100 * time.Millisecond) - notifier.NotifyDonSet(don) - }() - - ctx, cancel := context.WithTimeout(context.Background(), 1*time.Second) - defer cancel() - - result, err := notifier.WaitForDon(ctx) - require.NoError(t, err) - assert.Equal(t, don, result) - - result, err = notifier.WaitForDon(ctx) - require.NoError(t, err) - assert.Equal(t, don, result) -} - -func TestDonNotifier_WaitForDon_ContextTimeout(t *testing.T) { - notifier := capabilities.NewDonNotifier() - - ctx, cancel := context.WithTimeout(context.Background(), 20*time.Millisecond) - defer cancel() - - _, err := notifier.WaitForDon(ctx) - require.Error(t, err) - assert.Equal(t, context.DeadlineExceeded, err) -} diff --git a/core/capabilities/integration_tests/framework/capabilities_registry.go b/core/capabilities/integration_tests/framework/capabilities_registry.go index 3ebbb5081d3..5c23d2ebc1a 100644 --- a/core/capabilities/integration_tests/framework/capabilities_registry.go +++ b/core/capabilities/integration_tests/framework/capabilities_registry.go @@ -11,7 +11,7 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/capabilities/pb" "github.com/smartcontractkit/chainlink-common/pkg/values" - kcr "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry_1_1_0" + kcr "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry" "github.com/stretchr/testify/require" ) diff --git a/core/capabilities/integration_tests/framework/don.go b/core/capabilities/integration_tests/framework/don.go index c9b78a0db96..999966bdc1d 100644 --- a/core/capabilities/integration_tests/framework/don.go +++ b/core/capabilities/integration_tests/framework/don.go @@ -28,7 +28,7 @@ import ( remotetypes "github.com/smartcontractkit/chainlink/v2/core/capabilities/remote/types" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" - kcr "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry_1_1_0" + kcr "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/logger" diff --git a/core/capabilities/integration_tests/framework/peer.go b/core/capabilities/integration_tests/framework/peer.go index c4f73629450..d97abadf646 100644 --- a/core/capabilities/integration_tests/framework/peer.go +++ b/core/capabilities/integration_tests/framework/peer.go @@ -11,7 +11,7 @@ import ( ragetypes "github.com/smartcontractkit/libocr/ragep2p/types" - kcr "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry_1_1_0" + kcr "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/chaintype" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/ocr2key" diff --git a/core/capabilities/integration_tests/keystone/contracts_setup.go b/core/capabilities/integration_tests/keystone/contracts_setup.go index ad87850bf5f..d7b98327889 100644 --- a/core/capabilities/integration_tests/keystone/contracts_setup.go +++ b/core/capabilities/integration_tests/keystone/contracts_setup.go @@ -7,8 +7,8 @@ import ( "github.com/stretchr/testify/require" "github.com/smartcontractkit/chainlink/v2/core/capabilities/integration_tests/framework" - feeds_consumer "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/feeds_consumer_1_0_0" - forwarder "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/forwarder_1_0_0" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/feeds_consumer" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/forwarder" ) func SetupForwarderContract(t *testing.T, reportCreator *framework.DON, diff --git a/core/capabilities/integration_tests/keystone/keystone_test.go b/core/capabilities/integration_tests/keystone/keystone_test.go index 6cfa8c9f0df..17bfde7cda9 100644 --- a/core/capabilities/integration_tests/keystone/keystone_test.go +++ b/core/capabilities/integration_tests/keystone/keystone_test.go @@ -16,7 +16,7 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/capabilities/datastreams" "github.com/smartcontractkit/chainlink-common/pkg/values" "github.com/smartcontractkit/chainlink/v2/core/capabilities/integration_tests/framework" - feeds_consumer "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/feeds_consumer_1_0_0" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/feeds_consumer" "github.com/smartcontractkit/chainlink/v2/core/logger" reporttypes "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/mercury/v3/types" ) diff --git a/core/capabilities/integration_tests/keystone/setup.go b/core/capabilities/integration_tests/keystone/setup.go index 690e176e491..b9b98baaf7e 100644 --- a/core/capabilities/integration_tests/keystone/setup.go +++ b/core/capabilities/integration_tests/keystone/setup.go @@ -18,7 +18,7 @@ import ( v3 "github.com/smartcontractkit/chainlink-common/pkg/types/mercury/v3" "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" "github.com/smartcontractkit/chainlink/v2/core/capabilities/integration_tests/framework" - feeds_consumer "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/feeds_consumer_1_0_0" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/feeds_consumer" ocrTypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types" @@ -130,7 +130,7 @@ func newReport(t *testing.T, feedID [32]byte, price *big.Int, timestamp int64) [ v3Codec := reportcodec.NewReportCodec(feedID, logger.TestLogger(t)) raw, err := v3Codec.BuildReport(ctx, v3.ReportFields{ BenchmarkPrice: price, - + //nolint:gosec // disable G115 Timestamp: uint32(timestamp), Bid: big.NewInt(0), Ask: big.NewInt(0), diff --git a/core/capabilities/launcher.go b/core/capabilities/launcher.go index 51df7eeebfc..e75f2ebbc8f 100644 --- a/core/capabilities/launcher.go +++ b/core/capabilities/launcher.go @@ -19,7 +19,6 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/services" "github.com/smartcontractkit/chainlink-common/pkg/values" "github.com/smartcontractkit/chainlink/v2/core/capabilities/remote" - "github.com/smartcontractkit/chainlink/v2/core/capabilities/remote/aggregation" "github.com/smartcontractkit/chainlink/v2/core/capabilities/remote/executable" remotetypes "github.com/smartcontractkit/chainlink/v2/core/capabilities/remote/types" "github.com/smartcontractkit/chainlink/v2/core/capabilities/streams" @@ -44,12 +43,11 @@ var defaultStreamConfig = p2ptypes.StreamConfig{ type launcher struct { services.StateMachine - lggr logger.Logger - peerWrapper p2ptypes.PeerWrapper - dispatcher remotetypes.Dispatcher - registry *Registry - subServices []services.Service - workflowDonNotifier donNotifier + lggr logger.Logger + peerWrapper p2ptypes.PeerWrapper + dispatcher remotetypes.Dispatcher + registry *Registry + subServices []services.Service } func unmarshalCapabilityConfig(data []byte) (capabilities.CapabilityConfiguration, error) { @@ -88,24 +86,18 @@ func unmarshalCapabilityConfig(data []byte) (capabilities.CapabilityConfiguratio }, nil } -type donNotifier interface { - NotifyDonSet(don capabilities.DON) -} - func NewLauncher( lggr logger.Logger, peerWrapper p2ptypes.PeerWrapper, dispatcher remotetypes.Dispatcher, registry *Registry, - workflowDonNotifier donNotifier, ) *launcher { return &launcher{ - lggr: lggr.Named("CapabilitiesLauncher"), - peerWrapper: peerWrapper, - dispatcher: dispatcher, - registry: registry, - subServices: []services.Service{}, - workflowDonNotifier: workflowDonNotifier, + lggr: lggr.Named("CapabilitiesLauncher"), + peerWrapper: peerWrapper, + dispatcher: dispatcher, + registry: registry, + subServices: []services.Service{}, } } @@ -136,7 +128,6 @@ func (w *launcher) Name() string { } func (w *launcher) Launch(ctx context.Context, state *registrysyncer.LocalRegistry) error { - w.lggr.Debug("CapabilitiesLauncher triggered...") w.registry.SetLocalRegistry(state) allDONIDs := []registrysyncer.DonID{} @@ -224,9 +215,6 @@ func (w *launcher) Launch(ctx context.Context, state *registrysyncer.LocalRegist return errors.New("invariant violation: node is part of more than one workflowDON") } - w.lggr.Debug("Notifying DON set...") - w.workflowDonNotifier.NotifyDonSet(myDON.DON) - for _, rcd := range remoteCapabilityDONs { err := w.addRemoteCapabilities(ctx, myDON, rcd, state) if err != nil { @@ -281,7 +269,7 @@ func (w *launcher) addRemoteCapabilities(ctx context.Context, myDON registrysync w.lggr, ) } else { - aggregator = aggregation.NewDefaultModeAggregator(uint32(remoteDON.F) + 1) + aggregator = remote.NewDefaultModeAggregator(uint32(remoteDON.F) + 1) } // TODO: We need to implement a custom, Mercury-specific @@ -399,8 +387,7 @@ func (w *launcher) addToRegistryAndSetDispatcher(ctx context.Context, capability } var ( - // TODO: make this configurable - defaultTargetRequestTimeout = 8 * time.Minute + defaultTargetRequestTimeout = time.Minute ) func (w *launcher) exposeCapabilities(ctx context.Context, myPeerID p2ptypes.PeerID, don registrysyncer.DON, state *registrysyncer.LocalRegistry, remoteWorkflowDONs []registrysyncer.DON) error { @@ -472,8 +459,7 @@ func (w *launcher) exposeCapabilities(ctx context.Context, myPeerID p2ptypes.Pee err = w.addReceiver(ctx, capability, don, newActionServer) if err != nil { - w.lggr.Errorw("failed to add action server-side receiver - it won't be exposed remotely", "id", cid, "error", err) - // continue attempting other capabilities + return fmt.Errorf("failed to add action server-side receiver: %w", err) } case capabilities.CapabilityTypeConsensus: w.lggr.Warn("no remote client configured for capability type consensus, skipping configuration") diff --git a/core/capabilities/launcher_test.go b/core/capabilities/launcher_test.go index 167a2fcbd1b..013463bfdbb 100644 --- a/core/capabilities/launcher_test.go +++ b/core/capabilities/launcher_test.go @@ -23,7 +23,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/capabilities/remote" remotetypes "github.com/smartcontractkit/chainlink/v2/core/capabilities/remote/types" remoteMocks "github.com/smartcontractkit/chainlink/v2/core/capabilities/remote/types/mocks" - kcr "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry_1_1_0" + kcr "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry" "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/p2p/types" p2ptypes "github.com/smartcontractkit/chainlink/v2/core/services/p2p/types" @@ -33,12 +33,6 @@ import ( var _ capabilities.TriggerCapability = (*mockTrigger)(nil) -type mockDonNotifier struct { -} - -func (m *mockDonNotifier) NotifyDonSet(don capabilities.DON) { -} - type mockTrigger struct { capabilities.CapabilityInfo } @@ -202,7 +196,6 @@ func TestLauncher(t *testing.T) { wrapper, dispatcher, registry, - &mockDonNotifier{}, ) dispatcher.On("SetReceiver", fullTriggerCapID, dID, mock.AnythingOfType("*remote.triggerPublisher")).Return(nil) @@ -312,7 +305,6 @@ func TestLauncher(t *testing.T) { wrapper, dispatcher, registry, - &mockDonNotifier{}, ) err = launcher.Launch(ctx, state) @@ -417,7 +409,6 @@ func TestLauncher(t *testing.T) { wrapper, dispatcher, registry, - &mockDonNotifier{}, ) err = launcher.Launch(ctx, state) @@ -609,7 +600,6 @@ func TestLauncher_RemoteTriggerModeAggregatorShim(t *testing.T) { wrapper, dispatcher, registry, - &mockDonNotifier{}, ) dispatcher.On("SetReceiver", fullTriggerCapID, capDonID, mock.AnythingOfType("*remote.triggerSubscriber")).Return(nil) @@ -762,7 +752,6 @@ func TestSyncer_IgnoresCapabilitiesForPrivateDON(t *testing.T) { wrapper, dispatcher, registry, - &mockDonNotifier{}, ) // If the DON were public, this would fail with two errors: @@ -928,7 +917,6 @@ func TestLauncher_WiresUpClientsForPublicWorkflowDON(t *testing.T) { wrapper, dispatcher, registry, - &mockDonNotifier{}, ) dispatcher.On("SetReceiver", fullTriggerCapID, capDonID, mock.AnythingOfType("*remote.triggerSubscriber")).Return(nil) @@ -1094,7 +1082,6 @@ func TestLauncher_WiresUpClientsForPublicWorkflowDONButIgnoresPrivateCapabilitie wrapper, dispatcher, registry, - &mockDonNotifier{}, ) dispatcher.On("SetReceiver", fullTriggerCapID, triggerCapDonID, mock.AnythingOfType("*remote.triggerSubscriber")).Return(nil) @@ -1245,7 +1232,6 @@ func TestLauncher_SucceedsEvenIfDispatcherAlreadyHasReceiver(t *testing.T) { wrapper, dispatcher, registry, - &mockDonNotifier{}, ) err = launcher.Launch(ctx, state) diff --git a/core/capabilities/registry.go b/core/capabilities/registry.go index 7038dcdb4b7..47285505805 100644 --- a/core/capabilities/registry.go +++ b/core/capabilities/registry.go @@ -193,21 +193,6 @@ func (r *Registry) Add(ctx context.Context, c capabilities.BaseCapability) error return nil } -// Add adds a capability to the registry. -func (r *Registry) Remove(ctx context.Context, id string) error { - r.mu.Lock() - defer r.mu.Unlock() - - _, ok := r.m[id] - if !ok { - return fmt.Errorf("unable to remove, capability not found: %s", id) - } - - delete(r.m, id) - r.lggr.Infow("capability removed", "id", id) - return nil -} - // NewRegistry returns a new Registry. func NewRegistry(lggr logger.Logger) *Registry { return &Registry{ diff --git a/core/capabilities/remote/aggregation/default_mode.go b/core/capabilities/remote/aggregation/default_mode.go deleted file mode 100644 index 3d5e262920f..00000000000 --- a/core/capabilities/remote/aggregation/default_mode.go +++ /dev/null @@ -1,58 +0,0 @@ -package aggregation - -import ( - "crypto/sha256" - "encoding/hex" - "errors" - "fmt" - - commoncap "github.com/smartcontractkit/chainlink-common/pkg/capabilities" - "github.com/smartcontractkit/chainlink-common/pkg/capabilities/pb" - remotetypes "github.com/smartcontractkit/chainlink/v2/core/capabilities/remote/types" -) - -// Default MODE Aggregator needs a configurable number of identical responses for aggregation to succeed -type defaultModeAggregator struct { - minIdenticalResponses uint32 -} - -var _ remotetypes.Aggregator = &defaultModeAggregator{} - -func NewDefaultModeAggregator(minIdenticalResponses uint32) *defaultModeAggregator { - return &defaultModeAggregator{ - minIdenticalResponses: minIdenticalResponses, - } -} - -func (a *defaultModeAggregator) Aggregate(_ string, responses [][]byte) (commoncap.TriggerResponse, error) { - found, err := AggregateModeRaw(responses, a.minIdenticalResponses) - if err != nil { - return commoncap.TriggerResponse{}, fmt.Errorf("failed to aggregate responses, err: %w", err) - } - - unmarshaled, err := pb.UnmarshalTriggerResponse(found) - if err != nil { - return commoncap.TriggerResponse{}, fmt.Errorf("failed to unmarshal aggregated responses, err: %w", err) - } - return unmarshaled, nil -} - -func AggregateModeRaw(elemList [][]byte, minIdenticalResponses uint32) ([]byte, error) { - hashToCount := make(map[string]uint32) - var found []byte - for _, elem := range elemList { - hasher := sha256.New() - hasher.Write(elem) - sha := hex.EncodeToString(hasher.Sum(nil)) - hashToCount[sha]++ - if hashToCount[sha] >= minIdenticalResponses { - found = elem - // update in case we find another elem with an even higher count - minIdenticalResponses = hashToCount[sha] - } - } - if found == nil { - return nil, errors.New("not enough identical responses found") - } - return found, nil -} diff --git a/core/capabilities/remote/aggregation/default_mode_test.go b/core/capabilities/remote/aggregation/default_mode_test.go deleted file mode 100644 index 7c7d615e17a..00000000000 --- a/core/capabilities/remote/aggregation/default_mode_test.go +++ /dev/null @@ -1,51 +0,0 @@ -package aggregation - -import ( - "testing" - - "github.com/stretchr/testify/require" - - commoncap "github.com/smartcontractkit/chainlink-common/pkg/capabilities" - "github.com/smartcontractkit/chainlink-common/pkg/capabilities/pb" - "github.com/smartcontractkit/chainlink-common/pkg/values" -) - -var ( - triggerEvent1 = map[string]any{"event": "triggerEvent1"} - triggerEvent2 = map[string]any{"event": "triggerEvent2"} -) - -func TestDefaultModeAggregator_Aggregate(t *testing.T) { - val, err := values.NewMap(triggerEvent1) - require.NoError(t, err) - capResponse1 := commoncap.TriggerResponse{ - Event: commoncap.TriggerEvent{ - Outputs: val, - }, - Err: nil, - } - marshaled1, err := pb.MarshalTriggerResponse(capResponse1) - require.NoError(t, err) - - val2, err := values.NewMap(triggerEvent2) - require.NoError(t, err) - capResponse2 := commoncap.TriggerResponse{ - Event: commoncap.TriggerEvent{ - Outputs: val2, - }, - Err: nil, - } - marshaled2, err := pb.MarshalTriggerResponse(capResponse2) - require.NoError(t, err) - - agg := NewDefaultModeAggregator(2) - _, err = agg.Aggregate("", [][]byte{marshaled1}) - require.Error(t, err) - - _, err = agg.Aggregate("", [][]byte{marshaled1, marshaled2}) - require.Error(t, err) - - res, err := agg.Aggregate("", [][]byte{marshaled1, marshaled2, marshaled1}) - require.NoError(t, err) - require.Equal(t, res, capResponse1) -} diff --git a/core/capabilities/remote/dispatcher.go b/core/capabilities/remote/dispatcher.go index 905eda9d72d..e3229d35c1e 100644 --- a/core/capabilities/remote/dispatcher.go +++ b/core/capabilities/remote/dispatcher.go @@ -3,7 +3,6 @@ package remote import ( "context" "fmt" - "strconv" "sync" "time" @@ -43,8 +42,8 @@ type dispatcher struct { } type key struct { - capID string - donID uint32 + capId string + donId uint32 } var _ services.Service = &dispatcher{} @@ -75,7 +74,7 @@ func (d *dispatcher) Start(ctx context.Context) error { d.peer = d.peerWrapper.GetPeer() d.peerID = d.peer.ID() if d.peer == nil { - return errors.New("peer is not initialized") + return fmt.Errorf("peer is not initialized") } d.wg.Add(1) go func() { @@ -104,13 +103,13 @@ type receiver struct { ch chan *types.MessageBody } -func (d *dispatcher) SetReceiver(capabilityID string, donID uint32, rec types.Receiver) error { +func (d *dispatcher) SetReceiver(capabilityId string, donId uint32, rec types.Receiver) error { d.mu.Lock() defer d.mu.Unlock() - k := key{capabilityID, donID} + k := key{capabilityId, donId} _, ok := d.receivers[k] if ok { - return fmt.Errorf("%w: receiver already exists for capability %s and don %d", ErrReceiverExists, capabilityID, donID) + return fmt.Errorf("%w: receiver already exists for capability %s and don %d", ErrReceiverExists, capabilityId, donId) } receiverCh := make(chan *types.MessageBody, d.cfg.ReceiverBufferSize()) @@ -135,24 +134,23 @@ func (d *dispatcher) SetReceiver(capabilityID string, donID uint32, rec types.Re ch: receiverCh, } - d.lggr.Debugw("receiver set", "capabilityId", capabilityID, "donId", donID) + d.lggr.Debugw("receiver set", "capabilityId", capabilityId, "donId", donId) return nil } -func (d *dispatcher) RemoveReceiver(capabilityID string, donID uint32) { +func (d *dispatcher) RemoveReceiver(capabilityId string, donId uint32) { d.mu.Lock() defer d.mu.Unlock() - receiverKey := key{capabilityID, donID} + receiverKey := key{capabilityId, donId} if receiver, ok := d.receivers[receiverKey]; ok { receiver.cancel() delete(d.receivers, receiverKey) - d.lggr.Debugw("receiver removed", "capabilityId", capabilityID, "donId", donID) + d.lggr.Debugw("receiver removed", "capabilityId", capabilityId, "donId", donId) } } func (d *dispatcher) Send(peerID p2ptypes.PeerID, msgBody *types.MessageBody) error { - //nolint:gosec // disable G115 msgBody.Version = uint32(d.cfg.SupportedVersion()) msgBody.Sender = d.peerID[:] msgBody.Receiver = peerID[:] @@ -196,17 +194,17 @@ func (d *dispatcher) receive() { receiver, ok := d.receivers[k] d.mu.RUnlock() if !ok { - d.lggr.Debugw("received message for unregistered capability", "capabilityId", SanitizeLogString(k.capID), "donId", k.donID) + d.lggr.Debugw("received message for unregistered capability", "capabilityId", SanitizeLogString(k.capId), "donId", k.donId) d.tryRespondWithError(msg.Sender, body, types.Error_CAPABILITY_NOT_FOUND) continue } receiverQueueUsage := float64(len(receiver.ch)) / float64(d.cfg.ReceiverBufferSize()) - capReceiveChannelUsage.WithLabelValues(k.capID, strconv.FormatUint(uint64(k.donID), 10)).Set(receiverQueueUsage) + capReceiveChannelUsage.WithLabelValues(k.capId, fmt.Sprint(k.donId)).Set(receiverQueueUsage) select { case receiver.ch <- body: default: - d.lggr.Warnw("receiver channel full, dropping message", "capabilityId", k.capID, "donId", k.donID) + d.lggr.Warnw("receiver channel full, dropping message", "capabilityId", k.capId, "donId", k.donId) } } } diff --git a/core/capabilities/remote/dispatcher_test.go b/core/capabilities/remote/dispatcher_test.go index fbc9dbb4b49..50edc5f3530 100644 --- a/core/capabilities/remote/dispatcher_test.go +++ b/core/capabilities/remote/dispatcher_test.go @@ -104,13 +104,13 @@ func TestDispatcher_CleanStartClose(t *testing.T) { func TestDispatcher_Receive(t *testing.T) { lggr := logger.TestLogger(t) ctx := testutils.Context(t) - privKey1, peerID1 := newKeyPair(t) - _, peerID2 := newKeyPair(t) + privKey1, peerId1 := newKeyPair(t) + _, peerId2 := newKeyPair(t) peer := mocks.NewPeer(t) recvCh := make(chan p2ptypes.Message) peer.On("Receive", mock.Anything).Return((<-chan p2ptypes.Message)(recvCh)) - peer.On("ID", mock.Anything).Return(peerID2) + peer.On("ID", mock.Anything).Return(peerId2) wrapper := mocks.NewPeerWrapper(t) wrapper.On("GetPeer").Return(peer) signer := mocks.NewSigner(t) @@ -131,39 +131,39 @@ func TestDispatcher_Receive(t *testing.T) { require.NoError(t, dispatcher.Start(ctx)) rcv := newReceiver() - err = dispatcher.SetReceiver(capID1, donID1, rcv) + err = dispatcher.SetReceiver(capId1, donId1, rcv) require.NoError(t, err) // supported capability - recvCh <- encodeAndSign(t, privKey1, peerID1, peerID2, capID1, donID1, []byte(payload1)) + recvCh <- encodeAndSign(t, privKey1, peerId1, peerId2, capId1, donId1, []byte(payload1)) // unknown capability - recvCh <- encodeAndSign(t, privKey1, peerID1, peerID2, capID2, donID1, []byte(payload1)) + recvCh <- encodeAndSign(t, privKey1, peerId1, peerId2, capId2, donId1, []byte(payload1)) // sender doesn't match - invalid := encodeAndSign(t, privKey1, peerID1, peerID2, capID2, donID1, []byte(payload1)) - invalid.Sender = peerID2 + invalid := encodeAndSign(t, privKey1, peerId1, peerId2, capId2, donId1, []byte(payload1)) + invalid.Sender = peerId2 recvCh <- invalid // supported capability again - recvCh <- encodeAndSign(t, privKey1, peerID1, peerID2, capID1, donID1, []byte(payload2)) + recvCh <- encodeAndSign(t, privKey1, peerId1, peerId2, capId1, donId1, []byte(payload2)) m := <-rcv.ch require.Equal(t, payload1, string(m.Payload)) m = <-rcv.ch require.Equal(t, payload2, string(m.Payload)) - dispatcher.RemoveReceiver(capID1, donID1) + dispatcher.RemoveReceiver(capId1, donId1) require.NoError(t, dispatcher.Close()) } func TestDispatcher_RespondWithError(t *testing.T) { lggr := logger.TestLogger(t) ctx := testutils.Context(t) - privKey1, peerID1 := newKeyPair(t) - _, peerID2 := newKeyPair(t) + privKey1, peerId1 := newKeyPair(t) + _, peerId2 := newKeyPair(t) peer := mocks.NewPeer(t) recvCh := make(chan p2ptypes.Message) peer.On("Receive", mock.Anything).Return((<-chan p2ptypes.Message)(recvCh)) - peer.On("ID", mock.Anything).Return(peerID2) + peer.On("ID", mock.Anything).Return(peerId2) sendCh := make(chan p2ptypes.PeerID) peer.On("Send", mock.Anything, mock.Anything).Run(func(args mock.Arguments) { peerID := args.Get(0).(p2ptypes.PeerID) @@ -189,9 +189,9 @@ func TestDispatcher_RespondWithError(t *testing.T) { require.NoError(t, dispatcher.Start(ctx)) // unknown capability - recvCh <- encodeAndSign(t, privKey1, peerID1, peerID2, capID1, donID1, []byte(payload1)) + recvCh <- encodeAndSign(t, privKey1, peerId1, peerId2, capId1, donId1, []byte(payload1)) responseDestPeerID := <-sendCh - require.Equal(t, peerID1, responseDestPeerID) + require.Equal(t, peerId1, responseDestPeerID) require.NoError(t, dispatcher.Close()) } diff --git a/core/capabilities/remote/executable/client.go b/core/capabilities/remote/executable/client.go index 9f23ff4ce4a..08c773cdb86 100644 --- a/core/capabilities/remote/executable/client.go +++ b/core/capabilities/remote/executable/client.go @@ -41,13 +41,6 @@ var _ commoncap.ExecutableCapability = &client{} var _ types.Receiver = &client{} var _ services.Service = &client{} -const expiryCheckInterval = 30 * time.Second - -var ( - ErrRequestExpired = errors.New("request expired by executable client") - ErrContextDoneBeforeResponseQuorum = errors.New("context done before remote client received a quorum of responses") -) - func NewClient(remoteCapabilityInfo commoncap.CapabilityInfo, localDonInfo commoncap.DON, dispatcher types.Dispatcher, requestTimeout time.Duration, lggr logger.Logger) *client { return &client{ @@ -105,11 +98,7 @@ func (c *client) checkDispatcherReady() { } func (c *client) checkForExpiredRequests() { - tickerInterval := expiryCheckInterval - if c.requestTimeout < tickerInterval { - tickerInterval = c.requestTimeout - } - ticker := time.NewTicker(tickerInterval) + ticker := time.NewTicker(c.requestTimeout) defer ticker.Stop() for { select { @@ -127,7 +116,7 @@ func (c *client) expireRequests() { for messageID, req := range c.requestIDToCallerRequest { if req.Expired() { - req.Cancel(ErrRequestExpired) + req.Cancel(errors.New("request expired")) delete(c.requestIDToCallerRequest, messageID) } @@ -151,10 +140,40 @@ func (c *client) Info(ctx context.Context) (commoncap.CapabilityInfo, error) { } func (c *client) RegisterToWorkflow(ctx context.Context, registerRequest commoncap.RegisterToWorkflowRequest) error { + req, err := request.NewClientRegisterToWorkflowRequest(ctx, c.lggr, registerRequest, c.remoteCapabilityInfo, c.localDONInfo, c.dispatcher, + c.requestTimeout) + + if err != nil { + return fmt.Errorf("failed to create client request: %w", err) + } + + if err = c.sendRequest(req); err != nil { + return fmt.Errorf("failed to send request: %w", err) + } + + resp := <-req.ResponseChan() + if resp.Err != nil { + return fmt.Errorf("error executing request: %w", resp.Err) + } return nil } func (c *client) UnregisterFromWorkflow(ctx context.Context, unregisterRequest commoncap.UnregisterFromWorkflowRequest) error { + req, err := request.NewClientUnregisterFromWorkflowRequest(ctx, c.lggr, unregisterRequest, c.remoteCapabilityInfo, + c.localDONInfo, c.dispatcher, c.requestTimeout) + + if err != nil { + return fmt.Errorf("failed to create client request: %w", err) + } + + if err = c.sendRequest(req); err != nil { + return fmt.Errorf("failed to send request: %w", err) + } + + resp := <-req.ResponseChan() + if resp.Err != nil { + return fmt.Errorf("error executing request: %w", resp.Err) + } return nil } @@ -169,22 +188,12 @@ func (c *client) Execute(ctx context.Context, capReq commoncap.CapabilityRequest return commoncap.CapabilityResponse{}, fmt.Errorf("failed to send request: %w", err) } - var respResult []byte - var respErr error - select { - case resp := <-req.ResponseChan(): - respResult = resp.Result - respErr = resp.Err - case <-ctx.Done(): - // NOTE: ClientRequest will not block on sending to ResponseChan() because that channel is buffered (with size 1) - return commoncap.CapabilityResponse{}, errors.Join(ErrContextDoneBeforeResponseQuorum, ctx.Err()) - } - - if respErr != nil { - return commoncap.CapabilityResponse{}, fmt.Errorf("error executing request: %w", respErr) + resp := <-req.ResponseChan() + if resp.Err != nil { + return commoncap.CapabilityResponse{}, fmt.Errorf("error executing request: %w", resp.Err) } - capabilityResponse, err := pb.UnmarshalCapabilityResponse(respResult) + capabilityResponse, err := pb.UnmarshalCapabilityResponse(resp.Result) if err != nil { return commoncap.CapabilityResponse{}, fmt.Errorf("failed to unmarshal capability response: %w", err) } diff --git a/core/capabilities/remote/executable/client_test.go b/core/capabilities/remote/executable/client_test.go index 4e7d940a3b9..5c4da350b9e 100644 --- a/core/capabilities/remote/executable/client_test.go +++ b/core/capabilities/remote/executable/client_test.go @@ -13,7 +13,6 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/capabilities/pb" "github.com/smartcontractkit/chainlink-common/pkg/services/servicetest" "github.com/smartcontractkit/chainlink-common/pkg/values" - "github.com/smartcontractkit/chainlink/v2/core/capabilities/remote/executable" remotetypes "github.com/smartcontractkit/chainlink/v2/core/capabilities/remote/types" "github.com/smartcontractkit/chainlink/v2/core/capabilities/transmission" @@ -57,6 +56,18 @@ func Test_Client_DonTopologies(t *testing.T) { executeMethod(ctx, caller, transmissionSchedule, executeInputs, responseTest, t) }) + methods = append(methods, func(caller commoncap.ExecutableCapability) { + registerToWorkflowMethod(ctx, caller, transmissionSchedule, func(t *testing.T, responseError error) { + require.NoError(t, responseError) + }, t) + }) + + methods = append(methods, func(caller commoncap.ExecutableCapability) { + unregisterFromWorkflowMethod(ctx, caller, transmissionSchedule, func(t *testing.T, responseError error) { + require.NoError(t, responseError) + }, t) + }) + for _, method := range methods { testClient(t, 1, responseTimeOut, 1, 0, capability, method) @@ -132,8 +143,7 @@ func Test_Client_TimesOutIfInsufficientCapabilityPeerResponses(t *testing.T) { ctx := testutils.Context(t) responseTest := func(t *testing.T, response commoncap.CapabilityResponse, responseError error) { - require.Error(t, responseError) - require.ErrorIs(t, responseError, executable.ErrRequestExpired) + assert.Error(t, responseError) } capability := &TestCapability{} @@ -155,31 +165,6 @@ func Test_Client_TimesOutIfInsufficientCapabilityPeerResponses(t *testing.T) { }) } -func Test_Client_ContextCanceledBeforeQuorumReached(t *testing.T) { - ctx, cancel := context.WithCancel(testutils.Context(t)) - - responseTest := func(t *testing.T, response commoncap.CapabilityResponse, responseError error) { - require.Error(t, responseError) - require.ErrorIs(t, responseError, executable.ErrContextDoneBeforeResponseQuorum) - } - - capability := &TestCapability{} - transmissionSchedule, err := values.NewMap(map[string]any{ - "schedule": transmission.Schedule_AllAtOnce, - "deltaStage": "20s", - }) - require.NoError(t, err) - - cancel() - testClient(t, 2, 20*time.Second, 2, 2, - capability, - func(caller commoncap.ExecutableCapability) { - executeInputs, err := values.NewMap(map[string]any{"executeValue1": "aValue1"}) - require.NoError(t, err) - executeMethod(ctx, caller, transmissionSchedule, executeInputs, responseTest, t) - }) -} - func testClient(t *testing.T, numWorkflowPeers int, workflowNodeResponseTimeout time.Duration, numCapabilityPeers int, capabilityDonF uint8, underlying commoncap.ExecutableCapability, method func(caller commoncap.ExecutableCapability)) { @@ -249,6 +234,34 @@ func testClient(t *testing.T, numWorkflowPeers int, workflowNodeResponseTimeout wg.Wait() } +func registerToWorkflowMethod(ctx context.Context, caller commoncap.ExecutableCapability, transmissionSchedule *values.Map, + responseTest func(t *testing.T, responseError error), t *testing.T) { + err := caller.RegisterToWorkflow(ctx, commoncap.RegisterToWorkflowRequest{ + Metadata: commoncap.RegistrationMetadata{ + WorkflowID: workflowID1, + ReferenceID: stepReferenceID1, + WorkflowOwner: workflowOwnerID, + }, + Config: transmissionSchedule, + }) + + responseTest(t, err) +} + +func unregisterFromWorkflowMethod(ctx context.Context, caller commoncap.ExecutableCapability, transmissionSchedule *values.Map, + responseTest func(t *testing.T, responseError error), t *testing.T) { + err := caller.UnregisterFromWorkflow(ctx, commoncap.UnregisterFromWorkflowRequest{ + Metadata: commoncap.RegistrationMetadata{ + WorkflowID: workflowID1, + ReferenceID: stepReferenceID1, + WorkflowOwner: workflowOwnerID, + }, + Config: transmissionSchedule, + }) + + responseTest(t, err) +} + func executeMethod(ctx context.Context, caller commoncap.ExecutableCapability, transmissionSchedule *values.Map, executeInputs *values.Map, responseTest func(t *testing.T, responseCh commoncap.CapabilityResponse, responseError error), t *testing.T) { responseCh, err := caller.Execute(ctx, @@ -319,6 +332,21 @@ func (t *clientTestServer) Receive(_ context.Context, msg *remotetypes.MessageBo resp, responseErr := t.executableCapability.Execute(context.Background(), capabilityRequest) payload, marshalErr := pb.MarshalCapabilityResponse(resp) t.sendResponse(messageID, responseErr, payload, marshalErr) + + case remotetypes.MethodRegisterToWorkflow: + registerRequest, err := pb.UnmarshalRegisterToWorkflowRequest(msg.Payload) + if err != nil { + panic(err) + } + responseErr := t.executableCapability.RegisterToWorkflow(context.Background(), registerRequest) + t.sendResponse(messageID, responseErr, nil, nil) + case remotetypes.MethodUnregisterFromWorkflow: + unregisterRequest, err := pb.UnmarshalUnregisterFromWorkflowRequest(msg.Payload) + if err != nil { + panic(err) + } + responseErr := t.executableCapability.UnregisterFromWorkflow(context.Background(), unregisterRequest) + t.sendResponse(messageID, responseErr, nil, nil) default: panic("unknown method") } diff --git a/core/capabilities/remote/executable/endtoend_test.go b/core/capabilities/remote/executable/endtoend_test.go index 886bde9d33d..29f29ed9ee1 100644 --- a/core/capabilities/remote/executable/endtoend_test.go +++ b/core/capabilities/remote/executable/endtoend_test.go @@ -26,6 +26,84 @@ import ( p2ptypes "github.com/smartcontractkit/chainlink/v2/core/services/p2p/types" ) +func Test_RemoteExecutableCapability_InsufficientCapabilityResponses(t *testing.T) { + ctx := testutils.Context(t) + + responseTest := func(t *testing.T, responseCh commoncap.CapabilityResponse, responseError error) { + assert.NotNil(t, responseError) + } + + capability := &TestCapability{} + + transmissionSchedule, err := values.NewMap(map[string]any{ + "schedule": transmission.Schedule_AllAtOnce, + "deltaStage": "10ms", + }) + require.NoError(t, err) + + var methods []func(ctx context.Context, caller commoncap.ExecutableCapability) + + methods = append(methods, func(ctx context.Context, caller commoncap.ExecutableCapability) { + executeCapability(ctx, t, caller, transmissionSchedule, responseTest) + }) + + methods = append(methods, func(ctx context.Context, caller commoncap.ExecutableCapability) { + registerWorkflow(ctx, t, caller, transmissionSchedule, func(t *testing.T, responseError error) { + require.Error(t, responseError) + }) + }) + + methods = append(methods, func(ctx context.Context, caller commoncap.ExecutableCapability) { + unregisterWorkflow(ctx, t, caller, transmissionSchedule, func(t *testing.T, responseError error) { + require.Error(t, responseError) + }) + }) + + for _, method := range methods { + testRemoteExecutableCapability(ctx, t, capability, 10, 9, 10*time.Millisecond, 10, 10, 10*time.Minute, method) + } +} + +func Test_RemoteExecutableCapability_InsufficientWorkflowRequests(t *testing.T) { + ctx := testutils.Context(t) + + responseTest := func(t *testing.T, responseCh commoncap.CapabilityResponse, responseError error) { + assert.NotNil(t, responseError) + } + + timeOut := 10 * time.Minute + + capability := &TestCapability{} + + transmissionSchedule, err := values.NewMap(map[string]any{ + "schedule": transmission.Schedule_AllAtOnce, + "deltaStage": "10ms", + }) + require.NoError(t, err) + + var methods []func(ctx context.Context, caller commoncap.ExecutableCapability) + + methods = append(methods, func(ctx context.Context, caller commoncap.ExecutableCapability) { + executeCapability(ctx, t, caller, transmissionSchedule, responseTest) + }) + + methods = append(methods, func(ctx context.Context, caller commoncap.ExecutableCapability) { + registerWorkflow(ctx, t, caller, transmissionSchedule, func(t *testing.T, responseError error) { + require.Error(t, responseError) + }) + }) + + methods = append(methods, func(ctx context.Context, caller commoncap.ExecutableCapability) { + unregisterWorkflow(ctx, t, caller, transmissionSchedule, func(t *testing.T, responseError error) { + require.Error(t, responseError) + }) + }) + + for _, method := range methods { + testRemoteExecutableCapability(ctx, t, capability, 10, 10, 10*time.Millisecond, 10, 9, timeOut, method) + } +} + func Test_RemoteExecutableCapability_TransmissionSchedules(t *testing.T) { ctx := testutils.Context(t) @@ -63,6 +141,60 @@ func Test_RemoteExecutableCapability_TransmissionSchedules(t *testing.T) { testRemoteExecutableCapability(ctx, t, capability, 10, 9, timeOut, 10, 9, timeOut, method) } +func Test_RemoteExecutionCapability_DonTopologies(t *testing.T) { + ctx := testutils.Context(t) + + responseTest := func(t *testing.T, response commoncap.CapabilityResponse, responseError error) { + require.NoError(t, responseError) + mp, err := response.Value.Unwrap() + require.NoError(t, err) + assert.Equal(t, "aValue1", mp.(map[string]any)["response"].(string)) + } + + transmissionSchedule, err := values.NewMap(map[string]any{ + "schedule": transmission.Schedule_OneAtATime, + "deltaStage": "10ms", + }) + require.NoError(t, err) + + timeOut := 10 * time.Minute + + capability := &TestCapability{} + + var methods []func(ctx context.Context, caller commoncap.ExecutableCapability) + + methods = append(methods, func(ctx context.Context, caller commoncap.ExecutableCapability) { + executeCapability(ctx, t, caller, transmissionSchedule, responseTest) + }) + + methods = append(methods, func(ctx context.Context, caller commoncap.ExecutableCapability) { + registerWorkflow(ctx, t, caller, transmissionSchedule, func(t *testing.T, responseError error) { + require.NoError(t, responseError) + }) + }) + + methods = append(methods, func(ctx context.Context, caller commoncap.ExecutableCapability) { + unregisterWorkflow(ctx, t, caller, transmissionSchedule, func(t *testing.T, responseError error) { + require.NoError(t, responseError) + }) + }) + + for _, method := range methods { + // Test scenarios where the number of submissions is greater than or equal to F + 1 + testRemoteExecutableCapability(ctx, t, capability, 1, 0, timeOut, 1, 0, timeOut, method) + testRemoteExecutableCapability(ctx, t, capability, 4, 3, timeOut, 1, 0, timeOut, method) + testRemoteExecutableCapability(ctx, t, capability, 10, 3, timeOut, 1, 0, timeOut, method) + + testRemoteExecutableCapability(ctx, t, capability, 1, 0, timeOut, 1, 0, timeOut, method) + testRemoteExecutableCapability(ctx, t, capability, 1, 0, timeOut, 4, 3, timeOut, method) + testRemoteExecutableCapability(ctx, t, capability, 1, 0, timeOut, 10, 3, timeOut, method) + + testRemoteExecutableCapability(ctx, t, capability, 4, 3, timeOut, 4, 3, timeOut, method) + testRemoteExecutableCapability(ctx, t, capability, 10, 3, timeOut, 10, 3, timeOut, method) + testRemoteExecutableCapability(ctx, t, capability, 10, 9, timeOut, 10, 9, timeOut, method) + } +} + func Test_RemoteExecutionCapability_CapabilityError(t *testing.T) { ctx := testutils.Context(t) @@ -78,7 +210,19 @@ func Test_RemoteExecutionCapability_CapabilityError(t *testing.T) { methods = append(methods, func(ctx context.Context, caller commoncap.ExecutableCapability) { executeCapability(ctx, t, caller, transmissionSchedule, func(t *testing.T, responseCh commoncap.CapabilityResponse, responseError error) { - assert.Equal(t, "error executing request: failed to execute capability", responseError.Error()) + assert.Equal(t, "error executing request: failed to execute capability: an error", responseError.Error()) + }) + }) + + methods = append(methods, func(ctx context.Context, caller commoncap.ExecutableCapability) { + registerWorkflow(ctx, t, caller, transmissionSchedule, func(t *testing.T, responseError error) { + assert.Equal(t, "error executing request: failed to register to workflow: an error", responseError.Error()) + }) + }) + + methods = append(methods, func(ctx context.Context, caller commoncap.ExecutableCapability) { + unregisterWorkflow(ctx, t, caller, transmissionSchedule, func(t *testing.T, responseError error) { + assert.Equal(t, "error executing request: failed to unregister from workflow: an error", responseError.Error()) }) }) @@ -102,12 +246,24 @@ func Test_RemoteExecutableCapability_RandomCapabilityError(t *testing.T) { methods = append(methods, func(ctx context.Context, caller commoncap.ExecutableCapability) { executeCapability(ctx, t, caller, transmissionSchedule, func(t *testing.T, responseCh commoncap.CapabilityResponse, responseError error) { - assert.Equal(t, "error executing request: failed to execute capability", responseError.Error()) + assert.Equal(t, "error executing request: request expired", responseError.Error()) + }) + }) + + methods = append(methods, func(ctx context.Context, caller commoncap.ExecutableCapability) { + registerWorkflow(ctx, t, caller, transmissionSchedule, func(t *testing.T, responseError error) { + assert.Equal(t, "error executing request: request expired", responseError.Error()) + }) + }) + + methods = append(methods, func(ctx context.Context, caller commoncap.ExecutableCapability) { + unregisterWorkflow(ctx, t, caller, transmissionSchedule, func(t *testing.T, responseError error) { + assert.Equal(t, "error executing request: request expired", responseError.Error()) }) }) for _, method := range methods { - testRemoteExecutableCapability(ctx, t, capability, 10, 9, 1*time.Second, 10, 9, 10*time.Minute, + testRemoteExecutableCapability(ctx, t, capability, 10, 9, 10*time.Millisecond, 10, 9, 10*time.Minute, method) } } @@ -224,9 +380,9 @@ func (a *testAsyncMessageBroker) start(ctx context.Context) error { case <-ctx.Done(): return case msg := <-a.sendCh: - receiverID := toPeerID(msg.Receiver) + receiverId := toPeerID(msg.Receiver) - receiver, ok := a.nodes[receiverID] + receiver, ok := a.nodes[receiverId] if !ok { panic("server not found for peer id") } @@ -299,10 +455,10 @@ func (t *nodeDispatcher) Send(peerID p2ptypes.PeerID, msgBody *remotetypes.Messa return nil } -func (t *nodeDispatcher) SetReceiver(capabilityID string, donID uint32, receiver remotetypes.Receiver) error { +func (t *nodeDispatcher) SetReceiver(capabilityId string, donId uint32, receiver remotetypes.Receiver) error { return nil } -func (t *nodeDispatcher) RemoveReceiver(capabilityID string, donID uint32) {} +func (t *nodeDispatcher) RemoveReceiver(capabilityId string, donId uint32) {} type abstractTestCapability struct { } @@ -407,3 +563,29 @@ func executeCapability(ctx context.Context, t *testing.T, caller commoncap.Execu responseTest(t, response, err) } + +func registerWorkflow(ctx context.Context, t *testing.T, caller commoncap.ExecutableCapability, transmissionSchedule *values.Map, responseTest func(t *testing.T, responseError error)) { + err := caller.RegisterToWorkflow(ctx, commoncap.RegisterToWorkflowRequest{ + Metadata: commoncap.RegistrationMetadata{ + WorkflowID: workflowID1, + ReferenceID: stepReferenceID1, + WorkflowOwner: workflowOwnerID, + }, + Config: transmissionSchedule, + }) + + responseTest(t, err) +} + +func unregisterWorkflow(ctx context.Context, t *testing.T, caller commoncap.ExecutableCapability, transmissionSchedule *values.Map, responseTest func(t *testing.T, responseError error)) { + err := caller.UnregisterFromWorkflow(ctx, commoncap.UnregisterFromWorkflowRequest{ + Metadata: commoncap.RegistrationMetadata{ + WorkflowID: workflowID1, + ReferenceID: stepReferenceID1, + WorkflowOwner: workflowOwnerID, + }, + Config: transmissionSchedule, + }) + + responseTest(t, err) +} diff --git a/core/capabilities/remote/executable/request/client_request.go b/core/capabilities/remote/executable/request/client_request.go index 1d98e3366f1..6b4b9e3a0cd 100644 --- a/core/capabilities/remote/executable/request/client_request.go +++ b/core/capabilities/remote/executable/request/client_request.go @@ -48,6 +48,54 @@ type ClientRequest struct { wg *sync.WaitGroup } +func NewClientRegisterToWorkflowRequest(ctx context.Context, lggr logger.Logger, req commoncap.RegisterToWorkflowRequest, + remoteCapabilityInfo commoncap.CapabilityInfo, localDonInfo capabilities.DON, dispatcher types.Dispatcher, + requestTimeout time.Duration) (*ClientRequest, error) { + rawRequest, err := proto.MarshalOptions{Deterministic: true}.Marshal(pb.RegisterToWorkflowRequestToProto(req)) + if err != nil { + return nil, fmt.Errorf("failed to marshal register to workflow request: %w", err) + } + + workflowID := req.Metadata.WorkflowID + if err := validation.ValidateWorkflowOrExecutionID(workflowID); err != nil { + return nil, fmt.Errorf("workflow ID is invalid: %w", err) + } + + requestID := types.MethodRegisterToWorkflow + ":" + workflowID + + tc := transmission.TransmissionConfig{ + Schedule: transmission.Schedule_AllAtOnce, + DeltaStage: 0, + } + + return newClientRequest(ctx, lggr, requestID, remoteCapabilityInfo, localDonInfo, dispatcher, requestTimeout, + tc, types.MethodRegisterToWorkflow, rawRequest) +} + +func NewClientUnregisterFromWorkflowRequest(ctx context.Context, lggr logger.Logger, req commoncap.UnregisterFromWorkflowRequest, + remoteCapabilityInfo commoncap.CapabilityInfo, localDonInfo capabilities.DON, dispatcher types.Dispatcher, + requestTimeout time.Duration) (*ClientRequest, error) { + rawRequest, err := proto.MarshalOptions{Deterministic: true}.Marshal(pb.UnregisterFromWorkflowRequestToProto(req)) + if err != nil { + return nil, fmt.Errorf("failed to marshal unregister from workflow request: %w", err) + } + + workflowID := req.Metadata.WorkflowID + if err := validation.ValidateWorkflowOrExecutionID(workflowID); err != nil { + return nil, fmt.Errorf("workflow ID is invalid: %w", err) + } + + requestID := types.MethodUnregisterFromWorkflow + ":" + workflowID + + tc := transmission.TransmissionConfig{ + Schedule: transmission.Schedule_AllAtOnce, + DeltaStage: 0, + } + + return newClientRequest(ctx, lggr, requestID, remoteCapabilityInfo, localDonInfo, dispatcher, requestTimeout, + tc, types.MethodUnregisterFromWorkflow, rawRequest) +} + func NewClientExecuteRequest(ctx context.Context, lggr logger.Logger, req commoncap.CapabilityRequest, remoteCapabilityInfo commoncap.CapabilityInfo, localDonInfo capabilities.DON, dispatcher types.Dispatcher, requestTimeout time.Duration) (*ClientRequest, error) { @@ -164,7 +212,7 @@ func (c *ClientRequest) OnMessage(_ context.Context, msg *types.MessageBody) err } if msg.Sender == nil { - return errors.New("sender missing from message") + return fmt.Errorf("sender missing from message") } c.lggr.Debugw("OnMessage called for client request", "messageID", msg.MessageId) diff --git a/core/capabilities/remote/executable/request/client_request_test.go b/core/capabilities/remote/executable/request/client_request_test.go index 212b7265e4f..c46fd1363a0 100644 --- a/core/capabilities/remote/executable/request/client_request_test.go +++ b/core/capabilities/remote/executable/request/client_request_test.go @@ -80,6 +80,15 @@ func Test_ClientRequest_MessageValidation(t *testing.T) { Config: transmissionSchedule, } + registerToWorkflowRequest := commoncap.RegisterToWorkflowRequest{ + Metadata: commoncap.RegistrationMetadata{ + WorkflowID: workflowID1, + WorkflowOwner: "0xaa", + ReferenceID: "refID", + }, + Config: transmissionSchedule, + } + m, err := values.NewMap(map[string]any{"response": "response1"}) require.NoError(t, err) capabilityResponse := commoncap.CapabilityResponse{ @@ -158,7 +167,7 @@ func Test_ClientRequest_MessageValidation(t *testing.T) { nonDonPeer := NewP2PPeerID(t) msg.Sender = nonDonPeer[:] err = request.OnMessage(ctx, msg) - require.Error(t, err) + require.NotNil(t, err) select { case <-request.ResponseChan(): @@ -181,7 +190,7 @@ func Test_ClientRequest_MessageValidation(t *testing.T) { err = request.OnMessage(ctx, msg) require.NoError(t, err) err = request.OnMessage(ctx, msg) - require.Error(t, err) + require.NotNil(t, err) select { case <-request.ResponseChan(): @@ -202,7 +211,7 @@ func Test_ClientRequest_MessageValidation(t *testing.T) { <-dispatcher.msgs <-dispatcher.msgs - assert.Empty(t, dispatcher.msgs) + assert.Equal(t, 0, len(dispatcher.msgs)) msgWithError := &types.MessageBody{ CapabilityId: capInfo.ID, @@ -240,7 +249,7 @@ func Test_ClientRequest_MessageValidation(t *testing.T) { <-dispatcher.msgs <-dispatcher.msgs - assert.Empty(t, dispatcher.msgs) + assert.Equal(t, 0, len(dispatcher.msgs)) msgWithError := &types.MessageBody{ CapabilityId: capInfo.ID, @@ -290,7 +299,7 @@ func Test_ClientRequest_MessageValidation(t *testing.T) { <-dispatcher.msgs <-dispatcher.msgs - assert.Empty(t, dispatcher.msgs) + assert.Equal(t, 0, len(dispatcher.msgs)) msg.Sender = capabilityPeers[0][:] err = request.OnMessage(ctx, msg) @@ -308,6 +317,160 @@ func Test_ClientRequest_MessageValidation(t *testing.T) { assert.Equal(t, resp, values.NewString("response1")) }) + + t.Run("Register To Workflow Request", func(t *testing.T) { + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + dispatcher := &clientRequestTestDispatcher{msgs: make(chan *types.MessageBody, 100)} + request, err := request.NewClientRegisterToWorkflowRequest(ctx, lggr, registerToWorkflowRequest, capInfo, + workflowDonInfo, dispatcher, 10*time.Minute) + require.NoError(t, err) + defer request.Cancel(errors.New("test end")) + + <-dispatcher.msgs + <-dispatcher.msgs + assert.Empty(t, dispatcher.msgs) + + msg := &types.MessageBody{ + CapabilityId: capInfo.ID, + CapabilityDonId: capDonInfo.ID, + CallerDonId: workflowDonInfo.ID, + Method: types.MethodRegisterToWorkflow, + Payload: nil, + MessageId: []byte("messageID"), + } + + msg.Sender = capabilityPeers[0][:] + err = request.OnMessage(ctx, msg) + require.NoError(t, err) + + msg.Sender = capabilityPeers[1][:] + err = request.OnMessage(ctx, msg) + require.NoError(t, err) + + response := <-request.ResponseChan() + require.Nil(t, response.Result) + require.NoError(t, response.Err) + }) + + t.Run("Register To Workflow Request with error", func(t *testing.T) { + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + dispatcher := &clientRequestTestDispatcher{msgs: make(chan *types.MessageBody, 100)} + request, err := request.NewClientRegisterToWorkflowRequest(ctx, lggr, registerToWorkflowRequest, capInfo, + workflowDonInfo, dispatcher, 10*time.Minute) + require.NoError(t, err) + defer request.Cancel(errors.New("test end")) + + <-dispatcher.msgs + <-dispatcher.msgs + assert.Empty(t, dispatcher.msgs) + + msg := &types.MessageBody{ + CapabilityId: capInfo.ID, + CapabilityDonId: capDonInfo.ID, + CallerDonId: workflowDonInfo.ID, + Method: types.MethodRegisterToWorkflow, + Payload: nil, + MessageId: []byte("messageID"), + Error: types.Error_INTERNAL_ERROR, + ErrorMsg: "an error", + } + + msg.Sender = capabilityPeers[0][:] + err = request.OnMessage(ctx, msg) + require.NoError(t, err) + + msg.Sender = capabilityPeers[1][:] + err = request.OnMessage(ctx, msg) + require.NoError(t, err) + + response := <-request.ResponseChan() + require.Nil(t, response.Result) + assert.Equal(t, "an error", response.Err.Error()) + }) + + t.Run("Unregister From Workflow Request", func(t *testing.T) { + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + dispatcher := &clientRequestTestDispatcher{msgs: make(chan *types.MessageBody, 100)} + request, err := request.NewClientUnregisterFromWorkflowRequest(ctx, lggr, commoncap.UnregisterFromWorkflowRequest{ + Metadata: commoncap.RegistrationMetadata{ + WorkflowID: workflowID1, + }, + }, capInfo, workflowDonInfo, dispatcher, 10*time.Minute) + require.NoError(t, err) + defer request.Cancel(errors.New("test end")) + + <-dispatcher.msgs + <-dispatcher.msgs + assert.Empty(t, dispatcher.msgs) + + msg := &types.MessageBody{ + CapabilityId: capInfo.ID, + CapabilityDonId: capDonInfo.ID, + CallerDonId: workflowDonInfo.ID, + Method: types.MethodUnregisterFromWorkflow, + Payload: nil, + MessageId: []byte("messageID"), + } + + msg.Sender = capabilityPeers[0][:] + err = request.OnMessage(ctx, msg) + require.NoError(t, err) + + msg.Sender = capabilityPeers[1][:] + err = request.OnMessage(ctx, msg) + require.NoError(t, err) + + response := <-request.ResponseChan() + require.Nil(t, response.Result) + require.NoError(t, response.Err) + }) + + t.Run("Unregister From Workflow Request with error", func(t *testing.T) { + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + dispatcher := &clientRequestTestDispatcher{msgs: make(chan *types.MessageBody, 100)} + request, err := request.NewClientUnregisterFromWorkflowRequest(ctx, lggr, commoncap.UnregisterFromWorkflowRequest{ + Metadata: commoncap.RegistrationMetadata{ + WorkflowID: workflowID1, + }, + }, capInfo, workflowDonInfo, dispatcher, 10*time.Minute) + require.NoError(t, err) + defer request.Cancel(errors.New("test end")) + + <-dispatcher.msgs + <-dispatcher.msgs + assert.Empty(t, dispatcher.msgs) + + msg := &types.MessageBody{ + CapabilityId: capInfo.ID, + CapabilityDonId: capDonInfo.ID, + CallerDonId: workflowDonInfo.ID, + Method: types.MethodUnregisterFromWorkflow, + Payload: nil, + MessageId: []byte("messageID"), + Error: types.Error_INTERNAL_ERROR, + ErrorMsg: "an error", + } + + msg.Sender = capabilityPeers[0][:] + err = request.OnMessage(ctx, msg) + require.NoError(t, err) + + msg.Sender = capabilityPeers[1][:] + err = request.OnMessage(ctx, msg) + require.NoError(t, err) + + response := <-request.ResponseChan() + require.Nil(t, response.Result) + assert.Equal(t, "an error", response.Err.Error()) + }) } type clientRequestTestDispatcher struct { @@ -334,11 +497,11 @@ func (t *clientRequestTestDispatcher) HealthReport() map[string]error { return nil } -func (t *clientRequestTestDispatcher) SetReceiver(capabilityID string, donID uint32, receiver types.Receiver) error { +func (t *clientRequestTestDispatcher) SetReceiver(capabilityId string, donId uint32, receiver types.Receiver) error { return nil } -func (t *clientRequestTestDispatcher) RemoveReceiver(capabilityID string, donID uint32) {} +func (t *clientRequestTestDispatcher) RemoveReceiver(capabilityId string, donId uint32) {} func (t *clientRequestTestDispatcher) Send(peerID p2ptypes.PeerID, msgBody *types.MessageBody) error { t.msgs <- msgBody diff --git a/core/capabilities/remote/executable/request/server_request.go b/core/capabilities/remote/executable/request/server_request.go index a4f58194328..a4662e93987 100644 --- a/core/capabilities/remote/executable/request/server_request.go +++ b/core/capabilities/remote/executable/request/server_request.go @@ -2,7 +2,6 @@ package request import ( "context" - "errors" "fmt" "sync" "time" @@ -26,7 +25,7 @@ type response struct { type ServerRequest struct { capability capabilities.ExecutableCapability - capabilityPeerID p2ptypes.PeerID + capabilityPeerId p2ptypes.PeerID capabilityID string capabilityDonID uint32 @@ -49,8 +48,6 @@ type ServerRequest struct { lggr logger.Logger } -var errExternalErrorMsg = errors.New("failed to execute capability") - func NewServerRequest(capability capabilities.ExecutableCapability, method string, capabilityID string, capabilityDonID uint32, capabilityPeerID p2ptypes.PeerID, callingDon commoncap.DON, requestID string, @@ -60,7 +57,7 @@ func NewServerRequest(capability capabilities.ExecutableCapability, method strin createdTime: time.Now(), capabilityID: capabilityID, capabilityDonID: capabilityDonID, - capabilityPeerID: capabilityPeerID, + capabilityPeerId: capabilityPeerID, dispatcher: dispatcher, requesters: map[p2ptypes.PeerID]bool{}, responseSentToRequester: map[p2ptypes.PeerID]bool{}, @@ -77,7 +74,7 @@ func (e *ServerRequest) OnMessage(ctx context.Context, msg *types.MessageBody) e defer e.mux.Unlock() if msg.Sender == nil { - return errors.New("sender missing from message") + return fmt.Errorf("sender missing from message") } requester, err := remote.ToPeerID(msg.Sender) @@ -94,6 +91,10 @@ func (e *ServerRequest) OnMessage(ctx context.Context, msg *types.MessageBody) e switch e.method { case types.MethodExecute: e.executeRequest(ctx, msg.Payload, executeCapabilityRequest) + case types.MethodRegisterToWorkflow: + e.executeRequest(ctx, msg.Payload, registerToWorkflow) + case types.MethodUnregisterFromWorkflow: + e.executeRequest(ctx, msg.Payload, unregisterFromWorkflow) default: e.setError(types.Error_INTERNAL_ERROR, "unknown method %s"+e.method) } @@ -202,7 +203,7 @@ func (e *ServerRequest) sendResponse(requester p2ptypes.PeerID) error { CallerDonId: e.callingDon.ID, Method: types.MethodExecute, MessageId: []byte(e.requestMessageID), - Sender: e.capabilityPeerID[:], + Sender: e.capabilityPeerId[:], Receiver: requester[:], } @@ -227,24 +228,52 @@ func executeCapabilityRequest(ctx context.Context, lggr logger.Logger, capabilit payload []byte) ([]byte, error) { capabilityRequest, err := pb.UnmarshalCapabilityRequest(payload) if err != nil { - lggr.Errorw("failed to unmarshal capability request", "err", err) - return nil, errExternalErrorMsg + return nil, fmt.Errorf("failed to unmarshal capability request: %w", err) } lggr.Debugw("executing capability", "metadata", capabilityRequest.Metadata) capResponse, err := capability.Execute(ctx, capabilityRequest) if err != nil { - lggr.Errorw("received execution error", "workflowExecutionID", capabilityRequest.Metadata.WorkflowExecutionID, "error", err) - return nil, errExternalErrorMsg + lggr.Debugw("received execution error", "workflowExecutionID", capabilityRequest.Metadata.WorkflowExecutionID, "error", err) + return nil, fmt.Errorf("failed to execute capability: %w", err) } responsePayload, err := pb.MarshalCapabilityResponse(capResponse) if err != nil { - lggr.Errorw("failed to marshal capability request", "err", err) - return nil, errExternalErrorMsg + return nil, fmt.Errorf("failed to marshal capability response: %w", err) } lggr.Debugw("received execution results", "workflowExecutionID", capabilityRequest.Metadata.WorkflowExecutionID) return responsePayload, nil } + +func registerToWorkflow(ctx context.Context, _ logger.Logger, capability capabilities.ExecutableCapability, + payload []byte) ([]byte, error) { + registerRequest, err := pb.UnmarshalRegisterToWorkflowRequest(payload) + if err != nil { + return nil, fmt.Errorf("failed to unmarshal register to workflow request: %w", err) + } + + err = capability.RegisterToWorkflow(ctx, registerRequest) + if err != nil { + return nil, fmt.Errorf("failed to register to workflow: %w", err) + } + + return nil, nil +} + +func unregisterFromWorkflow(ctx context.Context, _ logger.Logger, capability capabilities.ExecutableCapability, + payload []byte) ([]byte, error) { + unregisterRequest, err := pb.UnmarshalUnregisterFromWorkflowRequest(payload) + if err != nil { + return nil, fmt.Errorf("failed to unmarshal unregister from workflow request: %w", err) + } + + err = capability.UnregisterFromWorkflow(ctx, unregisterRequest) + if err != nil { + return nil, fmt.Errorf("failed to unregister from workflow: %w", err) + } + + return nil, nil +} diff --git a/core/capabilities/remote/executable/request/server_request_test.go b/core/capabilities/remote/executable/request/server_request_test.go index d58b6edf3f2..cbeec833a1f 100644 --- a/core/capabilities/remote/executable/request/server_request_test.go +++ b/core/capabilities/remote/executable/request/server_request_test.go @@ -136,9 +136,9 @@ func Test_ServerRequest_MessageValidation(t *testing.T) { require.NoError(t, err) assert.Len(t, dispatcher.msgs, 2) assert.Equal(t, types.Error_INTERNAL_ERROR, dispatcher.msgs[0].Error) - assert.Equal(t, "failed to execute capability", dispatcher.msgs[0].ErrorMsg) + assert.Equal(t, "failed to execute capability: an error", dispatcher.msgs[0].ErrorMsg) assert.Equal(t, types.Error_INTERNAL_ERROR, dispatcher.msgs[1].Error) - assert.Equal(t, "failed to execute capability", dispatcher.msgs[1].ErrorMsg) + assert.Equal(t, "failed to execute capability: an error", dispatcher.msgs[1].ErrorMsg) }) t.Run("Execute capability", func(t *testing.T) { @@ -165,6 +165,107 @@ func Test_ServerRequest_MessageValidation(t *testing.T) { assert.Equal(t, types.Error_OK, dispatcher.msgs[0].Error) assert.Equal(t, types.Error_OK, dispatcher.msgs[1].Error) }) + t.Run("Register to workflow request", func(t *testing.T) { + dispatcher := &testDispatcher{} + request := request.NewServerRequest(capability, types.MethodRegisterToWorkflow, "capabilityID", 2, + capabilityPeerID, callingDon, "requestMessageID", dispatcher, 10*time.Minute, lggr) + + err := sendValidRequest(request, workflowPeers, capabilityPeerID, rawRequest) + require.NoError(t, err) + + err = request.OnMessage(context.Background(), &types.MessageBody{ + Version: 0, + Sender: workflowPeers[1][:], + Receiver: capabilityPeerID[:], + MessageId: []byte("workflowID" + "workflowExecutionID"), + CapabilityId: "capabilityID", + CapabilityDonId: 2, + CallerDonId: 1, + Method: types.MethodRegisterToWorkflow, + Payload: rawRequest, + }) + require.NoError(t, err) + assert.Len(t, dispatcher.msgs, 2) + assert.Equal(t, types.Error_OK, dispatcher.msgs[0].Error) + assert.Equal(t, types.Error_OK, dispatcher.msgs[1].Error) + }) + t.Run("Register to workflow request errors", func(t *testing.T) { + dispatcher := &testDispatcher{} + req := request.NewServerRequest(TestErrorCapability{}, types.MethodRegisterToWorkflow, "capabilityID", 2, + capabilityPeerID, callingDon, "requestMessageID", dispatcher, 10*time.Minute, lggr) + + err := sendValidRequest(req, workflowPeers, capabilityPeerID, rawRequest) + require.NoError(t, err) + + err = req.OnMessage(context.Background(), &types.MessageBody{ + Version: 0, + Sender: workflowPeers[1][:], + Receiver: capabilityPeerID[:], + MessageId: []byte("workflowID" + "workflowExecutionID"), + CapabilityId: "capabilityID", + CapabilityDonId: 2, + CallerDonId: 1, + Method: types.MethodRegisterToWorkflow, + Payload: rawRequest, + }) + require.NoError(t, err) + assert.Len(t, dispatcher.msgs, 2) + assert.Equal(t, types.Error_INTERNAL_ERROR, dispatcher.msgs[0].Error) + assert.Equal(t, "failed to register to workflow: an error", dispatcher.msgs[0].ErrorMsg) + assert.Equal(t, types.Error_INTERNAL_ERROR, dispatcher.msgs[1].Error) + assert.Equal(t, "failed to register to workflow: an error", dispatcher.msgs[1].ErrorMsg) + }) + t.Run("Unregister from workflow request", func(t *testing.T) { + dispatcher := &testDispatcher{} + request := request.NewServerRequest(capability, types.MethodUnregisterFromWorkflow, "capabilityID", 2, + capabilityPeerID, callingDon, "requestMessageID", dispatcher, 10*time.Minute, lggr) + + err := sendValidRequest(request, workflowPeers, capabilityPeerID, rawRequest) + require.NoError(t, err) + + err = request.OnMessage(context.Background(), &types.MessageBody{ + Version: 0, + Sender: workflowPeers[1][:], + Receiver: capabilityPeerID[:], + MessageId: []byte("workflowID" + "workflowExecutionID"), + CapabilityId: "capabilityID", + CapabilityDonId: 2, + CallerDonId: 1, + Method: types.MethodUnregisterFromWorkflow, + Payload: rawRequest, + }) + require.NoError(t, err) + assert.Len(t, dispatcher.msgs, 2) + assert.Equal(t, types.Error_OK, dispatcher.msgs[0].Error) + assert.Equal(t, types.Error_OK, dispatcher.msgs[1].Error) + }) + + t.Run("Unregister from workflow request errors", func(t *testing.T) { + dispatcher := &testDispatcher{} + req := request.NewServerRequest(TestErrorCapability{}, types.MethodUnregisterFromWorkflow, "capabilityID", 2, + capabilityPeerID, callingDon, "requestMessageID", dispatcher, 10*time.Minute, lggr) + + err := sendValidRequest(req, workflowPeers, capabilityPeerID, rawRequest) + require.NoError(t, err) + + err = req.OnMessage(context.Background(), &types.MessageBody{ + Version: 0, + Sender: workflowPeers[1][:], + Receiver: capabilityPeerID[:], + MessageId: []byte("workflowID" + "workflowExecutionID"), + CapabilityId: "capabilityID", + CapabilityDonId: 2, + CallerDonId: 1, + Method: types.MethodUnregisterFromWorkflow, + Payload: rawRequest, + }) + require.NoError(t, err) + assert.Len(t, dispatcher.msgs, 2) + assert.Equal(t, types.Error_INTERNAL_ERROR, dispatcher.msgs[0].Error) + assert.Equal(t, "failed to unregister from workflow: an error", dispatcher.msgs[0].ErrorMsg) + assert.Equal(t, types.Error_INTERNAL_ERROR, dispatcher.msgs[1].Error) + assert.Equal(t, "failed to unregister from workflow: an error", dispatcher.msgs[1].ErrorMsg) + }) } type serverRequest interface { @@ -210,11 +311,11 @@ func (t *testDispatcher) HealthReport() map[string]error { return nil } -func (t *testDispatcher) SetReceiver(capabilityID string, donID uint32, receiver types.Receiver) error { +func (t *testDispatcher) SetReceiver(capabilityId string, donId uint32, receiver types.Receiver) error { return nil } -func (t *testDispatcher) RemoveReceiver(capabilityID string, donID uint32) {} +func (t *testDispatcher) RemoveReceiver(capabilityId string, donId uint32) {} func (t *testDispatcher) Send(peerID p2ptypes.PeerID, msgBody *types.MessageBody) error { t.msgs = append(t.msgs, msgBody) diff --git a/core/capabilities/remote/executable/server.go b/core/capabilities/remote/executable/server.go index 5d6a0aff490..b767a2d7030 100644 --- a/core/capabilities/remote/executable/server.go +++ b/core/capabilities/remote/executable/server.go @@ -4,7 +4,6 @@ import ( "context" "crypto/sha256" "encoding/hex" - "errors" "fmt" "sync" "time" @@ -88,11 +87,7 @@ func (r *server) Start(ctx context.Context) error { r.wg.Add(1) go func() { defer r.wg.Done() - tickerInterval := expiryCheckInterval - if r.requestTimeout < tickerInterval { - tickerInterval = r.requestTimeout - } - ticker := time.NewTicker(tickerInterval) + ticker := time.NewTicker(r.requestTimeout) defer ticker.Stop() r.lggr.Info("executable capability server started") for { @@ -123,7 +118,7 @@ func (r *server) expireRequests() { for requestID, executeReq := range r.requestIDToRequest { if executeReq.request.Expired() { - err := executeReq.request.Cancel(types.Error_TIMEOUT, "request expired by executable server") + err := executeReq.request.Cancel(types.Error_TIMEOUT, "request expired") if err != nil { r.lggr.Errorw("failed to cancel request", "request", executeReq, "err", err) } @@ -138,13 +133,12 @@ func (r *server) Receive(ctx context.Context, msg *types.MessageBody) { defer r.receiveLock.Unlock() switch msg.Method { - case types.MethodExecute: + case types.MethodExecute, types.MethodRegisterToWorkflow, types.MethodUnregisterFromWorkflow: default: r.lggr.Errorw("received request for unsupported method type", "method", remote.SanitizeLogString(msg.Method)) - return } - messageID, err := GetMessageID(msg) + messageId, err := GetMessageID(msg) if err != nil { r.lggr.Errorw("invalid message id", "err", err, "id", remote.SanitizeLogString(string(msg.MessageId))) return @@ -158,21 +152,21 @@ func (r *server) Receive(ctx context.Context, msg *types.MessageBody) { // A request is uniquely identified by the message id and the hash of the payload to prevent a malicious // actor from sending a different payload with the same message id - requestID := messageID + hex.EncodeToString(msgHash[:]) + requestID := messageId + hex.EncodeToString(msgHash[:]) r.lggr.Debugw("received request", "msgId", msg.MessageId, "requestID", requestID) - if requestIDs, ok := r.messageIDToRequestIDsCount[messageID]; ok { - requestIDs[requestID]++ + if requestIDs, ok := r.messageIDToRequestIDsCount[messageId]; ok { + requestIDs[requestID] = requestIDs[requestID] + 1 } else { - r.messageIDToRequestIDsCount[messageID] = map[string]int{requestID: 1} + r.messageIDToRequestIDsCount[messageId] = map[string]int{requestID: 1} } - requestIDs := r.messageIDToRequestIDsCount[messageID] + requestIDs := r.messageIDToRequestIDsCount[messageId] if len(requestIDs) > 1 { // This is a potential attack vector as well as a situation that will occur if the client is sending non-deterministic payloads // so a warning is logged - r.lggr.Warnw("received messages with the same id and different payloads", "messageID", messageID, "lenRequestIDs", len(requestIDs)) + r.lggr.Warnw("received messages with the same id and different payloads", "messageID", messageId, "lenRequestIDs", len(requestIDs)) } if _, ok := r.requestIDToRequest[requestID]; !ok { @@ -184,8 +178,8 @@ func (r *server) Receive(ctx context.Context, msg *types.MessageBody) { r.requestIDToRequest[requestID] = requestAndMsgID{ request: request.NewServerRequest(r.underlying, msg.Method, r.capInfo.ID, r.localDonInfo.ID, r.peerID, - callingDon, messageID, r.dispatcher, r.requestTimeout, r.lggr), - messageID: messageID, + callingDon, messageId, r.dispatcher, r.requestTimeout, r.lggr), + messageID: messageId, } } @@ -220,7 +214,7 @@ func (r *server) getMessageHash(msg *types.MessageBody) ([32]byte, error) { func GetMessageID(msg *types.MessageBody) (string, error) { idStr := string(msg.MessageId) if !validation.IsValidID(idStr) { - return "", errors.New("invalid message id") + return "", fmt.Errorf("invalid message id") } return idStr, nil } diff --git a/core/capabilities/remote/executable/server_test.go b/core/capabilities/remote/executable/server_test.go index c92a996f846..1fb5c2dd413 100644 --- a/core/capabilities/remote/executable/server_test.go +++ b/core/capabilities/remote/executable/server_test.go @@ -83,6 +83,89 @@ func Test_Server_Execute_RespondsAfterSufficientRequests(t *testing.T) { closeServices(t, srvcs) } +func Test_Server_RegisterToWorkflow_RespondsAfterSufficientRequests(t *testing.T) { + ctx := testutils.Context(t) + + numCapabilityPeers := 4 + + callers, srvcs := testRemoteExecutableCapabilityServer(ctx, t, &commoncap.RemoteExecutableConfig{}, &TestCapability{}, 10, 9, numCapabilityPeers, 3, 10*time.Minute) + + for _, caller := range callers { + err := caller.RegisterToWorkflow(context.Background(), commoncap.RegisterToWorkflowRequest{ + Metadata: commoncap.RegistrationMetadata{ + WorkflowID: workflowID1, + ReferenceID: stepReferenceID1, + WorkflowOwner: workflowOwnerID, + }, + }) + + require.NoError(t, err) + } + + for _, caller := range callers { + for i := 0; i < numCapabilityPeers; i++ { + msg := <-caller.receivedMessages + assert.Equal(t, remotetypes.Error_OK, msg.Error) + } + } + closeServices(t, srvcs) +} + +func Test_Server_RegisterToWorkflow_Error(t *testing.T) { + ctx := testutils.Context(t) + + numCapabilityPeers := 4 + + callers, srvcs := testRemoteExecutableCapabilityServer(ctx, t, &commoncap.RemoteExecutableConfig{}, &TestErrorCapability{}, 10, 9, numCapabilityPeers, 3, 10*time.Minute) + + for _, caller := range callers { + err := caller.RegisterToWorkflow(context.Background(), commoncap.RegisterToWorkflowRequest{ + Metadata: commoncap.RegistrationMetadata{ + WorkflowID: workflowID1, + ReferenceID: stepReferenceID1, + WorkflowOwner: workflowOwnerID, + }, + }) + + require.NoError(t, err) + } + + for _, caller := range callers { + for i := 0; i < numCapabilityPeers; i++ { + msg := <-caller.receivedMessages + assert.Equal(t, remotetypes.Error_INTERNAL_ERROR, msg.Error) + } + } + closeServices(t, srvcs) +} + +func Test_Server_UnregisterFromWorkflow_RespondsAfterSufficientRequests(t *testing.T) { + ctx := testutils.Context(t) + + numCapabilityPeers := 4 + + callers, srvcs := testRemoteExecutableCapabilityServer(ctx, t, &commoncap.RemoteExecutableConfig{}, &TestCapability{}, 10, 9, numCapabilityPeers, 3, 10*time.Minute) + + for _, caller := range callers { + err := caller.UnregisterFromWorkflow(context.Background(), commoncap.UnregisterFromWorkflowRequest{ + Metadata: commoncap.RegistrationMetadata{ + WorkflowID: workflowID1, + ReferenceID: stepReferenceID1, + WorkflowOwner: workflowOwnerID, + }, + }) + require.NoError(t, err) + } + + for _, caller := range callers { + for i := 0; i < numCapabilityPeers; i++ { + msg := <-caller.receivedMessages + assert.Equal(t, remotetypes.Error_OK, msg.Error) + } + } + closeServices(t, srvcs) +} + func Test_Server_InsufficientCallers(t *testing.T) { ctx := testutils.Context(t) @@ -236,6 +319,62 @@ func (r *serverTestClient) Info(ctx context.Context) (commoncap.CapabilityInfo, panic("not implemented") } +func (r *serverTestClient) RegisterToWorkflow(ctx context.Context, req commoncap.RegisterToWorkflowRequest) error { + rawRequest, err := pb.MarshalRegisterToWorkflowRequest(req) + if err != nil { + return err + } + + messageID := remotetypes.MethodRegisterToWorkflow + ":" + req.Metadata.WorkflowID + + for _, node := range r.capabilityDonInfo.Members { + message := &remotetypes.MessageBody{ + CapabilityId: "capability-id", + CapabilityDonId: 1, + CallerDonId: 2, + Method: remotetypes.MethodRegisterToWorkflow, + Payload: rawRequest, + MessageId: []byte(messageID), + Sender: r.peerID[:], + Receiver: node[:], + } + + if err = r.dispatcher.Send(node, message); err != nil { + return err + } + } + + return nil +} + +func (r *serverTestClient) UnregisterFromWorkflow(ctx context.Context, req commoncap.UnregisterFromWorkflowRequest) error { + rawRequest, err := pb.MarshalUnregisterFromWorkflowRequest(req) + if err != nil { + return err + } + + messageID := remotetypes.MethodUnregisterFromWorkflow + ":" + req.Metadata.WorkflowID + + for _, node := range r.capabilityDonInfo.Members { + message := &remotetypes.MessageBody{ + CapabilityId: "capability-id", + CapabilityDonId: 1, + CallerDonId: 2, + Method: remotetypes.MethodUnregisterFromWorkflow, + Payload: rawRequest, + MessageId: []byte(messageID), + Sender: r.peerID[:], + Receiver: node[:], + } + + if err = r.dispatcher.Send(node, message); err != nil { + return err + } + } + + return nil +} + func (r *serverTestClient) Execute(ctx context.Context, req commoncap.CapabilityRequest) (<-chan commoncap.CapabilityResponse, error) { rawRequest, err := pb.MarshalCapabilityRequest(req) if err != nil { diff --git a/core/capabilities/remote/messagecache/message_cache.go b/core/capabilities/remote/message_cache.go similarity index 81% rename from core/capabilities/remote/messagecache/message_cache.go rename to core/capabilities/remote/message_cache.go index 28ef57ab875..f3a3a79b2c6 100644 --- a/core/capabilities/remote/messagecache/message_cache.go +++ b/core/capabilities/remote/message_cache.go @@ -1,9 +1,9 @@ -package messagecache +package remote // MessageCache is a simple store for messages, grouped by event ID and peer ID. // It is used to collect messages from multiple peers until they are ready for aggregation // based on quantity and freshness. -type MessageCache[EventID comparable, PeerID comparable] struct { +type messageCache[EventID comparable, PeerID comparable] struct { events map[EventID]*eventState[PeerID] } @@ -18,14 +18,14 @@ type msgState struct { payload []byte } -func NewMessageCache[EventID comparable, PeerID comparable]() *MessageCache[EventID, PeerID] { - return &MessageCache[EventID, PeerID]{ +func NewMessageCache[EventID comparable, PeerID comparable]() *messageCache[EventID, PeerID] { + return &messageCache[EventID, PeerID]{ events: make(map[EventID]*eventState[PeerID]), } } // Insert or overwrite a message for . Return creation timestamp of the event. -func (c *MessageCache[EventID, PeerID]) Insert(eventID EventID, peerID PeerID, timestamp int64, payload []byte) int64 { +func (c *messageCache[EventID, PeerID]) Insert(eventID EventID, peerID PeerID, timestamp int64, payload []byte) int64 { if _, ok := c.events[eventID]; !ok { c.events[eventID] = &eventState[PeerID]{ peerMsgs: make(map[PeerID]*msgState), @@ -43,7 +43,7 @@ func (c *MessageCache[EventID, PeerID]) Insert(eventID EventID, peerID PeerID, t // received more recently than . // Return all messages that satisfy the above condition. // Ready() will return true at most once per event if is true. -func (c *MessageCache[EventID, PeerID]) Ready(eventID EventID, minCount uint32, minTimestamp int64, once bool) (bool, [][]byte) { +func (c *messageCache[EventID, PeerID]) Ready(eventID EventID, minCount uint32, minTimestamp int64, once bool) (bool, [][]byte) { ev, ok := c.events[eventID] if !ok { return false, nil @@ -51,7 +51,6 @@ func (c *MessageCache[EventID, PeerID]) Ready(eventID EventID, minCount uint32, if ev.wasReady && once { return false, nil } - //nolint:gosec // G115 if uint32(len(ev.peerMsgs)) < minCount { return false, nil } @@ -70,13 +69,13 @@ func (c *MessageCache[EventID, PeerID]) Ready(eventID EventID, minCount uint32, return false, nil } -func (c *MessageCache[EventID, PeerID]) Delete(eventID EventID) { +func (c *messageCache[EventID, PeerID]) Delete(eventID EventID) { delete(c.events, eventID) } // Return the number of events deleted. // Scans all keys, which might be slow for large caches. -func (c *MessageCache[EventID, PeerID]) DeleteOlderThan(cutoffTimestamp int64) int { +func (c *messageCache[EventID, PeerID]) DeleteOlderThan(cutoffTimestamp int64) int { nDeleted := 0 for id, event := range c.events { if event.creationTimestamp < cutoffTimestamp { diff --git a/core/capabilities/remote/messagecache/message_cache_test.go b/core/capabilities/remote/message_cache_test.go similarity index 59% rename from core/capabilities/remote/messagecache/message_cache_test.go rename to core/capabilities/remote/message_cache_test.go index 2d059adef32..5ca909ca4ec 100644 --- a/core/capabilities/remote/messagecache/message_cache_test.go +++ b/core/capabilities/remote/message_cache_test.go @@ -1,53 +1,53 @@ -package messagecache_test +package remote_test import ( "testing" "github.com/stretchr/testify/require" - "github.com/smartcontractkit/chainlink/v2/core/capabilities/remote/messagecache" + "github.com/smartcontractkit/chainlink/v2/core/capabilities/remote" ) const ( - eventID1 = "event1" - eventID2 = "event2" - peerID1 = "peer1" - peerID2 = "peer2" + eventId1 = "event1" + eventId2 = "event2" + peerId1 = "peer1" + peerId2 = "peer2" payloadA = "payloadA" ) func TestMessageCache_InsertReady(t *testing.T) { - cache := messagecache.NewMessageCache[string, string]() + cache := remote.NewMessageCache[string, string]() // not ready with one message - ts := cache.Insert(eventID1, peerID1, 100, []byte(payloadA)) + ts := cache.Insert(eventId1, peerId1, 100, []byte(payloadA)) require.Equal(t, int64(100), ts) - ready, _ := cache.Ready(eventID1, 2, 100, true) + ready, _ := cache.Ready(eventId1, 2, 100, true) require.False(t, ready) // not ready with two messages but only one fresh enough - ts = cache.Insert(eventID1, peerID2, 200, []byte(payloadA)) + ts = cache.Insert(eventId1, peerId2, 200, []byte(payloadA)) require.Equal(t, int64(100), ts) - ready, _ = cache.Ready(eventID1, 2, 150, true) + ready, _ = cache.Ready(eventId1, 2, 150, true) require.False(t, ready) // ready with two messages (once only) - ready, messages := cache.Ready(eventID1, 2, 100, true) + ready, messages := cache.Ready(eventId1, 2, 100, true) require.True(t, ready) require.Equal(t, []byte(payloadA), messages[0]) require.Equal(t, []byte(payloadA), messages[1]) // not ready again for the same event ID - ready, _ = cache.Ready(eventID1, 2, 100, true) + ready, _ = cache.Ready(eventId1, 2, 100, true) require.False(t, ready) } func TestMessageCache_DeleteOlderThan(t *testing.T) { - cache := messagecache.NewMessageCache[string, string]() + cache := remote.NewMessageCache[string, string]() - ts := cache.Insert(eventID1, peerID1, 100, []byte(payloadA)) + ts := cache.Insert(eventId1, peerId1, 100, []byte(payloadA)) require.Equal(t, int64(100), ts) - ts = cache.Insert(eventID2, peerID2, 200, []byte(payloadA)) + ts = cache.Insert(eventId2, peerId2, 200, []byte(payloadA)) require.Equal(t, int64(200), ts) deleted := cache.DeleteOlderThan(150) diff --git a/core/capabilities/remote/trigger_publisher.go b/core/capabilities/remote/trigger_publisher.go index 24bd26757ac..315959605e8 100644 --- a/core/capabilities/remote/trigger_publisher.go +++ b/core/capabilities/remote/trigger_publisher.go @@ -10,8 +10,6 @@ import ( commoncap "github.com/smartcontractkit/chainlink-common/pkg/capabilities" "github.com/smartcontractkit/chainlink-common/pkg/capabilities/pb" "github.com/smartcontractkit/chainlink-common/pkg/services" - "github.com/smartcontractkit/chainlink/v2/core/capabilities/remote/aggregation" - "github.com/smartcontractkit/chainlink/v2/core/capabilities/remote/messagecache" "github.com/smartcontractkit/chainlink/v2/core/capabilities/remote/types" "github.com/smartcontractkit/chainlink/v2/core/capabilities/validation" "github.com/smartcontractkit/chainlink/v2/core/logger" @@ -32,7 +30,7 @@ type triggerPublisher struct { workflowDONs map[uint32]commoncap.DON membersCache map[uint32]map[p2ptypes.PeerID]bool dispatcher types.Dispatcher - messageCache *messagecache.MessageCache[registrationKey, p2ptypes.PeerID] + messageCache *messageCache[registrationKey, p2ptypes.PeerID] registrations map[registrationKey]*pubRegState mu sync.RWMutex // protects messageCache and registrations batchingQueue map[[32]byte]*batchedResponse @@ -44,8 +42,8 @@ type triggerPublisher struct { } type registrationKey struct { - callerDonID uint32 - workflowID string + callerDonId uint32 + workflowId string } type pubRegState struct { @@ -86,7 +84,7 @@ func NewTriggerPublisher(config *commoncap.RemoteTriggerConfig, underlying commo workflowDONs: workflowDONs, membersCache: membersCache, dispatcher: dispatcher, - messageCache: messagecache.NewMessageCache[registrationKey, p2ptypes.PeerID](), + messageCache: NewMessageCache[registrationKey, p2ptypes.PeerID](), registrations: make(map[registrationKey]*pubRegState), batchingQueue: make(map[[32]byte]*batchedResponse), batchingEnabled: config.MaxBatchSize > 1 && config.BatchCollectionPeriod >= minAllowedBatchCollectionPeriod, @@ -150,7 +148,7 @@ func (p *triggerPublisher) Receive(_ context.Context, msg *types.MessageBody) { p.lggr.Debugw("not ready to aggregate yet", "capabilityId", p.capInfo.ID, "workflowId", req.Metadata.WorkflowID, "minRequired", minRequired) return } - aggregated, err := aggregation.AggregateModeRaw(payloads, uint32(callerDon.F+1)) + aggregated, err := AggregateModeRaw(payloads, uint32(callerDon.F+1)) if err != nil { p.lggr.Errorw("failed to aggregate trigger registrations", "capabilityId", p.capInfo.ID, "workflowId", req.Metadata.WorkflowID, "err", err) return @@ -191,14 +189,14 @@ func (p *triggerPublisher) registrationCleanupLoop() { now := time.Now().UnixMilli() p.mu.Lock() for key, req := range p.registrations { - callerDon := p.workflowDONs[key.callerDonID] + callerDon := p.workflowDONs[key.callerDonId] ready, _ := p.messageCache.Ready(key, uint32(2*callerDon.F+1), now-p.config.RegistrationExpiry.Milliseconds(), false) if !ready { - p.lggr.Infow("trigger registration expired", "capabilityId", p.capInfo.ID, "callerDonID", key.callerDonID, "workflowId", key.workflowID) + p.lggr.Infow("trigger registration expired", "capabilityId", p.capInfo.ID, "callerDonID", key.callerDonId, "workflowId", key.workflowId) ctx, cancel := p.stopCh.NewCtx() err := p.underlying.UnregisterTrigger(ctx, req.request) cancel() - p.lggr.Infow("unregistered trigger", "capabilityId", p.capInfo.ID, "callerDonID", key.callerDonID, "workflowId", key.workflowID, "err", err) + p.lggr.Infow("unregistered trigger", "capabilityId", p.capInfo.ID, "callerDonID", key.callerDonId, "workflowId", key.workflowId, "err", err) // after calling UnregisterTrigger, the underlying trigger will not send any more events to the channel delete(p.registrations, key) p.messageCache.Delete(key) @@ -217,11 +215,11 @@ func (p *triggerPublisher) triggerEventLoop(callbackCh <-chan commoncap.TriggerR return case response, ok := <-callbackCh: if !ok { - p.lggr.Infow("triggerEventLoop channel closed", "capabilityId", p.capInfo.ID, "workflowId", key.workflowID) + p.lggr.Infow("triggerEventLoop channel closed", "capabilityId", p.capInfo.ID, "workflowId", key.workflowId) return } triggerEvent := response.Event - p.lggr.Debugw("received trigger event", "capabilityId", p.capInfo.ID, "workflowId", key.workflowID, "triggerEventID", triggerEvent.ID) + p.lggr.Debugw("received trigger event", "capabilityId", p.capInfo.ID, "workflowId", key.workflowId, "triggerEventID", triggerEvent.ID) marshaledResponse, err := pb.MarshalTriggerResponse(response) if err != nil { p.lggr.Debugw("can't marshal trigger event", "err", err) @@ -234,9 +232,9 @@ func (p *triggerPublisher) triggerEventLoop(callbackCh <-chan commoncap.TriggerR // a single-element "batch" p.sendBatch(&batchedResponse{ rawResponse: marshaledResponse, - callerDonID: key.callerDonID, + callerDonID: key.callerDonId, triggerEventID: triggerEvent.ID, - workflowIDs: []string{key.workflowID}, + workflowIDs: []string{key.workflowId}, }) } } @@ -246,7 +244,7 @@ func (p *triggerPublisher) triggerEventLoop(callbackCh <-chan commoncap.TriggerR func (p *triggerPublisher) enqueueForBatching(rawResponse []byte, key registrationKey, triggerEventID string) { // put in batching queue, group by hash(callerDonId, triggerEventID, response) combined := make([]byte, 4) - binary.LittleEndian.PutUint32(combined, key.callerDonID) + binary.LittleEndian.PutUint32(combined, key.callerDonId) combined = append(combined, []byte(triggerEventID)...) combined = append(combined, rawResponse...) sha := sha256.Sum256(combined) @@ -255,13 +253,13 @@ func (p *triggerPublisher) enqueueForBatching(rawResponse []byte, key registrati if !exists { elem = &batchedResponse{ rawResponse: rawResponse, - callerDonID: key.callerDonID, + callerDonID: key.callerDonId, triggerEventID: triggerEventID, - workflowIDs: []string{key.workflowID}, + workflowIDs: []string{key.workflowId}, } p.batchingQueue[sha] = elem } else { - elem.workflowIDs = append(elem.workflowIDs, key.workflowID) + elem.workflowIDs = append(elem.workflowIDs, key.workflowId) } p.bqMu.Unlock() } diff --git a/core/capabilities/remote/trigger_subscriber.go b/core/capabilities/remote/trigger_subscriber.go index 7edcbf5eba7..2638d9ca5f3 100644 --- a/core/capabilities/remote/trigger_subscriber.go +++ b/core/capabilities/remote/trigger_subscriber.go @@ -9,8 +9,6 @@ import ( commoncap "github.com/smartcontractkit/chainlink-common/pkg/capabilities" "github.com/smartcontractkit/chainlink-common/pkg/capabilities/pb" "github.com/smartcontractkit/chainlink-common/pkg/services" - "github.com/smartcontractkit/chainlink/v2/core/capabilities/remote/aggregation" - "github.com/smartcontractkit/chainlink/v2/core/capabilities/remote/messagecache" "github.com/smartcontractkit/chainlink/v2/core/capabilities/remote/types" "github.com/smartcontractkit/chainlink/v2/core/logger" p2ptypes "github.com/smartcontractkit/chainlink/v2/core/services/p2p/types" @@ -31,7 +29,7 @@ type triggerSubscriber struct { localDonInfo commoncap.DON dispatcher types.Dispatcher aggregator types.Aggregator - messageCache *messagecache.MessageCache[triggerEventKey, p2ptypes.PeerID] + messageCache *messageCache[triggerEventKey, p2ptypes.PeerID] registeredWorkflows map[string]*subRegState mu sync.RWMutex // protects registeredWorkflows and messageCache stopCh services.StopChan @@ -40,8 +38,8 @@ type triggerSubscriber struct { } type triggerEventKey struct { - triggerEventID string - workflowID string + triggerEventId string + workflowId string } type subRegState struct { @@ -67,7 +65,7 @@ const ( func NewTriggerSubscriber(config *commoncap.RemoteTriggerConfig, capInfo commoncap.CapabilityInfo, capDonInfo commoncap.DON, localDonInfo commoncap.DON, dispatcher types.Dispatcher, aggregator types.Aggregator, lggr logger.Logger) *triggerSubscriber { if aggregator == nil { lggr.Warnw("no aggregator provided, using default MODE aggregator", "capabilityId", capInfo.ID) - aggregator = aggregation.NewDefaultModeAggregator(uint32(capDonInfo.F + 1)) + aggregator = NewDefaultModeAggregator(uint32(capDonInfo.F + 1)) } if config == nil { lggr.Info("no config provided, using default values") @@ -86,7 +84,7 @@ func NewTriggerSubscriber(config *commoncap.RemoteTriggerConfig, capInfo commonc localDonInfo: localDonInfo, dispatcher: dispatcher, aggregator: aggregator, - messageCache: messagecache.NewMessageCache[triggerEventKey, p2ptypes.PeerID](), + messageCache: NewMessageCache[triggerEventKey, p2ptypes.PeerID](), registeredWorkflows: make(map[string]*subRegState), stopCh: make(services.StopChan), lggr: lggr.Named("TriggerSubscriber"), @@ -202,17 +200,17 @@ func (s *triggerSubscriber) Receive(_ context.Context, msg *types.MessageBody) { s.lggr.Errorw("received message with too many workflow IDs - truncating", "capabilityId", s.capInfo.ID, "nWorkflows", len(meta.WorkflowIds), "sender", sender) meta.WorkflowIds = meta.WorkflowIds[:maxBatchedWorkflowIDs] } - for _, workflowID := range meta.WorkflowIds { + for _, workflowId := range meta.WorkflowIds { s.mu.RLock() - registration, found := s.registeredWorkflows[workflowID] + registration, found := s.registeredWorkflows[workflowId] s.mu.RUnlock() if !found { - s.lggr.Errorw("received message for unregistered workflow", "capabilityId", s.capInfo.ID, "workflowID", SanitizeLogString(workflowID), "sender", sender) + s.lggr.Errorw("received message for unregistered workflow", "capabilityId", s.capInfo.ID, "workflowID", SanitizeLogString(workflowId), "sender", sender) continue } key := triggerEventKey{ - triggerEventID: meta.TriggerEventId, - workflowID: workflowID, + triggerEventId: meta.TriggerEventId, + workflowId: workflowId, } nowMs := time.Now().UnixMilli() s.mu.Lock() @@ -220,17 +218,17 @@ func (s *triggerSubscriber) Receive(_ context.Context, msg *types.MessageBody) { ready, payloads := s.messageCache.Ready(key, s.config.MinResponsesToAggregate, nowMs-s.config.MessageExpiry.Milliseconds(), true) s.mu.Unlock() if nowMs-creationTs > s.config.RegistrationExpiry.Milliseconds() { - s.lggr.Warnw("received trigger event for an expired ID", "triggerEventID", meta.TriggerEventId, "capabilityId", s.capInfo.ID, "workflowId", workflowID, "sender", sender) + s.lggr.Warnw("received trigger event for an expired ID", "triggerEventID", meta.TriggerEventId, "capabilityId", s.capInfo.ID, "workflowId", workflowId, "sender", sender) continue } if ready { - s.lggr.Debugw("trigger event ready to aggregate", "triggerEventID", meta.TriggerEventId, "capabilityId", s.capInfo.ID, "workflowId", workflowID) + s.lggr.Debugw("trigger event ready to aggregate", "triggerEventID", meta.TriggerEventId, "capabilityId", s.capInfo.ID, "workflowId", workflowId) aggregatedResponse, err := s.aggregator.Aggregate(meta.TriggerEventId, payloads) if err != nil { - s.lggr.Errorw("failed to aggregate responses", "triggerEventID", meta.TriggerEventId, "capabilityId", s.capInfo.ID, "workflowId", workflowID, "err", err) + s.lggr.Errorw("failed to aggregate responses", "triggerEventID", meta.TriggerEventId, "capabilityId", s.capInfo.ID, "workflowId", workflowId, "err", err) continue } - s.lggr.Infow("remote trigger event aggregated", "triggerEventID", meta.TriggerEventId, "capabilityId", s.capInfo.ID, "workflowId", workflowID) + s.lggr.Infow("remote trigger event aggregated", "triggerEventID", meta.TriggerEventId, "capabilityId", s.capInfo.ID, "workflowId", workflowId) registration.callback <- aggregatedResponse } } diff --git a/core/capabilities/remote/trigger_subscriber_test.go b/core/capabilities/remote/trigger_subscriber_test.go index d5b48bc1dc8..b8cc3ddc7bd 100644 --- a/core/capabilities/remote/trigger_subscriber_test.go +++ b/core/capabilities/remote/trigger_subscriber_test.go @@ -26,6 +26,7 @@ const ( var ( triggerEvent1 = map[string]any{"event": "triggerEvent1"} + triggerEvent2 = map[string]any{"event": "triggerEvent2"} ) func TestTriggerSubscriber_RegisterAndReceive(t *testing.T) { diff --git a/core/capabilities/remote/types/mocks/dispatcher.go b/core/capabilities/remote/types/mocks/dispatcher.go index d7f2ab45bac..0948698b935 100644 --- a/core/capabilities/remote/types/mocks/dispatcher.go +++ b/core/capabilities/remote/types/mocks/dispatcher.go @@ -206,9 +206,9 @@ func (_c *Dispatcher_Ready_Call) RunAndReturn(run func() error) *Dispatcher_Read return _c } -// RemoveReceiver provides a mock function with given fields: capabilityID, donID -func (_m *Dispatcher) RemoveReceiver(capabilityID string, donID uint32) { - _m.Called(capabilityID, donID) +// RemoveReceiver provides a mock function with given fields: capabilityId, donId +func (_m *Dispatcher) RemoveReceiver(capabilityId string, donId uint32) { + _m.Called(capabilityId, donId) } // Dispatcher_RemoveReceiver_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'RemoveReceiver' @@ -217,13 +217,13 @@ type Dispatcher_RemoveReceiver_Call struct { } // RemoveReceiver is a helper method to define mock.On call -// - capabilityID string -// - donID uint32 -func (_e *Dispatcher_Expecter) RemoveReceiver(capabilityID interface{}, donID interface{}) *Dispatcher_RemoveReceiver_Call { - return &Dispatcher_RemoveReceiver_Call{Call: _e.mock.On("RemoveReceiver", capabilityID, donID)} +// - capabilityId string +// - donId uint32 +func (_e *Dispatcher_Expecter) RemoveReceiver(capabilityId interface{}, donId interface{}) *Dispatcher_RemoveReceiver_Call { + return &Dispatcher_RemoveReceiver_Call{Call: _e.mock.On("RemoveReceiver", capabilityId, donId)} } -func (_c *Dispatcher_RemoveReceiver_Call) Run(run func(capabilityID string, donID uint32)) *Dispatcher_RemoveReceiver_Call { +func (_c *Dispatcher_RemoveReceiver_Call) Run(run func(capabilityId string, donId uint32)) *Dispatcher_RemoveReceiver_Call { _c.Call.Run(func(args mock.Arguments) { run(args[0].(string), args[1].(uint32)) }) @@ -287,9 +287,9 @@ func (_c *Dispatcher_Send_Call) RunAndReturn(run func(p2ptypes.PeerID, *types.Me return _c } -// SetReceiver provides a mock function with given fields: capabilityID, donID, receiver -func (_m *Dispatcher) SetReceiver(capabilityID string, donID uint32, receiver types.Receiver) error { - ret := _m.Called(capabilityID, donID, receiver) +// SetReceiver provides a mock function with given fields: capabilityId, donId, receiver +func (_m *Dispatcher) SetReceiver(capabilityId string, donId uint32, receiver types.Receiver) error { + ret := _m.Called(capabilityId, donId, receiver) if len(ret) == 0 { panic("no return value specified for SetReceiver") @@ -297,7 +297,7 @@ func (_m *Dispatcher) SetReceiver(capabilityID string, donID uint32, receiver ty var r0 error if rf, ok := ret.Get(0).(func(string, uint32, types.Receiver) error); ok { - r0 = rf(capabilityID, donID, receiver) + r0 = rf(capabilityId, donId, receiver) } else { r0 = ret.Error(0) } @@ -311,14 +311,14 @@ type Dispatcher_SetReceiver_Call struct { } // SetReceiver is a helper method to define mock.On call -// - capabilityID string -// - donID uint32 +// - capabilityId string +// - donId uint32 // - receiver types.Receiver -func (_e *Dispatcher_Expecter) SetReceiver(capabilityID interface{}, donID interface{}, receiver interface{}) *Dispatcher_SetReceiver_Call { - return &Dispatcher_SetReceiver_Call{Call: _e.mock.On("SetReceiver", capabilityID, donID, receiver)} +func (_e *Dispatcher_Expecter) SetReceiver(capabilityId interface{}, donId interface{}, receiver interface{}) *Dispatcher_SetReceiver_Call { + return &Dispatcher_SetReceiver_Call{Call: _e.mock.On("SetReceiver", capabilityId, donId, receiver)} } -func (_c *Dispatcher_SetReceiver_Call) Run(run func(capabilityID string, donID uint32, receiver types.Receiver)) *Dispatcher_SetReceiver_Call { +func (_c *Dispatcher_SetReceiver_Call) Run(run func(capabilityId string, donId uint32, receiver types.Receiver)) *Dispatcher_SetReceiver_Call { _c.Call.Run(func(args mock.Arguments) { run(args[0].(string), args[1].(uint32), args[2].(types.Receiver)) }) diff --git a/core/capabilities/remote/types/types.go b/core/capabilities/remote/types/types.go index 983ac6a8ed2..fefc9a9b5fe 100644 --- a/core/capabilities/remote/types/types.go +++ b/core/capabilities/remote/types/types.go @@ -13,16 +13,18 @@ import ( ) const ( - MethodRegisterTrigger = "RegisterTrigger" - MethodUnRegisterTrigger = "UnregisterTrigger" - MethodTriggerEvent = "TriggerEvent" - MethodExecute = "Execute" + MethodRegisterTrigger = "RegisterTrigger" + MethodUnRegisterTrigger = "UnregisterTrigger" + MethodTriggerEvent = "TriggerEvent" + MethodExecute = "Execute" + MethodRegisterToWorkflow = "RegisterToWorkflow" + MethodUnregisterFromWorkflow = "UnregisterFromWorkflow" ) type Dispatcher interface { services.Service - SetReceiver(capabilityID string, donID uint32, receiver Receiver) error - RemoveReceiver(capabilityID string, donID uint32) + SetReceiver(capabilityId string, donId uint32, receiver Receiver) error + RemoveReceiver(capabilityId string, donId uint32) Send(peerID p2ptypes.PeerID, msgBody *MessageBody) error } diff --git a/core/capabilities/remote/utils.go b/core/capabilities/remote/utils.go index 7af34c5c946..ea6a3efb186 100644 --- a/core/capabilities/remote/utils.go +++ b/core/capabilities/remote/utils.go @@ -3,6 +3,7 @@ package remote import ( "bytes" "crypto/ed25519" + "crypto/sha256" "encoding/hex" "errors" "fmt" @@ -10,6 +11,8 @@ import ( "google.golang.org/protobuf/proto" + commoncap "github.com/smartcontractkit/chainlink-common/pkg/capabilities" + "github.com/smartcontractkit/chainlink-common/pkg/capabilities/pb" remotetypes "github.com/smartcontractkit/chainlink/v2/core/capabilities/remote/types" p2ptypes "github.com/smartcontractkit/chainlink/v2/core/services/p2p/types" ) @@ -22,25 +25,25 @@ func ValidateMessage(msg p2ptypes.Message, expectedReceiver p2ptypes.PeerID) (*r var topLevelMessage remotetypes.Message err := proto.Unmarshal(msg.Payload, &topLevelMessage) if err != nil { - return nil, fmt.Errorf("failed to unmarshal message, err: %w", err) + return nil, fmt.Errorf("failed to unmarshal message, err: %v", err) } var body remotetypes.MessageBody err = proto.Unmarshal(topLevelMessage.Body, &body) if err != nil { - return nil, fmt.Errorf("failed to unmarshal message body, err: %w", err) + return nil, fmt.Errorf("failed to unmarshal message body, err: %v", err) } if len(body.Sender) != p2ptypes.PeerIDLength || len(body.Receiver) != p2ptypes.PeerIDLength { return &body, fmt.Errorf("invalid sender length (%d) or receiver length (%d)", len(body.Sender), len(body.Receiver)) } if !ed25519.Verify(body.Sender, topLevelMessage.Body, topLevelMessage.Signature) { - return &body, errors.New("failed to verify message signature") + return &body, fmt.Errorf("failed to verify message signature") } // NOTE we currently don't support relaying messages so the p2p message sender needs to be the message author if !bytes.Equal(body.Sender, msg.Sender[:]) { - return &body, errors.New("sender in message body does not match sender of p2p message") + return &body, fmt.Errorf("sender in message body does not match sender of p2p message") } if !bytes.Equal(body.Receiver, expectedReceiver[:]) { - return &body, errors.New("receiver in message body does not match expected receiver") + return &body, fmt.Errorf("receiver in message body does not match expected receiver") } return &body, nil } @@ -55,6 +58,52 @@ func ToPeerID(peerID []byte) (p2ptypes.PeerID, error) { return id, nil } +// Default MODE Aggregator needs a configurable number of identical responses for aggregation to succeed +type defaultModeAggregator struct { + minIdenticalResponses uint32 +} + +var _ remotetypes.Aggregator = &defaultModeAggregator{} + +func NewDefaultModeAggregator(minIdenticalResponses uint32) *defaultModeAggregator { + return &defaultModeAggregator{ + minIdenticalResponses: minIdenticalResponses, + } +} + +func (a *defaultModeAggregator) Aggregate(_ string, responses [][]byte) (commoncap.TriggerResponse, error) { + found, err := AggregateModeRaw(responses, a.minIdenticalResponses) + if err != nil { + return commoncap.TriggerResponse{}, fmt.Errorf("failed to aggregate responses, err: %w", err) + } + + unmarshaled, err := pb.UnmarshalTriggerResponse(found) + if err != nil { + return commoncap.TriggerResponse{}, fmt.Errorf("failed to unmarshal aggregated responses, err: %w", err) + } + return unmarshaled, nil +} + +func AggregateModeRaw(elemList [][]byte, minIdenticalResponses uint32) ([]byte, error) { + hashToCount := make(map[string]uint32) + var found []byte + for _, elem := range elemList { + hasher := sha256.New() + hasher.Write(elem) + sha := hex.EncodeToString(hasher.Sum(nil)) + hashToCount[sha]++ + if hashToCount[sha] >= minIdenticalResponses { + found = elem + // update in case we find another elem with an even higher count + minIdenticalResponses = hashToCount[sha] + } + } + if found == nil { + return nil, errors.New("not enough identical responses found") + } + return found, nil +} + func SanitizeLogString(s string) string { tooLongSuffix := "" if len(s) > maxLoggedStringLen { diff --git a/core/capabilities/remote/utils_test.go b/core/capabilities/remote/utils_test.go index 360ef9000ba..6707e6ffb25 100644 --- a/core/capabilities/remote/utils_test.go +++ b/core/capabilities/remote/utils_test.go @@ -10,39 +10,43 @@ import ( ragetypes "github.com/smartcontractkit/libocr/ragep2p/types" + commoncap "github.com/smartcontractkit/chainlink-common/pkg/capabilities" + "github.com/smartcontractkit/chainlink-common/pkg/capabilities/pb" + "github.com/smartcontractkit/chainlink-common/pkg/values" + "github.com/smartcontractkit/chainlink/v2/core/capabilities/remote" remotetypes "github.com/smartcontractkit/chainlink/v2/core/capabilities/remote/types" p2ptypes "github.com/smartcontractkit/chainlink/v2/core/services/p2p/types" ) const ( - capID1 = "cap1" - capID2 = "cap2" - donID1 = uint32(1) + capId1 = "cap1" + capId2 = "cap2" + donId1 = uint32(1) payload1 = "hello world" payload2 = "goodbye world" ) func TestValidateMessage(t *testing.T) { - privKey1, peerID1 := newKeyPair(t) - _, peerID2 := newKeyPair(t) + privKey1, peerId1 := newKeyPair(t) + _, peerId2 := newKeyPair(t) // valid - p2pMsg := encodeAndSign(t, privKey1, peerID1, peerID2, capID1, donID1, []byte(payload1)) - body, err := remote.ValidateMessage(p2pMsg, peerID2) + p2pMsg := encodeAndSign(t, privKey1, peerId1, peerId2, capId1, donId1, []byte(payload1)) + body, err := remote.ValidateMessage(p2pMsg, peerId2) require.NoError(t, err) - require.Equal(t, peerID1[:], body.Sender) + require.Equal(t, peerId1[:], body.Sender) require.Equal(t, payload1, string(body.Payload)) // invalid sender - p2pMsg = encodeAndSign(t, privKey1, peerID1, peerID2, capID1, donID1, []byte(payload1)) - p2pMsg.Sender = peerID2 - _, err = remote.ValidateMessage(p2pMsg, peerID2) + p2pMsg = encodeAndSign(t, privKey1, peerId1, peerId2, capId1, donId1, []byte(payload1)) + p2pMsg.Sender = peerId2 + _, err = remote.ValidateMessage(p2pMsg, peerId2) require.Error(t, err) // invalid receiver - p2pMsg = encodeAndSign(t, privKey1, peerID1, peerID2, capID1, donID1, []byte(payload1)) - _, err = remote.ValidateMessage(p2pMsg, peerID1) + p2pMsg = encodeAndSign(t, privKey1, peerId1, peerId2, capId1, donId1, []byte(payload1)) + _, err = remote.ValidateMessage(p2pMsg, peerId1) require.Error(t, err) } @@ -54,12 +58,12 @@ func newKeyPair(t *testing.T) (ed25519.PrivateKey, ragetypes.PeerID) { return privKey, peerID } -func encodeAndSign(t *testing.T, senderPrivKey ed25519.PrivateKey, senderID p2ptypes.PeerID, receiverID p2ptypes.PeerID, capabilityID string, donID uint32, payload []byte) p2ptypes.Message { +func encodeAndSign(t *testing.T, senderPrivKey ed25519.PrivateKey, senderId p2ptypes.PeerID, receiverId p2ptypes.PeerID, capabilityId string, donId uint32, payload []byte) p2ptypes.Message { body := remotetypes.MessageBody{ - Sender: senderID[:], - Receiver: receiverID[:], - CapabilityId: capabilityID, - CapabilityDonId: donID, + Sender: senderId[:], + Receiver: receiverId[:], + CapabilityId: capabilityId, + CapabilityDonId: donId, Payload: payload, } rawBody, err := proto.Marshal(&body) @@ -74,7 +78,7 @@ func encodeAndSign(t *testing.T, senderPrivKey ed25519.PrivateKey, senderID p2pt require.NoError(t, err) return p2ptypes.Message{ - Sender: senderID, + Sender: senderId, Payload: rawMsg, } } @@ -85,6 +89,41 @@ func TestToPeerID(t *testing.T) { require.Equal(t, "12D3KooWD8QYTQVYjB6oog4Ej8PcPpqTrPRnxLQap8yY8KUQRVvq", id.String()) } +func TestDefaultModeAggregator_Aggregate(t *testing.T) { + val, err := values.NewMap(triggerEvent1) + require.NoError(t, err) + capResponse1 := commoncap.TriggerResponse{ + Event: commoncap.TriggerEvent{ + Outputs: val, + }, + Err: nil, + } + marshaled1, err := pb.MarshalTriggerResponse(capResponse1) + require.NoError(t, err) + + val2, err := values.NewMap(triggerEvent2) + require.NoError(t, err) + capResponse2 := commoncap.TriggerResponse{ + Event: commoncap.TriggerEvent{ + Outputs: val2, + }, + Err: nil, + } + marshaled2, err := pb.MarshalTriggerResponse(capResponse2) + require.NoError(t, err) + + agg := remote.NewDefaultModeAggregator(2) + _, err = agg.Aggregate("", [][]byte{marshaled1}) + require.Error(t, err) + + _, err = agg.Aggregate("", [][]byte{marshaled1, marshaled2}) + require.Error(t, err) + + res, err := agg.Aggregate("", [][]byte{marshaled1, marshaled2, marshaled1}) + require.NoError(t, err) + require.Equal(t, res, capResponse1) +} + func TestSanitizeLogString(t *testing.T) { require.Equal(t, "hello", remote.SanitizeLogString("hello")) require.Equal(t, "[UNPRINTABLE] 0a", remote.SanitizeLogString("\n")) diff --git a/core/capabilities/targets/mocks/chain_writer.go b/core/capabilities/targets/mocks/chain_writer.go new file mode 100644 index 00000000000..5d7102fd4df --- /dev/null +++ b/core/capabilities/targets/mocks/chain_writer.go @@ -0,0 +1,435 @@ +// Code generated by mockery v2.46.3. DO NOT EDIT. + +package mocks + +import ( + context "context" + big "math/big" + + mock "github.com/stretchr/testify/mock" + + types "github.com/smartcontractkit/chainlink-common/pkg/types" +) + +// ChainWriter is an autogenerated mock type for the ChainWriter type +type ChainWriter struct { + mock.Mock +} + +type ChainWriter_Expecter struct { + mock *mock.Mock +} + +func (_m *ChainWriter) EXPECT() *ChainWriter_Expecter { + return &ChainWriter_Expecter{mock: &_m.Mock} +} + +// Close provides a mock function with given fields: +func (_m *ChainWriter) Close() error { + ret := _m.Called() + + if len(ret) == 0 { + panic("no return value specified for Close") + } + + var r0 error + if rf, ok := ret.Get(0).(func() error); ok { + r0 = rf() + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// ChainWriter_Close_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Close' +type ChainWriter_Close_Call struct { + *mock.Call +} + +// Close is a helper method to define mock.On call +func (_e *ChainWriter_Expecter) Close() *ChainWriter_Close_Call { + return &ChainWriter_Close_Call{Call: _e.mock.On("Close")} +} + +func (_c *ChainWriter_Close_Call) Run(run func()) *ChainWriter_Close_Call { + _c.Call.Run(func(args mock.Arguments) { + run() + }) + return _c +} + +func (_c *ChainWriter_Close_Call) Return(_a0 error) *ChainWriter_Close_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *ChainWriter_Close_Call) RunAndReturn(run func() error) *ChainWriter_Close_Call { + _c.Call.Return(run) + return _c +} + +// GetFeeComponents provides a mock function with given fields: ctx +func (_m *ChainWriter) GetFeeComponents(ctx context.Context) (*types.ChainFeeComponents, error) { + ret := _m.Called(ctx) + + if len(ret) == 0 { + panic("no return value specified for GetFeeComponents") + } + + var r0 *types.ChainFeeComponents + var r1 error + if rf, ok := ret.Get(0).(func(context.Context) (*types.ChainFeeComponents, error)); ok { + return rf(ctx) + } + if rf, ok := ret.Get(0).(func(context.Context) *types.ChainFeeComponents); ok { + r0 = rf(ctx) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*types.ChainFeeComponents) + } + } + + if rf, ok := ret.Get(1).(func(context.Context) error); ok { + r1 = rf(ctx) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// ChainWriter_GetFeeComponents_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetFeeComponents' +type ChainWriter_GetFeeComponents_Call struct { + *mock.Call +} + +// GetFeeComponents is a helper method to define mock.On call +// - ctx context.Context +func (_e *ChainWriter_Expecter) GetFeeComponents(ctx interface{}) *ChainWriter_GetFeeComponents_Call { + return &ChainWriter_GetFeeComponents_Call{Call: _e.mock.On("GetFeeComponents", ctx)} +} + +func (_c *ChainWriter_GetFeeComponents_Call) Run(run func(ctx context.Context)) *ChainWriter_GetFeeComponents_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context)) + }) + return _c +} + +func (_c *ChainWriter_GetFeeComponents_Call) Return(_a0 *types.ChainFeeComponents, _a1 error) *ChainWriter_GetFeeComponents_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *ChainWriter_GetFeeComponents_Call) RunAndReturn(run func(context.Context) (*types.ChainFeeComponents, error)) *ChainWriter_GetFeeComponents_Call { + _c.Call.Return(run) + return _c +} + +// GetTransactionStatus provides a mock function with given fields: ctx, transactionID +func (_m *ChainWriter) GetTransactionStatus(ctx context.Context, transactionID string) (types.TransactionStatus, error) { + ret := _m.Called(ctx, transactionID) + + if len(ret) == 0 { + panic("no return value specified for GetTransactionStatus") + } + + var r0 types.TransactionStatus + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, string) (types.TransactionStatus, error)); ok { + return rf(ctx, transactionID) + } + if rf, ok := ret.Get(0).(func(context.Context, string) types.TransactionStatus); ok { + r0 = rf(ctx, transactionID) + } else { + r0 = ret.Get(0).(types.TransactionStatus) + } + + if rf, ok := ret.Get(1).(func(context.Context, string) error); ok { + r1 = rf(ctx, transactionID) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// ChainWriter_GetTransactionStatus_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetTransactionStatus' +type ChainWriter_GetTransactionStatus_Call struct { + *mock.Call +} + +// GetTransactionStatus is a helper method to define mock.On call +// - ctx context.Context +// - transactionID string +func (_e *ChainWriter_Expecter) GetTransactionStatus(ctx interface{}, transactionID interface{}) *ChainWriter_GetTransactionStatus_Call { + return &ChainWriter_GetTransactionStatus_Call{Call: _e.mock.On("GetTransactionStatus", ctx, transactionID)} +} + +func (_c *ChainWriter_GetTransactionStatus_Call) Run(run func(ctx context.Context, transactionID string)) *ChainWriter_GetTransactionStatus_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(string)) + }) + return _c +} + +func (_c *ChainWriter_GetTransactionStatus_Call) Return(_a0 types.TransactionStatus, _a1 error) *ChainWriter_GetTransactionStatus_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *ChainWriter_GetTransactionStatus_Call) RunAndReturn(run func(context.Context, string) (types.TransactionStatus, error)) *ChainWriter_GetTransactionStatus_Call { + _c.Call.Return(run) + return _c +} + +// HealthReport provides a mock function with given fields: +func (_m *ChainWriter) HealthReport() map[string]error { + ret := _m.Called() + + if len(ret) == 0 { + panic("no return value specified for HealthReport") + } + + var r0 map[string]error + if rf, ok := ret.Get(0).(func() map[string]error); ok { + r0 = rf() + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(map[string]error) + } + } + + return r0 +} + +// ChainWriter_HealthReport_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'HealthReport' +type ChainWriter_HealthReport_Call struct { + *mock.Call +} + +// HealthReport is a helper method to define mock.On call +func (_e *ChainWriter_Expecter) HealthReport() *ChainWriter_HealthReport_Call { + return &ChainWriter_HealthReport_Call{Call: _e.mock.On("HealthReport")} +} + +func (_c *ChainWriter_HealthReport_Call) Run(run func()) *ChainWriter_HealthReport_Call { + _c.Call.Run(func(args mock.Arguments) { + run() + }) + return _c +} + +func (_c *ChainWriter_HealthReport_Call) Return(_a0 map[string]error) *ChainWriter_HealthReport_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *ChainWriter_HealthReport_Call) RunAndReturn(run func() map[string]error) *ChainWriter_HealthReport_Call { + _c.Call.Return(run) + return _c +} + +// Name provides a mock function with given fields: +func (_m *ChainWriter) Name() string { + ret := _m.Called() + + if len(ret) == 0 { + panic("no return value specified for Name") + } + + var r0 string + if rf, ok := ret.Get(0).(func() string); ok { + r0 = rf() + } else { + r0 = ret.Get(0).(string) + } + + return r0 +} + +// ChainWriter_Name_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Name' +type ChainWriter_Name_Call struct { + *mock.Call +} + +// Name is a helper method to define mock.On call +func (_e *ChainWriter_Expecter) Name() *ChainWriter_Name_Call { + return &ChainWriter_Name_Call{Call: _e.mock.On("Name")} +} + +func (_c *ChainWriter_Name_Call) Run(run func()) *ChainWriter_Name_Call { + _c.Call.Run(func(args mock.Arguments) { + run() + }) + return _c +} + +func (_c *ChainWriter_Name_Call) Return(_a0 string) *ChainWriter_Name_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *ChainWriter_Name_Call) RunAndReturn(run func() string) *ChainWriter_Name_Call { + _c.Call.Return(run) + return _c +} + +// Ready provides a mock function with given fields: +func (_m *ChainWriter) Ready() error { + ret := _m.Called() + + if len(ret) == 0 { + panic("no return value specified for Ready") + } + + var r0 error + if rf, ok := ret.Get(0).(func() error); ok { + r0 = rf() + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// ChainWriter_Ready_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Ready' +type ChainWriter_Ready_Call struct { + *mock.Call +} + +// Ready is a helper method to define mock.On call +func (_e *ChainWriter_Expecter) Ready() *ChainWriter_Ready_Call { + return &ChainWriter_Ready_Call{Call: _e.mock.On("Ready")} +} + +func (_c *ChainWriter_Ready_Call) Run(run func()) *ChainWriter_Ready_Call { + _c.Call.Run(func(args mock.Arguments) { + run() + }) + return _c +} + +func (_c *ChainWriter_Ready_Call) Return(_a0 error) *ChainWriter_Ready_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *ChainWriter_Ready_Call) RunAndReturn(run func() error) *ChainWriter_Ready_Call { + _c.Call.Return(run) + return _c +} + +// Start provides a mock function with given fields: _a0 +func (_m *ChainWriter) Start(_a0 context.Context) error { + ret := _m.Called(_a0) + + if len(ret) == 0 { + panic("no return value specified for Start") + } + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context) error); ok { + r0 = rf(_a0) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// ChainWriter_Start_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Start' +type ChainWriter_Start_Call struct { + *mock.Call +} + +// Start is a helper method to define mock.On call +// - _a0 context.Context +func (_e *ChainWriter_Expecter) Start(_a0 interface{}) *ChainWriter_Start_Call { + return &ChainWriter_Start_Call{Call: _e.mock.On("Start", _a0)} +} + +func (_c *ChainWriter_Start_Call) Run(run func(_a0 context.Context)) *ChainWriter_Start_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context)) + }) + return _c +} + +func (_c *ChainWriter_Start_Call) Return(_a0 error) *ChainWriter_Start_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *ChainWriter_Start_Call) RunAndReturn(run func(context.Context) error) *ChainWriter_Start_Call { + _c.Call.Return(run) + return _c +} + +// SubmitTransaction provides a mock function with given fields: ctx, contractName, method, args, transactionID, toAddress, meta, value +func (_m *ChainWriter) SubmitTransaction(ctx context.Context, contractName string, method string, args any, transactionID string, toAddress string, meta *types.TxMeta, value *big.Int) error { + ret := _m.Called(ctx, contractName, method, args, transactionID, toAddress, meta, value) + + if len(ret) == 0 { + panic("no return value specified for SubmitTransaction") + } + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context, string, string, any, string, string, *types.TxMeta, *big.Int) error); ok { + r0 = rf(ctx, contractName, method, args, transactionID, toAddress, meta, value) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// ChainWriter_SubmitTransaction_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'SubmitTransaction' +type ChainWriter_SubmitTransaction_Call struct { + *mock.Call +} + +// SubmitTransaction is a helper method to define mock.On call +// - ctx context.Context +// - contractName string +// - method string +// - args any +// - transactionID string +// - toAddress string +// - meta *types.TxMeta +// - value *big.Int +func (_e *ChainWriter_Expecter) SubmitTransaction(ctx interface{}, contractName interface{}, method interface{}, args interface{}, transactionID interface{}, toAddress interface{}, meta interface{}, value interface{}) *ChainWriter_SubmitTransaction_Call { + return &ChainWriter_SubmitTransaction_Call{Call: _e.mock.On("SubmitTransaction", ctx, contractName, method, args, transactionID, toAddress, meta, value)} +} + +func (_c *ChainWriter_SubmitTransaction_Call) Run(run func(ctx context.Context, contractName string, method string, args any, transactionID string, toAddress string, meta *types.TxMeta, value *big.Int)) *ChainWriter_SubmitTransaction_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(string), args[2].(string), args[3].(any), args[4].(string), args[5].(string), args[6].(*types.TxMeta), args[7].(*big.Int)) + }) + return _c +} + +func (_c *ChainWriter_SubmitTransaction_Call) Return(_a0 error) *ChainWriter_SubmitTransaction_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *ChainWriter_SubmitTransaction_Call) RunAndReturn(run func(context.Context, string, string, any, string, string, *types.TxMeta, *big.Int) error) *ChainWriter_SubmitTransaction_Call { + _c.Call.Return(run) + return _c +} + +// NewChainWriter creates a new instance of ChainWriter. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func NewChainWriter(t interface { + mock.TestingT + Cleanup(func()) +}) *ChainWriter { + mock := &ChainWriter{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/core/capabilities/targets/mocks/contract_writer.go b/core/capabilities/targets/mocks/contract_writer.go deleted file mode 100644 index c6128e68fc7..00000000000 --- a/core/capabilities/targets/mocks/contract_writer.go +++ /dev/null @@ -1,435 +0,0 @@ -// Code generated by mockery v2.46.3. DO NOT EDIT. - -package mocks - -import ( - context "context" - big "math/big" - - mock "github.com/stretchr/testify/mock" - - types "github.com/smartcontractkit/chainlink-common/pkg/types" -) - -// ContractWriter is an autogenerated mock type for the ContractWriter type -type ContractWriter struct { - mock.Mock -} - -type ContractWriter_Expecter struct { - mock *mock.Mock -} - -func (_m *ContractWriter) EXPECT() *ContractWriter_Expecter { - return &ContractWriter_Expecter{mock: &_m.Mock} -} - -// Close provides a mock function with given fields: -func (_m *ContractWriter) Close() error { - ret := _m.Called() - - if len(ret) == 0 { - panic("no return value specified for Close") - } - - var r0 error - if rf, ok := ret.Get(0).(func() error); ok { - r0 = rf() - } else { - r0 = ret.Error(0) - } - - return r0 -} - -// ContractWriter_Close_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Close' -type ContractWriter_Close_Call struct { - *mock.Call -} - -// Close is a helper method to define mock.On call -func (_e *ContractWriter_Expecter) Close() *ContractWriter_Close_Call { - return &ContractWriter_Close_Call{Call: _e.mock.On("Close")} -} - -func (_c *ContractWriter_Close_Call) Run(run func()) *ContractWriter_Close_Call { - _c.Call.Run(func(args mock.Arguments) { - run() - }) - return _c -} - -func (_c *ContractWriter_Close_Call) Return(_a0 error) *ContractWriter_Close_Call { - _c.Call.Return(_a0) - return _c -} - -func (_c *ContractWriter_Close_Call) RunAndReturn(run func() error) *ContractWriter_Close_Call { - _c.Call.Return(run) - return _c -} - -// GetFeeComponents provides a mock function with given fields: ctx -func (_m *ContractWriter) GetFeeComponents(ctx context.Context) (*types.ChainFeeComponents, error) { - ret := _m.Called(ctx) - - if len(ret) == 0 { - panic("no return value specified for GetFeeComponents") - } - - var r0 *types.ChainFeeComponents - var r1 error - if rf, ok := ret.Get(0).(func(context.Context) (*types.ChainFeeComponents, error)); ok { - return rf(ctx) - } - if rf, ok := ret.Get(0).(func(context.Context) *types.ChainFeeComponents); ok { - r0 = rf(ctx) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*types.ChainFeeComponents) - } - } - - if rf, ok := ret.Get(1).(func(context.Context) error); ok { - r1 = rf(ctx) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// ContractWriter_GetFeeComponents_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetFeeComponents' -type ContractWriter_GetFeeComponents_Call struct { - *mock.Call -} - -// GetFeeComponents is a helper method to define mock.On call -// - ctx context.Context -func (_e *ContractWriter_Expecter) GetFeeComponents(ctx interface{}) *ContractWriter_GetFeeComponents_Call { - return &ContractWriter_GetFeeComponents_Call{Call: _e.mock.On("GetFeeComponents", ctx)} -} - -func (_c *ContractWriter_GetFeeComponents_Call) Run(run func(ctx context.Context)) *ContractWriter_GetFeeComponents_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context)) - }) - return _c -} - -func (_c *ContractWriter_GetFeeComponents_Call) Return(_a0 *types.ChainFeeComponents, _a1 error) *ContractWriter_GetFeeComponents_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *ContractWriter_GetFeeComponents_Call) RunAndReturn(run func(context.Context) (*types.ChainFeeComponents, error)) *ContractWriter_GetFeeComponents_Call { - _c.Call.Return(run) - return _c -} - -// GetTransactionStatus provides a mock function with given fields: ctx, transactionID -func (_m *ContractWriter) GetTransactionStatus(ctx context.Context, transactionID string) (types.TransactionStatus, error) { - ret := _m.Called(ctx, transactionID) - - if len(ret) == 0 { - panic("no return value specified for GetTransactionStatus") - } - - var r0 types.TransactionStatus - var r1 error - if rf, ok := ret.Get(0).(func(context.Context, string) (types.TransactionStatus, error)); ok { - return rf(ctx, transactionID) - } - if rf, ok := ret.Get(0).(func(context.Context, string) types.TransactionStatus); ok { - r0 = rf(ctx, transactionID) - } else { - r0 = ret.Get(0).(types.TransactionStatus) - } - - if rf, ok := ret.Get(1).(func(context.Context, string) error); ok { - r1 = rf(ctx, transactionID) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// ContractWriter_GetTransactionStatus_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetTransactionStatus' -type ContractWriter_GetTransactionStatus_Call struct { - *mock.Call -} - -// GetTransactionStatus is a helper method to define mock.On call -// - ctx context.Context -// - transactionID string -func (_e *ContractWriter_Expecter) GetTransactionStatus(ctx interface{}, transactionID interface{}) *ContractWriter_GetTransactionStatus_Call { - return &ContractWriter_GetTransactionStatus_Call{Call: _e.mock.On("GetTransactionStatus", ctx, transactionID)} -} - -func (_c *ContractWriter_GetTransactionStatus_Call) Run(run func(ctx context.Context, transactionID string)) *ContractWriter_GetTransactionStatus_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context), args[1].(string)) - }) - return _c -} - -func (_c *ContractWriter_GetTransactionStatus_Call) Return(_a0 types.TransactionStatus, _a1 error) *ContractWriter_GetTransactionStatus_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *ContractWriter_GetTransactionStatus_Call) RunAndReturn(run func(context.Context, string) (types.TransactionStatus, error)) *ContractWriter_GetTransactionStatus_Call { - _c.Call.Return(run) - return _c -} - -// HealthReport provides a mock function with given fields: -func (_m *ContractWriter) HealthReport() map[string]error { - ret := _m.Called() - - if len(ret) == 0 { - panic("no return value specified for HealthReport") - } - - var r0 map[string]error - if rf, ok := ret.Get(0).(func() map[string]error); ok { - r0 = rf() - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(map[string]error) - } - } - - return r0 -} - -// ContractWriter_HealthReport_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'HealthReport' -type ContractWriter_HealthReport_Call struct { - *mock.Call -} - -// HealthReport is a helper method to define mock.On call -func (_e *ContractWriter_Expecter) HealthReport() *ContractWriter_HealthReport_Call { - return &ContractWriter_HealthReport_Call{Call: _e.mock.On("HealthReport")} -} - -func (_c *ContractWriter_HealthReport_Call) Run(run func()) *ContractWriter_HealthReport_Call { - _c.Call.Run(func(args mock.Arguments) { - run() - }) - return _c -} - -func (_c *ContractWriter_HealthReport_Call) Return(_a0 map[string]error) *ContractWriter_HealthReport_Call { - _c.Call.Return(_a0) - return _c -} - -func (_c *ContractWriter_HealthReport_Call) RunAndReturn(run func() map[string]error) *ContractWriter_HealthReport_Call { - _c.Call.Return(run) - return _c -} - -// Name provides a mock function with given fields: -func (_m *ContractWriter) Name() string { - ret := _m.Called() - - if len(ret) == 0 { - panic("no return value specified for Name") - } - - var r0 string - if rf, ok := ret.Get(0).(func() string); ok { - r0 = rf() - } else { - r0 = ret.Get(0).(string) - } - - return r0 -} - -// ContractWriter_Name_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Name' -type ContractWriter_Name_Call struct { - *mock.Call -} - -// Name is a helper method to define mock.On call -func (_e *ContractWriter_Expecter) Name() *ContractWriter_Name_Call { - return &ContractWriter_Name_Call{Call: _e.mock.On("Name")} -} - -func (_c *ContractWriter_Name_Call) Run(run func()) *ContractWriter_Name_Call { - _c.Call.Run(func(args mock.Arguments) { - run() - }) - return _c -} - -func (_c *ContractWriter_Name_Call) Return(_a0 string) *ContractWriter_Name_Call { - _c.Call.Return(_a0) - return _c -} - -func (_c *ContractWriter_Name_Call) RunAndReturn(run func() string) *ContractWriter_Name_Call { - _c.Call.Return(run) - return _c -} - -// Ready provides a mock function with given fields: -func (_m *ContractWriter) Ready() error { - ret := _m.Called() - - if len(ret) == 0 { - panic("no return value specified for Ready") - } - - var r0 error - if rf, ok := ret.Get(0).(func() error); ok { - r0 = rf() - } else { - r0 = ret.Error(0) - } - - return r0 -} - -// ContractWriter_Ready_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Ready' -type ContractWriter_Ready_Call struct { - *mock.Call -} - -// Ready is a helper method to define mock.On call -func (_e *ContractWriter_Expecter) Ready() *ContractWriter_Ready_Call { - return &ContractWriter_Ready_Call{Call: _e.mock.On("Ready")} -} - -func (_c *ContractWriter_Ready_Call) Run(run func()) *ContractWriter_Ready_Call { - _c.Call.Run(func(args mock.Arguments) { - run() - }) - return _c -} - -func (_c *ContractWriter_Ready_Call) Return(_a0 error) *ContractWriter_Ready_Call { - _c.Call.Return(_a0) - return _c -} - -func (_c *ContractWriter_Ready_Call) RunAndReturn(run func() error) *ContractWriter_Ready_Call { - _c.Call.Return(run) - return _c -} - -// Start provides a mock function with given fields: _a0 -func (_m *ContractWriter) Start(_a0 context.Context) error { - ret := _m.Called(_a0) - - if len(ret) == 0 { - panic("no return value specified for Start") - } - - var r0 error - if rf, ok := ret.Get(0).(func(context.Context) error); ok { - r0 = rf(_a0) - } else { - r0 = ret.Error(0) - } - - return r0 -} - -// ContractWriter_Start_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Start' -type ContractWriter_Start_Call struct { - *mock.Call -} - -// Start is a helper method to define mock.On call -// - _a0 context.Context -func (_e *ContractWriter_Expecter) Start(_a0 interface{}) *ContractWriter_Start_Call { - return &ContractWriter_Start_Call{Call: _e.mock.On("Start", _a0)} -} - -func (_c *ContractWriter_Start_Call) Run(run func(_a0 context.Context)) *ContractWriter_Start_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context)) - }) - return _c -} - -func (_c *ContractWriter_Start_Call) Return(_a0 error) *ContractWriter_Start_Call { - _c.Call.Return(_a0) - return _c -} - -func (_c *ContractWriter_Start_Call) RunAndReturn(run func(context.Context) error) *ContractWriter_Start_Call { - _c.Call.Return(run) - return _c -} - -// SubmitTransaction provides a mock function with given fields: ctx, contractName, method, args, transactionID, toAddress, meta, value -func (_m *ContractWriter) SubmitTransaction(ctx context.Context, contractName string, method string, args any, transactionID string, toAddress string, meta *types.TxMeta, value *big.Int) error { - ret := _m.Called(ctx, contractName, method, args, transactionID, toAddress, meta, value) - - if len(ret) == 0 { - panic("no return value specified for SubmitTransaction") - } - - var r0 error - if rf, ok := ret.Get(0).(func(context.Context, string, string, any, string, string, *types.TxMeta, *big.Int) error); ok { - r0 = rf(ctx, contractName, method, args, transactionID, toAddress, meta, value) - } else { - r0 = ret.Error(0) - } - - return r0 -} - -// ContractWriter_SubmitTransaction_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'SubmitTransaction' -type ContractWriter_SubmitTransaction_Call struct { - *mock.Call -} - -// SubmitTransaction is a helper method to define mock.On call -// - ctx context.Context -// - contractName string -// - method string -// - args any -// - transactionID string -// - toAddress string -// - meta *types.TxMeta -// - value *big.Int -func (_e *ContractWriter_Expecter) SubmitTransaction(ctx interface{}, contractName interface{}, method interface{}, args interface{}, transactionID interface{}, toAddress interface{}, meta interface{}, value interface{}) *ContractWriter_SubmitTransaction_Call { - return &ContractWriter_SubmitTransaction_Call{Call: _e.mock.On("SubmitTransaction", ctx, contractName, method, args, transactionID, toAddress, meta, value)} -} - -func (_c *ContractWriter_SubmitTransaction_Call) Run(run func(ctx context.Context, contractName string, method string, args any, transactionID string, toAddress string, meta *types.TxMeta, value *big.Int)) *ContractWriter_SubmitTransaction_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context), args[1].(string), args[2].(string), args[3].(any), args[4].(string), args[5].(string), args[6].(*types.TxMeta), args[7].(*big.Int)) - }) - return _c -} - -func (_c *ContractWriter_SubmitTransaction_Call) Return(_a0 error) *ContractWriter_SubmitTransaction_Call { - _c.Call.Return(_a0) - return _c -} - -func (_c *ContractWriter_SubmitTransaction_Call) RunAndReturn(run func(context.Context, string, string, any, string, string, *types.TxMeta, *big.Int) error) *ContractWriter_SubmitTransaction_Call { - _c.Call.Return(run) - return _c -} - -// NewContractWriter creates a new instance of ContractWriter. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. -// The first argument is typically a *testing.T value. -func NewContractWriter(t interface { - mock.TestingT - Cleanup(func()) -}) *ContractWriter { - mock := &ContractWriter{} - mock.Mock.Test(t) - - t.Cleanup(func() { mock.AssertExpectations(t) }) - - return mock -} diff --git a/core/capabilities/targets/write_target.go b/core/capabilities/targets/write_target.go index 09a0bbd2b36..9315a1ee199 100644 --- a/core/capabilities/targets/write_target.go +++ b/core/capabilities/targets/write_target.go @@ -7,7 +7,6 @@ import ( "encoding/hex" "fmt" "math/big" - "strings" "time" "github.com/ethereum/go-ethereum/common" @@ -31,7 +30,7 @@ const transactionStatusCheckInterval = 2 * time.Second type WriteTarget struct { cr ContractValueGetter - cw commontypes.ContractWriter + cw commontypes.ChainWriter binding commontypes.BoundContract forwarderAddress string // The minimum amount of gas that the receiver contract must get to process the forwarder report @@ -67,7 +66,7 @@ func NewWriteTarget( lggr logger.Logger, id string, cr ContractValueGetter, - cw commontypes.ContractWriter, + cw commontypes.ChainWriter, forwarderAddress string, txGasLimit uint64, ) *WriteTarget { @@ -187,23 +186,15 @@ func evaluate(rawRequest capabilities.CapabilityRequest) (r Request, err error) } if hex.EncodeToString(reportMetadata.WorkflowExecutionID[:]) != rawRequest.Metadata.WorkflowExecutionID { - return r, fmt.Errorf("WorkflowExecutionID in the report does not match WorkflowExecutionID in the request metadata. Report WorkflowExecutionID: %+v, request WorkflowExecutionID: %+v", hex.EncodeToString(reportMetadata.WorkflowExecutionID[:]), rawRequest.Metadata.WorkflowExecutionID) + return r, fmt.Errorf("WorkflowExecutionID in the report does not match WorkflowExecutionID in the request metadata. Report WorkflowExecutionID: %+v, request WorkflowExecutionID: %+v", reportMetadata.WorkflowExecutionID, rawRequest.Metadata.WorkflowExecutionID) } - // case-insensitive verification of the owner address (so that a check-summed address matches its non-checksummed version). - if !strings.EqualFold(hex.EncodeToString(reportMetadata.WorkflowOwner[:]), rawRequest.Metadata.WorkflowOwner) { - return r, fmt.Errorf("WorkflowOwner in the report does not match WorkflowOwner in the request metadata. Report WorkflowOwner: %+v, request WorkflowOwner: %+v", hex.EncodeToString(reportMetadata.WorkflowOwner[:]), rawRequest.Metadata.WorkflowOwner) + if hex.EncodeToString(reportMetadata.WorkflowOwner[:]) != rawRequest.Metadata.WorkflowOwner { + return r, fmt.Errorf("WorkflowOwner in the report does not match WorkflowOwner in the request metadata. Report WorkflowOwner: %+v, request WorkflowOwner: %+v", reportMetadata.WorkflowOwner, rawRequest.Metadata.WorkflowOwner) } - // workflowNames are padded to 10bytes - decodedName, err := hex.DecodeString(rawRequest.Metadata.WorkflowName) - if err != nil { - return r, err - } - var workflowName [10]byte - copy(workflowName[:], decodedName) - if !bytes.Equal(reportMetadata.WorkflowName[:], workflowName[:]) { - return r, fmt.Errorf("WorkflowName in the report does not match WorkflowName in the request metadata. Report WorkflowName: %+v, request WorkflowName: %+v", hex.EncodeToString(reportMetadata.WorkflowName[:]), hex.EncodeToString(workflowName[:])) + if hex.EncodeToString(reportMetadata.WorkflowName[:]) != rawRequest.Metadata.WorkflowName { + return r, fmt.Errorf("WorkflowName in the report does not match WorkflowName in the request metadata. Report WorkflowName: %+v, request WorkflowName: %+v", reportMetadata.WorkflowName, rawRequest.Metadata.WorkflowName) } if hex.EncodeToString(reportMetadata.WorkflowCID[:]) != rawRequest.Metadata.WorkflowID { diff --git a/core/capabilities/targets/write_target_test.go b/core/capabilities/targets/write_target_test.go index a702d78cb5d..38136f07df0 100644 --- a/core/capabilities/targets/write_target_test.go +++ b/core/capabilities/targets/write_target_test.go @@ -27,7 +27,7 @@ func TestWriteTarget(t *testing.T) { lggr := logger.TestLogger(t) ctx := context.Background() - cw := mocks.NewContractWriter(t) + cw := mocks.NewChainWriter(t) cr := mocks.NewContractValueGetter(t) forwarderA := testutils.NewAddress() @@ -42,10 +42,6 @@ func TestWriteTarget(t *testing.T) { require.NoError(t, err) reportID := [2]byte{0x00, 0x01} - var workflowName [10]byte - copy(workflowName[:], []byte("name")) - workflowOwnerString := "219BFD3D78fbb740c614432975CBE829E26C490e" - workflowOwner := common.HexToAddress(workflowOwnerString) reportMetadata := targets.ReportV1Metadata{ Version: 1, WorkflowExecutionID: [32]byte{}, @@ -53,8 +49,8 @@ func TestWriteTarget(t *testing.T) { DonID: 0, DonConfigVersion: 0, WorkflowCID: [32]byte{}, - WorkflowName: workflowName, - WorkflowOwner: workflowOwner, + WorkflowName: [10]byte{}, + WorkflowOwner: [20]byte{}, ReportID: reportID, } @@ -73,7 +69,7 @@ func TestWriteTarget(t *testing.T) { validMetadata := capabilities.RequestMetadata{ WorkflowID: hex.EncodeToString(reportMetadata.WorkflowCID[:]), - WorkflowOwner: workflowOwnerString, + WorkflowOwner: hex.EncodeToString(reportMetadata.WorkflowOwner[:]), WorkflowName: hex.EncodeToString(reportMetadata.WorkflowName[:]), WorkflowExecutionID: hex.EncodeToString(reportMetadata.WorkflowExecutionID[:]), } @@ -222,44 +218,4 @@ func TestWriteTarget(t *testing.T) { _, err2 := writeTarget.Execute(ctx, req) require.Error(t, err2) }) - - tests := []struct { - name string - modifyRequest func(*capabilities.CapabilityRequest) - expectedError string - }{ - { - name: "non-matching WorkflowOwner", - modifyRequest: func(req *capabilities.CapabilityRequest) { - req.Metadata.WorkflowOwner = "nonmatchingowner" - }, - expectedError: "WorkflowOwner in the report does not match WorkflowOwner in the request metadata", - }, - { - name: "non-matching WorkflowName", - modifyRequest: func(req *capabilities.CapabilityRequest) { - req.Metadata.WorkflowName = hex.EncodeToString([]byte("nonmatchingname")) - }, - expectedError: "WorkflowName in the report does not match WorkflowName in the request metadata", - }, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - req := capabilities.CapabilityRequest{ - Metadata: validMetadata, - Config: config, - Inputs: validInputs, - } - tt.modifyRequest(&req) - - _, err := writeTarget.Execute(ctx, req) - if tt.expectedError == "" { - require.NoError(t, err) - } else { - require.Error(t, err) - require.Contains(t, err.Error(), tt.expectedError) - } - }) - } } diff --git a/core/capabilities/triggers/logevent/trigger.go b/core/capabilities/triggers/logevent/trigger.go index 334c3c3f30e..7ee76c6f44a 100644 --- a/core/capabilities/triggers/logevent/trigger.go +++ b/core/capabilities/triggers/logevent/trigger.go @@ -67,11 +67,6 @@ func newLogEventTrigger(ctx context.Context, return nil, nil, err } - err = contractReader.Start(ctx) - if err != nil { - return nil, nil, err - } - // Get current block HEAD/tip of the blockchain to start polling from latestHead, err := relayer.LatestHead(ctx) if err != nil { diff --git a/core/capabilities/webapi/outgoing_connector_handler.go b/core/capabilities/webapi/outgoing_connector_handler.go index a9ff9ee3aae..b00b82b2bd0 100644 --- a/core/capabilities/webapi/outgoing_connector_handler.go +++ b/core/capabilities/webapi/outgoing_connector_handler.go @@ -6,26 +6,19 @@ import ( "fmt" "sort" "sync" - "time" "github.com/pkg/errors" "github.com/smartcontractkit/chainlink-common/pkg/logger" - "github.com/smartcontractkit/chainlink-common/pkg/services" "github.com/smartcontractkit/chainlink/v2/core/services/gateway/api" "github.com/smartcontractkit/chainlink/v2/core/services/gateway/connector" "github.com/smartcontractkit/chainlink/v2/core/services/gateway/handlers/capabilities" "github.com/smartcontractkit/chainlink/v2/core/services/gateway/handlers/common" ) -const ( - defaultFetchTimeoutMs = 20_000 -) - var _ connector.GatewayConnectorHandler = &OutgoingConnectorHandler{} type OutgoingConnectorHandler struct { - services.StateMachine gc connector.GatewayConnector method string lggr logger.Logger @@ -56,24 +49,8 @@ func NewOutgoingConnectorHandler(gc connector.GatewayConnector, config ServiceCo } // HandleSingleNodeRequest sends a request to first available gateway node and blocks until response is received -// TODO: handle retries -func (c *OutgoingConnectorHandler) HandleSingleNodeRequest(ctx context.Context, messageID string, req capabilities.Request) (*api.Message, error) { - // set default timeout if not provided for all outgoing requests - if req.TimeoutMs == 0 { - req.TimeoutMs = defaultFetchTimeoutMs - } - - // Create a subcontext with the timeout plus some margin for the gateway to process the request - timeoutDuration := time.Duration(req.TimeoutMs) * time.Millisecond - margin := 100 * time.Millisecond - ctx, cancel := context.WithTimeout(ctx, timeoutDuration+margin) - defer cancel() - - payload, err := json.Marshal(req) - if err != nil { - return nil, fmt.Errorf("failed to marshal fetch request: %w", err) - } - +// TODO: handle retries and timeouts +func (c *OutgoingConnectorHandler) HandleSingleNodeRequest(ctx context.Context, messageID string, payload []byte) (*api.Message, error) { ch := make(chan *api.Message, 1) c.responseChsMu.Lock() c.responseChs[messageID] = ch @@ -96,15 +73,8 @@ func (c *OutgoingConnectorHandler) HandleSingleNodeRequest(ctx context.Context, } sort.Strings(gatewayIDs) - selectedGateway := gatewayIDs[0] - - l.Infow("selected gateway, awaiting connection", "gatewayID", selectedGateway) - - if err := c.gc.AwaitConnection(ctx, selectedGateway); err != nil { - return nil, errors.Wrap(err, "await connection canceled") - } - - if err := c.gc.SignAndSendToGateway(ctx, selectedGateway, body); err != nil { + err := c.gc.SignAndSendToGateway(ctx, gatewayIDs[0], body) + if err != nil { return nil, errors.Wrap(err, "failed to send request to gateway") } @@ -128,7 +98,7 @@ func (c *OutgoingConnectorHandler) HandleGatewayMessage(ctx context.Context, gat } l.Debugw("handling gateway request") switch body.Method { - case capabilities.MethodWebAPITarget, capabilities.MethodComputeAction, capabilities.MethodWorkflowSyncer: + case capabilities.MethodWebAPITarget, capabilities.MethodComputeAction: body := &msg.Body var payload capabilities.Response err := json.Unmarshal(body.Payload, &payload) @@ -155,28 +125,16 @@ func (c *OutgoingConnectorHandler) HandleGatewayMessage(ctx context.Context, gat } func (c *OutgoingConnectorHandler) Start(ctx context.Context) error { - return c.StartOnce("OutgoingConnectorHandler", func() error { - return c.gc.AddHandler([]string{c.method}, c) - }) + return c.gc.AddHandler([]string{c.method}, c) } func (c *OutgoingConnectorHandler) Close() error { - return c.StopOnce("OutgoingConnectorHandler", func() error { - return nil - }) -} - -func (c *OutgoingConnectorHandler) HealthReport() map[string]error { - return map[string]error{c.Name(): c.Healthy()} -} - -func (c *OutgoingConnectorHandler) Name() string { - return c.lggr.Name() + return nil } func validMethod(method string) bool { switch method { - case capabilities.MethodWebAPITarget, capabilities.MethodComputeAction, capabilities.MethodWorkflowSyncer: + case capabilities.MethodWebAPITarget, capabilities.MethodComputeAction: return true default: return false diff --git a/core/capabilities/webapi/outgoing_connector_handler_test.go b/core/capabilities/webapi/outgoing_connector_handler_test.go deleted file mode 100644 index 4a8c425d4f1..00000000000 --- a/core/capabilities/webapi/outgoing_connector_handler_test.go +++ /dev/null @@ -1,135 +0,0 @@ -package webapi - -import ( - "context" - "encoding/json" - "testing" - - "github.com/stretchr/testify/mock" - "github.com/stretchr/testify/require" - - "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" - "github.com/smartcontractkit/chainlink/v2/core/logger" - "github.com/smartcontractkit/chainlink/v2/core/utils/matches" - - "github.com/smartcontractkit/chainlink/v2/core/services/gateway/api" - gcmocks "github.com/smartcontractkit/chainlink/v2/core/services/gateway/connector/mocks" - ghcapabilities "github.com/smartcontractkit/chainlink/v2/core/services/gateway/handlers/capabilities" - "github.com/smartcontractkit/chainlink/v2/core/services/gateway/handlers/common" -) - -func TestHandleSingleNodeRequest(t *testing.T) { - t.Run("OK-timeout_is_not_specify_default_timeout_is_expected", func(t *testing.T) { - ctx := tests.Context(t) - log := logger.TestLogger(t) - connector := gcmocks.NewGatewayConnector(t) - var defaultConfig = ServiceConfig{ - RateLimiter: common.RateLimiterConfig{ - GlobalRPS: 100.0, - GlobalBurst: 100, - PerSenderRPS: 100.0, - PerSenderBurst: 100, - }, - } - connectorHandler, err := NewOutgoingConnectorHandler(connector, defaultConfig, ghcapabilities.MethodComputeAction, log) - require.NoError(t, err) - - msgID := "msgID" - testURL := "http://localhost:8080" - connector.EXPECT().DonID().Return("donID") - connector.EXPECT().AwaitConnection(matches.AnyContext, "gateway1").Return(nil) - connector.EXPECT().GatewayIDs().Return([]string{"gateway1"}) - - // build the expected body with the default timeout - req := ghcapabilities.Request{ - URL: testURL, - TimeoutMs: defaultFetchTimeoutMs, - } - payload, err := json.Marshal(req) - require.NoError(t, err) - - expectedBody := &api.MessageBody{ - MessageId: msgID, - DonId: connector.DonID(), - Method: ghcapabilities.MethodComputeAction, - Payload: payload, - } - - // expect the request body to contain the default timeout - connector.EXPECT().SignAndSendToGateway(mock.Anything, "gateway1", expectedBody).Run(func(ctx context.Context, gatewayID string, msg *api.MessageBody) { - connectorHandler.HandleGatewayMessage(ctx, "gateway1", gatewayResponse(t, msgID)) - }).Return(nil).Times(1) - - _, err = connectorHandler.HandleSingleNodeRequest(ctx, msgID, ghcapabilities.Request{ - URL: testURL, - }) - require.NoError(t, err) - }) - - t.Run("OK-timeout_is_specified", func(t *testing.T) { - ctx := tests.Context(t) - log := logger.TestLogger(t) - connector := gcmocks.NewGatewayConnector(t) - var defaultConfig = ServiceConfig{ - RateLimiter: common.RateLimiterConfig{ - GlobalRPS: 100.0, - GlobalBurst: 100, - PerSenderRPS: 100.0, - PerSenderBurst: 100, - }, - } - connectorHandler, err := NewOutgoingConnectorHandler(connector, defaultConfig, ghcapabilities.MethodComputeAction, log) - require.NoError(t, err) - - msgID := "msgID" - testURL := "http://localhost:8080" - connector.EXPECT().DonID().Return("donID") - connector.EXPECT().AwaitConnection(matches.AnyContext, "gateway1").Return(nil) - connector.EXPECT().GatewayIDs().Return([]string{"gateway1"}) - - // build the expected body with the defined timeout - req := ghcapabilities.Request{ - URL: testURL, - TimeoutMs: 40000, - } - payload, err := json.Marshal(req) - require.NoError(t, err) - - expectedBody := &api.MessageBody{ - MessageId: msgID, - DonId: connector.DonID(), - Method: ghcapabilities.MethodComputeAction, - Payload: payload, - } - - // expect the request body to contain the defined timeout - connector.EXPECT().SignAndSendToGateway(mock.Anything, "gateway1", expectedBody).Run(func(ctx context.Context, gatewayID string, msg *api.MessageBody) { - connectorHandler.HandleGatewayMessage(ctx, "gateway1", gatewayResponse(t, msgID)) - }).Return(nil).Times(1) - - _, err = connectorHandler.HandleSingleNodeRequest(ctx, msgID, ghcapabilities.Request{ - URL: testURL, - TimeoutMs: 40000, - }) - require.NoError(t, err) - }) -} - -func gatewayResponse(t *testing.T, msgID string) *api.Message { - headers := map[string]string{"Content-Type": "application/json"} - body := []byte("response body") - responsePayload, err := json.Marshal(ghcapabilities.Response{ - StatusCode: 200, - Headers: headers, - Body: body, - ExecutionError: false, - }) - require.NoError(t, err) - return &api.Message{ - Body: api.MessageBody{ - MessageId: msgID, - Method: ghcapabilities.MethodWebAPITarget, - Payload: responsePayload, - }, - } -} diff --git a/core/capabilities/webapi/target/target.go b/core/capabilities/webapi/target/target.go index 4934ab382d5..4576f95a54e 100644 --- a/core/capabilities/webapi/target/target.go +++ b/core/capabilities/webapi/target/target.go @@ -5,7 +5,6 @@ import ( "encoding/json" "fmt" "strings" - "time" "github.com/smartcontractkit/chainlink-common/pkg/capabilities" "github.com/smartcontractkit/chainlink-common/pkg/logger" @@ -58,12 +57,6 @@ func (c *Capability) Start(ctx context.Context) error { } func (c *Capability) Close() error { - ctx, cancel := context.WithTimeout(context.Background(), time.Second) - defer cancel() - err := c.registry.Remove(ctx, c.capabilityInfo.ID) - if err != nil { - return err - } return nil } @@ -135,13 +128,18 @@ func (c *Capability) Execute(ctx context.Context, req capabilities.CapabilityReq return capabilities.CapabilityResponse{}, err } + payloadBytes, err := json.Marshal(payload) + if err != nil { + return capabilities.CapabilityResponse{}, err + } + // Default to SingleNode delivery mode deliveryMode := defaultIfNil(workflowCfg.DeliveryMode, webapi.SingleNode) switch deliveryMode { case webapi.SingleNode: // blocking call to handle single node request. waits for response from gateway - resp, err := c.connectorHandler.HandleSingleNodeRequest(ctx, messageID, payload) + resp, err := c.connectorHandler.HandleSingleNodeRequest(ctx, messageID, payloadBytes) if err != nil { return capabilities.CapabilityResponse{}, err } diff --git a/core/capabilities/webapi/target/target_test.go b/core/capabilities/webapi/target/target_test.go index 1af9a107054..f51cdcd0d70 100644 --- a/core/capabilities/webapi/target/target_test.go +++ b/core/capabilities/webapi/target/target_test.go @@ -194,7 +194,7 @@ func TestCapability_Execute(t *testing.T) { require.NoError(t, err) gatewayResp := gatewayResponse(t, msgID) - th.connector.EXPECT().AwaitConnection(mock.Anything, "gateway1").Return(nil) + th.connector.On("SignAndSendToGateway", mock.Anything, "gateway1", mock.Anything).Return(nil).Run(func(args mock.Arguments) { th.connectorHandler.HandleGatewayMessage(ctx, "gateway1", gatewayResp) }).Once() diff --git a/core/capabilities/webapi/trigger/trigger.go b/core/capabilities/webapi/trigger/trigger.go index 712cf38a4cc..c607f0dbb6f 100644 --- a/core/capabilities/webapi/trigger/trigger.go +++ b/core/capabilities/webapi/trigger/trigger.go @@ -6,7 +6,6 @@ import ( "errors" "fmt" "sync" - "time" ethCommon "github.com/ethereum/go-ethereum/common" @@ -257,12 +256,6 @@ func (h *triggerConnectorHandler) Start(ctx context.Context) error { } func (h *triggerConnectorHandler) Close() error { return h.StopOnce("GatewayConnectorServiceWrapper", func() error { - ctx, cancel := context.WithTimeout(context.Background(), time.Second) - defer cancel() - err := h.registry.Remove(ctx, h.ID) - if err != nil { - return err - } return nil }) } diff --git a/core/chainlink.Dockerfile b/core/chainlink.Dockerfile index 82858f3437c..753172a1a9f 100644 --- a/core/chainlink.Dockerfile +++ b/core/chainlink.Dockerfile @@ -1,5 +1,5 @@ # Build image: Chainlink binary -FROM golang:1.23-bullseye as buildgo +FROM golang:1.22-bullseye as buildgo RUN go version WORKDIR /chainlink @@ -31,7 +31,7 @@ RUN go list -m -f "{{.Dir}}" github.com/smartcontractkit/chainlink-feeds | xargs RUN go list -m -f "{{.Dir}}" github.com/smartcontractkit/chainlink-solana | xargs -I % ln -s % /chainlink-solana # Build image: Plugins -FROM golang:1.23-bullseye as buildplugins +FROM golang:1.22-bullseye as buildplugins RUN go version WORKDIR /chainlink-feeds diff --git a/core/chains/evm/client/chain_client.go b/core/chains/evm/client/chain_client.go index 0835b4c0ed8..79c2eef9769 100644 --- a/core/chains/evm/client/chain_client.go +++ b/core/chains/evm/client/chain_client.go @@ -2,7 +2,6 @@ package client import ( "context" - "errors" "math/big" "sync" "time" @@ -101,7 +100,7 @@ type chainClient struct { *big.Int, *RPCClient, ] - txSender *commonclient.TransactionSender[*types.Transaction, *SendTxResult, *big.Int, *RPCClient] + txSender *commonclient.TransactionSender[*types.Transaction, *big.Int, *RPCClient] logger logger.SugaredLogger chainType chaintype.ChainType clientErrors evmconfig.ClientErrors @@ -130,12 +129,16 @@ func NewChainClient( deathDeclarationDelay, ) - txSender := commonclient.NewTransactionSender[*types.Transaction, *SendTxResult, *big.Int, *RPCClient]( + classifySendError := func(tx *types.Transaction, err error) commonclient.SendTxReturnCode { + return ClassifySendError(err, clientErrors, logger.Sugared(logger.Nop()), tx, common.Address{}, chainType.IsL2()) + } + + txSender := commonclient.NewTransactionSender[*types.Transaction, *big.Int, *RPCClient]( lggr, chainID, chainFamily, multiNode, - NewSendTxResult, + classifySendError, 0, // use the default value provided by the implementation ) @@ -373,20 +376,15 @@ func (c *chainClient) PendingNonceAt(ctx context.Context, account common.Address } func (c *chainClient) SendTransaction(ctx context.Context, tx *types.Transaction) error { - var result *SendTxResult if c.chainType == chaintype.ChainHedera { activeRPC, err := c.multiNode.SelectRPC() if err != nil { return err } - result = activeRPC.SendTransaction(ctx, tx) - } else { - result = c.txSender.SendTransaction(ctx, tx) - } - if result == nil { - return errors.New("SendTransaction failed: result is nil") + return activeRPC.SendTransaction(ctx, tx) } - return result.Error() + _, err := c.txSender.SendTransaction(ctx, tx) + return err } func (c *chainClient) SendTransactionReturnCode(ctx context.Context, tx *types.Transaction, fromAddress common.Address) (commonclient.SendTxReturnCode, error) { diff --git a/core/chains/evm/client/errors.go b/core/chains/evm/client/errors.go index bde97185580..d47d97660b1 100644 --- a/core/chains/evm/client/errors.go +++ b/core/chains/evm/client/errors.go @@ -64,7 +64,6 @@ const ( ServiceUnavailable TerminallyStuck TooManyResults - ServiceTimeout ) type ClientErrors map[int]*regexp.Regexp @@ -161,8 +160,7 @@ var arbitrum = ClientErrors{ Fatal: arbitrumFatal, L2FeeTooLow: regexp.MustCompile(`(: |^)max fee per gas less than block base fee(:|$)`), L2Full: regexp.MustCompile(`(: |^)(queue full|sequencer pending tx pool full, please try again)(:|$)`), - ServiceUnavailable: regexp.MustCompile(`(: |^)502 Bad Gateway: [\s\S]*$|network is unreachable|i/o timeout|(: |^)503 Service Temporarily Unavailable(:|$)`), - ServiceTimeout: regexp.MustCompile(`(: |^)408 Request Timeout(:|$)`), + ServiceUnavailable: regexp.MustCompile(`(: |^)502 Bad Gateway: [\s\S]*$|network is unreachable|i/o timeout`), } // Treasure @@ -242,7 +240,7 @@ var harmony = ClientErrors{ var zkSync = ClientErrors{ NonceTooLow: regexp.MustCompile(`(?:: |^)nonce too low\..+actual: \d*$`), NonceTooHigh: regexp.MustCompile(`(?:: |^)nonce too high\..+actual: \d*$`), - TerminallyUnderpriced: regexp.MustCompile(`(?:: |^)(max fee per gas less than block base fee|virtual machine entered unexpected state. (?:P|p)lease contact developers and provide transaction details that caused this error. Error description: (?:The operator included transaction with an unacceptable gas price|Assertion error: Fair pubdata price too high))$`), + TerminallyUnderpriced: regexp.MustCompile(`(?:: |^)(max fee per gas less than block base fee|virtual machine entered unexpected state. please contact developers and provide transaction details that caused this error. Error description: The operator included transaction with an unacceptable gas price)$`), InsufficientEth: regexp.MustCompile(`(?:: |^)(?:insufficient balance for transfer$|insufficient funds for gas + value)`), TxFeeExceedsCap: regexp.MustCompile(`(?:: |^)max priority fee per gas higher than max fee per gas$`), // intrinsic gas too low - gas limit less than 14700 @@ -400,11 +398,6 @@ func (s *SendError) IsServiceUnavailable(configErrors *ClientErrors) bool { return s.is(ServiceUnavailable, configErrors) || pkgerrors.Is(s.err, commonclient.ErroringNodeError) } -// IsServiceTimeout indicates if the error was caused by a service timeout -func (s *SendError) IsServiceTimeout(configErrors *ClientErrors) bool { - return s.is(ServiceTimeout, configErrors) -} - // IsTerminallyStuck indicates if a transaction was stuck without any chance of inclusion func (s *SendError) IsTerminallyStuckConfigError(configErrors *ClientErrors) bool { return s.is(TerminallyStuck, configErrors) @@ -626,10 +619,6 @@ func ClassifySendError(err error, clientErrors config.ClientErrors, lggr logger. lggr.Errorw(fmt.Sprintf("service unavailable while sending transaction %x", tx.Hash()), "err", sendError, "etx", tx) return commonclient.Retryable } - if sendError.IsServiceTimeout(configErrors) { - lggr.Errorw(fmt.Sprintf("service timed out while sending transaction %x", tx.Hash()), "err", sendError, "etx", tx) - return commonclient.Retryable - } if sendError.IsTimeout() { lggr.Errorw(fmt.Sprintf("timeout while sending transaction %x", tx.Hash()), "err", sendError, "etx", tx) return commonclient.Retryable @@ -677,7 +666,7 @@ var drpc = ClientErrors{ // Linkpool, Blockdaemon, and Chainstack all return "request timed out" if the log results are too large for them to process var defaultClient = ClientErrors{ - TooManyResults: regexp.MustCompile(`request timed out|408 Request Timed Out`), + TooManyResults: regexp.MustCompile(`request timed out`), } // JSON-RPC error codes which can indicate a refusal of the server to process an eth_getLogs request because the result set is too large diff --git a/core/chains/evm/client/errors_test.go b/core/chains/evm/client/errors_test.go index 1f9aaa53365..7bdc87840d0 100644 --- a/core/chains/evm/client/errors_test.go +++ b/core/chains/evm/client/errors_test.go @@ -172,7 +172,6 @@ func Test_Eth_Errors(t *testing.T) { {"intrinsic gas too low", true, "Klaytn"}, {"max fee per gas less than block base fee", true, "zkSync"}, {"virtual machine entered unexpected state. please contact developers and provide transaction details that caused this error. Error description: The operator included transaction with an unacceptable gas price", true, "zkSync"}, - {"failed to validate the transaction. reason: Validation revert: virtual machine entered unexpected state. Please contact developers and provide transaction details that caused this error. Error description: Assertion error: Fair pubdata price too high", true, "zkSync"}, {"client error terminally underpriced", true, "tomlConfig"}, {"gas price less than block base fee", true, "aStar"}, {"[Request ID: e4d09e44-19a4-4eb7-babe-270db4c2ebc9] Gas price '830000000000' is below configured minimum gas price '950000000000'", true, "hedera"}, @@ -245,7 +244,6 @@ func Test_Eth_Errors(t *testing.T) { {"network is unreachable", true, "Arbitrum"}, {"client error service unavailable", true, "tomlConfig"}, {"[Request ID: 825608a8-fd8a-4b5b-aea7-92999509306d] Error invoking RPC: [Request ID: 825608a8-fd8a-4b5b-aea7-92999509306d] Transaction execution returns a null value for transaction", true, "hedera"}, - {"call failed: 503 Service Temporarily Unavailable: \r\n503 Service Temporarily Unavailable\r\n\r\n

503 Service Temporarily Unavailable

\r\n\r\n\r\n", true, "Arbitrum"}, } for _, test := range tests { err = evmclient.NewSendErrorS(test.message) @@ -261,20 +259,6 @@ func Test_Eth_Errors(t *testing.T) { } }) - t.Run("IsServiceTimeout", func(t *testing.T) { - tests := []errorCase{ - {"call failed: 408 Request Timeout: {", true, "Arbitrum"}, - {"408 Request Timeout: {\"id\":303,\"jsonrpc\":\"2.0\",\"error\":{\"code\\\":-32009,\\\"message\\\":\\\"request timeout\\\"}}\",\"errVerbose\":\"408 Request Timeout:\n", true, "Arbitrum"}, - {"request timeout", false, "tomlConfig"}, - } - for _, test := range tests { - err = evmclient.NewSendErrorS(test.message) - assert.Equal(t, err.IsServiceTimeout(clientErrors), test.expect) - err = newSendErrorWrapped(test.message) - assert.Equal(t, err.IsServiceTimeout(clientErrors), test.expect) - } - }) - t.Run("IsTxFeeExceedsCap", func(t *testing.T) { tests := []errorCase{ {"tx fee (1.10 ether) exceeds the configured cap (1.00 ether)", true, "geth"}, diff --git a/core/chains/evm/client/rpc_client.go b/core/chains/evm/client/rpc_client.go index 97046b4eff2..8d6e25d5540 100644 --- a/core/chains/evm/client/rpc_client.go +++ b/core/chains/evm/client/rpc_client.go @@ -98,7 +98,6 @@ type RPCClient struct { newHeadsPollInterval time.Duration rpcTimeout time.Duration chainType chaintype.ChainType - clientErrors config.ClientErrors ws *rawclient http *rawclient @@ -123,7 +122,7 @@ type RPCClient struct { } var _ commonclient.RPCClient[*big.Int, *evmtypes.Head] = (*RPCClient)(nil) -var _ commonclient.SendTxRPCClient[*types.Transaction, *SendTxResult] = (*RPCClient)(nil) +var _ commonclient.SendTxRPCClient[*types.Transaction] = (*RPCClient)(nil) func NewRPCClient( cfg config.NodePool, @@ -142,7 +141,6 @@ func NewRPCClient( largePayloadRPCTimeout: largePayloadRPCTimeout, rpcTimeout: rpcTimeout, chainType: chainType, - clientErrors: cfg.Errors(), } r.cfg = cfg r.name = name @@ -804,29 +802,7 @@ func (r *RPCClient) BlockByNumberGeth(ctx context.Context, number *big.Int) (blo return } -type SendTxResult struct { - err error - code commonclient.SendTxReturnCode -} - -var _ commonclient.SendTxResult = (*SendTxResult)(nil) - -func NewSendTxResult(err error) *SendTxResult { - result := &SendTxResult{ - err: err, - } - return result -} - -func (r *SendTxResult) Error() error { - return r.err -} - -func (r *SendTxResult) Code() commonclient.SendTxReturnCode { - return r.code -} - -func (r *RPCClient) SendTransaction(ctx context.Context, tx *types.Transaction) *SendTxResult { +func (r *RPCClient) SendTransaction(ctx context.Context, tx *types.Transaction) error { ctx, cancel, ws, http := r.makeLiveQueryCtxAndSafeGetClients(ctx, r.largePayloadRPCTimeout) defer cancel() lggr := r.newRqLggr().With("tx", tx) @@ -843,10 +819,7 @@ func (r *RPCClient) SendTransaction(ctx context.Context, tx *types.Transaction) r.logResult(lggr, err, duration, r.getRPCDomain(), "SendTransaction") - return &SendTxResult{ - err: err, - code: ClassifySendError(err, r.clientErrors, logger.Sugared(logger.Nop()), tx, common.Address{}, r.chainType.IsL2()), - } + return err } func (r *RPCClient) SimulateTransaction(ctx context.Context, tx *types.Transaction) error { diff --git a/core/chains/evm/client/rpc_client_test.go b/core/chains/evm/client/rpc_client_test.go index 109a49d6e2f..c8edc7c557c 100644 --- a/core/chains/evm/client/rpc_client_test.go +++ b/core/chains/evm/client/rpc_client_test.go @@ -518,8 +518,7 @@ func TestRpcClientLargePayloadTimeout(t *testing.T) { { Name: "SendTransaction", Fn: func(ctx context.Context, rpc *client.RPCClient) error { - result := rpc.SendTransaction(ctx, types.NewTx(&types.LegacyTx{})) - return result.Error() + return rpc.SendTransaction(ctx, types.NewTx(&types.LegacyTx{})) }, }, { diff --git a/core/chains/evm/client/simulated_backend_client.go b/core/chains/evm/client/simulated_backend_client.go index fd645203856..c44cebe0840 100644 --- a/core/chains/evm/client/simulated_backend_client.go +++ b/core/chains/evm/client/simulated_backend_client.go @@ -5,7 +5,6 @@ import ( "context" "errors" "fmt" - "math" "math/big" "strings" "testing" @@ -358,12 +357,9 @@ func (c *SimulatedBackendClient) SubscribeToHeads( case h := <-ch: var head *evmtypes.Head if h != nil { - if h.Time > math.MaxInt64 { - c.t.Fatalf("time overflows int64: %d", h.Time) - } head = &evmtypes.Head{ Difficulty: h.Difficulty, - Timestamp: time.Unix(int64(h.Time), 0), + Timestamp: time.Unix(int64(h.Time), 0), //nolint:gosec Number: h.Number.Int64(), Hash: h.Hash(), ParentHash: h.ParentHash, diff --git a/core/chains/evm/config/chain_scoped_transactions.go b/core/chains/evm/config/chain_scoped_transactions.go index 8cddce20e65..27edb12648a 100644 --- a/core/chains/evm/config/chain_scoped_transactions.go +++ b/core/chains/evm/config/chain_scoped_transactions.go @@ -11,10 +11,6 @@ type transactionsConfig struct { c toml.Transactions } -func (t *transactionsConfig) Enabled() bool { - return *t.c.Enabled -} - func (t *transactionsConfig) ForwardersEnabled() bool { return *t.c.ForwardersEnabled } diff --git a/core/chains/evm/config/config.go b/core/chains/evm/config/config.go index fbaf1ff6dda..f2a571f94b0 100644 --- a/core/chains/evm/config/config.go +++ b/core/chains/evm/config/config.go @@ -103,7 +103,6 @@ type ClientErrors interface { } type Transactions interface { - Enabled() bool ForwardersEnabled() bool ReaperInterval() time.Duration ResendAfterThreshold() time.Duration diff --git a/core/chains/evm/config/config_test.go b/core/chains/evm/config/config_test.go index ab0d600efe0..7eb13458f56 100644 --- a/core/chains/evm/config/config_test.go +++ b/core/chains/evm/config/config_test.go @@ -219,20 +219,9 @@ func TestChainScopedConfig(t *testing.T) { assert.Equal(t, false, cfg3.EVM().LogBroadcasterEnabled()) }) - }) - - t.Run("EVM.Transactions.Enabled", func(t *testing.T) { - t.Run("turn on EVM.Transactions.Enabled by default", func(t *testing.T) { - assert.True(t, cfg.EVM().Transactions().Enabled()) - }) - t.Run("verify EVM.Transactions.Enabled is set correctly", func(t *testing.T) { - val := false - cfg3 := testutils.NewTestChainScopedConfig(t, func(c *toml.EVMConfig) { - c.Transactions.Enabled = ptr(val) - }) + t.Run("use Noop logBroadcaster when LogBroadcaster is disabled", func(t *testing.T) { - assert.False(t, cfg3.EVM().Transactions().Enabled()) }) }) } diff --git a/core/chains/evm/config/toml/config.go b/core/chains/evm/config/toml/config.go index 807e1141791..0505449943e 100644 --- a/core/chains/evm/config/toml/config.go +++ b/core/chains/evm/config/toml/config.go @@ -472,7 +472,6 @@ func (c *Chain) ValidateConfig() (err error) { } type Transactions struct { - Enabled *bool ForwardersEnabled *bool MaxInFlight *uint32 MaxQueued *uint32 @@ -484,9 +483,6 @@ type Transactions struct { } func (t *Transactions) setFrom(f *Transactions) { - if v := f.Enabled; v != nil { - t.Enabled = v - } if v := f.ForwardersEnabled; v != nil { t.ForwardersEnabled = v } diff --git a/core/chains/evm/config/toml/defaults.go b/core/chains/evm/config/toml/defaults.go index 6f03575056b..0885d94e6df 100644 --- a/core/chains/evm/config/toml/defaults.go +++ b/core/chains/evm/config/toml/defaults.go @@ -236,6 +236,7 @@ func (c *Chain) SetFrom(f *Chain) { if v := f.FinalizedBlockOffset; v != nil { c.FinalizedBlockOffset = v } + if v := f.NoNewFinalizedHeadsThreshold; v != nil { c.NoNewFinalizedHeadsThreshold = v } diff --git a/core/chains/evm/config/toml/defaults/Avalanche_Fuji.toml b/core/chains/evm/config/toml/defaults/Avalanche_Fuji.toml index 2fd63004531..fbcc8e6f058 100644 --- a/core/chains/evm/config/toml/defaults/Avalanche_Fuji.toml +++ b/core/chains/evm/config/toml/defaults/Avalanche_Fuji.toml @@ -11,8 +11,9 @@ FinalizedBlockOffset = 2 NoNewFinalizedHeadsThreshold = '1m' [GasEstimator] -PriceMin = '1 gwei' -PriceDefault = '1 gwei' +PriceDefault = '25 gwei' +PriceMax = '115792089237316195423570985008687907853269984665.640564039457584007913129639935 tether' +PriceMin = '25 gwei' [GasEstimator.BlockHistory] BlockHistorySize = 24 diff --git a/core/chains/evm/config/toml/defaults/Avalanche_Mainnet.toml b/core/chains/evm/config/toml/defaults/Avalanche_Mainnet.toml index 9a8f32d3288..309fdab1db9 100644 --- a/core/chains/evm/config/toml/defaults/Avalanche_Mainnet.toml +++ b/core/chains/evm/config/toml/defaults/Avalanche_Mainnet.toml @@ -11,8 +11,9 @@ FinalizedBlockOffset = 2 NoNewFinalizedHeadsThreshold = '1m' [GasEstimator] -PriceMin = '1 gwei' -PriceDefault = '1 gwei' +PriceDefault = '25 gwei' +PriceMax = '115792089237316195423570985008687907853269984665.640564039457584007913129639935 tether' +PriceMin = '25 gwei' [GasEstimator.BlockHistory] # Average block time of 2s diff --git a/core/chains/evm/config/toml/defaults/BOB_Mainnet.toml b/core/chains/evm/config/toml/defaults/BOB_Mainnet.toml deleted file mode 100644 index 3211ee9caa7..00000000000 --- a/core/chains/evm/config/toml/defaults/BOB_Mainnet.toml +++ /dev/null @@ -1,27 +0,0 @@ -ChainID = '60808' -# OP stack https://docs.gobob.xyz/learn/introduction/stack-overview#rollup-layer -ChainType = 'optimismBedrock' -# FinalityDepth in mainnet showed more than 3k -FinalityDepth = 3150 -# block_time was: 2s, adding 1 second buffer -LogPollInterval = '3s' - -# finality_depth * block_time / 60 secs = ~105 min (finality time) -NoNewFinalizedHeadsThreshold = '110m' - -FinalityTagEnabled = true - -[GasEstimator] -EIP1559DynamicFees = true -Mode = 'FeeHistory' - -[GasEstimator.FeeHistory] -# block_time was: 2s, per recommendation skip 1-2 blocks -CacheTimeout = '4s' - -[GasEstimator.BlockHistory] -BlockHistorySize = 100 - -[GasEstimator.DAOracle] -OracleType = 'opstack' -OracleAddress = '0x420000000000000000000000000000000000000F' diff --git a/core/chains/evm/config/toml/defaults/BOB_Testnet.toml b/core/chains/evm/config/toml/defaults/BOB_Testnet.toml deleted file mode 100644 index 064137f97c7..00000000000 --- a/core/chains/evm/config/toml/defaults/BOB_Testnet.toml +++ /dev/null @@ -1,27 +0,0 @@ -ChainID = '808813' -# OP stack https://docs.gobob.xyz/learn/introduction/stack-overview#rollup-layer -ChainType = 'optimismBedrock' -# FinalityDepth in mainnet showed more than 3k -FinalityDepth = 3150 -# block_time was: 2s, adding 1 second buffer -LogPollInterval = '3s' - -# finality_depth * block_time / 60 secs = ~105 min (finality time) -NoNewFinalizedHeadsThreshold = '110m' - -FinalityTagEnabled = true - -[GasEstimator] -EIP1559DynamicFees = true -Mode = 'FeeHistory' - -[GasEstimator.FeeHistory] -# block_time was: 2s, per recommendation skip 1-2 blocks -CacheTimeout = '4s' - -[GasEstimator.BlockHistory] -BlockHistorySize = 100 - -[GasEstimator.DAOracle] -OracleType = 'opstack' -OracleAddress = '0x420000000000000000000000000000000000000F' diff --git a/core/chains/evm/config/toml/defaults/Berachain_Testnet.toml b/core/chains/evm/config/toml/defaults/Berachain_Testnet.toml deleted file mode 100644 index 7024d12a99f..00000000000 --- a/core/chains/evm/config/toml/defaults/Berachain_Testnet.toml +++ /dev/null @@ -1,19 +0,0 @@ -ChainID = '80084' -# finality_depth: instant -FinalityDepth = 10 -# block_time: 5s, adding 1 second buffer -LogPollInterval = '6s' - -# finality_depth * block_time / 60 secs = ~0.8 min (finality time) -NoNewFinalizedHeadsThreshold = '5m' - -[GasEstimator] -EIP1559DynamicFees = true -Mode = 'FeeHistory' - -[GasEstimator.FeeHistory] -# block_time was: 5s, per recommendation skip 1-2 blocks -CacheTimeout = '10s' - -[GasEstimator.BlockHistory] -BlockHistorySize = 100 diff --git a/core/chains/evm/config/toml/defaults/Bsquared_Mainnet.toml b/core/chains/evm/config/toml/defaults/Bsquared_Mainnet.toml deleted file mode 100644 index 82fb4567771..00000000000 --- a/core/chains/evm/config/toml/defaults/Bsquared_Mainnet.toml +++ /dev/null @@ -1,27 +0,0 @@ -ChainID = '223' -# OP stack from questionnaire https://docs.google.com/spreadsheets/d/1l8dx1GzxEnjgwH5x3vB60FUr5iFALzPcs6W_wOAiuDs/edit?gid=625078687#gid=625078687 -ChainType = 'optimismBedrock' -# finality_depth was: ~1900 -FinalityDepth = 2000 -# block_time: ~2s, adding 1 second buffer -LogPollInterval = '3s' - -# finality_depth * block_time / 60 secs = ~66 min (finality time) -NoNewFinalizedHeadsThreshold = '70m' - -FinalityTagEnabled = true - -[GasEstimator] -EIP1559DynamicFees = true -Mode = 'FeeHistory' - -[GasEstimator.FeeHistory] -# block_time was: 2s, per recommendation skip 1-2 blocks -CacheTimeout = '4s' - -[GasEstimator.BlockHistory] -BlockHistorySize = 100 - -[GasEstimator.DAOracle] -OracleType = 'opstack' -OracleAddress = '0x420000000000000000000000000000000000000F' \ No newline at end of file diff --git a/core/chains/evm/config/toml/defaults/Bsquared_Testnet.toml b/core/chains/evm/config/toml/defaults/Bsquared_Testnet.toml deleted file mode 100644 index 925ef6bea89..00000000000 --- a/core/chains/evm/config/toml/defaults/Bsquared_Testnet.toml +++ /dev/null @@ -1,27 +0,0 @@ -ChainID = '1123' -# OP stack from questionnaire https://docs.google.com/spreadsheets/d/1l8dx1GzxEnjgwH5x3vB60FUr5iFALzPcs6W_wOAiuDs/edit?gid=625078687#gid=625078687 -ChainType = 'optimismBedrock' -# finality_depth was: ~1900 -FinalityDepth = 2000 -# block_time: ~2s, adding 1 second buffer -LogPollInterval = '3s' - -# finality_depth * block_time / 60 secs = ~66 min (finality time) -NoNewFinalizedHeadsThreshold = '70m' - -FinalityTagEnabled = true - -[GasEstimator] -EIP1559DynamicFees = true -Mode = 'FeeHistory' - -[GasEstimator.FeeHistory] -# block_time was: 2s, per recommendation skip 1-2 blocks -CacheTimeout = '4s' - -[GasEstimator.BlockHistory] -BlockHistorySize = 100 - -[GasEstimator.DAOracle] -OracleType = 'opstack' -OracleAddress = '0x420000000000000000000000000000000000000F' diff --git a/core/chains/evm/config/toml/defaults/Ronin_Mainnet.toml b/core/chains/evm/config/toml/defaults/Ronin_Mainnet.toml deleted file mode 100644 index 051c528e0f3..00000000000 --- a/core/chains/evm/config/toml/defaults/Ronin_Mainnet.toml +++ /dev/null @@ -1,11 +0,0 @@ -ChainID = '2020' -FinalityTagEnabled = true -# Ronin produces blocks every 3 seconds -LogPollInterval = "3s" -NoNewHeadsThreshold = "3m" -LinkContractAddress = '0x3902228D6A3d2Dc44731fD9d45FeE6a61c722D0b' - -[GasEstimator] -# Ronin uses default gas price of 20 gwei https://docs.skymavis.com/mavis/mpc/guides/estimate-gas#overview -Mode = 'FeeHistory' -PriceMax = "1000 gwei" diff --git a/core/chains/evm/config/toml/defaults/Ronin_Saigon.toml b/core/chains/evm/config/toml/defaults/Ronin_Saigon.toml deleted file mode 100644 index 48695a9ec08..00000000000 --- a/core/chains/evm/config/toml/defaults/Ronin_Saigon.toml +++ /dev/null @@ -1,11 +0,0 @@ -ChainID = '2021' -FinalityTagEnabled = true -# Ronin produces blocks every 3 seconds -LogPollInterval = "3s" -NoNewHeadsThreshold = "3m" -LinkContractAddress = '0x5bB50A6888ee6a67E22afFDFD9513be7740F1c15' - -[GasEstimator] -# Ronin uses default gas price of 20 gwei https://docs.skymavis.com/mavis/mpc/guides/estimate-gas#overview -Mode = 'FeeHistory' -PriceMax = "1000 gwei" diff --git a/core/chains/evm/config/toml/defaults/Unichain_Testnet.toml b/core/chains/evm/config/toml/defaults/Unichain_Testnet.toml deleted file mode 100644 index 6754f49a569..00000000000 --- a/core/chains/evm/config/toml/defaults/Unichain_Testnet.toml +++ /dev/null @@ -1,30 +0,0 @@ -ChainID = '1301' -# OP stack: https://docs.unichain.org/docs/getting-started/set-up-a-node#overview -ChainType = 'optimismBedrock' -# finality_depth was: ~1900 -FinalityDepth = 2000 -# block_time was: ~1s, adding 1 second buffer -LogPollInterval = '2s' - -# batching_size_finalization_percentage = 30% according to the explorer batching view -# ( batching_size_finalization_percentage * finality_depth) * block_time / 60 secs = ~10 min (finality time) -# After running soak tests using 10m threw issues as there are batchs that take 35m, so we are bumping it to 45m to be sure -NoNewFinalizedHeadsThreshold = '45m' - -FinalityTagEnabled = true - -[GasEstimator] -EIP1559DynamicFees = true -Mode = 'FeeHistory' - -[GasEstimator.FeeHistory] -# block_time was: 1s, per recommendation skip 1-2 blocks -CacheTimeout = '2s' - -[GasEstimator.BlockHistory] -# As we see blocks containing between ~[8-12]tx, to get about ~1000 tx to check we would need to rougly go 100 tx back -BlockHistorySize = 100 - -[GasEstimator.DAOracle] -OracleType = 'opstack' -OracleAddress = '0x420000000000000000000000000000000000000F' diff --git a/core/chains/evm/config/toml/defaults/Worldchain_Mainnet.toml b/core/chains/evm/config/toml/defaults/Worldchain_Mainnet.toml deleted file mode 100644 index 24647e19fd6..00000000000 --- a/core/chains/evm/config/toml/defaults/Worldchain_Mainnet.toml +++ /dev/null @@ -1,27 +0,0 @@ -ChainID = '480' -# OP stack: https://worldcoin.notion.site/World-Chain-Developer-Preview-Guide-23c94a67683f4e71986e5303ab88c9f3 -ChainType = 'optimismBedrock' -# finality_depth was: ~2400 -FinalityDepth = 2500 -# block_time was: 2s, adding 1 second buffer -LogPollInterval = '3s' - -# finality_depth * block_time / 60 secs = ~83 min (finality time) -NoNewFinalizedHeadsThreshold = '90m' - -FinalityTagEnabled = true - -[GasEstimator] -EIP1559DynamicFees = true -Mode = 'FeeHistory' - -[GasEstimator.FeeHistory] -# block_time was: 2s, per recommendation skip 1-2 blocks -CacheTimeout = '4s' - -[GasEstimator.BlockHistory] -BlockHistorySize = 100 - -[GasEstimator.DAOracle] -OracleType = 'opstack' -OracleAddress = '0x420000000000000000000000000000000000000F' diff --git a/core/chains/evm/config/toml/defaults/Worldchain_Testnet.toml b/core/chains/evm/config/toml/defaults/Worldchain_Testnet.toml deleted file mode 100644 index 293584bb6ca..00000000000 --- a/core/chains/evm/config/toml/defaults/Worldchain_Testnet.toml +++ /dev/null @@ -1,27 +0,0 @@ -ChainID = '4801' -# OP stack: https://worldcoin.notion.site/World-Chain-Developer-Preview-Guide-23c94a67683f4e71986e5303ab88c9f3 -ChainType = 'optimismBedrock' -# finality_depth was: ~2400 -FinalityDepth = 2500 -# block_time was: 2s, adding 1 second buffer -LogPollInterval = '3s' - -# finality_depth * block_time / 60 secs = ~83 min (finality time) -NoNewFinalizedHeadsThreshold = '90m' - -FinalityTagEnabled = true - -[GasEstimator] -EIP1559DynamicFees = true -Mode = 'FeeHistory' - -[GasEstimator.FeeHistory] -# block_time was: 2s, per recommendation skip 1-2 blocks -CacheTimeout = '4s' - -[GasEstimator.BlockHistory] -BlockHistorySize = 100 - -[GasEstimator.DAOracle] -OracleType = 'opstack' -OracleAddress = '0x420000000000000000000000000000000000000F' diff --git a/core/chains/evm/config/toml/defaults/fallback.toml b/core/chains/evm/config/toml/defaults/fallback.toml index d2a6f0e4a2d..ab349ee4688 100644 --- a/core/chains/evm/config/toml/defaults/fallback.toml +++ b/core/chains/evm/config/toml/defaults/fallback.toml @@ -19,7 +19,6 @@ NoNewFinalizedHeadsThreshold = '0' LogBroadcasterEnabled = true [Transactions] -Enabled = true ForwardersEnabled = false MaxInFlight = 16 MaxQueued = 250 diff --git a/core/chains/evm/config/toml/defaults/zkSync_Mainnet.toml b/core/chains/evm/config/toml/defaults/zkSync_Mainnet.toml index c4e0cef4c61..85282ea81b3 100644 --- a/core/chains/evm/config/toml/defaults/zkSync_Mainnet.toml +++ b/core/chains/evm/config/toml/defaults/zkSync_Mainnet.toml @@ -16,6 +16,3 @@ OracleType = 'zksync' [HeadTracker] HistoryDepth = 50 - -[OCR2.Automation] -GasLimit = 6_000_000 diff --git a/core/chains/evm/config/toml/defaults/zkSync_Sepolia.toml b/core/chains/evm/config/toml/defaults/zkSync_Sepolia.toml index ed7c37b8ca1..78ed3c0768d 100644 --- a/core/chains/evm/config/toml/defaults/zkSync_Sepolia.toml +++ b/core/chains/evm/config/toml/defaults/zkSync_Sepolia.toml @@ -16,6 +16,3 @@ OracleType = 'zksync' [HeadTracker] HistoryDepth = 50 - -[OCR2.Automation] -GasLimit = 6_000_000 diff --git a/core/chains/evm/gas/models.go b/core/chains/evm/gas/models.go index 2d6fe971d9c..6cb89818c8f 100644 --- a/core/chains/evm/gas/models.go +++ b/core/chains/evm/gas/models.go @@ -9,7 +9,6 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/rpc" pkgerrors "github.com/pkg/errors" - "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink-common/pkg/services" bigmath "github.com/smartcontractkit/chainlink-common/pkg/utils/big_math" diff --git a/core/chains/evm/gas/rollups/l1_oracle.go b/core/chains/evm/gas/rollups/l1_oracle.go index d9f12dfa79e..ceecb80c608 100644 --- a/core/chains/evm/gas/rollups/l1_oracle.go +++ b/core/chains/evm/gas/rollups/l1_oracle.go @@ -10,7 +10,6 @@ import ( "github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum/rpc" - "github.com/smartcontractkit/chainlink-common/pkg/services" "github.com/smartcontractkit/chainlink-common/pkg/logger" diff --git a/core/chains/evm/label/label.go b/core/chains/evm/label/label.go index b6e80acfadf..4cca89f93fb 100644 --- a/core/chains/evm/label/label.go +++ b/core/chains/evm/label/label.go @@ -1,5 +1,6 @@ package label +// nolint const ( MaxInFlightTransactionsWarning = `WARNING: If this happens a lot, you may need to increase EVM.Transactions.MaxInFlight to boost your node's transaction throughput, however you do this at your own risk. You MUST first ensure your ethereum node is configured not to ever evict local transactions that exceed this number otherwise the node can get permanently stuck. See the performance guide for more details: https://docs.chain.link/docs/evm-performance-configuration/` MaxQueuedTransactionsWarning = `WARNING: Hitting EVM.Transactions.MaxQueued is a sanity limit and should never happen under normal operation. Unless you are operating with very high throughput, this error is unlikely to be a problem with your Chainlink node configuration, and instead more likely to be caused by a problem with your eth node's connectivity. Check your eth node: it may not be broadcasting transactions to the network, or it might be overloaded and evicting Chainlink's transactions from its mempool. It is recommended to run Chainlink with multiple primary and sendonly nodes for redundancy and to ensure fast and reliable transaction propagation. Increasing EVM.Transactions.MaxQueued will allow Chainlink to buffer more unsent transactions, but you should only do this if you need very high burst transmission rates. If you don't need very high burst throughput, increasing this limit is not the correct action to take here and will probably make things worse. See the performance guide for more details: https://docs.chain.link/docs/evm-performance-configuration/` diff --git a/core/chains/evm/logpoller/helper_test.go b/core/chains/evm/logpoller/helper_test.go index b8d849d7d83..947a839521c 100644 --- a/core/chains/evm/logpoller/helper_test.go +++ b/core/chains/evm/logpoller/helper_test.go @@ -118,19 +118,11 @@ func SetupTH(t testing.TB, opts logpoller.Opts) TestHarness { opts.PollPeriod = 1 * time.Hour } lp := logpoller.NewLogPoller(o, esc, lggr, headTracker, opts) - - pendingNonce, err := backend.Client().PendingNonceAt(testutils.Context(t), owner.From) - require.NoError(t, err) - - owner.Nonce = big.NewInt(0).SetUint64(pendingNonce) emitterAddress1, _, emitter1, err := log_emitter.DeployLogEmitter(owner, backend.Client()) require.NoError(t, err) - - owner.Nonce.Add(owner.Nonce, big.NewInt(1)) // Avoid race where DeployLogEmitter returns before PendingNonce has been incremented emitterAddress2, _, emitter2, err := log_emitter.DeployLogEmitter(owner, backend.Client()) require.NoError(t, err) backend.Commit() - owner.Nonce = nil // Just use pending nonce after this return TestHarness{ Lggr: lggr, diff --git a/core/chains/evm/logpoller/log_poller.go b/core/chains/evm/logpoller/log_poller.go index 725fdbda63c..3848c44da82 100644 --- a/core/chains/evm/logpoller/log_poller.go +++ b/core/chains/evm/logpoller/log_poller.go @@ -8,7 +8,7 @@ import ( "errors" "fmt" "math/big" - "math/rand/v2" + "math/rand" "sort" "strings" "sync" @@ -23,8 +23,6 @@ import ( pkgerrors "github.com/pkg/errors" "golang.org/x/exp/maps" - commontypes "github.com/smartcontractkit/chainlink-common/pkg/types" - "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink-common/pkg/services" "github.com/smartcontractkit/chainlink-common/pkg/timeutil" @@ -93,7 +91,6 @@ type Client interface { } type HeadTracker interface { - services.Service LatestAndFinalizedBlock(ctx context.Context) (latest, finalized *evmtypes.Head, err error) } @@ -102,6 +99,7 @@ var ( ErrReplayRequestAborted = pkgerrors.New("aborted, replay request cancelled") ErrReplayInProgress = pkgerrors.New("replay request cancelled, but replay is already in progress") ErrLogPollerShutdown = pkgerrors.New("replay aborted due to log poller shutdown") + ErrFinalityViolated = pkgerrors.New("finality violated") ) type logPoller struct { @@ -527,7 +525,7 @@ func (lp *logPoller) Close() error { func (lp *logPoller) Healthy() error { if lp.finalityViolated.Load() { - return commontypes.ErrFinalityViolated + return ErrFinalityViolated } return nil } @@ -689,7 +687,7 @@ func (lp *logPoller) backgroundWorkerRun() { // Start initial prune of unmatched logs after 5-15 successful expired log prunes, so that not all chains start // around the same time. After that, every 20 successful expired log prunes. - successfulExpiredLogPrunes := 5 + rand.IntN(10) //nolint:gosec // G404 + successfulExpiredLogPrunes := 5 + rand.Intn(10) //nolint:gosec for { select { diff --git a/core/chains/evm/logpoller/log_poller_test.go b/core/chains/evm/logpoller/log_poller_test.go index df688cd5e5c..7114960efdd 100644 --- a/core/chains/evm/logpoller/log_poller_test.go +++ b/core/chains/evm/logpoller/log_poller_test.go @@ -22,13 +22,10 @@ import ( "github.com/stretchr/testify/require" "go.uber.org/zap/zapcore" - commontypes "github.com/smartcontractkit/chainlink-common/pkg/types" - "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink-common/pkg/types/query" "github.com/smartcontractkit/chainlink-common/pkg/types/query/primitives" commonutils "github.com/smartcontractkit/chainlink-common/pkg/utils" - "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/chaintype" htMocks "github.com/smartcontractkit/chainlink/v2/common/headtracker/mocks" @@ -1109,8 +1106,7 @@ func TestLogPoller_ReorgDeeperThanFinality(t *testing.T) { secondPoll := th.PollAndSaveLogs(testutils.Context(t), firstPoll) assert.Equal(t, firstPoll, secondPoll) - require.Equal(t, commontypes.ErrFinalityViolated, th.LogPoller.Healthy()) - require.Equal(t, commontypes.ErrFinalityViolated, th.LogPoller.HealthReport()[th.LogPoller.Name()]) + assert.Equal(t, logpoller.ErrFinalityViolated, th.LogPoller.Healthy()) // Manually remove re-org'd chain from the log poller to bring it back to life // LogPoller should be healthy again after first poll @@ -1120,8 +1116,7 @@ func TestLogPoller_ReorgDeeperThanFinality(t *testing.T) { // Poll from latest recoveryPoll := th.PollAndSaveLogs(testutils.Context(t), 1) assert.Equal(t, int64(35), recoveryPoll) - require.NoError(t, th.LogPoller.Healthy()) - require.NoError(t, th.LogPoller.HealthReport()[th.LogPoller.Name()]) + assert.NoError(t, th.LogPoller.Healthy()) }) } } diff --git a/core/chains/evm/txmgr/builder.go b/core/chains/evm/txmgr/builder.go index 73c5614aba3..cbfb8775cfb 100644 --- a/core/chains/evm/txmgr/builder.go +++ b/core/chains/evm/txmgr/builder.go @@ -5,8 +5,6 @@ import ( "math/big" "time" - "github.com/ethereum/go-ethereum/common" - "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" "github.com/smartcontractkit/chainlink/v2/common/txmgr" @@ -61,8 +59,8 @@ func NewTxm( evmBroadcaster := NewEvmBroadcaster(txStore, txmClient, txmCfg, feeCfg, txConfig, listenerConfig, keyStore, txAttemptBuilder, lggr, checker, chainConfig.NonceAutoSync(), chainConfig.ChainType()) evmTracker := NewEvmTracker(txStore, keyStore, chainID, lggr) stuckTxDetector := NewStuckTxDetector(lggr, client.ConfiguredChainID(), chainConfig.ChainType(), fCfg.PriceMax(), txConfig.AutoPurge(), estimator, txStore, client) - evmConfirmer := NewEvmConfirmer(txStore, txmClient, feeCfg, txConfig, dbConfig, keyStore, txAttemptBuilder, lggr, stuckTxDetector, headTracker) - evmFinalizer := NewEvmFinalizer(lggr, client.ConfiguredChainID(), chainConfig.RPCDefaultBatchSize(), txConfig.ForwardersEnabled(), txStore, txmClient, headTracker) + evmConfirmer := NewEvmConfirmer(txStore, txmClient, txmCfg, feeCfg, txConfig, dbConfig, keyStore, txAttemptBuilder, lggr, stuckTxDetector, headTracker) + evmFinalizer := NewEvmFinalizer(lggr, client.ConfiguredChainID(), chainConfig.RPCDefaultBatchSize(), txStore, client, headTracker) var evmResender *Resender if txConfig.ResendAfterThreshold() > 0 { evmResender = NewEvmResender(lggr, txStore, txmClient, evmTracker, keyStore, txmgr.DefaultResenderPollInterval, chainConfig, txConfig) @@ -114,6 +112,7 @@ func NewEvmReaper(lggr logger.Logger, store txmgrtypes.TxHistoryReaper[*big.Int] func NewEvmConfirmer( txStore TxStore, client TxmClient, + chainConfig txmgrtypes.ConfirmerChainConfig, feeConfig txmgrtypes.ConfirmerFeeConfig, txConfig txmgrtypes.ConfirmerTransactionsConfig, dbConfig txmgrtypes.ConfirmerDatabaseConfig, @@ -123,7 +122,7 @@ func NewEvmConfirmer( stuckTxDetector StuckTxDetector, headTracker latestAndFinalizedBlockHeadTracker, ) *Confirmer { - return txmgr.NewConfirmer(txStore, client, feeConfig, txConfig, dbConfig, keystore, txAttemptBuilder, lggr, func(r *evmtypes.Receipt) bool { return r == nil }, stuckTxDetector) + return txmgr.NewConfirmer(txStore, client, chainConfig, feeConfig, txConfig, dbConfig, keystore, txAttemptBuilder, lggr, func(r *evmtypes.Receipt) bool { return r == nil }, stuckTxDetector, headTracker) } // NewEvmTracker instantiates a new EVM tracker for abandoned transactions @@ -133,7 +132,7 @@ func NewEvmTracker( chainID *big.Int, lggr logger.Logger, ) *Tracker { - return txmgr.NewTracker[*big.Int, common.Address, common.Hash, common.Hash, *evmtypes.Receipt](txStore, keyStore, chainID, lggr) + return txmgr.NewTracker(txStore, keyStore, chainID, lggr) } // NewEvmBroadcaster returns a new concrete EvmBroadcaster diff --git a/core/chains/evm/txmgr/client.go b/core/chains/evm/txmgr/client.go index 9ec175048d3..dfaa4e6bfd8 100644 --- a/core/chains/evm/txmgr/client.go +++ b/core/chains/evm/txmgr/client.go @@ -121,7 +121,7 @@ func (c *evmTxmClient) SequenceAt(ctx context.Context, addr common.Address, bloc if nonce > math.MaxInt64 { return 0, fmt.Errorf("overflow for nonce: %d", nonce) } - + //nolint:gosec // disable G115 return evmtypes.Nonce(nonce), err } @@ -139,7 +139,7 @@ func (c *evmTxmClient) BatchGetReceipts(ctx context.Context, attempts []TxAttemp } if err := c.client.BatchCallContext(ctx, reqs); err != nil { - return nil, nil, fmt.Errorf("error fetching receipts with BatchCallContext: %w", err) + return nil, nil, fmt.Errorf("EthConfirmer#batchFetchReceipts error fetching receipts with BatchCallContext: %w", err) } for _, req := range reqs { @@ -192,7 +192,3 @@ func (c *evmTxmClient) CallContract(ctx context.Context, a TxAttempt, blockNumbe func (c *evmTxmClient) HeadByHash(ctx context.Context, hash common.Hash) (*evmtypes.Head, error) { return c.client.HeadByHash(ctx, hash) } - -func (c *evmTxmClient) BatchCallContext(ctx context.Context, b []rpc.BatchElem) error { - return c.client.BatchCallContext(ctx, b) -} diff --git a/core/chains/evm/txmgr/config.go b/core/chains/evm/txmgr/config.go index d79a4e0d8af..af20c9a5901 100644 --- a/core/chains/evm/txmgr/config.go +++ b/core/chains/evm/txmgr/config.go @@ -46,6 +46,7 @@ type ( EvmTxmConfig txmgrtypes.TransactionManagerChainConfig EvmTxmFeeConfig txmgrtypes.TransactionManagerFeeConfig EvmBroadcasterConfig txmgrtypes.BroadcasterChainConfig + EvmConfirmerConfig txmgrtypes.ConfirmerChainConfig EvmResenderConfig txmgrtypes.ResenderChainConfig ) diff --git a/core/chains/evm/txmgr/confirmer_test.go b/core/chains/evm/txmgr/confirmer_test.go index ea251971860..d468d1b4c10 100644 --- a/core/chains/evm/txmgr/confirmer_test.go +++ b/core/chains/evm/txmgr/confirmer_test.go @@ -2,6 +2,7 @@ package txmgr_test import ( "context" + "encoding/json" "errors" "fmt" "math/big" @@ -13,7 +14,9 @@ import ( pkgerrors "github.com/pkg/errors" gethCommon "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/rpc" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/mock" "github.com/stretchr/testify/require" @@ -60,6 +63,12 @@ func newBroadcastLegacyEthTxAttempt(t *testing.T, etxID int64, gasPrice ...int64 return attempt } +func mustTxBeInState(t *testing.T, txStore txmgr.TestEvmTxStore, tx txmgr.Tx, expectedState txmgrtypes.TxState) { + etx, err := txStore.FindTxWithAttempts(tests.Context(t), tx.ID) + require.NoError(t, err) + require.Equal(t, expectedState, etx.State) +} + func newTxReceipt(hash gethCommon.Hash, blockNumber int, txIndex uint) evmtypes.Receipt { return evmtypes.Receipt{ TxHash: hash, @@ -124,7 +133,7 @@ func TestEthConfirmer_Lifecycle(t *testing.T) { txBuilder := txmgr.NewEvmTxAttemptBuilder(*ethClient.ConfiguredChainID(), ge, ethKeyStore, feeEstimator) stuckTxDetector := txmgr.NewStuckTxDetector(lggr, testutils.FixtureChainID, "", assets.NewWei(assets.NewEth(100).ToInt()), config.EVM().Transactions().AutoPurge(), feeEstimator, txStore, ethClient) ht := headtracker.NewSimulatedHeadTracker(ethClient, true, 0) - ec := txmgr.NewEvmConfirmer(txStore, txmgr.NewEvmTxmClient(ethClient, nil), txmgr.NewEvmTxmFeeConfig(ge), config.EVM().Transactions(), gconfig.Database(), ethKeyStore, txBuilder, lggr, stuckTxDetector, ht) + ec := txmgr.NewEvmConfirmer(txStore, txmgr.NewEvmTxmClient(ethClient, nil), txmgr.NewEvmTxmConfig(config.EVM()), txmgr.NewEvmTxmFeeConfig(ge), config.EVM().Transactions(), gconfig.Database(), ethKeyStore, txBuilder, lggr, stuckTxDetector, ht) ctx := tests.Context(t) // Can't close unstarted instance @@ -157,7 +166,8 @@ func TestEthConfirmer_Lifecycle(t *testing.T) { } head.Parent.Store(h9) - ethClient.On("NonceAt", mock.Anything, mock.Anything, mock.Anything).Return(uint64(0), nil) + ethClient.On("HeadByNumber", mock.Anything, (*big.Int)(nil)).Return(head, nil).Once() + ethClient.On("LatestFinalizedBlock", mock.Anything).Return(latestFinalizedHead, nil).Once() err = ec.ProcessHead(ctx, head) require.NoError(t, err) @@ -183,235 +193,1157 @@ func TestEthConfirmer_Lifecycle(t *testing.T) { require.NoError(t, ec.XXXTestCloseInternal()) } -func TestEthConfirmer_CheckForConfirmation(t *testing.T) { +func TestEthConfirmer_CheckForReceipts(t *testing.T) { t.Parallel() db := pgtest.NewSqlxDB(t) - cfg := configtest.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) { - c.EVM[0].GasEstimator.PriceMax = assets.GWei(500) - }) + gconfig, config := newTestChainScopedConfig(t) txStore := cltest.NewTestTxStore(t, db) + ethClient := testutils.NewEthClientMockWithDefaultChain(t) - evmcfg := evmtest.NewChainScopedConfig(t, cfg) + ethKeyStore := cltest.NewKeyStore(t, db).Eth() + + _, fromAddress := cltest.MustInsertRandomKey(t, ethKeyStore) + + ec := newEthConfirmer(t, txStore, ethClient, gconfig, config, ethKeyStore, nil) + nonce := int64(0) ctx := tests.Context(t) - blockNum := int64(100) - head := evmtypes.Head{ - Hash: testutils.NewHash(), - Number: blockNum, - } - head.IsFinalized.Store(true) + blockNum := int64(0) + latestFinalizedBlockNum := int64(0) - t.Run("does nothing if no re-org'd or included transactions found", func(t *testing.T) { - ethKeyStore := cltest.NewKeyStore(t, db).Eth() - _, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore) - etx1 := mustInsertConfirmedEthTxWithReceipt(t, txStore, fromAddress, 0, blockNum) - etx2 := mustInsertUnconfirmedTxWithBroadcastAttempts(t, txStore, 4, fromAddress, 1, blockNum, assets.NewWeiI(1)) - ec := newEthConfirmer(t, txStore, ethClient, cfg, evmcfg, ethKeyStore, nil) + t.Run("only finds eth_txes in unconfirmed state with at least one broadcast attempt", func(t *testing.T) { + mustInsertFatalErrorEthTx(t, txStore, fromAddress) + mustInsertInProgressEthTx(t, txStore, nonce, fromAddress) + nonce++ + cltest.MustInsertConfirmedEthTxWithLegacyAttempt(t, txStore, nonce, 1, fromAddress) + nonce++ + mustInsertUnconfirmedEthTxWithInsufficientEthAttempt(t, txStore, nonce, fromAddress) + nonce++ + mustCreateUnstartedGeneratedTx(t, txStore, fromAddress, config.EVM().ChainID()) + + // Do the thing + require.NoError(t, ec.CheckForReceipts(ctx, blockNum, latestFinalizedBlockNum)) + }) + + etx1 := cltest.MustInsertUnconfirmedEthTxWithBroadcastLegacyAttempt(t, txStore, nonce, fromAddress) + nonce++ + require.Len(t, etx1.TxAttempts, 1) + attempt1_1 := etx1.TxAttempts[0] + hashAttempt1_1 := attempt1_1.Hash + require.Len(t, attempt1_1.Receipts, 0) + + t.Run("fetches receipt for one unconfirmed eth_tx", func(t *testing.T) { + ethClient.On("NonceAt", mock.Anything, mock.Anything, mock.Anything).Return(uint64(10), nil) + // Transaction not confirmed yet, receipt is nil + ethClient.On("BatchCallContext", mock.Anything, mock.MatchedBy(func(b []rpc.BatchElem) bool { + return len(b) == 1 && cltest.BatchElemMatchesParams(b[0], hashAttempt1_1, "eth_getTransactionReceipt") + })).Return(nil).Run(func(args mock.Arguments) { + elems := args.Get(1).([]rpc.BatchElem) + elems[0].Result = &evmtypes.Receipt{} + }).Once() - ethClient.On("NonceAt", mock.Anything, fromAddress, mock.Anything).Return(uint64(1), nil).Maybe() - require.NoError(t, ec.CheckForConfirmation(ctx, &head)) + // Do the thing + require.NoError(t, ec.CheckForReceipts(ctx, blockNum, latestFinalizedBlockNum)) var err error etx1, err = txStore.FindTxWithAttempts(ctx, etx1.ID) + assert.NoError(t, err) + require.Len(t, etx1.TxAttempts, 1) + attempt1_1 = etx1.TxAttempts[0] require.NoError(t, err) - require.Equal(t, txmgrcommon.TxConfirmed, etx1.State) + require.Len(t, attempt1_1.Receipts, 0) + }) - etx2, err = txStore.FindTxWithAttempts(ctx, etx2.ID) + t.Run("saves nothing if returned receipt does not match the attempt", func(t *testing.T) { + txmReceipt := evmtypes.Receipt{ + TxHash: testutils.NewHash(), + BlockHash: testutils.NewHash(), + BlockNumber: big.NewInt(42), + TransactionIndex: uint(1), + } + + ethClient.On("NonceAt", mock.Anything, mock.Anything, mock.Anything).Return(uint64(10), nil) + // First transaction confirmed + ethClient.On("BatchCallContext", mock.Anything, mock.MatchedBy(func(b []rpc.BatchElem) bool { + return len(b) == 1 && cltest.BatchElemMatchesParams(b[0], hashAttempt1_1, "eth_getTransactionReceipt") + })).Return(nil).Run(func(args mock.Arguments) { + elems := args.Get(1).([]rpc.BatchElem) + *(elems[0].Result.(*evmtypes.Receipt)) = txmReceipt + }).Once() + + // No error because it is merely logged + require.NoError(t, ec.CheckForReceipts(ctx, blockNum, latestFinalizedBlockNum)) + + etx, err := txStore.FindTxWithAttempts(ctx, etx1.ID) require.NoError(t, err) - require.Equal(t, txmgrcommon.TxUnconfirmed, etx2.State) + require.Len(t, etx.TxAttempts, 1) + + require.Len(t, etx.TxAttempts[0].Receipts, 0) }) - t.Run("marks re-org'd confirmed transaction as unconfirmed, marks latest attempt as in-progress, deletes receipt", func(t *testing.T) { - ethKeyStore := cltest.NewKeyStore(t, db).Eth() - _, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore) - // Insert confirmed transaction that stays confirmed - etx := mustInsertConfirmedEthTxWithReceipt(t, txStore, fromAddress, 0, blockNum) - ec := newEthConfirmer(t, txStore, ethClient, cfg, evmcfg, ethKeyStore, nil) + t.Run("saves nothing if query returns error", func(t *testing.T) { + txmReceipt := evmtypes.Receipt{ + TxHash: attempt1_1.Hash, + BlockHash: testutils.NewHash(), + BlockNumber: big.NewInt(42), + TransactionIndex: uint(1), + } - ethClient.On("NonceAt", mock.Anything, fromAddress, mock.Anything).Return(uint64(0), nil).Maybe() - require.NoError(t, ec.CheckForConfirmation(ctx, &head)) + ethClient.On("NonceAt", mock.Anything, mock.Anything, mock.Anything).Return(uint64(10), nil) + // First transaction confirmed + ethClient.On("BatchCallContext", mock.Anything, mock.MatchedBy(func(b []rpc.BatchElem) bool { + return len(b) == 1 && cltest.BatchElemMatchesParams(b[0], hashAttempt1_1, "eth_getTransactionReceipt") + })).Return(nil).Run(func(args mock.Arguments) { + elems := args.Get(1).([]rpc.BatchElem) + *(elems[0].Result.(*evmtypes.Receipt)) = txmReceipt + elems[0].Error = errors.New("foo") + }).Once() - var err error - etx, err = txStore.FindTxWithAttempts(ctx, etx.ID) + // No error because it is merely logged + require.NoError(t, ec.CheckForReceipts(ctx, blockNum, latestFinalizedBlockNum)) + + etx, err := txStore.FindTxWithAttempts(ctx, etx1.ID) require.NoError(t, err) - require.Equal(t, txmgrcommon.TxUnconfirmed, etx.State) - attempt := etx.TxAttempts[0] - require.Equal(t, txmgrtypes.TxAttemptInProgress, attempt.State) - require.Empty(t, attempt.Receipts) + require.Len(t, etx.TxAttempts, 1) + require.Len(t, etx.TxAttempts[0].Receipts, 0) }) - t.Run("marks re-org'd terminally stuck transaction as unconfirmed, marks latest attempt as in-progress, deletes receipt, removed error", func(t *testing.T) { - ethKeyStore := cltest.NewKeyStore(t, db).Eth() - _, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore) - // Insert terminally stuck transaction that stays fatal error - etx := mustInsertTerminallyStuckTxWithAttempt(t, txStore, fromAddress, 0, blockNum) - mustInsertEthReceipt(t, txStore, blockNum, utils.NewHash(), etx.TxAttempts[0].Hash) - ec := newEthConfirmer(t, txStore, ethClient, cfg, evmcfg, ethKeyStore, nil) + etx2 := cltest.MustInsertUnconfirmedEthTxWithBroadcastLegacyAttempt(t, txStore, nonce, fromAddress) + nonce++ + require.Len(t, etx2.TxAttempts, 1) + attempt2_1 := etx2.TxAttempts[0] + require.Len(t, attempt2_1.Receipts, 0) + + t.Run("saves eth_receipt and marks eth_tx as confirmed when geth client returns valid receipt", func(t *testing.T) { + txmReceipt := evmtypes.Receipt{ + TxHash: attempt1_1.Hash, + BlockHash: testutils.NewHash(), + BlockNumber: big.NewInt(42), + TransactionIndex: uint(1), + Status: uint64(1), + } - ethClient.On("NonceAt", mock.Anything, fromAddress, mock.Anything).Return(uint64(0), nil).Maybe() - require.NoError(t, ec.CheckForConfirmation(ctx, &head)) + ethClient.On("NonceAt", mock.Anything, mock.Anything, mock.Anything).Return(uint64(10), nil) + ethClient.On("BatchCallContext", mock.Anything, mock.MatchedBy(func(b []rpc.BatchElem) bool { + return len(b) == 2 && + cltest.BatchElemMatchesParams(b[0], attempt1_1.Hash, "eth_getTransactionReceipt") && + cltest.BatchElemMatchesParams(b[1], attempt2_1.Hash, "eth_getTransactionReceipt") + })).Return(nil).Run(func(args mock.Arguments) { + elems := args.Get(1).([]rpc.BatchElem) + // First transaction confirmed + *(elems[0].Result.(*evmtypes.Receipt)) = txmReceipt + // Second transaction still unconfirmed + elems[1].Result = &evmtypes.Receipt{} + }).Once() - var err error - etx, err = txStore.FindTxWithAttempts(ctx, etx.ID) + // Do the thing + require.NoError(t, ec.CheckForReceipts(ctx, blockNum, latestFinalizedBlockNum)) + + // Check that the receipt was saved + etx, err := txStore.FindTxWithAttempts(ctx, etx1.ID) require.NoError(t, err) - require.Equal(t, txmgrcommon.TxUnconfirmed, etx.State) - require.Equal(t, "", etx.Error.String) - attempt := etx.TxAttempts[0] - require.Equal(t, txmgrtypes.TxAttemptInProgress, attempt.State) - require.Empty(t, attempt.Receipts) - }) - t.Run("handles multiple re-org transactions at a time", func(t *testing.T) { - ethKeyStore := cltest.NewKeyStore(t, db).Eth() - _, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore) - // Insert confirmed transaction that stays confirmed - etx1 := mustInsertConfirmedEthTxWithReceipt(t, txStore, fromAddress, 0, blockNum) - // Insert terminally stuck transaction that stays fatal error - etx2 := mustInsertTerminallyStuckTxWithAttempt(t, txStore, fromAddress, 1, blockNum) - mustInsertEthReceipt(t, txStore, blockNum, utils.NewHash(), etx2.TxAttempts[0].Hash) - // Insert confirmed transaction that gets re-org'd - etx3 := mustInsertConfirmedEthTxWithReceipt(t, txStore, fromAddress, 2, blockNum) - // Insert terminally stuck transaction that gets re-org'd - etx4 := mustInsertTerminallyStuckTxWithAttempt(t, txStore, fromAddress, 3, blockNum) - mustInsertEthReceipt(t, txStore, blockNum, utils.NewHash(), etx4.TxAttempts[0].Hash) - // Insert unconfirmed transaction that is untouched - etx5 := mustInsertUnconfirmedTxWithBroadcastAttempts(t, txStore, 4, fromAddress, 1, blockNum, assets.NewWeiI(1)) - ec := newEthConfirmer(t, txStore, ethClient, cfg, evmcfg, ethKeyStore, nil) + assert.Equal(t, txmgrcommon.TxConfirmed, etx.State) + assert.Len(t, etx.TxAttempts, 1) + attempt1_1 = etx.TxAttempts[0] + require.Len(t, attempt1_1.Receipts, 1) - ethClient.On("NonceAt", mock.Anything, fromAddress, mock.Anything).Return(uint64(2), nil).Maybe() - require.NoError(t, ec.CheckForConfirmation(ctx, &head)) + ethReceipt := attempt1_1.Receipts[0] - var err error - etx1, err = txStore.FindTxWithAttempts(ctx, etx1.ID) + assert.Equal(t, txmReceipt.TxHash, ethReceipt.GetTxHash()) + assert.Equal(t, txmReceipt.BlockHash, ethReceipt.GetBlockHash()) + assert.Equal(t, txmReceipt.BlockNumber.Int64(), ethReceipt.GetBlockNumber().Int64()) + assert.Equal(t, txmReceipt.TransactionIndex, ethReceipt.GetTransactionIndex()) + + receiptJSON, err := json.Marshal(txmReceipt) require.NoError(t, err) - require.Equal(t, txmgrcommon.TxConfirmed, etx1.State) - attempt1 := etx1.TxAttempts[0] - require.Equal(t, txmgrtypes.TxAttemptBroadcast, attempt1.State) - require.Len(t, attempt1.Receipts, 1) - etx2, err = txStore.FindTxWithAttempts(ctx, etx2.ID) + j, err := json.Marshal(ethReceipt) require.NoError(t, err) - require.Equal(t, txmgrcommon.TxFatalError, etx2.State) - require.Equal(t, client.TerminallyStuckMsg, etx2.Error.String) - attempt2 := etx2.TxAttempts[0] - require.Equal(t, txmgrtypes.TxAttemptBroadcast, attempt2.State) - require.Len(t, attempt2.Receipts, 1) + assert.JSONEq(t, string(receiptJSON), string(j)) + }) - etx3, err = txStore.FindTxWithAttempts(ctx, etx3.ID) + t.Run("fetches and saves receipts for several attempts in gas price order", func(t *testing.T) { + attempt2_2 := newBroadcastLegacyEthTxAttempt(t, etx2.ID) + attempt2_2.TxFee = gas.EvmFee{GasPrice: assets.NewWeiI(10)} + + attempt2_3 := newBroadcastLegacyEthTxAttempt(t, etx2.ID) + attempt2_3.TxFee = gas.EvmFee{GasPrice: assets.NewWeiI(20)} + + // Insert order deliberately reversed to test sorting by gas price + require.NoError(t, txStore.InsertTxAttempt(ctx, &attempt2_3)) + require.NoError(t, txStore.InsertTxAttempt(ctx, &attempt2_2)) + + txmReceipt := evmtypes.Receipt{ + TxHash: attempt2_2.Hash, + BlockHash: testutils.NewHash(), + BlockNumber: big.NewInt(42), + TransactionIndex: uint(1), + Status: uint64(1), + } + + ethClient.On("NonceAt", mock.Anything, mock.Anything, mock.Anything).Return(uint64(10), nil) + ethClient.On("BatchCallContext", mock.Anything, mock.MatchedBy(func(b []rpc.BatchElem) bool { + return len(b) == 3 && + cltest.BatchElemMatchesParams(b[2], attempt2_1.Hash, "eth_getTransactionReceipt") && + cltest.BatchElemMatchesParams(b[1], attempt2_2.Hash, "eth_getTransactionReceipt") && + cltest.BatchElemMatchesParams(b[0], attempt2_3.Hash, "eth_getTransactionReceipt") + })).Return(nil).Run(func(args mock.Arguments) { + elems := args.Get(1).([]rpc.BatchElem) + // Most expensive attempt still unconfirmed + elems[2].Result = &evmtypes.Receipt{} + // Second most expensive attempt is confirmed + *(elems[1].Result.(*evmtypes.Receipt)) = txmReceipt + // Cheapest attempt still unconfirmed + elems[0].Result = &evmtypes.Receipt{} + }).Once() + + // Do the thing + require.NoError(t, ec.CheckForReceipts(ctx, blockNum, latestFinalizedBlockNum)) + + // Check that the state was updated + etx, err := txStore.FindTxWithAttempts(ctx, etx2.ID) require.NoError(t, err) - require.Equal(t, txmgrcommon.TxUnconfirmed, etx3.State) - attempt3 := etx3.TxAttempts[0] - require.Equal(t, txmgrtypes.TxAttemptInProgress, attempt3.State) - require.Empty(t, attempt3.Receipts) - etx4, err = txStore.FindTxWithAttempts(ctx, etx4.ID) + require.Equal(t, txmgrcommon.TxConfirmed, etx.State) + require.Len(t, etx.TxAttempts, 3) + }) + + etx3 := cltest.MustInsertUnconfirmedEthTxWithBroadcastLegacyAttempt(t, txStore, nonce, fromAddress) + attempt3_1 := etx3.TxAttempts[0] + nonce++ + + t.Run("ignores receipt missing BlockHash that comes from querying parity too early", func(t *testing.T) { + ethClient.On("NonceAt", mock.Anything, mock.Anything, mock.Anything).Return(uint64(10), nil) + receipt := evmtypes.Receipt{ + TxHash: attempt3_1.Hash, + Status: uint64(1), + } + ethClient.On("BatchCallContext", mock.Anything, mock.MatchedBy(func(b []rpc.BatchElem) bool { + return len(b) == 1 && cltest.BatchElemMatchesParams(b[0], attempt3_1.Hash, "eth_getTransactionReceipt") + })).Return(nil).Run(func(args mock.Arguments) { + elems := args.Get(1).([]rpc.BatchElem) + *(elems[0].Result.(*evmtypes.Receipt)) = receipt + }).Once() + + // Do the thing + require.NoError(t, ec.CheckForReceipts(ctx, blockNum, latestFinalizedBlockNum)) + + // No receipt, but no error either + etx, err := txStore.FindTxWithAttempts(ctx, etx3.ID) require.NoError(t, err) - require.Equal(t, txmgrcommon.TxUnconfirmed, etx4.State) - require.Equal(t, "", etx4.Error.String) - attempt4 := etx4.TxAttempts[0] - require.Equal(t, txmgrtypes.TxAttemptInProgress, attempt4.State) - require.True(t, attempt4.IsPurgeAttempt) - require.Empty(t, attempt4.Receipts) - etx5, err = txStore.FindTxWithAttempts(ctx, etx5.ID) + assert.Equal(t, txmgrcommon.TxUnconfirmed, etx.State) + assert.Len(t, etx.TxAttempts, 1) + attempt3_1 = etx.TxAttempts[0] + require.Len(t, attempt3_1.Receipts, 0) + }) + + t.Run("does not panic if receipt has BlockHash but is missing some other fields somehow", func(t *testing.T) { + // NOTE: This should never happen, but we shouldn't panic regardless + receipt := evmtypes.Receipt{ + TxHash: attempt3_1.Hash, + BlockHash: testutils.NewHash(), + Status: uint64(1), + } + ethClient.On("BatchCallContext", mock.Anything, mock.MatchedBy(func(b []rpc.BatchElem) bool { + return len(b) == 1 && cltest.BatchElemMatchesParams(b[0], attempt3_1.Hash, "eth_getTransactionReceipt") + })).Return(nil).Run(func(args mock.Arguments) { + elems := args.Get(1).([]rpc.BatchElem) + *(elems[0].Result.(*evmtypes.Receipt)) = receipt + }).Once() + + // Do the thing + require.NoError(t, ec.CheckForReceipts(ctx, blockNum, latestFinalizedBlockNum)) + + // No receipt, but no error either + etx, err := txStore.FindTxWithAttempts(ctx, etx3.ID) require.NoError(t, err) - require.Equal(t, txmgrcommon.TxUnconfirmed, etx5.State) - attempt5 := etx5.TxAttempts[0] - require.Equal(t, txmgrtypes.TxAttemptBroadcast, attempt5.State) + + assert.Equal(t, txmgrcommon.TxUnconfirmed, etx.State) + assert.Len(t, etx.TxAttempts, 1) + attempt3_1 = etx.TxAttempts[0] + require.Len(t, attempt3_1.Receipts, 0) }) + t.Run("handles case where eth_receipt already exists somehow", func(t *testing.T) { + ethReceipt := mustInsertEthReceipt(t, txStore, 42, testutils.NewHash(), attempt3_1.Hash) + txmReceipt := evmtypes.Receipt{ + TxHash: attempt3_1.Hash, + BlockHash: ethReceipt.BlockHash, + BlockNumber: big.NewInt(ethReceipt.BlockNumber), + TransactionIndex: ethReceipt.TransactionIndex, + Status: uint64(1), + } + ethClient.On("NonceAt", mock.Anything, mock.Anything, mock.Anything).Return(uint64(10), nil) + ethClient.On("BatchCallContext", mock.Anything, mock.MatchedBy(func(b []rpc.BatchElem) bool { + return len(b) == 1 && cltest.BatchElemMatchesParams(b[0], attempt3_1.Hash, "eth_getTransactionReceipt") + })).Return(nil).Run(func(args mock.Arguments) { + elems := args.Get(1).([]rpc.BatchElem) + *(elems[0].Result.(*evmtypes.Receipt)) = txmReceipt + }).Once() - t.Run("marks valid transaction as confirmed if nonce less than mined tx count", func(t *testing.T) { - ethKeyStore := cltest.NewKeyStore(t, db).Eth() - _, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore) - etx := mustInsertUnconfirmedTxWithBroadcastAttempts(t, txStore, 0, fromAddress, 1, blockNum, assets.NewWeiI(1)) - ec := newEthConfirmer(t, txStore, ethClient, cfg, evmcfg, ethKeyStore, nil) + // Do the thing + require.NoError(t, ec.CheckForReceipts(ctx, blockNum, latestFinalizedBlockNum)) + + // Check that the receipt was unchanged + etx, err := txStore.FindTxWithAttempts(ctx, etx3.ID) + require.NoError(t, err) + + assert.Equal(t, txmgrcommon.TxConfirmed, etx.State) + assert.Len(t, etx.TxAttempts, 1) + attempt3_1 = etx.TxAttempts[0] + require.Len(t, attempt3_1.Receipts, 1) + + ethReceipt3_1 := attempt3_1.Receipts[0] + + assert.Equal(t, txmReceipt.TxHash, ethReceipt3_1.GetTxHash()) + assert.Equal(t, txmReceipt.BlockHash, ethReceipt3_1.GetBlockHash()) + assert.Equal(t, txmReceipt.BlockNumber.Int64(), ethReceipt3_1.GetBlockNumber().Int64()) + assert.Equal(t, txmReceipt.TransactionIndex, ethReceipt3_1.GetTransactionIndex()) + }) + + etx4 := cltest.MustInsertUnconfirmedEthTxWithBroadcastLegacyAttempt(t, txStore, nonce, fromAddress) + attempt4_1 := etx4.TxAttempts[0] + nonce++ - ethClient.On("NonceAt", mock.Anything, fromAddress, mock.Anything).Return(uint64(1), nil).Maybe() - require.NoError(t, ec.CheckForConfirmation(ctx, &head)) + t.Run("on receipt fetch marks in_progress eth_tx_attempt as broadcast", func(t *testing.T) { + attempt4_2 := newInProgressLegacyEthTxAttempt(t, etx4.ID) + attempt4_2.TxFee = gas.EvmFee{GasPrice: assets.NewWeiI(10)} + require.NoError(t, txStore.InsertTxAttempt(ctx, &attempt4_2)) + + txmReceipt := evmtypes.Receipt{ + TxHash: attempt4_2.Hash, + BlockHash: testutils.NewHash(), + BlockNumber: big.NewInt(42), + TransactionIndex: uint(1), + Status: uint64(1), + } + ethClient.On("NonceAt", mock.Anything, mock.Anything, mock.Anything).Return(uint64(10), nil) + // Second attempt is confirmed + ethClient.On("BatchCallContext", mock.Anything, mock.MatchedBy(func(b []rpc.BatchElem) bool { + return len(b) == 2 && + cltest.BatchElemMatchesParams(b[0], attempt4_2.Hash, "eth_getTransactionReceipt") && + cltest.BatchElemMatchesParams(b[1], attempt4_1.Hash, "eth_getTransactionReceipt") + })).Return(nil).Run(func(args mock.Arguments) { + elems := args.Get(1).([]rpc.BatchElem) + // First attempt still unconfirmed + elems[1].Result = &evmtypes.Receipt{} + // Second attempt is confirmed + *(elems[0].Result.(*evmtypes.Receipt)) = txmReceipt + }).Once() + + // Do the thing + require.NoError(t, ec.CheckForReceipts(ctx, blockNum, latestFinalizedBlockNum)) + + // Check that the state was updated var err error - etx, err = txStore.FindTxWithAttempts(ctx, etx.ID) + etx4, err = txStore.FindTxWithAttempts(ctx, etx4.ID) require.NoError(t, err) - require.Equal(t, txmgrcommon.TxConfirmed, etx.State) + + attempt4_1 = etx4.TxAttempts[1] + attempt4_2 = etx4.TxAttempts[0] + + // And the attempts + require.Equal(t, txmgrtypes.TxAttemptBroadcast, attempt4_1.State) + require.Nil(t, attempt4_1.BroadcastBeforeBlockNum) + require.Equal(t, txmgrtypes.TxAttemptBroadcast, attempt4_2.State) + require.Equal(t, int64(42), *attempt4_2.BroadcastBeforeBlockNum) + + // Check receipts + require.Len(t, attempt4_1.Receipts, 0) + require.Len(t, attempt4_2.Receipts, 1) }) - t.Run("marks purge transaction as terminally stuck if nonce less than mined tx count", func(t *testing.T) { - ethKeyStore := cltest.NewKeyStore(t, db).Eth() - _, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore) - etx := mustInsertUnconfirmedEthTxWithBroadcastPurgeAttempt(t, txStore, 0, fromAddress) - ec := newEthConfirmer(t, txStore, ethClient, cfg, evmcfg, ethKeyStore, nil) + etx5 := cltest.MustInsertUnconfirmedEthTxWithBroadcastLegacyAttempt(t, txStore, nonce, fromAddress) + attempt5_1 := etx5.TxAttempts[0] + nonce++ - ethClient.On("NonceAt", mock.Anything, fromAddress, mock.Anything).Return(uint64(1), nil).Maybe() - require.NoError(t, ec.CheckForConfirmation(ctx, &head)) + t.Run("simulate on revert", func(t *testing.T) { + txmReceipt := evmtypes.Receipt{ + TxHash: attempt5_1.Hash, + BlockHash: testutils.NewHash(), + BlockNumber: big.NewInt(42), + TransactionIndex: uint(1), + Status: uint64(0), + } + ethClient.On("NonceAt", mock.Anything, mock.Anything, mock.Anything).Return(uint64(10), nil) + // First attempt is confirmed and reverted + ethClient.On("BatchCallContext", mock.Anything, mock.MatchedBy(func(b []rpc.BatchElem) bool { + return len(b) == 1 && + cltest.BatchElemMatchesParams(b[0], attempt5_1.Hash, "eth_getTransactionReceipt") + })).Return(nil).Run(func(args mock.Arguments) { + elems := args.Get(1).([]rpc.BatchElem) + // First attempt still unconfirmed + *(elems[0].Result.(*evmtypes.Receipt)) = txmReceipt + }).Once() + data, err := utils.ABIEncode(`[{"type":"uint256"}]`, big.NewInt(10)) + require.NoError(t, err) + sig := utils.Keccak256Fixed([]byte(`MyError(uint256)`)) + ethClient.On("CallContract", mock.Anything, mock.Anything, mock.Anything).Return(nil, &client.JsonError{ + Code: 1, + Message: "reverted", + Data: utils.ConcatBytes(sig[:4], data), + }).Once() - var err error - etx, err = txStore.FindTxWithAttempts(ctx, etx.ID) + // Do the thing + require.NoError(t, ec.CheckForReceipts(ctx, blockNum, latestFinalizedBlockNum)) + + // Check that the state was updated + etx5, err = txStore.FindTxWithAttempts(ctx, etx5.ID) require.NoError(t, err) - require.Equal(t, txmgrcommon.TxFatalError, etx.State) - require.Equal(t, client.TerminallyStuckMsg, etx.Error.String) + + attempt5_1 = etx5.TxAttempts[0] + + // And the attempts + require.Equal(t, txmgrtypes.TxAttemptBroadcast, attempt5_1.State) + require.NotNil(t, attempt5_1.BroadcastBeforeBlockNum) + // Check receipts + require.Len(t, attempt5_1.Receipts, 1) }) +} - t.Run("handles multiple confirmed transactions at a time", func(t *testing.T) { - ethKeyStore := cltest.NewKeyStore(t, db).Eth() - _, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore) - // Insert valid confirmed transaction that is untouched - etx1 := mustInsertConfirmedEthTxWithReceipt(t, txStore, fromAddress, 0, blockNum) - // Insert terminally stuck transaction that is untouched - etx2 := mustInsertTerminallyStuckTxWithAttempt(t, txStore, fromAddress, 1, blockNum) - mustInsertEthReceipt(t, txStore, blockNum, utils.NewHash(), etx2.TxAttempts[0].Hash) - // Insert valid unconfirmed transaction that is confirmed - etx3 := mustInsertUnconfirmedTxWithBroadcastAttempts(t, txStore, 2, fromAddress, 1, blockNum, assets.NewWeiI(1)) - // Insert unconfirmed purge transaction that is confirmed and marked as terminally stuck - etx4 := mustInsertUnconfirmedEthTxWithBroadcastPurgeAttempt(t, txStore, 3, fromAddress) - // Insert unconfirmed transact that is not confirmed and left untouched - etx5 := mustInsertUnconfirmedTxWithBroadcastAttempts(t, txStore, 4, fromAddress, 1, blockNum, assets.NewWeiI(1)) - ec := newEthConfirmer(t, txStore, ethClient, cfg, evmcfg, ethKeyStore, nil) +func TestEthConfirmer_CheckForReceipts_batching(t *testing.T) { + t.Parallel() + + db := pgtest.NewSqlxDB(t) + cfg := configtest.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) { + c.EVM[0].RPCDefaultBatchSize = ptr[uint32](2) + }) + txStore := cltest.NewTestTxStore(t, db) + + ethKeyStore := cltest.NewKeyStore(t, db).Eth() + + _, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore) + + ethClient := testutils.NewEthClientMockWithDefaultChain(t) + + evmcfg := evmtest.NewChainScopedConfig(t, cfg) + + ec := newEthConfirmer(t, txStore, ethClient, cfg, evmcfg, ethKeyStore, nil) + ctx := tests.Context(t) + + etx := cltest.MustInsertUnconfirmedEthTx(t, txStore, 0, fromAddress) + var attempts []txmgr.TxAttempt + latestFinalizedBlockNum := int64(0) + + // Total of 5 attempts should lead to 3 batched fetches (2, 2, 1) + for i := 0; i < 5; i++ { + attempt := newBroadcastLegacyEthTxAttempt(t, etx.ID, int64(i+2)) + require.NoError(t, txStore.InsertTxAttempt(ctx, &attempt)) + attempts = append(attempts, attempt) + } + + ethClient.On("NonceAt", mock.Anything, mock.Anything, mock.Anything).Return(uint64(10), nil) + + ethClient.On("BatchCallContext", mock.Anything, mock.MatchedBy(func(b []rpc.BatchElem) bool { + return len(b) == 2 && + cltest.BatchElemMatchesParams(b[0], attempts[4].Hash, "eth_getTransactionReceipt") && + cltest.BatchElemMatchesParams(b[1], attempts[3].Hash, "eth_getTransactionReceipt") + })).Return(nil).Run(func(args mock.Arguments) { + elems := args.Get(1).([]rpc.BatchElem) + elems[0].Result = &evmtypes.Receipt{} + elems[1].Result = &evmtypes.Receipt{} + }).Once() + ethClient.On("BatchCallContext", mock.Anything, mock.MatchedBy(func(b []rpc.BatchElem) bool { + return len(b) == 2 && + cltest.BatchElemMatchesParams(b[0], attempts[2].Hash, "eth_getTransactionReceipt") && + cltest.BatchElemMatchesParams(b[1], attempts[1].Hash, "eth_getTransactionReceipt") + })).Return(nil).Run(func(args mock.Arguments) { + elems := args.Get(1).([]rpc.BatchElem) + elems[0].Result = &evmtypes.Receipt{} + elems[1].Result = &evmtypes.Receipt{} + }).Once() + ethClient.On("BatchCallContext", mock.Anything, mock.MatchedBy(func(b []rpc.BatchElem) bool { + return len(b) == 1 && + cltest.BatchElemMatchesParams(b[0], attempts[0].Hash, "eth_getTransactionReceipt") + })).Return(nil).Run(func(args mock.Arguments) { + elems := args.Get(1).([]rpc.BatchElem) + elems[0].Result = &evmtypes.Receipt{} + }).Once() + + require.NoError(t, ec.CheckForReceipts(ctx, 42, latestFinalizedBlockNum)) +} + +func TestEthConfirmer_CheckForReceipts_HandlesNonFwdTxsWithForwardingEnabled(t *testing.T) { + t.Parallel() + + db := pgtest.NewSqlxDB(t) + + cfg := configtest.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) { + c.EVM[0].RPCDefaultBatchSize = ptr[uint32](1) + c.EVM[0].Transactions.ForwardersEnabled = ptr(true) + }) + + txStore := cltest.NewTestTxStore(t, db) + ethKeyStore := cltest.NewKeyStore(t, db).Eth() + ethClient := testutils.NewEthClientMockWithDefaultChain(t) + evmcfg := evmtest.NewChainScopedConfig(t, cfg) + + _, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore) + ec := newEthConfirmer(t, txStore, ethClient, cfg, evmcfg, ethKeyStore, nil) + ctx := tests.Context(t) + latestFinalizedBlockNum := int64(0) + + // tx is not forwarded and doesn't have meta set. EthConfirmer should handle nil meta values + etx := cltest.MustInsertUnconfirmedEthTx(t, txStore, 0, fromAddress) + attempt := newBroadcastLegacyEthTxAttempt(t, etx.ID, 2) + attempt.Tx.Meta = nil + require.NoError(t, txStore.InsertTxAttempt(ctx, &attempt)) + dbtx, err := txStore.FindTxWithAttempts(ctx, etx.ID) + require.NoError(t, err) + require.Equal(t, 0, len(dbtx.TxAttempts[0].Receipts)) + + txmReceipt := evmtypes.Receipt{ + TxHash: attempt.Hash, + BlockHash: testutils.NewHash(), + BlockNumber: big.NewInt(42), + TransactionIndex: uint(1), + Status: uint64(1), + } + + ethClient.On("NonceAt", mock.Anything, mock.Anything, mock.Anything).Return(uint64(10), nil) + ethClient.On("BatchCallContext", mock.Anything, mock.MatchedBy(func(b []rpc.BatchElem) bool { + return len(b) == 1 && + cltest.BatchElemMatchesParams(b[0], attempt.Hash, "eth_getTransactionReceipt") + })).Return(nil).Run(func(args mock.Arguments) { + elems := args.Get(1).([]rpc.BatchElem) + *(elems[0].Result.(*evmtypes.Receipt)) = txmReceipt // confirmed + }).Once() - ethClient.On("NonceAt", mock.Anything, fromAddress, mock.Anything).Return(uint64(4), nil).Maybe() - require.NoError(t, ec.CheckForConfirmation(ctx, &head)) + require.NoError(t, ec.CheckForReceipts(ctx, 42, latestFinalizedBlockNum)) + // Check receipt is inserted correctly. + dbtx, err = txStore.FindTxWithAttempts(ctx, etx.ID) + require.NoError(t, err) + require.Equal(t, 1, len(dbtx.TxAttempts[0].Receipts)) +} + +func TestEthConfirmer_CheckForReceipts_only_likely_confirmed(t *testing.T) { + t.Parallel() + + db := pgtest.NewSqlxDB(t) + cfg := configtest.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) { + c.EVM[0].RPCDefaultBatchSize = ptr[uint32](6) + }) + txStore := cltest.NewTestTxStore(t, db) + + ethKeyStore := cltest.NewKeyStore(t, db).Eth() + + _, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore) + + ethClient := testutils.NewEthClientMockWithDefaultChain(t) + + evmcfg := evmtest.NewChainScopedConfig(t, cfg) + + ec := newEthConfirmer(t, txStore, ethClient, cfg, evmcfg, ethKeyStore, nil) + ctx := tests.Context(t) + latestFinalizedBlockNum := int64(0) + + var attempts []txmgr.TxAttempt + // inserting in DESC nonce order to test DB ASC ordering + etx2 := cltest.MustInsertUnconfirmedEthTx(t, txStore, 1, fromAddress) + for i := 0; i < 4; i++ { + attempt := newBroadcastLegacyEthTxAttempt(t, etx2.ID, int64(100-i)) + require.NoError(t, txStore.InsertTxAttempt(ctx, &attempt)) + } + etx := cltest.MustInsertUnconfirmedEthTx(t, txStore, 0, fromAddress) + for i := 0; i < 4; i++ { + attempt := newBroadcastLegacyEthTxAttempt(t, etx.ID, int64(100-i)) + require.NoError(t, txStore.InsertTxAttempt(ctx, &attempt)) + + // only adding these because a batch for only those attempts should be sent + attempts = append(attempts, attempt) + } + + ethClient.On("NonceAt", mock.Anything, mock.Anything, mock.Anything).Return(uint64(0), nil) + + var captured []rpc.BatchElem + ethClient.On("BatchCallContext", mock.Anything, mock.MatchedBy(func(b []rpc.BatchElem) bool { + return len(b) == 4 + })).Return(nil).Run(func(args mock.Arguments) { + elems := args.Get(1).([]rpc.BatchElem) + captured = append(captured, elems...) + elems[0].Result = &evmtypes.Receipt{} + elems[1].Result = &evmtypes.Receipt{} + elems[2].Result = &evmtypes.Receipt{} + elems[3].Result = &evmtypes.Receipt{} + }).Once() + + require.NoError(t, ec.CheckForReceipts(ctx, 42, latestFinalizedBlockNum)) + + cltest.BatchElemMustMatchParams(t, captured[0], attempts[0].Hash, "eth_getTransactionReceipt") + cltest.BatchElemMustMatchParams(t, captured[1], attempts[1].Hash, "eth_getTransactionReceipt") + cltest.BatchElemMustMatchParams(t, captured[2], attempts[2].Hash, "eth_getTransactionReceipt") + cltest.BatchElemMustMatchParams(t, captured[3], attempts[3].Hash, "eth_getTransactionReceipt") +} + +func TestEthConfirmer_CheckForReceipts_should_not_check_for_likely_unconfirmed(t *testing.T) { + t.Parallel() + + db := pgtest.NewSqlxDB(t) + gconfig, config := newTestChainScopedConfig(t) + txStore := cltest.NewTestTxStore(t, db) + + ethKeyStore := cltest.NewKeyStore(t, db).Eth() + + _, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore) + + ethClient := testutils.NewEthClientMockWithDefaultChain(t) + + ec := newEthConfirmer(t, txStore, ethClient, gconfig, config, ethKeyStore, nil) + ctx := tests.Context(t) + latestFinalizedBlockNum := int64(0) + + etx := cltest.MustInsertUnconfirmedEthTx(t, txStore, 1, fromAddress) + for i := 0; i < 4; i++ { + attempt := newBroadcastLegacyEthTxAttempt(t, etx.ID, int64(100-i)) + require.NoError(t, txStore.InsertTxAttempt(ctx, &attempt)) + } + + // latest nonce is lower that all attempts' nonces + ethClient.On("NonceAt", mock.Anything, mock.Anything, mock.Anything).Return(uint64(0), nil) + + require.NoError(t, ec.CheckForReceipts(ctx, 42, latestFinalizedBlockNum)) +} + +func TestEthConfirmer_CheckForReceipts_confirmed_missing_receipt_scoped_to_key(t *testing.T) { + t.Parallel() + + db := pgtest.NewSqlxDB(t) + cfg := configtest.NewTestGeneralConfig(t) + txStore := cltest.NewTestTxStore(t, db) + ethKeyStore := cltest.NewKeyStore(t, db).Eth() + + _, fromAddress1_1 := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore) + _, fromAddress1_2 := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore) + _, fromAddress2_1 := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore) + + ethClient := testutils.NewEthClientMockWithDefaultChain(t) + ethClient.On("NonceAt", mock.Anything, mock.Anything, mock.Anything).Return(uint64(20), nil) + evmcfg := evmtest.NewChainScopedConfig(t, cfg) + + ec := newEthConfirmer(t, txStore, ethClient, cfg, evmcfg, ethKeyStore, nil) + ctx := tests.Context(t) + latestFinalizedBlockNum := int64(0) + + // STATE + // key 1, tx with nonce 0 is unconfirmed + // key 1, tx with nonce 1 is unconfirmed + // key 2, tx with nonce 9 is unconfirmed and gets a receipt in block 10 + etx1_0 := cltest.MustInsertUnconfirmedEthTx(t, txStore, 0, fromAddress1_1) + etx1_1 := cltest.MustInsertUnconfirmedEthTx(t, txStore, 1, fromAddress1_1) + etx2_9 := cltest.MustInsertUnconfirmedEthTx(t, txStore, 3, fromAddress1_2) + // there also happens to be a confirmed tx with a higher nonce from a different chain in the DB + etx_other_chain := cltest.MustInsertUnconfirmedEthTx(t, txStore, 8, fromAddress2_1) + pgtest.MustExec(t, db, `UPDATE evm.txes SET state='confirmed' WHERE id = $1`, etx_other_chain.ID) + + attempt2_9 := newBroadcastLegacyEthTxAttempt(t, etx2_9.ID, int64(1)) + require.NoError(t, txStore.InsertTxAttempt(ctx, &attempt2_9)) + txmReceipt2_9 := newTxReceipt(attempt2_9.Hash, 10, 1) + + ethClient.On("BatchCallContext", mock.Anything, mock.MatchedBy(func(b []rpc.BatchElem) bool { + return len(b) == 1 && cltest.BatchElemMatchesParams(b[0], attempt2_9.Hash, "eth_getTransactionReceipt") + })).Return(nil).Run(func(args mock.Arguments) { + elems := args.Get(1).([]rpc.BatchElem) + *(elems[0].Result.(*evmtypes.Receipt)) = txmReceipt2_9 + }).Once() + + require.NoError(t, ec.CheckForReceipts(ctx, 10, latestFinalizedBlockNum)) + + mustTxBeInState(t, txStore, etx1_0, txmgrcommon.TxUnconfirmed) + mustTxBeInState(t, txStore, etx1_1, txmgrcommon.TxUnconfirmed) + mustTxBeInState(t, txStore, etx2_9, txmgrcommon.TxConfirmed) + + // Now etx1_1 gets a receipt in block 11, which should mark etx1_0 as confirmed_missing_receipt + attempt1_1 := newBroadcastLegacyEthTxAttempt(t, etx1_1.ID, int64(2)) + require.NoError(t, txStore.InsertTxAttempt(ctx, &attempt1_1)) + txmReceipt1_1 := newTxReceipt(attempt1_1.Hash, 11, 1) + + ethClient.On("BatchCallContext", mock.Anything, mock.MatchedBy(func(b []rpc.BatchElem) bool { + return len(b) == 1 && cltest.BatchElemMatchesParams(b[0], attempt1_1.Hash, "eth_getTransactionReceipt") + })).Return(nil).Run(func(args mock.Arguments) { + elems := args.Get(1).([]rpc.BatchElem) + *(elems[0].Result.(*evmtypes.Receipt)) = txmReceipt1_1 + }).Once() + + require.NoError(t, ec.CheckForReceipts(ctx, 11, latestFinalizedBlockNum)) + + mustTxBeInState(t, txStore, etx1_0, txmgrcommon.TxConfirmedMissingReceipt) + mustTxBeInState(t, txStore, etx1_1, txmgrcommon.TxConfirmed) + mustTxBeInState(t, txStore, etx2_9, txmgrcommon.TxConfirmed) +} + +func TestEthConfirmer_CheckForReceipts_confirmed_missing_receipt(t *testing.T) { + t.Parallel() + + db := pgtest.NewSqlxDB(t) + cfg := configtest.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) {}) + txStore := cltest.NewTestTxStore(t, db) + + ethKeyStore := cltest.NewKeyStore(t, db).Eth() + + _, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore) + + ethClient := testutils.NewEthClientMockWithDefaultChain(t) + + evmcfg := evmtest.NewChainScopedConfig(t, cfg) + + ec := newEthConfirmer(t, txStore, ethClient, cfg, evmcfg, ethKeyStore, nil) + ctx := tests.Context(t) + latestFinalizedBlockNum := int64(0) + + // STATE + // eth_txes with nonce 0 has two attempts (broadcast before block 21 and 41) the first of which will get a receipt + // eth_txes with nonce 1 has two attempts (broadcast before block 21 and 41) neither of which will ever get a receipt + // eth_txes with nonce 2 has an attempt (broadcast before block 41) that will not get a receipt on the first try but will get one later + // eth_txes with nonce 3 has an attempt (broadcast before block 41) that has been confirmed in block 42 + // All other attempts were broadcast before block 41 + b := int64(21) + + etx0 := cltest.MustInsertUnconfirmedEthTx(t, txStore, 0, fromAddress) + attempt0_1 := newBroadcastLegacyEthTxAttempt(t, etx0.ID, int64(1)) + attempt0_2 := newBroadcastLegacyEthTxAttempt(t, etx0.ID, int64(2)) + attempt0_2.BroadcastBeforeBlockNum = &b + require.NoError(t, txStore.InsertTxAttempt(ctx, &attempt0_1)) + require.NoError(t, txStore.InsertTxAttempt(ctx, &attempt0_2)) + + etx1 := cltest.MustInsertUnconfirmedEthTx(t, txStore, 1, fromAddress) + attempt1_1 := newBroadcastLegacyEthTxAttempt(t, etx1.ID, int64(1)) + attempt1_2 := newBroadcastLegacyEthTxAttempt(t, etx1.ID, int64(2)) + attempt1_2.BroadcastBeforeBlockNum = &b + require.NoError(t, txStore.InsertTxAttempt(ctx, &attempt1_1)) + require.NoError(t, txStore.InsertTxAttempt(ctx, &attempt1_2)) + + etx2 := cltest.MustInsertUnconfirmedEthTx(t, txStore, 2, fromAddress) + attempt2_1 := newBroadcastLegacyEthTxAttempt(t, etx2.ID, int64(1)) + require.NoError(t, txStore.InsertTxAttempt(ctx, &attempt2_1)) + + etx3 := cltest.MustInsertUnconfirmedEthTx(t, txStore, 3, fromAddress) + attempt3_1 := newBroadcastLegacyEthTxAttempt(t, etx3.ID, int64(1)) + require.NoError(t, txStore.InsertTxAttempt(ctx, &attempt3_1)) + + pgtest.MustExec(t, db, `UPDATE evm.tx_attempts SET broadcast_before_block_num = 41 WHERE broadcast_before_block_num IS NULL`) + + t.Run("marks buried eth_txes as 'confirmed_missing_receipt'", func(t *testing.T) { + txmReceipt0 := evmtypes.Receipt{ + TxHash: attempt0_2.Hash, + BlockHash: testutils.NewHash(), + BlockNumber: big.NewInt(42), + TransactionIndex: uint(1), + Status: uint64(1), + } + txmReceipt3 := evmtypes.Receipt{ + TxHash: attempt3_1.Hash, + BlockHash: testutils.NewHash(), + BlockNumber: big.NewInt(42), + TransactionIndex: uint(1), + Status: uint64(1), + } + ethClient.On("NonceAt", mock.Anything, mock.Anything, mock.Anything).Return(uint64(4), nil) + ethClient.On("BatchCallContext", mock.Anything, mock.MatchedBy(func(b []rpc.BatchElem) bool { + return len(b) == 6 && + cltest.BatchElemMatchesParams(b[0], attempt0_2.Hash, "eth_getTransactionReceipt") && + cltest.BatchElemMatchesParams(b[1], attempt0_1.Hash, "eth_getTransactionReceipt") && + cltest.BatchElemMatchesParams(b[2], attempt1_2.Hash, "eth_getTransactionReceipt") && + cltest.BatchElemMatchesParams(b[3], attempt1_1.Hash, "eth_getTransactionReceipt") && + cltest.BatchElemMatchesParams(b[4], attempt2_1.Hash, "eth_getTransactionReceipt") && + cltest.BatchElemMatchesParams(b[5], attempt3_1.Hash, "eth_getTransactionReceipt") + })).Return(nil).Run(func(args mock.Arguments) { + elems := args.Get(1).([]rpc.BatchElem) + // First transaction confirmed + *(elems[0].Result.(*evmtypes.Receipt)) = txmReceipt0 + elems[1].Result = &evmtypes.Receipt{} + // Second transaction stil unconfirmed + elems[2].Result = &evmtypes.Receipt{} + elems[3].Result = &evmtypes.Receipt{} + // Third transaction still unconfirmed + elems[4].Result = &evmtypes.Receipt{} + // Fourth transaction is confirmed + *(elems[5].Result.(*evmtypes.Receipt)) = txmReceipt3 + }).Once() + + // PERFORM + // Block num of 43 is one higher than the receipt (as would generally be expected) + require.NoError(t, ec.CheckForReceipts(ctx, 43, latestFinalizedBlockNum)) + + // Expected state is that the "top" eth_tx is now confirmed, with the + // two below it "confirmed_missing_receipt" and the "bottom" eth_tx also confirmed var err error - etx1, err = txStore.FindTxWithAttempts(ctx, etx1.ID) + etx3, err = txStore.FindTxWithAttempts(ctx, etx3.ID) require.NoError(t, err) - require.Equal(t, txmgrcommon.TxConfirmed, etx1.State) - attempt1 := etx1.TxAttempts[0] - require.Equal(t, txmgrtypes.TxAttemptBroadcast, attempt1.State) - require.Len(t, attempt1.Receipts, 1) + require.Equal(t, txmgrcommon.TxConfirmed, etx3.State) + + ethReceipt := etx3.TxAttempts[0].Receipts[0] + require.Equal(t, txmReceipt3.BlockHash, ethReceipt.GetBlockHash()) etx2, err = txStore.FindTxWithAttempts(ctx, etx2.ID) require.NoError(t, err) - require.Equal(t, txmgrcommon.TxFatalError, etx2.State) - require.Equal(t, client.TerminallyStuckMsg, etx2.Error.String) - attempt2 := etx2.TxAttempts[0] - require.Equal(t, txmgrtypes.TxAttemptBroadcast, attempt2.State) - require.Len(t, attempt2.Receipts, 1) + require.Equal(t, txmgrcommon.TxConfirmedMissingReceipt, etx2.State) + etx1, err = txStore.FindTxWithAttempts(ctx, etx1.ID) + require.NoError(t, err) + require.Equal(t, txmgrcommon.TxConfirmedMissingReceipt, etx1.State) + + etx0, err = txStore.FindTxWithAttempts(ctx, etx0.ID) + require.NoError(t, err) + require.Equal(t, txmgrcommon.TxConfirmed, etx0.State) + require.Len(t, etx0.TxAttempts, 2) + require.Len(t, etx0.TxAttempts[0].Receipts, 1) + ethReceipt = etx0.TxAttempts[0].Receipts[0] + require.Equal(t, txmReceipt0.BlockHash, ethReceipt.GetBlockHash()) + }) + + // STATE + // eth_txes with nonce 0 is confirmed + // eth_txes with nonce 1 is confirmed_missing_receipt + // eth_txes with nonce 2 is confirmed_missing_receipt + // eth_txes with nonce 3 is confirmed + + t.Run("marks eth_txes with state 'confirmed_missing_receipt' as 'confirmed' if a receipt finally shows up", func(t *testing.T) { + txmReceipt := evmtypes.Receipt{ + TxHash: attempt2_1.Hash, + BlockHash: testutils.NewHash(), + BlockNumber: big.NewInt(43), + TransactionIndex: uint(1), + Status: uint64(1), + } + ethClient.On("NonceAt", mock.Anything, mock.Anything, mock.Anything).Return(uint64(10), nil) + ethClient.On("BatchCallContext", mock.Anything, mock.MatchedBy(func(b []rpc.BatchElem) bool { + return len(b) == 3 && + cltest.BatchElemMatchesParams(b[0], attempt1_2.Hash, "eth_getTransactionReceipt") && + cltest.BatchElemMatchesParams(b[1], attempt1_1.Hash, "eth_getTransactionReceipt") && + cltest.BatchElemMatchesParams(b[2], attempt2_1.Hash, "eth_getTransactionReceipt") + })).Return(nil).Run(func(args mock.Arguments) { + elems := args.Get(1).([]rpc.BatchElem) + // First transaction still unconfirmed + elems[0].Result = &evmtypes.Receipt{} + elems[1].Result = &evmtypes.Receipt{} + // Second transaction confirmed + *(elems[2].Result.(*evmtypes.Receipt)) = txmReceipt + }).Once() + + // PERFORM + // Block num of 44 is one higher than the receipt (as would generally be expected) + require.NoError(t, ec.CheckForReceipts(ctx, 44, latestFinalizedBlockNum)) + + // Expected state is that the "top" two eth_txes are now confirmed, with the + // one below it still "confirmed_missing_receipt" and the bottom one remains confirmed + var err error etx3, err = txStore.FindTxWithAttempts(ctx, etx3.ID) require.NoError(t, err) require.Equal(t, txmgrcommon.TxConfirmed, etx3.State) - attempt3 := etx3.TxAttempts[0] - require.Equal(t, txmgrtypes.TxAttemptBroadcast, attempt3.State) - require.Empty(t, attempt3.Receipts) + etx2, err = txStore.FindTxWithAttempts(ctx, etx2.ID) + require.NoError(t, err) + require.Equal(t, txmgrcommon.TxConfirmed, etx2.State) - etx4, err = txStore.FindTxWithAttempts(ctx, etx4.ID) + ethReceipt := etx2.TxAttempts[0].Receipts[0] + require.Equal(t, txmReceipt.BlockHash, ethReceipt.GetBlockHash()) + + etx1, err = txStore.FindTxWithAttempts(ctx, etx1.ID) require.NoError(t, err) - require.Equal(t, txmgrcommon.TxFatalError, etx4.State) - require.Equal(t, client.TerminallyStuckMsg, etx4.Error.String) - attempt4 := etx4.TxAttempts[0] - require.Equal(t, txmgrtypes.TxAttemptBroadcast, attempt4.State) - require.True(t, attempt4.IsPurgeAttempt) - require.Empty(t, attempt4.Receipts) + require.Equal(t, txmgrcommon.TxConfirmedMissingReceipt, etx1.State) + etx0, err = txStore.FindTxWithAttempts(ctx, etx0.ID) + require.NoError(t, err) + require.Equal(t, txmgrcommon.TxConfirmed, etx0.State) + }) - etx5, err = txStore.FindTxWithAttempts(ctx, etx5.ID) + // STATE + // eth_txes with nonce 0 is confirmed + // eth_txes with nonce 1 is confirmed_missing_receipt + // eth_txes with nonce 2 is confirmed + // eth_txes with nonce 3 is confirmed + + t.Run("continues to leave eth_txes with state 'confirmed_missing_receipt' unchanged if at least one attempt is above LatestFinalizedBlockNum", func(t *testing.T) { + ethClient.On("NonceAt", mock.Anything, mock.Anything, mock.Anything).Return(uint64(10), nil) + ethClient.On("BatchCallContext", mock.Anything, mock.MatchedBy(func(b []rpc.BatchElem) bool { + return len(b) == 2 && + cltest.BatchElemMatchesParams(b[0], attempt1_2.Hash, "eth_getTransactionReceipt") && + cltest.BatchElemMatchesParams(b[1], attempt1_1.Hash, "eth_getTransactionReceipt") + })).Return(nil).Run(func(args mock.Arguments) { + elems := args.Get(1).([]rpc.BatchElem) + // Both attempts still unconfirmed + elems[0].Result = &evmtypes.Receipt{} + elems[1].Result = &evmtypes.Receipt{} + }).Once() + + latestFinalizedBlockNum = 30 + + // PERFORM + // Block num of 80 puts the first attempt (21) below threshold but second attempt (41) still above + require.NoError(t, ec.CheckForReceipts(ctx, 80, latestFinalizedBlockNum)) + + // Expected state is that the "top" two eth_txes are now confirmed, with the + // one below it still "confirmed_missing_receipt" and the bottom one remains confirmed + var err error + etx3, err = txStore.FindTxWithAttempts(ctx, etx3.ID) + require.NoError(t, err) + require.Equal(t, txmgrcommon.TxConfirmed, etx3.State) + etx2, err = txStore.FindTxWithAttempts(ctx, etx2.ID) + require.NoError(t, err) + require.Equal(t, txmgrcommon.TxConfirmed, etx2.State) + etx1, err = txStore.FindTxWithAttempts(ctx, etx1.ID) + require.NoError(t, err) + require.Equal(t, txmgrcommon.TxConfirmedMissingReceipt, etx1.State) + etx0, err = txStore.FindTxWithAttempts(ctx, etx0.ID) + require.NoError(t, err) + require.Equal(t, txmgrcommon.TxConfirmed, etx0.State) + }) + + // STATE + // eth_txes with nonce 0 is confirmed + // eth_txes with nonce 1 is confirmed_missing_receipt + // eth_txes with nonce 2 is confirmed + // eth_txes with nonce 3 is confirmed + + t.Run("marks eth_Txes with state 'confirmed_missing_receipt' as 'errored' if a receipt fails to show up and all attempts are buried deeper than LatestFinalizedBlockNum", func(t *testing.T) { + ethClient.On("NonceAt", mock.Anything, mock.Anything, mock.Anything).Return(uint64(10), nil) + ethClient.On("BatchCallContext", mock.Anything, mock.MatchedBy(func(b []rpc.BatchElem) bool { + return len(b) == 2 && + cltest.BatchElemMatchesParams(b[0], attempt1_2.Hash, "eth_getTransactionReceipt") && + cltest.BatchElemMatchesParams(b[1], attempt1_1.Hash, "eth_getTransactionReceipt") + })).Return(nil).Run(func(args mock.Arguments) { + elems := args.Get(1).([]rpc.BatchElem) + // Both attempts still unconfirmed + elems[0].Result = &evmtypes.Receipt{} + elems[1].Result = &evmtypes.Receipt{} + }).Once() + + latestFinalizedBlockNum = 50 + + // PERFORM + // Block num of 100 puts the first attempt (21) and second attempt (41) below threshold + require.NoError(t, ec.CheckForReceipts(ctx, 100, latestFinalizedBlockNum)) + + // Expected state is that the "top" two eth_txes are now confirmed, with the + // one below it marked as "fatal_error" and the bottom one remains confirmed + var err error + etx3, err = txStore.FindTxWithAttempts(ctx, etx3.ID) + require.NoError(t, err) + require.Equal(t, txmgrcommon.TxConfirmed, etx3.State) + etx2, err = txStore.FindTxWithAttempts(ctx, etx2.ID) + require.NoError(t, err) + require.Equal(t, txmgrcommon.TxConfirmed, etx2.State) + etx1, err = txStore.FindTxWithAttempts(ctx, etx1.ID) require.NoError(t, err) - require.Equal(t, txmgrcommon.TxUnconfirmed, etx5.State) - attempt5 := etx5.TxAttempts[0] - require.Equal(t, txmgrtypes.TxAttemptBroadcast, attempt5.State) - require.Empty(t, attempt3.Receipts) + require.Equal(t, txmgrcommon.TxFatalError, etx1.State) + etx0, err = txStore.FindTxWithAttempts(ctx, etx0.ID) + require.NoError(t, err) + require.Equal(t, txmgrcommon.TxConfirmed, etx0.State) }) } +func TestEthConfirmer_CheckConfirmedMissingReceipt(t *testing.T) { + t.Parallel() + + db := pgtest.NewSqlxDB(t) + cfg := configtest.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) {}) + txStore := cltest.NewTestTxStore(t, db) + + ethKeyStore := cltest.NewKeyStore(t, db).Eth() + + _, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore) + + ethClient := testutils.NewEthClientMockWithDefaultChain(t) + ethClient.On("IsL2").Return(false).Maybe() + + evmcfg := evmtest.NewChainScopedConfig(t, cfg) + + ec := newEthConfirmer(t, txStore, ethClient, cfg, evmcfg, ethKeyStore, nil) + ctx := tests.Context(t) + + // STATE + // eth_txes with nonce 0 has two attempts, the later attempt with higher gas fees + // eth_txes with nonce 1 has two attempts, the later attempt with higher gas fees + // eth_txes with nonce 2 has one attempt + originalBroadcastAt := time.Unix(1616509100, 0) + etx0 := mustInsertConfirmedMissingReceiptEthTxWithLegacyAttempt( + t, txStore, 0, 1, originalBroadcastAt, fromAddress) + attempt0_2 := newBroadcastLegacyEthTxAttempt(t, etx0.ID, int64(2)) + require.NoError(t, txStore.InsertTxAttempt(ctx, &attempt0_2)) + etx1 := mustInsertConfirmedMissingReceiptEthTxWithLegacyAttempt( + t, txStore, 1, 1, originalBroadcastAt, fromAddress) + attempt1_2 := newBroadcastLegacyEthTxAttempt(t, etx1.ID, int64(2)) + require.NoError(t, txStore.InsertTxAttempt(ctx, &attempt1_2)) + etx2 := mustInsertConfirmedMissingReceiptEthTxWithLegacyAttempt( + t, txStore, 2, 1, originalBroadcastAt, fromAddress) + attempt2_1 := etx2.TxAttempts[0] + etx3 := mustInsertConfirmedMissingReceiptEthTxWithLegacyAttempt( + t, txStore, 3, 1, originalBroadcastAt, fromAddress) + attempt3_1 := etx3.TxAttempts[0] + + ethClient.On("BatchCallContextAll", mock.Anything, mock.MatchedBy(func(b []rpc.BatchElem) bool { + return len(b) == 4 && + cltest.BatchElemMatchesParams(b[0], hexutil.Encode(attempt0_2.SignedRawTx), "eth_sendRawTransaction") && + cltest.BatchElemMatchesParams(b[1], hexutil.Encode(attempt1_2.SignedRawTx), "eth_sendRawTransaction") && + cltest.BatchElemMatchesParams(b[2], hexutil.Encode(attempt2_1.SignedRawTx), "eth_sendRawTransaction") && + cltest.BatchElemMatchesParams(b[3], hexutil.Encode(attempt3_1.SignedRawTx), "eth_sendRawTransaction") + })).Return(nil).Run(func(args mock.Arguments) { + elems := args.Get(1).([]rpc.BatchElem) + // First transaction confirmed + elems[0].Error = errors.New("nonce too low") + elems[1].Error = errors.New("transaction underpriced") + elems[2].Error = nil + elems[3].Error = errors.New("transaction already finalized") + }).Once() + + // PERFORM + require.NoError(t, ec.CheckConfirmedMissingReceipt(ctx)) + + // Expected state is that the "top" eth_tx is untouched but the other two + // are marked as unconfirmed + var err error + etx0, err = txStore.FindTxWithAttempts(ctx, etx0.ID) + assert.NoError(t, err) + assert.Equal(t, txmgrcommon.TxConfirmedMissingReceipt, etx0.State) + assert.Greater(t, etx0.BroadcastAt.Unix(), originalBroadcastAt.Unix()) + etx1, err = txStore.FindTxWithAttempts(ctx, etx1.ID) + assert.NoError(t, err) + assert.Equal(t, txmgrcommon.TxUnconfirmed, etx1.State) + assert.Greater(t, etx1.BroadcastAt.Unix(), originalBroadcastAt.Unix()) + etx2, err = txStore.FindTxWithAttempts(ctx, etx2.ID) + assert.NoError(t, err) + assert.Equal(t, txmgrcommon.TxUnconfirmed, etx2.State) + assert.Greater(t, etx2.BroadcastAt.Unix(), originalBroadcastAt.Unix()) + etx3, err = txStore.FindTxWithAttempts(ctx, etx3.ID) + assert.NoError(t, err) + assert.Equal(t, txmgrcommon.TxConfirmedMissingReceipt, etx3.State) + assert.Greater(t, etx3.BroadcastAt.Unix(), originalBroadcastAt.Unix()) +} + +func TestEthConfirmer_CheckConfirmedMissingReceipt_batchSendTransactions_fails(t *testing.T) { + t.Parallel() + + db := pgtest.NewSqlxDB(t) + cfg := configtest.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) {}) + txStore := cltest.NewTestTxStore(t, db) + + ethKeyStore := cltest.NewKeyStore(t, db).Eth() + + _, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore) + + ethClient := testutils.NewEthClientMockWithDefaultChain(t) + ethClient.On("IsL2").Return(false).Maybe() + + evmcfg := evmtest.NewChainScopedConfig(t, cfg) + + ec := newEthConfirmer(t, txStore, ethClient, cfg, evmcfg, ethKeyStore, nil) + ctx := tests.Context(t) + + // STATE + // eth_txes with nonce 0 has two attempts, the later attempt with higher gas fees + // eth_txes with nonce 1 has two attempts, the later attempt with higher gas fees + // eth_txes with nonce 2 has one attempt + originalBroadcastAt := time.Unix(1616509100, 0) + etx0 := mustInsertConfirmedMissingReceiptEthTxWithLegacyAttempt( + t, txStore, 0, 1, originalBroadcastAt, fromAddress) + attempt0_2 := newBroadcastLegacyEthTxAttempt(t, etx0.ID, int64(2)) + require.NoError(t, txStore.InsertTxAttempt(ctx, &attempt0_2)) + etx1 := mustInsertConfirmedMissingReceiptEthTxWithLegacyAttempt( + t, txStore, 1, 1, originalBroadcastAt, fromAddress) + attempt1_2 := newBroadcastLegacyEthTxAttempt(t, etx1.ID, int64(2)) + require.NoError(t, txStore.InsertTxAttempt(ctx, &attempt1_2)) + etx2 := mustInsertConfirmedMissingReceiptEthTxWithLegacyAttempt( + t, txStore, 2, 1, originalBroadcastAt, fromAddress) + attempt2_1 := etx2.TxAttempts[0] + + ethClient.On("BatchCallContextAll", mock.Anything, mock.MatchedBy(func(b []rpc.BatchElem) bool { + return len(b) == 3 && + cltest.BatchElemMatchesParams(b[0], hexutil.Encode(attempt0_2.SignedRawTx), "eth_sendRawTransaction") && + cltest.BatchElemMatchesParams(b[1], hexutil.Encode(attempt1_2.SignedRawTx), "eth_sendRawTransaction") && + cltest.BatchElemMatchesParams(b[2], hexutil.Encode(attempt2_1.SignedRawTx), "eth_sendRawTransaction") + })).Return(errors.New("Timed out")).Once() + + // PERFORM + require.NoError(t, ec.CheckConfirmedMissingReceipt(ctx)) + + // Expected state is that all txes are marked as unconfirmed, since the batch call had failed + var err error + etx0, err = txStore.FindTxWithAttempts(ctx, etx0.ID) + assert.NoError(t, err) + assert.Equal(t, txmgrcommon.TxUnconfirmed, etx0.State) + assert.Equal(t, etx0.BroadcastAt.Unix(), originalBroadcastAt.Unix()) + etx1, err = txStore.FindTxWithAttempts(ctx, etx1.ID) + assert.NoError(t, err) + assert.Equal(t, txmgrcommon.TxUnconfirmed, etx1.State) + assert.Equal(t, etx1.BroadcastAt.Unix(), originalBroadcastAt.Unix()) + etx2, err = txStore.FindTxWithAttempts(ctx, etx2.ID) + assert.NoError(t, err) + assert.Equal(t, txmgrcommon.TxUnconfirmed, etx2.State) + assert.Equal(t, etx2.BroadcastAt.Unix(), originalBroadcastAt.Unix()) +} + +func TestEthConfirmer_CheckConfirmedMissingReceipt_smallEvmRPCBatchSize_middleBatchSendTransactionFails(t *testing.T) { + t.Parallel() + + db := pgtest.NewSqlxDB(t) + cfg := configtest.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) { + c.EVM[0].RPCDefaultBatchSize = ptr[uint32](1) + }) + txStore := cltest.NewTestTxStore(t, db) + + ethKeyStore := cltest.NewKeyStore(t, db).Eth() + + _, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore) + + ethClient := testutils.NewEthClientMockWithDefaultChain(t) + ethClient.On("IsL2").Return(false).Maybe() + + evmcfg := evmtest.NewChainScopedConfig(t, cfg) + + ec := newEthConfirmer(t, txStore, ethClient, cfg, evmcfg, ethKeyStore, nil) + ctx := tests.Context(t) + + // STATE + // eth_txes with nonce 0 has two attempts, the later attempt with higher gas fees + // eth_txes with nonce 1 has two attempts, the later attempt with higher gas fees + // eth_txes with nonce 2 has one attempt + originalBroadcastAt := time.Unix(1616509100, 0) + etx0 := mustInsertConfirmedMissingReceiptEthTxWithLegacyAttempt( + t, txStore, 0, 1, originalBroadcastAt, fromAddress) + attempt0_2 := newBroadcastLegacyEthTxAttempt(t, etx0.ID, int64(2)) + require.NoError(t, txStore.InsertTxAttempt(ctx, &attempt0_2)) + etx1 := mustInsertConfirmedMissingReceiptEthTxWithLegacyAttempt( + t, txStore, 1, 1, originalBroadcastAt, fromAddress) + attempt1_2 := newBroadcastLegacyEthTxAttempt(t, etx1.ID, int64(2)) + require.NoError(t, txStore.InsertTxAttempt(ctx, &attempt1_2)) + etx2 := mustInsertConfirmedMissingReceiptEthTxWithLegacyAttempt( + t, txStore, 2, 1, originalBroadcastAt, fromAddress) + + // Expect eth_sendRawTransaction in 3 batches. First batch will pass, 2nd will fail, 3rd never attempted. + ethClient.On("BatchCallContextAll", mock.Anything, mock.MatchedBy(func(b []rpc.BatchElem) bool { + return len(b) == 1 && + cltest.BatchElemMatchesParams(b[0], hexutil.Encode(attempt0_2.SignedRawTx), "eth_sendRawTransaction") + })).Return(nil).Run(func(args mock.Arguments) { + elems := args.Get(1).([]rpc.BatchElem) + // First transaction confirmed + elems[0].Error = errors.New("nonce too low") + }).Once() + ethClient.On("BatchCallContextAll", mock.Anything, mock.MatchedBy(func(b []rpc.BatchElem) bool { + return len(b) == 1 && + cltest.BatchElemMatchesParams(b[0], hexutil.Encode(attempt1_2.SignedRawTx), "eth_sendRawTransaction") + })).Return(errors.New("Timed out")).Once() + + // PERFORM + require.NoError(t, ec.CheckConfirmedMissingReceipt(ctx)) + + // Expected state is that all transactions since failed batch will be unconfirmed + var err error + etx0, err = txStore.FindTxWithAttempts(ctx, etx0.ID) + assert.NoError(t, err) + assert.Equal(t, txmgrcommon.TxConfirmedMissingReceipt, etx0.State) + assert.Greater(t, etx0.BroadcastAt.Unix(), originalBroadcastAt.Unix()) + etx1, err = txStore.FindTxWithAttempts(ctx, etx1.ID) + assert.NoError(t, err) + assert.Equal(t, txmgrcommon.TxUnconfirmed, etx1.State) + assert.Equal(t, etx1.BroadcastAt.Unix(), originalBroadcastAt.Unix()) + etx2, err = txStore.FindTxWithAttempts(ctx, etx2.ID) + assert.NoError(t, err) + assert.Equal(t, txmgrcommon.TxUnconfirmed, etx2.State) + assert.Equal(t, etx2.BroadcastAt.Unix(), originalBroadcastAt.Unix()) +} + func TestEthConfirmer_FindTxsRequiringRebroadcast(t *testing.T) { t.Parallel() @@ -449,7 +1381,7 @@ func TestEthConfirmer_FindTxsRequiringRebroadcast(t *testing.T) { etxs, err := ec.FindTxsRequiringRebroadcast(tests.Context(t), lggr, evmFromAddress, currentHead, gasBumpThreshold, 10, 0, &cltest.FixtureChainID) require.NoError(t, err) - require.Empty(t, etxs) + assert.Len(t, etxs, 0) }) mustInsertInProgressEthTx(t, txStore, nonce, fromAddress) @@ -459,7 +1391,7 @@ func TestEthConfirmer_FindTxsRequiringRebroadcast(t *testing.T) { etxs, err := ec.FindTxsRequiringRebroadcast(tests.Context(t), lggr, evmFromAddress, currentHead, gasBumpThreshold, 10, 0, &cltest.FixtureChainID) require.NoError(t, err) - require.Empty(t, etxs) + assert.Len(t, etxs, 0) }) // This one has BroadcastBeforeBlockNum set as nil... which can happen, but it should be ignored @@ -470,7 +1402,7 @@ func TestEthConfirmer_FindTxsRequiringRebroadcast(t *testing.T) { etxs, err := ec.FindTxsRequiringRebroadcast(tests.Context(t), lggr, evmFromAddress, currentHead, gasBumpThreshold, 10, 0, &cltest.FixtureChainID) require.NoError(t, err) - require.Empty(t, etxs) + assert.Len(t, etxs, 0) }) etx1 := cltest.MustInsertUnconfirmedEthTxWithBroadcastLegacyAttempt(t, txStore, nonce, fromAddress) @@ -488,7 +1420,7 @@ func TestEthConfirmer_FindTxsRequiringRebroadcast(t *testing.T) { etxs, err := ec.FindTxsRequiringRebroadcast(tests.Context(t), lggr, evmFromAddress, currentHead, gasBumpThreshold, 10, 0, &cltest.FixtureChainID) require.NoError(t, err) - assert.Empty(t, etxs) + assert.Len(t, etxs, 0) }) etx2 := cltest.MustInsertUnconfirmedEthTxWithBroadcastLegacyAttempt(t, txStore, nonce, fromAddress) @@ -502,7 +1434,7 @@ func TestEthConfirmer_FindTxsRequiringRebroadcast(t *testing.T) { etxs, err := ec.FindTxsRequiringRebroadcast(tests.Context(t), lggr, evmFromAddress, currentHead, gasBumpThreshold, 10, 0, &cltest.FixtureChainID) require.NoError(t, err) - assert.Empty(t, etxs) + assert.Len(t, etxs, 0) }) etxWithoutAttempts := cltest.NewEthTx(fromAddress) @@ -521,7 +1453,7 @@ func TestEthConfirmer_FindTxsRequiringRebroadcast(t *testing.T) { etxs, err := ec.FindTxsRequiringRebroadcast(tests.Context(t), lggr, evmOtherAddress, currentHead, gasBumpThreshold, 10, 0, &cltest.FixtureChainID) require.NoError(t, err) - assert.Empty(t, etxs) + assert.Len(t, etxs, 0) }) t.Run("returns the transaction if it is unconfirmed and has no attempts (note that this is an invariant violation, but we handle it anyway)", func(t *testing.T) { @@ -536,7 +1468,7 @@ func TestEthConfirmer_FindTxsRequiringRebroadcast(t *testing.T) { etxs, err := ec.FindTxsRequiringRebroadcast(tests.Context(t), lggr, evmFromAddress, currentHead, gasBumpThreshold, 10, 0, big.NewInt(42)) require.NoError(t, err) - require.Empty(t, etxs) + require.Len(t, etxs, 0) }) etx3 := cltest.MustInsertUnconfirmedEthTxWithBroadcastLegacyAttempt(t, txStore, nonce, fromAddress) @@ -566,7 +1498,7 @@ func TestEthConfirmer_FindTxsRequiringRebroadcast(t *testing.T) { etxs, err := ec.FindTxsRequiringRebroadcast(tests.Context(t), lggr, evmFromAddress, currentHead, 0, 10, 0, &cltest.FixtureChainID) require.NoError(t, err) - require.Empty(t, etxs) + require.Len(t, etxs, 0) }) t.Run("does not return more transactions for gas bumping than gasBumpThreshold", func(t *testing.T) { @@ -737,7 +1669,7 @@ func TestEthConfirmer_RebroadcastWhereNecessary_WithConnectivityCheck(t *testing stuckTxDetector := txmgr.NewStuckTxDetector(lggr, testutils.FixtureChainID, "", assets.NewWei(assets.NewEth(100).ToInt()), ccfg.EVM().Transactions().AutoPurge(), feeEstimator, txStore, ethClient) ht := headtracker.NewSimulatedHeadTracker(ethClient, true, 0) // Create confirmer with necessary state - ec := txmgr.NewEvmConfirmer(txStore, txmgr.NewEvmTxmClient(ethClient, nil), txmgr.NewEvmTxmFeeConfig(ccfg.EVM().GasEstimator()), ccfg.EVM().Transactions(), cfg.Database(), kst, txBuilder, lggr, stuckTxDetector, ht) + ec := txmgr.NewEvmConfirmer(txStore, txmgr.NewEvmTxmClient(ethClient, nil), ccfg.EVM(), txmgr.NewEvmTxmFeeConfig(ccfg.EVM().GasEstimator()), ccfg.EVM().Transactions(), cfg.Database(), kst, txBuilder, lggr, stuckTxDetector, ht) servicetest.Run(t, ec) currentHead := int64(30) oldEnough := int64(15) @@ -786,7 +1718,7 @@ func TestEthConfirmer_RebroadcastWhereNecessary_WithConnectivityCheck(t *testing kst.On("EnabledAddressesForChain", mock.Anything, &cltest.FixtureChainID).Return(addresses, nil).Maybe() stuckTxDetector := txmgr.NewStuckTxDetector(lggr, testutils.FixtureChainID, "", assets.NewWei(assets.NewEth(100).ToInt()), ccfg.EVM().Transactions().AutoPurge(), feeEstimator, txStore, ethClient) ht := headtracker.NewSimulatedHeadTracker(ethClient, true, 0) - ec := txmgr.NewEvmConfirmer(txStore, txmgr.NewEvmTxmClient(ethClient, nil), txmgr.NewEvmTxmFeeConfig(ccfg.EVM().GasEstimator()), ccfg.EVM().Transactions(), cfg.Database(), kst, txBuilder, lggr, stuckTxDetector, ht) + ec := txmgr.NewEvmConfirmer(txStore, txmgr.NewEvmTxmClient(ethClient, nil), ccfg.EVM(), txmgr.NewEvmTxmFeeConfig(ccfg.EVM().GasEstimator()), ccfg.EVM().Transactions(), cfg.Database(), kst, txBuilder, lggr, stuckTxDetector, ht) servicetest.Run(t, ec) currentHead := int64(30) oldEnough := int64(15) @@ -861,7 +1793,7 @@ func TestEthConfirmer_RebroadcastWhereNecessary_MaxFeeScenario(t *testing.T) { // Once for the bumped attempt which exceeds limit ethClient.On("SendTransactionReturnCode", mock.Anything, mock.MatchedBy(func(tx *types.Transaction) bool { - return tx.GasPrice().Int64() == int64(20000000000) && tx.Nonce() == uint64(*etx.Sequence) //nolint:gosec // disable G115 + return tx.Nonce() == uint64(*etx.Sequence) && tx.GasPrice().Int64() == int64(20000000000) }), fromAddress).Return(commonclient.ExceedsMaxFee, errors.New("tx fee (1.10 ether) exceeds the configured cap (1.00 ether)")).Once() // Do the thing @@ -882,44 +1814,51 @@ func TestEthConfirmer_RebroadcastWhereNecessary_MaxFeeScenario(t *testing.T) { func TestEthConfirmer_RebroadcastWhereNecessary(t *testing.T) { t.Parallel() + db := pgtest.NewSqlxDB(t) cfg := configtest.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) { c.EVM[0].GasEstimator.PriceMax = assets.GWei(500) - c.EVM[0].GasEstimator.BumpMin = assets.NewWeiI(0) }) + txStore := cltest.NewTestTxStore(t, db) ctx := tests.Context(t) + ethClient := testutils.NewEthClientMockWithDefaultChain(t) + ethKeyStore := cltest.NewKeyStore(t, db).Eth() + evmcfg := evmtest.NewChainScopedConfig(t, cfg) + + _, _ = cltest.MustInsertRandomKeyReturningState(t, ethKeyStore) + _, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore) + + kst := ksmocks.NewEth(t) + addresses := []gethCommon.Address{fromAddress} + kst.On("EnabledAddressesForChain", mock.Anything, &cltest.FixtureChainID).Return(addresses, nil).Maybe() + // Use a mock keystore for this test + ec := newEthConfirmer(t, txStore, ethClient, cfg, evmcfg, kst, nil) currentHead := int64(30) + oldEnough := int64(19) + nonce := int64(0) t.Run("does nothing if no transactions require bumping", func(t *testing.T) { - db := pgtest.NewSqlxDB(t) - txStore := cltest.NewTestTxStore(t, db) - ethKeyStore := cltest.NewKeyStore(t, db).Eth() - cltest.MustInsertRandomKeyReturningState(t, ethKeyStore) - - ec := newEthConfirmer(t, txStore, ethClient, cfg, evmcfg, ethKeyStore, nil) - require.NoError(t, ec.RebroadcastWhereNecessary(ctx, currentHead)) + require.NoError(t, ec.RebroadcastWhereNecessary(tests.Context(t), currentHead)) }) + originalBroadcastAt := time.Unix(1616509100, 0) + etx := cltest.MustInsertUnconfirmedEthTxWithBroadcastLegacyAttempt(t, txStore, nonce, fromAddress, originalBroadcastAt) + nonce++ + attempt1_1 := etx.TxAttempts[0] + var dbAttempt txmgr.DbEthTxAttempt + require.NoError(t, db.Get(&dbAttempt, `UPDATE evm.tx_attempts SET broadcast_before_block_num=$1 WHERE id=$2 RETURNING *`, oldEnough, attempt1_1.ID)) + t.Run("re-sends previous transaction on keystore error", func(t *testing.T) { - db := pgtest.NewSqlxDB(t) - txStore := cltest.NewTestTxStore(t, db) - ethKeyStore := cltest.NewKeyStore(t, db).Eth() - _, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore) - etx := mustInsertUnconfirmedTxWithBroadcastAttempts(t, txStore, 0, fromAddress, 1, 25, assets.NewWeiI(100)) - kst := ksmocks.NewEth(t) - addresses := []gethCommon.Address{fromAddress} - kst.On("EnabledAddressesForChain", mock.Anything, &cltest.FixtureChainID).Return(addresses, nil).Maybe() // simulate bumped transaction that is somehow impossible to sign kst.On("SignTx", mock.Anything, fromAddress, mock.MatchedBy(func(tx *types.Transaction) bool { - return tx.Nonce() == uint64(*etx.Sequence) //nolint:gosec // disable G115 + return tx.Nonce() == uint64(*etx.Sequence) }), mock.Anything).Return(nil, errors.New("signing error")).Once() - // Use a mock keystore for this test - ec := newEthConfirmer(t, txStore, ethClient, cfg, evmcfg, kst, nil) - err := ec.RebroadcastWhereNecessary(ctx, currentHead) + // Do the thing + err := ec.RebroadcastWhereNecessary(tests.Context(t), currentHead) require.Error(t, err) require.Contains(t, err.Error(), "signing error") @@ -931,364 +1870,557 @@ func TestEthConfirmer_RebroadcastWhereNecessary(t *testing.T) { }) t.Run("does nothing and continues on fatal error", func(t *testing.T) { - db := pgtest.NewSqlxDB(t) - txStore := cltest.NewTestTxStore(t, db) - ethKeyStore := cltest.NewKeyStore(t, db).Eth() - _, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore) - etx := mustInsertUnconfirmedTxWithBroadcastAttempts(t, txStore, 0, fromAddress, 1, 25, assets.NewWeiI(100)) - ec := newEthConfirmer(t, txStore, ethClient, cfg, evmcfg, ethKeyStore, nil) - + ethTx := *types.NewTx(&types.LegacyTx{}) + kst.On("SignTx", mock.Anything, + fromAddress, + mock.MatchedBy(func(tx *types.Transaction) bool { + if tx.Nonce() != uint64(*etx.Sequence) { + return false + } + ethTx = *tx + return true + }), + mock.MatchedBy(func(chainID *big.Int) bool { + return chainID.Cmp(evmcfg.EVM().ChainID()) == 0 + })).Return(ðTx, nil).Once() ethClient.On("SendTransactionReturnCode", mock.Anything, mock.MatchedBy(func(tx *types.Transaction) bool { - return tx.Nonce() == uint64(*etx.Sequence) //nolint:gosec // disable G115 + return tx.Nonce() == uint64(*etx.Sequence) }), fromAddress).Return(commonclient.Fatal, errors.New("exceeds block gas limit")).Once() - require.NoError(t, ec.RebroadcastWhereNecessary(ctx, currentHead)) + // Do the thing + require.NoError(t, ec.RebroadcastWhereNecessary(tests.Context(t), currentHead)) var err error etx, err = txStore.FindTxWithAttempts(ctx, etx.ID) require.NoError(t, err) + require.Len(t, etx.TxAttempts, 1) }) + var attempt1_2 txmgr.TxAttempt + ethClient = testutils.NewEthClientMockWithDefaultChain(t) + ec.XXXTestSetClient(txmgr.NewEvmTxmClient(ethClient, nil)) + t.Run("creates new attempt with higher gas price if transaction has an attempt older than threshold", func(t *testing.T) { - db := pgtest.NewSqlxDB(t) - txStore := cltest.NewTestTxStore(t, db) - ethKeyStore := cltest.NewKeyStore(t, db).Eth() - _, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore) - latestGasPrice := assets.GWei(20) - etx := mustInsertUnconfirmedTxWithBroadcastAttempts(t, txStore, 0, fromAddress, 1, 25, latestGasPrice) - ec := newEthConfirmer(t, txStore, ethClient, cfg, evmcfg, ethKeyStore, nil) + expectedBumpedGasPrice := big.NewInt(20000000000) + require.Greater(t, expectedBumpedGasPrice.Int64(), attempt1_1.TxFee.GasPrice.ToInt().Int64()) + ethTx := *types.NewTx(&types.LegacyTx{}) + kst.On("SignTx", mock.Anything, + fromAddress, + mock.MatchedBy(func(tx *types.Transaction) bool { + if expectedBumpedGasPrice.Cmp(tx.GasPrice()) != 0 { + return false + } + ethTx = *tx + return true + }), + mock.MatchedBy(func(chainID *big.Int) bool { + return chainID.Cmp(evmcfg.EVM().ChainID()) == 0 + })).Return(ðTx, nil).Once() ethClient.On("SendTransactionReturnCode", mock.Anything, mock.MatchedBy(func(tx *types.Transaction) bool { - return tx.Nonce() == uint64(*etx.Sequence) //nolint:gosec // disable G115 + return expectedBumpedGasPrice.Cmp(tx.GasPrice()) == 0 }), fromAddress).Return(commonclient.Successful, nil).Once() - require.NoError(t, ec.RebroadcastWhereNecessary(ctx, currentHead)) + // Do the thing + require.NoError(t, ec.RebroadcastWhereNecessary(tests.Context(t), currentHead)) var err error etx, err = txStore.FindTxWithAttempts(ctx, etx.ID) require.NoError(t, err) require.Len(t, etx.TxAttempts, 2) + require.Equal(t, attempt1_1.ID, etx.TxAttempts[1].ID) // Got the new attempt - bumpAttempt := etx.TxAttempts[0] - expectedBumpedGas := latestGasPrice.AddPercentage(evmcfg.EVM().GasEstimator().BumpPercent()) - require.Equal(t, expectedBumpedGas.Int64(), bumpAttempt.TxFee.GasPrice.Int64()) - require.Equal(t, txmgrtypes.TxAttemptBroadcast, bumpAttempt.State) + attempt1_2 = etx.TxAttempts[0] + assert.Equal(t, expectedBumpedGasPrice.Int64(), attempt1_2.TxFee.GasPrice.ToInt().Int64()) + assert.Equal(t, txmgrtypes.TxAttemptBroadcast, attempt1_2.State) }) t.Run("does nothing if there is an attempt without BroadcastBeforeBlockNum set", func(t *testing.T) { - db := pgtest.NewSqlxDB(t) - txStore := cltest.NewTestTxStore(t, db) - ethKeyStore := cltest.NewKeyStore(t, db).Eth() - _, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore) - etx := mustInsertUnconfirmedEthTxWithAttemptState(t, txStore, 0, fromAddress, txmgrtypes.TxAttemptBroadcast) - ec := newEthConfirmer(t, txStore, ethClient, cfg, evmcfg, ethKeyStore, nil) - - require.NoError(t, ec.RebroadcastWhereNecessary(ctx, currentHead)) + // Do the thing + require.NoError(t, ec.RebroadcastWhereNecessary(tests.Context(t), currentHead)) var err error etx, err = txStore.FindTxWithAttempts(ctx, etx.ID) require.NoError(t, err) - require.Len(t, etx.TxAttempts, 1) + require.Len(t, etx.TxAttempts, 2) }) + require.NoError(t, db.Get(&dbAttempt, `UPDATE evm.tx_attempts SET broadcast_before_block_num=$1 WHERE id=$2 RETURNING *`, oldEnough, attempt1_2.ID)) + var attempt1_3 txmgr.TxAttempt t.Run("creates new attempt with higher gas price if transaction is already in mempool (e.g. due to previous crash before we could save the new attempt)", func(t *testing.T) { - db := pgtest.NewSqlxDB(t) - txStore := cltest.NewTestTxStore(t, db) - ethKeyStore := cltest.NewKeyStore(t, db).Eth() - _, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore) - latestGasPrice := assets.GWei(20) - etx := mustInsertUnconfirmedTxWithBroadcastAttempts(t, txStore, 0, fromAddress, 1, 25, latestGasPrice) - ec := newEthConfirmer(t, txStore, ethClient, cfg, evmcfg, ethKeyStore, nil) + expectedBumpedGasPrice := big.NewInt(25000000000) + require.Greater(t, expectedBumpedGasPrice.Int64(), attempt1_2.TxFee.GasPrice.ToInt().Int64()) + ethTx := *types.NewTx(&types.LegacyTx{}) + kst.On("SignTx", mock.Anything, + fromAddress, + mock.MatchedBy(func(tx *types.Transaction) bool { + if evmtypes.Nonce(tx.Nonce()) != *etx.Sequence || expectedBumpedGasPrice.Cmp(tx.GasPrice()) != 0 { + return false + } + ethTx = *tx + return true + }), + mock.Anything).Return(ðTx, nil).Once() ethClient.On("SendTransactionReturnCode", mock.Anything, mock.MatchedBy(func(tx *types.Transaction) bool { - return tx.Nonce() == uint64(*etx.Sequence) //nolint:gosec // disable G115 - }), fromAddress).Return(commonclient.Successful, fmt.Errorf("known transaction: %s", etx.TxAttempts[0].Hash.Hex())).Once() + return expectedBumpedGasPrice.Cmp(tx.GasPrice()) == 0 + }), fromAddress).Return(commonclient.Successful, fmt.Errorf("known transaction: %s", ethTx.Hash().Hex())).Once() - require.NoError(t, ec.RebroadcastWhereNecessary(ctx, currentHead)) + // Do the thing + require.NoError(t, ec.RebroadcastWhereNecessary(tests.Context(t), currentHead)) var err error etx, err = txStore.FindTxWithAttempts(ctx, etx.ID) require.NoError(t, err) - require.Len(t, etx.TxAttempts, 2) + require.Len(t, etx.TxAttempts, 3) + require.Equal(t, attempt1_1.ID, etx.TxAttempts[2].ID) + require.Equal(t, attempt1_2.ID, etx.TxAttempts[1].ID) // Got the new attempt - bumpAttempt := etx.TxAttempts[0] - expectedBumpedGas := latestGasPrice.AddPercentage(evmcfg.EVM().GasEstimator().BumpPercent()) - require.Equal(t, expectedBumpedGas.Int64(), bumpAttempt.TxFee.GasPrice.Int64()) - require.Equal(t, txmgrtypes.TxAttemptBroadcast, bumpAttempt.State) + attempt1_3 = etx.TxAttempts[0] + assert.Equal(t, expectedBumpedGasPrice.Int64(), attempt1_3.TxFee.GasPrice.ToInt().Int64()) + assert.Equal(t, txmgrtypes.TxAttemptBroadcast, attempt1_3.State) }) + require.NoError(t, db.Get(&dbAttempt, `UPDATE evm.tx_attempts SET broadcast_before_block_num=$1 WHERE id=$2 RETURNING *`, oldEnough, attempt1_3.ID)) + var attempt1_4 txmgr.TxAttempt + t.Run("saves new attempt even for transaction that has already been confirmed (nonce already used)", func(t *testing.T) { - db := pgtest.NewSqlxDB(t) - txStore := cltest.NewTestTxStore(t, db) - ethKeyStore := cltest.NewKeyStore(t, db).Eth() - _, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore) - latestGasPrice := assets.GWei(20) - etx := mustInsertUnconfirmedTxWithBroadcastAttempts(t, txStore, 0, fromAddress, 1, 25, latestGasPrice) - ec := newEthConfirmer(t, txStore, ethClient, cfg, evmcfg, ethKeyStore, nil) + expectedBumpedGasPrice := big.NewInt(30000000000) + require.Greater(t, expectedBumpedGasPrice.Int64(), attempt1_2.TxFee.GasPrice.ToInt().Int64()) + ethTx := *types.NewTx(&types.LegacyTx{}) + receipt := evmtypes.Receipt{BlockNumber: big.NewInt(40)} + kst.On("SignTx", mock.Anything, + fromAddress, + mock.MatchedBy(func(tx *types.Transaction) bool { + if evmtypes.Nonce(tx.Nonce()) != *etx.Sequence || expectedBumpedGasPrice.Cmp(tx.GasPrice()) != 0 { + return false + } + ethTx = *tx + receipt.TxHash = tx.Hash() + return true + }), + mock.Anything).Return(ðTx, nil).Once() ethClient.On("SendTransactionReturnCode", mock.Anything, mock.MatchedBy(func(tx *types.Transaction) bool { - return tx.Nonce() == uint64(*etx.Sequence) //nolint:gosec // disable G115 + return expectedBumpedGasPrice.Cmp(tx.GasPrice()) == 0 }), fromAddress).Return(commonclient.TransactionAlreadyKnown, errors.New("nonce too low")).Once() - require.NoError(t, ec.RebroadcastWhereNecessary(ctx, currentHead)) + // Do the thing + require.NoError(t, ec.RebroadcastWhereNecessary(tests.Context(t), currentHead)) var err error etx, err = txStore.FindTxWithAttempts(ctx, etx.ID) require.NoError(t, err) - require.Equal(t, txmgrcommon.TxConfirmed, etx.State) - // Got the new attempt - // Got the new attempt - bumpedAttempt := etx.TxAttempts[0] - expectedBumpedGas := latestGasPrice.AddPercentage(evmcfg.EVM().GasEstimator().BumpPercent()) - require.Equal(t, expectedBumpedGas.Int64(), bumpedAttempt.TxFee.GasPrice.Int64()) + assert.Equal(t, txmgrcommon.TxConfirmedMissingReceipt, etx.State) - require.Len(t, etx.TxAttempts, 2) + // Got the new attempt + attempt1_4 = etx.TxAttempts[0] + assert.Equal(t, expectedBumpedGasPrice.Int64(), attempt1_4.TxFee.GasPrice.ToInt().Int64()) + + require.Len(t, etx.TxAttempts, 4) + require.Equal(t, attempt1_1.ID, etx.TxAttempts[3].ID) + require.Equal(t, attempt1_2.ID, etx.TxAttempts[2].ID) + require.Equal(t, attempt1_3.ID, etx.TxAttempts[1].ID) + require.Equal(t, attempt1_4.ID, etx.TxAttempts[0].ID) require.Equal(t, txmgrtypes.TxAttemptBroadcast, etx.TxAttempts[0].State) require.Equal(t, txmgrtypes.TxAttemptBroadcast, etx.TxAttempts[1].State) + require.Equal(t, txmgrtypes.TxAttemptBroadcast, etx.TxAttempts[2].State) + require.Equal(t, txmgrtypes.TxAttemptBroadcast, etx.TxAttempts[3].State) }) + // Mark original tx as confirmed, so we won't pick it up anymore + pgtest.MustExec(t, db, `UPDATE evm.txes SET state = 'confirmed'`) + + etx2 := cltest.MustInsertUnconfirmedEthTxWithBroadcastLegacyAttempt(t, txStore, nonce, fromAddress) + nonce++ + attempt2_1 := etx2.TxAttempts[0] + require.NoError(t, db.Get(&dbAttempt, `UPDATE evm.tx_attempts SET broadcast_before_block_num=$1 WHERE id=$2 RETURNING *`, oldEnough, attempt2_1.ID)) + var attempt2_2 txmgr.TxAttempt + t.Run("saves in-progress attempt on temporary error and returns error", func(t *testing.T) { - db := pgtest.NewSqlxDB(t) - txStore := cltest.NewTestTxStore(t, db) - ethKeyStore := cltest.NewKeyStore(t, db).Eth() - _, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore) - latestGasPrice := assets.GWei(20) - broadcastBlockNum := int64(25) - etx := mustInsertUnconfirmedTxWithBroadcastAttempts(t, txStore, 0, fromAddress, 1, broadcastBlockNum, latestGasPrice) - ec := newEthConfirmer(t, txStore, ethClient, cfg, evmcfg, ethKeyStore, nil) + expectedBumpedGasPrice := big.NewInt(20000000000) + require.Greater(t, expectedBumpedGasPrice.Int64(), attempt2_1.TxFee.GasPrice.ToInt().Int64()) + ethTx := *types.NewTx(&types.LegacyTx{}) + n := *etx2.Sequence + kst.On("SignTx", mock.Anything, + fromAddress, + mock.MatchedBy(func(tx *types.Transaction) bool { + if evmtypes.Nonce(tx.Nonce()) != n || expectedBumpedGasPrice.Cmp(tx.GasPrice()) != 0 { + return false + } + ethTx = *tx + return true + }), + mock.Anything).Return(ðTx, nil).Once() ethClient.On("SendTransactionReturnCode", mock.Anything, mock.MatchedBy(func(tx *types.Transaction) bool { - return tx.Nonce() == uint64(*etx.Sequence) //nolint:gosec // disable G115 + return evmtypes.Nonce(tx.Nonce()) == n && expectedBumpedGasPrice.Cmp(tx.GasPrice()) == 0 }), fromAddress).Return(commonclient.Unknown, errors.New("some network error")).Once() - err := ec.RebroadcastWhereNecessary(ctx, currentHead) + // Do the thing + err := ec.RebroadcastWhereNecessary(tests.Context(t), currentHead) require.Error(t, err) require.Contains(t, err.Error(), "some network error") - etx, err = txStore.FindTxWithAttempts(ctx, etx.ID) + etx2, err = txStore.FindTxWithAttempts(ctx, etx2.ID) require.NoError(t, err) - require.Equal(t, txmgrcommon.TxUnconfirmed, etx.State) + + assert.Equal(t, txmgrcommon.TxUnconfirmed, etx2.State) // Old attempt is untouched - require.Len(t, etx.TxAttempts, 2) - originalAttempt := etx.TxAttempts[1] - require.Equal(t, txmgrtypes.TxAttemptBroadcast, originalAttempt.State) - require.Equal(t, broadcastBlockNum, *originalAttempt.BroadcastBeforeBlockNum) + require.Len(t, etx2.TxAttempts, 2) + require.Equal(t, attempt2_1.ID, etx2.TxAttempts[1].ID) + attempt2_1 = etx2.TxAttempts[1] + assert.Equal(t, txmgrtypes.TxAttemptBroadcast, attempt2_1.State) + assert.Equal(t, oldEnough, *attempt2_1.BroadcastBeforeBlockNum) // New in_progress attempt saved - bumpedAttempt := etx.TxAttempts[0] - require.Equal(t, txmgrtypes.TxAttemptInProgress, bumpedAttempt.State) - require.Nil(t, bumpedAttempt.BroadcastBeforeBlockNum) + attempt2_2 = etx2.TxAttempts[0] + assert.Equal(t, txmgrtypes.TxAttemptInProgress, attempt2_2.State) + assert.Nil(t, attempt2_2.BroadcastBeforeBlockNum) - // Try again and move the attempt into "broadcast" + // Do it again and move the attempt into "broadcast" + n = *etx2.Sequence ethClient.On("SendTransactionReturnCode", mock.Anything, mock.MatchedBy(func(tx *types.Transaction) bool { - return tx.Nonce() == uint64(*etx.Sequence) //nolint:gosec // disable G115 + return evmtypes.Nonce(tx.Nonce()) == n && expectedBumpedGasPrice.Cmp(tx.GasPrice()) == 0 }), fromAddress).Return(commonclient.Successful, nil).Once() - require.NoError(t, ec.RebroadcastWhereNecessary(ctx, currentHead)) + require.NoError(t, ec.RebroadcastWhereNecessary(tests.Context(t), currentHead)) - etx, err = txStore.FindTxWithAttempts(ctx, etx.ID) + // Attempt marked "broadcast" + etx2, err = txStore.FindTxWithAttempts(ctx, etx2.ID) require.NoError(t, err) - require.Equal(t, txmgrcommon.TxUnconfirmed, etx.State) - // New in_progress attempt saved and marked "broadcast" - require.Len(t, etx.TxAttempts, 2) - bumpedAttempt = etx.TxAttempts[0] - require.Equal(t, txmgrtypes.TxAttemptBroadcast, bumpedAttempt.State) - require.Nil(t, bumpedAttempt.BroadcastBeforeBlockNum) + assert.Equal(t, txmgrcommon.TxUnconfirmed, etx2.State) + + // New in_progress attempt saved + require.Len(t, etx2.TxAttempts, 2) + require.Equal(t, attempt2_2.ID, etx2.TxAttempts[0].ID) + attempt2_2 = etx2.TxAttempts[0] + require.Equal(t, txmgrtypes.TxAttemptBroadcast, attempt2_2.State) + assert.Nil(t, attempt2_2.BroadcastBeforeBlockNum) }) - t.Run("re-bumps attempt if initial bump is underpriced because the bumped gas price is insufficiently higher than the previous one", func(t *testing.T) { - db := pgtest.NewSqlxDB(t) - txStore := cltest.NewTestTxStore(t, db) - ethKeyStore := cltest.NewKeyStore(t, db).Eth() - _, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore) - latestGasPrice := assets.GWei(20) - broadcastBlockNum := int64(25) - etx := mustInsertUnconfirmedTxWithBroadcastAttempts(t, txStore, 0, fromAddress, 1, broadcastBlockNum, latestGasPrice) - ec := newEthConfirmer(t, txStore, ethClient, cfg, evmcfg, ethKeyStore, nil) + // Set BroadcastBeforeBlockNum again so the next test will pick it up + require.NoError(t, db.Get(&dbAttempt, `UPDATE evm.tx_attempts SET broadcast_before_block_num=$1 WHERE id=$2 RETURNING *`, oldEnough, attempt2_2.ID)) + + t.Run("assumes that 'nonce too low' error means confirmed_missing_receipt", func(t *testing.T) { + expectedBumpedGasPrice := big.NewInt(25000000000) + require.Greater(t, expectedBumpedGasPrice.Int64(), attempt2_1.TxFee.GasPrice.ToInt().Int64()) + + ethTx := *types.NewTx(&types.LegacyTx{}) + n := *etx2.Sequence + kst.On("SignTx", mock.Anything, + fromAddress, + mock.MatchedBy(func(tx *types.Transaction) bool { + if evmtypes.Nonce(tx.Nonce()) != n || expectedBumpedGasPrice.Cmp(tx.GasPrice()) != 0 { + return false + } + ethTx = *tx + return true + }), + mock.Anything).Return(ðTx, nil).Once() + ethClient.On("SendTransactionReturnCode", mock.Anything, mock.MatchedBy(func(tx *types.Transaction) bool { + return evmtypes.Nonce(tx.Nonce()) == n && expectedBumpedGasPrice.Cmp(tx.GasPrice()) == 0 + }), fromAddress).Return(commonclient.TransactionAlreadyKnown, errors.New("nonce too low")).Once() + + // Creates new attempt as normal if currentHead is not high enough + require.NoError(t, ec.RebroadcastWhereNecessary(tests.Context(t), currentHead)) + var err error + etx2, err = txStore.FindTxWithAttempts(ctx, etx2.ID) + require.NoError(t, err) + assert.Equal(t, txmgrcommon.TxConfirmedMissingReceipt, etx2.State) + + // One new attempt saved + require.Len(t, etx2.TxAttempts, 3) + assert.Equal(t, txmgrtypes.TxAttemptBroadcast, etx2.TxAttempts[0].State) + assert.Equal(t, txmgrtypes.TxAttemptBroadcast, etx2.TxAttempts[1].State) + assert.Equal(t, txmgrtypes.TxAttemptBroadcast, etx2.TxAttempts[2].State) + }) + + // Original tx is confirmed, so we won't pick it up anymore + etx3 := cltest.MustInsertUnconfirmedEthTxWithBroadcastLegacyAttempt(t, txStore, nonce, fromAddress) + nonce++ + attempt3_1 := etx3.TxAttempts[0] + require.NoError(t, db.Get(&dbAttempt, `UPDATE evm.tx_attempts SET broadcast_before_block_num=$1, gas_price=$2 WHERE id=$3 RETURNING *`, oldEnough, assets.NewWeiI(35000000000), attempt3_1.ID)) + + var attempt3_2 txmgr.TxAttempt + + t.Run("saves attempt anyway if replacement transaction is underpriced because the bumped gas price is insufficiently higher than the previous one", func(t *testing.T) { + expectedBumpedGasPrice := big.NewInt(42000000000) + require.Greater(t, expectedBumpedGasPrice.Int64(), attempt3_1.TxFee.GasPrice.ToInt().Int64()) + + ethTx := *types.NewTx(&types.LegacyTx{}) + kst.On("SignTx", mock.Anything, + fromAddress, + mock.MatchedBy(func(tx *types.Transaction) bool { + if evmtypes.Nonce(tx.Nonce()) != *etx3.Sequence || expectedBumpedGasPrice.Cmp(tx.GasPrice()) != 0 { + return false + } + ethTx = *tx + return true + }), + mock.Anything).Return(ðTx, nil).Once() + ethClient.On("SendTransactionReturnCode", mock.Anything, mock.MatchedBy(func(tx *types.Transaction) bool { + return evmtypes.Nonce(tx.Nonce()) == *etx3.Sequence && expectedBumpedGasPrice.Cmp(tx.GasPrice()) == 0 + }), fromAddress).Return(commonclient.Successful, errors.New("replacement transaction underpriced")).Once() + + // Do the thing + require.NoError(t, ec.RebroadcastWhereNecessary(tests.Context(t), currentHead)) + var err error + etx3, err = txStore.FindTxWithAttempts(ctx, etx3.ID) + require.NoError(t, err) + assert.Equal(t, txmgrcommon.TxUnconfirmed, etx3.State) + + require.Len(t, etx3.TxAttempts, 2) + require.Equal(t, attempt3_1.ID, etx3.TxAttempts[1].ID) + attempt3_2 = etx3.TxAttempts[0] + + assert.Equal(t, expectedBumpedGasPrice.Int64(), attempt3_2.TxFee.GasPrice.ToInt().Int64()) + }) + + require.NoError(t, db.Get(&dbAttempt, `UPDATE evm.tx_attempts SET broadcast_before_block_num=$1 WHERE id=$2 RETURNING *`, oldEnough, attempt3_2.ID)) + var attempt3_3 txmgr.TxAttempt + + t.Run("handles case where transaction is already known somehow", func(t *testing.T) { + expectedBumpedGasPrice := big.NewInt(50400000000) + require.Greater(t, expectedBumpedGasPrice.Int64(), attempt3_1.TxFee.GasPrice.ToInt().Int64()) + + ethTx := *types.NewTx(&types.LegacyTx{}) + kst.On("SignTx", mock.Anything, + fromAddress, + mock.MatchedBy(func(tx *types.Transaction) bool { + if evmtypes.Nonce(tx.Nonce()) != *etx3.Sequence || expectedBumpedGasPrice.Cmp(tx.GasPrice()) != 0 { + return false + } + ethTx = *tx + return true + }), + mock.Anything).Return(ðTx, nil).Once() ethClient.On("SendTransactionReturnCode", mock.Anything, mock.MatchedBy(func(tx *types.Transaction) bool { - return tx.Nonce() == uint64(*etx.Sequence) //nolint:gosec // disable G115 - }), fromAddress).Return(commonclient.Underpriced, errors.New("replacement transaction underpriced")).Once() + return evmtypes.Nonce(tx.Nonce()) == *etx3.Sequence && expectedBumpedGasPrice.Cmp(tx.GasPrice()) == 0 + }), fromAddress).Return(commonclient.Successful, fmt.Errorf("known transaction: %s", ethTx.Hash().Hex())).Once() + + // Do the thing + require.NoError(t, ec.RebroadcastWhereNecessary(tests.Context(t), currentHead)) + var err error + etx3, err = txStore.FindTxWithAttempts(ctx, etx3.ID) + require.NoError(t, err) + + assert.Equal(t, txmgrcommon.TxUnconfirmed, etx3.State) + + require.Len(t, etx3.TxAttempts, 3) + attempt3_3 = etx3.TxAttempts[0] + assert.Equal(t, expectedBumpedGasPrice.Int64(), attempt3_3.TxFee.GasPrice.ToInt().Int64()) + }) + + require.NoError(t, db.Get(&dbAttempt, `UPDATE evm.tx_attempts SET broadcast_before_block_num=$1 WHERE id=$2 RETURNING *`, oldEnough, attempt3_3.ID)) + var attempt3_4 txmgr.TxAttempt + + t.Run("pretends it was accepted and continues the cycle if rejected for being temporarily underpriced", func(t *testing.T) { + // This happens if parity is rejecting transactions that are not priced high enough to even get into the mempool at all + // It should pretend it was accepted into the mempool and hand off to the next cycle to continue bumping gas as normal + temporarilyUnderpricedError := "There are too many transactions in the queue. Your transaction was dropped due to limit. Try increasing the fee." + + expectedBumpedGasPrice := big.NewInt(60480000000) + require.Greater(t, expectedBumpedGasPrice.Int64(), attempt3_2.TxFee.GasPrice.ToInt().Int64()) + + ethTx := *types.NewTx(&types.LegacyTx{}) + kst.On("SignTx", mock.Anything, + fromAddress, + mock.MatchedBy(func(tx *types.Transaction) bool { + if evmtypes.Nonce(tx.Nonce()) != *etx3.Sequence || expectedBumpedGasPrice.Cmp(tx.GasPrice()) != 0 { + return false + } + ethTx = *tx + return true + }), + mock.Anything).Return(ðTx, nil).Once() ethClient.On("SendTransactionReturnCode", mock.Anything, mock.MatchedBy(func(tx *types.Transaction) bool { - return tx.Nonce() == uint64(*etx.Sequence) //nolint:gosec // disable G115 - }), fromAddress).Return(commonclient.Successful, nil).Once() + return evmtypes.Nonce(tx.Nonce()) == *etx3.Sequence && expectedBumpedGasPrice.Cmp(tx.GasPrice()) == 0 + }), fromAddress).Return(commonclient.Successful, errors.New(temporarilyUnderpricedError)).Once() // Do the thing - require.NoError(t, ec.RebroadcastWhereNecessary(ctx, currentHead)) + require.NoError(t, ec.RebroadcastWhereNecessary(tests.Context(t), currentHead)) var err error - etx, err = txStore.FindTxWithAttempts(ctx, etx.ID) + etx3, err = txStore.FindTxWithAttempts(ctx, etx3.ID) require.NoError(t, err) - require.Equal(t, txmgrcommon.TxUnconfirmed, etx.State) - require.Len(t, etx.TxAttempts, 2) - bumpedAttempt := etx.TxAttempts[0] - expectedBumpedGas := latestGasPrice.AddPercentage(evmcfg.EVM().GasEstimator().BumpPercent()) - expectedBumpedGas = expectedBumpedGas.AddPercentage(evmcfg.EVM().GasEstimator().BumpPercent()) - require.Equal(t, expectedBumpedGas.Int64(), bumpedAttempt.TxFee.GasPrice.Int64()) + assert.Equal(t, txmgrcommon.TxUnconfirmed, etx3.State) + + require.Len(t, etx3.TxAttempts, 4) + attempt3_4 = etx3.TxAttempts[0] + assert.Equal(t, expectedBumpedGasPrice.Int64(), attempt3_4.TxFee.GasPrice.ToInt().Int64()) }) + require.NoError(t, db.Get(&dbAttempt, `UPDATE evm.tx_attempts SET broadcast_before_block_num=$1 WHERE id=$2 RETURNING *`, oldEnough, attempt3_4.ID)) + t.Run("resubmits at the old price and does not create a new attempt if one of the bumped transactions would exceed EVM.GasEstimator.PriceMax", func(t *testing.T) { - db := pgtest.NewSqlxDB(t) - txStore := cltest.NewTestTxStore(t, db) - priceMax := assets.GWei(30) + // Set price such that the next bump will exceed EVM.GasEstimator.PriceMax + // Existing gas price is: 60480000000 + gasPrice := attempt3_4.TxFee.GasPrice.ToInt() gcfg := configtest.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) { - c.EVM[0].GasEstimator.PriceMax = priceMax + c.EVM[0].GasEstimator.PriceMax = assets.NewWeiI(60500000000) }) newCfg := evmtest.NewChainScopedConfig(t, gcfg) - ethKeyStore := cltest.NewKeyStore(t, db).Eth() - _, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore) - broadcastBlockNum := int64(25) - currentAttemptPrice := priceMax.Sub(assets.GWei(1)) - etx := mustInsertUnconfirmedTxWithBroadcastAttempts(t, txStore, 0, fromAddress, 1, broadcastBlockNum, currentAttemptPrice) - ec := newEthConfirmer(t, txStore, ethClient, cfg, newCfg, ethKeyStore, nil) + ec2 := newEthConfirmer(t, txStore, ethClient, gcfg, newCfg, ethKeyStore, nil) ethClient.On("SendTransactionReturnCode", mock.Anything, mock.MatchedBy(func(tx *types.Transaction) bool { - return tx.Nonce() == uint64(*etx.Sequence) //nolint:gosec // disable G115 - }), fromAddress).Return(commonclient.Underpriced, errors.New("underpriced")).Once() // we already submitted at this price, now it's time to bump and submit again but since we simply resubmitted rather than increasing gas price, geth already knows about this tx + return evmtypes.Nonce(tx.Nonce()) == *etx3.Sequence && gasPrice.Cmp(tx.GasPrice()) == 0 + }), fromAddress).Return(commonclient.Successful, errors.New("already known")).Once() // we already submitted at this price, now it's time to bump and submit again but since we simply resubmitted rather than increasing gas price, geth already knows about this tx // Do the thing - require.Error(t, ec.RebroadcastWhereNecessary(ctx, currentHead)) + require.NoError(t, ec2.RebroadcastWhereNecessary(tests.Context(t), currentHead)) var err error - etx, err = txStore.FindTxWithAttempts(ctx, etx.ID) + etx3, err = txStore.FindTxWithAttempts(ctx, etx3.ID) require.NoError(t, err) - require.Equal(t, txmgrcommon.TxUnconfirmed, etx.State) + + assert.Equal(t, txmgrcommon.TxUnconfirmed, etx3.State) // No new tx attempts - require.Len(t, etx.TxAttempts, 1) - bumpedAttempt := etx.TxAttempts[0] - require.Equal(t, currentAttemptPrice.Int64(), bumpedAttempt.TxFee.GasPrice.Int64()) + require.Len(t, etx3.TxAttempts, 4) + attempt3_4 = etx3.TxAttempts[0] + assert.Equal(t, gasPrice.Int64(), attempt3_4.TxFee.GasPrice.ToInt().Int64()) }) + require.NoError(t, db.Get(&dbAttempt, `UPDATE evm.tx_attempts SET broadcast_before_block_num=$1 WHERE id=$2 RETURNING *`, oldEnough, attempt3_4.ID)) + t.Run("resubmits at the old price and does not create a new attempt if the current price is exactly EVM.GasEstimator.PriceMax", func(t *testing.T) { - db := pgtest.NewSqlxDB(t) - txStore := cltest.NewTestTxStore(t, db) - priceMax := assets.GWei(30) + // Set price such that the current price is already at EVM.GasEstimator.PriceMax + // Existing gas price is: 60480000000 + gasPrice := attempt3_4.TxFee.GasPrice.ToInt() gcfg := configtest.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) { - c.EVM[0].GasEstimator.PriceMax = priceMax + c.EVM[0].GasEstimator.PriceMax = assets.NewWeiI(60480000000) }) newCfg := evmtest.NewChainScopedConfig(t, gcfg) - ethKeyStore := cltest.NewKeyStore(t, db).Eth() - _, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore) - broadcastBlockNum := int64(25) - etx := mustInsertUnconfirmedTxWithBroadcastAttempts(t, txStore, 0, fromAddress, 1, broadcastBlockNum, priceMax) - ec := newEthConfirmer(t, txStore, ethClient, cfg, newCfg, ethKeyStore, nil) + ec2 := newEthConfirmer(t, txStore, ethClient, gcfg, newCfg, ethKeyStore, nil) ethClient.On("SendTransactionReturnCode", mock.Anything, mock.MatchedBy(func(tx *types.Transaction) bool { - return tx.Nonce() == uint64(*etx.Sequence) //nolint:gosec // disable G115 - }), fromAddress).Return(commonclient.Underpriced, errors.New("underpriced")).Once() // we already submitted at this price, now it's time to bump and submit again but since we simply resubmitted rather than increasing gas price, geth already knows about this tx + return evmtypes.Nonce(tx.Nonce()) == *etx3.Sequence && gasPrice.Cmp(tx.GasPrice()) == 0 + }), fromAddress).Return(commonclient.Successful, errors.New("already known")).Once() // we already submitted at this price, now it's time to bump and submit again but since we simply resubmitted rather than increasing gas price, geth already knows about this tx // Do the thing - require.Error(t, ec.RebroadcastWhereNecessary(ctx, currentHead)) + require.NoError(t, ec2.RebroadcastWhereNecessary(tests.Context(t), currentHead)) var err error - etx, err = txStore.FindTxWithAttempts(ctx, etx.ID) + etx3, err = txStore.FindTxWithAttempts(ctx, etx3.ID) require.NoError(t, err) - require.Equal(t, txmgrcommon.TxUnconfirmed, etx.State) + + assert.Equal(t, txmgrcommon.TxUnconfirmed, etx3.State) // No new tx attempts - require.Len(t, etx.TxAttempts, 1) - bumpedAttempt := etx.TxAttempts[0] - require.Equal(t, priceMax.Int64(), bumpedAttempt.TxFee.GasPrice.Int64()) + require.Len(t, etx3.TxAttempts, 4) + attempt3_4 = etx3.TxAttempts[0] + assert.Equal(t, gasPrice.Int64(), attempt3_4.TxFee.GasPrice.ToInt().Int64()) }) - t.Run("EIP-1559: bumps using EIP-1559 rules when existing attempts are of type 0x2", func(t *testing.T) { - db := pgtest.NewSqlxDB(t) - txStore := cltest.NewTestTxStore(t, db) - gcfg := configtest.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) { - c.EVM[0].GasEstimator.BumpMin = assets.GWei(1) - }) - newCfg := evmtest.NewChainScopedConfig(t, gcfg) - ethKeyStore := cltest.NewKeyStore(t, db).Eth() - _, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore) - etx := mustInsertUnconfirmedEthTxWithBroadcastDynamicFeeAttempt(t, txStore, 0, fromAddress) - err := txStore.UpdateTxAttemptBroadcastBeforeBlockNum(ctx, etx.ID, uint(25)) - require.NoError(t, err) - ec := newEthConfirmer(t, txStore, ethClient, cfg, newCfg, ethKeyStore, nil) + // The EIP-1559 etx and attempt + etx4 := mustInsertUnconfirmedEthTxWithBroadcastDynamicFeeAttempt(t, txStore, nonce, fromAddress) + attempt4_1 := etx4.TxAttempts[0] + require.NoError(t, db.Get(&dbAttempt, `UPDATE evm.tx_attempts SET broadcast_before_block_num=$1, gas_tip_cap=$2, gas_fee_cap=$3 WHERE id=$4 RETURNING *`, + oldEnough, assets.GWei(35), assets.GWei(100), attempt4_1.ID)) + var attempt4_2 txmgr.TxAttempt + t.Run("EIP-1559: bumps using EIP-1559 rules when existing attempts are of type 0x2", func(t *testing.T) { + ethTx := *types.NewTx(&types.DynamicFeeTx{}) + kst.On("SignTx", mock.Anything, + fromAddress, + mock.MatchedBy(func(tx *types.Transaction) bool { + if evmtypes.Nonce(tx.Nonce()) != *etx4.Sequence { + return false + } + ethTx = *tx + return true + }), + mock.Anything).Return(ðTx, nil).Once() + // This is the new, EIP-1559 attempt + gasTipCap := assets.GWei(42) ethClient.On("SendTransactionReturnCode", mock.Anything, mock.MatchedBy(func(tx *types.Transaction) bool { - return tx.Nonce() == uint64(*etx.Sequence) //nolint:gosec // disable G115 + return evmtypes.Nonce(tx.Nonce()) == *etx4.Sequence && gasTipCap.ToInt().Cmp(tx.GasTipCap()) == 0 }), fromAddress).Return(commonclient.Successful, nil).Once() - require.NoError(t, ec.RebroadcastWhereNecessary(ctx, currentHead)) - etx, err = txStore.FindTxWithAttempts(ctx, etx.ID) + require.NoError(t, ec.RebroadcastWhereNecessary(tests.Context(t), currentHead)) + var err error + etx4, err = txStore.FindTxWithAttempts(ctx, etx4.ID) require.NoError(t, err) - require.Equal(t, txmgrcommon.TxUnconfirmed, etx.State) + + assert.Equal(t, txmgrcommon.TxUnconfirmed, etx4.State) // A new, bumped attempt - require.Len(t, etx.TxAttempts, 2) - bumpAttempt := etx.TxAttempts[0] - require.Nil(t, bumpAttempt.TxFee.GasPrice) - bumpedGas := assets.NewWeiI(1).Add(newCfg.EVM().GasEstimator().BumpMin()) - require.Equal(t, bumpedGas.Int64(), bumpAttempt.TxFee.GasTipCap.Int64()) - require.Equal(t, bumpedGas.Int64(), bumpAttempt.TxFee.GasFeeCap.Int64()) - require.Equal(t, txmgrtypes.TxAttemptBroadcast, bumpAttempt.State) + require.Len(t, etx4.TxAttempts, 2) + attempt4_2 = etx4.TxAttempts[0] + assert.Nil(t, attempt4_2.TxFee.GasPrice) + assert.Equal(t, assets.GWei(42).String(), attempt4_2.TxFee.GasTipCap.String()) + assert.Equal(t, assets.GWei(120).String(), attempt4_2.TxFee.GasFeeCap.String()) + assert.Equal(t, txmgrtypes.TxAttemptBroadcast, attempt1_2.State) }) + require.NoError(t, db.Get(&dbAttempt, `UPDATE evm.tx_attempts SET broadcast_before_block_num=$1, gas_tip_cap=$2, gas_fee_cap=$3 WHERE id=$4 RETURNING *`, + oldEnough, assets.GWei(999), assets.GWei(1000), attempt4_2.ID)) + t.Run("EIP-1559: resubmits at the old price and does not create a new attempt if one of the bumped EIP-1559 transactions would have its tip cap exceed EVM.GasEstimator.PriceMax", func(t *testing.T) { - db := pgtest.NewSqlxDB(t) - txStore := cltest.NewTestTxStore(t, db) gcfg := configtest.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) { - c.EVM[0].GasEstimator.PriceMax = assets.NewWeiI(1) + c.EVM[0].GasEstimator.PriceMax = assets.GWei(1000) }) newCfg := evmtest.NewChainScopedConfig(t, gcfg) - ethKeyStore := cltest.NewKeyStore(t, db).Eth() - _, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore) - etx := mustInsertUnconfirmedEthTxWithBroadcastDynamicFeeAttempt(t, txStore, 0, fromAddress) - err := txStore.UpdateTxAttemptBroadcastBeforeBlockNum(ctx, etx.ID, uint(25)) - require.NoError(t, err) - ec := newEthConfirmer(t, txStore, ethClient, cfg, newCfg, ethKeyStore, nil) + ec2 := newEthConfirmer(t, txStore, ethClient, gcfg, newCfg, ethKeyStore, nil) + // Third attempt failed to bump, resubmits old one instead ethClient.On("SendTransactionReturnCode", mock.Anything, mock.MatchedBy(func(tx *types.Transaction) bool { - return tx.Nonce() == uint64(*etx.Sequence) //nolint:gosec // disable G115 - }), fromAddress).Return(commonclient.Underpriced, errors.New("underpriced")).Once() + return evmtypes.Nonce(tx.Nonce()) == *etx4.Sequence && attempt4_2.Hash.String() == tx.Hash().String() + }), fromAddress).Return(commonclient.Successful, nil).Once() - require.Error(t, ec.RebroadcastWhereNecessary(ctx, currentHead)) - etx, err = txStore.FindTxWithAttempts(ctx, etx.ID) + require.NoError(t, ec2.RebroadcastWhereNecessary(tests.Context(t), currentHead)) + var err error + etx4, err = txStore.FindTxWithAttempts(ctx, etx4.ID) require.NoError(t, err) - assert.Equal(t, txmgrcommon.TxUnconfirmed, etx.State) + + assert.Equal(t, txmgrcommon.TxUnconfirmed, etx4.State) // No new tx attempts - require.Len(t, etx.TxAttempts, 1) - bumpedAttempt := etx.TxAttempts[0] - assert.Equal(t, assets.NewWeiI(1).Int64(), bumpedAttempt.TxFee.GasTipCap.Int64()) - assert.Equal(t, assets.NewWeiI(1).Int64(), bumpedAttempt.TxFee.GasFeeCap.Int64()) + require.Len(t, etx4.TxAttempts, 2) + assert.Equal(t, assets.GWei(999).Int64(), etx4.TxAttempts[0].TxFee.GasTipCap.ToInt().Int64()) + assert.Equal(t, assets.GWei(1000).Int64(), etx4.TxAttempts[0].TxFee.GasFeeCap.ToInt().Int64()) }) - t.Run("EIP-1559: re-bumps attempt if initial bump is underpriced because the bumped gas price is insufficiently higher than the previous one", func(t *testing.T) { - db := pgtest.NewSqlxDB(t) - txStore := cltest.NewTestTxStore(t, db) - gcfg := configtest.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) { - c.EVM[0].GasEstimator.BumpMin = assets.GWei(1) - }) - newCfg := evmtest.NewChainScopedConfig(t, gcfg) + require.NoError(t, db.Get(&dbAttempt, `UPDATE evm.tx_attempts SET broadcast_before_block_num=$1, gas_tip_cap=$2, gas_fee_cap=$3 WHERE id=$4 RETURNING *`, + oldEnough, assets.GWei(45), assets.GWei(100), attempt4_2.ID)) + + t.Run("EIP-1559: saves attempt anyway if replacement transaction is underpriced because the bumped gas price is insufficiently higher than the previous one", func(t *testing.T) { // NOTE: This test case was empirically impossible when I tried it on eth mainnet (any EIP1559 transaction with a higher tip cap is accepted even if it's only 1 wei more) but appears to be possible on Polygon/Matic, probably due to poor design that applies the 10% minimum to the overall value (base fee + tip cap) - ethKeyStore := cltest.NewKeyStore(t, db).Eth() - _, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore) - etx := mustInsertUnconfirmedEthTxWithBroadcastDynamicFeeAttempt(t, txStore, 0, fromAddress) - err := txStore.UpdateTxAttemptBroadcastBeforeBlockNum(ctx, etx.ID, uint(25)) - require.NoError(t, err) - ec := newEthConfirmer(t, txStore, ethClient, cfg, newCfg, ethKeyStore, nil) + expectedBumpedTipCap := assets.GWei(54) + require.Greater(t, expectedBumpedTipCap.Int64(), attempt4_2.TxFee.GasTipCap.ToInt().Int64()) + ethTx := *types.NewTx(&types.LegacyTx{}) + kst.On("SignTx", mock.Anything, + fromAddress, + mock.MatchedBy(func(tx *types.Transaction) bool { + if evmtypes.Nonce(tx.Nonce()) != *etx4.Sequence || expectedBumpedTipCap.ToInt().Cmp(tx.GasTipCap()) != 0 { + return false + } + ethTx = *tx + return true + }), + mock.Anything).Return(ðTx, nil).Once() ethClient.On("SendTransactionReturnCode", mock.Anything, mock.MatchedBy(func(tx *types.Transaction) bool { - return tx.Nonce() == uint64(*etx.Sequence) //nolint:gosec // disable G115 - }), fromAddress).Return(commonclient.Underpriced, errors.New("replacement transaction underpriced")).Once() - ethClient.On("SendTransactionReturnCode", mock.Anything, mock.MatchedBy(func(tx *types.Transaction) bool { - return tx.Nonce() == uint64(*etx.Sequence) //nolint:gosec // disable G115 - }), fromAddress).Return(commonclient.Successful, nil).Once() + return evmtypes.Nonce(tx.Nonce()) == *etx4.Sequence && expectedBumpedTipCap.ToInt().Cmp(tx.GasTipCap()) == 0 + }), fromAddress).Return(commonclient.Successful, errors.New("replacement transaction underpriced")).Once() // Do it - require.NoError(t, ec.RebroadcastWhereNecessary(ctx, currentHead)) - etx, err = txStore.FindTxWithAttempts(ctx, etx.ID) + require.NoError(t, ec.RebroadcastWhereNecessary(tests.Context(t), currentHead)) + var err error + etx4, err = txStore.FindTxWithAttempts(ctx, etx4.ID) require.NoError(t, err) - assert.Equal(t, txmgrcommon.TxUnconfirmed, etx.State) - require.Len(t, etx.TxAttempts, 2) - bumpAttempt := etx.TxAttempts[0] - bumpedGas := assets.NewWeiI(1).Add(newCfg.EVM().GasEstimator().BumpMin()) - bumpedGas = bumpedGas.Add(newCfg.EVM().GasEstimator().BumpMin()) - assert.Equal(t, bumpedGas.Int64(), bumpAttempt.TxFee.GasTipCap.Int64()) + assert.Equal(t, txmgrcommon.TxUnconfirmed, etx4.State) + + require.Len(t, etx4.TxAttempts, 3) + require.Equal(t, attempt4_1.ID, etx4.TxAttempts[2].ID) + require.Equal(t, attempt4_2.ID, etx4.TxAttempts[1].ID) + attempt4_3 := etx4.TxAttempts[0] + + assert.Equal(t, expectedBumpedTipCap.Int64(), attempt4_3.TxFee.GasTipCap.ToInt().Int64()) }) } @@ -1359,7 +2491,7 @@ func TestEthConfirmer_RebroadcastWhereNecessary_TerminallyUnderpriced_ThenGoesTh commonclient.Successful, nil).Once() signedLegacyTx := new(types.Transaction) kst.On("SignTx", mock.Anything, mock.Anything, mock.MatchedBy(func(tx *types.Transaction) bool { - return tx.Type() == 0x0 && tx.Nonce() == uint64(*etx.Sequence) //nolint:gosec // disable G115 + return tx.Type() == 0x0 && tx.Nonce() == uint64(*etx.Sequence) }), mock.Anything).Return( signedLegacyTx, nil, ).Run(func(args mock.Arguments) { @@ -1391,7 +2523,7 @@ func TestEthConfirmer_RebroadcastWhereNecessary_TerminallyUnderpriced_ThenGoesTh commonclient.Successful, nil).Once() signedDxFeeTx := new(types.Transaction) kst.On("SignTx", mock.Anything, mock.Anything, mock.MatchedBy(func(tx *types.Transaction) bool { - return tx.Type() == 0x2 && tx.Nonce() == uint64(*etx.Sequence) //nolint:gosec // disable G115 + return tx.Type() == 0x2 && tx.Nonce() == uint64(*etx.Sequence) }), mock.Anything).Return( signedDxFeeTx, nil, ).Run(func(args mock.Arguments) { @@ -1538,7 +2670,7 @@ func TestEthConfirmer_RebroadcastWhereNecessary_WhenOutOfEth(t *testing.T) { var dbAttempts []txmgr.DbEthTxAttempt require.NoError(t, db.Select(&dbAttempts, "SELECT * FROM evm.tx_attempts WHERE state = 'insufficient_eth'")) - require.Empty(t, dbAttempts) + require.Len(t, dbAttempts, 0) }) } @@ -1575,11 +2707,11 @@ func TestEthConfirmer_RebroadcastWhereNecessary_TerminallyStuckError(t *testing. // Return terminally stuck error on first rebroadcast ethClient.On("SendTransactionReturnCode", mock.Anything, mock.MatchedBy(func(tx *types.Transaction) bool { - return tx.Nonce() == uint64(*etx.Sequence) //nolint:gosec // disable G115 + return tx.Nonce() == uint64(*etx.Sequence) }), fromAddress).Return(commonclient.TerminallyStuck, errors.New(terminallyStuckError)).Once() // Return successful for purge attempt ethClient.On("SendTransactionReturnCode", mock.Anything, mock.MatchedBy(func(tx *types.Transaction) bool { - return tx.Nonce() == uint64(*etx.Sequence) //nolint:gosec // disable G115 + return tx.Nonce() == uint64(*etx.Sequence) }), fromAddress).Return(commonclient.Successful, nil).Once() // Start processing transactions for rebroadcast @@ -1594,6 +2726,180 @@ func TestEthConfirmer_RebroadcastWhereNecessary_TerminallyStuckError(t *testing. }) } +func TestEthConfirmer_EnsureConfirmedTransactionsInLongestChain(t *testing.T) { + t.Parallel() + + db := pgtest.NewSqlxDB(t) + txStore := cltest.NewTestTxStore(t, db) + ctx := tests.Context(t) + + ethKeyStore := cltest.NewKeyStore(t, db).Eth() + + _, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore) + + ethClient := testutils.NewEthClientMockWithDefaultChain(t) + + gconfig, config := newTestChainScopedConfig(t) + ec := newEthConfirmer(t, txStore, ethClient, gconfig, config, ethKeyStore, nil) + + h8 := &evmtypes.Head{ + Number: 8, + Hash: testutils.NewHash(), + } + h9 := &evmtypes.Head{ + Hash: testutils.NewHash(), + Number: 9, + } + h9.Parent.Store(h8) + head := &evmtypes.Head{ + Hash: testutils.NewHash(), + Number: 10, + } + head.Parent.Store(h9) + t.Run("does nothing if there aren't any transactions", func(t *testing.T) { + require.NoError(t, ec.EnsureConfirmedTransactionsInLongestChain(tests.Context(t), head)) + }) + + t.Run("does nothing to unconfirmed transactions", func(t *testing.T) { + etx := cltest.MustInsertUnconfirmedEthTxWithBroadcastLegacyAttempt(t, txStore, 0, fromAddress) + + // Do the thing + require.NoError(t, ec.EnsureConfirmedTransactionsInLongestChain(tests.Context(t), head)) + + etx, err := txStore.FindTxWithAttempts(ctx, etx.ID) + require.NoError(t, err) + assert.Equal(t, txmgrcommon.TxUnconfirmed, etx.State) + }) + + t.Run("does nothing to confirmed transactions with receipts within head height of the chain and included in the chain", func(t *testing.T) { + etx := cltest.MustInsertConfirmedEthTxWithLegacyAttempt(t, txStore, 2, 1, fromAddress) + mustInsertEthReceipt(t, txStore, head.Number, head.Hash, etx.TxAttempts[0].Hash) + + // Do the thing + require.NoError(t, ec.EnsureConfirmedTransactionsInLongestChain(tests.Context(t), head)) + + etx, err := txStore.FindTxWithAttempts(ctx, etx.ID) + require.NoError(t, err) + assert.Equal(t, txmgrcommon.TxConfirmed, etx.State) + }) + + t.Run("does nothing to confirmed transactions that only have receipts older than the start of the chain", func(t *testing.T) { + etx := cltest.MustInsertConfirmedEthTxWithLegacyAttempt(t, txStore, 3, 1, fromAddress) + // Add receipt that is older than the lowest block of the chain + mustInsertEthReceipt(t, txStore, h8.Number-1, testutils.NewHash(), etx.TxAttempts[0].Hash) + + // Do the thing + require.NoError(t, ec.EnsureConfirmedTransactionsInLongestChain(tests.Context(t), head)) + + etx, err := txStore.FindTxWithAttempts(ctx, etx.ID) + require.NoError(t, err) + assert.Equal(t, txmgrcommon.TxConfirmed, etx.State) + }) + + t.Run("unconfirms and rebroadcasts transactions that have receipts within head height of the chain but not included in the chain", func(t *testing.T) { + etx := cltest.MustInsertConfirmedEthTxWithLegacyAttempt(t, txStore, 4, 1, fromAddress) + attempt := etx.TxAttempts[0] + // Include one within head height but a different block hash + mustInsertEthReceipt(t, txStore, head.Parent.Load().Number, testutils.NewHash(), attempt.Hash) + + ethClient.On("SendTransactionReturnCode", mock.Anything, mock.MatchedBy(func(tx *types.Transaction) bool { + atx, err := txmgr.GetGethSignedTx(attempt.SignedRawTx) + require.NoError(t, err) + // Keeps gas price and nonce the same + return atx.GasPrice().Cmp(tx.GasPrice()) == 0 && atx.Nonce() == tx.Nonce() + }), fromAddress).Return(commonclient.Successful, nil).Once() + + // Do the thing + require.NoError(t, ec.EnsureConfirmedTransactionsInLongestChain(tests.Context(t), head)) + + etx, err := txStore.FindTxWithAttempts(ctx, etx.ID) + require.NoError(t, err) + assert.Equal(t, txmgrcommon.TxUnconfirmed, etx.State) + require.Len(t, etx.TxAttempts, 1) + attempt = etx.TxAttempts[0] + assert.Equal(t, txmgrtypes.TxAttemptBroadcast, attempt.State) + }) + + t.Run("unconfirms and rebroadcasts transactions that have receipts within head height of chain but not included in the chain even if a receipt exists older than the start of the chain", func(t *testing.T) { + etx := cltest.MustInsertConfirmedEthTxWithLegacyAttempt(t, txStore, 5, 1, fromAddress) + attempt := etx.TxAttempts[0] + attemptHash := attempt.Hash + // Add receipt that is older than the lowest block of the chain + mustInsertEthReceipt(t, txStore, h8.Number-1, testutils.NewHash(), attemptHash) + // Include one within head height but a different block hash + mustInsertEthReceipt(t, txStore, head.Parent.Load().Number, testutils.NewHash(), attemptHash) + + ethClient.On("SendTransactionReturnCode", mock.Anything, mock.Anything, fromAddress).Return( + commonclient.Successful, nil).Once() + + // Do the thing + require.NoError(t, ec.EnsureConfirmedTransactionsInLongestChain(tests.Context(t), head)) + + etx, err := txStore.FindTxWithAttempts(ctx, etx.ID) + require.NoError(t, err) + assert.Equal(t, txmgrcommon.TxUnconfirmed, etx.State) + require.Len(t, etx.TxAttempts, 1) + attempt = etx.TxAttempts[0] + assert.Equal(t, txmgrtypes.TxAttemptBroadcast, attempt.State) + }) + + t.Run("if more than one attempt has a receipt (should not be possible but isn't prevented by database constraints) unconfirms and rebroadcasts only the attempt with the highest gas price", func(t *testing.T) { + etx := cltest.MustInsertConfirmedEthTxWithLegacyAttempt(t, txStore, 6, 1, fromAddress) + require.Len(t, etx.TxAttempts, 1) + // Sanity check to assert the included attempt has the lowest gas price + require.Less(t, etx.TxAttempts[0].TxFee.GasPrice.ToInt().Int64(), int64(30000)) + + attempt2 := newBroadcastLegacyEthTxAttempt(t, etx.ID, 30000) + attempt2.SignedRawTx = hexutil.MustDecode("0xf88c8301f3a98503b9aca000832ab98094f5fff180082d6017036b771ba883025c654bc93580a4daa6d556000000000000000000000000000000000000000000000000000000000000000026a0f25601065ee369b6470c0399a2334afcfbeb0b5c8f3d9a9042e448ed29b5bcbda05b676e00248b85faf4dd889f0e2dcf91eb867e23ac9eeb14a73f9e4c14972cdf") + attempt3 := newBroadcastLegacyEthTxAttempt(t, etx.ID, 40000) + attempt3.SignedRawTx = hexutil.MustDecode("0xf88c8301f3a88503b9aca0008316e36094151445852b0cfdf6a4cc81440f2af99176e8ad0880a4daa6d556000000000000000000000000000000000000000000000000000000000000000026a0dcb5a7ad52b96a866257134429f944c505820716567f070e64abb74899803855a04c13eff2a22c218e68da80111e1bb6dc665d3dea7104ab40ff8a0275a99f630d") + require.NoError(t, txStore.InsertTxAttempt(ctx, &attempt2)) + require.NoError(t, txStore.InsertTxAttempt(ctx, &attempt3)) + + // Receipt is within head height but a different block hash + mustInsertEthReceipt(t, txStore, head.Parent.Load().Number, testutils.NewHash(), attempt2.Hash) + // Receipt is within head height but a different block hash + mustInsertEthReceipt(t, txStore, head.Parent.Load().Number, testutils.NewHash(), attempt3.Hash) + + ethClient.On("SendTransactionReturnCode", mock.Anything, mock.MatchedBy(func(tx *types.Transaction) bool { + s, err := txmgr.GetGethSignedTx(attempt3.SignedRawTx) + require.NoError(t, err) + return tx.Hash() == s.Hash() + }), fromAddress).Return(commonclient.Successful, nil).Once() + + // Do the thing + require.NoError(t, ec.EnsureConfirmedTransactionsInLongestChain(tests.Context(t), head)) + + etx, err := txStore.FindTxWithAttempts(ctx, etx.ID) + require.NoError(t, err) + assert.Equal(t, txmgrcommon.TxUnconfirmed, etx.State) + require.Len(t, etx.TxAttempts, 3) + attempt1 := etx.TxAttempts[0] + assert.Equal(t, txmgrtypes.TxAttemptBroadcast, attempt1.State) + attempt2 = etx.TxAttempts[1] + assert.Equal(t, txmgrtypes.TxAttemptBroadcast, attempt2.State) + attempt3 = etx.TxAttempts[2] + assert.Equal(t, txmgrtypes.TxAttemptBroadcast, attempt3.State) + }) + + t.Run("if receipt has a block number that is in the future, does not mark for rebroadcast (the safe thing to do is simply wait until heads catches up)", func(t *testing.T) { + etx := cltest.MustInsertConfirmedEthTxWithLegacyAttempt(t, txStore, 7, 1, fromAddress) + attempt := etx.TxAttempts[0] + // Add receipt that is higher than head + mustInsertEthReceipt(t, txStore, head.Number+1, testutils.NewHash(), attempt.Hash) + + require.NoError(t, ec.EnsureConfirmedTransactionsInLongestChain(tests.Context(t), head)) + + etx, err := txStore.FindTxWithAttempts(ctx, etx.ID) + require.NoError(t, err) + assert.Equal(t, txmgrcommon.TxConfirmed, etx.State) + require.Len(t, etx.TxAttempts, 1) + attempt = etx.TxAttempts[0] + assert.Equal(t, txmgrtypes.TxAttemptBroadcast, attempt.State) + assert.Len(t, attempt.Receipts, 1) + }) +} + func TestEthConfirmer_ForceRebroadcast(t *testing.T) { t.Parallel() @@ -1694,6 +3000,203 @@ func TestEthConfirmer_ForceRebroadcast(t *testing.T) { }) } +func TestEthConfirmer_ResumePendingRuns(t *testing.T) { + t.Parallel() + + db := pgtest.NewSqlxDB(t) + config := configtest.NewTestGeneralConfig(t) + txStore := cltest.NewTestTxStore(t, db) + + ethKeyStore := cltest.NewKeyStore(t, db).Eth() + + _, fromAddress := cltest.MustInsertRandomKey(t, ethKeyStore) + + ethClient := testutils.NewEthClientMockWithDefaultChain(t) + + evmcfg := evmtest.NewChainScopedConfig(t, config) + + h8 := &evmtypes.Head{ + Number: 8, + Hash: testutils.NewHash(), + } + h9 := &evmtypes.Head{ + Hash: testutils.NewHash(), + Number: 9, + } + h9.Parent.Store(h8) + head := evmtypes.Head{ + Hash: testutils.NewHash(), + Number: 10, + } + head.Parent.Store(h9) + + minConfirmations := int64(2) + + pgtest.MustExec(t, db, `SET CONSTRAINTS fk_pipeline_runs_pruning_key DEFERRED`) + pgtest.MustExec(t, db, `SET CONSTRAINTS pipeline_runs_pipeline_spec_id_fkey DEFERRED`) + + t.Run("doesn't process task runs that are not suspended (possibly already previously resumed)", func(t *testing.T) { + ec := newEthConfirmer(t, txStore, ethClient, config, evmcfg, ethKeyStore, func(context.Context, uuid.UUID, interface{}, error) error { + t.Fatal("No value expected") + return nil + }) + + run := cltest.MustInsertPipelineRun(t, db) + tr := cltest.MustInsertUnfinishedPipelineTaskRun(t, db, run.ID) + + etx := cltest.MustInsertConfirmedEthTxWithLegacyAttempt(t, txStore, 1, 1, fromAddress) + mustInsertEthReceipt(t, txStore, head.Number-minConfirmations, head.Hash, etx.TxAttempts[0].Hash) + // Setting both signal_callback and callback_completed to TRUE to simulate a completed pipeline task + // It would only be in a state past suspended if the resume callback was called and callback_completed was set to TRUE + pgtest.MustExec(t, db, `UPDATE evm.txes SET pipeline_task_run_id = $1, min_confirmations = $2, signal_callback = TRUE, callback_completed = TRUE WHERE id = $3`, &tr.ID, minConfirmations, etx.ID) + + err := ec.ResumePendingTaskRuns(tests.Context(t), head.Number, 0) + require.NoError(t, err) + }) + + t.Run("doesn't process task runs where the receipt is younger than minConfirmations", func(t *testing.T) { + ec := newEthConfirmer(t, txStore, ethClient, config, evmcfg, ethKeyStore, func(context.Context, uuid.UUID, interface{}, error) error { + t.Fatal("No value expected") + return nil + }) + + run := cltest.MustInsertPipelineRun(t, db) + tr := cltest.MustInsertUnfinishedPipelineTaskRun(t, db, run.ID) + + etx := cltest.MustInsertConfirmedEthTxWithLegacyAttempt(t, txStore, 2, 1, fromAddress) + mustInsertEthReceipt(t, txStore, head.Number, head.Hash, etx.TxAttempts[0].Hash) + + pgtest.MustExec(t, db, `UPDATE evm.txes SET pipeline_task_run_id = $1, min_confirmations = $2, signal_callback = TRUE WHERE id = $3`, &tr.ID, minConfirmations, etx.ID) + + err := ec.ResumePendingTaskRuns(tests.Context(t), head.Number, 0) + require.NoError(t, err) + }) + + t.Run("processes eth_txes with receipts older than minConfirmations", func(t *testing.T) { + ch := make(chan interface{}) + nonce := evmtypes.Nonce(3) + var err error + ec := newEthConfirmer(t, txStore, ethClient, config, evmcfg, ethKeyStore, func(ctx context.Context, id uuid.UUID, value interface{}, thisErr error) error { + err = thisErr + ch <- value + return nil + }) + + run := cltest.MustInsertPipelineRun(t, db) + tr := cltest.MustInsertUnfinishedPipelineTaskRun(t, db, run.ID) + pgtest.MustExec(t, db, `UPDATE pipeline_runs SET state = 'suspended' WHERE id = $1`, run.ID) + + etx := cltest.MustInsertConfirmedEthTxWithLegacyAttempt(t, txStore, int64(nonce), 1, fromAddress) + pgtest.MustExec(t, db, `UPDATE evm.txes SET meta='{"FailOnRevert": true}'`) + receipt := mustInsertEthReceipt(t, txStore, head.Number-minConfirmations, head.Hash, etx.TxAttempts[0].Hash) + + pgtest.MustExec(t, db, `UPDATE evm.txes SET pipeline_task_run_id = $1, min_confirmations = $2, signal_callback = TRUE WHERE id = $3`, &tr.ID, minConfirmations, etx.ID) + + done := make(chan struct{}) + t.Cleanup(func() { <-done }) + go func() { + defer close(done) + err2 := ec.ResumePendingTaskRuns(tests.Context(t), head.Number, 0) + if !assert.NoError(t, err2) { + return + } + // Retrieve Tx to check if callback completed flag was set to true + updateTx, err3 := txStore.FindTxWithSequence(tests.Context(t), fromAddress, nonce) + if assert.NoError(t, err3) { + assert.Equal(t, true, updateTx.CallbackCompleted) + } + }() + + select { + case data := <-ch: + assert.NoError(t, err) + + require.IsType(t, &evmtypes.Receipt{}, data) + r := data.(*evmtypes.Receipt) + require.Equal(t, receipt.TxHash, r.TxHash) + + case <-time.After(time.Second): + t.Fatal("no value received") + } + }) + + pgtest.MustExec(t, db, `DELETE FROM pipeline_runs`) + + t.Run("processes eth_txes with receipt older than minConfirmations that reverted", func(t *testing.T) { + type data struct { + value any + error + } + ch := make(chan data) + nonce := evmtypes.Nonce(4) + ec := newEthConfirmer(t, txStore, ethClient, config, evmcfg, ethKeyStore, func(ctx context.Context, id uuid.UUID, value interface{}, err error) error { + ch <- data{value, err} + return nil + }) + + run := cltest.MustInsertPipelineRun(t, db) + tr := cltest.MustInsertUnfinishedPipelineTaskRun(t, db, run.ID) + pgtest.MustExec(t, db, `UPDATE pipeline_runs SET state = 'suspended' WHERE id = $1`, run.ID) + + etx := cltest.MustInsertConfirmedEthTxWithLegacyAttempt(t, txStore, int64(nonce), 1, fromAddress) + pgtest.MustExec(t, db, `UPDATE evm.txes SET meta='{"FailOnRevert": true}'`) + + // receipt is not passed through as a value since it reverted and caused an error + mustInsertRevertedEthReceipt(t, txStore, head.Number-minConfirmations, head.Hash, etx.TxAttempts[0].Hash) + + pgtest.MustExec(t, db, `UPDATE evm.txes SET pipeline_task_run_id = $1, min_confirmations = $2, signal_callback = TRUE WHERE id = $3`, &tr.ID, minConfirmations, etx.ID) + + done := make(chan struct{}) + t.Cleanup(func() { <-done }) + go func() { + defer close(done) + err2 := ec.ResumePendingTaskRuns(tests.Context(t), head.Number, 0) + if !assert.NoError(t, err2) { + return + } + // Retrieve Tx to check if callback completed flag was set to true + updateTx, err3 := txStore.FindTxWithSequence(tests.Context(t), fromAddress, nonce) + if assert.NoError(t, err3) { + assert.Equal(t, true, updateTx.CallbackCompleted) + } + }() + + select { + case data := <-ch: + assert.Error(t, data.error) + + assert.EqualError(t, data.error, fmt.Sprintf("transaction %s reverted on-chain", etx.TxAttempts[0].Hash.String())) + + assert.Nil(t, data.value) + + case <-time.After(tests.WaitTimeout(t)): + t.Fatal("no value received") + } + }) + + t.Run("does not mark callback complete if callback fails", func(t *testing.T) { + nonce := evmtypes.Nonce(5) + ec := newEthConfirmer(t, txStore, ethClient, config, evmcfg, ethKeyStore, func(context.Context, uuid.UUID, interface{}, error) error { + return errors.New("error") + }) + + run := cltest.MustInsertPipelineRun(t, db) + tr := cltest.MustInsertUnfinishedPipelineTaskRun(t, db, run.ID) + + etx := cltest.MustInsertConfirmedEthTxWithLegacyAttempt(t, txStore, int64(nonce), 1, fromAddress) + mustInsertEthReceipt(t, txStore, head.Number-minConfirmations, head.Hash, etx.TxAttempts[0].Hash) + pgtest.MustExec(t, db, `UPDATE evm.txes SET pipeline_task_run_id = $1, min_confirmations = $2, signal_callback = TRUE WHERE id = $3`, &tr.ID, minConfirmations, etx.ID) + + err := ec.ResumePendingTaskRuns(tests.Context(t), head.Number, 0) + require.Error(t, err) + + // Retrieve Tx to check if callback completed flag was left unchanged + updateTx, err := txStore.FindTxWithSequence(tests.Context(t), fromAddress, nonce) + require.NoError(t, err) + require.Equal(t, false, updateTx.CallbackCompleted) + }) +} + func TestEthConfirmer_ProcessStuckTransactions(t *testing.T) { t.Parallel() @@ -1727,7 +3230,7 @@ func TestEthConfirmer_ProcessStuckTransactions(t *testing.T) { txBuilder := txmgr.NewEvmTxAttemptBuilder(*ethClient.ConfiguredChainID(), ge, ethKeyStore, feeEstimator) stuckTxDetector := txmgr.NewStuckTxDetector(lggr, testutils.FixtureChainID, "", assets.NewWei(assets.NewEth(100).ToInt()), evmcfg.EVM().Transactions().AutoPurge(), feeEstimator, txStore, ethClient) ht := headtracker.NewSimulatedHeadTracker(ethClient, true, 0) - ec := txmgr.NewEvmConfirmer(txStore, txmgr.NewEvmTxmClient(ethClient, nil), txmgr.NewEvmTxmFeeConfig(ge), evmcfg.EVM().Transactions(), cfg.Database(), ethKeyStore, txBuilder, lggr, stuckTxDetector, ht) + ec := txmgr.NewEvmConfirmer(txStore, txmgr.NewEvmTxmClient(ethClient, nil), txmgr.NewEvmTxmConfig(evmcfg.EVM()), txmgr.NewEvmTxmFeeConfig(ge), evmcfg.EVM().Transactions(), cfg.Database(), ethKeyStore, txBuilder, lggr, stuckTxDetector, ht) fn := func(ctx context.Context, id uuid.UUID, result interface{}, err error) error { require.ErrorContains(t, err, client.TerminallyStuckMsg) return nil @@ -1752,8 +3255,10 @@ func TestEthConfirmer_ProcessStuckTransactions(t *testing.T) { } head.IsFinalized.Store(true) - // Mined tx count does not increment due to terminally stuck transaction + ethClient.On("HeadByNumber", mock.Anything, (*big.Int)(nil)).Return(&head, nil).Once() + ethClient.On("LatestFinalizedBlock", mock.Anything).Return(&head, nil).Once() ethClient.On("NonceAt", mock.Anything, mock.Anything, mock.Anything).Return(uint64(0), nil).Once() + ethClient.On("BatchCallContext", mock.Anything, mock.Anything).Return(nil).Once() // First call to ProcessHead should: // 1. Detect a stuck transaction @@ -1768,7 +3273,7 @@ func TestEthConfirmer_ProcessStuckTransactions(t *testing.T) { require.NoError(t, err) require.NotNil(t, dbTx) latestAttempt := dbTx.TxAttempts[0] - require.True(t, latestAttempt.IsPurgeAttempt) + require.Equal(t, true, latestAttempt.IsPurgeAttempt) require.Equal(t, limitDefault, latestAttempt.ChainSpecificFeeLimit) require.Equal(t, bumpedFee.GasPrice, latestAttempt.TxFee.GasPrice) @@ -1776,8 +3281,23 @@ func TestEthConfirmer_ProcessStuckTransactions(t *testing.T) { Hash: testutils.NewHash(), Number: blockNum + 1, } - // Mined tx count incremented because of purge attempt + head.IsFinalized.Store(true) + ethClient.On("HeadByNumber", mock.Anything, (*big.Int)(nil)).Return(&head, nil).Once() + ethClient.On("LatestFinalizedBlock", mock.Anything).Return(&head, nil).Once() ethClient.On("NonceAt", mock.Anything, mock.Anything, mock.Anything).Return(uint64(1), nil) + ethClient.On("BatchCallContext", mock.Anything, mock.MatchedBy(func(b []rpc.BatchElem) bool { + return len(b) == 4 && cltest.BatchElemMatchesParams(b[0], latestAttempt.Hash, "eth_getTransactionReceipt") + })).Return(nil).Run(func(args mock.Arguments) { + elems := args.Get(1).([]rpc.BatchElem) + // First transaction confirmed + *(elems[0].Result.(*evmtypes.Receipt)) = evmtypes.Receipt{ + TxHash: latestAttempt.Hash, + BlockHash: testutils.NewHash(), + BlockNumber: big.NewInt(blockNum + 1), + TransactionIndex: uint(1), + Status: uint64(1), + } + }).Once() // Second call to ProcessHead on next head should: // 1. Check for receipts for purged transaction @@ -1789,7 +3309,7 @@ func TestEthConfirmer_ProcessStuckTransactions(t *testing.T) { require.NotNil(t, dbTx) require.Equal(t, txmgrcommon.TxFatalError, dbTx.State) require.Equal(t, client.TerminallyStuckMsg, dbTx.Error.String) - require.True(t, dbTx.CallbackCompleted) + require.Equal(t, true, dbTx.CallbackCompleted) }) } @@ -1804,7 +3324,7 @@ func newEthConfirmer(t testing.TB, txStore txmgr.EvmTxStore, ethClient client.Cl txBuilder := txmgr.NewEvmTxAttemptBuilder(*ethClient.ConfiguredChainID(), ge, ks, estimator) stuckTxDetector := txmgr.NewStuckTxDetector(lggr, testutils.FixtureChainID, "", assets.NewWei(assets.NewEth(100).ToInt()), config.EVM().Transactions().AutoPurge(), estimator, txStore, ethClient) ht := headtracker.NewSimulatedHeadTracker(ethClient, true, 0) - ec := txmgr.NewEvmConfirmer(txStore, txmgr.NewEvmTxmClient(ethClient, nil), txmgr.NewEvmTxmFeeConfig(ge), config.EVM().Transactions(), gconfig.Database(), ks, txBuilder, lggr, stuckTxDetector, ht) + ec := txmgr.NewEvmConfirmer(txStore, txmgr.NewEvmTxmClient(ethClient, nil), txmgr.NewEvmTxmConfig(config.EVM()), txmgr.NewEvmTxmFeeConfig(ge), config.EVM().Transactions(), gconfig.Database(), ks, txBuilder, lggr, stuckTxDetector, ht) ec.SetResumeCallback(fn) servicetest.Run(t, ec) return ec diff --git a/core/chains/evm/txmgr/evm_tx_store.go b/core/chains/evm/txmgr/evm_tx_store.go index 95756790cf3..b75533e8d05 100644 --- a/core/chains/evm/txmgr/evm_tx_store.go +++ b/core/chains/evm/txmgr/evm_tx_store.go @@ -34,6 +34,9 @@ import ( var ( ErrKeyNotUpdated = errors.New("evmTxStore: Key not updated") + // ErrCouldNotGetReceipt is the error string we save if we reach our LatestFinalizedBlockNum for a confirmed transaction + // without ever getting a receipt. This most likely happened because an external wallet used the account for this nonce + ErrCouldNotGetReceipt = "could not get receipt" ) // EvmTxStore combines the txmgr tx store interface and the interface needed for the API to read from the tx DB @@ -43,13 +46,8 @@ type EvmTxStore interface { TxStoreWebApi // methods used solely in EVM components - DeleteReceiptByTxHash(ctx context.Context, txHash common.Hash) error - FindAttemptsRequiringReceiptFetch(ctx context.Context, chainID *big.Int) (hashes []TxAttempt, err error) - FindConfirmedTxesReceipts(ctx context.Context, finalizedBlockNum int64, chainID *big.Int) (receipts []*evmtypes.Receipt, err error) - FindTxesPendingCallback(ctx context.Context, latest, finalized int64, chainID *big.Int) (receiptsPlus []ReceiptPlus, err error) - FindTxesByIDs(ctx context.Context, etxIDs []int64, chainID *big.Int) (etxs []*Tx, err error) - SaveFetchedReceipts(ctx context.Context, r []*evmtypes.Receipt) (err error) - UpdateTxStatesToFinalizedUsingTxHashes(ctx context.Context, txHashes []common.Hash, chainID *big.Int) error + FindConfirmedTxesReceipts(ctx context.Context, finalizedBlockNum int64, chainID *big.Int) (receipts []Receipt, err error) + UpdateTxStatesToFinalizedUsingReceiptIds(ctx context.Context, etxIDs []int64, chainId *big.Int) error } // TxStoreWebApi encapsulates the methods that are not used by the txmgr and only used by the various web controllers, readers, or evm specific components @@ -846,6 +844,28 @@ func (o *evmTxStore) UpdateTxsUnconfirmed(ctx context.Context, ids []int64) erro return nil } +func (o *evmTxStore) FindTxAttemptsRequiringReceiptFetch(ctx context.Context, chainID *big.Int) (attempts []TxAttempt, err error) { + var cancel context.CancelFunc + ctx, cancel = o.stopCh.Ctx(ctx) + defer cancel() + err = o.Transact(ctx, true, func(orm *evmTxStore) error { + var dbAttempts []DbEthTxAttempt + err = orm.q.SelectContext(ctx, &dbAttempts, ` +SELECT evm.tx_attempts.* FROM evm.tx_attempts +JOIN evm.txes ON evm.txes.id = evm.tx_attempts.eth_tx_id AND evm.txes.state IN ('unconfirmed', 'confirmed_missing_receipt') AND evm.txes.evm_chain_id = $1 +WHERE evm.tx_attempts.state != 'insufficient_eth' +ORDER BY evm.txes.nonce ASC, evm.tx_attempts.gas_price DESC, evm.tx_attempts.gas_tip_cap DESC +`, chainID.String()) + if err != nil { + return pkgerrors.Wrap(err, "FindEthTxAttemptsRequiringReceiptFetch failed to load evm.tx_attempts") + } + attempts = dbEthTxAttemptsToEthTxAttempts(dbAttempts) + err = orm.preloadTxesAtomic(ctx, attempts) + return pkgerrors.Wrap(err, "FindEthTxAttemptsRequiringReceiptFetch failed to load evm.txes") + }) + return +} + // Returns the transaction by state and from addresses // Loads attempt and receipts in the transactions func (o *evmTxStore) FindTxsByStateAndFromAddresses(ctx context.Context, addresses []common.Address, state txmgrtypes.TxState, chainID *big.Int) (txs []*Tx, err error) { @@ -878,7 +898,7 @@ func (o *evmTxStore) FindTxsByStateAndFromAddresses(ctx context.Context, address return } -func (o *evmTxStore) SaveFetchedReceipts(ctx context.Context, r []*evmtypes.Receipt) (err error) { +func (o *evmTxStore) SaveFetchedReceipts(ctx context.Context, r []*evmtypes.Receipt, state txmgrtypes.TxState, errorMsg *string, chainID *big.Int) (err error) { var cancel context.CancelFunc ctx, cancel = o.stopCh.Ctx(ctx) defer cancel() @@ -925,6 +945,7 @@ func (o *evmTxStore) SaveFetchedReceipts(ctx context.Context, r []*evmtypes.Rece valueStrs = append(valueStrs, "(?,?,?,?,?,NOW())") valueArgs = append(valueArgs, r.TxHash, r.BlockHash, r.BlockNumber.Int64(), r.TransactionIndex, receiptJSON) } + valueArgs = append(valueArgs, state, errorMsg, chainID.String()) /* #nosec G201 */ sql := ` @@ -936,13 +957,21 @@ func (o *evmTxStore) SaveFetchedReceipts(ctx context.Context, r []*evmtypes.Rece transaction_index = EXCLUDED.transaction_index, receipt = EXCLUDED.receipt RETURNING evm.receipts.tx_hash, evm.receipts.block_number + ), + updated_eth_tx_attempts AS ( + UPDATE evm.tx_attempts + SET + state = 'broadcast', + broadcast_before_block_num = COALESCE(evm.tx_attempts.broadcast_before_block_num, inserted_receipts.block_number) + FROM inserted_receipts + WHERE inserted_receipts.tx_hash = evm.tx_attempts.hash + RETURNING evm.tx_attempts.eth_tx_id ) - UPDATE evm.tx_attempts - SET - state = 'broadcast', - broadcast_before_block_num = COALESCE(evm.tx_attempts.broadcast_before_block_num, inserted_receipts.block_number) - FROM inserted_receipts - WHERE inserted_receipts.tx_hash = evm.tx_attempts.hash + UPDATE evm.txes + SET state = ?, error = ? + FROM updated_eth_tx_attempts + WHERE updated_eth_tx_attempts.eth_tx_id = evm.txes.id + AND evm_chain_id = ? ` stmt := fmt.Sprintf(sql, strings.Join(valueStrs, ",")) @@ -953,6 +982,57 @@ func (o *evmTxStore) SaveFetchedReceipts(ctx context.Context, r []*evmtypes.Rece return pkgerrors.Wrap(err, "SaveFetchedReceipts failed to save receipts") } +// MarkAllConfirmedMissingReceipt +// It is possible that we can fail to get a receipt for all evm.tx_attempts +// even though a transaction with this nonce has long since been confirmed (we +// know this because transactions with higher nonces HAVE returned a receipt). +// +// This can probably only happen if an external wallet used the account (or +// conceivably because of some bug in the remote eth node that prevents it +// from returning a receipt for a valid transaction). +// +// In this case we mark these transactions as 'confirmed_missing_receipt' to +// prevent gas bumping. +// +// NOTE: We continue to attempt to resend evm.txes in this state on +// every head to guard against the extremely rare scenario of nonce gap due to +// reorg that excludes the transaction (from another wallet) that had this +// nonce (until LatestFinalizedBlockNum is reached, after which we make the explicit +// decision to give up). This is done in the EthResender. +// +// We will continue to try to fetch a receipt for these attempts until all +// attempts are equal to or below the LatestFinalizedBlockNum from current head. +func (o *evmTxStore) MarkAllConfirmedMissingReceipt(ctx context.Context, chainID *big.Int) (err error) { + var cancel context.CancelFunc + ctx, cancel = o.stopCh.Ctx(ctx) + defer cancel() + res, err := o.q.ExecContext(ctx, ` +UPDATE evm.txes +SET state = 'confirmed_missing_receipt' +FROM ( + SELECT from_address, MAX(nonce) as max_nonce + FROM evm.txes + WHERE state = 'confirmed' AND evm_chain_id = $1 + GROUP BY from_address +) AS max_table +WHERE state = 'unconfirmed' + AND evm_chain_id = $1 + AND nonce < max_table.max_nonce + AND evm.txes.from_address = max_table.from_address + `, chainID.String()) + if err != nil { + return pkgerrors.Wrap(err, "markAllConfirmedMissingReceipt failed") + } + rowsAffected, err := res.RowsAffected() + if err != nil { + return pkgerrors.Wrap(err, "markAllConfirmedMissingReceipt RowsAffected failed") + } + if rowsAffected > 0 { + o.logger.Infow(fmt.Sprintf("%d transactions missing receipt", rowsAffected), "n", rowsAffected) + } + return +} + func (o *evmTxStore) GetInProgressTxAttempts(ctx context.Context, address common.Address, chainID *big.Int) (attempts []TxAttempt, err error) { var cancel context.CancelFunc ctx, cancel = o.stopCh.Ctx(ctx) @@ -1000,23 +1080,23 @@ func (o *evmTxStore) FindTxesPendingCallback(ctx context.Context, latest, finali } // Update tx to mark that its callback has been signaled -func (o *evmTxStore) UpdateTxCallbackCompleted(ctx context.Context, pipelineTaskRunID uuid.UUID, chainID *big.Int) error { +func (o *evmTxStore) UpdateTxCallbackCompleted(ctx context.Context, pipelineTaskRunId uuid.UUID, chainId *big.Int) error { var cancel context.CancelFunc ctx, cancel = o.stopCh.Ctx(ctx) defer cancel() - _, err := o.q.ExecContext(ctx, `UPDATE evm.txes SET callback_completed = TRUE WHERE pipeline_task_run_id = $1 AND evm_chain_id = $2`, pipelineTaskRunID, chainID.String()) + _, err := o.q.ExecContext(ctx, `UPDATE evm.txes SET callback_completed = TRUE WHERE pipeline_task_run_id = $1 AND evm_chain_id = $2`, pipelineTaskRunId, chainId.String()) if err != nil { return fmt.Errorf("failed to mark callback completed for transaction: %w", err) } return nil } -func (o *evmTxStore) FindLatestSequence(ctx context.Context, fromAddress common.Address, chainID *big.Int) (nonce evmtypes.Nonce, err error) { +func (o *evmTxStore) FindLatestSequence(ctx context.Context, fromAddress common.Address, chainId *big.Int) (nonce evmtypes.Nonce, err error) { var cancel context.CancelFunc ctx, cancel = o.stopCh.Ctx(ctx) defer cancel() sql := `SELECT nonce FROM evm.txes WHERE from_address = $1 AND evm_chain_id = $2 AND nonce IS NOT NULL ORDER BY nonce DESC LIMIT 1` - err = o.q.GetContext(ctx, &nonce, sql, fromAddress, chainID.String()) + err = o.q.GetContext(ctx, &nonce, sql, fromAddress, chainId.String()) return } @@ -1072,47 +1152,74 @@ SELECT * FROM evm.txes WHERE from_address = $1 AND nonce = $2 AND state IN ('con return } -func updateEthTxAttemptsUnbroadcast(ctx context.Context, orm *evmTxStore, attemptIDs []int64) error { - _, err := orm.q.ExecContext(ctx, `UPDATE evm.tx_attempts SET broadcast_before_block_num = NULL, state = 'in_progress' WHERE id = ANY($1)`, pq.Array(attemptIDs)) - return err +func updateEthTxAttemptUnbroadcast(ctx context.Context, orm *evmTxStore, attempt TxAttempt) error { + if attempt.State != txmgrtypes.TxAttemptBroadcast { + return errors.New("expected eth_tx_attempt to be broadcast") + } + _, err := orm.q.ExecContext(ctx, `UPDATE evm.tx_attempts SET broadcast_before_block_num = NULL, state = 'in_progress' WHERE id = $1`, attempt.ID) + return pkgerrors.Wrap(err, "updateEthTxAttemptUnbroadcast failed") } -func updateEthTxsUnconfirm(ctx context.Context, orm *evmTxStore, etxIDs []int64) error { - _, err := orm.q.ExecContext(ctx, `UPDATE evm.txes SET state = 'unconfirmed', error = NULL WHERE id = ANY($1)`, pq.Array(etxIDs)) - return err +func updateEthTxUnconfirm(ctx context.Context, orm *evmTxStore, etx Tx) error { + if etx.State != txmgr.TxConfirmed { + return errors.New("expected tx state to be confirmed") + } + _, err := orm.q.ExecContext(ctx, `UPDATE evm.txes SET state = 'unconfirmed' WHERE id = $1`, etx.ID) + return pkgerrors.Wrap(err, "updateEthTxUnconfirm failed") } -func deleteEthReceipts(ctx context.Context, orm *evmTxStore, etxIDs []int64) (err error) { +func deleteEthReceipts(ctx context.Context, orm *evmTxStore, etxID int64) (err error) { _, err = orm.q.ExecContext(ctx, ` DELETE FROM evm.receipts USING evm.tx_attempts WHERE evm.receipts.tx_hash = evm.tx_attempts.hash -AND evm.tx_attempts.eth_tx_id = ANY($1) - `, pq.Array(etxIDs)) +AND evm.tx_attempts.eth_tx_id = $1 + `, etxID) return pkgerrors.Wrap(err, "deleteEthReceipts failed") } -func (o *evmTxStore) DeleteReceiptByTxHash(ctx context.Context, txHash common.Hash) error { +func (o *evmTxStore) UpdateTxForRebroadcast(ctx context.Context, etx Tx, etxAttempt TxAttempt) error { var cancel context.CancelFunc ctx, cancel = o.stopCh.Ctx(ctx) defer cancel() - _, err := o.q.ExecContext(ctx, `DELETE FROM evm.receipts WHERE tx_hash = $1`, txHash) - return err + return o.Transact(ctx, false, func(orm *evmTxStore) error { + if err := deleteEthReceipts(ctx, orm, etx.ID); err != nil { + return pkgerrors.Wrapf(err, "deleteEthReceipts failed for etx %v", etx.ID) + } + if err := updateEthTxUnconfirm(ctx, orm, etx); err != nil { + return pkgerrors.Wrapf(err, "updateEthTxUnconfirm failed for etx %v", etx.ID) + } + return updateEthTxAttemptUnbroadcast(ctx, orm, etxAttempt) + }) } -func (o *evmTxStore) UpdateTxsForRebroadcast(ctx context.Context, etxIDs []int64, attemptIDs []int64) error { +func (o *evmTxStore) FindTransactionsConfirmedInBlockRange(ctx context.Context, highBlockNumber, lowBlockNumber int64, chainID *big.Int) (etxs []*Tx, err error) { var cancel context.CancelFunc ctx, cancel = o.stopCh.Ctx(ctx) defer cancel() - return o.Transact(ctx, false, func(orm *evmTxStore) error { - if err := deleteEthReceipts(ctx, orm, etxIDs); err != nil { - return pkgerrors.Wrapf(err, "deleteEthReceipts failed for etx %v", etxIDs) + err = o.Transact(ctx, true, func(orm *evmTxStore) error { + var dbEtxs []DbEthTx + err = orm.q.SelectContext(ctx, &dbEtxs, ` +SELECT DISTINCT evm.txes.* FROM evm.txes +INNER JOIN evm.tx_attempts ON evm.txes.id = evm.tx_attempts.eth_tx_id AND evm.tx_attempts.state = 'broadcast' +INNER JOIN evm.receipts ON evm.receipts.tx_hash = evm.tx_attempts.hash +WHERE evm.txes.state IN ('confirmed', 'confirmed_missing_receipt') AND block_number BETWEEN $1 AND $2 AND evm_chain_id = $3 +ORDER BY nonce ASC +`, lowBlockNumber, highBlockNumber, chainID.String()) + if err != nil { + return pkgerrors.Wrap(err, "FindTransactionsConfirmedInBlockRange failed to load evm.txes") } - if err := updateEthTxsUnconfirm(ctx, orm, etxIDs); err != nil { - return pkgerrors.Wrapf(err, "updateEthTxUnconfirm failed for etx %v", etxIDs) + etxs = make([]*Tx, len(dbEtxs)) + dbEthTxsToEvmEthTxPtrs(dbEtxs, etxs) + if err = orm.LoadTxesAttempts(ctx, etxs); err != nil { + return pkgerrors.Wrap(err, "FindTransactionsConfirmedInBlockRange failed to load evm.tx_attempts") } - return updateEthTxAttemptsUnbroadcast(ctx, orm, attemptIDs) + + // retrieve tx with attempts and partial receipt values for optimization purpose + err = orm.loadEthTxesAttemptsWithPartialReceipts(ctx, etxs) + return pkgerrors.Wrap(err, "FindTransactionsConfirmedInBlockRange failed to load evm.receipts") }) + return etxs, pkgerrors.Wrap(err, "FindTransactionsConfirmedInBlockRange failed") } func (o *evmTxStore) FindEarliestUnconfirmedBroadcastTime(ctx context.Context, chainID *big.Int) (broadcastAt nullv4.Time, err error) { @@ -1191,7 +1298,7 @@ func (o *evmTxStore) SaveSentAttempt(ctx context.Context, timeout time.Duration, return o.saveSentAttempt(ctx, timeout, attempt, broadcastAt) } -func (o *evmTxStore) SaveConfirmedAttempt(ctx context.Context, timeout time.Duration, attempt *TxAttempt, broadcastAt time.Time) error { +func (o *evmTxStore) SaveConfirmedMissingReceiptAttempt(ctx context.Context, timeout time.Duration, attempt *TxAttempt, broadcastAt time.Time) error { var cancel context.CancelFunc ctx, cancel = o.stopCh.Ctx(ctx) defer cancel() @@ -1199,12 +1306,12 @@ func (o *evmTxStore) SaveConfirmedAttempt(ctx context.Context, timeout time.Dura if err := orm.saveSentAttempt(ctx, timeout, attempt, broadcastAt); err != nil { return err } - if _, err := orm.q.ExecContext(ctx, `UPDATE evm.txes SET state = 'confirmed' WHERE id = $1`, attempt.TxID); err != nil { + if _, err := orm.q.ExecContext(ctx, `UPDATE evm.txes SET state = 'confirmed_missing_receipt' WHERE id = $1`, attempt.TxID); err != nil { return pkgerrors.Wrap(err, "failed to update evm.txes") } return nil }) - return pkgerrors.Wrap(err, "SaveConfirmedAttempt failed") + return pkgerrors.Wrap(err, "SaveConfirmedMissingReceiptAttempt failed") } func (o *evmTxStore) DeleteInProgressAttempt(ctx context.Context, attempt TxAttempt) error { @@ -1365,6 +1472,101 @@ ORDER BY nonce ASC return } +// markOldTxesMissingReceiptAsErrored +// +// Once eth_tx has all of its attempts broadcast equal to or before latestFinalizedBlockNum +// without receiving any receipts, we mark it as fatally errored (never sent). +// +// The job run will also be marked as errored in this case since we never got a +// receipt and thus cannot pass on any transaction hash +func (o *evmTxStore) MarkOldTxesMissingReceiptAsErrored(ctx context.Context, blockNum int64, latestFinalizedBlockNum int64, chainID *big.Int) error { + var cancel context.CancelFunc + ctx, cancel = o.stopCh.Ctx(ctx) + defer cancel() + // Any 'confirmed_missing_receipt' eth_tx with all attempts equal to or older than latestFinalizedBlockNum will be marked as errored + // We will not try to query for receipts for this transaction anymore + if latestFinalizedBlockNum <= 0 { + return nil + } + // note: if QOpt passes in a sql.Tx this will reuse it + return o.Transact(ctx, false, func(orm *evmTxStore) error { + type etx struct { + ID int64 + Nonce int64 + } + var data []etx + err := orm.q.SelectContext(ctx, &data, ` +UPDATE evm.txes +SET state='fatal_error', nonce=NULL, error=$1, broadcast_at=NULL, initial_broadcast_at=NULL +FROM ( + SELECT e1.id, e1.nonce, e1.from_address FROM evm.txes AS e1 WHERE id IN ( + SELECT e2.id FROM evm.txes AS e2 + INNER JOIN evm.tx_attempts ON e2.id = evm.tx_attempts.eth_tx_id + WHERE e2.state = 'confirmed_missing_receipt' + AND e2.evm_chain_id = $3 + GROUP BY e2.id + HAVING max(evm.tx_attempts.broadcast_before_block_num) <= $2 + ) + FOR UPDATE OF e1 +) e0 +WHERE e0.id = evm.txes.id +RETURNING e0.id, e0.nonce`, ErrCouldNotGetReceipt, latestFinalizedBlockNum, chainID.String()) + + if err != nil { + return pkgerrors.Wrap(err, "markOldTxesMissingReceiptAsErrored failed to query") + } + + // We need this little lookup table because we have to have the nonce + // from the first query, BEFORE it was updated/nullified + lookup := make(map[int64]etx) + for _, d := range data { + lookup[d.ID] = d + } + etxIDs := make([]int64, len(data)) + for i := 0; i < len(data); i++ { + etxIDs[i] = data[i].ID + } + + type result struct { + ID int64 + FromAddress common.Address + MaxBroadcastBeforeBlockNum int64 + TxHashes pq.ByteaArray + } + + var results []result + err = orm.q.SelectContext(ctx, &results, ` +SELECT e.id, e.from_address, max(a.broadcast_before_block_num) AS max_broadcast_before_block_num, array_agg(a.hash) AS tx_hashes +FROM evm.txes e +INNER JOIN evm.tx_attempts a ON e.id = a.eth_tx_id +WHERE e.id = ANY($1) +GROUP BY e.id +`, etxIDs) + + if err != nil { + return pkgerrors.Wrap(err, "markOldTxesMissingReceiptAsErrored failed to load additional data") + } + + for _, r := range results { + nonce := lookup[r.ID].Nonce + txHashesHex := make([]common.Address, len(r.TxHashes)) + for i := 0; i < len(r.TxHashes); i++ { + txHashesHex[i] = common.BytesToAddress(r.TxHashes[i]) + } + + orm.logger.Criticalw(fmt.Sprintf("eth_tx with ID %v expired without ever getting a receipt for any of our attempts. "+ + "Current block height is %v, transaction was broadcast before block height %v. This transaction may not have not been sent and will be marked as fatally errored. "+ + "This can happen if there is another instance of chainlink running that is using the same private key, or if "+ + "an external wallet has been used to send a transaction from account %s with nonce %v."+ + " Please note that Chainlink requires exclusive ownership of it's private keys and sharing keys across multiple"+ + " chainlink instances, or using the chainlink keys with an external wallet is NOT SUPPORTED and WILL lead to missed transactions", + r.ID, blockNum, r.MaxBroadcastBeforeBlockNum, r.FromAddress, nonce), "ethTxID", r.ID, "nonce", nonce, "fromAddress", r.FromAddress, "txHashes", txHashesHex) + } + + return nil + }) +} + func (o *evmTxStore) SaveReplacementInProgressAttempt(ctx context.Context, oldAttempt TxAttempt, replacementAttempt *TxAttempt) error { var cancel context.CancelFunc ctx, cancel = o.stopCh.Ctx(ctx) @@ -1407,10 +1609,13 @@ func (o *evmTxStore) FindNextUnstartedTransactionFromAddress(ctx context.Context return etx, nil } -func (o *evmTxStore) UpdateTxFatalErrorAndDeleteAttempts(ctx context.Context, etx *Tx) error { +func (o *evmTxStore) UpdateTxFatalError(ctx context.Context, etx *Tx) error { var cancel context.CancelFunc ctx, cancel = o.stopCh.Ctx(ctx) defer cancel() + if etx.State != txmgr.TxInProgress && etx.State != txmgr.TxUnstarted { + return pkgerrors.Errorf("can only transition to fatal_error from in_progress or unstarted, transaction is currently %s", etx.State) + } if !etx.Error.Valid { return errors.New("expected error field to be set") } @@ -1907,147 +2112,35 @@ func (o *evmTxStore) UpdateTxAttemptBroadcastBeforeBlockNum(ctx context.Context, return err } -// FindAttemptsRequiringReceiptFetch returns all broadcasted attempts for confirmed or terminally stuck transactions that do not have receipts stored in the DB -func (o *evmTxStore) FindAttemptsRequiringReceiptFetch(ctx context.Context, chainID *big.Int) (attempts []TxAttempt, err error) { - var cancel context.CancelFunc - ctx, cancel = o.stopCh.Ctx(ctx) - defer cancel() - var dbTxAttempts []DbEthTxAttempt - query := ` - SELECT evm.tx_attempts.* FROM evm.tx_attempts - JOIN evm.txes ON evm.txes.ID = evm.tx_attempts.eth_tx_id - WHERE evm.tx_attempts.state = 'broadcast' AND evm.txes.state IN ('confirmed', 'confirmed_missing_receipt', 'fatal_error') AND evm.txes.evm_chain_id = $1 AND evm.txes.ID NOT IN ( - SELECT DISTINCT evm.txes.ID FROM evm.txes - JOIN evm.tx_attempts ON evm.tx_attempts.eth_tx_id = evm.txes.ID - JOIN evm.receipts ON evm.receipts.tx_hash = evm.tx_attempts.hash - WHERE evm.txes.evm_chain_id = $1 AND evm.txes.state IN ('confirmed', 'confirmed_missing_receipt', 'fatal_error') AND evm.receipts.ID IS NOT NULL - ) - ORDER BY evm.txes.nonce ASC, evm.tx_attempts.gas_price DESC, evm.tx_attempts.gas_tip_cap DESC - ` - err = o.q.SelectContext(ctx, &dbTxAttempts, query, chainID.String()) - attempts = dbEthTxAttemptsToEthTxAttempts(dbTxAttempts) - return attempts, err -} - -// FindConfirmedTxesReceipts returns all confirmed transactions with receipt block nums older than or equal to the finalized block number -func (o *evmTxStore) FindConfirmedTxesReceipts(ctx context.Context, finalizedBlockNum int64, chainID *big.Int) (receipts []*evmtypes.Receipt, err error) { +// FindConfirmedTxesReceipts Returns all confirmed transactions with receipt block nums older than or equal to the finalized block number +func (o *evmTxStore) FindConfirmedTxesReceipts(ctx context.Context, finalizedBlockNum int64, chainID *big.Int) (receipts []Receipt, err error) { var cancel context.CancelFunc ctx, cancel = o.stopCh.Ctx(ctx) defer cancel() - var dbReceipts []Receipt // note the receipts are partially loaded for performance reason - query := `SELECT evm.receipts.tx_hash, evm.receipts.block_hash, evm.receipts.block_number FROM evm.receipts + query := `SELECT evm.receipts.id, evm.receipts.tx_hash, evm.receipts.block_hash, evm.receipts.block_number FROM evm.receipts INNER JOIN evm.tx_attempts ON evm.tx_attempts.hash = evm.receipts.tx_hash INNER JOIN evm.txes ON evm.txes.id = evm.tx_attempts.eth_tx_id WHERE evm.txes.state = 'confirmed' AND evm.receipts.block_number <= $1 AND evm.txes.evm_chain_id = $2` - err = o.q.SelectContext(ctx, &dbReceipts, query, finalizedBlockNum, chainID.String()) - for _, dbReceipt := range dbReceipts { - receipts = append(receipts, &evmtypes.Receipt{ - TxHash: dbReceipt.TxHash, - BlockHash: dbReceipt.BlockHash, - BlockNumber: big.NewInt(dbReceipt.BlockNumber), - }) - } + err = o.q.SelectContext(ctx, &receipts, query, finalizedBlockNum, chainID.String()) return receipts, err } -// Mark transactions corresponding to attempt hashes as finalized -func (o *evmTxStore) UpdateTxStatesToFinalizedUsingTxHashes(ctx context.Context, txHashes []common.Hash, chainID *big.Int) error { - if len(txHashes) == 0 { +// Mark transactions corresponding to receipt IDs as finalized +func (o *evmTxStore) UpdateTxStatesToFinalizedUsingReceiptIds(ctx context.Context, receiptIDs []int64, chainId *big.Int) error { + if len(receiptIDs) == 0 { return nil } - txHashBytea := make([][]byte, len(txHashes)) - for i, hash := range txHashes { - txHashBytea[i] = hash.Bytes() - } var cancel context.CancelFunc ctx, cancel = o.stopCh.Ctx(ctx) defer cancel() sql := ` UPDATE evm.txes SET state = 'finalized' WHERE evm.txes.evm_chain_id = $1 AND evm.txes.id IN (SELECT evm.txes.id FROM evm.txes INNER JOIN evm.tx_attempts ON evm.tx_attempts.eth_tx_id = evm.txes.id - WHERE evm.tx_attempts.hash = ANY($2)) + INNER JOIN evm.receipts ON evm.receipts.tx_hash = evm.tx_attempts.hash + WHERE evm.receipts.id = ANY($2)) ` - _, err := o.q.ExecContext(ctx, sql, chainID.String(), txHashBytea) + _, err := o.q.ExecContext(ctx, sql, chainId.String(), pq.Array(receiptIDs)) return err } - -// FindReorgOrIncludedTxs finds transactions that have either been re-org'd or included on-chain based on the mined transaction count -// If the mined transaction count receeds, transactions could have beeen re-org'd -// If it proceeds, transactions could have been included -// This check assumes transactions are broadcasted in ascending order and not out of order -func (o *evmTxStore) FindReorgOrIncludedTxs(ctx context.Context, fromAddress common.Address, minedTxCount evmtypes.Nonce, chainID *big.Int) (reorgTxs []*Tx, includedTxs []*Tx, err error) { - var cancel context.CancelFunc - ctx, cancel = o.stopCh.Ctx(ctx) - defer cancel() - err = o.Transact(ctx, true, func(orm *evmTxStore) error { - var dbReOrgEtxs []DbEthTx - query := `SELECT * FROM evm.txes WHERE from_address = $1 AND state IN ('confirmed', 'confirmed_missing_receipt', 'fatal_error', 'finalized') AND nonce >= $2 AND evm_chain_id = $3` - err = o.q.SelectContext(ctx, &dbReOrgEtxs, query, fromAddress, minedTxCount.Int64(), chainID.String()) - // If re-org'd transactions found, populate them with attempts and partial receipts, then return since new transactions could not have been included - if len(dbReOrgEtxs) > 0 { - reorgTxs = make([]*Tx, len(dbReOrgEtxs)) - dbEthTxsToEvmEthTxPtrs(dbReOrgEtxs, reorgTxs) - if err = orm.LoadTxesAttempts(ctx, reorgTxs); err != nil { - return fmt.Errorf("failed to load evm.tx_attempts: %w", err) - } - // retrieve tx with attempts and partial receipt values for optimization purpose - if err = orm.loadEthTxesAttemptsWithPartialReceipts(ctx, reorgTxs); err != nil { - return fmt.Errorf("failed to load partial evm.receipts: %w", err) - } - return nil - } - // If re-org'd transactions not found, find unconfirmed transactions could have been included and populate with attempts - var dbIncludedEtxs []DbEthTx - query = `SELECT * FROM evm.txes WHERE state = 'unconfirmed' AND from_address = $1 AND nonce < $2 AND evm_chain_id = $3` - err = o.q.SelectContext(ctx, &dbIncludedEtxs, query, fromAddress, minedTxCount.Int64(), chainID.String()) - includedTxs = make([]*Tx, len(dbIncludedEtxs)) - dbEthTxsToEvmEthTxPtrs(dbIncludedEtxs, includedTxs) - if err = orm.LoadTxesAttempts(ctx, includedTxs); err != nil { - return fmt.Errorf("failed to load evm.tx_attempts: %w", err) - } - return nil - }) - return -} - -func (o *evmTxStore) UpdateTxConfirmed(ctx context.Context, etxIDs []int64) error { - var cancel context.CancelFunc - ctx, cancel = o.stopCh.Ctx(ctx) - defer cancel() - err := o.Transact(ctx, true, func(orm *evmTxStore) error { - sql := `UPDATE evm.txes SET state = 'confirmed' WHERE id = ANY($1)` - _, err := o.q.ExecContext(ctx, sql, pq.Array(etxIDs)) - if err != nil { - return err - } - sql = `UPDATE evm.tx_attempts SET state = 'broadcast' WHERE state = 'in_progress' AND eth_tx_id = ANY($1)` - _, err = o.q.ExecContext(ctx, sql, pq.Array(etxIDs)) - return err - }) - return err -} - -func (o *evmTxStore) UpdateTxFatalError(ctx context.Context, etxIDs []int64, errMsg string) error { - var cancel context.CancelFunc - ctx, cancel = o.stopCh.Ctx(ctx) - defer cancel() - sql := `UPDATE evm.txes SET state = 'fatal_error', error = $1 WHERE id = ANY($2)` - _, err := o.q.ExecContext(ctx, sql, errMsg, pq.Array(etxIDs)) - return err -} - -func (o *evmTxStore) FindTxesByIDs(ctx context.Context, etxIDs []int64, chainID *big.Int) (etxs []*Tx, err error) { - var cancel context.CancelFunc - ctx, cancel = o.stopCh.Ctx(ctx) - defer cancel() - var dbEtxs []DbEthTx - sql := `SELECT * FROM evm.txes WHERE id = ANY($1) AND evm_chain_id = $2 ORDER BY created_at ASC, id ASC` - if err = o.q.SelectContext(ctx, &dbEtxs, sql, pq.Array(etxIDs), chainID.String()); err != nil { - return nil, fmt.Errorf("failed to find evm.tx: %w", err) - } - etxs = make([]*Tx, len(dbEtxs)) - dbEthTxsToEvmEthTxPtrs(dbEtxs, etxs) - return -} diff --git a/core/chains/evm/txmgr/evm_tx_store_test.go b/core/chains/evm/txmgr/evm_tx_store_test.go index a05cf3f9010..9e1f135e0b2 100644 --- a/core/chains/evm/txmgr/evm_tx_store_test.go +++ b/core/chains/evm/txmgr/evm_tx_store_test.go @@ -21,7 +21,6 @@ import ( txmgrcommon "github.com/smartcontractkit/chainlink/v2/common/txmgr" txmgrtypes "github.com/smartcontractkit/chainlink/v2/common/txmgr/types" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" - "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/gas" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/testutils" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr" @@ -113,8 +112,8 @@ func TestORM_Transactions(t *testing.T) { assert.Len(t, txs, 2) assert.Equal(t, evmtypes.Nonce(1), *txs[0].Sequence, "transactions should be sorted by nonce") assert.Equal(t, evmtypes.Nonce(0), *txs[1].Sequence, "transactions should be sorted by nonce") - assert.Empty(t, txs[0].TxAttempts, "eth tx attempts should not be preloaded") - assert.Empty(t, txs[1].TxAttempts) + assert.Len(t, txs[0].TxAttempts, 0, "eth tx attempts should not be preloaded") + assert.Len(t, txs[1].TxAttempts, 0) } func TestORM(t *testing.T) { @@ -165,7 +164,7 @@ func TestORM(t *testing.T) { assert.Equal(t, etx.TxAttempts[0].ID, attemptD.ID) assert.Equal(t, etx.TxAttempts[1].ID, attemptL.ID) require.Len(t, etx.TxAttempts[0].Receipts, 1) - require.Empty(t, etx.TxAttempts[1].Receipts) + require.Len(t, etx.TxAttempts[1].Receipts, 0) assert.Equal(t, r.BlockHash, etx.TxAttempts[0].Receipts[0].GetBlockHash()) }) t.Run("FindTxByHash", func(t *testing.T) { @@ -181,7 +180,7 @@ func TestORM(t *testing.T) { assert.Equal(t, etx.TxAttempts[0].ID, attemptD.ID) assert.Equal(t, etx.TxAttempts[1].ID, attemptL.ID) require.Len(t, etx.TxAttempts[0].Receipts, 1) - require.Empty(t, etx.TxAttempts[1].Receipts) + require.Len(t, etx.TxAttempts[1].Receipts, 0) assert.Equal(t, r.BlockHash, etx.TxAttempts[0].Receipts[0].GetBlockHash()) }) } @@ -249,7 +248,7 @@ func TestORM_FindTxAttemptsRequiringResend(t *testing.T) { olderThan := time.Now() attempts, err := txStore.FindTxAttemptsRequiringResend(tests.Context(t), olderThan, 10, testutils.FixtureChainID, fromAddress) require.NoError(t, err) - assert.Empty(t, attempts) + assert.Len(t, attempts, 0) }) // Mix up the insert order to assure that they come out sorted by nonce not implicitly or by ID @@ -292,7 +291,7 @@ func TestORM_FindTxAttemptsRequiringResend(t *testing.T) { olderThan := time.Now() attempts, err := txStore.FindTxAttemptsRequiringResend(tests.Context(t), olderThan, 10, testutils.FixtureChainID, utils.RandomAddress()) require.NoError(t, err) - assert.Empty(t, attempts) + assert.Len(t, attempts, 0) }) t.Run("returns the highest price attempt for each transaction that was last broadcast before or on the given time", func(t *testing.T) { @@ -438,32 +437,66 @@ func TestORM_SetBroadcastBeforeBlockNum(t *testing.T) { }) } -func TestORM_UpdateTxConfirmed(t *testing.T) { +func TestORM_FindTxAttemptsConfirmedMissingReceipt(t *testing.T) { t.Parallel() - ctx := tests.Context(t) db := pgtest.NewSqlxDB(t) txStore := cltest.NewTestTxStore(t, db) ethKeyStore := cltest.NewKeyStore(t, db).Eth() + ethClient := evmtest.NewEthClientMockWithDefaultChain(t) _, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore) - etx0 := mustInsertUnconfirmedEthTxWithAttemptState(t, txStore, 0, fromAddress, txmgrtypes.TxAttemptBroadcast) - etx1 := mustInsertUnconfirmedEthTxWithAttemptState(t, txStore, 1, fromAddress, txmgrtypes.TxAttemptInProgress) - assert.Equal(t, txmgrcommon.TxUnconfirmed, etx0.State) - assert.Equal(t, txmgrcommon.TxUnconfirmed, etx1.State) - require.NoError(t, txStore.UpdateTxConfirmed(tests.Context(t), []int64{etx0.ID, etx1.ID})) + originalBroadcastAt := time.Unix(1616509100, 0) + etx0 := mustInsertConfirmedMissingReceiptEthTxWithLegacyAttempt( + t, txStore, 0, 1, originalBroadcastAt, fromAddress) + + attempts, err := txStore.FindTxAttemptsConfirmedMissingReceipt(tests.Context(t), ethClient.ConfiguredChainID()) - var err error - etx0, err = txStore.FindTxWithAttempts(ctx, etx0.ID) require.NoError(t, err) - assert.Equal(t, txmgrcommon.TxConfirmed, etx0.State) + + assert.Len(t, attempts, 1) assert.Len(t, etx0.TxAttempts, 1) - assert.Equal(t, txmgrtypes.TxAttemptBroadcast, etx0.TxAttempts[0].State) - etx1, err = txStore.FindTxWithAttempts(ctx, etx1.ID) + assert.Equal(t, etx0.TxAttempts[0].ID, attempts[0].ID) +} + +func TestORM_UpdateTxsUnconfirmed(t *testing.T) { + t.Parallel() + + ctx := tests.Context(t) + db := pgtest.NewSqlxDB(t) + txStore := cltest.NewTestTxStore(t, db) + ethKeyStore := cltest.NewKeyStore(t, db).Eth() + _, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore) + + originalBroadcastAt := time.Unix(1616509100, 0) + etx0 := mustInsertConfirmedMissingReceiptEthTxWithLegacyAttempt( + t, txStore, 0, 1, originalBroadcastAt, fromAddress) + assert.Equal(t, etx0.State, txmgrcommon.TxConfirmedMissingReceipt) + require.NoError(t, txStore.UpdateTxsUnconfirmed(tests.Context(t), []int64{etx0.ID})) + + etx0, err := txStore.FindTxWithAttempts(ctx, etx0.ID) require.NoError(t, err) - assert.Equal(t, txmgrcommon.TxConfirmed, etx1.State) - assert.Len(t, etx1.TxAttempts, 1) - assert.Equal(t, txmgrtypes.TxAttemptBroadcast, etx1.TxAttempts[0].State) + assert.Equal(t, etx0.State, txmgrcommon.TxUnconfirmed) +} + +func TestORM_FindTxAttemptsRequiringReceiptFetch(t *testing.T) { + t.Parallel() + + db := pgtest.NewSqlxDB(t) + txStore := cltest.NewTestTxStore(t, db) + ethKeyStore := cltest.NewKeyStore(t, db).Eth() + ethClient := evmtest.NewEthClientMockWithDefaultChain(t) + _, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore) + + originalBroadcastAt := time.Unix(1616509100, 0) + etx0 := mustInsertConfirmedMissingReceiptEthTxWithLegacyAttempt( + t, txStore, 0, 1, originalBroadcastAt, fromAddress) + + attempts, err := txStore.FindTxAttemptsRequiringReceiptFetch(tests.Context(t), ethClient.ConfiguredChainID()) + require.NoError(t, err) + assert.Len(t, attempts, 1) + assert.Len(t, etx0.TxAttempts, 1) + assert.Equal(t, etx0.TxAttempts[0].ID, attempts[0].ID) } func TestORM_SaveFetchedReceipts(t *testing.T) { @@ -472,45 +505,62 @@ func TestORM_SaveFetchedReceipts(t *testing.T) { db := pgtest.NewSqlxDB(t) txStore := cltest.NewTestTxStore(t, db) ethKeyStore := cltest.NewKeyStore(t, db).Eth() + ethClient := evmtest.NewEthClientMockWithDefaultChain(t) _, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore) ctx := tests.Context(t) - tx1 := cltest.MustInsertConfirmedEthTxWithLegacyAttempt(t, txStore, 0, 100, fromAddress) - require.Len(t, tx1.TxAttempts, 1) - - tx2 := mustInsertTerminallyStuckTxWithAttempt(t, txStore, fromAddress, 1, 100) - require.Len(t, tx2.TxAttempts, 1) + originalBroadcastAt := time.Unix(1616509100, 0) + etx0 := mustInsertConfirmedMissingReceiptEthTxWithLegacyAttempt( + t, txStore, 0, 1, originalBroadcastAt, fromAddress) + require.Len(t, etx0.TxAttempts, 1) - // create receipts associated with transactions - txmReceipt1 := evmtypes.Receipt{ - TxHash: tx1.TxAttempts[0].Hash, - BlockHash: utils.NewHash(), - BlockNumber: big.NewInt(42), - TransactionIndex: uint(1), - } - txmReceipt2 := evmtypes.Receipt{ - TxHash: tx2.TxAttempts[0].Hash, + // create receipt associated with transaction + txmReceipt := evmtypes.Receipt{ + TxHash: etx0.TxAttempts[0].Hash, BlockHash: utils.NewHash(), BlockNumber: big.NewInt(42), TransactionIndex: uint(1), } - err := txStore.SaveFetchedReceipts(tests.Context(t), []*evmtypes.Receipt{&txmReceipt1, &txmReceipt2}) - require.NoError(t, err) + err := txStore.SaveFetchedReceipts(tests.Context(t), []*evmtypes.Receipt{&txmReceipt}, txmgrcommon.TxConfirmed, nil, ethClient.ConfiguredChainID()) - tx1, err = txStore.FindTxWithAttempts(ctx, tx1.ID) require.NoError(t, err) - require.Len(t, tx1.TxAttempts, 1) - require.Len(t, tx1.TxAttempts[0].Receipts, 1) - require.Equal(t, txmReceipt1.BlockHash, tx1.TxAttempts[0].Receipts[0].GetBlockHash()) - require.Equal(t, txmgrcommon.TxConfirmed, tx1.State) + etx0, err = txStore.FindTxWithAttempts(ctx, etx0.ID) + require.NoError(t, err) + require.Len(t, etx0.TxAttempts, 1) + require.Len(t, etx0.TxAttempts[0].Receipts, 1) + require.Equal(t, txmReceipt.BlockHash, etx0.TxAttempts[0].Receipts[0].GetBlockHash()) + require.Equal(t, txmgrcommon.TxConfirmed, etx0.State) +} + +func TestORM_MarkAllConfirmedMissingReceipt(t *testing.T) { + t.Parallel() + + db := pgtest.NewSqlxDB(t) + txStore := cltest.NewTestTxStore(t, db) + ethKeyStore := cltest.NewKeyStore(t, db).Eth() + _, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore) + ethClient := evmtest.NewEthClientMockWithDefaultChain(t) + ctx := tests.Context(t) + + // create transaction 0 (nonce 0) that is unconfirmed (block 7) + etx0_blocknum := int64(7) + etx0 := cltest.MustInsertUnconfirmedEthTx(t, txStore, 0, fromAddress) + etx0_attempt := newBroadcastLegacyEthTxAttempt(t, etx0.ID, int64(1)) + etx0_attempt.BroadcastBeforeBlockNum = &etx0_blocknum + require.NoError(t, txStore.InsertTxAttempt(ctx, &etx0_attempt)) + assert.Equal(t, txmgrcommon.TxUnconfirmed, etx0.State) + + // create transaction 1 (nonce 1) that is confirmed (block 77) + etx1 := mustInsertConfirmedEthTxBySaveFetchedReceipts(t, txStore, fromAddress, int64(1), int64(77), *ethClient.ConfiguredChainID()) + assert.Equal(t, etx1.State, txmgrcommon.TxConfirmed) - tx2, err = txStore.FindTxWithAttempts(ctx, tx2.ID) + // mark transaction 0 confirmed_missing_receipt + err := txStore.MarkAllConfirmedMissingReceipt(tests.Context(t), ethClient.ConfiguredChainID()) require.NoError(t, err) - require.Len(t, tx2.TxAttempts, 1) - require.Len(t, tx2.TxAttempts[0].Receipts, 1) - require.Equal(t, txmReceipt2.BlockHash, tx2.TxAttempts[0].Receipts[0].GetBlockHash()) - require.Equal(t, txmgrcommon.TxFatalError, tx2.State) + etx0, err = txStore.FindTxWithAttempts(ctx, etx0.ID) + require.NoError(t, err) + assert.Equal(t, txmgrcommon.TxConfirmedMissingReceipt, etx0.State) } func TestORM_PreloadTxes(t *testing.T) { @@ -591,6 +641,7 @@ func TestORM_FindTxesPendingCallback(t *testing.T) { Hash: testutils.NewHash(), Number: 10, } + head.Parent.Store(h9) minConfirmations := int64(2) @@ -718,7 +769,7 @@ func TestORM_UpdateTxForRebroadcast(t *testing.T) { _, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore) ctx := tests.Context(t) - t.Run("marks confirmed tx as unconfirmed, marks latest attempt as in-progress, deletes receipt", func(t *testing.T) { + t.Run("delete all receipts for eth transaction", func(t *testing.T) { etx := mustInsertConfirmedEthTxWithReceipt(t, txStore, fromAddress, 777, 1) etx, err := txStore.FindTxWithAttempts(ctx, etx.ID) assert.NoError(t, err) @@ -731,7 +782,7 @@ func TestORM_UpdateTxForRebroadcast(t *testing.T) { assert.Len(t, etx.TxAttempts[0].Receipts, 1) // use exported method - err = txStore.UpdateTxsForRebroadcast(tests.Context(t), []int64{etx.ID}, []int64{attempt.ID}) + err = txStore.UpdateTxForRebroadcast(tests.Context(t), etx, attempt) require.NoError(t, err) resultTx, err := txStore.FindTxWithAttempts(ctx, etx.ID) @@ -745,39 +796,49 @@ func TestORM_UpdateTxForRebroadcast(t *testing.T) { // assert tx state assert.Equal(t, txmgrcommon.TxUnconfirmed, resultTx.State) // assert receipt - assert.Empty(t, resultTxAttempt.Receipts) + assert.Len(t, resultTxAttempt.Receipts, 0) }) +} - t.Run("marks confirmed tx as unconfirmed, clears error, marks latest attempt as in-progress, deletes receipt", func(t *testing.T) { - blockNum := int64(100) - etx := mustInsertTerminallyStuckTxWithAttempt(t, txStore, fromAddress, 1, blockNum) - mustInsertEthReceipt(t, txStore, blockNum, utils.NewHash(), etx.TxAttempts[0].Hash) - etx, err := txStore.FindTxWithAttempts(ctx, etx.ID) - require.NoError(t, err) - // assert attempt state - attempt := etx.TxAttempts[0] - require.Equal(t, txmgrtypes.TxAttemptBroadcast, attempt.State) - // assert tx state - assert.Equal(t, txmgrcommon.TxFatalError, etx.State) - // assert receipt - assert.Len(t, etx.TxAttempts[0].Receipts, 1) +func TestORM_FindTransactionsConfirmedInBlockRange(t *testing.T) { + t.Parallel() - // use exported method - err = txStore.UpdateTxsForRebroadcast(tests.Context(t), []int64{etx.ID}, []int64{attempt.ID}) - require.NoError(t, err) + db := pgtest.NewSqlxDB(t) + txStore := cltest.NewTestTxStore(t, db) + ethKeyStore := cltest.NewKeyStore(t, db).Eth() + ethClient := evmtest.NewEthClientMockWithDefaultChain(t) + _, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore) - resultTx, err := txStore.FindTxWithAttempts(ctx, etx.ID) + h8 := &evmtypes.Head{ + Number: 8, + Hash: testutils.NewHash(), + } + h9 := &evmtypes.Head{ + Hash: testutils.NewHash(), + Number: 9, + } + h9.Parent.Store(h8) + head := evmtypes.Head{ + Hash: testutils.NewHash(), + Number: 10, + } + head.Parent.Store(h9) + + t.Run("find all transactions confirmed in range", func(t *testing.T) { + etx_8 := mustInsertConfirmedEthTxWithReceipt(t, txStore, fromAddress, 700, 8) + etx_9 := mustInsertConfirmedEthTxWithReceipt(t, txStore, fromAddress, 777, 9) + + etxes, err := txStore.FindTransactionsConfirmedInBlockRange(tests.Context(t), head.Number, 8, ethClient.ConfiguredChainID()) require.NoError(t, err) - require.Len(t, resultTx.TxAttempts, 1) - resultTxAttempt := resultTx.TxAttempts[0] + assert.Len(t, etxes, 2) + assert.Equal(t, etxes[0].Sequence, etx_8.Sequence) + assert.Equal(t, etxes[1].Sequence, etx_9.Sequence) + }) - // assert attempt state - assert.Equal(t, txmgrtypes.TxAttemptInProgress, resultTxAttempt.State) - assert.Nil(t, resultTxAttempt.BroadcastBeforeBlockNum) - // assert tx state - assert.Equal(t, txmgrcommon.TxUnconfirmed, resultTx.State) - // assert receipt - assert.Empty(t, resultTxAttempt.Receipts) + t.Run("return empty txes when no transactions in range found", func(t *testing.T) { + etxes, err := txStore.FindTransactionsConfirmedInBlockRange(tests.Context(t), 0, 0, ethClient.ConfiguredChainID()) + require.NoError(t, err) + assert.Len(t, etxes, 0) }) } @@ -883,7 +944,7 @@ func TestORM_SaveSentAttempt(t *testing.T) { }) } -func TestORM_SaveConfirmedAttempt(t *testing.T) { +func TestORM_SaveConfirmedMissingReceiptAttempt(t *testing.T) { t.Parallel() ctx := tests.Context(t) @@ -898,12 +959,12 @@ func TestORM_SaveConfirmedAttempt(t *testing.T) { etx := mustInsertUnconfirmedEthTxWithAttemptState(t, txStore, 1, fromAddress, txmgrtypes.TxAttemptInProgress) now := time.Now() - err = txStore.SaveConfirmedAttempt(tests.Context(t), defaultDuration, &etx.TxAttempts[0], now) + err = txStore.SaveConfirmedMissingReceiptAttempt(tests.Context(t), defaultDuration, &etx.TxAttempts[0], now) require.NoError(t, err) etx, err := txStore.FindTxWithAttempts(ctx, etx.ID) require.NoError(t, err) - assert.Equal(t, txmgrcommon.TxConfirmed, etx.State) + assert.Equal(t, txmgrcommon.TxConfirmedMissingReceipt, etx.State) assert.Equal(t, txmgrtypes.TxAttemptBroadcast, etx.TxAttempts[0].State) }) } @@ -1054,7 +1115,7 @@ func TestEthConfirmer_FindTxsRequiringResubmissionDueToInsufficientEth(t *testin etxs, err := txStore.FindTxsRequiringResubmissionDueToInsufficientFunds(tests.Context(t), fromAddress, big.NewInt(42)) require.NoError(t, err) - assert.Empty(t, etxs) + assert.Len(t, etxs, 0) }) t.Run("does not return confirmed or fatally errored eth_txes", func(t *testing.T) { @@ -1071,6 +1132,42 @@ func TestEthConfirmer_FindTxsRequiringResubmissionDueToInsufficientEth(t *testin }) } +func TestORM_MarkOldTxesMissingReceiptAsErrored(t *testing.T) { + t.Parallel() + + db := pgtest.NewSqlxDB(t) + txStore := cltest.NewTestTxStore(t, db) + ctx := tests.Context(t) + ethKeyStore := cltest.NewKeyStore(t, db).Eth() + ethClient := evmtest.NewEthClientMockWithDefaultChain(t) + _, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore) + latestFinalizedBlockNum := int64(8) + + // tx state should be confirmed missing receipt + // attempt should be before latestFinalizedBlockNum + t.Run("successfully mark errored transactions", func(t *testing.T) { + etx := mustInsertConfirmedMissingReceiptEthTxWithLegacyAttempt(t, txStore, 1, 7, time.Now(), fromAddress) + + err := txStore.MarkOldTxesMissingReceiptAsErrored(tests.Context(t), 10, latestFinalizedBlockNum, ethClient.ConfiguredChainID()) + require.NoError(t, err) + + etx, err = txStore.FindTxWithAttempts(ctx, etx.ID) + require.NoError(t, err) + assert.Equal(t, txmgrcommon.TxFatalError, etx.State) + }) + + t.Run("successfully mark errored transactions w/ qopt passing in sql.Tx", func(t *testing.T) { + etx := mustInsertConfirmedMissingReceiptEthTxWithLegacyAttempt(t, txStore, 1, 7, time.Now(), fromAddress) + err := txStore.MarkOldTxesMissingReceiptAsErrored(tests.Context(t), 10, latestFinalizedBlockNum, ethClient.ConfiguredChainID()) + require.NoError(t, err) + + // must run other query outside of postgres transaction so changes are committed + etx, err = txStore.FindTxWithAttempts(ctx, etx.ID) + require.NoError(t, err) + assert.Equal(t, txmgrcommon.TxFatalError, etx.State) + }) +} + func TestORM_LoadEthTxesAttempts(t *testing.T) { t.Parallel() @@ -1174,7 +1271,7 @@ func TestORM_FindNextUnstartedTransactionFromAddress(t *testing.T) { }) } -func TestORM_UpdateTxFatalErrorAndDeleteAttempts(t *testing.T) { +func TestORM_UpdateTxFatalError(t *testing.T) { t.Parallel() ctx := tests.Context(t) @@ -1189,11 +1286,11 @@ func TestORM_UpdateTxFatalErrorAndDeleteAttempts(t *testing.T) { etxPretendError := null.StringFrom("no more toilet paper") etx.Error = etxPretendError - err := txStore.UpdateTxFatalErrorAndDeleteAttempts(tests.Context(t), &etx) + err := txStore.UpdateTxFatalError(tests.Context(t), &etx) require.NoError(t, err) etx, err = txStore.FindTxWithAttempts(ctx, etx.ID) require.NoError(t, err) - assert.Empty(t, etx.TxAttempts) + assert.Len(t, etx.TxAttempts, 0) assert.Equal(t, txmgrcommon.TxFatalError, etx.State) }) } @@ -1707,7 +1804,7 @@ func TestORM_CreateTransaction(t *testing.T) { assert.Greater(t, etx.ID, int64(0)) assert.Equal(t, fromAddress, etx.FromAddress) - assert.True(t, etx.SignalCallback) + assert.Equal(t, true, etx.SignalCallback) cltest.AssertCount(t, db, "evm.txes", 3) @@ -1715,7 +1812,7 @@ func TestORM_CreateTransaction(t *testing.T) { require.NoError(t, db.Get(&dbEthTx, `SELECT * FROM evm.txes ORDER BY id DESC LIMIT 1`)) assert.Equal(t, fromAddress, dbEthTx.FromAddress) - assert.True(t, dbEthTx.SignalCallback) + assert.Equal(t, true, dbEthTx.SignalCallback) }) } @@ -1776,64 +1873,30 @@ func AssertCountPerSubject(t *testing.T, txStore txmgr.TestEvmTxStore, expected require.Equal(t, int(expected), count) } -func TestORM_FindAttemptsRequiringReceiptFetch(t *testing.T) { +func TestORM_FindTransactionsByState(t *testing.T) { t.Parallel() ctx := tests.Context(t) - blockNum := int64(100) - - t.Run("finds confirmed transaction requiring receipt fetch", func(t *testing.T) { - db := pgtest.NewSqlxDB(t) - txStore := cltest.NewTestTxStore(t, db) - kst := cltest.NewKeyStore(t, db) - _, fromAddress := cltest.MustInsertRandomKey(t, kst.Eth()) - // Transactions whose attempts should not be picked up for receipt fetch - mustInsertFatalErrorEthTx(t, txStore, fromAddress) - mustInsertUnstartedTx(t, txStore, fromAddress) - mustInsertInProgressEthTxWithAttempt(t, txStore, 4, fromAddress) - mustInsertUnconfirmedEthTxWithAttemptState(t, txStore, 3, fromAddress, txmgrtypes.TxAttemptBroadcast) - mustInsertConfirmedEthTxWithReceipt(t, txStore, fromAddress, 2, blockNum) - // Terminally stuck transaction with receipt should NOT be picked up for receipt fetch - stuckTx := mustInsertTerminallyStuckTxWithAttempt(t, txStore, fromAddress, 1, blockNum) - mustInsertEthReceipt(t, txStore, blockNum, utils.NewHash(), stuckTx.TxAttempts[0].Hash) - - // Confirmed transaction without receipt should be picked up for receipt fetch - confirmedTx := mustInsertConfirmedEthTx(t, txStore, 0, fromAddress) - attempt := newBroadcastLegacyEthTxAttempt(t, confirmedTx.ID) - err := txStore.InsertTxAttempt(ctx, &attempt) - require.NoError(t, err) - - attempts, err := txStore.FindAttemptsRequiringReceiptFetch(ctx, testutils.FixtureChainID) - require.NoError(t, err) - require.Len(t, attempts, 1) - require.Equal(t, attempt.Hash.String(), attempts[0].Hash.String()) - }) - - t.Run("finds terminally stuck transaction requiring receipt fetch", func(t *testing.T) { - db := pgtest.NewSqlxDB(t) - txStore := cltest.NewTestTxStore(t, db) - kst := cltest.NewKeyStore(t, db) - _, fromAddress := cltest.MustInsertRandomKey(t, kst.Eth()) - // Transactions whose attempts should not be picked up for receipt fetch - mustInsertFatalErrorEthTx(t, txStore, fromAddress) - mustInsertUnstartedTx(t, txStore, fromAddress) - mustInsertInProgressEthTxWithAttempt(t, txStore, 4, fromAddress) - mustInsertUnconfirmedEthTxWithAttemptState(t, txStore, 3, fromAddress, txmgrtypes.TxAttemptBroadcast) - mustInsertConfirmedEthTxWithReceipt(t, txStore, fromAddress, 2, blockNum) - // Terminally stuck transaction with receipt should NOT be picked up for receipt fetch - stuckTxWithReceipt := mustInsertTerminallyStuckTxWithAttempt(t, txStore, fromAddress, 1, blockNum) - mustInsertEthReceipt(t, txStore, blockNum, utils.NewHash(), stuckTxWithReceipt.TxAttempts[0].Hash) - // Terminally stuck transaction without receipt should be picked up for receipt fetch - stuckTxWoutReceipt := mustInsertTerminallyStuckTxWithAttempt(t, txStore, fromAddress, 0, blockNum) - - attempts, err := txStore.FindAttemptsRequiringReceiptFetch(ctx, testutils.FixtureChainID) - require.NoError(t, err) - require.Len(t, attempts, 1) - require.Equal(t, stuckTxWoutReceipt.TxAttempts[0].Hash.String(), attempts[0].Hash.String()) - }) + db := pgtest.NewSqlxDB(t) + txStore := cltest.NewTestTxStore(t, db) + kst := cltest.NewKeyStore(t, db) + _, fromAddress := cltest.MustInsertRandomKey(t, kst.Eth()) + finalizedBlockNum := int64(100) + + mustInsertUnstartedTx(t, txStore, fromAddress) + mustInsertInProgressEthTxWithAttempt(t, txStore, 0, fromAddress) + mustInsertUnconfirmedEthTxWithAttemptState(t, txStore, 1, fromAddress, txmgrtypes.TxAttemptBroadcast) + mustInsertConfirmedMissingReceiptEthTxWithLegacyAttempt(t, txStore, 2, finalizedBlockNum, time.Now(), fromAddress) + mustInsertConfirmedEthTxWithReceipt(t, txStore, fromAddress, 3, finalizedBlockNum+1) + mustInsertConfirmedEthTxWithReceipt(t, txStore, fromAddress, 4, finalizedBlockNum) + mustInsertFatalErrorEthTx(t, txStore, fromAddress) + + receipts, err := txStore.FindConfirmedTxesReceipts(ctx, finalizedBlockNum, testutils.FixtureChainID) + require.NoError(t, err) + require.Len(t, receipts, 1) } -func TestORM_UpdateTxStatesToFinalizedUsingTxHashes(t *testing.T) { +func TestORM_UpdateTxesFinalized(t *testing.T) { t.Parallel() ctx := tests.Context(t) @@ -1858,176 +1921,11 @@ func TestORM_UpdateTxStatesToFinalizedUsingTxHashes(t *testing.T) { attempt := newBroadcastLegacyEthTxAttempt(t, tx.ID) err = txStore.InsertTxAttempt(ctx, &attempt) require.NoError(t, err) - mustInsertEthReceipt(t, txStore, 100, testutils.NewHash(), attempt.Hash) - err = txStore.UpdateTxStatesToFinalizedUsingTxHashes(ctx, []common.Hash{attempt.Hash}, testutils.FixtureChainID) + receipt := mustInsertEthReceipt(t, txStore, 100, testutils.NewHash(), attempt.Hash) + err = txStore.UpdateTxStatesToFinalizedUsingReceiptIds(ctx, []int64{receipt.ID}, testutils.FixtureChainID) require.NoError(t, err) etx, err := txStore.FindTxWithAttempts(ctx, tx.ID) require.NoError(t, err) require.Equal(t, txmgrcommon.TxFinalized, etx.State) }) } - -func TestORM_FindReorgOrIncludedTxs(t *testing.T) { - t.Parallel() - - ctx := tests.Context(t) - db := pgtest.NewSqlxDB(t) - txStore := cltest.NewTestTxStore(t, db) - kst := cltest.NewKeyStore(t, db) - blockNum := int64(100) - t.Run("finds re-org'd transactions using the mined tx count", func(t *testing.T) { - _, fromAddress := cltest.MustInsertRandomKey(t, kst.Eth()) - _, otherAddress := cltest.MustInsertRandomKey(t, kst.Eth()) - // Unstarted can't be re-org'd - mustInsertUnstartedTx(t, txStore, fromAddress) - // In-Progress can't be re-org'd - mustInsertInProgressEthTxWithAttempt(t, txStore, 4, fromAddress) - // Unconfirmed can't be re-org'd - mustInsertUnconfirmedEthTxWithAttemptState(t, txStore, 3, fromAddress, txmgrtypes.TxAttemptBroadcast) - // Confirmed and nonce greater than mined tx count so has been re-org'd - mustInsertConfirmedEthTxWithReceipt(t, txStore, fromAddress, 2, blockNum) - // Fatal error and nonce equal to mined tx count so has been re-org'd - mustInsertTerminallyStuckTxWithAttempt(t, txStore, fromAddress, 1, blockNum) - // Nonce lower than mined tx count so has not been re-org - mustInsertConfirmedEthTxWithReceipt(t, txStore, fromAddress, 0, blockNum) - - // Tx for another from address should not be returned - mustInsertConfirmedEthTxWithReceipt(t, txStore, otherAddress, 1, blockNum) - mustInsertConfirmedEthTxWithReceipt(t, txStore, otherAddress, 0, blockNum) - - reorgTxs, includedTxs, err := txStore.FindReorgOrIncludedTxs(ctx, fromAddress, evmtypes.Nonce(1), testutils.FixtureChainID) - require.NoError(t, err) - require.Len(t, reorgTxs, 2) - require.Empty(t, includedTxs) - }) - - t.Run("finds transactions included on-chain using the mined tx count", func(t *testing.T) { - _, fromAddress := cltest.MustInsertRandomKey(t, kst.Eth()) - _, otherAddress := cltest.MustInsertRandomKey(t, kst.Eth()) - // Unstarted can't be included - mustInsertUnstartedTx(t, txStore, fromAddress) - // In-Progress can't be included - mustInsertInProgressEthTxWithAttempt(t, txStore, 5, fromAddress) - // Unconfirmed with higher nonce can't be included - mustInsertUnconfirmedEthTxWithAttemptState(t, txStore, 4, fromAddress, txmgrtypes.TxAttemptBroadcast) - // Unconfirmed with nonce less than mined tx count is newly included - mustInsertUnconfirmedEthTxWithAttemptState(t, txStore, 3, fromAddress, txmgrtypes.TxAttemptBroadcast) - // Unconfirmed with purge attempt with nonce less than mined tx cound is newly included - mustInsertUnconfirmedEthTxWithBroadcastPurgeAttempt(t, txStore, 2, fromAddress) - // Fatal error so already included - mustInsertTerminallyStuckTxWithAttempt(t, txStore, fromAddress, 1, blockNum) - // Confirmed so already included - mustInsertConfirmedEthTxWithReceipt(t, txStore, fromAddress, 0, blockNum) - - // Tx for another from address should not be returned - mustInsertConfirmedEthTxWithReceipt(t, txStore, otherAddress, 1, blockNum) - mustInsertConfirmedEthTxWithReceipt(t, txStore, otherAddress, 0, blockNum) - - reorgTxs, includedTxs, err := txStore.FindReorgOrIncludedTxs(ctx, fromAddress, evmtypes.Nonce(4), testutils.FixtureChainID) - require.NoError(t, err) - require.Len(t, includedTxs, 2) - require.Empty(t, reorgTxs) - }) -} - -func TestORM_UpdateTxFatalError(t *testing.T) { - t.Parallel() - - ctx := tests.Context(t) - db := pgtest.NewSqlxDB(t) - txStore := cltest.NewTestTxStore(t, db) - kst := cltest.NewKeyStore(t, db) - _, fromAddress := cltest.MustInsertRandomKey(t, kst.Eth()) - t.Run("successfully marks transaction as fatal with error message", func(t *testing.T) { - // Unconfirmed with purge attempt with nonce less than mined tx cound is newly included - tx1 := mustInsertUnconfirmedEthTxWithBroadcastPurgeAttempt(t, txStore, 0, fromAddress) - tx2 := mustInsertUnconfirmedEthTxWithBroadcastPurgeAttempt(t, txStore, 1, fromAddress) - - err := txStore.UpdateTxFatalError(ctx, []int64{tx1.ID, tx2.ID}, client.TerminallyStuckMsg) - require.NoError(t, err) - - tx1, err = txStore.FindTxWithAttempts(ctx, tx1.ID) - require.NoError(t, err) - require.Equal(t, txmgrcommon.TxFatalError, tx1.State) - require.Equal(t, client.TerminallyStuckMsg, tx1.Error.String) - tx2, err = txStore.FindTxWithAttempts(ctx, tx2.ID) - require.NoError(t, err) - require.Equal(t, txmgrcommon.TxFatalError, tx2.State) - require.Equal(t, client.TerminallyStuckMsg, tx2.Error.String) - }) -} - -func TestORM_FindTxesByIDs(t *testing.T) { - t.Parallel() - - db := pgtest.NewSqlxDB(t) - txStore := cltest.NewTestTxStore(t, db) - ctx := tests.Context(t) - ethKeyStore := cltest.NewKeyStore(t, db).Eth() - _, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore) - - // tx state should be confirmed missing receipt - // attempt should be before latestFinalizedBlockNum - t.Run("successfully finds transactions with IDs", func(t *testing.T) { - etx1 := mustInsertInProgressEthTxWithAttempt(t, txStore, 3, fromAddress) - etx2 := mustInsertUnconfirmedEthTxWithAttemptState(t, txStore, 2, fromAddress, txmgrtypes.TxAttemptBroadcast) - etx3 := mustInsertTerminallyStuckTxWithAttempt(t, txStore, fromAddress, 1, 100) - etx4 := mustInsertConfirmedEthTxWithReceipt(t, txStore, fromAddress, 0, 100) - - etxIDs := []int64{etx1.ID, etx2.ID, etx3.ID, etx4.ID} - oldTxs, err := txStore.FindTxesByIDs(ctx, etxIDs, testutils.FixtureChainID) - require.NoError(t, err) - require.Len(t, oldTxs, 4) - }) -} - -func TestORM_DeleteReceiptsByTxHash(t *testing.T) { - t.Parallel() - - db := pgtest.NewSqlxDB(t) - txStore := cltest.NewTestTxStore(t, db) - ctx := tests.Context(t) - ethKeyStore := cltest.NewKeyStore(t, db).Eth() - _, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore) - - etx1 := mustInsertConfirmedEthTxWithReceipt(t, txStore, fromAddress, 0, 100) - etx2 := mustInsertConfirmedEthTxWithReceipt(t, txStore, fromAddress, 2, 100) - - // Delete one transaction's receipt - err := txStore.DeleteReceiptByTxHash(ctx, etx1.TxAttempts[0].Hash) - require.NoError(t, err) - - // receipt has been deleted - etx1, err = txStore.FindTxWithAttempts(ctx, etx1.ID) - require.NoError(t, err) - require.Empty(t, etx1.TxAttempts[0].Receipts) - - // receipt still exists for other tx - etx2, err = txStore.FindTxWithAttempts(ctx, etx2.ID) - require.NoError(t, err) - require.Len(t, etx2.TxAttempts[0].Receipts, 1) -} - -func mustInsertTerminallyStuckTxWithAttempt(t *testing.T, txStore txmgr.TestEvmTxStore, fromAddress common.Address, nonceInt int64, broadcastBeforeBlockNum int64) txmgr.Tx { - ctx := tests.Context(t) - broadcast := time.Now() - nonce := evmtypes.Nonce(nonceInt) - tx := txmgr.Tx{ - Sequence: &nonce, - FromAddress: fromAddress, - EncodedPayload: []byte{1, 2, 3}, - State: txmgrcommon.TxFatalError, - BroadcastAt: &broadcast, - InitialBroadcastAt: &broadcast, - Error: null.StringFrom(client.TerminallyStuckMsg), - } - require.NoError(t, txStore.InsertTx(ctx, &tx)) - attempt := cltest.NewLegacyEthTxAttempt(t, tx.ID) - attempt.BroadcastBeforeBlockNum = &broadcastBeforeBlockNum - attempt.State = txmgrtypes.TxAttemptBroadcast - attempt.IsPurgeAttempt = true - require.NoError(t, txStore.InsertTxAttempt(ctx, &attempt)) - tx, err := txStore.FindTxWithAttempts(ctx, tx.ID) - require.NoError(t, err) - return tx -} diff --git a/core/chains/evm/txmgr/finalizer.go b/core/chains/evm/txmgr/finalizer.go index bc496202cd6..60744636159 100644 --- a/core/chains/evm/txmgr/finalizer.go +++ b/core/chains/evm/txmgr/finalizer.go @@ -2,21 +2,13 @@ package txmgr import ( "context" - "database/sql" - "errors" "fmt" "math/big" - "strconv" "sync" "time" - "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/rpc" - "github.com/google/uuid" - "github.com/prometheus/client_golang/prometheus" - "github.com/prometheus/client_golang/prometheus/promauto" - "gopkg.in/guregu/null.v4" "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink-common/pkg/services" @@ -28,70 +20,28 @@ import ( var _ Finalizer = (*evmFinalizer)(nil) -var ( - promNumSuccessfulTxs = promauto.NewCounterVec(prometheus.CounterOpts{ - Name: "tx_manager_num_successful_transactions", - Help: "Total number of successful transactions. Note that this can err to be too high since transactions are counted on each confirmation, which can happen multiple times per transaction in the case of re-orgs", - }, []string{"chainID"}) - promRevertedTxCount = promauto.NewCounterVec(prometheus.CounterOpts{ - Name: "tx_manager_num_tx_reverted", - Help: "Number of times a transaction reverted on-chain. Note that this can err to be too high since transactions are counted on each confirmation, which can happen multiple times per transaction in the case of re-orgs", - }, []string{"chainID"}) - promFwdTxCount = promauto.NewCounterVec(prometheus.CounterOpts{ - Name: "tx_manager_fwd_tx_count", - Help: "The number of forwarded transaction attempts labeled by status", - }, []string{"chainID", "successful"}) - promTxAttemptCount = promauto.NewGaugeVec(prometheus.GaugeOpts{ - Name: "tx_manager_tx_attempt_count", - Help: "The number of transaction attempts that are currently being processed by the transaction manager", - }, []string{"chainID"}) - promNumFinalizedTxs = promauto.NewCounterVec(prometheus.CounterOpts{ - Name: "tx_manager_num_finalized_transactions", - Help: "Total number of finalized transactions", - }, []string{"chainID"}) -) - -var ( - // ErrCouldNotGetReceipt is the error string we save if we reach our LatestFinalizedBlockNum for a confirmed transaction - // without ever getting a receipt. This most likely happened because an external wallet used the account for this nonce - ErrCouldNotGetReceipt = "could not get receipt" -) - // processHeadTimeout represents a sanity limit on how long ProcessHead should take to complete const processHeadTimeout = 10 * time.Minute type finalizerTxStore interface { - DeleteReceiptByTxHash(ctx context.Context, txHash common.Hash) error - FindAttemptsRequiringReceiptFetch(ctx context.Context, chainID *big.Int) (hashes []TxAttempt, err error) - FindConfirmedTxesReceipts(ctx context.Context, finalizedBlockNum int64, chainID *big.Int) (receipts []*evmtypes.Receipt, err error) - FindTxesPendingCallback(ctx context.Context, latest, finalized int64, chainID *big.Int) (receiptsPlus []ReceiptPlus, err error) - FindTxesByIDs(ctx context.Context, etxIDs []int64, chainID *big.Int) (etxs []*Tx, err error) - PreloadTxes(ctx context.Context, attempts []TxAttempt) error - SaveFetchedReceipts(ctx context.Context, r []*evmtypes.Receipt) (err error) - UpdateTxCallbackCompleted(ctx context.Context, pipelineTaskRunID uuid.UUID, chainID *big.Int) error - UpdateTxFatalErrorAndDeleteAttempts(ctx context.Context, etx *Tx) error - UpdateTxStatesToFinalizedUsingTxHashes(ctx context.Context, txHashes []common.Hash, chainID *big.Int) error + FindConfirmedTxesReceipts(ctx context.Context, finalizedBlockNum int64, chainID *big.Int) ([]Receipt, error) + UpdateTxStatesToFinalizedUsingReceiptIds(ctx context.Context, txs []int64, chainId *big.Int) error } type finalizerChainClient interface { BatchCallContext(ctx context.Context, elems []rpc.BatchElem) error - BatchGetReceipts(ctx context.Context, attempts []TxAttempt) (txReceipt []*evmtypes.Receipt, txErr []error, funcErr error) - CallContract(ctx context.Context, a TxAttempt, blockNumber *big.Int) (rpcErr fmt.Stringer, extractErr error) } type finalizerHeadTracker interface { LatestAndFinalizedBlock(ctx context.Context) (latest, finalized *evmtypes.Head, err error) } -type resumeCallback = func(context.Context, uuid.UUID, interface{}, error) error - // Finalizer handles processing new finalized blocks and marking transactions as finalized accordingly in the TXM DB type evmFinalizer struct { services.StateMachine - lggr logger.SugaredLogger - chainID *big.Int - rpcBatchSize int - forwardersEnabled bool + lggr logger.SugaredLogger + chainId *big.Int + rpcBatchSize int txStore finalizerTxStore client finalizerChainClient @@ -102,40 +52,32 @@ type evmFinalizer struct { wg sync.WaitGroup lastProcessedFinalizedBlockNum int64 - resumeCallback resumeCallback } func NewEvmFinalizer( lggr logger.Logger, - chainID *big.Int, + chainId *big.Int, rpcBatchSize uint32, - forwardersEnabled bool, txStore finalizerTxStore, client finalizerChainClient, headTracker finalizerHeadTracker, ) *evmFinalizer { lggr = logger.Named(lggr, "Finalizer") return &evmFinalizer{ - lggr: logger.Sugared(lggr), - chainID: chainID, - rpcBatchSize: int(rpcBatchSize), - forwardersEnabled: forwardersEnabled, - txStore: txStore, - client: client, - headTracker: headTracker, - mb: mailbox.NewSingle[*evmtypes.Head](), - resumeCallback: nil, + lggr: logger.Sugared(lggr), + chainId: chainId, + rpcBatchSize: int(rpcBatchSize), + txStore: txStore, + client: client, + headTracker: headTracker, + mb: mailbox.NewSingle[*evmtypes.Head](), } } -func (f *evmFinalizer) SetResumeCallback(callback resumeCallback) { - f.resumeCallback = callback -} - // Start the finalizer func (f *evmFinalizer) Start(ctx context.Context) error { return f.StartOnce("Finalizer", func() error { - f.lggr.Debugw("started Finalizer", "rpcBatchSize", f.rpcBatchSize, "forwardersEnabled", f.forwardersEnabled) + f.lggr.Debugf("started Finalizer with RPC batch size limit: %d", f.rpcBatchSize) f.stopCh = make(chan struct{}) f.wg.Add(1) go f.runLoop() @@ -199,23 +141,10 @@ func (f *evmFinalizer) ProcessHead(ctx context.Context, head *evmtypes.Head) err if err != nil { return fmt.Errorf("failed to retrieve latest finalized head: %w", err) } - // Fetch and store receipts for confirmed transactions that do not have locally stored receipts - err = f.FetchAndStoreReceipts(ctx, head, latestFinalizedHead) - // Do not return on error since other functions are not dependent on results - if err != nil { - f.lggr.Errorf("failed to fetch and store receipts for confirmed transactions: %s", err.Error()) - } - // Resume pending task runs if any receipts match the min confirmation criteria - err = f.ResumePendingTaskRuns(ctx, head.BlockNumber(), latestFinalizedHead.BlockNumber()) - // Do not return on error since other functions are not dependent on results - if err != nil { - f.lggr.Errorf("failed to resume pending task runs: %s", err.Error()) - } return f.processFinalizedHead(ctx, latestFinalizedHead) } -// processFinalizedHead determines if any confirmed transactions can be marked as finalized by comparing their receipts against the latest finalized block -// Fetches receipts directly from on-chain so re-org detection is not needed during finalization +// Determines if any confirmed transactions can be marked as finalized by comparing their receipts against the latest finalized block func (f *evmFinalizer) processFinalizedHead(ctx context.Context, latestFinalizedHead *evmtypes.Head) error { // Cannot determine finality without a finalized head for comparison if latestFinalizedHead == nil || !latestFinalizedHead.IsValid() { @@ -227,28 +156,23 @@ func (f *evmFinalizer) processFinalizedHead(ctx context.Context, latestFinalized return nil } if latestFinalizedHead.BlockNumber() < f.lastProcessedFinalizedBlockNum { - f.lggr.Errorw("Received finalized block older than one already processed", "lastProcessedFinalizedBlockNum", f.lastProcessedFinalizedBlockNum, "retrievedFinalizedBlockNum", latestFinalizedHead.BlockNumber()) + f.lggr.Errorw("Received finalized block older than one already processed. This should never happen and could be an issue with RPCs.", "lastProcessedFinalizedBlockNum", f.lastProcessedFinalizedBlockNum, "retrievedFinalizedBlockNum", latestFinalizedHead.BlockNumber()) return nil } earliestBlockNumInChain := latestFinalizedHead.EarliestHeadInChain().BlockNumber() f.lggr.Debugw("processing latest finalized head", "blockNum", latestFinalizedHead.BlockNumber(), "blockHash", latestFinalizedHead.BlockHash(), "earliestBlockNumInChain", earliestBlockNumInChain) - mark := time.Now() - // Retrieve all confirmed transactions with receipts older than or equal to the finalized block - unfinalizedReceipts, err := f.txStore.FindConfirmedTxesReceipts(ctx, latestFinalizedHead.BlockNumber(), f.chainID) + // Retrieve all confirmed transactions with receipts older than or equal to the finalized block, loaded with attempts and receipts + unfinalizedReceipts, err := f.txStore.FindConfirmedTxesReceipts(ctx, latestFinalizedHead.BlockNumber(), f.chainId) if err != nil { return fmt.Errorf("failed to retrieve receipts for confirmed, unfinalized transactions: %w", err) } - if len(unfinalizedReceipts) > 0 { - f.lggr.Debugw(fmt.Sprintf("found %d receipts for potential finalized transactions", len(unfinalizedReceipts)), "timeElapsed", time.Since(mark)) - } - mark = time.Now() - finalizedReceipts := make([]*evmtypes.Receipt, 0, len(unfinalizedReceipts)) + var finalizedReceipts []Receipt // Group by block hash transactions whose receipts cannot be validated using the cached heads - blockNumToReceiptsMap := make(map[int64][]*evmtypes.Receipt) - // Find receipts with block nums older than or equal to the latest finalized block num + blockNumToReceiptsMap := make(map[int64][]Receipt) + // Find transactions with receipt block nums older than the latest finalized block num and block hashes still in chain for _, receipt := range unfinalizedReceipts { // The tx store query ensures transactions have receipts but leaving this check here for a belts and braces approach if receipt.TxHash == utils.EmptyHash || receipt.BlockHash == utils.EmptyHash { @@ -256,64 +180,49 @@ func (f *evmFinalizer) processFinalizedHead(ctx context.Context, latestFinalized continue } // The tx store query only returns transactions with receipts older than or equal to the finalized block but leaving this check here for a belts and braces approach - if receipt.BlockNumber.Int64() > latestFinalizedHead.BlockNumber() { + if receipt.BlockNumber > latestFinalizedHead.BlockNumber() { continue } // Receipt block num older than earliest head in chain. Validate hash using RPC call later - if receipt.BlockNumber.Int64() < earliestBlockNumInChain { - blockNumToReceiptsMap[receipt.BlockNumber.Int64()] = append(blockNumToReceiptsMap[receipt.BlockNumber.Int64()], receipt) + if receipt.BlockNumber < earliestBlockNumInChain { + blockNumToReceiptsMap[receipt.BlockNumber] = append(blockNumToReceiptsMap[receipt.BlockNumber], receipt) continue } - blockHashInChain := latestFinalizedHead.HashAtHeight(receipt.BlockNumber.Int64()) + blockHashInChain := latestFinalizedHead.HashAtHeight(receipt.BlockNumber) // Receipt block hash does not match the block hash in chain. Transaction has been re-org'd out but DB state has not been updated yet if blockHashInChain.String() != receipt.BlockHash.String() { // Log error if a transaction is marked as confirmed with a receipt older than the finalized block - // This scenario could potentially be caused by a stale receipt stored for a re-org'd transaction - f.lggr.Debugw("found confirmed transaction with re-org'd receipt", "receipt", receipt, "onchainBlockHash", blockHashInChain.String()) - err = f.txStore.DeleteReceiptByTxHash(ctx, receipt.GetTxHash()) - // Log error but allow process to continue so other transactions can still be marked as finalized - if err != nil { - f.lggr.Errorw("failed to delete receipt", "receipt", receipt) - } + // This scenario could potentially point to a re-org'd transaction the Confirmer has lost track of + f.lggr.Errorw("found confirmed transaction with re-org'd receipt older than finalized block", "receipt", receipt, "onchainBlockHash", blockHashInChain.String()) continue } finalizedReceipts = append(finalizedReceipts, receipt) } - if len(finalizedReceipts) > 0 { - f.lggr.Debugw(fmt.Sprintf("found %d finalized transactions using local block history", len(finalizedReceipts)), "latestFinalizedBlockNum", latestFinalizedHead.BlockNumber(), "timeElapsed", time.Since(mark)) - } - mark = time.Now() // Check if block hashes exist for receipts on-chain older than the earliest cached head // Transactions are grouped by their receipt block hash to avoid repeat requests on the same hash in case transactions were confirmed in the same block validatedReceipts := f.batchCheckReceiptHashesOnchain(ctx, blockNumToReceiptsMap) finalizedReceipts = append(finalizedReceipts, validatedReceipts...) - if len(validatedReceipts) > 0 { - f.lggr.Debugw(fmt.Sprintf("found %d finalized transactions validated against RPC", len(validatedReceipts)), "latestFinalizedBlockNum", latestFinalizedHead.BlockNumber(), "timeElapsed", time.Since(mark)) - } - txHashes := f.buildTxHashList(finalizedReceipts) - err = f.txStore.UpdateTxStatesToFinalizedUsingTxHashes(ctx, txHashes, f.chainID) + receiptIDs := f.buildReceiptIdList(finalizedReceipts) + + err = f.txStore.UpdateTxStatesToFinalizedUsingReceiptIds(ctx, receiptIDs, f.chainId) if err != nil { return fmt.Errorf("failed to update transactions as finalized: %w", err) } // Update lastProcessedFinalizedBlockNum after processing has completed to allow failed processing to retry on subsequent heads // Does not need to be protected with mutex lock because the Finalizer only runs in a single loop f.lastProcessedFinalizedBlockNum = latestFinalizedHead.BlockNumber() - - // add newly finalized transactions to the prom metric - promNumFinalizedTxs.WithLabelValues(f.chainID.String()).Add(float64(len(txHashes))) - return nil } -func (f *evmFinalizer) batchCheckReceiptHashesOnchain(ctx context.Context, blockNumToReceiptsMap map[int64][]*evmtypes.Receipt) []*evmtypes.Receipt { +func (f *evmFinalizer) batchCheckReceiptHashesOnchain(ctx context.Context, blockNumToReceiptsMap map[int64][]Receipt) []Receipt { if len(blockNumToReceiptsMap) == 0 { return nil } // Group the RPC batch calls in groups of rpcBatchSize - rpcBatchGroups := make([][]rpc.BatchElem, 0, len(blockNumToReceiptsMap)) - rpcBatch := make([]rpc.BatchElem, 0, f.rpcBatchSize) + var rpcBatchGroups [][]rpc.BatchElem + var rpcBatch []rpc.BatchElem for blockNum := range blockNumToReceiptsMap { elem := rpc.BatchElem{ Method: "eth_getBlockByNumber", @@ -326,14 +235,14 @@ func (f *evmFinalizer) batchCheckReceiptHashesOnchain(ctx context.Context, block rpcBatch = append(rpcBatch, elem) if len(rpcBatch) >= f.rpcBatchSize { rpcBatchGroups = append(rpcBatchGroups, rpcBatch) - rpcBatch = make([]rpc.BatchElem, 0, f.rpcBatchSize) + rpcBatch = []rpc.BatchElem{} } } if len(rpcBatch) > 0 { rpcBatchGroups = append(rpcBatchGroups, rpcBatch) } - finalizedReceipts := make([]*evmtypes.Receipt, 0, len(blockNumToReceiptsMap)) + var finalizedReceipts []Receipt for _, rpcBatch := range rpcBatchGroups { err := f.client.BatchCallContext(ctx, rpcBatch) if err != nil { @@ -362,13 +271,8 @@ func (f *evmFinalizer) batchCheckReceiptHashesOnchain(ctx context.Context, block finalizedReceipts = append(finalizedReceipts, receipt) } else { // Log error if a transaction is marked as confirmed with a receipt older than the finalized block - // This scenario could potentially be caused by a stale receipt stored for a re-org'd transaction - f.lggr.Debugw("found confirmed transaction with re-org'd receipt", "receipt", receipt, "onchainBlockHash", head.BlockHash().String()) - err = f.txStore.DeleteReceiptByTxHash(ctx, receipt.GetTxHash()) - // Log error but allow process to continue so other transactions can still be marked as finalized - if err != nil { - f.lggr.Errorw("failed to delete receipt", "receipt", receipt) - } + // This scenario could potentially point to a re-org'd transaction the Confirmer has lost track of + f.lggr.Errorw("found confirmed transaction with re-org'd receipt older than finalized block", "receipt", receipt, "onchainBlockHash", head.BlockHash().String()) } } } @@ -376,293 +280,16 @@ func (f *evmFinalizer) batchCheckReceiptHashesOnchain(ctx context.Context, block return finalizedReceipts } -func (f *evmFinalizer) FetchAndStoreReceipts(ctx context.Context, head, latestFinalizedHead *evmtypes.Head) error { - attempts, err := f.txStore.FindAttemptsRequiringReceiptFetch(ctx, f.chainID) - if err != nil { - return fmt.Errorf("failed to fetch broadcasted attempts for confirmed transactions: %w", err) - } - if len(attempts) == 0 { - return nil - } - promTxAttemptCount.WithLabelValues(f.chainID.String()).Set(float64(len(attempts))) - - f.lggr.Debugw(fmt.Sprintf("Fetching receipts for %v transaction attempts", len(attempts))) - - batchSize := f.rpcBatchSize - if batchSize == 0 { - batchSize = len(attempts) - } - allReceipts := make([]*evmtypes.Receipt, 0, len(attempts)) - errorList := make([]error, 0, len(attempts)) - for i := 0; i < len(attempts); i += batchSize { - j := i + batchSize - if j > len(attempts) { - j = len(attempts) - } - batch := attempts[i:j] - - receipts, fetchErr := f.batchFetchReceipts(ctx, batch) - if fetchErr != nil { - errorList = append(errorList, fetchErr) - continue - } - - allReceipts = append(allReceipts, receipts...) - - if err = f.txStore.SaveFetchedReceipts(ctx, receipts); err != nil { - errorList = append(errorList, err) - continue - } - } - if len(errorList) > 0 { - return errors.Join(errorList...) - } - - oldTxIDs := findOldTxIDsWithoutReceipts(attempts, allReceipts, latestFinalizedHead) - // Process old transactions that never received receipts and need to be marked as fatal - err = f.ProcessOldTxsWithoutReceipts(ctx, oldTxIDs, head, latestFinalizedHead) - if err != nil { - return err - } - - return nil -} - -func (f *evmFinalizer) batchFetchReceipts(ctx context.Context, attempts []TxAttempt) (receipts []*evmtypes.Receipt, err error) { - // Metadata is required to determine whether a tx is forwarded or not. - if f.forwardersEnabled { - err = f.txStore.PreloadTxes(ctx, attempts) - if err != nil { - return nil, fmt.Errorf("Confirmer#batchFetchReceipts error loading txs for attempts: %w", err) - } - } - - txReceipts, txErrs, err := f.client.BatchGetReceipts(ctx, attempts) - if err != nil { - return nil, err - } - - for i, receipt := range txReceipts { - attempt := attempts[i] - err := txErrs[i] - if err != nil { - f.lggr.Error("FetchReceipts failed") - continue - } - ok := f.validateReceipt(ctx, receipt, attempt) - if !ok { - continue - } - receipts = append(receipts, receipt) - } - - return -} - -// Note this function will increment promRevertedTxCount upon receiving a reverted transaction receipt -func (f *evmFinalizer) validateReceipt(ctx context.Context, receipt *evmtypes.Receipt, attempt TxAttempt) bool { - l := attempt.Tx.GetLogger(f.lggr).With("txHash", attempt.Hash.String(), "txAttemptID", attempt.ID, - "txID", attempt.TxID, "nonce", attempt.Tx.Sequence, - ) - - if receipt == nil { - // NOTE: This should never happen, but it seems safer to check - // regardless to avoid a potential panic - l.AssumptionViolation("got nil receipt") - return false - } - - if receipt.IsZero() { - l.Debug("Still waiting for receipt") - return false - } - - l = l.With("blockHash", receipt.GetBlockHash().String(), "status", receipt.GetStatus(), "transactionIndex", receipt.GetTransactionIndex()) - - if receipt.IsUnmined() { - l.Debug("Got receipt for transaction but it's still in the mempool and not included in a block yet") - return false - } - - l.Debugw("Got receipt for transaction", "blockNumber", receipt.GetBlockNumber(), "feeUsed", receipt.GetFeeUsed()) - - if receipt.GetTxHash().String() != attempt.Hash.String() { - l.Errorf("Invariant violation, expected receipt with hash %s to have same hash as attempt with hash %s", receipt.GetTxHash().String(), attempt.Hash.String()) - return false - } - - if receipt.GetBlockNumber() == nil { - l.Error("Invariant violation, receipt was missing block number") - return false - } - - if receipt.GetStatus() == 0 { - if receipt.GetRevertReason() != nil { - l.Warnw("transaction reverted on-chain", "hash", receipt.GetTxHash(), "revertReason", *receipt.GetRevertReason()) - } else { - rpcError, errExtract := f.client.CallContract(ctx, attempt, receipt.GetBlockNumber()) - if errExtract == nil { - l.Warnw("transaction reverted on-chain", "hash", receipt.GetTxHash(), "rpcError", rpcError.String()) - } else { - l.Warnw("transaction reverted on-chain unable to extract revert reason", "hash", receipt.GetTxHash(), "err", errExtract) - } - } - // This might increment more than once e.g. in case of re-orgs going back and forth we might re-fetch the same receipt - promRevertedTxCount.WithLabelValues(f.chainID.String()).Add(1) - } else { - promNumSuccessfulTxs.WithLabelValues(f.chainID.String()).Add(1) - } - - // This is only recording forwarded tx that were mined and have a status. - // Counters are prone to being inaccurate due to re-orgs. - if f.forwardersEnabled { - meta, metaErr := attempt.Tx.GetMeta() - if metaErr == nil && meta != nil && meta.FwdrDestAddress != nil { - // promFwdTxCount takes two labels, chainID and a boolean of whether a tx was successful or not. - promFwdTxCount.WithLabelValues(f.chainID.String(), strconv.FormatBool(receipt.GetStatus() != 0)).Add(1) - } - } - return true -} - -// ResumePendingTaskRuns issues callbacks to task runs that are pending waiting for receipts -func (f *evmFinalizer) ResumePendingTaskRuns(ctx context.Context, latest, finalized int64) error { - if f.resumeCallback == nil { - return nil - } - receiptsPlus, err := f.txStore.FindTxesPendingCallback(ctx, latest, finalized, f.chainID) - - if err != nil { - return err - } - - if len(receiptsPlus) > 0 { - f.lggr.Debugf("Resuming %d task runs pending receipt", len(receiptsPlus)) - } else { - f.lggr.Debug("No task runs to resume") - } - for _, data := range receiptsPlus { - var taskErr error - var output interface{} - if data.FailOnRevert && data.Receipt.GetStatus() == 0 { - taskErr = fmt.Errorf("transaction %s reverted on-chain", data.Receipt.GetTxHash()) - } else { - output = data.Receipt - } - - f.lggr.Debugw("Callback: resuming tx with receipt", "output", output, "taskErr", taskErr, "pipelineTaskRunID", data.ID) - if err := f.resumeCallback(ctx, data.ID, output, taskErr); err != nil { - return fmt.Errorf("failed to resume suspended pipeline run: %w", err) - } - // Mark tx as having completed callback - if err := f.txStore.UpdateTxCallbackCompleted(ctx, data.ID, f.chainID); err != nil { - return err - } - } - - return nil -} - -func (f *evmFinalizer) ProcessOldTxsWithoutReceipts(ctx context.Context, oldTxIDs []int64, head, latestFinalizedHead *evmtypes.Head) error { - if len(oldTxIDs) == 0 { - return nil - } - oldTxs, err := f.txStore.FindTxesByIDs(ctx, oldTxIDs, f.chainID) - if err != nil { - return fmt.Errorf("failed to find transactions with IDs: %w", err) - } - - errorList := make([]error, 0, len(oldTxs)) - for _, oldTx := range oldTxs { - f.lggr.Criticalw(fmt.Sprintf("transaction with ID %v expired without ever getting a receipt for any of our attempts. "+ - "Current block height is %d, transaction was broadcast before finalized block %d. This transaction may not have not been sent and will be marked as fatally errored. "+ - "This can happen if there is another instance of chainlink running that is using the same private key, or if "+ - "an external wallet has been used to send a transaction from account %s with nonce %s."+ - " Please note that Chainlink requires exclusive ownership of it's private keys and sharing keys across multiple"+ - " chainlink instances, or using the chainlink keys with an external wallet is NOT SUPPORTED and WILL lead to missed transactions", - oldTx.ID, head.BlockNumber(), latestFinalizedHead.BlockNumber(), oldTx.FromAddress, oldTx.Sequence), "txID", oldTx.ID, "sequence", oldTx.Sequence, "fromAddress", oldTx.FromAddress) - - // Signal pending tasks for these transactions as failed - // Store errors and continue to allow all transactions a chance to be signaled - if f.resumeCallback != nil && oldTx.PipelineTaskRunID.Valid && oldTx.SignalCallback && !oldTx.CallbackCompleted { - err = f.resumeCallback(ctx, oldTx.PipelineTaskRunID.UUID, nil, errors.New(ErrCouldNotGetReceipt)) - switch { - case errors.Is(err, sql.ErrNoRows): - f.lggr.Debugw("callback missing or already resumed", "etxID", oldTx.ID) - case err != nil: - errorList = append(errorList, fmt.Errorf("failed to resume pipeline for ID %s: %w", oldTx.PipelineTaskRunID.UUID.String(), err)) - continue - default: - // Mark tx as having completed callback - if err = f.txStore.UpdateTxCallbackCompleted(ctx, oldTx.PipelineTaskRunID.UUID, f.chainID); err != nil { - errorList = append(errorList, fmt.Errorf("failed to update callback as complete for tx ID %d: %w", oldTx.ID, err)) - continue - } - } - } - - // Mark transaction as fatal error and delete attempts to prevent further receipt fetching - oldTx.Error = null.StringFrom(ErrCouldNotGetReceipt) - if err = f.txStore.UpdateTxFatalErrorAndDeleteAttempts(ctx, oldTx); err != nil { - errorList = append(errorList, fmt.Errorf("failed to mark tx with ID %d as fatal: %w", oldTx.ID, err)) - } - } - if len(errorList) > 0 { - return errors.Join(errorList...) - } - - return nil -} - -// findOldTxIDsWithoutReceipts finds IDs for transactions without receipts and attempts broadcasted at or before the finalized head -func findOldTxIDsWithoutReceipts(attempts []TxAttempt, receipts []*evmtypes.Receipt, latestFinalizedHead *evmtypes.Head) []int64 { - if len(attempts) == 0 { - return nil - } - txIDToAttemptsMap := make(map[int64][]TxAttempt) - hashToReceiptMap := make(map[common.Hash]bool) - // Store all receipts hashes in a map to easily access which attempt hash has a receipt - for _, receipt := range receipts { - hashToReceiptMap[receipt.TxHash] = true - } - // Store all attempts in a map of tx ID to attempts - for _, attempt := range attempts { - txIDToAttemptsMap[attempt.TxID] = append(txIDToAttemptsMap[attempt.TxID], attempt) - } - - // Determine which transactions still do not have a receipt and if all of their attempts are older or equal to the latest finalized head - oldTxIDs := make([]int64, 0, len(txIDToAttemptsMap)) - for txID, attempts := range txIDToAttemptsMap { - hasReceipt := false - hasAttemptAfterFinalizedHead := false - for _, attempt := range attempts { - if _, exists := hashToReceiptMap[attempt.Hash]; exists { - hasReceipt = true - break - } - if attempt.BroadcastBeforeBlockNum != nil && *attempt.BroadcastBeforeBlockNum > latestFinalizedHead.BlockNumber() { - hasAttemptAfterFinalizedHead = true - break - } - } - if hasReceipt || hasAttemptAfterFinalizedHead { - continue - } - oldTxIDs = append(oldTxIDs, txID) - } - return oldTxIDs -} - -// buildTxHashList builds list of transaction hashes from receipts considered finalized -func (f *evmFinalizer) buildTxHashList(finalizedReceipts []*evmtypes.Receipt) []common.Hash { - txHashes := make([]common.Hash, len(finalizedReceipts)) +// Build list of transaction IDs +func (f *evmFinalizer) buildReceiptIdList(finalizedReceipts []Receipt) []int64 { + receiptIds := make([]int64, len(finalizedReceipts)) for i, receipt := range finalizedReceipts { f.lggr.Debugw("transaction considered finalized", "txHash", receipt.TxHash.String(), - "receiptBlockNum", receipt.BlockNumber.Int64(), + "receiptBlockNum", receipt.BlockNumber, "receiptBlockHash", receipt.BlockHash.String(), ) - txHashes[i] = receipt.TxHash + receiptIds[i] = receipt.ID } - return txHashes + return receiptIds } diff --git a/core/chains/evm/txmgr/finalizer_test.go b/core/chains/evm/txmgr/finalizer_test.go index 76338d31836..b91121d773f 100644 --- a/core/chains/evm/txmgr/finalizer_test.go +++ b/core/chains/evm/txmgr/finalizer_test.go @@ -1,10 +1,7 @@ package txmgr_test import ( - "context" - "encoding/json" "errors" - "fmt" "math/big" "testing" "time" @@ -13,7 +10,6 @@ import ( "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/rpc" "github.com/google/uuid" - "github.com/stretchr/testify/assert" "github.com/stretchr/testify/mock" "github.com/stretchr/testify/require" @@ -22,17 +18,13 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" txmgrcommon "github.com/smartcontractkit/chainlink/v2/common/txmgr" - txmgrtypes "github.com/smartcontractkit/chainlink/v2/common/txmgr/types" - "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/headtracker" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/testutils" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr" evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" - "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest" - "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/evmtest" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest" ) @@ -44,7 +36,6 @@ func TestFinalizer_MarkTxFinalized(t *testing.T) { ethKeyStore := cltest.NewKeyStore(t, db).Eth() feeLimit := uint64(10_000) ethClient := testutils.NewEthClientMockWithDefaultChain(t) - txmClient := txmgr.NewEvmTxmClient(ethClient, nil) rpcBatchSize := uint32(1) ht := headtracker.NewSimulatedHeadTracker(ethClient, true, 0) @@ -60,7 +51,7 @@ func TestFinalizer_MarkTxFinalized(t *testing.T) { head.Parent.Store(h99) t.Run("returns not finalized for tx with receipt newer than finalized block", func(t *testing.T) { - finalizer := txmgr.NewEvmFinalizer(logger.Test(t), testutils.FixtureChainID, rpcBatchSize, false, txStore, txmClient, ht) + finalizer := txmgr.NewEvmFinalizer(logger.Test(t), testutils.FixtureChainID, rpcBatchSize, txStore, ethClient, ht) servicetest.Run(t, finalizer) idempotencyKey := uuid.New().String() @@ -89,8 +80,8 @@ func TestFinalizer_MarkTxFinalized(t *testing.T) { require.Equal(t, txmgrcommon.TxConfirmed, tx.State) }) - t.Run("returns not finalized for tx with receipt re-org'd out and deletes stale receipt", func(t *testing.T) { - finalizer := txmgr.NewEvmFinalizer(logger.Test(t), testutils.FixtureChainID, rpcBatchSize, false, txStore, txmClient, ht) + t.Run("returns not finalized for tx with receipt re-org'd out", func(t *testing.T) { + finalizer := txmgr.NewEvmFinalizer(logger.Test(t), testutils.FixtureChainID, rpcBatchSize, txStore, ethClient, ht) servicetest.Run(t, finalizer) idempotencyKey := uuid.New().String() @@ -117,12 +108,10 @@ func TestFinalizer_MarkTxFinalized(t *testing.T) { tx, err = txStore.FindTxWithIdempotencyKey(ctx, idempotencyKey, testutils.FixtureChainID) require.NoError(t, err) require.Equal(t, txmgrcommon.TxConfirmed, tx.State) - require.Len(t, tx.TxAttempts, 1) - require.Empty(t, tx.TxAttempts[0].Receipts) }) t.Run("returns finalized for tx with receipt in a finalized block", func(t *testing.T) { - finalizer := txmgr.NewEvmFinalizer(logger.Test(t), testutils.FixtureChainID, rpcBatchSize, false, txStore, txmClient, ht) + finalizer := txmgr.NewEvmFinalizer(logger.Test(t), testutils.FixtureChainID, rpcBatchSize, txStore, ethClient, ht) servicetest.Run(t, finalizer) idempotencyKey := uuid.New().String() @@ -152,7 +141,7 @@ func TestFinalizer_MarkTxFinalized(t *testing.T) { }) t.Run("returns finalized for tx with receipt older than block history depth", func(t *testing.T) { - finalizer := txmgr.NewEvmFinalizer(logger.Test(t), testutils.FixtureChainID, rpcBatchSize, false, txStore, txmClient, ht) + finalizer := txmgr.NewEvmFinalizer(logger.Test(t), testutils.FixtureChainID, rpcBatchSize, txStore, ethClient, ht) servicetest.Run(t, finalizer) idempotencyKey := uuid.New().String() @@ -192,7 +181,7 @@ func TestFinalizer_MarkTxFinalized(t *testing.T) { // Separate batch calls will be made for each tx due to RPC batch size set to 1 when finalizer initialized above ethClient.On("BatchCallContext", mock.Anything, mock.IsType([]rpc.BatchElem{})).Run(func(args mock.Arguments) { rpcElements := args.Get(1).([]rpc.BatchElem) - require.Len(t, rpcElements, 1) + require.Equal(t, 1, len(rpcElements)) require.Equal(t, "eth_getBlockByNumber", rpcElements[0].Method) require.Equal(t, false, rpcElements[0].Args[1]) @@ -220,7 +209,7 @@ func TestFinalizer_MarkTxFinalized(t *testing.T) { }) t.Run("returns error if failed to retrieve latest head in headtracker", func(t *testing.T) { - finalizer := txmgr.NewEvmFinalizer(logger.Test(t), testutils.FixtureChainID, rpcBatchSize, false, txStore, txmClient, ht) + finalizer := txmgr.NewEvmFinalizer(logger.Test(t), testutils.FixtureChainID, rpcBatchSize, txStore, ethClient, ht) servicetest.Run(t, finalizer) ethClient.On("HeadByNumber", mock.Anything, mock.Anything).Return(nil, errors.New("failed to get latest head")).Once() @@ -229,7 +218,7 @@ func TestFinalizer_MarkTxFinalized(t *testing.T) { }) t.Run("returns error if failed to calculate latest finalized head in headtracker", func(t *testing.T) { - finalizer := txmgr.NewEvmFinalizer(logger.Test(t), testutils.FixtureChainID, rpcBatchSize, false, txStore, txmClient, ht) + finalizer := txmgr.NewEvmFinalizer(logger.Test(t), testutils.FixtureChainID, rpcBatchSize, txStore, ethClient, ht) servicetest.Run(t, finalizer) ethClient.On("HeadByNumber", mock.Anything, mock.Anything).Return(head, nil).Once() @@ -250,917 +239,3 @@ func insertTxAndAttemptWithIdempotencyKey(t *testing.T, txStore txmgr.TestEvmTxS require.NoError(t, err) return attempt.Hash } - -func TestFinalizer_ResumePendingRuns(t *testing.T) { - t.Parallel() - ctx := tests.Context(t) - db := pgtest.NewSqlxDB(t) - txStore := cltest.NewTestTxStore(t, db) - ethKeyStore := cltest.NewKeyStore(t, db).Eth() - ethClient := testutils.NewEthClientMockWithDefaultChain(t) - txmClient := txmgr.NewEvmTxmClient(ethClient, nil) - rpcBatchSize := uint32(1) - ht := headtracker.NewSimulatedHeadTracker(ethClient, true, 0) - - grandParentHead := &evmtypes.Head{ - Number: 8, - Hash: testutils.NewHash(), - } - parentHead := &evmtypes.Head{ - Hash: testutils.NewHash(), - Number: 9, - } - parentHead.Parent.Store(grandParentHead) - head := evmtypes.Head{ - Hash: testutils.NewHash(), - Number: 10, - } - head.Parent.Store(parentHead) - - minConfirmations := int64(2) - - pgtest.MustExec(t, db, `SET CONSTRAINTS fk_pipeline_runs_pruning_key DEFERRED`) - pgtest.MustExec(t, db, `SET CONSTRAINTS pipeline_runs_pipeline_spec_id_fkey DEFERRED`) - - t.Run("doesn't process task runs that are not suspended (possibly already previously resumed)", func(t *testing.T) { - _, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore) - finalizer := txmgr.NewEvmFinalizer(logger.Test(t), testutils.FixtureChainID, rpcBatchSize, false, txStore, txmClient, ht) - finalizer.SetResumeCallback(func(context.Context, uuid.UUID, interface{}, error) error { - t.Fatal("No value expected") - return nil - }) - servicetest.Run(t, finalizer) - - run := cltest.MustInsertPipelineRun(t, db) - tr := cltest.MustInsertUnfinishedPipelineTaskRun(t, db, run.ID) - - etx := cltest.MustInsertConfirmedEthTxWithLegacyAttempt(t, txStore, 1, 1, fromAddress) - mustInsertEthReceipt(t, txStore, head.Number-minConfirmations, head.Hash, etx.TxAttempts[0].Hash) - // Setting both signal_callback and callback_completed to TRUE to simulate a completed pipeline task - // It would only be in a state past suspended if the resume callback was called and callback_completed was set to TRUE - pgtest.MustExec(t, db, `UPDATE evm.txes SET pipeline_task_run_id = $1, min_confirmations = $2, signal_callback = TRUE, callback_completed = TRUE WHERE id = $3`, &tr.ID, minConfirmations, etx.ID) - - err := finalizer.ResumePendingTaskRuns(ctx, head.BlockNumber(), 0) - require.NoError(t, err) - }) - - t.Run("doesn't process task runs where the receipt is younger than minConfirmations", func(t *testing.T) { - _, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore) - finalizer := txmgr.NewEvmFinalizer(logger.Test(t), testutils.FixtureChainID, rpcBatchSize, false, txStore, txmClient, ht) - finalizer.SetResumeCallback(func(context.Context, uuid.UUID, interface{}, error) error { - t.Fatal("No value expected") - return nil - }) - servicetest.Run(t, finalizer) - - run := cltest.MustInsertPipelineRun(t, db) - tr := cltest.MustInsertUnfinishedPipelineTaskRun(t, db, run.ID) - - etx := cltest.MustInsertConfirmedEthTxWithLegacyAttempt(t, txStore, 2, 1, fromAddress) - mustInsertEthReceipt(t, txStore, head.Number, head.Hash, etx.TxAttempts[0].Hash) - - pgtest.MustExec(t, db, `UPDATE evm.txes SET pipeline_task_run_id = $1, min_confirmations = $2, signal_callback = TRUE WHERE id = $3`, &tr.ID, minConfirmations, etx.ID) - - err := finalizer.ResumePendingTaskRuns(ctx, head.BlockNumber(), 0) - require.NoError(t, err) - }) - - t.Run("processes transactions with receipts older than minConfirmations", func(t *testing.T) { - ch := make(chan interface{}) - nonce := evmtypes.Nonce(3) - var err error - _, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore) - finalizer := txmgr.NewEvmFinalizer(logger.Test(t), testutils.FixtureChainID, rpcBatchSize, false, txStore, txmClient, ht) - finalizer.SetResumeCallback(func(ctx context.Context, id uuid.UUID, value interface{}, thisErr error) error { - err = thisErr - ch <- value - return nil - }) - servicetest.Run(t, finalizer) - - run := cltest.MustInsertPipelineRun(t, db) - tr := cltest.MustInsertUnfinishedPipelineTaskRun(t, db, run.ID) - pgtest.MustExec(t, db, `UPDATE pipeline_runs SET state = 'suspended' WHERE id = $1`, run.ID) - - etx := cltest.MustInsertConfirmedEthTxWithLegacyAttempt(t, txStore, int64(nonce), 1, fromAddress) - pgtest.MustExec(t, db, `UPDATE evm.txes SET meta='{"FailOnRevert": true}'`) - receipt := mustInsertEthReceipt(t, txStore, head.Number-minConfirmations, head.Hash, etx.TxAttempts[0].Hash) - - pgtest.MustExec(t, db, `UPDATE evm.txes SET pipeline_task_run_id = $1, min_confirmations = $2, signal_callback = TRUE WHERE id = $3`, &tr.ID, minConfirmations, etx.ID) - - done := make(chan struct{}) - t.Cleanup(func() { <-done }) - go func() { - defer close(done) - err2 := finalizer.ResumePendingTaskRuns(ctx, head.BlockNumber(), 0) - assert.NoError(t, err2) - - // Retrieve Tx to check if callback completed flag was set to true - updateTx, err3 := txStore.FindTxWithSequence(ctx, fromAddress, nonce) - assert.NoError(t, err3) - assert.True(t, updateTx.CallbackCompleted) - }() - - select { - case data := <-ch: - require.NoError(t, err) - - require.IsType(t, &evmtypes.Receipt{}, data) - r := data.(*evmtypes.Receipt) - require.Equal(t, receipt.TxHash, r.TxHash) - - case <-time.After(time.Second): - t.Fatal("no value received") - } - }) - - pgtest.MustExec(t, db, `DELETE FROM pipeline_runs`) - - t.Run("processes transactions with receipt older than minConfirmations that reverted", func(t *testing.T) { - type data struct { - value any - error - } - ch := make(chan data) - nonce := evmtypes.Nonce(4) - _, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore) - finalizer := txmgr.NewEvmFinalizer(logger.Test(t), testutils.FixtureChainID, rpcBatchSize, false, txStore, txmClient, ht) - finalizer.SetResumeCallback(func(ctx context.Context, id uuid.UUID, value interface{}, err error) error { - ch <- data{value, err} - return nil - }) - servicetest.Run(t, finalizer) - - run := cltest.MustInsertPipelineRun(t, db) - tr := cltest.MustInsertUnfinishedPipelineTaskRun(t, db, run.ID) - pgtest.MustExec(t, db, `UPDATE pipeline_runs SET state = 'suspended' WHERE id = $1`, run.ID) - - etx := cltest.MustInsertConfirmedEthTxWithLegacyAttempt(t, txStore, int64(nonce), 1, fromAddress) - pgtest.MustExec(t, db, `UPDATE evm.txes SET meta='{"FailOnRevert": true}'`) - - // receipt is not passed through as a value since it reverted and caused an error - mustInsertRevertedEthReceipt(t, txStore, head.Number-minConfirmations, head.Hash, etx.TxAttempts[0].Hash) - - pgtest.MustExec(t, db, `UPDATE evm.txes SET pipeline_task_run_id = $1, min_confirmations = $2, signal_callback = TRUE WHERE id = $3`, &tr.ID, minConfirmations, etx.ID) - - done := make(chan struct{}) - t.Cleanup(func() { <-done }) - go func() { - defer close(done) - err2 := finalizer.ResumePendingTaskRuns(ctx, head.BlockNumber(), 0) - assert.NoError(t, err2) - - // Retrieve Tx to check if callback completed flag was set to true - updateTx, err3 := txStore.FindTxWithSequence(ctx, fromAddress, nonce) - assert.NoError(t, err3) - assert.True(t, updateTx.CallbackCompleted) - }() - - select { - case data := <-ch: - require.Error(t, data.error) - - require.EqualError(t, data.error, fmt.Sprintf("transaction %s reverted on-chain", etx.TxAttempts[0].Hash.String())) - - require.Nil(t, data.value) - - case <-time.After(tests.WaitTimeout(t)): - t.Fatal("no value received") - } - }) - - t.Run("does not mark callback complete if callback fails", func(t *testing.T) { - nonce := evmtypes.Nonce(5) - _, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore) - finalizer := txmgr.NewEvmFinalizer(logger.Test(t), testutils.FixtureChainID, rpcBatchSize, false, txStore, txmClient, ht) - finalizer.SetResumeCallback(func(ctx context.Context, id uuid.UUID, value interface{}, err error) error { - return errors.New("error") - }) - servicetest.Run(t, finalizer) - - run := cltest.MustInsertPipelineRun(t, db) - tr := cltest.MustInsertUnfinishedPipelineTaskRun(t, db, run.ID) - - etx := cltest.MustInsertConfirmedEthTxWithLegacyAttempt(t, txStore, int64(nonce), 1, fromAddress) - mustInsertEthReceipt(t, txStore, head.Number-minConfirmations, head.Hash, etx.TxAttempts[0].Hash) - pgtest.MustExec(t, db, `UPDATE evm.txes SET pipeline_task_run_id = $1, min_confirmations = $2, signal_callback = TRUE WHERE id = $3`, &tr.ID, minConfirmations, etx.ID) - - err := finalizer.ResumePendingTaskRuns(ctx, head.BlockNumber(), 0) - require.Error(t, err) - - // Retrieve Tx to check if callback completed flag was left unchanged - updateTx, err := txStore.FindTxWithSequence(ctx, fromAddress, nonce) - require.NoError(t, err) - require.False(t, updateTx.CallbackCompleted) - }) -} - -func TestFinalizer_FetchAndStoreReceipts(t *testing.T) { - t.Parallel() - ctx := tests.Context(t) - cfg := configtest.NewTestGeneralConfig(t) - config := evmtest.NewChainScopedConfig(t, cfg) - ethClient := testutils.NewEthClientMockWithDefaultChain(t) - txmClient := txmgr.NewEvmTxmClient(ethClient, nil) - rpcBatchSize := config.EVM().RPCDefaultBatchSize() - ht := headtracker.NewSimulatedHeadTracker(ethClient, true, 0) - - latestFinalizedHead := &evmtypes.Head{ - Hash: utils.NewHash(), - Number: 99, - } - latestFinalizedHead.IsFinalized.Store(true) - head := &evmtypes.Head{ - Hash: utils.NewHash(), - Number: 100, - } - head.Parent.Store(latestFinalizedHead) - - t.Run("does nothing if no confirmed transactions without receipts found", func(t *testing.T) { - db := pgtest.NewSqlxDB(t) - txStore := cltest.NewTestTxStore(t, db) - ethKeyStore := cltest.NewKeyStore(t, db).Eth() - _, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore) - finalizer := txmgr.NewEvmFinalizer(logger.Test(t), testutils.FixtureChainID, config.EVM().RPCDefaultBatchSize(), false, txStore, txmClient, ht) - - mustInsertFatalErrorEthTx(t, txStore, fromAddress) - mustInsertInProgressEthTx(t, txStore, 0, fromAddress) - mustInsertUnconfirmedEthTxWithInsufficientEthAttempt(t, txStore, 2, fromAddress) - mustCreateUnstartedGeneratedTx(t, txStore, fromAddress, config.EVM().ChainID()) - // Insert confirmed transactions with receipt and multiple attempts to ensure none of the attempts are picked up - etx := mustInsertConfirmedEthTxWithReceipt(t, txStore, fromAddress, 3, head.Number) - attempt := newBroadcastLegacyEthTxAttempt(t, etx.ID, 2) - require.NoError(t, txStore.InsertTxAttempt(ctx, &attempt)) - - require.NoError(t, finalizer.FetchAndStoreReceipts(ctx, head, latestFinalizedHead)) - }) - - t.Run("fetches receipt for confirmed transaction without a receipt", func(t *testing.T) { - db := pgtest.NewSqlxDB(t) - txStore := cltest.NewTestTxStore(t, db) - ethKeyStore := cltest.NewKeyStore(t, db).Eth() - _, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore) - finalizer := txmgr.NewEvmFinalizer(logger.Test(t), testutils.FixtureChainID, rpcBatchSize, false, txStore, txmClient, ht) - // Insert confirmed transaction without receipt - etx := cltest.MustInsertConfirmedEthTxWithLegacyAttempt(t, txStore, 0, head.Number, fromAddress) - // Transaction not confirmed yet, receipt is nil - ethClient.On("BatchCallContext", mock.Anything, mock.MatchedBy(func(b []rpc.BatchElem) bool { - return len(b) == 1 && cltest.BatchElemMatchesParams(b[0], etx.TxAttempts[0].Hash, "eth_getTransactionReceipt") - })).Return(nil).Run(func(args mock.Arguments) { - elems := args.Get(1).([]rpc.BatchElem) - elems[0].Result = &evmtypes.Receipt{} - }).Once() - - require.NoError(t, finalizer.FetchAndStoreReceipts(ctx, head, latestFinalizedHead)) - - var err error - etx, err = txStore.FindTxWithAttempts(ctx, etx.ID) - require.NoError(t, err) - require.Len(t, etx.TxAttempts, 1) - attempt := etx.TxAttempts[0] - require.NoError(t, err) - require.Empty(t, attempt.Receipts) - }) - - t.Run("saves nothing if returned receipt does not match the attempt", func(t *testing.T) { - db := pgtest.NewSqlxDB(t) - txStore := cltest.NewTestTxStore(t, db) - ethKeyStore := cltest.NewKeyStore(t, db).Eth() - _, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore) - finalizer := txmgr.NewEvmFinalizer(logger.Test(t), testutils.FixtureChainID, rpcBatchSize, false, txStore, txmClient, ht) - // Insert confirmed transaction without receipt - etx := cltest.MustInsertConfirmedEthTxWithLegacyAttempt(t, txStore, 0, head.Number, fromAddress) - txmReceipt := evmtypes.Receipt{ - TxHash: testutils.NewHash(), - BlockHash: testutils.NewHash(), - BlockNumber: big.NewInt(42), - TransactionIndex: uint(1), - } - - // First transaction confirmed - ethClient.On("BatchCallContext", mock.Anything, mock.MatchedBy(func(b []rpc.BatchElem) bool { - return len(b) == 1 && cltest.BatchElemMatchesParams(b[0], etx.TxAttempts[0].Hash, "eth_getTransactionReceipt") - })).Return(nil).Run(func(args mock.Arguments) { - elems := args.Get(1).([]rpc.BatchElem) - *(elems[0].Result.(*evmtypes.Receipt)) = txmReceipt - }).Once() - - // No error because it is merely logged - require.NoError(t, finalizer.FetchAndStoreReceipts(ctx, head, latestFinalizedHead)) - - var err error - etx, err = txStore.FindTxWithAttempts(ctx, etx.ID) - require.NoError(t, err) - require.Len(t, etx.TxAttempts, 1) - require.Empty(t, etx.TxAttempts[0].Receipts) - }) - - t.Run("saves nothing if query returns error", func(t *testing.T) { - db := pgtest.NewSqlxDB(t) - txStore := cltest.NewTestTxStore(t, db) - ethKeyStore := cltest.NewKeyStore(t, db).Eth() - _, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore) - finalizer := txmgr.NewEvmFinalizer(logger.Test(t), testutils.FixtureChainID, rpcBatchSize, false, txStore, txmClient, ht) - // Insert confirmed transaction without receipt - etx := cltest.MustInsertConfirmedEthTxWithLegacyAttempt(t, txStore, 0, head.Number, fromAddress) - txmReceipt := evmtypes.Receipt{ - TxHash: etx.TxAttempts[0].Hash, - BlockHash: testutils.NewHash(), - BlockNumber: big.NewInt(42), - TransactionIndex: uint(1), - } - - // Batch receipt call fails - ethClient.On("BatchCallContext", mock.Anything, mock.MatchedBy(func(b []rpc.BatchElem) bool { - return len(b) == 1 && cltest.BatchElemMatchesParams(b[0], etx.TxAttempts[0].Hash, "eth_getTransactionReceipt") - })).Return(nil).Run(func(args mock.Arguments) { - elems := args.Get(1).([]rpc.BatchElem) - *(elems[0].Result.(*evmtypes.Receipt)) = txmReceipt - elems[0].Error = errors.New("foo") - }).Once() - - // No error because it is merely logged - require.NoError(t, finalizer.FetchAndStoreReceipts(ctx, head, latestFinalizedHead)) - - var err error - etx, err = txStore.FindTxWithAttempts(ctx, etx.ID) - require.NoError(t, err) - require.Len(t, etx.TxAttempts, 1) - require.Empty(t, etx.TxAttempts[0].Receipts) - }) - - t.Run("saves valid receipt returned by client", func(t *testing.T) { - db := pgtest.NewSqlxDB(t) - txStore := cltest.NewTestTxStore(t, db) - ethKeyStore := cltest.NewKeyStore(t, db).Eth() - _, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore) - finalizer := txmgr.NewEvmFinalizer(logger.Test(t), testutils.FixtureChainID, rpcBatchSize, false, txStore, txmClient, ht) - // Insert confirmed transaction without receipt - etx1 := cltest.MustInsertConfirmedEthTxWithLegacyAttempt(t, txStore, 0, head.Number, fromAddress) - // Insert confirmed transaction without receipt - etx2 := cltest.MustInsertConfirmedEthTxWithLegacyAttempt(t, txStore, 1, head.Number, fromAddress) - txmReceipt := evmtypes.Receipt{ - TxHash: etx1.TxAttempts[0].Hash, - BlockHash: testutils.NewHash(), - BlockNumber: big.NewInt(42), - TransactionIndex: uint(1), - Status: uint64(1), - } - - ethClient.On("BatchCallContext", mock.Anything, mock.MatchedBy(func(b []rpc.BatchElem) bool { - return len(b) == 2 && - cltest.BatchElemMatchesParams(b[0], etx1.TxAttempts[0].Hash, "eth_getTransactionReceipt") && - cltest.BatchElemMatchesParams(b[1], etx2.TxAttempts[0].Hash, "eth_getTransactionReceipt") - })).Return(nil).Run(func(args mock.Arguments) { - elems := args.Get(1).([]rpc.BatchElem) - // First transaction confirmed - *(elems[0].Result.(*evmtypes.Receipt)) = txmReceipt - // Second transaction still unconfirmed - elems[1].Result = &evmtypes.Receipt{} - }).Once() - - require.NoError(t, finalizer.FetchAndStoreReceipts(ctx, head, latestFinalizedHead)) - - // Check that the receipt was saved - var err error - etx1, err = txStore.FindTxWithAttempts(ctx, etx1.ID) - require.NoError(t, err) - - require.Equal(t, txmgrcommon.TxConfirmed, etx1.State) - require.Len(t, etx1.TxAttempts, 1) - attempt := etx1.TxAttempts[0] - require.Len(t, attempt.Receipts, 1) - receipt := attempt.Receipts[0] - require.Equal(t, txmReceipt.TxHash, receipt.GetTxHash()) - require.Equal(t, txmReceipt.BlockHash, receipt.GetBlockHash()) - require.Equal(t, txmReceipt.BlockNumber.Int64(), receipt.GetBlockNumber().Int64()) - require.Equal(t, txmReceipt.TransactionIndex, receipt.GetTransactionIndex()) - - receiptJSON, err := json.Marshal(txmReceipt) - require.NoError(t, err) - - storedReceiptJSON, err := json.Marshal(receipt) - require.NoError(t, err) - require.JSONEq(t, string(receiptJSON), string(storedReceiptJSON)) - }) - - t.Run("fetches and saves receipts for several attempts in gas price order", func(t *testing.T) { - db := pgtest.NewSqlxDB(t) - txStore := cltest.NewTestTxStore(t, db) - ethKeyStore := cltest.NewKeyStore(t, db).Eth() - _, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore) - finalizer := txmgr.NewEvmFinalizer(logger.Test(t), testutils.FixtureChainID, rpcBatchSize, false, txStore, txmClient, ht) - // Insert confirmed transaction without receipt - etx := cltest.MustInsertConfirmedEthTxWithLegacyAttempt(t, txStore, 0, head.Number, fromAddress) - attempt1 := etx.TxAttempts[0] - attempt2 := newBroadcastLegacyEthTxAttempt(t, etx.ID, 2) - attempt3 := newBroadcastLegacyEthTxAttempt(t, etx.ID, 3) - - // Insert order deliberately reversed to test sorting by gas price - require.NoError(t, txStore.InsertTxAttempt(ctx, &attempt3)) - require.NoError(t, txStore.InsertTxAttempt(ctx, &attempt2)) - - txmReceipt := evmtypes.Receipt{ - TxHash: attempt2.Hash, - BlockHash: testutils.NewHash(), - BlockNumber: big.NewInt(42), - TransactionIndex: uint(1), - Status: uint64(1), - } - - ethClient.On("BatchCallContext", mock.Anything, mock.MatchedBy(func(b []rpc.BatchElem) bool { - return len(b) == 3 && - cltest.BatchElemMatchesParams(b[2], attempt1.Hash, "eth_getTransactionReceipt") && - cltest.BatchElemMatchesParams(b[1], attempt2.Hash, "eth_getTransactionReceipt") && - cltest.BatchElemMatchesParams(b[0], attempt3.Hash, "eth_getTransactionReceipt") - })).Return(nil).Run(func(args mock.Arguments) { - elems := args.Get(1).([]rpc.BatchElem) - // Most expensive attempt still unconfirmed - elems[2].Result = &evmtypes.Receipt{} - // Second most expensive attempt is confirmed - *(elems[1].Result.(*evmtypes.Receipt)) = txmReceipt - // Cheapest attempt still unconfirmed - elems[0].Result = &evmtypes.Receipt{} - }).Once() - - require.NoError(t, finalizer.FetchAndStoreReceipts(ctx, head, latestFinalizedHead)) - - // Check that the receipt was stored - var err error - etx, err = txStore.FindTxWithAttempts(ctx, etx.ID) - require.NoError(t, err) - - require.Equal(t, txmgrcommon.TxConfirmed, etx.State) - require.Len(t, etx.TxAttempts, 3) - require.Empty(t, etx.TxAttempts[0].Receipts) - require.Len(t, etx.TxAttempts[1].Receipts, 1) - require.Empty(t, etx.TxAttempts[2].Receipts) - }) - - t.Run("ignores receipt missing BlockHash that comes from querying parity too early", func(t *testing.T) { - db := pgtest.NewSqlxDB(t) - txStore := cltest.NewTestTxStore(t, db) - ethKeyStore := cltest.NewKeyStore(t, db).Eth() - _, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore) - finalizer := txmgr.NewEvmFinalizer(logger.Test(t), testutils.FixtureChainID, rpcBatchSize, false, txStore, txmClient, ht) - // Insert confirmed transaction without receipt - etx := cltest.MustInsertConfirmedEthTxWithLegacyAttempt(t, txStore, 0, head.Number, fromAddress) - receipt := evmtypes.Receipt{ - TxHash: etx.TxAttempts[0].Hash, - Status: uint64(1), - } - ethClient.On("BatchCallContext", mock.Anything, mock.MatchedBy(func(b []rpc.BatchElem) bool { - return len(b) == 1 && cltest.BatchElemMatchesParams(b[0], etx.TxAttempts[0].Hash, "eth_getTransactionReceipt") - })).Return(nil).Run(func(args mock.Arguments) { - elems := args.Get(1).([]rpc.BatchElem) - *(elems[0].Result.(*evmtypes.Receipt)) = receipt - }).Once() - - require.NoError(t, finalizer.FetchAndStoreReceipts(ctx, head, latestFinalizedHead)) - - // No receipt, but no error either - var err error - etx, err = txStore.FindTxWithAttempts(ctx, etx.ID) - require.NoError(t, err) - - require.Equal(t, txmgrcommon.TxConfirmed, etx.State) - require.Len(t, etx.TxAttempts, 1) - attempt := etx.TxAttempts[0] - require.Empty(t, attempt.Receipts) - }) - - t.Run("does not panic if receipt has BlockHash but is missing some other fields somehow", func(t *testing.T) { - db := pgtest.NewSqlxDB(t) - txStore := cltest.NewTestTxStore(t, db) - ethKeyStore := cltest.NewKeyStore(t, db).Eth() - _, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore) - finalizer := txmgr.NewEvmFinalizer(logger.Test(t), testutils.FixtureChainID, rpcBatchSize, false, txStore, txmClient, ht) - // Insert confirmed transaction without receipt - etx := cltest.MustInsertConfirmedEthTxWithLegacyAttempt(t, txStore, 0, head.Number, fromAddress) - // NOTE: This should never happen, but we shouldn't panic regardless - receipt := evmtypes.Receipt{ - TxHash: etx.TxAttempts[0].Hash, - BlockHash: testutils.NewHash(), - Status: uint64(1), - } - ethClient.On("BatchCallContext", mock.Anything, mock.MatchedBy(func(b []rpc.BatchElem) bool { - return len(b) == 1 && cltest.BatchElemMatchesParams(b[0], etx.TxAttempts[0].Hash, "eth_getTransactionReceipt") - })).Return(nil).Run(func(args mock.Arguments) { - elems := args.Get(1).([]rpc.BatchElem) - *(elems[0].Result.(*evmtypes.Receipt)) = receipt - }).Once() - - require.NoError(t, finalizer.FetchAndStoreReceipts(ctx, head, latestFinalizedHead)) - - // No receipt, but no error either - etx, err := txStore.FindTxWithAttempts(ctx, etx.ID) - require.NoError(t, err) - - require.Equal(t, txmgrcommon.TxConfirmed, etx.State) - require.Len(t, etx.TxAttempts, 1) - attempt := etx.TxAttempts[0] - require.Empty(t, attempt.Receipts) - }) - - t.Run("simulate on revert", func(t *testing.T) { - db := pgtest.NewSqlxDB(t) - txStore := cltest.NewTestTxStore(t, db) - ethKeyStore := cltest.NewKeyStore(t, db).Eth() - _, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore) - finalizer := txmgr.NewEvmFinalizer(logger.Test(t), testutils.FixtureChainID, rpcBatchSize, false, txStore, txmClient, ht) - // Insert confirmed transaction without receipt - etx := cltest.MustInsertConfirmedEthTxWithLegacyAttempt(t, txStore, 0, head.Number, fromAddress) - attempt := etx.TxAttempts[0] - txmReceipt := evmtypes.Receipt{ - TxHash: attempt.Hash, - BlockHash: testutils.NewHash(), - BlockNumber: big.NewInt(42), - TransactionIndex: uint(1), - Status: uint64(0), - } - - // First attempt is confirmed and reverted - ethClient.On("BatchCallContext", mock.Anything, mock.MatchedBy(func(b []rpc.BatchElem) bool { - return len(b) == 1 && cltest.BatchElemMatchesParams(b[0], attempt.Hash, "eth_getTransactionReceipt") - })).Return(nil).Run(func(args mock.Arguments) { - elems := args.Get(1).([]rpc.BatchElem) - // First attempt still unconfirmed - *(elems[0].Result.(*evmtypes.Receipt)) = txmReceipt - }).Once() - data, err := utils.ABIEncode(`[{"type":"uint256"}]`, big.NewInt(10)) - require.NoError(t, err) - sig := utils.Keccak256Fixed([]byte(`MyError(uint256)`)) - ethClient.On("CallContract", mock.Anything, mock.Anything, mock.Anything).Return(nil, &client.JsonError{ - Code: 1, - Message: "reverted", - Data: utils.ConcatBytes(sig[:4], data), - }).Once() - - // Do the thing - require.NoError(t, finalizer.FetchAndStoreReceipts(ctx, head, latestFinalizedHead)) - - // Check that the state was updated - etx, err = txStore.FindTxWithAttempts(ctx, etx.ID) - require.NoError(t, err) - attempt = etx.TxAttempts[0] - require.Equal(t, txmgrtypes.TxAttemptBroadcast, attempt.State) - require.NotNil(t, attempt.BroadcastBeforeBlockNum) - // Check receipts - require.Len(t, attempt.Receipts, 1) - }) - - t.Run("find receipt for old transaction, avoid marking as fatal", func(t *testing.T) { - db := pgtest.NewSqlxDB(t) - txStore := cltest.NewTestTxStore(t, db) - ethKeyStore := cltest.NewKeyStore(t, db).Eth() - _, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore) - finalizer := txmgr.NewEvmFinalizer(logger.Test(t), testutils.FixtureChainID, rpcBatchSize, true, txStore, txmClient, ht) - - // Insert confirmed transaction without receipt - etx := cltest.MustInsertConfirmedEthTxWithLegacyAttempt(t, txStore, 0, latestFinalizedHead.Number, fromAddress) - - txmReceipt := evmtypes.Receipt{ - TxHash: etx.TxAttempts[0].Hash, - BlockHash: testutils.NewHash(), - BlockNumber: big.NewInt(42), - TransactionIndex: uint(1), - Status: uint64(1), - } - - // Transaction receipt is nil - ethClient.On("BatchCallContext", mock.Anything, mock.MatchedBy(func(b []rpc.BatchElem) bool { - return len(b) == 1 && cltest.BatchElemMatchesParams(b[0], etx.TxAttempts[0].Hash, "eth_getTransactionReceipt") - })).Return(nil).Run(func(args mock.Arguments) { - elems := args.Get(1).([]rpc.BatchElem) - *(elems[0].Result.(*evmtypes.Receipt)) = txmReceipt - }).Once() - - require.NoError(t, finalizer.FetchAndStoreReceipts(ctx, head, latestFinalizedHead)) - - // Check that transaction was picked up as old and marked as fatal - var err error - etx, err = txStore.FindTxWithAttempts(ctx, etx.ID) - require.NoError(t, err) - require.Equal(t, txmgrcommon.TxConfirmed, etx.State) - }) - - t.Run("old transaction failed to find receipt, marked as fatal", func(t *testing.T) { - db := pgtest.NewSqlxDB(t) - txStore := cltest.NewTestTxStore(t, db) - ethKeyStore := cltest.NewKeyStore(t, db).Eth() - _, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore) - finalizer := txmgr.NewEvmFinalizer(logger.Test(t), testutils.FixtureChainID, rpcBatchSize, true, txStore, txmClient, ht) - - // Insert confirmed transaction without receipt - etx := cltest.MustInsertConfirmedEthTxWithLegacyAttempt(t, txStore, 0, latestFinalizedHead.Number, fromAddress) - - // Transaction receipt is nil - ethClient.On("BatchCallContext", mock.Anything, mock.MatchedBy(func(b []rpc.BatchElem) bool { - return len(b) == 1 && cltest.BatchElemMatchesParams(b[0], etx.TxAttempts[0].Hash, "eth_getTransactionReceipt") - })).Return(nil).Run(func(args mock.Arguments) { - elems := args.Get(1).([]rpc.BatchElem) - elems[0].Result = &evmtypes.Receipt{} - }).Once() - - require.NoError(t, finalizer.FetchAndStoreReceipts(ctx, head, latestFinalizedHead)) - - // Check that transaction was picked up as old and marked as fatal - var err error - etx, err = txStore.FindTxWithAttempts(ctx, etx.ID) - require.NoError(t, err) - require.Equal(t, txmgrcommon.TxFatalError, etx.State) - require.Equal(t, txmgr.ErrCouldNotGetReceipt, etx.Error.String) - }) -} - -func TestFinalizer_FetchAndStoreReceipts_batching(t *testing.T) { - t.Parallel() - ctx := tests.Context(t) - ethClient := testutils.NewEthClientMockWithDefaultChain(t) - txmClient := txmgr.NewEvmTxmClient(ethClient, nil) - ht := headtracker.NewSimulatedHeadTracker(ethClient, true, 0) - - latestFinalizedHead := &evmtypes.Head{ - Hash: utils.NewHash(), - Number: 99, - } - latestFinalizedHead.IsFinalized.Store(true) - head := &evmtypes.Head{ - Hash: utils.NewHash(), - Number: 100, - } - head.Parent.Store(latestFinalizedHead) - - t.Run("fetch and store receipts from multiple batch calls", func(t *testing.T) { - db := pgtest.NewSqlxDB(t) - txStore := cltest.NewTestTxStore(t, db) - ethKeyStore := cltest.NewKeyStore(t, db).Eth() - _, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore) - rpcBatchSize := uint32(2) - finalizer := txmgr.NewEvmFinalizer(logger.Test(t), testutils.FixtureChainID, rpcBatchSize, false, txStore, txmClient, ht) - - // Insert confirmed transaction without receipt - etx := mustInsertConfirmedEthTx(t, txStore, 0, fromAddress) - - var attempts []txmgr.TxAttempt - // Total of 5 attempts should lead to 3 batched fetches (2, 2, 1)v - for i := 0; i < 5; i++ { - attempt := newBroadcastLegacyEthTxAttempt(t, etx.ID, int64(i+2)) - attempt.BroadcastBeforeBlockNum = &head.Number - require.NoError(t, txStore.InsertTxAttempt(ctx, &attempt)) - attempts = append(attempts, attempt) - } - - ethClient.On("BatchCallContext", mock.Anything, mock.MatchedBy(func(b []rpc.BatchElem) bool { - return len(b) == 2 && - cltest.BatchElemMatchesParams(b[0], attempts[4].Hash, "eth_getTransactionReceipt") && - cltest.BatchElemMatchesParams(b[1], attempts[3].Hash, "eth_getTransactionReceipt") - })).Return(nil).Run(func(args mock.Arguments) { - elems := args.Get(1).([]rpc.BatchElem) - elems[0].Result = &evmtypes.Receipt{} - elems[1].Result = &evmtypes.Receipt{} - }).Once() - ethClient.On("BatchCallContext", mock.Anything, mock.MatchedBy(func(b []rpc.BatchElem) bool { - return len(b) == 2 && - cltest.BatchElemMatchesParams(b[0], attempts[2].Hash, "eth_getTransactionReceipt") && - cltest.BatchElemMatchesParams(b[1], attempts[1].Hash, "eth_getTransactionReceipt") - })).Return(nil).Run(func(args mock.Arguments) { - elems := args.Get(1).([]rpc.BatchElem) - elems[0].Result = &evmtypes.Receipt{} - elems[1].Result = &evmtypes.Receipt{} - }).Once() - ethClient.On("BatchCallContext", mock.Anything, mock.MatchedBy(func(b []rpc.BatchElem) bool { - return len(b) == 1 && - cltest.BatchElemMatchesParams(b[0], attempts[0].Hash, "eth_getTransactionReceipt") - })).Return(nil).Run(func(args mock.Arguments) { - elems := args.Get(1).([]rpc.BatchElem) - elems[0].Result = &evmtypes.Receipt{} - }).Once() - - require.NoError(t, finalizer.FetchAndStoreReceipts(ctx, head, latestFinalizedHead)) - }) - - t.Run("continue to fetch and store receipts after batch call error", func(t *testing.T) { - db := pgtest.NewSqlxDB(t) - txStore := cltest.NewTestTxStore(t, db) - ethKeyStore := cltest.NewKeyStore(t, db).Eth() - _, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore) - rpcBatchSize := uint32(1) - finalizer := txmgr.NewEvmFinalizer(logger.Test(t), testutils.FixtureChainID, rpcBatchSize, false, txStore, txmClient, ht) - - // Insert confirmed transactions without receipts - etx1 := cltest.MustInsertConfirmedEthTxWithLegacyAttempt(t, txStore, 0, head.Number, fromAddress) - etx2 := cltest.MustInsertConfirmedEthTxWithLegacyAttempt(t, txStore, 1, head.Number, fromAddress) - - txmReceipt := evmtypes.Receipt{ - TxHash: etx2.TxAttempts[0].Hash, - BlockHash: testutils.NewHash(), - BlockNumber: big.NewInt(42), - TransactionIndex: uint(1), - Status: uint64(1), - } - - ethClient.On("BatchCallContext", mock.Anything, mock.MatchedBy(func(b []rpc.BatchElem) bool { - return len(b) == 1 && - cltest.BatchElemMatchesParams(b[0], etx1.TxAttempts[0].Hash, "eth_getTransactionReceipt") - })).Return(errors.New("batch call failed")).Once() - ethClient.On("BatchCallContext", mock.Anything, mock.MatchedBy(func(b []rpc.BatchElem) bool { - return len(b) == 1 && - cltest.BatchElemMatchesParams(b[0], etx2.TxAttempts[0].Hash, "eth_getTransactionReceipt") - })).Return(nil).Run(func(args mock.Arguments) { - elems := args.Get(1).([]rpc.BatchElem) - *(elems[0].Result.(*evmtypes.Receipt)) = txmReceipt // confirmed - }).Once() - - // Returns error due to batch call failure - require.Error(t, finalizer.FetchAndStoreReceipts(ctx, head, latestFinalizedHead)) - - // Still fetches and stores receipt for later batch call that succeeds - var err error - etx2, err = txStore.FindTxWithAttempts(ctx, etx2.ID) - require.NoError(t, err) - require.Len(t, etx2.TxAttempts, 1) - attempt := etx2.TxAttempts[0] - require.Len(t, attempt.Receipts, 1) - }) -} - -func TestFinalizer_FetchAndStoreReceipts_HandlesNonFwdTxsWithForwardingEnabled(t *testing.T) { - t.Parallel() - ctx := tests.Context(t) - ethClient := testutils.NewEthClientMockWithDefaultChain(t) - txmClient := txmgr.NewEvmTxmClient(ethClient, nil) - ht := headtracker.NewSimulatedHeadTracker(ethClient, true, 0) - - latestFinalizedHead := &evmtypes.Head{ - Hash: utils.NewHash(), - Number: 99, - } - latestFinalizedHead.IsFinalized.Store(true) - head := &evmtypes.Head{ - Hash: utils.NewHash(), - Number: 100, - } - head.Parent.Store(latestFinalizedHead) - - db := pgtest.NewSqlxDB(t) - txStore := cltest.NewTestTxStore(t, db) - ethKeyStore := cltest.NewKeyStore(t, db).Eth() - _, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore) - finalizer := txmgr.NewEvmFinalizer(logger.Test(t), testutils.FixtureChainID, 1, true, txStore, txmClient, ht) - - // tx is not forwarded and doesn't have meta set. Confirmer should handle nil meta values - etx := mustInsertConfirmedEthTx(t, txStore, 0, fromAddress) - attempt := newBroadcastLegacyEthTxAttempt(t, etx.ID, 2) - attempt.Tx.Meta = nil - require.NoError(t, txStore.InsertTxAttempt(ctx, &attempt)) - dbtx, err := txStore.FindTxWithAttempts(ctx, etx.ID) - require.NoError(t, err) - require.Empty(t, dbtx.TxAttempts[0].Receipts) - - txmReceipt := evmtypes.Receipt{ - TxHash: attempt.Hash, - BlockHash: testutils.NewHash(), - BlockNumber: big.NewInt(42), - TransactionIndex: uint(1), - Status: uint64(1), - } - - ethClient.On("BatchCallContext", mock.Anything, mock.MatchedBy(func(b []rpc.BatchElem) bool { - return len(b) == 1 && - cltest.BatchElemMatchesParams(b[0], attempt.Hash, "eth_getTransactionReceipt") - })).Return(nil).Run(func(args mock.Arguments) { - elems := args.Get(1).([]rpc.BatchElem) - *(elems[0].Result.(*evmtypes.Receipt)) = txmReceipt // confirmed - }).Once() - - require.NoError(t, finalizer.FetchAndStoreReceipts(ctx, head, latestFinalizedHead)) - - // Check receipt is inserted correctly. - dbtx, err = txStore.FindTxWithAttempts(ctx, etx.ID) - require.NoError(t, err) - require.Len(t, dbtx.TxAttempts[0].Receipts, 1) -} - -func TestFinalizer_ProcessOldTxsWithoutReceipts(t *testing.T) { - t.Parallel() - ctx := tests.Context(t) - ethClient := testutils.NewEthClientMockWithDefaultChain(t) - txmClient := txmgr.NewEvmTxmClient(ethClient, nil) - ht := headtracker.NewSimulatedHeadTracker(ethClient, true, 0) - - latestFinalizedHead := &evmtypes.Head{ - Hash: utils.NewHash(), - Number: 99, - } - latestFinalizedHead.IsFinalized.Store(true) - head := &evmtypes.Head{ - Hash: utils.NewHash(), - Number: 100, - } - head.Parent.Store(latestFinalizedHead) - - t.Run("does nothing if no old transactions found", func(t *testing.T) { - db := pgtest.NewSqlxDB(t) - txStore := cltest.NewTestTxStore(t, db) - finalizer := txmgr.NewEvmFinalizer(logger.Test(t), testutils.FixtureChainID, 1, true, txStore, txmClient, ht) - require.NoError(t, finalizer.ProcessOldTxsWithoutReceipts(ctx, []int64{}, head, latestFinalizedHead)) - }) - - t.Run("marks multiple old transactions as fatal", func(t *testing.T) { - db := pgtest.NewSqlxDB(t) - txStore := cltest.NewTestTxStore(t, db) - ethKeyStore := cltest.NewKeyStore(t, db).Eth() - _, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore) - finalizer := txmgr.NewEvmFinalizer(logger.Test(t), testutils.FixtureChainID, 1, true, txStore, txmClient, ht) - - // Insert confirmed transaction without receipt - etx1 := cltest.MustInsertConfirmedEthTxWithLegacyAttempt(t, txStore, 0, latestFinalizedHead.Number, fromAddress) - etx2 := cltest.MustInsertConfirmedEthTxWithLegacyAttempt(t, txStore, 1, latestFinalizedHead.Number, fromAddress) - - etxIDs := []int64{etx1.ID, etx2.ID} - require.NoError(t, finalizer.ProcessOldTxsWithoutReceipts(ctx, etxIDs, head, latestFinalizedHead)) - - // Check transactions marked as fatal - var err error - etx1, err = txStore.FindTxWithAttempts(ctx, etx1.ID) - require.NoError(t, err) - require.Equal(t, txmgrcommon.TxFatalError, etx1.State) - require.Equal(t, txmgr.ErrCouldNotGetReceipt, etx1.Error.String) - - etx2, err = txStore.FindTxWithAttempts(ctx, etx2.ID) - require.NoError(t, err) - require.Equal(t, txmgrcommon.TxFatalError, etx2.State) - require.Equal(t, txmgr.ErrCouldNotGetReceipt, etx2.Error.String) - }) - - t.Run("marks old transaction as fatal, resumes pending task as failed", func(t *testing.T) { - db := pgtest.NewSqlxDB(t) - txStore := cltest.NewTestTxStore(t, db) - ethKeyStore := cltest.NewKeyStore(t, db).Eth() - _, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore) - finalizer := txmgr.NewEvmFinalizer(logger.Test(t), testutils.FixtureChainID, 1, true, txStore, txmClient, ht) - finalizer.SetResumeCallback(func(context.Context, uuid.UUID, interface{}, error) error { return nil }) - - // Insert confirmed transaction with pending task run - etx := cltest.NewEthTx(fromAddress) - etx.State = txmgrcommon.TxConfirmed - n := evmtypes.Nonce(0) - etx.Sequence = &n - now := time.Now() - etx.BroadcastAt = &now - etx.InitialBroadcastAt = &now - etx.SignalCallback = true - etx.PipelineTaskRunID = uuid.NullUUID{UUID: uuid.New(), Valid: true} - require.NoError(t, txStore.InsertTx(tests.Context(t), &etx)) - - attempt := newBroadcastLegacyEthTxAttempt(t, etx.ID, 0) - attempt.BroadcastBeforeBlockNum = &latestFinalizedHead.Number // set broadcast time to finalized block num - require.NoError(t, txStore.InsertTxAttempt(ctx, &attempt)) - - require.NoError(t, finalizer.ProcessOldTxsWithoutReceipts(ctx, []int64{etx.ID}, head, latestFinalizedHead)) - - // Check transaction marked as fatal - var err error - etx, err = txStore.FindTxWithAttempts(ctx, etx.ID) - require.NoError(t, err) - require.Equal(t, txmgrcommon.TxFatalError, etx.State) - require.Equal(t, txmgr.ErrCouldNotGetReceipt, etx.Error.String) - require.True(t, etx.CallbackCompleted) - }) - - t.Run("transaction stays confirmed if failure to resume pending task", func(t *testing.T) { - db := pgtest.NewSqlxDB(t) - txStore := cltest.NewTestTxStore(t, db) - ethKeyStore := cltest.NewKeyStore(t, db).Eth() - _, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore) - finalizer := txmgr.NewEvmFinalizer(logger.Test(t), testutils.FixtureChainID, 1, true, txStore, txmClient, ht) - finalizer.SetResumeCallback(func(context.Context, uuid.UUID, interface{}, error) error { return errors.New("failure") }) - - // Insert confirmed transaction with pending task run - etx := cltest.NewEthTx(fromAddress) - etx.State = txmgrcommon.TxConfirmed - n := evmtypes.Nonce(0) - etx.Sequence = &n - now := time.Now() - etx.BroadcastAt = &now - etx.InitialBroadcastAt = &now - etx.SignalCallback = true - etx.PipelineTaskRunID = uuid.NullUUID{UUID: uuid.New(), Valid: true} - require.NoError(t, txStore.InsertTx(tests.Context(t), &etx)) - - attempt := newBroadcastLegacyEthTxAttempt(t, etx.ID, 0) - attempt.BroadcastBeforeBlockNum = &latestFinalizedHead.Number // set broadcast time to finalized block num - require.NoError(t, txStore.InsertTxAttempt(ctx, &attempt)) - - // Expect error since resuming pending task failed - require.Error(t, finalizer.ProcessOldTxsWithoutReceipts(ctx, []int64{etx.ID}, head, latestFinalizedHead)) - - // Check transaction marked as fatal - var err error - etx, err = txStore.FindTxWithAttempts(ctx, etx.ID) - require.NoError(t, err) - require.Equal(t, txmgrcommon.TxConfirmed, etx.State) - require.False(t, etx.CallbackCompleted) - }) -} diff --git a/core/chains/evm/txmgr/mocks/evm_tx_store.go b/core/chains/evm/txmgr/mocks/evm_tx_store.go index ca98ad6ceb8..fa324d84fb5 100644 --- a/core/chains/evm/txmgr/mocks/evm_tx_store.go +++ b/core/chains/evm/txmgr/mocks/evm_tx_store.go @@ -446,130 +446,24 @@ func (_c *EvmTxStore_DeleteInProgressAttempt_Call) RunAndReturn(run func(context return _c } -// DeleteReceiptByTxHash provides a mock function with given fields: ctx, txHash -func (_m *EvmTxStore) DeleteReceiptByTxHash(ctx context.Context, txHash common.Hash) error { - ret := _m.Called(ctx, txHash) - - if len(ret) == 0 { - panic("no return value specified for DeleteReceiptByTxHash") - } - - var r0 error - if rf, ok := ret.Get(0).(func(context.Context, common.Hash) error); ok { - r0 = rf(ctx, txHash) - } else { - r0 = ret.Error(0) - } - - return r0 -} - -// EvmTxStore_DeleteReceiptByTxHash_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'DeleteReceiptByTxHash' -type EvmTxStore_DeleteReceiptByTxHash_Call struct { - *mock.Call -} - -// DeleteReceiptByTxHash is a helper method to define mock.On call -// - ctx context.Context -// - txHash common.Hash -func (_e *EvmTxStore_Expecter) DeleteReceiptByTxHash(ctx interface{}, txHash interface{}) *EvmTxStore_DeleteReceiptByTxHash_Call { - return &EvmTxStore_DeleteReceiptByTxHash_Call{Call: _e.mock.On("DeleteReceiptByTxHash", ctx, txHash)} -} - -func (_c *EvmTxStore_DeleteReceiptByTxHash_Call) Run(run func(ctx context.Context, txHash common.Hash)) *EvmTxStore_DeleteReceiptByTxHash_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context), args[1].(common.Hash)) - }) - return _c -} - -func (_c *EvmTxStore_DeleteReceiptByTxHash_Call) Return(_a0 error) *EvmTxStore_DeleteReceiptByTxHash_Call { - _c.Call.Return(_a0) - return _c -} - -func (_c *EvmTxStore_DeleteReceiptByTxHash_Call) RunAndReturn(run func(context.Context, common.Hash) error) *EvmTxStore_DeleteReceiptByTxHash_Call { - _c.Call.Return(run) - return _c -} - -// FindAttemptsRequiringReceiptFetch provides a mock function with given fields: ctx, chainID -func (_m *EvmTxStore) FindAttemptsRequiringReceiptFetch(ctx context.Context, chainID *big.Int) ([]txmgr.TxAttempt, error) { - ret := _m.Called(ctx, chainID) - - if len(ret) == 0 { - panic("no return value specified for FindAttemptsRequiringReceiptFetch") - } - - var r0 []txmgr.TxAttempt - var r1 error - if rf, ok := ret.Get(0).(func(context.Context, *big.Int) ([]txmgr.TxAttempt, error)); ok { - return rf(ctx, chainID) - } - if rf, ok := ret.Get(0).(func(context.Context, *big.Int) []txmgr.TxAttempt); ok { - r0 = rf(ctx, chainID) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).([]txmgr.TxAttempt) - } - } - - if rf, ok := ret.Get(1).(func(context.Context, *big.Int) error); ok { - r1 = rf(ctx, chainID) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// EvmTxStore_FindAttemptsRequiringReceiptFetch_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'FindAttemptsRequiringReceiptFetch' -type EvmTxStore_FindAttemptsRequiringReceiptFetch_Call struct { - *mock.Call -} - -// FindAttemptsRequiringReceiptFetch is a helper method to define mock.On call -// - ctx context.Context -// - chainID *big.Int -func (_e *EvmTxStore_Expecter) FindAttemptsRequiringReceiptFetch(ctx interface{}, chainID interface{}) *EvmTxStore_FindAttemptsRequiringReceiptFetch_Call { - return &EvmTxStore_FindAttemptsRequiringReceiptFetch_Call{Call: _e.mock.On("FindAttemptsRequiringReceiptFetch", ctx, chainID)} -} - -func (_c *EvmTxStore_FindAttemptsRequiringReceiptFetch_Call) Run(run func(ctx context.Context, chainID *big.Int)) *EvmTxStore_FindAttemptsRequiringReceiptFetch_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context), args[1].(*big.Int)) - }) - return _c -} - -func (_c *EvmTxStore_FindAttemptsRequiringReceiptFetch_Call) Return(hashes []txmgr.TxAttempt, err error) *EvmTxStore_FindAttemptsRequiringReceiptFetch_Call { - _c.Call.Return(hashes, err) - return _c -} - -func (_c *EvmTxStore_FindAttemptsRequiringReceiptFetch_Call) RunAndReturn(run func(context.Context, *big.Int) ([]txmgr.TxAttempt, error)) *EvmTxStore_FindAttemptsRequiringReceiptFetch_Call { - _c.Call.Return(run) - return _c -} - // FindConfirmedTxesReceipts provides a mock function with given fields: ctx, finalizedBlockNum, chainID -func (_m *EvmTxStore) FindConfirmedTxesReceipts(ctx context.Context, finalizedBlockNum int64, chainID *big.Int) ([]*evmtypes.Receipt, error) { +func (_m *EvmTxStore) FindConfirmedTxesReceipts(ctx context.Context, finalizedBlockNum int64, chainID *big.Int) ([]txmgr.Receipt, error) { ret := _m.Called(ctx, finalizedBlockNum, chainID) if len(ret) == 0 { panic("no return value specified for FindConfirmedTxesReceipts") } - var r0 []*evmtypes.Receipt + var r0 []txmgr.Receipt var r1 error - if rf, ok := ret.Get(0).(func(context.Context, int64, *big.Int) ([]*evmtypes.Receipt, error)); ok { + if rf, ok := ret.Get(0).(func(context.Context, int64, *big.Int) ([]txmgr.Receipt, error)); ok { return rf(ctx, finalizedBlockNum, chainID) } - if rf, ok := ret.Get(0).(func(context.Context, int64, *big.Int) []*evmtypes.Receipt); ok { + if rf, ok := ret.Get(0).(func(context.Context, int64, *big.Int) []txmgr.Receipt); ok { r0 = rf(ctx, finalizedBlockNum, chainID) } else { if ret.Get(0) != nil { - r0 = ret.Get(0).([]*evmtypes.Receipt) + r0 = ret.Get(0).([]txmgr.Receipt) } } @@ -602,12 +496,12 @@ func (_c *EvmTxStore_FindConfirmedTxesReceipts_Call) Run(run func(ctx context.Co return _c } -func (_c *EvmTxStore_FindConfirmedTxesReceipts_Call) Return(receipts []*evmtypes.Receipt, err error) *EvmTxStore_FindConfirmedTxesReceipts_Call { +func (_c *EvmTxStore_FindConfirmedTxesReceipts_Call) Return(receipts []txmgr.Receipt, err error) *EvmTxStore_FindConfirmedTxesReceipts_Call { _c.Call.Return(receipts, err) return _c } -func (_c *EvmTxStore_FindConfirmedTxesReceipts_Call) RunAndReturn(run func(context.Context, int64, *big.Int) ([]*evmtypes.Receipt, error)) *EvmTxStore_FindConfirmedTxesReceipts_Call { +func (_c *EvmTxStore_FindConfirmedTxesReceipts_Call) RunAndReturn(run func(context.Context, int64, *big.Int) ([]txmgr.Receipt, error)) *EvmTxStore_FindConfirmedTxesReceipts_Call { _c.Call.Return(run) return _c } @@ -726,9 +620,9 @@ func (_c *EvmTxStore_FindEarliestUnconfirmedTxAttemptBlock_Call) RunAndReturn(ru return _c } -// FindLatestSequence provides a mock function with given fields: ctx, fromAddress, chainID -func (_m *EvmTxStore) FindLatestSequence(ctx context.Context, fromAddress common.Address, chainID *big.Int) (evmtypes.Nonce, error) { - ret := _m.Called(ctx, fromAddress, chainID) +// FindLatestSequence provides a mock function with given fields: ctx, fromAddress, chainId +func (_m *EvmTxStore) FindLatestSequence(ctx context.Context, fromAddress common.Address, chainId *big.Int) (evmtypes.Nonce, error) { + ret := _m.Called(ctx, fromAddress, chainId) if len(ret) == 0 { panic("no return value specified for FindLatestSequence") @@ -737,16 +631,16 @@ func (_m *EvmTxStore) FindLatestSequence(ctx context.Context, fromAddress common var r0 evmtypes.Nonce var r1 error if rf, ok := ret.Get(0).(func(context.Context, common.Address, *big.Int) (evmtypes.Nonce, error)); ok { - return rf(ctx, fromAddress, chainID) + return rf(ctx, fromAddress, chainId) } if rf, ok := ret.Get(0).(func(context.Context, common.Address, *big.Int) evmtypes.Nonce); ok { - r0 = rf(ctx, fromAddress, chainID) + r0 = rf(ctx, fromAddress, chainId) } else { r0 = ret.Get(0).(evmtypes.Nonce) } if rf, ok := ret.Get(1).(func(context.Context, common.Address, *big.Int) error); ok { - r1 = rf(ctx, fromAddress, chainID) + r1 = rf(ctx, fromAddress, chainId) } else { r1 = ret.Error(1) } @@ -762,12 +656,12 @@ type EvmTxStore_FindLatestSequence_Call struct { // FindLatestSequence is a helper method to define mock.On call // - ctx context.Context // - fromAddress common.Address -// - chainID *big.Int -func (_e *EvmTxStore_Expecter) FindLatestSequence(ctx interface{}, fromAddress interface{}, chainID interface{}) *EvmTxStore_FindLatestSequence_Call { - return &EvmTxStore_FindLatestSequence_Call{Call: _e.mock.On("FindLatestSequence", ctx, fromAddress, chainID)} +// - chainId *big.Int +func (_e *EvmTxStore_Expecter) FindLatestSequence(ctx interface{}, fromAddress interface{}, chainId interface{}) *EvmTxStore_FindLatestSequence_Call { + return &EvmTxStore_FindLatestSequence_Call{Call: _e.mock.On("FindLatestSequence", ctx, fromAddress, chainId)} } -func (_c *EvmTxStore_FindLatestSequence_Call) Run(run func(ctx context.Context, fromAddress common.Address, chainID *big.Int)) *EvmTxStore_FindLatestSequence_Call { +func (_c *EvmTxStore_FindLatestSequence_Call) Run(run func(ctx context.Context, fromAddress common.Address, chainId *big.Int)) *EvmTxStore_FindLatestSequence_Call { _c.Call.Run(func(args mock.Arguments) { run(args[0].(context.Context), args[1].(common.Address), args[2].(*big.Int)) }) @@ -844,72 +738,63 @@ func (_c *EvmTxStore_FindNextUnstartedTransactionFromAddress_Call) RunAndReturn( return _c } -// FindReorgOrIncludedTxs provides a mock function with given fields: ctx, fromAddress, nonce, chainID -func (_m *EvmTxStore) FindReorgOrIncludedTxs(ctx context.Context, fromAddress common.Address, nonce evmtypes.Nonce, chainID *big.Int) ([]*types.Tx[*big.Int, common.Address, common.Hash, common.Hash, evmtypes.Nonce, gas.EvmFee], []*types.Tx[*big.Int, common.Address, common.Hash, common.Hash, evmtypes.Nonce, gas.EvmFee], error) { - ret := _m.Called(ctx, fromAddress, nonce, chainID) +// FindTransactionsConfirmedInBlockRange provides a mock function with given fields: ctx, highBlockNumber, lowBlockNumber, chainID +func (_m *EvmTxStore) FindTransactionsConfirmedInBlockRange(ctx context.Context, highBlockNumber int64, lowBlockNumber int64, chainID *big.Int) ([]*types.Tx[*big.Int, common.Address, common.Hash, common.Hash, evmtypes.Nonce, gas.EvmFee], error) { + ret := _m.Called(ctx, highBlockNumber, lowBlockNumber, chainID) if len(ret) == 0 { - panic("no return value specified for FindReorgOrIncludedTxs") + panic("no return value specified for FindTransactionsConfirmedInBlockRange") } var r0 []*types.Tx[*big.Int, common.Address, common.Hash, common.Hash, evmtypes.Nonce, gas.EvmFee] - var r1 []*types.Tx[*big.Int, common.Address, common.Hash, common.Hash, evmtypes.Nonce, gas.EvmFee] - var r2 error - if rf, ok := ret.Get(0).(func(context.Context, common.Address, evmtypes.Nonce, *big.Int) ([]*types.Tx[*big.Int, common.Address, common.Hash, common.Hash, evmtypes.Nonce, gas.EvmFee], []*types.Tx[*big.Int, common.Address, common.Hash, common.Hash, evmtypes.Nonce, gas.EvmFee], error)); ok { - return rf(ctx, fromAddress, nonce, chainID) + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, int64, int64, *big.Int) ([]*types.Tx[*big.Int, common.Address, common.Hash, common.Hash, evmtypes.Nonce, gas.EvmFee], error)); ok { + return rf(ctx, highBlockNumber, lowBlockNumber, chainID) } - if rf, ok := ret.Get(0).(func(context.Context, common.Address, evmtypes.Nonce, *big.Int) []*types.Tx[*big.Int, common.Address, common.Hash, common.Hash, evmtypes.Nonce, gas.EvmFee]); ok { - r0 = rf(ctx, fromAddress, nonce, chainID) + if rf, ok := ret.Get(0).(func(context.Context, int64, int64, *big.Int) []*types.Tx[*big.Int, common.Address, common.Hash, common.Hash, evmtypes.Nonce, gas.EvmFee]); ok { + r0 = rf(ctx, highBlockNumber, lowBlockNumber, chainID) } else { if ret.Get(0) != nil { r0 = ret.Get(0).([]*types.Tx[*big.Int, common.Address, common.Hash, common.Hash, evmtypes.Nonce, gas.EvmFee]) } } - if rf, ok := ret.Get(1).(func(context.Context, common.Address, evmtypes.Nonce, *big.Int) []*types.Tx[*big.Int, common.Address, common.Hash, common.Hash, evmtypes.Nonce, gas.EvmFee]); ok { - r1 = rf(ctx, fromAddress, nonce, chainID) - } else { - if ret.Get(1) != nil { - r1 = ret.Get(1).([]*types.Tx[*big.Int, common.Address, common.Hash, common.Hash, evmtypes.Nonce, gas.EvmFee]) - } - } - - if rf, ok := ret.Get(2).(func(context.Context, common.Address, evmtypes.Nonce, *big.Int) error); ok { - r2 = rf(ctx, fromAddress, nonce, chainID) + if rf, ok := ret.Get(1).(func(context.Context, int64, int64, *big.Int) error); ok { + r1 = rf(ctx, highBlockNumber, lowBlockNumber, chainID) } else { - r2 = ret.Error(2) + r1 = ret.Error(1) } - return r0, r1, r2 + return r0, r1 } -// EvmTxStore_FindReorgOrIncludedTxs_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'FindReorgOrIncludedTxs' -type EvmTxStore_FindReorgOrIncludedTxs_Call struct { +// EvmTxStore_FindTransactionsConfirmedInBlockRange_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'FindTransactionsConfirmedInBlockRange' +type EvmTxStore_FindTransactionsConfirmedInBlockRange_Call struct { *mock.Call } -// FindReorgOrIncludedTxs is a helper method to define mock.On call +// FindTransactionsConfirmedInBlockRange is a helper method to define mock.On call // - ctx context.Context -// - fromAddress common.Address -// - nonce evmtypes.Nonce +// - highBlockNumber int64 +// - lowBlockNumber int64 // - chainID *big.Int -func (_e *EvmTxStore_Expecter) FindReorgOrIncludedTxs(ctx interface{}, fromAddress interface{}, nonce interface{}, chainID interface{}) *EvmTxStore_FindReorgOrIncludedTxs_Call { - return &EvmTxStore_FindReorgOrIncludedTxs_Call{Call: _e.mock.On("FindReorgOrIncludedTxs", ctx, fromAddress, nonce, chainID)} +func (_e *EvmTxStore_Expecter) FindTransactionsConfirmedInBlockRange(ctx interface{}, highBlockNumber interface{}, lowBlockNumber interface{}, chainID interface{}) *EvmTxStore_FindTransactionsConfirmedInBlockRange_Call { + return &EvmTxStore_FindTransactionsConfirmedInBlockRange_Call{Call: _e.mock.On("FindTransactionsConfirmedInBlockRange", ctx, highBlockNumber, lowBlockNumber, chainID)} } -func (_c *EvmTxStore_FindReorgOrIncludedTxs_Call) Run(run func(ctx context.Context, fromAddress common.Address, nonce evmtypes.Nonce, chainID *big.Int)) *EvmTxStore_FindReorgOrIncludedTxs_Call { +func (_c *EvmTxStore_FindTransactionsConfirmedInBlockRange_Call) Run(run func(ctx context.Context, highBlockNumber int64, lowBlockNumber int64, chainID *big.Int)) *EvmTxStore_FindTransactionsConfirmedInBlockRange_Call { _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context), args[1].(common.Address), args[2].(evmtypes.Nonce), args[3].(*big.Int)) + run(args[0].(context.Context), args[1].(int64), args[2].(int64), args[3].(*big.Int)) }) return _c } -func (_c *EvmTxStore_FindReorgOrIncludedTxs_Call) Return(reorgTx []*types.Tx[*big.Int, common.Address, common.Hash, common.Hash, evmtypes.Nonce, gas.EvmFee], includedTxs []*types.Tx[*big.Int, common.Address, common.Hash, common.Hash, evmtypes.Nonce, gas.EvmFee], err error) *EvmTxStore_FindReorgOrIncludedTxs_Call { - _c.Call.Return(reorgTx, includedTxs, err) +func (_c *EvmTxStore_FindTransactionsConfirmedInBlockRange_Call) Return(etxs []*types.Tx[*big.Int, common.Address, common.Hash, common.Hash, evmtypes.Nonce, gas.EvmFee], err error) *EvmTxStore_FindTransactionsConfirmedInBlockRange_Call { + _c.Call.Return(etxs, err) return _c } -func (_c *EvmTxStore_FindReorgOrIncludedTxs_Call) RunAndReturn(run func(context.Context, common.Address, evmtypes.Nonce, *big.Int) ([]*types.Tx[*big.Int, common.Address, common.Hash, common.Hash, evmtypes.Nonce, gas.EvmFee], []*types.Tx[*big.Int, common.Address, common.Hash, common.Hash, evmtypes.Nonce, gas.EvmFee], error)) *EvmTxStore_FindReorgOrIncludedTxs_Call { +func (_c *EvmTxStore_FindTransactionsConfirmedInBlockRange_Call) RunAndReturn(run func(context.Context, int64, int64, *big.Int) ([]*types.Tx[*big.Int, common.Address, common.Hash, common.Hash, evmtypes.Nonce, gas.EvmFee], error)) *EvmTxStore_FindTransactionsConfirmedInBlockRange_Call { _c.Call.Return(run) return _c } @@ -1091,6 +976,65 @@ func (_c *EvmTxStore_FindTxAttemptsConfirmedMissingReceipt_Call) RunAndReturn(ru return _c } +// FindTxAttemptsRequiringReceiptFetch provides a mock function with given fields: ctx, chainID +func (_m *EvmTxStore) FindTxAttemptsRequiringReceiptFetch(ctx context.Context, chainID *big.Int) ([]types.TxAttempt[*big.Int, common.Address, common.Hash, common.Hash, evmtypes.Nonce, gas.EvmFee], error) { + ret := _m.Called(ctx, chainID) + + if len(ret) == 0 { + panic("no return value specified for FindTxAttemptsRequiringReceiptFetch") + } + + var r0 []types.TxAttempt[*big.Int, common.Address, common.Hash, common.Hash, evmtypes.Nonce, gas.EvmFee] + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, *big.Int) ([]types.TxAttempt[*big.Int, common.Address, common.Hash, common.Hash, evmtypes.Nonce, gas.EvmFee], error)); ok { + return rf(ctx, chainID) + } + if rf, ok := ret.Get(0).(func(context.Context, *big.Int) []types.TxAttempt[*big.Int, common.Address, common.Hash, common.Hash, evmtypes.Nonce, gas.EvmFee]); ok { + r0 = rf(ctx, chainID) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]types.TxAttempt[*big.Int, common.Address, common.Hash, common.Hash, evmtypes.Nonce, gas.EvmFee]) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, *big.Int) error); ok { + r1 = rf(ctx, chainID) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// EvmTxStore_FindTxAttemptsRequiringReceiptFetch_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'FindTxAttemptsRequiringReceiptFetch' +type EvmTxStore_FindTxAttemptsRequiringReceiptFetch_Call struct { + *mock.Call +} + +// FindTxAttemptsRequiringReceiptFetch is a helper method to define mock.On call +// - ctx context.Context +// - chainID *big.Int +func (_e *EvmTxStore_Expecter) FindTxAttemptsRequiringReceiptFetch(ctx interface{}, chainID interface{}) *EvmTxStore_FindTxAttemptsRequiringReceiptFetch_Call { + return &EvmTxStore_FindTxAttemptsRequiringReceiptFetch_Call{Call: _e.mock.On("FindTxAttemptsRequiringReceiptFetch", ctx, chainID)} +} + +func (_c *EvmTxStore_FindTxAttemptsRequiringReceiptFetch_Call) Run(run func(ctx context.Context, chainID *big.Int)) *EvmTxStore_FindTxAttemptsRequiringReceiptFetch_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(*big.Int)) + }) + return _c +} + +func (_c *EvmTxStore_FindTxAttemptsRequiringReceiptFetch_Call) Return(attempts []types.TxAttempt[*big.Int, common.Address, common.Hash, common.Hash, evmtypes.Nonce, gas.EvmFee], err error) *EvmTxStore_FindTxAttemptsRequiringReceiptFetch_Call { + _c.Call.Return(attempts, err) + return _c +} + +func (_c *EvmTxStore_FindTxAttemptsRequiringReceiptFetch_Call) RunAndReturn(run func(context.Context, *big.Int) ([]types.TxAttempt[*big.Int, common.Address, common.Hash, common.Hash, evmtypes.Nonce, gas.EvmFee], error)) *EvmTxStore_FindTxAttemptsRequiringReceiptFetch_Call { + _c.Call.Return(run) + return _c +} + // FindTxAttemptsRequiringResend provides a mock function with given fields: ctx, olderThan, maxInFlightTransactions, chainID, address func (_m *EvmTxStore) FindTxAttemptsRequiringResend(ctx context.Context, olderThan time.Time, maxInFlightTransactions uint32, chainID *big.Int, address common.Address) ([]types.TxAttempt[*big.Int, common.Address, common.Hash, common.Hash, evmtypes.Nonce, gas.EvmFee], error) { ret := _m.Called(ctx, olderThan, maxInFlightTransactions, chainID, address) @@ -1389,66 +1333,6 @@ func (_c *EvmTxStore_FindTxWithSequence_Call) RunAndReturn(run func(context.Cont return _c } -// FindTxesByIDs provides a mock function with given fields: ctx, etxIDs, chainID -func (_m *EvmTxStore) FindTxesByIDs(ctx context.Context, etxIDs []int64, chainID *big.Int) ([]*txmgr.Tx, error) { - ret := _m.Called(ctx, etxIDs, chainID) - - if len(ret) == 0 { - panic("no return value specified for FindTxesByIDs") - } - - var r0 []*txmgr.Tx - var r1 error - if rf, ok := ret.Get(0).(func(context.Context, []int64, *big.Int) ([]*txmgr.Tx, error)); ok { - return rf(ctx, etxIDs, chainID) - } - if rf, ok := ret.Get(0).(func(context.Context, []int64, *big.Int) []*txmgr.Tx); ok { - r0 = rf(ctx, etxIDs, chainID) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).([]*txmgr.Tx) - } - } - - if rf, ok := ret.Get(1).(func(context.Context, []int64, *big.Int) error); ok { - r1 = rf(ctx, etxIDs, chainID) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// EvmTxStore_FindTxesByIDs_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'FindTxesByIDs' -type EvmTxStore_FindTxesByIDs_Call struct { - *mock.Call -} - -// FindTxesByIDs is a helper method to define mock.On call -// - ctx context.Context -// - etxIDs []int64 -// - chainID *big.Int -func (_e *EvmTxStore_Expecter) FindTxesByIDs(ctx interface{}, etxIDs interface{}, chainID interface{}) *EvmTxStore_FindTxesByIDs_Call { - return &EvmTxStore_FindTxesByIDs_Call{Call: _e.mock.On("FindTxesByIDs", ctx, etxIDs, chainID)} -} - -func (_c *EvmTxStore_FindTxesByIDs_Call) Run(run func(ctx context.Context, etxIDs []int64, chainID *big.Int)) *EvmTxStore_FindTxesByIDs_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context), args[1].([]int64), args[2].(*big.Int)) - }) - return _c -} - -func (_c *EvmTxStore_FindTxesByIDs_Call) Return(etxs []*txmgr.Tx, err error) *EvmTxStore_FindTxesByIDs_Call { - _c.Call.Return(etxs, err) - return _c -} - -func (_c *EvmTxStore_FindTxesByIDs_Call) RunAndReturn(run func(context.Context, []int64, *big.Int) ([]*txmgr.Tx, error)) *EvmTxStore_FindTxesByIDs_Call { - _c.Call.Return(run) - return _c -} - // FindTxesByMetaFieldAndStates provides a mock function with given fields: ctx, metaField, metaValue, states, chainID func (_m *EvmTxStore) FindTxesByMetaFieldAndStates(ctx context.Context, metaField string, metaValue string, states []types.TxState, chainID *big.Int) ([]*types.Tx[*big.Int, common.Address, common.Hash, common.Hash, evmtypes.Nonce, gas.EvmFee], error) { ret := _m.Called(ctx, metaField, metaValue, states, chainID) @@ -1512,23 +1396,23 @@ func (_c *EvmTxStore_FindTxesByMetaFieldAndStates_Call) RunAndReturn(run func(co } // FindTxesPendingCallback provides a mock function with given fields: ctx, latest, finalized, chainID -func (_m *EvmTxStore) FindTxesPendingCallback(ctx context.Context, latest int64, finalized int64, chainID *big.Int) ([]txmgr.ReceiptPlus, error) { +func (_m *EvmTxStore) FindTxesPendingCallback(ctx context.Context, latest int64, finalized int64, chainID *big.Int) ([]types.ReceiptPlus[*evmtypes.Receipt], error) { ret := _m.Called(ctx, latest, finalized, chainID) if len(ret) == 0 { panic("no return value specified for FindTxesPendingCallback") } - var r0 []txmgr.ReceiptPlus + var r0 []types.ReceiptPlus[*evmtypes.Receipt] var r1 error - if rf, ok := ret.Get(0).(func(context.Context, int64, int64, *big.Int) ([]txmgr.ReceiptPlus, error)); ok { + if rf, ok := ret.Get(0).(func(context.Context, int64, int64, *big.Int) ([]types.ReceiptPlus[*evmtypes.Receipt], error)); ok { return rf(ctx, latest, finalized, chainID) } - if rf, ok := ret.Get(0).(func(context.Context, int64, int64, *big.Int) []txmgr.ReceiptPlus); ok { + if rf, ok := ret.Get(0).(func(context.Context, int64, int64, *big.Int) []types.ReceiptPlus[*evmtypes.Receipt]); ok { r0 = rf(ctx, latest, finalized, chainID) } else { if ret.Get(0) != nil { - r0 = ret.Get(0).([]txmgr.ReceiptPlus) + r0 = ret.Get(0).([]types.ReceiptPlus[*evmtypes.Receipt]) } } @@ -1562,12 +1446,12 @@ func (_c *EvmTxStore_FindTxesPendingCallback_Call) Run(run func(ctx context.Cont return _c } -func (_c *EvmTxStore_FindTxesPendingCallback_Call) Return(receiptsPlus []txmgr.ReceiptPlus, err error) *EvmTxStore_FindTxesPendingCallback_Call { +func (_c *EvmTxStore_FindTxesPendingCallback_Call) Return(receiptsPlus []types.ReceiptPlus[*evmtypes.Receipt], err error) *EvmTxStore_FindTxesPendingCallback_Call { _c.Call.Return(receiptsPlus, err) return _c } -func (_c *EvmTxStore_FindTxesPendingCallback_Call) RunAndReturn(run func(context.Context, int64, int64, *big.Int) ([]txmgr.ReceiptPlus, error)) *EvmTxStore_FindTxesPendingCallback_Call { +func (_c *EvmTxStore_FindTxesPendingCallback_Call) RunAndReturn(run func(context.Context, int64, int64, *big.Int) ([]types.ReceiptPlus[*evmtypes.Receipt], error)) *EvmTxStore_FindTxesPendingCallback_Call { _c.Call.Return(run) return _c } @@ -2284,6 +2168,102 @@ func (_c *EvmTxStore_LoadTxAttempts_Call) RunAndReturn(run func(context.Context, return _c } +// MarkAllConfirmedMissingReceipt provides a mock function with given fields: ctx, chainID +func (_m *EvmTxStore) MarkAllConfirmedMissingReceipt(ctx context.Context, chainID *big.Int) error { + ret := _m.Called(ctx, chainID) + + if len(ret) == 0 { + panic("no return value specified for MarkAllConfirmedMissingReceipt") + } + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context, *big.Int) error); ok { + r0 = rf(ctx, chainID) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// EvmTxStore_MarkAllConfirmedMissingReceipt_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'MarkAllConfirmedMissingReceipt' +type EvmTxStore_MarkAllConfirmedMissingReceipt_Call struct { + *mock.Call +} + +// MarkAllConfirmedMissingReceipt is a helper method to define mock.On call +// - ctx context.Context +// - chainID *big.Int +func (_e *EvmTxStore_Expecter) MarkAllConfirmedMissingReceipt(ctx interface{}, chainID interface{}) *EvmTxStore_MarkAllConfirmedMissingReceipt_Call { + return &EvmTxStore_MarkAllConfirmedMissingReceipt_Call{Call: _e.mock.On("MarkAllConfirmedMissingReceipt", ctx, chainID)} +} + +func (_c *EvmTxStore_MarkAllConfirmedMissingReceipt_Call) Run(run func(ctx context.Context, chainID *big.Int)) *EvmTxStore_MarkAllConfirmedMissingReceipt_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(*big.Int)) + }) + return _c +} + +func (_c *EvmTxStore_MarkAllConfirmedMissingReceipt_Call) Return(err error) *EvmTxStore_MarkAllConfirmedMissingReceipt_Call { + _c.Call.Return(err) + return _c +} + +func (_c *EvmTxStore_MarkAllConfirmedMissingReceipt_Call) RunAndReturn(run func(context.Context, *big.Int) error) *EvmTxStore_MarkAllConfirmedMissingReceipt_Call { + _c.Call.Return(run) + return _c +} + +// MarkOldTxesMissingReceiptAsErrored provides a mock function with given fields: ctx, blockNum, latestFinalizedBlockNum, chainID +func (_m *EvmTxStore) MarkOldTxesMissingReceiptAsErrored(ctx context.Context, blockNum int64, latestFinalizedBlockNum int64, chainID *big.Int) error { + ret := _m.Called(ctx, blockNum, latestFinalizedBlockNum, chainID) + + if len(ret) == 0 { + panic("no return value specified for MarkOldTxesMissingReceiptAsErrored") + } + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context, int64, int64, *big.Int) error); ok { + r0 = rf(ctx, blockNum, latestFinalizedBlockNum, chainID) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// EvmTxStore_MarkOldTxesMissingReceiptAsErrored_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'MarkOldTxesMissingReceiptAsErrored' +type EvmTxStore_MarkOldTxesMissingReceiptAsErrored_Call struct { + *mock.Call +} + +// MarkOldTxesMissingReceiptAsErrored is a helper method to define mock.On call +// - ctx context.Context +// - blockNum int64 +// - latestFinalizedBlockNum int64 +// - chainID *big.Int +func (_e *EvmTxStore_Expecter) MarkOldTxesMissingReceiptAsErrored(ctx interface{}, blockNum interface{}, latestFinalizedBlockNum interface{}, chainID interface{}) *EvmTxStore_MarkOldTxesMissingReceiptAsErrored_Call { + return &EvmTxStore_MarkOldTxesMissingReceiptAsErrored_Call{Call: _e.mock.On("MarkOldTxesMissingReceiptAsErrored", ctx, blockNum, latestFinalizedBlockNum, chainID)} +} + +func (_c *EvmTxStore_MarkOldTxesMissingReceiptAsErrored_Call) Run(run func(ctx context.Context, blockNum int64, latestFinalizedBlockNum int64, chainID *big.Int)) *EvmTxStore_MarkOldTxesMissingReceiptAsErrored_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(int64), args[2].(int64), args[3].(*big.Int)) + }) + return _c +} + +func (_c *EvmTxStore_MarkOldTxesMissingReceiptAsErrored_Call) Return(_a0 error) *EvmTxStore_MarkOldTxesMissingReceiptAsErrored_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *EvmTxStore_MarkOldTxesMissingReceiptAsErrored_Call) RunAndReturn(run func(context.Context, int64, int64, *big.Int) error) *EvmTxStore_MarkOldTxesMissingReceiptAsErrored_Call { + _c.Call.Return(run) + return _c +} + // PreloadTxes provides a mock function with given fields: ctx, attempts func (_m *EvmTxStore) PreloadTxes(ctx context.Context, attempts []types.TxAttempt[*big.Int, common.Address, common.Hash, common.Hash, evmtypes.Nonce, gas.EvmFee]) error { ret := _m.Called(ctx, attempts) @@ -2439,12 +2419,12 @@ func (_c *EvmTxStore_ReapTxHistory_Call) RunAndReturn(run func(context.Context, return _c } -// SaveConfirmedAttempt provides a mock function with given fields: ctx, timeout, attempt, broadcastAt -func (_m *EvmTxStore) SaveConfirmedAttempt(ctx context.Context, timeout time.Duration, attempt *types.TxAttempt[*big.Int, common.Address, common.Hash, common.Hash, evmtypes.Nonce, gas.EvmFee], broadcastAt time.Time) error { +// SaveConfirmedMissingReceiptAttempt provides a mock function with given fields: ctx, timeout, attempt, broadcastAt +func (_m *EvmTxStore) SaveConfirmedMissingReceiptAttempt(ctx context.Context, timeout time.Duration, attempt *types.TxAttempt[*big.Int, common.Address, common.Hash, common.Hash, evmtypes.Nonce, gas.EvmFee], broadcastAt time.Time) error { ret := _m.Called(ctx, timeout, attempt, broadcastAt) if len(ret) == 0 { - panic("no return value specified for SaveConfirmedAttempt") + panic("no return value specified for SaveConfirmedMissingReceiptAttempt") } var r0 error @@ -2457,48 +2437,48 @@ func (_m *EvmTxStore) SaveConfirmedAttempt(ctx context.Context, timeout time.Dur return r0 } -// EvmTxStore_SaveConfirmedAttempt_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'SaveConfirmedAttempt' -type EvmTxStore_SaveConfirmedAttempt_Call struct { +// EvmTxStore_SaveConfirmedMissingReceiptAttempt_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'SaveConfirmedMissingReceiptAttempt' +type EvmTxStore_SaveConfirmedMissingReceiptAttempt_Call struct { *mock.Call } -// SaveConfirmedAttempt is a helper method to define mock.On call +// SaveConfirmedMissingReceiptAttempt is a helper method to define mock.On call // - ctx context.Context // - timeout time.Duration // - attempt *types.TxAttempt[*big.Int,common.Address,common.Hash,common.Hash,evmtypes.Nonce,gas.EvmFee] // - broadcastAt time.Time -func (_e *EvmTxStore_Expecter) SaveConfirmedAttempt(ctx interface{}, timeout interface{}, attempt interface{}, broadcastAt interface{}) *EvmTxStore_SaveConfirmedAttempt_Call { - return &EvmTxStore_SaveConfirmedAttempt_Call{Call: _e.mock.On("SaveConfirmedAttempt", ctx, timeout, attempt, broadcastAt)} +func (_e *EvmTxStore_Expecter) SaveConfirmedMissingReceiptAttempt(ctx interface{}, timeout interface{}, attempt interface{}, broadcastAt interface{}) *EvmTxStore_SaveConfirmedMissingReceiptAttempt_Call { + return &EvmTxStore_SaveConfirmedMissingReceiptAttempt_Call{Call: _e.mock.On("SaveConfirmedMissingReceiptAttempt", ctx, timeout, attempt, broadcastAt)} } -func (_c *EvmTxStore_SaveConfirmedAttempt_Call) Run(run func(ctx context.Context, timeout time.Duration, attempt *types.TxAttempt[*big.Int, common.Address, common.Hash, common.Hash, evmtypes.Nonce, gas.EvmFee], broadcastAt time.Time)) *EvmTxStore_SaveConfirmedAttempt_Call { +func (_c *EvmTxStore_SaveConfirmedMissingReceiptAttempt_Call) Run(run func(ctx context.Context, timeout time.Duration, attempt *types.TxAttempt[*big.Int, common.Address, common.Hash, common.Hash, evmtypes.Nonce, gas.EvmFee], broadcastAt time.Time)) *EvmTxStore_SaveConfirmedMissingReceiptAttempt_Call { _c.Call.Run(func(args mock.Arguments) { run(args[0].(context.Context), args[1].(time.Duration), args[2].(*types.TxAttempt[*big.Int, common.Address, common.Hash, common.Hash, evmtypes.Nonce, gas.EvmFee]), args[3].(time.Time)) }) return _c } -func (_c *EvmTxStore_SaveConfirmedAttempt_Call) Return(_a0 error) *EvmTxStore_SaveConfirmedAttempt_Call { +func (_c *EvmTxStore_SaveConfirmedMissingReceiptAttempt_Call) Return(_a0 error) *EvmTxStore_SaveConfirmedMissingReceiptAttempt_Call { _c.Call.Return(_a0) return _c } -func (_c *EvmTxStore_SaveConfirmedAttempt_Call) RunAndReturn(run func(context.Context, time.Duration, *types.TxAttempt[*big.Int, common.Address, common.Hash, common.Hash, evmtypes.Nonce, gas.EvmFee], time.Time) error) *EvmTxStore_SaveConfirmedAttempt_Call { +func (_c *EvmTxStore_SaveConfirmedMissingReceiptAttempt_Call) RunAndReturn(run func(context.Context, time.Duration, *types.TxAttempt[*big.Int, common.Address, common.Hash, common.Hash, evmtypes.Nonce, gas.EvmFee], time.Time) error) *EvmTxStore_SaveConfirmedMissingReceiptAttempt_Call { _c.Call.Return(run) return _c } -// SaveFetchedReceipts provides a mock function with given fields: ctx, r -func (_m *EvmTxStore) SaveFetchedReceipts(ctx context.Context, r []*evmtypes.Receipt) error { - ret := _m.Called(ctx, r) +// SaveFetchedReceipts provides a mock function with given fields: ctx, r, state, errorMsg, chainID +func (_m *EvmTxStore) SaveFetchedReceipts(ctx context.Context, r []*evmtypes.Receipt, state types.TxState, errorMsg *string, chainID *big.Int) error { + ret := _m.Called(ctx, r, state, errorMsg, chainID) if len(ret) == 0 { panic("no return value specified for SaveFetchedReceipts") } var r0 error - if rf, ok := ret.Get(0).(func(context.Context, []*evmtypes.Receipt) error); ok { - r0 = rf(ctx, r) + if rf, ok := ret.Get(0).(func(context.Context, []*evmtypes.Receipt, types.TxState, *string, *big.Int) error); ok { + r0 = rf(ctx, r, state, errorMsg, chainID) } else { r0 = ret.Error(0) } @@ -2514,23 +2494,26 @@ type EvmTxStore_SaveFetchedReceipts_Call struct { // SaveFetchedReceipts is a helper method to define mock.On call // - ctx context.Context // - r []*evmtypes.Receipt -func (_e *EvmTxStore_Expecter) SaveFetchedReceipts(ctx interface{}, r interface{}) *EvmTxStore_SaveFetchedReceipts_Call { - return &EvmTxStore_SaveFetchedReceipts_Call{Call: _e.mock.On("SaveFetchedReceipts", ctx, r)} +// - state types.TxState +// - errorMsg *string +// - chainID *big.Int +func (_e *EvmTxStore_Expecter) SaveFetchedReceipts(ctx interface{}, r interface{}, state interface{}, errorMsg interface{}, chainID interface{}) *EvmTxStore_SaveFetchedReceipts_Call { + return &EvmTxStore_SaveFetchedReceipts_Call{Call: _e.mock.On("SaveFetchedReceipts", ctx, r, state, errorMsg, chainID)} } -func (_c *EvmTxStore_SaveFetchedReceipts_Call) Run(run func(ctx context.Context, r []*evmtypes.Receipt)) *EvmTxStore_SaveFetchedReceipts_Call { +func (_c *EvmTxStore_SaveFetchedReceipts_Call) Run(run func(ctx context.Context, r []*evmtypes.Receipt, state types.TxState, errorMsg *string, chainID *big.Int)) *EvmTxStore_SaveFetchedReceipts_Call { _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context), args[1].([]*evmtypes.Receipt)) + run(args[0].(context.Context), args[1].([]*evmtypes.Receipt), args[2].(types.TxState), args[3].(*string), args[4].(*big.Int)) }) return _c } -func (_c *EvmTxStore_SaveFetchedReceipts_Call) Return(err error) *EvmTxStore_SaveFetchedReceipts_Call { - _c.Call.Return(err) +func (_c *EvmTxStore_SaveFetchedReceipts_Call) Return(_a0 error) *EvmTxStore_SaveFetchedReceipts_Call { + _c.Call.Return(_a0) return _c } -func (_c *EvmTxStore_SaveFetchedReceipts_Call) RunAndReturn(run func(context.Context, []*evmtypes.Receipt) error) *EvmTxStore_SaveFetchedReceipts_Call { +func (_c *EvmTxStore_SaveFetchedReceipts_Call) RunAndReturn(run func(context.Context, []*evmtypes.Receipt, types.TxState, *string, *big.Int) error) *EvmTxStore_SaveFetchedReceipts_Call { _c.Call.Return(run) return _c } @@ -3074,9 +3057,9 @@ func (_c *EvmTxStore_UpdateTxAttemptInProgressToBroadcast_Call) RunAndReturn(run return _c } -// UpdateTxCallbackCompleted provides a mock function with given fields: ctx, pipelineTaskRunRid, chainID -func (_m *EvmTxStore) UpdateTxCallbackCompleted(ctx context.Context, pipelineTaskRunRid uuid.UUID, chainID *big.Int) error { - ret := _m.Called(ctx, pipelineTaskRunRid, chainID) +// UpdateTxCallbackCompleted provides a mock function with given fields: ctx, pipelineTaskRunRid, chainId +func (_m *EvmTxStore) UpdateTxCallbackCompleted(ctx context.Context, pipelineTaskRunRid uuid.UUID, chainId *big.Int) error { + ret := _m.Called(ctx, pipelineTaskRunRid, chainId) if len(ret) == 0 { panic("no return value specified for UpdateTxCallbackCompleted") @@ -3084,7 +3067,7 @@ func (_m *EvmTxStore) UpdateTxCallbackCompleted(ctx context.Context, pipelineTas var r0 error if rf, ok := ret.Get(0).(func(context.Context, uuid.UUID, *big.Int) error); ok { - r0 = rf(ctx, pipelineTaskRunRid, chainID) + r0 = rf(ctx, pipelineTaskRunRid, chainId) } else { r0 = ret.Error(0) } @@ -3100,12 +3083,12 @@ type EvmTxStore_UpdateTxCallbackCompleted_Call struct { // UpdateTxCallbackCompleted is a helper method to define mock.On call // - ctx context.Context // - pipelineTaskRunRid uuid.UUID -// - chainID *big.Int -func (_e *EvmTxStore_Expecter) UpdateTxCallbackCompleted(ctx interface{}, pipelineTaskRunRid interface{}, chainID interface{}) *EvmTxStore_UpdateTxCallbackCompleted_Call { - return &EvmTxStore_UpdateTxCallbackCompleted_Call{Call: _e.mock.On("UpdateTxCallbackCompleted", ctx, pipelineTaskRunRid, chainID)} +// - chainId *big.Int +func (_e *EvmTxStore_Expecter) UpdateTxCallbackCompleted(ctx interface{}, pipelineTaskRunRid interface{}, chainId interface{}) *EvmTxStore_UpdateTxCallbackCompleted_Call { + return &EvmTxStore_UpdateTxCallbackCompleted_Call{Call: _e.mock.On("UpdateTxCallbackCompleted", ctx, pipelineTaskRunRid, chainId)} } -func (_c *EvmTxStore_UpdateTxCallbackCompleted_Call) Run(run func(ctx context.Context, pipelineTaskRunRid uuid.UUID, chainID *big.Int)) *EvmTxStore_UpdateTxCallbackCompleted_Call { +func (_c *EvmTxStore_UpdateTxCallbackCompleted_Call) Run(run func(ctx context.Context, pipelineTaskRunRid uuid.UUID, chainId *big.Int)) *EvmTxStore_UpdateTxCallbackCompleted_Call { _c.Call.Run(func(args mock.Arguments) { run(args[0].(context.Context), args[1].(uuid.UUID), args[2].(*big.Int)) }) @@ -3122,64 +3105,17 @@ func (_c *EvmTxStore_UpdateTxCallbackCompleted_Call) RunAndReturn(run func(conte return _c } -// UpdateTxConfirmed provides a mock function with given fields: ctx, etxIDs -func (_m *EvmTxStore) UpdateTxConfirmed(ctx context.Context, etxIDs []int64) error { - ret := _m.Called(ctx, etxIDs) - - if len(ret) == 0 { - panic("no return value specified for UpdateTxConfirmed") - } - - var r0 error - if rf, ok := ret.Get(0).(func(context.Context, []int64) error); ok { - r0 = rf(ctx, etxIDs) - } else { - r0 = ret.Error(0) - } - - return r0 -} - -// EvmTxStore_UpdateTxConfirmed_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'UpdateTxConfirmed' -type EvmTxStore_UpdateTxConfirmed_Call struct { - *mock.Call -} - -// UpdateTxConfirmed is a helper method to define mock.On call -// - ctx context.Context -// - etxIDs []int64 -func (_e *EvmTxStore_Expecter) UpdateTxConfirmed(ctx interface{}, etxIDs interface{}) *EvmTxStore_UpdateTxConfirmed_Call { - return &EvmTxStore_UpdateTxConfirmed_Call{Call: _e.mock.On("UpdateTxConfirmed", ctx, etxIDs)} -} - -func (_c *EvmTxStore_UpdateTxConfirmed_Call) Run(run func(ctx context.Context, etxIDs []int64)) *EvmTxStore_UpdateTxConfirmed_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context), args[1].([]int64)) - }) - return _c -} - -func (_c *EvmTxStore_UpdateTxConfirmed_Call) Return(_a0 error) *EvmTxStore_UpdateTxConfirmed_Call { - _c.Call.Return(_a0) - return _c -} - -func (_c *EvmTxStore_UpdateTxConfirmed_Call) RunAndReturn(run func(context.Context, []int64) error) *EvmTxStore_UpdateTxConfirmed_Call { - _c.Call.Return(run) - return _c -} - -// UpdateTxFatalError provides a mock function with given fields: ctx, etxIDs, errMsg -func (_m *EvmTxStore) UpdateTxFatalError(ctx context.Context, etxIDs []int64, errMsg string) error { - ret := _m.Called(ctx, etxIDs, errMsg) +// UpdateTxFatalError provides a mock function with given fields: ctx, etx +func (_m *EvmTxStore) UpdateTxFatalError(ctx context.Context, etx *types.Tx[*big.Int, common.Address, common.Hash, common.Hash, evmtypes.Nonce, gas.EvmFee]) error { + ret := _m.Called(ctx, etx) if len(ret) == 0 { panic("no return value specified for UpdateTxFatalError") } var r0 error - if rf, ok := ret.Get(0).(func(context.Context, []int64, string) error); ok { - r0 = rf(ctx, etxIDs, errMsg) + if rf, ok := ret.Get(0).(func(context.Context, *types.Tx[*big.Int, common.Address, common.Hash, common.Hash, evmtypes.Nonce, gas.EvmFee]) error); ok { + r0 = rf(ctx, etx) } else { r0 = ret.Error(0) } @@ -3194,15 +3130,14 @@ type EvmTxStore_UpdateTxFatalError_Call struct { // UpdateTxFatalError is a helper method to define mock.On call // - ctx context.Context -// - etxIDs []int64 -// - errMsg string -func (_e *EvmTxStore_Expecter) UpdateTxFatalError(ctx interface{}, etxIDs interface{}, errMsg interface{}) *EvmTxStore_UpdateTxFatalError_Call { - return &EvmTxStore_UpdateTxFatalError_Call{Call: _e.mock.On("UpdateTxFatalError", ctx, etxIDs, errMsg)} +// - etx *types.Tx[*big.Int,common.Address,common.Hash,common.Hash,evmtypes.Nonce,gas.EvmFee] +func (_e *EvmTxStore_Expecter) UpdateTxFatalError(ctx interface{}, etx interface{}) *EvmTxStore_UpdateTxFatalError_Call { + return &EvmTxStore_UpdateTxFatalError_Call{Call: _e.mock.On("UpdateTxFatalError", ctx, etx)} } -func (_c *EvmTxStore_UpdateTxFatalError_Call) Run(run func(ctx context.Context, etxIDs []int64, errMsg string)) *EvmTxStore_UpdateTxFatalError_Call { +func (_c *EvmTxStore_UpdateTxFatalError_Call) Run(run func(ctx context.Context, etx *types.Tx[*big.Int, common.Address, common.Hash, common.Hash, evmtypes.Nonce, gas.EvmFee])) *EvmTxStore_UpdateTxFatalError_Call { _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context), args[1].([]int64), args[2].(string)) + run(args[0].(context.Context), args[1].(*types.Tx[*big.Int, common.Address, common.Hash, common.Hash, evmtypes.Nonce, gas.EvmFee])) }) return _c } @@ -3212,22 +3147,22 @@ func (_c *EvmTxStore_UpdateTxFatalError_Call) Return(_a0 error) *EvmTxStore_Upda return _c } -func (_c *EvmTxStore_UpdateTxFatalError_Call) RunAndReturn(run func(context.Context, []int64, string) error) *EvmTxStore_UpdateTxFatalError_Call { +func (_c *EvmTxStore_UpdateTxFatalError_Call) RunAndReturn(run func(context.Context, *types.Tx[*big.Int, common.Address, common.Hash, common.Hash, evmtypes.Nonce, gas.EvmFee]) error) *EvmTxStore_UpdateTxFatalError_Call { _c.Call.Return(run) return _c } -// UpdateTxFatalErrorAndDeleteAttempts provides a mock function with given fields: ctx, etx -func (_m *EvmTxStore) UpdateTxFatalErrorAndDeleteAttempts(ctx context.Context, etx *types.Tx[*big.Int, common.Address, common.Hash, common.Hash, evmtypes.Nonce, gas.EvmFee]) error { - ret := _m.Called(ctx, etx) +// UpdateTxForRebroadcast provides a mock function with given fields: ctx, etx, etxAttempt +func (_m *EvmTxStore) UpdateTxForRebroadcast(ctx context.Context, etx types.Tx[*big.Int, common.Address, common.Hash, common.Hash, evmtypes.Nonce, gas.EvmFee], etxAttempt types.TxAttempt[*big.Int, common.Address, common.Hash, common.Hash, evmtypes.Nonce, gas.EvmFee]) error { + ret := _m.Called(ctx, etx, etxAttempt) if len(ret) == 0 { - panic("no return value specified for UpdateTxFatalErrorAndDeleteAttempts") + panic("no return value specified for UpdateTxForRebroadcast") } var r0 error - if rf, ok := ret.Get(0).(func(context.Context, *types.Tx[*big.Int, common.Address, common.Hash, common.Hash, evmtypes.Nonce, gas.EvmFee]) error); ok { - r0 = rf(ctx, etx) + if rf, ok := ret.Get(0).(func(context.Context, types.Tx[*big.Int, common.Address, common.Hash, common.Hash, evmtypes.Nonce, gas.EvmFee], types.TxAttempt[*big.Int, common.Address, common.Hash, common.Hash, evmtypes.Nonce, gas.EvmFee]) error); ok { + r0 = rf(ctx, etx, etxAttempt) } else { r0 = ret.Error(0) } @@ -3235,46 +3170,47 @@ func (_m *EvmTxStore) UpdateTxFatalErrorAndDeleteAttempts(ctx context.Context, e return r0 } -// EvmTxStore_UpdateTxFatalErrorAndDeleteAttempts_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'UpdateTxFatalErrorAndDeleteAttempts' -type EvmTxStore_UpdateTxFatalErrorAndDeleteAttempts_Call struct { +// EvmTxStore_UpdateTxForRebroadcast_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'UpdateTxForRebroadcast' +type EvmTxStore_UpdateTxForRebroadcast_Call struct { *mock.Call } -// UpdateTxFatalErrorAndDeleteAttempts is a helper method to define mock.On call +// UpdateTxForRebroadcast is a helper method to define mock.On call // - ctx context.Context -// - etx *types.Tx[*big.Int,common.Address,common.Hash,common.Hash,evmtypes.Nonce,gas.EvmFee] -func (_e *EvmTxStore_Expecter) UpdateTxFatalErrorAndDeleteAttempts(ctx interface{}, etx interface{}) *EvmTxStore_UpdateTxFatalErrorAndDeleteAttempts_Call { - return &EvmTxStore_UpdateTxFatalErrorAndDeleteAttempts_Call{Call: _e.mock.On("UpdateTxFatalErrorAndDeleteAttempts", ctx, etx)} +// - etx types.Tx[*big.Int,common.Address,common.Hash,common.Hash,evmtypes.Nonce,gas.EvmFee] +// - etxAttempt types.TxAttempt[*big.Int,common.Address,common.Hash,common.Hash,evmtypes.Nonce,gas.EvmFee] +func (_e *EvmTxStore_Expecter) UpdateTxForRebroadcast(ctx interface{}, etx interface{}, etxAttempt interface{}) *EvmTxStore_UpdateTxForRebroadcast_Call { + return &EvmTxStore_UpdateTxForRebroadcast_Call{Call: _e.mock.On("UpdateTxForRebroadcast", ctx, etx, etxAttempt)} } -func (_c *EvmTxStore_UpdateTxFatalErrorAndDeleteAttempts_Call) Run(run func(ctx context.Context, etx *types.Tx[*big.Int, common.Address, common.Hash, common.Hash, evmtypes.Nonce, gas.EvmFee])) *EvmTxStore_UpdateTxFatalErrorAndDeleteAttempts_Call { +func (_c *EvmTxStore_UpdateTxForRebroadcast_Call) Run(run func(ctx context.Context, etx types.Tx[*big.Int, common.Address, common.Hash, common.Hash, evmtypes.Nonce, gas.EvmFee], etxAttempt types.TxAttempt[*big.Int, common.Address, common.Hash, common.Hash, evmtypes.Nonce, gas.EvmFee])) *EvmTxStore_UpdateTxForRebroadcast_Call { _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context), args[1].(*types.Tx[*big.Int, common.Address, common.Hash, common.Hash, evmtypes.Nonce, gas.EvmFee])) + run(args[0].(context.Context), args[1].(types.Tx[*big.Int, common.Address, common.Hash, common.Hash, evmtypes.Nonce, gas.EvmFee]), args[2].(types.TxAttempt[*big.Int, common.Address, common.Hash, common.Hash, evmtypes.Nonce, gas.EvmFee])) }) return _c } -func (_c *EvmTxStore_UpdateTxFatalErrorAndDeleteAttempts_Call) Return(_a0 error) *EvmTxStore_UpdateTxFatalErrorAndDeleteAttempts_Call { +func (_c *EvmTxStore_UpdateTxForRebroadcast_Call) Return(_a0 error) *EvmTxStore_UpdateTxForRebroadcast_Call { _c.Call.Return(_a0) return _c } -func (_c *EvmTxStore_UpdateTxFatalErrorAndDeleteAttempts_Call) RunAndReturn(run func(context.Context, *types.Tx[*big.Int, common.Address, common.Hash, common.Hash, evmtypes.Nonce, gas.EvmFee]) error) *EvmTxStore_UpdateTxFatalErrorAndDeleteAttempts_Call { +func (_c *EvmTxStore_UpdateTxForRebroadcast_Call) RunAndReturn(run func(context.Context, types.Tx[*big.Int, common.Address, common.Hash, common.Hash, evmtypes.Nonce, gas.EvmFee], types.TxAttempt[*big.Int, common.Address, common.Hash, common.Hash, evmtypes.Nonce, gas.EvmFee]) error) *EvmTxStore_UpdateTxForRebroadcast_Call { _c.Call.Return(run) return _c } -// UpdateTxStatesToFinalizedUsingTxHashes provides a mock function with given fields: ctx, txHashes, chainID -func (_m *EvmTxStore) UpdateTxStatesToFinalizedUsingTxHashes(ctx context.Context, txHashes []common.Hash, chainID *big.Int) error { - ret := _m.Called(ctx, txHashes, chainID) +// UpdateTxStatesToFinalizedUsingReceiptIds provides a mock function with given fields: ctx, etxIDs, chainId +func (_m *EvmTxStore) UpdateTxStatesToFinalizedUsingReceiptIds(ctx context.Context, etxIDs []int64, chainId *big.Int) error { + ret := _m.Called(ctx, etxIDs, chainId) if len(ret) == 0 { - panic("no return value specified for UpdateTxStatesToFinalizedUsingTxHashes") + panic("no return value specified for UpdateTxStatesToFinalizedUsingReceiptIds") } var r0 error - if rf, ok := ret.Get(0).(func(context.Context, []common.Hash, *big.Int) error); ok { - r0 = rf(ctx, txHashes, chainID) + if rf, ok := ret.Get(0).(func(context.Context, []int64, *big.Int) error); ok { + r0 = rf(ctx, etxIDs, chainId) } else { r0 = ret.Error(0) } @@ -3282,32 +3218,32 @@ func (_m *EvmTxStore) UpdateTxStatesToFinalizedUsingTxHashes(ctx context.Context return r0 } -// EvmTxStore_UpdateTxStatesToFinalizedUsingTxHashes_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'UpdateTxStatesToFinalizedUsingTxHashes' -type EvmTxStore_UpdateTxStatesToFinalizedUsingTxHashes_Call struct { +// EvmTxStore_UpdateTxStatesToFinalizedUsingReceiptIds_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'UpdateTxStatesToFinalizedUsingReceiptIds' +type EvmTxStore_UpdateTxStatesToFinalizedUsingReceiptIds_Call struct { *mock.Call } -// UpdateTxStatesToFinalizedUsingTxHashes is a helper method to define mock.On call +// UpdateTxStatesToFinalizedUsingReceiptIds is a helper method to define mock.On call // - ctx context.Context -// - txHashes []common.Hash -// - chainID *big.Int -func (_e *EvmTxStore_Expecter) UpdateTxStatesToFinalizedUsingTxHashes(ctx interface{}, txHashes interface{}, chainID interface{}) *EvmTxStore_UpdateTxStatesToFinalizedUsingTxHashes_Call { - return &EvmTxStore_UpdateTxStatesToFinalizedUsingTxHashes_Call{Call: _e.mock.On("UpdateTxStatesToFinalizedUsingTxHashes", ctx, txHashes, chainID)} +// - etxIDs []int64 +// - chainId *big.Int +func (_e *EvmTxStore_Expecter) UpdateTxStatesToFinalizedUsingReceiptIds(ctx interface{}, etxIDs interface{}, chainId interface{}) *EvmTxStore_UpdateTxStatesToFinalizedUsingReceiptIds_Call { + return &EvmTxStore_UpdateTxStatesToFinalizedUsingReceiptIds_Call{Call: _e.mock.On("UpdateTxStatesToFinalizedUsingReceiptIds", ctx, etxIDs, chainId)} } -func (_c *EvmTxStore_UpdateTxStatesToFinalizedUsingTxHashes_Call) Run(run func(ctx context.Context, txHashes []common.Hash, chainID *big.Int)) *EvmTxStore_UpdateTxStatesToFinalizedUsingTxHashes_Call { +func (_c *EvmTxStore_UpdateTxStatesToFinalizedUsingReceiptIds_Call) Run(run func(ctx context.Context, etxIDs []int64, chainId *big.Int)) *EvmTxStore_UpdateTxStatesToFinalizedUsingReceiptIds_Call { _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context), args[1].([]common.Hash), args[2].(*big.Int)) + run(args[0].(context.Context), args[1].([]int64), args[2].(*big.Int)) }) return _c } -func (_c *EvmTxStore_UpdateTxStatesToFinalizedUsingTxHashes_Call) Return(_a0 error) *EvmTxStore_UpdateTxStatesToFinalizedUsingTxHashes_Call { +func (_c *EvmTxStore_UpdateTxStatesToFinalizedUsingReceiptIds_Call) Return(_a0 error) *EvmTxStore_UpdateTxStatesToFinalizedUsingReceiptIds_Call { _c.Call.Return(_a0) return _c } -func (_c *EvmTxStore_UpdateTxStatesToFinalizedUsingTxHashes_Call) RunAndReturn(run func(context.Context, []common.Hash, *big.Int) error) *EvmTxStore_UpdateTxStatesToFinalizedUsingTxHashes_Call { +func (_c *EvmTxStore_UpdateTxStatesToFinalizedUsingReceiptIds_Call) RunAndReturn(run func(context.Context, []int64, *big.Int) error) *EvmTxStore_UpdateTxStatesToFinalizedUsingReceiptIds_Call { _c.Call.Return(run) return _c } @@ -3360,57 +3296,9 @@ func (_c *EvmTxStore_UpdateTxUnstartedToInProgress_Call) RunAndReturn(run func(c return _c } -// UpdateTxsForRebroadcast provides a mock function with given fields: ctx, etxIDs, attemptIDs -func (_m *EvmTxStore) UpdateTxsForRebroadcast(ctx context.Context, etxIDs []int64, attemptIDs []int64) error { - ret := _m.Called(ctx, etxIDs, attemptIDs) - - if len(ret) == 0 { - panic("no return value specified for UpdateTxsForRebroadcast") - } - - var r0 error - if rf, ok := ret.Get(0).(func(context.Context, []int64, []int64) error); ok { - r0 = rf(ctx, etxIDs, attemptIDs) - } else { - r0 = ret.Error(0) - } - - return r0 -} - -// EvmTxStore_UpdateTxsForRebroadcast_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'UpdateTxsForRebroadcast' -type EvmTxStore_UpdateTxsForRebroadcast_Call struct { - *mock.Call -} - -// UpdateTxsForRebroadcast is a helper method to define mock.On call -// - ctx context.Context -// - etxIDs []int64 -// - attemptIDs []int64 -func (_e *EvmTxStore_Expecter) UpdateTxsForRebroadcast(ctx interface{}, etxIDs interface{}, attemptIDs interface{}) *EvmTxStore_UpdateTxsForRebroadcast_Call { - return &EvmTxStore_UpdateTxsForRebroadcast_Call{Call: _e.mock.On("UpdateTxsForRebroadcast", ctx, etxIDs, attemptIDs)} -} - -func (_c *EvmTxStore_UpdateTxsForRebroadcast_Call) Run(run func(ctx context.Context, etxIDs []int64, attemptIDs []int64)) *EvmTxStore_UpdateTxsForRebroadcast_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context), args[1].([]int64), args[2].([]int64)) - }) - return _c -} - -func (_c *EvmTxStore_UpdateTxsForRebroadcast_Call) Return(_a0 error) *EvmTxStore_UpdateTxsForRebroadcast_Call { - _c.Call.Return(_a0) - return _c -} - -func (_c *EvmTxStore_UpdateTxsForRebroadcast_Call) RunAndReturn(run func(context.Context, []int64, []int64) error) *EvmTxStore_UpdateTxsForRebroadcast_Call { - _c.Call.Return(run) - return _c -} - -// UpdateTxsUnconfirmed provides a mock function with given fields: ctx, etxIDs -func (_m *EvmTxStore) UpdateTxsUnconfirmed(ctx context.Context, etxIDs []int64) error { - ret := _m.Called(ctx, etxIDs) +// UpdateTxsUnconfirmed provides a mock function with given fields: ctx, ids +func (_m *EvmTxStore) UpdateTxsUnconfirmed(ctx context.Context, ids []int64) error { + ret := _m.Called(ctx, ids) if len(ret) == 0 { panic("no return value specified for UpdateTxsUnconfirmed") @@ -3418,7 +3306,7 @@ func (_m *EvmTxStore) UpdateTxsUnconfirmed(ctx context.Context, etxIDs []int64) var r0 error if rf, ok := ret.Get(0).(func(context.Context, []int64) error); ok { - r0 = rf(ctx, etxIDs) + r0 = rf(ctx, ids) } else { r0 = ret.Error(0) } @@ -3433,12 +3321,12 @@ type EvmTxStore_UpdateTxsUnconfirmed_Call struct { // UpdateTxsUnconfirmed is a helper method to define mock.On call // - ctx context.Context -// - etxIDs []int64 -func (_e *EvmTxStore_Expecter) UpdateTxsUnconfirmed(ctx interface{}, etxIDs interface{}) *EvmTxStore_UpdateTxsUnconfirmed_Call { - return &EvmTxStore_UpdateTxsUnconfirmed_Call{Call: _e.mock.On("UpdateTxsUnconfirmed", ctx, etxIDs)} +// - ids []int64 +func (_e *EvmTxStore_Expecter) UpdateTxsUnconfirmed(ctx interface{}, ids interface{}) *EvmTxStore_UpdateTxsUnconfirmed_Call { + return &EvmTxStore_UpdateTxsUnconfirmed_Call{Call: _e.mock.On("UpdateTxsUnconfirmed", ctx, ids)} } -func (_c *EvmTxStore_UpdateTxsUnconfirmed_Call) Run(run func(ctx context.Context, etxIDs []int64)) *EvmTxStore_UpdateTxsUnconfirmed_Call { +func (_c *EvmTxStore_UpdateTxsUnconfirmed_Call) Run(run func(ctx context.Context, ids []int64)) *EvmTxStore_UpdateTxsUnconfirmed_Call { _c.Call.Run(func(args mock.Arguments) { run(args[0].(context.Context), args[1].([]int64)) }) diff --git a/core/chains/evm/txmgr/nonce_tracker.go b/core/chains/evm/txmgr/nonce_tracker.go index 16d14308023..873f2595dbf 100644 --- a/core/chains/evm/txmgr/nonce_tracker.go +++ b/core/chains/evm/txmgr/nonce_tracker.go @@ -68,7 +68,6 @@ func (s *nonceTracker) getSequenceForAddr(ctx context.Context, address common.Ad seq, err = s.txStore.FindLatestSequence(ctx, address, s.chainID) if err == nil { seq++ - s.lggr.Debugw("found next nonce using stored transactions", "address", address.Hex(), "nonce", seq.String()) return seq, nil } // Look for nonce on-chain if no tx found for address in TxStore or if error occurred. @@ -79,7 +78,6 @@ func (s *nonceTracker) getSequenceForAddr(ctx context.Context, address common.Ad // If that occurs, there could be short term noise in the logs surfacing that a transaction expired without ever getting a receipt. nonce, err := s.client.SequenceAt(ctx, address, nil) if err == nil { - s.lggr.Debugw("found next nonce using RPC", "address", address.Hex(), "nonce", nonce.String()) return nonce, nil } s.lggr.Criticalw("failed to retrieve next sequence from on-chain for address: ", "address", address.String()) diff --git a/core/chains/evm/txmgr/txmgr_test.go b/core/chains/evm/txmgr/txmgr_test.go index 9ee2396846d..7052a694719 100644 --- a/core/chains/evm/txmgr/txmgr_test.go +++ b/core/chains/evm/txmgr/txmgr_test.go @@ -899,6 +899,19 @@ func mustInsertConfirmedEthTxWithReceipt(t *testing.T, txStore txmgr.TestEvmTxSt return etx } +func mustInsertConfirmedEthTxBySaveFetchedReceipts(t *testing.T, txStore txmgr.TestEvmTxStore, fromAddress common.Address, nonce int64, blockNum int64, chainID big.Int) (etx txmgr.Tx) { + etx = cltest.MustInsertConfirmedEthTxWithLegacyAttempt(t, txStore, nonce, blockNum, fromAddress) + receipt := evmtypes.Receipt{ + TxHash: etx.TxAttempts[0].Hash, + BlockHash: utils.NewHash(), + BlockNumber: big.NewInt(nonce), + TransactionIndex: uint(1), + } + err := txStore.SaveFetchedReceipts(tests.Context(t), []*evmtypes.Receipt{&receipt}, txmgrcommon.TxConfirmed, nil, &chainID) + require.NoError(t, err) + return etx +} + func mustInsertFatalErrorEthTx(t *testing.T, txStore txmgr.TestEvmTxStore, fromAddress common.Address) txmgr.Tx { etx := cltest.NewEthTx(fromAddress) etx.Error = null.StringFrom("something exploded") diff --git a/core/chains/legacyevm/chain.go b/core/chains/legacyevm/chain.go index 3e6aeef911c..d8eed88dedf 100644 --- a/core/chains/legacyevm/chain.go +++ b/core/chains/legacyevm/chain.go @@ -194,10 +194,10 @@ func newChain(ctx context.Context, cfg *evmconfig.ChainScoped, nodes []*toml.Nod chainID := cfg.EVM().ChainID() l := opts.Logger var client evmclient.Client - var err error if !opts.AppConfig.EVMRPCEnabled() { client = evmclient.NewNullClient(chainID, l) } else if opts.GenEthClient == nil { + var err error client, err = evmclient.NewEvmClient(cfg.EVM().NodePool(), cfg.EVM(), cfg.EVM().NodePool().Errors(), l, chainID, nodes, cfg.EVM().ChainType()) if err != nil { return nil, err @@ -244,24 +244,10 @@ func newChain(ctx context.Context, cfg *evmconfig.ChainScoped, nodes []*toml.Nod } } - // initialize gas estimator - gasEstimator, err := newGasEstimator(cfg.EVM(), client, l, opts, clientsByChainID) - if err != nil { - return nil, fmt.Errorf("failed to instantiate gas estimator for chain with ID %s: %w", chainID, err) - } - // note: gas estimator is started as a part of the txm - var txm txmgr.TxManager - //nolint:gocritic // ignoring suggestion to convert to switch statement - if !opts.AppConfig.EVMRPCEnabled() { - txm = &txmgr.NullTxManager{ErrMsg: fmt.Sprintf("Ethereum is disabled for chain %d", chainID)} - } else if !cfg.EVM().Transactions().Enabled() { - txm = &txmgr.NullTxManager{ErrMsg: fmt.Sprintf("TXM disabled for chain %d", chainID)} - } else { - txm, err = newEvmTxm(opts.DS, cfg.EVM(), opts.AppConfig.Database(), opts.AppConfig.Database().Listener(), client, l, logPoller, opts, headTracker, gasEstimator) - if err != nil { - return nil, fmt.Errorf("failed to instantiate EvmTxm for chain with ID %s: %w", chainID, err) - } + txm, gasEstimator, err := newEvmTxm(opts.DS, cfg.EVM(), opts.AppConfig.EVMRPCEnabled(), opts.AppConfig.Database(), opts.AppConfig.Database().Listener(), client, l, logPoller, opts, headTracker, clientsByChainID) + if err != nil { + return nil, fmt.Errorf("failed to instantiate EvmTxm for chain with ID %s: %w", chainID.String(), err) } headBroadcaster.Subscribe(txm) diff --git a/core/chains/legacyevm/evm_txm.go b/core/chains/legacyevm/evm_txm.go index 17dbce79e84..3a96a9da937 100644 --- a/core/chains/legacyevm/evm_txm.go +++ b/core/chains/legacyevm/evm_txm.go @@ -17,6 +17,7 @@ import ( func newEvmTxm( ds sqlutil.DataSource, cfg evmconfig.EVM, + evmRPCEnabled bool, databaseConfig txmgr.DatabaseConfig, listenerConfig txmgr.ListenerConfig, client evmclient.Client, @@ -24,11 +25,16 @@ func newEvmTxm( logPoller logpoller.LogPoller, opts ChainRelayOpts, headTracker httypes.HeadTracker, - estimator gas.EvmFeeEstimator, + clientsByChainID map[string]rollups.DAClient, ) (txm txmgr.TxManager, + estimator gas.EvmFeeEstimator, err error, ) { chainID := cfg.ChainID() + if !evmRPCEnabled { + txm = &txmgr.NullTxManager{ErrMsg: fmt.Sprintf("Ethereum is disabled for chain %d", chainID)} + return txm, nil, nil + } lggr = lggr.Named("Txm") lggr.Infow("Initializing EVM transaction manager", @@ -39,6 +45,15 @@ func newEvmTxm( "limitDefault", cfg.GasEstimator().LimitDefault(), ) + // build estimator from factory + if opts.GenGasEstimator == nil { + if estimator, err = gas.NewEstimator(lggr, client, cfg.ChainType(), chainID, cfg.GasEstimator(), clientsByChainID); err != nil { + return nil, nil, fmt.Errorf("failed to initialize estimator: %w", err) + } + } else { + estimator = opts.GenGasEstimator(chainID) + } + if opts.GenTxManager == nil { txm, err = txmgr.NewTxm( ds, @@ -59,23 +74,3 @@ func newEvmTxm( } return } - -func newGasEstimator( - cfg evmconfig.EVM, - client evmclient.Client, - lggr logger.Logger, - opts ChainRelayOpts, - clientsByChainID map[string]rollups.DAClient, -) (estimator gas.EvmFeeEstimator, err error) { - lggr = lggr.Named("Txm") - chainID := cfg.ChainID() - // build estimator from factory - if opts.GenGasEstimator == nil { - if estimator, err = gas.NewEstimator(lggr, client, cfg.ChainType(), chainID, cfg.GasEstimator(), clientsByChainID); err != nil { - return nil, fmt.Errorf("failed to initialize estimator: %w", err) - } - } else { - estimator = opts.GenGasEstimator(chainID) - } - return -} diff --git a/core/cmd/admin_commands.go b/core/cmd/admin_commands.go index 0af851d2c06..7bde0ec23fb 100644 --- a/core/cmd/admin_commands.go +++ b/core/cmd/admin_commands.go @@ -374,7 +374,6 @@ func (s *Shell) Profile(c *cli.Context) error { } respContent := string(b) // taken from pprof.Profile https://github.com/golang/go/blob/release-branch.go1.20/src/net/http/pprof/pprof.go#L133 - // note: no longer triggers as of 1.23 if strings.Contains(respContent, "profile duration exceeds server's WriteTimeout") { errs <- fmt.Errorf("%w: %s", ErrProfileTooLong, respContent) } else { diff --git a/core/cmd/app.go b/core/cmd/app.go index 8128d578238..53c96980de4 100644 --- a/core/cmd/app.go +++ b/core/cmd/app.go @@ -10,7 +10,6 @@ import ( "slices" "github.com/pkg/errors" - "github.com/prometheus/client_golang/prometheus" "github.com/urfave/cli" "github.com/smartcontractkit/chainlink/v2/core/build" @@ -86,7 +85,6 @@ func NewApp(s *Shell) *cli.App { } s.Logger = lggr - s.Registerer = prometheus.DefaultRegisterer // use the global DefaultRegisterer, should be safe since we only ever run one instance of the app per shell s.CloseLogger = closeFn s.Config = cfg @@ -290,14 +288,25 @@ func NewApp(s *Shell) *cli.App { }, }, { - Name: "chains", - Usage: "Commands for handling chain configuration", - Subcommands: initChainSubCmds(s), + Name: "chains", + Usage: "Commands for handling chain configuration", + Subcommands: cli.Commands{ + chainCommand("EVM", EVMChainClient(s), cli.Int64Flag{Name: "id", Usage: "chain ID"}), + chainCommand("Cosmos", CosmosChainClient(s), cli.StringFlag{Name: "id", Usage: "chain ID"}), + chainCommand("Solana", SolanaChainClient(s), + cli.StringFlag{Name: "id", Usage: "chain ID, options: [mainnet, testnet, devnet, localnet]"}), + chainCommand("StarkNet", StarkNetChainClient(s), cli.StringFlag{Name: "id", Usage: "chain ID"}), + }, }, { - Name: "nodes", - Usage: "Commands for handling node configuration", - Subcommands: initNodeSubCmds(s), + Name: "nodes", + Usage: "Commands for handling node configuration", + Subcommands: cli.Commands{ + initEVMNodeSubCmd(s), + initCosmosNodeSubCmd(s), + initSolanaNodeSubCmd(s), + initStarkNetNodeSubCmd(s), + }, }, { Name: "forwarders", diff --git a/core/cmd/chains_commands.go b/core/cmd/chains_commands.go index ffbff8ffdd3..6edb5afc5ba 100644 --- a/core/cmd/chains_commands.go +++ b/core/cmd/chains_commands.go @@ -2,15 +2,9 @@ package cmd import ( "fmt" - "maps" - "slices" - "strconv" "strings" "github.com/urfave/cli" - - "github.com/smartcontractkit/chainlink/v2/core/services/relay" - "github.com/smartcontractkit/chainlink/v2/core/web/presenters" ) var chainHeaders = []string{"ID", "Enabled", "Config"} @@ -45,12 +39,12 @@ type chainClient[P TableRenderer] struct { path string } -// NewChainClient returns a new ChainClient for a particular type of chains.Config. +// newChainClient returns a new ChainClient for a particular type of chains.Config. // P is a TableRenderer corresponding to R, and P2 is the slice variant (type P2 []P). -func NewChainClient(s *Shell, network string) ChainClient { - return &chainClient[ChainPresenters]{ +func newChainClient[P TableRenderer](s *Shell, name string) ChainClient { + return &chainClient[P]{ Shell: s, - path: "/v2/chains/" + network, + path: "/v2/chains/" + name, } } @@ -59,51 +53,3 @@ func (cli *chainClient[P]) IndexChains(c *cli.Context) (err error) { var p P return cli.getPage(cli.path, c.Int("page"), &p) } - -// ChainPresenter implements TableRenderer for a ChainResource -type ChainPresenter struct { - presenters.ChainResource -} - -// ToRow presents the ChainResource as a slice of strings. -func (p *ChainPresenter) ToRow() []string { - return []string{p.GetID(), strconv.FormatBool(p.Enabled), p.Config} -} - -// RenderTable implements TableRenderer -// Just renders a single row -func (p ChainPresenter) RenderTable(rt RendererTable) error { - rows := [][]string{} - rows = append(rows, p.ToRow()) - - renderList(chainHeaders, rows, rt.Writer) - - return nil -} - -// ChainPresenters implements TableRenderer for a slice of ChainPresenters. -type ChainPresenters []ChainPresenter - -// RenderTable implements TableRenderer -func (ps ChainPresenters) RenderTable(rt RendererTable) error { - rows := [][]string{} - - for _, p := range ps { - rows = append(rows, p.ToRow()) - } - - renderList(chainHeaders, rows, rt.Writer) - - return nil -} - -func initChainSubCmds(s *Shell) []cli.Command { - cmds := []cli.Command{} - for _, network := range slices.Sorted(maps.Keys(relay.SupportedNetworks)) { - if network == relay.NetworkDummy { - continue - } - cmds = append(cmds, chainCommand(network, NewChainClient(s, network), cli.StringFlag{Name: "id", Usage: "chain ID"})) - } - return cmds -} diff --git a/core/cmd/chains_commands_test.go b/core/cmd/chains_commands_test.go deleted file mode 100644 index d2c8a2e4744..00000000000 --- a/core/cmd/chains_commands_test.go +++ /dev/null @@ -1,81 +0,0 @@ -package cmd_test - -import ( - "strconv" - "testing" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - - coscfg "github.com/smartcontractkit/chainlink-cosmos/pkg/cosmos/config" - solcfg "github.com/smartcontractkit/chainlink-solana/pkg/solana/config" - - client2 "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" - "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" - "github.com/smartcontractkit/chainlink/v2/core/cmd" - "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" - "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" - "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/cosmostest" - "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/solanatest" - "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" -) - -func TestShell_IndexCosmosChains(t *testing.T) { - t.Parallel() - - chainID := cosmostest.RandomChainID() - chain := coscfg.TOMLConfig{ - ChainID: ptr(chainID), - Enabled: ptr(true), - } - app := cosmosStartNewApplication(t, &chain) - client, r := app.NewShellAndRenderer() - - require.NoError(t, cmd.NewChainClient(client, "cosmos").IndexChains(cltest.EmptyCLIContext())) - chains := *r.Renders[0].(*cmd.ChainPresenters) - require.Len(t, chains, 1) - c := chains[0] - assert.Equal(t, chainID, c.ID) - assertTableRenders(t, r) -} - -func newRandChainID() *big.Big { - return big.New(testutils.NewRandomEVMChainID()) -} - -func TestShell_IndexEVMChains(t *testing.T) { - t.Parallel() - - app := startNewApplicationV2(t, func(c *chainlink.Config, s *chainlink.Secrets) { - c.EVM[0].Enabled = ptr(true) - c.EVM[0].NonceAutoSync = ptr(false) - c.EVM[0].BalanceMonitor.Enabled = ptr(false) - }) - client, r := app.NewShellAndRenderer() - - require.NoError(t, cmd.NewChainClient(client, "evm").IndexChains(cltest.EmptyCLIContext())) - chains := *r.Renders[0].(*cmd.ChainPresenters) - require.Len(t, chains, 1) - c := chains[0] - assert.Equal(t, strconv.Itoa(client2.NullClientChainID), c.ID) - assertTableRenders(t, r) -} - -func TestShell_IndexSolanaChains(t *testing.T) { - t.Parallel() - - id := solanatest.RandomChainID() - cfg := solcfg.TOMLConfig{ - ChainID: &id, - Enabled: ptr(true), - } - app := solanaStartNewApplication(t, &cfg) - client, r := app.NewShellAndRenderer() - - require.NoError(t, cmd.NewChainClient(client, "solana").IndexChains(cltest.EmptyCLIContext())) - chains := *r.Renders[0].(*cmd.ChainPresenters) - require.Len(t, chains, 1) - c := chains[0] - assert.Equal(t, id, c.ID) - assertTableRenders(t, r) -} diff --git a/core/cmd/cosmos_chains_commands.go b/core/cmd/cosmos_chains_commands.go new file mode 100644 index 00000000000..d58b1baa159 --- /dev/null +++ b/core/cmd/cosmos_chains_commands.go @@ -0,0 +1,48 @@ +package cmd + +import ( + "strconv" + + "github.com/smartcontractkit/chainlink/v2/core/web/presenters" +) + +// CosmosChainPresenter implements TableRenderer for a CosmosChainResource +type CosmosChainPresenter struct { + presenters.CosmosChainResource +} + +// ToRow presents the CosmosChainResource as a slice of strings. +func (p *CosmosChainPresenter) ToRow() []string { + return []string{p.GetID(), strconv.FormatBool(p.Enabled), p.Config} +} + +// RenderTable implements TableRenderer +// Just renders a single row +func (p CosmosChainPresenter) RenderTable(rt RendererTable) error { + rows := [][]string{} + rows = append(rows, p.ToRow()) + + renderList(chainHeaders, rows, rt.Writer) + + return nil +} + +// CosmosChainPresenters implements TableRenderer for a slice of CosmosChainPresenters. +type CosmosChainPresenters []CosmosChainPresenter + +// RenderTable implements TableRenderer +func (ps CosmosChainPresenters) RenderTable(rt RendererTable) error { + rows := [][]string{} + + for _, p := range ps { + rows = append(rows, p.ToRow()) + } + + renderList(chainHeaders, rows, rt.Writer) + + return nil +} + +func CosmosChainClient(s *Shell) ChainClient { + return newChainClient[CosmosChainPresenters](s, "cosmos") +} diff --git a/core/cmd/cosmos_chains_commands_test.go b/core/cmd/cosmos_chains_commands_test.go new file mode 100644 index 00000000000..a0d2052d836 --- /dev/null +++ b/core/cmd/cosmos_chains_commands_test.go @@ -0,0 +1,33 @@ +package cmd_test + +import ( + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + coscfg "github.com/smartcontractkit/chainlink-cosmos/pkg/cosmos/config" + + "github.com/smartcontractkit/chainlink/v2/core/cmd" + "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" + "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/cosmostest" +) + +func TestShell_IndexCosmosChains(t *testing.T) { + t.Parallel() + + chainID := cosmostest.RandomChainID() + chain := coscfg.TOMLConfig{ + ChainID: ptr(chainID), + Enabled: ptr(true), + } + app := cosmosStartNewApplication(t, &chain) + client, r := app.NewShellAndRenderer() + + require.Nil(t, cmd.CosmosChainClient(client).IndexChains(cltest.EmptyCLIContext())) + chains := *r.Renders[0].(*cmd.CosmosChainPresenters) + require.Len(t, chains, 1) + c := chains[0] + assert.Equal(t, chainID, c.ID) + assertTableRenders(t, r) +} diff --git a/core/cmd/cosmos_node_commands.go b/core/cmd/cosmos_node_commands.go new file mode 100644 index 00000000000..760691d9379 --- /dev/null +++ b/core/cmd/cosmos_node_commands.go @@ -0,0 +1,44 @@ +package cmd + +import ( + "github.com/smartcontractkit/chainlink/v2/core/web/presenters" +) + +// CosmosNodePresenter implements TableRenderer for a CosmosNodeResource. +type CosmosNodePresenter struct { + presenters.CosmosNodeResource +} + +// ToRow presents the CosmosNodeResource as a slice of strings. +func (p *CosmosNodePresenter) ToRow() []string { + return []string{p.Name, p.ChainID, p.State, p.Config} +} + +// RenderTable implements TableRenderer +func (p CosmosNodePresenter) RenderTable(rt RendererTable) error { + var rows [][]string + rows = append(rows, p.ToRow()) + renderList(nodeHeaders, rows, rt.Writer) + + return nil +} + +// CosmosNodePresenters implements TableRenderer for a slice of CosmosNodePresenter. +type CosmosNodePresenters []CosmosNodePresenter + +// RenderTable implements TableRenderer +func (ps CosmosNodePresenters) RenderTable(rt RendererTable) error { + var rows [][]string + + for _, p := range ps { + rows = append(rows, p.ToRow()) + } + + renderList(nodeHeaders, rows, rt.Writer) + + return nil +} + +func NewCosmosNodeClient(s *Shell) NodeClient { + return newNodeClient[CosmosNodePresenters](s, "cosmos") +} diff --git a/core/cmd/cosmos_node_commands_test.go b/core/cmd/cosmos_node_commands_test.go new file mode 100644 index 00000000000..f6fa367440c --- /dev/null +++ b/core/cmd/cosmos_node_commands_test.go @@ -0,0 +1,71 @@ +package cmd_test + +import ( + "bytes" + "strings" + "testing" + + "github.com/pelletier/go-toml/v2" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + "github.com/smartcontractkit/chainlink-common/pkg/config" + coscfg "github.com/smartcontractkit/chainlink-cosmos/pkg/cosmos/config" + + "github.com/smartcontractkit/chainlink/v2/core/cmd" + "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" + "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/cosmostest" + "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" +) + +func cosmosStartNewApplication(t *testing.T, cfgs ...*coscfg.TOMLConfig) *cltest.TestApplication { + for i := range cfgs { + cfgs[i].SetDefaults() + } + return startNewApplicationV2(t, func(c *chainlink.Config, s *chainlink.Secrets) { + c.Cosmos = cfgs + c.EVM = nil + }) +} + +func TestShell_IndexCosmosNodes(t *testing.T) { + t.Parallel() + + chainID := cosmostest.RandomChainID() + node := coscfg.Node{ + Name: ptr("second"), + TendermintURL: config.MustParseURL("http://tender.mint.test/bombay-12"), + } + chain := coscfg.TOMLConfig{ + ChainID: ptr(chainID), + Enabled: ptr(true), + Nodes: coscfg.Nodes{&node}, + } + app := cosmosStartNewApplication(t, &chain) + client, r := app.NewShellAndRenderer() + require.Nil(t, cmd.NewCosmosNodeClient(client).IndexNodes(cltest.EmptyCLIContext())) + require.NotEmpty(t, r.Renders) + nodes := *r.Renders[0].(*cmd.CosmosNodePresenters) + require.Len(t, nodes, 1) + n := nodes[0] + assert.Equal(t, cltest.FormatWithPrefixedChainID(chainID, *node.Name), n.ID) + assert.Equal(t, chainID, n.ChainID) + assert.Equal(t, *node.Name, n.Name) + wantConfig, err := toml.Marshal(node) + require.NoError(t, err) + assert.Equal(t, string(wantConfig), n.Config) + assertTableRenders(t, r) + + // Render table and check the fields order + b := new(bytes.Buffer) + rt := cmd.RendererTable{b} + require.NoError(t, nodes.RenderTable(rt)) + renderLines := strings.Split(b.String(), "\n") + assert.Equal(t, 10, len(renderLines)) + assert.Contains(t, renderLines[2], "Name") + assert.Contains(t, renderLines[2], n.Name) + assert.Contains(t, renderLines[3], "Chain ID") + assert.Contains(t, renderLines[3], n.ChainID) + assert.Contains(t, renderLines[4], "State") + assert.Contains(t, renderLines[4], n.State) +} diff --git a/core/cmd/evm_chains_commands.go b/core/cmd/evm_chains_commands.go new file mode 100644 index 00000000000..d4025cfca53 --- /dev/null +++ b/core/cmd/evm_chains_commands.go @@ -0,0 +1,48 @@ +package cmd + +import ( + "strconv" + + "github.com/smartcontractkit/chainlink/v2/core/web/presenters" +) + +// EVMChainPresenter implements TableRenderer for an EVMChainResource. +type EVMChainPresenter struct { + presenters.EVMChainResource +} + +// ToRow presents the EVMChainResource as a slice of strings. +func (p *EVMChainPresenter) ToRow() []string { + return []string{p.GetID(), strconv.FormatBool(p.Enabled), p.Config} +} + +// RenderTable implements TableRenderer +// Just renders a single row +func (p EVMChainPresenter) RenderTable(rt RendererTable) error { + rows := [][]string{} + rows = append(rows, p.ToRow()) + + renderList(chainHeaders, rows, rt.Writer) + + return nil +} + +// EVMChainPresenters implements TableRenderer for a slice of EVMChainPresenters. +type EVMChainPresenters []EVMChainPresenter + +// RenderTable implements TableRenderer +func (ps EVMChainPresenters) RenderTable(rt RendererTable) error { + rows := [][]string{} + + for _, p := range ps { + rows = append(rows, p.ToRow()) + } + + renderList(chainHeaders, rows, rt.Writer) + + return nil +} + +func EVMChainClient(s *Shell) ChainClient { + return newChainClient[EVMChainPresenters](s, "evm") +} diff --git a/core/cmd/evm_chains_commands_test.go b/core/cmd/evm_chains_commands_test.go new file mode 100644 index 00000000000..fa6d7bb519c --- /dev/null +++ b/core/cmd/evm_chains_commands_test.go @@ -0,0 +1,38 @@ +package cmd_test + +import ( + "strconv" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + client2 "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" + "github.com/smartcontractkit/chainlink/v2/core/cmd" + "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" + "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" + "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" +) + +func newRandChainID() *big.Big { + return big.New(testutils.NewRandomEVMChainID()) +} + +func TestShell_IndexEVMChains(t *testing.T) { + t.Parallel() + + app := startNewApplicationV2(t, func(c *chainlink.Config, s *chainlink.Secrets) { + c.EVM[0].Enabled = ptr(true) + c.EVM[0].NonceAutoSync = ptr(false) + c.EVM[0].BalanceMonitor.Enabled = ptr(false) + }) + client, r := app.NewShellAndRenderer() + + require.Nil(t, cmd.EVMChainClient(client).IndexChains(cltest.EmptyCLIContext())) + chains := *r.Renders[0].(*cmd.EVMChainPresenters) + require.Len(t, chains, 1) + c := chains[0] + assert.Equal(t, strconv.Itoa(client2.NullClientChainID), c.ID) + assertTableRenders(t, r) +} diff --git a/core/cmd/evm_node_commands.go b/core/cmd/evm_node_commands.go new file mode 100644 index 00000000000..515ece18a8e --- /dev/null +++ b/core/cmd/evm_node_commands.go @@ -0,0 +1,44 @@ +package cmd + +import ( + "github.com/smartcontractkit/chainlink/v2/core/web/presenters" +) + +// EVMNodePresenter implements TableRenderer for an EVMNodeResource. +type EVMNodePresenter struct { + presenters.EVMNodeResource +} + +// ToRow presents the EVMNodeResource as a slice of strings. +func (p *EVMNodePresenter) ToRow() []string { + return []string{p.Name, p.ChainID, p.State, p.Config} +} + +// RenderTable implements TableRenderer +func (p EVMNodePresenter) RenderTable(rt RendererTable) error { + var rows [][]string + rows = append(rows, p.ToRow()) + renderList(nodeHeaders, rows, rt.Writer) + + return nil +} + +// EVMNodePresenters implements TableRenderer for a slice of EVMNodePresenter. +type EVMNodePresenters []EVMNodePresenter + +// RenderTable implements TableRenderer +func (ps EVMNodePresenters) RenderTable(rt RendererTable) error { + var rows [][]string + + for _, p := range ps { + rows = append(rows, p.ToRow()) + } + + renderList(nodeHeaders, rows, rt.Writer) + + return nil +} + +func NewEVMNodeClient(s *Shell) NodeClient { + return newNodeClient[EVMNodePresenters](s, "evm") +} diff --git a/core/cmd/evm_node_commands_test.go b/core/cmd/evm_node_commands_test.go new file mode 100644 index 00000000000..d743ee28e1b --- /dev/null +++ b/core/cmd/evm_node_commands_test.go @@ -0,0 +1,94 @@ +package cmd_test + +import ( + "bytes" + "strings" + "testing" + + "github.com/pelletier/go-toml/v2" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + commonconfig "github.com/smartcontractkit/chainlink-common/pkg/config" + evmcfg "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/toml" + "github.com/smartcontractkit/chainlink/v2/core/cmd" + "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" + "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" +) + +func assertTableRenders(t *testing.T, r *cltest.RendererMock) { + // Should be no error rendering any of the responses as tables + b := bytes.NewBuffer([]byte{}) + tb := cmd.RendererTable{b} + for _, rn := range r.Renders { + require.NoError(t, tb.Render(rn)) + } +} + +func TestShell_IndexEVMNodes(t *testing.T) { + t.Parallel() + + chainID := newRandChainID() + node1 := evmcfg.Node{ + Name: ptr("Test node 1"), + WSURL: commonconfig.MustParseURL("ws://localhost:8546"), + HTTPURL: commonconfig.MustParseURL("http://localhost:8546"), + SendOnly: ptr(false), + Order: ptr(int32(15)), + } + node2 := evmcfg.Node{ + Name: ptr("Test node 2"), + WSURL: commonconfig.MustParseURL("ws://localhost:8547"), + HTTPURL: commonconfig.MustParseURL("http://localhost:8547"), + SendOnly: ptr(false), + Order: ptr(int32(36)), + } + chain := evmcfg.EVMConfig{ + ChainID: chainID, + Chain: evmcfg.Defaults(chainID), + Nodes: evmcfg.EVMNodes{&node1, &node2}, + } + app := startNewApplicationV2(t, func(c *chainlink.Config, s *chainlink.Secrets) { + c.EVM = evmcfg.EVMConfigs{&chain} + }) + client, r := app.NewShellAndRenderer() + + require.Nil(t, cmd.NewEVMNodeClient(client).IndexNodes(cltest.EmptyCLIContext())) + require.NotEmpty(t, r.Renders) + nodes := *r.Renders[0].(*cmd.EVMNodePresenters) + require.Len(t, nodes, 2) + n1 := nodes[0] + n2 := nodes[1] + assert.Equal(t, chainID.String(), n1.ChainID) + assert.Equal(t, cltest.FormatWithPrefixedChainID(chainID.String(), *node1.Name), n1.ID) + assert.Equal(t, *node1.Name, n1.Name) + wantConfig, err := toml.Marshal(node1) + require.NoError(t, err) + assert.Equal(t, string(wantConfig), n1.Config) + assert.Equal(t, chainID.String(), n2.ChainID) + assert.Equal(t, cltest.FormatWithPrefixedChainID(chainID.String(), *node2.Name), n2.ID) + assert.Equal(t, *node2.Name, n2.Name) + wantConfig2, err := toml.Marshal(node2) + require.NoError(t, err) + assert.Equal(t, string(wantConfig2), n2.Config) + assertTableRenders(t, r) + + // Render table and check the fields order + b := new(bytes.Buffer) + rt := cmd.RendererTable{b} + require.NoError(t, nodes.RenderTable(rt)) + renderLines := strings.Split(b.String(), "\n") + assert.Equal(t, 23, len(renderLines)) + assert.Contains(t, renderLines[2], "Name") + assert.Contains(t, renderLines[2], n1.Name) + assert.Contains(t, renderLines[3], "Chain ID") + assert.Contains(t, renderLines[3], n1.ChainID) + assert.Contains(t, renderLines[4], "State") + assert.Contains(t, renderLines[4], n1.State) + assert.Contains(t, renderLines[12], "Name") + assert.Contains(t, renderLines[12], n2.Name) + assert.Contains(t, renderLines[13], "Chain ID") + assert.Contains(t, renderLines[13], n2.ChainID) + assert.Contains(t, renderLines[14], "State") + assert.Contains(t, renderLines[14], n2.State) +} diff --git a/core/cmd/node_commands_test.go b/core/cmd/node_commands_test.go deleted file mode 100644 index 8a17bad719e..00000000000 --- a/core/cmd/node_commands_test.go +++ /dev/null @@ -1,290 +0,0 @@ -package cmd_test - -import ( - "bytes" - "strings" - "testing" - - "github.com/pelletier/go-toml/v2" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - - "github.com/smartcontractkit/chainlink-common/pkg/config" - coscfg "github.com/smartcontractkit/chainlink-cosmos/pkg/cosmos/config" - solcfg "github.com/smartcontractkit/chainlink-solana/pkg/solana/config" - starkcfg "github.com/smartcontractkit/chainlink-starknet/relayer/pkg/chainlink/config" - evmcfg "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/toml" - - "github.com/smartcontractkit/chainlink/v2/core/cmd" - "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" - "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/cosmostest" - "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/solanatest" - "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" -) - -func assertTableRenders(t *testing.T, r *cltest.RendererMock) { - // Should be no error rendering any of the responses as tables - b := bytes.NewBuffer([]byte{}) - tb := cmd.RendererTable{b} - for _, rn := range r.Renders { - require.NoError(t, tb.Render(rn)) - } -} - -func TestShell_IndexEVMNodes(t *testing.T) { - t.Parallel() - - chainID := newRandChainID() - node1 := evmcfg.Node{ - Name: ptr("Test node 1"), - WSURL: config.MustParseURL("ws://localhost:8546"), - HTTPURL: config.MustParseURL("http://localhost:8546"), - SendOnly: ptr(false), - Order: ptr(int32(15)), - } - node2 := evmcfg.Node{ - Name: ptr("Test node 2"), - WSURL: config.MustParseURL("ws://localhost:8547"), - HTTPURL: config.MustParseURL("http://localhost:8547"), - SendOnly: ptr(false), - Order: ptr(int32(36)), - } - chain := evmcfg.EVMConfig{ - ChainID: chainID, - Chain: evmcfg.Defaults(chainID), - Nodes: evmcfg.EVMNodes{&node1, &node2}, - } - app := startNewApplicationV2(t, func(c *chainlink.Config, s *chainlink.Secrets) { - c.EVM = evmcfg.EVMConfigs{&chain} - }) - client, r := app.NewShellAndRenderer() - - require.NoError(t, cmd.NewNodeClient(client, "evm").IndexNodes(cltest.EmptyCLIContext())) - require.NotEmpty(t, r.Renders) - nodes := *r.Renders[0].(*cmd.NodePresenters) - require.Len(t, nodes, 2) - n1 := nodes[0] - n2 := nodes[1] - assert.Equal(t, chainID.String(), n1.ChainID) - assert.Equal(t, cltest.FormatWithPrefixedChainID(chainID.String(), *node1.Name), n1.ID) - assert.Equal(t, *node1.Name, n1.Name) - wantConfig, err := toml.Marshal(node1) - require.NoError(t, err) - assert.Equal(t, string(wantConfig), n1.Config) - assert.Equal(t, chainID.String(), n2.ChainID) - assert.Equal(t, cltest.FormatWithPrefixedChainID(chainID.String(), *node2.Name), n2.ID) - assert.Equal(t, *node2.Name, n2.Name) - wantConfig2, err := toml.Marshal(node2) - require.NoError(t, err) - assert.Equal(t, string(wantConfig2), n2.Config) - assertTableRenders(t, r) - - // Render table and check the fields order - b := new(bytes.Buffer) - rt := cmd.RendererTable{b} - require.NoError(t, nodes.RenderTable(rt)) - renderLines := strings.Split(b.String(), "\n") - assert.Len(t, renderLines, 23) - assert.Contains(t, renderLines[2], "Name") - assert.Contains(t, renderLines[2], n1.Name) - assert.Contains(t, renderLines[3], "Chain ID") - assert.Contains(t, renderLines[3], n1.ChainID) - assert.Contains(t, renderLines[4], "State") - assert.Contains(t, renderLines[4], n1.State) - assert.Contains(t, renderLines[12], "Name") - assert.Contains(t, renderLines[12], n2.Name) - assert.Contains(t, renderLines[13], "Chain ID") - assert.Contains(t, renderLines[13], n2.ChainID) - assert.Contains(t, renderLines[14], "State") - assert.Contains(t, renderLines[14], n2.State) -} - -func cosmosStartNewApplication(t *testing.T, cfgs ...*coscfg.TOMLConfig) *cltest.TestApplication { - for i := range cfgs { - cfgs[i].SetDefaults() - } - return startNewApplicationV2(t, func(c *chainlink.Config, s *chainlink.Secrets) { - c.Cosmos = cfgs - c.EVM = nil - }) -} - -func TestShell_IndexCosmosNodes(t *testing.T) { - t.Parallel() - - chainID := cosmostest.RandomChainID() - node := coscfg.Node{ - Name: ptr("second"), - TendermintURL: config.MustParseURL("http://tender.mint.test/bombay-12"), - } - chain := coscfg.TOMLConfig{ - ChainID: ptr(chainID), - Enabled: ptr(true), - Nodes: coscfg.Nodes{&node}, - } - app := cosmosStartNewApplication(t, &chain) - client, r := app.NewShellAndRenderer() - require.NoError(t, cmd.NewNodeClient(client, "cosmos").IndexNodes(cltest.EmptyCLIContext())) - require.NotEmpty(t, r.Renders) - nodes := *r.Renders[0].(*cmd.NodePresenters) - require.Len(t, nodes, 1) - n := nodes[0] - assert.Equal(t, cltest.FormatWithPrefixedChainID(chainID, *node.Name), n.ID) - assert.Equal(t, chainID, n.ChainID) - assert.Equal(t, *node.Name, n.Name) - wantConfig, err := toml.Marshal(node) - require.NoError(t, err) - assert.Equal(t, string(wantConfig), n.Config) - assertTableRenders(t, r) - - // Render table and check the fields order - b := new(bytes.Buffer) - rt := cmd.RendererTable{b} - require.NoError(t, nodes.RenderTable(rt)) - renderLines := strings.Split(b.String(), "\n") - assert.Len(t, renderLines, 10) - assert.Contains(t, renderLines[2], "Name") - assert.Contains(t, renderLines[2], n.Name) - assert.Contains(t, renderLines[3], "Chain ID") - assert.Contains(t, renderLines[3], n.ChainID) - assert.Contains(t, renderLines[4], "State") - assert.Contains(t, renderLines[4], n.State) -} -func solanaStartNewApplication(t *testing.T, cfgs ...*solcfg.TOMLConfig) *cltest.TestApplication { - for i := range cfgs { - cfgs[i].Chain.SetDefaults() - } - return startNewApplicationV2(t, func(c *chainlink.Config, s *chainlink.Secrets) { - c.Solana = cfgs - c.EVM = nil - }) -} - -func TestShell_IndexSolanaNodes(t *testing.T) { - t.Parallel() - - id := solanatest.RandomChainID() - node1 := solcfg.Node{ - Name: ptr("first"), - URL: config.MustParseURL("https://solana1.example"), - } - node2 := solcfg.Node{ - Name: ptr("second"), - URL: config.MustParseURL("https://solana2.example"), - } - chain := solcfg.TOMLConfig{ - ChainID: &id, - Nodes: solcfg.Nodes{&node1, &node2}, - } - app := solanaStartNewApplication(t, &chain) - client, r := app.NewShellAndRenderer() - - require.NoError(t, cmd.NewNodeClient(client, "solana").IndexNodes(cltest.EmptyCLIContext())) - require.NotEmpty(t, r.Renders) - nodes := *r.Renders[0].(*cmd.NodePresenters) - require.Len(t, nodes, 2) - n1 := nodes[0] - n2 := nodes[1] - assert.Equal(t, id, n1.ChainID) - assert.Equal(t, cltest.FormatWithPrefixedChainID(id, *node1.Name), n1.ID) - assert.Equal(t, *node1.Name, n1.Name) - wantConfig, err := toml.Marshal(node1) - require.NoError(t, err) - assert.Equal(t, string(wantConfig), n1.Config) - assert.Equal(t, id, n2.ChainID) - assert.Equal(t, cltest.FormatWithPrefixedChainID(id, *node2.Name), n2.ID) - assert.Equal(t, *node2.Name, n2.Name) - wantConfig2, err := toml.Marshal(node2) - require.NoError(t, err) - assert.Equal(t, string(wantConfig2), n2.Config) - assertTableRenders(t, r) - - // Render table and check the fields order - b := new(bytes.Buffer) - rt := cmd.RendererTable{b} - require.NoError(t, nodes.RenderTable(rt)) - renderLines := strings.Split(b.String(), "\n") - assert.Len(t, renderLines, 19) - assert.Contains(t, renderLines[2], "Name") - assert.Contains(t, renderLines[2], n1.Name) - assert.Contains(t, renderLines[3], "Chain ID") - assert.Contains(t, renderLines[3], n1.ChainID) - assert.Contains(t, renderLines[4], "State") - assert.Contains(t, renderLines[4], n1.State) - assert.Contains(t, renderLines[10], "Name") - assert.Contains(t, renderLines[10], n2.Name) - assert.Contains(t, renderLines[11], "Chain ID") - assert.Contains(t, renderLines[11], n2.ChainID) - assert.Contains(t, renderLines[12], "State") - assert.Contains(t, renderLines[12], n2.State) -} - -func starknetStartNewApplication(t *testing.T, cfgs ...*starkcfg.TOMLConfig) *cltest.TestApplication { - for i := range cfgs { - cfgs[i].SetDefaults() - } - return startNewApplicationV2(t, func(c *chainlink.Config, s *chainlink.Secrets) { - c.Starknet = cfgs - c.EVM = nil - c.Solana = nil - }) -} - -func TestShell_IndexStarkNetNodes(t *testing.T) { - t.Parallel() - - id := "starknet chain ID" - node1 := starkcfg.Node{ - Name: ptr("first"), - URL: config.MustParseURL("https://starknet1.example"), - } - node2 := starkcfg.Node{ - Name: ptr("second"), - URL: config.MustParseURL("https://starknet2.example"), - } - chain := starkcfg.TOMLConfig{ - ChainID: &id, - Nodes: starkcfg.Nodes{&node1, &node2}, - } - app := starknetStartNewApplication(t, &chain) - client, r := app.NewShellAndRenderer() - - require.NoError(t, cmd.NewNodeClient(client, "starknet").IndexNodes(cltest.EmptyCLIContext())) - require.NotEmpty(t, r.Renders) - nodes := *r.Renders[0].(*cmd.NodePresenters) - require.Len(t, nodes, 2) - n1 := nodes[0] - n2 := nodes[1] - assert.Equal(t, id, n1.ChainID) - assert.Equal(t, cltest.FormatWithPrefixedChainID(id, *node1.Name), n1.ID) - assert.Equal(t, *node1.Name, n1.Name) - wantConfig, err := toml.Marshal(node1) - require.NoError(t, err) - assert.Equal(t, string(wantConfig), n1.Config) - assert.Equal(t, id, n2.ChainID) - assert.Equal(t, cltest.FormatWithPrefixedChainID(id, *node2.Name), n2.ID) - assert.Equal(t, *node2.Name, n2.Name) - wantConfig2, err := toml.Marshal(node2) - require.NoError(t, err) - assert.Equal(t, string(wantConfig2), n2.Config) - assertTableRenders(t, r) - - // Render table and check the fields order - b := new(bytes.Buffer) - rt := cmd.RendererTable{b} - require.NoError(t, nodes.RenderTable(rt)) - renderLines := strings.Split(b.String(), "\n") - assert.Len(t, renderLines, 17) - assert.Contains(t, renderLines[2], "Name") - assert.Contains(t, renderLines[2], n1.Name) - assert.Contains(t, renderLines[3], "Chain ID") - assert.Contains(t, renderLines[3], n1.ChainID) - assert.Contains(t, renderLines[4], "State") - assert.Contains(t, renderLines[4], n1.State) - assert.Contains(t, renderLines[9], "Name") - assert.Contains(t, renderLines[9], n2.Name) - assert.Contains(t, renderLines[10], "Chain ID") - assert.Contains(t, renderLines[10], n2.ChainID) - assert.Contains(t, renderLines[11], "State") - assert.Contains(t, renderLines[11], n2.State) -} diff --git a/core/cmd/nodes_commands.go b/core/cmd/nodes_commands.go index 0420ef66ec4..efee10bb156 100644 --- a/core/cmd/nodes_commands.go +++ b/core/cmd/nodes_commands.go @@ -2,25 +2,25 @@ package cmd import ( "fmt" - "maps" - "slices" "strings" "github.com/urfave/cli" - - "github.com/smartcontractkit/chainlink/v2/core/services/relay" - "github.com/smartcontractkit/chainlink/v2/core/web/presenters" ) -func initNodeSubCmds(s *Shell) []cli.Command { - cmds := []cli.Command{} - for _, network := range slices.Sorted(maps.Keys(relay.SupportedNetworks)) { - if network == relay.NetworkDummy { - continue - } - cmds = append(cmds, nodeCommand(network, NewNodeClient(s, network))) - } - return cmds +func initCosmosNodeSubCmd(s *Shell) cli.Command { + return nodeCommand("Cosmos", NewCosmosNodeClient(s)) +} + +func initStarkNetNodeSubCmd(s *Shell) cli.Command { + return nodeCommand("StarkNet", NewStarkNetNodeClient(s)) +} + +func initEVMNodeSubCmd(s *Shell) cli.Command { + return nodeCommand("EVM", NewEVMNodeClient(s)) +} + +func initSolanaNodeSubCmd(s *Shell) cli.Command { + return nodeCommand("Solana", NewSolanaNodeClient(s)) } // nodeCommand returns a cli.Command with subcommands for the given NodeClient. @@ -40,41 +40,6 @@ func nodeCommand(typ string, client NodeClient) cli.Command { } } -// EVMNodePresenter implements TableRenderer for an EVMNodeResource. -type NodePresenter struct { - presenters.NodeResource -} - -// ToRow presents the EVMNodeResource as a slice of strings. -func (p *NodePresenter) ToRow() []string { - return []string{p.Name, p.ChainID, p.State, p.Config} -} - -// RenderTable implements TableRenderer -func (p NodePresenter) RenderTable(rt RendererTable) error { - var rows [][]string - rows = append(rows, p.ToRow()) - renderList(nodeHeaders, rows, rt.Writer) - - return nil -} - -// NodePresenters implements TableRenderer for a slice of NodePresenter. -type NodePresenters []NodePresenter - -// RenderTable implements TableRenderer -func (ps NodePresenters) RenderTable(rt RendererTable) error { - rows := [][]string{} - - for _, p := range ps { - rows = append(rows, p.ToRow()) - } - - renderList(nodeHeaders, rows, rt.Writer) - - return nil -} - // NodeClient is a generic client interface for any of node. type NodeClient interface { IndexNodes(c *cli.Context) error @@ -87,10 +52,10 @@ type nodeClient[P TableRenderer] struct { // newNodeClient returns a new NodeClient for a particular type of NodeStatus. // P is a TableRenderer for []types.NodeStatus. -func NewNodeClient(s *Shell, network string) NodeClient { - return &nodeClient[NodePresenters]{ +func newNodeClient[P TableRenderer](s *Shell, name string) NodeClient { + return &nodeClient[P]{ Shell: s, - path: "/v2/nodes/" + network, + path: "/v2/nodes/" + name, } } diff --git a/core/cmd/shell.go b/core/cmd/shell.go index 94664a3cf3d..966fa1a0ff8 100644 --- a/core/cmd/shell.go +++ b/core/cmd/shell.go @@ -25,7 +25,6 @@ import ( "github.com/gin-gonic/gin" "github.com/jmoiron/sqlx" "github.com/pkg/errors" - "github.com/prometheus/client_golang/prometheus" "github.com/urfave/cli" "go.opentelemetry.io/otel" "go.opentelemetry.io/otel/attribute" @@ -37,7 +36,6 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/loop" "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" "github.com/smartcontractkit/chainlink-common/pkg/utils/mailbox" - "github.com/smartcontractkit/chainlink/v2/core/build" "github.com/smartcontractkit/chainlink/v2/core/capabilities" "github.com/smartcontractkit/chainlink/v2/core/chains/legacyevm" @@ -53,7 +51,6 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/mercury/wsrpc/cache" "github.com/smartcontractkit/chainlink/v2/core/services/versioning" "github.com/smartcontractkit/chainlink/v2/core/services/webhook" - "github.com/smartcontractkit/chainlink/v2/core/services/workflows" "github.com/smartcontractkit/chainlink/v2/core/sessions" "github.com/smartcontractkit/chainlink/v2/core/static" "github.com/smartcontractkit/chainlink/v2/core/store/migrate" @@ -65,7 +62,7 @@ import ( var ( initGlobalsOnce sync.Once - ginPrometheus *ginprom.Prometheus + prometheus *ginprom.Prometheus grpcOpts loop.GRPCOpts ) @@ -74,7 +71,7 @@ func initGlobals(cfgProm config.Prometheus, cfgTracing config.Tracing, cfgTeleme var err error initGlobalsOnce.Do(func() { err = func() error { - ginPrometheus = ginprom.New(ginprom.Namespace("service"), ginprom.Token(cfgProm.AuthToken())) + prometheus = ginprom.New(ginprom.Namespace("service"), ginprom.Token(cfgProm.AuthToken())) grpcOpts = loop.NewGRPCOpts(nil) // default prometheus.Registerer otel.SetErrorHandler(otel.ErrorHandlerFunc(func(err error) { @@ -112,10 +109,6 @@ func initGlobals(cfgProm config.Prometheus, cfgTracing config.Tracing, cfgTeleme AuthPublicKeyHex: csaPubKeyHex, AuthHeaders: beholderAuthHeaders, } - // note: due to the OTEL specification, all histogram buckets - // must be defined when the beholder client is created - clientCfg.MetricViews = append(clientCfg.MetricViews, workflows.MetricViews()...) - if tracingCfg.Enabled { clientCfg.TraceSpanExporter, err = tracingCfg.NewSpanExporter() if err != nil { @@ -146,7 +139,6 @@ type Shell struct { Renderer Config chainlink.GeneralConfig // initialized in Before Logger logger.Logger // initialized in Before - Registerer prometheus.Registerer // initialized in Before CloseLogger func() error // called in After AppFactory AppFactory KeyStoreAuthenticator TerminalKeyStoreAuthenticator @@ -186,14 +178,14 @@ func (s *Shell) configExitErr(validateFn func() error) cli.ExitCoder { // AppFactory implements the NewApplication method. type AppFactory interface { - NewApplication(ctx context.Context, cfg chainlink.GeneralConfig, appLggr logger.Logger, appRegisterer prometheus.Registerer, db *sqlx.DB, keyStoreAuthenticator TerminalKeyStoreAuthenticator) (chainlink.Application, error) + NewApplication(ctx context.Context, cfg chainlink.GeneralConfig, appLggr logger.Logger, db *sqlx.DB, keyStoreAuthenticator TerminalKeyStoreAuthenticator) (chainlink.Application, error) } // ChainlinkAppFactory is used to create a new Application. type ChainlinkAppFactory struct{} // NewApplication returns a new instance of the node with the given config. -func (n ChainlinkAppFactory) NewApplication(ctx context.Context, cfg chainlink.GeneralConfig, appLggr logger.Logger, appRegisterer prometheus.Registerer, db *sqlx.DB, keyStoreAuthenticator TerminalKeyStoreAuthenticator) (app chainlink.Application, err error) { +func (n ChainlinkAppFactory) NewApplication(ctx context.Context, cfg chainlink.GeneralConfig, appLggr logger.Logger, db *sqlx.DB, keyStoreAuthenticator TerminalKeyStoreAuthenticator) (app chainlink.Application, err error) { err = migrate.SetMigrationENVVars(cfg) if err != nil { return nil, err @@ -245,7 +237,6 @@ func (n ChainlinkAppFactory) NewApplication(ctx context.Context, cfg chainlink.G // create the relayer-chain interoperators from application configuration relayerFactory := chainlink.RelayerFactory{ Logger: appLggr, - Registerer: appRegisterer, LoopRegistry: loopRegistry, GRPCOpts: grpcOpts, MercuryPool: mercuryPool, @@ -255,9 +246,9 @@ func (n ChainlinkAppFactory) NewApplication(ctx context.Context, cfg chainlink.G } evmFactoryCfg := chainlink.EVMFactoryConfig{ - CSAETHKeystore: keyStore, - ChainOpts: legacyevm.ChainOpts{AppConfig: cfg, MailMon: mailMon, DS: ds}, - MercuryConfig: cfg.Mercury(), + CSAETHKeystore: keyStore, + ChainOpts: legacyevm.ChainOpts{AppConfig: cfg, MailMon: mailMon, DS: ds}, + MercuryTransmitter: cfg.Mercury().Transmitter(), } // evm always enabled for backward compatibility // TODO BCF-2510 this needs to change in order to clear the path for EVM extraction @@ -275,7 +266,6 @@ func (n ChainlinkAppFactory) NewApplication(ctx context.Context, cfg chainlink.G solanaCfg := chainlink.SolanaFactoryConfig{ Keystore: keyStore.Solana(), TOMLConfigs: cfg.SolanaConfigs(), - DS: ds, } initOps = append(initOps, chainlink.InitSolana(ctx, relayerFactory, solanaCfg)) } @@ -399,7 +389,7 @@ func takeBackupIfVersionUpgrade(dbUrl url.URL, rootDir string, cfg periodicbacku } // Because backups can take a long time we must start a "fake" health report to prevent - // node shutdown because of healthcheck fail/timeout + //node shutdown because of healthcheck fail/timeout err = databaseBackup.RunBackup(appv.String()) return err } @@ -435,7 +425,7 @@ func (n ChainlinkRunner) Run(ctx context.Context, app chainlink.Application) err return errors.New("You must specify at least one port to listen on") } - handler, err := web.NewRouter(app, ginPrometheus) + handler, err := web.NewRouter(app, prometheus) if err != nil { return errors.Wrap(err, "failed to create web router") } diff --git a/core/cmd/shell_local.go b/core/cmd/shell_local.go index 1fdc1a46d34..50411e10d42 100644 --- a/core/cmd/shell_local.go +++ b/core/cmd/shell_local.go @@ -35,8 +35,6 @@ import ( cutils "github.com/smartcontractkit/chainlink-common/pkg/utils" - pgcommon "github.com/smartcontractkit/chainlink-common/pkg/sqlutil/pg" - "github.com/smartcontractkit/chainlink/v2/core/build" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/gas" @@ -49,6 +47,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/sessions" "github.com/smartcontractkit/chainlink/v2/core/shutdown" "github.com/smartcontractkit/chainlink/v2/core/static" + "github.com/smartcontractkit/chainlink/v2/core/store/dialects" "github.com/smartcontractkit/chainlink/v2/core/store/migrate" "github.com/smartcontractkit/chainlink/v2/core/utils" "github.com/smartcontractkit/chainlink/v2/core/web" @@ -383,7 +382,7 @@ func (s *Shell) runNode(c *cli.Context) error { // From now on, DB locks and DB connection will be released on every return. // Keep watching on logger.Fatal* calls and os.Exit(), because defer will not be executed. - app, err := s.AppFactory.NewApplication(rootCtx, s.Config, s.Logger, s.Registerer, ldb.DB(), s.KeyStoreAuthenticator) + app, err := s.AppFactory.NewApplication(rootCtx, s.Config, s.Logger, ldb.DB(), s.KeyStoreAuthenticator) if err != nil { return s.errorOut(errors.Wrap(err, "fatal error instantiating application")) } @@ -470,12 +469,14 @@ func (s *Shell) runNode(c *cli.Context) error { } } - err2 := app.GetKeyStore().Workflow().EnsureKey(rootCtx) - if err2 != nil { - return errors.Wrap(err2, "failed to ensure workflow key") + if s.Config.Capabilities().Peering().Enabled() { + err2 := app.GetKeyStore().Workflow().EnsureKey(rootCtx) + if err2 != nil { + return errors.Wrap(err2, "failed to ensure workflow key") + } } - err2 = app.GetKeyStore().CSA().EnsureKey(rootCtx) + err2 := app.GetKeyStore().CSA().EnsureKey(rootCtx) if err2 != nil { return errors.Wrap(err2, "failed to ensure CSA key") } @@ -628,7 +629,7 @@ func (s *Shell) RebroadcastTransactions(c *cli.Context) (err error) { } defer lggr.ErrorIfFn(db.Close, "Error closing db") - app, err := s.AppFactory.NewApplication(ctx, s.Config, lggr, s.Registerer, db, s.KeyStoreAuthenticator) + app, err := s.AppFactory.NewApplication(ctx, s.Config, lggr, db, s.KeyStoreAuthenticator) if err != nil { return s.errorOut(errors.Wrap(err, "fatal error instantiating application")) } @@ -675,16 +676,18 @@ func (s *Shell) RebroadcastTransactions(c *cli.Context) (err error) { orm := txmgr.NewTxStore(app.GetDB(), lggr) txBuilder := txmgr.NewEvmTxAttemptBuilder(*ethClient.ConfiguredChainID(), chain.Config().EVM().GasEstimator(), keyStore.Eth(), nil) + cfg := txmgr.NewEvmTxmConfig(chain.Config().EVM()) feeCfg := txmgr.NewEvmTxmFeeConfig(chain.Config().EVM().GasEstimator()) stuckTxDetector := txmgr.NewStuckTxDetector(lggr, ethClient.ConfiguredChainID(), "", assets.NewWei(assets.NewEth(100).ToInt()), chain.Config().EVM().Transactions().AutoPurge(), nil, orm, ethClient) ec := txmgr.NewEvmConfirmer(orm, txmgr.NewEvmTxmClient(ethClient, chain.Config().EVM().NodePool().Errors()), - feeCfg, chain.Config().EVM().Transactions(), app.GetConfig().Database(), keyStore.Eth(), txBuilder, chain.Logger(), stuckTxDetector, chain.HeadTracker()) + cfg, feeCfg, chain.Config().EVM().Transactions(), app.GetConfig().Database(), keyStore.Eth(), txBuilder, chain.Logger(), stuckTxDetector, chain.HeadTracker()) totalNonces := endingNonce - beginningNonce + 1 nonces := make([]evmtypes.Nonce, totalNonces) for i := int64(0); i < totalNonces; i++ { nonces[i] = evmtypes.Nonce(beginningNonce + i) } if gasPriceWei <= math.MaxInt64 { + //nolint:gosec // disable G115 return s.errorOut(ec.ForceRebroadcast(ctx, nonces, gas.EvmFee{GasPrice: assets.NewWeiI(int64(gasPriceWei))}, address, uint64(overrideGasLimit))) } return s.errorOut(fmt.Errorf("integer overflow conversion error. GasPrice: %v", gasPriceWei)) @@ -806,7 +809,7 @@ func (s *Shell) PrepareTestDatabase(c *cli.Context) error { // Creating pristine DB copy to speed up FullTestDB dbUrl := cfg.Database().URL() - db, err := sqlx.Open(string(pgcommon.Postgres), dbUrl.String()) + db, err := sqlx.Open(string(dialects.Postgres), dbUrl.String()) if err != nil { return s.errorOut(err) } @@ -1089,7 +1092,7 @@ type dbConfig interface { MaxOpenConns() int MaxIdleConns() int URL() url.URL - Dialect() pgcommon.DialectName + Dialect() dialects.DialectName } func newConnection(ctx context.Context, cfg dbConfig) (*sqlx.DB, error) { @@ -1105,7 +1108,7 @@ func dropAndCreateDB(parsed url.URL, force bool) (err error) { // to a different one. template1 should be present on all postgres installations dbname := parsed.Path[1:] parsed.Path = "/template1" - db, err := sql.Open(string(pgcommon.Postgres), parsed.String()) + db, err := sql.Open(string(dialects.Postgres), parsed.String()) if err != nil { return fmt.Errorf("unable to open postgres database for creating test db: %+v", err) } @@ -1204,7 +1207,7 @@ func checkSchema(dbURL url.URL, prevSchema string) error { } func insertFixtures(dbURL url.URL, pathToFixtures string) (err error) { - db, err := sql.Open(string(pgcommon.Postgres), dbURL.String()) + db, err := sql.Open(string(dialects.Postgres), dbURL.String()) if err != nil { return fmt.Errorf("unable to open postgres database for creating test db: %+v", err) } @@ -1273,7 +1276,7 @@ func (s *Shell) RemoveBlocks(c *cli.Context) error { // From now on, DB locks and DB connection will be released on every return. // Keep watching on logger.Fatal* calls and os.Exit(), because defer will not be executed. - app, err := s.AppFactory.NewApplication(ctx, s.Config, s.Logger, s.Registerer, ldb.DB(), s.KeyStoreAuthenticator) + app, err := s.AppFactory.NewApplication(ctx, s.Config, s.Logger, ldb.DB(), s.KeyStoreAuthenticator) if err != nil { return s.errorOut(errors.Wrap(err, "fatal error instantiating application")) } diff --git a/core/cmd/shell_local_test.go b/core/cmd/shell_local_test.go index 7cdc8c21840..78254c0279e 100644 --- a/core/cmd/shell_local_test.go +++ b/core/cmd/shell_local_test.go @@ -10,7 +10,6 @@ import ( "time" commonconfig "github.com/smartcontractkit/chainlink-common/pkg/config" - pgcommon "github.com/smartcontractkit/chainlink-common/pkg/sqlutil/pg" "github.com/smartcontractkit/chainlink-common/pkg/utils/mailbox" "github.com/smartcontractkit/chainlink/v2/common/client" @@ -30,6 +29,7 @@ import ( chainlinkmocks "github.com/smartcontractkit/chainlink/v2/core/services/chainlink/mocks" evmrelayer "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm" "github.com/smartcontractkit/chainlink/v2/core/sessions/localauth" + "github.com/smartcontractkit/chainlink/v2/core/store/dialects" "github.com/smartcontractkit/chainlink/v2/core/store/models" "github.com/smartcontractkit/chainlink/v2/core/utils" "github.com/smartcontractkit/chainlink/v2/core/utils/testutils/heavyweight" @@ -283,7 +283,7 @@ func TestShell_RebroadcastTransactions_Txm(t *testing.T) { // test multiple connections to the database, and changes made within // the transaction cannot be seen from another connection. config, sqlxDB := heavyweight.FullTestDBV2(t, func(c *chainlink.Config, s *chainlink.Secrets) { - c.Database.Dialect = pgcommon.Postgres + c.Database.Dialect = dialects.Postgres // evm config is used in this test. but if set, it must be pass config validation. // simplest to make it nil c.EVM = nil @@ -363,7 +363,7 @@ func TestShell_RebroadcastTransactions_OutsideRange_Txm(t *testing.T) { // test multiple connections to the database, and changes made within // the transaction cannot be seen from another connection. config, sqlxDB := heavyweight.FullTestDBV2(t, func(c *chainlink.Config, s *chainlink.Secrets) { - c.Database.Dialect = pgcommon.Postgres + c.Database.Dialect = dialects.Postgres // evm config is used in this test. but if set, it must be pass config validation. // simplest to make it nil c.EVM = nil @@ -441,7 +441,7 @@ func TestShell_RebroadcastTransactions_AddressCheck(t *testing.T) { for _, test := range tests { t.Run(test.name, func(t *testing.T) { config, sqlxDB := heavyweight.FullTestDBV2(t, func(c *chainlink.Config, s *chainlink.Secrets) { - c.Database.Dialect = pgcommon.Postgres + c.Database.Dialect = dialects.Postgres c.EVM = nil // seems to be needed for config validate @@ -499,7 +499,7 @@ func TestShell_RebroadcastTransactions_AddressCheck(t *testing.T) { func TestShell_CleanupChainTables(t *testing.T) { // Just check if it doesn't error, command itself shouldn't be changed unless major schema changes were made. // It would be really hard to write a test that accounts for schema changes, so this should be enough to alarm us that something broke. - config, _ := heavyweight.FullTestDBV2(t, func(c *chainlink.Config, s *chainlink.Secrets) { c.Database.Dialect = pgcommon.Postgres }) + config, _ := heavyweight.FullTestDBV2(t, func(c *chainlink.Config, s *chainlink.Secrets) { c.Database.Dialect = dialects.Postgres }) client := cmd.Shell{ Config: config, Logger: logger.TestLogger(t), diff --git a/core/cmd/shell_remote_test.go b/core/cmd/shell_remote_test.go index 0bf5067d364..f4661a58e82 100644 --- a/core/cmd/shell_remote_test.go +++ b/core/cmd/shell_remote_test.go @@ -463,6 +463,36 @@ func TestShell_ChangePassword(t *testing.T) { require.Contains(t, err.Error(), "Unauthorized") } +func TestShell_Profile_InvalidSecondsParam(t *testing.T) { + t.Parallel() + + app := startNewApplicationV2(t, nil) + u := cltest.NewUserWithSession(t, app.AuthenticationProvider()) + enteredStrings := []string{u.Email, cltest.Password} + prompter := &cltest.MockCountingPrompter{T: t, EnteredStrings: enteredStrings} + + client := app.NewAuthenticatingShell(prompter) + + set := flag.NewFlagSet("test", 0) + flagSetApplyFromAction(client.RemoteLogin, set, "") + + require.NoError(t, set.Set("file", "../internal/fixtures/apicredentials")) + require.NoError(t, set.Set("bypass-version-check", "true")) + + c := cli.NewContext(nil, set, nil) + err := client.RemoteLogin(c) + require.NoError(t, err) + + // pick a value larger than the default http service write timeout + d := app.Config.WebServer().HTTPWriteTimeout() + 2*time.Second + set.Uint("seconds", uint(d.Seconds()), "") + tDir := t.TempDir() + set.String("output_dir", tDir, "") + err = client.Profile(cli.NewContext(nil, set, nil)) + wantErr := cmd.ErrProfileTooLong + require.ErrorAs(t, err, &wantErr) +} + func TestShell_Profile(t *testing.T) { t.Parallel() diff --git a/core/cmd/shell_test.go b/core/cmd/shell_test.go index e73e1d51f24..13b914ba1c7 100644 --- a/core/cmd/shell_test.go +++ b/core/cmd/shell_test.go @@ -18,10 +18,8 @@ import ( "github.com/urfave/cli" commoncfg "github.com/smartcontractkit/chainlink-common/pkg/config" - "github.com/smartcontractkit/chainlink-common/pkg/sqlutil/sqltest" solcfg "github.com/smartcontractkit/chainlink-solana/pkg/solana/config" stkcfg "github.com/smartcontractkit/chainlink-starknet/relayer/pkg/chainlink/config" - "github.com/smartcontractkit/chainlink/v2/core/cmd" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" @@ -355,7 +353,6 @@ func TestSetupSolanaRelayer(t *testing.T) { lggr := logger.TestLogger(t) reg := plugins.NewLoopRegistry(lggr, nil, nil, nil, "") ks := mocks.NewSolana(t) - ds := sqltest.NewNoOpDataSource() // config 3 chains but only enable 2 => should only be 2 relayer nEnabledChains := 2 @@ -398,14 +395,9 @@ func TestSetupSolanaRelayer(t *testing.T) { LoopRegistry: reg, } - cfg := chainlink.SolanaFactoryConfig{ - Keystore: ks, - TOMLConfigs: tConfig.SolanaConfigs(), - DS: ds} - // not parallel; shared state t.Run("no plugin", func(t *testing.T) { - relayers, err := rf.NewSolana(cfg) + relayers, err := rf.NewSolana(ks, tConfig.SolanaConfigs()) require.NoError(t, err) require.NotNil(t, relayers) require.Len(t, relayers, nEnabledChains) @@ -416,7 +408,7 @@ func TestSetupSolanaRelayer(t *testing.T) { t.Run("plugin", func(t *testing.T) { t.Setenv("CL_SOLANA_CMD", "phony_solana_cmd") - relayers, err := rf.NewSolana(cfg) + relayers, err := rf.NewSolana(ks, tConfig.SolanaConfigs()) require.NoError(t, err) require.NotNil(t, relayers) require.Len(t, relayers, nEnabledChains) @@ -441,21 +433,16 @@ func TestSetupSolanaRelayer(t *testing.T) { }, } }) - dupCfg := chainlink.SolanaFactoryConfig{ - Keystore: ks, - TOMLConfigs: duplicateConfig.SolanaConfigs(), - DS: ds, - } // not parallel; shared state t.Run("no plugin, duplicate chains", func(t *testing.T) { - _, err := rf.NewSolana(dupCfg) + _, err := rf.NewSolana(ks, duplicateConfig.SolanaConfigs()) require.Error(t, err) }) t.Run("plugin, duplicate chains", func(t *testing.T) { t.Setenv("CL_SOLANA_CMD", "phony_solana_cmd") - _, err := rf.NewSolana(dupCfg) + _, err := rf.NewSolana(ks, duplicateConfig.SolanaConfigs()) require.Error(t, err) }) @@ -463,11 +450,7 @@ func TestSetupSolanaRelayer(t *testing.T) { t.Setenv("CL_SOLANA_CMD", "phony_solana_cmd") t.Setenv("CL_SOLANA_ENV", "fake_path") - _, err := rf.NewSolana(chainlink.SolanaFactoryConfig{ - Keystore: ks, - TOMLConfigs: t2Config.SolanaConfigs(), - DS: ds, - }) + _, err := rf.NewSolana(ks, t2Config.SolanaConfigs()) require.Error(t, err) require.Contains(t, err.Error(), "failed to parse Solana env file") }) @@ -475,7 +458,7 @@ func TestSetupSolanaRelayer(t *testing.T) { t.Run("plugin already registered", func(t *testing.T) { t.Setenv("CL_SOLANA_CMD", "phony_solana_cmd") - _, err := rf.NewSolana(cfg) + _, err := rf.NewSolana(ks, tConfig.SolanaConfigs()) require.Error(t, err) require.Contains(t, err.Error(), "failed to create Solana LOOP command") }) diff --git a/core/cmd/solana_chains_commands.go b/core/cmd/solana_chains_commands.go new file mode 100644 index 00000000000..aa2a07c0f8c --- /dev/null +++ b/core/cmd/solana_chains_commands.go @@ -0,0 +1,48 @@ +package cmd + +import ( + "strconv" + + "github.com/smartcontractkit/chainlink/v2/core/web/presenters" +) + +// SolanaChainPresenter implements TableRenderer for a SolanaChainResource +type SolanaChainPresenter struct { + presenters.SolanaChainResource +} + +// ToRow presents the SolanaChainResource as a slice of strings. +func (p *SolanaChainPresenter) ToRow() []string { + return []string{p.GetID(), strconv.FormatBool(p.Enabled), p.Config} +} + +// RenderTable implements TableRenderer +// Just renders a single row +func (p SolanaChainPresenter) RenderTable(rt RendererTable) error { + rows := [][]string{} + rows = append(rows, p.ToRow()) + + renderList(chainHeaders, rows, rt.Writer) + + return nil +} + +// SolanaChainPresenters implements TableRenderer for a slice of SolanaChainPresenters. +type SolanaChainPresenters []SolanaChainPresenter + +// RenderTable implements TableRenderer +func (ps SolanaChainPresenters) RenderTable(rt RendererTable) error { + rows := [][]string{} + + for _, p := range ps { + rows = append(rows, p.ToRow()) + } + + renderList(chainHeaders, rows, rt.Writer) + + return nil +} + +func SolanaChainClient(s *Shell) ChainClient { + return newChainClient[SolanaChainPresenters](s, "solana") +} diff --git a/core/cmd/solana_chains_commands_test.go b/core/cmd/solana_chains_commands_test.go new file mode 100644 index 00000000000..e374ba11c65 --- /dev/null +++ b/core/cmd/solana_chains_commands_test.go @@ -0,0 +1,32 @@ +package cmd_test + +import ( + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + solcfg "github.com/smartcontractkit/chainlink-solana/pkg/solana/config" + "github.com/smartcontractkit/chainlink/v2/core/cmd" + "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" + "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/solanatest" +) + +func TestShell_IndexSolanaChains(t *testing.T) { + t.Parallel() + + id := solanatest.RandomChainID() + cfg := solcfg.TOMLConfig{ + ChainID: &id, + Enabled: ptr(true), + } + app := solanaStartNewApplication(t, &cfg) + client, r := app.NewShellAndRenderer() + + require.Nil(t, cmd.SolanaChainClient(client).IndexChains(cltest.EmptyCLIContext())) + chains := *r.Renders[0].(*cmd.SolanaChainPresenters) + require.Len(t, chains, 1) + c := chains[0] + assert.Equal(t, id, c.ID) + assertTableRenders(t, r) +} diff --git a/core/cmd/solana_node_commands.go b/core/cmd/solana_node_commands.go new file mode 100644 index 00000000000..6ccf9a5864c --- /dev/null +++ b/core/cmd/solana_node_commands.go @@ -0,0 +1,44 @@ +package cmd + +import ( + "github.com/smartcontractkit/chainlink/v2/core/web/presenters" +) + +// SolanaNodePresenter implements TableRenderer for a SolanaNodeResource. +type SolanaNodePresenter struct { + presenters.SolanaNodeResource +} + +// ToRow presents the SolanaNodeResource as a slice of strings. +func (p *SolanaNodePresenter) ToRow() []string { + return []string{p.Name, p.ChainID, p.State, p.Config} +} + +// RenderTable implements TableRenderer +func (p SolanaNodePresenter) RenderTable(rt RendererTable) error { + var rows [][]string + rows = append(rows, p.ToRow()) + renderList(nodeHeaders, rows, rt.Writer) + + return nil +} + +// SolanaNodePresenters implements TableRenderer for a slice of SolanaNodePresenter. +type SolanaNodePresenters []SolanaNodePresenter + +// RenderTable implements TableRenderer +func (ps SolanaNodePresenters) RenderTable(rt RendererTable) error { + var rows [][]string + + for _, p := range ps { + rows = append(rows, p.ToRow()) + } + + renderList(nodeHeaders, rows, rt.Writer) + + return nil +} + +func NewSolanaNodeClient(s *Shell) NodeClient { + return newNodeClient[SolanaNodePresenters](s, "solana") +} diff --git a/core/cmd/solana_node_commands_test.go b/core/cmd/solana_node_commands_test.go new file mode 100644 index 00000000000..f08fcd7aaf0 --- /dev/null +++ b/core/cmd/solana_node_commands_test.go @@ -0,0 +1,88 @@ +package cmd_test + +import ( + "bytes" + "strings" + "testing" + + "github.com/pelletier/go-toml/v2" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + "github.com/smartcontractkit/chainlink-common/pkg/config" + solcfg "github.com/smartcontractkit/chainlink-solana/pkg/solana/config" + + "github.com/smartcontractkit/chainlink/v2/core/cmd" + "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" + "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/solanatest" + "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" +) + +func solanaStartNewApplication(t *testing.T, cfgs ...*solcfg.TOMLConfig) *cltest.TestApplication { + for i := range cfgs { + cfgs[i].Chain.SetDefaults() + } + return startNewApplicationV2(t, func(c *chainlink.Config, s *chainlink.Secrets) { + c.Solana = cfgs + c.EVM = nil + }) +} + +func TestShell_IndexSolanaNodes(t *testing.T) { + t.Parallel() + + id := solanatest.RandomChainID() + node1 := solcfg.Node{ + Name: ptr("first"), + URL: config.MustParseURL("https://solana1.example"), + } + node2 := solcfg.Node{ + Name: ptr("second"), + URL: config.MustParseURL("https://solana2.example"), + } + chain := solcfg.TOMLConfig{ + ChainID: &id, + Nodes: solcfg.Nodes{&node1, &node2}, + } + app := solanaStartNewApplication(t, &chain) + client, r := app.NewShellAndRenderer() + + require.Nil(t, cmd.NewSolanaNodeClient(client).IndexNodes(cltest.EmptyCLIContext())) + require.NotEmpty(t, r.Renders) + nodes := *r.Renders[0].(*cmd.SolanaNodePresenters) + require.Len(t, nodes, 2) + n1 := nodes[0] + n2 := nodes[1] + assert.Equal(t, id, n1.ChainID) + assert.Equal(t, cltest.FormatWithPrefixedChainID(id, *node1.Name), n1.ID) + assert.Equal(t, *node1.Name, n1.Name) + wantConfig, err := toml.Marshal(node1) + require.NoError(t, err) + assert.Equal(t, string(wantConfig), n1.Config) + assert.Equal(t, id, n2.ChainID) + assert.Equal(t, cltest.FormatWithPrefixedChainID(id, *node2.Name), n2.ID) + assert.Equal(t, *node2.Name, n2.Name) + wantConfig2, err := toml.Marshal(node2) + require.NoError(t, err) + assert.Equal(t, string(wantConfig2), n2.Config) + assertTableRenders(t, r) + + // Render table and check the fields order + b := new(bytes.Buffer) + rt := cmd.RendererTable{b} + require.NoError(t, nodes.RenderTable(rt)) + renderLines := strings.Split(b.String(), "\n") + assert.Equal(t, 19, len(renderLines)) + assert.Contains(t, renderLines[2], "Name") + assert.Contains(t, renderLines[2], n1.Name) + assert.Contains(t, renderLines[3], "Chain ID") + assert.Contains(t, renderLines[3], n1.ChainID) + assert.Contains(t, renderLines[4], "State") + assert.Contains(t, renderLines[4], n1.State) + assert.Contains(t, renderLines[10], "Name") + assert.Contains(t, renderLines[10], n2.Name) + assert.Contains(t, renderLines[11], "Chain ID") + assert.Contains(t, renderLines[11], n2.ChainID) + assert.Contains(t, renderLines[12], "State") + assert.Contains(t, renderLines[12], n2.State) +} diff --git a/core/cmd/starknet_chains_commands.go b/core/cmd/starknet_chains_commands.go new file mode 100644 index 00000000000..5b20b37ae22 --- /dev/null +++ b/core/cmd/starknet_chains_commands.go @@ -0,0 +1,48 @@ +package cmd + +import ( + "strconv" + + "github.com/smartcontractkit/chainlink/v2/core/web/presenters" +) + +// StarkNetChainPresenter implements TableRenderer for a StarkNetChainResource +type StarkNetChainPresenter struct { + presenters.StarkNetChainResource +} + +// ToRow presents the StarkNetChainResource as a slice of strings. +func (p *StarkNetChainPresenter) ToRow() []string { + return []string{p.GetID(), strconv.FormatBool(p.Enabled), p.Config} +} + +// RenderTable implements TableRenderer +// Just renders a single row +func (p StarkNetChainPresenter) RenderTable(rt RendererTable) error { + rows := [][]string{} + rows = append(rows, p.ToRow()) + + renderList(chainHeaders, rows, rt.Writer) + + return nil +} + +// StarkNetChainPresenters implements TableRenderer for a slice of StarkNetChainPresenters. +type StarkNetChainPresenters []StarkNetChainPresenter + +// RenderTable implements TableRenderer +func (ps StarkNetChainPresenters) RenderTable(rt RendererTable) error { + rows := [][]string{} + + for _, p := range ps { + rows = append(rows, p.ToRow()) + } + + renderList(chainHeaders, rows, rt.Writer) + + return nil +} + +func StarkNetChainClient(s *Shell) ChainClient { + return newChainClient[StarkNetChainPresenters](s, "starknet") +} diff --git a/core/cmd/starknet_node_commands.go b/core/cmd/starknet_node_commands.go new file mode 100644 index 00000000000..c26bb031145 --- /dev/null +++ b/core/cmd/starknet_node_commands.go @@ -0,0 +1,44 @@ +package cmd + +import ( + "github.com/smartcontractkit/chainlink/v2/core/web/presenters" +) + +// StarkNetNodePresenter implements TableRenderer for a StarkNetNodeResource. +type StarkNetNodePresenter struct { + presenters.StarkNetNodeResource +} + +// ToRow presents the StarkNetNodeResource as a slice of strings. +func (p *StarkNetNodePresenter) ToRow() []string { + return []string{p.Name, p.ChainID, p.State, p.Config} +} + +// RenderTable implements TableRenderer +func (p StarkNetNodePresenter) RenderTable(rt RendererTable) error { + var rows [][]string + rows = append(rows, p.ToRow()) + renderList(nodeHeaders, rows, rt.Writer) + + return nil +} + +// StarkNetNodePresenters implements TableRenderer for a slice of StarkNetNodePresenter. +type StarkNetNodePresenters []StarkNetNodePresenter + +// RenderTable implements TableRenderer +func (ps StarkNetNodePresenters) RenderTable(rt RendererTable) error { + var rows [][]string + + for _, p := range ps { + rows = append(rows, p.ToRow()) + } + + renderList(nodeHeaders, rows, rt.Writer) + + return nil +} + +func NewStarkNetNodeClient(s *Shell) NodeClient { + return newNodeClient[StarkNetNodePresenters](s, "starknet") +} diff --git a/core/cmd/starknet_node_commands_test.go b/core/cmd/starknet_node_commands_test.go new file mode 100644 index 00000000000..dae93682085 --- /dev/null +++ b/core/cmd/starknet_node_commands_test.go @@ -0,0 +1,88 @@ +package cmd_test + +import ( + "bytes" + "strings" + "testing" + + "github.com/pelletier/go-toml/v2" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + commoncfg "github.com/smartcontractkit/chainlink-common/pkg/config" + "github.com/smartcontractkit/chainlink-starknet/relayer/pkg/chainlink/config" + + "github.com/smartcontractkit/chainlink/v2/core/cmd" + "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" + "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" +) + +func starknetStartNewApplication(t *testing.T, cfgs ...*config.TOMLConfig) *cltest.TestApplication { + for i := range cfgs { + cfgs[i].SetDefaults() + } + return startNewApplicationV2(t, func(c *chainlink.Config, s *chainlink.Secrets) { + c.Starknet = cfgs + c.EVM = nil + c.Solana = nil + }) +} + +func TestShell_IndexStarkNetNodes(t *testing.T) { + t.Parallel() + + id := "starknet chain ID" + node1 := config.Node{ + Name: ptr("first"), + URL: commoncfg.MustParseURL("https://starknet1.example"), + } + node2 := config.Node{ + Name: ptr("second"), + URL: commoncfg.MustParseURL("https://starknet2.example"), + } + chain := config.TOMLConfig{ + ChainID: &id, + Nodes: config.Nodes{&node1, &node2}, + } + app := starknetStartNewApplication(t, &chain) + client, r := app.NewShellAndRenderer() + + require.Nil(t, cmd.NewStarkNetNodeClient(client).IndexNodes(cltest.EmptyCLIContext())) + require.NotEmpty(t, r.Renders) + nodes := *r.Renders[0].(*cmd.StarkNetNodePresenters) + require.Len(t, nodes, 2) + n1 := nodes[0] + n2 := nodes[1] + assert.Equal(t, id, n1.ChainID) + assert.Equal(t, cltest.FormatWithPrefixedChainID(id, *node1.Name), n1.ID) + assert.Equal(t, *node1.Name, n1.Name) + wantConfig, err := toml.Marshal(node1) + require.NoError(t, err) + assert.Equal(t, string(wantConfig), n1.Config) + assert.Equal(t, id, n2.ChainID) + assert.Equal(t, cltest.FormatWithPrefixedChainID(id, *node2.Name), n2.ID) + assert.Equal(t, *node2.Name, n2.Name) + wantConfig2, err := toml.Marshal(node2) + require.NoError(t, err) + assert.Equal(t, string(wantConfig2), n2.Config) + assertTableRenders(t, r) + + // Render table and check the fields order + b := new(bytes.Buffer) + rt := cmd.RendererTable{b} + require.NoError(t, nodes.RenderTable(rt)) + renderLines := strings.Split(b.String(), "\n") + assert.Equal(t, 17, len(renderLines)) + assert.Contains(t, renderLines[2], "Name") + assert.Contains(t, renderLines[2], n1.Name) + assert.Contains(t, renderLines[3], "Chain ID") + assert.Contains(t, renderLines[3], n1.ChainID) + assert.Contains(t, renderLines[4], "State") + assert.Contains(t, renderLines[4], n1.State) + assert.Contains(t, renderLines[9], "Name") + assert.Contains(t, renderLines[9], n2.Name) + assert.Contains(t, renderLines[10], "Chain ID") + assert.Contains(t, renderLines[10], n2.ChainID) + assert.Contains(t, renderLines[11], "State") + assert.Contains(t, renderLines[11], n2.State) +} diff --git a/core/config/app_config.go b/core/config/app_config.go index 3f2a5472b24..4cb7f1f610c 100644 --- a/core/config/app_config.go +++ b/core/config/app_config.go @@ -8,6 +8,7 @@ import ( "go.uber.org/zap/zapcore" ) +// nolint var ( ErrEnvUnset = pkgerrors.New("env var unset") ) diff --git a/core/config/capabilities_config.go b/core/config/capabilities_config.go index 74e06bf8bbb..b7e5a3b86a7 100644 --- a/core/config/capabilities_config.go +++ b/core/config/capabilities_config.go @@ -11,13 +11,6 @@ type CapabilitiesExternalRegistry interface { RelayID() types.RelayID } -type CapabilitiesWorkflowRegistry interface { - Address() string - NetworkID() string - ChainID() string - RelayID() types.RelayID -} - type GatewayConnector interface { ChainIDForNodeKey() string NodeAddress() string @@ -37,6 +30,5 @@ type Capabilities interface { Peering() P2P Dispatcher() Dispatcher ExternalRegistry() CapabilitiesExternalRegistry - WorkflowRegistry() CapabilitiesWorkflowRegistry GatewayConnector() GatewayConnector } diff --git a/core/config/database_config.go b/core/config/database_config.go index 56f8f8165d4..f1cdffc2f46 100644 --- a/core/config/database_config.go +++ b/core/config/database_config.go @@ -4,7 +4,7 @@ import ( "net/url" "time" - pgcommon "github.com/smartcontractkit/chainlink-common/pkg/sqlutil/pg" + "github.com/smartcontractkit/chainlink/v2/core/store/dialects" ) type Backup interface { @@ -35,7 +35,7 @@ type Database interface { DefaultIdleInTxSessionTimeout() time.Duration DefaultLockTimeout() time.Duration DefaultQueryTimeout() time.Duration - Dialect() pgcommon.DialectName + Dialect() dialects.DialectName LogSQL() bool MaxIdleConns() int MaxOpenConns() int diff --git a/core/config/docs/chains-evm.toml b/core/config/docs/chains-evm.toml index e8adb3d611c..62360cb02cb 100644 --- a/core/config/docs/chains-evm.toml +++ b/core/config/docs/chains-evm.toml @@ -106,8 +106,6 @@ LogBroadcasterEnabled = true # Default NoNewFinalizedHeadsThreshold = '0' # Default [EVM.Transactions] -# Enabled is a feature flag for the Transaction Manager. This flag also enables or disables the gas estimator since it is dependent on the TXM to start it. -Enabled = true # Default # ForwardersEnabled enables or disables sending transactions through forwarder contracts. ForwardersEnabled = false # Default # MaxInFlight controls how many transactions are allowed to be "in-flight" i.e. broadcast but unconfirmed at any one time. You can consider this a form of transaction throttling. diff --git a/core/config/docs/chains-solana.toml b/core/config/docs/chains-solana.toml index c4d757ffa85..c979581b258 100644 --- a/core/config/docs/chains-solana.toml +++ b/core/config/docs/chains-solana.toml @@ -17,9 +17,6 @@ TxTimeout = '1m' # Default TxRetryTimeout = '10s' # Default # TxConfirmTimeout is the duration to wait when confirming a tx signature, before discarding as unconfirmed. TxConfirmTimeout = '30s' # Default -# TxExpirationRebroadcast enables or disables transaction rebroadcast if expired. Expiration check is performed every `ConfirmPollPeriod` -# A transaction is considered expired if the blockhash it was sent with is 150 blocks older than the latest blockhash. -TxExpirationRebroadcast = false # Default # TxRetentionTimeout is the duration to retain transactions in storage after being marked as finalized or errored. Set to 0 to immediately drop transactions. TxRetentionTimeout = '0s' # Default # SkipPreflight enables or disables preflight checks when sending txs. diff --git a/core/config/docs/core.toml b/core/config/docs/core.toml index 20c519e81a1..e0fc76f449c 100644 --- a/core/config/docs/core.toml +++ b/core/config/docs/core.toml @@ -444,14 +444,6 @@ DeltaReconcile = '1m' # Default # but the host and port must be fully specified and cannot be empty. You can specify `0.0.0.0` (IPv4) or `::` (IPv6) to listen on all interfaces, but that is not recommended. ListenAddresses = ['1.2.3.4:9999', '[a52d:0:a88:1274::abcd]:1337'] # Example -[Capabilities.WorkflowRegistry] -# Address is the address for the workflow registry contract. -Address = '0x0' # Example -# NetworkID identifies the target network where the remote registry is located. -NetworkID = 'evm' # Default -# ChainID identifies the target chain id where the remote registry is located. -ChainID = '1' # Default - [Capabilities.ExternalRegistry] # Address is the address for the capabilities registry contract. Address = '0x0' # Example @@ -697,10 +689,6 @@ TransmitQueueMaxSize = 10_000 # Default # when sending a message to the mercury server, before aborting and considering # the transmission to be failed. TransmitTimeout = "5s" # Default -# TransmitConcurrency is the max number of concurrent transmits to each server. -# -# Only has effect with LLO jobs. -TransmitConcurrency = 100 # Default # Telemetry holds OTEL settings. # This data includes open telemetry metrics, traces, & logs. diff --git a/core/config/docs/defaults.go b/core/config/docs/defaults.go index 0d94be1b3cc..53e6433a8ef 100644 --- a/core/config/docs/defaults.go +++ b/core/config/docs/defaults.go @@ -5,10 +5,9 @@ import ( "strings" "github.com/smartcontractkit/chainlink-common/pkg/config" - pgcommon "github.com/smartcontractkit/chainlink-common/pkg/sqlutil/pg" - "github.com/smartcontractkit/chainlink/v2/core/config/toml" "github.com/smartcontractkit/chainlink/v2/core/services/chainlink/cfgtest" + "github.com/smartcontractkit/chainlink/v2/core/store/dialects" ) var ( @@ -23,7 +22,7 @@ func init() { func CoreDefaults() (c toml.Core) { c.SetFrom(&defaults) - c.Database.Dialect = pgcommon.Postgres // not user visible - overridden for tests only + c.Database.Dialect = dialects.Postgres // not user visible - overridden for tests only c.Tracing.Attributes = make(map[string]string) return } diff --git a/core/config/mercury_config.go b/core/config/mercury_config.go index 2e58ff0ee9d..d1b4b142e20 100644 --- a/core/config/mercury_config.go +++ b/core/config/mercury_config.go @@ -20,7 +20,6 @@ type MercuryTLS interface { type MercuryTransmitter interface { TransmitQueueMaxSize() uint32 TransmitTimeout() commonconfig.Duration - TransmitConcurrency() uint32 } type Mercury interface { diff --git a/core/config/toml/types.go b/core/config/toml/types.go index 620f7d96eee..d9302b81fb0 100644 --- a/core/config/toml/types.go +++ b/core/config/toml/types.go @@ -16,7 +16,6 @@ import ( ocrcommontypes "github.com/smartcontractkit/libocr/commontypes" commonconfig "github.com/smartcontractkit/chainlink-common/pkg/config" - pgcommon "github.com/smartcontractkit/chainlink-common/pkg/sqlutil/pg" "github.com/smartcontractkit/chainlink/v2/core/build" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" @@ -24,8 +23,10 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/config/parse" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/p2pkey" "github.com/smartcontractkit/chainlink/v2/core/sessions" + "github.com/smartcontractkit/chainlink/v2/core/store/dialects" "github.com/smartcontractkit/chainlink/v2/core/store/models" "github.com/smartcontractkit/chainlink/v2/core/utils" + configutils "github.com/smartcontractkit/chainlink/v2/core/utils/config" ) @@ -338,7 +339,7 @@ type Database struct { DefaultIdleInTxSessionTimeout *commonconfig.Duration DefaultLockTimeout *commonconfig.Duration DefaultQueryTimeout *commonconfig.Duration - Dialect pgcommon.DialectName `toml:"-"` + Dialect dialects.DialectName `toml:"-"` LogQueries *bool MaxIdleConns *int64 MaxOpenConns *int64 @@ -1329,7 +1330,6 @@ func (m *MercuryTLS) ValidateConfig() (err error) { type MercuryTransmitter struct { TransmitQueueMaxSize *uint32 TransmitTimeout *commonconfig.Duration - TransmitConcurrency *uint32 } func (m *MercuryTransmitter) setFrom(f *MercuryTransmitter) { @@ -1339,9 +1339,6 @@ func (m *MercuryTransmitter) setFrom(f *MercuryTransmitter) { if v := f.TransmitTimeout; v != nil { m.TransmitTimeout = v } - if v := f.TransmitConcurrency; v != nil { - m.TransmitConcurrency = v - } } type Mercury struct { @@ -1451,26 +1448,6 @@ func (r *ExternalRegistry) setFrom(f *ExternalRegistry) { } } -type WorkflowRegistry struct { - Address *string - NetworkID *string - ChainID *string -} - -func (r *WorkflowRegistry) setFrom(f *WorkflowRegistry) { - if f.Address != nil { - r.Address = f.Address - } - - if f.NetworkID != nil { - r.NetworkID = f.NetworkID - } - - if f.ChainID != nil { - r.ChainID = f.ChainID - } -} - type Dispatcher struct { SupportedVersion *int ReceiverBufferSize *int @@ -1560,14 +1537,12 @@ type Capabilities struct { Peering P2P `toml:",omitempty"` Dispatcher Dispatcher `toml:",omitempty"` ExternalRegistry ExternalRegistry `toml:",omitempty"` - WorkflowRegistry WorkflowRegistry `toml:",omitempty"` GatewayConnector GatewayConnector `toml:",omitempty"` } func (c *Capabilities) setFrom(f *Capabilities) { c.Peering.setFrom(&f.Peering) c.ExternalRegistry.setFrom(&f.ExternalRegistry) - c.WorkflowRegistry.setFrom(&f.WorkflowRegistry) c.Dispatcher.setFrom(&f.Dispatcher) c.GatewayConnector.setFrom(&f.GatewayConnector) } diff --git a/core/gethwrappers/ccip/deployment_test/deployment_test.go b/core/gethwrappers/ccip/deployment_test/deployment_test.go index 162c0df1946..02f00483651 100644 --- a/core/gethwrappers/ccip/deployment_test/deployment_test.go +++ b/core/gethwrappers/ccip/deployment_test/deployment_test.go @@ -41,11 +41,10 @@ func TestDeployAllV1_6(t *testing.T) { // offramp _, _, _, err = offramp.DeployOffRamp(owner, chain, offramp.OffRampStaticConfig{ - ChainSelector: 1, - GasForCallExactCheck: 5_000, - RmnRemote: common.HexToAddress("0x1"), - TokenAdminRegistry: common.HexToAddress("0x2"), - NonceManager: common.HexToAddress("0x3"), + ChainSelector: 1, + RmnRemote: common.HexToAddress("0x1"), + TokenAdminRegistry: common.HexToAddress("0x2"), + NonceManager: common.HexToAddress("0x3"), }, offramp.OffRampDynamicConfig{ FeeQuoter: common.HexToAddress("0x4"), PermissionLessExecutionThresholdSeconds: uint32((8 * time.Hour).Seconds()), diff --git a/core/gethwrappers/ccip/generated/burn_from_mint_token_pool/burn_from_mint_token_pool.go b/core/gethwrappers/ccip/generated/burn_from_mint_token_pool/burn_from_mint_token_pool.go index dd2ed6f7675..ff7ccd3a5dd 100644 --- a/core/gethwrappers/ccip/generated/burn_from_mint_token_pool/burn_from_mint_token_pool.go +++ b/core/gethwrappers/ccip/generated/burn_from_mint_token_pool/burn_from_mint_token_pool.go @@ -74,22 +74,23 @@ type RateLimiterTokenBucket struct { type TokenPoolChainUpdate struct { RemoteChainSelector uint64 - RemotePoolAddresses [][]byte + Allowed bool + RemotePoolAddress []byte RemoteTokenAddress []byte OutboundRateLimiterConfig RateLimiterConfig InboundRateLimiterConfig RateLimiterConfig } var BurnFromMintTokenPoolMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[{\"internalType\":\"contractIBurnMintERC20\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"localTokenDecimals\",\"type\":\"uint8\"},{\"internalType\":\"address[]\",\"name\":\"allowlist\",\"type\":\"address[]\"},{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"capacity\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"requested\",\"type\":\"uint256\"}],\"name\":\"AggregateValueMaxCapacityExceeded\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"minWaitInSeconds\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"available\",\"type\":\"uint256\"}],\"name\":\"AggregateValueRateLimitReached\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"AllowListNotEnabled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"BucketOverfilled\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"CallerIsNotARampOnRouter\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CannotTransferToSelf\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"}],\"name\":\"ChainAlreadyExists\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"ChainNotAllowed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CursedByRMN\",\"type\":\"error\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"config\",\"type\":\"tuple\"}],\"name\":\"DisabledNonZeroRateLimit\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"expected\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"actual\",\"type\":\"uint8\"}],\"name\":\"InvalidDecimalArgs\",\"type\":\"error\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"rateLimiterConfig\",\"type\":\"tuple\"}],\"name\":\"InvalidRateLimitRate\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolData\",\"type\":\"bytes\"}],\"name\":\"InvalidRemoteChainDecimals\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"InvalidRemotePoolForChain\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"}],\"name\":\"InvalidSourcePoolAddress\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"InvalidToken\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MismatchedArrayLengths\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MustBeProposedOwner\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"NonExistentChain\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByOwner\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"remoteDecimals\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"localDecimals\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"remoteAmount\",\"type\":\"uint256\"}],\"name\":\"OverflowDetected\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OwnerCannotBeZero\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"PoolAlreadyAdded\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RateLimitMustBeDisabled\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"SenderNotAllowed\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"capacity\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"requested\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenAddress\",\"type\":\"address\"}],\"name\":\"TokenMaxCapacityExceeded\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"minWaitInSeconds\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"available\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenAddress\",\"type\":\"address\"}],\"name\":\"TokenRateLimitReached\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"Unauthorized\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"AllowListAdd\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"AllowListRemove\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Burned\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"remoteToken\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundRateLimiterConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundRateLimiterConfig\",\"type\":\"tuple\"}],\"name\":\"ChainAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundRateLimiterConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundRateLimiterConfig\",\"type\":\"tuple\"}],\"name\":\"ChainConfigured\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"ChainRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"config\",\"type\":\"tuple\"}],\"name\":\"ConfigChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Locked\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Minted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"rateLimitAdmin\",\"type\":\"address\"}],\"name\":\"RateLimitAdminSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Released\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"RemotePoolAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"RemotePoolRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"oldRouter\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newRouter\",\"type\":\"address\"}],\"name\":\"RouterUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokens\",\"type\":\"uint256\"}],\"name\":\"TokensConsumed\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"addRemotePool\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"removes\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"adds\",\"type\":\"address[]\"}],\"name\":\"applyAllowListUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64[]\",\"name\":\"remoteChainSelectorsToRemove\",\"type\":\"uint64[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes[]\",\"name\":\"remotePoolAddresses\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes\",\"name\":\"remoteTokenAddress\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundRateLimiterConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundRateLimiterConfig\",\"type\":\"tuple\"}],\"internalType\":\"structTokenPool.ChainUpdate[]\",\"name\":\"chainsToAdd\",\"type\":\"tuple[]\"}],\"name\":\"applyChainUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAllowList\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAllowListEnabled\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getCurrentInboundRateLimiterState\",\"outputs\":[{\"components\":[{\"internalType\":\"uint128\",\"name\":\"tokens\",\"type\":\"uint128\"},{\"internalType\":\"uint32\",\"name\":\"lastUpdated\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.TokenBucket\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getCurrentOutboundRateLimiterState\",\"outputs\":[{\"components\":[{\"internalType\":\"uint128\",\"name\":\"tokens\",\"type\":\"uint128\"},{\"internalType\":\"uint32\",\"name\":\"lastUpdated\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.TokenBucket\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRateLimitAdmin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getRemotePools\",\"outputs\":[{\"internalType\":\"bytes[]\",\"name\":\"\",\"type\":\"bytes[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getRemoteToken\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRmnProxy\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRouter\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getSupportedChains\",\"outputs\":[{\"internalType\":\"uint64[]\",\"name\":\"\",\"type\":\"uint64[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getToken\",\"outputs\":[{\"internalType\":\"contractIERC20\",\"name\":\"token\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getTokenDecimals\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"decimals\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"isRemotePool\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"isSupportedChain\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"isSupportedToken\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"originalSender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"localToken\",\"type\":\"address\"}],\"internalType\":\"structPool.LockOrBurnInV1\",\"name\":\"lockOrBurnIn\",\"type\":\"tuple\"}],\"name\":\"lockOrBurn\",\"outputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"destPoolData\",\"type\":\"bytes\"}],\"internalType\":\"structPool.LockOrBurnOutV1\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"originalSender\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"localToken\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"sourcePoolData\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"offchainTokenData\",\"type\":\"bytes\"}],\"internalType\":\"structPool.ReleaseOrMintInV1\",\"name\":\"releaseOrMintIn\",\"type\":\"tuple\"}],\"name\":\"releaseOrMint\",\"outputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"destinationAmount\",\"type\":\"uint256\"}],\"internalType\":\"structPool.ReleaseOrMintOutV1\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"removeRemotePool\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundConfig\",\"type\":\"tuple\"}],\"name\":\"setChainRateLimiterConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64[]\",\"name\":\"remoteChainSelectors\",\"type\":\"uint64[]\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config[]\",\"name\":\"outboundConfigs\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config[]\",\"name\":\"inboundConfigs\",\"type\":\"tuple[]\"}],\"name\":\"setChainRateLimiterConfigs\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"rateLimitAdmin\",\"type\":\"address\"}],\"name\":\"setRateLimitAdmin\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newRouter\",\"type\":\"address\"}],\"name\":\"setRouter\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", - Bin: "0x610100806040523461035457614bb5803803809161001d82856105b2565b8339810160a0828203126103545781516001600160a01b03811692908390036103545761004c602082016105d5565b60408201516001600160401b0381116103545782019280601f85011215610354578351936001600160401b038511610359578460051b90602082019561009560405197886105b2565b865260208087019282010192831161035457602001905b82821061059a575050506100ce60806100c7606085016105e3565b93016105e3565b91331561058957600180546001600160a01b0319163317905584158015610578575b8015610567575b61055657608085905260c05260405163313ce56760e01b8152602081600481885afa6000918161051a575b506104ef575b5060a052600480546001600160a01b0319166001600160a01b03929092169190911790558051151560e08190526103d2575b50604051636eb1769f60e11b81523060048201819052602482015290602082604481845afa9182156103c657600092610392575b50600019820180921161037c57604051602081019263095ea7b360e01b84523060248301526044820152604481526101c76064826105b2565b6000806040948551936101da87866105b2565b602085527f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65646020860152519082865af13d1561036f573d906001600160401b03821161035957845161024b94909261023c601f8201601f1916602001856105b2565b83523d6000602085013e610781565b8051806102d9575b8251614363908161085282396080518181816115fc015281816117e80152818161220e015281816123ea01528181612707015261277f015260a0518181816118a90152818161268e0152818161316801526131eb015260c051818181610bd50152818161169801526122a9015260e051818181610b65015281816116db01526120050152f35b81602091810103126103545760200151801590811503610354576102fe573880610253565b5162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608490fd5b600080fd5b634e487b7160e01b600052604160045260246000fd5b9161024b92606091610781565b634e487b7160e01b600052601160045260246000fd5b9091506020813d6020116103be575b816103ae602093836105b2565b810103126103545751903861018e565b3d91506103a1565b6040513d6000823e3d90fd5b60206040516103e182826105b2565b60008152600036813760e051156104de5760005b815181101561045c576001906001600160a01b0361041382856105f7565b51168461041f82610639565b61042c575b5050016103f5565b7f800671136ab6cfee9fbe5ed1fb7ca417811aca3cf864800d127b927adedf756691604051908152a13884610424565b505060005b82518110156104d5576001906001600160a01b0361047f82866105f7565b511680156104cf578361049182610721565b61049f575b50505b01610461565b7f2640d4d76caf8bf478aabfa982fa4e1c4eb71a37f93cd15e80dbc657911546d891604051908152a13883610496565b50610499565b5050503861015a565b6335f4a7b360e01b60005260046000fd5b60ff1660ff82168181036105035750610128565b6332ad3e0760e11b60005260045260245260446000fd5b9091506020813d60201161054e575b81610536602093836105b2565b8101031261035457610547906105d5565b9038610122565b3d9150610529565b6342bcdf7f60e11b60005260046000fd5b506001600160a01b038116156100f7565b506001600160a01b038316156100f0565b639b15e16f60e01b60005260046000fd5b602080916105a7846105e3565b8152019101906100ac565b601f909101601f19168101906001600160401b0382119082101761035957604052565b519060ff8216820361035457565b51906001600160a01b038216820361035457565b805182101561060b5760209160051b010190565b634e487b7160e01b600052603260045260246000fd5b805482101561060b5760005260206000200190600090565b600081815260036020526040902054801561071a57600019810181811161037c5760025460001981019190821161037c578181036106c9575b50505060025480156106b3576000190161068d816002610621565b8154906000199060031b1b19169055600255600052600360205260006040812055600190565b634e487b7160e01b600052603160045260246000fd5b6107026106da6106eb936002610621565b90549060031b1c9283926002610621565b819391549060031b91821b91600019901b19161790565b90556000526003602052604060002055388080610672565b5050600090565b8060005260036020526040600020541560001461077b5760025468010000000000000000811015610359576107626106eb8260018594016002556002610621565b9055600254906000526003602052604060002055600190565b50600090565b919290156107e35750815115610795575090565b3b1561079e5790565b60405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606490fd5b8251909150156107f65750805190602001fd5b6040519062461bcd60e51b8252602060048301528181519182602483015260005b8381106108395750508160006044809484010152601f80199101168101030190fd5b6020828201810151604487840101528593500161081756fe608080604052600436101561001357600080fd5b600090813560e01c90816301ffc9a71461282257508063181f5a77146127a357806321df0da714612734578063240028e8146126b257806324f65ee71461265657806339077537146121685780634c5ef0ed1461214e57806354c8a4f314611fd157806362ddd3c414611f4d5780636d3d1a5814611efb57806379ba509714611e165780637d54534e14611d695780638926f54f14611d055780638da5cb5b14611cb3578063962d402014611b0f5780639a4575b914611554578063a42a7b8b146113cf578063a7cd63b714611303578063acfecf91146111df578063af58d59f14611178578063b0f479a114611126578063b7946580146110cf578063c0d7865514610fd7578063c4bffe2b14610e8e578063c75eea9c14610dc8578063cf7401f314610bf9578063dc0bd97114610b8a578063e0351e1314610b2f578063e8a1da171461025a5763f2fde38b1461016b57600080fd5b346102575760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102575773ffffffffffffffffffffffffffffffffffffffff6101b7612a50565b6101bf6132f5565b1633811461022f57807fffffffffffffffffffffffff000000000000000000000000000000000000000083541617825573ffffffffffffffffffffffffffffffffffffffff600154167fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12788380a380f35b6004827fdad89dca000000000000000000000000000000000000000000000000000000008152fd5b80fd5b50346102575761026936612b3e565b939190926102756132f5565b82915b80831061099a575050508063ffffffff4216917ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffee1843603015b85821015610996578160051b85013581811215610992578501906101208236031261099257604051956102e387612978565b823567ffffffffffffffff8116810361098d578752602083013567ffffffffffffffff81116109895783019536601f880112156109895786359661032688612d6a565b97610334604051998a6129b0565b8089526020808a019160051b830101903682116109855760208301905b828210610952575050505060208801968752604084013567ffffffffffffffff811161094e5761038490369086016130c2565b9860408901998a526103ae61039c3660608801612bfc565b9560608b0196875260c0369101612bfc565b9660808a019788526103c0865161376c565b6103ca885161376c565b8a515115610926576103e667ffffffffffffffff8b5116613fbf565b156108ef5767ffffffffffffffff8a5116815260076020526040812061052687516fffffffffffffffffffffffffffffffff604082015116906104e16fffffffffffffffffffffffffffffffff6020830151169151151583608060405161044c81612978565b858152602081018c905260408101849052606081018690520152855474ff000000000000000000000000000000000000000091151560a01b919091167fffffffffffffffffffffff0000000000000000000000000000000000000000009091166fffffffffffffffffffffffffffffffff84161773ffffffff0000000000000000000000000000000060808b901b1617178555565b60809190911b7fffffffffffffffffffffffffffffffff00000000000000000000000000000000166fffffffffffffffffffffffffffffffff91909116176001830155565b61064c89516fffffffffffffffffffffffffffffffff604082015116906106076fffffffffffffffffffffffffffffffff6020830151169151151583608060405161057081612978565b858152602081018c9052604081018490526060810186905201526002860180547fffffffffffffffffffffff000000000000000000000000000000000000000000166fffffffffffffffffffffffffffffffff85161773ffffffff0000000000000000000000000000000060808c901b161791151560a01b74ff000000000000000000000000000000000000000016919091179055565b60809190911b7fffffffffffffffffffffffffffffffff00000000000000000000000000000000166fffffffffffffffffffffffffffffffff91909116176003830155565b60048c5191019080519067ffffffffffffffff82116108c25761066f8354612e62565b601f8111610887575b50602090601f83116001146107e8576106c692918591836107dd575b50507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8260011b9260031b1c19161790565b90555b805b8951805182101561070157906106fb6001926106f4838f67ffffffffffffffff90511692612e4e565b5190613340565b016106cb565b5050975097987f8d340f17e19058004c20453540862a9c62778504476f6756755cb33bcd6c38c2929593966107cf67ffffffffffffffff600197949c511692519351915161079b610766604051968796875261010060208801526101008701906129f1565b9360408601906fffffffffffffffffffffffffffffffff60408092805115158552826020820151166020860152015116910152565b60a08401906fffffffffffffffffffffffffffffffff60408092805115158552826020820151166020860152015116910152565b0390a10190939492916102b1565b015190503880610694565b83855281852091907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08416865b81811061086f5750908460019594939210610838575b505050811b0190556106c9565b01517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88460031b161c1916905538808061082b565b92936020600181928786015181550195019301610815565b6108b29084865260208620601f850160051c810191602086106108b8575b601f0160051c0190613069565b38610678565b90915081906108a5565b6024847f4e487b710000000000000000000000000000000000000000000000000000000081526041600452fd5b60249067ffffffffffffffff8b51167f1d5ad3c5000000000000000000000000000000000000000000000000000000008252600452fd5b807f8579befe0000000000000000000000000000000000000000000000000000000060049252fd5b8680fd5b813567ffffffffffffffff81116109815760209161097683928336918901016130c2565b815201910190610351565b8a80fd5b8880fd5b8580fd5b600080fd5b8380fd5b8280f35b9092919367ffffffffffffffff6109ba6109b5878588612dea565b612e29565b16956109c587613cf3565b15610b035786845260076020526109e160056040862001613afa565b94845b8651811015610a1a576001908987526007602052610a1360056040892001610a0c838b612e4e565b5190613e1e565b50016109e4565b5093945094909580855260076020526005604086208681558660018201558660028201558660038201558660048201610a538154612e62565b80610ac2575b5050500180549086815581610aa4575b5050907f5204aec90a3c794d8e90fded8b46ae9c7c552803e7e832e0c1d358396d8599166020600193604051908152a1019190949394610278565b865260208620908101905b81811015610a6957868155600101610aaf565b601f8111600114610ad85750555b863880610a59565b81835260208320610af391601f01861c810190600101613069565b8082528160208120915555610ad0565b602484887f1e670e4b000000000000000000000000000000000000000000000000000000008252600452fd5b503461025757807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102575760206040517f000000000000000000000000000000000000000000000000000000000000000015158152f35b503461025757807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261025757602060405173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b50346102575760e07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261025757610c31612a73565b9060607fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdc36011261025757604051610c6881612994565b6024358015158103610dc45781526044356fffffffffffffffffffffffffffffffff81168103610dc45760208201526064356fffffffffffffffffffffffffffffffff81168103610dc457604082015260607fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7c360112610dc05760405190610cef82612994565b608435801515810361099257825260a4356fffffffffffffffffffffffffffffffff8116810361099257602083015260c4356fffffffffffffffffffffffffffffffff8116810361099257604083015273ffffffffffffffffffffffffffffffffffffffff6009541633141580610d9e575b610d7257610d6f92936135aa565b80f35b6024837f8e4a23d600000000000000000000000000000000000000000000000000000000815233600452fd5b5073ffffffffffffffffffffffffffffffffffffffff60015416331415610d61565b5080fd5b8280fd5b50346102575760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261025757610e31610e2c6040610e8a9367ffffffffffffffff610e15612a73565b610e1d612fb6565b50168152600760205220612fe1565b6136e7565b6040519182918291909160806fffffffffffffffffffffffffffffffff8160a084019582815116855263ffffffff6020820151166020860152604081015115156040860152826060820151166060860152015116910152565b0390f35b503461025757807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261025757604051906005548083528260208101600584526020842092845b818110610fbe575050610eec925003836129b0565b8151610f10610efa82612d6a565b91610f0860405193846129b0565b808352612d6a565b917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0602083019301368437805b8451811015610f6f578067ffffffffffffffff610f5c60019388612e4e565b5116610f688286612e4e565b5201610f3d565b50925090604051928392602084019060208552518091526040840192915b818110610f9b575050500390f35b825167ffffffffffffffff16845285945060209384019390920191600101610f8d565b8454835260019485019487945060209093019201610ed7565b50346102575760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102575773ffffffffffffffffffffffffffffffffffffffff611024612a50565b61102c6132f5565b1680156110a75760407f02dc5c233404867c793b749c6d644beb2277536d18a7e7974d3f238e4c6f16849160045490807fffffffffffffffffffffffff000000000000000000000000000000000000000083161760045573ffffffffffffffffffffffffffffffffffffffff8351921682526020820152a180f35b6004827f8579befe000000000000000000000000000000000000000000000000000000008152fd5b50346102575760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261025757610e8a61111261110d612a73565b613047565b6040519182916020835260208301906129f1565b503461025757807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261025757602073ffffffffffffffffffffffffffffffffffffffff60045416604051908152f35b50346102575760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261025757610e31610e2c60026040610e8a9467ffffffffffffffff6111c7612a73565b6111cf612fb6565b5016815260076020522001612fe1565b50346102575767ffffffffffffffff6111f736612a8a565b9290916112026132f5565b169161121b836000526006602052604060002054151590565b156112d757828452600760205261124a6005604086200161123d368486612c99565b6020815191012090613e1e565b1561128f57907f52d00ee4d9bd51b40168f2afc5848837288ce258784ad914278791464b3f4d7691611289604051928392602084526020840191612f77565b0390a280f35b826112d3836040519384937f74f23c7c0000000000000000000000000000000000000000000000000000000085526004850152604060248501526044840191612f77565b0390fd5b602484847f1e670e4b000000000000000000000000000000000000000000000000000000008252600452fd5b503461025757807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261025757604051600254808252602082018091600285526020852090855b8181106113b957505050826113629103836129b0565b604051928392602084019060208552518091526040840192915b81811061138a575050500390f35b825173ffffffffffffffffffffffffffffffffffffffff1684528594506020938401939092019160010161137c565b825484526020909301926001928301920161134c565b50346102575760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102575767ffffffffffffffff611410612a73565b168152600760205261142760056040832001613afa565b80517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe061146c61145683612d6a565b9261146460405194856129b0565b808452612d6a565b01835b818110611543575050825b82518110156114c0578061149060019285612e4e565b51855260086020526114a460408620612eb5565b6114ae8285612e4e565b526114b98184612e4e565b500161147a565b81846040519182916020830160208452825180915260408401602060408360051b870101940192905b8282106114f857505050500390f35b91936020611533827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0600195979984950301865288516129f1565b96019201920185949391926114e9565b80606060208093860101520161146f565b50346102575760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102575760043567ffffffffffffffff8111610dc05760a07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc8236030112610dc057606060206040516115d28161295c565b8281520152608481016115e481612cfe565b73ffffffffffffffffffffffffffffffffffffffff807f000000000000000000000000000000000000000000000000000000000000000016911603611ac55750602481019177ffffffffffffffff0000000000000000000000000000000061164b84612e29565b60801b16604051907f2cbc26bb000000000000000000000000000000000000000000000000000000008252600482015260208160248173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000165afa908115611955578291611a96575b50611a6e576116d960448301612cfe565b7f0000000000000000000000000000000000000000000000000000000000000000611a1b575b5067ffffffffffffffff61171284612e29565b1661172a816000526006602052604060002054151590565b156119ef57602073ffffffffffffffffffffffffffffffffffffffff60045416916024604051809481937fa8d87a3b00000000000000000000000000000000000000000000000000000000835260048301525afa801561195557829061198c575b73ffffffffffffffffffffffffffffffffffffffff91501633036119605767ffffffffffffffff60646117bd85612e29565b930135921681526007602052816118106040832073ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001692839161406e565b803b15610dc0576040517f79cc6790000000000000000000000000000000000000000000000000000000008152306004820152602481018490529082908290604490829084905af1801561195557611940575b61190f61189f61110d86866040519081527f696de425f79f4a40bc6d2122ca50507f0efbeabbff86a84871b7196ab8ea8df760203392a2612e29565b610e8a60405160ff7f0000000000000000000000000000000000000000000000000000000000000000166020820152602081526118dd6040826129b0565b604051926118ea8461295c565b83526020830190815260405193849360208552516040602086015260608501906129f1565b90517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08483030160408501526129f1565b61194b8280926129b0565b6102575780611863565b6040513d84823e3d90fd5b807f728fe07b000000000000000000000000000000000000000000000000000000006024925233600452fd5b506020813d6020116119e7575b816119a6602093836129b0565b81010312610dc0575173ffffffffffffffffffffffffffffffffffffffff81168103610dc05773ffffffffffffffffffffffffffffffffffffffff9061178b565b3d9150611999565b602492507fa9902c7e000000000000000000000000000000000000000000000000000000008252600452fd5b73ffffffffffffffffffffffffffffffffffffffff16808252600360205260408220546116ff57602492507fd0d25976000000000000000000000000000000000000000000000000000000008252600452fd5b807f53ad11d80000000000000000000000000000000000000000000000000000000060049252fd5b611ab8915060203d602011611abe575b611ab081836129b0565b8101906130dd565b386116c8565b503d611aa6565b8273ffffffffffffffffffffffffffffffffffffffff611ae6602493612cfe565b7f961c9a4f00000000000000000000000000000000000000000000000000000000835216600452fd5b50346102575760607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102575760043567ffffffffffffffff8111610dc057611b5f903690600401612b0d565b60243567ffffffffffffffff811161099257611b7f903690600401612bae565b60449291923567ffffffffffffffff811161098957611ba2903690600401612bae565b91909273ffffffffffffffffffffffffffffffffffffffff6009541633141580611c91575b611c6557818114801590611c5b575b611c3357865b818110611be7578780f35b80611c2d611bfb6109b5600194868c612dea565b611c0683878b612e3e565b611c27611c1f611c17868b8d612e3e565b923690612bfc565b913690612bfc565b916135aa565b01611bdc565b6004877f568efce2000000000000000000000000000000000000000000000000000000008152fd5b5082811415611bd6565b6024877f8e4a23d600000000000000000000000000000000000000000000000000000000815233600452fd5b5073ffffffffffffffffffffffffffffffffffffffff60015416331415611bc7565b503461025757807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261025757602073ffffffffffffffffffffffffffffffffffffffff60015416604051908152f35b50346102575760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610257576020611d5f67ffffffffffffffff611d4b612a73565b166000526006602052604060002054151590565b6040519015158152f35b50346102575760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610257577f44676b5284b809a22248eba0da87391d79098be38bb03154be88a58bf4d09174602073ffffffffffffffffffffffffffffffffffffffff611dd9612a50565b611de16132f5565b16807fffffffffffffffffffffffff00000000000000000000000000000000000000006009541617600955604051908152a180f35b503461025757807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261025757805473ffffffffffffffffffffffffffffffffffffffff81163303611ed3577fffffffffffffffffffffffff000000000000000000000000000000000000000060015491338284161760015516825573ffffffffffffffffffffffffffffffffffffffff3391167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08380a380f35b6004827f02b543c6000000000000000000000000000000000000000000000000000000008152fd5b503461025757807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261025757602073ffffffffffffffffffffffffffffffffffffffff60095416604051908152f35b503461025757611f5c36612a8a565b611f68939291936132f5565b67ffffffffffffffff8216611f8a816000526006602052604060002054151590565b15611fa65750610d6f9293611fa0913691612c99565b90613340565b7f1e670e4b000000000000000000000000000000000000000000000000000000008452600452602483fd5b503461025757611ffb90612003611fe736612b3e565b9591611ff49391936132f5565b3691612d82565b933691612d82565b7f00000000000000000000000000000000000000000000000000000000000000001561212657815b835181101561209e578073ffffffffffffffffffffffffffffffffffffffff61205660019387612e4e565b511661206181613b5d565b61206d575b500161202b565b60207f800671136ab6cfee9fbe5ed1fb7ca417811aca3cf864800d127b927adedf756691604051908152a138612066565b5090805b8251811015612122578073ffffffffffffffffffffffffffffffffffffffff6120cd60019386612e4e565b5116801561211c576120de81613f5f565b6120eb575b505b016120a2565b60207f2640d4d76caf8bf478aabfa982fa4e1c4eb71a37f93cd15e80dbc657911546d891604051908152a1846120e3565b506120e5565b5080f35b6004827f35f4a7b3000000000000000000000000000000000000000000000000000000008152fd5b5034610257576020611d5f61216236612a8a565b91612d1f565b50346102575760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102575760043567ffffffffffffffff8111610dc057806004016101007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc8336030112610dc457826040516121e881612911565b52608482016121f681612cfe565b73ffffffffffffffffffffffffffffffffffffffff807f00000000000000000000000000000000000000000000000000000000000000001691160361263557506024820177ffffffffffffffff0000000000000000000000000000000061225c82612e29565b60801b16604051907f2cbc26bb000000000000000000000000000000000000000000000000000000008252600482015260208160248173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000165afa9081156125b8578591612616575b506125ee5767ffffffffffffffff6122f082612e29565b16612308816000526006602052604060002054151590565b156125c357602073ffffffffffffffffffffffffffffffffffffffff60045416916044604051809481937f83826b2b00000000000000000000000000000000000000000000000000000000835260048301523360248301525afa9081156125b8578591612599575b501561256d5761237f81612e29565b61239160a48501916121628386612c48565b15612526575061242e67ffffffffffffffff9261242861242361241c6123b8604496612e29565b936064890135978895168a526007602052612412600260408c200173ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016998a9161406e565b60c4890190612c48565b3691612c99565b6130f5565b906131e8565b9201908361243b83612cfe565b823b15610dc0576040517f40c10f1900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff91909116600482015260248101859052918290604490829084905af1801561251b57916020946124c99273ffffffffffffffffffffffffffffffffffffffff9461250b575b5050612cfe565b166040518281527f9d228d69b5fdb8d273a2336f8fb8612d039631024ea9bf09c424a9503aa078f0843392a38060405161250281612911565b52604051908152f35b81612515916129b0565b386124c2565b6040513d86823e3d90fd5b6125309083612c48565b6112d36040519283927f24eb47e5000000000000000000000000000000000000000000000000000000008452602060048501526024840191612f77565b6024847f728fe07b00000000000000000000000000000000000000000000000000000000815233600452fd5b6125b2915060203d602011611abe57611ab081836129b0565b38612370565b6040513d87823e3d90fd5b7fa9902c7e000000000000000000000000000000000000000000000000000000008552600452602484fd5b6004847f53ad11d8000000000000000000000000000000000000000000000000000000008152fd5b61262f915060203d602011611abe57611ab081836129b0565b386122d9565b8373ffffffffffffffffffffffffffffffffffffffff611ae6602493612cfe565b503461025757807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261025757602060405160ff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b50346102575760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610257576020906126ed612a50565b905073ffffffffffffffffffffffffffffffffffffffff807f0000000000000000000000000000000000000000000000000000000000000000169116146040519015158152f35b503461025757807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261025757602060405173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b503461025757807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102575750610e8a6040516127e46040826129b0565b601b81527f4275726e46726f6d4d696e74546f6b656e506f6f6c20312e352e31000000000060208201526040519182916020835260208301906129f1565b905034610dc05760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610dc0576004357fffffffff000000000000000000000000000000000000000000000000000000008116809103610dc457602092507faff2afbf0000000000000000000000000000000000000000000000000000000081149081156128e7575b81156128bd575b5015158152f35b7f01ffc9a700000000000000000000000000000000000000000000000000000000915014386128b6565b7f0e64dd2900000000000000000000000000000000000000000000000000000000811491506128af565b6020810190811067ffffffffffffffff82111761292d57604052565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040810190811067ffffffffffffffff82111761292d57604052565b60a0810190811067ffffffffffffffff82111761292d57604052565b6060810190811067ffffffffffffffff82111761292d57604052565b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff82111761292d57604052565b919082519283825260005b848110612a3b5750507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8460006020809697860101520116010190565b806020809284010151828286010152016129fc565b6004359073ffffffffffffffffffffffffffffffffffffffff8216820361098d57565b6004359067ffffffffffffffff8216820361098d57565b60407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc82011261098d5760043567ffffffffffffffff8116810361098d579160243567ffffffffffffffff811161098d578260238201121561098d5780600401359267ffffffffffffffff841161098d576024848301011161098d576024019190565b9181601f8401121561098d5782359167ffffffffffffffff831161098d576020808501948460051b01011161098d57565b60407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc82011261098d5760043567ffffffffffffffff811161098d5781612b8791600401612b0d565b929092916024359067ffffffffffffffff821161098d57612baa91600401612b0d565b9091565b9181601f8401121561098d5782359167ffffffffffffffff831161098d576020808501946060850201011161098d57565b35906fffffffffffffffffffffffffffffffff8216820361098d57565b919082606091031261098d57604051612c1481612994565b8092803590811515820361098d576040612c439181938552612c3860208201612bdf565b602086015201612bdf565b910152565b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18136030182121561098d570180359067ffffffffffffffff821161098d5760200191813603831361098d57565b92919267ffffffffffffffff821161292d5760405191612ce1601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016602001846129b0565b82948184528183011161098d578281602093846000960137010152565b3573ffffffffffffffffffffffffffffffffffffffff8116810361098d5790565b612d67929167ffffffffffffffff612d4a921660005260076020526005604060002001923691612c99565b602081519101209060019160005201602052604060002054151590565b90565b67ffffffffffffffff811161292d5760051b60200190565b9291612d8d82612d6a565b93612d9b60405195866129b0565b602085848152019260051b810191821161098d57915b818310612dbd57505050565b823573ffffffffffffffffffffffffffffffffffffffff8116810361098d57815260209283019201612db1565b9190811015612dfa5760051b0190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b3567ffffffffffffffff8116810361098d5790565b9190811015612dfa576060020190565b8051821015612dfa5760209160051b010190565b90600182811c92168015612eab575b6020831014612e7c57565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b91607f1691612e71565b9060405191826000825492612ec984612e62565b8084529360018116908115612f375750600114612ef0575b50612eee925003836129b0565b565b90506000929192526020600020906000915b818310612f1b575050906020612eee9282010138612ee1565b6020919350806001915483858901015201910190918492612f02565b60209350612eee9592507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0091501682840152151560051b82010138612ee1565b601f82602094937fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0938186528686013760008582860101520116010190565b60405190612fc382612978565b60006080838281528260208201528260408201528260608201520152565b90604051612fee81612978565b60806001829460ff81546fffffffffffffffffffffffffffffffff8116865263ffffffff81861c16602087015260a01c161515604085015201546fffffffffffffffffffffffffffffffff81166060840152811c910152565b67ffffffffffffffff166000526007602052612d676004604060002001612eb5565b818110613074575050565b60008155600101613069565b8181029291811591840414171561309357565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b9080601f8301121561098d57816020612d6793359101612c99565b9081602091031261098d5751801515810361098d5790565b80518015613164576020036131265760208180518101031261098d5760208101519060ff8211613126575060ff1690565b6112d3906040519182917f953576f70000000000000000000000000000000000000000000000000000000083526020600484015260248301906129f1565b50507f000000000000000000000000000000000000000000000000000000000000000090565b9060ff8091169116039060ff821161309357565b60ff16604d811161309357600a0a90565b81156131b9570490565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b907f00000000000000000000000000000000000000000000000000000000000000009060ff82169060ff8116928284146132ee578284116132c4579061322d9161318a565b91604d60ff841611801561328b575b6132555750509061324f612d679261319e565b90613080565b9091507fa9cb113d0000000000000000000000000000000000000000000000000000000060005260045260245260445260646000fd5b506132958361319e565b80156131b9577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04841161323c565b6132cd9161318a565b91604d60ff841611613255575050906132e8612d679261319e565b906131af565b5050505090565b73ffffffffffffffffffffffffffffffffffffffff60015416330361331657565b7f2b5c74de0000000000000000000000000000000000000000000000000000000060005260046000fd5b908051156135805767ffffffffffffffff81516020830120921691826000526007602052613375816005604060002001614019565b1561353c5760005260086020526040600020815167ffffffffffffffff811161292d576133a28254612e62565b601f811161350a575b506020601f8211600114613444579161341e827f7d628c9a1796743d365ab521a8b2a4686e419b3269919dc9145ea2ce853b54ea959361343495600091613439575b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8260011b9260031b1c19161790565b90556040519182916020835260208301906129f1565b0390a2565b9050840151386133ed565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe082169083600052806000209160005b8181106134f25750926134349492600192827f7d628c9a1796743d365ab521a8b2a4686e419b3269919dc9145ea2ce853b54ea9896106134bb575b5050811b019055611112565b8501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88460031b161c1916905538806134af565b9192602060018192868a015181550194019201613474565b61353690836000526020600020601f840160051c810191602085106108b857601f0160051c0190613069565b386133ab565b50906112d36040519283927f393b8ad200000000000000000000000000000000000000000000000000000000845260048401526040602484015260448301906129f1565b7f8579befe0000000000000000000000000000000000000000000000000000000060005260046000fd5b67ffffffffffffffff1660008181526006602052604090205490929190156136ac57916136a960e092613675856136017f0350d63aa5f270e01729d00d627eeb8f3429772b1818c016c66a588a864f912b9761376c565b8460005260076020526136188160406000206138c7565b6136218361376c565b84600052600760205261363b8360026040600020016138c7565b60405194855260208501906fffffffffffffffffffffffffffffffff60408092805115158552826020820151166020860152015116910152565b60808301906fffffffffffffffffffffffffffffffff60408092805115158552826020820151166020860152015116910152565ba1565b827f1e670e4b0000000000000000000000000000000000000000000000000000000060005260045260246000fd5b9190820391821161309357565b6136ef612fb6565b506fffffffffffffffffffffffffffffffff6060820151166fffffffffffffffffffffffffffffffff808351169161374c602085019361374661373963ffffffff875116426136da565b8560808901511690613080565b90613f52565b8082101561376557505b16825263ffffffff4216905290565b9050613756565b805115613820576fffffffffffffffffffffffffffffffff6040820151166fffffffffffffffffffffffffffffffff602083015116811090811591613817575b506137b45750565b606490613815604051917f8020d12400000000000000000000000000000000000000000000000000000000835260048301906fffffffffffffffffffffffffffffffff60408092805115158552826020820151166020860152015116910152565bfd5b905015386137ac565b6fffffffffffffffffffffffffffffffff604082015116158015906138a8575b6138475750565b606490613815604051917fd68af9cc00000000000000000000000000000000000000000000000000000000835260048301906fffffffffffffffffffffffffffffffff60408092805115158552826020820151166020860152015116910152565b506fffffffffffffffffffffffffffffffff6020820151161515613840565b7f9ea3374b67bf275e6bb9c8ae68f9cae023e1c528b4b27e092f0bb209d3531c1991613a00606092805461390463ffffffff8260801c16426136da565b9081613a3f575b50506fffffffffffffffffffffffffffffffff6001816020860151169282815416808510600014613a3757508280855b16167fffffffffffffffffffffffffffffffff000000000000000000000000000000008254161781556139b48651151582907fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff74ff0000000000000000000000000000000000000000835492151560a01b169116179055565b60408601517fffffffffffffffffffffffffffffffff0000000000000000000000000000000060809190911b16939092166fffffffffffffffffffffffffffffffff1692909217910155565b6136a960405180926fffffffffffffffffffffffffffffffff60408092805115158552826020820151166020860152015116910152565b83809161393b565b6fffffffffffffffffffffffffffffffff91613a74839283613a6d6001880154948286169560801c90613080565b9116613f52565b80821015613af357505b83547fffffffffffffffffffffffff00000000ffffffffffffffffffffffffffffffff9290911692909216167fffffffffffffffffffffffff0000000000000000000000000000000000000000909116174260801b73ffffffff0000000000000000000000000000000016178155388061390b565b9050613a7e565b906040519182815491828252602082019060005260206000209260005b818110613b2c575050612eee925003836129b0565b8454835260019485019487945060209093019201613b17565b8054821015612dfa5760005260206000200190600090565b6000818152600360205260409020548015613cec577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff810181811161309357600254907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820191821161309357818103613c7d575b5050506002548015613c4e577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01613c0b816002613b45565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82549160031b1b19169055600255600052600360205260006040812055600190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b613cd4613c8e613c9f936002613b45565b90549060031b1c9283926002613b45565b81939154907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9060031b92831b921b19161790565b90556000526003602052604060002055388080613bd2565b5050600090565b6000818152600660205260409020548015613cec577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff810181811161309357600554907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820191821161309357818103613de4575b5050506005548015613c4e577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01613da1816005613b45565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82549160031b1b19169055600555600052600660205260006040812055600190565b613e06613df5613c9f936005613b45565b90549060031b1c9283926005613b45565b90556000526006602052604060002055388080613d68565b9060018201918160005282602052604060002054801515600014613f49577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8101818111613093578254907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820191821161309357818103613f12575b50505080548015613c4e577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190613ed38282613b45565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82549160031b1b191690555560005260205260006040812055600190565b613f32613f22613c9f9386613b45565b90549060031b1c92839286613b45565b905560005283602052604060002055388080613e9b565b50505050600090565b9190820180921161309357565b80600052600360205260406000205415600014613fb9576002546801000000000000000081101561292d57613fa0613c9f8260018594016002556002613b45565b9055600254906000526003602052604060002055600190565b50600090565b80600052600660205260406000205415600014613fb9576005546801000000000000000081101561292d57614000613c9f8260018594016005556005613b45565b9055600554906000526006602052604060002055600190565b6000828152600182016020526040902054613cec578054906801000000000000000082101561292d5782614057613c9f846001809601855584613b45565b905580549260005201602052604060002055600190565b929192805460ff8160a01c1615801561434e575b614347576fffffffffffffffffffffffffffffffff811690600183019081546140c763ffffffff6fffffffffffffffffffffffffffffffff83169360801c16426136da565b90816142a9575b5050848110614227575083821061415657507f1871cdf8010e63f2eb8384381a68dfa7416dc571a5517e66e88b2d2d0c0a690a939450906fffffffffffffffffffffffffffffffff8061412485602096956136da565b16167fffffffffffffffffffffffffffffffff00000000000000000000000000000000825416179055604051908152a1565b81945061416892505460801c926136da565b907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff810190808211613093576141b66141bb9273ffffffffffffffffffffffffffffffffffffffff94613f52565b6131af565b92169182156141f7577fd0c8d23a0000000000000000000000000000000000000000000000000000000060005260045260245260445260646000fd5b7f15279c080000000000000000000000000000000000000000000000000000000060005260045260245260446000fd5b8473ffffffffffffffffffffffffffffffffffffffff8816918215614279577f1a76572a0000000000000000000000000000000000000000000000000000000060005260045260245260445260646000fd5b7ff94ebcd10000000000000000000000000000000000000000000000000000000060005260045260245260446000fd5b82859293951161431d576142c4926137469160801c90613080565b808310156143185750815b83547fffffffffffffffffffffffff00000000ffffffffffffffffffffffffffffffff164260801b73ffffffff00000000000000000000000000000000161784559138806140ce565b6142cf565b7f9725942a0000000000000000000000000000000000000000000000000000000060005260046000fd5b5050509050565b50821561408256fea164736f6c634300081a000a", + ABI: "[{\"inputs\":[{\"internalType\":\"contractIBurnMintERC20\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"address[]\",\"name\":\"allowlist\",\"type\":\"address[]\"},{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"capacity\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"requested\",\"type\":\"uint256\"}],\"name\":\"AggregateValueMaxCapacityExceeded\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"minWaitInSeconds\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"available\",\"type\":\"uint256\"}],\"name\":\"AggregateValueRateLimitReached\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"AllowListNotEnabled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"BucketOverfilled\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"CallerIsNotARampOnRouter\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CannotTransferToSelf\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"}],\"name\":\"ChainAlreadyExists\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"ChainNotAllowed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CursedByRMN\",\"type\":\"error\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"config\",\"type\":\"tuple\"}],\"name\":\"DisabledNonZeroRateLimit\",\"type\":\"error\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"rateLimiterConfig\",\"type\":\"tuple\"}],\"name\":\"InvalidRateLimitRate\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"}],\"name\":\"InvalidSourcePoolAddress\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"InvalidToken\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MustBeProposedOwner\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"NonExistentChain\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByOwner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OwnerCannotBeZero\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RateLimitMustBeDisabled\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"SenderNotAllowed\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"capacity\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"requested\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenAddress\",\"type\":\"address\"}],\"name\":\"TokenMaxCapacityExceeded\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"minWaitInSeconds\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"available\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenAddress\",\"type\":\"address\"}],\"name\":\"TokenRateLimitReached\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"Unauthorized\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"AllowListAdd\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"AllowListRemove\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Burned\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"remoteToken\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundRateLimiterConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundRateLimiterConfig\",\"type\":\"tuple\"}],\"name\":\"ChainAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundRateLimiterConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundRateLimiterConfig\",\"type\":\"tuple\"}],\"name\":\"ChainConfigured\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"ChainRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"config\",\"type\":\"tuple\"}],\"name\":\"ConfigChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Locked\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Minted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"rateLimitAdmin\",\"type\":\"address\"}],\"name\":\"RateLimitAdminSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Released\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"previousPoolAddress\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"RemotePoolSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"oldRouter\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newRouter\",\"type\":\"address\"}],\"name\":\"RouterUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokens\",\"type\":\"uint256\"}],\"name\":\"TokensConsumed\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"removes\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"adds\",\"type\":\"address[]\"}],\"name\":\"applyAllowListUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"allowed\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"remoteTokenAddress\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundRateLimiterConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundRateLimiterConfig\",\"type\":\"tuple\"}],\"internalType\":\"structTokenPool.ChainUpdate[]\",\"name\":\"chains\",\"type\":\"tuple[]\"}],\"name\":\"applyChainUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAllowList\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAllowListEnabled\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getCurrentInboundRateLimiterState\",\"outputs\":[{\"components\":[{\"internalType\":\"uint128\",\"name\":\"tokens\",\"type\":\"uint128\"},{\"internalType\":\"uint32\",\"name\":\"lastUpdated\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.TokenBucket\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getCurrentOutboundRateLimiterState\",\"outputs\":[{\"components\":[{\"internalType\":\"uint128\",\"name\":\"tokens\",\"type\":\"uint128\"},{\"internalType\":\"uint32\",\"name\":\"lastUpdated\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.TokenBucket\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRateLimitAdmin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getRemotePool\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getRemoteToken\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRmnProxy\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRouter\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getSupportedChains\",\"outputs\":[{\"internalType\":\"uint64[]\",\"name\":\"\",\"type\":\"uint64[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getToken\",\"outputs\":[{\"internalType\":\"contractIERC20\",\"name\":\"token\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"isSupportedChain\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"isSupportedToken\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"originalSender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"localToken\",\"type\":\"address\"}],\"internalType\":\"structPool.LockOrBurnInV1\",\"name\":\"lockOrBurnIn\",\"type\":\"tuple\"}],\"name\":\"lockOrBurn\",\"outputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"destPoolData\",\"type\":\"bytes\"}],\"internalType\":\"structPool.LockOrBurnOutV1\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"originalSender\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"localToken\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"sourcePoolData\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"offchainTokenData\",\"type\":\"bytes\"}],\"internalType\":\"structPool.ReleaseOrMintInV1\",\"name\":\"releaseOrMintIn\",\"type\":\"tuple\"}],\"name\":\"releaseOrMint\",\"outputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"destinationAmount\",\"type\":\"uint256\"}],\"internalType\":\"structPool.ReleaseOrMintOutV1\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundConfig\",\"type\":\"tuple\"}],\"name\":\"setChainRateLimiterConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"rateLimitAdmin\",\"type\":\"address\"}],\"name\":\"setRateLimitAdmin\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"setRemotePool\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newRouter\",\"type\":\"address\"}],\"name\":\"setRouter\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", + Bin: "0x60e06040523480156200001157600080fd5b506040516200444a3803806200444a83398101604081905262000034916200085d565b83838383336000816200005a57604051639b15e16f60e01b815260040160405180910390fd5b600180546001600160a01b0319166001600160a01b03848116919091179091558116156200008d576200008d8162000159565b50506001600160a01b0384161580620000ad57506001600160a01b038116155b80620000c057506001600160a01b038216155b15620000df576040516342bcdf7f60e11b815260040160405180910390fd5b6001600160a01b0384811660805282811660a052600480546001600160a01b031916918316919091179055825115801560c0526200013257604080516000815260208101909152620001329084620001d3565b506200014f925050506001600160a01b0385163060001962000330565b5050505062000a99565b336001600160a01b038216036200018357604051636d6c4ee560e11b815260040160405180910390fd5b600080546001600160a01b0319166001600160a01b03838116918217835560015460405192939116917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b60c051620001f4576040516335f4a7b360e01b815260040160405180910390fd5b60005b82518110156200027f5760008382815181106200021857620002186200096d565b602090810291909101015190506200023260028262000416565b1562000275576040516001600160a01b03821681527f800671136ab6cfee9fbe5ed1fb7ca417811aca3cf864800d127b927adedf75669060200160405180910390a15b50600101620001f7565b5060005b81518110156200032b576000828281518110620002a457620002a46200096d565b6020026020010151905060006001600160a01b0316816001600160a01b031603620002d0575062000322565b620002dd60028262000436565b1562000320576040516001600160a01b03821681527f2640d4d76caf8bf478aabfa982fa4e1c4eb71a37f93cd15e80dbc657911546d89060200160405180910390a15b505b60010162000283565b505050565b604051636eb1769f60e11b81523060048201526001600160a01b038381166024830152600091839186169063dd62ed3e90604401602060405180830381865afa15801562000382573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620003a8919062000983565b620003b49190620009b3565b604080516001600160a01b038616602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b0390811663095ea7b360e01b1790915291925062000410918691906200044d16565b50505050565b60006200042d836001600160a01b03841662000522565b90505b92915050565b60006200042d836001600160a01b03841662000626565b6040805180820190915260208082527f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564908201526000906200049c906001600160a01b03851690849062000678565b8051909150156200032b5780806020019051810190620004bd9190620009c9565b6200032b5760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b60648201526084015b60405180910390fd5b600081815260018301602052604081205480156200061b57600062000549600183620009f4565b85549091506000906200055f90600190620009f4565b9050808214620005cb5760008660000182815481106200058357620005836200096d565b9060005260206000200154905080876000018481548110620005a957620005a96200096d565b6000918252602080832090910192909255918252600188019052604090208390555b8554869080620005df57620005df62000a0a565b60019003818190600052602060002001600090559055856001016000868152602001908152602001600020600090556001935050505062000430565b600091505062000430565b60008181526001830160205260408120546200066f5750815460018181018455600084815260208082209093018490558454848252828601909352604090209190915562000430565b50600062000430565b606062000689848460008562000691565b949350505050565b606082471015620006f45760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b606482015260840162000519565b600080866001600160a01b0316858760405162000712919062000a46565b60006040518083038185875af1925050503d806000811462000751576040519150601f19603f3d011682016040523d82523d6000602084013e62000756565b606091505b5090925090506200076a8783838762000775565b979650505050505050565b60608315620007e9578251600003620007e1576001600160a01b0385163b620007e15760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640162000519565b508162000689565b620006898383815115620008005781518083602001fd5b8060405162461bcd60e51b815260040162000519919062000a64565b6001600160a01b03811681146200083257600080fd5b50565b634e487b7160e01b600052604160045260246000fd5b805162000858816200081c565b919050565b600080600080608085870312156200087457600080fd5b845162000881816200081c565b602086810151919550906001600160401b0380821115620008a157600080fd5b818801915088601f830112620008b657600080fd5b815181811115620008cb57620008cb62000835565b8060051b604051601f19603f83011681018181108582111715620008f357620008f362000835565b60405291825284820192508381018501918b8311156200091257600080fd5b938501935b828510156200093b576200092b856200084b565b8452938501939285019262000917565b80985050505050505062000952604086016200084b565b915062000962606086016200084b565b905092959194509250565b634e487b7160e01b600052603260045260246000fd5b6000602082840312156200099657600080fd5b5051919050565b634e487b7160e01b600052601160045260246000fd5b808201808211156200043057620004306200099d565b600060208284031215620009dc57600080fd5b81518015158114620009ed57600080fd5b9392505050565b818103818111156200043057620004306200099d565b634e487b7160e01b600052603160045260246000fd5b60005b8381101562000a3d57818101518382015260200162000a23565b50506000910152565b6000825162000a5a81846020870162000a20565b9190910192915050565b602081526000825180602084015262000a8581604085016020870162000a20565b601f01601f19169190910160400192915050565b60805160a05160c05161393462000b16600039600081816104dd0152818161174a01526120fd0152600081816104b7015281816115ab0152611a000152600081816102390152818161028e015281816106e0015281816114cb0152818161192001528181611b180152818161209301526122e801526139346000f3fe608060405234801561001057600080fd5b50600436106101ae5760003560e01c80639a4575b9116100ee578063c4bffe2b11610097578063db6327dc11610071578063db6327dc146104a2578063dc0bd971146104b5578063e0351e13146104db578063f2fde38b1461050157600080fd5b8063c4bffe2b14610467578063c75eea9c1461047c578063cf7401f31461048f57600080fd5b8063b0f479a1116100c8578063b0f479a114610423578063b794658014610441578063c0d786551461045457600080fd5b80639a4575b91461037f578063a7cd63b71461039f578063af58d59f146103b457600080fd5b806354c8a4f31161015b57806379ba50971161013557806379ba5097146103335780637d54534e1461033b5780638926f54f1461034e5780638da5cb5b1461036157600080fd5b806354c8a4f3146102ed5780636d3d1a581461030257806378a010b21461032057600080fd5b806321df0da71161018c57806321df0da714610237578063240028e81461027e57806339077537146102cb57600080fd5b806301ffc9a7146101b35780630a2fd493146101db578063181f5a77146101fb575b600080fd5b6101c66101c1366004612a8b565b610514565b60405190151581526020015b60405180910390f35b6101ee6101e9366004612aea565b6105f9565b6040516101d29190612b69565b6101ee6040518060400160405280601b81526020017f4275726e46726f6d4d696e74546f6b656e506f6f6c20312e352e30000000000081525081565b7f00000000000000000000000000000000000000000000000000000000000000005b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101d2565b6101c661028c366004612ba9565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff90811691161490565b6102de6102d9366004612bc6565b6106a9565b604051905181526020016101d2565b6103006102fb366004612c4e565b61082f565b005b60085473ffffffffffffffffffffffffffffffffffffffff16610259565b61030061032e366004612cba565b6108aa565b610300610a1e565b610300610349366004612ba9565b610aec565b6101c661035c366004612aea565b610b6d565b60015473ffffffffffffffffffffffffffffffffffffffff16610259565b61039261038d366004612d3d565b610b84565b6040516101d29190612d78565b6103a7610c2b565b6040516101d29190612dd8565b6103c76103c2366004612aea565b610c3c565b6040516101d2919081516fffffffffffffffffffffffffffffffff908116825260208084015163ffffffff1690830152604080840151151590830152606080840151821690830152608092830151169181019190915260a00190565b60045473ffffffffffffffffffffffffffffffffffffffff16610259565b6101ee61044f366004612aea565b610d11565b610300610462366004612ba9565b610d3c565b61046f610e17565b6040516101d29190612e32565b6103c761048a366004612aea565b610ecf565b61030061049d366004612f9a565b610fa1565b6103006104b0366004612fdf565b61102a565b7f0000000000000000000000000000000000000000000000000000000000000000610259565b7f00000000000000000000000000000000000000000000000000000000000000006101c6565b61030061050f366004612ba9565b6114b0565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167faff2afbf0000000000000000000000000000000000000000000000000000000014806105a757507fffffffff0000000000000000000000000000000000000000000000000000000082167f0e64dd2900000000000000000000000000000000000000000000000000000000145b806105f357507fffffffff0000000000000000000000000000000000000000000000000000000082167f01ffc9a700000000000000000000000000000000000000000000000000000000145b92915050565b67ffffffffffffffff8116600090815260076020526040902060040180546060919061062490613021565b80601f016020809104026020016040519081016040528092919081815260200182805461065090613021565b801561069d5780601f106106725761010080835404028352916020019161069d565b820191906000526020600020905b81548152906001019060200180831161068057829003601f168201915b50505050509050919050565b6040805160208101909152600081526106c96106c48361311f565b6114c4565b73ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000166340c10f196107156060850160408601612ba9565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b16815273ffffffffffffffffffffffffffffffffffffffff909116600482015260608501356024820152604401600060405180830381600087803b15801561078557600080fd5b505af1158015610799573d6000803e3d6000fd5b506107ae925050506060830160408401612ba9565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f9d228d69b5fdb8d273a2336f8fb8612d039631024ea9bf09c424a9503aa078f0846060013560405161081091815260200190565b60405180910390a3506040805160208101909152606090910135815290565b6108376116f5565b6108a48484808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152505060408051602080880282810182019093528782529093508792508691829185019084908082843760009201919091525061174892505050565b50505050565b6108b26116f5565b6108bb83610b6d565b610902576040517f1e670e4b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff841660048201526024015b60405180910390fd5b67ffffffffffffffff83166000908152600760205260408120600401805461092990613021565b80601f016020809104026020016040519081016040528092919081815260200182805461095590613021565b80156109a25780601f10610977576101008083540402835291602001916109a2565b820191906000526020600020905b81548152906001019060200180831161098557829003601f168201915b5050505067ffffffffffffffff86166000908152600760205260409020919250506004016109d1838583613264565b508367ffffffffffffffff167fdb4d6220746a38cbc5335f7e108f7de80f482f4d23350253dfd0917df75a14bf828585604051610a109392919061337e565b60405180910390a250505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314610a6f576040517f02b543c600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000008082163390811790935560008054909116815560405173ffffffffffffffffffffffffffffffffffffffff909216929183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b610af46116f5565b600880547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040519081527f44676b5284b809a22248eba0da87391d79098be38bb03154be88a58bf4d091749060200160405180910390a150565b60006105f3600567ffffffffffffffff84166118fe565b6040805180820190915260608082526020820152610ba9610ba4836133e2565b611919565b610bb68260600135611ae3565b6040516060830135815233907f696de425f79f4a40bc6d2122ca50507f0efbeabbff86a84871b7196ab8ea8df79060200160405180910390a26040518060400160405280610c1084602001602081019061044f9190612aea565b81526040805160208181019092526000815291015292915050565b6060610c376002611b8c565b905090565b6040805160a08101825260008082526020820181905291810182905260608101829052608081019190915267ffffffffffffffff8216600090815260076020908152604091829020825160a08101845260028201546fffffffffffffffffffffffffffffffff808216835270010000000000000000000000000000000080830463ffffffff16958401959095527401000000000000000000000000000000000000000090910460ff1615159482019490945260039091015480841660608301529190910490911660808201526105f390611b99565b67ffffffffffffffff8116600090815260076020526040902060050180546060919061062490613021565b610d446116f5565b73ffffffffffffffffffffffffffffffffffffffff8116610d91576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6004805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff000000000000000000000000000000000000000083168117909355604080519190921680825260208201939093527f02dc5c233404867c793b749c6d644beb2277536d18a7e7974d3f238e4c6f1684910160405180910390a15050565b60606000610e256005611b8c565b90506000815167ffffffffffffffff811115610e4357610e43612e74565b604051908082528060200260200182016040528015610e6c578160200160208202803683370190505b50905060005b8251811015610ec857828181518110610e8d57610e8d613484565b6020026020010151828281518110610ea757610ea7613484565b67ffffffffffffffff90921660209283029190910190910152600101610e72565b5092915050565b6040805160a08101825260008082526020820181905291810182905260608101829052608081019190915267ffffffffffffffff8216600090815260076020908152604091829020825160a08101845281546fffffffffffffffffffffffffffffffff808216835270010000000000000000000000000000000080830463ffffffff16958401959095527401000000000000000000000000000000000000000090910460ff1615159482019490945260019091015480841660608301529190910490911660808201526105f390611b99565b60085473ffffffffffffffffffffffffffffffffffffffff163314801590610fe1575060015473ffffffffffffffffffffffffffffffffffffffff163314155b1561101a576040517f8e4a23d60000000000000000000000000000000000000000000000000000000081523360048201526024016108f9565b611025838383611c4b565b505050565b6110326116f5565b60005b8181101561102557600083838381811061105157611051613484565b905060200281019061106391906134b3565b61106c906134f1565b90506110818160800151826020015115611d35565b6110948160a00151826020015115611d35565b8060200151156113905780516110b69060059067ffffffffffffffff16611e6e565b6110fb5780516040517f1d5ad3c500000000000000000000000000000000000000000000000000000000815267ffffffffffffffff90911660048201526024016108f9565b60408101515115806111105750606081015151155b15611147576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805161012081018252608083810180516020908101516fffffffffffffffffffffffffffffffff9081168486019081524263ffffffff90811660a0808901829052865151151560c08a01528651860151851660e08a015295518901518416610100890152918752875180860189529489018051850151841686528585019290925281515115158589015281518401518316606080870191909152915188015183168587015283870194855288880151878901908152828a015183890152895167ffffffffffffffff1660009081526007865289902088518051825482890151838e01519289167fffffffffffffffffffffffff0000000000000000000000000000000000000000928316177001000000000000000000000000000000009188168202177fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff90811674010000000000000000000000000000000000000000941515850217865584890151948d0151948a16948a168202949094176001860155995180516002860180549b8301519f830151918b169b9093169a909a179d9096168a029c909c1790911696151502959095179098559081015194015193811693169091029190911760038201559151909190600482019061132890826135a5565b506060820151600582019061133d90826135a5565b505081516060830151608084015160a08501516040517f8d340f17e19058004c20453540862a9c62778504476f6756755cb33bcd6c38c2955061138394939291906136bf565b60405180910390a16114a7565b80516113a89060059067ffffffffffffffff16611e7a565b6113ed5780516040517f1e670e4b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff90911660048201526024016108f9565b805167ffffffffffffffff16600090815260076020526040812080547fffffffffffffffffffffff000000000000000000000000000000000000000000908116825560018201839055600282018054909116905560038101829055906114566004830182612a3d565b611464600583016000612a3d565b5050805160405167ffffffffffffffff90911681527f5204aec90a3c794d8e90fded8b46ae9c7c552803e7e832e0c1d358396d8599169060200160405180910390a15b50600101611035565b6114b86116f5565b6114c181611e86565b50565b60808101517f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff9081169116146115595760808101516040517f961c9a4f00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff90911660048201526024016108f9565b60208101516040517f2cbc26bb00000000000000000000000000000000000000000000000000000000815260809190911b77ffffffffffffffff000000000000000000000000000000001660048201527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1690632cbc26bb90602401602060405180830381865afa158015611607573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061162b9190613758565b15611662576040517f53ad11d800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61166f8160200151611f4a565b600061167e82602001516105f9565b90508051600014806116a2575080805190602001208260a001518051906020012014155b156116df578160a001516040517f24eb47e50000000000000000000000000000000000000000000000000000000081526004016108f99190612b69565b6116f182602001518360600151612070565b5050565b60015473ffffffffffffffffffffffffffffffffffffffff163314611746576040517f2b5c74de00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b565b7f000000000000000000000000000000000000000000000000000000000000000061179f576040517f35f4a7b300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b82518110156118355760008382815181106117bf576117bf613484565b602002602001015190506117dd8160026120b790919063ffffffff16565b1561182c5760405173ffffffffffffffffffffffffffffffffffffffff821681527f800671136ab6cfee9fbe5ed1fb7ca417811aca3cf864800d127b927adedf75669060200160405180910390a15b506001016117a2565b5060005b815181101561102557600082828151811061185657611856613484565b60200260200101519050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff160361189a57506118f6565b6118a56002826120d9565b156118f45760405173ffffffffffffffffffffffffffffffffffffffff821681527f2640d4d76caf8bf478aabfa982fa4e1c4eb71a37f93cd15e80dbc657911546d89060200160405180910390a15b505b600101611839565b600081815260018301602052604081205415155b9392505050565b60808101517f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff9081169116146119ae5760808101516040517f961c9a4f00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff90911660048201526024016108f9565b60208101516040517f2cbc26bb00000000000000000000000000000000000000000000000000000000815260809190911b77ffffffffffffffff000000000000000000000000000000001660048201527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1690632cbc26bb90602401602060405180830381865afa158015611a5c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a809190613758565b15611ab7576040517f53ad11d800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611ac481604001516120fb565b611ad1816020015161217a565b6114c1816020015182606001516122c8565b6040517f79cc6790000000000000000000000000000000000000000000000000000000008152306004820152602481018290527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16906379cc679090604401600060405180830381600087803b158015611b7157600080fd5b505af1158015611b85573d6000803e3d6000fd5b5050505050565b606060006119128361230c565b6040805160a081018252600080825260208201819052918101829052606081018290526080810191909152611c2782606001516fffffffffffffffffffffffffffffffff1683600001516fffffffffffffffffffffffffffffffff16846020015163ffffffff1642611c0b91906137a4565b85608001516fffffffffffffffffffffffffffffffff16612367565b6fffffffffffffffffffffffffffffffff1682525063ffffffff4216602082015290565b611c5483610b6d565b611c96576040517f1e670e4b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff841660048201526024016108f9565b611ca1826000611d35565b67ffffffffffffffff83166000908152600760205260409020611cc49083612391565b611ccf816000611d35565b67ffffffffffffffff83166000908152600760205260409020611cf59060020182612391565b7f0350d63aa5f270e01729d00d627eeb8f3429772b1818c016c66a588a864f912b838383604051611d28939291906137b7565b60405180910390a1505050565b815115611dfc5781602001516fffffffffffffffffffffffffffffffff1682604001516fffffffffffffffffffffffffffffffff16101580611d8b575060408201516fffffffffffffffffffffffffffffffff16155b15611dc457816040517f8020d1240000000000000000000000000000000000000000000000000000000081526004016108f9919061383a565b80156116f1576040517f433fc33d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60408201516fffffffffffffffffffffffffffffffff16151580611e35575060208201516fffffffffffffffffffffffffffffffff1615155b156116f157816040517fd68af9cc0000000000000000000000000000000000000000000000000000000081526004016108f9919061383a565b60006119128383612533565b60006119128383612582565b3373ffffffffffffffffffffffffffffffffffffffff821603611ed5576040517fdad89dca00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff838116918217835560015460405192939116917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b611f5381610b6d565b611f95576040517fa9902c7e00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff821660048201526024016108f9565b600480546040517f83826b2b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84169281019290925233602483015273ffffffffffffffffffffffffffffffffffffffff16906383826b2b90604401602060405180830381865afa158015612014573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120389190613758565b6114c1576040517f728fe07b0000000000000000000000000000000000000000000000000000000081523360048201526024016108f9565b67ffffffffffffffff821660009081526007602052604090206116f190600201827f0000000000000000000000000000000000000000000000000000000000000000612675565b60006119128373ffffffffffffffffffffffffffffffffffffffff8416612582565b60006119128373ffffffffffffffffffffffffffffffffffffffff8416612533565b7f0000000000000000000000000000000000000000000000000000000000000000156114c15761212c6002826129f8565b6114c1576040517fd0d2597600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff821660048201526024016108f9565b61218381610b6d565b6121c5576040517fa9902c7e00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff821660048201526024016108f9565b600480546040517fa8d87a3b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84169281019290925273ffffffffffffffffffffffffffffffffffffffff169063a8d87a3b90602401602060405180830381865afa15801561223e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122629190613876565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146114c1576040517f728fe07b0000000000000000000000000000000000000000000000000000000081523360048201526024016108f9565b67ffffffffffffffff821660009081526007602052604090206116f190827f0000000000000000000000000000000000000000000000000000000000000000612675565b60608160000180548060200260200160405190810160405280929190818152602001828054801561069d57602002820191906000526020600020905b8154815260200190600101908083116123485750505050509050919050565b6000612386856123778486613893565b61238190876138aa565b612a27565b90505b949350505050565b81546000906123ba90700100000000000000000000000000000000900463ffffffff16426137a4565b9050801561245c5760018301548354612402916fffffffffffffffffffffffffffffffff80821692811691859170010000000000000000000000000000000090910416612367565b83546fffffffffffffffffffffffffffffffff919091167fffffffffffffffffffffffff0000000000000000000000000000000000000000909116177001000000000000000000000000000000004263ffffffff16021783555b60208201518354612482916fffffffffffffffffffffffffffffffff9081169116612a27565b83548351151574010000000000000000000000000000000000000000027fffffffffffffffffffffff00ffffffff000000000000000000000000000000009091166fffffffffffffffffffffffffffffffff92831617178455602083015160408085015183167001000000000000000000000000000000000291909216176001850155517f9ea3374b67bf275e6bb9c8ae68f9cae023e1c528b4b27e092f0bb209d3531c1990611d2890849061383a565b600081815260018301602052604081205461257a575081546001818101845560008481526020808220909301849055845484825282860190935260409020919091556105f3565b5060006105f3565b6000818152600183016020526040812054801561266b5760006125a66001836137a4565b85549091506000906125ba906001906137a4565b905080821461261f5760008660000182815481106125da576125da613484565b90600052602060002001549050808760000184815481106125fd576125fd613484565b6000918252602080832090910192909255918252600188019052604090208390555b8554869080612630576126306138bd565b6001900381819060005260206000200160009055905585600101600086815260200190815260200160002060009055600193505050506105f3565b60009150506105f3565b825474010000000000000000000000000000000000000000900460ff16158061269c575081155b156126a657505050565b825460018401546fffffffffffffffffffffffffffffffff808316929116906000906126ec90700100000000000000000000000000000000900463ffffffff16426137a4565b905080156127ac578183111561272e576040517f9725942a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018601546127689083908590849070010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff16612367565b86547fffffffffffffffffffffffff00000000ffffffffffffffffffffffffffffffff167001000000000000000000000000000000004263ffffffff160217875592505b848210156128635773ffffffffffffffffffffffffffffffffffffffff841661280b576040517ff94ebcd100000000000000000000000000000000000000000000000000000000815260048101839052602481018690526044016108f9565b6040517f1a76572a000000000000000000000000000000000000000000000000000000008152600481018390526024810186905273ffffffffffffffffffffffffffffffffffffffff851660448201526064016108f9565b848310156129765760018681015470010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff169060009082906128a790826137a4565b6128b1878a6137a4565b6128bb91906138aa565b6128c591906138ec565b905073ffffffffffffffffffffffffffffffffffffffff861661291e576040517f15279c0800000000000000000000000000000000000000000000000000000000815260048101829052602481018690526044016108f9565b6040517fd0c8d23a000000000000000000000000000000000000000000000000000000008152600481018290526024810186905273ffffffffffffffffffffffffffffffffffffffff871660448201526064016108f9565b61298085846137a4565b86547fffffffffffffffffffffffffffffffff00000000000000000000000000000000166fffffffffffffffffffffffffffffffff82161787556040518681529093507f1871cdf8010e63f2eb8384381a68dfa7416dc571a5517e66e88b2d2d0c0a690a9060200160405180910390a1505050505050565b73ffffffffffffffffffffffffffffffffffffffff811660009081526001830160205260408120541515611912565b6000818310612a365781611912565b5090919050565b508054612a4990613021565b6000825580601f10612a59575050565b601f0160209004906000526020600020908101906114c191905b80821115612a875760008155600101612a73565b5090565b600060208284031215612a9d57600080fd5b81357fffffffff000000000000000000000000000000000000000000000000000000008116811461191257600080fd5b803567ffffffffffffffff81168114612ae557600080fd5b919050565b600060208284031215612afc57600080fd5b61191282612acd565b6000815180845260005b81811015612b2b57602081850181015186830182015201612b0f565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b6020815260006119126020830184612b05565b73ffffffffffffffffffffffffffffffffffffffff811681146114c157600080fd5b8035612ae581612b7c565b600060208284031215612bbb57600080fd5b813561191281612b7c565b600060208284031215612bd857600080fd5b813567ffffffffffffffff811115612bef57600080fd5b8201610100818503121561191257600080fd5b60008083601f840112612c1457600080fd5b50813567ffffffffffffffff811115612c2c57600080fd5b6020830191508360208260051b8501011115612c4757600080fd5b9250929050565b60008060008060408587031215612c6457600080fd5b843567ffffffffffffffff80821115612c7c57600080fd5b612c8888838901612c02565b90965094506020870135915080821115612ca157600080fd5b50612cae87828801612c02565b95989497509550505050565b600080600060408486031215612ccf57600080fd5b612cd884612acd565b9250602084013567ffffffffffffffff80821115612cf557600080fd5b818601915086601f830112612d0957600080fd5b813581811115612d1857600080fd5b876020828501011115612d2a57600080fd5b6020830194508093505050509250925092565b600060208284031215612d4f57600080fd5b813567ffffffffffffffff811115612d6657600080fd5b820160a0818503121561191257600080fd5b602081526000825160406020840152612d946060840182612b05565b905060208401517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0848303016040850152612dcf8282612b05565b95945050505050565b6020808252825182820181905260009190848201906040850190845b81811015612e2657835173ffffffffffffffffffffffffffffffffffffffff1683529284019291840191600101612df4565b50909695505050505050565b6020808252825182820181905260009190848201906040850190845b81811015612e2657835167ffffffffffffffff1683529284019291840191600101612e4e565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051610100810167ffffffffffffffff81118282101715612ec757612ec7612e74565b60405290565b60405160c0810167ffffffffffffffff81118282101715612ec757612ec7612e74565b80151581146114c157600080fd5b8035612ae581612ef0565b80356fffffffffffffffffffffffffffffffff81168114612ae557600080fd5b600060608284031215612f3b57600080fd5b6040516060810181811067ffffffffffffffff82111715612f5e57612f5e612e74565b6040529050808235612f6f81612ef0565b8152612f7d60208401612f09565b6020820152612f8e60408401612f09565b60408201525092915050565b600080600060e08486031215612faf57600080fd5b612fb884612acd565b9250612fc78560208601612f29565b9150612fd68560808601612f29565b90509250925092565b60008060208385031215612ff257600080fd5b823567ffffffffffffffff81111561300957600080fd5b61301585828601612c02565b90969095509350505050565b600181811c9082168061303557607f821691505b60208210810361306e577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b600082601f83011261308557600080fd5b813567ffffffffffffffff808211156130a0576130a0612e74565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f011681019082821181831017156130e6576130e6612e74565b816040528381528660208588010111156130ff57600080fd5b836020870160208301376000602085830101528094505050505092915050565b6000610100823603121561313257600080fd5b61313a612ea3565b823567ffffffffffffffff8082111561315257600080fd5b61315e36838701613074565b835261316c60208601612acd565b602084015261317d60408601612b9e565b60408401526060850135606084015261319860808601612b9e565b608084015260a08501359150808211156131b157600080fd5b6131bd36838701613074565b60a084015260c08501359150808211156131d657600080fd5b6131e236838701613074565b60c084015260e08501359150808211156131fb57600080fd5b5061320836828601613074565b60e08301525092915050565b601f821115611025576000816000526020600020601f850160051c8101602086101561323d5750805b601f850160051c820191505b8181101561325c57828155600101613249565b505050505050565b67ffffffffffffffff83111561327c5761327c612e74565b6132908361328a8354613021565b83613214565b6000601f8411600181146132e257600085156132ac5750838201355b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600387901b1c1916600186901b178355611b85565b6000838152602090207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0861690835b828110156133315786850135825560209485019460019092019101613311565b508682101561336c577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88860031b161c19848701351681555b505060018560011b0183555050505050565b6040815260006133916040830186612b05565b82810360208401528381528385602083013760006020858301015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f860116820101915050949350505050565b600060a082360312156133f457600080fd5b60405160a0810167ffffffffffffffff828210818311171561341857613418612e74565b81604052843591508082111561342d57600080fd5b5061343a36828601613074565b82525061344960208401612acd565b6020820152604083013561345c81612b7c565b604082015260608381013590820152608083013561347981612b7c565b608082015292915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600082357ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffec18336030181126134e757600080fd5b9190910192915050565b6000610140823603121561350457600080fd5b61350c612ecd565b61351583612acd565b815261352360208401612efe565b6020820152604083013567ffffffffffffffff8082111561354357600080fd5b61354f36838701613074565b6040840152606085013591508082111561356857600080fd5b5061357536828601613074565b6060830152506135883660808501612f29565b608082015261359a3660e08501612f29565b60a082015292915050565b815167ffffffffffffffff8111156135bf576135bf612e74565b6135d3816135cd8454613021565b84613214565b602080601f83116001811461362657600084156135f05750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b17855561325c565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b8281101561367357888601518255948401946001909101908401613654565b50858210156136af57878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b600061010067ffffffffffffffff871683528060208401526136e381840187612b05565b8551151560408581019190915260208701516fffffffffffffffffffffffffffffffff90811660608701529087015116608085015291506137219050565b8251151560a083015260208301516fffffffffffffffffffffffffffffffff90811660c084015260408401511660e0830152612dcf565b60006020828403121561376a57600080fd5b815161191281612ef0565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b818103818111156105f3576105f3613775565b67ffffffffffffffff8416815260e0810161380360208301858051151582526020808201516fffffffffffffffffffffffffffffffff9081169184019190915260409182015116910152565b82511515608083015260208301516fffffffffffffffffffffffffffffffff90811660a084015260408401511660c0830152612389565b606081016105f382848051151582526020808201516fffffffffffffffffffffffffffffffff9081169184019190915260409182015116910152565b60006020828403121561388857600080fd5b815161191281612b7c565b80820281158282048414176105f3576105f3613775565b808201808211156105f3576105f3613775565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b600082613922577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b50049056fea164736f6c6343000818000a", } var BurnFromMintTokenPoolABI = BurnFromMintTokenPoolMetaData.ABI var BurnFromMintTokenPoolBin = BurnFromMintTokenPoolMetaData.Bin -func DeployBurnFromMintTokenPool(auth *bind.TransactOpts, backend bind.ContractBackend, token common.Address, localTokenDecimals uint8, allowlist []common.Address, rmnProxy common.Address, router common.Address) (common.Address, *types.Transaction, *BurnFromMintTokenPool, error) { +func DeployBurnFromMintTokenPool(auth *bind.TransactOpts, backend bind.ContractBackend, token common.Address, allowlist []common.Address, rmnProxy common.Address, router common.Address) (common.Address, *types.Transaction, *BurnFromMintTokenPool, error) { parsed, err := BurnFromMintTokenPoolMetaData.GetAbi() if err != nil { return common.Address{}, nil, nil, err @@ -98,7 +99,7 @@ func DeployBurnFromMintTokenPool(auth *bind.TransactOpts, backend bind.ContractB return common.Address{}, nil, nil, errors.New("GetABI returned nil") } - address, tx, contract, err := bind.DeployContract(auth, *parsed, common.FromHex(BurnFromMintTokenPoolBin), backend, token, localTokenDecimals, allowlist, rmnProxy, router) + address, tx, contract, err := bind.DeployContract(auth, *parsed, common.FromHex(BurnFromMintTokenPoolBin), backend, token, allowlist, rmnProxy, router) if err != nil { return common.Address{}, nil, nil, err } @@ -331,26 +332,26 @@ func (_BurnFromMintTokenPool *BurnFromMintTokenPoolCallerSession) GetRateLimitAd return _BurnFromMintTokenPool.Contract.GetRateLimitAdmin(&_BurnFromMintTokenPool.CallOpts) } -func (_BurnFromMintTokenPool *BurnFromMintTokenPoolCaller) GetRemotePools(opts *bind.CallOpts, remoteChainSelector uint64) ([][]byte, error) { +func (_BurnFromMintTokenPool *BurnFromMintTokenPoolCaller) GetRemotePool(opts *bind.CallOpts, remoteChainSelector uint64) ([]byte, error) { var out []interface{} - err := _BurnFromMintTokenPool.contract.Call(opts, &out, "getRemotePools", remoteChainSelector) + err := _BurnFromMintTokenPool.contract.Call(opts, &out, "getRemotePool", remoteChainSelector) if err != nil { - return *new([][]byte), err + return *new([]byte), err } - out0 := *abi.ConvertType(out[0], new([][]byte)).(*[][]byte) + out0 := *abi.ConvertType(out[0], new([]byte)).(*[]byte) return out0, err } -func (_BurnFromMintTokenPool *BurnFromMintTokenPoolSession) GetRemotePools(remoteChainSelector uint64) ([][]byte, error) { - return _BurnFromMintTokenPool.Contract.GetRemotePools(&_BurnFromMintTokenPool.CallOpts, remoteChainSelector) +func (_BurnFromMintTokenPool *BurnFromMintTokenPoolSession) GetRemotePool(remoteChainSelector uint64) ([]byte, error) { + return _BurnFromMintTokenPool.Contract.GetRemotePool(&_BurnFromMintTokenPool.CallOpts, remoteChainSelector) } -func (_BurnFromMintTokenPool *BurnFromMintTokenPoolCallerSession) GetRemotePools(remoteChainSelector uint64) ([][]byte, error) { - return _BurnFromMintTokenPool.Contract.GetRemotePools(&_BurnFromMintTokenPool.CallOpts, remoteChainSelector) +func (_BurnFromMintTokenPool *BurnFromMintTokenPoolCallerSession) GetRemotePool(remoteChainSelector uint64) ([]byte, error) { + return _BurnFromMintTokenPool.Contract.GetRemotePool(&_BurnFromMintTokenPool.CallOpts, remoteChainSelector) } func (_BurnFromMintTokenPool *BurnFromMintTokenPoolCaller) GetRemoteToken(opts *bind.CallOpts, remoteChainSelector uint64) ([]byte, error) { @@ -463,50 +464,6 @@ func (_BurnFromMintTokenPool *BurnFromMintTokenPoolCallerSession) GetToken() (co return _BurnFromMintTokenPool.Contract.GetToken(&_BurnFromMintTokenPool.CallOpts) } -func (_BurnFromMintTokenPool *BurnFromMintTokenPoolCaller) GetTokenDecimals(opts *bind.CallOpts) (uint8, error) { - var out []interface{} - err := _BurnFromMintTokenPool.contract.Call(opts, &out, "getTokenDecimals") - - if err != nil { - return *new(uint8), err - } - - out0 := *abi.ConvertType(out[0], new(uint8)).(*uint8) - - return out0, err - -} - -func (_BurnFromMintTokenPool *BurnFromMintTokenPoolSession) GetTokenDecimals() (uint8, error) { - return _BurnFromMintTokenPool.Contract.GetTokenDecimals(&_BurnFromMintTokenPool.CallOpts) -} - -func (_BurnFromMintTokenPool *BurnFromMintTokenPoolCallerSession) GetTokenDecimals() (uint8, error) { - return _BurnFromMintTokenPool.Contract.GetTokenDecimals(&_BurnFromMintTokenPool.CallOpts) -} - -func (_BurnFromMintTokenPool *BurnFromMintTokenPoolCaller) IsRemotePool(opts *bind.CallOpts, remoteChainSelector uint64, remotePoolAddress []byte) (bool, error) { - var out []interface{} - err := _BurnFromMintTokenPool.contract.Call(opts, &out, "isRemotePool", remoteChainSelector, remotePoolAddress) - - if err != nil { - return *new(bool), err - } - - out0 := *abi.ConvertType(out[0], new(bool)).(*bool) - - return out0, err - -} - -func (_BurnFromMintTokenPool *BurnFromMintTokenPoolSession) IsRemotePool(remoteChainSelector uint64, remotePoolAddress []byte) (bool, error) { - return _BurnFromMintTokenPool.Contract.IsRemotePool(&_BurnFromMintTokenPool.CallOpts, remoteChainSelector, remotePoolAddress) -} - -func (_BurnFromMintTokenPool *BurnFromMintTokenPoolCallerSession) IsRemotePool(remoteChainSelector uint64, remotePoolAddress []byte) (bool, error) { - return _BurnFromMintTokenPool.Contract.IsRemotePool(&_BurnFromMintTokenPool.CallOpts, remoteChainSelector, remotePoolAddress) -} - func (_BurnFromMintTokenPool *BurnFromMintTokenPoolCaller) IsSupportedChain(opts *bind.CallOpts, remoteChainSelector uint64) (bool, error) { var out []interface{} err := _BurnFromMintTokenPool.contract.Call(opts, &out, "isSupportedChain", remoteChainSelector) @@ -629,18 +586,6 @@ func (_BurnFromMintTokenPool *BurnFromMintTokenPoolTransactorSession) AcceptOwne return _BurnFromMintTokenPool.Contract.AcceptOwnership(&_BurnFromMintTokenPool.TransactOpts) } -func (_BurnFromMintTokenPool *BurnFromMintTokenPoolTransactor) AddRemotePool(opts *bind.TransactOpts, remoteChainSelector uint64, remotePoolAddress []byte) (*types.Transaction, error) { - return _BurnFromMintTokenPool.contract.Transact(opts, "addRemotePool", remoteChainSelector, remotePoolAddress) -} - -func (_BurnFromMintTokenPool *BurnFromMintTokenPoolSession) AddRemotePool(remoteChainSelector uint64, remotePoolAddress []byte) (*types.Transaction, error) { - return _BurnFromMintTokenPool.Contract.AddRemotePool(&_BurnFromMintTokenPool.TransactOpts, remoteChainSelector, remotePoolAddress) -} - -func (_BurnFromMintTokenPool *BurnFromMintTokenPoolTransactorSession) AddRemotePool(remoteChainSelector uint64, remotePoolAddress []byte) (*types.Transaction, error) { - return _BurnFromMintTokenPool.Contract.AddRemotePool(&_BurnFromMintTokenPool.TransactOpts, remoteChainSelector, remotePoolAddress) -} - func (_BurnFromMintTokenPool *BurnFromMintTokenPoolTransactor) ApplyAllowListUpdates(opts *bind.TransactOpts, removes []common.Address, adds []common.Address) (*types.Transaction, error) { return _BurnFromMintTokenPool.contract.Transact(opts, "applyAllowListUpdates", removes, adds) } @@ -653,16 +598,16 @@ func (_BurnFromMintTokenPool *BurnFromMintTokenPoolTransactorSession) ApplyAllow return _BurnFromMintTokenPool.Contract.ApplyAllowListUpdates(&_BurnFromMintTokenPool.TransactOpts, removes, adds) } -func (_BurnFromMintTokenPool *BurnFromMintTokenPoolTransactor) ApplyChainUpdates(opts *bind.TransactOpts, remoteChainSelectorsToRemove []uint64, chainsToAdd []TokenPoolChainUpdate) (*types.Transaction, error) { - return _BurnFromMintTokenPool.contract.Transact(opts, "applyChainUpdates", remoteChainSelectorsToRemove, chainsToAdd) +func (_BurnFromMintTokenPool *BurnFromMintTokenPoolTransactor) ApplyChainUpdates(opts *bind.TransactOpts, chains []TokenPoolChainUpdate) (*types.Transaction, error) { + return _BurnFromMintTokenPool.contract.Transact(opts, "applyChainUpdates", chains) } -func (_BurnFromMintTokenPool *BurnFromMintTokenPoolSession) ApplyChainUpdates(remoteChainSelectorsToRemove []uint64, chainsToAdd []TokenPoolChainUpdate) (*types.Transaction, error) { - return _BurnFromMintTokenPool.Contract.ApplyChainUpdates(&_BurnFromMintTokenPool.TransactOpts, remoteChainSelectorsToRemove, chainsToAdd) +func (_BurnFromMintTokenPool *BurnFromMintTokenPoolSession) ApplyChainUpdates(chains []TokenPoolChainUpdate) (*types.Transaction, error) { + return _BurnFromMintTokenPool.Contract.ApplyChainUpdates(&_BurnFromMintTokenPool.TransactOpts, chains) } -func (_BurnFromMintTokenPool *BurnFromMintTokenPoolTransactorSession) ApplyChainUpdates(remoteChainSelectorsToRemove []uint64, chainsToAdd []TokenPoolChainUpdate) (*types.Transaction, error) { - return _BurnFromMintTokenPool.Contract.ApplyChainUpdates(&_BurnFromMintTokenPool.TransactOpts, remoteChainSelectorsToRemove, chainsToAdd) +func (_BurnFromMintTokenPool *BurnFromMintTokenPoolTransactorSession) ApplyChainUpdates(chains []TokenPoolChainUpdate) (*types.Transaction, error) { + return _BurnFromMintTokenPool.Contract.ApplyChainUpdates(&_BurnFromMintTokenPool.TransactOpts, chains) } func (_BurnFromMintTokenPool *BurnFromMintTokenPoolTransactor) LockOrBurn(opts *bind.TransactOpts, lockOrBurnIn PoolLockOrBurnInV1) (*types.Transaction, error) { @@ -689,18 +634,6 @@ func (_BurnFromMintTokenPool *BurnFromMintTokenPoolTransactorSession) ReleaseOrM return _BurnFromMintTokenPool.Contract.ReleaseOrMint(&_BurnFromMintTokenPool.TransactOpts, releaseOrMintIn) } -func (_BurnFromMintTokenPool *BurnFromMintTokenPoolTransactor) RemoveRemotePool(opts *bind.TransactOpts, remoteChainSelector uint64, remotePoolAddress []byte) (*types.Transaction, error) { - return _BurnFromMintTokenPool.contract.Transact(opts, "removeRemotePool", remoteChainSelector, remotePoolAddress) -} - -func (_BurnFromMintTokenPool *BurnFromMintTokenPoolSession) RemoveRemotePool(remoteChainSelector uint64, remotePoolAddress []byte) (*types.Transaction, error) { - return _BurnFromMintTokenPool.Contract.RemoveRemotePool(&_BurnFromMintTokenPool.TransactOpts, remoteChainSelector, remotePoolAddress) -} - -func (_BurnFromMintTokenPool *BurnFromMintTokenPoolTransactorSession) RemoveRemotePool(remoteChainSelector uint64, remotePoolAddress []byte) (*types.Transaction, error) { - return _BurnFromMintTokenPool.Contract.RemoveRemotePool(&_BurnFromMintTokenPool.TransactOpts, remoteChainSelector, remotePoolAddress) -} - func (_BurnFromMintTokenPool *BurnFromMintTokenPoolTransactor) SetChainRateLimiterConfig(opts *bind.TransactOpts, remoteChainSelector uint64, outboundConfig RateLimiterConfig, inboundConfig RateLimiterConfig) (*types.Transaction, error) { return _BurnFromMintTokenPool.contract.Transact(opts, "setChainRateLimiterConfig", remoteChainSelector, outboundConfig, inboundConfig) } @@ -713,18 +646,6 @@ func (_BurnFromMintTokenPool *BurnFromMintTokenPoolTransactorSession) SetChainRa return _BurnFromMintTokenPool.Contract.SetChainRateLimiterConfig(&_BurnFromMintTokenPool.TransactOpts, remoteChainSelector, outboundConfig, inboundConfig) } -func (_BurnFromMintTokenPool *BurnFromMintTokenPoolTransactor) SetChainRateLimiterConfigs(opts *bind.TransactOpts, remoteChainSelectors []uint64, outboundConfigs []RateLimiterConfig, inboundConfigs []RateLimiterConfig) (*types.Transaction, error) { - return _BurnFromMintTokenPool.contract.Transact(opts, "setChainRateLimiterConfigs", remoteChainSelectors, outboundConfigs, inboundConfigs) -} - -func (_BurnFromMintTokenPool *BurnFromMintTokenPoolSession) SetChainRateLimiterConfigs(remoteChainSelectors []uint64, outboundConfigs []RateLimiterConfig, inboundConfigs []RateLimiterConfig) (*types.Transaction, error) { - return _BurnFromMintTokenPool.Contract.SetChainRateLimiterConfigs(&_BurnFromMintTokenPool.TransactOpts, remoteChainSelectors, outboundConfigs, inboundConfigs) -} - -func (_BurnFromMintTokenPool *BurnFromMintTokenPoolTransactorSession) SetChainRateLimiterConfigs(remoteChainSelectors []uint64, outboundConfigs []RateLimiterConfig, inboundConfigs []RateLimiterConfig) (*types.Transaction, error) { - return _BurnFromMintTokenPool.Contract.SetChainRateLimiterConfigs(&_BurnFromMintTokenPool.TransactOpts, remoteChainSelectors, outboundConfigs, inboundConfigs) -} - func (_BurnFromMintTokenPool *BurnFromMintTokenPoolTransactor) SetRateLimitAdmin(opts *bind.TransactOpts, rateLimitAdmin common.Address) (*types.Transaction, error) { return _BurnFromMintTokenPool.contract.Transact(opts, "setRateLimitAdmin", rateLimitAdmin) } @@ -737,6 +658,18 @@ func (_BurnFromMintTokenPool *BurnFromMintTokenPoolTransactorSession) SetRateLim return _BurnFromMintTokenPool.Contract.SetRateLimitAdmin(&_BurnFromMintTokenPool.TransactOpts, rateLimitAdmin) } +func (_BurnFromMintTokenPool *BurnFromMintTokenPoolTransactor) SetRemotePool(opts *bind.TransactOpts, remoteChainSelector uint64, remotePoolAddress []byte) (*types.Transaction, error) { + return _BurnFromMintTokenPool.contract.Transact(opts, "setRemotePool", remoteChainSelector, remotePoolAddress) +} + +func (_BurnFromMintTokenPool *BurnFromMintTokenPoolSession) SetRemotePool(remoteChainSelector uint64, remotePoolAddress []byte) (*types.Transaction, error) { + return _BurnFromMintTokenPool.Contract.SetRemotePool(&_BurnFromMintTokenPool.TransactOpts, remoteChainSelector, remotePoolAddress) +} + +func (_BurnFromMintTokenPool *BurnFromMintTokenPoolTransactorSession) SetRemotePool(remoteChainSelector uint64, remotePoolAddress []byte) (*types.Transaction, error) { + return _BurnFromMintTokenPool.Contract.SetRemotePool(&_BurnFromMintTokenPool.TransactOpts, remoteChainSelector, remotePoolAddress) +} + func (_BurnFromMintTokenPool *BurnFromMintTokenPoolTransactor) SetRouter(opts *bind.TransactOpts, newRouter common.Address) (*types.Transaction, error) { return _BurnFromMintTokenPool.contract.Transact(opts, "setRouter", newRouter) } @@ -2387,8 +2320,8 @@ func (_BurnFromMintTokenPool *BurnFromMintTokenPoolFilterer) ParseReleased(log t return event, nil } -type BurnFromMintTokenPoolRemotePoolAddedIterator struct { - Event *BurnFromMintTokenPoolRemotePoolAdded +type BurnFromMintTokenPoolRemotePoolSetIterator struct { + Event *BurnFromMintTokenPoolRemotePoolSet contract *bind.BoundContract event string @@ -2399,7 +2332,7 @@ type BurnFromMintTokenPoolRemotePoolAddedIterator struct { fail error } -func (it *BurnFromMintTokenPoolRemotePoolAddedIterator) Next() bool { +func (it *BurnFromMintTokenPoolRemotePoolSetIterator) Next() bool { if it.fail != nil { return false @@ -2408,7 +2341,7 @@ func (it *BurnFromMintTokenPoolRemotePoolAddedIterator) Next() bool { if it.done { select { case log := <-it.logs: - it.Event = new(BurnFromMintTokenPoolRemotePoolAdded) + it.Event = new(BurnFromMintTokenPoolRemotePoolSet) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -2423,7 +2356,7 @@ func (it *BurnFromMintTokenPoolRemotePoolAddedIterator) Next() bool { select { case log := <-it.logs: - it.Event = new(BurnFromMintTokenPoolRemotePoolAdded) + it.Event = new(BurnFromMintTokenPoolRemotePoolSet) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -2438,43 +2371,44 @@ func (it *BurnFromMintTokenPoolRemotePoolAddedIterator) Next() bool { } } -func (it *BurnFromMintTokenPoolRemotePoolAddedIterator) Error() error { +func (it *BurnFromMintTokenPoolRemotePoolSetIterator) Error() error { return it.fail } -func (it *BurnFromMintTokenPoolRemotePoolAddedIterator) Close() error { +func (it *BurnFromMintTokenPoolRemotePoolSetIterator) Close() error { it.sub.Unsubscribe() return nil } -type BurnFromMintTokenPoolRemotePoolAdded struct { +type BurnFromMintTokenPoolRemotePoolSet struct { RemoteChainSelector uint64 + PreviousPoolAddress []byte RemotePoolAddress []byte Raw types.Log } -func (_BurnFromMintTokenPool *BurnFromMintTokenPoolFilterer) FilterRemotePoolAdded(opts *bind.FilterOpts, remoteChainSelector []uint64) (*BurnFromMintTokenPoolRemotePoolAddedIterator, error) { +func (_BurnFromMintTokenPool *BurnFromMintTokenPoolFilterer) FilterRemotePoolSet(opts *bind.FilterOpts, remoteChainSelector []uint64) (*BurnFromMintTokenPoolRemotePoolSetIterator, error) { var remoteChainSelectorRule []interface{} for _, remoteChainSelectorItem := range remoteChainSelector { remoteChainSelectorRule = append(remoteChainSelectorRule, remoteChainSelectorItem) } - logs, sub, err := _BurnFromMintTokenPool.contract.FilterLogs(opts, "RemotePoolAdded", remoteChainSelectorRule) + logs, sub, err := _BurnFromMintTokenPool.contract.FilterLogs(opts, "RemotePoolSet", remoteChainSelectorRule) if err != nil { return nil, err } - return &BurnFromMintTokenPoolRemotePoolAddedIterator{contract: _BurnFromMintTokenPool.contract, event: "RemotePoolAdded", logs: logs, sub: sub}, nil + return &BurnFromMintTokenPoolRemotePoolSetIterator{contract: _BurnFromMintTokenPool.contract, event: "RemotePoolSet", logs: logs, sub: sub}, nil } -func (_BurnFromMintTokenPool *BurnFromMintTokenPoolFilterer) WatchRemotePoolAdded(opts *bind.WatchOpts, sink chan<- *BurnFromMintTokenPoolRemotePoolAdded, remoteChainSelector []uint64) (event.Subscription, error) { +func (_BurnFromMintTokenPool *BurnFromMintTokenPoolFilterer) WatchRemotePoolSet(opts *bind.WatchOpts, sink chan<- *BurnFromMintTokenPoolRemotePoolSet, remoteChainSelector []uint64) (event.Subscription, error) { var remoteChainSelectorRule []interface{} for _, remoteChainSelectorItem := range remoteChainSelector { remoteChainSelectorRule = append(remoteChainSelectorRule, remoteChainSelectorItem) } - logs, sub, err := _BurnFromMintTokenPool.contract.WatchLogs(opts, "RemotePoolAdded", remoteChainSelectorRule) + logs, sub, err := _BurnFromMintTokenPool.contract.WatchLogs(opts, "RemotePoolSet", remoteChainSelectorRule) if err != nil { return nil, err } @@ -2484,8 +2418,8 @@ func (_BurnFromMintTokenPool *BurnFromMintTokenPoolFilterer) WatchRemotePoolAdde select { case log := <-logs: - event := new(BurnFromMintTokenPoolRemotePoolAdded) - if err := _BurnFromMintTokenPool.contract.UnpackLog(event, "RemotePoolAdded", log); err != nil { + event := new(BurnFromMintTokenPoolRemotePoolSet) + if err := _BurnFromMintTokenPool.contract.UnpackLog(event, "RemotePoolSet", log); err != nil { return err } event.Raw = log @@ -2506,137 +2440,9 @@ func (_BurnFromMintTokenPool *BurnFromMintTokenPoolFilterer) WatchRemotePoolAdde }), nil } -func (_BurnFromMintTokenPool *BurnFromMintTokenPoolFilterer) ParseRemotePoolAdded(log types.Log) (*BurnFromMintTokenPoolRemotePoolAdded, error) { - event := new(BurnFromMintTokenPoolRemotePoolAdded) - if err := _BurnFromMintTokenPool.contract.UnpackLog(event, "RemotePoolAdded", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -type BurnFromMintTokenPoolRemotePoolRemovedIterator struct { - Event *BurnFromMintTokenPoolRemotePoolRemoved - - contract *bind.BoundContract - event string - - logs chan types.Log - sub ethereum.Subscription - done bool - fail error -} - -func (it *BurnFromMintTokenPoolRemotePoolRemovedIterator) Next() bool { - - if it.fail != nil { - return false - } - - if it.done { - select { - case log := <-it.logs: - it.Event = new(BurnFromMintTokenPoolRemotePoolRemoved) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - default: - return false - } - } - - select { - case log := <-it.logs: - it.Event = new(BurnFromMintTokenPoolRemotePoolRemoved) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - case err := <-it.sub.Err(): - it.done = true - it.fail = err - return it.Next() - } -} - -func (it *BurnFromMintTokenPoolRemotePoolRemovedIterator) Error() error { - return it.fail -} - -func (it *BurnFromMintTokenPoolRemotePoolRemovedIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -type BurnFromMintTokenPoolRemotePoolRemoved struct { - RemoteChainSelector uint64 - RemotePoolAddress []byte - Raw types.Log -} - -func (_BurnFromMintTokenPool *BurnFromMintTokenPoolFilterer) FilterRemotePoolRemoved(opts *bind.FilterOpts, remoteChainSelector []uint64) (*BurnFromMintTokenPoolRemotePoolRemovedIterator, error) { - - var remoteChainSelectorRule []interface{} - for _, remoteChainSelectorItem := range remoteChainSelector { - remoteChainSelectorRule = append(remoteChainSelectorRule, remoteChainSelectorItem) - } - - logs, sub, err := _BurnFromMintTokenPool.contract.FilterLogs(opts, "RemotePoolRemoved", remoteChainSelectorRule) - if err != nil { - return nil, err - } - return &BurnFromMintTokenPoolRemotePoolRemovedIterator{contract: _BurnFromMintTokenPool.contract, event: "RemotePoolRemoved", logs: logs, sub: sub}, nil -} - -func (_BurnFromMintTokenPool *BurnFromMintTokenPoolFilterer) WatchRemotePoolRemoved(opts *bind.WatchOpts, sink chan<- *BurnFromMintTokenPoolRemotePoolRemoved, remoteChainSelector []uint64) (event.Subscription, error) { - - var remoteChainSelectorRule []interface{} - for _, remoteChainSelectorItem := range remoteChainSelector { - remoteChainSelectorRule = append(remoteChainSelectorRule, remoteChainSelectorItem) - } - - logs, sub, err := _BurnFromMintTokenPool.contract.WatchLogs(opts, "RemotePoolRemoved", remoteChainSelectorRule) - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - - event := new(BurnFromMintTokenPoolRemotePoolRemoved) - if err := _BurnFromMintTokenPool.contract.UnpackLog(event, "RemotePoolRemoved", log); err != nil { - return err - } - event.Raw = log - - select { - case sink <- event: - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - } - }), nil -} - -func (_BurnFromMintTokenPool *BurnFromMintTokenPoolFilterer) ParseRemotePoolRemoved(log types.Log) (*BurnFromMintTokenPoolRemotePoolRemoved, error) { - event := new(BurnFromMintTokenPoolRemotePoolRemoved) - if err := _BurnFromMintTokenPool.contract.UnpackLog(event, "RemotePoolRemoved", log); err != nil { +func (_BurnFromMintTokenPool *BurnFromMintTokenPoolFilterer) ParseRemotePoolSet(log types.Log) (*BurnFromMintTokenPoolRemotePoolSet, error) { + event := new(BurnFromMintTokenPoolRemotePoolSet) + if err := _BurnFromMintTokenPool.contract.UnpackLog(event, "RemotePoolSet", log); err != nil { return nil, err } event.Raw = log @@ -2906,10 +2712,8 @@ func (_BurnFromMintTokenPool *BurnFromMintTokenPool) ParseLog(log types.Log) (ge return _BurnFromMintTokenPool.ParseRateLimitAdminSet(log) case _BurnFromMintTokenPool.abi.Events["Released"].ID: return _BurnFromMintTokenPool.ParseReleased(log) - case _BurnFromMintTokenPool.abi.Events["RemotePoolAdded"].ID: - return _BurnFromMintTokenPool.ParseRemotePoolAdded(log) - case _BurnFromMintTokenPool.abi.Events["RemotePoolRemoved"].ID: - return _BurnFromMintTokenPool.ParseRemotePoolRemoved(log) + case _BurnFromMintTokenPool.abi.Events["RemotePoolSet"].ID: + return _BurnFromMintTokenPool.ParseRemotePoolSet(log) case _BurnFromMintTokenPool.abi.Events["RouterUpdated"].ID: return _BurnFromMintTokenPool.ParseRouterUpdated(log) case _BurnFromMintTokenPool.abi.Events["TokensConsumed"].ID: @@ -2972,12 +2776,8 @@ func (BurnFromMintTokenPoolReleased) Topic() common.Hash { return common.HexToHash("0x2d87480f50083e2b2759522a8fdda59802650a8055e609a7772cf70c07748f52") } -func (BurnFromMintTokenPoolRemotePoolAdded) Topic() common.Hash { - return common.HexToHash("0x7d628c9a1796743d365ab521a8b2a4686e419b3269919dc9145ea2ce853b54ea") -} - -func (BurnFromMintTokenPoolRemotePoolRemoved) Topic() common.Hash { - return common.HexToHash("0x52d00ee4d9bd51b40168f2afc5848837288ce258784ad914278791464b3f4d76") +func (BurnFromMintTokenPoolRemotePoolSet) Topic() common.Hash { + return common.HexToHash("0xdb4d6220746a38cbc5335f7e108f7de80f482f4d23350253dfd0917df75a14bf") } func (BurnFromMintTokenPoolRouterUpdated) Topic() common.Hash { @@ -3003,7 +2803,7 @@ type BurnFromMintTokenPoolInterface interface { GetRateLimitAdmin(opts *bind.CallOpts) (common.Address, error) - GetRemotePools(opts *bind.CallOpts, remoteChainSelector uint64) ([][]byte, error) + GetRemotePool(opts *bind.CallOpts, remoteChainSelector uint64) ([]byte, error) GetRemoteToken(opts *bind.CallOpts, remoteChainSelector uint64) ([]byte, error) @@ -3015,10 +2815,6 @@ type BurnFromMintTokenPoolInterface interface { GetToken(opts *bind.CallOpts) (common.Address, error) - GetTokenDecimals(opts *bind.CallOpts) (uint8, error) - - IsRemotePool(opts *bind.CallOpts, remoteChainSelector uint64, remotePoolAddress []byte) (bool, error) - IsSupportedChain(opts *bind.CallOpts, remoteChainSelector uint64) (bool, error) IsSupportedToken(opts *bind.CallOpts, token common.Address) (bool, error) @@ -3031,24 +2827,20 @@ type BurnFromMintTokenPoolInterface interface { AcceptOwnership(opts *bind.TransactOpts) (*types.Transaction, error) - AddRemotePool(opts *bind.TransactOpts, remoteChainSelector uint64, remotePoolAddress []byte) (*types.Transaction, error) - ApplyAllowListUpdates(opts *bind.TransactOpts, removes []common.Address, adds []common.Address) (*types.Transaction, error) - ApplyChainUpdates(opts *bind.TransactOpts, remoteChainSelectorsToRemove []uint64, chainsToAdd []TokenPoolChainUpdate) (*types.Transaction, error) + ApplyChainUpdates(opts *bind.TransactOpts, chains []TokenPoolChainUpdate) (*types.Transaction, error) LockOrBurn(opts *bind.TransactOpts, lockOrBurnIn PoolLockOrBurnInV1) (*types.Transaction, error) ReleaseOrMint(opts *bind.TransactOpts, releaseOrMintIn PoolReleaseOrMintInV1) (*types.Transaction, error) - RemoveRemotePool(opts *bind.TransactOpts, remoteChainSelector uint64, remotePoolAddress []byte) (*types.Transaction, error) - SetChainRateLimiterConfig(opts *bind.TransactOpts, remoteChainSelector uint64, outboundConfig RateLimiterConfig, inboundConfig RateLimiterConfig) (*types.Transaction, error) - SetChainRateLimiterConfigs(opts *bind.TransactOpts, remoteChainSelectors []uint64, outboundConfigs []RateLimiterConfig, inboundConfigs []RateLimiterConfig) (*types.Transaction, error) - SetRateLimitAdmin(opts *bind.TransactOpts, rateLimitAdmin common.Address) (*types.Transaction, error) + SetRemotePool(opts *bind.TransactOpts, remoteChainSelector uint64, remotePoolAddress []byte) (*types.Transaction, error) + SetRouter(opts *bind.TransactOpts, newRouter common.Address) (*types.Transaction, error) TransferOwnership(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) @@ -3131,17 +2923,11 @@ type BurnFromMintTokenPoolInterface interface { ParseReleased(log types.Log) (*BurnFromMintTokenPoolReleased, error) - FilterRemotePoolAdded(opts *bind.FilterOpts, remoteChainSelector []uint64) (*BurnFromMintTokenPoolRemotePoolAddedIterator, error) - - WatchRemotePoolAdded(opts *bind.WatchOpts, sink chan<- *BurnFromMintTokenPoolRemotePoolAdded, remoteChainSelector []uint64) (event.Subscription, error) - - ParseRemotePoolAdded(log types.Log) (*BurnFromMintTokenPoolRemotePoolAdded, error) - - FilterRemotePoolRemoved(opts *bind.FilterOpts, remoteChainSelector []uint64) (*BurnFromMintTokenPoolRemotePoolRemovedIterator, error) + FilterRemotePoolSet(opts *bind.FilterOpts, remoteChainSelector []uint64) (*BurnFromMintTokenPoolRemotePoolSetIterator, error) - WatchRemotePoolRemoved(opts *bind.WatchOpts, sink chan<- *BurnFromMintTokenPoolRemotePoolRemoved, remoteChainSelector []uint64) (event.Subscription, error) + WatchRemotePoolSet(opts *bind.WatchOpts, sink chan<- *BurnFromMintTokenPoolRemotePoolSet, remoteChainSelector []uint64) (event.Subscription, error) - ParseRemotePoolRemoved(log types.Log) (*BurnFromMintTokenPoolRemotePoolRemoved, error) + ParseRemotePoolSet(log types.Log) (*BurnFromMintTokenPoolRemotePoolSet, error) FilterRouterUpdated(opts *bind.FilterOpts) (*BurnFromMintTokenPoolRouterUpdatedIterator, error) diff --git a/core/gethwrappers/ccip/generated/burn_mint_token_pool/burn_mint_token_pool.go b/core/gethwrappers/ccip/generated/burn_mint_token_pool/burn_mint_token_pool.go index 8d78f234410..c43083c2585 100644 --- a/core/gethwrappers/ccip/generated/burn_mint_token_pool/burn_mint_token_pool.go +++ b/core/gethwrappers/ccip/generated/burn_mint_token_pool/burn_mint_token_pool.go @@ -74,22 +74,23 @@ type RateLimiterTokenBucket struct { type TokenPoolChainUpdate struct { RemoteChainSelector uint64 - RemotePoolAddresses [][]byte + Allowed bool + RemotePoolAddress []byte RemoteTokenAddress []byte OutboundRateLimiterConfig RateLimiterConfig InboundRateLimiterConfig RateLimiterConfig } var BurnMintTokenPoolMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[{\"internalType\":\"contractIBurnMintERC20\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"localTokenDecimals\",\"type\":\"uint8\"},{\"internalType\":\"address[]\",\"name\":\"allowlist\",\"type\":\"address[]\"},{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"capacity\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"requested\",\"type\":\"uint256\"}],\"name\":\"AggregateValueMaxCapacityExceeded\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"minWaitInSeconds\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"available\",\"type\":\"uint256\"}],\"name\":\"AggregateValueRateLimitReached\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"AllowListNotEnabled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"BucketOverfilled\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"CallerIsNotARampOnRouter\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CannotTransferToSelf\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"}],\"name\":\"ChainAlreadyExists\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"ChainNotAllowed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CursedByRMN\",\"type\":\"error\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"config\",\"type\":\"tuple\"}],\"name\":\"DisabledNonZeroRateLimit\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"expected\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"actual\",\"type\":\"uint8\"}],\"name\":\"InvalidDecimalArgs\",\"type\":\"error\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"rateLimiterConfig\",\"type\":\"tuple\"}],\"name\":\"InvalidRateLimitRate\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolData\",\"type\":\"bytes\"}],\"name\":\"InvalidRemoteChainDecimals\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"InvalidRemotePoolForChain\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"}],\"name\":\"InvalidSourcePoolAddress\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"InvalidToken\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MismatchedArrayLengths\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MustBeProposedOwner\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"NonExistentChain\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByOwner\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"remoteDecimals\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"localDecimals\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"remoteAmount\",\"type\":\"uint256\"}],\"name\":\"OverflowDetected\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OwnerCannotBeZero\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"PoolAlreadyAdded\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RateLimitMustBeDisabled\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"SenderNotAllowed\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"capacity\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"requested\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenAddress\",\"type\":\"address\"}],\"name\":\"TokenMaxCapacityExceeded\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"minWaitInSeconds\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"available\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenAddress\",\"type\":\"address\"}],\"name\":\"TokenRateLimitReached\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"Unauthorized\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"AllowListAdd\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"AllowListRemove\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Burned\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"remoteToken\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundRateLimiterConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundRateLimiterConfig\",\"type\":\"tuple\"}],\"name\":\"ChainAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundRateLimiterConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundRateLimiterConfig\",\"type\":\"tuple\"}],\"name\":\"ChainConfigured\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"ChainRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"config\",\"type\":\"tuple\"}],\"name\":\"ConfigChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Locked\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Minted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"rateLimitAdmin\",\"type\":\"address\"}],\"name\":\"RateLimitAdminSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Released\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"RemotePoolAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"RemotePoolRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"oldRouter\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newRouter\",\"type\":\"address\"}],\"name\":\"RouterUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokens\",\"type\":\"uint256\"}],\"name\":\"TokensConsumed\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"addRemotePool\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"removes\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"adds\",\"type\":\"address[]\"}],\"name\":\"applyAllowListUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64[]\",\"name\":\"remoteChainSelectorsToRemove\",\"type\":\"uint64[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes[]\",\"name\":\"remotePoolAddresses\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes\",\"name\":\"remoteTokenAddress\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundRateLimiterConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundRateLimiterConfig\",\"type\":\"tuple\"}],\"internalType\":\"structTokenPool.ChainUpdate[]\",\"name\":\"chainsToAdd\",\"type\":\"tuple[]\"}],\"name\":\"applyChainUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAllowList\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAllowListEnabled\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getCurrentInboundRateLimiterState\",\"outputs\":[{\"components\":[{\"internalType\":\"uint128\",\"name\":\"tokens\",\"type\":\"uint128\"},{\"internalType\":\"uint32\",\"name\":\"lastUpdated\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.TokenBucket\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getCurrentOutboundRateLimiterState\",\"outputs\":[{\"components\":[{\"internalType\":\"uint128\",\"name\":\"tokens\",\"type\":\"uint128\"},{\"internalType\":\"uint32\",\"name\":\"lastUpdated\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.TokenBucket\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRateLimitAdmin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getRemotePools\",\"outputs\":[{\"internalType\":\"bytes[]\",\"name\":\"\",\"type\":\"bytes[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getRemoteToken\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRmnProxy\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRouter\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getSupportedChains\",\"outputs\":[{\"internalType\":\"uint64[]\",\"name\":\"\",\"type\":\"uint64[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getToken\",\"outputs\":[{\"internalType\":\"contractIERC20\",\"name\":\"token\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getTokenDecimals\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"decimals\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"isRemotePool\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"isSupportedChain\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"isSupportedToken\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"originalSender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"localToken\",\"type\":\"address\"}],\"internalType\":\"structPool.LockOrBurnInV1\",\"name\":\"lockOrBurnIn\",\"type\":\"tuple\"}],\"name\":\"lockOrBurn\",\"outputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"destPoolData\",\"type\":\"bytes\"}],\"internalType\":\"structPool.LockOrBurnOutV1\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"originalSender\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"localToken\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"sourcePoolData\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"offchainTokenData\",\"type\":\"bytes\"}],\"internalType\":\"structPool.ReleaseOrMintInV1\",\"name\":\"releaseOrMintIn\",\"type\":\"tuple\"}],\"name\":\"releaseOrMint\",\"outputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"destinationAmount\",\"type\":\"uint256\"}],\"internalType\":\"structPool.ReleaseOrMintOutV1\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"removeRemotePool\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundConfig\",\"type\":\"tuple\"}],\"name\":\"setChainRateLimiterConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64[]\",\"name\":\"remoteChainSelectors\",\"type\":\"uint64[]\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config[]\",\"name\":\"outboundConfigs\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config[]\",\"name\":\"inboundConfigs\",\"type\":\"tuple[]\"}],\"name\":\"setChainRateLimiterConfigs\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"rateLimitAdmin\",\"type\":\"address\"}],\"name\":\"setRateLimitAdmin\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newRouter\",\"type\":\"address\"}],\"name\":\"setRouter\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", - Bin: "0x61010080604052346103635761491c803803809161001d82856103e2565b833981019060a0818303126103635780516001600160a01b038116908190036103635761004c60208301610405565b60408301519091906001600160401b0381116103635783019380601f86011215610363578451946001600160401b0386116103cc578560051b90602082019661009860405198896103e2565b875260208088019282010192831161036357602001905b8282106103b4575050506100d160806100ca60608601610413565b9401610413565b9233156103a357600180546001600160a01b0319163317905581158015610392575b8015610381575b610370578160209160049360805260c0526040519283809263313ce56760e01b82525afa6000918161032f575b50610304575b5060a052600480546001600160a01b0319166001600160a01b03929092169190911790558051151560e08190526101e6575b60405161435490816105c882396080518181816115fc015281816117e801528181612204015281816123e0015281816126f80152612770015260a05181818161189f0152818161267f0152818161315901526131dc015260c051818181610bd501528181611698015261229f015260e051818181610b65015281816116db0152611ffb0152f35b60405160206101f581836103e2565b60008252600036813760e051156102f35760005b8251811015610270576001906001600160a01b036102278286610427565b51168361023382610469565b610240575b505001610209565b7f800671136ab6cfee9fbe5ed1fb7ca417811aca3cf864800d127b927adedf756691604051908152a13883610238565b50905060005b82518110156102ea576001906001600160a01b036102948286610427565b511680156102e457836102a682610567565b6102b4575b50505b01610276565b7f2640d4d76caf8bf478aabfa982fa4e1c4eb71a37f93cd15e80dbc657911546d891604051908152a138836102ab565b506102ae565b5050503861015f565b6335f4a7b360e01b60005260046000fd5b60ff1660ff8216818103610318575061012d565b6332ad3e0760e11b60005260045260245260446000fd5b9091506020813d602011610368575b8161034b602093836103e2565b810103126103635761035c90610405565b9038610127565b600080fd5b3d915061033e565b6342bcdf7f60e11b60005260046000fd5b506001600160a01b038116156100fa565b506001600160a01b038416156100f3565b639b15e16f60e01b60005260046000fd5b602080916103c184610413565b8152019101906100af565b634e487b7160e01b600052604160045260246000fd5b601f909101601f19168101906001600160401b038211908210176103cc57604052565b519060ff8216820361036357565b51906001600160a01b038216820361036357565b805182101561043b5760209160051b010190565b634e487b7160e01b600052603260045260246000fd5b805482101561043b5760005260206000200190600090565b600081815260036020526040902054801561056057600019810181811161054a5760025460001981019190821161054a578181036104f9575b50505060025480156104e357600019016104bd816002610451565b8154906000199060031b1b19169055600255600052600360205260006040812055600190565b634e487b7160e01b600052603160045260246000fd5b61053261050a61051b936002610451565b90549060031b1c9283926002610451565b819391549060031b91821b91600019901b19161790565b905560005260036020526040600020553880806104a2565b634e487b7160e01b600052601160045260246000fd5b5050600090565b806000526003602052604060002054156000146105c157600254680100000000000000008110156103cc576105a861051b8260018594016002556002610451565b9055600254906000526003602052604060002055600190565b5060009056fe608080604052600436101561001357600080fd5b600090813560e01c90816301ffc9a71461281357508063181f5a771461279457806321df0da714612725578063240028e8146126a357806324f65ee714612647578063390775371461215e5780634c5ef0ed1461214457806354c8a4f314611fc757806362ddd3c414611f435780636d3d1a5814611ef157806379ba509714611e0c5780637d54534e14611d5f5780638926f54f14611cfb5780638da5cb5b14611ca9578063962d402014611b055780639a4575b914611554578063a42a7b8b146113cf578063a7cd63b714611303578063acfecf91146111df578063af58d59f14611178578063b0f479a114611126578063b7946580146110cf578063c0d7865514610fd7578063c4bffe2b14610e8e578063c75eea9c14610dc8578063cf7401f314610bf9578063dc0bd97114610b8a578063e0351e1314610b2f578063e8a1da171461025a5763f2fde38b1461016b57600080fd5b346102575760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102575773ffffffffffffffffffffffffffffffffffffffff6101b7612a41565b6101bf6132e6565b1633811461022f57807fffffffffffffffffffffffff000000000000000000000000000000000000000083541617825573ffffffffffffffffffffffffffffffffffffffff600154167fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12788380a380f35b6004827fdad89dca000000000000000000000000000000000000000000000000000000008152fd5b80fd5b50346102575761026936612b2f565b939190926102756132e6565b82915b80831061099a575050508063ffffffff4216917ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffee1843603015b85821015610996578160051b85013581811215610992578501906101208236031261099257604051956102e387612969565b823567ffffffffffffffff8116810361098d578752602083013567ffffffffffffffff81116109895783019536601f880112156109895786359661032688612d5b565b97610334604051998a6129a1565b8089526020808a019160051b830101903682116109855760208301905b828210610952575050505060208801968752604084013567ffffffffffffffff811161094e5761038490369086016130b3565b9860408901998a526103ae61039c3660608801612bed565b9560608b0196875260c0369101612bed565b9660808a019788526103c0865161375d565b6103ca885161375d565b8a515115610926576103e667ffffffffffffffff8b5116613fb0565b156108ef5767ffffffffffffffff8a5116815260076020526040812061052687516fffffffffffffffffffffffffffffffff604082015116906104e16fffffffffffffffffffffffffffffffff6020830151169151151583608060405161044c81612969565b858152602081018c905260408101849052606081018690520152855474ff000000000000000000000000000000000000000091151560a01b919091167fffffffffffffffffffffff0000000000000000000000000000000000000000009091166fffffffffffffffffffffffffffffffff84161773ffffffff0000000000000000000000000000000060808b901b1617178555565b60809190911b7fffffffffffffffffffffffffffffffff00000000000000000000000000000000166fffffffffffffffffffffffffffffffff91909116176001830155565b61064c89516fffffffffffffffffffffffffffffffff604082015116906106076fffffffffffffffffffffffffffffffff6020830151169151151583608060405161057081612969565b858152602081018c9052604081018490526060810186905201526002860180547fffffffffffffffffffffff000000000000000000000000000000000000000000166fffffffffffffffffffffffffffffffff85161773ffffffff0000000000000000000000000000000060808c901b161791151560a01b74ff000000000000000000000000000000000000000016919091179055565b60809190911b7fffffffffffffffffffffffffffffffff00000000000000000000000000000000166fffffffffffffffffffffffffffffffff91909116176003830155565b60048c5191019080519067ffffffffffffffff82116108c25761066f8354612e53565b601f8111610887575b50602090601f83116001146107e8576106c692918591836107dd575b50507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8260011b9260031b1c19161790565b90555b805b8951805182101561070157906106fb6001926106f4838f67ffffffffffffffff90511692612e3f565b5190613331565b016106cb565b5050975097987f8d340f17e19058004c20453540862a9c62778504476f6756755cb33bcd6c38c2929593966107cf67ffffffffffffffff600197949c511692519351915161079b610766604051968796875261010060208801526101008701906129e2565b9360408601906fffffffffffffffffffffffffffffffff60408092805115158552826020820151166020860152015116910152565b60a08401906fffffffffffffffffffffffffffffffff60408092805115158552826020820151166020860152015116910152565b0390a10190939492916102b1565b015190503880610694565b83855281852091907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08416865b81811061086f5750908460019594939210610838575b505050811b0190556106c9565b01517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88460031b161c1916905538808061082b565b92936020600181928786015181550195019301610815565b6108b29084865260208620601f850160051c810191602086106108b8575b601f0160051c019061305a565b38610678565b90915081906108a5565b6024847f4e487b710000000000000000000000000000000000000000000000000000000081526041600452fd5b60249067ffffffffffffffff8b51167f1d5ad3c5000000000000000000000000000000000000000000000000000000008252600452fd5b807f8579befe0000000000000000000000000000000000000000000000000000000060049252fd5b8680fd5b813567ffffffffffffffff81116109815760209161097683928336918901016130b3565b815201910190610351565b8a80fd5b8880fd5b8580fd5b600080fd5b8380fd5b8280f35b9092919367ffffffffffffffff6109ba6109b5878588612ddb565b612e1a565b16956109c587613ce4565b15610b035786845260076020526109e160056040862001613aeb565b94845b8651811015610a1a576001908987526007602052610a1360056040892001610a0c838b612e3f565b5190613e0f565b50016109e4565b5093945094909580855260076020526005604086208681558660018201558660028201558660038201558660048201610a538154612e53565b80610ac2575b5050500180549086815581610aa4575b5050907f5204aec90a3c794d8e90fded8b46ae9c7c552803e7e832e0c1d358396d8599166020600193604051908152a1019190949394610278565b865260208620908101905b81811015610a6957868155600101610aaf565b601f8111600114610ad85750555b863880610a59565b81835260208320610af391601f01861c81019060010161305a565b8082528160208120915555610ad0565b602484887f1e670e4b000000000000000000000000000000000000000000000000000000008252600452fd5b503461025757807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102575760206040517f000000000000000000000000000000000000000000000000000000000000000015158152f35b503461025757807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261025757602060405173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b50346102575760e07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261025757610c31612a64565b9060607fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdc36011261025757604051610c6881612985565b6024358015158103610dc45781526044356fffffffffffffffffffffffffffffffff81168103610dc45760208201526064356fffffffffffffffffffffffffffffffff81168103610dc457604082015260607fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7c360112610dc05760405190610cef82612985565b608435801515810361099257825260a4356fffffffffffffffffffffffffffffffff8116810361099257602083015260c4356fffffffffffffffffffffffffffffffff8116810361099257604083015273ffffffffffffffffffffffffffffffffffffffff6009541633141580610d9e575b610d7257610d6f929361359b565b80f35b6024837f8e4a23d600000000000000000000000000000000000000000000000000000000815233600452fd5b5073ffffffffffffffffffffffffffffffffffffffff60015416331415610d61565b5080fd5b8280fd5b50346102575760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261025757610e31610e2c6040610e8a9367ffffffffffffffff610e15612a64565b610e1d612fa7565b50168152600760205220612fd2565b6136d8565b6040519182918291909160806fffffffffffffffffffffffffffffffff8160a084019582815116855263ffffffff6020820151166020860152604081015115156040860152826060820151166060860152015116910152565b0390f35b503461025757807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261025757604051906005548083528260208101600584526020842092845b818110610fbe575050610eec925003836129a1565b8151610f10610efa82612d5b565b91610f0860405193846129a1565b808352612d5b565b917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0602083019301368437805b8451811015610f6f578067ffffffffffffffff610f5c60019388612e3f565b5116610f688286612e3f565b5201610f3d565b50925090604051928392602084019060208552518091526040840192915b818110610f9b575050500390f35b825167ffffffffffffffff16845285945060209384019390920191600101610f8d565b8454835260019485019487945060209093019201610ed7565b50346102575760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102575773ffffffffffffffffffffffffffffffffffffffff611024612a41565b61102c6132e6565b1680156110a75760407f02dc5c233404867c793b749c6d644beb2277536d18a7e7974d3f238e4c6f16849160045490807fffffffffffffffffffffffff000000000000000000000000000000000000000083161760045573ffffffffffffffffffffffffffffffffffffffff8351921682526020820152a180f35b6004827f8579befe000000000000000000000000000000000000000000000000000000008152fd5b50346102575760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261025757610e8a61111261110d612a64565b613038565b6040519182916020835260208301906129e2565b503461025757807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261025757602073ffffffffffffffffffffffffffffffffffffffff60045416604051908152f35b50346102575760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261025757610e31610e2c60026040610e8a9467ffffffffffffffff6111c7612a64565b6111cf612fa7565b5016815260076020522001612fd2565b50346102575767ffffffffffffffff6111f736612a7b565b9290916112026132e6565b169161121b836000526006602052604060002054151590565b156112d757828452600760205261124a6005604086200161123d368486612c8a565b6020815191012090613e0f565b1561128f57907f52d00ee4d9bd51b40168f2afc5848837288ce258784ad914278791464b3f4d7691611289604051928392602084526020840191612f68565b0390a280f35b826112d3836040519384937f74f23c7c0000000000000000000000000000000000000000000000000000000085526004850152604060248501526044840191612f68565b0390fd5b602484847f1e670e4b000000000000000000000000000000000000000000000000000000008252600452fd5b503461025757807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261025757604051600254808252602082018091600285526020852090855b8181106113b957505050826113629103836129a1565b604051928392602084019060208552518091526040840192915b81811061138a575050500390f35b825173ffffffffffffffffffffffffffffffffffffffff1684528594506020938401939092019160010161137c565b825484526020909301926001928301920161134c565b50346102575760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102575767ffffffffffffffff611410612a64565b168152600760205261142760056040832001613aeb565b80517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe061146c61145683612d5b565b9261146460405194856129a1565b808452612d5b565b01835b818110611543575050825b82518110156114c0578061149060019285612e3f565b51855260086020526114a460408620612ea6565b6114ae8285612e3f565b526114b98184612e3f565b500161147a565b81846040519182916020830160208452825180915260408401602060408360051b870101940192905b8282106114f857505050500390f35b91936020611533827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0600195979984950301865288516129e2565b96019201920185949391926114e9565b80606060208093860101520161146f565b50346102575760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102575760043567ffffffffffffffff8111610dc05760a07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc8236030112610dc057606060206040516115d28161294d565b8281520152608481016115e481612cef565b73ffffffffffffffffffffffffffffffffffffffff807f000000000000000000000000000000000000000000000000000000000000000016911603611abb5750602481019177ffffffffffffffff0000000000000000000000000000000061164b84612e1a565b60801b16604051907f2cbc26bb000000000000000000000000000000000000000000000000000000008252600482015260208160248173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000165afa90811561194b578291611a8c575b50611a64576116d960448301612cef565b7f0000000000000000000000000000000000000000000000000000000000000000611a11575b5067ffffffffffffffff61171284612e1a565b1661172a816000526006602052604060002054151590565b156119e557602073ffffffffffffffffffffffffffffffffffffffff60045416916024604051809481937fa8d87a3b00000000000000000000000000000000000000000000000000000000835260048301525afa801561194b578290611982575b73ffffffffffffffffffffffffffffffffffffffff91501633036119565767ffffffffffffffff60646117bd85612e1a565b930135921681526007602052816118106040832073ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001692839161405f565b803b15610dc0578180916024604051809481937f42966c680000000000000000000000000000000000000000000000000000000083528860048401525af1801561194b57611936575b61190561189561110d86866040519081527f696de425f79f4a40bc6d2122ca50507f0efbeabbff86a84871b7196ab8ea8df760203392a2612e1a565b610e8a60405160ff7f0000000000000000000000000000000000000000000000000000000000000000166020820152602081526118d36040826129a1565b604051926118e08461294d565b83526020830190815260405193849360208552516040602086015260608501906129e2565b90517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08483030160408501526129e2565b6119418280926129a1565b6102575780611859565b6040513d84823e3d90fd5b807f728fe07b000000000000000000000000000000000000000000000000000000006024925233600452fd5b506020813d6020116119dd575b8161199c602093836129a1565b81010312610dc0575173ffffffffffffffffffffffffffffffffffffffff81168103610dc05773ffffffffffffffffffffffffffffffffffffffff9061178b565b3d915061198f565b602492507fa9902c7e000000000000000000000000000000000000000000000000000000008252600452fd5b73ffffffffffffffffffffffffffffffffffffffff16808252600360205260408220546116ff57602492507fd0d25976000000000000000000000000000000000000000000000000000000008252600452fd5b807f53ad11d80000000000000000000000000000000000000000000000000000000060049252fd5b611aae915060203d602011611ab4575b611aa681836129a1565b8101906130ce565b386116c8565b503d611a9c565b8273ffffffffffffffffffffffffffffffffffffffff611adc602493612cef565b7f961c9a4f00000000000000000000000000000000000000000000000000000000835216600452fd5b50346102575760607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102575760043567ffffffffffffffff8111610dc057611b55903690600401612afe565b60243567ffffffffffffffff811161099257611b75903690600401612b9f565b60449291923567ffffffffffffffff811161098957611b98903690600401612b9f565b91909273ffffffffffffffffffffffffffffffffffffffff6009541633141580611c87575b611c5b57818114801590611c51575b611c2957865b818110611bdd578780f35b80611c23611bf16109b5600194868c612ddb565b611bfc83878b612e2f565b611c1d611c15611c0d868b8d612e2f565b923690612bed565b913690612bed565b9161359b565b01611bd2565b6004877f568efce2000000000000000000000000000000000000000000000000000000008152fd5b5082811415611bcc565b6024877f8e4a23d600000000000000000000000000000000000000000000000000000000815233600452fd5b5073ffffffffffffffffffffffffffffffffffffffff60015416331415611bbd565b503461025757807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261025757602073ffffffffffffffffffffffffffffffffffffffff60015416604051908152f35b50346102575760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610257576020611d5567ffffffffffffffff611d41612a64565b166000526006602052604060002054151590565b6040519015158152f35b50346102575760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610257577f44676b5284b809a22248eba0da87391d79098be38bb03154be88a58bf4d09174602073ffffffffffffffffffffffffffffffffffffffff611dcf612a41565b611dd76132e6565b16807fffffffffffffffffffffffff00000000000000000000000000000000000000006009541617600955604051908152a180f35b503461025757807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261025757805473ffffffffffffffffffffffffffffffffffffffff81163303611ec9577fffffffffffffffffffffffff000000000000000000000000000000000000000060015491338284161760015516825573ffffffffffffffffffffffffffffffffffffffff3391167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08380a380f35b6004827f02b543c6000000000000000000000000000000000000000000000000000000008152fd5b503461025757807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261025757602073ffffffffffffffffffffffffffffffffffffffff60095416604051908152f35b503461025757611f5236612a7b565b611f5e939291936132e6565b67ffffffffffffffff8216611f80816000526006602052604060002054151590565b15611f9c5750610d6f9293611f96913691612c8a565b90613331565b7f1e670e4b000000000000000000000000000000000000000000000000000000008452600452602483fd5b503461025757611ff190611ff9611fdd36612b2f565b9591611fea9391936132e6565b3691612d73565b933691612d73565b7f00000000000000000000000000000000000000000000000000000000000000001561211c57815b8351811015612094578073ffffffffffffffffffffffffffffffffffffffff61204c60019387612e3f565b511661205781613b4e565b612063575b5001612021565b60207f800671136ab6cfee9fbe5ed1fb7ca417811aca3cf864800d127b927adedf756691604051908152a13861205c565b5090805b8251811015612118578073ffffffffffffffffffffffffffffffffffffffff6120c360019386612e3f565b51168015612112576120d481613f50565b6120e1575b505b01612098565b60207f2640d4d76caf8bf478aabfa982fa4e1c4eb71a37f93cd15e80dbc657911546d891604051908152a1846120d9565b506120db565b5080f35b6004827f35f4a7b3000000000000000000000000000000000000000000000000000000008152fd5b5034610257576020611d5561215836612a7b565b91612d10565b50346102575760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102575760043567ffffffffffffffff8111610dc057806004016101007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc8336030112610dc457826040516121de81612902565b52608482016121ec81612cef565b73ffffffffffffffffffffffffffffffffffffffff807f00000000000000000000000000000000000000000000000000000000000000001691160361262657506024820177ffffffffffffffff0000000000000000000000000000000061225282612e1a565b60801b16604051907f2cbc26bb000000000000000000000000000000000000000000000000000000008252600482015260208160248173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000165afa9081156125a9578591612607575b506125df5767ffffffffffffffff6122e682612e1a565b166122fe816000526006602052604060002054151590565b156125b457602073ffffffffffffffffffffffffffffffffffffffff60045416916044604051809481937f83826b2b00000000000000000000000000000000000000000000000000000000835260048301523360248301525afa9081156125a957859161258a575b501561255e5761237581612e1a565b61238760a48501916121588386612c39565b15612517575061242467ffffffffffffffff9261241e6124196124126123ae604496612e1a565b936064890135978895168a526007602052612408600260408c200173ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016998a9161405f565b60c4890190612c39565b3691612c8a565b6130e6565b906131d9565b9201908361243183612cef565b823b15610dc057604473ffffffffffffffffffffffffffffffffffffffff918360405195869485937f40c10f190000000000000000000000000000000000000000000000000000000085521660048401528860248401525af1801561250c57916020946124ba9273ffffffffffffffffffffffffffffffffffffffff946124fc575b5050612cef565b166040518281527f9d228d69b5fdb8d273a2336f8fb8612d039631024ea9bf09c424a9503aa078f0843392a3806040516124f381612902565b52604051908152f35b81612506916129a1565b386124b3565b6040513d86823e3d90fd5b6125219083612c39565b6112d36040519283927f24eb47e5000000000000000000000000000000000000000000000000000000008452602060048501526024840191612f68565b6024847f728fe07b00000000000000000000000000000000000000000000000000000000815233600452fd5b6125a3915060203d602011611ab457611aa681836129a1565b38612366565b6040513d87823e3d90fd5b7fa9902c7e000000000000000000000000000000000000000000000000000000008552600452602484fd5b6004847f53ad11d8000000000000000000000000000000000000000000000000000000008152fd5b612620915060203d602011611ab457611aa681836129a1565b386122cf565b8373ffffffffffffffffffffffffffffffffffffffff611adc602493612cef565b503461025757807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261025757602060405160ff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b50346102575760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610257576020906126de612a41565b905073ffffffffffffffffffffffffffffffffffffffff807f0000000000000000000000000000000000000000000000000000000000000000169116146040519015158152f35b503461025757807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261025757602060405173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b503461025757807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102575750610e8a6040516127d56040826129a1565b601781527f4275726e4d696e74546f6b656e506f6f6c20312e352e3100000000000000000060208201526040519182916020835260208301906129e2565b905034610dc05760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610dc0576004357fffffffff000000000000000000000000000000000000000000000000000000008116809103610dc457602092507faff2afbf0000000000000000000000000000000000000000000000000000000081149081156128d8575b81156128ae575b5015158152f35b7f01ffc9a700000000000000000000000000000000000000000000000000000000915014386128a7565b7f0e64dd2900000000000000000000000000000000000000000000000000000000811491506128a0565b6020810190811067ffffffffffffffff82111761291e57604052565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040810190811067ffffffffffffffff82111761291e57604052565b60a0810190811067ffffffffffffffff82111761291e57604052565b6060810190811067ffffffffffffffff82111761291e57604052565b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff82111761291e57604052565b919082519283825260005b848110612a2c5750507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8460006020809697860101520116010190565b806020809284010151828286010152016129ed565b6004359073ffffffffffffffffffffffffffffffffffffffff8216820361098d57565b6004359067ffffffffffffffff8216820361098d57565b60407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc82011261098d5760043567ffffffffffffffff8116810361098d579160243567ffffffffffffffff811161098d578260238201121561098d5780600401359267ffffffffffffffff841161098d576024848301011161098d576024019190565b9181601f8401121561098d5782359167ffffffffffffffff831161098d576020808501948460051b01011161098d57565b60407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc82011261098d5760043567ffffffffffffffff811161098d5781612b7891600401612afe565b929092916024359067ffffffffffffffff821161098d57612b9b91600401612afe565b9091565b9181601f8401121561098d5782359167ffffffffffffffff831161098d576020808501946060850201011161098d57565b35906fffffffffffffffffffffffffffffffff8216820361098d57565b919082606091031261098d57604051612c0581612985565b8092803590811515820361098d576040612c349181938552612c2960208201612bd0565b602086015201612bd0565b910152565b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18136030182121561098d570180359067ffffffffffffffff821161098d5760200191813603831361098d57565b92919267ffffffffffffffff821161291e5760405191612cd2601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016602001846129a1565b82948184528183011161098d578281602093846000960137010152565b3573ffffffffffffffffffffffffffffffffffffffff8116810361098d5790565b612d58929167ffffffffffffffff612d3b921660005260076020526005604060002001923691612c8a565b602081519101209060019160005201602052604060002054151590565b90565b67ffffffffffffffff811161291e5760051b60200190565b9291612d7e82612d5b565b93612d8c60405195866129a1565b602085848152019260051b810191821161098d57915b818310612dae57505050565b823573ffffffffffffffffffffffffffffffffffffffff8116810361098d57815260209283019201612da2565b9190811015612deb5760051b0190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b3567ffffffffffffffff8116810361098d5790565b9190811015612deb576060020190565b8051821015612deb5760209160051b010190565b90600182811c92168015612e9c575b6020831014612e6d57565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b91607f1691612e62565b9060405191826000825492612eba84612e53565b8084529360018116908115612f285750600114612ee1575b50612edf925003836129a1565b565b90506000929192526020600020906000915b818310612f0c575050906020612edf9282010138612ed2565b6020919350806001915483858901015201910190918492612ef3565b60209350612edf9592507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0091501682840152151560051b82010138612ed2565b601f82602094937fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0938186528686013760008582860101520116010190565b60405190612fb482612969565b60006080838281528260208201528260408201528260608201520152565b90604051612fdf81612969565b60806001829460ff81546fffffffffffffffffffffffffffffffff8116865263ffffffff81861c16602087015260a01c161515604085015201546fffffffffffffffffffffffffffffffff81166060840152811c910152565b67ffffffffffffffff166000526007602052612d586004604060002001612ea6565b818110613065575050565b6000815560010161305a565b8181029291811591840414171561308457565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b9080601f8301121561098d57816020612d5893359101612c8a565b9081602091031261098d5751801515810361098d5790565b80518015613155576020036131175760208180518101031261098d5760208101519060ff8211613117575060ff1690565b6112d3906040519182917f953576f70000000000000000000000000000000000000000000000000000000083526020600484015260248301906129e2565b50507f000000000000000000000000000000000000000000000000000000000000000090565b9060ff8091169116039060ff821161308457565b60ff16604d811161308457600a0a90565b81156131aa570490565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b907f00000000000000000000000000000000000000000000000000000000000000009060ff82169060ff8116928284146132df578284116132b5579061321e9161317b565b91604d60ff841611801561327c575b61324657505090613240612d589261318f565b90613071565b9091507fa9cb113d0000000000000000000000000000000000000000000000000000000060005260045260245260445260646000fd5b506132868361318f565b80156131aa577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04841161322d565b6132be9161317b565b91604d60ff841611613246575050906132d9612d589261318f565b906131a0565b5050505090565b73ffffffffffffffffffffffffffffffffffffffff60015416330361330757565b7f2b5c74de0000000000000000000000000000000000000000000000000000000060005260046000fd5b908051156135715767ffffffffffffffff8151602083012092169182600052600760205261336681600560406000200161400a565b1561352d5760005260086020526040600020815167ffffffffffffffff811161291e576133938254612e53565b601f81116134fb575b506020601f8211600114613435579161340f827f7d628c9a1796743d365ab521a8b2a4686e419b3269919dc9145ea2ce853b54ea95936134259560009161342a575b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8260011b9260031b1c19161790565b90556040519182916020835260208301906129e2565b0390a2565b9050840151386133de565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe082169083600052806000209160005b8181106134e35750926134259492600192827f7d628c9a1796743d365ab521a8b2a4686e419b3269919dc9145ea2ce853b54ea9896106134ac575b5050811b019055611112565b8501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88460031b161c1916905538806134a0565b9192602060018192868a015181550194019201613465565b61352790836000526020600020601f840160051c810191602085106108b857601f0160051c019061305a565b3861339c565b50906112d36040519283927f393b8ad200000000000000000000000000000000000000000000000000000000845260048401526040602484015260448301906129e2565b7f8579befe0000000000000000000000000000000000000000000000000000000060005260046000fd5b67ffffffffffffffff16600081815260066020526040902054909291901561369d579161369a60e092613666856135f27f0350d63aa5f270e01729d00d627eeb8f3429772b1818c016c66a588a864f912b9761375d565b8460005260076020526136098160406000206138b8565b6136128361375d565b84600052600760205261362c8360026040600020016138b8565b60405194855260208501906fffffffffffffffffffffffffffffffff60408092805115158552826020820151166020860152015116910152565b60808301906fffffffffffffffffffffffffffffffff60408092805115158552826020820151166020860152015116910152565ba1565b827f1e670e4b0000000000000000000000000000000000000000000000000000000060005260045260246000fd5b9190820391821161308457565b6136e0612fa7565b506fffffffffffffffffffffffffffffffff6060820151166fffffffffffffffffffffffffffffffff808351169161373d602085019361373761372a63ffffffff875116426136cb565b8560808901511690613071565b90613f43565b8082101561375657505b16825263ffffffff4216905290565b9050613747565b805115613811576fffffffffffffffffffffffffffffffff6040820151166fffffffffffffffffffffffffffffffff602083015116811090811591613808575b506137a55750565b606490613806604051917f8020d12400000000000000000000000000000000000000000000000000000000835260048301906fffffffffffffffffffffffffffffffff60408092805115158552826020820151166020860152015116910152565bfd5b9050153861379d565b6fffffffffffffffffffffffffffffffff60408201511615801590613899575b6138385750565b606490613806604051917fd68af9cc00000000000000000000000000000000000000000000000000000000835260048301906fffffffffffffffffffffffffffffffff60408092805115158552826020820151166020860152015116910152565b506fffffffffffffffffffffffffffffffff6020820151161515613831565b7f9ea3374b67bf275e6bb9c8ae68f9cae023e1c528b4b27e092f0bb209d3531c19916139f160609280546138f563ffffffff8260801c16426136cb565b9081613a30575b50506fffffffffffffffffffffffffffffffff6001816020860151169282815416808510600014613a2857508280855b16167fffffffffffffffffffffffffffffffff000000000000000000000000000000008254161781556139a58651151582907fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff74ff0000000000000000000000000000000000000000835492151560a01b169116179055565b60408601517fffffffffffffffffffffffffffffffff0000000000000000000000000000000060809190911b16939092166fffffffffffffffffffffffffffffffff1692909217910155565b61369a60405180926fffffffffffffffffffffffffffffffff60408092805115158552826020820151166020860152015116910152565b83809161392c565b6fffffffffffffffffffffffffffffffff91613a65839283613a5e6001880154948286169560801c90613071565b9116613f43565b80821015613ae457505b83547fffffffffffffffffffffffff00000000ffffffffffffffffffffffffffffffff9290911692909216167fffffffffffffffffffffffff0000000000000000000000000000000000000000909116174260801b73ffffffff000000000000000000000000000000001617815538806138fc565b9050613a6f565b906040519182815491828252602082019060005260206000209260005b818110613b1d575050612edf925003836129a1565b8454835260019485019487945060209093019201613b08565b8054821015612deb5760005260206000200190600090565b6000818152600360205260409020548015613cdd577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff810181811161308457600254907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820191821161308457818103613c6e575b5050506002548015613c3f577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01613bfc816002613b36565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82549160031b1b19169055600255600052600360205260006040812055600190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b613cc5613c7f613c90936002613b36565b90549060031b1c9283926002613b36565b81939154907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9060031b92831b921b19161790565b90556000526003602052604060002055388080613bc3565b5050600090565b6000818152600660205260409020548015613cdd577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff810181811161308457600554907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820191821161308457818103613dd5575b5050506005548015613c3f577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01613d92816005613b36565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82549160031b1b19169055600555600052600660205260006040812055600190565b613df7613de6613c90936005613b36565b90549060031b1c9283926005613b36565b90556000526006602052604060002055388080613d59565b9060018201918160005282602052604060002054801515600014613f3a577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8101818111613084578254907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820191821161308457818103613f03575b50505080548015613c3f577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190613ec48282613b36565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82549160031b1b191690555560005260205260006040812055600190565b613f23613f13613c909386613b36565b90549060031b1c92839286613b36565b905560005283602052604060002055388080613e8c565b50505050600090565b9190820180921161308457565b80600052600360205260406000205415600014613faa576002546801000000000000000081101561291e57613f91613c908260018594016002556002613b36565b9055600254906000526003602052604060002055600190565b50600090565b80600052600660205260406000205415600014613faa576005546801000000000000000081101561291e57613ff1613c908260018594016005556005613b36565b9055600554906000526006602052604060002055600190565b6000828152600182016020526040902054613cdd578054906801000000000000000082101561291e5782614048613c90846001809601855584613b36565b905580549260005201602052604060002055600190565b929192805460ff8160a01c1615801561433f575b614338576fffffffffffffffffffffffffffffffff811690600183019081546140b863ffffffff6fffffffffffffffffffffffffffffffff83169360801c16426136cb565b908161429a575b5050848110614218575083821061414757507f1871cdf8010e63f2eb8384381a68dfa7416dc571a5517e66e88b2d2d0c0a690a939450906fffffffffffffffffffffffffffffffff8061411585602096956136cb565b16167fffffffffffffffffffffffffffffffff00000000000000000000000000000000825416179055604051908152a1565b81945061415992505460801c926136cb565b907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff810190808211613084576141a76141ac9273ffffffffffffffffffffffffffffffffffffffff94613f43565b6131a0565b92169182156141e8577fd0c8d23a0000000000000000000000000000000000000000000000000000000060005260045260245260445260646000fd5b7f15279c080000000000000000000000000000000000000000000000000000000060005260045260245260446000fd5b8473ffffffffffffffffffffffffffffffffffffffff881691821561426a577f1a76572a0000000000000000000000000000000000000000000000000000000060005260045260245260445260646000fd5b7ff94ebcd10000000000000000000000000000000000000000000000000000000060005260045260245260446000fd5b82859293951161430e576142b5926137379160801c90613071565b808310156143095750815b83547fffffffffffffffffffffffff00000000ffffffffffffffffffffffffffffffff164260801b73ffffffff00000000000000000000000000000000161784559138806140bf565b6142c0565b7f9725942a0000000000000000000000000000000000000000000000000000000060005260046000fd5b5050509050565b50821561407356fea164736f6c634300081a000a", + ABI: "[{\"inputs\":[{\"internalType\":\"contractIBurnMintERC20\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"address[]\",\"name\":\"allowlist\",\"type\":\"address[]\"},{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"capacity\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"requested\",\"type\":\"uint256\"}],\"name\":\"AggregateValueMaxCapacityExceeded\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"minWaitInSeconds\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"available\",\"type\":\"uint256\"}],\"name\":\"AggregateValueRateLimitReached\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"AllowListNotEnabled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"BucketOverfilled\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"CallerIsNotARampOnRouter\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CannotTransferToSelf\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"}],\"name\":\"ChainAlreadyExists\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"ChainNotAllowed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CursedByRMN\",\"type\":\"error\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"config\",\"type\":\"tuple\"}],\"name\":\"DisabledNonZeroRateLimit\",\"type\":\"error\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"rateLimiterConfig\",\"type\":\"tuple\"}],\"name\":\"InvalidRateLimitRate\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"}],\"name\":\"InvalidSourcePoolAddress\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"InvalidToken\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MustBeProposedOwner\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"NonExistentChain\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByOwner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OwnerCannotBeZero\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RateLimitMustBeDisabled\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"SenderNotAllowed\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"capacity\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"requested\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenAddress\",\"type\":\"address\"}],\"name\":\"TokenMaxCapacityExceeded\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"minWaitInSeconds\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"available\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenAddress\",\"type\":\"address\"}],\"name\":\"TokenRateLimitReached\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"Unauthorized\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"AllowListAdd\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"AllowListRemove\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Burned\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"remoteToken\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundRateLimiterConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundRateLimiterConfig\",\"type\":\"tuple\"}],\"name\":\"ChainAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundRateLimiterConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundRateLimiterConfig\",\"type\":\"tuple\"}],\"name\":\"ChainConfigured\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"ChainRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"config\",\"type\":\"tuple\"}],\"name\":\"ConfigChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Locked\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Minted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"rateLimitAdmin\",\"type\":\"address\"}],\"name\":\"RateLimitAdminSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Released\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"previousPoolAddress\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"RemotePoolSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"oldRouter\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newRouter\",\"type\":\"address\"}],\"name\":\"RouterUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokens\",\"type\":\"uint256\"}],\"name\":\"TokensConsumed\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"removes\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"adds\",\"type\":\"address[]\"}],\"name\":\"applyAllowListUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"allowed\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"remoteTokenAddress\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundRateLimiterConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundRateLimiterConfig\",\"type\":\"tuple\"}],\"internalType\":\"structTokenPool.ChainUpdate[]\",\"name\":\"chains\",\"type\":\"tuple[]\"}],\"name\":\"applyChainUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAllowList\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAllowListEnabled\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getCurrentInboundRateLimiterState\",\"outputs\":[{\"components\":[{\"internalType\":\"uint128\",\"name\":\"tokens\",\"type\":\"uint128\"},{\"internalType\":\"uint32\",\"name\":\"lastUpdated\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.TokenBucket\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getCurrentOutboundRateLimiterState\",\"outputs\":[{\"components\":[{\"internalType\":\"uint128\",\"name\":\"tokens\",\"type\":\"uint128\"},{\"internalType\":\"uint32\",\"name\":\"lastUpdated\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.TokenBucket\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRateLimitAdmin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getRemotePool\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getRemoteToken\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRmnProxy\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRouter\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getSupportedChains\",\"outputs\":[{\"internalType\":\"uint64[]\",\"name\":\"\",\"type\":\"uint64[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getToken\",\"outputs\":[{\"internalType\":\"contractIERC20\",\"name\":\"token\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"isSupportedChain\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"isSupportedToken\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"originalSender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"localToken\",\"type\":\"address\"}],\"internalType\":\"structPool.LockOrBurnInV1\",\"name\":\"lockOrBurnIn\",\"type\":\"tuple\"}],\"name\":\"lockOrBurn\",\"outputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"destPoolData\",\"type\":\"bytes\"}],\"internalType\":\"structPool.LockOrBurnOutV1\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"originalSender\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"localToken\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"sourcePoolData\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"offchainTokenData\",\"type\":\"bytes\"}],\"internalType\":\"structPool.ReleaseOrMintInV1\",\"name\":\"releaseOrMintIn\",\"type\":\"tuple\"}],\"name\":\"releaseOrMint\",\"outputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"destinationAmount\",\"type\":\"uint256\"}],\"internalType\":\"structPool.ReleaseOrMintOutV1\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundConfig\",\"type\":\"tuple\"}],\"name\":\"setChainRateLimiterConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"rateLimitAdmin\",\"type\":\"address\"}],\"name\":\"setRateLimitAdmin\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"setRemotePool\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newRouter\",\"type\":\"address\"}],\"name\":\"setRouter\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", + Bin: "0x60e06040523480156200001157600080fd5b5060405162003fee38038062003fee8339810160408190526200003491620004e5565b83838383336000816200005a57604051639b15e16f60e01b815260040160405180910390fd5b600180546001600160a01b0319166001600160a01b03848116919091179091558116156200008d576200008d8162000140565b50506001600160a01b0384161580620000ad57506001600160a01b038116155b80620000c057506001600160a01b038216155b15620000df576040516342bcdf7f60e11b815260040160405180910390fd5b6001600160a01b0384811660805282811660a052600480546001600160a01b031916918316919091179055825115801560c0526200013257604080516000815260208101909152620001329084620001ba565b505050505050505062000643565b336001600160a01b038216036200016a57604051636d6c4ee560e11b815260040160405180910390fd5b600080546001600160a01b0319166001600160a01b03838116918217835560015460405192939116917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b60c051620001db576040516335f4a7b360e01b815260040160405180910390fd5b60005b825181101562000266576000838281518110620001ff57620001ff620005f5565b602090810291909101015190506200021960028262000317565b156200025c576040516001600160a01b03821681527f800671136ab6cfee9fbe5ed1fb7ca417811aca3cf864800d127b927adedf75669060200160405180910390a15b50600101620001de565b5060005b8151811015620003125760008282815181106200028b576200028b620005f5565b6020026020010151905060006001600160a01b0316816001600160a01b031603620002b7575062000309565b620002c460028262000337565b1562000307576040516001600160a01b03821681527f2640d4d76caf8bf478aabfa982fa4e1c4eb71a37f93cd15e80dbc657911546d89060200160405180910390a15b505b6001016200026a565b505050565b60006200032e836001600160a01b0384166200034e565b90505b92915050565b60006200032e836001600160a01b03841662000452565b6000818152600183016020526040812054801562000447576000620003756001836200060b565b85549091506000906200038b906001906200060b565b9050808214620003f7576000866000018281548110620003af57620003af620005f5565b9060005260206000200154905080876000018481548110620003d557620003d5620005f5565b6000918252602080832090910192909255918252600188019052604090208390555b85548690806200040b576200040b6200062d565b60019003818190600052602060002001600090559055856001016000868152602001908152602001600020600090556001935050505062000331565b600091505062000331565b60008181526001830160205260408120546200049b5750815460018181018455600084815260208082209093018490558454848252828601909352604090209190915562000331565b50600062000331565b6001600160a01b0381168114620004ba57600080fd5b50565b634e487b7160e01b600052604160045260246000fd5b8051620004e081620004a4565b919050565b60008060008060808587031215620004fc57600080fd5b84516200050981620004a4565b602086810151919550906001600160401b03808211156200052957600080fd5b818801915088601f8301126200053e57600080fd5b815181811115620005535762000553620004bd565b8060051b604051601f19603f830116810181811085821117156200057b576200057b620004bd565b60405291825284820192508381018501918b8311156200059a57600080fd5b938501935b82851015620005c357620005b385620004d3565b845293850193928501926200059f565b809850505050505050620005da60408601620004d3565b9150620005ea60608601620004d3565b905092959194509250565b634e487b7160e01b600052603260045260246000fd5b818103818111156200033157634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052603160045260246000fd5b60805160a05160c05161392e620006c0600039600081816104dd0152818161174a01526120f70152600081816104b7015281816115ab0152611a000152600081816102390152818161028e015281816106e0015281816114cb0152818161192001528181611b120152818161208d01526122e2015261392e6000f3fe608060405234801561001057600080fd5b50600436106101ae5760003560e01c80639a4575b9116100ee578063c4bffe2b11610097578063db6327dc11610071578063db6327dc146104a2578063dc0bd971146104b5578063e0351e13146104db578063f2fde38b1461050157600080fd5b8063c4bffe2b14610467578063c75eea9c1461047c578063cf7401f31461048f57600080fd5b8063b0f479a1116100c8578063b0f479a114610423578063b794658014610441578063c0d786551461045457600080fd5b80639a4575b91461037f578063a7cd63b71461039f578063af58d59f146103b457600080fd5b806354c8a4f31161015b57806379ba50971161013557806379ba5097146103335780637d54534e1461033b5780638926f54f1461034e5780638da5cb5b1461036157600080fd5b806354c8a4f3146102ed5780636d3d1a581461030257806378a010b21461032057600080fd5b806321df0da71161018c57806321df0da714610237578063240028e81461027e57806339077537146102cb57600080fd5b806301ffc9a7146101b35780630a2fd493146101db578063181f5a77146101fb575b600080fd5b6101c66101c1366004612a85565b610514565b60405190151581526020015b60405180910390f35b6101ee6101e9366004612ae4565b6105f9565b6040516101d29190612b63565b6101ee6040518060400160405280601781526020017f4275726e4d696e74546f6b656e506f6f6c20312e352e3000000000000000000081525081565b7f00000000000000000000000000000000000000000000000000000000000000005b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101d2565b6101c661028c366004612ba3565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff90811691161490565b6102de6102d9366004612bc0565b6106a9565b604051905181526020016101d2565b6103006102fb366004612c48565b61082f565b005b60085473ffffffffffffffffffffffffffffffffffffffff16610259565b61030061032e366004612cb4565b6108aa565b610300610a1e565b610300610349366004612ba3565b610aec565b6101c661035c366004612ae4565b610b6d565b60015473ffffffffffffffffffffffffffffffffffffffff16610259565b61039261038d366004612d37565b610b84565b6040516101d29190612d72565b6103a7610c2b565b6040516101d29190612dd2565b6103c76103c2366004612ae4565b610c3c565b6040516101d2919081516fffffffffffffffffffffffffffffffff908116825260208084015163ffffffff1690830152604080840151151590830152606080840151821690830152608092830151169181019190915260a00190565b60045473ffffffffffffffffffffffffffffffffffffffff16610259565b6101ee61044f366004612ae4565b610d11565b610300610462366004612ba3565b610d3c565b61046f610e17565b6040516101d29190612e2c565b6103c761048a366004612ae4565b610ecf565b61030061049d366004612f94565b610fa1565b6103006104b0366004612fd9565b61102a565b7f0000000000000000000000000000000000000000000000000000000000000000610259565b7f00000000000000000000000000000000000000000000000000000000000000006101c6565b61030061050f366004612ba3565b6114b0565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167faff2afbf0000000000000000000000000000000000000000000000000000000014806105a757507fffffffff0000000000000000000000000000000000000000000000000000000082167f0e64dd2900000000000000000000000000000000000000000000000000000000145b806105f357507fffffffff0000000000000000000000000000000000000000000000000000000082167f01ffc9a700000000000000000000000000000000000000000000000000000000145b92915050565b67ffffffffffffffff811660009081526007602052604090206004018054606091906106249061301b565b80601f01602080910402602001604051908101604052809291908181526020018280546106509061301b565b801561069d5780601f106106725761010080835404028352916020019161069d565b820191906000526020600020905b81548152906001019060200180831161068057829003601f168201915b50505050509050919050565b6040805160208101909152600081526106c96106c483613119565b6114c4565b73ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000166340c10f196107156060850160408601612ba3565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b16815273ffffffffffffffffffffffffffffffffffffffff909116600482015260608501356024820152604401600060405180830381600087803b15801561078557600080fd5b505af1158015610799573d6000803e3d6000fd5b506107ae925050506060830160408401612ba3565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f9d228d69b5fdb8d273a2336f8fb8612d039631024ea9bf09c424a9503aa078f0846060013560405161081091815260200190565b60405180910390a3506040805160208101909152606090910135815290565b6108376116f5565b6108a48484808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152505060408051602080880282810182019093528782529093508792508691829185019084908082843760009201919091525061174892505050565b50505050565b6108b26116f5565b6108bb83610b6d565b610902576040517f1e670e4b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff841660048201526024015b60405180910390fd5b67ffffffffffffffff8316600090815260076020526040812060040180546109299061301b565b80601f01602080910402602001604051908101604052809291908181526020018280546109559061301b565b80156109a25780601f10610977576101008083540402835291602001916109a2565b820191906000526020600020905b81548152906001019060200180831161098557829003601f168201915b5050505067ffffffffffffffff86166000908152600760205260409020919250506004016109d183858361325e565b508367ffffffffffffffff167fdb4d6220746a38cbc5335f7e108f7de80f482f4d23350253dfd0917df75a14bf828585604051610a1093929190613378565b60405180910390a250505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314610a6f576040517f02b543c600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000008082163390811790935560008054909116815560405173ffffffffffffffffffffffffffffffffffffffff909216929183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b610af46116f5565b600880547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040519081527f44676b5284b809a22248eba0da87391d79098be38bb03154be88a58bf4d091749060200160405180910390a150565b60006105f3600567ffffffffffffffff84166118fe565b6040805180820190915260608082526020820152610ba9610ba4836133dc565b611919565b610bb68260600135611ae3565b6040516060830135815233907f696de425f79f4a40bc6d2122ca50507f0efbeabbff86a84871b7196ab8ea8df79060200160405180910390a26040518060400160405280610c1084602001602081019061044f9190612ae4565b81526040805160208181019092526000815291015292915050565b6060610c376002611b86565b905090565b6040805160a08101825260008082526020820181905291810182905260608101829052608081019190915267ffffffffffffffff8216600090815260076020908152604091829020825160a08101845260028201546fffffffffffffffffffffffffffffffff808216835270010000000000000000000000000000000080830463ffffffff16958401959095527401000000000000000000000000000000000000000090910460ff1615159482019490945260039091015480841660608301529190910490911660808201526105f390611b93565b67ffffffffffffffff811660009081526007602052604090206005018054606091906106249061301b565b610d446116f5565b73ffffffffffffffffffffffffffffffffffffffff8116610d91576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6004805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff000000000000000000000000000000000000000083168117909355604080519190921680825260208201939093527f02dc5c233404867c793b749c6d644beb2277536d18a7e7974d3f238e4c6f1684910160405180910390a15050565b60606000610e256005611b86565b90506000815167ffffffffffffffff811115610e4357610e43612e6e565b604051908082528060200260200182016040528015610e6c578160200160208202803683370190505b50905060005b8251811015610ec857828181518110610e8d57610e8d61347e565b6020026020010151828281518110610ea757610ea761347e565b67ffffffffffffffff90921660209283029190910190910152600101610e72565b5092915050565b6040805160a08101825260008082526020820181905291810182905260608101829052608081019190915267ffffffffffffffff8216600090815260076020908152604091829020825160a08101845281546fffffffffffffffffffffffffffffffff808216835270010000000000000000000000000000000080830463ffffffff16958401959095527401000000000000000000000000000000000000000090910460ff1615159482019490945260019091015480841660608301529190910490911660808201526105f390611b93565b60085473ffffffffffffffffffffffffffffffffffffffff163314801590610fe1575060015473ffffffffffffffffffffffffffffffffffffffff163314155b1561101a576040517f8e4a23d60000000000000000000000000000000000000000000000000000000081523360048201526024016108f9565b611025838383611c45565b505050565b6110326116f5565b60005b818110156110255760008383838181106110515761105161347e565b905060200281019061106391906134ad565b61106c906134eb565b90506110818160800151826020015115611d2f565b6110948160a00151826020015115611d2f565b8060200151156113905780516110b69060059067ffffffffffffffff16611e68565b6110fb5780516040517f1d5ad3c500000000000000000000000000000000000000000000000000000000815267ffffffffffffffff90911660048201526024016108f9565b60408101515115806111105750606081015151155b15611147576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805161012081018252608083810180516020908101516fffffffffffffffffffffffffffffffff9081168486019081524263ffffffff90811660a0808901829052865151151560c08a01528651860151851660e08a015295518901518416610100890152918752875180860189529489018051850151841686528585019290925281515115158589015281518401518316606080870191909152915188015183168587015283870194855288880151878901908152828a015183890152895167ffffffffffffffff1660009081526007865289902088518051825482890151838e01519289167fffffffffffffffffffffffff0000000000000000000000000000000000000000928316177001000000000000000000000000000000009188168202177fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff90811674010000000000000000000000000000000000000000941515850217865584890151948d0151948a16948a168202949094176001860155995180516002860180549b8301519f830151918b169b9093169a909a179d9096168a029c909c17909116961515029590951790985590810151940151938116931690910291909117600382015591519091906004820190611328908261359f565b506060820151600582019061133d908261359f565b505081516060830151608084015160a08501516040517f8d340f17e19058004c20453540862a9c62778504476f6756755cb33bcd6c38c2955061138394939291906136b9565b60405180910390a16114a7565b80516113a89060059067ffffffffffffffff16611e74565b6113ed5780516040517f1e670e4b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff90911660048201526024016108f9565b805167ffffffffffffffff16600090815260076020526040812080547fffffffffffffffffffffff000000000000000000000000000000000000000000908116825560018201839055600282018054909116905560038101829055906114566004830182612a37565b611464600583016000612a37565b5050805160405167ffffffffffffffff90911681527f5204aec90a3c794d8e90fded8b46ae9c7c552803e7e832e0c1d358396d8599169060200160405180910390a15b50600101611035565b6114b86116f5565b6114c181611e80565b50565b60808101517f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff9081169116146115595760808101516040517f961c9a4f00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff90911660048201526024016108f9565b60208101516040517f2cbc26bb00000000000000000000000000000000000000000000000000000000815260809190911b77ffffffffffffffff000000000000000000000000000000001660048201527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1690632cbc26bb90602401602060405180830381865afa158015611607573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061162b9190613752565b15611662576040517f53ad11d800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61166f8160200151611f44565b600061167e82602001516105f9565b90508051600014806116a2575080805190602001208260a001518051906020012014155b156116df578160a001516040517f24eb47e50000000000000000000000000000000000000000000000000000000081526004016108f99190612b63565b6116f18260200151836060015161206a565b5050565b60015473ffffffffffffffffffffffffffffffffffffffff163314611746576040517f2b5c74de00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b565b7f000000000000000000000000000000000000000000000000000000000000000061179f576040517f35f4a7b300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b82518110156118355760008382815181106117bf576117bf61347e565b602002602001015190506117dd8160026120b190919063ffffffff16565b1561182c5760405173ffffffffffffffffffffffffffffffffffffffff821681527f800671136ab6cfee9fbe5ed1fb7ca417811aca3cf864800d127b927adedf75669060200160405180910390a15b506001016117a2565b5060005b81518110156110255760008282815181106118565761185661347e565b60200260200101519050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff160361189a57506118f6565b6118a56002826120d3565b156118f45760405173ffffffffffffffffffffffffffffffffffffffff821681527f2640d4d76caf8bf478aabfa982fa4e1c4eb71a37f93cd15e80dbc657911546d89060200160405180910390a15b505b600101611839565b600081815260018301602052604081205415155b9392505050565b60808101517f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff9081169116146119ae5760808101516040517f961c9a4f00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff90911660048201526024016108f9565b60208101516040517f2cbc26bb00000000000000000000000000000000000000000000000000000000815260809190911b77ffffffffffffffff000000000000000000000000000000001660048201527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1690632cbc26bb90602401602060405180830381865afa158015611a5c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a809190613752565b15611ab7576040517f53ad11d800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611ac481604001516120f5565b611ad18160200151612174565b6114c1816020015182606001516122c2565b6040517f42966c68000000000000000000000000000000000000000000000000000000008152600481018290527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16906342966c6890602401600060405180830381600087803b158015611b6b57600080fd5b505af1158015611b7f573d6000803e3d6000fd5b5050505050565b6060600061191283612306565b6040805160a081018252600080825260208201819052918101829052606081018290526080810191909152611c2182606001516fffffffffffffffffffffffffffffffff1683600001516fffffffffffffffffffffffffffffffff16846020015163ffffffff1642611c05919061379e565b85608001516fffffffffffffffffffffffffffffffff16612361565b6fffffffffffffffffffffffffffffffff1682525063ffffffff4216602082015290565b611c4e83610b6d565b611c90576040517f1e670e4b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff841660048201526024016108f9565b611c9b826000611d2f565b67ffffffffffffffff83166000908152600760205260409020611cbe908361238b565b611cc9816000611d2f565b67ffffffffffffffff83166000908152600760205260409020611cef906002018261238b565b7f0350d63aa5f270e01729d00d627eeb8f3429772b1818c016c66a588a864f912b838383604051611d22939291906137b1565b60405180910390a1505050565b815115611df65781602001516fffffffffffffffffffffffffffffffff1682604001516fffffffffffffffffffffffffffffffff16101580611d85575060408201516fffffffffffffffffffffffffffffffff16155b15611dbe57816040517f8020d1240000000000000000000000000000000000000000000000000000000081526004016108f99190613834565b80156116f1576040517f433fc33d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60408201516fffffffffffffffffffffffffffffffff16151580611e2f575060208201516fffffffffffffffffffffffffffffffff1615155b156116f157816040517fd68af9cc0000000000000000000000000000000000000000000000000000000081526004016108f99190613834565b6000611912838361252d565b6000611912838361257c565b3373ffffffffffffffffffffffffffffffffffffffff821603611ecf576040517fdad89dca00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff838116918217835560015460405192939116917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b611f4d81610b6d565b611f8f576040517fa9902c7e00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff821660048201526024016108f9565b600480546040517f83826b2b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84169281019290925233602483015273ffffffffffffffffffffffffffffffffffffffff16906383826b2b90604401602060405180830381865afa15801561200e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120329190613752565b6114c1576040517f728fe07b0000000000000000000000000000000000000000000000000000000081523360048201526024016108f9565b67ffffffffffffffff821660009081526007602052604090206116f190600201827f000000000000000000000000000000000000000000000000000000000000000061266f565b60006119128373ffffffffffffffffffffffffffffffffffffffff841661257c565b60006119128373ffffffffffffffffffffffffffffffffffffffff841661252d565b7f0000000000000000000000000000000000000000000000000000000000000000156114c1576121266002826129f2565b6114c1576040517fd0d2597600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff821660048201526024016108f9565b61217d81610b6d565b6121bf576040517fa9902c7e00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff821660048201526024016108f9565b600480546040517fa8d87a3b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84169281019290925273ffffffffffffffffffffffffffffffffffffffff169063a8d87a3b90602401602060405180830381865afa158015612238573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061225c9190613870565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146114c1576040517f728fe07b0000000000000000000000000000000000000000000000000000000081523360048201526024016108f9565b67ffffffffffffffff821660009081526007602052604090206116f190827f000000000000000000000000000000000000000000000000000000000000000061266f565b60608160000180548060200260200160405190810160405280929190818152602001828054801561069d57602002820191906000526020600020905b8154815260200190600101908083116123425750505050509050919050565b600061238085612371848661388d565b61237b90876138a4565b612a21565b90505b949350505050565b81546000906123b490700100000000000000000000000000000000900463ffffffff164261379e565b9050801561245657600183015483546123fc916fffffffffffffffffffffffffffffffff80821692811691859170010000000000000000000000000000000090910416612361565b83546fffffffffffffffffffffffffffffffff919091167fffffffffffffffffffffffff0000000000000000000000000000000000000000909116177001000000000000000000000000000000004263ffffffff16021783555b6020820151835461247c916fffffffffffffffffffffffffffffffff9081169116612a21565b83548351151574010000000000000000000000000000000000000000027fffffffffffffffffffffff00ffffffff000000000000000000000000000000009091166fffffffffffffffffffffffffffffffff92831617178455602083015160408085015183167001000000000000000000000000000000000291909216176001850155517f9ea3374b67bf275e6bb9c8ae68f9cae023e1c528b4b27e092f0bb209d3531c1990611d22908490613834565b6000818152600183016020526040812054612574575081546001818101845560008481526020808220909301849055845484825282860190935260409020919091556105f3565b5060006105f3565b600081815260018301602052604081205480156126655760006125a060018361379e565b85549091506000906125b49060019061379e565b90508082146126195760008660000182815481106125d4576125d461347e565b90600052602060002001549050808760000184815481106125f7576125f761347e565b6000918252602080832090910192909255918252600188019052604090208390555b855486908061262a5761262a6138b7565b6001900381819060005260206000200160009055905585600101600086815260200190815260200160002060009055600193505050506105f3565b60009150506105f3565b825474010000000000000000000000000000000000000000900460ff161580612696575081155b156126a057505050565b825460018401546fffffffffffffffffffffffffffffffff808316929116906000906126e690700100000000000000000000000000000000900463ffffffff164261379e565b905080156127a65781831115612728576040517f9725942a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018601546127629083908590849070010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff16612361565b86547fffffffffffffffffffffffff00000000ffffffffffffffffffffffffffffffff167001000000000000000000000000000000004263ffffffff160217875592505b8482101561285d5773ffffffffffffffffffffffffffffffffffffffff8416612805576040517ff94ebcd100000000000000000000000000000000000000000000000000000000815260048101839052602481018690526044016108f9565b6040517f1a76572a000000000000000000000000000000000000000000000000000000008152600481018390526024810186905273ffffffffffffffffffffffffffffffffffffffff851660448201526064016108f9565b848310156129705760018681015470010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff169060009082906128a1908261379e565b6128ab878a61379e565b6128b591906138a4565b6128bf91906138e6565b905073ffffffffffffffffffffffffffffffffffffffff8616612918576040517f15279c0800000000000000000000000000000000000000000000000000000000815260048101829052602481018690526044016108f9565b6040517fd0c8d23a000000000000000000000000000000000000000000000000000000008152600481018290526024810186905273ffffffffffffffffffffffffffffffffffffffff871660448201526064016108f9565b61297a858461379e565b86547fffffffffffffffffffffffffffffffff00000000000000000000000000000000166fffffffffffffffffffffffffffffffff82161787556040518681529093507f1871cdf8010e63f2eb8384381a68dfa7416dc571a5517e66e88b2d2d0c0a690a9060200160405180910390a1505050505050565b73ffffffffffffffffffffffffffffffffffffffff811660009081526001830160205260408120541515611912565b6000818310612a305781611912565b5090919050565b508054612a439061301b565b6000825580601f10612a53575050565b601f0160209004906000526020600020908101906114c191905b80821115612a815760008155600101612a6d565b5090565b600060208284031215612a9757600080fd5b81357fffffffff000000000000000000000000000000000000000000000000000000008116811461191257600080fd5b803567ffffffffffffffff81168114612adf57600080fd5b919050565b600060208284031215612af657600080fd5b61191282612ac7565b6000815180845260005b81811015612b2557602081850181015186830182015201612b09565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b6020815260006119126020830184612aff565b73ffffffffffffffffffffffffffffffffffffffff811681146114c157600080fd5b8035612adf81612b76565b600060208284031215612bb557600080fd5b813561191281612b76565b600060208284031215612bd257600080fd5b813567ffffffffffffffff811115612be957600080fd5b8201610100818503121561191257600080fd5b60008083601f840112612c0e57600080fd5b50813567ffffffffffffffff811115612c2657600080fd5b6020830191508360208260051b8501011115612c4157600080fd5b9250929050565b60008060008060408587031215612c5e57600080fd5b843567ffffffffffffffff80821115612c7657600080fd5b612c8288838901612bfc565b90965094506020870135915080821115612c9b57600080fd5b50612ca887828801612bfc565b95989497509550505050565b600080600060408486031215612cc957600080fd5b612cd284612ac7565b9250602084013567ffffffffffffffff80821115612cef57600080fd5b818601915086601f830112612d0357600080fd5b813581811115612d1257600080fd5b876020828501011115612d2457600080fd5b6020830194508093505050509250925092565b600060208284031215612d4957600080fd5b813567ffffffffffffffff811115612d6057600080fd5b820160a0818503121561191257600080fd5b602081526000825160406020840152612d8e6060840182612aff565b905060208401517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0848303016040850152612dc98282612aff565b95945050505050565b6020808252825182820181905260009190848201906040850190845b81811015612e2057835173ffffffffffffffffffffffffffffffffffffffff1683529284019291840191600101612dee565b50909695505050505050565b6020808252825182820181905260009190848201906040850190845b81811015612e2057835167ffffffffffffffff1683529284019291840191600101612e48565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051610100810167ffffffffffffffff81118282101715612ec157612ec1612e6e565b60405290565b60405160c0810167ffffffffffffffff81118282101715612ec157612ec1612e6e565b80151581146114c157600080fd5b8035612adf81612eea565b80356fffffffffffffffffffffffffffffffff81168114612adf57600080fd5b600060608284031215612f3557600080fd5b6040516060810181811067ffffffffffffffff82111715612f5857612f58612e6e565b6040529050808235612f6981612eea565b8152612f7760208401612f03565b6020820152612f8860408401612f03565b60408201525092915050565b600080600060e08486031215612fa957600080fd5b612fb284612ac7565b9250612fc18560208601612f23565b9150612fd08560808601612f23565b90509250925092565b60008060208385031215612fec57600080fd5b823567ffffffffffffffff81111561300357600080fd5b61300f85828601612bfc565b90969095509350505050565b600181811c9082168061302f57607f821691505b602082108103613068577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b600082601f83011261307f57600080fd5b813567ffffffffffffffff8082111561309a5761309a612e6e565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f011681019082821181831017156130e0576130e0612e6e565b816040528381528660208588010111156130f957600080fd5b836020870160208301376000602085830101528094505050505092915050565b6000610100823603121561312c57600080fd5b613134612e9d565b823567ffffffffffffffff8082111561314c57600080fd5b6131583683870161306e565b835261316660208601612ac7565b602084015261317760408601612b98565b60408401526060850135606084015261319260808601612b98565b608084015260a08501359150808211156131ab57600080fd5b6131b73683870161306e565b60a084015260c08501359150808211156131d057600080fd5b6131dc3683870161306e565b60c084015260e08501359150808211156131f557600080fd5b506132023682860161306e565b60e08301525092915050565b601f821115611025576000816000526020600020601f850160051c810160208610156132375750805b601f850160051c820191505b8181101561325657828155600101613243565b505050505050565b67ffffffffffffffff83111561327657613276612e6e565b61328a83613284835461301b565b8361320e565b6000601f8411600181146132dc57600085156132a65750838201355b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600387901b1c1916600186901b178355611b7f565b6000838152602090207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0861690835b8281101561332b578685013582556020948501946001909201910161330b565b5086821015613366577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88860031b161c19848701351681555b505060018560011b0183555050505050565b60408152600061338b6040830186612aff565b82810360208401528381528385602083013760006020858301015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f860116820101915050949350505050565b600060a082360312156133ee57600080fd5b60405160a0810167ffffffffffffffff828210818311171561341257613412612e6e565b81604052843591508082111561342757600080fd5b506134343682860161306e565b82525061344360208401612ac7565b6020820152604083013561345681612b76565b604082015260608381013590820152608083013561347381612b76565b608082015292915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600082357ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffec18336030181126134e157600080fd5b9190910192915050565b600061014082360312156134fe57600080fd5b613506612ec7565b61350f83612ac7565b815261351d60208401612ef8565b6020820152604083013567ffffffffffffffff8082111561353d57600080fd5b6135493683870161306e565b6040840152606085013591508082111561356257600080fd5b5061356f3682860161306e565b6060830152506135823660808501612f23565b60808201526135943660e08501612f23565b60a082015292915050565b815167ffffffffffffffff8111156135b9576135b9612e6e565b6135cd816135c7845461301b565b8461320e565b602080601f83116001811461362057600084156135ea5750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b178555613256565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b8281101561366d5788860151825594840194600190910190840161364e565b50858210156136a957878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b600061010067ffffffffffffffff871683528060208401526136dd81840187612aff565b8551151560408581019190915260208701516fffffffffffffffffffffffffffffffff908116606087015290870151166080850152915061371b9050565b8251151560a083015260208301516fffffffffffffffffffffffffffffffff90811660c084015260408401511660e0830152612dc9565b60006020828403121561376457600080fd5b815161191281612eea565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b818103818111156105f3576105f361376f565b67ffffffffffffffff8416815260e081016137fd60208301858051151582526020808201516fffffffffffffffffffffffffffffffff9081169184019190915260409182015116910152565b82511515608083015260208301516fffffffffffffffffffffffffffffffff90811660a084015260408401511660c0830152612383565b606081016105f382848051151582526020808201516fffffffffffffffffffffffffffffffff9081169184019190915260409182015116910152565b60006020828403121561388257600080fd5b815161191281612b76565b80820281158282048414176105f3576105f361376f565b808201808211156105f3576105f361376f565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b60008261391c577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b50049056fea164736f6c6343000818000a", } var BurnMintTokenPoolABI = BurnMintTokenPoolMetaData.ABI var BurnMintTokenPoolBin = BurnMintTokenPoolMetaData.Bin -func DeployBurnMintTokenPool(auth *bind.TransactOpts, backend bind.ContractBackend, token common.Address, localTokenDecimals uint8, allowlist []common.Address, rmnProxy common.Address, router common.Address) (common.Address, *types.Transaction, *BurnMintTokenPool, error) { +func DeployBurnMintTokenPool(auth *bind.TransactOpts, backend bind.ContractBackend, token common.Address, allowlist []common.Address, rmnProxy common.Address, router common.Address) (common.Address, *types.Transaction, *BurnMintTokenPool, error) { parsed, err := BurnMintTokenPoolMetaData.GetAbi() if err != nil { return common.Address{}, nil, nil, err @@ -98,7 +99,7 @@ func DeployBurnMintTokenPool(auth *bind.TransactOpts, backend bind.ContractBacke return common.Address{}, nil, nil, errors.New("GetABI returned nil") } - address, tx, contract, err := bind.DeployContract(auth, *parsed, common.FromHex(BurnMintTokenPoolBin), backend, token, localTokenDecimals, allowlist, rmnProxy, router) + address, tx, contract, err := bind.DeployContract(auth, *parsed, common.FromHex(BurnMintTokenPoolBin), backend, token, allowlist, rmnProxy, router) if err != nil { return common.Address{}, nil, nil, err } @@ -331,26 +332,26 @@ func (_BurnMintTokenPool *BurnMintTokenPoolCallerSession) GetRateLimitAdmin() (c return _BurnMintTokenPool.Contract.GetRateLimitAdmin(&_BurnMintTokenPool.CallOpts) } -func (_BurnMintTokenPool *BurnMintTokenPoolCaller) GetRemotePools(opts *bind.CallOpts, remoteChainSelector uint64) ([][]byte, error) { +func (_BurnMintTokenPool *BurnMintTokenPoolCaller) GetRemotePool(opts *bind.CallOpts, remoteChainSelector uint64) ([]byte, error) { var out []interface{} - err := _BurnMintTokenPool.contract.Call(opts, &out, "getRemotePools", remoteChainSelector) + err := _BurnMintTokenPool.contract.Call(opts, &out, "getRemotePool", remoteChainSelector) if err != nil { - return *new([][]byte), err + return *new([]byte), err } - out0 := *abi.ConvertType(out[0], new([][]byte)).(*[][]byte) + out0 := *abi.ConvertType(out[0], new([]byte)).(*[]byte) return out0, err } -func (_BurnMintTokenPool *BurnMintTokenPoolSession) GetRemotePools(remoteChainSelector uint64) ([][]byte, error) { - return _BurnMintTokenPool.Contract.GetRemotePools(&_BurnMintTokenPool.CallOpts, remoteChainSelector) +func (_BurnMintTokenPool *BurnMintTokenPoolSession) GetRemotePool(remoteChainSelector uint64) ([]byte, error) { + return _BurnMintTokenPool.Contract.GetRemotePool(&_BurnMintTokenPool.CallOpts, remoteChainSelector) } -func (_BurnMintTokenPool *BurnMintTokenPoolCallerSession) GetRemotePools(remoteChainSelector uint64) ([][]byte, error) { - return _BurnMintTokenPool.Contract.GetRemotePools(&_BurnMintTokenPool.CallOpts, remoteChainSelector) +func (_BurnMintTokenPool *BurnMintTokenPoolCallerSession) GetRemotePool(remoteChainSelector uint64) ([]byte, error) { + return _BurnMintTokenPool.Contract.GetRemotePool(&_BurnMintTokenPool.CallOpts, remoteChainSelector) } func (_BurnMintTokenPool *BurnMintTokenPoolCaller) GetRemoteToken(opts *bind.CallOpts, remoteChainSelector uint64) ([]byte, error) { @@ -463,50 +464,6 @@ func (_BurnMintTokenPool *BurnMintTokenPoolCallerSession) GetToken() (common.Add return _BurnMintTokenPool.Contract.GetToken(&_BurnMintTokenPool.CallOpts) } -func (_BurnMintTokenPool *BurnMintTokenPoolCaller) GetTokenDecimals(opts *bind.CallOpts) (uint8, error) { - var out []interface{} - err := _BurnMintTokenPool.contract.Call(opts, &out, "getTokenDecimals") - - if err != nil { - return *new(uint8), err - } - - out0 := *abi.ConvertType(out[0], new(uint8)).(*uint8) - - return out0, err - -} - -func (_BurnMintTokenPool *BurnMintTokenPoolSession) GetTokenDecimals() (uint8, error) { - return _BurnMintTokenPool.Contract.GetTokenDecimals(&_BurnMintTokenPool.CallOpts) -} - -func (_BurnMintTokenPool *BurnMintTokenPoolCallerSession) GetTokenDecimals() (uint8, error) { - return _BurnMintTokenPool.Contract.GetTokenDecimals(&_BurnMintTokenPool.CallOpts) -} - -func (_BurnMintTokenPool *BurnMintTokenPoolCaller) IsRemotePool(opts *bind.CallOpts, remoteChainSelector uint64, remotePoolAddress []byte) (bool, error) { - var out []interface{} - err := _BurnMintTokenPool.contract.Call(opts, &out, "isRemotePool", remoteChainSelector, remotePoolAddress) - - if err != nil { - return *new(bool), err - } - - out0 := *abi.ConvertType(out[0], new(bool)).(*bool) - - return out0, err - -} - -func (_BurnMintTokenPool *BurnMintTokenPoolSession) IsRemotePool(remoteChainSelector uint64, remotePoolAddress []byte) (bool, error) { - return _BurnMintTokenPool.Contract.IsRemotePool(&_BurnMintTokenPool.CallOpts, remoteChainSelector, remotePoolAddress) -} - -func (_BurnMintTokenPool *BurnMintTokenPoolCallerSession) IsRemotePool(remoteChainSelector uint64, remotePoolAddress []byte) (bool, error) { - return _BurnMintTokenPool.Contract.IsRemotePool(&_BurnMintTokenPool.CallOpts, remoteChainSelector, remotePoolAddress) -} - func (_BurnMintTokenPool *BurnMintTokenPoolCaller) IsSupportedChain(opts *bind.CallOpts, remoteChainSelector uint64) (bool, error) { var out []interface{} err := _BurnMintTokenPool.contract.Call(opts, &out, "isSupportedChain", remoteChainSelector) @@ -629,18 +586,6 @@ func (_BurnMintTokenPool *BurnMintTokenPoolTransactorSession) AcceptOwnership() return _BurnMintTokenPool.Contract.AcceptOwnership(&_BurnMintTokenPool.TransactOpts) } -func (_BurnMintTokenPool *BurnMintTokenPoolTransactor) AddRemotePool(opts *bind.TransactOpts, remoteChainSelector uint64, remotePoolAddress []byte) (*types.Transaction, error) { - return _BurnMintTokenPool.contract.Transact(opts, "addRemotePool", remoteChainSelector, remotePoolAddress) -} - -func (_BurnMintTokenPool *BurnMintTokenPoolSession) AddRemotePool(remoteChainSelector uint64, remotePoolAddress []byte) (*types.Transaction, error) { - return _BurnMintTokenPool.Contract.AddRemotePool(&_BurnMintTokenPool.TransactOpts, remoteChainSelector, remotePoolAddress) -} - -func (_BurnMintTokenPool *BurnMintTokenPoolTransactorSession) AddRemotePool(remoteChainSelector uint64, remotePoolAddress []byte) (*types.Transaction, error) { - return _BurnMintTokenPool.Contract.AddRemotePool(&_BurnMintTokenPool.TransactOpts, remoteChainSelector, remotePoolAddress) -} - func (_BurnMintTokenPool *BurnMintTokenPoolTransactor) ApplyAllowListUpdates(opts *bind.TransactOpts, removes []common.Address, adds []common.Address) (*types.Transaction, error) { return _BurnMintTokenPool.contract.Transact(opts, "applyAllowListUpdates", removes, adds) } @@ -653,16 +598,16 @@ func (_BurnMintTokenPool *BurnMintTokenPoolTransactorSession) ApplyAllowListUpda return _BurnMintTokenPool.Contract.ApplyAllowListUpdates(&_BurnMintTokenPool.TransactOpts, removes, adds) } -func (_BurnMintTokenPool *BurnMintTokenPoolTransactor) ApplyChainUpdates(opts *bind.TransactOpts, remoteChainSelectorsToRemove []uint64, chainsToAdd []TokenPoolChainUpdate) (*types.Transaction, error) { - return _BurnMintTokenPool.contract.Transact(opts, "applyChainUpdates", remoteChainSelectorsToRemove, chainsToAdd) +func (_BurnMintTokenPool *BurnMintTokenPoolTransactor) ApplyChainUpdates(opts *bind.TransactOpts, chains []TokenPoolChainUpdate) (*types.Transaction, error) { + return _BurnMintTokenPool.contract.Transact(opts, "applyChainUpdates", chains) } -func (_BurnMintTokenPool *BurnMintTokenPoolSession) ApplyChainUpdates(remoteChainSelectorsToRemove []uint64, chainsToAdd []TokenPoolChainUpdate) (*types.Transaction, error) { - return _BurnMintTokenPool.Contract.ApplyChainUpdates(&_BurnMintTokenPool.TransactOpts, remoteChainSelectorsToRemove, chainsToAdd) +func (_BurnMintTokenPool *BurnMintTokenPoolSession) ApplyChainUpdates(chains []TokenPoolChainUpdate) (*types.Transaction, error) { + return _BurnMintTokenPool.Contract.ApplyChainUpdates(&_BurnMintTokenPool.TransactOpts, chains) } -func (_BurnMintTokenPool *BurnMintTokenPoolTransactorSession) ApplyChainUpdates(remoteChainSelectorsToRemove []uint64, chainsToAdd []TokenPoolChainUpdate) (*types.Transaction, error) { - return _BurnMintTokenPool.Contract.ApplyChainUpdates(&_BurnMintTokenPool.TransactOpts, remoteChainSelectorsToRemove, chainsToAdd) +func (_BurnMintTokenPool *BurnMintTokenPoolTransactorSession) ApplyChainUpdates(chains []TokenPoolChainUpdate) (*types.Transaction, error) { + return _BurnMintTokenPool.Contract.ApplyChainUpdates(&_BurnMintTokenPool.TransactOpts, chains) } func (_BurnMintTokenPool *BurnMintTokenPoolTransactor) LockOrBurn(opts *bind.TransactOpts, lockOrBurnIn PoolLockOrBurnInV1) (*types.Transaction, error) { @@ -689,18 +634,6 @@ func (_BurnMintTokenPool *BurnMintTokenPoolTransactorSession) ReleaseOrMint(rele return _BurnMintTokenPool.Contract.ReleaseOrMint(&_BurnMintTokenPool.TransactOpts, releaseOrMintIn) } -func (_BurnMintTokenPool *BurnMintTokenPoolTransactor) RemoveRemotePool(opts *bind.TransactOpts, remoteChainSelector uint64, remotePoolAddress []byte) (*types.Transaction, error) { - return _BurnMintTokenPool.contract.Transact(opts, "removeRemotePool", remoteChainSelector, remotePoolAddress) -} - -func (_BurnMintTokenPool *BurnMintTokenPoolSession) RemoveRemotePool(remoteChainSelector uint64, remotePoolAddress []byte) (*types.Transaction, error) { - return _BurnMintTokenPool.Contract.RemoveRemotePool(&_BurnMintTokenPool.TransactOpts, remoteChainSelector, remotePoolAddress) -} - -func (_BurnMintTokenPool *BurnMintTokenPoolTransactorSession) RemoveRemotePool(remoteChainSelector uint64, remotePoolAddress []byte) (*types.Transaction, error) { - return _BurnMintTokenPool.Contract.RemoveRemotePool(&_BurnMintTokenPool.TransactOpts, remoteChainSelector, remotePoolAddress) -} - func (_BurnMintTokenPool *BurnMintTokenPoolTransactor) SetChainRateLimiterConfig(opts *bind.TransactOpts, remoteChainSelector uint64, outboundConfig RateLimiterConfig, inboundConfig RateLimiterConfig) (*types.Transaction, error) { return _BurnMintTokenPool.contract.Transact(opts, "setChainRateLimiterConfig", remoteChainSelector, outboundConfig, inboundConfig) } @@ -713,18 +646,6 @@ func (_BurnMintTokenPool *BurnMintTokenPoolTransactorSession) SetChainRateLimite return _BurnMintTokenPool.Contract.SetChainRateLimiterConfig(&_BurnMintTokenPool.TransactOpts, remoteChainSelector, outboundConfig, inboundConfig) } -func (_BurnMintTokenPool *BurnMintTokenPoolTransactor) SetChainRateLimiterConfigs(opts *bind.TransactOpts, remoteChainSelectors []uint64, outboundConfigs []RateLimiterConfig, inboundConfigs []RateLimiterConfig) (*types.Transaction, error) { - return _BurnMintTokenPool.contract.Transact(opts, "setChainRateLimiterConfigs", remoteChainSelectors, outboundConfigs, inboundConfigs) -} - -func (_BurnMintTokenPool *BurnMintTokenPoolSession) SetChainRateLimiterConfigs(remoteChainSelectors []uint64, outboundConfigs []RateLimiterConfig, inboundConfigs []RateLimiterConfig) (*types.Transaction, error) { - return _BurnMintTokenPool.Contract.SetChainRateLimiterConfigs(&_BurnMintTokenPool.TransactOpts, remoteChainSelectors, outboundConfigs, inboundConfigs) -} - -func (_BurnMintTokenPool *BurnMintTokenPoolTransactorSession) SetChainRateLimiterConfigs(remoteChainSelectors []uint64, outboundConfigs []RateLimiterConfig, inboundConfigs []RateLimiterConfig) (*types.Transaction, error) { - return _BurnMintTokenPool.Contract.SetChainRateLimiterConfigs(&_BurnMintTokenPool.TransactOpts, remoteChainSelectors, outboundConfigs, inboundConfigs) -} - func (_BurnMintTokenPool *BurnMintTokenPoolTransactor) SetRateLimitAdmin(opts *bind.TransactOpts, rateLimitAdmin common.Address) (*types.Transaction, error) { return _BurnMintTokenPool.contract.Transact(opts, "setRateLimitAdmin", rateLimitAdmin) } @@ -737,6 +658,18 @@ func (_BurnMintTokenPool *BurnMintTokenPoolTransactorSession) SetRateLimitAdmin( return _BurnMintTokenPool.Contract.SetRateLimitAdmin(&_BurnMintTokenPool.TransactOpts, rateLimitAdmin) } +func (_BurnMintTokenPool *BurnMintTokenPoolTransactor) SetRemotePool(opts *bind.TransactOpts, remoteChainSelector uint64, remotePoolAddress []byte) (*types.Transaction, error) { + return _BurnMintTokenPool.contract.Transact(opts, "setRemotePool", remoteChainSelector, remotePoolAddress) +} + +func (_BurnMintTokenPool *BurnMintTokenPoolSession) SetRemotePool(remoteChainSelector uint64, remotePoolAddress []byte) (*types.Transaction, error) { + return _BurnMintTokenPool.Contract.SetRemotePool(&_BurnMintTokenPool.TransactOpts, remoteChainSelector, remotePoolAddress) +} + +func (_BurnMintTokenPool *BurnMintTokenPoolTransactorSession) SetRemotePool(remoteChainSelector uint64, remotePoolAddress []byte) (*types.Transaction, error) { + return _BurnMintTokenPool.Contract.SetRemotePool(&_BurnMintTokenPool.TransactOpts, remoteChainSelector, remotePoolAddress) +} + func (_BurnMintTokenPool *BurnMintTokenPoolTransactor) SetRouter(opts *bind.TransactOpts, newRouter common.Address) (*types.Transaction, error) { return _BurnMintTokenPool.contract.Transact(opts, "setRouter", newRouter) } @@ -2387,8 +2320,8 @@ func (_BurnMintTokenPool *BurnMintTokenPoolFilterer) ParseReleased(log types.Log return event, nil } -type BurnMintTokenPoolRemotePoolAddedIterator struct { - Event *BurnMintTokenPoolRemotePoolAdded +type BurnMintTokenPoolRemotePoolSetIterator struct { + Event *BurnMintTokenPoolRemotePoolSet contract *bind.BoundContract event string @@ -2399,7 +2332,7 @@ type BurnMintTokenPoolRemotePoolAddedIterator struct { fail error } -func (it *BurnMintTokenPoolRemotePoolAddedIterator) Next() bool { +func (it *BurnMintTokenPoolRemotePoolSetIterator) Next() bool { if it.fail != nil { return false @@ -2408,7 +2341,7 @@ func (it *BurnMintTokenPoolRemotePoolAddedIterator) Next() bool { if it.done { select { case log := <-it.logs: - it.Event = new(BurnMintTokenPoolRemotePoolAdded) + it.Event = new(BurnMintTokenPoolRemotePoolSet) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -2423,7 +2356,7 @@ func (it *BurnMintTokenPoolRemotePoolAddedIterator) Next() bool { select { case log := <-it.logs: - it.Event = new(BurnMintTokenPoolRemotePoolAdded) + it.Event = new(BurnMintTokenPoolRemotePoolSet) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -2438,43 +2371,44 @@ func (it *BurnMintTokenPoolRemotePoolAddedIterator) Next() bool { } } -func (it *BurnMintTokenPoolRemotePoolAddedIterator) Error() error { +func (it *BurnMintTokenPoolRemotePoolSetIterator) Error() error { return it.fail } -func (it *BurnMintTokenPoolRemotePoolAddedIterator) Close() error { +func (it *BurnMintTokenPoolRemotePoolSetIterator) Close() error { it.sub.Unsubscribe() return nil } -type BurnMintTokenPoolRemotePoolAdded struct { +type BurnMintTokenPoolRemotePoolSet struct { RemoteChainSelector uint64 + PreviousPoolAddress []byte RemotePoolAddress []byte Raw types.Log } -func (_BurnMintTokenPool *BurnMintTokenPoolFilterer) FilterRemotePoolAdded(opts *bind.FilterOpts, remoteChainSelector []uint64) (*BurnMintTokenPoolRemotePoolAddedIterator, error) { +func (_BurnMintTokenPool *BurnMintTokenPoolFilterer) FilterRemotePoolSet(opts *bind.FilterOpts, remoteChainSelector []uint64) (*BurnMintTokenPoolRemotePoolSetIterator, error) { var remoteChainSelectorRule []interface{} for _, remoteChainSelectorItem := range remoteChainSelector { remoteChainSelectorRule = append(remoteChainSelectorRule, remoteChainSelectorItem) } - logs, sub, err := _BurnMintTokenPool.contract.FilterLogs(opts, "RemotePoolAdded", remoteChainSelectorRule) + logs, sub, err := _BurnMintTokenPool.contract.FilterLogs(opts, "RemotePoolSet", remoteChainSelectorRule) if err != nil { return nil, err } - return &BurnMintTokenPoolRemotePoolAddedIterator{contract: _BurnMintTokenPool.contract, event: "RemotePoolAdded", logs: logs, sub: sub}, nil + return &BurnMintTokenPoolRemotePoolSetIterator{contract: _BurnMintTokenPool.contract, event: "RemotePoolSet", logs: logs, sub: sub}, nil } -func (_BurnMintTokenPool *BurnMintTokenPoolFilterer) WatchRemotePoolAdded(opts *bind.WatchOpts, sink chan<- *BurnMintTokenPoolRemotePoolAdded, remoteChainSelector []uint64) (event.Subscription, error) { +func (_BurnMintTokenPool *BurnMintTokenPoolFilterer) WatchRemotePoolSet(opts *bind.WatchOpts, sink chan<- *BurnMintTokenPoolRemotePoolSet, remoteChainSelector []uint64) (event.Subscription, error) { var remoteChainSelectorRule []interface{} for _, remoteChainSelectorItem := range remoteChainSelector { remoteChainSelectorRule = append(remoteChainSelectorRule, remoteChainSelectorItem) } - logs, sub, err := _BurnMintTokenPool.contract.WatchLogs(opts, "RemotePoolAdded", remoteChainSelectorRule) + logs, sub, err := _BurnMintTokenPool.contract.WatchLogs(opts, "RemotePoolSet", remoteChainSelectorRule) if err != nil { return nil, err } @@ -2484,8 +2418,8 @@ func (_BurnMintTokenPool *BurnMintTokenPoolFilterer) WatchRemotePoolAdded(opts * select { case log := <-logs: - event := new(BurnMintTokenPoolRemotePoolAdded) - if err := _BurnMintTokenPool.contract.UnpackLog(event, "RemotePoolAdded", log); err != nil { + event := new(BurnMintTokenPoolRemotePoolSet) + if err := _BurnMintTokenPool.contract.UnpackLog(event, "RemotePoolSet", log); err != nil { return err } event.Raw = log @@ -2506,137 +2440,9 @@ func (_BurnMintTokenPool *BurnMintTokenPoolFilterer) WatchRemotePoolAdded(opts * }), nil } -func (_BurnMintTokenPool *BurnMintTokenPoolFilterer) ParseRemotePoolAdded(log types.Log) (*BurnMintTokenPoolRemotePoolAdded, error) { - event := new(BurnMintTokenPoolRemotePoolAdded) - if err := _BurnMintTokenPool.contract.UnpackLog(event, "RemotePoolAdded", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -type BurnMintTokenPoolRemotePoolRemovedIterator struct { - Event *BurnMintTokenPoolRemotePoolRemoved - - contract *bind.BoundContract - event string - - logs chan types.Log - sub ethereum.Subscription - done bool - fail error -} - -func (it *BurnMintTokenPoolRemotePoolRemovedIterator) Next() bool { - - if it.fail != nil { - return false - } - - if it.done { - select { - case log := <-it.logs: - it.Event = new(BurnMintTokenPoolRemotePoolRemoved) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - default: - return false - } - } - - select { - case log := <-it.logs: - it.Event = new(BurnMintTokenPoolRemotePoolRemoved) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - case err := <-it.sub.Err(): - it.done = true - it.fail = err - return it.Next() - } -} - -func (it *BurnMintTokenPoolRemotePoolRemovedIterator) Error() error { - return it.fail -} - -func (it *BurnMintTokenPoolRemotePoolRemovedIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -type BurnMintTokenPoolRemotePoolRemoved struct { - RemoteChainSelector uint64 - RemotePoolAddress []byte - Raw types.Log -} - -func (_BurnMintTokenPool *BurnMintTokenPoolFilterer) FilterRemotePoolRemoved(opts *bind.FilterOpts, remoteChainSelector []uint64) (*BurnMintTokenPoolRemotePoolRemovedIterator, error) { - - var remoteChainSelectorRule []interface{} - for _, remoteChainSelectorItem := range remoteChainSelector { - remoteChainSelectorRule = append(remoteChainSelectorRule, remoteChainSelectorItem) - } - - logs, sub, err := _BurnMintTokenPool.contract.FilterLogs(opts, "RemotePoolRemoved", remoteChainSelectorRule) - if err != nil { - return nil, err - } - return &BurnMintTokenPoolRemotePoolRemovedIterator{contract: _BurnMintTokenPool.contract, event: "RemotePoolRemoved", logs: logs, sub: sub}, nil -} - -func (_BurnMintTokenPool *BurnMintTokenPoolFilterer) WatchRemotePoolRemoved(opts *bind.WatchOpts, sink chan<- *BurnMintTokenPoolRemotePoolRemoved, remoteChainSelector []uint64) (event.Subscription, error) { - - var remoteChainSelectorRule []interface{} - for _, remoteChainSelectorItem := range remoteChainSelector { - remoteChainSelectorRule = append(remoteChainSelectorRule, remoteChainSelectorItem) - } - - logs, sub, err := _BurnMintTokenPool.contract.WatchLogs(opts, "RemotePoolRemoved", remoteChainSelectorRule) - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - - event := new(BurnMintTokenPoolRemotePoolRemoved) - if err := _BurnMintTokenPool.contract.UnpackLog(event, "RemotePoolRemoved", log); err != nil { - return err - } - event.Raw = log - - select { - case sink <- event: - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - } - }), nil -} - -func (_BurnMintTokenPool *BurnMintTokenPoolFilterer) ParseRemotePoolRemoved(log types.Log) (*BurnMintTokenPoolRemotePoolRemoved, error) { - event := new(BurnMintTokenPoolRemotePoolRemoved) - if err := _BurnMintTokenPool.contract.UnpackLog(event, "RemotePoolRemoved", log); err != nil { +func (_BurnMintTokenPool *BurnMintTokenPoolFilterer) ParseRemotePoolSet(log types.Log) (*BurnMintTokenPoolRemotePoolSet, error) { + event := new(BurnMintTokenPoolRemotePoolSet) + if err := _BurnMintTokenPool.contract.UnpackLog(event, "RemotePoolSet", log); err != nil { return nil, err } event.Raw = log @@ -2906,10 +2712,8 @@ func (_BurnMintTokenPool *BurnMintTokenPool) ParseLog(log types.Log) (generated. return _BurnMintTokenPool.ParseRateLimitAdminSet(log) case _BurnMintTokenPool.abi.Events["Released"].ID: return _BurnMintTokenPool.ParseReleased(log) - case _BurnMintTokenPool.abi.Events["RemotePoolAdded"].ID: - return _BurnMintTokenPool.ParseRemotePoolAdded(log) - case _BurnMintTokenPool.abi.Events["RemotePoolRemoved"].ID: - return _BurnMintTokenPool.ParseRemotePoolRemoved(log) + case _BurnMintTokenPool.abi.Events["RemotePoolSet"].ID: + return _BurnMintTokenPool.ParseRemotePoolSet(log) case _BurnMintTokenPool.abi.Events["RouterUpdated"].ID: return _BurnMintTokenPool.ParseRouterUpdated(log) case _BurnMintTokenPool.abi.Events["TokensConsumed"].ID: @@ -2972,12 +2776,8 @@ func (BurnMintTokenPoolReleased) Topic() common.Hash { return common.HexToHash("0x2d87480f50083e2b2759522a8fdda59802650a8055e609a7772cf70c07748f52") } -func (BurnMintTokenPoolRemotePoolAdded) Topic() common.Hash { - return common.HexToHash("0x7d628c9a1796743d365ab521a8b2a4686e419b3269919dc9145ea2ce853b54ea") -} - -func (BurnMintTokenPoolRemotePoolRemoved) Topic() common.Hash { - return common.HexToHash("0x52d00ee4d9bd51b40168f2afc5848837288ce258784ad914278791464b3f4d76") +func (BurnMintTokenPoolRemotePoolSet) Topic() common.Hash { + return common.HexToHash("0xdb4d6220746a38cbc5335f7e108f7de80f482f4d23350253dfd0917df75a14bf") } func (BurnMintTokenPoolRouterUpdated) Topic() common.Hash { @@ -3003,7 +2803,7 @@ type BurnMintTokenPoolInterface interface { GetRateLimitAdmin(opts *bind.CallOpts) (common.Address, error) - GetRemotePools(opts *bind.CallOpts, remoteChainSelector uint64) ([][]byte, error) + GetRemotePool(opts *bind.CallOpts, remoteChainSelector uint64) ([]byte, error) GetRemoteToken(opts *bind.CallOpts, remoteChainSelector uint64) ([]byte, error) @@ -3015,10 +2815,6 @@ type BurnMintTokenPoolInterface interface { GetToken(opts *bind.CallOpts) (common.Address, error) - GetTokenDecimals(opts *bind.CallOpts) (uint8, error) - - IsRemotePool(opts *bind.CallOpts, remoteChainSelector uint64, remotePoolAddress []byte) (bool, error) - IsSupportedChain(opts *bind.CallOpts, remoteChainSelector uint64) (bool, error) IsSupportedToken(opts *bind.CallOpts, token common.Address) (bool, error) @@ -3031,24 +2827,20 @@ type BurnMintTokenPoolInterface interface { AcceptOwnership(opts *bind.TransactOpts) (*types.Transaction, error) - AddRemotePool(opts *bind.TransactOpts, remoteChainSelector uint64, remotePoolAddress []byte) (*types.Transaction, error) - ApplyAllowListUpdates(opts *bind.TransactOpts, removes []common.Address, adds []common.Address) (*types.Transaction, error) - ApplyChainUpdates(opts *bind.TransactOpts, remoteChainSelectorsToRemove []uint64, chainsToAdd []TokenPoolChainUpdate) (*types.Transaction, error) + ApplyChainUpdates(opts *bind.TransactOpts, chains []TokenPoolChainUpdate) (*types.Transaction, error) LockOrBurn(opts *bind.TransactOpts, lockOrBurnIn PoolLockOrBurnInV1) (*types.Transaction, error) ReleaseOrMint(opts *bind.TransactOpts, releaseOrMintIn PoolReleaseOrMintInV1) (*types.Transaction, error) - RemoveRemotePool(opts *bind.TransactOpts, remoteChainSelector uint64, remotePoolAddress []byte) (*types.Transaction, error) - SetChainRateLimiterConfig(opts *bind.TransactOpts, remoteChainSelector uint64, outboundConfig RateLimiterConfig, inboundConfig RateLimiterConfig) (*types.Transaction, error) - SetChainRateLimiterConfigs(opts *bind.TransactOpts, remoteChainSelectors []uint64, outboundConfigs []RateLimiterConfig, inboundConfigs []RateLimiterConfig) (*types.Transaction, error) - SetRateLimitAdmin(opts *bind.TransactOpts, rateLimitAdmin common.Address) (*types.Transaction, error) + SetRemotePool(opts *bind.TransactOpts, remoteChainSelector uint64, remotePoolAddress []byte) (*types.Transaction, error) + SetRouter(opts *bind.TransactOpts, newRouter common.Address) (*types.Transaction, error) TransferOwnership(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) @@ -3131,17 +2923,11 @@ type BurnMintTokenPoolInterface interface { ParseReleased(log types.Log) (*BurnMintTokenPoolReleased, error) - FilterRemotePoolAdded(opts *bind.FilterOpts, remoteChainSelector []uint64) (*BurnMintTokenPoolRemotePoolAddedIterator, error) - - WatchRemotePoolAdded(opts *bind.WatchOpts, sink chan<- *BurnMintTokenPoolRemotePoolAdded, remoteChainSelector []uint64) (event.Subscription, error) - - ParseRemotePoolAdded(log types.Log) (*BurnMintTokenPoolRemotePoolAdded, error) - - FilterRemotePoolRemoved(opts *bind.FilterOpts, remoteChainSelector []uint64) (*BurnMintTokenPoolRemotePoolRemovedIterator, error) + FilterRemotePoolSet(opts *bind.FilterOpts, remoteChainSelector []uint64) (*BurnMintTokenPoolRemotePoolSetIterator, error) - WatchRemotePoolRemoved(opts *bind.WatchOpts, sink chan<- *BurnMintTokenPoolRemotePoolRemoved, remoteChainSelector []uint64) (event.Subscription, error) + WatchRemotePoolSet(opts *bind.WatchOpts, sink chan<- *BurnMintTokenPoolRemotePoolSet, remoteChainSelector []uint64) (event.Subscription, error) - ParseRemotePoolRemoved(log types.Log) (*BurnMintTokenPoolRemotePoolRemoved, error) + ParseRemotePoolSet(log types.Log) (*BurnMintTokenPoolRemotePoolSet, error) FilterRouterUpdated(opts *bind.FilterOpts) (*BurnMintTokenPoolRouterUpdatedIterator, error) diff --git a/core/gethwrappers/ccip/generated/burn_with_from_mint_token_pool/burn_with_from_mint_token_pool.go b/core/gethwrappers/ccip/generated/burn_with_from_mint_token_pool/burn_with_from_mint_token_pool.go index f00b6fb9abd..22409787fd8 100644 --- a/core/gethwrappers/ccip/generated/burn_with_from_mint_token_pool/burn_with_from_mint_token_pool.go +++ b/core/gethwrappers/ccip/generated/burn_with_from_mint_token_pool/burn_with_from_mint_token_pool.go @@ -74,22 +74,23 @@ type RateLimiterTokenBucket struct { type TokenPoolChainUpdate struct { RemoteChainSelector uint64 - RemotePoolAddresses [][]byte + Allowed bool + RemotePoolAddress []byte RemoteTokenAddress []byte OutboundRateLimiterConfig RateLimiterConfig InboundRateLimiterConfig RateLimiterConfig } var BurnWithFromMintTokenPoolMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[{\"internalType\":\"contractIBurnMintERC20\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"localTokenDecimals\",\"type\":\"uint8\"},{\"internalType\":\"address[]\",\"name\":\"allowlist\",\"type\":\"address[]\"},{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"capacity\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"requested\",\"type\":\"uint256\"}],\"name\":\"AggregateValueMaxCapacityExceeded\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"minWaitInSeconds\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"available\",\"type\":\"uint256\"}],\"name\":\"AggregateValueRateLimitReached\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"AllowListNotEnabled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"BucketOverfilled\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"CallerIsNotARampOnRouter\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CannotTransferToSelf\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"}],\"name\":\"ChainAlreadyExists\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"ChainNotAllowed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CursedByRMN\",\"type\":\"error\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"config\",\"type\":\"tuple\"}],\"name\":\"DisabledNonZeroRateLimit\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"expected\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"actual\",\"type\":\"uint8\"}],\"name\":\"InvalidDecimalArgs\",\"type\":\"error\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"rateLimiterConfig\",\"type\":\"tuple\"}],\"name\":\"InvalidRateLimitRate\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolData\",\"type\":\"bytes\"}],\"name\":\"InvalidRemoteChainDecimals\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"InvalidRemotePoolForChain\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"}],\"name\":\"InvalidSourcePoolAddress\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"InvalidToken\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MismatchedArrayLengths\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MustBeProposedOwner\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"NonExistentChain\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByOwner\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"remoteDecimals\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"localDecimals\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"remoteAmount\",\"type\":\"uint256\"}],\"name\":\"OverflowDetected\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OwnerCannotBeZero\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"PoolAlreadyAdded\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RateLimitMustBeDisabled\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"SenderNotAllowed\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"capacity\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"requested\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenAddress\",\"type\":\"address\"}],\"name\":\"TokenMaxCapacityExceeded\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"minWaitInSeconds\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"available\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenAddress\",\"type\":\"address\"}],\"name\":\"TokenRateLimitReached\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"Unauthorized\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"AllowListAdd\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"AllowListRemove\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Burned\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"remoteToken\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundRateLimiterConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundRateLimiterConfig\",\"type\":\"tuple\"}],\"name\":\"ChainAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundRateLimiterConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundRateLimiterConfig\",\"type\":\"tuple\"}],\"name\":\"ChainConfigured\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"ChainRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"config\",\"type\":\"tuple\"}],\"name\":\"ConfigChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Locked\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Minted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"rateLimitAdmin\",\"type\":\"address\"}],\"name\":\"RateLimitAdminSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Released\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"RemotePoolAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"RemotePoolRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"oldRouter\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newRouter\",\"type\":\"address\"}],\"name\":\"RouterUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokens\",\"type\":\"uint256\"}],\"name\":\"TokensConsumed\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"addRemotePool\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"removes\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"adds\",\"type\":\"address[]\"}],\"name\":\"applyAllowListUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64[]\",\"name\":\"remoteChainSelectorsToRemove\",\"type\":\"uint64[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes[]\",\"name\":\"remotePoolAddresses\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes\",\"name\":\"remoteTokenAddress\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundRateLimiterConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundRateLimiterConfig\",\"type\":\"tuple\"}],\"internalType\":\"structTokenPool.ChainUpdate[]\",\"name\":\"chainsToAdd\",\"type\":\"tuple[]\"}],\"name\":\"applyChainUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAllowList\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAllowListEnabled\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getCurrentInboundRateLimiterState\",\"outputs\":[{\"components\":[{\"internalType\":\"uint128\",\"name\":\"tokens\",\"type\":\"uint128\"},{\"internalType\":\"uint32\",\"name\":\"lastUpdated\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.TokenBucket\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getCurrentOutboundRateLimiterState\",\"outputs\":[{\"components\":[{\"internalType\":\"uint128\",\"name\":\"tokens\",\"type\":\"uint128\"},{\"internalType\":\"uint32\",\"name\":\"lastUpdated\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.TokenBucket\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRateLimitAdmin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getRemotePools\",\"outputs\":[{\"internalType\":\"bytes[]\",\"name\":\"\",\"type\":\"bytes[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getRemoteToken\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRmnProxy\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRouter\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getSupportedChains\",\"outputs\":[{\"internalType\":\"uint64[]\",\"name\":\"\",\"type\":\"uint64[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getToken\",\"outputs\":[{\"internalType\":\"contractIERC20\",\"name\":\"token\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getTokenDecimals\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"decimals\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"isRemotePool\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"isSupportedChain\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"isSupportedToken\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"originalSender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"localToken\",\"type\":\"address\"}],\"internalType\":\"structPool.LockOrBurnInV1\",\"name\":\"lockOrBurnIn\",\"type\":\"tuple\"}],\"name\":\"lockOrBurn\",\"outputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"destPoolData\",\"type\":\"bytes\"}],\"internalType\":\"structPool.LockOrBurnOutV1\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"originalSender\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"localToken\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"sourcePoolData\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"offchainTokenData\",\"type\":\"bytes\"}],\"internalType\":\"structPool.ReleaseOrMintInV1\",\"name\":\"releaseOrMintIn\",\"type\":\"tuple\"}],\"name\":\"releaseOrMint\",\"outputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"destinationAmount\",\"type\":\"uint256\"}],\"internalType\":\"structPool.ReleaseOrMintOutV1\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"removeRemotePool\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundConfig\",\"type\":\"tuple\"}],\"name\":\"setChainRateLimiterConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64[]\",\"name\":\"remoteChainSelectors\",\"type\":\"uint64[]\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config[]\",\"name\":\"outboundConfigs\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config[]\",\"name\":\"inboundConfigs\",\"type\":\"tuple[]\"}],\"name\":\"setChainRateLimiterConfigs\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"rateLimitAdmin\",\"type\":\"address\"}],\"name\":\"setRateLimitAdmin\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newRouter\",\"type\":\"address\"}],\"name\":\"setRouter\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"pure\",\"type\":\"function\"}]", - Bin: "0x610100806040523461035457614bb5803803809161001d82856105b2565b8339810160a0828203126103545781516001600160a01b03811692908390036103545761004c602082016105d5565b60408201516001600160401b0381116103545782019280601f85011215610354578351936001600160401b038511610359578460051b90602082019561009560405197886105b2565b865260208087019282010192831161035457602001905b82821061059a575050506100ce60806100c7606085016105e3565b93016105e3565b91331561058957600180546001600160a01b0319163317905584158015610578575b8015610567575b61055657608085905260c05260405163313ce56760e01b8152602081600481885afa6000918161051a575b506104ef575b5060a052600480546001600160a01b0319166001600160a01b03929092169190911790558051151560e08190526103d2575b50604051636eb1769f60e11b81523060048201819052602482015290602082604481845afa9182156103c657600092610392575b50600019820180921161037c57604051602081019263095ea7b360e01b84523060248301526044820152604481526101c76064826105b2565b6000806040948551936101da87866105b2565b602085527f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65646020860152519082865af13d1561036f573d906001600160401b03821161035957845161024b94909261023c601f8201601f1916602001856105b2565b83523d6000602085013e610781565b8051806102d9575b8251614363908161085282396080518181816115fc015281816117e80152818161220e015281816123ea01528181612707015261277f015260a0518181816118a90152818161268e0152818161316801526131eb015260c051818181610bd50152818161169801526122a9015260e051818181610b65015281816116db01526120050152f35b81602091810103126103545760200151801590811503610354576102fe573880610253565b5162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608490fd5b600080fd5b634e487b7160e01b600052604160045260246000fd5b9161024b92606091610781565b634e487b7160e01b600052601160045260246000fd5b9091506020813d6020116103be575b816103ae602093836105b2565b810103126103545751903861018e565b3d91506103a1565b6040513d6000823e3d90fd5b60206040516103e182826105b2565b60008152600036813760e051156104de5760005b815181101561045c576001906001600160a01b0361041382856105f7565b51168461041f82610639565b61042c575b5050016103f5565b7f800671136ab6cfee9fbe5ed1fb7ca417811aca3cf864800d127b927adedf756691604051908152a13884610424565b505060005b82518110156104d5576001906001600160a01b0361047f82866105f7565b511680156104cf578361049182610721565b61049f575b50505b01610461565b7f2640d4d76caf8bf478aabfa982fa4e1c4eb71a37f93cd15e80dbc657911546d891604051908152a13883610496565b50610499565b5050503861015a565b6335f4a7b360e01b60005260046000fd5b60ff1660ff82168181036105035750610128565b6332ad3e0760e11b60005260045260245260446000fd5b9091506020813d60201161054e575b81610536602093836105b2565b8101031261035457610547906105d5565b9038610122565b3d9150610529565b6342bcdf7f60e11b60005260046000fd5b506001600160a01b038116156100f7565b506001600160a01b038316156100f0565b639b15e16f60e01b60005260046000fd5b602080916105a7846105e3565b8152019101906100ac565b601f909101601f19168101906001600160401b0382119082101761035957604052565b519060ff8216820361035457565b51906001600160a01b038216820361035457565b805182101561060b5760209160051b010190565b634e487b7160e01b600052603260045260246000fd5b805482101561060b5760005260206000200190600090565b600081815260036020526040902054801561071a57600019810181811161037c5760025460001981019190821161037c578181036106c9575b50505060025480156106b3576000190161068d816002610621565b8154906000199060031b1b19169055600255600052600360205260006040812055600190565b634e487b7160e01b600052603160045260246000fd5b6107026106da6106eb936002610621565b90549060031b1c9283926002610621565b819391549060031b91821b91600019901b19161790565b90556000526003602052604060002055388080610672565b5050600090565b8060005260036020526040600020541560001461077b5760025468010000000000000000811015610359576107626106eb8260018594016002556002610621565b9055600254906000526003602052604060002055600190565b50600090565b919290156107e35750815115610795575090565b3b1561079e5790565b60405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606490fd5b8251909150156107f65750805190602001fd5b6040519062461bcd60e51b8252602060048301528181519182602483015260005b8381106108395750508160006044809484010152601f80199101168101030190fd5b6020828201810151604487840101528593500161081756fe608080604052600436101561001357600080fd5b600090813560e01c90816301ffc9a71461282257508063181f5a77146127a357806321df0da714612734578063240028e8146126b257806324f65ee71461265657806339077537146121685780634c5ef0ed1461214e57806354c8a4f314611fd157806362ddd3c414611f4d5780636d3d1a5814611efb57806379ba509714611e165780637d54534e14611d695780638926f54f14611d055780638da5cb5b14611cb3578063962d402014611b0f5780639a4575b914611554578063a42a7b8b146113cf578063a7cd63b714611303578063acfecf91146111df578063af58d59f14611178578063b0f479a114611126578063b7946580146110cf578063c0d7865514610fd7578063c4bffe2b14610e8e578063c75eea9c14610dc8578063cf7401f314610bf9578063dc0bd97114610b8a578063e0351e1314610b2f578063e8a1da171461025a5763f2fde38b1461016b57600080fd5b346102575760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102575773ffffffffffffffffffffffffffffffffffffffff6101b7612970565b6101bf6132f5565b1633811461022f57807fffffffffffffffffffffffff000000000000000000000000000000000000000083541617825573ffffffffffffffffffffffffffffffffffffffff600154167fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12788380a380f35b6004827fdad89dca000000000000000000000000000000000000000000000000000000008152fd5b80fd5b50346102575761026936612a5e565b939190926102756132f5565b82915b80831061099a575050508063ffffffff4216917ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffee1843603015b85821015610996578160051b85013581811215610992578501906101208236031261099257604051956102e387612b66565b823567ffffffffffffffff8116810361098d578752602083013567ffffffffffffffff81116109895783019536601f880112156109895786359661032688612d6a565b97610334604051998a612b9e565b8089526020808a019160051b830101903682116109855760208301905b828210610952575050505060208801968752604084013567ffffffffffffffff811161094e5761038490369086016130c2565b9860408901998a526103ae61039c3660608801612bfc565b9560608b0196875260c0369101612bfc565b9660808a019788526103c0865161376c565b6103ca885161376c565b8a515115610926576103e667ffffffffffffffff8b5116613fbf565b156108ef5767ffffffffffffffff8a5116815260076020526040812061052687516fffffffffffffffffffffffffffffffff604082015116906104e16fffffffffffffffffffffffffffffffff6020830151169151151583608060405161044c81612b66565b858152602081018c905260408101849052606081018690520152855474ff000000000000000000000000000000000000000091151560a01b919091167fffffffffffffffffffffff0000000000000000000000000000000000000000009091166fffffffffffffffffffffffffffffffff84161773ffffffff0000000000000000000000000000000060808b901b1617178555565b60809190911b7fffffffffffffffffffffffffffffffff00000000000000000000000000000000166fffffffffffffffffffffffffffffffff91909116176001830155565b61064c89516fffffffffffffffffffffffffffffffff604082015116906106076fffffffffffffffffffffffffffffffff6020830151169151151583608060405161057081612b66565b858152602081018c9052604081018490526060810186905201526002860180547fffffffffffffffffffffff000000000000000000000000000000000000000000166fffffffffffffffffffffffffffffffff85161773ffffffff0000000000000000000000000000000060808c901b161791151560a01b74ff000000000000000000000000000000000000000016919091179055565b60809190911b7fffffffffffffffffffffffffffffffff00000000000000000000000000000000166fffffffffffffffffffffffffffffffff91909116176003830155565b60048c5191019080519067ffffffffffffffff82116108c25761066f8354612e62565b601f8111610887575b50602090601f83116001146107e8576106c692918591836107dd575b50507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8260011b9260031b1c19161790565b90555b805b8951805182101561070157906106fb6001926106f4838f67ffffffffffffffff90511692612e4e565b5190613340565b016106cb565b5050975097987f8d340f17e19058004c20453540862a9c62778504476f6756755cb33bcd6c38c2929593966107cf67ffffffffffffffff600197949c511692519351915161079b61076660405196879687526101006020880152610100870190612911565b9360408601906fffffffffffffffffffffffffffffffff60408092805115158552826020820151166020860152015116910152565b60a08401906fffffffffffffffffffffffffffffffff60408092805115158552826020820151166020860152015116910152565b0390a10190939492916102b1565b015190503880610694565b83855281852091907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08416865b81811061086f5750908460019594939210610838575b505050811b0190556106c9565b01517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88460031b161c1916905538808061082b565b92936020600181928786015181550195019301610815565b6108b29084865260208620601f850160051c810191602086106108b8575b601f0160051c0190613069565b38610678565b90915081906108a5565b6024847f4e487b710000000000000000000000000000000000000000000000000000000081526041600452fd5b60249067ffffffffffffffff8b51167f1d5ad3c5000000000000000000000000000000000000000000000000000000008252600452fd5b807f8579befe0000000000000000000000000000000000000000000000000000000060049252fd5b8680fd5b813567ffffffffffffffff81116109815760209161097683928336918901016130c2565b815201910190610351565b8a80fd5b8880fd5b8580fd5b600080fd5b8380fd5b8280f35b9092919367ffffffffffffffff6109ba6109b5878588612dea565b612e29565b16956109c587613cf3565b15610b035786845260076020526109e160056040862001613afa565b94845b8651811015610a1a576001908987526007602052610a1360056040892001610a0c838b612e4e565b5190613e1e565b50016109e4565b5093945094909580855260076020526005604086208681558660018201558660028201558660038201558660048201610a538154612e62565b80610ac2575b5050500180549086815581610aa4575b5050907f5204aec90a3c794d8e90fded8b46ae9c7c552803e7e832e0c1d358396d8599166020600193604051908152a1019190949394610278565b865260208620908101905b81811015610a6957868155600101610aaf565b601f8111600114610ad85750555b863880610a59565b81835260208320610af391601f01861c810190600101613069565b8082528160208120915555610ad0565b602484887f1e670e4b000000000000000000000000000000000000000000000000000000008252600452fd5b503461025757807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102575760206040517f000000000000000000000000000000000000000000000000000000000000000015158152f35b503461025757807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261025757602060405173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b50346102575760e07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261025757610c31612993565b9060607fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdc36011261025757604051610c6881612b82565b6024358015158103610dc45781526044356fffffffffffffffffffffffffffffffff81168103610dc45760208201526064356fffffffffffffffffffffffffffffffff81168103610dc457604082015260607fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7c360112610dc05760405190610cef82612b82565b608435801515810361099257825260a4356fffffffffffffffffffffffffffffffff8116810361099257602083015260c4356fffffffffffffffffffffffffffffffff8116810361099257604083015273ffffffffffffffffffffffffffffffffffffffff6009541633141580610d9e575b610d7257610d6f92936135aa565b80f35b6024837f8e4a23d600000000000000000000000000000000000000000000000000000000815233600452fd5b5073ffffffffffffffffffffffffffffffffffffffff60015416331415610d61565b5080fd5b8280fd5b50346102575760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261025757610e31610e2c6040610e8a9367ffffffffffffffff610e15612993565b610e1d612fb6565b50168152600760205220612fe1565b6136e7565b6040519182918291909160806fffffffffffffffffffffffffffffffff8160a084019582815116855263ffffffff6020820151166020860152604081015115156040860152826060820151166060860152015116910152565b0390f35b503461025757807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261025757604051906005548083528260208101600584526020842092845b818110610fbe575050610eec92500383612b9e565b8151610f10610efa82612d6a565b91610f086040519384612b9e565b808352612d6a565b917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0602083019301368437805b8451811015610f6f578067ffffffffffffffff610f5c60019388612e4e565b5116610f688286612e4e565b5201610f3d565b50925090604051928392602084019060208552518091526040840192915b818110610f9b575050500390f35b825167ffffffffffffffff16845285945060209384019390920191600101610f8d565b8454835260019485019487945060209093019201610ed7565b50346102575760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102575773ffffffffffffffffffffffffffffffffffffffff611024612970565b61102c6132f5565b1680156110a75760407f02dc5c233404867c793b749c6d644beb2277536d18a7e7974d3f238e4c6f16849160045490807fffffffffffffffffffffffff000000000000000000000000000000000000000083161760045573ffffffffffffffffffffffffffffffffffffffff8351921682526020820152a180f35b6004827f8579befe000000000000000000000000000000000000000000000000000000008152fd5b50346102575760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261025757610e8a61111261110d612993565b613047565b604051918291602083526020830190612911565b503461025757807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261025757602073ffffffffffffffffffffffffffffffffffffffff60045416604051908152f35b50346102575760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261025757610e31610e2c60026040610e8a9467ffffffffffffffff6111c7612993565b6111cf612fb6565b5016815260076020522001612fe1565b50346102575767ffffffffffffffff6111f7366129aa565b9290916112026132f5565b169161121b836000526006602052604060002054151590565b156112d757828452600760205261124a6005604086200161123d368486612c99565b6020815191012090613e1e565b1561128f57907f52d00ee4d9bd51b40168f2afc5848837288ce258784ad914278791464b3f4d7691611289604051928392602084526020840191612f77565b0390a280f35b826112d3836040519384937f74f23c7c0000000000000000000000000000000000000000000000000000000085526004850152604060248501526044840191612f77565b0390fd5b602484847f1e670e4b000000000000000000000000000000000000000000000000000000008252600452fd5b503461025757807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261025757604051600254808252602082018091600285526020852090855b8181106113b95750505082611362910383612b9e565b604051928392602084019060208552518091526040840192915b81811061138a575050500390f35b825173ffffffffffffffffffffffffffffffffffffffff1684528594506020938401939092019160010161137c565b825484526020909301926001928301920161134c565b50346102575760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102575767ffffffffffffffff611410612993565b168152600760205261142760056040832001613afa565b80517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe061146c61145683612d6a565b926114646040519485612b9e565b808452612d6a565b01835b818110611543575050825b82518110156114c0578061149060019285612e4e565b51855260086020526114a460408620612eb5565b6114ae8285612e4e565b526114b98184612e4e565b500161147a565b81846040519182916020830160208452825180915260408401602060408360051b870101940192905b8282106114f857505050500390f35b91936020611533827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc060019597998495030186528851612911565b96019201920185949391926114e9565b80606060208093860101520161146f565b50346102575760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102575760043567ffffffffffffffff8111610dc05760a07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc8236030112610dc057606060206040516115d281612b4a565b8281520152608481016115e481612cfe565b73ffffffffffffffffffffffffffffffffffffffff807f000000000000000000000000000000000000000000000000000000000000000016911603611ac55750602481019177ffffffffffffffff0000000000000000000000000000000061164b84612e29565b60801b16604051907f2cbc26bb000000000000000000000000000000000000000000000000000000008252600482015260208160248173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000165afa908115611955578291611a96575b50611a6e576116d960448301612cfe565b7f0000000000000000000000000000000000000000000000000000000000000000611a1b575b5067ffffffffffffffff61171284612e29565b1661172a816000526006602052604060002054151590565b156119ef57602073ffffffffffffffffffffffffffffffffffffffff60045416916024604051809481937fa8d87a3b00000000000000000000000000000000000000000000000000000000835260048301525afa801561195557829061198c575b73ffffffffffffffffffffffffffffffffffffffff91501633036119605767ffffffffffffffff60646117bd85612e29565b930135921681526007602052816118106040832073ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001692839161406e565b803b15610dc0576040517f9dc29fac000000000000000000000000000000000000000000000000000000008152306004820152602481018490529082908290604490829084905af1801561195557611940575b61190f61189f61110d86866040519081527f696de425f79f4a40bc6d2122ca50507f0efbeabbff86a84871b7196ab8ea8df760203392a2612e29565b610e8a60405160ff7f0000000000000000000000000000000000000000000000000000000000000000166020820152602081526118dd604082612b9e565b604051926118ea84612b4a565b8352602083019081526040519384936020855251604060208601526060850190612911565b90517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0848303016040850152612911565b61194b828092612b9e565b6102575780611863565b6040513d84823e3d90fd5b807f728fe07b000000000000000000000000000000000000000000000000000000006024925233600452fd5b506020813d6020116119e7575b816119a660209383612b9e565b81010312610dc0575173ffffffffffffffffffffffffffffffffffffffff81168103610dc05773ffffffffffffffffffffffffffffffffffffffff9061178b565b3d9150611999565b602492507fa9902c7e000000000000000000000000000000000000000000000000000000008252600452fd5b73ffffffffffffffffffffffffffffffffffffffff16808252600360205260408220546116ff57602492507fd0d25976000000000000000000000000000000000000000000000000000000008252600452fd5b807f53ad11d80000000000000000000000000000000000000000000000000000000060049252fd5b611ab8915060203d602011611abe575b611ab08183612b9e565b8101906130dd565b386116c8565b503d611aa6565b8273ffffffffffffffffffffffffffffffffffffffff611ae6602493612cfe565b7f961c9a4f00000000000000000000000000000000000000000000000000000000835216600452fd5b50346102575760607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102575760043567ffffffffffffffff8111610dc057611b5f903690600401612a2d565b60243567ffffffffffffffff811161099257611b7f903690600401612ace565b60449291923567ffffffffffffffff811161098957611ba2903690600401612ace565b91909273ffffffffffffffffffffffffffffffffffffffff6009541633141580611c91575b611c6557818114801590611c5b575b611c3357865b818110611be7578780f35b80611c2d611bfb6109b5600194868c612dea565b611c0683878b612e3e565b611c27611c1f611c17868b8d612e3e565b923690612bfc565b913690612bfc565b916135aa565b01611bdc565b6004877f568efce2000000000000000000000000000000000000000000000000000000008152fd5b5082811415611bd6565b6024877f8e4a23d600000000000000000000000000000000000000000000000000000000815233600452fd5b5073ffffffffffffffffffffffffffffffffffffffff60015416331415611bc7565b503461025757807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261025757602073ffffffffffffffffffffffffffffffffffffffff60015416604051908152f35b50346102575760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610257576020611d5f67ffffffffffffffff611d4b612993565b166000526006602052604060002054151590565b6040519015158152f35b50346102575760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610257577f44676b5284b809a22248eba0da87391d79098be38bb03154be88a58bf4d09174602073ffffffffffffffffffffffffffffffffffffffff611dd9612970565b611de16132f5565b16807fffffffffffffffffffffffff00000000000000000000000000000000000000006009541617600955604051908152a180f35b503461025757807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261025757805473ffffffffffffffffffffffffffffffffffffffff81163303611ed3577fffffffffffffffffffffffff000000000000000000000000000000000000000060015491338284161760015516825573ffffffffffffffffffffffffffffffffffffffff3391167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08380a380f35b6004827f02b543c6000000000000000000000000000000000000000000000000000000008152fd5b503461025757807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261025757602073ffffffffffffffffffffffffffffffffffffffff60095416604051908152f35b503461025757611f5c366129aa565b611f68939291936132f5565b67ffffffffffffffff8216611f8a816000526006602052604060002054151590565b15611fa65750610d6f9293611fa0913691612c99565b90613340565b7f1e670e4b000000000000000000000000000000000000000000000000000000008452600452602483fd5b503461025757611ffb90612003611fe736612a5e565b9591611ff49391936132f5565b3691612d82565b933691612d82565b7f00000000000000000000000000000000000000000000000000000000000000001561212657815b835181101561209e578073ffffffffffffffffffffffffffffffffffffffff61205660019387612e4e565b511661206181613b5d565b61206d575b500161202b565b60207f800671136ab6cfee9fbe5ed1fb7ca417811aca3cf864800d127b927adedf756691604051908152a138612066565b5090805b8251811015612122578073ffffffffffffffffffffffffffffffffffffffff6120cd60019386612e4e565b5116801561211c576120de81613f5f565b6120eb575b505b016120a2565b60207f2640d4d76caf8bf478aabfa982fa4e1c4eb71a37f93cd15e80dbc657911546d891604051908152a1846120e3565b506120e5565b5080f35b6004827f35f4a7b3000000000000000000000000000000000000000000000000000000008152fd5b5034610257576020611d5f612162366129aa565b91612d1f565b50346102575760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102575760043567ffffffffffffffff8111610dc057806004016101007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc8336030112610dc457826040516121e881612aff565b52608482016121f681612cfe565b73ffffffffffffffffffffffffffffffffffffffff807f00000000000000000000000000000000000000000000000000000000000000001691160361263557506024820177ffffffffffffffff0000000000000000000000000000000061225c82612e29565b60801b16604051907f2cbc26bb000000000000000000000000000000000000000000000000000000008252600482015260208160248173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000165afa9081156125b8578591612616575b506125ee5767ffffffffffffffff6122f082612e29565b16612308816000526006602052604060002054151590565b156125c357602073ffffffffffffffffffffffffffffffffffffffff60045416916044604051809481937f83826b2b00000000000000000000000000000000000000000000000000000000835260048301523360248301525afa9081156125b8578591612599575b501561256d5761237f81612e29565b61239160a48501916121628386612c48565b15612526575061242e67ffffffffffffffff9261242861242361241c6123b8604496612e29565b936064890135978895168a526007602052612412600260408c200173ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016998a9161406e565b60c4890190612c48565b3691612c99565b6130f5565b906131e8565b9201908361243b83612cfe565b823b15610dc0576040517f40c10f1900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff91909116600482015260248101859052918290604490829084905af1801561251b57916020946124c99273ffffffffffffffffffffffffffffffffffffffff9461250b575b5050612cfe565b166040518281527f9d228d69b5fdb8d273a2336f8fb8612d039631024ea9bf09c424a9503aa078f0843392a38060405161250281612aff565b52604051908152f35b8161251591612b9e565b386124c2565b6040513d86823e3d90fd5b6125309083612c48565b6112d36040519283927f24eb47e5000000000000000000000000000000000000000000000000000000008452602060048501526024840191612f77565b6024847f728fe07b00000000000000000000000000000000000000000000000000000000815233600452fd5b6125b2915060203d602011611abe57611ab08183612b9e565b38612370565b6040513d87823e3d90fd5b7fa9902c7e000000000000000000000000000000000000000000000000000000008552600452602484fd5b6004847f53ad11d8000000000000000000000000000000000000000000000000000000008152fd5b61262f915060203d602011611abe57611ab08183612b9e565b386122d9565b8373ffffffffffffffffffffffffffffffffffffffff611ae6602493612cfe565b503461025757807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261025757602060405160ff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b50346102575760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610257576020906126ed612970565b905073ffffffffffffffffffffffffffffffffffffffff807f0000000000000000000000000000000000000000000000000000000000000000169116146040519015158152f35b503461025757807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261025757602060405173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b503461025757807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102575750610e8a6040516127e4604082612b9e565b601f81527f4275726e5769746846726f6d4d696e74546f6b656e506f6f6c20312e352e31006020820152604051918291602083526020830190612911565b905034610dc05760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610dc0576004357fffffffff000000000000000000000000000000000000000000000000000000008116809103610dc457602092507faff2afbf0000000000000000000000000000000000000000000000000000000081149081156128e7575b81156128bd575b5015158152f35b7f01ffc9a700000000000000000000000000000000000000000000000000000000915014386128b6565b7f0e64dd2900000000000000000000000000000000000000000000000000000000811491506128af565b919082519283825260005b84811061295b5750507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8460006020809697860101520116010190565b8060208092840101518282860101520161291c565b6004359073ffffffffffffffffffffffffffffffffffffffff8216820361098d57565b6004359067ffffffffffffffff8216820361098d57565b60407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc82011261098d5760043567ffffffffffffffff8116810361098d579160243567ffffffffffffffff811161098d578260238201121561098d5780600401359267ffffffffffffffff841161098d576024848301011161098d576024019190565b9181601f8401121561098d5782359167ffffffffffffffff831161098d576020808501948460051b01011161098d57565b60407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc82011261098d5760043567ffffffffffffffff811161098d5781612aa791600401612a2d565b929092916024359067ffffffffffffffff821161098d57612aca91600401612a2d565b9091565b9181601f8401121561098d5782359167ffffffffffffffff831161098d576020808501946060850201011161098d57565b6020810190811067ffffffffffffffff821117612b1b57604052565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040810190811067ffffffffffffffff821117612b1b57604052565b60a0810190811067ffffffffffffffff821117612b1b57604052565b6060810190811067ffffffffffffffff821117612b1b57604052565b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff821117612b1b57604052565b35906fffffffffffffffffffffffffffffffff8216820361098d57565b919082606091031261098d57604051612c1481612b82565b8092803590811515820361098d576040612c439181938552612c3860208201612bdf565b602086015201612bdf565b910152565b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18136030182121561098d570180359067ffffffffffffffff821161098d5760200191813603831361098d57565b92919267ffffffffffffffff8211612b1b5760405191612ce1601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200184612b9e565b82948184528183011161098d578281602093846000960137010152565b3573ffffffffffffffffffffffffffffffffffffffff8116810361098d5790565b612d67929167ffffffffffffffff612d4a921660005260076020526005604060002001923691612c99565b602081519101209060019160005201602052604060002054151590565b90565b67ffffffffffffffff8111612b1b5760051b60200190565b9291612d8d82612d6a565b93612d9b6040519586612b9e565b602085848152019260051b810191821161098d57915b818310612dbd57505050565b823573ffffffffffffffffffffffffffffffffffffffff8116810361098d57815260209283019201612db1565b9190811015612dfa5760051b0190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b3567ffffffffffffffff8116810361098d5790565b9190811015612dfa576060020190565b8051821015612dfa5760209160051b010190565b90600182811c92168015612eab575b6020831014612e7c57565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b91607f1691612e71565b9060405191826000825492612ec984612e62565b8084529360018116908115612f375750600114612ef0575b50612eee92500383612b9e565b565b90506000929192526020600020906000915b818310612f1b575050906020612eee9282010138612ee1565b6020919350806001915483858901015201910190918492612f02565b60209350612eee9592507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0091501682840152151560051b82010138612ee1565b601f82602094937fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0938186528686013760008582860101520116010190565b60405190612fc382612b66565b60006080838281528260208201528260408201528260608201520152565b90604051612fee81612b66565b60806001829460ff81546fffffffffffffffffffffffffffffffff8116865263ffffffff81861c16602087015260a01c161515604085015201546fffffffffffffffffffffffffffffffff81166060840152811c910152565b67ffffffffffffffff166000526007602052612d676004604060002001612eb5565b818110613074575050565b60008155600101613069565b8181029291811591840414171561309357565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b9080601f8301121561098d57816020612d6793359101612c99565b9081602091031261098d5751801515810361098d5790565b80518015613164576020036131265760208180518101031261098d5760208101519060ff8211613126575060ff1690565b6112d3906040519182917f953576f7000000000000000000000000000000000000000000000000000000008352602060048401526024830190612911565b50507f000000000000000000000000000000000000000000000000000000000000000090565b9060ff8091169116039060ff821161309357565b60ff16604d811161309357600a0a90565b81156131b9570490565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b907f00000000000000000000000000000000000000000000000000000000000000009060ff82169060ff8116928284146132ee578284116132c4579061322d9161318a565b91604d60ff841611801561328b575b6132555750509061324f612d679261319e565b90613080565b9091507fa9cb113d0000000000000000000000000000000000000000000000000000000060005260045260245260445260646000fd5b506132958361319e565b80156131b9577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04841161323c565b6132cd9161318a565b91604d60ff841611613255575050906132e8612d679261319e565b906131af565b5050505090565b73ffffffffffffffffffffffffffffffffffffffff60015416330361331657565b7f2b5c74de0000000000000000000000000000000000000000000000000000000060005260046000fd5b908051156135805767ffffffffffffffff81516020830120921691826000526007602052613375816005604060002001614019565b1561353c5760005260086020526040600020815167ffffffffffffffff8111612b1b576133a28254612e62565b601f811161350a575b506020601f8211600114613444579161341e827f7d628c9a1796743d365ab521a8b2a4686e419b3269919dc9145ea2ce853b54ea959361343495600091613439575b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8260011b9260031b1c19161790565b9055604051918291602083526020830190612911565b0390a2565b9050840151386133ed565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe082169083600052806000209160005b8181106134f25750926134349492600192827f7d628c9a1796743d365ab521a8b2a4686e419b3269919dc9145ea2ce853b54ea9896106134bb575b5050811b019055611112565b8501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88460031b161c1916905538806134af565b9192602060018192868a015181550194019201613474565b61353690836000526020600020601f840160051c810191602085106108b857601f0160051c0190613069565b386133ab565b50906112d36040519283927f393b8ad20000000000000000000000000000000000000000000000000000000084526004840152604060248401526044830190612911565b7f8579befe0000000000000000000000000000000000000000000000000000000060005260046000fd5b67ffffffffffffffff1660008181526006602052604090205490929190156136ac57916136a960e092613675856136017f0350d63aa5f270e01729d00d627eeb8f3429772b1818c016c66a588a864f912b9761376c565b8460005260076020526136188160406000206138c7565b6136218361376c565b84600052600760205261363b8360026040600020016138c7565b60405194855260208501906fffffffffffffffffffffffffffffffff60408092805115158552826020820151166020860152015116910152565b60808301906fffffffffffffffffffffffffffffffff60408092805115158552826020820151166020860152015116910152565ba1565b827f1e670e4b0000000000000000000000000000000000000000000000000000000060005260045260246000fd5b9190820391821161309357565b6136ef612fb6565b506fffffffffffffffffffffffffffffffff6060820151166fffffffffffffffffffffffffffffffff808351169161374c602085019361374661373963ffffffff875116426136da565b8560808901511690613080565b90613f52565b8082101561376557505b16825263ffffffff4216905290565b9050613756565b805115613820576fffffffffffffffffffffffffffffffff6040820151166fffffffffffffffffffffffffffffffff602083015116811090811591613817575b506137b45750565b606490613815604051917f8020d12400000000000000000000000000000000000000000000000000000000835260048301906fffffffffffffffffffffffffffffffff60408092805115158552826020820151166020860152015116910152565bfd5b905015386137ac565b6fffffffffffffffffffffffffffffffff604082015116158015906138a8575b6138475750565b606490613815604051917fd68af9cc00000000000000000000000000000000000000000000000000000000835260048301906fffffffffffffffffffffffffffffffff60408092805115158552826020820151166020860152015116910152565b506fffffffffffffffffffffffffffffffff6020820151161515613840565b7f9ea3374b67bf275e6bb9c8ae68f9cae023e1c528b4b27e092f0bb209d3531c1991613a00606092805461390463ffffffff8260801c16426136da565b9081613a3f575b50506fffffffffffffffffffffffffffffffff6001816020860151169282815416808510600014613a3757508280855b16167fffffffffffffffffffffffffffffffff000000000000000000000000000000008254161781556139b48651151582907fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff74ff0000000000000000000000000000000000000000835492151560a01b169116179055565b60408601517fffffffffffffffffffffffffffffffff0000000000000000000000000000000060809190911b16939092166fffffffffffffffffffffffffffffffff1692909217910155565b6136a960405180926fffffffffffffffffffffffffffffffff60408092805115158552826020820151166020860152015116910152565b83809161393b565b6fffffffffffffffffffffffffffffffff91613a74839283613a6d6001880154948286169560801c90613080565b9116613f52565b80821015613af357505b83547fffffffffffffffffffffffff00000000ffffffffffffffffffffffffffffffff9290911692909216167fffffffffffffffffffffffff0000000000000000000000000000000000000000909116174260801b73ffffffff0000000000000000000000000000000016178155388061390b565b9050613a7e565b906040519182815491828252602082019060005260206000209260005b818110613b2c575050612eee92500383612b9e565b8454835260019485019487945060209093019201613b17565b8054821015612dfa5760005260206000200190600090565b6000818152600360205260409020548015613cec577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff810181811161309357600254907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820191821161309357818103613c7d575b5050506002548015613c4e577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01613c0b816002613b45565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82549160031b1b19169055600255600052600360205260006040812055600190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b613cd4613c8e613c9f936002613b45565b90549060031b1c9283926002613b45565b81939154907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9060031b92831b921b19161790565b90556000526003602052604060002055388080613bd2565b5050600090565b6000818152600660205260409020548015613cec577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff810181811161309357600554907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820191821161309357818103613de4575b5050506005548015613c4e577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01613da1816005613b45565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82549160031b1b19169055600555600052600660205260006040812055600190565b613e06613df5613c9f936005613b45565b90549060031b1c9283926005613b45565b90556000526006602052604060002055388080613d68565b9060018201918160005282602052604060002054801515600014613f49577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8101818111613093578254907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820191821161309357818103613f12575b50505080548015613c4e577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190613ed38282613b45565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82549160031b1b191690555560005260205260006040812055600190565b613f32613f22613c9f9386613b45565b90549060031b1c92839286613b45565b905560005283602052604060002055388080613e9b565b50505050600090565b9190820180921161309357565b80600052600360205260406000205415600014613fb95760025468010000000000000000811015612b1b57613fa0613c9f8260018594016002556002613b45565b9055600254906000526003602052604060002055600190565b50600090565b80600052600660205260406000205415600014613fb95760055468010000000000000000811015612b1b57614000613c9f8260018594016005556005613b45565b9055600554906000526006602052604060002055600190565b6000828152600182016020526040902054613cec5780549068010000000000000000821015612b1b5782614057613c9f846001809601855584613b45565b905580549260005201602052604060002055600190565b929192805460ff8160a01c1615801561434e575b614347576fffffffffffffffffffffffffffffffff811690600183019081546140c763ffffffff6fffffffffffffffffffffffffffffffff83169360801c16426136da565b90816142a9575b5050848110614227575083821061415657507f1871cdf8010e63f2eb8384381a68dfa7416dc571a5517e66e88b2d2d0c0a690a939450906fffffffffffffffffffffffffffffffff8061412485602096956136da565b16167fffffffffffffffffffffffffffffffff00000000000000000000000000000000825416179055604051908152a1565b81945061416892505460801c926136da565b907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff810190808211613093576141b66141bb9273ffffffffffffffffffffffffffffffffffffffff94613f52565b6131af565b92169182156141f7577fd0c8d23a0000000000000000000000000000000000000000000000000000000060005260045260245260445260646000fd5b7f15279c080000000000000000000000000000000000000000000000000000000060005260045260245260446000fd5b8473ffffffffffffffffffffffffffffffffffffffff8816918215614279577f1a76572a0000000000000000000000000000000000000000000000000000000060005260045260245260445260646000fd5b7ff94ebcd10000000000000000000000000000000000000000000000000000000060005260045260245260446000fd5b82859293951161431d576142c4926137469160801c90613080565b808310156143185750815b83547fffffffffffffffffffffffff00000000ffffffffffffffffffffffffffffffff164260801b73ffffffff00000000000000000000000000000000161784559138806140ce565b6142cf565b7f9725942a0000000000000000000000000000000000000000000000000000000060005260046000fd5b5050509050565b50821561408256fea164736f6c634300081a000a", + ABI: "[{\"inputs\":[{\"internalType\":\"contractIBurnMintERC20\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"address[]\",\"name\":\"allowlist\",\"type\":\"address[]\"},{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"capacity\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"requested\",\"type\":\"uint256\"}],\"name\":\"AggregateValueMaxCapacityExceeded\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"minWaitInSeconds\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"available\",\"type\":\"uint256\"}],\"name\":\"AggregateValueRateLimitReached\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"AllowListNotEnabled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"BucketOverfilled\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"CallerIsNotARampOnRouter\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CannotTransferToSelf\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"}],\"name\":\"ChainAlreadyExists\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"ChainNotAllowed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CursedByRMN\",\"type\":\"error\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"config\",\"type\":\"tuple\"}],\"name\":\"DisabledNonZeroRateLimit\",\"type\":\"error\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"rateLimiterConfig\",\"type\":\"tuple\"}],\"name\":\"InvalidRateLimitRate\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"}],\"name\":\"InvalidSourcePoolAddress\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"InvalidToken\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MustBeProposedOwner\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"NonExistentChain\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByOwner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OwnerCannotBeZero\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RateLimitMustBeDisabled\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"SenderNotAllowed\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"capacity\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"requested\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenAddress\",\"type\":\"address\"}],\"name\":\"TokenMaxCapacityExceeded\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"minWaitInSeconds\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"available\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenAddress\",\"type\":\"address\"}],\"name\":\"TokenRateLimitReached\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"Unauthorized\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"AllowListAdd\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"AllowListRemove\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Burned\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"remoteToken\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundRateLimiterConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundRateLimiterConfig\",\"type\":\"tuple\"}],\"name\":\"ChainAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundRateLimiterConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundRateLimiterConfig\",\"type\":\"tuple\"}],\"name\":\"ChainConfigured\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"ChainRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"config\",\"type\":\"tuple\"}],\"name\":\"ConfigChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Locked\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Minted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"rateLimitAdmin\",\"type\":\"address\"}],\"name\":\"RateLimitAdminSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Released\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"previousPoolAddress\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"RemotePoolSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"oldRouter\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newRouter\",\"type\":\"address\"}],\"name\":\"RouterUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokens\",\"type\":\"uint256\"}],\"name\":\"TokensConsumed\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"removes\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"adds\",\"type\":\"address[]\"}],\"name\":\"applyAllowListUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"allowed\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"remoteTokenAddress\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundRateLimiterConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundRateLimiterConfig\",\"type\":\"tuple\"}],\"internalType\":\"structTokenPool.ChainUpdate[]\",\"name\":\"chains\",\"type\":\"tuple[]\"}],\"name\":\"applyChainUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAllowList\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAllowListEnabled\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getCurrentInboundRateLimiterState\",\"outputs\":[{\"components\":[{\"internalType\":\"uint128\",\"name\":\"tokens\",\"type\":\"uint128\"},{\"internalType\":\"uint32\",\"name\":\"lastUpdated\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.TokenBucket\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getCurrentOutboundRateLimiterState\",\"outputs\":[{\"components\":[{\"internalType\":\"uint128\",\"name\":\"tokens\",\"type\":\"uint128\"},{\"internalType\":\"uint32\",\"name\":\"lastUpdated\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.TokenBucket\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRateLimitAdmin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getRemotePool\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getRemoteToken\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRmnProxy\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRouter\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getSupportedChains\",\"outputs\":[{\"internalType\":\"uint64[]\",\"name\":\"\",\"type\":\"uint64[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getToken\",\"outputs\":[{\"internalType\":\"contractIERC20\",\"name\":\"token\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"isSupportedChain\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"isSupportedToken\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"originalSender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"localToken\",\"type\":\"address\"}],\"internalType\":\"structPool.LockOrBurnInV1\",\"name\":\"lockOrBurnIn\",\"type\":\"tuple\"}],\"name\":\"lockOrBurn\",\"outputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"destPoolData\",\"type\":\"bytes\"}],\"internalType\":\"structPool.LockOrBurnOutV1\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"originalSender\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"localToken\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"sourcePoolData\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"offchainTokenData\",\"type\":\"bytes\"}],\"internalType\":\"structPool.ReleaseOrMintInV1\",\"name\":\"releaseOrMintIn\",\"type\":\"tuple\"}],\"name\":\"releaseOrMint\",\"outputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"destinationAmount\",\"type\":\"uint256\"}],\"internalType\":\"structPool.ReleaseOrMintOutV1\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundConfig\",\"type\":\"tuple\"}],\"name\":\"setChainRateLimiterConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"rateLimitAdmin\",\"type\":\"address\"}],\"name\":\"setRateLimitAdmin\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"setRemotePool\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newRouter\",\"type\":\"address\"}],\"name\":\"setRouter\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"pure\",\"type\":\"function\"}]", + Bin: "0x60e06040523480156200001157600080fd5b50604051620044473803806200444783398101604081905262000034916200085d565b83838383336000816200005a57604051639b15e16f60e01b815260040160405180910390fd5b600180546001600160a01b0319166001600160a01b03848116919091179091558116156200008d576200008d8162000159565b50506001600160a01b0384161580620000ad57506001600160a01b038116155b80620000c057506001600160a01b038216155b15620000df576040516342bcdf7f60e11b815260040160405180910390fd5b6001600160a01b0384811660805282811660a052600480546001600160a01b031916918316919091179055825115801560c0526200013257604080516000815260208101909152620001329084620001d3565b506200014f925050506001600160a01b0385163060001962000330565b5050505062000a99565b336001600160a01b038216036200018357604051636d6c4ee560e11b815260040160405180910390fd5b600080546001600160a01b0319166001600160a01b03838116918217835560015460405192939116917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b60c051620001f4576040516335f4a7b360e01b815260040160405180910390fd5b60005b82518110156200027f5760008382815181106200021857620002186200096d565b602090810291909101015190506200023260028262000416565b1562000275576040516001600160a01b03821681527f800671136ab6cfee9fbe5ed1fb7ca417811aca3cf864800d127b927adedf75669060200160405180910390a15b50600101620001f7565b5060005b81518110156200032b576000828281518110620002a457620002a46200096d565b6020026020010151905060006001600160a01b0316816001600160a01b031603620002d0575062000322565b620002dd60028262000436565b1562000320576040516001600160a01b03821681527f2640d4d76caf8bf478aabfa982fa4e1c4eb71a37f93cd15e80dbc657911546d89060200160405180910390a15b505b60010162000283565b505050565b604051636eb1769f60e11b81523060048201526001600160a01b038381166024830152600091839186169063dd62ed3e90604401602060405180830381865afa15801562000382573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620003a8919062000983565b620003b49190620009b3565b604080516001600160a01b038616602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b0390811663095ea7b360e01b1790915291925062000410918691906200044d16565b50505050565b60006200042d836001600160a01b03841662000522565b90505b92915050565b60006200042d836001600160a01b03841662000626565b6040805180820190915260208082527f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564908201526000906200049c906001600160a01b03851690849062000678565b8051909150156200032b5780806020019051810190620004bd9190620009c9565b6200032b5760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b60648201526084015b60405180910390fd5b600081815260018301602052604081205480156200061b57600062000549600183620009f4565b85549091506000906200055f90600190620009f4565b9050808214620005cb5760008660000182815481106200058357620005836200096d565b9060005260206000200154905080876000018481548110620005a957620005a96200096d565b6000918252602080832090910192909255918252600188019052604090208390555b8554869080620005df57620005df62000a0a565b60019003818190600052602060002001600090559055856001016000868152602001908152602001600020600090556001935050505062000430565b600091505062000430565b60008181526001830160205260408120546200066f5750815460018181018455600084815260208082209093018490558454848252828601909352604090209190915562000430565b50600062000430565b606062000689848460008562000691565b949350505050565b606082471015620006f45760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b606482015260840162000519565b600080866001600160a01b0316858760405162000712919062000a46565b60006040518083038185875af1925050503d806000811462000751576040519150601f19603f3d011682016040523d82523d6000602084013e62000756565b606091505b5090925090506200076a8783838762000775565b979650505050505050565b60608315620007e9578251600003620007e1576001600160a01b0385163b620007e15760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640162000519565b508162000689565b620006898383815115620008005781518083602001fd5b8060405162461bcd60e51b815260040162000519919062000a64565b6001600160a01b03811681146200083257600080fd5b50565b634e487b7160e01b600052604160045260246000fd5b805162000858816200081c565b919050565b600080600080608085870312156200087457600080fd5b845162000881816200081c565b602086810151919550906001600160401b0380821115620008a157600080fd5b818801915088601f830112620008b657600080fd5b815181811115620008cb57620008cb62000835565b8060051b604051601f19603f83011681018181108582111715620008f357620008f362000835565b60405291825284820192508381018501918b8311156200091257600080fd5b938501935b828510156200093b576200092b856200084b565b8452938501939285019262000917565b80985050505050505062000952604086016200084b565b915062000962606086016200084b565b905092959194509250565b634e487b7160e01b600052603260045260246000fd5b6000602082840312156200099657600080fd5b5051919050565b634e487b7160e01b600052601160045260246000fd5b808201808211156200043057620004306200099d565b600060208284031215620009dc57600080fd5b81518015158114620009ed57600080fd5b9392505050565b818103818111156200043057620004306200099d565b634e487b7160e01b600052603160045260246000fd5b60005b8381101562000a3d57818101518382015260200162000a23565b50506000910152565b6000825162000a5a81846020870162000a20565b9190910192915050565b602081526000825180602084015262000a8581604085016020870162000a20565b601f01601f19169190910160400192915050565b60805160a05160c05161393162000b16600039600081816104da0152818161174701526120fa0152600081816104b4015281816115a801526119fd0152600081816102360152818161028b015281816106dd015281816114c80152818161191d01528181611b150152818161209001526122e501526139316000f3fe608060405234801561001057600080fd5b50600436106101ae5760003560e01c80639a4575b9116100ee578063c4bffe2b11610097578063db6327dc11610071578063db6327dc1461049f578063dc0bd971146104b2578063e0351e13146104d8578063f2fde38b146104fe57600080fd5b8063c4bffe2b14610464578063c75eea9c14610479578063cf7401f31461048c57600080fd5b8063b0f479a1116100c8578063b0f479a114610420578063b79465801461043e578063c0d786551461045157600080fd5b80639a4575b91461037c578063a7cd63b71461039c578063af58d59f146103b157600080fd5b806354c8a4f31161015b57806379ba50971161013557806379ba5097146103305780637d54534e146103385780638926f54f1461034b5780638da5cb5b1461035e57600080fd5b806354c8a4f3146102ea5780636d3d1a58146102ff57806378a010b21461031d57600080fd5b806321df0da71161018c57806321df0da714610234578063240028e81461027b57806339077537146102c857600080fd5b806301ffc9a7146101b35780630a2fd493146101db578063181f5a77146101fb575b600080fd5b6101c66101c1366004612a88565b610511565b60405190151581526020015b60405180910390f35b6101ee6101e9366004612ae7565b6105f6565b6040516101d29190612b66565b60408051808201909152601f81527f4275726e5769746846726f6d4d696e74546f6b656e506f6f6c20312e352e300060208201526101ee565b7f00000000000000000000000000000000000000000000000000000000000000005b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101d2565b6101c6610289366004612ba6565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff90811691161490565b6102db6102d6366004612bc3565b6106a6565b604051905181526020016101d2565b6102fd6102f8366004612c4b565b61082c565b005b60085473ffffffffffffffffffffffffffffffffffffffff16610256565b6102fd61032b366004612cb7565b6108a7565b6102fd610a1b565b6102fd610346366004612ba6565b610ae9565b6101c6610359366004612ae7565b610b6a565b60015473ffffffffffffffffffffffffffffffffffffffff16610256565b61038f61038a366004612d3a565b610b81565b6040516101d29190612d75565b6103a4610c28565b6040516101d29190612dd5565b6103c46103bf366004612ae7565b610c39565b6040516101d2919081516fffffffffffffffffffffffffffffffff908116825260208084015163ffffffff1690830152604080840151151590830152606080840151821690830152608092830151169181019190915260a00190565b60045473ffffffffffffffffffffffffffffffffffffffff16610256565b6101ee61044c366004612ae7565b610d0e565b6102fd61045f366004612ba6565b610d39565b61046c610e14565b6040516101d29190612e2f565b6103c4610487366004612ae7565b610ecc565b6102fd61049a366004612f97565b610f9e565b6102fd6104ad366004612fdc565b611027565b7f0000000000000000000000000000000000000000000000000000000000000000610256565b7f00000000000000000000000000000000000000000000000000000000000000006101c6565b6102fd61050c366004612ba6565b6114ad565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167faff2afbf0000000000000000000000000000000000000000000000000000000014806105a457507fffffffff0000000000000000000000000000000000000000000000000000000082167f0e64dd2900000000000000000000000000000000000000000000000000000000145b806105f057507fffffffff0000000000000000000000000000000000000000000000000000000082167f01ffc9a700000000000000000000000000000000000000000000000000000000145b92915050565b67ffffffffffffffff811660009081526007602052604090206004018054606091906106219061301e565b80601f016020809104026020016040519081016040528092919081815260200182805461064d9061301e565b801561069a5780601f1061066f5761010080835404028352916020019161069a565b820191906000526020600020905b81548152906001019060200180831161067d57829003601f168201915b50505050509050919050565b6040805160208101909152600081526106c66106c18361311c565b6114c1565b73ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000166340c10f196107126060850160408601612ba6565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b16815273ffffffffffffffffffffffffffffffffffffffff909116600482015260608501356024820152604401600060405180830381600087803b15801561078257600080fd5b505af1158015610796573d6000803e3d6000fd5b506107ab925050506060830160408401612ba6565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f9d228d69b5fdb8d273a2336f8fb8612d039631024ea9bf09c424a9503aa078f0846060013560405161080d91815260200190565b60405180910390a3506040805160208101909152606090910135815290565b6108346116f2565b6108a18484808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152505060408051602080880282810182019093528782529093508792508691829185019084908082843760009201919091525061174592505050565b50505050565b6108af6116f2565b6108b883610b6a565b6108ff576040517f1e670e4b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff841660048201526024015b60405180910390fd5b67ffffffffffffffff8316600090815260076020526040812060040180546109269061301e565b80601f01602080910402602001604051908101604052809291908181526020018280546109529061301e565b801561099f5780601f106109745761010080835404028352916020019161099f565b820191906000526020600020905b81548152906001019060200180831161098257829003601f168201915b5050505067ffffffffffffffff86166000908152600760205260409020919250506004016109ce838583613261565b508367ffffffffffffffff167fdb4d6220746a38cbc5335f7e108f7de80f482f4d23350253dfd0917df75a14bf828585604051610a0d9392919061337b565b60405180910390a250505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314610a6c576040517f02b543c600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000008082163390811790935560008054909116815560405173ffffffffffffffffffffffffffffffffffffffff909216929183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b610af16116f2565b600880547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040519081527f44676b5284b809a22248eba0da87391d79098be38bb03154be88a58bf4d091749060200160405180910390a150565b60006105f0600567ffffffffffffffff84166118fb565b6040805180820190915260608082526020820152610ba6610ba1836133df565b611916565b610bb38260600135611ae0565b6040516060830135815233907f696de425f79f4a40bc6d2122ca50507f0efbeabbff86a84871b7196ab8ea8df79060200160405180910390a26040518060400160405280610c0d84602001602081019061044c9190612ae7565b81526040805160208181019092526000815291015292915050565b6060610c346002611b89565b905090565b6040805160a08101825260008082526020820181905291810182905260608101829052608081019190915267ffffffffffffffff8216600090815260076020908152604091829020825160a08101845260028201546fffffffffffffffffffffffffffffffff808216835270010000000000000000000000000000000080830463ffffffff16958401959095527401000000000000000000000000000000000000000090910460ff1615159482019490945260039091015480841660608301529190910490911660808201526105f090611b96565b67ffffffffffffffff811660009081526007602052604090206005018054606091906106219061301e565b610d416116f2565b73ffffffffffffffffffffffffffffffffffffffff8116610d8e576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6004805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff000000000000000000000000000000000000000083168117909355604080519190921680825260208201939093527f02dc5c233404867c793b749c6d644beb2277536d18a7e7974d3f238e4c6f1684910160405180910390a15050565b60606000610e226005611b89565b90506000815167ffffffffffffffff811115610e4057610e40612e71565b604051908082528060200260200182016040528015610e69578160200160208202803683370190505b50905060005b8251811015610ec557828181518110610e8a57610e8a613481565b6020026020010151828281518110610ea457610ea4613481565b67ffffffffffffffff90921660209283029190910190910152600101610e6f565b5092915050565b6040805160a08101825260008082526020820181905291810182905260608101829052608081019190915267ffffffffffffffff8216600090815260076020908152604091829020825160a08101845281546fffffffffffffffffffffffffffffffff808216835270010000000000000000000000000000000080830463ffffffff16958401959095527401000000000000000000000000000000000000000090910460ff1615159482019490945260019091015480841660608301529190910490911660808201526105f090611b96565b60085473ffffffffffffffffffffffffffffffffffffffff163314801590610fde575060015473ffffffffffffffffffffffffffffffffffffffff163314155b15611017576040517f8e4a23d60000000000000000000000000000000000000000000000000000000081523360048201526024016108f6565b611022838383611c48565b505050565b61102f6116f2565b60005b8181101561102257600083838381811061104e5761104e613481565b905060200281019061106091906134b0565b611069906134ee565b905061107e8160800151826020015115611d32565b6110918160a00151826020015115611d32565b80602001511561138d5780516110b39060059067ffffffffffffffff16611e6b565b6110f85780516040517f1d5ad3c500000000000000000000000000000000000000000000000000000000815267ffffffffffffffff90911660048201526024016108f6565b604081015151158061110d5750606081015151155b15611144576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805161012081018252608083810180516020908101516fffffffffffffffffffffffffffffffff9081168486019081524263ffffffff90811660a0808901829052865151151560c08a01528651860151851660e08a015295518901518416610100890152918752875180860189529489018051850151841686528585019290925281515115158589015281518401518316606080870191909152915188015183168587015283870194855288880151878901908152828a015183890152895167ffffffffffffffff1660009081526007865289902088518051825482890151838e01519289167fffffffffffffffffffffffff0000000000000000000000000000000000000000928316177001000000000000000000000000000000009188168202177fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff90811674010000000000000000000000000000000000000000941515850217865584890151948d0151948a16948a168202949094176001860155995180516002860180549b8301519f830151918b169b9093169a909a179d9096168a029c909c1790911696151502959095179098559081015194015193811693169091029190911760038201559151909190600482019061132590826135a2565b506060820151600582019061133a90826135a2565b505081516060830151608084015160a08501516040517f8d340f17e19058004c20453540862a9c62778504476f6756755cb33bcd6c38c2955061138094939291906136bc565b60405180910390a16114a4565b80516113a59060059067ffffffffffffffff16611e77565b6113ea5780516040517f1e670e4b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff90911660048201526024016108f6565b805167ffffffffffffffff16600090815260076020526040812080547fffffffffffffffffffffff000000000000000000000000000000000000000000908116825560018201839055600282018054909116905560038101829055906114536004830182612a3a565b611461600583016000612a3a565b5050805160405167ffffffffffffffff90911681527f5204aec90a3c794d8e90fded8b46ae9c7c552803e7e832e0c1d358396d8599169060200160405180910390a15b50600101611032565b6114b56116f2565b6114be81611e83565b50565b60808101517f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff9081169116146115565760808101516040517f961c9a4f00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff90911660048201526024016108f6565b60208101516040517f2cbc26bb00000000000000000000000000000000000000000000000000000000815260809190911b77ffffffffffffffff000000000000000000000000000000001660048201527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1690632cbc26bb90602401602060405180830381865afa158015611604573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116289190613755565b1561165f576040517f53ad11d800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61166c8160200151611f47565b600061167b82602001516105f6565b905080516000148061169f575080805190602001208260a001518051906020012014155b156116dc578160a001516040517f24eb47e50000000000000000000000000000000000000000000000000000000081526004016108f69190612b66565b6116ee8260200151836060015161206d565b5050565b60015473ffffffffffffffffffffffffffffffffffffffff163314611743576040517f2b5c74de00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b565b7f000000000000000000000000000000000000000000000000000000000000000061179c576040517f35f4a7b300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b82518110156118325760008382815181106117bc576117bc613481565b602002602001015190506117da8160026120b490919063ffffffff16565b156118295760405173ffffffffffffffffffffffffffffffffffffffff821681527f800671136ab6cfee9fbe5ed1fb7ca417811aca3cf864800d127b927adedf75669060200160405180910390a15b5060010161179f565b5060005b815181101561102257600082828151811061185357611853613481565b60200260200101519050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff160361189757506118f3565b6118a26002826120d6565b156118f15760405173ffffffffffffffffffffffffffffffffffffffff821681527f2640d4d76caf8bf478aabfa982fa4e1c4eb71a37f93cd15e80dbc657911546d89060200160405180910390a15b505b600101611836565b600081815260018301602052604081205415155b9392505050565b60808101517f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff9081169116146119ab5760808101516040517f961c9a4f00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff90911660048201526024016108f6565b60208101516040517f2cbc26bb00000000000000000000000000000000000000000000000000000000815260809190911b77ffffffffffffffff000000000000000000000000000000001660048201527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1690632cbc26bb90602401602060405180830381865afa158015611a59573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a7d9190613755565b15611ab4576040517f53ad11d800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611ac181604001516120f8565b611ace8160200151612177565b6114be816020015182606001516122c5565b6040517f9dc29fac000000000000000000000000000000000000000000000000000000008152306004820152602481018290527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1690639dc29fac90604401600060405180830381600087803b158015611b6e57600080fd5b505af1158015611b82573d6000803e3d6000fd5b5050505050565b6060600061190f83612309565b6040805160a081018252600080825260208201819052918101829052606081018290526080810191909152611c2482606001516fffffffffffffffffffffffffffffffff1683600001516fffffffffffffffffffffffffffffffff16846020015163ffffffff1642611c0891906137a1565b85608001516fffffffffffffffffffffffffffffffff16612364565b6fffffffffffffffffffffffffffffffff1682525063ffffffff4216602082015290565b611c5183610b6a565b611c93576040517f1e670e4b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff841660048201526024016108f6565b611c9e826000611d32565b67ffffffffffffffff83166000908152600760205260409020611cc1908361238e565b611ccc816000611d32565b67ffffffffffffffff83166000908152600760205260409020611cf2906002018261238e565b7f0350d63aa5f270e01729d00d627eeb8f3429772b1818c016c66a588a864f912b838383604051611d25939291906137b4565b60405180910390a1505050565b815115611df95781602001516fffffffffffffffffffffffffffffffff1682604001516fffffffffffffffffffffffffffffffff16101580611d88575060408201516fffffffffffffffffffffffffffffffff16155b15611dc157816040517f8020d1240000000000000000000000000000000000000000000000000000000081526004016108f69190613837565b80156116ee576040517f433fc33d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60408201516fffffffffffffffffffffffffffffffff16151580611e32575060208201516fffffffffffffffffffffffffffffffff1615155b156116ee57816040517fd68af9cc0000000000000000000000000000000000000000000000000000000081526004016108f69190613837565b600061190f8383612530565b600061190f838361257f565b3373ffffffffffffffffffffffffffffffffffffffff821603611ed2576040517fdad89dca00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff838116918217835560015460405192939116917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b611f5081610b6a565b611f92576040517fa9902c7e00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff821660048201526024016108f6565b600480546040517f83826b2b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84169281019290925233602483015273ffffffffffffffffffffffffffffffffffffffff16906383826b2b90604401602060405180830381865afa158015612011573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120359190613755565b6114be576040517f728fe07b0000000000000000000000000000000000000000000000000000000081523360048201526024016108f6565b67ffffffffffffffff821660009081526007602052604090206116ee90600201827f0000000000000000000000000000000000000000000000000000000000000000612672565b600061190f8373ffffffffffffffffffffffffffffffffffffffff841661257f565b600061190f8373ffffffffffffffffffffffffffffffffffffffff8416612530565b7f0000000000000000000000000000000000000000000000000000000000000000156114be576121296002826129f5565b6114be576040517fd0d2597600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff821660048201526024016108f6565b61218081610b6a565b6121c2576040517fa9902c7e00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff821660048201526024016108f6565b600480546040517fa8d87a3b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84169281019290925273ffffffffffffffffffffffffffffffffffffffff169063a8d87a3b90602401602060405180830381865afa15801561223b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061225f9190613873565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146114be576040517f728fe07b0000000000000000000000000000000000000000000000000000000081523360048201526024016108f6565b67ffffffffffffffff821660009081526007602052604090206116ee90827f0000000000000000000000000000000000000000000000000000000000000000612672565b60608160000180548060200260200160405190810160405280929190818152602001828054801561069a57602002820191906000526020600020905b8154815260200190600101908083116123455750505050509050919050565b6000612383856123748486613890565b61237e90876138a7565b612a24565b90505b949350505050565b81546000906123b790700100000000000000000000000000000000900463ffffffff16426137a1565b9050801561245957600183015483546123ff916fffffffffffffffffffffffffffffffff80821692811691859170010000000000000000000000000000000090910416612364565b83546fffffffffffffffffffffffffffffffff919091167fffffffffffffffffffffffff0000000000000000000000000000000000000000909116177001000000000000000000000000000000004263ffffffff16021783555b6020820151835461247f916fffffffffffffffffffffffffffffffff9081169116612a24565b83548351151574010000000000000000000000000000000000000000027fffffffffffffffffffffff00ffffffff000000000000000000000000000000009091166fffffffffffffffffffffffffffffffff92831617178455602083015160408085015183167001000000000000000000000000000000000291909216176001850155517f9ea3374b67bf275e6bb9c8ae68f9cae023e1c528b4b27e092f0bb209d3531c1990611d25908490613837565b6000818152600183016020526040812054612577575081546001818101845560008481526020808220909301849055845484825282860190935260409020919091556105f0565b5060006105f0565b600081815260018301602052604081205480156126685760006125a36001836137a1565b85549091506000906125b7906001906137a1565b905080821461261c5760008660000182815481106125d7576125d7613481565b90600052602060002001549050808760000184815481106125fa576125fa613481565b6000918252602080832090910192909255918252600188019052604090208390555b855486908061262d5761262d6138ba565b6001900381819060005260206000200160009055905585600101600086815260200190815260200160002060009055600193505050506105f0565b60009150506105f0565b825474010000000000000000000000000000000000000000900460ff161580612699575081155b156126a357505050565b825460018401546fffffffffffffffffffffffffffffffff808316929116906000906126e990700100000000000000000000000000000000900463ffffffff16426137a1565b905080156127a9578183111561272b576040517f9725942a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018601546127659083908590849070010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff16612364565b86547fffffffffffffffffffffffff00000000ffffffffffffffffffffffffffffffff167001000000000000000000000000000000004263ffffffff160217875592505b848210156128605773ffffffffffffffffffffffffffffffffffffffff8416612808576040517ff94ebcd100000000000000000000000000000000000000000000000000000000815260048101839052602481018690526044016108f6565b6040517f1a76572a000000000000000000000000000000000000000000000000000000008152600481018390526024810186905273ffffffffffffffffffffffffffffffffffffffff851660448201526064016108f6565b848310156129735760018681015470010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff169060009082906128a490826137a1565b6128ae878a6137a1565b6128b891906138a7565b6128c291906138e9565b905073ffffffffffffffffffffffffffffffffffffffff861661291b576040517f15279c0800000000000000000000000000000000000000000000000000000000815260048101829052602481018690526044016108f6565b6040517fd0c8d23a000000000000000000000000000000000000000000000000000000008152600481018290526024810186905273ffffffffffffffffffffffffffffffffffffffff871660448201526064016108f6565b61297d85846137a1565b86547fffffffffffffffffffffffffffffffff00000000000000000000000000000000166fffffffffffffffffffffffffffffffff82161787556040518681529093507f1871cdf8010e63f2eb8384381a68dfa7416dc571a5517e66e88b2d2d0c0a690a9060200160405180910390a1505050505050565b73ffffffffffffffffffffffffffffffffffffffff81166000908152600183016020526040812054151561190f565b6000818310612a33578161190f565b5090919050565b508054612a469061301e565b6000825580601f10612a56575050565b601f0160209004906000526020600020908101906114be91905b80821115612a845760008155600101612a70565b5090565b600060208284031215612a9a57600080fd5b81357fffffffff000000000000000000000000000000000000000000000000000000008116811461190f57600080fd5b803567ffffffffffffffff81168114612ae257600080fd5b919050565b600060208284031215612af957600080fd5b61190f82612aca565b6000815180845260005b81811015612b2857602081850181015186830182015201612b0c565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b60208152600061190f6020830184612b02565b73ffffffffffffffffffffffffffffffffffffffff811681146114be57600080fd5b8035612ae281612b79565b600060208284031215612bb857600080fd5b813561190f81612b79565b600060208284031215612bd557600080fd5b813567ffffffffffffffff811115612bec57600080fd5b8201610100818503121561190f57600080fd5b60008083601f840112612c1157600080fd5b50813567ffffffffffffffff811115612c2957600080fd5b6020830191508360208260051b8501011115612c4457600080fd5b9250929050565b60008060008060408587031215612c6157600080fd5b843567ffffffffffffffff80821115612c7957600080fd5b612c8588838901612bff565b90965094506020870135915080821115612c9e57600080fd5b50612cab87828801612bff565b95989497509550505050565b600080600060408486031215612ccc57600080fd5b612cd584612aca565b9250602084013567ffffffffffffffff80821115612cf257600080fd5b818601915086601f830112612d0657600080fd5b813581811115612d1557600080fd5b876020828501011115612d2757600080fd5b6020830194508093505050509250925092565b600060208284031215612d4c57600080fd5b813567ffffffffffffffff811115612d6357600080fd5b820160a0818503121561190f57600080fd5b602081526000825160406020840152612d916060840182612b02565b905060208401517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0848303016040850152612dcc8282612b02565b95945050505050565b6020808252825182820181905260009190848201906040850190845b81811015612e2357835173ffffffffffffffffffffffffffffffffffffffff1683529284019291840191600101612df1565b50909695505050505050565b6020808252825182820181905260009190848201906040850190845b81811015612e2357835167ffffffffffffffff1683529284019291840191600101612e4b565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051610100810167ffffffffffffffff81118282101715612ec457612ec4612e71565b60405290565b60405160c0810167ffffffffffffffff81118282101715612ec457612ec4612e71565b80151581146114be57600080fd5b8035612ae281612eed565b80356fffffffffffffffffffffffffffffffff81168114612ae257600080fd5b600060608284031215612f3857600080fd5b6040516060810181811067ffffffffffffffff82111715612f5b57612f5b612e71565b6040529050808235612f6c81612eed565b8152612f7a60208401612f06565b6020820152612f8b60408401612f06565b60408201525092915050565b600080600060e08486031215612fac57600080fd5b612fb584612aca565b9250612fc48560208601612f26565b9150612fd38560808601612f26565b90509250925092565b60008060208385031215612fef57600080fd5b823567ffffffffffffffff81111561300657600080fd5b61301285828601612bff565b90969095509350505050565b600181811c9082168061303257607f821691505b60208210810361306b577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b600082601f83011261308257600080fd5b813567ffffffffffffffff8082111561309d5761309d612e71565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f011681019082821181831017156130e3576130e3612e71565b816040528381528660208588010111156130fc57600080fd5b836020870160208301376000602085830101528094505050505092915050565b6000610100823603121561312f57600080fd5b613137612ea0565b823567ffffffffffffffff8082111561314f57600080fd5b61315b36838701613071565b835261316960208601612aca565b602084015261317a60408601612b9b565b60408401526060850135606084015261319560808601612b9b565b608084015260a08501359150808211156131ae57600080fd5b6131ba36838701613071565b60a084015260c08501359150808211156131d357600080fd5b6131df36838701613071565b60c084015260e08501359150808211156131f857600080fd5b5061320536828601613071565b60e08301525092915050565b601f821115611022576000816000526020600020601f850160051c8101602086101561323a5750805b601f850160051c820191505b8181101561325957828155600101613246565b505050505050565b67ffffffffffffffff83111561327957613279612e71565b61328d83613287835461301e565b83613211565b6000601f8411600181146132df57600085156132a95750838201355b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600387901b1c1916600186901b178355611b82565b6000838152602090207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0861690835b8281101561332e578685013582556020948501946001909201910161330e565b5086821015613369577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88860031b161c19848701351681555b505060018560011b0183555050505050565b60408152600061338e6040830186612b02565b82810360208401528381528385602083013760006020858301015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f860116820101915050949350505050565b600060a082360312156133f157600080fd5b60405160a0810167ffffffffffffffff828210818311171561341557613415612e71565b81604052843591508082111561342a57600080fd5b5061343736828601613071565b82525061344660208401612aca565b6020820152604083013561345981612b79565b604082015260608381013590820152608083013561347681612b79565b608082015292915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600082357ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffec18336030181126134e457600080fd5b9190910192915050565b6000610140823603121561350157600080fd5b613509612eca565b61351283612aca565b815261352060208401612efb565b6020820152604083013567ffffffffffffffff8082111561354057600080fd5b61354c36838701613071565b6040840152606085013591508082111561356557600080fd5b5061357236828601613071565b6060830152506135853660808501612f26565b60808201526135973660e08501612f26565b60a082015292915050565b815167ffffffffffffffff8111156135bc576135bc612e71565b6135d0816135ca845461301e565b84613211565b602080601f83116001811461362357600084156135ed5750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b178555613259565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b8281101561367057888601518255948401946001909101908401613651565b50858210156136ac57878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b600061010067ffffffffffffffff871683528060208401526136e081840187612b02565b8551151560408581019190915260208701516fffffffffffffffffffffffffffffffff908116606087015290870151166080850152915061371e9050565b8251151560a083015260208301516fffffffffffffffffffffffffffffffff90811660c084015260408401511660e0830152612dcc565b60006020828403121561376757600080fd5b815161190f81612eed565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b818103818111156105f0576105f0613772565b67ffffffffffffffff8416815260e0810161380060208301858051151582526020808201516fffffffffffffffffffffffffffffffff9081169184019190915260409182015116910152565b82511515608083015260208301516fffffffffffffffffffffffffffffffff90811660a084015260408401511660c0830152612386565b606081016105f082848051151582526020808201516fffffffffffffffffffffffffffffffff9081169184019190915260409182015116910152565b60006020828403121561388557600080fd5b815161190f81612b79565b80820281158282048414176105f0576105f0613772565b808201808211156105f0576105f0613772565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b60008261391f577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b50049056fea164736f6c6343000818000a", } var BurnWithFromMintTokenPoolABI = BurnWithFromMintTokenPoolMetaData.ABI var BurnWithFromMintTokenPoolBin = BurnWithFromMintTokenPoolMetaData.Bin -func DeployBurnWithFromMintTokenPool(auth *bind.TransactOpts, backend bind.ContractBackend, token common.Address, localTokenDecimals uint8, allowlist []common.Address, rmnProxy common.Address, router common.Address) (common.Address, *types.Transaction, *BurnWithFromMintTokenPool, error) { +func DeployBurnWithFromMintTokenPool(auth *bind.TransactOpts, backend bind.ContractBackend, token common.Address, allowlist []common.Address, rmnProxy common.Address, router common.Address) (common.Address, *types.Transaction, *BurnWithFromMintTokenPool, error) { parsed, err := BurnWithFromMintTokenPoolMetaData.GetAbi() if err != nil { return common.Address{}, nil, nil, err @@ -98,7 +99,7 @@ func DeployBurnWithFromMintTokenPool(auth *bind.TransactOpts, backend bind.Contr return common.Address{}, nil, nil, errors.New("GetABI returned nil") } - address, tx, contract, err := bind.DeployContract(auth, *parsed, common.FromHex(BurnWithFromMintTokenPoolBin), backend, token, localTokenDecimals, allowlist, rmnProxy, router) + address, tx, contract, err := bind.DeployContract(auth, *parsed, common.FromHex(BurnWithFromMintTokenPoolBin), backend, token, allowlist, rmnProxy, router) if err != nil { return common.Address{}, nil, nil, err } @@ -331,26 +332,26 @@ func (_BurnWithFromMintTokenPool *BurnWithFromMintTokenPoolCallerSession) GetRat return _BurnWithFromMintTokenPool.Contract.GetRateLimitAdmin(&_BurnWithFromMintTokenPool.CallOpts) } -func (_BurnWithFromMintTokenPool *BurnWithFromMintTokenPoolCaller) GetRemotePools(opts *bind.CallOpts, remoteChainSelector uint64) ([][]byte, error) { +func (_BurnWithFromMintTokenPool *BurnWithFromMintTokenPoolCaller) GetRemotePool(opts *bind.CallOpts, remoteChainSelector uint64) ([]byte, error) { var out []interface{} - err := _BurnWithFromMintTokenPool.contract.Call(opts, &out, "getRemotePools", remoteChainSelector) + err := _BurnWithFromMintTokenPool.contract.Call(opts, &out, "getRemotePool", remoteChainSelector) if err != nil { - return *new([][]byte), err + return *new([]byte), err } - out0 := *abi.ConvertType(out[0], new([][]byte)).(*[][]byte) + out0 := *abi.ConvertType(out[0], new([]byte)).(*[]byte) return out0, err } -func (_BurnWithFromMintTokenPool *BurnWithFromMintTokenPoolSession) GetRemotePools(remoteChainSelector uint64) ([][]byte, error) { - return _BurnWithFromMintTokenPool.Contract.GetRemotePools(&_BurnWithFromMintTokenPool.CallOpts, remoteChainSelector) +func (_BurnWithFromMintTokenPool *BurnWithFromMintTokenPoolSession) GetRemotePool(remoteChainSelector uint64) ([]byte, error) { + return _BurnWithFromMintTokenPool.Contract.GetRemotePool(&_BurnWithFromMintTokenPool.CallOpts, remoteChainSelector) } -func (_BurnWithFromMintTokenPool *BurnWithFromMintTokenPoolCallerSession) GetRemotePools(remoteChainSelector uint64) ([][]byte, error) { - return _BurnWithFromMintTokenPool.Contract.GetRemotePools(&_BurnWithFromMintTokenPool.CallOpts, remoteChainSelector) +func (_BurnWithFromMintTokenPool *BurnWithFromMintTokenPoolCallerSession) GetRemotePool(remoteChainSelector uint64) ([]byte, error) { + return _BurnWithFromMintTokenPool.Contract.GetRemotePool(&_BurnWithFromMintTokenPool.CallOpts, remoteChainSelector) } func (_BurnWithFromMintTokenPool *BurnWithFromMintTokenPoolCaller) GetRemoteToken(opts *bind.CallOpts, remoteChainSelector uint64) ([]byte, error) { @@ -463,50 +464,6 @@ func (_BurnWithFromMintTokenPool *BurnWithFromMintTokenPoolCallerSession) GetTok return _BurnWithFromMintTokenPool.Contract.GetToken(&_BurnWithFromMintTokenPool.CallOpts) } -func (_BurnWithFromMintTokenPool *BurnWithFromMintTokenPoolCaller) GetTokenDecimals(opts *bind.CallOpts) (uint8, error) { - var out []interface{} - err := _BurnWithFromMintTokenPool.contract.Call(opts, &out, "getTokenDecimals") - - if err != nil { - return *new(uint8), err - } - - out0 := *abi.ConvertType(out[0], new(uint8)).(*uint8) - - return out0, err - -} - -func (_BurnWithFromMintTokenPool *BurnWithFromMintTokenPoolSession) GetTokenDecimals() (uint8, error) { - return _BurnWithFromMintTokenPool.Contract.GetTokenDecimals(&_BurnWithFromMintTokenPool.CallOpts) -} - -func (_BurnWithFromMintTokenPool *BurnWithFromMintTokenPoolCallerSession) GetTokenDecimals() (uint8, error) { - return _BurnWithFromMintTokenPool.Contract.GetTokenDecimals(&_BurnWithFromMintTokenPool.CallOpts) -} - -func (_BurnWithFromMintTokenPool *BurnWithFromMintTokenPoolCaller) IsRemotePool(opts *bind.CallOpts, remoteChainSelector uint64, remotePoolAddress []byte) (bool, error) { - var out []interface{} - err := _BurnWithFromMintTokenPool.contract.Call(opts, &out, "isRemotePool", remoteChainSelector, remotePoolAddress) - - if err != nil { - return *new(bool), err - } - - out0 := *abi.ConvertType(out[0], new(bool)).(*bool) - - return out0, err - -} - -func (_BurnWithFromMintTokenPool *BurnWithFromMintTokenPoolSession) IsRemotePool(remoteChainSelector uint64, remotePoolAddress []byte) (bool, error) { - return _BurnWithFromMintTokenPool.Contract.IsRemotePool(&_BurnWithFromMintTokenPool.CallOpts, remoteChainSelector, remotePoolAddress) -} - -func (_BurnWithFromMintTokenPool *BurnWithFromMintTokenPoolCallerSession) IsRemotePool(remoteChainSelector uint64, remotePoolAddress []byte) (bool, error) { - return _BurnWithFromMintTokenPool.Contract.IsRemotePool(&_BurnWithFromMintTokenPool.CallOpts, remoteChainSelector, remotePoolAddress) -} - func (_BurnWithFromMintTokenPool *BurnWithFromMintTokenPoolCaller) IsSupportedChain(opts *bind.CallOpts, remoteChainSelector uint64) (bool, error) { var out []interface{} err := _BurnWithFromMintTokenPool.contract.Call(opts, &out, "isSupportedChain", remoteChainSelector) @@ -629,18 +586,6 @@ func (_BurnWithFromMintTokenPool *BurnWithFromMintTokenPoolTransactorSession) Ac return _BurnWithFromMintTokenPool.Contract.AcceptOwnership(&_BurnWithFromMintTokenPool.TransactOpts) } -func (_BurnWithFromMintTokenPool *BurnWithFromMintTokenPoolTransactor) AddRemotePool(opts *bind.TransactOpts, remoteChainSelector uint64, remotePoolAddress []byte) (*types.Transaction, error) { - return _BurnWithFromMintTokenPool.contract.Transact(opts, "addRemotePool", remoteChainSelector, remotePoolAddress) -} - -func (_BurnWithFromMintTokenPool *BurnWithFromMintTokenPoolSession) AddRemotePool(remoteChainSelector uint64, remotePoolAddress []byte) (*types.Transaction, error) { - return _BurnWithFromMintTokenPool.Contract.AddRemotePool(&_BurnWithFromMintTokenPool.TransactOpts, remoteChainSelector, remotePoolAddress) -} - -func (_BurnWithFromMintTokenPool *BurnWithFromMintTokenPoolTransactorSession) AddRemotePool(remoteChainSelector uint64, remotePoolAddress []byte) (*types.Transaction, error) { - return _BurnWithFromMintTokenPool.Contract.AddRemotePool(&_BurnWithFromMintTokenPool.TransactOpts, remoteChainSelector, remotePoolAddress) -} - func (_BurnWithFromMintTokenPool *BurnWithFromMintTokenPoolTransactor) ApplyAllowListUpdates(opts *bind.TransactOpts, removes []common.Address, adds []common.Address) (*types.Transaction, error) { return _BurnWithFromMintTokenPool.contract.Transact(opts, "applyAllowListUpdates", removes, adds) } @@ -653,16 +598,16 @@ func (_BurnWithFromMintTokenPool *BurnWithFromMintTokenPoolTransactorSession) Ap return _BurnWithFromMintTokenPool.Contract.ApplyAllowListUpdates(&_BurnWithFromMintTokenPool.TransactOpts, removes, adds) } -func (_BurnWithFromMintTokenPool *BurnWithFromMintTokenPoolTransactor) ApplyChainUpdates(opts *bind.TransactOpts, remoteChainSelectorsToRemove []uint64, chainsToAdd []TokenPoolChainUpdate) (*types.Transaction, error) { - return _BurnWithFromMintTokenPool.contract.Transact(opts, "applyChainUpdates", remoteChainSelectorsToRemove, chainsToAdd) +func (_BurnWithFromMintTokenPool *BurnWithFromMintTokenPoolTransactor) ApplyChainUpdates(opts *bind.TransactOpts, chains []TokenPoolChainUpdate) (*types.Transaction, error) { + return _BurnWithFromMintTokenPool.contract.Transact(opts, "applyChainUpdates", chains) } -func (_BurnWithFromMintTokenPool *BurnWithFromMintTokenPoolSession) ApplyChainUpdates(remoteChainSelectorsToRemove []uint64, chainsToAdd []TokenPoolChainUpdate) (*types.Transaction, error) { - return _BurnWithFromMintTokenPool.Contract.ApplyChainUpdates(&_BurnWithFromMintTokenPool.TransactOpts, remoteChainSelectorsToRemove, chainsToAdd) +func (_BurnWithFromMintTokenPool *BurnWithFromMintTokenPoolSession) ApplyChainUpdates(chains []TokenPoolChainUpdate) (*types.Transaction, error) { + return _BurnWithFromMintTokenPool.Contract.ApplyChainUpdates(&_BurnWithFromMintTokenPool.TransactOpts, chains) } -func (_BurnWithFromMintTokenPool *BurnWithFromMintTokenPoolTransactorSession) ApplyChainUpdates(remoteChainSelectorsToRemove []uint64, chainsToAdd []TokenPoolChainUpdate) (*types.Transaction, error) { - return _BurnWithFromMintTokenPool.Contract.ApplyChainUpdates(&_BurnWithFromMintTokenPool.TransactOpts, remoteChainSelectorsToRemove, chainsToAdd) +func (_BurnWithFromMintTokenPool *BurnWithFromMintTokenPoolTransactorSession) ApplyChainUpdates(chains []TokenPoolChainUpdate) (*types.Transaction, error) { + return _BurnWithFromMintTokenPool.Contract.ApplyChainUpdates(&_BurnWithFromMintTokenPool.TransactOpts, chains) } func (_BurnWithFromMintTokenPool *BurnWithFromMintTokenPoolTransactor) LockOrBurn(opts *bind.TransactOpts, lockOrBurnIn PoolLockOrBurnInV1) (*types.Transaction, error) { @@ -689,18 +634,6 @@ func (_BurnWithFromMintTokenPool *BurnWithFromMintTokenPoolTransactorSession) Re return _BurnWithFromMintTokenPool.Contract.ReleaseOrMint(&_BurnWithFromMintTokenPool.TransactOpts, releaseOrMintIn) } -func (_BurnWithFromMintTokenPool *BurnWithFromMintTokenPoolTransactor) RemoveRemotePool(opts *bind.TransactOpts, remoteChainSelector uint64, remotePoolAddress []byte) (*types.Transaction, error) { - return _BurnWithFromMintTokenPool.contract.Transact(opts, "removeRemotePool", remoteChainSelector, remotePoolAddress) -} - -func (_BurnWithFromMintTokenPool *BurnWithFromMintTokenPoolSession) RemoveRemotePool(remoteChainSelector uint64, remotePoolAddress []byte) (*types.Transaction, error) { - return _BurnWithFromMintTokenPool.Contract.RemoveRemotePool(&_BurnWithFromMintTokenPool.TransactOpts, remoteChainSelector, remotePoolAddress) -} - -func (_BurnWithFromMintTokenPool *BurnWithFromMintTokenPoolTransactorSession) RemoveRemotePool(remoteChainSelector uint64, remotePoolAddress []byte) (*types.Transaction, error) { - return _BurnWithFromMintTokenPool.Contract.RemoveRemotePool(&_BurnWithFromMintTokenPool.TransactOpts, remoteChainSelector, remotePoolAddress) -} - func (_BurnWithFromMintTokenPool *BurnWithFromMintTokenPoolTransactor) SetChainRateLimiterConfig(opts *bind.TransactOpts, remoteChainSelector uint64, outboundConfig RateLimiterConfig, inboundConfig RateLimiterConfig) (*types.Transaction, error) { return _BurnWithFromMintTokenPool.contract.Transact(opts, "setChainRateLimiterConfig", remoteChainSelector, outboundConfig, inboundConfig) } @@ -713,18 +646,6 @@ func (_BurnWithFromMintTokenPool *BurnWithFromMintTokenPoolTransactorSession) Se return _BurnWithFromMintTokenPool.Contract.SetChainRateLimiterConfig(&_BurnWithFromMintTokenPool.TransactOpts, remoteChainSelector, outboundConfig, inboundConfig) } -func (_BurnWithFromMintTokenPool *BurnWithFromMintTokenPoolTransactor) SetChainRateLimiterConfigs(opts *bind.TransactOpts, remoteChainSelectors []uint64, outboundConfigs []RateLimiterConfig, inboundConfigs []RateLimiterConfig) (*types.Transaction, error) { - return _BurnWithFromMintTokenPool.contract.Transact(opts, "setChainRateLimiterConfigs", remoteChainSelectors, outboundConfigs, inboundConfigs) -} - -func (_BurnWithFromMintTokenPool *BurnWithFromMintTokenPoolSession) SetChainRateLimiterConfigs(remoteChainSelectors []uint64, outboundConfigs []RateLimiterConfig, inboundConfigs []RateLimiterConfig) (*types.Transaction, error) { - return _BurnWithFromMintTokenPool.Contract.SetChainRateLimiterConfigs(&_BurnWithFromMintTokenPool.TransactOpts, remoteChainSelectors, outboundConfigs, inboundConfigs) -} - -func (_BurnWithFromMintTokenPool *BurnWithFromMintTokenPoolTransactorSession) SetChainRateLimiterConfigs(remoteChainSelectors []uint64, outboundConfigs []RateLimiterConfig, inboundConfigs []RateLimiterConfig) (*types.Transaction, error) { - return _BurnWithFromMintTokenPool.Contract.SetChainRateLimiterConfigs(&_BurnWithFromMintTokenPool.TransactOpts, remoteChainSelectors, outboundConfigs, inboundConfigs) -} - func (_BurnWithFromMintTokenPool *BurnWithFromMintTokenPoolTransactor) SetRateLimitAdmin(opts *bind.TransactOpts, rateLimitAdmin common.Address) (*types.Transaction, error) { return _BurnWithFromMintTokenPool.contract.Transact(opts, "setRateLimitAdmin", rateLimitAdmin) } @@ -737,6 +658,18 @@ func (_BurnWithFromMintTokenPool *BurnWithFromMintTokenPoolTransactorSession) Se return _BurnWithFromMintTokenPool.Contract.SetRateLimitAdmin(&_BurnWithFromMintTokenPool.TransactOpts, rateLimitAdmin) } +func (_BurnWithFromMintTokenPool *BurnWithFromMintTokenPoolTransactor) SetRemotePool(opts *bind.TransactOpts, remoteChainSelector uint64, remotePoolAddress []byte) (*types.Transaction, error) { + return _BurnWithFromMintTokenPool.contract.Transact(opts, "setRemotePool", remoteChainSelector, remotePoolAddress) +} + +func (_BurnWithFromMintTokenPool *BurnWithFromMintTokenPoolSession) SetRemotePool(remoteChainSelector uint64, remotePoolAddress []byte) (*types.Transaction, error) { + return _BurnWithFromMintTokenPool.Contract.SetRemotePool(&_BurnWithFromMintTokenPool.TransactOpts, remoteChainSelector, remotePoolAddress) +} + +func (_BurnWithFromMintTokenPool *BurnWithFromMintTokenPoolTransactorSession) SetRemotePool(remoteChainSelector uint64, remotePoolAddress []byte) (*types.Transaction, error) { + return _BurnWithFromMintTokenPool.Contract.SetRemotePool(&_BurnWithFromMintTokenPool.TransactOpts, remoteChainSelector, remotePoolAddress) +} + func (_BurnWithFromMintTokenPool *BurnWithFromMintTokenPoolTransactor) SetRouter(opts *bind.TransactOpts, newRouter common.Address) (*types.Transaction, error) { return _BurnWithFromMintTokenPool.contract.Transact(opts, "setRouter", newRouter) } @@ -2387,8 +2320,8 @@ func (_BurnWithFromMintTokenPool *BurnWithFromMintTokenPoolFilterer) ParseReleas return event, nil } -type BurnWithFromMintTokenPoolRemotePoolAddedIterator struct { - Event *BurnWithFromMintTokenPoolRemotePoolAdded +type BurnWithFromMintTokenPoolRemotePoolSetIterator struct { + Event *BurnWithFromMintTokenPoolRemotePoolSet contract *bind.BoundContract event string @@ -2399,7 +2332,7 @@ type BurnWithFromMintTokenPoolRemotePoolAddedIterator struct { fail error } -func (it *BurnWithFromMintTokenPoolRemotePoolAddedIterator) Next() bool { +func (it *BurnWithFromMintTokenPoolRemotePoolSetIterator) Next() bool { if it.fail != nil { return false @@ -2408,7 +2341,7 @@ func (it *BurnWithFromMintTokenPoolRemotePoolAddedIterator) Next() bool { if it.done { select { case log := <-it.logs: - it.Event = new(BurnWithFromMintTokenPoolRemotePoolAdded) + it.Event = new(BurnWithFromMintTokenPoolRemotePoolSet) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -2423,7 +2356,7 @@ func (it *BurnWithFromMintTokenPoolRemotePoolAddedIterator) Next() bool { select { case log := <-it.logs: - it.Event = new(BurnWithFromMintTokenPoolRemotePoolAdded) + it.Event = new(BurnWithFromMintTokenPoolRemotePoolSet) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -2438,43 +2371,44 @@ func (it *BurnWithFromMintTokenPoolRemotePoolAddedIterator) Next() bool { } } -func (it *BurnWithFromMintTokenPoolRemotePoolAddedIterator) Error() error { +func (it *BurnWithFromMintTokenPoolRemotePoolSetIterator) Error() error { return it.fail } -func (it *BurnWithFromMintTokenPoolRemotePoolAddedIterator) Close() error { +func (it *BurnWithFromMintTokenPoolRemotePoolSetIterator) Close() error { it.sub.Unsubscribe() return nil } -type BurnWithFromMintTokenPoolRemotePoolAdded struct { +type BurnWithFromMintTokenPoolRemotePoolSet struct { RemoteChainSelector uint64 + PreviousPoolAddress []byte RemotePoolAddress []byte Raw types.Log } -func (_BurnWithFromMintTokenPool *BurnWithFromMintTokenPoolFilterer) FilterRemotePoolAdded(opts *bind.FilterOpts, remoteChainSelector []uint64) (*BurnWithFromMintTokenPoolRemotePoolAddedIterator, error) { +func (_BurnWithFromMintTokenPool *BurnWithFromMintTokenPoolFilterer) FilterRemotePoolSet(opts *bind.FilterOpts, remoteChainSelector []uint64) (*BurnWithFromMintTokenPoolRemotePoolSetIterator, error) { var remoteChainSelectorRule []interface{} for _, remoteChainSelectorItem := range remoteChainSelector { remoteChainSelectorRule = append(remoteChainSelectorRule, remoteChainSelectorItem) } - logs, sub, err := _BurnWithFromMintTokenPool.contract.FilterLogs(opts, "RemotePoolAdded", remoteChainSelectorRule) + logs, sub, err := _BurnWithFromMintTokenPool.contract.FilterLogs(opts, "RemotePoolSet", remoteChainSelectorRule) if err != nil { return nil, err } - return &BurnWithFromMintTokenPoolRemotePoolAddedIterator{contract: _BurnWithFromMintTokenPool.contract, event: "RemotePoolAdded", logs: logs, sub: sub}, nil + return &BurnWithFromMintTokenPoolRemotePoolSetIterator{contract: _BurnWithFromMintTokenPool.contract, event: "RemotePoolSet", logs: logs, sub: sub}, nil } -func (_BurnWithFromMintTokenPool *BurnWithFromMintTokenPoolFilterer) WatchRemotePoolAdded(opts *bind.WatchOpts, sink chan<- *BurnWithFromMintTokenPoolRemotePoolAdded, remoteChainSelector []uint64) (event.Subscription, error) { +func (_BurnWithFromMintTokenPool *BurnWithFromMintTokenPoolFilterer) WatchRemotePoolSet(opts *bind.WatchOpts, sink chan<- *BurnWithFromMintTokenPoolRemotePoolSet, remoteChainSelector []uint64) (event.Subscription, error) { var remoteChainSelectorRule []interface{} for _, remoteChainSelectorItem := range remoteChainSelector { remoteChainSelectorRule = append(remoteChainSelectorRule, remoteChainSelectorItem) } - logs, sub, err := _BurnWithFromMintTokenPool.contract.WatchLogs(opts, "RemotePoolAdded", remoteChainSelectorRule) + logs, sub, err := _BurnWithFromMintTokenPool.contract.WatchLogs(opts, "RemotePoolSet", remoteChainSelectorRule) if err != nil { return nil, err } @@ -2484,8 +2418,8 @@ func (_BurnWithFromMintTokenPool *BurnWithFromMintTokenPoolFilterer) WatchRemote select { case log := <-logs: - event := new(BurnWithFromMintTokenPoolRemotePoolAdded) - if err := _BurnWithFromMintTokenPool.contract.UnpackLog(event, "RemotePoolAdded", log); err != nil { + event := new(BurnWithFromMintTokenPoolRemotePoolSet) + if err := _BurnWithFromMintTokenPool.contract.UnpackLog(event, "RemotePoolSet", log); err != nil { return err } event.Raw = log @@ -2506,137 +2440,9 @@ func (_BurnWithFromMintTokenPool *BurnWithFromMintTokenPoolFilterer) WatchRemote }), nil } -func (_BurnWithFromMintTokenPool *BurnWithFromMintTokenPoolFilterer) ParseRemotePoolAdded(log types.Log) (*BurnWithFromMintTokenPoolRemotePoolAdded, error) { - event := new(BurnWithFromMintTokenPoolRemotePoolAdded) - if err := _BurnWithFromMintTokenPool.contract.UnpackLog(event, "RemotePoolAdded", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -type BurnWithFromMintTokenPoolRemotePoolRemovedIterator struct { - Event *BurnWithFromMintTokenPoolRemotePoolRemoved - - contract *bind.BoundContract - event string - - logs chan types.Log - sub ethereum.Subscription - done bool - fail error -} - -func (it *BurnWithFromMintTokenPoolRemotePoolRemovedIterator) Next() bool { - - if it.fail != nil { - return false - } - - if it.done { - select { - case log := <-it.logs: - it.Event = new(BurnWithFromMintTokenPoolRemotePoolRemoved) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - default: - return false - } - } - - select { - case log := <-it.logs: - it.Event = new(BurnWithFromMintTokenPoolRemotePoolRemoved) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - case err := <-it.sub.Err(): - it.done = true - it.fail = err - return it.Next() - } -} - -func (it *BurnWithFromMintTokenPoolRemotePoolRemovedIterator) Error() error { - return it.fail -} - -func (it *BurnWithFromMintTokenPoolRemotePoolRemovedIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -type BurnWithFromMintTokenPoolRemotePoolRemoved struct { - RemoteChainSelector uint64 - RemotePoolAddress []byte - Raw types.Log -} - -func (_BurnWithFromMintTokenPool *BurnWithFromMintTokenPoolFilterer) FilterRemotePoolRemoved(opts *bind.FilterOpts, remoteChainSelector []uint64) (*BurnWithFromMintTokenPoolRemotePoolRemovedIterator, error) { - - var remoteChainSelectorRule []interface{} - for _, remoteChainSelectorItem := range remoteChainSelector { - remoteChainSelectorRule = append(remoteChainSelectorRule, remoteChainSelectorItem) - } - - logs, sub, err := _BurnWithFromMintTokenPool.contract.FilterLogs(opts, "RemotePoolRemoved", remoteChainSelectorRule) - if err != nil { - return nil, err - } - return &BurnWithFromMintTokenPoolRemotePoolRemovedIterator{contract: _BurnWithFromMintTokenPool.contract, event: "RemotePoolRemoved", logs: logs, sub: sub}, nil -} - -func (_BurnWithFromMintTokenPool *BurnWithFromMintTokenPoolFilterer) WatchRemotePoolRemoved(opts *bind.WatchOpts, sink chan<- *BurnWithFromMintTokenPoolRemotePoolRemoved, remoteChainSelector []uint64) (event.Subscription, error) { - - var remoteChainSelectorRule []interface{} - for _, remoteChainSelectorItem := range remoteChainSelector { - remoteChainSelectorRule = append(remoteChainSelectorRule, remoteChainSelectorItem) - } - - logs, sub, err := _BurnWithFromMintTokenPool.contract.WatchLogs(opts, "RemotePoolRemoved", remoteChainSelectorRule) - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - - event := new(BurnWithFromMintTokenPoolRemotePoolRemoved) - if err := _BurnWithFromMintTokenPool.contract.UnpackLog(event, "RemotePoolRemoved", log); err != nil { - return err - } - event.Raw = log - - select { - case sink <- event: - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - } - }), nil -} - -func (_BurnWithFromMintTokenPool *BurnWithFromMintTokenPoolFilterer) ParseRemotePoolRemoved(log types.Log) (*BurnWithFromMintTokenPoolRemotePoolRemoved, error) { - event := new(BurnWithFromMintTokenPoolRemotePoolRemoved) - if err := _BurnWithFromMintTokenPool.contract.UnpackLog(event, "RemotePoolRemoved", log); err != nil { +func (_BurnWithFromMintTokenPool *BurnWithFromMintTokenPoolFilterer) ParseRemotePoolSet(log types.Log) (*BurnWithFromMintTokenPoolRemotePoolSet, error) { + event := new(BurnWithFromMintTokenPoolRemotePoolSet) + if err := _BurnWithFromMintTokenPool.contract.UnpackLog(event, "RemotePoolSet", log); err != nil { return nil, err } event.Raw = log @@ -2906,10 +2712,8 @@ func (_BurnWithFromMintTokenPool *BurnWithFromMintTokenPool) ParseLog(log types. return _BurnWithFromMintTokenPool.ParseRateLimitAdminSet(log) case _BurnWithFromMintTokenPool.abi.Events["Released"].ID: return _BurnWithFromMintTokenPool.ParseReleased(log) - case _BurnWithFromMintTokenPool.abi.Events["RemotePoolAdded"].ID: - return _BurnWithFromMintTokenPool.ParseRemotePoolAdded(log) - case _BurnWithFromMintTokenPool.abi.Events["RemotePoolRemoved"].ID: - return _BurnWithFromMintTokenPool.ParseRemotePoolRemoved(log) + case _BurnWithFromMintTokenPool.abi.Events["RemotePoolSet"].ID: + return _BurnWithFromMintTokenPool.ParseRemotePoolSet(log) case _BurnWithFromMintTokenPool.abi.Events["RouterUpdated"].ID: return _BurnWithFromMintTokenPool.ParseRouterUpdated(log) case _BurnWithFromMintTokenPool.abi.Events["TokensConsumed"].ID: @@ -2972,12 +2776,8 @@ func (BurnWithFromMintTokenPoolReleased) Topic() common.Hash { return common.HexToHash("0x2d87480f50083e2b2759522a8fdda59802650a8055e609a7772cf70c07748f52") } -func (BurnWithFromMintTokenPoolRemotePoolAdded) Topic() common.Hash { - return common.HexToHash("0x7d628c9a1796743d365ab521a8b2a4686e419b3269919dc9145ea2ce853b54ea") -} - -func (BurnWithFromMintTokenPoolRemotePoolRemoved) Topic() common.Hash { - return common.HexToHash("0x52d00ee4d9bd51b40168f2afc5848837288ce258784ad914278791464b3f4d76") +func (BurnWithFromMintTokenPoolRemotePoolSet) Topic() common.Hash { + return common.HexToHash("0xdb4d6220746a38cbc5335f7e108f7de80f482f4d23350253dfd0917df75a14bf") } func (BurnWithFromMintTokenPoolRouterUpdated) Topic() common.Hash { @@ -3003,7 +2803,7 @@ type BurnWithFromMintTokenPoolInterface interface { GetRateLimitAdmin(opts *bind.CallOpts) (common.Address, error) - GetRemotePools(opts *bind.CallOpts, remoteChainSelector uint64) ([][]byte, error) + GetRemotePool(opts *bind.CallOpts, remoteChainSelector uint64) ([]byte, error) GetRemoteToken(opts *bind.CallOpts, remoteChainSelector uint64) ([]byte, error) @@ -3015,10 +2815,6 @@ type BurnWithFromMintTokenPoolInterface interface { GetToken(opts *bind.CallOpts) (common.Address, error) - GetTokenDecimals(opts *bind.CallOpts) (uint8, error) - - IsRemotePool(opts *bind.CallOpts, remoteChainSelector uint64, remotePoolAddress []byte) (bool, error) - IsSupportedChain(opts *bind.CallOpts, remoteChainSelector uint64) (bool, error) IsSupportedToken(opts *bind.CallOpts, token common.Address) (bool, error) @@ -3031,24 +2827,20 @@ type BurnWithFromMintTokenPoolInterface interface { AcceptOwnership(opts *bind.TransactOpts) (*types.Transaction, error) - AddRemotePool(opts *bind.TransactOpts, remoteChainSelector uint64, remotePoolAddress []byte) (*types.Transaction, error) - ApplyAllowListUpdates(opts *bind.TransactOpts, removes []common.Address, adds []common.Address) (*types.Transaction, error) - ApplyChainUpdates(opts *bind.TransactOpts, remoteChainSelectorsToRemove []uint64, chainsToAdd []TokenPoolChainUpdate) (*types.Transaction, error) + ApplyChainUpdates(opts *bind.TransactOpts, chains []TokenPoolChainUpdate) (*types.Transaction, error) LockOrBurn(opts *bind.TransactOpts, lockOrBurnIn PoolLockOrBurnInV1) (*types.Transaction, error) ReleaseOrMint(opts *bind.TransactOpts, releaseOrMintIn PoolReleaseOrMintInV1) (*types.Transaction, error) - RemoveRemotePool(opts *bind.TransactOpts, remoteChainSelector uint64, remotePoolAddress []byte) (*types.Transaction, error) - SetChainRateLimiterConfig(opts *bind.TransactOpts, remoteChainSelector uint64, outboundConfig RateLimiterConfig, inboundConfig RateLimiterConfig) (*types.Transaction, error) - SetChainRateLimiterConfigs(opts *bind.TransactOpts, remoteChainSelectors []uint64, outboundConfigs []RateLimiterConfig, inboundConfigs []RateLimiterConfig) (*types.Transaction, error) - SetRateLimitAdmin(opts *bind.TransactOpts, rateLimitAdmin common.Address) (*types.Transaction, error) + SetRemotePool(opts *bind.TransactOpts, remoteChainSelector uint64, remotePoolAddress []byte) (*types.Transaction, error) + SetRouter(opts *bind.TransactOpts, newRouter common.Address) (*types.Transaction, error) TransferOwnership(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) @@ -3131,17 +2923,11 @@ type BurnWithFromMintTokenPoolInterface interface { ParseReleased(log types.Log) (*BurnWithFromMintTokenPoolReleased, error) - FilterRemotePoolAdded(opts *bind.FilterOpts, remoteChainSelector []uint64) (*BurnWithFromMintTokenPoolRemotePoolAddedIterator, error) - - WatchRemotePoolAdded(opts *bind.WatchOpts, sink chan<- *BurnWithFromMintTokenPoolRemotePoolAdded, remoteChainSelector []uint64) (event.Subscription, error) - - ParseRemotePoolAdded(log types.Log) (*BurnWithFromMintTokenPoolRemotePoolAdded, error) - - FilterRemotePoolRemoved(opts *bind.FilterOpts, remoteChainSelector []uint64) (*BurnWithFromMintTokenPoolRemotePoolRemovedIterator, error) + FilterRemotePoolSet(opts *bind.FilterOpts, remoteChainSelector []uint64) (*BurnWithFromMintTokenPoolRemotePoolSetIterator, error) - WatchRemotePoolRemoved(opts *bind.WatchOpts, sink chan<- *BurnWithFromMintTokenPoolRemotePoolRemoved, remoteChainSelector []uint64) (event.Subscription, error) + WatchRemotePoolSet(opts *bind.WatchOpts, sink chan<- *BurnWithFromMintTokenPoolRemotePoolSet, remoteChainSelector []uint64) (event.Subscription, error) - ParseRemotePoolRemoved(log types.Log) (*BurnWithFromMintTokenPoolRemotePoolRemoved, error) + ParseRemotePoolSet(log types.Log) (*BurnWithFromMintTokenPoolRemotePoolSet, error) FilterRouterUpdated(opts *bind.FilterOpts) (*BurnWithFromMintTokenPoolRouterUpdatedIterator, error) diff --git a/core/gethwrappers/ccip/generated/ccip_config/ccip_config.go b/core/gethwrappers/ccip/generated/ccip_config/ccip_config.go new file mode 100644 index 00000000000..3c2d44cd302 --- /dev/null +++ b/core/gethwrappers/ccip/generated/ccip_config/ccip_config.go @@ -0,0 +1,1126 @@ +// Code generated - DO NOT EDIT. +// This file is a generated binding and any manual changes will be lost. + +package ccip_config + +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 CCIPConfigTypesChainConfig struct { + Readers [][32]byte + FChain uint8 + Config []byte +} + +type CCIPConfigTypesChainConfigInfo struct { + ChainSelector uint64 + ChainConfig CCIPConfigTypesChainConfig +} + +type CCIPConfigTypesOCR3Config struct { + PluginType uint8 + ChainSelector uint64 + F uint8 + OffchainConfigVersion uint64 + OfframpAddress []byte + P2pIds [][32]byte + Signers [][]byte + Transmitters [][]byte + OffchainConfig []byte +} + +type CCIPConfigTypesOCR3ConfigWithMeta struct { + Config CCIPConfigTypesOCR3Config + ConfigCount uint64 + ConfigDigest [32]byte +} + +var CCIPConfigMetaData = &bind.MetaData{ + ABI: "[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"capabilitiesRegistry\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"}],\"name\":\"ChainSelectorNotFound\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ChainSelectorNotSet\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FChainMustBePositive\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FMustBePositive\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FTooHigh\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"length\",\"type\":\"uint256\"}],\"name\":\"InvalidConfigLength\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"enumCCIPConfigTypes.ConfigState\",\"name\":\"currentState\",\"type\":\"uint8\"},{\"internalType\":\"enumCCIPConfigTypes.ConfigState\",\"name\":\"proposedState\",\"type\":\"uint8\"}],\"name\":\"InvalidConfigStateTransition\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidPluginType\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"p2pId\",\"type\":\"bytes32\"}],\"name\":\"NodeNotInRegistry\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NonExistentConfigTransition\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"got\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"minimum\",\"type\":\"uint256\"}],\"name\":\"NotEnoughTransmitters\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OfframpAddressCannotBeZero\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCapabilitiesRegistryCanCall\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"p2pIdsLength\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"signersLength\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"transmittersLength\",\"type\":\"uint256\"}],\"name\":\"P2PIdsLengthNotMatching\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TooManyOCR3Configs\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TooManySigners\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"got\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"expected\",\"type\":\"uint64\"}],\"name\":\"WrongConfigCount\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"got\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"expected\",\"type\":\"bytes32\"}],\"name\":\"WrongConfigDigest\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"got\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"expected\",\"type\":\"bytes32\"}],\"name\":\"WrongConfigDigestBlueGreen\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[],\"name\":\"CapabilityConfigurationSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"}],\"name\":\"ChainConfigRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bytes32[]\",\"name\":\"readers\",\"type\":\"bytes32[]\"},{\"internalType\":\"uint8\",\"name\":\"fChain\",\"type\":\"uint8\"},{\"internalType\":\"bytes\",\"name\":\"config\",\"type\":\"bytes\"}],\"indexed\":false,\"internalType\":\"structCCIPConfigTypes.ChainConfig\",\"name\":\"chainConfig\",\"type\":\"tuple\"}],\"name\":\"ChainConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64[]\",\"name\":\"chainSelectorRemoves\",\"type\":\"uint64[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bytes32[]\",\"name\":\"readers\",\"type\":\"bytes32[]\"},{\"internalType\":\"uint8\",\"name\":\"fChain\",\"type\":\"uint8\"},{\"internalType\":\"bytes\",\"name\":\"config\",\"type\":\"bytes\"}],\"internalType\":\"structCCIPConfigTypes.ChainConfig\",\"name\":\"chainConfig\",\"type\":\"tuple\"}],\"internalType\":\"structCCIPConfigTypes.ChainConfigInfo[]\",\"name\":\"chainConfigAdds\",\"type\":\"tuple[]\"}],\"name\":\"applyChainConfigUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[]\",\"name\":\"\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes\",\"name\":\"config\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"donId\",\"type\":\"uint32\"}],\"name\":\"beforeCapabilityConfigSet\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"pageIndex\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"pageSize\",\"type\":\"uint256\"}],\"name\":\"getAllChainConfigs\",\"outputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bytes32[]\",\"name\":\"readers\",\"type\":\"bytes32[]\"},{\"internalType\":\"uint8\",\"name\":\"fChain\",\"type\":\"uint8\"},{\"internalType\":\"bytes\",\"name\":\"config\",\"type\":\"bytes\"}],\"internalType\":\"structCCIPConfigTypes.ChainConfig\",\"name\":\"chainConfig\",\"type\":\"tuple\"}],\"internalType\":\"structCCIPConfigTypes.ChainConfigInfo[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"name\":\"getCapabilityConfiguration\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"configuration\",\"type\":\"bytes\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getCapabilityRegistry\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"donId\",\"type\":\"uint32\"},{\"internalType\":\"enumInternal.OCRPluginType\",\"name\":\"pluginType\",\"type\":\"uint8\"}],\"name\":\"getOCRConfig\",\"outputs\":[{\"components\":[{\"components\":[{\"internalType\":\"enumInternal.OCRPluginType\",\"name\":\"pluginType\",\"type\":\"uint8\"},{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint8\",\"name\":\"F\",\"type\":\"uint8\"},{\"internalType\":\"uint64\",\"name\":\"offchainConfigVersion\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"offrampAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes32[]\",\"name\":\"p2pIds\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes[]\",\"name\":\"signers\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes[]\",\"name\":\"transmitters\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"}],\"internalType\":\"structCCIPConfigTypes.OCR3Config\",\"name\":\"config\",\"type\":\"tuple\"},{\"internalType\":\"uint64\",\"name\":\"configCount\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"}],\"internalType\":\"structCCIPConfigTypes.OCR3ConfigWithMeta[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", + Bin: "0x60a06040523480156200001157600080fd5b5060405162004080380380620040808339810160408190526200003491620001a6565b33806000816200008b5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000be57620000be81620000fb565b5050506001600160a01b038116620000e9576040516342bcdf7f60e11b815260040160405180910390fd5b6001600160a01b0316608052620001d8565b336001600160a01b03821603620001555760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000082565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b600060208284031215620001b957600080fd5b81516001600160a01b0381168114620001d157600080fd5b9392505050565b608051613e7f620002016000396000818160f801528181610ea701526111170152613e7f6000f3fe608060405234801561001057600080fd5b50600436106100c95760003560e01c80638318ed5d11610081578063f2fde38b1161005b578063f2fde38b1461020f578063f442c89a14610222578063fba64a7c1461023557600080fd5b80638318ed5d146101b05780638da5cb5b146101d1578063b74b2356146101ef57600080fd5b8063181f5a77116100b2578063181f5a771461013d5780634bd0473f1461018657806379ba5097146101a657600080fd5b806301ffc9a7146100ce578063020330e6146100f6575b600080fd5b6100e16100dc366004612cbd565b610248565b60405190151581526020015b60405180910390f35b7f00000000000000000000000000000000000000000000000000000000000000005b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100ed565b6101796040518060400160405280601481526020017f43434950436f6e66696720312e362e302d64657600000000000000000000000081525081565b6040516100ed9190612d63565b610199610194366004612da7565b6102e1565b6040516100ed9190612ec6565b6101ae610759565b005b6101796101be366004613082565b5060408051602081019091526000815290565b60005473ffffffffffffffffffffffffffffffffffffffff16610118565b6102026101fd36600461309f565b61085b565b6040516100ed9190613105565b6101ae61021d366004613195565b610adc565b6101ae610230366004613217565b610af0565b6101ae61024336600461329b565b610e8f565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f78bea7210000000000000000000000000000000000000000000000000000000014806102db57507fffffffff0000000000000000000000000000000000000000000000000000000082167f01ffc9a700000000000000000000000000000000000000000000000000000000145b92915050565b63ffffffff8216600090815260056020526040812060609183600181111561030b5761030b612ddc565b600181111561031c5761031c612ddc565b8152602001908152602001600020805480602002602001604051908101604052809291908181526020016000905b8282101561074d57600084815260209020604080516101808101909152600884029091018054829060608201908390829060ff16600181111561038f5761038f612ddc565b60018111156103a0576103a0612ddc565b8152815467ffffffffffffffff61010082048116602084015260ff690100000000000000000083041660408401526a01000000000000000000009091041660608201526001820180546080909201916103f890613358565b80601f016020809104026020016040519081016040528092919081815260200182805461042490613358565b80156104715780601f1061044657610100808354040283529160200191610471565b820191906000526020600020905b81548152906001019060200180831161045457829003601f168201915b50505050508152602001600282018054806020026020016040519081016040528092919081815260200182805480156104c957602002820191906000526020600020905b8154815260200190600101908083116104b5575b5050505050815260200160038201805480602002602001604051908101604052809291908181526020016000905b828210156105a357838290600052602060002001805461051690613358565b80601f016020809104026020016040519081016040528092919081815260200182805461054290613358565b801561058f5780601f106105645761010080835404028352916020019161058f565b820191906000526020600020905b81548152906001019060200180831161057257829003601f168201915b5050505050815260200190600101906104f7565b50505050815260200160048201805480602002602001604051908101604052809291908181526020016000905b8282101561067c5783829060005260206000200180546105ef90613358565b80601f016020809104026020016040519081016040528092919081815260200182805461061b90613358565b80156106685780601f1061063d57610100808354040283529160200191610668565b820191906000526020600020905b81548152906001019060200180831161064b57829003601f168201915b5050505050815260200190600101906105d0565b50505050815260200160058201805461069490613358565b80601f01602080910402602001604051908101604052809291908181526020018280546106c090613358565b801561070d5780601f106106e25761010080835404028352916020019161070d565b820191906000526020600020905b8154815290600101906020018083116106f057829003601f168201915b505050919092525050508152600682015467ffffffffffffffff16602080830191909152600790920154604090910152908252600192909201910161034a565b50505050905092915050565b60015473ffffffffffffffffffffffffffffffffffffffff1633146107df576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064015b60405180910390fd5b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b606060006108696003610f4a565b9050600061087784866133da565b90508315806108865750818110155b156108c65760408051600080825260208201909252906108bc565b6108a9612a5c565b8152602001906001900390816108a15790505b50925050506102db565b60006108d28583613420565b9050828111156108df5750815b60006108eb8383613433565b67ffffffffffffffff811115610903576109036133f1565b60405190808252806020026020018201604052801561093c57816020015b610929612a5c565b8152602001906001900390816109215790505b509050600061094b6003610f54565b9050835b83811015610acf57600082828151811061096b5761096b613446565b60209081029190910181015160408051808201825267ffffffffffffffff8316808252600090815260028552829020825181546080818802830181019095526060820181815295975092958601949093919284928491908401828280156109f157602002820191906000526020600020905b8154815260200190600101908083116109dd575b5050509183525050600182015460ff166020820152600282018054604090920191610a1b90613358565b80601f0160208091040260200160405190810160405280929190818152602001828054610a4790613358565b8015610a945780601f10610a6957610100808354040283529160200191610a94565b820191906000526020600020905b815481529060010190602001808311610a7757829003601f168201915b50505091909252505050905284610aab8885613433565b81518110610abb57610abb613446565b60209081029190910101525060010161094f565b5090979650505050505050565b610ae4610f68565b610aed81610feb565b50565b610af8610f68565b60005b83811015610cde57610b3f858583818110610b1857610b18613446565b9050602002016020810190610b2d9190613475565b60039067ffffffffffffffff166110e0565b610ba957848482818110610b5557610b55613446565b9050602002016020810190610b6a9190613475565b6040517f1bd4d2d200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff90911660048201526024016107d6565b60026000868684818110610bbf57610bbf613446565b9050602002016020810190610bd49190613475565b67ffffffffffffffff1681526020810191909152604001600090812090610bfb8282612aa4565b6001820180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055610c33600283016000612ac2565b5050610c71858583818110610c4a57610c4a613446565b9050602002016020810190610c5f9190613475565b60039067ffffffffffffffff166110f8565b507f2a680691fef3b2d105196805935232c661ce703e92d464ef0b94a7bc62d714f0858583818110610ca557610ca5613446565b9050602002016020810190610cba9190613475565b60405167ffffffffffffffff909116815260200160405180910390a1600101610afb565b5060005b81811015610e88576000838383818110610cfe57610cfe613446565b9050602002810190610d109190613490565b610d1e9060208101906134ce565b610d27906136d0565b90506000848484818110610d3d57610d3d613446565b9050602002810190610d4f9190613490565b610d5d906020810190613475565b9050610d6c8260000151611104565b816020015160ff16600003610dad576040517fa9b3766e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff81166000908152600260209081526040909120835180518593610ddd928492910190612afc565b5060208201516001820180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660ff90921691909117905560408201516002820190610e2a90826137b7565b50610e4491506003905067ffffffffffffffff8316611250565b507f05dd57854af2c291a94ea52e7c43d80bc3be7fa73022f98b735dea86642fa5e08183604051610e769291906138d1565b60405180910390a15050600101610ce2565b5050505050565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610efe576040517fac7a7efd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080610f15610f108688018861397c565b61125c565b8151919350915015610f2d57610f2d836000846114a7565b805115610f4057610f40836001836114a7565b5050505050505050565b60006102db825490565b60606000610f6183611c09565b9392505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314610fe9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e65720000000000000000000060448201526064016107d6565b565b3373ffffffffffffffffffffffffffffffffffffffff82160361106a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c6600000000000000000060448201526064016107d6565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b60008181526001830160205260408120541515610f61565b6000610f618383611c65565b60005b815181101561124c5760008019167f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166350c946fe84848151811061116357611163613446565b60200260200101516040518263ffffffff1660e01b815260040161118991815260200190565b600060405180830381865afa1580156111a6573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526111ec9190810190613bc7565b60800151036112445781818151811061120757611207613446565b60200260200101516040517f8907a4fa0000000000000000000000000000000000000000000000000000000081526004016107d691815260200190565b600101611107565b5050565b6000610f618383611d5f565b606080600460ff168351111561129e576040517f8854586400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805160028082526060820190925290816020015b61131b6040805161012081019091528060008152602001600067ffffffffffffffff168152602001600060ff168152602001600067ffffffffffffffff16815260200160608152602001606081526020016060815260200160608152602001606081525090565b8152602001906001900390816112b457505060408051600280825260608201909252919350602082015b6113ac6040805161012081019091528060008152602001600067ffffffffffffffff168152602001600060ff168152602001600067ffffffffffffffff16815260200160608152602001606081526020016060815260200160608152602001606081525090565b81526020019060019003908161134557905050905060008060005b855181101561149a5760008682815181106113e4576113e4613446565b602002602001015160000151600181111561140157611401612ddc565b0361144e5785818151811061141857611418613446565b602002602001015185848151811061143257611432613446565b60200260200101819052508261144790613c9f565b9250611492565b85818151811061146057611460613446565b602002602001015184838151811061147a5761147a613446565b60200260200101819052508161148f90613c9f565b91505b6001016113c7565b5090835281529092909150565b63ffffffff83166000908152600560205260408120818460018111156114cf576114cf612ddc565b60018111156114e0576114e0612ddc565b8152602001908152602001600020805480602002602001604051908101604052809291908181526020016000905b8282101561191157600084815260209020604080516101808101909152600884029091018054829060608201908390829060ff16600181111561155357611553612ddc565b600181111561156457611564612ddc565b8152815467ffffffffffffffff61010082048116602084015260ff690100000000000000000083041660408401526a01000000000000000000009091041660608201526001820180546080909201916115bc90613358565b80601f01602080910402602001604051908101604052809291908181526020018280546115e890613358565b80156116355780601f1061160a57610100808354040283529160200191611635565b820191906000526020600020905b81548152906001019060200180831161161857829003601f168201915b505050505081526020016002820180548060200260200160405190810160405280929190818152602001828054801561168d57602002820191906000526020600020905b815481526020019060010190808311611679575b5050505050815260200160038201805480602002602001604051908101604052809291908181526020016000905b828210156117675783829060005260206000200180546116da90613358565b80601f016020809104026020016040519081016040528092919081815260200182805461170690613358565b80156117535780601f1061172857610100808354040283529160200191611753565b820191906000526020600020905b81548152906001019060200180831161173657829003601f168201915b5050505050815260200190600101906116bb565b50505050815260200160048201805480602002602001604051908101604052809291908181526020016000905b828210156118405783829060005260206000200180546117b390613358565b80601f01602080910402602001604051908101604052809291908181526020018280546117df90613358565b801561182c5780601f106118015761010080835404028352916020019161182c565b820191906000526020600020905b81548152906001019060200180831161180f57829003601f168201915b505050505081526020019060010190611794565b50505050815260200160058201805461185890613358565b80601f016020809104026020016040519081016040528092919081815260200182805461188490613358565b80156118d15780601f106118a6576101008083540402835291602001916118d1565b820191906000526020600020905b8154815290600101906020018083116118b457829003601f168201915b505050919092525050508152600682015467ffffffffffffffff16602080830191909152600790920154604090910152908252600192909201910161150e565b50505050905060006119238251611dae565b905060006119318451611dae565b905061193d8282611e00565b600061194c8785878686611ebc565b905061195884826122a0565b63ffffffff871660009081526005602052604081209087600181111561198057611980612ddc565b600181111561199157611991612ddc565b815260200190815260200160002060006119ab9190612b47565b60005b8151811015610f405763ffffffff88166000908152600560205260408120908860018111156119df576119df612ddc565b60018111156119f0576119f0612ddc565b8152602001908152602001600020828281518110611a1057611a10613446565b6020908102919091018101518254600181810185556000948552929093208151805160089095029091018054929490939192849283917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016908381811115611a7a57611a7a612ddc565b021790555060208201518154604084015160608501517fffffffffffffffffffffffffffffffffffffffffffff000000000000000000ff90921661010067ffffffffffffffff948516027fffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffffff1617690100000000000000000060ff90921691909102177fffffffffffffffffffffffffffff0000000000000000ffffffffffffffffffff166a0100000000000000000000929091169190910217815560808201516001820190611b4990826137b7565b5060a08201518051611b65916002840191602090910190612afc565b5060c08201518051611b81916003840191602090910190612b68565b5060e08201518051611b9d916004840191602090910190612b68565b506101008201516005820190611bb390826137b7565b50505060208201516006820180547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001667ffffffffffffffff9092169190911790556040909101516007909101556001016119ae565b606081600001805480602002602001604051908101604052809291908181526020018280548015611c5957602002820191906000526020600020905b815481526020019060010190808311611c45575b50505050509050919050565b60008181526001830160205260408120548015611d4e576000611c89600183613433565b8554909150600090611c9d90600190613433565b9050808214611d02576000866000018281548110611cbd57611cbd613446565b9060005260206000200154905080876000018481548110611ce057611ce0613446565b6000918252602080832090910192909255918252600188019052604090208390555b8554869080611d1357611d13613cd7565b6001900381819060005260206000200160009055905585600101600086815260200190815260200160002060009055600193505050506102db565b60009150506102db565b5092915050565b6000818152600183016020526040812054611da6575081546001818101845560008481526020808220909301849055845484825282860190935260409020919091556102db565b5060006102db565b60006002821115611dee576040517f3e478526000000000000000000000000000000000000000000000000000000008152600481018390526024016107d6565b8160028111156102db576102db612ddc565b6000826002811115611e1457611e14612ddc565b826002811115611e2657611e26612ddc565b611e309190613d06565b90508060011480611e7c5750807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff148015611e7c57506002836002811115611e7a57611e7a612ddc565b145b15611e8657505050565b82826040517f0a6b675b0000000000000000000000000000000000000000000000000000000081526004016107d6929190613d36565b60606000845167ffffffffffffffff811115611eda57611eda6133f1565b604051908082528060200260200182016040528015611f03578160200160208202803683370190505b5090506000846002811115611f1a57611f1a612ddc565b148015611f3857506001836002811115611f3657611f36612ddc565b145b15611f7957600181600081518110611f5257611f52613446565b602002602001019067ffffffffffffffff16908167ffffffffffffffff16815250506120e1565b6001846002811115611f8d57611f8d612ddc565b148015611fab57506002836002811115611fa957611fa9612ddc565b145b156120425785600081518110611fc357611fc3613446565b60200260200101516020015181600081518110611fe257611fe2613446565b602002602001019067ffffffffffffffff16908167ffffffffffffffff16815250508560008151811061201757612017613446565b602002602001015160200151600161202f9190613d51565b81600181518110611f5257611f52613446565b600284600281111561205657612056612ddc565b1480156120745750600183600281111561207257612072612ddc565b145b156120ab578560018151811061208c5761208c613446565b60200260200101516020015181600081518110611f5257611f52613446565b83836040517f0a6b675b0000000000000000000000000000000000000000000000000000000081526004016107d6929190613d36565b6000855167ffffffffffffffff8111156120fd576120fd6133f1565b6040519080825280602002602001820160405280156121ab57816020015b6040805161018081018252600060608083018281526080840183905260a0840183905260c0840183905260e08401829052610100840182905261012084018290526101408401829052610160840191909152825260208083018290529282015282527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90920191018161211b5790505b50905060005b8251811015612294576121dc8782815181106121cf576121cf613446565b602002602001015161261f565b60405180606001604052808883815181106121f9576121f9613446565b6020026020010151815260200184838151811061221857612218613446565b602002602001015167ffffffffffffffff16815260200161226c8b86858151811061224557612245613446565b60200260200101518b868151811061225f5761225f613446565b602002602001015161298e565b81525082828151811061228157612281613446565b60209081029190910101526001016121b1565b50979650505050505050565b81518151811580156122b25750806001145b1561235457826000815181106122ca576122ca613446565b60200260200101516020015167ffffffffffffffff1660011461234e57826000815181106122fa576122fa613446565b60209081029190910181015101516040517fc1658eb800000000000000000000000000000000000000000000000000000000815267ffffffffffffffff9091166004820152600160248201526044016107d6565b50505050565b8160011480156123645750806002145b1561251a578360008151811061237c5761237c613446565b6020026020010151604001518360008151811061239b5761239b613446565b6020026020010151604001511461242757826000815181106123bf576123bf613446565b602002602001015160400151846000815181106123de576123de613446565b6020026020010151604001516040517fc7ccdd7f0000000000000000000000000000000000000000000000000000000081526004016107d6929190918252602082015260400190565b8360008151811061243a5761243a613446565b60200260200101516020015160016124529190613d51565b67ffffffffffffffff168360018151811061246f5761246f613446565b60200260200101516020015167ffffffffffffffff161461234e578260018151811061249d5761249d613446565b602002602001015160200151846000815181106124bc576124bc613446565b60200260200101516020015160016124d49190613d51565b6040517fc1658eb800000000000000000000000000000000000000000000000000000000815267ffffffffffffffff9283166004820152911660248201526044016107d6565b81600214801561252a5750806001145b156125ed578360018151811061254257612542613446565b6020026020010151604001518360008151811061256157612561613446565b6020026020010151604001511461234e578260008151811061258557612585613446565b602002602001015160400151846001815181106125a4576125a4613446565b6020026020010151604001516040517f9e9756700000000000000000000000000000000000000000000000000000000081526004016107d6929190918252602082015260400190565b6040517f1f1b2bb600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b806020015167ffffffffffffffff16600003612667576040517f698cf8e000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008151600181111561267c5761267c612ddc565b1415801561269d575060018151600181111561269a5761269a612ddc565b14155b156126d4576040517f3302dbd700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6080810151511580612711575060408051600060208201520160405160208183030381529060405280519060200120816080015180519060200120145b15612748576040517f358c192700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60208101516127639060039067ffffffffffffffff166110e0565b6127ab5760208101516040517f1bd4d2d200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff90911660048201526024016107d6565b60208082015167ffffffffffffffff166000908152600290915260408120600101546127db9060ff166003613d72565b6127e6906001613d8e565b60ff169050808260e0015151101561283b5760e0820151516040517f548dd21f0000000000000000000000000000000000000000000000000000000081526004810191909152602481018290526044016107d6565b60c08201515161010081111561287d576040517f1b925da600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8260a00151518114158061289657508260e00151518114155b156128f05760a08301515160c08401515160e0850151516040517fba900f6d0000000000000000000000000000000000000000000000000000000081526004810193909352602483019190915260448201526064016107d6565b826040015160ff16600003612931576040517f39d1a4d000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040830151612941906003613d72565b60ff16811161297c576040517f4856694e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6129898360a00151611104565b505050565b60008082602001518584600001518560800151878760a001518860c001518960e001518a604001518b606001518c61010001516040516020016129db9b9a99989796959493929190613da7565b604080518083037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe001815291905280516020909101207dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e0a000000000000000000000000000000000000000000000000000000000000179150509392505050565b6040518060400160405280600067ffffffffffffffff168152602001612a9f604051806060016040528060608152602001600060ff168152602001606081525090565b905290565b5080546000825590600052602060002090810190610aed9190612bba565b508054612ace90613358565b6000825580601f10612ade575050565b601f016020900490600052602060002090810190610aed9190612bba565b828054828255906000526020600020908101928215612b37579160200282015b82811115612b37578251825591602001919060010190612b1c565b50612b43929150612bba565b5090565b5080546000825560080290600052602060002090810190610aed9190612bcf565b828054828255906000526020600020908101928215612bae579160200282015b82811115612bae5782518290612b9e90826137b7565b5091602001919060010190612b88565b50612b43929150612c82565b5b80821115612b435760008155600101612bbb565b80821115612b435780547fffffffffffffffffffffffffffff00000000000000000000000000000000000016815560008181612c0e6001830182612ac2565b612c1c600283016000612aa4565b612c2a600383016000612c9f565b612c38600483016000612c9f565b612c46600583016000612ac2565b5050506006810180547fffffffffffffffffffffffffffffffffffffffffffffffff000000000000000016905560006007820155600801612bcf565b80821115612b43576000612c968282612ac2565b50600101612c82565b5080546000825590600052602060002090810190610aed9190612c82565b600060208284031215612ccf57600080fd5b81357fffffffff0000000000000000000000000000000000000000000000000000000081168114610f6157600080fd5b6000815180845260005b81811015612d2557602081850181015186830182015201612d09565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b602081526000610f616020830184612cff565b63ffffffff81168114610aed57600080fd5b8035612d9381612d76565b919050565b803560028110612d9357600080fd5b60008060408385031215612dba57600080fd5b8235612dc581612d76565b9150612dd360208401612d98565b90509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b60028110612e1b57612e1b612ddc565b9052565b60008151808452602080850194506020840160005b83811015612e5057815187529582019590820190600101612e34565b509495945050505050565b60008282518085526020808601955060208260051b8401016020860160005b84811015610acf577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0868403018952612eb4838351612cff565b98840198925090830190600101612e7a565b600060208083018184528085518083526040925060408601915060408160051b87010184880160005b83811015613074577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0898403018552815160608151818652612f348287018251612e0b565b898101516080612f4f8189018367ffffffffffffffff169052565b8a830151915060a0612f65818a018460ff169052565b938301519360c09250612f838984018667ffffffffffffffff169052565b818401519450610120915060e082818b0152612fa36101808b0187612cff565b95508185015191507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa0610100818c890301818d0152612fe28885612e1f565b958701518c87038301868e0152959750612ffc8887612e5b565b9750828701519550818c8903016101408d01526130198887612e5b565b975080870151965050808b8803016101608c0152505050505061303c8282612cff565b915050888201516130588a87018267ffffffffffffffff169052565b5090870151938701939093529386019390860190600101612eef565b509098975050505050505050565b60006020828403121561309457600080fd5b8135610f6181612d76565b600080604083850312156130b257600080fd5b50508035926020909101359150565b60008151606084526130d66060850182612e1f565b905060ff6020840151166020850152604083015184820360408601526130fc8282612cff565b95945050505050565b600060208083018184528085518083526040925060408601915060408160051b87010184880160005b83811015613074578883037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc00185528151805167ffffffffffffffff168452870151878401879052613182878501826130c1565b958801959350509086019060010161312e565b6000602082840312156131a757600080fd5b813573ffffffffffffffffffffffffffffffffffffffff81168114610f6157600080fd5b60008083601f8401126131dd57600080fd5b50813567ffffffffffffffff8111156131f557600080fd5b6020830191508360208260051b850101111561321057600080fd5b9250929050565b6000806000806040858703121561322d57600080fd5b843567ffffffffffffffff8082111561324557600080fd5b613251888389016131cb565b9096509450602087013591508082111561326a57600080fd5b50613277878288016131cb565b95989497509550505050565b803567ffffffffffffffff81168114612d9357600080fd5b600080600080600080608087890312156132b457600080fd5b863567ffffffffffffffff808211156132cc57600080fd5b6132d88a838b016131cb565b909850965060208901359150808211156132f157600080fd5b818901915089601f83011261330557600080fd5b81358181111561331457600080fd5b8a602082850101111561332657600080fd5b60208301965080955050505061333e60408801613283565b915061334c60608801612d88565b90509295509295509295565b600181811c9082168061336c57607f821691505b6020821081036133a5577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b80820281158282048414176102db576102db6133ab565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b808201808211156102db576102db6133ab565b818103818111156102db576102db6133ab565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60006020828403121561348757600080fd5b610f6182613283565b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc18336030181126134c457600080fd5b9190910192915050565b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa18336030181126134c457600080fd5b604051610120810167ffffffffffffffff81118282101715613526576135266133f1565b60405290565b60405160e0810167ffffffffffffffff81118282101715613526576135266133f1565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715613596576135966133f1565b604052919050565b600067ffffffffffffffff8211156135b8576135b86133f1565b5060051b60200190565b600082601f8301126135d357600080fd5b813560206135e86135e38361359e565b61354f565b8083825260208201915060208460051b87010193508684111561360a57600080fd5b602086015b84811015613626578035835291830191830161360f565b509695505050505050565b803560ff81168114612d9357600080fd5b600082601f83011261365357600080fd5b813567ffffffffffffffff81111561366d5761366d6133f1565b61369e60207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8401160161354f565b8181528460208386010111156136b357600080fd5b816020850160208301376000918101602001919091529392505050565b6000606082360312156136e257600080fd5b6040516060810167ffffffffffffffff8282108183111715613706576137066133f1565b81604052843591508082111561371b57600080fd5b613727368387016135c2565b835261373560208601613631565b6020840152604085013591508082111561374e57600080fd5b5061375b36828601613642565b60408301525092915050565b601f821115612989576000816000526020600020601f850160051c810160208610156137905750805b601f850160051c820191505b818110156137af5782815560010161379c565b505050505050565b815167ffffffffffffffff8111156137d1576137d16133f1565b6137e5816137df8454613358565b84613767565b602080601f83116001811461383857600084156138025750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b1785556137af565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b8281101561388557888601518255948401946001909101908401613866565b50858210156138c157878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b67ffffffffffffffff831681526040602082015260006138f460408301846130c1565b949350505050565b600082601f83011261390d57600080fd5b8135602061391d6135e38361359e565b82815260059290921b8401810191818101908684111561393c57600080fd5b8286015b8481101561362657803567ffffffffffffffff8111156139605760008081fd5b61396e8986838b0101613642565b845250918301918301613940565b6000602080838503121561398f57600080fd5b823567ffffffffffffffff808211156139a757600080fd5b818501915085601f8301126139bb57600080fd5b81356139c96135e38261359e565b81815260059190911b830184019084810190888311156139e857600080fd5b8585015b83811015613b5057803585811115613a0357600080fd5b8601610120818c037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe001811315613a3957600080fd5b613a41613502565b613a4c8a8401612d98565b8152613a5a60408401613283565b8a820152613a6a60608401613631565b6040820152613a7b60808401613283565b606082015260a083013588811115613a9257600080fd5b613aa08e8c83870101613642565b60808301525060c083013588811115613ab857600080fd5b613ac68e8c838701016135c2565b60a08301525060e083013588811115613adf5760008081fd5b613aed8e8c838701016138fc565b60c0830152506101008084013589811115613b085760008081fd5b613b168f8d838801016138fc565b60e084015250918301359188831115613b2f5760008081fd5b613b3d8e8c85870101613642565b90820152855250509186019186016139ec565b5098975050505050505050565b8051612d9381612d76565b600082601f830112613b7957600080fd5b81516020613b896135e38361359e565b8083825260208201915060208460051b870101935086841115613bab57600080fd5b602086015b848110156136265780518352918301918301613bb0565b600060208284031215613bd957600080fd5b815167ffffffffffffffff80821115613bf157600080fd5b9083019060e08286031215613c0557600080fd5b613c0d61352c565b613c1683613b5d565b8152613c2460208401613b5d565b6020820152613c3560408401613b5d565b6040820152606083015160608201526080830151608082015260a083015182811115613c6057600080fd5b613c6c87828601613b68565b60a08301525060c083015182811115613c8457600080fd5b613c9087828601613b68565b60c08301525095945050505050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203613cd057613cd06133ab565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b8181036000831280158383131683831282161715611d5857611d586133ab565b60038110612e1b57612e1b612ddc565b60408101613d448285613d26565b610f616020830184613d26565b67ffffffffffffffff818116838216019080821115611d5857611d586133ab565b60ff8181168382160290811690818114611d5857611d586133ab565b60ff81811683821601908111156102db576102db6133ab565b600061016067ffffffffffffffff8e16835263ffffffff8d166020840152613dd2604084018d612e0b565b806060840152613de48184018c612cff565b67ffffffffffffffff8b166080850152905082810360a0840152613e08818a612e1f565b905082810360c0840152613e1c8189612e5b565b905082810360e0840152613e308188612e5b565b60ff8716610100850152905067ffffffffffffffff8516610120840152828103610140840152613e608185612cff565b9e9d505050505050505050505050505056fea164736f6c6343000818000a", +} + +var CCIPConfigABI = CCIPConfigMetaData.ABI + +var CCIPConfigBin = CCIPConfigMetaData.Bin + +func DeployCCIPConfig(auth *bind.TransactOpts, backend bind.ContractBackend, capabilitiesRegistry common.Address) (common.Address, *types.Transaction, *CCIPConfig, error) { + parsed, err := CCIPConfigMetaData.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(CCIPConfigBin), backend, capabilitiesRegistry) + if err != nil { + return common.Address{}, nil, nil, err + } + return address, tx, &CCIPConfig{address: address, abi: *parsed, CCIPConfigCaller: CCIPConfigCaller{contract: contract}, CCIPConfigTransactor: CCIPConfigTransactor{contract: contract}, CCIPConfigFilterer: CCIPConfigFilterer{contract: contract}}, nil +} + +type CCIPConfig struct { + address common.Address + abi abi.ABI + CCIPConfigCaller + CCIPConfigTransactor + CCIPConfigFilterer +} + +type CCIPConfigCaller struct { + contract *bind.BoundContract +} + +type CCIPConfigTransactor struct { + contract *bind.BoundContract +} + +type CCIPConfigFilterer struct { + contract *bind.BoundContract +} + +type CCIPConfigSession struct { + Contract *CCIPConfig + CallOpts bind.CallOpts + TransactOpts bind.TransactOpts +} + +type CCIPConfigCallerSession struct { + Contract *CCIPConfigCaller + CallOpts bind.CallOpts +} + +type CCIPConfigTransactorSession struct { + Contract *CCIPConfigTransactor + TransactOpts bind.TransactOpts +} + +type CCIPConfigRaw struct { + Contract *CCIPConfig +} + +type CCIPConfigCallerRaw struct { + Contract *CCIPConfigCaller +} + +type CCIPConfigTransactorRaw struct { + Contract *CCIPConfigTransactor +} + +func NewCCIPConfig(address common.Address, backend bind.ContractBackend) (*CCIPConfig, error) { + abi, err := abi.JSON(strings.NewReader(CCIPConfigABI)) + if err != nil { + return nil, err + } + contract, err := bindCCIPConfig(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &CCIPConfig{address: address, abi: abi, CCIPConfigCaller: CCIPConfigCaller{contract: contract}, CCIPConfigTransactor: CCIPConfigTransactor{contract: contract}, CCIPConfigFilterer: CCIPConfigFilterer{contract: contract}}, nil +} + +func NewCCIPConfigCaller(address common.Address, caller bind.ContractCaller) (*CCIPConfigCaller, error) { + contract, err := bindCCIPConfig(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &CCIPConfigCaller{contract: contract}, nil +} + +func NewCCIPConfigTransactor(address common.Address, transactor bind.ContractTransactor) (*CCIPConfigTransactor, error) { + contract, err := bindCCIPConfig(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &CCIPConfigTransactor{contract: contract}, nil +} + +func NewCCIPConfigFilterer(address common.Address, filterer bind.ContractFilterer) (*CCIPConfigFilterer, error) { + contract, err := bindCCIPConfig(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &CCIPConfigFilterer{contract: contract}, nil +} + +func bindCCIPConfig(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := CCIPConfigMetaData.GetAbi() + if err != nil { + return nil, err + } + return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil +} + +func (_CCIPConfig *CCIPConfigRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _CCIPConfig.Contract.CCIPConfigCaller.contract.Call(opts, result, method, params...) +} + +func (_CCIPConfig *CCIPConfigRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _CCIPConfig.Contract.CCIPConfigTransactor.contract.Transfer(opts) +} + +func (_CCIPConfig *CCIPConfigRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _CCIPConfig.Contract.CCIPConfigTransactor.contract.Transact(opts, method, params...) +} + +func (_CCIPConfig *CCIPConfigCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _CCIPConfig.Contract.contract.Call(opts, result, method, params...) +} + +func (_CCIPConfig *CCIPConfigTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _CCIPConfig.Contract.contract.Transfer(opts) +} + +func (_CCIPConfig *CCIPConfigTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _CCIPConfig.Contract.contract.Transact(opts, method, params...) +} + +func (_CCIPConfig *CCIPConfigCaller) GetAllChainConfigs(opts *bind.CallOpts, pageIndex *big.Int, pageSize *big.Int) ([]CCIPConfigTypesChainConfigInfo, error) { + var out []interface{} + err := _CCIPConfig.contract.Call(opts, &out, "getAllChainConfigs", pageIndex, pageSize) + + if err != nil { + return *new([]CCIPConfigTypesChainConfigInfo), err + } + + out0 := *abi.ConvertType(out[0], new([]CCIPConfigTypesChainConfigInfo)).(*[]CCIPConfigTypesChainConfigInfo) + + return out0, err + +} + +func (_CCIPConfig *CCIPConfigSession) GetAllChainConfigs(pageIndex *big.Int, pageSize *big.Int) ([]CCIPConfigTypesChainConfigInfo, error) { + return _CCIPConfig.Contract.GetAllChainConfigs(&_CCIPConfig.CallOpts, pageIndex, pageSize) +} + +func (_CCIPConfig *CCIPConfigCallerSession) GetAllChainConfigs(pageIndex *big.Int, pageSize *big.Int) ([]CCIPConfigTypesChainConfigInfo, error) { + return _CCIPConfig.Contract.GetAllChainConfigs(&_CCIPConfig.CallOpts, pageIndex, pageSize) +} + +func (_CCIPConfig *CCIPConfigCaller) GetCapabilityConfiguration(opts *bind.CallOpts, arg0 uint32) ([]byte, error) { + var out []interface{} + err := _CCIPConfig.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 (_CCIPConfig *CCIPConfigSession) GetCapabilityConfiguration(arg0 uint32) ([]byte, error) { + return _CCIPConfig.Contract.GetCapabilityConfiguration(&_CCIPConfig.CallOpts, arg0) +} + +func (_CCIPConfig *CCIPConfigCallerSession) GetCapabilityConfiguration(arg0 uint32) ([]byte, error) { + return _CCIPConfig.Contract.GetCapabilityConfiguration(&_CCIPConfig.CallOpts, arg0) +} + +func (_CCIPConfig *CCIPConfigCaller) GetCapabilityRegistry(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _CCIPConfig.contract.Call(opts, &out, "getCapabilityRegistry") + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +func (_CCIPConfig *CCIPConfigSession) GetCapabilityRegistry() (common.Address, error) { + return _CCIPConfig.Contract.GetCapabilityRegistry(&_CCIPConfig.CallOpts) +} + +func (_CCIPConfig *CCIPConfigCallerSession) GetCapabilityRegistry() (common.Address, error) { + return _CCIPConfig.Contract.GetCapabilityRegistry(&_CCIPConfig.CallOpts) +} + +func (_CCIPConfig *CCIPConfigCaller) GetOCRConfig(opts *bind.CallOpts, donId uint32, pluginType uint8) ([]CCIPConfigTypesOCR3ConfigWithMeta, error) { + var out []interface{} + err := _CCIPConfig.contract.Call(opts, &out, "getOCRConfig", donId, pluginType) + + if err != nil { + return *new([]CCIPConfigTypesOCR3ConfigWithMeta), err + } + + out0 := *abi.ConvertType(out[0], new([]CCIPConfigTypesOCR3ConfigWithMeta)).(*[]CCIPConfigTypesOCR3ConfigWithMeta) + + return out0, err + +} + +func (_CCIPConfig *CCIPConfigSession) GetOCRConfig(donId uint32, pluginType uint8) ([]CCIPConfigTypesOCR3ConfigWithMeta, error) { + return _CCIPConfig.Contract.GetOCRConfig(&_CCIPConfig.CallOpts, donId, pluginType) +} + +func (_CCIPConfig *CCIPConfigCallerSession) GetOCRConfig(donId uint32, pluginType uint8) ([]CCIPConfigTypesOCR3ConfigWithMeta, error) { + return _CCIPConfig.Contract.GetOCRConfig(&_CCIPConfig.CallOpts, donId, pluginType) +} + +func (_CCIPConfig *CCIPConfigCaller) Owner(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _CCIPConfig.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 (_CCIPConfig *CCIPConfigSession) Owner() (common.Address, error) { + return _CCIPConfig.Contract.Owner(&_CCIPConfig.CallOpts) +} + +func (_CCIPConfig *CCIPConfigCallerSession) Owner() (common.Address, error) { + return _CCIPConfig.Contract.Owner(&_CCIPConfig.CallOpts) +} + +func (_CCIPConfig *CCIPConfigCaller) SupportsInterface(opts *bind.CallOpts, interfaceId [4]byte) (bool, error) { + var out []interface{} + err := _CCIPConfig.contract.Call(opts, &out, "supportsInterface", interfaceId) + + if err != nil { + return *new(bool), err + } + + out0 := *abi.ConvertType(out[0], new(bool)).(*bool) + + return out0, err + +} + +func (_CCIPConfig *CCIPConfigSession) SupportsInterface(interfaceId [4]byte) (bool, error) { + return _CCIPConfig.Contract.SupportsInterface(&_CCIPConfig.CallOpts, interfaceId) +} + +func (_CCIPConfig *CCIPConfigCallerSession) SupportsInterface(interfaceId [4]byte) (bool, error) { + return _CCIPConfig.Contract.SupportsInterface(&_CCIPConfig.CallOpts, interfaceId) +} + +func (_CCIPConfig *CCIPConfigCaller) TypeAndVersion(opts *bind.CallOpts) (string, error) { + var out []interface{} + err := _CCIPConfig.contract.Call(opts, &out, "typeAndVersion") + + if err != nil { + return *new(string), err + } + + out0 := *abi.ConvertType(out[0], new(string)).(*string) + + return out0, err + +} + +func (_CCIPConfig *CCIPConfigSession) TypeAndVersion() (string, error) { + return _CCIPConfig.Contract.TypeAndVersion(&_CCIPConfig.CallOpts) +} + +func (_CCIPConfig *CCIPConfigCallerSession) TypeAndVersion() (string, error) { + return _CCIPConfig.Contract.TypeAndVersion(&_CCIPConfig.CallOpts) +} + +func (_CCIPConfig *CCIPConfigTransactor) AcceptOwnership(opts *bind.TransactOpts) (*types.Transaction, error) { + return _CCIPConfig.contract.Transact(opts, "acceptOwnership") +} + +func (_CCIPConfig *CCIPConfigSession) AcceptOwnership() (*types.Transaction, error) { + return _CCIPConfig.Contract.AcceptOwnership(&_CCIPConfig.TransactOpts) +} + +func (_CCIPConfig *CCIPConfigTransactorSession) AcceptOwnership() (*types.Transaction, error) { + return _CCIPConfig.Contract.AcceptOwnership(&_CCIPConfig.TransactOpts) +} + +func (_CCIPConfig *CCIPConfigTransactor) ApplyChainConfigUpdates(opts *bind.TransactOpts, chainSelectorRemoves []uint64, chainConfigAdds []CCIPConfigTypesChainConfigInfo) (*types.Transaction, error) { + return _CCIPConfig.contract.Transact(opts, "applyChainConfigUpdates", chainSelectorRemoves, chainConfigAdds) +} + +func (_CCIPConfig *CCIPConfigSession) ApplyChainConfigUpdates(chainSelectorRemoves []uint64, chainConfigAdds []CCIPConfigTypesChainConfigInfo) (*types.Transaction, error) { + return _CCIPConfig.Contract.ApplyChainConfigUpdates(&_CCIPConfig.TransactOpts, chainSelectorRemoves, chainConfigAdds) +} + +func (_CCIPConfig *CCIPConfigTransactorSession) ApplyChainConfigUpdates(chainSelectorRemoves []uint64, chainConfigAdds []CCIPConfigTypesChainConfigInfo) (*types.Transaction, error) { + return _CCIPConfig.Contract.ApplyChainConfigUpdates(&_CCIPConfig.TransactOpts, chainSelectorRemoves, chainConfigAdds) +} + +func (_CCIPConfig *CCIPConfigTransactor) BeforeCapabilityConfigSet(opts *bind.TransactOpts, arg0 [][32]byte, config []byte, arg2 uint64, donId uint32) (*types.Transaction, error) { + return _CCIPConfig.contract.Transact(opts, "beforeCapabilityConfigSet", arg0, config, arg2, donId) +} + +func (_CCIPConfig *CCIPConfigSession) BeforeCapabilityConfigSet(arg0 [][32]byte, config []byte, arg2 uint64, donId uint32) (*types.Transaction, error) { + return _CCIPConfig.Contract.BeforeCapabilityConfigSet(&_CCIPConfig.TransactOpts, arg0, config, arg2, donId) +} + +func (_CCIPConfig *CCIPConfigTransactorSession) BeforeCapabilityConfigSet(arg0 [][32]byte, config []byte, arg2 uint64, donId uint32) (*types.Transaction, error) { + return _CCIPConfig.Contract.BeforeCapabilityConfigSet(&_CCIPConfig.TransactOpts, arg0, config, arg2, donId) +} + +func (_CCIPConfig *CCIPConfigTransactor) TransferOwnership(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) { + return _CCIPConfig.contract.Transact(opts, "transferOwnership", to) +} + +func (_CCIPConfig *CCIPConfigSession) TransferOwnership(to common.Address) (*types.Transaction, error) { + return _CCIPConfig.Contract.TransferOwnership(&_CCIPConfig.TransactOpts, to) +} + +func (_CCIPConfig *CCIPConfigTransactorSession) TransferOwnership(to common.Address) (*types.Transaction, error) { + return _CCIPConfig.Contract.TransferOwnership(&_CCIPConfig.TransactOpts, to) +} + +type CCIPConfigCapabilityConfigurationSetIterator struct { + Event *CCIPConfigCapabilityConfigurationSet + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *CCIPConfigCapabilityConfigurationSetIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(CCIPConfigCapabilityConfigurationSet) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(CCIPConfigCapabilityConfigurationSet) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *CCIPConfigCapabilityConfigurationSetIterator) Error() error { + return it.fail +} + +func (it *CCIPConfigCapabilityConfigurationSetIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type CCIPConfigCapabilityConfigurationSet struct { + Raw types.Log +} + +func (_CCIPConfig *CCIPConfigFilterer) FilterCapabilityConfigurationSet(opts *bind.FilterOpts) (*CCIPConfigCapabilityConfigurationSetIterator, error) { + + logs, sub, err := _CCIPConfig.contract.FilterLogs(opts, "CapabilityConfigurationSet") + if err != nil { + return nil, err + } + return &CCIPConfigCapabilityConfigurationSetIterator{contract: _CCIPConfig.contract, event: "CapabilityConfigurationSet", logs: logs, sub: sub}, nil +} + +func (_CCIPConfig *CCIPConfigFilterer) WatchCapabilityConfigurationSet(opts *bind.WatchOpts, sink chan<- *CCIPConfigCapabilityConfigurationSet) (event.Subscription, error) { + + logs, sub, err := _CCIPConfig.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(CCIPConfigCapabilityConfigurationSet) + if err := _CCIPConfig.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 (_CCIPConfig *CCIPConfigFilterer) ParseCapabilityConfigurationSet(log types.Log) (*CCIPConfigCapabilityConfigurationSet, error) { + event := new(CCIPConfigCapabilityConfigurationSet) + if err := _CCIPConfig.contract.UnpackLog(event, "CapabilityConfigurationSet", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type CCIPConfigChainConfigRemovedIterator struct { + Event *CCIPConfigChainConfigRemoved + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *CCIPConfigChainConfigRemovedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(CCIPConfigChainConfigRemoved) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(CCIPConfigChainConfigRemoved) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *CCIPConfigChainConfigRemovedIterator) Error() error { + return it.fail +} + +func (it *CCIPConfigChainConfigRemovedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type CCIPConfigChainConfigRemoved struct { + ChainSelector uint64 + Raw types.Log +} + +func (_CCIPConfig *CCIPConfigFilterer) FilterChainConfigRemoved(opts *bind.FilterOpts) (*CCIPConfigChainConfigRemovedIterator, error) { + + logs, sub, err := _CCIPConfig.contract.FilterLogs(opts, "ChainConfigRemoved") + if err != nil { + return nil, err + } + return &CCIPConfigChainConfigRemovedIterator{contract: _CCIPConfig.contract, event: "ChainConfigRemoved", logs: logs, sub: sub}, nil +} + +func (_CCIPConfig *CCIPConfigFilterer) WatchChainConfigRemoved(opts *bind.WatchOpts, sink chan<- *CCIPConfigChainConfigRemoved) (event.Subscription, error) { + + logs, sub, err := _CCIPConfig.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(CCIPConfigChainConfigRemoved) + if err := _CCIPConfig.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 (_CCIPConfig *CCIPConfigFilterer) ParseChainConfigRemoved(log types.Log) (*CCIPConfigChainConfigRemoved, error) { + event := new(CCIPConfigChainConfigRemoved) + if err := _CCIPConfig.contract.UnpackLog(event, "ChainConfigRemoved", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type CCIPConfigChainConfigSetIterator struct { + Event *CCIPConfigChainConfigSet + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *CCIPConfigChainConfigSetIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(CCIPConfigChainConfigSet) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(CCIPConfigChainConfigSet) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *CCIPConfigChainConfigSetIterator) Error() error { + return it.fail +} + +func (it *CCIPConfigChainConfigSetIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type CCIPConfigChainConfigSet struct { + ChainSelector uint64 + ChainConfig CCIPConfigTypesChainConfig + Raw types.Log +} + +func (_CCIPConfig *CCIPConfigFilterer) FilterChainConfigSet(opts *bind.FilterOpts) (*CCIPConfigChainConfigSetIterator, error) { + + logs, sub, err := _CCIPConfig.contract.FilterLogs(opts, "ChainConfigSet") + if err != nil { + return nil, err + } + return &CCIPConfigChainConfigSetIterator{contract: _CCIPConfig.contract, event: "ChainConfigSet", logs: logs, sub: sub}, nil +} + +func (_CCIPConfig *CCIPConfigFilterer) WatchChainConfigSet(opts *bind.WatchOpts, sink chan<- *CCIPConfigChainConfigSet) (event.Subscription, error) { + + logs, sub, err := _CCIPConfig.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(CCIPConfigChainConfigSet) + if err := _CCIPConfig.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 (_CCIPConfig *CCIPConfigFilterer) ParseChainConfigSet(log types.Log) (*CCIPConfigChainConfigSet, error) { + event := new(CCIPConfigChainConfigSet) + if err := _CCIPConfig.contract.UnpackLog(event, "ChainConfigSet", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type CCIPConfigOwnershipTransferRequestedIterator struct { + Event *CCIPConfigOwnershipTransferRequested + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *CCIPConfigOwnershipTransferRequestedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(CCIPConfigOwnershipTransferRequested) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(CCIPConfigOwnershipTransferRequested) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *CCIPConfigOwnershipTransferRequestedIterator) Error() error { + return it.fail +} + +func (it *CCIPConfigOwnershipTransferRequestedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type CCIPConfigOwnershipTransferRequested struct { + From common.Address + To common.Address + Raw types.Log +} + +func (_CCIPConfig *CCIPConfigFilterer) FilterOwnershipTransferRequested(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*CCIPConfigOwnershipTransferRequestedIterator, 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 := _CCIPConfig.contract.FilterLogs(opts, "OwnershipTransferRequested", fromRule, toRule) + if err != nil { + return nil, err + } + return &CCIPConfigOwnershipTransferRequestedIterator{contract: _CCIPConfig.contract, event: "OwnershipTransferRequested", logs: logs, sub: sub}, nil +} + +func (_CCIPConfig *CCIPConfigFilterer) WatchOwnershipTransferRequested(opts *bind.WatchOpts, sink chan<- *CCIPConfigOwnershipTransferRequested, 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 := _CCIPConfig.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(CCIPConfigOwnershipTransferRequested) + if err := _CCIPConfig.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 (_CCIPConfig *CCIPConfigFilterer) ParseOwnershipTransferRequested(log types.Log) (*CCIPConfigOwnershipTransferRequested, error) { + event := new(CCIPConfigOwnershipTransferRequested) + if err := _CCIPConfig.contract.UnpackLog(event, "OwnershipTransferRequested", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type CCIPConfigOwnershipTransferredIterator struct { + Event *CCIPConfigOwnershipTransferred + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *CCIPConfigOwnershipTransferredIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(CCIPConfigOwnershipTransferred) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(CCIPConfigOwnershipTransferred) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *CCIPConfigOwnershipTransferredIterator) Error() error { + return it.fail +} + +func (it *CCIPConfigOwnershipTransferredIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type CCIPConfigOwnershipTransferred struct { + From common.Address + To common.Address + Raw types.Log +} + +func (_CCIPConfig *CCIPConfigFilterer) FilterOwnershipTransferred(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*CCIPConfigOwnershipTransferredIterator, 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 := _CCIPConfig.contract.FilterLogs(opts, "OwnershipTransferred", fromRule, toRule) + if err != nil { + return nil, err + } + return &CCIPConfigOwnershipTransferredIterator{contract: _CCIPConfig.contract, event: "OwnershipTransferred", logs: logs, sub: sub}, nil +} + +func (_CCIPConfig *CCIPConfigFilterer) WatchOwnershipTransferred(opts *bind.WatchOpts, sink chan<- *CCIPConfigOwnershipTransferred, 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 := _CCIPConfig.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(CCIPConfigOwnershipTransferred) + if err := _CCIPConfig.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 (_CCIPConfig *CCIPConfigFilterer) ParseOwnershipTransferred(log types.Log) (*CCIPConfigOwnershipTransferred, error) { + event := new(CCIPConfigOwnershipTransferred) + if err := _CCIPConfig.contract.UnpackLog(event, "OwnershipTransferred", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +func (_CCIPConfig *CCIPConfig) ParseLog(log types.Log) (generated.AbigenLog, error) { + switch log.Topics[0] { + case _CCIPConfig.abi.Events["CapabilityConfigurationSet"].ID: + return _CCIPConfig.ParseCapabilityConfigurationSet(log) + case _CCIPConfig.abi.Events["ChainConfigRemoved"].ID: + return _CCIPConfig.ParseChainConfigRemoved(log) + case _CCIPConfig.abi.Events["ChainConfigSet"].ID: + return _CCIPConfig.ParseChainConfigSet(log) + case _CCIPConfig.abi.Events["OwnershipTransferRequested"].ID: + return _CCIPConfig.ParseOwnershipTransferRequested(log) + case _CCIPConfig.abi.Events["OwnershipTransferred"].ID: + return _CCIPConfig.ParseOwnershipTransferred(log) + + default: + return nil, fmt.Errorf("abigen wrapper received unknown log topic: %v", log.Topics[0]) + } +} + +func (CCIPConfigCapabilityConfigurationSet) Topic() common.Hash { + return common.HexToHash("0x84ad7751b744c9e2ee77da1d902b428aec7f0a343d67a24bbe2142e6f58a8d0f") +} + +func (CCIPConfigChainConfigRemoved) Topic() common.Hash { + return common.HexToHash("0x2a680691fef3b2d105196805935232c661ce703e92d464ef0b94a7bc62d714f0") +} + +func (CCIPConfigChainConfigSet) Topic() common.Hash { + return common.HexToHash("0x05dd57854af2c291a94ea52e7c43d80bc3be7fa73022f98b735dea86642fa5e0") +} + +func (CCIPConfigOwnershipTransferRequested) Topic() common.Hash { + return common.HexToHash("0xed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae1278") +} + +func (CCIPConfigOwnershipTransferred) Topic() common.Hash { + return common.HexToHash("0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0") +} + +func (_CCIPConfig *CCIPConfig) Address() common.Address { + return _CCIPConfig.address +} + +type CCIPConfigInterface interface { + GetAllChainConfigs(opts *bind.CallOpts, pageIndex *big.Int, pageSize *big.Int) ([]CCIPConfigTypesChainConfigInfo, error) + + GetCapabilityConfiguration(opts *bind.CallOpts, arg0 uint32) ([]byte, error) + + GetCapabilityRegistry(opts *bind.CallOpts) (common.Address, error) + + GetOCRConfig(opts *bind.CallOpts, donId uint32, pluginType uint8) ([]CCIPConfigTypesOCR3ConfigWithMeta, error) + + Owner(opts *bind.CallOpts) (common.Address, error) + + SupportsInterface(opts *bind.CallOpts, interfaceId [4]byte) (bool, error) + + TypeAndVersion(opts *bind.CallOpts) (string, error) + + AcceptOwnership(opts *bind.TransactOpts) (*types.Transaction, error) + + ApplyChainConfigUpdates(opts *bind.TransactOpts, chainSelectorRemoves []uint64, chainConfigAdds []CCIPConfigTypesChainConfigInfo) (*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) (*CCIPConfigCapabilityConfigurationSetIterator, error) + + WatchCapabilityConfigurationSet(opts *bind.WatchOpts, sink chan<- *CCIPConfigCapabilityConfigurationSet) (event.Subscription, error) + + ParseCapabilityConfigurationSet(log types.Log) (*CCIPConfigCapabilityConfigurationSet, error) + + FilterChainConfigRemoved(opts *bind.FilterOpts) (*CCIPConfigChainConfigRemovedIterator, error) + + WatchChainConfigRemoved(opts *bind.WatchOpts, sink chan<- *CCIPConfigChainConfigRemoved) (event.Subscription, error) + + ParseChainConfigRemoved(log types.Log) (*CCIPConfigChainConfigRemoved, error) + + FilterChainConfigSet(opts *bind.FilterOpts) (*CCIPConfigChainConfigSetIterator, error) + + WatchChainConfigSet(opts *bind.WatchOpts, sink chan<- *CCIPConfigChainConfigSet) (event.Subscription, error) + + ParseChainConfigSet(log types.Log) (*CCIPConfigChainConfigSet, error) + + FilterOwnershipTransferRequested(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*CCIPConfigOwnershipTransferRequestedIterator, error) + + WatchOwnershipTransferRequested(opts *bind.WatchOpts, sink chan<- *CCIPConfigOwnershipTransferRequested, from []common.Address, to []common.Address) (event.Subscription, error) + + ParseOwnershipTransferRequested(log types.Log) (*CCIPConfigOwnershipTransferRequested, error) + + FilterOwnershipTransferred(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*CCIPConfigOwnershipTransferredIterator, error) + + WatchOwnershipTransferred(opts *bind.WatchOpts, sink chan<- *CCIPConfigOwnershipTransferred, from []common.Address, to []common.Address) (event.Subscription, error) + + ParseOwnershipTransferred(log types.Log) (*CCIPConfigOwnershipTransferred, error) + + ParseLog(log types.Log) (generated.AbigenLog, error) + + Address() common.Address +} diff --git a/core/gethwrappers/ccip/generated/ccip_home/ccip_home.go b/core/gethwrappers/ccip/generated/ccip_home/ccip_home.go index 2554265dcc8..b44dc9a5f96 100644 --- a/core/gethwrappers/ccip/generated/ccip_home/ccip_home.go +++ b/core/gethwrappers/ccip/generated/ccip_home/ccip_home.go @@ -65,8 +65,8 @@ type CCIPHomeVersionedConfig struct { } var CCIPHomeMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"capabilitiesRegistry\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"CanOnlySelfCall\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CannotTransferToSelf\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"}],\"name\":\"ChainSelectorNotFound\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ChainSelectorNotSet\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"expectedConfigDigest\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"gotConfigDigest\",\"type\":\"bytes32\"}],\"name\":\"ConfigDigestMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"callDonId\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"capabilityRegistryDonId\",\"type\":\"uint32\"}],\"name\":\"DONIdMismatch\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FChainMustBePositive\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"fChain\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"FRoleDON\",\"type\":\"uint256\"}],\"name\":\"FChainTooHigh\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FTooHigh\",\"type\":\"error\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"p2pId\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"signerKey\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"transmitterKey\",\"type\":\"bytes\"}],\"internalType\":\"structCCIPHome.OCR3Node\",\"name\":\"node\",\"type\":\"tuple\"}],\"name\":\"InvalidNode\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidPluginType\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"selector\",\"type\":\"bytes4\"}],\"name\":\"InvalidSelector\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MustBeProposedOwner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NoOpStateTransitionNotAllowed\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"got\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"minimum\",\"type\":\"uint256\"}],\"name\":\"NotEnoughTransmitters\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OfframpAddressCannotBeZero\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByOwner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCapabilitiesRegistryCanCall\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OwnerCannotBeZero\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RMNHomeAddressCannotBeZero\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RevokingZeroDigestNotAllowed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TooManySigners\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"}],\"name\":\"ActiveConfigRevoked\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"}],\"name\":\"CandidateConfigRevoked\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[],\"name\":\"CapabilityConfigurationSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"}],\"name\":\"ChainConfigRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bytes32[]\",\"name\":\"readers\",\"type\":\"bytes32[]\"},{\"internalType\":\"uint8\",\"name\":\"fChain\",\"type\":\"uint8\"},{\"internalType\":\"bytes\",\"name\":\"config\",\"type\":\"bytes\"}],\"indexed\":false,\"internalType\":\"structCCIPHome.ChainConfig\",\"name\":\"chainConfig\",\"type\":\"tuple\"}],\"name\":\"ChainConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"}],\"name\":\"ConfigPromoted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"version\",\"type\":\"uint32\"},{\"components\":[{\"internalType\":\"enumInternal.OCRPluginType\",\"name\":\"pluginType\",\"type\":\"uint8\"},{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint8\",\"name\":\"FRoleDON\",\"type\":\"uint8\"},{\"internalType\":\"uint64\",\"name\":\"offchainConfigVersion\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"offrampAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"rmnHomeAddress\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"p2pId\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"signerKey\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"transmitterKey\",\"type\":\"bytes\"}],\"internalType\":\"structCCIPHome.OCR3Node[]\",\"name\":\"nodes\",\"type\":\"tuple[]\"},{\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"}],\"indexed\":false,\"internalType\":\"structCCIPHome.OCR3Config\",\"name\":\"config\",\"type\":\"tuple\"}],\"name\":\"ConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64[]\",\"name\":\"chainSelectorRemoves\",\"type\":\"uint64[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bytes32[]\",\"name\":\"readers\",\"type\":\"bytes32[]\"},{\"internalType\":\"uint8\",\"name\":\"fChain\",\"type\":\"uint8\"},{\"internalType\":\"bytes\",\"name\":\"config\",\"type\":\"bytes\"}],\"internalType\":\"structCCIPHome.ChainConfig\",\"name\":\"chainConfig\",\"type\":\"tuple\"}],\"internalType\":\"structCCIPHome.ChainConfigArgs[]\",\"name\":\"chainConfigAdds\",\"type\":\"tuple[]\"}],\"name\":\"applyChainConfigUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[]\",\"name\":\"\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes\",\"name\":\"update\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"donId\",\"type\":\"uint32\"}],\"name\":\"beforeCapabilityConfigSet\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"donId\",\"type\":\"uint32\"},{\"internalType\":\"enumInternal.OCRPluginType\",\"name\":\"pluginType\",\"type\":\"uint8\"}],\"name\":\"getActiveDigest\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"pageIndex\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"pageSize\",\"type\":\"uint256\"}],\"name\":\"getAllChainConfigs\",\"outputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bytes32[]\",\"name\":\"readers\",\"type\":\"bytes32[]\"},{\"internalType\":\"uint8\",\"name\":\"fChain\",\"type\":\"uint8\"},{\"internalType\":\"bytes\",\"name\":\"config\",\"type\":\"bytes\"}],\"internalType\":\"structCCIPHome.ChainConfig\",\"name\":\"chainConfig\",\"type\":\"tuple\"}],\"internalType\":\"structCCIPHome.ChainConfigArgs[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"donId\",\"type\":\"uint32\"},{\"internalType\":\"enumInternal.OCRPluginType\",\"name\":\"pluginType\",\"type\":\"uint8\"}],\"name\":\"getAllConfigs\",\"outputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"version\",\"type\":\"uint32\"},{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"components\":[{\"internalType\":\"enumInternal.OCRPluginType\",\"name\":\"pluginType\",\"type\":\"uint8\"},{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint8\",\"name\":\"FRoleDON\",\"type\":\"uint8\"},{\"internalType\":\"uint64\",\"name\":\"offchainConfigVersion\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"offrampAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"rmnHomeAddress\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"p2pId\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"signerKey\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"transmitterKey\",\"type\":\"bytes\"}],\"internalType\":\"structCCIPHome.OCR3Node[]\",\"name\":\"nodes\",\"type\":\"tuple[]\"},{\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"}],\"internalType\":\"structCCIPHome.OCR3Config\",\"name\":\"config\",\"type\":\"tuple\"}],\"internalType\":\"structCCIPHome.VersionedConfig\",\"name\":\"activeConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"version\",\"type\":\"uint32\"},{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"components\":[{\"internalType\":\"enumInternal.OCRPluginType\",\"name\":\"pluginType\",\"type\":\"uint8\"},{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint8\",\"name\":\"FRoleDON\",\"type\":\"uint8\"},{\"internalType\":\"uint64\",\"name\":\"offchainConfigVersion\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"offrampAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"rmnHomeAddress\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"p2pId\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"signerKey\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"transmitterKey\",\"type\":\"bytes\"}],\"internalType\":\"structCCIPHome.OCR3Node[]\",\"name\":\"nodes\",\"type\":\"tuple[]\"},{\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"}],\"internalType\":\"structCCIPHome.OCR3Config\",\"name\":\"config\",\"type\":\"tuple\"}],\"internalType\":\"structCCIPHome.VersionedConfig\",\"name\":\"candidateConfig\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"donId\",\"type\":\"uint32\"},{\"internalType\":\"enumInternal.OCRPluginType\",\"name\":\"pluginType\",\"type\":\"uint8\"}],\"name\":\"getCandidateDigest\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"name\":\"getCapabilityConfiguration\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"configuration\",\"type\":\"bytes\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getCapabilityRegistry\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"}],\"name\":\"getChainConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"bytes32[]\",\"name\":\"readers\",\"type\":\"bytes32[]\"},{\"internalType\":\"uint8\",\"name\":\"fChain\",\"type\":\"uint8\"},{\"internalType\":\"bytes\",\"name\":\"config\",\"type\":\"bytes\"}],\"internalType\":\"structCCIPHome.ChainConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"donId\",\"type\":\"uint32\"},{\"internalType\":\"enumInternal.OCRPluginType\",\"name\":\"pluginType\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"}],\"name\":\"getConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"version\",\"type\":\"uint32\"},{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"components\":[{\"internalType\":\"enumInternal.OCRPluginType\",\"name\":\"pluginType\",\"type\":\"uint8\"},{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint8\",\"name\":\"FRoleDON\",\"type\":\"uint8\"},{\"internalType\":\"uint64\",\"name\":\"offchainConfigVersion\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"offrampAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"rmnHomeAddress\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"p2pId\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"signerKey\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"transmitterKey\",\"type\":\"bytes\"}],\"internalType\":\"structCCIPHome.OCR3Node[]\",\"name\":\"nodes\",\"type\":\"tuple[]\"},{\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"}],\"internalType\":\"structCCIPHome.OCR3Config\",\"name\":\"config\",\"type\":\"tuple\"}],\"internalType\":\"structCCIPHome.VersionedConfig\",\"name\":\"versionedConfig\",\"type\":\"tuple\"},{\"internalType\":\"bool\",\"name\":\"ok\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"donId\",\"type\":\"uint32\"},{\"internalType\":\"enumInternal.OCRPluginType\",\"name\":\"pluginType\",\"type\":\"uint8\"}],\"name\":\"getConfigDigests\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"activeConfigDigest\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"candidateConfigDigest\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getNumChainConfigurations\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"donId\",\"type\":\"uint32\"},{\"internalType\":\"enumInternal.OCRPluginType\",\"name\":\"pluginType\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"digestToPromote\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"digestToRevoke\",\"type\":\"bytes32\"}],\"name\":\"promoteCandidateAndRevokeActive\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"donId\",\"type\":\"uint32\"},{\"internalType\":\"enumInternal.OCRPluginType\",\"name\":\"pluginType\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"}],\"name\":\"revokeCandidate\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"donId\",\"type\":\"uint32\"},{\"internalType\":\"enumInternal.OCRPluginType\",\"name\":\"pluginType\",\"type\":\"uint8\"},{\"components\":[{\"internalType\":\"enumInternal.OCRPluginType\",\"name\":\"pluginType\",\"type\":\"uint8\"},{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint8\",\"name\":\"FRoleDON\",\"type\":\"uint8\"},{\"internalType\":\"uint64\",\"name\":\"offchainConfigVersion\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"offrampAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"rmnHomeAddress\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"p2pId\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"signerKey\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"transmitterKey\",\"type\":\"bytes\"}],\"internalType\":\"structCCIPHome.OCR3Node[]\",\"name\":\"nodes\",\"type\":\"tuple[]\"},{\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"}],\"internalType\":\"structCCIPHome.OCR3Config\",\"name\":\"config\",\"type\":\"tuple\"},{\"internalType\":\"bytes32\",\"name\":\"digestToOverwrite\",\"type\":\"bytes32\"}],\"name\":\"setCandidate\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"newConfigDigest\",\"type\":\"bytes32\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", - Bin: "0x60a03460bf57601f613d6638819003918201601f19168301916001600160401b0383118484101760c45780849260209460405283398101031260bf57516001600160a01b03811680820360bf57331560ae57600180546001600160a01b031916331790556006805463ffffffff1916905515609d57608052604051613c8b90816100db823960805181818161026601528181612f3901526139bd0152f35b6342bcdf7f60e11b60005260046000fd5b639b15e16f60e01b60005260046000fd5b600080fd5b634e487b7160e01b600052604160045260246000fdfe6080604052600436101561001257600080fd5b60003560e01c806301ffc9a714610157578063020330e614610152578063181f5a771461014d57806333d9704a146101485780633df45a72146101435780634851d5491461013e5780635a837f97146101395780635f1edd9c146101345780637524051a1461012f57806379ba50971461012a5780637ac0d41e146101255780638318ed5d146101205780638da5cb5b1461011b578063922ea40614610116578063b149092b14610111578063b74b23561461010c578063bae4e0fa14610107578063f2fde38b14610102578063f442c89a146100fd5763fba64a7c146100f857600080fd5b61172d565b611472565b61134e565b6110e5565b61100a565b610f90565b610ee2565b610e90565b610e2f565b610df3565b610d0a565b610c0f565b610bbb565b610934565b6108ae565b6107ce565b61072c565b610415565b61021b565b346102165760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610216576004357fffffffff00000000000000000000000000000000000000000000000000000000811680910361021657807f78bea72100000000000000000000000000000000000000000000000000000000602092149081156101ec575b506040519015158152f35b7f01ffc9a700000000000000000000000000000000000000000000000000000000915014386101e1565b600080fd5b346102165760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261021657602060405173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6060810190811067ffffffffffffffff8211176102d557604052565b61028a565b610100810190811067ffffffffffffffff8211176102d557604052565b6040810190811067ffffffffffffffff8211176102d557604052565b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff8211176102d557604052565b60405190610363604083610313565b565b6040519061036361010083610313565b67ffffffffffffffff81116102d557601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b60005b8381106103c25750506000910152565b81810151838201526020016103b2565b907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f60209361040e815180928187528780880191016103af565b0116010190565b346102165760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102165761049260408051906104568183610313565b601282527f43434950486f6d6520312e362e302d64657600000000000000000000000000006020830152519182916020835260208301906103d2565b0390f35b63ffffffff81160361021657565b6064359061036382610496565b6002111561021657565b3590610363826104b1565b7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc6060910112610216576004356104fc81610496565b90602435610509816104b1565b9060443590565b6002111561051a57565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b90600282101561051a5752565b61058a9181518152604061057960208401516060602085015260608401906103d2565b9201519060408184039101526103d2565b90565b9080602083519182815201916020808360051b8301019401926000915b8383106105b957505050505090565b90919293946020806105f5837fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe086600196030187528951610556565b970193019301919392906105aa565b90604061058a9263ffffffff81511683526020810151602084015201519060606040820152610637606082018351610549565b602082015167ffffffffffffffff166080820152604082015160ff1660a0820152606082015167ffffffffffffffff1660c082015260e06106f86106c361068e6080860151610100858701526101608601906103d2565b60a08601517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa0868303016101008701526103d2565b60c08501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa08583030161012086015261058d565b920151906101407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa0828503019101526103d2565b346102165761075a610746610740366104c6565b91611b23565b604051928392604084526040840190610604565b90151560208301520390f35b7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc60409101126102165760043561079c81610496565b9060243561058a816104b1565b90916107c061058a93604084526040840190610604565b916020818403910152610604565b34610216576107dc36610766565b906107e56117dc565b906107ee6117dc565b9261083d61083763ffffffff841680600052600560205261081384604060002061183b565b90600052600760205263ffffffff61082f85604060002061183b565b541690611882565b50611a52565b60208101516108a4575b508161087c82610876610837946108716108829763ffffffff166000526005602052604060002090565b61183b565b9261312a565b90611882565b602081015161089c575b50610492604051928392836107a9565b91503861088c565b9250610882610847565b346102165761091f60016108c136610766565b929061087c63ffffffff821694856000526005602052846109056108e983604060002061183b565b88600052600760205263ffffffff61082f85604060002061183b565b50015495600052600560205261087681604060002061183b565b50015460408051928352602083019190915290f35b346102165760807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102165760043561096f81610496565b6024359061097c826104b1565b604435916064359161098c613150565b831580610bb3575b610b89576109ae6109a5838361312a565b63ffffffff1690565b8460016109d8836109d3876108718863ffffffff166000526005602052604060002090565b611882565b50015403610b2f57506001610a2f610a04846108718563ffffffff166000526005602052604060002090565b61087c610a25866108718763ffffffff166000526007602052604060002090565b5463ffffffff1690565b50018054848103610af9575091610871610a60926000610aa0955563ffffffff166000526007602052604060002090565b6001610a70825463ffffffff1690565b1863ffffffff167fffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000825416179055565b80610ace575b507ffc3e98dbbd47c3fa7c1c05b6ec711caeaf70eca4554192b9ada8fc11a37f298e600080a2005b7f0b31c0055e2d464bef7781994b98c4ff9ef4ae0d05f59feb6a68c42de5e201b8600080a238610aa6565b7f93df584c00000000000000000000000000000000000000000000000000000000600052600452602484905260446000fd5b6000fd5b610b576001916109d3610b2b95610871899663ffffffff166000526005602052604060002090565b5001547f93df584c00000000000000000000000000000000000000000000000000000000600052600452602452604490565b7f7b4d1e4f0000000000000000000000000000000000000000000000000000000060005260046000fd5b508215610994565b346102165760206001610c0463ffffffff8061082f610bd936610766565b9316928360005260058752610bf281604060002061183b565b9360005260078752604060002061183b565b500154604051908152f35b3461021657610c1d366104c6565b91610c26613150565b8215610ce05763ffffffff610c3b838361312a565b169263ffffffff82166000526005602052806001610c61866109d387604060002061183b565b50015403610cb957926109d3600193610871610cb4946000977f53f5d9228f0a4173bea6e5931c9b3afe6eeb6692ede1d182952970f152534e3b8980a263ffffffff166000526005602052604060002090565b500155005b6001610b57856109d386610871610b2b9763ffffffff166000526005602052604060002090565b7f0849d8cc0000000000000000000000000000000000000000000000000000000060005260046000fd5b346102165760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102165760005473ffffffffffffffffffffffffffffffffffffffff81163303610dc9577fffffffffffffffffffffffff00000000000000000000000000000000000000006001549133828416176001551660005573ffffffffffffffffffffffffffffffffffffffff3391167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0600080a3005b7f02b543c60000000000000000000000000000000000000000000000000000000060005260046000fd5b346102165760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610216576020600354604051908152f35b346102165760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261021657610e69600435610496565b6040516020610e788183610313565b600082526104926040519282849384528301906103d2565b346102165760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261021657602073ffffffffffffffffffffffffffffffffffffffff60015416604051908152f35b34610216576020610efb610ef536610766565b90611bed565b604051908152f35b67ffffffffffffffff81160361021657565b6044359061036382610f03565b359061036382610f03565b9190606081019083519160608252825180915260206080830193019060005b818110610f7a5750505060408460ff602061058a9697015116602084015201519060408184039101526103d2565b8251855260209485019490920191600101610f4c565b346102165760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102165767ffffffffffffffff600435610fd481610f03565b610fdc611c1a565b50166000526002602052610492610ff66040600020611c3a565b604051918291602083526020830190610f2d565b346102165760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261021657611047602435600435611e24565b6040518091602082016020835281518091526040830190602060408260051b8601019301916000905b82821061107f57505050500390f35b919360206110d5827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc060019597998495030186526040838a5167ffffffffffffffff815116845201519181858201520190610f2d565b9601920192018594939192611070565b346102165760807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102165760043561112081610496565b60243561112c816104b1565b60443567ffffffffffffffff8111610216576101007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc826004019236030112610216576064359261117b613150565b61118d611188368461206f565b613231565b6111978382611bed565b9380850361131c57917f94f085b7c57ec2a270befd0b7b2ec7452580040edee8bb0fb04609c81f0359c69161087c9493610492966112f1575b506112cf8260026112936111f16111ec60065463ffffffff1690565b612158565b946112278663ffffffff167fffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000006006541617600655565b6112728660405161126b8161123f8960208301612418565b037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08101835282610313565b8b846135b0565b99896108768c9b6108718563ffffffff166000526005602052604060002090565b506001810188905580547fffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000001663ffffffff861617815501612936565b6112de60405192839283612abe565b0390a26040519081529081906020820190565b7f53f5d9228f0a4173bea6e5931c9b3afe6eeb6692ede1d182952970f152534e3b600080a2386111d0565b7f93df584c00000000000000000000000000000000000000000000000000000000600052600485905260245260446000fd5b346102165760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102165760043573ffffffffffffffffffffffffffffffffffffffff8116809103610216576113a66136c5565b33811461141757807fffffffffffffffffffffffff0000000000000000000000000000000000000000600054161760005573ffffffffffffffffffffffffffffffffffffffff600154167fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae1278600080a3005b7fdad89dca0000000000000000000000000000000000000000000000000000000060005260046000fd5b9181601f840112156102165782359167ffffffffffffffff8311610216576020808501948460051b01011161021657565b346102165760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102165760043567ffffffffffffffff8111610216576114c1903690600401611441565b60243567ffffffffffffffff8111610216576114e1903690600401611441565b9190926114ec6136c5565b60005b8281106116015750505060005b81811061150557005b611525611520611516838587612b7a565b6020810190612662565b612bba565b90611539611534828587612b7a565b612429565b6115438351613948565b61155a611554602085015160ff1690565b60ff1690565b156115d75782816115ab6001956115a67f05dd57854af2c291a94ea52e7c43d80bc3be7fa73022f98b735dea86642fa5e09567ffffffffffffffff166000526002602052604060002090565b612d9a565b6115be67ffffffffffffffff8216613bed565b506115ce60405192839283612e2d565b0390a1016114fc565b7fa9b3766e0000000000000000000000000000000000000000000000000000000060005260046000fd5b61163c611638611625611618611534858888612adb565b67ffffffffffffffff1690565b6000526004602052604060002054151590565b1590565b6116e657806116766116716116576115346001958888612adb565b67ffffffffffffffff166000526002602052604060002090565b612b33565b61168f61168a611618611534848888612adb565b613b09565b507f2a680691fef3b2d105196805935232c661ce703e92d464ef0b94a7bc62d714f06116dd6116c2611534848888612adb565b60405167ffffffffffffffff90911681529081906020820190565b0390a1016114ef565b61153490610b2b936116f793612adb565b7f1bd4d2d20000000000000000000000000000000000000000000000000000000060005267ffffffffffffffff16600452602490565b346102165760807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102165760043567ffffffffffffffff81116102165761177c903690600401611441565b505060243567ffffffffffffffff811161021657366023820112156102165780600401359067ffffffffffffffff8211610216573660248383010111610216576117da916117c8610f15565b5060246117d36104a4565b9201612f20565b005b604051906117e9826102b9565b8160008152600060208201526040805191611803836102da565b60008352600060208401526000828401526000606084015260606080840152606060a0840152606060c0840152606060e08401520152565b90600281101561051a57600052602052604060002090565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b906002811015611896576007020190600090565b611853565b600282101561051a5752565b90600182811c921680156118f0575b60208310146118c157565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b91607f16916118b6565b906040519182600082549261190e846118a7565b808452936001811690811561197a5750600114611933575b5061036392500383610313565b90506000929192526020600020906000915b81831061195e5750509060206103639282010138611926565b6020919350806001915483858901015201910190918492611945565b602093506103639592507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0091501682840152151560051b82010138611926565b67ffffffffffffffff81116102d55760051b60200190565b9081546119de816119ba565b926119ec6040519485610313565b818452602084019060005260206000206000915b838310611a0d5750505050565b60036020600192604051611a20816102b9565b85548152611a2f8587016118fa565b83820152611a3f600287016118fa565b6040820152815201920192019190611a00565b9060405191611a60836102b9565b60408363ffffffff835416815260018301546020820152611b1a6006835194611a88866102da565b611ae1611ad06002830154611aa060ff82168a61189b565b67ffffffffffffffff600882901c1660208a015260ff604882901c16888a015260501c67ffffffffffffffff1690565b67ffffffffffffffff166060880152565b611aed600382016118fa565b6080870152611afe600482016118fa565b60a0870152611b0f600582016119d2565b60c0870152016118fa565b60e08401520152565b90611b2c6117dc565b9260005b60028110611b42575050505090600090565b63ffffffff8416806000526005602052826001611b67846109d388604060002061183b565b5001541480611ba8575b611b7e5750600101611b30565b611ba2955061083794506109d392506000939193526005602052604060002061183b565b90600190565b50821515611b71565b91611be9918354907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9060031b92831b921b19161790565b9055565b611c149061087c60019363ffffffff8316600052600560205261087681604060002061183b565b50015490565b60405190611c27826102b9565b6060604083828152600060208201520152565b90604051611c47816102b9565b809260405180602083549182815201908360005260206000209060005b818110611cab5750505060409282611c83611ca6946002940382610313565b8552611ca0611c96600183015460ff1690565b60ff166020870152565b016118fa565b910152565b8254845260209093019260019283019201611c64565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b9081600302916003830403611d0157565b611cc1565b81810292918115918404141715611d0157565b60405190611d28602083610313565b600080835282815b828110611d3c57505050565b602090604051611d4b816102f7565b60008152611d57611c1a565b8382015282828501015201611d30565b90611d71826119ba565b611d7e6040519182610313565b8281527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0611dac82946119ba565b019060005b828110611dbd57505050565b602090604051611dcc816102f7565b60008152611dd8611c1a565b8382015282828501015201611db1565b9060018201809211611d0157565b91908201809211611d0157565b91908203918211611d0157565b80518210156118965760209160051b010190565b611e318260035492611d06565b9180158015611f03575b611ef857611e499083611df6565b90808211611ef0575b50611e65611e608383611e03565b611d67565b91805b828110611e755750505090565b80611ee9611e87611618600194613a41565b611ec8611ea88267ffffffffffffffff166000526002602052604060002090565b611ec3611eb3610354565b67ffffffffffffffff9094168452565b611c3a565b6020820152611ed78584611e03565b90611ee28289611e10565b5286611e10565b5001611e68565b905038611e52565b50505061058a611d19565b5081831015611e3b565b60ff81160361021657565b359061036382611f0d565b81601f8201121561021657803590611f3a82610375565b92611f486040519485610313565b8284526020838301011161021657816000926020809301838601378301015290565b9080601f8301121561021657813591611f82836119ba565b92611f906040519485610313565b80845260208085019160051b830101918383116102165760208101915b838310611fbc57505050505090565b823567ffffffffffffffff81116102165782019060607fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe083880301126102165760405190612009826102b9565b60208301358252604083013567ffffffffffffffff81116102165787602061203392860101611f23565b602083015260608301359167ffffffffffffffff83116102165761205f88602080969581960101611f23565b6040820152815201920191611fad565b9190916101008184031261021657612085610365565b9261208f826104bb565b845261209d60208301610f22565b60208501526120ae60408301611f18565b60408501526120bf60608301610f22565b6060850152608082013567ffffffffffffffff811161021657816120e4918401611f23565b608085015260a082013567ffffffffffffffff81116102165781612109918401611f23565b60a085015260c082013567ffffffffffffffff8111610216578161212e918401611f6a565b60c085015260e082013567ffffffffffffffff8111610216576121519201611f23565b60e0830152565b63ffffffff1663ffffffff8114611d015760010190565b90357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18236030181121561021657016020813591019167ffffffffffffffff821161021657813603831361021657565b601f82602094937fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0938186528686013760008582860101520116010190565b90357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18236030181121561021657016020813591019167ffffffffffffffff8211610216578160051b3603831361021657565b90602083828152019060208160051b85010193836000915b8383106122795750505050505090565b9091929394957fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe082820301865286357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa1843603018112156102165760206123206001938683940190813581526123126123076122f78685018561216f565b60608886015260608501916121bf565b92604081019061216f565b9160408185039101526121bf565b980196019493019190612269565b61058a916123448161233f846104bb565b610549565b61236461235360208401610f22565b67ffffffffffffffff166020830152565b61237d61237360408401611f18565b60ff166040830152565b61239d61238c60608401610f22565b67ffffffffffffffff166060830152565b61240a6123ff6123e46123c96123b6608087018761216f565b61010060808801526101008701916121bf565b6123d660a087018761216f565b9086830360a08801526121bf565b6123f160c08601866121fe565b9085830360c0870152612251565b9260e081019061216f565b9160e08185039101526121bf565b90602061058a92818152019061232e565b3561058a81610f03565b3561058a81611f0d565b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe181360301821215610216570180359067ffffffffffffffff82116102165760200191813603831361021657565b818110612499575050565b6000815560010161248e565b9190601f81116124b457505050565b610363926000526020600020906020601f840160051c830193106124e0575b601f0160051c019061248e565b90915081906124d3565b90929167ffffffffffffffff81116102d5576125108161250a84546118a7565b846124a5565b6000601f821160011461256a578190611be993949560009261255f575b50507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8260011b9260031b1c19161790565b01359050388061252d565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe082169461259d84600052602060002090565b91805b8781106125f65750836001959697106125be575b505050811b019055565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88560031b161c199101351690553880806125b4565b909260206001819286860135815501940191016125a0565b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe181360301821215610216570180359067ffffffffffffffff821161021657602001918160051b3603831361021657565b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa181360301821215610216570190565b61269f81546118a7565b90816126a9575050565b81601f600093116001146126bb575055565b818352602083206126d791601f0160051c81019060010161248e565b808252602082209081548360011b907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8560031b1c191617905555565b90803582556001820161272a602083018361243d565b9067ffffffffffffffff82116102d55761274e8261274885546118a7565b856124a5565b600090601f83116001146127bd57926127a7836127b49460029794610363999760009261255f5750507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8260011b9260031b1c19161790565b90555b604081019061243d565b929091016124ea565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08316916127f085600052602060002090565b92815b81811061285957509360029693610363989693600193836127b49810612821575b505050811b0190556127aa565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88560031b161c19910135169055388080612814565b919360206001819287870135815501950192016127f3565b6801000000000000000083116102d55780548382558084106128d9575b50906128a08192600052602060002090565b906000925b8484106128b3575050505050565b60036020826128cd6128c760019587612662565b87612714565b019301930192916128a5565b80600302906003820403611d015783600302600381048503611d015782600052602060002091820191015b818110612911575061288e565b6003906000815561292460018201612695565b61293060028201612695565b01612904565b90803591612943836104b1565b600283101561051a576127b46004926103639460ff7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0085541691161783556129ca61299060208301612429565b84547fffffffffffffffffffffffffffffffffffffffffffffff0000000000000000ff1660089190911b68ffffffffffffffff0016178455565b612a146129d960408301612433565b84547fffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffffff1660489190911b69ff00000000000000000016178455565b612a66612a2360608301612429565b84547fffffffffffffffffffffffffffff0000000000000000ffffffffffffffffffff1660509190911b71ffffffffffffffff0000000000000000000016178455565b612a80612a76608083018361243d565b90600186016124ea565b612a9a612a9060a083018361243d565b90600286016124ea565b612ab4612aaa60c083018361260e565b9060038601612871565b60e081019061243d565b60409063ffffffff61058a9493168152816020820152019061232e565b91908110156118965760051b0190565b906801000000000000000081116102d557815491818155828210612b0e57505050565b600052602060002091820191015b818110612b27575050565b60008155600101612b1c565b80546000825580612b53575b506002816000600161036394015501612695565b816000526020600020908101905b818110612b6e5750612b3f565b60008155600101612b61565b91908110156118965760051b810135907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc181360301821215610216570190565b6060813603126102165760405190612bd1826102b9565b803567ffffffffffffffff811161021657810136601f8201121561021657803590612bfb826119ba565b91612c096040519384610313565b80835260208084019160051b8301019136831161021657602001905b828210612c6b575050508252612c3d60208201611f18565b602083015260408101359067ffffffffffffffff821161021657612c6391369101611f23565b604082015290565b8135815260209182019101612c25565b919091825167ffffffffffffffff81116102d557612c9d8161250a84546118a7565b6020601f8211600114612cf6578190611be9939495600092612ceb5750507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8260011b9260031b1c19161790565b01519050388061252d565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0821690612d2984600052602060002090565b9160005b818110612d8257509583600195969710612d4b57505050811b019055565b01517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88460031b161c191690553880806125b4565b9192602060018192868b015181550194019201612d2d565b90805180519067ffffffffffffffff82116102d557602090612dbc8386612aeb565b0183600052602060002060005b838110612e1957505050509060026040610363936001840160ff6020830151167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0082541617905501519101612c7b565b600190602084519401938184015501612dc9565b60409067ffffffffffffffff61058a94931681528160208201520190610f2d565b906004116102165790600490565b906024116102165760040190602090565b919091357fffffffff0000000000000000000000000000000000000000000000000000000081169260048110612ea1575050565b7fffffffff00000000000000000000000000000000000000000000000000000000929350829060040360031b1b161690565b90816020910312610216573590565b908092918237016000815290565b3d15612f1b573d90612f0182610375565b91612f0f6040519384610313565b82523d6000602084013e565b606090565b909173ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016330361310057612f72612f6c8484612e4e565b90612e6d565b7fffffffff0000000000000000000000000000000000000000000000000000000081167fbae4e0fa0000000000000000000000000000000000000000000000000000000081141590816130d5575b816130aa575b5061305b5750612fe1612fd98484612e5c565b810190612ed3565b63ffffffff82168103613022575050600091829161300460405180938193612ee2565b039082305af1613012612ef0565b901561301b5750565b60203d9101fd5b7f8a6e4ce80000000000000000000000000000000000000000000000000000000060005263ffffffff9081166004521660245260446000fd5b7f12ba286f000000000000000000000000000000000000000000000000000000006000527fffffffff000000000000000000000000000000000000000000000000000000001660045260246000fd5b7f5a837f97000000000000000000000000000000000000000000000000000000009150141538612fc6565b7f7524051a000000000000000000000000000000000000000000000000000000008114159150612fc0565b7fac7a7efd0000000000000000000000000000000000000000000000000000000060005260046000fd5b61314a60019263ffffffff8093166000526007602052604060002061183b565b54161890565b30330361315957565b7f371a73280000000000000000000000000000000000000000000000000000000060005260046000fd5b6040516020810190600082526020815261319e604082610313565b51902090565b906131ae826119ba565b6131bb6040519182610313565b8281527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe06131e982946119ba565b0190602036910137565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8114611d015760010190565b90602061058a928181520190610556565b6020810167ffffffffffffffff613250825167ffffffffffffffff1690565b161561358657815161326181610510565b61326a81610510565b151580613568575b61353e57608082015180518015918215613528575b50506134fe5760a0820151805180159182156134e8575b50506134be576132bf611638611625611618845167ffffffffffffffff1690565b6134aa576132f961155460016132f16116576132e2611554604089015160ff1690565b955167ffffffffffffffff1690565b015460ff1690565b918183116134765760c0019182515191610100831161344c5761331b90611cf0565b8211156134225760009161332e816131a4565b9360005b8281106133905750505061334861334d91611cf0565b611de8565b9081811061336057505061036390613948565b7f548dd21f0000000000000000000000000000000000000000000000000000000060005260045260245260446000fd5b61339b818351611e10565b51604081015151613412575b602081015151158015613409575b6133cf5790600191516133c88289611e10565b5201613332565b613405906040519182917f9fa4031400000000000000000000000000000000000000000000000000000000835260048301613220565b0390fd5b508051156133b5565b9461341c906131f3565b946133a7565b7f4856694e0000000000000000000000000000000000000000000000000000000060005260046000fd5b7f1b925da60000000000000000000000000000000000000000000000000000000060005260046000fd5b507f2db220400000000000000000000000000000000000000000000000000000000060005260049190915260245260446000fd5b51610b2b9067ffffffffffffffff166116f7565b7fdee985740000000000000000000000000000000000000000000000000000000060005260046000fd5b6020012090506134f6613183565b14388061329e565b7f358c19270000000000000000000000000000000000000000000000000000000060005260046000fd5b602001209050613536613183565b143880613287565b7f3302dbd70000000000000000000000000000000000000000000000000000000060005260046000fd5b506001825161357681610510565b61357f81610510565b1415613272565b7f698cf8e00000000000000000000000000000000000000000000000000000000060005260046000fd5b90613677929361360663ffffffff9283604051957f45564d0000000000000000000000000000000000000000000000000000000000602088015246604088015230606088015216608086015260a0850190610549565b1660c082015260c0815261361b60e082610313565b6020604051938261363586945180928580880191016103af565b8301613649825180938580850191016103af565b0101037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08101835282610313565b602081519101207fffff00000000000000000000000000000000000000000000000000000000000019167e0a0000000000000000000000000000000000000000000000000000000000001790565b73ffffffffffffffffffffffffffffffffffffffff6001541633036136e657565b7f2b5c74de0000000000000000000000000000000000000000000000000000000060005260046000fd5b519061036382610496565b9080601f83011215610216578151613732816119ba565b926137406040519485610313565b81845260208085019260051b82010192831161021657602001905b8282106137685750505090565b815181526020918201910161375b565b9080601f8301121561021657815161378f816119ba565b9261379d6040519485610313565b81845260208085019260051b82010192831161021657602001905b8282106137c55750505090565b81518152602091820191016137b8565b6020818303126102165780519067ffffffffffffffff821161021657019080601f830112156102165781519161380a836119ba565b926138186040519485610313565b80845260208085019160051b830101918383116102165760208101915b83831061384457505050505090565b825167ffffffffffffffff8111610216578201906101007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe083880301126102165761388d610365565b9061389a60208401613710565b82526138a860408401613710565b60208301526138b960608401613710565b60408301526080830151606083015260a0830151608083015260c083015160a083015260e083015167ffffffffffffffff8111610216578760206138ff9286010161371b565b60c08301526101008301519167ffffffffffffffff83116102165761392c88602080969581960101613778565b60e0820152815201920191613835565b6040513d6000823e3d90fd5b80516139515750565b60405180917f05a519660000000000000000000000000000000000000000000000000000000082526024820160206004840152815180915260206044840192019060005b818110613a10575050509080600092038173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000165afa8015613a0b576139ec5750565b613a08903d806000833e613a008183610313565b8101906137d5565b50565b61393c565b8251845285945060209384019390920191600101613995565b80548210156118965760005260206000200190600090565b6003548110156118965760036000527fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b015490565b80548015613ada577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190613aab8282613a29565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82549160031b1b1916905555565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b600081815260046020526040902054908115613be6577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820190828211611d0157600354927fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8401938411611d01578383600095613ba59503613bab575b505050613b946003613a76565b600490600052602052604060002090565b55600190565b613b94613bd791613bcd613bc3613bdd956003613a29565b90549060031b1c90565b9283916003613a29565b90611bb1565b55388080613b87565b5050600090565b600081815260046020526040902054613c7857600354680100000000000000008110156102d557613c5f613c2a8260018594016003556003613a29565b81939154907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9060031b92831b921b19161790565b9055600354906000526004602052604060002055600190565b5060009056fea164736f6c634300081a000a", + ABI: "[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"capabilitiesRegistry\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"CanOnlySelfCall\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CannotTransferToSelf\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"}],\"name\":\"ChainSelectorNotFound\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ChainSelectorNotSet\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"expectedConfigDigest\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"gotConfigDigest\",\"type\":\"bytes32\"}],\"name\":\"ConfigDigestMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"callDonId\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"capabilityRegistryDonId\",\"type\":\"uint32\"}],\"name\":\"DONIdMismatch\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FChainMustBePositive\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"fChain\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"FRoleDON\",\"type\":\"uint256\"}],\"name\":\"FChainTooHigh\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FTooHigh\",\"type\":\"error\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"p2pId\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"signerKey\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"transmitterKey\",\"type\":\"bytes\"}],\"internalType\":\"structCCIPHome.OCR3Node\",\"name\":\"node\",\"type\":\"tuple\"}],\"name\":\"InvalidNode\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidPluginType\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"selector\",\"type\":\"bytes4\"}],\"name\":\"InvalidSelector\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MustBeProposedOwner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NoOpStateTransitionNotAllowed\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"got\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"minimum\",\"type\":\"uint256\"}],\"name\":\"NotEnoughTransmitters\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OfframpAddressCannotBeZero\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByOwner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCapabilitiesRegistryCanCall\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OwnerCannotBeZero\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RMNHomeAddressCannotBeZero\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RevokingZeroDigestNotAllowed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TooManySigners\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"}],\"name\":\"ActiveConfigRevoked\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"}],\"name\":\"CandidateConfigRevoked\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[],\"name\":\"CapabilityConfigurationSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"}],\"name\":\"ChainConfigRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bytes32[]\",\"name\":\"readers\",\"type\":\"bytes32[]\"},{\"internalType\":\"uint8\",\"name\":\"fChain\",\"type\":\"uint8\"},{\"internalType\":\"bytes\",\"name\":\"config\",\"type\":\"bytes\"}],\"indexed\":false,\"internalType\":\"structCCIPHome.ChainConfig\",\"name\":\"chainConfig\",\"type\":\"tuple\"}],\"name\":\"ChainConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"}],\"name\":\"ConfigPromoted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"version\",\"type\":\"uint32\"},{\"components\":[{\"internalType\":\"enumInternal.OCRPluginType\",\"name\":\"pluginType\",\"type\":\"uint8\"},{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint8\",\"name\":\"FRoleDON\",\"type\":\"uint8\"},{\"internalType\":\"uint64\",\"name\":\"offchainConfigVersion\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"offrampAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"rmnHomeAddress\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"p2pId\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"signerKey\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"transmitterKey\",\"type\":\"bytes\"}],\"internalType\":\"structCCIPHome.OCR3Node[]\",\"name\":\"nodes\",\"type\":\"tuple[]\"},{\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"}],\"indexed\":false,\"internalType\":\"structCCIPHome.OCR3Config\",\"name\":\"config\",\"type\":\"tuple\"}],\"name\":\"ConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64[]\",\"name\":\"chainSelectorRemoves\",\"type\":\"uint64[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bytes32[]\",\"name\":\"readers\",\"type\":\"bytes32[]\"},{\"internalType\":\"uint8\",\"name\":\"fChain\",\"type\":\"uint8\"},{\"internalType\":\"bytes\",\"name\":\"config\",\"type\":\"bytes\"}],\"internalType\":\"structCCIPHome.ChainConfig\",\"name\":\"chainConfig\",\"type\":\"tuple\"}],\"internalType\":\"structCCIPHome.ChainConfigArgs[]\",\"name\":\"chainConfigAdds\",\"type\":\"tuple[]\"}],\"name\":\"applyChainConfigUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[]\",\"name\":\"\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes\",\"name\":\"update\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"donId\",\"type\":\"uint32\"}],\"name\":\"beforeCapabilityConfigSet\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"donId\",\"type\":\"uint32\"},{\"internalType\":\"enumInternal.OCRPluginType\",\"name\":\"pluginType\",\"type\":\"uint8\"}],\"name\":\"getActiveDigest\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"pageIndex\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"pageSize\",\"type\":\"uint256\"}],\"name\":\"getAllChainConfigs\",\"outputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bytes32[]\",\"name\":\"readers\",\"type\":\"bytes32[]\"},{\"internalType\":\"uint8\",\"name\":\"fChain\",\"type\":\"uint8\"},{\"internalType\":\"bytes\",\"name\":\"config\",\"type\":\"bytes\"}],\"internalType\":\"structCCIPHome.ChainConfig\",\"name\":\"chainConfig\",\"type\":\"tuple\"}],\"internalType\":\"structCCIPHome.ChainConfigArgs[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"donId\",\"type\":\"uint32\"},{\"internalType\":\"enumInternal.OCRPluginType\",\"name\":\"pluginType\",\"type\":\"uint8\"}],\"name\":\"getAllConfigs\",\"outputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"version\",\"type\":\"uint32\"},{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"components\":[{\"internalType\":\"enumInternal.OCRPluginType\",\"name\":\"pluginType\",\"type\":\"uint8\"},{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint8\",\"name\":\"FRoleDON\",\"type\":\"uint8\"},{\"internalType\":\"uint64\",\"name\":\"offchainConfigVersion\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"offrampAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"rmnHomeAddress\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"p2pId\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"signerKey\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"transmitterKey\",\"type\":\"bytes\"}],\"internalType\":\"structCCIPHome.OCR3Node[]\",\"name\":\"nodes\",\"type\":\"tuple[]\"},{\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"}],\"internalType\":\"structCCIPHome.OCR3Config\",\"name\":\"config\",\"type\":\"tuple\"}],\"internalType\":\"structCCIPHome.VersionedConfig\",\"name\":\"activeConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"version\",\"type\":\"uint32\"},{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"components\":[{\"internalType\":\"enumInternal.OCRPluginType\",\"name\":\"pluginType\",\"type\":\"uint8\"},{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint8\",\"name\":\"FRoleDON\",\"type\":\"uint8\"},{\"internalType\":\"uint64\",\"name\":\"offchainConfigVersion\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"offrampAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"rmnHomeAddress\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"p2pId\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"signerKey\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"transmitterKey\",\"type\":\"bytes\"}],\"internalType\":\"structCCIPHome.OCR3Node[]\",\"name\":\"nodes\",\"type\":\"tuple[]\"},{\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"}],\"internalType\":\"structCCIPHome.OCR3Config\",\"name\":\"config\",\"type\":\"tuple\"}],\"internalType\":\"structCCIPHome.VersionedConfig\",\"name\":\"candidateConfig\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"donId\",\"type\":\"uint32\"},{\"internalType\":\"enumInternal.OCRPluginType\",\"name\":\"pluginType\",\"type\":\"uint8\"}],\"name\":\"getCandidateDigest\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"name\":\"getCapabilityConfiguration\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"configuration\",\"type\":\"bytes\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getCapabilityRegistry\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"donId\",\"type\":\"uint32\"},{\"internalType\":\"enumInternal.OCRPluginType\",\"name\":\"pluginType\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"}],\"name\":\"getConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"version\",\"type\":\"uint32\"},{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"components\":[{\"internalType\":\"enumInternal.OCRPluginType\",\"name\":\"pluginType\",\"type\":\"uint8\"},{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint8\",\"name\":\"FRoleDON\",\"type\":\"uint8\"},{\"internalType\":\"uint64\",\"name\":\"offchainConfigVersion\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"offrampAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"rmnHomeAddress\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"p2pId\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"signerKey\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"transmitterKey\",\"type\":\"bytes\"}],\"internalType\":\"structCCIPHome.OCR3Node[]\",\"name\":\"nodes\",\"type\":\"tuple[]\"},{\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"}],\"internalType\":\"structCCIPHome.OCR3Config\",\"name\":\"config\",\"type\":\"tuple\"}],\"internalType\":\"structCCIPHome.VersionedConfig\",\"name\":\"versionedConfig\",\"type\":\"tuple\"},{\"internalType\":\"bool\",\"name\":\"ok\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"donId\",\"type\":\"uint32\"},{\"internalType\":\"enumInternal.OCRPluginType\",\"name\":\"pluginType\",\"type\":\"uint8\"}],\"name\":\"getConfigDigests\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"activeConfigDigest\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"candidateConfigDigest\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getNumChainConfigurations\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"donId\",\"type\":\"uint32\"},{\"internalType\":\"enumInternal.OCRPluginType\",\"name\":\"pluginType\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"digestToPromote\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"digestToRevoke\",\"type\":\"bytes32\"}],\"name\":\"promoteCandidateAndRevokeActive\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"donId\",\"type\":\"uint32\"},{\"internalType\":\"enumInternal.OCRPluginType\",\"name\":\"pluginType\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"}],\"name\":\"revokeCandidate\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"donId\",\"type\":\"uint32\"},{\"internalType\":\"enumInternal.OCRPluginType\",\"name\":\"pluginType\",\"type\":\"uint8\"},{\"components\":[{\"internalType\":\"enumInternal.OCRPluginType\",\"name\":\"pluginType\",\"type\":\"uint8\"},{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint8\",\"name\":\"FRoleDON\",\"type\":\"uint8\"},{\"internalType\":\"uint64\",\"name\":\"offchainConfigVersion\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"offrampAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"rmnHomeAddress\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"p2pId\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"signerKey\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"transmitterKey\",\"type\":\"bytes\"}],\"internalType\":\"structCCIPHome.OCR3Node[]\",\"name\":\"nodes\",\"type\":\"tuple[]\"},{\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"}],\"internalType\":\"structCCIPHome.OCR3Config\",\"name\":\"config\",\"type\":\"tuple\"},{\"internalType\":\"bytes32\",\"name\":\"digestToOverwrite\",\"type\":\"bytes32\"}],\"name\":\"setCandidate\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"newConfigDigest\",\"type\":\"bytes32\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", + Bin: "0x60a06040526006805463ffffffff191690553480156200001e57600080fd5b5060405162004c7a38038062004c7a83398101604081905262000041916200014c565b336000816200006357604051639b15e16f60e01b815260040160405180910390fd5b600180546001600160a01b0319166001600160a01b038481169190911790915581161562000096576200009681620000d2565b50506001600160a01b038116620000c0576040516342bcdf7f60e11b815260040160405180910390fd5b6001600160a01b03166080526200017e565b336001600160a01b03821603620000fc57604051636d6c4ee560e11b815260040160405180910390fd5b600080546001600160a01b0319166001600160a01b03838116918217835560015460405192939116917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6000602082840312156200015f57600080fd5b81516001600160a01b03811681146200017757600080fd5b9392505050565b608051614ad2620001a860003960008181610180015281816121eb0152612c450152614ad26000f3fe608060405234801561001057600080fd5b50600436106101515760003560e01c806379ba5097116100cd578063b74b235611610081578063f2fde38b11610066578063f2fde38b14610356578063f442c89a14610369578063fba64a7c1461037c57600080fd5b8063b74b235614610323578063bae4e0fa1461034357600080fd5b80638318ed5d116100b25780638318ed5d146102d15780638da5cb5b146102f2578063922ea4061461031057600080fd5b806379ba5097146102c15780637ac0d41e146102c957600080fd5b80633df45a72116101245780635a837f97116101095780635a837f97146102785780635f1edd9c1461028d5780637524051a146102ae57600080fd5b80633df45a721461022f5780634851d5491461025057600080fd5b806301ffc9a714610156578063020330e61461017e578063181f5a77146101c557806333d9704a1461020e575b600080fd5b610169610164366004612fb2565b61038f565b60405190151581526020015b60405180910390f35b7f00000000000000000000000000000000000000000000000000000000000000005b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610175565b6102016040518060400160405280601281526020017f43434950486f6d6520312e362e302d646576000000000000000000000000000081525081565b6040516101759190613044565b61022161021c366004613091565b610428565b6040516101759291906132d8565b61024261023d3660046132fc565b610922565b604051610175929190613335565b61026361025e3660046132fc565b611222565b60408051928352602083019190915201610175565b61028b61028636600461335a565b611318565b005b6102a061029b3660046132fc565b61162b565b604051908152602001610175565b61028b6102bc366004613091565b6116a2565b61028b61188d565b6102a061195b565b6102016102df3660046133a0565b5060408051602081019091526000815290565b60015473ffffffffffffffffffffffffffffffffffffffff166101a0565b6102a061031e3660046132fc565b61196c565b6103366103313660046133bd565b6119bd565b6040516101759190613456565b6102a06103513660046134f4565b611c22565b61028b610364366004613564565b611e20565b61028b6103773660046135df565b611e34565b61028b61038a36600461366c565b6121d3565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f78bea72100000000000000000000000000000000000000000000000000000000148061042257507fffffffff0000000000000000000000000000000000000000000000000000000082167f01ffc9a700000000000000000000000000000000000000000000000000000000145b92915050565b610430612e3b565b6000805b60028110156109145763ffffffff861660009081526005602052604081208591876001811115610466576104666130d2565b6001811115610477576104776130d2565b8152602001908152602001600020826002811061049657610496613729565b60070201600101541480156104aa57508315155b1561090c5763ffffffff86166000908152600560205260408120908660018111156104d7576104d76130d2565b60018111156104e8576104e86130d2565b8152602001908152602001600020816002811061050757610507613729565b6040805160608101825260079290920292909201805463ffffffff1682526001808201546020840152835161010081018552600283018054939592949386938501929190829060ff1687811115610560576105606130d2565b6001811115610571576105716130d2565b8152815467ffffffffffffffff61010082048116602084015260ff690100000000000000000083041660408401526a01000000000000000000009091041660608201526001820180546080909201916105c990613758565b80601f01602080910402602001604051908101604052809291908181526020018280546105f590613758565b80156106425780601f1061061757610100808354040283529160200191610642565b820191906000526020600020905b81548152906001019060200180831161062557829003601f168201915b5050505050815260200160028201805461065b90613758565b80601f016020809104026020016040519081016040528092919081815260200182805461068790613758565b80156106d45780601f106106a9576101008083540402835291602001916106d4565b820191906000526020600020905b8154815290600101906020018083116106b757829003601f168201915b5050505050815260200160038201805480602002602001604051908101604052809291908181526020016000905b8282101561086257838290600052602060002090600302016040518060600160405290816000820154815260200160018201805461073f90613758565b80601f016020809104026020016040519081016040528092919081815260200182805461076b90613758565b80156107b85780601f1061078d576101008083540402835291602001916107b8565b820191906000526020600020905b81548152906001019060200180831161079b57829003601f168201915b505050505081526020016002820180546107d190613758565b80601f01602080910402602001604051908101604052809291908181526020018280546107fd90613758565b801561084a5780601f1061081f5761010080835404028352916020019161084a565b820191906000526020600020905b81548152906001019060200180831161082d57829003601f168201915b50505050508152505081526020019060010190610702565b50505050815260200160048201805461087a90613758565b80601f01602080910402602001604051908101604052809291908181526020018280546108a690613758565b80156108f35780601f106108c8576101008083540402835291602001916108f3565b820191906000526020600020905b8154815290600101906020018083116108d657829003601f168201915b505050505081525050815250509150925092505061091a565b600101610434565b50600090505b935093915050565b61092a612e3b565b610932612e3b565b63ffffffff841660009081526005602052604081208185600181111561095a5761095a6130d2565b600181111561096b5761096b6130d2565b81526020019081526020016000206109838686612490565b63ffffffff166002811061099957610999613729565b6040805160608101825260079290920292909201805463ffffffff1682526001808201546020840152835161010081018552600283018054949593949386019391929091839160ff909116908111156109f4576109f46130d2565b6001811115610a0557610a056130d2565b8152815467ffffffffffffffff61010082048116602084015260ff690100000000000000000083041660408401526a0100000000000000000000909104166060820152600182018054608090920191610a5d90613758565b80601f0160208091040260200160405190810160405280929190818152602001828054610a8990613758565b8015610ad65780601f10610aab57610100808354040283529160200191610ad6565b820191906000526020600020905b815481529060010190602001808311610ab957829003601f168201915b50505050508152602001600282018054610aef90613758565b80601f0160208091040260200160405190810160405280929190818152602001828054610b1b90613758565b8015610b685780601f10610b3d57610100808354040283529160200191610b68565b820191906000526020600020905b815481529060010190602001808311610b4b57829003601f168201915b5050505050815260200160038201805480602002602001604051908101604052809291908181526020016000905b82821015610cf6578382906000526020600020906003020160405180606001604052908160008201548152602001600182018054610bd390613758565b80601f0160208091040260200160405190810160405280929190818152602001828054610bff90613758565b8015610c4c5780601f10610c2157610100808354040283529160200191610c4c565b820191906000526020600020905b815481529060010190602001808311610c2f57829003601f168201915b50505050508152602001600282018054610c6590613758565b80601f0160208091040260200160405190810160405280929190818152602001828054610c9190613758565b8015610cde5780601f10610cb357610100808354040283529160200191610cde565b820191906000526020600020905b815481529060010190602001808311610cc157829003601f168201915b50505050508152505081526020019060010190610b96565b505050508152602001600482018054610d0e90613758565b80601f0160208091040260200160405190810160405280929190818152602001828054610d3a90613758565b8015610d875780601f10610d5c57610100808354040283529160200191610d87565b820191906000526020600020905b815481529060010190602001808311610d6a57829003601f168201915b50505091909252505050905250602081015190915015610da5578092505b63ffffffff8516600090815260056020526040812081866001811115610dcd57610dcd6130d2565b6001811115610dde57610dde6130d2565b8152602001908152602001600020610df687876124e7565b63ffffffff1660028110610e0c57610e0c613729565b6040805160608101825260079290920292909201805463ffffffff1682526001808201546020840152835161010081018552600283018054949593949386019391929091839160ff90911690811115610e6757610e676130d2565b6001811115610e7857610e786130d2565b8152815467ffffffffffffffff61010082048116602084015260ff690100000000000000000083041660408401526a0100000000000000000000909104166060820152600182018054608090920191610ed090613758565b80601f0160208091040260200160405190810160405280929190818152602001828054610efc90613758565b8015610f495780601f10610f1e57610100808354040283529160200191610f49565b820191906000526020600020905b815481529060010190602001808311610f2c57829003601f168201915b50505050508152602001600282018054610f6290613758565b80601f0160208091040260200160405190810160405280929190818152602001828054610f8e90613758565b8015610fdb5780601f10610fb057610100808354040283529160200191610fdb565b820191906000526020600020905b815481529060010190602001808311610fbe57829003601f168201915b5050505050815260200160038201805480602002602001604051908101604052809291908181526020016000905b8282101561116957838290600052602060002090600302016040518060600160405290816000820154815260200160018201805461104690613758565b80601f016020809104026020016040519081016040528092919081815260200182805461107290613758565b80156110bf5780601f10611094576101008083540402835291602001916110bf565b820191906000526020600020905b8154815290600101906020018083116110a257829003601f168201915b505050505081526020016002820180546110d890613758565b80601f016020809104026020016040519081016040528092919081815260200182805461110490613758565b80156111515780601f1061112657610100808354040283529160200191611151565b820191906000526020600020905b81548152906001019060200180831161113457829003601f168201915b50505050508152505081526020019060010190611009565b50505050815260200160048201805461118190613758565b80601f01602080910402602001604051908101604052809291908181526020018280546111ad90613758565b80156111fa5780601f106111cf576101008083540402835291602001916111fa565b820191906000526020600020905b8154815290600101906020018083116111dd57829003601f168201915b50505091909252505050905250602081015190915015611218578092505b50505b9250929050565b63ffffffff8216600090815260056020526040812081908184600181111561124c5761124c6130d2565b600181111561125d5761125d6130d2565b81526020019081526020016000206112758585612490565b63ffffffff166002811061128b5761128b613729565b6007020160010154600560008663ffffffff1663ffffffff16815260200190815260200160002060008560018111156112c6576112c66130d2565b60018111156112d7576112d76130d2565b81526020019081526020016000206112ef86866124e7565b63ffffffff166002811061130557611305613729565b6007020160010154915091509250929050565b611320612542565b8115801561132c575080155b15611363576040517f7b4d1e4f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600061136f85856124e7565b63ffffffff86811660009081526005602052604081209290911692508491908660018111156113a0576113a06130d2565b60018111156113b1576113b16130d2565b815260200190815260200160002082600281106113d0576113d0613729565b6007020160010154146114845763ffffffff8516600090815260056020526040812090856001811115611405576114056130d2565b6001811115611416576114166130d2565b8152602001908152602001600020816002811061143557611435613729565b6007020160010154836040517f93df584c00000000000000000000000000000000000000000000000000000000815260040161147b929190918252602082015260400190565b60405180910390fd5b63ffffffff85166000908152600560205260408120818660018111156114ac576114ac6130d2565b60018111156114bd576114bd6130d2565b81526020019081526020016000206114d58787612490565b63ffffffff16600281106114eb576114eb613729565b6007020190508281600101541461153e5760018101546040517f93df584c00000000000000000000000000000000000000000000000000000000815260048101919091526024810184905260440161147b565b6000600180830182905563ffffffff881682526007602052604082209091878381111561156d5761156d6130d2565b600181111561157e5761157e6130d2565b8152602081019190915260400160002080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000811663ffffffff918216939093181691909117905582156115f85760405183907f0b31c0055e2d464bef7781994b98c4ff9ef4ae0d05f59feb6a68c42de5e201b890600090a25b60405184907ffc3e98dbbd47c3fa7c1c05b6ec711caeaf70eca4554192b9ada8fc11a37f298e90600090a2505050505050565b63ffffffff8216600090815260056020526040812081836001811115611653576116536130d2565b6001811115611664576116646130d2565b815260200190815260200160002061167c8484612490565b63ffffffff166002811061169257611692613729565b6007020160010154905092915050565b6116aa612542565b806116e1576040517f0849d8cc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006116ed84846124e7565b63ffffffff858116600090815260056020526040812092909116925083919085600181111561171e5761171e6130d2565b600181111561172f5761172f6130d2565b8152602001908152602001600020826002811061174e5761174e613729565b6007020160010154146117f95763ffffffff8416600090815260056020526040812090846001811115611783576117836130d2565b6001811115611794576117946130d2565b815260200190815260200160002081600281106117b3576117b3613729565b6007020160010154826040517f93df584c00000000000000000000000000000000000000000000000000000000815260040161147b929190918252602082015260400190565b60405182907f53f5d9228f0a4173bea6e5931c9b3afe6eeb6692ede1d182952970f152534e3b90600090a263ffffffff841660009081526005602052604081209084600181111561184c5761184c6130d2565b600181111561185d5761185d6130d2565b8152602001908152602001600020816002811061187c5761187c613729565b600702016001016000905550505050565b60005473ffffffffffffffffffffffffffffffffffffffff1633146118de576040517f02b543c600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000008082163390811790935560008054909116815560405173ffffffffffffffffffffffffffffffffffffffff909216929183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b6000611967600361257d565b905090565b63ffffffff8216600090815260056020526040812081836001811115611994576119946130d2565b60018111156119a5576119a56130d2565b815260200190815260200160002061167c84846124e7565b606060006119cb600361257d565b905060006119d984866137da565b90508315806119e85750818110155b15611a28576040805160008082526020820190925290611a1e565b611a0b612eb7565b815260200190600190039081611a035790505b5092505050610422565b6000611a348583613820565b905082811115611a415750815b6000611a4d8383613833565b67ffffffffffffffff811115611a6557611a656137f1565b604051908082528060200260200182016040528015611a9e57816020015b611a8b612eb7565b815260200190600190039081611a835790505b509050825b82811015611c17576000611ab8600383612587565b60408051808201825267ffffffffffffffff83168082526000908152600260209081529083902083518154608081850283018101909652606082018181529697509395928601949093919284929091849190840182828015611b3957602002820191906000526020600020905b815481526020019060010190808311611b25575b5050509183525050600182015460ff166020820152600282018054604090920191611b6390613758565b80601f0160208091040260200160405190810160405280929190818152602001828054611b8f90613758565b8015611bdc5780601f10611bb157610100808354040283529160200191611bdc565b820191906000526020600020905b815481529060010190602001808311611bbf57829003601f168201915b50505091909252505050905283611bf38785613833565b81518110611c0357611c03613729565b602090810291909101015250600101611aa3565b509695505050505050565b6000611c2c612542565b611c3d611c3884613a61565b61259a565b6000611c49868661196c565b9050828114611c8e576040517f93df584c000000000000000000000000000000000000000000000000000000008152600481018290526024810184905260440161147b565b8015611cc05760405183907f53f5d9228f0a4173bea6e5931c9b3afe6eeb6692ede1d182952970f152534e3b90600090a25b60068054600091908290611cd99063ffffffff16613b5d565b91906101000a81548163ffffffff021916908363ffffffff16021790559050611d23878787604051602001611d0e9190613e39565b60405160208183030381529060405284612a08565b63ffffffff881660009081526005602052604081209194509081886001811115611d4f57611d4f6130d2565b6001811115611d6057611d606130d2565b8152602001908152602001600020611d7889896124e7565b63ffffffff1660028110611d8e57611d8e613729565b600702016001810185905580547fffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000001663ffffffff841617815590508560028201611dd8828261431f565b905050837f94f085b7c57ec2a270befd0b7b2ec7452580040edee8bb0fb04609c81f0359c68388604051611e0d9291906144e6565b60405180910390a2505050949350505050565b611e28612ac8565b611e3181612b19565b50565b611e3c612ac8565b60005b8381101561202257611e83858583818110611e5c57611e5c613729565b9050602002016020810190611e71919061450d565b60039067ffffffffffffffff16612bdd565b611eed57848482818110611e9957611e99613729565b9050602002016020810190611eae919061450d565b6040517f1bd4d2d200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff909116600482015260240161147b565b60026000868684818110611f0357611f03613729565b9050602002016020810190611f18919061450d565b67ffffffffffffffff1681526020810191909152604001600090812090611f3f8282612efa565b6001820180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055611f77600283016000612f18565b5050611fb5858583818110611f8e57611f8e613729565b9050602002016020810190611fa3919061450d565b60039067ffffffffffffffff16612bf5565b507f2a680691fef3b2d105196805935232c661ce703e92d464ef0b94a7bc62d714f0858583818110611fe957611fe9613729565b9050602002016020810190611ffe919061450d565b60405167ffffffffffffffff909116815260200160405180910390a1600101611e3f565b5060005b818110156121cc57600083838381811061204257612042613729565b9050602002810190612054919061452a565b612062906020810190614082565b61206b9061455e565b9050600084848481811061208157612081613729565b9050602002810190612093919061452a565b6120a190602081019061450d565b90506120b08260000151612c01565b816020015160ff166000036120f1576040517fa9b3766e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff81166000908152600260209081526040909120835180518593612121928492910190612f52565b5060208201516001820180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660ff9092169190911790556040820151600282019061216e9082614630565b5061218891506003905067ffffffffffffffff8316612cc3565b507f05dd57854af2c291a94ea52e7c43d80bc3be7fa73022f98b735dea86642fa5e081836040516121ba92919061472c565b60405180910390a15050600101612026565b5050505050565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614612242576040517fac7a7efd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000612251600482868861474f565b61225a91614779565b90507fffffffff0000000000000000000000000000000000000000000000000000000081167fbae4e0fa00000000000000000000000000000000000000000000000000000000148015906122f057507fffffffff0000000000000000000000000000000000000000000000000000000081167f7524051a0000000000000000000000000000000000000000000000000000000014155b801561233e57507fffffffff0000000000000000000000000000000000000000000000000000000081167f5a837f970000000000000000000000000000000000000000000000000000000014155b15612399576040517f12ba286f0000000000000000000000000000000000000000000000000000000081527fffffffff000000000000000000000000000000000000000000000000000000008216600482015260240161147b565b60006123a960246004878961474f565b8101906123b691906147c1565b90508263ffffffff168114612407576040517f8a6e4ce800000000000000000000000000000000000000000000000000000000815263ffffffff80831660048301528416602482015260440161147b565b6000803073ffffffffffffffffffffffffffffffffffffffff1688886040516124319291906147da565b6000604051808303816000865af19150503d806000811461246e576040519150601f19603f3d011682016040523d82523d6000602084013e612473565b606091505b509150915081612484573d60208201fd5b50505050505050505050565b63ffffffff82166000908152600760205260408120818360018111156124b8576124b86130d2565b60018111156124c9576124c96130d2565b815260208101919091526040016000205463ffffffff169392505050565b63ffffffff821660009081526007602052604081208183600181111561250f5761250f6130d2565b6001811115612520576125206130d2565b815260208101919091526040016000205463ffffffff16600118905092915050565b33301461257b576040517f371a732800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b565b6000610422825490565b60006125938383612ccf565b9392505050565b806020015167ffffffffffffffff166000036125e2576040517f698cf8e000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000815160018111156125f7576125f76130d2565b141580156126185750600181516001811115612615576126156130d2565b14155b1561264f576040517f3302dbd700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b608081015151158061268c575060408051600060208201520160405160208183030381529060405280519060200120816080015180519060200120145b156126c3576040517f358c192700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60a08101515115806127005750604080516000602082015201604051602081830303815290604052805190602001208160a0015180519060200120145b15612737576040517fdee9857400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60208101516127529060039067ffffffffffffffff16612bdd565b61279a5760208101516040517f1bd4d2d200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff909116600482015260240161147b565b60408082015160208084015167ffffffffffffffff1660009081526002909152919091206001015460ff91821691168181111561280d576040517f2db22040000000000000000000000000000000000000000000000000000000008152600481018290526024810183905260440161147b565b60c08301515161010081111561284f576040517f1b925da600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61285a8360036137da565b8111612892576040517f4856694e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000808267ffffffffffffffff8111156128ae576128ae6137f1565b6040519080825280602002602001820160405280156128d7578160200160208202803683370190505b50905060005b838110156129975760008760c0015182815181106128fd576128fd613729565b60200260200101519050806040015151600014612922578361291e816147ea565b9450505b602081015151158061293357508051155b1561296c57806040517f9fa4031400000000000000000000000000000000000000000000000000000000815260040161147b9190614822565b806000015183838151811061298357612983613729565b6020908102919091010152506001016128dd565b5060006129a58560036137da565b6129b0906001613820565b9050808310156129f6576040517f548dd21f000000000000000000000000000000000000000000000000000000008152600481018490526024810182905260440161147b565b6129ff82612c01565b50505050505050565b6040516000907dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90612a66907f45564d000000000000000000000000000000000000000000000000000000000090469030908a908a908990602001614835565b60408051601f1981840301815290829052612a8591869060200161488e565b60408051808303601f190181529190528051602090910120167e0a0000000000000000000000000000000000000000000000000000000000001795945050505050565b60015473ffffffffffffffffffffffffffffffffffffffff16331461257b576040517f2b5c74de00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff821603612b68576040517fdad89dca00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff838116918217835560015460405192939116917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b60008181526001830160205260408120541515612593565b60006125938383612cf9565b805115611e31576040517f05a5196600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016906305a5196690612c7a9084906004016148bd565b600060405180830381865afa158015612c97573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052612cbf919081019061493a565b5050565b60006125938383612dec565b6000826000018281548110612ce657612ce6613729565b9060005260206000200154905092915050565b60008181526001830160205260408120548015612de2576000612d1d600183613833565b8554909150600090612d3190600190613833565b9050808214612d96576000866000018281548110612d5157612d51613729565b9060005260206000200154905080876000018481548110612d7457612d74613729565b6000918252602080832090910192909255918252600188019052604090208390555b8554869080612da757612da7614a96565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050610422565b6000915050610422565b6000818152600183016020526040812054612e3357508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155610422565b506000610422565b6040805160608101825260008082526020820152908101612eb26040805161010081019091528060008152602001600067ffffffffffffffff168152602001600060ff168152602001600067ffffffffffffffff168152602001606081526020016060815260200160608152602001606081525090565b905290565b6040518060400160405280600067ffffffffffffffff168152602001612eb2604051806060016040528060608152602001600060ff168152602001606081525090565b5080546000825590600052602060002090810190611e319190612f9d565b508054612f2490613758565b6000825580601f10612f34575050565b601f016020900490600052602060002090810190611e319190612f9d565b828054828255906000526020600020908101928215612f8d579160200282015b82811115612f8d578251825591602001919060010190612f72565b50612f99929150612f9d565b5090565b5b80821115612f995760008155600101612f9e565b600060208284031215612fc457600080fd5b81357fffffffff000000000000000000000000000000000000000000000000000000008116811461259357600080fd5b60005b8381101561300f578181015183820152602001612ff7565b50506000910152565b60008151808452613030816020860160208601612ff4565b601f01601f19169290920160200192915050565b6020815260006125936020830184613018565b63ffffffff81168114611e3157600080fd5b803561307481613057565b919050565b60028110611e3157600080fd5b803561307481613079565b6000806000606084860312156130a657600080fd5b83356130b181613057565b925060208401356130c181613079565b929592945050506040919091013590565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b60028110613138577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b9052565b80518252600060208201516060602085015261315b6060850182613018565b9050604083015184820360408601526131748282613018565b95945050505050565b60008282518085526020808601955060208260051b8401016020860160005b848110156131ca57601f198684030189526131b883835161313c565b9884019892509083019060010161319c565b5090979650505050505050565b63ffffffff8151168252602081015160208301526000604082015160606040850152613207606085018251613101565b602081015167ffffffffffffffff8116608086015250604081015160ff811660a086015250606081015167ffffffffffffffff811660c08601525060808101516101008060e087015261325e610160870183613018565b915060a08301517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa08088850301838901526132998483613018565b935060c0850151925080888503016101208901526132b7848461317d565b935060e0850151945080888503016101408901525050506131748183613018565b6040815260006132eb60408301856131d7565b905082151560208301529392505050565b6000806040838503121561330f57600080fd5b823561331a81613057565b9150602083013561332a81613079565b809150509250929050565b60408152600061334860408301856131d7565b828103602084015261317481856131d7565b6000806000806080858703121561337057600080fd5b843561337b81613057565b9350602085013561338b81613079565b93969395505050506040820135916060013590565b6000602082840312156133b257600080fd5b813561259381613057565b600080604083850312156133d057600080fd5b50508035926020909101359150565b60008151808452602080850194506020840160005b83811015613410578151875295820195908201906001016133f4565b509495945050505050565b600081516060845261343060608501826133df565b905060ff6020840151166020850152604083015184820360408601526131748282613018565b600060208083018184528085518083526040925060408601915060408160051b87010184880160005b838110156134e6578883037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc00185528151805167ffffffffffffffff1684528701518784018790526134d38785018261341b565b958801959350509086019060010161347f565b509098975050505050505050565b6000806000806080858703121561350a57600080fd5b843561351581613057565b9350602085013561352581613079565b9250604085013567ffffffffffffffff81111561354157600080fd5b8501610100818803121561355457600080fd5b9396929550929360600135925050565b60006020828403121561357657600080fd5b813573ffffffffffffffffffffffffffffffffffffffff8116811461259357600080fd5b60008083601f8401126135ac57600080fd5b50813567ffffffffffffffff8111156135c457600080fd5b6020830191508360208260051b850101111561121b57600080fd5b600080600080604085870312156135f557600080fd5b843567ffffffffffffffff8082111561360d57600080fd5b6136198883890161359a565b9096509450602087013591508082111561363257600080fd5b5061363f8782880161359a565b95989497509550505050565b67ffffffffffffffff81168114611e3157600080fd5b80356130748161364b565b6000806000806000806080878903121561368557600080fd5b863567ffffffffffffffff8082111561369d57600080fd5b6136a98a838b0161359a565b909850965060208901359150808211156136c257600080fd5b818901915089601f8301126136d657600080fd5b8135818111156136e557600080fd5b8a60208285010111156136f757600080fd5b60208301965080955050505061370f60408801613661565b915061371d60608801613069565b90509295509295509295565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600181811c9082168061376c57607f821691505b6020821081036137a5577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b8082028115828204841417610422576104226137ab565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b80820180821115610422576104226137ab565b81810381811115610422576104226137ab565b6040516060810167ffffffffffffffff81118282101715613869576138696137f1565b60405290565b604051610100810167ffffffffffffffff81118282101715613869576138696137f1565b604051601f8201601f1916810167ffffffffffffffff811182821017156138bc576138bc6137f1565b604052919050565b60ff81168114611e3157600080fd5b8035613074816138c4565b600082601f8301126138ef57600080fd5b813567ffffffffffffffff811115613909576139096137f1565b61391c6020601f19601f84011601613893565b81815284602083860101111561393157600080fd5b816020850160208301376000918101602001919091529392505050565b600067ffffffffffffffff821115613968576139686137f1565b5060051b60200190565b600082601f83011261398357600080fd5b813560206139986139938361394e565b613893565b82815260059290921b840181019181810190868411156139b757600080fd5b8286015b84811015611c1757803567ffffffffffffffff808211156139dc5760008081fd5b8189019150606080601f19848d030112156139f75760008081fd5b6139ff613846565b87840135815260408085013584811115613a195760008081fd5b613a278e8b838901016138de565b838b015250918401359183831115613a3f5760008081fd5b613a4d8d8a858801016138de565b9082015286525050509183019183016139bb565b60006101008236031215613a7457600080fd5b613a7c61386f565b613a8583613086565b8152613a9360208401613661565b6020820152613aa4604084016138d3565b6040820152613ab560608401613661565b6060820152608083013567ffffffffffffffff80821115613ad557600080fd5b613ae1368387016138de565b608084015260a0850135915080821115613afa57600080fd5b613b06368387016138de565b60a084015260c0850135915080821115613b1f57600080fd5b613b2b36838701613972565b60c084015260e0850135915080821115613b4457600080fd5b50613b51368286016138de565b60e08301525092915050565b600063ffffffff808316818103613b7657613b766137ab565b6001019392505050565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112613bb557600080fd5b830160208101925035905067ffffffffffffffff811115613bd557600080fd5b80360382131561121b57600080fd5b818352818160208501375060006020828401015260006020601f19601f840116840101905092915050565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112613c4457600080fd5b830160208101925035905067ffffffffffffffff811115613c6457600080fd5b8060051b360382131561121b57600080fd5b60008383855260208086019550808560051b830101846000805b88811015613d3457601f19868503018a5282357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa1893603018112613cd2578283fd5b8801803585526060613ce687830183613b80565b8289890152613cf88389018284613be4565b925050506040613d0a81840184613b80565b935087830382890152613d1e838583613be4565b9d89019d97505050938601935050600101613c90565b509198975050505050505050565b6000610100613d5984613d5485613086565b613101565b613d6560208401613661565b67ffffffffffffffff166020850152613d80604084016138d3565b60ff166040850152613d9460608401613661565b67ffffffffffffffff166060850152613db06080840184613b80565b826080870152613dc38387018284613be4565b92505050613dd460a0840184613b80565b85830360a0870152613de7838284613be4565b92505050613df860c0840184613c0f565b85830360c0870152613e0b838284613c76565b92505050613e1c60e0840184613b80565b85830360e0870152613e2f838284613be4565b9695505050505050565b6020815260006125936020830184613d42565b600081356104228161364b565b60008135610422816138c4565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112613e9b57600080fd5b83018035915067ffffffffffffffff821115613eb657600080fd5b60200191503681900382131561121b57600080fd5b5b81811015612cbf5760008155600101613ecc565b601f821115613f1957806000526020600020601f840160051c81016020851015613f075750805b6121cc601f850160051c830182613ecb565b505050565b67ffffffffffffffff831115613f3657613f366137f1565b613f4a83613f448354613758565b83613ee0565b6000601f841160018114613f9c5760008515613f665750838201355b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600387901b1c1916600186901b1783556121cc565b600083815260209020601f19861690835b82811015613fcd5786850135825560209485019460019092019101613fad565b5086821015614008577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88860031b161c19848701351681555b505060018560011b0183555050505050565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261404f57600080fd5b83018035915067ffffffffffffffff82111561406a57600080fd5b6020019150600581901b360382131561121b57600080fd5b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa18336030181126140b657600080fd5b9190910192915050565b6140ca8154613758565b8015612cbf57601f8111600181146140e457505060009055565b826000526020600020614102601f840160051c820160018301613ecb565b60008085559055505050565b81358155600180820160206141266020860186613e66565b67ffffffffffffffff81111561413e5761413e6137f1565b6141528161414c8654613758565b86613ee0565b6000601f8211600181146141a4576000831561416e5750838201355b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600385901b1c1916600184901b178655614219565b600086815260209020601f19841690835b828110156141d257868501358255938701939089019087016141b5565b508482101561420d577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88660031b161c19848701351681555b505060018360011b0186555b5050505050505061422d6040830183613e66565b61423b818360028601613f1e565b50505050565b6801000000000000000083111561425a5761425a6137f1565b8054838255808410156142d95760038160030260038104831461427f5761427f6137ab565b85600302600381048714614295576142956137ab565b6000858152602081209283019291909101905b828210156142d4578082556142bf600183016140c0565b6142cb600283016140c0565b908301906142a8565b505050505b5060008181526020812083915b85811015614317576143016142fb8487614082565b8361410e565b60209290920191600391909101906001016142e6565b505050505050565b813561432a81613079565b60028110614361577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0082541660ff82168117835550506143d861439e60208401613e4c565b82547fffffffffffffffffffffffffffffffffffffffffffffff0000000000000000ff1660089190911b68ffffffffffffffff0016178255565b6144226143e760408401613e59565b82547fffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffffff1660489190911b69ff00000000000000000016178255565b61447461443160608401613e4c565b82547fffffffffffffffffffffffffffff0000000000000000ffffffffffffffffffff1660509190911b71ffffffffffffffff0000000000000000000016178255565b6144816080830183613e66565b61448f818360018601613f1e565b505061449e60a0830183613e66565b6144ac818360028601613f1e565b50506144bb60c083018361401a565b6144c9818360038601614241565b50506144d860e0830183613e66565b61423b818360048601613f1e565b63ffffffff831681526040602082015260006145056040830184613d42565b949350505050565b60006020828403121561451f57600080fd5b81356125938161364b565b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc18336030181126140b657600080fd5b60006060823603121561457057600080fd5b614578613846565b823567ffffffffffffffff8082111561459057600080fd5b9084019036601f8301126145a357600080fd5b813560206145b36139938361394e565b82815260059290921b840181019181810190368411156145d257600080fd5b948201945b838610156145f0578535825294820194908201906145d7565b8652506145fe8782016138d3565b9085015250604085013591508082111561461757600080fd5b50614624368286016138de565b60408301525092915050565b815167ffffffffffffffff81111561464a5761464a6137f1565b61465e816146588454613758565b84613ee0565b602080601f8311600181146146b1576000841561467b5750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b178555614317565b600085815260208120601f198616915b828110156146e0578886015182559484019460019091019084016146c1565b508582101561471c57878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b67ffffffffffffffff83168152604060208201526000614505604083018461341b565b6000808585111561475f57600080fd5b8386111561476c57600080fd5b5050820193919092039150565b7fffffffff0000000000000000000000000000000000000000000000000000000081358181169160048510156147b95780818660040360031b1b83161692505b505092915050565b6000602082840312156147d357600080fd5b5035919050565b8183823760009101908152919050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361481b5761481b6137ab565b5060010190565b602081526000612593602083018461313c565b8681526020810186905273ffffffffffffffffffffffffffffffffffffffff8516604082015263ffffffff848116606083015260c082019061487a6080840186613101565b80841660a084015250979650505050505050565b600083516148a0818460208801612ff4565b8351908301906148b4818360208801612ff4565b01949350505050565b60208152600061259360208301846133df565b805161307481613057565b600082601f8301126148ec57600080fd5b815160206148fc6139938361394e565b8083825260208201915060208460051b87010193508684111561491e57600080fd5b602086015b84811015611c175780518352918301918301614923565b6000602080838503121561494d57600080fd5b825167ffffffffffffffff8082111561496557600080fd5b818501915085601f83011261497957600080fd5b81516149876139938261394e565b81815260059190911b830184019084810190888311156149a657600080fd5b8585015b83811015614a89578051858111156149c157600080fd5b8601610100818c03601f19018113156149d957600080fd5b6149e161386f565b6149ec8a84016148d0565b81526149fa604084016148d0565b8a820152614a0a606084016148d0565b60408201526080830151606082015260a0830151608082015260c083015160a082015260e08084015189811115614a415760008081fd5b614a4f8f8d838801016148db565b60c084015250918301519188831115614a685760008081fd5b614a768e8c858701016148db565b90820152855250509186019186016149aa565b5098975050505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fdfea164736f6c6343000818000a", } var CCIPHomeABI = CCIPHomeMetaData.ABI @@ -345,28 +345,6 @@ func (_CCIPHome *CCIPHomeCallerSession) GetCapabilityRegistry() (common.Address, return _CCIPHome.Contract.GetCapabilityRegistry(&_CCIPHome.CallOpts) } -func (_CCIPHome *CCIPHomeCaller) GetChainConfig(opts *bind.CallOpts, chainSelector uint64) (CCIPHomeChainConfig, error) { - var out []interface{} - err := _CCIPHome.contract.Call(opts, &out, "getChainConfig", chainSelector) - - if err != nil { - return *new(CCIPHomeChainConfig), err - } - - out0 := *abi.ConvertType(out[0], new(CCIPHomeChainConfig)).(*CCIPHomeChainConfig) - - return out0, err - -} - -func (_CCIPHome *CCIPHomeSession) GetChainConfig(chainSelector uint64) (CCIPHomeChainConfig, error) { - return _CCIPHome.Contract.GetChainConfig(&_CCIPHome.CallOpts, chainSelector) -} - -func (_CCIPHome *CCIPHomeCallerSession) GetChainConfig(chainSelector uint64) (CCIPHomeChainConfig, error) { - return _CCIPHome.Contract.GetChainConfig(&_CCIPHome.CallOpts, chainSelector) -} - func (_CCIPHome *CCIPHomeCaller) GetConfig(opts *bind.CallOpts, donId uint32, pluginType uint8, configDigest [32]byte) (GetConfig, error) { @@ -1826,8 +1804,6 @@ type CCIPHomeInterface interface { GetCapabilityRegistry(opts *bind.CallOpts) (common.Address, error) - GetChainConfig(opts *bind.CallOpts, chainSelector uint64) (CCIPHomeChainConfig, error) - GetConfig(opts *bind.CallOpts, donId uint32, pluginType uint8, configDigest [32]byte) (GetConfig, error) diff --git a/core/gethwrappers/ccip/generated/ccip_reader_tester/ccip_reader_tester.go b/core/gethwrappers/ccip/generated/ccip_reader_tester/ccip_reader_tester.go index 7e68fc050b1..168d31806b8 100644 --- a/core/gethwrappers/ccip/generated/ccip_reader_tester/ccip_reader_tester.go +++ b/core/gethwrappers/ccip/generated/ccip_reader_tester/ccip_reader_tester.go @@ -100,8 +100,8 @@ type OffRampSourceChainConfig struct { } var CCIPReaderTesterMetaData = &bind.MetaData{ - ABI: "[{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"}],\"internalType\":\"structInternal.RampMessageHeader\",\"name\":\"header\",\"type\":\"tuple\"},{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraArgs\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"feeTokenAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"feeValueJuels\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"sourcePoolAddress\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"destExecData\",\"type\":\"bytes\"}],\"internalType\":\"structInternal.EVM2AnyTokenTransfer[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"}],\"indexed\":false,\"internalType\":\"structInternal.EVM2AnyRampMessage\",\"name\":\"message\",\"type\":\"tuple\"}],\"name\":\"CCIPMessageSent\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRampAddress\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"maxSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"merkleRoot\",\"type\":\"bytes32\"}],\"indexed\":false,\"internalType\":\"structInternal.MerkleRoot[]\",\"name\":\"merkleRoots\",\"type\":\"tuple[]\"},{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sourceToken\",\"type\":\"address\"},{\"internalType\":\"uint224\",\"name\":\"usdPerToken\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.TokenPriceUpdate[]\",\"name\":\"tokenPriceUpdates\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint224\",\"name\":\"usdPerUnitGas\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.GasPriceUpdate[]\",\"name\":\"gasPriceUpdates\",\"type\":\"tuple[]\"}],\"indexed\":false,\"internalType\":\"structInternal.PriceUpdates\",\"name\":\"priceUpdates\",\"type\":\"tuple\"}],\"name\":\"CommitReportAccepted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"messageHash\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"enumInternal.MessageExecutionState\",\"name\":\"state\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"returnData\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"gasUsed\",\"type\":\"uint256\"}],\"name\":\"ExecutionStateChanged\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"}],\"internalType\":\"structInternal.RampMessageHeader\",\"name\":\"header\",\"type\":\"tuple\"},{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraArgs\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"feeTokenAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"feeValueJuels\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"sourcePoolAddress\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"destExecData\",\"type\":\"bytes\"}],\"internalType\":\"structInternal.EVM2AnyTokenTransfer[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.EVM2AnyRampMessage\",\"name\":\"message\",\"type\":\"tuple\"}],\"name\":\"emitCCIPMessageSent\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sourceToken\",\"type\":\"address\"},{\"internalType\":\"uint224\",\"name\":\"usdPerToken\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.TokenPriceUpdate[]\",\"name\":\"tokenPriceUpdates\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint224\",\"name\":\"usdPerUnitGas\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.GasPriceUpdate[]\",\"name\":\"gasPriceUpdates\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.PriceUpdates\",\"name\":\"priceUpdates\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRampAddress\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"maxSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"merkleRoot\",\"type\":\"bytes32\"}],\"internalType\":\"structInternal.MerkleRoot[]\",\"name\":\"merkleRoots\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"internalType\":\"structIRMNRemote.Signature[]\",\"name\":\"rmnSignatures\",\"type\":\"tuple[]\"}],\"internalType\":\"structOffRamp.CommitReport\",\"name\":\"report\",\"type\":\"tuple\"}],\"name\":\"emitCommitReportAccepted\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"messageHash\",\"type\":\"bytes32\"},{\"internalType\":\"enumInternal.MessageExecutionState\",\"name\":\"state\",\"type\":\"uint8\"},{\"internalType\":\"bytes\",\"name\":\"returnData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"gasUsed\",\"type\":\"uint256\"}],\"name\":\"emitExecutionStateChanged\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"getExpectedNextSequenceNumber\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"sender\",\"type\":\"bytes\"}],\"name\":\"getInboundNonce\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getLatestPriceSequenceNumber\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"getSourceChainConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"internalType\":\"structOffRamp.SourceChainConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"setDestChainSeqNr\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"testNonce\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"sender\",\"type\":\"bytes\"}],\"name\":\"setInboundNonce\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"seqNr\",\"type\":\"uint64\"}],\"name\":\"setLatestPriceSequenceNumber\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"internalType\":\"structOffRamp.SourceChainConfig\",\"name\":\"sourceChainConfig\",\"type\":\"tuple\"}],\"name\":\"setSourceChainConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", - Bin: "0x608080604052346015576117e2908161001b8239f35b600080fdfe608080604052600436101561001357600080fd5b60003560e01c9081633f4b04aa14611503575080634bf7869714610f7457806369600bca14610f055780639041be3d14610e5657806393df286714610d97578063bfc9b789146107b9578063c1a5a3551461072b578063c7c1cba11461065b578063c9223625146105ca578063e83eabba1461029c5763e9d68a8e1461009857600080fd5b346102975760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102975767ffffffffffffffff6100d8611546565b6060806040516100e7816115c1565b60008152600060208201526000604082015201521660005260006020526040600020604051610115816115c1565b815473ffffffffffffffffffffffffffffffffffffffff811682526001602083019360ff8360a01c161515855267ffffffffffffffff604085019360a81c16835201926040519360009080549061016b82611782565b808852916001811690811561024057506001146101f0575b73ffffffffffffffffffffffffffffffffffffffff866101ec8967ffffffffffffffff89896101b4848b03856115dd565b6060860193845260405196879660208852511660208701525115156040860152511660608401525160808084015260a0830190611723565b0390f35b6000908152602081209092505b81831061022657505084016020018273ffffffffffffffffffffffffffffffffffffffff610183565b6001816020929493945483858b01015201910191906101fd565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166020808a019190915292151560051b8801909201925084915073ffffffffffffffffffffffffffffffffffffffff9050610183565b600080fd5b346102975760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610297576102d3611546565b60243567ffffffffffffffff81116102975760807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc82360301126102975760405161031d816115c1565b816004013573ffffffffffffffffffffffffffffffffffffffff8116810361029757815260248201358015158103610297576020820190815261036260448401611574565b6040830190815260648401359367ffffffffffffffff85116102975761039967ffffffffffffffff9160046001973692010161163f565b956060850196875216600052600060205273ffffffffffffffffffffffffffffffffffffffff60406000209351167fffffff00000000000000000000000000000000000000000000000000000000007cffffffffffffffff00000000000000000000000000000000000000000074ff000000000000000000000000000000000000000086549551151560a01b16935160a81b169316171717815501905190815167ffffffffffffffff811161059b576104528254611782565b601f8111610553575b50602092601f82116001146104b757928192936000926104ac575b50507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8260011b9260031b1c1916179055600080f35b015190508380610476565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe082169383600052806000209160005b86811061053b5750836001959610610504575b505050811b019055005b01517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88460031b161c191690558380806104fa565b919260206001819286850151815501940192016104e7565b826000526020600020601f830160051c81019160208410610591575b601f0160051c01905b818110610585575061045b565b60008155600101610578565b909150819061056f565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b346102975760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261029757610601611546565b60243567ffffffffffffffff81116102975767ffffffffffffffff6020809361062f839436906004016116cc565b939091166000526002825260406000208360405194859384378201908152030190205416604051908152f35b346102975760e07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261029757610692611546565b61069a61155d565b9060843560048110156102975760a43567ffffffffffffffff81116102975761070a6106eb7f05665fe9ad095383d018353f4cbcba77e84db27dd215081bbf7cdf9ae6fbe48b92369060040161163f565b6040519360643585526020850152608060408501526080840190611723565b9160c43560608201528067ffffffffffffffff8060443597169516930390a4005b346102975760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261029757610762611546565b67ffffffffffffffff61077361155d565b9116600052600160205267ffffffffffffffff604060002091167fffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000825416179055600080f35b346102975760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102975760043567ffffffffffffffff81116102975760607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc823603011261029757604051906060820182811067ffffffffffffffff82111761059b57604052806004013567ffffffffffffffff811161029757810160407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc82360301126102975760405190610893826115a5565b600481013567ffffffffffffffff81116102975760049082010136601f820112156102975780356108c3816116b4565b916108d160405193846115dd565b81835260208084019260061b8201019036821161029757602001915b818310610d58575050508252602481013567ffffffffffffffff811161029757600491010136601f82011215610297578035610928816116b4565b9161093660405193846115dd565b81835260208084019260061b8201019036821161029757602001915b818310610d195750505060208201528252602481013567ffffffffffffffff81116102975781019036602383011215610297576004820135610993816116b4565b926109a160405194856115dd565b818452602060048186019360051b83010101903682116102975760248101925b828410610c5857505050506020830191825260448101359067ffffffffffffffff8211610297570136602382011215610297576004810135610a02816116b4565b91610a1060405193846115dd565b818352602060048185019360061b830101019036821161029757602401915b818310610c2757505050604083015251905160405190604082016040835283518091526060830190602060608260051b8601019501916000905b828210610b8f57505050508183036020830152604083019080519160408552825180915260206060860193019060005b818110610b3957505050602001519260208183039101526020808451928381520193019060005b818110610aef577f35c02761bcd3ef995c6a601a1981f4ed3934dcbe5041e24e286c89f5531d17e484860385a1005b8251805167ffffffffffffffff1686526020908101517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff168187015260409095019490920191600101610ac0565b8251805173ffffffffffffffffffffffffffffffffffffffff1686526020908101517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff168187015260409095019490920191600101610a99565b90919295602080827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa0896001950301855289519067ffffffffffffffff8251168152608080610beb8585015160a08786015260a0850190611723565b9367ffffffffffffffff604082015116604085015267ffffffffffffffff60608201511660608501520151910152980192019201909291610a69565b6040833603126102975760206040918251610c41816115a5565b853581528286013583820152815201920191610a2f565b833567ffffffffffffffff81116102975760049083010160a07fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe082360301126102975760405191610ca883611589565b610cb460208301611574565b835260408201359267ffffffffffffffff84116102975760a060209493610ce1869586369184010161163f565b85840152610cf160608201611574565b6040840152610d0260808201611574565b6060840152013560808201528152019301926109c1565b6040833603126102975760206040918251610d33816115a5565b610d3c86611574565b8152610d498387016116fa565b83820152815201920191610952565b6040833603126102975760206040918251610d72816115a5565b610d7b8661161e565b8152610d888387016116fa565b838201528152019201916108ed565b346102975760607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261029757610dce611546565b610dd661155d565b906044359067ffffffffffffffff821161029757602067ffffffffffffffff9291610e06849336906004016116cc565b9390911660005260028252604060002083604051948593843782019081520301902091167fffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000825416179055600080f35b346102975760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102975767ffffffffffffffff610e96611546565b166000526001602052600167ffffffffffffffff604060002054160167ffffffffffffffff8111610ed65760209067ffffffffffffffff60405191168152f35b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b346102975760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102975767ffffffffffffffff610f45611546565b167fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000006003541617600355600080f35b346102975760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261029757610fab611546565b60243567ffffffffffffffff8111610297577ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc813603016101a08112610297576040519061012082019082821067ffffffffffffffff83111761059b5760a091604052126102975760405161101f81611589565b8260040135815261103260248401611574565b602082015261104360448401611574565b604082015261105460648401611574565b606082015261106560848401611574565b6080820152815261107860a4830161161e565b926020820193845260c483013567ffffffffffffffff8111610297576110a4906004369186010161163f565b6040830190815260e484013567ffffffffffffffff8111610297576110cf906004369187010161163f565b936060840194855261010481013567ffffffffffffffff8111610297576110fc906004369184010161163f565b9460808501958652611111610124830161161e565b9560a0860196875260c0860191610144840135835260e087019361016481013585526101848101359067ffffffffffffffff821161029757019436602387011215610297576004860135611164816116b4565b9661117260405198896115dd565b81885260206004818a019360051b83010101903682116102975760248101925b8284106114115750505050610100880195865287516060015167ffffffffffffffff16996040519860208a5251805160208b0152602081015167ffffffffffffffff1660408b0152604081015167ffffffffffffffff1660608b0152606081015167ffffffffffffffff1660808b01526080015167ffffffffffffffff1660a08a01525173ffffffffffffffffffffffffffffffffffffffff1660c08901525160e088016101a090526101c0880161124991611723565b9051908781037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe00161010089015261128091611723565b9051908681037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0016101208801526112b791611723565b955173ffffffffffffffffffffffffffffffffffffffff16610140860152516101608501525161018084015251928281037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0016101a0840152835180825260208201918160051b810160200195602001926000915b838310611367578867ffffffffffffffff87167f192442a2b2adb6a7948f097023cb6b57d29d3a7a5dd33e6666d33c39cc456f32898b038aa3005b9091929396602080611402837fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe086600196030187528b519073ffffffffffffffffffffffffffffffffffffffff825116815260806113e76113d58685015160a08886015260a0850190611723565b60408501518482036040860152611723565b92606081015160608401520151906080818403910152611723565b9901930193019193929061132c565b833567ffffffffffffffff81116102975760049083010160a07fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08236030112610297576040519161146183611589565b61146d6020830161161e565b8352604082013567ffffffffffffffff811161029757611493906020369185010161163f565b6020840152606082013567ffffffffffffffff8111610297576114bc906020369185010161163f565b60408401526080820135606084015260a08201359267ffffffffffffffff8411610297576114f3602094938580953692010161163f565b6080820152815201930192611192565b346102975760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102975760209067ffffffffffffffff600354168152f35b6004359067ffffffffffffffff8216820361029757565b6024359067ffffffffffffffff8216820361029757565b359067ffffffffffffffff8216820361029757565b60a0810190811067ffffffffffffffff82111761059b57604052565b6040810190811067ffffffffffffffff82111761059b57604052565b6080810190811067ffffffffffffffff82111761059b57604052565b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff82111761059b57604052565b359073ffffffffffffffffffffffffffffffffffffffff8216820361029757565b81601f820112156102975780359067ffffffffffffffff821161059b576040519261169260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f86011601856115dd565b8284526020838301011161029757816000926020809301838601378301015290565b67ffffffffffffffff811161059b5760051b60200190565b9181601f840112156102975782359167ffffffffffffffff8311610297576020838186019501011161029757565b35907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8216820361029757565b919082519283825260005b84811061176d5750507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8460006020809697860101520116010190565b8060208092840101518282860101520161172e565b90600182811c921680156117cb575b602083101461179c57565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b91607f169161179156fea164736f6c634300081a000a", + ABI: "[{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"}],\"internalType\":\"structInternal.RampMessageHeader\",\"name\":\"header\",\"type\":\"tuple\"},{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraArgs\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"feeTokenAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"feeValueJuels\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"sourcePoolAddress\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"destExecData\",\"type\":\"bytes\"}],\"internalType\":\"structInternal.EVM2AnyTokenTransfer[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"}],\"indexed\":false,\"internalType\":\"structInternal.EVM2AnyRampMessage\",\"name\":\"message\",\"type\":\"tuple\"}],\"name\":\"CCIPMessageSent\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRampAddress\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"maxSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"merkleRoot\",\"type\":\"bytes32\"}],\"indexed\":false,\"internalType\":\"structInternal.MerkleRoot[]\",\"name\":\"merkleRoots\",\"type\":\"tuple[]\"},{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sourceToken\",\"type\":\"address\"},{\"internalType\":\"uint224\",\"name\":\"usdPerToken\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.TokenPriceUpdate[]\",\"name\":\"tokenPriceUpdates\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint224\",\"name\":\"usdPerUnitGas\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.GasPriceUpdate[]\",\"name\":\"gasPriceUpdates\",\"type\":\"tuple[]\"}],\"indexed\":false,\"internalType\":\"structInternal.PriceUpdates\",\"name\":\"priceUpdates\",\"type\":\"tuple\"}],\"name\":\"CommitReportAccepted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"messageHash\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"enumInternal.MessageExecutionState\",\"name\":\"state\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"returnData\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"gasUsed\",\"type\":\"uint256\"}],\"name\":\"ExecutionStateChanged\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"}],\"internalType\":\"structInternal.RampMessageHeader\",\"name\":\"header\",\"type\":\"tuple\"},{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraArgs\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"feeTokenAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"feeValueJuels\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"sourcePoolAddress\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"destExecData\",\"type\":\"bytes\"}],\"internalType\":\"structInternal.EVM2AnyTokenTransfer[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.EVM2AnyRampMessage\",\"name\":\"message\",\"type\":\"tuple\"}],\"name\":\"emitCCIPMessageSent\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sourceToken\",\"type\":\"address\"},{\"internalType\":\"uint224\",\"name\":\"usdPerToken\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.TokenPriceUpdate[]\",\"name\":\"tokenPriceUpdates\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint224\",\"name\":\"usdPerUnitGas\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.GasPriceUpdate[]\",\"name\":\"gasPriceUpdates\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.PriceUpdates\",\"name\":\"priceUpdates\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRampAddress\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"maxSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"merkleRoot\",\"type\":\"bytes32\"}],\"internalType\":\"structInternal.MerkleRoot[]\",\"name\":\"merkleRoots\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"internalType\":\"structIRMNRemote.Signature[]\",\"name\":\"rmnSignatures\",\"type\":\"tuple[]\"}],\"internalType\":\"structOffRamp.CommitReport\",\"name\":\"report\",\"type\":\"tuple\"}],\"name\":\"emitCommitReportAccepted\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"messageHash\",\"type\":\"bytes32\"},{\"internalType\":\"enumInternal.MessageExecutionState\",\"name\":\"state\",\"type\":\"uint8\"},{\"internalType\":\"bytes\",\"name\":\"returnData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"gasUsed\",\"type\":\"uint256\"}],\"name\":\"emitExecutionStateChanged\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"getExpectedNextSequenceNumber\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"sender\",\"type\":\"bytes\"}],\"name\":\"getInboundNonce\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"getSourceChainConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"internalType\":\"structOffRamp.SourceChainConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"setDestChainSeqNr\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"testNonce\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"sender\",\"type\":\"bytes\"}],\"name\":\"setInboundNonce\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"internalType\":\"structOffRamp.SourceChainConfig\",\"name\":\"sourceChainConfig\",\"type\":\"tuple\"}],\"name\":\"setSourceChainConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", + Bin: "0x608060405234801561001057600080fd5b506118e3806100206000396000f3fe608060405234801561001057600080fd5b50600436106100a35760003560e01c8063c1a5a35511610076578063c92236251161005b578063c92236251461017c578063e83eabba1461018f578063e9d68a8e146101a257600080fd5b8063c1a5a35514610114578063c7c1cba11461016957600080fd5b80634bf78697146100a85780639041be3d146100bd57806393df2867146100ee578063bfc9b78914610101575b600080fd5b6100bb6100b63660046109d1565b6101c2565b005b6100d06100cb366004610b0c565b61021b565b60405167ffffffffffffffff90911681526020015b60405180910390f35b6100bb6100fc366004610b77565b61024b565b6100bb61010f366004610e25565b6102c6565b6100bb610122366004610fb0565b67ffffffffffffffff918216600090815260016020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001691909216179055565b6100bb610177366004610fe3565b610308565b6100d061018a366004611075565b610365565b6100bb61019d3660046110c8565b6103b1565b6101b56101b0366004610b0c565b61049b565b6040516100e591906111e8565b80600001516060015167ffffffffffffffff168267ffffffffffffffff167f192442a2b2adb6a7948f097023cb6b57d29d3a7a5dd33e6666d33c39cc456f328360405161020f919061132e565b60405180910390a35050565b67ffffffffffffffff80821660009081526001602081905260408220549192610245921690611486565b92915050565b67ffffffffffffffff841660009081526002602052604090819020905184919061027890859085906114d5565b908152604051908190036020019020805467ffffffffffffffff929092167fffffffffffffffffffffffffffffffffffffffffffffffff000000000000000090921691909117905550505050565b602081015181516040517f35c02761bcd3ef995c6a601a1981f4ed3934dcbe5041e24e286c89f5531d17e4926102fd9290916115d9565b60405180910390a150565b848667ffffffffffffffff168867ffffffffffffffff167f05665fe9ad095383d018353f4cbcba77e84db27dd215081bbf7cdf9ae6fbe48b8787878760405161035494939291906116b1565b60405180910390a450505050505050565b67ffffffffffffffff8316600090815260026020526040808220905161038e90859085906114d5565b9081526040519081900360200190205467ffffffffffffffff1690509392505050565b67ffffffffffffffff808316600090815260208181526040918290208451815492860151938601519094167501000000000000000000000000000000000000000000027fffffff0000000000000000ffffffffffffffffffffffffffffffffffffffffff93151574010000000000000000000000000000000000000000027fffffffffffffffffffffff00000000000000000000000000000000000000000090931673ffffffffffffffffffffffffffffffffffffffff9095169490941791909117919091169190911781556060820151829190600182019061049490826117bc565b5050505050565b604080516080808201835260008083526020808401829052838501829052606080850181905267ffffffffffffffff87811684528383529286902086519485018752805473ffffffffffffffffffffffffffffffffffffffff8116865274010000000000000000000000000000000000000000810460ff16151593860193909352750100000000000000000000000000000000000000000090920490921694830194909452600184018054939492939184019161055790611718565b80601f016020809104026020016040519081016040528092919081815260200182805461058390611718565b80156105d05780601f106105a5576101008083540402835291602001916105d0565b820191906000526020600020905b8154815290600101906020018083116105b357829003601f168201915b5050505050815250509050919050565b803567ffffffffffffffff811681146105f857600080fd5b919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60405160a0810167ffffffffffffffff8111828210171561064f5761064f6105fd565b60405290565b604051610120810167ffffffffffffffff8111828210171561064f5761064f6105fd565b6040805190810167ffffffffffffffff8111828210171561064f5761064f6105fd565b6040516060810167ffffffffffffffff8111828210171561064f5761064f6105fd565b6040516080810167ffffffffffffffff8111828210171561064f5761064f6105fd565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715610729576107296105fd565b604052919050565b600060a0828403121561074357600080fd5b61074b61062c565b90508135815261075d602083016105e0565b602082015261076e604083016105e0565b604082015261077f606083016105e0565b6060820152610790608083016105e0565b608082015292915050565b73ffffffffffffffffffffffffffffffffffffffff811681146107bd57600080fd5b50565b80356105f88161079b565b600082601f8301126107dc57600080fd5b813567ffffffffffffffff8111156107f6576107f66105fd565b61082760207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116016106e2565b81815284602083860101111561083c57600080fd5b816020850160208301376000918101602001919091529392505050565b600067ffffffffffffffff821115610873576108736105fd565b5060051b60200190565b600082601f83011261088e57600080fd5b813560206108a361089e83610859565b6106e2565b82815260059290921b840181019181810190868411156108c257600080fd5b8286015b848110156109c657803567ffffffffffffffff808211156108e75760008081fd5b818901915060a0807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0848d030112156109205760008081fd5b61092861062c565b6109338885016107c0565b8152604080850135848111156109495760008081fd5b6109578e8b838901016107cb565b8a84015250606080860135858111156109705760008081fd5b61097e8f8c838a01016107cb565b838501525060809150818601358184015250828501359250838311156109a45760008081fd5b6109b28d8a858801016107cb565b9082015286525050509183019183016108c6565b509695505050505050565b600080604083850312156109e457600080fd5b6109ed836105e0565b9150602083013567ffffffffffffffff80821115610a0a57600080fd5b908401906101a08287031215610a1f57600080fd5b610a27610655565b610a318784610731565b8152610a3f60a084016107c0565b602082015260c083013582811115610a5657600080fd5b610a62888286016107cb565b60408301525060e083013582811115610a7a57600080fd5b610a86888286016107cb565b6060830152506101008084013583811115610aa057600080fd5b610aac898287016107cb565b608084015250610abf61012085016107c0565b60a083015261014084013560c083015261016084013560e083015261018084013583811115610aed57600080fd5b610af98982870161087d565b8284015250508093505050509250929050565b600060208284031215610b1e57600080fd5b610b27826105e0565b9392505050565b60008083601f840112610b4057600080fd5b50813567ffffffffffffffff811115610b5857600080fd5b602083019150836020828501011115610b7057600080fd5b9250929050565b60008060008060608587031215610b8d57600080fd5b610b96856105e0565b9350610ba4602086016105e0565b9250604085013567ffffffffffffffff811115610bc057600080fd5b610bcc87828801610b2e565b95989497509550505050565b80357bffffffffffffffffffffffffffffffffffffffffffffffffffffffff811681146105f857600080fd5b600082601f830112610c1557600080fd5b81356020610c2561089e83610859565b82815260069290921b84018101918181019086841115610c4457600080fd5b8286015b848110156109c65760408189031215610c615760008081fd5b610c69610679565b610c72826105e0565b8152610c7f858301610bd8565b81860152835291830191604001610c48565b600082601f830112610ca257600080fd5b81356020610cb261089e83610859565b82815260059290921b84018101918181019086841115610cd157600080fd5b8286015b848110156109c657803567ffffffffffffffff80821115610cf65760008081fd5b818901915060a0807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0848d03011215610d2f5760008081fd5b610d3761062c565b610d428885016105e0565b815260408085013584811115610d585760008081fd5b610d668e8b838901016107cb565b8a8401525060609350610d7a8486016105e0565b908201526080610d8b8582016105e0565b93820193909352920135908201528352918301918301610cd5565b600082601f830112610db757600080fd5b81356020610dc761089e83610859565b82815260069290921b84018101918181019086841115610de657600080fd5b8286015b848110156109c65760408189031215610e035760008081fd5b610e0b610679565b813581528482013585820152835291830191604001610dea565b60006020808385031215610e3857600080fd5b823567ffffffffffffffff80821115610e5057600080fd5b9084019060608287031215610e6457600080fd5b610e6c61069c565b823582811115610e7b57600080fd5b83016040818903811315610e8e57600080fd5b610e96610679565b823585811115610ea557600080fd5b8301601f81018b13610eb657600080fd5b8035610ec461089e82610859565b81815260069190911b8201890190898101908d831115610ee357600080fd5b928a01925b82841015610f335785848f031215610f005760008081fd5b610f08610679565b8435610f138161079b565b8152610f20858d01610bd8565b818d0152825292850192908a0190610ee8565b845250505082870135915084821115610f4b57600080fd5b610f578a838501610c04565b81880152835250508284013582811115610f7057600080fd5b610f7c88828601610c91565b85830152506040830135935081841115610f9557600080fd5b610fa187858501610da6565b60408201529695505050505050565b60008060408385031215610fc357600080fd5b610fcc836105e0565b9150610fda602084016105e0565b90509250929050565b600080600080600080600060e0888a031215610ffe57600080fd5b611007886105e0565b9650611015602089016105e0565b9550604088013594506060880135935060808801356004811061103757600080fd5b925060a088013567ffffffffffffffff81111561105357600080fd5b61105f8a828b016107cb565b92505060c0880135905092959891949750929550565b60008060006040848603121561108a57600080fd5b611093846105e0565b9250602084013567ffffffffffffffff8111156110af57600080fd5b6110bb86828701610b2e565b9497909650939450505050565b600080604083850312156110db57600080fd5b6110e4836105e0565b9150602083013567ffffffffffffffff8082111561110157600080fd5b908401906080828703121561111557600080fd5b61111d6106bf565b82356111288161079b565b81526020830135801515811461113d57600080fd5b602082015261114e604084016105e0565b604082015260608301358281111561116557600080fd5b611171888286016107cb565b6060830152508093505050509250929050565b6000815180845260005b818110156111aa5760208185018101518683018201520161118e565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b6020815273ffffffffffffffffffffffffffffffffffffffff825116602082015260208201511515604082015267ffffffffffffffff60408301511660608201526000606083015160808084015261124360a0840182611184565b949350505050565b600082825180855260208086019550808260051b84010181860160005b84811015611321577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0868403018952815160a073ffffffffffffffffffffffffffffffffffffffff82511685528582015181878701526112ca82870182611184565b915050604080830151868303828801526112e48382611184565b9250505060608083015181870152506080808301519250858203818701525061130d8183611184565b9a86019a9450505090830190600101611268565b5090979650505050505050565b6020815261137f60208201835180518252602081015167ffffffffffffffff808216602085015280604084015116604085015280606084015116606085015280608084015116608085015250505050565b600060208301516113a860c084018273ffffffffffffffffffffffffffffffffffffffff169052565b5060408301516101a08060e08501526113c56101c0850183611184565b915060608501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe06101008187860301818801526114038584611184565b94506080880151925081878603016101208801526114218584611184565b945060a0880151925061144d61014088018473ffffffffffffffffffffffffffffffffffffffff169052565b60c088015161016088015260e088015161018088015287015186850390910183870152905061147c838261124b565b9695505050505050565b67ffffffffffffffff8181168382160190808211156114ce577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b5092915050565b8183823760009101908152919050565b805160408084528151848201819052600092602091908201906060870190855b8181101561155e578351805173ffffffffffffffffffffffffffffffffffffffff1684528501517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16858401529284019291850191600101611505565b50508583015187820388850152805180835290840192506000918401905b808310156115cd578351805167ffffffffffffffff1683528501517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff168583015292840192600192909201919085019061157c565b50979650505050505050565b60006040808301604084528086518083526060925060608601915060608160051b8701016020808a0160005b84811015611691577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa08a8503018652815160a067ffffffffffffffff80835116875285830151828789015261165c83890182611184565b848d01518316898e01528b8501519092168b890152506080928301519290960191909152509482019490820190600101611605565b5050878203908801526116a481896114e5565b9998505050505050505050565b8481526000600485106116ed577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b846020830152608060408301526117076080830185611184565b905082606083015295945050505050565b600181811c9082168061172c57607f821691505b602082108103611765577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b601f8211156117b7576000816000526020600020601f850160051c810160208610156117945750805b601f850160051c820191505b818110156117b3578281556001016117a0565b5050505b505050565b815167ffffffffffffffff8111156117d6576117d66105fd565b6117ea816117e48454611718565b8461176b565b602080601f83116001811461183d57600084156118075750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b1785556117b3565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b8281101561188a5788860151825594840194600190910190840161186b565b50858210156118c657878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b0190555056fea164736f6c6343000818000a", } var CCIPReaderTesterABI = CCIPReaderTesterMetaData.ABI @@ -284,28 +284,6 @@ func (_CCIPReaderTester *CCIPReaderTesterCallerSession) GetInboundNonce(sourceCh return _CCIPReaderTester.Contract.GetInboundNonce(&_CCIPReaderTester.CallOpts, sourceChainSelector, sender) } -func (_CCIPReaderTester *CCIPReaderTesterCaller) GetLatestPriceSequenceNumber(opts *bind.CallOpts) (uint64, error) { - var out []interface{} - err := _CCIPReaderTester.contract.Call(opts, &out, "getLatestPriceSequenceNumber") - - if err != nil { - return *new(uint64), err - } - - out0 := *abi.ConvertType(out[0], new(uint64)).(*uint64) - - return out0, err - -} - -func (_CCIPReaderTester *CCIPReaderTesterSession) GetLatestPriceSequenceNumber() (uint64, error) { - return _CCIPReaderTester.Contract.GetLatestPriceSequenceNumber(&_CCIPReaderTester.CallOpts) -} - -func (_CCIPReaderTester *CCIPReaderTesterCallerSession) GetLatestPriceSequenceNumber() (uint64, error) { - return _CCIPReaderTester.Contract.GetLatestPriceSequenceNumber(&_CCIPReaderTester.CallOpts) -} - func (_CCIPReaderTester *CCIPReaderTesterCaller) GetSourceChainConfig(opts *bind.CallOpts, sourceChainSelector uint64) (OffRampSourceChainConfig, error) { var out []interface{} err := _CCIPReaderTester.contract.Call(opts, &out, "getSourceChainConfig", sourceChainSelector) @@ -388,18 +366,6 @@ func (_CCIPReaderTester *CCIPReaderTesterTransactorSession) SetInboundNonce(sour return _CCIPReaderTester.Contract.SetInboundNonce(&_CCIPReaderTester.TransactOpts, sourceChainSelector, testNonce, sender) } -func (_CCIPReaderTester *CCIPReaderTesterTransactor) SetLatestPriceSequenceNumber(opts *bind.TransactOpts, seqNr uint64) (*types.Transaction, error) { - return _CCIPReaderTester.contract.Transact(opts, "setLatestPriceSequenceNumber", seqNr) -} - -func (_CCIPReaderTester *CCIPReaderTesterSession) SetLatestPriceSequenceNumber(seqNr uint64) (*types.Transaction, error) { - return _CCIPReaderTester.Contract.SetLatestPriceSequenceNumber(&_CCIPReaderTester.TransactOpts, seqNr) -} - -func (_CCIPReaderTester *CCIPReaderTesterTransactorSession) SetLatestPriceSequenceNumber(seqNr uint64) (*types.Transaction, error) { - return _CCIPReaderTester.Contract.SetLatestPriceSequenceNumber(&_CCIPReaderTester.TransactOpts, seqNr) -} - func (_CCIPReaderTester *CCIPReaderTesterTransactor) SetSourceChainConfig(opts *bind.TransactOpts, sourceChainSelector uint64, sourceChainConfig OffRampSourceChainConfig) (*types.Transaction, error) { return _CCIPReaderTester.contract.Transact(opts, "setSourceChainConfig", sourceChainSelector, sourceChainConfig) } @@ -851,8 +817,6 @@ type CCIPReaderTesterInterface interface { GetInboundNonce(opts *bind.CallOpts, sourceChainSelector uint64, sender []byte) (uint64, error) - GetLatestPriceSequenceNumber(opts *bind.CallOpts) (uint64, error) - GetSourceChainConfig(opts *bind.CallOpts, sourceChainSelector uint64) (OffRampSourceChainConfig, error) EmitCCIPMessageSent(opts *bind.TransactOpts, destChainSelector uint64, message InternalEVM2AnyRampMessage) (*types.Transaction, error) @@ -865,8 +829,6 @@ type CCIPReaderTesterInterface interface { SetInboundNonce(opts *bind.TransactOpts, sourceChainSelector uint64, testNonce uint64, sender []byte) (*types.Transaction, error) - SetLatestPriceSequenceNumber(opts *bind.TransactOpts, seqNr uint64) (*types.Transaction, error) - SetSourceChainConfig(opts *bind.TransactOpts, sourceChainSelector uint64, sourceChainConfig OffRampSourceChainConfig) (*types.Transaction, error) FilterCCIPMessageSent(opts *bind.FilterOpts, destChainSelector []uint64, sequenceNumber []uint64) (*CCIPReaderTesterCCIPMessageSentIterator, error) diff --git a/core/gethwrappers/ccip/generated/ether_sender_receiver/ether_sender_receiver.go b/core/gethwrappers/ccip/generated/ether_sender_receiver/ether_sender_receiver.go index 8b0051d7f67..505e42e98ec 100644 --- a/core/gethwrappers/ccip/generated/ether_sender_receiver/ether_sender_receiver.go +++ b/core/gethwrappers/ccip/generated/ether_sender_receiver/ether_sender_receiver.go @@ -51,7 +51,7 @@ type ClientEVMTokenAmount struct { var EtherSenderReceiverMetaData = &bind.MetaData{ ABI: "[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"}],\"name\":\"InvalidRouter\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"gotToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"expectedToken\",\"type\":\"address\"}],\"name\":\"InvalidToken\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"gotAmounts\",\"type\":\"uint256\"}],\"name\":\"InvalidTokenAmounts\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"gotAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"msgValue\",\"type\":\"uint256\"}],\"name\":\"TokenAmountNotEqualToMsgValue\",\"type\":\"error\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"sender\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structClient.EVMTokenAmount[]\",\"name\":\"destTokenAmounts\",\"type\":\"tuple[]\"}],\"internalType\":\"structClient.Any2EVMMessage\",\"name\":\"message\",\"type\":\"tuple\"}],\"name\":\"ccipReceive\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destinationChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structClient.EVMTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"},{\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"extraArgs\",\"type\":\"bytes\"}],\"internalType\":\"structClient.EVM2AnyMessage\",\"name\":\"message\",\"type\":\"tuple\"}],\"name\":\"ccipSend\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destinationChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structClient.EVMTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"},{\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"extraArgs\",\"type\":\"bytes\"}],\"internalType\":\"structClient.EVM2AnyMessage\",\"name\":\"message\",\"type\":\"tuple\"}],\"name\":\"getFee\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"fee\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRouter\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"i_weth\",\"outputs\":[{\"internalType\":\"contractIWrappedNative\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}]", - Bin: "0x60c080604052346101245761002a9061161380380380916100208285610180565b83398101906101b9565b6001600160a01b03811690811561016a5760805260405163e861e90760e01b815290602082600481845afa908115610131576044602092600094859161013d575b506001600160a01b031660a081905260405163095ea7b360e01b8152600481019390935284196024840152919384928391905af18015610131576100f4575b60405161143a90816101d9823960805181818160bd01528181610185015281816106170152610d44015260a0518181816102cf0152818161058601528181610ccc01526112d40152f35b6020813d602011610129575b8161010d60209383610180565b8101031261012457518015150361012457386100aa565b600080fd5b3d9150610100565b6040513d6000823e3d90fd5b61015d9150843d8611610163575b6101558183610180565b8101906101b9565b3861006b565b503d61014b565b6335fdcccd60e21b600052600060045260246000fd5b601f909101601f19168101906001600160401b038211908210176101a357604052565b634e487b7160e01b600052604160045260246000fd5b9081602091031261012457516001600160a01b0381168103610124579056fe608080604052600436101561001d575b50361561001b57600080fd5b005b600090813560e01c90816301ffc9a71461070b57508063181f5a771461068857806320487ded146105aa5780634dbe7e921461053b57806385572ffb1461010057806396f4e9f9146100e45763b0f479a10361000f57346100e157807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126100e157602060405173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b80fd5b60206100f86100f2366108f2565b90610c23565b604051908152f35b50346100e15760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126100e15760043567ffffffffffffffff81116105375760a07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc82360301126105375773ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016330361050b576040516101b7816107cd565b81600401358152602482013567ffffffffffffffff81168103610468576020820152604482013567ffffffffffffffff8111610468576101fd9060043691850101610ac0565b6040820152606482013567ffffffffffffffff8111610468576102269060043691850101610ac0565b9160608201928352608481013567ffffffffffffffff81116105075760809160046102549236920101610b28565b9101918183525160208180518101031261046857602001519073ffffffffffffffffffffffffffffffffffffffff82168092036104685751600181036104dc575073ffffffffffffffffffffffffffffffffffffffff6102b48351610bcf565b5151169173ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001680930361048b5761030260209151610bcf565b51015190823b15610468576040517f2e1a7d4d000000000000000000000000000000000000000000000000000000008152826004820152848160248183885af180156104805761046c575b508380808085855af161035e61132d565b5015610368578380f35b823b1561046857836040517fd0e30db0000000000000000000000000000000000000000000000000000000008152818160048187895af180156104445761044f575b506040517fa9059cbb00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff929092166004830152602482019290925291602091839160449183915af1801561044457610415575b80808380f35b6104369060203d60201161043d575b61042e8183610818565b810190610c0b565b503861040f565b503d610424565b6040513d84823e3d90fd5b8161045c91949394610818565b610468579083386103aa565b8380fd5b8461047991959295610818565b923861034d565b6040513d87823e3d90fd5b838373ffffffffffffffffffffffffffffffffffffffff6104ae60449451610bcf565b5151167f0fc746a1000000000000000000000000000000000000000000000000000000008352600452602452fd5b7f83b9f0ae000000000000000000000000000000000000000000000000000000008452600452602483fd5b8480fd5b6024827fd7f7333400000000000000000000000000000000000000000000000000000000815233600452fd5b5080fd5b50346100e157807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126100e157602060405173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b50346100e1576105fe60206105c96105c1366108f2565b9190916111ae565b9060405193849283927f20487ded0000000000000000000000000000000000000000000000000000000084526004840161097c565b038173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000165afa908115610444578291610652575b602082604051908152f35b90506020813d602011610680575b8161066d60209383610818565b8101031261053757602091505138610647565b3d9150610660565b50346100e157807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126100e157506107076040516106c9604082610818565b601981527f457468657253656e646572526563656976657220312e352e30000000000000006020820152604051918291602083526020830190610893565b0390f35b9050346105375760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610537576004357fffffffff0000000000000000000000000000000000000000000000000000000081168091036107c957602092507f85572ffb00000000000000000000000000000000000000000000000000000000811490811561079f575b5015158152f35b7f01ffc9a70000000000000000000000000000000000000000000000000000000091501438610798565b8280fd5b60a0810190811067ffffffffffffffff8211176107e957604052565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff8211176107e957604052565b67ffffffffffffffff81116107e957601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b919082519283825260005b8481106108dd5750507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8460006020809697860101520116010190565b8060208092840101518282860101520161089e565b9060407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc8301126109775760043567ffffffffffffffff8116810361097757916024359067ffffffffffffffff8211610977577ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc8260a0920301126109775760040190565b600080fd5b9067ffffffffffffffff90939293168152604060208201526109e16109ad845160a0604085015260e0840190610893565b60208501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0848303016060850152610893565b906040840151917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc08282030160808301526020808451928381520193019060005b818110610a885750505060808473ffffffffffffffffffffffffffffffffffffffff6060610a85969701511660a084015201519060c07fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc082850301910152610893565b90565b8251805173ffffffffffffffffffffffffffffffffffffffff1686526020908101518187015260409095019490920191600101610a22565b81601f8201121561097757803590610ad782610859565b92610ae56040519485610818565b8284526020838301011161097757816000926020809301838601378301015290565b359073ffffffffffffffffffffffffffffffffffffffff8216820361097757565b81601f820112156109775780359067ffffffffffffffff82116107e95760405192610b5960208460051b0185610818565b82845260208085019360061b8301019181831161097757602001925b828410610b83575050505090565b6040848303126109775760405190604082019082821067ffffffffffffffff8311176107e9576040926020928452610bba87610b07565b81528287013583820152815201930192610b75565b805115610bdc5760200190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b90816020910312610977575180151581036109775790565b9060009060408101357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1823603018112156107c9578101803567ffffffffffffffff8111610468578060061b3603602083011361046857156111815760400135606082013573ffffffffffffffffffffffffffffffffffffffff81168091036104685761114b575b50610cb5906111ae565b73ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000166020610cfb6040840151610bcf565b510151813b156104685783600491604051928380927fd0e30db0000000000000000000000000000000000000000000000000000000008252865af180156111405761112c575b507f00000000000000000000000000000000000000000000000000000000000000009373ffffffffffffffffffffffffffffffffffffffff851691604051907f20487ded00000000000000000000000000000000000000000000000000000000825260208280610db588876004840161097c565b0381875afa9182156111215786926110ed575b50606085019673ffffffffffffffffffffffffffffffffffffffff8851169788610e805750505050610e319394509060209291476040518096819582947f96f4e9f90000000000000000000000000000000000000000000000000000000084526004840161097c565b03925af1918215610e745791610e45575090565b90506020813d602011610e6c575b81610e6060209383610818565b81010312610977575190565b3d9150610e53565b604051903d90823e3d90fd5b610f20604051602081019a7f23b872dd000000000000000000000000000000000000000000000000000000008c5233602483015230604483015286606483015260648252610ecf608483610818565b8a8060409d8e94610ee286519687610818565b602086527f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65646020870152519082855af1610f1a61132d565b9161135d565b80518061104c575b50505173ffffffffffffffffffffffffffffffffffffffff16918203610fa9575b505050916020918493610f8a9587518097819582947f96f4e9f90000000000000000000000000000000000000000000000000000000084526004840161097c565b03925af1928315610f9f575091610e45575090565b51903d90823e3d90fd5b87517f095ea7b300000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff91909116600482015260248101929092526020908290604490829089905af18015611042579160209391610f8a969593611025575b8193959650829450610f49565b61103b90853d871161043d5761042e8183610818565b5038611018565b86513d87823e3d90fd5b9060208061105e938301019101610c0b565b1561106a573880610f28565b608489517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152fd5b9091506020813d602011611119575b8161110960209383610818565b8101031261097757519038610dc8565b3d91506110fc565b6040513d88823e3d90fd5b8361113991949294610818565b9138610d41565b6040513d86823e3d90fd5b348114610cab577fba2f746700000000000000000000000000000000000000000000000000000000835260045234602452604482fd5b6024837f4e487b710000000000000000000000000000000000000000000000000000000081526032600452fd5b606060806040516111be816107cd565b828152826020820152826040820152600083820152015260a08136031261097757604051906111ec826107cd565b803567ffffffffffffffff81116109775761120a9036908301610ac0565b8252602081013567ffffffffffffffff81116109775761122d9036908301610ac0565b60208301908152604082013567ffffffffffffffff8111610977576112559036908401610b28565b916040840192835261126960608201610b07565b606085015260808101359067ffffffffffffffff82116109775761128f91369101610ac0565b608084015281515160018103611300575060405190336020830152602082526112b9604083610818565b526112fb73ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169151610bcf565b515290565b7f83b9f0ae0000000000000000000000000000000000000000000000000000000060005260045260246000fd5b3d15611358573d9061133e82610859565b9161134c6040519384610818565b82523d6000602084013e565b606090565b919290156113d85750815115611371575090565b3b1561137a5790565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152fd5b8251909150156113eb5750805190602001fd5b611429906040519182917f08c379a0000000000000000000000000000000000000000000000000000000008352602060048401526024830190610893565b0390fdfea164736f6c634300081a000a", + Bin: "0x60c06040523480156200001157600080fd5b5060405162001a9838038062001a98833981016040819052620000349162000169565b806001600160a01b03811662000064576040516335fdcccd60e21b81526000600482015260240160405180910390fd5b806001600160a01b03166080816001600160a01b03168152505050806001600160a01b031663e861e9076040518163ffffffff1660e01b8152600401602060405180830381865afa158015620000be573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000e4919062000169565b6001600160a01b0390811660a081905260405163095ea7b360e01b8152918316600483015260001960248301529063095ea7b3906044016020604051808303816000875af11580156200013b573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200016191906200019b565b5050620001bf565b6000602082840312156200017c57600080fd5b81516001600160a01b03811681146200019457600080fd5b9392505050565b600060208284031215620001ae57600080fd5b815180151581146200019457600080fd5b60805160a051611851620002476000396000818161014b015281816104030152818161059401528181610905015281816109cc01528181610a6401528181610b0201528181610bf70152610cbf0152600081816101d6015281816102df01528181610377015281816104ab0152818161060b015281816106ff01526107bf01526118516000f3fe6080604052600436106100745760003560e01c80634dbe7e921161004e5780634dbe7e921461013957806385572ffb1461019257806396f4e9f9146101b4578063b0f479a1146101c757600080fd5b806301ffc9a714610080578063181f5a77146100b557806320487ded1461010b57600080fd5b3661007b57005b600080fd5b34801561008c57600080fd5b506100a061009b3660046110e3565b6101fa565b60405190151581526020015b60405180910390f35b3480156100c157600080fd5b506100fe6040518060400160405280601981526020017f457468657253656e646572526563656976657220312e352e300000000000000081525081565b6040516100ac919061119a565b34801561011757600080fd5b5061012b6101263660046111e2565b610293565b6040519081526020016100ac565b34801561014557600080fd5b5061016d7f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100ac565b34801561019e57600080fd5b506101b26101ad366004611230565b61035f565b005b61012b6101c23660046111e2565b6103e9565b3480156101d357600080fd5b507f000000000000000000000000000000000000000000000000000000000000000061016d565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f85572ffb00000000000000000000000000000000000000000000000000000000148061028d57507fffffffff0000000000000000000000000000000000000000000000000000000082167f01ffc9a700000000000000000000000000000000000000000000000000000000145b92915050565b60008061029f83610844565b6040517f20487ded00000000000000000000000000000000000000000000000000000000815290915073ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016906320487ded906103169087908590600401611265565b602060405180830381865afa158015610333573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610357919061137a565b949350505050565b3373ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016146103d5576040517fd7f733340000000000000000000000000000000000000000000000000000000081523360048201526024015b60405180910390fd5b6103e66103e1826115c5565b610966565b50565b60006103f482610d38565b60006103ff83610844565b90507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663d0e30db0826040015160008151811061045457610454611672565b6020026020010151602001516040518263ffffffff1660e01b81526004016000604051808303818588803b15801561048b57600080fd5b505af115801561049f573d6000803e3d6000fd5b505050505060006104cd7f000000000000000000000000000000000000000000000000000000000000000090565b73ffffffffffffffffffffffffffffffffffffffff166320487ded86846040518363ffffffff1660e01b8152600401610507929190611265565b602060405180830381865afa158015610524573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610548919061137a565b606083015190915073ffffffffffffffffffffffffffffffffffffffff16156107825760608201516105929073ffffffffffffffffffffffffffffffffffffffff16333084610df0565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16826060015173ffffffffffffffffffffffffffffffffffffffff16146106c257606082015173ffffffffffffffffffffffffffffffffffffffff1663095ea7b37f00000000000000000000000000000000000000000000000000000000000000006040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b16815273ffffffffffffffffffffffffffffffffffffffff9091166004820152602481018490526044016020604051808303816000875af115801561069c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106c091906116a1565b505b6040517f96f4e9f900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016906396f4e9f9906107369088908690600401611265565b6020604051808303816000875af1158015610755573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610779919061137a565b9250505061028d565b6040517f96f4e9f900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016906396f4e9f99047906107f89089908790600401611265565b60206040518083038185885af1158015610816573d6000803e3d6000fd5b50505050506040513d601f19601f8201168201806040525081019061083b919061137a565b95945050505050565b61088c6040518060a00160405280606081526020016060815260200160608152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001606081525090565b6000610897836116c3565b90508060400151516001146108e1578060400151516040517f83b9f0ae0000000000000000000000000000000000000000000000000000000081526004016103cc91815260200190565b604080513360208201520160405160208183030381529060405281602001819052507f0000000000000000000000000000000000000000000000000000000000000000816040015160008151811061093b5761093b611672565b602090810291909101015173ffffffffffffffffffffffffffffffffffffffff909116905292915050565b60008160600151806020019051810190610980919061177f565b90508160800151516001146109ca578160800151516040517f83b9f0ae0000000000000000000000000000000000000000000000000000000081526004016103cc91815260200190565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168260800151600081518110610a1857610a18611672565b60200260200101516000015173ffffffffffffffffffffffffffffffffffffffff1614610ad9578160800151600081518110610a5657610a56611672565b6020026020010151600001517f00000000000000000000000000000000000000000000000000000000000000006040517f0fc746a10000000000000000000000000000000000000000000000000000000081526004016103cc92919073ffffffffffffffffffffffffffffffffffffffff92831681529116602082015260400190565b60008260800151600081518110610af257610af2611672565b60200260200101516020015190507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16632e1a7d4d826040518263ffffffff1660e01b8152600401610b5b91815260200190565b600060405180830381600087803b158015610b7557600080fd5b505af1158015610b89573d6000803e3d6000fd5b5050505060008273ffffffffffffffffffffffffffffffffffffffff168260405160006040518083038185875af1925050503d8060008114610be7576040519150601f19603f3d011682016040523d82523d6000602084013e610bec565b606091505b5050905080610d32577f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663d0e30db0836040518263ffffffff1660e01b81526004016000604051808303818588803b158015610c5d57600080fd5b505af1158015610c71573d6000803e3d6000fd5b50506040517fa9059cbb00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8781166004830152602482018790527f000000000000000000000000000000000000000000000000000000000000000016935063a9059cbb925060440190506020604051808303816000875af1158015610d0c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d3091906116a1565b505b50505050565b6000610d47604083018361179c565b6000818110610d5857610d58611672565b905060400201602001359050600073ffffffffffffffffffffffffffffffffffffffff16826060016020810190610d8f919061180b565b73ffffffffffffffffffffffffffffffffffffffff1614610dec57803414610dec576040517fba2f7467000000000000000000000000000000000000000000000000000000008152600481018290523460248201526044016103cc565b5050565b6040805173ffffffffffffffffffffffffffffffffffffffff8581166024830152848116604483015260648083018590528351808403909101815260849092018352602080830180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f23b872dd0000000000000000000000000000000000000000000000000000000017905283518085019094528084527f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c656490840152610d3292879291600091610ec3918516908490610f72565b805190915015610f6d5780806020019051810190610ee191906116a1565b610f6d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f7420737563636565640000000000000000000000000000000000000000000060648201526084016103cc565b505050565b60606103578484600085856000808673ffffffffffffffffffffffffffffffffffffffff168587604051610fa69190611828565b60006040518083038185875af1925050503d8060008114610fe3576040519150601f19603f3d011682016040523d82523d6000602084013e610fe8565b606091505b5091509150610ff987838387611004565b979650505050505050565b6060831561109a5782516000036110935773ffffffffffffffffffffffffffffffffffffffff85163b611093576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016103cc565b5081610357565b61035783838151156110af5781518083602001fd5b806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016103cc919061119a565b6000602082840312156110f557600080fd5b81357fffffffff000000000000000000000000000000000000000000000000000000008116811461112557600080fd5b9392505050565b60005b8381101561114757818101518382015260200161112f565b50506000910152565b6000815180845261116881602086016020860161112c565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006111256020830184611150565b803567ffffffffffffffff811681146111c557600080fd5b919050565b600060a082840312156111dc57600080fd5b50919050565b600080604083850312156111f557600080fd5b6111fe836111ad565b9150602083013567ffffffffffffffff81111561121a57600080fd5b611226858286016111ca565b9150509250929050565b60006020828403121561124257600080fd5b813567ffffffffffffffff81111561125957600080fd5b610357848285016111ca565b6000604067ffffffffffffffff851683526020604081850152845160a0604086015261129460e0860182611150565b9050818601517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0808784030160608801526112cf8383611150565b6040890151888203830160808a01528051808352908601945060009350908501905b80841015611330578451805173ffffffffffffffffffffffffffffffffffffffff168352860151868301529385019360019390930192908601906112f1565b50606089015173ffffffffffffffffffffffffffffffffffffffff1660a08901526080890151888203830160c08a0152955061136c8187611150565b9a9950505050505050505050565b60006020828403121561138c57600080fd5b5051919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff811182821017156113e5576113e5611393565b60405290565b60405160a0810167ffffffffffffffff811182821017156113e5576113e5611393565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff8111828210171561145557611455611393565b604052919050565b600082601f83011261146e57600080fd5b813567ffffffffffffffff81111561148857611488611393565b6114b960207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8401160161140e565b8181528460208386010111156114ce57600080fd5b816020850160208301376000918101602001919091529392505050565b73ffffffffffffffffffffffffffffffffffffffff811681146103e657600080fd5b80356111c5816114eb565b600082601f83011261152957600080fd5b8135602067ffffffffffffffff82111561154557611545611393565b611553818360051b0161140e565b82815260069290921b8401810191818101908684111561157257600080fd5b8286015b848110156115ba576040818903121561158f5760008081fd5b6115976113c2565b81356115a2816114eb565b81528185013585820152835291830191604001611576565b509695505050505050565b600060a082360312156115d757600080fd5b6115df6113eb565b823581526115ef602084016111ad565b6020820152604083013567ffffffffffffffff8082111561160f57600080fd5b61161b3683870161145d565b6040840152606085013591508082111561163457600080fd5b6116403683870161145d565b6060840152608085013591508082111561165957600080fd5b5061166636828601611518565b60808301525092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6000602082840312156116b357600080fd5b8151801515811461112557600080fd5b600060a082360312156116d557600080fd5b6116dd6113eb565b823567ffffffffffffffff808211156116f557600080fd5b6117013683870161145d565b8352602085013591508082111561171757600080fd5b6117233683870161145d565b6020840152604085013591508082111561173c57600080fd5b61174836838701611518565b60408401526117596060860161150d565b6060840152608085013591508082111561177257600080fd5b506116663682860161145d565b60006020828403121561179157600080fd5b8151611125816114eb565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18436030181126117d157600080fd5b83018035915067ffffffffffffffff8211156117ec57600080fd5b6020019150600681901b360382131561180457600080fd5b9250929050565b60006020828403121561181d57600080fd5b8135611125816114eb565b6000825161183a81846020870161112c565b919091019291505056fea164736f6c6343000818000a", } var EtherSenderReceiverABI = EtherSenderReceiverMetaData.ABI diff --git a/core/gethwrappers/ccip/generated/fee_quoter/fee_quoter.go b/core/gethwrappers/ccip/generated/fee_quoter/fee_quoter.go index bda09c5c026..1d28c85f997 100644 --- a/core/gethwrappers/ccip/generated/fee_quoter/fee_quoter.go +++ b/core/gethwrappers/ccip/generated/fee_quoter/fee_quoter.go @@ -156,8 +156,8 @@ type KeystoneFeedsPermissionHandlerPermission struct { } var FeeQuoterMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[{\"components\":[{\"internalType\":\"uint96\",\"name\":\"maxFeeJuelsPerMsg\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"linkToken\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"tokenPriceStalenessThreshold\",\"type\":\"uint32\"}],\"internalType\":\"structFeeQuoter.StaticConfig\",\"name\":\"staticConfig\",\"type\":\"tuple\"},{\"internalType\":\"address[]\",\"name\":\"priceUpdaters\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"feeTokens\",\"type\":\"address[]\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"sourceToken\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"dataFeedAddress\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"tokenDecimals\",\"type\":\"uint8\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"}],\"internalType\":\"structFeeQuoter.TokenPriceFeedConfig\",\"name\":\"feedConfig\",\"type\":\"tuple\"}],\"internalType\":\"structFeeQuoter.TokenPriceFeedUpdate[]\",\"name\":\"tokenPriceFeeds\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"minFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"deciBps\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destBytesOverhead\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"}],\"internalType\":\"structFeeQuoter.TokenTransferFeeConfig\",\"name\":\"tokenTransferFeeConfig\",\"type\":\"tuple\"}],\"internalType\":\"structFeeQuoter.TokenTransferFeeConfigSingleTokenArgs[]\",\"name\":\"tokenTransferFeeConfigs\",\"type\":\"tuple[]\"}],\"internalType\":\"structFeeQuoter.TokenTransferFeeConfigArgs[]\",\"name\":\"tokenTransferFeeConfigArgs\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"premiumMultiplierWeiPerEth\",\"type\":\"uint64\"}],\"internalType\":\"structFeeQuoter.PremiumMultiplierWeiPerEthArgs[]\",\"name\":\"premiumMultiplierWeiPerEthArgs\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint16\",\"name\":\"maxNumberOfTokensPerMsg\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"maxDataBytes\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPerMsgGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerPayloadByte\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destDataAvailabilityOverheadGas\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerDataAvailabilityByte\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"destDataAvailabilityMultiplierBps\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"defaultTokenFeeUSDCents\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"defaultTokenDestGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"defaultTxGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint64\",\"name\":\"gasMultiplierWeiPerEth\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"networkFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"gasPriceStalenessThreshold\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"enforceOutOfOrder\",\"type\":\"bool\"},{\"internalType\":\"bytes4\",\"name\":\"chainFamilySelector\",\"type\":\"bytes4\"}],\"internalType\":\"structFeeQuoter.DestChainConfig\",\"name\":\"destChainConfig\",\"type\":\"tuple\"}],\"internalType\":\"structFeeQuoter.DestChainConfigArgs[]\",\"name\":\"destChainConfigArgs\",\"type\":\"tuple[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"CannotTransferToSelf\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"DataFeedValueOutOfUint224Range\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"DestinationChainNotEnabled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ExtraArgOutOfOrderExecutionMustBeTrue\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"FeeTokenNotSupported\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"destBytesOverhead\",\"type\":\"uint32\"}],\"name\":\"InvalidDestBytesOverhead\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"InvalidDestChainConfig\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"encodedAddress\",\"type\":\"bytes\"}],\"name\":\"InvalidEVMAddress\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidExtraArgsTag\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"minFeeUSDCents\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxFeeUSDCents\",\"type\":\"uint256\"}],\"name\":\"InvalidFeeRange\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidStaticConfig\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"msgFeeJuels\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxFeeJuelsPerMsg\",\"type\":\"uint256\"}],\"name\":\"MessageFeeTooHigh\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MessageGasLimitTooHigh\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"maxSize\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"actualSize\",\"type\":\"uint256\"}],\"name\":\"MessageTooLarge\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MustBeProposedOwner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByOwner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OwnerCannotBeZero\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"forwarder\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"workflowOwner\",\"type\":\"address\"},{\"internalType\":\"bytes10\",\"name\":\"workflowName\",\"type\":\"bytes10\"},{\"internalType\":\"bytes2\",\"name\":\"reportName\",\"type\":\"bytes2\"}],\"name\":\"ReportForwarderUnauthorized\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"SourceTokenDataTooLarge\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint256\",\"name\":\"threshold\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"timePassed\",\"type\":\"uint256\"}],\"name\":\"StaleGasPrice\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"TokenNotSupported\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"UnauthorizedCaller\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"numberOfTokens\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxNumberOfTokensPerMsg\",\"type\":\"uint256\"}],\"name\":\"UnsupportedNumberOfTokens\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"AuthorizedCallerAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"AuthorizedCallerRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint16\",\"name\":\"maxNumberOfTokensPerMsg\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"maxDataBytes\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPerMsgGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerPayloadByte\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destDataAvailabilityOverheadGas\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerDataAvailabilityByte\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"destDataAvailabilityMultiplierBps\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"defaultTokenFeeUSDCents\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"defaultTokenDestGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"defaultTxGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint64\",\"name\":\"gasMultiplierWeiPerEth\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"networkFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"gasPriceStalenessThreshold\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"enforceOutOfOrder\",\"type\":\"bool\"},{\"internalType\":\"bytes4\",\"name\":\"chainFamilySelector\",\"type\":\"bytes4\"}],\"indexed\":false,\"internalType\":\"structFeeQuoter.DestChainConfig\",\"name\":\"destChainConfig\",\"type\":\"tuple\"}],\"name\":\"DestChainAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint16\",\"name\":\"maxNumberOfTokensPerMsg\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"maxDataBytes\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPerMsgGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerPayloadByte\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destDataAvailabilityOverheadGas\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerDataAvailabilityByte\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"destDataAvailabilityMultiplierBps\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"defaultTokenFeeUSDCents\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"defaultTokenDestGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"defaultTxGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint64\",\"name\":\"gasMultiplierWeiPerEth\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"networkFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"gasPriceStalenessThreshold\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"enforceOutOfOrder\",\"type\":\"bool\"},{\"internalType\":\"bytes4\",\"name\":\"chainFamilySelector\",\"type\":\"bytes4\"}],\"indexed\":false,\"internalType\":\"structFeeQuoter.DestChainConfig\",\"name\":\"destChainConfig\",\"type\":\"tuple\"}],\"name\":\"DestChainConfigUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"}],\"name\":\"FeeTokenAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"}],\"name\":\"FeeTokenRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"premiumMultiplierWeiPerEth\",\"type\":\"uint64\"}],\"name\":\"PremiumMultiplierWeiPerEthUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"dataFeedAddress\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"tokenDecimals\",\"type\":\"uint8\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"}],\"indexed\":false,\"internalType\":\"structFeeQuoter.TokenPriceFeedConfig\",\"name\":\"priceFeedConfig\",\"type\":\"tuple\"}],\"name\":\"PriceFeedPerTokenUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"reportId\",\"type\":\"bytes32\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"forwarder\",\"type\":\"address\"},{\"internalType\":\"bytes10\",\"name\":\"workflowName\",\"type\":\"bytes10\"},{\"internalType\":\"bytes2\",\"name\":\"reportName\",\"type\":\"bytes2\"},{\"internalType\":\"address\",\"name\":\"workflowOwner\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"isAllowed\",\"type\":\"bool\"}],\"indexed\":false,\"internalType\":\"structKeystoneFeedsPermissionHandler.Permission\",\"name\":\"permission\",\"type\":\"tuple\"}],\"name\":\"ReportPermissionSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"TokenTransferFeeConfigDeleted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"minFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"deciBps\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destBytesOverhead\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"}],\"indexed\":false,\"internalType\":\"structFeeQuoter.TokenTransferFeeConfig\",\"name\":\"tokenTransferFeeConfig\",\"type\":\"tuple\"}],\"name\":\"TokenTransferFeeConfigUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"name\":\"UsdPerTokenUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChain\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"name\":\"UsdPerUnitGasUpdated\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"FEE_BASE_DECIMALS\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"KEYSTONE_PRICE_DECIMALS\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address[]\",\"name\":\"addedCallers\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"removedCallers\",\"type\":\"address[]\"}],\"internalType\":\"structAuthorizedCallers.AuthorizedCallerArgs\",\"name\":\"authorizedCallerArgs\",\"type\":\"tuple\"}],\"name\":\"applyAuthorizedCallerUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint16\",\"name\":\"maxNumberOfTokensPerMsg\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"maxDataBytes\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPerMsgGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerPayloadByte\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destDataAvailabilityOverheadGas\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerDataAvailabilityByte\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"destDataAvailabilityMultiplierBps\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"defaultTokenFeeUSDCents\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"defaultTokenDestGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"defaultTxGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint64\",\"name\":\"gasMultiplierWeiPerEth\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"networkFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"gasPriceStalenessThreshold\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"enforceOutOfOrder\",\"type\":\"bool\"},{\"internalType\":\"bytes4\",\"name\":\"chainFamilySelector\",\"type\":\"bytes4\"}],\"internalType\":\"structFeeQuoter.DestChainConfig\",\"name\":\"destChainConfig\",\"type\":\"tuple\"}],\"internalType\":\"structFeeQuoter.DestChainConfigArgs[]\",\"name\":\"destChainConfigArgs\",\"type\":\"tuple[]\"}],\"name\":\"applyDestChainConfigUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"feeTokensToRemove\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"feeTokensToAdd\",\"type\":\"address[]\"}],\"name\":\"applyFeeTokensUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"premiumMultiplierWeiPerEth\",\"type\":\"uint64\"}],\"internalType\":\"structFeeQuoter.PremiumMultiplierWeiPerEthArgs[]\",\"name\":\"premiumMultiplierWeiPerEthArgs\",\"type\":\"tuple[]\"}],\"name\":\"applyPremiumMultiplierWeiPerEthUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"minFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"deciBps\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destBytesOverhead\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"}],\"internalType\":\"structFeeQuoter.TokenTransferFeeConfig\",\"name\":\"tokenTransferFeeConfig\",\"type\":\"tuple\"}],\"internalType\":\"structFeeQuoter.TokenTransferFeeConfigSingleTokenArgs[]\",\"name\":\"tokenTransferFeeConfigs\",\"type\":\"tuple[]\"}],\"internalType\":\"structFeeQuoter.TokenTransferFeeConfigArgs[]\",\"name\":\"tokenTransferFeeConfigArgs\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"internalType\":\"structFeeQuoter.TokenTransferFeeConfigRemoveArgs[]\",\"name\":\"tokensToUseDefaultFeeConfigs\",\"type\":\"tuple[]\"}],\"name\":\"applyTokenTransferFeeConfigUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"fromToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"fromTokenAmount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"toToken\",\"type\":\"address\"}],\"name\":\"convertTokenAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAllAuthorizedCallers\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"getDestChainConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint16\",\"name\":\"maxNumberOfTokensPerMsg\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"maxDataBytes\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPerMsgGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerPayloadByte\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destDataAvailabilityOverheadGas\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerDataAvailabilityByte\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"destDataAvailabilityMultiplierBps\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"defaultTokenFeeUSDCents\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"defaultTokenDestGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"defaultTxGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint64\",\"name\":\"gasMultiplierWeiPerEth\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"networkFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"gasPriceStalenessThreshold\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"enforceOutOfOrder\",\"type\":\"bool\"},{\"internalType\":\"bytes4\",\"name\":\"chainFamilySelector\",\"type\":\"bytes4\"}],\"internalType\":\"structFeeQuoter.DestChainConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"getDestinationChainGasPrice\",\"outputs\":[{\"components\":[{\"internalType\":\"uint224\",\"name\":\"value\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"timestamp\",\"type\":\"uint32\"}],\"internalType\":\"structInternal.TimestampedPackedUint224\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getFeeTokens\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"getPremiumMultiplierWeiPerEth\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"premiumMultiplierWeiPerEth\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getStaticConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"uint96\",\"name\":\"maxFeeJuelsPerMsg\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"linkToken\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"tokenPriceStalenessThreshold\",\"type\":\"uint32\"}],\"internalType\":\"structFeeQuoter.StaticConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"getTokenAndGasPrices\",\"outputs\":[{\"internalType\":\"uint224\",\"name\":\"tokenPrice\",\"type\":\"uint224\"},{\"internalType\":\"uint224\",\"name\":\"gasPriceValue\",\"type\":\"uint224\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"getTokenPrice\",\"outputs\":[{\"components\":[{\"internalType\":\"uint224\",\"name\":\"value\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"timestamp\",\"type\":\"uint32\"}],\"internalType\":\"structInternal.TimestampedPackedUint224\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"getTokenPriceFeedConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"dataFeedAddress\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"tokenDecimals\",\"type\":\"uint8\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"}],\"internalType\":\"structFeeQuoter.TokenPriceFeedConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"tokens\",\"type\":\"address[]\"}],\"name\":\"getTokenPrices\",\"outputs\":[{\"components\":[{\"internalType\":\"uint224\",\"name\":\"value\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"timestamp\",\"type\":\"uint32\"}],\"internalType\":\"structInternal.TimestampedPackedUint224[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"getTokenTransferFeeConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"minFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"deciBps\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destBytesOverhead\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"}],\"internalType\":\"structFeeQuoter.TokenTransferFeeConfig\",\"name\":\"tokenTransferFeeConfig\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structClient.EVMTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"},{\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"extraArgs\",\"type\":\"bytes\"}],\"internalType\":\"structClient.EVM2AnyMessage\",\"name\":\"message\",\"type\":\"tuple\"}],\"name\":\"getValidatedFee\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"feeTokenAmount\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"getValidatedTokenPrice\",\"outputs\":[{\"internalType\":\"uint224\",\"name\":\"\",\"type\":\"uint224\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"metadata\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"report\",\"type\":\"bytes\"}],\"name\":\"onReport\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"feeTokenAmount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"extraArgs\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"sourcePoolAddress\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"destExecData\",\"type\":\"bytes\"}],\"internalType\":\"structInternal.EVM2AnyTokenTransfer[]\",\"name\":\"onRampTokenTransfers\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structClient.EVMTokenAmount[]\",\"name\":\"sourceTokenAmounts\",\"type\":\"tuple[]\"}],\"name\":\"processMessageArgs\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"msgFeeJuels\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"isOutOfOrderExecution\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"convertedExtraArgs\",\"type\":\"bytes\"},{\"internalType\":\"bytes[]\",\"name\":\"destExecDataPerToken\",\"type\":\"bytes[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"forwarder\",\"type\":\"address\"},{\"internalType\":\"bytes10\",\"name\":\"workflowName\",\"type\":\"bytes10\"},{\"internalType\":\"bytes2\",\"name\":\"reportName\",\"type\":\"bytes2\"},{\"internalType\":\"address\",\"name\":\"workflowOwner\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"isAllowed\",\"type\":\"bool\"}],\"internalType\":\"structKeystoneFeedsPermissionHandler.Permission[]\",\"name\":\"permissions\",\"type\":\"tuple[]\"}],\"name\":\"setReportPermissions\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sourceToken\",\"type\":\"address\"},{\"internalType\":\"uint224\",\"name\":\"usdPerToken\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.TokenPriceUpdate[]\",\"name\":\"tokenPriceUpdates\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint224\",\"name\":\"usdPerUnitGas\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.GasPriceUpdate[]\",\"name\":\"gasPriceUpdates\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.PriceUpdates\",\"name\":\"priceUpdates\",\"type\":\"tuple\"}],\"name\":\"updatePrices\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sourceToken\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"dataFeedAddress\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"tokenDecimals\",\"type\":\"uint8\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"}],\"internalType\":\"structFeeQuoter.TokenPriceFeedConfig\",\"name\":\"feedConfig\",\"type\":\"tuple\"}],\"internalType\":\"structFeeQuoter.TokenPriceFeedUpdate[]\",\"name\":\"tokenPriceFeedUpdates\",\"type\":\"tuple[]\"}],\"name\":\"updateTokenPriceFeeds\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", - Bin: "0x60e060405234610fed57617375803803806100198161125f565b9283398101908082036101208112610fed57606013610fed5761003a611221565b81516001600160601b0381168103610fed57815261005a60208301611284565b906020810191825261006e60408401611298565b6040820190815260608401516001600160401b038111610fed57856100949186016112c0565b60808501519094906001600160401b038111610fed57866100b69183016112c0565b60a08201519096906001600160401b038111610fed5782019181601f84011215610fed5782516100ed6100e8826112a9565b61125f565b9360208086848152019260071b82010190848211610fed57602001915b8183106111a65750505060c08101516001600160401b038111610fed5781019782601f8a011215610fed578851986101446100e88b6112a9565b996020808c838152019160051b83010191858311610fed5760208101915b838310611044575050505060e08201516001600160401b038111610fed5782019183601f84011215610fed57825161019c6100e8826112a9565b9360208086848152019260061b82010190868211610fed57602001915b81831061100857505050610100810151906001600160401b038211610fed570183601f82011215610fed578051906101f36100e8836112a9565b946020610240818886815201940283010191818311610fed57602001925b828410610e5157505050503315610e4057600180546001600160a01b031916331790556020986102408a61125f565b97600089526000368137610252611240565b998a52888b8b015260005b89518110156102c4576001906001600160a01b0361027b828d61134b565b51168d61028782611537565b610294575b50500161025d565b7fc3803387881faad271c47728894e3e36fac830ffc8602ca6fc07733cbda7758091604051908152a1388d61028c565b508a985089519660005b885181101561033f576001600160a01b036102e9828b61134b565b511690811561032e577feb1b9b92e50b7f88f9ff25d56765095ac6e91540eee214906f4036a908ffbdef8c836103206001956114bf565b50604051908152a1016102ce565b6342bcdf7f60e11b60005260046000fd5b5089959697508860018060a01b03835116158015610e2e575b8015610e1f575b610e0e5791516001600160a01b031660a05290516001600160601b03166080525163ffffffff1660c0526103928461125f565b9360008552600036813760005b855181101561040e576001906103c76001600160a01b036103c0838a61134b565b51166113cc565b6103d2575b0161039f565b818060a01b036103e2828961134b565b51167f1795838dc8ab2ffc5f431a1729a6afa0b587f982f7b2be0b9d7187a1ef547f91600080a26103cc565b508694508560005b84518110156104855760019061043e6001600160a01b03610437838961134b565b51166114fe565b610449575b01610416565b818060a01b03610459828861134b565b51167fdf1b1bd32a69711488d71554706bb130b1fc63a5fa1a2cd85e8440f84065ba23600080a2610443565b508593508460005b855181101561054757806104a36001928861134b565b517fe6a7a17d710bf0b2cd05e5397dc6f97a5da4ee79e31e234bf5f965ee2bd9a5bf606087858060a01b03845116930151836000526007895260406000209060ff878060a01b038251169283898060a01b03198254161781558b8301908151604082549501948460a81b8651151560a81b16918560a01b9060a01b169061ffff60a01b19161717905560405193845251168a8301525115156040820152a20161048d565b50828460005b8451811015610ab957610560818661134b565b51836001600160401b03610574848961134b565b5151169101519080158015610aa6575b8015610a86575b8015610a68575b610a54579081600193926000526009865263ffffffff60e01b846040600020015460381b161560001461090957807f525e3d4e0c31cef19cf9426af8d2c0ddd2d576359ca26bed92aac5fadda4626560405180610702868291909161020061022082019380511515835261ffff602082015116602084015263ffffffff604082015116604084015263ffffffff606082015116606084015263ffffffff608082015116608084015261ffff60a08201511660a084015263ffffffff60c08201511660c084015261ffff60e08201511660e084015261ffff6101008201511661010084015261ffff6101208201511661012084015263ffffffff6101408201511661014084015263ffffffff6101608201511661016084015260018060401b036101808201511661018084015263ffffffff6101a0820151166101a084015263ffffffff6101c0820151166101c08401526101e081015115156101e08401528163ffffffff60e01b91015116910152565b0390a25b600052600985528260406000208251151581549062ffff008986015160081b169166ffffffff000000604087015160181b166affffffff00000000000000606088015160381b16906effffffff0000000000000000000000608089015160581b169361ffff60781b60a08a015160781b169163ffffffff60881b60c08b015160881b169061ffff60a81b60e08c015160a81b169361ffff60b81b6101008d015160b81b16968c61012061ffff60c81b91015160c81b16988d61014063ffffffff60d81b91015160d81b169a63ffffffff60d81b199861ffff60c81b199761ffff60b81b199661ffff60a81b199563ffffffff60881b199461ffff60781b19936effffffff0000000000000000000000199260ff6affffffff000000000000001992169066ffffffffffffff1916171617161716171617161716171617161717178155019063ffffffff80610160830151161663ffffffff198354161782556101808101519082546fffffffff0000000000000000000000006101a083015160601b169063ffffffff60801b6101c084015160801b16916101e0840151151560a01b9363ffffffff60a81b9061020063ffffffff60a81b91015160381c16169463ffffffff60a81b199260ff60a01b19916401000000008b60601b03908d1b16906401000000008b60a01b03191617161716179060ff60a01b16171790550161054d565b807f283b699f411baff8f1c29fe49f32a828c8151596244b8e7e4c164edd6569a83560405180610a4c868291909161020061022082019380511515835261ffff602082015116602084015263ffffffff604082015116604084015263ffffffff606082015116606084015263ffffffff608082015116608084015261ffff60a08201511660a084015263ffffffff60c08201511660c084015261ffff60e08201511660e084015261ffff6101008201511661010084015261ffff6101208201511661012084015263ffffffff6101408201511661014084015263ffffffff6101608201511661016084015260018060401b036101808201511661018084015263ffffffff6101a0820151166101a084015263ffffffff6101c0820151166101c08401526101e081015115156101e08401528163ffffffff60e01b91015116910152565b0390a2610706565b63c35aa79d60e01b60005260045260246000fd5b5063ffffffff6101608301511663ffffffff60608401511610610592565b506102008201516001600160e01b031916630a04b54b60e21b141561058b565b5063ffffffff6101608301511615610584565b508260005b8151811015610b3e576001906001600160a01b03610adc828561134b565b5151167fbb77da6f7210cdd16904228a9360133d1d7dfff99b1bc75f128da5b53e28f97d86848060401b0381610b12868961134b565b510151168360005260088252604060002081878060401b0319825416179055604051908152a201610abe565b50506001610b4b8361125f565b9160008352600091610e09575b81925b8151841015610d4757610b6e848361134b565b5180516001600160401b0316929086019190845b8784518051831015610d365782610b989161134b565b51015184516001600160a01b0390610bb190849061134b565b5151169063ffffffff8151168a82019063ffffffff8251169081811015610d21575050608082019063ffffffff8251168c8110610d0a57507f94967ae9ea7729ad4f54021c1981765d2b1d954f7c92fbec340aa0a54f46b8b560c08d8098979563ffffffff600198968f8f9761ffff6040838b879552600a89528181208f808f9160a01b0316825289522091838751169784891685198554161784558482519285549560408b019469ffff0000000000000000865160401b169b60608101986dffffffff000000000000000000008a5160501b169060a08d8860701b905160701b1693019e8f60ff60901b9051151560901b169460ff60901b199267ffffffff000000008a60701b19928c1b169060016401000000009060701b0319161716171617171790556040519a8b5251169089015251166040870152511660608501525116608083015251151560a0820152a301909150610b82565b6312766e0160e11b8b52600485905260245260448afd5b6305a7b3d160e11b8b52600452602452604489fd5b505050925093600191500192610b5b565b905083825b8251811015610dca576001906001600160401b03610d6a828661134b565b515116828060a01b0384610d7e848861134b565b5101511690808752600a855260408720848060a01b038316885285528660408120557f4de5b1bcbca6018c11303a2c3f4a4b4f22a1c741d8c4ba430d246ac06c5ddf8b8780a301610d4c565b604051615da990816115cc82396080518181816104d4015261312d015260a05181818161051701526130c4015260c05181818161053e0152613ddc0152f35b610b58565b63d794ef9560e01b60005260046000fd5b5063ffffffff8251161561035f565b5080516001600160601b031615610358565b639b15e16f60e01b60005260046000fd5b8382036102408112610fed57610220610e68611240565b91610e7287611328565b8352601f190112610fed576040519161022083016001600160401b03811184821017610ff257604052610ea76020870161131b565b8352610eb56040870161133c565b6020840152610ec660608701611298565b6040840152610ed760808701611298565b6060840152610ee860a08701611298565b6080840152610ef960c0870161133c565b60a0840152610f0a60e08701611298565b60c0840152610f1c610100870161133c565b60e0840152610f2e610120870161133c565b610100840152610f41610140870161133c565b610120840152610f546101608701611298565b610140840152610f676101808701611298565b610160840152610f7a6101a08701611328565b610180840152610f8d6101c08701611298565b6101a0840152610fa06101e08701611298565b6101c0840152610fb3610200870161131b565b6101e0840152610220860151916001600160e01b031983168303610fed578360209361020061024096015283820152815201930192610211565b600080fd5b634e487b7160e01b600052604160045260246000fd5b604083880312610fed57602060409161101f611240565b61102886611284565b8152611035838701611328565b838201528152019201916101b9565b82516001600160401b038111610fed5782016040818903601f190112610fed5761106c611240565b9061107960208201611328565b825260408101516001600160401b038111610fed57602091010188601f82011215610fed5780516110ac6100e8826112a9565b91602060e08185858152019302820101908b8211610fed57602001915b8183106110e85750505091816020938480940152815201920191610162565b828c0360e08112610fed5760c06110fd611240565b9161110786611284565b8352601f190112610fed576040519160c08301916001600160401b03831184841017610ff25760e093602093604052611141848801611298565b815261114f60408801611298565b8482015261115f6060880161133c565b604082015261117060808801611298565b606082015261118160a08801611298565b608082015261119260c0880161131b565b60a0820152838201528152019201916110c9565b82850360808112610fed5760606111bb611240565b916111c586611284565b8352601f190112610fed576111d8611221565b916111e560208601611284565b835260408501519160ff83168303610fed578360209384608096015261120d6060880161131b565b60408201528382015281520192019161010a565b60405190606082016001600160401b03811183821017610ff257604052565b60408051919082016001600160401b03811183821017610ff257604052565b6040519190601f01601f191682016001600160401b03811183821017610ff257604052565b51906001600160a01b0382168203610fed57565b519063ffffffff82168203610fed57565b6001600160401b038111610ff25760051b60200190565b9080601f83011215610fed5781516112da6100e8826112a9565b9260208085848152019260051b820101928311610fed57602001905b8282106113035750505090565b6020809161131084611284565b8152019101906112f6565b51908115158203610fed57565b51906001600160401b0382168203610fed57565b519061ffff82168203610fed57565b805182101561135f5760209160051b010190565b634e487b7160e01b600052603260045260246000fd5b805482101561135f5760005260206000200190600090565b805480156113b65760001901906113a48282611375565b8154906000199060031b1b1916905555565b634e487b7160e01b600052603160045260246000fd5b6000818152600c6020526040902054801561148d57600019810181811161147757600b5460001981019190821161147757818103611426575b505050611412600b61138d565b600052600c60205260006040812055600190565b61145f61143761144893600b611375565b90549060031b1c928392600b611375565b819391549060031b91821b91600019901b19161790565b9055600052600c602052604060002055388080611405565b634e487b7160e01b600052601160045260246000fd5b5050600090565b80549068010000000000000000821015610ff257816114489160016114bb94018155611375565b9055565b806000526003602052604060002054156000146114f8576114e1816002611494565b600254906000526003602052604060002055600190565b50600090565b80600052600c602052604060002054156000146114f85761152081600b611494565b600b5490600052600c602052604060002055600190565b600081815260036020526040902054801561148d5760001981018181116114775760025460001981019190821161147757808203611591575b50505061157d600261138d565b600052600360205260006040812055600190565b6115b36115a2611448936002611375565b90549060031b1c9283926002611375565b9055600052600360205260406000205538808061157056fe6080604052600436101561001257600080fd5b60003560e01c806241e5be1461020657806301ffc9a714610201578063061877e3146101fc57806306285c69146101f7578063181f5a77146101f25780632451a627146101ed578063325c868e146101e85780633937306f146101e357806341ed29e7146101de578063430d138c146101d957806345ac924d146101d45780634ab35b0b146101cf578063514e8cff146101ca5780636cb5f3dd146101c55780636def4ce7146101c0578063770e2dc4146101bb57806379ba5097146101b65780637afac322146101b1578063805f2132146101ac57806382b49eb0146101a75780638da5cb5b146101a257806391a2749a1461019d578063a69c64c014610198578063bf78e03f14610193578063cdc73d511461018e578063d02641a014610189578063d63d3af214610184578063d8694ccd1461017f578063f2fde38b1461017a578063fbe3f778146101755763ffdb4b371461017057600080fd5b612bf2565b612ab9565b6129ba565b61258d565b612553565b6124d7565b612442565b612357565b612280565b6121b0565b61215e565b611fcc565b611c8b565b611b1a565b6119ca565b61176f565b611600565b61129a565b6111ab565b611140565b61103b565b610edb565b610c44565b610885565b61084b565b6107aa565b6106d9565b61047a565b610407565b6102c5565b61023b565b73ffffffffffffffffffffffffffffffffffffffff81160361022957565b600080fd5b35906102398261020b565b565b346102295760607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261022957602061029060043561027b8161020b565b6024356044359161028b8361020b565b612da7565b604051908152f35b35907fffffffff000000000000000000000000000000000000000000000000000000008216820361022957565b346102295760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610229576004357fffffffff0000000000000000000000000000000000000000000000000000000081168103610229577fffffffff00000000000000000000000000000000000000000000000000000000602091167f805f21320000000000000000000000000000000000000000000000000000000081149081156103dd575b81156103b3575b8115610389575b506040519015158152f35b7f01ffc9a7000000000000000000000000000000000000000000000000000000009150143861037e565b7f181f5a770000000000000000000000000000000000000000000000000000000081149150610377565b7f9b645f410000000000000000000000000000000000000000000000000000000081149150610370565b346102295760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102295773ffffffffffffffffffffffffffffffffffffffff6004356104578161020b565b166000526008602052602067ffffffffffffffff60406000205416604051908152f35b346102295760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610229576104b1612df0565b5060606040516104c0816105a5565b63ffffffff6bffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169182815273ffffffffffffffffffffffffffffffffffffffff60406020830192827f00000000000000000000000000000000000000000000000000000000000000001684520191837f00000000000000000000000000000000000000000000000000000000000000001683526040519485525116602084015251166040820152f35b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6060810190811067ffffffffffffffff8211176105c157604052565b610576565b60a0810190811067ffffffffffffffff8211176105c157604052565b6040810190811067ffffffffffffffff8211176105c157604052565b60c0810190811067ffffffffffffffff8211176105c157604052565b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff8211176105c157604052565b6040519061023960408361061a565b604051906102396102208361061a565b919082519283825260005b8481106106c45750507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8460006020809697860101520116010190565b80602080928401015182828601015201610685565b346102295760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261022957610756604080519061071a818361061a565b601382527f46656551756f74657220312e362e302d6465760000000000000000000000000060208301525191829160208352602083019061067a565b0390f35b602060408183019282815284518094520192019060005b81811061077e5750505090565b825173ffffffffffffffffffffffffffffffffffffffff16845260209384019390920191600101610771565b346102295760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102295760405180602060025491828152019060026000527f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ace9060005b81811061083557610756856108298187038261061a565b6040519182918261075a565b8254845260209093019260019283019201610812565b346102295760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261022957602060405160248152f35b346102295760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102295760043567ffffffffffffffff811161022957806004019060407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc8236030112610229576108ff614180565b6109098280612e0f565b4263ffffffff1692915060005b818110610ae35750506024019061092d8284612e0f565b92905060005b83811061093c57005b8061095b610956600193610950868a612e0f565b90612e92565b612f07565b7fdd84a3fa9ef9409f550d54d6affec7e9c480c878c6ab27b78912a03e1b371c6e67ffffffffffffffff610aaa610a876020850194610a796109b987517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1690565b6109e86109c461065b565b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff9092168252565b63ffffffff8c166020820152610a23610a09845167ffffffffffffffff1690565b67ffffffffffffffff166000526005602052604060002090565b815160209092015160e01b7fffffffff00000000000000000000000000000000000000000000000000000000167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff92909216919091179055565b5167ffffffffffffffff1690565b93517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1690565b604080517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff9290921682524260208301529190931692a201610933565b80610afc610af76001936109508980612e0f565b612ed0565b7f52f50aa6d1a95a4595361ecf953d095f125d442e4673716dede699e049de148a73ffffffffffffffffffffffffffffffffffffffff610bde610a876020850194610bc4610b6687517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1690565b610b716109c461065b565b63ffffffff8d166020820152610a23610b9e845173ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff166000526006602052604060002090565b5173ffffffffffffffffffffffffffffffffffffffff1690565b604080517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff9290921682524260208301529190931692a201610916565b67ffffffffffffffff81116105c15760051b60200190565b8015150361022957565b359061023982610c2f565b346102295760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102295760043567ffffffffffffffff8111610229573660238201121561022957806004013590610c9f82610c17565b90610cad604051928361061a565b828252602460a06020840194028201019036821161022957602401925b818410610cdc57610cda83612f2c565b005b60a0843603126102295760405190610cf3826105c6565b8435610cfe8161020b565b825260208501357fffffffffffffffffffff00000000000000000000000000000000000000000000811681036102295760208301526040850135907fffff000000000000000000000000000000000000000000000000000000000000821682036102295782602092604060a0950152610d796060880161022e565b6060820152610d8a60808801610c39565b6080820152815201930192610cca565b6004359067ffffffffffffffff8216820361022957565b6024359067ffffffffffffffff8216820361022957565b359067ffffffffffffffff8216820361022957565b9181601f840112156102295782359167ffffffffffffffff8311610229576020838186019501011161022957565b9181601f840112156102295782359167ffffffffffffffff8311610229576020808501948460051b01011161022957565b929091610e5d9284521515602084015260806040840152608083019061067a565b906060818303910152815180825260208201916020808360051b8301019401926000915b838310610e9057505050505090565b9091929394602080610ecc837fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08660019603018752895161067a565b97019301930191939290610e81565b346102295760c07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261022957610f12610d9a565b60243590610f1f8261020b565b60443560643567ffffffffffffffff811161022957610f42903690600401610ddd565b60849391933567ffffffffffffffff811161022957610f65903690600401610e0b565b9160a4359567ffffffffffffffff871161022957366023880112156102295786600401359567ffffffffffffffff8711610229573660248860061b8a01011161022957610756986024610fb99901966130b8565b9060409492945194859485610e3c565b602060408183019282815284518094520192019060005b818110610fed5750505090565b9091926020604082611030600194885163ffffffff602080927bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8151168552015116910152565b019401929101610fe0565b346102295760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102295760043567ffffffffffffffff81116102295761108a903690600401610e0b565b61109381610c17565b916110a1604051938461061a565b8183527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe06110ce83610c17565b0160005b81811061112957505060005b8281101561111b576001906110ff6110fa8260051b8501613208565b613d7b565b61110982876130a4565b5261111481866130a4565b50016110de565b604051806107568682610fc9565b6020906111346131ef565b828288010152016110d2565b346102295760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102295760206111856004356111808161020b565b6140d1565b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff60405191168152f35b346102295760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102295767ffffffffffffffff6111eb610d9a565b6111f36131ef565b5016600052600560205260406000206040519061120f826105e2565b547bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8116825260e01c6020820152604051809161075682604081019263ffffffff602080927bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8151168552015116910152565b359061ffff8216820361022957565b359063ffffffff8216820361022957565b346102295760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102295760043567ffffffffffffffff81116102295736602382011215610229578060040135906112f582610c17565b90611303604051928361061a565b82825260246102406020840194028201019036821161022957602401925b81841061133157610cda8361324c565b8336036102408112610229576102207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe06040519261136e846105e2565b61137788610dc8565b84520112610229576102409160209161138e61066a565b611399848901610c39565b81526113a76040890161127a565b848201526113b760608901611289565b60408201526113c860808901611289565b60608201526113d960a08901611289565b60808201526113ea60c0890161127a565b60a08201526113fb60e08901611289565b60c082015261140d610100890161127a565b60e082015261141f610120890161127a565b610100820152611432610140890161127a565b6101208201526114456101608901611289565b6101408201526114586101808901611289565b61016082015261146b6101a08901610dc8565b61018082015261147e6101c08901611289565b6101a08201526114916101e08901611289565b6101c08201526114a46102008901610c39565b6101e08201526114b76102208901610298565b61020082015283820152815201930192611321565b61023990929192610200806102208301956114e984825115159052565b60208181015161ffff169085015260408181015163ffffffff169085015260608181015163ffffffff169085015260808181015163ffffffff169085015260a08181015161ffff169085015260c08181015163ffffffff169085015260e08181015161ffff16908501526101008181015161ffff16908501526101208181015161ffff16908501526101408181015163ffffffff16908501526101608181015163ffffffff16908501526101808181015167ffffffffffffffff16908501526101a08181015163ffffffff16908501526101c08181015163ffffffff16908501526101e08181015115159085015201517fffffffff0000000000000000000000000000000000000000000000000000000016910152565b346102295760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610229576107566116d36116ce611640610d9a565b600061020061164d61066a565b8281528260208201528260408201528260608201528260808201528260a08201528260c08201528260e08201528261010082015282610120820152826101408201528261016082015282610180820152826101a0820152826101c0820152826101e0820152015267ffffffffffffffff166000526009602052604060002090565b6134bc565b604051918291826114cc565b81601f82011215610229578035906116f682610c17565b92611704604051948561061a565b82845260208085019360061b8301019181831161022957602001925b82841061172e575050505090565b6040848303126102295760206040918251611748816105e2565b61175187610dc8565b8152828701356117608161020b565b83820152815201930192611720565b346102295760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102295760043567ffffffffffffffff811161022957366023820112156102295780600401356117c981610c17565b916117d7604051938461061a565b8183526024602084019260051b820101903682116102295760248101925b828410611826576024358567ffffffffffffffff821161022957611820610cda9236906004016116df565b90613638565b833567ffffffffffffffff811161022957820160407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdc82360301126102295760405190611872826105e2565b61187e60248201610dc8565b8252604481013567ffffffffffffffff811161022957602491010136601f820112156102295780356118af81610c17565b916118bd604051938461061a565b818352602060e081850193028201019036821161022957602001915b8183106118f857505050918160209384809401528152019301926117f5565b82360360e081126102295760c07fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe060405192611933846105e2565b863561193e8161020b565b845201126102295760e091602091604051611958816105fe565b611963848801611289565b815261197160408801611289565b848201526119816060880161127a565b604082015261199260808801611289565b60608201526119a360a08801611289565b608082015260c08701356119b681610c2f565b60a0820152838201528152019201916118d9565b346102295760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102295760005473ffffffffffffffffffffffffffffffffffffffff81163303611a89577fffffffffffffffffffffffff00000000000000000000000000000000000000006001549133828416176001551660005573ffffffffffffffffffffffffffffffffffffffff3391167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0600080a3005b7f02b543c60000000000000000000000000000000000000000000000000000000060005260046000fd5b9080601f83011215610229578135611aca81610c17565b92611ad8604051948561061a565b81845260208085019260051b82010192831161022957602001905b828210611b005750505090565b602080918335611b0f8161020b565b815201910190611af3565b346102295760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102295760043567ffffffffffffffff811161022957611b69903690600401611ab3565b60243567ffffffffffffffff811161022957611b89903690600401611ab3565b90611b926141c4565b60005b8151811015611c0e5780611bb6611bb1610bc4600194866130a4565b61599e565b611bc1575b01611b95565b73ffffffffffffffffffffffffffffffffffffffff611be3610bc483866130a4565b167f1795838dc8ab2ffc5f431a1729a6afa0b587f982f7b2be0b9d7187a1ef547f91600080a2611bbb565b8260005b8151811015610cda5780611c33611c2e610bc4600194866130a4565b6159bf565b611c3e575b01611c12565b73ffffffffffffffffffffffffffffffffffffffff611c60610bc483866130a4565b167fdf1b1bd32a69711488d71554706bb130b1fc63a5fa1a2cd85e8440f84065ba23600080a2611c38565b346102295760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102295760043567ffffffffffffffff811161022957611cda903690600401610ddd565b6024359167ffffffffffffffff831161022957611d33611d2b611d11611d07611d3b963690600401610ddd565b9490953691613931565b90604082015190605e604a84015160601c93015191929190565b919033614e61565b810190613996565b60005b8151811015610cda57611da0611d9b611d75611d5a84866130a4565b515173ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff166000526007602052604060002090565b613a55565b611db4611db06040830151151590565b1590565b611f765790611e29611dcc6020600194015160ff1690565b611e23611e026020611dde86896130a4565b5101517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1690565b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1690565b90614f40565b611e446040611e3884876130a4565b51015163ffffffff1690565b63ffffffff611e6f611e66611e5f610b9e611d5a888b6130a4565b5460e01c90565b63ffffffff1690565b911610611f7057611ed2611e886040611e3885886130a4565b611ec2611e9361065b565b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff851681529163ffffffff166020830152565b610a23610b9e611d5a86896130a4565b7f52f50aa6d1a95a4595361ecf953d095f125d442e4673716dede699e049de148a73ffffffffffffffffffffffffffffffffffffffff611f15611d5a85886130a4565b611f66611f276040611e38888b6130a4565b60405193849316958390929163ffffffff6020917bffffffffffffffffffffffffffffffffffffffffffffffffffffffff604085019616845216910152565b0390a25b01611d3e565b50611f6a565b611fc8611f86611d5a84866130a4565b7f06439c6b0000000000000000000000000000000000000000000000000000000060005273ffffffffffffffffffffffffffffffffffffffff16600452602490565b6000fd5b346102295760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102295761075661207f612009610d9a565b67ffffffffffffffff6024359161201f8361020b565b600060a060405161202f816105fe565b828152826020820152826040820152826060820152826080820152015216600052600a60205260406000209073ffffffffffffffffffffffffffffffffffffffff16600052602052604060002090565b6120fb6120f260405192612092846105fe565b5463ffffffff8116845263ffffffff8160201c16602085015261ffff8160401c1660408501526120d96120cc8263ffffffff9060501c1690565b63ffffffff166060860152565b63ffffffff607082901c16608085015260901c60ff1690565b151560a0830152565b6040519182918291909160a08060c083019463ffffffff815116845263ffffffff602082015116602085015261ffff604082015116604085015263ffffffff606082015116606085015263ffffffff608082015116608085015201511515910152565b346102295760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261022957602073ffffffffffffffffffffffffffffffffffffffff60015416604051908152f35b346102295760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102295760043567ffffffffffffffff81116102295760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc823603011261022957604051612229816105e2565b816004013567ffffffffffffffff81116102295761224d9060043691850101611ab3565b8152602482013567ffffffffffffffff811161022957610cda9260046122769236920101611ab3565b6020820152613af2565b346102295760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102295760043567ffffffffffffffff81116102295736602382011215610229578060040135906122db82610c17565b906122e9604051928361061a565b8282526024602083019360061b8201019036821161022957602401925b81841061231657610cda83613c92565b6040843603126102295760206040918251612330816105e2565b863561233b8161020b565b8152612348838801610dc8565b83820152815201930192612306565b346102295760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102295773ffffffffffffffffffffffffffffffffffffffff6004356123a78161020b565b6123af612df0565b50166000526007602052610756604060002060ff604051916123d0836105a5565b5473ffffffffffffffffffffffffffffffffffffffff81168352818160a01c16602084015260a81c161515604082015260405191829182919091604080606083019473ffffffffffffffffffffffffffffffffffffffff815116845260ff602082015116602085015201511515910152565b346102295760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261022957604051806020600b54918281520190600b6000527f0175b7a638427703f0dbe7bb9bbf987a2551717b34e79f33b5b1008d1fa01db99060005b8181106124c157610756856108298187038261061a565b82548452602090930192600192830192016124aa565b346102295760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102295760406125176004356110fa8161020b565b6125518251809263ffffffff602080927bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8151168552015116910152565bf35b346102295760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261022957602060405160128152f35b346102295760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610229576125c4610d9a565b6024359067ffffffffffffffff821161022957816004019060a07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc8436030112610229576126296116ce8267ffffffffffffffff166000526009602052604060002090565b91612637611db08451151590565b61298257606484019061267b611db061264f84613208565b73ffffffffffffffffffffffffffffffffffffffff166000526001600b01602052604060002054151590565b61293457604485019361268e8583612e0f565b94905060248701966126c16126a38986613ecb565b9050876126ba6126b38880613ecb565b3691613931565b918661526a565b6126cd61118086613208565b966126e96126e36101c086015163ffffffff1690565b8461532a565b92600080891561290c57505090612717918961270e6127078a613208565b9389612e0f565b93909288615477565b9591955b60009861ffff61273161010089015161ffff1690565b166128a5575b5088612888896128888a8f8f9861287a61285461284e8f6107569f6128959f6101807bffffffffffffffffffffffffffffffffffffffffffffffffffffffff9f61288d9f936dffffffffffffffffffffffffffff61282a61284195612823896128009f6128419f60846128156128319a63ffffffff6128009f85826128068a6128006127f960a06127ef61280d9861281d9f6127e589916127df60808a015163ffffffff1690565b9b613ecb565b9290501690613f1c565b93015161ffff1690565b61ffff1690565b90612d5b565b9116613f1c565b911690613f1c565b950190613ecb565b90615795565b5190613f1c565b9116612d5b565b93015167ffffffffffffffff1690565b67ffffffffffffffff1690565b96613208565b73ffffffffffffffffffffffffffffffffffffffff166000526008602052604060002090565b5467ffffffffffffffff1690565b613f1c565b911690612d6e565b6040519081529081906020820190565b8597929a9950928181999594889d9897936128d289956dffffffffffffffffffffffffffff9060701c1690565b6dffffffffffffffffffffffffffff16916128ed8b86613ecb565b90506128f993876156f4565b9a9b9398965091509293979a959a612737565b915095915061292e612929611e666101a088015163ffffffff1690565b612d14565b9561271b565b611fc861294083613208565b7f2502348c0000000000000000000000000000000000000000000000000000000060005273ffffffffffffffffffffffffffffffffffffffff16600452602490565b7f99ac52f20000000000000000000000000000000000000000000000000000000060005267ffffffffffffffff821660045260246000fd5b346102295760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102295773ffffffffffffffffffffffffffffffffffffffff600435612a0a8161020b565b612a126141c4565b16338114612a8457807fffffffffffffffffffffffff0000000000000000000000000000000000000000600054161760005573ffffffffffffffffffffffffffffffffffffffff600154167fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae1278600080a3005b7fdad89dca0000000000000000000000000000000000000000000000000000000060005260046000fd5b60ff81160361022957565b346102295760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102295760043567ffffffffffffffff8111610229573660238201121561022957806004013590612b1482610c17565b90612b22604051928361061a565b8282526024602083019360071b8201019036821161022957602401925b818410612b4f57610cda83613f29565b833603608081126102295760607fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe060405192612b8a846105e2565b8735612b958161020b565b8452011261022957608091602091604051612baf816105a5565b83880135612bbc8161020b565b81526040880135612bcc81612aae565b848201526060880135612bde81610c2f565b604082015283820152815201930192612b3f565b346102295760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261022957600435612c2d8161020b565b612c35610db1565b9067ffffffffffffffff82169182600052600960205260ff6040600020541615612cb757612c65612c86926140d1565b92600052600960205263ffffffff60016040600020015460801c169061532a565b604080517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff9384168152919092166020820152f35b827f99ac52f20000000000000000000000000000000000000000000000000000000060005260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b90662386f26fc10000820291808304662386f26fc100001490151715612d3657565b612ce5565b90655af3107a4000820291808304655af3107a40001490151715612d3657565b81810292918115918404141715612d3657565b8115612d78570490565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b612de6612de0612ded94937bffffffffffffffffffffffffffffffffffffffffffffffffffffffff612dd981956140d1565b1690612d5b565b926140d1565b1690612d6e565b90565b60405190612dfd826105a5565b60006040838281528260208201520152565b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe181360301821215610229570180359067ffffffffffffffff821161022957602001918160061b3603831361022957565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b9190811015612ea25760061b0190565b612e63565b35907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8216820361022957565b60408136031261022957612eff602060405192612eec846105e2565b8035612ef78161020b565b845201612ea7565b602082015290565b60408136031261022957612eff602060405192612f23846105e2565b612ef781610dc8565b90612f356141c4565b60005b825181101561309f5780612f4e600192856130a4565b517f32a4ba3fa3351b11ad555d4c8ec70a744e8705607077a946807030d64b6ab1a360a073ffffffffffffffffffffffffffffffffffffffff83511692606081019373ffffffffffffffffffffffffffffffffffffffff80865116957fffff00000000000000000000000000000000000000000000000000000000000061300660208601947fffffffffffffffffffff00000000000000000000000000000000000000000000865116604088019a848c51169261583d565b977fffffffffffffffffffff000000000000000000000000000000000000000000006080870195613072875115158c600052600460205260406000209060ff7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0083541691151516179055565b8560405198511688525116602087015251166040850152511660608301525115156080820152a201612f38565b509050565b8051821015612ea25760209160051b010190565b989592919097949693977f00000000000000000000000000000000000000000000000000000000000000009073ffffffffffffffffffffffffffffffffffffffff821673ffffffffffffffffffffffffffffffffffffffff8216146000146131df575050965b6bffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168089116131ae5750916131936131a194926131a7969463ffffffff8060016131898f67ffffffffffffffff166000526009602052604060002090565b01541616916142e8565b9660208801511515996144b0565b926146c4565b9293929190565b887f6a92a4830000000000000000000000000000000000000000000000000000000060005260045260245260446000fd5b916131e992612da7565b9661311e565b604051906131fc826105e2565b60006020838281520152565b35612ded8161020b565b9060405161321f816105e2565b91547bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8116835260e01c6020830152565b906132556141c4565b60005b825181101561309f5761326b81846130a4565b51602061328a61327b84876130a4565b515167ffffffffffffffff1690565b9101519067ffffffffffffffff81168015801561349d575b8015613424575b80156133f6575b6133be5791613384826001959461333461330f886132e56133899867ffffffffffffffff166000526009602052604060002090565b015460381b7fffffffff000000000000000000000000000000000000000000000000000000001690565b7fffffffff000000000000000000000000000000000000000000000000000000001690565b61338f577f525e3d4e0c31cef19cf9426af8d2c0ddd2d576359ca26bed92aac5fadda462656040518061336787826114cc565b0390a267ffffffffffffffff166000526009602052604060002090565b614712565b01613258565b7f283b699f411baff8f1c29fe49f32a828c8151596244b8e7e4c164edd6569a8356040518061336787826114cc565b7fc35aa79d0000000000000000000000000000000000000000000000000000000060005267ffffffffffffffff821660045260246000fd5b5061016083015163ffffffff1663ffffffff61341c611e66606087015163ffffffff1690565b9116116132b0565b507f2812d52c000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000006134956102008601517fffffffff000000000000000000000000000000000000000000000000000000001690565b1614156132a9565b5063ffffffff6134b561016085015163ffffffff1690565b16156132a2565b9061023961360e60016134cd61066a565b9461358b61357d82546134e96134e38260ff1690565b15158a52565b61ffff600882901c1660208a015263ffffffff601882901c1660408a015263ffffffff603882901c1660608a015263ffffffff605882901c1660808a015261ffff607882901c1660a08a015263ffffffff608882901c1660c08a015261ffff60a882901c1660e08a015261ffff60b882901c166101008a015261ffff60c882901c166101208a015260d81c63ffffffff1690565b63ffffffff16610140880152565b015463ffffffff811661016086015267ffffffffffffffff602082901c1661018086015263ffffffff606082901c166101a086015263ffffffff608082901c166101c08601526135e660a082901c60ff1615156101e0870152565b60381b7fffffffff000000000000000000000000000000000000000000000000000000001690565b7fffffffff0000000000000000000000000000000000000000000000000000000016610200840152565b906136416141c4565b6000915b80518310156138725761365883826130a4565b519061366c825167ffffffffffffffff1690565b946020600093019367ffffffffffffffff8716935b8551805182101561385d57613698826020926130a4565b5101516136a9611d5a8389516130a4565b8151602083015163ffffffff908116911681811015613824575050608082015163ffffffff16602081106137d6575090867f94967ae9ea7729ad4f54021c1981765d2b1d954f7c92fbec340aa0a54f46b8b573ffffffffffffffffffffffffffffffffffffffff84613765858f6001999861373b6137609267ffffffffffffffff16600052600a602052604060002090565b9073ffffffffffffffffffffffffffffffffffffffff16600052602052604060002090565b614cd7565b6137cd60405192839216958291909160a08060c083019463ffffffff815116845263ffffffff602082015116602085015261ffff604082015116604085015263ffffffff606082015116606085015263ffffffff608082015116608085015201511515910152565b0390a301613681565b7f24ecdc020000000000000000000000000000000000000000000000000000000060005273ffffffffffffffffffffffffffffffffffffffff90911660045263ffffffff1660245260446000fd5b7f0b4f67a20000000000000000000000000000000000000000000000000000000060005263ffffffff9081166004521660245260446000fd5b50509550925092600191500191929092613645565b50905060005b815181101561392d578061389161327b600193856130a4565b67ffffffffffffffff73ffffffffffffffffffffffffffffffffffffffff6138da60206138be86896130a4565b51015173ffffffffffffffffffffffffffffffffffffffff1690565b60006138fe8261373b8767ffffffffffffffff16600052600a602052604060002090565b551691167f4de5b1bcbca6018c11303a2c3f4a4b4f22a1c741d8c4ba430d246ac06c5ddf8b600080a301613878565b5050565b92919267ffffffffffffffff82116105c15760405191613979601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0166020018461061a565b829481845281830111610229578281602093846000960137010152565b6020818303126102295780359067ffffffffffffffff8211610229570181601f82011215610229578035906139ca82610c17565b926139d8604051948561061a565b8284526020606081860194028301019181831161022957602001925b828410613a02575050505090565b606084830312610229576020606091604051613a1d816105a5565b8635613a288161020b565b8152613a35838801612ea7565b83820152613a4560408801611289565b60408201528152019301926139f4565b90604051613a62816105a5565b604060ff82945473ffffffffffffffffffffffffffffffffffffffff81168452818160a01c16602085015260a81c161515910152565b90610239604051613aa8816105fe565b925463ffffffff8082168552602082811c821690860152604082811c61ffff1690860152605082901c81166060860152607082901c16608085015260901c60ff16151560a0840152565b613afa6141c4565b60208101519160005b8351811015613bae5780613b1c610bc4600193876130a4565b613b58613b5373ffffffffffffffffffffffffffffffffffffffff83165b73ffffffffffffffffffffffffffffffffffffffff1690565b615cd5565b613b64575b5001613b03565b60405173ffffffffffffffffffffffffffffffffffffffff9190911681527fc3803387881faad271c47728894e3e36fac830ffc8602ca6fc07733cbda7758090602090a138613b5d565b5091505160005b815181101561392d57613bcb610bc482846130a4565b9073ffffffffffffffffffffffffffffffffffffffff821615613c68577feb1b9b92e50b7f88f9ff25d56765095ac6e91540eee214906f4036a908ffbdef613c5f83613c37613c32613b3a60019773ffffffffffffffffffffffffffffffffffffffff1690565b615c5c565b5060405173ffffffffffffffffffffffffffffffffffffffff90911681529081906020820190565b0390a101613bb5565b7f8579befe0000000000000000000000000000000000000000000000000000000060005260046000fd5b613c9a6141c4565b60005b815181101561392d578073ffffffffffffffffffffffffffffffffffffffff613cc8600193856130a4565b5151167fbb77da6f7210cdd16904228a9360133d1d7dfff99b1bc75f128da5b53e28f97d613d6567ffffffffffffffff6020613d0486896130a4565b51015116836000526008602052604060002067ffffffffffffffff82167fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000008254161790556040519182918291909167ffffffffffffffff6020820193169052565b0390a201613c9d565b91908203918211612d3657565b613d836131ef565b50613db6613db18273ffffffffffffffffffffffffffffffffffffffff166000526006602052604060002090565b613212565b6020810191613dd5613dcf611e66855163ffffffff1690565b42613d6e565b63ffffffff7f00000000000000000000000000000000000000000000000000000000000000001611613e8a57611d9b613e2e9173ffffffffffffffffffffffffffffffffffffffff166000526007602052604060002090565b613e3e611db06040830151151590565b8015613e90575b613e8a57613e52906150e1565b9163ffffffff613e7a611e66613e6f602087015163ffffffff1690565b935163ffffffff1690565b911610613e85575090565b905090565b50905090565b5073ffffffffffffffffffffffffffffffffffffffff613ec4825173ffffffffffffffffffffffffffffffffffffffff1690565b1615613e45565b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe181360301821215610229570180359067ffffffffffffffff82116102295760200191813603831361022957565b91908201809211612d3657565b90613f326141c4565b60005b825181101561309f5780613f4b600192856130a4565b517fe6a7a17d710bf0b2cd05e5397dc6f97a5da4ee79e31e234bf5f965ee2bd9a5bf6140c8602073ffffffffffffffffffffffffffffffffffffffff8451169301518360005260076020526040600020613ff773ffffffffffffffffffffffffffffffffffffffff835116829073ffffffffffffffffffffffffffffffffffffffff167fffffffffffffffffffffffff0000000000000000000000000000000000000000825416179055565b602082015181547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1660a09190911b74ff000000000000000000000000000000000000000016177fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff75ff0000000000000000000000000000000000000000006040850151151560a81b16911617905560405191829182919091604080606083019473ffffffffffffffffffffffffffffffffffffffff815116845260ff602082015116602085015201511515910152565b0390a201613f35565b6140da81613d7b565b9063ffffffff602083015116158015614159575b6141155750517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff907f06439c6b000000000000000000000000000000000000000000000000000000006000521660045260246000fd5b507bffffffffffffffffffffffffffffffffffffffffffffffffffffffff825116156140ee565b3360005260036020526040600020541561419657565b7fd86ad9cf000000000000000000000000000000000000000000000000000000006000523360045260246000fd5b73ffffffffffffffffffffffffffffffffffffffff6001541633036141e557565b7f2b5c74de0000000000000000000000000000000000000000000000000000000060005260046000fd5b919091357fffffffff0000000000000000000000000000000000000000000000000000000081169260048110614243575050565b7fffffffff00000000000000000000000000000000000000000000000000000000929350829060040360031b1b161690565b909291928360041161022957831161022957600401917ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0190565b90816020910312610229575190565b90816040910312610229576020604051916142d9836105e2565b805183520151612eff81610c2f565b916142f16131ef565b5081156143e757506143326126b3828061432c7fffffffff00000000000000000000000000000000000000000000000000000000958761420f565b95614275565b91167f181dcf1000000000000000000000000000000000000000000000000000000000810361436f575080602080612ded935183010191016142bf565b7f97a657c900000000000000000000000000000000000000000000000000000000146143bf577f5247fdce0000000000000000000000000000000000000000000000000000000060005260046000fd5b806020806143d2935183010191016142b0565b6143da61065b565b9081526000602082015290565b91505067ffffffffffffffff6143fb61065b565b911681526000602082015290565b9061441382610c17565b614420604051918261061a565b8281527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe061444e8294610c17565b019060005b82811061445f57505050565b806060602080938501015201614453565b9190811015612ea25760051b810135907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6181360301821215610229570190565b9092916144d660016132e58467ffffffffffffffff166000526009602052604060002090565b906144e081614409565b9560005b8281106144f5575050505050505090565b614508614503828489612e92565b613208565b8388614522614518858484614470565b6040810190613ecb565b90506020811161463c575b50839261455c6145566126b361454c60019861457f9761457a97614470565b6020810190613ecb565b896158ce565b61373b8967ffffffffffffffff16600052600a602052604060002090565b613a98565b60a081015115614602576145e66145a060606145ba93015163ffffffff1690565b6040805163ffffffff909216602083015290928391820190565b037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0810183528261061a565b6145f0828b6130a4565b526145fb818a6130a4565b50016144e4565b506145ba6145e661463761462a8967ffffffffffffffff166000526009602052604060002090565b5460d81c63ffffffff1690565b6145a0565b915050614674611e666146678461373b8b67ffffffffffffffff16600052600a602052604060002090565b5460701c63ffffffff1690565b106146815783883861452d565b7f36f536ca0000000000000000000000000000000000000000000000000000000060005273ffffffffffffffffffffffffffffffffffffffff1660045260246000fd5b6020604051917f181dcf1000000000000000000000000000000000000000000000000000000000828401528051602484015201511515604482015260448152612ded60648261061a565b9055565b90614c8d61020060016102399461475d61472c8651151590565b829060ff7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0083541691151516179055565b6147a361476f602087015161ffff1690565b82547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000ff1660089190911b62ffff0016178255565b6147ef6147b7604087015163ffffffff1690565b82547fffffffffffffffffffffffffffffffffffffffffffffffffff00000000ffffff1660189190911b66ffffffff00000016178255565b61483f614803606087015163ffffffff1690565b82547fffffffffffffffffffffffffffffffffffffffffff00000000ffffffffffffff1660389190911b6affffffff0000000000000016178255565b614893614853608087015163ffffffff1690565b82547fffffffffffffffffffffffffffffffffff00000000ffffffffffffffffffffff1660589190911b6effffffff000000000000000000000016178255565b6148e76148a560a087015161ffff1690565b82547fffffffffffffffffffffffffffffff0000ffffffffffffffffffffffffffffff1660789190911b70ffff00000000000000000000000000000016178255565b6149416148fb60c087015163ffffffff1690565b82547fffffffffffffffffffffff00000000ffffffffffffffffffffffffffffffffff1660889190911b74ffffffff000000000000000000000000000000000016178255565b61499b61495360e087015161ffff1690565b82547fffffffffffffffffff0000ffffffffffffffffffffffffffffffffffffffffff1660a89190911b76ffff00000000000000000000000000000000000000000016178255565b6149f86149ae61010087015161ffff1690565b82547fffffffffffffff0000ffffffffffffffffffffffffffffffffffffffffffffff1660b89190911b78ffff000000000000000000000000000000000000000000000016178255565b614a57614a0b61012087015161ffff1690565b82547fffffffffff0000ffffffffffffffffffffffffffffffffffffffffffffffffff1660c89190911b7affff0000000000000000000000000000000000000000000000000016178255565b614abc614a6c61014087015163ffffffff1690565b82547fff00000000ffffffffffffffffffffffffffffffffffffffffffffffffffffff1660d89190911b7effffffff00000000000000000000000000000000000000000000000000000016178255565b0192614b04614ad361016083015163ffffffff1690565b859063ffffffff167fffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000825416179055565b614b5a614b1d61018083015167ffffffffffffffff1690565b85547fffffffffffffffffffffffffffffffffffffffff0000000000000000ffffffff1660209190911b6bffffffffffffffff0000000016178555565b614bb0614b6f6101a083015163ffffffff1690565b85547fffffffffffffffffffffffffffffffff00000000ffffffffffffffffffffffff1660609190911b6fffffffff00000000000000000000000016178555565b614c0a614bc56101c083015163ffffffff1690565b85547fffffffffffffffffffffffff00000000ffffffffffffffffffffffffffffffff1660809190911b73ffffffff0000000000000000000000000000000016178555565b614c66614c1b6101e0830151151590565b85805490917fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff90911690151560a01b74ff000000000000000000000000000000000000000016179055565b01517fffffffff000000000000000000000000000000000000000000000000000000001690565b81547fffffffffffffff00000000ffffffffffffffffffffffffffffffffffffffffff1660389190911c78ffffffff00000000000000000000000000000000000000000016179055565b614e1d60a061023993614d1c63ffffffff825116859063ffffffff167fffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000825416179055565b60208181015185546040808501517fffffffffffffffffffffffffffffffffffffffffffff000000000000ffffffff9092169290931b67ffffffff000000001691909117911b69ffff0000000000000000161784556060810151614dbf9063ffffffff1685547fffffffffffffffffffffffffffffffffffff00000000ffffffffffffffffffff1660509190911b6dffffffff0000000000000000000016178555565b614e16614dd3608083015163ffffffff1690565b85547fffffffffffffffffffffffffffff00000000ffffffffffffffffffffffffffff1660709190911b71ffffffff000000000000000000000000000016178555565b0151151590565b81547fffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffff1690151560901b72ff00000000000000000000000000000000000016179055565b91929092614e718282868661583d565b600052600460205260ff6040600020541615614e8d5750505050565b6040517f097e17ff00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff93841660048201529390921660248401527fffffffffffffffffffff0000000000000000000000000000000000000000000090911660448301527fffff000000000000000000000000000000000000000000000000000000000000166064820152608490fd5b0390fd5b604d8111612d3657600a0a90565b60ff1660120160ff8111612d365760ff16906024821115615005577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdc8201918211612d3657614f91614f9792614f32565b90612d6e565b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8111614fdb577bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1690565b7f10cb51d10000000000000000000000000000000000000000000000000000000060005260046000fd5b906024039060248211612d365761280061501e92614f32565b614f97565b9060ff80911691160160ff8111612d365760ff16906024821115615005577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdc8201918211612d3657614f91614f9792614f32565b519069ffffffffffffffffffff8216820361022957565b908160a0910312610229576150a281615077565b91602082015191604081015191612ded608060608401519301615077565b6040513d6000823e3d90fd5b908160209103126102295751612ded81612aae565b6150e96131ef565b5061510e613b3a613b3a835173ffffffffffffffffffffffffffffffffffffffff1690565b90604051907ffeaf968c00000000000000000000000000000000000000000000000000000000825260a082600481865afa92831561522b57600092600094615230575b5060008312614fdb576020600491604051928380927f313ce5670000000000000000000000000000000000000000000000000000000082525afa92831561522b57612ded9363ffffffff936151b7936000926151f5575b506020015160ff165b90615023565b926151e76151c361065b565b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff9095168552565b1663ffffffff166020830152565b6151b191925061521c602091823d8411615224575b615214818361061a565b8101906150cc565b9291506151a8565b503d61520a565b6150c0565b90935061525691925060a03d60a011615263575b61524e818361061a565b81019061508e565b5093925050919238615151565b503d615244565b919063ffffffff6040840151168082116152fa57505061ffff602083015116908181116152c4575050907fffffffff00000000000000000000000000000000000000000000000000000000610200610239930151166158ce565b61ffff92507fd88dddd6000000000000000000000000000000000000000000000000000000006000526004521660245260446000fd5b7f869337890000000000000000000000000000000000000000000000000000000060005260045260245260446000fd5b67ffffffffffffffff8116600052600560205260406000209160405192615350846105e2565b547bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8116845260e01c9182602085015263ffffffff821692836153b4575b50505050612ded90517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1690565b63ffffffff164290810393908411612d365783116153d2578061538a565b7ff08bcb3e0000000000000000000000000000000000000000000000000000000060005267ffffffffffffffff1660045263ffffffff1660245260445260646000fd5b6040813603126102295760206040519161542e836105e2565b80356154398161020b565b83520135602082015290565b63ffffffff60209116019063ffffffff8211612d3657565b9063ffffffff8091169116019063ffffffff8211612d3657565b929593909491956000936000976000976000955b80871061549e5750505050505050929190565b9091929394959698996154ba6154b589848a612e92565b615415565b9961552261457a8c6154fe6154e38867ffffffffffffffff16600052600a602052604060002090565b915173ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff16600052602052604060002090565b91615533611db060a0850151151590565b6156a25760009b604084019061554e6127f9835161ffff1690565b615603575b5050606083015163ffffffff166155699161545d565b9b608083015161557c9063ffffffff1690565b6155859161545d565b9a82516155959063ffffffff1690565b63ffffffff166155a490612d14565b600193908083106155f75750612929611e6660206155c793015163ffffffff1690565b8082116155e657506155d891613f1c565b975b0195949392919061548b565b90506155f191613f1c565b976155da565b9150506155f191613f1c565b906128006127f9615693949f61568a9460208e61568193508d73ffffffffffffffffffffffffffffffffffffffff61564f855173ffffffffffffffffffffffffffffffffffffffff1690565b911673ffffffffffffffffffffffffffffffffffffffff82161461569b5761567791506140d1565b915b0151906159e0565b925161ffff1690565b620186a0900490565b9a3880615553565b5091615679565b989a50600191506156e86156cf6156ee926156c96129296127f96101208c015161ffff1690565b90613f1c565b996156e261014089015163ffffffff1690565b9061545d565b9b615445565b996155da565b91939093806101e00193846101e011612d36576101208102908082046101201490151715612d36576101e0910101809311612d36576127f96101006127ef612ded966dffffffffffffffffffffffffffff6157886157746157626157909a63ffffffff6128009a1690613f1c565b6128006127f960e08c015161ffff1690565b6156c9611e6660c08b015163ffffffff1690565b911690612d5b565b612d3b565b6157b4916157a16131ef565b5063ffffffff61016085015116916142e8565b90815163ffffffff806060840151161610615813576101e00151151580615807575b6157dd5790565b7fee433e990000000000000000000000000000000000000000000000000000000060005260046000fd5b506020810151156157d6565b7f4c4fc93a0000000000000000000000000000000000000000000000000000000060005260046000fd5b6040805173ffffffffffffffffffffffffffffffffffffffff9283166020820190815292909316908301527fffffffffffffffffffff0000000000000000000000000000000000000000000090921660608201527fffff0000000000000000000000000000000000000000000000000000000000009092166080830152906158c88160a081016145ba565b51902090565b7fffffffff00000000000000000000000000000000000000000000000000000000167f2812d52c00000000000000000000000000000000000000000000000000000000146159195750565b602081510361595c5761593560208251830101602083016142b0565b73ffffffffffffffffffffffffffffffffffffffff8111908115615992575b5061595c5750565b614f2e906040519182917f8d666f6000000000000000000000000000000000000000000000000000000000835260048301615a15565b61040091501038615954565b73ffffffffffffffffffffffffffffffffffffffff612ded9116600b615b09565b73ffffffffffffffffffffffffffffffffffffffff612ded9116600b615c97565b670de0b6b3a7640000917bffffffffffffffffffffffffffffffffffffffffffffffffffffffff615a119216612d5b565b0490565b906020612ded92818152019061067a565b8054821015612ea25760005260206000200190600090565b9161470e918354907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9060031b92831b921b19161790565b80548015615ada577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190615aab8282615a26565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82549160031b1b1916905555565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b6001810191806000528260205260406000205492831515600014615bf7577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8401848111612d36578354937fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8501948511612d36576000958583615ba897615b999503615bae575b505050615a76565b90600052602052604060002090565b55600190565b615bde615bd891615bcf615bc5615bee9588615a26565b90549060031b1c90565b92839187615a26565b90615a3e565b8590600052602052604060002090565b55388080615b91565b50505050600090565b805490680100000000000000008210156105c15781615c2791600161470e94018155615a26565b81939154907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9060031b92831b921b19161790565b600081815260036020526040902054615c9157615c7a816002615c00565b600254906000526003602052604060002055600190565b50600090565b6000828152600182016020526040902054615cce5780615cb983600193615c00565b80549260005201602052604060002055600190565b5050600090565b600081815260036020526040902054908115615cce577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820190828211612d3657600254927fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8401938411612d36578383615ba89460009603615d71575b505050615d606002615a76565b600390600052602052604060002090565b615d60615bd891615d89615bc5615d93956002615a26565b9283916002615a26565b55388080615d5356fea164736f6c634300081a000a", + ABI: "[{\"inputs\":[{\"components\":[{\"internalType\":\"uint96\",\"name\":\"maxFeeJuelsPerMsg\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"linkToken\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"tokenPriceStalenessThreshold\",\"type\":\"uint32\"}],\"internalType\":\"structFeeQuoter.StaticConfig\",\"name\":\"staticConfig\",\"type\":\"tuple\"},{\"internalType\":\"address[]\",\"name\":\"priceUpdaters\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"feeTokens\",\"type\":\"address[]\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"sourceToken\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"dataFeedAddress\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"tokenDecimals\",\"type\":\"uint8\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"}],\"internalType\":\"structFeeQuoter.TokenPriceFeedConfig\",\"name\":\"feedConfig\",\"type\":\"tuple\"}],\"internalType\":\"structFeeQuoter.TokenPriceFeedUpdate[]\",\"name\":\"tokenPriceFeeds\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"minFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"deciBps\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destBytesOverhead\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"}],\"internalType\":\"structFeeQuoter.TokenTransferFeeConfig\",\"name\":\"tokenTransferFeeConfig\",\"type\":\"tuple\"}],\"internalType\":\"structFeeQuoter.TokenTransferFeeConfigSingleTokenArgs[]\",\"name\":\"tokenTransferFeeConfigs\",\"type\":\"tuple[]\"}],\"internalType\":\"structFeeQuoter.TokenTransferFeeConfigArgs[]\",\"name\":\"tokenTransferFeeConfigArgs\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"premiumMultiplierWeiPerEth\",\"type\":\"uint64\"}],\"internalType\":\"structFeeQuoter.PremiumMultiplierWeiPerEthArgs[]\",\"name\":\"premiumMultiplierWeiPerEthArgs\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint16\",\"name\":\"maxNumberOfTokensPerMsg\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"maxDataBytes\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPerMsgGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerPayloadByte\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destDataAvailabilityOverheadGas\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerDataAvailabilityByte\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"destDataAvailabilityMultiplierBps\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"defaultTokenFeeUSDCents\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"defaultTokenDestGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"defaultTxGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint64\",\"name\":\"gasMultiplierWeiPerEth\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"networkFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"gasPriceStalenessThreshold\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"enforceOutOfOrder\",\"type\":\"bool\"},{\"internalType\":\"bytes4\",\"name\":\"chainFamilySelector\",\"type\":\"bytes4\"}],\"internalType\":\"structFeeQuoter.DestChainConfig\",\"name\":\"destChainConfig\",\"type\":\"tuple\"}],\"internalType\":\"structFeeQuoter.DestChainConfigArgs[]\",\"name\":\"destChainConfigArgs\",\"type\":\"tuple[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"CannotTransferToSelf\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"DataFeedValueOutOfUint224Range\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"DestinationChainNotEnabled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ExtraArgOutOfOrderExecutionMustBeTrue\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"FeeTokenNotSupported\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"destBytesOverhead\",\"type\":\"uint32\"}],\"name\":\"InvalidDestBytesOverhead\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"InvalidDestChainConfig\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"encodedAddress\",\"type\":\"bytes\"}],\"name\":\"InvalidEVMAddress\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidExtraArgsTag\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"minFeeUSDCents\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxFeeUSDCents\",\"type\":\"uint256\"}],\"name\":\"InvalidFeeRange\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidStaticConfig\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"msgFeeJuels\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxFeeJuelsPerMsg\",\"type\":\"uint256\"}],\"name\":\"MessageFeeTooHigh\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MessageGasLimitTooHigh\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"maxSize\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"actualSize\",\"type\":\"uint256\"}],\"name\":\"MessageTooLarge\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MustBeProposedOwner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByOwner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OwnerCannotBeZero\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"forwarder\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"workflowOwner\",\"type\":\"address\"},{\"internalType\":\"bytes10\",\"name\":\"workflowName\",\"type\":\"bytes10\"},{\"internalType\":\"bytes2\",\"name\":\"reportName\",\"type\":\"bytes2\"}],\"name\":\"ReportForwarderUnauthorized\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"SourceTokenDataTooLarge\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint256\",\"name\":\"threshold\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"timePassed\",\"type\":\"uint256\"}],\"name\":\"StaleGasPrice\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"TokenNotSupported\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"UnauthorizedCaller\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"numberOfTokens\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxNumberOfTokensPerMsg\",\"type\":\"uint256\"}],\"name\":\"UnsupportedNumberOfTokens\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"AuthorizedCallerAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"AuthorizedCallerRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint16\",\"name\":\"maxNumberOfTokensPerMsg\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"maxDataBytes\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPerMsgGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerPayloadByte\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destDataAvailabilityOverheadGas\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerDataAvailabilityByte\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"destDataAvailabilityMultiplierBps\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"defaultTokenFeeUSDCents\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"defaultTokenDestGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"defaultTxGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint64\",\"name\":\"gasMultiplierWeiPerEth\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"networkFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"gasPriceStalenessThreshold\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"enforceOutOfOrder\",\"type\":\"bool\"},{\"internalType\":\"bytes4\",\"name\":\"chainFamilySelector\",\"type\":\"bytes4\"}],\"indexed\":false,\"internalType\":\"structFeeQuoter.DestChainConfig\",\"name\":\"destChainConfig\",\"type\":\"tuple\"}],\"name\":\"DestChainAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint16\",\"name\":\"maxNumberOfTokensPerMsg\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"maxDataBytes\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPerMsgGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerPayloadByte\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destDataAvailabilityOverheadGas\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerDataAvailabilityByte\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"destDataAvailabilityMultiplierBps\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"defaultTokenFeeUSDCents\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"defaultTokenDestGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"defaultTxGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint64\",\"name\":\"gasMultiplierWeiPerEth\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"networkFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"gasPriceStalenessThreshold\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"enforceOutOfOrder\",\"type\":\"bool\"},{\"internalType\":\"bytes4\",\"name\":\"chainFamilySelector\",\"type\":\"bytes4\"}],\"indexed\":false,\"internalType\":\"structFeeQuoter.DestChainConfig\",\"name\":\"destChainConfig\",\"type\":\"tuple\"}],\"name\":\"DestChainConfigUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"}],\"name\":\"FeeTokenAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"}],\"name\":\"FeeTokenRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"premiumMultiplierWeiPerEth\",\"type\":\"uint64\"}],\"name\":\"PremiumMultiplierWeiPerEthUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"dataFeedAddress\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"tokenDecimals\",\"type\":\"uint8\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"}],\"indexed\":false,\"internalType\":\"structFeeQuoter.TokenPriceFeedConfig\",\"name\":\"priceFeedConfig\",\"type\":\"tuple\"}],\"name\":\"PriceFeedPerTokenUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"reportId\",\"type\":\"bytes32\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"forwarder\",\"type\":\"address\"},{\"internalType\":\"bytes10\",\"name\":\"workflowName\",\"type\":\"bytes10\"},{\"internalType\":\"bytes2\",\"name\":\"reportName\",\"type\":\"bytes2\"},{\"internalType\":\"address\",\"name\":\"workflowOwner\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"isAllowed\",\"type\":\"bool\"}],\"indexed\":false,\"internalType\":\"structKeystoneFeedsPermissionHandler.Permission\",\"name\":\"permission\",\"type\":\"tuple\"}],\"name\":\"ReportPermissionSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"TokenTransferFeeConfigDeleted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"minFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"deciBps\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destBytesOverhead\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"}],\"indexed\":false,\"internalType\":\"structFeeQuoter.TokenTransferFeeConfig\",\"name\":\"tokenTransferFeeConfig\",\"type\":\"tuple\"}],\"name\":\"TokenTransferFeeConfigUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"name\":\"UsdPerTokenUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChain\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"name\":\"UsdPerUnitGasUpdated\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"FEE_BASE_DECIMALS\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"KEYSTONE_PRICE_DECIMALS\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address[]\",\"name\":\"addedCallers\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"removedCallers\",\"type\":\"address[]\"}],\"internalType\":\"structAuthorizedCallers.AuthorizedCallerArgs\",\"name\":\"authorizedCallerArgs\",\"type\":\"tuple\"}],\"name\":\"applyAuthorizedCallerUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint16\",\"name\":\"maxNumberOfTokensPerMsg\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"maxDataBytes\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPerMsgGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerPayloadByte\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destDataAvailabilityOverheadGas\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerDataAvailabilityByte\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"destDataAvailabilityMultiplierBps\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"defaultTokenFeeUSDCents\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"defaultTokenDestGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"defaultTxGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint64\",\"name\":\"gasMultiplierWeiPerEth\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"networkFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"gasPriceStalenessThreshold\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"enforceOutOfOrder\",\"type\":\"bool\"},{\"internalType\":\"bytes4\",\"name\":\"chainFamilySelector\",\"type\":\"bytes4\"}],\"internalType\":\"structFeeQuoter.DestChainConfig\",\"name\":\"destChainConfig\",\"type\":\"tuple\"}],\"internalType\":\"structFeeQuoter.DestChainConfigArgs[]\",\"name\":\"destChainConfigArgs\",\"type\":\"tuple[]\"}],\"name\":\"applyDestChainConfigUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"feeTokensToRemove\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"feeTokensToAdd\",\"type\":\"address[]\"}],\"name\":\"applyFeeTokensUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"premiumMultiplierWeiPerEth\",\"type\":\"uint64\"}],\"internalType\":\"structFeeQuoter.PremiumMultiplierWeiPerEthArgs[]\",\"name\":\"premiumMultiplierWeiPerEthArgs\",\"type\":\"tuple[]\"}],\"name\":\"applyPremiumMultiplierWeiPerEthUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"minFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"deciBps\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destBytesOverhead\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"}],\"internalType\":\"structFeeQuoter.TokenTransferFeeConfig\",\"name\":\"tokenTransferFeeConfig\",\"type\":\"tuple\"}],\"internalType\":\"structFeeQuoter.TokenTransferFeeConfigSingleTokenArgs[]\",\"name\":\"tokenTransferFeeConfigs\",\"type\":\"tuple[]\"}],\"internalType\":\"structFeeQuoter.TokenTransferFeeConfigArgs[]\",\"name\":\"tokenTransferFeeConfigArgs\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"internalType\":\"structFeeQuoter.TokenTransferFeeConfigRemoveArgs[]\",\"name\":\"tokensToUseDefaultFeeConfigs\",\"type\":\"tuple[]\"}],\"name\":\"applyTokenTransferFeeConfigUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"fromToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"fromTokenAmount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"toToken\",\"type\":\"address\"}],\"name\":\"convertTokenAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAllAuthorizedCallers\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"getDestChainConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint16\",\"name\":\"maxNumberOfTokensPerMsg\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"maxDataBytes\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPerMsgGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerPayloadByte\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destDataAvailabilityOverheadGas\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerDataAvailabilityByte\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"destDataAvailabilityMultiplierBps\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"defaultTokenFeeUSDCents\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"defaultTokenDestGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"defaultTxGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint64\",\"name\":\"gasMultiplierWeiPerEth\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"networkFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"gasPriceStalenessThreshold\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"enforceOutOfOrder\",\"type\":\"bool\"},{\"internalType\":\"bytes4\",\"name\":\"chainFamilySelector\",\"type\":\"bytes4\"}],\"internalType\":\"structFeeQuoter.DestChainConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"getDestinationChainGasPrice\",\"outputs\":[{\"components\":[{\"internalType\":\"uint224\",\"name\":\"value\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"timestamp\",\"type\":\"uint32\"}],\"internalType\":\"structInternal.TimestampedPackedUint224\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getFeeTokens\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"getPremiumMultiplierWeiPerEth\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"premiumMultiplierWeiPerEth\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getStaticConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"uint96\",\"name\":\"maxFeeJuelsPerMsg\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"linkToken\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"tokenPriceStalenessThreshold\",\"type\":\"uint32\"}],\"internalType\":\"structFeeQuoter.StaticConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"getTokenAndGasPrices\",\"outputs\":[{\"internalType\":\"uint224\",\"name\":\"tokenPrice\",\"type\":\"uint224\"},{\"internalType\":\"uint224\",\"name\":\"gasPriceValue\",\"type\":\"uint224\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"getTokenPrice\",\"outputs\":[{\"components\":[{\"internalType\":\"uint224\",\"name\":\"value\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"timestamp\",\"type\":\"uint32\"}],\"internalType\":\"structInternal.TimestampedPackedUint224\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"getTokenPriceFeedConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"dataFeedAddress\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"tokenDecimals\",\"type\":\"uint8\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"}],\"internalType\":\"structFeeQuoter.TokenPriceFeedConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"tokens\",\"type\":\"address[]\"}],\"name\":\"getTokenPrices\",\"outputs\":[{\"components\":[{\"internalType\":\"uint224\",\"name\":\"value\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"timestamp\",\"type\":\"uint32\"}],\"internalType\":\"structInternal.TimestampedPackedUint224[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"getTokenTransferFeeConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"minFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"deciBps\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destBytesOverhead\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"}],\"internalType\":\"structFeeQuoter.TokenTransferFeeConfig\",\"name\":\"tokenTransferFeeConfig\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structClient.EVMTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"},{\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"extraArgs\",\"type\":\"bytes\"}],\"internalType\":\"structClient.EVM2AnyMessage\",\"name\":\"message\",\"type\":\"tuple\"}],\"name\":\"getValidatedFee\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"feeTokenAmount\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"getValidatedTokenPrice\",\"outputs\":[{\"internalType\":\"uint224\",\"name\":\"\",\"type\":\"uint224\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"metadata\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"report\",\"type\":\"bytes\"}],\"name\":\"onReport\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"feeTokenAmount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"extraArgs\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"sourcePoolAddress\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"destExecData\",\"type\":\"bytes\"}],\"internalType\":\"structInternal.EVM2AnyTokenTransfer[]\",\"name\":\"onRampTokenTransfers\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structClient.EVMTokenAmount[]\",\"name\":\"sourceTokenAmounts\",\"type\":\"tuple[]\"}],\"name\":\"processMessageArgs\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"msgFeeJuels\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"isOutOfOrderExecution\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"convertedExtraArgs\",\"type\":\"bytes\"},{\"internalType\":\"bytes[]\",\"name\":\"destExecDataPerToken\",\"type\":\"bytes[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"forwarder\",\"type\":\"address\"},{\"internalType\":\"bytes10\",\"name\":\"workflowName\",\"type\":\"bytes10\"},{\"internalType\":\"bytes2\",\"name\":\"reportName\",\"type\":\"bytes2\"},{\"internalType\":\"address\",\"name\":\"workflowOwner\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"isAllowed\",\"type\":\"bool\"}],\"internalType\":\"structKeystoneFeedsPermissionHandler.Permission[]\",\"name\":\"permissions\",\"type\":\"tuple[]\"}],\"name\":\"setReportPermissions\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sourceToken\",\"type\":\"address\"},{\"internalType\":\"uint224\",\"name\":\"usdPerToken\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.TokenPriceUpdate[]\",\"name\":\"tokenPriceUpdates\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint224\",\"name\":\"usdPerUnitGas\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.GasPriceUpdate[]\",\"name\":\"gasPriceUpdates\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.PriceUpdates\",\"name\":\"priceUpdates\",\"type\":\"tuple\"}],\"name\":\"updatePrices\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sourceToken\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"dataFeedAddress\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"tokenDecimals\",\"type\":\"uint8\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"}],\"internalType\":\"structFeeQuoter.TokenPriceFeedConfig\",\"name\":\"feedConfig\",\"type\":\"tuple\"}],\"internalType\":\"structFeeQuoter.TokenPriceFeedUpdate[]\",\"name\":\"tokenPriceFeedUpdates\",\"type\":\"tuple[]\"}],\"name\":\"updateTokenPriceFeeds\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", + Bin: "0x60e06040523480156200001157600080fd5b50604051620078f0380380620078f083398101604081905262000034916200189c565b85336000816200005757604051639b15e16f60e01b815260040160405180910390fd5b600180546001600160a01b0319166001600160a01b03848116919091179091558116156200008a576200008a81620001d0565b5050604080518082018252828152815160008152602080820190935291810191909152620000b8906200024a565b5060208701516001600160a01b03161580620000dc575086516001600160601b0316155b80620000f05750604087015163ffffffff16155b156200010f5760405163d794ef9560e01b815260040160405180910390fd5b6020878101516001600160a01b031660a05287516001600160601b031660805260408089015163ffffffff1660c052805160008152918201905262000155908662000399565b6200016084620004e1565b6200016b81620005d9565b620001768262000a45565b60408051600080825260208201909252620001c391859190620001bc565b6040805180820190915260008082526020820152815260200190600190039081620001945790505b5062000b11565b5050505050505062001b5a565b336001600160a01b03821603620001fa57604051636d6c4ee560e11b815260040160405180910390fd5b600080546001600160a01b0319166001600160a01b03838116918217835560015460405192939116917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b602081015160005b8151811015620002da576000828281518110620002735762000273620019bb565b602090810291909101015190506200028d60028262000e97565b15620002d0576040516001600160a01b03821681527fc3803387881faad271c47728894e3e36fac830ffc8602ca6fc07733cbda775809060200160405180910390a15b5060010162000252565b50815160005b815181101562000393576000828281518110620003015762000301620019bb565b6020026020010151905060006001600160a01b0316816001600160a01b0316036200033f576040516342bcdf7f60e11b815260040160405180910390fd5b6200034c60028262000eb7565b506040516001600160a01b03821681527feb1b9b92e50b7f88f9ff25d56765095ac6e91540eee214906f4036a908ffbdef9060200160405180910390a150600101620002e0565b50505050565b60005b82518110156200043a57620003d8838281518110620003bf57620003bf620019bb565b6020026020010151600b62000ece60201b90919060201c565b156200043157828181518110620003f357620003f3620019bb565b60200260200101516001600160a01b03167f1795838dc8ab2ffc5f431a1729a6afa0b587f982f7b2be0b9d7187a1ef547f9160405160405180910390a25b6001016200039c565b5060005b8151811015620004dc576200047a828281518110620004615762000461620019bb565b6020026020010151600b62000eb760201b90919060201c565b15620004d357818181518110620004955762000495620019bb565b60200260200101516001600160a01b03167fdf1b1bd32a69711488d71554706bb130b1fc63a5fa1a2cd85e8440f84065ba2360405160405180910390a25b6001016200043e565b505050565b60005b8151811015620005d5576000828281518110620005055762000505620019bb565b6020908102919091018101518051818301516001600160a01b0380831660008181526007875260409081902084518154868a0180518589018051949098166001600160a81b03199093168317600160a01b60ff928316021760ff60a81b1916600160a81b9415159490940293909317909355835190815291511697810197909752915115159186019190915292945090929091907fe6a7a17d710bf0b2cd05e5397dc6f97a5da4ee79e31e234bf5f965ee2bd9a5bf9060600160405180910390a2505050806001019050620004e4565b5050565b60005b8151811015620005d5576000828281518110620005fd57620005fd620019bb565b6020026020010151905060008383815181106200061e576200061e620019bb565b6020026020010151600001519050600082602001519050816001600160401b03166000148062000657575061016081015163ffffffff16155b806200067957506102008101516001600160e01b031916630a04b54b60e21b14155b80620006995750806060015163ffffffff1681610160015163ffffffff16115b15620006c85760405163c35aa79d60e01b81526001600160401b03831660048201526024015b60405180910390fd5b6001600160401b038216600090815260096020526040812060010154600160a81b900460e01b6001600160e01b03191690036200074857816001600160401b03167f525e3d4e0c31cef19cf9426af8d2c0ddd2d576359ca26bed92aac5fadda46265826040516200073a9190620019d1565b60405180910390a26200078c565b816001600160401b03167f283b699f411baff8f1c29fe49f32a828c8151596244b8e7e4c164edd6569a83582604051620007839190620019d1565b60405180910390a25b8060096000846001600160401b03166001600160401b0316815260200190815260200160002060008201518160000160006101000a81548160ff02191690831515021790555060208201518160000160016101000a81548161ffff021916908361ffff16021790555060408201518160000160036101000a81548163ffffffff021916908363ffffffff16021790555060608201518160000160076101000a81548163ffffffff021916908363ffffffff160217905550608082015181600001600b6101000a81548163ffffffff021916908363ffffffff16021790555060a082015181600001600f6101000a81548161ffff021916908361ffff16021790555060c08201518160000160116101000a81548163ffffffff021916908363ffffffff16021790555060e08201518160000160156101000a81548161ffff021916908361ffff1602179055506101008201518160000160176101000a81548161ffff021916908361ffff1602179055506101208201518160000160196101000a81548161ffff021916908361ffff16021790555061014082015181600001601b6101000a81548163ffffffff021916908363ffffffff1602179055506101608201518160010160006101000a81548163ffffffff021916908363ffffffff1602179055506101808201518160010160046101000a8154816001600160401b0302191690836001600160401b031602179055506101a082015181600101600c6101000a81548163ffffffff021916908363ffffffff1602179055506101c08201518160010160106101000a81548163ffffffff021916908363ffffffff1602179055506101e08201518160010160146101000a81548160ff0219169083151502179055506102008201518160010160156101000a81548163ffffffff021916908360e01c0217905550905050505050806001019050620005dc565b60005b8151811015620005d557600082828151811062000a695762000a69620019bb565b6020026020010151600001519050600083838151811062000a8e5762000a8e620019bb565b6020908102919091018101518101516001600160a01b03841660008181526008845260409081902080546001600160401b0319166001600160401b0385169081179091559051908152919350917fbb77da6f7210cdd16904228a9360133d1d7dfff99b1bc75f128da5b53e28f97d910160405180910390a2505060010162000a48565b60005b825181101562000dd157600083828151811062000b355762000b35620019bb565b6020026020010151905060008160000151905060005b82602001515181101562000dc25760008360200151828151811062000b745762000b74620019bb565b602002602001015160200151905060008460200151838151811062000b9d5762000b9d620019bb565b6020026020010151600001519050816020015163ffffffff16826000015163ffffffff161062000bf857815160208301516040516305a7b3d160e11b815263ffffffff928316600482015291166024820152604401620006bf565b602063ffffffff16826080015163ffffffff16101562000c495760808201516040516312766e0160e11b81526001600160a01b038316600482015263ffffffff9091166024820152604401620006bf565b6001600160401b0384166000818152600a602090815260408083206001600160a01b0386168085529083529281902086518154938801518389015160608a015160808b015160a08c01511515600160901b0260ff60901b1963ffffffff928316600160701b021664ffffffffff60701b199383166a01000000000000000000000263ffffffff60501b1961ffff90961668010000000000000000029590951665ffffffffffff60401b19968416640100000000026001600160401b0319909b16939097169290921798909817939093169390931717919091161792909217909155519091907f94967ae9ea7729ad4f54021c1981765d2b1d954f7c92fbec340aa0a54f46b8b59062000daf908690600060c08201905063ffffffff80845116835280602085015116602084015261ffff60408501511660408401528060608501511660608401528060808501511660808401525060a0830151151560a083015292915050565b60405180910390a3505060010162000b4b565b50505080600101905062000b14565b5060005b8151811015620004dc57600082828151811062000df65762000df6620019bb565b6020026020010151600001519050600083838151811062000e1b5762000e1b620019bb565b6020908102919091018101518101516001600160401b0384166000818152600a845260408082206001600160a01b038516808452955280822080546001600160981b03191690555192945090917f4de5b1bcbca6018c11303a2c3f4a4b4f22a1c741d8c4ba430d246ac06c5ddf8b9190a3505060010162000dd5565b600062000eae836001600160a01b03841662000ee5565b90505b92915050565b600062000eae836001600160a01b03841662000fe9565b600062000eae836001600160a01b0384166200103b565b6000818152600183016020526040812054801562000fde57600062000f0c60018362001b22565b855490915060009062000f229060019062001b22565b905081811462000f8e57600086600001828154811062000f465762000f46620019bb565b906000526020600020015490508087600001848154811062000f6c5762000f6c620019bb565b6000918252602080832090910192909255918252600188019052604090208390555b855486908062000fa25762000fa262001b44565b60019003818190600052602060002001600090559055856001016000868152602001908152602001600020600090556001935050505062000eb1565b600091505062000eb1565b6000818152600183016020526040812054620010325750815460018181018455600084815260208082209093018490558454848252828601909352604090209190915562000eb1565b50600062000eb1565b6000818152600183016020526040812054801562000fde5760006200106260018362001b22565b8554909150600090620010789060019062001b22565b905080821462000f8e57600086600001828154811062000f465762000f46620019bb565b634e487b7160e01b600052604160045260246000fd5b604051606081016001600160401b0381118282101715620010d757620010d76200109c565b60405290565b604080519081016001600160401b0381118282101715620010d757620010d76200109c565b60405160c081016001600160401b0381118282101715620010d757620010d76200109c565b60405161022081016001600160401b0381118282101715620010d757620010d76200109c565b604051601f8201601f191681016001600160401b03811182821017156200117857620011786200109c565b604052919050565b80516001600160a01b03811681146200119857600080fd5b919050565b805163ffffffff811681146200119857600080fd5b600060608284031215620011c557600080fd5b620011cf620010b2565b82519091506001600160601b0381168114620011ea57600080fd5b8152620011fa6020830162001180565b60208201526200120d604083016200119d565b604082015292915050565b60006001600160401b038211156200123457620012346200109c565b5060051b60200190565b600082601f8301126200125057600080fd5b8151602062001269620012638362001218565b6200114d565b8083825260208201915060208460051b8701019350868411156200128c57600080fd5b602086015b84811015620012b357620012a58162001180565b835291830191830162001291565b509695505050505050565b805180151581146200119857600080fd5b600082601f830112620012e157600080fd5b81516020620012f4620012638362001218565b82815260079290921b840181019181810190868411156200131457600080fd5b8286015b84811015620012b3578088036080811215620013345760008081fd5b6200133e620010dd565b620013498362001180565b8152606080601f1984011215620013605760008081fd5b6200136a620010b2565b92506200137987850162001180565b835260408085015160ff81168114620013925760008081fd5b84890152620013a3858301620012be565b90840152508086019190915283529183019160800162001318565b80516001600160401b03811681146200119857600080fd5b805161ffff811681146200119857600080fd5b600082601f830112620013fb57600080fd5b815160206200140e620012638362001218565b82815260059290921b840181019181810190868411156200142e57600080fd5b8286015b84811015620012b35780516001600160401b03808211156200145357600080fd5b908801906040601f19838c0381018213156200146e57600080fd5b62001478620010dd565b62001485898601620013be565b815282850151848111156200149957600080fd5b8086019550508c603f860112620014af57600080fd5b888501519350620014c4620012638562001218565b84815260e09094028501830193898101908e861115620014e357600080fd5b958401955b85871015620015bc57868f0360e08112156200150357600080fd5b6200150d620010dd565b620015188962001180565b815260c086830112156200152b57600080fd5b6200153562001102565b9150620015448d8a016200119d565b825262001553878a016200119d565b8d8301526200156560608a01620013d6565b878301526200157760808a016200119d565b60608301526200158a60a08a016200119d565b60808301526200159d60c08a01620012be565b60a0830152808d0191909152825260e09690960195908a0190620014e8565b828b01525087525050509284019250830162001432565b600082601f830112620015e557600080fd5b81516020620015f8620012638362001218565b82815260069290921b840181019181810190868411156200161857600080fd5b8286015b84811015620012b35760408189031215620016375760008081fd5b62001641620010dd565b6200164c8262001180565b81526200165b858301620013be565b818601528352918301916040016200161c565b80516001600160e01b0319811681146200119857600080fd5b600082601f8301126200169957600080fd5b81516020620016ac620012638362001218565b8281526102409283028501820192828201919087851115620016cd57600080fd5b8387015b858110156200188f5780890382811215620016ec5760008081fd5b620016f6620010dd565b6200170183620013be565b815261022080601f1984011215620017195760008081fd5b6200172362001127565b925062001732888501620012be565b8352604062001743818601620013d6565b898501526060620017568187016200119d565b82860152608091506200176b8287016200119d565b9085015260a06200177e8682016200119d565b8286015260c0915062001793828701620013d6565b9085015260e0620017a68682016200119d565b828601526101009150620017bc828701620013d6565b90850152610120620017d0868201620013d6565b828601526101409150620017e6828701620013d6565b90850152610160620017fa8682016200119d565b828601526101809150620018108287016200119d565b908501526101a062001824868201620013be565b828601526101c091506200183a8287016200119d565b908501526101e06200184e8682016200119d565b82860152610200915062001864828701620012be565b90850152620018758583016200166e565b9084015250808701919091528452928401928101620016d1565b5090979650505050505050565b6000806000806000806000610120888a031215620018b957600080fd5b620018c58989620011b2565b60608901519097506001600160401b0380821115620018e357600080fd5b620018f18b838c016200123e565b975060808a01519150808211156200190857600080fd5b620019168b838c016200123e565b965060a08a01519150808211156200192d57600080fd5b6200193b8b838c01620012cf565b955060c08a01519150808211156200195257600080fd5b620019608b838c01620013e9565b945060e08a01519150808211156200197757600080fd5b620019858b838c01620015d3565b93506101008a01519150808211156200199d57600080fd5b50620019ac8a828b0162001687565b91505092959891949750929550565b634e487b7160e01b600052603260045260246000fd5b81511515815261022081016020830151620019f2602084018261ffff169052565b50604083015162001a0b604084018263ffffffff169052565b50606083015162001a24606084018263ffffffff169052565b50608083015162001a3d608084018263ffffffff169052565b5060a083015162001a5460a084018261ffff169052565b5060c083015162001a6d60c084018263ffffffff169052565b5060e083015162001a8460e084018261ffff169052565b506101008381015161ffff9081169184019190915261012080850151909116908301526101408084015163ffffffff9081169184019190915261016080850151821690840152610180808501516001600160401b0316908401526101a0808501518216908401526101c080850151909116908301526101e080840151151590830152610200928301516001600160e01b031916929091019190915290565b8181038181111562000eb157634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052603160045260246000fd5b60805160a05160c051615d4362001bad600039600081816102fa01526117ba0152600081816102be01528181610ed50152610f3501526000818161028a01528181610f5e0152610fce0152615d436000f3fe608060405234801561001057600080fd5b50600436106101d95760003560e01c806379ba509711610104578063bf78e03f116100a2578063d8694ccd11610071578063d8694ccd14610ad6578063f2fde38b14610ae9578063fbe3f77814610afc578063ffdb4b3714610b0f57600080fd5b8063bf78e03f146109d5578063cdc73d5114610ab3578063d02641a014610abb578063d63d3af214610ace57600080fd5b806382b49eb0116100de57806382b49eb0146108175780638da5cb5b1461098757806391a2749a146109af578063a69c64c0146109c257600080fd5b806379ba5097146107e95780637afac322146107f1578063805f21321461080457600080fd5b806341ed29e71161017c578063514e8cff1161014b578063514e8cff146104845780636cb5f3dd146105275780636def4ce71461053a578063770e2dc4146107d657600080fd5b806341ed29e7146103ee578063430d138c1461040157806345ac924d146104245780634ab35b0b1461044457600080fd5b8063181f5a77116101b8578063181f5a77146103735780632451a627146103bc578063325c868e146103d15780633937306f146103d957600080fd5b806241e5be146101de578063061877e31461020457806306285c691461025d575b600080fd5b6101f16101ec36600461440b565b610b57565b6040519081526020015b60405180910390f35b610244610212366004614447565b73ffffffffffffffffffffffffffffffffffffffff1660009081526008602052604090205467ffffffffffffffff1690565b60405167ffffffffffffffff90911681526020016101fb565b610327604080516060810182526000808252602082018190529181019190915260405180606001604052807f00000000000000000000000000000000000000000000000000000000000000006bffffffffffffffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000000063ffffffff16815250905090565b6040805182516bffffffffffffffffffffffff16815260208084015173ffffffffffffffffffffffffffffffffffffffff16908201529181015163ffffffff16908201526060016101fb565b6103af6040518060400160405280601381526020017f46656551756f74657220312e362e302d6465760000000000000000000000000081525081565b6040516101fb91906144c6565b6103c4610bc5565b6040516101fb91906144d9565b6101f1602481565b6103ec6103e7366004614533565b610bd6565b005b6103ec6103fc3660046146df565b610e8b565b61041461040f3660046148ca565b610ecd565b6040516101fb94939291906149be565b610437610432366004614a5d565b6110dd565b6040516101fb9190614a9f565b610457610452366004614447565b6111a8565b6040517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff90911681526020016101fb565b61051a610492366004614b1a565b60408051808201909152600080825260208201525067ffffffffffffffff166000908152600560209081526040918290208251808401909352547bffffffffffffffffffffffffffffffffffffffffffffffffffffffff811683527c0100000000000000000000000000000000000000000000000000000000900463ffffffff169082015290565b6040516101fb9190614b35565b6103ec610535366004614bc6565b6111b3565b6107c9610548366004614b1a565b6040805161022081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e08101829052610100810182905261012081018290526101408101829052610160810182905261018081018290526101a081018290526101c081018290526101e081018290526102008101919091525067ffffffffffffffff908116600090815260096020908152604091829020825161022081018452815460ff8082161515835261ffff61010080840482169685019690965263ffffffff630100000084048116978501979097526701000000000000008304871660608501526b0100000000000000000000008304871660808501526f010000000000000000000000000000008304811660a0850152710100000000000000000000000000000000008304871660c08501527501000000000000000000000000000000000000000000808404821660e08087019190915277010000000000000000000000000000000000000000000000850483169786019790975279010000000000000000000000000000000000000000000000000084049091166101208501527b01000000000000000000000000000000000000000000000000000000909204861661014084015260019093015480861661016084015264010000000081049096166101808301526c01000000000000000000000000860485166101a083015270010000000000000000000000000000000086049094166101c082015274010000000000000000000000000000000000000000850490911615156101e08201527fffffffff0000000000000000000000000000000000000000000000000000000092909304901b1661020082015290565b6040516101fb9190614de6565b6103ec6107e4366004614fe4565b6111c7565b6103ec6111d9565b6103ec6107ff3660046152fe565b6112a7565b6103ec610812366004615362565b6112b9565b6109276108253660046153ce565b6040805160c081018252600080825260208201819052918101829052606081018290526080810182905260a08101919091525067ffffffffffffffff919091166000908152600a6020908152604080832073ffffffffffffffffffffffffffffffffffffffff94909416835292815290829020825160c081018452905463ffffffff8082168352640100000000820481169383019390935268010000000000000000810461ffff16938201939093526a01000000000000000000008304821660608201526e01000000000000000000000000000083049091166080820152720100000000000000000000000000000000000090910460ff16151560a082015290565b6040516101fb9190600060c08201905063ffffffff80845116835280602085015116602084015261ffff60408501511660408401528060608501511660608401528060808501511660808401525060a0830151151560a083015292915050565b60015460405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101fb565b6103ec6109bd3660046153f8565b6116f5565b6103ec6109d0366004615489565b611706565b610a766109e3366004614447565b60408051606080820183526000808352602080840182905292840181905273ffffffffffffffffffffffffffffffffffffffff9485168152600783528390208351918201845254938416815260ff74010000000000000000000000000000000000000000850481169282019290925275010000000000000000000000000000000000000000009093041615159082015290565b60408051825173ffffffffffffffffffffffffffffffffffffffff16815260208084015160ff1690820152918101511515908201526060016101fb565b6103c4611717565b61051a610ac9366004614447565b611723565b6101f1601281565b6101f1610ae436600461554e565b6118d8565b6103ec610af7366004614447565b611e10565b6103ec610b0a3660046155b2565b611e21565b610b22610b1d3660046156d2565b611e32565b604080517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff9384168152929091166020830152016101fb565b6000610b6282611eea565b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16610b8985611eea565b610bb1907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff168561572b565b610bbb9190615742565b90505b9392505050565b6060610bd16002611f84565b905090565b610bde611f91565b6000610bea828061577d565b9050905060005b81811015610d34576000610c05848061577d565b83818110610c1557610c156157e5565b905060400201803603810190610c2b9190615840565b604080518082018252602080840180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff908116845263ffffffff42818116858701908152885173ffffffffffffffffffffffffffffffffffffffff9081166000908152600690975295889020965190519092167c010000000000000000000000000000000000000000000000000000000002919092161790935584519051935194955016927f52f50aa6d1a95a4595361ecf953d095f125d442e4673716dede699e049de148a92610d239290917bffffffffffffffffffffffffffffffffffffffffffffffffffffffff929092168252602082015260400190565b60405180910390a250600101610bf1565b506000610d44602084018461577d565b9050905060005b81811015610e85576000610d62602086018661577d565b83818110610d7257610d726157e5565b905060400201803603810190610d88919061587d565b604080518082018252602080840180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff908116845263ffffffff42818116858701908152885167ffffffffffffffff9081166000908152600590975295889020965190519092167c010000000000000000000000000000000000000000000000000000000002919092161790935584519051935194955016927fdd84a3fa9ef9409f550d54d6affec7e9c480c878c6ab27b78912a03e1b371c6e92610e749290917bffffffffffffffffffffffffffffffffffffffffffffffffffffffff929092168252602082015260400190565b60405180910390a250600101610d4b565b50505050565b610e93611fd6565b60005b8151811015610ec957610ec1828281518110610eb457610eb46157e5565b6020026020010151612027565b600101610e96565b5050565b6000806060807f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168c73ffffffffffffffffffffffffffffffffffffffff1603610f2e578a9350610f5c565b610f598c8c7f0000000000000000000000000000000000000000000000000000000000000000610b57565b93505b7f00000000000000000000000000000000000000000000000000000000000000006bffffffffffffffffffffffff16841115611000576040517f6a92a483000000000000000000000000000000000000000000000000000000008152600481018590526bffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001660248201526044015b60405180910390fd5b67ffffffffffffffff8d1660009081526009602052604081206001015463ffffffff169061102f8c8c846121f9565b9050806020015194506110458f8b8b8b8b6123a2565b925085856110c5836040805182516024820152602092830151151560448083019190915282518083039091018152606490910190915290810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f181dcf100000000000000000000000000000000000000000000000000000000017905290565b95509550955050509950995099509995505050505050565b60608160008167ffffffffffffffff8111156110fb576110fb61456e565b60405190808252806020026020018201604052801561114057816020015b60408051808201909152600080825260208201528152602001906001900390816111195790505b50905060005b8281101561119d57611178868683818110611163576111636157e5565b9050602002016020810190610ac99190614447565b82828151811061118a5761118a6157e5565b6020908102919091010152600101611146565b509150505b92915050565b60006111a282611eea565b6111bb611fd6565b6111c481612725565b50565b6111cf611fd6565b610ec98282612bf7565b60005473ffffffffffffffffffffffffffffffffffffffff16331461122a576040517f02b543c600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000008082163390811790935560008054909116815560405173ffffffffffffffffffffffffffffffffffffffff909216929183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b6112af611fd6565b610ec9828261306d565b60008060006112fd87878080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506131b492505050565b92509250925061130f338385846131cf565b600061131d858701876158a0565b905060005b81518110156116ea57600060076000848481518110611343576113436157e5565b6020908102919091018101515173ffffffffffffffffffffffffffffffffffffffff908116835282820193909352604091820160002082516060810184529054938416815260ff740100000000000000000000000000000000000000008504811692820192909252750100000000000000000000000000000000000000000090930416151590820181905290915061143e578282815181106113e7576113e76157e5565b6020908102919091010151516040517f06439c6b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091166004820152602401610ff7565b600061148b6012836020015186868151811061145c5761145c6157e5565b6020026020010151602001517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16613327565b9050600660008585815181106114a3576114a36157e5565b60200260200101516000015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600001601c9054906101000a900463ffffffff1663ffffffff16848481518110611515576115156157e5565b60200260200101516040015163ffffffff1610156115345750506116e2565b6040518060400160405280827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff168152602001858581518110611575576115756157e5565b60200260200101516040015163ffffffff16815250600660008686815181106115a0576115a06157e5565b6020908102919091018101515173ffffffffffffffffffffffffffffffffffffffff168252818101929092526040016000208251929091015163ffffffff167c0100000000000000000000000000000000000000000000000000000000027bffffffffffffffffffffffffffffffffffffffffffffffffffffffff9092169190911790558351849084908110611638576116386157e5565b60200260200101516000015173ffffffffffffffffffffffffffffffffffffffff167f52f50aa6d1a95a4595361ecf953d095f125d442e4673716dede699e049de148a8286868151811061168e5761168e6157e5565b6020026020010151604001516040516116d79291907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff92909216825263ffffffff16602082015260400190565b60405180910390a250505b600101611322565b505050505050505050565b6116fd611fd6565b6111c4816133ea565b61170e611fd6565b6111c481613576565b6060610bd1600b611f84565b604080518082019091526000808252602082015273ffffffffffffffffffffffffffffffffffffffff82166000908152600660209081526040918290208251808401909352547bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8116835263ffffffff7c010000000000000000000000000000000000000000000000000000000090910481169183018290527f000000000000000000000000000000000000000000000000000000000000000016906117e59042615967565b10156117f15792915050565b73ffffffffffffffffffffffffffffffffffffffff80841660009081526007602090815260409182902082516060810184529054938416815260ff74010000000000000000000000000000000000000000850481169282019290925275010000000000000000000000000000000000000000009093041615801591830191909152806118925750805173ffffffffffffffffffffffffffffffffffffffff16155b1561189e575092915050565b60006118a982613660565b9050826020015163ffffffff16816020015163ffffffff1610156118cd57826118cf565b805b95945050505050565b67ffffffffffffffff8083166000908152600960209081526040808320815161022081018352815460ff808216151580845261ffff61010080850482169886019890985263ffffffff630100000085048116978601979097526701000000000000008404871660608601526b0100000000000000000000008404871660808601526f010000000000000000000000000000008404811660a0860152710100000000000000000000000000000000008404871660c08601527501000000000000000000000000000000000000000000808504821660e08088019190915277010000000000000000000000000000000000000000000000860483169987019990995279010000000000000000000000000000000000000000000000000085049091166101208601527b01000000000000000000000000000000000000000000000000000000909304861661014085015260019094015480861661016085015264010000000081049098166101808401526c01000000000000000000000000880485166101a084015270010000000000000000000000000000000088049094166101c083015274010000000000000000000000000000000000000000870490931615156101e08201527fffffffff000000000000000000000000000000000000000000000000000000009290950490921b16610200840152909190611b12576040517f99ac52f200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff85166004820152602401610ff7565b611b2d611b256080850160608601614447565b600b906137f2565b611b8c57611b416080840160608501614447565b6040517f2502348c00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091166004820152602401610ff7565b6000611b9b604085018561577d565b9150611bf7905082611bb0602087018761597a565b905083611bbd888061597a565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061382192505050565b6000611c11611c0c6080870160608801614447565b611eea565b90506000611c2487856101c001516138de565b9050600080808515611c6457611c58878b611c4560808d0160608e01614447565b88611c5360408f018f61577d565b6139de565b91945092509050611c84565b6101a0870151611c819063ffffffff16662386f26fc1000061572b565b92505b61010087015160009061ffff1615611cc857611cc5886dffffffffffffffffffffffffffff607088901c16611cbc60208e018e61597a565b90508a86613cb6565b90505b61018088015160009067ffffffffffffffff16611cf1611ceb60808e018e61597a565b8c613d66565b600001518563ffffffff168b60a0015161ffff168e8060200190611d15919061597a565b611d2092915061572b565b8c6080015163ffffffff16611d3591906159df565b611d3f91906159df565b611d4991906159df565b611d63906dffffffffffffffffffffffffffff891661572b565b611d6d919061572b565b9050867bffffffffffffffffffffffffffffffffffffffffffffffffffffffff168282600860008f6060016020810190611da79190614447565b73ffffffffffffffffffffffffffffffffffffffff168152602081019190915260400160002054611de29067ffffffffffffffff168961572b565b611dec91906159df565b611df691906159df565b611e009190615742565b9c9b505050505050505050505050565b611e18611fd6565b6111c481613e27565b611e29611fd6565b6111c481613eeb565b67ffffffffffffffff8116600090815260096020526040812054819060ff16611e93576040517f99ac52f200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84166004820152602401610ff7565b611e9c84611eea565b67ffffffffffffffff8416600090815260096020526040902060010154611ede908590700100000000000000000000000000000000900463ffffffff166138de565b915091505b9250929050565b600080611ef683611723565b9050806020015163ffffffff1660001480611f2e575080517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16155b15611f7d576040517f06439c6b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff84166004820152602401610ff7565b5192915050565b60606000610bbe8361403d565b611f9c6002336137f2565b611fd4576040517fd86ad9cf000000000000000000000000000000000000000000000000000000008152336004820152602401610ff7565b565b60015473ffffffffffffffffffffffffffffffffffffffff163314611fd4576040517f2b5c74de00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006120e082600001518360600151846020015185604001516040805173ffffffffffffffffffffffffffffffffffffffff80871660208301528516918101919091527fffffffffffffffffffff00000000000000000000000000000000000000000000831660608201527fffff0000000000000000000000000000000000000000000000000000000000008216608082015260009060a001604051602081830303815290604052805190602001209050949350505050565b60808301516000828152600460205260409081902080549215157fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00909316929092179091555190915081907f32a4ba3fa3351b11ad555d4c8ec70a744e8705607077a946807030d64b6ab1a3906121ed908590600060a08201905073ffffffffffffffffffffffffffffffffffffffff8084511683527fffffffffffffffffffff0000000000000000000000000000000000000000000060208501511660208401527fffff00000000000000000000000000000000000000000000000000000000000060408501511660408401528060608501511660608401525060808301511515608083015292915050565b60405180910390a25050565b6040805180820190915260008082526020820152600083900361223a57506040805180820190915267ffffffffffffffff8216815260006020820152610bbe565b600061224684866159f2565b905060006122578560048189615a38565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509293505050507fffffffff0000000000000000000000000000000000000000000000000000000082167fe7e230f000000000000000000000000000000000000000000000000000000000016122f457808060200190518101906122eb9190615a62565b92505050610bbe565b7f6859a837000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008316016123705760405180604001604052808280602001905181019061235c9190615a8e565b815260006020909101529250610bbe915050565b6040517f5247fdce00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff808616600090815260096020526040902060010154606091750100000000000000000000000000000000000000000090910460e01b9085908111156123f2576123f261456e565b60405190808252806020026020018201604052801561242557816020015b60608152602001906001900390816124105790505b50915060005b8581101561271a576000858583818110612447576124476157e5565b61245d9260206040909202019081019150614447565b90506000888884818110612473576124736157e5565b90506020028101906124859190615aa7565b61249390604081019061597a565b91505060208111156125435767ffffffffffffffff8a166000908152600a6020908152604080832073ffffffffffffffffffffffffffffffffffffffff861684529091529020546e010000000000000000000000000000900463ffffffff16811115612543576040517f36f536ca00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83166004820152602401610ff7565b6125b3848a8a86818110612559576125596157e5565b905060200281019061256b9190615aa7565b61257990602081019061597a565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061409992505050565b67ffffffffffffffff8a166000908152600a6020908152604080832073ffffffffffffffffffffffffffffffffffffffff861684528252808320815160c081018352905463ffffffff8082168352640100000000820481169483019490945268010000000000000000810461ffff16928201929092526a01000000000000000000008204831660608201526e010000000000000000000000000000820490921660808301527201000000000000000000000000000000000000900460ff16151560a082018190529091906126c55767ffffffffffffffff8c166000908152600960205260409020547b01000000000000000000000000000000000000000000000000000000900463ffffffff166126cb565b81606001515b6040805163ffffffff8316602082015291925001604051602081830303815290604052878681518110612700576127006157e5565b60200260200101819052505050505080600101905061242b565b505095945050505050565b60005b8151811015610ec9576000828281518110612745576127456157e5565b602002602001015190506000838381518110612763576127636157e5565b60200260200101516000015190506000826020015190508167ffffffffffffffff166000148061279c575061016081015163ffffffff16155b806127ee57506102008101517fffffffff00000000000000000000000000000000000000000000000000000000167f2812d52c0000000000000000000000000000000000000000000000000000000014155b8061280d5750806060015163ffffffff1681610160015163ffffffff16115b15612850576040517fc35aa79d00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff83166004820152602401610ff7565b67ffffffffffffffff82166000908152600960205260408120600101547501000000000000000000000000000000000000000000900460e01b7fffffffff000000000000000000000000000000000000000000000000000000001690036128f8578167ffffffffffffffff167f525e3d4e0c31cef19cf9426af8d2c0ddd2d576359ca26bed92aac5fadda46265826040516128eb9190614de6565b60405180910390a261293b565b8167ffffffffffffffff167f283b699f411baff8f1c29fe49f32a828c8151596244b8e7e4c164edd6569a835826040516129329190614de6565b60405180910390a25b80600960008467ffffffffffffffff1667ffffffffffffffff16815260200190815260200160002060008201518160000160006101000a81548160ff02191690831515021790555060208201518160000160016101000a81548161ffff021916908361ffff16021790555060408201518160000160036101000a81548163ffffffff021916908363ffffffff16021790555060608201518160000160076101000a81548163ffffffff021916908363ffffffff160217905550608082015181600001600b6101000a81548163ffffffff021916908363ffffffff16021790555060a082015181600001600f6101000a81548161ffff021916908361ffff16021790555060c08201518160000160116101000a81548163ffffffff021916908363ffffffff16021790555060e08201518160000160156101000a81548161ffff021916908361ffff1602179055506101008201518160000160176101000a81548161ffff021916908361ffff1602179055506101208201518160000160196101000a81548161ffff021916908361ffff16021790555061014082015181600001601b6101000a81548163ffffffff021916908363ffffffff1602179055506101608201518160010160006101000a81548163ffffffff021916908363ffffffff1602179055506101808201518160010160046101000a81548167ffffffffffffffff021916908367ffffffffffffffff1602179055506101a082015181600101600c6101000a81548163ffffffff021916908363ffffffff1602179055506101c08201518160010160106101000a81548163ffffffff021916908363ffffffff1602179055506101e08201518160010160146101000a81548160ff0219169083151502179055506102008201518160010160156101000a81548163ffffffff021916908360e01c0217905550905050505050806001019050612728565b60005b8251811015612f84576000838281518110612c1757612c176157e5565b6020026020010151905060008160000151905060005b826020015151811015612f7657600083602001518281518110612c5257612c526157e5565b6020026020010151602001519050600084602001518381518110612c7857612c786157e5565b6020026020010151600001519050816020015163ffffffff16826000015163ffffffff1610612cea57815160208301516040517f0b4f67a200000000000000000000000000000000000000000000000000000000815263ffffffff928316600482015291166024820152604401610ff7565b602063ffffffff16826080015163ffffffff161015612d5f5760808201516040517f24ecdc0200000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8316600482015263ffffffff9091166024820152604401610ff7565b67ffffffffffffffff84166000818152600a6020908152604080832073ffffffffffffffffffffffffffffffffffffffff86168085529083529281902086518154938801518389015160608a015160808b015160a08c015115157201000000000000000000000000000000000000027fffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffff63ffffffff9283166e01000000000000000000000000000002167fffffffffffffffffffffffffff0000000000ffffffffffffffffffffffffffff9383166a0100000000000000000000027fffffffffffffffffffffffffffffffffffff00000000ffffffffffffffffffff61ffff9096166801000000000000000002959095167fffffffffffffffffffffffffffffffffffff000000000000ffffffffffffffff968416640100000000027fffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000909b16939097169290921798909817939093169390931717919091161792909217909155519091907f94967ae9ea7729ad4f54021c1981765d2b1d954f7c92fbec340aa0a54f46b8b590612f64908690600060c08201905063ffffffff80845116835280602085015116602084015261ffff60408501511660408401528060608501511660608401528060808501511660808401525060a0830151151560a083015292915050565b60405180910390a35050600101612c2d565b505050806001019050612bfa565b5060005b8151811015613068576000828281518110612fa557612fa56157e5565b60200260200101516000015190506000838381518110612fc757612fc76157e5565b60209081029190910181015181015167ffffffffffffffff84166000818152600a8452604080822073ffffffffffffffffffffffffffffffffffffffff8516808452955280822080547fffffffffffffffffffffffffff000000000000000000000000000000000000001690555192945090917f4de5b1bcbca6018c11303a2c3f4a4b4f22a1c741d8c4ba430d246ac06c5ddf8b9190a35050600101612f88565b505050565b60005b8251811015613110576130a683828151811061308e5761308e6157e5565b6020026020010151600b6140eb90919063ffffffff16565b15613108578281815181106130bd576130bd6157e5565b602002602001015173ffffffffffffffffffffffffffffffffffffffff167f1795838dc8ab2ffc5f431a1729a6afa0b587f982f7b2be0b9d7187a1ef547f9160405160405180910390a25b600101613070565b5060005b81518110156130685761314a828281518110613132576131326157e5565b6020026020010151600b61410d90919063ffffffff16565b156131ac57818181518110613161576131616157e5565b602002602001015173ffffffffffffffffffffffffffffffffffffffff167fdf1b1bd32a69711488d71554706bb130b1fc63a5fa1a2cd85e8440f84065ba2360405160405180910390a25b600101613114565b6040810151604a820151605e90920151909260609290921c91565b6040805173ffffffffffffffffffffffffffffffffffffffff868116602080840191909152908616828401527fffffffffffffffffffff00000000000000000000000000000000000000000000851660608301527fffff00000000000000000000000000000000000000000000000000000000000084166080808401919091528351808403909101815260a09092018352815191810191909120600081815260049092529190205460ff16613320576040517f097e17ff00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8087166004830152851660248201527fffffffffffffffffffff00000000000000000000000000000000000000000000841660448201527fffff00000000000000000000000000000000000000000000000000000000000083166064820152608401610ff7565b5050505050565b6000806133348486615ae5565b9050600060248260ff16111561336e57613352602460ff8416615967565b61335d90600a615c1e565b6133679085615742565b9050613394565b61337c60ff83166024615967565b61338790600a615c1e565b613391908561572b565b90505b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8111156118cf576040517f10cb51d100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b602081015160005b815181101561348557600082828151811061340f5761340f6157e5565b6020026020010151905061342d81600261412f90919063ffffffff16565b1561347c5760405173ffffffffffffffffffffffffffffffffffffffff821681527fc3803387881faad271c47728894e3e36fac830ffc8602ca6fc07733cbda775809060200160405180910390a15b506001016133f2565b50815160005b8151811015610e855760008282815181106134a8576134a86157e5565b60200260200101519050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603613518576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61352360028261410d565b5060405173ffffffffffffffffffffffffffffffffffffffff821681527feb1b9b92e50b7f88f9ff25d56765095ac6e91540eee214906f4036a908ffbdef9060200160405180910390a15060010161348b565b60005b8151811015610ec9576000828281518110613596576135966157e5565b602002602001015160000151905060008383815181106135b8576135b86157e5565b60209081029190910181015181015173ffffffffffffffffffffffffffffffffffffffff841660008181526008845260409081902080547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001667ffffffffffffffff85169081179091559051908152919350917fbb77da6f7210cdd16904228a9360133d1d7dfff99b1bc75f128da5b53e28f97d910160405180910390a25050600101613579565b60408051808201909152600080825260208201526000826000015190506000808273ffffffffffffffffffffffffffffffffffffffff1663feaf968c6040518163ffffffff1660e01b815260040160a060405180830381865afa1580156136cb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906136ef9190615c44565b509350509250506000821215613731576040517f10cb51d100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006137b08473ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015613781573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906137a59190615c94565b876020015185613327565b604080518082019091527bffffffffffffffffffffffffffffffffffffffffffffffffffffffff909116815263ffffffff909216602083015250949350505050565b73ffffffffffffffffffffffffffffffffffffffff811660009081526001830160205260408120541515610bbe565b836040015163ffffffff1683111561387a5760408085015190517f8693378900000000000000000000000000000000000000000000000000000000815263ffffffff909116600482015260248101849052604401610ff7565b836020015161ffff168211156138cf5760208401516040517fd88dddd60000000000000000000000000000000000000000000000000000000081526004810184905261ffff9091166024820152604401610ff7565b610e8584610200015182614099565b67ffffffffffffffff821660009081526005602090815260408083208151808301909252547bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8116825263ffffffff7c0100000000000000000000000000000000000000000000000000000000909104811692820192909252908316156139d6576000816020015163ffffffff16426139739190615967565b90508363ffffffff168111156139d4576040517ff08bcb3e00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8616600482015263ffffffff8516602482015260448101829052606401610ff7565b505b519392505050565b6000808083815b81811015613ca8576000878783818110613a0157613a016157e5565b905060400201803603810190613a179190615cb1565b67ffffffffffffffff8c166000908152600a60209081526040808320845173ffffffffffffffffffffffffffffffffffffffff168452825291829020825160c081018452905463ffffffff8082168352640100000000820481169383019390935268010000000000000000810461ffff16938201939093526a01000000000000000000008304821660608201526e01000000000000000000000000000083049091166080820152720100000000000000000000000000000000000090910460ff16151560a0820181905291925090613b37576101208d0151613b049061ffff16662386f26fc1000061572b565b613b0e90886159df565b96508c610140015186613b219190615cea565b9550613b2e602086615cea565b94505050613ca0565b604081015160009061ffff1615613bf05760008c73ffffffffffffffffffffffffffffffffffffffff16846000015173ffffffffffffffffffffffffffffffffffffffff1614613b93578351613b8c90611eea565b9050613b96565b508a5b620186a0836040015161ffff16613bd88660200151847bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1661415190919063ffffffff16565b613be2919061572b565b613bec9190615742565b9150505b6060820151613bff9088615cea565b9650816080015186613c119190615cea565b8251909650600090613c309063ffffffff16662386f26fc1000061572b565b905080821015613c4f57613c44818a6159df565b985050505050613ca0565b6000836020015163ffffffff16662386f26fc10000613c6e919061572b565b905080831115613c8e57613c82818b6159df565b99505050505050613ca0565b613c98838b6159df565b995050505050505b6001016139e5565b505096509650969350505050565b60008063ffffffff8316613ccc6101208661572b565b613cd8876101e06159df565b613ce291906159df565b613cec91906159df565b905060008760c0015163ffffffff168860e0015161ffff1683613d0f919061572b565b613d1991906159df565b61010089015190915061ffff16613d406dffffffffffffffffffffffffffff89168361572b565b613d4a919061572b565b613d5a90655af3107a400061572b565b98975050505050505050565b60408051808201909152600080825260208201526000613d92858585610160015163ffffffff166121f9565b9050826060015163ffffffff1681600001511115613ddc576040517f4c4fc93a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b826101e001518015613df057508060200151155b15610bbb576040517fee433e9900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff821603613e76576040517fdad89dca00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff838116918217835560015460405192939116917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b60005b8151811015610ec9576000828281518110613f0b57613f0b6157e5565b60209081029190910181015180518183015173ffffffffffffffffffffffffffffffffffffffff80831660008181526007875260409081902084518154868a0180518589018051949098167fffffffffffffffffffffff00000000000000000000000000000000000000000090931683177401000000000000000000000000000000000000000060ff92831602177fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff1675010000000000000000000000000000000000000000009415159490940293909317909355835190815291511697810197909752915115159186019190915292945090929091907fe6a7a17d710bf0b2cd05e5397dc6f97a5da4ee79e31e234bf5f965ee2bd9a5bf9060600160405180910390a2505050806001019050613eee565b60608160000180548060200260200160405190810160405280929190818152602001828054801561408d57602002820191906000526020600020905b815481526020019060010190808311614079575b50505050509050919050565b7fd7ed2ad4000000000000000000000000000000000000000000000000000000007fffffffff00000000000000000000000000000000000000000000000000000000831601610ec9576130688161418e565b6000610bbe8373ffffffffffffffffffffffffffffffffffffffff8416614241565b6000610bbe8373ffffffffffffffffffffffffffffffffffffffff841661433b565b6000610bbe8373ffffffffffffffffffffffffffffffffffffffff841661438a565b6000670de0b6b3a7640000614184837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff861661572b565b610bbe9190615742565b600081516020146141cd57816040517f8d666f60000000000000000000000000000000000000000000000000000000008152600401610ff791906144c6565b6000828060200190518101906141e39190615a8e565b905073ffffffffffffffffffffffffffffffffffffffff811180614208575061040081105b156111a257826040517f8d666f60000000000000000000000000000000000000000000000000000000008152600401610ff791906144c6565b6000818152600183016020526040812054801561432a576000614265600183615967565b855490915060009061427990600190615967565b90508082146142de576000866000018281548110614299576142996157e5565b90600052602060002001549050808760000184815481106142bc576142bc6157e5565b6000918252602080832090910192909255918252600188019052604090208390555b85548690806142ef576142ef615d07565b6001900381819060005260206000200160009055905585600101600086815260200190815260200160002060009055600193505050506111a2565b60009150506111a2565b5092915050565b6000818152600183016020526040812054614382575081546001818101845560008481526020808220909301849055845484825282860190935260409020919091556111a2565b5060006111a2565b6000818152600183016020526040812054801561432a5760006143ae600183615967565b85549091506000906143c290600190615967565b90508181146142de576000866000018281548110614299576142996157e5565b803573ffffffffffffffffffffffffffffffffffffffff8116811461440657600080fd5b919050565b60008060006060848603121561442057600080fd5b614429846143e2565b92506020840135915061443e604085016143e2565b90509250925092565b60006020828403121561445957600080fd5b610bbe826143e2565b6000815180845260005b818110156144885760208185018101518683018201520161446c565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b602081526000610bbe6020830184614462565b6020808252825182820181905260009190848201906040850190845b8181101561452757835173ffffffffffffffffffffffffffffffffffffffff16835292840192918401916001016144f5565b50909695505050505050565b60006020828403121561454557600080fd5b813567ffffffffffffffff81111561455c57600080fd5b820160408185031215610bbe57600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60405160a0810167ffffffffffffffff811182821017156145c0576145c061456e565b60405290565b6040805190810167ffffffffffffffff811182821017156145c0576145c061456e565b604051610220810167ffffffffffffffff811182821017156145c0576145c061456e565b60405160c0810167ffffffffffffffff811182821017156145c0576145c061456e565b6040516060810167ffffffffffffffff811182821017156145c0576145c061456e565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff8111828210171561469a5761469a61456e565b604052919050565b600067ffffffffffffffff8211156146bc576146bc61456e565b5060051b60200190565b80151581146111c457600080fd5b8035614406816146c6565b600060208083850312156146f257600080fd5b823567ffffffffffffffff81111561470957600080fd5b8301601f8101851361471a57600080fd5b803561472d614728826146a2565b614653565b81815260a0918202830184019184820191908884111561474c57600080fd5b938501935b8385101561481f5780858a0312156147695760008081fd5b61477161459d565b61477a866143e2565b8152868601357fffffffffffffffffffff00000000000000000000000000000000000000000000811681146147af5760008081fd5b818801526040868101357fffff000000000000000000000000000000000000000000000000000000000000811681146147e85760008081fd5b9082015260606147f98782016143e2565b9082015260808681013561480c816146c6565b9082015283529384019391850191614751565b50979650505050505050565b803567ffffffffffffffff8116811461440657600080fd5b60008083601f84011261485557600080fd5b50813567ffffffffffffffff81111561486d57600080fd5b602083019150836020828501011115611ee357600080fd5b60008083601f84011261489757600080fd5b50813567ffffffffffffffff8111156148af57600080fd5b6020830191508360208260051b8501011115611ee357600080fd5b600080600080600080600080600060c08a8c0312156148e857600080fd5b6148f18a61482b565b98506148ff60208b016143e2565b975060408a0135965060608a013567ffffffffffffffff8082111561492357600080fd5b61492f8d838e01614843565b909850965060808c013591508082111561494857600080fd5b6149548d838e01614885565b909650945060a08c013591508082111561496d57600080fd5b818c0191508c601f83011261498157600080fd5b81358181111561499057600080fd5b8d60208260061b85010111156149a557600080fd5b6020830194508093505050509295985092959850929598565b8481526000602085151581840152608060408401526149e06080840186614462565b8381036060850152845180825282820190600581901b8301840184880160005b83811015614a4c577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0868403018552614a3a838351614462565b94870194925090860190600101614a00565b50909b9a5050505050505050505050565b60008060208385031215614a7057600080fd5b823567ffffffffffffffff811115614a8757600080fd5b614a9385828601614885565b90969095509350505050565b602080825282518282018190526000919060409081850190868401855b82811015614b0d57614afd84835180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16825260209081015163ffffffff16910152565b9284019290850190600101614abc565b5091979650505050505050565b600060208284031215614b2c57600080fd5b610bbe8261482b565b81517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16815260208083015163ffffffff1690820152604081016111a2565b803561ffff8116811461440657600080fd5b803563ffffffff8116811461440657600080fd5b80357fffffffff000000000000000000000000000000000000000000000000000000008116811461440657600080fd5b60006020808385031215614bd957600080fd5b823567ffffffffffffffff811115614bf057600080fd5b8301601f81018513614c0157600080fd5b8035614c0f614728826146a2565b8181526102409182028301840191848201919088841115614c2f57600080fd5b938501935b8385101561481f5784890381811215614c4d5760008081fd5b614c556145c6565b614c5e8761482b565b8152610220807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe084011215614c935760008081fd5b614c9b6145e9565b9250614ca88989016146d4565b83526040614cb7818a01614b70565b8a8501526060614cc8818b01614b82565b8286015260809150614cdb828b01614b82565b9085015260a0614cec8a8201614b82565b8286015260c09150614cff828b01614b70565b9085015260e0614d108a8201614b82565b828601526101009150614d24828b01614b70565b90850152610120614d368a8201614b70565b828601526101409150614d4a828b01614b70565b90850152610160614d5c8a8201614b82565b828601526101809150614d70828b01614b82565b908501526101a0614d828a820161482b565b828601526101c09150614d96828b01614b82565b908501526101e0614da88a8201614b82565b828601526102009150614dbc828b016146d4565b90850152614dcb898301614b96565b90840152508088019190915283529384019391850191614c34565b81511515815261022081016020830151614e06602084018261ffff169052565b506040830151614e1e604084018263ffffffff169052565b506060830151614e36606084018263ffffffff169052565b506080830151614e4e608084018263ffffffff169052565b5060a0830151614e6460a084018261ffff169052565b5060c0830151614e7c60c084018263ffffffff169052565b5060e0830151614e9260e084018261ffff169052565b506101008381015161ffff9081169184019190915261012080850151909116908301526101408084015163ffffffff90811691840191909152610160808501518216908401526101808085015167ffffffffffffffff16908401526101a0808501518216908401526101c080850151909116908301526101e080840151151590830152610200808401517fffffffff000000000000000000000000000000000000000000000000000000008116828501525b505092915050565b600082601f830112614f5d57600080fd5b81356020614f6d614728836146a2565b82815260069290921b84018101918181019086841115614f8c57600080fd5b8286015b84811015614fd95760408189031215614fa95760008081fd5b614fb16145c6565b614fba8261482b565b8152614fc78583016143e2565b81860152835291830191604001614f90565b509695505050505050565b60008060408385031215614ff757600080fd5b67ffffffffffffffff8335111561500d57600080fd5b83601f84358501011261501f57600080fd5b61502f61472884358501356146a2565b8335840180358083526020808401939260059290921b9091010186101561505557600080fd5b602085358601015b85358601803560051b016020018110156152625767ffffffffffffffff8135111561508757600080fd5b8035863587010160407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0828a030112156150c057600080fd5b6150c86145c6565b6150d46020830161482b565b815267ffffffffffffffff604083013511156150ef57600080fd5b88603f60408401358401011261510457600080fd5b61511a61472860206040850135850101356146a2565b6020604084810135850182810135808552928401939260e00201018b101561514157600080fd5b6040808501358501015b6040858101358601602081013560e00201018110156152435760e0818d03121561517457600080fd5b61517c6145c6565b615185826143e2565b815260c07fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0838f030112156151b957600080fd5b6151c161460d565b6151cd60208401614b82565b81526151db60408401614b82565b60208201526151ec60608401614b70565b60408201526151fd60808401614b82565b606082015261520e60a08401614b82565b608082015261522060c08401356146c6565b60c083013560a0820152602082810191909152908452929092019160e00161514b565b508060208401525050808552505060208301925060208101905061505d565b5092505067ffffffffffffffff6020840135111561527f57600080fd5b61528f8460208501358501614f4c565b90509250929050565b600082601f8301126152a957600080fd5b813560206152b9614728836146a2565b8083825260208201915060208460051b8701019350868411156152db57600080fd5b602086015b84811015614fd9576152f1816143e2565b83529183019183016152e0565b6000806040838503121561531157600080fd5b823567ffffffffffffffff8082111561532957600080fd5b61533586838701615298565b9350602085013591508082111561534b57600080fd5b5061535885828601615298565b9150509250929050565b6000806000806040858703121561537857600080fd5b843567ffffffffffffffff8082111561539057600080fd5b61539c88838901614843565b909650945060208701359150808211156153b557600080fd5b506153c287828801614843565b95989497509550505050565b600080604083850312156153e157600080fd5b6153ea8361482b565b915061528f602084016143e2565b60006020828403121561540a57600080fd5b813567ffffffffffffffff8082111561542257600080fd5b908301906040828603121561543657600080fd5b61543e6145c6565b82358281111561544d57600080fd5b61545987828601615298565b82525060208301358281111561546e57600080fd5b61547a87828601615298565b60208301525095945050505050565b6000602080838503121561549c57600080fd5b823567ffffffffffffffff8111156154b357600080fd5b8301601f810185136154c457600080fd5b80356154d2614728826146a2565b81815260069190911b820183019083810190878311156154f157600080fd5b928401925b82841015615543576040848903121561550f5760008081fd5b6155176145c6565b615520856143e2565b815261552d86860161482b565b81870152825260409390930192908401906154f6565b979650505050505050565b6000806040838503121561556157600080fd5b61556a8361482b565b9150602083013567ffffffffffffffff81111561558657600080fd5b830160a0818603121561559857600080fd5b809150509250929050565b60ff811681146111c457600080fd5b600060208083850312156155c557600080fd5b823567ffffffffffffffff8111156155dc57600080fd5b8301601f810185136155ed57600080fd5b80356155fb614728826146a2565b81815260079190911b8201830190838101908783111561561a57600080fd5b928401925b828410156155435783880360808112156156395760008081fd5b6156416145c6565b61564a866143e2565b81526060807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08401121561567e5760008081fd5b615686614630565b92506156938888016143e2565b83526040808801356156a4816155a3565b848a015290870135906156b6826146c6565b830152808701919091528252608093909301929084019061561f565b600080604083850312156156e557600080fd5b6156ee836143e2565b915061528f6020840161482b565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b80820281158282048414176111a2576111a26156fc565b600082615778577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18436030181126157b257600080fd5b83018035915067ffffffffffffffff8211156157cd57600080fd5b6020019150600681901b3603821315611ee357600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b80357bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8116811461440657600080fd5b60006040828403121561585257600080fd5b61585a6145c6565b615863836143e2565b815261587160208401615814565b60208201529392505050565b60006040828403121561588f57600080fd5b6158976145c6565b6158638361482b565b600060208083850312156158b357600080fd5b823567ffffffffffffffff8111156158ca57600080fd5b8301601f810185136158db57600080fd5b80356158e9614728826146a2565b8181526060918202830184019184820191908884111561590857600080fd5b938501935b8385101561481f5780858a0312156159255760008081fd5b61592d614630565b615936866143e2565b8152615943878701615814565b878201526040615954818801614b82565b908201528352938401939185019161590d565b818103818111156111a2576111a26156fc565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18436030181126159af57600080fd5b83018035915067ffffffffffffffff8211156159ca57600080fd5b602001915036819003821315611ee357600080fd5b808201808211156111a2576111a26156fc565b7fffffffff000000000000000000000000000000000000000000000000000000008135818116916004851015614f445760049490940360031b84901b1690921692915050565b60008085851115615a4857600080fd5b83861115615a5557600080fd5b5050820193919092039150565b600060408284031215615a7457600080fd5b615a7c6145c6565b825181526020830151615871816146c6565b600060208284031215615aa057600080fd5b5051919050565b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff61833603018112615adb57600080fd5b9190910192915050565b60ff81811683821601908111156111a2576111a26156fc565b600181815b80851115615b5757817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04821115615b3d57615b3d6156fc565b80851615615b4a57918102915b93841c9390800290615b03565b509250929050565b600082615b6e575060016111a2565b81615b7b575060006111a2565b8160018114615b915760028114615b9b57615bb7565b60019150506111a2565b60ff841115615bac57615bac6156fc565b50506001821b6111a2565b5060208310610133831016604e8410600b8410161715615bda575081810a6111a2565b615be48383615afe565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04821115615c1657615c166156fc565b029392505050565b6000610bbe8383615b5f565b805169ffffffffffffffffffff8116811461440657600080fd5b600080600080600060a08688031215615c5c57600080fd5b615c6586615c2a565b9450602086015193506040860151925060608601519150615c8860808701615c2a565b90509295509295909350565b600060208284031215615ca657600080fd5b8151610bbe816155a3565b600060408284031215615cc357600080fd5b615ccb6145c6565b615cd4836143e2565b8152602083013560208201528091505092915050565b63ffffffff818116838216019080821115614334576143346156fc565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fdfea164736f6c6343000818000a", } var FeeQuoterABI = FeeQuoterMetaData.ABI @@ -710,28 +710,6 @@ func (_FeeQuoter *FeeQuoterCallerSession) ProcessMessageArgs(destChainSelector u return _FeeQuoter.Contract.ProcessMessageArgs(&_FeeQuoter.CallOpts, destChainSelector, feeToken, feeTokenAmount, extraArgs, onRampTokenTransfers, sourceTokenAmounts) } -func (_FeeQuoter *FeeQuoterCaller) SupportsInterface(opts *bind.CallOpts, interfaceId [4]byte) (bool, error) { - var out []interface{} - err := _FeeQuoter.contract.Call(opts, &out, "supportsInterface", interfaceId) - - if err != nil { - return *new(bool), err - } - - out0 := *abi.ConvertType(out[0], new(bool)).(*bool) - - return out0, err - -} - -func (_FeeQuoter *FeeQuoterSession) SupportsInterface(interfaceId [4]byte) (bool, error) { - return _FeeQuoter.Contract.SupportsInterface(&_FeeQuoter.CallOpts, interfaceId) -} - -func (_FeeQuoter *FeeQuoterCallerSession) SupportsInterface(interfaceId [4]byte) (bool, error) { - return _FeeQuoter.Contract.SupportsInterface(&_FeeQuoter.CallOpts, interfaceId) -} - func (_FeeQuoter *FeeQuoterCaller) TypeAndVersion(opts *bind.CallOpts) (string, error) { var out []interface{} err := _FeeQuoter.contract.Call(opts, &out, "typeAndVersion") @@ -2971,8 +2949,6 @@ type FeeQuoterInterface interface { error) - SupportsInterface(opts *bind.CallOpts, interfaceId [4]byte) (bool, error) - TypeAndVersion(opts *bind.CallOpts) (string, error) AcceptOwnership(opts *bind.TransactOpts) (*types.Transaction, error) diff --git a/core/gethwrappers/ccip/generated/lock_release_token_pool/lock_release_token_pool.go b/core/gethwrappers/ccip/generated/lock_release_token_pool/lock_release_token_pool.go index a670442879c..307decf3b2c 100644 --- a/core/gethwrappers/ccip/generated/lock_release_token_pool/lock_release_token_pool.go +++ b/core/gethwrappers/ccip/generated/lock_release_token_pool/lock_release_token_pool.go @@ -74,22 +74,23 @@ type RateLimiterTokenBucket struct { type TokenPoolChainUpdate struct { RemoteChainSelector uint64 - RemotePoolAddresses [][]byte + Allowed bool + RemotePoolAddress []byte RemoteTokenAddress []byte OutboundRateLimiterConfig RateLimiterConfig InboundRateLimiterConfig RateLimiterConfig } var LockReleaseTokenPoolMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[{\"internalType\":\"contractIERC20\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"localTokenDecimals\",\"type\":\"uint8\"},{\"internalType\":\"address[]\",\"name\":\"allowlist\",\"type\":\"address[]\"},{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"acceptLiquidity\",\"type\":\"bool\"},{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"capacity\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"requested\",\"type\":\"uint256\"}],\"name\":\"AggregateValueMaxCapacityExceeded\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"minWaitInSeconds\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"available\",\"type\":\"uint256\"}],\"name\":\"AggregateValueRateLimitReached\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"AllowListNotEnabled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"BucketOverfilled\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"CallerIsNotARampOnRouter\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CannotTransferToSelf\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"}],\"name\":\"ChainAlreadyExists\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"ChainNotAllowed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CursedByRMN\",\"type\":\"error\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"config\",\"type\":\"tuple\"}],\"name\":\"DisabledNonZeroRateLimit\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InsufficientLiquidity\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"expected\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"actual\",\"type\":\"uint8\"}],\"name\":\"InvalidDecimalArgs\",\"type\":\"error\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"rateLimiterConfig\",\"type\":\"tuple\"}],\"name\":\"InvalidRateLimitRate\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolData\",\"type\":\"bytes\"}],\"name\":\"InvalidRemoteChainDecimals\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"InvalidRemotePoolForChain\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"}],\"name\":\"InvalidSourcePoolAddress\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"InvalidToken\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"LiquidityNotAccepted\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MismatchedArrayLengths\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MustBeProposedOwner\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"NonExistentChain\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByOwner\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"remoteDecimals\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"localDecimals\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"remoteAmount\",\"type\":\"uint256\"}],\"name\":\"OverflowDetected\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OwnerCannotBeZero\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"PoolAlreadyAdded\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RateLimitMustBeDisabled\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"SenderNotAllowed\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"capacity\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"requested\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenAddress\",\"type\":\"address\"}],\"name\":\"TokenMaxCapacityExceeded\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"minWaitInSeconds\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"available\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenAddress\",\"type\":\"address\"}],\"name\":\"TokenRateLimitReached\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"Unauthorized\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"AllowListAdd\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"AllowListRemove\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Burned\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"remoteToken\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundRateLimiterConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundRateLimiterConfig\",\"type\":\"tuple\"}],\"name\":\"ChainAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundRateLimiterConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundRateLimiterConfig\",\"type\":\"tuple\"}],\"name\":\"ChainConfigured\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"ChainRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"config\",\"type\":\"tuple\"}],\"name\":\"ConfigChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"provider\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"LiquidityAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"provider\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"LiquidityRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"LiquidityTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Locked\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Minted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"rateLimitAdmin\",\"type\":\"address\"}],\"name\":\"RateLimitAdminSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Released\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"RemotePoolAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"RemotePoolRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"oldRouter\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newRouter\",\"type\":\"address\"}],\"name\":\"RouterUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokens\",\"type\":\"uint256\"}],\"name\":\"TokensConsumed\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"addRemotePool\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"removes\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"adds\",\"type\":\"address[]\"}],\"name\":\"applyAllowListUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64[]\",\"name\":\"remoteChainSelectorsToRemove\",\"type\":\"uint64[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes[]\",\"name\":\"remotePoolAddresses\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes\",\"name\":\"remoteTokenAddress\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundRateLimiterConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundRateLimiterConfig\",\"type\":\"tuple\"}],\"internalType\":\"structTokenPool.ChainUpdate[]\",\"name\":\"chainsToAdd\",\"type\":\"tuple[]\"}],\"name\":\"applyChainUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"canAcceptLiquidity\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAllowList\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAllowListEnabled\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getCurrentInboundRateLimiterState\",\"outputs\":[{\"components\":[{\"internalType\":\"uint128\",\"name\":\"tokens\",\"type\":\"uint128\"},{\"internalType\":\"uint32\",\"name\":\"lastUpdated\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.TokenBucket\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getCurrentOutboundRateLimiterState\",\"outputs\":[{\"components\":[{\"internalType\":\"uint128\",\"name\":\"tokens\",\"type\":\"uint128\"},{\"internalType\":\"uint32\",\"name\":\"lastUpdated\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.TokenBucket\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRateLimitAdmin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRebalancer\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getRemotePools\",\"outputs\":[{\"internalType\":\"bytes[]\",\"name\":\"\",\"type\":\"bytes[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getRemoteToken\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRmnProxy\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRouter\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getSupportedChains\",\"outputs\":[{\"internalType\":\"uint64[]\",\"name\":\"\",\"type\":\"uint64[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getToken\",\"outputs\":[{\"internalType\":\"contractIERC20\",\"name\":\"token\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getTokenDecimals\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"decimals\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"isRemotePool\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"isSupportedChain\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"isSupportedToken\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"originalSender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"localToken\",\"type\":\"address\"}],\"internalType\":\"structPool.LockOrBurnInV1\",\"name\":\"lockOrBurnIn\",\"type\":\"tuple\"}],\"name\":\"lockOrBurn\",\"outputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"destPoolData\",\"type\":\"bytes\"}],\"internalType\":\"structPool.LockOrBurnOutV1\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"provideLiquidity\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"originalSender\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"localToken\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"sourcePoolData\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"offchainTokenData\",\"type\":\"bytes\"}],\"internalType\":\"structPool.ReleaseOrMintInV1\",\"name\":\"releaseOrMintIn\",\"type\":\"tuple\"}],\"name\":\"releaseOrMint\",\"outputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"destinationAmount\",\"type\":\"uint256\"}],\"internalType\":\"structPool.ReleaseOrMintOutV1\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"removeRemotePool\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundConfig\",\"type\":\"tuple\"}],\"name\":\"setChainRateLimiterConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64[]\",\"name\":\"remoteChainSelectors\",\"type\":\"uint64[]\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config[]\",\"name\":\"outboundConfigs\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config[]\",\"name\":\"inboundConfigs\",\"type\":\"tuple[]\"}],\"name\":\"setChainRateLimiterConfigs\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"rateLimitAdmin\",\"type\":\"address\"}],\"name\":\"setRateLimitAdmin\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"rebalancer\",\"type\":\"address\"}],\"name\":\"setRebalancer\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newRouter\",\"type\":\"address\"}],\"name\":\"setRouter\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"transferLiquidity\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"withdrawLiquidity\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", - Bin: "0x61012080604052346103945761504f803803809161001d8285610413565b8339810160c0828203126103945781516001600160a01b038116908181036103945761004b60208501610436565b60408501519091906001600160401b0381116103945785019380601f86011215610394578451946001600160401b0386116103fd578560051b9060208201966100976040519889610413565b875260208088019282010192831161039457602001905b8282106103e5575050506100c460608601610444565b9060808601519586151587036103945760a06100e09101610444565b9333156103d457600180546001600160a01b03191633179055801580156103c3575b80156103b2575b6103a15760049260209260805260c0526040519283809263313ce56760e01b82525afa60009181610360575b50610335575b5060a052600480546001600160a01b0319166001600160a01b03929092169190911790558051151560e0819052610218575b5061010052604051614a5690816105f9823960805181818161036301528181611800015281816119f70152818161258301528181612766015281816129e801528181612a600152612b57015260a051818181611a580152818161296f0152818161364f01526136d2015260c051818181610d7e0152818161189c015261261e015260e051818181610d0e015281816118df01526123270152610100518181816102d101526112ae0152f35b60206040516102278282610413565b60008152600036813760e051156103245760005b81518110156102a2576001906001600160a01b036102598285610458565b5116846102658261049a565b610272575b50500161023b565b7f800671136ab6cfee9fbe5ed1fb7ca417811aca3cf864800d127b927adedf756691604051908152a1388461026a565b505060005b825181101561031b576001906001600160a01b036102c58286610458565b5116801561031557836102d782610598565b6102e5575b50505b016102a7565b7f2640d4d76caf8bf478aabfa982fa4e1c4eb71a37f93cd15e80dbc657911546d891604051908152a138836102dc565b506102df565b5050503861016d565b6335f4a7b360e01b60005260046000fd5b60ff1660ff8216818103610349575061013b565b6332ad3e0760e11b60005260045260245260446000fd5b9091506020813d602011610399575b8161037c60209383610413565b810103126103945761038d90610436565b9038610135565b600080fd5b3d915061036f565b6342bcdf7f60e11b60005260046000fd5b506001600160a01b03831615610109565b506001600160a01b03851615610102565b639b15e16f60e01b60005260046000fd5b602080916103f284610444565b8152019101906100ae565b634e487b7160e01b600052604160045260246000fd5b601f909101601f19168101906001600160401b038211908210176103fd57604052565b519060ff8216820361039457565b51906001600160a01b038216820361039457565b805182101561046c5760209160051b010190565b634e487b7160e01b600052603260045260246000fd5b805482101561046c5760005260206000200190600090565b600081815260036020526040902054801561059157600019810181811161057b5760025460001981019190821161057b5781810361052a575b505050600254801561051457600019016104ee816002610482565b8154906000199060031b1b19169055600255600052600360205260006040812055600190565b634e487b7160e01b600052603160045260246000fd5b61056361053b61054c936002610482565b90549060031b1c9283926002610482565b819391549060031b91821b91600019901b19161790565b905560005260036020526040600020553880806104d3565b634e487b7160e01b600052601160045260246000fd5b5050600090565b806000526003602052604060002054156000146105f257600254680100000000000000008110156103fd576105d961054c8260018594016002556002610482565b9055600254906000526003602052604060002055600190565b5060009056fe608080604052600436101561001357600080fd5b600090813560e01c90816301ffc9a714612c67575080630a861f2a14612b03578063181f5a7714612a8457806321df0da714612a15578063240028e81461299357806324f65ee71461293757806339077537146124dc578063432a6ba31461248a5780634c5ef0ed1461247057806354c8a4f3146122f357806362ddd3c41461226f57806366320087146121675780636cfd1553146120e55780636d3d1a581461209357806379ba509714611fae5780637d54534e14611f015780638926f54f14611e9d5780638da5cb5b14611e4b578063962d402014611ca75780639a4575b914611758578063a42a7b8b146115d3578063a7cd63b714611507578063acfecf91146113e3578063af58d59f1461137c578063b0f479a11461132a578063b7946580146112d3578063bb98546b14611278578063c0d7865514611180578063c4bffe2b14611037578063c75eea9c14610f71578063cf7401f314610da2578063dc0bd97114610d33578063e0351e1314610cd8578063e8a1da1714610403578063eb521a4c1461029c5763f2fde38b146101ad57600080fd5b346102995760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102995773ffffffffffffffffffffffffffffffffffffffff6101f9612f02565b6102016137dc565b1633811461027157807fffffffffffffffffffffffff000000000000000000000000000000000000000083541617825573ffffffffffffffffffffffffffffffffffffffff600154167fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12788380a380f35b6004827fdad89dca000000000000000000000000000000000000000000000000000000008152fd5b80fd5b50346102995760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610299576004357f0000000000000000000000000000000000000000000000000000000000000000156103db5773ffffffffffffffffffffffffffffffffffffffff600a541633036103af576103876040517f23b872dd00000000000000000000000000000000000000000000000000000000602082015233602482015230604482015282606482015260648152610361608482612e28565b7f0000000000000000000000000000000000000000000000000000000000000000613dae565b337fc17cea59c2955cb181b03393209566960365771dbba9dc3d510180e7cb3120888380a380f35b6024827f8e4a23d600000000000000000000000000000000000000000000000000000000815233600452fd5b6004827fe93f8fa4000000000000000000000000000000000000000000000000000000008152fd5b50346102995761041236612ff0565b9391909261041e6137dc565b82915b808310610b43575050508063ffffffff4216917ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffee1843603015b85821015610b3f578160051b85013581811215610b3b5785019061012082360312610b3b576040519561048c87612df0565b823567ffffffffffffffff81168103610b36578752602083013567ffffffffffffffff8111610b325783019536601f88011215610b32578635966104cf886131ee565b976104dd604051998a612e28565b8089526020808a019160051b83010190368211610b2e5760208301905b828210610afb575050505060208801968752604084013567ffffffffffffffff8111610af75761052d9036908601613546565b9860408901998a5261055761054536606088016130ae565b9560608b0196875260c03691016130ae565b9660808a019788526105698651613c53565b6105738851613c53565b8a515115610acf5761058f67ffffffffffffffff8b51166145e6565b15610a985767ffffffffffffffff8a511681526007602052604081206106cf87516fffffffffffffffffffffffffffffffff6040820151169061068a6fffffffffffffffffffffffffffffffff602083015116915115158360806040516105f581612df0565b858152602081018c905260408101849052606081018690520152855474ff000000000000000000000000000000000000000091151560a01b919091167fffffffffffffffffffffff0000000000000000000000000000000000000000009091166fffffffffffffffffffffffffffffffff84161773ffffffff0000000000000000000000000000000060808b901b1617178555565b60809190911b7fffffffffffffffffffffffffffffffff00000000000000000000000000000000166fffffffffffffffffffffffffffffffff91909116176001830155565b6107f589516fffffffffffffffffffffffffffffffff604082015116906107b06fffffffffffffffffffffffffffffffff6020830151169151151583608060405161071981612df0565b858152602081018c9052604081018490526060810186905201526002860180547fffffffffffffffffffffff000000000000000000000000000000000000000000166fffffffffffffffffffffffffffffffff85161773ffffffff0000000000000000000000000000000060808c901b161791151560a01b74ff000000000000000000000000000000000000000016919091179055565b60809190911b7fffffffffffffffffffffffffffffffff00000000000000000000000000000000166fffffffffffffffffffffffffffffffff91909116176003830155565b60048c5191019080519067ffffffffffffffff8211610a6b5761081883546132e6565b601f8111610a30575b50602090601f83116001146109915761086f9291859183610986575b50507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8260011b9260031b1c19161790565b90555b805b895180518210156108aa57906108a460019261089d838f67ffffffffffffffff905116926132d2565b5190613827565b01610874565b5050975097987f8d340f17e19058004c20453540862a9c62778504476f6756755cb33bcd6c38c29295939661097867ffffffffffffffff600197949c511692519351915161094461090f60405196879687526101006020880152610100870190612ea3565b9360408601906fffffffffffffffffffffffffffffffff60408092805115158552826020820151166020860152015116910152565b60a08401906fffffffffffffffffffffffffffffffff60408092805115158552826020820151166020860152015116910152565b0390a101909394929161045a565b01519050388061083d565b83855281852091907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08416865b818110610a1857509084600195949392106109e1575b505050811b019055610872565b01517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88460031b161c191690553880806109d4565b929360206001819287860151815501950193016109be565b610a5b9084865260208620601f850160051c81019160208610610a61575b601f0160051c01906134ed565b38610821565b9091508190610a4e565b6024847f4e487b710000000000000000000000000000000000000000000000000000000081526041600452fd5b60249067ffffffffffffffff8b51167f1d5ad3c5000000000000000000000000000000000000000000000000000000008252600452fd5b807f8579befe0000000000000000000000000000000000000000000000000000000060049252fd5b8680fd5b813567ffffffffffffffff8111610b2a57602091610b1f8392833691890101613546565b8152019101906104fa565b8a80fd5b8880fd5b8580fd5b600080fd5b8380fd5b8280f35b9092919367ffffffffffffffff610b63610b5e87858861326e565b6132ad565b1695610b6e8761431a565b15610cac578684526007602052610b8a60056040862001614121565b94845b8651811015610bc3576001908987526007602052610bbc60056040892001610bb5838b6132d2565b5190614445565b5001610b8d565b5093945094909580855260076020526005604086208681558660018201558660028201558660038201558660048201610bfc81546132e6565b80610c6b575b5050500180549086815581610c4d575b5050907f5204aec90a3c794d8e90fded8b46ae9c7c552803e7e832e0c1d358396d8599166020600193604051908152a1019190949394610421565b865260208620908101905b81811015610c1257868155600101610c58565b601f8111600114610c815750555b863880610c02565b81835260208320610c9c91601f01861c8101906001016134ed565b8082528160208120915555610c79565b602484887f1e670e4b000000000000000000000000000000000000000000000000000000008252600452fd5b503461029957807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102995760206040517f000000000000000000000000000000000000000000000000000000000000000015158152f35b503461029957807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261029957602060405173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b50346102995760e07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261029957610dda612f25565b9060607fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdc36011261029957604051610e1181612e0c565b6024358015158103610f6d5781526044356fffffffffffffffffffffffffffffffff81168103610f6d5760208201526064356fffffffffffffffffffffffffffffffff81168103610f6d57604082015260607fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7c360112610f695760405190610e9882612e0c565b6084358015158103610b3b57825260a4356fffffffffffffffffffffffffffffffff81168103610b3b57602083015260c4356fffffffffffffffffffffffffffffffff81168103610b3b57604083015273ffffffffffffffffffffffffffffffffffffffff6009541633141580610f47575b610f1b57610f189293613a91565b80f35b6024837f8e4a23d600000000000000000000000000000000000000000000000000000000815233600452fd5b5073ffffffffffffffffffffffffffffffffffffffff60015416331415610f0a565b5080fd5b8280fd5b50346102995760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261029957610fda610fd560406110339367ffffffffffffffff610fbe612f25565b610fc661343a565b50168152600760205220613465565b613bce565b6040519182918291909160806fffffffffffffffffffffffffffffffff8160a084019582815116855263ffffffff6020820151166020860152604081015115156040860152826060820151166060860152015116910152565b0390f35b503461029957807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261029957604051906005548083528260208101600584526020842092845b81811061116757505061109592500383612e28565b81516110b96110a3826131ee565b916110b16040519384612e28565b8083526131ee565b917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0602083019301368437805b8451811015611118578067ffffffffffffffff611105600193886132d2565b511661111182866132d2565b52016110e6565b50925090604051928392602084019060208552518091526040840192915b818110611144575050500390f35b825167ffffffffffffffff16845285945060209384019390920191600101611136565b8454835260019485019487945060209093019201611080565b50346102995760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102995773ffffffffffffffffffffffffffffffffffffffff6111cd612f02565b6111d56137dc565b1680156112505760407f02dc5c233404867c793b749c6d644beb2277536d18a7e7974d3f238e4c6f16849160045490807fffffffffffffffffffffffff000000000000000000000000000000000000000083161760045573ffffffffffffffffffffffffffffffffffffffff8351921682526020820152a180f35b6004827f8579befe000000000000000000000000000000000000000000000000000000008152fd5b503461029957807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102995760206040517f000000000000000000000000000000000000000000000000000000000000000015158152f35b50346102995760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261029957611033611316611311612f25565b6134cb565b604051918291602083526020830190612ea3565b503461029957807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261029957602073ffffffffffffffffffffffffffffffffffffffff60045416604051908152f35b50346102995760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261029957610fda610fd5600260406110339467ffffffffffffffff6113cb612f25565b6113d361343a565b5016815260076020522001613465565b50346102995767ffffffffffffffff6113fb36612f3c565b9290916114066137dc565b169161141f836000526006602052604060002054151590565b156114db57828452600760205261144e6005604086200161144136848661314b565b6020815191012090614445565b1561149357907f52d00ee4d9bd51b40168f2afc5848837288ce258784ad914278791464b3f4d769161148d6040519283926020845260208401916133fb565b0390a280f35b826114d7836040519384937f74f23c7c00000000000000000000000000000000000000000000000000000000855260048501526040602485015260448401916133fb565b0390fd5b602484847f1e670e4b000000000000000000000000000000000000000000000000000000008252600452fd5b503461029957807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261029957604051600254808252602082018091600285526020852090855b8181106115bd5750505082611566910383612e28565b604051928392602084019060208552518091526040840192915b81811061158e575050500390f35b825173ffffffffffffffffffffffffffffffffffffffff16845285945060209384019390920191600101611580565b8254845260209093019260019283019201611550565b50346102995760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102995767ffffffffffffffff611614612f25565b168152600760205261162b60056040832001614121565b80517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe061167061165a836131ee565b926116686040519485612e28565b8084526131ee565b01835b818110611747575050825b82518110156116c45780611694600192856132d2565b51855260086020526116a860408620613339565b6116b282856132d2565b526116bd81846132d2565b500161167e565b81846040519182916020830160208452825180915260408401602060408360051b870101940192905b8282106116fc57505050500390f35b91936020611737827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc060019597998495030186528851612ea3565b96019201920185949391926116ed565b806060602080938601015201611673565b50346102995760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102995760043567ffffffffffffffff8111610f695760a07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc8236030112610f6957606060206040516117d681612dd4565b8281520152608481016117e881613182565b73ffffffffffffffffffffffffffffffffffffffff807f000000000000000000000000000000000000000000000000000000000000000016911603611c5d5750602481019077ffffffffffffffff0000000000000000000000000000000061184f836132ad565b60801b16604051907f2cbc26bb000000000000000000000000000000000000000000000000000000008252600482015260208160248173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000165afa908115611b7e578491611c2e575b50611c06576118dd60448201613182565b7f0000000000000000000000000000000000000000000000000000000000000000611bb4575b5067ffffffffffffffff611916836132ad565b1661192e816000526006602052604060002054151590565b15611b8957602073ffffffffffffffffffffffffffffffffffffffff60045416916024604051809481937fa8d87a3b00000000000000000000000000000000000000000000000000000000835260048301525afa8015611b7e578490611b1b575b73ffffffffffffffffffffffffffffffffffffffff9150163303611aef578161131191611a1d6040611abe9667ffffffffffffffff60646119d2611a4e996132ad565b950135941681526007602052208273ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001691614695565b6040519081527f9f1ec8c880f76798e7b793325d625e9b60e4082a553c98f42b6cda368dd6000860203392a26132ad565b61103360405160ff7f000000000000000000000000000000000000000000000000000000000000000016602082015260208152611a8c604082612e28565b60405192611a9984612dd4565b8352602083019081526040519384936020855251604060208601526060850190612ea3565b90517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0848303016040850152612ea3565b6024837f728fe07b00000000000000000000000000000000000000000000000000000000815233600452fd5b506020813d602011611b76575b81611b3560209383612e28565b81010312610b3b575173ffffffffffffffffffffffffffffffffffffffff81168103610b3b5773ffffffffffffffffffffffffffffffffffffffff9061198f565b3d9150611b28565b6040513d86823e3d90fd5b7fa9902c7e000000000000000000000000000000000000000000000000000000008452600452602483fd5b73ffffffffffffffffffffffffffffffffffffffff1680845260036020526040842054611903577fd0d25976000000000000000000000000000000000000000000000000000000008452600452602483fd5b6004837f53ad11d8000000000000000000000000000000000000000000000000000000008152fd5b611c50915060203d602011611c56575b611c488183612e28565b8101906135c3565b386118cc565b503d611c3e565b8273ffffffffffffffffffffffffffffffffffffffff611c7e602493613182565b7f961c9a4f00000000000000000000000000000000000000000000000000000000835216600452fd5b50346102995760607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102995760043567ffffffffffffffff8111610f6957611cf7903690600401612fbf565b60243567ffffffffffffffff8111610b3b57611d17903690600401613060565b60449291923567ffffffffffffffff8111610b3257611d3a903690600401613060565b91909273ffffffffffffffffffffffffffffffffffffffff6009541633141580611e29575b611dfd57818114801590611df3575b611dcb57865b818110611d7f578780f35b80611dc5611d93610b5e600194868c61326e565b611d9e83878b6132c2565b611dbf611db7611daf868b8d6132c2565b9236906130ae565b9136906130ae565b91613a91565b01611d74565b6004877f568efce2000000000000000000000000000000000000000000000000000000008152fd5b5082811415611d6e565b6024877f8e4a23d600000000000000000000000000000000000000000000000000000000815233600452fd5b5073ffffffffffffffffffffffffffffffffffffffff60015416331415611d5f565b503461029957807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261029957602073ffffffffffffffffffffffffffffffffffffffff60015416604051908152f35b50346102995760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610299576020611ef767ffffffffffffffff611ee3612f25565b166000526006602052604060002054151590565b6040519015158152f35b50346102995760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610299577f44676b5284b809a22248eba0da87391d79098be38bb03154be88a58bf4d09174602073ffffffffffffffffffffffffffffffffffffffff611f71612f02565b611f796137dc565b16807fffffffffffffffffffffffff00000000000000000000000000000000000000006009541617600955604051908152a180f35b503461029957807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261029957805473ffffffffffffffffffffffffffffffffffffffff8116330361206b577fffffffffffffffffffffffff000000000000000000000000000000000000000060015491338284161760015516825573ffffffffffffffffffffffffffffffffffffffff3391167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08380a380f35b6004827f02b543c6000000000000000000000000000000000000000000000000000000008152fd5b503461029957807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261029957602073ffffffffffffffffffffffffffffffffffffffff60095416604051908152f35b50346102995760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102995773ffffffffffffffffffffffffffffffffffffffff612132612f02565b61213a6137dc565b167fffffffffffffffffffffffff0000000000000000000000000000000000000000600a541617600a5580f35b50346102995760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102995761219f612f02565b73ffffffffffffffffffffffffffffffffffffffff602435916121c06137dc565b1690813b15610f6d576040517f0a861f2a000000000000000000000000000000000000000000000000000000008152816004820152838160248183875af18015611b7e57612238575b5060207f6fa7abcf1345d1d478e5ea0da6b5f26a90eadb0546ef15ed3833944fbfd1db6291604051908152a280f35b836122677f6fa7abcf1345d1d478e5ea0da6b5f26a90eadb0546ef15ed3833944fbfd1db629395602093612e28565b939150612209565b50346102995761227e36612f3c565b61228a939291936137dc565b67ffffffffffffffff82166122ac816000526006602052604060002054151590565b156122c85750610f1892936122c291369161314b565b90613827565b7f1e670e4b000000000000000000000000000000000000000000000000000000008452600452602483fd5b50346102995761231d9061232561230936612ff0565b95916123169391936137dc565b3691613206565b933691613206565b7f00000000000000000000000000000000000000000000000000000000000000001561244857815b83518110156123c0578073ffffffffffffffffffffffffffffffffffffffff612378600193876132d2565b511661238381614184565b61238f575b500161234d565b60207f800671136ab6cfee9fbe5ed1fb7ca417811aca3cf864800d127b927adedf756691604051908152a138612388565b5090805b8251811015612444578073ffffffffffffffffffffffffffffffffffffffff6123ef600193866132d2565b5116801561243e5761240081614586565b61240d575b505b016123c4565b60207f2640d4d76caf8bf478aabfa982fa4e1c4eb71a37f93cd15e80dbc657911546d891604051908152a184612405565b50612407565b5080f35b6004827f35f4a7b3000000000000000000000000000000000000000000000000000000008152fd5b5034610299576020611ef761248436612f3c565b916131a3565b503461029957807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261029957602073ffffffffffffffffffffffffffffffffffffffff600a5416604051908152f35b50346102995760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102995760043567ffffffffffffffff8111610f695780600401916101007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc8336030112610299578060405161255d81612d89565b526084820161256b81613182565b73ffffffffffffffffffffffffffffffffffffffff807f00000000000000000000000000000000000000000000000000000000000000001691160361291657506024820177ffffffffffffffff000000000000000000000000000000006125d1826132ad565b60801b16604051907f2cbc26bb000000000000000000000000000000000000000000000000000000008252600482015260208160248173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000165afa9081156128995783916128f7575b506128cf5767ffffffffffffffff612665826132ad565b1661267d816000526006602052604060002054151590565b156128a457602073ffffffffffffffffffffffffffffffffffffffff60045416916044604051809481937f83826b2b00000000000000000000000000000000000000000000000000000000835260048301523360248301525afa90811561289957839161287a575b501561284e576126f4816132ad565b61270660a485019161248483886130fa565b1561280757506020936127c06044946127ac73ffffffffffffffffffffffffffffffffffffffff956127a66127a161279a600260406127476127c59b6132ad565b9567ffffffffffffffff60648a01359716815260078f522001976127907f000000000000000000000000000000000000000000000000000000000000000099868d8c1691614695565b60c48701906130fa565b369161314b565b6135db565b906136cf565b95869101926127ba84613182565b90613561565b613182565b166040518281527f2d87480f50083e2b2759522a8fdda59802650a8055e609a7772cf70c07748f52843392a3806040516127fe81612d89565b52604051908152f35b61281190856130fa565b6114d76040519283927f24eb47e50000000000000000000000000000000000000000000000000000000084526020600485015260248401916133fb565b6024827f728fe07b00000000000000000000000000000000000000000000000000000000815233600452fd5b612893915060203d602011611c5657611c488183612e28565b386126e5565b6040513d85823e3d90fd5b7fa9902c7e000000000000000000000000000000000000000000000000000000008352600452602482fd5b6004827f53ad11d8000000000000000000000000000000000000000000000000000000008152fd5b612910915060203d602011611c5657611c488183612e28565b3861264e565b9073ffffffffffffffffffffffffffffffffffffffff611c7e602493613182565b503461029957807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261029957602060405160ff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b50346102995760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610299576020906129ce612f02565b905073ffffffffffffffffffffffffffffffffffffffff807f0000000000000000000000000000000000000000000000000000000000000000169116146040519015158152f35b503461029957807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261029957602060405173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b503461029957807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102995750611033604051612ac5604082612e28565b601a81527f4c6f636b52656c65617365546f6b656e506f6f6c20312e352e310000000000006020820152604051918291602083526020830190612ea3565b50346102995760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102995760043573ffffffffffffffffffffffffffffffffffffffff600a541633036103af577f00000000000000000000000000000000000000000000000000000000000000006040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015260208160248173ffffffffffffffffffffffffffffffffffffffff86165afa8015611b7e5783918591612c32575b5010612c0a5781612be2913390613561565b337fc2c3f06e49b9f15e7b4af9055e183b0d73362e033ad82a07dec9bf98401717198380a380f35b6004837fbb55fd27000000000000000000000000000000000000000000000000000000008152fd5b9150506020813d602011612c5f575b81612c4e60209383612e28565b81010312610b3b5782905138612bd0565b3d9150612c41565b905034610f695760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610f69576004357fffffffff000000000000000000000000000000000000000000000000000000008116809103610f6d57602092507fe1d40566000000000000000000000000000000000000000000000000000000008114908115612cfb575b5015158152f35b7faff2afbf00000000000000000000000000000000000000000000000000000000811491508115612d5f575b8115612d35575b5038612cf4565b7f01ffc9a70000000000000000000000000000000000000000000000000000000091501438612d2e565b7f0e64dd290000000000000000000000000000000000000000000000000000000081149150612d27565b6020810190811067ffffffffffffffff821117612da557604052565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040810190811067ffffffffffffffff821117612da557604052565b60a0810190811067ffffffffffffffff821117612da557604052565b6060810190811067ffffffffffffffff821117612da557604052565b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff821117612da557604052565b67ffffffffffffffff8111612da557601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b919082519283825260005b848110612eed5750507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8460006020809697860101520116010190565b80602080928401015182828601015201612eae565b6004359073ffffffffffffffffffffffffffffffffffffffff82168203610b3657565b6004359067ffffffffffffffff82168203610b3657565b60407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc820112610b365760043567ffffffffffffffff81168103610b36579160243567ffffffffffffffff8111610b365782602382011215610b365780600401359267ffffffffffffffff8411610b365760248483010111610b36576024019190565b9181601f84011215610b365782359167ffffffffffffffff8311610b36576020808501948460051b010111610b3657565b60407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc820112610b365760043567ffffffffffffffff8111610b36578161303991600401612fbf565b929092916024359067ffffffffffffffff8211610b365761305c91600401612fbf565b9091565b9181601f84011215610b365782359167ffffffffffffffff8311610b365760208085019460608502010111610b3657565b35906fffffffffffffffffffffffffffffffff82168203610b3657565b9190826060910312610b36576040516130c681612e0c565b80928035908115158203610b365760406130f591819385526130ea60208201613091565b602086015201613091565b910152565b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe181360301821215610b36570180359067ffffffffffffffff8211610b3657602001918136038313610b3657565b92919261315782612e69565b916131656040519384612e28565b829481845281830111610b36578281602093846000960137010152565b3573ffffffffffffffffffffffffffffffffffffffff81168103610b365790565b6131eb929167ffffffffffffffff6131ce92166000526007602052600560406000200192369161314b565b602081519101209060019160005201602052604060002054151590565b90565b67ffffffffffffffff8111612da55760051b60200190565b9291613211826131ee565b9361321f6040519586612e28565b602085848152019260051b8101918211610b3657915b81831061324157505050565b823573ffffffffffffffffffffffffffffffffffffffff81168103610b3657815260209283019201613235565b919081101561327e5760051b0190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b3567ffffffffffffffff81168103610b365790565b919081101561327e576060020190565b805182101561327e5760209160051b010190565b90600182811c9216801561332f575b602083101461330057565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b91607f16916132f5565b906040519182600082549261334d846132e6565b80845293600181169081156133bb5750600114613374575b5061337292500383612e28565b565b90506000929192526020600020906000915b81831061339f5750509060206133729282010138613365565b6020919350806001915483858901015201910190918492613386565b602093506133729592507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0091501682840152151560051b82010138613365565b601f82602094937fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0938186528686013760008582860101520116010190565b6040519061344782612df0565b60006080838281528260208201528260408201528260608201520152565b9060405161347281612df0565b60806001829460ff81546fffffffffffffffffffffffffffffffff8116865263ffffffff81861c16602087015260a01c161515604085015201546fffffffffffffffffffffffffffffffff81166060840152811c910152565b67ffffffffffffffff1660005260076020526131eb6004604060002001613339565b8181106134f8575050565b600081556001016134ed565b8181029291811591840414171561351757565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b9080601f83011215610b36578160206131eb9335910161314b565b6133729273ffffffffffffffffffffffffffffffffffffffff604051937fa9059cbb0000000000000000000000000000000000000000000000000000000060208601521660248401526044830152604482526135be606483612e28565b613dae565b90816020910312610b3657518015158103610b365790565b8051801561364b5760200361360d578051602082810191830183900312610b3657519060ff821161360d575060ff1690565b6114d7906040519182917f953576f7000000000000000000000000000000000000000000000000000000008352602060048401526024830190612ea3565b50507f000000000000000000000000000000000000000000000000000000000000000090565b9060ff8091169116039060ff821161351757565b60ff16604d811161351757600a0a90565b81156136a0570490565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b907f00000000000000000000000000000000000000000000000000000000000000009060ff82169060ff8116928284146137d5578284116137ab579061371491613671565b91604d60ff8416118015613772575b61373c575050906137366131eb92613685565b90613504565b9091507fa9cb113d0000000000000000000000000000000000000000000000000000000060005260045260245260445260646000fd5b5061377c83613685565b80156136a0577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048411613723565b6137b491613671565b91604d60ff84161161373c575050906137cf6131eb92613685565b90613696565b5050505090565b73ffffffffffffffffffffffffffffffffffffffff6001541633036137fd57565b7f2b5c74de0000000000000000000000000000000000000000000000000000000060005260046000fd5b90805115613a675767ffffffffffffffff8151602083012092169182600052600760205261385c816005604060002001614640565b15613a235760005260086020526040600020815167ffffffffffffffff8111612da55761388982546132e6565b601f81116139f1575b506020601f821160011461392b5791613905827f7d628c9a1796743d365ab521a8b2a4686e419b3269919dc9145ea2ce853b54ea959361391b95600091613920575b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8260011b9260031b1c19161790565b9055604051918291602083526020830190612ea3565b0390a2565b9050840151386138d4565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe082169083600052806000209160005b8181106139d957509261391b9492600192827f7d628c9a1796743d365ab521a8b2a4686e419b3269919dc9145ea2ce853b54ea9896106139a2575b5050811b019055611316565b8501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88460031b161c191690553880613996565b9192602060018192868a01518155019401920161395b565b613a1d90836000526020600020601f840160051c81019160208510610a6157601f0160051c01906134ed565b38613892565b50906114d76040519283927f393b8ad20000000000000000000000000000000000000000000000000000000084526004840152604060248401526044830190612ea3565b7f8579befe0000000000000000000000000000000000000000000000000000000060005260046000fd5b67ffffffffffffffff166000818152600660205260409020549092919015613b935791613b9060e092613b5c85613ae87f0350d63aa5f270e01729d00d627eeb8f3429772b1818c016c66a588a864f912b97613c53565b846000526007602052613aff816040600020613eee565b613b0883613c53565b846000526007602052613b22836002604060002001613eee565b60405194855260208501906fffffffffffffffffffffffffffffffff60408092805115158552826020820151166020860152015116910152565b60808301906fffffffffffffffffffffffffffffffff60408092805115158552826020820151166020860152015116910152565ba1565b827f1e670e4b0000000000000000000000000000000000000000000000000000000060005260045260246000fd5b9190820391821161351757565b613bd661343a565b506fffffffffffffffffffffffffffffffff6060820151166fffffffffffffffffffffffffffffffff8083511691613c336020850193613c2d613c2063ffffffff87511642613bc1565b8560808901511690613504565b90614579565b80821015613c4c57505b16825263ffffffff4216905290565b9050613c3d565b805115613d07576fffffffffffffffffffffffffffffffff6040820151166fffffffffffffffffffffffffffffffff602083015116811090811591613cfe575b50613c9b5750565b606490613cfc604051917f8020d12400000000000000000000000000000000000000000000000000000000835260048301906fffffffffffffffffffffffffffffffff60408092805115158552826020820151166020860152015116910152565bfd5b90501538613c93565b6fffffffffffffffffffffffffffffffff60408201511615801590613d8f575b613d2e5750565b606490613cfc604051917fd68af9cc00000000000000000000000000000000000000000000000000000000835260048301906fffffffffffffffffffffffffffffffff60408092805115158552826020820151166020860152015116910152565b506fffffffffffffffffffffffffffffffff6020820151161515613d27565b73ffffffffffffffffffffffffffffffffffffffff613e3d911691604092600080855193613ddc8786612e28565b602085527f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564602086015260208151910182855af13d15613ee6573d91613e2183612e69565b92613e2e87519485612e28565b83523d6000602085013e61497d565b80519081613e4a57505050565b602080613e5b9383010191016135c3565b15613e635750565b608490517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152fd5b60609161497d565b7f9ea3374b67bf275e6bb9c8ae68f9cae023e1c528b4b27e092f0bb209d3531c19916140276060928054613f2b63ffffffff8260801c1642613bc1565b9081614066575b50506fffffffffffffffffffffffffffffffff600181602086015116928281541680851060001461405e57508280855b16167fffffffffffffffffffffffffffffffff00000000000000000000000000000000825416178155613fdb8651151582907fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff74ff0000000000000000000000000000000000000000835492151560a01b169116179055565b60408601517fffffffffffffffffffffffffffffffff0000000000000000000000000000000060809190911b16939092166fffffffffffffffffffffffffffffffff1692909217910155565b613b9060405180926fffffffffffffffffffffffffffffffff60408092805115158552826020820151166020860152015116910152565b838091613f62565b6fffffffffffffffffffffffffffffffff9161409b8392836140946001880154948286169560801c90613504565b9116614579565b8082101561411a57505b83547fffffffffffffffffffffffff00000000ffffffffffffffffffffffffffffffff9290911692909216167fffffffffffffffffffffffff0000000000000000000000000000000000000000909116174260801b73ffffffff00000000000000000000000000000000161781553880613f32565b90506140a5565b906040519182815491828252602082019060005260206000209260005b81811061415357505061337292500383612e28565b845483526001948501948794506020909301920161413e565b805482101561327e5760005260206000200190600090565b6000818152600360205260409020548015614313577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff810181811161351757600254907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8201918211613517578181036142a4575b5050506002548015614275577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0161423281600261416c565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82549160031b1b19169055600255600052600360205260006040812055600190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b6142fb6142b56142c693600261416c565b90549060031b1c928392600261416c565b81939154907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9060031b92831b921b19161790565b905560005260036020526040600020553880806141f9565b5050600090565b6000818152600660205260409020548015614313577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff810181811161351757600554907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82019182116135175781810361440b575b5050506005548015614275577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff016143c881600561416c565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82549160031b1b19169055600555600052600660205260006040812055600190565b61442d61441c6142c693600561416c565b90549060031b1c928392600561416c565b9055600052600660205260406000205538808061438f565b9060018201918160005282602052604060002054801515600014614570577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8101818111613517578254907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820191821161351757818103614539575b50505080548015614275577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01906144fa828261416c565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82549160031b1b191690555560005260205260006040812055600190565b6145596145496142c6938661416c565b90549060031b1c9283928661416c565b9055600052836020526040600020553880806144c2565b50505050600090565b9190820180921161351757565b806000526003602052604060002054156000146145e05760025468010000000000000000811015612da5576145c76142c6826001859401600255600261416c565b9055600254906000526003602052604060002055600190565b50600090565b806000526006602052604060002054156000146145e05760055468010000000000000000811015612da5576146276142c6826001859401600555600561416c565b9055600554906000526006602052604060002055600190565b60008281526001820160205260409020546143135780549068010000000000000000821015612da5578261467e6142c684600180960185558461416c565b905580549260005201602052604060002055600190565b929192805460ff8160a01c16158015614975575b61496e576fffffffffffffffffffffffffffffffff811690600183019081546146ee63ffffffff6fffffffffffffffffffffffffffffffff83169360801c1642613bc1565b90816148d0575b505084811061484e575083821061477d57507f1871cdf8010e63f2eb8384381a68dfa7416dc571a5517e66e88b2d2d0c0a690a939450906fffffffffffffffffffffffffffffffff8061474b8560209695613bc1565b16167fffffffffffffffffffffffffffffffff00000000000000000000000000000000825416179055604051908152a1565b81945061478f92505460801c92613bc1565b907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff810190808211613517576147dd6147e29273ffffffffffffffffffffffffffffffffffffffff94614579565b613696565b921691821561481e577fd0c8d23a0000000000000000000000000000000000000000000000000000000060005260045260245260445260646000fd5b7f15279c080000000000000000000000000000000000000000000000000000000060005260045260245260446000fd5b8473ffffffffffffffffffffffffffffffffffffffff88169182156148a0577f1a76572a0000000000000000000000000000000000000000000000000000000060005260045260245260445260646000fd5b7ff94ebcd10000000000000000000000000000000000000000000000000000000060005260045260245260446000fd5b828592939511614944576148eb92613c2d9160801c90613504565b8083101561493f5750815b83547fffffffffffffffffffffffff00000000ffffffffffffffffffffffffffffffff164260801b73ffffffff00000000000000000000000000000000161784559138806146f5565b6148f6565b7f9725942a0000000000000000000000000000000000000000000000000000000060005260046000fd5b5050509050565b5082156146a9565b919290156149f85750815115614991575090565b3b1561499a5790565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152fd5b825190915015614a0b5750805190602001fd5b6114d7906040519182917f08c379a0000000000000000000000000000000000000000000000000000000008352602060048401526024830190612ea356fea164736f6c634300081a000a", + ABI: "[{\"inputs\":[{\"internalType\":\"contractIERC20\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"address[]\",\"name\":\"allowlist\",\"type\":\"address[]\"},{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"acceptLiquidity\",\"type\":\"bool\"},{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"capacity\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"requested\",\"type\":\"uint256\"}],\"name\":\"AggregateValueMaxCapacityExceeded\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"minWaitInSeconds\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"available\",\"type\":\"uint256\"}],\"name\":\"AggregateValueRateLimitReached\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"AllowListNotEnabled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"BucketOverfilled\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"CallerIsNotARampOnRouter\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CannotTransferToSelf\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"}],\"name\":\"ChainAlreadyExists\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"ChainNotAllowed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CursedByRMN\",\"type\":\"error\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"config\",\"type\":\"tuple\"}],\"name\":\"DisabledNonZeroRateLimit\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InsufficientLiquidity\",\"type\":\"error\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"rateLimiterConfig\",\"type\":\"tuple\"}],\"name\":\"InvalidRateLimitRate\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"}],\"name\":\"InvalidSourcePoolAddress\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"InvalidToken\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"LiquidityNotAccepted\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MustBeProposedOwner\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"NonExistentChain\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByOwner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OwnerCannotBeZero\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RateLimitMustBeDisabled\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"SenderNotAllowed\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"capacity\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"requested\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenAddress\",\"type\":\"address\"}],\"name\":\"TokenMaxCapacityExceeded\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"minWaitInSeconds\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"available\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenAddress\",\"type\":\"address\"}],\"name\":\"TokenRateLimitReached\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"Unauthorized\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"AllowListAdd\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"AllowListRemove\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Burned\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"remoteToken\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundRateLimiterConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundRateLimiterConfig\",\"type\":\"tuple\"}],\"name\":\"ChainAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundRateLimiterConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundRateLimiterConfig\",\"type\":\"tuple\"}],\"name\":\"ChainConfigured\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"ChainRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"config\",\"type\":\"tuple\"}],\"name\":\"ConfigChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"provider\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"LiquidityAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"provider\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"LiquidityRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"LiquidityTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Locked\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Minted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"rateLimitAdmin\",\"type\":\"address\"}],\"name\":\"RateLimitAdminSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Released\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"previousPoolAddress\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"RemotePoolSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"oldRouter\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newRouter\",\"type\":\"address\"}],\"name\":\"RouterUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokens\",\"type\":\"uint256\"}],\"name\":\"TokensConsumed\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"removes\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"adds\",\"type\":\"address[]\"}],\"name\":\"applyAllowListUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"allowed\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"remoteTokenAddress\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundRateLimiterConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundRateLimiterConfig\",\"type\":\"tuple\"}],\"internalType\":\"structTokenPool.ChainUpdate[]\",\"name\":\"chains\",\"type\":\"tuple[]\"}],\"name\":\"applyChainUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"canAcceptLiquidity\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAllowList\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAllowListEnabled\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getCurrentInboundRateLimiterState\",\"outputs\":[{\"components\":[{\"internalType\":\"uint128\",\"name\":\"tokens\",\"type\":\"uint128\"},{\"internalType\":\"uint32\",\"name\":\"lastUpdated\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.TokenBucket\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getCurrentOutboundRateLimiterState\",\"outputs\":[{\"components\":[{\"internalType\":\"uint128\",\"name\":\"tokens\",\"type\":\"uint128\"},{\"internalType\":\"uint32\",\"name\":\"lastUpdated\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.TokenBucket\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRateLimitAdmin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRebalancer\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getRemotePool\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getRemoteToken\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRmnProxy\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRouter\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getSupportedChains\",\"outputs\":[{\"internalType\":\"uint64[]\",\"name\":\"\",\"type\":\"uint64[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getToken\",\"outputs\":[{\"internalType\":\"contractIERC20\",\"name\":\"token\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"isSupportedChain\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"isSupportedToken\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"originalSender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"localToken\",\"type\":\"address\"}],\"internalType\":\"structPool.LockOrBurnInV1\",\"name\":\"lockOrBurnIn\",\"type\":\"tuple\"}],\"name\":\"lockOrBurn\",\"outputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"destPoolData\",\"type\":\"bytes\"}],\"internalType\":\"structPool.LockOrBurnOutV1\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"provideLiquidity\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"originalSender\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"localToken\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"sourcePoolData\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"offchainTokenData\",\"type\":\"bytes\"}],\"internalType\":\"structPool.ReleaseOrMintInV1\",\"name\":\"releaseOrMintIn\",\"type\":\"tuple\"}],\"name\":\"releaseOrMint\",\"outputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"destinationAmount\",\"type\":\"uint256\"}],\"internalType\":\"structPool.ReleaseOrMintOutV1\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundConfig\",\"type\":\"tuple\"}],\"name\":\"setChainRateLimiterConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"rateLimitAdmin\",\"type\":\"address\"}],\"name\":\"setRateLimitAdmin\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"rebalancer\",\"type\":\"address\"}],\"name\":\"setRebalancer\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"setRemotePool\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newRouter\",\"type\":\"address\"}],\"name\":\"setRouter\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"transferLiquidity\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"withdrawLiquidity\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", + Bin: "0x6101006040523480156200001257600080fd5b50604051620048e9380380620048e98339810160408190526200003591620004fe565b84848483336000816200005b57604051639b15e16f60e01b815260040160405180910390fd5b600180546001600160a01b0319166001600160a01b03848116919091179091558116156200008e576200008e8162000148565b50506001600160a01b0384161580620000ae57506001600160a01b038116155b80620000c157506001600160a01b038216155b15620000e0576040516342bcdf7f60e11b815260040160405180910390fd5b6001600160a01b0384811660805282811660a052600480546001600160a01b031916918316919091179055825115801560c0526200013357604080516000815260208101909152620001339084620001c2565b5050505090151560e052506200066f92505050565b336001600160a01b038216036200017257604051636d6c4ee560e11b815260040160405180910390fd5b600080546001600160a01b0319166001600160a01b03838116918217835560015460405192939116917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b60c051620001e3576040516335f4a7b360e01b815260040160405180910390fd5b60005b82518110156200026e57600083828151811062000207576200020762000621565b60209081029190910101519050620002216002826200031f565b1562000264576040516001600160a01b03821681527f800671136ab6cfee9fbe5ed1fb7ca417811aca3cf864800d127b927adedf75669060200160405180910390a15b50600101620001e6565b5060005b81518110156200031a57600082828151811062000293576200029362000621565b6020026020010151905060006001600160a01b0316816001600160a01b031603620002bf575062000311565b620002cc6002826200033f565b156200030f576040516001600160a01b03821681527f2640d4d76caf8bf478aabfa982fa4e1c4eb71a37f93cd15e80dbc657911546d89060200160405180910390a15b505b60010162000272565b505050565b600062000336836001600160a01b03841662000356565b90505b92915050565b600062000336836001600160a01b0384166200045a565b600081815260018301602052604081205480156200044f5760006200037d60018362000637565b8554909150600090620003939060019062000637565b9050808214620003ff576000866000018281548110620003b757620003b762000621565b9060005260206000200154905080876000018481548110620003dd57620003dd62000621565b6000918252602080832090910192909255918252600188019052604090208390555b855486908062000413576200041362000659565b60019003818190600052602060002001600090559055856001016000868152602001908152602001600020600090556001935050505062000339565b600091505062000339565b6000818152600183016020526040812054620004a35750815460018181018455600084815260208082209093018490558454848252828601909352604090209190915562000339565b50600062000339565b6001600160a01b0381168114620004c257600080fd5b50565b634e487b7160e01b600052604160045260246000fd5b8051620004e881620004ac565b919050565b80518015158114620004e857600080fd5b600080600080600060a086880312156200051757600080fd5b85516200052481620004ac565b602087810151919650906001600160401b03808211156200054457600080fd5b818901915089601f8301126200055957600080fd5b8151818111156200056e576200056e620004c5565b8060051b604051601f19603f83011681018181108582111715620005965762000596620004c5565b60405291825284820192508381018501918c831115620005b557600080fd5b938501935b82851015620005de57620005ce85620004db565b84529385019392850192620005ba565b809950505050505050620005f560408701620004db565b92506200060560608701620004ed565b91506200061560808701620004db565b90509295509295909350565b634e487b7160e01b600052603260045260246000fd5b818103818111156200033957634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052603160045260246000fd5b60805160a05160c05160e0516141de6200070b600039600081816104ef015261174501526000818161059c01528181611cb1015261272501526000818161057601528181611b120152611f67015260008181610290015281816102e50152818161077a0152818161084c015281816108ed0152818161180701528181611a3201528181611e87015281816126bb015261291001526141de6000f3fe608060405234801561001057600080fd5b50600436106101f05760003560e01c80638da5cb5b1161010f578063c4bffe2b116100a2578063dc0bd97111610071578063dc0bd97114610574578063e0351e131461059a578063eb521a4c146105c0578063f2fde38b146105d357600080fd5b8063c4bffe2b14610526578063c75eea9c1461053b578063cf7401f31461054e578063db6327dc1461056157600080fd5b8063b0f479a1116100de578063b0f479a1146104bc578063b7946580146104da578063bb98546b146104ed578063c0d786551461051357600080fd5b80638da5cb5b146103fa5780639a4575b914610418578063a7cd63b714610438578063af58d59f1461044d57600080fd5b806354c8a4f31161018757806378a010b21161015657806378a010b2146103b957806379ba5097146103cc5780637d54534e146103d45780638926f54f146103e757600080fd5b806354c8a4f31461036257806366320087146103755780636cfd1553146103885780636d3d1a581461039b57600080fd5b806321df0da7116101c357806321df0da71461028e578063240028e8146102d55780633907753714610322578063432a6ba31461034457600080fd5b806301ffc9a7146101f55780630a2fd4931461021d5780630a861f2a1461023d578063181f5a7714610252575b600080fd5b6102086102033660046132ba565b6105e6565b60405190151581526020015b60405180910390f35b61023061022b366004613319565b610642565b60405161021491906133a2565b61025061024b3660046133b5565b6106f2565b005b6102306040518060400160405280601a81526020017f4c6f636b52656c65617365546f6b656e506f6f6c20312e352e3000000000000081525081565b7f00000000000000000000000000000000000000000000000000000000000000005b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610214565b6102086102e33660046133fb565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff90811691161490565b610335610330366004613418565b6108a3565b60405190518152602001610214565b60095473ffffffffffffffffffffffffffffffffffffffff166102b0565b6102506103703660046134a0565b6109a9565b61025061038336600461350c565b610a24565b6102506103963660046133fb565b610b00565b60085473ffffffffffffffffffffffffffffffffffffffff166102b0565b6102506103c7366004613538565b610b4f565b610250610cbe565b6102506103e23660046133fb565b610d8c565b6102086103f5366004613319565b610e0d565b60015473ffffffffffffffffffffffffffffffffffffffff166102b0565b61042b6104263660046135bb565b610e24565b60405161021491906135f6565b610440610ebe565b6040516102149190613656565b61046061045b366004613319565b610ecf565b604051610214919081516fffffffffffffffffffffffffffffffff908116825260208084015163ffffffff1690830152604080840151151590830152606080840151821690830152608092830151169181019190915260a00190565b60045473ffffffffffffffffffffffffffffffffffffffff166102b0565b6102306104e8366004613319565b610fa4565b7f0000000000000000000000000000000000000000000000000000000000000000610208565b6102506105213660046133fb565b610fcf565b61052e6110aa565b60405161021491906136b0565b610460610549366004613319565b611162565b61025061055c366004613818565b611234565b61025061056f36600461385d565b6112bd565b7f00000000000000000000000000000000000000000000000000000000000000006102b0565b7f0000000000000000000000000000000000000000000000000000000000000000610208565b6102506105ce3660046133b5565b611743565b6102506105e13660046133fb565b61185f565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167fe1d4056600000000000000000000000000000000000000000000000000000000148061063c575061063c82611873565b92915050565b67ffffffffffffffff8116600090815260076020526040902060040180546060919061066d9061389f565b80601f01602080910402602001604051908101604052809291908181526020018280546106999061389f565b80156106e65780601f106106bb576101008083540402835291602001916106e6565b820191906000526020600020905b8154815290600101906020018083116106c957829003601f168201915b50505050509050919050565b60095473ffffffffffffffffffffffffffffffffffffffff16331461074a576040517f8e4a23d60000000000000000000000000000000000000000000000000000000081523360048201526024015b60405180910390fd5b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015281907f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16906370a0823190602401602060405180830381865afa1580156107d6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107fa91906138f2565b1015610832576040517fbb55fd2700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61087373ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000163383611957565b604051819033907fc2c3f06e49b9f15e7b4af9055e183b0d73362e033ad82a07dec9bf984017171990600090a350565b6040805160208101909152600081526108c36108be836139b6565b611a2b565b6109186108d660608401604085016133fb565b73ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016906060850135611957565b61092860608301604084016133fb565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f2d87480f50083e2b2759522a8fdda59802650a8055e609a7772cf70c07748f52846060013560405161098a91815260200190565b60405180910390a3506040805160208101909152606090910135815290565b6109b1611c5c565b610a1e84848080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050604080516020808802828101820190935287825290935087925086918291850190849080828437600092019190915250611caf92505050565b50505050565b610a2c611c5c565b6040517f0a861f2a0000000000000000000000000000000000000000000000000000000081526004810182905273ffffffffffffffffffffffffffffffffffffffff831690630a861f2a90602401600060405180830381600087803b158015610a9457600080fd5b505af1158015610aa8573d6000803e3d6000fd5b505050508173ffffffffffffffffffffffffffffffffffffffff167f6fa7abcf1345d1d478e5ea0da6b5f26a90eadb0546ef15ed3833944fbfd1db6282604051610af491815260200190565b60405180910390a25050565b610b08611c5c565b600980547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b610b57611c5c565b610b6083610e0d565b610ba2576040517f1e670e4b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84166004820152602401610741565b67ffffffffffffffff831660009081526007602052604081206004018054610bc99061389f565b80601f0160208091040260200160405190810160405280929190818152602001828054610bf59061389f565b8015610c425780601f10610c1757610100808354040283529160200191610c42565b820191906000526020600020905b815481529060010190602001808311610c2557829003601f168201915b5050505067ffffffffffffffff8616600090815260076020526040902091925050600401610c71838583613afb565b508367ffffffffffffffff167fdb4d6220746a38cbc5335f7e108f7de80f482f4d23350253dfd0917df75a14bf828585604051610cb093929190613c16565b60405180910390a250505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314610d0f576040517f02b543c600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000008082163390811790935560008054909116815560405173ffffffffffffffffffffffffffffffffffffffff909216929183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b610d94611c5c565b600880547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040519081527f44676b5284b809a22248eba0da87391d79098be38bb03154be88a58bf4d091749060200160405180910390a150565b600061063c600567ffffffffffffffff8416611e65565b6040805180820190915260608082526020820152610e49610e4483613c7a565b611e80565b6040516060830135815233907f9f1ec8c880f76798e7b793325d625e9b60e4082a553c98f42b6cda368dd600089060200160405180910390a26040518060400160405280610ea38460200160208101906104e89190613319565b81526040805160208181019092526000815291015292915050565b6060610eca600261204a565b905090565b6040805160a08101825260008082526020820181905291810182905260608101829052608081019190915267ffffffffffffffff8216600090815260076020908152604091829020825160a08101845260028201546fffffffffffffffffffffffffffffffff808216835270010000000000000000000000000000000080830463ffffffff16958401959095527401000000000000000000000000000000000000000090910460ff16151594820194909452600390910154808416606083015291909104909116608082015261063c90612057565b67ffffffffffffffff8116600090815260076020526040902060050180546060919061066d9061389f565b610fd7611c5c565b73ffffffffffffffffffffffffffffffffffffffff8116611024576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6004805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff000000000000000000000000000000000000000083168117909355604080519190921680825260208201939093527f02dc5c233404867c793b749c6d644beb2277536d18a7e7974d3f238e4c6f1684910160405180910390a15050565b606060006110b8600561204a565b90506000815167ffffffffffffffff8111156110d6576110d66136f2565b6040519080825280602002602001820160405280156110ff578160200160208202803683370190505b50905060005b825181101561115b5782818151811061112057611120613d1c565b602002602001015182828151811061113a5761113a613d1c565b67ffffffffffffffff90921660209283029190910190910152600101611105565b5092915050565b6040805160a08101825260008082526020820181905291810182905260608101829052608081019190915267ffffffffffffffff8216600090815260076020908152604091829020825160a08101845281546fffffffffffffffffffffffffffffffff808216835270010000000000000000000000000000000080830463ffffffff16958401959095527401000000000000000000000000000000000000000090910460ff16151594820194909452600190910154808416606083015291909104909116608082015261063c90612057565b60085473ffffffffffffffffffffffffffffffffffffffff163314801590611274575060015473ffffffffffffffffffffffffffffffffffffffff163314155b156112ad576040517f8e4a23d6000000000000000000000000000000000000000000000000000000008152336004820152602401610741565b6112b8838383612109565b505050565b6112c5611c5c565b60005b818110156112b85760008383838181106112e4576112e4613d1c565b90506020028101906112f69190613d4b565b6112ff90613d89565b905061131481608001518260200151156121f3565b6113278160a001518260200151156121f3565b8060200151156116235780516113499060059067ffffffffffffffff1661232c565b61138e5780516040517f1d5ad3c500000000000000000000000000000000000000000000000000000000815267ffffffffffffffff9091166004820152602401610741565b60408101515115806113a35750606081015151155b156113da576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805161012081018252608083810180516020908101516fffffffffffffffffffffffffffffffff9081168486019081524263ffffffff90811660a0808901829052865151151560c08a01528651860151851660e08a015295518901518416610100890152918752875180860189529489018051850151841686528585019290925281515115158589015281518401518316606080870191909152915188015183168587015283870194855288880151878901908152828a015183890152895167ffffffffffffffff1660009081526007865289902088518051825482890151838e01519289167fffffffffffffffffffffffff0000000000000000000000000000000000000000928316177001000000000000000000000000000000009188168202177fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff90811674010000000000000000000000000000000000000000941515850217865584890151948d0151948a16948a168202949094176001860155995180516002860180549b8301519f830151918b169b9093169a909a179d9096168a029c909c179091169615150295909517909855908101519401519381169316909102919091176003820155915190919060048201906115bb9082613e3d565b50606082015160058201906115d09082613e3d565b505081516060830151608084015160a08501516040517f8d340f17e19058004c20453540862a9c62778504476f6756755cb33bcd6c38c295506116169493929190613f57565b60405180910390a161173a565b805161163b9060059067ffffffffffffffff16612338565b6116805780516040517f1e670e4b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff9091166004820152602401610741565b805167ffffffffffffffff16600090815260076020526040812080547fffffffffffffffffffffff000000000000000000000000000000000000000000908116825560018201839055600282018054909116905560038101829055906116e9600483018261326c565b6116f760058301600061326c565b5050805160405167ffffffffffffffff90911681527f5204aec90a3c794d8e90fded8b46ae9c7c552803e7e832e0c1d358396d8599169060200160405180910390a15b506001016112c8565b7f000000000000000000000000000000000000000000000000000000000000000061179a576040517fe93f8fa400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60095473ffffffffffffffffffffffffffffffffffffffff1633146117ed576040517f8e4a23d6000000000000000000000000000000000000000000000000000000008152336004820152602401610741565b61182f73ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016333084612344565b604051819033907fc17cea59c2955cb181b03393209566960365771dbba9dc3d510180e7cb31208890600090a350565b611867611c5c565b611870816123a2565b50565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167faff2afbf00000000000000000000000000000000000000000000000000000000148061190657507fffffffff0000000000000000000000000000000000000000000000000000000082167f0e64dd2900000000000000000000000000000000000000000000000000000000145b8061063c57507fffffffff0000000000000000000000000000000000000000000000000000000082167f01ffc9a7000000000000000000000000000000000000000000000000000000001492915050565b60405173ffffffffffffffffffffffffffffffffffffffff83166024820152604481018290526112b89084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152612466565b60808101517f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff908116911614611ac05760808101516040517f961c9a4f00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091166004820152602401610741565b60208101516040517f2cbc26bb00000000000000000000000000000000000000000000000000000000815260809190911b77ffffffffffffffff000000000000000000000000000000001660048201527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1690632cbc26bb90602401602060405180830381865afa158015611b6e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b929190613ff0565b15611bc9576040517f53ad11d800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611bd68160200151612572565b6000611be58260200151610642565b9050805160001480611c09575080805190602001208260a001518051906020012014155b15611c46578160a001516040517f24eb47e500000000000000000000000000000000000000000000000000000000815260040161074191906133a2565b611c5882602001518360600151612698565b5050565b60015473ffffffffffffffffffffffffffffffffffffffff163314611cad576040517f2b5c74de00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b565b7f0000000000000000000000000000000000000000000000000000000000000000611d06576040517f35f4a7b300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b8251811015611d9c576000838281518110611d2657611d26613d1c565b60200260200101519050611d448160026126df90919063ffffffff16565b15611d935760405173ffffffffffffffffffffffffffffffffffffffff821681527f800671136ab6cfee9fbe5ed1fb7ca417811aca3cf864800d127b927adedf75669060200160405180910390a15b50600101611d09565b5060005b81518110156112b8576000828281518110611dbd57611dbd613d1c565b60200260200101519050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603611e015750611e5d565b611e0c600282612701565b15611e5b5760405173ffffffffffffffffffffffffffffffffffffffff821681527f2640d4d76caf8bf478aabfa982fa4e1c4eb71a37f93cd15e80dbc657911546d89060200160405180910390a15b505b600101611da0565b600081815260018301602052604081205415155b9392505050565b60808101517f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff908116911614611f155760808101516040517f961c9a4f00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091166004820152602401610741565b60208101516040517f2cbc26bb00000000000000000000000000000000000000000000000000000000815260809190911b77ffffffffffffffff000000000000000000000000000000001660048201527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1690632cbc26bb90602401602060405180830381865afa158015611fc3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fe79190613ff0565b1561201e576040517f53ad11d800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61202b8160400151612723565b61203881602001516127a2565b611870816020015182606001516128f0565b60606000611e7983612934565b6040805160a0810182526000808252602082018190529181018290526060810182905260808101919091526120e582606001516fffffffffffffffffffffffffffffffff1683600001516fffffffffffffffffffffffffffffffff16846020015163ffffffff16426120c9919061403c565b85608001516fffffffffffffffffffffffffffffffff1661298f565b6fffffffffffffffffffffffffffffffff1682525063ffffffff4216602082015290565b61211283610e0d565b612154576040517f1e670e4b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84166004820152602401610741565b61215f8260006121f3565b67ffffffffffffffff8316600090815260076020526040902061218290836129b9565b61218d8160006121f3565b67ffffffffffffffff831660009081526007602052604090206121b390600201826129b9565b7f0350d63aa5f270e01729d00d627eeb8f3429772b1818c016c66a588a864f912b8383836040516121e69392919061404f565b60405180910390a1505050565b8151156122ba5781602001516fffffffffffffffffffffffffffffffff1682604001516fffffffffffffffffffffffffffffffff16101580612249575060408201516fffffffffffffffffffffffffffffffff16155b1561228257816040517f8020d12400000000000000000000000000000000000000000000000000000000815260040161074191906140d2565b8015611c58576040517f433fc33d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60408201516fffffffffffffffffffffffffffffffff161515806122f3575060208201516fffffffffffffffffffffffffffffffff1615155b15611c5857816040517fd68af9cc00000000000000000000000000000000000000000000000000000000815260040161074191906140d2565b6000611e798383612b5b565b6000611e798383612baa565b60405173ffffffffffffffffffffffffffffffffffffffff80851660248301528316604482015260648101829052610a1e9085907f23b872dd00000000000000000000000000000000000000000000000000000000906084016119a9565b3373ffffffffffffffffffffffffffffffffffffffff8216036123f1576040517fdad89dca00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff838116918217835560015460405192939116917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b60006124c8826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16612c9d9092919063ffffffff16565b8051909150156112b857808060200190518101906124e69190613ff0565b6112b8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610741565b61257b81610e0d565b6125bd576040517fa9902c7e00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff82166004820152602401610741565b600480546040517f83826b2b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84169281019290925233602483015273ffffffffffffffffffffffffffffffffffffffff16906383826b2b90604401602060405180830381865afa15801561263c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126609190613ff0565b611870576040517f728fe07b000000000000000000000000000000000000000000000000000000008152336004820152602401610741565b67ffffffffffffffff82166000908152600760205260409020611c5890600201827f0000000000000000000000000000000000000000000000000000000000000000612cac565b6000611e798373ffffffffffffffffffffffffffffffffffffffff8416612baa565b6000611e798373ffffffffffffffffffffffffffffffffffffffff8416612b5b565b7f0000000000000000000000000000000000000000000000000000000000000000156118705761275460028261302f565b611870576040517fd0d2597600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff82166004820152602401610741565b6127ab81610e0d565b6127ed576040517fa9902c7e00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff82166004820152602401610741565b600480546040517fa8d87a3b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84169281019290925273ffffffffffffffffffffffffffffffffffffffff169063a8d87a3b90602401602060405180830381865afa158015612866573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061288a919061410e565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611870576040517f728fe07b000000000000000000000000000000000000000000000000000000008152336004820152602401610741565b67ffffffffffffffff82166000908152600760205260409020611c5890827f0000000000000000000000000000000000000000000000000000000000000000612cac565b6060816000018054806020026020016040519081016040528092919081815260200182805480156106e657602002820191906000526020600020905b8154815260200190600101908083116129705750505050509050919050565b60006129ae8561299f848661412b565b6129a99087614142565b61305e565b90505b949350505050565b81546000906129e290700100000000000000000000000000000000900463ffffffff164261403c565b90508015612a845760018301548354612a2a916fffffffffffffffffffffffffffffffff8082169281169185917001000000000000000000000000000000009091041661298f565b83546fffffffffffffffffffffffffffffffff919091167fffffffffffffffffffffffff0000000000000000000000000000000000000000909116177001000000000000000000000000000000004263ffffffff16021783555b60208201518354612aaa916fffffffffffffffffffffffffffffffff908116911661305e565b83548351151574010000000000000000000000000000000000000000027fffffffffffffffffffffff00ffffffff000000000000000000000000000000009091166fffffffffffffffffffffffffffffffff92831617178455602083015160408085015183167001000000000000000000000000000000000291909216176001850155517f9ea3374b67bf275e6bb9c8ae68f9cae023e1c528b4b27e092f0bb209d3531c19906121e69084906140d2565b6000818152600183016020526040812054612ba25750815460018181018455600084815260208082209093018490558454848252828601909352604090209190915561063c565b50600061063c565b60008181526001830160205260408120548015612c93576000612bce60018361403c565b8554909150600090612be29060019061403c565b9050808214612c47576000866000018281548110612c0257612c02613d1c565b9060005260206000200154905080876000018481548110612c2557612c25613d1c565b6000918252602080832090910192909255918252600188019052604090208390555b8554869080612c5857612c58614155565b60019003818190600052602060002001600090559055856001016000868152602001908152602001600020600090556001935050505061063c565b600091505061063c565b60606129b18484600085613074565b825474010000000000000000000000000000000000000000900460ff161580612cd3575081155b15612cdd57505050565b825460018401546fffffffffffffffffffffffffffffffff80831692911690600090612d2390700100000000000000000000000000000000900463ffffffff164261403c565b90508015612de35781831115612d65576040517f9725942a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001860154612d9f9083908590849070010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff1661298f565b86547fffffffffffffffffffffffff00000000ffffffffffffffffffffffffffffffff167001000000000000000000000000000000004263ffffffff160217875592505b84821015612e9a5773ffffffffffffffffffffffffffffffffffffffff8416612e42576040517ff94ebcd10000000000000000000000000000000000000000000000000000000081526004810183905260248101869052604401610741565b6040517f1a76572a000000000000000000000000000000000000000000000000000000008152600481018390526024810186905273ffffffffffffffffffffffffffffffffffffffff85166044820152606401610741565b84831015612fad5760018681015470010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff16906000908290612ede908261403c565b612ee8878a61403c565b612ef29190614142565b612efc9190614184565b905073ffffffffffffffffffffffffffffffffffffffff8616612f55576040517f15279c080000000000000000000000000000000000000000000000000000000081526004810182905260248101869052604401610741565b6040517fd0c8d23a000000000000000000000000000000000000000000000000000000008152600481018290526024810186905273ffffffffffffffffffffffffffffffffffffffff87166044820152606401610741565b612fb7858461403c565b86547fffffffffffffffffffffffffffffffff00000000000000000000000000000000166fffffffffffffffffffffffffffffffff82161787556040518681529093507f1871cdf8010e63f2eb8384381a68dfa7416dc571a5517e66e88b2d2d0c0a690a9060200160405180910390a1505050505050565b73ffffffffffffffffffffffffffffffffffffffff811660009081526001830160205260408120541515611e79565b600081831061306d5781611e79565b5090919050565b606082471015613106576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610741565b6000808673ffffffffffffffffffffffffffffffffffffffff16858760405161312f91906141bf565b60006040518083038185875af1925050503d806000811461316c576040519150601f19603f3d011682016040523d82523d6000602084013e613171565b606091505b50915091506131828783838761318d565b979650505050505050565b6060831561322357825160000361321c5773ffffffffffffffffffffffffffffffffffffffff85163b61321c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610741565b50816129b1565b6129b183838151156132385781518083602001fd5b806040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161074191906133a2565b5080546132789061389f565b6000825580601f10613288575050565b601f01602090049060005260206000209081019061187091905b808211156132b657600081556001016132a2565b5090565b6000602082840312156132cc57600080fd5b81357fffffffff0000000000000000000000000000000000000000000000000000000081168114611e7957600080fd5b803567ffffffffffffffff8116811461331457600080fd5b919050565b60006020828403121561332b57600080fd5b611e79826132fc565b60005b8381101561334f578181015183820152602001613337565b50506000910152565b60008151808452613370816020860160208601613334565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000611e796020830184613358565b6000602082840312156133c757600080fd5b5035919050565b73ffffffffffffffffffffffffffffffffffffffff8116811461187057600080fd5b8035613314816133ce565b60006020828403121561340d57600080fd5b8135611e79816133ce565b60006020828403121561342a57600080fd5b813567ffffffffffffffff81111561344157600080fd5b82016101008185031215611e7957600080fd5b60008083601f84011261346657600080fd5b50813567ffffffffffffffff81111561347e57600080fd5b6020830191508360208260051b850101111561349957600080fd5b9250929050565b600080600080604085870312156134b657600080fd5b843567ffffffffffffffff808211156134ce57600080fd5b6134da88838901613454565b909650945060208701359150808211156134f357600080fd5b5061350087828801613454565b95989497509550505050565b6000806040838503121561351f57600080fd5b823561352a816133ce565b946020939093013593505050565b60008060006040848603121561354d57600080fd5b613556846132fc565b9250602084013567ffffffffffffffff8082111561357357600080fd5b818601915086601f83011261358757600080fd5b81358181111561359657600080fd5b8760208285010111156135a857600080fd5b6020830194508093505050509250925092565b6000602082840312156135cd57600080fd5b813567ffffffffffffffff8111156135e457600080fd5b820160a08185031215611e7957600080fd5b6020815260008251604060208401526136126060840182613358565b905060208401517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe084830301604085015261364d8282613358565b95945050505050565b6020808252825182820181905260009190848201906040850190845b818110156136a457835173ffffffffffffffffffffffffffffffffffffffff1683529284019291840191600101613672565b50909695505050505050565b6020808252825182820181905260009190848201906040850190845b818110156136a457835167ffffffffffffffff16835292840192918401916001016136cc565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051610100810167ffffffffffffffff81118282101715613745576137456136f2565b60405290565b60405160c0810167ffffffffffffffff81118282101715613745576137456136f2565b801515811461187057600080fd5b80356133148161376e565b80356fffffffffffffffffffffffffffffffff8116811461331457600080fd5b6000606082840312156137b957600080fd5b6040516060810181811067ffffffffffffffff821117156137dc576137dc6136f2565b60405290508082356137ed8161376e565b81526137fb60208401613787565b602082015261380c60408401613787565b60408201525092915050565b600080600060e0848603121561382d57600080fd5b613836846132fc565b925061384585602086016137a7565b915061385485608086016137a7565b90509250925092565b6000806020838503121561387057600080fd5b823567ffffffffffffffff81111561388757600080fd5b61389385828601613454565b90969095509350505050565b600181811c908216806138b357607f821691505b6020821081036138ec577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b60006020828403121561390457600080fd5b5051919050565b600082601f83011261391c57600080fd5b813567ffffffffffffffff80821115613937576139376136f2565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190828211818310171561397d5761397d6136f2565b8160405283815286602085880101111561399657600080fd5b836020870160208301376000602085830101528094505050505092915050565b600061010082360312156139c957600080fd5b6139d1613721565b823567ffffffffffffffff808211156139e957600080fd5b6139f53683870161390b565b8352613a03602086016132fc565b6020840152613a14604086016133f0565b604084015260608501356060840152613a2f608086016133f0565b608084015260a0850135915080821115613a4857600080fd5b613a543683870161390b565b60a084015260c0850135915080821115613a6d57600080fd5b613a793683870161390b565b60c084015260e0850135915080821115613a9257600080fd5b50613a9f3682860161390b565b60e08301525092915050565b601f8211156112b8576000816000526020600020601f850160051c81016020861015613ad45750805b601f850160051c820191505b81811015613af357828155600101613ae0565b505050505050565b67ffffffffffffffff831115613b1357613b136136f2565b613b2783613b21835461389f565b83613aab565b6000601f841160018114613b795760008515613b435750838201355b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600387901b1c1916600186901b178355613c0f565b6000838152602090207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0861690835b82811015613bc85786850135825560209485019460019092019101613ba8565b5086821015613c03577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88860031b161c19848701351681555b505060018560011b0183555b5050505050565b604081526000613c296040830186613358565b82810360208401528381528385602083013760006020858301015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f860116820101915050949350505050565b600060a08236031215613c8c57600080fd5b60405160a0810167ffffffffffffffff8282108183111715613cb057613cb06136f2565b816040528435915080821115613cc557600080fd5b50613cd23682860161390b565b825250613ce1602084016132fc565b60208201526040830135613cf4816133ce565b6040820152606083810135908201526080830135613d11816133ce565b608082015292915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600082357ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffec1833603018112613d7f57600080fd5b9190910192915050565b60006101408236031215613d9c57600080fd5b613da461374b565b613dad836132fc565b8152613dbb6020840161377c565b6020820152604083013567ffffffffffffffff80821115613ddb57600080fd5b613de73683870161390b565b60408401526060850135915080821115613e0057600080fd5b50613e0d3682860161390b565b606083015250613e2036608085016137a7565b6080820152613e323660e085016137a7565b60a082015292915050565b815167ffffffffffffffff811115613e5757613e576136f2565b613e6b81613e65845461389f565b84613aab565b602080601f831160018114613ebe5760008415613e885750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b178555613af3565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b82811015613f0b57888601518255948401946001909101908401613eec565b5085821015613f4757878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b600061010067ffffffffffffffff87168352806020840152613f7b81840187613358565b8551151560408581019190915260208701516fffffffffffffffffffffffffffffffff9081166060870152908701511660808501529150613fb99050565b8251151560a083015260208301516fffffffffffffffffffffffffffffffff90811660c084015260408401511660e083015261364d565b60006020828403121561400257600080fd5b8151611e798161376e565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b8181038181111561063c5761063c61400d565b67ffffffffffffffff8416815260e0810161409b60208301858051151582526020808201516fffffffffffffffffffffffffffffffff9081169184019190915260409182015116910152565b82511515608083015260208301516fffffffffffffffffffffffffffffffff90811660a084015260408401511660c08301526129b1565b6060810161063c82848051151582526020808201516fffffffffffffffffffffffffffffffff9081169184019190915260409182015116910152565b60006020828403121561412057600080fd5b8151611e79816133ce565b808202811582820484141761063c5761063c61400d565b8082018082111561063c5761063c61400d565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b6000826141ba577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b60008251613d7f81846020870161333456fea164736f6c6343000818000a", } var LockReleaseTokenPoolABI = LockReleaseTokenPoolMetaData.ABI var LockReleaseTokenPoolBin = LockReleaseTokenPoolMetaData.Bin -func DeployLockReleaseTokenPool(auth *bind.TransactOpts, backend bind.ContractBackend, token common.Address, localTokenDecimals uint8, allowlist []common.Address, rmnProxy common.Address, acceptLiquidity bool, router common.Address) (common.Address, *types.Transaction, *LockReleaseTokenPool, error) { +func DeployLockReleaseTokenPool(auth *bind.TransactOpts, backend bind.ContractBackend, token common.Address, allowlist []common.Address, rmnProxy common.Address, acceptLiquidity bool, router common.Address) (common.Address, *types.Transaction, *LockReleaseTokenPool, error) { parsed, err := LockReleaseTokenPoolMetaData.GetAbi() if err != nil { return common.Address{}, nil, nil, err @@ -98,7 +99,7 @@ func DeployLockReleaseTokenPool(auth *bind.TransactOpts, backend bind.ContractBa return common.Address{}, nil, nil, errors.New("GetABI returned nil") } - address, tx, contract, err := bind.DeployContract(auth, *parsed, common.FromHex(LockReleaseTokenPoolBin), backend, token, localTokenDecimals, allowlist, rmnProxy, acceptLiquidity, router) + address, tx, contract, err := bind.DeployContract(auth, *parsed, common.FromHex(LockReleaseTokenPoolBin), backend, token, allowlist, rmnProxy, acceptLiquidity, router) if err != nil { return common.Address{}, nil, nil, err } @@ -375,26 +376,26 @@ func (_LockReleaseTokenPool *LockReleaseTokenPoolCallerSession) GetRebalancer() return _LockReleaseTokenPool.Contract.GetRebalancer(&_LockReleaseTokenPool.CallOpts) } -func (_LockReleaseTokenPool *LockReleaseTokenPoolCaller) GetRemotePools(opts *bind.CallOpts, remoteChainSelector uint64) ([][]byte, error) { +func (_LockReleaseTokenPool *LockReleaseTokenPoolCaller) GetRemotePool(opts *bind.CallOpts, remoteChainSelector uint64) ([]byte, error) { var out []interface{} - err := _LockReleaseTokenPool.contract.Call(opts, &out, "getRemotePools", remoteChainSelector) + err := _LockReleaseTokenPool.contract.Call(opts, &out, "getRemotePool", remoteChainSelector) if err != nil { - return *new([][]byte), err + return *new([]byte), err } - out0 := *abi.ConvertType(out[0], new([][]byte)).(*[][]byte) + out0 := *abi.ConvertType(out[0], new([]byte)).(*[]byte) return out0, err } -func (_LockReleaseTokenPool *LockReleaseTokenPoolSession) GetRemotePools(remoteChainSelector uint64) ([][]byte, error) { - return _LockReleaseTokenPool.Contract.GetRemotePools(&_LockReleaseTokenPool.CallOpts, remoteChainSelector) +func (_LockReleaseTokenPool *LockReleaseTokenPoolSession) GetRemotePool(remoteChainSelector uint64) ([]byte, error) { + return _LockReleaseTokenPool.Contract.GetRemotePool(&_LockReleaseTokenPool.CallOpts, remoteChainSelector) } -func (_LockReleaseTokenPool *LockReleaseTokenPoolCallerSession) GetRemotePools(remoteChainSelector uint64) ([][]byte, error) { - return _LockReleaseTokenPool.Contract.GetRemotePools(&_LockReleaseTokenPool.CallOpts, remoteChainSelector) +func (_LockReleaseTokenPool *LockReleaseTokenPoolCallerSession) GetRemotePool(remoteChainSelector uint64) ([]byte, error) { + return _LockReleaseTokenPool.Contract.GetRemotePool(&_LockReleaseTokenPool.CallOpts, remoteChainSelector) } func (_LockReleaseTokenPool *LockReleaseTokenPoolCaller) GetRemoteToken(opts *bind.CallOpts, remoteChainSelector uint64) ([]byte, error) { @@ -507,50 +508,6 @@ func (_LockReleaseTokenPool *LockReleaseTokenPoolCallerSession) GetToken() (comm return _LockReleaseTokenPool.Contract.GetToken(&_LockReleaseTokenPool.CallOpts) } -func (_LockReleaseTokenPool *LockReleaseTokenPoolCaller) GetTokenDecimals(opts *bind.CallOpts) (uint8, error) { - var out []interface{} - err := _LockReleaseTokenPool.contract.Call(opts, &out, "getTokenDecimals") - - if err != nil { - return *new(uint8), err - } - - out0 := *abi.ConvertType(out[0], new(uint8)).(*uint8) - - return out0, err - -} - -func (_LockReleaseTokenPool *LockReleaseTokenPoolSession) GetTokenDecimals() (uint8, error) { - return _LockReleaseTokenPool.Contract.GetTokenDecimals(&_LockReleaseTokenPool.CallOpts) -} - -func (_LockReleaseTokenPool *LockReleaseTokenPoolCallerSession) GetTokenDecimals() (uint8, error) { - return _LockReleaseTokenPool.Contract.GetTokenDecimals(&_LockReleaseTokenPool.CallOpts) -} - -func (_LockReleaseTokenPool *LockReleaseTokenPoolCaller) IsRemotePool(opts *bind.CallOpts, remoteChainSelector uint64, remotePoolAddress []byte) (bool, error) { - var out []interface{} - err := _LockReleaseTokenPool.contract.Call(opts, &out, "isRemotePool", remoteChainSelector, remotePoolAddress) - - if err != nil { - return *new(bool), err - } - - out0 := *abi.ConvertType(out[0], new(bool)).(*bool) - - return out0, err - -} - -func (_LockReleaseTokenPool *LockReleaseTokenPoolSession) IsRemotePool(remoteChainSelector uint64, remotePoolAddress []byte) (bool, error) { - return _LockReleaseTokenPool.Contract.IsRemotePool(&_LockReleaseTokenPool.CallOpts, remoteChainSelector, remotePoolAddress) -} - -func (_LockReleaseTokenPool *LockReleaseTokenPoolCallerSession) IsRemotePool(remoteChainSelector uint64, remotePoolAddress []byte) (bool, error) { - return _LockReleaseTokenPool.Contract.IsRemotePool(&_LockReleaseTokenPool.CallOpts, remoteChainSelector, remotePoolAddress) -} - func (_LockReleaseTokenPool *LockReleaseTokenPoolCaller) IsSupportedChain(opts *bind.CallOpts, remoteChainSelector uint64) (bool, error) { var out []interface{} err := _LockReleaseTokenPool.contract.Call(opts, &out, "isSupportedChain", remoteChainSelector) @@ -673,18 +630,6 @@ func (_LockReleaseTokenPool *LockReleaseTokenPoolTransactorSession) AcceptOwners return _LockReleaseTokenPool.Contract.AcceptOwnership(&_LockReleaseTokenPool.TransactOpts) } -func (_LockReleaseTokenPool *LockReleaseTokenPoolTransactor) AddRemotePool(opts *bind.TransactOpts, remoteChainSelector uint64, remotePoolAddress []byte) (*types.Transaction, error) { - return _LockReleaseTokenPool.contract.Transact(opts, "addRemotePool", remoteChainSelector, remotePoolAddress) -} - -func (_LockReleaseTokenPool *LockReleaseTokenPoolSession) AddRemotePool(remoteChainSelector uint64, remotePoolAddress []byte) (*types.Transaction, error) { - return _LockReleaseTokenPool.Contract.AddRemotePool(&_LockReleaseTokenPool.TransactOpts, remoteChainSelector, remotePoolAddress) -} - -func (_LockReleaseTokenPool *LockReleaseTokenPoolTransactorSession) AddRemotePool(remoteChainSelector uint64, remotePoolAddress []byte) (*types.Transaction, error) { - return _LockReleaseTokenPool.Contract.AddRemotePool(&_LockReleaseTokenPool.TransactOpts, remoteChainSelector, remotePoolAddress) -} - func (_LockReleaseTokenPool *LockReleaseTokenPoolTransactor) ApplyAllowListUpdates(opts *bind.TransactOpts, removes []common.Address, adds []common.Address) (*types.Transaction, error) { return _LockReleaseTokenPool.contract.Transact(opts, "applyAllowListUpdates", removes, adds) } @@ -697,16 +642,16 @@ func (_LockReleaseTokenPool *LockReleaseTokenPoolTransactorSession) ApplyAllowLi return _LockReleaseTokenPool.Contract.ApplyAllowListUpdates(&_LockReleaseTokenPool.TransactOpts, removes, adds) } -func (_LockReleaseTokenPool *LockReleaseTokenPoolTransactor) ApplyChainUpdates(opts *bind.TransactOpts, remoteChainSelectorsToRemove []uint64, chainsToAdd []TokenPoolChainUpdate) (*types.Transaction, error) { - return _LockReleaseTokenPool.contract.Transact(opts, "applyChainUpdates", remoteChainSelectorsToRemove, chainsToAdd) +func (_LockReleaseTokenPool *LockReleaseTokenPoolTransactor) ApplyChainUpdates(opts *bind.TransactOpts, chains []TokenPoolChainUpdate) (*types.Transaction, error) { + return _LockReleaseTokenPool.contract.Transact(opts, "applyChainUpdates", chains) } -func (_LockReleaseTokenPool *LockReleaseTokenPoolSession) ApplyChainUpdates(remoteChainSelectorsToRemove []uint64, chainsToAdd []TokenPoolChainUpdate) (*types.Transaction, error) { - return _LockReleaseTokenPool.Contract.ApplyChainUpdates(&_LockReleaseTokenPool.TransactOpts, remoteChainSelectorsToRemove, chainsToAdd) +func (_LockReleaseTokenPool *LockReleaseTokenPoolSession) ApplyChainUpdates(chains []TokenPoolChainUpdate) (*types.Transaction, error) { + return _LockReleaseTokenPool.Contract.ApplyChainUpdates(&_LockReleaseTokenPool.TransactOpts, chains) } -func (_LockReleaseTokenPool *LockReleaseTokenPoolTransactorSession) ApplyChainUpdates(remoteChainSelectorsToRemove []uint64, chainsToAdd []TokenPoolChainUpdate) (*types.Transaction, error) { - return _LockReleaseTokenPool.Contract.ApplyChainUpdates(&_LockReleaseTokenPool.TransactOpts, remoteChainSelectorsToRemove, chainsToAdd) +func (_LockReleaseTokenPool *LockReleaseTokenPoolTransactorSession) ApplyChainUpdates(chains []TokenPoolChainUpdate) (*types.Transaction, error) { + return _LockReleaseTokenPool.Contract.ApplyChainUpdates(&_LockReleaseTokenPool.TransactOpts, chains) } func (_LockReleaseTokenPool *LockReleaseTokenPoolTransactor) LockOrBurn(opts *bind.TransactOpts, lockOrBurnIn PoolLockOrBurnInV1) (*types.Transaction, error) { @@ -745,18 +690,6 @@ func (_LockReleaseTokenPool *LockReleaseTokenPoolTransactorSession) ReleaseOrMin return _LockReleaseTokenPool.Contract.ReleaseOrMint(&_LockReleaseTokenPool.TransactOpts, releaseOrMintIn) } -func (_LockReleaseTokenPool *LockReleaseTokenPoolTransactor) RemoveRemotePool(opts *bind.TransactOpts, remoteChainSelector uint64, remotePoolAddress []byte) (*types.Transaction, error) { - return _LockReleaseTokenPool.contract.Transact(opts, "removeRemotePool", remoteChainSelector, remotePoolAddress) -} - -func (_LockReleaseTokenPool *LockReleaseTokenPoolSession) RemoveRemotePool(remoteChainSelector uint64, remotePoolAddress []byte) (*types.Transaction, error) { - return _LockReleaseTokenPool.Contract.RemoveRemotePool(&_LockReleaseTokenPool.TransactOpts, remoteChainSelector, remotePoolAddress) -} - -func (_LockReleaseTokenPool *LockReleaseTokenPoolTransactorSession) RemoveRemotePool(remoteChainSelector uint64, remotePoolAddress []byte) (*types.Transaction, error) { - return _LockReleaseTokenPool.Contract.RemoveRemotePool(&_LockReleaseTokenPool.TransactOpts, remoteChainSelector, remotePoolAddress) -} - func (_LockReleaseTokenPool *LockReleaseTokenPoolTransactor) SetChainRateLimiterConfig(opts *bind.TransactOpts, remoteChainSelector uint64, outboundConfig RateLimiterConfig, inboundConfig RateLimiterConfig) (*types.Transaction, error) { return _LockReleaseTokenPool.contract.Transact(opts, "setChainRateLimiterConfig", remoteChainSelector, outboundConfig, inboundConfig) } @@ -769,18 +702,6 @@ func (_LockReleaseTokenPool *LockReleaseTokenPoolTransactorSession) SetChainRate return _LockReleaseTokenPool.Contract.SetChainRateLimiterConfig(&_LockReleaseTokenPool.TransactOpts, remoteChainSelector, outboundConfig, inboundConfig) } -func (_LockReleaseTokenPool *LockReleaseTokenPoolTransactor) SetChainRateLimiterConfigs(opts *bind.TransactOpts, remoteChainSelectors []uint64, outboundConfigs []RateLimiterConfig, inboundConfigs []RateLimiterConfig) (*types.Transaction, error) { - return _LockReleaseTokenPool.contract.Transact(opts, "setChainRateLimiterConfigs", remoteChainSelectors, outboundConfigs, inboundConfigs) -} - -func (_LockReleaseTokenPool *LockReleaseTokenPoolSession) SetChainRateLimiterConfigs(remoteChainSelectors []uint64, outboundConfigs []RateLimiterConfig, inboundConfigs []RateLimiterConfig) (*types.Transaction, error) { - return _LockReleaseTokenPool.Contract.SetChainRateLimiterConfigs(&_LockReleaseTokenPool.TransactOpts, remoteChainSelectors, outboundConfigs, inboundConfigs) -} - -func (_LockReleaseTokenPool *LockReleaseTokenPoolTransactorSession) SetChainRateLimiterConfigs(remoteChainSelectors []uint64, outboundConfigs []RateLimiterConfig, inboundConfigs []RateLimiterConfig) (*types.Transaction, error) { - return _LockReleaseTokenPool.Contract.SetChainRateLimiterConfigs(&_LockReleaseTokenPool.TransactOpts, remoteChainSelectors, outboundConfigs, inboundConfigs) -} - func (_LockReleaseTokenPool *LockReleaseTokenPoolTransactor) SetRateLimitAdmin(opts *bind.TransactOpts, rateLimitAdmin common.Address) (*types.Transaction, error) { return _LockReleaseTokenPool.contract.Transact(opts, "setRateLimitAdmin", rateLimitAdmin) } @@ -805,6 +726,18 @@ func (_LockReleaseTokenPool *LockReleaseTokenPoolTransactorSession) SetRebalance return _LockReleaseTokenPool.Contract.SetRebalancer(&_LockReleaseTokenPool.TransactOpts, rebalancer) } +func (_LockReleaseTokenPool *LockReleaseTokenPoolTransactor) SetRemotePool(opts *bind.TransactOpts, remoteChainSelector uint64, remotePoolAddress []byte) (*types.Transaction, error) { + return _LockReleaseTokenPool.contract.Transact(opts, "setRemotePool", remoteChainSelector, remotePoolAddress) +} + +func (_LockReleaseTokenPool *LockReleaseTokenPoolSession) SetRemotePool(remoteChainSelector uint64, remotePoolAddress []byte) (*types.Transaction, error) { + return _LockReleaseTokenPool.Contract.SetRemotePool(&_LockReleaseTokenPool.TransactOpts, remoteChainSelector, remotePoolAddress) +} + +func (_LockReleaseTokenPool *LockReleaseTokenPoolTransactorSession) SetRemotePool(remoteChainSelector uint64, remotePoolAddress []byte) (*types.Transaction, error) { + return _LockReleaseTokenPool.Contract.SetRemotePool(&_LockReleaseTokenPool.TransactOpts, remoteChainSelector, remotePoolAddress) +} + func (_LockReleaseTokenPool *LockReleaseTokenPoolTransactor) SetRouter(opts *bind.TransactOpts, newRouter common.Address) (*types.Transaction, error) { return _LockReleaseTokenPool.contract.Transact(opts, "setRouter", newRouter) } @@ -2879,8 +2812,8 @@ func (_LockReleaseTokenPool *LockReleaseTokenPoolFilterer) ParseReleased(log typ return event, nil } -type LockReleaseTokenPoolRemotePoolAddedIterator struct { - Event *LockReleaseTokenPoolRemotePoolAdded +type LockReleaseTokenPoolRemotePoolSetIterator struct { + Event *LockReleaseTokenPoolRemotePoolSet contract *bind.BoundContract event string @@ -2891,7 +2824,7 @@ type LockReleaseTokenPoolRemotePoolAddedIterator struct { fail error } -func (it *LockReleaseTokenPoolRemotePoolAddedIterator) Next() bool { +func (it *LockReleaseTokenPoolRemotePoolSetIterator) Next() bool { if it.fail != nil { return false @@ -2900,7 +2833,7 @@ func (it *LockReleaseTokenPoolRemotePoolAddedIterator) Next() bool { if it.done { select { case log := <-it.logs: - it.Event = new(LockReleaseTokenPoolRemotePoolAdded) + it.Event = new(LockReleaseTokenPoolRemotePoolSet) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -2915,7 +2848,7 @@ func (it *LockReleaseTokenPoolRemotePoolAddedIterator) Next() bool { select { case log := <-it.logs: - it.Event = new(LockReleaseTokenPoolRemotePoolAdded) + it.Event = new(LockReleaseTokenPoolRemotePoolSet) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -2930,43 +2863,44 @@ func (it *LockReleaseTokenPoolRemotePoolAddedIterator) Next() bool { } } -func (it *LockReleaseTokenPoolRemotePoolAddedIterator) Error() error { +func (it *LockReleaseTokenPoolRemotePoolSetIterator) Error() error { return it.fail } -func (it *LockReleaseTokenPoolRemotePoolAddedIterator) Close() error { +func (it *LockReleaseTokenPoolRemotePoolSetIterator) Close() error { it.sub.Unsubscribe() return nil } -type LockReleaseTokenPoolRemotePoolAdded struct { +type LockReleaseTokenPoolRemotePoolSet struct { RemoteChainSelector uint64 + PreviousPoolAddress []byte RemotePoolAddress []byte Raw types.Log } -func (_LockReleaseTokenPool *LockReleaseTokenPoolFilterer) FilterRemotePoolAdded(opts *bind.FilterOpts, remoteChainSelector []uint64) (*LockReleaseTokenPoolRemotePoolAddedIterator, error) { +func (_LockReleaseTokenPool *LockReleaseTokenPoolFilterer) FilterRemotePoolSet(opts *bind.FilterOpts, remoteChainSelector []uint64) (*LockReleaseTokenPoolRemotePoolSetIterator, error) { var remoteChainSelectorRule []interface{} for _, remoteChainSelectorItem := range remoteChainSelector { remoteChainSelectorRule = append(remoteChainSelectorRule, remoteChainSelectorItem) } - logs, sub, err := _LockReleaseTokenPool.contract.FilterLogs(opts, "RemotePoolAdded", remoteChainSelectorRule) + logs, sub, err := _LockReleaseTokenPool.contract.FilterLogs(opts, "RemotePoolSet", remoteChainSelectorRule) if err != nil { return nil, err } - return &LockReleaseTokenPoolRemotePoolAddedIterator{contract: _LockReleaseTokenPool.contract, event: "RemotePoolAdded", logs: logs, sub: sub}, nil + return &LockReleaseTokenPoolRemotePoolSetIterator{contract: _LockReleaseTokenPool.contract, event: "RemotePoolSet", logs: logs, sub: sub}, nil } -func (_LockReleaseTokenPool *LockReleaseTokenPoolFilterer) WatchRemotePoolAdded(opts *bind.WatchOpts, sink chan<- *LockReleaseTokenPoolRemotePoolAdded, remoteChainSelector []uint64) (event.Subscription, error) { +func (_LockReleaseTokenPool *LockReleaseTokenPoolFilterer) WatchRemotePoolSet(opts *bind.WatchOpts, sink chan<- *LockReleaseTokenPoolRemotePoolSet, remoteChainSelector []uint64) (event.Subscription, error) { var remoteChainSelectorRule []interface{} for _, remoteChainSelectorItem := range remoteChainSelector { remoteChainSelectorRule = append(remoteChainSelectorRule, remoteChainSelectorItem) } - logs, sub, err := _LockReleaseTokenPool.contract.WatchLogs(opts, "RemotePoolAdded", remoteChainSelectorRule) + logs, sub, err := _LockReleaseTokenPool.contract.WatchLogs(opts, "RemotePoolSet", remoteChainSelectorRule) if err != nil { return nil, err } @@ -2976,8 +2910,8 @@ func (_LockReleaseTokenPool *LockReleaseTokenPoolFilterer) WatchRemotePoolAdded( select { case log := <-logs: - event := new(LockReleaseTokenPoolRemotePoolAdded) - if err := _LockReleaseTokenPool.contract.UnpackLog(event, "RemotePoolAdded", log); err != nil { + event := new(LockReleaseTokenPoolRemotePoolSet) + if err := _LockReleaseTokenPool.contract.UnpackLog(event, "RemotePoolSet", log); err != nil { return err } event.Raw = log @@ -2998,137 +2932,9 @@ func (_LockReleaseTokenPool *LockReleaseTokenPoolFilterer) WatchRemotePoolAdded( }), nil } -func (_LockReleaseTokenPool *LockReleaseTokenPoolFilterer) ParseRemotePoolAdded(log types.Log) (*LockReleaseTokenPoolRemotePoolAdded, error) { - event := new(LockReleaseTokenPoolRemotePoolAdded) - if err := _LockReleaseTokenPool.contract.UnpackLog(event, "RemotePoolAdded", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -type LockReleaseTokenPoolRemotePoolRemovedIterator struct { - Event *LockReleaseTokenPoolRemotePoolRemoved - - contract *bind.BoundContract - event string - - logs chan types.Log - sub ethereum.Subscription - done bool - fail error -} - -func (it *LockReleaseTokenPoolRemotePoolRemovedIterator) Next() bool { - - if it.fail != nil { - return false - } - - if it.done { - select { - case log := <-it.logs: - it.Event = new(LockReleaseTokenPoolRemotePoolRemoved) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - default: - return false - } - } - - select { - case log := <-it.logs: - it.Event = new(LockReleaseTokenPoolRemotePoolRemoved) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - case err := <-it.sub.Err(): - it.done = true - it.fail = err - return it.Next() - } -} - -func (it *LockReleaseTokenPoolRemotePoolRemovedIterator) Error() error { - return it.fail -} - -func (it *LockReleaseTokenPoolRemotePoolRemovedIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -type LockReleaseTokenPoolRemotePoolRemoved struct { - RemoteChainSelector uint64 - RemotePoolAddress []byte - Raw types.Log -} - -func (_LockReleaseTokenPool *LockReleaseTokenPoolFilterer) FilterRemotePoolRemoved(opts *bind.FilterOpts, remoteChainSelector []uint64) (*LockReleaseTokenPoolRemotePoolRemovedIterator, error) { - - var remoteChainSelectorRule []interface{} - for _, remoteChainSelectorItem := range remoteChainSelector { - remoteChainSelectorRule = append(remoteChainSelectorRule, remoteChainSelectorItem) - } - - logs, sub, err := _LockReleaseTokenPool.contract.FilterLogs(opts, "RemotePoolRemoved", remoteChainSelectorRule) - if err != nil { - return nil, err - } - return &LockReleaseTokenPoolRemotePoolRemovedIterator{contract: _LockReleaseTokenPool.contract, event: "RemotePoolRemoved", logs: logs, sub: sub}, nil -} - -func (_LockReleaseTokenPool *LockReleaseTokenPoolFilterer) WatchRemotePoolRemoved(opts *bind.WatchOpts, sink chan<- *LockReleaseTokenPoolRemotePoolRemoved, remoteChainSelector []uint64) (event.Subscription, error) { - - var remoteChainSelectorRule []interface{} - for _, remoteChainSelectorItem := range remoteChainSelector { - remoteChainSelectorRule = append(remoteChainSelectorRule, remoteChainSelectorItem) - } - - logs, sub, err := _LockReleaseTokenPool.contract.WatchLogs(opts, "RemotePoolRemoved", remoteChainSelectorRule) - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - - event := new(LockReleaseTokenPoolRemotePoolRemoved) - if err := _LockReleaseTokenPool.contract.UnpackLog(event, "RemotePoolRemoved", log); err != nil { - return err - } - event.Raw = log - - select { - case sink <- event: - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - } - }), nil -} - -func (_LockReleaseTokenPool *LockReleaseTokenPoolFilterer) ParseRemotePoolRemoved(log types.Log) (*LockReleaseTokenPoolRemotePoolRemoved, error) { - event := new(LockReleaseTokenPoolRemotePoolRemoved) - if err := _LockReleaseTokenPool.contract.UnpackLog(event, "RemotePoolRemoved", log); err != nil { +func (_LockReleaseTokenPool *LockReleaseTokenPoolFilterer) ParseRemotePoolSet(log types.Log) (*LockReleaseTokenPoolRemotePoolSet, error) { + event := new(LockReleaseTokenPoolRemotePoolSet) + if err := _LockReleaseTokenPool.contract.UnpackLog(event, "RemotePoolSet", log); err != nil { return nil, err } event.Raw = log @@ -3404,10 +3210,8 @@ func (_LockReleaseTokenPool *LockReleaseTokenPool) ParseLog(log types.Log) (gene return _LockReleaseTokenPool.ParseRateLimitAdminSet(log) case _LockReleaseTokenPool.abi.Events["Released"].ID: return _LockReleaseTokenPool.ParseReleased(log) - case _LockReleaseTokenPool.abi.Events["RemotePoolAdded"].ID: - return _LockReleaseTokenPool.ParseRemotePoolAdded(log) - case _LockReleaseTokenPool.abi.Events["RemotePoolRemoved"].ID: - return _LockReleaseTokenPool.ParseRemotePoolRemoved(log) + case _LockReleaseTokenPool.abi.Events["RemotePoolSet"].ID: + return _LockReleaseTokenPool.ParseRemotePoolSet(log) case _LockReleaseTokenPool.abi.Events["RouterUpdated"].ID: return _LockReleaseTokenPool.ParseRouterUpdated(log) case _LockReleaseTokenPool.abi.Events["TokensConsumed"].ID: @@ -3482,12 +3286,8 @@ func (LockReleaseTokenPoolReleased) Topic() common.Hash { return common.HexToHash("0x2d87480f50083e2b2759522a8fdda59802650a8055e609a7772cf70c07748f52") } -func (LockReleaseTokenPoolRemotePoolAdded) Topic() common.Hash { - return common.HexToHash("0x7d628c9a1796743d365ab521a8b2a4686e419b3269919dc9145ea2ce853b54ea") -} - -func (LockReleaseTokenPoolRemotePoolRemoved) Topic() common.Hash { - return common.HexToHash("0x52d00ee4d9bd51b40168f2afc5848837288ce258784ad914278791464b3f4d76") +func (LockReleaseTokenPoolRemotePoolSet) Topic() common.Hash { + return common.HexToHash("0xdb4d6220746a38cbc5335f7e108f7de80f482f4d23350253dfd0917df75a14bf") } func (LockReleaseTokenPoolRouterUpdated) Topic() common.Hash { @@ -3517,7 +3317,7 @@ type LockReleaseTokenPoolInterface interface { GetRebalancer(opts *bind.CallOpts) (common.Address, error) - GetRemotePools(opts *bind.CallOpts, remoteChainSelector uint64) ([][]byte, error) + GetRemotePool(opts *bind.CallOpts, remoteChainSelector uint64) ([]byte, error) GetRemoteToken(opts *bind.CallOpts, remoteChainSelector uint64) ([]byte, error) @@ -3529,10 +3329,6 @@ type LockReleaseTokenPoolInterface interface { GetToken(opts *bind.CallOpts) (common.Address, error) - GetTokenDecimals(opts *bind.CallOpts) (uint8, error) - - IsRemotePool(opts *bind.CallOpts, remoteChainSelector uint64, remotePoolAddress []byte) (bool, error) - IsSupportedChain(opts *bind.CallOpts, remoteChainSelector uint64) (bool, error) IsSupportedToken(opts *bind.CallOpts, token common.Address) (bool, error) @@ -3545,11 +3341,9 @@ type LockReleaseTokenPoolInterface interface { AcceptOwnership(opts *bind.TransactOpts) (*types.Transaction, error) - AddRemotePool(opts *bind.TransactOpts, remoteChainSelector uint64, remotePoolAddress []byte) (*types.Transaction, error) - ApplyAllowListUpdates(opts *bind.TransactOpts, removes []common.Address, adds []common.Address) (*types.Transaction, error) - ApplyChainUpdates(opts *bind.TransactOpts, remoteChainSelectorsToRemove []uint64, chainsToAdd []TokenPoolChainUpdate) (*types.Transaction, error) + ApplyChainUpdates(opts *bind.TransactOpts, chains []TokenPoolChainUpdate) (*types.Transaction, error) LockOrBurn(opts *bind.TransactOpts, lockOrBurnIn PoolLockOrBurnInV1) (*types.Transaction, error) @@ -3557,16 +3351,14 @@ type LockReleaseTokenPoolInterface interface { ReleaseOrMint(opts *bind.TransactOpts, releaseOrMintIn PoolReleaseOrMintInV1) (*types.Transaction, error) - RemoveRemotePool(opts *bind.TransactOpts, remoteChainSelector uint64, remotePoolAddress []byte) (*types.Transaction, error) - SetChainRateLimiterConfig(opts *bind.TransactOpts, remoteChainSelector uint64, outboundConfig RateLimiterConfig, inboundConfig RateLimiterConfig) (*types.Transaction, error) - SetChainRateLimiterConfigs(opts *bind.TransactOpts, remoteChainSelectors []uint64, outboundConfigs []RateLimiterConfig, inboundConfigs []RateLimiterConfig) (*types.Transaction, error) - SetRateLimitAdmin(opts *bind.TransactOpts, rateLimitAdmin common.Address) (*types.Transaction, error) SetRebalancer(opts *bind.TransactOpts, rebalancer common.Address) (*types.Transaction, error) + SetRemotePool(opts *bind.TransactOpts, remoteChainSelector uint64, remotePoolAddress []byte) (*types.Transaction, error) + SetRouter(opts *bind.TransactOpts, newRouter common.Address) (*types.Transaction, error) TransferLiquidity(opts *bind.TransactOpts, from common.Address, amount *big.Int) (*types.Transaction, error) @@ -3671,17 +3463,11 @@ type LockReleaseTokenPoolInterface interface { ParseReleased(log types.Log) (*LockReleaseTokenPoolReleased, error) - FilterRemotePoolAdded(opts *bind.FilterOpts, remoteChainSelector []uint64) (*LockReleaseTokenPoolRemotePoolAddedIterator, error) - - WatchRemotePoolAdded(opts *bind.WatchOpts, sink chan<- *LockReleaseTokenPoolRemotePoolAdded, remoteChainSelector []uint64) (event.Subscription, error) - - ParseRemotePoolAdded(log types.Log) (*LockReleaseTokenPoolRemotePoolAdded, error) - - FilterRemotePoolRemoved(opts *bind.FilterOpts, remoteChainSelector []uint64) (*LockReleaseTokenPoolRemotePoolRemovedIterator, error) + FilterRemotePoolSet(opts *bind.FilterOpts, remoteChainSelector []uint64) (*LockReleaseTokenPoolRemotePoolSetIterator, error) - WatchRemotePoolRemoved(opts *bind.WatchOpts, sink chan<- *LockReleaseTokenPoolRemotePoolRemoved, remoteChainSelector []uint64) (event.Subscription, error) + WatchRemotePoolSet(opts *bind.WatchOpts, sink chan<- *LockReleaseTokenPoolRemotePoolSet, remoteChainSelector []uint64) (event.Subscription, error) - ParseRemotePoolRemoved(log types.Log) (*LockReleaseTokenPoolRemotePoolRemoved, error) + ParseRemotePoolSet(log types.Log) (*LockReleaseTokenPoolRemotePoolSet, error) FilterRouterUpdated(opts *bind.FilterOpts) (*LockReleaseTokenPoolRouterUpdatedIterator, error) diff --git a/core/gethwrappers/ccip/generated/maybe_revert_message_receiver/maybe_revert_message_receiver.go b/core/gethwrappers/ccip/generated/maybe_revert_message_receiver/maybe_revert_message_receiver.go index cdd0ada98fe..3b52e8c871b 100644 --- a/core/gethwrappers/ccip/generated/maybe_revert_message_receiver/maybe_revert_message_receiver.go +++ b/core/gethwrappers/ccip/generated/maybe_revert_message_receiver/maybe_revert_message_receiver.go @@ -45,7 +45,7 @@ type ClientEVMTokenAmount struct { var MaybeRevertMessageReceiverMetaData = &bind.MetaData{ ABI: "[{\"inputs\":[{\"internalType\":\"bool\",\"name\":\"toRevert\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"err\",\"type\":\"bytes\"}],\"name\":\"CustomError\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ReceiveRevert\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[],\"name\":\"MessageReceived\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"ValueReceived\",\"type\":\"event\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"sender\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structClient.EVMTokenAmount[]\",\"name\":\"destTokenAmounts\",\"type\":\"tuple[]\"}],\"internalType\":\"structClient.Any2EVMMessage\",\"name\":\"\",\"type\":\"tuple\"}],\"name\":\"ccipReceive\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"s_toRevert\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"err\",\"type\":\"bytes\"}],\"name\":\"setErr\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bool\",\"name\":\"toRevert\",\"type\":\"bool\"}],\"name\":\"setRevert\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}]", - Bin: "0x608034607d57601f6107a838819003918201601f19168301916001600160401b03831184841017608257808492602094604052833981010312607d5751801515809103607d57600080546001600160a81b0319163360ff60a01b19161760a09290921b60ff60a01b1691909117905560405161070f90816100998239f35b600080fd5b634e487b7160e01b600052604160045260246000fdfe608080604052600436101561007e575b50361561001b57600080fd5b60ff60005460a01c16610054577fe12e3b7047ff60a2dd763cf536a43597e5ce7fe7aa7476345bd4cd079912bcef6020604051348152a1005b7f3085b8db0000000000000000000000000000000000000000000000000000000060005260046000fd5b60003560e01c90816301ffc9a7146105f3575080635100fc21146105af57806377f5b0e6146102da57806385572ffb1461014d57638fb5f171146100c2573861000f565b346101485760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261014857600435801515809103610148577fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff74ff00000000000000000000000000000000000000006000549260a01b16911617600055600080f35b600080fd5b346101485760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101485760043567ffffffffffffffff8111610148577ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc60a091360301126101485760ff60005460a01c166101ee577fd82ce31e3523f6eeb2d24317b2b4133001e8472729657f663b68624c45f8f3e8600080a1005b6040517f5a4ff6710000000000000000000000000000000000000000000000000000000081526020600482015280600060015461022a816106af565b908160248501526001811690816000146102a2575060011461024b57500390fd5b6001600090815291507fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf65b81831061028857505081010360440190fd5b805460448487010152849350602090920191600101610276565b604493507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0091501682840152151560051b8201010390fd5b346101485760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101485760043567ffffffffffffffff8111610148573660238201121561014857806004013567ffffffffffffffff811161058057604051917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0603f81601f8501160116830183811067ffffffffffffffff82111761058057604052818352366024838301011161014857816000926024602093018386013783010152805167ffffffffffffffff8111610580576103be6001546106af565b601f81116104dd575b50602091601f821160011461042357918192600092610418575b50507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8260011b9260031b1c191617600155600080f35b0151905082806103e1565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe082169260016000527fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf69160005b8581106104c55750836001951061048e575b505050811b01600155005b01517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88460031b161c19169055828080610483565b91926020600181928685015181550194019201610471565b6001600052601f820160051c7fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf6019060208310610558575b601f0160051c7fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf601905b81811061054c57506103c7565b6000815560010161053f565b7fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf69150610515565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b346101485760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261014857602060ff60005460a01c166040519015158152f35b346101485760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261014857600435907fffffffff00000000000000000000000000000000000000000000000000000000821680920361014857817f85572ffb0000000000000000000000000000000000000000000000000000000060209314908115610685575b5015158152f35b7f01ffc9a7000000000000000000000000000000000000000000000000000000009150148361067e565b90600182811c921680156106f8575b60208310146106c957565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b91607f16916106be56fea164736f6c634300081a000a", + Bin: "0x608060405234801561001057600080fd5b506040516107e73803806107e783398101604081905261002f9161005d565b600080546001600160a81b0319163360ff60a01b191617600160a01b92151592909202919091179055610086565b60006020828403121561006f57600080fd5b8151801515811461007f57600080fd5b9392505050565b610752806100956000396000f3fe60806040526004361061005e5760003560e01c806377f5b0e61161004357806377f5b0e61461015857806385572ffb1461017a5780638fb5f1711461019a57600080fd5b806301ffc9a7146100f25780635100fc211461012657600080fd5b366100ed5760005474010000000000000000000000000000000000000000900460ff16156100b8576040517f3085b8db00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040513481527fe12e3b7047ff60a2dd763cf536a43597e5ce7fe7aa7476345bd4cd079912bcef9060200160405180910390a1005b600080fd5b3480156100fe57600080fd5b5061011261010d366004610335565b6101ff565b604051901515815260200160405180910390f35b34801561013257600080fd5b506000546101129074010000000000000000000000000000000000000000900460ff1681565b34801561016457600080fd5b506101786101733660046103ad565b610298565b005b34801561018657600080fd5b5061017861019536600461047c565b6102a8565b3480156101a657600080fd5b506101786101b53660046104b7565b6000805491151574010000000000000000000000000000000000000000027fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff909216919091179055565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f85572ffb00000000000000000000000000000000000000000000000000000000148061029257507fffffffff0000000000000000000000000000000000000000000000000000000082167f01ffc9a700000000000000000000000000000000000000000000000000000000145b92915050565b60016102a4828261057d565b5050565b60005474010000000000000000000000000000000000000000900460ff16156103095760016040517f5a4ff6710000000000000000000000000000000000000000000000000000000081526004016103009190610697565b60405180910390fd5b6040517fd82ce31e3523f6eeb2d24317b2b4133001e8472729657f663b68624c45f8f3e890600090a150565b60006020828403121561034757600080fd5b81357fffffffff000000000000000000000000000000000000000000000000000000008116811461037757600080fd5b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000602082840312156103bf57600080fd5b813567ffffffffffffffff808211156103d757600080fd5b818401915084601f8301126103eb57600080fd5b8135818111156103fd576103fd61037e565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f011681019083821181831017156104435761044361037e565b8160405282815287602084870101111561045c57600080fd5b826020860160208301376000928101602001929092525095945050505050565b60006020828403121561048e57600080fd5b813567ffffffffffffffff8111156104a557600080fd5b820160a0818503121561037757600080fd5b6000602082840312156104c957600080fd5b8135801515811461037757600080fd5b600181811c908216806104ed57607f821691505b602082108103610526577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b601f821115610578576000816000526020600020601f850160051c810160208610156105555750805b601f850160051c820191505b8181101561057457828155600101610561565b5050505b505050565b815167ffffffffffffffff8111156105975761059761037e565b6105ab816105a584546104d9565b8461052c565b602080601f8311600181146105fe57600084156105c85750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b178555610574565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b8281101561064b5788860151825594840194600190910190840161062c565b508582101561068757878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b60006020808352600084546106ab816104d9565b80602087015260406001808416600081146106cd576001811461070757610737565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00851660408a0152604084151560051b8a01019550610737565b89600052602060002060005b8581101561072e5781548b8201860152908301908801610713565b8a016040019650505b50939897505050505050505056fea164736f6c6343000818000a", } var MaybeRevertMessageReceiverABI = MaybeRevertMessageReceiverMetaData.ABI diff --git a/core/gethwrappers/ccip/generated/message_hasher/message_hasher.go b/core/gethwrappers/ccip/generated/message_hasher/message_hasher.go index 61dd8c0dda1..5b482517191 100644 --- a/core/gethwrappers/ccip/generated/message_hasher/message_hasher.go +++ b/core/gethwrappers/ccip/generated/message_hasher/message_hasher.go @@ -72,7 +72,7 @@ type InternalRampMessageHeader struct { var MessageHasherMetaData = &bind.MetaData{ ABI: "[{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"}],\"name\":\"decodeEVMExtraArgsV1\",\"outputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"}],\"internalType\":\"structClient.EVMExtraArgsV1\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"allowOutOfOrderExecution\",\"type\":\"bool\"}],\"name\":\"decodeEVMExtraArgsV2\",\"outputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"allowOutOfOrderExecution\",\"type\":\"bool\"}],\"internalType\":\"structClient.EVMExtraArgsV2\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"destTokenAddress\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"destGasAmount\",\"type\":\"uint32\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structInternal.Any2EVMTokenTransfer[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"}],\"name\":\"encodeAny2EVMTokenAmountsHashPreimage\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sourcePoolAddress\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"destExecData\",\"type\":\"bytes\"}],\"internalType\":\"structInternal.EVM2AnyTokenTransfer[]\",\"name\":\"tokenAmount\",\"type\":\"tuple[]\"}],\"name\":\"encodeEVM2AnyTokenAmountsHashPreimage\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"}],\"internalType\":\"structClient.EVMExtraArgsV1\",\"name\":\"extraArgs\",\"type\":\"tuple\"}],\"name\":\"encodeEVMExtraArgsV1\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"allowOutOfOrderExecution\",\"type\":\"bool\"}],\"internalType\":\"structClient.EVMExtraArgsV2\",\"name\":\"extraArgs\",\"type\":\"tuple\"}],\"name\":\"encodeEVMExtraArgsV2\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"leafDomainSeparator\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"metaDataHash\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"fixedSizeFieldsHash\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"senderHash\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"dataHash\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"tokenAmountsHash\",\"type\":\"bytes32\"}],\"name\":\"encodeFinalHashPreimage\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"}],\"name\":\"encodeFixedSizeFieldsHashPreimage\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"any2EVMMessageHash\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"onRampHash\",\"type\":\"bytes32\"}],\"name\":\"encodeMetadataHashPreimage\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"}],\"internalType\":\"structInternal.RampMessageHeader\",\"name\":\"header\",\"type\":\"tuple\"},{\"internalType\":\"bytes\",\"name\":\"sender\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"destTokenAddress\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"destGasAmount\",\"type\":\"uint32\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structInternal.Any2EVMTokenTransfer[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.Any2EVMRampMessage\",\"name\":\"message\",\"type\":\"tuple\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"name\":\"hash\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"}]", - Bin: "0x60808060405234601557610e90908161001b8239f35b600080fdfe608080604052600436101561001357600080fd5b60003560e01c9081633ec7c377146109e3575080638503839d146106c457806394b6624b14610438578063ae5663d7146103d1578063b17df71414610378578063bf0619ad14610304578063c63641bd1461027d578063c7ca9a18146101b3578063e04767b81461012c5763e733d2091461008d57600080fd5b346101275760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610127576101236040516100cb81610b6e565b6004358152604051907f97a657c90000000000000000000000000000000000000000000000000000000060208301525160248201526024815261010f604482610ba6565b604051918291602083526020830190610af3565b0390f35b600080fd5b346101275760807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101275760243567ffffffffffffffff8116809103610127576101239067ffffffffffffffff610185610ac7565b604051926004356020850152604084015216606082015260643560808201526080815261010f60a082610ba6565b346101275760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101275761012361025161010f6040516101f781610b8a565b6004358152610204610d9e565b60208201526040519283917f181dcf100000000000000000000000000000000000000000000000000000000060208401526024830191909160208060408301948051845201511515910152565b037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08101835282610ba6565b346101275760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610127576101236102b7610d9e565b600060206040516102c781610b8a565b8281520152604051906102d982610b8a565b6004358252151560208201526040519182918291909160208060408301948051845201511515910152565b346101275760c07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261012757610123604051600435602082015260243560408201526044356060820152606435608082015260843560a082015260a43560c082015260c0815261010f60e082610ba6565b346101275760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261012757602060043560006040516103ba81610b6e565b52806040516103c881610b6e565b52604051908152f35b346101275760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101275760043567ffffffffffffffff81116101275761025161010f610429610123933690600401610c74565b60405192839160208301610dad565b346101275760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101275760043567ffffffffffffffff811161012757366023820112156101275780600401359061049382610c5c565b906104a16040519283610ba6565b82825260208201906024829460051b820101903682116101275760248101925b8284106105d557858560405190604082019060208084015251809152606082019060608160051b84010193916000905b82821061052d576101238561010f8189037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08101835282610ba6565b909192946020806105c7837fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa0896001960301865289519073ffffffffffffffffffffffffffffffffffffffff825116815260806105ac61059a8685015160a08886015260a0850190610af3565b60408501518482036040860152610af3565b92606081015160608401520151906080818403910152610af3565b9701920192019092916104f1565b833567ffffffffffffffff811161012757820160a07fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdc8236030112610127576040519161062183610b52565b61062d60248301610aa6565b8352604482013567ffffffffffffffff8111610127576106539060243691850101610be7565b6020840152606482013567ffffffffffffffff81116101275761067c9060243691850101610be7565b60408401526084820135606084015260a48201359267ffffffffffffffff8411610127576106b4602094936024869536920101610be7565b60808201528152019301926104c1565b346101275760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101275760043567ffffffffffffffff8111610127577ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc813603016101408112610127576040519060c082019082821067ffffffffffffffff8311176109b45760a091604052126101275760405161076681610b52565b8260040135815261077960248401610ade565b602082015261078a60448401610ade565b604082015261079b60648401610ade565b60608201526107ac60848401610ade565b6080820152815260a482013567ffffffffffffffff8111610127576107d79060043691850101610be7565b6020820190815260c483013567ffffffffffffffff8111610127576108029060043691860101610be7565b6040830190815261081560e48501610aa6565b60608401908152608084019461010481013586526101248101359067ffffffffffffffff821161012757600461084e9236920101610c74565b9060a085019182526024359567ffffffffffffffff87116101275761094861087c6020983690600401610be7565b87519067ffffffffffffffff6040818c8501511693015116908a8151910120604051918b8301937f2425b0b9f9054c76ff151b0a175b18f37a4a4e82013a72e9f15c9caa095ed21f8552604084015260608301526080820152608081526108e460a082610ba6565b5190209651805193516060808301519451608093840151604080518e8101998a5273ffffffffffffffffffffffffffffffffffffffff9590951660208a015267ffffffffffffffff9788169089015291870152909316908401528160a08401610251565b519020925185815191012091518581519101209051604051610971816102518982019485610dad565b5190209160405193868501956000875260408601526060850152608084015260a083015260c082015260c081526109a960e082610ba6565b519020604051908152f35b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b346101275760a07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610127576024359073ffffffffffffffffffffffffffffffffffffffff8216820361012757610a3b610ac7565b916084359067ffffffffffffffff8216820361012757600435602084015273ffffffffffffffffffffffffffffffffffffffff16604083015267ffffffffffffffff9283166060830152606435608083015290911660a08201526101239061010f8160c08101610251565b359073ffffffffffffffffffffffffffffffffffffffff8216820361012757565b6044359067ffffffffffffffff8216820361012757565b359067ffffffffffffffff8216820361012757565b919082519283825260005b848110610b3d5750507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8460006020809697860101520116010190565b80602080928401015182828601015201610afe565b60a0810190811067ffffffffffffffff8211176109b457604052565b6020810190811067ffffffffffffffff8211176109b457604052565b6040810190811067ffffffffffffffff8211176109b457604052565b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff8211176109b457604052565b81601f820112156101275780359067ffffffffffffffff82116109b45760405192610c3a60207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8601160185610ba6565b8284526020838301011161012757816000926020809301838601378301015290565b67ffffffffffffffff81116109b45760051b60200190565b81601f8201121561012757803590610c8b82610c5c565b92610c996040519485610ba6565b82845260208085019360051b830101918183116101275760208101935b838510610cc557505050505090565b843567ffffffffffffffff811161012757820160a07fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe082860301126101275760405191610d1183610b52565b602082013567ffffffffffffffff811161012757856020610d3492850101610be7565b8352610d4260408301610aa6565b6020840152606082013563ffffffff8116810361012757604084015260808201359267ffffffffffffffff84116101275760a083610d87886020809881980101610be7565b606084015201356080820152815201940193610cb6565b60243590811515820361012757565b602081016020825282518091526040820191602060408360051b8301019401926000915b838310610de057505050505090565b9091929394602080827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc08560019503018652885190608080610e6e610e2e855160a0865260a0860190610af3565b73ffffffffffffffffffffffffffffffffffffffff87870151168786015263ffffffff604087015116604086015260608601518582036060870152610af3565b93015191015297019301930191939290610dd156fea164736f6c634300081a000a", + Bin: "0x608060405234801561001057600080fd5b50611053806100206000396000f3fe608060405234801561001057600080fd5b50600436106100be5760003560e01c8063bf0619ad11610076578063c7ca9a181161005b578063c7ca9a1814610273578063e04767b814610286578063e733d2091461029957600080fd5b8063bf0619ad146101c9578063c63641bd1461021c57600080fd5b806394b6624b116100a757806394b6624b14610168578063ae5663d71461017b578063b17df7141461018e57600080fd5b80633ec7c377146100c35780638503839d14610147575b600080fd5b6101316100d136600461065b565b60408051602081019690965273ffffffffffffffffffffffffffffffffffffffff949094168585015267ffffffffffffffff928316606086015260808501919091521660a0808401919091528151808403909101815260c0909201905290565b60405161013e9190610716565b60405180910390f35b61015a610155366004610a5b565b6102ac565b60405190815260200161013e565b610131610176366004610b65565b610343565b610131610189366004610cd5565b61036c565b6101ba61019c366004610d12565b60408051602080820183526000909152815190810190915290815290565b6040519051815260200161013e565b6101316101d7366004610d2b565b604080516020810197909752868101959095526060860193909352608085019190915260a084015260c0808401919091528151808403909101815260e0909201905290565b61025661022a366004610d7e565b604080518082019091526000808252602082015250604080518082019091529182521515602082015290565b60408051825181526020928301511515928101929092520161013e565b610131610281366004610daa565b61037f565b610131610294366004610dfe565b610390565b6101316102a7366004610e42565b6103e3565b600061033c837f2425b0b9f9054c76ff151b0a175b18f37a4a4e82013a72e9f15c9caa095ed21f8560000151602001518660000151604001518680519060200120604051602001610321949392919093845267ffffffffffffffff928316602085015291166040830152606082015260800190565b604051602081830303815290604052805190602001206103ee565b9392505050565b6060816040516020016103569190610e84565b6040516020818303038152906040529050919050565b6060816040516020016103569190610f71565b606061038a82610521565b92915050565b6060848484846040516020016103ca949392919093845267ffffffffffffffff928316602085015291166040830152606082015260800190565b6040516020818303038152906040529050949350505050565b606061038a826105e3565b815180516060808501519083015160808087015194015160405160009586958895610460959194909391929160200194855273ffffffffffffffffffffffffffffffffffffffff93909316602085015267ffffffffffffffff9182166040850152606084015216608082015260a00190565b604051602081830303815290604052805190602001208560200151805190602001208660400151805190602001208760a001516040516020016104a39190610f71565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181528282528051602091820120908301979097528101949094526060840192909252608083015260a082015260c081019190915260e00160405160208183030381529060405280519060200120905092915050565b604051815160248201526020820151151560448201526060907f181dcf1000000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009093169290921790915292915050565b604051815160248201526060907f97a657c90000000000000000000000000000000000000000000000000000000090604401610560565b803573ffffffffffffffffffffffffffffffffffffffff8116811461063e57600080fd5b919050565b803567ffffffffffffffff8116811461063e57600080fd5b600080600080600060a0868803121561067357600080fd5b853594506106836020870161061a565b935061069160408701610643565b9250606086013591506106a660808701610643565b90509295509295909350565b6000815180845260005b818110156106d8576020818501810151868301820152016106bc565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b60208152600061033c60208301846106b2565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60405160a0810167ffffffffffffffff8111828210171561077b5761077b610729565b60405290565b60405160c0810167ffffffffffffffff8111828210171561077b5761077b610729565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156107eb576107eb610729565b604052919050565b600060a0828403121561080557600080fd5b61080d610758565b90508135815261081f60208301610643565b602082015261083060408301610643565b604082015261084160608301610643565b606082015261085260808301610643565b608082015292915050565b600082601f83011261086e57600080fd5b813567ffffffffffffffff81111561088857610888610729565b6108b960207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116016107a4565b8181528460208386010111156108ce57600080fd5b816020850160208301376000918101602001919091529392505050565b600067ffffffffffffffff82111561090557610905610729565b5060051b60200190565b600082601f83011261092057600080fd5b81356020610935610930836108eb565b6107a4565b82815260059290921b8401810191818101908684111561095457600080fd5b8286015b84811015610a5057803567ffffffffffffffff808211156109795760008081fd5b818901915060a0807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0848d030112156109b25760008081fd5b6109ba610758565b87840135838111156109cc5760008081fd5b6109da8d8a8388010161085d565b82525060406109ea81860161061a565b8983015260608086013563ffffffff81168114610a075760008081fd5b808385015250608091508186013585811115610a235760008081fd5b610a318f8c838a010161085d565b9184019190915250919093013590830152508352918301918301610958565b509695505050505050565b60008060408385031215610a6e57600080fd5b823567ffffffffffffffff80821115610a8657600080fd5b908401906101408287031215610a9b57600080fd5b610aa3610781565b610aad87846107f3565b815260a083013582811115610ac157600080fd5b610acd8882860161085d565b60208301525060c083013582811115610ae557600080fd5b610af18882860161085d565b604083015250610b0360e0840161061a565b6060820152610100830135608082015261012083013582811115610b2657600080fd5b610b328882860161090f565b60a08301525093506020850135915080821115610b4e57600080fd5b50610b5b8582860161085d565b9150509250929050565b60006020808385031215610b7857600080fd5b823567ffffffffffffffff80821115610b9057600080fd5b818501915085601f830112610ba457600080fd5b8135610bb2610930826108eb565b81815260059190911b83018401908481019088831115610bd157600080fd5b8585015b83811015610cc857803585811115610bec57600080fd5b860160a0818c037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0011215610c215760008081fd5b610c29610758565b610c3489830161061a565b815260408083013588811115610c4a5760008081fd5b610c588e8c8387010161085d565b8b8401525060608084013589811115610c715760008081fd5b610c7f8f8d8388010161085d565b83850152506080915081840135818401525060a083013588811115610ca45760008081fd5b610cb28e8c8387010161085d565b9183019190915250845250918601918601610bd5565b5098975050505050505050565b600060208284031215610ce757600080fd5b813567ffffffffffffffff811115610cfe57600080fd5b610d0a8482850161090f565b949350505050565b600060208284031215610d2457600080fd5b5035919050565b60008060008060008060c08789031215610d4457600080fd5b505084359660208601359650604086013595606081013595506080810135945060a0013592509050565b8035801515811461063e57600080fd5b60008060408385031215610d9157600080fd5b82359150610da160208401610d6e565b90509250929050565b600060408284031215610dbc57600080fd5b6040516040810181811067ffffffffffffffff82111715610ddf57610ddf610729565b60405282358152610df260208401610d6e565b60208201529392505050565b60008060008060808587031215610e1457600080fd5b84359350610e2460208601610643565b9250610e3260408601610643565b9396929550929360600135925050565b600060208284031215610e5457600080fd5b6040516020810181811067ffffffffffffffff82111715610e7757610e77610729565b6040529135825250919050565b600060208083018184528085518083526040925060408601915060408160051b87010184880160005b83811015610f63577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0898403018552815160a073ffffffffffffffffffffffffffffffffffffffff825116855288820151818a870152610f0f828701826106b2565b9150508782015185820389870152610f2782826106b2565b915050606080830151818701525060808083015192508582038187015250610f4f81836106b2565b968901969450505090860190600101610ead565b509098975050505050505050565b600060208083018184528085518083526040925060408601915060408160051b87010184880160005b83811015610f63577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0898403018552815160a08151818652610fde828701826106b2565b91505073ffffffffffffffffffffffffffffffffffffffff89830151168986015263ffffffff8883015116888601526060808301518683038288015261102483826106b2565b6080948501519790940196909652505094870194925090860190600101610f9a56fea164736f6c6343000818000a", } var MessageHasherABI = MessageHasherMetaData.ABI diff --git a/core/gethwrappers/ccip/generated/mock_usdc_token_messenger/mock_usdc_token_messenger.go b/core/gethwrappers/ccip/generated/mock_usdc_token_messenger/mock_usdc_token_messenger.go index 81c39c76a1b..4d095a97da2 100644 --- a/core/gethwrappers/ccip/generated/mock_usdc_token_messenger/mock_usdc_token_messenger.go +++ b/core/gethwrappers/ccip/generated/mock_usdc_token_messenger/mock_usdc_token_messenger.go @@ -32,7 +32,7 @@ var ( var MockE2EUSDCTokenMessengerMetaData = &bind.MetaData{ ABI: "[{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"version\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"transmitter\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"burnToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"depositor\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"mintRecipient\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"destinationDomain\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"destinationTokenMessenger\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"destinationCaller\",\"type\":\"bytes32\"}],\"name\":\"DepositForBurn\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"DESTINATION_TOKEN_MESSENGER\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"uint32\",\"name\":\"destinationDomain\",\"type\":\"uint32\"},{\"internalType\":\"bytes32\",\"name\":\"mintRecipient\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"burnToken\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"destinationCaller\",\"type\":\"bytes32\"}],\"name\":\"depositForBurnWithCaller\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"localMessageTransmitter\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"localMessageTransmitterWithRelay\",\"outputs\":[{\"internalType\":\"contractIMessageTransmitterWithRelay\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"messageBodyVersion\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"s_nonce\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", - Bin: "0x60e0346100b757601f61082538819003918201601f19168301916001600160401b038311848410176100bc5780849260409485528339810103126100b75780519063ffffffff821682036100b757602001516001600160a01b038116918282036100b757608052600080546001600160401b031916600117905560a05260c05260405161075290816100d382396080518181816101fc01526103fb015260a051816104ae015260c05181818161039c015261065f0152f35b600080fd5b634e487b7160e01b600052604160045260246000fdfe608080604052600436101561001357600080fd5b600090813560e01c9081632c12192114610464575080637eccf63e1461041f5780639cdbb181146103c0578063a250c66a14610351578063f856ddb6146100be5763fb8406a91461006357600080fd5b346100bb57807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126100bb5760206040517f17c71eed51b181d8ae1908b4743526c6dbf099c201f158a1acd5f6718e82e8f68152f35b80fd5b50346100bb5760a07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126100bb576024359060043563ffffffff831680840361034d576044356064359173ffffffffffffffffffffffffffffffffffffffff831680930361034957608435916040517f23b872dd0000000000000000000000000000000000000000000000000000000081523360048201523060248201528560448201526020816064818a895af1801561030257610311575b50833b1561030d57604051967f42966c68000000000000000000000000000000000000000000000000000000008852856004890152868860248183895af1978815610302576020986102e2575b5061024f67ffffffffffffffff9185604051917fffffffff000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000060e01b168c8401528860248401528560448401528960648401523360848401526084835261024a60a4846104d6565b6105ca565b1695867fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000008254161790556040519485528685015260408401527f17c71eed51b181d8ae1908b4743526c6dbf099c201f158a1acd5f6718e82e8f660608401526080830152827f2fa9ca894982930190727e75500a97d8dc500233a5065e0f3126c48fbe0343c060a03394a4604051908152f35b876102fa67ffffffffffffffff939961024f936104d6565b9791506101c6565b6040513d89823e3d90fd5b8580fd5b6020813d602011610341575b8161032a602093836104d6565b8101031261033d57518015158114610179575b8680fd5b3d915061031d565b8480fd5b8280fd5b50346100bb57807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126100bb57602060405173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b50346100bb57807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126100bb57602060405163ffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b50346100bb57807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126100bb5767ffffffffffffffff6020915416604051908152f35b9050346104d257817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126104d25760209073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b5080fd5b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff82111761051757604052565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b90816020910312610566575167ffffffffffffffff811681036105665790565b600080fd5b919082519283825260005b8481106105b55750507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8460006020809697860101520116010190565b80602080928401015182828601015201610576565b90806106cb575063ffffffff60209161064460405194859384937f0ba469bc0000000000000000000000000000000000000000000000000000000085521660048401527f17c71eed51b181d8ae1908b4743526c6dbf099c201f158a1acd5f6718e82e8f6602484015260606044840152606483019061056b565b0381600073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000165af19081156106bf57600091610693575090565b6106b5915060203d6020116106b8575b6106ad81836104d6565b810190610546565b90565b503d6106a3565b6040513d6000823e3d90fd5b9160209161064463ffffffff9260405195869485947ff7259a750000000000000000000000000000000000000000000000000000000086521660048501527f17c71eed51b181d8ae1908b4743526c6dbf099c201f158a1acd5f6718e82e8f66024850152604484015260806064840152608483019061056b56fea164736f6c634300081a000a", + Bin: "0x60e060405234801561001057600080fd5b5060405161082d38038061082d83398101604081905261002f91610063565b63ffffffff909116608052600080546001600160401b03191660011790556001600160a01b031660a081905260c0526100b2565b6000806040838503121561007657600080fd5b825163ffffffff8116811461008a57600080fd5b60208401519092506001600160a01b03811681146100a757600080fd5b809150509250929050565b60805160a05160c0516107396100f4600039600081816101290152818161049b015261055b01526000607901526000818160fa01526102b801526107396000f3fe608060405234801561001057600080fd5b50600436106100725760003560e01c8063a250c66a11610050578063a250c66a14610124578063f856ddb61461014b578063fb8406a91461015e57600080fd5b80632c121921146100775780637eccf63e146100c35780639cdbb181146100f0575b600080fd5b7f00000000000000000000000000000000000000000000000000000000000000005b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b6000546100d79067ffffffffffffffff1681565b60405167ffffffffffffffff90911681526020016100ba565b60405163ffffffff7f00000000000000000000000000000000000000000000000000000000000000001681526020016100ba565b6100997f000000000000000000000000000000000000000000000000000000000000000081565b6100d761015936600461059e565b610193565b6101857f17c71eed51b181d8ae1908b4743526c6dbf099c201f158a1acd5f6718e82e8f681565b6040519081526020016100ba565b6040517f23b872dd0000000000000000000000000000000000000000000000000000000081523360048201523060248201526044810186905260009073ffffffffffffffffffffffffffffffffffffffff8416906323b872dd906064016020604051808303816000875af115801561020f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102339190610612565b506040517f42966c680000000000000000000000000000000000000000000000000000000081526004810187905273ffffffffffffffffffffffffffffffffffffffff8416906342966c6890602401600060405180830381600087803b15801561029c57600080fd5b505af11580156102b0573d6000803e3d6000fd5b5050604080517f000000000000000000000000000000000000000000000000000000000000000060e01b7fffffffff0000000000000000000000000000000000000000000000000000000016602082015273ffffffffffffffffffffffffffffffffffffffff8716602482015260448101889052606481018a9052336084808301919091528251808303909101815260a490910190915291506103779050867f17c71eed51b181d8ae1908b4743526c6dbf099c201f158a1acd5f6718e82e8f68584610457565b600080547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001667ffffffffffffffff929092169182179055604080518981526020810188905263ffffffff8916918101919091527f17c71eed51b181d8ae1908b4743526c6dbf099c201f158a1acd5f6718e82e8f6606082015260808101859052339173ffffffffffffffffffffffffffffffffffffffff8716917f2fa9ca894982930190727e75500a97d8dc500233a5065e0f3126c48fbe0343c09060a00160405180910390a4505060005467ffffffffffffffff1695945050505050565b60008261051e576040517f0ba469bc00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001690630ba469bc906104d49088908890879060040161069f565b6020604051808303816000875af11580156104f3573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061051791906106cd565b9050610596565b6040517ff7259a7500000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169063f7259a75906104d49088908890889088906004016106f7565b949350505050565b600080600080600060a086880312156105b657600080fd5b85359450602086013563ffffffff811681146105d157600080fd5b935060408601359250606086013573ffffffffffffffffffffffffffffffffffffffff8116811461060157600080fd5b949793965091946080013592915050565b60006020828403121561062457600080fd5b8151801515811461063457600080fd5b9392505050565b6000815180845260005b8181101561066157602081850181015186830182015201610645565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b63ffffffff841681528260208201526060604082015260006106c4606083018461063b565b95945050505050565b6000602082840312156106df57600080fd5b815167ffffffffffffffff8116811461063457600080fd5b63ffffffff85168152836020820152826040820152608060608201526000610722608083018461063b565b969550505050505056fea164736f6c6343000818000a", } var MockE2EUSDCTokenMessengerABI = MockE2EUSDCTokenMessengerMetaData.ABI diff --git a/core/gethwrappers/ccip/generated/mock_usdc_token_transmitter/mock_usdc_token_transmitter.go b/core/gethwrappers/ccip/generated/mock_usdc_token_transmitter/mock_usdc_token_transmitter.go index 0659a0f50d4..c3f12bab371 100644 --- a/core/gethwrappers/ccip/generated/mock_usdc_token_transmitter/mock_usdc_token_transmitter.go +++ b/core/gethwrappers/ccip/generated/mock_usdc_token_transmitter/mock_usdc_token_transmitter.go @@ -32,7 +32,7 @@ var ( var MockE2EUSDCTransmitterMetaData = &bind.MetaData{ ABI: "[{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"_version\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"_localDomain\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"message\",\"type\":\"bytes\"}],\"name\":\"MessageSent\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"localDomain\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"nextAvailableNonce\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"message\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"name\":\"receiveMessage\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"s_shouldSucceed\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"destinationDomain\",\"type\":\"uint32\"},{\"internalType\":\"bytes32\",\"name\":\"recipient\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"messageBody\",\"type\":\"bytes\"}],\"name\":\"sendMessage\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"destinationDomain\",\"type\":\"uint32\"},{\"internalType\":\"bytes32\",\"name\":\"recipient\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"destinationCaller\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"messageBody\",\"type\":\"bytes\"}],\"name\":\"sendMessageWithCaller\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bool\",\"name\":\"shouldSucceed\",\"type\":\"bool\"}],\"name\":\"setShouldSucceed\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"version\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", - Bin: "0x60e0346100c857601f610ab038819003918201601f19168301916001600160401b038311848410176100cd578084926060946040528339810103126100c857610047816100e3565b906040610056602083016100e3565b9101516001600160a01b03811692908390036100c85760805260a052600160ff19600054161760005560c0526040516109bb90816100f5823960805181818161011f0152818161063c0152610704015260a05181818161014901528181610418015261072e015260c051816105550152f35b600080fd5b634e487b7160e01b600052604160045260246000fd5b519063ffffffff821682036100c85756fe6080604052600436101561001257600080fd5b6000803560e01c80630ba469bc1461066057806354fd4d501461060157806357ecfd28146104c45780637a642935146104845780638371744e1461043c5780638d3638f4146103dd5780639e31ddb61461036e5763f7259a751461007557600080fd5b3461036b5760807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261036b576100ac61086b565b6044359160243560643567ffffffffffffffff8111610367576100d3903690600401610883565b9480156102e3576100e2610921565b94831561028557866020976101ed946094947fffffffff0000000000000000000000000000000000000000000000000000000097604051988996817f000000000000000000000000000000000000000000000000000000000000000060e01b168e890152817f000000000000000000000000000000000000000000000000000000000000000060e01b16602489015260e01b1660288701527fffffffffffffffff0000000000000000000000000000000000000000000000008b60c01b16602c87015233603487015260548601526074850152848401378101858382015203017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081018352826108b1565b604051918483528151918286850152815b838110610271575050827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f846040948585977f8c5261668696ce22758910d05bab8f186d6eb247ceac2af2e82c7dc17669b0369901015201168101030190a167ffffffffffffffff60405191168152f35b8181018701518582016040015286016101fe565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f526563697069656e74206d757374206265206e6f6e7a65726f000000000000006044820152fd5b60846040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f44657374696e6174696f6e2063616c6c6572206d757374206265206e6f6e7a6560448201527f726f0000000000000000000000000000000000000000000000000000000000006064820152fd5b8280fd5b80fd5b503461036b5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261036b576004358015158091036103d95760ff7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00835416911617815580f35b5080fd5b503461036b57807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261036b57602060405163ffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b503461036b57807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261036b5767ffffffffffffffff6020915460081c16604051908152f35b503461036b57807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261036b5760ff60209154166040519015158152f35b503461036b5760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261036b5760043567ffffffffffffffff81116103d957610514903690600401610883565b60243567ffffffffffffffff81116105fd57610534903690600401610883565b505060b8116103d9578173ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001691823b156103d957604460a4918360405195869485937f40c10f19000000000000000000000000000000000000000000000000000000008552013560601c6004840152600160248401525af180156105f2579160ff91816020946105e2575b505054166040519015158152f35b6105eb916108b1565b38816105d4565b6040513d84823e3d90fd5b8380fd5b503461036b57807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261036b57602060405163ffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b503461036b5760607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261036b5761069861086b565b906024359060443567ffffffffffffffff81116103d9576106bd903690600401610883565b90926106c7610921565b93811561028557602095837fffffffff00000000000000000000000000000000000000000000000000000000946094936107d395604051978895817f000000000000000000000000000000000000000000000000000000000000000060e01b168d880152817f000000000000000000000000000000000000000000000000000000000000000060e01b16602488015260e01b1660288601527fffffffffffffffff0000000000000000000000000000000000000000000000008a60c01b16602c8601523360348601526054850152876074850152848401378101858382015203017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081018352826108b1565b604051918483528151918286850152815b838110610857575050827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f846040948585977f8c5261668696ce22758910d05bab8f186d6eb247ceac2af2e82c7dc17669b0369901015201168101030190a167ffffffffffffffff60405191168152f35b8181018701518582016040015286016107e4565b6004359063ffffffff8216820361087e57565b600080fd5b9181601f8401121561087e5782359167ffffffffffffffff831161087e576020838186019501011161087e57565b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff8211176108f257604052565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60005467ffffffffffffffff8160081c16906001820167ffffffffffffffff811161097f5768ffffffffffffffff007fffffffffffffffffffffffffffffffffffffffffffffff0000000000000000ff9160081b1691161760005590565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fdfea164736f6c634300081a000a", + Bin: "0x60e060405234801561001057600080fd5b5060405161097338038061097383398101604081905261002f91610076565b63ffffffff928316608052911660a0526000805460ff191660011790556001600160a01b031660c0526100ca565b805163ffffffff8116811461007157600080fd5b919050565b60008060006060848603121561008b57600080fd5b6100948461005d565b92506100a26020850161005d565b60408501519092506001600160a01b03811681146100bf57600080fd5b809150509250925092565b60805160a05160c05161086d610106600039600061024e015260008181610140015261045801526000818160c00152610437015261086d6000f3fe608060405234801561001057600080fd5b50600436106100885760003560e01c80638371744e1161005b5780638371744e146101255780638d3638f41461013e5780639e31ddb614610164578063f7259a75146101a557600080fd5b80630ba469bc1461008d57806354fd4d50146100be57806357ecfd28146100f55780637a64293514610118575b600080fd5b6100a061009b36600461054a565b6101b8565b60405167ffffffffffffffff90911681526020015b60405180910390f35b7f00000000000000000000000000000000000000000000000000000000000000005b60405163ffffffff90911681526020016100b5565b6101086101033660046105a4565b6101e1565b60405190151581526020016100b5565b6000546101089060ff1681565b6000546100a090610100900467ffffffffffffffff1681565b7f00000000000000000000000000000000000000000000000000000000000000006100e0565b6101a3610172366004610604565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016911515919091179055565b005b6100a06101b336600461062d565b6102ba565b600080806101c461036a565b9050336101d688888584868b8b6103cc565b509695505050505050565b6000806101f260b860a48789610695565b6101fb916106bf565b6040517f40c10f1900000000000000000000000000000000000000000000000000000000815260609190911c6004820181905260016024830152915073ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016906340c10f1990604401600060405180830381600087803b15801561029257600080fd5b505af11580156102a6573d6000803e3d6000fd5b505060005460ff1698975050505050505050565b60008361034e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f44657374696e6174696f6e2063616c6c6572206d757374206265206e6f6e7a6560448201527f726f00000000000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b600061035861036a565b9050336101d688888884868a8a6103cc565b60008054610100900467ffffffffffffffff16610388816001610707565b6000805467ffffffffffffffff92909216610100027fffffffffffffffffffffffffffffffffffffffffffffff0000000000000000ff909216919091179055919050565b85610433576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f526563697069656e74206d757374206265206e6f6e7a65726f000000000000006044820152606401610345565b60007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000008986888b8b898960405160200161049699989796959493929190610756565b60405160208183030381529060405290507f8c5261668696ce22758910d05bab8f186d6eb247ceac2af2e82c7dc17669b036816040516104d691906107f3565b60405180910390a15050505050505050565b803563ffffffff811681146104fc57600080fd5b919050565b60008083601f84011261051357600080fd5b50813567ffffffffffffffff81111561052b57600080fd5b60208301915083602082850101111561054357600080fd5b9250929050565b6000806000806060858703121561056057600080fd5b610569856104e8565b935060208501359250604085013567ffffffffffffffff81111561058c57600080fd5b61059887828801610501565b95989497509550505050565b600080600080604085870312156105ba57600080fd5b843567ffffffffffffffff808211156105d257600080fd5b6105de88838901610501565b909650945060208701359150808211156105f757600080fd5b5061059887828801610501565b60006020828403121561061657600080fd5b8135801515811461062657600080fd5b9392505050565b60008060008060006080868803121561064557600080fd5b61064e866104e8565b94506020860135935060408601359250606086013567ffffffffffffffff81111561067857600080fd5b61068488828901610501565b969995985093965092949392505050565b600080858511156106a557600080fd5b838611156106b257600080fd5b5050820193919092039150565b7fffffffffffffffffffffffffffffffffffffffff00000000000000000000000081358181169160148510156106ff5780818660140360031b1b83161692505b505092915050565b67ffffffffffffffff81811683821601908082111561074f577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b5092915050565b60007fffffffff00000000000000000000000000000000000000000000000000000000808c60e01b168352808b60e01b166004840152808a60e01b166008840152507fffffffffffffffff0000000000000000000000000000000000000000000000008860c01b16600c83015286601483015285603483015284605483015282846074840137506000910160740190815298975050505050505050565b60006020808352835180602085015260005b8181101561082157858101830151858201604001528201610805565b5060006040828601015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f830116850101925050509291505056fea164736f6c6343000818000a", } var MockE2EUSDCTransmitterABI = MockE2EUSDCTransmitterMetaData.ABI diff --git a/core/gethwrappers/ccip/generated/mock_v3_aggregator_contract/mock_v3_aggregator_contract.go b/core/gethwrappers/ccip/generated/mock_v3_aggregator_contract/mock_v3_aggregator_contract.go index 4d29f5849a2..c3521d35151 100644 --- a/core/gethwrappers/ccip/generated/mock_v3_aggregator_contract/mock_v3_aggregator_contract.go +++ b/core/gethwrappers/ccip/generated/mock_v3_aggregator_contract/mock_v3_aggregator_contract.go @@ -32,7 +32,7 @@ var ( var MockV3AggregatorMetaData = &bind.MetaData{ ABI: "[{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"_decimals\",\"type\":\"uint8\"},{\"internalType\":\"int256\",\"name\":\"_initialAnswer\",\"type\":\"int256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"int256\",\"name\":\"current\",\"type\":\"int256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"roundId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"updatedAt\",\"type\":\"uint256\"}],\"name\":\"AnswerUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"roundId\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"startedBy\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"startedAt\",\"type\":\"uint256\"}],\"name\":\"NewRound\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"decimals\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"description\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"getAnswer\",\"outputs\":[{\"internalType\":\"int256\",\"name\":\"\",\"type\":\"int256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint80\",\"name\":\"_roundId\",\"type\":\"uint80\"}],\"name\":\"getRoundData\",\"outputs\":[{\"internalType\":\"uint80\",\"name\":\"roundId\",\"type\":\"uint80\"},{\"internalType\":\"int256\",\"name\":\"answer\",\"type\":\"int256\"},{\"internalType\":\"uint256\",\"name\":\"startedAt\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"updatedAt\",\"type\":\"uint256\"},{\"internalType\":\"uint80\",\"name\":\"answeredInRound\",\"type\":\"uint80\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"getTimestamp\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"latestAnswer\",\"outputs\":[{\"internalType\":\"int256\",\"name\":\"\",\"type\":\"int256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"latestRound\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"latestRoundData\",\"outputs\":[{\"internalType\":\"uint80\",\"name\":\"roundId\",\"type\":\"uint80\"},{\"internalType\":\"int256\",\"name\":\"answer\",\"type\":\"int256\"},{\"internalType\":\"uint256\",\"name\":\"startedAt\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"updatedAt\",\"type\":\"uint256\"},{\"internalType\":\"uint80\",\"name\":\"answeredInRound\",\"type\":\"uint80\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"latestTimestamp\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"int256\",\"name\":\"_answer\",\"type\":\"int256\"}],\"name\":\"updateAnswer\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint80\",\"name\":\"_roundId\",\"type\":\"uint80\"},{\"internalType\":\"int256\",\"name\":\"_answer\",\"type\":\"int256\"},{\"internalType\":\"uint256\",\"name\":\"_timestamp\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_startedAt\",\"type\":\"uint256\"}],\"name\":\"updateRoundData\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"version\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", - Bin: "0x60803460c857601f6106f738819003918201601f19168301916001600160401b0383118484101760cd57808492604094855283398101031260c85780519060ff821680920360c857602001519060ff1960005416176000558060015542600255600354600019811460b25760010180600355600052600460205260406000205560035460005260056020524260406000205560035460005260066020524260406000205560405161061390816100e48239f35b634e487b7160e01b600052601160045260246000fd5b600080fd5b634e487b7160e01b600052604160045260246000fdfe608080604052600436101561001357600080fd5b60003560e01c908163313ce567146105b1575080634aa2011f1461052357806350d25bcd146104e757806354fd4d50146104ad578063668a0f02146104715780637284e4161461035f5780638205bf6a146103235780639a6fc8f514610295578063a87a20ce146101c4578063b5ab58dc1461017a578063b633620c146101305763feaf968c146100a357600080fd5b3461012b5760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261012b576003546000818152600460209081526040808320546006835281842054600584529382902054825169ffffffffffffffffffff90961680875293860191909152908401929092526060830191909152608082015260a090f35b600080fd5b3461012b5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261012b5760043560005260056020526020604060002054604051908152f35b3461012b5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261012b5760043560005260046020526020604060002054604051908152f35b3461012b5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261012b5760043580600155426002556003547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff811461026657600101806003556000526004602052604060002055600354600052600560205242604060002055600354600052600660205242604060002055600080f35b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b3461012b5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261012b576102cc6105ed565b69ffffffffffffffffffff166000818152600460209081526040808320546006835281842054600584529382902054825186815293840191909152908201929092526060810191909152608081019190915260a090f35b3461012b5760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261012b576020600254604051908152f35b3461012b5760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261012b576040516040810181811067ffffffffffffffff82111761044257604052601f81527f76302e382f74657374732f4d6f636b563341676772656761746f722e736f6c00602082015260405190602082528181519182602083015260005b83811061042a5750507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f836000604080968601015201168101030190f35b602082820181015160408784010152859350016103ea565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b3461012b5760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261012b576020600354604051908152f35b3461012b5760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261012b57602060405160008152f35b3461012b5760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261012b576020600154604051908152f35b3461012b5760807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261012b5761055a6105ed565b60243569ffffffffffffffffffff6044359216806003558160015582600255600052600460205260406000205560035460005260056020526040600020556003546000526006602052606435604060002055600080f35b3461012b5760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261012b5760209060ff600054168152f35b6004359069ffffffffffffffffffff8216820361012b5756fea164736f6c634300081a000a", + Bin: "0x608060405234801561001057600080fd5b5060405161059638038061059683398101604081905261002f916100a4565b6000805460ff191660ff84161790556100478161004e565b50506100ff565b60018190554260025560038054906000610067836100d8565b9091555050600380546000908152600460209081526040808320949094558254825260058152838220429081905592548252600690529190912055565b600080604083850312156100b757600080fd5b825160ff811681146100c857600080fd5b6020939093015192949293505050565b6000600182016100f857634e487b7160e01b600052601160045260246000fd5b5060010190565b6104888061010e6000396000f3fe608060405234801561001057600080fd5b50600436106100d45760003560e01c80638205bf6a11610081578063b5ab58dc1161005b578063b5ab58dc1461025b578063b633620c1461027b578063feaf968c1461029b57600080fd5b80638205bf6a146101c15780639a6fc8f5146101ca578063a87a20ce1461024857600080fd5b806354fd4d50116100b257806354fd4d5014610171578063668a0f02146101795780637284e4161461018257600080fd5b8063313ce567146100d95780634aa2011f146100fd57806350d25bcd1461015a575b600080fd5b6000546100e69060ff1681565b60405160ff90911681526020015b60405180910390f35b61015861010b36600461033b565b69ffffffffffffffffffff90931660038181556001849055600283905560009182526004602090815260408084209590955581548352600581528483209390935554815260069091522055565b005b61016360015481565b6040519081526020016100f4565b610163600081565b61016360035481565b604080518082018252601f81527f76302e382f74657374732f4d6f636b563341676772656761746f722e736f6c00602082015290516100f49190610374565b61016360025481565b6102116101d83660046103e1565b69ffffffffffffffffffff8116600090815260046020908152604080832054600683528184205460059093529220549293919290918490565b6040805169ffffffffffffffffffff968716815260208101959095528401929092526060830152909116608082015260a0016100f4565b610158610256366004610403565b6102c6565b610163610269366004610403565b60046020526000908152604090205481565b610163610289366004610403565b60056020526000908152604090205481565b6003546000818152600460209081526040808320546006835281842054600590935292205483610211565b600181905542600255600380549060006102df8361041c565b9091555050600380546000908152600460209081526040808320949094558254825260058152838220429081905592548252600690529190912055565b803569ffffffffffffffffffff8116811461033657600080fd5b919050565b6000806000806080858703121561035157600080fd5b61035a8561031c565b966020860135965060408601359560600135945092505050565b60006020808352835180602085015260005b818110156103a257858101830151858201604001528201610386565b5060006040828601015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8301168501019250505092915050565b6000602082840312156103f357600080fd5b6103fc8261031c565b9392505050565b60006020828403121561041557600080fd5b5035919050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203610474577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b506001019056fea164736f6c6343000818000a", } var MockV3AggregatorABI = MockV3AggregatorMetaData.ABI diff --git a/core/gethwrappers/ccip/generated/multi_aggregate_rate_limiter/multi_aggregate_rate_limiter.go b/core/gethwrappers/ccip/generated/multi_aggregate_rate_limiter/multi_aggregate_rate_limiter.go index a52433265d9..7c2e2319b95 100644 --- a/core/gethwrappers/ccip/generated/multi_aggregate_rate_limiter/multi_aggregate_rate_limiter.go +++ b/core/gethwrappers/ccip/generated/multi_aggregate_rate_limiter/multi_aggregate_rate_limiter.go @@ -88,7 +88,7 @@ type RateLimiterTokenBucket struct { var MultiAggregateRateLimiterMetaData = &bind.MetaData{ ABI: "[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"address[]\",\"name\":\"authorizedCallers\",\"type\":\"address[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"capacity\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"requested\",\"type\":\"uint256\"}],\"name\":\"AggregateValueMaxCapacityExceeded\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"minWaitInSeconds\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"available\",\"type\":\"uint256\"}],\"name\":\"AggregateValueRateLimitReached\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"BucketOverfilled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CannotTransferToSelf\",\"type\":\"error\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"config\",\"type\":\"tuple\"}],\"name\":\"DisabledNonZeroRateLimit\",\"type\":\"error\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"rateLimiterConfig\",\"type\":\"tuple\"}],\"name\":\"InvalidRateLimitRate\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"errorReason\",\"type\":\"bytes\"}],\"name\":\"MessageValidationError\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MustBeProposedOwner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByOwner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OwnerCannotBeZero\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"PriceNotFoundForToken\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RateLimitMustBeDisabled\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"capacity\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"requested\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenAddress\",\"type\":\"address\"}],\"name\":\"TokenMaxCapacityExceeded\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"minWaitInSeconds\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"available\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenAddress\",\"type\":\"address\"}],\"name\":\"TokenRateLimitReached\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"UnauthorizedCaller\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroChainSelectorNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"AuthorizedCallerAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"AuthorizedCallerRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"config\",\"type\":\"tuple\"}],\"name\":\"ConfigChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newFeeQuoter\",\"type\":\"address\"}],\"name\":\"FeeQuoterSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"isOutboundLane\",\"type\":\"bool\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"config\",\"type\":\"tuple\"}],\"name\":\"RateLimiterConfigUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"remoteToken\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"localToken\",\"type\":\"address\"}],\"name\":\"TokenAggregateRateLimitAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"localToken\",\"type\":\"address\"}],\"name\":\"TokenAggregateRateLimitRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokens\",\"type\":\"uint256\"}],\"name\":\"TokensConsumed\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address[]\",\"name\":\"addedCallers\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"removedCallers\",\"type\":\"address[]\"}],\"internalType\":\"structAuthorizedCallers.AuthorizedCallerArgs\",\"name\":\"authorizedCallerArgs\",\"type\":\"tuple\"}],\"name\":\"applyAuthorizedCallerUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"isOutboundLane\",\"type\":\"bool\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"rateLimiterConfig\",\"type\":\"tuple\"}],\"internalType\":\"structMultiAggregateRateLimiter.RateLimiterConfigArgs[]\",\"name\":\"rateLimiterUpdates\",\"type\":\"tuple[]\"}],\"name\":\"applyRateLimiterConfigUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"isOutboundLane\",\"type\":\"bool\"}],\"name\":\"currentRateLimiterState\",\"outputs\":[{\"components\":[{\"internalType\":\"uint128\",\"name\":\"tokens\",\"type\":\"uint128\"},{\"internalType\":\"uint32\",\"name\":\"lastUpdated\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.TokenBucket\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAllAuthorizedCallers\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getAllRateLimitTokens\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"localTokens\",\"type\":\"address[]\"},{\"internalType\":\"bytes[]\",\"name\":\"remoteTokens\",\"type\":\"bytes[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getFeeQuoter\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"sender\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structClient.EVMTokenAmount[]\",\"name\":\"destTokenAmounts\",\"type\":\"tuple[]\"}],\"internalType\":\"structClient.Any2EVMMessage\",\"name\":\"message\",\"type\":\"tuple\"}],\"name\":\"onInboundMessage\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structClient.EVMTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"},{\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"extraArgs\",\"type\":\"bytes\"}],\"internalType\":\"structClient.EVM2AnyMessage\",\"name\":\"message\",\"type\":\"tuple\"}],\"name\":\"onOutboundMessage\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newFeeQuoter\",\"type\":\"address\"}],\"name\":\"setFeeQuoter\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"localToken\",\"type\":\"address\"}],\"internalType\":\"structMultiAggregateRateLimiter.LocalRateLimitToken[]\",\"name\":\"removes\",\"type\":\"tuple[]\"},{\"components\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"localToken\",\"type\":\"address\"}],\"internalType\":\"structMultiAggregateRateLimiter.LocalRateLimitToken\",\"name\":\"localTokenArgs\",\"type\":\"tuple\"},{\"internalType\":\"bytes\",\"name\":\"remoteToken\",\"type\":\"bytes\"}],\"internalType\":\"structMultiAggregateRateLimiter.RateLimitTokenArgs[]\",\"name\":\"adds\",\"type\":\"tuple[]\"}],\"name\":\"updateRateLimitTokens\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", - Bin: "0x60806040523461026457612f548038038061001981610269565b928339810190604081830312610264576100328161028e565b602082015190916001600160401b03821161026457019180601f84011215610264578251926001600160401b038411610225578360051b90602080610078818501610269565b80978152019282010192831161026457602001905b82821061024c57505050331561023b57600180546001600160a01b0319163317905560206100ba81610269565b60008152600036813760408051949085016001600160401b03811186821017610225576040528452808285015260005b8151811015610151576001906001600160a01b0361010882856102a2565b511684610114826102e4565b610121575b5050016100ea565b7fc3803387881faad271c47728894e3e36fac830ffc8602ca6fc07733cbda7758091604051908152a13884610119565b5050915160005b81518110156101c9576001600160a01b0361017382846102a2565b51169081156101b8577feb1b9b92e50b7f88f9ff25d56765095ac6e91540eee214906f4036a908ffbdef85836101aa6001956103e2565b50604051908152a101610158565b6342bcdf7f60e11b60005260046000fd5b50506001600160a01b03169081156101b857600580546001600160a01b031916831790556040519182527f7c737a8eddf62436489aa3600ed26e75e0a58b0f8c0d266bbcee64358c39fdac91a1604051612b1190816104438239f35b634e487b7160e01b600052604160045260246000fd5b639b15e16f60e01b60005260046000fd5b602080916102598461028e565b81520191019061008d565b600080fd5b6040519190601f01601f191682016001600160401b0381118382101761022557604052565b51906001600160a01b038216820361026457565b80518210156102b65760209160051b010190565b634e487b7160e01b600052603260045260246000fd5b80548210156102b65760005260206000200190600090565b60008181526003602052604090205480156103db5760001981018181116103c5576002546000198101919082116103c557808203610374575b505050600254801561035e57600019016103388160026102cc565b8154906000199060031b1b19169055600255600052600360205260006040812055600190565b634e487b7160e01b600052603160045260246000fd5b6103ad6103856103969360026102cc565b90549060031b1c92839260026102cc565b819391549060031b91821b91600019901b19161790565b9055600052600360205260406000205538808061031d565b634e487b7160e01b600052601160045260246000fd5b5050600090565b8060005260036020526040600020541560001461043c57600254680100000000000000008110156102255761042361039682600185940160025560026102cc565b9055600254906000526003602052604060002055600190565b5060009056fe608080604052600436101561001357600080fd5b60003560e01c90816308d450a114611ca3575080630a35bcc414611b72578063181f5a7714611ace5780631af18b7b1461156c5780632451a627146114bf578063537e304e146111f557806379ba50971461110c5780638da5cb5b146110ba57806391a2749a14610efc578063e0a0e50614610bbb578063e145291614610b69578063e835232b14610a8d578063f2fde38b1461099d5763fe843cd0146100b957600080fd5b346109985760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126109985760043567ffffffffffffffff81116109985736602382011215610998578060040135610113816120da565b916101216040519384611ff8565b818352602460a06020850193028201019036821161099857602401915b8183106108ea578361014e61243d565b6000905b80518210156108e8576101658282612345565b519160408301519267ffffffffffffffff8151169081156108be576020015115156101908183612408565b805463ffffffff8160801c16801560001461066757505085516000915015610592576fffffffffffffffffffffffffffffffff6040870151166fffffffffffffffffffffffffffffffff602088015116811090811591610589575b50610526577ff14a5415ce6988a9e870a85fff0b9d7b7dd79bbc228cb63cad610daf6f7b6b979161042960019697608093505b6fffffffffffffffffffffffffffffffff6040820151166fffffffffffffffffffffffffffffffff602083015116825115159160405161025d81611fa4565b828152602081019363ffffffff4216855260408201908152606082019384528882019283528a886000146104315760036103ef966103816fffffffffffffffffffffffffffffffff969587958695600052600660205261033a63ffffffff604060002095888060028901965116167fffffffffffffffffffffffffffffffff00000000000000000000000000000000865416178555511683907fffffffffffffffffffffffff00000000ffffffffffffffffffffffffffffffff73ffffffff0000000000000000000000000000000083549260801b169116179055565b5181547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1690151560a01b74ff000000000000000000000000000000000000000016179055565b01945116167fffffffffffffffffffffffffffffffff0000000000000000000000000000000084541617835551166fffffffffffffffffffffffffffffffff7fffffffffffffffffffffffffffffffff0000000000000000000000000000000083549260801b169116179055565b60405192835260208301906fffffffffffffffffffffffffffffffff60408092805115158552826020820151166020860152015116910152565ba20190610152565b8d6fffffffffffffffffffffffffffffffff949361038186946104da63ffffffff6105219b8897600052600660205287806040600020975116167fffffffffffffffffffffffffffffffff00000000000000000000000000000000875416178655511684907fffffffffffffffffffffffff00000000ffffffffffffffffffffffffffffffff73ffffffff0000000000000000000000000000000083549260801b169116179055565b5182547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1690151560a01b74ff000000000000000000000000000000000000000016178255565b6103ef565b606486610587604051917f8020d12400000000000000000000000000000000000000000000000000000000835260048301906fffffffffffffffffffffffffffffffff60408092805115158552826020820151166020860152015116910152565bfd5b905015876101eb565b506fffffffffffffffffffffffffffffffff60408601511615801590610648575b6105e75760807ff14a5415ce6988a9e870a85fff0b9d7b7dd79bbc228cb63cad610daf6f7b6b97916104296001969761021e565b606485610587604051917fd68af9cc00000000000000000000000000000000000000000000000000000000835260048301906fffffffffffffffffffffffffffffffff60408092805115158552826020820151166020860152015116910152565b506fffffffffffffffffffffffffffffffff60208601511615156105b3565b6001969761079c6080947ff14a5415ce6988a9e870a85fff0b9d7b7dd79bbc228cb63cad610daf6f7b6b9796946106a16104299542612430565b9081610804575b50506fffffffffffffffffffffffffffffffff8a8160208601511692828154168085106000146107fc57508280855b16167fffffffffffffffffffffffffffffffff000000000000000000000000000000008254161781556107508651151582907fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff74ff0000000000000000000000000000000000000000835492151560a01b169116179055565b60408601517fffffffffffffffffffffffffffffffff0000000000000000000000000000000060809190911b16939092166fffffffffffffffffffffffffffffffff1692909217910155565b7f9ea3374b67bf275e6bb9c8ae68f9cae023e1c528b4b27e092f0bb209d3531c1960606040516107f681856fffffffffffffffffffffffffffffffff60408092805115158552826020820151166020860152015116910152565ba16103ef565b8380916106d7565b6fffffffffffffffffffffffffffffffff916108388392838f6108319088015494828616958e1c906126f0565b91166123cc565b808210156108b757505b83547fffffffffffffffffffffffff00000000ffffffffffffffffffffffffffffffff9290911692909216167fffffffffffffffffffffffff0000000000000000000000000000000000000000909116174260801b73ffffffff00000000000000000000000000000000161781558b806106a8565b9050610842565b7fc65608950000000000000000000000000000000000000000000000000000000060005260046000fd5b005b82360360a081126109985760607fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc06040519261092584611fdc565b61092e87612050565b845261093c602088016121ac565b602085015201126109985760a09160209160405161095981611fdc565b610965604088016121ac565b8152610973606088016122fd565b84820152610983608088016122fd565b6040820152604082015281520192019161013e565b600080fd5b346109985760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126109985773ffffffffffffffffffffffffffffffffffffffff6109e96120f2565b6109f161243d565b16338114610a6357807fffffffffffffffffffffffff0000000000000000000000000000000000000000600054161760005573ffffffffffffffffffffffffffffffffffffffff600154167fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae1278600080a3005b7fdad89dca0000000000000000000000000000000000000000000000000000000060005260046000fd5b346109985760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126109985773ffffffffffffffffffffffffffffffffffffffff610ad96120f2565b610ae161243d565b168015610b3f576020817f7c737a8eddf62436489aa3600ed26e75e0a58b0f8c0d266bbcee64358c39fdac927fffffffffffffffffffffffff00000000000000000000000000000000000000006005541617600555604051908152a1005b7f8579befe0000000000000000000000000000000000000000000000000000000060005260046000fd5b346109985760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261099857602073ffffffffffffffffffffffffffffffffffffffff60055416604051908152f35b346109985760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261099857610bf2612039565b60243567ffffffffffffffff8111610998578036039060a07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc83011261099857610c3a612388565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdd60448201359201821215610998570160048101359067ffffffffffffffff8211610998576024018160061b3603811361099857610c99913691612136565b90610ca5600182612408565b9160ff835460a01c16610cb457005b6000929167ffffffffffffffff16835b8251811015610ee857816000526004602052610d16604060002073ffffffffffffffffffffffffffffffffffffffff610cfd8487612345565b5151169060019160005201602052604060002054151590565b610d23575b600101610cc4565b93610d2e8584612345565b5173ffffffffffffffffffffffffffffffffffffffff60055416604073ffffffffffffffffffffffffffffffffffffffff83511660248251809481937fd02641a000000000000000000000000000000000000000000000000000000000835260048301525afa8015610edc57600090610e3c575b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff91505116908115610df75791670de0b6b3a7640000610de8610def9360206001960151906126f0565b04906123cc565b949050610d1b565b73ffffffffffffffffffffffffffffffffffffffff9051167f9a655f7b0000000000000000000000000000000000000000000000000000000060005260045260246000fd5b6040823d8211610ed4575b81610e5460409383611ff8565b81010312610ecd5760405191610e6983611fc0565b80517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff81168103610ed0578352602001519063ffffffff82168203610ecd575060208201527bffffffffffffffffffffffffffffffffffffffffffffffffffffffff90610da2565b80fd5b8280fd5b3d9150610e47565b6040513d6000823e3d90fd5b5050509080610ef357005b6108e891612488565b346109985760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126109985760043567ffffffffffffffff81116109985760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc82360301126109985760405190610f7682611fc0565b806004013567ffffffffffffffff811161099857610f9a9060043691840101612298565b825260248101359067ffffffffffffffff8211610998576004610fc09236920101612298565b60208201908152610fcf61243d565b519060005b8251811015611047578073ffffffffffffffffffffffffffffffffffffffff610fff60019386612345565b511661100a81612785565b611016575b5001610fd4565b60207fc3803387881faad271c47728894e3e36fac830ffc8602ca6fc07733cbda7758091604051908152a18461100f565b505160005b81518110156108e85773ffffffffffffffffffffffffffffffffffffffff6110748284612345565b5116908115610b3f577feb1b9b92e50b7f88f9ff25d56765095ac6e91540eee214906f4036a908ffbdef6020836110ac600195612a4f565b50604051908152a10161104c565b346109985760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261099857602073ffffffffffffffffffffffffffffffffffffffff60015416604051908152f35b346109985760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126109985760005473ffffffffffffffffffffffffffffffffffffffff811633036111cb577fffffffffffffffffffffffff00000000000000000000000000000000000000006001549133828416176001551660005573ffffffffffffffffffffffffffffffffffffffff3391167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0600080a3005b7f02b543c60000000000000000000000000000000000000000000000000000000060005260046000fd5b346109985760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126109985767ffffffffffffffff611235612039565b168060005260046020526040600020549061124f826120da565b9161125d6040519384611ff8565b8083527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe061128a826120da565b0136602085013761129a816120da565b916112a86040519384611ff8565b8183527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe06112d5836120da565b0160005b8181106114ae57505060005b82811061138457611305858560405192839260408452604084019061224e565b8281036020840152815180825260208201916020808360051b8301019401926000915b8383106113355786860387f35b919395509193602080611372837fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0866001960301875289516121b9565b97019301930190928695949293611328565b8160005260046020526040600020600261139e838361276d565b90549060031b1c918260005201602052604060002090604051916000908054906113c782612703565b8086529160018116908115611469575060011461142f575b505082916114076001959473ffffffffffffffffffffffffffffffffffffffff930384611ff8565b166114128389612345565b5261141d8287612345565b526114288186612345565b50016112e5565b6000908152602081209092505b8183106114535750508201602001816114076113df565b600181602092548386890101520192019161143c565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660208088019190915292151560051b8601909201925083915061140790506113df565b8060606020809388010152016112d9565b346109985760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126109985760405180602060025491828152019060026000527f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ace9060005b818110611556576115528561153e81870382611ff8565b60405191829160208352602083019061224e565b0390f35b8254845260209093019260019283019201611527565b346109985760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126109985760043567ffffffffffffffff81116109985736602382011215610998578060040135906115c7826120da565b916115d56040519384611ff8565b8083526024602084019160061b8301019136831161099857602401905b828210611ab4576024358467ffffffffffffffff82116109985736602383011215610998578160040135611625816120da565b926116336040519485611ff8565b8184526024602085019260051b820101903682116109985760248101925b828410611a2157858561166261243d565b60005b815181101561176d578073ffffffffffffffffffffffffffffffffffffffff602061169260019486612345565b5101511667ffffffffffffffff6116a98386612345565b515116908160005260046020526116e7816040600020816000526002810160205260406000206116d98154612703565b908161172b575b505061291b565b6116f4575b505001611665565b7f530cabd30786b7235e124a6c0db77e0b685ef22813b1fe87554247f404eb8ed69160409182519182526020820152a184806116ec565b81601f600093118a146117425750555b89806116e0565b8183526020832061175d91601f0160051c8101908b01612756565b808252816020812091555561173b565b8260005b81518110156108e8576117848183612345565b515160206117928385612345565b51015173ffffffffffffffffffffffffffffffffffffffff6020830151169182158015611a18575b80156119ec575b610b3f5767ffffffffffffffff905116806000526004602052604060002083600052600281016020526040600020835167ffffffffffffffff81116119bd5761180a8254612703565b601f8111611980575b506020601f82116001146118d5579261186d9282889796959360019a99946000916118ca575b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff828c1b9260031b1c1916179055612aaf565b61187b575b50505001611771565b7fad72a792d2a307f400c278be7deaeec6964276783304580cdc4e905436b8d5c5926118b960405193849384526060602085015260608401906121b9565b9060408301520390a1838080611872565b90508701518c611839565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe082169083600052806000209160005b818110611968575083899897969361186d969360019c9b968d9410611931575b5050811b019055612aaf565b8901517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88460031b161c191690558c80611925565b9192602060018192868c015181550194019201611905565b6119ad90836000526020600020601f840160051c810191602085106119b3575b601f0160051c0190612756565b88611813565b90915081906119a0565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b508151602083012060405160208101906000825260208152611a0f604082611ff8565b519020146117c1565b508151156117ba565b833567ffffffffffffffff811161099857820160607fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdc82360301126109985760405191611a6d83611fc0565b611a7a3660248401612218565b835260648201359267ffffffffffffffff841161099857611aa5602094936024869536920101612065565b83820152815201930192611651565b6020604091611ac33685612218565b8152019101906115f2565b346109985760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261099857611552604051611b0e606082611ff8565b602381527f4d756c7469416767726567617465526174654c696d6974657220312e362e302d60208201527f646576000000000000000000000000000000000000000000000000000000000060408201526040519182916020835260208301906121b9565b346109985760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261099857611ba9612039565b6024359081151582036109985760a091611bcb91611bc561231a565b50612408565b6fffffffffffffffffffffffffffffffff60405191611be983611fa4565b8181549181831685526001602086019163ffffffff8560801c16835260ff6040880195891c161515855201549263ffffffff60608701928486168452608088019560801c8652611c3761231a565b508480855116611c64828b5116611c5e611c548787511642612430565b858c5116906126f0565b906123cc565b80821015611c9c57505b1680985281421681526040519788525116602087015251151560408601525116606084015251166080820152f35b9050611c6e565b346109985760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126109985760043567ffffffffffffffff81116109985760a07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc823603011261099857611d1982611fa4565b80600401358252611d2c60248201612050565b9060208301918252604481013567ffffffffffffffff811161099857611d589060043691840101612065565b6040840152606481013567ffffffffffffffff811161099857611d819060043691840101612065565b606084015260848101359067ffffffffffffffff821161099857019036602383011215610998576080611dc767ffffffffffffffff933690602460048201359101612136565b9301928352611dd4612388565b51169051611de3600083612408565b9060ff825460a01c16611df257005b60009260005b8251811015610ee857816000526004602052611e31604060002073ffffffffffffffffffffffffffffffffffffffff610cfd8487612345565b611e3e575b600101611df8565b93611e498584612345565b5173ffffffffffffffffffffffffffffffffffffffff60055416604073ffffffffffffffffffffffffffffffffffffffff83511660248251809481937fd02641a000000000000000000000000000000000000000000000000000000000835260048301525afa8015610edc57600090611f0b575b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff91505116908115610df75791670de0b6b3a7640000610de8611f039360206001960151906126f0565b949050611e36565b6040823d8211611f9c575b81611f2360409383611ff8565b81010312610ecd5760405191611f3883611fc0565b80517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff81168103610ed0578352602001519063ffffffff82168203610ecd575060208201527bffffffffffffffffffffffffffffffffffffffffffffffffffffffff90611ebd565b3d9150611f16565b60a0810190811067ffffffffffffffff8211176119bd57604052565b6040810190811067ffffffffffffffff8211176119bd57604052565b6060810190811067ffffffffffffffff8211176119bd57604052565b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff8211176119bd57604052565b6004359067ffffffffffffffff8216820361099857565b359067ffffffffffffffff8216820361099857565b81601f820112156109985780359067ffffffffffffffff82116119bd57604051926120b8601f84017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200185611ff8565b8284526020838301011161099857816000926020809301838601378301015290565b67ffffffffffffffff81116119bd5760051b60200190565b6004359073ffffffffffffffffffffffffffffffffffffffff8216820361099857565b359073ffffffffffffffffffffffffffffffffffffffff8216820361099857565b929192612142826120da565b936121506040519586611ff8565b602085848152019260061b82019181831161099857925b8284106121745750505050565b604084830312610998576020604091825161218e81611fc0565b61219787612115565b81528287013583820152815201930192612167565b3590811515820361099857565b919082519283825260005b8481106122035750507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8460006020809697860101520116010190565b806020809284010151828286010152016121c4565b91908260409103126109985760405161223081611fc0565b602061224981839561224181612050565b855201612115565b910152565b906020808351928381520192019060005b81811061226c5750505090565b825173ffffffffffffffffffffffffffffffffffffffff1684526020938401939092019160010161225f565b9080601f830112156109985781356122af816120da565b926122bd6040519485611ff8565b81845260208085019260051b82010192831161099857602001905b8282106122e55750505090565b602080916122f284612115565b8152019101906122d8565b35906fffffffffffffffffffffffffffffffff8216820361099857565b6040519061232782611fa4565b60006080838281528260208201528260408201528260608201520152565b80518210156123595760209160051b010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b3360005260036020526040600020541561239e57565b7fd86ad9cf000000000000000000000000000000000000000000000000000000006000523360045260246000fd5b919082018092116123d957565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b67ffffffffffffffff16600052600660205260406000209060001461242d5760020190565b90565b919082039182116123d957565b73ffffffffffffffffffffffffffffffffffffffff60015416330361245e57565b7f2b5c74de0000000000000000000000000000000000000000000000000000000060005260046000fd5b805460ff8160a01c161580156126e8575b6126e3576fffffffffffffffffffffffffffffffff811690600183019081546124de63ffffffff6fffffffffffffffffffffffffffffffff83169360801c1642612430565b9081612645575b5050848110612613575083821061256a5750916020916fffffffffffffffffffffffffffffffff80612538847f1871cdf8010e63f2eb8384381a68dfa7416dc571a5517e66e88b2d2d0c0a690a97612430565b16167fffffffffffffffffffffffffffffffff00000000000000000000000000000000825416179055604051908152a1565b5460801c6125788285612430565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82018281116123d9576125ab916123cc565b9080156125e45790047f15279c080000000000000000000000000000000000000000000000000000000060005260045260245260446000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b84907ff94ebcd10000000000000000000000000000000000000000000000000000000060005260045260245260446000fd5b8285929395116126b95761266092611c5e9160801c906126f0565b808310156126b45750815b83547fffffffffffffffffffffffff00000000ffffffffffffffffffffffffffffffff164260801b73ffffffff00000000000000000000000000000000161784559138806124e5565b61266b565b7f9725942a0000000000000000000000000000000000000000000000000000000060005260046000fd5b505050565b508215612499565b818102929181159184041417156123d957565b90600182811c9216801561274c575b602083101461271d57565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b91607f1691612712565b818110612761575050565b60008155600101612756565b80548210156123595760005260206000200190600090565b6000818152600360205260409020548015612914577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81018181116123d957600254907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82019182116123d9578082036128a5575b5050506002548015612876577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0161283381600261276d565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82549160031b1b19169055600255600052600360205260006040812055600190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b6128fc6128b66128c793600261276d565b90549060031b1c928392600261276d565b81939154907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9060031b92831b921b19161790565b905560005260036020526040600020553880806127fa565b5050600090565b9060018201918160005282602052604060002054801515600014612a46577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81018181116123d9578254907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82019182116123d957808203612a0f575b50505080548015612876577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01906129d0828261276d565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82549160031b1b191690555560005260205260006040812055600190565b612a2f612a1f6128c7938661276d565b90549060031b1c9283928661276d565b905560005283602052604060002055388080612998565b50505050600090565b80600052600360205260406000205415600014612aa957600254680100000000000000008110156119bd57612a906128c7826001859401600255600261276d565b9055600254906000526003602052604060002055600190565b50600090565b600082815260018201602052604090205461291457805490680100000000000000008210156119bd5782612aed6128c784600180960185558461276d565b90558054926000520160205260406000205560019056fea164736f6c634300081a000a", + Bin: "0x60806040523480156200001157600080fd5b50604051620032f2380380620032f28339810160408190526200003491620004d1565b80336000816200005757604051639b15e16f60e01b815260040160405180910390fd5b600180546001600160a01b0319166001600160a01b03848116919091179091558116156200008a576200008a81620000cc565b5050604080518082018252828152815160008152602080820190935291810191909152620000b89062000146565b50620000c48262000295565b505062000608565b336001600160a01b03821603620000f657604051636d6c4ee560e11b815260040160405180910390fd5b600080546001600160a01b0319166001600160a01b03838116918217835560015460405192939116917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b602081015160005b8151811015620001d65760008282815181106200016f576200016f620005ba565b602090810291909101015190506200018960028262000311565b15620001cc576040516001600160a01b03821681527fc3803387881faad271c47728894e3e36fac830ffc8602ca6fc07733cbda775809060200160405180910390a15b506001016200014e565b50815160005b81518110156200028f576000828281518110620001fd57620001fd620005ba565b6020026020010151905060006001600160a01b0316816001600160a01b0316036200023b576040516342bcdf7f60e11b815260040160405180910390fd5b6200024860028262000331565b506040516001600160a01b03821681527feb1b9b92e50b7f88f9ff25d56765095ac6e91540eee214906f4036a908ffbdef9060200160405180910390a150600101620001dc565b50505050565b6001600160a01b038116620002bd576040516342bcdf7f60e11b815260040160405180910390fd5b600580546001600160a01b0319166001600160a01b0383169081179091556040519081527f7c737a8eddf62436489aa3600ed26e75e0a58b0f8c0d266bbcee64358c39fdac9060200160405180910390a150565b600062000328836001600160a01b03841662000348565b90505b92915050565b600062000328836001600160a01b0384166200044c565b60008181526001830160205260408120548015620004415760006200036f600183620005d0565b85549091506000906200038590600190620005d0565b9050818114620003f1576000866000018281548110620003a957620003a9620005ba565b9060005260206000200154905080876000018481548110620003cf57620003cf620005ba565b6000918252602080832090910192909255918252600188019052604090208390555b8554869080620004055762000405620005f2565b6001900381819060005260206000200160009055905585600101600086815260200190815260200160002060009055600193505050506200032b565b60009150506200032b565b600081815260018301602052604081205462000495575081546001818101845560008481526020808220909301849055845484825282860190935260409020919091556200032b565b5060006200032b565b80516001600160a01b0381168114620004b657600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b60008060408385031215620004e557600080fd5b620004f0836200049e565b602084810151919350906001600160401b03808211156200051057600080fd5b818601915086601f8301126200052557600080fd5b8151818111156200053a576200053a620004bb565b8060051b604051601f19603f83011681018181108582111715620005625762000562620004bb565b6040529182528482019250838101850191898311156200058157600080fd5b938501935b82851015620005aa576200059a856200049e565b8452938501939285019262000586565b8096505050505050509250929050565b634e487b7160e01b600052603260045260246000fd5b818103818111156200032b57634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052603160045260246000fd5b612cda80620006186000396000f3fe608060405234801561001057600080fd5b50600436106100ea5760003560e01c80638da5cb5b1161008c578063e145291611610066578063e145291614610247578063e835232b14610265578063f2fde38b14610278578063fe843cd01461028b57600080fd5b80638da5cb5b146101e257806391a2749a14610221578063e0a0e5061461023457600080fd5b80631af18b7b116100c85780631af18b7b146101915780632451a627146101a4578063537e304e146101b957806379ba5097146101da57600080fd5b806308d450a1146100ef5780630a35bcc414610104578063181f5a771461017c575b600080fd5b6101026100fd3660046120e9565b61029e565b005b6101176101123660046121c9565b6102bd565b604051610173919081516fffffffffffffffffffffffffffffffff908116825260208084015163ffffffff1690830152604080840151151590830152606080840151821690830152608092830151169181019190915260a00190565b60405180910390f35b610184610382565b6040516101739190612260565b61010261019f36600461239a565b61039e565b6101ac6105fc565b60405161017391906124b7565b6101cc6101c73660046124ca565b61060d565b6040516101739291906124e5565b61010261077a565b60015473ffffffffffffffffffffffffffffffffffffffff165b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610173565b61010261022f3660046125db565b610848565b61010261024236600461266c565b610859565b60055473ffffffffffffffffffffffffffffffffffffffff166101fc565b6101026102733660046126c1565b6108ce565b6101026102863660046126c1565b6108df565b6101026102993660046126fc565b6108f0565b6102a6610c3a565b6102ba816020015182608001516000610c84565b50565b6040805160a0810182526000808252602082018190529181018290526060810182905260808101919091526103796102f58484610d5b565b6040805160a08101825282546fffffffffffffffffffffffffffffffff808216835270010000000000000000000000000000000080830463ffffffff1660208501527401000000000000000000000000000000000000000090920460ff16151593830193909352600190930154808316606083015292909204166080820152610d8b565b90505b92915050565b604051806060016040528060238152602001612cab6023913981565b6103a6610e3d565b60005b82518110156104845760008382815181106103c6576103c6612830565b602002602001015160200151905060008483815181106103e8576103e8612830565b6020908102919091018101515167ffffffffffffffff811660009081526004909252604090912090915061041c9083610e8e565b1561047a576040805167ffffffffffffffff8316815273ffffffffffffffffffffffffffffffffffffffff841660208201527f530cabd30786b7235e124a6c0db77e0b685ef22813b1fe87554247f404eb8ed6910160405180910390a15b50506001016103a9565b5060005b81518110156105f75760008282815181106104a5576104a5612830565b602002602001015160000151905060008383815181106104c7576104c7612830565b6020026020010151602001519050600082602001519050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16148061051857508151155b8061054a5750604080516000602082015201604051602081830303815290604052805190602001208280519060200120145b15610581576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b825167ffffffffffffffff811660009081526004602052604090206105a7908385610eb0565b156105e8577fad72a792d2a307f400c278be7deaeec6964276783304580cdc4e905436b8d5c58184846040516105df9392919061285f565b60405180910390a15b50505050806001019050610488565b505050565b60606106086002610edd565b905090565b67ffffffffffffffff81166000908152600460205260408120606091829161063490610eea565b90508067ffffffffffffffff81111561064f5761064f611e5a565b604051908082528060200260200182016040528015610678578160200160208202803683370190505b5092508067ffffffffffffffff81111561069457610694611e5a565b6040519080825280602002602001820160405280156106c757816020015b60608152602001906001900390816106b25790505b50915060005b818110156107735767ffffffffffffffff8516600090815260046020526040812081906106fa9084610ef5565b915091508186848151811061071157610711612830565b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250508085848151811061075e5761075e612830565b602090810291909101015250506001016106cd565b5050915091565b60005473ffffffffffffffffffffffffffffffffffffffff1633146107cb576040517f02b543c600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000008082163390811790935560008054909116815560405173ffffffffffffffffffffffffffffffffffffffff909216929183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b610850610e3d565b6102ba81610f14565b610861610c3a565b6108ca8261087260408401846128a8565b808060200260200160405190810160405280939291908181526020016000905b828210156108be576108af60408302860136819003810190612910565b81526020019060010190610892565b50505050506001610c84565b5050565b6108d6610e3d565b6102ba816110a0565b6108e7610e3d565b6102ba81611166565b6108f8610e3d565b60005b81518110156108ca57600082828151811061091857610918612830565b6020908102919091010151604081015181519192509067ffffffffffffffff8116600003610972576040517fc656089500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b602083015160006109838383610d5b565b8054909150700100000000000000000000000000000000900463ffffffff16600003610bdc576109b484600061122a565b6040805160a081018252602080870180516fffffffffffffffffffffffffffffffff908116845263ffffffff421692840192909252875115158385015251811660608301529186015190911660808201528215610af55767ffffffffffffffff8416600090815260066020908152604091829020835160028201805493860151948601516fffffffffffffffffffffffffffffffff9283167fffffffffffffffffffffffff00000000000000000000000000000000000000009095169490941770010000000000000000000000000000000063ffffffff9096168602177fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1674010000000000000000000000000000000000000000941515949094029390931790925560608401516080850151908316921690920217600390910155610bd6565b67ffffffffffffffff84166000908152600660209081526040918290208351815492850151938501516fffffffffffffffffffffffffffffffff9182167fffffffffffffffffffffffff00000000000000000000000000000000000000009094169390931770010000000000000000000000000000000063ffffffff9095168502177fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167401000000000000000000000000000000000000000093151593909302929092178155606084015160808501519083169216909202176001909101555b50610be6565b610be68185611363565b8267ffffffffffffffff167ff14a5415ce6988a9e870a85fff0b9d7b7dd79bbc228cb63cad610daf6f7b6b978386604051610c2292919061292c565b60405180910390a250505050508060010190506108fb565b610c45600233611512565b610c82576040517fd86ad9cf0000000000000000000000000000000000000000000000000000000081523360048201526024015b60405180910390fd5b565b6000610c908483610d5b565b805490915074010000000000000000000000000000000000000000900460ff1615610d55576000805b8451811015610d4057610d04858281518110610cd757610cd7612830565b6020908102919091018101515167ffffffffffffffff891660009081526004909252604090912090611541565b15610d3857610d2b858281518110610d1e57610d1e612830565b6020026020010151611563565b610d35908361299f565b91505b600101610cb9565b508015610d5357610d538282600061169f565b505b50505050565b67ffffffffffffffff821660009081526006602052604081208215610d8457600201905061037c565b905061037c565b6040805160a081018252600080825260208201819052918101829052606081018290526080810191909152610e1982606001516fffffffffffffffffffffffffffffffff1683600001516fffffffffffffffffffffffffffffffff16846020015163ffffffff1642610dfd91906129b2565b85608001516fffffffffffffffffffffffffffffffff16611a22565b6fffffffffffffffffffffffffffffffff1682525063ffffffff4216602082015290565b60015473ffffffffffffffffffffffffffffffffffffffff163314610c82576040517f2b5c74de00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006103798373ffffffffffffffffffffffffffffffffffffffff8416611a4a565b6000610ed38473ffffffffffffffffffffffffffffffffffffffff851684611a6e565b90505b9392505050565b60606000610ed683611a93565b600061037c82611aef565b600060608180610f058686611afa565b909450925050505b9250929050565b602081015160005b8151811015610faf576000828281518110610f3957610f39612830565b60200260200101519050610f57816002611bb790919063ffffffff16565b15610fa65760405173ffffffffffffffffffffffffffffffffffffffff821681527fc3803387881faad271c47728894e3e36fac830ffc8602ca6fc07733cbda775809060200160405180910390a15b50600101610f1c565b50815160005b8151811015610d55576000828281518110610fd257610fd2612830565b60200260200101519050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603611042576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61104d600282611bd9565b5060405173ffffffffffffffffffffffffffffffffffffffff821681527feb1b9b92e50b7f88f9ff25d56765095ac6e91540eee214906f4036a908ffbdef9060200160405180910390a150600101610fb5565b73ffffffffffffffffffffffffffffffffffffffff81166110ed576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600580547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040519081527f7c737a8eddf62436489aa3600ed26e75e0a58b0f8c0d266bbcee64358c39fdac9060200160405180910390a150565b3373ffffffffffffffffffffffffffffffffffffffff8216036111b5576040517fdad89dca00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff838116918217835560015460405192939116917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b8151156112f15781602001516fffffffffffffffffffffffffffffffff1682604001516fffffffffffffffffffffffffffffffff16101580611280575060408201516fffffffffffffffffffffffffffffffff16155b156112b957816040517f8020d124000000000000000000000000000000000000000000000000000000008152600401610c7991906129c5565b80156108ca576040517f433fc33d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60408201516fffffffffffffffffffffffffffffffff1615158061132a575060208201516fffffffffffffffffffffffffffffffff1615155b156108ca57816040517fd68af9cc000000000000000000000000000000000000000000000000000000008152600401610c7991906129c5565b815460009061138c90700100000000000000000000000000000000900463ffffffff16426129b2565b9050801561142e57600183015483546113d4916fffffffffffffffffffffffffffffffff80821692811691859170010000000000000000000000000000000090910416611a22565b83546fffffffffffffffffffffffffffffffff919091167fffffffffffffffffffffffff0000000000000000000000000000000000000000909116177001000000000000000000000000000000004263ffffffff16021783555b60208201518354611454916fffffffffffffffffffffffffffffffff9081169116611bfb565b83548351151574010000000000000000000000000000000000000000027fffffffffffffffffffffff00ffffffff000000000000000000000000000000009091166fffffffffffffffffffffffffffffffff92831617178455602083015160408085015183167001000000000000000000000000000000000291909216176001850155517f9ea3374b67bf275e6bb9c8ae68f9cae023e1c528b4b27e092f0bb209d3531c19906115059084906129c5565b60405180910390a1505050565b73ffffffffffffffffffffffffffffffffffffffff811660009081526001830160205260408120541515610379565b60006103798373ffffffffffffffffffffffffffffffffffffffff8416611c11565b60055481516040517fd02641a000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff91821660048201526000928392169063d02641a0906024016040805180830381865afa1580156115d7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115fb9190612a01565b5190507bffffffffffffffffffffffffffffffffffffffffffffffffffffffff81166000036116715782516040517f9a655f7b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091166004820152602401610c79565b6020830151610ed6907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff831690611c1d565b825474010000000000000000000000000000000000000000900460ff1615806116c6575081155b156116d057505050565b825460018401546fffffffffffffffffffffffffffffffff8083169291169060009061171690700100000000000000000000000000000000900463ffffffff16426129b2565b905080156117d65781831115611758576040517f9725942a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018601546117929083908590849070010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff16611a22565b86547fffffffffffffffffffffffff00000000ffffffffffffffffffffffffffffffff167001000000000000000000000000000000004263ffffffff160217875592505b8482101561188d5773ffffffffffffffffffffffffffffffffffffffff8416611835576040517ff94ebcd10000000000000000000000000000000000000000000000000000000081526004810183905260248101869052604401610c79565b6040517f1a76572a000000000000000000000000000000000000000000000000000000008152600481018390526024810186905273ffffffffffffffffffffffffffffffffffffffff85166044820152606401610c79565b848310156119a05760018681015470010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff169060009082906118d190826129b2565b6118db878a6129b2565b6118e5919061299f565b6118ef9190612a6c565b905073ffffffffffffffffffffffffffffffffffffffff8616611948576040517f15279c080000000000000000000000000000000000000000000000000000000081526004810182905260248101869052604401610c79565b6040517fd0c8d23a000000000000000000000000000000000000000000000000000000008152600481018290526024810186905273ffffffffffffffffffffffffffffffffffffffff87166044820152606401610c79565b6119aa85846129b2565b86547fffffffffffffffffffffffffffffffff00000000000000000000000000000000166fffffffffffffffffffffffffffffffff82161787556040518681529093507f1871cdf8010e63f2eb8384381a68dfa7416dc571a5517e66e88b2d2d0c0a690a9060200160405180910390a1505050505050565b6000611a4185611a328486612aa7565b611a3c908761299f565b611bfb565b95945050505050565b60008181526002830160205260408120611a649082611e0c565b6103798383611c5a565b60008281526002840160205260408120611a888382612b61565b50610ed38484611c66565b606081600001805480602002602001604051908101604052809291908181526020018280548015611ae357602002820191906000526020600020905b815481526020019060010190808311611acf575b50505050509050919050565b600061037c82611c72565b6000606081611b098585611c7c565b60008181526002870160205260409020805491925082918190611b2b90612abe565b80601f0160208091040260200160405190810160405280929190818152602001828054611b5790612abe565b8015611ba45780601f10611b7957610100808354040283529160200191611ba4565b820191906000526020600020905b815481529060010190602001808311611b8757829003601f168201915b5050505050905092509250509250929050565b60006103798373ffffffffffffffffffffffffffffffffffffffff8416611c88565b60006103798373ffffffffffffffffffffffffffffffffffffffff8416611d7b565b6000818310611c0a5781610379565b5090919050565b60006103798383611dca565b6000670de0b6b3a7640000611c50837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8616612aa7565b6103799190612a6c565b60006103798383611c88565b60006103798383611d7b565b600061037c825490565b60006103798383611de2565b60008181526001830160205260408120548015611d71576000611cac6001836129b2565b8554909150600090611cc0906001906129b2565b9050818114611d25576000866000018281548110611ce057611ce0612830565b9060005260206000200154905080876000018481548110611d0357611d03612830565b6000918252602080832090910192909255918252600188019052604090208390555b8554869080611d3657611d36612c7b565b60019003818190600052602060002001600090559055856001016000868152602001908152602001600020600090556001935050505061037c565b600091505061037c565b6000818152600183016020526040812054611dc25750815460018181018455600084815260208082209093018490558454848252828601909352604090209190915561037c565b50600061037c565b60008181526001830160205260408120541515610379565b6000826000018281548110611df957611df9612830565b9060005260206000200154905092915050565b508054611e1890612abe565b6000825580601f10611e28575050565b601f0160209004906000526020600020908101906102ba91905b80821115611e565760008155600101611e42565b5090565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff81118282101715611eac57611eac611e5a565b60405290565b60405160a0810167ffffffffffffffff81118282101715611eac57611eac611e5a565b6040516060810167ffffffffffffffff81118282101715611eac57611eac611e5a565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715611f3f57611f3f611e5a565b604052919050565b803567ffffffffffffffff81168114611f5f57600080fd5b919050565b600082601f830112611f7557600080fd5b813567ffffffffffffffff811115611f8f57611f8f611e5a565b611fc060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601611ef8565b818152846020838601011115611fd557600080fd5b816020850160208301376000918101602001919091529392505050565b600067ffffffffffffffff82111561200c5761200c611e5a565b5060051b60200190565b803573ffffffffffffffffffffffffffffffffffffffff81168114611f5f57600080fd5b60006040828403121561204c57600080fd5b612054611e89565b905061205f82612016565b81526020820135602082015292915050565b600082601f83011261208257600080fd5b8135602061209761209283611ff2565b611ef8565b8083825260208201915060208460061b8701019350868411156120b957600080fd5b602086015b848110156120de576120d0888261203a565b8352918301916040016120be565b509695505050505050565b6000602082840312156120fb57600080fd5b813567ffffffffffffffff8082111561211357600080fd5b9083019060a0828603121561212757600080fd5b61212f611eb2565b8235815261213f60208401611f47565b602082015260408301358281111561215657600080fd5b61216287828601611f64565b60408301525060608301358281111561217a57600080fd5b61218687828601611f64565b60608301525060808301358281111561219e57600080fd5b6121aa87828601612071565b60808301525095945050505050565b80358015158114611f5f57600080fd5b600080604083850312156121dc57600080fd5b6121e583611f47565b91506121f3602084016121b9565b90509250929050565b6000815180845260005b8181101561222257602081850181015186830182015201612206565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b60208152600061037960208301846121fc565b60006040828403121561228557600080fd5b61228d611e89565b905061229882611f47565b81526122a660208301612016565b602082015292915050565b600082601f8301126122c257600080fd5b813560206122d261209283611ff2565b82815260059290921b840181019181810190868411156122f157600080fd5b8286015b848110156120de57803567ffffffffffffffff808211156123165760008081fd5b81890191506060807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0848d0301121561234f5760008081fd5b612357611e89565b6123638c898601612273565b81529083013590828211156123785760008081fd5b6123868c8984870101611f64565b8189015286525050509183019183016122f5565b60008060408084860312156123ae57600080fd5b833567ffffffffffffffff808211156123c657600080fd5b818601915086601f8301126123da57600080fd5b813560206123ea61209283611ff2565b8083825260208201915060208460061b87010193508a84111561240c57600080fd5b6020860195505b83861015612434576124258b87612273565b82529486019490820190612413565b9750505050602086013592508083111561244d57600080fd5b505061245b858286016122b1565b9150509250929050565b60008151808452602080850194506020840160005b838110156124ac57815173ffffffffffffffffffffffffffffffffffffffff168752958201959082019060010161247a565b509495945050505050565b6020815260006103796020830184612465565b6000602082840312156124dc57600080fd5b61037982611f47565b6040815260006124f86040830185612465565b6020838203818501528185518084528284019150828160051b85010183880160005b83811015612566577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08784030185526125548383516121fc565b9486019492509085019060010161251a565b50909998505050505050505050565b600082601f83011261258657600080fd5b8135602061259661209283611ff2565b8083825260208201915060208460051b8701019350868411156125b857600080fd5b602086015b848110156120de576125ce81612016565b83529183019183016125bd565b6000602082840312156125ed57600080fd5b813567ffffffffffffffff8082111561260557600080fd5b908301906040828603121561261957600080fd5b612621611e89565b82358281111561263057600080fd5b61263c87828601612575565b82525060208301358281111561265157600080fd5b61265d87828601612575565b60208301525095945050505050565b6000806040838503121561267f57600080fd5b61268883611f47565b9150602083013567ffffffffffffffff8111156126a457600080fd5b830160a081860312156126b657600080fd5b809150509250929050565b6000602082840312156126d357600080fd5b61037982612016565b80356fffffffffffffffffffffffffffffffff81168114611f5f57600080fd5b6000602080838503121561270f57600080fd5b823567ffffffffffffffff81111561272657600080fd5b8301601f8101851361273757600080fd5b803561274561209282611ff2565b81815260a0918202830184019184820191908884111561276457600080fd5b938501935b8385101561282457848903818112156127825760008081fd5b61278a611ed5565b61279387611f47565b81526127a08888016121b9565b8882015260406060807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0850112156127d85760008081fd5b6127e0611ed5565b93506127ed828a016121b9565b84526127fa818a016126dc565b8a8501525061280b608089016126dc565b8382015281019190915283529384019391850191612769565b50979650505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b67ffffffffffffffff8416815260606020820152600061288260608301856121fc565b905073ffffffffffffffffffffffffffffffffffffffff83166040830152949350505050565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18436030181126128dd57600080fd5b83018035915067ffffffffffffffff8211156128f857600080fd5b6020019150600681901b3603821315610f0d57600080fd5b60006040828403121561292257600080fd5b610379838361203a565b821515815260808101610ed660208301848051151582526020808201516fffffffffffffffffffffffffffffffff9081169184019190915260409182015116910152565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b8082018082111561037c5761037c612970565b8181038181111561037c5761037c612970565b6060810161037c82848051151582526020808201516fffffffffffffffffffffffffffffffff9081169184019190915260409182015116910152565b600060408284031215612a1357600080fd5b612a1b611e89565b82517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff81168114612a4757600080fd5b8152602083015163ffffffff81168114612a6057600080fd5b60208201529392505050565b600082612aa2577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b808202811582820484141761037c5761037c612970565b600181811c90821680612ad257607f821691505b602082108103612b0b577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b601f8211156105f7576000816000526020600020601f850160051c81016020861015612b3a5750805b601f850160051c820191505b81811015612b5957828155600101612b46565b505050505050565b815167ffffffffffffffff811115612b7b57612b7b611e5a565b612b8f81612b898454612abe565b84612b11565b602080601f831160018114612be25760008415612bac5750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b178555612b59565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b82811015612c2f57888601518255948401946001909101908401612c10565b5085821015612c6b57878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fdfe4d756c7469416767726567617465526174654c696d6974657220312e362e302d646576a164736f6c6343000818000a", } var MultiAggregateRateLimiterABI = MultiAggregateRateLimiterMetaData.ABI diff --git a/core/gethwrappers/ccip/generated/multi_ocr3_helper/multi_ocr3_helper.go b/core/gethwrappers/ccip/generated/multi_ocr3_helper/multi_ocr3_helper.go index d59c7dc5994..0fc23b619f7 100644 --- a/core/gethwrappers/ccip/generated/multi_ocr3_helper/multi_ocr3_helper.go +++ b/core/gethwrappers/ccip/generated/multi_ocr3_helper/multi_ocr3_helper.go @@ -58,8 +58,8 @@ type MultiOCR3BaseOracle struct { } var MultiOCR3HelperMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[],\"name\":\"CannotTransferToSelf\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"expected\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"actual\",\"type\":\"bytes32\"}],\"name\":\"ConfigDigestMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"expected\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"actual\",\"type\":\"uint256\"}],\"name\":\"ForkedChain\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"enumMultiOCR3Base.InvalidConfigErrorType\",\"name\":\"errorType\",\"type\":\"uint8\"}],\"name\":\"InvalidConfig\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MustBeProposedOwner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NonUniqueSignatures\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByOwner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OracleCannotBeZeroAddress\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OwnerCannotBeZero\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"SignaturesOutOfRegistration\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"}],\"name\":\"StaticConfigCannotBeChanged\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnauthorizedSigner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnauthorizedTransmitter\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"expected\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"actual\",\"type\":\"uint256\"}],\"name\":\"WrongMessageLength\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"WrongNumberOfSignatures\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"}],\"name\":\"AfterConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"F\",\"type\":\"uint8\"}],\"name\":\"ConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"Transmitted\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"},{\"internalType\":\"address\",\"name\":\"oracleAddress\",\"type\":\"address\"}],\"name\":\"getOracle\",\"outputs\":[{\"components\":[{\"internalType\":\"uint8\",\"name\":\"index\",\"type\":\"uint8\"},{\"internalType\":\"enumMultiOCR3Base.Role\",\"name\":\"role\",\"type\":\"uint8\"}],\"internalType\":\"structMultiOCR3Base.Oracle\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"}],\"name\":\"latestConfigDetails\",\"outputs\":[{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"internalType\":\"uint8\",\"name\":\"F\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"n\",\"type\":\"uint8\"},{\"internalType\":\"bool\",\"name\":\"isSignatureVerificationEnabled\",\"type\":\"bool\"}],\"internalType\":\"structMultiOCR3Base.ConfigInfo\",\"name\":\"configInfo\",\"type\":\"tuple\"},{\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"}],\"internalType\":\"structMultiOCR3Base.OCRConfig\",\"name\":\"ocrConfig\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"F\",\"type\":\"uint8\"},{\"internalType\":\"bool\",\"name\":\"isSignatureVerificationEnabled\",\"type\":\"bool\"},{\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"}],\"internalType\":\"structMultiOCR3Base.OCRConfigArgs[]\",\"name\":\"ocrConfigArgs\",\"type\":\"tuple[]\"}],\"name\":\"setOCR3Configs\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"}],\"name\":\"setTransmitOcrPluginType\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[2]\",\"name\":\"reportContext\",\"type\":\"bytes32[2]\"},{\"internalType\":\"bytes\",\"name\":\"report\",\"type\":\"bytes\"},{\"internalType\":\"bytes32[]\",\"name\":\"rs\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes32[]\",\"name\":\"ss\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes32\",\"name\":\"rawVs\",\"type\":\"bytes32\"}],\"name\":\"transmitWithSignatures\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[2]\",\"name\":\"reportContext\",\"type\":\"bytes32[2]\"},{\"internalType\":\"bytes\",\"name\":\"report\",\"type\":\"bytes\"}],\"name\":\"transmitWithoutSignatures\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"pure\",\"type\":\"function\"}]", - Bin: "0x60a080604052346051573315604057600180546001600160a01b0319163317905546608052611f2090816100578239608051818181610f2f015261169b0152f35b639b15e16f60e01b60005260046000fd5b600080fdfe6080604052600436101561001257600080fd5b60003560e01c806310061068146115df578063181f5a771461150f57806334a9c92e146114285780633ecdb95b14610e2d57806379ba509714610d445780637ac0aa1a14610cdc5780638da5cb5b14610c8a578063c673e58414610b2e578063f2fde38b14610a3b5763f716f99f1461008a57600080fd5b34610a365760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610a365760043567ffffffffffffffff8111610a365736602382011215610a365780600401356100e481611c1a565b916100f26040519384611bd9565b8183526024602084019260051b82010190368211610a365760248101925b82841061093b5784610120611e58565b6002906000805b82518110156109395761013a8184611dc8565b5190604082019060ff8251161561090a5760ff60208401511692836000528660205260406000206001810190815460ff8116156000146108c6577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffff62ff00006060860151151560101b1691161782555b60a08301928351956101008751116107dc578651156108975760038301996101eb6101de6101e58d60405192838092611d78565b0382611bd9565b8a611ea3565b6060830151610566575b60005b88518110156103b55773ffffffffffffffffffffffffffffffffffffffff610220828b611dc8565b5116908a600052600360205260ff60408060002060009073ffffffffffffffffffffffffffffffffffffffff86168252602052205460081c16600381101561032e5761038757811561035d578b6040519261027a84611b85565b60ff83168452602084019161032e578f604060ff928f8493865260005260036020528160002073ffffffffffffffffffffffffffffffffffffffff60009216825260205220945116167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff008454161783555191600383101561032e576001927fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff61ff0083549260081b169116179055016101f8565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b7fd6c62c9b0000000000000000000000000000000000000000000000000000000060005260046000fd5b7f367f56a2000000000000000000000000000000000000000000000000000000006000526004805260246000fd5b509997969091929394959781519167ffffffffffffffff83116105375768010000000000000000831161053757815483835580841061050e575b509060208d989796959493920190600052602060002060005b8381106104e157505050509360019796936104cb7fab8b1b57514019638d7b5ce9c638fe71366fe8e2be1c40a7a80f1733d0e9f547946104bd7f897ac1b2c12867721b284f3eb147bd4ab046d4eef1cf31c1d8988bfcfb962b53999560ff60209a51169460ff86167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00825416179055519485835551916040519687968a88528b88015260a0604088015260a087019101611d78565b908482036060860152611b3b565b9060808301520390a1604051908152a101610127565b825173ffffffffffffffffffffffffffffffffffffffff16818301558e9950602090920191600101610408565b8260005283602060002091820191015b81811061052b57506103ef565b6000815560010161051e565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b8b840161058360405161057d816101de8186611d78565b8b611ea3565b60808401519061010082511161086957815160ff8551166003029060ff821691820361083a57111561080b5781518a51116107dc5781519087547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff61ff008460081b16911617885567ffffffffffffffff8211610537576801000000000000000082116105375780548282558083106107b3575b506020830190600052602060002060005b8381106107895750600193600093508392509050835b61064c575b505050506101f5565b80518310156107845773ffffffffffffffffffffffffffffffffffffffff6106748483611dc8565b5116928d600052600360205260ff60408060002060009073ffffffffffffffffffffffffffffffffffffffff88168252602052205460081c16600381101561032e5761038757831561035d5782604051946106ce86611b85565b60ff83168652602086019161032e578f604060ff9283928a865260005260036020528160002073ffffffffffffffffffffffffffffffffffffffff60009216825260205220965116167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff008654161785555190600382101561032e57859485927fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff61ff0083549260081b169116179055019261063e565b610643565b600190602073ffffffffffffffffffffffffffffffffffffffff8551169401938184015501610628565b8160005282602060002091820191015b8181106107d05750610617565b600081556001016107c3565b7f367f56a200000000000000000000000000000000000000000000000000000000600052600160045260246000fd5b7f367f56a200000000000000000000000000000000000000000000000000000000600052600360045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b8d7f367f56a20000000000000000000000000000000000000000000000000000000060005260045260246000fd5b7f367f56a200000000000000000000000000000000000000000000000000000000600052600560045260246000fd5b60ff606085015115159160101c16151503156101aa57857f87f6037c0000000000000000000000000000000000000000000000000000000060005260045260246000fd5b7f367f56a200000000000000000000000000000000000000000000000000000000600052600060045260246000fd5b005b833567ffffffffffffffff8111610a3657820160c07fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdc8236030112610a36576040519160c0830183811067ffffffffffffffff82111761053757604052602482013583526109ab60448301611afc565b60208401526109bc60648301611afc565b604084015260848201358015158103610a3657606084015260a482013567ffffffffffffffff8111610a36576109f89060243691850101611c32565b608084015260c48201359267ffffffffffffffff8411610a3657610a26602094936024869536920101611c32565b60a0820152815201930192610110565b600080fd5b34610a365760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610a365760043573ffffffffffffffffffffffffffffffffffffffff8116809103610a3657610a93611e58565b338114610b0457807fffffffffffffffffffffffff0000000000000000000000000000000000000000600054161760005573ffffffffffffffffffffffffffffffffffffffff600154167fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae1278600080a3005b7fdad89dca0000000000000000000000000000000000000000000000000000000060005260046000fd5b34610a365760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610a365760ff610b67611aec565b606060408051610b7681611ba1565b8151610b8181611bbd565b60008152600060208201526000838201526000848201528152826020820152015216600052600260205260606040600020610c866003610c5560405193610bc785611ba1565b610bd081611d3f565b8552610c0860405191610bf183610bea8160028501611d78565b0384611bd9565b60208701928352610bea6040518096819301611d78565b6040850192835260405195869560208752518051602088015260ff602082015116604088015260ff604082015116828801520151151560808601525160c060a086015260e0850190611b3b565b90517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08483030160c0850152611b3b565b0390f35b34610a365760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610a3657602073ffffffffffffffffffffffffffffffffffffffff60015416604051908152f35b34610a365760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610a365760ff610d15611aec565b167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff006004541617600455600080f35b34610a365760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610a365760005473ffffffffffffffffffffffffffffffffffffffff81163303610e03577fffffffffffffffffffffffff00000000000000000000000000000000000000006001549133828416176001551660005573ffffffffffffffffffffffffffffffffffffffff3391167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0600080a3005b7f02b543c60000000000000000000000000000000000000000000000000000000060005260046000fd5b34610a365760c07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610a365736604411610a365760443567ffffffffffffffff8111610a3657610e84903690600401611abe565b9060643567ffffffffffffffff8111610a3657610ea5903690600401611b0a565b919060843567ffffffffffffffff8111610a3657610eca610ee9913690600401611b0a565b9190610ee160a4359460ff60045416973691611cf3565b923691611cf3565b90846000526002602052610f006040600020611d3f565b9560043594610f0e82611e0b565b97606081019889516113db575b8036036113aa5750805187810361137857507f00000000000000000000000000000000000000000000000000000000000000004681036113475750876000526003602052604060002073ffffffffffffffffffffffffffffffffffffffff331660005260205260406000209860405199610f948b611b85565b5460ff81168b52610faf60ff60208d019260081c1682611ce7565b519960038b101561032e57600260009b1490816112d2575b50156112aa5751611014575b88887f198d6990ef96613a9026203077e422916918b03ff47f0be6bee7b02d8e139ef060408a815190815267ffffffffffffffff602435166020820152a280f35b60ff611027816020875194015116611e34565b160361128257825184510361125a578761104083611cad565b9161104e6040519384611bd9565b8383526020830193368183011161125657806020928637830101525190206040516020810191825260406004818301376060815261108d608082611bd9565b51902090869281519488945b8686106110a65750610fd3565b60208610156112295760208a60806110bf858a1a611e46565b6110c98a89611dc8565b516110d48b89611dc8565b519060ff604051938c855216868401526040830152606082015282805260015afa1561121e578951898b52600360205273ffffffffffffffffffffffffffffffffffffffff60408c2091168b5260205260408a206040519061113582611b85565b5460ff8116825261115060ff602084019260081c1682611ce7565b5160038110156111f1577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff016111c957600160ff8251161b82166111a15790600160ff819351161b17950194611099565b60048b7ff67bc7c4000000000000000000000000000000000000000000000000000000008152fd5b60048b7fca31867a000000000000000000000000000000000000000000000000000000008152fd5b60248c7f4e487b710000000000000000000000000000000000000000000000000000000081526021600452fd5b6040513d8b823e3d90fd5b60248a7f4e487b710000000000000000000000000000000000000000000000000000000081526032600452fd5b8280fd5b6004887fa75d88af000000000000000000000000000000000000000000000000000000008152fd5b6004887f71253a25000000000000000000000000000000000000000000000000000000008152fd5b60048a7fda0f08e8000000000000000000000000000000000000000000000000000000008152fd5b9050898b52600260205260ff600360408d200191511690805482101561131a579073ffffffffffffffffffffffffffffffffffffffff918c5260208c2001541633148b610fc7565b60248c7f4e487b710000000000000000000000000000000000000000000000000000000081526032600452fd5b7f0f01ce85000000000000000000000000000000000000000000000000000000006000526004524660245260446000fd5b87907f93df584c0000000000000000000000000000000000000000000000000000000060005260045260245260446000fd5b7f8e1192e1000000000000000000000000000000000000000000000000000000006000526004523660245260446000fd5b84518060051b908082046020149015171561083a576113f990611e19565b908651918260051b928084046020149015171561083a576114239261141d91611e27565b90611e27565b610f1b565b34610a365760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610a365761145f611aec565b6024359073ffffffffffffffffffffffffffffffffffffffff82168203610a365760ff906000602060405161149381611b85565b828152015216600052600360205273ffffffffffffffffffffffffffffffffffffffff604060002091166000526020526040600020604051906114d582611b85565b5460ff811682526114f060ff602084019260081c1682611ce7565b60ff60405192511682525190600382101561032e576040916020820152f35b34610a365760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610a3657604080519061154d8183611bd9565b601982527f4d756c74694f4352334261736548656c70657220312e302e30000000000000006020830152805180926020825280519081602084015260005b8281106115c85750506000828201840152601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168101030190f35b60208282018101518783018701528694500161158b565b34610a365760607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610a365736604411610a365760443567ffffffffffffffff8111610a3657611636903690600401611abe565b604051602092916116478483611bd9565b60008252600036813760ff6004541691826000526002855261166c6040600020611d3f565b936004359261167a81611e0b565b9560608101968751611a79575b8036036113aa57508051858103611a4757507f000000000000000000000000000000000000000000000000000000000000000046810361134757508560005260038852604060002073ffffffffffffffffffffffffffffffffffffffff33166000528852604060002096604051976116fe89611b85565b5460ff8116895261171860ff8b8b019260081c1682611ce7565b5197600389101561032e576002600099149081611a01575b50156119d9575161177d575b86867f198d6990ef96613a9026203077e422916918b03ff47f0be6bee7b02d8e139ef06040888c825191825267ffffffffffffffff6024351690820152a280f35b60ff61178f818a875194015116611e34565b16036119b15761179e81611cad565b906117ac6040519283611bd9565b8082528782019236828201116119ad578188928a928637830101525190206040518681019182526040600481830137606081526117ea608082611bd9565b519020849082519286925b848410611802575061173c565b88841015611980578888608061181982881a611e46565b6118238887611dc8565b5161182e8988611dc8565b519060ff604051938a855216868401526040830152606082015282805260015afa1561197557875187895260038a5273ffffffffffffffffffffffffffffffffffffffff60408a20911689528952604088206040519061188d82611b85565b5460ff811682526118a760ff8c84019260081c1682611ce7565b516003811015611948577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0161192057600160ff8251161b82166118f85790600160ff819351161b179301926117f5565b6004897ff67bc7c4000000000000000000000000000000000000000000000000000000008152fd5b6004897fca31867a000000000000000000000000000000000000000000000000000000008152fd5b60248a7f4e487b710000000000000000000000000000000000000000000000000000000081526021600452fd5b6040513d89823e3d90fd5b6024887f4e487b710000000000000000000000000000000000000000000000000000000081526032600452fd5b8780fd5b6004867f71253a25000000000000000000000000000000000000000000000000000000008152fd5b6004887fda0f08e8000000000000000000000000000000000000000000000000000000008152fd5b905087895260028a5260ff600360408b2001915116908054821015611229579073ffffffffffffffffffffffffffffffffffffffff918a528a8a2001541633148a611730565b85907f93df584c0000000000000000000000000000000000000000000000000000000060005260045260245260446000fd5b84518060051b908082048b149015171561083a57611a9690611e19565b908551918260051b928084048c149015171561083a57611ab99261141d91611e27565b611687565b9181601f84011215610a365782359167ffffffffffffffff8311610a365760208381860195010111610a3657565b6004359060ff82168203610a3657565b359060ff82168203610a3657565b9181601f84011215610a365782359167ffffffffffffffff8311610a36576020808501948460051b010111610a3657565b906020808351928381520192019060005b818110611b595750505090565b825173ffffffffffffffffffffffffffffffffffffffff16845260209384019390920191600101611b4c565b6040810190811067ffffffffffffffff82111761053757604052565b6060810190811067ffffffffffffffff82111761053757604052565b6080810190811067ffffffffffffffff82111761053757604052565b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff82111761053757604052565b67ffffffffffffffff81116105375760051b60200190565b9080601f83011215610a3657813590611c4a82611c1a565b92611c586040519485611bd9565b82845260208085019360051b820101918211610a3657602001915b818310611c805750505090565b823573ffffffffffffffffffffffffffffffffffffffff81168103610a3657815260209283019201611c73565b67ffffffffffffffff811161053757601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b600382101561032e5752565b929190611cff81611c1a565b93611d0d6040519586611bd9565b602085838152019160051b8101928311610a3657905b828210611d2f57505050565b8135815260209182019101611d23565b90604051611d4c81611bbd565b606060ff600183958054855201548181166020850152818160081c16604085015260101c161515910152565b906020825491828152019160005260206000209060005b818110611d9c5750505090565b825473ffffffffffffffffffffffffffffffffffffffff16845260209093019260019283019201611d8f565b8051821015611ddc5760209160051b010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b608401908160841161083a57565b60a001908160a01161083a57565b9190820180921161083a57565b60ff60019116019060ff821161083a57565b60ff601b9116019060ff821161083a57565b73ffffffffffffffffffffffffffffffffffffffff600154163303611e7957565b7f2b5c74de0000000000000000000000000000000000000000000000000000000060005260046000fd5b91909160005b8351811015611f0d5760019060ff831660005260036020526000604080822073ffffffffffffffffffffffffffffffffffffffff611ee7858a611dc8565b511673ffffffffffffffffffffffffffffffffffffffff16835260205281205501611ea9565b5050905056fea164736f6c634300081a000a", + ABI: "[{\"inputs\":[],\"name\":\"CannotTransferToSelf\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"expected\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"actual\",\"type\":\"bytes32\"}],\"name\":\"ConfigDigestMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"expected\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"actual\",\"type\":\"uint256\"}],\"name\":\"ForkedChain\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"enumMultiOCR3Base.InvalidConfigErrorType\",\"name\":\"errorType\",\"type\":\"uint8\"}],\"name\":\"InvalidConfig\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MustBeProposedOwner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NonUniqueSignatures\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByOwner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OracleCannotBeZeroAddress\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OwnerCannotBeZero\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"SignaturesOutOfRegistration\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"}],\"name\":\"StaticConfigCannotBeChanged\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnauthorizedSigner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnauthorizedTransmitter\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"expected\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"actual\",\"type\":\"uint256\"}],\"name\":\"WrongMessageLength\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"WrongNumberOfSignatures\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"}],\"name\":\"AfterConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"F\",\"type\":\"uint8\"}],\"name\":\"ConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"Transmitted\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"},{\"internalType\":\"address\",\"name\":\"oracleAddress\",\"type\":\"address\"}],\"name\":\"getOracle\",\"outputs\":[{\"components\":[{\"internalType\":\"uint8\",\"name\":\"index\",\"type\":\"uint8\"},{\"internalType\":\"enumMultiOCR3Base.Role\",\"name\":\"role\",\"type\":\"uint8\"}],\"internalType\":\"structMultiOCR3Base.Oracle\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"}],\"name\":\"latestConfigDetails\",\"outputs\":[{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"internalType\":\"uint8\",\"name\":\"F\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"n\",\"type\":\"uint8\"},{\"internalType\":\"bool\",\"name\":\"isSignatureVerificationEnabled\",\"type\":\"bool\"}],\"internalType\":\"structMultiOCR3Base.ConfigInfo\",\"name\":\"configInfo\",\"type\":\"tuple\"},{\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"}],\"internalType\":\"structMultiOCR3Base.OCRConfig\",\"name\":\"ocrConfig\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"F\",\"type\":\"uint8\"},{\"internalType\":\"bool\",\"name\":\"isSignatureVerificationEnabled\",\"type\":\"bool\"},{\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"}],\"internalType\":\"structMultiOCR3Base.OCRConfigArgs[]\",\"name\":\"ocrConfigArgs\",\"type\":\"tuple[]\"}],\"name\":\"setOCR3Configs\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"}],\"name\":\"setTransmitOcrPluginType\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[3]\",\"name\":\"reportContext\",\"type\":\"bytes32[3]\"},{\"internalType\":\"bytes\",\"name\":\"report\",\"type\":\"bytes\"},{\"internalType\":\"bytes32[]\",\"name\":\"rs\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes32[]\",\"name\":\"ss\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes32\",\"name\":\"rawVs\",\"type\":\"bytes32\"}],\"name\":\"transmitWithSignatures\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[3]\",\"name\":\"reportContext\",\"type\":\"bytes32[3]\"},{\"internalType\":\"bytes\",\"name\":\"report\",\"type\":\"bytes\"}],\"name\":\"transmitWithoutSignatures\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"pure\",\"type\":\"function\"}]", + Bin: "0x60a060405234801561001057600080fd5b503360008161003257604051639b15e16f60e01b815260040160405180910390fd5b600180546001600160a01b0319166001600160a01b0384811691909117909155811615610062576100628161006d565b5050466080526100e6565b336001600160a01b0382160361009657604051636d6c4ee560e11b815260040160405180910390fd5b600080546001600160a01b0319166001600160a01b03838116918217835560015460405192939116917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b608051611d256200010960003960008181610edd0152610f290152611d256000f3fe608060405234801561001057600080fd5b50600436106100be5760003560e01c80637ac0aa1a11610076578063c673e5841161005b578063c673e584146101c5578063f2fde38b146101e5578063f716f99f146101f857600080fd5b80637ac0aa1a1461015b5780638da5cb5b1461019d57600080fd5b806334a9c92e116100a757806334a9c92e1461012057806344e65e551461014057806379ba50971461015357600080fd5b8063181f5a77146100c357806326bf9d261461010b575b600080fd5b604080518082018252601981527f4d756c74694f4352334261736548656c70657220312e302e30000000000000006020820152905161010291906114ca565b60405180910390f35b61011e610119366004611591565b61020b565b005b61013361012e36600461161f565b61023a565b6040516101029190611681565b61011e61014e3660046116f4565b6102ca565b61011e61034d565b61011e6101693660046117a7565b600480547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660ff92909216919091179055565b60015460405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610102565b6101d86101d33660046117a7565b61041b565b604051610102919061181b565b61011e6101f33660046118ae565b610593565b61011e610206366004611a1a565b6105a7565b604080516000808252602082019092526004549091506102349060ff16858585858060006105e9565b50505050565b6040805180820182526000808252602080830182905260ff86811683526003825284832073ffffffffffffffffffffffffffffffffffffffff871684528252918490208451808601909552805480841686529394939092918401916101009091041660028111156102ad576102ad611652565b60028111156102be576102be611652565b90525090505b92915050565b60045460408051602080880282810182019093528782526103439360ff16928c928c928c928c918c91829185019084908082843760009201919091525050604080516020808d0282810182019093528c82529093508c92508b9182918501908490808284376000920191909152508a92506105e9915050565b5050505050505050565b60005473ffffffffffffffffffffffffffffffffffffffff16331461039e576040517f02b543c600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000008082163390811790935560008054909116815560405173ffffffffffffffffffffffffffffffffffffffff909216929183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b61045e6040805160e081019091526000606082018181526080830182905260a0830182905260c08301919091528190815260200160608152602001606081525090565b60ff808316600090815260026020818152604092839020835160e081018552815460608201908152600183015480881660808401526101008104881660a0840152620100009004909616151560c08201529485529182018054845181840281018401909552808552929385830193909283018282801561051457602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff1681526001909101906020018083116104e9575b505050505081526020016003820180548060200260200160405190810160405280929190818152602001828054801561058357602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff168152600190910190602001808311610558575b5050505050815250509050919050565b61059b610972565b6105a4816109c5565b50565b6105af610972565b60005b81518110156105e5576105dd8282815181106105d0576105d0611b83565b6020026020010151610a89565b6001016105b2565b5050565b60ff878116600090815260026020908152604080832081516080810183528154815260019091015480861693820193909352610100830485169181019190915262010000909104909216151560608301528735906106488760a4611be1565b9050826060015115610690578451610661906020611bf4565b865161066e906020611bf4565b6106799060a0611be1565b6106839190611be1565b61068d9082611be1565b90505b3681146106d7576040517f8e1192e1000000000000000000000000000000000000000000000000000000008152600481018290523660248201526044015b60405180910390fd5b508151811461071f5781516040517f93df584c0000000000000000000000000000000000000000000000000000000081526004810191909152602481018290526044016106ce565b610727610eda565b60ff808a166000908152600360209081526040808320338452825280832081518083019092528054808616835293949193909284019161010090910416600281111561077557610775611652565b600281111561078657610786611652565b90525090506002816020015160028111156107a3576107a3611652565b1480156108045750600260008b60ff1660ff168152602001908152602001600020600301816000015160ff16815481106107df576107df611b83565b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff1633145b61083a576040517fda0f08e800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5081606001511561091c576020820151610855906001611c0b565b60ff16855114610891576040517f71253a2500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b83518551146108cc576040517fa75d88af00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600087876040516108de929190611c24565b6040519081900381206108f5918b90602001611c34565b60405160208183030381529060405280519060200120905061091a8a82888888610f5b565b505b6040805182815260208a81013567ffffffffffffffff169082015260ff8b16917f198d6990ef96613a9026203077e422916918b03ff47f0be6bee7b02d8e139ef0910160405180910390a2505050505050505050565b60015473ffffffffffffffffffffffffffffffffffffffff1633146109c3576040517f2b5c74de00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b565b3373ffffffffffffffffffffffffffffffffffffffff821603610a14576040517fdad89dca00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff838116918217835560015460405192939116917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b806040015160ff16600003610acd5760006040517f367f56a20000000000000000000000000000000000000000000000000000000081526004016106ce9190611c48565b60208082015160ff80821660009081526002909352604083206001810154929390928392169003610b3a57606084015160018201805491151562010000027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffff909216919091179055610b8f565b6060840151600182015460ff6201000090910416151590151514610b8f576040517f87f6037c00000000000000000000000000000000000000000000000000000000815260ff841660048201526024016106ce565b60a084015180516101001015610bd45760016040517f367f56a20000000000000000000000000000000000000000000000000000000081526004016106ce9190611c48565b8051600003610c125760056040517f367f56a20000000000000000000000000000000000000000000000000000000081526004016106ce9190611c48565b610c858484600301805480602002602001604051908101604052809291908181526020018280548015610c7b57602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff168152600190910190602001808311610c50575b505050505061116b565b846060015115610e2a57610d008484600201805480602002602001604051908101604052809291908181526020018280548015610c7b5760200282019190600052602060002090815473ffffffffffffffffffffffffffffffffffffffff168152600190910190602001808311610c5057505050505061116b565b608085015180516101001015610d455760026040517f367f56a20000000000000000000000000000000000000000000000000000000081526004016106ce9190611c48565b6040860151610d55906003611c62565b60ff16815111610d945760036040517f367f56a20000000000000000000000000000000000000000000000000000000081526004016106ce9190611c48565b815181511015610dd35760016040517f367f56a20000000000000000000000000000000000000000000000000000000081526004016106ce9190611c48565b80516001840180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff1661010060ff841602179055610e1b906002860190602084019061142b565b50610e2885826001611203565b505b610e3684826002611203565b8051610e4b906003850190602084019061142b565b506040858101516001840180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660ff8316179055865180855560a088015192517fab8b1b57514019638d7b5ce9c638fe71366fe8e2be1c40a7a80f1733d0e9f54793610ec29389939260028a01929190611c85565b60405180910390a1610ed3846113f2565b5050505050565b467f0000000000000000000000000000000000000000000000000000000000000000146109c3576040517f0f01ce850000000000000000000000000000000000000000000000000000000081527f000000000000000000000000000000000000000000000000000000000000000060048201524660248201526044016106ce565b8251600090815b81811015610343576000600188868460208110610f8157610f81611b83565b610f8e91901a601b611c0b565b898581518110610fa057610fa0611b83565b6020026020010151898681518110610fba57610fba611b83565b602002602001015160405160008152602001604052604051610ff8949392919093845260ff9290921660208401526040830152606082015260800190565b6020604051602081039080840390855afa15801561101a573d6000803e3d6000fd5b5050604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081015160ff808e1660009081526003602090815285822073ffffffffffffffffffffffffffffffffffffffff8516835281528582208587019096528554808416865293975090955092939284019161010090041660028111156110a6576110a6611652565b60028111156110b7576110b7611652565b90525090506001816020015160028111156110d4576110d4611652565b1461110b576040517fca31867a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8051600160ff9091161b85161561114e576040517ff67bc7c400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b806000015160ff166001901b851794505050806001019050610f62565b60005b81518110156111fe5760ff8316600090815260036020526040812083519091908490849081106111a0576111a0611b83565b60209081029190910181015173ffffffffffffffffffffffffffffffffffffffff16825281019190915260400160002080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000016905560010161116e565b505050565b60005b825181101561023457600083828151811061122357611223611b83565b602002602001015190506000600281111561124057611240611652565b60ff808716600090815260036020908152604080832073ffffffffffffffffffffffffffffffffffffffff87168452909152902054610100900416600281111561128c5761128c611652565b146112c65760046040517f367f56a20000000000000000000000000000000000000000000000000000000081526004016106ce9190611c48565b73ffffffffffffffffffffffffffffffffffffffff8116611313576040517fd6c62c9b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60405180604001604052808360ff16815260200184600281111561133957611339611652565b905260ff808716600090815260036020908152604080832073ffffffffffffffffffffffffffffffffffffffff8716845282529091208351815493167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00841681178255918401519092909183917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000016176101008360028111156113de576113de611652565b021790555090505050806001019050611206565b60405160ff821681527f897ac1b2c12867721b284f3eb147bd4ab046d4eef1cf31c1d8988bfcfb962b539060200160405180910390a150565b8280548282559060005260206000209081019282156114a5579160200282015b828111156114a557825182547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff90911617825560209092019160019091019061144b565b506114b19291506114b5565b5090565b5b808211156114b157600081556001016114b6565b60006020808352835180602085015260005b818110156114f8578581018301518582016040015282016114dc565b5060006040828601015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8301168501019250505092915050565b80606081018310156102c457600080fd5b60008083601f84011261155a57600080fd5b50813567ffffffffffffffff81111561157257600080fd5b60208301915083602082850101111561158a57600080fd5b9250929050565b6000806000608084860312156115a657600080fd5b6115b08585611537565b9250606084013567ffffffffffffffff8111156115cc57600080fd5b6115d886828701611548565b9497909650939450505050565b803560ff811681146115f657600080fd5b919050565b803573ffffffffffffffffffffffffffffffffffffffff811681146115f657600080fd5b6000806040838503121561163257600080fd5b61163b836115e5565b9150611649602084016115fb565b90509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b815160ff16815260208201516040820190600381106116a2576116a2611652565b8060208401525092915050565b60008083601f8401126116c157600080fd5b50813567ffffffffffffffff8111156116d957600080fd5b6020830191508360208260051b850101111561158a57600080fd5b60008060008060008060008060e0898b03121561171057600080fd5b61171a8a8a611537565b9750606089013567ffffffffffffffff8082111561173757600080fd5b6117438c838d01611548565b909950975060808b013591508082111561175c57600080fd5b6117688c838d016116af565b909750955060a08b013591508082111561178157600080fd5b5061178e8b828c016116af565b999c989b50969995989497949560c00135949350505050565b6000602082840312156117b957600080fd5b6117c2826115e5565b9392505050565b60008151808452602080850194506020840160005b8381101561181057815173ffffffffffffffffffffffffffffffffffffffff16875295820195908201906001016117de565b509495945050505050565b60208152600082518051602084015260ff602082015116604084015260ff604082015116606084015260608101511515608084015250602083015160c060a084015261186a60e08401826117c9565b905060408401517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08483030160c08501526118a582826117c9565b95945050505050565b6000602082840312156118c057600080fd5b6117c2826115fb565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60405160c0810167ffffffffffffffff8111828210171561191b5761191b6118c9565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715611968576119686118c9565b604052919050565b600067ffffffffffffffff82111561198a5761198a6118c9565b5060051b60200190565b803580151581146115f657600080fd5b600082601f8301126119b557600080fd5b813560206119ca6119c583611970565b611921565b8083825260208201915060208460051b8701019350868411156119ec57600080fd5b602086015b84811015611a0f57611a02816115fb565b83529183019183016119f1565b509695505050505050565b60006020808385031215611a2d57600080fd5b823567ffffffffffffffff80821115611a4557600080fd5b818501915085601f830112611a5957600080fd5b8135611a676119c582611970565b81815260059190911b83018401908481019088831115611a8657600080fd5b8585015b83811015611b7657803585811115611aa157600080fd5b860160c0818c037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0011215611ad65760008081fd5b611ade6118f8565b8882013581526040611af18184016115e5565b8a8301526060611b028185016115e5565b8284015260809150611b15828501611994565b9083015260a08381013589811115611b2d5760008081fd5b611b3b8f8d838801016119a4565b838501525060c0840135915088821115611b555760008081fd5b611b638e8c848701016119a4565b9083015250845250918601918601611a8a565b5098975050505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b808201808211156102c4576102c4611bb2565b80820281158282048414176102c4576102c4611bb2565b60ff81811683821601908111156102c4576102c4611bb2565b8183823760009101908152919050565b828152606082602083013760800192915050565b6020810160068310611c5c57611c5c611652565b91905290565b60ff8181168382160290811690818114611c7e57611c7e611bb2565b5092915050565b600060a0820160ff88168352602087602085015260a0604085015281875480845260c086019150886000526020600020935060005b81811015611cec57845473ffffffffffffffffffffffffffffffffffffffff1683526001948501949284019201611cba565b50508481036060860152611d0081886117c9565b935050505060ff83166080830152969550505050505056fea164736f6c6343000818000a", } var MultiOCR3HelperABI = MultiOCR3HelperMetaData.ABI @@ -334,27 +334,27 @@ func (_MultiOCR3Helper *MultiOCR3HelperTransactorSession) TransferOwnership(to c return _MultiOCR3Helper.Contract.TransferOwnership(&_MultiOCR3Helper.TransactOpts, to) } -func (_MultiOCR3Helper *MultiOCR3HelperTransactor) TransmitWithSignatures(opts *bind.TransactOpts, reportContext [2][32]byte, report []byte, rs [][32]byte, ss [][32]byte, rawVs [32]byte) (*types.Transaction, error) { +func (_MultiOCR3Helper *MultiOCR3HelperTransactor) TransmitWithSignatures(opts *bind.TransactOpts, reportContext [3][32]byte, report []byte, rs [][32]byte, ss [][32]byte, rawVs [32]byte) (*types.Transaction, error) { return _MultiOCR3Helper.contract.Transact(opts, "transmitWithSignatures", reportContext, report, rs, ss, rawVs) } -func (_MultiOCR3Helper *MultiOCR3HelperSession) TransmitWithSignatures(reportContext [2][32]byte, report []byte, rs [][32]byte, ss [][32]byte, rawVs [32]byte) (*types.Transaction, error) { +func (_MultiOCR3Helper *MultiOCR3HelperSession) TransmitWithSignatures(reportContext [3][32]byte, report []byte, rs [][32]byte, ss [][32]byte, rawVs [32]byte) (*types.Transaction, error) { return _MultiOCR3Helper.Contract.TransmitWithSignatures(&_MultiOCR3Helper.TransactOpts, reportContext, report, rs, ss, rawVs) } -func (_MultiOCR3Helper *MultiOCR3HelperTransactorSession) TransmitWithSignatures(reportContext [2][32]byte, report []byte, rs [][32]byte, ss [][32]byte, rawVs [32]byte) (*types.Transaction, error) { +func (_MultiOCR3Helper *MultiOCR3HelperTransactorSession) TransmitWithSignatures(reportContext [3][32]byte, report []byte, rs [][32]byte, ss [][32]byte, rawVs [32]byte) (*types.Transaction, error) { return _MultiOCR3Helper.Contract.TransmitWithSignatures(&_MultiOCR3Helper.TransactOpts, reportContext, report, rs, ss, rawVs) } -func (_MultiOCR3Helper *MultiOCR3HelperTransactor) TransmitWithoutSignatures(opts *bind.TransactOpts, reportContext [2][32]byte, report []byte) (*types.Transaction, error) { +func (_MultiOCR3Helper *MultiOCR3HelperTransactor) TransmitWithoutSignatures(opts *bind.TransactOpts, reportContext [3][32]byte, report []byte) (*types.Transaction, error) { return _MultiOCR3Helper.contract.Transact(opts, "transmitWithoutSignatures", reportContext, report) } -func (_MultiOCR3Helper *MultiOCR3HelperSession) TransmitWithoutSignatures(reportContext [2][32]byte, report []byte) (*types.Transaction, error) { +func (_MultiOCR3Helper *MultiOCR3HelperSession) TransmitWithoutSignatures(reportContext [3][32]byte, report []byte) (*types.Transaction, error) { return _MultiOCR3Helper.Contract.TransmitWithoutSignatures(&_MultiOCR3Helper.TransactOpts, reportContext, report) } -func (_MultiOCR3Helper *MultiOCR3HelperTransactorSession) TransmitWithoutSignatures(reportContext [2][32]byte, report []byte) (*types.Transaction, error) { +func (_MultiOCR3Helper *MultiOCR3HelperTransactorSession) TransmitWithoutSignatures(reportContext [3][32]byte, report []byte) (*types.Transaction, error) { return _MultiOCR3Helper.Contract.TransmitWithoutSignatures(&_MultiOCR3Helper.TransactOpts, reportContext, report) } @@ -1056,9 +1056,9 @@ type MultiOCR3HelperInterface interface { TransferOwnership(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) - TransmitWithSignatures(opts *bind.TransactOpts, reportContext [2][32]byte, report []byte, rs [][32]byte, ss [][32]byte, rawVs [32]byte) (*types.Transaction, error) + TransmitWithSignatures(opts *bind.TransactOpts, reportContext [3][32]byte, report []byte, rs [][32]byte, ss [][32]byte, rawVs [32]byte) (*types.Transaction, error) - TransmitWithoutSignatures(opts *bind.TransactOpts, reportContext [2][32]byte, report []byte) (*types.Transaction, error) + TransmitWithoutSignatures(opts *bind.TransactOpts, reportContext [3][32]byte, report []byte) (*types.Transaction, error) FilterAfterConfigSet(opts *bind.FilterOpts) (*MultiOCR3HelperAfterConfigSetIterator, error) diff --git a/core/gethwrappers/ccip/generated/nonce_manager/nonce_manager.go b/core/gethwrappers/ccip/generated/nonce_manager/nonce_manager.go index 6c2bfd6a673..ccd28cdd6ce 100644 --- a/core/gethwrappers/ccip/generated/nonce_manager/nonce_manager.go +++ b/core/gethwrappers/ccip/generated/nonce_manager/nonce_manager.go @@ -48,7 +48,7 @@ type NonceManagerPreviousRampsArgs struct { var NonceManagerMetaData = &bind.MetaData{ ABI: "[{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"authorizedCallers\",\"type\":\"address[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"CannotTransferToSelf\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MustBeProposedOwner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByOwner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OwnerCannotBeZero\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"PreviousRampAlreadySet\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"UnauthorizedCaller\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"AuthorizedCallerAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"AuthorizedCallerRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"prevOnRamp\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"prevOffRamp\",\"type\":\"address\"}],\"indexed\":false,\"internalType\":\"structNonceManager.PreviousRamps\",\"name\":\"prevRamp\",\"type\":\"tuple\"}],\"name\":\"PreviousRampsUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"sender\",\"type\":\"bytes\"}],\"name\":\"SkippedIncorrectNonce\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address[]\",\"name\":\"addedCallers\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"removedCallers\",\"type\":\"address[]\"}],\"internalType\":\"structAuthorizedCallers.AuthorizedCallerArgs\",\"name\":\"authorizedCallerArgs\",\"type\":\"tuple\"}],\"name\":\"applyAuthorizedCallerUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"overrideExistingRamps\",\"type\":\"bool\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"prevOnRamp\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"prevOffRamp\",\"type\":\"address\"}],\"internalType\":\"structNonceManager.PreviousRamps\",\"name\":\"prevRamps\",\"type\":\"tuple\"}],\"internalType\":\"structNonceManager.PreviousRampsArgs[]\",\"name\":\"previousRampsArgs\",\"type\":\"tuple[]\"}],\"name\":\"applyPreviousRampsUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAllAuthorizedCallers\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"sender\",\"type\":\"bytes\"}],\"name\":\"getInboundNonce\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"getIncrementedOutboundNonce\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"getOutboundNonce\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"}],\"name\":\"getPreviousRamps\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"prevOnRamp\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"prevOffRamp\",\"type\":\"address\"}],\"internalType\":\"structNonceManager.PreviousRamps\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"expectedNonce\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"sender\",\"type\":\"bytes\"}],\"name\":\"incrementInboundNonce\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", - Bin: "0x60806040523461020f576117738038038061001981610214565b92833981019060208183031261020f578051906001600160401b03821161020f570181601f8201121561020f578051916001600160401b0383116101c8578260051b9160208061006a818601610214565b80968152019382010191821161020f57602001915b8183106101ef578333156101de57600180546001600160a01b031916331790556020906100ab82610214565b60008152600036813760408051929083016001600160401b038111848210176101c8576040528252808383015260005b8151811015610142576001906001600160a01b036100f98285610239565b5116856101058261027b565b610112575b5050016100db565b7fc3803387881faad271c47728894e3e36fac830ffc8602ca6fc07733cbda7758091604051908152a1858561010a565b50505160005b81518110156101b9576001600160a01b036101638284610239565b51169081156101a8577feb1b9b92e50b7f88f9ff25d56765095ac6e91540eee214906f4036a908ffbdef848361019a600195610379565b50604051908152a101610148565b6342bcdf7f60e11b60005260046000fd5b60405161139990816103da8239f35b634e487b7160e01b600052604160045260246000fd5b639b15e16f60e01b60005260046000fd5b82516001600160a01b038116810361020f5781526020928301920161007f565b600080fd5b6040519190601f01601f191682016001600160401b038111838210176101c857604052565b805182101561024d5760209160051b010190565b634e487b7160e01b600052603260045260246000fd5b805482101561024d5760005260206000200190600090565b600081815260036020526040902054801561037257600019810181811161035c5760025460001981019190821161035c5780820361030b575b50505060025480156102f557600019016102cf816002610263565b8154906000199060031b1b19169055600255600052600360205260006040812055600190565b634e487b7160e01b600052603160045260246000fd5b61034461031c61032d936002610263565b90549060031b1c9283926002610263565b819391549060031b91821b91600019901b19161790565b905560005260036020526040600020553880806102b4565b634e487b7160e01b600052601160045260246000fd5b5050600090565b806000526003602052604060002054156000146103d357600254680100000000000000008110156101c8576103ba61032d8260018594016002556002610263565b9055600254906000526003602052604060002055600190565b5060009056fe608080604052600436101561001357600080fd5b60003560e01c908163181f5a7714610a94575080632451a627146109a6578063294b5630146108ff57806379ba5097146108165780637a75a094146105f95780638da5cb5b146105a757806391a2749a146103bd578063bf18402a14610373578063c9223625146102fe578063e0e03cae14610272578063ea458c0c1461019b5763f2fde38b146100a357600080fd5b346101965760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101965760043573ffffffffffffffffffffffffffffffffffffffff8116809103610196576100fb610e81565b33811461016c57807fffffffffffffffffffffffff0000000000000000000000000000000000000000600054161760005573ffffffffffffffffffffffffffffffffffffffff600154167fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae1278600080a3005b7fdad89dca0000000000000000000000000000000000000000000000000000000060005260046000fd5b600080fd5b346101965760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101965760206101d4610bef565b6101dc610c06565b6101e461113a565b67ffffffffffffffff6101ff6101fa8385610f2f565b610d1e565b92166000526005835273ffffffffffffffffffffffffffffffffffffffff604060002091166000528252604060002067ffffffffffffffff82167fffffffffffffffffffffffffffffffffffffffffffffffff000000000000000082541617905567ffffffffffffffff60405191168152f35b346101965760607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610196576102a9610bef565b60243567ffffffffffffffff81168103610196576044359067ffffffffffffffff8211610196576020926102e46102f4933690600401610cba565b9290916102ef61113a565b610d6d565b6040519015158152f35b346101965760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261019657610335610bef565b60243567ffffffffffffffff81116101965760209161035b610361923690600401610cba565b9161104a565b67ffffffffffffffff60405191168152f35b346101965760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101965760206103616103af610bef565b6103b7610c06565b90610f2f565b346101965760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101965760043567ffffffffffffffff81116101965760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc8236030112610196576040519061043782610b63565b806004013567ffffffffffffffff81116101965761045b9060043691840101610c4a565b825260248101359067ffffffffffffffff82116101965760046104819236920101610c4a565b60208201908152610490610e81565b519060005b8251811015610508578073ffffffffffffffffffffffffffffffffffffffff6104c060019386610ecc565b51166104cb81611196565b6104d7575b5001610495565b60207fc3803387881faad271c47728894e3e36fac830ffc8602ca6fc07733cbda7758091604051908152a1846104d0565b505160005b81518110156105a55773ffffffffffffffffffffffffffffffffffffffff6105358284610ecc565b511690811561057b577feb1b9b92e50b7f88f9ff25d56765095ac6e91540eee214906f4036a908ffbdef60208361056d60019561132c565b50604051908152a10161050d565b7f8579befe0000000000000000000000000000000000000000000000000000000060005260046000fd5b005b346101965760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261019657602073ffffffffffffffffffffffffffffffffffffffff60015416604051908152f35b346101965760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101965760043567ffffffffffffffff8111610196573660238201121561019657806004013567ffffffffffffffff8111610196573660248260071b8401011161019657610670610e81565b60005b818110156105a55760008160071b84016024810167ffffffffffffffff61069982610ce8565b1683526004602052604083209273ffffffffffffffffffffffffffffffffffffffff845416158015906107f3575b6107b3575b5060408273ffffffffffffffffffffffffffffffffffffffff6107a667ffffffffffffffff6107907fa2e43edcbc4fd175ae4bebbe3fd6139871ed1f1783cd4a1ace59b90d302c3319966084606460019c9b9a01968661072b89610cfd565b167fffffffffffffffffffffffff00000000000000000000000000000000000000008c5416178b550198858c6107608c610cfd565b920191167fffffffffffffffffffffffff0000000000000000000000000000000000000000825416179055610ce8565b16958261079e865195610c29565b168452610c29565b166020820152a201610673565b60448301358015908115036107ef57156106cc57807fc6117ae20000000000000000000000000000000000000000000000000000000060049252fd5b5080fd5b5073ffffffffffffffffffffffffffffffffffffffff60018501541615156106c7565b346101965760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101965760005473ffffffffffffffffffffffffffffffffffffffff811633036108d5577fffffffffffffffffffffffff00000000000000000000000000000000000000006001549133828416176001551660005573ffffffffffffffffffffffffffffffffffffffff3391167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0600080a3005b7f02b543c60000000000000000000000000000000000000000000000000000000060005260046000fd5b346101965760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101965767ffffffffffffffff61093f610bef565b6000602060405161094f81610b63565b828152015216600052600460205260408060002073ffffffffffffffffffffffffffffffffffffffff825161098381610b63565b602082600181865416958685520154169101908152835192835251166020820152f35b346101965760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610196576040518060206002549283815201809260026000527f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ace9060005b818110610a7e5750505081610a25910382610bae565b6040519182916020830190602084525180915260408301919060005b818110610a4f575050500390f35b825173ffffffffffffffffffffffffffffffffffffffff16845285945060209384019390920191600101610a41565b8254845260209093019260019283019201610a0f565b346101965760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261019657610acc81610b63565b601681527f4e6f6e63654d616e6167657220312e362e302d64657600000000000000000000602082015260405190602082528181519182602083015260005b838110610b4b5750507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f836000604080968601015201168101030190f35b60208282018101516040878401015285935001610b0b565b6040810190811067ffffffffffffffff821117610b7f57604052565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff821117610b7f57604052565b6004359067ffffffffffffffff8216820361019657565b6024359073ffffffffffffffffffffffffffffffffffffffff8216820361019657565b359073ffffffffffffffffffffffffffffffffffffffff8216820361019657565b9080601f830112156101965781359167ffffffffffffffff8311610b7f578260051b9060405193610c7e6020840186610bae565b845260208085019282010192831161019657602001905b828210610ca25750505090565b60208091610caf84610c29565b815201910190610c95565b9181601f840112156101965782359167ffffffffffffffff8311610196576020838186019501011161019657565b3567ffffffffffffffff811681036101965790565b3573ffffffffffffffffffffffffffffffffffffffff811681036101965790565b67ffffffffffffffff60019116019067ffffffffffffffff8211610d3e57565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b9291909267ffffffffffffffff610d886101fa85858561104a565b94168067ffffffffffffffff861603610df8575067ffffffffffffffff9291836020921660005260068252604060002083604051948593843782019081520301902091167fffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000825416179055600190565b7f606ff8179e5e3c059b82df931acc496b7b6053e8879042f8267f930e0595f69f9450601f8467ffffffffffffffff956080957fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09460405198899716875260208701526060604087015281606087015286860137600085828601015201168101030190a1600090565b73ffffffffffffffffffffffffffffffffffffffff600154163303610ea257565b7f2b5c74de0000000000000000000000000000000000000000000000000000000060005260046000fd5b8051821015610ee05760209160051b010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b90816020910312610196575167ffffffffffffffff811681036101965790565b67ffffffffffffffff1690816000526005602052604060002073ffffffffffffffffffffffffffffffffffffffff821660005260205267ffffffffffffffff60406000205416918215610f8157505090565b600052600460205273ffffffffffffffffffffffffffffffffffffffff604060002054169081610fb057505090565b6020919250602473ffffffffffffffffffffffffffffffffffffffff9160405194859384927f856c82470000000000000000000000000000000000000000000000000000000084521660048301525afa90811561103e57600091611012575090565b611034915060203d602011611037575b61102c8183610bae565b810190610f0f565b90565b503d611022565b6040513d6000823e3d90fd5b67ffffffffffffffff90929192169182600052600660205267ffffffffffffffff60406000206020604051809286868337868201908152030190205416928315611095575b50505090565b600052600460205273ffffffffffffffffffffffffffffffffffffffff6001604060002001541691821561108f57819293509060209181010312610196573573ffffffffffffffffffffffffffffffffffffffff8116809103610196576020906024604051809481937f856c824700000000000000000000000000000000000000000000000000000000835260048301525afa90811561103e57600091611012575090565b3360005260036020526040600020541561115057565b7fd86ad9cf000000000000000000000000000000000000000000000000000000006000523360045260246000fd5b8054821015610ee05760005260206000200190600090565b6000818152600360205260409020548015611325577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8101818111610d3e57600254907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8201918211610d3e578082036112b6575b5050506002548015611287577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0161124481600261117e565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82549160031b1b19169055600255600052600360205260006040812055600190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b61130d6112c76112d893600261117e565b90549060031b1c928392600261117e565b81939154907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9060031b92831b921b19161790565b9055600052600360205260406000205538808061120b565b5050600090565b806000526003602052604060002054156000146113865760025468010000000000000000811015610b7f5761136d6112d8826001859401600255600261117e565b9055600254906000526003602052604060002055600190565b5060009056fea164736f6c634300081a000a", + Bin: "0x60806040523480156200001157600080fd5b5060405162001ad438038062001ad4833981016040819052620000349162000449565b80336000816200005757604051639b15e16f60e01b815260040160405180910390fd5b600180546001600160a01b0319166001600160a01b03848116919091179091558116156200008a576200008a81620000c0565b5050604080518082018252828152815160008152602080820190935291810191909152620000b8906200013a565b505062000569565b336001600160a01b03821603620000ea57604051636d6c4ee560e11b815260040160405180910390fd5b600080546001600160a01b0319166001600160a01b03838116918217835560015460405192939116917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b602081015160005b8151811015620001ca5760008282815181106200016357620001636200051b565b602090810291909101015190506200017d60028262000289565b15620001c0576040516001600160a01b03821681527fc3803387881faad271c47728894e3e36fac830ffc8602ca6fc07733cbda775809060200160405180910390a15b5060010162000142565b50815160005b815181101562000283576000828281518110620001f157620001f16200051b565b6020026020010151905060006001600160a01b0316816001600160a01b0316036200022f576040516342bcdf7f60e11b815260040160405180910390fd5b6200023c600282620002a9565b506040516001600160a01b03821681527feb1b9b92e50b7f88f9ff25d56765095ac6e91540eee214906f4036a908ffbdef9060200160405180910390a150600101620001d0565b50505050565b6000620002a0836001600160a01b038416620002c0565b90505b92915050565b6000620002a0836001600160a01b038416620003c4565b60008181526001830160205260408120548015620003b9576000620002e760018362000531565b8554909150600090620002fd9060019062000531565b9050818114620003695760008660000182815481106200032157620003216200051b565b90600052602060002001549050808760000184815481106200034757620003476200051b565b6000918252602080832090910192909255918252600188019052604090208390555b85548690806200037d576200037d62000553565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050620002a3565b6000915050620002a3565b60008181526001830160205260408120546200040d57508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155620002a3565b506000620002a3565b634e487b7160e01b600052604160045260246000fd5b80516001600160a01b03811681146200044457600080fd5b919050565b600060208083850312156200045d57600080fd5b82516001600160401b03808211156200047557600080fd5b818501915085601f8301126200048a57600080fd5b8151818111156200049f576200049f62000416565b8060051b604051601f19603f83011681018181108582111715620004c757620004c762000416565b604052918252848201925083810185019188831115620004e657600080fd5b938501935b828510156200050f57620004ff856200042c565b84529385019392850192620004eb565b98975050505050505050565b634e487b7160e01b600052603260045260246000fd5b81810381811115620002a357634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052603160045260246000fd5b61155b80620005796000396000f3fe608060405234801561001057600080fd5b50600436106100d45760003560e01c806391a2749a11610081578063e0e03cae1161005b578063e0e03cae1461027c578063ea458c0c1461029f578063f2fde38b146102b257600080fd5b806391a2749a1461022a578063bf18402a1461023d578063c92236251461026957600080fd5b806379ba5097116100b257806379ba5097146101e55780637a75a094146101ef5780638da5cb5b1461020257600080fd5b8063181f5a77146100d95780632451a6271461012b578063294b563014610140575b600080fd5b6101156040518060400160405280601681526020017f4e6f6e63654d616e6167657220312e362e302d6465760000000000000000000081525081565b6040516101229190610f05565b60405180910390f35b6101336102c5565b6040516101229190610f72565b6101b161014e366004610fe2565b60408051808201909152600080825260208201525067ffffffffffffffff166000908152600460209081526040918290208251808401909352805473ffffffffffffffffffffffffffffffffffffffff9081168452600190910154169082015290565b60408051825173ffffffffffffffffffffffffffffffffffffffff9081168252602093840151169281019290925201610122565b6101ed6102d6565b005b6101ed6101fd366004610fff565b6103a4565b60015460405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610122565b6101ed61023836600461118a565b610594565b61025061024b366004611231565b6105a8565b60405167ffffffffffffffff9091168152602001610122565b6102506102773660046112b3565b6105bd565b61028f61028a366004611308565b6105d4565b6040519015158152602001610122565b6102506102ad366004611231565b6106dd565b6101ed6102c036600461136d565b610771565b60606102d16002610782565b905090565b60005473ffffffffffffffffffffffffffffffffffffffff163314610327576040517f02b543c600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000008082163390811790935560008054909116815560405173ffffffffffffffffffffffffffffffffffffffff909216929183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b6103ac61078f565b60005b8181101561058f57368383838181106103ca576103ca61138a565b608002919091019150600090506004816103e76020850185610fe2565b67ffffffffffffffff1681526020810191909152604001600020805490915073ffffffffffffffffffffffffffffffffffffffff161515806104425750600181015473ffffffffffffffffffffffffffffffffffffffff1615155b1561048d5761045760408301602084016113b9565b61048d576040517fc6117ae200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61049d606083016040840161136d565b81547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff919091161781556104ed608083016060840161136d565b6001820180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff929092169190911790556105416020830183610fe2565b67ffffffffffffffff167fa2e43edcbc4fd175ae4bebbe3fd6139871ed1f1783cd4a1ace59b90d302c33198360400160405161057d91906113db565b60405180910390a250506001016103af565b505050565b61059c61078f565b6105a5816107e2565b50565b60006105b48383610974565b90505b92915050565b60006105ca848484610a91565b90505b9392505050565b60006105de610be2565b60006105eb868585610a91565b6105f6906001611452565b90508467ffffffffffffffff168167ffffffffffffffff161461065a577f606ff8179e5e3c059b82df931acc496b7b6053e8879042f8267f930e0595f69f868686866040516106489493929190611473565b60405180910390a160009150506106d5565b67ffffffffffffffff861660009081526006602052604090819020905182919061068790879087906114df565b908152604051908190036020019020805467ffffffffffffffff929092167fffffffffffffffffffffffffffffffffffffffffffffffff000000000000000090921691909117905550600190505b949350505050565b60006106e7610be2565b60006106f38484610974565b6106fe906001611452565b67ffffffffffffffff808616600090815260056020908152604080832073ffffffffffffffffffffffffffffffffffffffff89168452909152902080549183167fffffffffffffffffffffffffffffffffffffffffffffffff000000000000000090921691909117905591505092915050565b61077961078f565b6105a581610c29565b606060006105cd83610ced565b60015473ffffffffffffffffffffffffffffffffffffffff1633146107e0576040517f2b5c74de00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b565b602081015160005b815181101561087d5760008282815181106108075761080761138a565b60200260200101519050610825816002610d4990919063ffffffff16565b156108745760405173ffffffffffffffffffffffffffffffffffffffff821681527fc3803387881faad271c47728894e3e36fac830ffc8602ca6fc07733cbda775809060200160405180910390a15b506001016107ea565b50815160005b815181101561096e5760008282815181106108a0576108a061138a565b60200260200101519050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603610910576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61091b600282610d6b565b5060405173ffffffffffffffffffffffffffffffffffffffff821681527feb1b9b92e50b7f88f9ff25d56765095ac6e91540eee214906f4036a908ffbdef9060200160405180910390a150600101610883565b50505050565b67ffffffffffffffff808316600090815260056020908152604080832073ffffffffffffffffffffffffffffffffffffffff861684529091528120549091168082036105b45767ffffffffffffffff841660009081526004602052604090205473ffffffffffffffffffffffffffffffffffffffff168015610a89576040517f856c824700000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff858116600483015282169063856c824790602401602060405180830381865afa158015610a5c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a8091906114ef565b925050506105b7565b509392505050565b67ffffffffffffffff83166000908152600660205260408082209051829190610abd90869086906114df565b9081526040519081900360200190205467ffffffffffffffff16905060008190036105ca5767ffffffffffffffff851660009081526004602052604090206001015473ffffffffffffffffffffffffffffffffffffffff168015610bd95773ffffffffffffffffffffffffffffffffffffffff811663856c8247610b438688018861136d565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b16815273ffffffffffffffffffffffffffffffffffffffff9091166004820152602401602060405180830381865afa158015610bac573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bd091906114ef565b925050506105cd565b50949350505050565b610bed600233610d8d565b6107e0576040517fd86ad9cf00000000000000000000000000000000000000000000000000000000815233600482015260240160405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff821603610c78576040517fdad89dca00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff838116918217835560015460405192939116917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b606081600001805480602002602001604051908101604052809291908181526020018280548015610d3d57602002820191906000526020600020905b815481526020019060010190808311610d29575b50505050509050919050565b60006105b48373ffffffffffffffffffffffffffffffffffffffff8416610dbc565b60006105b48373ffffffffffffffffffffffffffffffffffffffff8416610eb6565b73ffffffffffffffffffffffffffffffffffffffff8116600090815260018301602052604081205415156105b4565b60008181526001830160205260408120548015610ea5576000610de060018361150c565b8554909150600090610df49060019061150c565b9050818114610e59576000866000018281548110610e1457610e1461138a565b9060005260206000200154905080876000018481548110610e3757610e3761138a565b6000918252602080832090910192909255918252600188019052604090208390555b8554869080610e6a57610e6a61151f565b6001900381819060005260206000200160009055905585600101600086815260200190815260200160002060009055600193505050506105b7565b60009150506105b7565b5092915050565b6000818152600183016020526040812054610efd575081546001818101845560008481526020808220909301849055845484825282860190935260409020919091556105b7565b5060006105b7565b60006020808352835180602085015260005b81811015610f3357858101830151858201604001528201610f17565b5060006040828601015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8301168501019250505092915050565b6020808252825182820181905260009190848201906040850190845b81811015610fc057835173ffffffffffffffffffffffffffffffffffffffff1683529284019291840191600101610f8e565b50909695505050505050565b67ffffffffffffffff811681146105a557600080fd5b600060208284031215610ff457600080fd5b81356105b481610fcc565b6000806020838503121561101257600080fd5b823567ffffffffffffffff8082111561102a57600080fd5b818501915085601f83011261103e57600080fd5b81358181111561104d57600080fd5b8660208260071b850101111561106257600080fd5b60209290920196919550909350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b73ffffffffffffffffffffffffffffffffffffffff811681146105a557600080fd5b600082601f8301126110d657600080fd5b8135602067ffffffffffffffff808311156110f3576110f3611074565b8260051b6040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0603f8301168101818110848211171561113657611136611074565b604052938452602081870181019490810192508785111561115657600080fd5b6020870191505b8482101561117f578135611170816110a3565b8352918301919083019061115d565b979650505050505050565b60006020828403121561119c57600080fd5b813567ffffffffffffffff808211156111b457600080fd5b90830190604082860312156111c857600080fd5b6040516040810181811083821117156111e3576111e3611074565b6040528235828111156111f557600080fd5b611201878286016110c5565b82525060208301358281111561121657600080fd5b611222878286016110c5565b60208301525095945050505050565b6000806040838503121561124457600080fd5b823561124f81610fcc565b9150602083013561125f816110a3565b809150509250929050565b60008083601f84011261127c57600080fd5b50813567ffffffffffffffff81111561129457600080fd5b6020830191508360208285010111156112ac57600080fd5b9250929050565b6000806000604084860312156112c857600080fd5b83356112d381610fcc565b9250602084013567ffffffffffffffff8111156112ef57600080fd5b6112fb8682870161126a565b9497909650939450505050565b6000806000806060858703121561131e57600080fd5b843561132981610fcc565b9350602085013561133981610fcc565b9250604085013567ffffffffffffffff81111561135557600080fd5b6113618782880161126a565b95989497509550505050565b60006020828403121561137f57600080fd5b81356105b4816110a3565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6000602082840312156113cb57600080fd5b813580151581146105b457600080fd5b6040810182356113ea816110a3565b73ffffffffffffffffffffffffffffffffffffffff9081168352602084013590611413826110a3565b8082166020850152505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b67ffffffffffffffff818116838216019080821115610eaf57610eaf611423565b600067ffffffffffffffff8087168352808616602084015250606060408301528260608301528284608084013760006080848401015260807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f850116830101905095945050505050565b8183823760009101908152919050565b60006020828403121561150157600080fd5b81516105b481610fcc565b818103818111156105b7576105b7611423565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fdfea164736f6c6343000818000a", } var NonceManagerABI = NonceManagerMetaData.ABI diff --git a/core/gethwrappers/ccip/generated/offramp/offramp.go b/core/gethwrappers/ccip/generated/offramp/offramp.go index 7de7683089b..6bc1b8d2d4f 100644 --- a/core/gethwrappers/ccip/generated/offramp/offramp.go +++ b/core/gethwrappers/ccip/generated/offramp/offramp.go @@ -148,16 +148,15 @@ type OffRampSourceChainConfigArgs struct { } type OffRampStaticConfig struct { - ChainSelector uint64 - GasForCallExactCheck uint16 - RmnRemote common.Address - TokenAdminRegistry common.Address - NonceManager common.Address + ChainSelector uint64 + RmnRemote common.Address + TokenAdminRegistry common.Address + NonceManager common.Address } var OffRampMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint16\",\"name\":\"gasForCallExactCheck\",\"type\":\"uint16\"},{\"internalType\":\"contractIRMNRemote\",\"name\":\"rmnRemote\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"}],\"internalType\":\"structOffRamp.StaticConfig\",\"name\":\"staticConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"permissionLessExecutionThresholdSeconds\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isRMNVerificationDisabled\",\"type\":\"bool\"},{\"internalType\":\"address\",\"name\":\"messageInterceptor\",\"type\":\"address\"}],\"internalType\":\"structOffRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"internalType\":\"structOffRamp.SourceChainConfigArgs[]\",\"name\":\"sourceChainConfigs\",\"type\":\"tuple[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"CanOnlySelfCall\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CannotTransferToSelf\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"reportOnRamp\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"configOnRamp\",\"type\":\"bytes\"}],\"name\":\"CommitOnRampMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"expected\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"actual\",\"type\":\"bytes32\"}],\"name\":\"ConfigDigestMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"CursedByRMN\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"EmptyBatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"EmptyReport\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"err\",\"type\":\"bytes\"}],\"name\":\"ExecutionError\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"expected\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"actual\",\"type\":\"uint256\"}],\"name\":\"ForkedChain\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"enumMultiOCR3Base.InvalidConfigErrorType\",\"name\":\"errorType\",\"type\":\"uint8\"}],\"name\":\"InvalidConfig\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"expected\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"got\",\"type\":\"uint256\"}],\"name\":\"InvalidDataLength\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"min\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"max\",\"type\":\"uint64\"}],\"name\":\"InvalidInterval\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"newLimit\",\"type\":\"uint256\"}],\"name\":\"InvalidManualExecutionGasLimit\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"tokenIndex\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"oldLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"tokenGasOverride\",\"type\":\"uint256\"}],\"name\":\"InvalidManualExecutionTokenGasOverride\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"messageDestChainSelector\",\"type\":\"uint64\"}],\"name\":\"InvalidMessageDestChainSelector\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"enumInternal.MessageExecutionState\",\"name\":\"newState\",\"type\":\"uint8\"}],\"name\":\"InvalidNewState\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"InvalidOnRampUpdate\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidProof\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidRoot\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"LeavesCannotBeEmpty\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"ManualExecutionGasAmountCountMismatch\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ManualExecutionGasLimitMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"ManualExecutionNotYetEnabled\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"errorReason\",\"type\":\"bytes\"}],\"name\":\"MessageValidationError\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MustBeProposedOwner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NonUniqueSignatures\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"notPool\",\"type\":\"address\"}],\"name\":\"NotACompatiblePool\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByOwner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OracleCannotBeZeroAddress\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OwnerCannotBeZero\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"err\",\"type\":\"bytes\"}],\"name\":\"ReceiverError\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountReleased\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"balancePre\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"balancePost\",\"type\":\"uint256\"}],\"name\":\"ReleaseOrMintBalanceMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"merkleRoot\",\"type\":\"bytes32\"}],\"name\":\"RootAlreadyCommitted\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"RootNotCommitted\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"SignatureVerificationNotAllowedInExecutionPlugin\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"SignatureVerificationRequiredInCommitPlugin\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"SignaturesOutOfRegistration\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"SourceChainNotEnabled\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"reportSourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"messageSourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"SourceChainSelectorMismatch\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"StaleCommitReport\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"}],\"name\":\"StaticConfigCannotBeChanged\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"TokenDataMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"err\",\"type\":\"bytes\"}],\"name\":\"TokenHandlingError\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnauthorizedSigner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnauthorizedTransmitter\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnexpectedTokenData\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"expected\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"actual\",\"type\":\"uint256\"}],\"name\":\"WrongMessageLength\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"WrongNumberOfSignatures\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroChainSelectorNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"AlreadyAttempted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRampAddress\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"maxSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"merkleRoot\",\"type\":\"bytes32\"}],\"indexed\":false,\"internalType\":\"structInternal.MerkleRoot[]\",\"name\":\"merkleRoots\",\"type\":\"tuple[]\"},{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sourceToken\",\"type\":\"address\"},{\"internalType\":\"uint224\",\"name\":\"usdPerToken\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.TokenPriceUpdate[]\",\"name\":\"tokenPriceUpdates\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint224\",\"name\":\"usdPerUnitGas\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.GasPriceUpdate[]\",\"name\":\"gasPriceUpdates\",\"type\":\"tuple[]\"}],\"indexed\":false,\"internalType\":\"structInternal.PriceUpdates\",\"name\":\"priceUpdates\",\"type\":\"tuple\"}],\"name\":\"CommitReportAccepted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"F\",\"type\":\"uint8\"}],\"name\":\"ConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"permissionLessExecutionThresholdSeconds\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isRMNVerificationDisabled\",\"type\":\"bool\"},{\"internalType\":\"address\",\"name\":\"messageInterceptor\",\"type\":\"address\"}],\"indexed\":false,\"internalType\":\"structOffRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"}],\"name\":\"DynamicConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"messageHash\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"enumInternal.MessageExecutionState\",\"name\":\"state\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"returnData\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"gasUsed\",\"type\":\"uint256\"}],\"name\":\"ExecutionStateChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"root\",\"type\":\"bytes32\"}],\"name\":\"RootRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"SkippedAlreadyExecutedMessage\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"SkippedReportExecution\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"indexed\":false,\"internalType\":\"structOffRamp.SourceChainConfig\",\"name\":\"sourceConfig\",\"type\":\"tuple\"}],\"name\":\"SourceChainConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"SourceChainSelectorAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint16\",\"name\":\"gasForCallExactCheck\",\"type\":\"uint16\"},{\"internalType\":\"contractIRMNRemote\",\"name\":\"rmnRemote\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"}],\"indexed\":false,\"internalType\":\"structOffRamp.StaticConfig\",\"name\":\"staticConfig\",\"type\":\"tuple\"}],\"name\":\"StaticConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"Transmitted\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"internalType\":\"structOffRamp.SourceChainConfigArgs[]\",\"name\":\"sourceChainConfigUpdates\",\"type\":\"tuple[]\"}],\"name\":\"applySourceChainConfigUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"sender\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structClient.EVMTokenAmount[]\",\"name\":\"destTokenAmounts\",\"type\":\"tuple[]\"}],\"internalType\":\"structClient.Any2EVMMessage\",\"name\":\"\",\"type\":\"tuple\"}],\"name\":\"ccipReceive\",\"outputs\":[],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[2]\",\"name\":\"reportContext\",\"type\":\"bytes32[2]\"},{\"internalType\":\"bytes\",\"name\":\"report\",\"type\":\"bytes\"},{\"internalType\":\"bytes32[]\",\"name\":\"rs\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes32[]\",\"name\":\"ss\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes32\",\"name\":\"rawVs\",\"type\":\"bytes32\"}],\"name\":\"commit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[2]\",\"name\":\"reportContext\",\"type\":\"bytes32[2]\"},{\"internalType\":\"bytes\",\"name\":\"report\",\"type\":\"bytes\"}],\"name\":\"execute\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"}],\"internalType\":\"structInternal.RampMessageHeader\",\"name\":\"header\",\"type\":\"tuple\"},{\"internalType\":\"bytes\",\"name\":\"sender\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"destTokenAddress\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"destGasAmount\",\"type\":\"uint32\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structInternal.Any2EVMTokenTransfer[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.Any2EVMRampMessage\",\"name\":\"message\",\"type\":\"tuple\"},{\"internalType\":\"bytes[]\",\"name\":\"offchainTokenData\",\"type\":\"bytes[]\"},{\"internalType\":\"uint32[]\",\"name\":\"tokenGasOverrides\",\"type\":\"uint32[]\"}],\"name\":\"executeSingleMessage\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAllSourceChainConfigs\",\"outputs\":[{\"internalType\":\"uint64[]\",\"name\":\"\",\"type\":\"uint64[]\"},{\"components\":[{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"internalType\":\"structOffRamp.SourceChainConfig[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getDynamicConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"permissionLessExecutionThresholdSeconds\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isRMNVerificationDisabled\",\"type\":\"bool\"},{\"internalType\":\"address\",\"name\":\"messageInterceptor\",\"type\":\"address\"}],\"internalType\":\"structOffRamp.DynamicConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"getExecutionState\",\"outputs\":[{\"internalType\":\"enumInternal.MessageExecutionState\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getLatestPriceSequenceNumber\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"root\",\"type\":\"bytes32\"}],\"name\":\"getMerkleRoot\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"getSourceChainConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"internalType\":\"structOffRamp.SourceChainConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getStaticConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint16\",\"name\":\"gasForCallExactCheck\",\"type\":\"uint16\"},{\"internalType\":\"contractIRMNRemote\",\"name\":\"rmnRemote\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"}],\"internalType\":\"structOffRamp.StaticConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"}],\"name\":\"latestConfigDetails\",\"outputs\":[{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"internalType\":\"uint8\",\"name\":\"F\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"n\",\"type\":\"uint8\"},{\"internalType\":\"bool\",\"name\":\"isSignatureVerificationEnabled\",\"type\":\"bool\"}],\"internalType\":\"structMultiOCR3Base.ConfigInfo\",\"name\":\"configInfo\",\"type\":\"tuple\"},{\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"}],\"internalType\":\"structMultiOCR3Base.OCRConfig\",\"name\":\"ocrConfig\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"}],\"internalType\":\"structInternal.RampMessageHeader\",\"name\":\"header\",\"type\":\"tuple\"},{\"internalType\":\"bytes\",\"name\":\"sender\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"destTokenAddress\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"destGasAmount\",\"type\":\"uint32\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structInternal.Any2EVMTokenTransfer[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.Any2EVMRampMessage[]\",\"name\":\"messages\",\"type\":\"tuple[]\"},{\"internalType\":\"bytes[][]\",\"name\":\"offchainTokenData\",\"type\":\"bytes[][]\"},{\"internalType\":\"bytes32[]\",\"name\":\"proofs\",\"type\":\"bytes32[]\"},{\"internalType\":\"uint256\",\"name\":\"proofFlagBits\",\"type\":\"uint256\"}],\"internalType\":\"structInternal.ExecutionReport[]\",\"name\":\"reports\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"receiverExecutionGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint32[]\",\"name\":\"tokenGasOverrides\",\"type\":\"uint32[]\"}],\"internalType\":\"structOffRamp.GasLimitOverride[][]\",\"name\":\"gasLimitOverrides\",\"type\":\"tuple[][]\"}],\"name\":\"manuallyExecute\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"permissionLessExecutionThresholdSeconds\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isRMNVerificationDisabled\",\"type\":\"bool\"},{\"internalType\":\"address\",\"name\":\"messageInterceptor\",\"type\":\"address\"}],\"internalType\":\"structOffRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"}],\"name\":\"setDynamicConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"F\",\"type\":\"uint8\"},{\"internalType\":\"bool\",\"name\":\"isSignatureVerificationEnabled\",\"type\":\"bool\"},{\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"}],\"internalType\":\"structMultiOCR3Base.OCRConfigArgs[]\",\"name\":\"ocrConfigArgs\",\"type\":\"tuple[]\"}],\"name\":\"setOCR3Configs\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", - Bin: "0x6101408060405234610848576162ef803803809161001d828561087e565b833981019080820361014081126108485760a08112610848576040519060a082016001600160401b0381118382101761084d5760405261005c836108a1565b825260208301519261ffff84168403610848576020830193845260408101516001600160a01b0381168103610848576040840190815261009e606083016108b5565b946060850195865260806100b38185016108b5565b86820190815294609f19011261084857604051946100d086610863565b6100dc60a085016108b5565b865260c08401519463ffffffff86168603610848576020870195865261010460e086016108c9565b976040880198895261011961010087016108b5565b6060890190815261012087015190966001600160401b03821161084857018a601f820112156108485780519a6001600160401b038c1161084d578b60051b916020806040519e8f9061016d8388018361087e565b81520193820101908282116108485760208101935b828510610748575050505050331561073757600180546001600160a01b031916331790554660805284516001600160a01b0316158015610725575b8015610713575b6106f15782516001600160401b0316156107025782516001600160401b0390811660a090815286516001600160a01b0390811660c0528351811660e0528451811661010052865161ffff90811661012052604080519751909416875296519096166020860152955185169084015251831660608301525190911660808201527fb0fa1fb01508c5097c502ad056fd77018870c9be9a86d9e56b6b471862d7c5b79190a182516001600160a01b0316156106f1579151600480548351865160ff60c01b90151560c01b1663ffffffff60a01b60a09290921b919091166001600160a01b039485166001600160c81b0319909316831717179091558351600580549184166001600160a01b031990921691909117905560408051918252925163ffffffff166020820152935115159184019190915290511660608201527fcbb53bda7106a610de67df506ac86b65c44d5afac0fd2b11070dc2d61a6f2dee90608090a160005b815181101561066b576020600582901b8301810151908101516001600160401b031690600090821561065c5780516001600160a01b03161561064d57828252600860205260408220906060810151600183019361038585546108d6565b6105ee578354600160a81b600160e81b031916600160a81b1784556040518681527ff4c1390c70e5c0f491ae1ccbc06f9117cbbadf2767b247b3bc203280f24c0fb990602090a15b815180159081156105c3575b506105b4578151916001600160401b0383116105a0576103f986546108d6565b601f811161055b575b50602091601f84116001146104e257926001989796949281926000805160206162cf8339815191529795926104d7575b5050600019600383901b1c191690881b1783555b60408101518254915160a089811b8a9003801960ff60a01b1990951693151590911b60ff60a01b169290921792909216911617815561048484610993565b506104ce6040519283926020845254888060a01b038116602085015260ff8160a01c1615156040850152888060401b039060a81c16606084015260808084015260a0830190610910565b0390a201610328565b015190503880610432565b9190601f198416878452828420935b818110610543575092600199989795939285926000805160206162cf83398151915298968c951061052a575b505050811b018355610446565b015160001960f88460031b161c1916905538808061051d565b929360206001819287860151815501950193016104f1565b86835260208320601f850160051c81019160208610610596575b601f0160051c01905b81811061058b5750610402565b83815560010161057e565b9091508190610575565b634e487b7160e01b82526041600452602482fd5b6342bcdf7f60e11b8152600490fd5b905060208301206040516020810190838252602081526105e460408261087e565b51902014386103d9565b835460a81c6001600160401b0316600114158061061f575b156103cd57632105803760e11b81526004869052602490fd5b50604051610638816106318189610910565b038261087e565b60208151910120825160208401201415610606565b6342bcdf7f60e11b8252600482fd5b63c656089560e01b8252600482fd5b6040516158a89081610a2782396080518161368c015260a05181818161048e01526141a1015260c0518181816104e401528181612cba0152818161310e015261413b015260e051818181610513015261497e01526101005181818161054201526145640152610120518181816104b50152818161243401528181614a7101526155dd0152f35b6342bcdf7f60e11b60005260046000fd5b63c656089560e01b60005260046000fd5b5081516001600160a01b0316156101c4565b5080516001600160a01b0316156101bd565b639b15e16f60e01b60005260046000fd5b84516001600160401b0381116108485782016080818603601f190112610848576040519061077582610863565b60208101516001600160a01b0381168103610848578252610798604082016108a1565b60208301526107a9606082016108c9565b604083015260808101516001600160401b03811161084857602091010185601f820112156108485780516001600160401b03811161084d57604051916107f9601f8301601f19166020018461087e565b81835287602083830101116108485760005b8281106108335750509181600060208096949581960101526060820152815201940193610182565b8060208092840101518282870101520161080b565b600080fd5b634e487b7160e01b600052604160045260246000fd5b608081019081106001600160401b0382111761084d57604052565b601f909101601f19168101906001600160401b0382119082101761084d57604052565b51906001600160401b038216820361084857565b51906001600160a01b038216820361084857565b5190811515820361084857565b90600182811c92168015610906575b60208310146108f057565b634e487b7160e01b600052602260045260246000fd5b91607f16916108e5565b60009291815491610920836108d6565b8083529260018116908115610976575060011461093c57505050565b60009081526020812093945091925b83831061095c575060209250010190565b60018160209294939454838587010152019101919061094b565b915050602093945060ff929192191683830152151560051b010190565b80600052600760205260406000205415600014610a20576006546801000000000000000081101561084d576001810180600655811015610a0a577ff652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d3f0181905560065460009182526007602052604090912055600190565b634e487b7160e01b600052603260045260246000fd5b5060009056fe6080604052600436101561001257600080fd5b60003560e01c806304666f9c1461015757806306285c6914610152578063181f5a771461014d5780633f4b04aa146101485780635215505b146101435780635e36480c1461013e5780635e7bb0081461013957806360987c20146101345780637437ff9f1461012f57806379ba50971461012a5780637edf52f41461012557806385572ffb146101205780638da5cb5b1461011b578063c673e58414610116578063ccd37ba314610111578063de5e0b9a1461010c578063e9d68a8e14610107578063f2fde38b14610102578063f58e03fc146100fd5763f716f99f146100f857600080fd5b6118d4565b6117b7565b61172c565b611691565b6115f5565b611571565b6114c6565b6113de565b6113a8565b6111e2565b611162565b6110b9565b61103e565b610e39565b6108ce565b610789565b61067c565b61061d565b61043d565b61031f565b634e487b7160e01b600052604160045260246000fd5b608081019081106001600160401b0382111761018d57604052565b61015c565b60a081019081106001600160401b0382111761018d57604052565b604081019081106001600160401b0382111761018d57604052565b606081019081106001600160401b0382111761018d57604052565b90601f801991011681019081106001600160401b0382111761018d57604052565b6040519061021360c0836101e3565b565b6040519061021360a0836101e3565b60405190610213610100836101e3565b604051906102136040836101e3565b6001600160401b03811161018d5760051b60200190565b6001600160a01b0381160361026b57565b600080fd5b600435906001600160401b038216820361026b57565b35906001600160401b038216820361026b57565b8015150361026b57565b35906102138261029a565b6001600160401b03811161018d57601f01601f191660200190565b9291926102d6826102af565b916102e460405193846101e3565b82948184528183011161026b578281602093846000960137010152565b9080601f8301121561026b5781602061031c933591016102ca565b90565b3461026b57602036600319011261026b576004356001600160401b03811161026b573660238201121561026b5780600401359061035b82610243565b9061036960405192836101e3565b8282526024602083019360051b8201019036821161026b5760248101935b8285106103995761039784611a0f565b005b84356001600160401b03811161026b5782016080602319823603011261026b57604051916103c683610172565b60248201356103d48161025a565b83526103e260448301610286565b602084015260648201356103f58161029a565b60408401526084820135926001600160401b03841161026b57610422602094936024869536920101610301565b6060820152815201940193610387565b600091031261026b57565b3461026b57600036600319011261026b576000608060405161045e81610192565b82815282602082015282604082015282606082015201526105bc60405161048481610192565b6001600160401b037f000000000000000000000000000000000000000000000000000000000000000016815261ffff7f00000000000000000000000000000000000000000000000000000000000000001660208201526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001660408201526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001660608201526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001660808201526040519182918291909160806001600160a01b038160a08401956001600160401b03815116855261ffff6020820151166020860152826040820151166040860152826060820151166060860152015116910152565b0390f35b604051906105cf6020836101e3565b60008252565b60005b8381106105e85750506000910152565b81810151838201526020016105d8565b90602091610611815180928185528580860191016105d5565b601f01601f1916010190565b3461026b57600036600319011261026b576105bc604080519061064081836101e3565b601182527f4f666652616d7020312e362e302d6465760000000000000000000000000000006020830152519182916020835260208301906105f8565b3461026b57600036600319011261026b5760206001600160401b03600b5416604051908152f35b906080606061031c936001600160a01b0381511684526020810151151560208501526001600160401b03604082015116604085015201519181606082015201906105f8565b6040810160408252825180915260206060830193019060005b81811061076a575050506020818303910152815180825260208201916020808360051b8301019401926000915b83831061073d57505050505090565b909192939460208061075b600193601f1986820301875289516106a3565b9701930193019193929061072e565b82516001600160401b0316855260209485019490920191600101610701565b3461026b57600036600319011261026b576006546107a681610243565b906107b460405192836101e3565b808252601f196107c382610243565b0160005b8181106108855750506107d981611ce2565b9060005b8181106107f55750506105bc604051928392836106e8565b8061082b610813610807600194614022565b6001600160401b031690565b61081d8387611d3c565b906001600160401b03169052565b61086961086461084b61083e8488611d3c565b516001600160401b031690565b6001600160401b03166000526008602052604060002090565b611e28565b6108738287611d3c565b5261087e8186611d3c565b50016107dd565b602090610890611cbb565b828287010152016107c7565b634e487b7160e01b600052602160045260246000fd5b600411156108bc57565b61089c565b9060048210156108bc5752565b3461026b57604036600319011261026b576108e7610270565b602435906001600160401b038216820361026b5760209161090791611ec4565b61091460405180926108c1565bf35b91908260a091031261026b5760405161092e81610192565b60806109738183958035855261094660208201610286565b602086015261095760408201610286565b604086015261096860608201610286565b606086015201610286565b910152565b35906102138261025a565b63ffffffff81160361026b57565b359061021382610983565b81601f8201121561026b578035906109b382610243565b926109c160405194856101e3565b82845260208085019360051b8301019181831161026b5760208101935b8385106109ed57505050505090565b84356001600160401b03811161026b57820160a0818503601f19011261026b5760405191610a1a83610192565b60208201356001600160401b03811161026b57856020610a3c92850101610301565b83526040820135610a4c8161025a565b6020840152610a5d60608301610991565b60408401526080820135926001600160401b03841161026b5760a083610a8a886020809881980101610301565b6060840152013560808201528152019401936109de565b9190916101408184031261026b57610ab7610204565b92610ac28183610916565b845260a08201356001600160401b03811161026b5781610ae3918401610301565b602085015260c08201356001600160401b03811161026b5781610b07918401610301565b6040850152610b1860e08301610978565b606085015261010082013560808501526101208201356001600160401b03811161026b57610b46920161099c565b60a0830152565b9080601f8301121561026b578135610b6481610243565b92610b7260405194856101e3565b81845260208085019260051b8201019183831161026b5760208201905b838210610b9e57505050505090565b81356001600160401b03811161026b57602091610bc087848094880101610aa1565b815201910190610b8f565b81601f8201121561026b57803590610be282610243565b92610bf060405194856101e3565b82845260208085019360051b8301019181831161026b5760208101935b838510610c1c57505050505090565b84356001600160401b03811161026b57820183603f8201121561026b576020810135610c4781610243565b91610c5560405193846101e3565b8183526020808085019360051b830101019186831161026b5760408201905b838210610c8e575050509082525060209485019401610c0d565b81356001600160401b03811161026b57602091610cb28a8480809589010101610301565b815201910190610c74565b929190610cc981610243565b93610cd760405195866101e3565b602085838152019160051b810192831161026b57905b828210610cf957505050565b8135815260209182019101610ced565b9080601f8301121561026b5781602061031c93359101610cbd565b81601f8201121561026b57803590610d3b82610243565b92610d4960405194856101e3565b82845260208085019360051b8301019181831161026b5760208101935b838510610d7557505050505090565b84356001600160401b03811161026b57820160a0818503601f19011261026b57610d9d610215565b91610daa60208301610286565b835260408201356001600160401b03811161026b57856020610dce92850101610b4d565b602084015260608201356001600160401b03811161026b57856020610df592850101610bcb565b60408401526080820135926001600160401b03841161026b5760a083610e22886020809881980101610d09565b606084015201356080820152815201940193610d66565b3461026b57604036600319011261026b576004356001600160401b03811161026b57610e69903690600401610d24565b6024356001600160401b03811161026b573660238201121561026b57806004013591610e9483610243565b91610ea260405193846101e3565b8383526024602084019460051b8201019036821161026b5760248101945b828610610ed1576103978585611f0c565b85356001600160401b03811161026b5782013660438201121561026b576024810135610efc81610243565b91610f0a60405193846101e3565b818352602060248185019360051b830101019036821161026b5760448101925b828410610f44575050509082525060209586019501610ec0565b83356001600160401b03811161026b576024908301016040601f19823603011261026b5760405190610f75826101ad565b6020810135825260408101356001600160401b03811161026b57602091010136601f8201121561026b57803590610fab82610243565b91610fb960405193846101e3565b80835260208084019160051b8301019136831161026b57602001905b828210610ff45750505091816020938480940152815201930192610f2a565b60208091833561100381610983565b815201910190610fd5565b9181601f8401121561026b578235916001600160401b03831161026b576020808501948460051b01011161026b57565b3461026b57606036600319011261026b576004356001600160401b03811161026b5761106e903690600401610aa1565b6024356001600160401b03811161026b5761108d90369060040161100e565b91604435926001600160401b03841161026b576110b161039794369060040161100e565b939092612318565b3461026b57600036600319011261026b576110d26125e5565b506105bc6040516110e281610172565b60ff6004546001600160a01b038116835263ffffffff8160a01c16602084015260c01c16151560408201526001600160a01b036005541660608201526040519182918291909160606001600160a01b0381608084019582815116855263ffffffff6020820151166020860152604081015115156040860152015116910152565b3461026b57600036600319011261026b576000546001600160a01b03811633036111d1576001600160a01b0319600154913382841617600155166000556001600160a01b033391167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0600080a3005b63015aa1e360e11b60005260046000fd5b3461026b57608036600319011261026b57600060405161120181610172565b60043561120d8161025a565b815260243561121b81610983565b602082015260443561122c8161029a565b604082015260643561123d8161025a565b606082015261124a613489565b6001600160a01b038151161561139957611393816112a96001600160a01b037fcbb53bda7106a610de67df506ac86b65c44d5afac0fd2b11070dc2d61a6f2dee9451166001600160a01b03166001600160a01b03196004541617600455565b60208101516004547fffffffffffffff0000000000ffffffffffffffffffffffffffffffffffffffff77ffffffff000000000000000000000000000000000000000078ff0000000000000000000000000000000000000000000000006040860151151560c01b169360a01b169116171760045561134f61133360608301516001600160a01b031690565b6001600160a01b03166001600160a01b03196005541617600555565b6040519182918291909160606001600160a01b0381608084019582815116855263ffffffff6020820151166020860152604081015115156040860152015116910152565b0390a180f35b6342bcdf7f60e11b8252600482fd5b3461026b57602036600319011261026b576004356001600160401b03811161026b5760a090600319903603011261026b57600080fd5b3461026b57600036600319011261026b5760206001600160a01b0360015416604051908152f35b6004359060ff8216820361026b57565b359060ff8216820361026b57565b906020808351928381520192019060005b8181106114415750505090565b82516001600160a01b0316845260209384019390920191600101611434565b9061031c9160208152606082518051602084015260ff602082015116604084015260ff6040820151168284015201511515608082015260406114b1602084015160c060a085015260e0840190611423565b9201519060c0601f1982850301910152611423565b3461026b57602036600319011261026b5760ff6114e1611405565b6060604080516114f0816101c8565b6114f86125e5565b815282602082015201521660005260026020526105bc6040600020600361156060405192611525846101c8565b61152e8161260a565b845260405161154b816115448160028601612643565b03826101e3565b60208501526115446040518094819301612643565b604082015260405191829182611460565b3461026b57604036600319011261026b5761158a610270565b6001600160401b036024359116600052600a6020526040600020906000526020526020604060002054604051908152f35b9060049160441161026b57565b9181601f8401121561026b578235916001600160401b03831161026b576020838186019501011161026b57565b3461026b5760c036600319011261026b5761160f366115bb565b6044356001600160401b03811161026b5761162e9036906004016115c8565b6064929192356001600160401b03811161026b5761165090369060040161100e565b60843594916001600160401b03861161026b5761167461039796369060040161100e565b94909360a43596612c75565b90602061031c9281815201906106a3565b3461026b57602036600319011261026b576001600160401b036116b2610270565b6116ba611cbb565b501660005260086020526105bc6040600020600161171b604051926116de84610172565b6001600160401b0381546001600160a01b038116865260ff8160a01c161515602087015260a81c1660408501526115446040518094819301611d8a565b606082015260405191829182611680565b3461026b57602036600319011261026b576001600160a01b036004356117518161025a565b611759613489565b163381146117a657806001600160a01b031960005416176000556001600160a01b03600154167fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae1278600080a3005b636d6c4ee560e11b60005260046000fd5b3461026b57606036600319011261026b576117d1366115bb565b6044356001600160401b03811161026b576117f09036906004016115c8565b9182820160208382031261026b578235906001600160401b03821161026b5761181a918401610d24565b60405190602061182a81846101e3565b60008352601f19810160005b81811061185e57505050610397949161184e916136cd565b611856613184565b928392613a33565b60608582018401528201611836565b9080601f8301121561026b57813561188481610243565b9261189260405194856101e3565b81845260208085019260051b82010192831161026b57602001905b8282106118ba5750505090565b6020809183356118c98161025a565b8152019101906118ad565b3461026b57602036600319011261026b576004356001600160401b03811161026b573660238201121561026b5780600401359061191082610243565b9061191e60405192836101e3565b8282526024602083019360051b8201019036821161026b5760248101935b82851061194c57610397846131a0565b84356001600160401b03811161026b57820160c0602319823603011261026b57611974610204565b916024820135835261198860448301611415565b602084015261199960648301611415565b60408401526119aa608483016102a4565b606084015260a48201356001600160401b03811161026b576119d2906024369185010161186d565b608084015260c4820135926001600160401b03841161026b576119ff60209493602486953692010161186d565b60a082015281520194019361193c565b611a17613489565b60005b8151811015611cb757611a2d8183611d3c565b5190611a4360208301516001600160401b031690565b916001600160401b038316908115611ca657611a78611a6c611a6c83516001600160a01b031690565b6001600160a01b031690565b15611c0d57611a9a846001600160401b03166000526008602052604060002090565b906060810151916001810195611ab08754611d50565b611c3457611b237ff4c1390c70e5c0f491ae1ccbc06f9117cbbadf2767b247b3bc203280f24c0fb991611b0984750100000000000000000000000000000000000000000067ffffffffffffffff60a81b19825416179055565b6040516001600160401b0390911681529081906020820190565b0390a15b82518015908115611c1e575b50611c0d57611bee611bd2611c0493611b6f7f49f51971edd25182e97182d6ea372a0488ce2ab639f6a3a7ab4df0d2636fe56b9660019a61352b565b611bc5611b7f6040830151151590565b85547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1690151560a01b74ff000000000000000000000000000000000000000016178555565b516001600160a01b031690565b82906001600160a01b03166001600160a01b0319825416179055565b611bf78461504a565b50604051918291826135fc565b0390a201611a1a565b6342bcdf7f60e11b60005260046000fd5b90506020840120611c2d6134ae565b1438611b33565b60016001600160401b03611c5384546001600160401b039060a81c1690565b16141580611c87575b611c665750611b27565b632105803760e11b6000526001600160401b031660045260246000fd5b6000fd5b50611c9187611e0d565b60208151910120845160208601201415611c5c565b63c656089560e01b60005260046000fd5b5050565b60405190611cc882610172565b606080836000815260006020820152600060408201520152565b90611cec82610243565b611cf960405191826101e3565b8281528092611d0a601f1991610243565b0190602036910137565b634e487b7160e01b600052603260045260246000fd5b805115611d375760200190565b611d14565b8051821015611d375760209160051b010190565b90600182811c92168015611d80575b6020831014611d6a57565b634e487b7160e01b600052602260045260246000fd5b91607f1691611d5f565b60009291815491611d9a83611d50565b8083529260018116908115611df05750600114611db657505050565b60009081526020812093945091925b838310611dd6575060209250010190565b600181602092949394548385870101520191019190611dc5565b915050602093945060ff929192191683830152151560051b010190565b90610213611e219260405193848092611d8a565b03836101e3565b9060016060604051611e3981610172565b611e8281956001600160401b0381546001600160a01b038116855260ff8160a01c161515602086015260a81c166040840152611e7b6040518096819301611d8a565b03846101e3565b0152565b634e487b7160e01b600052601160045260246000fd5b908160051b9180830460201490151715611eb257565b611e86565b91908203918211611eb257565b611ed082607f92613646565b9116906801fffffffffffffffe6001600160401b0383169260011b169180830460021490151715611eb2576003911c1660048110156108bc5790565b611f1461368a565b80518251810361210b5760005b818110611f3457505090610213916136cd565b611f3e8184611d3c565b516020810190815151611f518488611d3c565b51928351820361210b5790916000925b808410611f75575050505050600101611f21565b91949398611f87848b98939598611d3c565b515198611f95888851611d3c565b5199806120c2575b5060a08a01988b6020611fb38b8d515193611d3c565b51015151036120855760005b8a515181101561207057611ffb611ff2611fe88f6020611fe08f8793611d3c565b510151611d3c565b5163ffffffff1690565b63ffffffff1690565b8b8161200c575b5050600101611fbf565b611ff2604061201f8561202b9451611d3c565b51015163ffffffff1690565b9081811061203a57508b612002565b8d51516040516348e617b360e01b81526004810191909152602481019390935260448301919091526064820152608490fd5b0390fd5b50985098509893949095600101929091611f61565b611c838b516120a0606082519201516001600160401b031690565b6370a193fd60e01b6000526004919091526001600160401b0316602452604490565b60808b0151811015611f9d57611c83908b6120e488516001600160401b031690565b905151633a98d46360e11b6000526001600160401b03909116600452602452604452606490565b6320f8fd5960e21b60005260046000fd5b60405190612129826101ad565b60006020838281520152565b604051906121446020836101e3565b600080835282815b82811061215857505050565b60209061216361211c565b8282850101520161214c565b805182526001600160401b03602082015116602083015260806121b66121a4604084015160a0604087015260a08601906105f8565b606084015185820360608701526105f8565b9101519160808183039101526020808351928381520192019060005b8181106121df5750505090565b825180516001600160a01b0316855260209081015181860152604090940193909201916001016121d2565b90602061031c92818152019061216f565b6040513d6000823e3d90fd5b3d15612252573d90612238826102af565b9161224660405193846101e3565b82523d6000602084013e565b606090565b90602061031c9281815201906105f8565b909160608284031261026b57815161227f8161029a565b9260208301516001600160401b03811161026b5783019080601f8301121561026b578151916122ad836102af565b916122bb60405193846101e3565b8383526020848301011161026b576040926122dc91602080850191016105d5565b92015190565b9293606092959461ffff6123066001600160a01b039460808852608088019061216f565b97166020860152604085015216910152565b929093913033036125d45761232b612135565b9460a0850151805161258d575b5050505050805191612356602084519401516001600160401b031690565b906020830151916040840192612383845192612370610215565b9788526001600160401b03166020880152565b6040860152606085015260808401526001600160a01b036123ac6005546001600160a01b031690565b1680612510575b5051511580612504575b80156124ee575b80156124c5575b611cb75761245d9181612402611a6c6123f561084b602060009751016001600160401b0390511690565b546001600160a01b031690565b908361241d606060808401519301516001600160a01b031690565b604051633cf9798360e01b815296879586948593917f000000000000000000000000000000000000000000000000000000000000000090600486016122e2565b03925af19081156124c057600090600092612499575b501561247c5750565b6040516302a35ba360e21b815290819061206c9060048301612257565b90506124b891503d806000833e6124b081836101e3565b810190612268565b509038612473565b61221b565b506124e96124e56124e060608401516001600160a01b031690565b6138f4565b1590565b6123cb565b5060608101516001600160a01b03163b156123c4565b506080810151156123bd565b803b1561026b57600060405180926308d450a160e01b82528183816125388a6004830161220a565b03925af19081612572575b5061256c5761206c612553612227565b6040516309c2532560e01b815291829160048301612257565b386123b3565b806125816000612587936101e3565b80610432565b38612543565b85965060206125c99601516125ac60608901516001600160a01b031690565b906125c360208a51016001600160401b0390511690565b926137db565b903880808080612338565b6306e34e6560e31b60005260046000fd5b604051906125f282610172565b60006060838281528260208201528260408201520152565b9060405161261781610172565b606060ff600183958054855201548181166020850152818160081c16604085015260101c161515910152565b906020825491828152019160005260206000209060005b8181106126675750505090565b82546001600160a01b031684526020909301926001928301920161265a565b90610213611e219260405193848092612643565b35906001600160e01b038216820361026b57565b81601f8201121561026b578035906126c582610243565b926126d360405194856101e3565b82845260208085019360061b8301019181831161026b57602001925b8284106126fd575050505090565b60408483031261026b5760206040918251612717816101ad565b61272087610286565b815261272d83880161269a565b838201528152019301926126ef565b81601f8201121561026b5780359061275382610243565b9261276160405194856101e3565b82845260208085019360051b8301019181831161026b5760208101935b83851061278d57505050505090565b84356001600160401b03811161026b57820160a0818503601f19011261026b57604051916127ba83610192565b6127c660208301610286565b83526040820135926001600160401b03841161026b5760a0836127f0886020809881980101610301565b8584015261280060608201610286565b604084015261281160808201610286565b60608401520135608082015281520194019361277e565b81601f8201121561026b5780359061283f82610243565b9261284d60405194856101e3565b82845260208085019360061b8301019181831161026b57602001925b828410612877575050505090565b60408483031261026b5760206040918251612891816101ad565b863581528287013583820152815201930192612869565b60208183031261026b578035906001600160401b03821161026b570160608183031261026b57604051916128db836101c8565b81356001600160401b03811161026b57820160408183031261026b5760405190612904826101ad565b80356001600160401b03811161026b57810183601f8201121561026b57803561292c81610243565b9161293a60405193846101e3565b81835260208084019260061b8201019086821161026b57602001915b8183106129d25750505082526020810135906001600160401b03821161026b57612982918491016126ae565b6020820152835260208201356001600160401b03811161026b57816129a891840161273c565b602084015260408201356001600160401b03811161026b576129ca9201612828565b604082015290565b60408388031261026b57602060409182516129ec816101ad565b85356129f78161025a565b8152612a0483870161269a565b83820152815201920191612956565b9080602083519182815201916020808360051b8301019401926000915b838310612a3f57505050505090565b9091929394602080600192601f198582030186528851906001600160401b038251168152608080612a7d8585015160a08786015260a08501906105f8565b936001600160401b0360408201511660408501526001600160401b036060820151166060850152015191015297019301930191939290612a30565b916001600160a01b03612ad992168352606060208401526060830190612a13565b9060408183039101526020808351928381520192019060005b818110612aff5750505090565b8251805185526020908101518186015260409094019390920191600101612af2565b906020808351928381520192019060005b818110612b3f5750505090565b825180516001600160401b031685526020908101516001600160e01b03168186015260409094019390920191600101612b32565b9190604081019083519160408252825180915260206060830193019060005b818110612bb357505050602061031c93940151906020818403910152612b21565b825180516001600160a01b031686526020908101516001600160e01b03168187015260409095019490920191600101612b92565b90602061031c928181520190612b73565b9081602091031261026b575161031c8161029a565b9091612c2461031c936040845260408401906105f8565b916020818403910152611d8a565b6001600160401b036001911601906001600160401b038211611eb257565b9091612c6761031c93604084526040840190612a13565b916020818403910152612b73565b929693959190979497612c8a828201826128a8565b98612c9e6124e560045460ff9060c01c1690565b6130f2575b895180515115908115916130e3575b5061300a575b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316999860208a019860005b8a518051821015612fa85781612d0191611d3c565b518d612d1482516001600160401b031690565b604051632cbc26bb60e01b815267ffffffffffffffff60801b608083901b1660048201529091602090829060249082905afa9081156124c057600091612f7a575b50612f5d57612d6390613942565b60208201805160208151910120906001830191612d7f83611e0d565b6020815191012003612f40575050805460408301516001600160401b039081169160a81c168114801590612f18575b612ec657506080820151908115612eb557612dff82612df0612dd786516001600160401b031690565b6001600160401b0316600052600a602052604060002090565b90600052602052604060002090565b54612e81578291612e65612e7a92612e2c612e2760606001999801516001600160401b031690565b612c32565b67ffffffffffffffff60a81b197cffffffffffffffff00000000000000000000000000000000000000000083549260a81b169116179055565b612df0612dd74294516001600160401b031690565b5501612cec565b50612e96611c8392516001600160401b031690565b6332cf0cbf60e01b6000526001600160401b0316600452602452604490565b63504570e360e01b60005260046000fd5b82611c8391612ef06060612ee184516001600160401b031690565b9301516001600160401b031690565b636af0786b60e11b6000526001600160401b0392831660045290821660245216604452606490565b50612f3061080760608501516001600160401b031690565b6001600160401b03821611612dae565b5161206c60405192839263b80d8fa960e01b845260048401612c0d565b637edeb53960e11b6000526001600160401b031660045260246000fd5b612f9b915060203d8111612fa1575b612f9381836101e3565b810190612bf8565b38612d55565b503d612f89565b50506130049496989b507f35c02761bcd3ef995c6a601a1981f4ed3934dcbe5041e24e286c89f5531d17e46102139b612ffc949597999b51905190612ff260405192839283612c50565b0390a13691610cbd565b943691610cbd565b93613d11565b61301f602086015b356001600160401b031690565b600b546001600160401b03828116911610156130c757613055906001600160401b03166001600160401b0319600b541617600b55565b61306d611a6c611a6c6004546001600160a01b031690565b8a5190803b1561026b57604051633937306f60e01b815291600091839182908490829061309d9060048301612be7565b03925af180156124c0576130b2575b50612cb8565b8061258160006130c1936101e3565b386130ac565b5060208a015151612cb857632261116760e01b60005260046000fd5b60209150015151151538612cb2565b60208a01518051613104575b50612ca3565b6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169060408c0151823b1561026b57604051633854844f60e11b815292600092849283918291613160913060048501612ab8565b03915afa80156124c057156130fe5780612581600061317e936101e3565b386130fe565b604051906131936020836101e3565b6000808352366020840137565b6131a8613489565b60005b8151811015611cb7576131be8183611d3c565b51906040820160ff6131d1825160ff1690565b161561347357602083015160ff16926131f78460ff166000526002602052604060002090565b916001830191825461321261320c8260ff1690565b60ff1690565b613438575061323f6132276060830151151590565b845462ff0000191690151560101b62ff000016178455565b60a081019182516101008151116133e057805115613422576003860161326d61326782612686565b8a614df8565b60608401516132fd575b947fab8b1b57514019638d7b5ce9c638fe71366fe8e2be1c40a7a80f1733d0e9f547946002946132d96132c96132f79a966132c28760019f9c6132bd6132ef9a8f614f59565b613f25565b5160ff1690565b845460ff191660ff821617909455565b5190818555519060405195869501908886613fab565b0390a1614fdb565b016131ab565b9794600287939597019661331961331389612686565b88614df8565b60808501519461010086511161340c57855161334161320c61333c8a5160ff1690565b613f11565b10156133f65785518451116133e0576132d96132c97fab8b1b57514019638d7b5ce9c638fe71366fe8e2be1c40a7a80f1733d0e9f547986132c28760019f6132bd6132f79f9a8f6133c860029f6133c26132ef9f8f906132bd84926133a7845160ff1690565b908054909161ff001990911660089190911b61ff0016179055565b82614e8c565b505050979c9f50975050969a50505094509450613277565b631b3fab5160e11b600052600160045260246000fd5b631b3fab5160e11b600052600360045260246000fd5b631b3fab5160e11b600052600260045260246000fd5b631b3fab5160e11b600052600560045260246000fd5b60101c60ff1661345361344e6060840151151590565b151590565b9015151461323f576321fd80df60e21b60005260ff861660045260246000fd5b631b3fab5160e11b600090815260045260246000fd5b6001600160a01b0360015416330361349d57565b6315ae3a6f60e11b60005260046000fd5b604051602081019060008252602081526134c96040826101e3565b51902090565b8181106134da575050565b600081556001016134cf565b9190601f81116134f557505050565b610213926000526020600020906020601f840160051c83019310613521575b601f0160051c01906134cf565b9091508190613514565b91909182516001600160401b03811161018d576135528161354c8454611d50565b846134e6565b6020601f8211600114613593578190613584939495600092613588575b50508160011b916000199060031b1c19161790565b9055565b01519050388061356f565b601f198216906135a884600052602060002090565b9160005b8181106135e4575095836001959697106135cb575b505050811b019055565b015160001960f88460031b161c191690553880806135c1565b9192602060018192868b0151815501940192016135ac565b90600160a061031c93602081526001600160401b0384546001600160a01b038116602084015260ff81851c161515604084015260a81c166060820152608080820152019101611d8a565b906001600160401b03613686921660005260096020526701ffffffffffffff60406000209160071c166001600160401b0316600052602052604060002090565b5490565b7f00000000000000000000000000000000000000000000000000000000000000004681036136b55750565b630f01ce8560e01b6000526004524660245260446000fd5b91909180511561376f5782511592602091604051926136ec81856101e3565b60008452601f19810160005b81811061374b5750505060005b8151811015613743578061372c61371e60019385611d3c565b5188156137325786906140ea565b01613705565b61373c8387611d3c565b51906140ea565b505050509050565b8290604051613759816101ad565b60008152606083820152828289010152016136f8565b63c2e5347d60e01b60005260046000fd5b9190811015611d375760051b0190565b3561031c81610983565b9190811015611d375760051b81013590601e198136030182121561026b5701908135916001600160401b03831161026b57602001823603811361026b579190565b909294919397968151966137ee88610243565b976137fc604051998a6101e3565b80895261380b601f1991610243565b0160005b8181106138dd57505060005b83518110156138d057806138628c8a8a8a61385c613855878d61384e828f8f9d8f9e60019f8161387e575b505050611d3c565b519761379a565b36916102ca565b9361492f565b61386c828c611d3c565b52613877818b611d3c565b500161381b565b63ffffffff613896613891858585613780565b613790565b1615613846576138c6926138ad9261389192613780565b60406138b98585611d3c565b51019063ffffffff169052565b8f8f908391613846565b5096985050505050505050565b6020906138e861211c565b82828d0101520161380f565b6139056385572ffb60e01b82614c92565b908161391f575b81613915575090565b61031c9150614c64565b905061392a81614be9565b159061390c565b61390563aff2afbf60e01b82614c92565b6001600160401b031680600052600860205260406000209060ff825460a01c161561396b575090565b63ed053c5960e01b60005260045260246000fd5b6084019081608411611eb257565b60a001908160a011611eb257565b91908201809211611eb257565b600311156108bc57565b60038210156108bc5752565b906102136040516139ce816101ad565b602060ff829554818116845260081c1691016139b2565b8054821015611d375760005260206000200190600090565b60ff60019116019060ff8211611eb257565b60ff601b9116019060ff8211611eb257565b90606092604091835260208301370190565b6001600052600260205293613a677fe90b7bceb6e7df5418fb78d8ee546e97c83a08bbccc01a0644d599ccd2a7c2e061260a565b93853594613a748561397f565b6060820190613a838251151590565b613ce3575b803603613ccb57508151878103613cb25750613aa261368a565b60016000526003602052613af1613aec7fa15bc60c955c405d20d9149c709e2460f1c2d9a497496a7f46004d1772c3054c5b336001600160a01b0316600052602052604060002090565b6139be565b60026020820151613b01816139a8565b613b0a816139a8565b149081613c4a575b5015613c395751613b70575b50505050507f198d6990ef96613a9026203077e422916918b03ff47f0be6bee7b02d8e139ef090613b5461301260019460200190565b604080519283526001600160401b0391909116602083015290a2565b613b9161320c613b8c602085969799989a955194015160ff1690565b6139fd565b03613c28578151835103613c1757613c0f6000613b549461301294613bdb7f198d6990ef96613a9026203077e422916918b03ff47f0be6bee7b02d8e139ef09960019b36916102ca565b60208151910120604051613c0681613bf889602083019586613a21565b03601f1981018352826101e3565b5190208a614cc2565b948394613b1e565b63a75d88af60e01b60005260046000fd5b6371253a2560e01b60005260046000fd5b631b41e11d60e31b60005260046000fd5b60016000526002602052613caa9150611a6c90613c9790613c9160037fe90b7bceb6e7df5418fb78d8ee546e97c83a08bbccc01a0644d599ccd2a7c2e05b01915160ff1690565b906139e5565b90546001600160a01b039160031b1c1690565b331438613b12565b6324f7d61360e21b600052600452602487905260446000fd5b638e1192e160e01b6000526004523660245260446000fd5b613d0c90613d06613cfc613cf78751611e9c565b61398d565b613d068851611e9c565b9061399b565b613a88565b60008052600260205294909390929091613d4a7fac33ff75c19e70fe83507db0d683fd3465c996598dc972688b7ace676c89077b61260a565b94863595613d578361397f565b6060820190613d668251151590565b613eee575b803603613ccb57508151888103613ed55750613d8561368a565b600080526003602052613dba613aec7f3617319a054d772f909f7c479a2cebe5066e836a939412e32403c99029b92eff613ad4565b60026020820151613dca816139a8565b613dd3816139a8565b149081613e8c575b5015613c395751613e1e575b5050505050507f198d6990ef96613a9026203077e422916918b03ff47f0be6bee7b02d8e139ef090613b5461301260009460200190565b613e3a61320c613b8c602087989a999b96975194015160ff1690565b03613c28578351865103613c17576000967f198d6990ef96613a9026203077e422916918b03ff47f0be6bee7b02d8e139ef096613b5495613bdb613e83946130129736916102ca565b94839438613de7565b600080526002602052613ecd9150611a6c90613c9790613c9160037fac33ff75c19e70fe83507db0d683fd3465c996598dc972688b7ace676c89077b613c88565b331438613ddb565b6324f7d61360e21b600052600452602488905260446000fd5b613f0c90613d06613f02613cf78951611e9c565b613d068a51611e9c565b613d6b565b60ff166003029060ff8216918203611eb257565b8151916001600160401b03831161018d5768010000000000000000831161018d576020908254848455808510613f8e575b500190600052602060002060005b838110613f715750505050565b60019060206001600160a01b038551169401938184015501613f64565b613fa59084600052858460002091820191016134cf565b38613f56565b95949392909160ff613fd093168752602087015260a0604087015260a0860190612643565b84810360608601526020808351928381520192019060005b818110614003575050509060806102139294019060ff169052565b82516001600160a01b0316845260209384019390920191600101613fe8565b600654811015611d375760066000527ff652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d3f015490565b6001600160401b0361031c94938160609416835216602082015281604082015201906105f8565b60409061031c9392815281602082015201906105f8565b9291906001600160401b039081606495166004521660245260048110156108bc57604452565b9493926140d46060936140e593885260208801906108c1565b6080604087015260808601906105f8565b930152565b906140fc82516001600160401b031690565b8151604051632cbc26bb60e01b815267ffffffffffffffff60801b608084901b1660048201529015159391906001600160401b038216906020816024817f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03165afa9081156124c057600091614818575b506147d65760208301918251519485156147a6576040850180515187036147955761419e87611ce2565b957f00000000000000000000000000000000000000000000000000000000000000006141d460016141ce87613942565b01611e0d565b6020815191012060405161423481613bf86020820194868b876001600160401b036060929594938160808401977f2425b0b9f9054c76ff151b0a175b18f37a4a4e82013a72e9f15c9caa095ed21f85521660208401521660408201520152565b519020906001600160401b031660005b8a81106146fd57505050806080606061426493015191015190888661528b565b9788156146df5760005b8881106142815750505050505050505050565b5a61428d828951611d3c565b518051606001516142a7906001600160401b031688611ec4565b6142b0816108b2565b8015908d82831593846146cc575b15614689576060881561460c57506142e560206142db898d611d3c565b5101519242611eb7565b6004546142fa9060a01c63ffffffff16611ff2565b1080156145f9575b156145db57614311878b611d3c565b51516145c5575b845160800151614330906001600160401b0316610807565b61450d575b50614341868951611d3c565b5160a0850151518151036144d157936143a69695938c938f966143868e958c9261438061437a60608951016001600160401b0390511690565b896152bd565b86615464565b9a9080966143a060608851016001600160401b0390511690565b90615345565b61447f575b50506143b6826108b2565b60028203614437575b60019661442d7f05665fe9ad095383d018353f4cbcba77e84db27dd215081bbf7cdf9ae6fbe48b936001600160401b0393519261441e6144158b61440d60608801516001600160401b031690565b96519b611d3c565b51985a90611eb7565b916040519586951698856140bb565b0390a45b0161426e565b91509193949250614447826108b2565b6003820361445b578b929493918a916143bf565b51606001516349362d1f60e11b600052611c8391906001600160401b031689614095565b614488846108b2565b600384036143ab5790929495506144a09193506108b2565b6144b0578b92918a9138806143ab565b5151604051632b11b8d960e01b815290819061206c9087906004840161407e565b611c838b6144eb60608851016001600160401b0390511690565b631cfe6d8b60e01b6000526001600160401b0391821660045216602452604490565b614516836108b2565b614521575b38614335565b8351608001516001600160401b0316602080860151918c61455660405194859384936370701e5760e11b855260048501614057565b038160006001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000165af19081156124c0576000916145a7575b5061451b575050505050600190614431565b6145bf915060203d8111612fa157612f9381836101e3565b38614595565b6145cf878b611d3c565b51516080860152614318565b6354e7e43160e11b6000526001600160401b038b1660045260246000fd5b50614603836108b2565b60038314614302565b915083614618846108b2565b1561431857506001959450614681925061465f91507f3ef2a99c550a751d4b0b261268f05a803dfb049ab43616a1ffb388f61fe651209351016001600160401b0390511690565b604080516001600160401b03808c168252909216602083015290918291820190565b0390a1614431565b50505050600192915061468161465f60607f3b575419319662b2a6f5e2467d84521517a3382b908eb3d557bb3fdb0c50e23c9351016001600160401b0390511690565b506146d6836108b2565b600383146142be565b633ee8bd3f60e11b6000526001600160401b03841660045260246000fd5b614708818a51611d3c565b518051604001516001600160401b031683810361477857508051602001516001600160401b031689810361475557509061474484600193615183565b61474e828d611d3c565b5201614244565b636c95f1eb60e01b6000526001600160401b03808a166004521660245260446000fd5b631c21951160e11b6000526001600160401b031660045260246000fd5b6357e0e08360e01b60005260046000fd5b611c836147ba86516001600160401b031690565b63676cf24b60e11b6000526001600160401b0316600452602490565b5092915050612f5d576040516001600160401b039190911681527faab522ed53d887e56ed53dd37398a01aeef6a58e0fa77c2173beb9512d89493390602090a1565b614831915060203d602011612fa157612f9381836101e3565b38614174565b9081602091031261026b575161031c8161025a565b9061031c916020815260e06148ea6148d5614875855161010060208701526101208601906105f8565b60208601516001600160401b0316604086015260408601516001600160a01b03166060860152606086015160808601526148bf608087015160a08701906001600160a01b03169052565b60a0860151858203601f190160c08701526105f8565b60c0850151848203601f1901848601526105f8565b92015190610100601f19828503019101526105f8565b6040906001600160a01b0361031c949316815281602082015201906105f8565b9081602091031261026b575190565b9193929361493b61211c565b5060208301516001600160a01b031660405163bbe4f6db60e01b81526001600160a01b038216600482015290959092602084806024810103816001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000165afa9384156124c057600094614bb8575b506001600160a01b0384169586158015614ba6575b614b8857614a6d614a9692613bf8926149f16149ea611ff260408c015163ffffffff1690565b8c896155a5565b9690996080810151614a1f6060835193015193614a0c610224565b9687526001600160401b03166020870152565b6001600160a01b038a16604086015260608501526001600160a01b038d16608085015260a084015260c083015260e0820152604051633907753760e01b60208201529283916024830161484c565b82857f000000000000000000000000000000000000000000000000000000000000000092615633565b94909115614b6c5750805160208103614b53575090614abf826020808a95518301019101614920565b956001600160a01b03841603614af7575b5050505050614aef614ae0610234565b6001600160a01b039093168352565b602082015290565b614b0a93614b0491611eb7565b916155a5565b50908082108015614b40575b614b2257808481614ad0565b63a966e21f60e01b6000908152600493909352602452604452606490fd5b5082614b4c8284611eb7565b1415614b16565b631e3be00960e21b600052602060045260245260446000fd5b61206c604051928392634ff17cad60e11b845260048401614900565b63ae9b4ce960e01b6000526001600160a01b03851660045260246000fd5b50614bb36124e586613931565b6149c4565b614bdb91945060203d602011614be2575b614bd381836101e3565b810190614837565b92386149af565b503d614bc9565b60405160208101916301ffc9a760e01b835263ffffffff60e01b602483015260248252614c176044836101e3565b6179185a10614c53576020926000925191617530fa6000513d82614c47575b5081614c40575090565b9050151590565b60201115915038614c36565b63753fa58960e11b60005260046000fd5b60405160208101916301ffc9a760e01b83526301ffc9a760e01b602483015260248252614c176044836101e3565b6040519060208201926301ffc9a760e01b845263ffffffff60e01b16602483015260248252614c176044836101e3565b919390926000948051946000965b868810614ce1575050505050505050565b6020881015611d375760206000614cf9878b1a613a0f565b614d038b87611d3c565b5190614d3a614d128d8a611d3c565b5160405193849389859094939260ff6060936080840197845216602083015260408201520152565b838052039060015afa156124c057614d80613aec600051614d688960ff166000526003602052604060002090565b906001600160a01b0316600052602052604060002090565b9060016020830151614d91816139a8565b614d9a816139a8565b03614de757614db7614dad835160ff1690565b60ff600191161b90565b8116614dd657614dcd614dad6001935160ff1690565b17970196614cd0565b633d9ef1f160e21b60005260046000fd5b636518c33d60e11b60005260046000fd5b91909160005b8351811015614e515760019060ff831660005260036020526000614e4a604082206001600160a01b03614e31858a611d3c565b51166001600160a01b0316600052602052604060002090565b5501614dfe565b50509050565b8151815460ff191660ff91909116178155906020015160038110156108bc57815461ff00191660089190911b61ff0016179055565b919060005b8151811015614e5157614ea7611bc58284611d3c565b90614ed0614ec683614d688860ff166000526003602052604060002090565b5460081c60ff1690565b614ed9816139a8565b614f44576001600160a01b03821615614f3357614f2d600192614f28614efd610234565b60ff8516815291614f1186602085016139b2565b614d688960ff166000526003602052604060002090565b614e57565b01614e91565b63d6c62c9b60e01b60005260046000fd5b631b3fab5160e11b6000526004805260246000fd5b919060005b8151811015614e5157614f74611bc58284611d3c565b90614f93614ec683614d688860ff166000526003602052604060002090565b614f9c816139a8565b614f44576001600160a01b03821615614f3357614fd5600192614f28614fc0610234565b60ff8516815291614f116002602085016139b2565b01614f5e565b60ff1680600052600260205260ff60016040600020015460101c16908015600014615029575015615018576001600160401b0319600b5416600b55565b6317bd8dd160e11b60005260046000fd5b6001146150335750565b61503957565b6307b8c74d60e51b60005260046000fd5b806000526007602052604060002054156000146150c8576006546801000000000000000081101561018d57600181016006556000600654821015611d3757600690527ff652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d3f01819055600654906000526007602052604060002055600190565b50600090565b9080602083519182815201916020808360051b8301019401926000915b8383106150fa57505050505090565b9091929394602080600192601f1985820301865288519060808061515d61512a855160a0865260a08601906105f8565b6001600160a01b0387870151168786015263ffffffff6040870151166040860152606086015185820360608701526105f8565b930151910152970193019301919392906150eb565b90602061031c9281815201906150ce565b6134c981518051906152176151a260608601516001600160a01b031690565b613bf86151b960608501516001600160401b031690565b936151d26080808a01519201516001600160401b031690565b90604051958694602086019889936001600160401b036080946001600160a01b0382959998949960a089019a8952166020880152166040860152606085015216910152565b519020613bf86020840151602081519101209360a060408201516020815191012091015160405161525081613bf8602082019485615172565b51902090604051958694602086019889919260a093969594919660c08401976000855260208501526040840152606083015260808201520152565b926001600160401b039261529e926156f0565b9116600052600a60205260406000209060005260205260406000205490565b607f8216906801fffffffffffffffe6001600160401b0383169260011b169180830460021490151715611eb257615342916001600160401b036153008584613646565b921660005260096020526701ffffffffffffff60406000209460071c169160036001831b921b19161792906001600160401b0316600052602052604060002090565b55565b9091607f83166801fffffffffffffffe6001600160401b0382169160011b169080820460021490151715611eb25761537d8484613646565b60048310156108bc576001600160401b036153429416600052600960205260036701ffffffffffffff60406000209660071c1693831b921b19161792906001600160401b0316600052602052604060002090565b9080602083519182815201916020808360051b8301019401926000915b8383106153fd57505050505090565b909192939460208061541b600193601f1986820301875289516105f8565b970193019301919392906153ee565b906020808351928381520192019060005b8181106154485750505090565b825163ffffffff1684526020938401939092019160010161543b565b91606092303b1561026b5761556660a0926155546000956155426040519889978897630304c3e160e51b89528260048a01526001600160401b0360808251805160648d01528260208201511660848d01528260408201511660a48d015282868201511660c48d015201511660e48a015261552361550e6154f78b61014061010460208701519201526101a48d01906105f8565b60408401518c8203606319016101248e01526105f8565b938201516001600160a01b03166101448b0152565b60808101516101648a01520151878203606319016101848901526150ce565b858103600319016024870152906153d1565b8381036003190160448501529061542a565b038183305af19081615590575b5061558557615580612227565b600391565b60029061031c6105c0565b80612581600061559f936101e3565b38615573565b6040516370a0823160e01b60208201526001600160a01b039091166024820152919291615602906155d98160448101613bf8565b84837f000000000000000000000000000000000000000000000000000000000000000092615633565b92909115614b6c5750805160208103614b5357509061562d8260208061031c95518301019101614920565b93611eb7565b93919361564060846102af565b9461564e60405196876101e3565b6084865261565c60846102af565b602087019590601f1901368737833b156156df575a908082106156ce578291038060061c900311156156bd576000918291825a9560208451940192f1905a9003923d90608482116156b4575b6000908287523e929190565b608491506156a8565b6337c3be2960e01b60005260046000fd5b632be8ca8b60e21b60005260046000fd5b63030ed58f60e21b60005260046000fd5b805192825190841561584c5761010185111580615840575b1561576f5781850194600019860195610100871161576f5786156158305761572f87611ce2565b9660009586978795885b84811061579457505050505060011901809514938461578a575b505082615780575b50501561576f5761576b91611d3c565b5190565b6309bde33960e01b60005260046000fd5b149050388061575b565b1492503880615753565b6001811b8281160361582257868a101561580d576157b660018b019a85611d3c565b51905b8c888c10156157f957506157d160018c019b86611d3c565b515b818d1161576f576157f2828f926157ec9060019661585d565b92611d3c565b5201615739565b60018d019c61580791611d3c565b516157d3565b61581b60018c019b8d611d3c565b51906157b9565b61581b600189019884611d3c565b50505050905061576b9150611d2a565b50610101821115615708565b630469ac9960e21b60005260046000fd5b8181101561586f579061031c91615874565b61031c915b906040519060208201926001845260408301526060820152606081526134c96080826101e356fea164736f6c634300081a000a49f51971edd25182e97182d6ea372a0488ce2ab639f6a3a7ab4df0d2636fe56b", + ABI: "[{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"contractIRMNRemote\",\"name\":\"rmnRemote\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"}],\"internalType\":\"structOffRamp.StaticConfig\",\"name\":\"staticConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"permissionLessExecutionThresholdSeconds\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isRMNVerificationDisabled\",\"type\":\"bool\"},{\"internalType\":\"address\",\"name\":\"messageInterceptor\",\"type\":\"address\"}],\"internalType\":\"structOffRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"internalType\":\"structOffRamp.SourceChainConfigArgs[]\",\"name\":\"sourceChainConfigs\",\"type\":\"tuple[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"CanOnlySelfCall\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CannotTransferToSelf\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"reportOnRamp\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"configOnRamp\",\"type\":\"bytes\"}],\"name\":\"CommitOnRampMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"expected\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"actual\",\"type\":\"bytes32\"}],\"name\":\"ConfigDigestMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"CursedByRMN\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"EmptyBatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"EmptyReport\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"err\",\"type\":\"bytes\"}],\"name\":\"ExecutionError\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"expected\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"actual\",\"type\":\"uint256\"}],\"name\":\"ForkedChain\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"enumMultiOCR3Base.InvalidConfigErrorType\",\"name\":\"errorType\",\"type\":\"uint8\"}],\"name\":\"InvalidConfig\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"expected\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"got\",\"type\":\"uint256\"}],\"name\":\"InvalidDataLength\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"min\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"max\",\"type\":\"uint64\"}],\"name\":\"InvalidInterval\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"newLimit\",\"type\":\"uint256\"}],\"name\":\"InvalidManualExecutionGasLimit\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"tokenIndex\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"oldLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"tokenGasOverride\",\"type\":\"uint256\"}],\"name\":\"InvalidManualExecutionTokenGasOverride\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"messageDestChainSelector\",\"type\":\"uint64\"}],\"name\":\"InvalidMessageDestChainSelector\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"enumInternal.MessageExecutionState\",\"name\":\"newState\",\"type\":\"uint8\"}],\"name\":\"InvalidNewState\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"InvalidOnRampUpdate\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidProof\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidRoot\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"LeavesCannotBeEmpty\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"ManualExecutionGasAmountCountMismatch\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ManualExecutionGasLimitMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"ManualExecutionNotYetEnabled\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"errorReason\",\"type\":\"bytes\"}],\"name\":\"MessageValidationError\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MustBeProposedOwner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NonUniqueSignatures\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"notPool\",\"type\":\"address\"}],\"name\":\"NotACompatiblePool\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByOwner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OracleCannotBeZeroAddress\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OwnerCannotBeZero\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"err\",\"type\":\"bytes\"}],\"name\":\"ReceiverError\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountReleased\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"balancePre\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"balancePost\",\"type\":\"uint256\"}],\"name\":\"ReleaseOrMintBalanceMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"merkleRoot\",\"type\":\"bytes32\"}],\"name\":\"RootAlreadyCommitted\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"RootNotCommitted\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"SignatureVerificationNotAllowedInExecutionPlugin\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"SignatureVerificationRequiredInCommitPlugin\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"SignaturesOutOfRegistration\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"SourceChainNotEnabled\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"reportSourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"messageSourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"SourceChainSelectorMismatch\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"StaleCommitReport\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"}],\"name\":\"StaticConfigCannotBeChanged\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"TokenDataMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"err\",\"type\":\"bytes\"}],\"name\":\"TokenHandlingError\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnauthorizedSigner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnauthorizedTransmitter\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnexpectedTokenData\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"expected\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"actual\",\"type\":\"uint256\"}],\"name\":\"WrongMessageLength\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"WrongNumberOfSignatures\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroChainSelectorNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"AlreadyAttempted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRampAddress\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"maxSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"merkleRoot\",\"type\":\"bytes32\"}],\"indexed\":false,\"internalType\":\"structInternal.MerkleRoot[]\",\"name\":\"merkleRoots\",\"type\":\"tuple[]\"},{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sourceToken\",\"type\":\"address\"},{\"internalType\":\"uint224\",\"name\":\"usdPerToken\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.TokenPriceUpdate[]\",\"name\":\"tokenPriceUpdates\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint224\",\"name\":\"usdPerUnitGas\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.GasPriceUpdate[]\",\"name\":\"gasPriceUpdates\",\"type\":\"tuple[]\"}],\"indexed\":false,\"internalType\":\"structInternal.PriceUpdates\",\"name\":\"priceUpdates\",\"type\":\"tuple\"}],\"name\":\"CommitReportAccepted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"F\",\"type\":\"uint8\"}],\"name\":\"ConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"permissionLessExecutionThresholdSeconds\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isRMNVerificationDisabled\",\"type\":\"bool\"},{\"internalType\":\"address\",\"name\":\"messageInterceptor\",\"type\":\"address\"}],\"indexed\":false,\"internalType\":\"structOffRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"}],\"name\":\"DynamicConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"messageHash\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"enumInternal.MessageExecutionState\",\"name\":\"state\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"returnData\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"gasUsed\",\"type\":\"uint256\"}],\"name\":\"ExecutionStateChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"root\",\"type\":\"bytes32\"}],\"name\":\"RootRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"SkippedAlreadyExecutedMessage\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"SkippedReportExecution\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"indexed\":false,\"internalType\":\"structOffRamp.SourceChainConfig\",\"name\":\"sourceConfig\",\"type\":\"tuple\"}],\"name\":\"SourceChainConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"SourceChainSelectorAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"contractIRMNRemote\",\"name\":\"rmnRemote\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"}],\"indexed\":false,\"internalType\":\"structOffRamp.StaticConfig\",\"name\":\"staticConfig\",\"type\":\"tuple\"}],\"name\":\"StaticConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"Transmitted\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"internalType\":\"structOffRamp.SourceChainConfigArgs[]\",\"name\":\"sourceChainConfigUpdates\",\"type\":\"tuple[]\"}],\"name\":\"applySourceChainConfigUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"sender\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structClient.EVMTokenAmount[]\",\"name\":\"destTokenAmounts\",\"type\":\"tuple[]\"}],\"internalType\":\"structClient.Any2EVMMessage\",\"name\":\"\",\"type\":\"tuple\"}],\"name\":\"ccipReceive\",\"outputs\":[],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[3]\",\"name\":\"reportContext\",\"type\":\"bytes32[3]\"},{\"internalType\":\"bytes\",\"name\":\"report\",\"type\":\"bytes\"},{\"internalType\":\"bytes32[]\",\"name\":\"rs\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes32[]\",\"name\":\"ss\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes32\",\"name\":\"rawVs\",\"type\":\"bytes32\"}],\"name\":\"commit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[3]\",\"name\":\"reportContext\",\"type\":\"bytes32[3]\"},{\"internalType\":\"bytes\",\"name\":\"report\",\"type\":\"bytes\"}],\"name\":\"execute\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"}],\"internalType\":\"structInternal.RampMessageHeader\",\"name\":\"header\",\"type\":\"tuple\"},{\"internalType\":\"bytes\",\"name\":\"sender\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"destTokenAddress\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"destGasAmount\",\"type\":\"uint32\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structInternal.Any2EVMTokenTransfer[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.Any2EVMRampMessage\",\"name\":\"message\",\"type\":\"tuple\"},{\"internalType\":\"bytes[]\",\"name\":\"offchainTokenData\",\"type\":\"bytes[]\"},{\"internalType\":\"uint32[]\",\"name\":\"tokenGasOverrides\",\"type\":\"uint32[]\"}],\"name\":\"executeSingleMessage\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAllSourceChainConfigs\",\"outputs\":[{\"internalType\":\"uint64[]\",\"name\":\"\",\"type\":\"uint64[]\"},{\"components\":[{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"internalType\":\"structOffRamp.SourceChainConfig[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getDynamicConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"permissionLessExecutionThresholdSeconds\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isRMNVerificationDisabled\",\"type\":\"bool\"},{\"internalType\":\"address\",\"name\":\"messageInterceptor\",\"type\":\"address\"}],\"internalType\":\"structOffRamp.DynamicConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"getExecutionState\",\"outputs\":[{\"internalType\":\"enumInternal.MessageExecutionState\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getLatestPriceSequenceNumber\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"root\",\"type\":\"bytes32\"}],\"name\":\"getMerkleRoot\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"getSourceChainConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"internalType\":\"structOffRamp.SourceChainConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getStaticConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"contractIRMNRemote\",\"name\":\"rmnRemote\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"}],\"internalType\":\"structOffRamp.StaticConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"}],\"name\":\"latestConfigDetails\",\"outputs\":[{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"internalType\":\"uint8\",\"name\":\"F\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"n\",\"type\":\"uint8\"},{\"internalType\":\"bool\",\"name\":\"isSignatureVerificationEnabled\",\"type\":\"bool\"}],\"internalType\":\"structMultiOCR3Base.ConfigInfo\",\"name\":\"configInfo\",\"type\":\"tuple\"},{\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"}],\"internalType\":\"structMultiOCR3Base.OCRConfig\",\"name\":\"ocrConfig\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"}],\"internalType\":\"structInternal.RampMessageHeader\",\"name\":\"header\",\"type\":\"tuple\"},{\"internalType\":\"bytes\",\"name\":\"sender\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"destTokenAddress\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"destGasAmount\",\"type\":\"uint32\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structInternal.Any2EVMTokenTransfer[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.Any2EVMRampMessage[]\",\"name\":\"messages\",\"type\":\"tuple[]\"},{\"internalType\":\"bytes[][]\",\"name\":\"offchainTokenData\",\"type\":\"bytes[][]\"},{\"internalType\":\"bytes32[]\",\"name\":\"proofs\",\"type\":\"bytes32[]\"},{\"internalType\":\"uint256\",\"name\":\"proofFlagBits\",\"type\":\"uint256\"}],\"internalType\":\"structInternal.ExecutionReport[]\",\"name\":\"reports\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"receiverExecutionGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint32[]\",\"name\":\"tokenGasOverrides\",\"type\":\"uint32[]\"}],\"internalType\":\"structOffRamp.GasLimitOverride[][]\",\"name\":\"gasLimitOverrides\",\"type\":\"tuple[][]\"}],\"name\":\"manuallyExecute\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"permissionLessExecutionThresholdSeconds\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isRMNVerificationDisabled\",\"type\":\"bool\"},{\"internalType\":\"address\",\"name\":\"messageInterceptor\",\"type\":\"address\"}],\"internalType\":\"structOffRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"}],\"name\":\"setDynamicConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"F\",\"type\":\"uint8\"},{\"internalType\":\"bool\",\"name\":\"isSignatureVerificationEnabled\",\"type\":\"bool\"},{\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"}],\"internalType\":\"structMultiOCR3Base.OCRConfigArgs[]\",\"name\":\"ocrConfigArgs\",\"type\":\"tuple[]\"}],\"name\":\"setOCR3Configs\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", + Bin: "0x6101206040523480156200001257600080fd5b5060405162006bc738038062006bc7833981016040819052620000359162000880565b336000816200005757604051639b15e16f60e01b815260040160405180910390fd5b600180546001600160a01b0319166001600160a01b03848116919091179091558116156200008a576200008a81620001c4565b50504660805260208301516001600160a01b03161580620000b6575060408301516001600160a01b0316155b80620000cd575060608301516001600160a01b0316155b15620000ec576040516342bcdf7f60e11b815260040160405180910390fd5b82516001600160401b0316600003620001185760405163c656089560e01b815260040160405180910390fd5b82516001600160401b0390811660a052602080850180516001600160a01b0390811660c05260408088018051831660e0526060808a01805185166101005283518b519098168852945184169587019590955251821690850152905116908201527f683eb52ee924eb817377cfa8f41f238f4bb7a877da5267869dfffbad85f564d89060800160405180910390a1620001b0826200023e565b620001bb816200032c565b50505062000c72565b336001600160a01b03821603620001ee57604051636d6c4ee560e11b815260040160405180910390fd5b600080546001600160a01b0319166001600160a01b03838116918217835560015460405192939116917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b80516001600160a01b031662000267576040516342bcdf7f60e11b815260040160405180910390fd5b80516004805460208085018051604080880180516001600160a01b039889166001600160c01b03199097168717600160a01b63ffffffff958616021760ff60c01b1916600160c01b911515919091021790965560608089018051600580546001600160a01b031916918b169190911790558251968752935190921693850193909352935115159183019190915251909216908201527fcbb53bda7106a610de67df506ac86b65c44d5afac0fd2b11070dc2d61a6f2dee9060800160405180910390a150565b60005b8151811015620005c1576000828281518110620003505762000350620009aa565b60200260200101519050600081602001519050806001600160401b03166000036200038e5760405163c656089560e01b815260040160405180910390fd5b81516001600160a01b0316620003b7576040516342bcdf7f60e11b815260040160405180910390fd5b6001600160401b03811660009081526008602052604090206060830151600182018054620003e590620009c0565b905060000362000448578154600160a81b600160e81b031916600160a81b1782556040516001600160401b03841681527ff4c1390c70e5c0f491ae1ccbc06f9117cbbadf2767b247b3bc203280f24c0fb99060200160405180910390a1620004b9565b8154600160a81b90046001600160401b03166001148015906200048b57508051602082012060405162000480906001850190620009fc565b604051809103902014155b15620004b957604051632105803760e11b81526001600160401b038416600482015260240160405180910390fd5b80511580620004ef5750604080516000602082015201604051602081830303815290604052805190602001208180519060200120145b156200050e576040516342bcdf7f60e11b815260040160405180910390fd5b600182016200051e828262000acf565b506040840151825485516001600160a01b03166001600160a01b0319921515600160a01b02929092166001600160a81b0319909116171782556200056d60066001600160401b038516620005c5565b50826001600160401b03167f49f51971edd25182e97182d6ea372a0488ce2ab639f6a3a7ab4df0d2636fe56b83604051620005a9919062000b9b565b60405180910390a2505050508060010190506200032f565b5050565b6000620005d38383620005dc565b90505b92915050565b60008181526001830160205260408120546200062557508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155620005d6565b506000620005d6565b634e487b7160e01b600052604160045260246000fd5b604051608081016001600160401b03811182821017156200066957620006696200062e565b60405290565b604051601f8201601f191681016001600160401b03811182821017156200069a576200069a6200062e565b604052919050565b80516001600160401b0381168114620006ba57600080fd5b919050565b6001600160a01b0381168114620006d557600080fd5b50565b80518015158114620006ba57600080fd5b6000601f83601f840112620006fd57600080fd5b825160206001600160401b03808311156200071c576200071c6200062e565b8260051b6200072d8382016200066f565b93845286810183019383810190898611156200074857600080fd5b84890192505b858310156200087357825184811115620007685760008081fd5b89016080601f19828d038101821315620007825760008081fd5b6200078c62000644565b888401516200079b81620006bf565b81526040620007ac858201620006a2565b8a8301526060620007bf818701620006d8565b83830152938501519389851115620007d75760008081fd5b84860195508f603f870112620007ef57600094508485fd5b8a8601519450898511156200080857620008086200062e565b620008198b858f880116016200066f565b93508484528f82868801011115620008315760008081fd5b60005b8581101562000851578681018301518582018d01528b0162000834565b5060009484018b0194909452509182015283525091840191908401906200074e565b9998505050505050505050565b60008060008385036101208112156200089857600080fd5b6080811215620008a757600080fd5b620008b162000644565b620008bc86620006a2565b81526020860151620008ce81620006bf565b60208201526040860151620008e381620006bf565b60408201526060860151620008f881620006bf565b606082015293506080607f19820112156200091257600080fd5b506200091d62000644565b60808501516200092d81620006bf565b815260a085015163ffffffff811681146200094757600080fd5b60208201526200095a60c08601620006d8565b604082015260e08501516200096f81620006bf565b60608201526101008501519092506001600160401b038111156200099257600080fd5b620009a086828701620006e9565b9150509250925092565b634e487b7160e01b600052603260045260246000fd5b600181811c90821680620009d557607f821691505b602082108103620009f657634e487b7160e01b600052602260045260246000fd5b50919050565b600080835462000a0c81620009c0565b6001828116801562000a27576001811462000a3d5762000a6e565b60ff198416875282151583028701945062000a6e565b8760005260208060002060005b8581101562000a655781548a82015290840190820162000a4a565b50505082870194505b50929695505050505050565b601f82111562000aca576000816000526020600020601f850160051c8101602086101562000aa55750805b601f850160051c820191505b8181101562000ac65782815560010162000ab1565b5050505b505050565b81516001600160401b0381111562000aeb5762000aeb6200062e565b62000b038162000afc8454620009c0565b8462000a7a565b602080601f83116001811462000b3b576000841562000b225750858301515b600019600386901b1c1916600185901b17855562000ac6565b600085815260208120601f198616915b8281101562000b6c5788860151825594840194600190910190840162000b4b565b508582101562000b8b5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b602080825282546001600160a01b0381168383015260a081901c60ff161515604084015260a81c6001600160401b0316606083015260808083015260018084018054600093929190849062000bf081620009c0565b8060a089015260c0600183166000811462000c14576001811462000c315762000c63565b60ff19841660c08b015260c083151560051b8b0101945062000c63565b85600052602060002060005b8481101562000c5a5781548c820185015290880190890162000c3d565b8b0160c0019550505b50929998505050505050505050565b60805160a05160c05160e05161010051615ed862000cef600039600081816102070152612be30152600081816101d80152612eab0152600081816101a9015281816105820152818161073201526125e301526000818161017a0152818161278e0152612845015260008181611d120152611d450152615ed86000f3fe608060405234801561001057600080fd5b506004361061012c5760003560e01c80637437ff9f116100ad578063c673e58411610071578063c673e58414610474578063ccd37ba314610494578063e9d68a8e146104d8578063f2fde38b146104f8578063f716f99f1461050b57600080fd5b80637437ff9f1461037357806379ba5097146104305780637edf52f41461043857806385572ffb1461044b5780638da5cb5b1461045957600080fd5b80633f4b04aa116100f45780633f4b04aa146102fc5780635215505b146103175780635e36480c1461032d5780635e7bb0081461034d57806360987c201461036057600080fd5b806304666f9c1461013157806306285c6914610146578063181f5a771461028d5780632d04ab76146102d6578063311cd513146102e9575b600080fd5b61014461013f366004613e1e565b61051e565b005b61023760408051608081018252600080825260208201819052918101829052606081019190915260405180608001604052807f00000000000000000000000000000000000000000000000000000000000000006001600160401b031681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316815250905090565b604051610284919081516001600160401b031681526020808301516001600160a01b0390811691830191909152604080840151821690830152606092830151169181019190915260800190565b60405180910390f35b6102c96040518060400160405280601181526020017f4f666652616d7020312e362e302d64657600000000000000000000000000000081525081565b6040516102849190613f8c565b6101446102e436600461403c565b610532565b6101446102f73660046140ee565b610a46565b600b546040516001600160401b039091168152602001610284565b61031f610aaf565b604051610284929190614188565b61034061033b366004614229565b610d0a565b6040516102849190614286565b61014461035b3660046147ef565b610d5f565b61014461036e366004614a33565b610fee565b6103e960408051608081018252600080825260208201819052918101829052606081019190915250604080516080810182526004546001600160a01b038082168352600160a01b820463ffffffff166020840152600160c01b90910460ff16151592820192909252600554909116606082015290565b604051610284919081516001600160a01b03908116825260208084015163ffffffff1690830152604080840151151590830152606092830151169181019190915260800190565b6101446112a5565b610144610446366004614ac7565b611328565b61014461012c366004614b2c565b6001546040516001600160a01b039091168152602001610284565b610487610482366004614b77565b611339565b6040516102849190614bd7565b6104ca6104a2366004614c4c565b6001600160401b03919091166000908152600a60209081526040808320938352929052205490565b604051908152602001610284565b6104eb6104e6366004614c76565b611497565b6040516102849190614c91565b610144610506366004614ca4565b6115a3565b610144610519366004614d29565b6115b4565b6105266115f6565b61052f81611623565b50565b60006105408789018961507e565b6004805491925090600160c01b900460ff166105ea57602082015151156105ea5760208201516040808401519051633854844f60e11b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016926370a9089e926105b992309291906004016152a6565b60006040518083038186803b1580156105d157600080fd5b505afa1580156105e5573d6000803e3d6000fd5b505050505b8151515115158061060057508151602001515115155b156106cb57600b5460208b0135906001600160401b03808316911610156106a357600b805467ffffffffffffffff19166001600160401b03831617905581548351604051633937306f60e01b81526001600160a01b0390921691633937306f9161066c916004016153db565b600060405180830381600087803b15801561068657600080fd5b505af115801561069a573d6000803e3d6000fd5b505050506106c9565b8260200151516000036106c957604051632261116760e01b815260040160405180910390fd5b505b60005b826020015151811015610986576000836020015182815181106106f3576106f3615309565b60209081029190910101518051604051632cbc26bb60e01b815267ffffffffffffffff60801b608083901b166004820152919250906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690632cbc26bb90602401602060405180830381865afa158015610779573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061079d91906153ee565b156107cb57604051637edeb53960e11b81526001600160401b03821660048201526024015b60405180910390fd5b60006107d6826118ac565b9050806001016040516107e99190615445565b6040518091039020836020015180519060200120146108265782602001518160010160405163b80d8fa960e01b81526004016107c2929190615538565b60408301518154600160a81b90046001600160401b039081169116141580610867575082606001516001600160401b031683604001516001600160401b0316115b156108ac57825160408085015160608601519151636af0786b60e11b81526001600160401b0393841660048201529083166024820152911660448201526064016107c2565b6080830151806108cf5760405163504570e360e01b815260040160405180910390fd5b83516001600160401b03166000908152600a60209081526040808320848452909152902054156109275783516040516332cf0cbf60e01b81526001600160401b039091166004820152602481018290526044016107c2565b6060840151610937906001615573565b825467ffffffffffffffff60a81b1916600160a81b6001600160401b0392831602179092559251166000908152600a6020908152604080832094835293905291909120429055506001016106ce565b50602082015182516040517f35c02761bcd3ef995c6a601a1981f4ed3934dcbe5041e24e286c89f5531d17e4926109be92909161559a565b60405180910390a1610a3a60008b8b8b8b8b8080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050604080516020808f0282810182019093528e82529093508e92508d9182918501908490808284376000920191909152508c92506118f8915050565b50505050505050505050565b610a86610a55828401846155bf565b6040805160008082526020820190925290610a80565b6060815260200190600190039081610a6b5790505b50611bf1565b604080516000808252602082019092529050610aa96001858585858660006118f8565b50505050565b6060806000610abe6006611cb4565b6001600160401b03811115610ad557610ad5613c3e565b604051908082528060200260200182016040528015610b2657816020015b6040805160808101825260008082526020808301829052928201526060808201528252600019909201910181610af35790505b5090506000610b356006611cb4565b6001600160401b03811115610b4c57610b4c613c3e565b604051908082528060200260200182016040528015610b75578160200160208202803683370190505b50905060005b610b856006611cb4565b811015610d0157610b97600682611cbe565b828281518110610ba957610ba9615309565b60200260200101906001600160401b031690816001600160401b03168152505060086000838381518110610bdf57610bdf615309565b6020908102919091018101516001600160401b039081168352828201939093526040918201600020825160808101845281546001600160a01b038116825260ff600160a01b820416151593820193909352600160a81b90920490931691810191909152600182018054919291606084019190610c5a9061540b565b80601f0160208091040260200160405190810160405280929190818152602001828054610c869061540b565b8015610cd35780601f10610ca857610100808354040283529160200191610cd3565b820191906000526020600020905b815481529060010190602001808311610cb657829003601f168201915b505050505081525050838281518110610cee57610cee615309565b6020908102919091010152600101610b7b565b50939092509050565b6000610d18600160046155f3565b6002610d2560808561561c565b6001600160401b0316610d389190615642565b610d428585611cca565b901c166003811115610d5657610d5661425c565b90505b92915050565b610d67611d0f565b815181518114610d8a576040516320f8fd5960e21b815260040160405180910390fd5b60005b81811015610fde576000848281518110610da957610da9615309565b60200260200101519050600081602001515190506000858481518110610dd157610dd1615309565b6020026020010151905080518214610dfc576040516320f8fd5960e21b815260040160405180910390fd5b60005b82811015610fcf576000828281518110610e1b57610e1b615309565b6020026020010151600001519050600085602001518381518110610e4157610e41615309565b6020026020010151905081600014610e95578060800151821015610e95578551815151604051633a98d46360e11b81526001600160401b0390921660048301526024820152604481018390526064016107c2565b838381518110610ea757610ea7615309565b602002602001015160200151518160a001515114610ef457805180516060909101516040516370a193fd60e01b815260048101929092526001600160401b031660248201526044016107c2565b60005b8160a0015151811015610fc1576000858581518110610f1857610f18615309565b6020026020010151602001518281518110610f3557610f35615309565b602002602001015163ffffffff16905080600014610fb85760008360a001518381518110610f6557610f65615309565b60200260200101516040015163ffffffff16905080821015610fb6578351516040516348e617b360e01b815260048101919091526024810184905260448101829052606481018390526084016107c2565b505b50600101610ef7565b505050806001019050610dff565b50505050806001019050610d8d565b50610fe98383611bf1565b505050565b33301461100e576040516306e34e6560e31b815260040160405180910390fd5b604080516000808252602082019092528161104b565b60408051808201909152600080825260208201528152602001906001900390816110245790505b5060a087015151909150156110815761107e8660a001518760200151886060015189600001516020015189898989611d77565b90505b6040805160a081018252875151815287516020908101516001600160401b03168183015288015181830152908701516060820152608081018290526005546001600160a01b03168015611174576040516308d450a160e01b81526001600160a01b038216906308d450a1906110fa9085906004016156fa565b600060405180830381600087803b15801561111457600080fd5b505af1925050508015611125575060015b611174573d808015611153576040519150601f19603f3d011682016040523d82523d6000602084013e611158565b606091505b50806040516309c2532560e01b81526004016107c29190613f8c565b60408801515115801561118957506080880151155b806111a0575060608801516001600160a01b03163b155b806111c7575060608801516111c5906001600160a01b03166385572ffb60e01b611f28565b155b156111d45750505061129e565b87516020908101516001600160401b03166000908152600890915260408082205460808b015160608c01519251633cf9798360e01b815284936001600160a01b0390931692633cf9798392611232928992611388929160040161570d565b6000604051808303816000875af1158015611251573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526112799190810190615749565b509150915081610a3a57806040516302a35ba360e21b81526004016107c29190613f8c565b5050505050565b6000546001600160a01b031633146112d05760405163015aa1e360e11b815260040160405180910390fd5b600180546001600160a01b0319808216339081179093556000805490911681556040516001600160a01b03909216929183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b6113306115f6565b61052f81611f44565b61137c6040805160e081019091526000606082018181526080830182905260a0830182905260c08301919091528190815260200160608152602001606081525090565b60ff808316600090815260026020818152604092839020835160e081018552815460608201908152600183015480881660808401526101008104881660a0840152620100009004909616151560c08201529485529182018054845181840281018401909552808552929385830193909283018282801561142557602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311611407575b505050505081526020016003820180548060200260200160405190810160405280929190818152602001828054801561148757602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311611469575b5050505050815250509050919050565b60408051608080820183526000808352602080840182905283850182905260608085018190526001600160401b03878116845260088352928690208651948501875280546001600160a01b0381168652600160a01b810460ff16151593860193909352600160a81b9092049092169483019490945260018401805493949293918401916115239061540b565b80601f016020809104026020016040519081016040528092919081815260200182805461154f9061540b565b80156114875780601f1061157157610100808354040283529160200191611487565b820191906000526020600020905b81548152906001019060200180831161157f57505050919092525091949350505050565b6115ab6115f6565b61052f81612049565b6115bc6115f6565b60005b81518110156115f2576115ea8282815181106115dd576115dd615309565b60200260200101516120c2565b6001016115bf565b5050565b6001546001600160a01b03163314611621576040516315ae3a6f60e11b815260040160405180910390fd5b565b60005b81518110156115f257600082828151811061164357611643615309565b60200260200101519050600081602001519050806001600160401b03166000036116805760405163c656089560e01b815260040160405180910390fd5b81516001600160a01b03166116a8576040516342bcdf7f60e11b815260040160405180910390fd5b6001600160401b038116600090815260086020526040902060608301516001820180546116d49061540b565b905060000361173657815467ffffffffffffffff60a81b1916600160a81b1782556040516001600160401b03841681527ff4c1390c70e5c0f491ae1ccbc06f9117cbbadf2767b247b3bc203280f24c0fb99060200160405180910390a161179f565b8154600160a81b90046001600160401b031660011480159061177657508051602082012060405161176b906001850190615445565b604051809103902014155b1561179f57604051632105803760e11b81526001600160401b03841660048201526024016107c2565b805115806117d45750604080516000602082015201604051602081830303815290604052805190602001208180519060200120145b156117f2576040516342bcdf7f60e11b815260040160405180910390fd5b60018201611800828261582e565b506040840151825485516001600160a01b03166001600160a01b0319921515600160a01b029290921674ffffffffffffffffffffffffffffffffffffffffff199091161717825561185b60066001600160401b0385166123ec565b50826001600160401b03167f49f51971edd25182e97182d6ea372a0488ce2ab639f6a3a7ab4df0d2636fe56b8360405161189591906158ed565b60405180910390a250505050806001019050611626565b6001600160401b03811660009081526008602052604081208054600160a01b900460ff16610d595760405163ed053c5960e01b81526001600160401b03841660048201526024016107c2565b60ff878116600090815260026020908152604080832081516080810183528154815260019091015480861693820193909352610100830485169181019190915262010000909104909216151560608301528735906119578760a461593b565b905082606001511561199f578451611970906020615642565b865161197d906020615642565b6119889060a061593b565b611992919061593b565b61199c908261593b565b90505b3681146119c857604051638e1192e160e01b8152600481018290523660248201526044016107c2565b50815181146119f75781516040516324f7d61360e21b81526004810191909152602481018290526044016107c2565b6119ff611d0f565b60ff808a1660009081526003602090815260408083203384528252808320815180830190925280548086168352939491939092840191610100909104166002811115611a4d57611a4d61425c565b6002811115611a5e57611a5e61425c565b9052509050600281602001516002811115611a7b57611a7b61425c565b148015611acf5750600260008b60ff1660ff168152602001908152602001600020600301816000015160ff1681548110611ab757611ab7615309565b6000918252602090912001546001600160a01b031633145b611aec57604051631b41e11d60e31b815260040160405180910390fd5b50816060015115611b9c576020820151611b0790600161594e565b60ff16855114611b2a576040516371253a2560e01b815260040160405180910390fd5b8351855114611b4c5760405163a75d88af60e01b815260040160405180910390fd5b60008787604051611b5e929190615967565b604051908190038120611b75918b90602001615977565b604051602081830303815290604052805190602001209050611b9a8a828888886123f8565b505b6040805182815260208a8101356001600160401b03169082015260ff8b16917f198d6990ef96613a9026203077e422916918b03ff47f0be6bee7b02d8e139ef0910160405180910390a2505050505050505050565b8151600003611c135760405163c2e5347d60e01b815260040160405180910390fd5b80516040805160008082526020820190925291159181611c56565b604080518082019091526000815260606020820152815260200190600190039081611c2e5790505b50905060005b845181101561129e57611cac858281518110611c7a57611c7a615309565b602002602001015184611ca657858381518110611c9957611c99615309565b60200260200101516125b5565b836125b5565b600101611c5c565b6000610d59825490565b6000610d568383612e46565b6001600160401b038216600090815260096020526040812081611cee60808561598b565b6001600160401b031681526020810191909152604001600020549392505050565b467f00000000000000000000000000000000000000000000000000000000000000001461162157604051630f01ce8560e01b81527f000000000000000000000000000000000000000000000000000000000000000060048201524660248201526044016107c2565b606088516001600160401b03811115611d9257611d92613c3e565b604051908082528060200260200182016040528015611dd757816020015b6040805180820190915260008082526020820152815260200190600190039081611db05790505b509050811560005b8a51811015611f1a5781611e7757848482818110611dff57611dff615309565b9050602002016020810190611e1491906159b1565b63ffffffff1615611e7757848482818110611e3157611e31615309565b9050602002016020810190611e4691906159b1565b8b8281518110611e5857611e58615309565b60200260200101516040019063ffffffff16908163ffffffff16815250505b611ef58b8281518110611e8c57611e8c615309565b60200260200101518b8b8b8b8b87818110611ea957611ea9615309565b9050602002810190611ebb91906159cc565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250612e7092505050565b838281518110611f0757611f07615309565b6020908102919091010152600101611ddf565b505098975050505050505050565b6000611f3383613150565b8015610d565750610d568383613183565b80516001600160a01b0316611f6c576040516342bcdf7f60e11b815260040160405180910390fd5b80516004805460208085018051604080880180516001600160a01b039889167fffffffffffffffff0000000000000000000000000000000000000000000000009097168717600160a01b63ffffffff958616021760ff60c01b1916600160c01b911515919091021790965560608089018051600580546001600160a01b031916918b169190911790558251968752935190921693850193909352935115159183019190915251909216908201527fcbb53bda7106a610de67df506ac86b65c44d5afac0fd2b11070dc2d61a6f2dee9060800160405180910390a150565b336001600160a01b0382160361207257604051636d6c4ee560e11b815260040160405180910390fd5b600080546001600160a01b0319166001600160a01b03838116918217835560015460405192939116917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b806040015160ff166000036120ed576000604051631b3fab5160e11b81526004016107c29190615a12565b60208082015160ff8082166000908152600290935260408320600181015492939092839216900361213e576060840151600182018054911515620100000262ff00001990921691909117905561217a565b6060840151600182015460ff620100009091041615159015151461217a576040516321fd80df60e21b815260ff841660048201526024016107c2565b60a0840151805161010010156121a6576001604051631b3fab5160e11b81526004016107c29190615a12565b80516000036121cb576005604051631b3fab5160e11b81526004016107c29190615a12565b612231848460030180548060200260200160405190810160405280929190818152602001828054801561222757602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311612209575b505050505061320d565b8460600151156123615761229f8484600201805480602002602001604051908101604052809291908181526020018280548015612227576020028201919060005260206000209081546001600160a01b0316815260019091019060200180831161220957505050505061320d565b6080850151805161010010156122cb576002604051631b3fab5160e11b81526004016107c29190615a12565b60408601516122db906003615a2c565b60ff16815111612301576003604051631b3fab5160e11b81526004016107c29190615a12565b815181511015612327576001604051631b3fab5160e11b81526004016107c29190615a12565b805160018401805461ff00191661010060ff8416021790556123529060028601906020840190613bc4565b5061235f85826001613276565b505b61236d84826002613276565b80516123829060038501906020840190613bc4565b5060408581015160018401805460ff191660ff8316179055865180855560a088015192517fab8b1b57514019638d7b5ce9c638fe71366fe8e2be1c40a7a80f1733d0e9f547936123db9389939260028a01929190615a48565b60405180910390a161129e846133d1565b6000610d568383613454565b8251600090815b818110156125ab57600060018886846020811061241e5761241e615309565b61242b91901a601b61594e565b89858151811061243d5761243d615309565b602002602001015189868151811061245757612457615309565b602002602001015160405160008152602001604052604051612495949392919093845260ff9290921660208401526040830152606082015260800190565b6020604051602081039080840390855afa1580156124b7573d6000803e3d6000fd5b505060408051601f1981015160ff808e166000908152600360209081528582206001600160a01b038516835281528582208587019096528554808416865293975090955092939284019161010090041660028111156125185761251861425c565b60028111156125295761252961425c565b90525090506001816020015160028111156125465761254661425c565b1461256457604051636518c33d60e11b815260040160405180910390fd5b8051600160ff9091161b85161561258e57604051633d9ef1f160e21b815260040160405180910390fd5b806000015160ff166001901b8517945050508060010190506123ff565b5050505050505050565b81518151604051632cbc26bb60e01b8152608083901b67ffffffffffffffff60801b166004820152901515907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690632cbc26bb90602401602060405180830381865afa158015612632573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061265691906153ee565b156126c757801561268557604051637edeb53960e11b81526001600160401b03831660048201526024016107c2565b6040516001600160401b03831681527faab522ed53d887e56ed53dd37398a01aeef6a58e0fa77c2173beb9512d8949339060200160405180910390a150505050565b60208401515160008190036126fd57845160405163676cf24b60e11b81526001600160401b0390911660048201526024016107c2565b8460400151518114612722576040516357e0e08360e01b815260040160405180910390fd5b6000816001600160401b0381111561273c5761273c613c3e565b604051908082528060200260200182016040528015612765578160200160208202803683370190505b50905060007f2425b0b9f9054c76ff151b0a175b18f37a4a4e82013a72e9f15c9caa095ed21f857f00000000000000000000000000000000000000000000000000000000000000006127b6886118ac565b6001016040516127c69190615445565b6040519081900381206127fe949392916020019384526001600160401b03928316602085015291166040830152606082015260800190565b60405160208183030381529060405280519060200120905060005b838110156129345760008860200151828151811061283957612839615309565b602002602001015190507f00000000000000000000000000000000000000000000000000000000000000006001600160401b03168160000151604001516001600160401b0316146128b05780516040908101519051631c21951160e11b81526001600160401b0390911660048201526024016107c2565b866001600160401b03168160000151602001516001600160401b03161461290457805160200151604051636c95f1eb60e01b81526001600160401b03808a16600483015290911660248201526044016107c2565b61290e81846134a3565b84838151811061292057612920615309565b602090810291909101015250600101612819565b5050600061294c858389606001518a608001516135ab565b90508060000361297a57604051633ee8bd3f60e11b81526001600160401b03861660048201526024016107c2565b60005b838110156125ab5760005a90506000896020015183815181106129a2576129a2615309565b6020026020010151905060006129c089836000015160600151610d0a565b905060008160038111156129d6576129d661425c565b14806129f3575060038160038111156129f1576129f161425c565b145b612a4957815160600151604080516001600160401b03808d16825290921660208301527f3b575419319662b2a6f5e2467d84521517a3382b908eb3d557bb3fdb0c50e23c910160405180910390a1505050612e3e565b60608815612b28578a8581518110612a6357612a63615309565b6020908102919091018101510151600454909150600090600160a01b900463ffffffff16612a9188426155f3565b1190508080612ab157506003836003811115612aaf57612aaf61425c565b145b612ad9576040516354e7e43160e11b81526001600160401b038c1660048201526024016107c2565b8b8681518110612aeb57612aeb615309565b602002602001015160000151600014612b22578b8681518110612b1057612b10615309565b60209081029190910101515160808501525b50612b94565b6000826003811115612b3c57612b3c61425c565b14612b9457825160600151604080516001600160401b03808e16825290921660208301527f3ef2a99c550a751d4b0b261268f05a803dfb049ab43616a1ffb388f61fe65120910160405180910390a150505050612e3e565b8251608001516001600160401b031615612c6a576000826003811115612bbc57612bbc61425c565b03612c6a5782516080015160208401516040516370701e5760e11b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169263e0e03cae92612c1a928f929190600401615afa565b6020604051808303816000875af1158015612c39573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c5d91906153ee565b612c6a5750505050612e3e565b60008c604001518681518110612c8257612c82615309565b6020026020010151905080518460a001515114612ccc57835160600151604051631cfe6d8b60e01b81526001600160401b03808e16600483015290911660248201526044016107c2565b612ce08b85600001516060015160016135e8565b600080612cee86848661368d565b91509150612d058d876000015160600151846135e8565b8b15612d5c576003826003811115612d1f57612d1f61425c565b03612d5c576000856003811115612d3857612d3861425c565b14612d5c57855151604051632b11b8d960e01b81526107c291908390600401615b26565b6002826003811115612d7057612d7061425c565b14612db1576003826003811115612d8957612d8961425c565b14612db1578551606001516040516349362d1f60e11b81526107c2918f918590600401615b3f565b8560000151600001518660000151606001516001600160401b03168e6001600160401b03167f05665fe9ad095383d018353f4cbcba77e84db27dd215081bbf7cdf9ae6fbe48b8d8c81518110612e0957612e09615309565b602002602001015186865a612e1e908f6155f3565b604051612e2e9493929190615b64565b60405180910390a4505050505050505b60010161297d565b6000826000018281548110612e5d57612e5d615309565b9060005260206000200154905092915050565b6040805180820190915260008082526020820152602086015160405163bbe4f6db60e01b81526001600160a01b0380831660048301526000917f00000000000000000000000000000000000000000000000000000000000000009091169063bbe4f6db90602401602060405180830381865afa158015612ef4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f189190615b9b565b90506001600160a01b0381161580612f475750612f456001600160a01b03821663aff2afbf60e01b611f28565b155b15612f705760405163ae9b4ce960e01b81526001600160a01b03821660048201526024016107c2565b600080612f8888858c6040015163ffffffff16613741565b91509150600080600061303b6040518061010001604052808e81526020018c6001600160401b031681526020018d6001600160a01b031681526020018f608001518152602001896001600160a01b031681526020018f6000015181526020018f6060015181526020018b8152506040516024016130059190615bb8565b60408051601f198184030181529190526020810180516001600160e01b0316633907753760e01b17905287866113886084613824565b92509250925082613061578160405163e1cd550960e01b81526004016107c29190613f8c565b8151602014613090578151604051631e3be00960e21b81526020600482015260248101919091526044016107c2565b6000828060200190518101906130a69190615c84565b9050866001600160a01b03168c6001600160a01b0316146131225760006130d78d8a6130d2868a6155f3565b613741565b509050868110806130f15750816130ee88836155f3565b14155b156131205760405163a966e21f60e01b81526004810183905260248101889052604481018290526064016107c2565b505b604080518082019091526001600160a01b039098168852602088015250949550505050505095945050505050565b6000613163826301ffc9a760e01b613183565b8015610d59575061317c826001600160e01b0319613183565b1592915050565b6040516001600160e01b031982166024820152600090819060440160408051601f19818403018152919052602080820180516001600160e01b03166301ffc9a760e01b178152825192935060009283928392909183918a617530fa92503d915060005190508280156131f6575060208210155b80156132025750600081115b979650505050505050565b60005b8151811015610fe95760ff83166000908152600360205260408120835190919084908490811061324257613242615309565b6020908102919091018101516001600160a01b03168252810191909152604001600020805461ffff19169055600101613210565b60005b8251811015610aa957600083828151811061329657613296615309565b60200260200101519050600060028111156132b3576132b361425c565b60ff80871660009081526003602090815260408083206001600160a01b038716845290915290205461010090041660028111156132f2576132f261425c565b14613313576004604051631b3fab5160e11b81526004016107c29190615a12565b6001600160a01b03811661333a5760405163d6c62c9b60e01b815260040160405180910390fd5b60405180604001604052808360ff1681526020018460028111156133605761336061425c565b905260ff80871660009081526003602090815260408083206001600160a01b0387168452825290912083518154931660ff198416811782559184015190929091839161ffff1916176101008360028111156133bd576133bd61425c565b021790555090505050806001019050613279565b60ff818116600081815260026020526040902060010154620100009004909116906134295780613414576040516317bd8dd160e11b815260040160405180910390fd5b600b805467ffffffffffffffff191690555050565b60001960ff8316016115f25780156115f2576040516307b8c74d60e51b815260040160405180910390fd5b600081815260018301602052604081205461349b57508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155610d59565b506000610d59565b81518051606080850151908301516080808701519401516040516000958695889561350795919490939192916020019485526001600160a01b039390931660208501526001600160401b039182166040850152606084015216608082015260a00190565b604051602081830303815290604052805190602001208560200151805190602001208660400151805190602001208760a0015160405160200161354a9190615d3e565b60408051601f198184030181528282528051602091820120908301979097528101949094526060840192909252608083015260a082015260c081019190915260e0015b60405160208183030381529060405280519060200120905092915050565b6000806135b98585856138fe565b6001600160401b0387166000908152600a6020908152604080832093835292905220549150505b949350505050565b600060026135f760808561561c565b6001600160401b031661360a9190615642565b905060006136188585611cca565b905081613627600160046155f3565b901b19168183600381111561363e5761363e61425c565b6001600160401b03871660009081526009602052604081209190921b9290921791829161366c60808861598b565b6001600160401b031681526020810191909152604001600020555050505050565b604051630304c3e160e51b815260009060609030906360987c20906136ba90889088908890600401615dd5565b600060405180830381600087803b1580156136d457600080fd5b505af19250505080156136e5575060015b613724573d808015613713576040519150601f19603f3d011682016040523d82523d6000602084013e613718565b606091505b50600392509050613739565b50506040805160208101909152600081526002905b935093915050565b60008060008060006137a28860405160240161376c91906001600160a01b0391909116815260200190565b60408051601f198184030181529190526020810180516001600160e01b03166370a0823160e01b17905288886113886084613824565b925092509250826137c8578160405163e1cd550960e01b81526004016107c29190613f8c565b60208251146137f7578151604051631e3be00960e21b81526020600482015260248101919091526044016107c2565b8180602001905181019061380b9190615c84565b61381582886155f3565b94509450505050935093915050565b6000606060008361ffff166001600160401b0381111561384657613846613c3e565b6040519080825280601f01601f191660200182016040528015613870576020820181803683370190505b509150863b61388a5763030ed58f60e21b60005260046000fd5b5a858110156138a457632be8ca8b60e21b60005260046000fd5b85900360408104810387106138c4576337c3be2960e01b60005260046000fd5b505a6000808a5160208c0160008c8cf193505a900390503d848111156138e75750835b808352806000602085013e50955095509592505050565b825182516000919081830361392657604051630469ac9960e21b815260040160405180910390fd5b610101821180159061393a57506101018111155b613957576040516309bde33960e01b815260040160405180910390fd5b60001982820101610100811115613981576040516309bde33960e01b815260040160405180910390fd5b806000036139ae578660008151811061399c5761399c615309565b60200260200101519350505050613b7c565b6000816001600160401b038111156139c8576139c8613c3e565b6040519080825280602002602001820160405280156139f1578160200160208202803683370190505b50905060008080805b85811015613b1b5760006001821b8b811603613a555788851015613a3e578c5160018601958e918110613a2f57613a2f615309565b60200260200101519050613a77565b8551600185019487918110613a2f57613a2f615309565b8b5160018401938d918110613a6c57613a6c615309565b602002602001015190505b600089861015613aa7578d5160018701968f918110613a9857613a98615309565b60200260200101519050613ac9565b8651600186019588918110613abe57613abe615309565b602002602001015190505b82851115613aea576040516309bde33960e01b815260040160405180910390fd5b613af48282613b83565b878481518110613b0657613b06615309565b602090810291909101015250506001016139fa565b506001850382148015613b2d57508683145b8015613b3857508581145b613b55576040516309bde33960e01b815260040160405180910390fd5b836001860381518110613b6a57613b6a615309565b60200260200101519750505050505050505b9392505050565b6000818310613b9b57613b968284613ba1565b610d56565b610d5683835b60408051600160208201529081018390526060810182905260009060800161358d565b828054828255906000526020600020908101928215613c19579160200282015b82811115613c1957825182546001600160a01b0319166001600160a01b03909116178255602090920191600190910190613be4565b50613c25929150613c29565b5090565b5b80821115613c255760008155600101613c2a565b634e487b7160e01b600052604160045260246000fd5b604051608081016001600160401b0381118282101715613c7657613c76613c3e565b60405290565b60405160a081016001600160401b0381118282101715613c7657613c76613c3e565b60405160c081016001600160401b0381118282101715613c7657613c76613c3e565b604080519081016001600160401b0381118282101715613c7657613c76613c3e565b604051606081016001600160401b0381118282101715613c7657613c76613c3e565b604051601f8201601f191681016001600160401b0381118282101715613d2c57613d2c613c3e565b604052919050565b60006001600160401b03821115613d4d57613d4d613c3e565b5060051b60200190565b6001600160a01b038116811461052f57600080fd5b80356001600160401b0381168114613d8357600080fd5b919050565b801515811461052f57600080fd5b8035613d8381613d88565b60006001600160401b03821115613dba57613dba613c3e565b50601f01601f191660200190565b600082601f830112613dd957600080fd5b8135613dec613de782613da1565b613d04565b818152846020838601011115613e0157600080fd5b816020850160208301376000918101602001919091529392505050565b60006020808385031215613e3157600080fd5b82356001600160401b0380821115613e4857600080fd5b818501915085601f830112613e5c57600080fd5b8135613e6a613de782613d34565b81815260059190911b83018401908481019088831115613e8957600080fd5b8585015b83811015613f2f57803585811115613ea55760008081fd5b86016080818c03601f1901811315613ebd5760008081fd5b613ec5613c54565b89830135613ed281613d57565b81526040613ee1848201613d6c565b8b830152606080850135613ef481613d88565b83830152928401359289841115613f0d57600091508182fd5b613f1b8f8d86880101613dc8565b908301525085525050918601918601613e8d565b5098975050505050505050565b60005b83811015613f57578181015183820152602001613f3f565b50506000910152565b60008151808452613f78816020860160208601613f3c565b601f01601f19169290920160200192915050565b602081526000610d566020830184613f60565b8060608101831015610d5957600080fd5b60008083601f840112613fc257600080fd5b5081356001600160401b03811115613fd957600080fd5b602083019150836020828501011115613ff157600080fd5b9250929050565b60008083601f84011261400a57600080fd5b5081356001600160401b0381111561402157600080fd5b6020830191508360208260051b8501011115613ff157600080fd5b60008060008060008060008060e0898b03121561405857600080fd5b6140628a8a613f9f565b975060608901356001600160401b038082111561407e57600080fd5b61408a8c838d01613fb0565b909950975060808b01359150808211156140a357600080fd5b6140af8c838d01613ff8565b909750955060a08b01359150808211156140c857600080fd5b506140d58b828c01613ff8565b999c989b50969995989497949560c00135949350505050565b60008060006080848603121561410357600080fd5b61410d8585613f9f565b925060608401356001600160401b0381111561412857600080fd5b61413486828701613fb0565b9497909650939450505050565b6001600160a01b0381511682526020810151151560208301526001600160401b03604082015116604083015260006060820151608060608501526135e06080850182613f60565b604080825283519082018190526000906020906060840190828701845b828110156141ca5781516001600160401b0316845292840192908401906001016141a5565b50505083810382850152845180825282820190600581901b8301840187850160005b8381101561421a57601f19868403018552614208838351614141565b948701949250908601906001016141ec565b50909998505050505050505050565b6000806040838503121561423c57600080fd5b61424583613d6c565b915061425360208401613d6c565b90509250929050565b634e487b7160e01b600052602160045260246000fd5b600481106142825761428261425c565b9052565b60208101610d598284614272565b600060a082840312156142a657600080fd5b6142ae613c7c565b9050813581526142c060208301613d6c565b60208201526142d160408301613d6c565b60408201526142e260608301613d6c565b60608201526142f360808301613d6c565b608082015292915050565b8035613d8381613d57565b803563ffffffff81168114613d8357600080fd5b600082601f83011261432e57600080fd5b8135602061433e613de783613d34565b82815260059290921b8401810191818101908684111561435d57600080fd5b8286015b8481101561442d5780356001600160401b03808211156143815760008081fd5b9088019060a0828b03601f190181131561439b5760008081fd5b6143a3613c7c565b87840135838111156143b55760008081fd5b6143c38d8a83880101613dc8565b8252506040808501356143d581613d57565b828a015260606143e6868201614309565b828401526080915081860135858111156144005760008081fd5b61440e8f8c838a0101613dc8565b9184019190915250919093013590830152508352918301918301614361565b509695505050505050565b6000610140828403121561444b57600080fd5b614453613c9e565b905061445f8383614294565b815260a08201356001600160401b038082111561447b57600080fd5b61448785838601613dc8565b602084015260c08401359150808211156144a057600080fd5b6144ac85838601613dc8565b60408401526144bd60e085016142fe565b606084015261010084013560808401526101208401359150808211156144e257600080fd5b506144ef8482850161431d565b60a08301525092915050565b600082601f83011261450c57600080fd5b8135602061451c613de783613d34565b82815260059290921b8401810191818101908684111561453b57600080fd5b8286015b8481101561442d5780356001600160401b0381111561455e5760008081fd5b61456c8986838b0101614438565b84525091830191830161453f565b600082601f83011261458b57600080fd5b8135602061459b613de783613d34565b82815260059290921b840181019181810190868411156145ba57600080fd5b8286015b8481101561442d5780356001600160401b03808211156145dd57600080fd5b818901915089603f8301126145f157600080fd5b85820135614601613de782613d34565b81815260059190911b830160400190878101908c83111561462157600080fd5b604085015b8381101561465a5780358581111561463d57600080fd5b61464c8f6040838a0101613dc8565b845250918901918901614626565b508752505050928401925083016145be565b600082601f83011261467d57600080fd5b8135602061468d613de783613d34565b8083825260208201915060208460051b8701019350868411156146af57600080fd5b602086015b8481101561442d57803583529183019183016146b4565b600082601f8301126146dc57600080fd5b813560206146ec613de783613d34565b82815260059290921b8401810191818101908684111561470b57600080fd5b8286015b8481101561442d5780356001600160401b038082111561472f5760008081fd5b9088019060a0828b03601f19018113156147495760008081fd5b614751613c7c565b61475c888501613d6c565b8152604080850135848111156147725760008081fd5b6147808e8b838901016144fb565b8a84015250606080860135858111156147995760008081fd5b6147a78f8c838a010161457a565b83850152506080915081860135858111156147c25760008081fd5b6147d08f8c838a010161466c565b918401919091525091909301359083015250835291830191830161470f565b6000806040838503121561480257600080fd5b6001600160401b038335111561481757600080fd5b61482484843585016146cb565b91506001600160401b036020840135111561483e57600080fd5b6020830135830184601f82011261485457600080fd5b614861613de78235613d34565b81358082526020808301929160051b84010187101561487f57600080fd5b602083015b6020843560051b850101811015614a25576001600160401b03813511156148aa57600080fd5b87603f8235860101126148bc57600080fd5b6148cf613de76020833587010135613d34565b81358501602081810135808452908301929160059190911b016040018a10156148f757600080fd5b604083358701015b83358701602081013560051b01604001811015614a15576001600160401b038135111561492b57600080fd5b833587018135016040818d03603f1901121561494657600080fd5b61494e613cc0565b604082013581526001600160401b036060830135111561496d57600080fd5b8c605f60608401358401011261498257600080fd5b6040606083013583010135614999613de782613d34565b808282526020820191508f60608460051b60608801358801010111156149be57600080fd5b6060808601358601015b60608460051b6060880135880101018110156149f5576149e781614309565b8352602092830192016149c8565b5080602085015250505080855250506020830192506020810190506148ff565b5084525060209283019201614884565b508093505050509250929050565b600080600080600060608688031215614a4b57600080fd5b85356001600160401b0380821115614a6257600080fd5b614a6e89838a01614438565b96506020880135915080821115614a8457600080fd5b614a9089838a01613ff8565b90965094506040880135915080821115614aa957600080fd5b50614ab688828901613ff8565b969995985093965092949392505050565b600060808284031215614ad957600080fd5b614ae1613c54565b8235614aec81613d57565b8152614afa60208401614309565b60208201526040830135614b0d81613d88565b60408201526060830135614b2081613d57565b60608201529392505050565b600060208284031215614b3e57600080fd5b81356001600160401b03811115614b5457600080fd5b820160a08185031215613b7c57600080fd5b803560ff81168114613d8357600080fd5b600060208284031215614b8957600080fd5b610d5682614b66565b60008151808452602080850194506020840160005b83811015614bcc5781516001600160a01b031687529582019590820190600101614ba7565b509495945050505050565b60208152600082518051602084015260ff602082015116604084015260ff604082015116606084015260608101511515608084015250602083015160c060a0840152614c2660e0840182614b92565b90506040840151601f198483030160c0850152614c438282614b92565b95945050505050565b60008060408385031215614c5f57600080fd5b614c6883613d6c565b946020939093013593505050565b600060208284031215614c8857600080fd5b610d5682613d6c565b602081526000610d566020830184614141565b600060208284031215614cb657600080fd5b8135613b7c81613d57565b600082601f830112614cd257600080fd5b81356020614ce2613de783613d34565b8083825260208201915060208460051b870101935086841115614d0457600080fd5b602086015b8481101561442d578035614d1c81613d57565b8352918301918301614d09565b60006020808385031215614d3c57600080fd5b82356001600160401b0380821115614d5357600080fd5b818501915085601f830112614d6757600080fd5b8135614d75613de782613d34565b81815260059190911b83018401908481019088831115614d9457600080fd5b8585015b83811015613f2f57803585811115614daf57600080fd5b860160c0818c03601f19011215614dc65760008081fd5b614dce613c9e565b8882013581526040614de1818401614b66565b8a8301526060614df2818501614b66565b8284015260809150614e05828501613d96565b9083015260a08381013589811115614e1d5760008081fd5b614e2b8f8d83880101614cc1565b838501525060c0840135915088821115614e455760008081fd5b614e538e8c84870101614cc1565b9083015250845250918601918601614d98565b80356001600160e01b0381168114613d8357600080fd5b600082601f830112614e8e57600080fd5b81356020614e9e613de783613d34565b82815260069290921b84018101918181019086841115614ebd57600080fd5b8286015b8481101561442d5760408189031215614eda5760008081fd5b614ee2613cc0565b614eeb82613d6c565b8152614ef8858301614e66565b81860152835291830191604001614ec1565b600082601f830112614f1b57600080fd5b81356020614f2b613de783613d34565b82815260059290921b84018101918181019086841115614f4a57600080fd5b8286015b8481101561442d5780356001600160401b0380821115614f6e5760008081fd5b9088019060a0828b03601f1901811315614f885760008081fd5b614f90613c7c565b614f9b888501613d6c565b815260408085013584811115614fb15760008081fd5b614fbf8e8b83890101613dc8565b8a8401525060609350614fd3848601613d6c565b908201526080614fe4858201613d6c565b93820193909352920135908201528352918301918301614f4e565b600082601f83011261501057600080fd5b81356020615020613de783613d34565b82815260069290921b8401810191818101908684111561503f57600080fd5b8286015b8481101561442d576040818903121561505c5760008081fd5b615064613cc0565b813581528482013585820152835291830191604001615043565b6000602080838503121561509157600080fd5b82356001600160401b03808211156150a857600080fd5b90840190606082870312156150bc57600080fd5b6150c4613ce2565b8235828111156150d357600080fd5b830160408189038113156150e657600080fd5b6150ee613cc0565b8235858111156150fd57600080fd5b8301601f81018b1361510e57600080fd5b803561511c613de782613d34565b81815260069190911b8201890190898101908d83111561513b57600080fd5b928a01925b8284101561518b5785848f0312156151585760008081fd5b615160613cc0565b843561516b81613d57565b8152615178858d01614e66565b818d0152825292850192908a0190615140565b8452505050828701359150848211156151a357600080fd5b6151af8a838501614e7d565b818801528352505082840135828111156151c857600080fd5b6151d488828601614f0a565b858301525060408301359350818411156151ed57600080fd5b6151f987858501614fff565b60408201529695505050505050565b600082825180855260208086019550808260051b84010181860160005b8481101561529957601f19868403018952815160a06001600160401b0380835116865286830151828888015261525d83880182613f60565b60408581015184169089015260608086015190931692880192909252506080928301519290950191909152509783019790830190600101615225565b5090979650505050505050565b6001600160a01b0384168152600060206060818401526152c96060840186615208565b83810360408581019190915285518083528387019284019060005b8181101561421a578451805184528601518684015293850193918301916001016152e4565b634e487b7160e01b600052603260045260246000fd5b805160408084528151848201819052600092602091908201906060870190855b8181101561537657835180516001600160a01b031684528501516001600160e01b031685840152928401929185019160010161533f565b50508583015187820388850152805180835290840192506000918401905b808310156153cf57835180516001600160401b031683528501516001600160e01b031685830152928401926001929092019190850190615394565b50979650505050505050565b602081526000610d56602083018461531f565b60006020828403121561540057600080fd5b8151613b7c81613d88565b600181811c9082168061541f57607f821691505b60208210810361543f57634e487b7160e01b600052602260045260246000fd5b50919050565b60008083546154538161540b565b6001828116801561546b5760018114615480576154af565b60ff19841687528215158302870194506154af565b8760005260208060002060005b858110156154a65781548a82015290840190820161548d565b50505082870194505b50929695505050505050565b600081546154c88161540b565b8085526020600183811680156154e557600181146154ff5761552d565b60ff1985168884015283151560051b88018301955061552d565b866000528260002060005b858110156155255781548a820186015290830190840161550a565b890184019650505b505050505092915050565b60408152600061554b6040830185613f60565b8281036020840152614c4381856154bb565b634e487b7160e01b600052601160045260246000fd5b6001600160401b038181168382160190808211156155935761559361555d565b5092915050565b6040815260006155ad6040830185615208565b8281036020840152614c43818561531f565b6000602082840312156155d157600080fd5b81356001600160401b038111156155e757600080fd5b6135e0848285016146cb565b81810381811115610d5957610d5961555d565b634e487b7160e01b600052601260045260246000fd5b60006001600160401b038084168061563657615636615606565b92169190910692915050565b8082028115828204841417610d5957610d5961555d565b80518252600060206001600160401b0381840151168185015260408084015160a0604087015261568c60a0870182613f60565b9050606085015186820360608801526156a58282613f60565b608087810151898303918a01919091528051808352908601935060009250908501905b808310156153cf57835180516001600160a01b03168352860151868301529285019260019290920191908401906156c8565b602081526000610d566020830184615659565b6080815260006157206080830187615659565b61ffff9590951660208301525060408101929092526001600160a01b0316606090910152919050565b60008060006060848603121561575e57600080fd5b835161576981613d88565b60208501519093506001600160401b0381111561578557600080fd5b8401601f8101861361579657600080fd5b80516157a4613de782613da1565b8181528760208385010111156157b957600080fd5b6157ca826020830160208601613f3c565b809450505050604084015190509250925092565b601f821115610fe9576000816000526020600020601f850160051c810160208610156158075750805b601f850160051c820191505b8181101561582657828155600101615813565b505050505050565b81516001600160401b0381111561584757615847613c3e565b61585b81615855845461540b565b846157de565b602080601f83116001811461589057600084156158785750858301515b600019600386901b1c1916600185901b178555615826565b600085815260208120601f198616915b828110156158bf578886015182559484019460019091019084016158a0565b50858210156158dd5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b60208152600082546001600160a01b038116602084015260ff8160a01c16151560408401526001600160401b038160a81c16606084015250608080830152610d5660a08301600185016154bb565b80820180821115610d5957610d5961555d565b60ff8181168382160190811115610d5957610d5961555d565b8183823760009101908152919050565b828152606082602083013760800192915050565b60006001600160401b03808416806159a5576159a5615606565b92169190910492915050565b6000602082840312156159c357600080fd5b610d5682614309565b6000808335601e198436030181126159e357600080fd5b8301803591506001600160401b038211156159fd57600080fd5b602001915036819003821315613ff157600080fd5b6020810160068310615a2657615a2661425c565b91905290565b60ff81811683821602908116908181146155935761559361555d565b600060a0820160ff881683526020878185015260a0604085015281875480845260c0860191508860005282600020935060005b81811015615aa05784546001600160a01b031683526001948501949284019201615a7b565b50508481036060860152865180825290820192508187019060005b81811015615ae05782516001600160a01b031685529383019391830191600101615abb565b50505060ff851660808501525090505b9695505050505050565b60006001600160401b03808616835280851660208401525060606040830152614c436060830184613f60565b8281526040602082015260006135e06040830184613f60565b6001600160401b03848116825283166020820152606081016135e06040830184614272565b848152615b746020820185614272565b608060408201526000615b8a6080830185613f60565b905082606083015295945050505050565b600060208284031215615bad57600080fd5b8151613b7c81613d57565b6020815260008251610100806020850152615bd7610120850183613f60565b91506020850151615bf360408601826001600160401b03169052565b5060408501516001600160a01b038116606086015250606085015160808501526080850151615c2d60a08601826001600160a01b03169052565b5060a0850151601f19808685030160c0870152615c4a8483613f60565b935060c08701519150808685030160e0870152615c678483613f60565b935060e0870151915080868503018387015250615af08382613f60565b600060208284031215615c9657600080fd5b5051919050565b600082825180855260208086019550808260051b84010181860160005b8481101561529957601f19868403018952815160a08151818652615ce082870182613f60565b9150506001600160a01b03868301511686860152604063ffffffff8184015116818701525060608083015186830382880152615d1c8382613f60565b6080948501519790940196909652505098840198925090830190600101615cba565b602081526000610d566020830184615c9d565b60008282518085526020808601955060208260051b8401016020860160005b8481101561529957601f19868403018952615d8c838351613f60565b98840198925090830190600101615d70565b60008151808452602080850194506020840160005b83811015614bcc57815163ffffffff1687529582019590820190600101615db3565b60608152600084518051606084015260208101516001600160401b0380821660808601528060408401511660a08601528060608401511660c08601528060808401511660e0860152505050602085015161014080610100850152615e3d6101a0850183613f60565b91506040870151605f198086850301610120870152615e5c8483613f60565b935060608901519150615e79838701836001600160a01b03169052565b608089015161016087015260a0890151925080868503016101808701525050615ea28282615c9d565b9150508281036020840152615eb78186615d51565b90508281036040840152615af08185615d9e56fea164736f6c6343000818000a", } var OffRampABI = OffRampMetaData.ABI @@ -561,27 +560,27 @@ func (_OffRamp *OffRampTransactorSession) ApplySourceChainConfigUpdates(sourceCh return _OffRamp.Contract.ApplySourceChainConfigUpdates(&_OffRamp.TransactOpts, sourceChainConfigUpdates) } -func (_OffRamp *OffRampTransactor) Commit(opts *bind.TransactOpts, reportContext [2][32]byte, report []byte, rs [][32]byte, ss [][32]byte, rawVs [32]byte) (*types.Transaction, error) { +func (_OffRamp *OffRampTransactor) Commit(opts *bind.TransactOpts, reportContext [3][32]byte, report []byte, rs [][32]byte, ss [][32]byte, rawVs [32]byte) (*types.Transaction, error) { return _OffRamp.contract.Transact(opts, "commit", reportContext, report, rs, ss, rawVs) } -func (_OffRamp *OffRampSession) Commit(reportContext [2][32]byte, report []byte, rs [][32]byte, ss [][32]byte, rawVs [32]byte) (*types.Transaction, error) { +func (_OffRamp *OffRampSession) Commit(reportContext [3][32]byte, report []byte, rs [][32]byte, ss [][32]byte, rawVs [32]byte) (*types.Transaction, error) { return _OffRamp.Contract.Commit(&_OffRamp.TransactOpts, reportContext, report, rs, ss, rawVs) } -func (_OffRamp *OffRampTransactorSession) Commit(reportContext [2][32]byte, report []byte, rs [][32]byte, ss [][32]byte, rawVs [32]byte) (*types.Transaction, error) { +func (_OffRamp *OffRampTransactorSession) Commit(reportContext [3][32]byte, report []byte, rs [][32]byte, ss [][32]byte, rawVs [32]byte) (*types.Transaction, error) { return _OffRamp.Contract.Commit(&_OffRamp.TransactOpts, reportContext, report, rs, ss, rawVs) } -func (_OffRamp *OffRampTransactor) Execute(opts *bind.TransactOpts, reportContext [2][32]byte, report []byte) (*types.Transaction, error) { +func (_OffRamp *OffRampTransactor) Execute(opts *bind.TransactOpts, reportContext [3][32]byte, report []byte) (*types.Transaction, error) { return _OffRamp.contract.Transact(opts, "execute", reportContext, report) } -func (_OffRamp *OffRampSession) Execute(reportContext [2][32]byte, report []byte) (*types.Transaction, error) { +func (_OffRamp *OffRampSession) Execute(reportContext [3][32]byte, report []byte) (*types.Transaction, error) { return _OffRamp.Contract.Execute(&_OffRamp.TransactOpts, reportContext, report) } -func (_OffRamp *OffRampTransactorSession) Execute(reportContext [2][32]byte, report []byte) (*types.Transaction, error) { +func (_OffRamp *OffRampTransactorSession) Execute(reportContext [3][32]byte, report []byte) (*types.Transaction, error) { return _OffRamp.Contract.Execute(&_OffRamp.TransactOpts, reportContext, report) } @@ -2468,7 +2467,7 @@ func (OffRampSourceChainSelectorAdded) Topic() common.Hash { } func (OffRampStaticConfigSet) Topic() common.Hash { - return common.HexToHash("0xb0fa1fb01508c5097c502ad056fd77018870c9be9a86d9e56b6b471862d7c5b7") + return common.HexToHash("0x683eb52ee924eb817377cfa8f41f238f4bb7a877da5267869dfffbad85f564d8") } func (OffRampTransmitted) Topic() common.Hash { @@ -2506,9 +2505,9 @@ type OffRampInterface interface { ApplySourceChainConfigUpdates(opts *bind.TransactOpts, sourceChainConfigUpdates []OffRampSourceChainConfigArgs) (*types.Transaction, error) - Commit(opts *bind.TransactOpts, reportContext [2][32]byte, report []byte, rs [][32]byte, ss [][32]byte, rawVs [32]byte) (*types.Transaction, error) + Commit(opts *bind.TransactOpts, reportContext [3][32]byte, report []byte, rs [][32]byte, ss [][32]byte, rawVs [32]byte) (*types.Transaction, error) - Execute(opts *bind.TransactOpts, reportContext [2][32]byte, report []byte) (*types.Transaction, error) + Execute(opts *bind.TransactOpts, reportContext [3][32]byte, report []byte) (*types.Transaction, error) ExecuteSingleMessage(opts *bind.TransactOpts, message InternalAny2EVMRampMessage, offchainTokenData [][]byte, tokenGasOverrides []uint32) (*types.Transaction, error) diff --git a/core/gethwrappers/ccip/generated/onramp/onramp.go b/core/gethwrappers/ccip/generated/onramp/onramp.go index ec1f6baa2ec..f6f61ebc976 100644 --- a/core/gethwrappers/ccip/generated/onramp/onramp.go +++ b/core/gethwrappers/ccip/generated/onramp/onramp.go @@ -101,7 +101,7 @@ type OnRampStaticConfig struct { var OnRampMetaData = &bind.MetaData{ ABI: "[{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"contractIRMNRemote\",\"name\":\"rmnRemote\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"}],\"internalType\":\"structOnRamp.StaticConfig\",\"name\":\"staticConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"reentrancyGuardEntered\",\"type\":\"bool\"},{\"internalType\":\"address\",\"name\":\"messageInterceptor\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"feeAggregator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"allowlistAdmin\",\"type\":\"address\"}],\"internalType\":\"structOnRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"allowlistEnabled\",\"type\":\"bool\"}],\"internalType\":\"structOnRamp.DestChainConfigArgs[]\",\"name\":\"destChainConfigArgs\",\"type\":\"tuple[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"CannotSendZeroTokens\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CannotTransferToSelf\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"CursedByRMN\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"GetSupportedTokensFunctionalityRemovedCheckAdminRegistry\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"InvalidAllowListRequest\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidConfig\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"InvalidDestChainConfig\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MustBeCalledByRouter\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MustBeProposedOwner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByOwner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByOwnerOrAllowlistAdmin\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OwnerCannotBeZero\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ReentrancyGuardReentrantCall\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RouterMustSetOriginalSender\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"SenderNotAllowed\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"UnsupportedToken\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"allowlistAdmin\",\"type\":\"address\"}],\"name\":\"AllowListAdminSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"senders\",\"type\":\"address[]\"}],\"name\":\"AllowListSendersAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"senders\",\"type\":\"address[]\"}],\"name\":\"AllowListSendersRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"}],\"internalType\":\"structInternal.RampMessageHeader\",\"name\":\"header\",\"type\":\"tuple\"},{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraArgs\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"feeTokenAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"feeValueJuels\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"sourcePoolAddress\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"destExecData\",\"type\":\"bytes\"}],\"internalType\":\"structInternal.EVM2AnyTokenTransfer[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"}],\"indexed\":false,\"internalType\":\"structInternal.EVM2AnyRampMessage\",\"name\":\"message\",\"type\":\"tuple\"}],\"name\":\"CCIPMessageSent\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"contractIRMNRemote\",\"name\":\"rmnRemote\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"}],\"indexed\":false,\"internalType\":\"structOnRamp.StaticConfig\",\"name\":\"staticConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"reentrancyGuardEntered\",\"type\":\"bool\"},{\"internalType\":\"address\",\"name\":\"messageInterceptor\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"feeAggregator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"allowlistAdmin\",\"type\":\"address\"}],\"indexed\":false,\"internalType\":\"structOnRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"}],\"name\":\"ConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"allowlistEnabled\",\"type\":\"bool\"}],\"name\":\"DestChainConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"feeAggregator\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"FeeTokenWithdrawn\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"allowlistEnabled\",\"type\":\"bool\"},{\"internalType\":\"address[]\",\"name\":\"addedAllowlistedSenders\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"removedAllowlistedSenders\",\"type\":\"address[]\"}],\"internalType\":\"structOnRamp.AllowlistConfigArgs[]\",\"name\":\"allowlistConfigArgsItems\",\"type\":\"tuple[]\"}],\"name\":\"applyAllowlistUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"allowlistEnabled\",\"type\":\"bool\"}],\"internalType\":\"structOnRamp.DestChainConfigArgs[]\",\"name\":\"destChainConfigArgs\",\"type\":\"tuple[]\"}],\"name\":\"applyDestChainConfigUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structClient.EVMTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"},{\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"extraArgs\",\"type\":\"bytes\"}],\"internalType\":\"structClient.EVM2AnyMessage\",\"name\":\"message\",\"type\":\"tuple\"},{\"internalType\":\"uint256\",\"name\":\"feeTokenAmount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"originalSender\",\"type\":\"address\"}],\"name\":\"forwardFromRouter\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"getAllowedSendersList\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"address[]\",\"name\":\"configuredAddresses\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"getDestChainConfig\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"allowlistEnabled\",\"type\":\"bool\"},{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getDynamicConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"reentrancyGuardEntered\",\"type\":\"bool\"},{\"internalType\":\"address\",\"name\":\"messageInterceptor\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"feeAggregator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"allowlistAdmin\",\"type\":\"address\"}],\"internalType\":\"structOnRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"getExpectedNextSequenceNumber\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structClient.EVMTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"},{\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"extraArgs\",\"type\":\"bytes\"}],\"internalType\":\"structClient.EVM2AnyMessage\",\"name\":\"message\",\"type\":\"tuple\"}],\"name\":\"getFee\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"feeTokenAmount\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"},{\"internalType\":\"contractIERC20\",\"name\":\"sourceToken\",\"type\":\"address\"}],\"name\":\"getPoolBySourceToken\",\"outputs\":[{\"internalType\":\"contractIPoolV1\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getStaticConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"contractIRMNRemote\",\"name\":\"rmnRemote\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"}],\"internalType\":\"structOnRamp.StaticConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"name\":\"getSupportedTokens\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"reentrancyGuardEntered\",\"type\":\"bool\"},{\"internalType\":\"address\",\"name\":\"messageInterceptor\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"feeAggregator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"allowlistAdmin\",\"type\":\"address\"}],\"internalType\":\"structOnRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"}],\"name\":\"setDynamicConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"feeTokens\",\"type\":\"address[]\"}],\"name\":\"withdrawFeeTokens\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", - Bin: "0x6101006040523461055f57613c018038038061001a81610599565b92833981019080820390610140821261055f576080821261055f5761003d61057a565b90610047816105be565b82526020810151906001600160a01b038216820361055f5760208301918252610072604082016105d2565b926040810193845260a0610088606084016105d2565b6060830190815295607f19011261055f5760405160a081016001600160401b03811182821017610564576040526100c1608084016105d2565b81526100cf60a084016105e6565b602082019081526100e260c085016105d2565b91604081019283526100f660e086016105d2565b936060820194855261010b61010087016105d2565b6080830190815261012087015190966001600160401b03821161055f57018a601f8201121561055f578051906001600160401b0382116105645760209b8c6060610159828660051b01610599565b9e8f8681520194028301019181831161055f57602001925b8284106104f1575050505033156104e057600180546001600160a01b0319163317905580516001600160401b03161580156104ce575b80156104bc575b80156104aa575b61047d57516001600160401b0316608081905295516001600160a01b0390811660a08190529751811660c08190529851811660e08190528251909116158015610498575b801561048e575b61047d57815160028054855160ff60a01b90151560a01b166001600160a01b039384166001600160a81b0319909216919091171790558451600380549183166001600160a01b03199283161790558651600480549184169183169190911790558751600580549190931691161790557fc7372d2d886367d7bb1b0e0708a5436f2c91d6963de210eb2dc1ec2ecd6d21f19861012098606061029f61057a565b8a8152602080820193845260408083019586529290910194855281519a8b5291516001600160a01b03908116928b019290925291518116918901919091529051811660608801529051811660808701529051151560a08601529051811660c08501529051811660e0840152905116610100820152a16000905b805182101561040b5761032b82826105f3565b51916001600160401b0361033f82846105f3565b5151169283156103f65760008481526006602090815260409182902081840151815494840151600160401b600160e81b03198616604883901b600160481b600160e81b031617901515851b68ff000000000000000016179182905583516001600160401b0390951685526001600160a01b031691840191909152811c60ff1615159082015291926001927fd5ad72bc37dc7a80a8b9b9df20500046fd7341adb1be2258a540466fdd7dcef590606090a20190610318565b8363c35aa79d60e01b60005260045260246000fd5b6040516135e3908161061e82396080518181816103e301528181610b39015281816120c8015261286b015260a0518181816121010152818161261e01526128a4015260c051818181610efc0152818161213d01526128e0015260e0518181816121790152818161291c0152612edd0152f35b6306b7c75960e31b60005260046000fd5b5082511515610200565b5084516001600160a01b0316156101f9565b5088516001600160a01b0316156101b5565b5087516001600160a01b0316156101ae565b5086516001600160a01b0316156101a7565b639b15e16f60e01b60005260046000fd5b60608483031261055f5760405190606082016001600160401b0381118382101761056457604052610521856105be565b82526020850151906001600160a01b038216820361055f578260209283606095015261054f604088016105e6565b6040820152815201930192610171565b600080fd5b634e487b7160e01b600052604160045260246000fd5b60405190608082016001600160401b0381118382101761056457604052565b6040519190601f01601f191682016001600160401b0381118382101761056457604052565b51906001600160401b038216820361055f57565b51906001600160a01b038216820361055f57565b5190811515820361055f57565b80518210156106075760209160051b010190565b634e487b7160e01b600052603260045260246000fdfe608080604052600436101561001357600080fd5b600090813560e01c90816306285c691461280557508063181f5a771461278657806320487ded146125425780632716072b1461229257806327e936f114611e8c57806348a98aa414611e095780635cb80c5d14611b215780636def4ce714611a925780637437ff9f1461195957806379ba5097146118745780638da5cb5b146118225780639041be3d14611775578063972b4612146116a7578063c9b146b3146112da578063df0aa9e91461022c578063f2fde38b1461013f5763fbca3b74146100dc57600080fd5b3461013c5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261013c57600490610116612af4565b507f9e7177c8000000000000000000000000000000000000000000000000000000008152fd5b80fd5b503461013c5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261013c5773ffffffffffffffffffffffffffffffffffffffff61018c612b4a565b610194613280565b1633811461020457807fffffffffffffffffffffffff000000000000000000000000000000000000000083541617825573ffffffffffffffffffffffffffffffffffffffff600154167fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12788380a380f35b6004827fdad89dca000000000000000000000000000000000000000000000000000000008152fd5b503461013c5760807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261013c57610264612af4565b67ffffffffffffffff602435116112d65760a07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc602435360301126112d6576102ab612b6d565b60025460ff8160a01c166112ae577fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740100000000000000000000000000000000000000001760025567ffffffffffffffff8216835260066020526040832073ffffffffffffffffffffffffffffffffffffffff82161561128657805460ff8160401c16611218575b60481c73ffffffffffffffffffffffffffffffffffffffff1633036111f05773ffffffffffffffffffffffffffffffffffffffff6003541680611183575b50805467ffffffffffffffff811667ffffffffffffffff8114611156579067ffffffffffffffff60017fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000009493011692839116179055604051906103d5826129db565b84825267ffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016602083015267ffffffffffffffff8416604083015260608201528360808201526104366024803501602435600401613060565b61044560046024350180613060565b610453606460243501612f97565b936104686044602435016024356004016130b1565b9490507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe06104ae61049887612b25565b966104a66040519889612a13565b808852612b25565b018a5b81811061113f575050604051968761012081011067ffffffffffffffff6101208a011117611112576101208801604052875273ffffffffffffffffffffffffffffffffffffffff8816602088015261051c939291610510913691613131565b60408701523691613131565b606084015273ffffffffffffffffffffffffffffffffffffffff6020926040516105468582612a13565b88815260808601521660a084015260443560c08401528560e084015261010083015261057c6044602435016024356004016130b1565b61058881969296612b25565b906105966040519283612a13565b8082528382018097368360061b8201116110895780915b8360061b820183106110d75750505050865b6105d36044602435016024356004016130b1565b9050811015610959576105e6818361301d565b516106006105f960046024350180613060565b3691613131565b90610609613105565b5085810151156109315773ffffffffffffffffffffffffffffffffffffffff61063481835116612e7e565b169182158015610887575b61084457908a6106ee949392888873ffffffffffffffffffffffffffffffffffffffff8d838701518280895116926040519761067a896129db565b885267ffffffffffffffff87890196168652816040890191168152606088019283526080880193845267ffffffffffffffff6040519d8e998a997f9a4575b9000000000000000000000000000000000000000000000000000000008b5260048b01525160a060248b015260c48a0190612ab1565b965116604488015251166064860152516084850152511660a4830152038183865af1938415610839578b94610783575b5061077c918484928980600198519301519101519160405193610740856129db565b84528a8401526040830152606082015260405161075d8982612a13565b8c8152608082015261010089015190610776838361301d565b5261301d565b50016105bf565b93503d91828c863e6107958386612a13565b878584810103126108355784519167ffffffffffffffff83116108315760408387018588010312610831576040516107cc816129f7565b8387015167ffffffffffffffff811161082d576107f09086890190868a0101613168565b81528984880101519467ffffffffffffffff861161082d578761077c96889661081f9360019b01920101613168565b8a820152955091509161071e565b8e80fd5b8c80fd5b8b80fd5b6040513d8d823e3d90fd5b60248b73ffffffffffffffffffffffffffffffffffffffff8451167fbf16aab6000000000000000000000000000000000000000000000000000000008252600452fd5b506040517f01ffc9a70000000000000000000000000000000000000000000000000000000081527faff2afbf0000000000000000000000000000000000000000000000000000000060048201528781602481875afa908115610926578c916108f1575b501561063f565b90508781813d831161091f575b6109088183612a13565b810103126108355761091990612c2c565b386108ea565b503d6108fe565b6040513d8e823e3d90fd5b60048a7f5cf04449000000000000000000000000000000000000000000000000000000008152fd5b50867f430d138c00000000000000000000000000000000000000000000000000000000839282979873ffffffffffffffffffffffffffffffffffffffff600254169187610a496109ad606460243501612f97565b610a198c61010073ffffffffffffffffffffffffffffffffffffffff6109dd608460243501602435600401613060565b92909301519467ffffffffffffffff6040519e8f9d8e521660048d01521660248b015260443560448b015260c060648b015260c48a0191612c89565b907ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc8883030160848901526131aa565b917ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc8684030160a48701525191828152019190855b8982821061109c575050505082809103915afa9586156110915785869087938899610f7f575b5060e087015215610e8d5750845b67ffffffffffffffff6080865101911690526080840152835b61010084015151811015610b015780610ae66001928861301d565b516080610af88361010089015161301d565b51015201610acb565b509092604051848101907f130ac867e79e2789f923760a88743d292acdf7002139a588206e2260f73f7321825267ffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016604082015267ffffffffffffffff8416606082015230608082015260808152610b8360a082612a13565b51902073ffffffffffffffffffffffffffffffffffffffff602085015116845167ffffffffffffffff6080816060840151169201511673ffffffffffffffffffffffffffffffffffffffff60a08801511660c088015191604051938a850195865260408501526060840152608083015260a082015260a08152610c0760c082612a13565b51902060608501518681519101206040860151878151910120610100870151604051610c6d81610c418c8201948d865260408301906131aa565b037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08101835282612a13565b51902091608088015189815191012093604051958a870197885260408701526060860152608085015260a084015260c083015260e082015260e08152610cb561010082612a13565b51902082515267ffffffffffffffff60608351015116907f192442a2b2adb6a7948f097023cb6b57d29d3a7a5dd33e6666d33c39cc456f3260405185815267ffffffffffffffff608086518051898501528289820151166040850152826040820151166060850152826060820151168285015201511660a082015273ffffffffffffffffffffffffffffffffffffffff60208601511660c082015280610e58610ddf610daa610d7560408a01516101a060e08701526101c0860190612ab1565b60608a01517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe086830301610100870152612ab1565b60808901517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe085830301610120860152612ab1565b73ffffffffffffffffffffffffffffffffffffffff60a08901511661014084015260c088015161016084015260e088015161018084015267ffffffffffffffff610100890151967fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0858403016101a086015216956131aa565b0390a37fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff600254166002555151604051908152f35b73ffffffffffffffffffffffffffffffffffffffff604051917fea458c0c00000000000000000000000000000000000000000000000000000000835267ffffffffffffffff8516600484015216602482015283816044818973ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000165af1908115610f74578691610f32575b50610ab2565b90508381813d8311610f6d575b610f498183612a13565b81010312610f69575167ffffffffffffffff81168103610f695787610f2c565b8580fd5b503d610f3f565b6040513d88823e3d90fd5b9850505090503d908186883e610f958288612a13565b6080878381010312610f6957865196610faf858201612c2c565b97604082015167ffffffffffffffff811161108d57610fd390858401908401613168565b9160608101519467ffffffffffffffff861161108957808201601f87840101121561108957858201519161100683612b25565b966110146040519889612a13565b838852898801928083018b8660051b848601010111610831578a82840101935b8b8660051b84860101018510611054575050505050509790929789610aa4565b845167ffffffffffffffff811161082d578c809261107c829383878a0191898b010101613168565b8152019501949050611034565b8980fd5b8880fd5b6040513d87823e3d90fd5b8351805173ffffffffffffffffffffffffffffffffffffffff168652810151818601528c975088965060409094019390920191600101610a7e565b60408336031261110e578660409182516110f0816129f7565b6110f986612b90565b815282860135838201528152019201916105ad565b8a80fd5b60248b7f4e487b710000000000000000000000000000000000000000000000000000000081526041600452fd5b60209061114a613105565b82828a010152016104b1565b6024867f4e487b710000000000000000000000000000000000000000000000000000000081526011600452fd5b803b156111ec578460405180927fe0a0e5060000000000000000000000000000000000000000000000000000000082528183816111c96024356004018b60048401612cc8565b03925af18015611091571561037357846111e591959295612a13565b9238610373565b8480fd5b6004847f1c0a3529000000000000000000000000000000000000000000000000000000008152fd5b73ffffffffffffffffffffffffffffffffffffffff831660009081526002830160205260409020546103355760248573ffffffffffffffffffffffffffffffffffffffff857fd0d2597600000000000000000000000000000000000000000000000000000000835216600452fd5b6004847fa4ec7479000000000000000000000000000000000000000000000000000000008152fd5b6004847f3ee5aeb5000000000000000000000000000000000000000000000000000000008152fd5b5080fd5b503461013c5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261013c5760043567ffffffffffffffff81116112d65761132a903690600401612bb1565b73ffffffffffffffffffffffffffffffffffffffff60015416330361165f575b919081907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8181360301915b8481101561165b578060051b820135838112156111ec578201916080833603126111ec57604051946113a686612990565b6113af84612b10565b86526113bd60208501612b3d565b9660208701978852604085013567ffffffffffffffff8111611657576113e69036908701612fb8565b9460408801958652606081013567ffffffffffffffff81116116535761140e91369101612fb8565b60608801908152875167ffffffffffffffff1683526006602052604080842099518a547fffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffff169015159182901b68ff000000000000000016178a5590959081515161152b575b5095976001019550815b855180518210156114bc57906114b573ffffffffffffffffffffffffffffffffffffffff6114ad8360019561301d565b511689613374565b500161147d565b505095909694506001929193519081516114dc575b505001939293611375565b61152167ffffffffffffffff7fc237ec1921f855ccd5e9a5af9733f2d58943a5a8501ec5988e305d7a4d42158692511692604051918291602083526020830190612be2565b0390a238806114d1565b9893959296919094979860001461161c57600184019591875b865180518210156115c15761156e8273ffffffffffffffffffffffffffffffffffffffff9261301d565b5116801561158a57906115836001928a6132e3565b5001611544565b60248a67ffffffffffffffff8e51167f463258ff000000000000000000000000000000000000000000000000000000008252600452fd5b50509692955090929796937f330939f6eafe8bb516716892fe962ff19770570838686e6579dbc1cc51fc328161161267ffffffffffffffff8a51169251604051918291602083526020830190612be2565b0390a23880611473565b60248767ffffffffffffffff8b51167f463258ff000000000000000000000000000000000000000000000000000000008252600452fd5b8380fd5b8280fd5b8380f35b73ffffffffffffffffffffffffffffffffffffffff6005541633031561134a576004837f905d7d9b000000000000000000000000000000000000000000000000000000008152fd5b503461013c5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261013c5767ffffffffffffffff6116e8612af4565b16808252600660205260ff604083205460401c16908252600660205260016040832001916040518093849160208254918281520191845260208420935b81811061175c57505061173a92500383612a13565b61175860405192839215158352604060208401526040830190612be2565b0390f35b8454835260019485019487945060209093019201611725565b503461013c5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261013c5767ffffffffffffffff6117b6612af4565b1681526006602052600167ffffffffffffffff604083205416019067ffffffffffffffff82116117f55760208267ffffffffffffffff60405191168152f35b807f4e487b7100000000000000000000000000000000000000000000000000000000602492526011600452fd5b503461013c57807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261013c57602073ffffffffffffffffffffffffffffffffffffffff60015416604051908152f35b503461013c57807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261013c57805473ffffffffffffffffffffffffffffffffffffffff81163303611931577fffffffffffffffffffffffff000000000000000000000000000000000000000060015491338284161760015516825573ffffffffffffffffffffffffffffffffffffffff3391167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08380a380f35b6004827f02b543c6000000000000000000000000000000000000000000000000000000008152fd5b503461013c57807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261013c576080604051611996816129db565b828152826020820152826040820152826060820152015260a06040516119bb816129db565b60ff60025473ffffffffffffffffffffffffffffffffffffffff81168352831c161515602082015273ffffffffffffffffffffffffffffffffffffffff60035416604082015273ffffffffffffffffffffffffffffffffffffffff60045416606082015273ffffffffffffffffffffffffffffffffffffffff600554166080820152611a90604051809273ffffffffffffffffffffffffffffffffffffffff60808092828151168552602081015115156020860152826040820151166040860152826060820151166060860152015116910152565bf35b503461013c5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261013c57604060609167ffffffffffffffff611ad8612af4565b1681526006602052205473ffffffffffffffffffffffffffffffffffffffff6040519167ffffffffffffffff8116835260ff8160401c161515602084015260481c166040820152f35b503461013c5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261013c5760043567ffffffffffffffff81116112d657611b71903690600401612bb1565b9073ffffffffffffffffffffffffffffffffffffffff6004541690835b83811015611e055773ffffffffffffffffffffffffffffffffffffffff611bb98260051b8401612f97565b1690604051917f70a08231000000000000000000000000000000000000000000000000000000008352306004840152602083602481845afa928315611dfa578793611dc3575b5082611c11575b506001915001611b8e565b8460405193611ccc60208601957fa9059cbb00000000000000000000000000000000000000000000000000000000875283602482015282604482015260448152611c5c606482612a13565b8a80604098895193611c6e8b86612a13565b602085527f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65646020860152519082895af13d15611dbb573d90611caf82612a54565b91611cbc8a519384612a13565b82523d8d602084013e5b86613506565b805180611d08575b505060207f508d7d183612c18fc339b42618912b9fa3239f631dd7ec0671f950200a0fa66e9160019651908152a338611c06565b81929495969350906020918101031261108d576020611d279101612c2c565b15611d385792919085903880611cd4565b608490517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152fd5b606090611cc6565b9092506020813d8211611df2575b81611dde60209383612a13565b81010312611dee57519138611bff565b8680fd5b3d9150611dd1565b6040513d89823e3d90fd5b8480f35b503461013c5760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261013c57611e41612af4565b506024359073ffffffffffffffffffffffffffffffffffffffff8216820361013c576020611e6e83612e7e565b73ffffffffffffffffffffffffffffffffffffffff60405191168152f35b503461013c5760a07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261013c57604051611ec8816129db565b611ed0612b4a565b81526024358015158103611657576020820190815260443573ffffffffffffffffffffffffffffffffffffffff811681036116535760408301908152611f14612b6d565b90606084019182526084359273ffffffffffffffffffffffffffffffffffffffff84168403610f695760808501938452611f4c613280565b73ffffffffffffffffffffffffffffffffffffffff855116158015612273575b8015612269575b612241579273ffffffffffffffffffffffffffffffffffffffff859381809461012097827fc7372d2d886367d7bb1b0e0708a5436f2c91d6963de210eb2dc1ec2ecd6d21f19a51167fffffffffffffffffffffffff000000000000000000000000000000000000000060025416176002555115157fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff74ff00000000000000000000000000000000000000006002549260a01b1691161760025551167fffffffffffffffffffffffff0000000000000000000000000000000000000000600354161760035551167fffffffffffffffffffffffff0000000000000000000000000000000000000000600454161760045551167fffffffffffffffffffffffff0000000000000000000000000000000000000000600554161760055561223d604051916120bd83612990565b67ffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016835273ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016602084015273ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016604084015273ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001660608401526121ed604051809473ffffffffffffffffffffffffffffffffffffffff6060809267ffffffffffffffff8151168552826020820151166020860152826040820151166040860152015116910152565b608083019073ffffffffffffffffffffffffffffffffffffffff60808092828151168552602081015115156020860152826040820151166040860152826060820151166060860152015116910152565ba180f35b6004867f35be3ac8000000000000000000000000000000000000000000000000000000008152fd5b5080511515611f73565b5073ffffffffffffffffffffffffffffffffffffffff83511615611f6c565b503461013c5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261013c576004359067ffffffffffffffff821161013c573660238301121561013c5781600401356122ee81612b25565b926122fc6040519485612a13565b818452602460606020860193028201019036821161165357602401915b81831061249a5750505061232b613280565b805b825181101561249657612340818461301d565b5167ffffffffffffffff612354838661301d565b51511690811561246a57907fd5ad72bc37dc7a80a8b9b9df20500046fd7341adb1be2258a540466fdd7dcef5606060019493838752600660205260ff6040882061242b604060208501519483547fffffff0000000000000000000000000000000000000000ffffffffffffffffff7cffffffffffffffffffffffffffffffffffffffff0000000000000000008860481b1691161784550151151582907fffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffff68ff0000000000000000835492151560401b169116179055565b5473ffffffffffffffffffffffffffffffffffffffff6040519367ffffffffffffffff8316855216602084015260401c1615156040820152a20161232d565b602484837fc35aa79d000000000000000000000000000000000000000000000000000000008252600452fd5b5080f35b606083360312611653576040516060810181811067ffffffffffffffff821117612515576040526124ca84612b10565b8152602084013573ffffffffffffffffffffffffffffffffffffffff81168103610f6957918160609360208094015261250560408701612b3d565b6040820152815201920191612319565b6024867f4e487b710000000000000000000000000000000000000000000000000000000081526041600452fd5b503461013c5760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261013c5761257a612af4565b60243567ffffffffffffffff81116116575760a07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc8236030112611657576040517f2cbc26bb00000000000000000000000000000000000000000000000000000000815277ffffffffffffffff000000000000000000000000000000008360801b16600482015260208160248173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000165afa90811561277b578491612741575b5061270b576126ad9160209173ffffffffffffffffffffffffffffffffffffffff60025416906040518095819482937fd8694ccd0000000000000000000000000000000000000000000000000000000084526004019060048401612cc8565b03915afa9081156127005782916126ca575b602082604051908152f35b90506020813d6020116126f8575b816126e560209383612a13565b810103126112d6576020915051386126bf565b3d91506126d8565b6040513d84823e3d90fd5b60248367ffffffffffffffff847ffdbd6a7200000000000000000000000000000000000000000000000000000000835216600452fd5b90506020813d602011612773575b8161275c60209383612a13565b810103126116535761276d90612c2c565b3861264e565b3d915061274f565b6040513d86823e3d90fd5b503461013c57807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261013c57506117586040516127c7604082612a13565b601081527f4f6e52616d7020312e362e302d646576000000000000000000000000000000006020820152604051918291602083526020830190612ab1565b9050346112d657817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126112d65780612841606092612990565b8281528260208201528260408201520152608060405161286081612990565b67ffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016815273ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016602082015273ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016604082015273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000166060820152611a90604051809273ffffffffffffffffffffffffffffffffffffffff6060809267ffffffffffffffff8151168552826020820151166020860152826040820151166040860152015116910152565b6080810190811067ffffffffffffffff8211176129ac57604052565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60a0810190811067ffffffffffffffff8211176129ac57604052565b6040810190811067ffffffffffffffff8211176129ac57604052565b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff8211176129ac57604052565b67ffffffffffffffff81116129ac57601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b60005b838110612aa15750506000910152565b8181015183820152602001612a91565b907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f602093612aed81518092818752878088019101612a8e565b0116010190565b6004359067ffffffffffffffff82168203612b0b57565b600080fd5b359067ffffffffffffffff82168203612b0b57565b67ffffffffffffffff81116129ac5760051b60200190565b35908115158203612b0b57565b6004359073ffffffffffffffffffffffffffffffffffffffff82168203612b0b57565b6064359073ffffffffffffffffffffffffffffffffffffffff82168203612b0b57565b359073ffffffffffffffffffffffffffffffffffffffff82168203612b0b57565b9181601f84011215612b0b5782359167ffffffffffffffff8311612b0b576020808501948460051b010111612b0b57565b906020808351928381520192019060005b818110612c005750505090565b825173ffffffffffffffffffffffffffffffffffffffff16845260209384019390920191600101612bf3565b51908115158203612b0b57565b90357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe182360301811215612b0b57016020813591019167ffffffffffffffff8211612b0b578136038313612b0b57565b601f82602094937fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0938186528686013760008582860101520116010190565b9067ffffffffffffffff9093929316815260406020820152612d3e612d01612cf08580612c39565b60a0604086015260e0850191612c89565b612d0e6020860186612c39565b907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0858403016060860152612c89565b9060408401357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe185360301811215612b0b5784016020813591019267ffffffffffffffff8211612b0b578160061b36038413612b0b578281037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0016080840152818152602001929060005b818110612e3f57505050612e0c8473ffffffffffffffffffffffffffffffffffffffff612dfc6060612e3c979801612b90565b1660a08401526080810190612c39565b9160c07fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc082860301910152612c89565b90565b90919360408060019273ffffffffffffffffffffffffffffffffffffffff612e6689612b90565b16815260208881013590820152019501929101612dc9565b73ffffffffffffffffffffffffffffffffffffffff604051917fbbe4f6db00000000000000000000000000000000000000000000000000000000835216600482015260208160248173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000165afa908115612f8b57600091612f28575b5073ffffffffffffffffffffffffffffffffffffffff1690565b6020813d602011612f83575b81612f4160209383612a13565b810103126112d657519073ffffffffffffffffffffffffffffffffffffffff8216820361013c575073ffffffffffffffffffffffffffffffffffffffff612f0e565b3d9150612f34565b6040513d6000823e3d90fd5b3573ffffffffffffffffffffffffffffffffffffffff81168103612b0b5790565b9080601f83011215612b0b578135612fcf81612b25565b92612fdd6040519485612a13565b81845260208085019260051b820101928311612b0b57602001905b8282106130055750505090565b6020809161301284612b90565b815201910190612ff8565b80518210156130315760209160051b010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe181360301821215612b0b570180359067ffffffffffffffff8211612b0b57602001918136038313612b0b57565b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe181360301821215612b0b570180359067ffffffffffffffff8211612b0b57602001918160061b36038313612b0b57565b60405190613112826129db565b6060608083600081528260208201528260408201526000838201520152565b92919261313d82612a54565b9161314b6040519384612a13565b829481845281830111612b0b578281602093846000960137010152565b81601f82011215612b0b57805161317e81612a54565b9261318c6040519485612a13565b81845260208284010111612b0b57612e3c9160208085019101612a8e565b9080602083519182815201916020808360051b8301019401926000915b8383106131d657505050505090565b9091929394602080613271837fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0866001960301875289519073ffffffffffffffffffffffffffffffffffffffff825116815260806132566132448685015160a08886015260a0850190612ab1565b60408501518482036040860152612ab1565b92606081015160608401520151906080818403910152612ab1565b970193019301919392906131c7565b73ffffffffffffffffffffffffffffffffffffffff6001541633036132a157565b7f2b5c74de0000000000000000000000000000000000000000000000000000000060005260046000fd5b80548210156130315760005260206000200190600090565b600082815260018201602052604090205461336d57805490680100000000000000008210156129ac57826133566133218460018096018555846132cb565b81939154907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9060031b92831b921b19161790565b905580549260005201602052604060002055600190565b5050600090565b90600182019181600052826020526040600020548015156000146134fd577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81018181116134ce578254907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82019182116134ce57818103613497575b50505080548015613468577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff019061342982826132cb565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82549160031b1b191690555560005260205260006040812055600190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b6134b76134a761332193866132cb565b90549060031b1c928392866132cb565b9055600052836020526040600020553880806133f1565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b50505050600090565b91929015613581575081511561351a575090565b3b156135235790565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152fd5b8251909150156135945750805190602001fd5b6135d2906040519182917f08c379a0000000000000000000000000000000000000000000000000000000008352602060048401526024830190612ab1565b0390fdfea164736f6c634300081a000a", + Bin: "0x6101006040523480156200001257600080fd5b506040516200409f3803806200409f833981016040819052620000359162000709565b336000816200005757604051639b15e16f60e01b815260040160405180910390fd5b600180546001600160a01b0319166001600160a01b03848116919091179091558116156200008a576200008a816200014f565b505082516001600160401b03161580620000af575060208301516001600160a01b0316155b80620000c6575060408301516001600160a01b0316155b80620000dd575060608301516001600160a01b0316155b15620000fc576040516306b7c75960e31b815260040160405180910390fd5b82516001600160401b031660805260208301516001600160a01b0390811660a0526040840151811660c05260608401511660e0526200013b82620001c9565b620001468162000378565b5050506200080a565b336001600160a01b038216036200017957604051636d6c4ee560e11b815260040160405180910390fd5b600080546001600160a01b0319166001600160a01b03838116918217835560015460405192939116917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b80516001600160a01b03161580620001ec575060608101516001600160a01b0316155b80620001f9575080602001515b1562000218576040516306b7c75960e31b815260040160405180910390fd5b8051600280546020808501511515600160a01b026001600160a81b03199092166001600160a01b039485161791909117909155604080840151600380549185166001600160a01b0319928316179055606080860151600480549187169184169190911790556080808701516005805491881691909416179092558251808301845291516001600160401b0316825260a05185169382019390935260c05184168183015260e05190931691830191909152517fc7372d2d886367d7bb1b0e0708a5436f2c91d6963de210eb2dc1ec2ecd6d21f1916200036d91849082516001600160401b031681526020808401516001600160a01b03908116828401526040858101518216818501526060958601518216868501528451821660808086019190915292850151151560a0850152840151811660c084015293830151841660e0830152909101519091166101008201526101200190565b60405180910390a150565b60005b8151811015620004cb5760008282815181106200039c576200039c620007f4565b602002602001015190506000838381518110620003bd57620003bd620007f4565b6020026020010151600001519050806001600160401b0316600003620004055760405163c35aa79d60e01b81526001600160401b038216600482015260240160405180910390fd5b6001600160401b0381811660008181526006602090815260409182902086820151815488850151600160401b600160e81b031990911669010000000000000000006001600160a01b0390931692830260ff60401b19161768010000000000000000911515820217808455855197811688529387019190915260ff920491909116151591840191909152917fd5ad72bc37dc7a80a8b9b9df20500046fd7341adb1be2258a540466fdd7dcef59060600160405180910390a25050508060010190506200037b565b5050565b634e487b7160e01b600052604160045260246000fd5b604051606081016001600160401b03811182821017156200050a576200050a620004cf565b60405290565b604051601f8201601f191681016001600160401b03811182821017156200053b576200053b620004cf565b604052919050565b80516001600160401b03811681146200055b57600080fd5b919050565b6001600160a01b03811681146200057657600080fd5b50565b805180151581146200055b57600080fd5b600060a082840312156200059d57600080fd5b60405160a081016001600160401b0381118282101715620005c257620005c2620004cf565b80604052508091508251620005d78162000560565b8152620005e76020840162000579565b60208201526040830151620005fc8162000560565b60408201526060830151620006118162000560565b60608201526080830151620006268162000560565b6080919091015292915050565b600082601f8301126200064557600080fd5b815160206001600160401b03821115620006635762000663620004cf565b62000673818360051b0162000510565b828152606092830285018201928282019190878511156200069357600080fd5b8387015b85811015620006fc5781818a031215620006b15760008081fd5b620006bb620004e5565b620006c68262000543565b815285820151620006d78162000560565b818701526040620006ea83820162000579565b90820152845292840192810162000697565b5090979650505050505050565b60008060008385036101408112156200072157600080fd5b60808112156200073057600080fd5b50604051608081016001600160401b038082118383101715620007575762000757620004cf565b81604052620007668762000543565b8352602087015191506200077a8262000560565b81602084015260408701519150620007928262000560565b81604084015260608701519150620007aa8262000560565b816060840152829550620007c288608089016200058a565b9450610120870151925080831115620007da57600080fd5b5050620007ea8682870162000633565b9150509250925092565b634e487b7160e01b600052603260045260246000fd5b60805160a05160c05160e05161381c62000883600039600081816101fc015281816107670152611ac40152600081816101c0015281816114b90152611a9d015260008181610184015281816105a50152611a7301526000818161015401528181611040015281816115d60152611a4f015261381c6000f3fe608060405234801561001057600080fd5b506004361061011b5760003560e01c80637437ff9f116100b2578063972b461211610081578063df0aa9e911610066578063df0aa9e9146104fb578063f2fde38b1461050e578063fbca3b741461052157600080fd5b8063972b4612146104c7578063c9b146b3146104e857600080fd5b80637437ff9f146103cb57806379ba5097146104755780638da5cb5b1461047d5780639041be3d1461049b57600080fd5b806327e936f1116100ee57806327e936f1146102ce57806348a98aa4146102e15780635cb80c5d146103195780636def4ce71461032c57600080fd5b806306285c6914610120578063181f5a771461024f57806320487ded146102985780632716072b146102b9575b600080fd5b61023960408051608081018252600080825260208201819052918101829052606081019190915260405180608001604052807f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16815250905090565b6040516102469190612589565b60405180910390f35b61028b6040518060400160405280601081526020017f4f6e52616d7020312e362e302d6465760000000000000000000000000000000081525081565b604051610246919061264e565b6102ab6102a636600461268f565b610541565b604051908152602001610246565b6102cc6102c73660046127fd565b6106fa565b005b6102cc6102dc3660046128eb565b61070e565b6102f46102ef366004612983565b61071f565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610246565b6102cc610327366004612a08565b6107d4565b61038f61033a366004612a4a565b67ffffffffffffffff9081166000908152600660205260409020549081169168010000000000000000820460ff16916901000000000000000000900473ffffffffffffffffffffffffffffffffffffffff1690565b6040805167ffffffffffffffff9094168452911515602084015273ffffffffffffffffffffffffffffffffffffffff1690820152606001610246565b6104686040805160a081018252600080825260208201819052918101829052606081018290526080810191909152506040805160a08101825260025473ffffffffffffffffffffffffffffffffffffffff80821683527401000000000000000000000000000000000000000090910460ff161515602083015260035481169282019290925260045482166060820152600554909116608082015290565b6040516102469190612a67565b6102cc610956565b60015473ffffffffffffffffffffffffffffffffffffffff166102f4565b6104ae6104a9366004612a4a565b610a24565b60405167ffffffffffffffff9091168152602001610246565b6104da6104d5366004612a4a565b610a4d565b604051610246929190612b12565b6102cc6104f6366004612a08565b610a91565b6102ab610509366004612b2d565b610dad565b6102cc61051c366004612b99565b6116bb565b61053461052f366004612a4a565b6116cc565b6040516102469190612bb6565b6040517f2cbc26bb00000000000000000000000000000000000000000000000000000000815277ffffffffffffffff00000000000000000000000000000000608084901b16600482015260009073ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001690632cbc26bb90602401602060405180830381865afa1580156105ec573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106109190612bc9565b15610658576040517ffdbd6a7200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff841660048201526024015b60405180910390fd5b6002546040517fd8694ccd00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091169063d8694ccd906106b09086908690600401612ce8565b602060405180830381865afa1580156106cd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106f19190612e31565b90505b92915050565b610702611700565b61070b81611753565b50565b610716611700565b61070b816118f6565b6040517fbbe4f6db00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff82811660048301526000917f00000000000000000000000000000000000000000000000000000000000000009091169063bbe4f6db90602401602060405180830381865afa1580156107b0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106f19190612e4a565b60045473ffffffffffffffffffffffffffffffffffffffff1660005b8281101561095057600084848381811061080c5761080c612e67565b90506020020160208101906108219190612b99565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015290915060009073ffffffffffffffffffffffffffffffffffffffff8316906370a0823190602401602060405180830381865afa158015610891573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108b59190612e31565b90508015610946576108de73ffffffffffffffffffffffffffffffffffffffff83168583611b26565b8173ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f508d7d183612c18fc339b42618912b9fa3239f631dd7ec0671f950200a0fa66e8360405161093d91815260200190565b60405180910390a35b50506001016107f0565b50505050565b60005473ffffffffffffffffffffffffffffffffffffffff1633146109a7576040517f02b543c600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000008082163390811790935560008054909116815560405173ffffffffffffffffffffffffffffffffffffffff909216929183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b67ffffffffffffffff80821660009081526006602052604081205490916106f491166001612ec5565b67ffffffffffffffff8116600090815260066020526040812080546060916801000000000000000090910460ff1690610a8890600101611bb3565b91509150915091565b60015473ffffffffffffffffffffffffffffffffffffffff163314610b015760055473ffffffffffffffffffffffffffffffffffffffff163314610b01576040517f905d7d9b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b81811015610da8576000838383818110610b2057610b20612e67565b9050602002810190610b329190612ee6565b610b3b90612f97565b805167ffffffffffffffff1660009081526006602090815260409182902090830151815490151568010000000000000000027fffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffff90911617815590820151519192509015610cfb57816020015115610cba5760005b826040015151811015610c6a57600083604001518281518110610bd457610bd4612e67565b60200260200101519050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603610c535783516040517f463258ff00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff909116600482015260240161064f565b610c606001840182611bc7565b5050600101610baf565b50816000015167ffffffffffffffff167f330939f6eafe8bb516716892fe962ff19770570838686e6579dbc1cc51fc32818360400151604051610cad9190612bb6565b60405180910390a2610cfb565b81516040517f463258ff00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff909116600482015260240161064f565b60005b826060015151811015610d4757610d3e83606001518281518110610d2457610d24612e67565b602002602001015183600101611be990919063ffffffff16565b50600101610cfe565b5060608201515115610d9e57816000015167ffffffffffffffff167fc237ec1921f855ccd5e9a5af9733f2d58943a5a8501ec5988e305d7a4d4215868360600151604051610d959190612bb6565b60405180910390a25b5050600101610b04565b505050565b60025460009074010000000000000000000000000000000000000000900460ff1615610e05576040517f3ee5aeb500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167401000000000000000000000000000000000000000017905567ffffffffffffffff8516600090815260066020526040902073ffffffffffffffffffffffffffffffffffffffff8316610eaa576040517fa4ec747900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805468010000000000000000900460ff1615610f1b57610ecd6001820184611c0b565b610f1b576040517fd0d2597600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8416600482015260240161064f565b80546901000000000000000000900473ffffffffffffffffffffffffffffffffffffffff163314610f78576040517f1c0a352900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60035473ffffffffffffffffffffffffffffffffffffffff16801561101e576040517fe0a0e50600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff82169063e0a0e50690610feb908a908a90600401612ce8565b600060405180830381600087803b15801561100557600080fd5b505af1158015611019573d6000803e3d6000fd5b505050505b50604080516101c081019091526000610120820181815267ffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000811661014085015289811661016085015284549293928392916101808401918791879161108c9116613048565b91906101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905567ffffffffffffffff168152602001600067ffffffffffffffff1681525081526020018573ffffffffffffffffffffffffffffffffffffffff168152602001878060200190611100919061306f565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250505090825250602001611144888061306f565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920182905250938552505060408051602081810183529381529284019290925250016111a06080890160608a01612b99565b73ffffffffffffffffffffffffffffffffffffffff168152602001868152602001600081526020018780604001906111d891906130d4565b905067ffffffffffffffff8111156111f2576111f26126df565b60405190808252806020026020018201604052801561126b57816020015b6112586040518060a00160405280600073ffffffffffffffffffffffffffffffffffffffff168152602001606081526020016060815260200160008152602001606081525090565b8152602001906001900390816112105790505b5090529050600061127f60408801886130d4565b808060200260200160405190810160405280939291908181526020016000905b828210156112cb576112bc6040830286013681900381019061313c565b8152602001906001019061129f565b5050505050905060005b6112e260408901896130d4565b905081101561137c5761135282828151811061130057611300612e67565b60209081029190910101518a6113168b8061306f565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508c9250611c3a915050565b836101000151828151811061136957611369612e67565b60209081029190910101526001016112d5565b50600254600090606090819073ffffffffffffffffffffffffffffffffffffffff1663430d138c8c6113b360808e018e8601612b99565b8c8e80608001906113c4919061306f565b8b61010001518b6040518863ffffffff1660e01b81526004016113ed9796959493929190613259565b600060405180830381865afa15801561140a573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201604052611450919081019061338b565b60e0890193909352909450925090508261152b576040517fea458c0c00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8c16600482015273ffffffffffffffffffffffffffffffffffffffff89811660248301527f0000000000000000000000000000000000000000000000000000000000000000169063ea458c0c906044016020604051808303816000875af1158015611502573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611526919061347e565b61152e565b60005b855167ffffffffffffffff909116608091820152850182905260005b856101000151518110156115a05781818151811061156a5761156a612e67565b6020026020010151866101000151828151811061158957611589612e67565b60209081029190910101516080015260010161154a565b50604080517f130ac867e79e2789f923760a88743d292acdf7002139a588206e2260f73f7321602082015267ffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000811692820192909252908c16606082015230608082015261163090869060a00160405160208183030381529060405280519060200120611f51565b85515284516060015160405167ffffffffffffffff918216918d16907f192442a2b2adb6a7948f097023cb6b57d29d3a7a5dd33e6666d33c39cc456f329061167990899061349b565b60405180910390a35050600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff169055505051519150505b949350505050565b6116c3611700565b61070b816120a3565b60606040517f9e7177c800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60015473ffffffffffffffffffffffffffffffffffffffff163314611751576040517f2b5c74de00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b565b60005b81518110156118f257600082828151811061177357611773612e67565b60200260200101519050600083838151811061179157611791612e67565b60200260200101516000015190508067ffffffffffffffff166000036117ef576040517fc35aa79d00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8216600482015260240161064f565b67ffffffffffffffff818116600081815260066020908152604091829020868201518154888501517fffffff000000000000000000000000000000000000000000ffffffffffffffff909116690100000000000000000073ffffffffffffffffffffffffffffffffffffffff9093169283027fffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffff161768010000000000000000911515820217808455855197811688529387019190915260ff920491909116151591840191909152917fd5ad72bc37dc7a80a8b9b9df20500046fd7341adb1be2258a540466fdd7dcef59060600160405180910390a2505050806001019050611756565b5050565b805173ffffffffffffffffffffffffffffffffffffffff1615806119325750606081015173ffffffffffffffffffffffffffffffffffffffff16155b8061193e575080602001515b15611975576040517f35be3ac800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805160028054602080850151151574010000000000000000000000000000000000000000027fffffffffffffffffffffff00000000000000000000000000000000000000000090921673ffffffffffffffffffffffffffffffffffffffff9485161791909117909155604080840151600380549185167fffffffffffffffffffffffff0000000000000000000000000000000000000000928316179055606080860151600480549187169184169190911790556080808701516005805491881691909416179092558251918201835267ffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001682527f00000000000000000000000000000000000000000000000000000000000000008516938201939093527f00000000000000000000000000000000000000000000000000000000000000008416818301527f000000000000000000000000000000000000000000000000000000000000000090931691830191909152517fc7372d2d886367d7bb1b0e0708a5436f2c91d6963de210eb2dc1ec2ecd6d21f191611b1b9184906135f3565b60405180910390a150565b6040805173ffffffffffffffffffffffffffffffffffffffff8416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb00000000000000000000000000000000000000000000000000000000179052610da8908490612167565b60606000611bc083612273565b9392505050565b60006106f18373ffffffffffffffffffffffffffffffffffffffff84166122cf565b60006106f18373ffffffffffffffffffffffffffffffffffffffff841661231e565b73ffffffffffffffffffffffffffffffffffffffff8116600090815260018301602052604081205415156106f1565b611c826040518060a00160405280600073ffffffffffffffffffffffffffffffffffffffff168152602001606081526020016060815260200160008152602001606081525090565b8460200151600003611cc0576040517f5cf0444900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000611cd085876000015161071f565b905073ffffffffffffffffffffffffffffffffffffffff81161580611da057506040517f01ffc9a70000000000000000000000000000000000000000000000000000000081527faff2afbf00000000000000000000000000000000000000000000000000000000600482015273ffffffffffffffffffffffffffffffffffffffff8216906301ffc9a790602401602060405180830381865afa158015611d7a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d9e9190612bc9565b155b15611df25785516040517fbf16aab600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff909116600482015260240161064f565b60008173ffffffffffffffffffffffffffffffffffffffff16639a4575b96040518060a001604052808881526020018967ffffffffffffffff1681526020018773ffffffffffffffffffffffffffffffffffffffff1681526020018a6020015181526020018a6000015173ffffffffffffffffffffffffffffffffffffffff168152506040518263ffffffff1660e01b8152600401611e9191906136a1565b6000604051808303816000875af1158015611eb0573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201604052611ef69190810190613717565b6040805160a08101825273ffffffffffffffffffffffffffffffffffffffff90941684528151602080860191909152918201518482015288820151606085015280519182019052600081526080830152509050949350505050565b60008060001b8284602001518560000151606001518660000151608001518760a001518860c00151604051602001611fcf95949392919073ffffffffffffffffffffffffffffffffffffffff958616815267ffffffffffffffff94851660208201529290931660408301529092166060830152608082015260a00190565b6040516020818303038152906040528051906020012085606001518051906020012086604001518051906020012087610100015160405160200161201391906137a8565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815282825280516020918201206080808d0151805190840120928501999099529183019690965260608201949094529485019190915260a084015260c083015260e08201526101000160405160208183030381529060405280519060200120905092915050565b3373ffffffffffffffffffffffffffffffffffffffff8216036120f2576040517fdad89dca00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff838116918217835560015460405192939116917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b60006121c9826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff166124189092919063ffffffff16565b805190915015610da857808060200190518101906121e79190612bc9565b610da8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f74207375636365656400000000000000000000000000000000000000000000606482015260840161064f565b6060816000018054806020026020016040519081016040528092919081815260200182805480156122c357602002820191906000526020600020905b8154815260200190600101908083116122af575b50505050509050919050565b6000818152600183016020526040812054612316575081546001818101845560008481526020808220909301849055845484825282860190935260409020919091556106f4565b5060006106f4565b600081815260018301602052604081205480156124075760006123426001836137bb565b8554909150600090612356906001906137bb565b90508082146123bb57600086600001828154811061237657612376612e67565b906000526020600020015490508087600001848154811061239957612399612e67565b6000918252602080832090910192909255918252600188019052604090208390555b85548690806123cc576123cc6137ce565b6001900381819060005260206000200160009055905585600101600086815260200190815260200160002060009055600193505050506106f4565b60009150506106f4565b5092915050565b60606116b38484600085856000808673ffffffffffffffffffffffffffffffffffffffff16858760405161244c91906137fd565b60006040518083038185875af1925050503d8060008114612489576040519150601f19603f3d011682016040523d82523d6000602084013e61248e565b606091505b509150915061249f878383876124aa565b979650505050505050565b606083156125405782516000036125395773ffffffffffffffffffffffffffffffffffffffff85163b612539576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640161064f565b50816116b3565b6116b383838151156125555781518083602001fd5b806040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161064f919061264e565b608081016106f4828467ffffffffffffffff8151168252602081015173ffffffffffffffffffffffffffffffffffffffff808216602085015280604084015116604085015280606084015116606085015250505050565b60005b838110156125fb5781810151838201526020016125e3565b50506000910152565b6000815180845261261c8160208601602086016125e0565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006106f16020830184612604565b67ffffffffffffffff8116811461070b57600080fd5b600060a0828403121561268957600080fd5b50919050565b600080604083850312156126a257600080fd5b82356126ad81612661565b9150602083013567ffffffffffffffff8111156126c957600080fd5b6126d585828601612677565b9150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040516060810167ffffffffffffffff81118282101715612731576127316126df565b60405290565b6040805190810167ffffffffffffffff81118282101715612731576127316126df565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156127a1576127a16126df565b604052919050565b600067ffffffffffffffff8211156127c3576127c36126df565b5060051b60200190565b73ffffffffffffffffffffffffffffffffffffffff8116811461070b57600080fd5b801515811461070b57600080fd5b6000602080838503121561281057600080fd5b823567ffffffffffffffff81111561282757600080fd5b8301601f8101851361283857600080fd5b803561284b612846826127a9565b61275a565b8181526060918202830184019184820191908884111561286a57600080fd5b938501935b838510156128cf5780858a0312156128875760008081fd5b61288f61270e565b853561289a81612661565b8152858701356128a9816127cd565b818801526040868101356128bc816127ef565b908201528352938401939185019161286f565b50979650505050505050565b80356128e6816127cd565b919050565b600060a082840312156128fd57600080fd5b60405160a0810181811067ffffffffffffffff82111715612920576129206126df565b604052823561292e816127cd565b8152602083013561293e816127ef565b60208201526040830135612951816127cd565b60408201526060830135612964816127cd565b60608201526080830135612977816127cd565b60808201529392505050565b6000806040838503121561299657600080fd5b82356129a181612661565b915060208301356129b1816127cd565b809150509250929050565b60008083601f8401126129ce57600080fd5b50813567ffffffffffffffff8111156129e657600080fd5b6020830191508360208260051b8501011115612a0157600080fd5b9250929050565b60008060208385031215612a1b57600080fd5b823567ffffffffffffffff811115612a3257600080fd5b612a3e858286016129bc565b90969095509350505050565b600060208284031215612a5c57600080fd5b8135611bc081612661565b60a081016106f4828473ffffffffffffffffffffffffffffffffffffffff808251168352602082015115156020840152806040830151166040840152806060830151166060840152806080830151166080840152505050565b60008151808452602080850194506020840160005b83811015612b0757815173ffffffffffffffffffffffffffffffffffffffff1687529582019590820190600101612ad5565b509495945050505050565b82151581526040602082015260006116b36040830184612ac0565b60008060008060808587031215612b4357600080fd5b8435612b4e81612661565b9350602085013567ffffffffffffffff811115612b6a57600080fd5b612b7687828801612677565b935050604085013591506060850135612b8e816127cd565b939692955090935050565b600060208284031215612bab57600080fd5b8135611bc0816127cd565b6020815260006106f16020830184612ac0565b600060208284031215612bdb57600080fd5b8151611bc0816127ef565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112612c1b57600080fd5b830160208101925035905067ffffffffffffffff811115612c3b57600080fd5b803603821315612a0157600080fd5b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b8183526000602080850194508260005b85811015612b07578135612cb6816127cd565b73ffffffffffffffffffffffffffffffffffffffff168752818301358388015260409687019690910190600101612ca3565b600067ffffffffffffffff808516835260406020840152612d098485612be6565b60a06040860152612d1e60e086018284612c4a565b915050612d2e6020860186612be6565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc080878503016060880152612d64848385612c4a565b9350604088013592507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1883603018312612d9d57600080fd5b60209288019283019235915084821115612db657600080fd5b8160061b3603831315612dc857600080fd5b80878503016080880152612ddd848385612c93565b9450612deb606089016128db565b73ffffffffffffffffffffffffffffffffffffffff811660a08901529350612e166080890189612be6565b94509250808786030160c0880152505061249f838383612c4a565b600060208284031215612e4357600080fd5b5051919050565b600060208284031215612e5c57600080fd5b8151611bc0816127cd565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b67ffffffffffffffff81811683821601908082111561241157612411612e96565b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81833603018112612f1a57600080fd5b9190910192915050565b600082601f830112612f3557600080fd5b81356020612f45612846836127a9565b8083825260208201915060208460051b870101935086841115612f6757600080fd5b602086015b84811015612f8c578035612f7f816127cd565b8352918301918301612f6c565b509695505050505050565b600060808236031215612fa957600080fd5b6040516080810167ffffffffffffffff8282108183111715612fcd57612fcd6126df565b8160405284359150612fde82612661565b908252602084013590612ff0826127ef565b816020840152604085013591508082111561300a57600080fd5b61301636838701612f24565b6040840152606085013591508082111561302f57600080fd5b5061303c36828601612f24565b60608301525092915050565b600067ffffffffffffffff80831681810361306557613065612e96565b6001019392505050565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18436030181126130a457600080fd5b83018035915067ffffffffffffffff8211156130bf57600080fd5b602001915036819003821315612a0157600080fd5b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261310957600080fd5b83018035915067ffffffffffffffff82111561312457600080fd5b6020019150600681901b3603821315612a0157600080fd5b60006040828403121561314e57600080fd5b613156612737565b8235613161816127cd565b81526020928301359281019290925250919050565b600082825180855260208086019550808260051b84010181860160005b8481101561324c577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0868403018952815160a073ffffffffffffffffffffffffffffffffffffffff82511685528582015181878701526131f582870182612604565b9150506040808301518683038288015261320f8382612604565b925050506060808301518187015250608080830151925085820381870152506132388183612604565b9a86019a9450505090830190600101613193565b5090979650505050505050565b67ffffffffffffffff881681526000602073ffffffffffffffffffffffffffffffffffffffff808a1682850152604089604086015260c060608601526132a360c08601898b612c4a565b85810360808701526132b58189613176565b86810360a0880152875180825285890192509085019060005b818110156132f55783518051871684528701518784015292860192918401916001016132ce565b50909e9d5050505050505050505050505050565b600082601f83011261331a57600080fd5b815167ffffffffffffffff811115613334576133346126df565b61336560207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8401160161275a565b81815284602083860101111561337a57600080fd5b6116b38260208301602087016125e0565b600080600080608085870312156133a157600080fd5b845193506020808601516133b4816127ef565b604087015190945067ffffffffffffffff808211156133d257600080fd5b6133de89838a01613309565b945060608801519150808211156133f457600080fd5b818801915088601f83011261340857600080fd5b8151613416612846826127a9565b81815260059190911b8301840190848101908b83111561343557600080fd5b8585015b8381101561346d578051858111156134515760008081fd5b61345f8e89838a0101613309565b845250918601918601613439565b50989b979a50959850505050505050565b60006020828403121561349057600080fd5b8151611bc081612661565b602081526134ec60208201835180518252602081015167ffffffffffffffff808216602085015280604084015116604085015280606084015116606085015280608084015116608085015250505050565b6000602083015161351560c084018273ffffffffffffffffffffffffffffffffffffffff169052565b5060408301516101a08060e08501526135326101c0850183612604565b915060608501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe06101008187860301818801526135708584612604565b945060808801519250818786030161012088015261358e8584612604565b945060a088015192506135ba61014088018473ffffffffffffffffffffffffffffffffffffffff169052565b60c088015161016088015260e08801516101808801528701518685039091018387015290506135e98382613176565b9695505050505050565b610120810161364b828567ffffffffffffffff8151168252602081015173ffffffffffffffffffffffffffffffffffffffff808216602085015280604084015116604085015280606084015116606085015250505050565b825173ffffffffffffffffffffffffffffffffffffffff9081166080848101919091526020850151151560a08501526040850151821660c08501526060850151821660e085015284015116610100830152611bc0565b602081526000825160a060208401526136bd60c0840182612604565b905067ffffffffffffffff6020850151166040840152604084015173ffffffffffffffffffffffffffffffffffffffff8082166060860152606086015160808601528060808701511660a086015250508091505092915050565b60006020828403121561372957600080fd5b815167ffffffffffffffff8082111561374157600080fd5b908301906040828603121561375557600080fd5b61375d612737565b82518281111561376c57600080fd5b61377887828601613309565b82525060208301518281111561378d57600080fd5b61379987828601613309565b60208301525095945050505050565b6020815260006106f16020830184613176565b818103818111156106f4576106f4612e96565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b60008251612f1a8184602087016125e056fea164736f6c6343000818000a", } var OnRampABI = OnRampMetaData.ABI diff --git a/core/gethwrappers/ccip/generated/ping_pong_demo/ping_pong_demo.go b/core/gethwrappers/ccip/generated/ping_pong_demo/ping_pong_demo.go index a9b8b888fc4..2184e5926d0 100644 --- a/core/gethwrappers/ccip/generated/ping_pong_demo/ping_pong_demo.go +++ b/core/gethwrappers/ccip/generated/ping_pong_demo/ping_pong_demo.go @@ -45,7 +45,7 @@ type ClientEVMTokenAmount struct { var PingPongDemoMetaData = &bind.MetaData{ ABI: "[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"contractIERC20\",\"name\":\"feeToken\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"CannotTransferToSelf\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"}],\"name\":\"InvalidRouter\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MustBeProposedOwner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByOwner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OwnerCannotBeZero\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"isOutOfOrder\",\"type\":\"bool\"}],\"name\":\"OutOfOrderExecutionChange\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"pingPongCount\",\"type\":\"uint256\"}],\"name\":\"Ping\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"pingPongCount\",\"type\":\"uint256\"}],\"name\":\"Pong\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"sender\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structClient.EVMTokenAmount[]\",\"name\":\"destTokenAmounts\",\"type\":\"tuple[]\"}],\"internalType\":\"structClient.Any2EVMMessage\",\"name\":\"message\",\"type\":\"tuple\"}],\"name\":\"ccipReceive\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getCounterpartAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getCounterpartChainSelector\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getFeeToken\",\"outputs\":[{\"internalType\":\"contractIERC20\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getOutOfOrderExecution\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRouter\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"isPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"counterpartChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"counterpartAddress\",\"type\":\"address\"}],\"name\":\"setCounterpart\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"addr\",\"type\":\"address\"}],\"name\":\"setCounterpartAddress\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"}],\"name\":\"setCounterpartChainSelector\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bool\",\"name\":\"outOfOrderExecution\",\"type\":\"bool\"}],\"name\":\"setOutOfOrderExecution\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bool\",\"name\":\"pause\",\"type\":\"bool\"}],\"name\":\"setPaused\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"startPingPong\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"pure\",\"type\":\"function\"}]", - Bin: "0x60a0806040523461011f57604081611643803803809161001f828561015f565b83398101031261011f578051906001600160a01b0382169081830361011f57602001516001600160a01b038116929083900361011f57811561014957608052331561013857600180546001600160a01b031990811633179091556002805460ff60a01b19169055600380549091168317905560405163095ea7b360e01b81526004810191909152600019602482015290602090829060449082906000905af1801561012c576100ef575b6040516114aa908161019982396080518181816103df015281816105a00152610fd20152f35b6020813d602011610124575b816101086020938361015f565b8101031261011f57518015150361011f57386100c9565b600080fd5b3d91506100fb565b6040513d6000823e3d90fd5b639b15e16f60e01b60005260046000fd5b6335fdcccd60e21b600052600060045260246000fd5b601f909101601f19168101906001600160401b0382119082101761018257604052565b634e487b7160e01b600052604160045260246000fdfe608080604052600436101561001357600080fd5b60003560e01c90816301ffc9a7146111e05750806316c38b3c14611152578063181f5a77146110d15780631892b906146110415780632874d8bf14610cf25780632b6e5d6314610ca0578063665ed53714610bea57806379ba509714610b0157806385572ffb1461051c5780638da5cb5b146104ca5780639d2aede514610447578063ae90de5514610403578063b0f479a114610394578063b187bd2614610350578063b5a1101114610275578063bee518a41461022c578063ca709a25146101da5763f2fde38b146100e557600080fd5b346101d55760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101d55773ffffffffffffffffffffffffffffffffffffffff610131611312565b610139611452565b163381146101ab57807fffffffffffffffffffffffff0000000000000000000000000000000000000000600054161760005573ffffffffffffffffffffffffffffffffffffffff600154167fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae1278600080a3005b7fdad89dca0000000000000000000000000000000000000000000000000000000060005260046000fd5b600080fd5b346101d55760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101d557602073ffffffffffffffffffffffffffffffffffffffff60035416604051908152f35b346101d55760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101d557602067ffffffffffffffff60015460a01c16604051908152f35b346101d55760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101d5576102ac6112fb565b6024359073ffffffffffffffffffffffffffffffffffffffff82168092036101d5576102d6611452565b7fffffffff0000000000000000ffffffffffffffffffffffffffffffffffffffff7bffffffffffffffff00000000000000000000000000000000000000006001549260a01b169116176001557fffffffffffffffffffffffff00000000000000000000000000000000000000006002541617600255600080f35b346101d55760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101d557602060ff60025460a01c166040519015158152f35b346101d55760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101d557602060405173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b346101d55760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101d557602060ff60035460a01c166040519015158152f35b346101d55760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101d55773ffffffffffffffffffffffffffffffffffffffff610493611312565b61049b611452565b167fffffffffffffffffffffffff00000000000000000000000000000000000000006002541617600255600080f35b346101d55760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101d557602073ffffffffffffffffffffffffffffffffffffffff60015416604051908152f35b346101d55760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101d55760043567ffffffffffffffff81116101d55760a07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc82360301126101d55773ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016803303610ad3576000916040516105d681611335565b81600401358152602482013567ffffffffffffffff81168103610acb576020820152604482013567ffffffffffffffff8111610acb5761061c90600436918501016113dd565b6040820152606482013567ffffffffffffffff8111610acb5761064590600436918501016113dd565b916060820192835260848101359067ffffffffffffffff8211610acf57019036602383011215610acb57600482013567ffffffffffffffff8111610a9e5760208160051b0192610698604051948561139c565b818452602060048186019360061b8301010190368211610a9a57602401915b818310610a44575050506080015251602081805181010312610a4057602001519060ff60025460a01c16156106ea578280f35b60018201809211610a13576001828116036109e4577f48257dc961b6f792c2b78a080dacfed693b660960a702de21cee364e20270e2f6020604051848152a15b73ffffffffffffffffffffffffffffffffffffffff60025416906040519160208301526020825261075c60408361139c565b6040519260208401526020835261077460408461139c565b604051602093610784858361139c565b85825290918585936003546040519061079c82611380565b62030d40825286820160ff8260a01c1615158152604051927f181dcf1000000000000000000000000000000000000000000000000000000000898501525160248401525115156044830152604482526107f660648361139c565b6040519761080389611335565b88528688019586526040880192835273ffffffffffffffffffffffffffffffffffffffff6060890191168152608088019182526108c567ffffffffffffffff60015460a01c16966108946040519a8b997f96f4e9f9000000000000000000000000000000000000000000000000000000008b5260048b0152604060248b01525160a060448b015260e48a019061129c565b90517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffbc8983030160648a015261129c565b9251927fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffbc878203016084880152878085519283815201940190855b8181106109a757505050859392849273ffffffffffffffffffffffffffffffffffffffff61095f93511660a4850152517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffbc8483030160c485015261129c565b03925af1801561099c57610971578280f35b813d8311610995575b610984818361139c565b810103126109925781808280f35b80fd5b503d61097a565b6040513d85823e3d90fd5b8251805173ffffffffffffffffffffffffffffffffffffffff1687528a01518a8701528b998b99508d975060409096019590920191600101610900565b7f58b69f57828e6962d216502094c54f6562f3bf082ba758966c3454f9e37b15256020604051848152a161072a565b6024837f4e487b710000000000000000000000000000000000000000000000000000000081526011600452fd5b8280fd5b604083360312610a9a5760405190610a5b82611380565b83359073ffffffffffffffffffffffffffffffffffffffff82168203610a9657826020926040945282860135838201528152019201916106b7565b8980fd5b8780fd5b6024867f4e487b710000000000000000000000000000000000000000000000000000000081526041600452fd5b8480fd5b8580fd5b7fd7f73334000000000000000000000000000000000000000000000000000000006000523360045260246000fd5b346101d55760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101d55760005473ffffffffffffffffffffffffffffffffffffffff81163303610bc0577fffffffffffffffffffffffff00000000000000000000000000000000000000006001549133828416176001551660005573ffffffffffffffffffffffffffffffffffffffff3391167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0600080a3005b7f02b543c60000000000000000000000000000000000000000000000000000000060005260046000fd5b346101d55760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101d5576004358015158091036101d55760207f05a3fef9935c9013a24c6193df2240d34fcf6b0ebf8786b85efe8401d696cdd991610c52611452565b6003547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff74ff00000000000000000000000000000000000000008360a01b16911617600355604051908152a1005b346101d55760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101d557602073ffffffffffffffffffffffffffffffffffffffff60025416604051908152f35b346101d55760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101d557610d29611452565b7fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff600254166002557f48257dc961b6f792c2b78a080dacfed693b660960a702de21cee364e20270e2f602060405160018152a1600173ffffffffffffffffffffffffffffffffffffffff6002541660405190602082015260208152610daf60408261139c565b6040519082602083015260208252610dc860408361139c565b604051602092610dd8848361139c565b6000825260009461103c575b839060035460405190610df682611380565b62030d40825283820160ff8260a01c1615158152604051927f181dcf100000000000000000000000000000000000000000000000000000000086850152516024840152511515604483015260448252610e5060648361139c565b60405195610e5d87611335565b86528386019283526040860194855273ffffffffffffffffffffffffffffffffffffffff606087019116815260808601918252610f1f67ffffffffffffffff60015460a01c1693610eee6040519889967f96f4e9f90000000000000000000000000000000000000000000000000000000088526004880152604060248801525160a0604488015260e487019061129c565b90517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffbc86830301606487015261129c565b9451947fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffbc848203016084850152848087519283815201960190895b8181106110025750505093610fb89173ffffffffffffffffffffffffffffffffffffffff849596511660a4850152517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffbc8483030160c485015261129c565b03818673ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000165af1801561099c57610971578280f35b8251805173ffffffffffffffffffffffffffffffffffffffff16895287015187890152604090970196899689965090920191600101610f5a565b610de4565b346101d55760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101d5576110786112fb565b611080611452565b7fffffffff0000000000000000ffffffffffffffffffffffffffffffffffffffff7bffffffffffffffff00000000000000000000000000000000000000006001549260a01b16911617600155600080f35b346101d55760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101d55761114e6040805190611112818361139c565b601282527f50696e67506f6e6744656d6f20312e352e30000000000000000000000000000060208301525191829160208352602083019061129c565b0390f35b346101d55760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101d5576004358015158091036101d557611196611452565b7fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff74ff00000000000000000000000000000000000000006002549260a01b16911617600255600080f35b346101d55760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101d557600435907fffffffff0000000000000000000000000000000000000000000000000000000082168092036101d557817f85572ffb0000000000000000000000000000000000000000000000000000000060209314908115611272575b5015158152f35b7f01ffc9a7000000000000000000000000000000000000000000000000000000009150148361126b565b919082519283825260005b8481106112e65750507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8460006020809697860101520116010190565b806020809284010151828286010152016112a7565b6004359067ffffffffffffffff821682036101d557565b6004359073ffffffffffffffffffffffffffffffffffffffff821682036101d557565b60a0810190811067ffffffffffffffff82111761135157604052565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040810190811067ffffffffffffffff82111761135157604052565b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff82111761135157604052565b81601f820112156101d55780359067ffffffffffffffff82116113515760405192611430601f84017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0166020018561139c565b828452602083830101116101d557816000926020809301838601378301015290565b73ffffffffffffffffffffffffffffffffffffffff60015416330361147357565b7f2b5c74de0000000000000000000000000000000000000000000000000000000060005260046000fdfea164736f6c634300081a000a", + Bin: "0x60a06040523480156200001157600080fd5b50604051620014a8380380620014a88339810160408190526200003491620001ff565b336000836001600160a01b03811662000067576040516335fdcccd60e21b81526000600482015260240160405180910390fd5b6001600160a01b0390811660805282166200009557604051639b15e16f60e01b815260040160405180910390fd5b600180546001600160a01b0319166001600160a01b0384811691909117909155811615620000c857620000c8816200016c565b50506002805460ff60a01b19169055600380546001600160a01b0319166001600160a01b0383811691821790925560405163095ea7b360e01b8152918416600483015260001960248301529063095ea7b3906044016020604051808303816000875af11580156200013d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200016391906200023e565b50505062000269565b336001600160a01b038216036200019657604051636d6c4ee560e11b815260040160405180910390fd5b600080546001600160a01b0319166001600160a01b03838116918217835560015460405192939116917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6001600160a01b0381168114620001fc57600080fd5b50565b600080604083850312156200021357600080fd5b82516200022081620001e6565b60208401519092506200023381620001e6565b809150509250929050565b6000602082840312156200025157600080fd5b815180151581146200026257600080fd5b9392505050565b6080516112156200029360003960008181610295015281816106520152610a5901526112156000f3fe608060405234801561001057600080fd5b50600436106101365760003560e01c80638da5cb5b116100b2578063b187bd2611610081578063bee518a411610066578063bee518a4146102ef578063ca709a251461032d578063f2fde38b1461034b57600080fd5b8063b187bd26146102b9578063b5a11011146102dc57600080fd5b80638da5cb5b1461023f5780639d2aede51461025d578063ae90de5514610270578063b0f479a11461029357600080fd5b80632874d8bf11610109578063665ed537116100ee578063665ed5371461021157806379ba50971461022457806385572ffb1461022c57600080fd5b80632874d8bf146101ca5780632b6e5d63146101d257600080fd5b806301ffc9a71461013b57806316c38b3c14610163578063181f5a77146101785780631892b906146101b7575b600080fd5b61014e610149366004610c29565b61035e565b60405190151581526020015b60405180910390f35b610176610171366004610c72565b6103f7565b005b604080518082018252601281527f50696e67506f6e6744656d6f20312e352e3000000000000000000000000000006020820152905161015a9190610cf8565b6101766101c5366004610d28565b610449565b6101766104a4565b60025473ffffffffffffffffffffffffffffffffffffffff165b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161015a565b61017661021f366004610c72565b6104e0565b61017661056c565b61017661023a366004610d43565b61063a565b60015473ffffffffffffffffffffffffffffffffffffffff166101ec565b61017661026b366004610da2565b6106c3565b60035474010000000000000000000000000000000000000000900460ff1661014e565b7f00000000000000000000000000000000000000000000000000000000000000006101ec565b60025474010000000000000000000000000000000000000000900460ff1661014e565b6101766102ea366004610dbd565b610712565b60015474010000000000000000000000000000000000000000900467ffffffffffffffff1660405167ffffffffffffffff909116815260200161015a565b60035473ffffffffffffffffffffffffffffffffffffffff166101ec565b610176610359366004610da2565b6107b4565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f85572ffb0000000000000000000000000000000000000000000000000000000014806103f157507fffffffff0000000000000000000000000000000000000000000000000000000082167f01ffc9a700000000000000000000000000000000000000000000000000000000145b92915050565b6103ff6107c5565b6002805491151574010000000000000000000000000000000000000000027fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff909216919091179055565b6104516107c5565b6001805467ffffffffffffffff90921674010000000000000000000000000000000000000000027fffffffff0000000000000000ffffffffffffffffffffffffffffffffffffffff909216919091179055565b6104ac6107c5565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1690556104de6001610816565b565b6104e86107c5565b6003805482151574010000000000000000000000000000000000000000027fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff9091161790556040517f05a3fef9935c9013a24c6193df2240d34fcf6b0ebf8786b85efe8401d696cdd99061056190831515815260200190565b60405180910390a150565b60005473ffffffffffffffffffffffffffffffffffffffff1633146105bd576040517f02b543c600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000008082163390811790935560008054909116815560405173ffffffffffffffffffffffffffffffffffffffff909216929183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b3373ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016146106af576040517fd7f7333400000000000000000000000000000000000000000000000000000000815233600482015260240160405180910390fd5b6106c06106bb82610ff3565b610b0f565b50565b6106cb6107c5565b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b61071a6107c5565b6001805467ffffffffffffffff90931674010000000000000000000000000000000000000000027fffffffff0000000000000000ffffffffffffffffffffffffffffffffffffffff909316929092179091556002805473ffffffffffffffffffffffffffffffffffffffff9092167fffffffffffffffffffffffff0000000000000000000000000000000000000000909216919091179055565b6107bc6107c5565b6106c081610b65565b60015473ffffffffffffffffffffffffffffffffffffffff1633146104de576040517f2b5c74de00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80600116600103610859576040518181527f48257dc961b6f792c2b78a080dacfed693b660960a702de21cee364e20270e2f9060200160405180910390a161088d565b6040518181527f58b69f57828e6962d216502094c54f6562f3bf082ba758966c3454f9e37b15259060200160405180910390a15b6040805160a0810190915260025473ffffffffffffffffffffffffffffffffffffffff1660c08201526000908060e081016040516020818303038152906040528152602001836040516020016108e591815260200190565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190528152602001600060405190808252806020026020018201604052801561095f57816020015b60408051808201909152600080825260208201528152602001906001900390816109385790505b50815260035473ffffffffffffffffffffffffffffffffffffffff811660208084019190915260408051808201825262030d408082527401000000000000000000000000000000000000000090940460ff16151590830190815281516024810194909452511515604480850191909152815180850390910181526064909301815290820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f181dcf1000000000000000000000000000000000000000000000000000000000179052909101526001546040517f96f4e9f90000000000000000000000000000000000000000000000000000000081529192507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16916396f4e9f991610ac7917401000000000000000000000000000000000000000090910467ffffffffffffffff169085906004016110a0565b6020604051808303816000875af1158015610ae6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b0a91906111b5565b505050565b60008160600151806020019051810190610b2991906111b5565b60025490915074010000000000000000000000000000000000000000900460ff16610b6157610b61610b5c8260016111ce565b610816565b5050565b3373ffffffffffffffffffffffffffffffffffffffff821603610bb4576040517fdad89dca00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff838116918217835560015460405192939116917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b600060208284031215610c3b57600080fd5b81357fffffffff0000000000000000000000000000000000000000000000000000000081168114610c6b57600080fd5b9392505050565b600060208284031215610c8457600080fd5b81358015158114610c6b57600080fd5b6000815180845260005b81811015610cba57602081850181015186830182015201610c9e565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b602081526000610c6b6020830184610c94565b803567ffffffffffffffff81168114610d2357600080fd5b919050565b600060208284031215610d3a57600080fd5b610c6b82610d0b565b600060208284031215610d5557600080fd5b813567ffffffffffffffff811115610d6c57600080fd5b820160a08185031215610c6b57600080fd5b803573ffffffffffffffffffffffffffffffffffffffff81168114610d2357600080fd5b600060208284031215610db457600080fd5b610c6b82610d7e565b60008060408385031215610dd057600080fd5b610dd983610d0b565b9150610de760208401610d7e565b90509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff81118282101715610e4257610e42610df0565b60405290565b60405160a0810167ffffffffffffffff81118282101715610e4257610e42610df0565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715610eb257610eb2610df0565b604052919050565b600082601f830112610ecb57600080fd5b813567ffffffffffffffff811115610ee557610ee5610df0565b610f1660207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601610e6b565b818152846020838601011115610f2b57600080fd5b816020850160208301376000918101602001919091529392505050565b600082601f830112610f5957600080fd5b8135602067ffffffffffffffff821115610f7557610f75610df0565b610f83818360051b01610e6b565b82815260069290921b84018101918181019086841115610fa257600080fd5b8286015b84811015610fe85760408189031215610fbf5760008081fd5b610fc7610e1f565b610fd082610d7e565b81528185013585820152835291830191604001610fa6565b509695505050505050565b600060a0823603121561100557600080fd5b61100d610e48565b8235815261101d60208401610d0b565b6020820152604083013567ffffffffffffffff8082111561103d57600080fd5b61104936838701610eba565b6040840152606085013591508082111561106257600080fd5b61106e36838701610eba565b6060840152608085013591508082111561108757600080fd5b5061109436828601610f48565b60808301525092915050565b6000604067ffffffffffffffff851683526020604081850152845160a060408601526110cf60e0860182610c94565b9050818601517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc08087840301606088015261110a8383610c94565b6040890151888203830160808a01528051808352908601945060009350908501905b8084101561116b578451805173ffffffffffffffffffffffffffffffffffffffff1683528601518683015293850193600193909301929086019061112c565b50606089015173ffffffffffffffffffffffffffffffffffffffff1660a08901526080890151888203830160c08a015295506111a78187610c94565b9a9950505050505050505050565b6000602082840312156111c757600080fd5b5051919050565b808201808211156103f1577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fdfea164736f6c6343000818000a", } var PingPongDemoABI = PingPongDemoMetaData.ABI diff --git a/core/gethwrappers/ccip/generated/registry_module_owner_custom/registry_module_owner_custom.go b/core/gethwrappers/ccip/generated/registry_module_owner_custom/registry_module_owner_custom.go index 7fc04c7b2c6..315d75121b1 100644 --- a/core/gethwrappers/ccip/generated/registry_module_owner_custom/registry_module_owner_custom.go +++ b/core/gethwrappers/ccip/generated/registry_module_owner_custom/registry_module_owner_custom.go @@ -32,7 +32,7 @@ var ( var RegistryModuleOwnerCustomMetaData = &bind.MetaData{ ABI: "[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"AddressZero\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"CanOnlySelfRegister\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"msgSender\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"RequiredRoleNotFound\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"administrator\",\"type\":\"address\"}],\"name\":\"AdministratorRegistered\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"registerAccessControlDefaultAdmin\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"registerAdminViaGetCCIPAdmin\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"registerAdminViaOwner\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", - Bin: "0x60a034607e57601f6106e938819003918201601f19168301916001600160401b03831184841017608357808492602094604052833981010312607e57516001600160a01b03811690819003607e578015606d5760805260405161064f908161009a82396080518161052b0152f35b639fabe1c160e01b60005260046000fd5b600080fd5b634e487b7160e01b600052604160045260246000fdfe608080604052600436101561001357600080fd5b60003560e01c908163181f5a77146103795750806369c0081e146101e557806396ea2f7a1461012a5763ff12c3541461004b57600080fd5b346101255760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101255760043573ffffffffffffffffffffffffffffffffffffffff811690818103610125576020600492604051938480927f8fd6a6ac0000000000000000000000000000000000000000000000000000000082525afa908115610119576100e6926000926100e8575b506104f5565b005b61010b91925060203d602011610112575b6101038183610488565b8101906104c9565b90386100e0565b503d6100f9565b6040513d6000823e3d90fd5b600080fd5b346101255760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101255760043573ffffffffffffffffffffffffffffffffffffffff811690818103610125576020600492604051938480927f8da5cb5b0000000000000000000000000000000000000000000000000000000082525afa908115610119576100e6926000926101c457506104f5565b6101de91925060203d602011610112576101038183610488565b90836100e0565b346101255760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101255760043573ffffffffffffffffffffffffffffffffffffffff811690818103610125576040517fa217fddf000000000000000000000000000000000000000000000000000000008152602081600481865afa90811561011957600091610347575b506040517f91d14854000000000000000000000000000000000000000000000000000000008152816004820152336024820152602081604481875afa90811561011957600091610305575b50156102cf576100e633836104f5565b90507f86e0b344000000000000000000000000000000000000000000000000000000006000523360045260245260445260646000fd5b6020813d60201161033f575b8161031e60209383610488565b8101031261033b57519081151582036103385750846102bf565b80fd5b5080fd5b3d9150610311565b90506020813d602011610371575b8161036260209383610488565b81010312610125575183610274565b3d9150610355565b346101255760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610125576040810181811067ffffffffffffffff82111761045957604052601f81527f52656769737472794d6f64756c654f776e6572437573746f6d20312e362e3000602082015260405190602082528181519182602083015260005b8381106104415750507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f836000604080968601015201168101030190f35b60208282018101516040878401015285935001610401565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff82111761045957604052565b90816020910312610125575173ffffffffffffffffffffffffffffffffffffffff811681036101255790565b9073ffffffffffffffffffffffffffffffffffffffff16903382036105fb5773ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001690813b156101255773ffffffffffffffffffffffffffffffffffffffff906040519182917fe677ae3700000000000000000000000000000000000000000000000000000000835216928360048301528460248301528160446000948580945af180156105f05790827f09590fb70af4b833346363965e043a9339e8c7d378b8a2b903c75c277faec4f993926105e0575b9050a3565b6105e991610488565b38816105db565b6040513d84823e3d90fd5b73ffffffffffffffffffffffffffffffffffffffff917fc454d182000000000000000000000000000000000000000000000000000000006000526004521660245260446000fdfea164736f6c634300081a000a", + Bin: "0x60a060405234801561001057600080fd5b5060405161064a38038061064a83398101604081905261002f91610067565b6001600160a01b03811661005657604051639fabe1c160e01b815260040160405180910390fd5b6001600160a01b0316608052610097565b60006020828403121561007957600080fd5b81516001600160a01b038116811461009057600080fd5b9392505050565b6080516105986100b260003960006103db01526105986000f3fe608060405234801561001057600080fd5b506004361061004c5760003560e01c8063181f5a771461005157806369c0081e146100a357806396ea2f7a146100b8578063ff12c354146100cb575b600080fd5b61008d6040518060400160405280601f81526020017f52656769737472794d6f64756c654f776e6572437573746f6d20312e362e300081525081565b60405161009a9190610480565b60405180910390f35b6100b66100b136600461050f565b6100de565b005b6100b66100c636600461050f565b610255565b6100b66100d936600461050f565b6102d0565b60008173ffffffffffffffffffffffffffffffffffffffff1663a217fddf6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561012b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061014f9190610533565b6040517f91d148540000000000000000000000000000000000000000000000000000000081526004810182905233602482015290915073ffffffffffffffffffffffffffffffffffffffff8316906391d1485490604401602060405180830381865afa1580156101c3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101e7919061054c565b610247576040517f86e0b3440000000000000000000000000000000000000000000000000000000081523360048201526024810182905273ffffffffffffffffffffffffffffffffffffffff831660448201526064015b60405180910390fd5b610251823361031f565b5050565b6102cd818273ffffffffffffffffffffffffffffffffffffffff16638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156102a4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102c8919061056e565b61031f565b50565b6102cd818273ffffffffffffffffffffffffffffffffffffffff16638fd6a6ac6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156102a4573d6000803e3d6000fd5b73ffffffffffffffffffffffffffffffffffffffff8116331461038e576040517fc454d18200000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff80831660048301528316602482015260440161023e565b6040517fe677ae3700000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff838116600483015282811660248301527f0000000000000000000000000000000000000000000000000000000000000000169063e677ae3790604401600060405180830381600087803b15801561041f57600080fd5b505af1158015610433573d6000803e3d6000fd5b505060405173ffffffffffffffffffffffffffffffffffffffff8085169350851691507f09590fb70af4b833346363965e043a9339e8c7d378b8a2b903c75c277faec4f990600090a35050565b60006020808352835180602085015260005b818110156104ae57858101830151858201604001528201610492565b5060006040828601015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8301168501019250505092915050565b73ffffffffffffffffffffffffffffffffffffffff811681146102cd57600080fd5b60006020828403121561052157600080fd5b813561052c816104ed565b9392505050565b60006020828403121561054557600080fd5b5051919050565b60006020828403121561055e57600080fd5b8151801515811461052c57600080fd5b60006020828403121561058057600080fd5b815161052c816104ed56fea164736f6c6343000818000a", } var RegistryModuleOwnerCustomABI = RegistryModuleOwnerCustomMetaData.ABI diff --git a/core/gethwrappers/ccip/generated/report_codec/report_codec.go b/core/gethwrappers/ccip/generated/report_codec/report_codec.go index 1a7942c6266..0a58d0a6b93 100644 --- a/core/gethwrappers/ccip/generated/report_codec/report_codec.go +++ b/core/gethwrappers/ccip/generated/report_codec/report_codec.go @@ -99,7 +99,7 @@ type OffRampCommitReport struct { var ReportCodecMetaData = &bind.MetaData{ ABI: "[{\"anonymous\":false,\"inputs\":[{\"components\":[{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sourceToken\",\"type\":\"address\"},{\"internalType\":\"uint224\",\"name\":\"usdPerToken\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.TokenPriceUpdate[]\",\"name\":\"tokenPriceUpdates\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint224\",\"name\":\"usdPerUnitGas\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.GasPriceUpdate[]\",\"name\":\"gasPriceUpdates\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.PriceUpdates\",\"name\":\"priceUpdates\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRampAddress\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"maxSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"merkleRoot\",\"type\":\"bytes32\"}],\"internalType\":\"structInternal.MerkleRoot[]\",\"name\":\"merkleRoots\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"internalType\":\"structIRMNRemote.Signature[]\",\"name\":\"rmnSignatures\",\"type\":\"tuple[]\"}],\"indexed\":false,\"internalType\":\"structOffRamp.CommitReport\",\"name\":\"report\",\"type\":\"tuple\"}],\"name\":\"CommitReportDecoded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"}],\"internalType\":\"structInternal.RampMessageHeader\",\"name\":\"header\",\"type\":\"tuple\"},{\"internalType\":\"bytes\",\"name\":\"sender\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"destTokenAddress\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"destGasAmount\",\"type\":\"uint32\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structInternal.Any2EVMTokenTransfer[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.Any2EVMRampMessage[]\",\"name\":\"messages\",\"type\":\"tuple[]\"},{\"internalType\":\"bytes[][]\",\"name\":\"offchainTokenData\",\"type\":\"bytes[][]\"},{\"internalType\":\"bytes32[]\",\"name\":\"proofs\",\"type\":\"bytes32[]\"},{\"internalType\":\"uint256\",\"name\":\"proofFlagBits\",\"type\":\"uint256\"}],\"indexed\":false,\"internalType\":\"structInternal.ExecutionReport[]\",\"name\":\"report\",\"type\":\"tuple[]\"}],\"name\":\"ExecuteReportDecoded\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"report\",\"type\":\"bytes\"}],\"name\":\"decodeCommitReport\",\"outputs\":[{\"components\":[{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sourceToken\",\"type\":\"address\"},{\"internalType\":\"uint224\",\"name\":\"usdPerToken\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.TokenPriceUpdate[]\",\"name\":\"tokenPriceUpdates\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint224\",\"name\":\"usdPerUnitGas\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.GasPriceUpdate[]\",\"name\":\"gasPriceUpdates\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.PriceUpdates\",\"name\":\"priceUpdates\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRampAddress\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"maxSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"merkleRoot\",\"type\":\"bytes32\"}],\"internalType\":\"structInternal.MerkleRoot[]\",\"name\":\"merkleRoots\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"internalType\":\"structIRMNRemote.Signature[]\",\"name\":\"rmnSignatures\",\"type\":\"tuple[]\"}],\"internalType\":\"structOffRamp.CommitReport\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"report\",\"type\":\"bytes\"}],\"name\":\"decodeExecuteReport\",\"outputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"}],\"internalType\":\"structInternal.RampMessageHeader\",\"name\":\"header\",\"type\":\"tuple\"},{\"internalType\":\"bytes\",\"name\":\"sender\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"destTokenAddress\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"destGasAmount\",\"type\":\"uint32\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structInternal.Any2EVMTokenTransfer[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.Any2EVMRampMessage[]\",\"name\":\"messages\",\"type\":\"tuple[]\"},{\"internalType\":\"bytes[][]\",\"name\":\"offchainTokenData\",\"type\":\"bytes[][]\"},{\"internalType\":\"bytes32[]\",\"name\":\"proofs\",\"type\":\"bytes32[]\"},{\"internalType\":\"uint256\",\"name\":\"proofFlagBits\",\"type\":\"uint256\"}],\"internalType\":\"structInternal.ExecutionReport[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"pure\",\"type\":\"function\"}]", - Bin: "0x60808060405234601557611604908161001b8239f35b600080fdfe6101c0604052600436101561001357600080fd5b60003560e01c80636fb34956146106355763f816ec601461003357600080fd5b3461051d5761004136611462565b6060604061004d6113a4565b6100556113c4565b838152836020820152815282602082015201528051810190602082019060208184031261051d5760208101519067ffffffffffffffff821161051d57019060608284031261051d576100a56113a4565b92602083015167ffffffffffffffff811161051d578301602081019060409083031261051d576100d36113c4565b90805167ffffffffffffffff811161051d57810184601f8201121561051d57805161010561010082611545565b6113e4565b9160208084848152019260061b8201019087821161051d57602001915b8183106105f657505050825260208101519067ffffffffffffffff821161051d570183601f8201121561051d57805161015d61010082611545565b9160208084848152019260061b8201019086821161051d57602001915b8183106105b75750505060208201528452604083015167ffffffffffffffff811161051d576020908401019282601f8501121561051d578351936101c061010086611545565b9460208087838152019160051b8301019185831161051d5760208101915b838310610522575050505060208501938452606081015167ffffffffffffffff811161051d5760209101019180601f8401121561051d5782519161022461010084611545565b9360208086868152019460061b82010192831161051d5793959493602001925b8284106104e45750505050604082019283526040519283926020845251916060602085015260c0840192805193604060808701528451809152602060e0870195019060005b81811061048b5750505060200151927fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff808582030160a08601526020808551928381520194019060005b81811061043e5750505051917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0848203016040850152825180825260208201916020808360051b8301019501926000915b83831061039e57505050505051907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08382030160608401526020808351928381520192019060005b818110610379575050500390f35b825180518552602090810151818601528695506040909401939092019160010161036b565b91939650919394602080827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0856001950301865289519067ffffffffffffffff82511681526080806103fd8585015160a08786015260a0850190611502565b9367ffffffffffffffff604082015116604085015267ffffffffffffffff606082015116606085015201519101529801930193019092879695949293610323565b8251805167ffffffffffffffff1687526020908101517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1681880152889750604090960195909201916001016102d2565b8251805173ffffffffffffffffffffffffffffffffffffffff1688526020908101517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff168189015289985060409097019690920191600101610289565b6040602085849997989903011261051d5760206040916105026113c4565b86518152828701518382015281520193019295949395610244565b600080fd5b825167ffffffffffffffff811161051d57820160a08188031261051d57610547611384565b916105546020830161155d565b835260408201519267ffffffffffffffff841161051d5760a08361057f8c6020809881980101611572565b8584015261058f6060820161155d565b60408401526105a06080820161155d565b6060840152015160808201528152019201916101de565b60406020848803011261051d5760206040916105d16113c4565b6105da8661155d565b81526105e78387016115ce565b8382015281520192019161017a565b60406020848903011261051d5760206040916106106113c4565b610619866115ad565b81526106268387016115ce565b83820152815201920191610122565b3461051d5761064336611462565b61010052610100515161010051016101a0526020610100516101a051031261051d5760206101005101516101405267ffffffffffffffff610140511161051d5760206101a05101603f61014051610100510101121561051d5760206101405161010051010151610120526106bc61010061012051611545565b60c05260c051610180526101205160c05152602060c0510160c05260c0516101605260206101a051016020806101205160051b6101405161010051010101011161051d5760406101405161010051010160e0525b6020806101205160051b61014051610100510101010160e05110610adc5760405180602081016020825261018051518091526040820160408260051b8401019161016051916000905b82821061076857505050500390f35b91939092947fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc090820301825284519060a081019167ffffffffffffffff815116825260208101519260a06020840152835180915260c08301602060c08360051b86010195019160005b81811061092c57505050506040810151928281036040840152835180825260208201906020808260051b85010196019260005b8281106108715750505050506060810151928281036060840152602080855192838152019401906000905b80821061085957505050600192602092608080859401519101529601920192018594939192610759565b9091946020806001928851815201960192019061082f565b90919293967fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe083829e9d9e0301855287519081519081815260208101906020808460051b8301019401926000915b8183106108e35750505050506020806001929e9d9e99019501910192919092610804565b909192939460208061091f837fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe086600196030189528951611502565b97019501930191906108bf565b909192957fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff40868203018452865167ffffffffffffffff6080825180518552826020820151166020860152826040820151166040860152826060820151166060860152015116608083015260a06109c76109b5602084015161014084870152610140860190611502565b604084015185820360c0870152611502565b9173ffffffffffffffffffffffffffffffffffffffff60608201511660e0850152608081015161010085015201519161012081830391015281519081815260208101906020808460051b8301019401926000915b818310610a3b5750505050506020806001929801940191019190916107d1565b9091929394602080827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08560019503018852885190608080610ac9610a89855160a0865260a0860190611502565b73ffffffffffffffffffffffffffffffffffffffff87870151168786015263ffffffff604087015116604086015260608601518582036060870152611502565b9301519101529701950193019190610a1b565b60e0515160a05267ffffffffffffffff60a0511161051d5760a060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081835161014051610100510101016101a0510301011261051d57610b3b611384565b610b5560208060a05161014051610100510101010161155d565b81526040602060a0516101405161010051010101015160805267ffffffffffffffff6080511161051d5760206101a05101601f60206080518160a0516101405161010051010101010101121561051d5760206080518160a0516101405161010051010101010151610bc861010082611545565b90602082828152019060206101a0510160208260051b816080518160a0516101405161010051010101010101011161051d576020806080518160a0516101405161010051010101010101915b60208260051b816080518160a0516101405161010051010101010101018310610eff5750505060208201526060602060a0516101405161010051010101015167ffffffffffffffff811161051d5760206101a05101601f6020838160a0516101405161010051010101010101121561051d576020818160a051610140516101005101010101015190610ca861010083611545565b91602083828152019160206101a0510160208360051b81848160a0516101405161010051010101010101011161051d5760a051610140516101005101018101606001925b60208360051b81848160a0516101405161010051010101010101018410610dde5750505050604082015260a0805161014051610100510101015167ffffffffffffffff811161051d576020908160a0516101405161010051010101010160206101a05101601f8201121561051d57805190610d6961010083611545565b9160208084838152019160051b8301019160206101a05101831161051d57602001905b828210610dce57505050606082015260a06020815161014051610100510101010151608082015260c05152602060c0510160c052602060e0510160e052610710565b8151815260209182019101610d8c565b835167ffffffffffffffff811161051d5760206101a05101603f826020868160a051610140516101005101010101010101121561051d5760a051610140516101005101018301810160600151610e3661010082611545565b916020838381520160206101a051016020808560051b85828b8160a05161014051610100510101010101010101011161051d5760a0516101405161010051010186018201608001905b60a05161014051610100516080910190910188018401600586901b01018210610eb5575050509082525060209384019301610cec565b815167ffffffffffffffff811161051d576101a05160a051610140516101005160209586959094610ef4949087019360809301018d0189010101611572565b815201910190610e7f565b825167ffffffffffffffff811161051d5760207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe082826080518160a05161014051610100510101010101016101a05103010190610140821261051d576040519160c083019083821067ffffffffffffffff8311176113555760a0916040521261051d57610f8a611384565b602082816080518160a051610140516101005101010101010101518152610fca60408360206080518160a05161014051610100510101010101010161155d565b6020820152610ff260608360206080518160a05161014051610100510101010101010161155d565b6040820152611019608083602082518160a05161014051610100510101010101010161155d565b606082015261104060a083602060805181845161014051610100510101010101010161155d565b6080820152825260c08160206080518160a0516101405161010051010101010101015167ffffffffffffffff811161051d5761109d906020806101a051019184826080518160a05161014051610100510101010101010101611572565b602083015260e08160206080518160a0516101405161010051010101010101015167ffffffffffffffff811161051d576110f8906020806101a051019184826080518160a05161014051610100510101010101010101611572565b604083015261111f6101008260206080518160a051610140518651010101010101016115ad565b60608301526101208160206080518160a0516101405161010051010101010101015160808301526101408160206080518160a05185516101005101010101010101519067ffffffffffffffff821161051d5760206101a05101601f60208484826080518160a0516101405161010051010101010101010101121561051d5760208282826080518160a05161014051610100510101010101010101516111c661010082611545565b92602084838152019260206101a0510160208460051b818585826080518160a0516101405161010051010101010101010101011161051d576080805160a05161014051610100510101018201830101935b6080805160a051610140516101005101010183018401600586901b0101851061125257505050505060a0820152815260209283019201610c14565b845167ffffffffffffffff811161051d5760208484826080518160a051610140516101005101010101010101010160a060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0836101a0510301011261051d576112ba611384565b91602082015167ffffffffffffffff811161051d576112e4906020806101a0510191850101611572565b83526112f2604083016115ad565b6020840152606082015163ffffffff8116810361051d57604084015260808201519267ffffffffffffffff841161051d5760a06020949361133e869586806101a0510191840101611572565b606084015201516080820152815201940193611217565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040519060a0820182811067ffffffffffffffff82111761135557604052565b604051906060820182811067ffffffffffffffff82111761135557604052565b604051906040820182811067ffffffffffffffff82111761135557604052565b907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f604051930116820182811067ffffffffffffffff82111761135557604052565b67ffffffffffffffff811161135557601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b60207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc82011261051d5760043567ffffffffffffffff811161051d578160238201121561051d578060040135906114bb61010083611428565b928284526024838301011161051d5781600092602460209301838601378301015290565b60005b8381106114f25750506000910152565b81810151838201526020016114e2565b907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f60209361153e815180928187528780880191016114df565b0116010190565b67ffffffffffffffff81116113555760051b60200190565b519067ffffffffffffffff8216820361051d57565b81601f8201121561051d57805161158b61010082611428565b928184526020828401011161051d576115aa91602080850191016114df565b90565b519073ffffffffffffffffffffffffffffffffffffffff8216820361051d57565b51907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8216820361051d5756fea164736f6c634300081a000a", + Bin: "0x608060405234801561001057600080fd5b506113c3806100206000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c80636fb349561461003b578063f816ec6014610064575b600080fd5b61004e610049366004610231565b610084565b60405161005b91906104ee565b60405180910390f35b610077610072366004610231565b6100a0565b60405161005b9190610833565b60608180602001905181019061009a9190610e6d565b92915050565b6040805160a08101825260608082018181526080830182905282526020808301829052928201528251909161009a918401810190840161122d565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60405160a0810167ffffffffffffffff8111828210171561012d5761012d6100db565b60405290565b60405160c0810167ffffffffffffffff8111828210171561012d5761012d6100db565b6040805190810167ffffffffffffffff8111828210171561012d5761012d6100db565b6040516060810167ffffffffffffffff8111828210171561012d5761012d6100db565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156101e3576101e36100db565b604052919050565b600067ffffffffffffffff821115610205576102056100db565b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b60006020828403121561024357600080fd5b813567ffffffffffffffff81111561025a57600080fd5b8201601f8101841361026b57600080fd5b803561027e610279826101eb565b61019c565b81815285602083850101111561029357600080fd5b81602084016020830137600091810160200191909152949350505050565b60005b838110156102cc5781810151838201526020016102b4565b50506000910152565b600081518084526102ed8160208601602086016102b1565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b600082825180855260208086019550808260051b84010181860160005b848110156103eb577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0868403018952815160a08151818652610380828701826102d5565b91505073ffffffffffffffffffffffffffffffffffffffff868301511686860152604063ffffffff81840151168187015250606080830151868303828801526103c983826102d5565b608094850151979094019690965250509884019892509083019060010161033c565b5090979650505050505050565b6000828251808552602080860195506005818360051b8501018287016000805b868110156104a3577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe088850381018c5283518051808752908801908887019080891b88018a01865b8281101561048c57858a830301845261047a8286516102d5565b948c0194938c01939150600101610460565b509e8a019e97505050938701935050600101610418565b50919998505050505050505050565b60008151808452602080850194506020840160005b838110156104e3578151875295820195908201906001016104c7565b509495945050505050565b6000602080830181845280855180835260408601915060408160051b870101925083870160005b828110156106d6577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0888603018452815160a0860167ffffffffffffffff8083511688528883015160a08a8a015282815180855260c08b01915060c08160051b8c010194508b8301925060005b8181101561067f577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff408c87030183528351805180518852868f820151168f890152866040820151166040890152866060820151166060890152866080820151166080890152508d81015161014060a08901526106026101408901826102d5565b9050604082015188820360c08a015261061b82826102d5565b915050606082015161064560e08a018273ffffffffffffffffffffffffffffffffffffffff169052565b50608082015161010089015260a0820151915087810361012089015261066b818361031f565b97505050928c0192918c0191600101610582565b50505050506040820151878203604089015261069b82826103f8565b915050606082015187820360608901526106b582826104b2565b60809384015198909301979097525094509285019290850190600101610515565b5092979650505050505050565b60008151808452602080850194506020840160005b838110156104e3578151805167ffffffffffffffff1688528301517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1683880152604090960195908201906001016106f8565b600082825180855260208086019550808260051b84010181860160005b848110156103eb577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0868403018952815160a067ffffffffffffffff8083511686528683015182888801526107bb838801826102d5565b60408581015184169089015260608086015190931692880192909252506080928301519290950191909152509783019790830190600101610764565b60008151808452602080850194506020840160005b838110156104e357815180518852830151838801526040909601959082019060010161080c565b602080825282516060838301528051604060808501819052815160c086018190526000949392840191859160e08801905b808410156108c1578451805173ffffffffffffffffffffffffffffffffffffffff1683528701517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1687830152938601936001939093019290820190610864565b50938501518785037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff800160a0890152936108fb81866106e3565b9450505050508185015191507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08085830301604086015261093c8284610747565b925060408601519150808584030160608601525061095a82826107f7565b95945050505050565b600067ffffffffffffffff82111561097d5761097d6100db565b5060051b60200190565b805167ffffffffffffffff8116811461099f57600080fd5b919050565b600060a082840312156109b657600080fd5b6109be61010a565b9050815181526109d060208301610987565b60208201526109e160408301610987565b60408201526109f260608301610987565b6060820152610a0360808301610987565b608082015292915050565b600082601f830112610a1f57600080fd5b8151610a2d610279826101eb565b818152846020838601011115610a4257600080fd5b610a538260208301602087016102b1565b949350505050565b805173ffffffffffffffffffffffffffffffffffffffff8116811461099f57600080fd5b600082601f830112610a9057600080fd5b81516020610aa061027983610963565b82815260059290921b84018101918181019086841115610abf57600080fd5b8286015b84811015610bbb57805167ffffffffffffffff80821115610ae45760008081fd5b818901915060a0807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0848d03011215610b1d5760008081fd5b610b2561010a565b8784015183811115610b375760008081fd5b610b458d8a83880101610a0e565b8252506040610b55818601610a5b565b8983015260608086015163ffffffff81168114610b725760008081fd5b808385015250608091508186015185811115610b8e5760008081fd5b610b9c8f8c838a0101610a0e565b9184019190915250919093015190830152508352918301918301610ac3565b509695505050505050565b600082601f830112610bd757600080fd5b81516020610be761027983610963565b82815260059290921b84018101918181019086841115610c0657600080fd5b8286015b84811015610bbb57805167ffffffffffffffff80821115610c2b5760008081fd5b8189019150610140807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0848d03011215610c655760008081fd5b610c6d610133565b610c798c8986016109a4565b815260c084015183811115610c8e5760008081fd5b610c9c8d8a83880101610a0e565b898301525060e084015183811115610cb45760008081fd5b610cc28d8a83880101610a0e565b604083015250610cd56101008501610a5b565b60608201526101208401516080820152908301519082821115610cf85760008081fd5b610d068c8984870101610a7f565b60a08201528652505050918301918301610c0a565b600082601f830112610d2c57600080fd5b81516020610d3c61027983610963565b82815260059290921b84018101918181019086841115610d5b57600080fd5b8286015b84811015610bbb57805167ffffffffffffffff80821115610d7f57600080fd5b818901915089603f830112610d9357600080fd5b85820151610da361027982610963565b81815260059190911b830160400190878101908c831115610dc357600080fd5b604085015b83811015610dfc57805185811115610ddf57600080fd5b610dee8f6040838a0101610a0e565b845250918901918901610dc8565b50875250505092840192508301610d5f565b600082601f830112610e1f57600080fd5b81516020610e2f61027983610963565b8083825260208201915060208460051b870101935086841115610e5157600080fd5b602086015b84811015610bbb5780518352918301918301610e56565b60006020808385031215610e8057600080fd5b825167ffffffffffffffff80821115610e9857600080fd5b818501915085601f830112610eac57600080fd5b8151610eba61027982610963565b81815260059190911b83018401908481019088831115610ed957600080fd5b8585015b83811015610fd357805185811115610ef457600080fd5b860160a0818c037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0011215610f295760008081fd5b610f3161010a565b610f3c898301610987565b815260408083015188811115610f525760008081fd5b610f608e8c83870101610bc6565b8b8401525060608084015189811115610f795760008081fd5b610f878f8d83880101610d1b565b8385015250608091508184015189811115610fa25760008081fd5b610fb08f8d83880101610e0e565b918401919091525060a09290920151918101919091528352918601918601610edd565b5098975050505050505050565b80517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8116811461099f57600080fd5b600082601f83011261101d57600080fd5b8151602061102d61027983610963565b82815260069290921b8401810191818101908684111561104c57600080fd5b8286015b84811015610bbb57604081890312156110695760008081fd5b611071610156565b61107a82610987565b8152611087858301610fe0565b81860152835291830191604001611050565b600082601f8301126110aa57600080fd5b815160206110ba61027983610963565b82815260059290921b840181019181810190868411156110d957600080fd5b8286015b84811015610bbb57805167ffffffffffffffff808211156110fe5760008081fd5b818901915060a0807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0848d030112156111375760008081fd5b61113f61010a565b61114a888501610987565b8152604080850151848111156111605760008081fd5b61116e8e8b83890101610a0e565b8a8401525060609350611182848601610987565b908201526080611193858201610987565b938201939093529201519082015283529183019183016110dd565b600082601f8301126111bf57600080fd5b815160206111cf61027983610963565b82815260069290921b840181019181810190868411156111ee57600080fd5b8286015b84811015610bbb576040818903121561120b5760008081fd5b611213610156565b8151815284820151858201528352918301916040016111f2565b6000602080838503121561124057600080fd5b825167ffffffffffffffff8082111561125857600080fd5b908401906060828703121561126c57600080fd5b611274610179565b82518281111561128357600080fd5b8301604081890381131561129657600080fd5b61129e610156565b8251858111156112ad57600080fd5b8301601f81018b136112be57600080fd5b80516112cc61027982610963565b81815260069190911b8201890190898101908d8311156112eb57600080fd5b928a01925b828410156113395785848f0312156113085760008081fd5b611310610156565b61131985610a5b565b81526113268c8601610fe0565b818d0152825292850192908a01906112f0565b84525050508287015191508482111561135157600080fd5b61135d8a83850161100c565b8188015283525050828401518281111561137657600080fd5b61138288828601611099565b8583015250604083015193508184111561139b57600080fd5b6113a7878585016111ae565b6040820152969550505050505056fea164736f6c6343000818000a", } var ReportCodecABI = ReportCodecMetaData.ABI diff --git a/core/gethwrappers/ccip/generated/rmn_home/rmn_home.go b/core/gethwrappers/ccip/generated/rmn_home/rmn_home.go index 2afbe140ae1..268b49b4f96 100644 --- a/core/gethwrappers/ccip/generated/rmn_home/rmn_home.go +++ b/core/gethwrappers/ccip/generated/rmn_home/rmn_home.go @@ -60,7 +60,7 @@ type RMNHomeVersionedConfig struct { var RMNHomeMetaData = &bind.MetaData{ ABI: "[{\"inputs\":[],\"name\":\"CannotTransferToSelf\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"expectedConfigDigest\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"gotConfigDigest\",\"type\":\"bytes32\"}],\"name\":\"ConfigDigestMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"}],\"name\":\"DigestNotFound\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"DuplicateOffchainPublicKey\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"DuplicatePeerId\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"DuplicateSourceChain\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MustBeProposedOwner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NoOpStateTransitionNotAllowed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NotEnoughObservers\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByOwner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OutOfBoundsNodesLength\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OutOfBoundsObserverNodeIndex\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OwnerCannotBeZero\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RevokingZeroDigestNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"}],\"name\":\"ActiveConfigRevoked\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"}],\"name\":\"CandidateConfigRevoked\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"}],\"name\":\"ConfigPromoted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"version\",\"type\":\"uint32\"},{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"peerId\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"offchainPublicKey\",\"type\":\"bytes32\"}],\"internalType\":\"structRMNHome.Node[]\",\"name\":\"nodes\",\"type\":\"tuple[]\"},{\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"}],\"indexed\":false,\"internalType\":\"structRMNHome.StaticConfig\",\"name\":\"staticConfig\",\"type\":\"tuple\"},{\"components\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"f\",\"type\":\"uint64\"},{\"internalType\":\"uint256\",\"name\":\"observerNodesBitmap\",\"type\":\"uint256\"}],\"internalType\":\"structRMNHome.SourceChain[]\",\"name\":\"sourceChains\",\"type\":\"tuple[]\"},{\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"}],\"indexed\":false,\"internalType\":\"structRMNHome.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"}],\"name\":\"ConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"components\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"f\",\"type\":\"uint64\"},{\"internalType\":\"uint256\",\"name\":\"observerNodesBitmap\",\"type\":\"uint256\"}],\"internalType\":\"structRMNHome.SourceChain[]\",\"name\":\"sourceChains\",\"type\":\"tuple[]\"},{\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"}],\"indexed\":false,\"internalType\":\"structRMNHome.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"}],\"name\":\"DynamicConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getActiveDigest\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAllConfigs\",\"outputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"version\",\"type\":\"uint32\"},{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"peerId\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"offchainPublicKey\",\"type\":\"bytes32\"}],\"internalType\":\"structRMNHome.Node[]\",\"name\":\"nodes\",\"type\":\"tuple[]\"},{\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"}],\"internalType\":\"structRMNHome.StaticConfig\",\"name\":\"staticConfig\",\"type\":\"tuple\"},{\"components\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"f\",\"type\":\"uint64\"},{\"internalType\":\"uint256\",\"name\":\"observerNodesBitmap\",\"type\":\"uint256\"}],\"internalType\":\"structRMNHome.SourceChain[]\",\"name\":\"sourceChains\",\"type\":\"tuple[]\"},{\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"}],\"internalType\":\"structRMNHome.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"}],\"internalType\":\"structRMNHome.VersionedConfig\",\"name\":\"activeConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"version\",\"type\":\"uint32\"},{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"peerId\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"offchainPublicKey\",\"type\":\"bytes32\"}],\"internalType\":\"structRMNHome.Node[]\",\"name\":\"nodes\",\"type\":\"tuple[]\"},{\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"}],\"internalType\":\"structRMNHome.StaticConfig\",\"name\":\"staticConfig\",\"type\":\"tuple\"},{\"components\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"f\",\"type\":\"uint64\"},{\"internalType\":\"uint256\",\"name\":\"observerNodesBitmap\",\"type\":\"uint256\"}],\"internalType\":\"structRMNHome.SourceChain[]\",\"name\":\"sourceChains\",\"type\":\"tuple[]\"},{\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"}],\"internalType\":\"structRMNHome.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"}],\"internalType\":\"structRMNHome.VersionedConfig\",\"name\":\"candidateConfig\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getCandidateDigest\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"}],\"name\":\"getConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"version\",\"type\":\"uint32\"},{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"peerId\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"offchainPublicKey\",\"type\":\"bytes32\"}],\"internalType\":\"structRMNHome.Node[]\",\"name\":\"nodes\",\"type\":\"tuple[]\"},{\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"}],\"internalType\":\"structRMNHome.StaticConfig\",\"name\":\"staticConfig\",\"type\":\"tuple\"},{\"components\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"f\",\"type\":\"uint64\"},{\"internalType\":\"uint256\",\"name\":\"observerNodesBitmap\",\"type\":\"uint256\"}],\"internalType\":\"structRMNHome.SourceChain[]\",\"name\":\"sourceChains\",\"type\":\"tuple[]\"},{\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"}],\"internalType\":\"structRMNHome.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"}],\"internalType\":\"structRMNHome.VersionedConfig\",\"name\":\"versionedConfig\",\"type\":\"tuple\"},{\"internalType\":\"bool\",\"name\":\"ok\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getConfigDigests\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"activeConfigDigest\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"candidateConfigDigest\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"digestToPromote\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"digestToRevoke\",\"type\":\"bytes32\"}],\"name\":\"promoteCandidateAndRevokeActive\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"}],\"name\":\"revokeCandidate\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"peerId\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"offchainPublicKey\",\"type\":\"bytes32\"}],\"internalType\":\"structRMNHome.Node[]\",\"name\":\"nodes\",\"type\":\"tuple[]\"},{\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"}],\"internalType\":\"structRMNHome.StaticConfig\",\"name\":\"staticConfig\",\"type\":\"tuple\"},{\"components\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"f\",\"type\":\"uint64\"},{\"internalType\":\"uint256\",\"name\":\"observerNodesBitmap\",\"type\":\"uint256\"}],\"internalType\":\"structRMNHome.SourceChain[]\",\"name\":\"sourceChains\",\"type\":\"tuple[]\"},{\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"}],\"internalType\":\"structRMNHome.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"},{\"internalType\":\"bytes32\",\"name\":\"digestToOverwrite\",\"type\":\"bytes32\"}],\"name\":\"setCandidate\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"newConfigDigest\",\"type\":\"bytes32\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"f\",\"type\":\"uint64\"},{\"internalType\":\"uint256\",\"name\":\"observerNodesBitmap\",\"type\":\"uint256\"}],\"internalType\":\"structRMNHome.SourceChain[]\",\"name\":\"sourceChains\",\"type\":\"tuple[]\"},{\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"}],\"internalType\":\"structRMNHome.DynamicConfig\",\"name\":\"newDynamicConfig\",\"type\":\"tuple\"},{\"internalType\":\"bytes32\",\"name\":\"currentDigest\",\"type\":\"bytes32\"}],\"name\":\"setDynamicConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", - Bin: "0x60808060405234604d573315603c57600180546001600160a01b03191633179055600e80546001600160401b031916905561262690816100538239f35b639b15e16f60e01b60005260046000fd5b600080fdfe6080604052600436101561001257600080fd5b60003560e01c8063118dbac514610904578063123e65db146108ae578063181f5a77146108315780633567e6b4146107b757806338354c5c1461077657806363507956146106985780636dd5b69d1461063b578063736be802146105b457806379ba5097146104cb5780638c76967f146103255780638da5cb5b146102d3578063f2fde38b146101e05763fb4022d4146100ab57600080fd5b346101db5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101db576004356100e56123b4565b80156101b15763ffffffff610105600163ffffffff600e5460201c161890565b1660028110159081610152576006600391020191825481810361018157507f53f5d9228f0a4173bea6e5931c9b3afe6eeb6692ede1d182952970f152534e3b600080a26101525760009055005b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f93df584c0000000000000000000000000000000000000000000000000000000060005260045260245260446000fd5b7f0849d8cc0000000000000000000000000000000000000000000000000000000060005260046000fd5b600080fd5b346101db5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101db5760043573ffffffffffffffffffffffffffffffffffffffff81168091036101db576102386123b4565b3381146102a957807fffffffffffffffffffffffff0000000000000000000000000000000000000000600054161760005573ffffffffffffffffffffffffffffffffffffffff600154167fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae1278600080a3005b7fdad89dca0000000000000000000000000000000000000000000000000000000060005260046000fd5b346101db5760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101db57602073ffffffffffffffffffffffffffffffffffffffff60015416604051908152f35b346101db5760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101db576004356024356103626123b4565b8115806104c3575b6104995763ffffffff610388600163ffffffff600e5460201c161890565b1660028110156101525760060260030154828103610467575063ffffffff600e5460201c166002811015610152576006026003018054828103610467575060009055600e547fffffffffffffffffffffffffffffffffffffffffffffffff00000000ffffffff67ffffffff00000000600163ffffffff8460201c161860201b16911617600e558061043c575b507ffc3e98dbbd47c3fa7c1c05b6ec711caeaf70eca4554192b9ada8fc11a37f298e600080a2005b7f0b31c0055e2d464bef7781994b98c4ff9ef4ae0d05f59feb6a68c42de5e201b8600080a281610414565b90507f93df584c0000000000000000000000000000000000000000000000000000000060005260045260245260446000fd5b7f7b4d1e4f0000000000000000000000000000000000000000000000000000000060005260046000fd5b50801561036a565b346101db5760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101db5760005473ffffffffffffffffffffffffffffffffffffffff8116330361058a577fffffffffffffffffffffffff00000000000000000000000000000000000000006001549133828416176001551660005573ffffffffffffffffffffffffffffffffffffffff3391167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0600080a3005b7f02b543c60000000000000000000000000000000000000000000000000000000060005260046000fd5b346101db5760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101db5760043567ffffffffffffffff81116101db5760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc82360301126101db576106399061062d6123b4565b60243590600401611f4a565b005b346101db5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101db5761068c610678600435611eea565b6040519283926040845260408401906116d2565b90151560208301520390f35b346101db5760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101db576106cf611ca0565b6106d7611ca0565b9063ffffffff600e5460201c1660028110156101525760066106fc9102600201611d92565b602081015161076e575b50600e5460201c63ffffffff166001186002811015610152576107549261073560066107629302600201611d92565b6020810151610766575b506040519384936040855260408501906116d2565b9083820360208501526116d2565b0390f35b90508461073f565b905082610706565b346101db5760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101db5760206107af611c65565b604051908152f35b346101db5760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101db5763ffffffff600e5460201c1660028110156101525760060260030154600e5460201c63ffffffff16600118906002821015610152576003600660409302015482519182526020820152f35b346101db5760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101db576107626040805190610872818361162b565b601182527f524d4e486f6d6520312e362e302d64657600000000000000000000000000000060208301525191829160208352602083019061168f565b346101db5760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101db5763ffffffff600e5460201c1660028110156101525760036006602092020154604051908152f35b346101db5760607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101db5760043567ffffffffffffffff81116101db5760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc82360301126101db5767ffffffffffffffff602435116101db57602435360360407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc8201126101db576109b96123b4565b6040516000916109c8826115a8565b67ffffffffffffffff8460040135116115a4578360040135840190366023830112156115a0576109fb600483013561180a565b610a08604051918261162b565b6004830135808252602082019060061b84016024013681116112ad5760248501915b81831061156f575050508352602485013567ffffffffffffffff811161156b57610a5a9060043691880101611822565b6020840152610a6e366024356004016118ac565b94610100845151116115435790919484955b845151871015610b765760018701808811610b49575b85518051821015610b3c5788610aab916123ff565b5151610ab88288516123ff565b515114610b14576020610acc8988516123ff565b5101516020610adc8389516123ff565b51015114610aec57600101610a96565b6004877fae00651d000000000000000000000000000000000000000000000000000000008152fd5b6004877f221a8ae8000000000000000000000000000000000000000000000000000000008152fd5b5050600190960195610a80565b6024877f4e487b710000000000000000000000000000000000000000000000000000000081526011600452fd5b949390610b8591515190612413565b610b8d611c65565b6044358103611513576114e7575b600e549363ffffffff85169463ffffffff86146114ba5763ffffffff60017fffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000095969701169384911617600e557dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff604051610ccc610cfa6020830160208152610c5784610c2b604082018a600401611a26565b037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0810186528561162b565b602060405191818301957f45564d000000000000000000000000000000000000000000000000000000000087524660408501523060608501528a608085015260808452610ca560a08561162b565b604051958694610cbd858701998a925192839161166c565b8501915180938584019061166c565b0101037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0810183528261162b565b519020167e0b0000000000000000000000000000000000000000000000000000000000001793610d35600163ffffffff600e5460201c161890565b600281101561148d576006029182600201866003850155857fffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000825416179055600483017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdd85360301856004013512156112a95767ffffffffffffffff6004830135116112a957600482013560061b360360248301136112a9576801000000000000000060048301351161127c578054600483013580835581116113ff575b508752602087208790602483015b600484013583106113db575050505060058201610e246024850185600401611ad9565b9067ffffffffffffffff82116113ae578190610e408454611b2a565b601f811161135e575b508990601f83116001146112bc578a926112b1575b50507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8260011b9260031b1c19161790555b60068201907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdd6024356004013591018112156112ad57602435019060048201359167ffffffffffffffff83116112a95760240160608302360381136112a95768010000000000000000831161127c5781548383558084106111ca575b509087526020872087915b838310611150575050505060070191610f396024803501602435600401611ad9565b67ffffffffffffffff819592951161112357610f558254611b2a565b601f81116110de575b5090859392918760209890601f831160011461101a57907ff6c6d1be15ba0acc8ee645c1ec613c360ef786d2d3200eb8e695b6dec757dbf096978361100f575b50507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8260011b9260031b1c19161790555b611004610ff160405193849384526060898501526060840190600401611a26565b8281036040840152602435600401611b92565b0390a2604051908152f35b013590508980610f9e565b96907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe083168489528a8920985b8181106110c45750917ff6c6d1be15ba0acc8ee645c1ec613c360ef786d2d3200eb8e695b6dec757dbf097989184600195941061108c575b505050811b019055610fd0565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88560031b161c1991013516905589808061107f565b828401358a556001909901988a9850918b01918b01611047565b82885260208820601f830160051c81019160208410611119575b601f0160051c01905b81811061110e5750610f5e565b888155600101611101565b90915081906110f8565b6024877f4e487b710000000000000000000000000000000000000000000000000000000081526041600452fd5b600260608267ffffffffffffffff611169600195611b7d565b168554907fffffffffffffffffffffffffffffffff000000000000000000000000000000006fffffffffffffffff00000000000000006111ab60208601611b7d565b60401b1692161717855560408101358486015501920192019190610f17565b7f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8116810361124f577f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8416840361124f57828952602089209060011b8101908460011b015b81811061123d5750610f0c565b808a600292558a600182015501611230565b6024897f4e487b710000000000000000000000000000000000000000000000000000000081526011600452fd5b6024887f4e487b710000000000000000000000000000000000000000000000000000000081526041600452fd5b8780fd5b8680fd5b013590508980610e5e565b90917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01691848b5260208b20928b5b818110611346575090846001959493921061130e575b505050811b019055610e90565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88560031b161c19910135169055898080611301565b919360206001819287870135815501950192016112eb565b909150838a5260208a20601f840160051c810191602085106113a4575b90601f859493920160051c01905b8181106113965750610e49565b8b8155849350600101611389565b909150819061137b565b6024897f4e487b710000000000000000000000000000000000000000000000000000000081526041600452fd5b60016002604083600494358655602081013584870155019301930192919050610e01565b7f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8116810361124f5760048301357f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8116900361124f57818952602089209060011b810190600484013560011b015b81811061147b5750610df3565b6002908a81558a60018201550161146e565b6024877f4e487b710000000000000000000000000000000000000000000000000000000081526032600452fd5b6024857f4e487b710000000000000000000000000000000000000000000000000000000081526011600452fd5b6044357f53f5d9228f0a4173bea6e5931c9b3afe6eeb6692ede1d182952970f152534e3b8480a2610b9b565b7f93df584c0000000000000000000000000000000000000000000000000000000084526004526044803560245283fd5b6004857faf26d5e3000000000000000000000000000000000000000000000000000000008152fd5b8480fd5b6040833603126112a95760206040918251611589816115a8565b853581528286013583820152815201920191610a2a565b8380fd5b8280fd5b6040810190811067ffffffffffffffff8211176115c457604052565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6060810190811067ffffffffffffffff8211176115c457604052565b6080810190811067ffffffffffffffff8211176115c457604052565b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff8211176115c457604052565b60005b83811061167f5750506000910152565b818101518382015260200161166f565b907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f6020936116cb8151809281875287808801910161166c565b0116010190565b91909163ffffffff81511683526020810151602084015260408101516080604085015260c0840190805191604060808701528251809152602060e0870193019060005b8181106117e85750505060609160206117599201517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff808783030160a088015261168f565b910151926060818303910152604081019083519160408252825180915260206060830193019060005b8181106117a65750505060206117a39394015190602081840391015261168f565b90565b909193602060606001926040885167ffffffffffffffff815116835267ffffffffffffffff858201511685840152015160408201520195019101919091611782565b8251805186526020908101518187015260409095019490920191600101611715565b67ffffffffffffffff81116115c45760051b60200190565b81601f820112156101db5780359067ffffffffffffffff82116115c45760405192611875601f84017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0166020018561162b565b828452602083830101116101db57816000926020809301838601378301015290565b359067ffffffffffffffff821682036101db57565b91906040838203126101db57604051906118c5826115a8565b8193803567ffffffffffffffff81116101db57810182601f820112156101db5780356118f08161180a565b916118fe604051938461162b565b818352602060608185019302820101908582116101db57602001915b81831061194d57505050835260208101359167ffffffffffffffff83116101db576020926119489201611822565b910152565b6060838703126101db576020606091604051611968816115f3565b61197186611897565b815261197e838701611897565b838201526040860135604082015281520192019161191a565b90357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1823603018112156101db57016020813591019167ffffffffffffffff82116101db5781360383136101db57565b601f82602094937fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0938186528686013760008582860101520116010190565b9190604081019083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1853603018112156101db5784016020813591019267ffffffffffffffff82116101db578160061b360384136101db578190604084525260608201929060005b818110611ab957505050611aab8460206117a395960190611997565b9160208185039101526119e7565b823585526020808401359086015260409485019490920191600101611a8f565b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1813603018212156101db570180359067ffffffffffffffff82116101db576020019181360383136101db57565b90600182811c92168015611b73575b6020831014611b4457565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b91607f1691611b39565b3567ffffffffffffffff811681036101db5790565b9190604081019083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1853603018112156101db5784016020813591019267ffffffffffffffff82116101db5760608202360384136101db578190604084525260608201929060005b818110611c1757505050611aab8460206117a395960190611997565b90919360608060019267ffffffffffffffff611c3289611897565b16815267ffffffffffffffff611c4a60208a01611897565b16602082015260408881013590820152019501929101611bfb565b600e5460201c63ffffffff166001186002811015610152576006026003015490565b60405190611c94826115a8565b60606020838281520152565b60405190611cad8261160f565b816000815260006020820152611cc1611c87565b60408201526060611948611c87565b9060405191826000825492611ce484611b2a565b8084529360018116908115611d525750600114611d0b575b50611d099250038361162b565b565b90506000929192526020600020906000915b818310611d36575050906020611d099282010138611cfc565b6020919350806001915483858901015201910190918492611d1d565b60209350611d099592507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0091501682840152151560051b82010138611cfc565b9060405191611da08361160f565b8263ffffffff8254168152600182015460208201526002820160405190611dc6826115a8565b8054611dd18161180a565b91611ddf604051938461162b565b818352602083019060005260206000206000915b838310611ebd57505050508152611e0c60038401611cd0565b60208201526040820152600482019160405192611e28846115a8565b8054611e338161180a565b91611e41604051938461162b565b818352602083019060005260206000206000915b838310611e7b5750505050600560609392611e7292865201611cd0565b60208401520152565b60026020600192604051611e8e816115f3565b67ffffffffffffffff8654818116835260401c1683820152848601546040820152815201920192019190611e55565b60026020600192604051611ed0816115a8565b855481528486015483820152815201920192019190611df3565b611ef2611ca0565b9060005b6002811015611f4257600060068202908360038301541480611f39575b611f21575050600101611ef6565b91509150611f33925050600201611d92565b90600190565b50831515611f13565b505090600090565b9060005b60028110156123865760006006820290836003830154148061237d575b611f79575050600101611f4e565b90915092919250611f976004820154611f9236856118ac565b612413565b6000906006810183357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1853603018112156115a05784019081359167ffffffffffffffff831161156b57602001606083023603811361156b5768010000000000000000831161235057815483835580841061229e575b509084526020842084915b8383106122245750505050600701906120346020840184611ad9565b919067ffffffffffffffff83116121f75761204f8454611b2a565b601f81116121b2575b5081601f84116001146120ec57926120dc949281927f1f69d1a2edb327babc986b3deb80091f101b9105d42a6c30db4d99c31d7e62949795926120e1575b50507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8260011b9260031b1c19161790555b604051918291602083526020830190611b92565b0390a2565b013590503880612096565b917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0841685845260208420935b81811061219a57509260019285927f1f69d1a2edb327babc986b3deb80091f101b9105d42a6c30db4d99c31d7e629498966120dc989610612162575b505050811b0190556120c8565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88560031b161c19910135169055388080612155565b91936020600181928787013581550195019201612119565b84835260208320601f850160051c810191602086106121ed575b601f0160051c01905b8181106121e25750612058565b8381556001016121d5565b90915081906121cc565b6024827f4e487b710000000000000000000000000000000000000000000000000000000081526041600452fd5b600260608267ffffffffffffffff61223d600195611b7d565b168554907fffffffffffffffffffffffffffffffff000000000000000000000000000000006fffffffffffffffff000000000000000061227f60208601611b7d565b60401b1692161717855560408101358486015501920192019190612018565b7f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81168103612323577f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8416840361232357828652602086209060011b8101908460011b015b818110612311575061200d565b80876002925587600182015501612304565b6024867f4e487b710000000000000000000000000000000000000000000000000000000081526011600452fd5b6024857f4e487b710000000000000000000000000000000000000000000000000000000081526041600452fd5b50831515611f6b565b507fd0b2c0310000000000000000000000000000000000000000000000000000000060005260045260246000fd5b73ffffffffffffffffffffffffffffffffffffffff6001541633036123d557565b7f2b5c74de0000000000000000000000000000000000000000000000000000000060005260046000fd5b80518210156101525760209160051b010190565b908151519160005b8381106124285750505050565b6124338183516123ff565b5160018201808311612508575b8581106125bf575060408101519084610100036101008111612508577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83911c81160361259557816000925b61253757506020015160011b6801fffffffffffffffe67fffffffffffffffe8216911681036125085760010167ffffffffffffffff81116125085767ffffffffffffffff16116124de5760010161241b565b7fa804bcb30000000000000000000000000000000000000000000000000000000060005260046000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8101908082116125085716917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff811461250857600101918061248c565b7f2847b6060000000000000000000000000000000000000000000000000000000060005260046000fd5b67ffffffffffffffff82511667ffffffffffffffff6125df8387516123ff565b515116146125ef57600101612440565b7f3857f84d0000000000000000000000000000000000000000000000000000000060005260046000fdfea164736f6c634300081a000a", + Bin: "0x6080604052600e80546001600160401b03191690553480156200002157600080fd5b50336000816200004457604051639b15e16f60e01b815260040160405180910390fd5b600180546001600160a01b0319166001600160a01b0384811691909117909155811615620000775762000077816200007f565b5050620000f9565b336001600160a01b03821603620000a957604051636d6c4ee560e11b815260040160405180910390fd5b600080546001600160a01b0319166001600160a01b03838116918217835560015460405192939116917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6128cb80620001096000396000f3fe608060405234801561001057600080fd5b50600436106100df5760003560e01c80636dd5b69d1161008c5780638c76967f116100665780638c76967f146101d45780638da5cb5b146101e7578063f2fde38b1461020f578063fb4022d41461022257600080fd5b80636dd5b69d14610196578063736be802146101b757806379ba5097146101cc57600080fd5b80633567e6b4116100bd5780633567e6b41461015b57806338354c5c14610178578063635079561461018057600080fd5b8063118dbac5146100e4578063123e65db1461010a578063181f5a7714610112575b600080fd5b6100f76100f236600461186a565b610235565b6040519081526020015b60405180910390f35b6100f7610418565b61014e6040518060400160405280601181526020017f524d4e486f6d6520312e362e302d64657600000000000000000000000000000081525081565b6040516101019190611945565b610163610457565b60408051928352602083019190915201610101565b6100f76104d8565b6101886104f7565b604051610101929190611ab0565b6101a96101a4366004611ad5565b610a79565b604051610101929190611aee565b6101ca6101c5366004611b12565b610d5d565b005b6101ca610e79565b6101ca6101e2366004611b57565b610f47565b60015460405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610101565b6101ca61021d366004611b79565b61115a565b6101ca610230366004611ad5565b61116e565b600061023f61128a565b61025961024b85611d2b565b61025485611e2c565b6112dd565b60006102636104d8565b90508281146102ad576040517f93df584c00000000000000000000000000000000000000000000000000000000815260048101829052602481018490526044015b60405180910390fd5b80156102df5760405183907f53f5d9228f0a4173bea6e5931c9b3afe6eeb6692ede1d182952970f152534e3b90600090a25b600e80546000919082906102f89063ffffffff16611f41565b91906101000a81548163ffffffff021916908363ffffffff160217905590506103408660405160200161032b91906120ec565b60405160208183030381529060405282611455565b600e54909350600090600290640100000000900463ffffffff1660011863ffffffff1660028110610373576103736120ff565b600602016001810185905580547fffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000001663ffffffff8416178155905086600282016103bd828261234c565b50869050600482016103cf828261254b565b905050837ff6c6d1be15ba0acc8ee645c1ec613c360ef786d2d3200eb8e695b6dec757dbf08389896040516104069392919061278f565b60405180910390a25050509392505050565b60006002610434600e5463ffffffff6401000000009091041690565b63ffffffff166002811061044a5761044a6120ff565b6006020160010154905090565b6000806002610474600e5463ffffffff6401000000009091041690565b63ffffffff166002811061048a5761048a6120ff565b600602016001015460026104b2600e54600163ffffffff640100000000909204919091161890565b63ffffffff16600281106104c8576104c86120ff565b6006020160010154915091509091565b600e54600090600290640100000000900463ffffffff16600118610434565b6104ff6117ec565b6105076117ec565b60006002610523600e5463ffffffff6401000000009091041690565b63ffffffff1660028110610539576105396120ff565b6040805160808101825260069290920292909201805463ffffffff16825260018101546020808401919091528351600283018054606093810283018401875282870181815295969495948701949293919284929091849160009085015b828210156105dc57838290600052602060002090600202016040518060400160405290816000820154815260200160018201548152505081526020019060010190610596565b5050505081526020016001820180546105f490612193565b80601f016020809104026020016040519081016040528092919081815260200182805461062090612193565b801561066d5780601f106106425761010080835404028352916020019161066d565b820191906000526020600020905b81548152906001019060200180831161065057829003601f168201915b50505050508152505081526020016004820160405180604001604052908160008201805480602002602001604051908101604052809291908181526020016000905b8282101561070f5760008481526020908190206040805160608101825260028602909201805467ffffffffffffffff80821685526801000000000000000090910416838501526001908101549183019190915290835290920191016106af565b50505050815260200160018201805461072790612193565b80601f016020809104026020016040519081016040528092919081815260200182805461075390612193565b80156107a05780601f10610775576101008083540402835291602001916107a0565b820191906000526020600020905b81548152906001019060200180831161078357829003601f168201915b505050919092525050509052506020810151909150156107be578092505b600e54600090600290640100000000900463ffffffff1660011863ffffffff16600281106107ee576107ee6120ff565b6040805160808101825260069290920292909201805463ffffffff16825260018101546020808401919091528351600283018054606093810283018401875282870181815295969495948701949293919284929091849160009085015b828210156108915783829060005260206000209060020201604051806040016040529081600082015481526020016001820154815250508152602001906001019061084b565b5050505081526020016001820180546108a990612193565b80601f01602080910402602001604051908101604052809291908181526020018280546108d590612193565b80156109225780601f106108f757610100808354040283529160200191610922565b820191906000526020600020905b81548152906001019060200180831161090557829003601f168201915b50505050508152505081526020016004820160405180604001604052908160008201805480602002602001604051908101604052809291908181526020016000905b828210156109c45760008481526020908190206040805160608101825260028602909201805467ffffffffffffffff8082168552680100000000000000009091041683850152600190810154918301919091529083529092019101610964565b5050505081526020016001820180546109dc90612193565b80601f0160208091040260200160405190810160405280929190818152602001828054610a0890612193565b8015610a555780601f10610a2a57610100808354040283529160200191610a55565b820191906000526020600020905b815481529060010190602001808311610a3857829003601f168201915b50505091909252505050905250602081015190915015610a73578092505b50509091565b610a816117ec565b6000805b6002811015610d52578360028260028110610aa257610aa26120ff565b6006020160010154148015610ab657508315155b15610d4a5760028160028110610ace57610ace6120ff565b6040805160808101825260069290920292909201805463ffffffff16825260018082015460208085019190915284516002840180546060938102830184018852828801818152959794969588958701948492849160009085015b82821015610b6e57838290600052602060002090600202016040518060400160405290816000820154815260200160018201548152505081526020019060010190610b28565b505050508152602001600182018054610b8690612193565b80601f0160208091040260200160405190810160405280929190818152602001828054610bb290612193565b8015610bff5780601f10610bd457610100808354040283529160200191610bff565b820191906000526020600020905b815481529060010190602001808311610be257829003601f168201915b50505050508152505081526020016004820160405180604001604052908160008201805480602002602001604051908101604052809291908181526020016000905b82821015610ca15760008481526020908190206040805160608101825260028602909201805467ffffffffffffffff8082168552680100000000000000009091041683850152600190810154918301919091529083529092019101610c41565b505050508152602001600182018054610cb990612193565b80601f0160208091040260200160405190810160405280929190818152602001828054610ce590612193565b8015610d325780601f10610d0757610100808354040283529160200191610d32565b820191906000526020600020905b815481529060010190602001808311610d1557829003601f168201915b50505091909252505050905250969095509350505050565b600101610a85565b509092600092509050565b610d6561128a565b60005b6002811015610e3f578160028260028110610d8557610d856120ff565b6006020160010154148015610d9957508115155b15610e3757610dd0610daa84611e2c565b60028360028110610dbd57610dbd6120ff565b600602016002016000018054905061155d565b8260028260028110610de457610de46120ff565b600602016004018181610df7919061254b565b905050817f1f69d1a2edb327babc986b3deb80091f101b9105d42a6c30db4d99c31d7e629484604051610e2a91906127ca565b60405180910390a2505050565b600101610d68565b506040517fd0b2c031000000000000000000000000000000000000000000000000000000008152600481018290526024016102a4565b5050565b60005473ffffffffffffffffffffffffffffffffffffffff163314610eca576040517f02b543c600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000008082163390811790935560008054909116815560405173ffffffffffffffffffffffffffffffffffffffff909216929183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b610f4f61128a565b81158015610f5b575080155b15610f92576040517f7b4d1e4f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600e54600163ffffffff6401000000009092048216181682600282818110610fbc57610fbc6120ff565b6006020160010154146110225760028160028110610fdc57610fdc6120ff565b6006020160010154836040517f93df584c0000000000000000000000000000000000000000000000000000000081526004016102a4929190918252602082015260400190565b6000600261103e600e5463ffffffff6401000000009091041690565b63ffffffff1660028110611054576110546120ff565b600602019050828160010154146110a75760018101546040517f93df584c0000000000000000000000000000000000000000000000000000000081526004810191909152602481018490526044016102a4565b6000600180830191909155600e805463ffffffff6401000000008083048216909418169092027fffffffffffffffffffffffffffffffffffffffffffffffff00000000ffffffff90921691909117905582156111295760405183907f0b31c0055e2d464bef7781994b98c4ff9ef4ae0d05f59feb6a68c42de5e201b890600090a25b60405184907ffc3e98dbbd47c3fa7c1c05b6ec711caeaf70eca4554192b9ada8fc11a37f298e90600090a250505050565b61116261128a565b61116b81611728565b50565b61117661128a565b806111ad576040517f0849d8cc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600e54600163ffffffff64010000000090920482161816816002828181106111d7576111d76120ff565b60060201600101541461123d57600281600281106111f7576111f76120ff565b6006020160010154826040517f93df584c0000000000000000000000000000000000000000000000000000000081526004016102a4929190918252602082015260400190565b60405182907f53f5d9228f0a4173bea6e5931c9b3afe6eeb6692ede1d182952970f152534e3b90600090a26002816002811061127b5761127b6120ff565b60060201600101600090555050565b60015473ffffffffffffffffffffffffffffffffffffffff1633146112db576040517f2b5c74de00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b565b815151610100101561131b576040517faf26d5e300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b8251518110156114455760006113358260016127dd565b90505b83515181101561143c578351805182908110611356576113566120ff565b60200260200101516000015184600001518381518110611378576113786120ff565b602002602001015160000151036113bb576040517f221a8ae800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b83518051829081106113cf576113cf6120ff565b602002602001015160200151846000015183815181106113f1576113f16120ff565b60200260200101516020015103611434576040517fae00651d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600101611338565b5060010161131e565b50610e758183600001515161155d565b604080517f45564d00000000000000000000000000000000000000000000000000000000006020820152469181019190915230606082015263ffffffff821660808201526000907dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9060a001604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152908290526114fc9186906020016127f0565b604080518083037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe00181529190528051602090910120167e0b0000000000000000000000000000000000000000000000000000000000001790505b92915050565b81515160005b8181101561172257600084600001518281518110611583576115836120ff565b60200260200101519050600082600161159c91906127dd565b90505b8381101561161f5785518051829081106115bb576115bb6120ff565b60200260200101516000015167ffffffffffffffff16826000015167ffffffffffffffff1603611617576040517f3857f84d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60010161159f565b506040810151806116328661010061281f565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff901c82161461168e576040517f2847b60600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b81156116b6576116a260018361281f565b909116906116af81612832565b9050611691565b60208301516116c690600261286a565b6116d1906001612896565b67ffffffffffffffff16811015611714576040517fa804bcb300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505050806001019050611563565b50505050565b3373ffffffffffffffffffffffffffffffffffffffff821603611777576040517fdad89dca00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff838116918217835560015460405192939116917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6040518060800160405280600063ffffffff1681526020016000801916815260200161182b604051806040016040528060608152602001606081525090565b815260200161184d604051806040016040528060608152602001606081525090565b905290565b60006040828403121561186457600080fd5b50919050565b60008060006060848603121561187f57600080fd5b833567ffffffffffffffff8082111561189757600080fd5b6118a387838801611852565b945060208601359150808211156118b957600080fd5b506118c686828701611852565b925050604084013590509250925092565b60005b838110156118f25781810151838201526020016118da565b50506000910152565b600081518084526119138160208601602086016118d7565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60208152600061195860208301846118fb565b9392505050565b8051604080845281518482018190526000926060916020918201918388019190865b828110156119bb578451805167ffffffffffffffff9081168652838201511683860152870151878501529381019392850192600101611981565b50808801519550888303818a015250506119d581856118fb565b979650505050505050565b63ffffffff81511682526000602080830151818501526040808401516080604087015260c0860181516040608089015281815180845260e08a0191508683019350600092505b80831015611a4f5783518051835287015187830152928601926001929092019190850190611a26565b50948301518886037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff800160a08a015294611a8981876118fb565b9550505050505060608301518482036060860152611aa7828261195f565b95945050505050565b604081526000611ac360408301856119e0565b8281036020840152611aa781856119e0565b600060208284031215611ae757600080fd5b5035919050565b604081526000611b0160408301856119e0565b905082151560208301529392505050565b60008060408385031215611b2557600080fd5b823567ffffffffffffffff811115611b3c57600080fd5b611b4885828601611852565b95602094909401359450505050565b60008060408385031215611b6a57600080fd5b50508035926020909101359150565b600060208284031215611b8b57600080fd5b813573ffffffffffffffffffffffffffffffffffffffff8116811461195857600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff81118282101715611c0157611c01611baf565b60405290565b6040516060810167ffffffffffffffff81118282101715611c0157611c01611baf565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715611c7157611c71611baf565b604052919050565b600067ffffffffffffffff821115611c9357611c93611baf565b5060051b60200190565b600082601f830112611cae57600080fd5b813567ffffffffffffffff811115611cc857611cc8611baf565b611cf960207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601611c2a565b818152846020838601011115611d0e57600080fd5b816020850160208301376000918101602001919091529392505050565b60006040808336031215611d3e57600080fd5b611d46611bde565b833567ffffffffffffffff80821115611d5e57600080fd5b9085019036601f830112611d7157600080fd5b81356020611d86611d8183611c79565b611c2a565b82815260069290921b84018101918181019036841115611da557600080fd5b948201945b83861015611de557878636031215611dc25760008081fd5b611dca611bde565b86358152838701358482015282529487019490820190611daa565b86525087810135955082861115611dfb57600080fd5b611e0736878a01611c9d565b90850152509195945050505050565b67ffffffffffffffff8116811461116b57600080fd5b60006040808336031215611e3f57600080fd5b611e47611bde565b833567ffffffffffffffff80821115611e5f57600080fd5b9085019036601f830112611e7257600080fd5b81356020611e82611d8183611c79565b82815260609283028501820192828201919036851115611ea157600080fd5b958301955b84871015611efb57808736031215611ebe5760008081fd5b611ec6611c07565b8735611ed181611e16565b815287850135611ee081611e16565b81860152878a01358a82015283529586019591830191611ea6565b5086525087810135955082861115611dfb57600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600063ffffffff808316818103611f5a57611f5a611f12565b6001019392505050565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112611f9957600080fd5b830160208101925035905067ffffffffffffffff811115611fb957600080fd5b803603821315611fc857600080fd5b9250929050565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b6000604080840183357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe185360301811261205157600080fd5b8401602081810191359067ffffffffffffffff82111561207057600080fd5b8160061b360383131561208257600080fd5b6040885292819052909160009190606088015b828410156120bb5784358152818501358282015293850193600193909301928501612095565b6120c86020890189611f64565b9650945088810360208a01526120df818787611fcf565b9998505050505050505050565b6020815260006119586020830184612018565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261216357600080fd5b83018035915067ffffffffffffffff82111561217e57600080fd5b602001915036819003821315611fc857600080fd5b600181811c908216806121a757607f821691505b602082108103611864577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b601f82111561222c576000816000526020600020601f850160051c810160208610156122095750805b601f850160051c820191505b8181101561222857828155600101612215565b5050505b505050565b67ffffffffffffffff83111561224957612249611baf565b61225d836122578354612193565b836121e0565b6000601f8411600181146122af57600085156122795750838201355b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600387901b1c1916600186901b178355612345565b6000838152602090207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0861690835b828110156122fe57868501358255602094850194600190920191016122de565b5086821015612339577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88860031b161c19848701351681555b505060018560011b0183555b5050505050565b81357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe183360301811261237e57600080fd5b8201803567ffffffffffffffff81111561239757600080fd5b6020820191508060061b36038213156123af57600080fd5b680100000000000000008111156123c8576123c8611baf565b8254818455808210156124555760017f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff808316831461240957612409611f12565b808416841461241a5761241a611f12565b5060008560005260206000208360011b81018560011b820191505b80821015612450578282558284830155600282019150612435565b505050505b5060008381526020902060005b8281101561248e5783358255602084013560018301556040939093019260029190910190600101612462565b5050505061249f602083018361212e565b611722818360018601612231565b81356124b881611e16565b67ffffffffffffffff811690508154817fffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000821617835560208401356124fc81611e16565b6fffffffffffffffff00000000000000008160401b16837fffffffffffffffffffffffffffffffff00000000000000000000000000000000841617178455505050604082013560018201555050565b81357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe183360301811261257d57600080fd5b8201803567ffffffffffffffff81111561259657600080fd5b602082019150606080820236038313156125af57600080fd5b680100000000000000008211156125c8576125c8611baf565b8354828555808310156126555760017f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff808316831461260957612609611f12565b808516851461261a5761261a611f12565b5060008660005260206000208360011b81018660011b820191505b80821015612650578282558284830155600282019150612635565b505050505b5060008481526020902060005b838110156126875761267485836124ad565b9382019360029190910190600101612662565b505050505061249f602083018361212e565b6000604080840183357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18536030181126126d257600080fd5b8401602081810191359067ffffffffffffffff808311156126f257600080fd5b6060808402360385131561270557600080fd5b60408a529483905292936000939060608a015b8486101561275c57863561272b81611e16565b831681528684013561273c81611e16565b831681850152868801358882015295810195600195909501948101612718565b61276960208b018b611f64565b985096508a810360208c0152612780818989611fcf565b9b9a5050505050505050505050565b63ffffffff841681526060602082015260006127ae6060830185612018565b82810360408401526127c08185612699565b9695505050505050565b6020815260006119586020830184612699565b8082018082111561155757611557611f12565b600083516128028184602088016118d7565b8351908301906128168183602088016118d7565b01949350505050565b8181038181111561155757611557611f12565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361286357612863611f12565b5060010190565b67ffffffffffffffff81811683821602808216919082811461288e5761288e611f12565b505092915050565b67ffffffffffffffff8181168382160190808211156128b7576128b7611f12565b509291505056fea164736f6c6343000818000a", } var RMNHomeABI = RMNHomeMetaData.ABI diff --git a/core/gethwrappers/ccip/generated/rmn_proxy_contract/rmn_proxy_contract.go b/core/gethwrappers/ccip/generated/rmn_proxy_contract/rmn_proxy_contract.go index 1931488a5db..18fd9898d81 100644 --- a/core/gethwrappers/ccip/generated/rmn_proxy_contract/rmn_proxy_contract.go +++ b/core/gethwrappers/ccip/generated/rmn_proxy_contract/rmn_proxy_contract.go @@ -32,7 +32,7 @@ var ( var RMNProxyContractMetaData = &bind.MetaData{ ABI: "[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"arm\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"arm\",\"type\":\"address\"}],\"name\":\"ARMSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"stateMutability\":\"nonpayable\",\"type\":\"fallback\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getARM\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"arm\",\"type\":\"address\"}],\"name\":\"setARM\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", - Bin: "0x60803461012f5760009061079a3881900390601f8201601f191683016001600160401b0381118482101761011b579180849260209460405283398101031261011757516001600160a01b03811691908290036101145733156100cf5780546001600160a01b0319163317905580156100be57600280546001600160a01b031916821790556040519081527fef31f568d741a833c6a9dc85a6e1c65e06fa772740d5dc94d1da21827a4e0cab90602090a160405161066590816101358239f35b6342bcdf7f60e11b60005260046000fd5b60405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f00000000000000006044820152606490fd5b80fd5b5080fd5b634e487b7160e01b85526041600452602485fd5b600080fdfe6080604052600436101561001a575b3415610598575b600080fd5b60003560e01c8063181f5a771461007a5780632e90aa2114610075578063458fec3b1461007057806379ba50971461006b5780638da5cb5b146100665763f2fde38b0361000e5761049b565b610449565b6102ee565b61023b565b61019c565b346100155760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261001557604051604081019080821067ffffffffffffffff8311176101055761010191604052600e81527f41524d50726f787920312e302e30000000000000000000000000000000000000602082015260405191829182610134565b0390f35b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b9190916020815282519283602083015260005b8481106101865750507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8460006040809697860101520116010190565b8060208092840101516040828601015201610147565b346100155760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261001557602073ffffffffffffffffffffffffffffffffffffffff60025416604051908152f35b7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc60209101126100155760043573ffffffffffffffffffffffffffffffffffffffff811681036100155790565b346100155773ffffffffffffffffffffffffffffffffffffffff61025e366101ee565b6102666105d9565b1680156102c4576020817fef31f568d741a833c6a9dc85a6e1c65e06fa772740d5dc94d1da21827a4e0cab927fffffffffffffffffffffffff00000000000000000000000000000000000000006002541617600255604051908152a1005b7f8579befe0000000000000000000000000000000000000000000000000000000060005260046000fd5b346100155760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126100155773ffffffffffffffffffffffffffffffffffffffff6001541633036103eb5760005473ffffffffffffffffffffffffffffffffffffffff16600080547fffffffffffffffffffffffff000000000000000000000000000000000000000016331790556103ac7fffffffffffffffffffffffff000000000000000000000000000000000000000060015416600155565b73ffffffffffffffffffffffffffffffffffffffff3391167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0600080a3005b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e6572000000000000000000006044820152fd5b346100155760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261001557602073ffffffffffffffffffffffffffffffffffffffff60005416604051908152f35b346100155773ffffffffffffffffffffffffffffffffffffffff6104be366101ee565b6104c66105d9565b1633811461053a57807fffffffffffffffffffffffff0000000000000000000000000000000000000000600154161760015573ffffffffffffffffffffffffffffffffffffffff8060005416167fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae1278600080a3005b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152fd5b73ffffffffffffffffffffffffffffffffffffffff60025416803b15610015576000809136828037818036925af13d6000803e6105d4573d6000fd5b3d6000f35b73ffffffffffffffffffffffffffffffffffffffff6000541633036105fa57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152fdfea164736f6c634300081a000a", + Bin: "0x608060405234801561001057600080fd5b5060405161084138038061084183398101604081905261002f91610255565b33806000816100855760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b03848116919091179091558116156100b5576100b5816100cd565b5050506100c78161017660201b60201c565b50610285565b336001600160a01b038216036101255760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640161007c565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b61017e6101f9565b6001600160a01b0381166101a5576040516342bcdf7f60e11b815260040160405180910390fd5b600280546001600160a01b0319166001600160a01b0383169081179091556040519081527fef31f568d741a833c6a9dc85a6e1c65e06fa772740d5dc94d1da21827a4e0cab9060200160405180910390a150565b6000546001600160a01b031633146102535760405162461bcd60e51b815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e657200000000000000000000604482015260640161007c565b565b60006020828403121561026757600080fd5b81516001600160a01b038116811461027e57600080fd5b9392505050565b6105ad806102946000396000f3fe608060405234801561001057600080fd5b50600436106100725760003560e01c806379ba50971161005057806379ba5097146101615780638da5cb5b14610169578063f2fde38b1461018757610072565b8063181f5a77146100bb5780632e90aa211461010d578063458fec3b1461014c575b60025473ffffffffffffffffffffffffffffffffffffffff16803b61009657600080fd5b366000803760008036600080855af13d6000803e80156100b5573d6000f35b503d6000fd5b6100f76040518060400160405280600e81526020017f41524d50726f787920312e302e3000000000000000000000000000000000000081525081565b60405161010491906104f6565b60405180910390f35b60025473ffffffffffffffffffffffffffffffffffffffff165b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610104565b61015f61015a366004610563565b61019a565b005b61015f610268565b60005473ffffffffffffffffffffffffffffffffffffffff16610127565b61015f610195366004610563565b61036a565b6101a261037e565b73ffffffffffffffffffffffffffffffffffffffff81166101ef576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040519081527fef31f568d741a833c6a9dc85a6e1c65e06fa772740d5dc94d1da21827a4e0cab9060200160405180910390a150565b60015473ffffffffffffffffffffffffffffffffffffffff1633146102ee576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064015b60405180910390fd5b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b61037261037e565b61037b81610401565b50565b60005473ffffffffffffffffffffffffffffffffffffffff1633146103ff576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e65720000000000000000000060448201526064016102e5565b565b3373ffffffffffffffffffffffffffffffffffffffff821603610480576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c6600000000000000000060448201526064016102e5565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b60006020808352835180602085015260005b8181101561052457858101830151858201604001528201610508565b5060006040828601015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8301168501019250505092915050565b60006020828403121561057557600080fd5b813573ffffffffffffffffffffffffffffffffffffffff8116811461059957600080fd5b939250505056fea164736f6c6343000818000a", } var RMNProxyContractABI = RMNProxyContractMetaData.ABI diff --git a/core/gethwrappers/ccip/generated/rmn_remote/rmn_remote.go b/core/gethwrappers/ccip/generated/rmn_remote/rmn_remote.go index f6a9226bf1e..dd7655b92a1 100644 --- a/core/gethwrappers/ccip/generated/rmn_remote/rmn_remote.go +++ b/core/gethwrappers/ccip/generated/rmn_remote/rmn_remote.go @@ -35,11 +35,6 @@ type IRMNRemoteSignature struct { S [32]byte } -type IRMNTaggedRoot struct { - CommitStore common.Address - Root [32]byte -} - type InternalMerkleRoot struct { SourceChainSelector uint64 OnRampAddress []byte @@ -60,15 +55,15 @@ type RMNRemoteSigner struct { } var RMNRemoteMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"localChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"contractIRMN\",\"name\":\"legacyRMN\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"bytes16\",\"name\":\"subject\",\"type\":\"bytes16\"}],\"name\":\"AlreadyCursed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CannotTransferToSelf\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ConfigNotSet\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"DuplicateOnchainPublicKey\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidSignature\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidSignerOrder\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IsBlessedNotAvailable\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MustBeProposedOwner\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes16\",\"name\":\"subject\",\"type\":\"bytes16\"}],\"name\":\"NotCursed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NotEnoughSigners\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByOwner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OutOfOrderSignatures\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OwnerCannotBeZero\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ThresholdNotMet\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnexpectedSigner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroValueNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint32\",\"name\":\"version\",\"type\":\"uint32\"},{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"rmnHomeContractConfigDigest\",\"type\":\"bytes32\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"onchainPublicKey\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"nodeIndex\",\"type\":\"uint64\"}],\"internalType\":\"structRMNRemote.Signer[]\",\"name\":\"signers\",\"type\":\"tuple[]\"},{\"internalType\":\"uint64\",\"name\":\"f\",\"type\":\"uint64\"}],\"indexed\":false,\"internalType\":\"structRMNRemote.Config\",\"name\":\"config\",\"type\":\"tuple\"}],\"name\":\"ConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes16[]\",\"name\":\"subjects\",\"type\":\"bytes16[]\"}],\"name\":\"Cursed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes16[]\",\"name\":\"subjects\",\"type\":\"bytes16[]\"}],\"name\":\"Uncursed\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes16\",\"name\":\"subject\",\"type\":\"bytes16\"}],\"name\":\"curse\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes16[]\",\"name\":\"subjects\",\"type\":\"bytes16[]\"}],\"name\":\"curse\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getCursedSubjects\",\"outputs\":[{\"internalType\":\"bytes16[]\",\"name\":\"subjects\",\"type\":\"bytes16[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getLocalChainSelector\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"localChainSelector\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getReportDigestHeader\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"digestHeader\",\"type\":\"bytes32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getVersionedConfig\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"version\",\"type\":\"uint32\"},{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"rmnHomeContractConfigDigest\",\"type\":\"bytes32\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"onchainPublicKey\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"nodeIndex\",\"type\":\"uint64\"}],\"internalType\":\"structRMNRemote.Signer[]\",\"name\":\"signers\",\"type\":\"tuple[]\"},{\"internalType\":\"uint64\",\"name\":\"f\",\"type\":\"uint64\"}],\"internalType\":\"structRMNRemote.Config\",\"name\":\"config\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"commitStore\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"root\",\"type\":\"bytes32\"}],\"internalType\":\"structIRMN.TaggedRoot\",\"name\":\"taggedRoot\",\"type\":\"tuple\"}],\"name\":\"isBlessed\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes16\",\"name\":\"subject\",\"type\":\"bytes16\"}],\"name\":\"isCursed\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"isCursed\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"rmnHomeContractConfigDigest\",\"type\":\"bytes32\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"onchainPublicKey\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"nodeIndex\",\"type\":\"uint64\"}],\"internalType\":\"structRMNRemote.Signer[]\",\"name\":\"signers\",\"type\":\"tuple[]\"},{\"internalType\":\"uint64\",\"name\":\"f\",\"type\":\"uint64\"}],\"internalType\":\"structRMNRemote.Config\",\"name\":\"newConfig\",\"type\":\"tuple\"}],\"name\":\"setConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes16\",\"name\":\"subject\",\"type\":\"bytes16\"}],\"name\":\"uncurse\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes16[]\",\"name\":\"subjects\",\"type\":\"bytes16[]\"}],\"name\":\"uncurse\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"offRampAddress\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRampAddress\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"maxSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"merkleRoot\",\"type\":\"bytes32\"}],\"internalType\":\"structInternal.MerkleRoot[]\",\"name\":\"merkleRoots\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"internalType\":\"structIRMNRemote.Signature[]\",\"name\":\"signatures\",\"type\":\"tuple[]\"}],\"name\":\"verify\",\"outputs\":[],\"stateMutability\":\"view\",\"type\":\"function\"}]", - Bin: "0x60c0346100d357601f6121f938819003918201601f19168301916001600160401b038311848410176100d85780849260409485528339810103126100d35780516001600160401b038116918282036100d35760200151916001600160a01b03831683036100d35733156100c257600180546001600160a01b03191633179055156100b15760805260a05260405161210a90816100ef82396080518181816102fe0152610712015260a05181610f7d0152f35b63273e150360e21b60005260046000fd5b639b15e16f60e01b60005260046000fd5b600080fd5b634e487b7160e01b600052604160045260246000fdfe6080604052600436101561001257600080fd5b60003560e01c8063181f5a77146119ce578063198f0f77146112df5780631add205f146111145780632cbc26bb146110d3578063397796f7146110905780634d61677114610f3557806362eed41514610e155780636509a95414610dbc5780636d2d399314610c9c57806370a9089e146105f057806379ba5097146105075780638da5cb5b146104b55780639a19b329146103c7578063d881e09214610322578063eaa83ddd146102bf578063f2fde38b146101cf5763f8bb876e146100d757600080fd5b346101ca576100e536611b71565b6100ed611ec2565b60005b81518110156101955761012e7fffffffffffffffffffffffffffffffff000000000000000000000000000000006101278385611eae565b51166120a3565b1561013b576001016100f0565b610166907fffffffffffffffffffffffffffffffff0000000000000000000000000000000092611eae565b51167f19d5c79b0000000000000000000000000000000000000000000000000000000060005260045260246000fd5b6040517f1716e663a90a76d3b6c7e5f680673d1b051454c19c627e184c8daf28f3104f7490806101c58582611c38565b0390a1005b600080fd5b346101ca5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101ca5773ffffffffffffffffffffffffffffffffffffffff61021b611b36565b610223611ec2565b1633811461029557807fffffffffffffffffffffffff0000000000000000000000000000000000000000600054161760005573ffffffffffffffffffffffffffffffffffffffff600154167fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae1278600080a3005b7fdad89dca0000000000000000000000000000000000000000000000000000000060005260046000fd5b346101ca5760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101ca57602060405167ffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b346101ca5760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101ca5760405180602060065491828152019060066000527ff652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d3f9060005b8181106103b1576103ad856103a181870382611a67565b60405191829182611c38565b0390f35b825484526020909301926001928301920161038a565b346101ca576103d536611b71565b6103dd611ec2565b60005b81518110156104855761041e7fffffffffffffffffffffffffffffffff000000000000000000000000000000006104178385611eae565b5116611f0d565b1561042b576001016103e0565b610456907fffffffffffffffffffffffffffffffff0000000000000000000000000000000092611eae565b51167f73281fa10000000000000000000000000000000000000000000000000000000060005260045260246000fd5b6040517f0676e709c9cc74fa0519fd78f7c33be0f1b2b0bae0507c724aef7229379c6ba190806101c58582611c38565b346101ca5760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101ca57602073ffffffffffffffffffffffffffffffffffffffff60015416604051908152f35b346101ca5760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101ca5760005473ffffffffffffffffffffffffffffffffffffffff811633036105c6577fffffffffffffffffffffffff00000000000000000000000000000000000000006001549133828416176001551660005573ffffffffffffffffffffffffffffffffffffffff3391167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0600080a3005b7f02b543c60000000000000000000000000000000000000000000000000000000060005260046000fd5b346101ca5760607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101ca57610627611b36565b67ffffffffffffffff602435116101ca573660236024350112156101ca57602435600401359067ffffffffffffffff82116101ca573660248360051b81350101116101ca576044359067ffffffffffffffff82116101ca57366023830112156101ca5767ffffffffffffffff8260040135116101ca57366024836004013560061b840101116101ca5763ffffffff6005541615610c725767ffffffffffffffff6106d48160045416611d3c565b16826004013510610c485760025460405160c0810181811067ffffffffffffffff821117610c1957604052468152602081019267ffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168452604082019230845273ffffffffffffffffffffffffffffffffffffffff60608401921682526080830190815261076987611b59565b916107776040519384611a67565b8783526000976024803501602085015b60248360051b813501018210610a61575050509073ffffffffffffffffffffffffffffffffffffffff8095939260a0860193845260405196879567ffffffffffffffff602088019a7f9651943783dbf81935a60e98f218a9d9b5b28823fb2228bbd91320d632facf538c526040808a01526101208901995160608a015251166080880152511660a0860152511660c08401525160e08301525160c0610100830152805180935261014082019260206101408260051b85010192019388905b8282106109c8575050506108809250037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08101835282611a67565b5190208290815b83600401358310610896578480f35b60208560806108ad86886004013560248a01611ce8565b35836108c1888a6004013560248c01611ce8565b013560405191878352601b868401526040830152606082015282805260015afa156109bd5784519073ffffffffffffffffffffffffffffffffffffffff82169081156109955773ffffffffffffffffffffffffffffffffffffffff829116101561096d578552600860205260ff604086205416156109455760019290920191610887565b6004857faaaa9141000000000000000000000000000000000000000000000000000000008152fd5b6004867fbbe15e7f000000000000000000000000000000000000000000000000000000008152fd5b6004877f8baa579f000000000000000000000000000000000000000000000000000000008152fd5b6040513d86823e3d90fd5b91936020847ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffec08293600195970301855287519067ffffffffffffffff8251168152608080610a238585015160a08786015260a0850190611aa8565b9367ffffffffffffffff604082015116604085015267ffffffffffffffff606082015116606085015201519101529601920192018593919492610845565b81359067ffffffffffffffff8211610c155760a07fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdc836024350136030112610c15576040519060a0820182811067ffffffffffffffff821117610be457604052610ad060248481350101611d95565b82526044836024350101359167ffffffffffffffff8311610c115736604360243586018501011215610c115767ffffffffffffffff6024848682350101013511610be457908d9160207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f6024878982350101013501160193610b576040519586611a67565b60248035870182019081013580875236910160440111610be057602495602095869560a49387908a90813586018101808301359060440186850137858235010101358301015285840152610bb060648289350101611d95565b6040840152610bc460848289350101611d95565b6060840152863501013560808201528152019201919050610787565b8380fd5b60248e7f4e487b710000000000000000000000000000000000000000000000000000000081526041600452fd5b8d80fd5b8b80fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b7f59fa4a930000000000000000000000000000000000000000000000000000000060005260046000fd5b7face124bc0000000000000000000000000000000000000000000000000000000060005260046000fd5b346101ca5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101ca57610cd3611b07565b604090815190610ce38383611a67565b600182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe083013660208401377fffffffffffffffffffffffffffffffff00000000000000000000000000000000610d3a83611ea1565b91169052610d46611ec2565b60005b8151811015610d8d57610d807fffffffffffffffffffffffffffffffff000000000000000000000000000000006104178385611eae565b1561042b57600101610d49565b82517f0676e709c9cc74fa0519fd78f7c33be0f1b2b0bae0507c724aef7229379c6ba190806101c58582611c38565b346101ca5760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101ca5760206040517f9651943783dbf81935a60e98f218a9d9b5b28823fb2228bbd91320d632facf538152f35b346101ca5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101ca57610e4c611b07565b604090815190610e5c8383611a67565b600182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe083013660208401377fffffffffffffffffffffffffffffffff00000000000000000000000000000000610eb383611ea1565b91169052610ebf611ec2565b60005b8151811015610f0657610ef97fffffffffffffffffffffffffffffffff000000000000000000000000000000006101278385611eae565b1561013b57600101610ec2565b82517f1716e663a90a76d3b6c7e5f680673d1b051454c19c627e184c8daf28f3104f7490806101c58582611c38565b346101ca5760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101ca57600073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168015611068576020604491604051928380927f4d61677100000000000000000000000000000000000000000000000000000000825273ffffffffffffffffffffffffffffffffffffffff610fef611b36565b16600483015260243560248301525afa90811561105d57829161101a575b6020826040519015158152f35b90506020813d602011611055575b8161103560209383611a67565b810103126110515751801515810361105157602091508261100d565b5080fd5b3d9150611028565b6040513d84823e3d90fd5b6004827f0a7c4edd000000000000000000000000000000000000000000000000000000008152fd5b346101ca5760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101ca5760206110c9611e44565b6040519015158152f35b346101ca5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101ca5760206110c961110f611b07565b611daa565b346101ca5760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101ca5760006040805161115281611a4b565b82815260606020820152015263ffffffff600554166040519061117482611a4b565b60025482526003549161118683611b59565b926111946040519485611a67565b808452600360009081527fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b9190602086015b82821061128057505050506020810192835267ffffffffffffffff6004541692604082019384526040519283526040602084015260a083019151604084015251906060808401528151809152602060c0840192019060005b81811061123e5750505067ffffffffffffffff8293511660808301520390f35b8251805173ffffffffffffffffffffffffffffffffffffffff16855260209081015167ffffffffffffffff16818601526040909401939092019160010161121e565b6040516040810181811067ffffffffffffffff821117610c1957600192839260209260405267ffffffffffffffff885473ffffffffffffffffffffffffffffffffffffffff8116835260a01c16838201528152019401910190926111c6565b346101ca5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101ca5760043567ffffffffffffffff81116101ca57806004018136039160607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc8401126101ca5761135a611ec2565b81359081156119a457909260248201919060015b6113788486611c94565b90508110156114595761138b8486611c94565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83019183831161142a576113cc926020926113c692611ce8565b01611d27565b67ffffffffffffffff806113ef60206113c6866113e98b8d611c94565b90611ce8565b16911610156114005760010161136e565b7f448515170000000000000000000000000000000000000000000000000000000060005260046000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b508390856114678584611c94565b60448601915061147682611d27565b60011b6801fffffffffffffffe67fffffffffffffffe82169116810361142a576114a867ffffffffffffffff91611d3c565b161161197a57600354805b611877575060005b6114c58786611c94565b905081101561159e5773ffffffffffffffffffffffffffffffffffffffff6114f96114f4836113e98b8a611c94565b611d74565b16600052600860205260ff60406000205416611574578073ffffffffffffffffffffffffffffffffffffffff6115386114f46001946113e98c8b611c94565b1660005260086020526040600020827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00825416179055016114bb565b7f28cae27d0000000000000000000000000000000000000000000000000000000060005260046000fd5b50846115b08780959685600255611c94565b90680100000000000000008211610c195760035482600355808310611831575b50600360005260206000206000915b838310611783575050505067ffffffffffffffff6115fc83611d27565b167fffffffffffffffffffffffffffffffffffffffffffffffff000000000000000060045416176004556005549463ffffffff86169563ffffffff871461142a5763ffffffff60017fffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000098011696879116176005557fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdd6040519560208752608087019560208801523591018112156101ca57016024600482013591019267ffffffffffffffff82116101ca578160061b360384136101ca578190606060408701525260a0840192906000905b80821061173057867f7f22bf988149dbe8de8fb879c6b97a4e56e68b2bd57421ce1a4e79d4ef6b496c87808867ffffffffffffffff6117258a611d95565b1660608301520390a2005b90919384359073ffffffffffffffffffffffffffffffffffffffff82168092036101ca5760408160019382935267ffffffffffffffff61177260208a01611d95565b1660208201520195019201906116e7565b600160408273ffffffffffffffffffffffffffffffffffffffff6117a78495611d74565b167fffffffffffffffffffffffff00000000000000000000000000000000000000008654161785556117db60208201611d27565b7fffffffff0000000000000000ffffffffffffffffffffffffffffffffffffffff7bffffffffffffffff000000000000000000000000000000000000000087549260a01b169116178555019201920191906115df565b60036000527fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b9081019083015b81811061186b57506115d0565b6000815560010161185e565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff810181811161142a57600090600354111561194d57600390527fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85a81015473ffffffffffffffffffffffffffffffffffffffff16600090815260086020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055801561142a577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01806114b3565b807f4e487b7100000000000000000000000000000000000000000000000000000000602492526032600452fd5b7f014c50200000000000000000000000000000000000000000000000000000000060005260046000fd5b7f9cf8540c0000000000000000000000000000000000000000000000000000000060005260046000fd5b346101ca5760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101ca576103ad6040805190611a0f8183611a67565b601382527f524d4e52656d6f746520312e362e302d64657600000000000000000000000000602083015251918291602083526020830190611aa8565b6060810190811067ffffffffffffffff821117610c1957604052565b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff821117610c1957604052565b919082519283825260005b848110611af25750507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8460006020809697860101520116010190565b80602080928401015182828601015201611ab3565b600435907fffffffffffffffffffffffffffffffff00000000000000000000000000000000821682036101ca57565b6004359073ffffffffffffffffffffffffffffffffffffffff821682036101ca57565b67ffffffffffffffff8111610c195760051b60200190565b60207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc8201126101ca576004359067ffffffffffffffff82116101ca57806023830112156101ca57816004013590611bc882611b59565b92611bd66040519485611a67565b8284526024602085019360051b8201019182116101ca57602401915b818310611bff5750505090565b82357fffffffffffffffffffffffffffffffff00000000000000000000000000000000811681036101ca57815260209283019201611bf2565b602060408183019282815284518094520192019060005b818110611c5c5750505090565b82517fffffffffffffffffffffffffffffffff0000000000000000000000000000000016845260209384019390920191600101611c4f565b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1813603018212156101ca570180359067ffffffffffffffff82116101ca57602001918160061b360383136101ca57565b9190811015611cf85760061b0190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b3567ffffffffffffffff811681036101ca5790565b67ffffffffffffffff60019116019067ffffffffffffffff821161142a57565b8054821015611cf85760005260206000200190600090565b3573ffffffffffffffffffffffffffffffffffffffff811681036101ca5790565b359067ffffffffffffffff821682036101ca57565b60065415611e3e577fffffffffffffffffffffffffffffffff0000000000000000000000000000000016600052600760205260406000205415801590611ded5790565b507f010000000000000000000000000000010000000000000000000000000000000060005260076020527f70b766b11586b6b505ed3893938b0cc6c6c98bd6f65e969ac311168d34e4f9e254151590565b50600090565b60065415611e9c577f010000000000000000000000000000010000000000000000000000000000000060005260076020527f70b766b11586b6b505ed3893938b0cc6c6c98bd6f65e969ac311168d34e4f9e254151590565b600090565b805115611cf85760200190565b8051821015611cf85760209160051b010190565b73ffffffffffffffffffffffffffffffffffffffff600154163303611ee357565b7f2b5c74de0000000000000000000000000000000000000000000000000000000060005260046000fd5b600081815260076020526040902054801561209c577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff810181811161142a57600654907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820191821161142a5781810361202d575b5050506006548015611ffe577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01611fbb816006611d5c565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82549160031b1b19169055600655600052600760205260006040812055600190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b61208461203e61204f936006611d5c565b90549060031b1c9283926006611d5c565b81939154907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9060031b92831b921b19161790565b90556000526007602052604060002055388080611f82565b5050600090565b80600052600760205260406000205415600014611e3e5760065468010000000000000000811015610c19576120e461204f8260018594016006556006611d5c565b905560065490600052600760205260406000205560019056fea164736f6c634300081a000a", + ABI: "[{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"localChainSelector\",\"type\":\"uint64\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"bytes16\",\"name\":\"subject\",\"type\":\"bytes16\"}],\"name\":\"AlreadyCursed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CannotTransferToSelf\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ConfigNotSet\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"DuplicateOnchainPublicKey\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidSignature\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidSignerOrder\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MustBeProposedOwner\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes16\",\"name\":\"subject\",\"type\":\"bytes16\"}],\"name\":\"NotCursed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NotEnoughSigners\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByOwner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OutOfOrderSignatures\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OwnerCannotBeZero\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ThresholdNotMet\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnexpectedSigner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroValueNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint32\",\"name\":\"version\",\"type\":\"uint32\"},{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"rmnHomeContractConfigDigest\",\"type\":\"bytes32\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"onchainPublicKey\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"nodeIndex\",\"type\":\"uint64\"}],\"internalType\":\"structRMNRemote.Signer[]\",\"name\":\"signers\",\"type\":\"tuple[]\"},{\"internalType\":\"uint64\",\"name\":\"f\",\"type\":\"uint64\"}],\"indexed\":false,\"internalType\":\"structRMNRemote.Config\",\"name\":\"config\",\"type\":\"tuple\"}],\"name\":\"ConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes16[]\",\"name\":\"subjects\",\"type\":\"bytes16[]\"}],\"name\":\"Cursed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes16[]\",\"name\":\"subjects\",\"type\":\"bytes16[]\"}],\"name\":\"Uncursed\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes16\",\"name\":\"subject\",\"type\":\"bytes16\"}],\"name\":\"curse\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes16[]\",\"name\":\"subjects\",\"type\":\"bytes16[]\"}],\"name\":\"curse\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getCursedSubjects\",\"outputs\":[{\"internalType\":\"bytes16[]\",\"name\":\"subjects\",\"type\":\"bytes16[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getLocalChainSelector\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"localChainSelector\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getReportDigestHeader\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"digestHeader\",\"type\":\"bytes32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getVersionedConfig\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"version\",\"type\":\"uint32\"},{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"rmnHomeContractConfigDigest\",\"type\":\"bytes32\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"onchainPublicKey\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"nodeIndex\",\"type\":\"uint64\"}],\"internalType\":\"structRMNRemote.Signer[]\",\"name\":\"signers\",\"type\":\"tuple[]\"},{\"internalType\":\"uint64\",\"name\":\"f\",\"type\":\"uint64\"}],\"internalType\":\"structRMNRemote.Config\",\"name\":\"config\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes16\",\"name\":\"subject\",\"type\":\"bytes16\"}],\"name\":\"isCursed\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"isCursed\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"rmnHomeContractConfigDigest\",\"type\":\"bytes32\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"onchainPublicKey\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"nodeIndex\",\"type\":\"uint64\"}],\"internalType\":\"structRMNRemote.Signer[]\",\"name\":\"signers\",\"type\":\"tuple[]\"},{\"internalType\":\"uint64\",\"name\":\"f\",\"type\":\"uint64\"}],\"internalType\":\"structRMNRemote.Config\",\"name\":\"newConfig\",\"type\":\"tuple\"}],\"name\":\"setConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes16\",\"name\":\"subject\",\"type\":\"bytes16\"}],\"name\":\"uncurse\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes16[]\",\"name\":\"subjects\",\"type\":\"bytes16[]\"}],\"name\":\"uncurse\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"offrampAddress\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRampAddress\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"maxSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"merkleRoot\",\"type\":\"bytes32\"}],\"internalType\":\"structInternal.MerkleRoot[]\",\"name\":\"merkleRoots\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"internalType\":\"structIRMNRemote.Signature[]\",\"name\":\"signatures\",\"type\":\"tuple[]\"}],\"name\":\"verify\",\"outputs\":[],\"stateMutability\":\"view\",\"type\":\"function\"}]", + Bin: "0x60a06040523480156200001157600080fd5b50604051620020ff380380620020ff833981016040819052620000349162000142565b336000816200005657604051639b15e16f60e01b815260040160405180910390fd5b600180546001600160a01b0319166001600160a01b038481169190911790915581161562000089576200008981620000c8565b5050806001600160401b0316600003620000b65760405163273e150360e21b815260040160405180910390fd5b6001600160401b031660805262000174565b336001600160a01b03821603620000f257604051636d6c4ee560e11b815260040160405180910390fd5b600080546001600160a01b0319166001600160a01b03838116918217835560015460405192939116917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6000602082840312156200015557600080fd5b81516001600160401b03811681146200016d57600080fd5b9392505050565b608051611f68620001976000396000818161027a0152610a2c0152611f686000f3fe608060405234801561001057600080fd5b50600436106101005760003560e01c806370a9089e11610097578063d881e09211610066578063d881e09214610257578063eaa83ddd1461026c578063f2fde38b146102a4578063f8bb876e146102b757600080fd5b806370a9089e1461020157806379ba5097146102145780638da5cb5b1461021c5780639a19b3291461024457600080fd5b8063397796f7116100d3578063397796f7146101a557806362eed415146101ad5780636509a954146101c05780636d2d3993146101ee57600080fd5b8063181f5a7714610105578063198f0f77146101575780631add205f1461016c5780632cbc26bb14610182575b600080fd5b6101416040518060400160405280601381526020017f524d4e52656d6f746520312e362e302d6465760000000000000000000000000081525081565b60405161014e9190611389565b60405180910390f35b61016a61016536600461139c565b6102ca565b005b6101746106c4565b60405161014e9291906113d7565b6101956101903660046114b5565b6107bc565b604051901515815260200161014e565b610195610819565b61016a6101bb3660046114b5565b610893565b6040517f9651943783dbf81935a60e98f218a9d9b5b28823fb2228bbd91320d632facf53815260200161014e565b61016a6101fc3660046114b5565b610907565b61016a61020f36600461153e565b610977565b61016a610cd2565b60015460405173ffffffffffffffffffffffffffffffffffffffff909116815260200161014e565b61016a6102523660046116bd565b610da0565b61025f610ea6565b60405161014e919061175a565b60405167ffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016815260200161014e565b61016a6102b23660046117c0565b610eb2565b61016a6102c53660046116bd565b610ec6565b6102d2610fb8565b803561030a576040517f9cf8540c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60015b61031a60208301836117dd565b90508110156103ea5761033060208301836117dd565b8281811061034057610340611845565b90506040020160200160208101906103589190611895565b67ffffffffffffffff1661036f60208401846117dd565b61037a6001856118e1565b81811061038957610389611845565b90506040020160200160208101906103a19190611895565b67ffffffffffffffff16106103e2576040517f4485151700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60010161030d565b506103fb6060820160408301611895565b6104069060026118f4565b610411906001611920565b67ffffffffffffffff1661042860208301836117dd565b90501015610462576040517f014c502000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6003545b80156104f45760086000600361047d6001856118e1565b8154811061048d5761048d611845565b600091825260208083209091015473ffffffffffffffffffffffffffffffffffffffff168352820192909252604001902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001690556104ed81611941565b9050610466565b5060005b61050560208301836117dd565b905081101561063a576008600061051f60208501856117dd565b8481811061052f5761052f611845565b61054592602060409092020190810191506117c0565b73ffffffffffffffffffffffffffffffffffffffff16815260208101919091526040016000205460ff16156105a6576040517f28cae27d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600860006105b960208601866117dd565b858181106105c9576105c9611845565b6105df92602060409092020190810191506117c0565b73ffffffffffffffffffffffffffffffffffffffff168152602081019190915260400160002080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169115159190911790556001016104f8565b508060026106488282611a2f565b5050600580546000919082906106639063ffffffff16611b6a565b91906101000a81548163ffffffff021916908363ffffffff160217905590508063ffffffff167f7f22bf988149dbe8de8fb879c6b97a4e56e68b2bd57421ce1a4e79d4ef6b496c836040516106b89190611b8d565b60405180910390a25050565b6040805160608082018352600080835260208301919091529181018290526005546040805160608101825260028054825260038054845160208281028201810190965281815263ffffffff9096169592948593818601939092909160009084015b82821015610793576000848152602090819020604080518082019091529084015473ffffffffffffffffffffffffffffffffffffffff8116825274010000000000000000000000000000000000000000900467ffffffffffffffff1681830152825260019092019101610725565b505050908252506002919091015467ffffffffffffffff16602090910152919491935090915050565b60006107c8600661100b565b6000036107d757506000919050565b6107e2600683611015565b80610813575061081360067f0100000000000000000000000000000100000000000000000000000000000000611015565b92915050565b6000610825600661100b565b6000036108325750600090565b61085d60067f0100000000000000000000000000000000000000000000000000000000000000611015565b8061088e575061088e60067f0100000000000000000000000000000100000000000000000000000000000000611015565b905090565b6040805160018082528183019092526000916020808301908036833701905050905081816000815181106108c9576108c9611845565b7fffffffffffffffffffffffffffffffff000000000000000000000000000000009092166020928302919091019091015261090381610ec6565b5050565b60408051600180825281830190925260009160208083019080368337019050509050818160008151811061093d5761093d611845565b7fffffffffffffffffffffffffffffffff000000000000000000000000000000009092166020928302919091019091015261090381610da0565b60055463ffffffff166000036109b9576040517face124bc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6004546109d19067ffffffffffffffff166001611920565b67ffffffffffffffff16811015610a14576040517f59fa4a9300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805160c08101825246815267ffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000166020820152309181019190915273ffffffffffffffffffffffffffffffffffffffff8616606082015260025460808201526000907f9651943783dbf81935a60e98f218a9d9b5b28823fb2228bbd91320d632facf539060a08101610ab08789611c97565b9052604051610ac3929190602001611df7565b60405160208183030381529060405280519060200120905060008060005b84811015610cc757600184601b888885818110610b0057610b00611845565b90506040020160000135898986818110610b1c57610b1c611845565b9050604002016020013560405160008152602001604052604051610b5c949392919093845260ff9290921660208401526040830152606082015260800190565b6020604051602081039080840390855afa158015610b7e573d6000803e3d6000fd5b50506040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0015192505073ffffffffffffffffffffffffffffffffffffffff8216610bf6576040517f8baa579f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1610610c5b576040517fbbe15e7f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff821660009081526008602052604090205460ff16610cba576040517faaaa914100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b9091508190600101610ae1565b505050505050505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314610d23576040517f02b543c600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000008082163390811790935560008054909116815560405173ffffffffffffffffffffffffffffffffffffffff909216929183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b610da8610fb8565b60005b8151811015610e6b57610de1828281518110610dc957610dc9611845565b6020026020010151600661105390919063ffffffff16565b610e6357818181518110610df757610df7611845565b60200260200101516040517f73281fa1000000000000000000000000000000000000000000000000000000008152600401610e5a91907fffffffffffffffffffffffffffffffff0000000000000000000000000000000091909116815260200190565b60405180910390fd5b600101610dab565b507f0676e709c9cc74fa0519fd78f7c33be0f1b2b0bae0507c724aef7229379c6ba181604051610e9b919061175a565b60405180910390a150565b606061088e6006611081565b610eba610fb8565b610ec38161108e565b50565b610ece610fb8565b60005b8151811015610f8857610f07828281518110610eef57610eef611845565b6020026020010151600661115290919063ffffffff16565b610f8057818181518110610f1d57610f1d611845565b60200260200101516040517f19d5c79b000000000000000000000000000000000000000000000000000000008152600401610e5a91907fffffffffffffffffffffffffffffffff0000000000000000000000000000000091909116815260200190565b600101610ed1565b507f1716e663a90a76d3b6c7e5f680673d1b051454c19c627e184c8daf28f3104f7481604051610e9b919061175a565b60015473ffffffffffffffffffffffffffffffffffffffff163314611009576040517f2b5c74de00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b565b6000610813825490565b7fffffffffffffffffffffffffffffffff000000000000000000000000000000008116600090815260018301602052604081205415155b9392505050565b600061104c837fffffffffffffffffffffffffffffffff000000000000000000000000000000008416611180565b6060600061104c8361127a565b3373ffffffffffffffffffffffffffffffffffffffff8216036110dd576040517fdad89dca00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff838116918217835560015460405192939116917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b600061104c837fffffffffffffffffffffffffffffffff0000000000000000000000000000000084166112d6565b600081815260018301602052604081205480156112695760006111a46001836118e1565b85549091506000906111b8906001906118e1565b905080821461121d5760008660000182815481106111d8576111d8611845565b90600052602060002001549050808760000184815481106111fb576111fb611845565b6000918252602080832090910192909255918252600188019052604090208390555b855486908061122e5761122e611f2c565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050610813565b6000915050610813565b5092915050565b6060816000018054806020026020016040519081016040528092919081815260200182805480156112ca57602002820191906000526020600020905b8154815260200190600101908083116112b6575b50505050509050919050565b600081815260018301602052604081205461131d57508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155610813565b506000610813565b6000815180845260005b8181101561134b5760208185018101518683018201520161132f565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b60208152600061104c6020830184611325565b6000602082840312156113ae57600080fd5b813567ffffffffffffffff8111156113c557600080fd5b82016060818503121561104c57600080fd5b63ffffffff831681526040602080830182905283518383015283810151606080850152805160a085018190526000939291820190849060c08701905b8083101561145c578351805173ffffffffffffffffffffffffffffffffffffffff16835285015167ffffffffffffffff1685830152928401926001929092019190850190611413565b50604088015167ffffffffffffffff81166080890152945098975050505050505050565b80357fffffffffffffffffffffffffffffffff00000000000000000000000000000000811681146114b057600080fd5b919050565b6000602082840312156114c757600080fd5b61104c82611480565b73ffffffffffffffffffffffffffffffffffffffff81168114610ec357600080fd5b60008083601f84011261150457600080fd5b50813567ffffffffffffffff81111561151c57600080fd5b6020830191508360208260061b850101111561153757600080fd5b9250929050565b60008060008060006060868803121561155657600080fd5b8535611561816114d0565b9450602086013567ffffffffffffffff8082111561157e57600080fd5b818801915088601f83011261159257600080fd5b8135818111156115a157600080fd5b8960208260051b85010111156115b657600080fd5b6020830196508095505060408801359150808211156115d457600080fd5b506115e1888289016114f2565b969995985093965092949392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60405160a0810167ffffffffffffffff81118282101715611644576116446115f2565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715611691576116916115f2565b604052919050565b600067ffffffffffffffff8211156116b3576116b36115f2565b5060051b60200190565b600060208083850312156116d057600080fd5b823567ffffffffffffffff8111156116e757600080fd5b8301601f810185136116f857600080fd5b803561170b61170682611699565b61164a565b81815260059190911b8201830190838101908783111561172a57600080fd5b928401925b8284101561174f5761174084611480565b8252928401929084019061172f565b979650505050505050565b6020808252825182820181905260009190848201906040850190845b818110156117b45783517fffffffffffffffffffffffffffffffff000000000000000000000000000000001683529284019291840191600101611776565b50909695505050505050565b6000602082840312156117d257600080fd5b813561104c816114d0565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261181257600080fd5b83018035915067ffffffffffffffff82111561182d57600080fd5b6020019150600681901b360382131561153757600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b67ffffffffffffffff81168114610ec357600080fd5b80356114b081611874565b6000602082840312156118a757600080fd5b813561104c81611874565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b81810381811115610813576108136118b2565b67ffffffffffffffff818116838216028082169190828114611918576119186118b2565b505092915050565b67ffffffffffffffff818116838216019080821115611273576112736118b2565b600081611950576119506118b2565b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190565b6000813561081381611874565b813561198e816114d0565b73ffffffffffffffffffffffffffffffffffffffff811690508154817fffffffffffffffffffffffff0000000000000000000000000000000000000000821617835560208401356119de81611874565b7bffffffffffffffff00000000000000000000000000000000000000008160a01b16837fffffffff000000000000000000000000000000000000000000000000000000008416171784555050505050565b81358155600180820160208401357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1853603018112611a6d57600080fd5b8401803567ffffffffffffffff811115611a8657600080fd5b6020820191508060061b3603821315611a9e57600080fd5b68010000000000000000811115611ab757611ab76115f2565b825481845580821015611aec576000848152602081208381019083015b80821015611ae85782825590870190611ad4565b5050505b50600092835260208320925b81811015611b1c57611b0a8385611983565b92840192604092909201918401611af8565b5050505050610903611b3060408401611976565b6002830167ffffffffffffffff82167fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000008254161781555050565b600063ffffffff808316818103611b8357611b836118b2565b6001019392505050565b6000602080835260808301843582850152818501357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1863603018112611bd257600080fd5b8501828101903567ffffffffffffffff80821115611bef57600080fd5b8160061b3603831315611c0157600080fd5b6040606060408901528483865260a089019050849550600094505b83851015611c6c578535611c2f816114d0565b73ffffffffffffffffffffffffffffffffffffffff16815285870135611c5481611874565b83168188015294810194600194909401938101611c1c565b611c7860408b0161188a565b67ffffffffffffffff811660608b015296509998505050505050505050565b6000611ca561170684611699565b80848252602080830192508560051b850136811115611cc357600080fd5b855b81811015611deb57803567ffffffffffffffff80821115611ce65760008081fd5b818901915060a08236031215611cfc5760008081fd5b611d04611621565b8235611d0f81611874565b81528286013582811115611d235760008081fd5b8301601f3681830112611d365760008081fd5b813584811115611d4857611d486115f2565b611d77897fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0848401160161164a565b94508085523689828501011115611d9057600091508182fd5b808984018a8701376000898287010152505050818682015260409150611db782840161188a565b8282015260609150611dca82840161188a565b91810191909152608091820135918101919091528552938201938201611cc5565b50919695505050505050565b60006040848352602060408185015261010084018551604086015281860151606067ffffffffffffffff808316606089015260408901519250608073ffffffffffffffffffffffffffffffffffffffff80851660808b015260608b0151945060a081861660a08c015260808c015160c08c015260a08c0151955060c060e08c015286915085518088526101209750878c019250878160051b8d01019750888701965060005b81811015611f19577ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffee08d8a030184528751868151168a528a810151848c8c0152611ee8858c0182611325565b828e015189168c8f01528983015189168a8d0152918701519a87019a909a5298509689019692890192600101611e9c565b50969d9c50505050505050505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fdfea164736f6c6343000818000a", } var RMNRemoteABI = RMNRemoteMetaData.ABI var RMNRemoteBin = RMNRemoteMetaData.Bin -func DeployRMNRemote(auth *bind.TransactOpts, backend bind.ContractBackend, localChainSelector uint64, legacyRMN common.Address) (common.Address, *types.Transaction, *RMNRemote, error) { +func DeployRMNRemote(auth *bind.TransactOpts, backend bind.ContractBackend, localChainSelector uint64) (common.Address, *types.Transaction, *RMNRemote, error) { parsed, err := RMNRemoteMetaData.GetAbi() if err != nil { return common.Address{}, nil, nil, err @@ -77,7 +72,7 @@ func DeployRMNRemote(auth *bind.TransactOpts, backend bind.ContractBackend, loca return common.Address{}, nil, nil, errors.New("GetABI returned nil") } - address, tx, contract, err := bind.DeployContract(auth, *parsed, common.FromHex(RMNRemoteBin), backend, localChainSelector, legacyRMN) + address, tx, contract, err := bind.DeployContract(auth, *parsed, common.FromHex(RMNRemoteBin), backend, localChainSelector) if err != nil { return common.Address{}, nil, nil, err } @@ -296,28 +291,6 @@ func (_RMNRemote *RMNRemoteCallerSession) GetVersionedConfig() (GetVersionedConf return _RMNRemote.Contract.GetVersionedConfig(&_RMNRemote.CallOpts) } -func (_RMNRemote *RMNRemoteCaller) IsBlessed(opts *bind.CallOpts, taggedRoot IRMNTaggedRoot) (bool, error) { - var out []interface{} - err := _RMNRemote.contract.Call(opts, &out, "isBlessed", taggedRoot) - - if err != nil { - return *new(bool), err - } - - out0 := *abi.ConvertType(out[0], new(bool)).(*bool) - - return out0, err - -} - -func (_RMNRemote *RMNRemoteSession) IsBlessed(taggedRoot IRMNTaggedRoot) (bool, error) { - return _RMNRemote.Contract.IsBlessed(&_RMNRemote.CallOpts, taggedRoot) -} - -func (_RMNRemote *RMNRemoteCallerSession) IsBlessed(taggedRoot IRMNTaggedRoot) (bool, error) { - return _RMNRemote.Contract.IsBlessed(&_RMNRemote.CallOpts, taggedRoot) -} - func (_RMNRemote *RMNRemoteCaller) IsCursed(opts *bind.CallOpts, subject [16]byte) (bool, error) { var out []interface{} err := _RMNRemote.contract.Call(opts, &out, "isCursed", subject) @@ -406,9 +379,9 @@ func (_RMNRemote *RMNRemoteCallerSession) TypeAndVersion() (string, error) { return _RMNRemote.Contract.TypeAndVersion(&_RMNRemote.CallOpts) } -func (_RMNRemote *RMNRemoteCaller) Verify(opts *bind.CallOpts, offRampAddress common.Address, merkleRoots []InternalMerkleRoot, signatures []IRMNRemoteSignature) error { +func (_RMNRemote *RMNRemoteCaller) Verify(opts *bind.CallOpts, offrampAddress common.Address, merkleRoots []InternalMerkleRoot, signatures []IRMNRemoteSignature) error { var out []interface{} - err := _RMNRemote.contract.Call(opts, &out, "verify", offRampAddress, merkleRoots, signatures) + err := _RMNRemote.contract.Call(opts, &out, "verify", offrampAddress, merkleRoots, signatures) if err != nil { return err @@ -418,12 +391,12 @@ func (_RMNRemote *RMNRemoteCaller) Verify(opts *bind.CallOpts, offRampAddress co } -func (_RMNRemote *RMNRemoteSession) Verify(offRampAddress common.Address, merkleRoots []InternalMerkleRoot, signatures []IRMNRemoteSignature) error { - return _RMNRemote.Contract.Verify(&_RMNRemote.CallOpts, offRampAddress, merkleRoots, signatures) +func (_RMNRemote *RMNRemoteSession) Verify(offrampAddress common.Address, merkleRoots []InternalMerkleRoot, signatures []IRMNRemoteSignature) error { + return _RMNRemote.Contract.Verify(&_RMNRemote.CallOpts, offrampAddress, merkleRoots, signatures) } -func (_RMNRemote *RMNRemoteCallerSession) Verify(offRampAddress common.Address, merkleRoots []InternalMerkleRoot, signatures []IRMNRemoteSignature) error { - return _RMNRemote.Contract.Verify(&_RMNRemote.CallOpts, offRampAddress, merkleRoots, signatures) +func (_RMNRemote *RMNRemoteCallerSession) Verify(offrampAddress common.Address, merkleRoots []InternalMerkleRoot, signatures []IRMNRemoteSignature) error { + return _RMNRemote.Contract.Verify(&_RMNRemote.CallOpts, offrampAddress, merkleRoots, signatures) } func (_RMNRemote *RMNRemoteTransactor) AcceptOwnership(opts *bind.TransactOpts) (*types.Transaction, error) { @@ -1202,8 +1175,6 @@ type RMNRemoteInterface interface { error) - IsBlessed(opts *bind.CallOpts, taggedRoot IRMNTaggedRoot) (bool, error) - IsCursed(opts *bind.CallOpts, subject [16]byte) (bool, error) IsCursed0(opts *bind.CallOpts) (bool, error) @@ -1212,7 +1183,7 @@ type RMNRemoteInterface interface { TypeAndVersion(opts *bind.CallOpts) (string, error) - Verify(opts *bind.CallOpts, offRampAddress common.Address, merkleRoots []InternalMerkleRoot, signatures []IRMNRemoteSignature) error + Verify(opts *bind.CallOpts, offrampAddress common.Address, merkleRoots []InternalMerkleRoot, signatures []IRMNRemoteSignature) error AcceptOwnership(opts *bind.TransactOpts) (*types.Transaction, error) diff --git a/core/gethwrappers/ccip/generated/router/router.go b/core/gethwrappers/ccip/generated/router/router.go index 995346bcb2a..9a0d4a40559 100644 --- a/core/gethwrappers/ccip/generated/router/router.go +++ b/core/gethwrappers/ccip/generated/router/router.go @@ -63,7 +63,7 @@ type RouterOnRamp struct { var RouterMetaData = &bind.MetaData{ ABI: "[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"wrappedNative\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"armProxy\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"BadARMSignal\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FailedToSendValue\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InsufficientFeeTokenAmount\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidMsgValue\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"InvalidRecipientAddress\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"offRamp\",\"type\":\"address\"}],\"name\":\"OffRampMismatch\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyOffRamp\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"UnsupportedDestinationChain\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"offRamp\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"calldataHash\",\"type\":\"bytes32\"}],\"name\":\"MessageExecuted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"offRamp\",\"type\":\"address\"}],\"name\":\"OffRampAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"offRamp\",\"type\":\"address\"}],\"name\":\"OffRampRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"onRamp\",\"type\":\"address\"}],\"name\":\"OnRampSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"MAX_RET_BYTES\",\"outputs\":[{\"internalType\":\"uint16\",\"name\":\"\",\"type\":\"uint16\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"onRamp\",\"type\":\"address\"}],\"internalType\":\"structRouter.OnRamp[]\",\"name\":\"onRampUpdates\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"offRamp\",\"type\":\"address\"}],\"internalType\":\"structRouter.OffRamp[]\",\"name\":\"offRampRemoves\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"offRamp\",\"type\":\"address\"}],\"internalType\":\"structRouter.OffRamp[]\",\"name\":\"offRampAdds\",\"type\":\"tuple[]\"}],\"name\":\"applyRampUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destinationChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structClient.EVMTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"},{\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"extraArgs\",\"type\":\"bytes\"}],\"internalType\":\"structClient.EVM2AnyMessage\",\"name\":\"message\",\"type\":\"tuple\"}],\"name\":\"ccipSend\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getArmProxy\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destinationChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structClient.EVMTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"},{\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"extraArgs\",\"type\":\"bytes\"}],\"internalType\":\"structClient.EVM2AnyMessage\",\"name\":\"message\",\"type\":\"tuple\"}],\"name\":\"getFee\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"fee\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getOffRamps\",\"outputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"offRamp\",\"type\":\"address\"}],\"internalType\":\"structRouter.OffRamp[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"getOnRamp\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"}],\"name\":\"getSupportedTokens\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getWrappedNative\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"}],\"name\":\"isChainSupported\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"offRamp\",\"type\":\"address\"}],\"name\":\"isOffRamp\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenAddress\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"recoverTokens\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"sender\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structClient.EVMTokenAmount[]\",\"name\":\"destTokenAmounts\",\"type\":\"tuple[]\"}],\"internalType\":\"structClient.Any2EVMMessage\",\"name\":\"message\",\"type\":\"tuple\"},{\"internalType\":\"uint16\",\"name\":\"gasForCallExactCheck\",\"type\":\"uint16\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"}],\"name\":\"routeMessage\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"retData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"gasUsed\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"wrappedNative\",\"type\":\"address\"}],\"name\":\"setWrappedNative\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", - Bin: "0x60a0346100f557601f612b2e38819003918201601f19168301916001600160401b038311848410176100fa5780849260409485528339810103126100f557610052602061004b83610110565b9201610110565b9033156100b057600080546001600160a01b03199081163317909155600280549091166001600160a01b0392909216919091179055608052604051612a099081610125823960805181818161084e01528181610bfb0152611d290152f35b60405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f00000000000000006044820152606490fd5b600080fd5b634e487b7160e01b600052604160045260246000fd5b51906001600160a01b03821682036100f55756fe6080604052600436101561001257600080fd5b60003560e01c8063181f5a771461013757806320487ded146101325780633cf979831461012d5780635246492f1461012857806352cb60ca146101235780635f3e849f1461011e578063787350e31461011957806379ba50971461011457806383826b2b1461010f5780638da5cb5b1461010a57806396f4e9f914610105578063a40e69c714610100578063a48a9058146100fb578063a8d87a3b146100f6578063da5fcac8146100f1578063e861e907146100ec578063f2fde38b146100e75763fbca3b74146100e257600080fd5b611922565b6117de565b61178c565b611413565b61136f565b6112fc565b6111ab565b610baf565b610b5d565b610aeb565b610990565b610956565b6108f9565b610872565b610803565b610758565b61057d565b6102aa565b600091031261014757565b600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040810190811067ffffffffffffffff82111761019757604052565b61014c565b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff82111761019757604052565b604051906101ec60a08361019c565b565b604051906101ec60408361019c565b67ffffffffffffffff811161019757601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b919082519283825260005b8481106102815750507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8460006020809697860101520116010190565b80602080928401015182828601015201610242565b9060206102a7928181520190610237565b90565b346101475760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101475761032760408051906102eb818361019c565b600c82527f526f7574657220312e322e300000000000000000000000000000000000000000602083015251918291602083526020830190610237565b0390f35b67ffffffffffffffff81160361014757565b81601f8201121561014757803590610354826101fd565b92610362604051948561019c565b8284526020838301011161014757816000926020809301838601378301015290565b67ffffffffffffffff81116101975760051b60200190565b73ffffffffffffffffffffffffffffffffffffffff81160361014757565b35906101ec8261039c565b81601f82011215610147578035906103dc82610384565b926103ea604051948561019c565b82845260208085019360061b8301019181831161014757602001925b828410610414575050505090565b604084830312610147576020604091825161042e8161017b565b86356104398161039c565b81528287013583820152815201930192610406565b9060407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc830112610147576004356104858161032b565b9160243567ffffffffffffffff81116101475760a07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc8284030112610147576104cc6101dd565b91816004013567ffffffffffffffff8111610147578160046104f09285010161033d565b8352602482013567ffffffffffffffff8111610147578160046105159285010161033d565b6020840152604482013567ffffffffffffffff81116101475781600461053d928501016103c5565b604084015261054e606483016103ba565b606084015260848201359167ffffffffffffffff831161014757610575920160040161033d565b608082015290565b346101475761058b3661044e565b6060810173ffffffffffffffffffffffffffffffffffffffff6105c2825173ffffffffffffffffffffffffffffffffffffffff1690565b16156106f1575b5073ffffffffffffffffffffffffffffffffffffffff61061a6106008467ffffffffffffffff166000526003602052604060002090565b5473ffffffffffffffffffffffffffffffffffffffff1690565b1680156106b9579060209161065e936040518095819482937f20487ded00000000000000000000000000000000000000000000000000000000845260048401611a98565b03915afa80156106b45761032791600091610685575b506040519081529081906020820190565b6106a7915060203d6020116106ad575b61069f818361019c565b8101906119c0565b38610674565b503d610695565b611ab9565b7fae236d9c0000000000000000000000000000000000000000000000000000000060005267ffffffffffffffff831660045260246000fd5b61072e9061071460025473ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff169052565b386105c9565b9392916107539060409215158652606060208701526060860190610237565b930152565b346101475760807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101475760043567ffffffffffffffff81116101475760a07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc82360301126101475760243561ffff8116810361014757610327916107f49160443590606435926107ec8461039c565b600401611ce2565b60409391935193849384610734565b346101475760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261014757602060405173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b346101475760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101475773ffffffffffffffffffffffffffffffffffffffff6004356108c28161039c565b6108ca6123fe565b167fffffffffffffffffffffffff00000000000000000000000000000000000000006002541617600255600080f35b346101475760607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610147576109546004356109378161039c565b6024356109438161039c565b6044359161094f6123fe565b611ef4565b005b346101475760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261014757602060405160848152f35b346101475760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101475773ffffffffffffffffffffffffffffffffffffffff600154163303610a8d5760005473ffffffffffffffffffffffffffffffffffffffff16600080547fffffffffffffffffffffffff00000000000000000000000000000000000000001633179055610a4e7fffffffffffffffffffffffff000000000000000000000000000000000000000060015416600155565b73ffffffffffffffffffffffffffffffffffffffff3391167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0600080a3005b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e6572000000000000000000006044820152fd5b346101475760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610147576020610b53610b40600435610b2e8161032b565b60243590610b3b8261039c565b61250e565b6000526005602052604060002054151590565b6040519015158152f35b346101475760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261014757602073ffffffffffffffffffffffffffffffffffffffff60005416604051908152f35b610bb83661044e565b6040517f397796f700000000000000000000000000000000000000000000000000000000815260208160048173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000165afa9081156106b457600091611116575b506110ec57610c526106008367ffffffffffffffff166000526003602052604060002090565b73ffffffffffffffffffffffffffffffffffffffff811680156110b4576060830191610cae610c95845173ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff1690565b610fe157610cee610cd460025473ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff168452565b6040517f20487ded00000000000000000000000000000000000000000000000000000000815260208180610d26888a60048401611a98565b0381865afa9081156106b457600091610fc2575b503410610f98573492610d67610c95610c95835173ffffffffffffffffffffffffffffffffffffffff1690565b91823b15610147576000600493604051948580927fd0e30db000000000000000000000000000000000000000000000000000000000825234905af19283156106b457610dda93610f7d575b50610dd5610c9534935173ffffffffffffffffffffffffffffffffffffffff1690565b61247d565b9190915b604082019160005b83518051821015610ef557610c95610e0183610e1c93611fdc565b515173ffffffffffffffffffffffffffffffffffffffff1690565b6040517f48a98aa400000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8816600482015273ffffffffffffffffffffffffffffffffffffffff82166024820152909190602081604481885afa80156106b457600193610ebf92600092610ec5575b5073ffffffffffffffffffffffffffffffffffffffff6020610eb2868b51611fdc565b5101519216903390612558565b01610de6565b610ee791925060203d8111610eee575b610edf818361019c565b810190611ff5565b9038610e8f565b503d610ed5565b610f386020888689600088604051968795869485937fdf0aa9e900000000000000000000000000000000000000000000000000000000855233926004860161200a565b03925af180156106b45761032791600091610f5e57506040519081529081906020820190565b610f77915060203d6020116106ad5761069f818361019c565b82610674565b80610f8c6000610f929361019c565b8061013c565b38610db2565b7f07da6ee60000000000000000000000000000000000000000000000000000000060005260046000fd5b610fdb915060203d6020116106ad5761069f818361019c565b38610d3a565b3461108a57604051907f20487ded0000000000000000000000000000000000000000000000000000000082526020828061101f888a60048401611a98565b0381865afa9081156106b45761106192600092611069575b5061105a610c9583965173ffffffffffffffffffffffffffffffffffffffff1690565b3390612558565b919091610dde565b61108391925060203d6020116106ad5761069f818361019c565b9038611037565b7f1841b4e10000000000000000000000000000000000000000000000000000000060005260046000fd5b7fae236d9c0000000000000000000000000000000000000000000000000000000060005267ffffffffffffffff841660045260246000fd5b7fc14837150000000000000000000000000000000000000000000000000000000060005260046000fd5b611138915060203d60201161113e575b611130818361019c565b810190611ac5565b38610c2c565b503d611126565b602060408183019282815284518094520192019060005b8181106111695750505090565b8251805167ffffffffffffffff16855260209081015173ffffffffffffffffffffffffffffffffffffffff16818601526040909401939092019160010161115c565b346101475760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101475760405180816020600454928381520160046000527f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b9260005b8181106112e35750506112289250038261019c565b6112328151612052565b9060005b81518110156112d5578061124c60019284611fdc565b516112b973ffffffffffffffffffffffffffffffffffffffff61127f6112728460a01c90565b67ffffffffffffffff1690565b9261129b61128b6101ee565b67ffffffffffffffff9095168552565b1673ffffffffffffffffffffffffffffffffffffffff166020830152565b6112c38286611fdc565b526112ce8185611fdc565b5001611236565b604051806103278582611145565b8454835260019485019486945060209093019201611213565b346101475760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610147576020610b5360043561133c8161032b565b67ffffffffffffffff16600052600360205273ffffffffffffffffffffffffffffffffffffffff60406000205416151590565b346101475760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101475767ffffffffffffffff6004356113b38161032b565b166000526003602052602073ffffffffffffffffffffffffffffffffffffffff60406000205416604051908152f35b9181601f840112156101475782359167ffffffffffffffff8311610147576020808501948460061b01011161014757565b346101475760607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101475760043567ffffffffffffffff8111610147576114629036906004016113e2565b60243567ffffffffffffffff8111610147576114829036906004016113e2565b60443567ffffffffffffffff8111610147576114a29036906004016113e2565b9490936114ad6123fe565b60005b81811061165d5750505060005b8181106115755750505060005b8281106114d357005b806114e96114e460019386866120cd565b611add565b6114ff60206114f98488886120cd565b01612116565b9061151261150d838361250e565b6128a3565b61151f575b5050016114ca565b60405173ffffffffffffffffffffffffffffffffffffffff92909216825267ffffffffffffffff16907fa4bdf64ebdf3316320601a081916a75aa144bcef6c4beeb0e9fb1982cacc6b9490602090a23880611517565b6115836114e48284866120cd565b61159360206114f98486886120cd565b906115ad6115a96115a4848461250e565b6127bf565b1590565b61160d5760405173ffffffffffffffffffffffffffffffffffffffff9290921682526001929167ffffffffffffffff91909116907fa823809efda3ba66c873364eec120fa0923d9fabda73bc97dd5663341e2d9bcb90602090a2016114bd565b7f496477900000000000000000000000000000000000000000000000000000000060005267ffffffffffffffff1660045273ffffffffffffffffffffffffffffffffffffffff1660245260446000fd5b8061167361166e60019385876120cd565b6120dd565b7f1f7d0ec248b80e5c0dde0ee531c4fc8fdb6ce9a2b3d90f560c74acd6a7202f2367ffffffffffffffff61176161174660208501946117386116c9875173ffffffffffffffffffffffffffffffffffffffff1690565b6116f86116de845167ffffffffffffffff1690565b67ffffffffffffffff166000526003602052604060002090565b9073ffffffffffffffffffffffffffffffffffffffff167fffffffffffffffffffffffff0000000000000000000000000000000000000000825416179055565b5167ffffffffffffffff1690565b935173ffffffffffffffffffffffffffffffffffffffff1690565b60405173ffffffffffffffffffffffffffffffffffffffff919091168152921691602090a2016114b0565b346101475760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261014757602073ffffffffffffffffffffffffffffffffffffffff60025416604051908152f35b346101475760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101475773ffffffffffffffffffffffffffffffffffffffff60043561182e8161039c565b6118366123fe565b163381146118c457807fffffffffffffffffffffffff0000000000000000000000000000000000000000600154161760015573ffffffffffffffffffffffffffffffffffffffff61189c60005473ffffffffffffffffffffffffffffffffffffffff1690565b167fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae1278600080a3005b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152fd5b346101475760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610147576119656004356119608161032b565b6121a4565b60405180916020820160208352815180915260206040840192019060005b818110611991575050500390f35b825173ffffffffffffffffffffffffffffffffffffffff16845285945060209384019390920191600101611983565b90816020910312610147575190565b91906119f96119e7845160a0845260a0840190610237565b60208501518382036020850152610237565b9060408401519181810360408301526020808451928381520193019060005b818110611a6057505050608084611a5060606102a796970151606085019073ffffffffffffffffffffffffffffffffffffffff169052565b0151906080818403910152610237565b8251805173ffffffffffffffffffffffffffffffffffffffff1686526020908101518187015260409095019490920191600101611a18565b60409067ffffffffffffffff6102a7949316815281602082015201906119cf565b6040513d6000823e3d90fd5b90816020910312610147575180151581036101475790565b356102a78161032b565b90357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18236030181121561014757016020813591019167ffffffffffffffff821161014757813603831361014757565b601f82602094937fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0938186528686013760008582860101520116010190565b9160209082815201919060005b818110611b905750505090565b90919260408060019273ffffffffffffffffffffffffffffffffffffffff8735611bb98161039c565b16815260208781013590820152019401929101611b83565b90602082528035602083015267ffffffffffffffff6020820135611bf48161032b565b166040830152611c5b611c1e611c0d6040840184611ae7565b60a0606087015260c0860191611b37565b611c2b6060840184611ae7565b907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0868403016080870152611b37565b9060808101357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe182360301811215610147570160208135910167ffffffffffffffff8211610147578160061b36038113610147578360a07fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe06102a796860301910152611b76565b939190926040517f397796f700000000000000000000000000000000000000000000000000000000815260208160048173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000165afa9081156106b457600091611ea5575b506110ec5760208501611d7b610b408235611d748161032b565b339061250e565b15611e7b57611deb611e73611e1d7f85572ffb0000000000000000000000000000000000000000000000000000000097611e29967f9b877de93ea9895756e337442c657f95a34fc68e7eb988bdfa693d5be83016b696611e178c604051978891602083019e8f5260248301611bd1565b037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0810188528761019c565b856122d8565b98919690993594611add565b925190206040519384933391859094939273ffffffffffffffffffffffffffffffffffffffff9067ffffffffffffffff606094608085019885521660208401521660408201520152565b0390a1929190565b7fd2316ede0000000000000000000000000000000000000000000000000000000060005260046000fd5b611ebe915060203d60201161113e57611130818361019c565b38611d5a565b3d15611eef573d90611ed5826101fd565b91611ee3604051938461019c565b82523d6000602084013e565b606090565b91909173ffffffffffffffffffffffffffffffffffffffff83168015611f80575073ffffffffffffffffffffffffffffffffffffffff16918215611f3b576101ec9261247d565b6000809350809281925af1611f4e611ec4565b5015611f5657565b7fe417b80b0000000000000000000000000000000000000000000000000000000060005260046000fd5b7f26a78f8f0000000000000000000000000000000000000000000000000000000060005260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b8051821015611ff05760209160051b010190565b611fad565b9081602091031261014757516102a78161039c565b92949361204660609367ffffffffffffffff73ffffffffffffffffffffffffffffffffffffffff941686526080602087015260808601906119cf565b95604085015216910152565b9061205c82610384565b612069604051918261019c565b8281527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe06120978294610384565b019060005b8281106120a857505050565b6020906040516120b78161017b565b600081526000838201528282850101520161209c565b9190811015611ff05760061b0190565b604081360312610147576020604051916120f68361017b565b80356121018161032b565b8352013561210e8161039c565b602082015290565b356102a78161039c565b6020818303126101475780519067ffffffffffffffff821161014757019080601f8301121561014757815161215481610384565b92612162604051948561019c565b81845260208085019260051b82010192831161014757602001905b82821061218a5750505090565b6020809183516121998161039c565b81520191019061217d565b6121db8167ffffffffffffffff16600052600360205273ffffffffffffffffffffffffffffffffffffffff60406000205416151590565b156122985760006122659167ffffffffffffffff811682526003602052612220610c95610c956040852073ffffffffffffffffffffffffffffffffffffffff90541690565b60405180809581947ffbca3b740000000000000000000000000000000000000000000000000000000083526004830191909167ffffffffffffffff6020820193169052565b03915afa9081156106b45760009161227b575090565b6102a791503d806000833e612290818361019c565b810190612120565b5060405160206122a8818361019c565b600082527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0810190369083013790565b9391936122e560846101fd565b946122f3604051968761019c565b6084865261230160846101fd565b947fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0602088019601368737833b156123d4575a908082106123aa578291038060061c90031115612380576000918291825a9560208451940192f1905a9003923d9060848211612377575b6000908287523e929190565b6084915061236b565b7f37c3be290000000000000000000000000000000000000000000000000000000060005260046000fd5b7fafa32a2c0000000000000000000000000000000000000000000000000000000060005260046000fd5b7f0c3b563c0000000000000000000000000000000000000000000000000000000060005260046000fd5b73ffffffffffffffffffffffffffffffffffffffff60005416330361241f57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152fd5b6101ec9273ffffffffffffffffffffffffffffffffffffffff604051937fa9059cbb0000000000000000000000000000000000000000000000000000000060208601521660248401526044830152604482526124da60648361019c565b6125bf565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b7bffffffffffffffff000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff9160a01b16911681018091116125535790565b6124df565b90919273ffffffffffffffffffffffffffffffffffffffff6101ec9481604051957f23b872dd0000000000000000000000000000000000000000000000000000000060208801521660248601521660448401526064830152606482526124da60848361019c565b73ffffffffffffffffffffffffffffffffffffffff61262f9116916040926000808551936125ed878661019c565b602085527f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564602086015260208151910182855af1612629611ec4565b91612934565b8051908161263c57505050565b60208061264d938301019101611ac5565b156126555750565b608490517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152fd5b8054821015611ff05760005260206000200190600090565b91612728918354907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9060031b92831b921b19161790565b9055565b80548015612790577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff019061276182826126d8565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82549160031b1b1916905555565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b60008181526005602052604090205490811561289c577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82019082821161255357600454927fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff840193841161255357838360009561285b9503612861575b50505061284a600461272c565b600590600052602052604060002090565b55600190565b61284a61288d916128836128796128939560046126d8565b90549060031b1c90565b92839160046126d8565b906126f0565b5538808061283d565b5050600090565b60008181526005602052604090205461292e5760045468010000000000000000811015610197576129156128e082600185940160045560046126d8565b81939154907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9060031b92831b921b19161790565b9055600454906000526005602052604060002055600190565b50600090565b919290156129af5750815115612948575090565b3b156129515790565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152fd5b8251909150156129c25750805190602001fd5b6129f8906040519182917f08c379a000000000000000000000000000000000000000000000000000000000835260048301610296565b0390fdfea164736f6c634300081a000a", + Bin: "0x60a06040523480156200001157600080fd5b5060405162002d2838038062002d288339810160408190526200003491620001af565b33806000816200008b5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000be57620000be81620000e7565b5050600280546001600160a01b0319166001600160a01b039485161790555016608052620001e7565b336001600160a01b03821603620001415760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000082565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b80516001600160a01b0381168114620001aa57600080fd5b919050565b60008060408385031215620001c357600080fd5b620001ce8362000192565b9150620001de6020840162000192565b90509250929050565b608051612b1762000211600039600081816101f9015281816105e10152610af20152612b176000f3fe6080604052600436106101295760003560e01c80638da5cb5b116100a5578063a8d87a3b11610074578063e861e90711610059578063e861e90714610409578063f2fde38b14610434578063fbca3b741461045457600080fd5b8063a8d87a3b1461039c578063da5fcac8146103e957600080fd5b80638da5cb5b146102ed57806396f4e9f914610318578063a40e69c71461032b578063a48a90581461034d57600080fd5b806352cb60ca116100fc578063787350e3116100e1578063787350e31461028057806379ba5097146102a857806383826b2b146102bd57600080fd5b806352cb60ca1461023e5780635f3e849f1461026057600080fd5b8063181f5a771461012e57806320487ded1461018d5780633cf97983146101bb5780635246492f146101ea575b600080fd5b34801561013a57600080fd5b506101776040518060400160405280600c81526020017f526f7574657220312e322e30000000000000000000000000000000000000000081525081565b6040516101849190611f3c565b60405180910390f35b34801561019957600080fd5b506101ad6101a83660046121ad565b610481565b604051908152602001610184565b3480156101c757600080fd5b506101db6101d63660046122aa565b6105d9565b60405161018493929190612322565b3480156101f657600080fd5b507f00000000000000000000000000000000000000000000000000000000000000005b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610184565b34801561024a57600080fd5b5061025e61025936600461234d565b610836565b005b34801561026c57600080fd5b5061025e61027b36600461236a565b610885565b34801561028c57600080fd5b50610295608481565b60405161ffff9091168152602001610184565b3480156102b457600080fd5b5061025e6109d3565b3480156102c957600080fd5b506102dd6102d83660046123ab565b610ad0565b6040519015158152602001610184565b3480156102f957600080fd5b5060005473ffffffffffffffffffffffffffffffffffffffff16610219565b6101ad6103263660046121ad565b610aee565b34801561033757600080fd5b50610340611087565b60405161018491906123e2565b34801561035957600080fd5b506102dd610368366004612451565b67ffffffffffffffff1660009081526003602052604090205473ffffffffffffffffffffffffffffffffffffffff16151590565b3480156103a857600080fd5b506102196103b7366004612451565b67ffffffffffffffff1660009081526003602052604090205473ffffffffffffffffffffffffffffffffffffffff1690565b3480156103f557600080fd5b5061025e6104043660046124b8565b61118b565b34801561041557600080fd5b5060025473ffffffffffffffffffffffffffffffffffffffff16610219565b34801561044057600080fd5b5061025e61044f36600461234d565b611490565b34801561046057600080fd5b5061047461046f366004612451565b6114a4565b6040516101849190612552565b606081015160009073ffffffffffffffffffffffffffffffffffffffff166104c25760025473ffffffffffffffffffffffffffffffffffffffff1660608301525b67ffffffffffffffff831660009081526003602052604090205473ffffffffffffffffffffffffffffffffffffffff168061053a576040517fae236d9c00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff851660048201526024015b60405180910390fd5b6040517f20487ded00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8216906320487ded9061058e9087908790600401612689565b602060405180830381865afa1580156105ab573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105cf91906126ac565b9150505b92915050565b6000606060007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663397796f76040518163ffffffff1660e01b8152600401602060405180830381865afa15801561064a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061066e91906126c5565b156106a5576040517fc148371500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6106be6106b86040890160208a01612451565b33610ad0565b6106f4576040517fd2316ede00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006385572ffb60e01b8860405160240161070f91906127f4565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152905061079c8186888a60846115c4565b919550935091507f9b877de93ea9895756e337442c657f95a34fc68e7eb988bdfa693d5be83016b688356107d660408b0160208c01612451565b83516020850120604051610823939291339193845267ffffffffffffffff92909216602084015273ffffffffffffffffffffffffffffffffffffffff166040830152606082015260800190565b60405180910390a1509450945094915050565b61083e6116ea565b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b61088d6116ea565b73ffffffffffffffffffffffffffffffffffffffff82166108f2576040517f26a78f8f00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83166004820152602401610531565b73ffffffffffffffffffffffffffffffffffffffff83166109ad5760008273ffffffffffffffffffffffffffffffffffffffff168260405160006040518083038185875af1925050503d8060008114610967576040519150601f19603f3d011682016040523d82523d6000602084013e61096c565b606091505b50509050806109a7576040517fe417b80b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50505050565b6109ce73ffffffffffffffffffffffffffffffffffffffff8416838361176d565b505050565b60015473ffffffffffffffffffffffffffffffffffffffff163314610a54576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e6572000000000000000000006044820152606401610531565b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b6000610ae7610adf8484611841565b600490611885565b9392505050565b60007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663397796f76040518163ffffffff1660e01b8152600401602060405180830381865afa158015610b5b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b7f91906126c5565b15610bb6576040517fc148371500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff831660009081526003602052604090205473ffffffffffffffffffffffffffffffffffffffff1680610c29576040517fae236d9c00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff85166004820152602401610531565b606083015160009073ffffffffffffffffffffffffffffffffffffffff16610dbb5760025473ffffffffffffffffffffffffffffffffffffffff90811660608601526040517f20487ded000000000000000000000000000000000000000000000000000000008152908316906320487ded90610cab9088908890600401612689565b602060405180830381865afa158015610cc8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cec91906126ac565b905080341015610d28576040517f07da6ee600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b349050836060015173ffffffffffffffffffffffffffffffffffffffff1663d0e30db0826040518263ffffffff1660e01b81526004016000604051808303818588803b158015610d7757600080fd5b505af1158015610d8b573d6000803e3d6000fd5b505050506060850151610db6915073ffffffffffffffffffffffffffffffffffffffff16838361176d565b610eb2565b3415610df3576040517f1841b4e100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517f20487ded00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8316906320487ded90610e479088908890600401612689565b602060405180830381865afa158015610e64573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e8891906126ac565b6060850151909150610eb29073ffffffffffffffffffffffffffffffffffffffff1633848461189d565b60005b846040015151811015610fe257600085604001518281518110610eda57610eda612900565b6020908102919091010151516040517f48a98aa400000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8916600482015273ffffffffffffffffffffffffffffffffffffffff8083166024830152919250610fd9913391908716906348a98aa490604401602060405180830381865afa158015610f6c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f90919061292f565b88604001518581518110610fa657610fa6612900565b6020026020010151602001518473ffffffffffffffffffffffffffffffffffffffff1661189d909392919063ffffffff16565b50600101610eb5565b506040517fdf0aa9e900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83169063df0aa9e99061103b90889088908690339060040161294c565b6020604051808303816000875af115801561105a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061107e91906126ac565b95945050505050565b6060600061109560046118fb565b90506000815167ffffffffffffffff8111156110b3576110b3611f6c565b6040519080825280602002602001820160405280156110f857816020015b60408051808201909152600080825260208201528152602001906001900390816110d15790505b50905060005b825181101561118457600083828151811061111b5761111b612900565b60200260200101519050604051806040016040528060a083901c67ffffffffffffffff1681526020018273ffffffffffffffffffffffffffffffffffffffff1681525083838151811061117057611170612900565b6020908102919091010152506001016110fe565b5092915050565b6111936116ea565b60005b8581101561126f5760008787838181106111b2576111b2612900565b9050604002018036038101906111c8919061299c565b60208181018051835167ffffffffffffffff90811660009081526003855260409081902080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff948516179055855193519051921682529394509216917f1f7d0ec248b80e5c0dde0ee531c4fc8fdb6ce9a2b3d90f560c74acd6a7202f23910160405180910390a250600101611196565b5060005b838110156113a757600085858381811061128f5761128f612900565b6112a59260206040909202019081019150612451565b905060008686848181106112bb576112bb612900565b90506040020160200160208101906112d3919061234d565b90506112ea6112e28383611841565b600490611908565b611348576040517f4964779000000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8316600482015273ffffffffffffffffffffffffffffffffffffffff82166024820152604401610531565b60405173ffffffffffffffffffffffffffffffffffffffff8216815267ffffffffffffffff8316907fa823809efda3ba66c873364eec120fa0923d9fabda73bc97dd5663341e2d9bcb9060200160405180910390a25050600101611273565b5060005b818110156114875760008383838181106113c7576113c7612900565b6113dd9260206040909202019081019150612451565b905060008484848181106113f3576113f3612900565b905060400201602001602081019061140b919061234d565b905061142261141a8383611841565b600490611914565b1561147d5760405173ffffffffffffffffffffffffffffffffffffffff8216815267ffffffffffffffff8316907fa4bdf64ebdf3316320601a081916a75aa144bcef6c4beeb0e9fb1982cacc6b949060200160405180910390a25b50506001016113ab565b50505050505050565b6114986116ea565b6114a181611920565b50565b60606114de8267ffffffffffffffff1660009081526003602052604090205473ffffffffffffffffffffffffffffffffffffffff16151590565b6114f8576040805160008082526020820190925290611184565b67ffffffffffffffff8216600081815260036020526040908190205490517ffbca3b74000000000000000000000000000000000000000000000000000000008152600481019290925273ffffffffffffffffffffffffffffffffffffffff169063fbca3b7490602401600060405180830381865afa15801561157e573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526105d391908101906129db565b6000606060008361ffff1667ffffffffffffffff8111156115e7576115e7611f6c565b6040519080825280601f01601f191660200182016040528015611611576020820181803683370190505b509150863b611644577f0c3b563c0000000000000000000000000000000000000000000000000000000060005260046000fd5b5a85811015611677577fafa32a2c0000000000000000000000000000000000000000000000000000000060005260046000fd5b85900360408104810387106116b0577f37c3be290000000000000000000000000000000000000000000000000000000060005260046000fd5b505a6000808a5160208c0160008c8cf193505a900390503d848111156116d35750835b808352806000602085013e50955095509592505050565b60005473ffffffffffffffffffffffffffffffffffffffff16331461176b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401610531565b565b60405173ffffffffffffffffffffffffffffffffffffffff83166024820152604481018290526109ce9084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152611a15565b6000610ae773ffffffffffffffffffffffffffffffffffffffff83167bffffffffffffffff000000000000000000000000000000000000000060a086901b16612a99565b60008181526001830160205260408120541515610ae7565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526109a79085907f23b872dd00000000000000000000000000000000000000000000000000000000906084016117bf565b60606000610ae783611b21565b6000610ae78383611b7d565b6000610ae78383611c70565b3373ffffffffffffffffffffffffffffffffffffffff82160361199f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401610531565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6000611a77826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16611cbf9092919063ffffffff16565b8051909150156109ce5780806020019051810190611a9591906126c5565b6109ce576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610531565b606081600001805480602002602001604051908101604052809291908181526020018280548015611b7157602002820191906000526020600020905b815481526020019060010190808311611b5d575b50505050509050919050565b60008181526001830160205260408120548015611c66576000611ba1600183612aac565b8554909150600090611bb590600190612aac565b9050808214611c1a576000866000018281548110611bd557611bd5612900565b9060005260206000200154905080876000018481548110611bf857611bf8612900565b6000918252602080832090910192909255918252600188019052604090208390555b8554869080611c2b57611c2b612abf565b6001900381819060005260206000200160009055905585600101600086815260200190815260200160002060009055600193505050506105d3565b60009150506105d3565b6000818152600183016020526040812054611cb7575081546001818101845560008481526020808220909301849055845484825282860190935260409020919091556105d3565b5060006105d3565b6060611cce8484600085611cd6565b949350505050565b606082471015611d68576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610531565b6000808673ffffffffffffffffffffffffffffffffffffffff168587604051611d919190612aee565b60006040518083038185875af1925050503d8060008114611dce576040519150601f19603f3d011682016040523d82523d6000602084013e611dd3565b606091505b5091509150611de487838387611def565b979650505050505050565b60608315611e85578251600003611e7e5773ffffffffffffffffffffffffffffffffffffffff85163b611e7e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610531565b5081611cce565b611cce8383815115611e9a5781518083602001fd5b806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016105319190611f3c565b60005b83811015611ee9578181015183820152602001611ed1565b50506000910152565b60008151808452611f0a816020860160208601611ece565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000610ae76020830184611ef2565b803567ffffffffffffffff81168114611f6757600080fd5b919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff81118282101715611fbe57611fbe611f6c565b60405290565b60405160a0810167ffffffffffffffff81118282101715611fbe57611fbe611f6c565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff8111828210171561202e5761202e611f6c565b604052919050565b600082601f83011261204757600080fd5b813567ffffffffffffffff81111561206157612061611f6c565b61209260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601611fe7565b8181528460208386010111156120a757600080fd5b816020850160208301376000918101602001919091529392505050565b600067ffffffffffffffff8211156120de576120de611f6c565b5060051b60200190565b73ffffffffffffffffffffffffffffffffffffffff811681146114a157600080fd5b8035611f67816120e8565b600082601f83011261212657600080fd5b8135602061213b612136836120c4565b611fe7565b82815260069290921b8401810191818101908684111561215a57600080fd5b8286015b848110156121a257604081890312156121775760008081fd5b61217f611f9b565b813561218a816120e8565b8152818501358582015283529183019160400161215e565b509695505050505050565b600080604083850312156121c057600080fd5b6121c983611f4f565b9150602083013567ffffffffffffffff808211156121e657600080fd5b9084019060a082870312156121fa57600080fd5b612202611fc4565b82358281111561221157600080fd5b61221d88828601612036565b82525060208301358281111561223257600080fd5b61223e88828601612036565b60208301525060408301358281111561225657600080fd5b61226288828601612115565b6040830152506122746060840161210a565b606082015260808301358281111561228b57600080fd5b61229788828601612036565b6080830152508093505050509250929050565b600080600080608085870312156122c057600080fd5b843567ffffffffffffffff8111156122d757600080fd5b850160a081880312156122e957600080fd5b9350602085013561ffff8116811461230057600080fd5b9250604085013591506060850135612317816120e8565b939692955090935050565b831515815260606020820152600061233d6060830185611ef2565b9050826040830152949350505050565b60006020828403121561235f57600080fd5b8135610ae7816120e8565b60008060006060848603121561237f57600080fd5b833561238a816120e8565b9250602084013561239a816120e8565b929592945050506040919091013590565b600080604083850312156123be57600080fd5b6123c783611f4f565b915060208301356123d7816120e8565b809150509250929050565b602080825282518282018190526000919060409081850190868401855b82811015612444578151805167ffffffffffffffff16855286015173ffffffffffffffffffffffffffffffffffffffff168685015292840192908501906001016123ff565b5091979650505050505050565b60006020828403121561246357600080fd5b610ae782611f4f565b60008083601f84011261247e57600080fd5b50813567ffffffffffffffff81111561249657600080fd5b6020830191508360208260061b85010111156124b157600080fd5b9250929050565b600080600080600080606087890312156124d157600080fd5b863567ffffffffffffffff808211156124e957600080fd5b6124f58a838b0161246c565b9098509650602089013591508082111561250e57600080fd5b61251a8a838b0161246c565b9096509450604089013591508082111561253357600080fd5b5061254089828a0161246c565b979a9699509497509295939492505050565b6020808252825182820181905260009190848201906040850190845b818110156125a057835173ffffffffffffffffffffffffffffffffffffffff168352928401929184019160010161256e565b50909695505050505050565b6000815160a084526125c160a0850182611ef2565b9050602080840151858303828701526125da8382611ef2565b60408681015188830389830152805180845290850195509092506000918401905b8083101561263a578551805173ffffffffffffffffffffffffffffffffffffffff168352850151858301529484019460019290920191908301906125fb565b5060608701519450612664606089018673ffffffffffffffffffffffffffffffffffffffff169052565b60808701519450878103608089015261267d8186611ef2565b98975050505050505050565b67ffffffffffffffff83168152604060208201526000611cce60408301846125ac565b6000602082840312156126be57600080fd5b5051919050565b6000602082840312156126d757600080fd5b81518015158114610ae757600080fd5b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261271c57600080fd5b830160208101925035905067ffffffffffffffff81111561273c57600080fd5b8036038213156124b157600080fd5b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b8183526000602080850194508260005b858110156127e95781356127b7816120e8565b73ffffffffffffffffffffffffffffffffffffffff1687528183013583880152604096870196909101906001016127a4565b509495945050505050565b6020815281356020820152600061280d60208401611f4f565b67ffffffffffffffff808216604085015261282b60408601866126e7565b925060a0606086015261284260c08601848361274b565b92505061285260608601866126e7565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08087860301608088015261288885838561274b565b9450608088013592507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18836030183126128c157600080fd5b602092880192830192359150838211156128da57600080fd5b8160061b36038313156128ec57600080fd5b8685030160a0870152611de4848284612794565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60006020828403121561294157600080fd5b8151610ae7816120e8565b67ffffffffffffffff8516815260806020820152600061296f60808301866125ac565b905083604083015273ffffffffffffffffffffffffffffffffffffffff8316606083015295945050505050565b6000604082840312156129ae57600080fd5b6129b6611f9b565b6129bf83611f4f565b815260208301356129cf816120e8565b60208201529392505050565b600060208083850312156129ee57600080fd5b825167ffffffffffffffff811115612a0557600080fd5b8301601f81018513612a1657600080fd5b8051612a24612136826120c4565b81815260059190911b82018301908381019087831115612a4357600080fd5b928401925b82841015611de4578351612a5b816120e8565b82529284019290840190612a48565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b808201808211156105d3576105d3612a6a565b818103818111156105d3576105d3612a6a565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b60008251612b00818460208701611ece565b919091019291505056fea164736f6c6343000818000a", } var RouterABI = RouterMetaData.ABI diff --git a/core/gethwrappers/ccip/generated/token_admin_registry/token_admin_registry.go b/core/gethwrappers/ccip/generated/token_admin_registry/token_admin_registry.go index f61341b95c0..4e1a15ce60f 100644 --- a/core/gethwrappers/ccip/generated/token_admin_registry/token_admin_registry.go +++ b/core/gethwrappers/ccip/generated/token_admin_registry/token_admin_registry.go @@ -38,7 +38,7 @@ type TokenAdminRegistryTokenConfig struct { var TokenAdminRegistryMetaData = &bind.MetaData{ ABI: "[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"AlreadyRegistered\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CannotTransferToSelf\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"InvalidTokenPoolToken\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MustBeProposedOwner\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"OnlyAdministrator\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByOwner\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"OnlyPendingAdministrator\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"OnlyRegistryModuleOrOwner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OwnerCannotBeZero\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddress\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"currentAdmin\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newAdmin\",\"type\":\"address\"}],\"name\":\"AdministratorTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newAdmin\",\"type\":\"address\"}],\"name\":\"AdministratorTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousPool\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newPool\",\"type\":\"address\"}],\"name\":\"PoolSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"module\",\"type\":\"address\"}],\"name\":\"RegistryModuleAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"module\",\"type\":\"address\"}],\"name\":\"RegistryModuleRemoved\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"localToken\",\"type\":\"address\"}],\"name\":\"acceptAdminRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"module\",\"type\":\"address\"}],\"name\":\"addRegistryModule\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"startIndex\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"maxCount\",\"type\":\"uint64\"}],\"name\":\"getAllConfiguredTokens\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"tokens\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"getPool\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"tokens\",\"type\":\"address[]\"}],\"name\":\"getPools\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"getTokenConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"administrator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"pendingAdministrator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenPool\",\"type\":\"address\"}],\"internalType\":\"structTokenAdminRegistry.TokenConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"localToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"administrator\",\"type\":\"address\"}],\"name\":\"isAdministrator\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"module\",\"type\":\"address\"}],\"name\":\"isRegistryModule\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"localToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"administrator\",\"type\":\"address\"}],\"name\":\"proposeAdministrator\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"module\",\"type\":\"address\"}],\"name\":\"removeRegistryModule\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"localToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"pool\",\"type\":\"address\"}],\"name\":\"setPool\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"localToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"newAdmin\",\"type\":\"address\"}],\"name\":\"transferAdminRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", - Bin: "0x60808060405234603d573315602c57600180546001600160a01b031916331790556114a790816100438239f35b639b15e16f60e01b60005260046000fd5b600080fdfe6080604052600436101561001257600080fd5b60003560e01c806310cbcf1814610e82578063156194da14610d45578063181f5a7714610c335780633dc4577214610ba25780634e847fc7146109b65780635e63547a146108be57806372d64a811461084957806379ba5097146107605780637d3f2552146106f15780638da5cb5b1461069f578063bbe4f6db14610621578063c1af6e0314610587578063cb67e3b1146104b5578063ddadfa8e14610385578063e677ae37146101c15763f2fde38b146100cc57600080fd5b346101bc5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101bc5773ffffffffffffffffffffffffffffffffffffffff610118610f0d565b6101206111e7565b1633811461019257807fffffffffffffffffffffffff0000000000000000000000000000000000000000600054161760005573ffffffffffffffffffffffffffffffffffffffff600154167fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae1278600080a3005b7fdad89dca0000000000000000000000000000000000000000000000000000000060005260046000fd5b600080fd5b346101bc5760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101bc576101f8610f0d565b610200610f30565b610217336000526006602052604060002054151590565b1580610363575b6103355773ffffffffffffffffffffffffffffffffffffffff1690811561030b5773ffffffffffffffffffffffffffffffffffffffff16806000526002602052604060002073ffffffffffffffffffffffffffffffffffffffff8154166102dd5760010180547fffffffffffffffffffffffff000000000000000000000000000000000000000016831790556000906102b681611440565b507fc54c3051ff16e63bb9203214432372aca006c589e3653619b577a3265675b7168280a4005b507f45ed80e90000000000000000000000000000000000000000000000000000000060005260045260246000fd5b7fd92e233d0000000000000000000000000000000000000000000000000000000060005260046000fd5b7f51ca1ec3000000000000000000000000000000000000000000000000000000006000523360045260246000fd5b5073ffffffffffffffffffffffffffffffffffffffff6001541633141561021e565b346101bc5760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101bc576103bc610f0d565b73ffffffffffffffffffffffffffffffffffffffff6103d9610f30565b91169081600052600260205273ffffffffffffffffffffffffffffffffffffffff6040600020541633036104835773ffffffffffffffffffffffffffffffffffffffff9082600052600260205260016040600020018282167fffffffffffffffffffffffff0000000000000000000000000000000000000000825416179055169033907fc54c3051ff16e63bb9203214432372aca006c589e3653619b577a3265675b716600080a4005b507fed5d85b5000000000000000000000000000000000000000000000000000000006000523360045260245260446000fd5b346101bc5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101bc5773ffffffffffffffffffffffffffffffffffffffff610501610f0d565b60006040805161051081610f53565b82815282602082015201521660005260026020526060604060002073ffffffffffffffffffffffffffffffffffffffff60405161054c81610f53565b818084541693848352604082600281600185015416936020870194855201541693019283526040519485525116602084015251166040820152f35b346101bc5760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101bc5760206105c0610f0d565b73ffffffffffffffffffffffffffffffffffffffff6105dd610f30565b91166000526002825273ffffffffffffffffffffffffffffffffffffffff6040600020541673ffffffffffffffffffffffffffffffffffffffff6040519216148152f35b346101bc5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101bc5773ffffffffffffffffffffffffffffffffffffffff61066d610f0d565b166000526002602052602073ffffffffffffffffffffffffffffffffffffffff60026040600020015416604051908152f35b346101bc5760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101bc57602073ffffffffffffffffffffffffffffffffffffffff60015416604051908152f35b346101bc5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101bc57602061075673ffffffffffffffffffffffffffffffffffffffff610742610f0d565b166000526006602052604060002054151590565b6040519015158152f35b346101bc5760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101bc5760005473ffffffffffffffffffffffffffffffffffffffff8116330361081f577fffffffffffffffffffffffff00000000000000000000000000000000000000006001549133828416176001551660005573ffffffffffffffffffffffffffffffffffffffff3391167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0600080a3005b7f02b543c60000000000000000000000000000000000000000000000000000000060005260046000fd5b346101bc5760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101bc5760043567ffffffffffffffff811681036101bc576024359067ffffffffffffffff821682036101bc576108ba916108ae916110e6565b60405191829182610fb0565b0390f35b346101bc5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101bc5760043567ffffffffffffffff81116101bc57366023820112156101bc57806004013567ffffffffffffffff81116101bc573660248260051b840101116101bc5761093681611018565b60005b828110156109a857600060248260051b8601013573ffffffffffffffffffffffffffffffffffffffff81168091036109a457600260408373ffffffffffffffffffffffffffffffffffffffff936001969552826020522001541661099d8285611067565b5201610939565b5080fd5b604051806108ba8482610fb0565b346101bc5760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101bc576109ed610f0d565b73ffffffffffffffffffffffffffffffffffffffff610a0a610f30565b91169081600052600260205273ffffffffffffffffffffffffffffffffffffffff6040600020541633036104835773ffffffffffffffffffffffffffffffffffffffff169081151580610b0c575b610adf5780600052600260205260026040600020019073ffffffffffffffffffffffffffffffffffffffff82541691837fffffffffffffffffffffffff0000000000000000000000000000000000000000825416179055828203610ab857005b7f754449ec3aff3bd528bfce43ae9319c4a381b67fcd1d20097b3b24dacaecc35d600080a4005b7f962b60e60000000000000000000000000000000000000000000000000000000060005260045260246000fd5b506040517f240028e8000000000000000000000000000000000000000000000000000000008152816004820152602081602481865afa908115610b9657600091610b58575b5015610a58565b6020813d602011610b8e575b81610b7160209383610f6f565b810103126109a45751908115158203610b8b575083610b51565b80fd5b3d9150610b64565b6040513d6000823e3d90fd5b346101bc5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101bc5773ffffffffffffffffffffffffffffffffffffffff610bee610f0d565b610bf66111e7565b16610c00816113e0565b610c0657005b60207f3cabf004338366bfeaeb610ad827cb58d16b588017c509501f2c97c83caae7b291604051908152a1005b346101bc5760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101bc576040516040810181811067ffffffffffffffff821117610d1657604052601881527f546f6b656e41646d696e526567697374727920312e352e300000000000000000602082015260405190602082528181519182602083015260005b838110610cfe5750507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f836000604080968601015201168101030190f35b60208282018101516040878401015285935001610cbe565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b346101bc5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101bc5773ffffffffffffffffffffffffffffffffffffffff610d91610f0d565b168060005260026020526040600020600181019073ffffffffffffffffffffffffffffffffffffffff8254163303610e505773ffffffffffffffffffffffffffffffffffffffff33167fffffffffffffffffffffffff00000000000000000000000000000000000000008254161790557fffffffffffffffffffffffff0000000000000000000000000000000000000000815416905533907f399b55200f7f639a63d76efe3dcfa9156ce367058d6b673041b84a628885f5a7600080a3005b827f3edffe75000000000000000000000000000000000000000000000000000000006000523360045260245260446000fd5b346101bc5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101bc5773ffffffffffffffffffffffffffffffffffffffff610ece610f0d565b610ed66111e7565b16610ee08161124a565b610ee657005b7f93eaa26dcb9275e56bacb1d33fdbf402262da6f0f4baf2a6e2cd154b73f387f8600080a2005b6004359073ffffffffffffffffffffffffffffffffffffffff821682036101bc57565b6024359073ffffffffffffffffffffffffffffffffffffffff821682036101bc57565b6060810190811067ffffffffffffffff821117610d1657604052565b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff821117610d1657604052565b602060408183019282815284518094520192019060005b818110610fd45750505090565b825173ffffffffffffffffffffffffffffffffffffffff16845260209384019390920191600101610fc7565b67ffffffffffffffff8111610d165760051b60200190565b9061102282611000565b61102f6040519182610f6f565b8281527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe061105d8294611000565b0190602036910137565b805182101561107b5760209160051b010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b919082018092116110b757565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b67ffffffffffffffff600354911691818310156111df5767ffffffffffffffff16908061111384846110aa565b116111ce575b509061112482611018565b91600091600354925b82811061113b575050505090565b61114581836110aa565b6000858210156111a157600390527fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b01546001919073ffffffffffffffffffffffffffffffffffffffff1661119a8288611067565b520161112d565b807f4e487b7100000000000000000000000000000000000000000000000000000000602492526032600452fd5b828103915081116110b75738611119565b505050606090565b73ffffffffffffffffffffffffffffffffffffffff60015416330361120857565b7f2b5c74de0000000000000000000000000000000000000000000000000000000060005260046000fd5b805482101561107b5760005260206000200190600090565b60008181526006602052604090205480156113d9577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81018181116110b757600554907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82019182116110b75781810361136a575b505050600554801561133b577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff016112f8816005611232565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82549160031b1b19169055600555600052600660205260006040812055600190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b6113c161137b61138c936005611232565b90549060031b1c9283926005611232565b81939154907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9060031b92831b921b19161790565b905560005260066020526040600020553880806112bf565b5050600090565b8060005260066020526040600020541560001461143a5760055468010000000000000000811015610d165761142161138c8260018594016005556005611232565b9055600554906000526006602052604060002055600190565b50600090565b8060005260046020526040600020541560001461143a5760035468010000000000000000811015610d165761148161138c8260018594016003556003611232565b905560035490600052600460205260406000205560019056fea164736f6c634300081a000a", + Bin: "0x608060405234801561001057600080fd5b503360008161003257604051639b15e16f60e01b815260040160405180910390fd5b600180546001600160a01b0319166001600160a01b03848116919091179091558116156100625761006281610069565b50506100e2565b336001600160a01b0382160361009257604051636d6c4ee560e11b815260040160405180910390fd5b600080546001600160a01b0319166001600160a01b03838116918217835560015460405192939116917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6113b9806100f16000396000f3fe608060405234801561001057600080fd5b50600436106101005760003560e01c80637d3f255211610097578063cb67e3b111610066578063cb67e3b1146102bc578063ddadfa8e14610374578063e677ae3714610387578063f2fde38b1461039a57600080fd5b80637d3f2552146101e05780638da5cb5b14610203578063bbe4f6db14610242578063c1af6e031461027f57600080fd5b80634e847fc7116100d35780634e847fc7146101925780635e63547a146101a557806372d64a81146101c557806379ba5097146101d857600080fd5b806310cbcf1814610105578063156194da1461011a578063181f5a771461012d5780633dc457721461017f575b600080fd5b6101186101133660046110dc565b6103ad565b005b6101186101283660046110dc565b61040a565b6101696040518060400160405280601881526020017f546f6b656e41646d696e526567697374727920312e352e30000000000000000081525081565b60405161017691906110f7565b60405180910390f35b61011861018d3660046110dc565b61050f565b6101186101a0366004611164565b610573565b6101b86101b3366004611197565b6107d3565b604051610176919061120c565b6101b86101d336600461127e565b6108cc565b6101186109e2565b6101f36101ee3660046110dc565b610ab0565b6040519015158152602001610176565b60015473ffffffffffffffffffffffffffffffffffffffff165b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610176565b61021d6102503660046110dc565b73ffffffffffffffffffffffffffffffffffffffff908116600090815260026020819052604090912001541690565b6101f361028d366004611164565b73ffffffffffffffffffffffffffffffffffffffff918216600090815260026020526040902054821691161490565b6103356102ca3660046110dc565b60408051606080820183526000808352602080840182905292840181905273ffffffffffffffffffffffffffffffffffffffff948516815260028084529084902084519283018552805486168352600181015486169383019390935291909101549092169082015290565b60408051825173ffffffffffffffffffffffffffffffffffffffff90811682526020808501518216908301529282015190921690820152606001610176565b610118610382366004611164565b610abd565b610118610395366004611164565b610bc7565b6101186103a83660046110dc565b610d8f565b6103b5610da0565b6103c0600582610df3565b156104075760405173ffffffffffffffffffffffffffffffffffffffff8216907f93eaa26dcb9275e56bacb1d33fdbf402262da6f0f4baf2a6e2cd154b73f387f890600090a25b50565b73ffffffffffffffffffffffffffffffffffffffff808216600090815260026020526040902060018101549091163314610493576040517f3edffe7500000000000000000000000000000000000000000000000000000000815233600482015273ffffffffffffffffffffffffffffffffffffffff831660248201526044015b60405180910390fd5b8054337fffffffffffffffffffffffff00000000000000000000000000000000000000009182168117835560018301805490921690915560405173ffffffffffffffffffffffffffffffffffffffff8416907f399b55200f7f639a63d76efe3dcfa9156ce367058d6b673041b84a628885f5a790600090a35050565b610517610da0565b610522600582610e1c565b156104075760405173ffffffffffffffffffffffffffffffffffffffff821681527f3cabf004338366bfeaeb610ad827cb58d16b588017c509501f2c97c83caae7b29060200160405180910390a150565b73ffffffffffffffffffffffffffffffffffffffff80831660009081526002602052604090205483911633146105f3576040517fed5d85b500000000000000000000000000000000000000000000000000000000815233600482015273ffffffffffffffffffffffffffffffffffffffff8216602482015260440161048a565b73ffffffffffffffffffffffffffffffffffffffff8216158015906106a557506040517f240028e800000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff848116600483015283169063240028e890602401602060405180830381865afa15801561067f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106a391906112a8565b155b156106f4576040517f962b60e600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8416600482015260240161048a565b73ffffffffffffffffffffffffffffffffffffffff808416600090815260026020819052604090912090810180548584167fffffffffffffffffffffffff0000000000000000000000000000000000000000821681179092559192919091169081146107cc578373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff167f754449ec3aff3bd528bfce43ae9319c4a381b67fcd1d20097b3b24dacaecc35d60405160405180910390a45b5050505050565b606060008267ffffffffffffffff8111156107f0576107f06112ca565b604051908082528060200260200182016040528015610819578160200160208202803683370190505b50905060005b838110156108c2576002600086868481811061083d5761083d6112f9565b905060200201602081019061085291906110dc565b73ffffffffffffffffffffffffffffffffffffffff90811682526020820192909252604001600020600201548351911690839083908110610895576108956112f9565b73ffffffffffffffffffffffffffffffffffffffff9092166020928302919091019091015260010161081f565b5090505b92915050565b606060006108da6003610e3e565b9050808467ffffffffffffffff16106108f357506108c6565b67ffffffffffffffff80841690829061090e90871683611357565b111561092b5761092867ffffffffffffffff86168361136a565b90505b8067ffffffffffffffff811115610944576109446112ca565b60405190808252806020026020018201604052801561096d578160200160208202803683370190505b50925060005b818110156109d95761099a6109928267ffffffffffffffff8916611357565b600390610e48565b8482815181106109ac576109ac6112f9565b73ffffffffffffffffffffffffffffffffffffffff90921660209283029190910190910152600101610973565b50505092915050565b60005473ffffffffffffffffffffffffffffffffffffffff163314610a33576040517f02b543c600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000008082163390811790935560008054909116815560405173ffffffffffffffffffffffffffffffffffffffff909216929183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b60006108c6600583610e54565b73ffffffffffffffffffffffffffffffffffffffff8083166000908152600260205260409020548391163314610b3d576040517fed5d85b500000000000000000000000000000000000000000000000000000000815233600482015273ffffffffffffffffffffffffffffffffffffffff8216602482015260440161048a565b73ffffffffffffffffffffffffffffffffffffffff8381166000818152600260205260408082206001810180547fffffffffffffffffffffffff00000000000000000000000000000000000000001695881695861790559051909392339290917fc54c3051ff16e63bb9203214432372aca006c589e3653619b577a3265675b7169190a450505050565b610bd033610ab0565b158015610bf5575060015473ffffffffffffffffffffffffffffffffffffffff163314155b15610c2e576040517f51ca1ec300000000000000000000000000000000000000000000000000000000815233600482015260240161048a565b73ffffffffffffffffffffffffffffffffffffffff8116610c7b576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8083166000908152600260205260409020805490911615610cf5576040517f45ed80e900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8416600482015260240161048a565b6001810180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff8416179055610d42600384610e1c565b5060405173ffffffffffffffffffffffffffffffffffffffff808416916000918616907fc54c3051ff16e63bb9203214432372aca006c589e3653619b577a3265675b716908390a4505050565b610d97610da0565b61040781610e83565b60015473ffffffffffffffffffffffffffffffffffffffff163314610df1576040517f2b5c74de00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b565b6000610e158373ffffffffffffffffffffffffffffffffffffffff8416610f47565b9392505050565b6000610e158373ffffffffffffffffffffffffffffffffffffffff841661103a565b60006108c6825490565b6000610e158383611089565b73ffffffffffffffffffffffffffffffffffffffff811660009081526001830160205260408120541515610e15565b3373ffffffffffffffffffffffffffffffffffffffff821603610ed2576040517fdad89dca00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff838116918217835560015460405192939116917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b60008181526001830160205260408120548015611030576000610f6b60018361136a565b8554909150600090610f7f9060019061136a565b9050808214610fe4576000866000018281548110610f9f57610f9f6112f9565b9060005260206000200154905080876000018481548110610fc257610fc26112f9565b6000918252602080832090910192909255918252600188019052604090208390555b8554869080610ff557610ff561137d565b6001900381819060005260206000200160009055905585600101600086815260200190815260200160002060009055600193505050506108c6565b60009150506108c6565b6000818152600183016020526040812054611081575081546001818101845560008481526020808220909301849055845484825282860190935260409020919091556108c6565b5060006108c6565b60008260000182815481106110a0576110a06112f9565b9060005260206000200154905092915050565b803573ffffffffffffffffffffffffffffffffffffffff811681146110d757600080fd5b919050565b6000602082840312156110ee57600080fd5b610e15826110b3565b60006020808352835180602085015260005b8181101561112557858101830151858201604001528201611109565b5060006040828601015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8301168501019250505092915050565b6000806040838503121561117757600080fd5b611180836110b3565b915061118e602084016110b3565b90509250929050565b600080602083850312156111aa57600080fd5b823567ffffffffffffffff808211156111c257600080fd5b818501915085601f8301126111d657600080fd5b8135818111156111e557600080fd5b8660208260051b85010111156111fa57600080fd5b60209290920196919550909350505050565b6020808252825182820181905260009190848201906040850190845b8181101561125a57835173ffffffffffffffffffffffffffffffffffffffff1683529284019291840191600101611228565b50909695505050505050565b803567ffffffffffffffff811681146110d757600080fd5b6000806040838503121561129157600080fd5b61129a83611266565b915061118e60208401611266565b6000602082840312156112ba57600080fd5b81518015158114610e1557600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b808201808211156108c6576108c6611328565b818103818111156108c6576108c6611328565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fdfea164736f6c6343000818000a", } var TokenAdminRegistryABI = TokenAdminRegistryMetaData.ABI diff --git a/core/gethwrappers/ccip/generated/token_pool/token_pool.go b/core/gethwrappers/ccip/generated/token_pool/token_pool.go index c7c947d8636..3465ff76fe0 100644 --- a/core/gethwrappers/ccip/generated/token_pool/token_pool.go +++ b/core/gethwrappers/ccip/generated/token_pool/token_pool.go @@ -74,14 +74,15 @@ type RateLimiterTokenBucket struct { type TokenPoolChainUpdate struct { RemoteChainSelector uint64 - RemotePoolAddresses [][]byte + Allowed bool + RemotePoolAddress []byte RemoteTokenAddress []byte OutboundRateLimiterConfig RateLimiterConfig InboundRateLimiterConfig RateLimiterConfig } var TokenPoolMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[],\"name\":\"AllowListNotEnabled\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"CallerIsNotARampOnRouter\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CannotTransferToSelf\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"}],\"name\":\"ChainAlreadyExists\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"ChainNotAllowed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CursedByRMN\",\"type\":\"error\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"config\",\"type\":\"tuple\"}],\"name\":\"DisabledNonZeroRateLimit\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"expected\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"actual\",\"type\":\"uint8\"}],\"name\":\"InvalidDecimalArgs\",\"type\":\"error\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"rateLimiterConfig\",\"type\":\"tuple\"}],\"name\":\"InvalidRateLimitRate\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolData\",\"type\":\"bytes\"}],\"name\":\"InvalidRemoteChainDecimals\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"InvalidRemotePoolForChain\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"}],\"name\":\"InvalidSourcePoolAddress\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"InvalidToken\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MismatchedArrayLengths\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MustBeProposedOwner\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"NonExistentChain\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByOwner\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"remoteDecimals\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"localDecimals\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"remoteAmount\",\"type\":\"uint256\"}],\"name\":\"OverflowDetected\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OwnerCannotBeZero\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"PoolAlreadyAdded\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RateLimitMustBeDisabled\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"SenderNotAllowed\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"Unauthorized\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"AllowListAdd\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"AllowListRemove\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Burned\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"remoteToken\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundRateLimiterConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundRateLimiterConfig\",\"type\":\"tuple\"}],\"name\":\"ChainAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundRateLimiterConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundRateLimiterConfig\",\"type\":\"tuple\"}],\"name\":\"ChainConfigured\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"ChainRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"config\",\"type\":\"tuple\"}],\"name\":\"ConfigChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Locked\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Minted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"rateLimitAdmin\",\"type\":\"address\"}],\"name\":\"RateLimitAdminSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Released\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"RemotePoolAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"RemotePoolRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"oldRouter\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newRouter\",\"type\":\"address\"}],\"name\":\"RouterUpdated\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"addRemotePool\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"removes\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"adds\",\"type\":\"address[]\"}],\"name\":\"applyAllowListUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64[]\",\"name\":\"remoteChainSelectorsToRemove\",\"type\":\"uint64[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes[]\",\"name\":\"remotePoolAddresses\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes\",\"name\":\"remoteTokenAddress\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundRateLimiterConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundRateLimiterConfig\",\"type\":\"tuple\"}],\"internalType\":\"structTokenPool.ChainUpdate[]\",\"name\":\"chainsToAdd\",\"type\":\"tuple[]\"}],\"name\":\"applyChainUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAllowList\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAllowListEnabled\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getCurrentInboundRateLimiterState\",\"outputs\":[{\"components\":[{\"internalType\":\"uint128\",\"name\":\"tokens\",\"type\":\"uint128\"},{\"internalType\":\"uint32\",\"name\":\"lastUpdated\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.TokenBucket\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getCurrentOutboundRateLimiterState\",\"outputs\":[{\"components\":[{\"internalType\":\"uint128\",\"name\":\"tokens\",\"type\":\"uint128\"},{\"internalType\":\"uint32\",\"name\":\"lastUpdated\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.TokenBucket\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRateLimitAdmin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getRemotePools\",\"outputs\":[{\"internalType\":\"bytes[]\",\"name\":\"\",\"type\":\"bytes[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getRemoteToken\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRmnProxy\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRouter\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getSupportedChains\",\"outputs\":[{\"internalType\":\"uint64[]\",\"name\":\"\",\"type\":\"uint64[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getToken\",\"outputs\":[{\"internalType\":\"contractIERC20\",\"name\":\"token\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getTokenDecimals\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"decimals\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"isRemotePool\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"isSupportedChain\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"isSupportedToken\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"originalSender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"localToken\",\"type\":\"address\"}],\"internalType\":\"structPool.LockOrBurnInV1\",\"name\":\"lockOrBurnIn\",\"type\":\"tuple\"}],\"name\":\"lockOrBurn\",\"outputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"destPoolData\",\"type\":\"bytes\"}],\"internalType\":\"structPool.LockOrBurnOutV1\",\"name\":\"lockOrBurnOut\",\"type\":\"tuple\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"originalSender\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"localToken\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"sourcePoolData\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"offchainTokenData\",\"type\":\"bytes\"}],\"internalType\":\"structPool.ReleaseOrMintInV1\",\"name\":\"releaseOrMintIn\",\"type\":\"tuple\"}],\"name\":\"releaseOrMint\",\"outputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"destinationAmount\",\"type\":\"uint256\"}],\"internalType\":\"structPool.ReleaseOrMintOutV1\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"removeRemotePool\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundConfig\",\"type\":\"tuple\"}],\"name\":\"setChainRateLimiterConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64[]\",\"name\":\"remoteChainSelectors\",\"type\":\"uint64[]\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config[]\",\"name\":\"outboundConfigs\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config[]\",\"name\":\"inboundConfigs\",\"type\":\"tuple[]\"}],\"name\":\"setChainRateLimiterConfigs\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"rateLimitAdmin\",\"type\":\"address\"}],\"name\":\"setRateLimitAdmin\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newRouter\",\"type\":\"address\"}],\"name\":\"setRouter\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", + ABI: "[{\"inputs\":[],\"name\":\"AllowListNotEnabled\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"CallerIsNotARampOnRouter\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CannotTransferToSelf\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"}],\"name\":\"ChainAlreadyExists\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"ChainNotAllowed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CursedByRMN\",\"type\":\"error\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"config\",\"type\":\"tuple\"}],\"name\":\"DisabledNonZeroRateLimit\",\"type\":\"error\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"rateLimiterConfig\",\"type\":\"tuple\"}],\"name\":\"InvalidRateLimitRate\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"}],\"name\":\"InvalidSourcePoolAddress\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"InvalidToken\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MustBeProposedOwner\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"NonExistentChain\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByOwner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OwnerCannotBeZero\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RateLimitMustBeDisabled\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"SenderNotAllowed\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"Unauthorized\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"AllowListAdd\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"AllowListRemove\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Burned\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"remoteToken\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundRateLimiterConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundRateLimiterConfig\",\"type\":\"tuple\"}],\"name\":\"ChainAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundRateLimiterConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundRateLimiterConfig\",\"type\":\"tuple\"}],\"name\":\"ChainConfigured\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"ChainRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"config\",\"type\":\"tuple\"}],\"name\":\"ConfigChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Locked\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Minted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"rateLimitAdmin\",\"type\":\"address\"}],\"name\":\"RateLimitAdminSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Released\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"previousPoolAddress\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"RemotePoolSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"oldRouter\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newRouter\",\"type\":\"address\"}],\"name\":\"RouterUpdated\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"removes\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"adds\",\"type\":\"address[]\"}],\"name\":\"applyAllowListUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"allowed\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"remoteTokenAddress\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundRateLimiterConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundRateLimiterConfig\",\"type\":\"tuple\"}],\"internalType\":\"structTokenPool.ChainUpdate[]\",\"name\":\"chains\",\"type\":\"tuple[]\"}],\"name\":\"applyChainUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAllowList\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAllowListEnabled\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getCurrentInboundRateLimiterState\",\"outputs\":[{\"components\":[{\"internalType\":\"uint128\",\"name\":\"tokens\",\"type\":\"uint128\"},{\"internalType\":\"uint32\",\"name\":\"lastUpdated\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.TokenBucket\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getCurrentOutboundRateLimiterState\",\"outputs\":[{\"components\":[{\"internalType\":\"uint128\",\"name\":\"tokens\",\"type\":\"uint128\"},{\"internalType\":\"uint32\",\"name\":\"lastUpdated\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.TokenBucket\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRateLimitAdmin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getRemotePool\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getRemoteToken\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRmnProxy\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRouter\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getSupportedChains\",\"outputs\":[{\"internalType\":\"uint64[]\",\"name\":\"\",\"type\":\"uint64[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getToken\",\"outputs\":[{\"internalType\":\"contractIERC20\",\"name\":\"token\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"isSupportedChain\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"isSupportedToken\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"originalSender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"localToken\",\"type\":\"address\"}],\"internalType\":\"structPool.LockOrBurnInV1\",\"name\":\"lockOrBurnIn\",\"type\":\"tuple\"}],\"name\":\"lockOrBurn\",\"outputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"destPoolData\",\"type\":\"bytes\"}],\"internalType\":\"structPool.LockOrBurnOutV1\",\"name\":\"lockOrBurnOut\",\"type\":\"tuple\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"originalSender\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"localToken\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"sourcePoolData\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"offchainTokenData\",\"type\":\"bytes\"}],\"internalType\":\"structPool.ReleaseOrMintInV1\",\"name\":\"releaseOrMintIn\",\"type\":\"tuple\"}],\"name\":\"releaseOrMint\",\"outputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"destinationAmount\",\"type\":\"uint256\"}],\"internalType\":\"structPool.ReleaseOrMintOutV1\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundConfig\",\"type\":\"tuple\"}],\"name\":\"setChainRateLimiterConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"rateLimitAdmin\",\"type\":\"address\"}],\"name\":\"setRateLimitAdmin\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"setRemotePool\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newRouter\",\"type\":\"address\"}],\"name\":\"setRouter\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", } var TokenPoolABI = TokenPoolMetaData.ABI @@ -312,26 +313,26 @@ func (_TokenPool *TokenPoolCallerSession) GetRateLimitAdmin() (common.Address, e return _TokenPool.Contract.GetRateLimitAdmin(&_TokenPool.CallOpts) } -func (_TokenPool *TokenPoolCaller) GetRemotePools(opts *bind.CallOpts, remoteChainSelector uint64) ([][]byte, error) { +func (_TokenPool *TokenPoolCaller) GetRemotePool(opts *bind.CallOpts, remoteChainSelector uint64) ([]byte, error) { var out []interface{} - err := _TokenPool.contract.Call(opts, &out, "getRemotePools", remoteChainSelector) + err := _TokenPool.contract.Call(opts, &out, "getRemotePool", remoteChainSelector) if err != nil { - return *new([][]byte), err + return *new([]byte), err } - out0 := *abi.ConvertType(out[0], new([][]byte)).(*[][]byte) + out0 := *abi.ConvertType(out[0], new([]byte)).(*[]byte) return out0, err } -func (_TokenPool *TokenPoolSession) GetRemotePools(remoteChainSelector uint64) ([][]byte, error) { - return _TokenPool.Contract.GetRemotePools(&_TokenPool.CallOpts, remoteChainSelector) +func (_TokenPool *TokenPoolSession) GetRemotePool(remoteChainSelector uint64) ([]byte, error) { + return _TokenPool.Contract.GetRemotePool(&_TokenPool.CallOpts, remoteChainSelector) } -func (_TokenPool *TokenPoolCallerSession) GetRemotePools(remoteChainSelector uint64) ([][]byte, error) { - return _TokenPool.Contract.GetRemotePools(&_TokenPool.CallOpts, remoteChainSelector) +func (_TokenPool *TokenPoolCallerSession) GetRemotePool(remoteChainSelector uint64) ([]byte, error) { + return _TokenPool.Contract.GetRemotePool(&_TokenPool.CallOpts, remoteChainSelector) } func (_TokenPool *TokenPoolCaller) GetRemoteToken(opts *bind.CallOpts, remoteChainSelector uint64) ([]byte, error) { @@ -444,50 +445,6 @@ func (_TokenPool *TokenPoolCallerSession) GetToken() (common.Address, error) { return _TokenPool.Contract.GetToken(&_TokenPool.CallOpts) } -func (_TokenPool *TokenPoolCaller) GetTokenDecimals(opts *bind.CallOpts) (uint8, error) { - var out []interface{} - err := _TokenPool.contract.Call(opts, &out, "getTokenDecimals") - - if err != nil { - return *new(uint8), err - } - - out0 := *abi.ConvertType(out[0], new(uint8)).(*uint8) - - return out0, err - -} - -func (_TokenPool *TokenPoolSession) GetTokenDecimals() (uint8, error) { - return _TokenPool.Contract.GetTokenDecimals(&_TokenPool.CallOpts) -} - -func (_TokenPool *TokenPoolCallerSession) GetTokenDecimals() (uint8, error) { - return _TokenPool.Contract.GetTokenDecimals(&_TokenPool.CallOpts) -} - -func (_TokenPool *TokenPoolCaller) IsRemotePool(opts *bind.CallOpts, remoteChainSelector uint64, remotePoolAddress []byte) (bool, error) { - var out []interface{} - err := _TokenPool.contract.Call(opts, &out, "isRemotePool", remoteChainSelector, remotePoolAddress) - - if err != nil { - return *new(bool), err - } - - out0 := *abi.ConvertType(out[0], new(bool)).(*bool) - - return out0, err - -} - -func (_TokenPool *TokenPoolSession) IsRemotePool(remoteChainSelector uint64, remotePoolAddress []byte) (bool, error) { - return _TokenPool.Contract.IsRemotePool(&_TokenPool.CallOpts, remoteChainSelector, remotePoolAddress) -} - -func (_TokenPool *TokenPoolCallerSession) IsRemotePool(remoteChainSelector uint64, remotePoolAddress []byte) (bool, error) { - return _TokenPool.Contract.IsRemotePool(&_TokenPool.CallOpts, remoteChainSelector, remotePoolAddress) -} - func (_TokenPool *TokenPoolCaller) IsSupportedChain(opts *bind.CallOpts, remoteChainSelector uint64) (bool, error) { var out []interface{} err := _TokenPool.contract.Call(opts, &out, "isSupportedChain", remoteChainSelector) @@ -588,18 +545,6 @@ func (_TokenPool *TokenPoolTransactorSession) AcceptOwnership() (*types.Transact return _TokenPool.Contract.AcceptOwnership(&_TokenPool.TransactOpts) } -func (_TokenPool *TokenPoolTransactor) AddRemotePool(opts *bind.TransactOpts, remoteChainSelector uint64, remotePoolAddress []byte) (*types.Transaction, error) { - return _TokenPool.contract.Transact(opts, "addRemotePool", remoteChainSelector, remotePoolAddress) -} - -func (_TokenPool *TokenPoolSession) AddRemotePool(remoteChainSelector uint64, remotePoolAddress []byte) (*types.Transaction, error) { - return _TokenPool.Contract.AddRemotePool(&_TokenPool.TransactOpts, remoteChainSelector, remotePoolAddress) -} - -func (_TokenPool *TokenPoolTransactorSession) AddRemotePool(remoteChainSelector uint64, remotePoolAddress []byte) (*types.Transaction, error) { - return _TokenPool.Contract.AddRemotePool(&_TokenPool.TransactOpts, remoteChainSelector, remotePoolAddress) -} - func (_TokenPool *TokenPoolTransactor) ApplyAllowListUpdates(opts *bind.TransactOpts, removes []common.Address, adds []common.Address) (*types.Transaction, error) { return _TokenPool.contract.Transact(opts, "applyAllowListUpdates", removes, adds) } @@ -612,16 +557,16 @@ func (_TokenPool *TokenPoolTransactorSession) ApplyAllowListUpdates(removes []co return _TokenPool.Contract.ApplyAllowListUpdates(&_TokenPool.TransactOpts, removes, adds) } -func (_TokenPool *TokenPoolTransactor) ApplyChainUpdates(opts *bind.TransactOpts, remoteChainSelectorsToRemove []uint64, chainsToAdd []TokenPoolChainUpdate) (*types.Transaction, error) { - return _TokenPool.contract.Transact(opts, "applyChainUpdates", remoteChainSelectorsToRemove, chainsToAdd) +func (_TokenPool *TokenPoolTransactor) ApplyChainUpdates(opts *bind.TransactOpts, chains []TokenPoolChainUpdate) (*types.Transaction, error) { + return _TokenPool.contract.Transact(opts, "applyChainUpdates", chains) } -func (_TokenPool *TokenPoolSession) ApplyChainUpdates(remoteChainSelectorsToRemove []uint64, chainsToAdd []TokenPoolChainUpdate) (*types.Transaction, error) { - return _TokenPool.Contract.ApplyChainUpdates(&_TokenPool.TransactOpts, remoteChainSelectorsToRemove, chainsToAdd) +func (_TokenPool *TokenPoolSession) ApplyChainUpdates(chains []TokenPoolChainUpdate) (*types.Transaction, error) { + return _TokenPool.Contract.ApplyChainUpdates(&_TokenPool.TransactOpts, chains) } -func (_TokenPool *TokenPoolTransactorSession) ApplyChainUpdates(remoteChainSelectorsToRemove []uint64, chainsToAdd []TokenPoolChainUpdate) (*types.Transaction, error) { - return _TokenPool.Contract.ApplyChainUpdates(&_TokenPool.TransactOpts, remoteChainSelectorsToRemove, chainsToAdd) +func (_TokenPool *TokenPoolTransactorSession) ApplyChainUpdates(chains []TokenPoolChainUpdate) (*types.Transaction, error) { + return _TokenPool.Contract.ApplyChainUpdates(&_TokenPool.TransactOpts, chains) } func (_TokenPool *TokenPoolTransactor) LockOrBurn(opts *bind.TransactOpts, lockOrBurnIn PoolLockOrBurnInV1) (*types.Transaction, error) { @@ -648,18 +593,6 @@ func (_TokenPool *TokenPoolTransactorSession) ReleaseOrMint(releaseOrMintIn Pool return _TokenPool.Contract.ReleaseOrMint(&_TokenPool.TransactOpts, releaseOrMintIn) } -func (_TokenPool *TokenPoolTransactor) RemoveRemotePool(opts *bind.TransactOpts, remoteChainSelector uint64, remotePoolAddress []byte) (*types.Transaction, error) { - return _TokenPool.contract.Transact(opts, "removeRemotePool", remoteChainSelector, remotePoolAddress) -} - -func (_TokenPool *TokenPoolSession) RemoveRemotePool(remoteChainSelector uint64, remotePoolAddress []byte) (*types.Transaction, error) { - return _TokenPool.Contract.RemoveRemotePool(&_TokenPool.TransactOpts, remoteChainSelector, remotePoolAddress) -} - -func (_TokenPool *TokenPoolTransactorSession) RemoveRemotePool(remoteChainSelector uint64, remotePoolAddress []byte) (*types.Transaction, error) { - return _TokenPool.Contract.RemoveRemotePool(&_TokenPool.TransactOpts, remoteChainSelector, remotePoolAddress) -} - func (_TokenPool *TokenPoolTransactor) SetChainRateLimiterConfig(opts *bind.TransactOpts, remoteChainSelector uint64, outboundConfig RateLimiterConfig, inboundConfig RateLimiterConfig) (*types.Transaction, error) { return _TokenPool.contract.Transact(opts, "setChainRateLimiterConfig", remoteChainSelector, outboundConfig, inboundConfig) } @@ -672,18 +605,6 @@ func (_TokenPool *TokenPoolTransactorSession) SetChainRateLimiterConfig(remoteCh return _TokenPool.Contract.SetChainRateLimiterConfig(&_TokenPool.TransactOpts, remoteChainSelector, outboundConfig, inboundConfig) } -func (_TokenPool *TokenPoolTransactor) SetChainRateLimiterConfigs(opts *bind.TransactOpts, remoteChainSelectors []uint64, outboundConfigs []RateLimiterConfig, inboundConfigs []RateLimiterConfig) (*types.Transaction, error) { - return _TokenPool.contract.Transact(opts, "setChainRateLimiterConfigs", remoteChainSelectors, outboundConfigs, inboundConfigs) -} - -func (_TokenPool *TokenPoolSession) SetChainRateLimiterConfigs(remoteChainSelectors []uint64, outboundConfigs []RateLimiterConfig, inboundConfigs []RateLimiterConfig) (*types.Transaction, error) { - return _TokenPool.Contract.SetChainRateLimiterConfigs(&_TokenPool.TransactOpts, remoteChainSelectors, outboundConfigs, inboundConfigs) -} - -func (_TokenPool *TokenPoolTransactorSession) SetChainRateLimiterConfigs(remoteChainSelectors []uint64, outboundConfigs []RateLimiterConfig, inboundConfigs []RateLimiterConfig) (*types.Transaction, error) { - return _TokenPool.Contract.SetChainRateLimiterConfigs(&_TokenPool.TransactOpts, remoteChainSelectors, outboundConfigs, inboundConfigs) -} - func (_TokenPool *TokenPoolTransactor) SetRateLimitAdmin(opts *bind.TransactOpts, rateLimitAdmin common.Address) (*types.Transaction, error) { return _TokenPool.contract.Transact(opts, "setRateLimitAdmin", rateLimitAdmin) } @@ -696,6 +617,18 @@ func (_TokenPool *TokenPoolTransactorSession) SetRateLimitAdmin(rateLimitAdmin c return _TokenPool.Contract.SetRateLimitAdmin(&_TokenPool.TransactOpts, rateLimitAdmin) } +func (_TokenPool *TokenPoolTransactor) SetRemotePool(opts *bind.TransactOpts, remoteChainSelector uint64, remotePoolAddress []byte) (*types.Transaction, error) { + return _TokenPool.contract.Transact(opts, "setRemotePool", remoteChainSelector, remotePoolAddress) +} + +func (_TokenPool *TokenPoolSession) SetRemotePool(remoteChainSelector uint64, remotePoolAddress []byte) (*types.Transaction, error) { + return _TokenPool.Contract.SetRemotePool(&_TokenPool.TransactOpts, remoteChainSelector, remotePoolAddress) +} + +func (_TokenPool *TokenPoolTransactorSession) SetRemotePool(remoteChainSelector uint64, remotePoolAddress []byte) (*types.Transaction, error) { + return _TokenPool.Contract.SetRemotePool(&_TokenPool.TransactOpts, remoteChainSelector, remotePoolAddress) +} + func (_TokenPool *TokenPoolTransactor) SetRouter(opts *bind.TransactOpts, newRouter common.Address) (*types.Transaction, error) { return _TokenPool.contract.Transact(opts, "setRouter", newRouter) } @@ -2346,8 +2279,8 @@ func (_TokenPool *TokenPoolFilterer) ParseReleased(log types.Log) (*TokenPoolRel return event, nil } -type TokenPoolRemotePoolAddedIterator struct { - Event *TokenPoolRemotePoolAdded +type TokenPoolRemotePoolSetIterator struct { + Event *TokenPoolRemotePoolSet contract *bind.BoundContract event string @@ -2358,7 +2291,7 @@ type TokenPoolRemotePoolAddedIterator struct { fail error } -func (it *TokenPoolRemotePoolAddedIterator) Next() bool { +func (it *TokenPoolRemotePoolSetIterator) Next() bool { if it.fail != nil { return false @@ -2367,7 +2300,7 @@ func (it *TokenPoolRemotePoolAddedIterator) Next() bool { if it.done { select { case log := <-it.logs: - it.Event = new(TokenPoolRemotePoolAdded) + it.Event = new(TokenPoolRemotePoolSet) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -2382,7 +2315,7 @@ func (it *TokenPoolRemotePoolAddedIterator) Next() bool { select { case log := <-it.logs: - it.Event = new(TokenPoolRemotePoolAdded) + it.Event = new(TokenPoolRemotePoolSet) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -2397,43 +2330,44 @@ func (it *TokenPoolRemotePoolAddedIterator) Next() bool { } } -func (it *TokenPoolRemotePoolAddedIterator) Error() error { +func (it *TokenPoolRemotePoolSetIterator) Error() error { return it.fail } -func (it *TokenPoolRemotePoolAddedIterator) Close() error { +func (it *TokenPoolRemotePoolSetIterator) Close() error { it.sub.Unsubscribe() return nil } -type TokenPoolRemotePoolAdded struct { +type TokenPoolRemotePoolSet struct { RemoteChainSelector uint64 + PreviousPoolAddress []byte RemotePoolAddress []byte Raw types.Log } -func (_TokenPool *TokenPoolFilterer) FilterRemotePoolAdded(opts *bind.FilterOpts, remoteChainSelector []uint64) (*TokenPoolRemotePoolAddedIterator, error) { +func (_TokenPool *TokenPoolFilterer) FilterRemotePoolSet(opts *bind.FilterOpts, remoteChainSelector []uint64) (*TokenPoolRemotePoolSetIterator, error) { var remoteChainSelectorRule []interface{} for _, remoteChainSelectorItem := range remoteChainSelector { remoteChainSelectorRule = append(remoteChainSelectorRule, remoteChainSelectorItem) } - logs, sub, err := _TokenPool.contract.FilterLogs(opts, "RemotePoolAdded", remoteChainSelectorRule) + logs, sub, err := _TokenPool.contract.FilterLogs(opts, "RemotePoolSet", remoteChainSelectorRule) if err != nil { return nil, err } - return &TokenPoolRemotePoolAddedIterator{contract: _TokenPool.contract, event: "RemotePoolAdded", logs: logs, sub: sub}, nil + return &TokenPoolRemotePoolSetIterator{contract: _TokenPool.contract, event: "RemotePoolSet", logs: logs, sub: sub}, nil } -func (_TokenPool *TokenPoolFilterer) WatchRemotePoolAdded(opts *bind.WatchOpts, sink chan<- *TokenPoolRemotePoolAdded, remoteChainSelector []uint64) (event.Subscription, error) { +func (_TokenPool *TokenPoolFilterer) WatchRemotePoolSet(opts *bind.WatchOpts, sink chan<- *TokenPoolRemotePoolSet, remoteChainSelector []uint64) (event.Subscription, error) { var remoteChainSelectorRule []interface{} for _, remoteChainSelectorItem := range remoteChainSelector { remoteChainSelectorRule = append(remoteChainSelectorRule, remoteChainSelectorItem) } - logs, sub, err := _TokenPool.contract.WatchLogs(opts, "RemotePoolAdded", remoteChainSelectorRule) + logs, sub, err := _TokenPool.contract.WatchLogs(opts, "RemotePoolSet", remoteChainSelectorRule) if err != nil { return nil, err } @@ -2443,8 +2377,8 @@ func (_TokenPool *TokenPoolFilterer) WatchRemotePoolAdded(opts *bind.WatchOpts, select { case log := <-logs: - event := new(TokenPoolRemotePoolAdded) - if err := _TokenPool.contract.UnpackLog(event, "RemotePoolAdded", log); err != nil { + event := new(TokenPoolRemotePoolSet) + if err := _TokenPool.contract.UnpackLog(event, "RemotePoolSet", log); err != nil { return err } event.Raw = log @@ -2465,137 +2399,9 @@ func (_TokenPool *TokenPoolFilterer) WatchRemotePoolAdded(opts *bind.WatchOpts, }), nil } -func (_TokenPool *TokenPoolFilterer) ParseRemotePoolAdded(log types.Log) (*TokenPoolRemotePoolAdded, error) { - event := new(TokenPoolRemotePoolAdded) - if err := _TokenPool.contract.UnpackLog(event, "RemotePoolAdded", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -type TokenPoolRemotePoolRemovedIterator struct { - Event *TokenPoolRemotePoolRemoved - - contract *bind.BoundContract - event string - - logs chan types.Log - sub ethereum.Subscription - done bool - fail error -} - -func (it *TokenPoolRemotePoolRemovedIterator) Next() bool { - - if it.fail != nil { - return false - } - - if it.done { - select { - case log := <-it.logs: - it.Event = new(TokenPoolRemotePoolRemoved) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - default: - return false - } - } - - select { - case log := <-it.logs: - it.Event = new(TokenPoolRemotePoolRemoved) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - case err := <-it.sub.Err(): - it.done = true - it.fail = err - return it.Next() - } -} - -func (it *TokenPoolRemotePoolRemovedIterator) Error() error { - return it.fail -} - -func (it *TokenPoolRemotePoolRemovedIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -type TokenPoolRemotePoolRemoved struct { - RemoteChainSelector uint64 - RemotePoolAddress []byte - Raw types.Log -} - -func (_TokenPool *TokenPoolFilterer) FilterRemotePoolRemoved(opts *bind.FilterOpts, remoteChainSelector []uint64) (*TokenPoolRemotePoolRemovedIterator, error) { - - var remoteChainSelectorRule []interface{} - for _, remoteChainSelectorItem := range remoteChainSelector { - remoteChainSelectorRule = append(remoteChainSelectorRule, remoteChainSelectorItem) - } - - logs, sub, err := _TokenPool.contract.FilterLogs(opts, "RemotePoolRemoved", remoteChainSelectorRule) - if err != nil { - return nil, err - } - return &TokenPoolRemotePoolRemovedIterator{contract: _TokenPool.contract, event: "RemotePoolRemoved", logs: logs, sub: sub}, nil -} - -func (_TokenPool *TokenPoolFilterer) WatchRemotePoolRemoved(opts *bind.WatchOpts, sink chan<- *TokenPoolRemotePoolRemoved, remoteChainSelector []uint64) (event.Subscription, error) { - - var remoteChainSelectorRule []interface{} - for _, remoteChainSelectorItem := range remoteChainSelector { - remoteChainSelectorRule = append(remoteChainSelectorRule, remoteChainSelectorItem) - } - - logs, sub, err := _TokenPool.contract.WatchLogs(opts, "RemotePoolRemoved", remoteChainSelectorRule) - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - - event := new(TokenPoolRemotePoolRemoved) - if err := _TokenPool.contract.UnpackLog(event, "RemotePoolRemoved", log); err != nil { - return err - } - event.Raw = log - - select { - case sink <- event: - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - } - }), nil -} - -func (_TokenPool *TokenPoolFilterer) ParseRemotePoolRemoved(log types.Log) (*TokenPoolRemotePoolRemoved, error) { - event := new(TokenPoolRemotePoolRemoved) - if err := _TokenPool.contract.UnpackLog(event, "RemotePoolRemoved", log); err != nil { +func (_TokenPool *TokenPoolFilterer) ParseRemotePoolSet(log types.Log) (*TokenPoolRemotePoolSet, error) { + event := new(TokenPoolRemotePoolSet) + if err := _TokenPool.contract.UnpackLog(event, "RemotePoolSet", log); err != nil { return nil, err } event.Raw = log @@ -2748,10 +2554,8 @@ func (_TokenPool *TokenPool) ParseLog(log types.Log) (generated.AbigenLog, error return _TokenPool.ParseRateLimitAdminSet(log) case _TokenPool.abi.Events["Released"].ID: return _TokenPool.ParseReleased(log) - case _TokenPool.abi.Events["RemotePoolAdded"].ID: - return _TokenPool.ParseRemotePoolAdded(log) - case _TokenPool.abi.Events["RemotePoolRemoved"].ID: - return _TokenPool.ParseRemotePoolRemoved(log) + case _TokenPool.abi.Events["RemotePoolSet"].ID: + return _TokenPool.ParseRemotePoolSet(log) case _TokenPool.abi.Events["RouterUpdated"].ID: return _TokenPool.ParseRouterUpdated(log) @@ -2812,12 +2616,8 @@ func (TokenPoolReleased) Topic() common.Hash { return common.HexToHash("0x2d87480f50083e2b2759522a8fdda59802650a8055e609a7772cf70c07748f52") } -func (TokenPoolRemotePoolAdded) Topic() common.Hash { - return common.HexToHash("0x7d628c9a1796743d365ab521a8b2a4686e419b3269919dc9145ea2ce853b54ea") -} - -func (TokenPoolRemotePoolRemoved) Topic() common.Hash { - return common.HexToHash("0x52d00ee4d9bd51b40168f2afc5848837288ce258784ad914278791464b3f4d76") +func (TokenPoolRemotePoolSet) Topic() common.Hash { + return common.HexToHash("0xdb4d6220746a38cbc5335f7e108f7de80f482f4d23350253dfd0917df75a14bf") } func (TokenPoolRouterUpdated) Topic() common.Hash { @@ -2839,7 +2639,7 @@ type TokenPoolInterface interface { GetRateLimitAdmin(opts *bind.CallOpts) (common.Address, error) - GetRemotePools(opts *bind.CallOpts, remoteChainSelector uint64) ([][]byte, error) + GetRemotePool(opts *bind.CallOpts, remoteChainSelector uint64) ([]byte, error) GetRemoteToken(opts *bind.CallOpts, remoteChainSelector uint64) ([]byte, error) @@ -2851,10 +2651,6 @@ type TokenPoolInterface interface { GetToken(opts *bind.CallOpts) (common.Address, error) - GetTokenDecimals(opts *bind.CallOpts) (uint8, error) - - IsRemotePool(opts *bind.CallOpts, remoteChainSelector uint64, remotePoolAddress []byte) (bool, error) - IsSupportedChain(opts *bind.CallOpts, remoteChainSelector uint64) (bool, error) IsSupportedToken(opts *bind.CallOpts, token common.Address) (bool, error) @@ -2865,24 +2661,20 @@ type TokenPoolInterface interface { AcceptOwnership(opts *bind.TransactOpts) (*types.Transaction, error) - AddRemotePool(opts *bind.TransactOpts, remoteChainSelector uint64, remotePoolAddress []byte) (*types.Transaction, error) - ApplyAllowListUpdates(opts *bind.TransactOpts, removes []common.Address, adds []common.Address) (*types.Transaction, error) - ApplyChainUpdates(opts *bind.TransactOpts, remoteChainSelectorsToRemove []uint64, chainsToAdd []TokenPoolChainUpdate) (*types.Transaction, error) + ApplyChainUpdates(opts *bind.TransactOpts, chains []TokenPoolChainUpdate) (*types.Transaction, error) LockOrBurn(opts *bind.TransactOpts, lockOrBurnIn PoolLockOrBurnInV1) (*types.Transaction, error) ReleaseOrMint(opts *bind.TransactOpts, releaseOrMintIn PoolReleaseOrMintInV1) (*types.Transaction, error) - RemoveRemotePool(opts *bind.TransactOpts, remoteChainSelector uint64, remotePoolAddress []byte) (*types.Transaction, error) - SetChainRateLimiterConfig(opts *bind.TransactOpts, remoteChainSelector uint64, outboundConfig RateLimiterConfig, inboundConfig RateLimiterConfig) (*types.Transaction, error) - SetChainRateLimiterConfigs(opts *bind.TransactOpts, remoteChainSelectors []uint64, outboundConfigs []RateLimiterConfig, inboundConfigs []RateLimiterConfig) (*types.Transaction, error) - SetRateLimitAdmin(opts *bind.TransactOpts, rateLimitAdmin common.Address) (*types.Transaction, error) + SetRemotePool(opts *bind.TransactOpts, remoteChainSelector uint64, remotePoolAddress []byte) (*types.Transaction, error) + SetRouter(opts *bind.TransactOpts, newRouter common.Address) (*types.Transaction, error) TransferOwnership(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) @@ -2965,17 +2757,11 @@ type TokenPoolInterface interface { ParseReleased(log types.Log) (*TokenPoolReleased, error) - FilterRemotePoolAdded(opts *bind.FilterOpts, remoteChainSelector []uint64) (*TokenPoolRemotePoolAddedIterator, error) - - WatchRemotePoolAdded(opts *bind.WatchOpts, sink chan<- *TokenPoolRemotePoolAdded, remoteChainSelector []uint64) (event.Subscription, error) - - ParseRemotePoolAdded(log types.Log) (*TokenPoolRemotePoolAdded, error) - - FilterRemotePoolRemoved(opts *bind.FilterOpts, remoteChainSelector []uint64) (*TokenPoolRemotePoolRemovedIterator, error) + FilterRemotePoolSet(opts *bind.FilterOpts, remoteChainSelector []uint64) (*TokenPoolRemotePoolSetIterator, error) - WatchRemotePoolRemoved(opts *bind.WatchOpts, sink chan<- *TokenPoolRemotePoolRemoved, remoteChainSelector []uint64) (event.Subscription, error) + WatchRemotePoolSet(opts *bind.WatchOpts, sink chan<- *TokenPoolRemotePoolSet, remoteChainSelector []uint64) (event.Subscription, error) - ParseRemotePoolRemoved(log types.Log) (*TokenPoolRemotePoolRemoved, error) + ParseRemotePoolSet(log types.Log) (*TokenPoolRemotePoolSet, error) FilterRouterUpdated(opts *bind.FilterOpts) (*TokenPoolRouterUpdatedIterator, error) diff --git a/core/gethwrappers/ccip/generated/usdc_reader_tester/usdc_reader_tester.go b/core/gethwrappers/ccip/generated/usdc_reader_tester/usdc_reader_tester.go index 99aaf3eb373..f9bd3b56efa 100644 --- a/core/gethwrappers/ccip/generated/usdc_reader_tester/usdc_reader_tester.go +++ b/core/gethwrappers/ccip/generated/usdc_reader_tester/usdc_reader_tester.go @@ -32,7 +32,7 @@ var ( var USDCReaderTesterMetaData = &bind.MetaData{ ABI: "[{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"name\":\"MessageSent\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"version\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"sourceDomain\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destinationDomain\",\"type\":\"uint32\"},{\"internalType\":\"bytes32\",\"name\":\"recipient\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"destinationCaller\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"sender\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"messageBody\",\"type\":\"bytes\"}],\"name\":\"emitMessageSent\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", - Bin: "0x6080806040523460155761034b908161001b8239f35b600080fdfe608080604052600436101561001357600080fd5b60003560e01c6362826f181461002857600080fd5b346102a6576101007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102a65760043563ffffffff811681036102a65760243563ffffffff811681036102a6576044359063ffffffff821682036102a65760c4359367ffffffffffffffff851685036102a65760e4359067ffffffffffffffff82116102a657366023830112156102a65781600401359567ffffffffffffffff87116102a65736602488850101116102a657600087601f8299017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200161011490856102ab565b8084528060208501956024018637830160200152604051948594602086019760e01b7fffffffff0000000000000000000000000000000000000000000000000000000016885260e01b7fffffffff0000000000000000000000000000000000000000000000000000000016602486015260e01b7fffffffff0000000000000000000000000000000000000000000000000000000016602885015260c01b7fffffffffffffffff00000000000000000000000000000000000000000000000016602c84015260a435603484015260643560548401526084356074840152519081609484016102009261031b565b8101036094017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08101825261023590826102ab565b60405191829160208352519081602084015281604084016102559261031b565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168101036040017f8c5261668696ce22758910d05bab8f186d6eb247ceac2af2e82c7dc17669b03691a180f35b600080fd5b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff8211176102ec57604052565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60005b83811061032e5750506000910152565b818101518382015260200161031e56fea164736f6c634300081a000a", + Bin: "0x608060405234801561001057600080fd5b5061032c806100206000396000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c806362826f1814610030575b600080fd5b61004361003e366004610129565b610045565b005b600061008d8a8a8a87898c8c8a8a8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506100d292505050565b90507f8c5261668696ce22758910d05bab8f186d6eb247ceac2af2e82c7dc17669b036816040516100be9190610228565b60405180910390a150505050505050505050565b606088888888888888886040516020016100f3989796959493929190610279565b604051602081830303815290604052905098975050505050505050565b803563ffffffff8116811461012457600080fd5b919050565b60008060008060008060008060006101008a8c03121561014857600080fd5b6101518a610110565b985061015f60208b01610110565b975061016d60408b01610110565b965060608a0135955060808a0135945060a08a0135935060c08a013567ffffffffffffffff80821682146101a057600080fd5b90935060e08b013590808211156101b657600080fd5b818c0191508c601f8301126101ca57600080fd5b8135818111156101d957600080fd5b8d60208285010111156101eb57600080fd5b6020830194508093505050509295985092959850929598565b60005b8381101561021f578181015183820152602001610207565b50506000910152565b6020815260008251806020840152610247816040850160208701610204565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169190910160400192915050565b60007fffffffff00000000000000000000000000000000000000000000000000000000808b60e01b168352808a60e01b166004840152808960e01b166008840152507fffffffffffffffff0000000000000000000000000000000000000000000000008760c01b16600c830152856014830152846034830152836054830152825161030b816074850160208701610204565b91909101607401999850505050505050505056fea164736f6c6343000818000a", } var USDCReaderTesterABI = USDCReaderTesterMetaData.ABI diff --git a/core/gethwrappers/ccip/generated/usdc_token_pool/usdc_token_pool.go b/core/gethwrappers/ccip/generated/usdc_token_pool/usdc_token_pool.go index 3bf933b8a20..1d6b173b628 100644 --- a/core/gethwrappers/ccip/generated/usdc_token_pool/usdc_token_pool.go +++ b/core/gethwrappers/ccip/generated/usdc_token_pool/usdc_token_pool.go @@ -74,7 +74,8 @@ type RateLimiterTokenBucket struct { type TokenPoolChainUpdate struct { RemoteChainSelector uint64 - RemotePoolAddresses [][]byte + Allowed bool + RemotePoolAddress []byte RemoteTokenAddress []byte OutboundRateLimiterConfig RateLimiterConfig InboundRateLimiterConfig RateLimiterConfig @@ -94,8 +95,8 @@ type USDCTokenPoolDomainUpdate struct { } var USDCTokenPoolMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[{\"internalType\":\"contractITokenMessenger\",\"name\":\"tokenMessenger\",\"type\":\"address\"},{\"internalType\":\"contractIERC20\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"address[]\",\"name\":\"allowlist\",\"type\":\"address[]\"},{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"capacity\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"requested\",\"type\":\"uint256\"}],\"name\":\"AggregateValueMaxCapacityExceeded\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"minWaitInSeconds\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"available\",\"type\":\"uint256\"}],\"name\":\"AggregateValueRateLimitReached\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"AllowListNotEnabled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"BucketOverfilled\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"CallerIsNotARampOnRouter\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CannotTransferToSelf\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"}],\"name\":\"ChainAlreadyExists\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"ChainNotAllowed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CursedByRMN\",\"type\":\"error\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"config\",\"type\":\"tuple\"}],\"name\":\"DisabledNonZeroRateLimit\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidConfig\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"expected\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"actual\",\"type\":\"uint8\"}],\"name\":\"InvalidDecimalArgs\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"expected\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"got\",\"type\":\"uint32\"}],\"name\":\"InvalidDestinationDomain\",\"type\":\"error\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"allowedCaller\",\"type\":\"bytes32\"},{\"internalType\":\"uint32\",\"name\":\"domainIdentifier\",\"type\":\"uint32\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"enabled\",\"type\":\"bool\"}],\"internalType\":\"structUSDCTokenPool.DomainUpdate\",\"name\":\"domain\",\"type\":\"tuple\"}],\"name\":\"InvalidDomain\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"version\",\"type\":\"uint32\"}],\"name\":\"InvalidMessageVersion\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"expected\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"got\",\"type\":\"uint64\"}],\"name\":\"InvalidNonce\",\"type\":\"error\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"rateLimiterConfig\",\"type\":\"tuple\"}],\"name\":\"InvalidRateLimitRate\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"}],\"name\":\"InvalidReceiver\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolData\",\"type\":\"bytes\"}],\"name\":\"InvalidRemoteChainDecimals\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"InvalidRemotePoolForChain\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"expected\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"got\",\"type\":\"uint32\"}],\"name\":\"InvalidSourceDomain\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"}],\"name\":\"InvalidSourcePoolAddress\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"InvalidToken\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"version\",\"type\":\"uint32\"}],\"name\":\"InvalidTokenMessengerVersion\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MismatchedArrayLengths\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MustBeProposedOwner\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"NonExistentChain\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByOwner\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"remoteDecimals\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"localDecimals\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"remoteAmount\",\"type\":\"uint256\"}],\"name\":\"OverflowDetected\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OwnerCannotBeZero\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"PoolAlreadyAdded\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RateLimitMustBeDisabled\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"SenderNotAllowed\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"capacity\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"requested\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenAddress\",\"type\":\"address\"}],\"name\":\"TokenMaxCapacityExceeded\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"minWaitInSeconds\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"available\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenAddress\",\"type\":\"address\"}],\"name\":\"TokenRateLimitReached\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"Unauthorized\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"domain\",\"type\":\"uint64\"}],\"name\":\"UnknownDomain\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnlockingUSDCFailed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"AllowListAdd\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"AllowListRemove\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Burned\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"remoteToken\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundRateLimiterConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundRateLimiterConfig\",\"type\":\"tuple\"}],\"name\":\"ChainAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundRateLimiterConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundRateLimiterConfig\",\"type\":\"tuple\"}],\"name\":\"ChainConfigured\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"ChainRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"config\",\"type\":\"tuple\"}],\"name\":\"ConfigChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"tokenMessenger\",\"type\":\"address\"}],\"name\":\"ConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"allowedCaller\",\"type\":\"bytes32\"},{\"internalType\":\"uint32\",\"name\":\"domainIdentifier\",\"type\":\"uint32\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"enabled\",\"type\":\"bool\"}],\"indexed\":false,\"internalType\":\"structUSDCTokenPool.DomainUpdate[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"name\":\"DomainsSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Locked\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Minted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"rateLimitAdmin\",\"type\":\"address\"}],\"name\":\"RateLimitAdminSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Released\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"RemotePoolAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"RemotePoolRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"oldRouter\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newRouter\",\"type\":\"address\"}],\"name\":\"RouterUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokens\",\"type\":\"uint256\"}],\"name\":\"TokensConsumed\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"SUPPORTED_USDC_VERSION\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"addRemotePool\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"removes\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"adds\",\"type\":\"address[]\"}],\"name\":\"applyAllowListUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64[]\",\"name\":\"remoteChainSelectorsToRemove\",\"type\":\"uint64[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes[]\",\"name\":\"remotePoolAddresses\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes\",\"name\":\"remoteTokenAddress\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundRateLimiterConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundRateLimiterConfig\",\"type\":\"tuple\"}],\"internalType\":\"structTokenPool.ChainUpdate[]\",\"name\":\"chainsToAdd\",\"type\":\"tuple[]\"}],\"name\":\"applyChainUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAllowList\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAllowListEnabled\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getCurrentInboundRateLimiterState\",\"outputs\":[{\"components\":[{\"internalType\":\"uint128\",\"name\":\"tokens\",\"type\":\"uint128\"},{\"internalType\":\"uint32\",\"name\":\"lastUpdated\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.TokenBucket\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getCurrentOutboundRateLimiterState\",\"outputs\":[{\"components\":[{\"internalType\":\"uint128\",\"name\":\"tokens\",\"type\":\"uint128\"},{\"internalType\":\"uint32\",\"name\":\"lastUpdated\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.TokenBucket\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"}],\"name\":\"getDomain\",\"outputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"allowedCaller\",\"type\":\"bytes32\"},{\"internalType\":\"uint32\",\"name\":\"domainIdentifier\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"enabled\",\"type\":\"bool\"}],\"internalType\":\"structUSDCTokenPool.Domain\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRateLimitAdmin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getRemotePools\",\"outputs\":[{\"internalType\":\"bytes[]\",\"name\":\"\",\"type\":\"bytes[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getRemoteToken\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRmnProxy\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRouter\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getSupportedChains\",\"outputs\":[{\"internalType\":\"uint64[]\",\"name\":\"\",\"type\":\"uint64[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getToken\",\"outputs\":[{\"internalType\":\"contractIERC20\",\"name\":\"token\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getTokenDecimals\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"decimals\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"i_localDomainIdentifier\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"i_messageTransmitter\",\"outputs\":[{\"internalType\":\"contractIMessageTransmitter\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"i_tokenMessenger\",\"outputs\":[{\"internalType\":\"contractITokenMessenger\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"isRemotePool\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"isSupportedChain\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"isSupportedToken\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"originalSender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"localToken\",\"type\":\"address\"}],\"internalType\":\"structPool.LockOrBurnInV1\",\"name\":\"lockOrBurnIn\",\"type\":\"tuple\"}],\"name\":\"lockOrBurn\",\"outputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"destPoolData\",\"type\":\"bytes\"}],\"internalType\":\"structPool.LockOrBurnOutV1\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"originalSender\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"localToken\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"sourcePoolData\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"offchainTokenData\",\"type\":\"bytes\"}],\"internalType\":\"structPool.ReleaseOrMintInV1\",\"name\":\"releaseOrMintIn\",\"type\":\"tuple\"}],\"name\":\"releaseOrMint\",\"outputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"destinationAmount\",\"type\":\"uint256\"}],\"internalType\":\"structPool.ReleaseOrMintOutV1\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"removeRemotePool\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundConfig\",\"type\":\"tuple\"}],\"name\":\"setChainRateLimiterConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64[]\",\"name\":\"remoteChainSelectors\",\"type\":\"uint64[]\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config[]\",\"name\":\"outboundConfigs\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config[]\",\"name\":\"inboundConfigs\",\"type\":\"tuple[]\"}],\"name\":\"setChainRateLimiterConfigs\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"allowedCaller\",\"type\":\"bytes32\"},{\"internalType\":\"uint32\",\"name\":\"domainIdentifier\",\"type\":\"uint32\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"enabled\",\"type\":\"bool\"}],\"internalType\":\"structUSDCTokenPool.DomainUpdate[]\",\"name\":\"domains\",\"type\":\"tuple[]\"}],\"name\":\"setDomains\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"rateLimitAdmin\",\"type\":\"address\"}],\"name\":\"setRateLimitAdmin\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newRouter\",\"type\":\"address\"}],\"name\":\"setRouter\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", - Bin: "0x610160806040523461049b5761582d803803809161001d82856107dc565b8339810160a08282031261049b5781516001600160a01b0381169290919083830361049b5760208101516001600160a01b038116919082810361049b5760408201516001600160401b03811161049b5782019380601f8601121561049b578451946001600160401b0386116104a0578560051b9060208201966100a360405198896107dc565b875260208088019282010192831161049b57602001905b8282106107c4575050506100dc60806100d5606085016107ff565b93016107ff565b9233156107b357600180546001600160a01b03191633179055801580156107a2575b8015610791575b6107805760049260209260805260c0526040519283809263313ce56760e01b82525afa809160009161073d575b5090610719575b50600660a052600480546001600160a01b0319166001600160a01b03929092169190911790558051151560e08190526105f7575b5081156105e657604051632c12192160e01b8152602081600481865afa90811561050b576000916105ac575b5060405163054fd4d560e41b81526001600160a01b03919091169190602081600481865afa801561050b5763ffffffff9160009161058d575b5016806105795750604051639cdbb18160e01b8152602081600481875afa801561050b5763ffffffff9160009161055a575b50168061054657506004916020916101005280610120526040519283809263234d8e3d60e21b82525afa90811561050b57600091610517575b506101405260805161010051604051636eb1769f60e11b81523060048201526001600160a01b0391821660248201819052939290911690602081604481855afa90811561050b576000916104d9575b5060001981018091116104c35760405190602082019463095ea7b360e01b865260248301526044820152604481526102c56064826107dc565b6000806040958651936102d888866107dc565b602085527f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65646020860152519082865af13d156104b6573d906001600160401b0382116104a057855161034994909261033a601f8201601f1916602001856107dc565b83523d6000602085013e6109b9565b80518061041f575b837f2e902d38f15b233cbb63711add0fca4545334d3a169d60c0a616494d7eea95446020858351908152a151614da39081610a8a82396080518181816105fa0152818161069401528181611422015281816140080152614485015260a051816106fc015260c051818181612067015281816136710152613bb4015260e051818181610acd0152818161218d01526142de015261010051818181610ceb015261148501526101205181818161083c0152612710015261014051818181610dcd0152818161152e01526138140152f35b816020918101031261049b576020015180159081150361049b57610444573880610351565b815162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608490fd5b600080fd5b634e487b7160e01b600052604160045260246000fd5b91610349926060916109b9565b634e487b7160e01b600052601160045260246000fd5b90506020813d602011610503575b816104f4602093836107dc565b8101031261049b57513861028c565b3d91506104e7565b6040513d6000823e3d90fd5b610539915060203d60201161053f575b61053181836107dc565b810190610813565b3861023d565b503d610527565b6316ba39c560e31b60005260045260246000fd5b610573915060203d60201161053f5761053181836107dc565b38610204565b6334697c6b60e11b60005260045260246000fd5b6105a6915060203d60201161053f5761053181836107dc565b386101d2565b90506020813d6020116105de575b816105c7602093836107dc565b8101031261049b576105d8906107ff565b38610199565b3d91506105ba565b6306b7c75960e31b60005260046000fd5b906020906040519061060983836107dc565b60008252600036813760e051156107085760005b8251811015610684576001906001600160a01b0361063b828661082f565b51168561064782610871565b610654575b50500161061d565b7f800671136ab6cfee9fbe5ed1fb7ca417811aca3cf864800d127b927adedf756691604051908152a1388561064c565b5092905060005b81518110156106ff576001906001600160a01b036106a9828561082f565b511680156106f957846106bb82610959565b6106c9575b50505b0161068b565b7f2640d4d76caf8bf478aabfa982fa4e1c4eb71a37f93cd15e80dbc657911546d891604051908152a138846106c0565b506106c3565b5050503861016d565b6335f4a7b360e01b60005260046000fd5b60ff1660068114610139576332ad3e0760e11b600052600660045260245260446000fd5b6020813d602011610778575b81610756602093836107dc565b8101031261077457519060ff82168203610771575038610132565b80fd5b5080fd5b3d9150610749565b6342bcdf7f60e11b60005260046000fd5b506001600160a01b03831615610105565b506001600160a01b038416156100fe565b639b15e16f60e01b60005260046000fd5b602080916107d1846107ff565b8152019101906100ba565b601f909101601f19168101906001600160401b038211908210176104a057604052565b51906001600160a01b038216820361049b57565b9081602091031261049b575163ffffffff8116810361049b5790565b80518210156108435760209160051b010190565b634e487b7160e01b600052603260045260246000fd5b80548210156108435760005260206000200190600090565b60008181526003602052604090205480156109525760001981018181116104c3576002546000198101919082116104c357818103610901575b50505060025480156108eb57600019016108c5816002610859565b8154906000199060031b1b19169055600255600052600360205260006040812055600190565b634e487b7160e01b600052603160045260246000fd5b61093a610912610923936002610859565b90549060031b1c9283926002610859565b819391549060031b91821b91600019901b19161790565b905560005260036020526040600020553880806108aa565b5050600090565b806000526003602052604060002054156000146109b357600254680100000000000000008110156104a05761099a6109238260018594016002556002610859565b9055600254906000526003602052604060002055600190565b50600090565b91929015610a1b57508151156109cd575090565b3b156109d65790565b60405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606490fd5b825190915015610a2e5750805190602001fd5b6040519062461bcd60e51b8252602060048301528181519182602483015260005b838110610a715750508160006044809484010152601f80199101168101030190fd5b60208282018101516044878401015285935001610a4f56fe6080604052600436101561001257600080fd5b60003560e01c806241d3c11461025657806301ffc9a714610251578063181f5a771461024c57806321df0da714610247578063240028e81461024257806324f65ee71461023d57806339077537146102385780634c5ef0ed1461023357806354c8a4f31461022e5780636155cda01461022957806362ddd3c4146102245780636b716b0d1461021f5780636d3d1a581461021a57806379ba5097146102155780637d54534e146102105780638926f54f1461020b5780638da5cb5b14610206578063962d4020146102015780639a4575b9146101fc5780639fdf13ff146101f7578063a42a7b8b146101f2578063a7cd63b7146101ed578063acfecf91146101e8578063af58d59f146101e3578063b0f479a1146101de578063b7946580146101d9578063c0d78655146101d4578063c4bffe2b146101cf578063c75eea9c146101ca578063cf7401f3146101c5578063dc0bd971146101c0578063dfadfa35146101bb578063e0351e13146101b6578063e8a1da17146101b1578063f2fde38b146101ac5763fbf84dd7146101a757600080fd5b6126c5565b6125d1565b6121b2565b612157565b61208b565b61201c565b611f00565b611d9d565b611cec565b611bac565b611b57565b611af4565b611a2a565b6118fe565b61186c565b61174c565b611694565b6112ce565b6110bb565b611038565b610fdb565b610f2c565b610e43565b610df1565b610d92565b610d0f565b610ca0565b610a9b565b6109e1565b610720565b6106c4565b61063c565b6105af565b61052e565b6102d8565b346102d35760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102d35760043567ffffffffffffffff81116102d357366023820112156102d357806004013567ffffffffffffffff81116102d3573660248260071b840101116102d35760246102d19201612734565b005b600080fd5b346102d35760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102d3576004357fffffffff0000000000000000000000000000000000000000000000000000000081168091036102d357807faff2afbf000000000000000000000000000000000000000000000000000000006020921490811561039e575b8115610374575b506040519015158152f35b7f01ffc9a70000000000000000000000000000000000000000000000000000000091501438610369565b7f0e64dd290000000000000000000000000000000000000000000000000000000081149150610362565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6060810190811067ffffffffffffffff82111761041357604052565b6103c8565b6040810190811067ffffffffffffffff82111761041357604052565b60a0810190811067ffffffffffffffff82111761041357604052565b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff82111761041357604052565b604051906104a0602083610450565b565b604051906104a0604083610450565b604051906104a060a083610450565b604051906104a0606083610450565b919082519283825260005b8481106105195750507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8460006020809697860101520116010190565b806020809284010151828286010152016104da565b346102d35760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102d3576105ab604080519061056f8183610450565b601382527f55534443546f6b656e506f6f6c20312e352e31000000000000000000000000006020830152519182916020835260208301906104cf565b0390f35b346102d35760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102d357602060405173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b73ffffffffffffffffffffffffffffffffffffffff8116036102d357565b346102d35760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102d35760206106ba60043561067c8161061e565b73ffffffffffffffffffffffffffffffffffffffff807f00000000000000000000000000000000000000000000000000000000000000001691161490565b6040519015158152f35b346102d35760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102d357602060405160ff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b346102d35760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102d35760043567ffffffffffffffff81116102d357806004016101007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc83360301126102d3576020610821916107a0612a20565b506107aa816135a3565b6107e66107de6107d66107cb6107c360c4890186612a44565b810190612a95565b9360e4880190612a44565b810190612b4d565b9182516137c9565b8181519101519060405193849283927f57ecfd2800000000000000000000000000000000000000000000000000000000845260048401612bd3565b0381600073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000165af190811561094457600091610915575b50156108eb5780606461088560446105ab9401612c04565b60405191909201358082529173ffffffffffffffffffffffffffffffffffffffff169033907f9d228d69b5fdb8d273a2336f8fb8612d039631024ea9bf09c424a9503aa078f090602090a36108d8610491565b8190526040519081529081906020820190565b7fbf969f220000000000000000000000000000000000000000000000000000000060005260046000fd5b610937915060203d60201161093d575b61092f8183610450565b810190612bbe565b3861086d565b503d610925565b612bf8565b67ffffffffffffffff8116036102d357565b35906104a082610949565b60407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc8201126102d35760043561099c81610949565b9160243567ffffffffffffffff81116102d357826023820112156102d35780600401359267ffffffffffffffff84116102d357602484830101116102d3576024019190565b346102d35760206106ba6109f436610966565b91612c0e565b9181601f840112156102d35782359167ffffffffffffffff83116102d3576020808501948460051b0101116102d357565b60407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc8201126102d35760043567ffffffffffffffff81116102d35781610a74916004016109fa565b929092916024359067ffffffffffffffff82116102d357610a97916004016109fa565b9091565b346102d357610ac3610acb610aaf36610a2b565b9491610abc939193613558565b3691612c6e565b923691612c6e565b7f000000000000000000000000000000000000000000000000000000000000000015610c765760005b8251811015610bb95780610b27610b0d60019386612dce565b5173ffffffffffffffffffffffffffffffffffffffff1690565b610b63610b5e73ffffffffffffffffffffffffffffffffffffffff83165b73ffffffffffffffffffffffffffffffffffffffff1690565b614637565b610b6f575b5001610af4565b60405173ffffffffffffffffffffffffffffffffffffffff9190911681527f800671136ab6cfee9fbe5ed1fb7ca417811aca3cf864800d127b927adedf756690602090a138610b68565b5060005b81518110156102d15780610bd6610b0d60019385612dce565b73ffffffffffffffffffffffffffffffffffffffff811615610c7057610c19610c1473ffffffffffffffffffffffffffffffffffffffff8316610b45565b6148ed565b610c26575b505b01610bbd565b60405173ffffffffffffffffffffffffffffffffffffffff9190911681527f2640d4d76caf8bf478aabfa982fa4e1c4eb71a37f93cd15e80dbc657911546d890602090a183610c1e565b50610c20565b7f35f4a7b30000000000000000000000000000000000000000000000000000000060005260046000fd5b346102d35760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102d357602060405173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b346102d357610d1d36610966565b610d28929192613558565b67ffffffffffffffff8216610d4a816000526006602052604060002054151590565b15610d6557506102d192610d5f913691612acd565b90613975565b7f1e670e4b0000000000000000000000000000000000000000000000000000000060005260045260246000fd5b346102d35760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102d357602060405163ffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b346102d35760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102d357602073ffffffffffffffffffffffffffffffffffffffff60095416604051908152f35b346102d35760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102d35760005473ffffffffffffffffffffffffffffffffffffffff81163303610f02577fffffffffffffffffffffffff00000000000000000000000000000000000000006001549133828416176001551660005573ffffffffffffffffffffffffffffffffffffffff3391167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0600080a3005b7f02b543c60000000000000000000000000000000000000000000000000000000060005260046000fd5b346102d35760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102d3577f44676b5284b809a22248eba0da87391d79098be38bb03154be88a58bf4d09174602073ffffffffffffffffffffffffffffffffffffffff600435610f9f8161061e565b610fa7613558565b16807fffffffffffffffffffffffff00000000000000000000000000000000000000006009541617600955604051908152a1005b346102d35760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102d35760206106ba67ffffffffffffffff60043561102481610949565b166000526006602052604060002054151590565b346102d35760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102d357602073ffffffffffffffffffffffffffffffffffffffff60015416604051908152f35b9181601f840112156102d35782359167ffffffffffffffff83116102d357602080850194606085020101116102d357565b346102d35760607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102d35760043567ffffffffffffffff81116102d35761110a9036906004016109fa565b9060243567ffffffffffffffff81116102d35761112b90369060040161108a565b9060443567ffffffffffffffff81116102d35761114c90369060040161108a565b61116e610b4560095473ffffffffffffffffffffffffffffffffffffffff1690565b3314158061124d575b61121b57838614801590611211575b6111e75760005b86811061119657005b806111e16111af6111aa6001948b8b612ce5565b612cf5565b6111ba838989612cff565b6111db6111d36111cb86898b612cff565b923690611eb7565b913690611eb7565b91613a3a565b0161118d565b7f568efce20000000000000000000000000000000000000000000000000000000060005260046000fd5b5080861415611186565b7f8e4a23d6000000000000000000000000000000000000000000000000000000006000523360045260246000fd5b6000fd5b50611270610b4560015473ffffffffffffffffffffffffffffffffffffffff1690565b331415611177565b906112cb91602081526020611298835160408385015260608401906104cf565b9201519060407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0828503019101526104cf565b90565b346102d35760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102d35760043567ffffffffffffffff81116102d3578060040160a07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc83360301126102d357611347612d0f565b5061135181613b6a565b6024820161138361137e61136483612cf5565b67ffffffffffffffff16600052600a602052604060002090565b612d28565b916113986113946040850151151590565b1590565b6116525760206113a88280612a44565b90500361160e5760646113c86113c083602094612a44565b810190612daa565b940135926113dc8282015163ffffffff1690565b90516040517ff856ddb60000000000000000000000000000000000000000000000000000000081526004810186905263ffffffff909216602483015260448201959095527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1660648201526084810194909452838060a481010381600073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000165af1918215610944576105ab936000936115cb575b5061150b611506611583936115af937f696de425f79f4a40bc6d2122ca50507f0efbeabbff86a84871b7196ab8ea8df7604051806114fe3394829190602083019252565b0390a2612cf5565b612f9b565b926115276115176104a2565b67ffffffffffffffff9092168252565b63ffffffff7f000000000000000000000000000000000000000000000000000000000000000016602082015260405192839160208301919091602063ffffffff81604084019567ffffffffffffffff8151168552015116910152565b037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08101835282610450565b6115b76104a2565b918252602082015260405191829182611278565b6115af919350611506611583936115fc61150b9360203d602011611607575b6115f48183610450565b810190612db9565b9593509350506114ba565b503d6115ea565b8061161891612a44565b9061164e6040519283927fa3c8cf0900000000000000000000000000000000000000000000000000000000845260048401612d99565b0390fd5b61124961165e83612cf5565b7fd201c48a0000000000000000000000000000000000000000000000000000000060005267ffffffffffffffff16600452602490565b346102d35760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102d357602060405160008152f35b602081016020825282518091526040820191602060408360051b8301019401926000915b83831061170157505050505090565b909192939460208061173d837fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0866001960301875289516104cf565b970193019301919392906116f2565b346102d35760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102d35767ffffffffffffffff60043561179081610949565b1660005260076020526117a96005604060002001614541565b8051907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe06117ef6117d984612c56565b936117e76040519586610450565b808552612c56565b0160005b81811061185b57505060005b815181101561184d578061183161182c61181b60019486612dce565b516000526008602052604060002090565b612e35565b61183b8286612dce565b526118468185612dce565b50016117ff565b604051806105ab85826116ce565b8060606020809387010152016117f3565b346102d35760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102d3576118a36144ab565b60405180916020820160208352815180915260206040840192019060005b8181106118cf575050500390f35b825173ffffffffffffffffffffffffffffffffffffffff168452859450602093840193909201916001016118c1565b346102d35761190c36610966565b611917929192613558565b67ffffffffffffffff82169161193d611394846000526006602052604060002054151590565b6119f35761198061139460056119678467ffffffffffffffff166000526007602052604060002090565b01611973368689612acd565b60208151910120906147e2565b6119bc57507f52d00ee4d9bd51b40168f2afc5848837288ce258784ad914278791464b3f4d7691926119b760405192839283612d99565b0390a2005b61164e84926040519384937f74f23c7c00000000000000000000000000000000000000000000000000000000855260048501612ef5565b7f1e670e4b0000000000000000000000000000000000000000000000000000000060005267ffffffffffffffff1660045260246000fd5b346102d35760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102d35767ffffffffffffffff600435611a6e81610949565b611a76612f16565b501660005260076020526105ab611a9b611a966002604060002001612f41565b613c7a565b6040519182918291909160806fffffffffffffffffffffffffffffffff8160a084019582815116855263ffffffff6020820151166020860152604081015115156040860152826060820151166060860152015116910152565b346102d35760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102d357602073ffffffffffffffffffffffffffffffffffffffff60045416604051908152f35b9060206112cb9281815201906104cf565b346102d35760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102d3576105ab611b9860043561150681610949565b6040519182916020835260208301906104cf565b346102d35760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102d35773ffffffffffffffffffffffffffffffffffffffff600435611bfc8161061e565b611c04613558565b168015611c7e5760407f02dc5c233404867c793b749c6d644beb2277536d18a7e7974d3f238e4c6f16849160045490807fffffffffffffffffffffffff000000000000000000000000000000000000000083161760045573ffffffffffffffffffffffffffffffffffffffff8351921682526020820152a1005b7f8579befe0000000000000000000000000000000000000000000000000000000060005260046000fd5b602060408183019282815284518094520192019060005b818110611ccc5750505090565b825167ffffffffffffffff16845260209384019390920191600101611cbf565b346102d35760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102d357611d236144f6565b8051907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0611d536117d984612c56565b0136602084013760005b8151811015611d8f578067ffffffffffffffff611d7c60019385612dce565b5116611d888286612dce565b5201611d5d565b604051806105ab8582611ca8565b346102d35760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102d35767ffffffffffffffff600435611de181610949565b611de9612f16565b501660005260076020526105ab611a9b611a966040600020612f41565b801515036102d357565b35906fffffffffffffffffffffffffffffffff821682036102d357565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7c60609101126102d35760405190611e64826103f7565b81608435611e7181611e06565b815260a4356fffffffffffffffffffffffffffffffff811681036102d357602082015260c435906fffffffffffffffffffffffffffffffff821682036102d35760400152565b91908260609103126102d357604051611ecf816103f7565b6040611efb8183958035611ee281611e06565b8552611ef060208201611e10565b602086015201611e10565b910152565b346102d35760e07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102d357600435611f3b81610949565b60607fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdc3601126102d357604051611f71816103f7565b602435611f7d81611e06565b81526044356fffffffffffffffffffffffffffffffff811681036102d35760208201526064356fffffffffffffffffffffffffffffffff811681036102d3576040820152611fca36611e2d565b9073ffffffffffffffffffffffffffffffffffffffff6009541633141580611ffa575b61121b576102d192613a3a565b5073ffffffffffffffffffffffffffffffffffffffff60015416331415611fed565b346102d35760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102d357602060405173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b346102d35760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102d35767ffffffffffffffff6004356120cf81610949565b6000604080516120de816103f7565b828152826020820152015216600052600a6020526105ab604060002060ff60016040519261210b846103f7565b80548452015463ffffffff8116602084015260201c16151560408201526040519182918291909160408060608301948051845263ffffffff602082015116602085015201511515910152565b346102d35760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102d35760206040517f000000000000000000000000000000000000000000000000000000000000000015158152f35b346102d3576121c036610a2b565b9190926121cb613558565b6000915b80831061247d5750505060009163ffffffff4216925b8281106121ee57005b6122016121fc82858561313a565b6131f9565b90606082016122108151613d57565b608083019361221f8551613d57565b604084019081515115611c7e57612259611394612254612247885167ffffffffffffffff1690565b67ffffffffffffffff1690565b61497e565b61243257612392612292612278879a999a5167ffffffffffffffff1690565b67ffffffffffffffff166000526007602052604060002090565b6123558961234f87516123366122bb60408301516fffffffffffffffffffffffffffffffff1690565b9161231d6122e66122df60208401516fffffffffffffffffffffffffffffffff1690565b9251151590565b6123146122f16104b1565b6fffffffffffffffffffffffffffffffff851681529763ffffffff166020890152565b15156040870152565b6fffffffffffffffffffffffffffffffff166060850152565b6fffffffffffffffffffffffffffffffff166080830152565b82613290565b6123878961237e8a516123366122bb60408301516fffffffffffffffffffffffffffffffff1690565b60028301613290565b60048451910161339c565b602085019660005b885180518210156123d557906123cf6001926123c8836123c28c5167ffffffffffffffff1690565b92612dce565b5190613975565b0161239a565b505097965094906124297f8d340f17e19058004c20453540862a9c62778504476f6756755cb33bcd6c38c293926124166001975167ffffffffffffffff1690565b92519351905190604051948594856134c3565b0390a1016121e5565b611249612447865167ffffffffffffffff1690565b7f1d5ad3c50000000000000000000000000000000000000000000000000000000060005267ffffffffffffffff16600452602490565b90919261248e6111aa858486612ce5565b946124a561139467ffffffffffffffff881661471b565b612599576124d260056124cc8867ffffffffffffffff166000526007602052604060002090565b01614541565b9360005b855181101561251e5760019061251760056125058b67ffffffffffffffff166000526007602052604060002090565b01612510838a612dce565b51906147e2565b50016124d6565b509350937f5204aec90a3c794d8e90fded8b46ae9c7c552803e7e832e0c1d358396d85991661258b6001939761257061256b8267ffffffffffffffff166000526007602052604060002090565b61308b565b60405167ffffffffffffffff90911681529081906020820190565b0390a10191909392936121cf565b7f1e670e4b0000000000000000000000000000000000000000000000000000000060005267ffffffffffffffff861660045260246000fd5b346102d35760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102d35773ffffffffffffffffffffffffffffffffffffffff6004356126218161061e565b612629613558565b1633811461269b57807fffffffffffffffffffffffff0000000000000000000000000000000000000000600054161760005573ffffffffffffffffffffffffffffffffffffffff600154167fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae1278600080a3005b7fdad89dca0000000000000000000000000000000000000000000000000000000060005260046000fd5b346102d35760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102d357602060405173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b61273c613558565b60005b82811061277e5750907f1889010d2535a0ab1643678d1da87fbbe8b87b2f585b47ddb72ec622aef9ee5691612779604051928392836129a1565b0390a1565b61279161278c828585612914565b61293a565b80511580156128bf575b61285c57906128568261280661136460406127bf6020600198015163ffffffff1690565b936127f78151956127ef6127d66060850151151590565b916127df6104c0565b98895263ffffffff166020890152565b151586840152565b015167ffffffffffffffff1690565b60019082518155019063ffffffff6020820151167fffffffffffffffffffffffffffffffffffffffffffffffffffffff000000000064ff0000000060408554940151151560201b16921617179055565b0161273f565b604080517fa087bd2900000000000000000000000000000000000000000000000000000000815282516004820152602083015163ffffffff1660248201529082015167ffffffffffffffff16604482015260609091015115156064820152608490fd5b5067ffffffffffffffff6128de604083015167ffffffffffffffff1690565b161561279b565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b91908110156129245760071b0190565b6128e5565b359063ffffffff821682036102d357565b6080813603126102d35760405190608082019082821067ffffffffffffffff831117610413576060916040528035835261297660208201612929565b6020840152604081013561298981610949565b6040840152013561299981611e06565b606082015290565b602080825281018390526040019160005b8181106129bf5750505090565b9091926080806001928635815263ffffffff6129dd60208901612929565b16602082015267ffffffffffffffff60408801356129fa81610949565b1660408201526060870135612a0e81611e06565b151560608201520194019291016129b2565b604051906020820182811067ffffffffffffffff8211176104135760405260008252565b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1813603018212156102d3570180359067ffffffffffffffff82116102d3576020019181360383136102d357565b908160409103126102d357612ac5602060405192612ab284610418565b8035612abd81610949565b845201612929565b602082015290565b92919267ffffffffffffffff82116104135760405191612b15601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200184610450565b8294818452818301116102d3578281602093846000960137010152565b9080601f830112156102d3578160206112cb93359101612acd565b6020818303126102d35780359067ffffffffffffffff82116102d357016040818303126102d35760405191612b8183610418565b813567ffffffffffffffff81116102d35781612b9e918401612b32565b8352602082013567ffffffffffffffff81116102d357612ac59201612b32565b908160209103126102d357516112cb81611e06565b9091612bea6112cb936040845260408401906104cf565b9160208184039101526104cf565b6040513d6000823e3d90fd5b356112cb8161061e565b6112cb929167ffffffffffffffff612c39921660005260076020526005604060002001923691612acd565b602081519101209060019160005201602052604060002054151590565b67ffffffffffffffff81116104135760051b60200190565b929190612c7a81612c56565b93612c886040519586610450565b602085838152019160051b81019283116102d357905b828210612caa57505050565b602080918335612cb98161061e565b815201910190612c9e565b67ffffffffffffffff6112cb91166000526006602052604060002054151590565b91908110156129245760051b0190565b356112cb81610949565b9190811015612924576060020190565b60405190612d1c82610418565b60606020838281520152565b90604051612d35816103f7565b604060ff6001839580548552015463ffffffff8116602085015260201c161515910152565b601f82602094937fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0938186528686013760008582860101520116010190565b9160206112cb938181520191612d5a565b908160209103126102d3573590565b908160209103126102d357516112cb81610949565b80518210156129245760209160051b010190565b90600182811c92168015612e2b575b6020831014612dfc57565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b91607f1691612df1565b9060405191826000825492612e4984612de2565b8084529360018116908115612eb55750600114612e6e575b506104a092500383610450565b90506000929192526020600020906000915b818310612e995750509060206104a09282010138612e61565b6020919350806001915483858901015201910190918492612e80565b602093506104a09592507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0091501682840152151560051b82010138612e61565b60409067ffffffffffffffff6112cb95931681528160208201520191612d5a565b60405190612f2382610434565b60006080838281528260208201528260408201528260608201520152565b90604051612f4e81610434565b60806fffffffffffffffffffffffffffffffff6001839560ff8154848116875263ffffffff81871c16602088015260a01c1615156040860152015481808216166060850152821c16910152565b67ffffffffffffffff1660005260076020526112cb6004604060002001612e35565b91612ff5918354907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9060031b92831b921b19161790565b9055565b818110613004575050565b60008155600101612ff9565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b8181029291811591840414171561305257565b613010565b8054906000815581613067575050565b6000526020600020908101905b81811061307f575050565b60008155600101613074565b60056104a09160008155600060018201556000600282015560006003820155600481016130b88154612de2565b90816130c7575b505001613057565b81601f600093116001146130df5750555b38806130bf565b818352602083206130fa91601f01861c810190600101612ff9565b808252602082209081548360011b907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8560031b1c1916179055556130d8565b91908110156129245760051b810135907ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffee1813603018212156102d3570190565b9080601f830112156102d357813561319181612c56565b9261319f6040519485610450565b81845260208085019260051b820101918383116102d35760208201905b8382106131cb57505050505090565b813567ffffffffffffffff81116102d3576020916131ee87848094880101612b32565b8152019101906131bc565b610120813603126102d3576040519061321182610434565b61321a8161095b565b8252602081013567ffffffffffffffff81116102d35761323d903690830161317a565b602083015260408101359067ffffffffffffffff82116102d3576132676132889236908301612b32565b60408401526132793660608301611eb7565b606084015260c0369101611eb7565b608082015290565b8151815460208401516040850151608091821b73ffffffff00000000000000000000000000000000166fffffffffffffffffffffffffffffffff9485167fffffffffffffffffffffff000000000000000000000000000000000000000000909416939093179290921791151560a01b74ff000000000000000000000000000000000000000016919091178355606084015193810151901b7fffffffffffffffffffffffffffffffff0000000000000000000000000000000016921691909117600190910155565b9190601f811161336657505050565b6104a0926000526020600020906020601f840160051c83019310613392575b601f0160051c0190612ff9565b9091508190613385565b919091825167ffffffffffffffff8111610413576133c4816133be8454612de2565b84613357565b6020601f821160011461341e578190612ff5939495600092613413575b50507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8260011b9260031b1c19161790565b0151905038806133e1565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe082169061345184600052602060002090565b9160005b8181106134ab57509583600195969710613474575b505050811b019055565b01517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88460031b161c1916905538808061346a565b9192602060018192868b015181550194019201613455565b6135276134f26104a09597969467ffffffffffffffff60a09516845261010060208501526101008401906104cf565b9660408301906fffffffffffffffffffffffffffffffff60408092805115158552826020820151166020860152015116910152565b01906fffffffffffffffffffffffffffffffff60408092805115158552826020820151166020860152015116910152565b73ffffffffffffffffffffffffffffffffffffffff60015416330361357957565b7f2b5c74de0000000000000000000000000000000000000000000000000000000060005260046000fd5b90608082016135b761139461067c83612c04565b61377b5750602082019161365860206135fd6135d561224787612cf5565b60801b7fffffffffffffffffffffffffffffffff000000000000000000000000000000001690565b6040517f2cbc26bb0000000000000000000000000000000000000000000000000000000081527fffffffffffffffffffffffffffffffff00000000000000000000000000000000909116600482015291829081906024820190565b038173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000165afa9081156109445760009161375c575b50613732576136b86136b384612cf5565b613ead565b6136c183612cf5565b6136d661139460a08401926109f48486612a44565b6136f3575060606136ea6104a09394612cf5565b91013590613fd1565b6136fc91612a44565b9061164e6040519283927f24eb47e500000000000000000000000000000000000000000000000000000000845260048401612d99565b7f53ad11d80000000000000000000000000000000000000000000000000000000060005260046000fd5b613775915060203d60201161093d5761092f8183610450565b386136a2565b61378761124991612c04565b7f961c9a4f0000000000000000000000000000000000000000000000000000000060005273ffffffffffffffffffffffffffffffffffffffff16600452602490565b90600482015163ffffffff811661392157506008820151916014600c820151910151926137fd602084015163ffffffff1690565b63ffffffff811663ffffffff8316036138e85750507f000000000000000000000000000000000000000000000000000000000000000063ffffffff811663ffffffff8316036138af5750505167ffffffffffffffff1667ffffffffffffffff811667ffffffffffffffff831603613872575050565b7ff917ffea0000000000000000000000000000000000000000000000000000000060005267ffffffffffffffff9081166004521660245260446000fd5b7f77e480260000000000000000000000000000000000000000000000000000000060005263ffffffff9081166004521660245260446000fd5b7fe366a1170000000000000000000000000000000000000000000000000000000060005263ffffffff9081166004521660245260446000fd5b7f68d2f8d60000000000000000000000000000000000000000000000000000000060005263ffffffff1660045260246000fd5b60409067ffffffffffffffff6112cb949316815281602082015201906104cf565b90805115611c7e578051602082012067ffffffffffffffff8316928360005260076020526139aa8260056040600020016149d4565b15613a035750816139f27f7d628c9a1796743d365ab521a8b2a4686e419b3269919dc9145ea2ce853b54ea936139ed6139fe946000526008602052604060002090565b61339c565b60405191829182611b46565b0390a2565b905061164e6040519283927f393b8ad200000000000000000000000000000000000000000000000000000000845260048401613954565b67ffffffffffffffff166000818152600660205260409020549092919015613b3c5791613b3960e092613b0585613a917f0350d63aa5f270e01729d00d627eeb8f3429772b1818c016c66a588a864f912b97613d57565b846000526007602052613aa881604060002061402e565b613ab183613d57565b846000526007602052613acb83600260406000200161402e565b60405194855260208501906fffffffffffffffffffffffffffffffff60408092805115158552826020820151166020860152015116910152565b60808301906fffffffffffffffffffffffffffffffff60408092805115158552826020820151166020860152015116910152565ba1565b827f1e670e4b0000000000000000000000000000000000000000000000000000000060005260045260246000fd5b60808101613b7d61139461067c83612c04565b61377b57506020810190613b9b60206135fd6135d561224786612cf5565b038173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000165afa90811561094457600091613c21575b50613732576060613c186104a093613c07613c0260408601612c04565b6142dc565b6111aa613c1382612cf5565b614373565b91013590614451565b613c3a915060203d60201161093d5761092f8183610450565b38613be5565b907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820191821161305257565b9190820391821161305257565b613c82612f16565b506fffffffffffffffffffffffffffffffff6060820151166fffffffffffffffffffffffffffffffff82511690602083019163ffffffff835116420342811161305257613ce6906fffffffffffffffffffffffffffffffff6080870151169061303f565b810180911161305257613d0c6fffffffffffffffffffffffffffffffff92918392614d84565b161682524263ffffffff16905290565b6104a09092919260608101936fffffffffffffffffffffffffffffffff60408092805115158552826020820151166020860152015116910152565b805115613e105760408101516fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff613dbb613da660208501516fffffffffffffffffffffffffffffffff1690565b6fffffffffffffffffffffffffffffffff1690565b911690811090811591613e07575b50613dd15750565b61164e906040519182917f8020d12400000000000000000000000000000000000000000000000000000000835260048301613d1c565b90501538613dc9565b6fffffffffffffffffffffffffffffffff613e3e60408301516fffffffffffffffffffffffffffffffff1690565b1615801590613e85575b613e4f5750565b61164e906040519182917fd68af9cc00000000000000000000000000000000000000000000000000000000835260048301613d1c565b50613ea6613da660208301516fffffffffffffffffffffffffffffffff1690565b1515613e48565b613eb961139482612cc4565b613f9a576020613f3291613ee5610b4560045473ffffffffffffffffffffffffffffffffffffffff1690565b6040517f83826b2b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff90921660048301523360248301529092839190829081906044820190565b03915afa90811561094457600091613f7b575b5015613f4d57565b7f728fe07b000000000000000000000000000000000000000000000000000000006000523360045260246000fd5b613f94915060203d60201161093d5761092f8183610450565b38613f45565b7fa9902c7e0000000000000000000000000000000000000000000000000000000060005267ffffffffffffffff1660045260246000fd5b9067ffffffffffffffff6104a09216600052600760205260026040600020019073ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001691614a62565b7f9ea3374b67bf275e6bb9c8ae68f9cae023e1c528b4b27e092f0bb209d3531c199161420d61277992805461407f6140796140708363ffffffff9060801c1690565b63ffffffff1690565b42613c6d565b9081614219575b50506141c760016140aa60208601516fffffffffffffffffffffffffffffffff1690565b926141356140f8613da66fffffffffffffffffffffffffffffffff6140df85546fffffffffffffffffffffffffffffffff1690565b166fffffffffffffffffffffffffffffffff8816614d84565b82906fffffffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffffff00000000000000000000000000000000825416179055565b6141886141428751151590565b82547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1690151560a01b74ff000000000000000000000000000000000000000016178255565b019182906fffffffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffffff00000000000000000000000000000000825416179055565b604083015181546fffffffffffffffffffffffffffffffff1660809190911b7fffffffffffffffffffffffffffffffff0000000000000000000000000000000016179055565b60405191829182613d1c565b613da66140f8916fffffffffffffffffffffffffffffffff61428d614294958261428660018a0154928261427f614278614262876fffffffffffffffffffffffffffffffff1690565b996fffffffffffffffffffffffffffffffff1690565b9560801c90565b169061303f565b91166148c3565b9116614d84565b80547fffffffffffffffffffffffff00000000ffffffffffffffffffffffffffffffff164260801b73ffffffff00000000000000000000000000000000161781553880614086565b7f00000000000000000000000000000000000000000000000000000000000000006143045750565b73ffffffffffffffffffffffffffffffffffffffff16806000526003602052604060002054156143315750565b7fd0d259760000000000000000000000000000000000000000000000000000000060005260045260246000fd5b908160209103126102d357516112cb8161061e565b61437f61139482612cc4565b613f9a5760206143f0916143ab610b4560045473ffffffffffffffffffffffffffffffffffffffff1690565b60405180809581947fa8d87a3b0000000000000000000000000000000000000000000000000000000083526004830191909167ffffffffffffffff6020820193169052565b03915afa80156109445773ffffffffffffffffffffffffffffffffffffffff91600091614422575b50163303613f4d57565b614444915060203d60201161444a575b61443c8183610450565b81019061435e565b38614418565b503d614432565b9067ffffffffffffffff6104a09216600052600760205260406000209073ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001691614a62565b604051906002548083528260208101600260005260206000209260005b8181106144dd5750506104a092500383610450565b84548352600194850194879450602090930192016144c8565b604051906005548083528260208101600560005260206000209260005b8181106145285750506104a092500383610450565b8454835260019485019487945060209093019201614513565b906040519182815491828252602082019060005260206000209260005b8181106145735750506104a092500383610450565b845483526001948501948794506020909301920161455e565b80548210156129245760005260206000200190600090565b80548015614608577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01906145d9828261458c565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82549160031b1b1916905555565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b600081815260036020526040902054908115614714577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82019082821161305257600254927fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff84019384116130525783836000956146d395036146d9575b5050506146c260026145a4565b600390600052602052604060002090565b55600190565b6146c2614705916146fb6146f161470b95600261458c565b90549060031b1c90565b928391600261458c565b90612fbd565b553880806146b5565b5050600090565b600081815260066020526040902054908115614714577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82019082821161305257600554927fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff84019384116130525783836000956146d395036147b7575b5050506147a660056145a4565b600690600052602052604060002090565b6147a6614705916147cf6146f16147d995600561458c565b928391600561458c565b55388080614799565b60018101918060005282602052604060002054928315156000146148ba577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8401848111613052578354937fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff85019485116130525760009585836146d3976148729503614881575b5050506145a4565b90600052602052604060002090565b6148a1614705916148986146f16148b1958861458c565b9283918761458c565b8590600052602052604060002090565b5538808061486a565b50505050600090565b9190820180921161305257565b926148db919261303f565b8101809111613052576112cb91614d84565b60008181526003602052604090205461497857600254680100000000000000008110156104135761495f61492a826001859401600255600261458c565b81939154907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9060031b92831b921b19161790565b9055600254906000526003602052604060002055600190565b50600090565b6000818152600660205260409020546149785760055468010000000000000000811015610413576149bb61492a826001859401600555600561458c565b9055600554906000526006602052604060002055600190565b600082815260018201602052604090205461471457805490680100000000000000008210156104135782614a1261492a84600180960185558461458c565b905580549260005201602052604060002055600190565b8115614a33570490565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b9091815490614a786113948360ff9060a01c1690565b8015614d7c575b614d7657614a9e6fffffffffffffffffffffffffffffffff8316613da6565b9160018401908154614ad8614079614070614acb613da6856fffffffffffffffffffffffffffffffff1690565b9460801c63ffffffff1690565b80614ce2575b5050858110614c435750848310614b7257505091614b6261277992614b27613da6847f1871cdf8010e63f2eb8384381a68dfa7416dc571a5517e66e88b2d2d0c0a690a97613c6d565b6fffffffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffffff00000000000000000000000000000000825416179055565b6040519081529081906020820190565b84614ba0614b9185614b8b613da6614ba5965460801c90565b93613c6d565b614b9a83613c40565b906148c3565b614a29565b9173ffffffffffffffffffffffffffffffffffffffff821615614c1157611249927fd0c8d23a00000000000000000000000000000000000000000000000000000000600052929173ffffffffffffffffffffffffffffffffffffffff9160649460045260245216604452565b7f15279c0800000000000000000000000000000000000000000000000000000000600052600483905260245260446000fd5b828673ffffffffffffffffffffffffffffffffffffffff821615614cb057611249927f1a76572a00000000000000000000000000000000000000000000000000000000600052929173ffffffffffffffffffffffffffffffffffffffff9160649460045260245216604452565b7ff94ebcd100000000000000000000000000000000000000000000000000000000600052600483905260245260446000fd5b828692939611614d4c57614cfc613da6614d039460801c90565b91866148d0565b84547fffffffffffffffffffffffff00000000ffffffffffffffffffffffffffffffff164260801b73ffffffff0000000000000000000000000000000016178555923880614ade565b7f9725942a0000000000000000000000000000000000000000000000000000000060005260046000fd5b50505050565b508315614a7f565b9080821015614d91575090565b90509056fea164736f6c634300081a000a", + ABI: "[{\"inputs\":[{\"internalType\":\"contractITokenMessenger\",\"name\":\"tokenMessenger\",\"type\":\"address\"},{\"internalType\":\"contractIERC20\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"address[]\",\"name\":\"allowlist\",\"type\":\"address[]\"},{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"capacity\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"requested\",\"type\":\"uint256\"}],\"name\":\"AggregateValueMaxCapacityExceeded\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"minWaitInSeconds\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"available\",\"type\":\"uint256\"}],\"name\":\"AggregateValueRateLimitReached\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"AllowListNotEnabled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"BucketOverfilled\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"CallerIsNotARampOnRouter\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CannotTransferToSelf\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"}],\"name\":\"ChainAlreadyExists\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"ChainNotAllowed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CursedByRMN\",\"type\":\"error\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"config\",\"type\":\"tuple\"}],\"name\":\"DisabledNonZeroRateLimit\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidConfig\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"expected\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"got\",\"type\":\"uint32\"}],\"name\":\"InvalidDestinationDomain\",\"type\":\"error\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"allowedCaller\",\"type\":\"bytes32\"},{\"internalType\":\"uint32\",\"name\":\"domainIdentifier\",\"type\":\"uint32\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"enabled\",\"type\":\"bool\"}],\"internalType\":\"structUSDCTokenPool.DomainUpdate\",\"name\":\"domain\",\"type\":\"tuple\"}],\"name\":\"InvalidDomain\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"version\",\"type\":\"uint32\"}],\"name\":\"InvalidMessageVersion\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"expected\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"got\",\"type\":\"uint64\"}],\"name\":\"InvalidNonce\",\"type\":\"error\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"rateLimiterConfig\",\"type\":\"tuple\"}],\"name\":\"InvalidRateLimitRate\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"}],\"name\":\"InvalidReceiver\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"expected\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"got\",\"type\":\"uint32\"}],\"name\":\"InvalidSourceDomain\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"}],\"name\":\"InvalidSourcePoolAddress\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"InvalidToken\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"version\",\"type\":\"uint32\"}],\"name\":\"InvalidTokenMessengerVersion\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MustBeProposedOwner\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"NonExistentChain\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByOwner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OwnerCannotBeZero\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RateLimitMustBeDisabled\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"SenderNotAllowed\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"capacity\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"requested\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenAddress\",\"type\":\"address\"}],\"name\":\"TokenMaxCapacityExceeded\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"minWaitInSeconds\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"available\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenAddress\",\"type\":\"address\"}],\"name\":\"TokenRateLimitReached\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"Unauthorized\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"domain\",\"type\":\"uint64\"}],\"name\":\"UnknownDomain\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnlockingUSDCFailed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"AllowListAdd\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"AllowListRemove\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Burned\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"remoteToken\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundRateLimiterConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundRateLimiterConfig\",\"type\":\"tuple\"}],\"name\":\"ChainAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundRateLimiterConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundRateLimiterConfig\",\"type\":\"tuple\"}],\"name\":\"ChainConfigured\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"ChainRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"config\",\"type\":\"tuple\"}],\"name\":\"ConfigChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"tokenMessenger\",\"type\":\"address\"}],\"name\":\"ConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"allowedCaller\",\"type\":\"bytes32\"},{\"internalType\":\"uint32\",\"name\":\"domainIdentifier\",\"type\":\"uint32\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"enabled\",\"type\":\"bool\"}],\"indexed\":false,\"internalType\":\"structUSDCTokenPool.DomainUpdate[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"name\":\"DomainsSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Locked\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Minted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"rateLimitAdmin\",\"type\":\"address\"}],\"name\":\"RateLimitAdminSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Released\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"previousPoolAddress\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"RemotePoolSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"oldRouter\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newRouter\",\"type\":\"address\"}],\"name\":\"RouterUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokens\",\"type\":\"uint256\"}],\"name\":\"TokensConsumed\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"SUPPORTED_USDC_VERSION\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"removes\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"adds\",\"type\":\"address[]\"}],\"name\":\"applyAllowListUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"allowed\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"remoteTokenAddress\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundRateLimiterConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundRateLimiterConfig\",\"type\":\"tuple\"}],\"internalType\":\"structTokenPool.ChainUpdate[]\",\"name\":\"chains\",\"type\":\"tuple[]\"}],\"name\":\"applyChainUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAllowList\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAllowListEnabled\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getCurrentInboundRateLimiterState\",\"outputs\":[{\"components\":[{\"internalType\":\"uint128\",\"name\":\"tokens\",\"type\":\"uint128\"},{\"internalType\":\"uint32\",\"name\":\"lastUpdated\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.TokenBucket\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getCurrentOutboundRateLimiterState\",\"outputs\":[{\"components\":[{\"internalType\":\"uint128\",\"name\":\"tokens\",\"type\":\"uint128\"},{\"internalType\":\"uint32\",\"name\":\"lastUpdated\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.TokenBucket\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"}],\"name\":\"getDomain\",\"outputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"allowedCaller\",\"type\":\"bytes32\"},{\"internalType\":\"uint32\",\"name\":\"domainIdentifier\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"enabled\",\"type\":\"bool\"}],\"internalType\":\"structUSDCTokenPool.Domain\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRateLimitAdmin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getRemotePool\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getRemoteToken\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRmnProxy\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRouter\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getSupportedChains\",\"outputs\":[{\"internalType\":\"uint64[]\",\"name\":\"\",\"type\":\"uint64[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getToken\",\"outputs\":[{\"internalType\":\"contractIERC20\",\"name\":\"token\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"i_localDomainIdentifier\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"i_messageTransmitter\",\"outputs\":[{\"internalType\":\"contractIMessageTransmitter\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"i_tokenMessenger\",\"outputs\":[{\"internalType\":\"contractITokenMessenger\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"isSupportedChain\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"isSupportedToken\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"originalSender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"localToken\",\"type\":\"address\"}],\"internalType\":\"structPool.LockOrBurnInV1\",\"name\":\"lockOrBurnIn\",\"type\":\"tuple\"}],\"name\":\"lockOrBurn\",\"outputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"destPoolData\",\"type\":\"bytes\"}],\"internalType\":\"structPool.LockOrBurnOutV1\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"originalSender\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"localToken\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"sourcePoolData\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"offchainTokenData\",\"type\":\"bytes\"}],\"internalType\":\"structPool.ReleaseOrMintInV1\",\"name\":\"releaseOrMintIn\",\"type\":\"tuple\"}],\"name\":\"releaseOrMint\",\"outputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"destinationAmount\",\"type\":\"uint256\"}],\"internalType\":\"structPool.ReleaseOrMintOutV1\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundConfig\",\"type\":\"tuple\"}],\"name\":\"setChainRateLimiterConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"allowedCaller\",\"type\":\"bytes32\"},{\"internalType\":\"uint32\",\"name\":\"domainIdentifier\",\"type\":\"uint32\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"enabled\",\"type\":\"bool\"}],\"internalType\":\"structUSDCTokenPool.DomainUpdate[]\",\"name\":\"domains\",\"type\":\"tuple[]\"}],\"name\":\"setDomains\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"rateLimitAdmin\",\"type\":\"address\"}],\"name\":\"setRateLimitAdmin\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"setRemotePool\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newRouter\",\"type\":\"address\"}],\"name\":\"setRouter\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", + Bin: "0x6101406040523480156200001257600080fd5b506040516200520538038062005205833981016040819052620000359162000ae9565b83838383336000816200005b57604051639b15e16f60e01b815260040160405180910390fd5b600180546001600160a01b0319166001600160a01b03848116919091179091558116156200008e576200008e81620003e9565b50506001600160a01b0384161580620000ae57506001600160a01b038116155b80620000c157506001600160a01b038216155b15620000e0576040516342bcdf7f60e11b815260040160405180910390fd5b6001600160a01b0384811660805282811660a052600480546001600160a01b031916918316919091179055825115801560c052620001335760408051600081526020810190915262000133908462000463565b5050506001600160a01b038616905062000160576040516306b7c75960e31b815260040160405180910390fd5b6000856001600160a01b0316632c1219216040518163ffffffff1660e01b8152600401602060405180830381865afa158015620001a1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620001c7919062000c0f565b90506000816001600160a01b03166354fd4d506040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200020a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000230919062000c36565b905063ffffffff81161562000265576040516334697c6b60e11b815263ffffffff821660048201526024015b60405180910390fd5b6000876001600160a01b0316639cdbb1816040518163ffffffff1660e01b8152600401602060405180830381865afa158015620002a6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620002cc919062000c36565b905063ffffffff811615620002fd576040516316ba39c560e31b815263ffffffff821660048201526024016200025c565b6001600160a01b0380891660e05283166101008190526040805163234d8e3d60e21b81529051638d3638f4916004808201926020929091908290030181865afa1580156200034f573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000375919062000c36565b63ffffffff166101205260e0516080516200039f916001600160a01b0390911690600019620005c0565b6040516001600160a01b03891681527f2e902d38f15b233cbb63711add0fca4545334d3a169d60c0a616494d7eea95449060200160405180910390a1505050505050505062000d83565b336001600160a01b038216036200041357604051636d6c4ee560e11b815260040160405180910390fd5b600080546001600160a01b0319166001600160a01b03838116918217835560015460405192939116917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b60c05162000484576040516335f4a7b360e01b815260040160405180910390fd5b60005b82518110156200050f576000838281518110620004a857620004a862000c5e565b60209081029190910101519050620004c2600282620006a6565b1562000505576040516001600160a01b03821681527f800671136ab6cfee9fbe5ed1fb7ca417811aca3cf864800d127b927adedf75669060200160405180910390a15b5060010162000487565b5060005b8151811015620005bb57600082828151811062000534576200053462000c5e565b6020026020010151905060006001600160a01b0316816001600160a01b031603620005605750620005b2565b6200056d600282620006c6565b15620005b0576040516001600160a01b03821681527f2640d4d76caf8bf478aabfa982fa4e1c4eb71a37f93cd15e80dbc657911546d89060200160405180910390a15b505b60010162000513565b505050565b604051636eb1769f60e11b81523060048201526001600160a01b038381166024830152600091839186169063dd62ed3e90604401602060405180830381865afa15801562000612573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000638919062000c74565b62000644919062000ca4565b604080516001600160a01b038616602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b0390811663095ea7b360e01b17909152919250620006a091869190620006dd16565b50505050565b6000620006bd836001600160a01b038416620007ae565b90505b92915050565b6000620006bd836001600160a01b038416620008b2565b6040805180820190915260208082527f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564908201526000906200072c906001600160a01b03851690849062000904565b805190915015620005bb57808060200190518101906200074d919062000cba565b620005bb5760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b60648201526084016200025c565b60008181526001830160205260408120548015620008a7576000620007d560018362000cde565b8554909150600090620007eb9060019062000cde565b9050808214620008575760008660000182815481106200080f576200080f62000c5e565b906000526020600020015490508087600001848154811062000835576200083562000c5e565b6000918252602080832090910192909255918252600188019052604090208390555b85548690806200086b576200086b62000cf4565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050620006c0565b6000915050620006c0565b6000818152600183016020526040812054620008fb57508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155620006c0565b506000620006c0565b60606200091584846000856200091d565b949350505050565b606082471015620009805760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b60648201526084016200025c565b600080866001600160a01b031685876040516200099e919062000d30565b60006040518083038185875af1925050503d8060008114620009dd576040519150601f19603f3d011682016040523d82523d6000602084013e620009e2565b606091505b509092509050620009f68783838762000a01565b979650505050505050565b6060831562000a7557825160000362000a6d576001600160a01b0385163b62000a6d5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016200025c565b508162000915565b62000915838381511562000a8c5781518083602001fd5b8060405162461bcd60e51b81526004016200025c919062000d4e565b6001600160a01b038116811462000abe57600080fd5b50565b634e487b7160e01b600052604160045260246000fd5b805162000ae48162000aa8565b919050565b600080600080600060a0868803121562000b0257600080fd5b855162000b0f8162000aa8565b8095505060208087015162000b248162000aa8565b60408801519095506001600160401b038082111562000b4257600080fd5b818901915089601f83011262000b5757600080fd5b81518181111562000b6c5762000b6c62000ac1565b8060051b604051601f19603f8301168101818110858211171562000b945762000b9462000ac1565b60405291825284820192508381018501918c83111562000bb357600080fd5b938501935b8285101562000bdc5762000bcc8562000ad7565b8452938501939285019262000bb8565b80985050505050505062000bf36060870162000ad7565b915062000c036080870162000ad7565b90509295509295909350565b60006020828403121562000c2257600080fd5b815162000c2f8162000aa8565b9392505050565b60006020828403121562000c4957600080fd5b815163ffffffff8116811462000c2f57600080fd5b634e487b7160e01b600052603260045260246000fd5b60006020828403121562000c8757600080fd5b5051919050565b634e487b7160e01b600052601160045260246000fd5b80820180821115620006c057620006c062000c8e565b60006020828403121562000ccd57600080fd5b8151801515811462000c2f57600080fd5b81810381811115620006c057620006c062000c8e565b634e487b7160e01b600052603160045260246000fd5b60005b8381101562000d2757818101518382015260200162000d0d565b50506000910152565b6000825162000d4481846020870162000d0a565b9190910192915050565b602081526000825180602084015262000d6f81604085016020870162000d0a565b601f01601f19169190910160400192915050565b60805160a05160c05160e05161010051610120516143c962000e3c60003960008181610382015281816111d401528181611e1d0152611e7b0152600081816106760152610a7801526000818161035b01526110ea01526000818161063a01528181611f18015261282201526000818161057601528181611c1b01526121ce01526000818161028f015281816102e4015281816110b401528181611b3b015281816120ee015281816127b80152612a0d01526143c96000f3fe608060405234801561001057600080fd5b50600436106101ef5760003560e01c80639a4575b91161010f578063c75eea9c116100a2578063dfadfa3511610071578063dfadfa351461059a578063e0351e1314610638578063f2fde38b1461065e578063fbf84dd71461067157600080fd5b8063c75eea9c1461053b578063cf7401f31461054e578063db6327dc14610561578063dc0bd9711461057457600080fd5b8063b0f479a1116100de578063b0f479a1146104e2578063b794658014610500578063c0d7865514610513578063c4bffe2b1461052657600080fd5b80639a4575b9146104365780639fdf13ff14610456578063a7cd63b71461045e578063af58d59f1461047357600080fd5b80636155cda01161018757806379ba50971161015657806379ba5097146103ea5780637d54534e146103f25780638926f54f146104055780638da5cb5b1461041857600080fd5b80636155cda0146103565780636b716b0d1461037d5780636d3d1a58146103b957806378a010b2146103d757600080fd5b806321df0da7116101c357806321df0da71461028d578063240028e8146102d4578063390775371461032157806354c8a4f31461034357600080fd5b806241d3c1146101f457806301ffc9a7146102095780630a2fd49314610231578063181f5a7714610251575b600080fd5b6102076102023660046131b0565b610698565b005b61021c610217366004613225565b610835565b60405190151581526020015b60405180910390f35b61024461023f36600461328d565b61091a565b604051610228919061330e565b6102446040518060400160405280601381526020017f55534443546f6b656e506f6f6c20312e352e300000000000000000000000000081525081565b7f00000000000000000000000000000000000000000000000000000000000000005b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610228565b61021c6102e236600461334e565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff90811691161490565b61033461032f36600461336b565b6109ca565b60405190518152602001610228565b6102076103513660046133f3565b610bb7565b6102af7f000000000000000000000000000000000000000000000000000000000000000081565b6103a47f000000000000000000000000000000000000000000000000000000000000000081565b60405163ffffffff9091168152602001610228565b60085473ffffffffffffffffffffffffffffffffffffffff166102af565b6102076103e536600461345f565b610c32565b610207610da1565b61020761040036600461334e565b610e6f565b61021c61041336600461328d565b610ef0565b60015473ffffffffffffffffffffffffffffffffffffffff166102af565b6104496104443660046134e4565b610f07565b604051610228919061351f565b6103a4600081565b61046661124f565b604051610228919061357f565b61048661048136600461328d565b611260565b604051610228919081516fffffffffffffffffffffffffffffffff908116825260208084015163ffffffff1690830152604080840151151590830152606080840151821690830152608092830151169181019190915260a00190565b60045473ffffffffffffffffffffffffffffffffffffffff166102af565b61024461050e36600461328d565b611335565b61020761052136600461334e565b611360565b61052e611434565b60405161022891906135d9565b61048661054936600461328d565b6114ec565b61020761055c366004613764565b6115be565b61020761056f3660046137ab565b611647565b7f00000000000000000000000000000000000000000000000000000000000000006102af565b61060e6105a836600461328d565b60408051606080820183526000808352602080840182905292840181905267ffffffffffffffff949094168452600982529282902082519384018352805484526001015463ffffffff811691840191909152640100000000900460ff1615159082015290565b604080518251815260208084015163ffffffff169082015291810151151590820152606001610228565b7f000000000000000000000000000000000000000000000000000000000000000061021c565b61020761066c36600461334e565b611acd565b6102af7f000000000000000000000000000000000000000000000000000000000000000081565b6106a0611ae1565b60005b818110156107f75760008383838181106106bf576106bf6137ed565b9050608002018036038101906106d59190613830565b805190915015806106f25750604081015167ffffffffffffffff16155b1561076157604080517fa087bd2900000000000000000000000000000000000000000000000000000000815282516004820152602083015163ffffffff1660248201529082015167ffffffffffffffff1660448201526060820151151560648201526084015b60405180910390fd5b60408051606080820183528351825260208085015163ffffffff9081168285019081529286015115158486019081529585015167ffffffffffffffff166000908152600990925293902091518255516001918201805494511515640100000000027fffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000009095169190931617929092179055016106a3565b507f1889010d2535a0ab1643678d1da87fbbe8b87b2f585b47ddb72ec622aef9ee5682826040516108299291906138aa565b60405180910390a15050565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167faff2afbf0000000000000000000000000000000000000000000000000000000014806108c857507fffffffff0000000000000000000000000000000000000000000000000000000082167f0e64dd2900000000000000000000000000000000000000000000000000000000145b8061091457507fffffffff0000000000000000000000000000000000000000000000000000000082167f01ffc9a700000000000000000000000000000000000000000000000000000000145b92915050565b67ffffffffffffffff8116600090815260076020526040902060040180546060919061094590613931565b80601f016020809104026020016040519081016040528092919081815260200182805461097190613931565b80156109be5780601f10610993576101008083540402835291602001916109be565b820191906000526020600020905b8154815290600101906020018083116109a157829003601f168201915b50505050509050919050565b6040805160208101909152600081526109ea6109e583613a2f565b611b34565b60006109f960c0840184613b24565b810190610a069190613b89565b90506000610a1760e0850185613b24565b810190610a249190613bc8565b9050610a34816000015183611d65565b805160208201516040517f57ecfd2800000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016926357ecfd2892610aab92600401613c59565b6020604051808303816000875af1158015610aca573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610aee9190613c7e565b610b24576040517fbf969f2200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610b34606085016040860161334e565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f9d228d69b5fdb8d273a2336f8fb8612d039631024ea9bf09c424a9503aa078f08660600135604051610b9691815260200190565b60405180910390a35050604080516020810190915260609092013582525090565b610bbf611ae1565b610c2c84848080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050604080516020808802828101820190935287825290935087925086918291850190849080828437600092019190915250611f1692505050565b50505050565b610c3a611ae1565b610c4383610ef0565b610c85576040517f1e670e4b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84166004820152602401610758565b67ffffffffffffffff831660009081526007602052604081206004018054610cac90613931565b80601f0160208091040260200160405190810160405280929190818152602001828054610cd890613931565b8015610d255780601f10610cfa57610100808354040283529160200191610d25565b820191906000526020600020905b815481529060010190602001808311610d0857829003601f168201915b5050505067ffffffffffffffff8616600090815260076020526040902091925050600401610d54838583613ce3565b508367ffffffffffffffff167fdb4d6220746a38cbc5335f7e108f7de80f482f4d23350253dfd0917df75a14bf828585604051610d9393929190613e47565b60405180910390a250505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314610df2576040517f02b543c600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000008082163390811790935560008054909116815560405173ffffffffffffffffffffffffffffffffffffffff909216929183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b610e77611ae1565b600880547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040519081527f44676b5284b809a22248eba0da87391d79098be38bb03154be88a58bf4d091749060200160405180910390a150565b6000610914600567ffffffffffffffff84166120cc565b6040805180820190915260608082526020820152610f2c610f2783613e77565b6120e7565b6000600981610f41604086016020870161328d565b67ffffffffffffffff168152602080820192909252604090810160002081516060810183528154815260019091015463ffffffff81169382019390935264010000000090920460ff161515908201819052909150610fe857610fa9604084016020850161328d565b6040517fd201c48a00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff9091166004820152602401610758565b610ff28380613b24565b9050602014611039576110058380613b24565b6040517fa3c8cf09000000000000000000000000000000000000000000000000000000008152600401610758929190613f1b565b60006110458480613b24565b8101906110529190613f2f565b602083015183516040517ff856ddb60000000000000000000000000000000000000000000000000000000081526060880135600482015263ffffffff90921660248301526044820183905273ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000008116606484015260848301919091529192506000917f0000000000000000000000000000000000000000000000000000000000000000169063f856ddb69060a4016020604051808303816000875af1158015611133573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111579190613f48565b6040516060870135815290915033907f696de425f79f4a40bc6d2122ca50507f0efbeabbff86a84871b7196ab8ea8df79060200160405180910390a260405180604001604052806111b487602001602081019061050e919061328d565b815260408051808201825267ffffffffffffffff851680825263ffffffff7f00000000000000000000000000000000000000000000000000000000000000008116602093840190815284518085019390935251169281019290925290910190606001604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152919052905295945050505050565b606061125b60026122b1565b905090565b6040805160a08101825260008082526020820181905291810182905260608101829052608081019190915267ffffffffffffffff8216600090815260076020908152604091829020825160a08101845260028201546fffffffffffffffffffffffffffffffff808216835270010000000000000000000000000000000080830463ffffffff16958401959095527401000000000000000000000000000000000000000090910460ff161515948201949094526003909101548084166060830152919091049091166080820152610914906122be565b67ffffffffffffffff8116600090815260076020526040902060050180546060919061094590613931565b611368611ae1565b73ffffffffffffffffffffffffffffffffffffffff81166113b5576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6004805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff000000000000000000000000000000000000000083168117909355604080519190921680825260208201939093527f02dc5c233404867c793b749c6d644beb2277536d18a7e7974d3f238e4c6f16849101610829565b6060600061144260056122b1565b90506000815167ffffffffffffffff8111156114605761146061361b565b604051908082528060200260200182016040528015611489578160200160208202803683370190505b50905060005b82518110156114e5578281815181106114aa576114aa6137ed565b60200260200101518282815181106114c4576114c46137ed565b67ffffffffffffffff9092166020928302919091019091015260010161148f565b5092915050565b6040805160a08101825260008082526020820181905291810182905260608101829052608081019190915267ffffffffffffffff8216600090815260076020908152604091829020825160a08101845281546fffffffffffffffffffffffffffffffff808216835270010000000000000000000000000000000080830463ffffffff16958401959095527401000000000000000000000000000000000000000090910460ff161515948201949094526001909101548084166060830152919091049091166080820152610914906122be565b60085473ffffffffffffffffffffffffffffffffffffffff1633148015906115fe575060015473ffffffffffffffffffffffffffffffffffffffff163314155b15611637576040517f8e4a23d6000000000000000000000000000000000000000000000000000000008152336004820152602401610758565b611642838383612370565b505050565b61164f611ae1565b60005b8181101561164257600083838381811061166e5761166e6137ed565b90506020028101906116809190613f65565b61168990613fa3565b905061169e816080015182602001511561245a565b6116b18160a0015182602001511561245a565b8060200151156119ad5780516116d39060059067ffffffffffffffff16612593565b6117185780516040517f1d5ad3c500000000000000000000000000000000000000000000000000000000815267ffffffffffffffff9091166004820152602401610758565b604081015151158061172d5750606081015151155b15611764576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805161012081018252608083810180516020908101516fffffffffffffffffffffffffffffffff9081168486019081524263ffffffff90811660a0808901829052865151151560c08a01528651860151851660e08a015295518901518416610100890152918752875180860189529489018051850151841686528585019290925281515115158589015281518401518316606080870191909152915188015183168587015283870194855288880151878901908152828a015183890152895167ffffffffffffffff1660009081526007865289902088518051825482890151838e01519289167fffffffffffffffffffffffff0000000000000000000000000000000000000000928316177001000000000000000000000000000000009188168202177fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff90811674010000000000000000000000000000000000000000941515850217865584890151948d0151948a16948a168202949094176001860155995180516002860180549b8301519f830151918b169b9093169a909a179d9096168a029c909c179091169615150295909517909855908101519401519381169316909102919091176003820155915190919060048201906119459082614057565b506060820151600582019061195a9082614057565b505081516060830151608084015160a08501516040517f8d340f17e19058004c20453540862a9c62778504476f6756755cb33bcd6c38c295506119a09493929190614171565b60405180910390a1611ac4565b80516119c59060059067ffffffffffffffff1661259f565b611a0a5780516040517f1e670e4b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff9091166004820152602401610758565b805167ffffffffffffffff16600090815260076020526040812080547fffffffffffffffffffffff00000000000000000000000000000000000000000090811682556001820183905560028201805490911690556003810182905590611a736004830182613162565b611a81600583016000613162565b5050805160405167ffffffffffffffff90911681527f5204aec90a3c794d8e90fded8b46ae9c7c552803e7e832e0c1d358396d8599169060200160405180910390a15b50600101611652565b611ad5611ae1565b611ade816125ab565b50565b60015473ffffffffffffffffffffffffffffffffffffffff163314611b32576040517f2b5c74de00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b565b60808101517f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff908116911614611bc95760808101516040517f961c9a4f00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091166004820152602401610758565b60208101516040517f2cbc26bb00000000000000000000000000000000000000000000000000000000815260809190911b77ffffffffffffffff000000000000000000000000000000001660048201527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1690632cbc26bb90602401602060405180830381865afa158015611c77573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c9b9190613c7e565b15611cd2576040517f53ad11d800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611cdf816020015161266f565b6000611cee826020015161091a565b9050805160001480611d12575080805190602001208260a001518051906020012014155b15611d4f578160a001516040517f24eb47e5000000000000000000000000000000000000000000000000000000008152600401610758919061330e565b611d6182602001518360600151612795565b5050565b600482015163ffffffff811615611db0576040517f68d2f8d600000000000000000000000000000000000000000000000000000000815263ffffffff82166004820152602401610758565b6008830151600c8401516014850151602085015163ffffffff808516911614611e1b5760208501516040517fe366a11700000000000000000000000000000000000000000000000000000000815263ffffffff91821660048201529084166024820152604401610758565b7f000000000000000000000000000000000000000000000000000000000000000063ffffffff168263ffffffff1614611eb0576040517f77e4802600000000000000000000000000000000000000000000000000000000815263ffffffff7f00000000000000000000000000000000000000000000000000000000000000008116600483015283166024820152604401610758565b845167ffffffffffffffff828116911614611f0e5784516040517ff917ffea00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff91821660048201529082166024820152604401610758565b505050505050565b7f0000000000000000000000000000000000000000000000000000000000000000611f6d576040517f35f4a7b300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b8251811015612003576000838281518110611f8d57611f8d6137ed565b60200260200101519050611fab8160026127dc90919063ffffffff16565b15611ffa5760405173ffffffffffffffffffffffffffffffffffffffff821681527f800671136ab6cfee9fbe5ed1fb7ca417811aca3cf864800d127b927adedf75669060200160405180910390a15b50600101611f70565b5060005b8151811015611642576000828281518110612024576120246137ed565b60200260200101519050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff160361206857506120c4565b6120736002826127fe565b156120c25760405173ffffffffffffffffffffffffffffffffffffffff821681527f2640d4d76caf8bf478aabfa982fa4e1c4eb71a37f93cd15e80dbc657911546d89060200160405180910390a15b505b600101612007565b600081815260018301602052604081205415155b9392505050565b60808101517f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff90811691161461217c5760808101516040517f961c9a4f00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091166004820152602401610758565b60208101516040517f2cbc26bb00000000000000000000000000000000000000000000000000000000815260809190911b77ffffffffffffffff000000000000000000000000000000001660048201527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1690632cbc26bb90602401602060405180830381865afa15801561222a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061224e9190613c7e565b15612285576040517f53ad11d800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6122928160400151612820565b61229f816020015161289f565b611ade816020015182606001516129ed565b606060006120e083612a31565b6040805160a08101825260008082526020820181905291810182905260608101829052608081019190915261234c82606001516fffffffffffffffffffffffffffffffff1683600001516fffffffffffffffffffffffffffffffff16846020015163ffffffff16426123309190614239565b85608001516fffffffffffffffffffffffffffffffff16612a8c565b6fffffffffffffffffffffffffffffffff1682525063ffffffff4216602082015290565b61237983610ef0565b6123bb576040517f1e670e4b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84166004820152602401610758565b6123c682600061245a565b67ffffffffffffffff831660009081526007602052604090206123e99083612ab6565b6123f481600061245a565b67ffffffffffffffff8316600090815260076020526040902061241a9060020182612ab6565b7f0350d63aa5f270e01729d00d627eeb8f3429772b1818c016c66a588a864f912b83838360405161244d9392919061424c565b60405180910390a1505050565b8151156125215781602001516fffffffffffffffffffffffffffffffff1682604001516fffffffffffffffffffffffffffffffff161015806124b0575060408201516fffffffffffffffffffffffffffffffff16155b156124e957816040517f8020d12400000000000000000000000000000000000000000000000000000000815260040161075891906142cf565b8015611d61576040517f433fc33d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60408201516fffffffffffffffffffffffffffffffff1615158061255a575060208201516fffffffffffffffffffffffffffffffff1615155b15611d6157816040517fd68af9cc00000000000000000000000000000000000000000000000000000000815260040161075891906142cf565b60006120e08383612c58565b60006120e08383612ca7565b3373ffffffffffffffffffffffffffffffffffffffff8216036125fa576040517fdad89dca00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff838116918217835560015460405192939116917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b61267881610ef0565b6126ba576040517fa9902c7e00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff82166004820152602401610758565b600480546040517f83826b2b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84169281019290925233602483015273ffffffffffffffffffffffffffffffffffffffff16906383826b2b90604401602060405180830381865afa158015612739573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061275d9190613c7e565b611ade576040517f728fe07b000000000000000000000000000000000000000000000000000000008152336004820152602401610758565b67ffffffffffffffff82166000908152600760205260409020611d6190600201827f0000000000000000000000000000000000000000000000000000000000000000612d9a565b60006120e08373ffffffffffffffffffffffffffffffffffffffff8416612ca7565b60006120e08373ffffffffffffffffffffffffffffffffffffffff8416612c58565b7f000000000000000000000000000000000000000000000000000000000000000015611ade5761285160028261311d565b611ade576040517fd0d2597600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff82166004820152602401610758565b6128a881610ef0565b6128ea576040517fa9902c7e00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff82166004820152602401610758565b600480546040517fa8d87a3b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84169281019290925273ffffffffffffffffffffffffffffffffffffffff169063a8d87a3b90602401602060405180830381865afa158015612963573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612987919061430b565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611ade576040517f728fe07b000000000000000000000000000000000000000000000000000000008152336004820152602401610758565b67ffffffffffffffff82166000908152600760205260409020611d6190827f0000000000000000000000000000000000000000000000000000000000000000612d9a565b6060816000018054806020026020016040519081016040528092919081815260200182805480156109be57602002820191906000526020600020905b815481526020019060010190808311612a6d5750505050509050919050565b6000612aab85612a9c8486614328565b612aa6908761433f565b61314c565b90505b949350505050565b8154600090612adf90700100000000000000000000000000000000900463ffffffff1642614239565b90508015612b815760018301548354612b27916fffffffffffffffffffffffffffffffff80821692811691859170010000000000000000000000000000000090910416612a8c565b83546fffffffffffffffffffffffffffffffff919091167fffffffffffffffffffffffff0000000000000000000000000000000000000000909116177001000000000000000000000000000000004263ffffffff16021783555b60208201518354612ba7916fffffffffffffffffffffffffffffffff908116911661314c565b83548351151574010000000000000000000000000000000000000000027fffffffffffffffffffffff00ffffffff000000000000000000000000000000009091166fffffffffffffffffffffffffffffffff92831617178455602083015160408085015183167001000000000000000000000000000000000291909216176001850155517f9ea3374b67bf275e6bb9c8ae68f9cae023e1c528b4b27e092f0bb209d3531c199061244d9084906142cf565b6000818152600183016020526040812054612c9f57508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155610914565b506000610914565b60008181526001830160205260408120548015612d90576000612ccb600183614239565b8554909150600090612cdf90600190614239565b9050808214612d44576000866000018281548110612cff57612cff6137ed565b9060005260206000200154905080876000018481548110612d2257612d226137ed565b6000918252602080832090910192909255918252600188019052604090208390555b8554869080612d5557612d55614352565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050610914565b6000915050610914565b825474010000000000000000000000000000000000000000900460ff161580612dc1575081155b15612dcb57505050565b825460018401546fffffffffffffffffffffffffffffffff80831692911690600090612e1190700100000000000000000000000000000000900463ffffffff1642614239565b90508015612ed15781831115612e53576040517f9725942a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001860154612e8d9083908590849070010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff16612a8c565b86547fffffffffffffffffffffffff00000000ffffffffffffffffffffffffffffffff167001000000000000000000000000000000004263ffffffff160217875592505b84821015612f885773ffffffffffffffffffffffffffffffffffffffff8416612f30576040517ff94ebcd10000000000000000000000000000000000000000000000000000000081526004810183905260248101869052604401610758565b6040517f1a76572a000000000000000000000000000000000000000000000000000000008152600481018390526024810186905273ffffffffffffffffffffffffffffffffffffffff85166044820152606401610758565b8483101561309b5760018681015470010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff16906000908290612fcc9082614239565b612fd6878a614239565b612fe0919061433f565b612fea9190614381565b905073ffffffffffffffffffffffffffffffffffffffff8616613043576040517f15279c080000000000000000000000000000000000000000000000000000000081526004810182905260248101869052604401610758565b6040517fd0c8d23a000000000000000000000000000000000000000000000000000000008152600481018290526024810186905273ffffffffffffffffffffffffffffffffffffffff87166044820152606401610758565b6130a58584614239565b86547fffffffffffffffffffffffffffffffff00000000000000000000000000000000166fffffffffffffffffffffffffffffffff82161787556040518681529093507f1871cdf8010e63f2eb8384381a68dfa7416dc571a5517e66e88b2d2d0c0a690a9060200160405180910390a1505050505050565b73ffffffffffffffffffffffffffffffffffffffff8116600090815260018301602052604081205415156120e0565b600081831061315b57816120e0565b5090919050565b50805461316e90613931565b6000825580601f1061317e575050565b601f016020900490600052602060002090810190611ade91905b808211156131ac5760008155600101613198565b5090565b600080602083850312156131c357600080fd5b823567ffffffffffffffff808211156131db57600080fd5b818501915085601f8301126131ef57600080fd5b8135818111156131fe57600080fd5b8660208260071b850101111561321357600080fd5b60209290920196919550909350505050565b60006020828403121561323757600080fd5b81357fffffffff00000000000000000000000000000000000000000000000000000000811681146120e057600080fd5b67ffffffffffffffff81168114611ade57600080fd5b803561328881613267565b919050565b60006020828403121561329f57600080fd5b81356120e081613267565b6000815180845260005b818110156132d0576020818501810151868301820152016132b4565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b6020815260006120e060208301846132aa565b73ffffffffffffffffffffffffffffffffffffffff81168114611ade57600080fd5b803561328881613321565b60006020828403121561336057600080fd5b81356120e081613321565b60006020828403121561337d57600080fd5b813567ffffffffffffffff81111561339457600080fd5b820161010081850312156120e057600080fd5b60008083601f8401126133b957600080fd5b50813567ffffffffffffffff8111156133d157600080fd5b6020830191508360208260051b85010111156133ec57600080fd5b9250929050565b6000806000806040858703121561340957600080fd5b843567ffffffffffffffff8082111561342157600080fd5b61342d888389016133a7565b9096509450602087013591508082111561344657600080fd5b50613453878288016133a7565b95989497509550505050565b60008060006040848603121561347457600080fd5b833561347f81613267565b9250602084013567ffffffffffffffff8082111561349c57600080fd5b818601915086601f8301126134b057600080fd5b8135818111156134bf57600080fd5b8760208285010111156134d157600080fd5b6020830194508093505050509250925092565b6000602082840312156134f657600080fd5b813567ffffffffffffffff81111561350d57600080fd5b820160a081850312156120e057600080fd5b60208152600082516040602084015261353b60608401826132aa565b905060208401517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe084830301604085015261357682826132aa565b95945050505050565b6020808252825182820181905260009190848201906040850190845b818110156135cd57835173ffffffffffffffffffffffffffffffffffffffff168352928401929184019160010161359b565b50909695505050505050565b6020808252825182820181905260009190848201906040850190845b818110156135cd57835167ffffffffffffffff16835292840192918401916001016135f5565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051610100810167ffffffffffffffff8111828210171561366e5761366e61361b565b60405290565b6040805190810167ffffffffffffffff8111828210171561366e5761366e61361b565b60405160c0810167ffffffffffffffff8111828210171561366e5761366e61361b565b8015158114611ade57600080fd5b8035613288816136ba565b80356fffffffffffffffffffffffffffffffff8116811461328857600080fd5b60006060828403121561370557600080fd5b6040516060810181811067ffffffffffffffff821117156137285761372861361b565b6040529050808235613739816136ba565b8152613747602084016136d3565b6020820152613758604084016136d3565b60408201525092915050565b600080600060e0848603121561377957600080fd5b833561378481613267565b925061379385602086016136f3565b91506137a285608086016136f3565b90509250925092565b600080602083850312156137be57600080fd5b823567ffffffffffffffff8111156137d557600080fd5b6137e1858286016133a7565b90969095509350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b803563ffffffff8116811461328857600080fd5b60006080828403121561384257600080fd5b6040516080810181811067ffffffffffffffff821117156138655761386561361b565b604052823581526138786020840161381c565b6020820152604083013561388b81613267565b6040820152606083013561389e816136ba565b60608201529392505050565b6020808252818101839052600090604080840186845b87811015613924578135835263ffffffff6138dc86840161381c565b1685840152838201356138ee81613267565b67ffffffffffffffff168385015260608281013561390b816136ba565b15159084015260809283019291909101906001016138c0565b5090979650505050505050565b600181811c9082168061394557607f821691505b60208210810361397e577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b600082601f83011261399557600080fd5b813567ffffffffffffffff808211156139b0576139b061361b565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f011681019082821181831017156139f6576139f661361b565b81604052838152866020858801011115613a0f57600080fd5b836020870160208301376000602085830101528094505050505092915050565b60006101008236031215613a4257600080fd5b613a4a61364a565b823567ffffffffffffffff80821115613a6257600080fd5b613a6e36838701613984565b8352613a7c6020860161327d565b6020840152613a8d60408601613343565b604084015260608501356060840152613aa860808601613343565b608084015260a0850135915080821115613ac157600080fd5b613acd36838701613984565b60a084015260c0850135915080821115613ae657600080fd5b613af236838701613984565b60c084015260e0850135915080821115613b0b57600080fd5b50613b1836828601613984565b60e08301525092915050565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112613b5957600080fd5b83018035915067ffffffffffffffff821115613b7457600080fd5b6020019150368190038213156133ec57600080fd5b600060408284031215613b9b57600080fd5b613ba3613674565b8235613bae81613267565b8152613bbc6020840161381c565b60208201529392505050565b600060208284031215613bda57600080fd5b813567ffffffffffffffff80821115613bf257600080fd5b9083019060408286031215613c0657600080fd5b613c0e613674565b823582811115613c1d57600080fd5b613c2987828601613984565b825250602083013582811115613c3e57600080fd5b613c4a87828601613984565b60208301525095945050505050565b604081526000613c6c60408301856132aa565b828103602084015261357681856132aa565b600060208284031215613c9057600080fd5b81516120e0816136ba565b601f821115611642576000816000526020600020601f850160051c81016020861015613cc45750805b601f850160051c820191505b81811015611f0e57828155600101613cd0565b67ffffffffffffffff831115613cfb57613cfb61361b565b613d0f83613d098354613931565b83613c9b565b6000601f841160018114613d615760008515613d2b5750838201355b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600387901b1c1916600186901b178355613df7565b6000838152602090207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0861690835b82811015613db05786850135825560209485019460019092019101613d90565b5086821015613deb577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88860031b161c19848701351681555b505060018560011b0183555b5050505050565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b604081526000613e5a60408301866132aa565b8281036020840152613e6d818587613dfe565b9695505050505050565b600060a08236031215613e8957600080fd5b60405160a0810167ffffffffffffffff8282108183111715613ead57613ead61361b565b816040528435915080821115613ec257600080fd5b50613ecf36828601613984565b8252506020830135613ee081613267565b60208201526040830135613ef381613321565b6040820152606083810135908201526080830135613f1081613321565b608082015292915050565b602081526000612aae602083018486613dfe565b600060208284031215613f4157600080fd5b5035919050565b600060208284031215613f5a57600080fd5b81516120e081613267565b600082357ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffec1833603018112613f9957600080fd5b9190910192915050565b60006101408236031215613fb657600080fd5b613fbe613697565b613fc78361327d565b8152613fd5602084016136c8565b6020820152604083013567ffffffffffffffff80821115613ff557600080fd5b61400136838701613984565b6040840152606085013591508082111561401a57600080fd5b5061402736828601613984565b60608301525061403a36608085016136f3565b608082015261404c3660e085016136f3565b60a082015292915050565b815167ffffffffffffffff8111156140715761407161361b565b6140858161407f8454613931565b84613c9b565b602080601f8311600181146140d857600084156140a25750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b178555611f0e565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b8281101561412557888601518255948401946001909101908401614106565b508582101561416157878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b600061010067ffffffffffffffff87168352806020840152614195818401876132aa565b8551151560408581019190915260208701516fffffffffffffffffffffffffffffffff90811660608701529087015116608085015291506141d39050565b8251151560a083015260208301516fffffffffffffffffffffffffffffffff90811660c084015260408401511660e0830152613576565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b818103818111156109145761091461420a565b67ffffffffffffffff8416815260e0810161429860208301858051151582526020808201516fffffffffffffffffffffffffffffffff9081169184019190915260409182015116910152565b82511515608083015260208301516fffffffffffffffffffffffffffffffff90811660a084015260408401511660c0830152612aae565b6060810161091482848051151582526020808201516fffffffffffffffffffffffffffffffff9081169184019190915260409182015116910152565b60006020828403121561431d57600080fd5b81516120e081613321565b80820281158282048414176109145761091461420a565b808201808211156109145761091461420a565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b6000826143b7577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b50049056fea164736f6c6343000818000a", } var USDCTokenPoolABI = USDCTokenPoolMetaData.ABI @@ -388,26 +389,26 @@ func (_USDCTokenPool *USDCTokenPoolCallerSession) GetRateLimitAdmin() (common.Ad return _USDCTokenPool.Contract.GetRateLimitAdmin(&_USDCTokenPool.CallOpts) } -func (_USDCTokenPool *USDCTokenPoolCaller) GetRemotePools(opts *bind.CallOpts, remoteChainSelector uint64) ([][]byte, error) { +func (_USDCTokenPool *USDCTokenPoolCaller) GetRemotePool(opts *bind.CallOpts, remoteChainSelector uint64) ([]byte, error) { var out []interface{} - err := _USDCTokenPool.contract.Call(opts, &out, "getRemotePools", remoteChainSelector) + err := _USDCTokenPool.contract.Call(opts, &out, "getRemotePool", remoteChainSelector) if err != nil { - return *new([][]byte), err + return *new([]byte), err } - out0 := *abi.ConvertType(out[0], new([][]byte)).(*[][]byte) + out0 := *abi.ConvertType(out[0], new([]byte)).(*[]byte) return out0, err } -func (_USDCTokenPool *USDCTokenPoolSession) GetRemotePools(remoteChainSelector uint64) ([][]byte, error) { - return _USDCTokenPool.Contract.GetRemotePools(&_USDCTokenPool.CallOpts, remoteChainSelector) +func (_USDCTokenPool *USDCTokenPoolSession) GetRemotePool(remoteChainSelector uint64) ([]byte, error) { + return _USDCTokenPool.Contract.GetRemotePool(&_USDCTokenPool.CallOpts, remoteChainSelector) } -func (_USDCTokenPool *USDCTokenPoolCallerSession) GetRemotePools(remoteChainSelector uint64) ([][]byte, error) { - return _USDCTokenPool.Contract.GetRemotePools(&_USDCTokenPool.CallOpts, remoteChainSelector) +func (_USDCTokenPool *USDCTokenPoolCallerSession) GetRemotePool(remoteChainSelector uint64) ([]byte, error) { + return _USDCTokenPool.Contract.GetRemotePool(&_USDCTokenPool.CallOpts, remoteChainSelector) } func (_USDCTokenPool *USDCTokenPoolCaller) GetRemoteToken(opts *bind.CallOpts, remoteChainSelector uint64) ([]byte, error) { @@ -520,28 +521,6 @@ func (_USDCTokenPool *USDCTokenPoolCallerSession) GetToken() (common.Address, er return _USDCTokenPool.Contract.GetToken(&_USDCTokenPool.CallOpts) } -func (_USDCTokenPool *USDCTokenPoolCaller) GetTokenDecimals(opts *bind.CallOpts) (uint8, error) { - var out []interface{} - err := _USDCTokenPool.contract.Call(opts, &out, "getTokenDecimals") - - if err != nil { - return *new(uint8), err - } - - out0 := *abi.ConvertType(out[0], new(uint8)).(*uint8) - - return out0, err - -} - -func (_USDCTokenPool *USDCTokenPoolSession) GetTokenDecimals() (uint8, error) { - return _USDCTokenPool.Contract.GetTokenDecimals(&_USDCTokenPool.CallOpts) -} - -func (_USDCTokenPool *USDCTokenPoolCallerSession) GetTokenDecimals() (uint8, error) { - return _USDCTokenPool.Contract.GetTokenDecimals(&_USDCTokenPool.CallOpts) -} - func (_USDCTokenPool *USDCTokenPoolCaller) ILocalDomainIdentifier(opts *bind.CallOpts) (uint32, error) { var out []interface{} err := _USDCTokenPool.contract.Call(opts, &out, "i_localDomainIdentifier") @@ -608,28 +587,6 @@ func (_USDCTokenPool *USDCTokenPoolCallerSession) ITokenMessenger() (common.Addr return _USDCTokenPool.Contract.ITokenMessenger(&_USDCTokenPool.CallOpts) } -func (_USDCTokenPool *USDCTokenPoolCaller) IsRemotePool(opts *bind.CallOpts, remoteChainSelector uint64, remotePoolAddress []byte) (bool, error) { - var out []interface{} - err := _USDCTokenPool.contract.Call(opts, &out, "isRemotePool", remoteChainSelector, remotePoolAddress) - - if err != nil { - return *new(bool), err - } - - out0 := *abi.ConvertType(out[0], new(bool)).(*bool) - - return out0, err - -} - -func (_USDCTokenPool *USDCTokenPoolSession) IsRemotePool(remoteChainSelector uint64, remotePoolAddress []byte) (bool, error) { - return _USDCTokenPool.Contract.IsRemotePool(&_USDCTokenPool.CallOpts, remoteChainSelector, remotePoolAddress) -} - -func (_USDCTokenPool *USDCTokenPoolCallerSession) IsRemotePool(remoteChainSelector uint64, remotePoolAddress []byte) (bool, error) { - return _USDCTokenPool.Contract.IsRemotePool(&_USDCTokenPool.CallOpts, remoteChainSelector, remotePoolAddress) -} - func (_USDCTokenPool *USDCTokenPoolCaller) IsSupportedChain(opts *bind.CallOpts, remoteChainSelector uint64) (bool, error) { var out []interface{} err := _USDCTokenPool.contract.Call(opts, &out, "isSupportedChain", remoteChainSelector) @@ -752,18 +709,6 @@ func (_USDCTokenPool *USDCTokenPoolTransactorSession) AcceptOwnership() (*types. return _USDCTokenPool.Contract.AcceptOwnership(&_USDCTokenPool.TransactOpts) } -func (_USDCTokenPool *USDCTokenPoolTransactor) AddRemotePool(opts *bind.TransactOpts, remoteChainSelector uint64, remotePoolAddress []byte) (*types.Transaction, error) { - return _USDCTokenPool.contract.Transact(opts, "addRemotePool", remoteChainSelector, remotePoolAddress) -} - -func (_USDCTokenPool *USDCTokenPoolSession) AddRemotePool(remoteChainSelector uint64, remotePoolAddress []byte) (*types.Transaction, error) { - return _USDCTokenPool.Contract.AddRemotePool(&_USDCTokenPool.TransactOpts, remoteChainSelector, remotePoolAddress) -} - -func (_USDCTokenPool *USDCTokenPoolTransactorSession) AddRemotePool(remoteChainSelector uint64, remotePoolAddress []byte) (*types.Transaction, error) { - return _USDCTokenPool.Contract.AddRemotePool(&_USDCTokenPool.TransactOpts, remoteChainSelector, remotePoolAddress) -} - func (_USDCTokenPool *USDCTokenPoolTransactor) ApplyAllowListUpdates(opts *bind.TransactOpts, removes []common.Address, adds []common.Address) (*types.Transaction, error) { return _USDCTokenPool.contract.Transact(opts, "applyAllowListUpdates", removes, adds) } @@ -776,16 +721,16 @@ func (_USDCTokenPool *USDCTokenPoolTransactorSession) ApplyAllowListUpdates(remo return _USDCTokenPool.Contract.ApplyAllowListUpdates(&_USDCTokenPool.TransactOpts, removes, adds) } -func (_USDCTokenPool *USDCTokenPoolTransactor) ApplyChainUpdates(opts *bind.TransactOpts, remoteChainSelectorsToRemove []uint64, chainsToAdd []TokenPoolChainUpdate) (*types.Transaction, error) { - return _USDCTokenPool.contract.Transact(opts, "applyChainUpdates", remoteChainSelectorsToRemove, chainsToAdd) +func (_USDCTokenPool *USDCTokenPoolTransactor) ApplyChainUpdates(opts *bind.TransactOpts, chains []TokenPoolChainUpdate) (*types.Transaction, error) { + return _USDCTokenPool.contract.Transact(opts, "applyChainUpdates", chains) } -func (_USDCTokenPool *USDCTokenPoolSession) ApplyChainUpdates(remoteChainSelectorsToRemove []uint64, chainsToAdd []TokenPoolChainUpdate) (*types.Transaction, error) { - return _USDCTokenPool.Contract.ApplyChainUpdates(&_USDCTokenPool.TransactOpts, remoteChainSelectorsToRemove, chainsToAdd) +func (_USDCTokenPool *USDCTokenPoolSession) ApplyChainUpdates(chains []TokenPoolChainUpdate) (*types.Transaction, error) { + return _USDCTokenPool.Contract.ApplyChainUpdates(&_USDCTokenPool.TransactOpts, chains) } -func (_USDCTokenPool *USDCTokenPoolTransactorSession) ApplyChainUpdates(remoteChainSelectorsToRemove []uint64, chainsToAdd []TokenPoolChainUpdate) (*types.Transaction, error) { - return _USDCTokenPool.Contract.ApplyChainUpdates(&_USDCTokenPool.TransactOpts, remoteChainSelectorsToRemove, chainsToAdd) +func (_USDCTokenPool *USDCTokenPoolTransactorSession) ApplyChainUpdates(chains []TokenPoolChainUpdate) (*types.Transaction, error) { + return _USDCTokenPool.Contract.ApplyChainUpdates(&_USDCTokenPool.TransactOpts, chains) } func (_USDCTokenPool *USDCTokenPoolTransactor) LockOrBurn(opts *bind.TransactOpts, lockOrBurnIn PoolLockOrBurnInV1) (*types.Transaction, error) { @@ -812,18 +757,6 @@ func (_USDCTokenPool *USDCTokenPoolTransactorSession) ReleaseOrMint(releaseOrMin return _USDCTokenPool.Contract.ReleaseOrMint(&_USDCTokenPool.TransactOpts, releaseOrMintIn) } -func (_USDCTokenPool *USDCTokenPoolTransactor) RemoveRemotePool(opts *bind.TransactOpts, remoteChainSelector uint64, remotePoolAddress []byte) (*types.Transaction, error) { - return _USDCTokenPool.contract.Transact(opts, "removeRemotePool", remoteChainSelector, remotePoolAddress) -} - -func (_USDCTokenPool *USDCTokenPoolSession) RemoveRemotePool(remoteChainSelector uint64, remotePoolAddress []byte) (*types.Transaction, error) { - return _USDCTokenPool.Contract.RemoveRemotePool(&_USDCTokenPool.TransactOpts, remoteChainSelector, remotePoolAddress) -} - -func (_USDCTokenPool *USDCTokenPoolTransactorSession) RemoveRemotePool(remoteChainSelector uint64, remotePoolAddress []byte) (*types.Transaction, error) { - return _USDCTokenPool.Contract.RemoveRemotePool(&_USDCTokenPool.TransactOpts, remoteChainSelector, remotePoolAddress) -} - func (_USDCTokenPool *USDCTokenPoolTransactor) SetChainRateLimiterConfig(opts *bind.TransactOpts, remoteChainSelector uint64, outboundConfig RateLimiterConfig, inboundConfig RateLimiterConfig) (*types.Transaction, error) { return _USDCTokenPool.contract.Transact(opts, "setChainRateLimiterConfig", remoteChainSelector, outboundConfig, inboundConfig) } @@ -836,18 +769,6 @@ func (_USDCTokenPool *USDCTokenPoolTransactorSession) SetChainRateLimiterConfig( return _USDCTokenPool.Contract.SetChainRateLimiterConfig(&_USDCTokenPool.TransactOpts, remoteChainSelector, outboundConfig, inboundConfig) } -func (_USDCTokenPool *USDCTokenPoolTransactor) SetChainRateLimiterConfigs(opts *bind.TransactOpts, remoteChainSelectors []uint64, outboundConfigs []RateLimiterConfig, inboundConfigs []RateLimiterConfig) (*types.Transaction, error) { - return _USDCTokenPool.contract.Transact(opts, "setChainRateLimiterConfigs", remoteChainSelectors, outboundConfigs, inboundConfigs) -} - -func (_USDCTokenPool *USDCTokenPoolSession) SetChainRateLimiterConfigs(remoteChainSelectors []uint64, outboundConfigs []RateLimiterConfig, inboundConfigs []RateLimiterConfig) (*types.Transaction, error) { - return _USDCTokenPool.Contract.SetChainRateLimiterConfigs(&_USDCTokenPool.TransactOpts, remoteChainSelectors, outboundConfigs, inboundConfigs) -} - -func (_USDCTokenPool *USDCTokenPoolTransactorSession) SetChainRateLimiterConfigs(remoteChainSelectors []uint64, outboundConfigs []RateLimiterConfig, inboundConfigs []RateLimiterConfig) (*types.Transaction, error) { - return _USDCTokenPool.Contract.SetChainRateLimiterConfigs(&_USDCTokenPool.TransactOpts, remoteChainSelectors, outboundConfigs, inboundConfigs) -} - func (_USDCTokenPool *USDCTokenPoolTransactor) SetDomains(opts *bind.TransactOpts, domains []USDCTokenPoolDomainUpdate) (*types.Transaction, error) { return _USDCTokenPool.contract.Transact(opts, "setDomains", domains) } @@ -872,6 +793,18 @@ func (_USDCTokenPool *USDCTokenPoolTransactorSession) SetRateLimitAdmin(rateLimi return _USDCTokenPool.Contract.SetRateLimitAdmin(&_USDCTokenPool.TransactOpts, rateLimitAdmin) } +func (_USDCTokenPool *USDCTokenPoolTransactor) SetRemotePool(opts *bind.TransactOpts, remoteChainSelector uint64, remotePoolAddress []byte) (*types.Transaction, error) { + return _USDCTokenPool.contract.Transact(opts, "setRemotePool", remoteChainSelector, remotePoolAddress) +} + +func (_USDCTokenPool *USDCTokenPoolSession) SetRemotePool(remoteChainSelector uint64, remotePoolAddress []byte) (*types.Transaction, error) { + return _USDCTokenPool.Contract.SetRemotePool(&_USDCTokenPool.TransactOpts, remoteChainSelector, remotePoolAddress) +} + +func (_USDCTokenPool *USDCTokenPoolTransactorSession) SetRemotePool(remoteChainSelector uint64, remotePoolAddress []byte) (*types.Transaction, error) { + return _USDCTokenPool.Contract.SetRemotePool(&_USDCTokenPool.TransactOpts, remoteChainSelector, remotePoolAddress) +} + func (_USDCTokenPool *USDCTokenPoolTransactor) SetRouter(opts *bind.TransactOpts, newRouter common.Address) (*types.Transaction, error) { return _USDCTokenPool.contract.Transact(opts, "setRouter", newRouter) } @@ -2756,8 +2689,8 @@ func (_USDCTokenPool *USDCTokenPoolFilterer) ParseReleased(log types.Log) (*USDC return event, nil } -type USDCTokenPoolRemotePoolAddedIterator struct { - Event *USDCTokenPoolRemotePoolAdded +type USDCTokenPoolRemotePoolSetIterator struct { + Event *USDCTokenPoolRemotePoolSet contract *bind.BoundContract event string @@ -2768,7 +2701,7 @@ type USDCTokenPoolRemotePoolAddedIterator struct { fail error } -func (it *USDCTokenPoolRemotePoolAddedIterator) Next() bool { +func (it *USDCTokenPoolRemotePoolSetIterator) Next() bool { if it.fail != nil { return false @@ -2777,7 +2710,7 @@ func (it *USDCTokenPoolRemotePoolAddedIterator) Next() bool { if it.done { select { case log := <-it.logs: - it.Event = new(USDCTokenPoolRemotePoolAdded) + it.Event = new(USDCTokenPoolRemotePoolSet) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -2792,7 +2725,7 @@ func (it *USDCTokenPoolRemotePoolAddedIterator) Next() bool { select { case log := <-it.logs: - it.Event = new(USDCTokenPoolRemotePoolAdded) + it.Event = new(USDCTokenPoolRemotePoolSet) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -2807,43 +2740,44 @@ func (it *USDCTokenPoolRemotePoolAddedIterator) Next() bool { } } -func (it *USDCTokenPoolRemotePoolAddedIterator) Error() error { +func (it *USDCTokenPoolRemotePoolSetIterator) Error() error { return it.fail } -func (it *USDCTokenPoolRemotePoolAddedIterator) Close() error { +func (it *USDCTokenPoolRemotePoolSetIterator) Close() error { it.sub.Unsubscribe() return nil } -type USDCTokenPoolRemotePoolAdded struct { +type USDCTokenPoolRemotePoolSet struct { RemoteChainSelector uint64 + PreviousPoolAddress []byte RemotePoolAddress []byte Raw types.Log } -func (_USDCTokenPool *USDCTokenPoolFilterer) FilterRemotePoolAdded(opts *bind.FilterOpts, remoteChainSelector []uint64) (*USDCTokenPoolRemotePoolAddedIterator, error) { +func (_USDCTokenPool *USDCTokenPoolFilterer) FilterRemotePoolSet(opts *bind.FilterOpts, remoteChainSelector []uint64) (*USDCTokenPoolRemotePoolSetIterator, error) { var remoteChainSelectorRule []interface{} for _, remoteChainSelectorItem := range remoteChainSelector { remoteChainSelectorRule = append(remoteChainSelectorRule, remoteChainSelectorItem) } - logs, sub, err := _USDCTokenPool.contract.FilterLogs(opts, "RemotePoolAdded", remoteChainSelectorRule) + logs, sub, err := _USDCTokenPool.contract.FilterLogs(opts, "RemotePoolSet", remoteChainSelectorRule) if err != nil { return nil, err } - return &USDCTokenPoolRemotePoolAddedIterator{contract: _USDCTokenPool.contract, event: "RemotePoolAdded", logs: logs, sub: sub}, nil + return &USDCTokenPoolRemotePoolSetIterator{contract: _USDCTokenPool.contract, event: "RemotePoolSet", logs: logs, sub: sub}, nil } -func (_USDCTokenPool *USDCTokenPoolFilterer) WatchRemotePoolAdded(opts *bind.WatchOpts, sink chan<- *USDCTokenPoolRemotePoolAdded, remoteChainSelector []uint64) (event.Subscription, error) { +func (_USDCTokenPool *USDCTokenPoolFilterer) WatchRemotePoolSet(opts *bind.WatchOpts, sink chan<- *USDCTokenPoolRemotePoolSet, remoteChainSelector []uint64) (event.Subscription, error) { var remoteChainSelectorRule []interface{} for _, remoteChainSelectorItem := range remoteChainSelector { remoteChainSelectorRule = append(remoteChainSelectorRule, remoteChainSelectorItem) } - logs, sub, err := _USDCTokenPool.contract.WatchLogs(opts, "RemotePoolAdded", remoteChainSelectorRule) + logs, sub, err := _USDCTokenPool.contract.WatchLogs(opts, "RemotePoolSet", remoteChainSelectorRule) if err != nil { return nil, err } @@ -2853,8 +2787,8 @@ func (_USDCTokenPool *USDCTokenPoolFilterer) WatchRemotePoolAdded(opts *bind.Wat select { case log := <-logs: - event := new(USDCTokenPoolRemotePoolAdded) - if err := _USDCTokenPool.contract.UnpackLog(event, "RemotePoolAdded", log); err != nil { + event := new(USDCTokenPoolRemotePoolSet) + if err := _USDCTokenPool.contract.UnpackLog(event, "RemotePoolSet", log); err != nil { return err } event.Raw = log @@ -2875,137 +2809,9 @@ func (_USDCTokenPool *USDCTokenPoolFilterer) WatchRemotePoolAdded(opts *bind.Wat }), nil } -func (_USDCTokenPool *USDCTokenPoolFilterer) ParseRemotePoolAdded(log types.Log) (*USDCTokenPoolRemotePoolAdded, error) { - event := new(USDCTokenPoolRemotePoolAdded) - if err := _USDCTokenPool.contract.UnpackLog(event, "RemotePoolAdded", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -type USDCTokenPoolRemotePoolRemovedIterator struct { - Event *USDCTokenPoolRemotePoolRemoved - - contract *bind.BoundContract - event string - - logs chan types.Log - sub ethereum.Subscription - done bool - fail error -} - -func (it *USDCTokenPoolRemotePoolRemovedIterator) Next() bool { - - if it.fail != nil { - return false - } - - if it.done { - select { - case log := <-it.logs: - it.Event = new(USDCTokenPoolRemotePoolRemoved) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - default: - return false - } - } - - select { - case log := <-it.logs: - it.Event = new(USDCTokenPoolRemotePoolRemoved) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - case err := <-it.sub.Err(): - it.done = true - it.fail = err - return it.Next() - } -} - -func (it *USDCTokenPoolRemotePoolRemovedIterator) Error() error { - return it.fail -} - -func (it *USDCTokenPoolRemotePoolRemovedIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -type USDCTokenPoolRemotePoolRemoved struct { - RemoteChainSelector uint64 - RemotePoolAddress []byte - Raw types.Log -} - -func (_USDCTokenPool *USDCTokenPoolFilterer) FilterRemotePoolRemoved(opts *bind.FilterOpts, remoteChainSelector []uint64) (*USDCTokenPoolRemotePoolRemovedIterator, error) { - - var remoteChainSelectorRule []interface{} - for _, remoteChainSelectorItem := range remoteChainSelector { - remoteChainSelectorRule = append(remoteChainSelectorRule, remoteChainSelectorItem) - } - - logs, sub, err := _USDCTokenPool.contract.FilterLogs(opts, "RemotePoolRemoved", remoteChainSelectorRule) - if err != nil { - return nil, err - } - return &USDCTokenPoolRemotePoolRemovedIterator{contract: _USDCTokenPool.contract, event: "RemotePoolRemoved", logs: logs, sub: sub}, nil -} - -func (_USDCTokenPool *USDCTokenPoolFilterer) WatchRemotePoolRemoved(opts *bind.WatchOpts, sink chan<- *USDCTokenPoolRemotePoolRemoved, remoteChainSelector []uint64) (event.Subscription, error) { - - var remoteChainSelectorRule []interface{} - for _, remoteChainSelectorItem := range remoteChainSelector { - remoteChainSelectorRule = append(remoteChainSelectorRule, remoteChainSelectorItem) - } - - logs, sub, err := _USDCTokenPool.contract.WatchLogs(opts, "RemotePoolRemoved", remoteChainSelectorRule) - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - - event := new(USDCTokenPoolRemotePoolRemoved) - if err := _USDCTokenPool.contract.UnpackLog(event, "RemotePoolRemoved", log); err != nil { - return err - } - event.Raw = log - - select { - case sink <- event: - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - } - }), nil -} - -func (_USDCTokenPool *USDCTokenPoolFilterer) ParseRemotePoolRemoved(log types.Log) (*USDCTokenPoolRemotePoolRemoved, error) { - event := new(USDCTokenPoolRemotePoolRemoved) - if err := _USDCTokenPool.contract.UnpackLog(event, "RemotePoolRemoved", log); err != nil { +func (_USDCTokenPool *USDCTokenPoolFilterer) ParseRemotePoolSet(log types.Log) (*USDCTokenPoolRemotePoolSet, error) { + event := new(USDCTokenPoolRemotePoolSet) + if err := _USDCTokenPool.contract.UnpackLog(event, "RemotePoolSet", log); err != nil { return nil, err } event.Raw = log @@ -3279,10 +3085,8 @@ func (_USDCTokenPool *USDCTokenPool) ParseLog(log types.Log) (generated.AbigenLo return _USDCTokenPool.ParseRateLimitAdminSet(log) case _USDCTokenPool.abi.Events["Released"].ID: return _USDCTokenPool.ParseReleased(log) - case _USDCTokenPool.abi.Events["RemotePoolAdded"].ID: - return _USDCTokenPool.ParseRemotePoolAdded(log) - case _USDCTokenPool.abi.Events["RemotePoolRemoved"].ID: - return _USDCTokenPool.ParseRemotePoolRemoved(log) + case _USDCTokenPool.abi.Events["RemotePoolSet"].ID: + return _USDCTokenPool.ParseRemotePoolSet(log) case _USDCTokenPool.abi.Events["RouterUpdated"].ID: return _USDCTokenPool.ParseRouterUpdated(log) case _USDCTokenPool.abi.Events["TokensConsumed"].ID: @@ -3353,12 +3157,8 @@ func (USDCTokenPoolReleased) Topic() common.Hash { return common.HexToHash("0x2d87480f50083e2b2759522a8fdda59802650a8055e609a7772cf70c07748f52") } -func (USDCTokenPoolRemotePoolAdded) Topic() common.Hash { - return common.HexToHash("0x7d628c9a1796743d365ab521a8b2a4686e419b3269919dc9145ea2ce853b54ea") -} - -func (USDCTokenPoolRemotePoolRemoved) Topic() common.Hash { - return common.HexToHash("0x52d00ee4d9bd51b40168f2afc5848837288ce258784ad914278791464b3f4d76") +func (USDCTokenPoolRemotePoolSet) Topic() common.Hash { + return common.HexToHash("0xdb4d6220746a38cbc5335f7e108f7de80f482f4d23350253dfd0917df75a14bf") } func (USDCTokenPoolRouterUpdated) Topic() common.Hash { @@ -3388,7 +3188,7 @@ type USDCTokenPoolInterface interface { GetRateLimitAdmin(opts *bind.CallOpts) (common.Address, error) - GetRemotePools(opts *bind.CallOpts, remoteChainSelector uint64) ([][]byte, error) + GetRemotePool(opts *bind.CallOpts, remoteChainSelector uint64) ([]byte, error) GetRemoteToken(opts *bind.CallOpts, remoteChainSelector uint64) ([]byte, error) @@ -3400,16 +3200,12 @@ type USDCTokenPoolInterface interface { GetToken(opts *bind.CallOpts) (common.Address, error) - GetTokenDecimals(opts *bind.CallOpts) (uint8, error) - ILocalDomainIdentifier(opts *bind.CallOpts) (uint32, error) IMessageTransmitter(opts *bind.CallOpts) (common.Address, error) ITokenMessenger(opts *bind.CallOpts) (common.Address, error) - IsRemotePool(opts *bind.CallOpts, remoteChainSelector uint64, remotePoolAddress []byte) (bool, error) - IsSupportedChain(opts *bind.CallOpts, remoteChainSelector uint64) (bool, error) IsSupportedToken(opts *bind.CallOpts, token common.Address) (bool, error) @@ -3422,26 +3218,22 @@ type USDCTokenPoolInterface interface { AcceptOwnership(opts *bind.TransactOpts) (*types.Transaction, error) - AddRemotePool(opts *bind.TransactOpts, remoteChainSelector uint64, remotePoolAddress []byte) (*types.Transaction, error) - ApplyAllowListUpdates(opts *bind.TransactOpts, removes []common.Address, adds []common.Address) (*types.Transaction, error) - ApplyChainUpdates(opts *bind.TransactOpts, remoteChainSelectorsToRemove []uint64, chainsToAdd []TokenPoolChainUpdate) (*types.Transaction, error) + ApplyChainUpdates(opts *bind.TransactOpts, chains []TokenPoolChainUpdate) (*types.Transaction, error) LockOrBurn(opts *bind.TransactOpts, lockOrBurnIn PoolLockOrBurnInV1) (*types.Transaction, error) ReleaseOrMint(opts *bind.TransactOpts, releaseOrMintIn PoolReleaseOrMintInV1) (*types.Transaction, error) - RemoveRemotePool(opts *bind.TransactOpts, remoteChainSelector uint64, remotePoolAddress []byte) (*types.Transaction, error) - SetChainRateLimiterConfig(opts *bind.TransactOpts, remoteChainSelector uint64, outboundConfig RateLimiterConfig, inboundConfig RateLimiterConfig) (*types.Transaction, error) - SetChainRateLimiterConfigs(opts *bind.TransactOpts, remoteChainSelectors []uint64, outboundConfigs []RateLimiterConfig, inboundConfigs []RateLimiterConfig) (*types.Transaction, error) - SetDomains(opts *bind.TransactOpts, domains []USDCTokenPoolDomainUpdate) (*types.Transaction, error) SetRateLimitAdmin(opts *bind.TransactOpts, rateLimitAdmin common.Address) (*types.Transaction, error) + SetRemotePool(opts *bind.TransactOpts, remoteChainSelector uint64, remotePoolAddress []byte) (*types.Transaction, error) + SetRouter(opts *bind.TransactOpts, newRouter common.Address) (*types.Transaction, error) TransferOwnership(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) @@ -3536,17 +3328,11 @@ type USDCTokenPoolInterface interface { ParseReleased(log types.Log) (*USDCTokenPoolReleased, error) - FilterRemotePoolAdded(opts *bind.FilterOpts, remoteChainSelector []uint64) (*USDCTokenPoolRemotePoolAddedIterator, error) - - WatchRemotePoolAdded(opts *bind.WatchOpts, sink chan<- *USDCTokenPoolRemotePoolAdded, remoteChainSelector []uint64) (event.Subscription, error) - - ParseRemotePoolAdded(log types.Log) (*USDCTokenPoolRemotePoolAdded, error) - - FilterRemotePoolRemoved(opts *bind.FilterOpts, remoteChainSelector []uint64) (*USDCTokenPoolRemotePoolRemovedIterator, error) + FilterRemotePoolSet(opts *bind.FilterOpts, remoteChainSelector []uint64) (*USDCTokenPoolRemotePoolSetIterator, error) - WatchRemotePoolRemoved(opts *bind.WatchOpts, sink chan<- *USDCTokenPoolRemotePoolRemoved, remoteChainSelector []uint64) (event.Subscription, error) + WatchRemotePoolSet(opts *bind.WatchOpts, sink chan<- *USDCTokenPoolRemotePoolSet, remoteChainSelector []uint64) (event.Subscription, error) - ParseRemotePoolRemoved(log types.Log) (*USDCTokenPoolRemotePoolRemoved, error) + ParseRemotePoolSet(log types.Log) (*USDCTokenPoolRemotePoolSet, error) FilterRouterUpdated(opts *bind.FilterOpts) (*USDCTokenPoolRouterUpdatedIterator, error) diff --git a/core/gethwrappers/ccip/generated/weth9/weth9.go b/core/gethwrappers/ccip/generated/weth9/weth9.go index cab454b7c23..50d0aa23f73 100644 --- a/core/gethwrappers/ccip/generated/weth9/weth9.go +++ b/core/gethwrappers/ccip/generated/weth9/weth9.go @@ -32,7 +32,7 @@ var ( var WETH9MetaData = &bind.MetaData{ ABI: "[{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"src\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"guy\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"wad\",\"type\":\"uint256\"}],\"name\":\"Approval\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"dst\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"wad\",\"type\":\"uint256\"}],\"name\":\"Deposit\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"src\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"dst\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"wad\",\"type\":\"uint256\"}],\"name\":\"Transfer\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"src\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"wad\",\"type\":\"uint256\"}],\"name\":\"Withdrawal\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"allowance\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"guy\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"wad\",\"type\":\"uint256\"}],\"name\":\"approve\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"decimals\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"deposit\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"name\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"symbol\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"totalSupply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"dst\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"wad\",\"type\":\"uint256\"}],\"name\":\"transfer\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"src\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"dst\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"wad\",\"type\":\"uint256\"}],\"name\":\"transferFrom\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"wad\",\"type\":\"uint256\"}],\"name\":\"withdraw\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}]", - Bin: "0x60806040523461011457610014600054610119565b601f81116100cb575b507f577261707065642045746865720000000000000000000000000000000000001a60005560015461004e90610119565b601f8111610081575b6008630ae8aa8960e31b016001556002805460ff19166012179055604051610a5a90816101548239f35b6001600052601f0160051c7fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf6908101905b8181106100bf5750610057565b600081556001016100b2565b60008052601f0160051c7f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e563908101905b818110610108575061001d565b600081556001016100fb565b600080fd5b90600182811c92168015610149575b602083101461013357565b634e487b7160e01b600052602260045260246000fd5b91607f169161012856fe60806040526004361015610062575b361561001957600080fd5b33600052600360205260406000206100323482546108a0565b90556040513481527fe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c60203392a2005b60003560e01c806306fdde0314610696578063095ea7b3146105ef57806318160ddd146105b557806323b872dd146105685780632e1a7d4d146104aa578063313ce5671461046b57806370a082311461040657806395d89b4114610208578063a9059cbb146101b8578063d0e30db0146101755763dd62ed3e0361000e57346101705760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101705761011761081e565b73ffffffffffffffffffffffffffffffffffffffff610134610841565b9116600052600460205273ffffffffffffffffffffffffffffffffffffffff604060002091166000526020526020604060002054604051908152f35b600080fd5b60007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101705733600052600360205260406000206100323482546108a0565b346101705760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101705760206101fe6101f461081e565b60243590336108ad565b6040519015158152f35b346101705760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610170576000604051908091600154928360011c600185169485156103fc575b6020821086146103cf57839495828552908160001461036f57506001146102f6575b5003601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff8111828210176102c9576102c59250604052604051918291826107b6565b0390f35b6024837f4e487b710000000000000000000000000000000000000000000000000000000081526041600452fd5b600185528491507fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf65b81831061035357505081016020017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0610275565b602091935080600191548385880101520191019091839261031f565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660208581019190915291151560051b840190910191507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09050610275565b6024857f4e487b710000000000000000000000000000000000000000000000000000000081526022600452fd5b90607f1690610253565b346101705760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101705773ffffffffffffffffffffffffffffffffffffffff61045261081e565b1660005260036020526020604060002054604051908152f35b346101705760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261017057602060ff60025416604051908152f35b346101705760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261017057600435336000526003602052806040600020541061017057336000526003602052604060002061050a828254610864565b9055806000811561055f575b600080809381933390f115610553576040519081527f7fcf532c15f0a6db0bd6d0e038bea71d30d808c7d98cb3bf7268a95bf5081b6560203392a2005b6040513d6000823e3d90fd5b506108fc610516565b346101705760607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101705760206101fe6105a461081e565b6105ac610841565b604435916108ad565b346101705760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261017057602047604051908152f35b346101705760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101705761062661081e565b73ffffffffffffffffffffffffffffffffffffffff6024359133600052600460205260406000208282166000526020528260406000205560405192835216907f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560203392a3602060405160018152f35b346101705760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101705760006040519080918154928360011c600185169485156107ac575b6020821086146103cf57839495828552908160001461036f5750600114610751575003601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff8111828210176102c9576102c59250604052604051918291826107b6565b848052602085208592505b81831061079057505081016020017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0610275565b602091935080600191548385880101520191019091839261075c565b90607f16906106e0565b9190916020815282519283602083015260005b8481106108085750507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8460006040809697860101520116010190565b80602080928401015160408286010152016107c9565b6004359073ffffffffffffffffffffffffffffffffffffffff8216820361017057565b6024359073ffffffffffffffffffffffffffffffffffffffff8216820361017057565b9190820391821161087157565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b9190820180921161087157565b73ffffffffffffffffffffffffffffffffffffffff16908160005260036020528260406000205410610170573382141580610a03575b610963575b602073ffffffffffffffffffffffffffffffffffffffff7fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9284600052600383526040600020610939878254610864565b90551693846000526003825260406000206109558282546108a0565b9055604051908152a3600190565b816000526004602052604060002073ffffffffffffffffffffffffffffffffffffffff3316600052602052826040600020541061017057602073ffffffffffffffffffffffffffffffffffffffff7fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9284600052600483526040600020823316600052835260406000206109f8878254610864565b9055925050506108e8565b50816000526004602052604060002073ffffffffffffffffffffffffffffffffffffffff33166000526020526fffffffffffffffffffffffffffffffff60406000205414156108e356fea164736f6c634300081a000a", + Bin: "0x60c0604052600d60809081526c2bb930b83832b21022ba3432b960991b60a05260009061002c9082610116565b506040805180820190915260048152630ae8aa8960e31b60208201526001906100559082610116565b506002805460ff1916601217905534801561006f57600080fd5b506101d5565b634e487b7160e01b600052604160045260246000fd5b600181811c9082168061009f57607f821691505b6020821081036100bf57634e487b7160e01b600052602260045260246000fd5b50919050565b601f821115610111576000816000526020600020601f850160051c810160208610156100ee5750805b601f850160051c820191505b8181101561010d578281556001016100fa565b5050505b505050565b81516001600160401b0381111561012f5761012f610075565b6101438161013d845461008b565b846100c5565b602080601f83116001811461017857600084156101605750858301515b600019600386901b1c1916600185901b17855561010d565b600085815260208120601f198616915b828110156101a757888601518255948401946001909101908401610188565b50858210156101c55787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b6108ad806101e46000396000f3fe6080604052600436106100c05760003560e01c8063313ce56711610074578063a9059cbb1161004e578063a9059cbb146101fa578063d0e30db01461021a578063dd62ed3e1461022257600080fd5b8063313ce5671461018c57806370a08231146101b857806395d89b41146101e557600080fd5b806318160ddd116100a557806318160ddd1461012f57806323b872dd1461014c5780632e1a7d4d1461016c57600080fd5b806306fdde03146100d4578063095ea7b3146100ff57600080fd5b366100cf576100cd61025a565b005b600080fd5b3480156100e057600080fd5b506100e96102b5565b6040516100f69190610695565b60405180910390f35b34801561010b57600080fd5b5061011f61011a36600461072b565b610343565b60405190151581526020016100f6565b34801561013b57600080fd5b50475b6040519081526020016100f6565b34801561015857600080fd5b5061011f610167366004610755565b6103bd565b34801561017857600080fd5b506100cd610187366004610791565b6105c4565b34801561019857600080fd5b506002546101a69060ff1681565b60405160ff90911681526020016100f6565b3480156101c457600080fd5b5061013e6101d33660046107aa565b60036020526000908152604090205481565b3480156101f157600080fd5b506100e961066a565b34801561020657600080fd5b5061011f61021536600461072b565b610677565b6100cd61068b565b34801561022e57600080fd5b5061013e61023d3660046107c5565b600460209081526000928352604080842090915290825290205481565b3360009081526003602052604081208054349290610279908490610827565b909155505060405134815233907fe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c9060200160405180910390a2565b600080546102c29061083a565b80601f01602080910402602001604051908101604052809291908181526020018280546102ee9061083a565b801561033b5780601f106103105761010080835404028352916020019161033b565b820191906000526020600020905b81548152906001019060200180831161031e57829003601f168201915b505050505081565b33600081815260046020908152604080832073ffffffffffffffffffffffffffffffffffffffff8716808552925280832085905551919290917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925906103ab9086815260200190565b60405180910390a35060015b92915050565b73ffffffffffffffffffffffffffffffffffffffff83166000908152600360205260408120548211156103ef57600080fd5b73ffffffffffffffffffffffffffffffffffffffff84163314801590610455575073ffffffffffffffffffffffffffffffffffffffff841660009081526004602090815260408083203384529091529020546fffffffffffffffffffffffffffffffff14155b156104dd5773ffffffffffffffffffffffffffffffffffffffff8416600090815260046020908152604080832033845290915290205482111561049757600080fd5b73ffffffffffffffffffffffffffffffffffffffff84166000908152600460209081526040808320338452909152812080548492906104d790849061088d565b90915550505b73ffffffffffffffffffffffffffffffffffffffff84166000908152600360205260408120805484929061051290849061088d565b909155505073ffffffffffffffffffffffffffffffffffffffff83166000908152600360205260408120805484929061054c908490610827565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040516105b291815260200190565b60405180910390a35060019392505050565b336000908152600360205260409020548111156105e057600080fd5b33600090815260036020526040812080548392906105ff90849061088d565b9091555050604051339082156108fc029083906000818181858888f19350505050158015610631573d6000803e3d6000fd5b5060405181815233907f7fcf532c15f0a6db0bd6d0e038bea71d30d808c7d98cb3bf7268a95bf5081b659060200160405180910390a250565b600180546102c29061083a565b60006106843384846103bd565b9392505050565b61069361025a565b565b60006020808352835180602085015260005b818110156106c3578581018301518582016040015282016106a7565b5060006040828601015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8301168501019250505092915050565b803573ffffffffffffffffffffffffffffffffffffffff8116811461072657600080fd5b919050565b6000806040838503121561073e57600080fd5b61074783610702565b946020939093013593505050565b60008060006060848603121561076a57600080fd5b61077384610702565b925061078160208501610702565b9150604084013590509250925092565b6000602082840312156107a357600080fd5b5035919050565b6000602082840312156107bc57600080fd5b61068482610702565b600080604083850312156107d857600080fd5b6107e183610702565b91506107ef60208401610702565b90509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b808201808211156103b7576103b76107f8565b600181811c9082168061084e57607f821691505b602082108103610887577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b818103818111156103b7576103b76107f856fea164736f6c6343000818000a", } var WETH9ABI = WETH9MetaData.ABI diff --git a/core/gethwrappers/ccip/generation/generated-wrapper-dependency-versions-do-not-edit.txt b/core/gethwrappers/ccip/generation/generated-wrapper-dependency-versions-do-not-edit.txt index 1c28df496d4..47aeb6db587 100644 --- a/core/gethwrappers/ccip/generation/generated-wrapper-dependency-versions-do-not-edit.txt +++ b/core/gethwrappers/ccip/generation/generated-wrapper-dependency-versions-do-not-edit.txt @@ -1,32 +1,32 @@ GETH_VERSION: 1.14.11 -burn_from_mint_token_pool: ../../../contracts/solc/v0.8.26/BurnFromMintTokenPool/BurnFromMintTokenPool.abi ../../../contracts/solc/v0.8.26/BurnFromMintTokenPool/BurnFromMintTokenPool.bin 54c6b5d460bc32a5c5cdde325e40c402b6c9b93b1dc8f3299cba67664c81e98f -burn_mint_token_pool: ../../../contracts/solc/v0.8.26/BurnMintTokenPool/BurnMintTokenPool.abi ../../../contracts/solc/v0.8.26/BurnMintTokenPool/BurnMintTokenPool.bin b88b73b703eaf05686878ca38810c9bbd039d2d00a42462cfb66af6e5a5a9383 -burn_with_from_mint_token_pool: ../../../contracts/solc/v0.8.26/BurnWithFromMintTokenPool/BurnWithFromMintTokenPool.abi ../../../contracts/solc/v0.8.26/BurnWithFromMintTokenPool/BurnWithFromMintTokenPool.bin a65953e86432c1b8317617ccd8b49888f8aee811dd2a064eaf64041c9901dadc -ccip_encoding_utils: ../../../contracts/solc/v0.8.26/ICCIPEncodingUtils/ICCIPEncodingUtils.abi ../../../contracts/solc/v0.8.26/ICCIPEncodingUtils/ICCIPEncodingUtils.bin 9971fc93c34442a0989570d3dab90a125de31e6e60754ad972807ce6ad4dfba0 -ccip_home: ../../../contracts/solc/v0.8.26/CCIPHome/CCIPHome.abi ../../../contracts/solc/v0.8.26/CCIPHome/CCIPHome.bin 8406cd785db043c667b93a5ce300316098d619fe15c8c9ecbd7182b0964c137e -ccip_reader_tester: ../../../contracts/solc/v0.8.26/CCIPReaderTester/CCIPReaderTester.abi ../../../contracts/solc/v0.8.26/CCIPReaderTester/CCIPReaderTester.bin 5566701183b0eeb93cf12d08dcedc9c16b52aa51029ca13f4749021735439744 -ether_sender_receiver: ../../../contracts/solc/v0.8.26/EtherSenderReceiver/EtherSenderReceiver.abi ../../../contracts/solc/v0.8.26/EtherSenderReceiver/EtherSenderReceiver.bin fbab164d4d69a76ee95518717a9a2356fd1a64475dbe651ba777f1a259b5e450 -fee_quoter: ../../../contracts/solc/v0.8.26/FeeQuoter/FeeQuoter.abi ../../../contracts/solc/v0.8.26/FeeQuoter/FeeQuoter.bin 4141d3a6ca47d7fd8b62ec0be85296ac30e717f29b8aaa88fa6954579fd92e3a -lock_release_token_pool: ../../../contracts/solc/v0.8.26/LockReleaseTokenPool/LockReleaseTokenPool.abi ../../../contracts/solc/v0.8.26/LockReleaseTokenPool/LockReleaseTokenPool.bin b4624ddc3510fd6ff0c0d1061d95bef8802c7d857202de40ed08e77eca568b1c -maybe_revert_message_receiver: ../../../contracts/solc/v0.8.26/MaybeRevertMessageReceiver/MaybeRevertMessageReceiver.abi ../../../contracts/solc/v0.8.26/MaybeRevertMessageReceiver/MaybeRevertMessageReceiver.bin 8465ccd6e86136682ff4f650ce7daa67edee77832466452bc2d8030fcd1456e0 -message_hasher: ../../../contracts/solc/v0.8.26/MessageHasher/MessageHasher.abi ../../../contracts/solc/v0.8.26/MessageHasher/MessageHasher.bin 802372d2f3366bc909d75a1b1c319f0bc86f3f9c581630038a1a0922d2cacd42 -mock_usdc_token_messenger: ../../../contracts/solc/v0.8.26/MockE2EUSDCTokenMessenger/MockE2EUSDCTokenMessenger.abi ../../../contracts/solc/v0.8.26/MockE2EUSDCTokenMessenger/MockE2EUSDCTokenMessenger.bin 0c93c386ecb27e4fa3247a6b8cacb8019fe73b04710c72e3f6ecbe0abbcd0261 -mock_usdc_token_transmitter: ../../../contracts/solc/v0.8.26/MockE2EUSDCTransmitter/MockE2EUSDCTransmitter.abi ../../../contracts/solc/v0.8.26/MockE2EUSDCTransmitter/MockE2EUSDCTransmitter.bin 7fd9cddabff0243103e1009e2b0252f68245efe99adfff64061bed4318a9b625 -mock_v3_aggregator_contract: ../../../contracts/solc/v0.8.26/MockV3Aggregator/MockV3Aggregator.abi ../../../contracts/solc/v0.8.26/MockV3Aggregator/MockV3Aggregator.bin ec9f4f023f34789f3d53f80c6cbd9587746e2392095ae2e31c02de96ca201a82 -multi_aggregate_rate_limiter: ../../../contracts/solc/v0.8.26/MultiAggregateRateLimiter/MultiAggregateRateLimiter.abi ../../../contracts/solc/v0.8.26/MultiAggregateRateLimiter/MultiAggregateRateLimiter.bin 167ac2f314daf0b51c416b0161750e82a573fcb4f05fabf760a74f4da9a41bf7 -multi_ocr3_helper: ../../../contracts/solc/v0.8.26/MultiOCR3Helper/MultiOCR3Helper.abi ../../../contracts/solc/v0.8.26/MultiOCR3Helper/MultiOCR3Helper.bin 8cf784799522df0ce73dc06e9842b95bf59a9f5b21126e7e022785ca6f806f2b -nonce_manager: ../../../contracts/solc/v0.8.26/NonceManager/NonceManager.abi ../../../contracts/solc/v0.8.26/NonceManager/NonceManager.bin 238ac7c7a8336ed31dae0b6ef9e253fca2ca5ff39b67b3e38567bf745555d6fe -offramp: ../../../contracts/solc/v0.8.26/OffRamp/OffRamp.abi ../../../contracts/solc/v0.8.26/OffRamp/OffRamp.bin 5c446e48ab45dbaaf438ba07a54595528a5a04a6fc1ecf849c7603c594b4fa61 -onramp: ../../../contracts/solc/v0.8.26/OnRamp/OnRamp.abi ../../../contracts/solc/v0.8.26/OnRamp/OnRamp.bin 0fe8873e4bec7bd2270d84dce9195fe81b0d1982f5e502cf92381f4ecb9f01be -ping_pong_demo: ../../../contracts/solc/v0.8.26/PingPongDemo/PingPongDemo.abi ../../../contracts/solc/v0.8.26/PingPongDemo/PingPongDemo.bin dd78bee8e0b89f659e9ee61b7fc8a78bb734f2469ff18d83b9ab2c61ccf213ba -registry_module_owner_custom: ../../../contracts/solc/v0.8.26/RegistryModuleOwnerCustom/RegistryModuleOwnerCustom.abi ../../../contracts/solc/v0.8.26/RegistryModuleOwnerCustom/RegistryModuleOwnerCustom.bin 85ce7f022c5c204cf97ba4c05ac55b4fe09955c8ac7d2cb10df3b0548b4ccca0 -report_codec: ../../../contracts/solc/v0.8.26/ReportCodec/ReportCodec.abi ../../../contracts/solc/v0.8.26/ReportCodec/ReportCodec.bin b7105317723227338fb66d803e007696fb2bb3d0e9ebf9416c42c6e5d549e9ac -rmn_home: ../../../contracts/solc/v0.8.26/RMNHome/RMNHome.abi ../../../contracts/solc/v0.8.26/RMNHome/RMNHome.bin cf0c4f6be2fe80f0091f8fc1aa3e8d2f6e9e30f308a1b6d62c9ff65218822b85 -rmn_proxy_contract: ../../../contracts/solc/v0.8.26/ARMProxy/ARMProxy.abi ../../../contracts/solc/v0.8.26/ARMProxy/ARMProxy.bin 83a5c20d31cf4451f5962a744f56ba5221763151b3cc0d3e7b5d2988bcfb82eb -rmn_remote: ../../../contracts/solc/v0.8.26/RMNRemote/RMNRemote.abi ../../../contracts/solc/v0.8.26/RMNRemote/RMNRemote.bin 4850c11c168537cd44bbdca22cde122da4ecb6c2c97ccf67f3a42f99f57f67f9 -router: ../../../contracts/solc/v0.8.26/Router/Router.abi ../../../contracts/solc/v0.8.26/Router/Router.bin 02a393da5df7e9adc7c2481511f0b6e6602b01cd0807286728686a3a2767505c -token_admin_registry: ../../../contracts/solc/v0.8.26/TokenAdminRegistry/TokenAdminRegistry.abi ../../../contracts/solc/v0.8.26/TokenAdminRegistry/TokenAdminRegistry.bin 5ac3bc6a85b46c8762def67e0c6a80d4f1f20a3e6d9acc328d597aaeb3e26b09 -token_pool: ../../../contracts/solc/v0.8.26/TokenPool/TokenPool.abi ../../../contracts/solc/v0.8.26/TokenPool/TokenPool.bin 793d65f336929becdcf8bc3f2208a5b6de93774215fe2e863bef64df419cfdb0 -usdc_reader_tester: ../../../contracts/solc/v0.8.26/USDCReaderTester/USDCReaderTester.abi ../../../contracts/solc/v0.8.26/USDCReaderTester/USDCReaderTester.bin 3827700ad6d0706c254eb715c276258a64300e2ca4545bd88fe6573afe9c607d -usdc_token_pool: ../../../contracts/solc/v0.8.26/USDCTokenPool/USDCTokenPool.abi ../../../contracts/solc/v0.8.26/USDCTokenPool/USDCTokenPool.bin 8946473c55c3d43e95a47de2b6eeaad0471532e369a82a45afc514238e79f00a -weth9: ../../../contracts/solc/v0.8.26/WETH9/WETH9.abi ../../../contracts/solc/v0.8.26/WETH9/WETH9.bin d67072812a8702788a056c06f47c30a2291300e6656641a1b67051c061cb034b +burn_from_mint_token_pool: ../../../contracts/solc/v0.8.24/BurnFromMintTokenPool/BurnFromMintTokenPool.abi ../../../contracts/solc/v0.8.24/BurnFromMintTokenPool/BurnFromMintTokenPool.bin d5a1028728ed52d3c12ccd0e2f54d536697a6d5f689b0e89a4d083011a8cb1f6 +burn_mint_token_pool: ../../../contracts/solc/v0.8.24/BurnMintTokenPool/BurnMintTokenPool.abi ../../../contracts/solc/v0.8.24/BurnMintTokenPool/BurnMintTokenPool.bin 7f6b367ccf37878317fd9f50488370770204f0cc10c6e0e576be7e7c4ca8db56 +burn_with_from_mint_token_pool: ../../../contracts/solc/v0.8.24/BurnWithFromMintTokenPool/BurnWithFromMintTokenPool.abi ../../../contracts/solc/v0.8.24/BurnWithFromMintTokenPool/BurnWithFromMintTokenPool.bin e136c9f7a1d7af46ed5bd5bb836317c97715a71ee024868251abd0c462f1f115 +ccip_encoding_utils: ../../../contracts/solc/v0.8.24/ICCIPEncodingUtils/ICCIPEncodingUtils.abi ../../../contracts/solc/v0.8.24/ICCIPEncodingUtils/ICCIPEncodingUtils.bin 9971fc93c34442a0989570d3dab90a125de31e6e60754ad972807ce6ad4dfba0 +ccip_home: ../../../contracts/solc/v0.8.24/CCIPHome/CCIPHome.abi ../../../contracts/solc/v0.8.24/CCIPHome/CCIPHome.bin 02cb75b4274a5be7f4006cf2b72cc09e77eb6dba4c1a9c720af86668ff8ea1df +ccip_reader_tester: ../../../contracts/solc/v0.8.24/CCIPReaderTester/CCIPReaderTester.abi ../../../contracts/solc/v0.8.24/CCIPReaderTester/CCIPReaderTester.bin 893c9930e874fe5235db24e28a22650c37f562da94fac93618566bcd84839fdc +ether_sender_receiver: ../../../contracts/solc/v0.8.24/EtherSenderReceiver/EtherSenderReceiver.abi ../../../contracts/solc/v0.8.24/EtherSenderReceiver/EtherSenderReceiver.bin 09510a3f773f108a3c231e8d202835c845ded862d071ec54c4f89c12d868b8de +fee_quoter: ../../../contracts/solc/v0.8.24/FeeQuoter/FeeQuoter.abi ../../../contracts/solc/v0.8.24/FeeQuoter/FeeQuoter.bin 8a0869d14bb5247fbc6d836fc20d123358373ed688e0d3b387d59e7d05496fea +lock_release_token_pool: ../../../contracts/solc/v0.8.24/LockReleaseTokenPool/LockReleaseTokenPool.abi ../../../contracts/solc/v0.8.24/LockReleaseTokenPool/LockReleaseTokenPool.bin b30d5520449d57a4fffa3c3675e46d50ad29b066e09c16971153538a38ab25f7 +maybe_revert_message_receiver: ../../../contracts/solc/v0.8.24/MaybeRevertMessageReceiver/MaybeRevertMessageReceiver.abi ../../../contracts/solc/v0.8.24/MaybeRevertMessageReceiver/MaybeRevertMessageReceiver.bin d73956c26232ebcc4a5444429fa99cbefed960e323be9b5a24925885c2e477d5 +message_hasher: ../../../contracts/solc/v0.8.24/MessageHasher/MessageHasher.abi ../../../contracts/solc/v0.8.24/MessageHasher/MessageHasher.bin ec2d3a92348d8e7b8f0d359b62a45157b9d2c750c01fbcf991826c4392f6e218 +mock_usdc_token_messenger: ../../../contracts/solc/v0.8.24/MockE2EUSDCTokenMessenger/MockE2EUSDCTokenMessenger.abi ../../../contracts/solc/v0.8.24/MockE2EUSDCTokenMessenger/MockE2EUSDCTokenMessenger.bin d976651d36b33ac2196b32b9d2f4fa6690c6a18d41b621365659fce1c1d1e737 +mock_usdc_token_transmitter: ../../../contracts/solc/v0.8.24/MockE2EUSDCTransmitter/MockE2EUSDCTransmitter.abi ../../../contracts/solc/v0.8.24/MockE2EUSDCTransmitter/MockE2EUSDCTransmitter.bin be0dbc3e475741ea0b7a54ec2b935a321b428baa9f4ce18180a87fb38bb87de2 +mock_v3_aggregator_contract: ../../../contracts/solc/v0.8.24/MockV3Aggregator/MockV3Aggregator.abi ../../../contracts/solc/v0.8.24/MockV3Aggregator/MockV3Aggregator.bin 518e19efa2ff52b0fefd8e597b05765317ee7638189bfe34ca43de2f6599faf4 +multi_aggregate_rate_limiter: ../../../contracts/solc/v0.8.24/MultiAggregateRateLimiter/MultiAggregateRateLimiter.abi ../../../contracts/solc/v0.8.24/MultiAggregateRateLimiter/MultiAggregateRateLimiter.bin c3cac2010c2815b484055bf981363a2bd04e7fbe7bb502dc8fd29a16165d221c +multi_ocr3_helper: ../../../contracts/solc/v0.8.24/MultiOCR3Helper/MultiOCR3Helper.abi ../../../contracts/solc/v0.8.24/MultiOCR3Helper/MultiOCR3Helper.bin 79bfbd1f7d3c2aeee6301ae1275c39924a0b41f16b051d1c0046d3fc4265093d +nonce_manager: ../../../contracts/solc/v0.8.24/NonceManager/NonceManager.abi ../../../contracts/solc/v0.8.24/NonceManager/NonceManager.bin e6008490d916826cefd1903612db39621d51617300fc9bb42b68c6c117958198 +offramp: ../../../contracts/solc/v0.8.24/OffRamp/OffRamp.abi ../../../contracts/solc/v0.8.24/OffRamp/OffRamp.bin d20e6c0baf08926b341c31ed0018983e135a75b7d120591de49ca4ece3824d0b +onramp: ../../../contracts/solc/v0.8.24/OnRamp/OnRamp.abi ../../../contracts/solc/v0.8.24/OnRamp/OnRamp.bin 2bf74188a997218502031f177cb2df505b272d66b25fd341a741289e77380c59 +ping_pong_demo: ../../../contracts/solc/v0.8.24/PingPongDemo/PingPongDemo.abi ../../../contracts/solc/v0.8.24/PingPongDemo/PingPongDemo.bin 24b4415a883a470d65c484be0fa20714a46b1c9262db205f1c958017820307b2 +registry_module_owner_custom: ../../../contracts/solc/v0.8.24/RegistryModuleOwnerCustom/RegistryModuleOwnerCustom.abi ../../../contracts/solc/v0.8.24/RegistryModuleOwnerCustom/RegistryModuleOwnerCustom.bin 0fc277a0b512db4e20b5a32a775b94ed2c0d342d8237511de78c94f7dacad428 +report_codec: ../../../contracts/solc/v0.8.24/ReportCodec/ReportCodec.abi ../../../contracts/solc/v0.8.24/ReportCodec/ReportCodec.bin 6c943b39f003aa67c3cefa19a8ff99e846236a058e1ceae77569c3a065ffd5c7 +rmn_home: ../../../contracts/solc/v0.8.24/RMNHome/RMNHome.abi ../../../contracts/solc/v0.8.24/RMNHome/RMNHome.bin 84ca84b3d0c00949905a3d10a91255f877cf32b2a0d7f7f7ce3121ced34a8cb7 +rmn_proxy_contract: ../../../contracts/solc/v0.8.24/ARMProxy/ARMProxy.abi ../../../contracts/solc/v0.8.24/ARMProxy/ARMProxy.bin b048d8e752e3c41113ebb305c1efa06737ad36b4907b93e627fb0a3113023454 +rmn_remote: ../../../contracts/solc/v0.8.24/RMNRemote/RMNRemote.abi ../../../contracts/solc/v0.8.24/RMNRemote/RMNRemote.bin faee0b0cdbe67f2e28deccf12acd4df13dd90992f6cbc0ba17bab845b8f4eb1c +router: ../../../contracts/solc/v0.8.24/Router/Router.abi ../../../contracts/solc/v0.8.24/Router/Router.bin 2e4f0a7826c8abb49d882bb49fc5ff20a186dbd3137624b9097ffed903ae4888 +token_admin_registry: ../../../contracts/solc/v0.8.24/TokenAdminRegistry/TokenAdminRegistry.abi ../../../contracts/solc/v0.8.24/TokenAdminRegistry/TokenAdminRegistry.bin 397bc7be08c2848c0f4715f90b16206d6367f78ffb7cd48e2b1dfc0ccc5aea26 +token_pool: ../../../contracts/solc/v0.8.24/TokenPool/TokenPool.abi ../../../contracts/solc/v0.8.24/TokenPool/TokenPool.bin 7956641010fdb65dc2cf5cc1a51c5ed3e0c32493d6916eb563d24a855e827342 +usdc_reader_tester: ../../../contracts/solc/v0.8.24/USDCReaderTester/USDCReaderTester.abi ../../../contracts/solc/v0.8.24/USDCReaderTester/USDCReaderTester.bin 672a07c9218fd6ad7c04dde583088b0f5ffc8d55a46f4be1714008dd3409438b +usdc_token_pool: ../../../contracts/solc/v0.8.24/USDCTokenPool/USDCTokenPool.abi ../../../contracts/solc/v0.8.24/USDCTokenPool/USDCTokenPool.bin da68b8ea71a12762d9fd3581cabddcb1c6f5b64a3fe3923842216dbf9d2aa9c6 +weth9: ../../../contracts/solc/v0.8.24/WETH9/WETH9.abi ../../../contracts/solc/v0.8.24/WETH9/WETH9.bin 2970d79a0ca6dd6279cde130de45e56c8790ed695eae477fb5ba4c1bb75b720d diff --git a/core/gethwrappers/ccip/go_generate.go b/core/gethwrappers/ccip/go_generate.go index d5cfedf03b5..9d6fa7c4645 100644 --- a/core/gethwrappers/ccip/go_generate.go +++ b/core/gethwrappers/ccip/go_generate.go @@ -2,43 +2,43 @@ // golang packages, using abigen. package ccip -//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.26/ARMProxy/ARMProxy.abi ../../../contracts/solc/v0.8.26/ARMProxy/ARMProxy.bin RMNProxyContract rmn_proxy_contract -//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.26/TokenAdminRegistry/TokenAdminRegistry.abi ../../../contracts/solc/v0.8.26/TokenAdminRegistry/TokenAdminRegistry.bin TokenAdminRegistry token_admin_registry -//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.26/RegistryModuleOwnerCustom/RegistryModuleOwnerCustom.abi ../../../contracts/solc/v0.8.26/RegistryModuleOwnerCustom/RegistryModuleOwnerCustom.bin RegistryModuleOwnerCustom registry_module_owner_custom -//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.26/OnRamp/OnRamp.abi ../../../contracts/solc/v0.8.26/OnRamp/OnRamp.bin OnRamp onramp -//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.26/OffRamp/OffRamp.abi ../../../contracts/solc/v0.8.26/OffRamp/OffRamp.bin OffRamp offramp -//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.26/RMNRemote/RMNRemote.abi ../../../contracts/solc/v0.8.26/RMNRemote/RMNRemote.bin RMNRemote rmn_remote -//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.26/RMNHome/RMNHome.abi ../../../contracts/solc/v0.8.26/RMNHome/RMNHome.bin RMNHome rmn_home -//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.26/MultiAggregateRateLimiter/MultiAggregateRateLimiter.abi ../../../contracts/solc/v0.8.26/MultiAggregateRateLimiter/MultiAggregateRateLimiter.bin MultiAggregateRateLimiter multi_aggregate_rate_limiter -//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.26/Router/Router.abi ../../../contracts/solc/v0.8.26/Router/Router.bin Router router -//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.26/FeeQuoter/FeeQuoter.abi ../../../contracts/solc/v0.8.26/FeeQuoter/FeeQuoter.bin FeeQuoter fee_quoter -//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.26/CCIPHome/CCIPHome.abi ../../../contracts/solc/v0.8.26/CCIPHome/CCIPHome.bin CCIPHome ccip_home -//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.26/NonceManager/NonceManager.abi ../../../contracts/solc/v0.8.26/NonceManager/NonceManager.bin NonceManager nonce_manager +//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.24/ARMProxy/ARMProxy.abi ../../../contracts/solc/v0.8.24/ARMProxy/ARMProxy.bin RMNProxyContract rmn_proxy_contract +//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.24/TokenAdminRegistry/TokenAdminRegistry.abi ../../../contracts/solc/v0.8.24/TokenAdminRegistry/TokenAdminRegistry.bin TokenAdminRegistry token_admin_registry +//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.24/RegistryModuleOwnerCustom/RegistryModuleOwnerCustom.abi ../../../contracts/solc/v0.8.24/RegistryModuleOwnerCustom/RegistryModuleOwnerCustom.bin RegistryModuleOwnerCustom registry_module_owner_custom +//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.24/OnRamp/OnRamp.abi ../../../contracts/solc/v0.8.24/OnRamp/OnRamp.bin OnRamp onramp +//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.24/OffRamp/OffRamp.abi ../../../contracts/solc/v0.8.24/OffRamp/OffRamp.bin OffRamp offramp +//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.24/RMNRemote/RMNRemote.abi ../../../contracts/solc/v0.8.24/RMNRemote/RMNRemote.bin RMNRemote rmn_remote +//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.24/RMNHome/RMNHome.abi ../../../contracts/solc/v0.8.24/RMNHome/RMNHome.bin RMNHome rmn_home +//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.24/MultiAggregateRateLimiter/MultiAggregateRateLimiter.abi ../../../contracts/solc/v0.8.24/MultiAggregateRateLimiter/MultiAggregateRateLimiter.bin MultiAggregateRateLimiter multi_aggregate_rate_limiter +//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.24/Router/Router.abi ../../../contracts/solc/v0.8.24/Router/Router.bin Router router +//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.24/FeeQuoter/FeeQuoter.abi ../../../contracts/solc/v0.8.24/FeeQuoter/FeeQuoter.bin FeeQuoter fee_quoter +//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.24/CCIPHome/CCIPHome.abi ../../../contracts/solc/v0.8.24/CCIPHome/CCIPHome.bin CCIPHome ccip_home +//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.24/NonceManager/NonceManager.abi ../../../contracts/solc/v0.8.24/NonceManager/NonceManager.bin NonceManager nonce_manager // Pools -//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.26/BurnMintTokenPool/BurnMintTokenPool.abi ../../../contracts/solc/v0.8.26/BurnMintTokenPool/BurnMintTokenPool.bin BurnMintTokenPool burn_mint_token_pool -//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.26/BurnFromMintTokenPool/BurnFromMintTokenPool.abi ../../../contracts/solc/v0.8.26/BurnFromMintTokenPool/BurnFromMintTokenPool.bin BurnFromMintTokenPool burn_from_mint_token_pool -//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.26/BurnWithFromMintTokenPool/BurnWithFromMintTokenPool.abi ../../../contracts/solc/v0.8.26/BurnWithFromMintTokenPool/BurnWithFromMintTokenPool.bin BurnWithFromMintTokenPool burn_with_from_mint_token_pool -//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.26/LockReleaseTokenPool/LockReleaseTokenPool.abi ../../../contracts/solc/v0.8.26/LockReleaseTokenPool/LockReleaseTokenPool.bin LockReleaseTokenPool lock_release_token_pool -//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.26/TokenPool/TokenPool.abi ../../../contracts/solc/v0.8.26/TokenPool/TokenPool.bin TokenPool token_pool -//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.26/USDCTokenPool/USDCTokenPool.abi ../../../contracts/solc/v0.8.26/USDCTokenPool/USDCTokenPool.bin USDCTokenPool usdc_token_pool +//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.24/BurnMintTokenPool/BurnMintTokenPool.abi ../../../contracts/solc/v0.8.24/BurnMintTokenPool/BurnMintTokenPool.bin BurnMintTokenPool burn_mint_token_pool +//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.24/BurnFromMintTokenPool/BurnFromMintTokenPool.abi ../../../contracts/solc/v0.8.24/BurnFromMintTokenPool/BurnFromMintTokenPool.bin BurnFromMintTokenPool burn_from_mint_token_pool +//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.24/BurnWithFromMintTokenPool/BurnWithFromMintTokenPool.abi ../../../contracts/solc/v0.8.24/BurnWithFromMintTokenPool/BurnWithFromMintTokenPool.bin BurnWithFromMintTokenPool burn_with_from_mint_token_pool +//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.24/LockReleaseTokenPool/LockReleaseTokenPool.abi ../../../contracts/solc/v0.8.24/LockReleaseTokenPool/LockReleaseTokenPool.bin LockReleaseTokenPool lock_release_token_pool +//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.24/TokenPool/TokenPool.abi ../../../contracts/solc/v0.8.24/TokenPool/TokenPool.bin TokenPool token_pool +//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.24/USDCTokenPool/USDCTokenPool.abi ../../../contracts/solc/v0.8.24/USDCTokenPool/USDCTokenPool.bin USDCTokenPool usdc_token_pool // Helpers -//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.26/MockV3Aggregator/MockV3Aggregator.abi ../../../contracts/solc/v0.8.26/MockV3Aggregator/MockV3Aggregator.bin MockV3Aggregator mock_v3_aggregator_contract -//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.26/MaybeRevertMessageReceiver/MaybeRevertMessageReceiver.abi ../../../contracts/solc/v0.8.26/MaybeRevertMessageReceiver/MaybeRevertMessageReceiver.bin MaybeRevertMessageReceiver maybe_revert_message_receiver -//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.26/PingPongDemo/PingPongDemo.abi ../../../contracts/solc/v0.8.26/PingPongDemo/PingPongDemo.bin PingPongDemo ping_pong_demo -//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.26/MessageHasher/MessageHasher.abi ../../../contracts/solc/v0.8.26/MessageHasher/MessageHasher.bin MessageHasher message_hasher -//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.26/MultiOCR3Helper/MultiOCR3Helper.abi ../../../contracts/solc/v0.8.26/MultiOCR3Helper/MultiOCR3Helper.bin MultiOCR3Helper multi_ocr3_helper -//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.26/USDCReaderTester/USDCReaderTester.abi ../../../contracts/solc/v0.8.26/USDCReaderTester/USDCReaderTester.bin USDCReaderTester usdc_reader_tester -//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.26/ReportCodec/ReportCodec.abi ../../../contracts/solc/v0.8.26/ReportCodec/ReportCodec.bin ReportCodec report_codec -//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.26/EtherSenderReceiver/EtherSenderReceiver.abi ../../../contracts/solc/v0.8.26/EtherSenderReceiver/EtherSenderReceiver.bin EtherSenderReceiver ether_sender_receiver -//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.26/WETH9/WETH9.abi ../../../contracts/solc/v0.8.26/WETH9/WETH9.bin WETH9 weth9 -//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.26/MockE2EUSDCTokenMessenger/MockE2EUSDCTokenMessenger.abi ../../../contracts/solc/v0.8.26/MockE2EUSDCTokenMessenger/MockE2EUSDCTokenMessenger.bin MockE2EUSDCTokenMessenger mock_usdc_token_messenger -//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.26/MockE2EUSDCTransmitter/MockE2EUSDCTransmitter.abi ../../../contracts/solc/v0.8.26/MockE2EUSDCTransmitter/MockE2EUSDCTransmitter.bin MockE2EUSDCTransmitter mock_usdc_token_transmitter -//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.26/CCIPReaderTester/CCIPReaderTester.abi ../../../contracts/solc/v0.8.26/CCIPReaderTester/CCIPReaderTester.bin CCIPReaderTester ccip_reader_tester +//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.24/MockV3Aggregator/MockV3Aggregator.abi ../../../contracts/solc/v0.8.24/MockV3Aggregator/MockV3Aggregator.bin MockV3Aggregator mock_v3_aggregator_contract +//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.24/MaybeRevertMessageReceiver/MaybeRevertMessageReceiver.abi ../../../contracts/solc/v0.8.24/MaybeRevertMessageReceiver/MaybeRevertMessageReceiver.bin MaybeRevertMessageReceiver maybe_revert_message_receiver +//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.24/PingPongDemo/PingPongDemo.abi ../../../contracts/solc/v0.8.24/PingPongDemo/PingPongDemo.bin PingPongDemo ping_pong_demo +//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.24/MessageHasher/MessageHasher.abi ../../../contracts/solc/v0.8.24/MessageHasher/MessageHasher.bin MessageHasher message_hasher +//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.24/MultiOCR3Helper/MultiOCR3Helper.abi ../../../contracts/solc/v0.8.24/MultiOCR3Helper/MultiOCR3Helper.bin MultiOCR3Helper multi_ocr3_helper +//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.24/USDCReaderTester/USDCReaderTester.abi ../../../contracts/solc/v0.8.24/USDCReaderTester/USDCReaderTester.bin USDCReaderTester usdc_reader_tester +//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.24/ReportCodec/ReportCodec.abi ../../../contracts/solc/v0.8.24/ReportCodec/ReportCodec.bin ReportCodec report_codec +//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.24/EtherSenderReceiver/EtherSenderReceiver.abi ../../../contracts/solc/v0.8.24/EtherSenderReceiver/EtherSenderReceiver.bin EtherSenderReceiver ether_sender_receiver +//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.24/WETH9/WETH9.abi ../../../contracts/solc/v0.8.24/WETH9/WETH9.bin WETH9 weth9 +//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.24/MockE2EUSDCTokenMessenger/MockE2EUSDCTokenMessenger.abi ../../../contracts/solc/v0.8.24/MockE2EUSDCTokenMessenger/MockE2EUSDCTokenMessenger.bin MockE2EUSDCTokenMessenger mock_usdc_token_messenger +//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.24/MockE2EUSDCTransmitter/MockE2EUSDCTransmitter.abi ../../../contracts/solc/v0.8.24/MockE2EUSDCTransmitter/MockE2EUSDCTransmitter.bin MockE2EUSDCTransmitter mock_usdc_token_transmitter +//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.24/CCIPReaderTester/CCIPReaderTester.abi ../../../contracts/solc/v0.8.24/CCIPReaderTester/CCIPReaderTester.bin CCIPReaderTester ccip_reader_tester // EncodingUtils -//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.26/ICCIPEncodingUtils/ICCIPEncodingUtils.abi ../../../contracts/solc/v0.8.26/ICCIPEncodingUtils/ICCIPEncodingUtils.bin EncodingUtils ccip_encoding_utils +//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.24/ICCIPEncodingUtils/ICCIPEncodingUtils.abi ../../../contracts/solc/v0.8.24/ICCIPEncodingUtils/ICCIPEncodingUtils.bin EncodingUtils ccip_encoding_utils // To run these commands, you must either install docker, or the correct version // of abigen. The latter can be installed with these commands, at least on linux: diff --git a/core/gethwrappers/ccip/mocks/fee_quoter_interface.go b/core/gethwrappers/ccip/mocks/fee_quoter_interface.go index 8fadeb40e08..7c0f421526e 100644 --- a/core/gethwrappers/ccip/mocks/fee_quoter_interface.go +++ b/core/gethwrappers/ccip/mocks/fee_quoter_interface.go @@ -3416,63 +3416,6 @@ func (_c *FeeQuoterInterface_SetReportPermissions_Call) RunAndReturn(run func(*b return _c } -// SupportsInterface provides a mock function with given fields: opts, interfaceId -func (_m *FeeQuoterInterface) SupportsInterface(opts *bind.CallOpts, interfaceId [4]byte) (bool, error) { - ret := _m.Called(opts, interfaceId) - - if len(ret) == 0 { - panic("no return value specified for SupportsInterface") - } - - var r0 bool - var r1 error - if rf, ok := ret.Get(0).(func(*bind.CallOpts, [4]byte) (bool, error)); ok { - return rf(opts, interfaceId) - } - if rf, ok := ret.Get(0).(func(*bind.CallOpts, [4]byte) bool); ok { - r0 = rf(opts, interfaceId) - } else { - r0 = ret.Get(0).(bool) - } - - if rf, ok := ret.Get(1).(func(*bind.CallOpts, [4]byte) error); ok { - r1 = rf(opts, interfaceId) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// FeeQuoterInterface_SupportsInterface_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'SupportsInterface' -type FeeQuoterInterface_SupportsInterface_Call struct { - *mock.Call -} - -// SupportsInterface is a helper method to define mock.On call -// - opts *bind.CallOpts -// - interfaceId [4]byte -func (_e *FeeQuoterInterface_Expecter) SupportsInterface(opts interface{}, interfaceId interface{}) *FeeQuoterInterface_SupportsInterface_Call { - return &FeeQuoterInterface_SupportsInterface_Call{Call: _e.mock.On("SupportsInterface", opts, interfaceId)} -} - -func (_c *FeeQuoterInterface_SupportsInterface_Call) Run(run func(opts *bind.CallOpts, interfaceId [4]byte)) *FeeQuoterInterface_SupportsInterface_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(*bind.CallOpts), args[1].([4]byte)) - }) - return _c -} - -func (_c *FeeQuoterInterface_SupportsInterface_Call) Return(_a0 bool, _a1 error) *FeeQuoterInterface_SupportsInterface_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *FeeQuoterInterface_SupportsInterface_Call) RunAndReturn(run func(*bind.CallOpts, [4]byte) (bool, error)) *FeeQuoterInterface_SupportsInterface_Call { - _c.Call.Return(run) - return _c -} - // TransferOwnership provides a mock function with given fields: opts, to func (_m *FeeQuoterInterface) TransferOwnership(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) { ret := _m.Called(opts, to) diff --git a/core/gethwrappers/go_generate.go b/core/gethwrappers/go_generate.go index f725ff95c06..25001027a59 100644 --- a/core/gethwrappers/go_generate.go +++ b/core/gethwrappers/go_generate.go @@ -160,6 +160,7 @@ package gethwrappers //go:generate go generate ./llo-feeds //go:generate go generate ./operatorforwarder //go:generate go generate ./shared +//go:generate go generate ./transmission //go:generate go generate ./ccip //go:generate go generate ./liquiditymanager //go:generate go generate ./workflow diff --git a/core/gethwrappers/go_generate_test.go b/core/gethwrappers/go_generate_test.go index 1066149278f..a6253cb1a66 100644 --- a/core/gethwrappers/go_generate_test.go +++ b/core/gethwrappers/go_generate_test.go @@ -16,8 +16,7 @@ import ( "github.com/fatih/color" cutils "github.com/smartcontractkit/chainlink-common/pkg/utils" - "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" - + "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/utils" "github.com/stretchr/testify/assert" @@ -30,7 +29,7 @@ const compileCommand = "../../contracts/scripts/native_solc_compile_all" // contract artifacts in contracts/solc with the abi and bytecode stored in the // contract wrapper func TestCheckContractHashesFromLastGoGenerate(t *testing.T) { - tests.SkipShort(t, "requires compiled artifacts") + testutils.SkipShort(t, "requires compiled artifacts") versions, err := ReadVersionsDB() require.NoError(t, err) require.NotEmpty(t, versions.GethVersion, `version DB should have a "GETH_VERSION:" line`) diff --git a/core/gethwrappers/keystone/generated/capabilities_registry_1_1_0/capabilities_registry.go b/core/gethwrappers/keystone/generated/capabilities_registry_1_1_0/capabilities_registry.go deleted file mode 100644 index 2a21f64da56..00000000000 --- a/core/gethwrappers/keystone/generated/capabilities_registry_1_1_0/capabilities_registry.go +++ /dev/null @@ -1,2352 +0,0 @@ -// Code generated - DO NOT EDIT. -// This file is a generated binding and any manual changes will be lost. - -package capabilities_registry - -import ( - "errors" - "fmt" - "math/big" - "strings" - - ethereum "github.com/ethereum/go-ethereum" - "github.com/ethereum/go-ethereum/accounts/abi" - "github.com/ethereum/go-ethereum/accounts/abi/bind" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/event" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated" -) - -var ( - _ = errors.New - _ = big.NewInt - _ = strings.NewReader - _ = ethereum.NotFound - _ = bind.Bind - _ = common.Big1 - _ = types.BloomLookup - _ = event.NewSubscription - _ = abi.ConvertType -) - -type CapabilitiesRegistryCapability struct { - LabelledName string - Version string - CapabilityType uint8 - ResponseType uint8 - ConfigurationContract common.Address -} - -type CapabilitiesRegistryCapabilityConfiguration struct { - CapabilityId [32]byte - Config []byte -} - -type CapabilitiesRegistryCapabilityInfo struct { - HashedId [32]byte - LabelledName string - Version string - CapabilityType uint8 - ResponseType uint8 - ConfigurationContract common.Address - IsDeprecated bool -} - -type CapabilitiesRegistryDONInfo struct { - Id uint32 - ConfigCount uint32 - F uint8 - IsPublic bool - AcceptsWorkflows bool - NodeP2PIds [][32]byte - CapabilityConfigurations []CapabilitiesRegistryCapabilityConfiguration -} - -type CapabilitiesRegistryNodeOperator struct { - Admin common.Address - Name string -} - -type CapabilitiesRegistryNodeParams struct { - NodeOperatorId uint32 - Signer [32]byte - P2pId [32]byte - EncryptionPublicKey [32]byte - HashedCapabilityIds [][32]byte -} - -type INodeInfoProviderNodeInfo struct { - NodeOperatorId uint32 - ConfigCount uint32 - WorkflowDONId uint32 - Signer [32]byte - P2pId [32]byte - EncryptionPublicKey [32]byte - HashedCapabilityIds [][32]byte - CapabilitiesDONIds []*big.Int -} - -var CapabilitiesRegistryMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"AccessForbidden\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"hashedCapabilityId\",\"type\":\"bytes32\"}],\"name\":\"CapabilityAlreadyExists\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"hashedCapabilityId\",\"type\":\"bytes32\"}],\"name\":\"CapabilityDoesNotExist\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"hashedCapabilityId\",\"type\":\"bytes32\"}],\"name\":\"CapabilityIsDeprecated\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"hashedCapabilityId\",\"type\":\"bytes32\"},{\"internalType\":\"uint32\",\"name\":\"donId\",\"type\":\"uint32\"}],\"name\":\"CapabilityRequiredByDON\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"donId\",\"type\":\"uint32\"}],\"name\":\"DONDoesNotExist\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"donId\",\"type\":\"uint32\"},{\"internalType\":\"bytes32\",\"name\":\"capabilityId\",\"type\":\"bytes32\"}],\"name\":\"DuplicateDONCapability\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"donId\",\"type\":\"uint32\"},{\"internalType\":\"bytes32\",\"name\":\"nodeP2PId\",\"type\":\"bytes32\"}],\"name\":\"DuplicateDONNode\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"proposedConfigurationContract\",\"type\":\"address\"}],\"name\":\"InvalidCapabilityConfigurationContractInterface\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"f\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"nodeCount\",\"type\":\"uint256\"}],\"name\":\"InvalidFaultTolerance\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32[]\",\"name\":\"hashedCapabilityIds\",\"type\":\"bytes32[]\"}],\"name\":\"InvalidNodeCapabilities\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"encryptionPublicKey\",\"type\":\"bytes32\"}],\"name\":\"InvalidNodeEncryptionPublicKey\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidNodeOperatorAdmin\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"p2pId\",\"type\":\"bytes32\"}],\"name\":\"InvalidNodeP2PId\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidNodeSigner\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"lengthOne\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"lengthTwo\",\"type\":\"uint256\"}],\"name\":\"LengthMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"nodeP2PId\",\"type\":\"bytes32\"}],\"name\":\"NodeAlreadyExists\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"nodeP2PId\",\"type\":\"bytes32\"}],\"name\":\"NodeDoesNotExist\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"nodeP2PId\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"capabilityId\",\"type\":\"bytes32\"}],\"name\":\"NodeDoesNotSupportCapability\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"nodeOperatorId\",\"type\":\"uint32\"}],\"name\":\"NodeOperatorDoesNotExist\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"donId\",\"type\":\"uint32\"},{\"internalType\":\"bytes32\",\"name\":\"nodeP2PId\",\"type\":\"bytes32\"}],\"name\":\"NodePartOfCapabilitiesDON\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"donId\",\"type\":\"uint32\"},{\"internalType\":\"bytes32\",\"name\":\"nodeP2PId\",\"type\":\"bytes32\"}],\"name\":\"NodePartOfWorkflowDON\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"hashedCapabilityId\",\"type\":\"bytes32\"}],\"name\":\"CapabilityConfigured\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"hashedCapabilityId\",\"type\":\"bytes32\"}],\"name\":\"CapabilityDeprecated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint32\",\"name\":\"donId\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"configCount\",\"type\":\"uint32\"}],\"name\":\"ConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"p2pId\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"uint32\",\"name\":\"nodeOperatorId\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"signer\",\"type\":\"bytes32\"}],\"name\":\"NodeAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint32\",\"name\":\"nodeOperatorId\",\"type\":\"uint32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"}],\"name\":\"NodeOperatorAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint32\",\"name\":\"nodeOperatorId\",\"type\":\"uint32\"}],\"name\":\"NodeOperatorRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint32\",\"name\":\"nodeOperatorId\",\"type\":\"uint32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"}],\"name\":\"NodeOperatorUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"p2pId\",\"type\":\"bytes32\"}],\"name\":\"NodeRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"p2pId\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"uint32\",\"name\":\"nodeOperatorId\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"signer\",\"type\":\"bytes32\"}],\"name\":\"NodeUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"string\",\"name\":\"labelledName\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"version\",\"type\":\"string\"},{\"internalType\":\"enumCapabilitiesRegistry.CapabilityType\",\"name\":\"capabilityType\",\"type\":\"uint8\"},{\"internalType\":\"enumCapabilitiesRegistry.CapabilityResponseType\",\"name\":\"responseType\",\"type\":\"uint8\"},{\"internalType\":\"address\",\"name\":\"configurationContract\",\"type\":\"address\"}],\"internalType\":\"structCapabilitiesRegistry.Capability[]\",\"name\":\"capabilities\",\"type\":\"tuple[]\"}],\"name\":\"addCapabilities\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[]\",\"name\":\"nodes\",\"type\":\"bytes32[]\"},{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"capabilityId\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"config\",\"type\":\"bytes\"}],\"internalType\":\"structCapabilitiesRegistry.CapabilityConfiguration[]\",\"name\":\"capabilityConfigurations\",\"type\":\"tuple[]\"},{\"internalType\":\"bool\",\"name\":\"isPublic\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"acceptsWorkflows\",\"type\":\"bool\"},{\"internalType\":\"uint8\",\"name\":\"f\",\"type\":\"uint8\"}],\"name\":\"addDON\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"}],\"internalType\":\"structCapabilitiesRegistry.NodeOperator[]\",\"name\":\"nodeOperators\",\"type\":\"tuple[]\"}],\"name\":\"addNodeOperators\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"nodeOperatorId\",\"type\":\"uint32\"},{\"internalType\":\"bytes32\",\"name\":\"signer\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"p2pId\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"encryptionPublicKey\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32[]\",\"name\":\"hashedCapabilityIds\",\"type\":\"bytes32[]\"}],\"internalType\":\"structCapabilitiesRegistry.NodeParams[]\",\"name\":\"nodes\",\"type\":\"tuple[]\"}],\"name\":\"addNodes\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[]\",\"name\":\"hashedCapabilityIds\",\"type\":\"bytes32[]\"}],\"name\":\"deprecateCapabilities\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getCapabilities\",\"outputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"hashedId\",\"type\":\"bytes32\"},{\"internalType\":\"string\",\"name\":\"labelledName\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"version\",\"type\":\"string\"},{\"internalType\":\"enumCapabilitiesRegistry.CapabilityType\",\"name\":\"capabilityType\",\"type\":\"uint8\"},{\"internalType\":\"enumCapabilitiesRegistry.CapabilityResponseType\",\"name\":\"responseType\",\"type\":\"uint8\"},{\"internalType\":\"address\",\"name\":\"configurationContract\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"isDeprecated\",\"type\":\"bool\"}],\"internalType\":\"structCapabilitiesRegistry.CapabilityInfo[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"hashedId\",\"type\":\"bytes32\"}],\"name\":\"getCapability\",\"outputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"hashedId\",\"type\":\"bytes32\"},{\"internalType\":\"string\",\"name\":\"labelledName\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"version\",\"type\":\"string\"},{\"internalType\":\"enumCapabilitiesRegistry.CapabilityType\",\"name\":\"capabilityType\",\"type\":\"uint8\"},{\"internalType\":\"enumCapabilitiesRegistry.CapabilityResponseType\",\"name\":\"responseType\",\"type\":\"uint8\"},{\"internalType\":\"address\",\"name\":\"configurationContract\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"isDeprecated\",\"type\":\"bool\"}],\"internalType\":\"structCapabilitiesRegistry.CapabilityInfo\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"donId\",\"type\":\"uint32\"},{\"internalType\":\"bytes32\",\"name\":\"capabilityId\",\"type\":\"bytes32\"}],\"name\":\"getCapabilityConfigs\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"donId\",\"type\":\"uint32\"}],\"name\":\"getDON\",\"outputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"id\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"configCount\",\"type\":\"uint32\"},{\"internalType\":\"uint8\",\"name\":\"f\",\"type\":\"uint8\"},{\"internalType\":\"bool\",\"name\":\"isPublic\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"acceptsWorkflows\",\"type\":\"bool\"},{\"internalType\":\"bytes32[]\",\"name\":\"nodeP2PIds\",\"type\":\"bytes32[]\"},{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"capabilityId\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"config\",\"type\":\"bytes\"}],\"internalType\":\"structCapabilitiesRegistry.CapabilityConfiguration[]\",\"name\":\"capabilityConfigurations\",\"type\":\"tuple[]\"}],\"internalType\":\"structCapabilitiesRegistry.DONInfo\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getDONs\",\"outputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"id\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"configCount\",\"type\":\"uint32\"},{\"internalType\":\"uint8\",\"name\":\"f\",\"type\":\"uint8\"},{\"internalType\":\"bool\",\"name\":\"isPublic\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"acceptsWorkflows\",\"type\":\"bool\"},{\"internalType\":\"bytes32[]\",\"name\":\"nodeP2PIds\",\"type\":\"bytes32[]\"},{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"capabilityId\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"config\",\"type\":\"bytes\"}],\"internalType\":\"structCapabilitiesRegistry.CapabilityConfiguration[]\",\"name\":\"capabilityConfigurations\",\"type\":\"tuple[]\"}],\"internalType\":\"structCapabilitiesRegistry.DONInfo[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"labelledName\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"version\",\"type\":\"string\"}],\"name\":\"getHashedCapabilityId\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getNextDONId\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"p2pId\",\"type\":\"bytes32\"}],\"name\":\"getNode\",\"outputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"nodeOperatorId\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"configCount\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"workflowDONId\",\"type\":\"uint32\"},{\"internalType\":\"bytes32\",\"name\":\"signer\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"p2pId\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"encryptionPublicKey\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32[]\",\"name\":\"hashedCapabilityIds\",\"type\":\"bytes32[]\"},{\"internalType\":\"uint256[]\",\"name\":\"capabilitiesDONIds\",\"type\":\"uint256[]\"}],\"internalType\":\"structINodeInfoProvider.NodeInfo\",\"name\":\"nodeInfo\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"nodeOperatorId\",\"type\":\"uint32\"}],\"name\":\"getNodeOperator\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"}],\"internalType\":\"structCapabilitiesRegistry.NodeOperator\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getNodeOperators\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"}],\"internalType\":\"structCapabilitiesRegistry.NodeOperator[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getNodes\",\"outputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"nodeOperatorId\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"configCount\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"workflowDONId\",\"type\":\"uint32\"},{\"internalType\":\"bytes32\",\"name\":\"signer\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"p2pId\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"encryptionPublicKey\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32[]\",\"name\":\"hashedCapabilityIds\",\"type\":\"bytes32[]\"},{\"internalType\":\"uint256[]\",\"name\":\"capabilitiesDONIds\",\"type\":\"uint256[]\"}],\"internalType\":\"structINodeInfoProvider.NodeInfo[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[]\",\"name\":\"p2pIds\",\"type\":\"bytes32[]\"}],\"name\":\"getNodesByP2PIds\",\"outputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"nodeOperatorId\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"configCount\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"workflowDONId\",\"type\":\"uint32\"},{\"internalType\":\"bytes32\",\"name\":\"signer\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"p2pId\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"encryptionPublicKey\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32[]\",\"name\":\"hashedCapabilityIds\",\"type\":\"bytes32[]\"},{\"internalType\":\"uint256[]\",\"name\":\"capabilitiesDONIds\",\"type\":\"uint256[]\"}],\"internalType\":\"structINodeInfoProvider.NodeInfo[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"hashedCapabilityId\",\"type\":\"bytes32\"}],\"name\":\"isCapabilityDeprecated\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32[]\",\"name\":\"donIds\",\"type\":\"uint32[]\"}],\"name\":\"removeDONs\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32[]\",\"name\":\"nodeOperatorIds\",\"type\":\"uint32[]\"}],\"name\":\"removeNodeOperators\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[]\",\"name\":\"removedNodeP2PIds\",\"type\":\"bytes32[]\"}],\"name\":\"removeNodes\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"donId\",\"type\":\"uint32\"},{\"internalType\":\"bytes32[]\",\"name\":\"nodes\",\"type\":\"bytes32[]\"},{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"capabilityId\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"config\",\"type\":\"bytes\"}],\"internalType\":\"structCapabilitiesRegistry.CapabilityConfiguration[]\",\"name\":\"capabilityConfigurations\",\"type\":\"tuple[]\"},{\"internalType\":\"bool\",\"name\":\"isPublic\",\"type\":\"bool\"},{\"internalType\":\"uint8\",\"name\":\"f\",\"type\":\"uint8\"}],\"name\":\"updateDON\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32[]\",\"name\":\"nodeOperatorIds\",\"type\":\"uint32[]\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"}],\"internalType\":\"structCapabilitiesRegistry.NodeOperator[]\",\"name\":\"nodeOperators\",\"type\":\"tuple[]\"}],\"name\":\"updateNodeOperators\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"nodeOperatorId\",\"type\":\"uint32\"},{\"internalType\":\"bytes32\",\"name\":\"signer\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"p2pId\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"encryptionPublicKey\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32[]\",\"name\":\"hashedCapabilityIds\",\"type\":\"bytes32[]\"}],\"internalType\":\"structCapabilitiesRegistry.NodeParams[]\",\"name\":\"nodes\",\"type\":\"tuple[]\"}],\"name\":\"updateNodes\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", - Bin: "0x6080604052600e80546001600160401b0319166401000000011790553480156200002857600080fd5b503380600081620000805760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000b357620000b381620000bc565b50505062000167565b336001600160a01b03821603620001165760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000077565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b61536d80620001776000396000f3fe608060405234801561001057600080fd5b50600436106101c45760003560e01c806350c946fe116100f95780638da5cb5b11610097578063ddbe4f8211610071578063ddbe4f821461044d578063e29581aa14610462578063f2fde38b1461046a578063fcdc8efe1461047d57600080fd5b80638da5cb5b146103f25780639cb7c5f41461041a578063d8bc7b681461043a57600080fd5b8063715f5295116100d3578063715f5295146103b157806379ba5097146103c457806384f5ed8a146103cc57806386fa4246146103df57600080fd5b806350c946fe146103695780635d83d9671461038957806366acaa331461039c57600080fd5b806323537405116101665780632c01a1e8116101405780632c01a1e81461030f578063358039f414610322578063398f3773146103355780633f2a13c91461034857600080fd5b806323537405146102c9578063275459f2146102e95780632a852933146102fc57600080fd5b8063181f5a77116101a2578063181f5a77146102365780631d05394c1461027f578063214502431461029457806322bdbcbc146102a957600080fd5b806305a51966146101c95780630fe5800a146101f25780631257001114610213575b600080fd5b6101dc6101d73660046140ab565b6104a3565b6040516101e991906141aa565b60405180910390f35b61020561020036600461436f565b61062c565b6040519081526020016101e9565b6102266102213660046143d3565b61065f565b60405190151581526020016101e9565b6102726040518060400160405280601a81526020017f4361706162696c6974696573526567697374727920312e312e3000000000000081525081565b6040516101e9919061445a565b61029261028d3660046140ab565b61066c565b005b61029c610874565b6040516101e99190614568565b6102bc6102b73660046145f6565b6109d1565b6040516101e9919061464e565b6102dc6102d73660046145f6565b610abe565b6040516101e99190614661565b6102926102f73660046140ab565b610b02565b61029261030a366004614695565b610bd9565b61029261031d3660046140ab565b610cb9565b6102926103303660046140ab565b610f5c565b6102926103433660046140ab565b6116d1565b61035b610356366004614737565b611890565b6040516101e9929190614761565b61037c6103773660046143d3565b611a7c565b6040516101e99190614786565b6102926103973660046140ab565b611b69565b6103a4611c5e565b6040516101e99190614799565b6102926103bf3660046140ab565b611e41565b610292611ef3565b6102926103da3660046140ab565b611ff0565b6102926103ed36600461480e565b61250b565b60005460405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101e9565b61042d6104283660046143d3565b61284b565b6040516101e99190614955565b610292610448366004614968565b612a86565b610455612b50565b6040516101e991906149ee565b6101dc612c44565b610292610478366004614a87565b612d55565b600e54640100000000900463ffffffff1660405163ffffffff90911681526020016101e9565b606060008267ffffffffffffffff8111156104c0576104c061422c565b60405190808252806020026020018201604052801561054f57816020015b60408051610100810182526000808252602080830182905292820181905260608083018290526080830182905260a083019190915260c0820181905260e082015282527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9092019101816104de5790505b50905060005b838110156106225761057e85858381811061057257610572614aa2565b90506020020135611a7c565b82828151811061059057610590614aa2565b602002602001018190525060008019168282815181106105b2576105b2614aa2565b6020026020010151608001510361061a578484828181106105d5576105d5614aa2565b905060200201356040517fd82f6adb00000000000000000000000000000000000000000000000000000000815260040161061191815260200190565b60405180910390fd5b600101610555565b5090505b92915050565b60008282604051602001610641929190614761565b60405160208183030381529060405280519060200120905092915050565b6000610626600583612d69565b610674612d84565b60005b8181101561086f57600083838381811061069357610693614aa2565b90506020020160208101906106a891906145f6565b63ffffffff8181166000908152600d60209081526040808320805464010000000081049095168085526001820190935290832094955093909290916a010000000000000000000090910460ff16905b61070083612e07565b8110156107a057811561075657600c600061071b8584612e11565b8152602081019190915260400160002080547fffffffffffffffffffffffffffffffffffffffff00000000ffffffffffffffff169055610798565b6107968663ffffffff16600c60006107778588612e1190919063ffffffff16565b8152602001908152602001600020600501612e1d90919063ffffffff16565b505b6001016106f7565b508354640100000000900463ffffffff166000036107f2576040517f2b62be9b00000000000000000000000000000000000000000000000000000000815263ffffffff86166004820152602401610611565b63ffffffff85166000818152600d6020908152604080832080547fffffffffffffffffffffffffffffffffffffffffff0000000000000000000000169055519182527ff264aae70bf6a9d90e68e0f9b393f4e7fbea67b063b0f336e0b36c1581703651910160405180910390a25050505050806001019050610677565b505050565b600e54606090640100000000900463ffffffff166000610895600183614b00565b63ffffffff1667ffffffffffffffff8111156108b3576108b361422c565b60405190808252806020026020018201604052801561093a57816020015b6040805160e081018252600080825260208083018290529282018190526060808301829052608083019190915260a0820181905260c082015282527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9092019101816108d15790505b509050600060015b8363ffffffff168163ffffffff1610156109ae5763ffffffff8082166000908152600d602052604090205416156109a65761097c81612e29565b83838151811061098e5761098e614aa2565b6020026020010181905250816109a390614b1d565b91505b600101610942565b506109ba600184614b00565b63ffffffff1681146109ca578082525b5092915050565b60408051808201909152600081526060602082015263ffffffff82166000908152600b60209081526040918290208251808401909352805473ffffffffffffffffffffffffffffffffffffffff1683526001810180549192840191610a3590614b55565b80601f0160208091040260200160405190810160405280929190818152602001828054610a6190614b55565b8015610aae5780601f10610a8357610100808354040283529160200191610aae565b820191906000526020600020905b815481529060010190602001808311610a9157829003601f168201915b5050505050815250509050919050565b6040805160e0810182526000808252602082018190529181018290526060808201839052608082019290925260a0810182905260c081019190915261062682612e29565b610b0a612d84565b60005b63ffffffff811682111561086f57600083838363ffffffff16818110610b3557610b35614aa2565b9050602002016020810190610b4a91906145f6565b63ffffffff81166000908152600b6020526040812080547fffffffffffffffffffffffff0000000000000000000000000000000000000000168155919250610b956001830182613ff9565b505060405163ffffffff8216907fa59268ca81d40429e65ccea5385b59cf2d3fc6519371dee92f8eb1dae5107a7a90600090a250610bd281614ba8565b9050610b0d565b610be1612d84565b63ffffffff8088166000908152600d60205260408120805490926401000000009091041690819003610c47576040517f2b62be9b00000000000000000000000000000000000000000000000000000000815263ffffffff8a166004820152602401610611565b610cae888888886040518060a001604052808f63ffffffff16815260200187610c6f90614ba8565b63ffffffff811682528b15156020830152895460ff6a01000000000000000000009091048116151560408401528b1660609092019190915296506130f4565b505050505050505050565b6000805473ffffffffffffffffffffffffffffffffffffffff163314905b82811015610f56576000848483818110610cf357610cf3614aa2565b602090810292909201356000818152600c90935260409092206001810154929350919050610d50576040517fd82f6adb00000000000000000000000000000000000000000000000000000000815260048101839052602401610611565b6000610d5e82600501612e07565b1115610db357610d716005820184612e11565b6040517f60a6d89800000000000000000000000000000000000000000000000000000000815263ffffffff909116600482015260248101839052604401610611565b805468010000000000000000900463ffffffff1615610e1b5780546040517f60b9df730000000000000000000000000000000000000000000000000000000081526801000000000000000090910463ffffffff16600482015260248101839052604401610611565b83158015610e555750805463ffffffff166000908152600b602052604090205473ffffffffffffffffffffffffffffffffffffffff163314155b15610e8e576040517f9473075d000000000000000000000000000000000000000000000000000000008152336004820152602401610611565b6001810154610e9f90600790612e1d565b506002810154610eb190600990612e1d565b506000828152600c6020526040812080547fffffffffffffffffffffffffffffffffffffffff0000000000000000000000001681556001810182905560028101829055600381018290559060058201818181610f0d8282614033565b5050505050507f5254e609a97bab37b7cc79fe128f85c097bd6015c6e1624ae0ba392eb975320582604051610f4491815260200190565b60405180910390a15050600101610cd7565b50505050565b6000805473ffffffffffffffffffffffffffffffffffffffff163314905b82811015610f56576000848483818110610f9657610f96614aa2565b9050602002810190610fa89190614bcb565b610fb190614c09565b6040808201516000908152600c6020908152828220805463ffffffff168352600b82528383208451808601909552805473ffffffffffffffffffffffffffffffffffffffff168552600181018054969750919593949390928401919061101690614b55565b80601f016020809104026020016040519081016040528092919081815260200182805461104290614b55565b801561108f5780601f106110645761010080835404028352916020019161108f565b820191906000526020600020905b81548152906001019060200180831161107257829003601f168201915b5050509190925250505060018301549091506110df5782604001516040517fd82f6adb00000000000000000000000000000000000000000000000000000000815260040161061191815260200190565b841580156111045750805173ffffffffffffffffffffffffffffffffffffffff163314155b1561113d576040517f9473075d000000000000000000000000000000000000000000000000000000008152336004820152602401610611565b6020830151611178576040517f8377314600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001820154602084015181146111f957602084015161119990600790612d69565b156111d0576040517f8377314600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b602084015160018401556111e5600782612e1d565b5060208401516111f79060079061390b565b505b606084015161123c5783606001516040517f37d8976500000000000000000000000000000000000000000000000000000000815260040161061191815260200190565b6080840151805160000361127e57806040517f3748d4c60000000000000000000000000000000000000000000000000000000081526004016106119190614ce6565b8354600090859060049061129f90640100000000900463ffffffff16614ba8565b91906101000a81548163ffffffff021916908363ffffffff1602179055905060005b8251811015611384576112f78382815181106112df576112df614aa2565b60200260200101516003612d6990919063ffffffff16565b61132f57826040517f3748d4c60000000000000000000000000000000000000000000000000000000081526004016106119190614ce6565b61137b83828151811061134457611344614aa2565b60200260200101518760040160008563ffffffff1663ffffffff16815260200190815260200160002061390b90919063ffffffff16565b506001016112c1565b50845468010000000000000000900463ffffffff1680156114e55763ffffffff8082166000908152600d60209081526040808320805464010000000090049094168352600190930181528282206002018054845181840281018401909552808552929392909183018282801561141957602002820191906000526020600020905b815481526020019060010190808311611405575b5050505050905060005b81518110156114e25761147882828151811061144157611441614aa2565b60200260200101518960040160008763ffffffff1663ffffffff168152602001908152602001600020612d6990919063ffffffff16565b6114da5781818151811061148e5761148e614aa2565b6020026020010151836040517f03dcd86200000000000000000000000000000000000000000000000000000000815260040161061192919091825263ffffffff16602082015260400190565b600101611423565b50505b60006114f387600501613917565b905060005b81518163ffffffff161015611639576000828263ffffffff168151811061152157611521614aa2565b60209081029190910181015163ffffffff8082166000908152600d845260408082208054640100000000900490931682526001909201845281812060020180548351818702810187019094528084529395509093919290918301828280156115a857602002820191906000526020600020905b815481526020019060010190808311611594575b5050505050905060005b8151811015611625576116078282815181106115d0576115d0614aa2565b60200260200101518c60040160008a63ffffffff1663ffffffff168152602001908152602001600020612d6990919063ffffffff16565b61161d5781818151811061148e5761148e614aa2565b6001016115b2565b5050508061163290614ba8565b90506114f8565b50875187547fffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000001663ffffffff90911690811788556040808a015160028a0181905560608b015160038b01556020808c01518351928352908201527f4b5b465e22eea0c3d40c30e936643245b80d19b2dcf75788c0699fe8d8db645b910160405180910390a25050505050505050806001019050610f7a565b6116d9612d84565b60005b8181101561086f5760008383838181106116f8576116f8614aa2565b905060200281019061170a9190614d2a565b61171390614d5e565b805190915073ffffffffffffffffffffffffffffffffffffffff16611764576040517feeacd93900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600e54604080518082018252835173ffffffffffffffffffffffffffffffffffffffff908116825260208086015181840190815263ffffffff9095166000818152600b909252939020825181547fffffffffffffffffffffffff000000000000000000000000000000000000000016921691909117815592519192909160018201906117f09082614e18565b5050600e805490915060009061180b9063ffffffff16614ba8565b91906101000a81548163ffffffff021916908363ffffffff160217905550816000015173ffffffffffffffffffffffffffffffffffffffff168163ffffffff167f78e94ca80be2c30abc061b99e7eb8583b1254781734b1e3ce339abb57da2fe8e846020015160405161187e919061445a565b60405180910390a350506001016116dc565b63ffffffff8083166000908152600d602090815260408083208054640100000000900490941680845260019094018252808320858452600301909152812080546060938493909290916118e290614b55565b80601f016020809104026020016040519081016040528092919081815260200182805461190e90614b55565b801561195b5780601f106119305761010080835404028352916020019161195b565b820191906000526020600020905b81548152906001019060200180831161193e57829003601f168201915b5050506000888152600260208190526040909120015492935060609262010000900473ffffffffffffffffffffffffffffffffffffffff16159150611a6e905057600086815260026020819052604091829020015490517f8318ed5d00000000000000000000000000000000000000000000000000000000815263ffffffff891660048201526201000090910473ffffffffffffffffffffffffffffffffffffffff1690638318ed5d90602401600060405180830381865afa158015611a25573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201604052611a6b9190810190614f32565b90505b9093509150505b9250929050565b604080516101008101825260008082526020820181905291810182905260608082018390526080820183905260a082019290925260c0810182905260e081019190915260408051610100810182526000848152600c6020908152838220805463ffffffff8082168652640100000000820481168487018190526801000000000000000090920416858701526001820154606086015260028201546080860152600382015460a0860152835260040190529190912060c0820190611b3e90613917565b8152602001611b61600c6000868152602001908152602001600020600501613917565b905292915050565b611b71612d84565b60005b8181101561086f576000838383818110611b9057611b90614aa2565b905060200201359050611bad816003612d6990919063ffffffff16565b611be6576040517fe181733f00000000000000000000000000000000000000000000000000000000815260048101829052602401610611565b611bf160058261390b565b611c2a576040517ff7d7a29400000000000000000000000000000000000000000000000000000000815260048101829052602401610611565b60405181907fdcea1b78b6ddc31592a94607d537543fcaafda6cc52d6d5cc7bbfca1422baf2190600090a250600101611b74565b600e5460609063ffffffff166000611c77600183614b00565b63ffffffff1667ffffffffffffffff811115611c9557611c9561422c565b604051908082528060200260200182016040528015611cdb57816020015b604080518082019091526000815260606020820152815260200190600190039081611cb35790505b509050600060015b8363ffffffff168163ffffffff161015611e2b5763ffffffff81166000908152600b602052604090205473ffffffffffffffffffffffffffffffffffffffff1615611e235763ffffffff81166000908152600b60209081526040918290208251808401909352805473ffffffffffffffffffffffffffffffffffffffff1683526001810180549192840191611d7790614b55565b80601f0160208091040260200160405190810160405280929190818152602001828054611da390614b55565b8015611df05780601f10611dc557610100808354040283529160200191611df0565b820191906000526020600020905b815481529060010190602001808311611dd357829003601f168201915b505050505081525050838381518110611e0b57611e0b614aa2565b602002602001018190525081611e2090614b1d565b91505b600101611ce3565b50600e546109ba9060019063ffffffff16614b00565b611e49612d84565b60005b8181101561086f576000838383818110611e6857611e68614aa2565b9050602002810190611e7a9190614bcb565b611e8390614faf565b90506000611e998260000151836020015161062c565b9050611ea660038261390b565b611edf576040517febf5255100000000000000000000000000000000000000000000000000000000815260048101829052602401610611565b611ee98183613924565b5050600101611e4c565b60015473ffffffffffffffffffffffffffffffffffffffff163314611f74576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e6572000000000000000000006044820152606401610611565b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b6000805473ffffffffffffffffffffffffffffffffffffffff163314905b82811015610f5657600084848381811061202a5761202a614aa2565b905060200281019061203c9190614bcb565b61204590614c09565b805163ffffffff166000908152600b602090815260408083208151808301909252805473ffffffffffffffffffffffffffffffffffffffff16825260018101805495965093949193909284019161209b90614b55565b80601f01602080910402602001604051908101604052809291908181526020018280546120c790614b55565b80156121145780601f106120e957610100808354040283529160200191612114565b820191906000526020600020905b8154815290600101906020018083116120f757829003601f168201915b50505091909252505081519192505073ffffffffffffffffffffffffffffffffffffffff1661217a5781516040517fadd9ae1e00000000000000000000000000000000000000000000000000000000815263ffffffff9091166004820152602401610611565b8315801561219f5750805173ffffffffffffffffffffffffffffffffffffffff163314155b156121d8576040517f9473075d000000000000000000000000000000000000000000000000000000008152336004820152602401610611565b6040808301516000908152600c6020522060018101541561222d5782604001516040517f5461848300000000000000000000000000000000000000000000000000000000815260040161061191815260200190565b60408301516122705782604001516040517f64e2ee9200000000000000000000000000000000000000000000000000000000815260040161061191815260200190565b6020830151158061228d5750602083015161228d90600790612d69565b156122c4576040517f8377314600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60608301516123075782606001516040517f37d8976500000000000000000000000000000000000000000000000000000000815260040161061191815260200190565b6080830151805160000361234957806040517f3748d4c60000000000000000000000000000000000000000000000000000000081526004016106119190614ce6565b8154829060049061236790640100000000900463ffffffff16614ba8565b82546101009290920a63ffffffff818102199093169183160217909155825464010000000090041660005b825181101561243d576123b08382815181106112df576112df614aa2565b6123e857826040517f3748d4c60000000000000000000000000000000000000000000000000000000081526004016106119190614ce6565b6124348382815181106123fd576123fd614aa2565b60200260200101518560040160008563ffffffff1663ffffffff16815260200190815260200160002061390b90919063ffffffff16565b50600101612392565b5060608501516003840155845183547fffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000001663ffffffff9182161784556040860151600285015560208601516001850181905561249d916007919061390b16565b5060408501516124af9060099061390b565b50845160408087015160208089015183519283529082015263ffffffff909216917f74becb12a5e8fd0e98077d02dfba8f647c9670c9df177e42c2418cf17a636f05910160405180910390a2505050505080600101905061200e565b82811461254e576040517fab8b67c60000000000000000000000000000000000000000000000000000000081526004810184905260248101829052604401610611565b6000805473ffffffffffffffffffffffffffffffffffffffff16905b8481101561284357600086868381811061258657612586614aa2565b905060200201602081019061259b91906145f6565b63ffffffff81166000908152600b6020526040902080549192509073ffffffffffffffffffffffffffffffffffffffff1661260a576040517fadd9ae1e00000000000000000000000000000000000000000000000000000000815263ffffffff83166004820152602401610611565b600086868581811061261e5761261e614aa2565b90506020028101906126309190614d2a565b61263990614d5e565b805190915073ffffffffffffffffffffffffffffffffffffffff1661268a576040517feeacd93900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b815473ffffffffffffffffffffffffffffffffffffffff1633148015906126c757503373ffffffffffffffffffffffffffffffffffffffff861614155b15612700576040517f9473075d000000000000000000000000000000000000000000000000000000008152336004820152602401610611565b8051825473ffffffffffffffffffffffffffffffffffffffff908116911614158061277c5750602080820151604051612739920161445a565b60405160208183030381529060405280519060200120826001016040516020016127639190615055565b6040516020818303038152906040528051906020012014155b1561283557805182547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff909116178255602081015160018301906127d69082614e18565b50806000015173ffffffffffffffffffffffffffffffffffffffff168363ffffffff167f86f41145bde5dd7f523305452e4aad3685508c181432ec733d5f345009358a28836020015160405161282c919061445a565b60405180910390a35b50505080600101905061256a565b505050505050565b61288c6040805160e0810182526000808252606060208301819052928201839052909182019081526020016000815260006020820181905260409091015290565b6040805160e081018252838152600084815260026020908152929020805491928301916128b890614b55565b80601f01602080910402602001604051908101604052809291908181526020018280546128e490614b55565b80156129315780601f1061290657610100808354040283529160200191612931565b820191906000526020600020905b81548152906001019060200180831161291457829003601f168201915b5050505050815260200160026000858152602001908152602001600020600101805461295c90614b55565b80601f016020809104026020016040519081016040528092919081815260200182805461298890614b55565b80156129d55780601f106129aa576101008083540402835291602001916129d5565b820191906000526020600020905b8154815290600101906020018083116129b857829003601f168201915b50505091835250506000848152600260208181526040909220015491019060ff166003811115612a0757612a0761487a565b815260008481526002602081815260409092200154910190610100900460ff166001811115612a3857612a3861487a565b81526000848152600260208181526040928390209091015462010000900473ffffffffffffffffffffffffffffffffffffffff169083015201612a7c600585612d69565b1515905292915050565b612a8e612d84565b600e805460009164010000000090910463ffffffff16906004612ab083614ba8565b82546101009290920a63ffffffff81810219909316918316021790915581166000818152600d602090815260409182902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000001684179055815160a08101835292835260019083015286151590820152841515606082015260ff84166080820152909150612b469089908990899089906130f4565b5050505050505050565b60606000612b5e6003613917565b90506000815167ffffffffffffffff811115612b7c57612b7c61422c565b604051908082528060200260200182016040528015612bee57816020015b612bdb6040805160e0810182526000808252606060208301819052928201839052909182019081526020016000815260006020820181905260409091015290565b815260200190600190039081612b9a5790505b50905060005b82518110156109ca57612c1f838281518110612c1257612c12614aa2565b602002602001015161284b565b828281518110612c3157612c31614aa2565b6020908102919091010152600101612bf4565b60606000612c526009613917565b90506000815167ffffffffffffffff811115612c7057612c7061422c565b604051908082528060200260200182016040528015612cff57816020015b60408051610100810182526000808252602080830182905292820181905260608083018290526080830182905260a083019190915260c0820181905260e082015282527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff909201910181612c8e5790505b50905060005b82518110156109ca57612d30838281518110612d2357612d23614aa2565b6020026020010151611a7c565b828281518110612d4257612d42614aa2565b6020908102919091010152600101612d05565b612d5d612d84565b612d6681613b0c565b50565b600081815260018301602052604081205415155b9392505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314612e05576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401610611565b565b6000610626825490565b6000612d7d8383613c01565b6000612d7d8383613c2b565b6040805160e0810182526000808252602080830182905282840182905260608084018390526080840183905260a0840181905260c084015263ffffffff8581168352600d8252848320805464010000000090049091168084526001909101825284832060028101805487518186028101860190985280885295969295919493909190830182828015612eda57602002820191906000526020600020905b815481526020019060010190808311612ec6575b505050505090506000815167ffffffffffffffff811115612efd57612efd61422c565b604051908082528060200260200182016040528015612f4357816020015b604080518082019091526000815260606020820152815260200190600190039081612f1b5790505b50905060005b815181101561305b576040518060400160405280848381518110612f6f57612f6f614aa2565b60200260200101518152602001856003016000868581518110612f9457612f94614aa2565b602002602001015181526020019081526020016000208054612fb590614b55565b80601f0160208091040260200160405190810160405280929190818152602001828054612fe190614b55565b801561302e5780601f106130035761010080835404028352916020019161302e565b820191906000526020600020905b81548152906001019060200180831161301157829003601f168201915b505050505081525082828151811061304857613048614aa2565b6020908102919091010152600101612f49565b506040805160e08101825263ffffffff8089166000818152600d6020818152868320548086168752948b168187015260ff680100000000000000008604811697870197909752690100000000000000000085048716151560608701529290915290526a010000000000000000000090049091161515608082015260a081016130e285613917565b81526020019190915295945050505050565b805163ffffffff9081166000908152600d602090815260408083208286015190941683526001909301905220608082015160ff161580613146575060808201518590613141906001615103565b60ff16115b1561318f5760808201516040517f25b4d61800000000000000000000000000000000000000000000000000000000815260ff909116600482015260248101869052604401610611565b6001826020015163ffffffff16111561327757815163ffffffff166000908152600d6020908152604082209084015160019182019183916131d09190614b00565b63ffffffff1663ffffffff168152602001908152602001600020905060005b6131f882612e07565b81101561327457613227846000015163ffffffff16600c60006107778587600001612e1190919063ffffffff16565b50600c60006132368484612e11565b8152602081019190915260400160002080547fffffffffffffffffffffffffffffffffffffffff00000000ffffffffffffffff1690556001016131ef565b50505b60005b858110156134b1576132a787878381811061329757613297614aa2565b859260209091020135905061390b565b6133085782518787838181106132bf576132bf614aa2565b6040517f636e405700000000000000000000000000000000000000000000000000000000815263ffffffff90941660048501526020029190910135602483015250604401610611565b82606001511561345f57825163ffffffff16600c600089898581811061333057613330614aa2565b602090810292909201358352508101919091526040016000205468010000000000000000900463ffffffff16148015906133aa5750600c600088888481811061337b5761337b614aa2565b602090810292909201358352508101919091526040016000205468010000000000000000900463ffffffff1615155b1561340c5782518787838181106133c3576133c3614aa2565b6040517f60b9df7300000000000000000000000000000000000000000000000000000000815263ffffffff90941660048501526020029190910135602483015250604401610611565b8251600c600089898581811061342457613424614aa2565b90506020020135815260200190815260200160002060000160086101000a81548163ffffffff021916908363ffffffff1602179055506134a9565b82516134a79063ffffffff16600c60008a8a8681811061348157613481614aa2565b90506020020135815260200190815260200160002060050161390b90919063ffffffff16565b505b60010161327a565b5060005b838110156138bf57368585838181106134d0576134d0614aa2565b90506020028101906134e29190614d2a565b90506134f060038235612d69565b613529576040517fe181733f00000000000000000000000000000000000000000000000000000000815281356004820152602401610611565b61353560058235612d69565b1561356f576040517ff7d7a29400000000000000000000000000000000000000000000000000000000815281356004820152602401610611565b803560009081526003840160205260408120805461358c90614b55565b905011156135d85783516040517f3927d08000000000000000000000000000000000000000000000000000000000815263ffffffff909116600482015281356024820152604401610611565b60005b878110156136e25761367f8235600c60008c8c868181106135fe576135fe614aa2565b9050602002013581526020019081526020016000206004016000600c60008e8e8881811061362e5761362e614aa2565b90506020020135815260200190815260200160002060000160049054906101000a900463ffffffff1663ffffffff1663ffffffff168152602001908152602001600020612d6990919063ffffffff16565b6136da5788888281811061369557613695614aa2565b6040517fa7e792500000000000000000000000000000000000000000000000000000000081526020909102929092013560048301525082356024820152604401610611565b6001016135db565b506002830180546001810182556000918252602091829020833591015561370b9082018261511c565b82356000908152600386016020526040902091613729919083615181565b50604080850151855163ffffffff9081166000908152600d602090815284822080549415156901000000000000000000027fffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffffff90951694909417909355606088015188518316825284822080549115156a0100000000000000000000027fffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffffffff9092169190911790556080880151885183168252848220805460ff9290921668010000000000000000027fffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffff909216919091179055828801805189518416835294909120805494909216640100000000027fffffffffffffffffffffffffffffffffffffffffffffffff00000000ffffffff909416939093179055855191516138b692918435908c908c9061387c9088018861511c565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250613d1e92505050565b506001016134b5565b50815160208084015160405163ffffffff91821681529216917ff264aae70bf6a9d90e68e0f9b393f4e7fbea67b063b0f336e0b36c1581703651910160405180910390a2505050505050565b6000612d7d8383613dff565b60606000612d7d83613e4e565b608081015173ffffffffffffffffffffffffffffffffffffffff16156139c65761397281608001517f78bea72100000000000000000000000000000000000000000000000000000000613eaa565b6139c65760808101516040517fabb5e3fd00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091166004820152602401610611565b6000828152600260205260409020815182919081906139e59082614e18565b50602082015160018201906139fa9082614e18565b5060408201516002820180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001836003811115613a3c57613a3c61487a565b021790555060608201516002820180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff16610100836001811115613a8357613a8361487a565b0217905550608091909101516002909101805473ffffffffffffffffffffffffffffffffffffffff90921662010000027fffffffffffffffffffff0000000000000000000000000000000000000000ffff90921691909117905560405182907f04f0a9bcf3f3a3b42a4d7ca081119755f82ebe43e0d30c8f7292c4fe0dc4a2ae90600090a25050565b3373ffffffffffffffffffffffffffffffffffffffff821603613b8b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401610611565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6000826000018281548110613c1857613c18614aa2565b9060005260206000200154905092915050565b60008181526001830160205260408120548015613d14576000613c4f60018361529c565b8554909150600090613c639060019061529c565b9050818114613cc8576000866000018281548110613c8357613c83614aa2565b9060005260206000200154905080876000018481548110613ca657613ca6614aa2565b6000918252602080832090910192909255918252600188019052604090208390555b8554869080613cd957613cd96152af565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050610626565b6000915050610626565b6000848152600260208190526040909120015462010000900473ffffffffffffffffffffffffffffffffffffffff161561284357600084815260026020819052604091829020015490517ffba64a7c0000000000000000000000000000000000000000000000000000000081526201000090910473ffffffffffffffffffffffffffffffffffffffff169063fba64a7c90613dc5908690869086908b908d906004016152de565b600060405180830381600087803b158015613ddf57600080fd5b505af1158015613df3573d6000803e3d6000fd5b50505050505050505050565b6000818152600183016020526040812054613e4657508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155610626565b506000610626565b606081600001805480602002602001604051908101604052809291908181526020018280548015613e9e57602002820191906000526020600020905b815481526020019060010190808311613e8a575b50505050509050919050565b6000613eb583613ec6565b8015612d7d5750612d7d8383613f2a565b6000613ef2827f01ffc9a700000000000000000000000000000000000000000000000000000000613f2a565b80156106265750613f23827fffffffff00000000000000000000000000000000000000000000000000000000613f2a565b1592915050565b604080517fffffffff000000000000000000000000000000000000000000000000000000008316602480830191909152825180830390910181526044909101909152602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f01ffc9a700000000000000000000000000000000000000000000000000000000178152825160009392849283928392918391908a617530fa92503d91506000519050828015613fe2575060208210155b8015613fee5750600081115b979650505050505050565b50805461400590614b55565b6000825580601f10614015575050565b601f016020900490600052602060002090810190612d66919061404d565b5080546000825590600052602060002090810190612d6691905b5b80821115614062576000815560010161404e565b5090565b60008083601f84011261407857600080fd5b50813567ffffffffffffffff81111561409057600080fd5b6020830191508360208260051b8501011115611a7557600080fd5b600080602083850312156140be57600080fd5b823567ffffffffffffffff8111156140d557600080fd5b6140e185828601614066565b90969095509350505050565b60008151808452602080850194506020840160005b8381101561411e57815187529582019590820190600101614102565b509495945050505050565b600061010063ffffffff80845116855280602085015116602086015280604085015116604086015250606083015160608501526080830151608085015260a083015160a085015260c08301518160c0860152614187828601826140ed565b91505060e083015184820360e08601526141a182826140ed565b95945050505050565b600060208083016020845280855180835260408601915060408160051b87010192506020870160005b8281101561421f577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc088860301845261420d858351614129565b945092850192908501906001016141d3565b5092979650505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60405160a0810167ffffffffffffffff8111828210171561427e5761427e61422c565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156142cb576142cb61422c565b604052919050565b600067ffffffffffffffff8211156142ed576142ed61422c565b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b600082601f83011261432a57600080fd5b813561433d614338826142d3565b614284565b81815284602083860101111561435257600080fd5b816020850160208301376000918101602001919091529392505050565b6000806040838503121561438257600080fd5b823567ffffffffffffffff8082111561439a57600080fd5b6143a686838701614319565b935060208501359150808211156143bc57600080fd5b506143c985828601614319565b9150509250929050565b6000602082840312156143e557600080fd5b5035919050565b60005b838110156144075781810151838201526020016143ef565b50506000910152565b600081518084526144288160208601602086016143ec565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000612d7d6020830184614410565b600082825180855260208086019550808260051b84010181860160005b848110156144ea578583037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe001895281518051845284015160408585018190526144d681860183614410565b9a86019a945050509083019060010161448a565b5090979650505050505050565b600063ffffffff8083511684528060208401511660208501525060ff604083015116604084015260608201511515606084015260808201511515608084015260a082015160e060a085015261454f60e08501826140ed565b905060c083015184820360c08601526141a1828261446d565b600060208083016020845280855180835260408601915060408160051b87010192506020870160005b8281101561421f577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc08886030184526145cb8583516144f7565b94509285019290850190600101614591565b803563ffffffff811681146145f157600080fd5b919050565b60006020828403121561460857600080fd5b612d7d826145dd565b73ffffffffffffffffffffffffffffffffffffffff815116825260006020820151604060208501526146466040850182614410565b949350505050565b602081526000612d7d6020830184614611565b602081526000612d7d60208301846144f7565b803580151581146145f157600080fd5b803560ff811681146145f157600080fd5b600080600080600080600060a0888a0312156146b057600080fd5b6146b9886145dd565b9650602088013567ffffffffffffffff808211156146d657600080fd5b6146e28b838c01614066565b909850965060408a01359150808211156146fb57600080fd5b506147088a828b01614066565b909550935061471b905060608901614674565b915061472960808901614684565b905092959891949750929550565b6000806040838503121561474a57600080fd5b614753836145dd565b946020939093013593505050565b6040815260006147746040830185614410565b82810360208401526141a18185614410565b602081526000612d7d6020830184614129565b600060208083016020845280855180835260408601915060408160051b87010192506020870160005b8281101561421f577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc08886030184526147fc858351614611565b945092850192908501906001016147c2565b6000806000806040858703121561482457600080fd5b843567ffffffffffffffff8082111561483c57600080fd5b61484888838901614066565b9096509450602087013591508082111561486157600080fd5b5061486e87828801614066565b95989497509550505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b805182526000602082015160e060208501526148c860e0850182614410565b9050604083015184820360408601526148e18282614410565b9150506060830151600481106148f9576148f961487a565b60608501526080830151600281106149135761491361487a565b8060808601525060a083015161494160a086018273ffffffffffffffffffffffffffffffffffffffff169052565b5060c083015161062260c086018215159052565b602081526000612d7d60208301846148a9565b600080600080600080600060a0888a03121561498357600080fd5b873567ffffffffffffffff8082111561499b57600080fd5b6149a78b838c01614066565b909950975060208a01359150808211156149c057600080fd5b506149cd8a828b01614066565b90965094506149e0905060408901614674565b925061471b60608901614674565b600060208083016020845280855180835260408601915060408160051b87010192506020870160005b8281101561421f577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0888603018452614a518583516148a9565b94509285019290850190600101614a17565b803573ffffffffffffffffffffffffffffffffffffffff811681146145f157600080fd5b600060208284031215614a9957600080fd5b612d7d82614a63565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b63ffffffff8281168282160390808211156109ca576109ca614ad1565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203614b4e57614b4e614ad1565b5060010190565b600181811c90821680614b6957607f821691505b602082108103614ba2577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b600063ffffffff808316818103614bc157614bc1614ad1565b6001019392505050565b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff61833603018112614bff57600080fd5b9190910192915050565b600060a08236031215614c1b57600080fd5b614c2361425b565b614c2c836145dd565b8152602080840135818301526040840135604083015260608401356060830152608084013567ffffffffffffffff80821115614c6757600080fd5b9085019036601f830112614c7a57600080fd5b813581811115614c8c57614c8c61422c565b8060051b9150614c9d848301614284565b8181529183018401918481019036841115614cb757600080fd5b938501935b83851015614cd557843582529385019390850190614cbc565b608087015250939695505050505050565b6020808252825182820181905260009190848201906040850190845b81811015614d1e57835183529284019291840191600101614d02565b50909695505050505050565b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc1833603018112614bff57600080fd5b600060408236031215614d7057600080fd5b6040516040810167ffffffffffffffff8282108183111715614d9457614d9461422c565b81604052614da185614a63565b83526020850135915080821115614db757600080fd5b50614dc436828601614319565b60208301525092915050565b601f82111561086f576000816000526020600020601f850160051c81016020861015614df95750805b601f850160051c820191505b8181101561284357828155600101614e05565b815167ffffffffffffffff811115614e3257614e3261422c565b614e4681614e408454614b55565b84614dd0565b602080601f831160018114614e995760008415614e635750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b178555612843565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b82811015614ee657888601518255948401946001909101908401614ec7565b5085821015614f2257878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b600060208284031215614f4457600080fd5b815167ffffffffffffffff811115614f5b57600080fd5b8201601f81018413614f6c57600080fd5b8051614f7a614338826142d3565b818152856020838501011115614f8f57600080fd5b6141a18260208301602086016143ec565b8035600281106145f157600080fd5b600060a08236031215614fc157600080fd5b614fc961425b565b823567ffffffffffffffff80821115614fe157600080fd5b614fed36838701614319565b8352602085013591508082111561500357600080fd5b5061501036828601614319565b60208301525060408301356004811061502857600080fd5b604082015261503960608401614fa0565b606082015261504a60808401614a63565b608082015292915050565b600060208083526000845461506981614b55565b806020870152604060018084166000811461508b57600181146150c5576150f5565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00851660408a0152604084151560051b8a010195506150f5565b89600052602060002060005b858110156150ec5781548b82018601529083019088016150d1565b8a016040019650505b509398975050505050505050565b60ff818116838216019081111561062657610626614ad1565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261515157600080fd5b83018035915067ffffffffffffffff82111561516c57600080fd5b602001915036819003821315611a7557600080fd5b67ffffffffffffffff8311156151995761519961422c565b6151ad836151a78354614b55565b83614dd0565b6000601f8411600181146151ff57600085156151c95750838201355b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600387901b1c1916600186901b178355615295565b6000838152602090207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0861690835b8281101561524e578685013582556020948501946001909201910161522e565b5086821015615289577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88860031b161c19848701351681555b505060018560011b0183555b5050505050565b8181038181111561062657610626614ad1565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b6080815284608082015260007f07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff86111561531757600080fd5b8560051b808860a0850137820182810360a0908101602085015261533d90820187614410565b91505063ffffffff8085166040840152808416606084015250969550505050505056fea164736f6c6343000818000a", -} - -var CapabilitiesRegistryABI = CapabilitiesRegistryMetaData.ABI - -var CapabilitiesRegistryBin = CapabilitiesRegistryMetaData.Bin - -func DeployCapabilitiesRegistry(auth *bind.TransactOpts, backend bind.ContractBackend) (common.Address, *types.Transaction, *CapabilitiesRegistry, error) { - parsed, err := CapabilitiesRegistryMetaData.GetAbi() - if err != nil { - return common.Address{}, nil, nil, err - } - if parsed == nil { - return common.Address{}, nil, nil, errors.New("GetABI returned nil") - } - - address, tx, contract, err := bind.DeployContract(auth, *parsed, common.FromHex(CapabilitiesRegistryBin), backend) - if err != nil { - return common.Address{}, nil, nil, err - } - return address, tx, &CapabilitiesRegistry{address: address, abi: *parsed, CapabilitiesRegistryCaller: CapabilitiesRegistryCaller{contract: contract}, CapabilitiesRegistryTransactor: CapabilitiesRegistryTransactor{contract: contract}, CapabilitiesRegistryFilterer: CapabilitiesRegistryFilterer{contract: contract}}, nil -} - -type CapabilitiesRegistry struct { - address common.Address - abi abi.ABI - CapabilitiesRegistryCaller - CapabilitiesRegistryTransactor - CapabilitiesRegistryFilterer -} - -type CapabilitiesRegistryCaller struct { - contract *bind.BoundContract -} - -type CapabilitiesRegistryTransactor struct { - contract *bind.BoundContract -} - -type CapabilitiesRegistryFilterer struct { - contract *bind.BoundContract -} - -type CapabilitiesRegistrySession struct { - Contract *CapabilitiesRegistry - CallOpts bind.CallOpts - TransactOpts bind.TransactOpts -} - -type CapabilitiesRegistryCallerSession struct { - Contract *CapabilitiesRegistryCaller - CallOpts bind.CallOpts -} - -type CapabilitiesRegistryTransactorSession struct { - Contract *CapabilitiesRegistryTransactor - TransactOpts bind.TransactOpts -} - -type CapabilitiesRegistryRaw struct { - Contract *CapabilitiesRegistry -} - -type CapabilitiesRegistryCallerRaw struct { - Contract *CapabilitiesRegistryCaller -} - -type CapabilitiesRegistryTransactorRaw struct { - Contract *CapabilitiesRegistryTransactor -} - -func NewCapabilitiesRegistry(address common.Address, backend bind.ContractBackend) (*CapabilitiesRegistry, error) { - abi, err := abi.JSON(strings.NewReader(CapabilitiesRegistryABI)) - if err != nil { - return nil, err - } - contract, err := bindCapabilitiesRegistry(address, backend, backend, backend) - if err != nil { - return nil, err - } - return &CapabilitiesRegistry{address: address, abi: abi, CapabilitiesRegistryCaller: CapabilitiesRegistryCaller{contract: contract}, CapabilitiesRegistryTransactor: CapabilitiesRegistryTransactor{contract: contract}, CapabilitiesRegistryFilterer: CapabilitiesRegistryFilterer{contract: contract}}, nil -} - -func NewCapabilitiesRegistryCaller(address common.Address, caller bind.ContractCaller) (*CapabilitiesRegistryCaller, error) { - contract, err := bindCapabilitiesRegistry(address, caller, nil, nil) - if err != nil { - return nil, err - } - return &CapabilitiesRegistryCaller{contract: contract}, nil -} - -func NewCapabilitiesRegistryTransactor(address common.Address, transactor bind.ContractTransactor) (*CapabilitiesRegistryTransactor, error) { - contract, err := bindCapabilitiesRegistry(address, nil, transactor, nil) - if err != nil { - return nil, err - } - return &CapabilitiesRegistryTransactor{contract: contract}, nil -} - -func NewCapabilitiesRegistryFilterer(address common.Address, filterer bind.ContractFilterer) (*CapabilitiesRegistryFilterer, error) { - contract, err := bindCapabilitiesRegistry(address, nil, nil, filterer) - if err != nil { - return nil, err - } - return &CapabilitiesRegistryFilterer{contract: contract}, nil -} - -func bindCapabilitiesRegistry(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { - parsed, err := CapabilitiesRegistryMetaData.GetAbi() - if err != nil { - return nil, err - } - return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil -} - -func (_CapabilitiesRegistry *CapabilitiesRegistryRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { - return _CapabilitiesRegistry.Contract.CapabilitiesRegistryCaller.contract.Call(opts, result, method, params...) -} - -func (_CapabilitiesRegistry *CapabilitiesRegistryRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { - return _CapabilitiesRegistry.Contract.CapabilitiesRegistryTransactor.contract.Transfer(opts) -} - -func (_CapabilitiesRegistry *CapabilitiesRegistryRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { - return _CapabilitiesRegistry.Contract.CapabilitiesRegistryTransactor.contract.Transact(opts, method, params...) -} - -func (_CapabilitiesRegistry *CapabilitiesRegistryCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { - return _CapabilitiesRegistry.Contract.contract.Call(opts, result, method, params...) -} - -func (_CapabilitiesRegistry *CapabilitiesRegistryTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { - return _CapabilitiesRegistry.Contract.contract.Transfer(opts) -} - -func (_CapabilitiesRegistry *CapabilitiesRegistryTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { - return _CapabilitiesRegistry.Contract.contract.Transact(opts, method, params...) -} - -func (_CapabilitiesRegistry *CapabilitiesRegistryCaller) GetCapabilities(opts *bind.CallOpts) ([]CapabilitiesRegistryCapabilityInfo, error) { - var out []interface{} - err := _CapabilitiesRegistry.contract.Call(opts, &out, "getCapabilities") - - if err != nil { - return *new([]CapabilitiesRegistryCapabilityInfo), err - } - - out0 := *abi.ConvertType(out[0], new([]CapabilitiesRegistryCapabilityInfo)).(*[]CapabilitiesRegistryCapabilityInfo) - - return out0, err - -} - -func (_CapabilitiesRegistry *CapabilitiesRegistrySession) GetCapabilities() ([]CapabilitiesRegistryCapabilityInfo, error) { - return _CapabilitiesRegistry.Contract.GetCapabilities(&_CapabilitiesRegistry.CallOpts) -} - -func (_CapabilitiesRegistry *CapabilitiesRegistryCallerSession) GetCapabilities() ([]CapabilitiesRegistryCapabilityInfo, error) { - return _CapabilitiesRegistry.Contract.GetCapabilities(&_CapabilitiesRegistry.CallOpts) -} - -func (_CapabilitiesRegistry *CapabilitiesRegistryCaller) GetCapability(opts *bind.CallOpts, hashedId [32]byte) (CapabilitiesRegistryCapabilityInfo, error) { - var out []interface{} - err := _CapabilitiesRegistry.contract.Call(opts, &out, "getCapability", hashedId) - - if err != nil { - return *new(CapabilitiesRegistryCapabilityInfo), err - } - - out0 := *abi.ConvertType(out[0], new(CapabilitiesRegistryCapabilityInfo)).(*CapabilitiesRegistryCapabilityInfo) - - return out0, err - -} - -func (_CapabilitiesRegistry *CapabilitiesRegistrySession) GetCapability(hashedId [32]byte) (CapabilitiesRegistryCapabilityInfo, error) { - return _CapabilitiesRegistry.Contract.GetCapability(&_CapabilitiesRegistry.CallOpts, hashedId) -} - -func (_CapabilitiesRegistry *CapabilitiesRegistryCallerSession) GetCapability(hashedId [32]byte) (CapabilitiesRegistryCapabilityInfo, error) { - return _CapabilitiesRegistry.Contract.GetCapability(&_CapabilitiesRegistry.CallOpts, hashedId) -} - -func (_CapabilitiesRegistry *CapabilitiesRegistryCaller) GetCapabilityConfigs(opts *bind.CallOpts, donId uint32, capabilityId [32]byte) ([]byte, []byte, error) { - var out []interface{} - err := _CapabilitiesRegistry.contract.Call(opts, &out, "getCapabilityConfigs", donId, capabilityId) - - if err != nil { - return *new([]byte), *new([]byte), err - } - - out0 := *abi.ConvertType(out[0], new([]byte)).(*[]byte) - out1 := *abi.ConvertType(out[1], new([]byte)).(*[]byte) - - return out0, out1, err - -} - -func (_CapabilitiesRegistry *CapabilitiesRegistrySession) GetCapabilityConfigs(donId uint32, capabilityId [32]byte) ([]byte, []byte, error) { - return _CapabilitiesRegistry.Contract.GetCapabilityConfigs(&_CapabilitiesRegistry.CallOpts, donId, capabilityId) -} - -func (_CapabilitiesRegistry *CapabilitiesRegistryCallerSession) GetCapabilityConfigs(donId uint32, capabilityId [32]byte) ([]byte, []byte, error) { - return _CapabilitiesRegistry.Contract.GetCapabilityConfigs(&_CapabilitiesRegistry.CallOpts, donId, capabilityId) -} - -func (_CapabilitiesRegistry *CapabilitiesRegistryCaller) GetDON(opts *bind.CallOpts, donId uint32) (CapabilitiesRegistryDONInfo, error) { - var out []interface{} - err := _CapabilitiesRegistry.contract.Call(opts, &out, "getDON", donId) - - if err != nil { - return *new(CapabilitiesRegistryDONInfo), err - } - - out0 := *abi.ConvertType(out[0], new(CapabilitiesRegistryDONInfo)).(*CapabilitiesRegistryDONInfo) - - return out0, err - -} - -func (_CapabilitiesRegistry *CapabilitiesRegistrySession) GetDON(donId uint32) (CapabilitiesRegistryDONInfo, error) { - return _CapabilitiesRegistry.Contract.GetDON(&_CapabilitiesRegistry.CallOpts, donId) -} - -func (_CapabilitiesRegistry *CapabilitiesRegistryCallerSession) GetDON(donId uint32) (CapabilitiesRegistryDONInfo, error) { - return _CapabilitiesRegistry.Contract.GetDON(&_CapabilitiesRegistry.CallOpts, donId) -} - -func (_CapabilitiesRegistry *CapabilitiesRegistryCaller) GetDONs(opts *bind.CallOpts) ([]CapabilitiesRegistryDONInfo, error) { - var out []interface{} - err := _CapabilitiesRegistry.contract.Call(opts, &out, "getDONs") - - if err != nil { - return *new([]CapabilitiesRegistryDONInfo), err - } - - out0 := *abi.ConvertType(out[0], new([]CapabilitiesRegistryDONInfo)).(*[]CapabilitiesRegistryDONInfo) - - return out0, err - -} - -func (_CapabilitiesRegistry *CapabilitiesRegistrySession) GetDONs() ([]CapabilitiesRegistryDONInfo, error) { - return _CapabilitiesRegistry.Contract.GetDONs(&_CapabilitiesRegistry.CallOpts) -} - -func (_CapabilitiesRegistry *CapabilitiesRegistryCallerSession) GetDONs() ([]CapabilitiesRegistryDONInfo, error) { - return _CapabilitiesRegistry.Contract.GetDONs(&_CapabilitiesRegistry.CallOpts) -} - -func (_CapabilitiesRegistry *CapabilitiesRegistryCaller) GetHashedCapabilityId(opts *bind.CallOpts, labelledName string, version string) ([32]byte, error) { - var out []interface{} - err := _CapabilitiesRegistry.contract.Call(opts, &out, "getHashedCapabilityId", labelledName, version) - - if err != nil { - return *new([32]byte), err - } - - out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) - - return out0, err - -} - -func (_CapabilitiesRegistry *CapabilitiesRegistrySession) GetHashedCapabilityId(labelledName string, version string) ([32]byte, error) { - return _CapabilitiesRegistry.Contract.GetHashedCapabilityId(&_CapabilitiesRegistry.CallOpts, labelledName, version) -} - -func (_CapabilitiesRegistry *CapabilitiesRegistryCallerSession) GetHashedCapabilityId(labelledName string, version string) ([32]byte, error) { - return _CapabilitiesRegistry.Contract.GetHashedCapabilityId(&_CapabilitiesRegistry.CallOpts, labelledName, version) -} - -func (_CapabilitiesRegistry *CapabilitiesRegistryCaller) GetNextDONId(opts *bind.CallOpts) (uint32, error) { - var out []interface{} - err := _CapabilitiesRegistry.contract.Call(opts, &out, "getNextDONId") - - if err != nil { - return *new(uint32), err - } - - out0 := *abi.ConvertType(out[0], new(uint32)).(*uint32) - - return out0, err - -} - -func (_CapabilitiesRegistry *CapabilitiesRegistrySession) GetNextDONId() (uint32, error) { - return _CapabilitiesRegistry.Contract.GetNextDONId(&_CapabilitiesRegistry.CallOpts) -} - -func (_CapabilitiesRegistry *CapabilitiesRegistryCallerSession) GetNextDONId() (uint32, error) { - return _CapabilitiesRegistry.Contract.GetNextDONId(&_CapabilitiesRegistry.CallOpts) -} - -func (_CapabilitiesRegistry *CapabilitiesRegistryCaller) GetNode(opts *bind.CallOpts, p2pId [32]byte) (INodeInfoProviderNodeInfo, error) { - var out []interface{} - err := _CapabilitiesRegistry.contract.Call(opts, &out, "getNode", p2pId) - - if err != nil { - return *new(INodeInfoProviderNodeInfo), err - } - - out0 := *abi.ConvertType(out[0], new(INodeInfoProviderNodeInfo)).(*INodeInfoProviderNodeInfo) - - return out0, err - -} - -func (_CapabilitiesRegistry *CapabilitiesRegistrySession) GetNode(p2pId [32]byte) (INodeInfoProviderNodeInfo, error) { - return _CapabilitiesRegistry.Contract.GetNode(&_CapabilitiesRegistry.CallOpts, p2pId) -} - -func (_CapabilitiesRegistry *CapabilitiesRegistryCallerSession) GetNode(p2pId [32]byte) (INodeInfoProviderNodeInfo, error) { - return _CapabilitiesRegistry.Contract.GetNode(&_CapabilitiesRegistry.CallOpts, p2pId) -} - -func (_CapabilitiesRegistry *CapabilitiesRegistryCaller) GetNodeOperator(opts *bind.CallOpts, nodeOperatorId uint32) (CapabilitiesRegistryNodeOperator, error) { - var out []interface{} - err := _CapabilitiesRegistry.contract.Call(opts, &out, "getNodeOperator", nodeOperatorId) - - if err != nil { - return *new(CapabilitiesRegistryNodeOperator), err - } - - out0 := *abi.ConvertType(out[0], new(CapabilitiesRegistryNodeOperator)).(*CapabilitiesRegistryNodeOperator) - - return out0, err - -} - -func (_CapabilitiesRegistry *CapabilitiesRegistrySession) GetNodeOperator(nodeOperatorId uint32) (CapabilitiesRegistryNodeOperator, error) { - return _CapabilitiesRegistry.Contract.GetNodeOperator(&_CapabilitiesRegistry.CallOpts, nodeOperatorId) -} - -func (_CapabilitiesRegistry *CapabilitiesRegistryCallerSession) GetNodeOperator(nodeOperatorId uint32) (CapabilitiesRegistryNodeOperator, error) { - return _CapabilitiesRegistry.Contract.GetNodeOperator(&_CapabilitiesRegistry.CallOpts, nodeOperatorId) -} - -func (_CapabilitiesRegistry *CapabilitiesRegistryCaller) GetNodeOperators(opts *bind.CallOpts) ([]CapabilitiesRegistryNodeOperator, error) { - var out []interface{} - err := _CapabilitiesRegistry.contract.Call(opts, &out, "getNodeOperators") - - if err != nil { - return *new([]CapabilitiesRegistryNodeOperator), err - } - - out0 := *abi.ConvertType(out[0], new([]CapabilitiesRegistryNodeOperator)).(*[]CapabilitiesRegistryNodeOperator) - - return out0, err - -} - -func (_CapabilitiesRegistry *CapabilitiesRegistrySession) GetNodeOperators() ([]CapabilitiesRegistryNodeOperator, error) { - return _CapabilitiesRegistry.Contract.GetNodeOperators(&_CapabilitiesRegistry.CallOpts) -} - -func (_CapabilitiesRegistry *CapabilitiesRegistryCallerSession) GetNodeOperators() ([]CapabilitiesRegistryNodeOperator, error) { - return _CapabilitiesRegistry.Contract.GetNodeOperators(&_CapabilitiesRegistry.CallOpts) -} - -func (_CapabilitiesRegistry *CapabilitiesRegistryCaller) GetNodes(opts *bind.CallOpts) ([]INodeInfoProviderNodeInfo, error) { - var out []interface{} - err := _CapabilitiesRegistry.contract.Call(opts, &out, "getNodes") - - if err != nil { - return *new([]INodeInfoProviderNodeInfo), err - } - - out0 := *abi.ConvertType(out[0], new([]INodeInfoProviderNodeInfo)).(*[]INodeInfoProviderNodeInfo) - - return out0, err - -} - -func (_CapabilitiesRegistry *CapabilitiesRegistrySession) GetNodes() ([]INodeInfoProviderNodeInfo, error) { - return _CapabilitiesRegistry.Contract.GetNodes(&_CapabilitiesRegistry.CallOpts) -} - -func (_CapabilitiesRegistry *CapabilitiesRegistryCallerSession) GetNodes() ([]INodeInfoProviderNodeInfo, error) { - return _CapabilitiesRegistry.Contract.GetNodes(&_CapabilitiesRegistry.CallOpts) -} - -func (_CapabilitiesRegistry *CapabilitiesRegistryCaller) GetNodesByP2PIds(opts *bind.CallOpts, p2pIds [][32]byte) ([]INodeInfoProviderNodeInfo, error) { - var out []interface{} - err := _CapabilitiesRegistry.contract.Call(opts, &out, "getNodesByP2PIds", p2pIds) - - if err != nil { - return *new([]INodeInfoProviderNodeInfo), err - } - - out0 := *abi.ConvertType(out[0], new([]INodeInfoProviderNodeInfo)).(*[]INodeInfoProviderNodeInfo) - - return out0, err - -} - -func (_CapabilitiesRegistry *CapabilitiesRegistrySession) GetNodesByP2PIds(p2pIds [][32]byte) ([]INodeInfoProviderNodeInfo, error) { - return _CapabilitiesRegistry.Contract.GetNodesByP2PIds(&_CapabilitiesRegistry.CallOpts, p2pIds) -} - -func (_CapabilitiesRegistry *CapabilitiesRegistryCallerSession) GetNodesByP2PIds(p2pIds [][32]byte) ([]INodeInfoProviderNodeInfo, error) { - return _CapabilitiesRegistry.Contract.GetNodesByP2PIds(&_CapabilitiesRegistry.CallOpts, p2pIds) -} - -func (_CapabilitiesRegistry *CapabilitiesRegistryCaller) IsCapabilityDeprecated(opts *bind.CallOpts, hashedCapabilityId [32]byte) (bool, error) { - var out []interface{} - err := _CapabilitiesRegistry.contract.Call(opts, &out, "isCapabilityDeprecated", hashedCapabilityId) - - if err != nil { - return *new(bool), err - } - - out0 := *abi.ConvertType(out[0], new(bool)).(*bool) - - return out0, err - -} - -func (_CapabilitiesRegistry *CapabilitiesRegistrySession) IsCapabilityDeprecated(hashedCapabilityId [32]byte) (bool, error) { - return _CapabilitiesRegistry.Contract.IsCapabilityDeprecated(&_CapabilitiesRegistry.CallOpts, hashedCapabilityId) -} - -func (_CapabilitiesRegistry *CapabilitiesRegistryCallerSession) IsCapabilityDeprecated(hashedCapabilityId [32]byte) (bool, error) { - return _CapabilitiesRegistry.Contract.IsCapabilityDeprecated(&_CapabilitiesRegistry.CallOpts, hashedCapabilityId) -} - -func (_CapabilitiesRegistry *CapabilitiesRegistryCaller) Owner(opts *bind.CallOpts) (common.Address, error) { - var out []interface{} - err := _CapabilitiesRegistry.contract.Call(opts, &out, "owner") - - if err != nil { - return *new(common.Address), err - } - - out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) - - return out0, err - -} - -func (_CapabilitiesRegistry *CapabilitiesRegistrySession) Owner() (common.Address, error) { - return _CapabilitiesRegistry.Contract.Owner(&_CapabilitiesRegistry.CallOpts) -} - -func (_CapabilitiesRegistry *CapabilitiesRegistryCallerSession) Owner() (common.Address, error) { - return _CapabilitiesRegistry.Contract.Owner(&_CapabilitiesRegistry.CallOpts) -} - -func (_CapabilitiesRegistry *CapabilitiesRegistryCaller) TypeAndVersion(opts *bind.CallOpts) (string, error) { - var out []interface{} - err := _CapabilitiesRegistry.contract.Call(opts, &out, "typeAndVersion") - - if err != nil { - return *new(string), err - } - - out0 := *abi.ConvertType(out[0], new(string)).(*string) - - return out0, err - -} - -func (_CapabilitiesRegistry *CapabilitiesRegistrySession) TypeAndVersion() (string, error) { - return _CapabilitiesRegistry.Contract.TypeAndVersion(&_CapabilitiesRegistry.CallOpts) -} - -func (_CapabilitiesRegistry *CapabilitiesRegistryCallerSession) TypeAndVersion() (string, error) { - return _CapabilitiesRegistry.Contract.TypeAndVersion(&_CapabilitiesRegistry.CallOpts) -} - -func (_CapabilitiesRegistry *CapabilitiesRegistryTransactor) AcceptOwnership(opts *bind.TransactOpts) (*types.Transaction, error) { - return _CapabilitiesRegistry.contract.Transact(opts, "acceptOwnership") -} - -func (_CapabilitiesRegistry *CapabilitiesRegistrySession) AcceptOwnership() (*types.Transaction, error) { - return _CapabilitiesRegistry.Contract.AcceptOwnership(&_CapabilitiesRegistry.TransactOpts) -} - -func (_CapabilitiesRegistry *CapabilitiesRegistryTransactorSession) AcceptOwnership() (*types.Transaction, error) { - return _CapabilitiesRegistry.Contract.AcceptOwnership(&_CapabilitiesRegistry.TransactOpts) -} - -func (_CapabilitiesRegistry *CapabilitiesRegistryTransactor) AddCapabilities(opts *bind.TransactOpts, capabilities []CapabilitiesRegistryCapability) (*types.Transaction, error) { - return _CapabilitiesRegistry.contract.Transact(opts, "addCapabilities", capabilities) -} - -func (_CapabilitiesRegistry *CapabilitiesRegistrySession) AddCapabilities(capabilities []CapabilitiesRegistryCapability) (*types.Transaction, error) { - return _CapabilitiesRegistry.Contract.AddCapabilities(&_CapabilitiesRegistry.TransactOpts, capabilities) -} - -func (_CapabilitiesRegistry *CapabilitiesRegistryTransactorSession) AddCapabilities(capabilities []CapabilitiesRegistryCapability) (*types.Transaction, error) { - return _CapabilitiesRegistry.Contract.AddCapabilities(&_CapabilitiesRegistry.TransactOpts, capabilities) -} - -func (_CapabilitiesRegistry *CapabilitiesRegistryTransactor) AddDON(opts *bind.TransactOpts, nodes [][32]byte, capabilityConfigurations []CapabilitiesRegistryCapabilityConfiguration, isPublic bool, acceptsWorkflows bool, f uint8) (*types.Transaction, error) { - return _CapabilitiesRegistry.contract.Transact(opts, "addDON", nodes, capabilityConfigurations, isPublic, acceptsWorkflows, f) -} - -func (_CapabilitiesRegistry *CapabilitiesRegistrySession) AddDON(nodes [][32]byte, capabilityConfigurations []CapabilitiesRegistryCapabilityConfiguration, isPublic bool, acceptsWorkflows bool, f uint8) (*types.Transaction, error) { - return _CapabilitiesRegistry.Contract.AddDON(&_CapabilitiesRegistry.TransactOpts, nodes, capabilityConfigurations, isPublic, acceptsWorkflows, f) -} - -func (_CapabilitiesRegistry *CapabilitiesRegistryTransactorSession) AddDON(nodes [][32]byte, capabilityConfigurations []CapabilitiesRegistryCapabilityConfiguration, isPublic bool, acceptsWorkflows bool, f uint8) (*types.Transaction, error) { - return _CapabilitiesRegistry.Contract.AddDON(&_CapabilitiesRegistry.TransactOpts, nodes, capabilityConfigurations, isPublic, acceptsWorkflows, f) -} - -func (_CapabilitiesRegistry *CapabilitiesRegistryTransactor) AddNodeOperators(opts *bind.TransactOpts, nodeOperators []CapabilitiesRegistryNodeOperator) (*types.Transaction, error) { - return _CapabilitiesRegistry.contract.Transact(opts, "addNodeOperators", nodeOperators) -} - -func (_CapabilitiesRegistry *CapabilitiesRegistrySession) AddNodeOperators(nodeOperators []CapabilitiesRegistryNodeOperator) (*types.Transaction, error) { - return _CapabilitiesRegistry.Contract.AddNodeOperators(&_CapabilitiesRegistry.TransactOpts, nodeOperators) -} - -func (_CapabilitiesRegistry *CapabilitiesRegistryTransactorSession) AddNodeOperators(nodeOperators []CapabilitiesRegistryNodeOperator) (*types.Transaction, error) { - return _CapabilitiesRegistry.Contract.AddNodeOperators(&_CapabilitiesRegistry.TransactOpts, nodeOperators) -} - -func (_CapabilitiesRegistry *CapabilitiesRegistryTransactor) AddNodes(opts *bind.TransactOpts, nodes []CapabilitiesRegistryNodeParams) (*types.Transaction, error) { - return _CapabilitiesRegistry.contract.Transact(opts, "addNodes", nodes) -} - -func (_CapabilitiesRegistry *CapabilitiesRegistrySession) AddNodes(nodes []CapabilitiesRegistryNodeParams) (*types.Transaction, error) { - return _CapabilitiesRegistry.Contract.AddNodes(&_CapabilitiesRegistry.TransactOpts, nodes) -} - -func (_CapabilitiesRegistry *CapabilitiesRegistryTransactorSession) AddNodes(nodes []CapabilitiesRegistryNodeParams) (*types.Transaction, error) { - return _CapabilitiesRegistry.Contract.AddNodes(&_CapabilitiesRegistry.TransactOpts, nodes) -} - -func (_CapabilitiesRegistry *CapabilitiesRegistryTransactor) DeprecateCapabilities(opts *bind.TransactOpts, hashedCapabilityIds [][32]byte) (*types.Transaction, error) { - return _CapabilitiesRegistry.contract.Transact(opts, "deprecateCapabilities", hashedCapabilityIds) -} - -func (_CapabilitiesRegistry *CapabilitiesRegistrySession) DeprecateCapabilities(hashedCapabilityIds [][32]byte) (*types.Transaction, error) { - return _CapabilitiesRegistry.Contract.DeprecateCapabilities(&_CapabilitiesRegistry.TransactOpts, hashedCapabilityIds) -} - -func (_CapabilitiesRegistry *CapabilitiesRegistryTransactorSession) DeprecateCapabilities(hashedCapabilityIds [][32]byte) (*types.Transaction, error) { - return _CapabilitiesRegistry.Contract.DeprecateCapabilities(&_CapabilitiesRegistry.TransactOpts, hashedCapabilityIds) -} - -func (_CapabilitiesRegistry *CapabilitiesRegistryTransactor) RemoveDONs(opts *bind.TransactOpts, donIds []uint32) (*types.Transaction, error) { - return _CapabilitiesRegistry.contract.Transact(opts, "removeDONs", donIds) -} - -func (_CapabilitiesRegistry *CapabilitiesRegistrySession) RemoveDONs(donIds []uint32) (*types.Transaction, error) { - return _CapabilitiesRegistry.Contract.RemoveDONs(&_CapabilitiesRegistry.TransactOpts, donIds) -} - -func (_CapabilitiesRegistry *CapabilitiesRegistryTransactorSession) RemoveDONs(donIds []uint32) (*types.Transaction, error) { - return _CapabilitiesRegistry.Contract.RemoveDONs(&_CapabilitiesRegistry.TransactOpts, donIds) -} - -func (_CapabilitiesRegistry *CapabilitiesRegistryTransactor) RemoveNodeOperators(opts *bind.TransactOpts, nodeOperatorIds []uint32) (*types.Transaction, error) { - return _CapabilitiesRegistry.contract.Transact(opts, "removeNodeOperators", nodeOperatorIds) -} - -func (_CapabilitiesRegistry *CapabilitiesRegistrySession) RemoveNodeOperators(nodeOperatorIds []uint32) (*types.Transaction, error) { - return _CapabilitiesRegistry.Contract.RemoveNodeOperators(&_CapabilitiesRegistry.TransactOpts, nodeOperatorIds) -} - -func (_CapabilitiesRegistry *CapabilitiesRegistryTransactorSession) RemoveNodeOperators(nodeOperatorIds []uint32) (*types.Transaction, error) { - return _CapabilitiesRegistry.Contract.RemoveNodeOperators(&_CapabilitiesRegistry.TransactOpts, nodeOperatorIds) -} - -func (_CapabilitiesRegistry *CapabilitiesRegistryTransactor) RemoveNodes(opts *bind.TransactOpts, removedNodeP2PIds [][32]byte) (*types.Transaction, error) { - return _CapabilitiesRegistry.contract.Transact(opts, "removeNodes", removedNodeP2PIds) -} - -func (_CapabilitiesRegistry *CapabilitiesRegistrySession) RemoveNodes(removedNodeP2PIds [][32]byte) (*types.Transaction, error) { - return _CapabilitiesRegistry.Contract.RemoveNodes(&_CapabilitiesRegistry.TransactOpts, removedNodeP2PIds) -} - -func (_CapabilitiesRegistry *CapabilitiesRegistryTransactorSession) RemoveNodes(removedNodeP2PIds [][32]byte) (*types.Transaction, error) { - return _CapabilitiesRegistry.Contract.RemoveNodes(&_CapabilitiesRegistry.TransactOpts, removedNodeP2PIds) -} - -func (_CapabilitiesRegistry *CapabilitiesRegistryTransactor) TransferOwnership(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) { - return _CapabilitiesRegistry.contract.Transact(opts, "transferOwnership", to) -} - -func (_CapabilitiesRegistry *CapabilitiesRegistrySession) TransferOwnership(to common.Address) (*types.Transaction, error) { - return _CapabilitiesRegistry.Contract.TransferOwnership(&_CapabilitiesRegistry.TransactOpts, to) -} - -func (_CapabilitiesRegistry *CapabilitiesRegistryTransactorSession) TransferOwnership(to common.Address) (*types.Transaction, error) { - return _CapabilitiesRegistry.Contract.TransferOwnership(&_CapabilitiesRegistry.TransactOpts, to) -} - -func (_CapabilitiesRegistry *CapabilitiesRegistryTransactor) UpdateDON(opts *bind.TransactOpts, donId uint32, nodes [][32]byte, capabilityConfigurations []CapabilitiesRegistryCapabilityConfiguration, isPublic bool, f uint8) (*types.Transaction, error) { - return _CapabilitiesRegistry.contract.Transact(opts, "updateDON", donId, nodes, capabilityConfigurations, isPublic, f) -} - -func (_CapabilitiesRegistry *CapabilitiesRegistrySession) UpdateDON(donId uint32, nodes [][32]byte, capabilityConfigurations []CapabilitiesRegistryCapabilityConfiguration, isPublic bool, f uint8) (*types.Transaction, error) { - return _CapabilitiesRegistry.Contract.UpdateDON(&_CapabilitiesRegistry.TransactOpts, donId, nodes, capabilityConfigurations, isPublic, f) -} - -func (_CapabilitiesRegistry *CapabilitiesRegistryTransactorSession) UpdateDON(donId uint32, nodes [][32]byte, capabilityConfigurations []CapabilitiesRegistryCapabilityConfiguration, isPublic bool, f uint8) (*types.Transaction, error) { - return _CapabilitiesRegistry.Contract.UpdateDON(&_CapabilitiesRegistry.TransactOpts, donId, nodes, capabilityConfigurations, isPublic, f) -} - -func (_CapabilitiesRegistry *CapabilitiesRegistryTransactor) UpdateNodeOperators(opts *bind.TransactOpts, nodeOperatorIds []uint32, nodeOperators []CapabilitiesRegistryNodeOperator) (*types.Transaction, error) { - return _CapabilitiesRegistry.contract.Transact(opts, "updateNodeOperators", nodeOperatorIds, nodeOperators) -} - -func (_CapabilitiesRegistry *CapabilitiesRegistrySession) UpdateNodeOperators(nodeOperatorIds []uint32, nodeOperators []CapabilitiesRegistryNodeOperator) (*types.Transaction, error) { - return _CapabilitiesRegistry.Contract.UpdateNodeOperators(&_CapabilitiesRegistry.TransactOpts, nodeOperatorIds, nodeOperators) -} - -func (_CapabilitiesRegistry *CapabilitiesRegistryTransactorSession) UpdateNodeOperators(nodeOperatorIds []uint32, nodeOperators []CapabilitiesRegistryNodeOperator) (*types.Transaction, error) { - return _CapabilitiesRegistry.Contract.UpdateNodeOperators(&_CapabilitiesRegistry.TransactOpts, nodeOperatorIds, nodeOperators) -} - -func (_CapabilitiesRegistry *CapabilitiesRegistryTransactor) UpdateNodes(opts *bind.TransactOpts, nodes []CapabilitiesRegistryNodeParams) (*types.Transaction, error) { - return _CapabilitiesRegistry.contract.Transact(opts, "updateNodes", nodes) -} - -func (_CapabilitiesRegistry *CapabilitiesRegistrySession) UpdateNodes(nodes []CapabilitiesRegistryNodeParams) (*types.Transaction, error) { - return _CapabilitiesRegistry.Contract.UpdateNodes(&_CapabilitiesRegistry.TransactOpts, nodes) -} - -func (_CapabilitiesRegistry *CapabilitiesRegistryTransactorSession) UpdateNodes(nodes []CapabilitiesRegistryNodeParams) (*types.Transaction, error) { - return _CapabilitiesRegistry.Contract.UpdateNodes(&_CapabilitiesRegistry.TransactOpts, nodes) -} - -type CapabilitiesRegistryCapabilityConfiguredIterator struct { - Event *CapabilitiesRegistryCapabilityConfigured - - contract *bind.BoundContract - event string - - logs chan types.Log - sub ethereum.Subscription - done bool - fail error -} - -func (it *CapabilitiesRegistryCapabilityConfiguredIterator) Next() bool { - - if it.fail != nil { - return false - } - - if it.done { - select { - case log := <-it.logs: - it.Event = new(CapabilitiesRegistryCapabilityConfigured) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - default: - return false - } - } - - select { - case log := <-it.logs: - it.Event = new(CapabilitiesRegistryCapabilityConfigured) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - case err := <-it.sub.Err(): - it.done = true - it.fail = err - return it.Next() - } -} - -func (it *CapabilitiesRegistryCapabilityConfiguredIterator) Error() error { - return it.fail -} - -func (it *CapabilitiesRegistryCapabilityConfiguredIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -type CapabilitiesRegistryCapabilityConfigured struct { - HashedCapabilityId [32]byte - Raw types.Log -} - -func (_CapabilitiesRegistry *CapabilitiesRegistryFilterer) FilterCapabilityConfigured(opts *bind.FilterOpts, hashedCapabilityId [][32]byte) (*CapabilitiesRegistryCapabilityConfiguredIterator, error) { - - var hashedCapabilityIdRule []interface{} - for _, hashedCapabilityIdItem := range hashedCapabilityId { - hashedCapabilityIdRule = append(hashedCapabilityIdRule, hashedCapabilityIdItem) - } - - logs, sub, err := _CapabilitiesRegistry.contract.FilterLogs(opts, "CapabilityConfigured", hashedCapabilityIdRule) - if err != nil { - return nil, err - } - return &CapabilitiesRegistryCapabilityConfiguredIterator{contract: _CapabilitiesRegistry.contract, event: "CapabilityConfigured", logs: logs, sub: sub}, nil -} - -func (_CapabilitiesRegistry *CapabilitiesRegistryFilterer) WatchCapabilityConfigured(opts *bind.WatchOpts, sink chan<- *CapabilitiesRegistryCapabilityConfigured, hashedCapabilityId [][32]byte) (event.Subscription, error) { - - var hashedCapabilityIdRule []interface{} - for _, hashedCapabilityIdItem := range hashedCapabilityId { - hashedCapabilityIdRule = append(hashedCapabilityIdRule, hashedCapabilityIdItem) - } - - logs, sub, err := _CapabilitiesRegistry.contract.WatchLogs(opts, "CapabilityConfigured", hashedCapabilityIdRule) - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - - event := new(CapabilitiesRegistryCapabilityConfigured) - if err := _CapabilitiesRegistry.contract.UnpackLog(event, "CapabilityConfigured", log); err != nil { - return err - } - event.Raw = log - - select { - case sink <- event: - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - } - }), nil -} - -func (_CapabilitiesRegistry *CapabilitiesRegistryFilterer) ParseCapabilityConfigured(log types.Log) (*CapabilitiesRegistryCapabilityConfigured, error) { - event := new(CapabilitiesRegistryCapabilityConfigured) - if err := _CapabilitiesRegistry.contract.UnpackLog(event, "CapabilityConfigured", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -type CapabilitiesRegistryCapabilityDeprecatedIterator struct { - Event *CapabilitiesRegistryCapabilityDeprecated - - contract *bind.BoundContract - event string - - logs chan types.Log - sub ethereum.Subscription - done bool - fail error -} - -func (it *CapabilitiesRegistryCapabilityDeprecatedIterator) Next() bool { - - if it.fail != nil { - return false - } - - if it.done { - select { - case log := <-it.logs: - it.Event = new(CapabilitiesRegistryCapabilityDeprecated) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - default: - return false - } - } - - select { - case log := <-it.logs: - it.Event = new(CapabilitiesRegistryCapabilityDeprecated) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - case err := <-it.sub.Err(): - it.done = true - it.fail = err - return it.Next() - } -} - -func (it *CapabilitiesRegistryCapabilityDeprecatedIterator) Error() error { - return it.fail -} - -func (it *CapabilitiesRegistryCapabilityDeprecatedIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -type CapabilitiesRegistryCapabilityDeprecated struct { - HashedCapabilityId [32]byte - Raw types.Log -} - -func (_CapabilitiesRegistry *CapabilitiesRegistryFilterer) FilterCapabilityDeprecated(opts *bind.FilterOpts, hashedCapabilityId [][32]byte) (*CapabilitiesRegistryCapabilityDeprecatedIterator, error) { - - var hashedCapabilityIdRule []interface{} - for _, hashedCapabilityIdItem := range hashedCapabilityId { - hashedCapabilityIdRule = append(hashedCapabilityIdRule, hashedCapabilityIdItem) - } - - logs, sub, err := _CapabilitiesRegistry.contract.FilterLogs(opts, "CapabilityDeprecated", hashedCapabilityIdRule) - if err != nil { - return nil, err - } - return &CapabilitiesRegistryCapabilityDeprecatedIterator{contract: _CapabilitiesRegistry.contract, event: "CapabilityDeprecated", logs: logs, sub: sub}, nil -} - -func (_CapabilitiesRegistry *CapabilitiesRegistryFilterer) WatchCapabilityDeprecated(opts *bind.WatchOpts, sink chan<- *CapabilitiesRegistryCapabilityDeprecated, hashedCapabilityId [][32]byte) (event.Subscription, error) { - - var hashedCapabilityIdRule []interface{} - for _, hashedCapabilityIdItem := range hashedCapabilityId { - hashedCapabilityIdRule = append(hashedCapabilityIdRule, hashedCapabilityIdItem) - } - - logs, sub, err := _CapabilitiesRegistry.contract.WatchLogs(opts, "CapabilityDeprecated", hashedCapabilityIdRule) - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - - event := new(CapabilitiesRegistryCapabilityDeprecated) - if err := _CapabilitiesRegistry.contract.UnpackLog(event, "CapabilityDeprecated", log); err != nil { - return err - } - event.Raw = log - - select { - case sink <- event: - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - } - }), nil -} - -func (_CapabilitiesRegistry *CapabilitiesRegistryFilterer) ParseCapabilityDeprecated(log types.Log) (*CapabilitiesRegistryCapabilityDeprecated, error) { - event := new(CapabilitiesRegistryCapabilityDeprecated) - if err := _CapabilitiesRegistry.contract.UnpackLog(event, "CapabilityDeprecated", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -type CapabilitiesRegistryConfigSetIterator struct { - Event *CapabilitiesRegistryConfigSet - - contract *bind.BoundContract - event string - - logs chan types.Log - sub ethereum.Subscription - done bool - fail error -} - -func (it *CapabilitiesRegistryConfigSetIterator) Next() bool { - - if it.fail != nil { - return false - } - - if it.done { - select { - case log := <-it.logs: - it.Event = new(CapabilitiesRegistryConfigSet) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - default: - return false - } - } - - select { - case log := <-it.logs: - it.Event = new(CapabilitiesRegistryConfigSet) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - case err := <-it.sub.Err(): - it.done = true - it.fail = err - return it.Next() - } -} - -func (it *CapabilitiesRegistryConfigSetIterator) Error() error { - return it.fail -} - -func (it *CapabilitiesRegistryConfigSetIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -type CapabilitiesRegistryConfigSet struct { - DonId uint32 - ConfigCount uint32 - Raw types.Log -} - -func (_CapabilitiesRegistry *CapabilitiesRegistryFilterer) FilterConfigSet(opts *bind.FilterOpts, donId []uint32) (*CapabilitiesRegistryConfigSetIterator, error) { - - var donIdRule []interface{} - for _, donIdItem := range donId { - donIdRule = append(donIdRule, donIdItem) - } - - logs, sub, err := _CapabilitiesRegistry.contract.FilterLogs(opts, "ConfigSet", donIdRule) - if err != nil { - return nil, err - } - return &CapabilitiesRegistryConfigSetIterator{contract: _CapabilitiesRegistry.contract, event: "ConfigSet", logs: logs, sub: sub}, nil -} - -func (_CapabilitiesRegistry *CapabilitiesRegistryFilterer) WatchConfigSet(opts *bind.WatchOpts, sink chan<- *CapabilitiesRegistryConfigSet, donId []uint32) (event.Subscription, error) { - - var donIdRule []interface{} - for _, donIdItem := range donId { - donIdRule = append(donIdRule, donIdItem) - } - - logs, sub, err := _CapabilitiesRegistry.contract.WatchLogs(opts, "ConfigSet", donIdRule) - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - - event := new(CapabilitiesRegistryConfigSet) - if err := _CapabilitiesRegistry.contract.UnpackLog(event, "ConfigSet", log); err != nil { - return err - } - event.Raw = log - - select { - case sink <- event: - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - } - }), nil -} - -func (_CapabilitiesRegistry *CapabilitiesRegistryFilterer) ParseConfigSet(log types.Log) (*CapabilitiesRegistryConfigSet, error) { - event := new(CapabilitiesRegistryConfigSet) - if err := _CapabilitiesRegistry.contract.UnpackLog(event, "ConfigSet", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -type CapabilitiesRegistryNodeAddedIterator struct { - Event *CapabilitiesRegistryNodeAdded - - contract *bind.BoundContract - event string - - logs chan types.Log - sub ethereum.Subscription - done bool - fail error -} - -func (it *CapabilitiesRegistryNodeAddedIterator) Next() bool { - - if it.fail != nil { - return false - } - - if it.done { - select { - case log := <-it.logs: - it.Event = new(CapabilitiesRegistryNodeAdded) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - default: - return false - } - } - - select { - case log := <-it.logs: - it.Event = new(CapabilitiesRegistryNodeAdded) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - case err := <-it.sub.Err(): - it.done = true - it.fail = err - return it.Next() - } -} - -func (it *CapabilitiesRegistryNodeAddedIterator) Error() error { - return it.fail -} - -func (it *CapabilitiesRegistryNodeAddedIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -type CapabilitiesRegistryNodeAdded struct { - P2pId [32]byte - NodeOperatorId uint32 - Signer [32]byte - Raw types.Log -} - -func (_CapabilitiesRegistry *CapabilitiesRegistryFilterer) FilterNodeAdded(opts *bind.FilterOpts, nodeOperatorId []uint32) (*CapabilitiesRegistryNodeAddedIterator, error) { - - var nodeOperatorIdRule []interface{} - for _, nodeOperatorIdItem := range nodeOperatorId { - nodeOperatorIdRule = append(nodeOperatorIdRule, nodeOperatorIdItem) - } - - logs, sub, err := _CapabilitiesRegistry.contract.FilterLogs(opts, "NodeAdded", nodeOperatorIdRule) - if err != nil { - return nil, err - } - return &CapabilitiesRegistryNodeAddedIterator{contract: _CapabilitiesRegistry.contract, event: "NodeAdded", logs: logs, sub: sub}, nil -} - -func (_CapabilitiesRegistry *CapabilitiesRegistryFilterer) WatchNodeAdded(opts *bind.WatchOpts, sink chan<- *CapabilitiesRegistryNodeAdded, nodeOperatorId []uint32) (event.Subscription, error) { - - var nodeOperatorIdRule []interface{} - for _, nodeOperatorIdItem := range nodeOperatorId { - nodeOperatorIdRule = append(nodeOperatorIdRule, nodeOperatorIdItem) - } - - logs, sub, err := _CapabilitiesRegistry.contract.WatchLogs(opts, "NodeAdded", nodeOperatorIdRule) - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - - event := new(CapabilitiesRegistryNodeAdded) - if err := _CapabilitiesRegistry.contract.UnpackLog(event, "NodeAdded", log); err != nil { - return err - } - event.Raw = log - - select { - case sink <- event: - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - } - }), nil -} - -func (_CapabilitiesRegistry *CapabilitiesRegistryFilterer) ParseNodeAdded(log types.Log) (*CapabilitiesRegistryNodeAdded, error) { - event := new(CapabilitiesRegistryNodeAdded) - if err := _CapabilitiesRegistry.contract.UnpackLog(event, "NodeAdded", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -type CapabilitiesRegistryNodeOperatorAddedIterator struct { - Event *CapabilitiesRegistryNodeOperatorAdded - - contract *bind.BoundContract - event string - - logs chan types.Log - sub ethereum.Subscription - done bool - fail error -} - -func (it *CapabilitiesRegistryNodeOperatorAddedIterator) Next() bool { - - if it.fail != nil { - return false - } - - if it.done { - select { - case log := <-it.logs: - it.Event = new(CapabilitiesRegistryNodeOperatorAdded) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - default: - return false - } - } - - select { - case log := <-it.logs: - it.Event = new(CapabilitiesRegistryNodeOperatorAdded) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - case err := <-it.sub.Err(): - it.done = true - it.fail = err - return it.Next() - } -} - -func (it *CapabilitiesRegistryNodeOperatorAddedIterator) Error() error { - return it.fail -} - -func (it *CapabilitiesRegistryNodeOperatorAddedIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -type CapabilitiesRegistryNodeOperatorAdded struct { - NodeOperatorId uint32 - Admin common.Address - Name string - Raw types.Log -} - -func (_CapabilitiesRegistry *CapabilitiesRegistryFilterer) FilterNodeOperatorAdded(opts *bind.FilterOpts, nodeOperatorId []uint32, admin []common.Address) (*CapabilitiesRegistryNodeOperatorAddedIterator, error) { - - var nodeOperatorIdRule []interface{} - for _, nodeOperatorIdItem := range nodeOperatorId { - nodeOperatorIdRule = append(nodeOperatorIdRule, nodeOperatorIdItem) - } - var adminRule []interface{} - for _, adminItem := range admin { - adminRule = append(adminRule, adminItem) - } - - logs, sub, err := _CapabilitiesRegistry.contract.FilterLogs(opts, "NodeOperatorAdded", nodeOperatorIdRule, adminRule) - if err != nil { - return nil, err - } - return &CapabilitiesRegistryNodeOperatorAddedIterator{contract: _CapabilitiesRegistry.contract, event: "NodeOperatorAdded", logs: logs, sub: sub}, nil -} - -func (_CapabilitiesRegistry *CapabilitiesRegistryFilterer) WatchNodeOperatorAdded(opts *bind.WatchOpts, sink chan<- *CapabilitiesRegistryNodeOperatorAdded, nodeOperatorId []uint32, admin []common.Address) (event.Subscription, error) { - - var nodeOperatorIdRule []interface{} - for _, nodeOperatorIdItem := range nodeOperatorId { - nodeOperatorIdRule = append(nodeOperatorIdRule, nodeOperatorIdItem) - } - var adminRule []interface{} - for _, adminItem := range admin { - adminRule = append(adminRule, adminItem) - } - - logs, sub, err := _CapabilitiesRegistry.contract.WatchLogs(opts, "NodeOperatorAdded", nodeOperatorIdRule, adminRule) - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - - event := new(CapabilitiesRegistryNodeOperatorAdded) - if err := _CapabilitiesRegistry.contract.UnpackLog(event, "NodeOperatorAdded", log); err != nil { - return err - } - event.Raw = log - - select { - case sink <- event: - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - } - }), nil -} - -func (_CapabilitiesRegistry *CapabilitiesRegistryFilterer) ParseNodeOperatorAdded(log types.Log) (*CapabilitiesRegistryNodeOperatorAdded, error) { - event := new(CapabilitiesRegistryNodeOperatorAdded) - if err := _CapabilitiesRegistry.contract.UnpackLog(event, "NodeOperatorAdded", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -type CapabilitiesRegistryNodeOperatorRemovedIterator struct { - Event *CapabilitiesRegistryNodeOperatorRemoved - - contract *bind.BoundContract - event string - - logs chan types.Log - sub ethereum.Subscription - done bool - fail error -} - -func (it *CapabilitiesRegistryNodeOperatorRemovedIterator) Next() bool { - - if it.fail != nil { - return false - } - - if it.done { - select { - case log := <-it.logs: - it.Event = new(CapabilitiesRegistryNodeOperatorRemoved) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - default: - return false - } - } - - select { - case log := <-it.logs: - it.Event = new(CapabilitiesRegistryNodeOperatorRemoved) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - case err := <-it.sub.Err(): - it.done = true - it.fail = err - return it.Next() - } -} - -func (it *CapabilitiesRegistryNodeOperatorRemovedIterator) Error() error { - return it.fail -} - -func (it *CapabilitiesRegistryNodeOperatorRemovedIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -type CapabilitiesRegistryNodeOperatorRemoved struct { - NodeOperatorId uint32 - Raw types.Log -} - -func (_CapabilitiesRegistry *CapabilitiesRegistryFilterer) FilterNodeOperatorRemoved(opts *bind.FilterOpts, nodeOperatorId []uint32) (*CapabilitiesRegistryNodeOperatorRemovedIterator, error) { - - var nodeOperatorIdRule []interface{} - for _, nodeOperatorIdItem := range nodeOperatorId { - nodeOperatorIdRule = append(nodeOperatorIdRule, nodeOperatorIdItem) - } - - logs, sub, err := _CapabilitiesRegistry.contract.FilterLogs(opts, "NodeOperatorRemoved", nodeOperatorIdRule) - if err != nil { - return nil, err - } - return &CapabilitiesRegistryNodeOperatorRemovedIterator{contract: _CapabilitiesRegistry.contract, event: "NodeOperatorRemoved", logs: logs, sub: sub}, nil -} - -func (_CapabilitiesRegistry *CapabilitiesRegistryFilterer) WatchNodeOperatorRemoved(opts *bind.WatchOpts, sink chan<- *CapabilitiesRegistryNodeOperatorRemoved, nodeOperatorId []uint32) (event.Subscription, error) { - - var nodeOperatorIdRule []interface{} - for _, nodeOperatorIdItem := range nodeOperatorId { - nodeOperatorIdRule = append(nodeOperatorIdRule, nodeOperatorIdItem) - } - - logs, sub, err := _CapabilitiesRegistry.contract.WatchLogs(opts, "NodeOperatorRemoved", nodeOperatorIdRule) - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - - event := new(CapabilitiesRegistryNodeOperatorRemoved) - if err := _CapabilitiesRegistry.contract.UnpackLog(event, "NodeOperatorRemoved", log); err != nil { - return err - } - event.Raw = log - - select { - case sink <- event: - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - } - }), nil -} - -func (_CapabilitiesRegistry *CapabilitiesRegistryFilterer) ParseNodeOperatorRemoved(log types.Log) (*CapabilitiesRegistryNodeOperatorRemoved, error) { - event := new(CapabilitiesRegistryNodeOperatorRemoved) - if err := _CapabilitiesRegistry.contract.UnpackLog(event, "NodeOperatorRemoved", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -type CapabilitiesRegistryNodeOperatorUpdatedIterator struct { - Event *CapabilitiesRegistryNodeOperatorUpdated - - contract *bind.BoundContract - event string - - logs chan types.Log - sub ethereum.Subscription - done bool - fail error -} - -func (it *CapabilitiesRegistryNodeOperatorUpdatedIterator) Next() bool { - - if it.fail != nil { - return false - } - - if it.done { - select { - case log := <-it.logs: - it.Event = new(CapabilitiesRegistryNodeOperatorUpdated) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - default: - return false - } - } - - select { - case log := <-it.logs: - it.Event = new(CapabilitiesRegistryNodeOperatorUpdated) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - case err := <-it.sub.Err(): - it.done = true - it.fail = err - return it.Next() - } -} - -func (it *CapabilitiesRegistryNodeOperatorUpdatedIterator) Error() error { - return it.fail -} - -func (it *CapabilitiesRegistryNodeOperatorUpdatedIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -type CapabilitiesRegistryNodeOperatorUpdated struct { - NodeOperatorId uint32 - Admin common.Address - Name string - Raw types.Log -} - -func (_CapabilitiesRegistry *CapabilitiesRegistryFilterer) FilterNodeOperatorUpdated(opts *bind.FilterOpts, nodeOperatorId []uint32, admin []common.Address) (*CapabilitiesRegistryNodeOperatorUpdatedIterator, error) { - - var nodeOperatorIdRule []interface{} - for _, nodeOperatorIdItem := range nodeOperatorId { - nodeOperatorIdRule = append(nodeOperatorIdRule, nodeOperatorIdItem) - } - var adminRule []interface{} - for _, adminItem := range admin { - adminRule = append(adminRule, adminItem) - } - - logs, sub, err := _CapabilitiesRegistry.contract.FilterLogs(opts, "NodeOperatorUpdated", nodeOperatorIdRule, adminRule) - if err != nil { - return nil, err - } - return &CapabilitiesRegistryNodeOperatorUpdatedIterator{contract: _CapabilitiesRegistry.contract, event: "NodeOperatorUpdated", logs: logs, sub: sub}, nil -} - -func (_CapabilitiesRegistry *CapabilitiesRegistryFilterer) WatchNodeOperatorUpdated(opts *bind.WatchOpts, sink chan<- *CapabilitiesRegistryNodeOperatorUpdated, nodeOperatorId []uint32, admin []common.Address) (event.Subscription, error) { - - var nodeOperatorIdRule []interface{} - for _, nodeOperatorIdItem := range nodeOperatorId { - nodeOperatorIdRule = append(nodeOperatorIdRule, nodeOperatorIdItem) - } - var adminRule []interface{} - for _, adminItem := range admin { - adminRule = append(adminRule, adminItem) - } - - logs, sub, err := _CapabilitiesRegistry.contract.WatchLogs(opts, "NodeOperatorUpdated", nodeOperatorIdRule, adminRule) - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - - event := new(CapabilitiesRegistryNodeOperatorUpdated) - if err := _CapabilitiesRegistry.contract.UnpackLog(event, "NodeOperatorUpdated", log); err != nil { - return err - } - event.Raw = log - - select { - case sink <- event: - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - } - }), nil -} - -func (_CapabilitiesRegistry *CapabilitiesRegistryFilterer) ParseNodeOperatorUpdated(log types.Log) (*CapabilitiesRegistryNodeOperatorUpdated, error) { - event := new(CapabilitiesRegistryNodeOperatorUpdated) - if err := _CapabilitiesRegistry.contract.UnpackLog(event, "NodeOperatorUpdated", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -type CapabilitiesRegistryNodeRemovedIterator struct { - Event *CapabilitiesRegistryNodeRemoved - - contract *bind.BoundContract - event string - - logs chan types.Log - sub ethereum.Subscription - done bool - fail error -} - -func (it *CapabilitiesRegistryNodeRemovedIterator) Next() bool { - - if it.fail != nil { - return false - } - - if it.done { - select { - case log := <-it.logs: - it.Event = new(CapabilitiesRegistryNodeRemoved) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - default: - return false - } - } - - select { - case log := <-it.logs: - it.Event = new(CapabilitiesRegistryNodeRemoved) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - case err := <-it.sub.Err(): - it.done = true - it.fail = err - return it.Next() - } -} - -func (it *CapabilitiesRegistryNodeRemovedIterator) Error() error { - return it.fail -} - -func (it *CapabilitiesRegistryNodeRemovedIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -type CapabilitiesRegistryNodeRemoved struct { - P2pId [32]byte - Raw types.Log -} - -func (_CapabilitiesRegistry *CapabilitiesRegistryFilterer) FilterNodeRemoved(opts *bind.FilterOpts) (*CapabilitiesRegistryNodeRemovedIterator, error) { - - logs, sub, err := _CapabilitiesRegistry.contract.FilterLogs(opts, "NodeRemoved") - if err != nil { - return nil, err - } - return &CapabilitiesRegistryNodeRemovedIterator{contract: _CapabilitiesRegistry.contract, event: "NodeRemoved", logs: logs, sub: sub}, nil -} - -func (_CapabilitiesRegistry *CapabilitiesRegistryFilterer) WatchNodeRemoved(opts *bind.WatchOpts, sink chan<- *CapabilitiesRegistryNodeRemoved) (event.Subscription, error) { - - logs, sub, err := _CapabilitiesRegistry.contract.WatchLogs(opts, "NodeRemoved") - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - - event := new(CapabilitiesRegistryNodeRemoved) - if err := _CapabilitiesRegistry.contract.UnpackLog(event, "NodeRemoved", log); err != nil { - return err - } - event.Raw = log - - select { - case sink <- event: - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - } - }), nil -} - -func (_CapabilitiesRegistry *CapabilitiesRegistryFilterer) ParseNodeRemoved(log types.Log) (*CapabilitiesRegistryNodeRemoved, error) { - event := new(CapabilitiesRegistryNodeRemoved) - if err := _CapabilitiesRegistry.contract.UnpackLog(event, "NodeRemoved", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -type CapabilitiesRegistryNodeUpdatedIterator struct { - Event *CapabilitiesRegistryNodeUpdated - - contract *bind.BoundContract - event string - - logs chan types.Log - sub ethereum.Subscription - done bool - fail error -} - -func (it *CapabilitiesRegistryNodeUpdatedIterator) Next() bool { - - if it.fail != nil { - return false - } - - if it.done { - select { - case log := <-it.logs: - it.Event = new(CapabilitiesRegistryNodeUpdated) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - default: - return false - } - } - - select { - case log := <-it.logs: - it.Event = new(CapabilitiesRegistryNodeUpdated) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - case err := <-it.sub.Err(): - it.done = true - it.fail = err - return it.Next() - } -} - -func (it *CapabilitiesRegistryNodeUpdatedIterator) Error() error { - return it.fail -} - -func (it *CapabilitiesRegistryNodeUpdatedIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -type CapabilitiesRegistryNodeUpdated struct { - P2pId [32]byte - NodeOperatorId uint32 - Signer [32]byte - Raw types.Log -} - -func (_CapabilitiesRegistry *CapabilitiesRegistryFilterer) FilterNodeUpdated(opts *bind.FilterOpts, nodeOperatorId []uint32) (*CapabilitiesRegistryNodeUpdatedIterator, error) { - - var nodeOperatorIdRule []interface{} - for _, nodeOperatorIdItem := range nodeOperatorId { - nodeOperatorIdRule = append(nodeOperatorIdRule, nodeOperatorIdItem) - } - - logs, sub, err := _CapabilitiesRegistry.contract.FilterLogs(opts, "NodeUpdated", nodeOperatorIdRule) - if err != nil { - return nil, err - } - return &CapabilitiesRegistryNodeUpdatedIterator{contract: _CapabilitiesRegistry.contract, event: "NodeUpdated", logs: logs, sub: sub}, nil -} - -func (_CapabilitiesRegistry *CapabilitiesRegistryFilterer) WatchNodeUpdated(opts *bind.WatchOpts, sink chan<- *CapabilitiesRegistryNodeUpdated, nodeOperatorId []uint32) (event.Subscription, error) { - - var nodeOperatorIdRule []interface{} - for _, nodeOperatorIdItem := range nodeOperatorId { - nodeOperatorIdRule = append(nodeOperatorIdRule, nodeOperatorIdItem) - } - - logs, sub, err := _CapabilitiesRegistry.contract.WatchLogs(opts, "NodeUpdated", nodeOperatorIdRule) - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - - event := new(CapabilitiesRegistryNodeUpdated) - if err := _CapabilitiesRegistry.contract.UnpackLog(event, "NodeUpdated", log); err != nil { - return err - } - event.Raw = log - - select { - case sink <- event: - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - } - }), nil -} - -func (_CapabilitiesRegistry *CapabilitiesRegistryFilterer) ParseNodeUpdated(log types.Log) (*CapabilitiesRegistryNodeUpdated, error) { - event := new(CapabilitiesRegistryNodeUpdated) - if err := _CapabilitiesRegistry.contract.UnpackLog(event, "NodeUpdated", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -type CapabilitiesRegistryOwnershipTransferRequestedIterator struct { - Event *CapabilitiesRegistryOwnershipTransferRequested - - contract *bind.BoundContract - event string - - logs chan types.Log - sub ethereum.Subscription - done bool - fail error -} - -func (it *CapabilitiesRegistryOwnershipTransferRequestedIterator) Next() bool { - - if it.fail != nil { - return false - } - - if it.done { - select { - case log := <-it.logs: - it.Event = new(CapabilitiesRegistryOwnershipTransferRequested) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - default: - return false - } - } - - select { - case log := <-it.logs: - it.Event = new(CapabilitiesRegistryOwnershipTransferRequested) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - case err := <-it.sub.Err(): - it.done = true - it.fail = err - return it.Next() - } -} - -func (it *CapabilitiesRegistryOwnershipTransferRequestedIterator) Error() error { - return it.fail -} - -func (it *CapabilitiesRegistryOwnershipTransferRequestedIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -type CapabilitiesRegistryOwnershipTransferRequested struct { - From common.Address - To common.Address - Raw types.Log -} - -func (_CapabilitiesRegistry *CapabilitiesRegistryFilterer) FilterOwnershipTransferRequested(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*CapabilitiesRegistryOwnershipTransferRequestedIterator, error) { - - var fromRule []interface{} - for _, fromItem := range from { - fromRule = append(fromRule, fromItem) - } - var toRule []interface{} - for _, toItem := range to { - toRule = append(toRule, toItem) - } - - logs, sub, err := _CapabilitiesRegistry.contract.FilterLogs(opts, "OwnershipTransferRequested", fromRule, toRule) - if err != nil { - return nil, err - } - return &CapabilitiesRegistryOwnershipTransferRequestedIterator{contract: _CapabilitiesRegistry.contract, event: "OwnershipTransferRequested", logs: logs, sub: sub}, nil -} - -func (_CapabilitiesRegistry *CapabilitiesRegistryFilterer) WatchOwnershipTransferRequested(opts *bind.WatchOpts, sink chan<- *CapabilitiesRegistryOwnershipTransferRequested, from []common.Address, to []common.Address) (event.Subscription, error) { - - var fromRule []interface{} - for _, fromItem := range from { - fromRule = append(fromRule, fromItem) - } - var toRule []interface{} - for _, toItem := range to { - toRule = append(toRule, toItem) - } - - logs, sub, err := _CapabilitiesRegistry.contract.WatchLogs(opts, "OwnershipTransferRequested", fromRule, toRule) - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - - event := new(CapabilitiesRegistryOwnershipTransferRequested) - if err := _CapabilitiesRegistry.contract.UnpackLog(event, "OwnershipTransferRequested", log); err != nil { - return err - } - event.Raw = log - - select { - case sink <- event: - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - } - }), nil -} - -func (_CapabilitiesRegistry *CapabilitiesRegistryFilterer) ParseOwnershipTransferRequested(log types.Log) (*CapabilitiesRegistryOwnershipTransferRequested, error) { - event := new(CapabilitiesRegistryOwnershipTransferRequested) - if err := _CapabilitiesRegistry.contract.UnpackLog(event, "OwnershipTransferRequested", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -type CapabilitiesRegistryOwnershipTransferredIterator struct { - Event *CapabilitiesRegistryOwnershipTransferred - - contract *bind.BoundContract - event string - - logs chan types.Log - sub ethereum.Subscription - done bool - fail error -} - -func (it *CapabilitiesRegistryOwnershipTransferredIterator) Next() bool { - - if it.fail != nil { - return false - } - - if it.done { - select { - case log := <-it.logs: - it.Event = new(CapabilitiesRegistryOwnershipTransferred) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - default: - return false - } - } - - select { - case log := <-it.logs: - it.Event = new(CapabilitiesRegistryOwnershipTransferred) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - case err := <-it.sub.Err(): - it.done = true - it.fail = err - return it.Next() - } -} - -func (it *CapabilitiesRegistryOwnershipTransferredIterator) Error() error { - return it.fail -} - -func (it *CapabilitiesRegistryOwnershipTransferredIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -type CapabilitiesRegistryOwnershipTransferred struct { - From common.Address - To common.Address - Raw types.Log -} - -func (_CapabilitiesRegistry *CapabilitiesRegistryFilterer) FilterOwnershipTransferred(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*CapabilitiesRegistryOwnershipTransferredIterator, error) { - - var fromRule []interface{} - for _, fromItem := range from { - fromRule = append(fromRule, fromItem) - } - var toRule []interface{} - for _, toItem := range to { - toRule = append(toRule, toItem) - } - - logs, sub, err := _CapabilitiesRegistry.contract.FilterLogs(opts, "OwnershipTransferred", fromRule, toRule) - if err != nil { - return nil, err - } - return &CapabilitiesRegistryOwnershipTransferredIterator{contract: _CapabilitiesRegistry.contract, event: "OwnershipTransferred", logs: logs, sub: sub}, nil -} - -func (_CapabilitiesRegistry *CapabilitiesRegistryFilterer) WatchOwnershipTransferred(opts *bind.WatchOpts, sink chan<- *CapabilitiesRegistryOwnershipTransferred, from []common.Address, to []common.Address) (event.Subscription, error) { - - var fromRule []interface{} - for _, fromItem := range from { - fromRule = append(fromRule, fromItem) - } - var toRule []interface{} - for _, toItem := range to { - toRule = append(toRule, toItem) - } - - logs, sub, err := _CapabilitiesRegistry.contract.WatchLogs(opts, "OwnershipTransferred", fromRule, toRule) - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - - event := new(CapabilitiesRegistryOwnershipTransferred) - if err := _CapabilitiesRegistry.contract.UnpackLog(event, "OwnershipTransferred", log); err != nil { - return err - } - event.Raw = log - - select { - case sink <- event: - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - } - }), nil -} - -func (_CapabilitiesRegistry *CapabilitiesRegistryFilterer) ParseOwnershipTransferred(log types.Log) (*CapabilitiesRegistryOwnershipTransferred, error) { - event := new(CapabilitiesRegistryOwnershipTransferred) - if err := _CapabilitiesRegistry.contract.UnpackLog(event, "OwnershipTransferred", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -func (_CapabilitiesRegistry *CapabilitiesRegistry) ParseLog(log types.Log) (generated.AbigenLog, error) { - switch log.Topics[0] { - case _CapabilitiesRegistry.abi.Events["CapabilityConfigured"].ID: - return _CapabilitiesRegistry.ParseCapabilityConfigured(log) - case _CapabilitiesRegistry.abi.Events["CapabilityDeprecated"].ID: - return _CapabilitiesRegistry.ParseCapabilityDeprecated(log) - case _CapabilitiesRegistry.abi.Events["ConfigSet"].ID: - return _CapabilitiesRegistry.ParseConfigSet(log) - case _CapabilitiesRegistry.abi.Events["NodeAdded"].ID: - return _CapabilitiesRegistry.ParseNodeAdded(log) - case _CapabilitiesRegistry.abi.Events["NodeOperatorAdded"].ID: - return _CapabilitiesRegistry.ParseNodeOperatorAdded(log) - case _CapabilitiesRegistry.abi.Events["NodeOperatorRemoved"].ID: - return _CapabilitiesRegistry.ParseNodeOperatorRemoved(log) - case _CapabilitiesRegistry.abi.Events["NodeOperatorUpdated"].ID: - return _CapabilitiesRegistry.ParseNodeOperatorUpdated(log) - case _CapabilitiesRegistry.abi.Events["NodeRemoved"].ID: - return _CapabilitiesRegistry.ParseNodeRemoved(log) - case _CapabilitiesRegistry.abi.Events["NodeUpdated"].ID: - return _CapabilitiesRegistry.ParseNodeUpdated(log) - case _CapabilitiesRegistry.abi.Events["OwnershipTransferRequested"].ID: - return _CapabilitiesRegistry.ParseOwnershipTransferRequested(log) - case _CapabilitiesRegistry.abi.Events["OwnershipTransferred"].ID: - return _CapabilitiesRegistry.ParseOwnershipTransferred(log) - - default: - return nil, fmt.Errorf("abigen wrapper received unknown log topic: %v", log.Topics[0]) - } -} - -func (CapabilitiesRegistryCapabilityConfigured) Topic() common.Hash { - return common.HexToHash("0x04f0a9bcf3f3a3b42a4d7ca081119755f82ebe43e0d30c8f7292c4fe0dc4a2ae") -} - -func (CapabilitiesRegistryCapabilityDeprecated) Topic() common.Hash { - return common.HexToHash("0xdcea1b78b6ddc31592a94607d537543fcaafda6cc52d6d5cc7bbfca1422baf21") -} - -func (CapabilitiesRegistryConfigSet) Topic() common.Hash { - return common.HexToHash("0xf264aae70bf6a9d90e68e0f9b393f4e7fbea67b063b0f336e0b36c1581703651") -} - -func (CapabilitiesRegistryNodeAdded) Topic() common.Hash { - return common.HexToHash("0x74becb12a5e8fd0e98077d02dfba8f647c9670c9df177e42c2418cf17a636f05") -} - -func (CapabilitiesRegistryNodeOperatorAdded) Topic() common.Hash { - return common.HexToHash("0x78e94ca80be2c30abc061b99e7eb8583b1254781734b1e3ce339abb57da2fe8e") -} - -func (CapabilitiesRegistryNodeOperatorRemoved) Topic() common.Hash { - return common.HexToHash("0xa59268ca81d40429e65ccea5385b59cf2d3fc6519371dee92f8eb1dae5107a7a") -} - -func (CapabilitiesRegistryNodeOperatorUpdated) Topic() common.Hash { - return common.HexToHash("0x86f41145bde5dd7f523305452e4aad3685508c181432ec733d5f345009358a28") -} - -func (CapabilitiesRegistryNodeRemoved) Topic() common.Hash { - return common.HexToHash("0x5254e609a97bab37b7cc79fe128f85c097bd6015c6e1624ae0ba392eb9753205") -} - -func (CapabilitiesRegistryNodeUpdated) Topic() common.Hash { - return common.HexToHash("0x4b5b465e22eea0c3d40c30e936643245b80d19b2dcf75788c0699fe8d8db645b") -} - -func (CapabilitiesRegistryOwnershipTransferRequested) Topic() common.Hash { - return common.HexToHash("0xed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae1278") -} - -func (CapabilitiesRegistryOwnershipTransferred) Topic() common.Hash { - return common.HexToHash("0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0") -} - -func (_CapabilitiesRegistry *CapabilitiesRegistry) Address() common.Address { - return _CapabilitiesRegistry.address -} - -type CapabilitiesRegistryInterface interface { - GetCapabilities(opts *bind.CallOpts) ([]CapabilitiesRegistryCapabilityInfo, error) - - GetCapability(opts *bind.CallOpts, hashedId [32]byte) (CapabilitiesRegistryCapabilityInfo, error) - - GetCapabilityConfigs(opts *bind.CallOpts, donId uint32, capabilityId [32]byte) ([]byte, []byte, error) - - GetDON(opts *bind.CallOpts, donId uint32) (CapabilitiesRegistryDONInfo, error) - - GetDONs(opts *bind.CallOpts) ([]CapabilitiesRegistryDONInfo, error) - - GetHashedCapabilityId(opts *bind.CallOpts, labelledName string, version string) ([32]byte, error) - - GetNextDONId(opts *bind.CallOpts) (uint32, error) - - GetNode(opts *bind.CallOpts, p2pId [32]byte) (INodeInfoProviderNodeInfo, error) - - GetNodeOperator(opts *bind.CallOpts, nodeOperatorId uint32) (CapabilitiesRegistryNodeOperator, error) - - GetNodeOperators(opts *bind.CallOpts) ([]CapabilitiesRegistryNodeOperator, error) - - GetNodes(opts *bind.CallOpts) ([]INodeInfoProviderNodeInfo, error) - - GetNodesByP2PIds(opts *bind.CallOpts, p2pIds [][32]byte) ([]INodeInfoProviderNodeInfo, error) - - IsCapabilityDeprecated(opts *bind.CallOpts, hashedCapabilityId [32]byte) (bool, error) - - Owner(opts *bind.CallOpts) (common.Address, error) - - TypeAndVersion(opts *bind.CallOpts) (string, error) - - AcceptOwnership(opts *bind.TransactOpts) (*types.Transaction, error) - - AddCapabilities(opts *bind.TransactOpts, capabilities []CapabilitiesRegistryCapability) (*types.Transaction, error) - - AddDON(opts *bind.TransactOpts, nodes [][32]byte, capabilityConfigurations []CapabilitiesRegistryCapabilityConfiguration, isPublic bool, acceptsWorkflows bool, f uint8) (*types.Transaction, error) - - AddNodeOperators(opts *bind.TransactOpts, nodeOperators []CapabilitiesRegistryNodeOperator) (*types.Transaction, error) - - AddNodes(opts *bind.TransactOpts, nodes []CapabilitiesRegistryNodeParams) (*types.Transaction, error) - - DeprecateCapabilities(opts *bind.TransactOpts, hashedCapabilityIds [][32]byte) (*types.Transaction, error) - - RemoveDONs(opts *bind.TransactOpts, donIds []uint32) (*types.Transaction, error) - - RemoveNodeOperators(opts *bind.TransactOpts, nodeOperatorIds []uint32) (*types.Transaction, error) - - RemoveNodes(opts *bind.TransactOpts, removedNodeP2PIds [][32]byte) (*types.Transaction, error) - - TransferOwnership(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) - - UpdateDON(opts *bind.TransactOpts, donId uint32, nodes [][32]byte, capabilityConfigurations []CapabilitiesRegistryCapabilityConfiguration, isPublic bool, f uint8) (*types.Transaction, error) - - UpdateNodeOperators(opts *bind.TransactOpts, nodeOperatorIds []uint32, nodeOperators []CapabilitiesRegistryNodeOperator) (*types.Transaction, error) - - UpdateNodes(opts *bind.TransactOpts, nodes []CapabilitiesRegistryNodeParams) (*types.Transaction, error) - - FilterCapabilityConfigured(opts *bind.FilterOpts, hashedCapabilityId [][32]byte) (*CapabilitiesRegistryCapabilityConfiguredIterator, error) - - WatchCapabilityConfigured(opts *bind.WatchOpts, sink chan<- *CapabilitiesRegistryCapabilityConfigured, hashedCapabilityId [][32]byte) (event.Subscription, error) - - ParseCapabilityConfigured(log types.Log) (*CapabilitiesRegistryCapabilityConfigured, error) - - FilterCapabilityDeprecated(opts *bind.FilterOpts, hashedCapabilityId [][32]byte) (*CapabilitiesRegistryCapabilityDeprecatedIterator, error) - - WatchCapabilityDeprecated(opts *bind.WatchOpts, sink chan<- *CapabilitiesRegistryCapabilityDeprecated, hashedCapabilityId [][32]byte) (event.Subscription, error) - - ParseCapabilityDeprecated(log types.Log) (*CapabilitiesRegistryCapabilityDeprecated, error) - - FilterConfigSet(opts *bind.FilterOpts, donId []uint32) (*CapabilitiesRegistryConfigSetIterator, error) - - WatchConfigSet(opts *bind.WatchOpts, sink chan<- *CapabilitiesRegistryConfigSet, donId []uint32) (event.Subscription, error) - - ParseConfigSet(log types.Log) (*CapabilitiesRegistryConfigSet, error) - - FilterNodeAdded(opts *bind.FilterOpts, nodeOperatorId []uint32) (*CapabilitiesRegistryNodeAddedIterator, error) - - WatchNodeAdded(opts *bind.WatchOpts, sink chan<- *CapabilitiesRegistryNodeAdded, nodeOperatorId []uint32) (event.Subscription, error) - - ParseNodeAdded(log types.Log) (*CapabilitiesRegistryNodeAdded, error) - - FilterNodeOperatorAdded(opts *bind.FilterOpts, nodeOperatorId []uint32, admin []common.Address) (*CapabilitiesRegistryNodeOperatorAddedIterator, error) - - WatchNodeOperatorAdded(opts *bind.WatchOpts, sink chan<- *CapabilitiesRegistryNodeOperatorAdded, nodeOperatorId []uint32, admin []common.Address) (event.Subscription, error) - - ParseNodeOperatorAdded(log types.Log) (*CapabilitiesRegistryNodeOperatorAdded, error) - - FilterNodeOperatorRemoved(opts *bind.FilterOpts, nodeOperatorId []uint32) (*CapabilitiesRegistryNodeOperatorRemovedIterator, error) - - WatchNodeOperatorRemoved(opts *bind.WatchOpts, sink chan<- *CapabilitiesRegistryNodeOperatorRemoved, nodeOperatorId []uint32) (event.Subscription, error) - - ParseNodeOperatorRemoved(log types.Log) (*CapabilitiesRegistryNodeOperatorRemoved, error) - - FilterNodeOperatorUpdated(opts *bind.FilterOpts, nodeOperatorId []uint32, admin []common.Address) (*CapabilitiesRegistryNodeOperatorUpdatedIterator, error) - - WatchNodeOperatorUpdated(opts *bind.WatchOpts, sink chan<- *CapabilitiesRegistryNodeOperatorUpdated, nodeOperatorId []uint32, admin []common.Address) (event.Subscription, error) - - ParseNodeOperatorUpdated(log types.Log) (*CapabilitiesRegistryNodeOperatorUpdated, error) - - FilterNodeRemoved(opts *bind.FilterOpts) (*CapabilitiesRegistryNodeRemovedIterator, error) - - WatchNodeRemoved(opts *bind.WatchOpts, sink chan<- *CapabilitiesRegistryNodeRemoved) (event.Subscription, error) - - ParseNodeRemoved(log types.Log) (*CapabilitiesRegistryNodeRemoved, error) - - FilterNodeUpdated(opts *bind.FilterOpts, nodeOperatorId []uint32) (*CapabilitiesRegistryNodeUpdatedIterator, error) - - WatchNodeUpdated(opts *bind.WatchOpts, sink chan<- *CapabilitiesRegistryNodeUpdated, nodeOperatorId []uint32) (event.Subscription, error) - - ParseNodeUpdated(log types.Log) (*CapabilitiesRegistryNodeUpdated, error) - - FilterOwnershipTransferRequested(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*CapabilitiesRegistryOwnershipTransferRequestedIterator, error) - - WatchOwnershipTransferRequested(opts *bind.WatchOpts, sink chan<- *CapabilitiesRegistryOwnershipTransferRequested, from []common.Address, to []common.Address) (event.Subscription, error) - - ParseOwnershipTransferRequested(log types.Log) (*CapabilitiesRegistryOwnershipTransferRequested, error) - - FilterOwnershipTransferred(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*CapabilitiesRegistryOwnershipTransferredIterator, error) - - WatchOwnershipTransferred(opts *bind.WatchOpts, sink chan<- *CapabilitiesRegistryOwnershipTransferred, from []common.Address, to []common.Address) (event.Subscription, error) - - ParseOwnershipTransferred(log types.Log) (*CapabilitiesRegistryOwnershipTransferred, error) - - ParseLog(log types.Log) (generated.AbigenLog, error) - - Address() common.Address -} diff --git a/core/gethwrappers/keystone/generated/feeds_consumer_1_0_0/feeds_consumer.go b/core/gethwrappers/keystone/generated/feeds_consumer_1_0_0/feeds_consumer.go deleted file mode 100644 index 8b618fbddb5..00000000000 --- a/core/gethwrappers/keystone/generated/feeds_consumer_1_0_0/feeds_consumer.go +++ /dev/null @@ -1,756 +0,0 @@ -// Code generated - DO NOT EDIT. -// This file is a generated binding and any manual changes will be lost. - -package feeds_consumer - -import ( - "errors" - "fmt" - "math/big" - "strings" - - ethereum "github.com/ethereum/go-ethereum" - "github.com/ethereum/go-ethereum/accounts/abi" - "github.com/ethereum/go-ethereum/accounts/abi/bind" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/event" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated" -) - -var ( - _ = errors.New - _ = big.NewInt - _ = strings.NewReader - _ = ethereum.NotFound - _ = bind.Bind - _ = common.Big1 - _ = types.BloomLookup - _ = event.NewSubscription - _ = abi.ConvertType -) - -var KeystoneFeedsConsumerMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"UnauthorizedSender\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes10\",\"name\":\"workflowName\",\"type\":\"bytes10\"}],\"name\":\"UnauthorizedWorkflowName\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"workflowOwner\",\"type\":\"address\"}],\"name\":\"UnauthorizedWorkflowOwner\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"feedId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint224\",\"name\":\"price\",\"type\":\"uint224\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"timestamp\",\"type\":\"uint32\"}],\"name\":\"FeedReceived\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"feedId\",\"type\":\"bytes32\"}],\"name\":\"getPrice\",\"outputs\":[{\"internalType\":\"uint224\",\"name\":\"\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"metadata\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"rawReport\",\"type\":\"bytes\"}],\"name\":\"onReport\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"_allowedSendersList\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"_allowedWorkflowOwnersList\",\"type\":\"address[]\"},{\"internalType\":\"bytes10[]\",\"name\":\"_allowedWorkflowNamesList\",\"type\":\"bytes10[]\"}],\"name\":\"setConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", - Bin: "0x608060405234801561001057600080fd5b5033806000816100675760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615610097576100978161009f565b505050610148565b336001600160a01b038216036100f75760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640161005e565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6112d8806101576000396000f3fe608060405234801561001057600080fd5b506004361061007d5760003560e01c8063805f21321161005b578063805f2132146101695780638da5cb5b1461017c578063e3401711146101a4578063f2fde38b146101b757600080fd5b806301ffc9a71461008257806331d98b3f146100aa57806379ba50971461015f575b600080fd5b610095610090366004610e2b565b6101ca565b60405190151581526020015b60405180910390f35b6101266100b8366004610e74565b6000908152600260209081526040918290208251808401909352547bffffffffffffffffffffffffffffffffffffffffffffffffffffffff81168084527c010000000000000000000000000000000000000000000000000000000090910463ffffffff169290910182905291565b604080517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff909316835263ffffffff9091166020830152016100a1565b610167610263565b005b610167610177366004610ed6565b610365565b60005460405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100a1565b6101676101b2366004610f87565b6106e4565b6101676101c5366004611021565b610b24565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f805f213200000000000000000000000000000000000000000000000000000000148061025d57507fffffffff0000000000000000000000000000000000000000000000000000000082167f01ffc9a700000000000000000000000000000000000000000000000000000000145b92915050565b60015473ffffffffffffffffffffffffffffffffffffffff1633146102e9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064015b60405180910390fd5b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b3360009081526004602052604090205460ff166103b0576040517f3fcc3f170000000000000000000000000000000000000000000000000000000081523360048201526024016102e0565b6000806103f286868080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250610b3892505050565b7fffffffffffffffffffff000000000000000000000000000000000000000000008216600090815260086020526040902054919350915060ff16610486576040517f4b942f800000000000000000000000000000000000000000000000000000000081527fffffffffffffffffffff00000000000000000000000000000000000000000000831660048201526024016102e0565b73ffffffffffffffffffffffffffffffffffffffff811660009081526006602052604090205460ff166104fd576040517fbf24162300000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff821660048201526024016102e0565b600061050b848601866110fe565b905060005b81518110156106da57604051806040016040528083838151811061053657610536611210565b6020026020010151602001517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16815260200183838151811061057757610577611210565b60200260200101516040015163ffffffff16815250600260008484815181106105a2576105a2611210565b602090810291909101810151518252818101929092526040016000208251929091015163ffffffff167c0100000000000000000000000000000000000000000000000000000000027bffffffffffffffffffffffffffffffffffffffffffffffffffffffff909216919091179055815182908290811061062457610624611210565b6020026020010151600001517f2c30f5cb3caf4239d0f994ce539d7ef24817fa550169c388e3a110f02e40197d83838151811061066357610663611210565b60200260200101516020015184848151811061068157610681611210565b6020026020010151604001516040516106ca9291907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff92909216825263ffffffff16602082015260400190565b60405180910390a2600101610510565b5050505050505050565b6106ec610b4e565b60005b60035463ffffffff8216101561078d5760006004600060038463ffffffff168154811061071e5761071e611210565b60009182526020808320919091015473ffffffffffffffffffffffffffffffffffffffff168352820192909252604001902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169115159190911790556107868161123f565b90506106ef565b5060005b63ffffffff81168611156108355760016004600089898563ffffffff168181106107bd576107bd611210565b90506020020160208101906107d29190611021565b73ffffffffffffffffffffffffffffffffffffffff168152602081019190915260400160002080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001691151591909117905561082e8161123f565b9050610791565b5061084260038787610cc6565b5060005b60055463ffffffff821610156108e45760006006600060058463ffffffff168154811061087557610875611210565b60009182526020808320919091015473ffffffffffffffffffffffffffffffffffffffff168352820192909252604001902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169115159190911790556108dd8161123f565b9050610846565b5060005b63ffffffff811684111561098c5760016006600087878563ffffffff1681811061091457610914611210565b90506020020160208101906109299190611021565b73ffffffffffffffffffffffffffffffffffffffff168152602081019190915260400160002080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169115159190911790556109858161123f565b90506108e8565b5061099960058585610cc6565b5060005b60075463ffffffff82161015610a5a5760006008600060078463ffffffff16815481106109cc576109cc611210565b600091825260208083206003808404909101549206600a026101000a90910460b01b7fffffffffffffffffffff00000000000000000000000000000000000000000000168352820192909252604001902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016911515919091179055610a538161123f565b905061099d565b5060005b63ffffffff8116821115610b0e5760016008600085858563ffffffff16818110610a8a57610a8a611210565b9050602002016020810190610a9f9190611289565b7fffffffffffffffffffff00000000000000000000000000000000000000000000168152602081019190915260400160002080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016911515919091179055610b078161123f565b9050610a5e565b50610b1b60078383610d4e565b50505050505050565b610b2c610b4e565b610b3581610bd1565b50565b6040810151604a90910151909160609190911c90565b60005473ffffffffffffffffffffffffffffffffffffffff163314610bcf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e65720000000000000000000060448201526064016102e0565b565b3373ffffffffffffffffffffffffffffffffffffffff821603610c50576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c6600000000000000000060448201526064016102e0565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b828054828255906000526020600020908101928215610d3e579160200282015b82811115610d3e5781547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff843516178255602090920191600190910190610ce6565b50610d4a929150610e16565b5090565b82805482825590600052602060002090600201600390048101928215610d3e5791602002820160005b83821115610dd757833575ffffffffffffffffffffffffffffffffffffffffffff191683826101000a81548169ffffffffffffffffffff021916908360b01c02179055509260200192600a01602081600901049283019260010302610d77565b8015610e0d5782816101000a81549069ffffffffffffffffffff0219169055600a01602081600901049283019260010302610dd7565b5050610d4a9291505b5b80821115610d4a5760008155600101610e17565b600060208284031215610e3d57600080fd5b81357fffffffff0000000000000000000000000000000000000000000000000000000081168114610e6d57600080fd5b9392505050565b600060208284031215610e8657600080fd5b5035919050565b60008083601f840112610e9f57600080fd5b50813567ffffffffffffffff811115610eb757600080fd5b602083019150836020828501011115610ecf57600080fd5b9250929050565b60008060008060408587031215610eec57600080fd5b843567ffffffffffffffff80821115610f0457600080fd5b610f1088838901610e8d565b90965094506020870135915080821115610f2957600080fd5b50610f3687828801610e8d565b95989497509550505050565b60008083601f840112610f5457600080fd5b50813567ffffffffffffffff811115610f6c57600080fd5b6020830191508360208260051b8501011115610ecf57600080fd5b60008060008060008060608789031215610fa057600080fd5b863567ffffffffffffffff80821115610fb857600080fd5b610fc48a838b01610f42565b90985096506020890135915080821115610fdd57600080fd5b610fe98a838b01610f42565b9096509450604089013591508082111561100257600080fd5b5061100f89828a01610f42565b979a9699509497509295939492505050565b60006020828403121561103357600080fd5b813573ffffffffffffffffffffffffffffffffffffffff81168114610e6d57600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040516060810167ffffffffffffffff811182821017156110a9576110a9611057565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156110f6576110f6611057565b604052919050565b6000602080838503121561111157600080fd5b823567ffffffffffffffff8082111561112957600080fd5b818501915085601f83011261113d57600080fd5b81358181111561114f5761114f611057565b61115d848260051b016110af565b8181528481019250606091820284018501918883111561117c57600080fd5b938501935b828510156112045780858a0312156111995760008081fd5b6111a1611086565b85358152868601357bffffffffffffffffffffffffffffffffffffffffffffffffffffffff811681146111d45760008081fd5b8188015260408681013563ffffffff811681146111f15760008081fd5b9082015284529384019392850192611181565b50979650505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600063ffffffff80831681810361127f577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6001019392505050565b60006020828403121561129b57600080fd5b81357fffffffffffffffffffff0000000000000000000000000000000000000000000081168114610e6d57600080fdfea164736f6c6343000818000a", -} - -var KeystoneFeedsConsumerABI = KeystoneFeedsConsumerMetaData.ABI - -var KeystoneFeedsConsumerBin = KeystoneFeedsConsumerMetaData.Bin - -func DeployKeystoneFeedsConsumer(auth *bind.TransactOpts, backend bind.ContractBackend) (common.Address, *types.Transaction, *KeystoneFeedsConsumer, error) { - parsed, err := KeystoneFeedsConsumerMetaData.GetAbi() - if err != nil { - return common.Address{}, nil, nil, err - } - if parsed == nil { - return common.Address{}, nil, nil, errors.New("GetABI returned nil") - } - - address, tx, contract, err := bind.DeployContract(auth, *parsed, common.FromHex(KeystoneFeedsConsumerBin), backend) - if err != nil { - return common.Address{}, nil, nil, err - } - return address, tx, &KeystoneFeedsConsumer{address: address, abi: *parsed, KeystoneFeedsConsumerCaller: KeystoneFeedsConsumerCaller{contract: contract}, KeystoneFeedsConsumerTransactor: KeystoneFeedsConsumerTransactor{contract: contract}, KeystoneFeedsConsumerFilterer: KeystoneFeedsConsumerFilterer{contract: contract}}, nil -} - -type KeystoneFeedsConsumer struct { - address common.Address - abi abi.ABI - KeystoneFeedsConsumerCaller - KeystoneFeedsConsumerTransactor - KeystoneFeedsConsumerFilterer -} - -type KeystoneFeedsConsumerCaller struct { - contract *bind.BoundContract -} - -type KeystoneFeedsConsumerTransactor struct { - contract *bind.BoundContract -} - -type KeystoneFeedsConsumerFilterer struct { - contract *bind.BoundContract -} - -type KeystoneFeedsConsumerSession struct { - Contract *KeystoneFeedsConsumer - CallOpts bind.CallOpts - TransactOpts bind.TransactOpts -} - -type KeystoneFeedsConsumerCallerSession struct { - Contract *KeystoneFeedsConsumerCaller - CallOpts bind.CallOpts -} - -type KeystoneFeedsConsumerTransactorSession struct { - Contract *KeystoneFeedsConsumerTransactor - TransactOpts bind.TransactOpts -} - -type KeystoneFeedsConsumerRaw struct { - Contract *KeystoneFeedsConsumer -} - -type KeystoneFeedsConsumerCallerRaw struct { - Contract *KeystoneFeedsConsumerCaller -} - -type KeystoneFeedsConsumerTransactorRaw struct { - Contract *KeystoneFeedsConsumerTransactor -} - -func NewKeystoneFeedsConsumer(address common.Address, backend bind.ContractBackend) (*KeystoneFeedsConsumer, error) { - abi, err := abi.JSON(strings.NewReader(KeystoneFeedsConsumerABI)) - if err != nil { - return nil, err - } - contract, err := bindKeystoneFeedsConsumer(address, backend, backend, backend) - if err != nil { - return nil, err - } - return &KeystoneFeedsConsumer{address: address, abi: abi, KeystoneFeedsConsumerCaller: KeystoneFeedsConsumerCaller{contract: contract}, KeystoneFeedsConsumerTransactor: KeystoneFeedsConsumerTransactor{contract: contract}, KeystoneFeedsConsumerFilterer: KeystoneFeedsConsumerFilterer{contract: contract}}, nil -} - -func NewKeystoneFeedsConsumerCaller(address common.Address, caller bind.ContractCaller) (*KeystoneFeedsConsumerCaller, error) { - contract, err := bindKeystoneFeedsConsumer(address, caller, nil, nil) - if err != nil { - return nil, err - } - return &KeystoneFeedsConsumerCaller{contract: contract}, nil -} - -func NewKeystoneFeedsConsumerTransactor(address common.Address, transactor bind.ContractTransactor) (*KeystoneFeedsConsumerTransactor, error) { - contract, err := bindKeystoneFeedsConsumer(address, nil, transactor, nil) - if err != nil { - return nil, err - } - return &KeystoneFeedsConsumerTransactor{contract: contract}, nil -} - -func NewKeystoneFeedsConsumerFilterer(address common.Address, filterer bind.ContractFilterer) (*KeystoneFeedsConsumerFilterer, error) { - contract, err := bindKeystoneFeedsConsumer(address, nil, nil, filterer) - if err != nil { - return nil, err - } - return &KeystoneFeedsConsumerFilterer{contract: contract}, nil -} - -func bindKeystoneFeedsConsumer(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { - parsed, err := KeystoneFeedsConsumerMetaData.GetAbi() - if err != nil { - return nil, err - } - return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil -} - -func (_KeystoneFeedsConsumer *KeystoneFeedsConsumerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { - return _KeystoneFeedsConsumer.Contract.KeystoneFeedsConsumerCaller.contract.Call(opts, result, method, params...) -} - -func (_KeystoneFeedsConsumer *KeystoneFeedsConsumerRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { - return _KeystoneFeedsConsumer.Contract.KeystoneFeedsConsumerTransactor.contract.Transfer(opts) -} - -func (_KeystoneFeedsConsumer *KeystoneFeedsConsumerRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { - return _KeystoneFeedsConsumer.Contract.KeystoneFeedsConsumerTransactor.contract.Transact(opts, method, params...) -} - -func (_KeystoneFeedsConsumer *KeystoneFeedsConsumerCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { - return _KeystoneFeedsConsumer.Contract.contract.Call(opts, result, method, params...) -} - -func (_KeystoneFeedsConsumer *KeystoneFeedsConsumerTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { - return _KeystoneFeedsConsumer.Contract.contract.Transfer(opts) -} - -func (_KeystoneFeedsConsumer *KeystoneFeedsConsumerTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { - return _KeystoneFeedsConsumer.Contract.contract.Transact(opts, method, params...) -} - -func (_KeystoneFeedsConsumer *KeystoneFeedsConsumerCaller) GetPrice(opts *bind.CallOpts, feedId [32]byte) (*big.Int, uint32, error) { - var out []interface{} - err := _KeystoneFeedsConsumer.contract.Call(opts, &out, "getPrice", feedId) - - if err != nil { - return *new(*big.Int), *new(uint32), err - } - - out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) - out1 := *abi.ConvertType(out[1], new(uint32)).(*uint32) - - return out0, out1, err - -} - -func (_KeystoneFeedsConsumer *KeystoneFeedsConsumerSession) GetPrice(feedId [32]byte) (*big.Int, uint32, error) { - return _KeystoneFeedsConsumer.Contract.GetPrice(&_KeystoneFeedsConsumer.CallOpts, feedId) -} - -func (_KeystoneFeedsConsumer *KeystoneFeedsConsumerCallerSession) GetPrice(feedId [32]byte) (*big.Int, uint32, error) { - return _KeystoneFeedsConsumer.Contract.GetPrice(&_KeystoneFeedsConsumer.CallOpts, feedId) -} - -func (_KeystoneFeedsConsumer *KeystoneFeedsConsumerCaller) Owner(opts *bind.CallOpts) (common.Address, error) { - var out []interface{} - err := _KeystoneFeedsConsumer.contract.Call(opts, &out, "owner") - - if err != nil { - return *new(common.Address), err - } - - out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) - - return out0, err - -} - -func (_KeystoneFeedsConsumer *KeystoneFeedsConsumerSession) Owner() (common.Address, error) { - return _KeystoneFeedsConsumer.Contract.Owner(&_KeystoneFeedsConsumer.CallOpts) -} - -func (_KeystoneFeedsConsumer *KeystoneFeedsConsumerCallerSession) Owner() (common.Address, error) { - return _KeystoneFeedsConsumer.Contract.Owner(&_KeystoneFeedsConsumer.CallOpts) -} - -func (_KeystoneFeedsConsumer *KeystoneFeedsConsumerCaller) SupportsInterface(opts *bind.CallOpts, interfaceId [4]byte) (bool, error) { - var out []interface{} - err := _KeystoneFeedsConsumer.contract.Call(opts, &out, "supportsInterface", interfaceId) - - if err != nil { - return *new(bool), err - } - - out0 := *abi.ConvertType(out[0], new(bool)).(*bool) - - return out0, err - -} - -func (_KeystoneFeedsConsumer *KeystoneFeedsConsumerSession) SupportsInterface(interfaceId [4]byte) (bool, error) { - return _KeystoneFeedsConsumer.Contract.SupportsInterface(&_KeystoneFeedsConsumer.CallOpts, interfaceId) -} - -func (_KeystoneFeedsConsumer *KeystoneFeedsConsumerCallerSession) SupportsInterface(interfaceId [4]byte) (bool, error) { - return _KeystoneFeedsConsumer.Contract.SupportsInterface(&_KeystoneFeedsConsumer.CallOpts, interfaceId) -} - -func (_KeystoneFeedsConsumer *KeystoneFeedsConsumerTransactor) AcceptOwnership(opts *bind.TransactOpts) (*types.Transaction, error) { - return _KeystoneFeedsConsumer.contract.Transact(opts, "acceptOwnership") -} - -func (_KeystoneFeedsConsumer *KeystoneFeedsConsumerSession) AcceptOwnership() (*types.Transaction, error) { - return _KeystoneFeedsConsumer.Contract.AcceptOwnership(&_KeystoneFeedsConsumer.TransactOpts) -} - -func (_KeystoneFeedsConsumer *KeystoneFeedsConsumerTransactorSession) AcceptOwnership() (*types.Transaction, error) { - return _KeystoneFeedsConsumer.Contract.AcceptOwnership(&_KeystoneFeedsConsumer.TransactOpts) -} - -func (_KeystoneFeedsConsumer *KeystoneFeedsConsumerTransactor) OnReport(opts *bind.TransactOpts, metadata []byte, rawReport []byte) (*types.Transaction, error) { - return _KeystoneFeedsConsumer.contract.Transact(opts, "onReport", metadata, rawReport) -} - -func (_KeystoneFeedsConsumer *KeystoneFeedsConsumerSession) OnReport(metadata []byte, rawReport []byte) (*types.Transaction, error) { - return _KeystoneFeedsConsumer.Contract.OnReport(&_KeystoneFeedsConsumer.TransactOpts, metadata, rawReport) -} - -func (_KeystoneFeedsConsumer *KeystoneFeedsConsumerTransactorSession) OnReport(metadata []byte, rawReport []byte) (*types.Transaction, error) { - return _KeystoneFeedsConsumer.Contract.OnReport(&_KeystoneFeedsConsumer.TransactOpts, metadata, rawReport) -} - -func (_KeystoneFeedsConsumer *KeystoneFeedsConsumerTransactor) SetConfig(opts *bind.TransactOpts, _allowedSendersList []common.Address, _allowedWorkflowOwnersList []common.Address, _allowedWorkflowNamesList [][10]byte) (*types.Transaction, error) { - return _KeystoneFeedsConsumer.contract.Transact(opts, "setConfig", _allowedSendersList, _allowedWorkflowOwnersList, _allowedWorkflowNamesList) -} - -func (_KeystoneFeedsConsumer *KeystoneFeedsConsumerSession) SetConfig(_allowedSendersList []common.Address, _allowedWorkflowOwnersList []common.Address, _allowedWorkflowNamesList [][10]byte) (*types.Transaction, error) { - return _KeystoneFeedsConsumer.Contract.SetConfig(&_KeystoneFeedsConsumer.TransactOpts, _allowedSendersList, _allowedWorkflowOwnersList, _allowedWorkflowNamesList) -} - -func (_KeystoneFeedsConsumer *KeystoneFeedsConsumerTransactorSession) SetConfig(_allowedSendersList []common.Address, _allowedWorkflowOwnersList []common.Address, _allowedWorkflowNamesList [][10]byte) (*types.Transaction, error) { - return _KeystoneFeedsConsumer.Contract.SetConfig(&_KeystoneFeedsConsumer.TransactOpts, _allowedSendersList, _allowedWorkflowOwnersList, _allowedWorkflowNamesList) -} - -func (_KeystoneFeedsConsumer *KeystoneFeedsConsumerTransactor) TransferOwnership(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) { - return _KeystoneFeedsConsumer.contract.Transact(opts, "transferOwnership", to) -} - -func (_KeystoneFeedsConsumer *KeystoneFeedsConsumerSession) TransferOwnership(to common.Address) (*types.Transaction, error) { - return _KeystoneFeedsConsumer.Contract.TransferOwnership(&_KeystoneFeedsConsumer.TransactOpts, to) -} - -func (_KeystoneFeedsConsumer *KeystoneFeedsConsumerTransactorSession) TransferOwnership(to common.Address) (*types.Transaction, error) { - return _KeystoneFeedsConsumer.Contract.TransferOwnership(&_KeystoneFeedsConsumer.TransactOpts, to) -} - -type KeystoneFeedsConsumerFeedReceivedIterator struct { - Event *KeystoneFeedsConsumerFeedReceived - - contract *bind.BoundContract - event string - - logs chan types.Log - sub ethereum.Subscription - done bool - fail error -} - -func (it *KeystoneFeedsConsumerFeedReceivedIterator) Next() bool { - - if it.fail != nil { - return false - } - - if it.done { - select { - case log := <-it.logs: - it.Event = new(KeystoneFeedsConsumerFeedReceived) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - default: - return false - } - } - - select { - case log := <-it.logs: - it.Event = new(KeystoneFeedsConsumerFeedReceived) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - case err := <-it.sub.Err(): - it.done = true - it.fail = err - return it.Next() - } -} - -func (it *KeystoneFeedsConsumerFeedReceivedIterator) Error() error { - return it.fail -} - -func (it *KeystoneFeedsConsumerFeedReceivedIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -type KeystoneFeedsConsumerFeedReceived struct { - FeedId [32]byte - Price *big.Int - Timestamp uint32 - Raw types.Log -} - -func (_KeystoneFeedsConsumer *KeystoneFeedsConsumerFilterer) FilterFeedReceived(opts *bind.FilterOpts, feedId [][32]byte) (*KeystoneFeedsConsumerFeedReceivedIterator, error) { - - var feedIdRule []interface{} - for _, feedIdItem := range feedId { - feedIdRule = append(feedIdRule, feedIdItem) - } - - logs, sub, err := _KeystoneFeedsConsumer.contract.FilterLogs(opts, "FeedReceived", feedIdRule) - if err != nil { - return nil, err - } - return &KeystoneFeedsConsumerFeedReceivedIterator{contract: _KeystoneFeedsConsumer.contract, event: "FeedReceived", logs: logs, sub: sub}, nil -} - -func (_KeystoneFeedsConsumer *KeystoneFeedsConsumerFilterer) WatchFeedReceived(opts *bind.WatchOpts, sink chan<- *KeystoneFeedsConsumerFeedReceived, feedId [][32]byte) (event.Subscription, error) { - - var feedIdRule []interface{} - for _, feedIdItem := range feedId { - feedIdRule = append(feedIdRule, feedIdItem) - } - - logs, sub, err := _KeystoneFeedsConsumer.contract.WatchLogs(opts, "FeedReceived", feedIdRule) - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - - event := new(KeystoneFeedsConsumerFeedReceived) - if err := _KeystoneFeedsConsumer.contract.UnpackLog(event, "FeedReceived", log); err != nil { - return err - } - event.Raw = log - - select { - case sink <- event: - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - } - }), nil -} - -func (_KeystoneFeedsConsumer *KeystoneFeedsConsumerFilterer) ParseFeedReceived(log types.Log) (*KeystoneFeedsConsumerFeedReceived, error) { - event := new(KeystoneFeedsConsumerFeedReceived) - if err := _KeystoneFeedsConsumer.contract.UnpackLog(event, "FeedReceived", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -type KeystoneFeedsConsumerOwnershipTransferRequestedIterator struct { - Event *KeystoneFeedsConsumerOwnershipTransferRequested - - contract *bind.BoundContract - event string - - logs chan types.Log - sub ethereum.Subscription - done bool - fail error -} - -func (it *KeystoneFeedsConsumerOwnershipTransferRequestedIterator) Next() bool { - - if it.fail != nil { - return false - } - - if it.done { - select { - case log := <-it.logs: - it.Event = new(KeystoneFeedsConsumerOwnershipTransferRequested) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - default: - return false - } - } - - select { - case log := <-it.logs: - it.Event = new(KeystoneFeedsConsumerOwnershipTransferRequested) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - case err := <-it.sub.Err(): - it.done = true - it.fail = err - return it.Next() - } -} - -func (it *KeystoneFeedsConsumerOwnershipTransferRequestedIterator) Error() error { - return it.fail -} - -func (it *KeystoneFeedsConsumerOwnershipTransferRequestedIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -type KeystoneFeedsConsumerOwnershipTransferRequested struct { - From common.Address - To common.Address - Raw types.Log -} - -func (_KeystoneFeedsConsumer *KeystoneFeedsConsumerFilterer) FilterOwnershipTransferRequested(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*KeystoneFeedsConsumerOwnershipTransferRequestedIterator, error) { - - var fromRule []interface{} - for _, fromItem := range from { - fromRule = append(fromRule, fromItem) - } - var toRule []interface{} - for _, toItem := range to { - toRule = append(toRule, toItem) - } - - logs, sub, err := _KeystoneFeedsConsumer.contract.FilterLogs(opts, "OwnershipTransferRequested", fromRule, toRule) - if err != nil { - return nil, err - } - return &KeystoneFeedsConsumerOwnershipTransferRequestedIterator{contract: _KeystoneFeedsConsumer.contract, event: "OwnershipTransferRequested", logs: logs, sub: sub}, nil -} - -func (_KeystoneFeedsConsumer *KeystoneFeedsConsumerFilterer) WatchOwnershipTransferRequested(opts *bind.WatchOpts, sink chan<- *KeystoneFeedsConsumerOwnershipTransferRequested, from []common.Address, to []common.Address) (event.Subscription, error) { - - var fromRule []interface{} - for _, fromItem := range from { - fromRule = append(fromRule, fromItem) - } - var toRule []interface{} - for _, toItem := range to { - toRule = append(toRule, toItem) - } - - logs, sub, err := _KeystoneFeedsConsumer.contract.WatchLogs(opts, "OwnershipTransferRequested", fromRule, toRule) - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - - event := new(KeystoneFeedsConsumerOwnershipTransferRequested) - if err := _KeystoneFeedsConsumer.contract.UnpackLog(event, "OwnershipTransferRequested", log); err != nil { - return err - } - event.Raw = log - - select { - case sink <- event: - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - } - }), nil -} - -func (_KeystoneFeedsConsumer *KeystoneFeedsConsumerFilterer) ParseOwnershipTransferRequested(log types.Log) (*KeystoneFeedsConsumerOwnershipTransferRequested, error) { - event := new(KeystoneFeedsConsumerOwnershipTransferRequested) - if err := _KeystoneFeedsConsumer.contract.UnpackLog(event, "OwnershipTransferRequested", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -type KeystoneFeedsConsumerOwnershipTransferredIterator struct { - Event *KeystoneFeedsConsumerOwnershipTransferred - - contract *bind.BoundContract - event string - - logs chan types.Log - sub ethereum.Subscription - done bool - fail error -} - -func (it *KeystoneFeedsConsumerOwnershipTransferredIterator) Next() bool { - - if it.fail != nil { - return false - } - - if it.done { - select { - case log := <-it.logs: - it.Event = new(KeystoneFeedsConsumerOwnershipTransferred) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - default: - return false - } - } - - select { - case log := <-it.logs: - it.Event = new(KeystoneFeedsConsumerOwnershipTransferred) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - case err := <-it.sub.Err(): - it.done = true - it.fail = err - return it.Next() - } -} - -func (it *KeystoneFeedsConsumerOwnershipTransferredIterator) Error() error { - return it.fail -} - -func (it *KeystoneFeedsConsumerOwnershipTransferredIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -type KeystoneFeedsConsumerOwnershipTransferred struct { - From common.Address - To common.Address - Raw types.Log -} - -func (_KeystoneFeedsConsumer *KeystoneFeedsConsumerFilterer) FilterOwnershipTransferred(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*KeystoneFeedsConsumerOwnershipTransferredIterator, error) { - - var fromRule []interface{} - for _, fromItem := range from { - fromRule = append(fromRule, fromItem) - } - var toRule []interface{} - for _, toItem := range to { - toRule = append(toRule, toItem) - } - - logs, sub, err := _KeystoneFeedsConsumer.contract.FilterLogs(opts, "OwnershipTransferred", fromRule, toRule) - if err != nil { - return nil, err - } - return &KeystoneFeedsConsumerOwnershipTransferredIterator{contract: _KeystoneFeedsConsumer.contract, event: "OwnershipTransferred", logs: logs, sub: sub}, nil -} - -func (_KeystoneFeedsConsumer *KeystoneFeedsConsumerFilterer) WatchOwnershipTransferred(opts *bind.WatchOpts, sink chan<- *KeystoneFeedsConsumerOwnershipTransferred, from []common.Address, to []common.Address) (event.Subscription, error) { - - var fromRule []interface{} - for _, fromItem := range from { - fromRule = append(fromRule, fromItem) - } - var toRule []interface{} - for _, toItem := range to { - toRule = append(toRule, toItem) - } - - logs, sub, err := _KeystoneFeedsConsumer.contract.WatchLogs(opts, "OwnershipTransferred", fromRule, toRule) - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - - event := new(KeystoneFeedsConsumerOwnershipTransferred) - if err := _KeystoneFeedsConsumer.contract.UnpackLog(event, "OwnershipTransferred", log); err != nil { - return err - } - event.Raw = log - - select { - case sink <- event: - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - } - }), nil -} - -func (_KeystoneFeedsConsumer *KeystoneFeedsConsumerFilterer) ParseOwnershipTransferred(log types.Log) (*KeystoneFeedsConsumerOwnershipTransferred, error) { - event := new(KeystoneFeedsConsumerOwnershipTransferred) - if err := _KeystoneFeedsConsumer.contract.UnpackLog(event, "OwnershipTransferred", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -func (_KeystoneFeedsConsumer *KeystoneFeedsConsumer) ParseLog(log types.Log) (generated.AbigenLog, error) { - switch log.Topics[0] { - case _KeystoneFeedsConsumer.abi.Events["FeedReceived"].ID: - return _KeystoneFeedsConsumer.ParseFeedReceived(log) - case _KeystoneFeedsConsumer.abi.Events["OwnershipTransferRequested"].ID: - return _KeystoneFeedsConsumer.ParseOwnershipTransferRequested(log) - case _KeystoneFeedsConsumer.abi.Events["OwnershipTransferred"].ID: - return _KeystoneFeedsConsumer.ParseOwnershipTransferred(log) - - default: - return nil, fmt.Errorf("abigen wrapper received unknown log topic: %v", log.Topics[0]) - } -} - -func (KeystoneFeedsConsumerFeedReceived) Topic() common.Hash { - return common.HexToHash("0x2c30f5cb3caf4239d0f994ce539d7ef24817fa550169c388e3a110f02e40197d") -} - -func (KeystoneFeedsConsumerOwnershipTransferRequested) Topic() common.Hash { - return common.HexToHash("0xed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae1278") -} - -func (KeystoneFeedsConsumerOwnershipTransferred) Topic() common.Hash { - return common.HexToHash("0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0") -} - -func (_KeystoneFeedsConsumer *KeystoneFeedsConsumer) Address() common.Address { - return _KeystoneFeedsConsumer.address -} - -type KeystoneFeedsConsumerInterface interface { - GetPrice(opts *bind.CallOpts, feedId [32]byte) (*big.Int, uint32, error) - - Owner(opts *bind.CallOpts) (common.Address, error) - - SupportsInterface(opts *bind.CallOpts, interfaceId [4]byte) (bool, error) - - AcceptOwnership(opts *bind.TransactOpts) (*types.Transaction, error) - - OnReport(opts *bind.TransactOpts, metadata []byte, rawReport []byte) (*types.Transaction, error) - - SetConfig(opts *bind.TransactOpts, _allowedSendersList []common.Address, _allowedWorkflowOwnersList []common.Address, _allowedWorkflowNamesList [][10]byte) (*types.Transaction, error) - - TransferOwnership(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) - - FilterFeedReceived(opts *bind.FilterOpts, feedId [][32]byte) (*KeystoneFeedsConsumerFeedReceivedIterator, error) - - WatchFeedReceived(opts *bind.WatchOpts, sink chan<- *KeystoneFeedsConsumerFeedReceived, feedId [][32]byte) (event.Subscription, error) - - ParseFeedReceived(log types.Log) (*KeystoneFeedsConsumerFeedReceived, error) - - FilterOwnershipTransferRequested(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*KeystoneFeedsConsumerOwnershipTransferRequestedIterator, error) - - WatchOwnershipTransferRequested(opts *bind.WatchOpts, sink chan<- *KeystoneFeedsConsumerOwnershipTransferRequested, from []common.Address, to []common.Address) (event.Subscription, error) - - ParseOwnershipTransferRequested(log types.Log) (*KeystoneFeedsConsumerOwnershipTransferRequested, error) - - FilterOwnershipTransferred(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*KeystoneFeedsConsumerOwnershipTransferredIterator, error) - - WatchOwnershipTransferred(opts *bind.WatchOpts, sink chan<- *KeystoneFeedsConsumerOwnershipTransferred, from []common.Address, to []common.Address) (event.Subscription, error) - - ParseOwnershipTransferred(log types.Log) (*KeystoneFeedsConsumerOwnershipTransferred, error) - - ParseLog(log types.Log) (generated.AbigenLog, error) - - Address() common.Address -} diff --git a/core/gethwrappers/keystone/generated/forwarder_1_0_0/forwarder.go b/core/gethwrappers/keystone/generated/forwarder_1_0_0/forwarder.go deleted file mode 100644 index c62e4904deb..00000000000 --- a/core/gethwrappers/keystone/generated/forwarder_1_0_0/forwarder.go +++ /dev/null @@ -1,1337 +0,0 @@ -// Code generated - DO NOT EDIT. -// This file is a generated binding and any manual changes will be lost. - -package forwarder - -import ( - "errors" - "fmt" - "math/big" - "strings" - - ethereum "github.com/ethereum/go-ethereum" - "github.com/ethereum/go-ethereum/accounts/abi" - "github.com/ethereum/go-ethereum/accounts/abi/bind" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/event" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated" -) - -var ( - _ = errors.New - _ = big.NewInt - _ = strings.NewReader - _ = ethereum.NotFound - _ = bind.Bind - _ = common.Big1 - _ = types.BloomLookup - _ = event.NewSubscription - _ = abi.ConvertType -) - -type IRouterTransmissionInfo struct { - TransmissionId [32]byte - State uint8 - Transmitter common.Address - InvalidReceiver bool - Success bool - GasLimit *big.Int -} - -var KeystoneForwarderMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"transmissionId\",\"type\":\"bytes32\"}],\"name\":\"AlreadyAttempted\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"signer\",\"type\":\"address\"}],\"name\":\"DuplicateSigner\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"numSigners\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxSigners\",\"type\":\"uint256\"}],\"name\":\"ExcessSigners\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FaultToleranceMustBePositive\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"transmissionId\",\"type\":\"bytes32\"}],\"name\":\"InsufficientGasForRouting\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"numSigners\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"minSigners\",\"type\":\"uint256\"}],\"name\":\"InsufficientSigners\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"configId\",\"type\":\"uint64\"}],\"name\":\"InvalidConfig\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidReport\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"signature\",\"type\":\"bytes\"}],\"name\":\"InvalidSignature\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"expected\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"received\",\"type\":\"uint256\"}],\"name\":\"InvalidSignatureCount\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"signer\",\"type\":\"address\"}],\"name\":\"InvalidSigner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnauthorizedForwarder\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint32\",\"name\":\"donId\",\"type\":\"uint32\"},{\"indexed\":true,\"internalType\":\"uint32\",\"name\":\"configVersion\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"f\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"}],\"name\":\"ConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"forwarder\",\"type\":\"address\"}],\"name\":\"ForwarderAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"forwarder\",\"type\":\"address\"}],\"name\":\"ForwarderRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"workflowExecutionId\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"bytes2\",\"name\":\"reportId\",\"type\":\"bytes2\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"result\",\"type\":\"bool\"}],\"name\":\"ReportProcessed\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"forwarder\",\"type\":\"address\"}],\"name\":\"addForwarder\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"donId\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"configVersion\",\"type\":\"uint32\"}],\"name\":\"clearConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"workflowExecutionId\",\"type\":\"bytes32\"},{\"internalType\":\"bytes2\",\"name\":\"reportId\",\"type\":\"bytes2\"}],\"name\":\"getTransmissionId\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"workflowExecutionId\",\"type\":\"bytes32\"},{\"internalType\":\"bytes2\",\"name\":\"reportId\",\"type\":\"bytes2\"}],\"name\":\"getTransmissionInfo\",\"outputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"transmissionId\",\"type\":\"bytes32\"},{\"internalType\":\"enumIRouter.TransmissionState\",\"name\":\"state\",\"type\":\"uint8\"},{\"internalType\":\"address\",\"name\":\"transmitter\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"invalidReceiver\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\"},{\"internalType\":\"uint80\",\"name\":\"gasLimit\",\"type\":\"uint80\"}],\"internalType\":\"structIRouter.TransmissionInfo\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"workflowExecutionId\",\"type\":\"bytes32\"},{\"internalType\":\"bytes2\",\"name\":\"reportId\",\"type\":\"bytes2\"}],\"name\":\"getTransmitter\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"forwarder\",\"type\":\"address\"}],\"name\":\"isForwarder\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"forwarder\",\"type\":\"address\"}],\"name\":\"removeForwarder\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"rawReport\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"reportContext\",\"type\":\"bytes\"},{\"internalType\":\"bytes[]\",\"name\":\"signatures\",\"type\":\"bytes[]\"}],\"name\":\"report\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"transmissionId\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"transmitter\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"metadata\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"validatedReport\",\"type\":\"bytes\"}],\"name\":\"route\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"donId\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"configVersion\",\"type\":\"uint32\"},{\"internalType\":\"uint8\",\"name\":\"f\",\"type\":\"uint8\"},{\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"}],\"name\":\"setConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", - Bin: "0x60806040523480156200001157600080fd5b503380600081620000695760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b03848116919091179091558116156200009c576200009c81620000bf565b5050306000908152600360205260409020805460ff19166001179055506200016a565b336001600160a01b03821603620001195760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000060565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b61218f806200017a6000396000f3fe608060405234801561001057600080fd5b50600436106100ea5760003560e01c806379ba50971161008c578063abcef55411610066578063abcef5541461035d578063ee59d26c14610396578063ef6e17a0146103a9578063f2fde38b146103bc57600080fd5b806379ba50971461025e5780638864b864146102665780638da5cb5b1461033f57600080fd5b8063272cbd93116100c8578063272cbd9314610179578063354bdd66146101995780634d93172d146102385780635c41d2fe1461024b57600080fd5b806311289565146100ef578063181f5a7714610104578063233fd52d14610156575b600080fd5b6101026100fd366004611a33565b6103cf565b005b6101406040518060400160405280601781526020017f4b657973746f6e65466f7277617264657220312e302e3000000000000000000081525081565b60405161014d9190611ade565b60405180910390f35b610169610164366004611b4b565b610989565b604051901515815260200161014d565b61018c610187366004611bd3565b610d4a565b60405161014d9190611c67565b61022a6101a7366004611bd3565b6040517fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606085901b166020820152603481018390527fffff000000000000000000000000000000000000000000000000000000000000821660548201526000906056016040516020818303038152906040528051906020012090509392505050565b60405190815260200161014d565b610102610246366004611d0f565b610f50565b610102610259366004611d0f565b610fcc565b61010261104b565b61031a610274366004611bd3565b6040805160609490941b7fffffffffffffffffffffffffffffffffffffffff0000000000000000000000001660208086019190915260348501939093527fffff000000000000000000000000000000000000000000000000000000000000919091166054840152805160368185030181526056909301815282519282019290922060009081526004909152205473ffffffffffffffffffffffffffffffffffffffff1690565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161014d565b60005473ffffffffffffffffffffffffffffffffffffffff1661031a565b61016961036b366004611d0f565b73ffffffffffffffffffffffffffffffffffffffff1660009081526003602052604090205460ff1690565b6101026103a4366004611d3e565b611148565b6101026103b7366004611dbc565b611525565b6101026103ca366004611d0f565b6115c5565b606d85101561040a576040517fb55ac75400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080600061044e89898080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506115d992505050565b67ffffffffffffffff8216600090815260026020526040812080549497509195509193509160ff16908190036104c1576040517fdf3b81ea00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff841660048201526024015b60405180910390fd5b856104cd826001611e1e565b60ff161461051f576104e0816001611e1e565b6040517fd6022e8e00000000000000000000000000000000000000000000000000000000815260ff9091166004820152602481018790526044016104b8565b60008b8b604051610531929190611e37565b60405190819003812061054a918c908c90602001611e47565b60405160208183030381529060405280519060200120905061056a6118c0565b60005b888110156107ec573660008b8b8481811061058a5761058a611e61565b905060200281019061059c9190611e90565b9092509050604181146105df5781816040517f2adfdc300000000000000000000000000000000000000000000000000000000081526004016104b8929190611f3e565b6000600186848460408181106105f7576105f7611e61565b61060992013560f81c9050601b611e1e565b610617602060008789611f5a565b61062091611f84565b61062e60406020888a611f5a565b61063791611f84565b6040805160008152602081018083529590955260ff909316928401929092526060830152608082015260a0016020604051602081039080840390855afa158015610685573d6000803e3d6000fd5b5050604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0015173ffffffffffffffffffffffffffffffffffffffff8116600090815260028c0160205291822054909350915081900361072b576040517fbf18af4300000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff831660048201526024016104b8565b600086826020811061073f5761073f611e61565b602002015173ffffffffffffffffffffffffffffffffffffffff16146107a9576040517fe021c4f200000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff831660048201526024016104b8565b818682602081106107bc576107bc611e61565b73ffffffffffffffffffffffffffffffffffffffff909216602092909202015250506001909201915061056d9050565b50506040805160608f901b7fffffffffffffffffffffffffffffffffffffffff00000000000000000000000016602080830191909152603482018990527fffff0000000000000000000000000000000000000000000000000000000000008816605483015282516036818403018152605690920190925280519101206000945030935063233fd52d92509050338d8d8d602d90606d9261088e93929190611f5a565b8f8f606d9080926108a193929190611f5a565b6040518863ffffffff1660e01b81526004016108c39796959493929190611fc0565b6020604051808303816000875af11580156108e2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109069190612021565b9050817dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916838b73ffffffffffffffffffffffffffffffffffffffff167f3617b009e9785c42daebadb6d3fb553243a4bf586d07ea72d65d80013ce116b584604051610975911515815260200190565b60405180910390a450505050505050505050565b3360009081526003602052604081205460ff166109d2576040517fd79e123d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006109e26113886161a861204a565b5a6109ed919061205d565b90506109fd6113886161a861204a565b610a0a9062015f9061204a565b610a169061271061204a565b811015610a52576040517f0bfecd63000000000000000000000000000000000000000000000000000000008152600481018a90526024016104b8565b6000898152600460209081526040918290208251608081018452905473ffffffffffffffffffffffffffffffffffffffff8116825274010000000000000000000000000000000000000000810460ff90811615159383019390935275010000000000000000000000000000000000000000008104909216151592810183905276010000000000000000000000000000000000000000000090910469ffffffffffffffffffff1660608201529080610b0a575080602001515b15610b44576040517fa53dc8ca000000000000000000000000000000000000000000000000000000008152600481018b90526024016104b8565b60008a8152600460205260409020805469ffffffffffffffffffff84167601000000000000000000000000000000000000000000000275ffff000000000000000000000000000000000000000090911673ffffffffffffffffffffffffffffffffffffffff8c1617179055610bd9887f805f2132000000000000000000000000000000000000000000000000000000006115f4565b610c3057505050600087815260046020526040812080547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1674010000000000000000000000000000000000000000179055610d3f565b60008088888888604051602401610c4a9493929190612070565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f805f213200000000000000000000000000000000000000000000000000000000179052905060006113885a610cd2919061205d565b905060008083516020850160008f86f192508215610d375760008d815260046020526040902080547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff1675010000000000000000000000000000000000000000001790555b509093505050505b979650505050505050565b6040805160c0810182526000808252602080830182905282840182905260608084018390526080840183905260a0840183905284519088901b7fffffffffffffffffffffffffffffffffffffffff0000000000000000000000001681830152603481018790527fffff000000000000000000000000000000000000000000000000000000000000861660548201528451603681830301815260568201808752815191840191909120808552600490935285842060d68301909652945473ffffffffffffffffffffffffffffffffffffffff811680875274010000000000000000000000000000000000000000820460ff9081161515607685015275010000000000000000000000000000000000000000008304161515609684015276010000000000000000000000000000000000000000000090910469ffffffffffffffffffff1660b69092019190915292939092909190610ea857506000610ed0565b816020015115610eba57506002610ed0565b8160400151610eca576003610ecd565b60015b90505b6040518060c00160405280848152602001826003811115610ef357610ef3611c38565b8152602001836000015173ffffffffffffffffffffffffffffffffffffffff168152602001836020015115158152602001836040015115158152602001836060015169ffffffffffffffffffff1681525093505050509392505050565b610f58611619565b73ffffffffffffffffffffffffffffffffffffffff811660008181526003602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055517fb96d15bf9258c7b8df062753a6a262864611fc7b060a5ee2e57e79b85f898d389190a250565b610fd4611619565b73ffffffffffffffffffffffffffffffffffffffff811660008181526003602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055517f0ea0ce2c048ff45a4a95f2947879de3fb94abec2f152190400cab2d1272a68e79190a250565b60015473ffffffffffffffffffffffffffffffffffffffff1633146110cc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064016104b8565b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b611150611619565b8260ff1660000361118d576040517f0743bae600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b601f8111156111d2576040517f61750f4000000000000000000000000000000000000000000000000000000000815260048101829052601f60248201526044016104b8565b6111dd836003612097565b60ff16811161123b57806111f2846003612097565b6111fd906001611e1e565b6040517f9dd9e6d8000000000000000000000000000000000000000000000000000000008152600481019290925260ff1660248201526044016104b8565b67ffffffff00000000602086901b1663ffffffff85161760005b67ffffffffffffffff82166000908152600260205260409020600101548110156112eb5767ffffffffffffffff82166000908152600260208190526040822060018101805491909201929190849081106112b1576112b1611e61565b600091825260208083209091015473ffffffffffffffffffffffffffffffffffffffff168352820192909252604001812055600101611255565b5060005b8281101561146757600084848381811061130b5761130b611e61565b90506020020160208101906113209190611d0f565b905073ffffffffffffffffffffffffffffffffffffffff8116611387576040517fbf18af4300000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff821660048201526024016104b8565b67ffffffffffffffff8316600090815260026020818152604080842073ffffffffffffffffffffffffffffffffffffffff86168552909201905290205415611413576040517fe021c4f200000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff821660048201526024016104b8565b61141e82600161204a565b67ffffffffffffffff8416600090815260026020818152604080842073ffffffffffffffffffffffffffffffffffffffff909616845294909101905291909120556001016112ef565b5067ffffffffffffffff8116600090815260026020526040902061148f9060010184846118df565b5067ffffffffffffffff81166000908152600260205260409081902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660ff87161790555163ffffffff86811691908816907f4120bd3b23957dd423555817d55654d4481b438aa15485c21b4180c784f1a45590611515908890889088906120b3565b60405180910390a3505050505050565b61152d611619565b63ffffffff818116602084811b67ffffffff00000000168217600090815260028252604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001690558051828152928301905291928516917f4120bd3b23957dd423555817d55654d4481b438aa15485c21b4180c784f1a455916040516115b9929190612119565b60405180910390a35050565b6115cd611619565b6115d68161169c565b50565b60218101516045820151608b90920151909260c09290921c91565b60006115ff83611791565b8015611610575061161083836117f5565b90505b92915050565b60005473ffffffffffffffffffffffffffffffffffffffff16331461169a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e65720000000000000000000060448201526064016104b8565b565b3373ffffffffffffffffffffffffffffffffffffffff82160361171b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c6600000000000000000060448201526064016104b8565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b60006117bd827f01ffc9a7000000000000000000000000000000000000000000000000000000006117f5565b801561161357506117ee827fffffffff000000000000000000000000000000000000000000000000000000006117f5565b1592915050565b604080517fffffffff000000000000000000000000000000000000000000000000000000008316602480830191909152825180830390910181526044909101909152602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f01ffc9a700000000000000000000000000000000000000000000000000000000178152825160009392849283928392918391908a617530fa92503d915060005190508280156118ad575060208210155b8015610d3f575015159695505050505050565b6040518061040001604052806020906020820280368337509192915050565b828054828255906000526020600020908101928215611957579160200282015b828111156119575781547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff8435161782556020909201916001909101906118ff565b50611963929150611967565b5090565b5b808211156119635760008155600101611968565b803573ffffffffffffffffffffffffffffffffffffffff811681146119a057600080fd5b919050565b60008083601f8401126119b757600080fd5b50813567ffffffffffffffff8111156119cf57600080fd5b6020830191508360208285010111156119e757600080fd5b9250929050565b60008083601f840112611a0057600080fd5b50813567ffffffffffffffff811115611a1857600080fd5b6020830191508360208260051b85010111156119e757600080fd5b60008060008060008060006080888a031215611a4e57600080fd5b611a578861197c565b9650602088013567ffffffffffffffff80821115611a7457600080fd5b611a808b838c016119a5565b909850965060408a0135915080821115611a9957600080fd5b611aa58b838c016119a5565b909650945060608a0135915080821115611abe57600080fd5b50611acb8a828b016119ee565b989b979a50959850939692959293505050565b60006020808352835180602085015260005b81811015611b0c57858101830151858201604001528201611af0565b5060006040828601015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8301168501019250505092915050565b600080600080600080600060a0888a031215611b6657600080fd5b87359650611b766020890161197c565b9550611b846040890161197c565b9450606088013567ffffffffffffffff80821115611ba157600080fd5b611bad8b838c016119a5565b909650945060808a0135915080821115611bc657600080fd5b50611acb8a828b016119a5565b600080600060608486031215611be857600080fd5b611bf18461197c565b92506020840135915060408401357fffff00000000000000000000000000000000000000000000000000000000000081168114611c2d57600080fd5b809150509250925092565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b81518152602082015160c082019060048110611cac577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b8060208401525073ffffffffffffffffffffffffffffffffffffffff604084015116604083015260608301511515606083015260808301511515608083015260a0830151611d0860a084018269ffffffffffffffffffff169052565b5092915050565b600060208284031215611d2157600080fd5b6116108261197c565b803563ffffffff811681146119a057600080fd5b600080600080600060808688031215611d5657600080fd5b611d5f86611d2a565b9450611d6d60208701611d2a565b9350604086013560ff81168114611d8357600080fd5b9250606086013567ffffffffffffffff811115611d9f57600080fd5b611dab888289016119ee565b969995985093965092949392505050565b60008060408385031215611dcf57600080fd5b611dd883611d2a565b9150611de660208401611d2a565b90509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60ff818116838216019081111561161357611613611def565b8183823760009101908152919050565b838152818360208301376000910160200190815292915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112611ec557600080fd5b83018035915067ffffffffffffffff821115611ee057600080fd5b6020019150368190038213156119e757600080fd5b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b602081526000611f52602083018486611ef5565b949350505050565b60008085851115611f6a57600080fd5b83861115611f7757600080fd5b5050820193919092039150565b80356020831015611613577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff602084900360031b1b1692915050565b878152600073ffffffffffffffffffffffffffffffffffffffff808916602084015280881660408401525060a0606083015261200060a083018688611ef5565b8281036080840152612013818587611ef5565b9a9950505050505050505050565b60006020828403121561203357600080fd5b8151801515811461204357600080fd5b9392505050565b8082018082111561161357611613611def565b8181038181111561161357611613611def565b604081526000612084604083018688611ef5565b8281036020840152610d3f818587611ef5565b60ff8181168382160290811690818114611d0857611d08611def565b60ff8416815260406020808301829052908201839052600090849060608401835b8681101561210d5773ffffffffffffffffffffffffffffffffffffffff6120fa8561197c565b16825292820192908201906001016120d4565b50979650505050505050565b60006040820160ff8516835260206040602085015281855180845260608601915060208701935060005b8181101561217557845173ffffffffffffffffffffffffffffffffffffffff1683529383019391830191600101612143565b509097965050505050505056fea164736f6c6343000818000a", -} - -var KeystoneForwarderABI = KeystoneForwarderMetaData.ABI - -var KeystoneForwarderBin = KeystoneForwarderMetaData.Bin - -func DeployKeystoneForwarder(auth *bind.TransactOpts, backend bind.ContractBackend) (common.Address, *types.Transaction, *KeystoneForwarder, error) { - parsed, err := KeystoneForwarderMetaData.GetAbi() - if err != nil { - return common.Address{}, nil, nil, err - } - if parsed == nil { - return common.Address{}, nil, nil, errors.New("GetABI returned nil") - } - - address, tx, contract, err := bind.DeployContract(auth, *parsed, common.FromHex(KeystoneForwarderBin), backend) - if err != nil { - return common.Address{}, nil, nil, err - } - return address, tx, &KeystoneForwarder{address: address, abi: *parsed, KeystoneForwarderCaller: KeystoneForwarderCaller{contract: contract}, KeystoneForwarderTransactor: KeystoneForwarderTransactor{contract: contract}, KeystoneForwarderFilterer: KeystoneForwarderFilterer{contract: contract}}, nil -} - -type KeystoneForwarder struct { - address common.Address - abi abi.ABI - KeystoneForwarderCaller - KeystoneForwarderTransactor - KeystoneForwarderFilterer -} - -type KeystoneForwarderCaller struct { - contract *bind.BoundContract -} - -type KeystoneForwarderTransactor struct { - contract *bind.BoundContract -} - -type KeystoneForwarderFilterer struct { - contract *bind.BoundContract -} - -type KeystoneForwarderSession struct { - Contract *KeystoneForwarder - CallOpts bind.CallOpts - TransactOpts bind.TransactOpts -} - -type KeystoneForwarderCallerSession struct { - Contract *KeystoneForwarderCaller - CallOpts bind.CallOpts -} - -type KeystoneForwarderTransactorSession struct { - Contract *KeystoneForwarderTransactor - TransactOpts bind.TransactOpts -} - -type KeystoneForwarderRaw struct { - Contract *KeystoneForwarder -} - -type KeystoneForwarderCallerRaw struct { - Contract *KeystoneForwarderCaller -} - -type KeystoneForwarderTransactorRaw struct { - Contract *KeystoneForwarderTransactor -} - -func NewKeystoneForwarder(address common.Address, backend bind.ContractBackend) (*KeystoneForwarder, error) { - abi, err := abi.JSON(strings.NewReader(KeystoneForwarderABI)) - if err != nil { - return nil, err - } - contract, err := bindKeystoneForwarder(address, backend, backend, backend) - if err != nil { - return nil, err - } - return &KeystoneForwarder{address: address, abi: abi, KeystoneForwarderCaller: KeystoneForwarderCaller{contract: contract}, KeystoneForwarderTransactor: KeystoneForwarderTransactor{contract: contract}, KeystoneForwarderFilterer: KeystoneForwarderFilterer{contract: contract}}, nil -} - -func NewKeystoneForwarderCaller(address common.Address, caller bind.ContractCaller) (*KeystoneForwarderCaller, error) { - contract, err := bindKeystoneForwarder(address, caller, nil, nil) - if err != nil { - return nil, err - } - return &KeystoneForwarderCaller{contract: contract}, nil -} - -func NewKeystoneForwarderTransactor(address common.Address, transactor bind.ContractTransactor) (*KeystoneForwarderTransactor, error) { - contract, err := bindKeystoneForwarder(address, nil, transactor, nil) - if err != nil { - return nil, err - } - return &KeystoneForwarderTransactor{contract: contract}, nil -} - -func NewKeystoneForwarderFilterer(address common.Address, filterer bind.ContractFilterer) (*KeystoneForwarderFilterer, error) { - contract, err := bindKeystoneForwarder(address, nil, nil, filterer) - if err != nil { - return nil, err - } - return &KeystoneForwarderFilterer{contract: contract}, nil -} - -func bindKeystoneForwarder(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { - parsed, err := KeystoneForwarderMetaData.GetAbi() - if err != nil { - return nil, err - } - return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil -} - -func (_KeystoneForwarder *KeystoneForwarderRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { - return _KeystoneForwarder.Contract.KeystoneForwarderCaller.contract.Call(opts, result, method, params...) -} - -func (_KeystoneForwarder *KeystoneForwarderRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { - return _KeystoneForwarder.Contract.KeystoneForwarderTransactor.contract.Transfer(opts) -} - -func (_KeystoneForwarder *KeystoneForwarderRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { - return _KeystoneForwarder.Contract.KeystoneForwarderTransactor.contract.Transact(opts, method, params...) -} - -func (_KeystoneForwarder *KeystoneForwarderCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { - return _KeystoneForwarder.Contract.contract.Call(opts, result, method, params...) -} - -func (_KeystoneForwarder *KeystoneForwarderTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { - return _KeystoneForwarder.Contract.contract.Transfer(opts) -} - -func (_KeystoneForwarder *KeystoneForwarderTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { - return _KeystoneForwarder.Contract.contract.Transact(opts, method, params...) -} - -func (_KeystoneForwarder *KeystoneForwarderCaller) GetTransmissionId(opts *bind.CallOpts, receiver common.Address, workflowExecutionId [32]byte, reportId [2]byte) ([32]byte, error) { - var out []interface{} - err := _KeystoneForwarder.contract.Call(opts, &out, "getTransmissionId", receiver, workflowExecutionId, reportId) - - if err != nil { - return *new([32]byte), err - } - - out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) - - return out0, err - -} - -func (_KeystoneForwarder *KeystoneForwarderSession) GetTransmissionId(receiver common.Address, workflowExecutionId [32]byte, reportId [2]byte) ([32]byte, error) { - return _KeystoneForwarder.Contract.GetTransmissionId(&_KeystoneForwarder.CallOpts, receiver, workflowExecutionId, reportId) -} - -func (_KeystoneForwarder *KeystoneForwarderCallerSession) GetTransmissionId(receiver common.Address, workflowExecutionId [32]byte, reportId [2]byte) ([32]byte, error) { - return _KeystoneForwarder.Contract.GetTransmissionId(&_KeystoneForwarder.CallOpts, receiver, workflowExecutionId, reportId) -} - -func (_KeystoneForwarder *KeystoneForwarderCaller) GetTransmissionInfo(opts *bind.CallOpts, receiver common.Address, workflowExecutionId [32]byte, reportId [2]byte) (IRouterTransmissionInfo, error) { - var out []interface{} - err := _KeystoneForwarder.contract.Call(opts, &out, "getTransmissionInfo", receiver, workflowExecutionId, reportId) - - if err != nil { - return *new(IRouterTransmissionInfo), err - } - - out0 := *abi.ConvertType(out[0], new(IRouterTransmissionInfo)).(*IRouterTransmissionInfo) - - return out0, err - -} - -func (_KeystoneForwarder *KeystoneForwarderSession) GetTransmissionInfo(receiver common.Address, workflowExecutionId [32]byte, reportId [2]byte) (IRouterTransmissionInfo, error) { - return _KeystoneForwarder.Contract.GetTransmissionInfo(&_KeystoneForwarder.CallOpts, receiver, workflowExecutionId, reportId) -} - -func (_KeystoneForwarder *KeystoneForwarderCallerSession) GetTransmissionInfo(receiver common.Address, workflowExecutionId [32]byte, reportId [2]byte) (IRouterTransmissionInfo, error) { - return _KeystoneForwarder.Contract.GetTransmissionInfo(&_KeystoneForwarder.CallOpts, receiver, workflowExecutionId, reportId) -} - -func (_KeystoneForwarder *KeystoneForwarderCaller) GetTransmitter(opts *bind.CallOpts, receiver common.Address, workflowExecutionId [32]byte, reportId [2]byte) (common.Address, error) { - var out []interface{} - err := _KeystoneForwarder.contract.Call(opts, &out, "getTransmitter", receiver, workflowExecutionId, reportId) - - if err != nil { - return *new(common.Address), err - } - - out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) - - return out0, err - -} - -func (_KeystoneForwarder *KeystoneForwarderSession) GetTransmitter(receiver common.Address, workflowExecutionId [32]byte, reportId [2]byte) (common.Address, error) { - return _KeystoneForwarder.Contract.GetTransmitter(&_KeystoneForwarder.CallOpts, receiver, workflowExecutionId, reportId) -} - -func (_KeystoneForwarder *KeystoneForwarderCallerSession) GetTransmitter(receiver common.Address, workflowExecutionId [32]byte, reportId [2]byte) (common.Address, error) { - return _KeystoneForwarder.Contract.GetTransmitter(&_KeystoneForwarder.CallOpts, receiver, workflowExecutionId, reportId) -} - -func (_KeystoneForwarder *KeystoneForwarderCaller) IsForwarder(opts *bind.CallOpts, forwarder common.Address) (bool, error) { - var out []interface{} - err := _KeystoneForwarder.contract.Call(opts, &out, "isForwarder", forwarder) - - if err != nil { - return *new(bool), err - } - - out0 := *abi.ConvertType(out[0], new(bool)).(*bool) - - return out0, err - -} - -func (_KeystoneForwarder *KeystoneForwarderSession) IsForwarder(forwarder common.Address) (bool, error) { - return _KeystoneForwarder.Contract.IsForwarder(&_KeystoneForwarder.CallOpts, forwarder) -} - -func (_KeystoneForwarder *KeystoneForwarderCallerSession) IsForwarder(forwarder common.Address) (bool, error) { - return _KeystoneForwarder.Contract.IsForwarder(&_KeystoneForwarder.CallOpts, forwarder) -} - -func (_KeystoneForwarder *KeystoneForwarderCaller) Owner(opts *bind.CallOpts) (common.Address, error) { - var out []interface{} - err := _KeystoneForwarder.contract.Call(opts, &out, "owner") - - if err != nil { - return *new(common.Address), err - } - - out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) - - return out0, err - -} - -func (_KeystoneForwarder *KeystoneForwarderSession) Owner() (common.Address, error) { - return _KeystoneForwarder.Contract.Owner(&_KeystoneForwarder.CallOpts) -} - -func (_KeystoneForwarder *KeystoneForwarderCallerSession) Owner() (common.Address, error) { - return _KeystoneForwarder.Contract.Owner(&_KeystoneForwarder.CallOpts) -} - -func (_KeystoneForwarder *KeystoneForwarderCaller) TypeAndVersion(opts *bind.CallOpts) (string, error) { - var out []interface{} - err := _KeystoneForwarder.contract.Call(opts, &out, "typeAndVersion") - - if err != nil { - return *new(string), err - } - - out0 := *abi.ConvertType(out[0], new(string)).(*string) - - return out0, err - -} - -func (_KeystoneForwarder *KeystoneForwarderSession) TypeAndVersion() (string, error) { - return _KeystoneForwarder.Contract.TypeAndVersion(&_KeystoneForwarder.CallOpts) -} - -func (_KeystoneForwarder *KeystoneForwarderCallerSession) TypeAndVersion() (string, error) { - return _KeystoneForwarder.Contract.TypeAndVersion(&_KeystoneForwarder.CallOpts) -} - -func (_KeystoneForwarder *KeystoneForwarderTransactor) AcceptOwnership(opts *bind.TransactOpts) (*types.Transaction, error) { - return _KeystoneForwarder.contract.Transact(opts, "acceptOwnership") -} - -func (_KeystoneForwarder *KeystoneForwarderSession) AcceptOwnership() (*types.Transaction, error) { - return _KeystoneForwarder.Contract.AcceptOwnership(&_KeystoneForwarder.TransactOpts) -} - -func (_KeystoneForwarder *KeystoneForwarderTransactorSession) AcceptOwnership() (*types.Transaction, error) { - return _KeystoneForwarder.Contract.AcceptOwnership(&_KeystoneForwarder.TransactOpts) -} - -func (_KeystoneForwarder *KeystoneForwarderTransactor) AddForwarder(opts *bind.TransactOpts, forwarder common.Address) (*types.Transaction, error) { - return _KeystoneForwarder.contract.Transact(opts, "addForwarder", forwarder) -} - -func (_KeystoneForwarder *KeystoneForwarderSession) AddForwarder(forwarder common.Address) (*types.Transaction, error) { - return _KeystoneForwarder.Contract.AddForwarder(&_KeystoneForwarder.TransactOpts, forwarder) -} - -func (_KeystoneForwarder *KeystoneForwarderTransactorSession) AddForwarder(forwarder common.Address) (*types.Transaction, error) { - return _KeystoneForwarder.Contract.AddForwarder(&_KeystoneForwarder.TransactOpts, forwarder) -} - -func (_KeystoneForwarder *KeystoneForwarderTransactor) ClearConfig(opts *bind.TransactOpts, donId uint32, configVersion uint32) (*types.Transaction, error) { - return _KeystoneForwarder.contract.Transact(opts, "clearConfig", donId, configVersion) -} - -func (_KeystoneForwarder *KeystoneForwarderSession) ClearConfig(donId uint32, configVersion uint32) (*types.Transaction, error) { - return _KeystoneForwarder.Contract.ClearConfig(&_KeystoneForwarder.TransactOpts, donId, configVersion) -} - -func (_KeystoneForwarder *KeystoneForwarderTransactorSession) ClearConfig(donId uint32, configVersion uint32) (*types.Transaction, error) { - return _KeystoneForwarder.Contract.ClearConfig(&_KeystoneForwarder.TransactOpts, donId, configVersion) -} - -func (_KeystoneForwarder *KeystoneForwarderTransactor) RemoveForwarder(opts *bind.TransactOpts, forwarder common.Address) (*types.Transaction, error) { - return _KeystoneForwarder.contract.Transact(opts, "removeForwarder", forwarder) -} - -func (_KeystoneForwarder *KeystoneForwarderSession) RemoveForwarder(forwarder common.Address) (*types.Transaction, error) { - return _KeystoneForwarder.Contract.RemoveForwarder(&_KeystoneForwarder.TransactOpts, forwarder) -} - -func (_KeystoneForwarder *KeystoneForwarderTransactorSession) RemoveForwarder(forwarder common.Address) (*types.Transaction, error) { - return _KeystoneForwarder.Contract.RemoveForwarder(&_KeystoneForwarder.TransactOpts, forwarder) -} - -func (_KeystoneForwarder *KeystoneForwarderTransactor) Report(opts *bind.TransactOpts, receiver common.Address, rawReport []byte, reportContext []byte, signatures [][]byte) (*types.Transaction, error) { - return _KeystoneForwarder.contract.Transact(opts, "report", receiver, rawReport, reportContext, signatures) -} - -func (_KeystoneForwarder *KeystoneForwarderSession) Report(receiver common.Address, rawReport []byte, reportContext []byte, signatures [][]byte) (*types.Transaction, error) { - return _KeystoneForwarder.Contract.Report(&_KeystoneForwarder.TransactOpts, receiver, rawReport, reportContext, signatures) -} - -func (_KeystoneForwarder *KeystoneForwarderTransactorSession) Report(receiver common.Address, rawReport []byte, reportContext []byte, signatures [][]byte) (*types.Transaction, error) { - return _KeystoneForwarder.Contract.Report(&_KeystoneForwarder.TransactOpts, receiver, rawReport, reportContext, signatures) -} - -func (_KeystoneForwarder *KeystoneForwarderTransactor) Route(opts *bind.TransactOpts, transmissionId [32]byte, transmitter common.Address, receiver common.Address, metadata []byte, validatedReport []byte) (*types.Transaction, error) { - return _KeystoneForwarder.contract.Transact(opts, "route", transmissionId, transmitter, receiver, metadata, validatedReport) -} - -func (_KeystoneForwarder *KeystoneForwarderSession) Route(transmissionId [32]byte, transmitter common.Address, receiver common.Address, metadata []byte, validatedReport []byte) (*types.Transaction, error) { - return _KeystoneForwarder.Contract.Route(&_KeystoneForwarder.TransactOpts, transmissionId, transmitter, receiver, metadata, validatedReport) -} - -func (_KeystoneForwarder *KeystoneForwarderTransactorSession) Route(transmissionId [32]byte, transmitter common.Address, receiver common.Address, metadata []byte, validatedReport []byte) (*types.Transaction, error) { - return _KeystoneForwarder.Contract.Route(&_KeystoneForwarder.TransactOpts, transmissionId, transmitter, receiver, metadata, validatedReport) -} - -func (_KeystoneForwarder *KeystoneForwarderTransactor) SetConfig(opts *bind.TransactOpts, donId uint32, configVersion uint32, f uint8, signers []common.Address) (*types.Transaction, error) { - return _KeystoneForwarder.contract.Transact(opts, "setConfig", donId, configVersion, f, signers) -} - -func (_KeystoneForwarder *KeystoneForwarderSession) SetConfig(donId uint32, configVersion uint32, f uint8, signers []common.Address) (*types.Transaction, error) { - return _KeystoneForwarder.Contract.SetConfig(&_KeystoneForwarder.TransactOpts, donId, configVersion, f, signers) -} - -func (_KeystoneForwarder *KeystoneForwarderTransactorSession) SetConfig(donId uint32, configVersion uint32, f uint8, signers []common.Address) (*types.Transaction, error) { - return _KeystoneForwarder.Contract.SetConfig(&_KeystoneForwarder.TransactOpts, donId, configVersion, f, signers) -} - -func (_KeystoneForwarder *KeystoneForwarderTransactor) TransferOwnership(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) { - return _KeystoneForwarder.contract.Transact(opts, "transferOwnership", to) -} - -func (_KeystoneForwarder *KeystoneForwarderSession) TransferOwnership(to common.Address) (*types.Transaction, error) { - return _KeystoneForwarder.Contract.TransferOwnership(&_KeystoneForwarder.TransactOpts, to) -} - -func (_KeystoneForwarder *KeystoneForwarderTransactorSession) TransferOwnership(to common.Address) (*types.Transaction, error) { - return _KeystoneForwarder.Contract.TransferOwnership(&_KeystoneForwarder.TransactOpts, to) -} - -type KeystoneForwarderConfigSetIterator struct { - Event *KeystoneForwarderConfigSet - - contract *bind.BoundContract - event string - - logs chan types.Log - sub ethereum.Subscription - done bool - fail error -} - -func (it *KeystoneForwarderConfigSetIterator) Next() bool { - - if it.fail != nil { - return false - } - - if it.done { - select { - case log := <-it.logs: - it.Event = new(KeystoneForwarderConfigSet) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - default: - return false - } - } - - select { - case log := <-it.logs: - it.Event = new(KeystoneForwarderConfigSet) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - case err := <-it.sub.Err(): - it.done = true - it.fail = err - return it.Next() - } -} - -func (it *KeystoneForwarderConfigSetIterator) Error() error { - return it.fail -} - -func (it *KeystoneForwarderConfigSetIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -type KeystoneForwarderConfigSet struct { - DonId uint32 - ConfigVersion uint32 - F uint8 - Signers []common.Address - Raw types.Log -} - -func (_KeystoneForwarder *KeystoneForwarderFilterer) FilterConfigSet(opts *bind.FilterOpts, donId []uint32, configVersion []uint32) (*KeystoneForwarderConfigSetIterator, error) { - - var donIdRule []interface{} - for _, donIdItem := range donId { - donIdRule = append(donIdRule, donIdItem) - } - var configVersionRule []interface{} - for _, configVersionItem := range configVersion { - configVersionRule = append(configVersionRule, configVersionItem) - } - - logs, sub, err := _KeystoneForwarder.contract.FilterLogs(opts, "ConfigSet", donIdRule, configVersionRule) - if err != nil { - return nil, err - } - return &KeystoneForwarderConfigSetIterator{contract: _KeystoneForwarder.contract, event: "ConfigSet", logs: logs, sub: sub}, nil -} - -func (_KeystoneForwarder *KeystoneForwarderFilterer) WatchConfigSet(opts *bind.WatchOpts, sink chan<- *KeystoneForwarderConfigSet, donId []uint32, configVersion []uint32) (event.Subscription, error) { - - var donIdRule []interface{} - for _, donIdItem := range donId { - donIdRule = append(donIdRule, donIdItem) - } - var configVersionRule []interface{} - for _, configVersionItem := range configVersion { - configVersionRule = append(configVersionRule, configVersionItem) - } - - logs, sub, err := _KeystoneForwarder.contract.WatchLogs(opts, "ConfigSet", donIdRule, configVersionRule) - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - - event := new(KeystoneForwarderConfigSet) - if err := _KeystoneForwarder.contract.UnpackLog(event, "ConfigSet", log); err != nil { - return err - } - event.Raw = log - - select { - case sink <- event: - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - } - }), nil -} - -func (_KeystoneForwarder *KeystoneForwarderFilterer) ParseConfigSet(log types.Log) (*KeystoneForwarderConfigSet, error) { - event := new(KeystoneForwarderConfigSet) - if err := _KeystoneForwarder.contract.UnpackLog(event, "ConfigSet", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -type KeystoneForwarderForwarderAddedIterator struct { - Event *KeystoneForwarderForwarderAdded - - contract *bind.BoundContract - event string - - logs chan types.Log - sub ethereum.Subscription - done bool - fail error -} - -func (it *KeystoneForwarderForwarderAddedIterator) Next() bool { - - if it.fail != nil { - return false - } - - if it.done { - select { - case log := <-it.logs: - it.Event = new(KeystoneForwarderForwarderAdded) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - default: - return false - } - } - - select { - case log := <-it.logs: - it.Event = new(KeystoneForwarderForwarderAdded) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - case err := <-it.sub.Err(): - it.done = true - it.fail = err - return it.Next() - } -} - -func (it *KeystoneForwarderForwarderAddedIterator) Error() error { - return it.fail -} - -func (it *KeystoneForwarderForwarderAddedIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -type KeystoneForwarderForwarderAdded struct { - Forwarder common.Address - Raw types.Log -} - -func (_KeystoneForwarder *KeystoneForwarderFilterer) FilterForwarderAdded(opts *bind.FilterOpts, forwarder []common.Address) (*KeystoneForwarderForwarderAddedIterator, error) { - - var forwarderRule []interface{} - for _, forwarderItem := range forwarder { - forwarderRule = append(forwarderRule, forwarderItem) - } - - logs, sub, err := _KeystoneForwarder.contract.FilterLogs(opts, "ForwarderAdded", forwarderRule) - if err != nil { - return nil, err - } - return &KeystoneForwarderForwarderAddedIterator{contract: _KeystoneForwarder.contract, event: "ForwarderAdded", logs: logs, sub: sub}, nil -} - -func (_KeystoneForwarder *KeystoneForwarderFilterer) WatchForwarderAdded(opts *bind.WatchOpts, sink chan<- *KeystoneForwarderForwarderAdded, forwarder []common.Address) (event.Subscription, error) { - - var forwarderRule []interface{} - for _, forwarderItem := range forwarder { - forwarderRule = append(forwarderRule, forwarderItem) - } - - logs, sub, err := _KeystoneForwarder.contract.WatchLogs(opts, "ForwarderAdded", forwarderRule) - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - - event := new(KeystoneForwarderForwarderAdded) - if err := _KeystoneForwarder.contract.UnpackLog(event, "ForwarderAdded", log); err != nil { - return err - } - event.Raw = log - - select { - case sink <- event: - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - } - }), nil -} - -func (_KeystoneForwarder *KeystoneForwarderFilterer) ParseForwarderAdded(log types.Log) (*KeystoneForwarderForwarderAdded, error) { - event := new(KeystoneForwarderForwarderAdded) - if err := _KeystoneForwarder.contract.UnpackLog(event, "ForwarderAdded", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -type KeystoneForwarderForwarderRemovedIterator struct { - Event *KeystoneForwarderForwarderRemoved - - contract *bind.BoundContract - event string - - logs chan types.Log - sub ethereum.Subscription - done bool - fail error -} - -func (it *KeystoneForwarderForwarderRemovedIterator) Next() bool { - - if it.fail != nil { - return false - } - - if it.done { - select { - case log := <-it.logs: - it.Event = new(KeystoneForwarderForwarderRemoved) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - default: - return false - } - } - - select { - case log := <-it.logs: - it.Event = new(KeystoneForwarderForwarderRemoved) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - case err := <-it.sub.Err(): - it.done = true - it.fail = err - return it.Next() - } -} - -func (it *KeystoneForwarderForwarderRemovedIterator) Error() error { - return it.fail -} - -func (it *KeystoneForwarderForwarderRemovedIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -type KeystoneForwarderForwarderRemoved struct { - Forwarder common.Address - Raw types.Log -} - -func (_KeystoneForwarder *KeystoneForwarderFilterer) FilterForwarderRemoved(opts *bind.FilterOpts, forwarder []common.Address) (*KeystoneForwarderForwarderRemovedIterator, error) { - - var forwarderRule []interface{} - for _, forwarderItem := range forwarder { - forwarderRule = append(forwarderRule, forwarderItem) - } - - logs, sub, err := _KeystoneForwarder.contract.FilterLogs(opts, "ForwarderRemoved", forwarderRule) - if err != nil { - return nil, err - } - return &KeystoneForwarderForwarderRemovedIterator{contract: _KeystoneForwarder.contract, event: "ForwarderRemoved", logs: logs, sub: sub}, nil -} - -func (_KeystoneForwarder *KeystoneForwarderFilterer) WatchForwarderRemoved(opts *bind.WatchOpts, sink chan<- *KeystoneForwarderForwarderRemoved, forwarder []common.Address) (event.Subscription, error) { - - var forwarderRule []interface{} - for _, forwarderItem := range forwarder { - forwarderRule = append(forwarderRule, forwarderItem) - } - - logs, sub, err := _KeystoneForwarder.contract.WatchLogs(opts, "ForwarderRemoved", forwarderRule) - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - - event := new(KeystoneForwarderForwarderRemoved) - if err := _KeystoneForwarder.contract.UnpackLog(event, "ForwarderRemoved", log); err != nil { - return err - } - event.Raw = log - - select { - case sink <- event: - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - } - }), nil -} - -func (_KeystoneForwarder *KeystoneForwarderFilterer) ParseForwarderRemoved(log types.Log) (*KeystoneForwarderForwarderRemoved, error) { - event := new(KeystoneForwarderForwarderRemoved) - if err := _KeystoneForwarder.contract.UnpackLog(event, "ForwarderRemoved", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -type KeystoneForwarderOwnershipTransferRequestedIterator struct { - Event *KeystoneForwarderOwnershipTransferRequested - - contract *bind.BoundContract - event string - - logs chan types.Log - sub ethereum.Subscription - done bool - fail error -} - -func (it *KeystoneForwarderOwnershipTransferRequestedIterator) Next() bool { - - if it.fail != nil { - return false - } - - if it.done { - select { - case log := <-it.logs: - it.Event = new(KeystoneForwarderOwnershipTransferRequested) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - default: - return false - } - } - - select { - case log := <-it.logs: - it.Event = new(KeystoneForwarderOwnershipTransferRequested) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - case err := <-it.sub.Err(): - it.done = true - it.fail = err - return it.Next() - } -} - -func (it *KeystoneForwarderOwnershipTransferRequestedIterator) Error() error { - return it.fail -} - -func (it *KeystoneForwarderOwnershipTransferRequestedIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -type KeystoneForwarderOwnershipTransferRequested struct { - From common.Address - To common.Address - Raw types.Log -} - -func (_KeystoneForwarder *KeystoneForwarderFilterer) FilterOwnershipTransferRequested(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*KeystoneForwarderOwnershipTransferRequestedIterator, error) { - - var fromRule []interface{} - for _, fromItem := range from { - fromRule = append(fromRule, fromItem) - } - var toRule []interface{} - for _, toItem := range to { - toRule = append(toRule, toItem) - } - - logs, sub, err := _KeystoneForwarder.contract.FilterLogs(opts, "OwnershipTransferRequested", fromRule, toRule) - if err != nil { - return nil, err - } - return &KeystoneForwarderOwnershipTransferRequestedIterator{contract: _KeystoneForwarder.contract, event: "OwnershipTransferRequested", logs: logs, sub: sub}, nil -} - -func (_KeystoneForwarder *KeystoneForwarderFilterer) WatchOwnershipTransferRequested(opts *bind.WatchOpts, sink chan<- *KeystoneForwarderOwnershipTransferRequested, from []common.Address, to []common.Address) (event.Subscription, error) { - - var fromRule []interface{} - for _, fromItem := range from { - fromRule = append(fromRule, fromItem) - } - var toRule []interface{} - for _, toItem := range to { - toRule = append(toRule, toItem) - } - - logs, sub, err := _KeystoneForwarder.contract.WatchLogs(opts, "OwnershipTransferRequested", fromRule, toRule) - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - - event := new(KeystoneForwarderOwnershipTransferRequested) - if err := _KeystoneForwarder.contract.UnpackLog(event, "OwnershipTransferRequested", log); err != nil { - return err - } - event.Raw = log - - select { - case sink <- event: - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - } - }), nil -} - -func (_KeystoneForwarder *KeystoneForwarderFilterer) ParseOwnershipTransferRequested(log types.Log) (*KeystoneForwarderOwnershipTransferRequested, error) { - event := new(KeystoneForwarderOwnershipTransferRequested) - if err := _KeystoneForwarder.contract.UnpackLog(event, "OwnershipTransferRequested", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -type KeystoneForwarderOwnershipTransferredIterator struct { - Event *KeystoneForwarderOwnershipTransferred - - contract *bind.BoundContract - event string - - logs chan types.Log - sub ethereum.Subscription - done bool - fail error -} - -func (it *KeystoneForwarderOwnershipTransferredIterator) Next() bool { - - if it.fail != nil { - return false - } - - if it.done { - select { - case log := <-it.logs: - it.Event = new(KeystoneForwarderOwnershipTransferred) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - default: - return false - } - } - - select { - case log := <-it.logs: - it.Event = new(KeystoneForwarderOwnershipTransferred) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - case err := <-it.sub.Err(): - it.done = true - it.fail = err - return it.Next() - } -} - -func (it *KeystoneForwarderOwnershipTransferredIterator) Error() error { - return it.fail -} - -func (it *KeystoneForwarderOwnershipTransferredIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -type KeystoneForwarderOwnershipTransferred struct { - From common.Address - To common.Address - Raw types.Log -} - -func (_KeystoneForwarder *KeystoneForwarderFilterer) FilterOwnershipTransferred(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*KeystoneForwarderOwnershipTransferredIterator, error) { - - var fromRule []interface{} - for _, fromItem := range from { - fromRule = append(fromRule, fromItem) - } - var toRule []interface{} - for _, toItem := range to { - toRule = append(toRule, toItem) - } - - logs, sub, err := _KeystoneForwarder.contract.FilterLogs(opts, "OwnershipTransferred", fromRule, toRule) - if err != nil { - return nil, err - } - return &KeystoneForwarderOwnershipTransferredIterator{contract: _KeystoneForwarder.contract, event: "OwnershipTransferred", logs: logs, sub: sub}, nil -} - -func (_KeystoneForwarder *KeystoneForwarderFilterer) WatchOwnershipTransferred(opts *bind.WatchOpts, sink chan<- *KeystoneForwarderOwnershipTransferred, from []common.Address, to []common.Address) (event.Subscription, error) { - - var fromRule []interface{} - for _, fromItem := range from { - fromRule = append(fromRule, fromItem) - } - var toRule []interface{} - for _, toItem := range to { - toRule = append(toRule, toItem) - } - - logs, sub, err := _KeystoneForwarder.contract.WatchLogs(opts, "OwnershipTransferred", fromRule, toRule) - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - - event := new(KeystoneForwarderOwnershipTransferred) - if err := _KeystoneForwarder.contract.UnpackLog(event, "OwnershipTransferred", log); err != nil { - return err - } - event.Raw = log - - select { - case sink <- event: - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - } - }), nil -} - -func (_KeystoneForwarder *KeystoneForwarderFilterer) ParseOwnershipTransferred(log types.Log) (*KeystoneForwarderOwnershipTransferred, error) { - event := new(KeystoneForwarderOwnershipTransferred) - if err := _KeystoneForwarder.contract.UnpackLog(event, "OwnershipTransferred", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -type KeystoneForwarderReportProcessedIterator struct { - Event *KeystoneForwarderReportProcessed - - contract *bind.BoundContract - event string - - logs chan types.Log - sub ethereum.Subscription - done bool - fail error -} - -func (it *KeystoneForwarderReportProcessedIterator) Next() bool { - - if it.fail != nil { - return false - } - - if it.done { - select { - case log := <-it.logs: - it.Event = new(KeystoneForwarderReportProcessed) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - default: - return false - } - } - - select { - case log := <-it.logs: - it.Event = new(KeystoneForwarderReportProcessed) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - case err := <-it.sub.Err(): - it.done = true - it.fail = err - return it.Next() - } -} - -func (it *KeystoneForwarderReportProcessedIterator) Error() error { - return it.fail -} - -func (it *KeystoneForwarderReportProcessedIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -type KeystoneForwarderReportProcessed struct { - Receiver common.Address - WorkflowExecutionId [32]byte - ReportId [2]byte - Result bool - Raw types.Log -} - -func (_KeystoneForwarder *KeystoneForwarderFilterer) FilterReportProcessed(opts *bind.FilterOpts, receiver []common.Address, workflowExecutionId [][32]byte, reportId [][2]byte) (*KeystoneForwarderReportProcessedIterator, error) { - - var receiverRule []interface{} - for _, receiverItem := range receiver { - receiverRule = append(receiverRule, receiverItem) - } - var workflowExecutionIdRule []interface{} - for _, workflowExecutionIdItem := range workflowExecutionId { - workflowExecutionIdRule = append(workflowExecutionIdRule, workflowExecutionIdItem) - } - var reportIdRule []interface{} - for _, reportIdItem := range reportId { - reportIdRule = append(reportIdRule, reportIdItem) - } - - logs, sub, err := _KeystoneForwarder.contract.FilterLogs(opts, "ReportProcessed", receiverRule, workflowExecutionIdRule, reportIdRule) - if err != nil { - return nil, err - } - return &KeystoneForwarderReportProcessedIterator{contract: _KeystoneForwarder.contract, event: "ReportProcessed", logs: logs, sub: sub}, nil -} - -func (_KeystoneForwarder *KeystoneForwarderFilterer) WatchReportProcessed(opts *bind.WatchOpts, sink chan<- *KeystoneForwarderReportProcessed, receiver []common.Address, workflowExecutionId [][32]byte, reportId [][2]byte) (event.Subscription, error) { - - var receiverRule []interface{} - for _, receiverItem := range receiver { - receiverRule = append(receiverRule, receiverItem) - } - var workflowExecutionIdRule []interface{} - for _, workflowExecutionIdItem := range workflowExecutionId { - workflowExecutionIdRule = append(workflowExecutionIdRule, workflowExecutionIdItem) - } - var reportIdRule []interface{} - for _, reportIdItem := range reportId { - reportIdRule = append(reportIdRule, reportIdItem) - } - - logs, sub, err := _KeystoneForwarder.contract.WatchLogs(opts, "ReportProcessed", receiverRule, workflowExecutionIdRule, reportIdRule) - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - - event := new(KeystoneForwarderReportProcessed) - if err := _KeystoneForwarder.contract.UnpackLog(event, "ReportProcessed", log); err != nil { - return err - } - event.Raw = log - - select { - case sink <- event: - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - } - }), nil -} - -func (_KeystoneForwarder *KeystoneForwarderFilterer) ParseReportProcessed(log types.Log) (*KeystoneForwarderReportProcessed, error) { - event := new(KeystoneForwarderReportProcessed) - if err := _KeystoneForwarder.contract.UnpackLog(event, "ReportProcessed", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -func (_KeystoneForwarder *KeystoneForwarder) ParseLog(log types.Log) (generated.AbigenLog, error) { - switch log.Topics[0] { - case _KeystoneForwarder.abi.Events["ConfigSet"].ID: - return _KeystoneForwarder.ParseConfigSet(log) - case _KeystoneForwarder.abi.Events["ForwarderAdded"].ID: - return _KeystoneForwarder.ParseForwarderAdded(log) - case _KeystoneForwarder.abi.Events["ForwarderRemoved"].ID: - return _KeystoneForwarder.ParseForwarderRemoved(log) - case _KeystoneForwarder.abi.Events["OwnershipTransferRequested"].ID: - return _KeystoneForwarder.ParseOwnershipTransferRequested(log) - case _KeystoneForwarder.abi.Events["OwnershipTransferred"].ID: - return _KeystoneForwarder.ParseOwnershipTransferred(log) - case _KeystoneForwarder.abi.Events["ReportProcessed"].ID: - return _KeystoneForwarder.ParseReportProcessed(log) - - default: - return nil, fmt.Errorf("abigen wrapper received unknown log topic: %v", log.Topics[0]) - } -} - -func (KeystoneForwarderConfigSet) Topic() common.Hash { - return common.HexToHash("0x4120bd3b23957dd423555817d55654d4481b438aa15485c21b4180c784f1a455") -} - -func (KeystoneForwarderForwarderAdded) Topic() common.Hash { - return common.HexToHash("0x0ea0ce2c048ff45a4a95f2947879de3fb94abec2f152190400cab2d1272a68e7") -} - -func (KeystoneForwarderForwarderRemoved) Topic() common.Hash { - return common.HexToHash("0xb96d15bf9258c7b8df062753a6a262864611fc7b060a5ee2e57e79b85f898d38") -} - -func (KeystoneForwarderOwnershipTransferRequested) Topic() common.Hash { - return common.HexToHash("0xed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae1278") -} - -func (KeystoneForwarderOwnershipTransferred) Topic() common.Hash { - return common.HexToHash("0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0") -} - -func (KeystoneForwarderReportProcessed) Topic() common.Hash { - return common.HexToHash("0x3617b009e9785c42daebadb6d3fb553243a4bf586d07ea72d65d80013ce116b5") -} - -func (_KeystoneForwarder *KeystoneForwarder) Address() common.Address { - return _KeystoneForwarder.address -} - -type KeystoneForwarderInterface interface { - GetTransmissionId(opts *bind.CallOpts, receiver common.Address, workflowExecutionId [32]byte, reportId [2]byte) ([32]byte, error) - - GetTransmissionInfo(opts *bind.CallOpts, receiver common.Address, workflowExecutionId [32]byte, reportId [2]byte) (IRouterTransmissionInfo, error) - - GetTransmitter(opts *bind.CallOpts, receiver common.Address, workflowExecutionId [32]byte, reportId [2]byte) (common.Address, error) - - IsForwarder(opts *bind.CallOpts, forwarder common.Address) (bool, error) - - Owner(opts *bind.CallOpts) (common.Address, error) - - TypeAndVersion(opts *bind.CallOpts) (string, error) - - AcceptOwnership(opts *bind.TransactOpts) (*types.Transaction, error) - - AddForwarder(opts *bind.TransactOpts, forwarder common.Address) (*types.Transaction, error) - - ClearConfig(opts *bind.TransactOpts, donId uint32, configVersion uint32) (*types.Transaction, error) - - RemoveForwarder(opts *bind.TransactOpts, forwarder common.Address) (*types.Transaction, error) - - Report(opts *bind.TransactOpts, receiver common.Address, rawReport []byte, reportContext []byte, signatures [][]byte) (*types.Transaction, error) - - Route(opts *bind.TransactOpts, transmissionId [32]byte, transmitter common.Address, receiver common.Address, metadata []byte, validatedReport []byte) (*types.Transaction, error) - - SetConfig(opts *bind.TransactOpts, donId uint32, configVersion uint32, f uint8, signers []common.Address) (*types.Transaction, error) - - TransferOwnership(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) - - FilterConfigSet(opts *bind.FilterOpts, donId []uint32, configVersion []uint32) (*KeystoneForwarderConfigSetIterator, error) - - WatchConfigSet(opts *bind.WatchOpts, sink chan<- *KeystoneForwarderConfigSet, donId []uint32, configVersion []uint32) (event.Subscription, error) - - ParseConfigSet(log types.Log) (*KeystoneForwarderConfigSet, error) - - FilterForwarderAdded(opts *bind.FilterOpts, forwarder []common.Address) (*KeystoneForwarderForwarderAddedIterator, error) - - WatchForwarderAdded(opts *bind.WatchOpts, sink chan<- *KeystoneForwarderForwarderAdded, forwarder []common.Address) (event.Subscription, error) - - ParseForwarderAdded(log types.Log) (*KeystoneForwarderForwarderAdded, error) - - FilterForwarderRemoved(opts *bind.FilterOpts, forwarder []common.Address) (*KeystoneForwarderForwarderRemovedIterator, error) - - WatchForwarderRemoved(opts *bind.WatchOpts, sink chan<- *KeystoneForwarderForwarderRemoved, forwarder []common.Address) (event.Subscription, error) - - ParseForwarderRemoved(log types.Log) (*KeystoneForwarderForwarderRemoved, error) - - FilterOwnershipTransferRequested(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*KeystoneForwarderOwnershipTransferRequestedIterator, error) - - WatchOwnershipTransferRequested(opts *bind.WatchOpts, sink chan<- *KeystoneForwarderOwnershipTransferRequested, from []common.Address, to []common.Address) (event.Subscription, error) - - ParseOwnershipTransferRequested(log types.Log) (*KeystoneForwarderOwnershipTransferRequested, error) - - FilterOwnershipTransferred(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*KeystoneForwarderOwnershipTransferredIterator, error) - - WatchOwnershipTransferred(opts *bind.WatchOpts, sink chan<- *KeystoneForwarderOwnershipTransferred, from []common.Address, to []common.Address) (event.Subscription, error) - - ParseOwnershipTransferred(log types.Log) (*KeystoneForwarderOwnershipTransferred, error) - - FilterReportProcessed(opts *bind.FilterOpts, receiver []common.Address, workflowExecutionId [][32]byte, reportId [][2]byte) (*KeystoneForwarderReportProcessedIterator, error) - - WatchReportProcessed(opts *bind.WatchOpts, sink chan<- *KeystoneForwarderReportProcessed, receiver []common.Address, workflowExecutionId [][32]byte, reportId [][2]byte) (event.Subscription, error) - - ParseReportProcessed(log types.Log) (*KeystoneForwarderReportProcessed, error) - - ParseLog(log types.Log) (generated.AbigenLog, error) - - Address() common.Address -} diff --git a/core/gethwrappers/keystone/generated/ocr3_capability_1_0_0/ocr3_capability.go b/core/gethwrappers/keystone/generated/ocr3_capability_1_0_0/ocr3_capability.go deleted file mode 100644 index b4292c44125..00000000000 --- a/core/gethwrappers/keystone/generated/ocr3_capability_1_0_0/ocr3_capability.go +++ /dev/null @@ -1,946 +0,0 @@ -// Code generated - DO NOT EDIT. -// This file is a generated binding and any manual changes will be lost. - -package ocr3_capability - -import ( - "errors" - "fmt" - "math/big" - "strings" - - ethereum "github.com/ethereum/go-ethereum" - "github.com/ethereum/go-ethereum/accounts/abi" - "github.com/ethereum/go-ethereum/accounts/abi/bind" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/event" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated" -) - -var ( - _ = errors.New - _ = big.NewInt - _ = strings.NewReader - _ = ethereum.NotFound - _ = bind.Bind - _ = common.Big1 - _ = types.BloomLookup - _ = event.NewSubscription - _ = abi.ConvertType -) - -var OCR3CapabilityMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[{\"internalType\":\"string\",\"name\":\"message\",\"type\":\"string\"}],\"name\":\"InvalidConfig\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ReportingUnsupported\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"previousConfigBlockNumber\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"configCount\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes[]\",\"name\":\"signers\",\"type\":\"bytes[]\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"f\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"onchainConfig\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"offchainConfigVersion\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"}],\"name\":\"ConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"epoch\",\"type\":\"uint32\"}],\"name\":\"Transmitted\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"latestConfigDetails\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"configCount\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"blockNumber\",\"type\":\"uint32\"},{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"latestConfigDigestAndEpoch\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"scanLogs\",\"type\":\"bool\"},{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"internalType\":\"uint32\",\"name\":\"epoch\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes[]\",\"name\":\"_signers\",\"type\":\"bytes[]\"},{\"internalType\":\"address[]\",\"name\":\"_transmitters\",\"type\":\"address[]\"},{\"internalType\":\"uint8\",\"name\":\"_f\",\"type\":\"uint8\"},{\"internalType\":\"bytes\",\"name\":\"_onchainConfig\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"_offchainConfigVersion\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"_offchainConfig\",\"type\":\"bytes\"}],\"name\":\"setConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[3]\",\"name\":\"\",\"type\":\"bytes32[3]\"},{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"},{\"internalType\":\"bytes32[]\",\"name\":\"\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes32[]\",\"name\":\"\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"name\":\"transmit\",\"outputs\":[],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", - Bin: "0x608060405234801561001057600080fd5b5033806000816100675760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615610097576100978161009f565b505050610148565b336001600160a01b038216036100f75760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640161005e565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6112bc806101576000396000f3fe608060405234801561001057600080fd5b50600436106100885760003560e01c80638da5cb5b1161005b5780638da5cb5b14610169578063afcb95d714610191578063b1dc65a4146101b1578063f2fde38b146101c457600080fd5b8063181f5a771461008d57806379ba5097146100df5780637f3c87d3146100e957806381ff7048146100fc575b600080fd5b6100c96040518060400160405280601481526020017f4f4352334361706162696c69747920312e302e3000000000000000000000000081525081565b6040516100d69190610b8a565b60405180910390f35b6100e76101d7565b005b6100e76100f7366004610cf8565b6102d9565b61014660015460025463ffffffff74010000000000000000000000000000000000000000830481169378010000000000000000000000000000000000000000000000009093041691565b6040805163ffffffff9485168152939092166020840152908201526060016100d6565b60005460405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100d6565b6040805160018152600060208201819052918101919091526060016100d6565b6100e76101bf366004610dd4565b6108b7565b6100e76101d2366004610edd565b6108e9565b60015473ffffffffffffffffffffffffffffffffffffffff16331461025d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064015b60405180910390fd5b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b868560ff8616601f83111561034a576040517f89a6198900000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f746f6f206d616e79207369676e657273000000000000000000000000000000006044820152606401610254565b806000036103b4576040517f89a6198900000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f66206d75737420626520706f73697469766500000000000000000000000000006044820152606401610254565b818314610442576040517f89a61989000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f6f7261636c6520616464726573736573206f7574206f6620726567697374726160448201527f74696f6e000000000000000000000000000000000000000000000000000000006064820152608401610254565b61044d816003610f27565b83116104b5576040517f89a6198900000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f6661756c74792d6f7261636c65206620746f6f206869676800000000000000006044820152606401610254565b6104bd6108fd565b60005b8a8110156107255760008a8a838181106104dc576104dc610f44565b90506020020160208101906104f19190610edd565b73ffffffffffffffffffffffffffffffffffffffff160361056e576040517f89a6198900000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f7472616e736d6974746572206d757374206e6f7420626520656d7074790000006044820152606401610254565b3660008d8d8481811061058357610583610f44565b90506020028101906105959190610f73565b9092509050600061ffff82165b8082101561071657806105b6836003610fd8565b111561061e576040517f89a6198900000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f696e76616c6964207369676e6572207075624b657920656e636f64696e6700006044820152606401610254565b60006008858561062f866002610fd8565b81811061063e5761063e610f44565b919091013560f81c90911b90508585610658866001610fd8565b81811061066757610667610f44565b6106789392013560f81c9050610fd8565b90508181610687856003610fd8565b6106919190610fd8565b11156106f9576040517f89a6198900000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f696e76616c6964207369676e6572207075624b657920656e636f64696e6700006044820152606401610254565b610704816003610fd8565b61070e9084610fd8565b9250506105a2565b505050508060010190506104c0565b50600380547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660ff8916179055600180547fffffffff00000000ffffffffffffffffffffffffffffffffffffffffffffffff8116780100000000000000000000000000000000000000000000000063ffffffff43811682029290921780855592048116929182916014916107d491849174010000000000000000000000000000000000000000900416610feb565b92506101000a81548163ffffffff021916908363ffffffff16021790555061081d4630600160149054906101000a900463ffffffff1663ffffffff168f8f8f8f8f8f8f8f610980565b6002600001819055508b8b9050600260010160016101000a81548160ff021916908360ff1602179055507f36257c6e8d535293ad661e377c0baac536289be6707b8a488ac175ddaa4055c881600260000154600160149054906101000a900463ffffffff168f8f8f8f8f8f8f8f6040516108a19b9a9998979695949392919061117e565b60405180910390a1505050505050505050505050565b6040517f0750181900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6108f16108fd565b6108fa81610a31565b50565b60005473ffffffffffffffffffffffffffffffffffffffff16331461097e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401610254565b565b6000808c8c8c8c8c8c8c8c8c8c8c6040516020016109a89b9a99989796959493929190611218565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815291905280516020909101207dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e0e000000000000000000000000000000000000000000000000000000000000179150509b9a5050505050505050505050565b3373ffffffffffffffffffffffffffffffffffffffff821603610ab0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401610254565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6000815180845260005b81811015610b4c57602081850181015186830182015201610b30565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b602081526000610b9d6020830184610b26565b9392505050565b60008083601f840112610bb657600080fd5b50813567ffffffffffffffff811115610bce57600080fd5b6020830191508360208260051b8501011115610be957600080fd5b9250929050565b803560ff81168114610c0157600080fd5b919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f830112610c4657600080fd5b813567ffffffffffffffff80821115610c6157610c61610c06565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908282118183101715610ca757610ca7610c06565b81604052838152866020858801011115610cc057600080fd5b836020870160208301376000602085830101528094505050505092915050565b803567ffffffffffffffff81168114610c0157600080fd5b60008060008060008060008060c0898b031215610d1457600080fd5b883567ffffffffffffffff80821115610d2c57600080fd5b610d388c838d01610ba4565b909a50985060208b0135915080821115610d5157600080fd5b610d5d8c838d01610ba4565b9098509650869150610d7160408c01610bf0565b955060608b0135915080821115610d8757600080fd5b610d938c838d01610c35565b9450610da160808c01610ce0565b935060a08b0135915080821115610db757600080fd5b50610dc48b828c01610c35565b9150509295985092959890939650565b60008060008060008060008060e0898b031215610df057600080fd5b606089018a811115610e0157600080fd5b8998503567ffffffffffffffff80821115610e1b57600080fd5b818b0191508b601f830112610e2f57600080fd5b813581811115610e3e57600080fd5b8c6020828501011115610e5057600080fd5b6020830199508098505060808b0135915080821115610e6e57600080fd5b610e7a8c838d01610ba4565b909750955060a08b0135915080821115610e9357600080fd5b50610ea08b828c01610ba4565b999c989b50969995989497949560c00135949350505050565b803573ffffffffffffffffffffffffffffffffffffffff81168114610c0157600080fd5b600060208284031215610eef57600080fd5b610b9d82610eb9565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b8082028115828204841417610f3e57610f3e610ef8565b92915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112610fa857600080fd5b83018035915067ffffffffffffffff821115610fc357600080fd5b602001915036819003821315610be957600080fd5b80820180821115610f3e57610f3e610ef8565b63ffffffff81811683821601908082111561100857611008610ef8565b5092915050565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b6000838385526020808601955060208560051b8301018460005b8781101561111d577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe085840301895281357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18836030181126110d357600080fd5b8701848101903567ffffffffffffffff8111156110ef57600080fd5b8036038213156110fe57600080fd5b61110985828461100f565b9a86019a9450505090830190600101611072565b5090979650505050505050565b8183526000602080850194508260005b858110156111735773ffffffffffffffffffffffffffffffffffffffff61116083610eb9565b168752958201959082019060010161113a565b509495945050505050565b600061012063ffffffff808f1684528d6020850152808d166040850152508060608401526111af8184018b8d611058565b905082810360808401526111c481898b61112a565b905060ff871660a084015282810360c08401526111e18187610b26565b905067ffffffffffffffff851660e08401528281036101008401526112068185610b26565b9e9d5050505050505050505050505050565b60006101208d835273ffffffffffffffffffffffffffffffffffffffff8d16602084015267ffffffffffffffff808d1660408501528160608501526112608285018c8e611058565b91508382036080850152611275828a8c61112a565b915060ff881660a085015283820360c08501526112928288610b26565b90861660e085015283810361010085015290506112068185610b2656fea164736f6c6343000818000a", -} - -var OCR3CapabilityABI = OCR3CapabilityMetaData.ABI - -var OCR3CapabilityBin = OCR3CapabilityMetaData.Bin - -func DeployOCR3Capability(auth *bind.TransactOpts, backend bind.ContractBackend) (common.Address, *types.Transaction, *OCR3Capability, error) { - parsed, err := OCR3CapabilityMetaData.GetAbi() - if err != nil { - return common.Address{}, nil, nil, err - } - if parsed == nil { - return common.Address{}, nil, nil, errors.New("GetABI returned nil") - } - - address, tx, contract, err := bind.DeployContract(auth, *parsed, common.FromHex(OCR3CapabilityBin), backend) - if err != nil { - return common.Address{}, nil, nil, err - } - return address, tx, &OCR3Capability{address: address, abi: *parsed, OCR3CapabilityCaller: OCR3CapabilityCaller{contract: contract}, OCR3CapabilityTransactor: OCR3CapabilityTransactor{contract: contract}, OCR3CapabilityFilterer: OCR3CapabilityFilterer{contract: contract}}, nil -} - -type OCR3Capability struct { - address common.Address - abi abi.ABI - OCR3CapabilityCaller - OCR3CapabilityTransactor - OCR3CapabilityFilterer -} - -type OCR3CapabilityCaller struct { - contract *bind.BoundContract -} - -type OCR3CapabilityTransactor struct { - contract *bind.BoundContract -} - -type OCR3CapabilityFilterer struct { - contract *bind.BoundContract -} - -type OCR3CapabilitySession struct { - Contract *OCR3Capability - CallOpts bind.CallOpts - TransactOpts bind.TransactOpts -} - -type OCR3CapabilityCallerSession struct { - Contract *OCR3CapabilityCaller - CallOpts bind.CallOpts -} - -type OCR3CapabilityTransactorSession struct { - Contract *OCR3CapabilityTransactor - TransactOpts bind.TransactOpts -} - -type OCR3CapabilityRaw struct { - Contract *OCR3Capability -} - -type OCR3CapabilityCallerRaw struct { - Contract *OCR3CapabilityCaller -} - -type OCR3CapabilityTransactorRaw struct { - Contract *OCR3CapabilityTransactor -} - -func NewOCR3Capability(address common.Address, backend bind.ContractBackend) (*OCR3Capability, error) { - abi, err := abi.JSON(strings.NewReader(OCR3CapabilityABI)) - if err != nil { - return nil, err - } - contract, err := bindOCR3Capability(address, backend, backend, backend) - if err != nil { - return nil, err - } - return &OCR3Capability{address: address, abi: abi, OCR3CapabilityCaller: OCR3CapabilityCaller{contract: contract}, OCR3CapabilityTransactor: OCR3CapabilityTransactor{contract: contract}, OCR3CapabilityFilterer: OCR3CapabilityFilterer{contract: contract}}, nil -} - -func NewOCR3CapabilityCaller(address common.Address, caller bind.ContractCaller) (*OCR3CapabilityCaller, error) { - contract, err := bindOCR3Capability(address, caller, nil, nil) - if err != nil { - return nil, err - } - return &OCR3CapabilityCaller{contract: contract}, nil -} - -func NewOCR3CapabilityTransactor(address common.Address, transactor bind.ContractTransactor) (*OCR3CapabilityTransactor, error) { - contract, err := bindOCR3Capability(address, nil, transactor, nil) - if err != nil { - return nil, err - } - return &OCR3CapabilityTransactor{contract: contract}, nil -} - -func NewOCR3CapabilityFilterer(address common.Address, filterer bind.ContractFilterer) (*OCR3CapabilityFilterer, error) { - contract, err := bindOCR3Capability(address, nil, nil, filterer) - if err != nil { - return nil, err - } - return &OCR3CapabilityFilterer{contract: contract}, nil -} - -func bindOCR3Capability(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { - parsed, err := OCR3CapabilityMetaData.GetAbi() - if err != nil { - return nil, err - } - return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil -} - -func (_OCR3Capability *OCR3CapabilityRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { - return _OCR3Capability.Contract.OCR3CapabilityCaller.contract.Call(opts, result, method, params...) -} - -func (_OCR3Capability *OCR3CapabilityRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { - return _OCR3Capability.Contract.OCR3CapabilityTransactor.contract.Transfer(opts) -} - -func (_OCR3Capability *OCR3CapabilityRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { - return _OCR3Capability.Contract.OCR3CapabilityTransactor.contract.Transact(opts, method, params...) -} - -func (_OCR3Capability *OCR3CapabilityCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { - return _OCR3Capability.Contract.contract.Call(opts, result, method, params...) -} - -func (_OCR3Capability *OCR3CapabilityTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { - return _OCR3Capability.Contract.contract.Transfer(opts) -} - -func (_OCR3Capability *OCR3CapabilityTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { - return _OCR3Capability.Contract.contract.Transact(opts, method, params...) -} - -func (_OCR3Capability *OCR3CapabilityCaller) LatestConfigDetails(opts *bind.CallOpts) (LatestConfigDetails, - - error) { - var out []interface{} - err := _OCR3Capability.contract.Call(opts, &out, "latestConfigDetails") - - outstruct := new(LatestConfigDetails) - if err != nil { - return *outstruct, err - } - - outstruct.ConfigCount = *abi.ConvertType(out[0], new(uint32)).(*uint32) - outstruct.BlockNumber = *abi.ConvertType(out[1], new(uint32)).(*uint32) - outstruct.ConfigDigest = *abi.ConvertType(out[2], new([32]byte)).(*[32]byte) - - return *outstruct, err - -} - -func (_OCR3Capability *OCR3CapabilitySession) LatestConfigDetails() (LatestConfigDetails, - - error) { - return _OCR3Capability.Contract.LatestConfigDetails(&_OCR3Capability.CallOpts) -} - -func (_OCR3Capability *OCR3CapabilityCallerSession) LatestConfigDetails() (LatestConfigDetails, - - error) { - return _OCR3Capability.Contract.LatestConfigDetails(&_OCR3Capability.CallOpts) -} - -func (_OCR3Capability *OCR3CapabilityCaller) LatestConfigDigestAndEpoch(opts *bind.CallOpts) (LatestConfigDigestAndEpoch, - - error) { - var out []interface{} - err := _OCR3Capability.contract.Call(opts, &out, "latestConfigDigestAndEpoch") - - outstruct := new(LatestConfigDigestAndEpoch) - if err != nil { - return *outstruct, err - } - - outstruct.ScanLogs = *abi.ConvertType(out[0], new(bool)).(*bool) - outstruct.ConfigDigest = *abi.ConvertType(out[1], new([32]byte)).(*[32]byte) - outstruct.Epoch = *abi.ConvertType(out[2], new(uint32)).(*uint32) - - return *outstruct, err - -} - -func (_OCR3Capability *OCR3CapabilitySession) LatestConfigDigestAndEpoch() (LatestConfigDigestAndEpoch, - - error) { - return _OCR3Capability.Contract.LatestConfigDigestAndEpoch(&_OCR3Capability.CallOpts) -} - -func (_OCR3Capability *OCR3CapabilityCallerSession) LatestConfigDigestAndEpoch() (LatestConfigDigestAndEpoch, - - error) { - return _OCR3Capability.Contract.LatestConfigDigestAndEpoch(&_OCR3Capability.CallOpts) -} - -func (_OCR3Capability *OCR3CapabilityCaller) Owner(opts *bind.CallOpts) (common.Address, error) { - var out []interface{} - err := _OCR3Capability.contract.Call(opts, &out, "owner") - - if err != nil { - return *new(common.Address), err - } - - out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) - - return out0, err - -} - -func (_OCR3Capability *OCR3CapabilitySession) Owner() (common.Address, error) { - return _OCR3Capability.Contract.Owner(&_OCR3Capability.CallOpts) -} - -func (_OCR3Capability *OCR3CapabilityCallerSession) Owner() (common.Address, error) { - return _OCR3Capability.Contract.Owner(&_OCR3Capability.CallOpts) -} - -func (_OCR3Capability *OCR3CapabilityCaller) Transmit(opts *bind.CallOpts, arg0 [3][32]byte, arg1 []byte, arg2 [][32]byte, arg3 [][32]byte, arg4 [32]byte) error { - var out []interface{} - err := _OCR3Capability.contract.Call(opts, &out, "transmit", arg0, arg1, arg2, arg3, arg4) - - if err != nil { - return err - } - - return err - -} - -func (_OCR3Capability *OCR3CapabilitySession) Transmit(arg0 [3][32]byte, arg1 []byte, arg2 [][32]byte, arg3 [][32]byte, arg4 [32]byte) error { - return _OCR3Capability.Contract.Transmit(&_OCR3Capability.CallOpts, arg0, arg1, arg2, arg3, arg4) -} - -func (_OCR3Capability *OCR3CapabilityCallerSession) Transmit(arg0 [3][32]byte, arg1 []byte, arg2 [][32]byte, arg3 [][32]byte, arg4 [32]byte) error { - return _OCR3Capability.Contract.Transmit(&_OCR3Capability.CallOpts, arg0, arg1, arg2, arg3, arg4) -} - -func (_OCR3Capability *OCR3CapabilityCaller) TypeAndVersion(opts *bind.CallOpts) (string, error) { - var out []interface{} - err := _OCR3Capability.contract.Call(opts, &out, "typeAndVersion") - - if err != nil { - return *new(string), err - } - - out0 := *abi.ConvertType(out[0], new(string)).(*string) - - return out0, err - -} - -func (_OCR3Capability *OCR3CapabilitySession) TypeAndVersion() (string, error) { - return _OCR3Capability.Contract.TypeAndVersion(&_OCR3Capability.CallOpts) -} - -func (_OCR3Capability *OCR3CapabilityCallerSession) TypeAndVersion() (string, error) { - return _OCR3Capability.Contract.TypeAndVersion(&_OCR3Capability.CallOpts) -} - -func (_OCR3Capability *OCR3CapabilityTransactor) AcceptOwnership(opts *bind.TransactOpts) (*types.Transaction, error) { - return _OCR3Capability.contract.Transact(opts, "acceptOwnership") -} - -func (_OCR3Capability *OCR3CapabilitySession) AcceptOwnership() (*types.Transaction, error) { - return _OCR3Capability.Contract.AcceptOwnership(&_OCR3Capability.TransactOpts) -} - -func (_OCR3Capability *OCR3CapabilityTransactorSession) AcceptOwnership() (*types.Transaction, error) { - return _OCR3Capability.Contract.AcceptOwnership(&_OCR3Capability.TransactOpts) -} - -func (_OCR3Capability *OCR3CapabilityTransactor) SetConfig(opts *bind.TransactOpts, _signers [][]byte, _transmitters []common.Address, _f uint8, _onchainConfig []byte, _offchainConfigVersion uint64, _offchainConfig []byte) (*types.Transaction, error) { - return _OCR3Capability.contract.Transact(opts, "setConfig", _signers, _transmitters, _f, _onchainConfig, _offchainConfigVersion, _offchainConfig) -} - -func (_OCR3Capability *OCR3CapabilitySession) SetConfig(_signers [][]byte, _transmitters []common.Address, _f uint8, _onchainConfig []byte, _offchainConfigVersion uint64, _offchainConfig []byte) (*types.Transaction, error) { - return _OCR3Capability.Contract.SetConfig(&_OCR3Capability.TransactOpts, _signers, _transmitters, _f, _onchainConfig, _offchainConfigVersion, _offchainConfig) -} - -func (_OCR3Capability *OCR3CapabilityTransactorSession) SetConfig(_signers [][]byte, _transmitters []common.Address, _f uint8, _onchainConfig []byte, _offchainConfigVersion uint64, _offchainConfig []byte) (*types.Transaction, error) { - return _OCR3Capability.Contract.SetConfig(&_OCR3Capability.TransactOpts, _signers, _transmitters, _f, _onchainConfig, _offchainConfigVersion, _offchainConfig) -} - -func (_OCR3Capability *OCR3CapabilityTransactor) TransferOwnership(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) { - return _OCR3Capability.contract.Transact(opts, "transferOwnership", to) -} - -func (_OCR3Capability *OCR3CapabilitySession) TransferOwnership(to common.Address) (*types.Transaction, error) { - return _OCR3Capability.Contract.TransferOwnership(&_OCR3Capability.TransactOpts, to) -} - -func (_OCR3Capability *OCR3CapabilityTransactorSession) TransferOwnership(to common.Address) (*types.Transaction, error) { - return _OCR3Capability.Contract.TransferOwnership(&_OCR3Capability.TransactOpts, to) -} - -type OCR3CapabilityConfigSetIterator struct { - Event *OCR3CapabilityConfigSet - - contract *bind.BoundContract - event string - - logs chan types.Log - sub ethereum.Subscription - done bool - fail error -} - -func (it *OCR3CapabilityConfigSetIterator) Next() bool { - - if it.fail != nil { - return false - } - - if it.done { - select { - case log := <-it.logs: - it.Event = new(OCR3CapabilityConfigSet) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - default: - return false - } - } - - select { - case log := <-it.logs: - it.Event = new(OCR3CapabilityConfigSet) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - case err := <-it.sub.Err(): - it.done = true - it.fail = err - return it.Next() - } -} - -func (it *OCR3CapabilityConfigSetIterator) Error() error { - return it.fail -} - -func (it *OCR3CapabilityConfigSetIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -type OCR3CapabilityConfigSet struct { - PreviousConfigBlockNumber uint32 - ConfigDigest [32]byte - ConfigCount uint64 - Signers [][]byte - Transmitters []common.Address - F uint8 - OnchainConfig []byte - OffchainConfigVersion uint64 - OffchainConfig []byte - Raw types.Log -} - -func (_OCR3Capability *OCR3CapabilityFilterer) FilterConfigSet(opts *bind.FilterOpts) (*OCR3CapabilityConfigSetIterator, error) { - - logs, sub, err := _OCR3Capability.contract.FilterLogs(opts, "ConfigSet") - if err != nil { - return nil, err - } - return &OCR3CapabilityConfigSetIterator{contract: _OCR3Capability.contract, event: "ConfigSet", logs: logs, sub: sub}, nil -} - -func (_OCR3Capability *OCR3CapabilityFilterer) WatchConfigSet(opts *bind.WatchOpts, sink chan<- *OCR3CapabilityConfigSet) (event.Subscription, error) { - - logs, sub, err := _OCR3Capability.contract.WatchLogs(opts, "ConfigSet") - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - - event := new(OCR3CapabilityConfigSet) - if err := _OCR3Capability.contract.UnpackLog(event, "ConfigSet", log); err != nil { - return err - } - event.Raw = log - - select { - case sink <- event: - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - } - }), nil -} - -func (_OCR3Capability *OCR3CapabilityFilterer) ParseConfigSet(log types.Log) (*OCR3CapabilityConfigSet, error) { - event := new(OCR3CapabilityConfigSet) - if err := _OCR3Capability.contract.UnpackLog(event, "ConfigSet", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -type OCR3CapabilityOwnershipTransferRequestedIterator struct { - Event *OCR3CapabilityOwnershipTransferRequested - - contract *bind.BoundContract - event string - - logs chan types.Log - sub ethereum.Subscription - done bool - fail error -} - -func (it *OCR3CapabilityOwnershipTransferRequestedIterator) Next() bool { - - if it.fail != nil { - return false - } - - if it.done { - select { - case log := <-it.logs: - it.Event = new(OCR3CapabilityOwnershipTransferRequested) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - default: - return false - } - } - - select { - case log := <-it.logs: - it.Event = new(OCR3CapabilityOwnershipTransferRequested) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - case err := <-it.sub.Err(): - it.done = true - it.fail = err - return it.Next() - } -} - -func (it *OCR3CapabilityOwnershipTransferRequestedIterator) Error() error { - return it.fail -} - -func (it *OCR3CapabilityOwnershipTransferRequestedIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -type OCR3CapabilityOwnershipTransferRequested struct { - From common.Address - To common.Address - Raw types.Log -} - -func (_OCR3Capability *OCR3CapabilityFilterer) FilterOwnershipTransferRequested(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*OCR3CapabilityOwnershipTransferRequestedIterator, error) { - - var fromRule []interface{} - for _, fromItem := range from { - fromRule = append(fromRule, fromItem) - } - var toRule []interface{} - for _, toItem := range to { - toRule = append(toRule, toItem) - } - - logs, sub, err := _OCR3Capability.contract.FilterLogs(opts, "OwnershipTransferRequested", fromRule, toRule) - if err != nil { - return nil, err - } - return &OCR3CapabilityOwnershipTransferRequestedIterator{contract: _OCR3Capability.contract, event: "OwnershipTransferRequested", logs: logs, sub: sub}, nil -} - -func (_OCR3Capability *OCR3CapabilityFilterer) WatchOwnershipTransferRequested(opts *bind.WatchOpts, sink chan<- *OCR3CapabilityOwnershipTransferRequested, from []common.Address, to []common.Address) (event.Subscription, error) { - - var fromRule []interface{} - for _, fromItem := range from { - fromRule = append(fromRule, fromItem) - } - var toRule []interface{} - for _, toItem := range to { - toRule = append(toRule, toItem) - } - - logs, sub, err := _OCR3Capability.contract.WatchLogs(opts, "OwnershipTransferRequested", fromRule, toRule) - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - - event := new(OCR3CapabilityOwnershipTransferRequested) - if err := _OCR3Capability.contract.UnpackLog(event, "OwnershipTransferRequested", log); err != nil { - return err - } - event.Raw = log - - select { - case sink <- event: - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - } - }), nil -} - -func (_OCR3Capability *OCR3CapabilityFilterer) ParseOwnershipTransferRequested(log types.Log) (*OCR3CapabilityOwnershipTransferRequested, error) { - event := new(OCR3CapabilityOwnershipTransferRequested) - if err := _OCR3Capability.contract.UnpackLog(event, "OwnershipTransferRequested", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -type OCR3CapabilityOwnershipTransferredIterator struct { - Event *OCR3CapabilityOwnershipTransferred - - contract *bind.BoundContract - event string - - logs chan types.Log - sub ethereum.Subscription - done bool - fail error -} - -func (it *OCR3CapabilityOwnershipTransferredIterator) Next() bool { - - if it.fail != nil { - return false - } - - if it.done { - select { - case log := <-it.logs: - it.Event = new(OCR3CapabilityOwnershipTransferred) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - default: - return false - } - } - - select { - case log := <-it.logs: - it.Event = new(OCR3CapabilityOwnershipTransferred) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - case err := <-it.sub.Err(): - it.done = true - it.fail = err - return it.Next() - } -} - -func (it *OCR3CapabilityOwnershipTransferredIterator) Error() error { - return it.fail -} - -func (it *OCR3CapabilityOwnershipTransferredIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -type OCR3CapabilityOwnershipTransferred struct { - From common.Address - To common.Address - Raw types.Log -} - -func (_OCR3Capability *OCR3CapabilityFilterer) FilterOwnershipTransferred(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*OCR3CapabilityOwnershipTransferredIterator, error) { - - var fromRule []interface{} - for _, fromItem := range from { - fromRule = append(fromRule, fromItem) - } - var toRule []interface{} - for _, toItem := range to { - toRule = append(toRule, toItem) - } - - logs, sub, err := _OCR3Capability.contract.FilterLogs(opts, "OwnershipTransferred", fromRule, toRule) - if err != nil { - return nil, err - } - return &OCR3CapabilityOwnershipTransferredIterator{contract: _OCR3Capability.contract, event: "OwnershipTransferred", logs: logs, sub: sub}, nil -} - -func (_OCR3Capability *OCR3CapabilityFilterer) WatchOwnershipTransferred(opts *bind.WatchOpts, sink chan<- *OCR3CapabilityOwnershipTransferred, from []common.Address, to []common.Address) (event.Subscription, error) { - - var fromRule []interface{} - for _, fromItem := range from { - fromRule = append(fromRule, fromItem) - } - var toRule []interface{} - for _, toItem := range to { - toRule = append(toRule, toItem) - } - - logs, sub, err := _OCR3Capability.contract.WatchLogs(opts, "OwnershipTransferred", fromRule, toRule) - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - - event := new(OCR3CapabilityOwnershipTransferred) - if err := _OCR3Capability.contract.UnpackLog(event, "OwnershipTransferred", log); err != nil { - return err - } - event.Raw = log - - select { - case sink <- event: - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - } - }), nil -} - -func (_OCR3Capability *OCR3CapabilityFilterer) ParseOwnershipTransferred(log types.Log) (*OCR3CapabilityOwnershipTransferred, error) { - event := new(OCR3CapabilityOwnershipTransferred) - if err := _OCR3Capability.contract.UnpackLog(event, "OwnershipTransferred", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -type OCR3CapabilityTransmittedIterator struct { - Event *OCR3CapabilityTransmitted - - contract *bind.BoundContract - event string - - logs chan types.Log - sub ethereum.Subscription - done bool - fail error -} - -func (it *OCR3CapabilityTransmittedIterator) Next() bool { - - if it.fail != nil { - return false - } - - if it.done { - select { - case log := <-it.logs: - it.Event = new(OCR3CapabilityTransmitted) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - default: - return false - } - } - - select { - case log := <-it.logs: - it.Event = new(OCR3CapabilityTransmitted) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - case err := <-it.sub.Err(): - it.done = true - it.fail = err - return it.Next() - } -} - -func (it *OCR3CapabilityTransmittedIterator) Error() error { - return it.fail -} - -func (it *OCR3CapabilityTransmittedIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -type OCR3CapabilityTransmitted struct { - ConfigDigest [32]byte - Epoch uint32 - Raw types.Log -} - -func (_OCR3Capability *OCR3CapabilityFilterer) FilterTransmitted(opts *bind.FilterOpts) (*OCR3CapabilityTransmittedIterator, error) { - - logs, sub, err := _OCR3Capability.contract.FilterLogs(opts, "Transmitted") - if err != nil { - return nil, err - } - return &OCR3CapabilityTransmittedIterator{contract: _OCR3Capability.contract, event: "Transmitted", logs: logs, sub: sub}, nil -} - -func (_OCR3Capability *OCR3CapabilityFilterer) WatchTransmitted(opts *bind.WatchOpts, sink chan<- *OCR3CapabilityTransmitted) (event.Subscription, error) { - - logs, sub, err := _OCR3Capability.contract.WatchLogs(opts, "Transmitted") - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - - event := new(OCR3CapabilityTransmitted) - if err := _OCR3Capability.contract.UnpackLog(event, "Transmitted", log); err != nil { - return err - } - event.Raw = log - - select { - case sink <- event: - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - } - }), nil -} - -func (_OCR3Capability *OCR3CapabilityFilterer) ParseTransmitted(log types.Log) (*OCR3CapabilityTransmitted, error) { - event := new(OCR3CapabilityTransmitted) - if err := _OCR3Capability.contract.UnpackLog(event, "Transmitted", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -type LatestConfigDetails struct { - ConfigCount uint32 - BlockNumber uint32 - ConfigDigest [32]byte -} -type LatestConfigDigestAndEpoch struct { - ScanLogs bool - ConfigDigest [32]byte - Epoch uint32 -} - -func (_OCR3Capability *OCR3Capability) ParseLog(log types.Log) (generated.AbigenLog, error) { - switch log.Topics[0] { - case _OCR3Capability.abi.Events["ConfigSet"].ID: - return _OCR3Capability.ParseConfigSet(log) - case _OCR3Capability.abi.Events["OwnershipTransferRequested"].ID: - return _OCR3Capability.ParseOwnershipTransferRequested(log) - case _OCR3Capability.abi.Events["OwnershipTransferred"].ID: - return _OCR3Capability.ParseOwnershipTransferred(log) - case _OCR3Capability.abi.Events["Transmitted"].ID: - return _OCR3Capability.ParseTransmitted(log) - - default: - return nil, fmt.Errorf("abigen wrapper received unknown log topic: %v", log.Topics[0]) - } -} - -func (OCR3CapabilityConfigSet) Topic() common.Hash { - return common.HexToHash("0x36257c6e8d535293ad661e377c0baac536289be6707b8a488ac175ddaa4055c8") -} - -func (OCR3CapabilityOwnershipTransferRequested) Topic() common.Hash { - return common.HexToHash("0xed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae1278") -} - -func (OCR3CapabilityOwnershipTransferred) Topic() common.Hash { - return common.HexToHash("0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0") -} - -func (OCR3CapabilityTransmitted) Topic() common.Hash { - return common.HexToHash("0xb04e63db38c49950639fa09d29872f21f5d49d614f3a969d8adf3d4b52e41a62") -} - -func (_OCR3Capability *OCR3Capability) Address() common.Address { - return _OCR3Capability.address -} - -type OCR3CapabilityInterface interface { - LatestConfigDetails(opts *bind.CallOpts) (LatestConfigDetails, - - error) - - LatestConfigDigestAndEpoch(opts *bind.CallOpts) (LatestConfigDigestAndEpoch, - - error) - - Owner(opts *bind.CallOpts) (common.Address, error) - - Transmit(opts *bind.CallOpts, arg0 [3][32]byte, arg1 []byte, arg2 [][32]byte, arg3 [][32]byte, arg4 [32]byte) error - - TypeAndVersion(opts *bind.CallOpts) (string, error) - - AcceptOwnership(opts *bind.TransactOpts) (*types.Transaction, error) - - SetConfig(opts *bind.TransactOpts, _signers [][]byte, _transmitters []common.Address, _f uint8, _onchainConfig []byte, _offchainConfigVersion uint64, _offchainConfig []byte) (*types.Transaction, error) - - TransferOwnership(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) - - FilterConfigSet(opts *bind.FilterOpts) (*OCR3CapabilityConfigSetIterator, error) - - WatchConfigSet(opts *bind.WatchOpts, sink chan<- *OCR3CapabilityConfigSet) (event.Subscription, error) - - ParseConfigSet(log types.Log) (*OCR3CapabilityConfigSet, error) - - FilterOwnershipTransferRequested(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*OCR3CapabilityOwnershipTransferRequestedIterator, error) - - WatchOwnershipTransferRequested(opts *bind.WatchOpts, sink chan<- *OCR3CapabilityOwnershipTransferRequested, from []common.Address, to []common.Address) (event.Subscription, error) - - ParseOwnershipTransferRequested(log types.Log) (*OCR3CapabilityOwnershipTransferRequested, error) - - FilterOwnershipTransferred(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*OCR3CapabilityOwnershipTransferredIterator, error) - - WatchOwnershipTransferred(opts *bind.WatchOpts, sink chan<- *OCR3CapabilityOwnershipTransferred, from []common.Address, to []common.Address) (event.Subscription, error) - - ParseOwnershipTransferred(log types.Log) (*OCR3CapabilityOwnershipTransferred, error) - - FilterTransmitted(opts *bind.FilterOpts) (*OCR3CapabilityTransmittedIterator, error) - - WatchTransmitted(opts *bind.WatchOpts, sink chan<- *OCR3CapabilityTransmitted) (event.Subscription, error) - - ParseTransmitted(log types.Log) (*OCR3CapabilityTransmitted, error) - - ParseLog(log types.Log) (generated.AbigenLog, error) - - Address() common.Address -} diff --git a/core/gethwrappers/llo-feeds/generated/configurator/configurator.go b/core/gethwrappers/llo-feeds/generated/configurator/configurator.go index a2dd90b571b..d9a1581938f 100644 --- a/core/gethwrappers/llo-feeds/generated/configurator/configurator.go +++ b/core/gethwrappers/llo-feeds/generated/configurator/configurator.go @@ -32,7 +32,7 @@ var ( var ConfiguratorMetaData = &bind.MetaData{ ABI: "[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"configId\",\"type\":\"bytes32\"}],\"name\":\"ConfigUnset\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"configId\",\"type\":\"bytes32\"},{\"internalType\":\"bool\",\"name\":\"isGreenProduction\",\"type\":\"bool\"}],\"name\":\"ConfigUnsetProduction\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"configId\",\"type\":\"bytes32\"},{\"internalType\":\"bool\",\"name\":\"isGreenProduction\",\"type\":\"bool\"}],\"name\":\"ConfigUnsetStaging\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"numSigners\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxSigners\",\"type\":\"uint256\"}],\"name\":\"ExcessSigners\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FaultToleranceMustBePositive\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"numSigners\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"minSigners\",\"type\":\"uint256\"}],\"name\":\"InsufficientSigners\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"onchainConfigLength\",\"type\":\"uint256\"}],\"name\":\"InvalidOnchainLength\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"predecessorConfigDigest\",\"type\":\"bytes32\"}],\"name\":\"InvalidPredecessorConfigDigest\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"configId\",\"type\":\"bytes32\"},{\"internalType\":\"bool\",\"name\":\"isGreenProductionContractState\",\"type\":\"bool\"}],\"name\":\"IsGreenProductionMustMatchContractState\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"predecessorConfigDigest\",\"type\":\"bytes32\"}],\"name\":\"NonZeroPredecessorConfigDigest\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"version\",\"type\":\"uint256\"}],\"name\":\"UnsupportedOnchainConfigVersion\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"configId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"previousConfigBlockNumber\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"configCount\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes[]\",\"name\":\"signers\",\"type\":\"bytes[]\"},{\"indexed\":false,\"internalType\":\"bytes32[]\",\"name\":\"offchainTransmitters\",\"type\":\"bytes32[]\"},{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"f\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"onchainConfig\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"offchainConfigVersion\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"isGreenProduction\",\"type\":\"bool\"}],\"name\":\"ProductionConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"configId\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"retiredConfigDigest\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"isGreenProduction\",\"type\":\"bool\"}],\"name\":\"PromoteStagingConfig\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"configId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"previousConfigBlockNumber\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"configCount\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes[]\",\"name\":\"signers\",\"type\":\"bytes[]\"},{\"indexed\":false,\"internalType\":\"bytes32[]\",\"name\":\"offchainTransmitters\",\"type\":\"bytes32[]\"},{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"f\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"onchainConfig\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"offchainConfigVersion\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"isGreenProduction\",\"type\":\"bool\"}],\"name\":\"StagingConfigSet\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"configId\",\"type\":\"bytes32\"},{\"internalType\":\"bool\",\"name\":\"isGreenProduction\",\"type\":\"bool\"}],\"name\":\"promoteStagingConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"configId\",\"type\":\"bytes32\"},{\"internalType\":\"bytes[]\",\"name\":\"signers\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes32[]\",\"name\":\"offchainTransmitters\",\"type\":\"bytes32[]\"},{\"internalType\":\"uint8\",\"name\":\"f\",\"type\":\"uint8\"},{\"internalType\":\"bytes\",\"name\":\"onchainConfig\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"offchainConfigVersion\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"}],\"name\":\"setProductionConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"configId\",\"type\":\"bytes32\"},{\"internalType\":\"bytes[]\",\"name\":\"signers\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes32[]\",\"name\":\"offchainTransmitters\",\"type\":\"bytes32[]\"},{\"internalType\":\"uint8\",\"name\":\"f\",\"type\":\"uint8\"},{\"internalType\":\"bytes\",\"name\":\"onchainConfig\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"offchainConfigVersion\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"}],\"name\":\"setStagingConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"isVerifier\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"pure\",\"type\":\"function\"}]", - Bin: "0x608060405234801561001057600080fd5b5033806000816100675760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615610097576100978161009f565b505050610148565b336001600160a01b038216036100f75760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640161005e565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b611459806101576000396000f3fe608060405234801561001057600080fd5b50600436106100885760003560e01c80638da5cb5b1161005b5780638da5cb5b14610153578063dfb533d01461017b578063e6e7c5a41461018e578063f2fde38b146101a157600080fd5b806301ffc9a71461008d578063181f5a77146100f7578063790464e01461013657806379ba50971461014b575b600080fd5b6100e261009b366004610d71565b7fffffffff00000000000000000000000000000000000000000000000000000000167f40569294000000000000000000000000000000000000000000000000000000001490565b60405190151581526020015b60405180910390f35b604080518082018252601281527f436f6e666967757261746f7220302e352e300000000000000000000000000000602082015290516100ee9190610e1e565b61014961014436600461107a565b6101b4565b005b61014961038d565b60005460405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100ee565b61014961018936600461107a565b61048a565b61014961019c366004611152565b6106fb565b6101496101af366004611187565b610907565b85518460ff16806000036101f4576040517f0743bae600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b601f82111561023e576040517f61750f4000000000000000000000000000000000000000000000000000000000815260048101839052601f60248201526044015b60405180910390fd5b6102498160036111ec565b82116102a1578161025b8260036111ec565b610266906001611209565b6040517f9dd9e6d800000000000000000000000000000000000000000000000000000000815260048101929092526024820152604401610235565b6102a961091b565b6040855110156102ea5784516040517f3e936ca800000000000000000000000000000000000000000000000000000000815260040161023591815260200190565b602085015160408601516001821015610332576040517f8f01e0d700000000000000000000000000000000000000000000000000000000815260048101839052602401610235565b801561036d576040517fb96bb76000000000000000000000000000000000000000000000000000000000815260048101829052602401610235565b6103808b46308d8d8d8d8d8d600161099e565b5050505050505050505050565b60015473ffffffffffffffffffffffffffffffffffffffff16331461040e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e6572000000000000000000006044820152606401610235565b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b85518460ff16806000036104ca576040517f0743bae600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b601f82111561050f576040517f61750f4000000000000000000000000000000000000000000000000000000000815260048101839052601f6024820152604401610235565b61051a8160036111ec565b821161052c578161025b8260036111ec565b61053461091b565b6040855110156105755784516040517f3e936ca800000000000000000000000000000000000000000000000000000000815260040161023591815260200190565b6020850151604086015160018210156105bd576040517f8f01e0d700000000000000000000000000000000000000000000000000000000815260048101839052602401610235565b60008b81526002602081815260408084208151608081018352815467ffffffffffffffff8116825268010000000000000000810463ffffffff16948201949094526c0100000000000000000000000090930460ff161515838301528151808301928390529293909260608501929091600185019182845b8154815260200190600101908083116106345750505050508152505090506000801b8214806106a05750600260008d81526020019081526020016000206001018160400151610684576000610687565b60015b60ff166002811061069a5761069a61121c565b01548214155b156106da576040517f7d78c2a100000000000000000000000000000000000000000000000000000000815260048101839052602401610235565b6106ed8c46308e8e8e8e8e8e600061099e565b505050505050505050505050565b61070361091b565b600082815260026020526040902080546c01000000000000000000000000900460ff1615158215151461076c576040517f85fa3a370000000000000000000000000000000000000000000000000000000081526004810184905282156024820152604401610235565b805467ffffffffffffffff166000036107b4576040517f90e6f6dc00000000000000000000000000000000000000000000000000000000815260048101849052602401610235565b600060018201836107c65760016107c9565b60005b60ff16600281106107dc576107dc61121c565b015403610820576040517f5b7f6357000000000000000000000000000000000000000000000000000000008152600481018490528215156024820152604401610235565b60008160010183610832576000610835565b60015b60ff16600281106108485761084861121c565b015490508061088e576040517fcaf1e773000000000000000000000000000000000000000000000000000000008152600481018590528315156024820152604401610235565b81547fffffffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffff1683156c010000000000000000000000008102919091178355604051908152819085907f1062aa08ac6046a0e69e3eafdf12d1eba63a67b71a874623e86eb06348a1d84f9060200160405180910390a350505050565b61090f61091b565b61091881610bce565b50565b60005473ffffffffffffffffffffffffffffffffffffffff16331461099c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401610235565b565b60008a81526002602052604081208054909190829082906109c89067ffffffffffffffff1661124b565b91906101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905590506000610a038d8d8d858e8e8e8e8e8e610cc3565b90508315610acb578c7f261b20c2ecd99d86d6e936279e4f78db34603a3de3a4a84d6f3d4e0dd55e24788460000160089054906101000a900463ffffffff1683858e8e8e8e8e8e8d600001600c9054906101000a900460ff16604051610a729a999897969594939291906112ff565b60405180910390a260008d815260026020526040902083548291600101906c01000000000000000000000000900460ff16610aae576000610ab1565b60015b60ff1660028110610ac457610ac461121c565b0155610b87565b8c7fef1b5f9d1b927b0fe871b12c7e7846457602d67b2bc36b0bc95feaf480e890568460000160089054906101000a900463ffffffff1683858e8e8e8e8e8e8d600001600c9054906101000a900460ff16604051610b329a999897969594939291906112ff565b60405180910390a260008d815260026020526040902083548291600101906c01000000000000000000000000900460ff16610b6e576001610b71565b60005b60ff1660028110610b8457610b8461121c565b01555b505080547fffffffffffffffffffffffffffffffffffffffff00000000ffffffffffffffff16680100000000000000004363ffffffff160217905550505050505050505050565b3373ffffffffffffffffffffffffffffffffffffffff821603610c4d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401610235565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6000808b8b8b8b8b8b8b8b8b8b604051602001610ce99a9998979695949392919061139f565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815291905280516020909101207dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e09000000000000000000000000000000000000000000000000000000000000179150509a9950505050505050505050565b600060208284031215610d8357600080fd5b81357fffffffff0000000000000000000000000000000000000000000000000000000081168114610db357600080fd5b9392505050565b6000815180845260005b81811015610de057602081850181015186830182015201610dc4565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b602081526000610db36020830184610dba565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715610ea757610ea7610e31565b604052919050565b600067ffffffffffffffff821115610ec957610ec9610e31565b5060051b60200190565b600082601f830112610ee457600080fd5b813567ffffffffffffffff811115610efe57610efe610e31565b610f2f60207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601610e60565b818152846020838601011115610f4457600080fd5b816020850160208301376000918101602001919091529392505050565b600082601f830112610f7257600080fd5b81356020610f87610f8283610eaf565b610e60565b82815260059290921b84018101918181019086841115610fa657600080fd5b8286015b84811015610fe657803567ffffffffffffffff811115610fca5760008081fd5b610fd88986838b0101610ed3565b845250918301918301610faa565b509695505050505050565b600082601f83011261100257600080fd5b81356020611012610f8283610eaf565b82815260059290921b8401810191818101908684111561103157600080fd5b8286015b84811015610fe65780358352918301918301611035565b803560ff8116811461105d57600080fd5b919050565b803567ffffffffffffffff8116811461105d57600080fd5b600080600080600080600060e0888a03121561109557600080fd5b87359650602088013567ffffffffffffffff808211156110b457600080fd5b6110c08b838c01610f61565b975060408a01359150808211156110d657600080fd5b6110e28b838c01610ff1565b96506110f060608b0161104c565b955060808a013591508082111561110657600080fd5b6111128b838c01610ed3565b945061112060a08b01611062565b935060c08a013591508082111561113657600080fd5b506111438a828b01610ed3565b91505092959891949750929550565b6000806040838503121561116557600080fd5b823591506020830135801515811461117c57600080fd5b809150509250929050565b60006020828403121561119957600080fd5b813573ffffffffffffffffffffffffffffffffffffffff81168114610db357600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b8082028115828204841417611203576112036111bd565b92915050565b80820180821115611203576112036111bd565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600067ffffffffffffffff808316818103611268576112686111bd565b6001019392505050565b6000815180845260208085019450848260051b860182860160005b858110156112b75783830389526112a5838351610dba565b9885019892509084019060010161128d565b5090979650505050505050565b600081518084526020808501945080840160005b838110156112f4578151875295820195908201906001016112d8565b509495945050505050565b600061014063ffffffff8d1683528b602084015267ffffffffffffffff808c1660408501528160608501526113368285018c611272565b9150838203608085015261134a828b6112c4565b915060ff891660a085015283820360c08501526113678289610dba565b90871660e085015283810361010085015290506113848186610dba565b9150508215156101208301529b9a5050505050505050505050565b60006101408c83528b602084015273ffffffffffffffffffffffffffffffffffffffff8b16604084015267ffffffffffffffff808b1660608501528160808501526113ec8285018b611272565b915083820360a0850152611400828a6112c4565b915060ff881660c085015283820360e085015261141d8288610dba565b908616610100850152838103610120850152905061143b8185610dba565b9d9c5050505050505050505050505056fea164736f6c6343000813000a", + Bin: "0x608060405234801561001057600080fd5b5033806000816100675760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615610097576100978161009f565b505050610148565b336001600160a01b038216036100f75760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640161005e565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b61144a806101576000396000f3fe608060405234801561001057600080fd5b50600436106100885760003560e01c80638da5cb5b1161005b5780638da5cb5b14610153578063dfb533d01461017b578063e6e7c5a41461018e578063f2fde38b146101a157600080fd5b806301ffc9a71461008d578063181f5a77146100f7578063790464e01461013657806379ba50971461014b575b600080fd5b6100e261009b366004610d62565b7fffffffff00000000000000000000000000000000000000000000000000000000167f40569294000000000000000000000000000000000000000000000000000000001490565b60405190151581526020015b60405180910390f35b604080518082018252601281527f436f6e666967757261746f7220302e352e300000000000000000000000000000602082015290516100ee9190610e0f565b61014961014436600461106b565b6101b4565b005b61014961038d565b60005460405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100ee565b61014961018936600461106b565b61048a565b61014961019c366004611143565b6106ec565b6101496101af366004611178565b6108f8565b85518460ff16806000036101f4576040517f0743bae600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b601f82111561023e576040517f61750f4000000000000000000000000000000000000000000000000000000000815260048101839052601f60248201526044015b60405180910390fd5b6102498160036111dd565b82116102a1578161025b8260036111dd565b6102669060016111fa565b6040517f9dd9e6d800000000000000000000000000000000000000000000000000000000815260048101929092526024820152604401610235565b6102a961090c565b6040855110156102ea5784516040517f3e936ca800000000000000000000000000000000000000000000000000000000815260040161023591815260200190565b602085015160408601516001821015610332576040517f8f01e0d700000000000000000000000000000000000000000000000000000000815260048101839052602401610235565b801561036d576040517fb96bb76000000000000000000000000000000000000000000000000000000000815260048101829052602401610235565b6103808b46308d8d8d8d8d8d600161098f565b5050505050505050505050565b60015473ffffffffffffffffffffffffffffffffffffffff16331461040e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e6572000000000000000000006044820152606401610235565b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b85518460ff16806000036104ca576040517f0743bae600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b601f82111561050f576040517f61750f4000000000000000000000000000000000000000000000000000000000815260048101839052601f6024820152604401610235565b61051a8160036111dd565b821161052c578161025b8260036111dd565b61053461090c565b6040855110156105755784516040517f3e936ca800000000000000000000000000000000000000000000000000000000815260040161023591815260200190565b6020850151604086015160018210156105bd576040517f8f01e0d700000000000000000000000000000000000000000000000000000000815260048101839052602401610235565b60008b81526002602081815260408084208151608081018352815467ffffffffffffffff8116825268010000000000000000810463ffffffff16948201949094526c0100000000000000000000000090930460ff161515838301528151808301928390529293909260608501929091600185019182845b815481526020019060010190808311610634575050505050815250509050600260008d8152602001908152602001600020600101816040015161067857600061067b565b60015b60ff166002811061068e5761068e61120d565b015482146106cb576040517f7d78c2a100000000000000000000000000000000000000000000000000000000815260048101839052602401610235565b6106de8c46308e8e8e8e8e8e600061098f565b505050505050505050505050565b6106f461090c565b600082815260026020526040902080546c01000000000000000000000000900460ff1615158215151461075d576040517f85fa3a370000000000000000000000000000000000000000000000000000000081526004810184905282156024820152604401610235565b805467ffffffffffffffff166000036107a5576040517f90e6f6dc00000000000000000000000000000000000000000000000000000000815260048101849052602401610235565b600060018201836107b75760016107ba565b60005b60ff16600281106107cd576107cd61120d565b015403610811576040517f5b7f6357000000000000000000000000000000000000000000000000000000008152600481018490528215156024820152604401610235565b60008160010183610823576000610826565b60015b60ff16600281106108395761083961120d565b015490508061087f576040517fcaf1e773000000000000000000000000000000000000000000000000000000008152600481018590528315156024820152604401610235565b81547fffffffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffff1683156c010000000000000000000000008102919091178355604051908152819085907f1062aa08ac6046a0e69e3eafdf12d1eba63a67b71a874623e86eb06348a1d84f9060200160405180910390a350505050565b61090061090c565b61090981610bbf565b50565b60005473ffffffffffffffffffffffffffffffffffffffff16331461098d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401610235565b565b60008a81526002602052604081208054909190829082906109b99067ffffffffffffffff1661123c565b91906101000a81548167ffffffffffffffff021916908367ffffffffffffffff1602179055905060006109f48d8d8d858e8e8e8e8e8e610cb4565b90508315610abc578c7f261b20c2ecd99d86d6e936279e4f78db34603a3de3a4a84d6f3d4e0dd55e24788460000160089054906101000a900463ffffffff1683858e8e8e8e8e8e8d600001600c9054906101000a900460ff16604051610a639a999897969594939291906112f0565b60405180910390a260008d815260026020526040902083548291600101906c01000000000000000000000000900460ff16610a9f576000610aa2565b60015b60ff1660028110610ab557610ab561120d565b0155610b78565b8c7fef1b5f9d1b927b0fe871b12c7e7846457602d67b2bc36b0bc95feaf480e890568460000160089054906101000a900463ffffffff1683858e8e8e8e8e8e8d600001600c9054906101000a900460ff16604051610b239a999897969594939291906112f0565b60405180910390a260008d815260026020526040902083548291600101906c01000000000000000000000000900460ff16610b5f576001610b62565b60005b60ff1660028110610b7557610b7561120d565b01555b505080547fffffffffffffffffffffffffffffffffffffffff00000000ffffffffffffffff16680100000000000000004363ffffffff160217905550505050505050505050565b3373ffffffffffffffffffffffffffffffffffffffff821603610c3e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401610235565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6000808b8b8b8b8b8b8b8b8b8b604051602001610cda9a99989796959493929190611390565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815291905280516020909101207dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e09000000000000000000000000000000000000000000000000000000000000179150509a9950505050505050505050565b600060208284031215610d7457600080fd5b81357fffffffff0000000000000000000000000000000000000000000000000000000081168114610da457600080fd5b9392505050565b6000815180845260005b81811015610dd157602081850181015186830182015201610db5565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b602081526000610da46020830184610dab565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715610e9857610e98610e22565b604052919050565b600067ffffffffffffffff821115610eba57610eba610e22565b5060051b60200190565b600082601f830112610ed557600080fd5b813567ffffffffffffffff811115610eef57610eef610e22565b610f2060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601610e51565b818152846020838601011115610f3557600080fd5b816020850160208301376000918101602001919091529392505050565b600082601f830112610f6357600080fd5b81356020610f78610f7383610ea0565b610e51565b82815260059290921b84018101918181019086841115610f9757600080fd5b8286015b84811015610fd757803567ffffffffffffffff811115610fbb5760008081fd5b610fc98986838b0101610ec4565b845250918301918301610f9b565b509695505050505050565b600082601f830112610ff357600080fd5b81356020611003610f7383610ea0565b82815260059290921b8401810191818101908684111561102257600080fd5b8286015b84811015610fd75780358352918301918301611026565b803560ff8116811461104e57600080fd5b919050565b803567ffffffffffffffff8116811461104e57600080fd5b600080600080600080600060e0888a03121561108657600080fd5b87359650602088013567ffffffffffffffff808211156110a557600080fd5b6110b18b838c01610f52565b975060408a01359150808211156110c757600080fd5b6110d38b838c01610fe2565b96506110e160608b0161103d565b955060808a01359150808211156110f757600080fd5b6111038b838c01610ec4565b945061111160a08b01611053565b935060c08a013591508082111561112757600080fd5b506111348a828b01610ec4565b91505092959891949750929550565b6000806040838503121561115657600080fd5b823591506020830135801515811461116d57600080fd5b809150509250929050565b60006020828403121561118a57600080fd5b813573ffffffffffffffffffffffffffffffffffffffff81168114610da457600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b80820281158282048414176111f4576111f46111ae565b92915050565b808201808211156111f4576111f46111ae565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600067ffffffffffffffff808316818103611259576112596111ae565b6001019392505050565b6000815180845260208085019450848260051b860182860160005b858110156112a8578383038952611296838351610dab565b9885019892509084019060010161127e565b5090979650505050505050565b600081518084526020808501945080840160005b838110156112e5578151875295820195908201906001016112c9565b509495945050505050565b600061014063ffffffff8d1683528b602084015267ffffffffffffffff808c1660408501528160608501526113278285018c611263565b9150838203608085015261133b828b6112b5565b915060ff891660a085015283820360c08501526113588289610dab565b90871660e085015283810361010085015290506113758186610dab565b9150508215156101208301529b9a5050505050505050505050565b60006101408c83528b602084015273ffffffffffffffffffffffffffffffffffffffff8b16604084015267ffffffffffffffff808b1660608501528160808501526113dd8285018b611263565b915083820360a08501526113f1828a6112b5565b915060ff881660c085015283820360e085015261140e8288610dab565b908616610100850152838103610120850152905061142c8185610dab565b9d9c5050505050505050505050505056fea164736f6c6343000813000a", } var ConfiguratorABI = ConfiguratorMetaData.ABI diff --git a/core/gethwrappers/llo-feeds/generated/exposed_configurator/exposed_configurator.go b/core/gethwrappers/llo-feeds/generated/exposed_configurator/exposed_configurator.go index 3b99de7d7ea..756a9fa8432 100644 --- a/core/gethwrappers/llo-feeds/generated/exposed_configurator/exposed_configurator.go +++ b/core/gethwrappers/llo-feeds/generated/exposed_configurator/exposed_configurator.go @@ -39,7 +39,7 @@ type ConfiguratorConfigurationState struct { var ExposedConfiguratorMetaData = &bind.MetaData{ ABI: "[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"configId\",\"type\":\"bytes32\"}],\"name\":\"ConfigUnset\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"configId\",\"type\":\"bytes32\"},{\"internalType\":\"bool\",\"name\":\"isGreenProduction\",\"type\":\"bool\"}],\"name\":\"ConfigUnsetProduction\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"configId\",\"type\":\"bytes32\"},{\"internalType\":\"bool\",\"name\":\"isGreenProduction\",\"type\":\"bool\"}],\"name\":\"ConfigUnsetStaging\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"numSigners\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxSigners\",\"type\":\"uint256\"}],\"name\":\"ExcessSigners\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FaultToleranceMustBePositive\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"numSigners\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"minSigners\",\"type\":\"uint256\"}],\"name\":\"InsufficientSigners\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"onchainConfigLength\",\"type\":\"uint256\"}],\"name\":\"InvalidOnchainLength\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"predecessorConfigDigest\",\"type\":\"bytes32\"}],\"name\":\"InvalidPredecessorConfigDigest\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"configId\",\"type\":\"bytes32\"},{\"internalType\":\"bool\",\"name\":\"isGreenProductionContractState\",\"type\":\"bool\"}],\"name\":\"IsGreenProductionMustMatchContractState\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"predecessorConfigDigest\",\"type\":\"bytes32\"}],\"name\":\"NonZeroPredecessorConfigDigest\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"version\",\"type\":\"uint256\"}],\"name\":\"UnsupportedOnchainConfigVersion\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"configId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"previousConfigBlockNumber\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"configCount\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes[]\",\"name\":\"signers\",\"type\":\"bytes[]\"},{\"indexed\":false,\"internalType\":\"bytes32[]\",\"name\":\"offchainTransmitters\",\"type\":\"bytes32[]\"},{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"f\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"onchainConfig\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"offchainConfigVersion\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"isGreenProduction\",\"type\":\"bool\"}],\"name\":\"ProductionConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"configId\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"retiredConfigDigest\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"isGreenProduction\",\"type\":\"bool\"}],\"name\":\"PromoteStagingConfig\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"configId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"previousConfigBlockNumber\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"configCount\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes[]\",\"name\":\"signers\",\"type\":\"bytes[]\"},{\"indexed\":false,\"internalType\":\"bytes32[]\",\"name\":\"offchainTransmitters\",\"type\":\"bytes32[]\"},{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"f\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"onchainConfig\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"offchainConfigVersion\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"isGreenProduction\",\"type\":\"bool\"}],\"name\":\"StagingConfigSet\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"_configId\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"_chainId\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"_contractAddress\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"_configCount\",\"type\":\"uint64\"},{\"internalType\":\"bytes[]\",\"name\":\"_signers\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes32[]\",\"name\":\"_offchainTransmitters\",\"type\":\"bytes32[]\"},{\"internalType\":\"uint8\",\"name\":\"_f\",\"type\":\"uint8\"},{\"internalType\":\"bytes\",\"name\":\"_onchainConfig\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"_encodedConfigVersion\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"_encodedConfig\",\"type\":\"bytes\"}],\"name\":\"exposedConfigDigestFromConfigData\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"configId\",\"type\":\"bytes32\"}],\"name\":\"exposedReadConfigurationStates\",\"outputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"configCount\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"latestConfigBlockNumber\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isGreenProduction\",\"type\":\"bool\"},{\"internalType\":\"bytes32[2]\",\"name\":\"configDigest\",\"type\":\"bytes32[2]\"}],\"internalType\":\"structConfigurator.ConfigurationState\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"configId\",\"type\":\"bytes32\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"configCount\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"latestConfigBlockNumber\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isGreenProduction\",\"type\":\"bool\"},{\"internalType\":\"bytes32[2]\",\"name\":\"configDigest\",\"type\":\"bytes32[2]\"}],\"internalType\":\"structConfigurator.ConfigurationState\",\"name\":\"state\",\"type\":\"tuple\"}],\"name\":\"exposedSetConfigurationState\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"configId\",\"type\":\"bytes32\"},{\"internalType\":\"bool\",\"name\":\"isGreenProduction\",\"type\":\"bool\"}],\"name\":\"exposedSetIsGreenProduction\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"configId\",\"type\":\"bytes32\"},{\"internalType\":\"bool\",\"name\":\"isGreenProduction\",\"type\":\"bool\"}],\"name\":\"promoteStagingConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"configId\",\"type\":\"bytes32\"},{\"internalType\":\"bytes[]\",\"name\":\"signers\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes32[]\",\"name\":\"offchainTransmitters\",\"type\":\"bytes32[]\"},{\"internalType\":\"uint8\",\"name\":\"f\",\"type\":\"uint8\"},{\"internalType\":\"bytes\",\"name\":\"onchainConfig\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"offchainConfigVersion\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"}],\"name\":\"setProductionConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"configId\",\"type\":\"bytes32\"},{\"internalType\":\"bytes[]\",\"name\":\"signers\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes32[]\",\"name\":\"offchainTransmitters\",\"type\":\"bytes32[]\"},{\"internalType\":\"uint8\",\"name\":\"f\",\"type\":\"uint8\"},{\"internalType\":\"bytes\",\"name\":\"onchainConfig\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"offchainConfigVersion\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"}],\"name\":\"setStagingConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"isVerifier\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"pure\",\"type\":\"function\"}]", - Bin: "0x608060405234801561001057600080fd5b5033806000816100675760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615610097576100978161009f565b505050610148565b336001600160a01b038216036100f75760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640161005e565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b611acf80620001586000396000f3fe608060405234801561001057600080fd5b50600436106100d45760003560e01c806379ba509711610081578063dfb533d01161005b578063dfb533d014610278578063e6e7c5a41461028b578063f2fde38b1461029e57600080fd5b806379ba5097146102285780638da5cb5b1461023057806399a073401461025857600080fd5b8063639fec28116100b2578063639fec28146101a357806369a120eb146101b8578063790464e01461021557600080fd5b806301ffc9a7146100d9578063181f5a771461014357806360e72ec914610182575b600080fd5b61012e6100e73660046110cb565b7fffffffff00000000000000000000000000000000000000000000000000000000167f40569294000000000000000000000000000000000000000000000000000000001490565b60405190151581526020015b60405180910390f35b604080518082018252601281527f436f6e666967757261746f7220302e352e3000000000000000000000000000006020820152905161013a9190611178565b61019561019036600461148d565b6102b1565b60405190815260200161013a565b6101b66101b13660046115ae565b61030d565b005b6101b66101c6366004611693565b60009182526002602052604090912080549115156c01000000000000000000000000027fffffffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffff909216919091179055565b6101b66102233660046116bf565b6103cc565b6101b66105a5565b60005460405173ffffffffffffffffffffffffffffffffffffffff909116815260200161013a565b61026b610266366004611797565b6106a2565b60405161013a91906117b0565b6101b66102863660046116bf565b610745565b6101b6610299366004611693565b6109b6565b6101b66102ac366004611815565b610bc2565b60006102fd8c8c8c8c8c8c8c8c8c8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508e92508d9150610bd69050565b9c9b505050505050505050505050565b60008281526002602081815260409283902084518154928601519486015115156c01000000000000000000000000027fffffffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffff63ffffffff90961668010000000000000000027fffffffffffffffffffffffffffffffffffffffff00000000000000000000000090941667ffffffffffffffff90921691909117929092179390931617825560608301518392916103c591600184019161102c565b5050505050565b85518460ff168060000361040c576040517f0743bae600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b601f821115610456576040517f61750f4000000000000000000000000000000000000000000000000000000000815260048101839052601f60248201526044015b60405180910390fd5b61046181600361185f565b82116104b9578161047382600361185f565b61047e90600161187c565b6040517f9dd9e6d80000000000000000000000000000000000000000000000000000000081526004810192909252602482015260440161044d565b6104c1610c84565b6040855110156105025784516040517f3e936ca800000000000000000000000000000000000000000000000000000000815260040161044d91815260200190565b60208501516040860151600182101561054a576040517f8f01e0d70000000000000000000000000000000000000000000000000000000081526004810183905260240161044d565b8015610585576040517fb96bb7600000000000000000000000000000000000000000000000000000000081526004810182905260240161044d565b6105988b46308d8d8d8d8d8d6001610d07565b5050505050505050505050565b60015473ffffffffffffffffffffffffffffffffffffffff163314610626576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e657200000000000000000000604482015260640161044d565b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b6106aa61106a565b6000828152600260208181526040928390208351608081018552815467ffffffffffffffff8116825268010000000000000000810463ffffffff16938201939093526c0100000000000000000000000090920460ff161515828501528351808501948590529193909260608501929160018501919082845b815481526020019060010190808311610722575050505050815250509050919050565b85518460ff1680600003610785576040517f0743bae600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b601f8211156107ca576040517f61750f4000000000000000000000000000000000000000000000000000000000815260048101839052601f602482015260440161044d565b6107d581600361185f565b82116107e7578161047382600361185f565b6107ef610c84565b6040855110156108305784516040517f3e936ca800000000000000000000000000000000000000000000000000000000815260040161044d91815260200190565b602085015160408601516001821015610878576040517f8f01e0d70000000000000000000000000000000000000000000000000000000081526004810183905260240161044d565b60008b81526002602081815260408084208151608081018352815467ffffffffffffffff8116825268010000000000000000810463ffffffff16948201949094526c0100000000000000000000000090930460ff161515838301528151808301928390529293909260608501929091600185019182845b8154815260200190600101908083116108ef5750505050508152505090506000801b82148061095b5750600260008d8152602001908152602001600020600101816040015161093f576000610942565b60015b60ff16600281106109555761095561188f565b01548214155b15610995576040517f7d78c2a10000000000000000000000000000000000000000000000000000000081526004810183905260240161044d565b6109a88c46308e8e8e8e8e8e6000610d07565b505050505050505050505050565b6109be610c84565b600082815260026020526040902080546c01000000000000000000000000900460ff16151582151514610a27576040517f85fa3a37000000000000000000000000000000000000000000000000000000008152600481018490528215602482015260440161044d565b805467ffffffffffffffff16600003610a6f576040517f90e6f6dc0000000000000000000000000000000000000000000000000000000081526004810184905260240161044d565b60006001820183610a81576001610a84565b60005b60ff1660028110610a9757610a9761188f565b015403610adb576040517f5b7f635700000000000000000000000000000000000000000000000000000000815260048101849052821515602482015260440161044d565b60008160010183610aed576000610af0565b60015b60ff1660028110610b0357610b0361188f565b0154905080610b49576040517fcaf1e77300000000000000000000000000000000000000000000000000000000815260048101859052831515602482015260440161044d565b81547fffffffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffff1683156c010000000000000000000000008102919091178355604051908152819085907f1062aa08ac6046a0e69e3eafdf12d1eba63a67b71a874623e86eb06348a1d84f9060200160405180910390a350505050565b610bca610c84565b610bd381610f37565b50565b6000808b8b8b8b8b8b8b8b8b8b604051602001610bfc9a9998979695949392919061194e565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815291905280516020909101207dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e09000000000000000000000000000000000000000000000000000000000000179150509a9950505050505050505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314610d05576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e657200000000000000000000604482015260640161044d565b565b60008a8152600260205260408120805490919082908290610d319067ffffffffffffffff166119fb565b91906101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905590506000610d6c8d8d8d858e8e8e8e8e8e610bd6565b90508315610e34578c7f261b20c2ecd99d86d6e936279e4f78db34603a3de3a4a84d6f3d4e0dd55e24788460000160089054906101000a900463ffffffff1683858e8e8e8e8e8e8d600001600c9054906101000a900460ff16604051610ddb9a99989796959493929190611a22565b60405180910390a260008d815260026020526040902083548291600101906c01000000000000000000000000900460ff16610e17576000610e1a565b60015b60ff1660028110610e2d57610e2d61188f565b0155610ef0565b8c7fef1b5f9d1b927b0fe871b12c7e7846457602d67b2bc36b0bc95feaf480e890568460000160089054906101000a900463ffffffff1683858e8e8e8e8e8e8d600001600c9054906101000a900460ff16604051610e9b9a99989796959493929190611a22565b60405180910390a260008d815260026020526040902083548291600101906c01000000000000000000000000900460ff16610ed7576001610eda565b60005b60ff1660028110610eed57610eed61188f565b01555b505080547fffffffffffffffffffffffffffffffffffffffff00000000ffffffffffffffff16680100000000000000004363ffffffff160217905550505050505050505050565b3373ffffffffffffffffffffffffffffffffffffffff821603610fb6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640161044d565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b826002810192821561105a579160200282015b8281111561105a57825182559160200191906001019061103f565b50611066929150611098565b5090565b6040805160808101825260008082526020820181905291810191909152606081016110936110ad565b905290565b5b808211156110665760008155600101611099565b60405180604001604052806002906020820280368337509192915050565b6000602082840312156110dd57600080fd5b81357fffffffff000000000000000000000000000000000000000000000000000000008116811461110d57600080fd5b9392505050565b6000815180845260005b8181101561113a5760208185018101518683018201520161111e565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b60208152600061110d6020830184611114565b803573ffffffffffffffffffffffffffffffffffffffff811681146111af57600080fd5b919050565b803567ffffffffffffffff811681146111af57600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040516080810167ffffffffffffffff8111828210171561121e5761121e6111cc565b60405290565b6040805190810167ffffffffffffffff8111828210171561121e5761121e6111cc565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff8111828210171561128e5761128e6111cc565b604052919050565b600067ffffffffffffffff8211156112b0576112b06111cc565b5060051b60200190565b600082601f8301126112cb57600080fd5b813567ffffffffffffffff8111156112e5576112e56111cc565b61131660207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601611247565b81815284602083860101111561132b57600080fd5b816020850160208301376000918101602001919091529392505050565b600082601f83011261135957600080fd5b8135602061136e61136983611296565b611247565b82815260059290921b8401810191818101908684111561138d57600080fd5b8286015b848110156113cd57803567ffffffffffffffff8111156113b15760008081fd5b6113bf8986838b01016112ba565b845250918301918301611391565b509695505050505050565b600082601f8301126113e957600080fd5b813560206113f961136983611296565b82815260059290921b8401810191818101908684111561141857600080fd5b8286015b848110156113cd578035835291830191830161141c565b803560ff811681146111af57600080fd5b60008083601f84011261145657600080fd5b50813567ffffffffffffffff81111561146e57600080fd5b60208301915083602082850101111561148657600080fd5b9250929050565b60008060008060008060008060008060006101408c8e0312156114af57600080fd5b8b359a5060208c013599506114c660408d0161118b565b98506114d460608d016111b4565b975067ffffffffffffffff8060808e013511156114f057600080fd5b6115008e60808f01358f01611348565b97508060a08e0135111561151357600080fd5b6115238e60a08f01358f016113d8565b965061153160c08e01611433565b95508060e08e0135111561154457600080fd5b6115548e60e08f01358f01611444565b90955093506115666101008e016111b4565b9250806101208e0135111561157a57600080fd5b5061158c8d6101208e01358e016112ba565b90509295989b509295989b9093969950565b803580151581146111af57600080fd5b60008082840360c08112156115c257600080fd5b83359250602060a07fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0830112156115f857600080fd5b6116006111fb565b915061160d8186016111b4565b8252604085013563ffffffff8116811461162657600080fd5b828201526116366060860161159e565b604083015285609f86011261164a57600080fd5b611652611224565b8060c087018881111561166457600080fd5b608088015b818110156116805780358452928401928401611669565b5050606084015250929590945092505050565b600080604083850312156116a657600080fd5b823591506116b66020840161159e565b90509250929050565b600080600080600080600060e0888a0312156116da57600080fd5b87359650602088013567ffffffffffffffff808211156116f957600080fd5b6117058b838c01611348565b975060408a013591508082111561171b57600080fd5b6117278b838c016113d8565b965061173560608b01611433565b955060808a013591508082111561174b57600080fd5b6117578b838c016112ba565b945061176560a08b016111b4565b935060c08a013591508082111561177b57600080fd5b506117888a828b016112ba565b91505092959891949750929550565b6000602082840312156117a957600080fd5b5035919050565b600060a08201905067ffffffffffffffff8351168252602063ffffffff81850151168184015260408401511515604084015260608401516060840160005b600281101561180b578251825291830191908301906001016117ee565b5050505092915050565b60006020828403121561182757600080fd5b61110d8261118b565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b808202811582820484141761187657611876611830565b92915050565b8082018082111561187657611876611830565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600081518084526020808501808196508360051b8101915082860160005b858110156119065782840389526118f4848351611114565b988501989350908401906001016118dc565b5091979650505050505050565b600081518084526020808501945080840160005b8381101561194357815187529582019590820190600101611927565b509495945050505050565b60006101408c83528b602084015273ffffffffffffffffffffffffffffffffffffffff8b16604084015267ffffffffffffffff808b16606085015281608085015261199b8285018b6118be565b915083820360a08501526119af828a611913565b915060ff881660c085015283820360e08501526119cc8288611114565b90861661010085015283810361012085015290506119ea8185611114565b9d9c50505050505050505050505050565b600067ffffffffffffffff808316818103611a1857611a18611830565b6001019392505050565b600061014063ffffffff8d1683528b602084015267ffffffffffffffff808c166040850152816060850152611a598285018c6118be565b91508382036080850152611a6d828b611913565b915060ff891660a085015283820360c0850152611a8a8289611114565b90871660e08501528381036101008501529050611aa78186611114565b9150508215156101208301529b9a505050505050505050505056fea164736f6c6343000813000a", + Bin: "0x608060405234801561001057600080fd5b5033806000816100675760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615610097576100978161009f565b505050610148565b336001600160a01b038216036100f75760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640161005e565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b611ac080620001586000396000f3fe608060405234801561001057600080fd5b50600436106100d45760003560e01c806379ba509711610081578063dfb533d01161005b578063dfb533d014610278578063e6e7c5a41461028b578063f2fde38b1461029e57600080fd5b806379ba5097146102285780638da5cb5b1461023057806399a073401461025857600080fd5b8063639fec28116100b2578063639fec28146101a357806369a120eb146101b8578063790464e01461021557600080fd5b806301ffc9a7146100d9578063181f5a771461014357806360e72ec914610182575b600080fd5b61012e6100e73660046110bc565b7fffffffff00000000000000000000000000000000000000000000000000000000167f40569294000000000000000000000000000000000000000000000000000000001490565b60405190151581526020015b60405180910390f35b604080518082018252601281527f436f6e666967757261746f7220302e352e3000000000000000000000000000006020820152905161013a9190611169565b61019561019036600461147e565b6102b1565b60405190815260200161013a565b6101b66101b136600461159f565b61030d565b005b6101b66101c6366004611684565b60009182526002602052604090912080549115156c01000000000000000000000000027fffffffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffff909216919091179055565b6101b66102233660046116b0565b6103cc565b6101b66105a5565b60005460405173ffffffffffffffffffffffffffffffffffffffff909116815260200161013a565b61026b610266366004611788565b6106a2565b60405161013a91906117a1565b6101b66102863660046116b0565b610745565b6101b6610299366004611684565b6109a7565b6101b66102ac366004611806565b610bb3565b60006102fd8c8c8c8c8c8c8c8c8c8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508e92508d9150610bc79050565b9c9b505050505050505050505050565b60008281526002602081815260409283902084518154928601519486015115156c01000000000000000000000000027fffffffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffff63ffffffff90961668010000000000000000027fffffffffffffffffffffffffffffffffffffffff00000000000000000000000090941667ffffffffffffffff90921691909117929092179390931617825560608301518392916103c591600184019161101d565b5050505050565b85518460ff168060000361040c576040517f0743bae600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b601f821115610456576040517f61750f4000000000000000000000000000000000000000000000000000000000815260048101839052601f60248201526044015b60405180910390fd5b610461816003611850565b82116104b95781610473826003611850565b61047e90600161186d565b6040517f9dd9e6d80000000000000000000000000000000000000000000000000000000081526004810192909252602482015260440161044d565b6104c1610c75565b6040855110156105025784516040517f3e936ca800000000000000000000000000000000000000000000000000000000815260040161044d91815260200190565b60208501516040860151600182101561054a576040517f8f01e0d70000000000000000000000000000000000000000000000000000000081526004810183905260240161044d565b8015610585576040517fb96bb7600000000000000000000000000000000000000000000000000000000081526004810182905260240161044d565b6105988b46308d8d8d8d8d8d6001610cf8565b5050505050505050505050565b60015473ffffffffffffffffffffffffffffffffffffffff163314610626576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e657200000000000000000000604482015260640161044d565b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b6106aa61105b565b6000828152600260208181526040928390208351608081018552815467ffffffffffffffff8116825268010000000000000000810463ffffffff16938201939093526c0100000000000000000000000090920460ff161515828501528351808501948590529193909260608501929160018501919082845b815481526020019060010190808311610722575050505050815250509050919050565b85518460ff1680600003610785576040517f0743bae600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b601f8211156107ca576040517f61750f4000000000000000000000000000000000000000000000000000000000815260048101839052601f602482015260440161044d565b6107d5816003611850565b82116107e75781610473826003611850565b6107ef610c75565b6040855110156108305784516040517f3e936ca800000000000000000000000000000000000000000000000000000000815260040161044d91815260200190565b602085015160408601516001821015610878576040517f8f01e0d70000000000000000000000000000000000000000000000000000000081526004810183905260240161044d565b60008b81526002602081815260408084208151608081018352815467ffffffffffffffff8116825268010000000000000000810463ffffffff16948201949094526c0100000000000000000000000090930460ff161515838301528151808301928390529293909260608501929091600185019182845b8154815260200190600101908083116108ef575050505050815250509050600260008d81526020019081526020016000206001018160400151610933576000610936565b60015b60ff166002811061094957610949611880565b01548214610986576040517f7d78c2a10000000000000000000000000000000000000000000000000000000081526004810183905260240161044d565b6109998c46308e8e8e8e8e8e6000610cf8565b505050505050505050505050565b6109af610c75565b600082815260026020526040902080546c01000000000000000000000000900460ff16151582151514610a18576040517f85fa3a37000000000000000000000000000000000000000000000000000000008152600481018490528215602482015260440161044d565b805467ffffffffffffffff16600003610a60576040517f90e6f6dc0000000000000000000000000000000000000000000000000000000081526004810184905260240161044d565b60006001820183610a72576001610a75565b60005b60ff1660028110610a8857610a88611880565b015403610acc576040517f5b7f635700000000000000000000000000000000000000000000000000000000815260048101849052821515602482015260440161044d565b60008160010183610ade576000610ae1565b60015b60ff1660028110610af457610af4611880565b0154905080610b3a576040517fcaf1e77300000000000000000000000000000000000000000000000000000000815260048101859052831515602482015260440161044d565b81547fffffffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffff1683156c010000000000000000000000008102919091178355604051908152819085907f1062aa08ac6046a0e69e3eafdf12d1eba63a67b71a874623e86eb06348a1d84f9060200160405180910390a350505050565b610bbb610c75565b610bc481610f28565b50565b6000808b8b8b8b8b8b8b8b8b8b604051602001610bed9a9998979695949392919061193f565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815291905280516020909101207dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e09000000000000000000000000000000000000000000000000000000000000179150509a9950505050505050505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314610cf6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e657200000000000000000000604482015260640161044d565b565b60008a8152600260205260408120805490919082908290610d229067ffffffffffffffff166119ec565b91906101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905590506000610d5d8d8d8d858e8e8e8e8e8e610bc7565b90508315610e25578c7f261b20c2ecd99d86d6e936279e4f78db34603a3de3a4a84d6f3d4e0dd55e24788460000160089054906101000a900463ffffffff1683858e8e8e8e8e8e8d600001600c9054906101000a900460ff16604051610dcc9a99989796959493929190611a13565b60405180910390a260008d815260026020526040902083548291600101906c01000000000000000000000000900460ff16610e08576000610e0b565b60015b60ff1660028110610e1e57610e1e611880565b0155610ee1565b8c7fef1b5f9d1b927b0fe871b12c7e7846457602d67b2bc36b0bc95feaf480e890568460000160089054906101000a900463ffffffff1683858e8e8e8e8e8e8d600001600c9054906101000a900460ff16604051610e8c9a99989796959493929190611a13565b60405180910390a260008d815260026020526040902083548291600101906c01000000000000000000000000900460ff16610ec8576001610ecb565b60005b60ff1660028110610ede57610ede611880565b01555b505080547fffffffffffffffffffffffffffffffffffffffff00000000ffffffffffffffff16680100000000000000004363ffffffff160217905550505050505050505050565b3373ffffffffffffffffffffffffffffffffffffffff821603610fa7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640161044d565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b826002810192821561104b579160200282015b8281111561104b578251825591602001919060010190611030565b50611057929150611089565b5090565b60408051608081018252600080825260208201819052918101919091526060810161108461109e565b905290565b5b80821115611057576000815560010161108a565b60405180604001604052806002906020820280368337509192915050565b6000602082840312156110ce57600080fd5b81357fffffffff00000000000000000000000000000000000000000000000000000000811681146110fe57600080fd5b9392505050565b6000815180845260005b8181101561112b5760208185018101518683018201520161110f565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b6020815260006110fe6020830184611105565b803573ffffffffffffffffffffffffffffffffffffffff811681146111a057600080fd5b919050565b803567ffffffffffffffff811681146111a057600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040516080810167ffffffffffffffff8111828210171561120f5761120f6111bd565b60405290565b6040805190810167ffffffffffffffff8111828210171561120f5761120f6111bd565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff8111828210171561127f5761127f6111bd565b604052919050565b600067ffffffffffffffff8211156112a1576112a16111bd565b5060051b60200190565b600082601f8301126112bc57600080fd5b813567ffffffffffffffff8111156112d6576112d66111bd565b61130760207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601611238565b81815284602083860101111561131c57600080fd5b816020850160208301376000918101602001919091529392505050565b600082601f83011261134a57600080fd5b8135602061135f61135a83611287565b611238565b82815260059290921b8401810191818101908684111561137e57600080fd5b8286015b848110156113be57803567ffffffffffffffff8111156113a25760008081fd5b6113b08986838b01016112ab565b845250918301918301611382565b509695505050505050565b600082601f8301126113da57600080fd5b813560206113ea61135a83611287565b82815260059290921b8401810191818101908684111561140957600080fd5b8286015b848110156113be578035835291830191830161140d565b803560ff811681146111a057600080fd5b60008083601f84011261144757600080fd5b50813567ffffffffffffffff81111561145f57600080fd5b60208301915083602082850101111561147757600080fd5b9250929050565b60008060008060008060008060008060006101408c8e0312156114a057600080fd5b8b359a5060208c013599506114b760408d0161117c565b98506114c560608d016111a5565b975067ffffffffffffffff8060808e013511156114e157600080fd5b6114f18e60808f01358f01611339565b97508060a08e0135111561150457600080fd5b6115148e60a08f01358f016113c9565b965061152260c08e01611424565b95508060e08e0135111561153557600080fd5b6115458e60e08f01358f01611435565b90955093506115576101008e016111a5565b9250806101208e0135111561156b57600080fd5b5061157d8d6101208e01358e016112ab565b90509295989b509295989b9093969950565b803580151581146111a057600080fd5b60008082840360c08112156115b357600080fd5b83359250602060a07fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0830112156115e957600080fd5b6115f16111ec565b91506115fe8186016111a5565b8252604085013563ffffffff8116811461161757600080fd5b828201526116276060860161158f565b604083015285609f86011261163b57600080fd5b611643611215565b8060c087018881111561165557600080fd5b608088015b81811015611671578035845292840192840161165a565b5050606084015250929590945092505050565b6000806040838503121561169757600080fd5b823591506116a76020840161158f565b90509250929050565b600080600080600080600060e0888a0312156116cb57600080fd5b87359650602088013567ffffffffffffffff808211156116ea57600080fd5b6116f68b838c01611339565b975060408a013591508082111561170c57600080fd5b6117188b838c016113c9565b965061172660608b01611424565b955060808a013591508082111561173c57600080fd5b6117488b838c016112ab565b945061175660a08b016111a5565b935060c08a013591508082111561176c57600080fd5b506117798a828b016112ab565b91505092959891949750929550565b60006020828403121561179a57600080fd5b5035919050565b600060a08201905067ffffffffffffffff8351168252602063ffffffff81850151168184015260408401511515604084015260608401516060840160005b60028110156117fc578251825291830191908301906001016117df565b5050505092915050565b60006020828403121561181857600080fd5b6110fe8261117c565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b808202811582820484141761186757611867611821565b92915050565b8082018082111561186757611867611821565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600081518084526020808501808196508360051b8101915082860160005b858110156118f75782840389526118e5848351611105565b988501989350908401906001016118cd565b5091979650505050505050565b600081518084526020808501945080840160005b8381101561193457815187529582019590820190600101611918565b509495945050505050565b60006101408c83528b602084015273ffffffffffffffffffffffffffffffffffffffff8b16604084015267ffffffffffffffff808b16606085015281608085015261198c8285018b6118af565b915083820360a08501526119a0828a611904565b915060ff881660c085015283820360e08501526119bd8288611105565b90861661010085015283810361012085015290506119db8185611105565b9d9c50505050505050505050505050565b600067ffffffffffffffff808316818103611a0957611a09611821565b6001019392505050565b600061014063ffffffff8d1683528b602084015267ffffffffffffffff808c166040850152816060850152611a4a8285018c6118af565b91508382036080850152611a5e828b611904565b915060ff891660a085015283820360c0850152611a7b8289611105565b90871660e08501528381036101008501529050611a988186611105565b9150508215156101208301529b9a505050505050505050505056fea164736f6c6343000813000a", } var ExposedConfiguratorABI = ExposedConfiguratorMetaData.ABI diff --git a/core/gethwrappers/llo-feeds/generation/generated-wrapper-dependency-versions-do-not-edit.txt b/core/gethwrappers/llo-feeds/generation/generated-wrapper-dependency-versions-do-not-edit.txt index 8498720be6b..96b09fbf67d 100644 --- a/core/gethwrappers/llo-feeds/generation/generated-wrapper-dependency-versions-do-not-edit.txt +++ b/core/gethwrappers/llo-feeds/generation/generated-wrapper-dependency-versions-do-not-edit.txt @@ -2,14 +2,14 @@ GETH_VERSION: 1.14.11 channel_config_store: ../../../contracts/solc/v0.8.19/ChannelConfigStore/ChannelConfigStore.abi ../../../contracts/solc/v0.8.19/ChannelConfigStore/ChannelConfigStore.bin 3fafe83ea21d50488f5533962f62683988ffa6fd1476dccbbb9040be2369cb37 channel_config_verifier_proxy: ../../../contracts/solc/v0.8.19/ChannelVerifierProxy/ChannelVerifierProxy.abi ../../../contracts/solc/v0.8.19/ChannelVerifierProxy/ChannelVerifierProxy.bin 655658e5f61dfadfe3268de04f948b7e690ad03ca45676e645d6cd6018154661 channel_verifier: ../../../contracts/solc/v0.8.19/ChannelVerifier/ChannelVerifier.abi ../../../contracts/solc/v0.8.19/ChannelVerifier/ChannelVerifier.bin e6020553bd8e3e6b250fcaffe7efd22aea955c8c1a0eb05d282fdeb0ab6550b7 -configurator: ../../../contracts/solc/v0.8.19/Configurator/Configurator.abi ../../../contracts/solc/v0.8.19/Configurator/Configurator.bin 7d1640ca82b55c743c7dea4040e4d353a85bcc4751f42c08e29f42742d81d704 +configurator: ../../../contracts/solc/v0.8.19/Configurator/Configurator.abi ../../../contracts/solc/v0.8.19/Configurator/Configurator.bin ee5ed0cd4f42636b6e008a12a8952c0efe3381094974e97269928eb13329c636 destination_fee_manager: ../../../contracts/solc/v0.8.19/DestinationFeeManager/DestinationFeeManager.abi ../../../contracts/solc/v0.8.19/DestinationFeeManager/DestinationFeeManager.bin a56ae53e35e6610269f086b1e915ca1e80f5d0bf5695d09156e82fccfc2d77b3 destination_reward_manager: ../../../contracts/solc/v0.8.19/DestinationRewardManager/DestinationRewardManager.abi ../../../contracts/solc/v0.8.19/DestinationRewardManager/DestinationRewardManager.bin 77874e97a54ecbd9c61132964da5b053f0b584dc7b774d75dd51baedd2bc7c40 destination_verifier: ../../../contracts/solc/v0.8.19/DestinationVerifier/DestinationVerifier.abi ../../../contracts/solc/v0.8.19/DestinationVerifier/DestinationVerifier.bin 369323ce520923b9eb31ed90885f5ebd0f46b6799288fbf4da5d6ede7d697aef destination_verifier_proxy: ../../../contracts/solc/v0.8.19/DestinationVerifierProxy/DestinationVerifierProxy.abi ../../../contracts/solc/v0.8.19/DestinationVerifierProxy/DestinationVerifierProxy.bin 4e255301cf6657777e7292eccea3e4c0ce65281404341e9248e095703a9fe392 errored_verifier: ../../../contracts/solc/v0.8.19/ErroredVerifier/ErroredVerifier.abi ../../../contracts/solc/v0.8.19/ErroredVerifier/ErroredVerifier.bin ad8ac8d6b99890081725e2304d79d1ba7dd5212b89d130aa9689f4269eed4691 exposed_channel_verifier: ../../../contracts/solc/v0.8.19/ExposedChannelVerifier/ExposedChannelVerifier.abi ../../../contracts/solc/v0.8.19/ExposedChannelVerifier/ExposedChannelVerifier.bin c21cde078900241c06de69e2bc5d906c5ef558b52db66caa68bed065940a2253 -exposed_configurator: ../../../contracts/solc/v0.8.19/ExposedConfigurator/ExposedConfigurator.abi ../../../contracts/solc/v0.8.19/ExposedConfigurator/ExposedConfigurator.bin f1d4d7b812df5676bf0fd2a94187a9e871c19ed59b68aebb70ce8ee9bb4de42d +exposed_configurator: ../../../contracts/solc/v0.8.19/ExposedConfigurator/ExposedConfigurator.abi ../../../contracts/solc/v0.8.19/ExposedConfigurator/ExposedConfigurator.bin f43362e7ef7588ecbd4d7ebd45b750cc4308e89c3d9e54fba1383e792213bbef exposed_verifier: ../../../contracts/solc/v0.8.19/ExposedVerifier/ExposedVerifier.abi ../../../contracts/solc/v0.8.19/ExposedVerifier/ExposedVerifier.bin 00816ab345f768e522c79abadeadf9155c2c688067e18f8f73e5d6ab71037663 fee_manager: ../../../contracts/solc/v0.8.19/FeeManager/FeeManager.abi ../../../contracts/solc/v0.8.19/FeeManager/FeeManager.bin edc85f34294ae7c90d45c4c71eb5c105c60a4842dfbbf700c692870ffcc403a1 llo_feeds: ../../../contracts/solc/v0.8.19/FeeManager.abi ../../../contracts/solc/v0.8.19/FeeManager.bin cb71e018f67e49d7bc0e194c822204dfd59f79ff42e4fc8fd8ab63f3acd71361 diff --git a/core/gethwrappers/shared/generated/burn_mint_erc20/burn_mint_erc20.go b/core/gethwrappers/shared/generated/burn_mint_erc20/burn_mint_erc20.go deleted file mode 100644 index 9780521156e..00000000000 --- a/core/gethwrappers/shared/generated/burn_mint_erc20/burn_mint_erc20.go +++ /dev/null @@ -1,1639 +0,0 @@ -// Code generated - DO NOT EDIT. -// This file is a generated binding and any manual changes will be lost. - -package burn_mint_erc20 - -import ( - "errors" - "fmt" - "math/big" - "strings" - - ethereum "github.com/ethereum/go-ethereum" - "github.com/ethereum/go-ethereum/accounts/abi" - "github.com/ethereum/go-ethereum/accounts/abi/bind" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/event" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated" -) - -var ( - _ = errors.New - _ = big.NewInt - _ = strings.NewReader - _ = ethereum.NotFound - _ = bind.Bind - _ = common.Big1 - _ = types.BloomLookup - _ = event.NewSubscription - _ = abi.ConvertType -) - -var BurnMintERC20MetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"symbol\",\"type\":\"string\"},{\"internalType\":\"uint8\",\"name\":\"decimals_\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"maxSupply_\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"preMint\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"}],\"name\":\"InvalidRecipient\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"supplyAfterMint\",\"type\":\"uint256\"}],\"name\":\"MaxSupplyExceeded\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Approval\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousAdmin\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newAdmin\",\"type\":\"address\"}],\"name\":\"CCIPAdminTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"previousAdminRole\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"newAdminRole\",\"type\":\"bytes32\"}],\"name\":\"RoleAdminChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"RoleGranted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"RoleRevoked\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Transfer\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"BURNER_ROLE\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"DEFAULT_ADMIN_ROLE\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"MINTER_ROLE\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"}],\"name\":\"allowance\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"approve\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"burn\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"burn\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"burnFrom\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"decimals\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"subtractedValue\",\"type\":\"uint256\"}],\"name\":\"decreaseAllowance\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getCCIPAdmin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"}],\"name\":\"getRoleAdmin\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"burnAndMinter\",\"type\":\"address\"}],\"name\":\"grantMintAndBurnRoles\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"grantRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"hasRole\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"addedValue\",\"type\":\"uint256\"}],\"name\":\"increaseAllowance\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"maxSupply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"mint\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"name\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"renounceRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"revokeRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newAdmin\",\"type\":\"address\"}],\"name\":\"setCCIPAdmin\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"symbol\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"totalSupply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"transfer\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"transferFrom\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", - Bin: "0x60c06040523480156200001157600080fd5b5060405162002260380380620022608339810160408190526200003491620002e7565b848460036200004483826200040b565b5060046200005382826200040b565b50505060ff831660805260a0829052600680546001600160a01b03191633179055801562000087576200008733826200009f565b6200009460003362000166565b5050505050620004f9565b6001600160a01b038216620000fa5760405162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f206164647265737300604482015260640160405180910390fd5b80600260008282546200010e9190620004d7565b90915550506001600160a01b038216600081815260208181526040808320805486019055518481527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a35b5050565b620001728282620001f5565b620001625760008281526005602090815260408083206001600160a01b03851684529091529020805460ff19166001179055620001ac3390565b6001600160a01b0316816001600160a01b0316837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b505050565b60008281526005602090815260408083206001600160a01b038516845290915290205460ff165b92915050565b634e487b7160e01b600052604160045260246000fd5b600082601f8301126200024a57600080fd5b81516001600160401b038082111562000267576200026762000222565b604051601f8301601f19908116603f0116810190828211818310171562000292576200029262000222565b81604052838152602092508683858801011115620002af57600080fd5b600091505b83821015620002d35785820183015181830184015290820190620002b4565b600093810190920192909252949350505050565b600080600080600060a086880312156200030057600080fd5b85516001600160401b03808211156200031857600080fd5b6200032689838a0162000238565b965060208801519150808211156200033d57600080fd5b506200034c8882890162000238565b945050604086015160ff811681146200036457600080fd5b6060870151608090970151959894975095949392505050565b600181811c908216806200039257607f821691505b602082108103620003b357634e487b7160e01b600052602260045260246000fd5b50919050565b601f821115620001f057600081815260208120601f850160051c81016020861015620003e25750805b601f850160051c820191505b818110156200040357828155600101620003ee565b505050505050565b81516001600160401b0381111562000427576200042762000222565b6200043f816200043884546200037d565b84620003b9565b602080601f8311600181146200047757600084156200045e5750858301515b600019600386901b1c1916600185901b17855562000403565b600085815260208120601f198616915b82811015620004a85788860151825594840194600190910190840162000487565b5085821015620004c75787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b808201808211156200021c57634e487b7160e01b600052601160045260246000fd5b60805160a051611d336200052d6000396000818161047c015281816108f2015261091c015260006102a40152611d336000f3fe608060405234801561001057600080fd5b50600436106101c45760003560e01c806379cc6790116100f9578063a8fa343c11610097578063d539139311610071578063d539139314610440578063d547741f14610467578063d5abeb011461047a578063dd62ed3e146104a057600080fd5b8063a8fa343c14610407578063a9059cbb1461041a578063c630948d1461042d57600080fd5b806395d89b41116100d357806395d89b41146103d15780639dc29fac146103d9578063a217fddf146103ec578063a457c2d7146103f457600080fd5b806379cc6790146103505780638fd6a6ac1461036357806391d148541461038b57600080fd5b80632f2ff15d11610166578063395093511161014057806339509351146102e157806340c10f19146102f457806342966c681461030757806370a082311461031a57600080fd5b80632f2ff15d14610288578063313ce5671461029d57806336568abe146102ce57600080fd5b806318160ddd116101a257806318160ddd1461021957806323b872dd1461022b578063248a9ca31461023e578063282c51f31461026157600080fd5b806301ffc9a7146101c957806306fdde03146101f1578063095ea7b314610206575b600080fd5b6101dc6101d7366004611996565b6104e6565b60405190151581526020015b60405180910390f35b6101f9610663565b6040516101e891906119fc565b6101dc610214366004611a76565b6106f5565b6002545b6040519081526020016101e8565b6101dc610239366004611aa0565b61070d565b61021d61024c366004611adc565b60009081526005602052604090206001015490565b61021d7f3c11d16cbaffd01df69ce1c404f6340ee057498f5f00246190ea54220576a84881565b61029b610296366004611af5565b610731565b005b60405160ff7f00000000000000000000000000000000000000000000000000000000000000001681526020016101e8565b61029b6102dc366004611af5565b61075b565b6101dc6102ef366004611a76565b610813565b61029b610302366004611a76565b61085f565b61029b610315366004611adc565b6109a9565b61021d610328366004611b21565b73ffffffffffffffffffffffffffffffffffffffff1660009081526020819052604090205490565b61029b61035e366004611a76565b6109dc565b60065460405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101e8565b6101dc610399366004611af5565b600091825260056020908152604080842073ffffffffffffffffffffffffffffffffffffffff93909316845291905290205460ff1690565b6101f9610a10565b61029b6103e7366004611a76565b610a1f565b61021d600081565b6101dc610402366004611a76565b610a29565b61029b610415366004611b21565b610afa565b6101dc610428366004611a76565b610b7d565b61029b61043b366004611b21565b610b8b565b61021d7f9f2df0fed2c77648de5860a4cc508cd0818c85b8b8a1ab4ceeef8d981c8956a681565b61029b610475366004611af5565b610be2565b7f000000000000000000000000000000000000000000000000000000000000000061021d565b61021d6104ae366004611b3c565b73ffffffffffffffffffffffffffffffffffffffff918216600090815260016020908152604080832093909416825291909152205490565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f36372b0700000000000000000000000000000000000000000000000000000000148061057957507fffffffff0000000000000000000000000000000000000000000000000000000082167fe6599b4d00000000000000000000000000000000000000000000000000000000145b806105c557507fffffffff0000000000000000000000000000000000000000000000000000000082167f01ffc9a700000000000000000000000000000000000000000000000000000000145b8061061157507fffffffff0000000000000000000000000000000000000000000000000000000082167f7965db0b00000000000000000000000000000000000000000000000000000000145b8061065d57507fffffffff0000000000000000000000000000000000000000000000000000000082167f8fd6a6ac00000000000000000000000000000000000000000000000000000000145b92915050565b60606003805461067290611b66565b80601f016020809104026020016040519081016040528092919081815260200182805461069e90611b66565b80156106eb5780601f106106c0576101008083540402835291602001916106eb565b820191906000526020600020905b8154815290600101906020018083116106ce57829003601f168201915b5050505050905090565b600033610703818585610c07565b5060019392505050565b60003361071b858285610c79565b610726858585610d50565b506001949350505050565b60008281526005602052604090206001015461074c81610dc2565b6107568383610dcc565b505050565b73ffffffffffffffffffffffffffffffffffffffff81163314610805576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636560448201527f20726f6c657320666f722073656c66000000000000000000000000000000000060648201526084015b60405180910390fd5b61080f8282610ec0565b5050565b33600081815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff87168452909152812054909190610703908290869061085a908790611be8565b610c07565b7f9f2df0fed2c77648de5860a4cc508cd0818c85b8b8a1ab4ceeef8d981c8956a661088981610dc2565b3073ffffffffffffffffffffffffffffffffffffffff8416036108f0576040517f17858bbe00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff841660048201526024016107fc565b7f00000000000000000000000000000000000000000000000000000000000000001580159061095157507f00000000000000000000000000000000000000000000000000000000000000008261094560025490565b61094f9190611be8565b115b1561099f578161096060025490565b61096a9190611be8565b6040517fcbbf11130000000000000000000000000000000000000000000000000000000081526004016107fc91815260200190565b6107568383610f7b565b7f3c11d16cbaffd01df69ce1c404f6340ee057498f5f00246190ea54220576a8486109d381610dc2565b61080f8261106e565b7f3c11d16cbaffd01df69ce1c404f6340ee057498f5f00246190ea54220576a848610a0681610dc2565b6107568383611078565b60606004805461067290611b66565b61080f82826109dc565b33600081815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff8716845290915281205490919083811015610aed576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f7760448201527f207a65726f00000000000000000000000000000000000000000000000000000060648201526084016107fc565b6107268286868403610c07565b6000610b0581610dc2565b6006805473ffffffffffffffffffffffffffffffffffffffff8481167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f9524c9e4b0b61eb018dd58a1cd856e3e74009528328ab4a613b434fa631d724290600090a3505050565b600033610703818585610d50565b610bb57f9f2df0fed2c77648de5860a4cc508cd0818c85b8b8a1ab4ceeef8d981c8956a682610731565b610bdf7f3c11d16cbaffd01df69ce1c404f6340ee057498f5f00246190ea54220576a84882610731565b50565b600082815260056020526040902060010154610bfd81610dc2565b6107568383610ec0565b3073ffffffffffffffffffffffffffffffffffffffff831603610c6e576040517f17858bbe00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff831660048201526024016107fc565b61075683838361108d565b73ffffffffffffffffffffffffffffffffffffffff8381166000908152600160209081526040808320938616835292905220547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8114610d4a5781811015610d3d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e636500000060448201526064016107fc565b610d4a8484848403610c07565b50505050565b3073ffffffffffffffffffffffffffffffffffffffff831603610db7576040517f17858bbe00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff831660048201526024016107fc565b610756838383611240565b610bdf81336114af565b600082815260056020908152604080832073ffffffffffffffffffffffffffffffffffffffff8516845290915290205460ff1661080f57600082815260056020908152604080832073ffffffffffffffffffffffffffffffffffffffff85168452909152902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055610e623390565b73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b600082815260056020908152604080832073ffffffffffffffffffffffffffffffffffffffff8516845290915290205460ff161561080f57600082815260056020908152604080832073ffffffffffffffffffffffffffffffffffffffff8516808552925280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016905551339285917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a45050565b73ffffffffffffffffffffffffffffffffffffffff8216610ff8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f20616464726573730060448201526064016107fc565b806002600082825461100a9190611be8565b909155505073ffffffffffffffffffffffffffffffffffffffff8216600081815260208181526040808320805486019055518481527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a35050565b610bdf3382611569565b611083823383610c79565b61080f8282611569565b73ffffffffffffffffffffffffffffffffffffffff831661112f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f2061646460448201527f726573730000000000000000000000000000000000000000000000000000000060648201526084016107fc565b73ffffffffffffffffffffffffffffffffffffffff82166111d2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f20616464726560448201527f737300000000000000000000000000000000000000000000000000000000000060648201526084016107fc565b73ffffffffffffffffffffffffffffffffffffffff83811660008181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505050565b73ffffffffffffffffffffffffffffffffffffffff83166112e3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f20616460448201527f647265737300000000000000000000000000000000000000000000000000000060648201526084016107fc565b73ffffffffffffffffffffffffffffffffffffffff8216611386576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201527f657373000000000000000000000000000000000000000000000000000000000060648201526084016107fc565b73ffffffffffffffffffffffffffffffffffffffff83166000908152602081905260409020548181101561143c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e742065786365656473206260448201527f616c616e6365000000000000000000000000000000000000000000000000000060648201526084016107fc565b73ffffffffffffffffffffffffffffffffffffffff848116600081815260208181526040808320878703905593871680835291849020805487019055925185815290927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a3610d4a565b600082815260056020908152604080832073ffffffffffffffffffffffffffffffffffffffff8516845290915290205460ff1661080f576114ef8161172d565b6114fa83602061174c565b60405160200161150b929190611bfb565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152908290527f08c379a00000000000000000000000000000000000000000000000000000000082526107fc916004016119fc565b73ffffffffffffffffffffffffffffffffffffffff821661160c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f2061646472657360448201527f730000000000000000000000000000000000000000000000000000000000000060648201526084016107fc565b73ffffffffffffffffffffffffffffffffffffffff8216600090815260208190526040902054818110156116c2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e60448201527f636500000000000000000000000000000000000000000000000000000000000060648201526084016107fc565b73ffffffffffffffffffffffffffffffffffffffff83166000818152602081815260408083208686039055600280548790039055518581529192917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a3505050565b606061065d73ffffffffffffffffffffffffffffffffffffffff831660145b6060600061175b836002611c7c565b611766906002611be8565b67ffffffffffffffff81111561177e5761177e611c93565b6040519080825280601f01601f1916602001820160405280156117a8576020820181803683370190505b5090507f3000000000000000000000000000000000000000000000000000000000000000816000815181106117df576117df611cc2565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053507f78000000000000000000000000000000000000000000000000000000000000008160018151811061184257611842611cc2565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350600061187e846002611c7c565b611889906001611be8565b90505b6001811115611926577f303132333435363738396162636465660000000000000000000000000000000085600f16601081106118ca576118ca611cc2565b1a60f81b8282815181106118e0576118e0611cc2565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535060049490941c9361191f81611cf1565b905061188c565b50831561198f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e7460448201526064016107fc565b9392505050565b6000602082840312156119a857600080fd5b81357fffffffff000000000000000000000000000000000000000000000000000000008116811461198f57600080fd5b60005b838110156119f35781810151838201526020016119db565b50506000910152565b6020815260008251806020840152611a1b8160408501602087016119d8565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169190910160400192915050565b803573ffffffffffffffffffffffffffffffffffffffff81168114611a7157600080fd5b919050565b60008060408385031215611a8957600080fd5b611a9283611a4d565b946020939093013593505050565b600080600060608486031215611ab557600080fd5b611abe84611a4d565b9250611acc60208501611a4d565b9150604084013590509250925092565b600060208284031215611aee57600080fd5b5035919050565b60008060408385031215611b0857600080fd5b82359150611b1860208401611a4d565b90509250929050565b600060208284031215611b3357600080fd5b61198f82611a4d565b60008060408385031215611b4f57600080fd5b611b5883611a4d565b9150611b1860208401611a4d565b600181811c90821680611b7a57607f821691505b602082108103611bb3577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b8082018082111561065d5761065d611bb9565b7f416363657373436f6e74726f6c3a206163636f756e7420000000000000000000815260008351611c338160178501602088016119d8565b7f206973206d697373696e6720726f6c65200000000000000000000000000000006017918401918201528351611c708160288401602088016119d8565b01602801949350505050565b808202811582820484141761065d5761065d611bb9565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600081611d0057611d00611bb9565b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff019056fea164736f6c6343000813000a", -} - -var BurnMintERC20ABI = BurnMintERC20MetaData.ABI - -var BurnMintERC20Bin = BurnMintERC20MetaData.Bin - -func DeployBurnMintERC20(auth *bind.TransactOpts, backend bind.ContractBackend, name string, symbol string, decimals_ uint8, maxSupply_ *big.Int, preMint *big.Int) (common.Address, *types.Transaction, *BurnMintERC20, error) { - parsed, err := BurnMintERC20MetaData.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(BurnMintERC20Bin), backend, name, symbol, decimals_, maxSupply_, preMint) - if err != nil { - return common.Address{}, nil, nil, err - } - return address, tx, &BurnMintERC20{address: address, abi: *parsed, BurnMintERC20Caller: BurnMintERC20Caller{contract: contract}, BurnMintERC20Transactor: BurnMintERC20Transactor{contract: contract}, BurnMintERC20Filterer: BurnMintERC20Filterer{contract: contract}}, nil -} - -type BurnMintERC20 struct { - address common.Address - abi abi.ABI - BurnMintERC20Caller - BurnMintERC20Transactor - BurnMintERC20Filterer -} - -type BurnMintERC20Caller struct { - contract *bind.BoundContract -} - -type BurnMintERC20Transactor struct { - contract *bind.BoundContract -} - -type BurnMintERC20Filterer struct { - contract *bind.BoundContract -} - -type BurnMintERC20Session struct { - Contract *BurnMintERC20 - CallOpts bind.CallOpts - TransactOpts bind.TransactOpts -} - -type BurnMintERC20CallerSession struct { - Contract *BurnMintERC20Caller - CallOpts bind.CallOpts -} - -type BurnMintERC20TransactorSession struct { - Contract *BurnMintERC20Transactor - TransactOpts bind.TransactOpts -} - -type BurnMintERC20Raw struct { - Contract *BurnMintERC20 -} - -type BurnMintERC20CallerRaw struct { - Contract *BurnMintERC20Caller -} - -type BurnMintERC20TransactorRaw struct { - Contract *BurnMintERC20Transactor -} - -func NewBurnMintERC20(address common.Address, backend bind.ContractBackend) (*BurnMintERC20, error) { - abi, err := abi.JSON(strings.NewReader(BurnMintERC20ABI)) - if err != nil { - return nil, err - } - contract, err := bindBurnMintERC20(address, backend, backend, backend) - if err != nil { - return nil, err - } - return &BurnMintERC20{address: address, abi: abi, BurnMintERC20Caller: BurnMintERC20Caller{contract: contract}, BurnMintERC20Transactor: BurnMintERC20Transactor{contract: contract}, BurnMintERC20Filterer: BurnMintERC20Filterer{contract: contract}}, nil -} - -func NewBurnMintERC20Caller(address common.Address, caller bind.ContractCaller) (*BurnMintERC20Caller, error) { - contract, err := bindBurnMintERC20(address, caller, nil, nil) - if err != nil { - return nil, err - } - return &BurnMintERC20Caller{contract: contract}, nil -} - -func NewBurnMintERC20Transactor(address common.Address, transactor bind.ContractTransactor) (*BurnMintERC20Transactor, error) { - contract, err := bindBurnMintERC20(address, nil, transactor, nil) - if err != nil { - return nil, err - } - return &BurnMintERC20Transactor{contract: contract}, nil -} - -func NewBurnMintERC20Filterer(address common.Address, filterer bind.ContractFilterer) (*BurnMintERC20Filterer, error) { - contract, err := bindBurnMintERC20(address, nil, nil, filterer) - if err != nil { - return nil, err - } - return &BurnMintERC20Filterer{contract: contract}, nil -} - -func bindBurnMintERC20(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { - parsed, err := BurnMintERC20MetaData.GetAbi() - if err != nil { - return nil, err - } - return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil -} - -func (_BurnMintERC20 *BurnMintERC20Raw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { - return _BurnMintERC20.Contract.BurnMintERC20Caller.contract.Call(opts, result, method, params...) -} - -func (_BurnMintERC20 *BurnMintERC20Raw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { - return _BurnMintERC20.Contract.BurnMintERC20Transactor.contract.Transfer(opts) -} - -func (_BurnMintERC20 *BurnMintERC20Raw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { - return _BurnMintERC20.Contract.BurnMintERC20Transactor.contract.Transact(opts, method, params...) -} - -func (_BurnMintERC20 *BurnMintERC20CallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { - return _BurnMintERC20.Contract.contract.Call(opts, result, method, params...) -} - -func (_BurnMintERC20 *BurnMintERC20TransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { - return _BurnMintERC20.Contract.contract.Transfer(opts) -} - -func (_BurnMintERC20 *BurnMintERC20TransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { - return _BurnMintERC20.Contract.contract.Transact(opts, method, params...) -} - -func (_BurnMintERC20 *BurnMintERC20Caller) BURNERROLE(opts *bind.CallOpts) ([32]byte, error) { - var out []interface{} - err := _BurnMintERC20.contract.Call(opts, &out, "BURNER_ROLE") - - if err != nil { - return *new([32]byte), err - } - - out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) - - return out0, err - -} - -func (_BurnMintERC20 *BurnMintERC20Session) BURNERROLE() ([32]byte, error) { - return _BurnMintERC20.Contract.BURNERROLE(&_BurnMintERC20.CallOpts) -} - -func (_BurnMintERC20 *BurnMintERC20CallerSession) BURNERROLE() ([32]byte, error) { - return _BurnMintERC20.Contract.BURNERROLE(&_BurnMintERC20.CallOpts) -} - -func (_BurnMintERC20 *BurnMintERC20Caller) DEFAULTADMINROLE(opts *bind.CallOpts) ([32]byte, error) { - var out []interface{} - err := _BurnMintERC20.contract.Call(opts, &out, "DEFAULT_ADMIN_ROLE") - - if err != nil { - return *new([32]byte), err - } - - out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) - - return out0, err - -} - -func (_BurnMintERC20 *BurnMintERC20Session) DEFAULTADMINROLE() ([32]byte, error) { - return _BurnMintERC20.Contract.DEFAULTADMINROLE(&_BurnMintERC20.CallOpts) -} - -func (_BurnMintERC20 *BurnMintERC20CallerSession) DEFAULTADMINROLE() ([32]byte, error) { - return _BurnMintERC20.Contract.DEFAULTADMINROLE(&_BurnMintERC20.CallOpts) -} - -func (_BurnMintERC20 *BurnMintERC20Caller) MINTERROLE(opts *bind.CallOpts) ([32]byte, error) { - var out []interface{} - err := _BurnMintERC20.contract.Call(opts, &out, "MINTER_ROLE") - - if err != nil { - return *new([32]byte), err - } - - out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) - - return out0, err - -} - -func (_BurnMintERC20 *BurnMintERC20Session) MINTERROLE() ([32]byte, error) { - return _BurnMintERC20.Contract.MINTERROLE(&_BurnMintERC20.CallOpts) -} - -func (_BurnMintERC20 *BurnMintERC20CallerSession) MINTERROLE() ([32]byte, error) { - return _BurnMintERC20.Contract.MINTERROLE(&_BurnMintERC20.CallOpts) -} - -func (_BurnMintERC20 *BurnMintERC20Caller) Allowance(opts *bind.CallOpts, owner common.Address, spender common.Address) (*big.Int, error) { - var out []interface{} - err := _BurnMintERC20.contract.Call(opts, &out, "allowance", owner, spender) - - if err != nil { - return *new(*big.Int), err - } - - out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) - - return out0, err - -} - -func (_BurnMintERC20 *BurnMintERC20Session) Allowance(owner common.Address, spender common.Address) (*big.Int, error) { - return _BurnMintERC20.Contract.Allowance(&_BurnMintERC20.CallOpts, owner, spender) -} - -func (_BurnMintERC20 *BurnMintERC20CallerSession) Allowance(owner common.Address, spender common.Address) (*big.Int, error) { - return _BurnMintERC20.Contract.Allowance(&_BurnMintERC20.CallOpts, owner, spender) -} - -func (_BurnMintERC20 *BurnMintERC20Caller) BalanceOf(opts *bind.CallOpts, account common.Address) (*big.Int, error) { - var out []interface{} - err := _BurnMintERC20.contract.Call(opts, &out, "balanceOf", account) - - if err != nil { - return *new(*big.Int), err - } - - out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) - - return out0, err - -} - -func (_BurnMintERC20 *BurnMintERC20Session) BalanceOf(account common.Address) (*big.Int, error) { - return _BurnMintERC20.Contract.BalanceOf(&_BurnMintERC20.CallOpts, account) -} - -func (_BurnMintERC20 *BurnMintERC20CallerSession) BalanceOf(account common.Address) (*big.Int, error) { - return _BurnMintERC20.Contract.BalanceOf(&_BurnMintERC20.CallOpts, account) -} - -func (_BurnMintERC20 *BurnMintERC20Caller) Decimals(opts *bind.CallOpts) (uint8, error) { - var out []interface{} - err := _BurnMintERC20.contract.Call(opts, &out, "decimals") - - if err != nil { - return *new(uint8), err - } - - out0 := *abi.ConvertType(out[0], new(uint8)).(*uint8) - - return out0, err - -} - -func (_BurnMintERC20 *BurnMintERC20Session) Decimals() (uint8, error) { - return _BurnMintERC20.Contract.Decimals(&_BurnMintERC20.CallOpts) -} - -func (_BurnMintERC20 *BurnMintERC20CallerSession) Decimals() (uint8, error) { - return _BurnMintERC20.Contract.Decimals(&_BurnMintERC20.CallOpts) -} - -func (_BurnMintERC20 *BurnMintERC20Caller) GetCCIPAdmin(opts *bind.CallOpts) (common.Address, error) { - var out []interface{} - err := _BurnMintERC20.contract.Call(opts, &out, "getCCIPAdmin") - - if err != nil { - return *new(common.Address), err - } - - out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) - - return out0, err - -} - -func (_BurnMintERC20 *BurnMintERC20Session) GetCCIPAdmin() (common.Address, error) { - return _BurnMintERC20.Contract.GetCCIPAdmin(&_BurnMintERC20.CallOpts) -} - -func (_BurnMintERC20 *BurnMintERC20CallerSession) GetCCIPAdmin() (common.Address, error) { - return _BurnMintERC20.Contract.GetCCIPAdmin(&_BurnMintERC20.CallOpts) -} - -func (_BurnMintERC20 *BurnMintERC20Caller) GetRoleAdmin(opts *bind.CallOpts, role [32]byte) ([32]byte, error) { - var out []interface{} - err := _BurnMintERC20.contract.Call(opts, &out, "getRoleAdmin", role) - - if err != nil { - return *new([32]byte), err - } - - out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) - - return out0, err - -} - -func (_BurnMintERC20 *BurnMintERC20Session) GetRoleAdmin(role [32]byte) ([32]byte, error) { - return _BurnMintERC20.Contract.GetRoleAdmin(&_BurnMintERC20.CallOpts, role) -} - -func (_BurnMintERC20 *BurnMintERC20CallerSession) GetRoleAdmin(role [32]byte) ([32]byte, error) { - return _BurnMintERC20.Contract.GetRoleAdmin(&_BurnMintERC20.CallOpts, role) -} - -func (_BurnMintERC20 *BurnMintERC20Caller) HasRole(opts *bind.CallOpts, role [32]byte, account common.Address) (bool, error) { - var out []interface{} - err := _BurnMintERC20.contract.Call(opts, &out, "hasRole", role, account) - - if err != nil { - return *new(bool), err - } - - out0 := *abi.ConvertType(out[0], new(bool)).(*bool) - - return out0, err - -} - -func (_BurnMintERC20 *BurnMintERC20Session) HasRole(role [32]byte, account common.Address) (bool, error) { - return _BurnMintERC20.Contract.HasRole(&_BurnMintERC20.CallOpts, role, account) -} - -func (_BurnMintERC20 *BurnMintERC20CallerSession) HasRole(role [32]byte, account common.Address) (bool, error) { - return _BurnMintERC20.Contract.HasRole(&_BurnMintERC20.CallOpts, role, account) -} - -func (_BurnMintERC20 *BurnMintERC20Caller) MaxSupply(opts *bind.CallOpts) (*big.Int, error) { - var out []interface{} - err := _BurnMintERC20.contract.Call(opts, &out, "maxSupply") - - if err != nil { - return *new(*big.Int), err - } - - out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) - - return out0, err - -} - -func (_BurnMintERC20 *BurnMintERC20Session) MaxSupply() (*big.Int, error) { - return _BurnMintERC20.Contract.MaxSupply(&_BurnMintERC20.CallOpts) -} - -func (_BurnMintERC20 *BurnMintERC20CallerSession) MaxSupply() (*big.Int, error) { - return _BurnMintERC20.Contract.MaxSupply(&_BurnMintERC20.CallOpts) -} - -func (_BurnMintERC20 *BurnMintERC20Caller) Name(opts *bind.CallOpts) (string, error) { - var out []interface{} - err := _BurnMintERC20.contract.Call(opts, &out, "name") - - if err != nil { - return *new(string), err - } - - out0 := *abi.ConvertType(out[0], new(string)).(*string) - - return out0, err - -} - -func (_BurnMintERC20 *BurnMintERC20Session) Name() (string, error) { - return _BurnMintERC20.Contract.Name(&_BurnMintERC20.CallOpts) -} - -func (_BurnMintERC20 *BurnMintERC20CallerSession) Name() (string, error) { - return _BurnMintERC20.Contract.Name(&_BurnMintERC20.CallOpts) -} - -func (_BurnMintERC20 *BurnMintERC20Caller) SupportsInterface(opts *bind.CallOpts, interfaceId [4]byte) (bool, error) { - var out []interface{} - err := _BurnMintERC20.contract.Call(opts, &out, "supportsInterface", interfaceId) - - if err != nil { - return *new(bool), err - } - - out0 := *abi.ConvertType(out[0], new(bool)).(*bool) - - return out0, err - -} - -func (_BurnMintERC20 *BurnMintERC20Session) SupportsInterface(interfaceId [4]byte) (bool, error) { - return _BurnMintERC20.Contract.SupportsInterface(&_BurnMintERC20.CallOpts, interfaceId) -} - -func (_BurnMintERC20 *BurnMintERC20CallerSession) SupportsInterface(interfaceId [4]byte) (bool, error) { - return _BurnMintERC20.Contract.SupportsInterface(&_BurnMintERC20.CallOpts, interfaceId) -} - -func (_BurnMintERC20 *BurnMintERC20Caller) Symbol(opts *bind.CallOpts) (string, error) { - var out []interface{} - err := _BurnMintERC20.contract.Call(opts, &out, "symbol") - - if err != nil { - return *new(string), err - } - - out0 := *abi.ConvertType(out[0], new(string)).(*string) - - return out0, err - -} - -func (_BurnMintERC20 *BurnMintERC20Session) Symbol() (string, error) { - return _BurnMintERC20.Contract.Symbol(&_BurnMintERC20.CallOpts) -} - -func (_BurnMintERC20 *BurnMintERC20CallerSession) Symbol() (string, error) { - return _BurnMintERC20.Contract.Symbol(&_BurnMintERC20.CallOpts) -} - -func (_BurnMintERC20 *BurnMintERC20Caller) TotalSupply(opts *bind.CallOpts) (*big.Int, error) { - var out []interface{} - err := _BurnMintERC20.contract.Call(opts, &out, "totalSupply") - - if err != nil { - return *new(*big.Int), err - } - - out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) - - return out0, err - -} - -func (_BurnMintERC20 *BurnMintERC20Session) TotalSupply() (*big.Int, error) { - return _BurnMintERC20.Contract.TotalSupply(&_BurnMintERC20.CallOpts) -} - -func (_BurnMintERC20 *BurnMintERC20CallerSession) TotalSupply() (*big.Int, error) { - return _BurnMintERC20.Contract.TotalSupply(&_BurnMintERC20.CallOpts) -} - -func (_BurnMintERC20 *BurnMintERC20Transactor) Approve(opts *bind.TransactOpts, spender common.Address, amount *big.Int) (*types.Transaction, error) { - return _BurnMintERC20.contract.Transact(opts, "approve", spender, amount) -} - -func (_BurnMintERC20 *BurnMintERC20Session) Approve(spender common.Address, amount *big.Int) (*types.Transaction, error) { - return _BurnMintERC20.Contract.Approve(&_BurnMintERC20.TransactOpts, spender, amount) -} - -func (_BurnMintERC20 *BurnMintERC20TransactorSession) Approve(spender common.Address, amount *big.Int) (*types.Transaction, error) { - return _BurnMintERC20.Contract.Approve(&_BurnMintERC20.TransactOpts, spender, amount) -} - -func (_BurnMintERC20 *BurnMintERC20Transactor) Burn(opts *bind.TransactOpts, amount *big.Int) (*types.Transaction, error) { - return _BurnMintERC20.contract.Transact(opts, "burn", amount) -} - -func (_BurnMintERC20 *BurnMintERC20Session) Burn(amount *big.Int) (*types.Transaction, error) { - return _BurnMintERC20.Contract.Burn(&_BurnMintERC20.TransactOpts, amount) -} - -func (_BurnMintERC20 *BurnMintERC20TransactorSession) Burn(amount *big.Int) (*types.Transaction, error) { - return _BurnMintERC20.Contract.Burn(&_BurnMintERC20.TransactOpts, amount) -} - -func (_BurnMintERC20 *BurnMintERC20Transactor) Burn0(opts *bind.TransactOpts, account common.Address, amount *big.Int) (*types.Transaction, error) { - return _BurnMintERC20.contract.Transact(opts, "burn0", account, amount) -} - -func (_BurnMintERC20 *BurnMintERC20Session) Burn0(account common.Address, amount *big.Int) (*types.Transaction, error) { - return _BurnMintERC20.Contract.Burn0(&_BurnMintERC20.TransactOpts, account, amount) -} - -func (_BurnMintERC20 *BurnMintERC20TransactorSession) Burn0(account common.Address, amount *big.Int) (*types.Transaction, error) { - return _BurnMintERC20.Contract.Burn0(&_BurnMintERC20.TransactOpts, account, amount) -} - -func (_BurnMintERC20 *BurnMintERC20Transactor) BurnFrom(opts *bind.TransactOpts, account common.Address, amount *big.Int) (*types.Transaction, error) { - return _BurnMintERC20.contract.Transact(opts, "burnFrom", account, amount) -} - -func (_BurnMintERC20 *BurnMintERC20Session) BurnFrom(account common.Address, amount *big.Int) (*types.Transaction, error) { - return _BurnMintERC20.Contract.BurnFrom(&_BurnMintERC20.TransactOpts, account, amount) -} - -func (_BurnMintERC20 *BurnMintERC20TransactorSession) BurnFrom(account common.Address, amount *big.Int) (*types.Transaction, error) { - return _BurnMintERC20.Contract.BurnFrom(&_BurnMintERC20.TransactOpts, account, amount) -} - -func (_BurnMintERC20 *BurnMintERC20Transactor) DecreaseAllowance(opts *bind.TransactOpts, spender common.Address, subtractedValue *big.Int) (*types.Transaction, error) { - return _BurnMintERC20.contract.Transact(opts, "decreaseAllowance", spender, subtractedValue) -} - -func (_BurnMintERC20 *BurnMintERC20Session) DecreaseAllowance(spender common.Address, subtractedValue *big.Int) (*types.Transaction, error) { - return _BurnMintERC20.Contract.DecreaseAllowance(&_BurnMintERC20.TransactOpts, spender, subtractedValue) -} - -func (_BurnMintERC20 *BurnMintERC20TransactorSession) DecreaseAllowance(spender common.Address, subtractedValue *big.Int) (*types.Transaction, error) { - return _BurnMintERC20.Contract.DecreaseAllowance(&_BurnMintERC20.TransactOpts, spender, subtractedValue) -} - -func (_BurnMintERC20 *BurnMintERC20Transactor) GrantMintAndBurnRoles(opts *bind.TransactOpts, burnAndMinter common.Address) (*types.Transaction, error) { - return _BurnMintERC20.contract.Transact(opts, "grantMintAndBurnRoles", burnAndMinter) -} - -func (_BurnMintERC20 *BurnMintERC20Session) GrantMintAndBurnRoles(burnAndMinter common.Address) (*types.Transaction, error) { - return _BurnMintERC20.Contract.GrantMintAndBurnRoles(&_BurnMintERC20.TransactOpts, burnAndMinter) -} - -func (_BurnMintERC20 *BurnMintERC20TransactorSession) GrantMintAndBurnRoles(burnAndMinter common.Address) (*types.Transaction, error) { - return _BurnMintERC20.Contract.GrantMintAndBurnRoles(&_BurnMintERC20.TransactOpts, burnAndMinter) -} - -func (_BurnMintERC20 *BurnMintERC20Transactor) GrantRole(opts *bind.TransactOpts, role [32]byte, account common.Address) (*types.Transaction, error) { - return _BurnMintERC20.contract.Transact(opts, "grantRole", role, account) -} - -func (_BurnMintERC20 *BurnMintERC20Session) GrantRole(role [32]byte, account common.Address) (*types.Transaction, error) { - return _BurnMintERC20.Contract.GrantRole(&_BurnMintERC20.TransactOpts, role, account) -} - -func (_BurnMintERC20 *BurnMintERC20TransactorSession) GrantRole(role [32]byte, account common.Address) (*types.Transaction, error) { - return _BurnMintERC20.Contract.GrantRole(&_BurnMintERC20.TransactOpts, role, account) -} - -func (_BurnMintERC20 *BurnMintERC20Transactor) IncreaseAllowance(opts *bind.TransactOpts, spender common.Address, addedValue *big.Int) (*types.Transaction, error) { - return _BurnMintERC20.contract.Transact(opts, "increaseAllowance", spender, addedValue) -} - -func (_BurnMintERC20 *BurnMintERC20Session) IncreaseAllowance(spender common.Address, addedValue *big.Int) (*types.Transaction, error) { - return _BurnMintERC20.Contract.IncreaseAllowance(&_BurnMintERC20.TransactOpts, spender, addedValue) -} - -func (_BurnMintERC20 *BurnMintERC20TransactorSession) IncreaseAllowance(spender common.Address, addedValue *big.Int) (*types.Transaction, error) { - return _BurnMintERC20.Contract.IncreaseAllowance(&_BurnMintERC20.TransactOpts, spender, addedValue) -} - -func (_BurnMintERC20 *BurnMintERC20Transactor) Mint(opts *bind.TransactOpts, account common.Address, amount *big.Int) (*types.Transaction, error) { - return _BurnMintERC20.contract.Transact(opts, "mint", account, amount) -} - -func (_BurnMintERC20 *BurnMintERC20Session) Mint(account common.Address, amount *big.Int) (*types.Transaction, error) { - return _BurnMintERC20.Contract.Mint(&_BurnMintERC20.TransactOpts, account, amount) -} - -func (_BurnMintERC20 *BurnMintERC20TransactorSession) Mint(account common.Address, amount *big.Int) (*types.Transaction, error) { - return _BurnMintERC20.Contract.Mint(&_BurnMintERC20.TransactOpts, account, amount) -} - -func (_BurnMintERC20 *BurnMintERC20Transactor) RenounceRole(opts *bind.TransactOpts, role [32]byte, account common.Address) (*types.Transaction, error) { - return _BurnMintERC20.contract.Transact(opts, "renounceRole", role, account) -} - -func (_BurnMintERC20 *BurnMintERC20Session) RenounceRole(role [32]byte, account common.Address) (*types.Transaction, error) { - return _BurnMintERC20.Contract.RenounceRole(&_BurnMintERC20.TransactOpts, role, account) -} - -func (_BurnMintERC20 *BurnMintERC20TransactorSession) RenounceRole(role [32]byte, account common.Address) (*types.Transaction, error) { - return _BurnMintERC20.Contract.RenounceRole(&_BurnMintERC20.TransactOpts, role, account) -} - -func (_BurnMintERC20 *BurnMintERC20Transactor) RevokeRole(opts *bind.TransactOpts, role [32]byte, account common.Address) (*types.Transaction, error) { - return _BurnMintERC20.contract.Transact(opts, "revokeRole", role, account) -} - -func (_BurnMintERC20 *BurnMintERC20Session) RevokeRole(role [32]byte, account common.Address) (*types.Transaction, error) { - return _BurnMintERC20.Contract.RevokeRole(&_BurnMintERC20.TransactOpts, role, account) -} - -func (_BurnMintERC20 *BurnMintERC20TransactorSession) RevokeRole(role [32]byte, account common.Address) (*types.Transaction, error) { - return _BurnMintERC20.Contract.RevokeRole(&_BurnMintERC20.TransactOpts, role, account) -} - -func (_BurnMintERC20 *BurnMintERC20Transactor) SetCCIPAdmin(opts *bind.TransactOpts, newAdmin common.Address) (*types.Transaction, error) { - return _BurnMintERC20.contract.Transact(opts, "setCCIPAdmin", newAdmin) -} - -func (_BurnMintERC20 *BurnMintERC20Session) SetCCIPAdmin(newAdmin common.Address) (*types.Transaction, error) { - return _BurnMintERC20.Contract.SetCCIPAdmin(&_BurnMintERC20.TransactOpts, newAdmin) -} - -func (_BurnMintERC20 *BurnMintERC20TransactorSession) SetCCIPAdmin(newAdmin common.Address) (*types.Transaction, error) { - return _BurnMintERC20.Contract.SetCCIPAdmin(&_BurnMintERC20.TransactOpts, newAdmin) -} - -func (_BurnMintERC20 *BurnMintERC20Transactor) Transfer(opts *bind.TransactOpts, to common.Address, amount *big.Int) (*types.Transaction, error) { - return _BurnMintERC20.contract.Transact(opts, "transfer", to, amount) -} - -func (_BurnMintERC20 *BurnMintERC20Session) Transfer(to common.Address, amount *big.Int) (*types.Transaction, error) { - return _BurnMintERC20.Contract.Transfer(&_BurnMintERC20.TransactOpts, to, amount) -} - -func (_BurnMintERC20 *BurnMintERC20TransactorSession) Transfer(to common.Address, amount *big.Int) (*types.Transaction, error) { - return _BurnMintERC20.Contract.Transfer(&_BurnMintERC20.TransactOpts, to, amount) -} - -func (_BurnMintERC20 *BurnMintERC20Transactor) TransferFrom(opts *bind.TransactOpts, from common.Address, to common.Address, amount *big.Int) (*types.Transaction, error) { - return _BurnMintERC20.contract.Transact(opts, "transferFrom", from, to, amount) -} - -func (_BurnMintERC20 *BurnMintERC20Session) TransferFrom(from common.Address, to common.Address, amount *big.Int) (*types.Transaction, error) { - return _BurnMintERC20.Contract.TransferFrom(&_BurnMintERC20.TransactOpts, from, to, amount) -} - -func (_BurnMintERC20 *BurnMintERC20TransactorSession) TransferFrom(from common.Address, to common.Address, amount *big.Int) (*types.Transaction, error) { - return _BurnMintERC20.Contract.TransferFrom(&_BurnMintERC20.TransactOpts, from, to, amount) -} - -type BurnMintERC20ApprovalIterator struct { - Event *BurnMintERC20Approval - - contract *bind.BoundContract - event string - - logs chan types.Log - sub ethereum.Subscription - done bool - fail error -} - -func (it *BurnMintERC20ApprovalIterator) Next() bool { - - if it.fail != nil { - return false - } - - if it.done { - select { - case log := <-it.logs: - it.Event = new(BurnMintERC20Approval) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - default: - return false - } - } - - select { - case log := <-it.logs: - it.Event = new(BurnMintERC20Approval) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - case err := <-it.sub.Err(): - it.done = true - it.fail = err - return it.Next() - } -} - -func (it *BurnMintERC20ApprovalIterator) Error() error { - return it.fail -} - -func (it *BurnMintERC20ApprovalIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -type BurnMintERC20Approval struct { - Owner common.Address - Spender common.Address - Value *big.Int - Raw types.Log -} - -func (_BurnMintERC20 *BurnMintERC20Filterer) FilterApproval(opts *bind.FilterOpts, owner []common.Address, spender []common.Address) (*BurnMintERC20ApprovalIterator, error) { - - var ownerRule []interface{} - for _, ownerItem := range owner { - ownerRule = append(ownerRule, ownerItem) - } - var spenderRule []interface{} - for _, spenderItem := range spender { - spenderRule = append(spenderRule, spenderItem) - } - - logs, sub, err := _BurnMintERC20.contract.FilterLogs(opts, "Approval", ownerRule, spenderRule) - if err != nil { - return nil, err - } - return &BurnMintERC20ApprovalIterator{contract: _BurnMintERC20.contract, event: "Approval", logs: logs, sub: sub}, nil -} - -func (_BurnMintERC20 *BurnMintERC20Filterer) WatchApproval(opts *bind.WatchOpts, sink chan<- *BurnMintERC20Approval, owner []common.Address, spender []common.Address) (event.Subscription, error) { - - var ownerRule []interface{} - for _, ownerItem := range owner { - ownerRule = append(ownerRule, ownerItem) - } - var spenderRule []interface{} - for _, spenderItem := range spender { - spenderRule = append(spenderRule, spenderItem) - } - - logs, sub, err := _BurnMintERC20.contract.WatchLogs(opts, "Approval", ownerRule, spenderRule) - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - - event := new(BurnMintERC20Approval) - if err := _BurnMintERC20.contract.UnpackLog(event, "Approval", log); err != nil { - return err - } - event.Raw = log - - select { - case sink <- event: - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - } - }), nil -} - -func (_BurnMintERC20 *BurnMintERC20Filterer) ParseApproval(log types.Log) (*BurnMintERC20Approval, error) { - event := new(BurnMintERC20Approval) - if err := _BurnMintERC20.contract.UnpackLog(event, "Approval", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -type BurnMintERC20CCIPAdminTransferredIterator struct { - Event *BurnMintERC20CCIPAdminTransferred - - contract *bind.BoundContract - event string - - logs chan types.Log - sub ethereum.Subscription - done bool - fail error -} - -func (it *BurnMintERC20CCIPAdminTransferredIterator) Next() bool { - - if it.fail != nil { - return false - } - - if it.done { - select { - case log := <-it.logs: - it.Event = new(BurnMintERC20CCIPAdminTransferred) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - default: - return false - } - } - - select { - case log := <-it.logs: - it.Event = new(BurnMintERC20CCIPAdminTransferred) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - case err := <-it.sub.Err(): - it.done = true - it.fail = err - return it.Next() - } -} - -func (it *BurnMintERC20CCIPAdminTransferredIterator) Error() error { - return it.fail -} - -func (it *BurnMintERC20CCIPAdminTransferredIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -type BurnMintERC20CCIPAdminTransferred struct { - PreviousAdmin common.Address - NewAdmin common.Address - Raw types.Log -} - -func (_BurnMintERC20 *BurnMintERC20Filterer) FilterCCIPAdminTransferred(opts *bind.FilterOpts, previousAdmin []common.Address, newAdmin []common.Address) (*BurnMintERC20CCIPAdminTransferredIterator, error) { - - var previousAdminRule []interface{} - for _, previousAdminItem := range previousAdmin { - previousAdminRule = append(previousAdminRule, previousAdminItem) - } - var newAdminRule []interface{} - for _, newAdminItem := range newAdmin { - newAdminRule = append(newAdminRule, newAdminItem) - } - - logs, sub, err := _BurnMintERC20.contract.FilterLogs(opts, "CCIPAdminTransferred", previousAdminRule, newAdminRule) - if err != nil { - return nil, err - } - return &BurnMintERC20CCIPAdminTransferredIterator{contract: _BurnMintERC20.contract, event: "CCIPAdminTransferred", logs: logs, sub: sub}, nil -} - -func (_BurnMintERC20 *BurnMintERC20Filterer) WatchCCIPAdminTransferred(opts *bind.WatchOpts, sink chan<- *BurnMintERC20CCIPAdminTransferred, previousAdmin []common.Address, newAdmin []common.Address) (event.Subscription, error) { - - var previousAdminRule []interface{} - for _, previousAdminItem := range previousAdmin { - previousAdminRule = append(previousAdminRule, previousAdminItem) - } - var newAdminRule []interface{} - for _, newAdminItem := range newAdmin { - newAdminRule = append(newAdminRule, newAdminItem) - } - - logs, sub, err := _BurnMintERC20.contract.WatchLogs(opts, "CCIPAdminTransferred", previousAdminRule, newAdminRule) - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - - event := new(BurnMintERC20CCIPAdminTransferred) - if err := _BurnMintERC20.contract.UnpackLog(event, "CCIPAdminTransferred", log); err != nil { - return err - } - event.Raw = log - - select { - case sink <- event: - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - } - }), nil -} - -func (_BurnMintERC20 *BurnMintERC20Filterer) ParseCCIPAdminTransferred(log types.Log) (*BurnMintERC20CCIPAdminTransferred, error) { - event := new(BurnMintERC20CCIPAdminTransferred) - if err := _BurnMintERC20.contract.UnpackLog(event, "CCIPAdminTransferred", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -type BurnMintERC20RoleAdminChangedIterator struct { - Event *BurnMintERC20RoleAdminChanged - - contract *bind.BoundContract - event string - - logs chan types.Log - sub ethereum.Subscription - done bool - fail error -} - -func (it *BurnMintERC20RoleAdminChangedIterator) Next() bool { - - if it.fail != nil { - return false - } - - if it.done { - select { - case log := <-it.logs: - it.Event = new(BurnMintERC20RoleAdminChanged) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - default: - return false - } - } - - select { - case log := <-it.logs: - it.Event = new(BurnMintERC20RoleAdminChanged) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - case err := <-it.sub.Err(): - it.done = true - it.fail = err - return it.Next() - } -} - -func (it *BurnMintERC20RoleAdminChangedIterator) Error() error { - return it.fail -} - -func (it *BurnMintERC20RoleAdminChangedIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -type BurnMintERC20RoleAdminChanged struct { - Role [32]byte - PreviousAdminRole [32]byte - NewAdminRole [32]byte - Raw types.Log -} - -func (_BurnMintERC20 *BurnMintERC20Filterer) FilterRoleAdminChanged(opts *bind.FilterOpts, role [][32]byte, previousAdminRole [][32]byte, newAdminRole [][32]byte) (*BurnMintERC20RoleAdminChangedIterator, error) { - - var roleRule []interface{} - for _, roleItem := range role { - roleRule = append(roleRule, roleItem) - } - var previousAdminRoleRule []interface{} - for _, previousAdminRoleItem := range previousAdminRole { - previousAdminRoleRule = append(previousAdminRoleRule, previousAdminRoleItem) - } - var newAdminRoleRule []interface{} - for _, newAdminRoleItem := range newAdminRole { - newAdminRoleRule = append(newAdminRoleRule, newAdminRoleItem) - } - - logs, sub, err := _BurnMintERC20.contract.FilterLogs(opts, "RoleAdminChanged", roleRule, previousAdminRoleRule, newAdminRoleRule) - if err != nil { - return nil, err - } - return &BurnMintERC20RoleAdminChangedIterator{contract: _BurnMintERC20.contract, event: "RoleAdminChanged", logs: logs, sub: sub}, nil -} - -func (_BurnMintERC20 *BurnMintERC20Filterer) WatchRoleAdminChanged(opts *bind.WatchOpts, sink chan<- *BurnMintERC20RoleAdminChanged, role [][32]byte, previousAdminRole [][32]byte, newAdminRole [][32]byte) (event.Subscription, error) { - - var roleRule []interface{} - for _, roleItem := range role { - roleRule = append(roleRule, roleItem) - } - var previousAdminRoleRule []interface{} - for _, previousAdminRoleItem := range previousAdminRole { - previousAdminRoleRule = append(previousAdminRoleRule, previousAdminRoleItem) - } - var newAdminRoleRule []interface{} - for _, newAdminRoleItem := range newAdminRole { - newAdminRoleRule = append(newAdminRoleRule, newAdminRoleItem) - } - - logs, sub, err := _BurnMintERC20.contract.WatchLogs(opts, "RoleAdminChanged", roleRule, previousAdminRoleRule, newAdminRoleRule) - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - - event := new(BurnMintERC20RoleAdminChanged) - if err := _BurnMintERC20.contract.UnpackLog(event, "RoleAdminChanged", log); err != nil { - return err - } - event.Raw = log - - select { - case sink <- event: - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - } - }), nil -} - -func (_BurnMintERC20 *BurnMintERC20Filterer) ParseRoleAdminChanged(log types.Log) (*BurnMintERC20RoleAdminChanged, error) { - event := new(BurnMintERC20RoleAdminChanged) - if err := _BurnMintERC20.contract.UnpackLog(event, "RoleAdminChanged", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -type BurnMintERC20RoleGrantedIterator struct { - Event *BurnMintERC20RoleGranted - - contract *bind.BoundContract - event string - - logs chan types.Log - sub ethereum.Subscription - done bool - fail error -} - -func (it *BurnMintERC20RoleGrantedIterator) Next() bool { - - if it.fail != nil { - return false - } - - if it.done { - select { - case log := <-it.logs: - it.Event = new(BurnMintERC20RoleGranted) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - default: - return false - } - } - - select { - case log := <-it.logs: - it.Event = new(BurnMintERC20RoleGranted) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - case err := <-it.sub.Err(): - it.done = true - it.fail = err - return it.Next() - } -} - -func (it *BurnMintERC20RoleGrantedIterator) Error() error { - return it.fail -} - -func (it *BurnMintERC20RoleGrantedIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -type BurnMintERC20RoleGranted struct { - Role [32]byte - Account common.Address - Sender common.Address - Raw types.Log -} - -func (_BurnMintERC20 *BurnMintERC20Filterer) FilterRoleGranted(opts *bind.FilterOpts, role [][32]byte, account []common.Address, sender []common.Address) (*BurnMintERC20RoleGrantedIterator, error) { - - var roleRule []interface{} - for _, roleItem := range role { - roleRule = append(roleRule, roleItem) - } - var accountRule []interface{} - for _, accountItem := range account { - accountRule = append(accountRule, accountItem) - } - var senderRule []interface{} - for _, senderItem := range sender { - senderRule = append(senderRule, senderItem) - } - - logs, sub, err := _BurnMintERC20.contract.FilterLogs(opts, "RoleGranted", roleRule, accountRule, senderRule) - if err != nil { - return nil, err - } - return &BurnMintERC20RoleGrantedIterator{contract: _BurnMintERC20.contract, event: "RoleGranted", logs: logs, sub: sub}, nil -} - -func (_BurnMintERC20 *BurnMintERC20Filterer) WatchRoleGranted(opts *bind.WatchOpts, sink chan<- *BurnMintERC20RoleGranted, role [][32]byte, account []common.Address, sender []common.Address) (event.Subscription, error) { - - var roleRule []interface{} - for _, roleItem := range role { - roleRule = append(roleRule, roleItem) - } - var accountRule []interface{} - for _, accountItem := range account { - accountRule = append(accountRule, accountItem) - } - var senderRule []interface{} - for _, senderItem := range sender { - senderRule = append(senderRule, senderItem) - } - - logs, sub, err := _BurnMintERC20.contract.WatchLogs(opts, "RoleGranted", roleRule, accountRule, senderRule) - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - - event := new(BurnMintERC20RoleGranted) - if err := _BurnMintERC20.contract.UnpackLog(event, "RoleGranted", log); err != nil { - return err - } - event.Raw = log - - select { - case sink <- event: - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - } - }), nil -} - -func (_BurnMintERC20 *BurnMintERC20Filterer) ParseRoleGranted(log types.Log) (*BurnMintERC20RoleGranted, error) { - event := new(BurnMintERC20RoleGranted) - if err := _BurnMintERC20.contract.UnpackLog(event, "RoleGranted", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -type BurnMintERC20RoleRevokedIterator struct { - Event *BurnMintERC20RoleRevoked - - contract *bind.BoundContract - event string - - logs chan types.Log - sub ethereum.Subscription - done bool - fail error -} - -func (it *BurnMintERC20RoleRevokedIterator) Next() bool { - - if it.fail != nil { - return false - } - - if it.done { - select { - case log := <-it.logs: - it.Event = new(BurnMintERC20RoleRevoked) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - default: - return false - } - } - - select { - case log := <-it.logs: - it.Event = new(BurnMintERC20RoleRevoked) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - case err := <-it.sub.Err(): - it.done = true - it.fail = err - return it.Next() - } -} - -func (it *BurnMintERC20RoleRevokedIterator) Error() error { - return it.fail -} - -func (it *BurnMintERC20RoleRevokedIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -type BurnMintERC20RoleRevoked struct { - Role [32]byte - Account common.Address - Sender common.Address - Raw types.Log -} - -func (_BurnMintERC20 *BurnMintERC20Filterer) FilterRoleRevoked(opts *bind.FilterOpts, role [][32]byte, account []common.Address, sender []common.Address) (*BurnMintERC20RoleRevokedIterator, error) { - - var roleRule []interface{} - for _, roleItem := range role { - roleRule = append(roleRule, roleItem) - } - var accountRule []interface{} - for _, accountItem := range account { - accountRule = append(accountRule, accountItem) - } - var senderRule []interface{} - for _, senderItem := range sender { - senderRule = append(senderRule, senderItem) - } - - logs, sub, err := _BurnMintERC20.contract.FilterLogs(opts, "RoleRevoked", roleRule, accountRule, senderRule) - if err != nil { - return nil, err - } - return &BurnMintERC20RoleRevokedIterator{contract: _BurnMintERC20.contract, event: "RoleRevoked", logs: logs, sub: sub}, nil -} - -func (_BurnMintERC20 *BurnMintERC20Filterer) WatchRoleRevoked(opts *bind.WatchOpts, sink chan<- *BurnMintERC20RoleRevoked, role [][32]byte, account []common.Address, sender []common.Address) (event.Subscription, error) { - - var roleRule []interface{} - for _, roleItem := range role { - roleRule = append(roleRule, roleItem) - } - var accountRule []interface{} - for _, accountItem := range account { - accountRule = append(accountRule, accountItem) - } - var senderRule []interface{} - for _, senderItem := range sender { - senderRule = append(senderRule, senderItem) - } - - logs, sub, err := _BurnMintERC20.contract.WatchLogs(opts, "RoleRevoked", roleRule, accountRule, senderRule) - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - - event := new(BurnMintERC20RoleRevoked) - if err := _BurnMintERC20.contract.UnpackLog(event, "RoleRevoked", log); err != nil { - return err - } - event.Raw = log - - select { - case sink <- event: - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - } - }), nil -} - -func (_BurnMintERC20 *BurnMintERC20Filterer) ParseRoleRevoked(log types.Log) (*BurnMintERC20RoleRevoked, error) { - event := new(BurnMintERC20RoleRevoked) - if err := _BurnMintERC20.contract.UnpackLog(event, "RoleRevoked", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -type BurnMintERC20TransferIterator struct { - Event *BurnMintERC20Transfer - - contract *bind.BoundContract - event string - - logs chan types.Log - sub ethereum.Subscription - done bool - fail error -} - -func (it *BurnMintERC20TransferIterator) Next() bool { - - if it.fail != nil { - return false - } - - if it.done { - select { - case log := <-it.logs: - it.Event = new(BurnMintERC20Transfer) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - default: - return false - } - } - - select { - case log := <-it.logs: - it.Event = new(BurnMintERC20Transfer) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - case err := <-it.sub.Err(): - it.done = true - it.fail = err - return it.Next() - } -} - -func (it *BurnMintERC20TransferIterator) Error() error { - return it.fail -} - -func (it *BurnMintERC20TransferIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -type BurnMintERC20Transfer struct { - From common.Address - To common.Address - Value *big.Int - Raw types.Log -} - -func (_BurnMintERC20 *BurnMintERC20Filterer) FilterTransfer(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*BurnMintERC20TransferIterator, 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 := _BurnMintERC20.contract.FilterLogs(opts, "Transfer", fromRule, toRule) - if err != nil { - return nil, err - } - return &BurnMintERC20TransferIterator{contract: _BurnMintERC20.contract, event: "Transfer", logs: logs, sub: sub}, nil -} - -func (_BurnMintERC20 *BurnMintERC20Filterer) WatchTransfer(opts *bind.WatchOpts, sink chan<- *BurnMintERC20Transfer, 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 := _BurnMintERC20.contract.WatchLogs(opts, "Transfer", fromRule, toRule) - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - - event := new(BurnMintERC20Transfer) - if err := _BurnMintERC20.contract.UnpackLog(event, "Transfer", log); err != nil { - return err - } - event.Raw = log - - select { - case sink <- event: - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - } - }), nil -} - -func (_BurnMintERC20 *BurnMintERC20Filterer) ParseTransfer(log types.Log) (*BurnMintERC20Transfer, error) { - event := new(BurnMintERC20Transfer) - if err := _BurnMintERC20.contract.UnpackLog(event, "Transfer", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -func (_BurnMintERC20 *BurnMintERC20) ParseLog(log types.Log) (generated.AbigenLog, error) { - switch log.Topics[0] { - case _BurnMintERC20.abi.Events["Approval"].ID: - return _BurnMintERC20.ParseApproval(log) - case _BurnMintERC20.abi.Events["CCIPAdminTransferred"].ID: - return _BurnMintERC20.ParseCCIPAdminTransferred(log) - case _BurnMintERC20.abi.Events["RoleAdminChanged"].ID: - return _BurnMintERC20.ParseRoleAdminChanged(log) - case _BurnMintERC20.abi.Events["RoleGranted"].ID: - return _BurnMintERC20.ParseRoleGranted(log) - case _BurnMintERC20.abi.Events["RoleRevoked"].ID: - return _BurnMintERC20.ParseRoleRevoked(log) - case _BurnMintERC20.abi.Events["Transfer"].ID: - return _BurnMintERC20.ParseTransfer(log) - - default: - return nil, fmt.Errorf("abigen wrapper received unknown log topic: %v", log.Topics[0]) - } -} - -func (BurnMintERC20Approval) Topic() common.Hash { - return common.HexToHash("0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925") -} - -func (BurnMintERC20CCIPAdminTransferred) Topic() common.Hash { - return common.HexToHash("0x9524c9e4b0b61eb018dd58a1cd856e3e74009528328ab4a613b434fa631d7242") -} - -func (BurnMintERC20RoleAdminChanged) Topic() common.Hash { - return common.HexToHash("0xbd79b86ffe0ab8e8776151514217cd7cacd52c909f66475c3af44e129f0b00ff") -} - -func (BurnMintERC20RoleGranted) Topic() common.Hash { - return common.HexToHash("0x2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d") -} - -func (BurnMintERC20RoleRevoked) Topic() common.Hash { - return common.HexToHash("0xf6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b") -} - -func (BurnMintERC20Transfer) Topic() common.Hash { - return common.HexToHash("0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef") -} - -func (_BurnMintERC20 *BurnMintERC20) Address() common.Address { - return _BurnMintERC20.address -} - -type BurnMintERC20Interface interface { - BURNERROLE(opts *bind.CallOpts) ([32]byte, error) - - DEFAULTADMINROLE(opts *bind.CallOpts) ([32]byte, error) - - MINTERROLE(opts *bind.CallOpts) ([32]byte, error) - - Allowance(opts *bind.CallOpts, owner common.Address, spender common.Address) (*big.Int, error) - - BalanceOf(opts *bind.CallOpts, account common.Address) (*big.Int, error) - - Decimals(opts *bind.CallOpts) (uint8, error) - - GetCCIPAdmin(opts *bind.CallOpts) (common.Address, error) - - GetRoleAdmin(opts *bind.CallOpts, role [32]byte) ([32]byte, error) - - HasRole(opts *bind.CallOpts, role [32]byte, account common.Address) (bool, error) - - MaxSupply(opts *bind.CallOpts) (*big.Int, error) - - Name(opts *bind.CallOpts) (string, error) - - SupportsInterface(opts *bind.CallOpts, interfaceId [4]byte) (bool, error) - - Symbol(opts *bind.CallOpts) (string, error) - - TotalSupply(opts *bind.CallOpts) (*big.Int, error) - - Approve(opts *bind.TransactOpts, spender common.Address, amount *big.Int) (*types.Transaction, error) - - Burn(opts *bind.TransactOpts, amount *big.Int) (*types.Transaction, error) - - Burn0(opts *bind.TransactOpts, account common.Address, amount *big.Int) (*types.Transaction, error) - - BurnFrom(opts *bind.TransactOpts, account common.Address, amount *big.Int) (*types.Transaction, error) - - DecreaseAllowance(opts *bind.TransactOpts, spender common.Address, subtractedValue *big.Int) (*types.Transaction, error) - - GrantMintAndBurnRoles(opts *bind.TransactOpts, burnAndMinter common.Address) (*types.Transaction, error) - - GrantRole(opts *bind.TransactOpts, role [32]byte, account common.Address) (*types.Transaction, error) - - IncreaseAllowance(opts *bind.TransactOpts, spender common.Address, addedValue *big.Int) (*types.Transaction, error) - - Mint(opts *bind.TransactOpts, account common.Address, amount *big.Int) (*types.Transaction, error) - - RenounceRole(opts *bind.TransactOpts, role [32]byte, account common.Address) (*types.Transaction, error) - - RevokeRole(opts *bind.TransactOpts, role [32]byte, account common.Address) (*types.Transaction, error) - - SetCCIPAdmin(opts *bind.TransactOpts, newAdmin common.Address) (*types.Transaction, error) - - Transfer(opts *bind.TransactOpts, to common.Address, amount *big.Int) (*types.Transaction, error) - - TransferFrom(opts *bind.TransactOpts, from common.Address, to common.Address, amount *big.Int) (*types.Transaction, error) - - FilterApproval(opts *bind.FilterOpts, owner []common.Address, spender []common.Address) (*BurnMintERC20ApprovalIterator, error) - - WatchApproval(opts *bind.WatchOpts, sink chan<- *BurnMintERC20Approval, owner []common.Address, spender []common.Address) (event.Subscription, error) - - ParseApproval(log types.Log) (*BurnMintERC20Approval, error) - - FilterCCIPAdminTransferred(opts *bind.FilterOpts, previousAdmin []common.Address, newAdmin []common.Address) (*BurnMintERC20CCIPAdminTransferredIterator, error) - - WatchCCIPAdminTransferred(opts *bind.WatchOpts, sink chan<- *BurnMintERC20CCIPAdminTransferred, previousAdmin []common.Address, newAdmin []common.Address) (event.Subscription, error) - - ParseCCIPAdminTransferred(log types.Log) (*BurnMintERC20CCIPAdminTransferred, error) - - FilterRoleAdminChanged(opts *bind.FilterOpts, role [][32]byte, previousAdminRole [][32]byte, newAdminRole [][32]byte) (*BurnMintERC20RoleAdminChangedIterator, error) - - WatchRoleAdminChanged(opts *bind.WatchOpts, sink chan<- *BurnMintERC20RoleAdminChanged, role [][32]byte, previousAdminRole [][32]byte, newAdminRole [][32]byte) (event.Subscription, error) - - ParseRoleAdminChanged(log types.Log) (*BurnMintERC20RoleAdminChanged, error) - - FilterRoleGranted(opts *bind.FilterOpts, role [][32]byte, account []common.Address, sender []common.Address) (*BurnMintERC20RoleGrantedIterator, error) - - WatchRoleGranted(opts *bind.WatchOpts, sink chan<- *BurnMintERC20RoleGranted, role [][32]byte, account []common.Address, sender []common.Address) (event.Subscription, error) - - ParseRoleGranted(log types.Log) (*BurnMintERC20RoleGranted, error) - - FilterRoleRevoked(opts *bind.FilterOpts, role [][32]byte, account []common.Address, sender []common.Address) (*BurnMintERC20RoleRevokedIterator, error) - - WatchRoleRevoked(opts *bind.WatchOpts, sink chan<- *BurnMintERC20RoleRevoked, role [][32]byte, account []common.Address, sender []common.Address) (event.Subscription, error) - - ParseRoleRevoked(log types.Log) (*BurnMintERC20RoleRevoked, error) - - FilterTransfer(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*BurnMintERC20TransferIterator, error) - - WatchTransfer(opts *bind.WatchOpts, sink chan<- *BurnMintERC20Transfer, from []common.Address, to []common.Address) (event.Subscription, error) - - ParseTransfer(log types.Log) (*BurnMintERC20Transfer, error) - - ParseLog(log types.Log) (generated.AbigenLog, error) - - Address() common.Address -} diff --git a/core/gethwrappers/shared/generated/multicall3/multicall3.go b/core/gethwrappers/shared/generated/multicall3/multicall3.go deleted file mode 100644 index 91d612756b8..00000000000 --- a/core/gethwrappers/shared/generated/multicall3/multicall3.go +++ /dev/null @@ -1,525 +0,0 @@ -// Code generated - DO NOT EDIT. -// This file is a generated binding and any manual changes will be lost. - -package multicall3 - -import ( - "errors" - "math/big" - "strings" - - ethereum "github.com/ethereum/go-ethereum" - "github.com/ethereum/go-ethereum/accounts/abi" - "github.com/ethereum/go-ethereum/accounts/abi/bind" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/event" -) - -var ( - _ = errors.New - _ = big.NewInt - _ = strings.NewReader - _ = ethereum.NotFound - _ = bind.Bind - _ = common.Big1 - _ = types.BloomLookup - _ = event.NewSubscription - _ = abi.ConvertType -) - -type Multicall3Call struct { - Target common.Address - CallData []byte -} - -type Multicall3Call3 struct { - Target common.Address - AllowFailure bool - CallData []byte -} - -type Multicall3Call3Value struct { - Target common.Address - AllowFailure bool - Value *big.Int - CallData []byte -} - -type Multicall3Result struct { - Success bool - ReturnData []byte -} - -var Multicall3MetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"}],\"internalType\":\"structMulticall3.Call[]\",\"name\":\"calls\",\"type\":\"tuple[]\"}],\"name\":\"aggregate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"blockNumber\",\"type\":\"uint256\"},{\"internalType\":\"bytes[]\",\"name\":\"returnData\",\"type\":\"bytes[]\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"allowFailure\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"}],\"internalType\":\"structMulticall3.Call3[]\",\"name\":\"calls\",\"type\":\"tuple[]\"}],\"name\":\"aggregate3\",\"outputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"returnData\",\"type\":\"bytes\"}],\"internalType\":\"structMulticall3.Result[]\",\"name\":\"returnData\",\"type\":\"tuple[]\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"allowFailure\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"}],\"internalType\":\"structMulticall3.Call3Value[]\",\"name\":\"calls\",\"type\":\"tuple[]\"}],\"name\":\"aggregate3Value\",\"outputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"returnData\",\"type\":\"bytes\"}],\"internalType\":\"structMulticall3.Result[]\",\"name\":\"returnData\",\"type\":\"tuple[]\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"}],\"internalType\":\"structMulticall3.Call[]\",\"name\":\"calls\",\"type\":\"tuple[]\"}],\"name\":\"blockAndAggregate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"blockNumber\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"blockHash\",\"type\":\"bytes32\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"returnData\",\"type\":\"bytes\"}],\"internalType\":\"structMulticall3.Result[]\",\"name\":\"returnData\",\"type\":\"tuple[]\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getBasefee\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"basefee\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"blockNumber\",\"type\":\"uint256\"}],\"name\":\"getBlockHash\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"blockHash\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getBlockNumber\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"blockNumber\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getChainId\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"chainid\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getCurrentBlockCoinbase\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"coinbase\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getCurrentBlockDifficulty\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"difficulty\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getCurrentBlockGasLimit\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"gaslimit\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getCurrentBlockTimestamp\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"addr\",\"type\":\"address\"}],\"name\":\"getEthBalance\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"balance\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getLastBlockHash\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"blockHash\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bool\",\"name\":\"requireSuccess\",\"type\":\"bool\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"}],\"internalType\":\"structMulticall3.Call[]\",\"name\":\"calls\",\"type\":\"tuple[]\"}],\"name\":\"tryAggregate\",\"outputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"returnData\",\"type\":\"bytes\"}],\"internalType\":\"structMulticall3.Result[]\",\"name\":\"returnData\",\"type\":\"tuple[]\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bool\",\"name\":\"requireSuccess\",\"type\":\"bool\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"}],\"internalType\":\"structMulticall3.Call[]\",\"name\":\"calls\",\"type\":\"tuple[]\"}],\"name\":\"tryBlockAndAggregate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"blockNumber\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"blockHash\",\"type\":\"bytes32\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"returnData\",\"type\":\"bytes\"}],\"internalType\":\"structMulticall3.Result[]\",\"name\":\"returnData\",\"type\":\"tuple[]\"}],\"stateMutability\":\"payable\",\"type\":\"function\"}]", - Bin: "0x608060405234801561001057600080fd5b50610eb0806100206000396000f3fe6080604052600436106100f35760003560e01c80634d2301cc1161008a578063a8b0574e11610059578063a8b0574e1461025a578063bce38bd714610275578063c3077fa914610288578063ee82ac5e1461029b57600080fd5b80634d2301cc146101ec57806372425d9d1461022157806382ad56cb1461023457806386d516e81461024757600080fd5b80633408e470116100c65780633408e47014610191578063399542e9146101a45780633e64a696146101c657806342cbb15c146101d957600080fd5b80630f28c97d146100f8578063174dea711461011a578063252dba421461013a57806327e86d6e1461015b575b600080fd5b34801561010457600080fd5b50425b6040519081526020015b60405180910390f35b61012d610128366004610a85565b6102ba565b6040516101119190610bb7565b61014d610148366004610a85565b6104ef565b604051610111929190610bd1565b34801561016757600080fd5b50437fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0140610107565b34801561019d57600080fd5b5046610107565b6101b76101b2366004610c59565b610690565b60405161011193929190610cb3565b3480156101d257600080fd5b5048610107565b3480156101e557600080fd5b5043610107565b3480156101f857600080fd5b50610107610207366004610cdb565b73ffffffffffffffffffffffffffffffffffffffff163190565b34801561022d57600080fd5b5044610107565b61012d610242366004610a85565b6106ab565b34801561025357600080fd5b5045610107565b34801561026657600080fd5b50604051418152602001610111565b61012d610283366004610c59565b61085a565b6101b7610296366004610a85565b610a1a565b3480156102a757600080fd5b506101076102b6366004610d11565b4090565b60606000828067ffffffffffffffff8111156102d8576102d8610d2a565b60405190808252806020026020018201604052801561031e57816020015b6040805180820190915260008152606060208201528152602001906001900390816102f65790505b5092503660005b8281101561047757600085828151811061034157610341610d59565b6020026020010151905087878381811061035d5761035d610d59565b905060200281019061036f9190610d88565b6040810135958601959093506103886020850185610cdb565b73ffffffffffffffffffffffffffffffffffffffff16816103ac6060870187610dc6565b6040516103ba929190610e2b565b60006040518083038185875af1925050503d80600081146103f7576040519150601f19603f3d011682016040523d82523d6000602084013e6103fc565b606091505b50602080850191909152901515808452908501351761046d577f08c379a000000000000000000000000000000000000000000000000000000000600052602060045260176024527f4d756c746963616c6c333a2063616c6c206661696c656400000000000000000060445260846000fd5b5050600101610325565b508234146104e6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f4d756c746963616c6c333a2076616c7565206d69736d6174636800000000000060448201526064015b60405180910390fd5b50505092915050565b436060828067ffffffffffffffff81111561050c5761050c610d2a565b60405190808252806020026020018201604052801561053f57816020015b606081526020019060019003908161052a5790505b5091503660005b8281101561068657600087878381811061056257610562610d59565b90506020028101906105749190610e3b565b92506105836020840184610cdb565b73ffffffffffffffffffffffffffffffffffffffff166105a66020850185610dc6565b6040516105b4929190610e2b565b6000604051808303816000865af19150503d80600081146105f1576040519150601f19603f3d011682016040523d82523d6000602084013e6105f6565b606091505b5086848151811061060957610609610d59565b602090810291909101015290508061067d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f4d756c746963616c6c333a2063616c6c206661696c656400000000000000000060448201526064016104dd565b50600101610546565b5050509250929050565b43804060606106a086868661085a565b905093509350939050565b6060818067ffffffffffffffff8111156106c7576106c7610d2a565b60405190808252806020026020018201604052801561070d57816020015b6040805180820190915260008152606060208201528152602001906001900390816106e55790505b5091503660005b828110156104e657600084828151811061073057610730610d59565b6020026020010151905086868381811061074c5761074c610d59565b905060200281019061075e9190610e6f565b925061076d6020840184610cdb565b73ffffffffffffffffffffffffffffffffffffffff166107906040850185610dc6565b60405161079e929190610e2b565b6000604051808303816000865af19150503d80600081146107db576040519150601f19603f3d011682016040523d82523d6000602084013e6107e0565b606091505b506020808401919091529015158083529084013517610851577f08c379a000000000000000000000000000000000000000000000000000000000600052602060045260176024527f4d756c746963616c6c333a2063616c6c206661696c656400000000000000000060445260646000fd5b50600101610714565b6060818067ffffffffffffffff81111561087657610876610d2a565b6040519080825280602002602001820160405280156108bc57816020015b6040805180820190915260008152606060208201528152602001906001900390816108945790505b5091503660005b82811015610a105760008482815181106108df576108df610d59565b602002602001015190508686838181106108fb576108fb610d59565b905060200281019061090d9190610e3b565b925061091c6020840184610cdb565b73ffffffffffffffffffffffffffffffffffffffff1661093f6020850185610dc6565b60405161094d929190610e2b565b6000604051808303816000865af19150503d806000811461098a576040519150601f19603f3d011682016040523d82523d6000602084013e61098f565b606091505b506020830152151581528715610a07578051610a07576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f4d756c746963616c6c333a2063616c6c206661696c656400000000000000000060448201526064016104dd565b506001016108c3565b5050509392505050565b6000806060610a2b60018686610690565b919790965090945092505050565b60008083601f840112610a4b57600080fd5b50813567ffffffffffffffff811115610a6357600080fd5b6020830191508360208260051b8501011115610a7e57600080fd5b9250929050565b60008060208385031215610a9857600080fd5b823567ffffffffffffffff811115610aaf57600080fd5b610abb85828601610a39565b90969095509350505050565b6000815180845260005b81811015610aed57602081850181015186830182015201610ad1565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b600082825180855260208086019550808260051b84010181860160005b84811015610baa578583037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe001895281518051151584528401516040858501819052610b9681860183610ac7565b9a86019a9450505090830190600101610b48565b5090979650505050505050565b602081526000610bca6020830184610b2b565b9392505050565b600060408201848352602060408185015281855180845260608601915060608160051b870101935082870160005b82811015610c4b577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa0888703018452610c39868351610ac7565b95509284019290840190600101610bff565b509398975050505050505050565b600080600060408486031215610c6e57600080fd5b83358015158114610c7e57600080fd5b9250602084013567ffffffffffffffff811115610c9a57600080fd5b610ca686828701610a39565b9497909650939450505050565b838152826020820152606060408201526000610cd26060830184610b2b565b95945050505050565b600060208284031215610ced57600080fd5b813573ffffffffffffffffffffffffffffffffffffffff81168114610bca57600080fd5b600060208284031215610d2357600080fd5b5035919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81833603018112610dbc57600080fd5b9190910192915050565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112610dfb57600080fd5b83018035915067ffffffffffffffff821115610e1657600080fd5b602001915036819003821315610a7e57600080fd5b8183823760009101908152919050565b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc1833603018112610dbc57600080fd5b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa1833603018112610dbc57600080fdfea164736f6c6343000813000a", -} - -var Multicall3ABI = Multicall3MetaData.ABI - -var Multicall3Bin = Multicall3MetaData.Bin - -func DeployMulticall3(auth *bind.TransactOpts, backend bind.ContractBackend) (common.Address, *types.Transaction, *Multicall3, error) { - parsed, err := Multicall3MetaData.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(Multicall3Bin), backend) - if err != nil { - return common.Address{}, nil, nil, err - } - return address, tx, &Multicall3{address: address, abi: *parsed, Multicall3Caller: Multicall3Caller{contract: contract}, Multicall3Transactor: Multicall3Transactor{contract: contract}, Multicall3Filterer: Multicall3Filterer{contract: contract}}, nil -} - -type Multicall3 struct { - address common.Address - abi abi.ABI - Multicall3Caller - Multicall3Transactor - Multicall3Filterer -} - -type Multicall3Caller struct { - contract *bind.BoundContract -} - -type Multicall3Transactor struct { - contract *bind.BoundContract -} - -type Multicall3Filterer struct { - contract *bind.BoundContract -} - -type Multicall3Session struct { - Contract *Multicall3 - CallOpts bind.CallOpts - TransactOpts bind.TransactOpts -} - -type Multicall3CallerSession struct { - Contract *Multicall3Caller - CallOpts bind.CallOpts -} - -type Multicall3TransactorSession struct { - Contract *Multicall3Transactor - TransactOpts bind.TransactOpts -} - -type Multicall3Raw struct { - Contract *Multicall3 -} - -type Multicall3CallerRaw struct { - Contract *Multicall3Caller -} - -type Multicall3TransactorRaw struct { - Contract *Multicall3Transactor -} - -func NewMulticall3(address common.Address, backend bind.ContractBackend) (*Multicall3, error) { - abi, err := abi.JSON(strings.NewReader(Multicall3ABI)) - if err != nil { - return nil, err - } - contract, err := bindMulticall3(address, backend, backend, backend) - if err != nil { - return nil, err - } - return &Multicall3{address: address, abi: abi, Multicall3Caller: Multicall3Caller{contract: contract}, Multicall3Transactor: Multicall3Transactor{contract: contract}, Multicall3Filterer: Multicall3Filterer{contract: contract}}, nil -} - -func NewMulticall3Caller(address common.Address, caller bind.ContractCaller) (*Multicall3Caller, error) { - contract, err := bindMulticall3(address, caller, nil, nil) - if err != nil { - return nil, err - } - return &Multicall3Caller{contract: contract}, nil -} - -func NewMulticall3Transactor(address common.Address, transactor bind.ContractTransactor) (*Multicall3Transactor, error) { - contract, err := bindMulticall3(address, nil, transactor, nil) - if err != nil { - return nil, err - } - return &Multicall3Transactor{contract: contract}, nil -} - -func NewMulticall3Filterer(address common.Address, filterer bind.ContractFilterer) (*Multicall3Filterer, error) { - contract, err := bindMulticall3(address, nil, nil, filterer) - if err != nil { - return nil, err - } - return &Multicall3Filterer{contract: contract}, nil -} - -func bindMulticall3(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { - parsed, err := Multicall3MetaData.GetAbi() - if err != nil { - return nil, err - } - return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil -} - -func (_Multicall3 *Multicall3Raw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { - return _Multicall3.Contract.Multicall3Caller.contract.Call(opts, result, method, params...) -} - -func (_Multicall3 *Multicall3Raw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { - return _Multicall3.Contract.Multicall3Transactor.contract.Transfer(opts) -} - -func (_Multicall3 *Multicall3Raw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { - return _Multicall3.Contract.Multicall3Transactor.contract.Transact(opts, method, params...) -} - -func (_Multicall3 *Multicall3CallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { - return _Multicall3.Contract.contract.Call(opts, result, method, params...) -} - -func (_Multicall3 *Multicall3TransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { - return _Multicall3.Contract.contract.Transfer(opts) -} - -func (_Multicall3 *Multicall3TransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { - return _Multicall3.Contract.contract.Transact(opts, method, params...) -} - -func (_Multicall3 *Multicall3Caller) GetBasefee(opts *bind.CallOpts) (*big.Int, error) { - var out []interface{} - err := _Multicall3.contract.Call(opts, &out, "getBasefee") - - if err != nil { - return *new(*big.Int), err - } - - out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) - - return out0, err - -} - -func (_Multicall3 *Multicall3Session) GetBasefee() (*big.Int, error) { - return _Multicall3.Contract.GetBasefee(&_Multicall3.CallOpts) -} - -func (_Multicall3 *Multicall3CallerSession) GetBasefee() (*big.Int, error) { - return _Multicall3.Contract.GetBasefee(&_Multicall3.CallOpts) -} - -func (_Multicall3 *Multicall3Caller) GetBlockHash(opts *bind.CallOpts, blockNumber *big.Int) ([32]byte, error) { - var out []interface{} - err := _Multicall3.contract.Call(opts, &out, "getBlockHash", blockNumber) - - if err != nil { - return *new([32]byte), err - } - - out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) - - return out0, err - -} - -func (_Multicall3 *Multicall3Session) GetBlockHash(blockNumber *big.Int) ([32]byte, error) { - return _Multicall3.Contract.GetBlockHash(&_Multicall3.CallOpts, blockNumber) -} - -func (_Multicall3 *Multicall3CallerSession) GetBlockHash(blockNumber *big.Int) ([32]byte, error) { - return _Multicall3.Contract.GetBlockHash(&_Multicall3.CallOpts, blockNumber) -} - -func (_Multicall3 *Multicall3Caller) GetBlockNumber(opts *bind.CallOpts) (*big.Int, error) { - var out []interface{} - err := _Multicall3.contract.Call(opts, &out, "getBlockNumber") - - if err != nil { - return *new(*big.Int), err - } - - out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) - - return out0, err - -} - -func (_Multicall3 *Multicall3Session) GetBlockNumber() (*big.Int, error) { - return _Multicall3.Contract.GetBlockNumber(&_Multicall3.CallOpts) -} - -func (_Multicall3 *Multicall3CallerSession) GetBlockNumber() (*big.Int, error) { - return _Multicall3.Contract.GetBlockNumber(&_Multicall3.CallOpts) -} - -func (_Multicall3 *Multicall3Caller) GetChainId(opts *bind.CallOpts) (*big.Int, error) { - var out []interface{} - err := _Multicall3.contract.Call(opts, &out, "getChainId") - - if err != nil { - return *new(*big.Int), err - } - - out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) - - return out0, err - -} - -func (_Multicall3 *Multicall3Session) GetChainId() (*big.Int, error) { - return _Multicall3.Contract.GetChainId(&_Multicall3.CallOpts) -} - -func (_Multicall3 *Multicall3CallerSession) GetChainId() (*big.Int, error) { - return _Multicall3.Contract.GetChainId(&_Multicall3.CallOpts) -} - -func (_Multicall3 *Multicall3Caller) GetCurrentBlockCoinbase(opts *bind.CallOpts) (common.Address, error) { - var out []interface{} - err := _Multicall3.contract.Call(opts, &out, "getCurrentBlockCoinbase") - - if err != nil { - return *new(common.Address), err - } - - out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) - - return out0, err - -} - -func (_Multicall3 *Multicall3Session) GetCurrentBlockCoinbase() (common.Address, error) { - return _Multicall3.Contract.GetCurrentBlockCoinbase(&_Multicall3.CallOpts) -} - -func (_Multicall3 *Multicall3CallerSession) GetCurrentBlockCoinbase() (common.Address, error) { - return _Multicall3.Contract.GetCurrentBlockCoinbase(&_Multicall3.CallOpts) -} - -func (_Multicall3 *Multicall3Caller) GetCurrentBlockDifficulty(opts *bind.CallOpts) (*big.Int, error) { - var out []interface{} - err := _Multicall3.contract.Call(opts, &out, "getCurrentBlockDifficulty") - - if err != nil { - return *new(*big.Int), err - } - - out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) - - return out0, err - -} - -func (_Multicall3 *Multicall3Session) GetCurrentBlockDifficulty() (*big.Int, error) { - return _Multicall3.Contract.GetCurrentBlockDifficulty(&_Multicall3.CallOpts) -} - -func (_Multicall3 *Multicall3CallerSession) GetCurrentBlockDifficulty() (*big.Int, error) { - return _Multicall3.Contract.GetCurrentBlockDifficulty(&_Multicall3.CallOpts) -} - -func (_Multicall3 *Multicall3Caller) GetCurrentBlockGasLimit(opts *bind.CallOpts) (*big.Int, error) { - var out []interface{} - err := _Multicall3.contract.Call(opts, &out, "getCurrentBlockGasLimit") - - if err != nil { - return *new(*big.Int), err - } - - out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) - - return out0, err - -} - -func (_Multicall3 *Multicall3Session) GetCurrentBlockGasLimit() (*big.Int, error) { - return _Multicall3.Contract.GetCurrentBlockGasLimit(&_Multicall3.CallOpts) -} - -func (_Multicall3 *Multicall3CallerSession) GetCurrentBlockGasLimit() (*big.Int, error) { - return _Multicall3.Contract.GetCurrentBlockGasLimit(&_Multicall3.CallOpts) -} - -func (_Multicall3 *Multicall3Caller) GetCurrentBlockTimestamp(opts *bind.CallOpts) (*big.Int, error) { - var out []interface{} - err := _Multicall3.contract.Call(opts, &out, "getCurrentBlockTimestamp") - - if err != nil { - return *new(*big.Int), err - } - - out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) - - return out0, err - -} - -func (_Multicall3 *Multicall3Session) GetCurrentBlockTimestamp() (*big.Int, error) { - return _Multicall3.Contract.GetCurrentBlockTimestamp(&_Multicall3.CallOpts) -} - -func (_Multicall3 *Multicall3CallerSession) GetCurrentBlockTimestamp() (*big.Int, error) { - return _Multicall3.Contract.GetCurrentBlockTimestamp(&_Multicall3.CallOpts) -} - -func (_Multicall3 *Multicall3Caller) GetEthBalance(opts *bind.CallOpts, addr common.Address) (*big.Int, error) { - var out []interface{} - err := _Multicall3.contract.Call(opts, &out, "getEthBalance", addr) - - if err != nil { - return *new(*big.Int), err - } - - out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) - - return out0, err - -} - -func (_Multicall3 *Multicall3Session) GetEthBalance(addr common.Address) (*big.Int, error) { - return _Multicall3.Contract.GetEthBalance(&_Multicall3.CallOpts, addr) -} - -func (_Multicall3 *Multicall3CallerSession) GetEthBalance(addr common.Address) (*big.Int, error) { - return _Multicall3.Contract.GetEthBalance(&_Multicall3.CallOpts, addr) -} - -func (_Multicall3 *Multicall3Caller) GetLastBlockHash(opts *bind.CallOpts) ([32]byte, error) { - var out []interface{} - err := _Multicall3.contract.Call(opts, &out, "getLastBlockHash") - - if err != nil { - return *new([32]byte), err - } - - out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) - - return out0, err - -} - -func (_Multicall3 *Multicall3Session) GetLastBlockHash() ([32]byte, error) { - return _Multicall3.Contract.GetLastBlockHash(&_Multicall3.CallOpts) -} - -func (_Multicall3 *Multicall3CallerSession) GetLastBlockHash() ([32]byte, error) { - return _Multicall3.Contract.GetLastBlockHash(&_Multicall3.CallOpts) -} - -func (_Multicall3 *Multicall3Transactor) Aggregate(opts *bind.TransactOpts, calls []Multicall3Call) (*types.Transaction, error) { - return _Multicall3.contract.Transact(opts, "aggregate", calls) -} - -func (_Multicall3 *Multicall3Session) Aggregate(calls []Multicall3Call) (*types.Transaction, error) { - return _Multicall3.Contract.Aggregate(&_Multicall3.TransactOpts, calls) -} - -func (_Multicall3 *Multicall3TransactorSession) Aggregate(calls []Multicall3Call) (*types.Transaction, error) { - return _Multicall3.Contract.Aggregate(&_Multicall3.TransactOpts, calls) -} - -func (_Multicall3 *Multicall3Transactor) Aggregate3(opts *bind.TransactOpts, calls []Multicall3Call3) (*types.Transaction, error) { - return _Multicall3.contract.Transact(opts, "aggregate3", calls) -} - -func (_Multicall3 *Multicall3Session) Aggregate3(calls []Multicall3Call3) (*types.Transaction, error) { - return _Multicall3.Contract.Aggregate3(&_Multicall3.TransactOpts, calls) -} - -func (_Multicall3 *Multicall3TransactorSession) Aggregate3(calls []Multicall3Call3) (*types.Transaction, error) { - return _Multicall3.Contract.Aggregate3(&_Multicall3.TransactOpts, calls) -} - -func (_Multicall3 *Multicall3Transactor) Aggregate3Value(opts *bind.TransactOpts, calls []Multicall3Call3Value) (*types.Transaction, error) { - return _Multicall3.contract.Transact(opts, "aggregate3Value", calls) -} - -func (_Multicall3 *Multicall3Session) Aggregate3Value(calls []Multicall3Call3Value) (*types.Transaction, error) { - return _Multicall3.Contract.Aggregate3Value(&_Multicall3.TransactOpts, calls) -} - -func (_Multicall3 *Multicall3TransactorSession) Aggregate3Value(calls []Multicall3Call3Value) (*types.Transaction, error) { - return _Multicall3.Contract.Aggregate3Value(&_Multicall3.TransactOpts, calls) -} - -func (_Multicall3 *Multicall3Transactor) BlockAndAggregate(opts *bind.TransactOpts, calls []Multicall3Call) (*types.Transaction, error) { - return _Multicall3.contract.Transact(opts, "blockAndAggregate", calls) -} - -func (_Multicall3 *Multicall3Session) BlockAndAggregate(calls []Multicall3Call) (*types.Transaction, error) { - return _Multicall3.Contract.BlockAndAggregate(&_Multicall3.TransactOpts, calls) -} - -func (_Multicall3 *Multicall3TransactorSession) BlockAndAggregate(calls []Multicall3Call) (*types.Transaction, error) { - return _Multicall3.Contract.BlockAndAggregate(&_Multicall3.TransactOpts, calls) -} - -func (_Multicall3 *Multicall3Transactor) TryAggregate(opts *bind.TransactOpts, requireSuccess bool, calls []Multicall3Call) (*types.Transaction, error) { - return _Multicall3.contract.Transact(opts, "tryAggregate", requireSuccess, calls) -} - -func (_Multicall3 *Multicall3Session) TryAggregate(requireSuccess bool, calls []Multicall3Call) (*types.Transaction, error) { - return _Multicall3.Contract.TryAggregate(&_Multicall3.TransactOpts, requireSuccess, calls) -} - -func (_Multicall3 *Multicall3TransactorSession) TryAggregate(requireSuccess bool, calls []Multicall3Call) (*types.Transaction, error) { - return _Multicall3.Contract.TryAggregate(&_Multicall3.TransactOpts, requireSuccess, calls) -} - -func (_Multicall3 *Multicall3Transactor) TryBlockAndAggregate(opts *bind.TransactOpts, requireSuccess bool, calls []Multicall3Call) (*types.Transaction, error) { - return _Multicall3.contract.Transact(opts, "tryBlockAndAggregate", requireSuccess, calls) -} - -func (_Multicall3 *Multicall3Session) TryBlockAndAggregate(requireSuccess bool, calls []Multicall3Call) (*types.Transaction, error) { - return _Multicall3.Contract.TryBlockAndAggregate(&_Multicall3.TransactOpts, requireSuccess, calls) -} - -func (_Multicall3 *Multicall3TransactorSession) TryBlockAndAggregate(requireSuccess bool, calls []Multicall3Call) (*types.Transaction, error) { - return _Multicall3.Contract.TryBlockAndAggregate(&_Multicall3.TransactOpts, requireSuccess, calls) -} - -func (_Multicall3 *Multicall3) Address() common.Address { - return _Multicall3.address -} - -type Multicall3Interface interface { - GetBasefee(opts *bind.CallOpts) (*big.Int, error) - - GetBlockHash(opts *bind.CallOpts, blockNumber *big.Int) ([32]byte, error) - - GetBlockNumber(opts *bind.CallOpts) (*big.Int, error) - - GetChainId(opts *bind.CallOpts) (*big.Int, error) - - GetCurrentBlockCoinbase(opts *bind.CallOpts) (common.Address, error) - - GetCurrentBlockDifficulty(opts *bind.CallOpts) (*big.Int, error) - - GetCurrentBlockGasLimit(opts *bind.CallOpts) (*big.Int, error) - - GetCurrentBlockTimestamp(opts *bind.CallOpts) (*big.Int, error) - - GetEthBalance(opts *bind.CallOpts, addr common.Address) (*big.Int, error) - - GetLastBlockHash(opts *bind.CallOpts) ([32]byte, error) - - Aggregate(opts *bind.TransactOpts, calls []Multicall3Call) (*types.Transaction, error) - - Aggregate3(opts *bind.TransactOpts, calls []Multicall3Call3) (*types.Transaction, error) - - Aggregate3Value(opts *bind.TransactOpts, calls []Multicall3Call3Value) (*types.Transaction, error) - - BlockAndAggregate(opts *bind.TransactOpts, calls []Multicall3Call) (*types.Transaction, error) - - TryAggregate(opts *bind.TransactOpts, requireSuccess bool, calls []Multicall3Call) (*types.Transaction, error) - - TryBlockAndAggregate(opts *bind.TransactOpts, requireSuccess bool, calls []Multicall3Call) (*types.Transaction, error) - - Address() common.Address -} diff --git a/core/gethwrappers/shared/generation/generated-wrapper-dependency-versions-do-not-edit.txt b/core/gethwrappers/shared/generation/generated-wrapper-dependency-versions-do-not-edit.txt index 470cd477fe0..6c0f572e460 100644 --- a/core/gethwrappers/shared/generation/generated-wrapper-dependency-versions-do-not-edit.txt +++ b/core/gethwrappers/shared/generation/generated-wrapper-dependency-versions-do-not-edit.txt @@ -1,7 +1,5 @@ GETH_VERSION: 1.14.11 -burn_mint_erc20: ../../../contracts/solc/v0.8.19/BurnMintERC20/BurnMintERC20.abi ../../../contracts/solc/v0.8.19/BurnMintERC20/BurnMintERC20.bin 9faa5e698c31f771907d9e8404f95fa33b61ecc18ca02cb379836206566331a5 burn_mint_erc677: ../../../contracts/solc/v0.8.19/BurnMintERC677/BurnMintERC677.abi ../../../contracts/solc/v0.8.19/BurnMintERC677/BurnMintERC677.bin 405c9016171e614b17e10588653ef8d33dcea21dd569c3fddc596a46fcff68a3 erc20: ../../../contracts/solc/v0.8.19/ERC20/ERC20.abi ../../../contracts/solc/v0.8.19/ERC20/ERC20.bin 5b1a93d9b24f250e49a730c96335a8113c3f7010365cba578f313b483001d4fc link_token: ../../../contracts/solc/v0.8.19/LinkToken/LinkToken.abi ../../../contracts/solc/v0.8.19/LinkToken/LinkToken.bin c0ef9b507103aae541ebc31d87d051c2764ba9d843076b30ec505d37cdfffaba -multicall3: ../../../contracts/solc/v0.8.19/Multicall3/Multicall3.abi ../../../contracts/solc/v0.8.19/Multicall3/Multicall3.bin 66fff7368bbd7dfe1cb20d31cf29efa917a24cf5344e2d79b34994b8c3b9530a werc20_mock: ../../../contracts/solc/v0.8.19/WERC20Mock/WERC20Mock.abi ../../../contracts/solc/v0.8.19/WERC20Mock/WERC20Mock.bin ff2ca3928b2aa9c412c892cb8226c4d754c73eeb291bb7481c32c48791b2aa94 diff --git a/core/gethwrappers/shared/go_generate.go b/core/gethwrappers/shared/go_generate.go index 7fe9d6a8ef2..6f3bead7d6b 100644 --- a/core/gethwrappers/shared/go_generate.go +++ b/core/gethwrappers/shared/go_generate.go @@ -4,7 +4,5 @@ package gethwrappers //go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.19/BurnMintERC677/BurnMintERC677.abi ../../../contracts/solc/v0.8.19/BurnMintERC677/BurnMintERC677.bin BurnMintERC677 burn_mint_erc677 //go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.19/LinkToken/LinkToken.abi ../../../contracts/solc/v0.8.19/LinkToken/LinkToken.bin LinkToken link_token -//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.19/BurnMintERC20/BurnMintERC20.abi ../../../contracts/solc/v0.8.19/BurnMintERC20/BurnMintERC20.bin BurnMintERC20 burn_mint_erc20 //go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.19/ERC20/ERC20.abi ../../../contracts/solc/v0.8.19/ERC20/ERC20.bin ERC20 erc20 //go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.19/WERC20Mock/WERC20Mock.abi ../../../contracts/solc/v0.8.19/WERC20Mock/WERC20Mock.bin WERC20Mock werc20_mock -//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.19/Multicall3/Multicall3.abi ../../../contracts/solc/v0.8.19/Multicall3/Multicall3.bin Multicall3 multicall3 diff --git a/core/gethwrappers/transmission/generated/entry_point/entry_point.go b/core/gethwrappers/transmission/generated/entry_point/entry_point.go new file mode 100644 index 00000000000..5a22214cb0e --- /dev/null +++ b/core/gethwrappers/transmission/generated/entry_point/entry_point.go @@ -0,0 +1,1871 @@ +// Code generated - DO NOT EDIT. +// This file is a generated binding and any manual changes will be lost. + +package entry_point + +import ( + "errors" + "fmt" + "math/big" + "strings" + + ethereum "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/event" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated" +) + +var ( + _ = errors.New + _ = big.NewInt + _ = strings.NewReader + _ = ethereum.NotFound + _ = bind.Bind + _ = common.Big1 + _ = types.BloomLookup + _ = event.NewSubscription + _ = abi.ConvertType +) + +type EntryPointMemoryUserOp struct { + Sender common.Address + Nonce *big.Int + CallGasLimit *big.Int + VerificationGasLimit *big.Int + PreVerificationGas *big.Int + Paymaster common.Address + MaxFeePerGas *big.Int + MaxPriorityFeePerGas *big.Int +} + +type EntryPointUserOpInfo struct { + MUserOp EntryPointMemoryUserOp + UserOpHash [32]byte + Prefund *big.Int + ContextOffset *big.Int + PreOpGas *big.Int +} + +type IEntryPointUserOpsPerAggregator struct { + UserOps []UserOperation + Aggregator common.Address + Signature []byte +} + +type IStakeManagerDepositInfo struct { + Deposit *big.Int + Staked bool + Stake *big.Int + UnstakeDelaySec uint32 + WithdrawTime *big.Int +} + +type UserOperation struct { + Sender common.Address + Nonce *big.Int + InitCode []byte + CallData []byte + CallGasLimit *big.Int + VerificationGasLimit *big.Int + PreVerificationGas *big.Int + MaxFeePerGas *big.Int + MaxPriorityFeePerGas *big.Int + PaymasterAndData []byte + Signature []byte +} + +var EntryPointMetaData = &bind.MetaData{ + ABI: "[{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"preOpGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"paid\",\"type\":\"uint256\"},{\"internalType\":\"uint48\",\"name\":\"validAfter\",\"type\":\"uint48\"},{\"internalType\":\"uint48\",\"name\":\"validUntil\",\"type\":\"uint48\"},{\"internalType\":\"bool\",\"name\":\"targetSuccess\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"targetResult\",\"type\":\"bytes\"}],\"name\":\"ExecutionResult\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"opIndex\",\"type\":\"uint256\"},{\"internalType\":\"string\",\"name\":\"reason\",\"type\":\"string\"}],\"name\":\"FailedOp\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"SenderAddressResult\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"aggregator\",\"type\":\"address\"}],\"name\":\"SignatureValidationFailed\",\"type\":\"error\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"preOpGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"prefund\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"sigFailed\",\"type\":\"bool\"},{\"internalType\":\"uint48\",\"name\":\"validAfter\",\"type\":\"uint48\"},{\"internalType\":\"uint48\",\"name\":\"validUntil\",\"type\":\"uint48\"},{\"internalType\":\"bytes\",\"name\":\"paymasterContext\",\"type\":\"bytes\"}],\"internalType\":\"structIEntryPoint.ReturnInfo\",\"name\":\"returnInfo\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"stake\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"unstakeDelaySec\",\"type\":\"uint256\"}],\"internalType\":\"structIStakeManager.StakeInfo\",\"name\":\"senderInfo\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"stake\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"unstakeDelaySec\",\"type\":\"uint256\"}],\"internalType\":\"structIStakeManager.StakeInfo\",\"name\":\"factoryInfo\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"stake\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"unstakeDelaySec\",\"type\":\"uint256\"}],\"internalType\":\"structIStakeManager.StakeInfo\",\"name\":\"paymasterInfo\",\"type\":\"tuple\"}],\"name\":\"ValidationResult\",\"type\":\"error\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"preOpGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"prefund\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"sigFailed\",\"type\":\"bool\"},{\"internalType\":\"uint48\",\"name\":\"validAfter\",\"type\":\"uint48\"},{\"internalType\":\"uint48\",\"name\":\"validUntil\",\"type\":\"uint48\"},{\"internalType\":\"bytes\",\"name\":\"paymasterContext\",\"type\":\"bytes\"}],\"internalType\":\"structIEntryPoint.ReturnInfo\",\"name\":\"returnInfo\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"stake\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"unstakeDelaySec\",\"type\":\"uint256\"}],\"internalType\":\"structIStakeManager.StakeInfo\",\"name\":\"senderInfo\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"stake\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"unstakeDelaySec\",\"type\":\"uint256\"}],\"internalType\":\"structIStakeManager.StakeInfo\",\"name\":\"factoryInfo\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"stake\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"unstakeDelaySec\",\"type\":\"uint256\"}],\"internalType\":\"structIStakeManager.StakeInfo\",\"name\":\"paymasterInfo\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"aggregator\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"stake\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"unstakeDelaySec\",\"type\":\"uint256\"}],\"internalType\":\"structIStakeManager.StakeInfo\",\"name\":\"stakeInfo\",\"type\":\"tuple\"}],\"internalType\":\"structIEntryPoint.AggregatorStakeInfo\",\"name\":\"aggregatorInfo\",\"type\":\"tuple\"}],\"name\":\"ValidationResultWithAggregation\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"userOpHash\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"factory\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"paymaster\",\"type\":\"address\"}],\"name\":\"AccountDeployed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"totalDeposit\",\"type\":\"uint256\"}],\"name\":\"Deposited\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"aggregator\",\"type\":\"address\"}],\"name\":\"SignatureAggregatorChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"totalStaked\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"unstakeDelaySec\",\"type\":\"uint256\"}],\"name\":\"StakeLocked\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"withdrawTime\",\"type\":\"uint256\"}],\"name\":\"StakeUnlocked\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"withdrawAddress\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"StakeWithdrawn\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"userOpHash\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"paymaster\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"actualGasCost\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"actualGasUsed\",\"type\":\"uint256\"}],\"name\":\"UserOperationEvent\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"userOpHash\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"revertReason\",\"type\":\"bytes\"}],\"name\":\"UserOperationRevertReason\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"withdrawAddress\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Withdrawn\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"SIG_VALIDATION_FAILED\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"initCode\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"paymasterAndData\",\"type\":\"bytes\"}],\"name\":\"_validateSenderAndPaymaster\",\"outputs\":[],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"unstakeDelaySec\",\"type\":\"uint32\"}],\"name\":\"addStake\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"depositTo\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"deposits\",\"outputs\":[{\"internalType\":\"uint112\",\"name\":\"deposit\",\"type\":\"uint112\"},{\"internalType\":\"bool\",\"name\":\"staked\",\"type\":\"bool\"},{\"internalType\":\"uint112\",\"name\":\"stake\",\"type\":\"uint112\"},{\"internalType\":\"uint32\",\"name\":\"unstakeDelaySec\",\"type\":\"uint32\"},{\"internalType\":\"uint48\",\"name\":\"withdrawTime\",\"type\":\"uint48\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"getDepositInfo\",\"outputs\":[{\"components\":[{\"internalType\":\"uint112\",\"name\":\"deposit\",\"type\":\"uint112\"},{\"internalType\":\"bool\",\"name\":\"staked\",\"type\":\"bool\"},{\"internalType\":\"uint112\",\"name\":\"stake\",\"type\":\"uint112\"},{\"internalType\":\"uint32\",\"name\":\"unstakeDelaySec\",\"type\":\"uint32\"},{\"internalType\":\"uint48\",\"name\":\"withdrawTime\",\"type\":\"uint48\"}],\"internalType\":\"structIStakeManager.DepositInfo\",\"name\":\"info\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"initCode\",\"type\":\"bytes\"}],\"name\":\"getSenderAddress\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"initCode\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"callGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"verificationGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"preVerificationGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxFeePerGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxPriorityFeePerGas\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"paymasterAndData\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"signature\",\"type\":\"bytes\"}],\"internalType\":\"structUserOperation\",\"name\":\"userOp\",\"type\":\"tuple\"}],\"name\":\"getUserOpHash\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"initCode\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"callGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"verificationGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"preVerificationGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxFeePerGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxPriorityFeePerGas\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"paymasterAndData\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"signature\",\"type\":\"bytes\"}],\"internalType\":\"structUserOperation[]\",\"name\":\"userOps\",\"type\":\"tuple[]\"},{\"internalType\":\"contractIAggregator\",\"name\":\"aggregator\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"signature\",\"type\":\"bytes\"}],\"internalType\":\"structIEntryPoint.UserOpsPerAggregator[]\",\"name\":\"opsPerAggregator\",\"type\":\"tuple[]\"},{\"internalType\":\"addresspayable\",\"name\":\"beneficiary\",\"type\":\"address\"}],\"name\":\"handleAggregatedOps\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"initCode\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"callGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"verificationGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"preVerificationGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxFeePerGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxPriorityFeePerGas\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"paymasterAndData\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"signature\",\"type\":\"bytes\"}],\"internalType\":\"structUserOperation[]\",\"name\":\"ops\",\"type\":\"tuple[]\"},{\"internalType\":\"addresspayable\",\"name\":\"beneficiary\",\"type\":\"address\"}],\"name\":\"handleOps\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"},{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"callGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"verificationGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"preVerificationGas\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"paymaster\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"maxFeePerGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxPriorityFeePerGas\",\"type\":\"uint256\"}],\"internalType\":\"structEntryPoint.MemoryUserOp\",\"name\":\"mUserOp\",\"type\":\"tuple\"},{\"internalType\":\"bytes32\",\"name\":\"userOpHash\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"prefund\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"contextOffset\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"preOpGas\",\"type\":\"uint256\"}],\"internalType\":\"structEntryPoint.UserOpInfo\",\"name\":\"opInfo\",\"type\":\"tuple\"},{\"internalType\":\"bytes\",\"name\":\"context\",\"type\":\"bytes\"}],\"name\":\"innerHandleOp\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"actualGasCost\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"initCode\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"callGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"verificationGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"preVerificationGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxFeePerGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxPriorityFeePerGas\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"paymasterAndData\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"signature\",\"type\":\"bytes\"}],\"internalType\":\"structUserOperation\",\"name\":\"op\",\"type\":\"tuple\"},{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"targetCallData\",\"type\":\"bytes\"}],\"name\":\"simulateHandleOp\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"initCode\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"callGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"verificationGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"preVerificationGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxFeePerGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxPriorityFeePerGas\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"paymasterAndData\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"signature\",\"type\":\"bytes\"}],\"internalType\":\"structUserOperation\",\"name\":\"userOp\",\"type\":\"tuple\"}],\"name\":\"simulateValidation\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"unlockStake\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"addresspayable\",\"name\":\"withdrawAddress\",\"type\":\"address\"}],\"name\":\"withdrawStake\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"addresspayable\",\"name\":\"withdrawAddress\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"withdrawAmount\",\"type\":\"uint256\"}],\"name\":\"withdrawTo\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}]", + Bin: "0x60a0604052604051620000129062000050565b604051809103906000f0801580156200002f573d6000803e3d6000fd5b506001600160a01b03166080523480156200004957600080fd5b506200005e565b61020a8062004b0483390190565b608051614a83620000816000396000818161146e015261363e0152614a836000f3fe6080604052600436106101125760003560e01c8063957122ab116100a5578063bb9fe6bf11610074578063d6383f9411610059578063d6383f941461042c578063ee2194231461044c578063fc7e286d1461046c57600080fd5b8063bb9fe6bf146103f7578063c23a5cea1461040c57600080fd5b8063957122ab146103845780639b249f69146103a4578063a6193531146103c4578063b760faf9146103e457600080fd5b80634b1d7cf5116100e15780634b1d7cf5146101ad5780635287ce12146101cd57806370a082311461031c5780638f41ec5a1461036f57600080fd5b80630396cb60146101275780631d7327561461013a5780631fad948c1461016d578063205c28781461018d57600080fd5b366101225761012033610546565b005b600080fd5b6101206101353660046139b1565b6105c1565b34801561014657600080fd5b5061015a610155366004613c28565b610944565b6040519081526020015b60405180910390f35b34801561017957600080fd5b50610120610188366004613d33565b610af7565b34801561019957600080fd5b506101206101a8366004613d8a565b610c38565b3480156101b957600080fd5b506101206101c8366004613d33565b610e3a565b3480156101d957600080fd5b506102bd6101e8366004613db6565b6040805160a0810182526000808252602082018190529181018290526060810182905260808101919091525073ffffffffffffffffffffffffffffffffffffffff1660009081526020818152604091829020825160a08101845281546dffffffffffffffffffffffffffff80821683526e010000000000000000000000000000820460ff161515948301949094526f0100000000000000000000000000000090049092169282019290925260019091015463ffffffff81166060830152640100000000900465ffffffffffff16608082015290565b6040805182516dffffffffffffffffffffffffffff908116825260208085015115159083015283830151169181019190915260608083015163ffffffff169082015260809182015165ffffffffffff169181019190915260a001610164565b34801561032857600080fd5b5061015a610337366004613db6565b73ffffffffffffffffffffffffffffffffffffffff166000908152602081905260409020546dffffffffffffffffffffffffffff1690565b34801561037b57600080fd5b5061015a600181565b34801561039057600080fd5b5061012061039f366004613dd3565b6112d9565b3480156103b057600080fd5b506101206103bf366004613e58565b611431565b3480156103d057600080fd5b5061015a6103df366004613eb3565b611533565b6101206103f2366004613db6565b610546565b34801561040357600080fd5b50610120611575565b34801561041857600080fd5b50610120610427366004613db6565b61172c565b34801561043857600080fd5b50610120610447366004613ee8565b611a2c565b34801561045857600080fd5b50610120610467366004613eb3565b611b5a565b34801561047857600080fd5b506104f9610487366004613db6565b600060208190529081526040902080546001909101546dffffffffffffffffffffffffffff808316926e010000000000000000000000000000810460ff16926f010000000000000000000000000000009091049091169063ffffffff811690640100000000900465ffffffffffff1685565b604080516dffffffffffffffffffffffffffff96871681529415156020860152929094169183019190915263ffffffff16606082015265ffffffffffff909116608082015260a001610164565b6105508134611ec2565b73ffffffffffffffffffffffffffffffffffffffff811660008181526020818152604091829020805492516dffffffffffffffffffffffffffff909316835292917f2da466a7b24304f47e87fa2e1e5a81b9831ce54fec19055ce277ca2f39ba42c491015b60405180910390a25050565b33600090815260208190526040902063ffffffff8216610642576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f6d757374207370656369667920756e7374616b652064656c617900000000000060448201526064015b60405180910390fd5b600181015463ffffffff90811690831610156106ba576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f63616e6e6f7420646563726561736520756e7374616b652074696d65000000006044820152606401610639565b80546000906106ed9034906f0100000000000000000000000000000090046dffffffffffffffffffffffffffff16613f79565b905060008111610759576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f6e6f207374616b652073706563696669656400000000000000000000000000006044820152606401610639565b6dffffffffffffffffffffffffffff8111156107d1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f7374616b65206f766572666c6f770000000000000000000000000000000000006044820152606401610639565b6040805160a08101825283546dffffffffffffffffffffffffffff90811682526001602080840182815286841685870190815263ffffffff808b16606088019081526000608089018181523380835296829052908a9020985189549551945189166f01000000000000000000000000000000027fffffff0000000000000000000000000000ffffffffffffffffffffffffffffff9515156e010000000000000000000000000000027fffffffffffffffffffffffffffffffffff0000000000000000000000000000009097169190991617949094179290921695909517865551949092018054925165ffffffffffff16640100000000027fffffffffffffffffffffffffffffffffffffffffffff00000000000000000000909316949093169390931717905590517fa5ae833d0bb1dcd632d98a8b70973e8516812898e19bf27b70071ebc8dc52c0190610937908490879091825263ffffffff16602082015260400190565b60405180910390a2505050565b6000805a90503330146109b3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f4141393220696e7465726e616c2063616c6c206f6e6c790000000000000000006044820152606401610639565b8451604081015160608201518101611388015a10156109f6577fdeaddead0000000000000000000000000000000000000000000000000000000060005260206000fd5b875160009015610a97576000610a13846000015160008c86611fbf565b905080610a95576000610a27610800611fd7565b805190915015610a8f57846000015173ffffffffffffffffffffffffffffffffffffffff168a602001517f1c4fada7374c0a9ee8841fc38afe82932dc0f8e69012e927f061a8bae611a201876020015184604051610a86929190613ffa565b60405180910390a35b60019250505b505b600088608001515a8603019050610ae96000838b8b8b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250889250612003915050565b9a9950505050505050505050565b8160008167ffffffffffffffff811115610b1357610b136139d7565b604051908082528060200260200182016040528015610b4c57816020015b610b3961390d565b815260200190600190039081610b315790505b50905060005b82811015610bc5576000828281518110610b6e57610b6e614013565b60200260200101519050600080610ba9848a8a87818110610b9157610b91614013565b9050602002810190610ba39190614042565b856123e1565b91509150610bba84838360006125a3565b505050600101610b52565b506000805b83811015610c2557610c1981888884818110610be857610be8614013565b9050602002810190610bfa9190614042565b858481518110610c0c57610c0c614013565b60200260200101516127f8565b90910190600101610bca565b50610c30848261297d565b505050505050565b33600090815260208190526040902080546dffffffffffffffffffffffffffff16821115610cc2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f576974686472617720616d6f756e7420746f6f206c61726765000000000000006044820152606401610639565b8054610cdf9083906dffffffffffffffffffffffffffff16614080565b81547fffffffffffffffffffffffffffffffffffff0000000000000000000000000000166dffffffffffffffffffffffffffff919091161781556040805173ffffffffffffffffffffffffffffffffffffffff851681526020810184905233917fd1c19fbcd4551a5edfb66d43d2e337c04837afda3482b42bdf569a8fccdae5fb910160405180910390a260008373ffffffffffffffffffffffffffffffffffffffff168360405160006040518083038185875af1925050503d8060008114610dc4576040519150601f19603f3d011682016040523d82523d6000602084013e610dc9565b606091505b5050905080610e34576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f6661696c656420746f20776974686472617700000000000000000000000000006044820152606401610639565b50505050565b816000805b828110156110335736868683818110610e5a57610e5a614013565b9050602002810190610e6c9190614093565b9050366000610e7b83806140c7565b90925090506000610e926040850160208601613db6565b90507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff73ffffffffffffffffffffffffffffffffffffffff821601610f33576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f4141393620696e76616c69642061676772656761746f720000000000000000006044820152606401610639565b73ffffffffffffffffffffffffffffffffffffffff8116156110105773ffffffffffffffffffffffffffffffffffffffff811663e3563a4f8484610f7a604089018961412f565b6040518563ffffffff1660e01b8152600401610f999493929190614345565b60006040518083038186803b158015610fb157600080fd5b505afa925050508015610fc2575060015b611010576040517f86a9f75000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff82166004820152602401610639565b61101a8287613f79565b955050505050808061102b906143fc565b915050610e3f565b5060008167ffffffffffffffff81111561104f5761104f6139d7565b60405190808252806020026020018201604052801561108857816020015b61107561390d565b81526020019060019003908161106d5790505b5090506000805b8481101561117357368888838181106110aa576110aa614013565b90506020028101906110bc9190614093565b90503660006110cb83806140c7565b909250905060006110e26040850160208601613db6565b90508160005b8181101561115a57600089898151811061110457611104614013565b602002602001015190506000806111278b898987818110610b9157610b91614013565b91509150611137848383896125a3565b8a611141816143fc565b9b50505050508080611152906143fc565b9150506110e8565b505050505050808061116b906143fc565b91505061108f565b50600080915060005b85811015611299573689898381811061119757611197614013565b90506020028101906111a99190614093565b90506111bb6040820160208301613db6565b73ffffffffffffffffffffffffffffffffffffffff167f575ff3acadd5ab348fe1855e217e0f3678f8d767d7494c9f9fefbee2e17cca4d60405160405180910390a236600061120a83806140c7565b90925090508060005b81811015611281576112558885858481811061123157611231614013565b90506020028101906112439190614042565b8b8b81518110610c0c57610c0c614013565b61125f9088613f79565b96508761126b816143fc565b9850508080611279906143fc565b915050611213565b50505050508080611291906143fc565b91505061117c565b506040516000907f575ff3acadd5ab348fe1855e217e0f3678f8d767d7494c9f9fefbee2e17cca4d908290a26112cf868261297d565b5050505050505050565b831580156112fc575073ffffffffffffffffffffffffffffffffffffffff83163b155b15611363576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f41413230206163636f756e74206e6f74206465706c6f796564000000000000006044820152606401610639565b601481106113f557600061137a6014828486614434565b6113839161445e565b60601c9050803b6000036113f3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f41413330207061796d6173746572206e6f74206465706c6f79656400000000006044820152606401610639565b505b6040517f08c379a00000000000000000000000000000000000000000000000000000000081526020600482015260006024820152604401610639565b6040517f570e1a3600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169063570e1a36906114a590859085906004016144a6565b6020604051808303816000875af11580156114c4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114e891906144ba565b6040517f6ca7b80600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091166004820152602401610639565b600061153e82612ac9565b6040805160208101929092523090820152466060820152608001604051602081830303815290604052805190602001209050919050565b3360009081526020819052604081206001810154909163ffffffff90911690036115fb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600a60248201527f6e6f74207374616b6564000000000000000000000000000000000000000000006044820152606401610639565b80546e010000000000000000000000000000900460ff16611678576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f616c726561647920756e7374616b696e670000000000000000000000000000006044820152606401610639565b60018101546000906116909063ffffffff16426144d7565b6001830180547fffffffffffffffffffffffffffffffffffffffffffff000000000000ffffffff1664010000000065ffffffffffff84169081029190911790915583547fffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffff16845560405190815290915033907ffa9b3c14cc825c412c9ed81b3ba365a5b459439403f18829e572ed53a4180f0a906020016105b5565b33600090815260208190526040902080546f0100000000000000000000000000000090046dffffffffffffffffffffffffffff16806117c7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f4e6f207374616b6520746f2077697468647261770000000000000000000000006044820152606401610639565b6001820154640100000000900465ffffffffffff16611842576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f6d7573742063616c6c20756e6c6f636b5374616b6528292066697273740000006044820152606401610639565b60018201544264010000000090910465ffffffffffff1611156118c1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f5374616b65207769746864726177616c206973206e6f742064756500000000006044820152606401610639565b6001820180547fffffffffffffffffffffffffffffffffffffffffffff0000000000000000000016905581547fffffff0000000000000000000000000000ffffffffffffffffffffffffffffff1682556040805173ffffffffffffffffffffffffffffffffffffffff851681526020810183905233917fb7c918e0e249f999e965cafeb6c664271b3f4317d296461500e71da39f0cbda3910160405180910390a260008373ffffffffffffffffffffffffffffffffffffffff168260405160006040518083038185875af1925050503d80600081146119bc576040519150601f19603f3d011682016040523d82523d6000602084013e6119c1565b606091505b5050905080610e34576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f6661696c656420746f207769746864726177207374616b6500000000000000006044820152606401610639565b611a3461390d565b611a3d85612ae2565b600080611a4c600088856123e1565b915091506000611a5c8383612bd5565b9050611a6743600052565b6000611a7560008a876127f8565b9050611a8043600052565b6000606073ffffffffffffffffffffffffffffffffffffffff8a1615611b10578973ffffffffffffffffffffffffffffffffffffffff168989604051611ac79291906144fd565b6000604051808303816000865af19150503d8060008114611b04576040519150601f19603f3d011682016040523d82523d6000602084013e611b09565b606091505b5090925090505b8660800151838560200151866040015185856040517f8b7ac9800000000000000000000000000000000000000000000000000000000081526004016106399695949392919061450d565b611b6261390d565b611b6b82612ae2565b600080611b7a600085856123e1565b845160a001516040805180820182526000808252602080830182815273ffffffffffffffffffffffffffffffffffffffff958616835282825284832080546dffffffffffffffffffffffffffff6f01000000000000000000000000000000918290048116875260019283015463ffffffff9081169094528d51518851808a018a5287815280870188815291909a16875286865288872080549390930490911689529101549091169052835180850190945281845283015293955091935090366000611c4860408a018a61412f565b909250905060006014821015611c5f576000611c7a565b611c6d601460008486614434565b611c769161445e565b60601c5b6040805180820182526000808252602080830182815273ffffffffffffffffffffffffffffffffffffffff861683529082905292902080546f0100000000000000000000000000000090046dffffffffffffffffffffffffffff1682526001015463ffffffff1690915290915093505050506000611cf88686612bd5565b90506000816000015190506000600173ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614905060006040518060c001604052808b6080015181526020018b6040015181526020018315158152602001856020015165ffffffffffff168152602001856040015165ffffffffffff168152602001611d8f8c6060015190565b9052905073ffffffffffffffffffffffffffffffffffffffff831615801590611dcf575073ffffffffffffffffffffffffffffffffffffffff8316600114155b15611e885760408051808201825273ffffffffffffffffffffffffffffffffffffffff851680825282518084018452600080825260208083018281529382528181529085902080546f0100000000000000000000000000000090046dffffffffffffffffffffffffffff1683526001015463ffffffff169092529082015290517ffaecb4e4000000000000000000000000000000000000000000000000000000008152610639908390899089908c9086906004016145af565b808686896040517fe0cff05f000000000000000000000000000000000000000000000000000000008152600401610639949392919061463c565b73ffffffffffffffffffffffffffffffffffffffff821660009081526020819052604081208054909190611f079084906dffffffffffffffffffffffffffff16613f79565b90506dffffffffffffffffffffffffffff811115611f81576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f6465706f736974206f766572666c6f77000000000000000000000000000000006044820152606401610639565b81547fffffffffffffffffffffffffffffffffffff0000000000000000000000000000166dffffffffffffffffffffffffffff919091161790555050565b6000806000845160208601878987f195945050505050565b60603d82811115611fe55750815b604051602082018101604052818152816000602083013e9392505050565b6000805a85519091506000908161201982612cbc565b60a083015190915073ffffffffffffffffffffffffffffffffffffffff81166120455782519350612293565b80935060008851111561229357868202955060028a600281111561206b5761206b614693565b146121035760608301516040517fa9a2340900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83169163a9a23409916120cb908e908d908c906004016146c2565b600060405180830381600088803b1580156120e557600080fd5b5087f11580156120f9573d6000803e3d6000fd5b5050505050612293565b60608301516040517fa9a2340900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83169163a9a234099161215e908e908d908c906004016146c2565b600060405180830381600088803b15801561217857600080fd5b5087f19350505050801561218a575060015b61229357612196614722565b806308c379a00361222657506121aa61473e565b806121b55750612228565b8b816040516020016121c791906147e6565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152908290527f220266b60000000000000000000000000000000000000000000000000000000082526106399291600401613ffa565b505b8a6040517f220266b60000000000000000000000000000000000000000000000000000000081526004016106399181526040602082018190526012908201527f4141353020706f73744f70207265766572740000000000000000000000000000606082015260800190565b5a85038701965081870295508589604001511015612315578a6040517f220266b600000000000000000000000000000000000000000000000000000000815260040161063991815260406020808301829052908201527f414135312070726566756e642062656c6f772061637475616c476173436f7374606082015260800190565b60408901518690036123278582611ec2565b6000808c600281111561233c5761233c614693565b1490508460a0015173ffffffffffffffffffffffffffffffffffffffff16856000015173ffffffffffffffffffffffffffffffffffffffff168c602001517f49628fd1471006c1482da88028e9ce4dbb080b815c9b0344d39e5a8e6ec1419f8860200151858d8f6040516123c9949392919093845291151560208401526040830152606082015260800190565b60405180910390a45050505050505095945050505050565b60008060005a84519091506123f68682612cec565b6123ff86611533565b6020860152604081015160608201516080830151171760e087013517610100870135176effffffffffffffffffffffffffffff81111561249b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f41413934206761732076616c756573206f766572666c6f7700000000000000006044820152606401610639565b6000806124a784612e0c565b90506124b58a8a8a84612e66565b975091506124c243600052565b60a084015160609073ffffffffffffffffffffffffffffffffffffffff16156124f7576124f28b8b8b858761317c565b975090505b60005a87039050808b60a001351015612575578b6040517f220266b6000000000000000000000000000000000000000000000000000000008152600401610639918152604060208201819052601e908201527f41413430206f76657220766572696669636174696f6e4761734c696d69740000606082015260800190565b60408a018390528160608b015260c08b01355a8803018a608001818152505050505050505050935093915050565b6000806125af8561343f565b915091508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161461265157856040517f220266b60000000000000000000000000000000000000000000000000000000081526004016106399181526040602082018190526014908201527f41413234207369676e6174757265206572726f72000000000000000000000000606082015260800190565b80156126c257856040517f220266b60000000000000000000000000000000000000000000000000000000081526004016106399181526040602082018190526017908201527f414132322065787069726564206f72206e6f7420647565000000000000000000606082015260800190565b60006126cd8561343f565b9250905073ffffffffffffffffffffffffffffffffffffffff81161561275857866040517f220266b60000000000000000000000000000000000000000000000000000000081526004016106399181526040602082018190526014908201527f41413334207369676e6174757265206572726f72000000000000000000000000606082015260800190565b81156127ef57866040517f220266b60000000000000000000000000000000000000000000000000000000081526004016106399181526040602082018190526021908201527f41413332207061796d61737465722065787069726564206f72206e6f7420647560608201527f6500000000000000000000000000000000000000000000000000000000000000608082015260a00190565b50505050505050565b6000805a9050600061280b846060015190565b905030631d732756612820606088018861412f565b87856040518563ffffffff1660e01b8152600401612841949392919061482b565b6020604051808303816000875af192505050801561289a575060408051601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201909252612897918101906148ec565b60015b61297157600060206000803e506000517f2152215300000000000000000000000000000000000000000000000000000000810161293c57866040517f220266b6000000000000000000000000000000000000000000000000000000008152600401610639918152604060208201819052600f908201527f41413935206f7574206f66206761730000000000000000000000000000000000606082015260800190565b600085608001515a61294e9086614080565b6129589190613f79565b9050612968886002888685612003565b94505050612974565b92505b50509392505050565b73ffffffffffffffffffffffffffffffffffffffff82166129fa576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f4141393020696e76616c69642062656e656669636961727900000000000000006044820152606401610639565b60008273ffffffffffffffffffffffffffffffffffffffff168260405160006040518083038185875af1925050503d8060008114612a54576040519150601f19603f3d011682016040523d82523d6000602084013e612a59565b606091505b5050905080612ac4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f41413931206661696c65642073656e6420746f2062656e6566696369617279006044820152606401610639565b505050565b6000612ad482613492565b805190602001209050919050565b3063957122ab612af5604084018461412f565b612b026020860186613db6565b612b1061012087018761412f565b6040518663ffffffff1660e01b8152600401612b30959493929190614905565b60006040518083038186803b158015612b4857600080fd5b505afa925050508015612b59575060015b612bd257612b65614722565b806308c379a003612bc65750612b7961473e565b80612b845750612bc8565b805115612bc2576000816040517f220266b6000000000000000000000000000000000000000000000000000000008152600401610639929190613ffa565b5050565b505b3d6000803e3d6000fd5b50565b6040805160608101825260008082526020820181905291810182905290612bfb846134d1565b90506000612c08846134d1565b825190915073ffffffffffffffffffffffffffffffffffffffff8116612c2c575080515b602080840151604080860151928501519085015191929165ffffffffffff8083169085161015612c5a578193505b8065ffffffffffff168365ffffffffffff161115612c76578092505b50506040805160608101825273ffffffffffffffffffffffffffffffffffffffff909416845265ffffffffffff9283166020850152911690820152925050505b92915050565b60c081015160e082015160009190808203612cd8575092915050565b612ce48248830161354f565b949350505050565b612cf96020830183613db6565b73ffffffffffffffffffffffffffffffffffffffff16815260208083013590820152608080830135604083015260a0830135606083015260c0808401359183019190915260e0808401359183019190915261010083013590820152366000612d6561012085018561412f565b90925090508015612dff576014811015612ddb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f4141393320696e76616c6964207061796d6173746572416e64446174610000006044820152606401610639565b612de9601460008385614434565b612df29161445e565b60601c60a0840152610e34565b600060a084015250505050565b60a0810151600090819073ffffffffffffffffffffffffffffffffffffffff16612e37576001612e3a565b60035b60ff16905060008360800151828560600151028560400151010190508360c00151810292505050919050565b60008060005a8551805191925090612e8b8988612e8660408c018c61412f565b613567565b60a0820151612e9943600052565b600073ffffffffffffffffffffffffffffffffffffffff8216612f025773ffffffffffffffffffffffffffffffffffffffff83166000908152602081905260409020546dffffffffffffffffffffffffffff16888111612efb57808903612efe565b60005b9150505b606084015160208a01516040517f3a871cdd00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff861692633a871cdd929091612f62918f918790600401614948565b60206040518083038160008887f193505050508015612fbc575060408051601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201909252612fb9918101906148ec565b60015b61306657612fc8614722565b806308c379a003612ff95750612fdc61473e565b80612fe75750612ffb565b8b816040516020016121c7919061496d565b505b8a6040517f220266b60000000000000000000000000000000000000000000000000000000081526004016106399181526040602082018190526016908201527f4141323320726576657274656420286f72204f4f472900000000000000000000606082015260800190565b955073ffffffffffffffffffffffffffffffffffffffff82166131695773ffffffffffffffffffffffffffffffffffffffff8316600090815260208190526040902080546dffffffffffffffffffffffffffff16808a111561312d578c6040517f220266b60000000000000000000000000000000000000000000000000000000081526004016106399181526040602082018190526017908201527f41413231206469646e2774207061792070726566756e64000000000000000000606082015260800190565b81547fffffffffffffffffffffffffffffffffffff000000000000000000000000000016908a90036dffffffffffffffffffffffffffff161790555b5a85039650505050505094509492505050565b825160608181015190916000918481116131f2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f4141343120746f6f206c6974746c6520766572696669636174696f6e476173006044820152606401610639565b60a082015173ffffffffffffffffffffffffffffffffffffffff8116600090815260208190526040902080548784039291906dffffffffffffffffffffffffffff16898110156132a7578c6040517f220266b6000000000000000000000000000000000000000000000000000000008152600401610639918152604060208201819052601e908201527f41413331207061796d6173746572206465706f73697420746f6f206c6f770000606082015260800190565b8981038260000160006101000a8154816dffffffffffffffffffffffffffff02191690836dffffffffffffffffffffffffffff1602179055508273ffffffffffffffffffffffffffffffffffffffff1663f465c77e858e8e602001518e6040518563ffffffff1660e01b815260040161332293929190614948565b60006040518083038160008887f19350505050801561338157506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016820160405261337e91908101906149b2565b60015b61342b5761338d614722565b806308c379a0036133be57506133a161473e565b806133ac57506133c0565b8d816040516020016121c79190614a3e565b505b8c6040517f220266b60000000000000000000000000000000000000000000000000000000081526004016106399181526040602082018190526016908201527f4141333320726576657274656420286f72204f4f472900000000000000000000606082015260800190565b909e909d509b505050505050505050505050565b6000808260000361345557506000928392509050565b6000613460846134d1565b9050806040015165ffffffffffff164211806134875750806020015165ffffffffffff1642105b905194909350915050565b60603660006134a561014085018561412f565b915091508360208184030360405194506020810185016040528085528082602087013750505050919050565b60408051606081018252600080825260208201819052918101919091528160a081901c65ffffffffffff811660000361350d575065ffffffffffff5b6040805160608101825273ffffffffffffffffffffffffffffffffffffffff909316835260d09490941c602083015265ffffffffffff16928101929092525090565b600081831061355e5781613560565b825b9392505050565b8015610e345782515173ffffffffffffffffffffffffffffffffffffffff81163b156135f857846040517f220266b6000000000000000000000000000000000000000000000000000000008152600401610639918152604060208201819052601f908201527f414131302073656e64657220616c726561647920636f6e737472756374656400606082015260800190565b8351606001516040517f570e1a3600000000000000000000000000000000000000000000000000000000815260009173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169163570e1a36919061367690889088906004016144a6565b60206040518083038160008887f1158015613695573d6000803e3d6000fd5b50505050506040513d601f19601f820116820180604052508101906136ba91906144ba565b905073ffffffffffffffffffffffffffffffffffffffff811661374257856040517f220266b6000000000000000000000000000000000000000000000000000000008152600401610639918152604060208201819052601b908201527f4141313320696e6974436f6465206661696c6564206f72204f4f470000000000606082015260800190565b8173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16146137df57856040517f220266b600000000000000000000000000000000000000000000000000000000815260040161063991815260406020808301829052908201527f4141313420696e6974436f6465206d7573742072657475726e2073656e646572606082015260800190565b8073ffffffffffffffffffffffffffffffffffffffff163b60000361386857856040517f220266b600000000000000000000000000000000000000000000000000000000815260040161063991815260406020808301829052908201527f4141313520696e6974436f6465206d757374206372656174652073656e646572606082015260800190565b60006138776014828688614434565b6138809161445e565b60601c90508273ffffffffffffffffffffffffffffffffffffffff1686602001517fd51a9c61267aa6196961883ecf5ff2da6619c37dac0fa92122513fb32c032d2d83896000015160a001516040516138fc92919073ffffffffffffffffffffffffffffffffffffffff92831681529116602082015260400190565b60405180910390a350505050505050565b6040518060a0016040528061398c604051806101000160405280600073ffffffffffffffffffffffffffffffffffffffff16815260200160008152602001600081526020016000815260200160008152602001600073ffffffffffffffffffffffffffffffffffffffff16815260200160008152602001600081525090565b8152602001600080191681526020016000815260200160008152602001600081525090565b6000602082840312156139c357600080fd5b813563ffffffff8116811461356057600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60a0810181811067ffffffffffffffff82111715613a2657613a266139d7565b60405250565b610100810181811067ffffffffffffffff82111715613a2657613a266139d7565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f830116810181811067ffffffffffffffff82111715613a9157613a916139d7565b6040525050565b600067ffffffffffffffff821115613ab257613ab26139d7565b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b73ffffffffffffffffffffffffffffffffffffffff81168114612bd257600080fd5b8035613b0b81613ade565b919050565b6000818303610180811215613b2457600080fd5b604051613b3081613a06565b80925061010080831215613b4357600080fd5b6040519250613b5183613a2c565b613b5a85613b00565b835260208501356020840152604085013560408401526060850135606084015260808501356080840152613b9060a08601613b00565b60a084015260c085013560c084015260e085013560e084015282825280850135602083015250610120840135604082015261014084013560608201526101608401356080820152505092915050565b60008083601f840112613bf157600080fd5b50813567ffffffffffffffff811115613c0957600080fd5b602083019150836020828501011115613c2157600080fd5b9250929050565b6000806000806101c08587031215613c3f57600080fd5b843567ffffffffffffffff80821115613c5757600080fd5b818701915087601f830112613c6b57600080fd5b8135613c7681613a98565b604051613c838282613a4d565b8281528a6020848701011115613c9857600080fd5b82602086016020830137600060208483010152809850505050613cbe8860208901613b10565b94506101a0870135915080821115613cd557600080fd5b50613ce287828801613bdf565b95989497509550505050565b60008083601f840112613d0057600080fd5b50813567ffffffffffffffff811115613d1857600080fd5b6020830191508360208260051b8501011115613c2157600080fd5b600080600060408486031215613d4857600080fd5b833567ffffffffffffffff811115613d5f57600080fd5b613d6b86828701613cee565b9094509250506020840135613d7f81613ade565b809150509250925092565b60008060408385031215613d9d57600080fd5b8235613da881613ade565b946020939093013593505050565b600060208284031215613dc857600080fd5b813561356081613ade565b600080600080600060608688031215613deb57600080fd5b853567ffffffffffffffff80821115613e0357600080fd5b613e0f89838a01613bdf565b909750955060208801359150613e2482613ade565b90935060408701359080821115613e3a57600080fd5b50613e4788828901613bdf565b969995985093965092949392505050565b60008060208385031215613e6b57600080fd5b823567ffffffffffffffff811115613e8257600080fd5b613e8e85828601613bdf565b90969095509350505050565b60006101608284031215613ead57600080fd5b50919050565b600060208284031215613ec557600080fd5b813567ffffffffffffffff811115613edc57600080fd5b612ce484828501613e9a565b60008060008060608587031215613efe57600080fd5b843567ffffffffffffffff80821115613f1657600080fd5b613f2288838901613e9a565b955060208701359150613f3482613ade565b90935060408601359080821115613cd557600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b80820180821115612cb657612cb6613f4a565b60005b83811015613fa7578181015183820152602001613f8f565b50506000910152565b60008151808452613fc8816020860160208601613f8c565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b828152604060208201526000612ce46040830184613fb0565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600082357ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffea183360301811261407657600080fd5b9190910192915050565b81810381811115612cb657612cb6613f4a565b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa183360301811261407657600080fd5b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18436030181126140fc57600080fd5b83018035915067ffffffffffffffff82111561411757600080fd5b6020019150600581901b3603821315613c2157600080fd5b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261416457600080fd5b83018035915067ffffffffffffffff82111561417f57600080fd5b602001915036819003821315613c2157600080fd5b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18436030181126141c957600080fd5b830160208101925035905067ffffffffffffffff8111156141e957600080fd5b803603821315613c2157600080fd5b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b600061016061426d8461425385613b00565b73ffffffffffffffffffffffffffffffffffffffff169052565b602083013560208501526142846040840184614194565b82604087015261429783870182846141f8565b925050506142a86060840184614194565b85830360608701526142bb8382846141f8565b925050506080830135608085015260a083013560a085015260c083013560c085015260e083013560e085015261010080840135818601525061012061430281850185614194565b868403838801526143148482846141f8565b935050505061014061432881850185614194565b8684038388015261433a8482846141f8565b979650505050505050565b6040808252810184905260006060600586901b830181019083018783805b898110156143e5577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa087860301845282357ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffea18c36030181126143c3578283fd5b6143cf868d8301614241565b9550506020938401939290920191600101614363565b50505050828103602084015261433a8185876141f8565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361442d5761442d613f4a565b5060010190565b6000808585111561444457600080fd5b8386111561445157600080fd5b5050820193919092039150565b7fffffffffffffffffffffffffffffffffffffffff000000000000000000000000813581811691601485101561449e5780818660140360031b1b83161692505b505092915050565b602081526000612ce46020830184866141f8565b6000602082840312156144cc57600080fd5b815161356081613ade565b65ffffffffffff8181168382160190808211156144f6576144f6613f4a565b5092915050565b8183823760009101908152919050565b868152856020820152600065ffffffffffff8087166040840152808616606084015250831515608083015260c060a083015261454c60c0830184613fb0565b98975050505050505050565b80518252602081015160208301526040810151151560408301526000606082015165ffffffffffff8082166060860152806080850151166080860152505060a082015160c060a0850152612ce460c0850182613fb0565b60006101408083526145c381840189614558565b9150506145dd602083018780518252602090810151910152565b845160608301526020948501516080830152835160a08301529284015160c0820152815173ffffffffffffffffffffffffffffffffffffffff1660e0820152908301518051610100830152909201516101209092019190915292915050565b60e08152600061464f60e0830187614558565b9050614668602083018680518252602090810151910152565b8351606083015260208401516080830152825160a0830152602083015160c083015295945050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b6000600385106146fb577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b848252606060208301526147126060830185613fb0565b9050826040830152949350505050565b600060033d111561473b5760046000803e5060005160e01c5b90565b600060443d101561474c5790565b6040517ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc803d016004833e81513d67ffffffffffffffff816024840111818411171561479a57505050505090565b82850191508151818111156147b25750505050505090565b843d87010160208285010111156147cc5750505050505090565b6147db60208286010187613a4d565b509095945050505050565b7f4141353020706f73744f702072657665727465643a200000000000000000000081526000825161481e816016850160208701613f8c565b9190910160160192915050565b60006101c080835261484081840187896141f8565b9050845173ffffffffffffffffffffffffffffffffffffffff808251166020860152602082015160408601526040820151606086015260608201516080860152608082015160a08601528060a08301511660c08601525060c081015160e085015260e08101516101008501525060208501516101208401526040850151610140840152606085015161016084015260808501516101808401528281036101a084015261433a8185613fb0565b6000602082840312156148fe57600080fd5b5051919050565b6060815260006149196060830187896141f8565b73ffffffffffffffffffffffffffffffffffffffff86166020840152828103604084015261454c8185876141f8565b60608152600061495b6060830186614241565b60208301949094525060400152919050565b7f414132332072657665727465643a2000000000000000000000000000000000008152600082516149a581600f850160208701613f8c565b91909101600f0192915050565b600080604083850312156149c557600080fd5b825167ffffffffffffffff8111156149dc57600080fd5b8301601f810185136149ed57600080fd5b80516149f881613a98565b604051614a058282613a4d565b828152876020848601011115614a1a57600080fd5b614a2b836020830160208701613f8c565b6020969096015195979596505050505050565b7f414133332072657665727465643a2000000000000000000000000000000000008152600082516149a581600f850160208701613f8c56fea164736f6c6343000813000a608060405234801561001057600080fd5b506101ea806100206000396000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c8063570e1a3614610030575b600080fd5b61004361003e3660046100f9565b61006c565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b60008061007c601482858761016b565b61008591610195565b60601c90506000610099846014818861016b565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092018290525084519495509360209350849250905082850182875af190506000519350806100f057600093505b50505092915050565b6000806020838503121561010c57600080fd5b823567ffffffffffffffff8082111561012457600080fd5b818501915085601f83011261013857600080fd5b81358181111561014757600080fd5b86602082850101111561015957600080fd5b60209290920196919550909350505050565b6000808585111561017b57600080fd5b8386111561018857600080fd5b5050820193919092039150565b7fffffffffffffffffffffffffffffffffffffffff00000000000000000000000081358181169160148510156101d55780818660140360031b1b83161692505b50509291505056fea164736f6c6343000813000a", +} + +var EntryPointABI = EntryPointMetaData.ABI + +var EntryPointBin = EntryPointMetaData.Bin + +func DeployEntryPoint(auth *bind.TransactOpts, backend bind.ContractBackend) (common.Address, *types.Transaction, *EntryPoint, error) { + parsed, err := EntryPointMetaData.GetAbi() + if err != nil { + return common.Address{}, nil, nil, err + } + if parsed == nil { + return common.Address{}, nil, nil, errors.New("GetABI returned nil") + } + + address, tx, contract, err := bind.DeployContract(auth, *parsed, common.FromHex(EntryPointBin), backend) + if err != nil { + return common.Address{}, nil, nil, err + } + return address, tx, &EntryPoint{address: address, abi: *parsed, EntryPointCaller: EntryPointCaller{contract: contract}, EntryPointTransactor: EntryPointTransactor{contract: contract}, EntryPointFilterer: EntryPointFilterer{contract: contract}}, nil +} + +type EntryPoint struct { + address common.Address + abi abi.ABI + EntryPointCaller + EntryPointTransactor + EntryPointFilterer +} + +type EntryPointCaller struct { + contract *bind.BoundContract +} + +type EntryPointTransactor struct { + contract *bind.BoundContract +} + +type EntryPointFilterer struct { + contract *bind.BoundContract +} + +type EntryPointSession struct { + Contract *EntryPoint + CallOpts bind.CallOpts + TransactOpts bind.TransactOpts +} + +type EntryPointCallerSession struct { + Contract *EntryPointCaller + CallOpts bind.CallOpts +} + +type EntryPointTransactorSession struct { + Contract *EntryPointTransactor + TransactOpts bind.TransactOpts +} + +type EntryPointRaw struct { + Contract *EntryPoint +} + +type EntryPointCallerRaw struct { + Contract *EntryPointCaller +} + +type EntryPointTransactorRaw struct { + Contract *EntryPointTransactor +} + +func NewEntryPoint(address common.Address, backend bind.ContractBackend) (*EntryPoint, error) { + abi, err := abi.JSON(strings.NewReader(EntryPointABI)) + if err != nil { + return nil, err + } + contract, err := bindEntryPoint(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &EntryPoint{address: address, abi: abi, EntryPointCaller: EntryPointCaller{contract: contract}, EntryPointTransactor: EntryPointTransactor{contract: contract}, EntryPointFilterer: EntryPointFilterer{contract: contract}}, nil +} + +func NewEntryPointCaller(address common.Address, caller bind.ContractCaller) (*EntryPointCaller, error) { + contract, err := bindEntryPoint(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &EntryPointCaller{contract: contract}, nil +} + +func NewEntryPointTransactor(address common.Address, transactor bind.ContractTransactor) (*EntryPointTransactor, error) { + contract, err := bindEntryPoint(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &EntryPointTransactor{contract: contract}, nil +} + +func NewEntryPointFilterer(address common.Address, filterer bind.ContractFilterer) (*EntryPointFilterer, error) { + contract, err := bindEntryPoint(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &EntryPointFilterer{contract: contract}, nil +} + +func bindEntryPoint(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := EntryPointMetaData.GetAbi() + if err != nil { + return nil, err + } + return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil +} + +func (_EntryPoint *EntryPointRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _EntryPoint.Contract.EntryPointCaller.contract.Call(opts, result, method, params...) +} + +func (_EntryPoint *EntryPointRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _EntryPoint.Contract.EntryPointTransactor.contract.Transfer(opts) +} + +func (_EntryPoint *EntryPointRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _EntryPoint.Contract.EntryPointTransactor.contract.Transact(opts, method, params...) +} + +func (_EntryPoint *EntryPointCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _EntryPoint.Contract.contract.Call(opts, result, method, params...) +} + +func (_EntryPoint *EntryPointTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _EntryPoint.Contract.contract.Transfer(opts) +} + +func (_EntryPoint *EntryPointTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _EntryPoint.Contract.contract.Transact(opts, method, params...) +} + +func (_EntryPoint *EntryPointCaller) SIGVALIDATIONFAILED(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _EntryPoint.contract.Call(opts, &out, "SIG_VALIDATION_FAILED") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +func (_EntryPoint *EntryPointSession) SIGVALIDATIONFAILED() (*big.Int, error) { + return _EntryPoint.Contract.SIGVALIDATIONFAILED(&_EntryPoint.CallOpts) +} + +func (_EntryPoint *EntryPointCallerSession) SIGVALIDATIONFAILED() (*big.Int, error) { + return _EntryPoint.Contract.SIGVALIDATIONFAILED(&_EntryPoint.CallOpts) +} + +func (_EntryPoint *EntryPointCaller) ValidateSenderAndPaymaster(opts *bind.CallOpts, initCode []byte, sender common.Address, paymasterAndData []byte) error { + var out []interface{} + err := _EntryPoint.contract.Call(opts, &out, "_validateSenderAndPaymaster", initCode, sender, paymasterAndData) + + if err != nil { + return err + } + + return err + +} + +func (_EntryPoint *EntryPointSession) ValidateSenderAndPaymaster(initCode []byte, sender common.Address, paymasterAndData []byte) error { + return _EntryPoint.Contract.ValidateSenderAndPaymaster(&_EntryPoint.CallOpts, initCode, sender, paymasterAndData) +} + +func (_EntryPoint *EntryPointCallerSession) ValidateSenderAndPaymaster(initCode []byte, sender common.Address, paymasterAndData []byte) error { + return _EntryPoint.Contract.ValidateSenderAndPaymaster(&_EntryPoint.CallOpts, initCode, sender, paymasterAndData) +} + +func (_EntryPoint *EntryPointCaller) BalanceOf(opts *bind.CallOpts, account common.Address) (*big.Int, error) { + var out []interface{} + err := _EntryPoint.contract.Call(opts, &out, "balanceOf", account) + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +func (_EntryPoint *EntryPointSession) BalanceOf(account common.Address) (*big.Int, error) { + return _EntryPoint.Contract.BalanceOf(&_EntryPoint.CallOpts, account) +} + +func (_EntryPoint *EntryPointCallerSession) BalanceOf(account common.Address) (*big.Int, error) { + return _EntryPoint.Contract.BalanceOf(&_EntryPoint.CallOpts, account) +} + +func (_EntryPoint *EntryPointCaller) Deposits(opts *bind.CallOpts, arg0 common.Address) (Deposits, + + error) { + var out []interface{} + err := _EntryPoint.contract.Call(opts, &out, "deposits", arg0) + + outstruct := new(Deposits) + if err != nil { + return *outstruct, err + } + + outstruct.Deposit = *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + outstruct.Staked = *abi.ConvertType(out[1], new(bool)).(*bool) + outstruct.Stake = *abi.ConvertType(out[2], new(*big.Int)).(**big.Int) + outstruct.UnstakeDelaySec = *abi.ConvertType(out[3], new(uint32)).(*uint32) + outstruct.WithdrawTime = *abi.ConvertType(out[4], new(*big.Int)).(**big.Int) + + return *outstruct, err + +} + +func (_EntryPoint *EntryPointSession) Deposits(arg0 common.Address) (Deposits, + + error) { + return _EntryPoint.Contract.Deposits(&_EntryPoint.CallOpts, arg0) +} + +func (_EntryPoint *EntryPointCallerSession) Deposits(arg0 common.Address) (Deposits, + + error) { + return _EntryPoint.Contract.Deposits(&_EntryPoint.CallOpts, arg0) +} + +func (_EntryPoint *EntryPointCaller) GetDepositInfo(opts *bind.CallOpts, account common.Address) (IStakeManagerDepositInfo, error) { + var out []interface{} + err := _EntryPoint.contract.Call(opts, &out, "getDepositInfo", account) + + if err != nil { + return *new(IStakeManagerDepositInfo), err + } + + out0 := *abi.ConvertType(out[0], new(IStakeManagerDepositInfo)).(*IStakeManagerDepositInfo) + + return out0, err + +} + +func (_EntryPoint *EntryPointSession) GetDepositInfo(account common.Address) (IStakeManagerDepositInfo, error) { + return _EntryPoint.Contract.GetDepositInfo(&_EntryPoint.CallOpts, account) +} + +func (_EntryPoint *EntryPointCallerSession) GetDepositInfo(account common.Address) (IStakeManagerDepositInfo, error) { + return _EntryPoint.Contract.GetDepositInfo(&_EntryPoint.CallOpts, account) +} + +func (_EntryPoint *EntryPointCaller) GetUserOpHash(opts *bind.CallOpts, userOp UserOperation) ([32]byte, error) { + var out []interface{} + err := _EntryPoint.contract.Call(opts, &out, "getUserOpHash", userOp) + + if err != nil { + return *new([32]byte), err + } + + out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) + + return out0, err + +} + +func (_EntryPoint *EntryPointSession) GetUserOpHash(userOp UserOperation) ([32]byte, error) { + return _EntryPoint.Contract.GetUserOpHash(&_EntryPoint.CallOpts, userOp) +} + +func (_EntryPoint *EntryPointCallerSession) GetUserOpHash(userOp UserOperation) ([32]byte, error) { + return _EntryPoint.Contract.GetUserOpHash(&_EntryPoint.CallOpts, userOp) +} + +func (_EntryPoint *EntryPointTransactor) AddStake(opts *bind.TransactOpts, unstakeDelaySec uint32) (*types.Transaction, error) { + return _EntryPoint.contract.Transact(opts, "addStake", unstakeDelaySec) +} + +func (_EntryPoint *EntryPointSession) AddStake(unstakeDelaySec uint32) (*types.Transaction, error) { + return _EntryPoint.Contract.AddStake(&_EntryPoint.TransactOpts, unstakeDelaySec) +} + +func (_EntryPoint *EntryPointTransactorSession) AddStake(unstakeDelaySec uint32) (*types.Transaction, error) { + return _EntryPoint.Contract.AddStake(&_EntryPoint.TransactOpts, unstakeDelaySec) +} + +func (_EntryPoint *EntryPointTransactor) DepositTo(opts *bind.TransactOpts, account common.Address) (*types.Transaction, error) { + return _EntryPoint.contract.Transact(opts, "depositTo", account) +} + +func (_EntryPoint *EntryPointSession) DepositTo(account common.Address) (*types.Transaction, error) { + return _EntryPoint.Contract.DepositTo(&_EntryPoint.TransactOpts, account) +} + +func (_EntryPoint *EntryPointTransactorSession) DepositTo(account common.Address) (*types.Transaction, error) { + return _EntryPoint.Contract.DepositTo(&_EntryPoint.TransactOpts, account) +} + +func (_EntryPoint *EntryPointTransactor) GetSenderAddress(opts *bind.TransactOpts, initCode []byte) (*types.Transaction, error) { + return _EntryPoint.contract.Transact(opts, "getSenderAddress", initCode) +} + +func (_EntryPoint *EntryPointSession) GetSenderAddress(initCode []byte) (*types.Transaction, error) { + return _EntryPoint.Contract.GetSenderAddress(&_EntryPoint.TransactOpts, initCode) +} + +func (_EntryPoint *EntryPointTransactorSession) GetSenderAddress(initCode []byte) (*types.Transaction, error) { + return _EntryPoint.Contract.GetSenderAddress(&_EntryPoint.TransactOpts, initCode) +} + +func (_EntryPoint *EntryPointTransactor) HandleAggregatedOps(opts *bind.TransactOpts, opsPerAggregator []IEntryPointUserOpsPerAggregator, beneficiary common.Address) (*types.Transaction, error) { + return _EntryPoint.contract.Transact(opts, "handleAggregatedOps", opsPerAggregator, beneficiary) +} + +func (_EntryPoint *EntryPointSession) HandleAggregatedOps(opsPerAggregator []IEntryPointUserOpsPerAggregator, beneficiary common.Address) (*types.Transaction, error) { + return _EntryPoint.Contract.HandleAggregatedOps(&_EntryPoint.TransactOpts, opsPerAggregator, beneficiary) +} + +func (_EntryPoint *EntryPointTransactorSession) HandleAggregatedOps(opsPerAggregator []IEntryPointUserOpsPerAggregator, beneficiary common.Address) (*types.Transaction, error) { + return _EntryPoint.Contract.HandleAggregatedOps(&_EntryPoint.TransactOpts, opsPerAggregator, beneficiary) +} + +func (_EntryPoint *EntryPointTransactor) HandleOps(opts *bind.TransactOpts, ops []UserOperation, beneficiary common.Address) (*types.Transaction, error) { + return _EntryPoint.contract.Transact(opts, "handleOps", ops, beneficiary) +} + +func (_EntryPoint *EntryPointSession) HandleOps(ops []UserOperation, beneficiary common.Address) (*types.Transaction, error) { + return _EntryPoint.Contract.HandleOps(&_EntryPoint.TransactOpts, ops, beneficiary) +} + +func (_EntryPoint *EntryPointTransactorSession) HandleOps(ops []UserOperation, beneficiary common.Address) (*types.Transaction, error) { + return _EntryPoint.Contract.HandleOps(&_EntryPoint.TransactOpts, ops, beneficiary) +} + +func (_EntryPoint *EntryPointTransactor) InnerHandleOp(opts *bind.TransactOpts, callData []byte, opInfo EntryPointUserOpInfo, context []byte) (*types.Transaction, error) { + return _EntryPoint.contract.Transact(opts, "innerHandleOp", callData, opInfo, context) +} + +func (_EntryPoint *EntryPointSession) InnerHandleOp(callData []byte, opInfo EntryPointUserOpInfo, context []byte) (*types.Transaction, error) { + return _EntryPoint.Contract.InnerHandleOp(&_EntryPoint.TransactOpts, callData, opInfo, context) +} + +func (_EntryPoint *EntryPointTransactorSession) InnerHandleOp(callData []byte, opInfo EntryPointUserOpInfo, context []byte) (*types.Transaction, error) { + return _EntryPoint.Contract.InnerHandleOp(&_EntryPoint.TransactOpts, callData, opInfo, context) +} + +func (_EntryPoint *EntryPointTransactor) SimulateHandleOp(opts *bind.TransactOpts, op UserOperation, target common.Address, targetCallData []byte) (*types.Transaction, error) { + return _EntryPoint.contract.Transact(opts, "simulateHandleOp", op, target, targetCallData) +} + +func (_EntryPoint *EntryPointSession) SimulateHandleOp(op UserOperation, target common.Address, targetCallData []byte) (*types.Transaction, error) { + return _EntryPoint.Contract.SimulateHandleOp(&_EntryPoint.TransactOpts, op, target, targetCallData) +} + +func (_EntryPoint *EntryPointTransactorSession) SimulateHandleOp(op UserOperation, target common.Address, targetCallData []byte) (*types.Transaction, error) { + return _EntryPoint.Contract.SimulateHandleOp(&_EntryPoint.TransactOpts, op, target, targetCallData) +} + +func (_EntryPoint *EntryPointTransactor) SimulateValidation(opts *bind.TransactOpts, userOp UserOperation) (*types.Transaction, error) { + return _EntryPoint.contract.Transact(opts, "simulateValidation", userOp) +} + +func (_EntryPoint *EntryPointSession) SimulateValidation(userOp UserOperation) (*types.Transaction, error) { + return _EntryPoint.Contract.SimulateValidation(&_EntryPoint.TransactOpts, userOp) +} + +func (_EntryPoint *EntryPointTransactorSession) SimulateValidation(userOp UserOperation) (*types.Transaction, error) { + return _EntryPoint.Contract.SimulateValidation(&_EntryPoint.TransactOpts, userOp) +} + +func (_EntryPoint *EntryPointTransactor) UnlockStake(opts *bind.TransactOpts) (*types.Transaction, error) { + return _EntryPoint.contract.Transact(opts, "unlockStake") +} + +func (_EntryPoint *EntryPointSession) UnlockStake() (*types.Transaction, error) { + return _EntryPoint.Contract.UnlockStake(&_EntryPoint.TransactOpts) +} + +func (_EntryPoint *EntryPointTransactorSession) UnlockStake() (*types.Transaction, error) { + return _EntryPoint.Contract.UnlockStake(&_EntryPoint.TransactOpts) +} + +func (_EntryPoint *EntryPointTransactor) WithdrawStake(opts *bind.TransactOpts, withdrawAddress common.Address) (*types.Transaction, error) { + return _EntryPoint.contract.Transact(opts, "withdrawStake", withdrawAddress) +} + +func (_EntryPoint *EntryPointSession) WithdrawStake(withdrawAddress common.Address) (*types.Transaction, error) { + return _EntryPoint.Contract.WithdrawStake(&_EntryPoint.TransactOpts, withdrawAddress) +} + +func (_EntryPoint *EntryPointTransactorSession) WithdrawStake(withdrawAddress common.Address) (*types.Transaction, error) { + return _EntryPoint.Contract.WithdrawStake(&_EntryPoint.TransactOpts, withdrawAddress) +} + +func (_EntryPoint *EntryPointTransactor) WithdrawTo(opts *bind.TransactOpts, withdrawAddress common.Address, withdrawAmount *big.Int) (*types.Transaction, error) { + return _EntryPoint.contract.Transact(opts, "withdrawTo", withdrawAddress, withdrawAmount) +} + +func (_EntryPoint *EntryPointSession) WithdrawTo(withdrawAddress common.Address, withdrawAmount *big.Int) (*types.Transaction, error) { + return _EntryPoint.Contract.WithdrawTo(&_EntryPoint.TransactOpts, withdrawAddress, withdrawAmount) +} + +func (_EntryPoint *EntryPointTransactorSession) WithdrawTo(withdrawAddress common.Address, withdrawAmount *big.Int) (*types.Transaction, error) { + return _EntryPoint.Contract.WithdrawTo(&_EntryPoint.TransactOpts, withdrawAddress, withdrawAmount) +} + +func (_EntryPoint *EntryPointTransactor) Receive(opts *bind.TransactOpts) (*types.Transaction, error) { + return _EntryPoint.contract.RawTransact(opts, nil) +} + +func (_EntryPoint *EntryPointSession) Receive() (*types.Transaction, error) { + return _EntryPoint.Contract.Receive(&_EntryPoint.TransactOpts) +} + +func (_EntryPoint *EntryPointTransactorSession) Receive() (*types.Transaction, error) { + return _EntryPoint.Contract.Receive(&_EntryPoint.TransactOpts) +} + +type EntryPointAccountDeployedIterator struct { + Event *EntryPointAccountDeployed + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *EntryPointAccountDeployedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(EntryPointAccountDeployed) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(EntryPointAccountDeployed) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *EntryPointAccountDeployedIterator) Error() error { + return it.fail +} + +func (it *EntryPointAccountDeployedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type EntryPointAccountDeployed struct { + UserOpHash [32]byte + Sender common.Address + Factory common.Address + Paymaster common.Address + Raw types.Log +} + +func (_EntryPoint *EntryPointFilterer) FilterAccountDeployed(opts *bind.FilterOpts, userOpHash [][32]byte, sender []common.Address) (*EntryPointAccountDeployedIterator, error) { + + var userOpHashRule []interface{} + for _, userOpHashItem := range userOpHash { + userOpHashRule = append(userOpHashRule, userOpHashItem) + } + var senderRule []interface{} + for _, senderItem := range sender { + senderRule = append(senderRule, senderItem) + } + + logs, sub, err := _EntryPoint.contract.FilterLogs(opts, "AccountDeployed", userOpHashRule, senderRule) + if err != nil { + return nil, err + } + return &EntryPointAccountDeployedIterator{contract: _EntryPoint.contract, event: "AccountDeployed", logs: logs, sub: sub}, nil +} + +func (_EntryPoint *EntryPointFilterer) WatchAccountDeployed(opts *bind.WatchOpts, sink chan<- *EntryPointAccountDeployed, userOpHash [][32]byte, sender []common.Address) (event.Subscription, error) { + + var userOpHashRule []interface{} + for _, userOpHashItem := range userOpHash { + userOpHashRule = append(userOpHashRule, userOpHashItem) + } + var senderRule []interface{} + for _, senderItem := range sender { + senderRule = append(senderRule, senderItem) + } + + logs, sub, err := _EntryPoint.contract.WatchLogs(opts, "AccountDeployed", userOpHashRule, senderRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(EntryPointAccountDeployed) + if err := _EntryPoint.contract.UnpackLog(event, "AccountDeployed", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_EntryPoint *EntryPointFilterer) ParseAccountDeployed(log types.Log) (*EntryPointAccountDeployed, error) { + event := new(EntryPointAccountDeployed) + if err := _EntryPoint.contract.UnpackLog(event, "AccountDeployed", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type EntryPointDepositedIterator struct { + Event *EntryPointDeposited + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *EntryPointDepositedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(EntryPointDeposited) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(EntryPointDeposited) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *EntryPointDepositedIterator) Error() error { + return it.fail +} + +func (it *EntryPointDepositedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type EntryPointDeposited struct { + Account common.Address + TotalDeposit *big.Int + Raw types.Log +} + +func (_EntryPoint *EntryPointFilterer) FilterDeposited(opts *bind.FilterOpts, account []common.Address) (*EntryPointDepositedIterator, error) { + + var accountRule []interface{} + for _, accountItem := range account { + accountRule = append(accountRule, accountItem) + } + + logs, sub, err := _EntryPoint.contract.FilterLogs(opts, "Deposited", accountRule) + if err != nil { + return nil, err + } + return &EntryPointDepositedIterator{contract: _EntryPoint.contract, event: "Deposited", logs: logs, sub: sub}, nil +} + +func (_EntryPoint *EntryPointFilterer) WatchDeposited(opts *bind.WatchOpts, sink chan<- *EntryPointDeposited, account []common.Address) (event.Subscription, error) { + + var accountRule []interface{} + for _, accountItem := range account { + accountRule = append(accountRule, accountItem) + } + + logs, sub, err := _EntryPoint.contract.WatchLogs(opts, "Deposited", accountRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(EntryPointDeposited) + if err := _EntryPoint.contract.UnpackLog(event, "Deposited", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_EntryPoint *EntryPointFilterer) ParseDeposited(log types.Log) (*EntryPointDeposited, error) { + event := new(EntryPointDeposited) + if err := _EntryPoint.contract.UnpackLog(event, "Deposited", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type EntryPointSignatureAggregatorChangedIterator struct { + Event *EntryPointSignatureAggregatorChanged + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *EntryPointSignatureAggregatorChangedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(EntryPointSignatureAggregatorChanged) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(EntryPointSignatureAggregatorChanged) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *EntryPointSignatureAggregatorChangedIterator) Error() error { + return it.fail +} + +func (it *EntryPointSignatureAggregatorChangedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type EntryPointSignatureAggregatorChanged struct { + Aggregator common.Address + Raw types.Log +} + +func (_EntryPoint *EntryPointFilterer) FilterSignatureAggregatorChanged(opts *bind.FilterOpts, aggregator []common.Address) (*EntryPointSignatureAggregatorChangedIterator, error) { + + var aggregatorRule []interface{} + for _, aggregatorItem := range aggregator { + aggregatorRule = append(aggregatorRule, aggregatorItem) + } + + logs, sub, err := _EntryPoint.contract.FilterLogs(opts, "SignatureAggregatorChanged", aggregatorRule) + if err != nil { + return nil, err + } + return &EntryPointSignatureAggregatorChangedIterator{contract: _EntryPoint.contract, event: "SignatureAggregatorChanged", logs: logs, sub: sub}, nil +} + +func (_EntryPoint *EntryPointFilterer) WatchSignatureAggregatorChanged(opts *bind.WatchOpts, sink chan<- *EntryPointSignatureAggregatorChanged, aggregator []common.Address) (event.Subscription, error) { + + var aggregatorRule []interface{} + for _, aggregatorItem := range aggregator { + aggregatorRule = append(aggregatorRule, aggregatorItem) + } + + logs, sub, err := _EntryPoint.contract.WatchLogs(opts, "SignatureAggregatorChanged", aggregatorRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(EntryPointSignatureAggregatorChanged) + if err := _EntryPoint.contract.UnpackLog(event, "SignatureAggregatorChanged", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_EntryPoint *EntryPointFilterer) ParseSignatureAggregatorChanged(log types.Log) (*EntryPointSignatureAggregatorChanged, error) { + event := new(EntryPointSignatureAggregatorChanged) + if err := _EntryPoint.contract.UnpackLog(event, "SignatureAggregatorChanged", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type EntryPointStakeLockedIterator struct { + Event *EntryPointStakeLocked + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *EntryPointStakeLockedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(EntryPointStakeLocked) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(EntryPointStakeLocked) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *EntryPointStakeLockedIterator) Error() error { + return it.fail +} + +func (it *EntryPointStakeLockedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type EntryPointStakeLocked struct { + Account common.Address + TotalStaked *big.Int + UnstakeDelaySec *big.Int + Raw types.Log +} + +func (_EntryPoint *EntryPointFilterer) FilterStakeLocked(opts *bind.FilterOpts, account []common.Address) (*EntryPointStakeLockedIterator, error) { + + var accountRule []interface{} + for _, accountItem := range account { + accountRule = append(accountRule, accountItem) + } + + logs, sub, err := _EntryPoint.contract.FilterLogs(opts, "StakeLocked", accountRule) + if err != nil { + return nil, err + } + return &EntryPointStakeLockedIterator{contract: _EntryPoint.contract, event: "StakeLocked", logs: logs, sub: sub}, nil +} + +func (_EntryPoint *EntryPointFilterer) WatchStakeLocked(opts *bind.WatchOpts, sink chan<- *EntryPointStakeLocked, account []common.Address) (event.Subscription, error) { + + var accountRule []interface{} + for _, accountItem := range account { + accountRule = append(accountRule, accountItem) + } + + logs, sub, err := _EntryPoint.contract.WatchLogs(opts, "StakeLocked", accountRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(EntryPointStakeLocked) + if err := _EntryPoint.contract.UnpackLog(event, "StakeLocked", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_EntryPoint *EntryPointFilterer) ParseStakeLocked(log types.Log) (*EntryPointStakeLocked, error) { + event := new(EntryPointStakeLocked) + if err := _EntryPoint.contract.UnpackLog(event, "StakeLocked", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type EntryPointStakeUnlockedIterator struct { + Event *EntryPointStakeUnlocked + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *EntryPointStakeUnlockedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(EntryPointStakeUnlocked) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(EntryPointStakeUnlocked) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *EntryPointStakeUnlockedIterator) Error() error { + return it.fail +} + +func (it *EntryPointStakeUnlockedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type EntryPointStakeUnlocked struct { + Account common.Address + WithdrawTime *big.Int + Raw types.Log +} + +func (_EntryPoint *EntryPointFilterer) FilterStakeUnlocked(opts *bind.FilterOpts, account []common.Address) (*EntryPointStakeUnlockedIterator, error) { + + var accountRule []interface{} + for _, accountItem := range account { + accountRule = append(accountRule, accountItem) + } + + logs, sub, err := _EntryPoint.contract.FilterLogs(opts, "StakeUnlocked", accountRule) + if err != nil { + return nil, err + } + return &EntryPointStakeUnlockedIterator{contract: _EntryPoint.contract, event: "StakeUnlocked", logs: logs, sub: sub}, nil +} + +func (_EntryPoint *EntryPointFilterer) WatchStakeUnlocked(opts *bind.WatchOpts, sink chan<- *EntryPointStakeUnlocked, account []common.Address) (event.Subscription, error) { + + var accountRule []interface{} + for _, accountItem := range account { + accountRule = append(accountRule, accountItem) + } + + logs, sub, err := _EntryPoint.contract.WatchLogs(opts, "StakeUnlocked", accountRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(EntryPointStakeUnlocked) + if err := _EntryPoint.contract.UnpackLog(event, "StakeUnlocked", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_EntryPoint *EntryPointFilterer) ParseStakeUnlocked(log types.Log) (*EntryPointStakeUnlocked, error) { + event := new(EntryPointStakeUnlocked) + if err := _EntryPoint.contract.UnpackLog(event, "StakeUnlocked", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type EntryPointStakeWithdrawnIterator struct { + Event *EntryPointStakeWithdrawn + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *EntryPointStakeWithdrawnIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(EntryPointStakeWithdrawn) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(EntryPointStakeWithdrawn) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *EntryPointStakeWithdrawnIterator) Error() error { + return it.fail +} + +func (it *EntryPointStakeWithdrawnIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type EntryPointStakeWithdrawn struct { + Account common.Address + WithdrawAddress common.Address + Amount *big.Int + Raw types.Log +} + +func (_EntryPoint *EntryPointFilterer) FilterStakeWithdrawn(opts *bind.FilterOpts, account []common.Address) (*EntryPointStakeWithdrawnIterator, error) { + + var accountRule []interface{} + for _, accountItem := range account { + accountRule = append(accountRule, accountItem) + } + + logs, sub, err := _EntryPoint.contract.FilterLogs(opts, "StakeWithdrawn", accountRule) + if err != nil { + return nil, err + } + return &EntryPointStakeWithdrawnIterator{contract: _EntryPoint.contract, event: "StakeWithdrawn", logs: logs, sub: sub}, nil +} + +func (_EntryPoint *EntryPointFilterer) WatchStakeWithdrawn(opts *bind.WatchOpts, sink chan<- *EntryPointStakeWithdrawn, account []common.Address) (event.Subscription, error) { + + var accountRule []interface{} + for _, accountItem := range account { + accountRule = append(accountRule, accountItem) + } + + logs, sub, err := _EntryPoint.contract.WatchLogs(opts, "StakeWithdrawn", accountRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(EntryPointStakeWithdrawn) + if err := _EntryPoint.contract.UnpackLog(event, "StakeWithdrawn", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_EntryPoint *EntryPointFilterer) ParseStakeWithdrawn(log types.Log) (*EntryPointStakeWithdrawn, error) { + event := new(EntryPointStakeWithdrawn) + if err := _EntryPoint.contract.UnpackLog(event, "StakeWithdrawn", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type EntryPointUserOperationEventIterator struct { + Event *EntryPointUserOperationEvent + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *EntryPointUserOperationEventIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(EntryPointUserOperationEvent) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(EntryPointUserOperationEvent) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *EntryPointUserOperationEventIterator) Error() error { + return it.fail +} + +func (it *EntryPointUserOperationEventIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type EntryPointUserOperationEvent struct { + UserOpHash [32]byte + Sender common.Address + Paymaster common.Address + Nonce *big.Int + Success bool + ActualGasCost *big.Int + ActualGasUsed *big.Int + Raw types.Log +} + +func (_EntryPoint *EntryPointFilterer) FilterUserOperationEvent(opts *bind.FilterOpts, userOpHash [][32]byte, sender []common.Address, paymaster []common.Address) (*EntryPointUserOperationEventIterator, error) { + + var userOpHashRule []interface{} + for _, userOpHashItem := range userOpHash { + userOpHashRule = append(userOpHashRule, userOpHashItem) + } + var senderRule []interface{} + for _, senderItem := range sender { + senderRule = append(senderRule, senderItem) + } + var paymasterRule []interface{} + for _, paymasterItem := range paymaster { + paymasterRule = append(paymasterRule, paymasterItem) + } + + logs, sub, err := _EntryPoint.contract.FilterLogs(opts, "UserOperationEvent", userOpHashRule, senderRule, paymasterRule) + if err != nil { + return nil, err + } + return &EntryPointUserOperationEventIterator{contract: _EntryPoint.contract, event: "UserOperationEvent", logs: logs, sub: sub}, nil +} + +func (_EntryPoint *EntryPointFilterer) WatchUserOperationEvent(opts *bind.WatchOpts, sink chan<- *EntryPointUserOperationEvent, userOpHash [][32]byte, sender []common.Address, paymaster []common.Address) (event.Subscription, error) { + + var userOpHashRule []interface{} + for _, userOpHashItem := range userOpHash { + userOpHashRule = append(userOpHashRule, userOpHashItem) + } + var senderRule []interface{} + for _, senderItem := range sender { + senderRule = append(senderRule, senderItem) + } + var paymasterRule []interface{} + for _, paymasterItem := range paymaster { + paymasterRule = append(paymasterRule, paymasterItem) + } + + logs, sub, err := _EntryPoint.contract.WatchLogs(opts, "UserOperationEvent", userOpHashRule, senderRule, paymasterRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(EntryPointUserOperationEvent) + if err := _EntryPoint.contract.UnpackLog(event, "UserOperationEvent", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_EntryPoint *EntryPointFilterer) ParseUserOperationEvent(log types.Log) (*EntryPointUserOperationEvent, error) { + event := new(EntryPointUserOperationEvent) + if err := _EntryPoint.contract.UnpackLog(event, "UserOperationEvent", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type EntryPointUserOperationRevertReasonIterator struct { + Event *EntryPointUserOperationRevertReason + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *EntryPointUserOperationRevertReasonIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(EntryPointUserOperationRevertReason) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(EntryPointUserOperationRevertReason) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *EntryPointUserOperationRevertReasonIterator) Error() error { + return it.fail +} + +func (it *EntryPointUserOperationRevertReasonIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type EntryPointUserOperationRevertReason struct { + UserOpHash [32]byte + Sender common.Address + Nonce *big.Int + RevertReason []byte + Raw types.Log +} + +func (_EntryPoint *EntryPointFilterer) FilterUserOperationRevertReason(opts *bind.FilterOpts, userOpHash [][32]byte, sender []common.Address) (*EntryPointUserOperationRevertReasonIterator, error) { + + var userOpHashRule []interface{} + for _, userOpHashItem := range userOpHash { + userOpHashRule = append(userOpHashRule, userOpHashItem) + } + var senderRule []interface{} + for _, senderItem := range sender { + senderRule = append(senderRule, senderItem) + } + + logs, sub, err := _EntryPoint.contract.FilterLogs(opts, "UserOperationRevertReason", userOpHashRule, senderRule) + if err != nil { + return nil, err + } + return &EntryPointUserOperationRevertReasonIterator{contract: _EntryPoint.contract, event: "UserOperationRevertReason", logs: logs, sub: sub}, nil +} + +func (_EntryPoint *EntryPointFilterer) WatchUserOperationRevertReason(opts *bind.WatchOpts, sink chan<- *EntryPointUserOperationRevertReason, userOpHash [][32]byte, sender []common.Address) (event.Subscription, error) { + + var userOpHashRule []interface{} + for _, userOpHashItem := range userOpHash { + userOpHashRule = append(userOpHashRule, userOpHashItem) + } + var senderRule []interface{} + for _, senderItem := range sender { + senderRule = append(senderRule, senderItem) + } + + logs, sub, err := _EntryPoint.contract.WatchLogs(opts, "UserOperationRevertReason", userOpHashRule, senderRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(EntryPointUserOperationRevertReason) + if err := _EntryPoint.contract.UnpackLog(event, "UserOperationRevertReason", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_EntryPoint *EntryPointFilterer) ParseUserOperationRevertReason(log types.Log) (*EntryPointUserOperationRevertReason, error) { + event := new(EntryPointUserOperationRevertReason) + if err := _EntryPoint.contract.UnpackLog(event, "UserOperationRevertReason", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type EntryPointWithdrawnIterator struct { + Event *EntryPointWithdrawn + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *EntryPointWithdrawnIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(EntryPointWithdrawn) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(EntryPointWithdrawn) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *EntryPointWithdrawnIterator) Error() error { + return it.fail +} + +func (it *EntryPointWithdrawnIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type EntryPointWithdrawn struct { + Account common.Address + WithdrawAddress common.Address + Amount *big.Int + Raw types.Log +} + +func (_EntryPoint *EntryPointFilterer) FilterWithdrawn(opts *bind.FilterOpts, account []common.Address) (*EntryPointWithdrawnIterator, error) { + + var accountRule []interface{} + for _, accountItem := range account { + accountRule = append(accountRule, accountItem) + } + + logs, sub, err := _EntryPoint.contract.FilterLogs(opts, "Withdrawn", accountRule) + if err != nil { + return nil, err + } + return &EntryPointWithdrawnIterator{contract: _EntryPoint.contract, event: "Withdrawn", logs: logs, sub: sub}, nil +} + +func (_EntryPoint *EntryPointFilterer) WatchWithdrawn(opts *bind.WatchOpts, sink chan<- *EntryPointWithdrawn, account []common.Address) (event.Subscription, error) { + + var accountRule []interface{} + for _, accountItem := range account { + accountRule = append(accountRule, accountItem) + } + + logs, sub, err := _EntryPoint.contract.WatchLogs(opts, "Withdrawn", accountRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(EntryPointWithdrawn) + if err := _EntryPoint.contract.UnpackLog(event, "Withdrawn", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_EntryPoint *EntryPointFilterer) ParseWithdrawn(log types.Log) (*EntryPointWithdrawn, error) { + event := new(EntryPointWithdrawn) + if err := _EntryPoint.contract.UnpackLog(event, "Withdrawn", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type Deposits struct { + Deposit *big.Int + Staked bool + Stake *big.Int + UnstakeDelaySec uint32 + WithdrawTime *big.Int +} + +func (_EntryPoint *EntryPoint) ParseLog(log types.Log) (generated.AbigenLog, error) { + switch log.Topics[0] { + case _EntryPoint.abi.Events["AccountDeployed"].ID: + return _EntryPoint.ParseAccountDeployed(log) + case _EntryPoint.abi.Events["Deposited"].ID: + return _EntryPoint.ParseDeposited(log) + case _EntryPoint.abi.Events["SignatureAggregatorChanged"].ID: + return _EntryPoint.ParseSignatureAggregatorChanged(log) + case _EntryPoint.abi.Events["StakeLocked"].ID: + return _EntryPoint.ParseStakeLocked(log) + case _EntryPoint.abi.Events["StakeUnlocked"].ID: + return _EntryPoint.ParseStakeUnlocked(log) + case _EntryPoint.abi.Events["StakeWithdrawn"].ID: + return _EntryPoint.ParseStakeWithdrawn(log) + case _EntryPoint.abi.Events["UserOperationEvent"].ID: + return _EntryPoint.ParseUserOperationEvent(log) + case _EntryPoint.abi.Events["UserOperationRevertReason"].ID: + return _EntryPoint.ParseUserOperationRevertReason(log) + case _EntryPoint.abi.Events["Withdrawn"].ID: + return _EntryPoint.ParseWithdrawn(log) + + default: + return nil, fmt.Errorf("abigen wrapper received unknown log topic: %v", log.Topics[0]) + } +} + +func (EntryPointAccountDeployed) Topic() common.Hash { + return common.HexToHash("0xd51a9c61267aa6196961883ecf5ff2da6619c37dac0fa92122513fb32c032d2d") +} + +func (EntryPointDeposited) Topic() common.Hash { + return common.HexToHash("0x2da466a7b24304f47e87fa2e1e5a81b9831ce54fec19055ce277ca2f39ba42c4") +} + +func (EntryPointSignatureAggregatorChanged) Topic() common.Hash { + return common.HexToHash("0x575ff3acadd5ab348fe1855e217e0f3678f8d767d7494c9f9fefbee2e17cca4d") +} + +func (EntryPointStakeLocked) Topic() common.Hash { + return common.HexToHash("0xa5ae833d0bb1dcd632d98a8b70973e8516812898e19bf27b70071ebc8dc52c01") +} + +func (EntryPointStakeUnlocked) Topic() common.Hash { + return common.HexToHash("0xfa9b3c14cc825c412c9ed81b3ba365a5b459439403f18829e572ed53a4180f0a") +} + +func (EntryPointStakeWithdrawn) Topic() common.Hash { + return common.HexToHash("0xb7c918e0e249f999e965cafeb6c664271b3f4317d296461500e71da39f0cbda3") +} + +func (EntryPointUserOperationEvent) Topic() common.Hash { + return common.HexToHash("0x49628fd1471006c1482da88028e9ce4dbb080b815c9b0344d39e5a8e6ec1419f") +} + +func (EntryPointUserOperationRevertReason) Topic() common.Hash { + return common.HexToHash("0x1c4fada7374c0a9ee8841fc38afe82932dc0f8e69012e927f061a8bae611a201") +} + +func (EntryPointWithdrawn) Topic() common.Hash { + return common.HexToHash("0xd1c19fbcd4551a5edfb66d43d2e337c04837afda3482b42bdf569a8fccdae5fb") +} + +func (_EntryPoint *EntryPoint) Address() common.Address { + return _EntryPoint.address +} + +type EntryPointInterface interface { + SIGVALIDATIONFAILED(opts *bind.CallOpts) (*big.Int, error) + + ValidateSenderAndPaymaster(opts *bind.CallOpts, initCode []byte, sender common.Address, paymasterAndData []byte) error + + BalanceOf(opts *bind.CallOpts, account common.Address) (*big.Int, error) + + Deposits(opts *bind.CallOpts, arg0 common.Address) (Deposits, + + error) + + GetDepositInfo(opts *bind.CallOpts, account common.Address) (IStakeManagerDepositInfo, error) + + GetUserOpHash(opts *bind.CallOpts, userOp UserOperation) ([32]byte, error) + + AddStake(opts *bind.TransactOpts, unstakeDelaySec uint32) (*types.Transaction, error) + + DepositTo(opts *bind.TransactOpts, account common.Address) (*types.Transaction, error) + + GetSenderAddress(opts *bind.TransactOpts, initCode []byte) (*types.Transaction, error) + + HandleAggregatedOps(opts *bind.TransactOpts, opsPerAggregator []IEntryPointUserOpsPerAggregator, beneficiary common.Address) (*types.Transaction, error) + + HandleOps(opts *bind.TransactOpts, ops []UserOperation, beneficiary common.Address) (*types.Transaction, error) + + InnerHandleOp(opts *bind.TransactOpts, callData []byte, opInfo EntryPointUserOpInfo, context []byte) (*types.Transaction, error) + + SimulateHandleOp(opts *bind.TransactOpts, op UserOperation, target common.Address, targetCallData []byte) (*types.Transaction, error) + + SimulateValidation(opts *bind.TransactOpts, userOp UserOperation) (*types.Transaction, error) + + UnlockStake(opts *bind.TransactOpts) (*types.Transaction, error) + + WithdrawStake(opts *bind.TransactOpts, withdrawAddress common.Address) (*types.Transaction, error) + + WithdrawTo(opts *bind.TransactOpts, withdrawAddress common.Address, withdrawAmount *big.Int) (*types.Transaction, error) + + Receive(opts *bind.TransactOpts) (*types.Transaction, error) + + FilterAccountDeployed(opts *bind.FilterOpts, userOpHash [][32]byte, sender []common.Address) (*EntryPointAccountDeployedIterator, error) + + WatchAccountDeployed(opts *bind.WatchOpts, sink chan<- *EntryPointAccountDeployed, userOpHash [][32]byte, sender []common.Address) (event.Subscription, error) + + ParseAccountDeployed(log types.Log) (*EntryPointAccountDeployed, error) + + FilterDeposited(opts *bind.FilterOpts, account []common.Address) (*EntryPointDepositedIterator, error) + + WatchDeposited(opts *bind.WatchOpts, sink chan<- *EntryPointDeposited, account []common.Address) (event.Subscription, error) + + ParseDeposited(log types.Log) (*EntryPointDeposited, error) + + FilterSignatureAggregatorChanged(opts *bind.FilterOpts, aggregator []common.Address) (*EntryPointSignatureAggregatorChangedIterator, error) + + WatchSignatureAggregatorChanged(opts *bind.WatchOpts, sink chan<- *EntryPointSignatureAggregatorChanged, aggregator []common.Address) (event.Subscription, error) + + ParseSignatureAggregatorChanged(log types.Log) (*EntryPointSignatureAggregatorChanged, error) + + FilterStakeLocked(opts *bind.FilterOpts, account []common.Address) (*EntryPointStakeLockedIterator, error) + + WatchStakeLocked(opts *bind.WatchOpts, sink chan<- *EntryPointStakeLocked, account []common.Address) (event.Subscription, error) + + ParseStakeLocked(log types.Log) (*EntryPointStakeLocked, error) + + FilterStakeUnlocked(opts *bind.FilterOpts, account []common.Address) (*EntryPointStakeUnlockedIterator, error) + + WatchStakeUnlocked(opts *bind.WatchOpts, sink chan<- *EntryPointStakeUnlocked, account []common.Address) (event.Subscription, error) + + ParseStakeUnlocked(log types.Log) (*EntryPointStakeUnlocked, error) + + FilterStakeWithdrawn(opts *bind.FilterOpts, account []common.Address) (*EntryPointStakeWithdrawnIterator, error) + + WatchStakeWithdrawn(opts *bind.WatchOpts, sink chan<- *EntryPointStakeWithdrawn, account []common.Address) (event.Subscription, error) + + ParseStakeWithdrawn(log types.Log) (*EntryPointStakeWithdrawn, error) + + FilterUserOperationEvent(opts *bind.FilterOpts, userOpHash [][32]byte, sender []common.Address, paymaster []common.Address) (*EntryPointUserOperationEventIterator, error) + + WatchUserOperationEvent(opts *bind.WatchOpts, sink chan<- *EntryPointUserOperationEvent, userOpHash [][32]byte, sender []common.Address, paymaster []common.Address) (event.Subscription, error) + + ParseUserOperationEvent(log types.Log) (*EntryPointUserOperationEvent, error) + + FilterUserOperationRevertReason(opts *bind.FilterOpts, userOpHash [][32]byte, sender []common.Address) (*EntryPointUserOperationRevertReasonIterator, error) + + WatchUserOperationRevertReason(opts *bind.WatchOpts, sink chan<- *EntryPointUserOperationRevertReason, userOpHash [][32]byte, sender []common.Address) (event.Subscription, error) + + ParseUserOperationRevertReason(log types.Log) (*EntryPointUserOperationRevertReason, error) + + FilterWithdrawn(opts *bind.FilterOpts, account []common.Address) (*EntryPointWithdrawnIterator, error) + + WatchWithdrawn(opts *bind.WatchOpts, sink chan<- *EntryPointWithdrawn, account []common.Address) (event.Subscription, error) + + ParseWithdrawn(log types.Log) (*EntryPointWithdrawn, error) + + ParseLog(log types.Log) (generated.AbigenLog, error) + + Address() common.Address +} diff --git a/core/gethwrappers/transmission/generated/greeter_wrapper/greeter_wrapper.go b/core/gethwrappers/transmission/generated/greeter_wrapper/greeter_wrapper.go new file mode 100644 index 00000000000..0f9e4a7719d --- /dev/null +++ b/core/gethwrappers/transmission/generated/greeter_wrapper/greeter_wrapper.go @@ -0,0 +1,216 @@ +// Code generated - DO NOT EDIT. +// This file is a generated binding and any manual changes will be lost. + +package greeter_wrapper + +import ( + "errors" + "math/big" + "strings" + + ethereum "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/event" +) + +var ( + _ = errors.New + _ = big.NewInt + _ = strings.NewReader + _ = ethereum.NotFound + _ = bind.Bind + _ = common.Big1 + _ = types.BloomLookup + _ = event.NewSubscription + _ = abi.ConvertType +) + +var GreeterMetaData = &bind.MetaData{ + ABI: "[{\"inputs\":[],\"name\":\"getGreeting\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"greeting\",\"type\":\"string\"}],\"name\":\"setGreeting\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", + Bin: "0x608060405234801561001057600080fd5b50610443806100206000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c8063a41368621461003b578063fe50cc7214610050575b600080fd5b61004e61004936600461013f565b61006e565b005b61005861007e565b604051610065919061020e565b60405180910390f35b600061007a828261031c565b5050565b60606000805461008d9061027a565b80601f01602080910402602001604051908101604052809291908181526020018280546100b99061027a565b80156101065780601f106100db57610100808354040283529160200191610106565b820191906000526020600020905b8154815290600101906020018083116100e957829003601f168201915b5050505050905090565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60006020828403121561015157600080fd5b813567ffffffffffffffff8082111561016957600080fd5b818401915084601f83011261017d57600080fd5b81358181111561018f5761018f610110565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f011681019083821181831017156101d5576101d5610110565b816040528281528760208487010111156101ee57600080fd5b826020860160208301376000928101602001929092525095945050505050565b600060208083528351808285015260005b8181101561023b5785810183015185820160400152820161021f565b5060006040828601015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8301168501019250505092915050565b600181811c9082168061028e57607f821691505b6020821081036102c7577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b601f82111561031757600081815260208120601f850160051c810160208610156102f45750805b601f850160051c820191505b8181101561031357828155600101610300565b5050505b505050565b815167ffffffffffffffff81111561033657610336610110565b61034a81610344845461027a565b846102cd565b602080601f83116001811461039d57600084156103675750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b178555610313565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b828110156103ea578886015182559484019460019091019084016103cb565b508582101561042657878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b0190555056fea164736f6c6343000813000a", +} + +var GreeterABI = GreeterMetaData.ABI + +var GreeterBin = GreeterMetaData.Bin + +func DeployGreeter(auth *bind.TransactOpts, backend bind.ContractBackend) (common.Address, *types.Transaction, *Greeter, error) { + parsed, err := GreeterMetaData.GetAbi() + if err != nil { + return common.Address{}, nil, nil, err + } + if parsed == nil { + return common.Address{}, nil, nil, errors.New("GetABI returned nil") + } + + address, tx, contract, err := bind.DeployContract(auth, *parsed, common.FromHex(GreeterBin), backend) + if err != nil { + return common.Address{}, nil, nil, err + } + return address, tx, &Greeter{address: address, abi: *parsed, GreeterCaller: GreeterCaller{contract: contract}, GreeterTransactor: GreeterTransactor{contract: contract}, GreeterFilterer: GreeterFilterer{contract: contract}}, nil +} + +type Greeter struct { + address common.Address + abi abi.ABI + GreeterCaller + GreeterTransactor + GreeterFilterer +} + +type GreeterCaller struct { + contract *bind.BoundContract +} + +type GreeterTransactor struct { + contract *bind.BoundContract +} + +type GreeterFilterer struct { + contract *bind.BoundContract +} + +type GreeterSession struct { + Contract *Greeter + CallOpts bind.CallOpts + TransactOpts bind.TransactOpts +} + +type GreeterCallerSession struct { + Contract *GreeterCaller + CallOpts bind.CallOpts +} + +type GreeterTransactorSession struct { + Contract *GreeterTransactor + TransactOpts bind.TransactOpts +} + +type GreeterRaw struct { + Contract *Greeter +} + +type GreeterCallerRaw struct { + Contract *GreeterCaller +} + +type GreeterTransactorRaw struct { + Contract *GreeterTransactor +} + +func NewGreeter(address common.Address, backend bind.ContractBackend) (*Greeter, error) { + abi, err := abi.JSON(strings.NewReader(GreeterABI)) + if err != nil { + return nil, err + } + contract, err := bindGreeter(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &Greeter{address: address, abi: abi, GreeterCaller: GreeterCaller{contract: contract}, GreeterTransactor: GreeterTransactor{contract: contract}, GreeterFilterer: GreeterFilterer{contract: contract}}, nil +} + +func NewGreeterCaller(address common.Address, caller bind.ContractCaller) (*GreeterCaller, error) { + contract, err := bindGreeter(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &GreeterCaller{contract: contract}, nil +} + +func NewGreeterTransactor(address common.Address, transactor bind.ContractTransactor) (*GreeterTransactor, error) { + contract, err := bindGreeter(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &GreeterTransactor{contract: contract}, nil +} + +func NewGreeterFilterer(address common.Address, filterer bind.ContractFilterer) (*GreeterFilterer, error) { + contract, err := bindGreeter(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &GreeterFilterer{contract: contract}, nil +} + +func bindGreeter(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := GreeterMetaData.GetAbi() + if err != nil { + return nil, err + } + return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil +} + +func (_Greeter *GreeterRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _Greeter.Contract.GreeterCaller.contract.Call(opts, result, method, params...) +} + +func (_Greeter *GreeterRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _Greeter.Contract.GreeterTransactor.contract.Transfer(opts) +} + +func (_Greeter *GreeterRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _Greeter.Contract.GreeterTransactor.contract.Transact(opts, method, params...) +} + +func (_Greeter *GreeterCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _Greeter.Contract.contract.Call(opts, result, method, params...) +} + +func (_Greeter *GreeterTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _Greeter.Contract.contract.Transfer(opts) +} + +func (_Greeter *GreeterTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _Greeter.Contract.contract.Transact(opts, method, params...) +} + +func (_Greeter *GreeterCaller) GetGreeting(opts *bind.CallOpts) (string, error) { + var out []interface{} + err := _Greeter.contract.Call(opts, &out, "getGreeting") + + if err != nil { + return *new(string), err + } + + out0 := *abi.ConvertType(out[0], new(string)).(*string) + + return out0, err + +} + +func (_Greeter *GreeterSession) GetGreeting() (string, error) { + return _Greeter.Contract.GetGreeting(&_Greeter.CallOpts) +} + +func (_Greeter *GreeterCallerSession) GetGreeting() (string, error) { + return _Greeter.Contract.GetGreeting(&_Greeter.CallOpts) +} + +func (_Greeter *GreeterTransactor) SetGreeting(opts *bind.TransactOpts, greeting string) (*types.Transaction, error) { + return _Greeter.contract.Transact(opts, "setGreeting", greeting) +} + +func (_Greeter *GreeterSession) SetGreeting(greeting string) (*types.Transaction, error) { + return _Greeter.Contract.SetGreeting(&_Greeter.TransactOpts, greeting) +} + +func (_Greeter *GreeterTransactorSession) SetGreeting(greeting string) (*types.Transaction, error) { + return _Greeter.Contract.SetGreeting(&_Greeter.TransactOpts, greeting) +} + +func (_Greeter *Greeter) Address() common.Address { + return _Greeter.address +} + +type GreeterInterface interface { + GetGreeting(opts *bind.CallOpts) (string, error) + + SetGreeting(opts *bind.TransactOpts, greeting string) (*types.Transaction, error) + + Address() common.Address +} diff --git a/core/gethwrappers/transmission/generated/paymaster_wrapper/paymaster_wrapper.go b/core/gethwrappers/transmission/generated/paymaster_wrapper/paymaster_wrapper.go new file mode 100644 index 00000000000..63a2712ca3f --- /dev/null +++ b/core/gethwrappers/transmission/generated/paymaster_wrapper/paymaster_wrapper.go @@ -0,0 +1,719 @@ +// Code generated - DO NOT EDIT. +// This file is a generated binding and any manual changes will be lost. + +package paymaster_wrapper + +import ( + "errors" + "fmt" + "math/big" + "strings" + + ethereum "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/event" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated" +) + +var ( + _ = errors.New + _ = big.NewInt + _ = strings.NewReader + _ = ethereum.NotFound + _ = bind.Bind + _ = common.Big1 + _ = types.BloomLookup + _ = event.NewSubscription + _ = abi.ConvertType +) + +type UserOperation struct { + Sender common.Address + Nonce *big.Int + InitCode []byte + CallData []byte + CallGasLimit *big.Int + VerificationGasLimit *big.Int + PreVerificationGas *big.Int + MaxFeePerGas *big.Int + MaxPriorityFeePerGas *big.Int + PaymasterAndData []byte + Signature []byte +} + +var PaymasterMetaData = &bind.MetaData{ + ABI: "[{\"inputs\":[{\"internalType\":\"contractLinkTokenInterface\",\"name\":\"linkToken\",\"type\":\"address\"},{\"internalType\":\"contractAggregatorV3Interface\",\"name\":\"linkEthFeed\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"entryPoint\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"juelsNeeded\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"subscriptionBalance\",\"type\":\"uint256\"}],\"name\":\"InsufficientFunds\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidCalldata\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableFromLink\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"validator\",\"type\":\"address\"}],\"name\":\"Unauthorized\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"userOpHash\",\"type\":\"bytes32\"}],\"name\":\"UserOperationAlreadyTried\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"i_entryPoint\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"i_linkEthFeed\",\"outputs\":[{\"internalType\":\"contractAggregatorV3Interface\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"i_linkToken\",\"outputs\":[{\"internalType\":\"contractLinkTokenInterface\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"_data\",\"type\":\"bytes\"}],\"name\":\"onTokenTransfer\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"enumIPaymaster.PostOpMode\",\"name\":\"\",\"type\":\"uint8\"},{\"internalType\":\"bytes\",\"name\":\"context\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"actualGasCost\",\"type\":\"uint256\"}],\"name\":\"postOp\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"s_config\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"stalenessSeconds\",\"type\":\"uint32\"},{\"internalType\":\"int256\",\"name\":\"fallbackWeiPerUnitLink\",\"type\":\"int256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"stalenessSeconds\",\"type\":\"uint32\"},{\"internalType\":\"int256\",\"name\":\"fallbackWeiPerUnitLink\",\"type\":\"int256\"}],\"name\":\"setConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"initCode\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"callGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"verificationGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"preVerificationGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxFeePerGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxPriorityFeePerGas\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"paymasterAndData\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"signature\",\"type\":\"bytes\"}],\"internalType\":\"structUserOperation\",\"name\":\"userOp\",\"type\":\"tuple\"},{\"internalType\":\"bytes32\",\"name\":\"userOpHash\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"maxCost\",\"type\":\"uint256\"}],\"name\":\"validatePaymasterUserOp\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"context\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"validationData\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", + Bin: "0x60e06040523480156200001157600080fd5b50604051620014c4380380620014c48339810160408190526200003491620001a3565b33806000816200008b5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000be57620000be81620000df565b5050506001600160a01b0392831660805290821660a0521660c052620001f7565b336001600160a01b03821603620001395760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000082565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6001600160a01b0381168114620001a057600080fd5b50565b600080600060608486031215620001b957600080fd5b8351620001c6816200018a565b6020850151909350620001d9816200018a565b6040850151909250620001ec816200018a565b809150509250925092565b60805160a05160c0516112656200025f600039600081816101080152818161049f01528181610507015281816105cd015261063501526000818161018f0152610cb60152600081816101dc015281816103a201528181610ac90152610b8101526112656000f3fe608060405234801561001057600080fd5b50600436106100c95760003560e01c80639b9bd4de11610081578063db37983b1161005b578063db37983b146101d7578063f2fde38b146101fe578063f465c77e1461021157600080fd5b80639b9bd4de1461018a578063a4c0ed36146101b1578063a9a23409146101c457600080fd5b806379ba5097116100b257806379ba50971461014f5780638a38f365146101595780638da5cb5b1461016c57600080fd5b8063088070f5146100ce578063140fcfb114610103575b600080fd5b6002546003546100e29163ffffffff169082565b6040805163ffffffff90931683526020830191909152015b60405180910390f35b61012a7f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100fa565b610157610232565b005b610157610167366004610d5b565b610334565b60005473ffffffffffffffffffffffffffffffffffffffff1661012a565b61012a7f000000000000000000000000000000000000000000000000000000000000000081565b6101576101bf366004610dfb565b61038a565b6101576101d2366004610e57565b610487565b61012a7f000000000000000000000000000000000000000000000000000000000000000081565b61015761020c366004610eb7565b61059d565b61022461021f366004610edb565b6105b1565b6040516100fa929190610f2f565b60015473ffffffffffffffffffffffffffffffffffffffff1633146102b8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064015b60405180910390fd5b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b61033c610849565b6040805180820190915263ffffffff9092168083526020909201819052600280547fffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000016909217909155600355565b3373ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016146103f9576040517f44b0e3c300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60208114610433576040517f8129bbcd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600061044182840184610eb7565b73ffffffffffffffffffffffffffffffffffffffff811660009081526005602052604081208054929350869290919061047b908490610fd1565b90915550505050505050565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610534576040517f295a81c100000000000000000000000000000000000000000000000000000000815233600482015273ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001660248201526044016102af565b60008061054384860186610fe4565b9150915080610551846108cc565b61055b9190610fd1565b73ffffffffffffffffffffffffffffffffffffffff831660009081526005602052604081208054909190610590908490611002565b9091555050505050505050565b6105a5610849565b6105ae816108f8565b50565b606060003373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610662576040517f295a81c100000000000000000000000000000000000000000000000000000000815233600482015273ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001660248201526044016102af565b60008481526004602052604090205460ff16156106ae576040517f7413dcf8000000000000000000000000000000000000000000000000000000008152600481018590526024016102af565b60006106b9866109ed565b90506000816106c7866108cc565b6106d19190610fd1565b905080600560006106e560208b018b610eb7565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205410156107b057806005600061073860208b018b610eb7565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020546040517f03eb8b540000000000000000000000000000000000000000000000000000000081526004016102af929190918252602082015260400190565b600086815260046020908152604090912080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790556107f690880188610eb7565b6040805173ffffffffffffffffffffffffffffffffffffffff9092166020830152810183905260600160405160208183030381529060405261083b6000806000610c29565b935093505050935093915050565b60005473ffffffffffffffffffffffffffffffffffffffff1633146108ca576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e65720000000000000000000060448201526064016102af565b565b60006108d6610c61565b6108e883670de0b6b3a7640000611015565b6108f2919061102c565b92915050565b3373ffffffffffffffffffffffffffffffffffffffff821603610977576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c6600000000000000000060448201526064016102af565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b60006109fd610120830183611067565b9050601403610a0e57506000919050565b6000610a1e610120840184611067565b6014818110610a2f57610a2f6110cc565b919091013560f81c9150819050610c23576000610a50610120850185611067565b610a5e9160159082906110fb565b810190610a6b9190611125565b90508060200151600014158015610b385750602081015181516040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff91821660048201527f0000000000000000000000000000000000000000000000000000000000000000909116906370a0823190602401602060405180830381865afa158015610b12573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b3691906111ae565b105b15610c2157805160408083015190517fa9059cbb00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169263a9059cbb92610bd59260040173ffffffffffffffffffffffffffffffffffffffff929092168252602082015260400190565b6020604051808303816000875af1158015610bf4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c1891906111c7565b50806040015192505b505b50919050565b600060d08265ffffffffffff16901b60a08465ffffffffffff16901b85610c51576000610c54565b60015b60ff161717949350505050565b600254604080517ffeaf968c000000000000000000000000000000000000000000000000000000008152905160009263ffffffff1691821515918491829173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169163feaf968c9160048083019260a09291908290030181865afa158015610d01573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d259190611208565b509450909250849150508015610d495750610d408242611002565b8463ffffffff16105b15610d5357506003545b949350505050565b60008060408385031215610d6e57600080fd5b823563ffffffff81168114610d8257600080fd5b946020939093013593505050565b73ffffffffffffffffffffffffffffffffffffffff811681146105ae57600080fd5b60008083601f840112610dc457600080fd5b50813567ffffffffffffffff811115610ddc57600080fd5b602083019150836020828501011115610df457600080fd5b9250929050565b60008060008060608587031215610e1157600080fd5b8435610e1c81610d90565b935060208501359250604085013567ffffffffffffffff811115610e3f57600080fd5b610e4b87828801610db2565b95989497509550505050565b60008060008060608587031215610e6d57600080fd5b843560038110610e7c57600080fd5b9350602085013567ffffffffffffffff811115610e9857600080fd5b610ea487828801610db2565b9598909750949560400135949350505050565b600060208284031215610ec957600080fd5b8135610ed481610d90565b9392505050565b600080600060608486031215610ef057600080fd5b833567ffffffffffffffff811115610f0757600080fd5b84016101608187031215610f1a57600080fd5b95602085013595506040909401359392505050565b604081526000835180604084015260005b81811015610f5d5760208187018101516060868401015201610f40565b5060006060828501015260607fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8301168401019150508260208301529392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b808201808211156108f2576108f2610fa2565b60008060408385031215610ff757600080fd5b8235610d8281610d90565b818103818111156108f2576108f2610fa2565b80820281158282048414176108f2576108f2610fa2565b600082611062577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261109c57600080fd5b83018035915067ffffffffffffffff8211156110b757600080fd5b602001915036819003821315610df457600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6000808585111561110b57600080fd5b8386111561111857600080fd5b5050820193919092039150565b60006060828403121561113757600080fd5b6040516060810181811067ffffffffffffffff82111715611181577f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604052823561118f81610d90565b8152602083810135908201526040928301359281019290925250919050565b6000602082840312156111c057600080fd5b5051919050565b6000602082840312156111d957600080fd5b81518015158114610ed457600080fd5b805169ffffffffffffffffffff8116811461120357600080fd5b919050565b600080600080600060a0868803121561122057600080fd5b611229866111e9565b945060208601519350604086015192506060860151915061124c608087016111e9565b9050929550929590935056fea164736f6c6343000813000a", +} + +var PaymasterABI = PaymasterMetaData.ABI + +var PaymasterBin = PaymasterMetaData.Bin + +func DeployPaymaster(auth *bind.TransactOpts, backend bind.ContractBackend, linkToken common.Address, linkEthFeed common.Address, entryPoint common.Address) (common.Address, *types.Transaction, *Paymaster, error) { + parsed, err := PaymasterMetaData.GetAbi() + if err != nil { + return common.Address{}, nil, nil, err + } + if parsed == nil { + return common.Address{}, nil, nil, errors.New("GetABI returned nil") + } + + address, tx, contract, err := bind.DeployContract(auth, *parsed, common.FromHex(PaymasterBin), backend, linkToken, linkEthFeed, entryPoint) + if err != nil { + return common.Address{}, nil, nil, err + } + return address, tx, &Paymaster{address: address, abi: *parsed, PaymasterCaller: PaymasterCaller{contract: contract}, PaymasterTransactor: PaymasterTransactor{contract: contract}, PaymasterFilterer: PaymasterFilterer{contract: contract}}, nil +} + +type Paymaster struct { + address common.Address + abi abi.ABI + PaymasterCaller + PaymasterTransactor + PaymasterFilterer +} + +type PaymasterCaller struct { + contract *bind.BoundContract +} + +type PaymasterTransactor struct { + contract *bind.BoundContract +} + +type PaymasterFilterer struct { + contract *bind.BoundContract +} + +type PaymasterSession struct { + Contract *Paymaster + CallOpts bind.CallOpts + TransactOpts bind.TransactOpts +} + +type PaymasterCallerSession struct { + Contract *PaymasterCaller + CallOpts bind.CallOpts +} + +type PaymasterTransactorSession struct { + Contract *PaymasterTransactor + TransactOpts bind.TransactOpts +} + +type PaymasterRaw struct { + Contract *Paymaster +} + +type PaymasterCallerRaw struct { + Contract *PaymasterCaller +} + +type PaymasterTransactorRaw struct { + Contract *PaymasterTransactor +} + +func NewPaymaster(address common.Address, backend bind.ContractBackend) (*Paymaster, error) { + abi, err := abi.JSON(strings.NewReader(PaymasterABI)) + if err != nil { + return nil, err + } + contract, err := bindPaymaster(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &Paymaster{address: address, abi: abi, PaymasterCaller: PaymasterCaller{contract: contract}, PaymasterTransactor: PaymasterTransactor{contract: contract}, PaymasterFilterer: PaymasterFilterer{contract: contract}}, nil +} + +func NewPaymasterCaller(address common.Address, caller bind.ContractCaller) (*PaymasterCaller, error) { + contract, err := bindPaymaster(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &PaymasterCaller{contract: contract}, nil +} + +func NewPaymasterTransactor(address common.Address, transactor bind.ContractTransactor) (*PaymasterTransactor, error) { + contract, err := bindPaymaster(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &PaymasterTransactor{contract: contract}, nil +} + +func NewPaymasterFilterer(address common.Address, filterer bind.ContractFilterer) (*PaymasterFilterer, error) { + contract, err := bindPaymaster(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &PaymasterFilterer{contract: contract}, nil +} + +func bindPaymaster(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := PaymasterMetaData.GetAbi() + if err != nil { + return nil, err + } + return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil +} + +func (_Paymaster *PaymasterRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _Paymaster.Contract.PaymasterCaller.contract.Call(opts, result, method, params...) +} + +func (_Paymaster *PaymasterRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _Paymaster.Contract.PaymasterTransactor.contract.Transfer(opts) +} + +func (_Paymaster *PaymasterRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _Paymaster.Contract.PaymasterTransactor.contract.Transact(opts, method, params...) +} + +func (_Paymaster *PaymasterCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _Paymaster.Contract.contract.Call(opts, result, method, params...) +} + +func (_Paymaster *PaymasterTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _Paymaster.Contract.contract.Transfer(opts) +} + +func (_Paymaster *PaymasterTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _Paymaster.Contract.contract.Transact(opts, method, params...) +} + +func (_Paymaster *PaymasterCaller) IEntryPoint(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _Paymaster.contract.Call(opts, &out, "i_entryPoint") + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +func (_Paymaster *PaymasterSession) IEntryPoint() (common.Address, error) { + return _Paymaster.Contract.IEntryPoint(&_Paymaster.CallOpts) +} + +func (_Paymaster *PaymasterCallerSession) IEntryPoint() (common.Address, error) { + return _Paymaster.Contract.IEntryPoint(&_Paymaster.CallOpts) +} + +func (_Paymaster *PaymasterCaller) ILinkEthFeed(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _Paymaster.contract.Call(opts, &out, "i_linkEthFeed") + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +func (_Paymaster *PaymasterSession) ILinkEthFeed() (common.Address, error) { + return _Paymaster.Contract.ILinkEthFeed(&_Paymaster.CallOpts) +} + +func (_Paymaster *PaymasterCallerSession) ILinkEthFeed() (common.Address, error) { + return _Paymaster.Contract.ILinkEthFeed(&_Paymaster.CallOpts) +} + +func (_Paymaster *PaymasterCaller) ILinkToken(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _Paymaster.contract.Call(opts, &out, "i_linkToken") + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +func (_Paymaster *PaymasterSession) ILinkToken() (common.Address, error) { + return _Paymaster.Contract.ILinkToken(&_Paymaster.CallOpts) +} + +func (_Paymaster *PaymasterCallerSession) ILinkToken() (common.Address, error) { + return _Paymaster.Contract.ILinkToken(&_Paymaster.CallOpts) +} + +func (_Paymaster *PaymasterCaller) Owner(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _Paymaster.contract.Call(opts, &out, "owner") + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +func (_Paymaster *PaymasterSession) Owner() (common.Address, error) { + return _Paymaster.Contract.Owner(&_Paymaster.CallOpts) +} + +func (_Paymaster *PaymasterCallerSession) Owner() (common.Address, error) { + return _Paymaster.Contract.Owner(&_Paymaster.CallOpts) +} + +func (_Paymaster *PaymasterCaller) SConfig(opts *bind.CallOpts) (SConfig, + + error) { + var out []interface{} + err := _Paymaster.contract.Call(opts, &out, "s_config") + + outstruct := new(SConfig) + if err != nil { + return *outstruct, err + } + + outstruct.StalenessSeconds = *abi.ConvertType(out[0], new(uint32)).(*uint32) + outstruct.FallbackWeiPerUnitLink = *abi.ConvertType(out[1], new(*big.Int)).(**big.Int) + + return *outstruct, err + +} + +func (_Paymaster *PaymasterSession) SConfig() (SConfig, + + error) { + return _Paymaster.Contract.SConfig(&_Paymaster.CallOpts) +} + +func (_Paymaster *PaymasterCallerSession) SConfig() (SConfig, + + error) { + return _Paymaster.Contract.SConfig(&_Paymaster.CallOpts) +} + +func (_Paymaster *PaymasterTransactor) AcceptOwnership(opts *bind.TransactOpts) (*types.Transaction, error) { + return _Paymaster.contract.Transact(opts, "acceptOwnership") +} + +func (_Paymaster *PaymasterSession) AcceptOwnership() (*types.Transaction, error) { + return _Paymaster.Contract.AcceptOwnership(&_Paymaster.TransactOpts) +} + +func (_Paymaster *PaymasterTransactorSession) AcceptOwnership() (*types.Transaction, error) { + return _Paymaster.Contract.AcceptOwnership(&_Paymaster.TransactOpts) +} + +func (_Paymaster *PaymasterTransactor) OnTokenTransfer(opts *bind.TransactOpts, arg0 common.Address, _amount *big.Int, _data []byte) (*types.Transaction, error) { + return _Paymaster.contract.Transact(opts, "onTokenTransfer", arg0, _amount, _data) +} + +func (_Paymaster *PaymasterSession) OnTokenTransfer(arg0 common.Address, _amount *big.Int, _data []byte) (*types.Transaction, error) { + return _Paymaster.Contract.OnTokenTransfer(&_Paymaster.TransactOpts, arg0, _amount, _data) +} + +func (_Paymaster *PaymasterTransactorSession) OnTokenTransfer(arg0 common.Address, _amount *big.Int, _data []byte) (*types.Transaction, error) { + return _Paymaster.Contract.OnTokenTransfer(&_Paymaster.TransactOpts, arg0, _amount, _data) +} + +func (_Paymaster *PaymasterTransactor) PostOp(opts *bind.TransactOpts, arg0 uint8, context []byte, actualGasCost *big.Int) (*types.Transaction, error) { + return _Paymaster.contract.Transact(opts, "postOp", arg0, context, actualGasCost) +} + +func (_Paymaster *PaymasterSession) PostOp(arg0 uint8, context []byte, actualGasCost *big.Int) (*types.Transaction, error) { + return _Paymaster.Contract.PostOp(&_Paymaster.TransactOpts, arg0, context, actualGasCost) +} + +func (_Paymaster *PaymasterTransactorSession) PostOp(arg0 uint8, context []byte, actualGasCost *big.Int) (*types.Transaction, error) { + return _Paymaster.Contract.PostOp(&_Paymaster.TransactOpts, arg0, context, actualGasCost) +} + +func (_Paymaster *PaymasterTransactor) SetConfig(opts *bind.TransactOpts, stalenessSeconds uint32, fallbackWeiPerUnitLink *big.Int) (*types.Transaction, error) { + return _Paymaster.contract.Transact(opts, "setConfig", stalenessSeconds, fallbackWeiPerUnitLink) +} + +func (_Paymaster *PaymasterSession) SetConfig(stalenessSeconds uint32, fallbackWeiPerUnitLink *big.Int) (*types.Transaction, error) { + return _Paymaster.Contract.SetConfig(&_Paymaster.TransactOpts, stalenessSeconds, fallbackWeiPerUnitLink) +} + +func (_Paymaster *PaymasterTransactorSession) SetConfig(stalenessSeconds uint32, fallbackWeiPerUnitLink *big.Int) (*types.Transaction, error) { + return _Paymaster.Contract.SetConfig(&_Paymaster.TransactOpts, stalenessSeconds, fallbackWeiPerUnitLink) +} + +func (_Paymaster *PaymasterTransactor) TransferOwnership(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) { + return _Paymaster.contract.Transact(opts, "transferOwnership", to) +} + +func (_Paymaster *PaymasterSession) TransferOwnership(to common.Address) (*types.Transaction, error) { + return _Paymaster.Contract.TransferOwnership(&_Paymaster.TransactOpts, to) +} + +func (_Paymaster *PaymasterTransactorSession) TransferOwnership(to common.Address) (*types.Transaction, error) { + return _Paymaster.Contract.TransferOwnership(&_Paymaster.TransactOpts, to) +} + +func (_Paymaster *PaymasterTransactor) ValidatePaymasterUserOp(opts *bind.TransactOpts, userOp UserOperation, userOpHash [32]byte, maxCost *big.Int) (*types.Transaction, error) { + return _Paymaster.contract.Transact(opts, "validatePaymasterUserOp", userOp, userOpHash, maxCost) +} + +func (_Paymaster *PaymasterSession) ValidatePaymasterUserOp(userOp UserOperation, userOpHash [32]byte, maxCost *big.Int) (*types.Transaction, error) { + return _Paymaster.Contract.ValidatePaymasterUserOp(&_Paymaster.TransactOpts, userOp, userOpHash, maxCost) +} + +func (_Paymaster *PaymasterTransactorSession) ValidatePaymasterUserOp(userOp UserOperation, userOpHash [32]byte, maxCost *big.Int) (*types.Transaction, error) { + return _Paymaster.Contract.ValidatePaymasterUserOp(&_Paymaster.TransactOpts, userOp, userOpHash, maxCost) +} + +type PaymasterOwnershipTransferRequestedIterator struct { + Event *PaymasterOwnershipTransferRequested + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *PaymasterOwnershipTransferRequestedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(PaymasterOwnershipTransferRequested) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(PaymasterOwnershipTransferRequested) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *PaymasterOwnershipTransferRequestedIterator) Error() error { + return it.fail +} + +func (it *PaymasterOwnershipTransferRequestedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type PaymasterOwnershipTransferRequested struct { + From common.Address + To common.Address + Raw types.Log +} + +func (_Paymaster *PaymasterFilterer) FilterOwnershipTransferRequested(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*PaymasterOwnershipTransferRequestedIterator, error) { + + var fromRule []interface{} + for _, fromItem := range from { + fromRule = append(fromRule, fromItem) + } + var toRule []interface{} + for _, toItem := range to { + toRule = append(toRule, toItem) + } + + logs, sub, err := _Paymaster.contract.FilterLogs(opts, "OwnershipTransferRequested", fromRule, toRule) + if err != nil { + return nil, err + } + return &PaymasterOwnershipTransferRequestedIterator{contract: _Paymaster.contract, event: "OwnershipTransferRequested", logs: logs, sub: sub}, nil +} + +func (_Paymaster *PaymasterFilterer) WatchOwnershipTransferRequested(opts *bind.WatchOpts, sink chan<- *PaymasterOwnershipTransferRequested, from []common.Address, to []common.Address) (event.Subscription, error) { + + var fromRule []interface{} + for _, fromItem := range from { + fromRule = append(fromRule, fromItem) + } + var toRule []interface{} + for _, toItem := range to { + toRule = append(toRule, toItem) + } + + logs, sub, err := _Paymaster.contract.WatchLogs(opts, "OwnershipTransferRequested", fromRule, toRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(PaymasterOwnershipTransferRequested) + if err := _Paymaster.contract.UnpackLog(event, "OwnershipTransferRequested", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_Paymaster *PaymasterFilterer) ParseOwnershipTransferRequested(log types.Log) (*PaymasterOwnershipTransferRequested, error) { + event := new(PaymasterOwnershipTransferRequested) + if err := _Paymaster.contract.UnpackLog(event, "OwnershipTransferRequested", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type PaymasterOwnershipTransferredIterator struct { + Event *PaymasterOwnershipTransferred + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *PaymasterOwnershipTransferredIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(PaymasterOwnershipTransferred) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(PaymasterOwnershipTransferred) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *PaymasterOwnershipTransferredIterator) Error() error { + return it.fail +} + +func (it *PaymasterOwnershipTransferredIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type PaymasterOwnershipTransferred struct { + From common.Address + To common.Address + Raw types.Log +} + +func (_Paymaster *PaymasterFilterer) FilterOwnershipTransferred(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*PaymasterOwnershipTransferredIterator, error) { + + var fromRule []interface{} + for _, fromItem := range from { + fromRule = append(fromRule, fromItem) + } + var toRule []interface{} + for _, toItem := range to { + toRule = append(toRule, toItem) + } + + logs, sub, err := _Paymaster.contract.FilterLogs(opts, "OwnershipTransferred", fromRule, toRule) + if err != nil { + return nil, err + } + return &PaymasterOwnershipTransferredIterator{contract: _Paymaster.contract, event: "OwnershipTransferred", logs: logs, sub: sub}, nil +} + +func (_Paymaster *PaymasterFilterer) WatchOwnershipTransferred(opts *bind.WatchOpts, sink chan<- *PaymasterOwnershipTransferred, from []common.Address, to []common.Address) (event.Subscription, error) { + + var fromRule []interface{} + for _, fromItem := range from { + fromRule = append(fromRule, fromItem) + } + var toRule []interface{} + for _, toItem := range to { + toRule = append(toRule, toItem) + } + + logs, sub, err := _Paymaster.contract.WatchLogs(opts, "OwnershipTransferred", fromRule, toRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(PaymasterOwnershipTransferred) + if err := _Paymaster.contract.UnpackLog(event, "OwnershipTransferred", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_Paymaster *PaymasterFilterer) ParseOwnershipTransferred(log types.Log) (*PaymasterOwnershipTransferred, error) { + event := new(PaymasterOwnershipTransferred) + if err := _Paymaster.contract.UnpackLog(event, "OwnershipTransferred", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type SConfig struct { + StalenessSeconds uint32 + FallbackWeiPerUnitLink *big.Int +} + +func (_Paymaster *Paymaster) ParseLog(log types.Log) (generated.AbigenLog, error) { + switch log.Topics[0] { + case _Paymaster.abi.Events["OwnershipTransferRequested"].ID: + return _Paymaster.ParseOwnershipTransferRequested(log) + case _Paymaster.abi.Events["OwnershipTransferred"].ID: + return _Paymaster.ParseOwnershipTransferred(log) + + default: + return nil, fmt.Errorf("abigen wrapper received unknown log topic: %v", log.Topics[0]) + } +} + +func (PaymasterOwnershipTransferRequested) Topic() common.Hash { + return common.HexToHash("0xed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae1278") +} + +func (PaymasterOwnershipTransferred) Topic() common.Hash { + return common.HexToHash("0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0") +} + +func (_Paymaster *Paymaster) Address() common.Address { + return _Paymaster.address +} + +type PaymasterInterface interface { + IEntryPoint(opts *bind.CallOpts) (common.Address, error) + + ILinkEthFeed(opts *bind.CallOpts) (common.Address, error) + + ILinkToken(opts *bind.CallOpts) (common.Address, error) + + Owner(opts *bind.CallOpts) (common.Address, error) + + SConfig(opts *bind.CallOpts) (SConfig, + + error) + + AcceptOwnership(opts *bind.TransactOpts) (*types.Transaction, error) + + OnTokenTransfer(opts *bind.TransactOpts, arg0 common.Address, _amount *big.Int, _data []byte) (*types.Transaction, error) + + PostOp(opts *bind.TransactOpts, arg0 uint8, context []byte, actualGasCost *big.Int) (*types.Transaction, error) + + SetConfig(opts *bind.TransactOpts, stalenessSeconds uint32, fallbackWeiPerUnitLink *big.Int) (*types.Transaction, error) + + TransferOwnership(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) + + ValidatePaymasterUserOp(opts *bind.TransactOpts, userOp UserOperation, userOpHash [32]byte, maxCost *big.Int) (*types.Transaction, error) + + FilterOwnershipTransferRequested(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*PaymasterOwnershipTransferRequestedIterator, error) + + WatchOwnershipTransferRequested(opts *bind.WatchOpts, sink chan<- *PaymasterOwnershipTransferRequested, from []common.Address, to []common.Address) (event.Subscription, error) + + ParseOwnershipTransferRequested(log types.Log) (*PaymasterOwnershipTransferRequested, error) + + FilterOwnershipTransferred(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*PaymasterOwnershipTransferredIterator, error) + + WatchOwnershipTransferred(opts *bind.WatchOpts, sink chan<- *PaymasterOwnershipTransferred, from []common.Address, to []common.Address) (event.Subscription, error) + + ParseOwnershipTransferred(log types.Log) (*PaymasterOwnershipTransferred, error) + + ParseLog(log types.Log) (generated.AbigenLog, error) + + Address() common.Address +} diff --git a/core/gethwrappers/transmission/generated/sca_wrapper/sca_wrapper.go b/core/gethwrappers/transmission/generated/sca_wrapper/sca_wrapper.go new file mode 100644 index 00000000000..989e4058685 --- /dev/null +++ b/core/gethwrappers/transmission/generated/sca_wrapper/sca_wrapper.go @@ -0,0 +1,292 @@ +// Code generated - DO NOT EDIT. +// This file is a generated binding and any manual changes will be lost. + +package sca_wrapper + +import ( + "errors" + "math/big" + "strings" + + ethereum "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/event" +) + +var ( + _ = errors.New + _ = big.NewInt + _ = strings.NewReader + _ = ethereum.NotFound + _ = bind.Bind + _ = common.Big1 + _ = types.BloomLookup + _ = event.NewSubscription + _ = abi.ConvertType +) + +type UserOperation struct { + Sender common.Address + Nonce *big.Int + InitCode []byte + CallData []byte + CallGasLimit *big.Int + VerificationGasLimit *big.Int + PreVerificationGas *big.Int + MaxFeePerGas *big.Int + MaxPriorityFeePerGas *big.Int + PaymasterAndData []byte + Signature []byte +} + +var SCAMetaData = &bind.MetaData{ + ABI: "[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"entryPoint\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"BadFormatOrOOG\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"currentNonce\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"nonceGiven\",\"type\":\"uint256\"}],\"name\":\"IncorrectNonce\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"operationHash\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"}],\"name\":\"InvalidSignature\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"NotAuthorized\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"currentTimestamp\",\"type\":\"uint256\"}],\"name\":\"TransactionExpired\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"internalType\":\"uint48\",\"name\":\"deadline\",\"type\":\"uint48\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"executeTransactionFromEntryPoint\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"i_entryPoint\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"i_owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"s_nonce\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"initCode\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"callGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"verificationGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"preVerificationGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxFeePerGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxPriorityFeePerGas\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"paymasterAndData\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"signature\",\"type\":\"bytes\"}],\"internalType\":\"structUserOperation\",\"name\":\"userOp\",\"type\":\"tuple\"},{\"internalType\":\"bytes32\",\"name\":\"userOpHash\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"validateUserOp\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"validationData\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", + Bin: "0x60c060405234801561001057600080fd5b50604051610acb380380610acb83398101604081905261002f91610062565b6001600160a01b039182166080521660a052610095565b80516001600160a01b038116811461005d57600080fd5b919050565b6000806040838503121561007557600080fd5b61007e83610046565b915061008c60208401610046565b90509250929050565b60805160a051610a046100c760003960008181607101526102b801526000818161010101526101e30152610a046000f3fe608060405234801561001057600080fd5b50600436106100675760003560e01c80637eccf63e116100505780637eccf63e146100de57806389553be4146100e7578063dba6335f146100fc57600080fd5b8063140fcfb11461006c5780633a871cdd146100bd575b600080fd5b6100937f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b6100d06100cb366004610646565b610123565b6040519081526020016100b4565b6100d060005481565b6100fa6100f53660046106da565b6102a0565b005b6100937f000000000000000000000000000000000000000000000000000000000000000081565b60008054846020013514610179576000546040517f7ba633940000000000000000000000000000000000000000000000000000000081526004810191909152602085013560248201526044015b60405180910390fd5b60006101858430610439565b90506000610197610140870187610777565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509293505073ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016915061021190508284610550565b73ffffffffffffffffffffffffffffffffffffffff161461024257610239600160008061060e565b92505050610299565b60008054908061025183610812565b90915550600090506102666060880188610777565b61027491600490829061084a565b81019061028191906108a3565b5092505050610293600082600061060e565b93505050505b9392505050565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610311576040517f4a0bfec1000000000000000000000000000000000000000000000000000000008152336004820152602401610170565b65ffffffffffff83161580159061032f57508265ffffffffffff1642115b15610376576040517f300249d700000000000000000000000000000000000000000000000000000000815265ffffffffffff84166004820152426024820152604401610170565b6000808673ffffffffffffffffffffffffffffffffffffffff168685856040516103a192919061099f565b60006040518083038185875af1925050503d80600081146103de576040519150601f19603f3d011682016040523d82523d6000602084013e6103e3565b606091505b509150915081610430578051600003610428576040517f20e9b5d200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805181602001fd5b50505050505050565b604080517f4750045d47fce615521b32cee713ff8db50147e98aec5ca94926b52651ca3fa0602080830191909152818301859052825180830384018152606080840185528151918301919091207f190000000000000000000000000000000000000000000000000000000000000060808501527f010000000000000000000000000000000000000000000000000000000000000060818501527f1c7d3b72b37a35523e273aaadd7b4cd66f618bb81429ab053412d51f50ccea6160828501524660a28501529085901b7fffffffffffffffffffffffffffffffffffffffff0000000000000000000000001660c284015260d6808401919091528351808403909101815260f690920190925280519101205b92915050565b602082015160408084015184516000939284918791908110610574576105746109af565b016020015160f81c905060018561058c83601b6109de565b6040805160008152602081018083529390935260ff90911690820152606081018590526080810184905260a0016020604051602081039080840390855afa1580156105db573d6000803e3d6000fd5b50506040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe00151979650505050505050565b600060d08265ffffffffffff16901b60a08465ffffffffffff16901b85610636576000610639565b60015b60ff161717949350505050565b60008060006060848603121561065b57600080fd5b833567ffffffffffffffff81111561067257600080fd5b8401610160818703121561068557600080fd5b95602085013595506040909401359392505050565b73ffffffffffffffffffffffffffffffffffffffff811681146106bc57600080fd5b50565b803565ffffffffffff811681146106d557600080fd5b919050565b6000806000806000608086880312156106f257600080fd5b85356106fd8161069a565b945060208601359350610712604087016106bf565b9250606086013567ffffffffffffffff8082111561072f57600080fd5b818801915088601f83011261074357600080fd5b81358181111561075257600080fd5b89602082850101111561076457600080fd5b9699959850939650602001949392505050565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18436030181126107ac57600080fd5b83018035915067ffffffffffffffff8211156107c757600080fd5b6020019150368190038213156107dc57600080fd5b9250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203610843576108436107e3565b5060010190565b6000808585111561085a57600080fd5b8386111561086757600080fd5b5050820193919092039150565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600080600080608085870312156108b957600080fd5b84356108c48161069a565b9350602085013592506108d9604086016106bf565b9150606085013567ffffffffffffffff808211156108f657600080fd5b818701915087601f83011261090a57600080fd5b81358181111561091c5761091c610874565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190838211818310171561096257610962610874565b816040528281528a602084870101111561097b57600080fd5b82602086016020830137600060208483010152809550505050505092959194509250565b8183823760009101908152919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60ff818116838216019081111561054a5761054a6107e356fea164736f6c6343000813000a", +} + +var SCAABI = SCAMetaData.ABI + +var SCABin = SCAMetaData.Bin + +func DeploySCA(auth *bind.TransactOpts, backend bind.ContractBackend, owner common.Address, entryPoint common.Address) (common.Address, *types.Transaction, *SCA, error) { + parsed, err := SCAMetaData.GetAbi() + if err != nil { + return common.Address{}, nil, nil, err + } + if parsed == nil { + return common.Address{}, nil, nil, errors.New("GetABI returned nil") + } + + address, tx, contract, err := bind.DeployContract(auth, *parsed, common.FromHex(SCABin), backend, owner, entryPoint) + if err != nil { + return common.Address{}, nil, nil, err + } + return address, tx, &SCA{address: address, abi: *parsed, SCACaller: SCACaller{contract: contract}, SCATransactor: SCATransactor{contract: contract}, SCAFilterer: SCAFilterer{contract: contract}}, nil +} + +type SCA struct { + address common.Address + abi abi.ABI + SCACaller + SCATransactor + SCAFilterer +} + +type SCACaller struct { + contract *bind.BoundContract +} + +type SCATransactor struct { + contract *bind.BoundContract +} + +type SCAFilterer struct { + contract *bind.BoundContract +} + +type SCASession struct { + Contract *SCA + CallOpts bind.CallOpts + TransactOpts bind.TransactOpts +} + +type SCACallerSession struct { + Contract *SCACaller + CallOpts bind.CallOpts +} + +type SCATransactorSession struct { + Contract *SCATransactor + TransactOpts bind.TransactOpts +} + +type SCARaw struct { + Contract *SCA +} + +type SCACallerRaw struct { + Contract *SCACaller +} + +type SCATransactorRaw struct { + Contract *SCATransactor +} + +func NewSCA(address common.Address, backend bind.ContractBackend) (*SCA, error) { + abi, err := abi.JSON(strings.NewReader(SCAABI)) + if err != nil { + return nil, err + } + contract, err := bindSCA(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &SCA{address: address, abi: abi, SCACaller: SCACaller{contract: contract}, SCATransactor: SCATransactor{contract: contract}, SCAFilterer: SCAFilterer{contract: contract}}, nil +} + +func NewSCACaller(address common.Address, caller bind.ContractCaller) (*SCACaller, error) { + contract, err := bindSCA(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &SCACaller{contract: contract}, nil +} + +func NewSCATransactor(address common.Address, transactor bind.ContractTransactor) (*SCATransactor, error) { + contract, err := bindSCA(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &SCATransactor{contract: contract}, nil +} + +func NewSCAFilterer(address common.Address, filterer bind.ContractFilterer) (*SCAFilterer, error) { + contract, err := bindSCA(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &SCAFilterer{contract: contract}, nil +} + +func bindSCA(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := SCAMetaData.GetAbi() + if err != nil { + return nil, err + } + return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil +} + +func (_SCA *SCARaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _SCA.Contract.SCACaller.contract.Call(opts, result, method, params...) +} + +func (_SCA *SCARaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _SCA.Contract.SCATransactor.contract.Transfer(opts) +} + +func (_SCA *SCARaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _SCA.Contract.SCATransactor.contract.Transact(opts, method, params...) +} + +func (_SCA *SCACallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _SCA.Contract.contract.Call(opts, result, method, params...) +} + +func (_SCA *SCATransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _SCA.Contract.contract.Transfer(opts) +} + +func (_SCA *SCATransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _SCA.Contract.contract.Transact(opts, method, params...) +} + +func (_SCA *SCACaller) IEntryPoint(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _SCA.contract.Call(opts, &out, "i_entryPoint") + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +func (_SCA *SCASession) IEntryPoint() (common.Address, error) { + return _SCA.Contract.IEntryPoint(&_SCA.CallOpts) +} + +func (_SCA *SCACallerSession) IEntryPoint() (common.Address, error) { + return _SCA.Contract.IEntryPoint(&_SCA.CallOpts) +} + +func (_SCA *SCACaller) IOwner(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _SCA.contract.Call(opts, &out, "i_owner") + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +func (_SCA *SCASession) IOwner() (common.Address, error) { + return _SCA.Contract.IOwner(&_SCA.CallOpts) +} + +func (_SCA *SCACallerSession) IOwner() (common.Address, error) { + return _SCA.Contract.IOwner(&_SCA.CallOpts) +} + +func (_SCA *SCACaller) SNonce(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _SCA.contract.Call(opts, &out, "s_nonce") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +func (_SCA *SCASession) SNonce() (*big.Int, error) { + return _SCA.Contract.SNonce(&_SCA.CallOpts) +} + +func (_SCA *SCACallerSession) SNonce() (*big.Int, error) { + return _SCA.Contract.SNonce(&_SCA.CallOpts) +} + +func (_SCA *SCATransactor) ExecuteTransactionFromEntryPoint(opts *bind.TransactOpts, to common.Address, value *big.Int, deadline *big.Int, data []byte) (*types.Transaction, error) { + return _SCA.contract.Transact(opts, "executeTransactionFromEntryPoint", to, value, deadline, data) +} + +func (_SCA *SCASession) ExecuteTransactionFromEntryPoint(to common.Address, value *big.Int, deadline *big.Int, data []byte) (*types.Transaction, error) { + return _SCA.Contract.ExecuteTransactionFromEntryPoint(&_SCA.TransactOpts, to, value, deadline, data) +} + +func (_SCA *SCATransactorSession) ExecuteTransactionFromEntryPoint(to common.Address, value *big.Int, deadline *big.Int, data []byte) (*types.Transaction, error) { + return _SCA.Contract.ExecuteTransactionFromEntryPoint(&_SCA.TransactOpts, to, value, deadline, data) +} + +func (_SCA *SCATransactor) ValidateUserOp(opts *bind.TransactOpts, userOp UserOperation, userOpHash [32]byte, arg2 *big.Int) (*types.Transaction, error) { + return _SCA.contract.Transact(opts, "validateUserOp", userOp, userOpHash, arg2) +} + +func (_SCA *SCASession) ValidateUserOp(userOp UserOperation, userOpHash [32]byte, arg2 *big.Int) (*types.Transaction, error) { + return _SCA.Contract.ValidateUserOp(&_SCA.TransactOpts, userOp, userOpHash, arg2) +} + +func (_SCA *SCATransactorSession) ValidateUserOp(userOp UserOperation, userOpHash [32]byte, arg2 *big.Int) (*types.Transaction, error) { + return _SCA.Contract.ValidateUserOp(&_SCA.TransactOpts, userOp, userOpHash, arg2) +} + +func (_SCA *SCA) Address() common.Address { + return _SCA.address +} + +type SCAInterface interface { + IEntryPoint(opts *bind.CallOpts) (common.Address, error) + + IOwner(opts *bind.CallOpts) (common.Address, error) + + SNonce(opts *bind.CallOpts) (*big.Int, error) + + ExecuteTransactionFromEntryPoint(opts *bind.TransactOpts, to common.Address, value *big.Int, deadline *big.Int, data []byte) (*types.Transaction, error) + + ValidateUserOp(opts *bind.TransactOpts, userOp UserOperation, userOpHash [32]byte, arg2 *big.Int) (*types.Transaction, error) + + Address() common.Address +} diff --git a/core/gethwrappers/transmission/generated/smart_contract_account_factory/smart_contract_account_factory.go b/core/gethwrappers/transmission/generated/smart_contract_account_factory/smart_contract_account_factory.go new file mode 100644 index 00000000000..aa9205641c5 --- /dev/null +++ b/core/gethwrappers/transmission/generated/smart_contract_account_factory/smart_contract_account_factory.go @@ -0,0 +1,333 @@ +// Code generated - DO NOT EDIT. +// This file is a generated binding and any manual changes will be lost. + +package smart_contract_account_factory + +import ( + "errors" + "fmt" + "math/big" + "strings" + + ethereum "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/event" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated" +) + +var ( + _ = errors.New + _ = big.NewInt + _ = strings.NewReader + _ = ethereum.NotFound + _ = bind.Bind + _ = common.Big1 + _ = types.BloomLookup + _ = event.NewSubscription + _ = abi.ConvertType +) + +var SmartContractAccountFactoryMetaData = &bind.MetaData{ + ABI: "[{\"inputs\":[],\"name\":\"DeploymentFailed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"scaAddress\",\"type\":\"address\"}],\"name\":\"ContractCreated\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"abiEncodedOwnerAddress\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"initCode\",\"type\":\"bytes\"}],\"name\":\"deploySmartContractAccount\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"scaAddress\",\"type\":\"address\"}],\"stateMutability\":\"payable\",\"type\":\"function\"}]", + Bin: "0x608060405234801561001057600080fd5b5061021e806100206000396000f3fe60806040526004361061001e5760003560e01c80630af4926f14610023575b600080fd5b610036610031366004610138565b61005f565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b6000828251836020016000f5905073ffffffffffffffffffffffffffffffffffffffff81166100ba576040517f3011642500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60405173ffffffffffffffffffffffffffffffffffffffff821681527fcf78cf0d6f3d8371e1075c69c492ab4ec5d8cf23a1a239b6a51a1d00be7ca3129060200160405180910390a192915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000806040838503121561014b57600080fd5b82359150602083013567ffffffffffffffff8082111561016a57600080fd5b818501915085601f83011261017e57600080fd5b81358181111561019057610190610109565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f011681019083821181831017156101d6576101d6610109565b816040528281528860208487010111156101ef57600080fd5b826020860160208301376000602084830101528095505050505050925092905056fea164736f6c6343000813000a", +} + +var SmartContractAccountFactoryABI = SmartContractAccountFactoryMetaData.ABI + +var SmartContractAccountFactoryBin = SmartContractAccountFactoryMetaData.Bin + +func DeploySmartContractAccountFactory(auth *bind.TransactOpts, backend bind.ContractBackend) (common.Address, *types.Transaction, *SmartContractAccountFactory, error) { + parsed, err := SmartContractAccountFactoryMetaData.GetAbi() + if err != nil { + return common.Address{}, nil, nil, err + } + if parsed == nil { + return common.Address{}, nil, nil, errors.New("GetABI returned nil") + } + + address, tx, contract, err := bind.DeployContract(auth, *parsed, common.FromHex(SmartContractAccountFactoryBin), backend) + if err != nil { + return common.Address{}, nil, nil, err + } + return address, tx, &SmartContractAccountFactory{address: address, abi: *parsed, SmartContractAccountFactoryCaller: SmartContractAccountFactoryCaller{contract: contract}, SmartContractAccountFactoryTransactor: SmartContractAccountFactoryTransactor{contract: contract}, SmartContractAccountFactoryFilterer: SmartContractAccountFactoryFilterer{contract: contract}}, nil +} + +type SmartContractAccountFactory struct { + address common.Address + abi abi.ABI + SmartContractAccountFactoryCaller + SmartContractAccountFactoryTransactor + SmartContractAccountFactoryFilterer +} + +type SmartContractAccountFactoryCaller struct { + contract *bind.BoundContract +} + +type SmartContractAccountFactoryTransactor struct { + contract *bind.BoundContract +} + +type SmartContractAccountFactoryFilterer struct { + contract *bind.BoundContract +} + +type SmartContractAccountFactorySession struct { + Contract *SmartContractAccountFactory + CallOpts bind.CallOpts + TransactOpts bind.TransactOpts +} + +type SmartContractAccountFactoryCallerSession struct { + Contract *SmartContractAccountFactoryCaller + CallOpts bind.CallOpts +} + +type SmartContractAccountFactoryTransactorSession struct { + Contract *SmartContractAccountFactoryTransactor + TransactOpts bind.TransactOpts +} + +type SmartContractAccountFactoryRaw struct { + Contract *SmartContractAccountFactory +} + +type SmartContractAccountFactoryCallerRaw struct { + Contract *SmartContractAccountFactoryCaller +} + +type SmartContractAccountFactoryTransactorRaw struct { + Contract *SmartContractAccountFactoryTransactor +} + +func NewSmartContractAccountFactory(address common.Address, backend bind.ContractBackend) (*SmartContractAccountFactory, error) { + abi, err := abi.JSON(strings.NewReader(SmartContractAccountFactoryABI)) + if err != nil { + return nil, err + } + contract, err := bindSmartContractAccountFactory(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &SmartContractAccountFactory{address: address, abi: abi, SmartContractAccountFactoryCaller: SmartContractAccountFactoryCaller{contract: contract}, SmartContractAccountFactoryTransactor: SmartContractAccountFactoryTransactor{contract: contract}, SmartContractAccountFactoryFilterer: SmartContractAccountFactoryFilterer{contract: contract}}, nil +} + +func NewSmartContractAccountFactoryCaller(address common.Address, caller bind.ContractCaller) (*SmartContractAccountFactoryCaller, error) { + contract, err := bindSmartContractAccountFactory(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &SmartContractAccountFactoryCaller{contract: contract}, nil +} + +func NewSmartContractAccountFactoryTransactor(address common.Address, transactor bind.ContractTransactor) (*SmartContractAccountFactoryTransactor, error) { + contract, err := bindSmartContractAccountFactory(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &SmartContractAccountFactoryTransactor{contract: contract}, nil +} + +func NewSmartContractAccountFactoryFilterer(address common.Address, filterer bind.ContractFilterer) (*SmartContractAccountFactoryFilterer, error) { + contract, err := bindSmartContractAccountFactory(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &SmartContractAccountFactoryFilterer{contract: contract}, nil +} + +func bindSmartContractAccountFactory(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := SmartContractAccountFactoryMetaData.GetAbi() + if err != nil { + return nil, err + } + return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil +} + +func (_SmartContractAccountFactory *SmartContractAccountFactoryRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _SmartContractAccountFactory.Contract.SmartContractAccountFactoryCaller.contract.Call(opts, result, method, params...) +} + +func (_SmartContractAccountFactory *SmartContractAccountFactoryRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _SmartContractAccountFactory.Contract.SmartContractAccountFactoryTransactor.contract.Transfer(opts) +} + +func (_SmartContractAccountFactory *SmartContractAccountFactoryRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _SmartContractAccountFactory.Contract.SmartContractAccountFactoryTransactor.contract.Transact(opts, method, params...) +} + +func (_SmartContractAccountFactory *SmartContractAccountFactoryCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _SmartContractAccountFactory.Contract.contract.Call(opts, result, method, params...) +} + +func (_SmartContractAccountFactory *SmartContractAccountFactoryTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _SmartContractAccountFactory.Contract.contract.Transfer(opts) +} + +func (_SmartContractAccountFactory *SmartContractAccountFactoryTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _SmartContractAccountFactory.Contract.contract.Transact(opts, method, params...) +} + +func (_SmartContractAccountFactory *SmartContractAccountFactoryTransactor) DeploySmartContractAccount(opts *bind.TransactOpts, abiEncodedOwnerAddress [32]byte, initCode []byte) (*types.Transaction, error) { + return _SmartContractAccountFactory.contract.Transact(opts, "deploySmartContractAccount", abiEncodedOwnerAddress, initCode) +} + +func (_SmartContractAccountFactory *SmartContractAccountFactorySession) DeploySmartContractAccount(abiEncodedOwnerAddress [32]byte, initCode []byte) (*types.Transaction, error) { + return _SmartContractAccountFactory.Contract.DeploySmartContractAccount(&_SmartContractAccountFactory.TransactOpts, abiEncodedOwnerAddress, initCode) +} + +func (_SmartContractAccountFactory *SmartContractAccountFactoryTransactorSession) DeploySmartContractAccount(abiEncodedOwnerAddress [32]byte, initCode []byte) (*types.Transaction, error) { + return _SmartContractAccountFactory.Contract.DeploySmartContractAccount(&_SmartContractAccountFactory.TransactOpts, abiEncodedOwnerAddress, initCode) +} + +type SmartContractAccountFactoryContractCreatedIterator struct { + Event *SmartContractAccountFactoryContractCreated + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *SmartContractAccountFactoryContractCreatedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(SmartContractAccountFactoryContractCreated) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(SmartContractAccountFactoryContractCreated) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *SmartContractAccountFactoryContractCreatedIterator) Error() error { + return it.fail +} + +func (it *SmartContractAccountFactoryContractCreatedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type SmartContractAccountFactoryContractCreated struct { + ScaAddress common.Address + Raw types.Log +} + +func (_SmartContractAccountFactory *SmartContractAccountFactoryFilterer) FilterContractCreated(opts *bind.FilterOpts) (*SmartContractAccountFactoryContractCreatedIterator, error) { + + logs, sub, err := _SmartContractAccountFactory.contract.FilterLogs(opts, "ContractCreated") + if err != nil { + return nil, err + } + return &SmartContractAccountFactoryContractCreatedIterator{contract: _SmartContractAccountFactory.contract, event: "ContractCreated", logs: logs, sub: sub}, nil +} + +func (_SmartContractAccountFactory *SmartContractAccountFactoryFilterer) WatchContractCreated(opts *bind.WatchOpts, sink chan<- *SmartContractAccountFactoryContractCreated) (event.Subscription, error) { + + logs, sub, err := _SmartContractAccountFactory.contract.WatchLogs(opts, "ContractCreated") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(SmartContractAccountFactoryContractCreated) + if err := _SmartContractAccountFactory.contract.UnpackLog(event, "ContractCreated", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_SmartContractAccountFactory *SmartContractAccountFactoryFilterer) ParseContractCreated(log types.Log) (*SmartContractAccountFactoryContractCreated, error) { + event := new(SmartContractAccountFactoryContractCreated) + if err := _SmartContractAccountFactory.contract.UnpackLog(event, "ContractCreated", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +func (_SmartContractAccountFactory *SmartContractAccountFactory) ParseLog(log types.Log) (generated.AbigenLog, error) { + switch log.Topics[0] { + case _SmartContractAccountFactory.abi.Events["ContractCreated"].ID: + return _SmartContractAccountFactory.ParseContractCreated(log) + + default: + return nil, fmt.Errorf("abigen wrapper received unknown log topic: %v", log.Topics[0]) + } +} + +func (SmartContractAccountFactoryContractCreated) Topic() common.Hash { + return common.HexToHash("0xcf78cf0d6f3d8371e1075c69c492ab4ec5d8cf23a1a239b6a51a1d00be7ca312") +} + +func (_SmartContractAccountFactory *SmartContractAccountFactory) Address() common.Address { + return _SmartContractAccountFactory.address +} + +type SmartContractAccountFactoryInterface interface { + DeploySmartContractAccount(opts *bind.TransactOpts, abiEncodedOwnerAddress [32]byte, initCode []byte) (*types.Transaction, error) + + FilterContractCreated(opts *bind.FilterOpts) (*SmartContractAccountFactoryContractCreatedIterator, error) + + WatchContractCreated(opts *bind.WatchOpts, sink chan<- *SmartContractAccountFactoryContractCreated) (event.Subscription, error) + + ParseContractCreated(log types.Log) (*SmartContractAccountFactoryContractCreated, error) + + ParseLog(log types.Log) (generated.AbigenLog, error) + + Address() common.Address +} diff --git a/core/gethwrappers/transmission/generated/smart_contract_account_helper/smart_contract_account_helper.go b/core/gethwrappers/transmission/generated/smart_contract_account_helper/smart_contract_account_helper.go new file mode 100644 index 00000000000..36e63e3683e --- /dev/null +++ b/core/gethwrappers/transmission/generated/smart_contract_account_helper/smart_contract_account_helper.go @@ -0,0 +1,322 @@ +// Code generated - DO NOT EDIT. +// This file is a generated binding and any manual changes will be lost. + +package smart_contract_account_helper + +import ( + "errors" + "math/big" + "strings" + + ethereum "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/event" +) + +var ( + _ = errors.New + _ = big.NewInt + _ = strings.NewReader + _ = ethereum.NotFound + _ = bind.Bind + _ = common.Big1 + _ = types.BloomLookup + _ = event.NewSubscription + _ = abi.ConvertType +) + +var SmartContractAccountHelperMetaData = &bind.MetaData{ + ABI: "[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"entryPoint\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"factory\",\"type\":\"address\"}],\"name\":\"calculateSmartContractAccountAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"topupThreshold\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"topupAmount\",\"type\":\"uint256\"}],\"name\":\"getAbiEncodedDirectRequestData\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"endContract\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"getFullEndTxEncoding\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"encoding\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"userOpHash\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"scaAddress\",\"type\":\"address\"}],\"name\":\"getFullHashForSigning\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"factory\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"entryPoint\",\"type\":\"address\"}],\"name\":\"getInitCode\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"initCode\",\"type\":\"bytes\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"entryPoint\",\"type\":\"address\"}],\"name\":\"getSCAInitCodeWithConstructor\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"initCode\",\"type\":\"bytes\"}],\"stateMutability\":\"pure\",\"type\":\"function\"}]", + Bin: "0x61161361003a600b82828239805160001a60731461002d57634e487b7160e01b600052600060045260246000fd5b30600052607381538281f3fe730000000000000000000000000000000000000000301460806040526004361061007c5760003560e01c8063e0237bef1161005a578063e0237bef14610134578063e464b3631461016c578063fc59bac31461017f57600080fd5b80632c86cb35146100815780634b770f561461010057806382311e3314610113575b600080fd5b6100ea61008f36600461076d565b604080516060808201835273ffffffffffffffffffffffffffffffffffffffff959095168082526020808301958652918301938452825191820152925183820152905182840152805180830390930183526080909101905290565b6040516100f7919061080e565b60405180910390f35b6100ea61010e366004610821565b610192565b610126610121366004610864565b610336565b6040519081526020016100f7565b610147610142366004610821565b610456565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100f7565b6100ea61017a366004610890565b6105e1565b6100ea61018d3660046108e9565b61069f565b6040516060907fffffffffffffffffffffffffffffffffffffffff00000000000000000000000084831b16906000906101cd60208201610737565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe082820381018352601f90910116604081815273ffffffffffffffffffffffffffffffffffffffff8881166020840152871690820152606001604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529082905261026292916020016109dc565b60405160208183030381529060405290508560601b630af4926f60e01b8383604051602401610292929190610a0b565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152918152602080830180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909516949094179093525161031c939201610a2c565b604051602081830303815290604052925050509392505050565b600061044d8383604080517f4750045d47fce615521b32cee713ff8db50147e98aec5ca94926b52651ca3fa060208083019190915281830194909452815180820383018152606080830184528151918601919091207f190000000000000000000000000000000000000000000000000000000000000060808401527f010000000000000000000000000000000000000000000000000000000000000060818401527f1c7d3b72b37a35523e273aaadd7b4cd66f618bb81429ab053412d51f50ccea6160828401524660a284015293901b7fffffffffffffffffffffffffffffffffffffffff0000000000000000000000001660c282015260d6808201939093528151808203909301835260f6019052805191012090565b90505b92915050565b6040516000907fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606086901b1690829061049260208201610737565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe082820381018352601f90910116604081815273ffffffffffffffffffffffffffffffffffffffff8981166020840152881690820152606001604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529082905261052792916020016109dc565b604080518083037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe001815282825280516020918201207fff000000000000000000000000000000000000000000000000000000000000008285015260609790971b7fffffffffffffffffffffffffffffffffffffffff000000000000000000000000166021840152603583019490945260558083019690965280518083039096018652607590910190525082519201919091209392505050565b6060604051806020016105f390610737565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe082820381018352601f90910116604081815273ffffffffffffffffffffffffffffffffffffffff8681166020840152851690820152606001604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529082905261068892916020016109dc565b604051602081830303815290604052905092915050565b60607f89553be40000000000000000000000000000000000000000000000000000000085856106ce8642610a74565b856040516020016106e29493929190610aae565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529082905261071e9291602001610af3565b6040516020818303038152906040529050949350505050565b610acb80610b3c83390190565b803573ffffffffffffffffffffffffffffffffffffffff8116811461076857600080fd5b919050565b60008060006060848603121561078257600080fd5b61078b84610744565b95602085013595506040909401359392505050565b60005b838110156107bb5781810151838201526020016107a3565b50506000910152565b600081518084526107dc8160208601602086016107a0565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60208152600061044d60208301846107c4565b60008060006060848603121561083657600080fd5b61083f84610744565b925061084d60208501610744565b915061085b60408501610744565b90509250925092565b6000806040838503121561087757600080fd5b8235915061088760208401610744565b90509250929050565b600080604083850312156108a357600080fd5b6108ac83610744565b915061088760208401610744565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600080600080608085870312156108ff57600080fd5b61090885610744565b93506020850135925060408501359150606085013567ffffffffffffffff8082111561093357600080fd5b818701915087601f83011261094757600080fd5b813581811115610959576109596108ba565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190838211818310171561099f5761099f6108ba565b816040528281528a60208487010111156109b857600080fd5b82602086016020830137600060208483010152809550505050505092959194509250565b600083516109ee8184602088016107a0565b835190830190610a028183602088016107a0565b01949350505050565b828152604060208201526000610a2460408301846107c4565b949350505050565b7fffffffffffffffffffffffffffffffffffffffff0000000000000000000000008316815260008251610a668160148501602087016107a0565b919091016014019392505050565b80820180821115610450577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b73ffffffffffffffffffffffffffffffffffffffff85168152836020820152826040820152608060608201526000610ae960808301846107c4565b9695505050505050565b7fffffffff000000000000000000000000000000000000000000000000000000008316815260008251610b2d8160048501602087016107a0565b91909101600401939250505056fe60c060405234801561001057600080fd5b50604051610acb380380610acb83398101604081905261002f91610062565b6001600160a01b039182166080521660a052610095565b80516001600160a01b038116811461005d57600080fd5b919050565b6000806040838503121561007557600080fd5b61007e83610046565b915061008c60208401610046565b90509250929050565b60805160a051610a046100c760003960008181607101526102b801526000818161010101526101e30152610a046000f3fe608060405234801561001057600080fd5b50600436106100675760003560e01c80637eccf63e116100505780637eccf63e146100de57806389553be4146100e7578063dba6335f146100fc57600080fd5b8063140fcfb11461006c5780633a871cdd146100bd575b600080fd5b6100937f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b6100d06100cb366004610646565b610123565b6040519081526020016100b4565b6100d060005481565b6100fa6100f53660046106da565b6102a0565b005b6100937f000000000000000000000000000000000000000000000000000000000000000081565b60008054846020013514610179576000546040517f7ba633940000000000000000000000000000000000000000000000000000000081526004810191909152602085013560248201526044015b60405180910390fd5b60006101858430610439565b90506000610197610140870187610777565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509293505073ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016915061021190508284610550565b73ffffffffffffffffffffffffffffffffffffffff161461024257610239600160008061060e565b92505050610299565b60008054908061025183610812565b90915550600090506102666060880188610777565b61027491600490829061084a565b81019061028191906108a3565b5092505050610293600082600061060e565b93505050505b9392505050565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610311576040517f4a0bfec1000000000000000000000000000000000000000000000000000000008152336004820152602401610170565b65ffffffffffff83161580159061032f57508265ffffffffffff1642115b15610376576040517f300249d700000000000000000000000000000000000000000000000000000000815265ffffffffffff84166004820152426024820152604401610170565b6000808673ffffffffffffffffffffffffffffffffffffffff168685856040516103a192919061099f565b60006040518083038185875af1925050503d80600081146103de576040519150601f19603f3d011682016040523d82523d6000602084013e6103e3565b606091505b509150915081610430578051600003610428576040517f20e9b5d200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805181602001fd5b50505050505050565b604080517f4750045d47fce615521b32cee713ff8db50147e98aec5ca94926b52651ca3fa0602080830191909152818301859052825180830384018152606080840185528151918301919091207f190000000000000000000000000000000000000000000000000000000000000060808501527f010000000000000000000000000000000000000000000000000000000000000060818501527f1c7d3b72b37a35523e273aaadd7b4cd66f618bb81429ab053412d51f50ccea6160828501524660a28501529085901b7fffffffffffffffffffffffffffffffffffffffff0000000000000000000000001660c284015260d6808401919091528351808403909101815260f690920190925280519101205b92915050565b602082015160408084015184516000939284918791908110610574576105746109af565b016020015160f81c905060018561058c83601b6109de565b6040805160008152602081018083529390935260ff90911690820152606081018590526080810184905260a0016020604051602081039080840390855afa1580156105db573d6000803e3d6000fd5b50506040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe00151979650505050505050565b600060d08265ffffffffffff16901b60a08465ffffffffffff16901b85610636576000610639565b60015b60ff161717949350505050565b60008060006060848603121561065b57600080fd5b833567ffffffffffffffff81111561067257600080fd5b8401610160818703121561068557600080fd5b95602085013595506040909401359392505050565b73ffffffffffffffffffffffffffffffffffffffff811681146106bc57600080fd5b50565b803565ffffffffffff811681146106d557600080fd5b919050565b6000806000806000608086880312156106f257600080fd5b85356106fd8161069a565b945060208601359350610712604087016106bf565b9250606086013567ffffffffffffffff8082111561072f57600080fd5b818801915088601f83011261074357600080fd5b81358181111561075257600080fd5b89602082850101111561076457600080fd5b9699959850939650602001949392505050565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18436030181126107ac57600080fd5b83018035915067ffffffffffffffff8211156107c757600080fd5b6020019150368190038213156107dc57600080fd5b9250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203610843576108436107e3565b5060010190565b6000808585111561085a57600080fd5b8386111561086757600080fd5b5050820193919092039150565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600080600080608085870312156108b957600080fd5b84356108c48161069a565b9350602085013592506108d9604086016106bf565b9150606085013567ffffffffffffffff808211156108f657600080fd5b818701915087601f83011261090a57600080fd5b81358181111561091c5761091c610874565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190838211818310171561096257610962610874565b816040528281528a602084870101111561097b57600080fd5b82602086016020830137600060208483010152809550505050505092959194509250565b8183823760009101908152919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60ff818116838216019081111561054a5761054a6107e356fea164736f6c6343000813000aa164736f6c6343000813000a", +} + +var SmartContractAccountHelperABI = SmartContractAccountHelperMetaData.ABI + +var SmartContractAccountHelperBin = SmartContractAccountHelperMetaData.Bin + +func DeploySmartContractAccountHelper(auth *bind.TransactOpts, backend bind.ContractBackend) (common.Address, *types.Transaction, *SmartContractAccountHelper, error) { + parsed, err := SmartContractAccountHelperMetaData.GetAbi() + if err != nil { + return common.Address{}, nil, nil, err + } + if parsed == nil { + return common.Address{}, nil, nil, errors.New("GetABI returned nil") + } + + address, tx, contract, err := bind.DeployContract(auth, *parsed, common.FromHex(SmartContractAccountHelperBin), backend) + if err != nil { + return common.Address{}, nil, nil, err + } + return address, tx, &SmartContractAccountHelper{address: address, abi: *parsed, SmartContractAccountHelperCaller: SmartContractAccountHelperCaller{contract: contract}, SmartContractAccountHelperTransactor: SmartContractAccountHelperTransactor{contract: contract}, SmartContractAccountHelperFilterer: SmartContractAccountHelperFilterer{contract: contract}}, nil +} + +type SmartContractAccountHelper struct { + address common.Address + abi abi.ABI + SmartContractAccountHelperCaller + SmartContractAccountHelperTransactor + SmartContractAccountHelperFilterer +} + +type SmartContractAccountHelperCaller struct { + contract *bind.BoundContract +} + +type SmartContractAccountHelperTransactor struct { + contract *bind.BoundContract +} + +type SmartContractAccountHelperFilterer struct { + contract *bind.BoundContract +} + +type SmartContractAccountHelperSession struct { + Contract *SmartContractAccountHelper + CallOpts bind.CallOpts + TransactOpts bind.TransactOpts +} + +type SmartContractAccountHelperCallerSession struct { + Contract *SmartContractAccountHelperCaller + CallOpts bind.CallOpts +} + +type SmartContractAccountHelperTransactorSession struct { + Contract *SmartContractAccountHelperTransactor + TransactOpts bind.TransactOpts +} + +type SmartContractAccountHelperRaw struct { + Contract *SmartContractAccountHelper +} + +type SmartContractAccountHelperCallerRaw struct { + Contract *SmartContractAccountHelperCaller +} + +type SmartContractAccountHelperTransactorRaw struct { + Contract *SmartContractAccountHelperTransactor +} + +func NewSmartContractAccountHelper(address common.Address, backend bind.ContractBackend) (*SmartContractAccountHelper, error) { + abi, err := abi.JSON(strings.NewReader(SmartContractAccountHelperABI)) + if err != nil { + return nil, err + } + contract, err := bindSmartContractAccountHelper(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &SmartContractAccountHelper{address: address, abi: abi, SmartContractAccountHelperCaller: SmartContractAccountHelperCaller{contract: contract}, SmartContractAccountHelperTransactor: SmartContractAccountHelperTransactor{contract: contract}, SmartContractAccountHelperFilterer: SmartContractAccountHelperFilterer{contract: contract}}, nil +} + +func NewSmartContractAccountHelperCaller(address common.Address, caller bind.ContractCaller) (*SmartContractAccountHelperCaller, error) { + contract, err := bindSmartContractAccountHelper(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &SmartContractAccountHelperCaller{contract: contract}, nil +} + +func NewSmartContractAccountHelperTransactor(address common.Address, transactor bind.ContractTransactor) (*SmartContractAccountHelperTransactor, error) { + contract, err := bindSmartContractAccountHelper(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &SmartContractAccountHelperTransactor{contract: contract}, nil +} + +func NewSmartContractAccountHelperFilterer(address common.Address, filterer bind.ContractFilterer) (*SmartContractAccountHelperFilterer, error) { + contract, err := bindSmartContractAccountHelper(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &SmartContractAccountHelperFilterer{contract: contract}, nil +} + +func bindSmartContractAccountHelper(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := SmartContractAccountHelperMetaData.GetAbi() + if err != nil { + return nil, err + } + return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil +} + +func (_SmartContractAccountHelper *SmartContractAccountHelperRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _SmartContractAccountHelper.Contract.SmartContractAccountHelperCaller.contract.Call(opts, result, method, params...) +} + +func (_SmartContractAccountHelper *SmartContractAccountHelperRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _SmartContractAccountHelper.Contract.SmartContractAccountHelperTransactor.contract.Transfer(opts) +} + +func (_SmartContractAccountHelper *SmartContractAccountHelperRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _SmartContractAccountHelper.Contract.SmartContractAccountHelperTransactor.contract.Transact(opts, method, params...) +} + +func (_SmartContractAccountHelper *SmartContractAccountHelperCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _SmartContractAccountHelper.Contract.contract.Call(opts, result, method, params...) +} + +func (_SmartContractAccountHelper *SmartContractAccountHelperTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _SmartContractAccountHelper.Contract.contract.Transfer(opts) +} + +func (_SmartContractAccountHelper *SmartContractAccountHelperTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _SmartContractAccountHelper.Contract.contract.Transact(opts, method, params...) +} + +func (_SmartContractAccountHelper *SmartContractAccountHelperCaller) CalculateSmartContractAccountAddress(opts *bind.CallOpts, owner common.Address, entryPoint common.Address, factory common.Address) (common.Address, error) { + var out []interface{} + err := _SmartContractAccountHelper.contract.Call(opts, &out, "calculateSmartContractAccountAddress", owner, entryPoint, factory) + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +func (_SmartContractAccountHelper *SmartContractAccountHelperSession) CalculateSmartContractAccountAddress(owner common.Address, entryPoint common.Address, factory common.Address) (common.Address, error) { + return _SmartContractAccountHelper.Contract.CalculateSmartContractAccountAddress(&_SmartContractAccountHelper.CallOpts, owner, entryPoint, factory) +} + +func (_SmartContractAccountHelper *SmartContractAccountHelperCallerSession) CalculateSmartContractAccountAddress(owner common.Address, entryPoint common.Address, factory common.Address) (common.Address, error) { + return _SmartContractAccountHelper.Contract.CalculateSmartContractAccountAddress(&_SmartContractAccountHelper.CallOpts, owner, entryPoint, factory) +} + +func (_SmartContractAccountHelper *SmartContractAccountHelperCaller) GetAbiEncodedDirectRequestData(opts *bind.CallOpts, recipient common.Address, topupThreshold *big.Int, topupAmount *big.Int) ([]byte, error) { + var out []interface{} + err := _SmartContractAccountHelper.contract.Call(opts, &out, "getAbiEncodedDirectRequestData", recipient, topupThreshold, topupAmount) + + if err != nil { + return *new([]byte), err + } + + out0 := *abi.ConvertType(out[0], new([]byte)).(*[]byte) + + return out0, err + +} + +func (_SmartContractAccountHelper *SmartContractAccountHelperSession) GetAbiEncodedDirectRequestData(recipient common.Address, topupThreshold *big.Int, topupAmount *big.Int) ([]byte, error) { + return _SmartContractAccountHelper.Contract.GetAbiEncodedDirectRequestData(&_SmartContractAccountHelper.CallOpts, recipient, topupThreshold, topupAmount) +} + +func (_SmartContractAccountHelper *SmartContractAccountHelperCallerSession) GetAbiEncodedDirectRequestData(recipient common.Address, topupThreshold *big.Int, topupAmount *big.Int) ([]byte, error) { + return _SmartContractAccountHelper.Contract.GetAbiEncodedDirectRequestData(&_SmartContractAccountHelper.CallOpts, recipient, topupThreshold, topupAmount) +} + +func (_SmartContractAccountHelper *SmartContractAccountHelperCaller) GetFullEndTxEncoding(opts *bind.CallOpts, endContract common.Address, value *big.Int, deadline *big.Int, data []byte) ([]byte, error) { + var out []interface{} + err := _SmartContractAccountHelper.contract.Call(opts, &out, "getFullEndTxEncoding", endContract, value, deadline, data) + + if err != nil { + return *new([]byte), err + } + + out0 := *abi.ConvertType(out[0], new([]byte)).(*[]byte) + + return out0, err + +} + +func (_SmartContractAccountHelper *SmartContractAccountHelperSession) GetFullEndTxEncoding(endContract common.Address, value *big.Int, deadline *big.Int, data []byte) ([]byte, error) { + return _SmartContractAccountHelper.Contract.GetFullEndTxEncoding(&_SmartContractAccountHelper.CallOpts, endContract, value, deadline, data) +} + +func (_SmartContractAccountHelper *SmartContractAccountHelperCallerSession) GetFullEndTxEncoding(endContract common.Address, value *big.Int, deadline *big.Int, data []byte) ([]byte, error) { + return _SmartContractAccountHelper.Contract.GetFullEndTxEncoding(&_SmartContractAccountHelper.CallOpts, endContract, value, deadline, data) +} + +func (_SmartContractAccountHelper *SmartContractAccountHelperCaller) GetFullHashForSigning(opts *bind.CallOpts, userOpHash [32]byte, scaAddress common.Address) ([32]byte, error) { + var out []interface{} + err := _SmartContractAccountHelper.contract.Call(opts, &out, "getFullHashForSigning", userOpHash, scaAddress) + + if err != nil { + return *new([32]byte), err + } + + out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) + + return out0, err + +} + +func (_SmartContractAccountHelper *SmartContractAccountHelperSession) GetFullHashForSigning(userOpHash [32]byte, scaAddress common.Address) ([32]byte, error) { + return _SmartContractAccountHelper.Contract.GetFullHashForSigning(&_SmartContractAccountHelper.CallOpts, userOpHash, scaAddress) +} + +func (_SmartContractAccountHelper *SmartContractAccountHelperCallerSession) GetFullHashForSigning(userOpHash [32]byte, scaAddress common.Address) ([32]byte, error) { + return _SmartContractAccountHelper.Contract.GetFullHashForSigning(&_SmartContractAccountHelper.CallOpts, userOpHash, scaAddress) +} + +func (_SmartContractAccountHelper *SmartContractAccountHelperCaller) GetInitCode(opts *bind.CallOpts, factory common.Address, owner common.Address, entryPoint common.Address) ([]byte, error) { + var out []interface{} + err := _SmartContractAccountHelper.contract.Call(opts, &out, "getInitCode", factory, owner, entryPoint) + + if err != nil { + return *new([]byte), err + } + + out0 := *abi.ConvertType(out[0], new([]byte)).(*[]byte) + + return out0, err + +} + +func (_SmartContractAccountHelper *SmartContractAccountHelperSession) GetInitCode(factory common.Address, owner common.Address, entryPoint common.Address) ([]byte, error) { + return _SmartContractAccountHelper.Contract.GetInitCode(&_SmartContractAccountHelper.CallOpts, factory, owner, entryPoint) +} + +func (_SmartContractAccountHelper *SmartContractAccountHelperCallerSession) GetInitCode(factory common.Address, owner common.Address, entryPoint common.Address) ([]byte, error) { + return _SmartContractAccountHelper.Contract.GetInitCode(&_SmartContractAccountHelper.CallOpts, factory, owner, entryPoint) +} + +func (_SmartContractAccountHelper *SmartContractAccountHelperCaller) GetSCAInitCodeWithConstructor(opts *bind.CallOpts, owner common.Address, entryPoint common.Address) ([]byte, error) { + var out []interface{} + err := _SmartContractAccountHelper.contract.Call(opts, &out, "getSCAInitCodeWithConstructor", owner, entryPoint) + + if err != nil { + return *new([]byte), err + } + + out0 := *abi.ConvertType(out[0], new([]byte)).(*[]byte) + + return out0, err + +} + +func (_SmartContractAccountHelper *SmartContractAccountHelperSession) GetSCAInitCodeWithConstructor(owner common.Address, entryPoint common.Address) ([]byte, error) { + return _SmartContractAccountHelper.Contract.GetSCAInitCodeWithConstructor(&_SmartContractAccountHelper.CallOpts, owner, entryPoint) +} + +func (_SmartContractAccountHelper *SmartContractAccountHelperCallerSession) GetSCAInitCodeWithConstructor(owner common.Address, entryPoint common.Address) ([]byte, error) { + return _SmartContractAccountHelper.Contract.GetSCAInitCodeWithConstructor(&_SmartContractAccountHelper.CallOpts, owner, entryPoint) +} + +func (_SmartContractAccountHelper *SmartContractAccountHelper) Address() common.Address { + return _SmartContractAccountHelper.address +} + +type SmartContractAccountHelperInterface interface { + CalculateSmartContractAccountAddress(opts *bind.CallOpts, owner common.Address, entryPoint common.Address, factory common.Address) (common.Address, error) + + GetAbiEncodedDirectRequestData(opts *bind.CallOpts, recipient common.Address, topupThreshold *big.Int, topupAmount *big.Int) ([]byte, error) + + GetFullEndTxEncoding(opts *bind.CallOpts, endContract common.Address, value *big.Int, deadline *big.Int, data []byte) ([]byte, error) + + GetFullHashForSigning(opts *bind.CallOpts, userOpHash [32]byte, scaAddress common.Address) ([32]byte, error) + + GetInitCode(opts *bind.CallOpts, factory common.Address, owner common.Address, entryPoint common.Address) ([]byte, error) + + GetSCAInitCodeWithConstructor(opts *bind.CallOpts, owner common.Address, entryPoint common.Address) ([]byte, error) + + Address() common.Address +} diff --git a/core/gethwrappers/transmission/generation/generated-wrapper-dependency-versions-do-not-edit.txt b/core/gethwrappers/transmission/generation/generated-wrapper-dependency-versions-do-not-edit.txt new file mode 100644 index 00000000000..3ccf8656388 --- /dev/null +++ b/core/gethwrappers/transmission/generation/generated-wrapper-dependency-versions-do-not-edit.txt @@ -0,0 +1,9 @@ +GETH_VERSION: 1.14.11 +entry_point: ../../../contracts/solc/v0.8.19/EntryPoint/EntryPoint.abi ../../../contracts/solc/v0.8.19/EntryPoint/EntryPoint.bin e43da0e61256471b317cab1c87f2425cecba9b81ac21633334f889bab2f0777d +greeter: ../../../contracts/solc/v0.8.15/Greeter.abi ../../../contracts/solc/v0.8.15/Greeter.bin 653dcba5c33a46292073939ce1e639372cf521c0ec2814d4c9f20c72f796f18c +greeter_wrapper: ../../../contracts/solc/v0.8.19/Greeter/Greeter.abi ../../../contracts/solc/v0.8.19/Greeter/Greeter.bin 7f6def58e337a53553a46cb7992cf2d75ec951014d79376fcb869a2b16b53f6d +paymaster_wrapper: ../../../contracts/solc/v0.8.19/Paymaster/Paymaster.abi ../../../contracts/solc/v0.8.19/Paymaster/Paymaster.bin dbdd1341cfa2d5c09730e0decc32339f62d1a4ea89835a51ff774226ddfbd04b +sca: ../../../contracts/solc/v0.8.15/SCA.abi ../../../contracts/solc/v0.8.15/SCA.bin ae0f860cdac87d4ac505edbd228bd3ea1108550453aba67aebcb61f09cf70d0b +sca_wrapper: ../../../contracts/solc/v0.8.19/SCA/SCA.abi ../../../contracts/solc/v0.8.19/SCA/SCA.bin 6ef817bdefad1b5e84f06e0bdc40848000ab00e1a38371435b793946f425a8e6 +smart_contract_account_factory: ../../../contracts/solc/v0.8.19/SmartContractAccountFactory/SmartContractAccountFactory.abi ../../../contracts/solc/v0.8.19/SmartContractAccountFactory/SmartContractAccountFactory.bin a357132e2782c462fa31ed80c270fe002e666a48ecfe407b71c278fc3a0d3679 +smart_contract_account_helper: ../../../contracts/solc/v0.8.19/SmartContractAccountHelper/SmartContractAccountHelper.abi ../../../contracts/solc/v0.8.19/SmartContractAccountHelper/SmartContractAccountHelper.bin a06aff23aded74d53bd342fdc32d80c3b474ff38223df27f3395e9fd90abd12a diff --git a/core/gethwrappers/transmission/go_generate.go b/core/gethwrappers/transmission/go_generate.go new file mode 100644 index 00000000000..b3f2b4b0eb9 --- /dev/null +++ b/core/gethwrappers/transmission/go_generate.go @@ -0,0 +1,11 @@ +// Package gethwrappers provides tools for wrapping solidity contracts with +// golang packages, using abigen. +package gethwrappers + +// Transmission +//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.19/Greeter/Greeter.abi ../../../contracts/solc/v0.8.19/Greeter/Greeter.bin Greeter greeter_wrapper +//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.19/SmartContractAccountFactory/SmartContractAccountFactory.abi ../../../contracts/solc/v0.8.19/SmartContractAccountFactory/SmartContractAccountFactory.bin SmartContractAccountFactory smart_contract_account_factory +//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.19/EntryPoint/EntryPoint.abi ../../../contracts/solc/v0.8.19/EntryPoint/EntryPoint.bin EntryPoint entry_point +//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.19/SmartContractAccountHelper/SmartContractAccountHelper.abi ../../../contracts/solc/v0.8.19/SmartContractAccountHelper/SmartContractAccountHelper.bin SmartContractAccountHelper smart_contract_account_helper +//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.19/SCA/SCA.abi ../../../contracts/solc/v0.8.19/SCA/SCA.bin SCA sca_wrapper +//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.19/Paymaster/Paymaster.abi ../../../contracts/solc/v0.8.19/Paymaster/Paymaster.bin Paymaster paymaster_wrapper diff --git a/core/gethwrappers/workflow/generated/workflow_registry_wrapper/workflow_registry_wrapper.go b/core/gethwrappers/workflow/generated/workflow_registry_wrapper/workflow_registry_wrapper.go index a81d69c343e..008fffab28a 100644 --- a/core/gethwrappers/workflow/generated/workflow_registry_wrapper/workflow_registry_wrapper.go +++ b/core/gethwrappers/workflow/generated/workflow_registry_wrapper/workflow_registry_wrapper.go @@ -42,8 +42,8 @@ type WorkflowRegistryWorkflowMetadata struct { } var WorkflowRegistryMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"AddressNotAuthorized\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"CallerIsNotWorkflowOwner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CannotTransferToSelf\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"donID\",\"type\":\"uint32\"}],\"name\":\"DONNotAllowed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidWorkflowID\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MustBeProposedOwner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByOwner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OwnerCannotBeZero\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RegistryLocked\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"providedLength\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"maxAllowedLength\",\"type\":\"uint8\"}],\"name\":\"URLTooLong\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"WorkflowAlreadyInDesiredStatus\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"WorkflowAlreadyRegistered\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"WorkflowContentNotUpdated\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"WorkflowDoesNotExist\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"WorkflowIDAlreadyExists\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"WorkflowIDNotUpdated\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"providedLength\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"maxAllowedLength\",\"type\":\"uint8\"}],\"name\":\"WorkflowNameTooLong\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint32[]\",\"name\":\"donIDs\",\"type\":\"uint32[]\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"allowed\",\"type\":\"bool\"}],\"name\":\"AllowedDONsUpdatedV1\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"addresses\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"allowed\",\"type\":\"bool\"}],\"name\":\"AuthorizedAddressesUpdatedV1\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"lockedBy\",\"type\":\"address\"}],\"name\":\"RegistryLockedV1\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"unlockedBy\",\"type\":\"address\"}],\"name\":\"RegistryUnlockedV1\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"workflowID\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"workflowOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"uint32\",\"name\":\"donID\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"workflowName\",\"type\":\"string\"}],\"name\":\"WorkflowActivatedV1\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"workflowID\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"workflowOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"uint32\",\"name\":\"donID\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"workflowName\",\"type\":\"string\"}],\"name\":\"WorkflowDeletedV1\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"secretsURLHash\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"workflowName\",\"type\":\"string\"}],\"name\":\"WorkflowForceUpdateSecretsRequestedV1\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"workflowID\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"workflowOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"uint32\",\"name\":\"donID\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"workflowName\",\"type\":\"string\"}],\"name\":\"WorkflowPausedV1\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"workflowID\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"workflowOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"uint32\",\"name\":\"donID\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"enumWorkflowRegistry.WorkflowStatus\",\"name\":\"status\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"workflowName\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"binaryURL\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"configURL\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"secretsURL\",\"type\":\"string\"}],\"name\":\"WorkflowRegisteredV1\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"oldWorkflowID\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"workflowOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"uint32\",\"name\":\"donID\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"newWorkflowID\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"workflowName\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"binaryURL\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"configURL\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"secretsURL\",\"type\":\"string\"}],\"name\":\"WorkflowUpdatedV1\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"workflowKey\",\"type\":\"bytes32\"}],\"name\":\"activateWorkflow\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"field\",\"type\":\"string\"}],\"name\":\"computeHashKey\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"workflowKey\",\"type\":\"bytes32\"}],\"name\":\"deleteWorkflow\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAllAllowedDONs\",\"outputs\":[{\"internalType\":\"uint32[]\",\"name\":\"allowedDONs\",\"type\":\"uint32[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAllAuthorizedAddresses\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"authorizedAddresses\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"workflowOwner\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"workflowName\",\"type\":\"string\"}],\"name\":\"getWorkflowMetadata\",\"outputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"workflowID\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"donID\",\"type\":\"uint32\"},{\"internalType\":\"enumWorkflowRegistry.WorkflowStatus\",\"name\":\"status\",\"type\":\"uint8\"},{\"internalType\":\"string\",\"name\":\"workflowName\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"binaryURL\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"configURL\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"secretsURL\",\"type\":\"string\"}],\"internalType\":\"structWorkflowRegistry.WorkflowMetadata\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"donID\",\"type\":\"uint32\"},{\"internalType\":\"uint256\",\"name\":\"start\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"limit\",\"type\":\"uint256\"}],\"name\":\"getWorkflowMetadataListByDON\",\"outputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"workflowID\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"donID\",\"type\":\"uint32\"},{\"internalType\":\"enumWorkflowRegistry.WorkflowStatus\",\"name\":\"status\",\"type\":\"uint8\"},{\"internalType\":\"string\",\"name\":\"workflowName\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"binaryURL\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"configURL\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"secretsURL\",\"type\":\"string\"}],\"internalType\":\"structWorkflowRegistry.WorkflowMetadata[]\",\"name\":\"workflowMetadataList\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"workflowOwner\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"start\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"limit\",\"type\":\"uint256\"}],\"name\":\"getWorkflowMetadataListByOwner\",\"outputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"workflowID\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"donID\",\"type\":\"uint32\"},{\"internalType\":\"enumWorkflowRegistry.WorkflowStatus\",\"name\":\"status\",\"type\":\"uint8\"},{\"internalType\":\"string\",\"name\":\"workflowName\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"binaryURL\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"configURL\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"secretsURL\",\"type\":\"string\"}],\"internalType\":\"structWorkflowRegistry.WorkflowMetadata[]\",\"name\":\"workflowMetadataList\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"isRegistryLocked\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"lockRegistry\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"workflowKey\",\"type\":\"bytes32\"}],\"name\":\"pauseWorkflow\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"workflowName\",\"type\":\"string\"},{\"internalType\":\"bytes32\",\"name\":\"workflowID\",\"type\":\"bytes32\"},{\"internalType\":\"uint32\",\"name\":\"donID\",\"type\":\"uint32\"},{\"internalType\":\"enumWorkflowRegistry.WorkflowStatus\",\"name\":\"status\",\"type\":\"uint8\"},{\"internalType\":\"string\",\"name\":\"binaryURL\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"configURL\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"secretsURL\",\"type\":\"string\"}],\"name\":\"registerWorkflow\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"secretsURL\",\"type\":\"string\"}],\"name\":\"requestForceUpdateSecrets\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"unlockRegistry\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32[]\",\"name\":\"donIDs\",\"type\":\"uint32[]\"},{\"internalType\":\"bool\",\"name\":\"allowed\",\"type\":\"bool\"}],\"name\":\"updateAllowedDONs\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"addresses\",\"type\":\"address[]\"},{\"internalType\":\"bool\",\"name\":\"allowed\",\"type\":\"bool\"}],\"name\":\"updateAuthorizedAddresses\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"workflowKey\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"newWorkflowID\",\"type\":\"bytes32\"},{\"internalType\":\"string\",\"name\":\"binaryURL\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"configURL\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"secretsURL\",\"type\":\"string\"}],\"name\":\"updateWorkflow\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", - Bin: "0x6080806040523461004a57331561003b57600180546001600160a01b03191633179055600b805460ff191690556040516134e290816100508239f35b639b15e16f60e01b8152600490fd5b600080fdfe6080604052600436101561001257600080fd5b60003560e01c806308e7f63a1461210e578063181f5a771461207f5780632303348a14611f425780632b596f6d14611eb45780633ccd14ff14611572578063695e1340146113965780636f351771146112bd578063724c13dd146111c65780637497066b146110ab57806379ba509714610fd55780637ec0846d14610f4a5780638da5cb5b14610ef85780639f4cb53414610ed7578063b87a019414610e81578063d4b89c7414610698578063db800092146105fd578063e3dce080146104d6578063e690f33214610362578063f2fde38b14610284578063f794bdeb146101495763f99ecb6b1461010357600080fd5b346101445760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261014457602060ff600b54166040519015158152f35b600080fd5b346101445760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610144576007805461018581612488565b610192604051918261230f565b81815261019e82612488565b916020937fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe060208401940136853760005b82811061023257505050906040519283926020840190602085525180915260408401929160005b82811061020557505050500390f35b835173ffffffffffffffffffffffffffffffffffffffff16855286955093810193928101926001016101f6565b6001908260005273ffffffffffffffffffffffffffffffffffffffff817fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c68801541661027d82876125ba565b52016101cf565b346101445760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610144576102bb6123f6565b6102c3612c53565b73ffffffffffffffffffffffffffffffffffffffff8091169033821461033857817fffffffffffffffffffffffff00000000000000000000000000000000000000006000541617600055600154167fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae1278600080a3005b60046040517fdad89dca000000000000000000000000000000000000000000000000000000008152fd5b346101445760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101445760ff600b54166104ac576103a760043533612eb0565b600181019081549160ff8360c01c16600281101561047d576001146104535778010000000000000000000000000000000000000000000000007fffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffffff841617905580547f6a0ed88e9cf3cb493ab4028fcb1dc7d18f0130fcdfba096edde0aadbfbf5e99f63ffffffff604051946020865260a01c16938061044e3395600260208401910161265c565b0390a4005b60046040517f6f861db1000000000000000000000000000000000000000000000000000000008152fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b60046040517f78a4e7d9000000000000000000000000000000000000000000000000000000008152fd5b34610144576104e43661237e565b916104ed612c53565b60ff600b54166104ac5760005b828110610589575060405191806040840160408552526060830191906000905b8082106105515785151560208601527f509460cccbb176edde6cac28895a4415a24961b8f3a0bd2617b9bb7b4e166c9b85850386a1005b90919283359073ffffffffffffffffffffffffffffffffffffffff82168092036101445760019181526020809101940192019061051a565b60019084156105cb576105c373ffffffffffffffffffffffffffffffffffffffff6105bd6105b8848888612af3565b612c32565b1661308b565b505b016104fa565b6105f773ffffffffffffffffffffffffffffffffffffffff6105f16105b8848888612af3565b166132bc565b506105c5565b346101445761061d61060e36612419565b916106176124a0565b50612b14565b6000526004602052604060002073ffffffffffffffffffffffffffffffffffffffff6001820154161561066e5761065661066a91612710565b6040519182916020835260208301906121cc565b0390f35b60046040517f871e01b2000000000000000000000000000000000000000000000000000000008152fd5b346101445760a07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101445760443567ffffffffffffffff8111610144576106e7903690600401612350565b9060643567ffffffffffffffff811161014457610708903690600401612350565b9160843567ffffffffffffffff811161014457610729903690600401612350565b60ff600b94929454166104ac57610741818688612d48565b61074d60043533612eb0565b9163ffffffff600184015460a01c16956107673388612c9e565b8354946024358614610e57576107a26040516107918161078a8160038b0161265c565b038261230f565b61079c368c856128c4565b90612f1f565b6107c46040516107b98161078a8160048c0161265c565b61079c3686886128c4565b6107e66040516107db8161078a8160058d0161265c565b61079c36898d6128c4565b918080610e50575b80610e49575b610e1f57610803602435612e08565b88600052600660205260406000207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff008154169055602435885515610cca575b15610b79575b156108cc575b926108bc7f41161473ce2ed633d9f902aab9702d16a5531da27ec84e1939abeffe54ad7353959361044e936108ae6108a0978d604051998a996024358b5260a060208c0152600260a08c01910161265c565b9189830360408b0152612987565b918683036060880152612987565b9083820360808501523397612987565b6108d96005860154612609565b610b12575b67ffffffffffffffff8411610ae357610907846108fe6005880154612609565b60058801612940565b6000601f85116001146109e3579284926108ae6108bc938a9b9c61098b876108a09b9a61044e9a7f41161473ce2ed633d9f902aab9702d16a5531da27ec84e1939abeffe54ad73539e9f6000926109d8575b50507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8260011b9260031b1c19161790565b60058a01555b8c87806109ae575b50509c9b9a995093505092949550925061084e565b6109b89133612b14565b60005260056020526109d060043560406000206130dd565b508c87610999565b013590508f80610959565b9860058601600052602060002060005b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe087168110610acb5750926108ae6108bc9361044e969388968c7f41161473ce2ed633d9f902aab9702d16a5531da27ec84e1939abeffe54ad73539c9d9e9f897fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe06108a09e9d1610610a93575b505050600187811b0160058a0155610991565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88b60031b161c199101351690558e8d81610a80565b898c0135825560209b8c019b600190920191016109f3565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040516020810190610b5881610b2c60058a0133866129c6565b037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0810183528261230f565b5190206000526005602052610b736004356040600020613383565b506108de565b67ffffffffffffffff8311610ae357610ba283610b996004890154612609565b60048901612940565b600083601f8111600114610c035780610bee92600091610bf8575b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8260011b9260031b1c19161790565b6004870155610848565b90508601358d610bbd565b506004870160005260206000209060005b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe086168110610cb25750847fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0811610610c7a575b5050600183811b016004870155610848565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88660031b161c19908601351690558a80610c68565b9091602060018192858a013581550193019101610c14565b67ffffffffffffffff8b11610ae357610cf38b610cea60038a0154612609565b60038a01612940565b60008b601f8111600114610d535780610d3e92600091610d4857507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8260011b9260031b1c19161790565b6003880155610842565b90508501358e610bbd565b506003880160005260206000209060005b8d7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081168210610e06578091507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0811610610dcd575b905060018092501b016003880155610842565b60f87fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9160031b161c19908501351690558b808c610dba565b5085820135835560019092019160209182019101610d64565b60046040517f6b4a810d000000000000000000000000000000000000000000000000000000008152fd5b50826107f4565b50816107ee565b60046040517f95406722000000000000000000000000000000000000000000000000000000008152fd5b346101445760607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101445761066a610ecb610ebe6123f6565b6044359060243590612b6f565b60405191829182612270565b34610144576020610ef0610eea36612419565b91612b14565b604051908152f35b346101445760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261014457602073ffffffffffffffffffffffffffffffffffffffff60015416604051908152f35b346101445760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261014457610f81612c53565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00600b5416600b557f11a03e25ee25bf1459f9e1cb293ea03707d84917f54a65e32c9a7be2f2edd68a6020604051338152a1005b346101445760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101445760005473ffffffffffffffffffffffffffffffffffffffff808216330361108157600154917fffffffffffffffffffffffff0000000000000000000000000000000000000000903382851617600155166000553391167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0600080a3005b60046040517f02b543c6000000000000000000000000000000000000000000000000000000008152fd5b346101445760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261014457600980546110e781612488565b6110f4604051918261230f565b81815261110082612488565b916020937fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe060208401940136853760005b82811061118457505050906040519283926020840190602085525180915260408401929160005b82811061116757505050500390f35b835163ffffffff1685528695509381019392810192600101611158565b6001908260005263ffffffff817f6e1540171b6c0c960b71a7020d9f60077f6af931a8bbf590da0223dacf75c7af0154166111bf82876125ba565b5201611131565b34610144576111d43661237e565b916111dd612c53565b60ff600b54166104ac5760005b828110611269575060405191806040840160408552526060830191906000905b8082106112415785151560208601527fcab63bf31d1e656baa23cebef64e12033ea0ffbd44b1278c3747beec2d2f618c85850386a1005b90919283359063ffffffff82168092036101445760019181526020809101940192019061120a565b600190841561129b5761129363ffffffff61128d611288848888612af3565b612b03565b16612fd2565b505b016111ea565b6112b763ffffffff6112b1611288848888612af3565b16613169565b50611295565b346101445760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101445760ff600b54166104ac5761130260043533612eb0565b600181019081549163ffffffff8360a01c169260ff8160c01c16600281101561047d5715610453577fffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffffff906113563386612c9e565b16905580547f17b2d730bb5e064df3fbc6165c8aceb3b0d62c524c196c0bc1012209280bc9a6604051602081528061044e3395600260208401910161265c565b34610144576020807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610144576004359060ff600b54166104ac576113de8233612eb0565b916113f6336000526008602052604060002054151590565b156115425782600493546000526006835260406000207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0081541690553360005260028352611448826040600020613383565b50600181019063ffffffff80835460a01c166000526003855261146f846040600020613383565b506005820161147e8154612609565b61150e575b508154925460a01c16917f76ee2dfcae10cb8522e62e713e62660e09ecfaab08db15d9404de19141322571604051868152806114c6339560028a8401910161265c565b0390a46000525261150c6005604060002060008155600060018201556114ee60028201612aaa565b6114fa60038201612aaa565b61150660048201612aaa565b01612aaa565b005b60405161152381610b2c8982019433866129c6565b5190206000526005855261153b846040600020613383565b5086611483565b60246040517f85982a00000000000000000000000000000000000000000000000000000000008152336004820152fd5b346101445760e07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101445760043567ffffffffffffffff8111610144576115c1903690600401612350565b6044359163ffffffff8316830361014457600260643510156101445760843567ffffffffffffffff8111610144576115fd903690600401612350565b91909260a43567ffffffffffffffff811161014457611620903690600401612350565b60c43567ffffffffffffffff811161014457611640903690600401612350565b96909560ff600b54166104ac57611657338a612c9e565b60408511611e7c5761166a888483612d48565b611675858733612b14565b80600052600460205273ffffffffffffffffffffffffffffffffffffffff60016040600020015416611e52576116ac602435612e08565b604051906116b9826122f2565b602435825233602083015263ffffffff8b1660408301526116df606435606084016125fd565b6116ea36888a6128c4565b60808301526116fa3684866128c4565b60a083015261170a3686886128c4565b60c083015261171a368b8b6128c4565b60e0830152806000526004602052604060002091805183556001830173ffffffffffffffffffffffffffffffffffffffff60208301511681549077ffffffff0000000000000000000000000000000000000000604085015160a01b16906060850151600281101561047d5778ff0000000000000000000000000000000000000000000000007fffffffffffffff000000000000000000000000000000000000000000000000009160c01b1693161717179055608081015180519067ffffffffffffffff8211610ae3576117fd826117f46002880154612609565b60028801612940565b602090601f8311600114611d865761184a929160009183611caf5750507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8260011b9260031b1c19161790565b60028401555b60a081015180519067ffffffffffffffff8211610ae357611881826118786003880154612609565b60038801612940565b602090601f8311600114611cba576118ce929160009183611caf5750507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8260011b9260031b1c19161790565b60038401555b60c081015180519067ffffffffffffffff8211610ae357611905826118fc6004880154612609565b60048801612940565b602090601f8311600114611be25791806119569260e09594600092611abd5750507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8260011b9260031b1c19161790565b60048501555b015180519267ffffffffffffffff8411610ae357838d9261198e8e966119856005860154612609565b60058601612940565b602090601f8311600114611ac8579463ffffffff6108ae95819a957fc4399022965bad9b2b468bbd8c758a7e80cdde36ff3088ddbb7f93bdfb5623cb9f9e9d9994611a1a8761044e9f9b98600593611a7e9f9a600092611abd5750507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8260011b9260031b1c19161790565b9101555b336000526002602052611a358360406000206130dd565b50166000526003602052611a4d8160406000206130dd565b508d82611a94575b5050506108a06040519a8b9a611a6d8c606435612161565b60a060208d015260a08c0191612987565b9783890360808501521696339660243596612987565b611ab492611aa29133612b14565b600052600560205260406000206130dd565b508c8f8d611a55565b015190503880610959565b906005840160005260206000209160005b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe085168110611bb857506108ae9563ffffffff9a957fc4399022965bad9b2b468bbd8c758a7e80cdde36ff3088ddbb7f93bdfb5623cb9f9e9d999460018761044e9f9b96928f9693611a7e9f9a94837fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe06005971610611b81575b505050811b01910155611a1e565b01517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88460031b161c19169055388080611b73565b939550918194969750600160209291839285015181550194019201918f9492918f97969492611ad9565b906004860160005260206000209160005b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe085168110611c975750918391600193837fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe060e098971610611c60575b505050811b01600485015561195c565b01517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88460031b161c191690558f8080611c50565b91926020600181928685015181550194019201611bf3565b015190508f80610959565b9190600386016000526020600020906000935b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe084168510611d6b5760019450837fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0811610611d34575b505050811b0160038401556118d4565b01517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88460031b161c191690558e8080611d24565b81810151835560209485019460019093019290910190611ccd565b9190600286016000526020600020906000935b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe084168510611e375760019450837fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0811610611e00575b505050811b016002840155611850565b01517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88460031b161c191690558e8080611df0565b81810151835560209485019460019093019290910190611d99565b60046040517fa0677dd0000000000000000000000000000000000000000000000000000000008152fd5b604485604051907f36a7c503000000000000000000000000000000000000000000000000000000008252600482015260406024820152fd5b346101445760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261014457611eeb612c53565b60017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00600b541617600b557f2789711f6fd67d131ad68378617b5d1d21a2c92b34d7c3745d70b3957c08096c6020604051338152a1005b34610144576020807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101445760043567ffffffffffffffff811161014457611f92903690600401612350565b60ff600b54166104ac57611fa69133612b14565b90816000526005602052604060002091825491821561066e5760005b838110611fcb57005b80611fd860019287612fba565b90549060031b1c60005260048352604060002063ffffffff8382015460a01c16600052600a8452604060002054151580612062575b612019575b5001611fc2565b7f95d94f817db4971aa99ba35d0fe019bd8cc39866fbe02b6d47b5f0f3727fb673604051868152604086820152806120593394600260408401910161265c565b0390a286612012565b5061207a336000526008602052604060002054151590565b61200d565b346101445760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261014457604051604081019080821067ffffffffffffffff831117610ae35761066a91604052601a81527f576f726b666c6f77526567697374727920312e302e302d646576000000000000602082015260405191829160208352602083019061216e565b346101445760607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101445760043563ffffffff8116810361014457610ecb61066a9160443590602435906127cf565b90600282101561047d5752565b919082519283825260005b8481106121b85750507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8460006020809697860101520116010190565b602081830181015184830182015201612179565b61226d9160e061225c61224a6122386101008651865273ffffffffffffffffffffffffffffffffffffffff602088015116602087015263ffffffff604088015116604087015261222460608801516060880190612161565b60808701519080608088015286019061216e565b60a086015185820360a087015261216e565b60c085015184820360c086015261216e565b9201519060e081840391015261216e565b90565b6020808201906020835283518092526040830192602060408460051b8301019501936000915b8483106122a65750505050505090565b90919293949584806122e2837fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc086600196030187528a516121cc565b9801930193019194939290612296565b610100810190811067ffffffffffffffff821117610ae357604052565b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff821117610ae357604052565b9181601f840112156101445782359167ffffffffffffffff8311610144576020838186019501011161014457565b9060407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc8301126101445760043567ffffffffffffffff9283821161014457806023830112156101445781600401359384116101445760248460051b8301011161014457602401919060243580151581036101445790565b6004359073ffffffffffffffffffffffffffffffffffffffff8216820361014457565b9060407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc8301126101445760043573ffffffffffffffffffffffffffffffffffffffff8116810361014457916024359067ffffffffffffffff82116101445761248491600401612350565b9091565b67ffffffffffffffff8111610ae35760051b60200190565b604051906124ad826122f2565b606060e0836000815260006020820152600060408201526000838201528260808201528260a08201528260c08201520152565b6040516020810181811067ffffffffffffffff821117610ae3576040526000815290565b9061250e82612488565b61251b604051918261230f565b8281527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe06125498294612488565b019060005b82811061255a57505050565b6020906125656124a0565b8282850101520161254e565b9190820180921161257e57565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b9190820391821161257e57565b80518210156125ce5760209160051b010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600282101561047d5752565b90600182811c92168015612652575b602083101461262357565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b91607f1691612618565b80546000939261266b82612609565b918282526020936001916001811690816000146126d35750600114612692575b5050505050565b90939495506000929192528360002092846000945b8386106126bf5750505050010190388080808061268b565b8054858701830152940193859082016126a7565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00168685015250505090151560051b01019150388080808061268b565b90600560e06040936127cb855191612727836122f2565b6127c483978254855261277160ff600185015473ffffffffffffffffffffffffffffffffffffffff8116602089015263ffffffff8160a01c168489015260c01c16606087016125fd565b80516127848161078a816002880161265c565b6080860152805161279c8161078a816003880161265c565b60a086015280516127b48161078a816004880161265c565b60c086015251809681930161265c565b038461230f565b0152565b63ffffffff1691600083815260036020906003602052604093604084205490818710156128b4576128239181606489931180156128ac575b6128a4575b816128178285612571565b111561289457506125ad565b9461282d86612504565b96845b87811061284257505050505050505090565b60019082875284865261286188882061285b8387612571565b90612fba565b905490861b1c875260048652612878888820612710565b612882828c6125ba565b5261288d818b6125ba565b5001612830565b61289f915082612571565b6125ad565b50606461280c565b508015612807565b505050505050505061226d6124e0565b92919267ffffffffffffffff8211610ae3576040519161290c60207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116018461230f565b829481845281830111610144578281602093846000960137010152565b818110612934575050565b60008155600101612929565b9190601f811161294f57505050565b61297b926000526020600020906020601f840160051c8301931061297d575b601f0160051c0190612929565b565b909150819061296e565b601f82602094937fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0938186528686013760008582860101520116010190565b91907fffffffffffffffffffffffffffffffffffffffff0000000000000000000000009060601b168252601490600092815492612a0284612609565b92600194600181169081600014612a695750600114612a24575b505050505090565b9091929395945060005260209460206000206000905b858210612a565750505050601492935001013880808080612a1c565b8054858301850152908701908201612a3a565b92505050601494507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0091935016838301528015150201013880808080612a1c565b612ab48154612609565b9081612abe575050565b81601f60009311600114612ad0575055565b908083918252612aef601f60208420940160051c840160018501612929565b5555565b91908110156125ce5760051b0190565b3563ffffffff811681036101445790565b91906034612b6991836040519485927fffffffffffffffffffffffffffffffffffffffff000000000000000000000000602085019860601b16885284840137810160008382015203601481018452018261230f565b51902090565b73ffffffffffffffffffffffffffffffffffffffff169160008381526002926020906002602052604093604084205490818310156128b457612bc69181606485931180156128ac576128a457816128178285612571565b94612bd086612504565b96845b878110612be557505050505050505090565b600190828752838652612bfe88882061285b8388612571565b90549060031b1c875260048652612c16888820612710565b612c20828c6125ba565b52612c2b818b6125ba565b5001612bd3565b3573ffffffffffffffffffffffffffffffffffffffff811681036101445790565b73ffffffffffffffffffffffffffffffffffffffff600154163303612c7457565b60046040517f2b5c74de000000000000000000000000000000000000000000000000000000008152fd5b63ffffffff1680600052600a60205260406000205415612d17575073ffffffffffffffffffffffffffffffffffffffff1680600052600860205260406000205415612ce65750565b602490604051907f85982a000000000000000000000000000000000000000000000000000000000082526004820152fd5b602490604051907f8fe6d7e10000000000000000000000000000000000000000000000000000000082526004820152fd5b9060c891828111612dd25750818111612d9d5750808211612d67575050565b60449250604051917ecd56a800000000000000000000000000000000000000000000000000000000835260048301526024820152fd5b604491604051917ecd56a800000000000000000000000000000000000000000000000000000000835260048301526024820152fd5b60449083604051917ecd56a800000000000000000000000000000000000000000000000000000000835260048301526024820152fd5b8015612e865780600052600660205260ff60406000205416612e5c576000526006602052604060002060017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00825416179055565b60046040517f4cb050e4000000000000000000000000000000000000000000000000000000008152fd5b60046040517f7dc2f4e1000000000000000000000000000000000000000000000000000000008152fd5b90600052600460205260406000209073ffffffffffffffffffffffffffffffffffffffff8060018401541691821561066e5716809103612eee575090565b602490604051907f31ee6dc70000000000000000000000000000000000000000000000000000000082526004820152fd5b9081518151908181149384612f36575b5050505090565b6020929394508201209201201438808080612f2f565b6009548110156125ce5760096000527f6e1540171b6c0c960b71a7020d9f60077f6af931a8bbf590da0223dacf75c7af0190600090565b6007548110156125ce5760076000527fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c6880190600090565b80548210156125ce5760005260206000200190600090565b6000818152600a6020526040812054613086576009546801000000000000000081101561305957908261304561301084600160409601600955612f4c565b81939154907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9060031b92831b921b19161790565b9055600954928152600a6020522055600190565b6024827f4e487b710000000000000000000000000000000000000000000000000000000081526041600452fd5b905090565b60008181526008602052604081205461308657600754680100000000000000008110156130595790826130c961301084600160409601600755612f83565b905560075492815260086020522055600190565b9190600183016000908282528060205260408220541560001461316357845494680100000000000000008610156131365783613126613010886001604098999a01855584612fba565b9055549382526020522055600190565b6024837f4e487b710000000000000000000000000000000000000000000000000000000081526041600452fd5b50925050565b6000818152600a602052604081205490919080156132b7577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9081810181811161328a576009549083820191821161325d57818103613229575b50505060095480156131fc578101906131db82612f4c565b909182549160031b1b191690556009558152600a6020526040812055600190565b6024847f4e487b710000000000000000000000000000000000000000000000000000000081526031600452fd5b61324761323861301093612f4c565b90549060031b1c928392612f4c565b90558452600a60205260408420553880806131c3565b6024867f4e487b710000000000000000000000000000000000000000000000000000000081526011600452fd5b6024857f4e487b710000000000000000000000000000000000000000000000000000000081526011600452fd5b505090565b60008181526008602052604081205490919080156132b7577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9081810181811161328a576007549083820191821161325d5781810361334f575b50505060075480156131fc5781019061332e82612f83565b909182549160031b1b19169055600755815260086020526040812055600190565b61336d61335e61301093612f83565b90549060031b1c928392612f83565b9055845260086020526040842055388080613316565b90600182019060009281845282602052604084205490811515600014612f2f577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff918281018181116134a85782549084820191821161347b57818103613446575b50505080548015613419578201916133fc8383612fba565b909182549160031b1b191690555582526020526040812055600190565b6024867f4e487b710000000000000000000000000000000000000000000000000000000081526031600452fd5b6134666134566130109386612fba565b90549060031b1c92839286612fba565b905586528460205260408620553880806133e4565b6024887f4e487b710000000000000000000000000000000000000000000000000000000081526011600452fd5b6024877f4e487b710000000000000000000000000000000000000000000000000000000081526011600452fdfea164736f6c6343000818000a", + ABI: "[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"AddressNotAuthorized\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"CallerIsNotWorkflowOwner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CannotTransferToSelf\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"donID\",\"type\":\"uint32\"}],\"name\":\"DONNotAllowed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidWorkflowID\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MustBeProposedOwner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByOwner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OwnerCannotBeZero\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RegistryLocked\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"providedLength\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"maxAllowedLength\",\"type\":\"uint8\"}],\"name\":\"URLTooLong\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"WorkflowAlreadyInDesiredStatus\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"WorkflowAlreadyRegistered\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"WorkflowContentNotUpdated\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"WorkflowDoesNotExist\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"WorkflowIDAlreadyExists\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"WorkflowIDNotUpdated\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"providedLength\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"maxAllowedLength\",\"type\":\"uint8\"}],\"name\":\"WorkflowNameTooLong\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint32[]\",\"name\":\"donIDs\",\"type\":\"uint32[]\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"allowed\",\"type\":\"bool\"}],\"name\":\"AllowedDONsUpdatedV1\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"addresses\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"allowed\",\"type\":\"bool\"}],\"name\":\"AuthorizedAddressesUpdatedV1\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"lockedBy\",\"type\":\"address\"}],\"name\":\"RegistryLockedV1\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"unlockedBy\",\"type\":\"address\"}],\"name\":\"RegistryUnlockedV1\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"workflowID\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"workflowOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"uint32\",\"name\":\"donID\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"workflowName\",\"type\":\"string\"}],\"name\":\"WorkflowActivatedV1\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"workflowID\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"workflowOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"uint32\",\"name\":\"donID\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"workflowName\",\"type\":\"string\"}],\"name\":\"WorkflowDeletedV1\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"secretsURLHash\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"workflowName\",\"type\":\"string\"}],\"name\":\"WorkflowForceUpdateSecretsRequestedV1\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"workflowID\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"workflowOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"uint32\",\"name\":\"donID\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"workflowName\",\"type\":\"string\"}],\"name\":\"WorkflowPausedV1\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"workflowID\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"workflowOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"uint32\",\"name\":\"donID\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"enumWorkflowRegistry.WorkflowStatus\",\"name\":\"status\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"workflowName\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"binaryURL\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"configURL\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"secretsURL\",\"type\":\"string\"}],\"name\":\"WorkflowRegisteredV1\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"oldWorkflowID\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"workflowOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"uint32\",\"name\":\"donID\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"newWorkflowID\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"workflowName\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"binaryURL\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"configURL\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"secretsURL\",\"type\":\"string\"}],\"name\":\"WorkflowUpdatedV1\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"workflowKey\",\"type\":\"bytes32\"}],\"name\":\"activateWorkflow\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"field\",\"type\":\"string\"}],\"name\":\"computeHashKey\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"workflowKey\",\"type\":\"bytes32\"}],\"name\":\"deleteWorkflow\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAllAllowedDONs\",\"outputs\":[{\"internalType\":\"uint32[]\",\"name\":\"allowedDONs\",\"type\":\"uint32[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAllAuthorizedAddresses\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"authorizedAddresses\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"workflowOwner\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"workflowName\",\"type\":\"string\"}],\"name\":\"getWorkflowMetadata\",\"outputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"workflowID\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"donID\",\"type\":\"uint32\"},{\"internalType\":\"enumWorkflowRegistry.WorkflowStatus\",\"name\":\"status\",\"type\":\"uint8\"},{\"internalType\":\"string\",\"name\":\"workflowName\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"binaryURL\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"configURL\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"secretsURL\",\"type\":\"string\"}],\"internalType\":\"structWorkflowRegistry.WorkflowMetadata\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"donID\",\"type\":\"uint32\"},{\"internalType\":\"uint256\",\"name\":\"start\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"limit\",\"type\":\"uint256\"}],\"name\":\"getWorkflowMetadataListByDON\",\"outputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"workflowID\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"donID\",\"type\":\"uint32\"},{\"internalType\":\"enumWorkflowRegistry.WorkflowStatus\",\"name\":\"status\",\"type\":\"uint8\"},{\"internalType\":\"string\",\"name\":\"workflowName\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"binaryURL\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"configURL\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"secretsURL\",\"type\":\"string\"}],\"internalType\":\"structWorkflowRegistry.WorkflowMetadata[]\",\"name\":\"workflowMetadataList\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"workflowOwner\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"start\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"limit\",\"type\":\"uint256\"}],\"name\":\"getWorkflowMetadataListByOwner\",\"outputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"workflowID\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"donID\",\"type\":\"uint32\"},{\"internalType\":\"enumWorkflowRegistry.WorkflowStatus\",\"name\":\"status\",\"type\":\"uint8\"},{\"internalType\":\"string\",\"name\":\"workflowName\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"binaryURL\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"configURL\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"secretsURL\",\"type\":\"string\"}],\"internalType\":\"structWorkflowRegistry.WorkflowMetadata[]\",\"name\":\"workflowMetadataList\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"isRegistryLocked\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"lockRegistry\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"workflowKey\",\"type\":\"bytes32\"}],\"name\":\"pauseWorkflow\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"workflowName\",\"type\":\"string\"},{\"internalType\":\"bytes32\",\"name\":\"workflowID\",\"type\":\"bytes32\"},{\"internalType\":\"uint32\",\"name\":\"donID\",\"type\":\"uint32\"},{\"internalType\":\"enumWorkflowRegistry.WorkflowStatus\",\"name\":\"status\",\"type\":\"uint8\"},{\"internalType\":\"string\",\"name\":\"binaryURL\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"configURL\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"secretsURL\",\"type\":\"string\"}],\"name\":\"registerWorkflow\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"secretsURL\",\"type\":\"string\"}],\"name\":\"requestForceUpdateSecrets\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"unlockRegistry\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32[]\",\"name\":\"donIDs\",\"type\":\"uint32[]\"},{\"internalType\":\"bool\",\"name\":\"allowed\",\"type\":\"bool\"}],\"name\":\"updateAllowedDONs\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"addresses\",\"type\":\"address[]\"},{\"internalType\":\"bool\",\"name\":\"allowed\",\"type\":\"bool\"}],\"name\":\"updateAuthorizedAddresses\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"workflowKey\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"newWorkflowID\",\"type\":\"bytes32\"},{\"internalType\":\"string\",\"name\":\"binaryURL\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"configURL\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"secretsURL\",\"type\":\"string\"}],\"name\":\"updateWorkflow\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", + Bin: "0x6080806040523461004a57331561003b57600180546001600160a01b03191633179055600a805460ff191690556040516133df90816100508239f35b639b15e16f60e01b8152600490fd5b600080fdfe6080604052600436101561001257600080fd5b60003560e01c806308e7f63a14612082578063181f5a7714611ff35780632303348a14611eb65780632b596f6d14611e2c5780633ccd14ff146114f2578063695e1340146113565780636f3517711461127d578063724c13dd146111865780637497066b1461106b57806379ba509714610f955780637ec0846d14610f0e5780638da5cb5b14610ebc5780639f4cb53414610e9b578063b87a019414610e45578063d4b89c7414610698578063db800092146105fd578063e3dce080146104d6578063e690f33214610362578063f2fde38b14610284578063f794bdeb146101495763f99ecb6b1461010357600080fd5b346101445760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261014457602060ff600a54166040519015158152f35b600080fd5b346101445760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101445760068054610185816123fc565b6101926040519182612283565b81815261019e826123fc565b916020937fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe060208401940136853760005b82811061023257505050906040519283926020840190602085525180915260408401929160005b82811061020557505050500390f35b835173ffffffffffffffffffffffffffffffffffffffff16855286955093810193928101926001016101f6565b6001908260005273ffffffffffffffffffffffffffffffffffffffff817ff652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d3f01541661027d828761252e565b52016101cf565b346101445760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610144576102bb61236a565b6102c3612bc7565b73ffffffffffffffffffffffffffffffffffffffff8091169033821461033857817fffffffffffffffffffffffff00000000000000000000000000000000000000006000541617600055600154167fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae1278600080a3005b60046040517fdad89dca000000000000000000000000000000000000000000000000000000008152fd5b346101445760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101445760ff600a54166104ac576103a760043533612dad565b600181019081549160ff8360c01c16600281101561047d576001146104535778010000000000000000000000000000000000000000000000007fffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffffff841617905580547f6a0ed88e9cf3cb493ab4028fcb1dc7d18f0130fcdfba096edde0aadbfbf5e99f63ffffffff604051946020865260a01c16938061044e339560026020840191016125d0565b0390a4005b60046040517f6f861db1000000000000000000000000000000000000000000000000000000008152fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b60046040517f78a4e7d9000000000000000000000000000000000000000000000000000000008152fd5b34610144576104e4366122f2565b916104ed612bc7565b60ff600a54166104ac5760005b828110610589575060405191806040840160408552526060830191906000905b8082106105515785151560208601527f509460cccbb176edde6cac28895a4415a24961b8f3a0bd2617b9bb7b4e166c9b85850386a1005b90919283359073ffffffffffffffffffffffffffffffffffffffff82168092036101445760019181526020809101940192019061051a565b60019084156105cb576105c373ffffffffffffffffffffffffffffffffffffffff6105bd6105b8848888612a67565b612ba6565b16612f88565b505b016104fa565b6105f773ffffffffffffffffffffffffffffffffffffffff6105f16105b8848888612a67565b166131b9565b506105c5565b346101445761061d61060e3661238d565b91610617612414565b50612a88565b6000526004602052604060002073ffffffffffffffffffffffffffffffffffffffff6001820154161561066e5761065661066a91612684565b604051918291602083526020830190612140565b0390f35b60046040517f871e01b2000000000000000000000000000000000000000000000000000000008152fd5b346101445760a07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101445760443567ffffffffffffffff8111610144576106e79036906004016122c4565b9060643567ffffffffffffffff8111610144576107089036906004016122c4565b9160843567ffffffffffffffff8111610144576107299036906004016122c4565b60ff600a94929454166104ac57610744818688602435612cbc565b61075060043533612dad565b9163ffffffff600184015460a01c169561076a3388612c12565b8354946024358614610e1b576107a56040516107948161078d8160038b016125d0565b0382612283565b61079f368c85612838565b90612e1c565b6107c76040516107bc8161078d8160048c016125d0565b61079f368688612838565b6107e96040516107de8161078d8160058d016125d0565b61079f36898d612838565b918080610e14575b80610e0d575b610de357602435885515610c8e575b15610b3d575b15610890575b926108807f41161473ce2ed633d9f902aab9702d16a5531da27ec84e1939abeffe54ad7353959361044e93610872610864978d604051998a996024358b5260a060208c0152600260a08c0191016125d0565b9189830360408b01526128fb565b9186830360608801526128fb565b90838203608085015233976128fb565b61089d600586015461257d565b610ad6575b67ffffffffffffffff8411610aa7576108cb846108c2600588015461257d565b600588016128b4565b6000601f85116001146109a757928492610872610880938a9b9c61094f876108649b9a61044e9a7f41161473ce2ed633d9f902aab9702d16a5531da27ec84e1939abeffe54ad73539e9f60009261099c575b50507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8260011b9260031b1c19161790565b60058a01555b8c8780610972575b50509c9b9a9950935050929495509250610812565b61097c9133612a88565b60005260056020526109946004356040600020612fda565b508c8761095d565b013590508f8061091d565b9860058601600052602060002060005b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe087168110610a8f5750926108726108809361044e969388968c7f41161473ce2ed633d9f902aab9702d16a5531da27ec84e1939abeffe54ad73539c9d9e9f897fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe06108649e9d1610610a57575b505050600187811b0160058a0155610955565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88b60031b161c199101351690558e8d81610a44565b898c0135825560209b8c019b600190920191016109b7565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040516020810190610b1c81610af060058a01338661293a565b037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08101835282612283565b5190206000526005602052610b376004356040600020613280565b506108a2565b67ffffffffffffffff8311610aa757610b6683610b5d600489015461257d565b600489016128b4565b600083601f8111600114610bc75780610bb292600091610bbc575b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8260011b9260031b1c19161790565b600487015561080c565b90508601358d610b81565b506004870160005260206000209060005b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe086168110610c765750847fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0811610610c3e575b5050600183811b01600487015561080c565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88660031b161c19908601351690558a80610c2c565b9091602060018192858a013581550193019101610bd8565b67ffffffffffffffff8b11610aa757610cb78b610cae60038a015461257d565b60038a016128b4565b60008b601f8111600114610d175780610d0292600091610d0c57507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8260011b9260031b1c19161790565b6003880155610806565b90508501358e610b81565b506003880160005260206000209060005b8d7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081168210610dca578091507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0811610610d91575b905060018092501b016003880155610806565b60f87fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9160031b161c19908501351690558b808c610d7e565b5085820135835560019092019160209182019101610d28565b60046040517f6b4a810d000000000000000000000000000000000000000000000000000000008152fd5b50826107f7565b50816107f1565b60046040517f95406722000000000000000000000000000000000000000000000000000000008152fd5b346101445760607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101445761066a610e8f610e8261236a565b6044359060243590612ae3565b604051918291826121e4565b34610144576020610eb4610eae3661238d565b91612a88565b604051908152f35b346101445760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261014457602073ffffffffffffffffffffffffffffffffffffffff60015416604051908152f35b346101445760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261014457610f45612bc7565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00600a5416600a55337f11a03e25ee25bf1459f9e1cb293ea03707d84917f54a65e32c9a7be2f2edd68a600080a2005b346101445760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101445760005473ffffffffffffffffffffffffffffffffffffffff808216330361104157600154917fffffffffffffffffffffffff0000000000000000000000000000000000000000903382851617600155166000553391167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0600080a3005b60046040517f02b543c6000000000000000000000000000000000000000000000000000000008152fd5b346101445760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261014457600880546110a7816123fc565b6110b46040519182612283565b8181526110c0826123fc565b916020937fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe060208401940136853760005b82811061114457505050906040519283926020840190602085525180915260408401929160005b82811061112757505050500390f35b835163ffffffff1685528695509381019392810192600101611118565b6001908260005263ffffffff817ff3f7a9fe364faab93b216da50a3214154f22a0a2b415b23a84c8169e8b636ee301541661117f828761252e565b52016110f1565b3461014457611194366122f2565b9161119d612bc7565b60ff600a54166104ac5760005b828110611229575060405191806040840160408552526060830191906000905b8082106112015785151560208601527fcab63bf31d1e656baa23cebef64e12033ea0ffbd44b1278c3747beec2d2f618c85850386a1005b90919283359063ffffffff8216809203610144576001918152602080910194019201906111ca565b600190841561125b5761125363ffffffff61124d611248848888612a67565b612a77565b16612ecf565b505b016111aa565b61127763ffffffff611271611248848888612a67565b16613066565b50611255565b346101445760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101445760ff600a54166104ac576112c260043533612dad565b600181019081549163ffffffff8360a01c169260ff8160c01c16600281101561047d5715610453577fffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffffff906113163386612c12565b16905580547f17b2d730bb5e064df3fbc6165c8aceb3b0d62c524c196c0bc1012209280bc9a6604051602081528061044e339560026020840191016125d0565b34610144576020807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610144576004359060ff600a54166104ac5761139e8233612dad565b63ffffffff600182015460a01c16926113c4336000526007602052604060002054151590565b156114c25733600052600283526113df816040600020613280565b5083600052600383526113f6816040600020613280565b5060058201611405815461257d565b61148e575b506000526004825261145160056040600020600081556000600182015561143360028201612a1e565b61143f60038201612a1e565b61144b60048201612a1e565b01612a1e565b7f76ee2dfcae10cb8522e62e713e62660e09ecfaab08db15d9404de1914132257161044e82549260405191829186835260023397840191016125d0565b6040516114a381610af087820194338661293a565b519020600052600583526114bb816040600020613280565b508461140a565b60246040517f85982a00000000000000000000000000000000000000000000000000000000008152336004820152fd5b346101445760e07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101445760043567ffffffffffffffff8111610144576115419036906004016122c4565b6044359163ffffffff8316830361014457600260643510156101445760843567ffffffffffffffff81116101445761157d9036906004016122c4565b91909260a43567ffffffffffffffff8111610144576115a09036906004016122c4565b60c43567ffffffffffffffff8111610144576115c09036906004016122c4565b96909560ff600a54166104ac576115d7338a612c12565b60408511611df4576115ed888483602435612cbc565b6115f8858733612a88565b80600052600460205273ffffffffffffffffffffffffffffffffffffffff60016040600020015416611dca576040519061163182612266565b602435825233602083015263ffffffff8b16604083015261165760643560608401612571565b61166236888a612838565b6080830152611672368486612838565b60a0830152611682368688612838565b60c0830152611692368b8b612838565b60e0830152806000526004602052604060002091805183556001830173ffffffffffffffffffffffffffffffffffffffff60208301511681549077ffffffff0000000000000000000000000000000000000000604085015160a01b16906060850151600281101561047d5778ff0000000000000000000000000000000000000000000000007fffffffffffffff000000000000000000000000000000000000000000000000009160c01b1693161717179055608081015180519067ffffffffffffffff8211610aa7576117758261176c600288015461257d565b600288016128b4565b602090601f8311600114611cfe576117c2929160009183611c275750507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8260011b9260031b1c19161790565b60028401555b60a081015180519067ffffffffffffffff8211610aa7576117f9826117f0600388015461257d565b600388016128b4565b602090601f8311600114611c3257611846929160009183611c275750507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8260011b9260031b1c19161790565b60038401555b60c081015180519067ffffffffffffffff8211610aa75761187d82611874600488015461257d565b600488016128b4565b602090601f8311600114611b5a5791806118ce9260e09594600092611a355750507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8260011b9260031b1c19161790565b60048501555b015180519267ffffffffffffffff8411610aa757838d926119068e966118fd600586015461257d565b600586016128b4565b602090601f8311600114611a40579463ffffffff61087295819a957fc4399022965bad9b2b468bbd8c758a7e80cdde36ff3088ddbb7f93bdfb5623cb9f9e9d99946119928761044e9f9b986005936119f69f9a600092611a355750507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8260011b9260031b1c19161790565b9101555b3360005260026020526119ad836040600020612fda565b501660005260036020526119c5816040600020612fda565b508d82611a0c575b5050506108646040519a8b9a6119e58c6064356120d5565b60a060208d015260a08c01916128fb565b97838903608085015216963396602435966128fb565b611a2c92611a1a9133612a88565b60005260056020526040600020612fda565b508c8f8d6119cd565b01519050388061091d565b906005840160005260206000209160005b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe085168110611b3057506108729563ffffffff9a957fc4399022965bad9b2b468bbd8c758a7e80cdde36ff3088ddbb7f93bdfb5623cb9f9e9d999460018761044e9f9b96928f96936119f69f9a94837fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe06005971610611af9575b505050811b01910155611996565b01517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88460031b161c19169055388080611aeb565b939550918194969750600160209291839285015181550194019201918f9492918f97969492611a51565b906004860160005260206000209160005b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe085168110611c0f5750918391600193837fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe060e098971610611bd8575b505050811b0160048501556118d4565b01517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88460031b161c191690558f8080611bc8565b91926020600181928685015181550194019201611b6b565b015190508f8061091d565b9190600386016000526020600020906000935b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe084168510611ce35760019450837fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0811610611cac575b505050811b01600384015561184c565b01517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88460031b161c191690558e8080611c9c565b81810151835560209485019460019093019290910190611c45565b9190600286016000526020600020906000935b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe084168510611daf5760019450837fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0811610611d78575b505050811b0160028401556117c8565b01517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88460031b161c191690558e8080611d68565b81810151835560209485019460019093019290910190611d11565b60046040517fa0677dd0000000000000000000000000000000000000000000000000000000008152fd5b604485604051907f36a7c503000000000000000000000000000000000000000000000000000000008252600482015260406024820152fd5b346101445760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261014457611e63612bc7565b60017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00600a541617600a55337f2789711f6fd67d131ad68378617b5d1d21a2c92b34d7c3745d70b3957c08096c600080a2005b34610144576020807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101445760043567ffffffffffffffff811161014457611f069036906004016122c4565b60ff600a54166104ac57611f1a9133612a88565b90816000526005602052604060002091825491821561066e5760005b838110611f3f57005b80611f4c60019287612eb7565b90549060031b1c60005260048352604060002063ffffffff8382015460a01c1660005260098452604060002054151580611fd6575b611f8d575b5001611f36565b7f95d94f817db4971aa99ba35d0fe019bd8cc39866fbe02b6d47b5f0f3727fb67360405186815260408682015280611fcd339460026040840191016125d0565b0390a286611f86565b50611fee336000526007602052604060002054151590565b611f81565b346101445760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261014457604051604081019080821067ffffffffffffffff831117610aa75761066a91604052601a81527f576f726b666c6f77526567697374727920312e302e302d64657600000000000060208201526040519182916020835260208301906120e2565b346101445760607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101445760043563ffffffff8116810361014457610e8f61066a916044359060243590612743565b90600282101561047d5752565b919082519283825260005b84811061212c5750507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8460006020809697860101520116010190565b6020818301810151848301820152016120ed565b6121e19160e06121d06121be6121ac6101008651865273ffffffffffffffffffffffffffffffffffffffff602088015116602087015263ffffffff6040880151166040870152612198606088015160608801906120d5565b6080870151908060808801528601906120e2565b60a086015185820360a08701526120e2565b60c085015184820360c08601526120e2565b9201519060e08184039101526120e2565b90565b6020808201906020835283518092526040830192602060408460051b8301019501936000915b84831061221a5750505050505090565b9091929394958480612256837fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc086600196030187528a51612140565b980193019301919493929061220a565b610100810190811067ffffffffffffffff821117610aa757604052565b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff821117610aa757604052565b9181601f840112156101445782359167ffffffffffffffff8311610144576020838186019501011161014457565b9060407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc8301126101445760043567ffffffffffffffff9283821161014457806023830112156101445781600401359384116101445760248460051b8301011161014457602401919060243580151581036101445790565b6004359073ffffffffffffffffffffffffffffffffffffffff8216820361014457565b9060407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc8301126101445760043573ffffffffffffffffffffffffffffffffffffffff8116810361014457916024359067ffffffffffffffff8211610144576123f8916004016122c4565b9091565b67ffffffffffffffff8111610aa75760051b60200190565b6040519061242182612266565b606060e0836000815260006020820152600060408201526000838201528260808201528260a08201528260c08201520152565b6040516020810181811067ffffffffffffffff821117610aa7576040526000815290565b90612482826123fc565b61248f6040519182612283565b8281527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe06124bd82946123fc565b019060005b8281106124ce57505050565b6020906124d9612414565b828285010152016124c2565b919082018092116124f257565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b919082039182116124f257565b80518210156125425760209160051b010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600282101561047d5752565b90600182811c921680156125c6575b602083101461259757565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b91607f169161258c565b8054600093926125df8261257d565b918282526020936001916001811690816000146126475750600114612606575b5050505050565b90939495506000929192528360002092846000945b838610612633575050505001019038808080806125ff565b80548587018301529401938590820161261b565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00168685015250505090151560051b0101915038808080806125ff565b90600560e060409361273f85519161269b83612266565b6127388397825485526126e560ff600185015473ffffffffffffffffffffffffffffffffffffffff8116602089015263ffffffff8160a01c168489015260c01c1660608701612571565b80516126f88161078d81600288016125d0565b608086015280516127108161078d81600388016125d0565b60a086015280516127288161078d81600488016125d0565b60c08601525180968193016125d0565b0384612283565b0152565b63ffffffff16916000838152600360209060036020526040936040842054908187101561282857612797918160648993118015612820575b612818575b8161278b82856124e5565b11156128085750612521565b946127a186612478565b96845b8781106127b657505050505050505090565b6001908287528486526127d58888206127cf83876124e5565b90612eb7565b905490861b1c8752600486526127ec888820612684565b6127f6828c61252e565b52612801818b61252e565b50016127a4565b6128139150826124e5565b612521565b506064612780565b50801561277b565b50505050505050506121e1612454565b92919267ffffffffffffffff8211610aa7576040519161288060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8401160184612283565b829481845281830111610144578281602093846000960137010152565b8181106128a8575050565b6000815560010161289d565b9190601f81116128c357505050565b6128ef926000526020600020906020601f840160051c830193106128f1575b601f0160051c019061289d565b565b90915081906128e2565b601f82602094937fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0938186528686013760008582860101520116010190565b91907fffffffffffffffffffffffffffffffffffffffff0000000000000000000000009060601b1682526014906000928154926129768461257d565b926001946001811690816000146129dd5750600114612998575b505050505090565b9091929395945060005260209460206000206000905b8582106129ca5750505050601492935001013880808080612990565b80548583018501529087019082016129ae565b92505050601494507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0091935016838301528015150201013880808080612990565b612a28815461257d565b9081612a32575050565b81601f60009311600114612a44575055565b908083918252612a63601f60208420940160051c84016001850161289d565b5555565b91908110156125425760051b0190565b3563ffffffff811681036101445790565b91906034612add91836040519485927fffffffffffffffffffffffffffffffffffffffff000000000000000000000000602085019860601b168852848401378101600083820152036014810184520182612283565b51902090565b73ffffffffffffffffffffffffffffffffffffffff1691600083815260029260209060026020526040936040842054908183101561282857612b3a91816064859311801561282057612818578161278b82856124e5565b94612b4486612478565b96845b878110612b5957505050505050505090565b600190828752838652612b728888206127cf83886124e5565b90549060031b1c875260048652612b8a888820612684565b612b94828c61252e565b52612b9f818b61252e565b5001612b47565b3573ffffffffffffffffffffffffffffffffffffffff811681036101445790565b73ffffffffffffffffffffffffffffffffffffffff600154163303612be857565b60046040517f2b5c74de000000000000000000000000000000000000000000000000000000008152fd5b63ffffffff1680600052600960205260406000205415612c8b575073ffffffffffffffffffffffffffffffffffffffff1680600052600760205260406000205415612c5a5750565b602490604051907f85982a000000000000000000000000000000000000000000000000000000000082526004820152fd5b602490604051907f8fe6d7e10000000000000000000000000000000000000000000000000000000082526004820152fd5b91909115612d835760c891828111612d4d5750818111612d185750808211612ce2575050565b60449250604051917ecd56a800000000000000000000000000000000000000000000000000000000835260048301526024820152fd5b604491604051917ecd56a800000000000000000000000000000000000000000000000000000000835260048301526024820152fd5b60449083604051917ecd56a800000000000000000000000000000000000000000000000000000000835260048301526024820152fd5b60046040517f7dc2f4e1000000000000000000000000000000000000000000000000000000008152fd5b90600052600460205260406000209073ffffffffffffffffffffffffffffffffffffffff8060018401541691821561066e5716809103612deb575090565b602490604051907f31ee6dc70000000000000000000000000000000000000000000000000000000082526004820152fd5b9081518151908181149384612e33575b5050505090565b6020929394508201209201201438808080612e2c565b6008548110156125425760086000527ff3f7a9fe364faab93b216da50a3214154f22a0a2b415b23a84c8169e8b636ee30190600090565b6006548110156125425760066000527ff652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d3f0190600090565b80548210156125425760005260206000200190600090565b600081815260096020526040812054612f835760085468010000000000000000811015612f56579082612f42612f0d84600160409601600855612e49565b81939154907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9060031b92831b921b19161790565b905560085492815260096020522055600190565b6024827f4e487b710000000000000000000000000000000000000000000000000000000081526041600452fd5b905090565b600081815260076020526040812054612f835760065468010000000000000000811015612f56579082612fc6612f0d84600160409601600655612e80565b905560065492815260076020522055600190565b9190600183016000908282528060205260408220541560001461306057845494680100000000000000008610156130335783613023612f0d886001604098999a01855584612eb7565b9055549382526020522055600190565b6024837f4e487b710000000000000000000000000000000000000000000000000000000081526041600452fd5b50925050565b60008181526009602052604081205490919080156131b4577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90818101818111613187576008549083820191821161315a57818103613126575b50505060085480156130f9578101906130d882612e49565b909182549160031b1b19169055600855815260096020526040812055600190565b6024847f4e487b710000000000000000000000000000000000000000000000000000000081526031600452fd5b613144613135612f0d93612e49565b90549060031b1c928392612e49565b90558452600960205260408420553880806130c0565b6024867f4e487b710000000000000000000000000000000000000000000000000000000081526011600452fd5b6024857f4e487b710000000000000000000000000000000000000000000000000000000081526011600452fd5b505090565b60008181526007602052604081205490919080156131b4577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90818101818111613187576006549083820191821161315a5781810361324c575b50505060065480156130f95781019061322b82612e80565b909182549160031b1b19169055600655815260076020526040812055600190565b61326a61325b612f0d93612e80565b90549060031b1c928392612e80565b9055845260076020526040842055388080613213565b90600182019060009281845282602052604084205490811515600014612e2c577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff918281018181116133a55782549084820191821161337857818103613343575b50505080548015613316578201916132f98383612eb7565b909182549160031b1b191690555582526020526040812055600190565b6024867f4e487b710000000000000000000000000000000000000000000000000000000081526031600452fd5b613363613353612f0d9386612eb7565b90549060031b1c92839286612eb7565b905586528460205260408620553880806132e1565b6024887f4e487b710000000000000000000000000000000000000000000000000000000081526011600452fd5b6024877f4e487b710000000000000000000000000000000000000000000000000000000081526011600452fdfea164736f6c6343000818000a", } var WorkflowRegistryABI = WorkflowRegistryMetaData.ABI @@ -1097,18 +1097,28 @@ type WorkflowRegistryRegistryLockedV1 struct { Raw types.Log } -func (_WorkflowRegistry *WorkflowRegistryFilterer) FilterRegistryLockedV1(opts *bind.FilterOpts) (*WorkflowRegistryRegistryLockedV1Iterator, error) { +func (_WorkflowRegistry *WorkflowRegistryFilterer) FilterRegistryLockedV1(opts *bind.FilterOpts, lockedBy []common.Address) (*WorkflowRegistryRegistryLockedV1Iterator, error) { - logs, sub, err := _WorkflowRegistry.contract.FilterLogs(opts, "RegistryLockedV1") + var lockedByRule []interface{} + for _, lockedByItem := range lockedBy { + lockedByRule = append(lockedByRule, lockedByItem) + } + + logs, sub, err := _WorkflowRegistry.contract.FilterLogs(opts, "RegistryLockedV1", lockedByRule) if err != nil { return nil, err } return &WorkflowRegistryRegistryLockedV1Iterator{contract: _WorkflowRegistry.contract, event: "RegistryLockedV1", logs: logs, sub: sub}, nil } -func (_WorkflowRegistry *WorkflowRegistryFilterer) WatchRegistryLockedV1(opts *bind.WatchOpts, sink chan<- *WorkflowRegistryRegistryLockedV1) (event.Subscription, error) { +func (_WorkflowRegistry *WorkflowRegistryFilterer) WatchRegistryLockedV1(opts *bind.WatchOpts, sink chan<- *WorkflowRegistryRegistryLockedV1, lockedBy []common.Address) (event.Subscription, error) { + + var lockedByRule []interface{} + for _, lockedByItem := range lockedBy { + lockedByRule = append(lockedByRule, lockedByItem) + } - logs, sub, err := _WorkflowRegistry.contract.WatchLogs(opts, "RegistryLockedV1") + logs, sub, err := _WorkflowRegistry.contract.WatchLogs(opts, "RegistryLockedV1", lockedByRule) if err != nil { return nil, err } @@ -1214,18 +1224,28 @@ type WorkflowRegistryRegistryUnlockedV1 struct { Raw types.Log } -func (_WorkflowRegistry *WorkflowRegistryFilterer) FilterRegistryUnlockedV1(opts *bind.FilterOpts) (*WorkflowRegistryRegistryUnlockedV1Iterator, error) { +func (_WorkflowRegistry *WorkflowRegistryFilterer) FilterRegistryUnlockedV1(opts *bind.FilterOpts, unlockedBy []common.Address) (*WorkflowRegistryRegistryUnlockedV1Iterator, error) { - logs, sub, err := _WorkflowRegistry.contract.FilterLogs(opts, "RegistryUnlockedV1") + var unlockedByRule []interface{} + for _, unlockedByItem := range unlockedBy { + unlockedByRule = append(unlockedByRule, unlockedByItem) + } + + logs, sub, err := _WorkflowRegistry.contract.FilterLogs(opts, "RegistryUnlockedV1", unlockedByRule) if err != nil { return nil, err } return &WorkflowRegistryRegistryUnlockedV1Iterator{contract: _WorkflowRegistry.contract, event: "RegistryUnlockedV1", logs: logs, sub: sub}, nil } -func (_WorkflowRegistry *WorkflowRegistryFilterer) WatchRegistryUnlockedV1(opts *bind.WatchOpts, sink chan<- *WorkflowRegistryRegistryUnlockedV1) (event.Subscription, error) { +func (_WorkflowRegistry *WorkflowRegistryFilterer) WatchRegistryUnlockedV1(opts *bind.WatchOpts, sink chan<- *WorkflowRegistryRegistryUnlockedV1, unlockedBy []common.Address) (event.Subscription, error) { + + var unlockedByRule []interface{} + for _, unlockedByItem := range unlockedBy { + unlockedByRule = append(unlockedByRule, unlockedByItem) + } - logs, sub, err := _WorkflowRegistry.contract.WatchLogs(opts, "RegistryUnlockedV1") + logs, sub, err := _WorkflowRegistry.contract.WatchLogs(opts, "RegistryUnlockedV1", unlockedByRule) if err != nil { return nil, err } @@ -2284,15 +2304,15 @@ type WorkflowRegistryInterface interface { ParseOwnershipTransferred(log types.Log) (*WorkflowRegistryOwnershipTransferred, error) - FilterRegistryLockedV1(opts *bind.FilterOpts) (*WorkflowRegistryRegistryLockedV1Iterator, error) + FilterRegistryLockedV1(opts *bind.FilterOpts, lockedBy []common.Address) (*WorkflowRegistryRegistryLockedV1Iterator, error) - WatchRegistryLockedV1(opts *bind.WatchOpts, sink chan<- *WorkflowRegistryRegistryLockedV1) (event.Subscription, error) + WatchRegistryLockedV1(opts *bind.WatchOpts, sink chan<- *WorkflowRegistryRegistryLockedV1, lockedBy []common.Address) (event.Subscription, error) ParseRegistryLockedV1(log types.Log) (*WorkflowRegistryRegistryLockedV1, error) - FilterRegistryUnlockedV1(opts *bind.FilterOpts) (*WorkflowRegistryRegistryUnlockedV1Iterator, error) + FilterRegistryUnlockedV1(opts *bind.FilterOpts, unlockedBy []common.Address) (*WorkflowRegistryRegistryUnlockedV1Iterator, error) - WatchRegistryUnlockedV1(opts *bind.WatchOpts, sink chan<- *WorkflowRegistryRegistryUnlockedV1) (event.Subscription, error) + WatchRegistryUnlockedV1(opts *bind.WatchOpts, sink chan<- *WorkflowRegistryRegistryUnlockedV1, unlockedBy []common.Address) (event.Subscription, error) ParseRegistryUnlockedV1(log types.Log) (*WorkflowRegistryRegistryUnlockedV1, error) diff --git a/core/gethwrappers/workflow/generation/generated-wrapper-dependency-versions-do-not-edit.txt b/core/gethwrappers/workflow/generation/generated-wrapper-dependency-versions-do-not-edit.txt index a908ff2e724..b937cc957a6 100644 --- a/core/gethwrappers/workflow/generation/generated-wrapper-dependency-versions-do-not-edit.txt +++ b/core/gethwrappers/workflow/generation/generated-wrapper-dependency-versions-do-not-edit.txt @@ -1,2 +1,2 @@ GETH_VERSION: 1.14.11 -workflow_registry_wrapper: ../../../contracts/solc/v0.8.24/WorkflowRegistry/WorkflowRegistry.abi ../../../contracts/solc/v0.8.24/WorkflowRegistry/WorkflowRegistry.bin bad48df0196c8a170a8e5486d0334183defd60e74bd89d3885989e00d6f13d23 +workflow_registry_wrapper: ../../../contracts/solc/v0.8.24/WorkflowRegistry/WorkflowRegistry.abi ../../../contracts/solc/v0.8.24/WorkflowRegistry/WorkflowRegistry.bin 2f7e6d51370fbb3a6c467515127333b6cb4b998c61f2e0b74d5e07ccb1a8716b diff --git a/core/internal/cltest/cltest.go b/core/internal/cltest/cltest.go index a55c57cc9a2..32c63e7944c 100644 --- a/core/internal/cltest/cltest.go +++ b/core/internal/cltest/cltest.go @@ -29,7 +29,6 @@ import ( "github.com/jmoiron/sqlx" "github.com/manyminds/api2go/jsonapi" "github.com/onsi/gomega" - "github.com/prometheus/client_golang/prometheus" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/mock" "github.com/stretchr/testify/require" @@ -47,7 +46,6 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/loop" "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" "github.com/smartcontractkit/chainlink-common/pkg/utils/mailbox" - "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" "github.com/smartcontractkit/chainlink/v2/common/client" commonmocks "github.com/smartcontractkit/chainlink/v2/common/types/mocks" @@ -408,7 +406,6 @@ func NewApplicationWithConfig(t testing.TB, cfg chainlink.GeneralConfig, flagsAn Logger: lggr, LoopRegistry: loopRegistry, GRPCOpts: loop.GRPCOpts{}, - Registerer: prometheus.NewRegistry(), // Don't use global registry here since otherwise multiple apps can create name conflicts. Could also potentially give a mock registry to test prometheus. MercuryPool: mercuryPool, CapabilitiesRegistry: capabilitiesRegistry, HTTPClient: c, @@ -421,8 +418,8 @@ func NewApplicationWithConfig(t testing.TB, cfg chainlink.GeneralConfig, flagsAn MailMon: mailMon, DS: ds, }, - CSAETHKeystore: keyStore, - MercuryConfig: cfg.Mercury(), + CSAETHKeystore: keyStore, + MercuryTransmitter: cfg.Mercury().Transmitter(), } if cfg.EVMEnabled() { @@ -453,7 +450,6 @@ func NewApplicationWithConfig(t testing.TB, cfg chainlink.GeneralConfig, flagsAn solanaCfg := chainlink.SolanaFactoryConfig{ Keystore: keyStore.Solana(), TOMLConfigs: cfg.SolanaConfigs(), - DS: ds, } initOps = append(initOps, chainlink.InitSolana(ctx, relayerFactory, solanaCfg)) } @@ -532,7 +528,7 @@ func NewEthMocks(t testing.TB) *evmclimocks.Client { } func NewEthMocksWithStartupAssertions(t testing.TB) *evmclimocks.Client { - tests.SkipShort(t, "long test") + testutils.SkipShort(t, "long test") c := NewEthMocks(t) chHead := make(<-chan *evmtypes.Head) c.On("Dial", mock.Anything).Maybe().Return(nil) @@ -555,7 +551,7 @@ func NewEthMocksWithStartupAssertions(t testing.TB) *evmclimocks.Client { // NewEthMocksWithTransactionsOnBlocksAssertions sets an Eth mock with transactions on blocks func NewEthMocksWithTransactionsOnBlocksAssertions(t testing.TB) *evmclimocks.Client { - tests.SkipShort(t, "long test") + testutils.SkipShort(t, "long test") c := NewEthMocks(t) chHead := make(<-chan *evmtypes.Head) c.On("Dial", mock.Anything).Maybe().Return(nil) diff --git a/core/internal/cltest/mocks.go b/core/internal/cltest/mocks.go index 17c79f00831..b8bb4657056 100644 --- a/core/internal/cltest/mocks.go +++ b/core/internal/cltest/mocks.go @@ -11,7 +11,6 @@ import ( "time" "github.com/jmoiron/sqlx" - "github.com/prometheus/client_golang/prometheus" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" @@ -88,7 +87,7 @@ type InstanceAppFactoryWithKeystoreMock struct { } // NewApplication creates a new application with specified config and calls the authenticate function of the keystore -func (f InstanceAppFactoryWithKeystoreMock) NewApplication(ctx context.Context, cfg chainlink.GeneralConfig, lggr logger.Logger, registerer prometheus.Registerer, db *sqlx.DB, ks cmd.TerminalKeyStoreAuthenticator) (chainlink.Application, error) { +func (f InstanceAppFactoryWithKeystoreMock) NewApplication(ctx context.Context, cfg chainlink.GeneralConfig, lggr logger.Logger, db *sqlx.DB, ks cmd.TerminalKeyStoreAuthenticator) (chainlink.Application, error) { keyStore := f.App.GetKeyStore() err := ks.Authenticate(ctx, keyStore, cfg.Password()) if err != nil { @@ -103,7 +102,7 @@ type InstanceAppFactory struct { } // NewApplication creates a new application with specified config -func (f InstanceAppFactory) NewApplication(context.Context, chainlink.GeneralConfig, logger.Logger, prometheus.Registerer, *sqlx.DB, cmd.TerminalKeyStoreAuthenticator) (chainlink.Application, error) { +func (f InstanceAppFactory) NewApplication(context.Context, chainlink.GeneralConfig, logger.Logger, *sqlx.DB, cmd.TerminalKeyStoreAuthenticator) (chainlink.Application, error) { return f.App, nil } @@ -111,7 +110,7 @@ type seededAppFactory struct { Application chainlink.Application } -func (s seededAppFactory) NewApplication(context.Context, chainlink.GeneralConfig, logger.Logger, prometheus.Registerer, *sqlx.DB, cmd.TerminalKeyStoreAuthenticator) (chainlink.Application, error) { +func (s seededAppFactory) NewApplication(context.Context, chainlink.GeneralConfig, logger.Logger, *sqlx.DB, cmd.TerminalKeyStoreAuthenticator) (chainlink.Application, error) { return noopStopApplication{s.Application}, nil } diff --git a/core/internal/features/features_test.go b/core/internal/features/features_test.go index 88305403f2b..bf7b2e4ccba 100644 --- a/core/internal/features/features_test.go +++ b/core/internal/features/features_test.go @@ -40,7 +40,6 @@ import ( commonconfig "github.com/smartcontractkit/chainlink-common/pkg/config" "github.com/smartcontractkit/chainlink-common/pkg/services/servicetest" - "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" "github.com/smartcontractkit/chainlink/v2/core/auth" "github.com/smartcontractkit/chainlink/v2/core/bridges" @@ -65,8 +64,8 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" "github.com/smartcontractkit/chainlink/v2/core/services/job" + "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/keystest" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/ocrkey" - "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/p2pkey" "github.com/smartcontractkit/chainlink/v2/core/services/ocr" "github.com/smartcontractkit/chainlink/v2/core/services/pipeline" "github.com/smartcontractkit/chainlink/v2/core/services/webhook" @@ -527,15 +526,10 @@ observationSource = """ assert.Equal(t, []*string(nil), run.Errors) testutils.WaitForLogMessage(t, o, "Sending transaction") - gomega.NewWithT(t).Eventually(func() bool { - b.Commit() // Process new head until tx confirmed, receipt is fetched, and task resumed - for _, l := range o.All() { - if strings.Contains(l.Message, "Resume run success") { - return true - } - } - return false - }, testutils.WaitTimeout(t), 1*time.Second).Should(gomega.BeTrue()) + b.Commit() // Needs at least two confirmations + b.Commit() // Needs at least two confirmations + b.Commit() // Needs at least two confirmations + testutils.WaitForLogMessage(t, o, "Resume run success") pipelineRuns := cltest.WaitForPipelineComplete(t, 0, j.ID, 1, 1, app.JobORM(), testutils.WaitTimeout(t), time.Second) @@ -578,15 +572,10 @@ observationSource = """ assert.Equal(t, []*string(nil), run.Errors) testutils.WaitForLogMessage(t, o, "Sending transaction") - gomega.NewWithT(t).Eventually(func() bool { - b.Commit() // Process new head until tx confirmed, receipt is fetched, and task resumed - for _, l := range o.All() { - if strings.Contains(l.Message, "Resume run success") { - return true - } - } - return false - }, testutils.WaitTimeout(t), 1*time.Second).Should(gomega.BeTrue()) + b.Commit() // Needs at least two confirmations + b.Commit() // Needs at least two confirmations + b.Commit() // Needs at least two confirmations + testutils.WaitForLogMessage(t, o, "Resume run success") pipelineRuns := cltest.WaitForPipelineError(t, 0, j.ID, 1, 1, app.JobORM(), testutils.WaitTimeout(t), time.Second) @@ -621,15 +610,10 @@ observationSource = """ assert.Equal(t, []*string(nil), run.Errors) testutils.WaitForLogMessage(t, o, "Sending transaction") - gomega.NewWithT(t).Eventually(func() bool { - b.Commit() // Process new head until tx confirmed, receipt is fetched, and task resumed - for _, l := range o.All() { - if strings.Contains(l.Message, "Resume run success") { - return true - } - } - return false - }, testutils.WaitTimeout(t), 1*time.Second).Should(gomega.BeTrue()) + b.Commit() // Needs at least two confirmations + b.Commit() // Needs at least two confirmations + b.Commit() // Needs at least two confirmations + testutils.WaitForLogMessage(t, o, "Resume run success") pipelineRuns := cltest.WaitForPipelineComplete(t, 0, j.ID, 1, 1, app.JobORM(), testutils.WaitTimeout(t), time.Second) @@ -641,7 +625,7 @@ observationSource = """ require.Len(t, outputs, 1) output := outputs[0] receipt := output.(map[string]interface{}) - assert.Equal(t, "0x13", receipt["blockNumber"]) + assert.Equal(t, "0x11", receipt["blockNumber"]) assert.Equal(t, "0x7a120", receipt["gasUsed"]) assert.Equal(t, "0x0", receipt["status"]) }) @@ -694,7 +678,7 @@ func setupNode(t *testing.T, owner *bind.TransactOpts, portV2 int, b evmtypes.Backend, overrides func(c *chainlink.Config, s *chainlink.Secrets), ) (*cltest.TestApplication, string, common.Address, ocrkey.KeyV2) { ctx := testutils.Context(t) - p2pKey := p2pkey.MustNewV2XXXTestingOnly(big.NewInt(int64(portV2))) + p2pKey := keystest.NewP2PKeyV2(t) config, _ := heavyweight.FullTestDBV2(t, func(c *chainlink.Config, s *chainlink.Secrets) { c.Insecure.OCRDevelopmentMode = ptr(true) // Disables ocr spec validation so we can have fast polling for the test. @@ -739,7 +723,7 @@ func setupNode(t *testing.T, owner *bind.TransactOpts, portV2 int, func setupForwarderEnabledNode(t *testing.T, owner *bind.TransactOpts, portV2 int, b evmtypes.Backend, overrides func(c *chainlink.Config, s *chainlink.Secrets)) (*cltest.TestApplication, string, common.Address, common.Address, ocrkey.KeyV2) { ctx := testutils.Context(t) - p2pKey := p2pkey.MustNewV2XXXTestingOnly(big.NewInt(int64(portV2))) + p2pKey := keystest.NewP2PKeyV2(t) config, _ := heavyweight.FullTestDBV2(t, func(c *chainlink.Config, s *chainlink.Secrets) { c.Insecure.OCRDevelopmentMode = ptr(true) // Disables ocr spec validation so we can have fast polling for the test. @@ -799,7 +783,7 @@ func setupForwarderEnabledNode(t *testing.T, owner *bind.TransactOpts, portV2 in func TestIntegration_OCR(t *testing.T) { t.Skip("fails after geth upgrade https://github.com/smartcontractkit/chainlink/pull/11809; passes local but fails CI") - tests.SkipShort(t, "long test") + testutils.SkipShort(t, "long test") t.Parallel() tests := []struct { id int @@ -1032,7 +1016,7 @@ observationSource = """ func TestIntegration_OCR_ForwarderFlow(t *testing.T) { t.Skip("fails after geth upgrade https://github.com/smartcontractkit/chainlink/pull/11809") - tests.SkipShort(t, "long test") + testutils.SkipShort(t, "long test") t.Parallel() numOracles := 4 t.Run("ocr_forwarder_flow", func(t *testing.T) { diff --git a/core/internal/features/ocr2/features_ocr2_helper.go b/core/internal/features/ocr2/features_ocr2_helper.go deleted file mode 100644 index 9287d0df5b1..00000000000 --- a/core/internal/features/ocr2/features_ocr2_helper.go +++ /dev/null @@ -1,705 +0,0 @@ -package ocr2 - -import ( - "bytes" - "encoding/json" - "fmt" - "io" - "maps" - "math/big" - "net/http" - "net/http/httptest" - "net/url" - "strconv" - "strings" - "sync" - "testing" - "time" - - "github.com/ethereum/go-ethereum/accounts/abi" - "github.com/ethereum/go-ethereum/accounts/abi/bind" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/eth/ethconfig" - "github.com/ethereum/go-ethereum/ethclient/simulated" - "github.com/hashicorp/consul/sdk/freeport" - "github.com/onsi/gomega" - testoffchainaggregator2 "github.com/smartcontractkit/libocr/gethwrappers2/testocr2aggregator" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - - "github.com/smartcontractkit/libocr/commontypes" - "github.com/smartcontractkit/libocr/gethwrappers2/ocr2aggregator" - - confighelper2 "github.com/smartcontractkit/libocr/offchainreporting2plus/confighelper" - ocrtypes2 "github.com/smartcontractkit/libocr/offchainreporting2plus/types" - - commonconfig "github.com/smartcontractkit/chainlink-common/pkg/config" - "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/testhelpers" - "github.com/smartcontractkit/chainlink/v2/core/services/ocrbootstrap" - - "github.com/smartcontractkit/chainlink/v2/core/bridges" - "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" - "github.com/smartcontractkit/chainlink/v2/core/chains/evm/forwarders" - ubig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/authorized_forwarder" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/link_token_interface" - "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" - "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" - "github.com/smartcontractkit/chainlink/v2/core/logger" - "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" - "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/ocr2key" - "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/p2pkey" - "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/validate" - "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm" - "github.com/smartcontractkit/chainlink/v2/core/store/models" - "github.com/smartcontractkit/chainlink/v2/core/utils/testutils/heavyweight" -) - -type Node struct { - App *cltest.TestApplication - PeerID string - Transmitter common.Address - EffectiveTransmitter common.Address - KeyBundle ocr2key.KeyBundle -} - -func SetupOCR2Contracts(t *testing.T) (*bind.TransactOpts, *simulated.Backend, common.Address, *ocr2aggregator.OCR2Aggregator) { - owner := testutils.MustNewSimTransactor(t) - sb := new(big.Int) - sb, _ = sb.SetString("100000000000000000000", 10) // 1 eth - genesisData := types.GenesisAlloc{owner.From: {Balance: sb}} - gasLimit := ethconfig.Defaults.Miner.GasCeil * 2 - b := simulated.NewBackend(genesisData, simulated.WithBlockGasLimit(gasLimit)) - linkTokenAddress, _, linkContract, err := link_token_interface.DeployLinkToken(owner, b.Client()) - require.NoError(t, err) - b.Commit() - accessAddress, _, _, err := testoffchainaggregator2.DeploySimpleWriteAccessController(owner, b.Client()) - require.NoError(t, err, "failed to deploy test access controller contract") - b.Commit() - - minAnswer, maxAnswer := new(big.Int), new(big.Int) - minAnswer.Exp(big.NewInt(-2), big.NewInt(191), nil) - maxAnswer.Exp(big.NewInt(2), big.NewInt(191), nil) - maxAnswer.Sub(maxAnswer, big.NewInt(1)) - ocrContractAddress, _, ocrContract, err := ocr2aggregator.DeployOCR2Aggregator( - owner, - b.Client(), - linkTokenAddress, // _link common.Address, - minAnswer, // -2**191 - maxAnswer, // 2**191 - 1 - accessAddress, - accessAddress, - 9, - "TEST", - ) - // Ensure we have finality depth worth of blocks to start. - for i := 0; i < 20; i++ { - b.Commit() - } - require.NoError(t, err) - _, err = linkContract.Transfer(owner, ocrContractAddress, big.NewInt(1000)) - require.NoError(t, err) - b.Commit() - return owner, b, ocrContractAddress, ocrContract -} - -func SetupNodeOCR2( - t *testing.T, - owner *bind.TransactOpts, - port int, - useForwarder bool, - b *simulated.Backend, - p2pV2Bootstrappers []commontypes.BootstrapperLocator, -) *Node { - ctx := testutils.Context(t) - p2pKey := p2pkey.MustNewV2XXXTestingOnly(big.NewInt(int64(port))) - config, _ := heavyweight.FullTestDBV2(t, func(c *chainlink.Config, s *chainlink.Secrets) { - c.Insecure.OCRDevelopmentMode = ptr(true) // Disables ocr spec validation so we can have fast polling for the test. - - c.Feature.LogPoller = ptr(true) - - c.OCR.Enabled = ptr(false) - c.OCR2.Enabled = ptr(true) - - c.P2P.PeerID = ptr(p2pKey.PeerID()) - c.P2P.V2.Enabled = ptr(true) - c.P2P.V2.DeltaDial = commonconfig.MustNewDuration(500 * time.Millisecond) - c.P2P.V2.DeltaReconcile = commonconfig.MustNewDuration(5 * time.Second) - c.P2P.V2.ListenAddresses = &[]string{fmt.Sprintf("127.0.0.1:%d", port)} - if len(p2pV2Bootstrappers) > 0 { - c.P2P.V2.DefaultBootstrappers = &p2pV2Bootstrappers - } - - c.EVM[0].LogPollInterval = commonconfig.MustNewDuration(5 * time.Second) - c.EVM[0].Transactions.ForwardersEnabled = &useForwarder - }) - - app := cltest.NewApplicationWithConfigV2AndKeyOnSimulatedBlockchain(t, config, b, p2pKey) - - sendingKeys, err := app.KeyStore.Eth().EnabledKeysForChain(testutils.Context(t), testutils.SimulatedChainID) - require.NoError(t, err) - require.Len(t, sendingKeys, 1) - transmitter := sendingKeys[0].Address - effectiveTransmitter := sendingKeys[0].Address - - // Fund the transmitter address with some ETH - n, err := b.Client().NonceAt(testutils.Context(t), owner.From, nil) - require.NoError(t, err) - - tx := cltest.NewLegacyTransaction( - n, transmitter, - assets.Ether(1).ToInt(), - 21000, - assets.GWei(1).ToInt(), - nil) - signedTx, err := owner.Signer(owner.From, tx) - require.NoError(t, err) - err = b.Client().SendTransaction(testutils.Context(t), signedTx) - require.NoError(t, err) - b.Commit() - - kb, err := app.GetKeyStore().OCR2().Create(ctx, "evm") - require.NoError(t, err) - - if useForwarder { - // deploy a forwarder - faddr, _, authorizedForwarder, err2 := authorized_forwarder.DeployAuthorizedForwarder(owner, b.Client(), common.HexToAddress("0x326C977E6efc84E512bB9C30f76E30c160eD06FB"), owner.From, common.Address{}, []byte{}) - require.NoError(t, err2) - b.Commit() - - // set EOA as an authorized sender for the forwarder - _, err2 = authorizedForwarder.SetAuthorizedSenders(owner, []common.Address{transmitter}) - require.NoError(t, err2) - b.Commit() - - // add forwarder address to be tracked in db - forwarderORM := forwarders.NewORM(app.GetDB()) - chainID, err := b.Client().ChainID(testutils.Context(t)) - require.NoError(t, err) - _, err2 = forwarderORM.CreateForwarder(testutils.Context(t), faddr, ubig.Big(*chainID)) - require.NoError(t, err2) - - effectiveTransmitter = faddr - } - return &Node{ - App: app, - PeerID: p2pKey.PeerID().Raw(), - Transmitter: transmitter, - EffectiveTransmitter: effectiveTransmitter, - KeyBundle: kb, - } -} - -func RunTestIntegrationOCR2(t *testing.T) { - for _, test := range []struct { - name string - chainReaderAndCodec bool - }{ - {"legacy", false}, - {"chain-reader", true}, - } { - test := test - t.Run(test.name, func(t *testing.T) { - owner, b, ocrContractAddress, ocrContract := SetupOCR2Contracts(t) - - lggr := logger.TestLogger(t) - bootstrapNodePort := freeport.GetOne(t) - bootstrapNode := SetupNodeOCR2(t, owner, bootstrapNodePort, false /* useForwarders */, b, nil) - - var ( - oracles []confighelper2.OracleIdentityExtra - transmitters []common.Address - kbs []ocr2key.KeyBundle - apps []*cltest.TestApplication - ) - ports := freeport.GetN(t, 4) - for i := 0; i < 4; i++ { - node := SetupNodeOCR2(t, owner, ports[i], false /* useForwarders */, b, []commontypes.BootstrapperLocator{ - // Supply the bootstrap IP and port as a V2 peer address - {PeerID: bootstrapNode.PeerID, Addrs: []string{fmt.Sprintf("127.0.0.1:%d", bootstrapNodePort)}}, - }) - - kbs = append(kbs, node.KeyBundle) - apps = append(apps, node.App) - transmitters = append(transmitters, node.Transmitter) - - oracles = append(oracles, confighelper2.OracleIdentityExtra{ - OracleIdentity: confighelper2.OracleIdentity{ - OnchainPublicKey: node.KeyBundle.PublicKey(), - TransmitAccount: ocrtypes2.Account(node.Transmitter.String()), - OffchainPublicKey: node.KeyBundle.OffchainPublicKey(), - PeerID: node.PeerID, - }, - ConfigEncryptionPublicKey: node.KeyBundle.ConfigEncryptionPublicKey(), - }) - } - - blockBeforeConfig := InitOCR2(t, lggr, b, ocrContract, owner, bootstrapNode, oracles, transmitters, transmitters, func(blockNum int64) string { - return fmt.Sprintf(` -type = "bootstrap" -name = "bootstrap" -relay = "evm" -schemaVersion = 1 -contractID = "%s" -[relayConfig] -chainID = 1337 -fromBlock = %d -`, ocrContractAddress, blockNum) - }) - - tick := time.NewTicker(1 * time.Second) - defer tick.Stop() - go func() { - for range tick.C { - b.Commit() - } - }() - - var jids []int32 - var servers, slowServers = make([]*httptest.Server, 4), make([]*httptest.Server, 4) - // We expect metadata of: - // latestAnswer:nil // First call - // latestAnswer:0 - // latestAnswer:10 - // latestAnswer:20 - // latestAnswer:30 - var metaLock sync.Mutex - expectedMeta := map[string]struct{}{ - "0": {}, "10": {}, "20": {}, "30": {}, - } - returnData := int(10) - for i := 0; i < 4; i++ { - s := i - require.NoError(t, apps[i].Start(testutils.Context(t))) - - // API speed is > observation timeout set in ContractSetConfigArgsForIntegrationTest - slowServers[i] = httptest.NewServer(http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) { - time.Sleep(5 * time.Second) - var result string - metaLock.Lock() - result = fmt.Sprintf(`{"data":%d}`, returnData) - metaLock.Unlock() - res.WriteHeader(http.StatusOK) - t.Logf("Slow Bridge %d returning data:10", s) - _, err := res.Write([]byte(result)) - assert.NoError(t, err) - })) - t.Cleanup(slowServers[s].Close) - servers[i] = httptest.NewServer(http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) { - b, err := io.ReadAll(req.Body) - if !assert.NoError(t, err) { - res.WriteHeader(http.StatusInternalServerError) - return - } - var m bridges.BridgeMetaDataJSON - if !assert.NoError(t, json.Unmarshal(b, &m)) { - res.WriteHeader(http.StatusInternalServerError) - return - } - var result string - metaLock.Lock() - result = fmt.Sprintf(`{"data":%d}`, returnData) - metaLock.Unlock() - if m.Meta.LatestAnswer != nil && m.Meta.UpdatedAt != nil { - t.Logf("Bridge %d deleting %s, from request body: %s", s, m.Meta.LatestAnswer, b) - metaLock.Lock() - delete(expectedMeta, m.Meta.LatestAnswer.String()) - metaLock.Unlock() - } - res.WriteHeader(http.StatusOK) - _, err = res.Write([]byte(result)) - assert.NoError(t, err) - })) - t.Cleanup(servers[s].Close) - u, _ := url.Parse(servers[i].URL) - bridgeName := fmt.Sprintf("bridge%d", i) - require.NoError(t, apps[i].BridgeORM().CreateBridgeType(testutils.Context(t), &bridges.BridgeType{ - Name: bridges.BridgeName(bridgeName), - URL: models.WebURL(*u), - })) - - var chainReaderSpec string - if test.chainReaderAndCodec { - chainReaderSpec = ` -[relayConfig.chainReader.contracts.median] -contractPollingFilter.genericEventNames = ["LatestRoundRequested"] - -contractABI = ''' -[ - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "requester", - "type": "address" - }, - { - "indexed": false, - "internalType": "bytes32", - "name": "configDigest", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "uint32", - "name": "epoch", - "type": "uint32" - }, - { - "indexed": false, - "internalType": "uint8", - "name": "round", - "type": "uint8" - } - ], - "name": "RoundRequested", - "type": "event" - }, - { - "inputs": [], - "name": "latestTransmissionDetails", - "outputs": [ - { - "internalType": "bytes32", - "name": "configDigest", - "type": "bytes32" - }, - { - "internalType": "uint32", - "name": "epoch", - "type": "uint32" - }, - { - "internalType": "uint8", - "name": "round", - "type": "uint8" - }, - { - "internalType": "int192", - "name": "latestAnswer_", - "type": "int192" - }, - { - "internalType": "uint64", - "name": "latestTimestamp_", - "type": "uint64" - } - ], - "stateMutability": "view", - "type": "function" - } -] -''' - -[relayConfig.chainReader.contracts.median.configs] -LatestRoundRequested = ''' -{ - "chainSpecificName": "RoundRequested", - "readType": "event" -} -''' -LatestTransmissionDetails = ''' -{ - "chainSpecificName": "latestTransmissionDetails", - "outputModifications": [ - { - "Fields": [ - "LatestTimestamp_" - ], - "type": "epoch to time" - }, - { - "Fields": { - "LatestAnswer_": "LatestAnswer", - "LatestTimestamp_": "LatestTimestamp" - }, - "type": "rename" - } - ] -} -''' - -[relayConfig.codec.configs.MedianReport] -typeABI = ''' -[ - { - "Name": "Timestamp", - "Type": "uint32" - }, - { - "Name": "Observers", - "Type": "bytes32" - }, - { - "Name": "Observations", - "Type": "int192[]" - }, - { - "Name": "JuelsPerFeeCoin", - "Type": "int192" - } -] -''' -` - } - ocrJob, err := validate.ValidatedOracleSpecToml(testutils.Context(t), apps[i].Config.OCR2(), apps[i].Config.Insecure(), fmt.Sprintf(` -type = "offchainreporting2" -relay = "evm" -schemaVersion = 1 -pluginType = "median" -name = "web oracle spec" -contractID = "%s" -ocrKeyBundleID = "%s" -transmitterID = "%s" -contractConfigConfirmations = 1 -contractConfigTrackerPollInterval = "1s" -observationSource = """ - // data source 1 - ds1 [type=bridge name="%s"]; - ds1_parse [type=jsonparse path="data"]; - ds1_multiply [type=multiply times=%d]; - - // data source 2 - ds2 [type=http method=GET url="%s"]; - ds2_parse [type=jsonparse path="data"]; - ds2_multiply [type=multiply times=%d]; - - ds1 -> ds1_parse -> ds1_multiply -> answer1; - ds2 -> ds2_parse -> ds2_multiply -> answer1; - - answer1 [type=median index=0]; -""" - -[relayConfig] -chainID = 1337 -fromBlock = %d -%s - -[pluginConfig] -juelsPerFeeCoinSource = """ - // data source 1 - ds1 [type=bridge name="%s"]; - ds1_parse [type=jsonparse path="data"]; - ds1_multiply [type=multiply times=%d]; - - // data source 2 - ds2 [type=http method=GET url="%s"]; - ds2_parse [type=jsonparse path="data"]; - ds2_multiply [type=multiply times=%d]; - - ds1 -> ds1_parse -> ds1_multiply -> answer1; - ds2 -> ds2_parse -> ds2_multiply -> answer1; - - answer1 [type=median index=0]; -""" -gasPriceSubunitsSource = """ - // data source - dsp [type=bridge name="%s"]; - dsp_parse [type=jsonparse path="data"]; - dsp -> dsp_parse; -""" -[pluginConfig.juelsPerFeeCoinCache] -updateInterval = "1m" -`, ocrContractAddress, kbs[i].ID(), transmitters[i], bridgeName, i, slowServers[i].URL, i, blockBeforeConfig.Number().Int64(), chainReaderSpec, bridgeName, i, slowServers[i].URL, i, bridgeName), nil) - require.NoError(t, err) - err = apps[i].AddJobV2(testutils.Context(t), &ocrJob) - require.NoError(t, err) - jids = append(jids, ocrJob.ID) - } - - // Watch for OCR2AggregatorTransmitted events - start := uint64(0) - txEvents := make(chan *ocr2aggregator.OCR2AggregatorTransmitted) - _, err := ocrContract.WatchTransmitted(&bind.WatchOpts{Start: &start, Context: testutils.Context(t)}, txEvents) - require.NoError(t, err) - newTxEvents := make(chan *ocr2aggregator.OCR2AggregatorNewTransmission) - _, err = ocrContract.WatchNewTransmission(&bind.WatchOpts{Start: &start, Context: testutils.Context(t)}, newTxEvents, []uint32{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}) - require.NoError(t, err) - - go func() { - var newTxEvent *ocr2aggregator.OCR2AggregatorNewTransmission - select { - case txEvent := <-txEvents: - t.Logf("txEvent: %v", txEvent) - if newTxEvent != nil { - assert.Equal(t, uint64(txEvent.Epoch), newTxEvent.EpochAndRound.Uint64()) - } - case newTxEvent = <-newTxEvents: - t.Logf("newTxEvent: %v", newTxEvent) - } - }() - - ctx := testutils.Context(t) - for trial := 0; trial < 2; trial++ { - var retVal int - - metaLock.Lock() - returnData = 10 * (trial + 1) - retVal = returnData - for i := 0; i < 4; i++ { - expectedMeta[strconv.Itoa(returnData*i)] = struct{}{} - } - metaLock.Unlock() - - // Assert that all the OCR jobs get a run with valid values eventually. - var wg sync.WaitGroup - for i := 0; i < 4; i++ { - ic := i - wg.Add(1) - go func() { - defer wg.Done() - completedRuns, err2 := apps[ic].JobORM().FindPipelineRunIDsByJobID(ctx, jids[ic], 0, 1000) - if !assert.NoError(t, err2) { - return - } - // Want at least 2 runs so we see all the metadata. - pr := cltest.WaitForPipelineComplete(t, ic, jids[ic], len(completedRuns)+2, 7, apps[ic].JobORM(), 2*time.Minute, 5*time.Second) - jb, err2 := pr[0].Outputs.MarshalJSON() - if !assert.NoError(t, err2) { - return - } - assert.Equal(t, []byte(fmt.Sprintf("[\"%d\"]", retVal*ic)), jb, "pr[0] %+v pr[1] %+v", pr[0], pr[1]) - }() - } - wg.Wait() - - // Trail #1: 4 oracles reporting 0, 10, 20, 30. Answer should be 20 (results[4/2]). - // Trial #2: 4 oracles reporting 0, 20, 40, 60. Answer should be 40 (results[4/2]). - gomega.NewGomegaWithT(t).Eventually(func() string { - answer, err2 := ocrContract.LatestAnswer(nil) - require.NoError(t, err2) - return answer.String() - }, 1*time.Minute, 200*time.Millisecond).Should(gomega.Equal(strconv.Itoa(2 * retVal))) - - for _, app := range apps { - jobs, _, err2 := app.JobORM().FindJobs(ctx, 0, 1000) - require.NoError(t, err2) - // No spec errors - for _, j := range jobs { - ignore := 0 - for i := range j.JobSpecErrors { - // Non-fatal timing related error, ignore for testing. - if strings.Contains(j.JobSpecErrors[i].Description, "leader's phase conflicts tGrace timeout") { - ignore++ - } - } - require.Len(t, j.JobSpecErrors, ignore) - } - } - em := map[string]struct{}{} - metaLock.Lock() - maps.Copy(em, expectedMeta) - metaLock.Unlock() - assert.Empty(t, em, "expected metadata %v", em) - - t.Logf("======= Summary =======") - roundID, err2 := ocrContract.LatestRound(nil) - require.NoError(t, err2) - for i := 0; i <= int(roundID.Int64()); i++ { - roundData, err3 := ocrContract.GetRoundData(nil, big.NewInt(int64(i))) - require.NoError(t, err3) - t.Logf("RoundId: %d, AnsweredInRound: %d, Answer: %d, StartedAt: %v, UpdatedAt: %v", roundData.RoundId, roundData.AnsweredInRound, roundData.Answer, roundData.StartedAt, roundData.UpdatedAt) - } - - expectedAnswer := big.NewInt(2 * int64(retVal)) - - // Assert we can read the latest config digest and epoch after a report has been submitted. - contractABI, err2 := abi.JSON(strings.NewReader(ocr2aggregator.OCR2AggregatorABI)) - require.NoError(t, err2) - apps[0].GetRelayers().LegacyEVMChains().Slice() - ct, err2 := evm.NewOCRContractTransmitter(testutils.Context(t), ocrContractAddress, apps[0].GetRelayers().LegacyEVMChains().Slice()[0].Client(), contractABI, nil, apps[0].GetRelayers().LegacyEVMChains().Slice()[0].LogPoller(), lggr) - require.NoError(t, err2) - configDigest, epoch, err2 := ct.LatestConfigDigestAndEpoch(testutils.Context(t)) - require.NoError(t, err2) - details, err2 := ocrContract.LatestConfigDetails(nil) - require.NoError(t, err2) - assert.True(t, bytes.Equal(configDigest[:], details.ConfigDigest[:])) - digestAndEpoch, err2 := ocrContract.LatestConfigDigestAndEpoch(nil) - require.NoError(t, err2) - assert.Equal(t, digestAndEpoch.Epoch, epoch) - latestTransmissionDetails, err2 := ocrContract.LatestTransmissionDetails(nil) - require.NoError(t, err2) - assert.Equal(t, expectedAnswer, latestTransmissionDetails.LatestAnswer) - require.NoError(t, err2) - newTransmissionEvents, err2 := ocrContract.FilterTransmitted(&bind.FilterOpts{Start: 0, End: nil}) - require.NoError(t, err2) - for newTransmissionEvents.Next() { - assert.Equal(t, 3, newTransmissionEvents.Event.Epoch) - } - } - }) - } -} - -func InitOCR2(t *testing.T, lggr logger.Logger, b *simulated.Backend, - ocrContract *ocr2aggregator.OCR2Aggregator, - owner *bind.TransactOpts, - bootstrapNode *Node, - oracles []confighelper2.OracleIdentityExtra, - transmitters []common.Address, - payees []common.Address, - specFn func(int64) string, -) ( - blockBeforeConfig *types.Block, -) { - lggr.Debugw("Setting Payees on OraclePlugin Contract", "transmitters", payees) - _, err := ocrContract.SetPayees( - owner, - transmitters, - payees, - ) - require.NoError(t, err) - b.Commit() - blockBeforeConfig, err = b.Client().BlockByNumber(testutils.Context(t), nil) - require.NoError(t, err) - signers, effectiveTransmitters, threshold, _, encodedConfigVersion, encodedConfig, err := confighelper2.ContractSetConfigArgsForEthereumIntegrationTest( - oracles, - 1, - 1000000000/100, // threshold PPB - ) - require.NoError(t, err) - - minAnswer, maxAnswer := new(big.Int), new(big.Int) - minAnswer.Exp(big.NewInt(-2), big.NewInt(191), nil) - maxAnswer.Exp(big.NewInt(2), big.NewInt(191), nil) - maxAnswer.Sub(maxAnswer, big.NewInt(1)) - - onchainConfig, err := testhelpers.GenerateDefaultOCR2OnchainConfig(minAnswer, maxAnswer) - require.NoError(t, err) - - lggr.Debugw("Setting Config on Oracle Contract", - "signers", signers, - "transmitters", transmitters, - "effectiveTransmitters", effectiveTransmitters, - "threshold", threshold, - "onchainConfig", onchainConfig, - "encodedConfigVersion", encodedConfigVersion, - ) - _, err = ocrContract.SetConfig( - owner, - signers, - effectiveTransmitters, - threshold, - onchainConfig, - encodedConfigVersion, - encodedConfig, - ) - require.NoError(t, err) - b.Commit() - - err = bootstrapNode.App.Start(testutils.Context(t)) - require.NoError(t, err) - - chainSet := bootstrapNode.App.GetRelayers().LegacyEVMChains() - require.NotNil(t, chainSet) - ocrJob, err := ocrbootstrap.ValidatedBootstrapSpecToml(specFn(blockBeforeConfig.Number().Int64())) - require.NoError(t, err) - err = bootstrapNode.App.AddJobV2(testutils.Context(t), &ocrJob) - require.NoError(t, err) - return -} - -func ptr[T any](v T) *T { return &v } diff --git a/core/internal/features/ocr2/features_ocr2_plugin_test.go b/core/internal/features/ocr2/features_ocr2_plugin_test.go new file mode 100644 index 00000000000..96a9f32e957 --- /dev/null +++ b/core/internal/features/ocr2/features_ocr2_plugin_test.go @@ -0,0 +1,14 @@ +//go:build integration + +package ocr2_test + +import ( + "testing" + + "github.com/smartcontractkit/chainlink/v2/core/config/env" +) + +func TestIntegration_OCR2_plugins(t *testing.T) { + t.Setenv(string(env.MedianPlugin.Cmd), "chainlink-feeds") + testIntegration_OCR2(t) +} diff --git a/core/internal/features/ocr2/features_ocr2_test.go b/core/internal/features/ocr2/features_ocr2_test.go index 01c269d19e3..2d8f55fcc9d 100644 --- a/core/internal/features/ocr2/features_ocr2_test.go +++ b/core/internal/features/ocr2/features_ocr2_test.go @@ -1,4 +1,4 @@ -package ocr2 +package ocr2_test import ( "bytes" @@ -6,6 +6,7 @@ import ( "fmt" "io" "maps" + "math/big" "net/http" "net/http/httptest" "net/url" @@ -15,7 +16,11 @@ import ( "time" "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/eth/ethconfig" + "github.com/ethereum/go-ethereum/ethclient/simulated" "github.com/hashicorp/consul/sdk/freeport" "github.com/onsi/gomega" "github.com/stretchr/testify/assert" @@ -24,31 +29,681 @@ import ( "github.com/smartcontractkit/libocr/commontypes" "github.com/smartcontractkit/libocr/gethwrappers2/ocr2aggregator" + testoffchainaggregator2 "github.com/smartcontractkit/libocr/gethwrappers2/testocr2aggregator" confighelper2 "github.com/smartcontractkit/libocr/offchainreporting2plus/confighelper" ocrtypes2 "github.com/smartcontractkit/libocr/offchainreporting2plus/types" + commonconfig "github.com/smartcontractkit/chainlink-common/pkg/config" + "github.com/smartcontractkit/chainlink/v2/core/bridges" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/forwarders" + ubig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/authorized_forwarder" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/link_token_interface" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/logger" + "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" + "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/keystest" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/ocr2key" + "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/testhelpers" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/validate" + "github.com/smartcontractkit/chainlink/v2/core/services/ocrbootstrap" "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm" "github.com/smartcontractkit/chainlink/v2/core/store/models" + "github.com/smartcontractkit/chainlink/v2/core/utils/testutils/heavyweight" ) +type ocr2Node struct { + app *cltest.TestApplication + peerID string + transmitter common.Address + effectiveTransmitter common.Address + keybundle ocr2key.KeyBundle +} + +func setupOCR2Contracts(t *testing.T) (*bind.TransactOpts, *simulated.Backend, common.Address, *ocr2aggregator.OCR2Aggregator) { + owner := testutils.MustNewSimTransactor(t) + sb := new(big.Int) + sb, _ = sb.SetString("100000000000000000000", 10) // 1 eth + genesisData := types.GenesisAlloc{owner.From: {Balance: sb}} + gasLimit := ethconfig.Defaults.Miner.GasCeil * 2 + b := simulated.NewBackend(genesisData, simulated.WithBlockGasLimit(gasLimit)) + linkTokenAddress, _, linkContract, err := link_token_interface.DeployLinkToken(owner, b.Client()) + require.NoError(t, err) + b.Commit() + accessAddress, _, _, err := testoffchainaggregator2.DeploySimpleWriteAccessController(owner, b.Client()) + require.NoError(t, err, "failed to deploy test access controller contract") + b.Commit() + + minAnswer, maxAnswer := new(big.Int), new(big.Int) + minAnswer.Exp(big.NewInt(-2), big.NewInt(191), nil) + maxAnswer.Exp(big.NewInt(2), big.NewInt(191), nil) + maxAnswer.Sub(maxAnswer, big.NewInt(1)) + ocrContractAddress, _, ocrContract, err := ocr2aggregator.DeployOCR2Aggregator( + owner, + b.Client(), + linkTokenAddress, // _link common.Address, + minAnswer, // -2**191 + maxAnswer, // 2**191 - 1 + accessAddress, + accessAddress, + 9, + "TEST", + ) + // Ensure we have finality depth worth of blocks to start. + for i := 0; i < 20; i++ { + b.Commit() + } + require.NoError(t, err) + _, err = linkContract.Transfer(owner, ocrContractAddress, big.NewInt(1000)) + require.NoError(t, err) + b.Commit() + return owner, b, ocrContractAddress, ocrContract +} + +func setupNodeOCR2( + t *testing.T, + owner *bind.TransactOpts, + port int, + useForwarder bool, + b *simulated.Backend, + p2pV2Bootstrappers []commontypes.BootstrapperLocator, +) *ocr2Node { + ctx := testutils.Context(t) + p2pKey := keystest.NewP2PKeyV2(t) + config, _ := heavyweight.FullTestDBV2(t, func(c *chainlink.Config, s *chainlink.Secrets) { + c.Insecure.OCRDevelopmentMode = ptr(true) // Disables ocr spec validation so we can have fast polling for the test. + + c.Feature.LogPoller = ptr(true) + + c.OCR.Enabled = ptr(false) + c.OCR2.Enabled = ptr(true) + + c.P2P.PeerID = ptr(p2pKey.PeerID()) + c.P2P.V2.Enabled = ptr(true) + c.P2P.V2.DeltaDial = commonconfig.MustNewDuration(500 * time.Millisecond) + c.P2P.V2.DeltaReconcile = commonconfig.MustNewDuration(5 * time.Second) + c.P2P.V2.ListenAddresses = &[]string{fmt.Sprintf("127.0.0.1:%d", port)} + if len(p2pV2Bootstrappers) > 0 { + c.P2P.V2.DefaultBootstrappers = &p2pV2Bootstrappers + } + + c.EVM[0].LogPollInterval = commonconfig.MustNewDuration(5 * time.Second) + c.EVM[0].Transactions.ForwardersEnabled = &useForwarder + }) + + app := cltest.NewApplicationWithConfigV2AndKeyOnSimulatedBlockchain(t, config, b, p2pKey) + + sendingKeys, err := app.KeyStore.Eth().EnabledKeysForChain(testutils.Context(t), testutils.SimulatedChainID) + require.NoError(t, err) + require.Len(t, sendingKeys, 1) + transmitter := sendingKeys[0].Address + effectiveTransmitter := sendingKeys[0].Address + + // Fund the transmitter address with some ETH + n, err := b.Client().NonceAt(testutils.Context(t), owner.From, nil) + require.NoError(t, err) + + tx := cltest.NewLegacyTransaction( + n, transmitter, + assets.Ether(1).ToInt(), + 21000, + assets.GWei(1).ToInt(), + nil) + signedTx, err := owner.Signer(owner.From, tx) + require.NoError(t, err) + err = b.Client().SendTransaction(testutils.Context(t), signedTx) + require.NoError(t, err) + b.Commit() + + kb, err := app.GetKeyStore().OCR2().Create(ctx, "evm") + require.NoError(t, err) + + if useForwarder { + // deploy a forwarder + faddr, _, authorizedForwarder, err2 := authorized_forwarder.DeployAuthorizedForwarder(owner, b.Client(), common.HexToAddress("0x326C977E6efc84E512bB9C30f76E30c160eD06FB"), owner.From, common.Address{}, []byte{}) + require.NoError(t, err2) + b.Commit() + + // set EOA as an authorized sender for the forwarder + _, err2 = authorizedForwarder.SetAuthorizedSenders(owner, []common.Address{transmitter}) + require.NoError(t, err2) + b.Commit() + + // add forwarder address to be tracked in db + forwarderORM := forwarders.NewORM(app.GetDB()) + chainID, err := b.Client().ChainID(testutils.Context(t)) + require.NoError(t, err) + _, err2 = forwarderORM.CreateForwarder(testutils.Context(t), faddr, ubig.Big(*chainID)) + require.NoError(t, err2) + + effectiveTransmitter = faddr + } + return &ocr2Node{ + app: app, + peerID: p2pKey.PeerID().Raw(), + transmitter: transmitter, + effectiveTransmitter: effectiveTransmitter, + keybundle: kb, + } +} + func TestIntegration_OCR2(t *testing.T) { t.Parallel() - RunTestIntegrationOCR2(t) + testIntegration_OCR2(t) +} + +func testIntegration_OCR2(t *testing.T) { + for _, test := range []struct { + name string + chainReaderAndCodec bool + }{ + {"legacy", false}, + {"chain-reader", true}, + } { + test := test + t.Run(test.name, func(t *testing.T) { + owner, b, ocrContractAddress, ocrContract := setupOCR2Contracts(t) + + lggr := logger.TestLogger(t) + bootstrapNodePort := freeport.GetOne(t) + bootstrapNode := setupNodeOCR2(t, owner, bootstrapNodePort, false /* useForwarders */, b, nil) + + var ( + oracles []confighelper2.OracleIdentityExtra + transmitters []common.Address + kbs []ocr2key.KeyBundle + apps []*cltest.TestApplication + ) + ports := freeport.GetN(t, 4) + for i := 0; i < 4; i++ { + node := setupNodeOCR2(t, owner, ports[i], false /* useForwarders */, b, []commontypes.BootstrapperLocator{ + // Supply the bootstrap IP and port as a V2 peer address + {PeerID: bootstrapNode.peerID, Addrs: []string{fmt.Sprintf("127.0.0.1:%d", bootstrapNodePort)}}, + }) + + kbs = append(kbs, node.keybundle) + apps = append(apps, node.app) + transmitters = append(transmitters, node.transmitter) + + oracles = append(oracles, confighelper2.OracleIdentityExtra{ + OracleIdentity: confighelper2.OracleIdentity{ + OnchainPublicKey: node.keybundle.PublicKey(), + TransmitAccount: ocrtypes2.Account(node.transmitter.String()), + OffchainPublicKey: node.keybundle.OffchainPublicKey(), + PeerID: node.peerID, + }, + ConfigEncryptionPublicKey: node.keybundle.ConfigEncryptionPublicKey(), + }) + } + + tick := time.NewTicker(1 * time.Second) + defer tick.Stop() + go func() { + for range tick.C { + b.Commit() + } + }() + + blockBeforeConfig := initOCR2(t, lggr, b, ocrContract, owner, bootstrapNode, oracles, transmitters, transmitters, func(blockNum int64) string { + return fmt.Sprintf(` +type = "bootstrap" +name = "bootstrap" +relay = "evm" +schemaVersion = 1 +contractID = "%s" +[relayConfig] +chainID = 1337 +fromBlock = %d +`, ocrContractAddress, blockNum) + }) + + var jids []int32 + var servers, slowServers = make([]*httptest.Server, 4), make([]*httptest.Server, 4) + // We expect metadata of: + // latestAnswer:nil // First call + // latestAnswer:0 + // latestAnswer:10 + // latestAnswer:20 + // latestAnswer:30 + var metaLock sync.Mutex + expectedMeta := map[string]struct{}{ + "0": {}, "10": {}, "20": {}, "30": {}, + } + returnData := int(10) + for i := 0; i < 4; i++ { + s := i + require.NoError(t, apps[i].Start(testutils.Context(t))) + + // API speed is > observation timeout set in ContractSetConfigArgsForIntegrationTest + slowServers[i] = httptest.NewServer(http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) { + time.Sleep(5 * time.Second) + var result string + metaLock.Lock() + result = fmt.Sprintf(`{"data":%d}`, returnData) + metaLock.Unlock() + res.WriteHeader(http.StatusOK) + t.Logf("Slow Bridge %d returning data:10", s) + _, err := res.Write([]byte(result)) + require.NoError(t, err) + })) + t.Cleanup(slowServers[s].Close) + servers[i] = httptest.NewServer(http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) { + b, err := io.ReadAll(req.Body) + require.NoError(t, err) + var m bridges.BridgeMetaDataJSON + require.NoError(t, json.Unmarshal(b, &m)) + var result string + metaLock.Lock() + result = fmt.Sprintf(`{"data":%d}`, returnData) + metaLock.Unlock() + if m.Meta.LatestAnswer != nil && m.Meta.UpdatedAt != nil { + t.Logf("Bridge %d deleting %s, from request body: %s", s, m.Meta.LatestAnswer, b) + metaLock.Lock() + delete(expectedMeta, m.Meta.LatestAnswer.String()) + metaLock.Unlock() + } + res.WriteHeader(http.StatusOK) + _, err = res.Write([]byte(result)) + require.NoError(t, err) + })) + t.Cleanup(servers[s].Close) + u, _ := url.Parse(servers[i].URL) + bridgeName := fmt.Sprintf("bridge%d", i) + require.NoError(t, apps[i].BridgeORM().CreateBridgeType(testutils.Context(t), &bridges.BridgeType{ + Name: bridges.BridgeName(bridgeName), + URL: models.WebURL(*u), + })) + + var chainReaderSpec string + if test.chainReaderAndCodec { + chainReaderSpec = ` +[relayConfig.chainReader.contracts.median] +contractPollingFilter.genericEventNames = ["LatestRoundRequested"] + +contractABI = ''' +[ + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "requester", + "type": "address" + }, + { + "indexed": false, + "internalType": "bytes32", + "name": "configDigest", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "epoch", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "uint8", + "name": "round", + "type": "uint8" + } + ], + "name": "RoundRequested", + "type": "event" + }, + { + "inputs": [], + "name": "latestTransmissionDetails", + "outputs": [ + { + "internalType": "bytes32", + "name": "configDigest", + "type": "bytes32" + }, + { + "internalType": "uint32", + "name": "epoch", + "type": "uint32" + }, + { + "internalType": "uint8", + "name": "round", + "type": "uint8" + }, + { + "internalType": "int192", + "name": "latestAnswer_", + "type": "int192" + }, + { + "internalType": "uint64", + "name": "latestTimestamp_", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + } +] +''' + +[relayConfig.chainReader.contracts.median.configs] +LatestRoundRequested = ''' +{ + "chainSpecificName": "RoundRequested", + "readType": "event" +} +''' +LatestTransmissionDetails = ''' +{ + "chainSpecificName": "latestTransmissionDetails", + "outputModifications": [ + { + "Fields": [ + "LatestTimestamp_" + ], + "type": "epoch to time" + }, + { + "Fields": { + "LatestAnswer_": "LatestAnswer", + "LatestTimestamp_": "LatestTimestamp" + }, + "type": "rename" + } + ] +} +''' + +[relayConfig.codec.configs.MedianReport] +typeABI = ''' +[ + { + "Name": "Timestamp", + "Type": "uint32" + }, + { + "Name": "Observers", + "Type": "bytes32" + }, + { + "Name": "Observations", + "Type": "int192[]" + }, + { + "Name": "JuelsPerFeeCoin", + "Type": "int192" + } +] +''' +` + } + ocrJob, err := validate.ValidatedOracleSpecToml(testutils.Context(t), apps[i].Config.OCR2(), apps[i].Config.Insecure(), fmt.Sprintf(` +type = "offchainreporting2" +relay = "evm" +schemaVersion = 1 +pluginType = "median" +name = "web oracle spec" +contractID = "%s" +ocrKeyBundleID = "%s" +transmitterID = "%s" +contractConfigConfirmations = 1 +contractConfigTrackerPollInterval = "1s" +observationSource = """ + // data source 1 + ds1 [type=bridge name="%s"]; + ds1_parse [type=jsonparse path="data"]; + ds1_multiply [type=multiply times=%d]; + + // data source 2 + ds2 [type=http method=GET url="%s"]; + ds2_parse [type=jsonparse path="data"]; + ds2_multiply [type=multiply times=%d]; + + ds1 -> ds1_parse -> ds1_multiply -> answer1; + ds2 -> ds2_parse -> ds2_multiply -> answer1; + + answer1 [type=median index=0]; +""" + +[relayConfig] +chainID = 1337 +fromBlock = %d +%s + +[pluginConfig] +juelsPerFeeCoinSource = """ + // data source 1 + ds1 [type=bridge name="%s"]; + ds1_parse [type=jsonparse path="data"]; + ds1_multiply [type=multiply times=%d]; + + // data source 2 + ds2 [type=http method=GET url="%s"]; + ds2_parse [type=jsonparse path="data"]; + ds2_multiply [type=multiply times=%d]; + + ds1 -> ds1_parse -> ds1_multiply -> answer1; + ds2 -> ds2_parse -> ds2_multiply -> answer1; + + answer1 [type=median index=0]; +""" +gasPriceSubunitsSource = """ + // data source + dsp [type=bridge name="%s"]; + dsp_parse [type=jsonparse path="data"]; + dsp -> dsp_parse; +""" +[pluginConfig.juelsPerFeeCoinCache] +updateInterval = "1m" +`, ocrContractAddress, kbs[i].ID(), transmitters[i], bridgeName, i, slowServers[i].URL, i, blockBeforeConfig.Number().Int64(), chainReaderSpec, bridgeName, i, slowServers[i].URL, i, bridgeName), nil) + require.NoError(t, err) + err = apps[i].AddJobV2(testutils.Context(t), &ocrJob) + require.NoError(t, err) + jids = append(jids, ocrJob.ID) + } + + // Watch for OCR2AggregatorTransmitted events + start := uint64(0) + txEvents := make(chan *ocr2aggregator.OCR2AggregatorTransmitted) + _, err := ocrContract.WatchTransmitted(&bind.WatchOpts{Start: &start, Context: testutils.Context(t)}, txEvents) + require.NoError(t, err) + newTxEvents := make(chan *ocr2aggregator.OCR2AggregatorNewTransmission) + _, err = ocrContract.WatchNewTransmission(&bind.WatchOpts{Start: &start, Context: testutils.Context(t)}, newTxEvents, []uint32{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}) + require.NoError(t, err) + + go func() { + var newTxEvent *ocr2aggregator.OCR2AggregatorNewTransmission + select { + case txEvent := <-txEvents: + t.Logf("txEvent: %v", txEvent) + if newTxEvent != nil { + assert.Equal(t, txEvent.Epoch, uint32(newTxEvent.EpochAndRound.Uint64())) + } + case newTxEvent = <-newTxEvents: + t.Logf("newTxEvent: %v", newTxEvent) + } + }() + + ctx := testutils.Context(t) + for trial := 0; trial < 2; trial++ { + var retVal int + + metaLock.Lock() + returnData = 10 * (trial + 1) + retVal = returnData + for i := 0; i < 4; i++ { + expectedMeta[fmt.Sprintf("%d", returnData*i)] = struct{}{} + } + metaLock.Unlock() + + // Assert that all the OCR jobs get a run with valid values eventually. + var wg sync.WaitGroup + for i := 0; i < 4; i++ { + ic := i + wg.Add(1) + go func() { + defer wg.Done() + completedRuns, err2 := apps[ic].JobORM().FindPipelineRunIDsByJobID(ctx, jids[ic], 0, 1000) + require.NoError(t, err2) + // Want at least 2 runs so we see all the metadata. + pr := cltest.WaitForPipelineComplete(t, ic, jids[ic], len(completedRuns)+2, 7, apps[ic].JobORM(), 2*time.Minute, 5*time.Second) + jb, err2 := pr[0].Outputs.MarshalJSON() + require.NoError(t, err2) + assert.Equal(t, []byte(fmt.Sprintf("[\"%d\"]", retVal*ic)), jb, "pr[0] %+v pr[1] %+v", pr[0], pr[1]) + require.NoError(t, err2) + }() + } + wg.Wait() + + // Trail #1: 4 oracles reporting 0, 10, 20, 30. Answer should be 20 (results[4/2]). + // Trial #2: 4 oracles reporting 0, 20, 40, 60. Answer should be 40 (results[4/2]). + gomega.NewGomegaWithT(t).Eventually(func() string { + answer, err2 := ocrContract.LatestAnswer(nil) + require.NoError(t, err2) + return answer.String() + }, 1*time.Minute, 200*time.Millisecond).Should(gomega.Equal(fmt.Sprintf("%d", 2*retVal))) + + for _, app := range apps { + jobs, _, err2 := app.JobORM().FindJobs(ctx, 0, 1000) + require.NoError(t, err2) + // No spec errors + for _, j := range jobs { + ignore := 0 + for i := range j.JobSpecErrors { + // Non-fatal timing related error, ignore for testing. + if strings.Contains(j.JobSpecErrors[i].Description, "leader's phase conflicts tGrace timeout") { + ignore++ + } + } + require.Len(t, j.JobSpecErrors, ignore) + } + } + em := map[string]struct{}{} + metaLock.Lock() + maps.Copy(em, expectedMeta) + metaLock.Unlock() + assert.Len(t, em, 0, "expected metadata %v", em) + + t.Logf("======= Summary =======") + roundId, err2 := ocrContract.LatestRound(nil) + require.NoError(t, err2) + for i := 0; i <= int(roundId.Int64()); i++ { + roundData, err3 := ocrContract.GetRoundData(nil, big.NewInt(int64(i))) + require.NoError(t, err3) + t.Logf("RoundId: %d, AnsweredInRound: %d, Answer: %d, StartedAt: %v, UpdatedAt: %v", roundData.RoundId, roundData.AnsweredInRound, roundData.Answer, roundData.StartedAt, roundData.UpdatedAt) + } + + expectedAnswer := big.NewInt(2 * int64(retVal)) + + // Assert we can read the latest config digest and epoch after a report has been submitted. + contractABI, err2 := abi.JSON(strings.NewReader(ocr2aggregator.OCR2AggregatorABI)) + require.NoError(t, err2) + apps[0].GetRelayers().LegacyEVMChains().Slice() + ct, err2 := evm.NewOCRContractTransmitter(testutils.Context(t), ocrContractAddress, apps[0].GetRelayers().LegacyEVMChains().Slice()[0].Client(), contractABI, nil, apps[0].GetRelayers().LegacyEVMChains().Slice()[0].LogPoller(), lggr) + require.NoError(t, err2) + configDigest, epoch, err2 := ct.LatestConfigDigestAndEpoch(testutils.Context(t)) + require.NoError(t, err2) + details, err2 := ocrContract.LatestConfigDetails(nil) + require.NoError(t, err2) + assert.True(t, bytes.Equal(configDigest[:], details.ConfigDigest[:])) + digestAndEpoch, err2 := ocrContract.LatestConfigDigestAndEpoch(nil) + require.NoError(t, err2) + assert.Equal(t, digestAndEpoch.Epoch, epoch) + latestTransmissionDetails, err2 := ocrContract.LatestTransmissionDetails(nil) + require.NoError(t, err2) + assert.Equal(t, expectedAnswer, latestTransmissionDetails.LatestAnswer) + require.NoError(t, err2) + newTransmissionEvents, err2 := ocrContract.FilterTransmitted(&bind.FilterOpts{Start: 0, End: nil}) + require.NoError(t, err2) + for newTransmissionEvents.Next() { + assert.Equal(t, 3, newTransmissionEvents.Event.Epoch) + } + } + }) + } +} + +func initOCR2(t *testing.T, lggr logger.Logger, b *simulated.Backend, + ocrContract *ocr2aggregator.OCR2Aggregator, + owner *bind.TransactOpts, + bootstrapNode *ocr2Node, + oracles []confighelper2.OracleIdentityExtra, + transmitters []common.Address, + payees []common.Address, + specFn func(int64) string, +) ( + blockBeforeConfig *types.Block, +) { + lggr.Debugw("Setting Payees on OraclePlugin Contract", "transmitters", payees) + _, err := ocrContract.SetPayees( + owner, + transmitters, + payees, + ) + require.NoError(t, err) + b.Commit() + blockBeforeConfig, err = b.Client().BlockByNumber(testutils.Context(t), nil) + require.NoError(t, err) + signers, effectiveTransmitters, threshold, _, encodedConfigVersion, encodedConfig, err := confighelper2.ContractSetConfigArgsForEthereumIntegrationTest( + oracles, + 1, + 1000000000/100, // threshold PPB + ) + require.NoError(t, err) + + minAnswer, maxAnswer := new(big.Int), new(big.Int) + minAnswer.Exp(big.NewInt(-2), big.NewInt(191), nil) + maxAnswer.Exp(big.NewInt(2), big.NewInt(191), nil) + maxAnswer.Sub(maxAnswer, big.NewInt(1)) + + onchainConfig, err := testhelpers.GenerateDefaultOCR2OnchainConfig(minAnswer, maxAnswer) + require.NoError(t, err) + + lggr.Debugw("Setting Config on Oracle Contract", + "signers", signers, + "transmitters", transmitters, + "effectiveTransmitters", effectiveTransmitters, + "threshold", threshold, + "onchainConfig", onchainConfig, + "encodedConfigVersion", encodedConfigVersion, + ) + _, err = ocrContract.SetConfig( + owner, + signers, + effectiveTransmitters, + threshold, + onchainConfig, + encodedConfigVersion, + encodedConfig, + ) + require.NoError(t, err) + b.Commit() + + err = bootstrapNode.app.Start(testutils.Context(t)) + require.NoError(t, err) + + chainSet := bootstrapNode.app.GetRelayers().LegacyEVMChains() + require.NotNil(t, chainSet) + ocrJob, err := ocrbootstrap.ValidatedBootstrapSpecToml(specFn(blockBeforeConfig.Number().Int64())) + require.NoError(t, err) + err = bootstrapNode.app.AddJobV2(testutils.Context(t), &ocrJob) + require.NoError(t, err) + return } func TestIntegration_OCR2_ForwarderFlow(t *testing.T) { t.Parallel() - owner, b, ocrContractAddress, ocrContract := SetupOCR2Contracts(t) + owner, b, ocrContractAddress, ocrContract := setupOCR2Contracts(t) lggr := logger.TestLogger(t) bootstrapNodePort := freeport.GetOne(t) - bootstrapNode := SetupNodeOCR2(t, owner, bootstrapNodePort, true /* useForwarders */, b, nil) + bootstrapNode := setupNodeOCR2(t, owner, bootstrapNodePort, true /* useForwarders */, b, nil) var ( oracles []confighelper2.OracleIdentityExtra @@ -59,31 +714,39 @@ func TestIntegration_OCR2_ForwarderFlow(t *testing.T) { ) ports := freeport.GetN(t, 4) for i := uint16(0); i < 4; i++ { - node := SetupNodeOCR2(t, owner, ports[i], true /* useForwarders */, b, []commontypes.BootstrapperLocator{ + node := setupNodeOCR2(t, owner, ports[i], true /* useForwarders */, b, []commontypes.BootstrapperLocator{ // Supply the bootstrap IP and port as a V2 peer address - {PeerID: bootstrapNode.PeerID, Addrs: []string{fmt.Sprintf("127.0.0.1:%d", bootstrapNodePort)}}, + {PeerID: bootstrapNode.peerID, Addrs: []string{fmt.Sprintf("127.0.0.1:%d", bootstrapNodePort)}}, }) // Effective transmitter should be a forwarder not an EOA. - require.NotEqual(t, node.EffectiveTransmitter, node.Transmitter) + require.NotEqual(t, node.effectiveTransmitter, node.transmitter) - kbs = append(kbs, node.KeyBundle) - apps = append(apps, node.App) - forwarderContracts = append(forwarderContracts, node.EffectiveTransmitter) - transmitters = append(transmitters, node.Transmitter) + kbs = append(kbs, node.keybundle) + apps = append(apps, node.app) + forwarderContracts = append(forwarderContracts, node.effectiveTransmitter) + transmitters = append(transmitters, node.transmitter) oracles = append(oracles, confighelper2.OracleIdentityExtra{ OracleIdentity: confighelper2.OracleIdentity{ - OnchainPublicKey: node.KeyBundle.PublicKey(), - TransmitAccount: ocrtypes2.Account(node.EffectiveTransmitter.String()), - OffchainPublicKey: node.KeyBundle.OffchainPublicKey(), - PeerID: node.PeerID, + OnchainPublicKey: node.keybundle.PublicKey(), + TransmitAccount: ocrtypes2.Account(node.effectiveTransmitter.String()), + OffchainPublicKey: node.keybundle.OffchainPublicKey(), + PeerID: node.peerID, }, - ConfigEncryptionPublicKey: node.KeyBundle.ConfigEncryptionPublicKey(), + ConfigEncryptionPublicKey: node.keybundle.ConfigEncryptionPublicKey(), }) } - blockBeforeConfig := InitOCR2(t, lggr, b, ocrContract, owner, bootstrapNode, oracles, forwarderContracts, transmitters, func(int64) string { + tick := time.NewTicker(1 * time.Second) + defer tick.Stop() + go func() { + for range tick.C { + b.Commit() + } + }() + + blockBeforeConfig := initOCR2(t, lggr, b, ocrContract, owner, bootstrapNode, oracles, forwarderContracts, transmitters, func(int64) string { return fmt.Sprintf(` type = "bootstrap" name = "bootstrap" @@ -96,14 +759,6 @@ chainID = 1337 `, ocrContractAddress) }) - tick := time.NewTicker(1 * time.Second) - defer tick.Stop() - go func() { - for range tick.C { - b.Commit() - } - }() - var jids []int32 var servers, slowServers = make([]*httptest.Server, 4), make([]*httptest.Server, 4) // We expect metadata of: @@ -214,7 +869,7 @@ updateInterval = "1m" for _, app := range apps { require.NoError(t, app.GetRelayers().LegacyEVMChains().Slice()[0].LogPoller().Replay(testutils.Context(t), blockBeforeConfig.Number().Int64())) } - require.NoError(t, bootstrapNode.App.GetRelayers().LegacyEVMChains().Slice()[0].LogPoller().Replay(testutils.Context(t), blockBeforeConfig.Number().Int64())) + require.NoError(t, bootstrapNode.app.GetRelayers().LegacyEVMChains().Slice()[0].LogPoller().Replay(testutils.Context(t), blockBeforeConfig.Number().Int64())) // Assert that all the OCR jobs get a run with valid values eventually. var wg sync.WaitGroup @@ -275,3 +930,5 @@ updateInterval = "1m" require.NoError(t, err) assert.Equal(t, digestAndEpoch.Epoch, epoch) } + +func ptr[T any](v T) *T { return &v } diff --git a/core/internal/features/ocr2/plugins/features_ocr2_plugin_test.go b/core/internal/features/ocr2/plugins/features_ocr2_plugin_test.go deleted file mode 100644 index 260a931a65f..00000000000 --- a/core/internal/features/ocr2/plugins/features_ocr2_plugin_test.go +++ /dev/null @@ -1,16 +0,0 @@ -//go:build integration - -// This package exists to separate a long-running test which sets environment variables, and so cannot be run in parallel. -package plugins - -import ( - "testing" - - "github.com/smartcontractkit/chainlink/v2/core/config/env" - "github.com/smartcontractkit/chainlink/v2/core/internal/features/ocr2" -) - -func TestIntegration_OCR2_plugins(t *testing.T) { - t.Setenv(string(env.MedianPlugin.Cmd), "chainlink-feeds") - ocr2.RunTestIntegrationOCR2(t) -} diff --git a/core/internal/features/ocr2/plugins/plugins.go b/core/internal/features/ocr2/plugins/plugins.go deleted file mode 100644 index 8e3c36c581d..00000000000 --- a/core/internal/features/ocr2/plugins/plugins.go +++ /dev/null @@ -1,3 +0,0 @@ -package plugins - -// empty file w/o build tag so the package "builds" diff --git a/core/internal/testutils/configtest/general_config.go b/core/internal/testutils/configtest/general_config.go index f0851c67740..63aba18c351 100644 --- a/core/internal/testutils/configtest/general_config.go +++ b/core/internal/testutils/configtest/general_config.go @@ -7,16 +7,14 @@ import ( "github.com/stretchr/testify/require" - pgcommon "github.com/smartcontractkit/chainlink-common/pkg/sqlutil/pg" - commonconfig "github.com/smartcontractkit/chainlink-common/pkg/config" - "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" evmclient "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" evmcfg "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/toml" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" + "github.com/smartcontractkit/chainlink/v2/core/store/dialects" "github.com/smartcontractkit/chainlink/v2/core/store/models" ) @@ -50,7 +48,7 @@ func overrides(c *chainlink.Config, s *chainlink.Secrets) { c.InsecureFastScrypt = ptr(true) c.ShutdownGracePeriod = commonconfig.MustNewDuration(testutils.DefaultWaitTimeout) - c.Database.Dialect = pgcommon.TransactionWrappedPostgres + c.Database.Dialect = dialects.TransactionWrappedPostgres c.Database.Lock.Enabled = ptr(false) c.Database.MaxIdleConns = ptr[int64](20) c.Database.MaxOpenConns = ptr[int64](20) diff --git a/core/internal/testutils/pgtest/pgtest.go b/core/internal/testutils/pgtest/pgtest.go index ee17d8f4d14..8464604b667 100644 --- a/core/internal/testutils/pgtest/pgtest.go +++ b/core/internal/testutils/pgtest/pgtest.go @@ -3,25 +3,26 @@ package pgtest import ( "testing" + "github.com/google/uuid" "github.com/jmoiron/sqlx" + "github.com/scylladb/go-reflectx" + "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" - "github.com/smartcontractkit/chainlink-common/pkg/sqlutil/pg" "github.com/smartcontractkit/chainlink-common/pkg/utils" - - "github.com/smartcontractkit/chainlink/v2/core/config/env" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" + "github.com/smartcontractkit/chainlink/v2/core/store/dialects" ) func NewSqlxDB(t testing.TB) *sqlx.DB { testutils.SkipShortDB(t) - dbURL := string(env.DatabaseURL.Get()) - if dbURL == "" { - t.Errorf("you must provide a CL_DATABASE_URL environment variable") - return nil - } - return pg.NewTestDB(t, dbURL) + db, err := sqlx.Open(string(dialects.TransactionWrappedPostgres), uuid.New().String()) + require.NoError(t, err) + t.Cleanup(func() { assert.NoError(t, db.Close()) }) + db.MapperFunc(reflectx.CamelToSnakeASCII) + + return db } func MustExec(t *testing.T, ds sqlutil.DataSource, stmt string, args ...interface{}) { diff --git a/core/internal/testutils/pgtest/txdb.go b/core/internal/testutils/pgtest/txdb.go new file mode 100644 index 00000000000..7591054305c --- /dev/null +++ b/core/internal/testutils/pgtest/txdb.go @@ -0,0 +1,509 @@ +package pgtest + +import ( + "context" + "database/sql" + "database/sql/driver" + "flag" + "fmt" + "io" + "net/url" + "strings" + "sync" + "testing" + + "github.com/jmoiron/sqlx" + "go.uber.org/multierr" + + "github.com/smartcontractkit/chainlink/v2/core/config/env" + "github.com/smartcontractkit/chainlink/v2/core/store/dialects" +) + +// txdb is a simplified version of https://github.com/DATA-DOG/go-txdb +// +// The original lib has various problems and is hard to understand because it +// tries to be more general. The version in this file is more tightly focused +// to our needs and should be easier to reason about and less likely to have +// subtle bugs/races. +// +// It doesn't currently support savepoints but could be made to if necessary. +// +// Transaction BEGIN/ROLLBACK effectively becomes a no-op, this should have no +// negative impact on normal test operation. +// +// If you MUST test BEGIN/ROLLBACK behaviour, you will have to configure your +// store to use the raw DialectPostgres dialect and setup a one-use database. +// See heavyweight.FullTestDB() as a convenience function to help you do this, +// but please use sparingly because as it's name implies, it is expensive. +func init() { + testing.Init() + if !flag.Parsed() { + flag.Parse() + } + if testing.Short() { + // -short tests don't need a DB + return + } + dbURL := string(env.DatabaseURL.Get()) + if dbURL == "" { + panic("you must provide a CL_DATABASE_URL environment variable") + } + + parsed, err := url.Parse(dbURL) + if err != nil { + panic(err) + } + if parsed.Path == "" { + msg := fmt.Sprintf("invalid %[1]s: `%[2]s`. You must set %[1]s env var to point to your test database. Note that the test database MUST end in `_test` to differentiate from a possible production DB. HINT: Try %[1]s=postgresql://postgres@localhost:5432/chainlink_test?sslmode=disable", env.DatabaseURL, parsed.String()) + panic(msg) + } + if !strings.HasSuffix(parsed.Path, "_test") { + msg := fmt.Sprintf("cannot run tests against database named `%s`. Note that the test database MUST end in `_test` to differentiate from a possible production DB. HINT: Try %s=postgresql://postgres@localhost:5432/chainlink_test?sslmode=disable", parsed.Path[1:], env.DatabaseURL) + panic(msg) + } + name := string(dialects.TransactionWrappedPostgres) + sql.Register(name, &txDriver{ + dbURL: dbURL, + conns: make(map[string]*conn), + }) + sqlx.BindDriver(name, sqlx.DOLLAR) +} + +var _ driver.Conn = &conn{} + +var _ driver.Validator = &conn{} +var _ driver.SessionResetter = &conn{} + +// txDriver is an sql driver which runs on a single transaction. +// When `Close` is called, transaction is rolled back. +type txDriver struct { + sync.Mutex + db *sql.DB + conns map[string]*conn + + dbURL string +} + +func (d *txDriver) Open(dsn string) (driver.Conn, error) { + d.Lock() + defer d.Unlock() + // Open real db connection if its the first call + if d.db == nil { + db, err := sql.Open(string(dialects.Postgres), d.dbURL) + if err != nil { + return nil, err + } + d.db = db + } + c, exists := d.conns[dsn] + if !exists || !c.tryOpen() { + tx, err := d.db.Begin() + if err != nil { + return nil, err + } + c = &conn{tx: tx, opened: 1, dsn: dsn} + c.removeSelf = func() error { + return d.deleteConn(c) + } + d.conns[dsn] = c + } + return c, nil +} + +// deleteConn is called by a connection when it is closed via the `close` method. +// It also auto-closes the DB when the last checked out connection is closed. +func (d *txDriver) deleteConn(c *conn) error { + // must lock here to avoid racing with Open + d.Lock() + defer d.Unlock() + + if d.conns[c.dsn] != c { + return nil // already been replaced + } + delete(d.conns, c.dsn) + if len(d.conns) == 0 && d.db != nil { + if err := d.db.Close(); err != nil { + return err + } + d.db = nil + } + return nil +} + +type conn struct { + sync.Mutex + dsn string + tx *sql.Tx // tx may be shared by many conns, definitive one lives in the map keyed by DSN on the txDriver. Do not modify from conn + closed bool + opened int + removeSelf func() error +} + +func (c *conn) Begin() (driver.Tx, error) { + c.Lock() + defer c.Unlock() + if c.closed { + panic("conn is closed") + } + // Begin is a noop because the transaction was already opened + return tx{c.tx}, nil +} + +// Implement the "ConnBeginTx" interface +func (c *conn) BeginTx(_ context.Context, opts driver.TxOptions) (driver.Tx, error) { + // Context is ignored, because single transaction is shared by all callers, thus caller should not be able to + // control it with local context + return c.Begin() +} + +// Prepare returns a prepared statement, bound to this connection. +func (c *conn) Prepare(query string) (driver.Stmt, error) { + return c.PrepareContext(context.Background(), query) +} + +// Implement the "ConnPrepareContext" interface +func (c *conn) PrepareContext(ctx context.Context, query string) (driver.Stmt, error) { + c.Lock() + defer c.Unlock() + if c.closed { + panic("conn is closed") + } + + // TODO: Fix context handling + // FIXME: It is not safe to give the passed in context to the tx directly + // because the tx is shared by many conns and cancelling the context will + // destroy the tx which can affect other conns + st, err := c.tx.PrepareContext(context.Background(), query) + if err != nil { + return nil, err + } + return &stmt{st, c}, nil +} + +// IsValid is called prior to placing the connection into the +// connection pool by database/sql. The connection will be discarded if false is returned. +func (c *conn) IsValid() bool { + c.Lock() + defer c.Unlock() + return !c.closed +} + +func (c *conn) ResetSession(ctx context.Context) error { + // Ensure bad connections are reported: From database/sql/driver: + // If a connection is never returned to the connection pool but immediately reused, then + // ResetSession is called prior to reuse but IsValid is not called. + c.Lock() + defer c.Unlock() + if c.closed { + return driver.ErrBadConn + } + + return nil +} + +// pgx returns nil +func (c *conn) CheckNamedValue(nv *driver.NamedValue) error { + return nil +} + +// Implement the "QueryerContext" interface +func (c *conn) QueryContext(ctx context.Context, query string, args []driver.NamedValue) (driver.Rows, error) { + c.Lock() + defer c.Unlock() + if c.closed { + panic("conn is closed") + } + + // TODO: Fix context handling + rs, err := c.tx.QueryContext(context.Background(), query, mapNamedArgs(args)...) + if err != nil { + return nil, err + } + defer rs.Close() + + return buildRows(rs) +} + +// Implement the "ExecerContext" interface +func (c *conn) ExecContext(ctx context.Context, query string, args []driver.NamedValue) (driver.Result, error) { + c.Lock() + defer c.Unlock() + if c.closed { + panic("conn is closed") + } + // TODO: Fix context handling + return c.tx.ExecContext(context.Background(), query, mapNamedArgs(args)...) +} + +// tryOpen attempts to increment the open count, but returns false if closed. +func (c *conn) tryOpen() bool { + c.Lock() + defer c.Unlock() + if c.closed { + return false + } + c.opened++ + return true +} + +// Close invalidates and potentially stops any current +// prepared statements and transactions, marking this +// connection as no longer in use. +// +// Because the sql package maintains a free pool of +// connections and only calls Close when there's a surplus of +// idle connections, it shouldn't be necessary for drivers to +// do their own connection caching. +// +// Drivers must ensure all network calls made by Close +// do not block indefinitely (e.g. apply a timeout). +func (c *conn) Close() (err error) { + if !c.close() { + return + } + // Wait to remove self to avoid nesting locks. + if err := c.removeSelf(); err != nil { + panic(err) + } + return +} + +func (c *conn) close() bool { + c.Lock() + defer c.Unlock() + if c.closed { + // Double close, should be a safe to make this a noop + // PGX allows double close + // See: https://github.com/jackc/pgx/blob/a457da8bffa4f90ad672fa093ee87f20cf06687b/conn.go#L249 + return false + } + + c.opened-- + if c.opened > 0 { + return false + } + if c.tx != nil { + if err := c.tx.Rollback(); err != nil { + panic(err) + } + c.tx = nil + } + c.closed = true + return true +} + +type tx struct { + tx *sql.Tx +} + +func (tx tx) Commit() error { + // Commit is a noop because the transaction will be rolled back at the end + return nil +} + +func (tx tx) Rollback() error { + // Rollback is a noop because the transaction will be rolled back at the end + return nil +} + +type stmt struct { + st *sql.Stmt + conn *conn +} + +func (s stmt) Exec(args []driver.Value) (driver.Result, error) { + s.conn.Lock() + defer s.conn.Unlock() + if s.conn.closed { + panic("conn is closed") + } + return s.st.Exec(mapArgs(args)...) +} + +// Implement the "StmtExecContext" interface +func (s *stmt) ExecContext(ctx context.Context, args []driver.NamedValue) (driver.Result, error) { + s.conn.Lock() + defer s.conn.Unlock() + if s.conn.closed { + panic("conn is closed") + } + // TODO: Fix context handling + return s.st.ExecContext(context.Background(), mapNamedArgs(args)...) +} + +func mapArgs(args []driver.Value) (res []interface{}) { + res = make([]interface{}, len(args)) + for i := range args { + res[i] = args[i] + } + return +} + +func (s stmt) NumInput() int { + return -1 +} + +func (s stmt) Query(args []driver.Value) (driver.Rows, error) { + s.conn.Lock() + defer s.conn.Unlock() + if s.conn.closed { + panic("conn is closed") + } + rows, err := s.st.Query(mapArgs(args)...) + defer func() { + err = multierr.Combine(err, rows.Close()) + }() + if err != nil { + return nil, err + } + return buildRows(rows) +} + +// Implement the "StmtQueryContext" interface +func (s *stmt) QueryContext(ctx context.Context, args []driver.NamedValue) (driver.Rows, error) { + s.conn.Lock() + defer s.conn.Unlock() + if s.conn.closed { + panic("conn is closed") + } + // TODO: Fix context handling + rows, err := s.st.QueryContext(context.Background(), mapNamedArgs(args)...) + if err != nil { + return nil, err + } + return buildRows(rows) +} + +func (s stmt) Close() error { + s.conn.Lock() + defer s.conn.Unlock() + return s.st.Close() +} + +func buildRows(r *sql.Rows) (driver.Rows, error) { + set := &rowSets{} + rs := &rows{} + if err := rs.read(r); err != nil { + return set, err + } + set.sets = append(set.sets, rs) + for r.NextResultSet() { + rss := &rows{} + if err := rss.read(r); err != nil { + return set, err + } + set.sets = append(set.sets, rss) + } + return set, nil +} + +// Implement the "RowsNextResultSet" interface +func (rs *rowSets) HasNextResultSet() bool { + return rs.pos+1 < len(rs.sets) +} + +// Implement the "RowsNextResultSet" interface +func (rs *rowSets) NextResultSet() error { + if !rs.HasNextResultSet() { + return io.EOF + } + + rs.pos++ + return nil +} + +type rows struct { + rows [][]driver.Value + pos int + cols []string + colTypes []*sql.ColumnType +} + +func (r *rows) Columns() []string { + return r.cols +} + +func (r *rows) ColumnTypeDatabaseTypeName(index int) string { + return r.colTypes[index].DatabaseTypeName() +} + +func (r *rows) Next(dest []driver.Value) error { + r.pos++ + if r.pos > len(r.rows) { + return io.EOF + } + + for i, val := range r.rows[r.pos-1] { + dest[i] = *(val.(*interface{})) + } + + return nil +} + +func (r *rows) Close() error { + return nil +} + +func (r *rows) read(rs *sql.Rows) error { + var err error + r.cols, err = rs.Columns() + if err != nil { + return err + } + + r.colTypes, err = rs.ColumnTypes() + if err != nil { + return err + } + + for rs.Next() { + values := make([]interface{}, len(r.cols)) + for i := range values { + values[i] = new(interface{}) + } + if err := rs.Scan(values...); err != nil { + return err + } + row := make([]driver.Value, len(r.cols)) + for i, v := range values { + row[i] = driver.Value(v) + } + r.rows = append(r.rows, row) + } + return rs.Err() +} + +type rowSets struct { + sets []*rows + pos int +} + +func (rs *rowSets) Columns() []string { + return rs.sets[rs.pos].cols +} + +func (rs *rowSets) ColumnTypeDatabaseTypeName(index int) string { + return rs.sets[rs.pos].ColumnTypeDatabaseTypeName(index) +} + +func (rs *rowSets) Close() error { + return nil +} + +// advances to next row +func (rs *rowSets) Next(dest []driver.Value) error { + return rs.sets[rs.pos].Next(dest) +} + +func mapNamedArgs(args []driver.NamedValue) (res []interface{}) { + res = make([]interface{}, len(args)) + for i := range args { + name := args[i].Name + if name != "" { + res[i] = sql.Named(name, args[i].Value) + } else { + res[i] = args[i].Value + } + } + return +} diff --git a/core/internal/testutils/testutils.go b/core/internal/testutils/testutils.go index 53b555c0e8b..0504570365b 100644 --- a/core/internal/testutils/testutils.go +++ b/core/internal/testutils/testutils.go @@ -32,7 +32,6 @@ import ( // NOTE: To avoid circular dependencies, this package MUST NOT import // anything from "github.com/smartcontractkit/chainlink/v2/core" "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" - "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" ) const ( @@ -416,9 +415,16 @@ func WaitForLogMessageCount(t *testing.T, observedLogs *observer.ObservedLogs, m }) } +// SkipShort skips tb during -short runs, and notes why. +func SkipShort(tb testing.TB, why string) { + if testing.Short() { + tb.Skipf("skipping: %s", why) + } +} + // SkipShortDB skips tb during -short runs, and notes the DB dependency. func SkipShortDB(tb testing.TB) { - tests.SkipShort(tb, "DB dependency") + SkipShort(tb, "DB dependency") } func AssertCount(t *testing.T, ds sqlutil.DataSource, tableName string, expected int64) { @@ -448,6 +454,10 @@ func MustDecodeBase64(s string) (b []byte) { return } +func SkipFlakey(t *testing.T, ticketURL string) { + t.Skip("Flakey", ticketURL) +} + func MustRandBytes(n int) (b []byte) { b = make([]byte, n) _, err := rand.Read(b) diff --git a/core/logger/null_logger.go b/core/logger/null_logger.go index e3e841e138c..9bddd9b336f 100644 --- a/core/logger/null_logger.go +++ b/core/logger/null_logger.go @@ -4,6 +4,7 @@ import ( "go.uber.org/zap/zapcore" ) +// nolint var NullLogger Logger = &nullLogger{} type nullLogger struct{} diff --git a/core/platform/monitoring.go b/core/platform/monitoring.go index b5e12ace80c..30221db240c 100644 --- a/core/platform/monitoring.go +++ b/core/platform/monitoring.go @@ -1,10 +1,5 @@ package platform -import ( - "iter" - "slices" -) - // Observability keys const ( KeyCapabilityID = "capabilityID" @@ -17,13 +12,4 @@ const ( KeyStepRef = "stepRef" ) -func LabelKeysSorted() iter.Seq[string] { - return slices.Values([]string{ - KeyStepRef, - KeyStepID, - KeyTriggerID, - KeyCapabilityID, - KeyWorkflowExecutionID, - KeyWorkflowID, - }) -} +var OrderedLabelKeys = []string{KeyStepRef, KeyStepID, KeyTriggerID, KeyCapabilityID, KeyWorkflowExecutionID, KeyWorkflowID} diff --git a/core/scripts/chaincli/README.md b/core/scripts/chaincli/README.md index bd32c3cbf11..992250ae77c 100644 --- a/core/scripts/chaincli/README.md +++ b/core/scripts/chaincli/README.md @@ -101,7 +101,7 @@ You can also combine the `bootstrap` and `launch-and-test` commands into a singl ```shell ./chaincli keeper launch-and-test --bootstrap ``` -In the output of this command, you will see the http address of the nodes, e.g. `http://localhost:6688`. This is the Chainlink Operator GUI. You can use the default username `notreal@fakeemail.ch` and password `fj293fbBnlQ!f9vNs` to log in. +In the output of this command, you will see the http address of the nodes, e.g. `http://localhost:6688`. This is the Chainlink Operator GUI. You can use the default username `notreal@fakeemail.ch` and password `fj293fbBnlQ!f9vNs~#` to log in. ### Logs Now that the nodes are running, you can use the `logs` subcommand to stream the output of the containers to your local terminal: diff --git a/core/scripts/chaincli/handler/handler.go b/core/scripts/chaincli/handler/handler.go index 50576fe0fe8..d40ee84a312 100644 --- a/core/scripts/chaincli/handler/handler.go +++ b/core/scripts/chaincli/handler/handler.go @@ -44,7 +44,7 @@ import ( const ( defaultChainlinkNodeLogin = "notreal@fakeemail.ch" - defaultChainlinkNodePassword = "fj293fbBnlQ!f9vNs" + defaultChainlinkNodePassword = "fj293fbBnlQ!f9vNs~#" ethKeysEndpoint = "/v2/keys/eth" ocr2KeysEndpoint = "/v2/keys/ocr2" p2pKeysEndpoint = "/v2/keys/p2p" diff --git a/core/scripts/go.mod b/core/scripts/go.mod index e3680eb414e..63167093ed4 100644 --- a/core/scripts/go.mod +++ b/core/scripts/go.mod @@ -1,21 +1,12 @@ module github.com/smartcontractkit/chainlink/core/scripts -go 1.23.3 - -toolchain go1.23.4 +go 1.22.8 // Make sure we're working with the latest chainlink libs replace github.com/smartcontractkit/chainlink/v2 => ../../ replace github.com/smartcontractkit/chainlink/deployment => ../../deployment -// Using a separate `require` here to avoid surrounding line changes -// creating potential merge conflicts. -require ( - github.com/smartcontractkit/chainlink/deployment v0.0.0-20241206210521-125d98cdaf66 - github.com/smartcontractkit/chainlink/v2 v2.0.0-20241206210521-125d98cdaf66 -) - require ( github.com/docker/docker v27.3.1+incompatible github.com/docker/go-connections v0.5.0 @@ -33,11 +24,13 @@ require ( github.com/prometheus/client_golang v1.20.5 github.com/shopspring/decimal v1.4.0 github.com/smartcontractkit/chainlink-automation v0.8.1 - github.com/smartcontractkit/chainlink-common v0.4.1-0.20241217120918-bbe318cd0760 + github.com/smartcontractkit/chainlink-common v0.3.1-0.20241114134822-aadff98ef068 + github.com/smartcontractkit/chainlink/deployment v0.0.0-00010101000000-000000000000 + github.com/smartcontractkit/chainlink/v2 v2.14.0-mercury-20240807.0.20241106193309-5560cd76211a github.com/smartcontractkit/libocr v0.0.0-20241007185508-adbe57025f12 github.com/spf13/cobra v1.8.1 github.com/spf13/viper v1.19.0 - github.com/stretchr/testify v1.10.0 + github.com/stretchr/testify v1.9.0 github.com/umbracle/ethgo v0.1.3 github.com/umbracle/fastrlp v0.0.0-20220527094140-59d5dd30e722 github.com/urfave/cli v1.22.14 @@ -54,41 +47,77 @@ require ( cosmossdk.io/depinject v1.0.0-alpha.4 // indirect cosmossdk.io/errors v1.0.1 // indirect cosmossdk.io/math v1.3.0 // indirect + dario.cat/mergo v1.0.1 // indirect filippo.io/edwards25519 v1.1.0 // indirect github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 // indirect github.com/99designs/keyring v1.2.1 // indirect + github.com/Azure/azure-sdk-for-go/sdk/azcore v1.13.0 // indirect + github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.7.0 // indirect + github.com/Azure/azure-sdk-for-go/sdk/internal v1.10.0 // indirect + github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 // indirect github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358 // indirect + github.com/AzureAD/microsoft-authentication-library-for-go v1.2.2 // indirect github.com/ChainSafe/go-schnorrkel v1.0.0 // indirect github.com/CosmWasm/wasmd v0.40.1 // indirect github.com/CosmWasm/wasmvm v1.2.4 // indirect github.com/DataDog/zstd v1.5.2 // indirect github.com/Depado/ginprom v1.8.0 // indirect + github.com/MakeNowJust/heredoc v1.0.0 // indirect + github.com/Masterminds/goutils v1.1.1 // indirect github.com/Masterminds/semver/v3 v3.3.0 // indirect + github.com/Masterminds/sprig/v3 v3.2.3 // indirect github.com/Microsoft/go-winio v0.6.2 // indirect github.com/NethermindEth/juno v0.3.1 // indirect github.com/NethermindEth/starknet.go v0.7.1-0.20240401080518-34a506f3cfdb // indirect github.com/VictoriaMetrics/fastcache v1.12.2 // indirect github.com/XSAM/otelsql v0.27.0 // indirect - github.com/andybalholm/brotli v1.1.1 // indirect + github.com/alecthomas/units v0.0.0-20240626203959-61d1e3462e30 // indirect + github.com/andybalholm/brotli v1.1.0 // indirect github.com/armon/go-metrics v0.4.1 // indirect + github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect github.com/atombender/go-jsonschema v0.16.1-0.20240916205339-a74cd4e2851c // indirect + github.com/avast/retry-go v3.0.0+incompatible // indirect github.com/avast/retry-go/v4 v4.6.0 // indirect + github.com/awalterschulze/gographviz v2.0.3+incompatible // indirect github.com/aws/aws-sdk-go v1.54.19 // indirect + github.com/aws/aws-sdk-go-v2 v1.32.2 // indirect + github.com/aws/aws-sdk-go-v2/config v1.28.0 // indirect + github.com/aws/aws-sdk-go-v2/credentials v1.17.41 // indirect + github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.17 // indirect + github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.21 // indirect + github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.21 // indirect + github.com/aws/aws-sdk-go-v2/internal/ini v1.8.1 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.0 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.2 // indirect + github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.34.2 // indirect + github.com/aws/aws-sdk-go-v2/service/sso v1.24.2 // indirect + github.com/aws/aws-sdk-go-v2/service/ssooidc v1.28.2 // indirect + github.com/aws/aws-sdk-go-v2/service/sts v1.32.2 // indirect + github.com/aws/constructs-go/constructs/v10 v10.4.2 // indirect + github.com/aws/jsii-runtime-go v1.104.0 // indirect + github.com/aws/smithy-go v1.22.0 // indirect github.com/bahlo/generic-list-go v0.2.0 // indirect + github.com/bboreham/go-loser v0.0.0-20230920113527-fcc2c21820a3 // indirect github.com/benbjohnson/clock v1.3.5 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/bgentry/speakeasy v0.1.1-0.20220910012023-760eaf8b6816 // indirect github.com/bits-and-blooms/bitset v1.13.0 // indirect + github.com/blang/semver/v4 v4.0.0 // indirect github.com/blendle/zapdriver v1.3.1 // indirect github.com/btcsuite/btcd/btcec/v2 v2.3.4 // indirect github.com/buger/jsonparser v1.1.1 // indirect github.com/bytecodealliance/wasmtime-go/v23 v23.0.0 // indirect github.com/bytedance/sonic v1.11.6 // indirect github.com/bytedance/sonic/loader v0.1.1 // indirect + github.com/c2h5oh/datasize v0.0.0-20220606134207-859f65c6625b // indirect + github.com/c9s/goprocinfo v0.0.0-20210130143923-c95fcf8c64a8 // indirect + github.com/cdk8s-team/cdk8s-core-go/cdk8s/v2 v2.7.5 // indirect github.com/cenkalti/backoff v2.2.1+incompatible // indirect github.com/cenkalti/backoff/v4 v4.3.0 // indirect github.com/cespare/xxhash v1.1.0 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect + github.com/chai2010/gettext-go v1.0.2 // indirect + github.com/chaos-mesh/chaos-mesh/api v0.0.0-20240821051457-da69c6d9617a // indirect github.com/cloudwego/base64x v0.1.4 // indirect github.com/cloudwego/iasm v0.2.0 // indirect github.com/cockroachdb/errors v1.11.3 // indirect @@ -97,11 +126,16 @@ require ( github.com/cockroachdb/pebble v1.1.2 // indirect github.com/cockroachdb/redact v1.1.5 // indirect github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 // indirect + github.com/coder/websocket v1.8.12 // indirect github.com/cometbft/cometbft v0.37.5 // indirect github.com/cometbft/cometbft-db v0.8.0 // indirect github.com/confio/ics23/go v0.9.0 // indirect github.com/consensys/bavard v0.1.13 // indirect github.com/consensys/gnark-crypto v0.12.1 // indirect + github.com/containerd/log v0.1.0 // indirect + github.com/containerd/platforms v0.2.1 // indirect + github.com/coreos/go-semver v0.3.1 // indirect + github.com/coreos/go-systemd/v22 v22.5.0 // indirect github.com/cosmos/btcutil v1.0.5 // indirect github.com/cosmos/cosmos-proto v1.0.0-beta.5 // indirect github.com/cosmos/cosmos-sdk v0.47.11 // indirect @@ -111,6 +145,7 @@ require ( github.com/cosmos/ibc-go/v7 v7.5.1 // indirect github.com/cosmos/ics23/go v0.10.0 // indirect github.com/cosmos/ledger-cosmos-go v0.12.4 // indirect + github.com/cpuguy83/dockercfg v0.3.2 // indirect github.com/cpuguy83/go-md2man/v2 v2.0.5 // indirect github.com/crate-crypto/go-ipa v0.0.0-20240223125850-b1e8a79f509c // indirect github.com/crate-crypto/go-kzg-4844 v1.0.0 // indirect @@ -118,33 +153,40 @@ require ( github.com/danielkov/gin-helmet v0.0.0-20171108135313-1387e224435e // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/deckarep/golang-set/v2 v2.6.0 // indirect - github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 // indirect + github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 // indirect + github.com/dennwc/varint v1.0.0 // indirect github.com/dfuse-io/logging v0.0.0-20210109005628-b97a57253f70 // indirect github.com/dgraph-io/badger/v2 v2.2007.4 // indirect github.com/dgraph-io/ristretto v0.1.1 // indirect github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13 // indirect + github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect github.com/distribution/reference v0.6.0 // indirect github.com/docker/distribution v2.8.2+incompatible // indirect github.com/docker/go-units v0.5.0 // indirect github.com/dominikbraun/graph v0.23.0 // indirect github.com/dustin/go-humanize v1.0.1 // indirect github.com/dvsekhvalnov/jose2go v1.7.0 // indirect + github.com/edsrzf/mmap-go v1.1.0 // indirect github.com/emicklei/go-restful/v3 v3.12.1 // indirect github.com/esote/minmaxheap v1.0.0 // indirect github.com/ethereum/c-kzg-4844 v1.0.0 // indirect github.com/ethereum/go-verkle v0.1.1-0.20240829091221-dffa7562dbe9 // indirect + github.com/evanphx/json-patch/v5 v5.9.0 // indirect + github.com/exponent-io/jsonpath v0.0.0-20210407135951-1de76d718b3f // indirect + github.com/facette/natsort v0.0.0-20181210072756-2cd4dd1e2dcb // indirect + github.com/fatih/camelcase v1.0.0 // indirect github.com/fatih/color v1.17.0 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect github.com/fsnotify/fsnotify v1.7.0 // indirect github.com/fxamacker/cbor/v2 v2.7.0 // indirect github.com/gabriel-vasile/mimetype v1.4.3 // indirect - github.com/gagliardetto/binary v0.8.0 // indirect - github.com/gagliardetto/solana-go v1.12.0 // indirect + github.com/gagliardetto/binary v0.7.7 // indirect + github.com/gagliardetto/solana-go v1.8.4 // indirect github.com/gagliardetto/treeout v0.1.4 // indirect github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08 // indirect github.com/gedex/inflector v0.0.0-20170307190818-16278e9db813 // indirect github.com/getsentry/sentry-go v0.27.0 // indirect - github.com/gin-contrib/cors v1.7.2 // indirect + github.com/gin-contrib/cors v1.5.0 // indirect github.com/gin-contrib/expvar v0.0.1 // indirect github.com/gin-contrib/sessions v0.0.5 // indirect github.com/gin-contrib/size v0.0.0-20230212012657-e14a14094dc4 // indirect @@ -153,6 +195,7 @@ require ( github.com/gkampitakis/ciinfo v0.3.0 // indirect github.com/gkampitakis/go-diff v1.3.2 // indirect github.com/go-asn1-ber/asn1-ber v1.5.5 // indirect + github.com/go-errors/errors v1.4.2 // indirect github.com/go-json-experiment/json v0.0.0-20231102232822-2e55bd4e08b0 // indirect github.com/go-kit/kit v0.12.0 // indirect github.com/go-kit/log v0.2.1 // indirect @@ -161,20 +204,30 @@ require ( github.com/go-logr/logr v1.4.2 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/go-ole/go-ole v1.3.0 // indirect + github.com/go-openapi/analysis v0.22.2 // indirect + github.com/go-openapi/errors v0.22.0 // indirect github.com/go-openapi/jsonpointer v0.21.0 // indirect github.com/go-openapi/jsonreference v0.21.0 // indirect + github.com/go-openapi/loads v0.21.5 // indirect + github.com/go-openapi/spec v0.20.14 // indirect + github.com/go-openapi/strfmt v0.23.0 // indirect github.com/go-openapi/swag v0.23.0 // indirect + github.com/go-openapi/validate v0.23.0 // indirect github.com/go-playground/locales v0.14.1 // indirect github.com/go-playground/universal-translator v0.18.1 // indirect github.com/go-playground/validator/v10 v10.22.0 // indirect + github.com/go-redis/redis/v8 v8.11.5 // indirect + github.com/go-resty/resty/v2 v2.15.3 // indirect github.com/go-viper/mapstructure/v2 v2.1.0 // indirect github.com/go-webauthn/webauthn v0.9.4 // indirect github.com/go-webauthn/x v0.1.5 // indirect - github.com/goccy/go-json v0.10.3 // indirect + github.com/goccy/go-json v0.10.2 // indirect github.com/goccy/go-yaml v1.12.0 // indirect github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2 // indirect github.com/gofrs/flock v0.8.1 // indirect + github.com/gogo/googleapis v1.4.1 // indirect github.com/gogo/protobuf v1.3.3 // indirect + github.com/gogo/status v1.1.1 // indirect github.com/golang-jwt/jwt/v4 v4.5.0 // indirect github.com/golang-jwt/jwt/v5 v5.2.1 // indirect github.com/golang/glog v1.2.2 // indirect @@ -183,17 +236,28 @@ require ( github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb // indirect github.com/google/btree v1.1.2 // indirect github.com/google/gnostic-models v0.6.9-0.20230804172637-c7be7c783f49 // indirect + github.com/google/go-github/v41 v41.0.0 // indirect + github.com/google/go-querystring v1.1.0 // indirect github.com/google/go-tpm v0.9.0 // indirect github.com/google/gofuzz v1.2.0 // indirect github.com/google/pprof v0.0.0-20240827171923-fa2c70bbbfe5 // indirect + github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect github.com/gorilla/context v1.1.1 // indirect + github.com/gorilla/mux v1.8.0 // indirect github.com/gorilla/securecookie v1.1.2 // indirect github.com/gorilla/sessions v1.2.2 // indirect github.com/gorilla/websocket v1.5.1 // indirect + github.com/grafana/dskit v0.0.0-20231120170505-765e343eda4f // indirect + github.com/grafana/gomemcache v0.0.0-20231023152154-6947259a0586 // indirect + github.com/grafana/grafana-foundation-sdk/go v0.0.0-20240326122733-6f96a993222b // indirect + github.com/grafana/loki v1.6.2-0.20231215164305-b51b7d7b5503 // indirect + github.com/grafana/loki/pkg/push v0.0.0-20231201111602-11ef833ed3e4 // indirect github.com/grafana/pyroscope-go v1.1.2 // indirect github.com/grafana/pyroscope-go/godeltaprof v0.1.8 // indirect + github.com/grafana/regexp v0.0.0-20240518133315-a468a5bfb3bc // indirect github.com/graph-gophers/dataloader v5.0.0+incompatible // indirect github.com/graph-gophers/graphql-go v1.5.0 // indirect + github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79 // indirect github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 // indirect github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.0.1 // indirect github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.1.0 // indirect @@ -202,23 +266,31 @@ require ( github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c // indirect github.com/gtank/merlin v0.1.1 // indirect github.com/gtank/ristretto255 v0.1.2 // indirect + github.com/hashicorp/consul/api v1.29.2 // indirect github.com/hashicorp/consul/sdk v0.16.1 // indirect + github.com/hashicorp/errwrap v1.1.0 // indirect github.com/hashicorp/go-bexpr v0.1.10 // indirect github.com/hashicorp/go-cleanhttp v0.5.2 // indirect github.com/hashicorp/go-envparse v0.1.0 // indirect github.com/hashicorp/go-hclog v1.6.3 // indirect github.com/hashicorp/go-immutable-radix v1.3.1 // indirect + github.com/hashicorp/go-msgpack v0.5.5 // indirect + github.com/hashicorp/go-multierror v1.1.1 // indirect github.com/hashicorp/go-plugin v1.6.2 // indirect github.com/hashicorp/go-retryablehttp v0.7.7 // indirect - github.com/hashicorp/go-version v1.7.0 // indirect + github.com/hashicorp/go-rootcerts v1.0.2 // indirect + github.com/hashicorp/go-sockaddr v1.0.6 // indirect github.com/hashicorp/golang-lru v0.6.0 // indirect github.com/hashicorp/hcl v1.0.0 // indirect + github.com/hashicorp/memberlist v0.5.0 // indirect + github.com/hashicorp/serf v0.10.1 // indirect github.com/hashicorp/yamux v0.1.1 // indirect github.com/hdevalence/ed25519consensus v0.1.0 // indirect github.com/holiman/billy v0.0.0-20240216141850-2abb0c79d3c4 // indirect github.com/holiman/bloomfilter/v2 v2.0.3 // indirect github.com/holiman/uint256 v1.3.1 // indirect github.com/huandu/skiplist v1.2.0 // indirect + github.com/huandu/xstrings v1.4.0 // indirect github.com/huin/goupnp v1.3.0 // indirect github.com/iancoleman/strcase v0.3.0 // indirect github.com/imdario/mergo v0.3.16 // indirect @@ -238,17 +310,21 @@ require ( github.com/josharian/intern v1.0.0 // indirect github.com/jpillora/backoff v1.0.0 // indirect github.com/json-iterator/go v1.1.12 // indirect - github.com/klauspost/compress v1.17.11 // indirect - github.com/klauspost/cpuid/v2 v2.2.8 // indirect + github.com/julienschmidt/httprouter v1.3.0 // indirect + github.com/kelseyhightower/envconfig v1.4.0 // indirect + github.com/klauspost/compress v1.17.9 // indirect + github.com/klauspost/cpuid/v2 v2.2.7 // indirect github.com/kr/pretty v0.3.1 // indirect github.com/kr/text v0.2.0 // indirect github.com/kylelemons/godebug v1.1.0 // indirect - github.com/leanovate/gopter v0.2.11 // indirect + github.com/leanovate/gopter v0.2.10-0.20210127095200-9abe2343507a // indirect github.com/leodido/go-urn v1.4.0 // indirect github.com/lib/pq v1.10.9 // indirect github.com/libp2p/go-buffer-pool v0.1.0 // indirect + github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de // indirect github.com/linxGnu/grocksdb v1.7.16 // indirect github.com/logrusorgru/aurora v2.0.3+incompatible // indirect + github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect github.com/magiconair/properties v1.8.7 // indirect github.com/mailru/easyjson v0.7.7 // indirect github.com/maruel/natural v1.1.1 // indirect @@ -256,41 +332,64 @@ require ( github.com/mattn/go-isatty v0.0.20 // indirect github.com/mattn/go-runewidth v0.0.14 // indirect github.com/mfridman/interpolate v0.0.2 // indirect + github.com/miekg/dns v1.1.61 // indirect github.com/mimoo/StrobeGo v0.0.0-20210601165009-122bf33a46e0 // indirect + github.com/mitchellh/copystructure v1.2.0 // indirect github.com/mitchellh/go-homedir v1.1.0 // indirect github.com/mitchellh/go-testing-interface v1.14.1 // indirect github.com/mitchellh/go-wordwrap v1.0.1 // indirect github.com/mitchellh/mapstructure v1.5.0 // indirect github.com/mitchellh/pointerstructure v1.2.0 // indirect + github.com/mitchellh/reflectwalk v1.0.2 // indirect github.com/mmcloughlin/addchain v0.4.0 // indirect github.com/moby/docker-image-spec v1.3.1 // indirect + github.com/moby/patternmatcher v0.6.0 // indirect + github.com/moby/spdystream v0.4.0 // indirect + github.com/moby/sys/sequential v0.6.0 // indirect + github.com/moby/sys/user v0.3.0 // indirect + github.com/moby/sys/userns v0.1.0 // indirect + github.com/moby/term v0.5.0 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect + github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 // indirect + github.com/morikuni/aec v1.0.0 // indirect github.com/mostynb/zstdpool-freelist v0.0.0-20201229113212-927304c0c3b1 // indirect github.com/mr-tron/base58 v1.2.0 // indirect github.com/mtibben/percent v0.2.1 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect + github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f // indirect + github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f // indirect github.com/oklog/run v1.1.0 // indirect - github.com/onsi/ginkgo/v2 v2.20.1 // indirect + github.com/oklog/ulid v1.3.1 // indirect github.com/opencontainers/go-digest v1.0.0 // indirect github.com/opencontainers/image-spec v1.1.0 // indirect + github.com/opentracing-contrib/go-grpc v0.0.0-20210225150812-73cb765af46e // indirect + github.com/opentracing-contrib/go-stdlib v1.0.0 // indirect github.com/opentracing/opentracing-go v1.2.0 // indirect + github.com/otiai10/copy v1.14.0 // indirect github.com/patrickmn/go-cache v2.1.0+incompatible // indirect + github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58 // indirect github.com/pelletier/go-toml v1.9.5 // indirect + github.com/peterbourgon/diskv v2.0.1+incompatible // indirect github.com/petermattis/goid v0.0.0-20230317030725-371a4b8eda08 // indirect + github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c // indirect github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect github.com/pressly/goose/v3 v3.21.1 // indirect + github.com/prometheus/alertmanager v0.27.0 // indirect github.com/prometheus/client_model v0.6.1 // indirect github.com/prometheus/common v0.60.0 // indirect + github.com/prometheus/common/sigv4 v0.1.0 // indirect + github.com/prometheus/exporter-toolkit v0.11.0 // indirect github.com/prometheus/procfs v0.15.1 // indirect github.com/prometheus/prometheus v0.54.1 // indirect github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect github.com/rivo/uniseg v0.4.4 // indirect github.com/robfig/cron/v3 v3.0.1 // indirect - github.com/rogpeppe/go-internal v1.13.1 // indirect + github.com/rogpeppe/go-internal v1.12.0 // indirect github.com/rs/cors v1.10.1 // indirect + github.com/rs/zerolog v1.33.0 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/sagikazarmark/locafero v0.4.0 // indirect github.com/sagikazarmark/slog-shim v0.1.0 // indirect @@ -298,30 +397,39 @@ require ( github.com/santhosh-tekuri/jsonschema/v5 v5.3.1 // indirect github.com/sasha-s/go-deadlock v0.3.1 // indirect github.com/scylladb/go-reflectx v1.0.1 // indirect + github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529 // indirect + github.com/sercand/kuberesolver/v5 v5.1.1 // indirect github.com/sethvargo/go-retry v0.2.4 // indirect github.com/shirou/gopsutil v3.21.11+incompatible // indirect github.com/shirou/gopsutil/v3 v3.24.3 // indirect - github.com/smartcontractkit/ccip-owner-contracts v0.0.0-salt-fix // indirect - github.com/smartcontractkit/chain-selectors v1.0.34 // indirect - github.com/smartcontractkit/chainlink-ccip v0.0.0-20241218114855-f74219171000 // indirect - github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241202195413-82468150ac1e // indirect - github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20241216163550-fa030d178ba3 // indirect + github.com/shoenig/go-m1cpu v0.1.6 // indirect + github.com/sirupsen/logrus v1.9.3 // indirect + github.com/smartcontractkit/ccip-owner-contracts v0.0.0-20240926212305-a6deabdfce86 // indirect + github.com/smartcontractkit/chain-selectors v1.0.29 // indirect + github.com/smartcontractkit/chainlink-ccip v0.0.0-20241118091009-43c2b4804cec // indirect + github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241017133723-5277829bd53f // indirect + github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20241018134907-a00ba3729b5e // indirect github.com/smartcontractkit/chainlink-feeds v0.1.1 // indirect - github.com/smartcontractkit/chainlink-protos/job-distributor v0.6.0 // indirect - github.com/smartcontractkit/chainlink-protos/orchestrator v0.4.0 // indirect - github.com/smartcontractkit/chainlink-solana v1.1.1-0.20241219173444-150f7443fdd3 // indirect - github.com/smartcontractkit/chainlink-starknet/relayer v0.1.1-0.20241202202529-2033490e77b8 // indirect + github.com/smartcontractkit/chainlink-protos/job-distributor v0.4.0 // indirect + github.com/smartcontractkit/chainlink-protos/orchestrator v0.3.0 // indirect + github.com/smartcontractkit/chainlink-solana v1.1.1-0.20241115191142-8b8369c1f44e // indirect + github.com/smartcontractkit/chainlink-starknet/relayer v0.1.1-0.20241017135645-176a23722fd8 // indirect github.com/smartcontractkit/chainlink-testing-framework/lib v1.50.13 // indirect + github.com/smartcontractkit/chainlink-testing-framework/lib/grafana v1.50.0 // indirect + github.com/smartcontractkit/chainlink-testing-framework/seth v1.50.5 // indirect + github.com/smartcontractkit/chainlink-testing-framework/wasp v1.50.2 // indirect github.com/smartcontractkit/grpc-proxy v0.0.0-20240830132753-a7e17fec5ab7 // indirect github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20241009055228-33d0c0bf38de // indirect github.com/smartcontractkit/tdh2/go/tdh2 v0.0.0-20241009055228-33d0c0bf38de // indirect - github.com/smartcontractkit/wsrpc v0.8.3 // indirect + github.com/smartcontractkit/wsrpc v0.8.2 // indirect + github.com/soheilhy/cmux v0.1.5 // indirect + github.com/sony/gobreaker v0.5.0 // indirect github.com/sourcegraph/conc v0.3.0 // indirect github.com/spf13/afero v1.11.0 // indirect github.com/spf13/cast v1.6.0 // indirect github.com/spf13/pflag v1.0.5 // indirect github.com/status-im/keycard-go v0.2.0 // indirect - github.com/streamingfast/logging v0.0.0-20230608130331-f22c91403091 // indirect + github.com/streamingfast/logging v0.0.0-20220405224725-2755dab2ce75 // indirect github.com/stretchr/objx v0.5.2 // indirect github.com/subosito/gotenv v1.6.0 // indirect github.com/supranational/blst v0.3.13 // indirect @@ -329,6 +437,7 @@ require ( github.com/tendermint/go-amino v0.16.0 // indirect github.com/teris-io/shortid v0.0.0-20201117134242-e59966efd125 // indirect github.com/test-go/testify v1.1.4 // indirect + github.com/testcontainers/testcontainers-go v0.34.0 // indirect github.com/theodesp/go-heaps v0.0.0-20190520121037-88e35354fe0a // indirect github.com/tidwall/btree v1.6.0 // indirect github.com/tidwall/gjson v1.17.0 // indirect @@ -339,6 +448,8 @@ require ( github.com/tklauser/numcpus v0.6.1 // indirect github.com/twitchyliquid64/golang-asm v0.15.1 // indirect github.com/tyler-smith/go-bip39 v1.1.0 // indirect + github.com/uber/jaeger-client-go v2.30.0+incompatible // indirect + github.com/uber/jaeger-lib v2.4.1+incompatible // indirect github.com/ugorji/go/codec v1.2.12 // indirect github.com/ulule/limiter/v3 v3.11.2 // indirect github.com/unrolled/secure v1.13.0 // indirect @@ -346,6 +457,7 @@ require ( github.com/valyala/fastjson v1.4.1 // indirect github.com/wk8/go-ordered-map/v2 v2.1.8 // indirect github.com/x448/float16 v0.8.4 // indirect + github.com/xlab/treeprint v1.2.0 // indirect github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 // indirect github.com/yusufpapurcu/wmi v1.2.4 // indirect github.com/zondax/hid v0.9.2 // indirect @@ -353,8 +465,13 @@ require ( go.dedis.ch/fixbuf v1.0.3 // indirect go.dedis.ch/kyber/v3 v3.1.0 // indirect go.etcd.io/bbolt v1.3.9 // indirect + go.etcd.io/etcd/api/v3 v3.5.14 // indirect + go.etcd.io/etcd/client/pkg/v3 v3.5.14 // indirect + go.etcd.io/etcd/client/v3 v3.5.14 // indirect go.mongodb.org/mongo-driver v1.15.0 // indirect go.opencensus.io v0.24.0 // indirect + go.opentelemetry.io/collector/pdata v1.12.0 // indirect + go.opentelemetry.io/collector/semconv v0.105.0 // indirect go.opentelemetry.io/contrib/instrumentation/github.com/gin-gonic/gin/otelgin v0.49.0 // indirect go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.56.0 // indirect go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.56.0 // indirect @@ -376,39 +493,52 @@ require ( go.opentelemetry.io/otel/sdk/metric v1.31.0 // indirect go.opentelemetry.io/otel/trace v1.31.0 // indirect go.opentelemetry.io/proto/otlp v1.3.1 // indirect + go.starlark.net v0.0.0-20230525235612-a134d8f9ddca // indirect + go.uber.org/atomic v1.11.0 // indirect + go.uber.org/goleak v1.3.0 // indirect go.uber.org/multierr v1.11.0 // indirect go.uber.org/ratelimit v0.3.1 // indirect go.uber.org/zap v1.27.0 // indirect + go4.org/netipx v0.0.0-20230125063823-8449b0a6169f // indirect golang.org/x/arch v0.11.0 // indirect - golang.org/x/crypto v0.31.0 // indirect - golang.org/x/exp v0.0.0-20241210194714-1829a127f884 // indirect - golang.org/x/mod v0.22.0 // indirect - golang.org/x/net v0.32.0 // indirect + golang.org/x/crypto v0.28.0 // indirect + golang.org/x/exp v0.0.0-20241009180824-f66d83c29e7c // indirect + golang.org/x/mod v0.21.0 // indirect + golang.org/x/net v0.30.0 // indirect golang.org/x/oauth2 v0.23.0 // indirect - golang.org/x/sync v0.10.0 // indirect - golang.org/x/sys v0.28.0 // indirect - golang.org/x/term v0.27.0 // indirect - golang.org/x/text v0.21.0 // indirect + golang.org/x/sync v0.8.0 // indirect + golang.org/x/sys v0.26.0 // indirect + golang.org/x/term v0.25.0 // indirect + golang.org/x/text v0.19.0 // indirect golang.org/x/time v0.7.0 // indirect - golang.org/x/tools v0.28.0 // indirect + golang.org/x/tools v0.26.0 // indirect golang.org/x/xerrors v0.0.0-20240903120638-7835f813f4da // indirect + gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect gonum.org/v1/gonum v0.15.1 // indirect google.golang.org/genproto v0.0.0-20241021214115-324edc3d5d38 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20241021214115-324edc3d5d38 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20241021214115-324edc3d5d38 // indirect google.golang.org/grpc v1.67.1 // indirect + gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect gopkg.in/guregu/null.v4 v4.0.0 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/natefinch/lumberjack.v2 v2.2.1 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect + k8s.io/apiextensions-apiserver v0.31.0 // indirect + k8s.io/cli-runtime v0.31.1 // indirect + k8s.io/component-base v0.31.1 // indirect k8s.io/klog/v2 v2.130.1 // indirect k8s.io/kube-openapi v0.0.0-20240709000822-3c01b740850f // indirect + k8s.io/kubectl v0.31.1 // indirect k8s.io/utils v0.0.0-20240711033017-18e509b52bc8 // indirect pgregory.net/rapid v1.1.0 // indirect rsc.io/tmplfunc v0.0.3 // indirect + sigs.k8s.io/controller-runtime v0.19.0 // indirect sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect + sigs.k8s.io/kustomize/api v0.17.2 // indirect + sigs.k8s.io/kustomize/kyaml v0.17.1 // indirect sigs.k8s.io/structured-merge-diff/v4 v4.4.1 // indirect sigs.k8s.io/yaml v1.4.0 // indirect ) diff --git a/core/scripts/go.sum b/core/scripts/go.sum index 4013f374b0d..719ea492a88 100644 --- a/core/scripts/go.sum +++ b/core/scripts/go.sum @@ -16,11 +16,6 @@ cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKV cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs= cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc= cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= -cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI= -cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk= -cloud.google.com/go v0.78.0/go.mod h1:QjdrLG0uq+YwhjoVOLsS1t7TW8fs36kLs4XO5R5ECHg= -cloud.google.com/go v0.79.0/go.mod h1:3bzgcEeQlzbuEAYu4mrWhKqWjmpprinYgKJLgKHnbb8= -cloud.google.com/go v0.81.0/go.mod h1:mk/AM35KwGk/Nm2YSeZbxXdrNK3KZOYHmLkOqC2V6E0= cloud.google.com/go v0.116.0 h1:B3fRrSDkLRt5qSHWe40ERJvhvnQwdZiHu0bJOpldweE= cloud.google.com/go v0.116.0/go.mod h1:cEPSRWPzZEswwdr9BxE6ChEn01dWlTaF05LiC2Xs70U= cloud.google.com/go/auth v0.9.9 h1:BmtbpNQozo8ZwW2t7QJjnrQtdganSdmqeIBxHxNkEZQ= @@ -72,6 +67,8 @@ cosmossdk.io/math v1.3.0 h1:RC+jryuKeytIiictDslBP9i1fhkVm6ZDmZEoNP316zE= cosmossdk.io/math v1.3.0/go.mod h1:vnRTxewy+M7BtXBNFybkuhSH4WfedVAAnERHgVFhp3k= cosmossdk.io/tools/rosetta v0.2.1 h1:ddOMatOH+pbxWbrGJKRAawdBkPYLfKXutK9IETnjYxw= cosmossdk.io/tools/rosetta v0.2.1/go.mod h1:Pqdc1FdvkNV3LcNIkYWt2RQY6IP1ge6YWZk8MhhO9Hw= +dario.cat/mergo v1.0.1 h1:Ra4+bf83h2ztPIQYNP99R6m+Y7KfnARDfID+a+vLl4s= +dario.cat/mergo v1.0.1/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= filippo.io/edwards25519 v1.0.0-rc.1/go.mod h1:N1IkdkCkiLB6tki+MYJoSx2JTY9NUlxZE7eHn5EwJns= filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= @@ -80,17 +77,34 @@ github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 h1:/vQbFIOMb github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4/go.mod h1:hN7oaIRCjzsZ2dE+yG5k+rsdt3qcwykqK6HVGcKwsw4= github.com/99designs/keyring v1.2.1 h1:tYLp1ULvO7i3fI5vE21ReQuj99QFSs7lGm0xWyJo87o= github.com/99designs/keyring v1.2.1/go.mod h1:fc+wB5KTk9wQ9sDx0kFXB3A0MaeGHM9AwRStKOQ5vOA= +github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24 h1:bvDV9vkmnHYOMsOr4WLk+Vo07yKIzd94sVoIqshQ4bU= +github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24/go.mod h1:8o94RPi1/7XTJvwPpRSzSUedZrtlirdB3r9Z20bi2f8= github.com/AlekSi/pointer v1.1.0 h1:SSDMPcXD9jSl8FPy9cRzoRaMJtm9g9ggGTxecRUbQoI= github.com/AlekSi/pointer v1.1.0/go.mod h1:y7BvfRI3wXPWKXEBhU71nbnIEEZX0QTSB2Bj48UJIZE= +github.com/Azure/azure-sdk-for-go v65.0.0+incompatible h1:HzKLt3kIwMm4KeJYTdx9EbjRYTySD/t8i1Ee/W5EGXw= +github.com/Azure/azure-sdk-for-go/sdk/azcore v1.13.0 h1:GJHeeA2N7xrG3q30L2UXDyuWRzDM900/65j70wcM4Ww= +github.com/Azure/azure-sdk-for-go/sdk/azcore v1.13.0/go.mod h1:l38EPgmsp71HHLq9j7De57JcKOWPyhrsW1Awm1JS6K0= +github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.7.0 h1:tfLQ34V6F7tVSwoTf/4lH5sE0o6eCJuNDTmH09nDpbc= +github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.7.0/go.mod h1:9kIvujWAA58nmPmWB1m23fyWic1kYZMxD9CxaWn4Qpg= +github.com/Azure/azure-sdk-for-go/sdk/internal v1.10.0 h1:ywEEhmNahHBihViHepv3xPBn1663uRv2t2q/ESv9seY= +github.com/Azure/azure-sdk-for-go/sdk/internal v1.10.0/go.mod h1:iZDifYGJTIgIIkYRNWPENUnqx6bJ2xnSDFI2tjwZNuY= +github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v5 v5.7.0 h1:LkHbJbgF3YyvC53aqYGR+wWQDn2Rdp9AQdGndf9QvY4= +github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v5 v5.7.0/go.mod h1:QyiQdW4f4/BIfB8ZutZ2s+28RAgfa/pT+zS++ZHyM1I= +github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork/v4 v4.3.0 h1:bXwSugBiSbgtz7rOtbfGf+woewp4f06orW9OP5BjHLA= +github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork/v4 v4.3.0/go.mod h1:Y/HgrePTmGy9HjdSGTqZNa+apUpTVIEVKXJyARP2lrk= github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 h1:L/gRVlceqvL25UVaW/CKtUDjefjrs0SPonmDGUVOYP0= github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358 h1:mFRzDkZVAjdal+s7s0MwaRv9igoPqLRdzOLzw/8Xvq8= github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358/go.mod h1:chxPXzSsl7ZWRAuOIE23GDNzjWuZquvFlgA8xmpunjU= +github.com/AzureAD/microsoft-authentication-library-for-go v1.2.2 h1:XHOnouVk1mxXfQidrMEnLlPk9UMeRtyBTnEFtxkV0kU= +github.com/AzureAD/microsoft-authentication-library-for-go v1.2.2/go.mod h1:wP83P5OoQ5p6ip3ScPr0BAq0BvuPAvacpEuSzyouqAI= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/ChainSafe/go-schnorrkel v1.0.0 h1:3aDA67lAykLaG1y3AOjs88dMxC88PgUuHRrLeDnvGIM= github.com/ChainSafe/go-schnorrkel v1.0.0/go.mod h1:dpzHYVxLZcp8pjlV+O+UR8K0Hp/z7vcchBSbMBEhCw4= +github.com/Code-Hex/go-generics-cache v1.5.1 h1:6vhZGc5M7Y/YD8cIUcY8kcuQLB4cHR7U+0KMqAA0KcU= +github.com/Code-Hex/go-generics-cache v1.5.1/go.mod h1:qxcC9kRVrct9rHeiYpFWSoW1vxyillCVzX13KZG8dl4= github.com/CosmWasm/wasmd v0.40.1 h1:LxbO78t/6S8TkeQlUrJ0m5O87HtAwLx4RGHq3rdrOEU= github.com/CosmWasm/wasmd v0.40.1/go.mod h1:6EOwnv7MpuFaEqxcUOdFV9i4yvrdOciaY6VQ1o7A3yg= github.com/CosmWasm/wasmvm v1.2.4 h1:6OfeZuEcEH/9iqwrg2pkeVtDCkMoj9U6PpKtcrCyVrQ= @@ -108,9 +122,18 @@ github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.48 github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.48.3/go.mod h1:SsdWig2J5PMnfMvfJuEb1uZa8Y+kvNyvrULFo69gTFk= github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.48.3 h1:2vcVkrNdSMJpoOVAWi9ApsQR5iqNeFGt5Qx8Xlt3IoI= github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.48.3/go.mod h1:wRbFgBQUVm1YXrvWKofAEmq9HNJTDphbAaJSSX01KUI= +github.com/HdrHistogram/hdrhistogram-go v1.1.2 h1:5IcZpTvzydCQeHzK4Ef/D5rrSqwxob0t8PQPMybUNFM= +github.com/HdrHistogram/hdrhistogram-go v1.1.2/go.mod h1:yDgFjdqOqDEKOvasDdhWNXYg9BVp4O+o5f6V/ehm6Oo= +github.com/MakeNowJust/heredoc v1.0.0 h1:cXCdzVdstXyiTqTvfqk9SDHpKNjxuom+DOlyEeQ4pzQ= +github.com/MakeNowJust/heredoc v1.0.0/go.mod h1:mG5amYoWBHf8vpLOuehzbGGw0EHxpZZ6lCpQ4fNJ8LE= +github.com/Masterminds/goutils v1.1.1 h1:5nUrii3FMTL5diU80unEVvNevw1nH4+ZV4DSLVJLSYI= +github.com/Masterminds/goutils v1.1.1/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU= github.com/Masterminds/semver/v3 v3.1.1/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs= +github.com/Masterminds/semver/v3 v3.2.0/go.mod h1:qvl/7zhW3nngYb5+80sSMF+FG2BjYrf8m9wsX0PNOMQ= github.com/Masterminds/semver/v3 v3.3.0 h1:B8LGeaivUe71a5qox1ICM/JLl0NqZSW5CHyL+hmvYS0= github.com/Masterminds/semver/v3 v3.3.0/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM= +github.com/Masterminds/sprig/v3 v3.2.3 h1:eL2fZNezLomi0uOLqjQoN6BfsDD+fyLtgbJMAj9n6YA= +github.com/Masterminds/sprig/v3 v3.2.3/go.mod h1:rXcFaZ2zZbLRJv/xSysmlgIM1u11eBaRMhvYXJNkGuM= github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY= github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU= github.com/NethermindEth/juno v0.3.1 h1:AW72LiAm9gqUeCVJWvepnZcTnpU4Vkl0KzPMxS+42FA= @@ -126,6 +149,8 @@ github.com/VictoriaMetrics/fastcache v1.12.2 h1:N0y9ASrJ0F6h0QaC3o6uJb3NIZ9VKLjC github.com/VictoriaMetrics/fastcache v1.12.2/go.mod h1:AmC+Nzz1+3G2eCPapF6UcsnkThDcMsQicp4xDukwJYI= github.com/VividCortex/gohistogram v1.0.0 h1:6+hBz+qvs0JOrrNhhmR7lFxo5sINxBCGXrdtl/UvroE= github.com/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/4+TcAqDqk/vUH7g= +github.com/Workiva/go-datastructures v1.1.0 h1:hu20UpgZneBhQ3ZvwiOGlqJSKIosin2Rd5wAKUHEO/k= +github.com/Workiva/go-datastructures v1.1.0/go.mod h1:1yZL+zfsztete+ePzZz/Zb1/t5BnDuE2Ya2MMGhzP6A= github.com/XSAM/otelsql v0.27.0 h1:i9xtxtdcqXV768a5C6SoT/RkG+ue3JTOgkYInzlTOqs= github.com/XSAM/otelsql v0.27.0/go.mod h1:0mFB3TvLa7NCuhm/2nU7/b2wEtsczkj8Rey8ygO7V+A= github.com/akavel/rsrc v0.8.0/go.mod h1:uLoCtb9J+EyAqh+26kdrTgmzRBFPGOolLWKpdxkKq+c= @@ -133,17 +158,23 @@ github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuy github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= +github.com/alecthomas/units v0.0.0-20240626203959-61d1e3462e30 h1:t3eaIm0rUkzbrIewtiFmMK5RXHej2XnoXNhxVsAYUfg= +github.com/alecthomas/units v0.0.0-20240626203959-61d1e3462e30/go.mod h1:fvzegU4vN3H1qMT+8wDmzjAcDONcgo2/SZ/TyfdUOFs= github.com/alexbrainman/sspi v0.0.0-20210105120005-909beea2cc74 h1:Kk6a4nehpJ3UuJRqlA3JxYxBZEqCeOmATOvrbT4p9RA= github.com/alexbrainman/sspi v0.0.0-20210105120005-909beea2cc74/go.mod h1:cEWa1LVoE5KvSD9ONXsZrj0z6KqySlCCNKHlLzbqAt4= +github.com/alicebob/gopher-json v0.0.0-20200520072559-a9ecdc9d1d3a h1:HbKu58rmZpUGpz5+4FfNmIU+FmZg2P3Xaj2v2bfNWmk= +github.com/alicebob/gopher-json v0.0.0-20200520072559-a9ecdc9d1d3a/go.mod h1:SGnFV6hVsYE877CKEZ6tDNTjaSXYUk6QqoIK6PrAtcc= +github.com/alicebob/miniredis v2.5.0+incompatible h1:yBHoLpsyjupjz3NL3MhKMVkR41j82Yjf3KFv7ApYzUI= +github.com/alicebob/miniredis/v2 v2.30.4 h1:8S4/o1/KoUArAGbGwPxcwf0krlzceva2XVOSchFS7Eo= +github.com/alicebob/miniredis/v2 v2.30.4/go.mod h1:b25qWj4fCEsBeAAR2mlb0ufImGC6uH3VlUfb/HS5zKg= github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM= github.com/allegro/bigcache v1.2.1 h1:hg1sY1raCwic3Vnsvje6TT7/pnZba83LeFck5NrFKSc= github.com/allegro/bigcache v1.2.1/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM= github.com/andres-erbsen/clock v0.0.0-20160526145045-9e14626cd129/go.mod h1:rFgpPQZYZ8vdbc+48xibu8ALc3yeyd64IhHS+PU6Yyg= -github.com/andybalholm/brotli v1.1.1 h1:PR2pgnyFznKEugtsUo0xLdDop5SKXd5Qf5ysW+7XdTA= -github.com/andybalholm/brotli v1.1.1/go.mod h1:05ib4cKhjx3OQYUY22hTVd34Bc8upXjOLL2rKwwZBoA= +github.com/andybalholm/brotli v1.1.0 h1:eLKJA0d02Lf0mVpIDgYnqXcUn0GqVmEFny3VuID1U3M= +github.com/andybalholm/brotli v1.1.0/go.mod h1:sms7XGricyQI9K10gOSf56VKKWS4oLer58Q+mhRPtnY= github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= -github.com/apache/arrow-go/v18 v18.0.0 h1:1dBDaSbH3LtulTyOVYaBCHO3yVRwjV+TZaqn3g6V7ZM= -github.com/apache/arrow-go/v18 v18.0.0/go.mod h1:t6+cWRSmKgdQ6HsxisQjok+jBpKGhRDiqcf3p0p/F+A= github.com/appleboy/gofight/v2 v2.1.2 h1:VOy3jow4vIK8BRQJoC/I9muxyYlJ2yb9ht2hZoS3rf4= github.com/appleboy/gofight/v2 v2.1.2/go.mod h1:frW+U1QZEdDgixycTj4CygQ48yLTUhplt43+Wczp3rw= github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= @@ -152,16 +183,62 @@ github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmV github.com/armon/go-metrics v0.4.1 h1:hR91U9KYmb6bLBYLQjyM+3j+rcd/UhE+G78SFnF8gJA= github.com/armon/go-metrics v0.4.1/go.mod h1:E6amYzXo6aW1tqzoZGT755KkbgrJsSdpwZ+3JqfkOG4= github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= +github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= +github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= +github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= +github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 h1:DklsrG3dyBCFEj5IhUbnKptjxatkF07cF2ak3yi77so= +github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw= github.com/atombender/go-jsonschema v0.16.1-0.20240916205339-a74cd4e2851c h1:cxQVoh6kY+c4b0HUchHjGWBI8288VhH50qxKG3hdEg0= github.com/atombender/go-jsonschema v0.16.1-0.20240916205339-a74cd4e2851c/go.mod h1:3XzxudkrYVUvbduN/uI2fl4lSrMSzU0+3RCu2mpnfx8= +github.com/avast/retry-go v3.0.0+incompatible h1:4SOWQ7Qs+oroOTQOYnAHqelpCO0biHSxpiH9JdtuBj0= +github.com/avast/retry-go v3.0.0+incompatible/go.mod h1:XtSnn+n/sHqQIpZ10K1qAevBhOOCWBLXXy3hyiqqBrY= github.com/avast/retry-go/v4 v4.6.0 h1:K9xNA+KeB8HHc2aWFuLb25Offp+0iVRXEvFx8IinRJA= github.com/avast/retry-go/v4 v4.6.0/go.mod h1:gvWlPhBVsvBbLkVGDg/KwvBv0bEkCOLRRSHKIr2PyOE= +github.com/awalterschulze/gographviz v2.0.3+incompatible h1:9sVEXJBJLwGX7EQVhLm2elIKCm7P2YHFC8v6096G09E= +github.com/awalterschulze/gographviz v2.0.3+incompatible/go.mod h1:GEV5wmg4YquNw7v1kkyoX9etIk8yVmXj+AkDHuuETHs= github.com/aws/aws-sdk-go v1.22.1/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= github.com/aws/aws-sdk-go v1.23.20/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= +github.com/aws/aws-sdk-go v1.38.35/go.mod h1:hcU610XS61/+aQV88ixoOzUoG7v3b31pl2zKMmprdro= github.com/aws/aws-sdk-go v1.54.19 h1:tyWV+07jagrNiCcGRzRhdtVjQs7Vy41NwsuOcl0IbVI= github.com/aws/aws-sdk-go v1.54.19/go.mod h1:eRwEWoyTWFMVYVQzKMNHWP5/RV4xIUGMQfXQHfHkpNU= +github.com/aws/aws-sdk-go-v2 v1.32.2 h1:AkNLZEyYMLnx/Q/mSKkcMqwNFXMAvFto9bNsHqcTduI= +github.com/aws/aws-sdk-go-v2 v1.32.2/go.mod h1:2SK5n0a2karNTv5tbP1SjsX0uhttou00v/HpXKM1ZUo= +github.com/aws/aws-sdk-go-v2/config v1.28.0 h1:FosVYWcqEtWNxHn8gB/Vs6jOlNwSoyOCA/g/sxyySOQ= +github.com/aws/aws-sdk-go-v2/config v1.28.0/go.mod h1:pYhbtvg1siOOg8h5an77rXle9tVG8T+BWLWAo7cOukc= +github.com/aws/aws-sdk-go-v2/credentials v1.17.41 h1:7gXo+Axmp+R4Z+AK8YFQO0ZV3L0gizGINCOWxSLY9W8= +github.com/aws/aws-sdk-go-v2/credentials v1.17.41/go.mod h1:u4Eb8d3394YLubphT4jLEwN1rLNq2wFOlT6OuxFwPzU= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.17 h1:TMH3f/SCAWdNtXXVPPu5D6wrr4G5hI1rAxbcocKfC7Q= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.17/go.mod h1:1ZRXLdTpzdJb9fwTMXiLipENRxkGMTn1sfKexGllQCw= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.21 h1:UAsR3xA31QGf79WzpG/ixT9FZvQlh5HY1NRqSHBNOCk= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.21/go.mod h1:JNr43NFf5L9YaG3eKTm7HQzls9J+A9YYcGI5Quh1r2Y= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.21 h1:6jZVETqmYCadGFvrYEQfC5fAQmlo80CeL5psbno6r0s= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.21/go.mod h1:1SR0GbLlnN3QUmYaflZNiH1ql+1qrSiB2vwcJ+4UM60= +github.com/aws/aws-sdk-go-v2/internal/ini v1.8.1 h1:VaRN3TlFdd6KxX1x3ILT5ynH6HvKgqdiXoTxAF4HQcQ= +github.com/aws/aws-sdk-go-v2/internal/ini v1.8.1/go.mod h1:FbtygfRFze9usAadmnGJNc8KsP346kEe+y2/oyhGAGc= +github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.0 h1:TToQNkvGguu209puTojY/ozlqy2d/SFNcoLIqTFi42g= +github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.0/go.mod h1:0jp+ltwkf+SwG2fm/PKo8t4y8pJSgOCO4D8Lz3k0aHQ= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.2 h1:s7NA1SOw8q/5c0wr8477yOPp0z+uBaXBnLE0XYb0POA= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.2/go.mod h1:fnjjWyAW/Pj5HYOxl9LJqWtEwS7W2qgcRLWP+uWbss0= +github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.34.2 h1:Rrqru2wYkKQCS2IM5/JrgKUQIoNTqA6y/iuxkjzxC6M= +github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.34.2/go.mod h1:QuCURO98Sqee2AXmqDNxKXYFm2OEDAVAPApMqO0Vqnc= +github.com/aws/aws-sdk-go-v2/service/sso v1.24.2 h1:bSYXVyUzoTHoKalBmwaZxs97HU9DWWI3ehHSAMa7xOk= +github.com/aws/aws-sdk-go-v2/service/sso v1.24.2/go.mod h1:skMqY7JElusiOUjMJMOv1jJsP7YUg7DrhgqZZWuzu1U= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.28.2 h1:AhmO1fHINP9vFYUE0LHzCWg/LfUWUF+zFPEcY9QXb7o= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.28.2/go.mod h1:o8aQygT2+MVP0NaV6kbdE1YnnIM8RRVQzoeUH45GOdI= +github.com/aws/aws-sdk-go-v2/service/sts v1.32.2 h1:CiS7i0+FUe+/YY1GvIBLLrR/XNGZ4CtM1Ll0XavNuVo= +github.com/aws/aws-sdk-go-v2/service/sts v1.32.2/go.mod h1:HtaiBI8CjYoNVde8arShXb94UbQQi9L4EMr6D+xGBwo= +github.com/aws/constructs-go/constructs/v10 v10.4.2 h1:+hDLTsFGLJmKIn0Dg20vWpKBrVnFrEWYgTEY5UiTEG8= +github.com/aws/constructs-go/constructs/v10 v10.4.2/go.mod h1:cXsNCKDV+9eR9zYYfwy6QuE4uPFp6jsq6TtH1MwBx9w= +github.com/aws/jsii-runtime-go v1.104.0 h1:651Sh6J2FtatfnVzlOQ3/Ye1WWPAseZ6E/tSQxEKdSI= +github.com/aws/jsii-runtime-go v1.104.0/go.mod h1:7ZmQXxV0AAhhvv/GaHX4n6zbgA1tSRVdnQYAJbIhXHk= +github.com/aws/smithy-go v1.22.0 h1:uunKnWlcoL3zO7q+gG2Pk53joueEOsnNB28QdMsmiMM= +github.com/aws/smithy-go v1.22.0/go.mod h1:irrKGvNn1InZwb2d7fkIRNucdfwR8R+Ts3wxYa/cJHg= github.com/bahlo/generic-list-go v0.2.0 h1:5sz/EEAK+ls5wF+NeqDpk5+iNdMDXrh3z3nPnH1Wvgk= github.com/bahlo/generic-list-go v0.2.0/go.mod h1:2KvAjgMlE5NNynlg/5iLrrCCZ2+5xWbdbCW3pNTGyYg= +github.com/barkimedes/go-deepcopy v0.0.0-20220514131651-17c30cfc62df h1:GSoSVRLoBaFpOOds6QyY1L8AX7uoY+Ln3BHc22W40X0= +github.com/barkimedes/go-deepcopy v0.0.0-20220514131651-17c30cfc62df/go.mod h1:hiVxq5OP2bUGBRNS3Z/bt/reCLFNbdcST6gISi1fiOM= +github.com/bboreham/go-loser v0.0.0-20230920113527-fcc2c21820a3 h1:6df1vn4bBlDDo4tARvBm7l6KA9iVMnE3NWizDeWSrps= +github.com/bboreham/go-loser v0.0.0-20230920113527-fcc2c21820a3/go.mod h1:CIWtjkly68+yqLPbvwwR/fjNJA/idrtULjZWh2v1ys0= github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= github.com/benbjohnson/clock v1.3.5 h1:VvXlSJBzZpA/zum6Sj74hxwYI2DIxRWuNIoXAzHZz5o= github.com/benbjohnson/clock v1.3.5/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= @@ -177,26 +254,35 @@ github.com/bgentry/speakeasy v0.1.1-0.20220910012023-760eaf8b6816/go.mod h1:+zsy github.com/bits-and-blooms/bitset v1.13.0 h1:bAQ9OPNFYbGHV6Nez0tmNI0RiEu7/hxlYJRUA0wFAVE= github.com/bits-and-blooms/bitset v1.13.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8= github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84= -github.com/bketelsen/crypt v0.0.4/go.mod h1:aI6NrJ0pMGgvZKL1iVgXLnfIFJtfV+bKCoqOes/6LfM= +github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM= +github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ= github.com/blendle/zapdriver v1.3.1 h1:C3dydBOWYRiOk+B8X9IVZ5IOe+7cl+tGOexN4QqHfpE= github.com/blendle/zapdriver v1.3.1/go.mod h1:mdXfREi6u5MArG4j9fewC+FGnXaBR+T4Ox4J2u4eHCc= github.com/btcsuite/btcd v0.22.1 h1:CnwP9LM/M9xuRrGSCGeMVs9iv09uMqwsVX7EeIpgV2c= github.com/btcsuite/btcd/btcec/v2 v2.3.2 h1:5n0X6hX0Zk+6omWcihdYvdAlGf2DfasC0GMf7DClJ3U= github.com/btcsuite/btcd/btcec/v2 v2.3.2/go.mod h1:zYzJ8etWJQIv1Ogk7OzpWjowwOdXY1W/17j2MW85J04= -github.com/btcsuite/btcd/btcutil v1.1.5 h1:+wER79R5670vs/ZusMTF1yTcRYE5GUsFbdjdisflzM8= -github.com/btcsuite/btcd/btcutil v1.1.5/go.mod h1:PSZZ4UitpLBWzxGd5VGOrLnmOjtPP/a6HaFo12zMs00= -github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0 h1:59Kx4K6lzOW5w6nFlA0v5+lk/6sjybR934QNHSJZPTQ= -github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= +github.com/btcsuite/btcd/btcutil v1.1.3 h1:xfbtw8lwpp0G6NwSHb+UE67ryTFHJAiNuipusjXSohQ= +github.com/btcsuite/btcd/btcutil v1.1.3/go.mod h1:UR7dsSJzJUfMmFiiLlIrMq1lS9jh9EdCV7FStZSnpi0= +github.com/btcsuite/btcd/chaincfg/chainhash v1.0.3 h1:SDlJ7bAm4ewvrmZtR0DaiYbQGdKPeaaIm7bM+qRhFeU= +github.com/btcsuite/btcd/chaincfg/chainhash v1.0.3/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= github.com/bufbuild/protocompile v0.4.0 h1:LbFKd2XowZvQ/kajzguUp2DC9UEIQhIq77fZZlaQsNA= github.com/bufbuild/protocompile v0.4.0/go.mod h1:3v93+mbWn/v3xzN+31nwkJfrEpAUwp+BagBSZWx+TP8= github.com/buger/jsonparser v1.1.1 h1:2PnMjfWD7wBILjqQbt530v576A/cAbQvEW9gGIpYMUs= github.com/buger/jsonparser v1.1.1/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx27UK13J/0= +github.com/bxcodec/faker v2.0.1+incompatible h1:P0KUpUw5w6WJXwrPfv35oc91i4d8nf40Nwln+M/+faA= +github.com/bxcodec/faker v2.0.1+incompatible/go.mod h1:BNzfpVdTwnFJ6GtfYTcQu6l6rHShT+veBxNCnjCx5XM= github.com/bytecodealliance/wasmtime-go/v23 v23.0.0 h1:NJvU4S8KEk1GnF6+FvlnzMD/8wXTj/mYJSG6Q4yu3Pw= github.com/bytecodealliance/wasmtime-go/v23 v23.0.0/go.mod h1:5YIL+Ouiww2zpO7u+iZ1U1G5NvmwQYaXdmCZQGjQM0U= github.com/bytedance/sonic v1.11.6 h1:oUp34TzMlL+OY1OUWxHqsdkgC/Zfc85zGqw9siXjrc0= github.com/bytedance/sonic v1.11.6/go.mod h1:LysEHSvpvDySVdC2f87zGWf6CIKJcAvqab1ZaiQtds4= github.com/bytedance/sonic/loader v0.1.1 h1:c+e5Pt1k/cy5wMveRDyk2X4B9hF4g7an8N3zCYjJFNM= github.com/bytedance/sonic/loader v0.1.1/go.mod h1:ncP89zfokxS5LZrJxl5z0UJcsk4M4yY2JpfqGeCtNLU= +github.com/c2h5oh/datasize v0.0.0-20220606134207-859f65c6625b h1:6+ZFm0flnudZzdSE0JxlhR2hKnGPcNB35BjQf4RYQDY= +github.com/c2h5oh/datasize v0.0.0-20220606134207-859f65c6625b/go.mod h1:S/7n9copUssQ56c7aAgHqftWO4LTf4xY6CGWt8Bc+3M= +github.com/c9s/goprocinfo v0.0.0-20210130143923-c95fcf8c64a8 h1:SjZ2GvvOononHOpK84APFuMvxqsk3tEIaKH/z4Rpu3g= +github.com/c9s/goprocinfo v0.0.0-20210130143923-c95fcf8c64a8/go.mod h1:uEyr4WpAH4hio6LFriaPkL938XnrvLpNPmQHBdrmbIE= +github.com/cdk8s-team/cdk8s-core-go/cdk8s/v2 v2.7.5 h1:rvc39Ol6z3MvaBzXkxFC6Nfsnixq/dRypushKDd7Nc0= +github.com/cdk8s-team/cdk8s-core-go/cdk8s/v2 v2.7.5/go.mod h1:R/pdNYDYFQk+tuuOo7QES1kkv6OLmp5ze2XBZQIVffM= github.com/cenkalti/backoff v2.2.1+incompatible h1:tNowT99t7UNflLxfYYSlKYsBpXdEet03Pg2g16Swow4= github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM= github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= @@ -212,6 +298,10 @@ github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XL github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/chai2010/gettext-go v1.0.2 h1:1Lwwip6Q2QGsAdl/ZKPCwTe9fe0CjlUbqj5bFNSjIRk= +github.com/chai2010/gettext-go v1.0.2/go.mod h1:y+wnP2cHYaVj19NZhYKAwEMH2CI1gNHeQQ+5AjwawxA= +github.com/chaos-mesh/chaos-mesh/api v0.0.0-20240821051457-da69c6d9617a h1:6Pg3a6j/41QDzH/oYcMLwwKsf3x/HXcu9W/dBaf2Hzs= +github.com/chaos-mesh/chaos-mesh/api v0.0.0-20240821051457-da69c6d9617a/go.mod h1:x11iCbZV6hzzSQWMq610B6Wl5Lg1dhwqcVfeiWQQnQQ= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= github.com/chzyer/readline v1.5.1 h1:upd/6fQk4src78LMRzh5vItIt361/o4uq553V8B5sGI= @@ -225,7 +315,6 @@ github.com/cloudwego/base64x v0.1.4/go.mod h1:0zlkT4Wn5C6NdauXdJRhSKRlJvmclQ1hhJ github.com/cloudwego/iasm v0.2.0 h1:1KNIy1I1H9hNNFEEH3DVnI4UujN+1zjpuk6gwHLTssg= github.com/cloudwego/iasm v0.2.0/go.mod h1:8rXZaNYT2n95jn+zTI1sDr+IgcD2GVs0nlbbQPiEFhY= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= -github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cncf/xds/go v0.0.0-20240723142845-024c85f92f20 h1:N+3sFI5GUjRKBi+i0TxYVST9h4Ie192jJWpHvthBBgg= github.com/cncf/xds/go v0.0.0-20240723142845-024c85f92f20/go.mod h1:W+zGtBO5Y1IgJhy4+A9GOqVhqLpfZi+vwmdNXUehLA8= @@ -247,6 +336,8 @@ github.com/cockroachdb/redact v1.1.5 h1:u1PMllDkdFfPWaNGMyLD1+so+aq3uUItthCFqzwP github.com/cockroachdb/redact v1.1.5/go.mod h1:BVNblN9mBWFyMyqK1k3AAiSxhvhfK2oOZZ2lK+dpvRg= github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 h1:zuQyyAKVxetITBuuhv3BI9cMrmStnpT18zmgmTxunpo= github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06/go.mod h1:7nc4anLGjupUW/PeY5qiNYsdNXj7zopG+eqsS7To5IQ= +github.com/coder/websocket v1.8.12 h1:5bUXkEPPIbewrnkU8LTCLVaxi4N4J8ahufH2vlo4NAo= +github.com/coder/websocket v1.8.12/go.mod h1:LNVeNrXQZfe5qhS9ALED3uA+l5pPqvwXg3CKoDBB2gs= github.com/coinbase/rosetta-sdk-go/types v1.0.0 h1:jpVIwLcPoOeCR6o1tU+Xv7r5bMONNbHU7MuEHboiFuA= github.com/coinbase/rosetta-sdk-go/types v1.0.0/go.mod h1:eq7W2TMRH22GTW0N0beDnN931DW0/WOI1R2sdHNHG4c= github.com/cometbft/cometbft v0.37.5 h1:/U/TlgMh4NdnXNo+YU9T2NMCWyhXNDF34Mx582jlvq0= @@ -263,15 +354,20 @@ github.com/containerd/continuity v0.4.3 h1:6HVkalIp+2u1ZLH1J/pYX2oBVXlJZvh1X1A7b github.com/containerd/continuity v0.4.3/go.mod h1:F6PTNCKepoxEaXLQp3wDAjygEnImnZ/7o4JzpodfroQ= github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I= github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo= +github.com/containerd/platforms v0.2.1 h1:zvwtM3rz2YHPQsF2CHYM8+KtB5dvhISiXh5ZpSBQv6A= +github.com/containerd/platforms v0.2.1/go.mod h1:XHCb+2/hzowdiut9rkudds9bE5yJ7npe7dG/wG+uFPw= github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= github.com/coreos/etcd v3.3.13+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk= github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= +github.com/coreos/go-semver v0.3.1 h1:yi21YpKnrx1gt5R+la8n5WgS0kCrsPp33dmEyHReZr4= +github.com/coreos/go-semver v0.3.1/go.mod h1:irMmmIw/7yzSRPWryHsK7EYSg09caPQL03VsM8rvUec= github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= -github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= +github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs= +github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= github.com/cosmos/btcutil v1.0.5 h1:t+ZFcX77LpKtDBhjucvnOH8C2l2ioGsBNEQ3jef8xFk= github.com/cosmos/btcutil v1.0.5/go.mod h1:IyB7iuqZMJlthe2tkIFL33xPyzbFYP0XVdS8P5lUPis= @@ -296,6 +392,8 @@ github.com/cosmos/ledger-cosmos-go v0.12.4 h1:drvWt+GJP7Aiw550yeb3ON/zsrgW0jgh5s github.com/cosmos/ledger-cosmos-go v0.12.4/go.mod h1:fjfVWRf++Xkygt9wzCsjEBdjcf7wiiY35fv3ctT+k4M= github.com/cosmos/rosetta-sdk-go v0.10.0 h1:E5RhTruuoA7KTIXUcMicL76cffyeoyvNybzUGSKFTcM= github.com/cosmos/rosetta-sdk-go v0.10.0/go.mod h1:SImAZkb96YbwvoRkzSMQB6noNJXFgWl/ENIznEoYQI4= +github.com/cpuguy83/dockercfg v0.3.2 h1:DlJTyZGBDlXqUZ2Dk2Q3xHs/FtnooJJVaad2S9GKorA= +github.com/cpuguy83/dockercfg v0.3.2/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc= github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= @@ -310,6 +408,8 @@ github.com/creachadair/taskgroup v0.4.2 h1:jsBLdAJE42asreGss2xZGZ8fJra7WtwnHWeJF github.com/creachadair/taskgroup v0.4.2/go.mod h1:qiXUOSrbwAY3u0JPGTzObbE3yf9hcXHDKBZ2ZjpCbgM= github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= +github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= +github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= github.com/daaku/go.zipexe v1.0.0/go.mod h1:z8IiR6TsVLEYKwXAoE/I+8ys/sDkgTzSL0CLnGVd57E= github.com/danieljoos/wincred v1.1.2 h1:QLdCxFs1/Yl4zduvBdcHB8goaYk9RARS2SgLLRuAyr0= github.com/danieljoos/wincred v1.1.2/go.mod h1:GijpziifJoIBfYh+S7BbkdUTU4LfM+QnGqR5Vl2tAx0= @@ -326,7 +426,8 @@ github.com/decred/dcrd/crypto/blake256 v1.0.1 h1:7PltbUIQB7u/FfZ39+DGa/ShuMyJ5il github.com/decred/dcrd/crypto/blake256 v1.0.1/go.mod h1:2OfgNZ5wDpcsFmHmCK5gZTPcCXqlm2ArzUIkw9czNJo= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 h1:8UrgZ3GkP4i/CLijOJx79Yu+etlyjdBU4sfcs2WYQMs= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0/go.mod h1:v57UDF4pDQJcEfFUCRop3lJL149eHGSe9Jvczhzjo/0= -github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0/go.mod h1:v57UDF4pDQJcEfFUCRop3lJL149eHGSe9Jvczhzjo/0= +github.com/dennwc/varint v1.0.0 h1:kGNFFSSw8ToIy3obO/kKr8U9GZYUAxQEVuix4zfDWzE= +github.com/dennwc/varint v1.0.0/go.mod h1:hnItb35rvZvJrbTALZtY/iQfDs48JKRG1RPpgziApxA= github.com/desertbit/timer v0.0.0-20180107155436-c41aec40b27f h1:U5y3Y5UE0w7amNe7Z5G/twsBW0KEalRQXZzf8ufSh9I= github.com/desertbit/timer v0.0.0-20180107155436-c41aec40b27f/go.mod h1:xH/i4TFMt8koVQZ6WFms69WAsDWr2XsYL3Hkl7jkoLE= github.com/dfuse-io/logging v0.0.0-20201110202154-26697de88c79/go.mod h1:V+ED4kT/t/lKtH99JQmKIb0v9WL3VaYkJ36CfHlVECI= @@ -341,7 +442,11 @@ github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZm github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13 h1:fAjc9m62+UWV/WAFKLNi6ZS0675eEUC9y3AlwSbQu1Y= github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= +github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78= +github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc= github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= +github.com/digitalocean/godo v1.118.0 h1:lkzGFQmACrVCp7UqH1sAi4JK/PWwlc5aaxubgorKmC4= +github.com/digitalocean/godo v1.118.0/go.mod h1:Vk0vpCot2HOAJwc5WE8wljZGtJ3ZtWIc8MQ8rF38sdo= github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk= github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= github.com/docker/distribution v2.8.2+incompatible h1:T3de5rq0dB1j30rp0sA2rER+m322EBzniBPB6ZIzuh8= @@ -359,14 +464,14 @@ github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkp github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= github.com/dvsekhvalnov/jose2go v1.7.0 h1:bnQc8+GMnidJZA8zc6lLEAb4xNrIqHwO+9TzqvtQZPo= github.com/dvsekhvalnov/jose2go v1.7.0/go.mod h1:QsHjhyTlD/lAVqn/NSbVZmSCGeDehTB/mPZadG+mhXU= +github.com/edsrzf/mmap-go v1.1.0 h1:6EUwBLQ/Mcr1EYLE4Tn1VdW1A4ckqCQWZBw8Hr0kjpQ= +github.com/edsrzf/mmap-go v1.1.0/go.mod h1:19H/e8pUPLicwkyNgOykDXkJ9F0MHE+Z52B8EIth78Q= github.com/emicklei/go-restful/v3 v3.12.1 h1:PJMDIM/ak7btuL8Ex0iYET9hxM3CI2sjZtzpL63nKAU= github.com/emicklei/go-restful/v3 v3.12.1/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= -github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po= github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= -github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= github.com/envoyproxy/go-control-plane v0.13.0 h1:HzkeUz1Knt+3bK+8LG1bxOO/jzWZmdxpwC51i202les= github.com/envoyproxy/go-control-plane v0.13.0/go.mod h1:GRaKG3dwvFoTg4nj7aXdZnvMg4d7nvT/wl9WgVXn3Q8= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= @@ -380,6 +485,16 @@ github.com/ethereum/go-ethereum v1.14.11 h1:8nFDCUUE67rPc6AKxFj7JKaOa2W/W1Rse3oS github.com/ethereum/go-ethereum v1.14.11/go.mod h1:+l/fr42Mma+xBnhefL/+z11/hcmJ2egl+ScIVPjhc7E= github.com/ethereum/go-verkle v0.1.1-0.20240829091221-dffa7562dbe9 h1:8NfxH2iXvJ60YRB8ChToFTUzl8awsc3cJ8CbLjGIl/A= github.com/ethereum/go-verkle v0.1.1-0.20240829091221-dffa7562dbe9/go.mod h1:M3b90YRnzqKyyzBEWJGqj8Qff4IDeXnzFw0P9bFw3uk= +github.com/evanphx/json-patch v5.6.0+incompatible h1:jBYDEEiFBPxA0v50tFdvOzQQTCvpL6mnFh5mB2/l16U= +github.com/evanphx/json-patch v5.6.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= +github.com/evanphx/json-patch/v5 v5.9.0 h1:kcBlZQbplgElYIlo/n1hJbls2z/1awpXxpRi0/FOJfg= +github.com/evanphx/json-patch/v5 v5.9.0/go.mod h1:VNkHZ/282BpEyt/tObQO8s5CMPmYYq14uClGH4abBuQ= +github.com/exponent-io/jsonpath v0.0.0-20210407135951-1de76d718b3f h1:Wl78ApPPB2Wvf/TIe2xdyJxTlb6obmF18d8QdkxNDu4= +github.com/exponent-io/jsonpath v0.0.0-20210407135951-1de76d718b3f/go.mod h1:OSYXu++VVOHnXeitef/D8n/6y4QV8uLHSFXX4NeXMGc= +github.com/facette/natsort v0.0.0-20181210072756-2cd4dd1e2dcb h1:IT4JYU7k4ikYg1SCxNI1/Tieq/NFvh6dzLdgi7eu0tM= +github.com/facette/natsort v0.0.0-20181210072756-2cd4dd1e2dcb/go.mod h1:bH6Xx7IW64qjjJq8M2u4dxNaBiDfKK+z/3eGDpXEQhc= +github.com/fatih/camelcase v1.0.0 h1:hxNvNX/xYBp0ovncs8WyWZrOrpBNub/JfaMvbURyft8= +github.com/fatih/camelcase v1.0.0/go.mod h1:yN2Sb0lFhZJUdVvtELVWefmrXpuZESvPmqwoZc+/fpc= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU= github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= @@ -402,12 +517,10 @@ github.com/gabriel-vasile/mimetype v1.4.3 h1:in2uUcidCuFcDKtdcBxlR0rJ1+fsokWf+uq github.com/gabriel-vasile/mimetype v1.4.3/go.mod h1:d8uq/6HKRL6CGdk+aubisF/M5GcPfT7nKyLpA0lbSSk= github.com/gagliardetto/binary v0.7.7 h1:QZpT38+sgoPg+TIQjH94sLbl/vX+nlIRA37pEyOsjfY= github.com/gagliardetto/binary v0.7.7/go.mod h1:mUuay5LL8wFVnIlecHakSZMvcdqfs+CsotR5n77kyjM= -github.com/gagliardetto/binary v0.8.0/go.mod h1:2tfj51g5o9dnvsc+fL3Jxr22MuWzYXwx9wEoN0XQ7/c= github.com/gagliardetto/gofuzz v1.2.2 h1:XL/8qDMzcgvR4+CyRQW9UGdwPRPMHVJfqQ/uMvSUuQw= github.com/gagliardetto/gofuzz v1.2.2/go.mod h1:bkH/3hYLZrMLbfYWA0pWzXmi5TTRZnu4pMGZBkqMKvY= github.com/gagliardetto/solana-go v1.8.4 h1:vmD/JmTlonyXGy39bAo0inMhmbdAwV7rXZtLDMZeodE= github.com/gagliardetto/solana-go v1.8.4/go.mod h1:i+7aAyNDTHG0jK8GZIBSI4OVvDqkt2Qx+LklYclRNG8= -github.com/gagliardetto/solana-go v1.12.0/go.mod h1:l/qqqIN6qJJPtxW/G1PF4JtcE3Zg2vD2EliZrr9Gn5k= github.com/gagliardetto/treeout v0.1.4 h1:ozeYerrLCmCubo1TcIjFiOWTTGteOOHND1twdFpgwaw= github.com/gagliardetto/treeout v0.1.4/go.mod h1:loUefvXTrlRG5rYmJmExNryyBRh8f89VZhmMOyCyqok= github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08 h1:f6D9Hr8xV8uYKlyuj8XIruxlh9WjVjdh1gIicAS7ays= @@ -417,8 +530,8 @@ github.com/gedex/inflector v0.0.0-20170307190818-16278e9db813/go.mod h1:P+oSoE9y github.com/getsentry/sentry-go v0.27.0 h1:Pv98CIbtB3LkMWmXi4Joa5OOcwbmnX88sF5qbK3r3Ps= github.com/getsentry/sentry-go v0.27.0/go.mod h1:lc76E2QywIyW8WuBnwl8Lc4bkmQH4+w1gwTf25trprY= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= -github.com/gin-contrib/cors v1.7.2 h1:oLDHxdg8W/XDoN/8zamqk/Drgt4oVZDvaV0YmvVICQw= -github.com/gin-contrib/cors v1.7.2/go.mod h1:SUJVARKgQ40dmrzgXEVxj2m7Ig1v1qIboQkPDTQ9t2E= +github.com/gin-contrib/cors v1.5.0 h1:DgGKV7DDoOn36DFkNtbHrjoRiT5ExCe+PC9/xp7aKvk= +github.com/gin-contrib/cors v1.5.0/go.mod h1:TvU7MAZ3EwrPLI2ztzTt3tqgvBCq+wn8WpZmfADjupI= github.com/gin-contrib/expvar v0.0.1 h1:IuU5ArEgihz50vG8Onrwz22kJr7Mcvgv9xSSpfU5g+w= github.com/gin-contrib/expvar v0.0.1/go.mod h1:8o2CznfQi1JjktORdHr2/abg3wSV6OCnXh0yGypvvVw= github.com/gin-contrib/sessions v0.0.5 h1:CATtfHmLMQrMNpJRgzjWXD7worTh7g7ritsQfmF+0jE= @@ -467,15 +580,29 @@ github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= +github.com/go-logr/zapr v1.3.0 h1:XGdV8XW8zdwFiwOA2Dryh1gj2KRQyOOoNmBy4EplIcQ= +github.com/go-logr/zapr v1.3.0/go.mod h1:YKepepNBd1u/oyhd/yQmtjVXmm9uML4IXUgMOwR8/Gg= github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE= github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78= +github.com/go-openapi/analysis v0.22.2 h1:ZBmNoP2h5omLKr/srIC9bfqrUGzT6g6gNv03HE9Vpj0= +github.com/go-openapi/analysis v0.22.2/go.mod h1:pDF4UbZsQTo/oNuRfAWWd4dAh4yuYf//LYorPTjrpvo= +github.com/go-openapi/errors v0.22.0 h1:c4xY/OLxUBSTiepAg3j/MHuAv5mJhnf53LLMWFB+u/w= +github.com/go-openapi/errors v0.22.0/go.mod h1:J3DmZScxCDufmIMsdOuDHxJbdOGC0xtUynjIx092vXE= github.com/go-openapi/jsonpointer v0.21.0 h1:YgdVicSA9vH5RiHs9TZW5oyafXZFc6+2Vc1rr/O9oNQ= github.com/go-openapi/jsonpointer v0.21.0/go.mod h1:IUyH9l/+uyhIYQ/PXVA41Rexl+kOkAPDdXEYns6fzUY= github.com/go-openapi/jsonreference v0.21.0 h1:Rs+Y7hSXT83Jacb7kFyjn4ijOuVGSvOdF2+tg1TRrwQ= github.com/go-openapi/jsonreference v0.21.0/go.mod h1:LmZmgsrTkVg9LG4EaHeY8cBDslNPMo06cago5JNLkm4= +github.com/go-openapi/loads v0.21.5 h1:jDzF4dSoHw6ZFADCGltDb2lE4F6De7aWSpe+IcsRzT0= +github.com/go-openapi/loads v0.21.5/go.mod h1:PxTsnFBoBe+z89riT+wYt3prmSBP6GDAQh2l9H1Flz8= +github.com/go-openapi/spec v0.20.14 h1:7CBlRnw+mtjFGlPDRZmAMnq35cRzI91xj03HVyUi/Do= +github.com/go-openapi/spec v0.20.14/go.mod h1:8EOhTpBoFiask8rrgwbLC3zmJfz4zsCUueRuPM6GNkw= +github.com/go-openapi/strfmt v0.23.0 h1:nlUS6BCqcnAk0pyhi9Y+kdDVZdZMHfEKQiS4HaMgO/c= +github.com/go-openapi/strfmt v0.23.0/go.mod h1:NrtIpfKtWIygRkKVsxh7XQMDQW5HKQl6S5ik2elW+K4= github.com/go-openapi/swag v0.23.0 h1:vsEVJDUo2hPJ2tu0/Xc+4noaxyEffXNIs3cOULZ+GrE= github.com/go-openapi/swag v0.23.0/go.mod h1:esZ8ITTYEsH1V2trKHjAN8Ai7xHb8RV+YSZ577vPjgQ= +github.com/go-openapi/validate v0.23.0 h1:2l7PJLzCis4YUGEoW6eoQw3WhyM65WSIcjX6SQnlfDw= +github.com/go-openapi/validate v0.23.0/go.mod h1:EeiAZ5bmpSIOJV1WLfyYF9qp/B1ZgSaEpHTJHtN5cbE= github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s= github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= @@ -488,11 +615,15 @@ github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91 github.com/go-playground/validator/v10 v10.10.0/go.mod h1:74x4gJWsvQexRdW8Pn3dXSGrTK4nAUsbPlLADvpJkos= github.com/go-playground/validator/v10 v10.22.0 h1:k6HsTZ0sTnROkhS//R0O+55JgM8C4Bx7ia+JlgcnOao= github.com/go-playground/validator/v10 v10.22.0/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM= +github.com/go-redis/redis/v8 v8.11.5 h1:AcZZR7igkdvfVmQTPnu9WE37LRrO/YrBH5zWyjDC0oI= +github.com/go-redis/redis/v8 v8.11.5/go.mod h1:gREzHqY1hg6oD9ngVRbLStwAWKhA0FEgq8Jd4h5lpwo= +github.com/go-resty/resty/v2 v2.15.3 h1:bqff+hcqAflpiF591hhJzNdkRsFhlB96CYfBwSFvql8= +github.com/go-resty/resty/v2 v2.15.3/go.mod h1:0fHAoK7JoBy/Ch36N8VFeMsK7xQOHhvWaC3iOktwmIU= github.com/go-sql-driver/mysql v1.8.1 h1:LedoTUt/eveggdHS9qUFC1EFSa8bU2+1pZjSRpvNJ1Y= github.com/go-sql-driver/mysql v1.8.1/go.mod h1:wEBSXgmK//2ZFJyE+qWnIsVGmvmEKlqwuVSjsCm7DZg= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= -github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 h1:p104kn46Q8WdvHunIJ9dAyjPVtrBPhSr3KT2yUst43I= github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= +github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI= github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI= github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8= github.com/go-viper/mapstructure/v2 v2.1.0 h1:gHnMa2Y/pIxElCH2GlZZ1lZSsn6XMtufpGyP1XxdC/w= @@ -501,9 +632,11 @@ github.com/go-webauthn/webauthn v0.9.4 h1:YxvHSqgUyc5AK2pZbqkWWR55qKeDPhP8zLDr6l github.com/go-webauthn/webauthn v0.9.4/go.mod h1:LqupCtzSef38FcxzaklmOn7AykGKhAhr9xlRbdbgnTw= github.com/go-webauthn/x v0.1.5 h1:V2TCzDU2TGLd0kSZOXdrqDVV5JB9ILnKxA9S53CSBw0= github.com/go-webauthn/x v0.1.5/go.mod h1:qbzWwcFcv4rTwtCLOZd+icnr6B7oSsAGZJqlt8cukqY= +github.com/go-zookeeper/zk v1.0.3 h1:7M2kwOsc//9VeeFiPtf+uSJlVpU66x9Ba5+8XK7/TDg= +github.com/go-zookeeper/zk v1.0.3/go.mod h1:nOB03cncLtlp4t+UAkGSV+9beXP/akpekBwL+UX1Qcw= github.com/goccy/go-json v0.9.7/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= -github.com/goccy/go-json v0.10.3 h1:KZ5WoDbxAIgm2HNbYckL0se1fHD6rz5j4ywS6ebzDqA= -github.com/goccy/go-json v0.10.3/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M= +github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU= +github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= github.com/goccy/go-yaml v1.12.0 h1:/1WHjnMsI1dlIBQutrvSMGZRQufVO3asrHfTwfACoPM= github.com/goccy/go-yaml v1.12.0/go.mod h1:wKnAMd44+9JAAnGQpWVEgBzGt3YuTaQ4uXoHvE4m7WU= github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2 h1:ZpnhV/YsD2/4cESfV5+Hoeu/iUR3ruzNvZ+yQfO03a0= @@ -514,8 +647,11 @@ github.com/gofrs/flock v0.8.1/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14j github.com/gofrs/uuid v4.0.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= github.com/gofrs/uuid v4.4.0+incompatible h1:3qXRTX8/NbyulANqlc0lchS1gqAVxRgsuW1YrTJupqA= github.com/gofrs/uuid v4.4.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= +github.com/gogo/googleapis v0.0.0-20180223154316-0cd9801be74a/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s= github.com/gogo/googleapis v1.4.1 h1:1Yx4Myt7BxzvUr5ldGSbwYiZG6t9wGBZ+8/fX3Wvtq0= github.com/gogo/googleapis v1.4.1/go.mod h1:2lpHqI5OcWCtVElxXnPt+s8oJvMpySlOyM6xDCrzib4= +github.com/gogo/status v1.1.1 h1:DuHXlSFHNKqTQ+/ACf5Vs6r4X/dH2EgIzR9Vr+H65kg= +github.com/gogo/status v1.1.1/go.mod h1:jpG3dM5QPcqu19Hg8lkUhBFBa3TcLs1DG7+2Jqci7oU= github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg= github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= github.com/golang-jwt/jwt/v5 v5.2.1 h1:OuVbFODueb089Lh128TAcimifWaLhJwVflnrgM17wHk= @@ -536,7 +672,6 @@ github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= -github.com/golang/mock v1.5.0/go.mod h1:CWnOUgYIOo4TcNZ0wHX3YZCqsaM1I1Jvs6v3mP3KVu8= github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc= github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= @@ -568,8 +703,6 @@ github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Z github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.1.2 h1:xf4v41cLI2Z6FxbKm+8Bu+m8ifhj15JuZ9sa0jZCMUU= github.com/google/btree v1.1.2/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4= -github.com/google/flatbuffers v24.3.25+incompatible h1:CX395cjN9Kke9mmalRoL3d81AtFUxJM+yDthflgJGkI= -github.com/google/flatbuffers v24.3.25+incompatible/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8= github.com/google/gnostic-models v0.6.9-0.20230804172637-c7be7c783f49 h1:0VpGH+cDhbDtdcweoyCVsF3fhN8kejK6rFe/2FFX2nU= github.com/google/gnostic-models v0.6.9-0.20230804172637-c7be7c783f49/go.mod h1:BkkQ4L1KS1xMt2aWSPStnn55ChGC0DPOn2FQYj+f25M= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= @@ -588,6 +721,10 @@ github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8 github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-github/v41 v41.0.0 h1:HseJrM2JFf2vfiZJ8anY2hqBjdfY1Vlj/K27ueww4gg= +github.com/google/go-github/v41 v41.0.0/go.mod h1:XgmCA5H323A9rtgExdTcnDkcqp6S30AVACCBDOonIxg= +github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8= +github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU= github.com/google/go-tpm v0.9.0 h1:sQF6YqWMi+SCXpsmS3fd21oPy/vSddwZry4JnmltHVk= github.com/google/go-tpm v0.9.0/go.mod h1:FkNVkc6C+IsvDI9Jw1OveJmxGZUUaKxtrpOS47QWKfU= github.com/google/gofuzz v0.0.0-20170612174753-24818f796faf/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI= @@ -596,7 +733,6 @@ github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= -github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= github.com/google/orderedcode v0.0.1 h1:UzfcAexk9Vhv8+9pNOgRu41f16lHq725vPwnSeiG/Us= github.com/google/orderedcode v0.0.1/go.mod h1:iVyU4/qPKHY5h/wSd6rZZCDcLJNxiWO6dvsYES2Sb20= github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= @@ -606,17 +742,16 @@ github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hf github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20240827171923-fa2c70bbbfe5 h1:5iH8iuqE5apketRbSFBy+X1V0o+l+8NF1avt4HWl7cA= github.com/google/pprof v0.0.0-20240827171923-fa2c70bbbfe5/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/s2a-go v0.1.7 h1:60BLSyTrOV4/haCDW4zb1guZItoSq8foHCXrAnjBo/o= github.com/google/s2a-go v0.1.7/go.mod h1:50CgR4k1jNlWBu4UfS4AcfhVe1r6pdZPygJ3R8F0Qdw= +github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4= +github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ= github.com/google/subcommands v1.2.0/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk= +github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= @@ -627,8 +762,9 @@ github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+ github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= github.com/googleapis/gax-go/v2 v2.13.0 h1:yitjD5f7jQHhyDsnhKEBU52NdvvdSeGzlAnDPT0hH1s= github.com/googleapis/gax-go/v2 v2.13.0/go.mod h1:Z/fvTZXF8/uw7Xu5GuslPw+bplx6SS338j1Is2S+B7A= +github.com/gophercloud/gophercloud v1.13.0 h1:8iY9d1DAbzMW6Vok1AxbbK5ZaUjzMp0tdyt4fX9IeJ0= +github.com/gophercloud/gophercloud v1.13.0/go.mod h1:aAVqcocTSXh2vYFZ1JTvx4EQmfgzxRcNupUfxZbBNDM= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= -github.com/gopherjs/gopherjs v1.17.2/go.mod h1:pRRIvn/QzFLrKfvEz3qUuEhtE/zLCWfreZ6J5gM2i+k= github.com/gorilla/context v1.1.1 h1:AWwleXJkX/nhcU9bZSnZoi3h/qGYqQAGhq6zZe/aQW8= github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= github.com/gorilla/handlers v1.5.1 h1:9lRY6j8DEeeBT10CvO9hGW0gmky0BprnvDI5vfhUHH4= @@ -643,14 +779,28 @@ github.com/gorilla/sessions v1.2.2/go.mod h1:ePLdVu+jbEgHH+KWw8I1z2wqd0BAdAQh/8L github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY= github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY= +github.com/grafana/dskit v0.0.0-20231120170505-765e343eda4f h1:gyojr97YeWZ70pKNakWv5/tKwBHuLy3icnIeCo9gQr4= +github.com/grafana/dskit v0.0.0-20231120170505-765e343eda4f/go.mod h1:8dsy5tQOkeNQyjXpm5mQsbCu3H5uzeBD35MzRQFznKU= +github.com/grafana/gomemcache v0.0.0-20231023152154-6947259a0586 h1:/of8Z8taCPftShATouOrBVy6GaTTjgQd/VfNiZp/VXQ= +github.com/grafana/gomemcache v0.0.0-20231023152154-6947259a0586/go.mod h1:PGk3RjYHpxMM8HFPhKKo+vve3DdlPUELZLSDEFehPuU= +github.com/grafana/grafana-foundation-sdk/go v0.0.0-20240326122733-6f96a993222b h1:Msqs1nc2qWMxTriDCITKl58Td+7Md/RURmUmH7RXKns= +github.com/grafana/grafana-foundation-sdk/go v0.0.0-20240326122733-6f96a993222b/go.mod h1:WtWosval1KCZP9BGa42b8aVoJmVXSg0EvQXi9LDSVZQ= +github.com/grafana/loki v1.6.2-0.20231215164305-b51b7d7b5503 h1:gdrsYbmk8822v6qvPwZO5DC6QjnAW7uKJ9YXnoUmV8c= +github.com/grafana/loki v1.6.2-0.20231215164305-b51b7d7b5503/go.mod h1:d8seWXCEXkL42mhuIJYcGi6DxfehzoIpLrMQWJojvOo= +github.com/grafana/loki/pkg/push v0.0.0-20231201111602-11ef833ed3e4 h1:wQ0FnSeebhJIBkgYOD06Mxk9HV2KhtEG0hp/7R+5RUQ= +github.com/grafana/loki/pkg/push v0.0.0-20231201111602-11ef833ed3e4/go.mod h1:f3JSoxBTPXX5ec4FxxeC19nTBSxoTz+cBgS3cYLMcr0= github.com/grafana/pyroscope-go v1.1.2 h1:7vCfdORYQMCxIzI3NlYAs3FcBP760+gWuYWOyiVyYx8= github.com/grafana/pyroscope-go v1.1.2/go.mod h1:HSSmHo2KRn6FasBA4vK7BMiQqyQq8KSuBKvrhkXxYPU= github.com/grafana/pyroscope-go/godeltaprof v0.1.8 h1:iwOtYXeeVSAeYefJNaxDytgjKtUuKQbJqgAIjlnicKg= github.com/grafana/pyroscope-go/godeltaprof v0.1.8/go.mod h1:2+l7K7twW49Ct4wFluZD3tZ6e0SjanjcUUBPVD/UuGU= +github.com/grafana/regexp v0.0.0-20240518133315-a468a5bfb3bc h1:GN2Lv3MGO7AS6PrRoT6yV5+wkrOpcszoIsO4+4ds248= +github.com/grafana/regexp v0.0.0-20240518133315-a468a5bfb3bc/go.mod h1:+JKpmjMGhpgPL+rXZ5nsZieVzvarn86asRlBg4uNGnk= github.com/graph-gophers/dataloader v5.0.0+incompatible h1:R+yjsbrNq1Mo3aPG+Z/EKYrXrXXUNJHOgbRt+U6jOug= github.com/graph-gophers/dataloader v5.0.0+incompatible/go.mod h1:jk4jk0c5ZISbKaMe8WsVopGB5/15GvGHMdMdPtwlRp4= github.com/graph-gophers/graphql-go v1.5.0 h1:fDqblo50TEpD0LY7RXk/LFVYEVqo3+tXMNMPSVXA1yc= github.com/graph-gophers/graphql-go v1.5.0/go.mod h1:YtmJZDLbF1YYNrlNAuiO5zAStUWc3XZT07iGsVqe1Os= +github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79 h1:+ngKgrYPPJrOjhax5N+uePQ0Fh1Z7PheYoUI/0nzkPA= +github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 h1:+9834+KizmvFV7pXQGSXQTsaWhq2GjuNUt0aUU0YBYw= github.com/grpc-ecosystem/go-grpc-middleware v1.3.0/go.mod h1:z0ButlSOZa5vEBq9m2m2hlwIgKw+rp3sdCBRoJY+30Y= @@ -664,6 +814,7 @@ github.com/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4 github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= github.com/grpc-ecosystem/grpc-gateway/v2 v2.22.0 h1:asbCHRVmodnJTuQ3qamDwqVOIjwqUPTYmYuemVOx+Ys= github.com/grpc-ecosystem/grpc-gateway/v2 v2.22.0/go.mod h1:ggCgvZ2r7uOoQjOyu2Y1NhHmEPPzzuhWgcza5M1Ji1I= +github.com/grpc-ecosystem/grpc-opentracing v0.0.0-20180507213350-8e809c8a8645/go.mod h1:6iZfnjpejD4L/4DwD7NryNaJyCQdzwWwH2MWhCA90Kw= github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c h1:6rhixN/i8ZofjG1Y75iExal34USq5p+wiN1tpie8IrU= github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c/go.mod h1:NMPJylDgVpX0MLRlPy15sqSwOFv/U1GZ2m21JhFfek0= github.com/gtank/merlin v0.1.1-0.20191105220539-8318aed1a79f/go.mod h1:T86dnYJhcGOh5BjZFCJWTDeTK7XW8uE+E21Cy/bIQ+s= @@ -672,10 +823,18 @@ github.com/gtank/merlin v0.1.1/go.mod h1:T86dnYJhcGOh5BjZFCJWTDeTK7XW8uE+E21Cy/b github.com/gtank/ristretto255 v0.1.2 h1:JEqUCPA1NvLq5DwYtuzigd7ss8fwbYay9fi4/5uMzcc= github.com/gtank/ristretto255 v0.1.2/go.mod h1:Ph5OpO6c7xKUGROZfWVLiJf9icMDwUeIvY4OmlYW69o= github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q= +github.com/hashicorp/consul/api v1.29.2 h1:aYyRn8EdE2mSfG14S1+L9Qkjtz8RzmaWh6AcNGRNwPw= +github.com/hashicorp/consul/api v1.29.2/go.mod h1:0YObcaLNDSbtlgzIRtmRXI1ZkeuK0trCBxwZQ4MYnIk= +github.com/hashicorp/consul/proto-public v0.6.2 h1:+DA/3g/IiKlJZb88NBn0ZgXrxJp2NlvCZdEyl+qxvL0= +github.com/hashicorp/consul/proto-public v0.6.2/go.mod h1:cXXbOg74KBNGajC+o8RlA502Esf0R9prcoJgiOX/2Tg= github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= github.com/hashicorp/consul/sdk v0.16.1 h1:V8TxTnImoPD5cj0U9Spl0TUxcytjcbbJeADFF07KdHg= github.com/hashicorp/consul/sdk v0.16.1/go.mod h1:fSXvwxB2hmh1FMZCNl6PwX0Q/1wdWtHJcZ7Ea5tns0s= +github.com/hashicorp/cronexpr v1.1.2 h1:wG/ZYIKT+RT3QkOdgYc+xsKWVRgnxJ1OJtjjy84fJ9A= +github.com/hashicorp/cronexpr v1.1.2/go.mod h1:P4wA0KBl9C5q2hABiMO7cp6jcIg96CDh1Efb3g1PWA4= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I= +github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/go-bexpr v0.1.10 h1:9kuI5PFotCboP3dkDYFr/wi0gg0QVbSNz5oFRpxn4uE= github.com/hashicorp/go-bexpr v0.1.10/go.mod h1:oxlubA2vC/gFVfX1A6JGp7ls7uCDlfJn732ehYYg+g0= github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= @@ -692,16 +851,25 @@ github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjh github.com/hashicorp/go-immutable-radix v1.3.1 h1:DKHmCUm2hRBK510BaiZlwvpD40f8bJFeZnpfm2KLowc= github.com/hashicorp/go-immutable-radix v1.3.1/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= +github.com/hashicorp/go-msgpack v0.5.5 h1:i9R9JSrqIz0QVLz3sz+i3YJdT7TTSLcfLLzJi9aZTuI= +github.com/hashicorp/go-msgpack v0.5.5/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= +github.com/hashicorp/go-multierror v1.1.0/go.mod h1:spPvp8C1qA32ftKqdAHm4hHTbPw+vmowP0z+KUhOZdA= +github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= +github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= github.com/hashicorp/go-plugin v1.6.2 h1:zdGAEd0V1lCaU0u+MxWQhtSDQmahpkwOun8U8EiRVog= github.com/hashicorp/go-plugin v1.6.2/go.mod h1:CkgLQ5CZqNmdL9U9JzM532t8ZiYQ35+pj3b1FD37R0Q= github.com/hashicorp/go-retryablehttp v0.5.3/go.mod h1:9B5zBasrRhHXnJnui7y6sL7es7NDiJgTc6Er0maI1Xs= github.com/hashicorp/go-retryablehttp v0.7.7 h1:C8hUCYzor8PIfXHa4UrZkU4VvK8o9ISHxT2Q8+VepXU= github.com/hashicorp/go-retryablehttp v0.7.7/go.mod h1:pkQpWZeYWskR+D1tR2O5OcBFOxfA7DoAO6xtkuQnHTk= github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU= +github.com/hashicorp/go-rootcerts v1.0.2 h1:jzhAVGtqPKbwpyCPELlgNWhE1znq+qwJtW5Oi2viEzc= +github.com/hashicorp/go-rootcerts v1.0.2/go.mod h1:pqUvnprVnM5bf7AOirdbb01K4ccR319Vf4pU3K5EGc8= github.com/hashicorp/go-safetemp v1.0.0 h1:2HR189eFNrjHQyENnQMMpCiBAsRxzbTMIgBhEyExpmo= github.com/hashicorp/go-safetemp v1.0.0/go.mod h1:oaerMy3BhqiTbVye6QuFhFtIceqFoDHxNAB65b+Rj1I= github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU= +github.com/hashicorp/go-sockaddr v1.0.6 h1:RSG8rKU28VTUTvEKghe5gIhIQpv8evvNpnDEyqO4u9I= +github.com/hashicorp/go-sockaddr v1.0.6/go.mod h1:uoUUmtwU7n9Dv3O4SNLeFvg0SxQ3lyjsj6+CCykpaxI= github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4= github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= @@ -721,12 +889,21 @@ github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ= +github.com/hashicorp/mdns v1.0.4/go.mod h1:mtBihi+LeNXGtG8L9dX59gAEa12BDtBQSp4v/YAJqrc= github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= +github.com/hashicorp/memberlist v0.5.0 h1:EtYPN8DpAURiapus508I4n9CzHs2W+8NZGbmmR/prTM= +github.com/hashicorp/memberlist v0.5.0/go.mod h1:yvyXLpo0QaGE59Y7hDTsTzDD25JYBZ4mHgHUZ8lrOI0= +github.com/hashicorp/nomad/api v0.0.0-20240717122358-3d93bd3778f3 h1:fgVfQ4AC1avVOnu2cfms8VAiD8lUq3vWI8mTocOXN/w= +github.com/hashicorp/nomad/api v0.0.0-20240717122358-3d93bd3778f3/go.mod h1:svtxn6QnrQ69P23VvIWMR34tg3vmwLz4UdUzm1dSCgE= github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= +github.com/hashicorp/serf v0.10.1 h1:Z1H2J60yRKvfDYAOZLd2MU0ND4AH/WDz7xYHDWQsIPY= +github.com/hashicorp/serf v0.10.1/go.mod h1:yL2t6BqATOLGc5HF7qbFkTfXoPIY0WZdWHfEvMqbG+4= github.com/hashicorp/yamux v0.1.1 h1:yrQxtgseBDrq9Y652vSRDvsKCJKOUD+GzTS4Y0Y8pvE= github.com/hashicorp/yamux v0.1.1/go.mod h1:CtWFDAQgb7dxtzFs4tWbplKIe2jSi3+5vKbgIO0SLnQ= github.com/hdevalence/ed25519consensus v0.1.0 h1:jtBwzzcHuTmFrQN6xQZn6CQEO/V9f7HsjsjeEZ6auqU= github.com/hdevalence/ed25519consensus v0.1.0/go.mod h1:w3BHWjwJbFU29IRHL1Iqkw3sus+7FctEyM4RqDxYNzo= +github.com/hetznercloud/hcloud-go/v2 v2.10.2 h1:9gyTUPhfNbfbS40Spgij5mV5k37bOZgt8iHKCbfGs5I= +github.com/hetznercloud/hcloud-go/v2 v2.10.2/go.mod h1:xQ+8KhIS62W0D78Dpi57jsufWh844gUw1az5OUvaeq8= github.com/holiman/billy v0.0.0-20240216141850-2abb0c79d3c4 h1:X4egAf/gcS1zATw6wn4Ej8vjuVGxeHdan+bRb2ebyv4= github.com/holiman/billy v0.0.0-20240216141850-2abb0c79d3c4/go.mod h1:5GuXa7vkL8u9FkFuWdVvfR5ix8hRB7DbOAaYULamFpc= github.com/holiman/bloomfilter/v2 v2.0.3 h1:73e0e/V0tCydx14a0SCYS/EWCxgwLZ18CZcZKVu0fao= @@ -738,12 +915,16 @@ github.com/huandu/go-assert v1.1.5 h1:fjemmA7sSfYHJD7CUqs9qTwwfdNAx7/j2/ZlHXzNB3 github.com/huandu/go-assert v1.1.5/go.mod h1:yOLvuqZwmcHIC5rIzrBhT7D3Q9c3GFnd0JrPVhn/06U= github.com/huandu/skiplist v1.2.0 h1:gox56QD77HzSC0w+Ws3MH3iie755GBJU1OER3h5VsYw= github.com/huandu/skiplist v1.2.0/go.mod h1:7v3iFjLcSAzO4fN5B8dvebvo/qsfumiLiDXMrPiHF9w= +github.com/huandu/xstrings v1.3.3/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= +github.com/huandu/xstrings v1.4.0 h1:D17IlohoQq4UcpqD7fDk80P7l+lwAmlFaBHgOipl2FU= +github.com/huandu/xstrings v1.4.0/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= github.com/huin/goupnp v1.3.0 h1:UvLUlWDNpoUdYzb2TCn+MuTWtcjXKSza2n6CBdQ0xXc= github.com/huin/goupnp v1.3.0/go.mod h1:gnGPsThkYa7bFi/KWmEysQRf48l2dvR5bxr2OFckNX8= github.com/iancoleman/strcase v0.3.0 h1:nTXanmYxhfFAMjZL34Ov6gkzEsSJZ5DbhxWjvSASxEI= github.com/iancoleman/strcase v0.3.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= +github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= github.com/imdario/mergo v0.3.16 h1:wwQJbIsHYGMUyLSPrEq1CT16AhnhNJQ51+4fdHUnCl4= github.com/imdario/mergo v0.3.16/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+hD27ysY= github.com/improbable-eng/grpc-web v0.15.0 h1:BN+7z6uNXZ1tQGcNAuaU1YjsLTApzkjt2tzCixLaUPQ= @@ -753,6 +934,8 @@ github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2 github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/invopop/jsonschema v0.12.0 h1:6ovsNSuvn9wEQVOyc72aycBMVQFKz7cPdMJn10CvzRI= github.com/invopop/jsonschema v0.12.0/go.mod h1:ffZ5Km5SWWRAIN6wbDXItl95euhFz2uON45H2qjYt+0= +github.com/ionos-cloud/sdk-go/v6 v6.1.11 h1:J/uRN4UWO3wCyGOeDdMKv8LWRzKu6UIkLEaes38Kzh8= +github.com/ionos-cloud/sdk-go/v6 v6.1.11/go.mod h1:EzEgRIDxBELvfoa/uBN0kOQaqovLjUWEB7iW4/Q+t4k= github.com/jackc/chunkreader v1.0.0/go.mod h1:RT6O25fNZIuasFJRyZ4R/Y2BbhasbmZXF9QQ7T3kePo= github.com/jackc/chunkreader/v2 v2.0.0/go.mod h1:odVSm741yZoC3dpHEUXIqA9tQRhFrgOHwnPIn9lDKlk= github.com/jackc/chunkreader/v2 v2.0.1 h1:i+RDz65UE+mmpjTfyz0MoVTnzeYxroil2G82ki7MGG8= @@ -825,6 +1008,7 @@ github.com/jpillora/backoff v1.0.0 h1:uvFg412JmmHBHw7iwprIxkPMI+sGQ4kzOWsMeHnm2E github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= @@ -832,20 +1016,26 @@ github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1 github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= +github.com/julienschmidt/httprouter v1.3.0 h1:U0609e9tgbseu3rBINet9P48AI/D3oJs4dN7jwJOQ1U= +github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= +github.com/kelseyhightower/envconfig v1.4.0 h1:Im6hONhd3pLkfDFsbRgu68RDNkGF1r3dvMUtDTo2cv8= +github.com/kelseyhightower/envconfig v1.4.0/go.mod h1:cccZRl6mQpaq41TPp5QxidR+Sa3axMbJDNb//FQX6Gg= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/klauspost/compress v1.11.4/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= github.com/klauspost/compress v1.12.3/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg= github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= -github.com/klauspost/compress v1.17.11 h1:In6xLpyWOi1+C7tXUUWv2ot1QvBjxevKAaI6IXrJmUc= -github.com/klauspost/compress v1.17.11/go.mod h1:pMDklpSncoRMuLFrf1W9Ss9KT+0rH90U12bZKk7uwG0= +github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA= +github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= -github.com/klauspost/cpuid/v2 v2.2.8 h1:+StwCXwm9PdpiEkPyzBXIy+M9KUb4ODm0Zarf1kS5BM= -github.com/klauspost/cpuid/v2 v2.2.8/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws= +github.com/klauspost/cpuid/v2 v2.2.7 h1:ZWSB3igEs+d0qvnxR/ZBzXVmxkgt8DdzP6m9pfuVLDM= +github.com/klauspost/cpuid/v2 v2.2.7/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws= github.com/knz/go-libedit v1.10.1/go.mod h1:MZTVkCWyz0oBc7JOWP3wNAzd002ZbM/5hgShxwh4x8M= +github.com/kolo/xmlrpc v0.0.0-20220921171641-a4b6fa1dd06b h1:udzkj9S/zlT5X367kqJis0QP7YMxobob6zhzq6Yre00= +github.com/kolo/xmlrpc v0.0.0-20220921171641-a4b6fa1dd06b/go.mod h1:pcaDhQK0/NJZEvtCO0qQPPropqV0sJOJ6YW7X+9kRwM= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= +github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= @@ -859,8 +1049,8 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= -github.com/leanovate/gopter v0.2.11 h1:vRjThO1EKPb/1NsDXuDrzldR28RLkBflWYcU9CvzWu4= -github.com/leanovate/gopter v0.2.11/go.mod h1:aK3tzZP/C+p1m3SPRE4SYZFGP7jjkuSI4f7Xvpt0S9c= +github.com/leanovate/gopter v0.2.10-0.20210127095200-9abe2343507a h1:dHCfT5W7gghzPtfsW488uPmEOm85wewI+ypUwibyTdU= +github.com/leanovate/gopter v0.2.10-0.20210127095200-9abe2343507a/go.mod h1:U2L/78B+KVFIx2VmW6onHJQzXtFb+p5y3y2Sh+Jxxv8= github.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ictyFfxY= github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ= github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI= @@ -872,14 +1062,20 @@ github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw= github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/libp2p/go-buffer-pool v0.1.0 h1:oK4mSFcQz7cTQIfqbe4MIj9gLW+mnanjyFtc6cdF0Y8= github.com/libp2p/go-buffer-pool v0.1.0/go.mod h1:N+vh8gMqimBzdKkSMVuydVDq+UV5QTWy5HSiZacSbPg= +github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de h1:9TO3cAIGXtEhnIaL+V+BEER86oLrvS+kWobKpbJuye0= +github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de/go.mod h1:zAbeS9B/r2mtpb6U+EI2rYA5OAXxsYw6wTamcNW+zcE= +github.com/linode/linodego v1.37.0 h1:B/2Spzv9jYXzKA+p+GD8fVCNJ7Wuw6P91ZDD9eCkkso= +github.com/linode/linodego v1.37.0/go.mod h1:L7GXKFD3PoN2xSEtFc04wIXP5WK65O10jYQx0PQISWQ= github.com/linxGnu/grocksdb v1.7.16 h1:Q2co1xrpdkr5Hx3Fp+f+f7fRGhQFQhvi/+226dtLmA8= github.com/linxGnu/grocksdb v1.7.16/go.mod h1:JkS7pl5qWpGpuVb3bPqTz8nC12X3YtPZT+Xq7+QfQo4= +github.com/lithammer/dedent v1.1.0 h1:VNzHMVCBNG1j0fh3OrsFRkVUwStdDArbgBWoPAffktY= +github.com/lithammer/dedent v1.1.0/go.mod h1:jrXYCQtgg0nJiN+StA2KgR7w6CiQNv9Fd/Z9BP0jIOc= github.com/logrusorgru/aurora v2.0.3+incompatible h1:tOpm7WcpBTn4fjmVfgpQq0EfczGlG91VSDkswnjF5A8= github.com/logrusorgru/aurora v2.0.3+incompatible/go.mod h1:7rIyQOR62GCctdiQpZ/zOJlFyk6y+94wXzv6RNZgaR4= +github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ81pIr0yLvtUWk2if982qA3F3QD6H4= github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I= github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= -github.com/magiconair/properties v1.8.5/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= @@ -888,8 +1084,6 @@ github.com/manifoldco/promptui v0.9.0 h1:3V4HzJk1TtXW1MTZMP7mdlwbBpIinw3HztaIlYt github.com/manifoldco/promptui v0.9.0/go.mod h1:ka04sppxSGFAtxX0qhlYQjISsg9mR4GWtQEhdbn6Pgg= github.com/manyminds/api2go v0.0.0-20171030193247-e7b693844a6f h1:tVvGiZQFjOXP+9YyGqSA6jE55x1XVxmoPYudncxrZ8U= github.com/manyminds/api2go v0.0.0-20171030193247-e7b693844a6f/go.mod h1:Z60vy0EZVSu0bOugCHdcN5ZxFMKSpjRgsnh0XKPFqqk= -github.com/marcboeker/go-duckdb v1.8.3 h1:ZkYwiIZhbYsT6MmJsZ3UPTHrTZccDdM4ztoqSlEMXiQ= -github.com/marcboeker/go-duckdb v1.8.3/go.mod h1:C9bYRE1dPYb1hhfu/SSomm78B0FXmNgRvv6YBW/Hooc= github.com/maruel/natural v1.1.1 h1:Hja7XhhmvEFhcByqDoHz9QZbkWey+COd9xWfCfn1ioo= github.com/maruel/natural v1.1.1/go.mod h1:v+Rfd79xlw1AgVBjbO0BEQmptqb5HvL/k9GRHB7ZKEg= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= @@ -908,6 +1102,7 @@ github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOA github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= @@ -920,12 +1115,20 @@ github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5 github.com/mfridman/interpolate v0.0.2 h1:pnuTK7MQIxxFz1Gr+rjSIx9u7qVjf5VOoM/u6BbAxPY= github.com/mfridman/interpolate v0.0.2/go.mod h1:p+7uk6oE07mpE/Ik1b8EckO0O4ZXiGAfshKBWLUM9Xg= github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= +github.com/miekg/dns v1.1.26/go.mod h1:bPDLeHnStXmXAq1m/Ch/hvfNHr14JKNPMBo3VZKjuso= +github.com/miekg/dns v1.1.41/go.mod h1:p6aan82bvRIyn+zDIv9xYNUpwa73JcSh9BKwknJysuI= +github.com/miekg/dns v1.1.61 h1:nLxbwF3XxhwVSm8g9Dghm9MHPaUZuqhPiGL+675ZmEs= +github.com/miekg/dns v1.1.61/go.mod h1:mnAarhS3nWaW+NVP2wTkYVIZyHNJ098SJZUki3eykwQ= github.com/mimoo/StrobeGo v0.0.0-20181016162300-f8f6d4d2b643/go.mod h1:43+3pMjjKimDBf5Kr4ZFNGbLql1zKkbImw+fZbw3geM= github.com/mimoo/StrobeGo v0.0.0-20210601165009-122bf33a46e0 h1:QRUSJEgZn2Snx0EmT/QLXibWjSUDjKWvXIT19NBVp94= github.com/mimoo/StrobeGo v0.0.0-20210601165009-122bf33a46e0/go.mod h1:43+3pMjjKimDBf5Kr4ZFNGbLql1zKkbImw+fZbw3geM= github.com/minio/highwayhash v1.0.2 h1:Aak5U0nElisjDCfPSG79Tgzkn2gl66NxOMspRrKnA/g= github.com/minio/highwayhash v1.0.2/go.mod h1:BQskDq+xkJ12lmlUUi7U0M5Swg3EWR+dLTk+kldvVxY= github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= +github.com/mitchellh/cli v1.1.0/go.mod h1:xcISNoH86gajksDmfB23e/pu+B+GeFRMYmoHXxx3xhI= +github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw= +github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw= +github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s= github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= @@ -943,11 +1146,24 @@ github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyua github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/pointerstructure v1.2.0 h1:O+i9nHnXS3l/9Wu7r4NrEdwA2VFTicjUEN1uBnDo34A= github.com/mitchellh/pointerstructure v1.2.0/go.mod h1:BRAsLI5zgXmw97Lf6s25bs8ohIXc3tViBH44KcwB2g4= +github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= +github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ= +github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= github.com/mmcloughlin/addchain v0.4.0 h1:SobOdjm2xLj1KkXN5/n0xTIWyZA2+s99UCY1iPfkHRY= github.com/mmcloughlin/addchain v0.4.0/go.mod h1:A86O+tHqZLMNO4w6ZZ4FlVQEadcoqkyU72HC5wJ4RlU= github.com/mmcloughlin/profile v0.1.1/go.mod h1:IhHD7q1ooxgwTgjxQYkACGA77oFTDdFVejUS1/tS/qU= github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3Nl2EsFP0= github.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo= +github.com/moby/patternmatcher v0.6.0 h1:GmP9lR19aU5GqSSFko+5pRqHi+Ohk1O69aFiKkVGiPk= +github.com/moby/patternmatcher v0.6.0/go.mod h1:hDPoyOpDY7OrrMDLaYoY3hf52gNCR/YOUYxkhApJIxc= +github.com/moby/spdystream v0.4.0 h1:Vy79D6mHeJJjiPdFEL2yku1kl0chZpJfZcPpb16BRl8= +github.com/moby/spdystream v0.4.0/go.mod h1:xBAYlnt/ay+11ShkdFKNAG7LsyK/tmNBVvVOwrfMgdI= +github.com/moby/sys/sequential v0.6.0 h1:qrx7XFUd/5DxtqcoH1h438hF5TmOvzC/lspjy7zgvCU= +github.com/moby/sys/sequential v0.6.0/go.mod h1:uyv8EUTrca5PnDsdMGXhZe6CCe8U/UiTWd+lL+7b/Ko= +github.com/moby/sys/user v0.3.0 h1:9ni5DlcW5an3SvRSx4MouotOygvzaXbaSrc/wGDFWPo= +github.com/moby/sys/user v0.3.0/go.mod h1:bG+tYYYJgaMtRKgEmuueC0hJEAZWwtIbZTB+85uoHjs= +github.com/moby/sys/userns v0.1.0 h1:tVLXkFOxVu9A64/yh59slHVv9ahO9UIev4JZusOLG/g= +github.com/moby/sys/userns v0.1.0/go.mod h1:IHUYgu/kao6N8YZlp9Cf444ySSvCmDlmzUcYfDHOl28= github.com/moby/term v0.5.0 h1:xt8Q1nalod/v7BqbG21f8mQPqH+xAaC9C3N3wfWbVP0= github.com/moby/term v0.5.0/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3Y= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= @@ -957,6 +1173,8 @@ github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lN github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= +github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 h1:n6/2gBQ3RWajuToeY6ZtZTIKv2v7ThUy5KKusIT0yc0= +github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00/go.mod h1:Pm3mSP3c5uWn86xMLZ5Sa7JB9GsEZySvHYXCTK4E9q4= github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc= github.com/montanaflynn/stats v0.7.1 h1:etflOAAHORrCC44V+aR6Ftzort912ZU+YLiSTuV8eaE= github.com/montanaflynn/stats v0.7.1/go.mod h1:etXPPgVO6n31NxCd9KQUMvCM+ve0ruNzt6R8Bnaayow= @@ -971,10 +1189,12 @@ github.com/mtibben/percent v0.2.1/go.mod h1:KG9uO+SZkUp+VkRHsCdYQV3XSZrrSpR3O9ib github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= +github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f h1:KUppIJq7/+SVif2QVs3tOP0zanoHgBEVAwHxUSIzRqU= +github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= +github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f h1:y5//uYreIhSUg3J1GEMiLbxo1LJaP8RfCpH6pymGZus= +github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw= github.com/ncruces/go-strftime v0.1.9 h1:bY0MQC28UADQmHmaF5dgpLmImcShSi2kHU9XLdhx/f4= github.com/ncruces/go-strftime v0.1.9/go.mod h1:Fwc5htZGVVkseilnfgOVb9mKy6w1naJmn9CehxcKcls= -github.com/neelance/astrewrite v0.0.0-20160511093645-99348263ae86/go.mod h1:kHJEU3ofeGjhHklVoIGuVj85JJwZ6kWPaJwCIxgnFmo= -github.com/neelance/sourcemap v0.0.0-20200213170602-2833bce08e4c/go.mod h1:Qr6/a/Q4r9LP1IltGz7tA7iOK1WonHEYhu1HRBA7ZiM= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= github.com/nkovacs/streamquote v0.0.0-20170412213628-49af9bddb229/go.mod h1:0aYXnNPJ8l7uZxf45rWW1a/uME32OF0rhiYGNQ2oF2E= github.com/nsf/jsondiff v0.0.0-20230430225905-43f6cf3098c1 h1:dOYG7LS/WK00RWZc8XGgcUTlTxpp3mKhdR2Q9z9HbXM= @@ -984,6 +1204,7 @@ github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= github.com/oklog/run v1.1.0 h1:GEenZ1cK0+q0+wsJew9qUg/DyD8k3JzYsZAi5gYi2mA= github.com/oklog/run v1.1.0/go.mod h1:sVPdnTZT1zYwAJeCMu2Th4T21pA3FPOQRfWjQlk7DVU= +github.com/oklog/ulid v1.3.1 h1:EGfNDEx6MqHz8B3uNV6QAib1UR2Lm97sHi3ocA6ESJ4= github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= @@ -993,8 +1214,8 @@ github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vv github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU= github.com/onsi/ginkgo/v2 v2.1.3/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c= -github.com/onsi/ginkgo/v2 v2.20.1 h1:YlVIbqct+ZmnEph770q9Q7NVAz4wwIiVNahee6JyUzo= -github.com/onsi/ginkgo/v2 v2.20.1/go.mod h1:lG9ey2Z29hR41WMVthyJBGUBcBhGOtoPF2VFMvBXFCI= +github.com/onsi/ginkgo/v2 v2.19.0 h1:9Cnnf7UHo57Hy3k6/m5k3dRfGTMXGvxhHFvkDTCTpvA= +github.com/onsi/ginkgo/v2 v2.19.0/go.mod h1:rlwLi9PilAFJ8jCg9UE1QP6VBpd6/xj3SRC0d6TU0To= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= @@ -1007,36 +1228,50 @@ github.com/opencontainers/image-spec v1.1.0 h1:8SG7/vwALn54lVB/0yZ/MMwhFrPYtpEHQ github.com/opencontainers/image-spec v1.1.0/go.mod h1:W4s4sFTMaBeK1BQLXbG4AdM2szdn85PY75RI83NrTrM= github.com/opencontainers/runc v1.1.10 h1:EaL5WeO9lv9wmS6SASjszOeQdSctvpbu0DdBQBizE40= github.com/opencontainers/runc v1.1.10/go.mod h1:+/R6+KmDlh+hOO8NkjmgkG9Qzvypzk0yXxAPYYR65+M= +github.com/opentracing-contrib/go-grpc v0.0.0-20210225150812-73cb765af46e h1:4cPxUYdgaGzZIT5/j0IfqOrrXmq6bG8AwvwisMXpdrg= +github.com/opentracing-contrib/go-grpc v0.0.0-20210225150812-73cb765af46e/go.mod h1:DYR5Eij8rJl8h7gblRrOZ8g0kW1umSpKqYIBTgeDtLo= +github.com/opentracing-contrib/go-stdlib v1.0.0 h1:TBS7YuVotp8myLon4Pv7BtCBzOTo1DeZCld0Z63mW2w= +github.com/opentracing-contrib/go-stdlib v1.0.0/go.mod h1:qtI1ogk+2JhVPIXVc6q+NHziSmy2W5GbdQZFUHADCBU= github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= github.com/opentracing/opentracing-go v1.2.0 h1:uEJPy/1a5RIPAJ0Ov+OIO8OxWu77jEv+1B0VhjKrZUs= github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc= github.com/ory/dockertest v3.3.5+incompatible h1:iLLK6SQwIhcbrG783Dghaaa3WPzGc+4Emza6EbVUUGA= github.com/ory/dockertest v3.3.5+incompatible/go.mod h1:1vX4m9wsvi00u5bseYwXaSnhNrne+V0E6LAcBILJdPs= +github.com/otiai10/copy v1.14.0 h1:dCI/t1iTdYGtkvCuBG2BgR6KZa83PTclw4U5n2wAllU= +github.com/otiai10/copy v1.14.0/go.mod h1:ECfuL02W+/FkTWZWgQqXPWZgW9oeKCSQ5qVfSc4qc4w= +github.com/otiai10/mint v1.5.1 h1:XaPLeE+9vGbuyEHem1JNk3bYc7KKqyI/na0/mLd/Kks= +github.com/otiai10/mint v1.5.1/go.mod h1:MJm72SBthJjz8qhefc4z1PYEieWmy8Bku7CjcAqyUSM= +github.com/ovh/go-ovh v1.6.0 h1:ixLOwxQdzYDx296sXcgS35TOPEahJkpjMGtzPadCjQI= +github.com/ovh/go-ovh v1.6.0/go.mod h1:cTVDnl94z4tl8pP1uZ/8jlVxntjSIf09bNcQ5TJSC7c= github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/pascaldekloe/goe v0.1.0 h1:cBOtyMzM9HTpWjXfbbunk26uA6nG3a8n06Wieeh0MwY= github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/patrickmn/go-cache v2.1.0+incompatible h1:HRMgzkcYKYpi3C8ajMPV8OFXaaRUnok+kx1WdO15EQc= github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ= +github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58 h1:onHthvaw9LFnH4t2DcNVpwGmV9E1BkGknEliJkfwQj0= +github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58/go.mod h1:DXv8WO4yhMYhSNPKjeNKa5WY9YCIEBRbNzFFPJbWO6Y= github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= -github.com/pelletier/go-toml v1.9.3/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8= github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= github.com/pelletier/go-toml/v2 v2.0.1/go.mod h1:r9LEWfGN8R5k0VXJ+0BkIe7MYkRdwZOjgMj2KwnJFUo= github.com/pelletier/go-toml/v2 v2.2.3 h1:YmeHyLY8mFWbdkNWwpr+qIL2bEqT0o95WSdkNHvL12M= github.com/pelletier/go-toml/v2 v2.2.3/go.mod h1:MfCQTFTvCcUyyvvwm1+G6H/jORL20Xlb6rzQu9GuUkc= +github.com/peterbourgon/diskv v2.0.1+incompatible h1:UBdAOUP5p4RWqPBg048CAvpKN+vxiaj6gdUUzhl4XmI= +github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU= github.com/petermattis/goid v0.0.0-20180202154549-b0b1615b78e5/go.mod h1:jvVRKCrJTQWu0XVbaOlby/2lO20uSCHEMzzplHXte1o= github.com/petermattis/goid v0.0.0-20230317030725-371a4b8eda08 h1:hDSdbBuw3Lefr6R18ax0tZ2BJeNB3NehB3trOwYBsdU= github.com/petermattis/goid v0.0.0-20230317030725-371a4b8eda08/go.mod h1:pxMtw7cyUw6B2bRH0ZBANSPg+AoSud1I1iyJHI69jH4= -github.com/pierrec/lz4/v4 v4.1.21 h1:yOVMLb6qSIDP67pl/5F7RepeKYu/VmTyEXvuMI5d9mQ= -github.com/pierrec/lz4/v4 v4.1.21/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= +github.com/pierrec/lz4/v4 v4.1.18 h1:xaKrnTkyoqfh1YItXl56+6KJNVYWlEEPuAQW9xsplYQ= +github.com/pierrec/lz4/v4 v4.1.18/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= github.com/pingcap/errors v0.11.4 h1:lFuQV/oaUMGcD2tqt+01ROSmJs75VG1ToEOkZIZ4nE4= github.com/pingcap/errors v0.11.4/go.mod h1:Oi8TUi2kEtXXLMJk9l1cGmz20kV3TaQ0usTwv5KuLY8= +github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c h1:+mdjkGKdHQG3305AYmdv1U2eRNDiU2ErMBj1gwrq8eQ= +github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c/go.mod h1:7rwL4CYBLnjLxUqIJNnCWiEdr3bn6IUYi15bNlnbCCU= github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI= github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10 h1:GFCKgmp0tecUJ0sJuv4pzYCqS9+RGSn52M3FUwPs+uo= github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10/go.mod h1:t/avpk3KcrXxUnYOhZhMXJlSEyie6gQbtLq5NM3loB8= github.com/pmezard/go-difflib v0.0.0-20151028094244-d8ed2627bdf0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= @@ -1044,14 +1279,19 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN 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/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= +github.com/posener/complete v1.2.3/go.mod h1:WZIdtGGp+qx0sLrYKtIRAruyNpv6hFCicSgv7Sy7s/s= github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c h1:ncq/mPwQF4JjgDlrVEn3C11VoGHZN7m8qihwgMEtzYw= github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE= github.com/pressly/goose/v3 v3.21.1 h1:5SSAKKWej8LVVzNLuT6KIvP1eFDuPvxa+B6H0w78buQ= github.com/pressly/goose/v3 v3.21.1/go.mod h1:sqthmzV8PitchEkjecFJII//l43dLOCzfWh8pHEe+vE= +github.com/prometheus/alertmanager v0.27.0 h1:V6nTa2J5V4s8TG4C4HtrBP/WNSebCCTYGGv4qecA/+I= +github.com/prometheus/alertmanager v0.27.0/go.mod h1:8Ia/R3urPmbzJ8OsdvmZvIprDwvwmYCmUbwBL+jlPOE= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= +github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= +github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= github.com/prometheus/client_golang v1.20.5 h1:cxppBPuYhUnsO6yo/aoRol4L7q7UFfdm+bR9r+8l63Y= github.com/prometheus/client_golang v1.20.5/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= @@ -1064,12 +1304,21 @@ github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7q github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4= +github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= +github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc= +github.com/prometheus/common v0.29.0/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= github.com/prometheus/common v0.60.0 h1:+V9PAREWNvJMAuJ1x1BaWl9dewMW4YrHZQbx0sJNllA= github.com/prometheus/common v0.60.0/go.mod h1:h0LYf1R1deLSKtD4Vdg8gy4RuOvENW2J/h19V5NADQw= +github.com/prometheus/common/sigv4 v0.1.0 h1:qoVebwtwwEhS85Czm2dSROY5fTo2PAPEVdDeppTwGX4= +github.com/prometheus/common/sigv4 v0.1.0/go.mod h1:2Jkxxk9yYvCkE5G1sQT7GuEXm57JrvHu9k5YwTjsNtI= +github.com/prometheus/exporter-toolkit v0.11.0 h1:yNTsuZ0aNCNFQ3aFTD2uhPOvr4iD7fdBvKPAEGkNf+g= +github.com/prometheus/exporter-toolkit v0.11.0/go.mod h1:BVnENhnNecpwoTLiABx7mrPB/OLRIgN74qlQbV+FK1Q= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= +github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= +github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc= github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk= github.com/prometheus/prometheus v0.54.1 h1:vKuwQNjnYN2/mDoWfHXDhAsz/68q/dQDb+YbcEqU7MQ= @@ -1094,11 +1343,12 @@ github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFR github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE= github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= -github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII= -github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o= +github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= +github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= github.com/rs/cors v1.10.1 h1:L0uuZVXIKlI1SShY2nhFfo44TYvDPQ1w4oFkUJNfhyo= github.com/rs/cors v1.10.1/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU= github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ= +github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= github.com/rs/zerolog v1.13.0/go.mod h1:YbFCdg8HfsridGWAh22vktObvhZbQsZXe4/zB0OKkWU= github.com/rs/zerolog v1.15.0/go.mod h1:xYTKnLHcpfU2225ny5qZjxnj9NvkumZYjJHlAThCjNc= github.com/rs/zerolog v1.33.0 h1:1cU2KZkvPxNyfgEmhHAz/1A9Bz+llsdYzklWFzgp0r8= @@ -1119,58 +1369,70 @@ github.com/santhosh-tekuri/jsonschema/v5 v5.3.1/go.mod h1:uToXkOrWAZ6/Oc07xWQrPO github.com/sasha-s/go-deadlock v0.3.1 h1:sqv7fDNShgjcaxkO0JNcOAlr8B9+cV5Ey/OB71efZx0= github.com/sasha-s/go-deadlock v0.3.1/go.mod h1:F73l+cr82YSh10GxyRI6qZiCgK64VaZjwesgfQ1/iLM= github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= +github.com/scaleway/scaleway-sdk-go v1.0.0-beta.29 h1:BkTk4gynLjguayxrYxZoMZjBnAOh7ntQvUkOFmkMqPU= +github.com/scaleway/scaleway-sdk-go v1.0.0-beta.29/go.mod h1:fCa7OJZ/9DRTnOKmxvT6pn+LPWUptQAmHF/SBJUGEcg= github.com/scylladb/go-reflectx v1.0.1 h1:b917wZM7189pZdlND9PbIJ6NQxfDPfBvUaQ7cjj1iZQ= github.com/scylladb/go-reflectx v1.0.1/go.mod h1:rWnOfDIRWBGN0miMLIcoPt/Dhi2doCMZqwMCJ3KupFc= +github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529 h1:nn5Wsu0esKSJiIVhscUtVbo7ada43DJhG55ua/hjS5I= github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= +github.com/sercand/kuberesolver/v5 v5.1.1 h1:CYH+d67G0sGBj7q5wLK61yzqJJ8gLLC8aeprPTHb6yY= +github.com/sercand/kuberesolver/v5 v5.1.1/go.mod h1:Fs1KbKhVRnB2aDWN12NjKCB+RgYMWZJ294T3BtmVCpQ= +github.com/sergi/go-diff v1.2.0 h1:XU+rvMAioB0UC3q1MFrIQy4Vo5/4VsRDQQXHsEya6xQ= +github.com/sergi/go-diff v1.2.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= github.com/sethvargo/go-retry v0.2.4 h1:T+jHEQy/zKJf5s95UkguisicE0zuF9y7+/vgz08Ocec= github.com/sethvargo/go-retry v0.2.4/go.mod h1:1afjQuvh7s4gflMObvjLPaWgluLLyhA1wmVZ6KLpICw= github.com/shirou/gopsutil v3.21.11+incompatible h1:+1+c1VGhc88SSonWP6foOcLhvnKlUeu/erjjvaPEYiI= github.com/shirou/gopsutil v3.21.11+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= github.com/shirou/gopsutil/v3 v3.24.3 h1:eoUGJSmdfLzJ3mxIhmOAhgKEKgQkeOwKpz1NbhVnuPE= github.com/shirou/gopsutil/v3 v3.24.3/go.mod h1:JpND7O217xa72ewWz9zN2eIIkPWsDN/3pl0H8Qt0uwg= +github.com/shoenig/go-m1cpu v0.1.6 h1:nxdKQNcEB6vzgA2E2bvzKIYRuNj7XNJ4S/aRSwKzFtM= github.com/shoenig/go-m1cpu v0.1.6/go.mod h1:1JJMcUBvfNwpq05QDQVAnx3gUHr9IYF7GNg9SUEw2VQ= +github.com/shoenig/test v0.6.4 h1:kVTaSd7WLz5WZ2IaoM0RSzRsUD+m8wRR+5qvntpn4LU= github.com/shoenig/test v0.6.4/go.mod h1:byHiCGXqrVaflBLAMq/srcZIHynQPQgeyvkvXnjqq0k= github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24/go.mod h1:M+9NzErvs504Cn4c5DxATwIqPbtswREoFCre64PpcG4= github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= github.com/shopspring/decimal v1.3.1/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= github.com/shopspring/decimal v1.4.0 h1:bxl37RwXBklmTi0C79JfXCEBD1cqqHt0bbgBAGFp81k= github.com/shopspring/decimal v1.4.0/go.mod h1:gawqmDU56v4yIKSwfBSFip1HdCCXN8/+DMd9qYNcwME= -github.com/shurcooL/go v0.0.0-20200502201357-93f07166e636/go.mod h1:TDJrrUr11Vxrven61rcy3hJMUqaf/CLWYhHNPmT14Lk= -github.com/shurcooL/httpfs v0.0.0-20190707220628-8d4bc4ba7749/go.mod h1:ZY1cvUeJuFPAdZ/B6v7RHavJWZn2YPVFQ1OSXhCGOkg= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= -github.com/shurcooL/vfsgen v0.0.0-20200824052919-0d455de96546/go.mod h1:TrYk7fJVaAttu97ZZKrO9UbRa8izdowaMIZcxYMbVaw= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= -github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= +github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= -github.com/smartcontractkit/ccip-owner-contracts v0.0.0-salt-fix h1:DPJD++yKLSx0EfT+U14P8vLVxjXFmoIETiCO9lVwQo8= -github.com/smartcontractkit/ccip-owner-contracts v0.0.0-salt-fix/go.mod h1:NnT6w4Kj42OFFXhSx99LvJZWPpMjmo4+CpDEWfw61xY= -github.com/smartcontractkit/chain-selectors v1.0.34 h1:MJ17OGu8+jjl426pcKrJkCf3fePb3eCreuAnUA3RBj4= -github.com/smartcontractkit/chain-selectors v1.0.34/go.mod h1:xsKM0aN3YGcQKTPRPDDtPx2l4mlTN1Djmg0VVXV40b8= +github.com/smartcontractkit/ccip-owner-contracts v0.0.0-20240926212305-a6deabdfce86 h1:qQH6fZZe31nBAG6INHph3z5ysDTPptyu0TR9uoJ1+ok= +github.com/smartcontractkit/ccip-owner-contracts v0.0.0-20240926212305-a6deabdfce86/go.mod h1:WtWOoVQQEHxRHL2hNmuRrvDfYfQG/CioFNoa9Rr2mBE= +github.com/smartcontractkit/chain-selectors v1.0.29 h1:aZ9+OoUSMn4nqnissHtDvDoKR7JONfDqTHX3MHYIUIE= +github.com/smartcontractkit/chain-selectors v1.0.29/go.mod h1:xsKM0aN3YGcQKTPRPDDtPx2l4mlTN1Djmg0VVXV40b8= github.com/smartcontractkit/chainlink-automation v0.8.1 h1:sTc9LKpBvcKPc1JDYAmgBc2xpDKBco/Q4h4ydl6+UUU= github.com/smartcontractkit/chainlink-automation v0.8.1/go.mod h1:Iij36PvWZ6blrdC5A/nrQUBuf3MH3JvsBB9sSyc9W08= -github.com/smartcontractkit/chainlink-ccip v0.0.0-20241218114855-f74219171000 h1:6Zzr/R1j6P7bbvcUlt5WUIbItvrrGdGzIsiAzQezcwo= -github.com/smartcontractkit/chainlink-ccip v0.0.0-20241218114855-f74219171000/go.mod h1:ncjd6mPZSRlelEqH/2KeLE1pU3UlqzBSn8RYkEoECzY= -github.com/smartcontractkit/chainlink-common v0.4.1-0.20241217120918-bbe318cd0760 h1:lB5A3TP0zOVuu1n0kEm6d8/o/4Knh6HLvsU/GChk+sI= -github.com/smartcontractkit/chainlink-common v0.4.1-0.20241217120918-bbe318cd0760/go.mod h1:yti7e1+G9hhkYhj+L5sVUULn9Bn3bBL5/AxaNqdJ5YQ= -github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241202195413-82468150ac1e h1:PRoeby6ZlTuTkv2f+7tVU4+zboTfRzI+beECynF4JQ0= -github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241202195413-82468150ac1e/go.mod h1:mUh5/woemsVaHgTorA080hrYmO3syBCmPdnWc/5dOqk= -github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20241216163550-fa030d178ba3 h1:aeiBdBHGY8QNftps+VqrIk6OnfeeOD5z4jrAabW4ZSc= -github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20241216163550-fa030d178ba3/go.mod h1:AS6zY2BkcRwfiGzNabGbHhfrLSrXrcI/GmjnT4jQ5/s= +github.com/smartcontractkit/chainlink-ccip v0.0.0-20241118091009-43c2b4804cec h1:5vS1k8Qn09p8SQ3JzvS8iy4Pve7s3aVq+UPIdl74smY= +github.com/smartcontractkit/chainlink-ccip v0.0.0-20241118091009-43c2b4804cec/go.mod h1:4adKaHNaxFsRvV/lYfqtbsWyyvIPUMLR0FdOJN/ljis= +github.com/smartcontractkit/chainlink-common v0.3.1-0.20241114134822-aadff98ef068 h1:2llRW4Tn9W/EZp2XvXclQ9IjeTBwwxVPrrqaerX+vCE= +github.com/smartcontractkit/chainlink-common v0.3.1-0.20241114134822-aadff98ef068/go.mod h1:ny87uTW6hLjCTLiBqBRNFEhETSXhHWevYlPclT5lSco= +github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241017133723-5277829bd53f h1:BwrIaQIx5Iy6eT+DfLhFfK2XqjxRm74mVdlX8gbu4dw= +github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241017133723-5277829bd53f/go.mod h1:wHtwSR3F1CQSJJZDQKuqaqFYnvkT+kMyget7dl8Clvo= +github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20241018134907-a00ba3729b5e h1:JiETqdNM0bktAUGMc62COwXIaw3rR3M77Me6bBLG0Fg= +github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20241018134907-a00ba3729b5e/go.mod h1:iK3BNHKCLgSgkOyiu3iE7sfZ20Qnuk7xwjV/yO/6gnQ= github.com/smartcontractkit/chainlink-feeds v0.1.1 h1:JzvUOM/OgGQA1sOqTXXl52R6AnNt+Wg64sVG+XSA49c= github.com/smartcontractkit/chainlink-feeds v0.1.1/go.mod h1:55EZ94HlKCfAsUiKUTNI7QlE/3d3IwTlsU3YNa/nBb4= -github.com/smartcontractkit/chainlink-protos/job-distributor v0.6.0 h1:0ewLMbAz3rZrovdRUCgd028yOXX8KigB4FndAUdI2kM= -github.com/smartcontractkit/chainlink-protos/job-distributor v0.6.0/go.mod h1:/dVVLXrsp+V0AbcYGJo3XMzKg3CkELsweA/TTopCsKE= -github.com/smartcontractkit/chainlink-protos/orchestrator v0.4.0 h1:ZBat8EBvE2LpSQR9U1gEbRV6PfAkiFdINmQ8nVnXIAQ= -github.com/smartcontractkit/chainlink-protos/orchestrator v0.4.0/go.mod h1:m/A3lqD7ms/RsQ9BT5P2uceYY0QX5mIt4KQxT2G6qEo= -github.com/smartcontractkit/chainlink-solana v1.1.1-0.20241219173444-150f7443fdd3 h1:AIIiwrZ5T4nEjFT33aLZKoXwD63JSMu72wWe/rUdfm0= -github.com/smartcontractkit/chainlink-solana v1.1.1-0.20241219173444-150f7443fdd3/go.mod h1:ARILnIgKelP0YkVzxXO111S9j0b4uKyt7iLpYjOkCtU= -github.com/smartcontractkit/chainlink-starknet/relayer v0.1.1-0.20241202202529-2033490e77b8 h1:tNS7U9lrxkFvEuyxQv11HHOiV9LPDGC9wYEy+yM/Jv4= -github.com/smartcontractkit/chainlink-starknet/relayer v0.1.1-0.20241202202529-2033490e77b8/go.mod h1:EBrEgcdIbwepqguClkv8Ohy7CbyWSJaE4EC9aBJlQK0= +github.com/smartcontractkit/chainlink-protos/job-distributor v0.4.0 h1:1xTm8UGeDUAjvCXRh08+4xBRX33owH5MqC522JdelM0= +github.com/smartcontractkit/chainlink-protos/job-distributor v0.4.0/go.mod h1:/dVVLXrsp+V0AbcYGJo3XMzKg3CkELsweA/TTopCsKE= +github.com/smartcontractkit/chainlink-protos/orchestrator v0.3.0 h1:PBUaFfPLm+Efq7H9kdfGBivH+QhJ6vB5EZTR/sCZsxI= +github.com/smartcontractkit/chainlink-protos/orchestrator v0.3.0/go.mod h1:m/A3lqD7ms/RsQ9BT5P2uceYY0QX5mIt4KQxT2G6qEo= +github.com/smartcontractkit/chainlink-solana v1.1.1-0.20241115191142-8b8369c1f44e h1:XxTWJ9VIXK+XuAjP5131PqqBn0NEt5lBvnRAWRdqy8A= +github.com/smartcontractkit/chainlink-solana v1.1.1-0.20241115191142-8b8369c1f44e/go.mod h1:mGmRvlk54ufCufV4EBWizOGtXoXfePoFAuYEVC8EwdY= +github.com/smartcontractkit/chainlink-starknet/relayer v0.1.1-0.20241017135645-176a23722fd8 h1:B4DFdk6MGcQnoCjjMBCx7Z+GWQpxRWJ4O8W/dVJyWGA= +github.com/smartcontractkit/chainlink-starknet/relayer v0.1.1-0.20241017135645-176a23722fd8/go.mod h1:WkBqgBo+g34Gm5vWkDDl8Fh3Mzd7bF5hXp7rryg0t5o= github.com/smartcontractkit/chainlink-testing-framework/lib v1.50.13 h1:T0kbw07Vb6xUyA9MIJZfErMgWseWi1zf7cYvRpoq7ug= github.com/smartcontractkit/chainlink-testing-framework/lib v1.50.13/go.mod h1:1CKUOzoK+Ga19WuhRH9pxZ+qUUnrlIx108VEA6qSzeQ= +github.com/smartcontractkit/chainlink-testing-framework/lib/grafana v1.50.0 h1:VIxK8u0Jd0Q/VuhmsNm6Bls6Tb31H/sA3A/rbc5hnhg= +github.com/smartcontractkit/chainlink-testing-framework/lib/grafana v1.50.0/go.mod h1:lyAu+oMXdNUzEDScj2DXB2IueY+SDXPPfyl/kb63tMM= +github.com/smartcontractkit/chainlink-testing-framework/seth v1.50.5 h1:BxN9wddNLiugruN3k7nYoSMQTO0tz9qR+vILFW2l0Ps= +github.com/smartcontractkit/chainlink-testing-framework/seth v1.50.5/go.mod h1:lJk0atEJ5Zyo3Tqrmf1Pl9jUEe79EgDb9bD3K5OTUBI= +github.com/smartcontractkit/chainlink-testing-framework/wasp v1.50.2 h1:7bCdbTUWzyczQg+kwHCxlx6y07zE8HNB8+ntTne6qd8= +github.com/smartcontractkit/chainlink-testing-framework/wasp v1.50.2/go.mod h1:MltlNu3jcXm/DyLN98I5TFNtu/o1NNAcaPAFKMXWk70= github.com/smartcontractkit/grpc-proxy v0.0.0-20240830132753-a7e17fec5ab7 h1:12ijqMM9tvYVEm+nR826WsrNi6zCKpwBhuApq127wHs= github.com/smartcontractkit/grpc-proxy v0.0.0-20240830132753-a7e17fec5ab7/go.mod h1:FX7/bVdoep147QQhsOPkYsPEXhGZjeYx6lBSaSXtZOA= github.com/smartcontractkit/libocr v0.0.0-20241007185508-adbe57025f12 h1:NzZGjaqez21I3DU7objl3xExTH4fxYvzTqar8DC6360= @@ -1179,20 +1441,21 @@ github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20241009055228- github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20241009055228-33d0c0bf38de/go.mod h1:Sl2MF/Fp3fgJIVzhdGhmZZX2BlnM0oUUyBP4s4xYb6o= github.com/smartcontractkit/tdh2/go/tdh2 v0.0.0-20241009055228-33d0c0bf38de h1:66VQxXx3lvTaAZrMBkIcdH9VEjujUEvmBQdnyOJnkOc= github.com/smartcontractkit/tdh2/go/tdh2 v0.0.0-20241009055228-33d0c0bf38de/go.mod h1:NSc7hgOQbXG3DAwkOdWnZzLTZENXSwDJ7Va1nBp0YU0= -github.com/smartcontractkit/wsrpc v0.8.3 h1:9tDf7Ut61g36RJIyxV9iI73SqoOMasKPfURV9oMLrPg= -github.com/smartcontractkit/wsrpc v0.8.3/go.mod h1:2u/wfnhl5R4RlSXseN4n6HHIWk8w1Am3AT6gWftQbNg= -github.com/smarty/assertions v1.15.0/go.mod h1:yABtdzeQs6l1brC900WlRNwj6ZR55d7B+E8C6HtKdec= +github.com/smartcontractkit/wsrpc v0.8.2 h1:XB/xcn/MMseHW+8JE8+a/rceA86ck7Ur6cEa9LiUC8M= +github.com/smartcontractkit/wsrpc v0.8.2/go.mod h1:2u/wfnhl5R4RlSXseN4n6HHIWk8w1Am3AT6gWftQbNg= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= -github.com/smartystreets/goconvey v1.8.1/go.mod h1:+/u4qLyY6x1jReYOp7GOM2FSt8aP9CzCZL03bI28W60= github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= +github.com/soheilhy/cmux v0.1.5 h1:jjzc5WVemNEDTLwv9tlmemhC73tI08BNOIGwBOo10Js= +github.com/soheilhy/cmux v0.1.5/go.mod h1:T7TcVDs9LWfQgPlPsdngu6I6QIoyIFZDDC6sNE1GqG0= +github.com/sony/gobreaker v0.5.0 h1:dRCvqm0P490vZPmy7ppEk2qCnCieBooFJ+YoXGYB+yg= +github.com/sony/gobreaker v0.5.0/go.mod h1:ZKptC7FHNvhBz7dN2LGjPVBz2sZJmc0/PkyDJOjmxWY= github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo= github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI= github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= -github.com/spf13/afero v1.6.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I= github.com/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8= github.com/spf13/afero v1.11.0/go.mod h1:GH9Y3pIexgf1MTIWtNGyogA5MwRIDXGUr+hbWNoBjkY= github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= @@ -1201,25 +1464,21 @@ github.com/spf13/cast v1.6.0 h1:GEiTHELF+vaR5dhz3VqZfFSzZjYbgeKDpBxQVS4GYJ0= github.com/spf13/cast v1.6.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo= github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU= github.com/spf13/cobra v1.1.1/go.mod h1:WnodtKOvamDL/PwE2M4iKs8aMDBZ5Q5klgD3qfVJQMI= -github.com/spf13/cobra v1.2.1/go.mod h1:ExllRjgxM/piMAM+3tAZvg8fsklGAf3tPfi+i8t68Nk= github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM= github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y= github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= -github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= github.com/spf13/viper v1.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg= github.com/spf13/viper v1.7.1/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg= -github.com/spf13/viper v1.8.1/go.mod h1:o0Pch8wJ9BVSWGQMbra6iw0oQ5oktSIBaujf1rJH9Ns= github.com/spf13/viper v1.19.0 h1:RWq5SEjt8o25SROyN3z2OrDB9l7RPd3lwTWU8EcEdcI= github.com/spf13/viper v1.19.0/go.mod h1:GQUN9bilAbhU/jgc1bKs99f/suXKeUMct8Adx5+Ntkg= github.com/status-im/keycard-go v0.2.0 h1:QDLFswOQu1r5jsycloeQh3bVU8n/NatHHaZobtDnDzA= github.com/status-im/keycard-go v0.2.0/go.mod h1:wlp8ZLbsmrF6g6WjugPAx+IzoLrkdf9+mHxBEeo3Hbg= github.com/streamingfast/logging v0.0.0-20220405224725-2755dab2ce75 h1:ZqpS7rAhhKD7S7DnrpEdrnW1/gZcv82ytpMviovkli4= github.com/streamingfast/logging v0.0.0-20220405224725-2755dab2ce75/go.mod h1:VlduQ80JcGJSargkRU4Sg9Xo63wZD/l8A5NC/Uo1/uU= -github.com/streamingfast/logging v0.0.0-20230608130331-f22c91403091/go.mod h1:VlduQ80JcGJSargkRU4Sg9Xo63wZD/l8A5NC/Uo1/uU= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= @@ -1241,7 +1500,6 @@ github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= -github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8= github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= @@ -1256,6 +1514,8 @@ github.com/teris-io/shortid v0.0.0-20201117134242-e59966efd125 h1:3SNcvBmEPE1YlB github.com/teris-io/shortid v0.0.0-20201117134242-e59966efd125/go.mod h1:M8agBzgqHIhgj7wEn9/0hJUZcrvt9VY+Ln+S1I5Mha0= github.com/test-go/testify v1.1.4 h1:Tf9lntrKUMHiXQ07qBScBTSA0dhYQlu83hswqelv1iE= github.com/test-go/testify v1.1.4/go.mod h1:rH7cfJo/47vWGdi4GPj16x3/t1xGOj2YxzmNQzk2ghU= +github.com/testcontainers/testcontainers-go v0.34.0 h1:5fbgF0vIN5u+nD3IWabQwRybuB4GY8G2HHgCkbMzMHo= +github.com/testcontainers/testcontainers-go v0.34.0/go.mod h1:6P/kMkQe8yqPHfPWNulFGdFHTD8HB2vLq/231xY2iPQ= github.com/theodesp/go-heaps v0.0.0-20190520121037-88e35354fe0a h1:YuO+afVc3eqrjiCUizNCxI53bl/BnPiVwXqLzqYTqgU= github.com/theodesp/go-heaps v0.0.0-20190520121037-88e35354fe0a/go.mod h1:/sfW47zCZp9FrtGcWyo1VjbgDaodxX9ovZvgLb/MxaA= github.com/tidwall/btree v1.6.0 h1:LDZfKfQIBHGHWSwckhXI0RPSXzlo+KYdjK7FWSqOzzg= @@ -1282,6 +1542,10 @@ github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08= github.com/tyler-smith/go-bip39 v1.1.0 h1:5eUemwrMargf3BSLRRCalXT93Ns6pQJIjYQN2nyfOP8= github.com/tyler-smith/go-bip39 v1.1.0/go.mod h1:gUYDtqQw1JS3ZJ8UWVcGTGqqr6YIN3CWg+kkNaLt55U= +github.com/uber/jaeger-client-go v2.30.0+incompatible h1:D6wyKGCecFaSRUpo8lCVbaOOb6ThwMmTEbhRwtKR97o= +github.com/uber/jaeger-client-go v2.30.0+incompatible/go.mod h1:WVhlPFC8FDjOFMMWRy2pZqQJSXxYSwNYOkTr/Z6d3Kk= +github.com/uber/jaeger-lib v2.4.1+incompatible h1:td4jdvLcExb4cBISKIpHuGoVXh+dVKhn2Um6rjCsSsg= +github.com/uber/jaeger-lib v2.4.1+incompatible/go.mod h1:ComeNDZlWwrWnDv8aPp0Ba6+uUTzImX/AauajbLI56U= github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= github.com/ugorji/go v1.2.7/go.mod h1:nF9osbDWLy6bDVv/Rtoh6QgnvNDpmCalQV5urGCCS6M= github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= @@ -1306,6 +1570,8 @@ github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyC github.com/valyala/fastjson v1.4.1 h1:hrltpHpIpkaxll8QltMU8c3QZ5+qIiCL8yKqPFJI/yE= github.com/valyala/fastjson v1.4.1/go.mod h1:nV6MsjxL2IMJQUoHDIrjEI7oLyeqK6aBD7EFWPsvP8o= github.com/valyala/fasttemplate v1.0.1/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPUpymEIMZ47gx8= +github.com/vultr/govultr/v2 v2.17.2 h1:gej/rwr91Puc/tgh+j33p/BLR16UrIPnSr+AIwYWZQs= +github.com/vultr/govultr/v2 v2.17.2/go.mod h1:ZFOKGWmgjytfyjeyAdhQlSWwTjh2ig+X49cAp50dzXI= github.com/wk8/go-ordered-map/v2 v2.1.8 h1:5h/BUHu93oj4gIdvHHHGsScSTMijfx5PeYkE/fJgbpc= github.com/wk8/go-ordered-map/v2 v2.1.8/go.mod h1:5nJHM5DyteebpVlHnWMV0rPz6Zp7+xBAnxjb1X5vnTw= github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM= @@ -1314,11 +1580,11 @@ github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT github.com/xdg-go/scram v1.1.1/go.mod h1:RaEWvsqvNKKvBPvcKeFjrG2cJqOkHTiyTpzz23ni57g= github.com/xdg-go/stringprep v1.0.3/go.mod h1:W3f5j4i+9rC0kuIEJL0ky1VpHXQU3ocBgklLGvcBnW8= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= +github.com/xlab/treeprint v1.2.0 h1:HzHnuAF1plUN2zGlAFHbSQP2qJ0ZAD3XF5XD7OesXRQ= +github.com/xlab/treeprint v1.2.0/go.mod h1:gj5Gd3gPdKtR1ikdDK6fnFLdmIS0X30kTTuNd/WEJu0= github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 h1:gEOO8jv9F4OT7lGCjxCBTO/36wtF6j2nSip77qHd4x4= github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1/go.mod h1:Ohn+xnUBiLI6FVj/9LpzZWtj1/D6lUovWYBkxHVV3aM= -github.com/xyproto/randomstring v1.0.5 h1:YtlWPoRdgMu3NZtP45drfy1GKoojuR7hmRcnhZqKjWU= -github.com/xyproto/randomstring v1.0.5/go.mod h1:rgmS5DeNXLivK7YprL0pY+lTuhNQW3iGxZ18UQApw/E= github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d/go.mod h1:rHwXgn7JulP+udvsHwJoVG1YGAP6VLg4y9I5dyZdqmA= github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= @@ -1326,10 +1592,10 @@ github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= +github.com/yuin/gopher-lua v1.1.0 h1:BojcDhfyDWgU2f2TOzYK/g5p2gxMrku8oupLDqlnSqE= +github.com/yuin/gopher-lua v1.1.0/go.mod h1:GBR0iDaNXjAgGg9zfCvksxSRnQx76gclCIb7kdAd1Pw= github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo0= github.com/yusufpapurcu/wmi v1.2.4/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= -github.com/zeebo/xxh3 v1.0.2 h1:xZmwmqxHZA8AI603jOQ0tMqmBr9lPeFwGg6d+xy9DC0= -github.com/zeebo/xxh3 v1.0.2/go.mod h1:5NWz9Sef7zIDm2JHfFlcQvNekmcEl9ekUZQQKCYaDcA= github.com/zenazn/goji v0.9.0/go.mod h1:7S9M489iMyHBNxwZnk9/EHS098H4/F6TATF2mIxtB1Q= github.com/zondax/hid v0.9.2 h1:WCJFnEDMiqGF64nlZz28E9qLVZ0KSJ7xpc5DLEyma2U= github.com/zondax/hid v0.9.2/go.mod h1:l5wttcP0jwtdLjqjMMWFVEE7d1zO0jvSPA9OPZxWpEM= @@ -1347,9 +1613,12 @@ go.dedis.ch/protobuf v1.0.11/go.mod h1:97QR256dnkimeNdfmURz0wAMNVbd1VmLXhG1CrTYr go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.etcd.io/bbolt v1.3.9 h1:8x7aARPEXiXbHmtUwAIv7eV2fQFHrLLavdiJ3uzJXoI= go.etcd.io/bbolt v1.3.9/go.mod h1:zaO32+Ti0PK1ivdPtgMESzuzL2VPoIG1PCQNvOdo/dE= -go.etcd.io/etcd/api/v3 v3.5.0/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs= -go.etcd.io/etcd/client/pkg/v3 v3.5.0/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g= -go.etcd.io/etcd/client/v2 v2.305.0/go.mod h1:h9puh54ZTgAKtEbut2oe9P4L/oqKCVB6xsXlzd7alYQ= +go.etcd.io/etcd/api/v3 v3.5.14 h1:vHObSCxyB9zlF60w7qzAdTcGaglbJOpSj1Xj9+WGxq0= +go.etcd.io/etcd/api/v3 v3.5.14/go.mod h1:BmtWcRlQvwa1h3G2jvKYwIQy4PkHlDej5t7uLMUdJUU= +go.etcd.io/etcd/client/pkg/v3 v3.5.14 h1:SaNH6Y+rVEdxfpA2Jr5wkEvN6Zykme5+YnbCkxvuWxQ= +go.etcd.io/etcd/client/pkg/v3 v3.5.14/go.mod h1:8uMgAokyG1czCtIdsq+AGyYQMvpIKnSvPjFMunkgeZI= +go.etcd.io/etcd/client/v3 v3.5.14 h1:CWfRs4FDaDoSz81giL7zPpZH2Z35tbOrAJkkjMqOupg= +go.etcd.io/etcd/client/v3 v3.5.14/go.mod h1:k3XfdV/VIHy/97rqWjoUzrj9tk7GgJGH9J8L4dNXmAk= go.mongodb.org/mongo-driver v1.11.0/go.mod h1:s7p5vEtfbeR1gYi6pnj3c3/urpbLv2T5Sfd6Rp2HBB8= go.mongodb.org/mongo-driver v1.15.0 h1:rJCKC8eEliewXjZGf0ddURtl7tTVy1TK3bfl0gkUSLc= go.mongodb.org/mongo-driver v1.15.0/go.mod h1:Vzb0Mk/pa7e6cWw85R4F/endUC3u0U9jGcNU603k65c= @@ -1360,9 +1629,12 @@ go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= -go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= +go.opentelemetry.io/collector/pdata v1.12.0 h1:Xx5VK1p4VO0md8MWm2icwC1MnJ7f8EimKItMWw46BmA= +go.opentelemetry.io/collector/pdata v1.12.0/go.mod h1:MYeB0MmMAxeM0hstCFrCqWLzdyeYySim2dG6pDT6nYI= +go.opentelemetry.io/collector/semconv v0.105.0 h1:8p6dZ3JfxFTjbY38d8xlQGB1TQ3nPUvs+D0RERniZ1g= +go.opentelemetry.io/collector/semconv v0.105.0/go.mod h1:yMVUCNoQPZVq/IPfrHrnntZTWsLf5YGZ7qwKulIl5hw= go.opentelemetry.io/contrib/detectors/gcp v1.31.0 h1:G1JQOreVrfhRkner+l4mrGxmfqYCAuy76asTDAo0xsA= go.opentelemetry.io/contrib/detectors/gcp v1.31.0/go.mod h1:tzQL6E1l+iV44YFTkcAeNQqzXUiekSYP9jjJjXwEd00= go.opentelemetry.io/contrib/instrumentation/github.com/gin-gonic/gin/otelgin v0.49.0 h1:1f31+6grJmV3X4lxcEvUy13i5/kfDw1nJZwhd8mA4tg= @@ -1411,6 +1683,8 @@ go.opentelemetry.io/otel/trace v1.31.0 h1:ffjsj1aRouKewfr85U2aGagJ46+MvodynlQ1HY go.opentelemetry.io/otel/trace v1.31.0/go.mod h1:TXZkRk7SM2ZQLtR6eoAWQFIHPvzQ06FJAsO1tJg480A= go.opentelemetry.io/proto/otlp v1.3.1 h1:TrMUixzpM0yuc/znrFTP9MMRh8trP93mkCiDVeXrui0= go.opentelemetry.io/proto/otlp v1.3.1/go.mod h1:0X1WI4de4ZsLrrJNLAQbFeLCm3T7yBkR0XqQ7niQU+8= +go.starlark.net v0.0.0-20230525235612-a134d8f9ddca h1:VdD38733bfYv5tUZwEIskMM93VanwNIi5bIKnDrJdEY= +go.starlark.net v0.0.0-20230525235612-a134d8f9ddca/go.mod h1:jxU+3+j+71eXOW14274+SmmuW82qJzl6iZSeqEtTGds= go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= @@ -1436,10 +1710,11 @@ go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= go.uber.org/zap v1.14.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= go.uber.org/zap v1.16.0/go.mod h1:MA8QOfq0BHJwdXa996Y4dYkAqRKB8/1K1QMMZVaNZjQ= -go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo= go.uber.org/zap v1.21.0/go.mod h1:wjWOCqI0f2ZZrJF/UufIOkiC8ii6tm1iqIsLo76RfJw= go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= +go4.org/netipx v0.0.0-20230125063823-8449b0a6169f h1:ketMxHg+vWm3yccyYiq+uK8D3fRmna2Fcj+awpQp84s= +go4.org/netipx v0.0.0-20230125063823-8449b0a6169f/go.mod h1:tgPU4N2u9RByaTN3NC2p9xOzyFpte4jYwsIIRF7XlSc= golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= golang.org/x/arch v0.11.0 h1:KXV8WWKCXm6tRpLirl2szsO5j/oOODwZf4hATmGVNs4= golang.org/x/arch v0.11.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys= @@ -1452,6 +1727,7 @@ golang.org/x/crypto v0.0.0-20190411191339-88737f569e3a/go.mod h1:WFFai1msRO1wXaE golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3H3cr1v9wB50oz8l4C4h62xy7jSTY= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191206172530-e9b2fee46413/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= @@ -1460,12 +1736,14 @@ golang.org/x/crypto v0.0.0-20201203163018-be400aefbc4c/go.mod h1:jdWPYTVW3xRLrWP golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20220214200702-86341886e292/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/crypto v0.3.0/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4= golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc= -golang.org/x/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U= -golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk= +golang.org/x/crypto v0.28.0 h1:GBDwsMXVQi34v5CCYUm2jkJvu4cbtru2U4TN2PSyQnw= +golang.org/x/crypto v0.28.0/go.mod h1:rmgy+3RHxRZMyY0jjAJShp2zgEdOqj2AO7U0pYmeQ7U= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -1478,7 +1756,6 @@ golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EH golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= golang.org/x/exp v0.0.0-20241009180824-f66d83c29e7c h1:7dEasQXItcW1xKJ2+gg5VOiBnqWrJc+rq0DPKyvvdbY= golang.org/x/exp v0.0.0-20241009180824-f66d83c29e7c/go.mod h1:NQtJDoLvd6faHhE7m4T/1IY708gDefGGjR/iUW8yQQ8= -golang.org/x/exp v0.0.0-20241210194714-1829a127f884/go.mod h1:qj5a5QZpwLU2NLQudwIN5koi3beDhSAlJwa67PuM98c= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= @@ -1492,7 +1769,6 @@ golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRu golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= @@ -1501,15 +1777,11 @@ golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzB golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/mod v0.9.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.21.0 h1:vvrHzRwRfVKSiLrG+d4FMl/Qi4ukBCE6kZlTUkDYRT0= golang.org/x/mod v0.21.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY= -golang.org/x/mod v0.22.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -1529,6 +1801,7 @@ golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190921015927-1a5e07d1ff72/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= @@ -1546,37 +1819,30 @@ golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81R golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc= golang.org/x/net v0.0.0-20210331212208-0fccb6fa2b5c/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= +golang.org/x/net v0.0.0-20210410081132-afb366fc7cd1/go.mod h1:9tjilg8BloeKEkVJvy7fQ90B1CfIiPueXVOjqfkSzI8= golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= +golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220607020251-c690dde0001d/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= -golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/net v0.30.0 h1:AcW1SDZMkb8IpzCdQUaIq2sP4sZ4zw+55h6ynffypl4= golang.org/x/net v0.30.0/go.mod h1:2wGyMJ5iFasEhkwi13ChkO/t1ECNC4X4eBKkVFyYFlU= -golang.org/x/net v0.32.0/go.mod h1:CwU0IoeOlnQQWJ6ioyFrfRuomB8GKF6KbYXZVyeXNfs= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210220000619-9bb904979d93/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210313182246-cd4f82c27b84/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210402161424-2e8d93401602/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.23.0 h1:PbgcYx2W7i4LvjJWEbf0ngHV6qJYr86PkAV3bXdLEbs= golang.org/x/oauth2 v0.23.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -1592,8 +1858,8 @@ golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ= -golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ= +golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -1619,12 +1885,15 @@ golang.org/x/sys v0.0.0-20190804053845-51ab0e2deafa/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190922100055-0a153f010e69/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -1638,25 +1907,25 @@ golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210305230114-8fe3ee5dd75b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210303074136-134d130e1a04/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210331175145-43e1dd70ce54/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210819135213-f52c844e1c1c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -1665,10 +1934,13 @@ golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20221010170243-090e33056c14/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -1676,18 +1948,19 @@ golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA= -golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo= +golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20201210144234-2321bbc49cbf/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.0.0-20220526004731-065cf7ba2467/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= -golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU= -golang.org/x/term v0.27.0 h1:WP60Sv1nlK1T6SupCHbXzSaN0b9wUmsPoRS9b61A23Q= -golang.org/x/term v0.27.0/go.mod h1:iMsnZpn0cago0GOrHO2+Y7u7JPn5AylBrcoWkElMTSM= +golang.org/x/term v0.25.0 h1:WtHI/ltw4NvSUig5KARz9h521QvRC8RmF/cuYqifU24= +golang.org/x/term v0.25.0/go.mod h1:RPyXicDX+6vLxogjjRxjgD2TKtmAO6NZBsBRfrOLu7M= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -1697,12 +1970,12 @@ golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= -golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo= -golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ= +golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM= +golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -1724,6 +1997,7 @@ golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgw golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20190823170909-c4a336ef6a2f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20190907020128-2ca718005c18/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191010075000-0337d82405ff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= @@ -1758,22 +2032,14 @@ golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roY golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE= -golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= -golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= -golang.org/x/tools v0.7.0/go.mod h1:4pg6aUX35JBAogB10C9AtvVL+qowtN4pT3CGSQex14s= golang.org/x/tools v0.26.0 h1:v/60pFQmzmT9ExmjDv2gGIfi3OqfKoEP6I5+umXlbnQ= golang.org/x/tools v0.26.0/go.mod h1:TPVVj70c7JJ3WCazhD8OdXcZg/og+b9+tH/KxylGwH0= -golang.org/x/tools v0.28.0/go.mod h1:dcIOrVd3mfQKTgrDVQHqCPMWy6lnhfhtX3hLXYVLfRw= golang.org/x/xerrors v0.0.0-20190410155217-1f06c39b4373/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20190513163551-3ee3066db522/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -1783,6 +2049,8 @@ golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20220517211312-f3a8303e98df/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= golang.org/x/xerrors v0.0.0-20240903120638-7835f813f4da h1:noIWHXmPHxILtqtCOPIhSt0ABwskkZKjD3bXGnZGpNY= golang.org/x/xerrors v0.0.0-20240903120638-7835f813f4da/go.mod h1:NDW/Ps6MPRej6fsCIbMTohpP40sJ/P/vI1MoTEGwX90= +gomodules.xyz/jsonpatch/v2 v2.4.0 h1:Ci3iUJyx9UeRx7CeFN8ARgGbkESwJK+KB9lLcWxY/Zw= +gomodules.xyz/jsonpatch/v2 v2.4.0/go.mod h1:AH3dM2RI6uoBZxn3LVrfvJ3E0/9dG4cSrbuBJT4moAY= gonum.org/v1/gonum v0.15.1 h1:FNy7N6OUZVUaWG9pTiD+jlhdQ3lMP+/LcTpJ6+a8sQ0= gonum.org/v1/gonum v0.15.1/go.mod h1:eZTZuRFrzu5pcyjN5wJhcIhnUdNijYxX1T2IcrOGY0o= google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= @@ -1802,12 +2070,6 @@ google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0M google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM= google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc= -google.golang.org/api v0.35.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg= -google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34qYtE= -google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8= -google.golang.org/api v0.41.0/go.mod h1:RkxM5lITDfTzmyKFPt+wGrCJbVfniCr2ool8kTBzRTU= -google.golang.org/api v0.43.0/go.mod h1:nQsDGjRXMo4lvh5hP0TKqF244gqhGcr/YSIykhUk/94= -google.golang.org/api v0.44.0/go.mod h1:EBOGZqzyhtvMDoxwS97ctnh0zUmYY6CxqXsc1AvkYD8= google.golang.org/api v0.202.0 h1:y1iuVHMqokQbimW79ZqPZWo4CiyFu6HcCYHwSNyzlfo= google.golang.org/api v0.202.0/go.mod h1:3Jjeq7M/SFblTNCp7ES2xhq+WvGL0KeXI0joHQBfwTQ= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= @@ -1818,6 +2080,7 @@ google.golang.org/appengine v1.6.2/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/genproto v0.0.0-20180518175338-11a468237815/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20180831171423-11092d34479b/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= @@ -1852,24 +2115,14 @@ google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7Fc google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210222152913-aa3ee6e6a81c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210303154014-9728d6b83eeb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210310155132-4ce2db91004e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210319143718-93e7006c17a6/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210401141331-865547bb08e2/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A= -google.golang.org/genproto v0.0.0-20210402141018-6c239bbf2bb1/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A= -google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= google.golang.org/genproto v0.0.0-20241021214115-324edc3d5d38 h1:Q3nlH8iSQSRUwOskjbcSMcF2jiYMNiQYZ0c2KEJLKKU= google.golang.org/genproto v0.0.0-20241021214115-324edc3d5d38/go.mod h1:xBI+tzfqGGN2JBeSebfKXFSdBpWVQ7sLW40PTupVRm4= google.golang.org/genproto/googleapis/api v0.0.0-20241021214115-324edc3d5d38 h1:2oV8dfuIkM1Ti7DwXc0BJfnwr9csz4TDXI9EmiI+Rbw= google.golang.org/genproto/googleapis/api v0.0.0-20241021214115-324edc3d5d38/go.mod h1:vuAjtvlwkDKF6L1GQ0SokiRLCGFfeBUXWr/aFFkHACc= google.golang.org/genproto/googleapis/rpc v0.0.0-20241021214115-324edc3d5d38 h1:zciRKQ4kBpFgpfC5QQCVtnnNAcLIqweL7plyZRQHVpI= google.golang.org/genproto/googleapis/rpc v0.0.0-20241021214115-324edc3d5d38/go.mod h1:GX3210XPVPUjJbTUbvwI8f2IpZDMZuPJWDzDuebbviI= +google.golang.org/grpc v1.12.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= @@ -1884,14 +2137,9 @@ google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKa google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= -google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= -google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8= -google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= -google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= google.golang.org/grpc v1.36.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= -google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= google.golang.org/grpc v1.67.1 h1:zWnc1Vrcno+lHZCOofnIMvycFcc0QRGIzm9dhnDX68E= google.golang.org/grpc v1.67.1/go.mod h1:1gLDyUQU7CTLJI90u3nXZ9ekeghjeM7pTDZlqFNg2AA= google.golang.org/grpc/stats/opentelemetry v0.0.0-20241022174616-4bb0170ac65f h1:TsfHqsKI7qhOoYugDRyFDSKAuzegDVmkSCpjUyLkb+8= @@ -1919,6 +2167,8 @@ gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b/go.mod h1:Co6ibVJAznAaIkqp8 gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= +gopkg.in/evanphx/json-patch.v4 v4.12.0 h1:n6jtcsulIzXPJaxegRbvFNNrZDjbij7ny3gmSPG+6V4= +gopkg.in/evanphx/json-patch.v4 v4.12.0/go.mod h1:p8EYWUEYMpynmqDbY58zCKCFZw8pRWMG4EsWvDvM72M= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/go-playground/assert.v1 v1.2.1/go.mod h1:9RXL0bg/zibRAgZUYszZSwO/z8Y/a8bDuhia5mkpMnE= gopkg.in/go-playground/validator.v8 v8.18.2/go.mod h1:RX2a/7Ha8BgOhfk7j780h4/u/RRjR0eouCJSH80/M2Y= @@ -1930,7 +2180,6 @@ gopkg.in/inconshreveable/log15.v2 v2.0.0-20180818164646-67afb5ed74ec/go.mod h1:a gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= -gopkg.in/ini.v1 v1.62.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/natefinch/lumberjack.v2 v2.2.1 h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST95x9zc= @@ -1965,14 +2214,22 @@ honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9 honnef.co/go/tools v0.1.3/go.mod h1:NgwopIslSNH47DimFoV78dnkksY2EFtX0ajyb3K/las= k8s.io/api v0.31.1 h1:Xe1hX/fPW3PXYYv8BlozYqw63ytA92snr96zMW9gWTU= k8s.io/api v0.31.1/go.mod h1:sbN1g6eY6XVLeqNsZGLnI5FwVseTrZX7Fv3O26rhAaI= +k8s.io/apiextensions-apiserver v0.31.0 h1:fZgCVhGwsclj3qCw1buVXCV6khjRzKC5eCFt24kyLSk= +k8s.io/apiextensions-apiserver v0.31.0/go.mod h1:b9aMDEYaEe5sdK+1T0KU78ApR/5ZVp4i56VacZYEHxk= k8s.io/apimachinery v0.31.1 h1:mhcUBbj7KUjaVhyXILglcVjuS4nYXiwC+KKFBgIVy7U= k8s.io/apimachinery v0.31.1/go.mod h1:rsPdaZJfTfLsNJSQzNHQvYoTmxhoOEofxtOsF3rtsMo= +k8s.io/cli-runtime v0.31.1 h1:/ZmKhmZ6hNqDM+yf9s3Y4KEYakNXUn5sod2LWGGwCuk= +k8s.io/cli-runtime v0.31.1/go.mod h1:pKv1cDIaq7ehWGuXQ+A//1OIF+7DI+xudXtExMCbe9U= k8s.io/client-go v0.31.1 h1:f0ugtWSbWpxHR7sjVpQwuvw9a3ZKLXX0u0itkFXufb0= k8s.io/client-go v0.31.1/go.mod h1:sKI8871MJN2OyeqRlmA4W4KM9KBdBUpDLu/43eGemCg= +k8s.io/component-base v0.31.1 h1:UpOepcrX3rQ3ab5NB6g5iP0tvsgJWzxTyAo20sgYSy8= +k8s.io/component-base v0.31.1/go.mod h1:WGeaw7t/kTsqpVTaCoVEtillbqAhF2/JgvO0LDOMa0w= k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk= k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE= k8s.io/kube-openapi v0.0.0-20240709000822-3c01b740850f h1:2sXuKesAYbRHxL3aE2PN6zX/gcJr22cjrsej+W784Tc= k8s.io/kube-openapi v0.0.0-20240709000822-3c01b740850f/go.mod h1:UxDHUPsUwTOOxSU+oXURfFBcAS6JwiRXTYqYwfuGowc= +k8s.io/kubectl v0.31.1 h1:ih4JQJHxsEggFqDJEHSOdJ69ZxZftgeZvYo7M/cpp24= +k8s.io/kubectl v0.31.1/go.mod h1:aNuQoR43W6MLAtXQ/Bu4GDmoHlbhHKuyD49lmTC8eJM= k8s.io/utils v0.0.0-20240711033017-18e509b52bc8 h1:pUdcCO1Lk/tbT5ztQWOBi5HBgbBP1J8+AsQnQCKsi8A= k8s.io/utils v0.0.0-20240711033017-18e509b52bc8/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= modernc.org/gc/v3 v3.0.0-20240107210532-573471604cb6 h1:5D53IMaUuA5InSeMu9eJtlQXS2NxAhyWQvkKEgXZhHI= @@ -2000,8 +2257,14 @@ rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= rsc.io/tmplfunc v0.0.3 h1:53XFQh69AfOa8Tw0Jm7t+GV7KZhOi6jzsCzTtKbMvzU= rsc.io/tmplfunc v0.0.3/go.mod h1:AG3sTPzElb1Io3Yg4voV9AGZJuleGAwaVRxL9M49PhA= +sigs.k8s.io/controller-runtime v0.19.0 h1:nWVM7aq+Il2ABxwiCizrVDSlmDcshi9llbaFbC0ji/Q= +sigs.k8s.io/controller-runtime v0.19.0/go.mod h1:iRmWllt8IlaLjvTTDLhRBXIEtkCK6hwVBJJsYS9Ajf4= sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd h1:EDPBXCAspyGV4jQlpZSudPeMmr1bNJefnuqLsRAsHZo= sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0= +sigs.k8s.io/kustomize/api v0.17.2 h1:E7/Fjk7V5fboiuijoZHgs4aHuexi5Y2loXlVOAVAG5g= +sigs.k8s.io/kustomize/api v0.17.2/go.mod h1:UWTz9Ct+MvoeQsHcJ5e+vziRRkwimm3HytpZgIYqye0= +sigs.k8s.io/kustomize/kyaml v0.17.1 h1:TnxYQxFXzbmNG6gOINgGWQt09GghzgTP6mIurOgrLCQ= +sigs.k8s.io/kustomize/kyaml v0.17.1/go.mod h1:9V0mCjIEYjlXuCdYsSXvyoy2BTsLESH7TlGV81S282U= sigs.k8s.io/structured-merge-diff/v4 v4.4.1 h1:150L+0vs/8DA78h1u02ooW1/fFq/Lwr+sGiqlzvrtq4= sigs.k8s.io/structured-merge-diff/v4 v4.4.1/go.mod h1:N8hJocpFajUSSeSJ9bOZ77VzejKZaXsTtZo4/u7Io08= sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E= diff --git a/core/scripts/keystone/README.md b/core/scripts/keystone/README.md index f08f738cb78..9bf6adfff4e 100644 --- a/core/scripts/keystone/README.md +++ b/core/scripts/keystone/README.md @@ -51,7 +51,7 @@ If you want to redeploy all resources, then you'll want to do the following: ```bash # From /crib devspace purge --profile keystone # Remove all k8s resources -DEVSPACE_NAMESPACE=crib- crib init # Purge currently leaves some hanging resources, make a new namespace +./cribbit.sh crib- # Purge currently leaves some hanging resources, make a new namespace devspace deploy --profile keysone --clean # Wipe any keystone related persisted data, like artefacts and caches. ``` diff --git a/core/scripts/keystone/src/01_deploy_contracts_cmd.go b/core/scripts/keystone/src/01_deploy_contracts_cmd.go index 14c8d989063..6fc3f1399cf 100644 --- a/core/scripts/keystone/src/01_deploy_contracts_cmd.go +++ b/core/scripts/keystone/src/01_deploy_contracts_cmd.go @@ -12,9 +12,9 @@ import ( "github.com/ethereum/go-ethereum/common" helpers "github.com/smartcontractkit/chainlink/core/scripts/common" - "github.com/smartcontractkit/chainlink/deployment/keystone/changeset" - forwarder "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/forwarder_1_0_0" - ocr3_capability "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/ocr3_capability_1_0_0" + ksdeploy "github.com/smartcontractkit/chainlink/deployment/keystone" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/forwarder" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/ocr3_capability" ) type deployedContracts struct { @@ -157,7 +157,7 @@ func deploy( func setOCR3Config( env helpers.Environment, - ocrConfig changeset.OCR3OnchainConfig, + ocrConfig ksdeploy.Orc2drOracleConfig, artefacts string, ) { loadedContracts, err := LoadDeployedContracts(artefacts) diff --git a/core/scripts/keystone/src/05_deploy_initialize_capabilities_registry.go b/core/scripts/keystone/src/05_deploy_initialize_capabilities_registry.go index b7fc9df2c88..f4e394b7da5 100644 --- a/core/scripts/keystone/src/05_deploy_initialize_capabilities_registry.go +++ b/core/scripts/keystone/src/05_deploy_initialize_capabilities_registry.go @@ -8,9 +8,11 @@ import ( "log" "os" "strings" + "time" "github.com/ethereum/go-ethereum/common" "google.golang.org/protobuf/proto" + "google.golang.org/protobuf/types/known/durationpb" ragetypes "github.com/smartcontractkit/libocr/ragep2p/types" @@ -20,7 +22,7 @@ import ( "github.com/ethereum/go-ethereum/accounts/abi/bind" helpers "github.com/smartcontractkit/chainlink/core/scripts/common" - kcr "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry_1_1_0" + kcr "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry" ) type peer struct { @@ -32,24 +34,126 @@ type peer struct { var ( workflowDonPeers = []peer{ { - PeerID: "12D3KooWQXfwA26jysiKKPXKuHcJtWTbGSwzoJxj4rYtEJyQTnFj", - Signer: "0xC44686106b85687F741e1d6182a5e2eD2211a115", - EncryptionPublicKey: "0x0f8b6629bc26321b39dfb7e2bc096584fe43dccfda54b67c24f53fd827efbc72", + PeerID: "12D3KooWBCF1XT5Wi8FzfgNCqRL76Swv8TRU3TiD4QiJm8NMNX7N", + Signer: "0x9639dCc7D0ca4468B5f684ef89F12F0B365c9F6d", + EncryptionPublicKey: "0xe7f44e3eedf3527199efec7334183b5384ba0e7c7c57b390b63a3de5a10cd53c", }, { - PeerID: "12D3KooWGCRg5wNKoRFUAypA68ZkwXz8dT5gyF3VdQpEH3FtLqHZ", - Signer: "0x0ee7C8Aa7F8cb5E08415C57B79d7d387F2665E8b", - EncryptionPublicKey: "0x4cb8a297d524469e63e8d8a15c7682891126987acaa39bc4f1db78c066f7af63", + PeerID: "12D3KooWG1AyvwmCpZ93J8pBQUE1SuzrjDXnT4BeouncHR3jWLCG", + Signer: "0x8f0fAE64f5f75067833ed5deDC2804B62b21383d", + EncryptionPublicKey: "0x315c6097f89baef3c3ae1503b801aaabf411134ffec66bbe8d1d184540588728", }, { - PeerID: "12D3KooWHggbPfMcSSAwpBZHvwpo2UHzkf1ij3qjTnRiWQ7S5p4g", - Signer: "0xEd850731Be048afE986DaA90Bb482BC3b0f78aec", - EncryptionPublicKey: "0x7a9be509ace5f004fa397b7013893fed13a135dd273f7293dc3c7b6e57f1764e", + PeerID: "12D3KooWGeUKZBRMbx27FUTgBwZa9Ap9Ym92mywwpuqkEtz8XWyv", + Signer: "0xf09A863D920840c13277e76F43CFBdfB22b8FB7C", + EncryptionPublicKey: "0xa7a5e118213552a939f310e19167f49e9ad952cfe9d51eaae1ad37d92d9f0583", }, { - PeerID: "12D3KooWC44picK3WvVkP1oufHYu1mB18xUg6mF2sNKM8Hc3EmdW", - Signer: "0xD3400B75f2016878dC2013ff2bC2Cf03bD5F19f5", - EncryptionPublicKey: "0x66dcec518809c1dd4ec5c094f651061b974d3cdbf5388cf4f47740c76fb58616", + PeerID: "12D3KooW9zYWQv3STmDeNDidyzxsJSTxoCTLicafgfeEz9nhwhC4", + Signer: "0x7eD90b519bC3054a575C464dBf39946b53Ff90EF", + EncryptionPublicKey: "0x75f75a86910eed0259e3107b3c368f72c0ad0301bac696fd340916e2437194c3", + }, + { + PeerID: "12D3KooWG1AeBnSJH2mdcDusXQVye2jqodZ6pftTH98HH6xvrE97", + Signer: "0x8F572978673d711b2F061EB7d514BD46EAD6668A", + EncryptionPublicKey: "0xd032f1e884a22fd05151f59565f05a4ccbf984afccbbee13469fc25947e69360", + }, + { + PeerID: "12D3KooWBf3PrkhNoPEmp7iV291YnPuuTsgEDHTscLajxoDvwHGA", + Signer: "0x21eF07Dfaf8f7C10CB0d53D18b641ee690541f9D", + EncryptionPublicKey: "0xed64ed4a2c2954f7390bfdf41a714934c0e55693ad1c0b91505d51f4eb9e4c06", + }, + { + PeerID: "12D3KooWP3FrMTFXXRU2tBC8aYvEBgUX6qhcH9q2JZCUi9Wvc2GX", + Signer: "0x7Fa21F6f716CFaF8f249564D72Ce727253186C89", + EncryptionPublicKey: "0xed64ed4a2c2954f7390bfdf41a714934c0e55693ad1c0b91505d51f4eb9e4c06", + }, + } + triggerDonPeers = []peer{ + { + PeerID: "12D3KooWBaiTbbRwwt2fbNifiL7Ew9tn3vds9AJE3Nf3eaVBX36m", + Signer: "0x9CcE7293a4Cc2621b61193135A95928735e4795F", + EncryptionPublicKey: "0xed64ed4a2c2954f7390bfdf41a714934c0e55693ad1c0b91505d51f4eb9e4c06", + }, + { + PeerID: "12D3KooWS7JSY9fzSfWgbCE1S3W2LNY6ZVpRuun74moVBkKj6utE", + Signer: "0x3c775F20bCB2108C1A818741Ce332Bb5fe0dB925", + EncryptionPublicKey: "0xed64ed4a2c2954f7390bfdf41a714934c0e55693ad1c0b91505d51f4eb9e4c06", + }, + { + PeerID: "12D3KooWMMTDXcWhpVnwrdAer1jnVARTmnr3RyT3v7Djg8ZuoBh9", + Signer: "0x50314239e2CF05555ceeD53E7F47eB2A8Eab0dbB", + EncryptionPublicKey: "0xce0e88d12d568653757f1db154f9c503db3d3d7b37cb03d84b61f39f09824cc0", + }, + { + PeerID: "12D3KooWGzVXsKxXsF4zLgxSDM8Gzx1ywq2pZef4PrHMKuVg4K3P", + Signer: "0xd76A4f98898c3b9A72b244476d7337b50D54BCd8", + EncryptionPublicKey: "0xce0e88d12d568653757f1db154f9c503db3d3d7b37cb03d84b61f39f09824cc0", + }, + { + PeerID: "12D3KooWSyjmmzjVtCzwN7bXzZQFmWiJRuVcKBerNjVgL7HdLJBW", + Signer: "0x656A873f6895b8a03Fb112dE927d43FA54B2c92A", + EncryptionPublicKey: "0x91f11910104ff55209d6d344a15eef6a222a54d4973aaebd301807444b555e3f", + }, + { + PeerID: "12D3KooWLGz9gzhrNsvyM6XnXS3JRkZoQdEzuAvysovnSChNK5ZK", + Signer: "0x5d1e87d87bF2e0cD4Ea64F381a2dbF45e5f0a553", + EncryptionPublicKey: "0x20ff771215e567cf7e9a1fea8f2d4df90adc8303794175f79893037ff8808b51", + }, + { + PeerID: "12D3KooWAvZnvknFAfSiUYjATyhzEJLTeKvAzpcLELHi4ogM3GET", + Signer: "0x91d9b0062265514f012Eb8fABA59372fD9520f56", + EncryptionPublicKey: "0x54176f154052068943569b676fa7eec7dc836e17bbe743ce56b1c7e205191d9c", + }, + } + targetDonPeers = []peer{ + { + PeerID: "12D3KooWJrthXtnPHw7xyHFAxo6NxifYTvc8igKYaA6wRRRqtsMb", + Signer: "0x3F82750353Ea7a051ec9bA011BC628284f9a5327", + EncryptionPublicKey: "0x1a746e0fcaf3e50db87bcc765fbbaee7d24a28166ea1461338a03fcbffb088cf", + }, + { + PeerID: "12D3KooWFQekP9sGex4XhqEJav5EScjTpDVtDqJFg1JvrePBCEGJ", + Signer: "0xc23545876A208AA0443B1b8d552c7be4FF4b53F0", + EncryptionPublicKey: "0x1a746e0fcaf3e50db87bcc765fbbaee7d24a28166ea1461338a03fcbffb088cf", + }, + { + PeerID: "12D3KooWFLEq4hYtdyKWwe47dXGEbSiHMZhmr5xLSJNhpfiEz8NF", + Signer: "0x82601Fa43d8B1dC1d4eB640451aC86a7CDA37011", + EncryptionPublicKey: "0x1a746e0fcaf3e50db87bcc765fbbaee7d24a28166ea1461338a03fcbffb088cf", + }, + { + PeerID: "12D3KooWN2hztiXNNS1jMQTTvvPRYcarK1C7T3Mdqk4x4gwyo5WS", + Signer: "0x1a684B3d8f917fe496b7B1A8b29EDDAED64F649f", + EncryptionPublicKey: "0x1a746e0fcaf3e50db87bcc765fbbaee7d24a28166ea1461338a03fcbffb088cf", + }, + } + + aptosTargetDonPeers = []peer{ + { + PeerID: "12D3KooWNBr1AD3vD3dzSLgg1tK56qyJoenDx7EYNnZpbr1g4jD6", + Signer: "a41f9a561ff2266d94240996a76f9c2b3b7d8184", + EncryptionPublicKey: "0xf28fcfaf2933289b3a98d387f6edf85853df32528c094dee9e737f4ca63e5a30", + }, + { + PeerID: "12D3KooWRRgWiZGw5GYsPa62CkwFNKJb5u4hWo4DinnvjG6GE6Nj", + Signer: "e4f3c7204776530fb7833db6f9dbfdb8bd0ec96892965324a71c20d6776f67f0", + EncryptionPublicKey: "0x49c837675372d8f430e69ccd91c43029600c2c6469a2f933c4a1c4bbbc974c6d", + }, + { + PeerID: "12D3KooWKwzgUHw5YbqUsYUVt3yiLSJcqc8ANofUtqHX6qTm7ox2", + Signer: "4071ea00e2e2c76b3406018ba9f66bf6b9aee3a6762e62ac823b1ee91ba7d7b0", + EncryptionPublicKey: "0x8fe005ef16d57091160c0b4373232e7389c321dff971fc0251a39e360d9ac34a", + }, + { + PeerID: "12D3KooWBRux5o2bw1j3SQwEHzCspjkt7Xe3Y3agRUuab2SUnExj", + Signer: "6f5180c7d276876dbe413bf9b0efff7301d1367f39f4bac64180090cab70989b", + EncryptionPublicKey: "0x90dd41db21351c06396761dd683a82c791cd71e536fce246e582a4ef058091ae", + }, + { + PeerID: "12D3KooWFqvDaMSDGa6eMSTF9en6G2c3ZbGLmaA5Xs3AgxVBPb8B", + Signer: "dbce9a6df8a04d54e52a109d01ee9b5d32873b1d2436cf7b7fae61fd6eca46f8", + EncryptionPublicKey: "0x87cf298dd236a307ea887cd5d81eb0b708e3dd48c984c0700bb26c072e427942", }, } @@ -200,7 +304,7 @@ func (c *deployAndInitializeCapabilitiesRegistryCommand) Run(args []string) { Version: "1.0.0", CapabilityType: uint8(0), // trigger } - _, err = reg.GetHashedCapabilityId(&bind.CallOpts{}, streamsTrigger.LabelledName, streamsTrigger.Version) + sid, err := reg.GetHashedCapabilityId(&bind.CallOpts{}, streamsTrigger.LabelledName, streamsTrigger.Version) if err != nil { panic(err) } @@ -230,7 +334,7 @@ func (c *deployAndInitializeCapabilitiesRegistryCommand) Run(args []string) { Version: "1.0.0", CapabilityType: uint8(3), // target } - _, err = reg.GetHashedCapabilityId(&bind.CallOpts{}, writeChain.LabelledName, writeChain.Version) + wid, err := reg.GetHashedCapabilityId(&bind.CallOpts{}, writeChain.LabelledName, writeChain.Version) if err != nil { log.Printf("failed to call GetHashedCapabilityId: %s", err) } @@ -240,7 +344,7 @@ func (c *deployAndInitializeCapabilitiesRegistryCommand) Run(args []string) { Version: "1.0.0", CapabilityType: uint8(3), // target } - _, err = reg.GetHashedCapabilityId(&bind.CallOpts{}, aptosWriteChain.LabelledName, aptosWriteChain.Version) + awid, err := reg.GetHashedCapabilityId(&bind.CallOpts{}, aptosWriteChain.LabelledName, aptosWriteChain.Version) if err != nil { log.Printf("failed to call GetHashedCapabilityId: %s", err) } @@ -294,7 +398,37 @@ func (c *deployAndInitializeCapabilitiesRegistryCommand) Run(args []string) { panic(innerErr) } - n.HashedCapabilityIds = [][32]byte{ocrid, ctid, aid} + n.HashedCapabilityIds = [][32]byte{ocrid, ctid} + nodes = append(nodes, n) + } + + for _, triggerPeer := range triggerDonPeers { + n, innerErr := peerToNode(nopID, triggerPeer) + if innerErr != nil { + panic(innerErr) + } + + n.HashedCapabilityIds = [][32]byte{sid} + nodes = append(nodes, n) + } + + for _, targetPeer := range targetDonPeers { + n, innerErr := peerToNode(nopID, targetPeer) + if innerErr != nil { + panic(innerErr) + } + + n.HashedCapabilityIds = [][32]byte{wid} + nodes = append(nodes, n) + } + + for _, targetPeer := range aptosTargetDonPeers { + n, innerErr := peerToNode(nopID, targetPeer) + if innerErr != nil { + panic(innerErr) + } + + n.HashedCapabilityIds = [][32]byte{awid} nodes = append(nodes, n) } @@ -337,11 +471,100 @@ func (c *deployAndInitializeCapabilitiesRegistryCommand) Run(args []string) { Config: ccfgb, }, } - _, err = reg.AddDON(env.Owner, ps, cfgs, true, true, 1) + _, err = reg.AddDON(env.Owner, ps, cfgs, true, true, 2) if err != nil { log.Printf("workflowDON: failed to AddDON: %s", err) } + // trigger DON + ps, err = peers(triggerDonPeers) + if err != nil { + panic(err) + } + + config := &capabilitiespb.CapabilityConfig{ + DefaultConfig: values.Proto(values.EmptyMap()).GetMapValue(), + RemoteConfig: &capabilitiespb.CapabilityConfig_RemoteTriggerConfig{ + RemoteTriggerConfig: &capabilitiespb.RemoteTriggerConfig{ + RegistrationRefresh: durationpb.New(20 * time.Second), + RegistrationExpiry: durationpb.New(60 * time.Second), + // F + 1 + MinResponsesToAggregate: uint32(1) + 1, + }, + }, + } + configb, err := proto.Marshal(config) + if err != nil { + panic(err) + } + cfgs = []kcr.CapabilitiesRegistryCapabilityConfiguration{ + { + CapabilityId: sid, + Config: configb, + }, + } + _, err = reg.AddDON(env.Owner, ps, cfgs, true, false, 1) + if err != nil { + log.Printf("triggerDON: failed to AddDON: %s", err) + } + + // target DON + ps, err = peers(targetDonPeers) + if err != nil { + panic(err) + } + + targetCapabilityConfig := newCapabilityConfig() + targetCapabilityConfig.RemoteConfig = &capabilitiespb.CapabilityConfig_RemoteTargetConfig{ + RemoteTargetConfig: &capabilitiespb.RemoteTargetConfig{ + RequestHashExcludedAttributes: []string{"signed_report.Signatures"}, + }, + } + + remoteTargetConfigBytes, err := proto.Marshal(targetCapabilityConfig) + if err != nil { + panic(err) + } + + cfgs = []kcr.CapabilitiesRegistryCapabilityConfiguration{ + { + CapabilityId: wid, + Config: remoteTargetConfigBytes, + }, + } + _, err = reg.AddDON(env.Owner, ps, cfgs, true, false, 1) + if err != nil { + log.Printf("targetDON: failed to AddDON: %s", err) + } + + // Aptos target DON + ps, err = peers(aptosTargetDonPeers) + if err != nil { + panic(err) + } + + targetCapabilityConfig = newCapabilityConfig() + targetCapabilityConfig.RemoteConfig = &capabilitiespb.CapabilityConfig_RemoteTargetConfig{ + RemoteTargetConfig: &capabilitiespb.RemoteTargetConfig{ + RequestHashExcludedAttributes: []string{"signed_report.Signatures"}, + }, + } + + remoteTargetConfigBytes, err = proto.Marshal(targetCapabilityConfig) + if err != nil { + panic(err) + } + + cfgs = []kcr.CapabilitiesRegistryCapabilityConfiguration{ + { + CapabilityId: awid, + Config: remoteTargetConfigBytes, + }, + } + _, err = reg.AddDON(env.Owner, ps, cfgs, true, false, 1) + if err != nil { + log.Printf("targetDON: failed to AddDON: %s", err) + } } func deployCapabilitiesRegistry(env helpers.Environment) *kcr.CapabilitiesRegistry { diff --git a/core/scripts/keystone/src/88_gen_jobspecs.go b/core/scripts/keystone/src/88_gen_jobspecs.go index e88833c9865..4f59a89be2d 100644 --- a/core/scripts/keystone/src/88_gen_jobspecs.go +++ b/core/scripts/keystone/src/88_gen_jobspecs.go @@ -7,7 +7,7 @@ import ( "strings" helpers "github.com/smartcontractkit/chainlink/core/scripts/common" - "github.com/smartcontractkit/chainlink/deployment/keystone/changeset" + ksdeploy "github.com/smartcontractkit/chainlink/deployment/keystone" ) type spec []string @@ -74,7 +74,7 @@ func replacePlaceholders( chainID, p2pPort int64, contractAddress, bootHost string, - boot, node changeset.NodeKeys, + boot, node ksdeploy.NodeKeys, ) (output []string) { chainIDStr := strconv.FormatInt(chainID, 10) bootstrapper := fmt.Sprintf("%s@%s:%d", boot.P2PPeerID, bootHost, p2pPort) diff --git a/core/scripts/keystone/src/88_gen_ocr3_config.go b/core/scripts/keystone/src/88_gen_ocr3_config.go index 94217b07f4e..a437410346a 100644 --- a/core/scripts/keystone/src/88_gen_ocr3_config.go +++ b/core/scripts/keystone/src/88_gen_ocr3_config.go @@ -3,18 +3,19 @@ package src import ( helpers "github.com/smartcontractkit/chainlink/core/scripts/common" "github.com/smartcontractkit/chainlink/deployment" - ksdeploy "github.com/smartcontractkit/chainlink/deployment/keystone/changeset" + ksdeploy "github.com/smartcontractkit/chainlink/deployment/keystone" ) func mustReadConfig(fileName string) (output ksdeploy.TopLevelConfigSource) { return mustParseJSON[ksdeploy.TopLevelConfigSource](fileName) } -func generateOCR3Config(nodeList string, configFile string, chainID int64, pubKeysPath string) ksdeploy.OCR3OnchainConfig { +func generateOCR3Config(nodeList string, configFile string, chainID int64, pubKeysPath string) ksdeploy.Orc2drOracleConfig { topLevelCfg := mustReadConfig(configFile) cfg := topLevelCfg.OracleConfig + cfg.OCRSecrets = deployment.XXXGenerateTestOCRSecrets() nca := downloadNodePubKeys(nodeList, chainID, pubKeysPath) - c, err := ksdeploy.GenerateOCR3Config(cfg, nca, deployment.XXXGenerateTestOCRSecrets()) + c, err := ksdeploy.GenerateOCR3Config(cfg, nca) helpers.PanicErr(err) return c } diff --git a/core/scripts/keystone/src/99_fetch_keys.go b/core/scripts/keystone/src/99_fetch_keys.go index 056769dc714..8899da95b11 100644 --- a/core/scripts/keystone/src/99_fetch_keys.go +++ b/core/scripts/keystone/src/99_fetch_keys.go @@ -13,17 +13,17 @@ import ( "github.com/urfave/cli" helpers "github.com/smartcontractkit/chainlink/core/scripts/common" - "github.com/smartcontractkit/chainlink/deployment/keystone/changeset" + ksdeploy "github.com/smartcontractkit/chainlink/deployment/keystone" ubig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" "github.com/smartcontractkit/chainlink/v2/core/cmd" "github.com/smartcontractkit/chainlink/v2/core/web/presenters" ) -func downloadNodePubKeys(nodeList string, chainID int64, pubKeysPath string) []changeset.NodeKeys { +func downloadNodePubKeys(nodeList string, chainID int64, pubKeysPath string) []ksdeploy.NodeKeys { // Check if file exists already, and if so, return the keys if _, err := os.Stat(pubKeysPath); err == nil { fmt.Println("Loading existing public keys at:", pubKeysPath) - return mustParseJSON[[]changeset.NodeKeys](pubKeysPath) + return mustParseJSON[[]ksdeploy.NodeKeys](pubKeysPath) } nodes := downloadNodeAPICredentials(nodeList) @@ -97,7 +97,7 @@ type ocr2Bundle struct { ConfigPublicKey string `json:"configPublicKey"` } -func mustFetchNodesKeys(chainID int64, nodes []*node) (nca []changeset.NodeKeys) { +func mustFetchNodesKeys(chainID int64, nodes []*node) (nca []ksdeploy.NodeKeys) { for _, n := range nodes { output := &bytes.Buffer{} client, app := newApp(n, output) @@ -209,7 +209,7 @@ func mustFetchNodesKeys(chainID int64, nodes []*node) (nca []changeset.NodeKeys) helpers.PanicErr(err) output.Reset() - nc := changeset.NodeKeys{ + nc := ksdeploy.NodeKeys{ EthAddress: ethAddress, AptosAccount: aptosAccount, P2PPeerID: peerID, diff --git a/core/services/chainlink/application.go b/core/services/chainlink/application.go index 4004b86c341..abbe9dad9ab 100644 --- a/core/services/chainlink/application.go +++ b/core/services/chainlink/application.go @@ -20,7 +20,6 @@ import ( "go.uber.org/multierr" "go.uber.org/zap/zapcore" - "github.com/smartcontractkit/chainlink-common/pkg/custmsg" "github.com/smartcontractkit/chainlink-common/pkg/loop" commonservices "github.com/smartcontractkit/chainlink-common/pkg/services" "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" @@ -214,16 +213,10 @@ func NewApplication(opts ApplicationOpts) (Application, error) { opts.CapabilitiesRegistry = capabilities.NewRegistry(globalLogger) } - var gatewayConnectorWrapper *gatewayconnector.ServiceWrapper - if cfg.Capabilities().GatewayConnector().DonID() != "" { - globalLogger.Debugw("Creating GatewayConnector wrapper", "donID", cfg.Capabilities().GatewayConnector().DonID()) - gatewayConnectorWrapper = gatewayconnector.NewGatewayConnectorServiceWrapper( - cfg.Capabilities().GatewayConnector(), - keyStore.Eth(), - clockwork.NewRealClock(), - globalLogger) - srvcs = append(srvcs, gatewayConnectorWrapper) - } + // TODO: wire this up to config so we only instantiate it + // if a workflow registry address is provided. + workflowRegistrySyncer := syncer.NewWorkflowRegistry() + srvcs = append(srvcs, workflowRegistrySyncer) var externalPeerWrapper p2ptypes.PeerWrapper if cfg.Capabilities().Peering().Enabled() { @@ -269,66 +262,32 @@ func NewApplication(opts ApplicationOpts) (Application, error) { return nil, fmt.Errorf("could not configure syncer: %w", err) } - workflowDonNotifier := capabilities.NewDonNotifier() - wfLauncher := capabilities.NewLauncher( globalLogger, externalPeerWrapper, dispatcher, opts.CapabilitiesRegistry, - workflowDonNotifier, ) registrySyncer.AddLauncher(wfLauncher) srvcs = append(srvcs, wfLauncher, registrySyncer) - - if cfg.Capabilities().WorkflowRegistry().Address() != "" { - if gatewayConnectorWrapper == nil { - return nil, errors.New("unable to create workflow registry syncer without gateway connector") - } - - err = keyStore.Workflow().EnsureKey(context.Background()) - if err != nil { - return nil, fmt.Errorf("failed to ensure workflow key: %w", err) - } - - keys, err := keyStore.Workflow().GetAll() - if err != nil { - return nil, fmt.Errorf("failed to get all workflow keys: %w", err) - } - if len(keys) != 1 { - return nil, fmt.Errorf("expected 1 key, got %d", len(keys)) - } - - lggr := globalLogger.Named("WorkflowRegistrySyncer") - fetcher := syncer.NewFetcherService(lggr, gatewayConnectorWrapper) - - eventHandler := syncer.NewEventHandler(lggr, syncer.NewWorkflowRegistryDS(opts.DS, globalLogger), - fetcher.Fetch, workflowstore.NewDBStore(opts.DS, lggr, clockwork.NewRealClock()), opts.CapabilitiesRegistry, - custmsg.NewLabeler(), clockwork.NewRealClock(), keys[0]) - - globalLogger.Debugw("Creating WorkflowRegistrySyncer") - wfSyncer := syncer.NewWorkflowRegistry( - lggr, - func(ctx context.Context, bytes []byte) (syncer.ContractReader, error) { - return relayer.NewContractReader(ctx, bytes) - }, - cfg.Capabilities().WorkflowRegistry().Address(), - syncer.WorkflowEventPollerConfig{ - QueryCount: 100, - }, - eventHandler, - workflowDonNotifier, - ) - - srvcs = append(srvcs, fetcher, wfSyncer) - } } } else { globalLogger.Debug("External registry not configured, skipping registry syncer and starting with an empty registry") opts.CapabilitiesRegistry.SetLocalRegistry(&capabilities.TestMetadataRegistry{}) } + var gatewayConnectorWrapper *gatewayconnector.ServiceWrapper + if cfg.Capabilities().GatewayConnector().DonID() != "" { + globalLogger.Debugw("Creating GatewayConnector wrapper", "donID", cfg.Capabilities().GatewayConnector().DonID()) + gatewayConnectorWrapper = gatewayconnector.NewGatewayConnectorServiceWrapper( + cfg.Capabilities().GatewayConnector(), + keyStore.Eth(), + clockwork.NewRealClock(), + globalLogger) + srvcs = append(srvcs, gatewayConnectorWrapper) + } + // LOOPs can be created as options, in the case of LOOP relayers, or // as OCR2 job implementations, in the case of Median today. // We will have a non-nil registry here in LOOP relayers are being used, otherwise @@ -519,6 +478,7 @@ func NewApplication(opts ApplicationOpts) (Application, error) { delegates[job.Workflow] = workflows.NewDelegate( globalLogger, opts.CapabilitiesRegistry, + workflowRegistrySyncer, workflowORM, ) diff --git a/core/services/chainlink/config_capabilities.go b/core/services/chainlink/config_capabilities.go index 37ab1fce72f..032eec58bea 100644 --- a/core/services/chainlink/config_capabilities.go +++ b/core/services/chainlink/config_capabilities.go @@ -22,12 +22,6 @@ func (c *capabilitiesConfig) ExternalRegistry() config.CapabilitiesExternalRegis } } -func (c *capabilitiesConfig) WorkflowRegistry() config.CapabilitiesWorkflowRegistry { - return &capabilitiesWorkflowRegistry{ - c: c.c.WorkflowRegistry, - } -} - func (c *capabilitiesConfig) Dispatcher() config.Dispatcher { return &dispatcher{d: c.c.Dispatcher} } @@ -94,26 +88,6 @@ func (c *capabilitiesExternalRegistry) Address() string { return *c.c.Address } -type capabilitiesWorkflowRegistry struct { - c toml.WorkflowRegistry -} - -func (c *capabilitiesWorkflowRegistry) RelayID() types.RelayID { - return types.NewRelayID(c.NetworkID(), c.ChainID()) -} - -func (c *capabilitiesWorkflowRegistry) NetworkID() string { - return *c.c.NetworkID -} - -func (c *capabilitiesWorkflowRegistry) ChainID() string { - return *c.c.ChainID -} - -func (c *capabilitiesWorkflowRegistry) Address() string { - return *c.c.Address -} - type gatewayConnector struct { c toml.GatewayConnector } diff --git a/core/services/chainlink/config_database.go b/core/services/chainlink/config_database.go index 27e61479146..fe10c63f71b 100644 --- a/core/services/chainlink/config_database.go +++ b/core/services/chainlink/config_database.go @@ -4,10 +4,9 @@ import ( "net/url" "time" - pgcommon "github.com/smartcontractkit/chainlink-common/pkg/sqlutil/pg" - "github.com/smartcontractkit/chainlink/v2/core/config" "github.com/smartcontractkit/chainlink/v2/core/config/toml" + "github.com/smartcontractkit/chainlink/v2/core/store/dialects" ) type backupConfig struct { @@ -107,13 +106,10 @@ func (d *databaseConfig) DefaultQueryTimeout() time.Duration { } func (d *databaseConfig) URL() url.URL { - if d.s.URL == nil { - return url.URL{} - } return *d.s.URL.URL() } -func (d *databaseConfig) Dialect() pgcommon.DialectName { +func (d *databaseConfig) Dialect() dialects.DialectName { return d.c.Dialect } diff --git a/core/services/chainlink/config_database_test.go b/core/services/chainlink/config_database_test.go index f8f864f97ab..b52d17452aa 100644 --- a/core/services/chainlink/config_database_test.go +++ b/core/services/chainlink/config_database_test.go @@ -7,9 +7,8 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - pgcommon "github.com/smartcontractkit/chainlink-common/pkg/sqlutil/pg" - "github.com/smartcontractkit/chainlink/v2/core/config" + "github.com/smartcontractkit/chainlink/v2/core/store/dialects" ) func TestDatabaseConfig(t *testing.T) { @@ -22,31 +21,31 @@ URL = "postgresql://doesnotexist:justtopassvalidationtests@localhost:5432/chainl require.NoError(t, err) backup := cfg.Database().Backup() - assert.Equal(t, "test/backup/dir", backup.Dir()) - assert.Equal(t, 1*time.Hour, backup.Frequency()) - assert.Equal(t, config.DatabaseBackupModeFull, backup.Mode()) - assert.True(t, backup.OnVersionUpgrade()) + assert.Equal(t, backup.Dir(), "test/backup/dir") + assert.Equal(t, backup.Frequency(), 1*time.Hour) + assert.Equal(t, backup.Mode(), config.DatabaseBackupModeFull) + assert.Equal(t, backup.OnVersionUpgrade(), true) assert.Nil(t, backup.URL()) db := cfg.Database() - assert.Equal(t, 1*time.Minute, db.DefaultIdleInTxSessionTimeout()) - assert.Equal(t, 1*time.Hour, db.DefaultLockTimeout()) - assert.Equal(t, 1*time.Second, db.DefaultQueryTimeout()) - assert.True(t, db.LogSQL()) - assert.Equal(t, 7, db.MaxIdleConns()) - assert.Equal(t, 13, db.MaxOpenConns()) - assert.True(t, db.MigrateDatabase()) - assert.Equal(t, pgcommon.Postgres, db.Dialect()) + assert.Equal(t, db.DefaultIdleInTxSessionTimeout(), 1*time.Minute) + assert.Equal(t, db.DefaultLockTimeout(), 1*time.Hour) + assert.Equal(t, db.DefaultQueryTimeout(), 1*time.Second) + assert.Equal(t, db.LogSQL(), true) + assert.Equal(t, db.MaxIdleConns(), 7) + assert.Equal(t, db.MaxOpenConns(), 13) + assert.Equal(t, db.MigrateDatabase(), true) + assert.Equal(t, db.Dialect(), dialects.Postgres) url := db.URL() assert.NotEqual(t, url.String(), "") lock := db.Lock() - assert.Equal(t, "none", lock.LockingMode()) - assert.Equal(t, 1*time.Minute, lock.LeaseDuration()) - assert.Equal(t, 1*time.Second, lock.LeaseRefreshInterval()) + assert.Equal(t, lock.LockingMode(), "none") + assert.Equal(t, lock.LeaseDuration(), 1*time.Minute) + assert.Equal(t, lock.LeaseRefreshInterval(), 1*time.Second) l := db.Listener() - assert.Equal(t, 1*time.Minute, l.MaxReconnectDuration()) - assert.Equal(t, 5*time.Minute, l.MinReconnectInterval()) - assert.Equal(t, 2*time.Minute, l.FallbackPollInterval()) + assert.Equal(t, l.MaxReconnectDuration(), 1*time.Minute) + assert.Equal(t, l.MinReconnectInterval(), 5*time.Minute) + assert.Equal(t, l.FallbackPollInterval(), 2*time.Minute) } diff --git a/core/services/chainlink/config_mercury.go b/core/services/chainlink/config_mercury.go index 0e56105406b..bc4aed6fb07 100644 --- a/core/services/chainlink/config_mercury.go +++ b/core/services/chainlink/config_mercury.go @@ -50,10 +50,6 @@ func (m *mercuryTransmitterConfig) TransmitTimeout() commonconfig.Duration { return *m.c.TransmitTimeout } -func (m *mercuryTransmitterConfig) TransmitConcurrency() uint32 { - return *m.c.TransmitConcurrency -} - type mercuryConfig struct { c toml.Mercury s toml.MercurySecrets diff --git a/core/services/chainlink/config_test.go b/core/services/chainlink/config_test.go index 65ece5a88c0..76b80672dbb 100644 --- a/core/services/chainlink/config_test.go +++ b/core/services/chainlink/config_test.go @@ -494,11 +494,6 @@ func TestConfig_Marshal(t *testing.T) { ChainID: ptr("1"), NetworkID: ptr("evm"), }, - WorkflowRegistry: toml.WorkflowRegistry{ - Address: ptr(""), - ChainID: ptr("1"), - NetworkID: ptr("evm"), - }, Dispatcher: toml.Dispatcher{ SupportedVersion: ptr(1), ReceiverBufferSize: ptr(10000), @@ -654,7 +649,6 @@ func TestConfig_Marshal(t *testing.T) { NoNewFinalizedHeadsThreshold: &hour, Transactions: evmcfg.Transactions{ - Enabled: ptr(true), MaxInFlight: ptr[uint32](19), MaxQueued: ptr[uint32](99), ReaperInterval: &minute, @@ -751,7 +745,6 @@ func TestConfig_Marshal(t *testing.T) { TxTimeout: commoncfg.MustNewDuration(time.Hour), TxRetryTimeout: commoncfg.MustNewDuration(time.Minute), TxConfirmTimeout: commoncfg.MustNewDuration(time.Second), - TxExpirationRebroadcast: ptr(false), TxRetentionTimeout: commoncfg.MustNewDuration(0 * time.Second), SkipPreflight: ptr(true), Commitment: ptr("banana"), @@ -845,7 +838,6 @@ func TestConfig_Marshal(t *testing.T) { Transmitter: toml.MercuryTransmitter{ TransmitQueueMaxSize: ptr(uint32(123)), TransmitTimeout: commoncfg.MustNewDuration(234 * time.Second), - TransmitConcurrency: ptr(uint32(456)), }, VerboseLogging: ptr(true), } @@ -1120,7 +1112,6 @@ FinalizedBlockOffset = 16 NoNewFinalizedHeadsThreshold = '1h0m0s' [EVM.Transactions] -Enabled = true ForwardersEnabled = true MaxInFlight = 19 MaxQueued = 99 @@ -1282,7 +1273,6 @@ OCR2CacheTTL = '1h0m0s' TxTimeout = '1h0m0s' TxRetryTimeout = '1m0s' TxConfirmTimeout = '1s' -TxExpirationRebroadcast = false TxRetentionTimeout = '0s' SkipPreflight = true Commitment = 'banana' @@ -1358,7 +1348,6 @@ CertFile = '/path/to/cert.pem' [Mercury.Transmitter] TransmitQueueMaxSize = 123 TransmitTimeout = '3m54s' -TransmitConcurrency = 456 `}, {"full", full, fullTOML}, {"multi-chain", multiChain, multiChainTOML}, diff --git a/core/services/chainlink/mocks/relayer_chain_interoperators.go b/core/services/chainlink/mocks/relayer_chain_interoperators.go index bc30ede77ee..3ebe1411c19 100644 --- a/core/services/chainlink/mocks/relayer_chain_interoperators.go +++ b/core/services/chainlink/mocks/relayer_chain_interoperators.go @@ -4,7 +4,6 @@ import ( "context" "slices" - commonTypes "github.com/smartcontractkit/chainlink/v2/common/types" services2 "github.com/smartcontractkit/chainlink/v2/core/services" "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" @@ -70,6 +69,6 @@ func (f *FakeRelayerChainInteroperators) ChainStatus(ctx context.Context, id typ panic("unimplemented") } -func (f *FakeRelayerChainInteroperators) ChainStatuses(ctx context.Context, offset, limit int) ([]commonTypes.ChainStatusWithID, int, error) { +func (f *FakeRelayerChainInteroperators) ChainStatuses(ctx context.Context, offset, limit int) ([]types.ChainStatus, int, error) { panic("unimplemented") } diff --git a/core/services/chainlink/relayer_chain_interoperators.go b/core/services/chainlink/relayer_chain_interoperators.go index 2fc671bfe6e..8197b12ec7b 100644 --- a/core/services/chainlink/relayer_chain_interoperators.go +++ b/core/services/chainlink/relayer_chain_interoperators.go @@ -11,10 +11,8 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/types" "github.com/smartcontractkit/chainlink-cosmos/pkg/cosmos" "github.com/smartcontractkit/chainlink-cosmos/pkg/cosmos/adapters" - "github.com/smartcontractkit/chainlink/v2/core/services/relay" - commonTypes "github.com/smartcontractkit/chainlink/v2/common/types" "github.com/smartcontractkit/chainlink/v2/core/chains" "github.com/smartcontractkit/chainlink/v2/core/chains/legacyevm" "github.com/smartcontractkit/chainlink/v2/core/services" @@ -54,7 +52,7 @@ type LegacyChainer interface { type ChainStatuser interface { ChainStatus(ctx context.Context, id types.RelayID) (types.ChainStatus, error) - ChainStatuses(ctx context.Context, offset, limit int) ([]commonTypes.ChainStatusWithID, int, error) + ChainStatuses(ctx context.Context, offset, limit int) ([]types.ChainStatus, int, error) } // NodesStatuser is an interface for node configuration and state. @@ -156,7 +154,7 @@ func InitCosmos(ctx context.Context, factory RelayerFactory, config CosmosFactor // InitSolana is a option for instantiating Solana relayers func InitSolana(ctx context.Context, factory RelayerFactory, config SolanaFactoryConfig) CoreRelayerChainInitFunc { return func(op *CoreRelayerChainInteroperators) error { - solRelayers, err := factory.NewSolana(config) + solRelayers, err := factory.NewSolana(config.Keystore, config.TOMLConfigs) if err != nil { return fmt.Errorf("failed to setup Solana relayer: %w", err) } @@ -262,9 +260,9 @@ func (rs *CoreRelayerChainInteroperators) ChainStatus(ctx context.Context, id ty return lr.GetChainStatus(ctx) } -func (rs *CoreRelayerChainInteroperators) ChainStatuses(ctx context.Context, offset, limit int) ([]commonTypes.ChainStatusWithID, int, error) { +func (rs *CoreRelayerChainInteroperators) ChainStatuses(ctx context.Context, offset, limit int) ([]types.ChainStatus, int, error) { var ( - stats []commonTypes.ChainStatusWithID + stats []types.ChainStatus totalErr error ) rs.mu.Lock() @@ -284,7 +282,7 @@ func (rs *CoreRelayerChainInteroperators) ChainStatuses(ctx context.Context, off totalErr = errors.Join(totalErr, err) continue } - stats = append(stats, commonTypes.ChainStatusWithID{ChainStatus: stat, RelayID: rid}) + stats = append(stats, stat) } if totalErr != nil { diff --git a/core/services/chainlink/relayer_factory.go b/core/services/chainlink/relayer_factory.go index a1571663d5a..3740878fd19 100644 --- a/core/services/chainlink/relayer_factory.go +++ b/core/services/chainlink/relayer_factory.go @@ -7,7 +7,6 @@ import ( "net/http" "github.com/pelletier/go-toml/v2" - "github.com/prometheus/client_golang/prometheus" "github.com/smartcontractkit/chainlink-common/pkg/loop" "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" @@ -38,7 +37,6 @@ type RelayerFactory struct { logger.Logger *plugins.LoopRegistry loop.GRPCOpts - Registerer prometheus.Registerer MercuryPool wsrpc.Pool CapabilitiesRegistry coretypes.CapabilitiesRegistry HTTPClient *http.Client @@ -56,7 +54,7 @@ func (r *RelayerFactory) NewDummy(config DummyFactoryConfig) (loop.Relayer, erro type EVMFactoryConfig struct { legacyevm.ChainOpts evmrelay.CSAETHKeystore - MercuryConfig coreconfig.Mercury + coreconfig.MercuryTransmitter } func (r *RelayerFactory) NewEVM(ctx context.Context, config EVMFactoryConfig) (map[types.RelayID]evmrelay.LOOPRelayAdapter, error) { @@ -83,10 +81,9 @@ func (r *RelayerFactory) NewEVM(ctx context.Context, config EVMFactoryConfig) (m relayerOpts := evmrelay.RelayerOpts{ DS: ccOpts.DS, - Registerer: r.Registerer, CSAETHKeystore: config.CSAETHKeystore, MercuryPool: r.MercuryPool, - MercuryConfig: config.MercuryConfig, + TransmitterConfig: config.MercuryTransmitter, CapabilitiesRegistry: r.CapabilitiesRegistry, HTTPClient: r.HTTPClient, RetirementReportCache: r.RetirementReportCache, @@ -107,11 +104,9 @@ func (r *RelayerFactory) NewEVM(ctx context.Context, config EVMFactoryConfig) (m type SolanaFactoryConfig struct { Keystore keystore.Solana solcfg.TOMLConfigs - DS sqlutil.DataSource } -func (r *RelayerFactory) NewSolana(config SolanaFactoryConfig) (map[types.RelayID]loop.Relayer, error) { - chainCfgs, ds, ks := config.TOMLConfigs, config.DS, config.Keystore +func (r *RelayerFactory) NewSolana(ks keystore.Solana, chainCfgs solcfg.TOMLConfigs) (map[types.RelayID]loop.Relayer, error) { solanaRelayers := make(map[types.RelayID]loop.Relayer) var ( solLggr = r.Logger.Named("Solana") @@ -164,7 +159,6 @@ func (r *RelayerFactory) NewSolana(config SolanaFactoryConfig) (map[types.RelayI opts := solana.ChainOpts{ Logger: lggr, KeyStore: signer, - DS: ds, } chain, err := solana.NewChain(chainCfg, opts) diff --git a/core/services/chainlink/testdata/config-empty-effective.toml b/core/services/chainlink/testdata/config-empty-effective.toml index a2052c04a8e..cd51afac5f8 100644 --- a/core/services/chainlink/testdata/config-empty-effective.toml +++ b/core/services/chainlink/testdata/config-empty-effective.toml @@ -237,7 +237,6 @@ CertFile = '' [Mercury.Transmitter] TransmitQueueMaxSize = 10000 TransmitTimeout = '5s' -TransmitConcurrency = 100 [Capabilities] [Capabilities.Peering] @@ -269,11 +268,6 @@ Address = '' NetworkID = 'evm' ChainID = '1' -[Capabilities.WorkflowRegistry] -Address = '' -NetworkID = 'evm' -ChainID = '1' - [Capabilities.GatewayConnector] ChainIDForNodeKey = '' NodeAddress = '' diff --git a/core/services/chainlink/testdata/config-full.toml b/core/services/chainlink/testdata/config-full.toml index 6878e09c911..c6a5302a459 100644 --- a/core/services/chainlink/testdata/config-full.toml +++ b/core/services/chainlink/testdata/config-full.toml @@ -247,7 +247,6 @@ CertFile = '/path/to/cert.pem' [Mercury.Transmitter] TransmitQueueMaxSize = 123 TransmitTimeout = '3m54s' -TransmitConcurrency = 456 [Capabilities] [Capabilities.Peering] @@ -279,11 +278,6 @@ Address = '' NetworkID = 'evm' ChainID = '1' -[Capabilities.WorkflowRegistry] -Address = '' -NetworkID = 'evm' -ChainID = '1' - [Capabilities.GatewayConnector] ChainIDForNodeKey = '11155111' NodeAddress = '0x68902d681c28119f9b2531473a417088bf008e59' @@ -337,7 +331,6 @@ FinalizedBlockOffset = 16 NoNewFinalizedHeadsThreshold = '1h0m0s' [EVM.Transactions] -Enabled = true ForwardersEnabled = true MaxInFlight = 19 MaxQueued = 99 @@ -499,7 +492,6 @@ OCR2CacheTTL = '1h0m0s' TxTimeout = '1h0m0s' TxRetryTimeout = '1m0s' TxConfirmTimeout = '1s' -TxExpirationRebroadcast = false TxRetentionTimeout = '0s' SkipPreflight = true Commitment = 'banana' diff --git a/core/services/chainlink/testdata/config-multi-chain-effective.toml b/core/services/chainlink/testdata/config-multi-chain-effective.toml index ba7538cac04..e8da8142181 100644 --- a/core/services/chainlink/testdata/config-multi-chain-effective.toml +++ b/core/services/chainlink/testdata/config-multi-chain-effective.toml @@ -237,7 +237,6 @@ CertFile = '' [Mercury.Transmitter] TransmitQueueMaxSize = 10000 TransmitTimeout = '5s' -TransmitConcurrency = 100 [Capabilities] [Capabilities.Peering] @@ -269,11 +268,6 @@ Address = '' NetworkID = 'evm' ChainID = '1' -[Capabilities.WorkflowRegistry] -Address = '' -NetworkID = 'evm' -ChainID = '1' - [Capabilities.GatewayConnector] ChainIDForNodeKey = '' NodeAddress = '' @@ -320,7 +314,6 @@ FinalizedBlockOffset = 12 NoNewFinalizedHeadsThreshold = '9m0s' [EVM.Transactions] -Enabled = true ForwardersEnabled = false MaxInFlight = 16 MaxQueued = 250 @@ -431,7 +424,6 @@ FinalizedBlockOffset = 0 NoNewFinalizedHeadsThreshold = '0s' [EVM.Transactions] -Enabled = true ForwardersEnabled = false MaxInFlight = 16 MaxQueued = 250 @@ -536,7 +528,6 @@ FinalizedBlockOffset = 0 NoNewFinalizedHeadsThreshold = '6m0s' [EVM.Transactions] -Enabled = true ForwardersEnabled = false MaxInFlight = 16 MaxQueued = 5000 @@ -662,7 +653,6 @@ OCR2CacheTTL = '1m0s' TxTimeout = '1m0s' TxRetryTimeout = '10s' TxConfirmTimeout = '30s' -TxExpirationRebroadcast = false TxRetentionTimeout = '0s' SkipPreflight = true Commitment = 'confirmed' @@ -708,7 +698,6 @@ OCR2CacheTTL = '1m0s' TxTimeout = '1m0s' TxRetryTimeout = '10s' TxConfirmTimeout = '30s' -TxExpirationRebroadcast = false TxRetentionTimeout = '0s' SkipPreflight = true Commitment = 'confirmed' diff --git a/core/services/feeds/models.go b/core/services/feeds/models.go index a6cf103b4e9..93dddd86dae 100644 --- a/core/services/feeds/models.go +++ b/core/services/feeds/models.go @@ -12,7 +12,6 @@ import ( "gopkg.in/guregu/null.v4" proto "github.com/smartcontractkit/chainlink-protos/orchestrator/feedsmanager" - "github.com/smartcontractkit/chainlink/v2/core/utils/crypto" ) @@ -83,7 +82,6 @@ const ( ChainTypeEVM ChainType = "EVM" ChainTypeSolana ChainType = "SOLANA" ChainTypeStarknet ChainType = "STARKNET" - ChainTypeTron ChainType = "TRON" ) func NewChainType(s string) (ChainType, error) { @@ -96,8 +94,6 @@ func NewChainType(s string) (ChainType, error) { return ChainTypeSolana, nil case "APTOS": return ChainTypeAptos, nil - case "TRON": - return ChainTypeTron, nil default: return ChainTypeUnknown, errors.New("invalid chain type") } diff --git a/core/services/feeds/models_test.go b/core/services/feeds/models_test.go index d0d4382b055..13567281735 100644 --- a/core/services/feeds/models_test.go +++ b/core/services/feeds/models_test.go @@ -28,11 +28,6 @@ func Test_NewChainType(t *testing.T) { give: "STARKNET", want: ChainTypeStarknet, }, - { - name: "Tron Chain Type", - give: "TRON", - want: ChainTypeTron, - }, { name: "Invalid Chain Type", give: "", diff --git a/core/services/feeds/service.go b/core/services/feeds/service.go index 04ab747c9ab..f986d1753af 100644 --- a/core/services/feeds/service.go +++ b/core/services/feeds/service.go @@ -19,11 +19,9 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" ccip "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/validate" - "github.com/smartcontractkit/chainlink/v2/core/services/streams" "github.com/smartcontractkit/chainlink/v2/plugins" pb "github.com/smartcontractkit/chainlink-protos/orchestrator/feedsmanager" - "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" "github.com/smartcontractkit/chainlink/v2/core/chains/legacyevm" @@ -128,7 +126,6 @@ type service struct { p2pKeyStore keystore.P2P ocr1KeyStore keystore.OCR ocr2KeyStore keystore.OCR2 - workflowKeyStore keystore.Workflow jobSpawner job.Spawner gCfg GeneralConfig featCfg FeatureConfig @@ -171,7 +168,6 @@ func NewService( csaKeyStore: keyStore.CSA(), ocr1KeyStore: keyStore.OCR(), ocr2KeyStore: keyStore.OCR2(), - workflowKeyStore: keyStore.Workflow(), gCfg: gCfg, featCfg: fCfg, insecureCfg: insecureCfg, @@ -279,11 +275,9 @@ func (s *service) SyncNodeInfo(ctx context.Context, id int64) error { cfgMsgs = append(cfgMsgs, cfgMsg) } - workflowKey := s.getWorkflowPublicKey() if _, err = fmsClient.UpdateNode(ctx, &pb.UpdateNodeRequest{ Version: s.version, ChainConfigs: cfgMsgs, - WorkflowKey: &workflowKey, }); err != nil { return err } @@ -368,8 +362,8 @@ func (s *service) ListManagersByIDs(ctx context.Context, ids []int64) ([]FeedsMa return nil, errors.Wrap(err, "failed to list managers by IDs") } - for i, manager := range managers { - managers[i].IsConnectionActive = s.connMgr.IsConnected(manager.ID) + for _, manager := range managers { + manager.IsConnectionActive = s.connMgr.IsConnected(manager.ID) } return managers, nil @@ -516,33 +510,6 @@ func (s *service) DeleteJob(ctx context.Context, args *DeleteJobArgs) (int64, er logger.Errorw("Failed to push metrics for job proposal deletion", "err", err) } - // auto-cancellation for Workflow specs - if !proposal.ExternalJobID.Valid { - logger.Infow("ExternalJobID is null", "id", proposal.ID, "name", proposal.Name) - return proposal.ID, nil - } - job, err := s.jobORM.FindJobByExternalJobID(ctx, proposal.ExternalJobID.UUID) - if err != nil { - // NOTE: at this stage, we don't know if this job is of Workflow type - // so we don't want to return an error - logger.Infow("FindJobByExternalJobID failed", "id", proposal.ID, "externalJobID", proposal.ExternalJobID.UUID, "name", proposal.Name) - return proposal.ID, nil - } - if job.WorkflowSpecID != nil { // this is a Workflow job - jobSpecID := int64(*job.WorkflowSpecID) - jpSpec, err2 := s.orm.GetApprovedSpec(ctx, proposal.ID) - if err2 != nil { - logger.Errorw("GetApprovedSpec failed - no approved specs to cancel?", "id", proposal.ID, "err", err2, "name", job.Name) - // return success if there are no approved specs to cancel - return proposal.ID, nil - } - if err := s.CancelSpec(ctx, jpSpec.ID); err != nil { - logger.Errorw("Failed to auto-cancel workflow spec", "jobProposalID", proposal.ID, "jobProposalSpecID", jpSpec.ID, "jobSpecID", jobSpecID, "err", err, "name", job.Name) - return 0, fmt.Errorf("failed to auto-cancel workflow spec (job proposal spec ID: %d): %w", jpSpec.ID, err) - } - logger.Infow("Successfully auto-cancelled a workflow spec", "jobProposalID", proposal.ID, "jobProposalSpecID", jpSpec.ID, "jobSpecID", jobSpecID, "name", job.Name) - } - return proposal.ID, nil } @@ -892,13 +859,6 @@ func (s *service) ApproveSpec(ctx context.Context, id int64, force bool) error { if txerr != nil && !errors.Is(txerr, sql.ErrNoRows) { return fmt.Errorf("failed while checking for existing ccip job: %w", txerr) } - case job.Stream: - existingJobID, txerr = tx.jobORM.FindJobIDByStreamID(ctx, *j.StreamID) - // Return an error if the repository errors. If there is a not found - // error we want to continue with approving the job. - if txerr != nil && !errors.Is(txerr, sql.ErrNoRows) { - return fmt.Errorf("failed while checking for existing stream job: %w", txerr) - } default: return errors.Errorf("unsupported job type when approving job proposal specs: %s", j.Type) } @@ -1183,20 +1143,6 @@ func (s *service) getCSAPrivateKey() (privkey []byte, err error) { return keys[0].Raw(), nil } -// getWorkflowPublicKey retrieves the server's Workflow public key. -// Since there will be at most one key, it returns the first key found. -// If an error occurs or no keys are found, it returns blank. -func (s *service) getWorkflowPublicKey() string { - keys, err := s.workflowKeyStore.GetAll() - if err != nil { - return "" - } - if len(keys) < 1 { - return "" - } - return keys[0].PublicKeyString() -} - // observeJobProposalCounts is a helper method that queries the repository for the count of // job proposals by status and then updates prometheus gauges. func (s *service) observeJobProposalCounts(ctx context.Context) error { @@ -1303,8 +1249,6 @@ func (s *service) generateJob(ctx context.Context, spec string) (*job.Job, error js, err = workflows.ValidatedWorkflowJobSpec(ctx, spec) case job.CCIP: js, err = ccip.ValidatedCCIPSpec(spec) - case job.Stream: - js, err = streams.ValidatedStreamSpec(spec) default: return nil, errors.Errorf("unknown job type: %s", jobType) } diff --git a/core/services/feeds/service_test.go b/core/services/feeds/service_test.go index d449d585401..115695d8514 100644 --- a/core/services/feeds/service_test.go +++ b/core/services/feeds/service_test.go @@ -5,7 +5,6 @@ import ( "database/sql" "encoding/hex" "fmt" - "math/big" "testing" "time" @@ -21,10 +20,9 @@ import ( commonconfig "github.com/smartcontractkit/chainlink-common/pkg/config" "github.com/smartcontractkit/chainlink-common/pkg/services/servicetest" proto "github.com/smartcontractkit/chainlink-protos/orchestrator/feedsmanager" - "github.com/smartcontractkit/chainlink/v2/core/chains/evm/headtracker" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" - evmbig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" "github.com/smartcontractkit/chainlink/v2/core/chains/legacyevm" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" @@ -38,9 +36,8 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/services/job" jobmocks "github.com/smartcontractkit/chainlink/v2/core/services/job/mocks" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/csakey" + "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/keystest" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/ocrkey" - "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/p2pkey" - "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/workflowkey" ksmocks "github.com/smartcontractkit/chainlink/v2/core/services/keystore/mocks" "github.com/smartcontractkit/chainlink/v2/core/services/pipeline" "github.com/smartcontractkit/chainlink/v2/core/services/versioning" @@ -137,41 +134,6 @@ answer1 [type=median index=0]; [pluginConfig.juelsPerFeeCoinCache] updateInterval = "1m" ` - -const StreamTestSpecTemplate = ` -name = '%s' -type = 'stream' -schemaVersion = 1 -externalJobID = '%s' -streamID = %d -observationSource = """ -ds1_payload [type=bridge name=\"bridge-ncfx\" timeout=\"50s\" requestData=\"{\\\"data\\\":{\\\"endpoint\\\":\\\"cryptolwba\\\",\\\"from\\\":\\\"SEI\\\",\\\"to\\\":\\\"USD\\\"}}\"]; -ds1_benchmark [type=jsonparse path=\"data,mid\"]; -ds1_bid [type=jsonparse path=\"data,bid\"]; -ds1_ask [type=jsonparse path=\"data,ask\"]; -ds2_payload [type=bridge name=\"bridge-tiingo\" timeout=\"50s\" requestData=\"{\\\"data\\\":{\\\"endpoint\\\":\\\"cryptolwba\\\",\\\"from\\\":\\\"SEI\\\",\\\"to\\\":\\\"USD\\\"}}\"]; -ds2_benchmark [type=jsonparse path=\"data,mid\"]; -ds2_bid [type=jsonparse path=\"data,bid\"]; -ds2_ask [type=jsonparse path=\"data,ask\"]; -ds3_payload [type=bridge name=\"bridge-gsr\" timeout=\"50s\" requestData=\"{\\\"data\\\":{\\\"endpoint\\\":\\\"cryptolwba\\\",\\\"from\\\":\\\"SEI\\\",\\\"to\\\":\\\"USD\\\"}}\"]; -ds3_benchmark [type=jsonparse path=\"data,mid\"]; -ds3_bid [type=jsonparse path=\"data,bid\"]; -ds3_ask [type=jsonparse path=\"data,ask\"]; -ds1_payload -> ds1_benchmark -> benchmark_price; -ds2_payload -> ds2_benchmark -> benchmark_price; -ds3_payload -> ds3_benchmark -> benchmark_price; -benchmark_price [type=median allowedFaults=2 index=0]; -ds1_payload -> ds1_bid -> bid_price; -ds2_payload -> ds2_bid -> bid_price; -ds3_payload -> ds3_bid -> bid_price; -bid_price [type=median allowedFaults=2 index=1]; -ds1_payload -> ds1_ask -> ask_price; -ds2_payload -> ds2_ask -> ask_price; -ds3_payload -> ds3_ask -> ask_price; -ask_price [type=median allowedFaults=2 index=2]; -""" -` - const BootstrapTestSpecTemplate = ` type = "bootstrap" schemaVersion = 1 @@ -184,17 +146,16 @@ chainID = 1337 type TestService struct { feeds.Service - orm *mocks.ORM - jobORM *jobmocks.ORM - connMgr *mocks.ConnectionsManager - spawner *jobmocks.Spawner - fmsClient *mocks.FeedsManagerClient - csaKeystore *ksmocks.CSA - p2pKeystore *ksmocks.P2P - ocr1Keystore *ksmocks.OCR - ocr2Keystore *ksmocks.OCR2 - workflowKeystore *ksmocks.Workflow - legacyChains legacyevm.LegacyChainContainer + orm *mocks.ORM + jobORM *jobmocks.ORM + connMgr *mocks.ConnectionsManager + spawner *jobmocks.Spawner + fmsClient *mocks.FeedsManagerClient + csaKeystore *ksmocks.CSA + p2pKeystore *ksmocks.P2P + ocr1Keystore *ksmocks.OCR + ocr2Keystore *ksmocks.OCR2 + legacyChains legacyevm.LegacyChainContainer } func setupTestService(t *testing.T) *TestService { @@ -207,16 +168,15 @@ func setupTestServiceCfg(t *testing.T, overrideCfg func(c *chainlink.Config, s * t.Helper() var ( - orm = mocks.NewORM(t) - jobORM = jobmocks.NewORM(t) - connMgr = mocks.NewConnectionsManager(t) - spawner = jobmocks.NewSpawner(t) - fmsClient = mocks.NewFeedsManagerClient(t) - csaKeystore = ksmocks.NewCSA(t) - p2pKeystore = ksmocks.NewP2P(t) - ocr1Keystore = ksmocks.NewOCR(t) - ocr2Keystore = ksmocks.NewOCR2(t) - workflowKeystore = ksmocks.NewWorkflow(t) + orm = mocks.NewORM(t) + jobORM = jobmocks.NewORM(t) + connMgr = mocks.NewConnectionsManager(t) + spawner = jobmocks.NewSpawner(t) + fmsClient = mocks.NewFeedsManagerClient(t) + csaKeystore = ksmocks.NewCSA(t) + p2pKeystore = ksmocks.NewP2P(t) + ocr1Keystore = ksmocks.NewOCR(t) + ocr2Keystore = ksmocks.NewOCR2(t) ) lggr := logger.TestLogger(t) @@ -232,23 +192,21 @@ func setupTestServiceCfg(t *testing.T, overrideCfg func(c *chainlink.Config, s * keyStore.On("P2P").Return(p2pKeystore) keyStore.On("OCR").Return(ocr1Keystore) keyStore.On("OCR2").Return(ocr2Keystore) - keyStore.On("Workflow").Return(workflowKeystore) svc := feeds.NewService(orm, jobORM, db, spawner, keyStore, gcfg, gcfg.Feature(), gcfg.Insecure(), gcfg.JobPipeline(), gcfg.OCR(), gcfg.OCR2(), legacyChains, lggr, "1.0.0", nil) svc.SetConnectionsManager(connMgr) return &TestService{ - Service: svc, - orm: orm, - jobORM: jobORM, - connMgr: connMgr, - spawner: spawner, - fmsClient: fmsClient, - csaKeystore: csaKeystore, - p2pKeystore: p2pKeystore, - ocr1Keystore: ocr1Keystore, - ocr2Keystore: ocr2Keystore, - workflowKeystore: workflowKeystore, - legacyChains: legacyChains, + Service: svc, + orm: orm, + jobORM: jobORM, + connMgr: connMgr, + spawner: spawner, + fmsClient: fmsClient, + csaKeystore: csaKeystore, + p2pKeystore: p2pKeystore, + ocr1Keystore: ocr1Keystore, + ocr2Keystore: ocr2Keystore, + legacyChains: legacyChains, } } @@ -618,15 +576,10 @@ func Test_Service_CreateChainConfig(t *testing.T) { svc = setupTestService(t) ) - workflowKey, err := workflowkey.New() - require.NoError(t, err) - svc.workflowKeystore.On("GetAll").Return([]workflowkey.Key{workflowKey}, nil) - svc.orm.On("CreateChainConfig", mock.Anything, cfg).Return(int64(1), nil) svc.orm.On("GetManager", mock.Anything, mgr.ID).Return(&mgr, nil) svc.connMgr.On("GetClient", mgr.ID).Return(svc.fmsClient, nil) svc.orm.On("ListChainConfigsByManagerIDs", mock.Anything, []int64{mgr.ID}).Return([]feeds.ChainConfig{cfg}, nil) - wkID := workflowKey.ID() svc.fmsClient.On("UpdateNode", mock.Anything, &proto.UpdateNodeRequest{ Version: nodeVersion.Version, ChainConfigs: []*proto.ChainConfig{ @@ -643,7 +596,6 @@ func Test_Service_CreateChainConfig(t *testing.T) { Ocr2Config: &proto.OCR2Config{Enabled: false}, }, }, - WorkflowKey: &wkID, }).Return(&proto.UpdateNodeResponse{}, nil) actual, err := svc.CreateChainConfig(testutils.Context(t), cfg) @@ -688,20 +640,14 @@ func Test_Service_DeleteChainConfig(t *testing.T) { svc = setupTestService(t) ) - workflowKey, err := workflowkey.New() - require.NoError(t, err) - svc.workflowKeystore.On("GetAll").Return([]workflowkey.Key{workflowKey}, nil) - svc.orm.On("GetChainConfig", mock.Anything, cfg.ID).Return(&cfg, nil) svc.orm.On("DeleteChainConfig", mock.Anything, cfg.ID).Return(cfg.ID, nil) svc.orm.On("GetManager", mock.Anything, mgr.ID).Return(&mgr, nil) svc.connMgr.On("GetClient", mgr.ID).Return(svc.fmsClient, nil) svc.orm.On("ListChainConfigsByManagerIDs", mock.Anything, []int64{mgr.ID}).Return([]feeds.ChainConfig{}, nil) - wkID := workflowKey.ID() svc.fmsClient.On("UpdateNode", mock.Anything, &proto.UpdateNodeRequest{ Version: nodeVersion.Version, ChainConfigs: []*proto.ChainConfig{}, - WorkflowKey: &wkID, }).Return(&proto.UpdateNodeResponse{}, nil) actual, err := svc.DeleteChainConfig(testutils.Context(t), cfg.ID) @@ -779,15 +725,10 @@ func Test_Service_UpdateChainConfig(t *testing.T) { svc = setupTestService(t) ) - workflowKey, err := workflowkey.New() - require.NoError(t, err) - svc.workflowKeystore.On("GetAll").Return([]workflowkey.Key{workflowKey}, nil) - svc.orm.On("UpdateChainConfig", mock.Anything, cfg).Return(int64(1), nil) svc.orm.On("GetChainConfig", mock.Anything, cfg.ID).Return(&cfg, nil) svc.connMgr.On("GetClient", mgr.ID).Return(svc.fmsClient, nil) svc.orm.On("ListChainConfigsByManagerIDs", mock.Anything, []int64{mgr.ID}).Return([]feeds.ChainConfig{cfg}, nil) - wkID := workflowKey.ID() svc.fmsClient.On("UpdateNode", mock.Anything, &proto.UpdateNodeRequest{ Version: nodeVersion.Version, ChainConfigs: []*proto.ChainConfig{ @@ -804,7 +745,6 @@ func Test_Service_UpdateChainConfig(t *testing.T) { Ocr2Config: &proto.OCR2Config{Enabled: false}, }, }, - WorkflowKey: &wkID, }).Return(&proto.UpdateNodeResponse{}, nil) actual, err := svc.UpdateChainConfig(testutils.Context(t), cfg) @@ -1329,25 +1269,12 @@ func Test_Service_DeleteJob(t *testing.T) { } approved = feeds.JobProposal{ - ID: 321, + ID: 1, FeedsManagerID: 1, RemoteUUID: remoteUUID, - ExternalJobID: uuid.NullUUID{UUID: uuid.New(), Valid: true}, Status: feeds.JobProposalStatusApproved, } - wfSpecID = int32(4321) - workflowJob = job.Job{ - ID: 1, - WorkflowSpecID: &wfSpecID, - } - jobProposalSpec = &feeds.JobProposalSpec{ - ID: 20, - Status: feeds.SpecStatusApproved, - JobProposalID: approved.ID, - Version: 1, - } - httpTimeout = *commonconfig.MustNewDuration(1 * time.Second) ) @@ -1364,7 +1291,6 @@ func Test_Service_DeleteJob(t *testing.T) { svc.orm.On("GetJobProposalByRemoteUUID", mock.Anything, approved.RemoteUUID).Return(&approved, nil) svc.orm.On("DeleteProposal", mock.Anything, approved.ID).Return(nil) svc.orm.On("CountJobProposalsByStatus", mock.Anything).Return(&feeds.JobProposalCounts{}, nil) - svc.jobORM.On("FindJobByExternalJobID", mock.Anything, approved.ExternalJobID.UUID).Return(job.Job{}, sql.ErrNoRows) }, args: args, wantID: approved.ID, @@ -1408,38 +1334,6 @@ func Test_Service_DeleteJob(t *testing.T) { args: args, wantErr: "DeleteProposal failed", }, - { - name: "Delete workflow-spec with auto-cancellation", - before: func(svc *TestService) { - svc.orm.On("GetJobProposalByRemoteUUID", mock.Anything, approved.RemoteUUID).Return(&approved, nil) - svc.orm.On("DeleteProposal", mock.Anything, approved.ID).Return(nil) - svc.orm.On("CountJobProposalsByStatus", mock.Anything).Return(&feeds.JobProposalCounts{}, nil) - svc.jobORM.On("FindJobByExternalJobID", mock.Anything, approved.ExternalJobID.UUID).Return(workflowJob, nil) - svc.orm.On("GetApprovedSpec", mock.Anything, approved.ID).Return(jobProposalSpec, nil) - - // mocks for CancelSpec() - svc.orm.On("GetSpec", mock.Anything, jobProposalSpec.ID).Return(jobProposalSpec, nil) - svc.orm.On("GetJobProposal", mock.Anything, approved.ID).Return(&approved, nil) - svc.connMgr.On("GetClient", mock.Anything).Return(svc.fmsClient, nil) - - svc.orm.On("CancelSpec", mock.Anything, jobProposalSpec.ID).Return(nil) - svc.jobORM.On("FindJobByExternalJobID", mock.Anything, approved.ExternalJobID.UUID).Return(workflowJob, nil) - svc.spawner.On("DeleteJob", mock.Anything, mock.Anything, workflowJob.ID).Return(nil) - - svc.fmsClient.On("CancelledJob", - mock.MatchedBy(func(ctx context.Context) bool { return true }), - &proto.CancelledJobRequest{ - Uuid: approved.RemoteUUID.String(), - Version: int64(jobProposalSpec.Version), - }, - ).Return(&proto.CancelledJobResponse{}, nil) - svc.orm.On("CountJobProposalsByStatus", mock.Anything).Return(&feeds.JobProposalCounts{}, nil) - svc.orm.On("WithDataSource", mock.Anything).Return(feeds.ORM(svc.orm)) - svc.jobORM.On("WithDataSource", mock.Anything).Return(job.ORM(svc.jobORM)) - }, - args: args, - wantID: approved.ID, - }, } for _, tc := range testCases { @@ -1726,14 +1620,11 @@ func Test_Service_SyncNodeInfo(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - p2pKey := p2pkey.MustNewV2XXXTestingOnly(big.NewInt(1)) + p2pKey := keystest.NewP2PKeyV2(t) ocrKey, err := ocrkey.NewV2() require.NoError(t, err) - workflowKey, err := workflowkey.New() - require.NoError(t, err) - var ( multiaddr = "/dns4/chain.link/tcp/1234/p2p/16Uiu2HAm58SP7UL8zsnpeuwHfytLocaqgnyaYKP8wu7qRdrixLju" mgr = &feeds.FeedsManager{ID: 1} @@ -1781,8 +1672,6 @@ func Test_Service_SyncNodeInfo(t *testing.T) { svc.p2pKeystore.On("Get", p2pKey.PeerID()).Return(p2pKey, nil) svc.ocr1Keystore.On("Get", ocrKey.GetID()).Return(ocrKey, nil) - svc.workflowKeystore.On("GetAll").Return([]workflowkey.Key{workflowKey}, nil) - wkID := workflowKey.ID() svc.fmsClient.On("UpdateNode", mock.Anything, &proto.UpdateNodeRequest{ Version: nodeVersion.Version, ChainConfigs: []*proto.ChainConfig{ @@ -1823,7 +1712,6 @@ func Test_Service_SyncNodeInfo(t *testing.T) { }, }, }, - WorkflowKey: &wkID, }).Return(&proto.UpdateNodeResponse{}, nil) err = svc.SyncNodeInfo(testutils.Context(t), mgr.ID) @@ -2158,7 +2046,7 @@ func Test_Service_ListSpecsByJobProposalIDs(t *testing.T) { } func Test_Service_ApproveSpec(t *testing.T) { - var evmChainID *evmbig.Big + var evmChainID *big.Big address := types.EIP55AddressFromAddress(common.Address{}) externalJobID := uuid.New() @@ -3380,514 +3268,6 @@ updateInterval = "20m" } } -func Test_Service_ApproveSpec_Stream(t *testing.T) { - externalJobID := uuid.New() - streamName := "LINK / ETH | version 3 | contract 0x0000000000000000000000000000000000000000" - streamID := uint32(1009001032) - - var ( - ctx = testutils.Context(t) - - jp = &feeds.JobProposal{ - ID: 1, - FeedsManagerID: 100, - } - spec = &feeds.JobProposalSpec{ - ID: 20, - Status: feeds.SpecStatusPending, - JobProposalID: jp.ID, - Version: 1, - Definition: fmt.Sprintf(StreamTestSpecTemplate, streamName, externalJobID.String(), streamID), - } - rejectedSpec = &feeds.JobProposalSpec{ - ID: 20, - Status: feeds.SpecStatusRejected, - JobProposalID: jp.ID, - Version: 1, - Definition: fmt.Sprintf(StreamTestSpecTemplate, streamName, externalJobID.String(), streamID), - } - cancelledSpec = &feeds.JobProposalSpec{ - ID: 20, - Status: feeds.SpecStatusCancelled, - JobProposalID: jp.ID, - Version: 1, - Definition: fmt.Sprintf(StreamTestSpecTemplate, streamName, externalJobID.String(), streamID), - } - j = job.Job{ - ID: 1, - ExternalJobID: externalJobID, - } - ) - - testCases := []struct { - name string - httpTimeout *commonconfig.Duration - before func(svc *TestService) - id int64 - force bool - wantErr string - }{ - { - name: "pending job success", - httpTimeout: commonconfig.MustNewDuration(1 * time.Minute), - before: func(svc *TestService) { - svc.orm.On("GetSpec", mock.Anything, spec.ID).Return(spec, nil) - svc.orm.On("GetJobProposal", mock.Anything, jp.ID).Return(jp, nil) - svc.connMgr.On("GetClient", jp.FeedsManagerID).Return(svc.fmsClient, nil) - svc.jobORM.On("AssertBridgesExist", mock.Anything, mock.IsType(pipeline.Pipeline{})).Return(nil) - svc.jobORM.On("FindJobByExternalJobID", mock.Anything, externalJobID).Return(job.Job{}, sql.ErrNoRows) - svc.jobORM.On("FindJobIDByStreamID", mock.Anything, mock.Anything).Return(int32(0), sql.ErrNoRows) - - svc.spawner. - On("CreateJob", - mock.Anything, - mock.Anything, - mock.MatchedBy(func(j *job.Job) bool { - return j.Name.String == streamName - }), - ). - Run(func(args mock.Arguments) { (args.Get(2).(*job.Job)).ID = 1 }). - Return(nil) - svc.orm.On("ApproveSpec", - mock.Anything, - spec.ID, - externalJobID, - ).Return(nil) - svc.fmsClient.On("ApprovedJob", - mock.MatchedBy(func(ctx context.Context) bool { return true }), - &proto.ApprovedJobRequest{ - Uuid: jp.RemoteUUID.String(), - Version: int64(spec.Version), - }, - ).Return(&proto.ApprovedJobResponse{}, nil) - svc.orm.On("CountJobProposalsByStatus", mock.Anything).Return(&feeds.JobProposalCounts{}, nil) - svc.orm.On("WithDataSource", mock.Anything).Return(feeds.ORM(svc.orm)) - svc.jobORM.On("WithDataSource", mock.Anything).Return(job.ORM(svc.jobORM)) - }, - id: spec.ID, - force: false, - }, - { - name: "cancelled spec success when it is the latest spec", - httpTimeout: commonconfig.MustNewDuration(1 * time.Minute), - before: func(svc *TestService) { - svc.connMgr.On("GetClient", jp.FeedsManagerID).Return(svc.fmsClient, nil) - svc.orm.On("GetSpec", mock.Anything, cancelledSpec.ID, mock.Anything).Return(cancelledSpec, nil) - svc.orm.On("GetJobProposal", mock.Anything, jp.ID).Return(jp, nil) - svc.orm.On("GetLatestSpec", mock.Anything, cancelledSpec.JobProposalID).Return(cancelledSpec, nil) - svc.jobORM.On("AssertBridgesExist", mock.Anything, mock.IsType(pipeline.Pipeline{})).Return(nil) - - svc.jobORM.On("FindJobByExternalJobID", mock.Anything, externalJobID).Return(job.Job{}, sql.ErrNoRows) - svc.jobORM.On("FindJobIDByStreamID", mock.Anything, mock.Anything).Return(int32(0), sql.ErrNoRows) - - svc.spawner. - On("CreateJob", - mock.Anything, - mock.Anything, - mock.MatchedBy(func(j *job.Job) bool { - return j.Name.String == streamName - }), - ). - Run(func(args mock.Arguments) { (args.Get(2).(*job.Job)).ID = 1 }). - Return(nil) - svc.orm.On("ApproveSpec", - mock.Anything, - cancelledSpec.ID, - externalJobID, - ).Return(nil) - svc.fmsClient.On("ApprovedJob", - mock.MatchedBy(func(ctx context.Context) bool { return true }), - &proto.ApprovedJobRequest{ - Uuid: jp.RemoteUUID.String(), - Version: int64(spec.Version), - }, - ).Return(&proto.ApprovedJobResponse{}, nil) - svc.orm.On("CountJobProposalsByStatus", mock.Anything).Return(&feeds.JobProposalCounts{}, nil) - svc.orm.On("WithDataSource", mock.Anything).Return(feeds.ORM(svc.orm)) - svc.jobORM.On("WithDataSource", mock.Anything).Return(job.ORM(svc.jobORM)) - }, - id: cancelledSpec.ID, - force: false, - }, - { - name: "cancelled spec failed not latest spec", - before: func(svc *TestService) { - svc.orm.On("GetSpec", mock.Anything, cancelledSpec.ID, mock.Anything).Return(cancelledSpec, nil) - svc.orm.On("GetJobProposal", mock.Anything, jp.ID).Return(jp, nil) - svc.orm.On("GetLatestSpec", mock.Anything, cancelledSpec.JobProposalID).Return(&feeds.JobProposalSpec{ - ID: 21, - Status: feeds.SpecStatusPending, - JobProposalID: jp.ID, - Version: 2, - Definition: StreamTestSpecTemplate, - }, nil) - }, - id: cancelledSpec.ID, - force: false, - wantErr: "cannot approve a cancelled spec", - }, - { - name: "rejected spec failed cannot be approved", - before: func(svc *TestService) { - svc.orm.On("GetSpec", mock.Anything, cancelledSpec.ID, mock.Anything).Return(rejectedSpec, nil) - svc.orm.On("GetJobProposal", mock.Anything, jp.ID).Return(jp, nil) - }, - id: rejectedSpec.ID, - force: false, - wantErr: "cannot approve a rejected spec", - }, - { - name: "already existing job replacement error", - httpTimeout: commonconfig.MustNewDuration(1 * time.Minute), - before: func(svc *TestService) { - svc.connMgr.On("GetClient", jp.FeedsManagerID).Return(svc.fmsClient, nil) - svc.orm.On("GetSpec", mock.Anything, spec.ID).Return(spec, nil) - svc.orm.On("GetJobProposal", mock.Anything, jp.ID).Return(jp, nil) - svc.jobORM.On("AssertBridgesExist", mock.Anything, mock.IsType(pipeline.Pipeline{})).Return(nil) - svc.jobORM.On("FindJobByExternalJobID", mock.Anything, externalJobID).Return(job.Job{}, sql.ErrNoRows) - svc.jobORM.On("FindJobIDByStreamID", mock.Anything, mock.Anything).Return(j.ID, nil) - svc.orm.On("WithDataSource", mock.Anything).Return(feeds.ORM(svc.orm)) - svc.jobORM.On("WithDataSource", mock.Anything).Return(job.ORM(svc.jobORM)) - }, - id: spec.ID, - force: false, - wantErr: "could not approve job proposal: a job for this contract address already exists - please use the 'force' option to replace it", - }, - { - name: "already existing self managed job replacement success if forced without feedID", - httpTimeout: commonconfig.MustNewDuration(1 * time.Minute), - before: func(svc *TestService) { - svc.connMgr.On("GetClient", jp.FeedsManagerID).Return(svc.fmsClient, nil) - svc.orm.On("GetSpec", mock.Anything, spec.ID).Return(spec, nil) - svc.orm.On("GetJobProposal", mock.Anything, jp.ID).Return(jp, nil) - svc.jobORM.On("AssertBridgesExist", mock.Anything, mock.IsType(pipeline.Pipeline{})).Return(nil) - svc.orm.EXPECT().GetApprovedSpec(mock.Anything, jp.ID).Return(nil, sql.ErrNoRows) - svc.jobORM.On("FindJobByExternalJobID", mock.Anything, externalJobID).Return(job.Job{}, sql.ErrNoRows) - svc.jobORM.On("FindJobIDByStreamID", mock.Anything, mock.Anything).Return(j.ID, nil) - svc.spawner.On("DeleteJob", mock.Anything, mock.Anything, j.ID).Return(nil) - - svc.spawner. - On("CreateJob", - mock.Anything, - mock.Anything, - mock.MatchedBy(func(j *job.Job) bool { - return j.Name.String == streamName - }), - ). - Run(func(args mock.Arguments) { (args.Get(2).(*job.Job)).ID = 1 }). - Return(nil) - svc.orm.On("ApproveSpec", - mock.Anything, - spec.ID, - externalJobID, - ).Return(nil) - svc.fmsClient.On("ApprovedJob", - mock.MatchedBy(func(ctx context.Context) bool { return true }), - &proto.ApprovedJobRequest{ - Uuid: jp.RemoteUUID.String(), - Version: int64(spec.Version), - }, - ).Return(&proto.ApprovedJobResponse{}, nil) - svc.orm.On("CountJobProposalsByStatus", mock.Anything).Return(&feeds.JobProposalCounts{}, nil) - svc.orm.On("WithDataSource", mock.Anything).Return(feeds.ORM(svc.orm)) - svc.jobORM.On("WithDataSource", mock.Anything).Return(job.ORM(svc.jobORM)) - }, - id: spec.ID, - force: true, - }, - { - name: "already existing self managed job replacement success if forced with feedID", - httpTimeout: commonconfig.MustNewDuration(1 * time.Minute), - before: func(svc *TestService) { - svc.connMgr.On("GetClient", jp.FeedsManagerID).Return(svc.fmsClient, nil) - svc.orm.On("GetSpec", mock.Anything, spec.ID).Return(&feeds.JobProposalSpec{ - ID: 20, - Status: feeds.SpecStatusPending, - JobProposalID: jp.ID, - Version: 1, - Definition: fmt.Sprintf(StreamTestSpecTemplate, streamName, externalJobID.String(), streamID), - }, nil) - svc.orm.On("GetJobProposal", mock.Anything, jp.ID).Return(jp, nil) - svc.jobORM.On("AssertBridgesExist", mock.Anything, mock.IsType(pipeline.Pipeline{})).Return(nil) - svc.orm.EXPECT().GetApprovedSpec(mock.Anything, jp.ID).Return(nil, sql.ErrNoRows) - svc.jobORM.On("FindJobByExternalJobID", mock.Anything, externalJobID).Return(job.Job{}, sql.ErrNoRows) - svc.jobORM.On("FindJobIDByStreamID", mock.Anything, mock.Anything).Return(j.ID, nil) - svc.spawner.On("DeleteJob", mock.Anything, mock.Anything, j.ID).Return(nil) - - svc.spawner. - On("CreateJob", - mock.Anything, - mock.Anything, - mock.MatchedBy(func(j *job.Job) bool { - return j.Name.String == streamName - }), - ). - Run(func(args mock.Arguments) { (args.Get(2).(*job.Job)).ID = 1 }). - Return(nil) - svc.orm.On("ApproveSpec", - mock.Anything, - spec.ID, - externalJobID, - ).Return(nil) - svc.fmsClient.On("ApprovedJob", - mock.MatchedBy(func(ctx context.Context) bool { return true }), - &proto.ApprovedJobRequest{ - Uuid: jp.RemoteUUID.String(), - Version: int64(spec.Version), - }, - ).Return(&proto.ApprovedJobResponse{}, nil) - svc.orm.On("CountJobProposalsByStatus", mock.Anything).Return(&feeds.JobProposalCounts{}, nil) - svc.orm.On("WithDataSource", mock.Anything).Return(feeds.ORM(svc.orm)) - svc.jobORM.On("WithDataSource", mock.Anything).Return(job.ORM(svc.jobORM)) - }, - id: spec.ID, - force: true, - }, - { - name: "already existing FMS managed job replacement success if forced", - httpTimeout: commonconfig.MustNewDuration(1 * time.Minute), - before: func(svc *TestService) { - svc.connMgr.On("GetClient", jp.FeedsManagerID).Return(svc.fmsClient, nil) - svc.orm.On("GetSpec", mock.Anything, spec.ID).Return(spec, nil) - svc.orm.On("GetJobProposal", mock.Anything, jp.ID).Return(jp, nil) - svc.jobORM.On("AssertBridgesExist", mock.Anything, mock.IsType(pipeline.Pipeline{})).Return(nil) - svc.orm.EXPECT().GetApprovedSpec(mock.Anything, jp.ID).Return(&feeds.JobProposalSpec{ID: 100}, nil) - svc.orm.EXPECT().CancelSpec(mock.Anything, int64(100)).Return(nil) - svc.jobORM.On("FindJobByExternalJobID", mock.Anything, externalJobID).Return(job.Job{}, sql.ErrNoRows) - svc.jobORM.On("FindJobIDByStreamID", mock.Anything, mock.Anything).Return(j.ID, nil) - svc.spawner.On("DeleteJob", mock.Anything, mock.Anything, j.ID).Return(nil) - - svc.spawner. - On("CreateJob", - mock.Anything, - mock.Anything, - mock.MatchedBy(func(j *job.Job) bool { - return j.Name.String == streamName - }), - ). - Run(func(args mock.Arguments) { (args.Get(2).(*job.Job)).ID = 1 }). - Return(nil) - svc.orm.On("ApproveSpec", - mock.Anything, - spec.ID, - externalJobID, - ).Return(nil) - svc.fmsClient.On("ApprovedJob", - mock.MatchedBy(func(ctx context.Context) bool { return true }), - &proto.ApprovedJobRequest{ - Uuid: jp.RemoteUUID.String(), - Version: int64(spec.Version), - }, - ).Return(&proto.ApprovedJobResponse{}, nil) - svc.orm.On("CountJobProposalsByStatus", mock.Anything).Return(&feeds.JobProposalCounts{}, nil) - svc.orm.On("WithDataSource", mock.Anything).Return(feeds.ORM(svc.orm)) - svc.jobORM.On("WithDataSource", mock.Anything).Return(job.ORM(svc.jobORM)) - }, - id: spec.ID, - force: true, - }, - { - name: "spec does not exist", - before: func(svc *TestService) { - svc.orm.On("GetSpec", mock.Anything, spec.ID).Return(nil, errors.New("Not Found")) - }, - id: spec.ID, - force: false, - wantErr: "orm: job proposal spec: Not Found", - }, - { - name: "cannot approve an approved spec", - before: func(svc *TestService) { - aspec := &feeds.JobProposalSpec{ - ID: spec.ID, - JobProposalID: jp.ID, - Status: feeds.SpecStatusApproved, - } - svc.orm.On("GetSpec", mock.Anything, spec.ID).Return(aspec, nil) - svc.orm.On("GetJobProposal", mock.Anything, jp.ID).Return(jp, nil) - }, - id: spec.ID, - force: false, - wantErr: "cannot approve an approved spec", - }, - { - name: "cannot approved a rejected spec", - before: func(svc *TestService) { - rspec := &feeds.JobProposalSpec{ - ID: spec.ID, - JobProposalID: jp.ID, - Status: feeds.SpecStatusRejected, - } - svc.orm.On("GetSpec", mock.Anything, rspec.ID, mock.Anything).Return(rspec, nil) - svc.orm.On("GetJobProposal", mock.Anything, jp.ID).Return(jp, nil) - }, - id: spec.ID, - force: false, - wantErr: "cannot approve a rejected spec", - }, - { - name: "job proposal does not exist", - before: func(svc *TestService) { - svc.orm.On("GetSpec", mock.Anything, spec.ID).Return(spec, nil) - svc.orm.On("GetJobProposal", mock.Anything, jp.ID).Return(nil, errors.New("Not Found")) - }, - id: spec.ID, - wantErr: "orm: job proposal: Not Found", - }, - { - name: "bridges do not exist", - httpTimeout: commonconfig.MustNewDuration(1 * time.Minute), - before: func(svc *TestService) { - svc.connMgr.On("GetClient", jp.FeedsManagerID).Return(svc.fmsClient, nil) - svc.orm.On("GetSpec", mock.Anything, spec.ID).Return(spec, nil) - svc.orm.On("GetJobProposal", mock.Anything, jp.ID).Return(jp, nil) - svc.jobORM.On("AssertBridgesExist", mock.Anything, mock.IsType(pipeline.Pipeline{})).Return(errors.New("bridges do not exist")) - }, - id: spec.ID, - wantErr: "failed to approve job spec due to bridge check: bridges do not exist", - }, - { - name: "rpc client not connected", - before: func(svc *TestService) { - svc.orm.On("GetSpec", mock.Anything, spec.ID).Return(spec, nil) - svc.orm.On("GetJobProposal", mock.Anything, jp.ID).Return(jp, nil) - svc.connMgr.On("GetClient", jp.FeedsManagerID).Return(nil, errors.New("Not Connected")) - }, - id: spec.ID, - force: false, - wantErr: "fms rpc client: Not Connected", - }, - { - name: "create job error", - httpTimeout: commonconfig.MustNewDuration(1 * time.Minute), - before: func(svc *TestService) { - svc.orm.On("GetSpec", mock.Anything, spec.ID).Return(spec, nil) - svc.orm.On("GetJobProposal", mock.Anything, jp.ID).Return(jp, nil) - svc.connMgr.On("GetClient", jp.FeedsManagerID).Return(svc.fmsClient, nil) - svc.jobORM.On("AssertBridgesExist", mock.Anything, mock.IsType(pipeline.Pipeline{})).Return(nil) - - svc.jobORM.On("FindJobByExternalJobID", mock.Anything, externalJobID).Return(job.Job{}, sql.ErrNoRows) - svc.jobORM.On("FindJobIDByStreamID", mock.Anything, mock.Anything).Return(int32(0), sql.ErrNoRows) - - svc.spawner. - On("CreateJob", - mock.Anything, - mock.Anything, - mock.MatchedBy(func(j *job.Job) bool { - return j.Name.String == streamName - }), - ). - Return(errors.New("could not save")) - svc.orm.On("WithDataSource", mock.Anything).Return(feeds.ORM(svc.orm)) - svc.jobORM.On("WithDataSource", mock.Anything).Return(job.ORM(svc.jobORM)) - }, - id: spec.ID, - force: false, - wantErr: "could not approve job proposal: could not save", - }, - { - name: "approve spec orm error", - httpTimeout: commonconfig.MustNewDuration(1 * time.Minute), - before: func(svc *TestService) { - svc.orm.On("GetSpec", mock.Anything, spec.ID).Return(spec, nil) - svc.orm.On("GetJobProposal", mock.Anything, jp.ID).Return(jp, nil) - svc.connMgr.On("GetClient", jp.FeedsManagerID).Return(svc.fmsClient, nil) - svc.jobORM.On("AssertBridgesExist", mock.Anything, mock.IsType(pipeline.Pipeline{})).Return(nil) - - svc.jobORM.On("FindJobByExternalJobID", mock.Anything, externalJobID).Return(job.Job{}, sql.ErrNoRows) - svc.jobORM.On("FindJobIDByStreamID", mock.Anything, mock.Anything).Return(int32(0), sql.ErrNoRows) - - svc.spawner. - On("CreateJob", - mock.Anything, - mock.Anything, - mock.MatchedBy(func(j *job.Job) bool { - return j.Name.String == streamName - }), - ). - Run(func(args mock.Arguments) { (args.Get(2).(*job.Job)).ID = 1 }). - Return(nil) - svc.orm.On("ApproveSpec", - mock.Anything, - spec.ID, - externalJobID, - ).Return(errors.New("failure")) - svc.orm.On("WithDataSource", mock.Anything).Return(feeds.ORM(svc.orm)) - svc.jobORM.On("WithDataSource", mock.Anything).Return(job.ORM(svc.jobORM)) - }, - id: spec.ID, - force: false, - wantErr: "could not approve job proposal: failure", - }, - { - name: "fms call error", - httpTimeout: commonconfig.MustNewDuration(1 * time.Minute), - before: func(svc *TestService) { - svc.orm.On("GetSpec", mock.Anything, spec.ID).Return(spec, nil) - svc.orm.On("GetJobProposal", mock.Anything, jp.ID).Return(jp, nil) - svc.connMgr.On("GetClient", jp.FeedsManagerID).Return(svc.fmsClient, nil) - svc.jobORM.On("AssertBridgesExist", mock.Anything, mock.IsType(pipeline.Pipeline{})).Return(nil) - - svc.jobORM.On("FindJobByExternalJobID", mock.Anything, externalJobID).Return(job.Job{}, sql.ErrNoRows) - svc.jobORM.On("FindJobIDByStreamID", mock.Anything, mock.Anything).Return(int32(0), sql.ErrNoRows) - - svc.spawner. - On("CreateJob", - mock.Anything, - mock.Anything, - mock.MatchedBy(func(j *job.Job) bool { - return j.Name.String == streamName - }), - ). - Run(func(args mock.Arguments) { (args.Get(2).(*job.Job)).ID = 1 }). - Return(nil) - svc.orm.On("ApproveSpec", - mock.Anything, - spec.ID, - externalJobID, - ).Return(nil) - svc.fmsClient.On("ApprovedJob", - mock.MatchedBy(func(ctx context.Context) bool { return true }), - &proto.ApprovedJobRequest{ - Uuid: jp.RemoteUUID.String(), - Version: int64(spec.Version), - }, - ).Return(nil, errors.New("failure")) - svc.orm.On("WithDataSource", mock.Anything).Return(feeds.ORM(svc.orm)) - svc.jobORM.On("WithDataSource", mock.Anything).Return(job.ORM(svc.jobORM)) - }, - id: spec.ID, - force: false, - wantErr: "could not approve job proposal: failure", - }, - } - - for _, tc := range testCases { - tc := tc - t.Run(tc.name, func(t *testing.T) { - svc := setupTestServiceCfg(t, func(c *chainlink.Config, s *chainlink.Secrets) { - c.OCR2.Enabled = testutils.Ptr(true) - if tc.httpTimeout != nil { - c.JobPipeline.HTTPRequest.DefaultTimeout = tc.httpTimeout - } - }) - - if tc.before != nil { - tc.before(svc) - } - - err := svc.ApproveSpec(ctx, tc.id, tc.force) - - if tc.wantErr != "" { - require.Error(t, err) - assert.EqualError(t, err, tc.wantErr) - } else { - require.NoError(t, err) - } - }) - } -} - func Test_Service_ApproveSpec_Bootstrap(t *testing.T) { address := "0x613a38AC1659769640aaE063C651F48E0250454C" feedIDHex := "0x0000000000000000000000000000000000000000000000000000000000000001" diff --git a/core/services/fluxmonitorv2/flux_monitor_test.go b/core/services/fluxmonitorv2/flux_monitor_test.go index 150db269e45..88b364cdeb3 100644 --- a/core/services/fluxmonitorv2/flux_monitor_test.go +++ b/core/services/fluxmonitorv2/flux_monitor_test.go @@ -150,7 +150,7 @@ type setupOptions struct { // functional options to configure the setup func setup(t *testing.T, ds sqlutil.DataSource, optionFns ...func(*setupOptions)) (*fluxmonitorv2.FluxMonitor, *testMocks) { t.Helper() - tests.SkipShort(t, "long test") + testutils.SkipShort(t, "long test") tm := setupMocks(t) options := setupOptions{ diff --git a/core/services/fluxmonitorv2/integrations_test.go b/core/services/fluxmonitorv2/integrations_test.go index d30ff4479a8..e2344be3483 100644 --- a/core/services/fluxmonitorv2/integrations_test.go +++ b/core/services/fluxmonitorv2/integrations_test.go @@ -25,7 +25,6 @@ import ( commonconfig "github.com/smartcontractkit/chainlink-common/pkg/config" "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" - "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" "github.com/smartcontractkit/chainlink/v2/core/bridges" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" @@ -56,10 +55,9 @@ const fee = int64(100) // Amount paid by FA contract, in LINK-wei const faTimeout = uint32(1) var pollTimerPeriod = 200 * time.Millisecond // if failing due to timeouts, increase this +var oneEth = big.NewInt(1000000000000000000) var emptyList = []common.Address{} -func oneEth() *big.Int { return big.NewInt(1000000000000000000) } - // fluxAggregatorUniverse represents the universe with which the aggregator // contract interacts type fluxAggregatorUniverse struct { @@ -96,7 +94,7 @@ func WithMinMaxSubmission(min, max *big.Int) func(cfg *fluxAggregatorUniverseCon // arguments match the arguments of the same name in the FluxAggregator // constructor. func setupFluxAggregatorUniverse(t *testing.T, configOptions ...func(cfg *fluxAggregatorUniverseConfig)) fluxAggregatorUniverse { - tests.SkipShort(t, "VRFCoordinatorV2Universe") + testutils.SkipShort(t, "VRFCoordinatorV2Universe") cfg := &fluxAggregatorUniverseConfig{ MinSubmission: big.NewInt(0), MaxSubmission: big.NewInt(100000000000), @@ -164,7 +162,7 @@ func setupFluxAggregatorUniverse(t *testing.T, configOptions ...func(cfg *fluxAg f.sergey.GasLimit = oldGasLimit - _, err = f.linkContract.Transfer(f.sergey, f.aggregatorContractAddress, oneEth()) // Actually, LINK + _, err = f.linkContract.Transfer(f.sergey, f.aggregatorContractAddress, oneEth) // Actually, LINK require.NoError(t, err, "failed to fund FluxAggregator contract with LINK") f.backend.Commit() @@ -174,9 +172,9 @@ func setupFluxAggregatorUniverse(t *testing.T, configOptions ...func(cfg *fluxAg f.backend.Commit() availableFunds, err := f.aggregatorContract.AvailableFunds(nil) require.NoError(t, err, "failed to retrieve AvailableFunds") - require.Equal(t, availableFunds, oneEth()) + require.Equal(t, availableFunds, oneEth) - ilogs, err := f.aggregatorContract.FilterAvailableFundsUpdated(nil, []*big.Int{oneEth()}) + ilogs, err := f.aggregatorContract.FilterAvailableFundsUpdated(nil, []*big.Int{oneEth}) require.NoError(t, err, "failed to gather AvailableFundsUpdated logs") logs := cltest.GetLogs(t, nil, ilogs) diff --git a/core/services/gateway/connector/connector.go b/core/services/gateway/connector/connector.go index cab123d4ce5..18d34007c56 100644 --- a/core/services/gateway/connector/connector.go +++ b/core/services/gateway/connector/connector.go @@ -23,19 +23,18 @@ import ( // GatewayConnector is a component run by Nodes to connect to a set of Gateways. type GatewayConnector interface { - services.Service + job.ServiceCtx network.ConnectionInitiator AddHandler(methods []string, handler GatewayConnectorHandler) error // SendToGateway takes a signed message as argument and sends it to the specified gateway - SendToGateway(ctx context.Context, gatewayID string, msg *api.Message) error + SendToGateway(ctx context.Context, gatewayId string, msg *api.Message) error // SignAndSendToGateway signs the message and sends the message to the specified gateway SignAndSendToGateway(ctx context.Context, gatewayID string, msg *api.MessageBody) error // GatewayIDs returns the list of Gateway IDs GatewayIDs() []string // DonID returns the DON ID DonID() string - AwaitConnection(ctx context.Context, gatewayID string) error } // Signer implementation needs to be provided by a GatewayConnector user (node) @@ -79,30 +78,12 @@ func (c *gatewayConnector) HealthReport() map[string]error { func (c *gatewayConnector) Name() string { return c.lggr.Name() } type gatewayState struct { - // signal channel is closed once the gateway is connected - signalCh chan struct{} - conn network.WSConnectionWrapper config ConnectorGatewayConfig url *url.URL wsClient network.WebSocketClient } -// A gatewayState is connected when the signal channel is closed -func (gs *gatewayState) signal() { - close(gs.signalCh) -} - -// awaitConn blocks until the gateway is connected or the context is done -func (gs *gatewayState) awaitConn(ctx context.Context) error { - select { - case <-ctx.Done(): - return fmt.Errorf("await connection failed: %w", ctx.Err()) - case <-gs.signalCh: - return nil - } -} - func NewGatewayConnector(config *ConnectorConfig, signer Signer, clock clockwork.Clock, lggr logger.Logger) (GatewayConnector, error) { if config == nil || signer == nil || clock == nil || lggr == nil { return nil, errors.New("nil dependency") @@ -144,7 +125,6 @@ func NewGatewayConnector(config *ConnectorConfig, signer Signer, clock clockwork config: gw, url: parsedURL, wsClient: network.NewWebSocketClient(config.WsClientConfig, connector, lggr), - signalCh: make(chan struct{}), } gateways[gw.Id] = gateway urlToId[gw.URL] = gw.Id @@ -170,25 +150,17 @@ func (c *gatewayConnector) AddHandler(methods []string, handler GatewayConnector return nil } -func (c *gatewayConnector) AwaitConnection(ctx context.Context, gatewayID string) error { - gateway, ok := c.gateways[gatewayID] - if !ok { - return fmt.Errorf("invalid Gateway ID %s", gatewayID) - } - return gateway.awaitConn(ctx) -} - -func (c *gatewayConnector) SendToGateway(ctx context.Context, gatewayID string, msg *api.Message) error { +func (c *gatewayConnector) SendToGateway(ctx context.Context, gatewayId string, msg *api.Message) error { data, err := c.codec.EncodeResponse(msg) if err != nil { - return fmt.Errorf("error encoding response for gateway %s: %w", gatewayID, err) + return fmt.Errorf("error encoding response for gateway %s: %v", gatewayId, err) } - gateway, ok := c.gateways[gatewayID] + gateway, ok := c.gateways[gatewayId] if !ok { - return fmt.Errorf("invalid Gateway ID %s", gatewayID) + return fmt.Errorf("invalid Gateway ID %s", gatewayId) } if gateway.conn == nil { - return errors.New("connector not started") + return fmt.Errorf("connector not started") } return gateway.conn.Write(ctx, websocket.BinaryMessage, data) } @@ -270,15 +242,10 @@ func (c *gatewayConnector) reconnectLoop(gatewayState *gatewayState) { } else { c.lggr.Infow("connected successfully", "url", gatewayState.url) closeCh := gatewayState.conn.Reset(conn) - gatewayState.signal() <-closeCh c.lggr.Infow("connection closed", "url", gatewayState.url) - // reset backoff redialBackoff = utils.NewRedialBackoff() - - // reset signal channel - gatewayState.signalCh = make(chan struct{}) } select { case <-c.shutdownCh: diff --git a/core/services/gateway/connector/mocks/gateway_connector.go b/core/services/gateway/connector/mocks/gateway_connector.go index ba5c2213b5f..f9951af98e9 100644 --- a/core/services/gateway/connector/mocks/gateway_connector.go +++ b/core/services/gateway/connector/mocks/gateway_connector.go @@ -73,53 +73,6 @@ func (_c *GatewayConnector_AddHandler_Call) RunAndReturn(run func([]string, conn return _c } -// AwaitConnection provides a mock function with given fields: ctx, gatewayID -func (_m *GatewayConnector) AwaitConnection(ctx context.Context, gatewayID string) error { - ret := _m.Called(ctx, gatewayID) - - if len(ret) == 0 { - panic("no return value specified for AwaitConnection") - } - - var r0 error - if rf, ok := ret.Get(0).(func(context.Context, string) error); ok { - r0 = rf(ctx, gatewayID) - } else { - r0 = ret.Error(0) - } - - return r0 -} - -// GatewayConnector_AwaitConnection_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'AwaitConnection' -type GatewayConnector_AwaitConnection_Call struct { - *mock.Call -} - -// AwaitConnection is a helper method to define mock.On call -// - ctx context.Context -// - gatewayID string -func (_e *GatewayConnector_Expecter) AwaitConnection(ctx interface{}, gatewayID interface{}) *GatewayConnector_AwaitConnection_Call { - return &GatewayConnector_AwaitConnection_Call{Call: _e.mock.On("AwaitConnection", ctx, gatewayID)} -} - -func (_c *GatewayConnector_AwaitConnection_Call) Run(run func(ctx context.Context, gatewayID string)) *GatewayConnector_AwaitConnection_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context), args[1].(string)) - }) - return _c -} - -func (_c *GatewayConnector_AwaitConnection_Call) Return(_a0 error) *GatewayConnector_AwaitConnection_Call { - _c.Call.Return(_a0) - return _c -} - -func (_c *GatewayConnector_AwaitConnection_Call) RunAndReturn(run func(context.Context, string) error) *GatewayConnector_AwaitConnection_Call { - _c.Call.Return(run) - return _c -} - // ChallengeResponse provides a mock function with given fields: _a0, challenge func (_m *GatewayConnector) ChallengeResponse(_a0 *url.URL, challenge []byte) ([]byte, error) { ret := _m.Called(_a0, challenge) @@ -316,98 +269,6 @@ func (_c *GatewayConnector_GatewayIDs_Call) RunAndReturn(run func() []string) *G return _c } -// HealthReport provides a mock function with given fields: -func (_m *GatewayConnector) HealthReport() map[string]error { - ret := _m.Called() - - if len(ret) == 0 { - panic("no return value specified for HealthReport") - } - - var r0 map[string]error - if rf, ok := ret.Get(0).(func() map[string]error); ok { - r0 = rf() - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(map[string]error) - } - } - - return r0 -} - -// GatewayConnector_HealthReport_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'HealthReport' -type GatewayConnector_HealthReport_Call struct { - *mock.Call -} - -// HealthReport is a helper method to define mock.On call -func (_e *GatewayConnector_Expecter) HealthReport() *GatewayConnector_HealthReport_Call { - return &GatewayConnector_HealthReport_Call{Call: _e.mock.On("HealthReport")} -} - -func (_c *GatewayConnector_HealthReport_Call) Run(run func()) *GatewayConnector_HealthReport_Call { - _c.Call.Run(func(args mock.Arguments) { - run() - }) - return _c -} - -func (_c *GatewayConnector_HealthReport_Call) Return(_a0 map[string]error) *GatewayConnector_HealthReport_Call { - _c.Call.Return(_a0) - return _c -} - -func (_c *GatewayConnector_HealthReport_Call) RunAndReturn(run func() map[string]error) *GatewayConnector_HealthReport_Call { - _c.Call.Return(run) - return _c -} - -// Name provides a mock function with given fields: -func (_m *GatewayConnector) Name() string { - ret := _m.Called() - - if len(ret) == 0 { - panic("no return value specified for Name") - } - - var r0 string - if rf, ok := ret.Get(0).(func() string); ok { - r0 = rf() - } else { - r0 = ret.Get(0).(string) - } - - return r0 -} - -// GatewayConnector_Name_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Name' -type GatewayConnector_Name_Call struct { - *mock.Call -} - -// Name is a helper method to define mock.On call -func (_e *GatewayConnector_Expecter) Name() *GatewayConnector_Name_Call { - return &GatewayConnector_Name_Call{Call: _e.mock.On("Name")} -} - -func (_c *GatewayConnector_Name_Call) Run(run func()) *GatewayConnector_Name_Call { - _c.Call.Run(func(args mock.Arguments) { - run() - }) - return _c -} - -func (_c *GatewayConnector_Name_Call) Return(_a0 string) *GatewayConnector_Name_Call { - _c.Call.Return(_a0) - return _c -} - -func (_c *GatewayConnector_Name_Call) RunAndReturn(run func() string) *GatewayConnector_Name_Call { - _c.Call.Return(run) - return _c -} - // NewAuthHeader provides a mock function with given fields: _a0 func (_m *GatewayConnector) NewAuthHeader(_a0 *url.URL) ([]byte, error) { ret := _m.Called(_a0) @@ -466,54 +327,9 @@ func (_c *GatewayConnector_NewAuthHeader_Call) RunAndReturn(run func(*url.URL) ( return _c } -// Ready provides a mock function with given fields: -func (_m *GatewayConnector) Ready() error { - ret := _m.Called() - - if len(ret) == 0 { - panic("no return value specified for Ready") - } - - var r0 error - if rf, ok := ret.Get(0).(func() error); ok { - r0 = rf() - } else { - r0 = ret.Error(0) - } - - return r0 -} - -// GatewayConnector_Ready_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Ready' -type GatewayConnector_Ready_Call struct { - *mock.Call -} - -// Ready is a helper method to define mock.On call -func (_e *GatewayConnector_Expecter) Ready() *GatewayConnector_Ready_Call { - return &GatewayConnector_Ready_Call{Call: _e.mock.On("Ready")} -} - -func (_c *GatewayConnector_Ready_Call) Run(run func()) *GatewayConnector_Ready_Call { - _c.Call.Run(func(args mock.Arguments) { - run() - }) - return _c -} - -func (_c *GatewayConnector_Ready_Call) Return(_a0 error) *GatewayConnector_Ready_Call { - _c.Call.Return(_a0) - return _c -} - -func (_c *GatewayConnector_Ready_Call) RunAndReturn(run func() error) *GatewayConnector_Ready_Call { - _c.Call.Return(run) - return _c -} - -// SendToGateway provides a mock function with given fields: ctx, gatewayID, msg -func (_m *GatewayConnector) SendToGateway(ctx context.Context, gatewayID string, msg *api.Message) error { - ret := _m.Called(ctx, gatewayID, msg) +// SendToGateway provides a mock function with given fields: ctx, gatewayId, msg +func (_m *GatewayConnector) SendToGateway(ctx context.Context, gatewayId string, msg *api.Message) error { + ret := _m.Called(ctx, gatewayId, msg) if len(ret) == 0 { panic("no return value specified for SendToGateway") @@ -521,7 +337,7 @@ func (_m *GatewayConnector) SendToGateway(ctx context.Context, gatewayID string, var r0 error if rf, ok := ret.Get(0).(func(context.Context, string, *api.Message) error); ok { - r0 = rf(ctx, gatewayID, msg) + r0 = rf(ctx, gatewayId, msg) } else { r0 = ret.Error(0) } @@ -536,13 +352,13 @@ type GatewayConnector_SendToGateway_Call struct { // SendToGateway is a helper method to define mock.On call // - ctx context.Context -// - gatewayID string +// - gatewayId string // - msg *api.Message -func (_e *GatewayConnector_Expecter) SendToGateway(ctx interface{}, gatewayID interface{}, msg interface{}) *GatewayConnector_SendToGateway_Call { - return &GatewayConnector_SendToGateway_Call{Call: _e.mock.On("SendToGateway", ctx, gatewayID, msg)} +func (_e *GatewayConnector_Expecter) SendToGateway(ctx interface{}, gatewayId interface{}, msg interface{}) *GatewayConnector_SendToGateway_Call { + return &GatewayConnector_SendToGateway_Call{Call: _e.mock.On("SendToGateway", ctx, gatewayId, msg)} } -func (_c *GatewayConnector_SendToGateway_Call) Run(run func(ctx context.Context, gatewayID string, msg *api.Message)) *GatewayConnector_SendToGateway_Call { +func (_c *GatewayConnector_SendToGateway_Call) Run(run func(ctx context.Context, gatewayId string, msg *api.Message)) *GatewayConnector_SendToGateway_Call { _c.Call.Run(func(args mock.Arguments) { run(args[0].(context.Context), args[1].(string), args[2].(*api.Message)) }) diff --git a/core/services/gateway/handlers/capabilities/handler.go b/core/services/gateway/handlers/capabilities/handler.go index e1bdfdf8441..904a64c8896 100644 --- a/core/services/gateway/handlers/capabilities/handler.go +++ b/core/services/gateway/handlers/capabilities/handler.go @@ -20,10 +20,9 @@ import ( const ( // NOTE: more methods will go here. HTTP trigger/action/target; etc. - MethodWebAPITarget = "web_api_target" - MethodWebAPITrigger = "web_api_trigger" - MethodComputeAction = "compute_action" - MethodWorkflowSyncer = "workflow_syncer" + MethodWebAPITarget = "web_api_target" + MethodWebAPITrigger = "web_api_trigger" + MethodComputeAction = "compute_action" ) type handler struct { @@ -146,8 +145,7 @@ func (h *handler) handleWebAPIOutgoingMessage(ctx context.Context, msg *api.Mess newCtx := context.WithoutCancel(ctx) newCtx, cancel := context.WithTimeout(newCtx, timeout) defer cancel() - l := h.lggr.With("url", payload.URL, "messageId", msg.Body.MessageId, "method", payload.Method, "timeout", payload.TimeoutMs) - l.Debug("Sending request to client") + l := h.lggr.With("url", payload.URL, "messageId", msg.Body.MessageId, "method", payload.Method) respMsg, err := h.sendHTTPMessageToClient(newCtx, req, msg) if err != nil { l.Errorw("error while sending HTTP request to external endpoint", "err", err) @@ -188,7 +186,7 @@ func (h *handler) HandleNodeMessage(ctx context.Context, msg *api.Message, nodeA switch msg.Body.Method { case MethodWebAPITrigger: return h.handleWebAPITriggerMessage(ctx, msg, nodeAddr) - case MethodWebAPITarget, MethodComputeAction, MethodWorkflowSyncer: + case MethodWebAPITarget, MethodComputeAction: return h.handleWebAPIOutgoingMessage(ctx, msg, nodeAddr) default: return fmt.Errorf("unsupported method: %s", msg.Body.Method) diff --git a/core/services/gateway/network/httpclient.go b/core/services/gateway/network/httpclient.go index 52130c8d069..4aecaaed3cd 100644 --- a/core/services/gateway/network/httpclient.go +++ b/core/services/gateway/network/httpclient.go @@ -78,7 +78,7 @@ func (c *httpClient) Send(ctx context.Context, req HTTPRequest) (*HTTPResponse, // joining them to a single string in case array size is greater than 1 headers[k] = strings.Join(v, ",") } - c.lggr.Debugw("received HTTP response", "statusCode", resp.StatusCode, "url", req.URL, "headers", headers) + c.lggr.Debugw("received HTTP response", "statusCode", resp.StatusCode, "body", string(body), "url", req.URL, "headers", headers) return &HTTPResponse{ Headers: headers, diff --git a/core/services/job/job_orm_test.go b/core/services/job/job_orm_test.go index 27223e0d706..9db99fcd48d 100644 --- a/core/services/job/job_orm_test.go +++ b/core/services/job/job_orm_test.go @@ -43,10 +43,8 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/services/ocrbootstrap" "github.com/smartcontractkit/chainlink/v2/core/services/pipeline" "github.com/smartcontractkit/chainlink/v2/core/services/relay" - "github.com/smartcontractkit/chainlink/v2/core/services/streams" "github.com/smartcontractkit/chainlink/v2/core/services/vrf/vrfcommon" "github.com/smartcontractkit/chainlink/v2/core/services/webhook" - "github.com/smartcontractkit/chainlink/v2/core/services/workflows/syncer" "github.com/smartcontractkit/chainlink/v2/core/testdata/testspecs" "github.com/smartcontractkit/chainlink/v2/core/utils/testutils/heavyweight" ) @@ -445,18 +443,6 @@ func TestORM_DeleteJob_DeletesAssociatedRecords(t *testing.T) { cltest.AssertCount(t, db, "jobs", 0) }) - t.Run("it creates and deletes records for stream jobs", func(t *testing.T) { - ctx := testutils.Context(t) - jb, err := streams.ValidatedStreamSpec(testspecs.GenerateStreamSpec(testspecs.StreamSpecParams{Name: "Test-stream", StreamID: 1}).Toml()) - require.NoError(t, err) - err = jobORM.CreateJob(ctx, &jb) - require.NoError(t, err) - cltest.AssertCount(t, db, "jobs", 1) - err = jobORM.DeleteJob(ctx, jb.ID, jb.Type) - require.NoError(t, err) - cltest.AssertCount(t, db, "jobs", 0) - }) - t.Run("does not allow to delete external initiators if they have referencing external_initiator_webhook_specs", func(t *testing.T) { // create new db because this will rollback transaction and poison it db := pgtest.NewSqlxDB(t) @@ -1887,7 +1873,6 @@ func Test_ORM_FindJobByWorkflow(t *testing.T) { c.ID = s.ID c.Workflow = pkgworkflows.WFYamlSpec(t, "workflow99", addr1) // insert with mismatched name c.SpecType = job.YamlSpec - c.SecretsID = s.SecretsID return mustInsertWFJob(t, o, &c) }, }, @@ -1907,7 +1892,6 @@ func Test_ORM_FindJobByWorkflow(t *testing.T) { var c job.WorkflowSpec c.ID = s.ID c.Workflow = pkgworkflows.WFYamlSpec(t, "workflow03", addr2) // insert with mismatched owner - c.SecretsID = s.SecretsID return mustInsertWFJob(t, o, &c) }, }, @@ -1915,32 +1899,22 @@ func Test_ORM_FindJobByWorkflow(t *testing.T) { }, } - for i, tt := range tests { + for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - ctx := testutils.Context(t) ks := cltest.NewKeyStore(t, tt.fields.ds) - - secretsORM := syncer.NewWorkflowRegistryDS(tt.fields.ds, logger.TestLogger(t)) - - sid, err := secretsORM.Create(ctx, "some-url.com", fmt.Sprintf("some-hash-%d", i), "some-contentz") - require.NoError(t, err) - tt.args.spec.SecretsID = sql.NullInt64{Int64: sid, Valid: true} - pipelineORM := pipeline.NewORM(tt.fields.ds, logger.TestLogger(t), configtest.NewTestGeneralConfig(t).JobPipeline().MaxSuccessfulRuns()) bridgesORM := bridges.NewORM(tt.fields.ds) o := NewTestORM(t, tt.fields.ds, pipelineORM, bridgesORM, ks) - var wantJobID int32 if tt.args.before != nil { wantJobID = tt.args.before(t, o, tt.args.spec) } - + ctx := testutils.Context(t) gotJ, err := o.FindJobIDByWorkflow(ctx, *tt.args.spec) if (err != nil) != tt.wantErr { t.Errorf("orm.FindJobByWorkflow() error = %v, wantErr %v", err, tt.wantErr) return } - if err == nil { assert.Equal(t, wantJobID, gotJ, "mismatch job id") } @@ -1962,36 +1936,25 @@ func Test_ORM_FindJobByWorkflow_Multiple(t *testing.T) { bridges.NewORM(db), cltest.NewKeyStore(t, db)) ctx := testutils.Context(t) - secretsORM := syncer.NewWorkflowRegistryDS(db, logger.TestLogger(t)) - - var sids []int64 - for i := 0; i < 3; i++ { - sid, err := secretsORM.Create(ctx, "some-url.com", fmt.Sprintf("some-hash-%d", i), "some-contentz") - require.NoError(t, err) - sids = append(sids, sid) - } wfYaml1 := pkgworkflows.WFYamlSpec(t, "workflow00", addr1) s1 := job.WorkflowSpec{ - Workflow: wfYaml1, - SpecType: job.YamlSpec, - SecretsID: sql.NullInt64{Int64: sids[0], Valid: true}, + Workflow: wfYaml1, + SpecType: job.YamlSpec, } wantJobID1 := mustInsertWFJob(t, o, &s1) wfYaml2 := pkgworkflows.WFYamlSpec(t, "workflow01", addr1) s2 := job.WorkflowSpec{ - Workflow: wfYaml2, - SpecType: job.YamlSpec, - SecretsID: sql.NullInt64{Int64: sids[1], Valid: true}, + Workflow: wfYaml2, + SpecType: job.YamlSpec, } wantJobID2 := mustInsertWFJob(t, o, &s2) wfYaml3 := pkgworkflows.WFYamlSpec(t, "workflow00", addr2) s3 := job.WorkflowSpec{ - Workflow: wfYaml3, - SpecType: job.YamlSpec, - SecretsID: sql.NullInt64{Int64: sids[2], Valid: true}, + Workflow: wfYaml3, + SpecType: job.YamlSpec, } wantJobID3 := mustInsertWFJob(t, o, &s3) @@ -2029,7 +1992,7 @@ func mustInsertWFJob(t *testing.T, orm job.ORM, s *job.WorkflowSpec) int32 { } err = orm.CreateJob(ctx, &j) - require.NoError(t, err, "failed to insert job with wf spec %+v %s", s, err) + require.NoError(t, err, "failed to insert job with wf spec %v %s", s, s.Workflow) return j.ID } diff --git a/core/services/job/mocks/orm.go b/core/services/job/mocks/orm.go index 96513866f37..89426b55a21 100644 --- a/core/services/job/mocks/orm.go +++ b/core/services/job/mocks/orm.go @@ -601,63 +601,6 @@ func (_c *ORM_FindJobIDByCapabilityNameAndVersion_Call) RunAndReturn(run func(co return _c } -// FindJobIDByStreamID provides a mock function with given fields: ctx, streamID -func (_m *ORM) FindJobIDByStreamID(ctx context.Context, streamID uint32) (int32, error) { - ret := _m.Called(ctx, streamID) - - if len(ret) == 0 { - panic("no return value specified for FindJobIDByStreamID") - } - - var r0 int32 - var r1 error - if rf, ok := ret.Get(0).(func(context.Context, uint32) (int32, error)); ok { - return rf(ctx, streamID) - } - if rf, ok := ret.Get(0).(func(context.Context, uint32) int32); ok { - r0 = rf(ctx, streamID) - } else { - r0 = ret.Get(0).(int32) - } - - if rf, ok := ret.Get(1).(func(context.Context, uint32) error); ok { - r1 = rf(ctx, streamID) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// ORM_FindJobIDByStreamID_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'FindJobIDByStreamID' -type ORM_FindJobIDByStreamID_Call struct { - *mock.Call -} - -// FindJobIDByStreamID is a helper method to define mock.On call -// - ctx context.Context -// - streamID uint32 -func (_e *ORM_Expecter) FindJobIDByStreamID(ctx interface{}, streamID interface{}) *ORM_FindJobIDByStreamID_Call { - return &ORM_FindJobIDByStreamID_Call{Call: _e.mock.On("FindJobIDByStreamID", ctx, streamID)} -} - -func (_c *ORM_FindJobIDByStreamID_Call) Run(run func(ctx context.Context, streamID uint32)) *ORM_FindJobIDByStreamID_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context), args[1].(uint32)) - }) - return _c -} - -func (_c *ORM_FindJobIDByStreamID_Call) Return(_a0 int32, _a1 error) *ORM_FindJobIDByStreamID_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *ORM_FindJobIDByStreamID_Call) RunAndReturn(run func(context.Context, uint32) (int32, error)) *ORM_FindJobIDByStreamID_Call { - _c.Call.Return(run) - return _c -} - // FindJobIDByWorkflow provides a mock function with given fields: ctx, spec func (_m *ORM) FindJobIDByWorkflow(ctx context.Context, spec job.WorkflowSpec) (int32, error) { ret := _m.Called(ctx, spec) diff --git a/core/services/job/models.go b/core/services/job/models.go index 26d563c7ac8..231bf10fda0 100644 --- a/core/services/job/models.go +++ b/core/services/job/models.go @@ -2,7 +2,6 @@ package job import ( "context" - "database/sql" "database/sql/driver" "encoding/json" "fmt" @@ -869,30 +868,18 @@ const ( DefaultSpecType = "" ) -type WorkflowSpecStatus string - -const ( - WorkflowSpecStatusActive WorkflowSpecStatus = "active" - WorkflowSpecStatusPaused WorkflowSpecStatus = "paused" - WorkflowSpecStatusDefault WorkflowSpecStatus = "" -) - type WorkflowSpec struct { ID int32 `toml:"-"` Workflow string `toml:"workflow"` // the raw representation of the workflow Config string `toml:"config" db:"config"` // the raw representation of the config // fields derived from the yaml spec, used for indexing the database // note: i tried to make these private, but translating them to the database seems to require them to be public - WorkflowID string `toml:"-" db:"workflow_id"` // Derived. Do not modify. the CID of the workflow. - WorkflowOwner string `toml:"-" db:"workflow_owner"` // Derived. Do not modify. the owner of the workflow. - WorkflowName string `toml:"-" db:"workflow_name"` // Derived. Do not modify. the name of the workflow. - Status WorkflowSpecStatus `db:"status"` - BinaryURL string `db:"binary_url"` - ConfigURL string `db:"config_url"` - SecretsID sql.NullInt64 `db:"secrets_id"` - CreatedAt time.Time `toml:"-"` - UpdatedAt time.Time `toml:"-"` - SpecType WorkflowSpecType `toml:"spec_type" db:"spec_type"` + WorkflowID string `toml:"-" db:"workflow_id"` // Derived. Do not modify. the CID of the workflow. + WorkflowOwner string `toml:"-" db:"workflow_owner"` // Derived. Do not modify. the owner of the workflow. + WorkflowName string `toml:"-" db:"workflow_name"` // Derived. Do not modify. the name of the workflow. + CreatedAt time.Time `toml:"-"` + UpdatedAt time.Time `toml:"-"` + SpecType WorkflowSpecType `toml:"spec_type" db:"spec_type"` sdkWorkflow *sdk.WorkflowSpec rawSpec []byte config []byte diff --git a/core/services/job/models_test.go b/core/services/job/models_test.go index df52a5cca0c..5ef36ea9f48 100644 --- a/core/services/job/models_test.go +++ b/core/services/job/models_test.go @@ -345,6 +345,8 @@ func TestWorkflowSpec_Validate(t *testing.T) { err := w.Validate(testutils.Context(t)) require.NoError(t, err) + assert.Equal(t, "owner", w.WorkflowOwner) + assert.Equal(t, "name", w.WorkflowName) require.NotEmpty(t, w.WorkflowID) }) } diff --git a/core/services/job/orm.go b/core/services/job/orm.go index cfd8060d60c..5e8b5ce127f 100644 --- a/core/services/job/orm.go +++ b/core/services/job/orm.go @@ -78,8 +78,6 @@ type ORM interface { FindJobIDByWorkflow(ctx context.Context, spec WorkflowSpec) (int32, error) FindJobIDByCapabilityNameAndVersion(ctx context.Context, spec CCIPSpec) (int32, error) - - FindJobIDByStreamID(ctx context.Context, streamID uint32) (int32, error) } type ORMConfig interface { @@ -435,8 +433,8 @@ func (o *orm) CreateJob(ctx context.Context, jb *Job) error { case Stream: // 'stream' type has no associated spec, nothing to do here case Workflow: - sql := `INSERT INTO workflow_specs (workflow, workflow_id, workflow_owner, workflow_name, binary_url, config_url, secrets_id, created_at, updated_at, spec_type, config) - VALUES (:workflow, :workflow_id, :workflow_owner, :workflow_name, :binary_url, :config_url, :secrets_id, NOW(), NOW(), :spec_type, :config) + sql := `INSERT INTO workflow_specs (workflow, workflow_id, workflow_owner, workflow_name, created_at, updated_at, spec_type, config) + VALUES (:workflow, :workflow_id, :workflow_owner, :workflow_name, NOW(), NOW(), :spec_type, :config) RETURNING id;` specID, err := tx.prepareQuerySpecID(ctx, sql, jb.WorkflowSpec) if err != nil { @@ -747,7 +745,6 @@ func (o *orm) DeleteJob(ctx context.Context, id int32, jobType Type) error { Workflow: `DELETE FROM workflow_specs WHERE id in (SELECT workflow_spec_id FROM deleted_jobs)`, StandardCapabilities: `DELETE FROM standardcapabilities_specs WHERE id in (SELECT standard_capabilities_spec_id FROM deleted_jobs)`, CCIP: `DELETE FROM ccip_specs WHERE id in (SELECT ccip_spec_id FROM deleted_jobs)`, - Stream: ``, } q, ok := queries[jobType] if !ok { @@ -758,7 +755,7 @@ func (o *orm) DeleteJob(ctx context.Context, id int32, jobType Type) error { // and this query was taking ~40secs. ctx, cancel := context.WithTimeout(sqlutil.WithoutDefaultTimeout(ctx), time.Minute) defer cancel() - query := ` + query := fmt.Sprintf(` WITH deleted_jobs AS ( DELETE FROM jobs WHERE id = $1 RETURNING id, @@ -776,19 +773,15 @@ func (o *orm) DeleteJob(ctx context.Context, id int32, jobType Type) error { gateway_spec_id, workflow_spec_id, standard_capabilities_spec_id, - ccip_spec_id, - stream_id - ),` - if len(q) > 0 { - query += fmt.Sprintf(`deleted_specific_specs AS ( - %s - ),`, q) - } - query += ` + ccip_spec_id + ), + deleted_specific_specs AS ( + %s + ), deleted_job_pipeline_specs AS ( DELETE FROM job_pipeline_specs WHERE job_id IN (SELECT id FROM deleted_jobs) RETURNING pipeline_spec_id ) - DELETE FROM pipeline_specs WHERE id IN (SELECT pipeline_spec_id FROM deleted_job_pipeline_specs)` + DELETE FROM pipeline_specs WHERE id IN (SELECT pipeline_spec_id FROM deleted_job_pipeline_specs)`, q) res, err := o.ds.ExecContext(ctx, query, id) if err != nil { return errors.Wrap(err, "DeleteJob failed to delete job") @@ -1341,20 +1334,6 @@ func (o *orm) FindJobsByPipelineSpecIDs(ctx context.Context, ids []int32) ([]Job return jbs, errors.Wrap(err, "FindJobsByPipelineSpecIDs failed") } -func (o *orm) FindJobIDByStreamID(ctx context.Context, streamID uint32) (jobID int32, err error) { - stmt := `SELECT id FROM jobs WHERE type = 'stream' AND stream_id = $1` - err = o.ds.GetContext(ctx, &jobID, stmt, streamID) - if err != nil { - if !errors.Is(err, sql.ErrNoRows) { - err = errors.Wrap(err, "error searching for job by stream id") - } - err = errors.Wrap(err, "FindJobIDByStreamID failed") - return - } - - return -} - // PipelineRuns returns pipeline runs for a job, with spec and taskruns loaded, latest first // If jobID is nil, returns all pipeline runs func (o *orm) PipelineRuns(ctx context.Context, jobID *int32, offset, size int) (runs []pipeline.Run, count int, err error) { diff --git a/core/services/job/testdata/wasm/test_workflow_spec.go b/core/services/job/testdata/wasm/test_workflow_spec.go index 477ba097ca3..40b9c0bbb67 100644 --- a/core/services/job/testdata/wasm/test_workflow_spec.go +++ b/core/services/job/testdata/wasm/test_workflow_spec.go @@ -3,6 +3,9 @@ package main import ( + "encoding/json" + "log" + "github.com/smartcontractkit/chainlink-common/pkg/workflows/wasm" "github.com/smartcontractkit/chainlink-common/pkg/capabilities/cli/cmd/testdata/fixtures/capabilities/basictrigger" @@ -10,7 +13,12 @@ import ( ) func BuildWorkflow(config []byte) *sdk.WorkflowSpecFactory { - workflow := sdk.NewWorkflowSpecFactory() + params := sdk.NewWorkflowParams{} + if err := json.Unmarshal(config, ¶ms); err != nil { + log.Fatal(err) + } + + workflow := sdk.NewWorkflowSpecFactory(params) triggerCfg := basictrigger.TriggerConfig{Name: "trigger", Number: 100} _ = triggerCfg.New(workflow) diff --git a/core/services/keystore/keys/csakey/key_v2.go b/core/services/keystore/keys/csakey/key_v2.go index ddccbfb488b..08207f52af4 100644 --- a/core/services/keystore/keys/csakey/key_v2.go +++ b/core/services/keystore/keys/csakey/key_v2.go @@ -16,7 +16,7 @@ func (raw Raw) Key() KeyV2 { privKey := ed25519.PrivateKey(raw) return KeyV2{ privateKey: &privKey, - PublicKey: privKey.Public().(ed25519.PublicKey), + PublicKey: ed25519PubKeyFromPrivKey(privKey), } } @@ -66,7 +66,7 @@ func MustNewV2XXXTestingOnly(k *big.Int) KeyV2 { privKey := ed25519.NewKeyFromSeed(seed) return KeyV2{ privateKey: &privKey, - PublicKey: privKey.Public().(ed25519.PublicKey), + PublicKey: ed25519PubKeyFromPrivKey(privKey), Version: 2, } } @@ -90,3 +90,9 @@ func (k KeyV2) String() string { func (k KeyV2) GoString() string { return k.String() } + +func ed25519PubKeyFromPrivKey(privKey ed25519.PrivateKey) ed25519.PublicKey { + publicKey := make([]byte, ed25519.PublicKeySize) + copy(publicKey, privKey[32:]) + return publicKey +} diff --git a/core/services/keystore/keys/keystest/keystest.go b/core/services/keystore/keys/keystest/keystest.go new file mode 100644 index 00000000000..9265dc6e189 --- /dev/null +++ b/core/services/keystore/keys/keystest/keystest.go @@ -0,0 +1,15 @@ +package keystest + +import ( + "testing" + + "github.com/stretchr/testify/require" + + "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/p2pkey" +) + +func NewP2PKeyV2(t *testing.T) p2pkey.KeyV2 { + k, err := p2pkey.NewV2() + require.NoError(t, err) + return k +} diff --git a/core/services/keystore/keys/ocr2key/evm_keyring.go b/core/services/keystore/keys/ocr2key/evm_keyring.go index 554d655443d..5d937e36a6e 100644 --- a/core/services/keystore/keys/ocr2key/evm_keyring.go +++ b/core/services/keystore/keys/ocr2key/evm_keyring.go @@ -60,7 +60,7 @@ func (ekr *evmKeyring) reportToSigData3(digest types.ConfigDigest, seqNr uint64, func RawReportContext3(digest types.ConfigDigest, seqNr uint64) [2][32]byte { seqNrBytes := [32]byte{} - binary.BigEndian.PutUint64(seqNrBytes[24:], seqNr) + binary.BigEndian.PutUint64(seqNrBytes[:], seqNr) return [2][32]byte{ digest, seqNrBytes, diff --git a/core/services/keystore/keys/ocr2key/evm_keyring_test.go b/core/services/keystore/keys/ocr2key/evm_keyring_test.go index 85dad74eb88..20ac197159a 100644 --- a/core/services/keystore/keys/ocr2key/evm_keyring_test.go +++ b/core/services/keystore/keys/ocr2key/evm_keyring_test.go @@ -3,7 +3,6 @@ package ocr2key import ( "bytes" cryptorand "crypto/rand" - "math" "math/rand" "testing" @@ -97,66 +96,3 @@ func TestEVMKeyring_Marshalling(t *testing.T) { // Invalid seed size should error assert.Error(t, kr2.Unmarshal([]byte{0x01})) } - -func TestRawReportContext3(t *testing.T) { - testCases := []struct { - name string - digest [32]byte - seqNr uint64 - expected [2][32]byte - }{ - { - name: "zero values", - digest: [32]byte{}, - seqNr: 0, - expected: [2][32]byte{ - {}, - {}, - }, - }, - { - name: "some digest", - digest: [32]byte{1, 2, 3}, - seqNr: 0, - expected: [2][32]byte{ - {1, 2, 3}, - {}, - }, - }, - { - name: "sequence number set to 1", - digest: [32]byte{}, - seqNr: 1, - expected: [2][32]byte{ - {}, - { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 1, - }, - }, - }, - { - name: "sequence number set to max uint64", - digest: [32]byte{1, 2, 3}, - seqNr: math.MaxUint64, - expected: [2][32]byte{ - {1, 2, 3}, - { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - }, - }, - }, - } - - for _, tc := range testCases { - t.Run(tc.name, func(t *testing.T) { - actual := RawReportContext3(tc.digest, tc.seqNr) - assert.Equal(t, tc.expected, actual, "unexpected result") - }) - } -} diff --git a/core/services/keystore/keys/ocr2key/key_bundle.go b/core/services/keystore/keys/ocr2key/key_bundle.go index a08bd84ac30..2c25a159fef 100644 --- a/core/services/keystore/keys/ocr2key/key_bundle.go +++ b/core/services/keystore/keys/ocr2key/key_bundle.go @@ -19,6 +19,7 @@ type OCR3SignerVerifier interface { Verify3(publicKey ocrtypes.OnchainPublicKey, cd ocrtypes.ConfigDigest, seqNr uint64, r ocrtypes.Report, signature []byte) bool } +// nolint type KeyBundle interface { // OnchainKeyring is used for signing reports (groups of observations, verified onchain) ocrtypes.OnchainKeyring @@ -107,6 +108,7 @@ func (kb keyBundleBase) GoString() string { return kb.String() } +// nolint type Raw []byte func (raw Raw) Key() (kb KeyBundle) { diff --git a/core/services/keystore/keys/ocrkey/key_bundle.go b/core/services/keystore/keys/ocrkey/key_bundle.go new file mode 100644 index 00000000000..a73d8d5bd1e --- /dev/null +++ b/core/services/keystore/keys/ocrkey/key_bundle.go @@ -0,0 +1,259 @@ +package ocrkey + +import ( + "crypto/ecdsa" + "crypto/ed25519" + cryptorand "crypto/rand" + "crypto/sha256" + "encoding/hex" + "encoding/json" + "fmt" + "io" + "log" + "time" + + "github.com/ethereum/go-ethereum/accounts/keystore" + "github.com/pkg/errors" + ocrtypes "github.com/smartcontractkit/libocr/offchainreporting/types" + "golang.org/x/crypto/curve25519" + + "github.com/smartcontractkit/chainlink/v2/core/store/models" + "github.com/smartcontractkit/chainlink/v2/core/utils" +) + +type ( + // KeyBundle represents the bundle of keys needed for OCR + KeyBundle struct { + ID models.Sha256Hash + onChainSigning *onChainPrivateKey + offChainSigning *offChainPrivateKey + offChainEncryption *[curve25519.ScalarSize]byte + } + + // EncryptedKeyBundle holds an encrypted KeyBundle + EncryptedKeyBundle struct { + ID models.Sha256Hash + OnChainSigningAddress OnChainSigningAddress + OffChainPublicKey OffChainPublicKey + ConfigPublicKey ConfigPublicKey + EncryptedPrivateKeys []byte + CreatedAt time.Time + UpdatedAt time.Time + DeletedAt *time.Time + } +) + +func (ekb EncryptedKeyBundle) GetID() string { + return ekb.ID.String() +} + +func (ekb *EncryptedKeyBundle) SetID(value string) error { + var result models.Sha256Hash + decodedString, err := hex.DecodeString(value) + + if err != nil { + return err + } + + copy(result[:], decodedString[:32]) + ekb.ID = result + return nil +} + +// New makes a new set of OCR key bundles from cryptographically secure entropy +func New() (*KeyBundle, error) { + return NewFrom(cryptorand.Reader, cryptorand.Reader, cryptorand.Reader) +} + +// NewFrom makes a new set of OCR key bundles from cryptographically secure entropy +func NewFrom(onChainSigning io.Reader, offChainSigning io.Reader, offChainEncryption io.Reader) (*KeyBundle, error) { + ecdsaKey, err := ecdsa.GenerateKey(curve, onChainSigning) + if err != nil { + return nil, err + } + onChainPriv := (*onChainPrivateKey)(ecdsaKey) + + _, offChainPriv, err := ed25519.GenerateKey(offChainSigning) + if err != nil { + return nil, err + } + var encryptionPriv [curve25519.ScalarSize]byte + _, err = offChainEncryption.Read(encryptionPriv[:]) + if err != nil { + return nil, err + } + k := &KeyBundle{ + onChainSigning: onChainPriv, + offChainSigning: (*offChainPrivateKey)(&offChainPriv), + offChainEncryption: &encryptionPriv, + } + marshalledPrivK, err := json.Marshal(k) + if err != nil { + return nil, err + } + k.ID = sha256.Sum256(marshalledPrivK) + return k, nil +} + +// SignOnChain returns an ethereum-style ECDSA secp256k1 signature on msg. +func (pk *KeyBundle) SignOnChain(msg []byte) (signature []byte, err error) { + return pk.onChainSigning.Sign(msg) +} + +// SignOffChain returns an EdDSA-Ed25519 signature on msg. +func (pk *KeyBundle) SignOffChain(msg []byte) (signature []byte, err error) { + return pk.offChainSigning.Sign(msg) +} + +// ConfigDiffieHellman returns the shared point obtained by multiplying someone's +// public key by a secret scalar ( in this case, the offChainEncryption key.) +func (pk *KeyBundle) ConfigDiffieHellman(base *[curve25519.PointSize]byte) ( + sharedPoint *[curve25519.PointSize]byte, err error, +) { + p, err := curve25519.X25519(pk.offChainEncryption[:], base[:]) + if err != nil { + return nil, err + } + sharedPoint = new([ed25519.PublicKeySize]byte) + copy(sharedPoint[:], p) + return sharedPoint, nil +} + +// PublicKeyAddressOnChain returns public component of the keypair used in +// SignOnChain +func (pk *KeyBundle) PublicKeyAddressOnChain() ocrtypes.OnChainSigningAddress { + return ocrtypes.OnChainSigningAddress(pk.onChainSigning.Address()) +} + +// PublicKeyOffChain returns the public component of the keypair used in SignOffChain +func (pk *KeyBundle) PublicKeyOffChain() ocrtypes.OffchainPublicKey { + return ocrtypes.OffchainPublicKey(pk.offChainSigning.PublicKey()) +} + +// PublicKeyConfig returns the public component of the keypair used in ConfigKeyShare +func (pk *KeyBundle) PublicKeyConfig() [curve25519.PointSize]byte { + rv, err := curve25519.X25519(pk.offChainEncryption[:], curve25519.Basepoint) + if err != nil { + log.Println("failure while computing public key: " + err.Error()) + } + var rvFixed [curve25519.PointSize]byte + copy(rvFixed[:], rv) + return rvFixed +} + +// Encrypt combines the KeyBundle into a single json-serialized +// bytes array and then encrypts +func (pk *KeyBundle) Encrypt(auth string, scryptParams utils.ScryptParams) (*EncryptedKeyBundle, error) { + return pk.encrypt(auth, scryptParams) +} + +// encrypt combines the KeyBundle into a single json-serialized +// bytes array and then encrypts, using the provided scrypt params +// separated into a different function so that scryptParams can be +// weakened in tests +func (pk *KeyBundle) encrypt(auth string, scryptParams utils.ScryptParams) (*EncryptedKeyBundle, error) { + marshalledPrivK, err := json.Marshal(&pk) + if err != nil { + return nil, err + } + cryptoJSON, err := keystore.EncryptDataV3( + marshalledPrivK, + []byte(adulteratedPassword(auth)), + scryptParams.N, + scryptParams.P, + ) + if err != nil { + return nil, errors.Wrapf(err, "could not encrypt ocr key") + } + encryptedPrivKeys, err := json.Marshal(&cryptoJSON) + if err != nil { + return nil, errors.Wrapf(err, "could not encode cryptoJSON") + } + return &EncryptedKeyBundle{ + ID: pk.ID, + OnChainSigningAddress: pk.onChainSigning.Address(), + OffChainPublicKey: pk.offChainSigning.PublicKey(), + ConfigPublicKey: pk.PublicKeyConfig(), + EncryptedPrivateKeys: encryptedPrivKeys, + }, nil +} + +// Decrypt returns the PrivateKeys in e, decrypted via auth, or an error +func (ekb *EncryptedKeyBundle) Decrypt(auth string) (*KeyBundle, error) { + var cryptoJSON keystore.CryptoJSON + err := json.Unmarshal(ekb.EncryptedPrivateKeys, &cryptoJSON) + if err != nil { + return nil, errors.Wrapf(err, "invalid cryptoJSON for OCR key bundle") + } + marshalledPrivK, err := keystore.DecryptDataV3(cryptoJSON, adulteratedPassword(auth)) + if err != nil { + return nil, errors.Wrapf(err, "could not decrypt OCR key bundle") + } + var pk KeyBundle + err = json.Unmarshal(marshalledPrivK, &pk) + if err != nil { + return nil, errors.Wrapf(err, "could not unmarshal OCR key bundle") + } + return &pk, nil +} + +// MarshalJSON marshals the private keys into json +func (pk *KeyBundle) MarshalJSON() ([]byte, error) { + rawKeyData := keyBundleRawData{ + EcdsaD: *pk.onChainSigning.D, + Ed25519PrivKey: []byte(*pk.offChainSigning), + OffChainEncryption: *pk.offChainEncryption, + } + return json.Marshal(&rawKeyData) +} + +// UnmarshalJSON constructs KeyBundle from raw json +func (pk *KeyBundle) UnmarshalJSON(b []byte) (err error) { + var rawKeyData keyBundleRawData + err = json.Unmarshal(b, &rawKeyData) + if err != nil { + return err + } + ecdsaDSize := len(rawKeyData.EcdsaD.Bytes()) + if ecdsaDSize > curve25519.PointSize { + return errors.Wrapf(ErrScalarTooBig, "got %d byte ecdsa scalar", ecdsaDSize) + } + + publicKey := ecdsa.PublicKey{Curve: curve} + publicKey.X, publicKey.Y = curve.ScalarBaseMult(rawKeyData.EcdsaD.Bytes()) + privateKey := ecdsa.PrivateKey{ + PublicKey: publicKey, + D: &rawKeyData.EcdsaD, + } + onChainSigning := onChainPrivateKey(privateKey) + offChainSigning := offChainPrivateKey(rawKeyData.Ed25519PrivKey) + pk.onChainSigning = &onChainSigning + pk.offChainSigning = &offChainSigning + pk.offChainEncryption = &rawKeyData.OffChainEncryption + pk.ID = sha256.Sum256(b) + return nil +} + +// String reduces the risk of accidentally logging the private key +func (pk KeyBundle) String() string { + addressOnChain := pk.PublicKeyAddressOnChain() + return fmt.Sprintf( + "KeyBundle{PublicKeyAddressOnChain: %s, PublicKeyOffChain: %s}", + hex.EncodeToString(addressOnChain[:]), + hex.EncodeToString(pk.PublicKeyOffChain()), + ) +} + +// GoString reduces the risk of accidentally logging the private key +func (pk KeyBundle) GoString() string { + return pk.String() +} + +// GoString reduces the risk of accidentally logging the private key +func (pk KeyBundle) ToV2() KeyV2 { + return KeyV2{ + OnChainSigning: pk.onChainSigning, + OffChainSigning: pk.offChainSigning, + OffChainEncryption: pk.offChainEncryption, + } +} diff --git a/core/services/keystore/keys/ocrkey/key_bundle_test.go b/core/services/keystore/keys/ocrkey/key_bundle_test.go new file mode 100644 index 00000000000..fe9391735a1 --- /dev/null +++ b/core/services/keystore/keys/ocrkey/key_bundle_test.go @@ -0,0 +1,102 @@ +package ocrkey_test + +import ( + "math/big" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/ocrkey" + "github.com/smartcontractkit/chainlink/v2/core/utils" +) + +func assertKeyBundlesNotEqual(t *testing.T, pk1 ocrkey.KeyV2, pk2 ocrkey.KeyV2) { + assert.NotEqual(t, pk1.ID(), pk2.ID()) + assert.NotEqual(t, pk1.ExportedOnChainSigning().X, pk2.ExportedOnChainSigning().X) + assert.NotEqual(t, pk1.ExportedOnChainSigning().Y, pk2.ExportedOnChainSigning().Y) + assert.NotEqual(t, pk1.ExportedOnChainSigning().D, pk2.ExportedOnChainSigning().D) + assert.NotEqual(t, pk1.ExportedOffChainSigning().PublicKey(), pk2.ExportedOffChainSigning().PublicKey()) + assert.NotEqual(t, pk1.ExportedOffChainEncryption(), pk2.ExportedOffChainEncryption()) +} + +func TestOCRKeys_New(t *testing.T) { + t.Parallel() + pk1, err := ocrkey.NewV2() + require.NoError(t, err) + pk2, err := ocrkey.NewV2() + require.NoError(t, err) + pk3, err := ocrkey.NewV2() + require.NoError(t, err) + assertKeyBundlesNotEqual(t, pk1, pk2) + assertKeyBundlesNotEqual(t, pk1, pk3) + assertKeyBundlesNotEqual(t, pk2, pk3) +} + +func TestOCRKeys_NewBundleIDMatchesOld(t *testing.T) { + t.Parallel() + oldKey, err := ocrkey.New() + require.NoError(t, err) + newKey := oldKey.ToV2() + require.Equal(t, oldKey.ID.String(), newKey.ID()) +} + +func TestOCRKeys_Raw_Key(t *testing.T) { + t.Parallel() + key := ocrkey.MustNewV2XXXTestingOnly(big.NewInt(1)) + require.Equal(t, key.ID(), key.Raw().Key().ID()) +} + +func TestOCRKeys_BundleSetID(t *testing.T) { + t.Parallel() + + k, err := ocrkey.New() + require.NoError(t, err) + ek, err := k.Encrypt("test", utils.FastScryptParams) + require.NoError(t, err) + + oldId := ek.GetID() + err = ek.SetID("48656c6c6f20476f7068657221") + require.NoError(t, err) + + assert.NotEqual(t, oldId, ek.GetID()) + + err = ek.SetID("invalid id") + assert.Error(t, err) +} + +func TestOCRKeys_BundleDecrypt(t *testing.T) { + t.Parallel() + + k, err := ocrkey.New() + require.NoError(t, err) + ek, err := k.Encrypt("test", utils.FastScryptParams) + require.NoError(t, err) + + _, err = ek.Decrypt("wrongpass") + assert.Error(t, err) + + dk, err := ek.Decrypt("test") + require.NoError(t, err) + + dk.GoString() + assert.Equal(t, k.GoString(), dk.GoString()) + assert.Equal(t, k.ID.String(), dk.ID.String()) +} + +func TestOCRKeys_BundleMarshalling(t *testing.T) { + t.Parallel() + + k, err := ocrkey.New() + require.NoError(t, err) + k2, err := ocrkey.New() + require.NoError(t, err) + + mk, err := k.MarshalJSON() + require.NoError(t, err) + + err = k2.UnmarshalJSON(mk) + require.NoError(t, err) + + assert.Equal(t, k.String(), k2.String()) +} diff --git a/core/services/keystore/keys/ocrkey/key_v2_test.go b/core/services/keystore/keys/ocrkey/key_v2_test.go deleted file mode 100644 index 3fd2417b704..00000000000 --- a/core/services/keystore/keys/ocrkey/key_v2_test.go +++ /dev/null @@ -1,38 +0,0 @@ -package ocrkey_test - -import ( - "math/big" - "testing" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - - "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/ocrkey" -) - -func assertKeyBundlesNotEqual(t *testing.T, pk1 ocrkey.KeyV2, pk2 ocrkey.KeyV2) { - assert.NotEqual(t, pk1.ID(), pk2.ID()) - assert.NotEqual(t, pk1.ExportedOnChainSigning().X, pk2.ExportedOnChainSigning().X) - assert.NotEqual(t, pk1.ExportedOnChainSigning().Y, pk2.ExportedOnChainSigning().Y) - assert.NotEqual(t, pk1.ExportedOnChainSigning().D, pk2.ExportedOnChainSigning().D) - assert.NotEqual(t, pk1.ExportedOffChainSigning().PublicKey(), pk2.ExportedOffChainSigning().PublicKey()) - assert.NotEqual(t, pk1.ExportedOffChainEncryption(), pk2.ExportedOffChainEncryption()) -} - -func TestOCRKeys_New(t *testing.T) { - t.Parallel() - pk1, err := ocrkey.NewV2() - require.NoError(t, err) - pk2, err := ocrkey.NewV2() - require.NoError(t, err) - pk3, err := ocrkey.NewV2() - require.NoError(t, err) - assertKeyBundlesNotEqual(t, pk1, pk2) - assertKeyBundlesNotEqual(t, pk1, pk3) - assertKeyBundlesNotEqual(t, pk2, pk3) -} -func TestOCRKeys_Raw_Key(t *testing.T) { - t.Parallel() - key := ocrkey.MustNewV2XXXTestingOnly(big.NewInt(1)) - require.Equal(t, key.ID(), key.Raw().Key().ID()) -} diff --git a/core/services/keystore/keys/ocrkey/off_chain_private_key_test.go b/core/services/keystore/keys/ocrkey/off_chan_private_key_test.go similarity index 77% rename from core/services/keystore/keys/ocrkey/off_chain_private_key_test.go rename to core/services/keystore/keys/ocrkey/off_chan_private_key_test.go index a7eadc72860..0c0f6a96957 100644 --- a/core/services/keystore/keys/ocrkey/off_chain_private_key_test.go +++ b/core/services/keystore/keys/ocrkey/off_chan_private_key_test.go @@ -10,10 +10,10 @@ import ( func TestOCRKeys_OffChainPrivateKey(t *testing.T) { t.Parallel() - k, err := NewV2() + k, err := New() require.NoError(t, err) - sig, err := k.OffChainSigning.Sign([]byte("hello world")) + sig, err := k.offChainSigning.Sign([]byte("hello world")) assert.NoError(t, err) assert.NotEmpty(t, sig) diff --git a/core/services/keystore/keys/solkey/key.go b/core/services/keystore/keys/solkey/key.go index 610dada64b1..c6cdd62d3bf 100644 --- a/core/services/keystore/keys/solkey/key.go +++ b/core/services/keystore/keys/solkey/key.go @@ -17,9 +17,11 @@ type Raw []byte // Key gets the Key func (raw Raw) Key() Key { privKey := ed25519.NewKeyFromSeed(raw) + pubKey := make([]byte, ed25519.PublicKeySize) + copy(pubKey, privKey[ed25519.PublicKeySize:]) return Key{ privkey: privKey, - pubKey: privKey.Public().(ed25519.PublicKey), + pubKey: pubKey, } } diff --git a/core/services/keystore/keys/workflowkey/key.go b/core/services/keystore/keys/workflowkey/key.go index 084878a5ee3..ce8560303e0 100644 --- a/core/services/keystore/keys/workflowkey/key.go +++ b/core/services/keystore/keys/workflowkey/key.go @@ -50,18 +50,10 @@ func New() (Key, error) { } func (k Key) PublicKey() [curve25519.PointSize]byte { - if k.publicKey == nil { - return [curve25519.PointSize]byte{} - } - return *k.publicKey } func (k Key) PublicKeyString() string { - if k.publicKey == nil { - return "" - } - return hex.EncodeToString(k.publicKey[:]) } @@ -86,10 +78,6 @@ func (k Key) GoString() string { // Encrypt encrypts a message using the public key func (k Key) Encrypt(plaintext []byte) ([]byte, error) { publicKey := k.PublicKey() - if publicKey == [curve25519.PointSize]byte{} { - return nil, errors.New("public key is empty") - } - encrypted, err := box.SealAnonymous(nil, plaintext, &publicKey, cryptorand.Reader) if err != nil { return nil, err @@ -101,10 +89,6 @@ func (k Key) Encrypt(plaintext []byte) ([]byte, error) { // Decrypt decrypts a message that was encrypted using the private key func (k Key) Decrypt(ciphertext []byte) (plaintext []byte, err error) { publicKey := k.PublicKey() - if publicKey == [curve25519.PointSize]byte{} { - return nil, errors.New("public key is empty") - } - decrypted, success := box.OpenAnonymous(nil, ciphertext, &publicKey, k.privateKey) if !success { return nil, errors.New("decryption failed") diff --git a/core/services/keystore/keystoretest.go b/core/services/keystore/keystoretest.go index 626cc4bab99..e179b51bb54 100644 --- a/core/services/keystore/keystoretest.go +++ b/core/services/keystore/keystoretest.go @@ -75,6 +75,5 @@ func NewInMemory(ds sqlutil.DataSource, scryptParams utils.ScryptParams, lggr lo starknet: newStarkNetKeyStore(km), aptos: newAptosKeyStore(km), vrf: newVRFKeyStore(km), - workflow: newWorkflowKeyStore(km), } } diff --git a/core/services/keystore/mocks/workflow.go b/core/services/keystore/mocks/workflow.go deleted file mode 100644 index f19045cecc4..00000000000 --- a/core/services/keystore/mocks/workflow.go +++ /dev/null @@ -1,474 +0,0 @@ -// Code generated by mockery v2.46.3. DO NOT EDIT. - -package mocks - -import ( - context "context" - - mock "github.com/stretchr/testify/mock" - - workflowkey "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/workflowkey" -) - -// Workflow is an autogenerated mock type for the Workflow type -type Workflow struct { - mock.Mock -} - -type Workflow_Expecter struct { - mock *mock.Mock -} - -func (_m *Workflow) EXPECT() *Workflow_Expecter { - return &Workflow_Expecter{mock: &_m.Mock} -} - -// Add provides a mock function with given fields: ctx, key -func (_m *Workflow) Add(ctx context.Context, key workflowkey.Key) error { - ret := _m.Called(ctx, key) - - if len(ret) == 0 { - panic("no return value specified for Add") - } - - var r0 error - if rf, ok := ret.Get(0).(func(context.Context, workflowkey.Key) error); ok { - r0 = rf(ctx, key) - } else { - r0 = ret.Error(0) - } - - return r0 -} - -// Workflow_Add_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Add' -type Workflow_Add_Call struct { - *mock.Call -} - -// Add is a helper method to define mock.On call -// - ctx context.Context -// - key workflowkey.Key -func (_e *Workflow_Expecter) Add(ctx interface{}, key interface{}) *Workflow_Add_Call { - return &Workflow_Add_Call{Call: _e.mock.On("Add", ctx, key)} -} - -func (_c *Workflow_Add_Call) Run(run func(ctx context.Context, key workflowkey.Key)) *Workflow_Add_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context), args[1].(workflowkey.Key)) - }) - return _c -} - -func (_c *Workflow_Add_Call) Return(_a0 error) *Workflow_Add_Call { - _c.Call.Return(_a0) - return _c -} - -func (_c *Workflow_Add_Call) RunAndReturn(run func(context.Context, workflowkey.Key) error) *Workflow_Add_Call { - _c.Call.Return(run) - return _c -} - -// Create provides a mock function with given fields: ctx -func (_m *Workflow) Create(ctx context.Context) (workflowkey.Key, error) { - ret := _m.Called(ctx) - - if len(ret) == 0 { - panic("no return value specified for Create") - } - - var r0 workflowkey.Key - var r1 error - if rf, ok := ret.Get(0).(func(context.Context) (workflowkey.Key, error)); ok { - return rf(ctx) - } - if rf, ok := ret.Get(0).(func(context.Context) workflowkey.Key); ok { - r0 = rf(ctx) - } else { - r0 = ret.Get(0).(workflowkey.Key) - } - - if rf, ok := ret.Get(1).(func(context.Context) error); ok { - r1 = rf(ctx) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// Workflow_Create_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Create' -type Workflow_Create_Call struct { - *mock.Call -} - -// Create is a helper method to define mock.On call -// - ctx context.Context -func (_e *Workflow_Expecter) Create(ctx interface{}) *Workflow_Create_Call { - return &Workflow_Create_Call{Call: _e.mock.On("Create", ctx)} -} - -func (_c *Workflow_Create_Call) Run(run func(ctx context.Context)) *Workflow_Create_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context)) - }) - return _c -} - -func (_c *Workflow_Create_Call) Return(_a0 workflowkey.Key, _a1 error) *Workflow_Create_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *Workflow_Create_Call) RunAndReturn(run func(context.Context) (workflowkey.Key, error)) *Workflow_Create_Call { - _c.Call.Return(run) - return _c -} - -// Delete provides a mock function with given fields: ctx, id -func (_m *Workflow) Delete(ctx context.Context, id string) (workflowkey.Key, error) { - ret := _m.Called(ctx, id) - - if len(ret) == 0 { - panic("no return value specified for Delete") - } - - var r0 workflowkey.Key - var r1 error - if rf, ok := ret.Get(0).(func(context.Context, string) (workflowkey.Key, error)); ok { - return rf(ctx, id) - } - if rf, ok := ret.Get(0).(func(context.Context, string) workflowkey.Key); ok { - r0 = rf(ctx, id) - } else { - r0 = ret.Get(0).(workflowkey.Key) - } - - if rf, ok := ret.Get(1).(func(context.Context, string) error); ok { - r1 = rf(ctx, id) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// Workflow_Delete_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Delete' -type Workflow_Delete_Call struct { - *mock.Call -} - -// Delete is a helper method to define mock.On call -// - ctx context.Context -// - id string -func (_e *Workflow_Expecter) Delete(ctx interface{}, id interface{}) *Workflow_Delete_Call { - return &Workflow_Delete_Call{Call: _e.mock.On("Delete", ctx, id)} -} - -func (_c *Workflow_Delete_Call) Run(run func(ctx context.Context, id string)) *Workflow_Delete_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context), args[1].(string)) - }) - return _c -} - -func (_c *Workflow_Delete_Call) Return(_a0 workflowkey.Key, _a1 error) *Workflow_Delete_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *Workflow_Delete_Call) RunAndReturn(run func(context.Context, string) (workflowkey.Key, error)) *Workflow_Delete_Call { - _c.Call.Return(run) - return _c -} - -// EnsureKey provides a mock function with given fields: ctx -func (_m *Workflow) EnsureKey(ctx context.Context) error { - ret := _m.Called(ctx) - - if len(ret) == 0 { - panic("no return value specified for EnsureKey") - } - - var r0 error - if rf, ok := ret.Get(0).(func(context.Context) error); ok { - r0 = rf(ctx) - } else { - r0 = ret.Error(0) - } - - return r0 -} - -// Workflow_EnsureKey_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'EnsureKey' -type Workflow_EnsureKey_Call struct { - *mock.Call -} - -// EnsureKey is a helper method to define mock.On call -// - ctx context.Context -func (_e *Workflow_Expecter) EnsureKey(ctx interface{}) *Workflow_EnsureKey_Call { - return &Workflow_EnsureKey_Call{Call: _e.mock.On("EnsureKey", ctx)} -} - -func (_c *Workflow_EnsureKey_Call) Run(run func(ctx context.Context)) *Workflow_EnsureKey_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context)) - }) - return _c -} - -func (_c *Workflow_EnsureKey_Call) Return(_a0 error) *Workflow_EnsureKey_Call { - _c.Call.Return(_a0) - return _c -} - -func (_c *Workflow_EnsureKey_Call) RunAndReturn(run func(context.Context) error) *Workflow_EnsureKey_Call { - _c.Call.Return(run) - return _c -} - -// Export provides a mock function with given fields: id, password -func (_m *Workflow) Export(id string, password string) ([]byte, error) { - ret := _m.Called(id, password) - - if len(ret) == 0 { - panic("no return value specified for Export") - } - - var r0 []byte - var r1 error - if rf, ok := ret.Get(0).(func(string, string) ([]byte, error)); ok { - return rf(id, password) - } - if rf, ok := ret.Get(0).(func(string, string) []byte); ok { - r0 = rf(id, password) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).([]byte) - } - } - - if rf, ok := ret.Get(1).(func(string, string) error); ok { - r1 = rf(id, password) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// Workflow_Export_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Export' -type Workflow_Export_Call struct { - *mock.Call -} - -// Export is a helper method to define mock.On call -// - id string -// - password string -func (_e *Workflow_Expecter) Export(id interface{}, password interface{}) *Workflow_Export_Call { - return &Workflow_Export_Call{Call: _e.mock.On("Export", id, password)} -} - -func (_c *Workflow_Export_Call) Run(run func(id string, password string)) *Workflow_Export_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(string), args[1].(string)) - }) - return _c -} - -func (_c *Workflow_Export_Call) Return(_a0 []byte, _a1 error) *Workflow_Export_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *Workflow_Export_Call) RunAndReturn(run func(string, string) ([]byte, error)) *Workflow_Export_Call { - _c.Call.Return(run) - return _c -} - -// Get provides a mock function with given fields: id -func (_m *Workflow) Get(id string) (workflowkey.Key, error) { - ret := _m.Called(id) - - if len(ret) == 0 { - panic("no return value specified for Get") - } - - var r0 workflowkey.Key - var r1 error - if rf, ok := ret.Get(0).(func(string) (workflowkey.Key, error)); ok { - return rf(id) - } - if rf, ok := ret.Get(0).(func(string) workflowkey.Key); ok { - r0 = rf(id) - } else { - r0 = ret.Get(0).(workflowkey.Key) - } - - if rf, ok := ret.Get(1).(func(string) error); ok { - r1 = rf(id) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// Workflow_Get_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Get' -type Workflow_Get_Call struct { - *mock.Call -} - -// Get is a helper method to define mock.On call -// - id string -func (_e *Workflow_Expecter) Get(id interface{}) *Workflow_Get_Call { - return &Workflow_Get_Call{Call: _e.mock.On("Get", id)} -} - -func (_c *Workflow_Get_Call) Run(run func(id string)) *Workflow_Get_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(string)) - }) - return _c -} - -func (_c *Workflow_Get_Call) Return(_a0 workflowkey.Key, _a1 error) *Workflow_Get_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *Workflow_Get_Call) RunAndReturn(run func(string) (workflowkey.Key, error)) *Workflow_Get_Call { - _c.Call.Return(run) - return _c -} - -// GetAll provides a mock function with given fields: -func (_m *Workflow) GetAll() ([]workflowkey.Key, error) { - ret := _m.Called() - - if len(ret) == 0 { - panic("no return value specified for GetAll") - } - - var r0 []workflowkey.Key - var r1 error - if rf, ok := ret.Get(0).(func() ([]workflowkey.Key, error)); ok { - return rf() - } - if rf, ok := ret.Get(0).(func() []workflowkey.Key); ok { - r0 = rf() - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).([]workflowkey.Key) - } - } - - if rf, ok := ret.Get(1).(func() error); ok { - r1 = rf() - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// Workflow_GetAll_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetAll' -type Workflow_GetAll_Call struct { - *mock.Call -} - -// GetAll is a helper method to define mock.On call -func (_e *Workflow_Expecter) GetAll() *Workflow_GetAll_Call { - return &Workflow_GetAll_Call{Call: _e.mock.On("GetAll")} -} - -func (_c *Workflow_GetAll_Call) Run(run func()) *Workflow_GetAll_Call { - _c.Call.Run(func(args mock.Arguments) { - run() - }) - return _c -} - -func (_c *Workflow_GetAll_Call) Return(_a0 []workflowkey.Key, _a1 error) *Workflow_GetAll_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *Workflow_GetAll_Call) RunAndReturn(run func() ([]workflowkey.Key, error)) *Workflow_GetAll_Call { - _c.Call.Return(run) - return _c -} - -// Import provides a mock function with given fields: ctx, keyJSON, password -func (_m *Workflow) Import(ctx context.Context, keyJSON []byte, password string) (workflowkey.Key, error) { - ret := _m.Called(ctx, keyJSON, password) - - if len(ret) == 0 { - panic("no return value specified for Import") - } - - var r0 workflowkey.Key - var r1 error - if rf, ok := ret.Get(0).(func(context.Context, []byte, string) (workflowkey.Key, error)); ok { - return rf(ctx, keyJSON, password) - } - if rf, ok := ret.Get(0).(func(context.Context, []byte, string) workflowkey.Key); ok { - r0 = rf(ctx, keyJSON, password) - } else { - r0 = ret.Get(0).(workflowkey.Key) - } - - if rf, ok := ret.Get(1).(func(context.Context, []byte, string) error); ok { - r1 = rf(ctx, keyJSON, password) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// Workflow_Import_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Import' -type Workflow_Import_Call struct { - *mock.Call -} - -// Import is a helper method to define mock.On call -// - ctx context.Context -// - keyJSON []byte -// - password string -func (_e *Workflow_Expecter) Import(ctx interface{}, keyJSON interface{}, password interface{}) *Workflow_Import_Call { - return &Workflow_Import_Call{Call: _e.mock.On("Import", ctx, keyJSON, password)} -} - -func (_c *Workflow_Import_Call) Run(run func(ctx context.Context, keyJSON []byte, password string)) *Workflow_Import_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context), args[1].([]byte), args[2].(string)) - }) - return _c -} - -func (_c *Workflow_Import_Call) Return(_a0 workflowkey.Key, _a1 error) *Workflow_Import_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *Workflow_Import_Call) RunAndReturn(run func(context.Context, []byte, string) (workflowkey.Key, error)) *Workflow_Import_Call { - _c.Call.Return(run) - return _c -} - -// NewWorkflow creates a new instance of Workflow. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. -// The first argument is typically a *testing.T value. -func NewWorkflow(t interface { - mock.TestingT - Cleanup(func()) -}) *Workflow { - mock := &Workflow{} - mock.Mock.Test(t) - - t.Cleanup(func() { mock.AssertExpectations(t) }) - - return mock -} diff --git a/core/services/keystore/models.go b/core/services/keystore/models.go index 151934827c3..e0b53ef95e4 100644 --- a/core/services/keystore/models.go +++ b/core/services/keystore/models.go @@ -239,9 +239,6 @@ func (kr *keyRing) raw() (rawKeys rawKeyRing) { for _, vrfKey := range kr.VRF { rawKeys.VRF = append(rawKeys.VRF, vrfKey.Raw()) } - for _, workflowKey := range kr.Workflow { - rawKeys.Workflow = append(rawKeys.Workflow, workflowKey.Raw()) - } return rawKeys } @@ -287,12 +284,6 @@ func (kr *keyRing) logPubKeys(lggr logger.Logger) { for _, VRFKey := range kr.VRF { vrfIDs = append(vrfIDs, VRFKey.ID()) } - workflowIDs := make([]string, len(kr.Workflow)) - i := 0 - for _, workflowKey := range kr.Workflow { - workflowIDs[i] = workflowKey.ID() - i++ - } if len(csaIDs) > 0 { lggr.Infow(fmt.Sprintf("Unlocked %d CSA keys", len(csaIDs)), "keys", csaIDs) } @@ -323,9 +314,6 @@ func (kr *keyRing) logPubKeys(lggr logger.Logger) { if len(vrfIDs) > 0 { lggr.Infow(fmt.Sprintf("Unlocked %d VRF keys", len(vrfIDs)), "keys", vrfIDs) } - if len(workflowIDs) > 0 { - lggr.Infow(fmt.Sprintf("Unlocked %d Workflow keys", len(workflowIDs)), "keys", workflowIDs) - } if len(kr.LegacyKeys.legacyRawKeys) > 0 { lggr.Infow(fmt.Sprintf("%d keys stored in legacy system", kr.LegacyKeys.legacyRawKeys.len())) } @@ -345,7 +333,6 @@ type rawKeyRing struct { StarkNet []starkkey.Raw Aptos []aptoskey.Raw VRF []vrfkey.Raw - Workflow []workflowkey.Raw LegacyKeys LegacyKeyStorage `json:"-"` } @@ -392,10 +379,6 @@ func (rawKeys rawKeyRing) keys() (*keyRing, error) { vrfKey := rawVRFKey.Key() keyRing.VRF[vrfKey.ID()] = vrfKey } - for _, rawWorkflowKey := range rawKeys.Workflow { - workflowKey := rawWorkflowKey.Key() - keyRing.Workflow[workflowKey.ID()] = workflowKey - } keyRing.LegacyKeys = rawKeys.LegacyKeys return keyRing, nil diff --git a/core/services/keystore/workflow_test.go b/core/services/keystore/workflow_test.go index d7e540b9c75..051ebdb76a7 100644 --- a/core/services/keystore/workflow_test.go +++ b/core/services/keystore/workflow_test.go @@ -175,39 +175,4 @@ func Test_EncryptionKeyStore_E2E(t *testing.T) { require.NoError(t, err) require.Len(t, keys, 1) }) - - t.Run("persists keys across restarts", func(t *testing.T) { - defer reset() - ctx := testutils.Context(t) - - keys, err := ks.GetAll() - require.NoError(t, err) - assert.Empty(t, keys) - - err = keyStore.Workflow().EnsureKey(ctx) - require.NoError(t, err) - - keys, err = ks.GetAll() - require.NoError(t, err) - - require.NoError(t, err) - require.Len(t, keys, 1) - - // Now instantiate the keystore again, but with the same DB - // This should fetch the key directly from the DB. - keyStore := keystore.ExposedNewMaster(t, db) - require.NoError(t, keyStore.Unlock(testutils.Context(t), cltest.Password)) - - gotKeys, err := keyStore.Workflow().GetAll() - require.NoError(t, err) - require.Len(t, gotKeys, 1) - - assert.Equal(t, keys[0].PublicKeyString(), gotKeys[0].PublicKeyString()) - - err = keyStore.Workflow().EnsureKey(testutils.Context(t)) - require.NoError(t, err) - gotKeys, err = keyStore.Workflow().GetAll() - require.NoError(t, err) - require.Len(t, gotKeys, 1) - }) } diff --git a/core/services/llo/bm/dummy_transmitter.go b/core/services/llo/bm/dummy_transmitter.go index f62635a7953..b7fa2bd9e15 100644 --- a/core/services/llo/bm/dummy_transmitter.go +++ b/core/services/llo/bm/dummy_transmitter.go @@ -23,11 +23,9 @@ import ( // A dummy transmitter useful for benchmarking and testing var ( - promTransmitSuccessCount = promauto.NewCounter(prometheus.CounterOpts{ - Namespace: "llo", - Subsystem: "dummytransmitter", - Name: "transmit_success_count", - Help: "Running count of successful transmits", + transmitSuccessCount = promauto.NewCounter(prometheus.CounterOpts{ + Name: "llo_transmit_success_count", + Help: "Running count of successful transmits", }) ) @@ -103,7 +101,7 @@ func (t *transmitter) Transmit( lggr.Debugw(fmt.Sprintf("Failed to decode report with type %s", report.Info.ReportFormat), "err", err) } } - promTransmitSuccessCount.Inc() + transmitSuccessCount.Inc() lggr.Infow("Transmit (dummy)", "digest", digest, "seqNr", seqNr, "report.Report", report.Report, "report.Info", report.Info, "sigs", sigs) return nil } diff --git a/core/services/llo/channel_definition_cache_factory.go b/core/services/llo/channel_definition_cache_factory.go index 3306a274aef..0cc2543cdf1 100644 --- a/core/services/llo/channel_definition_cache_factory.go +++ b/core/services/llo/channel_definition_cache_factory.go @@ -41,6 +41,8 @@ type channelDefinitionCacheFactory struct { mu sync.Mutex } +// TODO: Test this +// MERC-3653 func (f *channelDefinitionCacheFactory) NewCache(cfg lloconfig.PluginConfig) (llotypes.ChannelDefinitionCache, error) { if cfg.ChannelDefinitions != "" { return NewStaticChannelDefinitionCache(f.lggr, cfg.ChannelDefinitions) diff --git a/core/services/llo/channel_definition_cache_factory_test.go b/core/services/llo/channel_definition_cache_factory_test.go deleted file mode 100644 index 1be9d3dd0bc..00000000000 --- a/core/services/llo/channel_definition_cache_factory_test.go +++ /dev/null @@ -1,58 +0,0 @@ -package llo - -import ( - "testing" - - "github.com/ethereum/go-ethereum/common" - "github.com/stretchr/testify/require" - - "github.com/smartcontractkit/chainlink/v2/core/logger" - lloconfig "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/llo/config" -) - -func Test_ChannelDefinitionCacheFactory(t *testing.T) { - lggr := logger.TestLogger(t) - cdcFactory := NewChannelDefinitionCacheFactory(lggr, nil, nil, nil) - - t.Run("NewCache", func(t *testing.T) { - t.Run("when ChannelDefinitions is present, returns static cache", func(t *testing.T) { - _, err := cdcFactory.NewCache(lloconfig.PluginConfig{ChannelDefinitions: "..."}) - require.EqualError(t, err, "failed to unmarshal static channel definitions: invalid character '.' looking for beginning of value") - - cdc, err := cdcFactory.NewCache(lloconfig.PluginConfig{ChannelDefinitions: "{}"}) - require.NoError(t, err) - require.IsType(t, &staticCDC{}, cdc) - }) - t.Run("when ChannelDefinitions is not present, returns dynamic cache", func(t *testing.T) { - cdc, err := cdcFactory.NewCache(lloconfig.PluginConfig{ - ChannelDefinitionsContractAddress: common.HexToAddress("0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"), - DonID: 1, - }) - require.NoError(t, err) - require.IsType(t, &channelDefinitionCache{}, cdc) - - // returns error if you try to do it again with the same addr/donID - _, err = cdcFactory.NewCache(lloconfig.PluginConfig{ - ChannelDefinitionsContractAddress: common.HexToAddress("0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"), - DonID: 1, - }) - require.EqualError(t, err, "cache already exists for contract address 0xaAaAaAaaAaAaAaaAaAAAAAAAAaaaAaAaAaaAaaAa and don ID 1") - - // is fine if you do it again with different addr - cdc, err = cdcFactory.NewCache(lloconfig.PluginConfig{ - ChannelDefinitionsContractAddress: common.HexToAddress("0xbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"), - DonID: 1, - }) - require.NoError(t, err) - require.IsType(t, &channelDefinitionCache{}, cdc) - - // is fine if you do it again with different don ID - cdc, err = cdcFactory.NewCache(lloconfig.PluginConfig{ - ChannelDefinitionsContractAddress: common.HexToAddress("0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"), - DonID: 2, - }) - require.NoError(t, err) - require.IsType(t, &channelDefinitionCache{}, cdc) - }) - }) -} diff --git a/core/services/llo/codecs.go b/core/services/llo/codecs.go index f9c5b7b3380..7813c8923ea 100644 --- a/core/services/llo/codecs.go +++ b/core/services/llo/codecs.go @@ -1,7 +1,6 @@ package llo import ( - "github.com/smartcontractkit/chainlink-common/pkg/logger" llotypes "github.com/smartcontractkit/chainlink-common/pkg/types/llo" "github.com/smartcontractkit/chainlink-data-streams/llo" @@ -9,11 +8,11 @@ import ( ) // NOTE: All supported codecs must be specified here -func NewReportCodecs(lggr logger.Logger, donID uint32) map[llotypes.ReportFormat]llo.ReportCodec { +func NewReportCodecs() map[llotypes.ReportFormat]llo.ReportCodec { codecs := make(map[llotypes.ReportFormat]llo.ReportCodec) codecs[llotypes.ReportFormatJSON] = llo.JSONReportCodec{} - codecs[llotypes.ReportFormatEVMPremiumLegacy] = evm.NewReportCodecPremiumLegacy(lggr, donID) + codecs[llotypes.ReportFormatEVMPremiumLegacy] = evm.ReportCodecPremiumLegacy{} return codecs } diff --git a/core/services/llo/codecs_test.go b/core/services/llo/codecs_test.go index ad7d732f7cc..4a7f3f65571 100644 --- a/core/services/llo/codecs_test.go +++ b/core/services/llo/codecs_test.go @@ -6,11 +6,10 @@ import ( "github.com/stretchr/testify/assert" llotypes "github.com/smartcontractkit/chainlink-common/pkg/types/llo" - "github.com/smartcontractkit/chainlink/v2/core/logger" ) func Test_NewReportCodecs(t *testing.T) { - c := NewReportCodecs(logger.TestLogger(t), 1) + c := NewReportCodecs() assert.Contains(t, c, llotypes.ReportFormatJSON, "expected JSON to be supported") assert.Contains(t, c, llotypes.ReportFormatEVMPremiumLegacy, "expected EVMPremiumLegacy to be supported") diff --git a/core/services/llo/data_source.go b/core/services/llo/data_source.go index 2afe9e090a3..ef333f821a1 100644 --- a/core/services/llo/data_source.go +++ b/core/services/llo/data_source.go @@ -3,10 +3,8 @@ package llo import ( "context" "fmt" - "slices" "sort" "sync" - "time" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/promauto" @@ -24,18 +22,14 @@ import ( var ( promMissingStreamCount = promauto.NewCounterVec(prometheus.CounterOpts{ - Namespace: "llo", - Subsystem: "datasource", - Name: "stream_missing_count", - Help: "Number of times we tried to observe a stream, but it was missing", + Name: "llo_stream_missing_count", + Help: "Number of times we tried to observe a stream, but it was missing", }, []string{"streamID"}, ) promObservationErrorCount = promauto.NewCounterVec(prometheus.CounterOpts{ - Namespace: "llo", - Subsystem: "datasource", - Name: "stream_observation_error_count", - Help: "Number of times we tried to observe a stream, but it failed with an error", + Name: "llo_stream_observation_error_count", + Help: "Number of times we tried to observe a stream, but it failed with an error", }, []string{"streamID"}, ) @@ -91,7 +85,11 @@ func newDataSource(lggr logger.Logger, registry Registry, t Telemeter) *dataSour // Observe looks up all streams in the registry and populates a map of stream ID => value func (d *dataSource) Observe(ctx context.Context, streamValues llo.StreamValues, opts llo.DSOpts) error { - now := time.Now() + var wg sync.WaitGroup + wg.Add(len(streamValues)) + var svmu sync.Mutex + var errs []ErrObservationFailed + var errmu sync.Mutex if opts.VerboseLogging() { streamIDs := make([]streams.StreamID, 0, len(streamValues)) @@ -102,13 +100,6 @@ func (d *dataSource) Observe(ctx context.Context, streamValues llo.StreamValues, d.lggr.Debugw("Observing streams", "streamIDs", streamIDs, "configDigest", opts.ConfigDigest(), "seqNr", opts.OutCtx().SeqNr) } - var wg sync.WaitGroup - wg.Add(len(streamValues)) - - var mu sync.Mutex - successfulStreamIDs := make([]streams.StreamID, 0, len(streamValues)) - var errs []ErrObservationFailed - for _, streamID := range maps.Keys(streamValues) { go func(streamID llotypes.StreamID) { defer wg.Done() @@ -117,17 +108,17 @@ func (d *dataSource) Observe(ctx context.Context, streamValues llo.StreamValues, stream, exists := d.registry.Get(streamID) if !exists { - mu.Lock() + errmu.Lock() errs = append(errs, ErrObservationFailed{streamID: streamID, reason: fmt.Sprintf("missing stream: %d", streamID)}) - mu.Unlock() + errmu.Unlock() promMissingStreamCount.WithLabelValues(fmt.Sprintf("%d", streamID)).Inc() return } run, trrs, err := stream.Run(ctx) if err != nil { - mu.Lock() + errmu.Lock() errs = append(errs, ErrObservationFailed{inner: err, run: run, streamID: streamID, reason: "pipeline run failed"}) - mu.Unlock() + errmu.Unlock() promObservationErrorCount.WithLabelValues(fmt.Sprintf("%d", streamID)).Inc() // TODO: Consolidate/reduce telemetry. We should send all observation results in a single packet // https://smartcontract-it.atlassian.net/browse/MERC-6290 @@ -138,50 +129,44 @@ func (d *dataSource) Observe(ctx context.Context, streamValues llo.StreamValues, // https://smartcontract-it.atlassian.net/browse/MERC-6290 val, err = ExtractStreamValue(trrs) if err != nil { - mu.Lock() + errmu.Lock() errs = append(errs, ErrObservationFailed{inner: err, run: run, streamID: streamID, reason: "failed to extract big.Int"}) - mu.Unlock() + errmu.Unlock() return } d.t.EnqueueV3PremiumLegacy(run, trrs, streamID, opts, val, nil) - mu.Lock() - defer mu.Unlock() - - successfulStreamIDs = append(successfulStreamIDs, streamID) if val != nil { + svmu.Lock() + defer svmu.Unlock() streamValues[streamID] = val } }(streamID) } wg.Wait() - elapsed := time.Since(now) - // Only log on errors or if VerboseLogging is turned on - if len(errs) > 0 || opts.VerboseLogging() { - slices.Sort(successfulStreamIDs) + // Failed observations are always logged at warn level + var failedStreamIDs []streams.StreamID + if len(errs) > 0 { sort.Slice(errs, func(i, j int) bool { return errs[i].streamID < errs[j].streamID }) - - failedStreamIDs := make([]streams.StreamID, len(errs)) + failedStreamIDs = make([]streams.StreamID, len(errs)) errStrs := make([]string, len(errs)) for i, e := range errs { errStrs[i] = e.String() failedStreamIDs[i] = e.streamID } + d.lggr.Warnw("Observation failed for streams", "failedStreamIDs", failedStreamIDs, "errs", errStrs, "configDigest", opts.ConfigDigest(), "seqNr", opts.OutCtx().SeqNr) + } - lggr := logger.With(d.lggr, "elapsed", elapsed, "nSuccessfulStreams", len(successfulStreamIDs), "nFailedStreams", len(failedStreamIDs), "successfulStreamIDs", successfulStreamIDs, "failedStreamIDs", failedStreamIDs, "errs", errStrs, "configDigest", opts.ConfigDigest(), "seqNr", opts.OutCtx().SeqNr) - - if opts.VerboseLogging() { - lggr = logger.With(lggr, "streamValues", streamValues) - } - - if len(errs) == 0 && opts.VerboseLogging() { - lggr.Infow("Observation succeeded for all streams") - } else if len(errs) > 0 { - lggr.Warnw("Observation failed for streams") + if opts.VerboseLogging() { + successes := make([]streams.StreamID, 0, len(streamValues)) + for strmID := range streamValues { + successes = append(successes, strmID) } + sort.Slice(successes, func(i, j int) bool { return successes[i] < successes[j] }) + d.lggr.Debugw("Observation complete", "successfulStreamIDs", successes, "failedStreamIDs", failedStreamIDs, "configDigest", opts.ConfigDigest(), "values", streamValues, "seqNr", opts.OutCtx().SeqNr) } return nil @@ -193,6 +178,9 @@ func ExtractStreamValue(trrs pipeline.TaskRunResults) (llo.StreamValue, error) { // by the pipeline executor finaltrrs := trrs.Terminals() + // TODO: Special handling for missing native/link streams? + // https://smartcontract-it.atlassian.net/browse/MERC-5949 + // HACK: Right now we rely on the number of outputs to determine whether // its a Decimal or a Quote. // This isn't very robust or future-proof but is sufficient to support v0.3 diff --git a/core/services/llo/delegate.go b/core/services/llo/delegate.go index 0c7d539427e..f5f9b5f05f1 100644 --- a/core/services/llo/delegate.go +++ b/core/services/llo/delegate.go @@ -19,9 +19,7 @@ import ( "github.com/smartcontractkit/chainlink-data-streams/llo" datastreamsllo "github.com/smartcontractkit/chainlink-data-streams/llo" - corelogger "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/job" - "github.com/smartcontractkit/chainlink/v2/core/services/ocr3/promwrapper" "github.com/smartcontractkit/chainlink/v2/core/services/streams" ) @@ -60,7 +58,6 @@ type DelegateConfig struct { ShouldRetireCache datastreamsllo.ShouldRetireCache EAMonitoringEndpoint ocrcommontypes.MonitoringEndpoint DonID uint32 - ChainID string // OCR3 TraceLogging bool @@ -69,12 +66,12 @@ type DelegateConfig struct { // One Oracle will be started for each ContractConfigTracker ContractConfigTrackers []ocr2types.ContractConfigTracker ContractTransmitter ocr3types.ContractTransmitter[llotypes.ReportInfo] + Database ocr3types.Database OCR3MonitoringEndpoint ocrcommontypes.MonitoringEndpoint OffchainConfigDigester ocr2types.OffchainConfigDigester OffchainKeyring ocr2types.OffchainKeyring OnchainKeyring ocr3types.OnchainKeyring[llotypes.ReportInfo] LocalConfig ocr2types.LocalConfig - NewOCR3DB func(pluginID int32) ocr3types.Database } func NewDelegate(cfg DelegateConfig) (job.ServiceCtx, error) { @@ -94,13 +91,7 @@ func NewDelegate(cfg DelegateConfig) (job.ServiceCtx, error) { if cfg.ShouldRetireCache == nil { return nil, errors.New("ShouldRetireCache must not be nil") } - var codecLggr logger.Logger - if cfg.ReportingPluginConfig.VerboseLogging { - codecLggr = logger.Named(lggr, "ReportCodecs") - } else { - codecLggr = corelogger.NullLogger - } - reportCodecs := NewReportCodecs(codecLggr, cfg.DonID) + reportCodecs := NewReportCodecs() var t TelemeterService if cfg.CaptureEATelemetry { @@ -135,10 +126,9 @@ func (d *delegate) Start(ctx context.Context) error { case 1: lggr = logger.With(lggr, "instanceType", "Green") } - ocrLogger := logger.NewOCRWrapper(NewSuppressedLogger(lggr, d.cfg.ReportingPluginConfig.VerboseLogging), d.cfg.TraceLogging, func(msg string) { - // NOTE: Some OCR loggers include a DB-persist here - // We do not DB persist errors in LLO, since they could be quite voluminous and ought to be present in logs anyway. - // This is a performance optimization + ocrLogger := logger.NewOCRWrapper(lggr, d.cfg.TraceLogging, func(msg string) { + // TODO: do we actually need to DB-persist errors? + // MERC-3524 }) oracle, err := ocr2plus.NewOracle(ocr2plus.OCR3OracleArgs[llotypes.ReportInfo]{ @@ -146,28 +136,15 @@ func (d *delegate) Start(ctx context.Context) error { V2Bootstrappers: d.cfg.V2Bootstrappers, ContractConfigTracker: configTracker, ContractTransmitter: d.cfg.ContractTransmitter, - Database: d.cfg.NewOCR3DB(int32(i)), // //nolint:gosec // G115 // impossible due to check on line 119 + Database: d.cfg.Database, LocalConfig: d.cfg.LocalConfig, Logger: ocrLogger, MonitoringEndpoint: d.cfg.OCR3MonitoringEndpoint, OffchainConfigDigester: d.cfg.OffchainConfigDigester, OffchainKeyring: d.cfg.OffchainKeyring, OnchainKeyring: d.cfg.OnchainKeyring, - ReportingPluginFactory: promwrapper.NewReportingPluginFactory( - datastreamsllo.NewPluginFactory( - d.cfg.ReportingPluginConfig, - psrrc, - d.src, - d.cfg.RetirementReportCodec, - d.cfg.ChannelDefinitionCache, - d.ds, - logger.Named(lggr, "ReportingPlugin"), - llo.EVMOnchainConfigCodec{}, - d.reportCodecs, - ), - lggr, - d.cfg.ChainID, - "llo", + ReportingPluginFactory: datastreamsllo.NewPluginFactory( + d.cfg.ReportingPluginConfig, psrrc, d.src, d.cfg.RetirementReportCodec, d.cfg.ChannelDefinitionCache, d.ds, logger.Named(lggr, "LLOReportingPlugin"), llo.EVMOnchainConfigCodec{}, d.reportCodecs, ), MetricsRegisterer: prometheus.WrapRegistererWith(map[string]string{"job_name": d.cfg.JobName.ValueOrZero()}, prometheus.DefaultRegisterer), }) diff --git a/core/services/llo/evm/fees_test.go b/core/services/llo/evm/fees_test.go index 33888de14ec..16ee98db7df 100644 --- a/core/services/llo/evm/fees_test.go +++ b/core/services/llo/evm/fees_test.go @@ -42,14 +42,4 @@ func Test_Fees(t *testing.T) { fee := CalculateFee(tokenPriceInUSD, BaseUSDFee) assert.Equal(t, big.NewInt(0), fee) }) - - t.Run("ridiculously high value rounds down fee to zero", func(t *testing.T) { - // 20dp - tokenPriceInUSD, err := decimal.NewFromString("12984833000000000000") - require.NoError(t, err) - BaseUSDFee, err = decimal.NewFromString("0.1") - require.NoError(t, err) - fee := CalculateFee(tokenPriceInUSD, BaseUSDFee) - assert.Equal(t, big.NewInt(0), fee) - }) } diff --git a/core/services/llo/evm/report_codec.go b/core/services/llo/evm/report_codec.go new file mode 100644 index 00000000000..b5a4ef9ffa7 --- /dev/null +++ b/core/services/llo/evm/report_codec.go @@ -0,0 +1,54 @@ +package evm + +import ( + "context" + "errors" + "fmt" + + "github.com/ethereum/go-ethereum/accounts/abi" + + llotypes "github.com/smartcontractkit/chainlink-common/pkg/types/llo" + + "github.com/smartcontractkit/chainlink-data-streams/llo" +) + +var ( + _ llo.ReportCodec = ReportCodec{} + Schema = getSchema() +) + +func getSchema() abi.Arguments { + mustNewType := func(t string) abi.Type { + result, err := abi.NewType(t, "", []abi.ArgumentMarshaling{}) + if err != nil { + panic(fmt.Sprintf("Unexpected error during abi.NewType: %s", err)) + } + return result + } + return abi.Arguments([]abi.Argument{ + {Name: "configDigest", Type: mustNewType("bytes32")}, + {Name: "chainId", Type: mustNewType("uint64")}, + // TODO: + // could also include address of verifier to make things more specific. + // downside is increased data size. + // for now we assume that a channelId will only be registered on a single + // verifier per chain. + // https://smartcontract-it.atlassian.net/browse/MERC-3652 + {Name: "seqNr", Type: mustNewType("uint64")}, + {Name: "channelId", Type: mustNewType("uint32")}, + {Name: "validAfterSeconds", Type: mustNewType("uint32")}, + {Name: "validUntilSeconds", Type: mustNewType("uint32")}, + {Name: "values", Type: mustNewType("int192[]")}, + {Name: "specimen", Type: mustNewType("bool")}, + }) +} + +type ReportCodec struct{} + +func NewReportCodec() ReportCodec { + return ReportCodec{} +} + +func (ReportCodec) Encode(ctx context.Context, report llo.Report, cd llotypes.ChannelDefinition) ([]byte, error) { + return nil, errors.New("not implemented") +} diff --git a/core/services/llo/evm/report_codec_premium_legacy.go b/core/services/llo/evm/report_codec_premium_legacy.go index fdbad6aead9..9bca9587a0e 100644 --- a/core/services/llo/evm/report_codec_premium_legacy.go +++ b/core/services/llo/evm/report_codec_premium_legacy.go @@ -5,8 +5,6 @@ import ( "encoding/json" "errors" "fmt" - "math" - "math/big" "github.com/ethereum/go-ethereum/common" "github.com/shopspring/decimal" @@ -15,12 +13,12 @@ import ( "github.com/smartcontractkit/libocr/offchainreporting2/types" ocr2types "github.com/smartcontractkit/libocr/offchainreporting2plus/types" - "github.com/smartcontractkit/chainlink-common/pkg/logger" llotypes "github.com/smartcontractkit/chainlink-common/pkg/types/llo" v3 "github.com/smartcontractkit/chainlink-common/pkg/types/mercury/v3" "github.com/smartcontractkit/chainlink-data-streams/llo" ubig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" + "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/mercury" reportcodecv3 "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/mercury/v3/reportcodec" reporttypes "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/mercury/v3/types" @@ -30,13 +28,10 @@ var ( _ llo.ReportCodec = ReportCodecPremiumLegacy{} ) -type ReportCodecPremiumLegacy struct { - logger.Logger - donID uint32 -} +type ReportCodecPremiumLegacy struct{ logger.Logger } -func NewReportCodecPremiumLegacy(lggr logger.Logger, donID uint32) ReportCodecPremiumLegacy { - return ReportCodecPremiumLegacy{logger.Sugared(lggr).Named("ReportCodecPremiumLegacy"), donID} +func NewReportCodecPremiumLegacy(lggr logger.Logger) llo.ReportCodec { + return ReportCodecPremiumLegacy{lggr.Named("ReportCodecPremiumLegacy")} } type ReportFormatEVMPremiumLegacyOpts struct { @@ -97,9 +92,6 @@ func (r ReportCodecPremiumLegacy) Encode(ctx context.Context, report llo.Report, Bid: quote.Bid.Mul(multiplier).BigInt(), Ask: quote.Ask.Mul(multiplier).BigInt(), } - - r.Logger.Debugw("Encoding report", "report", report, "opts", opts, "nativePrice", nativePrice, "linkPrice", linkPrice, "quote", quote, "multiplier", multiplier, "rf", rf) - return codec.BuildReport(ctx, rf) } @@ -122,10 +114,7 @@ func (r ReportCodecPremiumLegacy) Pack(digest types.ConfigDigest, seqNr uint64, ss = append(ss, s) vs[i] = v } - reportCtx, err := LegacyReportContext(digest, seqNr, r.donID) - if err != nil { - return nil, fmt.Errorf("failed to get legacy report context: %w", err) - } + reportCtx := LegacyReportContext(digest, seqNr) rawReportCtx := evmutil.RawReportContext(reportCtx) payload, err := mercury.PayloadTypes.Pack(rawReportCtx, []byte(report), rs, ss, vs) @@ -187,48 +176,25 @@ func extractPrice(price llo.StreamValue) (decimal.Decimal, error) { } } -const PluginVersion uint32 = 1 // the legacy mercury plugin is 0 - -// Uniquely identifies this as LLO plugin, rather than the legacy plugin (which -// uses all zeroes). -// -// This is quite a hack but serves the purpose of uniquely identifying -// dons/plugin versions to the mercury server without having to modify any -// existing tooling or breaking backwards compatibility. It should be safe -// since the DonID is encoded into the config digest anyway so report context -// is already dependent on it, and all LLO jobs in the same don are expected to -// have the same don ID set. -// -// Packs donID+pluginVersion as (uint32, uint32), for example donID=2, -// PluginVersion=1 Yields: -// 0x0000000000000000000000000000000000000000000000000000000200000001 -func LLOExtraHash(donID uint32) common.Hash { - combined := uint64(donID)<<32 | uint64(PluginVersion) - return common.BigToHash(new(big.Int).SetUint64(combined)) -} +// TODO: Consider embedding the DON ID here? +// MERC-3524 +var LLOExtraHash = common.HexToHash("0x0000000000000000000000000000000000000000000000000000000000000001") -func SeqNrToEpochAndRound(seqNr uint64) (epoch uint32, round uint8, err error) { +func SeqNrToEpochAndRound(seqNr uint64) (epoch uint32, round uint8) { // Simulate 256 rounds/epoch - if seqNr/256 > math.MaxUint32 { - err = fmt.Errorf("epoch overflows uint32: %d", seqNr) - return - } - epoch = uint32(seqNr / 256) //nolint:gosec // G115 false positive - round = uint8(seqNr % 256) //nolint:gosec // G115 false positive + epoch = uint32(seqNr / 256) // nolint + round = uint8(seqNr % 256) // nolint return } -func LegacyReportContext(cd ocr2types.ConfigDigest, seqNr uint64, donID uint32) (ocr2types.ReportContext, error) { - epoch, round, err := SeqNrToEpochAndRound(seqNr) - if err != nil { - return ocr2types.ReportContext{}, err - } +func LegacyReportContext(cd ocr2types.ConfigDigest, seqNr uint64) ocr2types.ReportContext { + epoch, round := SeqNrToEpochAndRound(seqNr) return ocr2types.ReportContext{ ReportTimestamp: ocr2types.ReportTimestamp{ ConfigDigest: cd, - Epoch: epoch, - Round: round, + Epoch: uint32(epoch), + Round: uint8(round), }, - ExtraHash: LLOExtraHash(donID), // ExtraHash is always zero for mercury, we use LLOExtraHash here to differentiate from the legacy plugin - }, nil + ExtraHash: LLOExtraHash, // ExtraHash is always zero for mercury, we use LLOExtraHash here to differentiate from the legacy plugin + } } diff --git a/core/services/llo/evm/report_codec_premium_legacy_test.go b/core/services/llo/evm/report_codec_premium_legacy_test.go index a88626e6c57..804555d06be 100644 --- a/core/services/llo/evm/report_codec_premium_legacy_test.go +++ b/core/services/llo/evm/report_codec_premium_legacy_test.go @@ -12,7 +12,6 @@ import ( "github.com/smartcontractkit/libocr/offchainreporting2plus/types" "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" - "github.com/smartcontractkit/chainlink/v2/core/logger" reporttypes "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/mercury/v3/types" llotypes "github.com/smartcontractkit/chainlink-common/pkg/types/llo" @@ -20,28 +19,6 @@ import ( "github.com/smartcontractkit/chainlink-data-streams/llo" ) -func FuzzReportCodecPremiumLegacy_Decode(f *testing.F) { - f.Add([]byte("not a protobuf")) - f.Add([]byte{0x0a, 0x00}) // empty protobuf - f.Add([]byte{0x0a, 0x02, 0x08, 0x01}) // invalid protobuf - f.Add(([]byte)(nil)) - f.Add([]byte{}) - - validReport := newValidPremiumLegacyReport() - feedID := [32]uint8{0x1, 0x2, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0} - cd := llotypes.ChannelDefinition{Opts: llotypes.ChannelOpts(fmt.Sprintf(`{"baseUSDFee":"10.50","expirationWindow":60,"feedId":"0x%x","multiplier":10}`, feedID))} - - codec := ReportCodecPremiumLegacy{logger.NullLogger, 100002} - - validEncodedReport, err := codec.Encode(tests.Context(f), validReport, cd) - require.NoError(f, err) - f.Add(validEncodedReport) - - f.Fuzz(func(t *testing.T, data []byte) { - codec.Decode(data) //nolint:errcheck // test that it doesn't panic, don't care about errors - }) -} - func newValidPremiumLegacyReport() llo.Report { return llo.Report{ ConfigDigest: types.ConfigDigest{1, 2, 3}, @@ -55,7 +32,7 @@ func newValidPremiumLegacyReport() llo.Report { } func Test_ReportCodecPremiumLegacy(t *testing.T) { - rc := ReportCodecPremiumLegacy{logger.TestLogger(t), 2} + rc := ReportCodecPremiumLegacy{} feedID := [32]uint8{0x1, 0x2, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0} cd := llotypes.ChannelDefinition{Opts: llotypes.ChannelOpts(fmt.Sprintf(`{"baseUSDFee":"10.50","expirationWindow":60,"feedId":"0x%x","multiplier":10}`, feedID))} @@ -247,9 +224,3 @@ func Test_ExtractReportValues(t *testing.T) { assert.Equal(t, &llo.Quote{Bid: decimal.NewFromInt(37), Benchmark: decimal.NewFromInt(38), Ask: decimal.NewFromInt(39)}, quote) }) } - -func Test_LLOExtraHash(t *testing.T) { - donID := uint32(8) - extraHash := LLOExtraHash(donID) - assert.Equal(t, "0x0000000000000000000000000000000000000000000000000000000800000001", extraHash.String()) -} diff --git a/core/services/llo/keyring.go b/core/services/llo/keyring.go index d4bf615711c..8137a5ac3da 100644 --- a/core/services/llo/keyring.go +++ b/core/services/llo/keyring.go @@ -33,14 +33,13 @@ type Key interface { } type onchainKeyring struct { - lggr logger.Logger - keys map[llotypes.ReportFormat]Key - donID uint32 + lggr logger.Logger + keys map[llotypes.ReportFormat]Key } -func NewOnchainKeyring(lggr logger.Logger, keys map[llotypes.ReportFormat]Key, donID uint32) LLOOnchainKeyring { +func NewOnchainKeyring(lggr logger.Logger, keys map[llotypes.ReportFormat]Key) LLOOnchainKeyring { return &onchainKeyring{ - lggr.Named("OnchainKeyring"), keys, donID, + lggr.Named("OnchainKeyring"), keys, } } @@ -84,10 +83,7 @@ func (okr *onchainKeyring) Sign(digest types.ConfigDigest, seqNr uint64, r ocr3t rf := r.Info.ReportFormat if key, exists := okr.keys[rf]; exists { // NOTE: Must use legacy Sign method for compatibility with v0.3 report verification - rc, err := evm.LegacyReportContext(digest, seqNr, okr.donID) - if err != nil { - return nil, fmt.Errorf("failed to get legacy report context: %w", err) - } + rc := evm.LegacyReportContext(digest, seqNr) return key.Sign(rc, r.Report) } default: @@ -105,11 +101,7 @@ func (okr *onchainKeyring) Verify(key types.OnchainPublicKey, digest types.Confi rf := r.Info.ReportFormat if verifier, exists := okr.keys[rf]; exists { // NOTE: Must use legacy Verify method for compatibility with v0.3 report verification - rc, err := evm.LegacyReportContext(digest, seqNr, okr.donID) - if err != nil { - okr.lggr.Errorw("Verify failed; unable to get legacy report context", "err", err) - return false - } + rc := evm.LegacyReportContext(digest, seqNr) return verifier.Verify(key, rc, r.Report, signature) } default: diff --git a/core/services/llo/keyring_test.go b/core/services/llo/keyring_test.go index b50e8d169c0..44371e14967 100644 --- a/core/services/llo/keyring_test.go +++ b/core/services/llo/keyring_test.go @@ -2,14 +2,13 @@ package llo import ( "fmt" - "math" - "math/rand/v2" + "math/rand" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "github.com/smartcontractkit/libocr/offchainreporting2plus/ocr3types" + ocr3types "github.com/smartcontractkit/libocr/offchainreporting2plus/ocr3types" "github.com/smartcontractkit/libocr/offchainreporting2plus/types" ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types" @@ -69,7 +68,7 @@ func Test_Keyring(t *testing.T) { llotypes.ReportFormatJSON: &mockKey{format: llotypes.ReportFormatJSON, maxSignatureLen: 2, sig: []byte("sig-2")}, } - kr := NewOnchainKeyring(lggr, ks, 2) + kr := NewOnchainKeyring(lggr, ks) cases := []struct { format llotypes.ReportFormat @@ -84,7 +83,7 @@ func Test_Keyring(t *testing.T) { cd, err := ocrtypes.BytesToConfigDigest(testutils.MustRandBytes(32)) require.NoError(t, err) - seqNr := rand.Uint64N(math.MaxUint32 << 8) + seqNr := rand.Uint64() t.Run("Sign+Verify", func(t *testing.T) { for _, tc := range cases { t.Run(tc.format.String(), func(t *testing.T) { diff --git a/core/services/llo/mercurytransmitter/orm.go b/core/services/llo/mercurytransmitter/orm.go index f557e2293a5..ed8c8843f4c 100644 --- a/core/services/llo/mercurytransmitter/orm.go +++ b/core/services/llo/mercurytransmitter/orm.go @@ -72,7 +72,7 @@ func (o *orm) Insert(ctx context.Context, transmissions []*Transmission) error { DonID: o.donID, ServerURL: t.ServerURL, ConfigDigest: t.ConfigDigest, - SeqNr: int64(t.SeqNr), + SeqNr: int64(t.SeqNr), //nolint Report: t.Report.Report, LifecycleStage: string(t.Report.Info.LifeCycleStage), ReportFormat: uint32(t.Report.Info.ReportFormat), @@ -162,7 +162,7 @@ func (o *orm) Get(ctx context.Context, serverURL string) ([]*Transmission, error } transmission.Sigs = append(transmission.Sigs, ocrtypes.AttributedOnchainSignature{ Signature: sig, - Signer: commontypes.OracleID(signers[i]), //nolint:gosec // G115 false positive + Signer: commontypes.OracleID(signers[i]), //nolint }) } diff --git a/core/services/llo/mercurytransmitter/queue.go b/core/services/llo/mercurytransmitter/queue.go index 6610010a469..a5a606c5b32 100644 --- a/core/services/llo/mercurytransmitter/queue.go +++ b/core/services/llo/mercurytransmitter/queue.go @@ -4,7 +4,6 @@ import ( "context" "errors" "fmt" - "strconv" "sync" "time" @@ -23,11 +22,9 @@ type asyncDeleter interface { var _ services.Service = (*transmitQueue)(nil) -var promTransmitQueueLoad = promauto.NewGaugeVec(prometheus.GaugeOpts{ - Namespace: "llo", - Subsystem: "mercurytransmitter", - Name: "transmit_queue_load", - Help: "Current count of items in the transmit queue", +var transmitQueueLoad = promauto.NewGaugeVec(prometheus.GaugeOpts{ + Name: "llo_transmit_queue_load", + Help: "Current count of items in the transmit queue", }, []string{"donID", "serverURL", "capacity"}, ) @@ -78,7 +75,7 @@ func NewTransmitQueue(lggr logger.Logger, serverURL string, maxlen int, asyncDel maxlen, false, nil, - promTransmitQueueLoad.WithLabelValues(strconv.FormatUint(uint64(asyncDeleter.DonID()), 10), serverURL, strconv.FormatInt(int64(maxlen), 10)), + transmitQueueLoad.WithLabelValues(fmt.Sprintf("%d", asyncDeleter.DonID()), serverURL, fmt.Sprintf("%d", maxlen)), } } @@ -98,8 +95,8 @@ func (tq *transmitQueue) Push(t *Transmission) (ok bool) { if tq.maxlen != 0 && tq.pq.Len() == tq.maxlen { // evict oldest entry to make room + tq.lggr.Criticalf("Transmit queue is full; dropping oldest transmission (reached max length of %d)", tq.maxlen) removed := heap.PopMax(tq.pq) - tq.lggr.Criticalw(fmt.Sprintf("Transmit queue is full; dropping oldest transmission (reached max length of %d)", tq.maxlen), "transmission", removed) if removed, ok := removed.(*Transmission); ok { tq.asyncDeleter.AsyncDelete(removed.Hash()) } diff --git a/core/services/llo/mercurytransmitter/server.go b/core/services/llo/mercurytransmitter/server.go index 3ce2b0a4b4a..70e76655961 100644 --- a/core/services/llo/mercurytransmitter/server.go +++ b/core/services/llo/mercurytransmitter/server.go @@ -3,26 +3,19 @@ package mercurytransmitter import ( "context" "fmt" - "strconv" "sync" - "sync/atomic" "time" "github.com/jpillora/backoff" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/promauto" - "github.com/smartcontractkit/libocr/offchainreporting2plus/types" - - ocr2types "github.com/smartcontractkit/libocr/offchainreporting2plus/types" - commonconfig "github.com/smartcontractkit/chainlink-common/pkg/config" "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink-common/pkg/services" llotypes "github.com/smartcontractkit/chainlink-common/pkg/types/llo" "github.com/smartcontractkit/chainlink-data-streams/llo" - corelogger "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/llo/evm" "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/mercury/wsrpc" "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/mercury/wsrpc/pb" @@ -30,65 +23,36 @@ import ( ) var ( - promTransmitQueueDeleteErrorCount = promauto.NewCounterVec(prometheus.CounterOpts{ - Namespace: "llo", - Subsystem: "mercurytransmitter", - Name: "transmit_queue_delete_error_count", - Help: "Running count of DB errors when trying to delete an item from the queue DB", + transmitQueueDeleteErrorCount = promauto.NewCounterVec(prometheus.CounterOpts{ + Name: "llo_mercury_transmit_queue_delete_error_count", + Help: "Running count of DB errors when trying to delete an item from the queue DB", }, []string{"donID", "serverURL"}, ) - promTransmitQueueInsertErrorCount = promauto.NewCounterVec(prometheus.CounterOpts{ - Namespace: "llo", - Subsystem: "mercurytransmitter", - Name: "transmit_queue_insert_error_count", - Help: "Running count of DB errors when trying to insert an item into the queue DB", + transmitQueueInsertErrorCount = promauto.NewCounterVec(prometheus.CounterOpts{ + Name: "llo_mercury_transmit_queue_insert_error_count", + Help: "Running count of DB errors when trying to insert an item into the queue DB", }, []string{"donID", "serverURL"}, ) - promTransmitQueuePushErrorCount = promauto.NewCounterVec(prometheus.CounterOpts{ - Namespace: "llo", - Subsystem: "mercurytransmitter", - Name: "transmit_queue_push_error_count", - Help: "Running count of DB errors when trying to push an item onto the queue", + transmitQueuePushErrorCount = promauto.NewCounterVec(prometheus.CounterOpts{ + Name: "llo_mercury_transmit_queue_push_error_count", + Help: "Running count of DB errors when trying to push an item onto the queue", }, []string{"donID", "serverURL"}, ) - promTransmitServerErrorCount = promauto.NewCounterVec(prometheus.CounterOpts{ - Namespace: "llo", - Subsystem: "mercurytransmitter", - Name: "transmit_server_error_count", - Help: "Number of errored transmissions that failed due to an error returned by the mercury server", + transmitServerErrorCount = promauto.NewCounterVec(prometheus.CounterOpts{ + Name: "llo_mercury_transmit_server_error_count", + Help: "Number of errored transmissions that failed due to an error returned by the mercury server", }, []string{"donID", "serverURL", "code"}, ) - promTransmitConcurrentTransmitGauge = promauto.NewGaugeVec(prometheus.GaugeOpts{ - Namespace: "llo", - Subsystem: "mercurytransmitter", - Name: "concurrent_transmit_gauge", - Help: "Gauge that measures the number of transmit threads currently waiting on a remote transmit call. You may wish to alert if this exceeds some number for a given period of time, or if it ever reaches its max.", - }, - []string{"donID", "serverURL"}, - ) - promTransmitConcurrentDeleteGauge = prometheus.NewGaugeVec(prometheus.GaugeOpts{ - Namespace: "llo", - Subsystem: "mercurytransmitter", - Name: "concurrent_delete_gauge", - Help: "Gauge that measures the number of delete threads currently waiting on a delete call to the DB. You may wish to alert if this exceeds some number for a given period of time, or if it ever reaches its max.", - }, - []string{"donID", "serverURL"}, - ) ) -type ReportPacker interface { - Pack(digest types.ConfigDigest, seqNr uint64, report ocr2types.Report, sigs []ocr2types.AttributedOnchainSignature) ([]byte, error) -} - // A server handles the queue for a given mercury server type server struct { - lggr logger.SugaredLogger - verboseLogging bool + lggr logger.SugaredLogger transmitTimeout time.Duration @@ -100,20 +64,12 @@ type server struct { url string - evmPremiumLegacyPacker ReportPacker - jsonPacker ReportPacker - - transmitSuccessCount prometheus.Counter - transmitDuplicateCount prometheus.Counter - transmitConnectionErrorCount prometheus.Counter - transmitQueueDeleteErrorCount prometheus.Counter - transmitQueueInsertErrorCount prometheus.Counter - transmitQueuePushErrorCount prometheus.Counter - transmitConcurrentTransmitGauge prometheus.Gauge - transmitConcurrentDeleteGauge prometheus.Gauge - - transmitThreadBusyCount atomic.Int32 - deleteThreadBusyCount atomic.Int32 + transmitSuccessCount prometheus.Counter + transmitDuplicateCount prometheus.Counter + transmitConnectionErrorCount prometheus.Counter + transmitQueueDeleteErrorCount prometheus.Counter + transmitQueueInsertErrorCount prometheus.Counter + transmitQueuePushErrorCount prometheus.Counter } type QueueConfig interface { @@ -121,40 +77,24 @@ type QueueConfig interface { TransmitTimeout() commonconfig.Duration } -func newServer(lggr logger.Logger, verboseLogging bool, cfg QueueConfig, client wsrpc.Client, orm ORM, serverURL string) *server { +func newServer(lggr logger.Logger, cfg QueueConfig, client wsrpc.Client, orm ORM, serverURL string) *server { pm := NewPersistenceManager(lggr, orm, serverURL, int(cfg.TransmitQueueMaxSize()), flushDeletesFrequency, pruneFrequency) donIDStr := fmt.Sprintf("%d", pm.DonID()) - var codecLggr logger.Logger - if verboseLogging { - codecLggr = lggr - } else { - codecLggr = corelogger.NullLogger - } - - s := &server{ + return &server{ logger.Sugared(lggr), - verboseLogging, cfg.TransmitTimeout().Duration(), client, pm, NewTransmitQueue(lggr, serverURL, int(cfg.TransmitQueueMaxSize()), pm), make(chan [32]byte, int(cfg.TransmitQueueMaxSize())), serverURL, - evm.NewReportCodecPremiumLegacy(codecLggr, pm.DonID()), - llo.JSONReportCodec{}, - promTransmitSuccessCount.WithLabelValues(donIDStr, serverURL), - promTransmitDuplicateCount.WithLabelValues(donIDStr, serverURL), - promTransmitConnectionErrorCount.WithLabelValues(donIDStr, serverURL), - promTransmitQueueDeleteErrorCount.WithLabelValues(donIDStr, serverURL), - promTransmitQueueInsertErrorCount.WithLabelValues(donIDStr, serverURL), - promTransmitQueuePushErrorCount.WithLabelValues(donIDStr, serverURL), - promTransmitConcurrentTransmitGauge.WithLabelValues(donIDStr, serverURL), - promTransmitConcurrentDeleteGauge.WithLabelValues(donIDStr, serverURL), - atomic.Int32{}, - atomic.Int32{}, + transmitSuccessCount.WithLabelValues(donIDStr, serverURL), + transmitDuplicateCount.WithLabelValues(donIDStr, serverURL), + transmitConnectionErrorCount.WithLabelValues(donIDStr, serverURL), + transmitQueueDeleteErrorCount.WithLabelValues(donIDStr, serverURL), + transmitQueueInsertErrorCount.WithLabelValues(donIDStr, serverURL), + transmitQueuePushErrorCount.WithLabelValues(donIDStr, serverURL), } - - return s } func (s *server) HealthReport() map[string]error { @@ -181,7 +121,6 @@ func (s *server) runDeleteQueueLoop(stopCh services.StopChan, wg *sync.WaitGroup select { case hash := <-s.deleteQueue: for { - s.deleteThreadBusyCountInc() if err := s.pm.orm.Delete(ctx, [][32]byte{hash}); err != nil { s.lggr.Errorw("Failed to delete transmission record", "err", err, "transmissionHash", hash) s.transmitQueueDeleteErrorCount.Inc() @@ -190,7 +129,6 @@ func (s *server) runDeleteQueueLoop(stopCh services.StopChan, wg *sync.WaitGroup // Wait a backoff duration before trying to delete again continue case <-stopCh: - s.deleteThreadBusyCountDec() // abort and return immediately on stop even if items remain in queue return } @@ -199,7 +137,6 @@ func (s *server) runDeleteQueueLoop(stopCh services.StopChan, wg *sync.WaitGroup } // success b.Reset() - s.deleteThreadBusyCountDec() case <-stopCh: // abort and return immediately on stop even if items remain in queue return @@ -207,23 +144,6 @@ func (s *server) runDeleteQueueLoop(stopCh services.StopChan, wg *sync.WaitGroup } } -func (s *server) transmitThreadBusyCountInc() { - val := s.transmitThreadBusyCount.Add(1) - s.transmitConcurrentTransmitGauge.Set(float64(val)) -} -func (s *server) transmitThreadBusyCountDec() { - val := s.transmitThreadBusyCount.Add(-1) - s.transmitConcurrentTransmitGauge.Set(float64(val)) -} -func (s *server) deleteThreadBusyCountInc() { - val := s.deleteThreadBusyCount.Add(1) - s.transmitConcurrentDeleteGauge.Set(float64(val)) -} -func (s *server) deleteThreadBusyCountDec() { - val := s.deleteThreadBusyCount.Add(-1) - s.transmitConcurrentDeleteGauge.Set(float64(val)) -} - func (s *server) runQueueLoop(stopCh services.StopChan, wg *sync.WaitGroup, donIDStr string) { defer wg.Done() // Exponential backoff with very short retry interval (since latency is a priority) @@ -236,87 +156,79 @@ func (s *server) runQueueLoop(stopCh services.StopChan, wg *sync.WaitGroup, donI } ctx, cancel := stopCh.NewCtx() defer cancel() - cont := true - for cont { - cont = func() bool { - t := s.q.BlockingPop() - if t == nil { - // queue was closed - return false + for { + t := s.q.BlockingPop() + if t == nil { + // queue was closed + return + } + res, err := func(ctx context.Context) (*pb.TransmitResponse, error) { + ctx, cancelFn := context.WithTimeout(ctx, utils.WithJitter(s.transmitTimeout)) + defer cancelFn() + return s.transmit(ctx, t) + }(ctx) + if ctx.Err() != nil { + // only canceled on transmitter close so we can exit + return + } else if err != nil { + s.transmitConnectionErrorCount.Inc() + s.lggr.Errorw("Transmit report failed", "err", err, "transmission", t) + if ok := s.q.Push(t); !ok { + s.lggr.Error("Failed to push report to transmit queue; queue is closed") + return } - - s.transmitThreadBusyCountInc() - defer s.transmitThreadBusyCountDec() - - req, res, err := func(ctx context.Context) (*pb.TransmitRequest, *pb.TransmitResponse, error) { - ctx, cancelFn := context.WithTimeout(ctx, utils.WithJitter(s.transmitTimeout)) - defer cancelFn() - return s.transmit(ctx, t) - }(ctx) - if ctx.Err() != nil { - // only canceled on transmitter close so we can exit - return false - } else if err != nil { - s.transmitConnectionErrorCount.Inc() - s.lggr.Errorw("Transmit report failed", "err", err, "req.Payload", req.Payload, "req.ReportFormat", req.ReportFormat, "transmission", t) - if ok := s.q.Push(t); !ok { - s.lggr.Error("Failed to push report to transmit queue; queue is closed") - return false - } - // Wait a backoff duration before pulling the most recent transmission - // the heap - select { - case <-time.After(b.Duration()): - return true - case <-stopCh: - return false - } + // Wait a backoff duration before pulling the most recent transmission + // the heap + select { + case <-time.After(b.Duration()): + continue + case <-stopCh: + return } + } - b.Reset() - if res.Error == "" { + b.Reset() + if res.Error == "" { + s.transmitSuccessCount.Inc() + s.lggr.Debugw("Transmit report success", "transmission", t, "response", res) + } else { + // We don't need to retry here because the mercury server + // has confirmed it received the report. We only need to retry + // on networking/unknown errors + switch res.Code { + case DuplicateReport: s.transmitSuccessCount.Inc() - s.lggr.Debugw("Transmit report success", "req.ReportFormat", req.ReportFormat, "req.Payload", req.Payload, "transmission", t, "response", res) - } else { - // We don't need to retry here because the mercury server - // has confirmed it received the report. We only need to retry - // on networking/unknown errors - switch res.Code { - case DuplicateReport: - s.transmitSuccessCount.Inc() - s.transmitDuplicateCount.Inc() - s.lggr.Debugw("Transmit report success; duplicate report", "req.ReportFormat", req.ReportFormat, "req.Payload", req.Payload, "transmission", t, "response", res) - default: - promTransmitServerErrorCount.WithLabelValues(donIDStr, s.url, strconv.FormatInt(int64(res.Code), 10)).Inc() - s.lggr.Errorw("Transmit report failed; mercury server returned error", "req.ReportFormat", req.ReportFormat, "req.Payload", req.Payload, "response", res, "transmission", t, "err", res.Error, "code", res.Code) - } - } - - select { - case s.deleteQueue <- t.Hash(): + s.transmitDuplicateCount.Inc() + s.lggr.Debugw("Transmit report success; duplicate report", "transmission", t, "response", res) default: - s.lggr.Criticalw("Delete queue is full", "transmission", t, "transmissionHash", fmt.Sprintf("%x", t.Hash())) + transmitServerErrorCount.WithLabelValues(donIDStr, s.url, fmt.Sprintf("%d", res.Code)).Inc() + s.lggr.Errorw("Transmit report failed; mercury server returned error", "response", res, "transmission", t, "err", res.Error, "code", res.Code) } - return true - }() + } + + select { + case s.deleteQueue <- t.Hash(): + default: + s.lggr.Criticalw("Delete queue is full", "transmission", t) + } } } -func (s *server) transmit(ctx context.Context, t *Transmission) (*pb.TransmitRequest, *pb.TransmitResponse, error) { +func (s *server) transmit(ctx context.Context, t *Transmission) (*pb.TransmitResponse, error) { var payload []byte var err error switch t.Report.Info.ReportFormat { case llotypes.ReportFormatJSON: - payload, err = s.jsonPacker.Pack(t.ConfigDigest, t.SeqNr, t.Report.Report, t.Sigs) + payload, err = llo.JSONReportCodec{}.Pack(t.ConfigDigest, t.SeqNr, t.Report.Report, t.Sigs) case llotypes.ReportFormatEVMPremiumLegacy: - payload, err = s.evmPremiumLegacyPacker.Pack(t.ConfigDigest, t.SeqNr, t.Report.Report, t.Sigs) + payload, err = evm.ReportCodecPremiumLegacy{}.Pack(t.ConfigDigest, t.SeqNr, t.Report.Report, t.Sigs) default: - return nil, nil, fmt.Errorf("Transmit failed; don't know how to Pack unsupported report format: %q", t.Report.Info.ReportFormat) + return nil, fmt.Errorf("Transmit failed; unsupported report format: %q", t.Report.Info.ReportFormat) } if err != nil { - return nil, nil, fmt.Errorf("Transmit: encode failed; %w", err) + return nil, fmt.Errorf("Transmit: encode failed; %w", err) } req := &pb.TransmitRequest{ @@ -324,6 +236,5 @@ func (s *server) transmit(ctx context.Context, t *Transmission) (*pb.TransmitReq ReportFormat: uint32(t.Report.Info.ReportFormat), } - resp, err := s.c.Transmit(ctx, req) - return req, resp, err + return s.c.Transmit(ctx, req) } diff --git a/core/services/llo/mercurytransmitter/transmitter.go b/core/services/llo/mercurytransmitter/transmitter.go index 23aa4b79e58..33090ed9574 100644 --- a/core/services/llo/mercurytransmitter/transmitter.go +++ b/core/services/llo/mercurytransmitter/transmitter.go @@ -8,7 +8,6 @@ import ( "errors" "fmt" "io" - "strconv" "sync" "github.com/prometheus/client_golang/prometheus" @@ -33,27 +32,21 @@ const ( ) var ( - promTransmitSuccessCount = promauto.NewCounterVec(prometheus.CounterOpts{ - Namespace: "llo", - Subsystem: "mercurytransmitter", - Name: "transmit_success_count", - Help: "Number of successful transmissions (duplicates are counted as success)", + transmitSuccessCount = promauto.NewCounterVec(prometheus.CounterOpts{ + Name: "llo_mercury_transmit_success_count", + Help: "Number of successful transmissions (duplicates are counted as success)", }, []string{"donID", "serverURL"}, ) - promTransmitDuplicateCount = promauto.NewCounterVec(prometheus.CounterOpts{ - Namespace: "llo", - Subsystem: "mercurytransmitter", - Name: "transmit_duplicate_count", - Help: "Number of transmissions where the server told us it was a duplicate", + transmitDuplicateCount = promauto.NewCounterVec(prometheus.CounterOpts{ + Name: "llo_mercury_transmit_duplicate_count", + Help: "Number of transmissions where the server told us it was a duplicate", }, []string{"donID", "serverURL"}, ) - promTransmitConnectionErrorCount = promauto.NewCounterVec(prometheus.CounterOpts{ - Namespace: "llo", - Subsystem: "mercurytransmitter", - Name: "transmit_connection_error_count", - Help: "Number of errored transmissions that failed due to problem with the connection", + transmitConnectionErrorCount = promauto.NewCounterVec(prometheus.CounterOpts{ + Name: "llo_mercury_transmit_connection_error_count", + Help: "Number of errored transmissions that failed due to problem with the connection", }, []string{"donID", "serverURL"}, ) @@ -104,18 +97,15 @@ var _ Transmitter = (*transmitter)(nil) type Config interface { TransmitQueueMaxSize() uint32 TransmitTimeout() commonconfig.Duration - TransmitConcurrency() uint32 } type transmitter struct { services.StateMachine - lggr logger.SugaredLogger - verboseLogging bool - cfg Config + lggr logger.SugaredLogger + cfg Config - orm ORM - servers map[string]*server - registerer prometheus.Registerer + orm ORM + servers map[string]*server donID uint32 fromAccount string @@ -125,14 +115,12 @@ type transmitter struct { } type Opts struct { - Lggr logger.Logger - Registerer prometheus.Registerer - VerboseLogging bool - Cfg Config - Clients map[string]wsrpc.Client - FromAccount ed25519.PublicKey - DonID uint32 - ORM ORM + Lggr logger.Logger + Cfg Config + Clients map[string]wsrpc.Client + FromAccount ed25519.PublicKey + DonID uint32 + ORM ORM } func New(opts Opts) Transmitter { @@ -144,16 +132,14 @@ func newTransmitter(opts Opts) *transmitter { servers := make(map[string]*server, len(opts.Clients)) for serverURL, client := range opts.Clients { sLggr := sugared.Named(serverURL).With("serverURL", serverURL) - servers[serverURL] = newServer(sLggr, opts.VerboseLogging, opts.Cfg, client, opts.ORM, serverURL) + servers[serverURL] = newServer(sLggr, opts.Cfg, client, opts.ORM, serverURL) } return &transmitter{ services.StateMachine{}, sugared.Named("LLOMercuryTransmitter").With("donID", opts.ORM.DonID()), - opts.VerboseLogging, opts.Cfg, opts.ORM, servers, - opts.Registerer, opts.DonID, fmt.Sprintf("%x", opts.FromAccount), make(services.StopChan), @@ -163,9 +149,7 @@ func newTransmitter(opts Opts) *transmitter { func (mt *transmitter) Start(ctx context.Context) (err error) { return mt.StartOnce("LLOMercuryTransmitter", func() error { - if mt.verboseLogging { - mt.lggr.Debugw("Loading transmit requests from database") - } + mt.lggr.Debugw("Loading transmit requests from database") { var startClosers []services.StartClose @@ -175,23 +159,12 @@ func (mt *transmitter) Start(ctx context.Context) (err error) { return err } s.q.Init(transmissions) - // starting pm after loading from it is fine because it simply - // spawns some garbage collection/prune goroutines + // starting pm after loading from it is fine because it simply spawns some garbage collection/prune goroutines startClosers = append(startClosers, s.c, s.q, s.pm) - // Number of goroutines per server will be roughly - // 2*nServers*TransmitConcurrency because each server has a - // delete queue and a transmit queue. - // - // This could potentially be reduced by implementing transmit batching, - // see: https://smartcontract-it.atlassian.net/browse/MERC-6635 - nThreads := int(mt.cfg.TransmitConcurrency()) - mt.wg.Add(2 * nThreads) - donIDStr := strconv.FormatUint(uint64(mt.donID), 10) - for i := 0; i < nThreads; i++ { - go s.runDeleteQueueLoop(mt.stopCh, mt.wg) - go s.runQueueLoop(mt.stopCh, mt.wg, donIDStr) - } + mt.wg.Add(2) + go s.runDeleteQueueLoop(mt.stopCh, mt.wg) + go s.runQueueLoop(mt.stopCh, mt.wg, fmt.Sprintf("%d", mt.donID)) } if err := (&services.MultiStart{}).Start(ctx, startClosers...); err != nil { return err @@ -261,9 +234,7 @@ func (mt *transmitter) Transmit( g := new(errgroup.Group) for i := range transmissions { t := transmissions[i] - if mt.verboseLogging { - mt.lggr.Debugw("LLOMercuryTransmit", "digest", digest.Hex(), "seqNr", seqNr, "reportFormat", report.Info.ReportFormat, "reportLifeCycleStage", report.Info.LifeCycleStage, "transmissionHash", fmt.Sprintf("%x", t.Hash())) - } + mt.lggr.Debugw("LLOMercuryTransmit", "digest", digest.Hex(), "seqNr", seqNr, "reportFormat", report.Info.ReportFormat, "reportLifeCycleStage", report.Info.LifeCycleStage, "transmissionHash", fmt.Sprintf("%x", t.Hash())) g.Go(func() error { s := mt.servers[t.ServerURL] if ok := s.q.Push(t); !ok { diff --git a/core/services/llo/mercurytransmitter/transmitter_test.go b/core/services/llo/mercurytransmitter/transmitter_test.go index fabc9bb0d0e..db3d0d2e584 100644 --- a/core/services/llo/mercurytransmitter/transmitter_test.go +++ b/core/services/llo/mercurytransmitter/transmitter_test.go @@ -33,10 +33,6 @@ func (m mockCfg) TransmitTimeout() commonconfig.Duration { return *commonconfig.MustNewDuration(1 * time.Hour) } -func (m mockCfg) TransmitConcurrency() uint32 { - return 5 -} - func Test_Transmitter_Transmit(t *testing.T) { lggr := logger.TestLogger(t) db := pgtest.NewSqlxDB(t) @@ -139,7 +135,7 @@ func Test_Transmitter_runQueueLoop(t *testing.T) { orm := NewORM(db, donID) cfg := mockCfg{} - s := newServer(lggr, true, cfg, c, orm, sURL) + s := newServer(lggr, cfg, c, orm, sURL) t.Run("pulls from queue and transmits successfully", func(t *testing.T) { transmit := make(chan *pb.TransmitRequest, 1) @@ -159,7 +155,7 @@ func Test_Transmitter_runQueueLoop(t *testing.T) { select { case tr := <-transmit: - assert.Equal(t, []byte{0x0, 0x9, 0x57, 0xdd, 0x2f, 0x63, 0x56, 0x69, 0x34, 0xfd, 0xc2, 0xe1, 0xcd, 0xc1, 0xe, 0x3e, 0x25, 0xb9, 0x26, 0x5a, 0x16, 0x23, 0x91, 0xa6, 0x53, 0x16, 0x66, 0x59, 0x51, 0x0, 0x28, 0x7c, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0xe2, 0x40, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xe0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0x80, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x20, 0x0, 0x3, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x66, 0xde, 0xf5, 0xba, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x66, 0xde, 0xf5, 0xba, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1e, 0x8e, 0x95, 0xcf, 0xb5, 0xd8, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1a, 0xd0, 0x1c, 0x67, 0xa9, 0xcf, 0xb3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x66, 0xdf, 0x3, 0xca, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1b, 0x1c, 0x93, 0x6d, 0xa4, 0xf2, 0x17, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1b, 0x14, 0x8d, 0x9a, 0xc1, 0xd9, 0x6f, 0xc0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1b, 0x40, 0x5c, 0xcf, 0xa1, 0xbc, 0x63, 0xc0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0x9d, 0xab, 0x8f, 0xa7, 0xca, 0x7, 0x62, 0x57, 0xf7, 0x11, 0x2c, 0xb7, 0xf3, 0x49, 0x37, 0x12, 0xbd, 0xe, 0x14, 0x27, 0xfc, 0x32, 0x5c, 0xec, 0xa6, 0xb9, 0x7f, 0xf9, 0xd7, 0x7b, 0xa6, 0x36, 0x9a, 0x47, 0x4a, 0x3, 0x1a, 0x95, 0xcf, 0x46, 0x10, 0xaf, 0xcc, 0x90, 0x49, 0xb2, 0xce, 0xbf, 0x63, 0xaa, 0xc7, 0x25, 0x4d, 0x2a, 0x8, 0x36, 0xda, 0xd5, 0x9f, 0x9d, 0x63, 0x69, 0x22, 0xb3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0x30, 0x9d, 0x84, 0x29, 0xbf, 0xd4, 0xeb, 0xc5, 0xc9, 0x29, 0xef, 0xdd, 0xd3, 0x2f, 0xa6, 0x25, 0x63, 0xda, 0xd9, 0x2c, 0xa1, 0x4a, 0xba, 0x75, 0xb2, 0x85, 0x25, 0x8f, 0x2b, 0x84, 0xcd, 0x99, 0x36, 0xd9, 0x6e, 0xf, 0xae, 0x7b, 0xd1, 0x61, 0x59, 0xf, 0x36, 0x4a, 0x22, 0xec, 0xde, 0x45, 0x32, 0xe0, 0x5b, 0x5c, 0xe3, 0x14, 0x29, 0x4, 0x60, 0x7b, 0xce, 0xa3, 0x89, 0x6b, 0xbb, 0xe0}, tr.Payload) + assert.Equal(t, []byte{0x0, 0x9, 0x57, 0xdd, 0x2f, 0x63, 0x56, 0x69, 0x34, 0xfd, 0xc2, 0xe1, 0xcd, 0xc1, 0xe, 0x3e, 0x25, 0xb9, 0x26, 0x5a, 0x16, 0x23, 0x91, 0xa6, 0x53, 0x16, 0x66, 0x59, 0x51, 0x0, 0x28, 0x7c, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xe0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0x80, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x20, 0x0, 0x3, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x66, 0xde, 0xf5, 0xba, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x66, 0xde, 0xf5, 0xba, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1e, 0x8e, 0x95, 0xcf, 0xb5, 0xd8, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1a, 0xd0, 0x1c, 0x67, 0xa9, 0xcf, 0xb3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x66, 0xdf, 0x3, 0xca, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1b, 0x1c, 0x93, 0x6d, 0xa4, 0xf2, 0x17, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1b, 0x14, 0x8d, 0x9a, 0xc1, 0xd9, 0x6f, 0xc0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1b, 0x40, 0x5c, 0xcf, 0xa1, 0xbc, 0x63, 0xc0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0x9d, 0xab, 0x8f, 0xa7, 0xca, 0x7, 0x62, 0x57, 0xf7, 0x11, 0x2c, 0xb7, 0xf3, 0x49, 0x37, 0x12, 0xbd, 0xe, 0x14, 0x27, 0xfc, 0x32, 0x5c, 0xec, 0xa6, 0xb9, 0x7f, 0xf9, 0xd7, 0x7b, 0xa6, 0x36, 0x9a, 0x47, 0x4a, 0x3, 0x1a, 0x95, 0xcf, 0x46, 0x10, 0xaf, 0xcc, 0x90, 0x49, 0xb2, 0xce, 0xbf, 0x63, 0xaa, 0xc7, 0x25, 0x4d, 0x2a, 0x8, 0x36, 0xda, 0xd5, 0x9f, 0x9d, 0x63, 0x69, 0x22, 0xb3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0x30, 0x9d, 0x84, 0x29, 0xbf, 0xd4, 0xeb, 0xc5, 0xc9, 0x29, 0xef, 0xdd, 0xd3, 0x2f, 0xa6, 0x25, 0x63, 0xda, 0xd9, 0x2c, 0xa1, 0x4a, 0xba, 0x75, 0xb2, 0x85, 0x25, 0x8f, 0x2b, 0x84, 0xcd, 0x99, 0x36, 0xd9, 0x6e, 0xf, 0xae, 0x7b, 0xd1, 0x61, 0x59, 0xf, 0x36, 0x4a, 0x22, 0xec, 0xde, 0x45, 0x32, 0xe0, 0x5b, 0x5c, 0xe3, 0x14, 0x29, 0x4, 0x60, 0x7b, 0xce, 0xa3, 0x89, 0x6b, 0xbb, 0xe0}, tr.Payload) assert.Equal(t, int(transmission.Report.Info.ReportFormat), int(tr.ReportFormat)) case <-time.After(testutils.WaitTimeout(t)): t.Fatal("expected a transmit request to be sent") @@ -187,7 +183,7 @@ func Test_Transmitter_runQueueLoop(t *testing.T) { select { case tr := <-transmit: - assert.Equal(t, []byte{0x0, 0x9, 0x57, 0xdd, 0x2f, 0x63, 0x56, 0x69, 0x34, 0xfd, 0xc2, 0xe1, 0xcd, 0xc1, 0xe, 0x3e, 0x25, 0xb9, 0x26, 0x5a, 0x16, 0x23, 0x91, 0xa6, 0x53, 0x16, 0x66, 0x59, 0x51, 0x0, 0x28, 0x7c, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0xe2, 0x40, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xe0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0x80, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x20, 0x0, 0x3, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x66, 0xde, 0xf5, 0xba, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x66, 0xde, 0xf5, 0xba, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1e, 0x8e, 0x95, 0xcf, 0xb5, 0xd8, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1a, 0xd0, 0x1c, 0x67, 0xa9, 0xcf, 0xb3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x66, 0xdf, 0x3, 0xca, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1b, 0x1c, 0x93, 0x6d, 0xa4, 0xf2, 0x17, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1b, 0x14, 0x8d, 0x9a, 0xc1, 0xd9, 0x6f, 0xc0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1b, 0x40, 0x5c, 0xcf, 0xa1, 0xbc, 0x63, 0xc0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0x9d, 0xab, 0x8f, 0xa7, 0xca, 0x7, 0x62, 0x57, 0xf7, 0x11, 0x2c, 0xb7, 0xf3, 0x49, 0x37, 0x12, 0xbd, 0xe, 0x14, 0x27, 0xfc, 0x32, 0x5c, 0xec, 0xa6, 0xb9, 0x7f, 0xf9, 0xd7, 0x7b, 0xa6, 0x36, 0x9a, 0x47, 0x4a, 0x3, 0x1a, 0x95, 0xcf, 0x46, 0x10, 0xaf, 0xcc, 0x90, 0x49, 0xb2, 0xce, 0xbf, 0x63, 0xaa, 0xc7, 0x25, 0x4d, 0x2a, 0x8, 0x36, 0xda, 0xd5, 0x9f, 0x9d, 0x63, 0x69, 0x22, 0xb3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0x30, 0x9d, 0x84, 0x29, 0xbf, 0xd4, 0xeb, 0xc5, 0xc9, 0x29, 0xef, 0xdd, 0xd3, 0x2f, 0xa6, 0x25, 0x63, 0xda, 0xd9, 0x2c, 0xa1, 0x4a, 0xba, 0x75, 0xb2, 0x85, 0x25, 0x8f, 0x2b, 0x84, 0xcd, 0x99, 0x36, 0xd9, 0x6e, 0xf, 0xae, 0x7b, 0xd1, 0x61, 0x59, 0xf, 0x36, 0x4a, 0x22, 0xec, 0xde, 0x45, 0x32, 0xe0, 0x5b, 0x5c, 0xe3, 0x14, 0x29, 0x4, 0x60, 0x7b, 0xce, 0xa3, 0x89, 0x6b, 0xbb, 0xe0}, tr.Payload) + assert.Equal(t, []byte{0x0, 0x9, 0x57, 0xdd, 0x2f, 0x63, 0x56, 0x69, 0x34, 0xfd, 0xc2, 0xe1, 0xcd, 0xc1, 0xe, 0x3e, 0x25, 0xb9, 0x26, 0x5a, 0x16, 0x23, 0x91, 0xa6, 0x53, 0x16, 0x66, 0x59, 0x51, 0x0, 0x28, 0x7c, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xe0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0x80, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x20, 0x0, 0x3, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x66, 0xde, 0xf5, 0xba, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x66, 0xde, 0xf5, 0xba, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1e, 0x8e, 0x95, 0xcf, 0xb5, 0xd8, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1a, 0xd0, 0x1c, 0x67, 0xa9, 0xcf, 0xb3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x66, 0xdf, 0x3, 0xca, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1b, 0x1c, 0x93, 0x6d, 0xa4, 0xf2, 0x17, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1b, 0x14, 0x8d, 0x9a, 0xc1, 0xd9, 0x6f, 0xc0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1b, 0x40, 0x5c, 0xcf, 0xa1, 0xbc, 0x63, 0xc0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0x9d, 0xab, 0x8f, 0xa7, 0xca, 0x7, 0x62, 0x57, 0xf7, 0x11, 0x2c, 0xb7, 0xf3, 0x49, 0x37, 0x12, 0xbd, 0xe, 0x14, 0x27, 0xfc, 0x32, 0x5c, 0xec, 0xa6, 0xb9, 0x7f, 0xf9, 0xd7, 0x7b, 0xa6, 0x36, 0x9a, 0x47, 0x4a, 0x3, 0x1a, 0x95, 0xcf, 0x46, 0x10, 0xaf, 0xcc, 0x90, 0x49, 0xb2, 0xce, 0xbf, 0x63, 0xaa, 0xc7, 0x25, 0x4d, 0x2a, 0x8, 0x36, 0xda, 0xd5, 0x9f, 0x9d, 0x63, 0x69, 0x22, 0xb3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0x30, 0x9d, 0x84, 0x29, 0xbf, 0xd4, 0xeb, 0xc5, 0xc9, 0x29, 0xef, 0xdd, 0xd3, 0x2f, 0xa6, 0x25, 0x63, 0xda, 0xd9, 0x2c, 0xa1, 0x4a, 0xba, 0x75, 0xb2, 0x85, 0x25, 0x8f, 0x2b, 0x84, 0xcd, 0x99, 0x36, 0xd9, 0x6e, 0xf, 0xae, 0x7b, 0xd1, 0x61, 0x59, 0xf, 0x36, 0x4a, 0x22, 0xec, 0xde, 0x45, 0x32, 0xe0, 0x5b, 0x5c, 0xe3, 0x14, 0x29, 0x4, 0x60, 0x7b, 0xce, 0xa3, 0x89, 0x6b, 0xbb, 0xe0}, tr.Payload) assert.Equal(t, int(transmission.Report.Info.ReportFormat), int(tr.ReportFormat)) case <-time.After(testutils.WaitTimeout(t)): t.Fatal("expected a transmit request to be sent") @@ -214,7 +210,7 @@ func Test_Transmitter_runQueueLoop(t *testing.T) { select { case tr := <-transmit: - assert.Equal(t, []byte{0x0, 0x9, 0x57, 0xdd, 0x2f, 0x63, 0x56, 0x69, 0x34, 0xfd, 0xc2, 0xe1, 0xcd, 0xc1, 0xe, 0x3e, 0x25, 0xb9, 0x26, 0x5a, 0x16, 0x23, 0x91, 0xa6, 0x53, 0x16, 0x66, 0x59, 0x51, 0x0, 0x28, 0x7c, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0xe2, 0x40, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xe0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0x80, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x20, 0x0, 0x3, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x66, 0xde, 0xf5, 0xba, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x66, 0xde, 0xf5, 0xba, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1e, 0x8e, 0x95, 0xcf, 0xb5, 0xd8, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1a, 0xd0, 0x1c, 0x67, 0xa9, 0xcf, 0xb3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x66, 0xdf, 0x3, 0xca, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1b, 0x1c, 0x93, 0x6d, 0xa4, 0xf2, 0x17, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1b, 0x14, 0x8d, 0x9a, 0xc1, 0xd9, 0x6f, 0xc0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1b, 0x40, 0x5c, 0xcf, 0xa1, 0xbc, 0x63, 0xc0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0x9d, 0xab, 0x8f, 0xa7, 0xca, 0x7, 0x62, 0x57, 0xf7, 0x11, 0x2c, 0xb7, 0xf3, 0x49, 0x37, 0x12, 0xbd, 0xe, 0x14, 0x27, 0xfc, 0x32, 0x5c, 0xec, 0xa6, 0xb9, 0x7f, 0xf9, 0xd7, 0x7b, 0xa6, 0x36, 0x9a, 0x47, 0x4a, 0x3, 0x1a, 0x95, 0xcf, 0x46, 0x10, 0xaf, 0xcc, 0x90, 0x49, 0xb2, 0xce, 0xbf, 0x63, 0xaa, 0xc7, 0x25, 0x4d, 0x2a, 0x8, 0x36, 0xda, 0xd5, 0x9f, 0x9d, 0x63, 0x69, 0x22, 0xb3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0x30, 0x9d, 0x84, 0x29, 0xbf, 0xd4, 0xeb, 0xc5, 0xc9, 0x29, 0xef, 0xdd, 0xd3, 0x2f, 0xa6, 0x25, 0x63, 0xda, 0xd9, 0x2c, 0xa1, 0x4a, 0xba, 0x75, 0xb2, 0x85, 0x25, 0x8f, 0x2b, 0x84, 0xcd, 0x99, 0x36, 0xd9, 0x6e, 0xf, 0xae, 0x7b, 0xd1, 0x61, 0x59, 0xf, 0x36, 0x4a, 0x22, 0xec, 0xde, 0x45, 0x32, 0xe0, 0x5b, 0x5c, 0xe3, 0x14, 0x29, 0x4, 0x60, 0x7b, 0xce, 0xa3, 0x89, 0x6b, 0xbb, 0xe0}, tr.Payload) + assert.Equal(t, []byte{0x0, 0x9, 0x57, 0xdd, 0x2f, 0x63, 0x56, 0x69, 0x34, 0xfd, 0xc2, 0xe1, 0xcd, 0xc1, 0xe, 0x3e, 0x25, 0xb9, 0x26, 0x5a, 0x16, 0x23, 0x91, 0xa6, 0x53, 0x16, 0x66, 0x59, 0x51, 0x0, 0x28, 0x7c, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xe0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0x80, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x20, 0x0, 0x3, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x66, 0xde, 0xf5, 0xba, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x66, 0xde, 0xf5, 0xba, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1e, 0x8e, 0x95, 0xcf, 0xb5, 0xd8, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1a, 0xd0, 0x1c, 0x67, 0xa9, 0xcf, 0xb3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x66, 0xdf, 0x3, 0xca, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1b, 0x1c, 0x93, 0x6d, 0xa4, 0xf2, 0x17, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1b, 0x14, 0x8d, 0x9a, 0xc1, 0xd9, 0x6f, 0xc0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1b, 0x40, 0x5c, 0xcf, 0xa1, 0xbc, 0x63, 0xc0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0x9d, 0xab, 0x8f, 0xa7, 0xca, 0x7, 0x62, 0x57, 0xf7, 0x11, 0x2c, 0xb7, 0xf3, 0x49, 0x37, 0x12, 0xbd, 0xe, 0x14, 0x27, 0xfc, 0x32, 0x5c, 0xec, 0xa6, 0xb9, 0x7f, 0xf9, 0xd7, 0x7b, 0xa6, 0x36, 0x9a, 0x47, 0x4a, 0x3, 0x1a, 0x95, 0xcf, 0x46, 0x10, 0xaf, 0xcc, 0x90, 0x49, 0xb2, 0xce, 0xbf, 0x63, 0xaa, 0xc7, 0x25, 0x4d, 0x2a, 0x8, 0x36, 0xda, 0xd5, 0x9f, 0x9d, 0x63, 0x69, 0x22, 0xb3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0x30, 0x9d, 0x84, 0x29, 0xbf, 0xd4, 0xeb, 0xc5, 0xc9, 0x29, 0xef, 0xdd, 0xd3, 0x2f, 0xa6, 0x25, 0x63, 0xda, 0xd9, 0x2c, 0xa1, 0x4a, 0xba, 0x75, 0xb2, 0x85, 0x25, 0x8f, 0x2b, 0x84, 0xcd, 0x99, 0x36, 0xd9, 0x6e, 0xf, 0xae, 0x7b, 0xd1, 0x61, 0x59, 0xf, 0x36, 0x4a, 0x22, 0xec, 0xde, 0x45, 0x32, 0xe0, 0x5b, 0x5c, 0xe3, 0x14, 0x29, 0x4, 0x60, 0x7b, 0xce, 0xa3, 0x89, 0x6b, 0xbb, 0xe0}, tr.Payload) assert.Equal(t, int(transmission.Report.Info.ReportFormat), int(tr.ReportFormat)) case <-time.After(testutils.WaitTimeout(t)): t.Fatal("expected a transmit request to be sent") @@ -245,7 +241,7 @@ func Test_Transmitter_runQueueLoop(t *testing.T) { for { select { case tr := <-transmit: - assert.Equal(t, []byte{0x0, 0x9, 0x57, 0xdd, 0x2f, 0x63, 0x56, 0x69, 0x34, 0xfd, 0xc2, 0xe1, 0xcd, 0xc1, 0xe, 0x3e, 0x25, 0xb9, 0x26, 0x5a, 0x16, 0x23, 0x91, 0xa6, 0x53, 0x16, 0x66, 0x59, 0x51, 0x0, 0x28, 0x7c, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0xe2, 0x40, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xe0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0x80, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x20, 0x0, 0x3, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x66, 0xde, 0xf5, 0xba, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x66, 0xde, 0xf5, 0xba, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1e, 0x8e, 0x95, 0xcf, 0xb5, 0xd8, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1a, 0xd0, 0x1c, 0x67, 0xa9, 0xcf, 0xb3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x66, 0xdf, 0x3, 0xca, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1b, 0x1c, 0x93, 0x6d, 0xa4, 0xf2, 0x17, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1b, 0x14, 0x8d, 0x9a, 0xc1, 0xd9, 0x6f, 0xc0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1b, 0x40, 0x5c, 0xcf, 0xa1, 0xbc, 0x63, 0xc0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0x9d, 0xab, 0x8f, 0xa7, 0xca, 0x7, 0x62, 0x57, 0xf7, 0x11, 0x2c, 0xb7, 0xf3, 0x49, 0x37, 0x12, 0xbd, 0xe, 0x14, 0x27, 0xfc, 0x32, 0x5c, 0xec, 0xa6, 0xb9, 0x7f, 0xf9, 0xd7, 0x7b, 0xa6, 0x36, 0x9a, 0x47, 0x4a, 0x3, 0x1a, 0x95, 0xcf, 0x46, 0x10, 0xaf, 0xcc, 0x90, 0x49, 0xb2, 0xce, 0xbf, 0x63, 0xaa, 0xc7, 0x25, 0x4d, 0x2a, 0x8, 0x36, 0xda, 0xd5, 0x9f, 0x9d, 0x63, 0x69, 0x22, 0xb3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0x30, 0x9d, 0x84, 0x29, 0xbf, 0xd4, 0xeb, 0xc5, 0xc9, 0x29, 0xef, 0xdd, 0xd3, 0x2f, 0xa6, 0x25, 0x63, 0xda, 0xd9, 0x2c, 0xa1, 0x4a, 0xba, 0x75, 0xb2, 0x85, 0x25, 0x8f, 0x2b, 0x84, 0xcd, 0x99, 0x36, 0xd9, 0x6e, 0xf, 0xae, 0x7b, 0xd1, 0x61, 0x59, 0xf, 0x36, 0x4a, 0x22, 0xec, 0xde, 0x45, 0x32, 0xe0, 0x5b, 0x5c, 0xe3, 0x14, 0x29, 0x4, 0x60, 0x7b, 0xce, 0xa3, 0x89, 0x6b, 0xbb, 0xe0}, tr.Payload) + assert.Equal(t, []byte{0x0, 0x9, 0x57, 0xdd, 0x2f, 0x63, 0x56, 0x69, 0x34, 0xfd, 0xc2, 0xe1, 0xcd, 0xc1, 0xe, 0x3e, 0x25, 0xb9, 0x26, 0x5a, 0x16, 0x23, 0x91, 0xa6, 0x53, 0x16, 0x66, 0x59, 0x51, 0x0, 0x28, 0x7c, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xe0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0x80, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x20, 0x0, 0x3, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x66, 0xde, 0xf5, 0xba, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x66, 0xde, 0xf5, 0xba, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1e, 0x8e, 0x95, 0xcf, 0xb5, 0xd8, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1a, 0xd0, 0x1c, 0x67, 0xa9, 0xcf, 0xb3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x66, 0xdf, 0x3, 0xca, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1b, 0x1c, 0x93, 0x6d, 0xa4, 0xf2, 0x17, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1b, 0x14, 0x8d, 0x9a, 0xc1, 0xd9, 0x6f, 0xc0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1b, 0x40, 0x5c, 0xcf, 0xa1, 0xbc, 0x63, 0xc0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0x9d, 0xab, 0x8f, 0xa7, 0xca, 0x7, 0x62, 0x57, 0xf7, 0x11, 0x2c, 0xb7, 0xf3, 0x49, 0x37, 0x12, 0xbd, 0xe, 0x14, 0x27, 0xfc, 0x32, 0x5c, 0xec, 0xa6, 0xb9, 0x7f, 0xf9, 0xd7, 0x7b, 0xa6, 0x36, 0x9a, 0x47, 0x4a, 0x3, 0x1a, 0x95, 0xcf, 0x46, 0x10, 0xaf, 0xcc, 0x90, 0x49, 0xb2, 0xce, 0xbf, 0x63, 0xaa, 0xc7, 0x25, 0x4d, 0x2a, 0x8, 0x36, 0xda, 0xd5, 0x9f, 0x9d, 0x63, 0x69, 0x22, 0xb3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0x30, 0x9d, 0x84, 0x29, 0xbf, 0xd4, 0xeb, 0xc5, 0xc9, 0x29, 0xef, 0xdd, 0xd3, 0x2f, 0xa6, 0x25, 0x63, 0xda, 0xd9, 0x2c, 0xa1, 0x4a, 0xba, 0x75, 0xb2, 0x85, 0x25, 0x8f, 0x2b, 0x84, 0xcd, 0x99, 0x36, 0xd9, 0x6e, 0xf, 0xae, 0x7b, 0xd1, 0x61, 0x59, 0xf, 0x36, 0x4a, 0x22, 0xec, 0xde, 0x45, 0x32, 0xe0, 0x5b, 0x5c, 0xe3, 0x14, 0x29, 0x4, 0x60, 0x7b, 0xce, 0xa3, 0x89, 0x6b, 0xbb, 0xe0}, tr.Payload) assert.Equal(t, int(transmission.Report.Info.ReportFormat), int(tr.ReportFormat)) if cnt > 2 { break Loop diff --git a/core/services/llo/onchain_channel_definition_cache.go b/core/services/llo/onchain_channel_definition_cache.go index 461c309a73a..3613108d133 100644 --- a/core/services/llo/onchain_channel_definition_cache.go +++ b/core/services/llo/onchain_channel_definition_cache.go @@ -11,7 +11,6 @@ import ( "maps" "math/big" "net/http" - "strconv" "strings" "sync" "time" @@ -23,8 +22,6 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink-common/pkg/services" llotypes "github.com/smartcontractkit/chainlink-common/pkg/types/llo" - "github.com/smartcontractkit/chainlink-common/pkg/types/query" - "github.com/smartcontractkit/chainlink-common/pkg/types/query/primitives" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/llo-feeds/generated/channel_config_store" @@ -46,10 +43,10 @@ const ( ) var ( - channelConfigStoreABI abi.ABI - NewChannelDefinition = (channel_config_store.ChannelConfigStoreNewChannelDefinition{}).Topic() + channelConfigStoreABI abi.ABI + topicNewChannelDefinition = (channel_config_store.ChannelConfigStoreNewChannelDefinition{}).Topic() - NoLimitSortAsc = query.NewLimitAndSort(query.Limit{}, query.NewSortBySequence(query.Asc)) + allTopics = []common.Hash{topicNewChannelDefinition} ) func init() { @@ -70,7 +67,7 @@ var _ llotypes.ChannelDefinitionCache = &channelDefinitionCache{} type LogPoller interface { LatestBlock(ctx context.Context) (logpoller.LogPollerBlock, error) - FilteredLogs(ctx context.Context, filter []query.Expression, limitAndSort query.LimitAndSort, queryName string) ([]logpoller.Log, error) + LogsWithSigs(ctx context.Context, start, end int64, eventSigs []common.Hash, address common.Address) ([]logpoller.Log, error) RegisterFilter(ctx context.Context, filter logpoller.Filter) error UnregisterFilter(ctx context.Context, filterName string) error } @@ -95,8 +92,6 @@ type channelDefinitionCache struct { logPollInterval time.Duration addr common.Address donID uint32 - donIDTopic common.Hash - filterExprs []query.Expression lggr logger.SugaredLogger initialBlockNum int64 @@ -126,20 +121,6 @@ func filterName(addr common.Address, donID uint32) string { func NewChannelDefinitionCache(lggr logger.Logger, orm ChannelDefinitionCacheORM, client HTTPClient, lp logpoller.LogPoller, addr common.Address, donID uint32, fromBlock int64, options ...Option) llotypes.ChannelDefinitionCache { filterName := logpoller.FilterName("OCR3 LLO ChannelDefinitionCachePoller", addr.String(), donID) - donIDTopic := common.BigToHash(big.NewInt(int64(donID))) - - exprs := []query.Expression{ - logpoller.NewAddressFilter(addr), - logpoller.NewEventSigFilter(NewChannelDefinition), - logpoller.NewEventByTopicFilter(1, []logpoller.HashedValueComparator{ - {Value: donIDTopic, Operator: primitives.Eq}, - }), - // NOTE: Optimize for fast pickup of new channel definitions. On - // Arbitrum, finalization can take tens of minutes - // (https://grafana.ops.prod.cldev.sh/d/e0453cc9-4b4a-41e1-9f01-7c21de805b39/blockchain-finality-and-gas?orgId=1&var-env=All&var-network_name=ethereum-testnet-sepolia-arbitrum-1&var-network_name=ethereum-mainnet-arbitrum-1&from=1732460992641&to=1732547392641) - query.Confidence(primitives.Unconfirmed), - } - cdc := &channelDefinitionCache{ orm: orm, client: client, @@ -149,8 +130,6 @@ func NewChannelDefinitionCache(lggr logger.Logger, orm ChannelDefinitionCacheORM logPollInterval: defaultLogPollInterval, addr: addr, donID: donID, - donIDTopic: donIDTopic, - filterExprs: exprs, lggr: logger.Sugared(lggr).Named("ChannelDefinitionCache").With("addr", addr, "fromBlock", fromBlock), newLogCh: make(chan *channel_config_store.ChannelConfigStoreNewChannelDefinition, 1), initialBlockNum: fromBlock, @@ -165,7 +144,8 @@ func NewChannelDefinitionCache(lggr logger.Logger, orm ChannelDefinitionCacheORM func (c *channelDefinitionCache) Start(ctx context.Context) error { // Initial load from DB, then async poll from chain thereafter return c.StartOnce("ChannelDefinitionCache", func() (err error) { - err = c.lp.RegisterFilter(ctx, logpoller.Filter{Name: c.filterName, EventSigs: []common.Hash{NewChannelDefinition}, Topic2: []common.Hash{c.donIDTopic}, Addresses: []common.Address{c.addr}}) + donIDTopic := common.BigToHash(big.NewInt(int64(c.donID))) + err = c.lp.RegisterFilter(ctx, logpoller.Filter{Name: c.filterName, EventSigs: allTopics, Topic2: []common.Hash{donIDTopic}, Addresses: []common.Address{c.addr}}) if err != nil { return err } @@ -236,49 +216,48 @@ func (c *channelDefinitionCache) readLogs(ctx context.Context) (err error) { return nil } - exprs := make([]query.Expression, 0, len(c.filterExprs)+2) - exprs = append(exprs, c.filterExprs...) - exprs = append(exprs, - query.Block(strconv.FormatInt(fromBlock, 10), primitives.Gte), - query.Block(strconv.FormatInt(toBlock, 10), primitives.Lte), - ) - - logs, err := c.lp.FilteredLogs(ctx, exprs, NoLimitSortAsc, "ChannelDefinitionCachePoller - NewChannelDefinition") + // NOTE: We assume that log poller returns logs in order of block_num, log_index ASC + // TODO: Could improve performance a little bit here by adding a don ID topic filter + // MERC-3524 + logs, err := c.lp.LogsWithSigs(ctx, fromBlock, toBlock, allTopics, c.addr) if err != nil { return err } for _, log := range logs { - if log.EventSig != NewChannelDefinition { - // ignore unrecognized logs - continue - } - unpacked := new(channel_config_store.ChannelConfigStoreNewChannelDefinition) + switch log.EventSig { + case topicNewChannelDefinition: + unpacked := new(channel_config_store.ChannelConfigStoreNewChannelDefinition) - err := channelConfigStoreABI.UnpackIntoInterface(unpacked, newChannelDefinitionEventName, log.Data) - if err != nil { - return fmt.Errorf("failed to unpack log data: %w", err) - } - if len(log.Topics) < 2 { - // should never happen but must guard against unexpected panics - c.lggr.Warnw("Log missing expected topics", "log", log) - continue - } - unpacked.DonId = new(big.Int).SetBytes(log.Topics[1]) + err := channelConfigStoreABI.UnpackIntoInterface(unpacked, newChannelDefinitionEventName, log.Data) + if err != nil { + return fmt.Errorf("failed to unpack log data: %w", err) + } + if len(log.Topics) < 2 { + // should never happen but must guard against unexpected panics + c.lggr.Warnw("Log missing expected topics", "log", log) + continue + } + unpacked.DonId = new(big.Int).SetBytes(log.Topics[1]) - if unpacked.DonId.Cmp(big.NewInt(int64(c.donID))) != 0 { - // skip logs for other donIDs, shouldn't happen given the - // FilterLogs call, but belts and braces - continue - } + if unpacked.DonId.Cmp(big.NewInt(int64(c.donID))) != 0 { + // skip logs for other donIDs + continue + } + + c.newLogMu.Lock() + if c.newLog == nil || unpacked.Version > c.newLog.Version { + // assume that donID is correct due to log poller filtering + c.lggr.Infow("Got new channel definitions from chain", "version", unpacked.Version, "blockNumber", log.BlockNumber, "sha", fmt.Sprintf("%x", unpacked.Sha), "url", unpacked.Url) + c.newLog = unpacked + c.newLogCh <- unpacked + } + c.newLogMu.Unlock() - c.newLogMu.Lock() - if c.newLog == nil || unpacked.Version > c.newLog.Version { - c.lggr.Infow("Got new channel definitions from chain", "version", unpacked.Version, "blockNumber", log.BlockNumber, "sha", fmt.Sprintf("%x", unpacked.Sha), "url", unpacked.Url) - c.newLog = unpacked - c.newLogCh <- unpacked + default: + // ignore unrecognized logs + continue } - c.newLogMu.Unlock() } return nil @@ -468,10 +447,8 @@ func (c *channelDefinitionCache) persist(ctx context.Context) (memoryVersion, pe c.persistedVersion = persistedVersion } - // NOTE: We could, in theory, delete the old logs from logpoller here since - // they are no longer needed. But logpoller does not currently support - // that, and in any case, the number is likely to be small so not worth - // worrying about. + // TODO: we could delete the old logs from logpoller here actually + // https://smartcontract-it.atlassian.net/browse/MERC-3653 return } @@ -502,6 +479,8 @@ func (c *channelDefinitionCache) failedPersistLoop() { } func (c *channelDefinitionCache) Close() error { + // TODO: unregister filter (on job delete)? + // https://smartcontract-it.atlassian.net/browse/MERC-3653 return c.StopOnce("ChannelDefinitionCache", func() error { // Cancel all contexts but try one final persist before closing close(c.chStop) diff --git a/core/services/llo/onchain_channel_definition_cache_test.go b/core/services/llo/onchain_channel_definition_cache_test.go index e6ea3264273..33fc60313c4 100644 --- a/core/services/llo/onchain_channel_definition_cache_test.go +++ b/core/services/llo/onchain_channel_definition_cache_test.go @@ -18,7 +18,6 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/logger" llotypes "github.com/smartcontractkit/chainlink-common/pkg/types/llo" - "github.com/smartcontractkit/chainlink-common/pkg/types/query" "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/llo-feeds/generated/channel_config_store" @@ -28,8 +27,8 @@ import ( type mockLogPoller struct { latestBlock logpoller.LogPollerBlock latestBlockErr error - filteredLogs []logpoller.Log - filteredLogsErr error + logsWithSigs []logpoller.Log + logsWithSigsErr error unregisteredFilterNames []string } @@ -40,8 +39,8 @@ func (m *mockLogPoller) RegisterFilter(ctx context.Context, filter logpoller.Fil func (m *mockLogPoller) LatestBlock(ctx context.Context) (logpoller.LogPollerBlock, error) { return m.latestBlock, m.latestBlockErr } -func (m *mockLogPoller) FilteredLogs(ctx context.Context, filter []query.Expression, limitAndSort query.LimitAndSort, queryName string) ([]logpoller.Log, error) { - return m.filteredLogs, m.filteredLogsErr +func (m *mockLogPoller) LogsWithSigs(ctx context.Context, start, end int64, eventSigs []common.Hash, address common.Address) ([]logpoller.Log, error) { + return m.logsWithSigs, m.logsWithSigsErr } func (m *mockLogPoller) UnregisterFilter(ctx context.Context, name string) error { m.unregisteredFilterNames = append(m.unregisteredFilterNames, name) @@ -89,7 +88,7 @@ func (m *mockCDCORM) CleanupChannelDefinitions(ctx context.Context, addr common. func makeLog(t *testing.T, donID, version uint32, url string, sha [32]byte) logpoller.Log { data := makeLogData(t, donID, version, url, sha) - return logpoller.Log{EventSig: NewChannelDefinition, Topics: [][]byte{NewChannelDefinition[:], makeDonIDTopic(donID)}, Data: data} + return logpoller.Log{EventSig: topicNewChannelDefinition, Topics: [][]byte{topicNewChannelDefinition[:], makeDonIDTopic(donID)}, Data: data} } func makeLogData(t *testing.T, donID, version uint32, url string, sha [32]byte) []byte { @@ -152,10 +151,10 @@ func Test_ChannelDefinitionCache(t *testing.T) { assert.NoError(t, err) assert.Nil(t, cdc.newLog) }) - t.Run("returns error if FilteredLogs fails", func(t *testing.T) { + t.Run("returns error if LogsWithSigs fails", func(t *testing.T) { ctx := tests.Context(t) cdc.definitionsBlockNum = 0 - lp.filteredLogsErr = errors.New("test error 2") + lp.logsWithSigsErr = errors.New("test error 2") err := cdc.readLogs(ctx) assert.EqualError(t, err, "test error 2") @@ -163,8 +162,8 @@ func Test_ChannelDefinitionCache(t *testing.T) { }) t.Run("ignores logs with different topic", func(t *testing.T) { ctx := tests.Context(t) - lp.filteredLogsErr = nil - lp.filteredLogs = []logpoller.Log{{EventSig: common.Hash{1, 2, 3, 4}}} + lp.logsWithSigsErr = nil + lp.logsWithSigs = []logpoller.Log{{EventSig: common.Hash{1, 2, 3, 4}}} err := cdc.readLogs(ctx) assert.NoError(t, err) @@ -172,17 +171,17 @@ func Test_ChannelDefinitionCache(t *testing.T) { }) t.Run("returns error if log is malformed", func(t *testing.T) { ctx := tests.Context(t) - lp.filteredLogsErr = nil - lp.filteredLogs = []logpoller.Log{{EventSig: NewChannelDefinition}} + lp.logsWithSigsErr = nil + lp.logsWithSigs = []logpoller.Log{{EventSig: topicNewChannelDefinition}} err := cdc.readLogs(ctx) assert.EqualError(t, err, "failed to unpack log data: abi: attempting to unmarshal an empty string while arguments are expected") assert.Nil(t, cdc.newLog) }) - t.Run("sets definitions and sends on channel if FilteredLogs returns new event with a later version", func(t *testing.T) { + t.Run("sets definitions and sends on channel if LogsWithSigs returns new event with a later version", func(t *testing.T) { ctx := tests.Context(t) - lp.filteredLogsErr = nil - lp.filteredLogs = []logpoller.Log{makeLog(t, donID, uint32(43), "http://example.com/xxx.json", [32]byte{1, 2, 3, 4})} + lp.logsWithSigsErr = nil + lp.logsWithSigs = []logpoller.Log{makeLog(t, donID, uint32(43), "http://example.com/xxx.json", [32]byte{1, 2, 3, 4})} err := cdc.readLogs(ctx) require.NoError(t, err) @@ -205,8 +204,8 @@ func Test_ChannelDefinitionCache(t *testing.T) { }) t.Run("does nothing if version older or the same as the one currently set", func(t *testing.T) { ctx := tests.Context(t) - lp.filteredLogsErr = nil - lp.filteredLogs = []logpoller.Log{ + lp.logsWithSigsErr = nil + lp.logsWithSigs = []logpoller.Log{ makeLog(t, donID, uint32(42), "http://example.com/xxx.json", [32]byte{1, 2, 3, 4}), makeLog(t, donID, uint32(43), "http://example.com/xxx.json", [32]byte{1, 2, 3, 4}), } @@ -217,8 +216,8 @@ func Test_ChannelDefinitionCache(t *testing.T) { }) t.Run("in case of multiple logs, takes the latest", func(t *testing.T) { ctx := tests.Context(t) - lp.filteredLogsErr = nil - lp.filteredLogs = []logpoller.Log{ + lp.logsWithSigsErr = nil + lp.logsWithSigs = []logpoller.Log{ makeLog(t, donID, uint32(42), "http://example.com/xxx.json", [32]byte{1, 2, 3, 4}), makeLog(t, donID, uint32(45), "http://example.com/xxx2.json", [32]byte{2, 2, 3, 4}), makeLog(t, donID, uint32(44), "http://example.com/xxx3.json", [32]byte{3, 2, 3, 4}), @@ -245,8 +244,8 @@ func Test_ChannelDefinitionCache(t *testing.T) { }) t.Run("ignores logs with incorrect don ID", func(t *testing.T) { ctx := tests.Context(t) - lp.filteredLogsErr = nil - lp.filteredLogs = []logpoller.Log{ + lp.logsWithSigsErr = nil + lp.logsWithSigs = []logpoller.Log{ makeLog(t, donID+1, uint32(42), "http://example.com/xxx.json", [32]byte{1, 2, 3, 4}), } @@ -267,10 +266,10 @@ func Test_ChannelDefinitionCache(t *testing.T) { }) t.Run("ignores logs with wrong number of topics", func(t *testing.T) { ctx := tests.Context(t) - lp.filteredLogsErr = nil + lp.logsWithSigsErr = nil lg := makeLog(t, donID, uint32(42), "http://example.com/xxx.json", [32]byte{1, 2, 3, 4}) lg.Topics = lg.Topics[:1] - lp.filteredLogs = []logpoller.Log{lg} + lp.logsWithSigs = []logpoller.Log{lg} err := cdc.readLogs(ctx) require.NoError(t, err) @@ -298,7 +297,7 @@ func Test_ChannelDefinitionCache(t *testing.T) { } t.Run("nil ctx returns error", func(t *testing.T) { - _, err := cdc.fetchChannelDefinitions(nil, "notvalid://foos", [32]byte{}) //nolint:staticcheck // SA1012 we pass nil intentionally here + _, err := cdc.fetchChannelDefinitions(nil, "notvalid://foos", [32]byte{}) //nolint assert.EqualError(t, err, "failed to create http.Request; net/http: nil Context") }) diff --git a/core/services/llo/plugin_scoped_retirement_report_cache_test.go b/core/services/llo/plugin_scoped_retirement_report_cache_test.go index f370cd9f1b4..e1afb203fd2 100644 --- a/core/services/llo/plugin_scoped_retirement_report_cache_test.go +++ b/core/services/llo/plugin_scoped_retirement_report_cache_test.go @@ -16,25 +16,6 @@ import ( llotypes "github.com/smartcontractkit/chainlink-common/pkg/types/llo" ) -func FuzzPluginScopedRetirementReportCache_CheckAttestedRetirementReport(f *testing.F) { - f.Add([]byte("not a protobuf")) - f.Add([]byte{0x0a, 0x00}) // empty protobuf - f.Add([]byte{0x0a, 0x02, 0x08, 0x01}) // invalid protobuf - f.Add(([]byte)(nil)) - f.Add([]byte{}) - - rrc := &mockRetirementReportCache{} - v := &mockVerifier{} - c := &mockCodec{} - psrrc := NewPluginScopedRetirementReportCache(rrc, v, c) - - exampleDigest := ocr2types.ConfigDigest{1} - - f.Fuzz(func(t *testing.T, data []byte) { - psrrc.CheckAttestedRetirementReport(exampleDigest, data) //nolint:errcheck // test that it doesn't panic, don't care about errors - }) -} - type mockRetirementReportCache struct { arr []byte cfg Config diff --git a/core/services/llo/static_channel_definitions_cache.go b/core/services/llo/static_channel_definitions_cache.go index d087d24e5e4..980625bd599 100644 --- a/core/services/llo/static_channel_definitions_cache.go +++ b/core/services/llo/static_channel_definitions_cache.go @@ -3,7 +3,6 @@ package llo import ( "context" "encoding/json" - "fmt" "github.com/smartcontractkit/chainlink-common/pkg/services" llotypes "github.com/smartcontractkit/chainlink-common/pkg/types/llo" @@ -26,7 +25,7 @@ type staticCDC struct { func NewStaticChannelDefinitionCache(lggr logger.Logger, dfnstr string) (llotypes.ChannelDefinitionCache, error) { var definitions llotypes.ChannelDefinitions if err := json.Unmarshal([]byte(dfnstr), &definitions); err != nil { - return nil, fmt.Errorf("failed to unmarshal static channel definitions: %w", err) + return nil, err } return &staticCDC{services.StateMachine{}, logger.Named(lggr, "StaticChannelDefinitionCache"), definitions}, nil } diff --git a/core/services/llo/suppressed_logger.go b/core/services/llo/suppressed_logger.go deleted file mode 100644 index 9fe6e6731e5..00000000000 --- a/core/services/llo/suppressed_logger.go +++ /dev/null @@ -1,51 +0,0 @@ -package llo - -import "github.com/smartcontractkit/chainlink-common/pkg/logger" - -// Suppressed logger swallows debug/info unless the verbose flag is turned on -// Useful for OCR to calm down its verbosity - -var _ logger.Logger = &SuppressedLogger{} - -func NewSuppressedLogger(lggr logger.Logger, verbose bool) logger.Logger { - return &SuppressedLogger{ - Logger: lggr, - Verbose: verbose, - } -} - -type SuppressedLogger struct { - logger.Logger - Verbose bool -} - -func (s *SuppressedLogger) Debug(args ...interface{}) { - if s.Verbose { - s.Logger.Debug(args...) - } -} -func (s *SuppressedLogger) Info(args ...interface{}) { - if s.Verbose { - s.Logger.Info(args...) - } -} -func (s *SuppressedLogger) Debugf(format string, values ...interface{}) { - if s.Verbose { - s.Logger.Debugf(format, values...) - } -} -func (s *SuppressedLogger) Infof(format string, values ...interface{}) { - if s.Verbose { - s.Logger.Infof(format, values...) - } -} -func (s *SuppressedLogger) Debugw(msg string, keysAndValues ...interface{}) { - if s.Verbose { - s.Logger.Debugw(msg, keysAndValues...) - } -} -func (s *SuppressedLogger) Infow(msg string, keysAndValues ...interface{}) { - if s.Verbose { - s.Logger.Infow(msg, keysAndValues...) - } -} diff --git a/core/services/llo/telemetry.go b/core/services/llo/telemetry.go index 0b315d78d2b..888ee9d5d36 100644 --- a/core/services/llo/telemetry.go +++ b/core/services/llo/telemetry.go @@ -39,11 +39,7 @@ func NewTelemeterService(lggr logger.Logger, monitoringEndpoint commontypes.Moni } func newTelemeter(lggr logger.Logger, monitoringEndpoint commontypes.MonitoringEndpoint, donID uint32) *telemeter { - // NOTE: This channel must take multiple telemetry packets per round (1 per - // feed) so we need to make sure the buffer is large enough. - // - // 2000 feeds * 5s/250ms = 40_000 should hold ~5s of buffer in the worst case. - chTelemetryObservation := make(chan TelemetryObservation, 40_000) + chTelemetryObservation := make(chan TelemetryObservation, 100) t := &telemeter{ chTelemetryObservation: chTelemetryObservation, monitoringEndpoint: monitoringEndpoint, @@ -119,6 +115,7 @@ func (t *telemeter) collectV3PremiumLegacyTelemetry(d TelemetryObservation) { askPrice = v.Ask.IntPart() ask = v.Ask.String() } + epoch, round := evm.SeqNrToEpochAndRound(d.opts.OutCtx().SeqNr) tea := &telem.EnhancedEAMercury{ DataSource: eaTelem.DataSource, DpBenchmarkPrice: eaTelem.DpBenchmarkPrice, @@ -141,17 +138,12 @@ func (t *telemeter) collectV3PremiumLegacyTelemetry(d TelemetryObservation) { IsLinkFeed: false, IsNativeFeed: false, ConfigDigest: d.opts.ConfigDigest().Hex(), + Round: int64(round), + Epoch: int64(epoch), AssetSymbol: eaTelem.AssetSymbol, Version: uint32(1000 + mercuryutils.REPORT_V3), // add 1000 to distinguish between legacy feeds, this can be changed if necessary DonId: t.donID, } - epoch, round, err := evm.SeqNrToEpochAndRound(d.opts.OutCtx().SeqNr) - if err != nil { - t.eng.SugaredLogger.Warnw("Failed to convert sequence number to epoch and round", "err", err) - } else { - tea.Round = int64(round) - tea.Epoch = int64(epoch) - } bytes, err := proto.Marshal(tea) if err != nil { diff --git a/core/services/llo/transmitter.go b/core/services/llo/transmitter.go index 94b508bfcee..7696c69c291 100644 --- a/core/services/llo/transmitter.go +++ b/core/services/llo/transmitter.go @@ -23,9 +23,17 @@ import ( // If you need to "fan-out" transmits and send reports to a new destination, // add a new subTransmitter +// TODO: prom metrics (common with mercury/transmitter.go?) +// https://smartcontract-it.atlassian.net/browse/MERC-3659 + const ( // Mercury server error codes DuplicateReport = 2 + // TODO: revisit these values in light of parallel composition + // https://smartcontract-it.atlassian.net/browse/MERC-3659 + // maxTransmitQueueSize = 10_000 + // maxDeleteQueueSize = 10_000 + // transmitTimeout = 5 * time.Second ) type Transmitter interface { @@ -39,9 +47,8 @@ type TransmitterRetirementReportCacheWriter interface { type transmitter struct { services.StateMachine - lggr logger.Logger - verboseLogging bool - fromAccount string + lggr logger.Logger + fromAccount string subTransmitters []Transmitter retirementReportCache TransmitterRetirementReportCacheWriter @@ -49,7 +56,6 @@ type transmitter struct { type TransmitterOpts struct { Lggr logger.Logger - VerboseLogging bool FromAccount string MercuryTransmitterOpts mercurytransmitter.Opts RetirementReportCache TransmitterRetirementReportCacheWriter @@ -63,7 +69,6 @@ func NewTransmitter(opts TransmitterOpts) Transmitter { return &transmitter{ services.StateMachine{}, opts.Lggr, - opts.VerboseLogging, opts.FromAccount, subTransmitters, opts.RetirementReportCache, @@ -109,10 +114,6 @@ func (t *transmitter) Transmit( report ocr3types.ReportWithInfo[llotypes.ReportInfo], sigs []types.AttributedOnchainSignature, ) (err error) { - if t.verboseLogging { - t.lggr.Debugw("Transmit report", "digest", digest, "seqNr", seqNr, "report", report, "sigs", sigs) - } - if report.Info.ReportFormat == llotypes.ReportFormatRetirement { // Retirement reports don't get transmitted; rather, they are stored in // the RetirementReportCache diff --git a/core/services/ocr/database.go b/core/services/ocr/database.go index b570c89e5a2..b5f890565f1 100644 --- a/core/services/ocr/database.go +++ b/core/services/ocr/database.go @@ -209,7 +209,7 @@ func (d *db) StorePendingTransmission(ctx context.Context, k ocrtypes.ReportTime } func (d *db) PendingTransmissionsWithConfigDigest(ctx context.Context, cd ocrtypes.ConfigDigest) (map[ocrtypes.ReportTimestamp]ocrtypes.PendingTransmission, error) { - //nolint:sqlclosecheck // false positive + //nolint sqlclosecheck false positive rows, err := d.ds.QueryContext(ctx, ` SELECT config_digest, diff --git a/core/services/ocr2/database.go b/core/services/ocr2/database.go index 11de288432f..919d8ff5741 100644 --- a/core/services/ocr2/database.go +++ b/core/services/ocr2/database.go @@ -278,7 +278,7 @@ func (d *db) PendingTransmissionsWithConfigDigest(ctx context.Context, cd ocrtyp FROM ocr2_pending_transmissions WHERE ocr2_oracle_spec_id = $1 AND config_digest = $2 ` - rows, err := d.ds.QueryxContext(ctx, stmt, d.oracleSpecID, cd) + rows, err := d.ds.QueryxContext(ctx, stmt, d.oracleSpecID, cd) //nolint sqlclosecheck false positive if err != nil { return nil, errors.Wrap(err, "PendingTransmissionsWithConfigDigest failed to query rows") } diff --git a/core/services/ocr2/delegate.go b/core/services/ocr2/delegate.go index 13094fefb1a..acee4168a5a 100644 --- a/core/services/ocr2/delegate.go +++ b/core/services/ocr2/delegate.go @@ -683,9 +683,9 @@ func (d *Delegate) newServicesGenericPlugin( providerClientConn = providerConn.ClientConn() } else { // We chose to deal with the difference between a LOOP provider and an embedded provider here rather than - // in NewServerAdapter because this has a smaller blast radius, as the scope of this workaround is to - // enable the medianpoc for EVM and not touch the other providers. - // TODO: remove this workaround when the EVM relayer is running inside of an LOOPP + //in NewServerAdapter because this has a smaller blast radius, as the scope of this workaround is to + //enable the medianpoc for EVM and not touch the other providers. + //TODO: remove this workaround when the EVM relayer is running inside of an LOOPP d.lggr.Info("provider is not a LOOPP provider, switching to provider server") ps, err2 := loop.NewProviderServer(provider, types.OCR2PluginType(pCfg.ProviderType), d.lggr) @@ -883,10 +883,12 @@ func (d *Delegate) newServicesMercury( return nil, errors.New("could not coerce PluginProvider to MercuryProvider") } - lc.ContractConfigTrackerPollInterval = 1 * time.Second // This is the fastest that libocr supports. See: https://github.com/smartcontractkit/offchain-reporting/pull/520 + // HACK: We need fast config switchovers because they create downtime. This + // won't be properly resolved until we implement blue-green deploys: + // https://smartcontract-it.atlassian.net/browse/MERC-3386 + lc.ContractConfigTrackerPollInterval = 1 * time.Second // Mercury requires a fast poll interval, this is the fastest that libocr supports. See: https://github.com/smartcontractkit/offchain-reporting/pull/520 - // Disable OCR debug+info logging for legacy mercury jobs unless tracelogging is enabled, because its simply too verbose (150 jobs => ~50k logs per second) - ocrLogger := ocrcommon.NewOCRWrapper(llo.NewSuppressedLogger(lggr, d.cfg.OCR2().TraceLogging()), d.cfg.OCR2().TraceLogging(), func(ctx context.Context, msg string) { + ocrLogger := ocrcommon.NewOCRWrapper(lggr, d.cfg.OCR2().TraceLogging(), func(ctx context.Context, msg string) { lggr.ErrorIf(d.jobORM.RecordError(ctx, jb.ID, msg), "unable to record error") }) @@ -1003,7 +1005,7 @@ func (d *Delegate) newServicesLLO( // Use the default key bundle if not specified // NOTE: Only JSON and EVMPremiumLegacy supported for now - // TODO: MERC-3594 + // https://smartcontract-it.atlassian.net/browse/MERC-3722 // // Also re-use EVM keys for signing the retirement report. This isn't // required, just seems easiest since it's the only key type available for @@ -1030,7 +1032,7 @@ func (d *Delegate) newServicesLLO( // config on the job spec instead. // https://smartcontract-it.atlassian.net/browse/MERC-3594 lggr.Infof("Using on-chain signing keys for LLO job %d (%s): %v", jb.ID, jb.Name.ValueOrZero(), kbm) - kr := llo.NewOnchainKeyring(lggr, kbm, pluginCfg.DonID) + kr := llo.NewOnchainKeyring(lggr, kbm) telemetryContractID := fmt.Sprintf("%s/%d", spec.ContractID, pluginCfg.DonID) @@ -1049,13 +1051,13 @@ func (d *Delegate) newServicesLLO( RetirementReportCodec: datastreamsllo.StandardRetirementReportCodec{}, EAMonitoringEndpoint: d.monitoringEndpointGen.GenMonitoringEndpoint(rid.Network, rid.ChainID, telemetryContractID, synchronization.EnhancedEAMercury), DonID: pluginCfg.DonID, - ChainID: rid.ChainID, TraceLogging: d.cfg.OCR2().TraceLogging(), BinaryNetworkEndpointFactory: d.peerWrapper.Peer2, V2Bootstrappers: bootstrapPeers, ContractTransmitter: provider.ContractTransmitter(), ContractConfigTrackers: provider.ContractConfigTrackers(), + Database: ocrDB, LocalConfig: lc, OCR3MonitoringEndpoint: d.monitoringEndpointGen.GenMonitoringEndpoint(rid.Network, rid.ChainID, telemetryContractID, synchronization.OCR3Mercury), OffchainConfigDigester: provider.OffchainConfigDigester(), @@ -1064,9 +1066,6 @@ func (d *Delegate) newServicesLLO( // Enable verbose logging if either Mercury.VerboseLogging is on or OCR2.TraceLogging is on ReportingPluginConfig: datastreamsllo.Config{VerboseLogging: d.cfg.Mercury().VerboseLogging() || d.cfg.OCR2().TraceLogging()}, - NewOCR3DB: func(pluginID int32) ocr3types.Database { - return NewDB(d.ds, spec.ID, pluginID, lggr) - }, } oracle, err := llo.NewDelegate(cfg) if err != nil { diff --git a/core/services/ocr2/plugins/ccip/ccipexec/gashelpers_test.go b/core/services/ocr2/plugins/ccip/ccipexec/gashelpers_test.go index 42a62a1be99..afcd580e24b 100644 --- a/core/services/ocr2/plugins/ccip/ccipexec/gashelpers_test.go +++ b/core/services/ocr2/plugins/ccip/ccipexec/gashelpers_test.go @@ -168,6 +168,12 @@ func TestWaitBoostedFee(t *testing.T) { boosted := waitBoostedFee(tc.sendTimeDiff, tc.fee, tc.relativeBoostPerWaitHour) diff := big.NewInt(0).Sub(boosted, tc.fee) assert.Equal(t, diff, tc.diff) + // we check that the actual diff is approximately equals to expected diff, + // as we might get slightly different results locally vs. CI therefore normal Equal() would be unstable + // diffUpperLimit := big.NewInt(0).Add(tc.diff, big.NewInt(1e9)) + //diffLowerLimit := big.NewInt(0).Add(tc.diff, big.NewInt(-1e9)) + //require.Equalf(t, -1, diff.Cmp(diffUpperLimit), "actual diff (%s) is larger than expected (%s)", diff.String(), diffUpperLimit.String()) + //require.Equal(t, 1, diff.Cmp(diffLowerLimit), "actual diff (%s) is smaller than expected (%s)", diff.String(), diffLowerLimit.String()) }) } } diff --git a/core/services/ocr2/plugins/ccip/clo_ccip_integration_test.go b/core/services/ocr2/plugins/ccip/clo_ccip_integration_test.go index 52eb15c77d2..daac8cc37f9 100644 --- a/core/services/ocr2/plugins/ccip/clo_ccip_integration_test.go +++ b/core/services/ocr2/plugins/ccip/clo_ccip_integration_test.go @@ -22,7 +22,6 @@ import ( ) func Test_CLOSpecApprovalFlow_pipeline(t *testing.T) { - t.Parallel() ccipTH := integrationtesthelpers.SetupCCIPIntegrationTH( t, testhelpers.SourceChainID, @@ -41,7 +40,6 @@ func Test_CLOSpecApprovalFlow_pipeline(t *testing.T) { } func Test_CLOSpecApprovalFlow_dynamicPriceGetter(t *testing.T) { - t.Parallel() ccipTH := integrationtesthelpers.SetupCCIPIntegrationTH( t, testhelpers.SourceChainID, diff --git a/core/services/ocr2/plugins/ccip/integration_legacy_test.go b/core/services/ocr2/plugins/ccip/integration_legacy_test.go new file mode 100644 index 00000000000..12a117d47c4 --- /dev/null +++ b/core/services/ocr2/plugins/ccip/integration_legacy_test.go @@ -0,0 +1,594 @@ +package ccip_test + +import ( + "context" + "encoding/json" + "fmt" + "math/big" + "sync" + "testing" + "time" + + "github.com/ethereum/go-ethereum/common" + gethtypes "github.com/ethereum/go-ethereum/core/types" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + evm_2_evm_onramp "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/evm_2_evm_onramp_1_2_0" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/router" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/mock_v3_aggregator_contract" + "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" + "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/config" + "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/ccipdata" + "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_2_0" + testhelpers_new "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/testhelpers" + testhelpers "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/testhelpers/testhelpers_1_4_0" +) + +func TestIntegration_legacy_CCIP(t *testing.T) { + // Run the batches of tests for both pipeline and dynamic price getter setups. + // We will remove the pipeline batch once the feature is deleted from the code. + tests := []struct { + name string + withPipeline bool + }{ + { + name: "with pipeline", + withPipeline: true, + }, + { + name: "with dynamic price getter", + withPipeline: false, + }, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + ccipTH := testhelpers.SetupCCIPIntegrationTH(t, testhelpers.SourceChainID, testhelpers.SourceChainSelector, testhelpers.DestChainID, testhelpers.DestChainSelector) + + tokenPricesUSDPipeline := "" + priceGetterConfigJson := "" + + if test.withPipeline { + // Set up a test pipeline. + testPricePipeline, linkUSD, ethUSD := ccipTH.CreatePricesPipeline(t) + defer linkUSD.Close() + defer ethUSD.Close() + tokenPricesUSDPipeline = testPricePipeline + } else { + // Set up a test price getter. + // Set up the aggregators here to avoid modifying ccipTH. + aggSrcNatAddr, _, aggSrcNat, err := mock_v3_aggregator_contract.DeployMockV3AggregatorContract(ccipTH.Source.User, ccipTH.Source.Chain.Client(), 18, big.NewInt(2e18)) + require.NoError(t, err) + _, err = aggSrcNat.UpdateRoundData(ccipTH.Source.User, big.NewInt(50), big.NewInt(17000000), big.NewInt(1000), big.NewInt(1000)) + require.NoError(t, err) + ccipTH.Source.Chain.Commit() + + aggDstLnkAddr, _, aggDstLnk, err := mock_v3_aggregator_contract.DeployMockV3AggregatorContract(ccipTH.Dest.User, ccipTH.Dest.Chain.Client(), 18, big.NewInt(3e18)) + require.NoError(t, err) + ccipTH.Dest.Chain.Commit() + _, err = aggDstLnk.UpdateRoundData(ccipTH.Dest.User, big.NewInt(50), big.NewInt(8000000), big.NewInt(1000), big.NewInt(1000)) + require.NoError(t, err) + ccipTH.Dest.Chain.Commit() + + priceGetterConfig := config.DynamicPriceGetterConfig{ + AggregatorPrices: map[common.Address]config.AggregatorPriceConfig{ + ccipTH.Source.WrappedNative.Address(): { + ChainID: ccipTH.Source.ChainID, + AggregatorContractAddress: aggSrcNatAddr, + }, + ccipTH.Dest.LinkToken.Address(): { + ChainID: ccipTH.Dest.ChainID, + AggregatorContractAddress: aggDstLnkAddr, + }, + ccipTH.Dest.WrappedNative.Address(): { + ChainID: ccipTH.Dest.ChainID, + AggregatorContractAddress: aggDstLnkAddr, + }, + }, + StaticPrices: map[common.Address]config.StaticPriceConfig{}, + } + priceGetterConfigBytes, err := json.MarshalIndent(priceGetterConfig, "", " ") + require.NoError(t, err) + priceGetterConfigJson = string(priceGetterConfigBytes) + } + + jobParams := ccipTH.SetUpNodesAndJobs(t, tokenPricesUSDPipeline, priceGetterConfigJson, "") + + currentSeqNum := 1 + + t.Run("single", func(t *testing.T) { + tokenAmount := big.NewInt(500000003) // prime number + gasLimit := big.NewInt(200_003) // prime number + + extraArgs, err2 := testhelpers.GetEVMExtraArgsV1(gasLimit, false) + require.NoError(t, err2) + + sourceBalances, err2 := testhelpers.GetBalances(t, []testhelpers.BalanceReq{ + {Name: testhelpers.SourcePool, Addr: ccipTH.Source.LinkTokenPool.Address(), Getter: ccipTH.GetSourceLinkBalance}, + {Name: testhelpers.OnRamp, Addr: ccipTH.Source.OnRamp.Address(), Getter: ccipTH.GetSourceLinkBalance}, + {Name: testhelpers.SourceRouter, Addr: ccipTH.Source.Router.Address(), Getter: ccipTH.GetSourceLinkBalance}, + {Name: testhelpers.SourcePriceRegistry, Addr: ccipTH.Source.PriceRegistry.Address(), Getter: ccipTH.GetSourceLinkBalance}, + }) + require.NoError(t, err2) + destBalances, err2 := testhelpers.GetBalances(t, []testhelpers.BalanceReq{ + {Name: testhelpers.Receiver, Addr: ccipTH.Dest.Receivers[0].Receiver.Address(), Getter: ccipTH.GetDestLinkBalance}, + {Name: testhelpers.DestPool, Addr: ccipTH.Dest.LinkTokenPool.Address(), Getter: ccipTH.GetDestLinkBalance}, + {Name: testhelpers.OffRamp, Addr: ccipTH.Dest.OffRamp.Address(), Getter: ccipTH.GetDestLinkBalance}, + }) + require.NoError(t, err2) + + ccipTH.Source.User.Value = tokenAmount + _, err2 = ccipTH.Source.WrappedNative.Deposit(ccipTH.Source.User) + require.NoError(t, err2) + ccipTH.Source.Chain.Commit() + ccipTH.Source.User.Value = nil + + msg := router.ClientEVM2AnyMessage{ + Receiver: testhelpers.MustEncodeAddress(t, ccipTH.Dest.Receivers[0].Receiver.Address()), + Data: []byte("hello"), + TokenAmounts: []router.ClientEVMTokenAmount{ + { + Token: ccipTH.Source.LinkToken.Address(), + Amount: tokenAmount, + }, + { + Token: ccipTH.Source.WrappedNative.Address(), + Amount: tokenAmount, + }, + }, + FeeToken: ccipTH.Source.LinkToken.Address(), + ExtraArgs: extraArgs, + } + fee, err2 := ccipTH.Source.Router.GetFee(nil, testhelpers.DestChainSelector, msg) + require.NoError(t, err2) + // Currently no overhead and 10gwei dest gas price. So fee is simply (gasLimit * gasPrice)* link/native + // require.Equal(t, new(big.Int).Mul(gasLimit, gasPrice).String(), fee.String()) + // Approve the fee amount + the token amount + _, err2 = ccipTH.Source.LinkToken.Approve(ccipTH.Source.User, ccipTH.Source.Router.Address(), new(big.Int).Add(fee, tokenAmount)) + require.NoError(t, err2) + ccipTH.Source.Chain.Commit() + _, err2 = ccipTH.Source.WrappedNative.Approve(ccipTH.Source.User, ccipTH.Source.Router.Address(), tokenAmount) + require.NoError(t, err2) + ccipTH.Source.Chain.Commit() + + ccipTH.SendRequest(t, msg) + // Should eventually see this executed. + ccipTH.AllNodesHaveReqSeqNum(t, currentSeqNum) + ccipTH.EventuallyReportCommitted(t, currentSeqNum) + + executionLogs := ccipTH.AllNodesHaveExecutedSeqNums(t, currentSeqNum, currentSeqNum) + assert.Len(t, executionLogs, 1) + ccipTH.AssertExecState(t, executionLogs[0], testhelpers.ExecutionStateSuccess) + + // Asserts + // 1) The total pool input == total pool output + // 2) Pool flow equals tokens sent + // 3) Sent tokens arrive at the receiver + ccipTH.AssertBalances(t, []testhelpers.BalanceAssertion{ + { + Name: testhelpers.SourcePool, + Address: ccipTH.Source.LinkTokenPool.Address(), + Expected: testhelpers.MustAddBigInt(sourceBalances[testhelpers.SourcePool], tokenAmount.String()).String(), + Getter: ccipTH.GetSourceLinkBalance, + }, + { + Name: testhelpers.SourcePriceRegistry, + Address: ccipTH.Source.PriceRegistry.Address(), + Expected: sourceBalances[testhelpers.SourcePriceRegistry].String(), + Getter: ccipTH.GetSourceLinkBalance, + }, + { + // Fees end up in the onramp. + Name: testhelpers.OnRamp, + Address: ccipTH.Source.OnRamp.Address(), + Expected: testhelpers.MustAddBigInt(sourceBalances[testhelpers.SourcePriceRegistry], fee.String()).String(), + Getter: ccipTH.GetSourceLinkBalance, + }, + { + Name: testhelpers.SourceRouter, + Address: ccipTH.Source.Router.Address(), + Expected: sourceBalances[testhelpers.SourceRouter].String(), + Getter: ccipTH.GetSourceLinkBalance, + }, + { + Name: testhelpers.Receiver, + Address: ccipTH.Dest.Receivers[0].Receiver.Address(), + Expected: testhelpers.MustAddBigInt(destBalances[testhelpers.Receiver], tokenAmount.String()).String(), + Getter: ccipTH.GetDestLinkBalance, + }, + { + Name: testhelpers.DestPool, + Address: ccipTH.Dest.LinkTokenPool.Address(), + Expected: testhelpers.MustSubBigInt(destBalances[testhelpers.DestPool], tokenAmount.String()).String(), + Getter: ccipTH.GetDestLinkBalance, + }, + { + Name: testhelpers.OffRamp, + Address: ccipTH.Dest.OffRamp.Address(), + Expected: destBalances[testhelpers.OffRamp].String(), + Getter: ccipTH.GetDestLinkBalance, + }, + }) + currentSeqNum++ + }) + + t.Run("multiple batches", func(t *testing.T) { + tokenAmount := big.NewInt(500000003) + gasLimit := big.NewInt(250_000) + + var txs []*gethtypes.Transaction + // Enough to require batched executions as gasLimit per tx is 250k -> 500k -> 750k .... + // The actual gas usage of executing 15 messages is higher than the gas limit for + // a single tx. This means that when batching is turned off, and we simply include + // all txs without checking gas, this also fails. + n := 15 + for i := 0; i < n; i++ { + txGasLimit := new(big.Int).Mul(gasLimit, big.NewInt(int64(i+1))) + extraArgs, err2 := testhelpers.GetEVMExtraArgsV1(txGasLimit, false) + require.NoError(t, err2) + msg := router.ClientEVM2AnyMessage{ + Receiver: testhelpers.MustEncodeAddress(t, ccipTH.Dest.Receivers[0].Receiver.Address()), + Data: []byte("hello"), + TokenAmounts: []router.ClientEVMTokenAmount{ + { + Token: ccipTH.Source.LinkToken.Address(), + Amount: tokenAmount, + }, + }, + FeeToken: ccipTH.Source.LinkToken.Address(), + ExtraArgs: extraArgs, + } + fee, err2 := ccipTH.Source.Router.GetFee(nil, testhelpers.DestChainSelector, msg) + require.NoError(t, err2) + // Currently no overhead and 1gwei dest gas price. So fee is simply gasLimit * gasPrice. + // require.Equal(t, new(big.Int).Mul(txGasLimit, gasPrice).String(), fee.String()) + // Approve the fee amount + the token amount + _, err2 = ccipTH.Source.LinkToken.Approve(ccipTH.Source.User, ccipTH.Source.Router.Address(), new(big.Int).Add(fee, tokenAmount)) + require.NoError(t, err2) + ccipTH.Source.Chain.Commit() + tx, err2 := ccipTH.Source.Router.CcipSend(ccipTH.Source.User, ccipTH.Dest.ChainSelector, msg) + require.NoError(t, err2) + ccipTH.Source.Chain.Commit() + txs = append(txs, tx) + } + + // Send a batch of requests in a single block + testhelpers_new.ConfirmTxs(t, txs, ccipTH.Source.Chain) + for i := 0; i < n; i++ { + ccipTH.AllNodesHaveReqSeqNum(t, currentSeqNum+i) + } + // Should see a report with the full range + ccipTH.EventuallyReportCommitted(t, currentSeqNum+n-1) + // Should all be executed + executionLogs := ccipTH.AllNodesHaveExecutedSeqNums(t, currentSeqNum, currentSeqNum+n-1) + for _, execLog := range executionLogs { + ccipTH.AssertExecState(t, execLog, testhelpers.ExecutionStateSuccess) + } + + currentSeqNum += n + }) + + // Deploy new on ramp,Commit store,off ramp + // Delete v1 jobs + // Send a number of requests + // Upgrade the router with new contracts + // create new jobs + // Verify all pending requests are sent after the contracts are upgraded + t.Run("upgrade contracts and verify requests can be sent with upgraded contract", func(t *testing.T) { + ctx := testutils.Context(t) + gasLimit := big.NewInt(200_003) // prime number + tokenAmount := big.NewInt(100) + commitStoreV1 := ccipTH.Dest.CommitStore + offRampV1 := ccipTH.Dest.OffRamp + onRampV1 := ccipTH.Source.OnRamp + // deploy v2 contracts + ccipTH.DeployNewOnRamp(t) + ccipTH.DeployNewCommitStore(t) + ccipTH.DeployNewOffRamp(t) + + // send a request as the v2 contracts are not enabled in router it should route through the v1 contracts + t.Logf("sending request for seqnum %d", currentSeqNum) + ccipTH.SendMessage(t, gasLimit, tokenAmount, ccipTH.Dest.Receivers[0].Receiver.Address()) + ccipTH.Source.Chain.Commit() + ccipTH.Dest.Chain.Commit() + t.Logf("verifying seqnum %d on previous onRamp %s", currentSeqNum, onRampV1.Address().Hex()) + ccipTH.AllNodesHaveReqSeqNum(t, currentSeqNum, onRampV1.Address()) + ccipTH.EventuallyReportCommitted(t, currentSeqNum, commitStoreV1.Address()) + executionLog := ccipTH.AllNodesHaveExecutedSeqNums(t, currentSeqNum, currentSeqNum, offRampV1.Address()) + ccipTH.AssertExecState(t, executionLog[0], testhelpers.ExecutionStateSuccess, offRampV1.Address()) + + nonceAtOnRampV1, err := onRampV1.GetSenderNonce(nil, ccipTH.Source.User.From) + require.NoError(t, err, "getting nonce from onRamp") + require.Equal(t, currentSeqNum, int(nonceAtOnRampV1)) + nonceAtOffRampV1, err := offRampV1.GetSenderNonce(nil, ccipTH.Source.User.From) + require.NoError(t, err, "getting nonce from offRamp") + require.Equal(t, currentSeqNum, int(nonceAtOffRampV1)) + + // enable the newly deployed contracts + newConfigBlock, err := ccipTH.Dest.Chain.Client().BlockNumber(ctx) + require.NoError(t, err) + ccipTH.EnableOnRamp(t) + ccipTH.EnableCommitStore(t) + ccipTH.EnableOffRamp(t) + srcStartBlock, err := ccipTH.Source.Chain.Client().BlockNumber(ctx) + require.NoError(t, err) + + // send a number of requests, the requests should not be delivered yet as the previous contracts are not configured + // with the router anymore + startSeq := 1 + noOfRequests := 5 + endSeqNum := startSeq + noOfRequests + for i := startSeq; i <= endSeqNum; i++ { + t.Logf("sending request for seqnum %d", i) + ccipTH.SendMessage(t, gasLimit, tokenAmount, ccipTH.Dest.Receivers[0].Receiver.Address()) + ccipTH.Source.Chain.Commit() + ccipTH.Dest.Chain.Commit() + ccipTH.EventuallySendRequested(t, uint64(i)) + } + + // delete v1 jobs + for _, node := range ccipTH.Nodes { + id := node.FindJobIDForContract(t, commitStoreV1.Address()) + require.Greater(t, id, int32(0)) + t.Logf("deleting job %d", id) + err = node.App.DeleteJob(context.Background(), id) + require.NoError(t, err) + id = node.FindJobIDForContract(t, offRampV1.Address()) + require.Greater(t, id, int32(0)) + t.Logf("deleting job %d", id) + err = node.App.DeleteJob(context.Background(), id) + require.NoError(t, err) + } + + // Commit on both chains to reach Finality + ccipTH.Source.Chain.Commit() + ccipTH.Dest.Chain.Commit() + + // create new jobs + jobParams = ccipTH.NewCCIPJobSpecParams(tokenPricesUSDPipeline, priceGetterConfigJson, newConfigBlock, "") + jobParams.Version = "v2" + jobParams.SourceStartBlock = srcStartBlock + ccipTH.AddAllJobs(t, jobParams) + committedSeqNum := uint64(0) + // Now the requests should be delivered + for i := startSeq; i <= endSeqNum; i++ { + t.Logf("verifying seqnum %d", i) + ccipTH.AllNodesHaveReqSeqNum(t, i) + if committedSeqNum < uint64(i+1) { + committedSeqNum = ccipTH.EventuallyReportCommitted(t, i) + } + ccipTH.EventuallyExecutionStateChangedToSuccess(t, []uint64{uint64(i)}, uint64(newConfigBlock)) + } + + // nonces should be correctly synced from v1 contracts for the sender + nonceAtOnRampV2, err := ccipTH.Source.OnRamp.GetSenderNonce(nil, ccipTH.Source.User.From) + require.NoError(t, err, "getting nonce from onRamp") + nonceAtOffRampV2, err := ccipTH.Dest.OffRamp.GetSenderNonce(nil, ccipTH.Source.User.From) + require.NoError(t, err, "getting nonce from offRamp") + require.Equal(t, nonceAtOnRampV1+uint64(noOfRequests)+1, nonceAtOnRampV2, "nonce should be synced from v1 onRamps") + require.Equal(t, nonceAtOffRampV1+uint64(noOfRequests)+1, nonceAtOffRampV2, "nonce should be synced from v1 offRamps") + currentSeqNum = endSeqNum + 1 + }) + + t.Run("pay nops", func(t *testing.T) { + linkToTransferToOnRamp := big.NewInt(1e18) + + // transfer some link to onramp to pay the nops + _, err := ccipTH.Source.LinkToken.Transfer(ccipTH.Source.User, ccipTH.Source.OnRamp.Address(), linkToTransferToOnRamp) + require.NoError(t, err) + ccipTH.Source.Chain.Commit() + + srcBalReq := []testhelpers.BalanceReq{ + { + Name: testhelpers.Sender, + Addr: ccipTH.Source.User.From, + Getter: ccipTH.GetSourceWrappedTokenBalance, + }, + { + Name: testhelpers.OnRampNative, + Addr: ccipTH.Source.OnRamp.Address(), + Getter: ccipTH.GetSourceWrappedTokenBalance, + }, + { + Name: testhelpers.OnRamp, + Addr: ccipTH.Source.OnRamp.Address(), + Getter: ccipTH.GetSourceLinkBalance, + }, + { + Name: testhelpers.SourceRouter, + Addr: ccipTH.Source.Router.Address(), + Getter: ccipTH.GetSourceWrappedTokenBalance, + }, + } + + var nopsAndWeights []evm_2_evm_onramp.EVM2EVMOnRampNopAndWeight + var totalWeight uint16 + nodes := ccipTH.Nodes + for i := range nodes { + // For now set the transmitter addresses to be the same as the payee addresses + nodes[i].PaymentReceiver = nodes[i].Transmitter + nopsAndWeights = append(nopsAndWeights, evm_2_evm_onramp.EVM2EVMOnRampNopAndWeight{ + Nop: nodes[i].PaymentReceiver, + Weight: 5, + }) + totalWeight += 5 + srcBalReq = append(srcBalReq, testhelpers.BalanceReq{ + Name: fmt.Sprintf("node %d", i), + Addr: nodes[i].PaymentReceiver, + Getter: ccipTH.GetSourceLinkBalance, + }) + } + srcBalances, err := testhelpers.GetBalances(t, srcBalReq) + require.NoError(t, err) + + // set nops on the onramp + ccipTH.SetNopsOnRamp(t, nopsAndWeights) + + // send a message + extraArgs, err := testhelpers.GetEVMExtraArgsV1(big.NewInt(200_000), true) + require.NoError(t, err) + + // FeeToken is empty, indicating it should use native token + msg := router.ClientEVM2AnyMessage{ + Receiver: testhelpers.MustEncodeAddress(t, ccipTH.Dest.Receivers[1].Receiver.Address()), + Data: []byte("hello"), + TokenAmounts: []router.ClientEVMTokenAmount{}, + ExtraArgs: extraArgs, + FeeToken: common.Address{}, + } + fee, err := ccipTH.Source.Router.GetFee(nil, testhelpers.DestChainSelector, msg) + require.NoError(t, err) + + // verify message is sent + ccipTH.Source.User.Value = fee + ccipTH.SendRequest(t, msg) + ccipTH.Source.User.Value = nil + ccipTH.AllNodesHaveReqSeqNum(t, currentSeqNum) + ccipTH.EventuallyReportCommitted(t, currentSeqNum) + + executionLogs := ccipTH.AllNodesHaveExecutedSeqNums(t, currentSeqNum, currentSeqNum) + assert.Len(t, executionLogs, 1) + ccipTH.AssertExecState(t, executionLogs[0], testhelpers.ExecutionStateSuccess) + currentSeqNum++ + + // get the nop fee + nopFee, err := ccipTH.Source.OnRamp.GetNopFeesJuels(nil) + require.NoError(t, err) + t.Log("nopFee", nopFee) + + // withdraw fees and verify there is still fund left for nop payment + _, err = ccipTH.Source.OnRamp.WithdrawNonLinkFees( + ccipTH.Source.User, + ccipTH.Source.WrappedNative.Address(), + ccipTH.Source.User.From, + ) + require.NoError(t, err) + ccipTH.Source.Chain.Commit() + + // pay nops + _, err = ccipTH.Source.OnRamp.PayNops(ccipTH.Source.User) + require.NoError(t, err) + ccipTH.Source.Chain.Commit() + + srcBalanceAssertions := []testhelpers.BalanceAssertion{ + { + // Onramp should not have any balance left in wrapped native + Name: testhelpers.OnRampNative, + Address: ccipTH.Source.OnRamp.Address(), + Expected: big.NewInt(0).String(), + Getter: ccipTH.GetSourceWrappedTokenBalance, + }, + { + // Onramp should have the remaining link after paying nops + Name: testhelpers.OnRamp, + Address: ccipTH.Source.OnRamp.Address(), + Expected: new(big.Int).Sub(srcBalances[testhelpers.OnRamp], nopFee).String(), + Getter: ccipTH.GetSourceLinkBalance, + }, + { + Name: testhelpers.SourceRouter, + Address: ccipTH.Source.Router.Address(), + Expected: srcBalances[testhelpers.SourceRouter].String(), + Getter: ccipTH.GetSourceWrappedTokenBalance, + }, + // onRamp's balance (of previously sent fee during message sending) should have been transferred to + // the owner as a result of WithdrawNonLinkFees + { + Name: testhelpers.Sender, + Address: ccipTH.Source.User.From, + Expected: fee.String(), + Getter: ccipTH.GetSourceWrappedTokenBalance, + }, + } + + // the nodes should be paid according to the weights assigned + for i, node := range nodes { + paymentWeight := float64(nopsAndWeights[i].Weight) / float64(totalWeight) + paidInFloat := paymentWeight * float64(nopFee.Int64()) + paid, _ := new(big.Float).SetFloat64(paidInFloat).Int64() + bal := new(big.Int).Add( + new(big.Int).SetInt64(paid), + srcBalances[fmt.Sprintf("node %d", i)]).String() + srcBalanceAssertions = append(srcBalanceAssertions, testhelpers.BalanceAssertion{ + Name: fmt.Sprintf("node %d", i), + Address: node.PaymentReceiver, + Expected: bal, + Getter: ccipTH.GetSourceLinkBalance, + }) + } + ccipTH.AssertBalances(t, srcBalanceAssertions) + }) + + // Keep on sending a bunch of messages + // In the meantime update onchainConfig with new price registry address + // Verify if the jobs can pick up updated config + // Verify if all the messages are sent + t.Run("config change or price registry update while requests are inflight", func(t *testing.T) { + gasLimit := big.NewInt(200_003) // prime number + tokenAmount := big.NewInt(100) + msgWg := &sync.WaitGroup{} + msgWg.Add(1) + ticker := time.NewTicker(100 * time.Millisecond) + defer ticker.Stop() + startSeq := currentSeqNum + endSeq := currentSeqNum + 20 + + // send message with the old configs + ccipTH.SendMessage(t, gasLimit, tokenAmount, ccipTH.Dest.Receivers[0].Receiver.Address()) + ccipTH.Source.Chain.Commit() + + go func(ccipContracts testhelpers.CCIPContracts, currentSeqNum int) { + seqNumber := currentSeqNum + 1 + defer msgWg.Done() + for { + <-ticker.C // wait for ticker + t.Logf("sending request for seqnum %d", seqNumber) + ccipContracts.SendMessage(t, gasLimit, tokenAmount, ccipTH.Dest.Receivers[0].Receiver.Address()) + ccipContracts.Source.Chain.Commit() + seqNumber++ + if seqNumber == endSeq { + return + } + } + }(ccipTH.CCIPContracts, currentSeqNum) + + ccipTH.DeployNewPriceRegistry(t) + commitOnchainConfig := ccipTH.CreateDefaultCommitOnchainConfig(t) + commitOffchainConfig := ccipTH.CreateDefaultCommitOffchainConfig(t) + execOnchainConfig := ccipTH.CreateDefaultExecOnchainConfig(t) + execOffchainConfig := ccipTH.CreateDefaultExecOffchainConfig(t) + + ccipTH.SetupOnchainConfig(t, commitOnchainConfig, commitOffchainConfig, execOnchainConfig, execOffchainConfig) + + // wait for all requests to be complete + msgWg.Wait() + for i := startSeq; i < endSeq; i++ { + ccipTH.AllNodesHaveReqSeqNum(t, i) + ccipTH.EventuallyReportCommitted(t, i) + + executionLogs := ccipTH.AllNodesHaveExecutedSeqNums(t, i, i) + assert.Len(t, executionLogs, 1) + ccipTH.AssertExecState(t, executionLogs[0], testhelpers.ExecutionStateSuccess) + } + + for i, node := range ccipTH.Nodes { + t.Logf("verifying node %d", i) + node.EventuallyNodeUsesNewCommitConfig(t, ccipTH, ccipdata.CommitOnchainConfig{ + PriceRegistry: ccipTH.Dest.PriceRegistry.Address(), + }) + node.EventuallyNodeUsesNewExecConfig(t, ccipTH, v1_2_0.ExecOnchainConfig{ + PermissionLessExecutionThresholdSeconds: testhelpers.PermissionLessExecutionThresholdSeconds, + Router: ccipTH.Dest.Router.Address(), + PriceRegistry: ccipTH.Dest.PriceRegistry.Address(), + MaxDataBytes: 1e5, + MaxNumberOfTokensPerMsg: 5, + MaxPoolReleaseOrMintGas: 200_000, + }) + node.EventuallyNodeUsesUpdatedPriceRegistry(t, ccipTH) + } + currentSeqNum = endSeq + }) + }) + } +} diff --git a/core/services/ocr2/plugins/ccip/integration_test.go b/core/services/ocr2/plugins/ccip/integration_test.go index b116a470363..e644a3e6f4a 100644 --- a/core/services/ocr2/plugins/ccip/integration_test.go +++ b/core/services/ocr2/plugins/ccip/integration_test.go @@ -29,7 +29,6 @@ import ( ) func TestIntegration_CCIP(t *testing.T) { - t.Parallel() // Run tke batches of tests for both pipeline and dynamic price getter setups. // We will remove the pipeline batch once the feature is deleted from the code. tests := []struct { @@ -651,7 +650,6 @@ func TestIntegration_CCIP(t *testing.T) { // TestReorg ensures that CCIP works even when a below finality depth reorg happens func TestReorg(t *testing.T) { - t.Parallel() // We need higher finality depth on the destination to perform reorg deep enough to revert commit and execution reports destinationFinalityDepth := uint32(50) ccipTH := integrationtesthelpers.SetupCCIPIntegrationTH( diff --git a/core/services/ocr2/plugins/ccip/metrics_test.go b/core/services/ocr2/plugins/ccip/metrics_test.go index 0487df2b28d..eec67db7dd0 100644 --- a/core/services/ocr2/plugins/ccip/metrics_test.go +++ b/core/services/ocr2/plugins/ccip/metrics_test.go @@ -13,7 +13,6 @@ const ( ) func Test_SequenceNumbers(t *testing.T) { - t.Parallel() collector := NewPluginMetricsCollector("test", sourceChainId, destChainId) collector.SequenceNumber(Report, 10) @@ -24,7 +23,6 @@ func Test_SequenceNumbers(t *testing.T) { } func Test_NumberOfMessages(t *testing.T) { - t.Parallel() collector := NewPluginMetricsCollector("test", sourceChainId, destChainId) collector2 := NewPluginMetricsCollector("test2", destChainId, sourceChainId) @@ -39,7 +37,6 @@ func Test_NumberOfMessages(t *testing.T) { } func Test_UnexpiredCommitRoots(t *testing.T) { - t.Parallel() collector := NewPluginMetricsCollector("test", sourceChainId, destChainId) collector.UnexpiredCommitRoots(10) diff --git a/core/services/ocr2/plugins/ccip/observations_test.go b/core/services/ocr2/plugins/ccip/observations_test.go index c39be8e5a2c..a3143f157d7 100644 --- a/core/services/ocr2/plugins/ccip/observations_test.go +++ b/core/services/ocr2/plugins/ccip/observations_test.go @@ -22,7 +22,6 @@ import ( ) func TestObservationFilter(t *testing.T) { - t.Parallel() lggr := logger.TestLogger(t) obs1 := CommitObservation{Interval: cciptypes.CommitStoreInterval{Min: 1, Max: 10}} b1, err := obs1.Marshal() @@ -40,7 +39,6 @@ type CommitObservationLegacy struct { } func TestObservationCompat_MultiChainGas(t *testing.T) { - t.Parallel() obsLegacy := CommitObservationLegacy{ Interval: cciptypes.CommitStoreInterval{ Min: 1, @@ -68,7 +66,6 @@ func TestObservationCompat_MultiChainGas(t *testing.T) { } func TestCommitObservationJsonDeserialization(t *testing.T) { - t.Parallel() expectedObservation := CommitObservation{ Interval: cciptypes.CommitStoreInterval{ Min: 1, @@ -96,7 +93,6 @@ func TestCommitObservationJsonDeserialization(t *testing.T) { } func TestCommitObservationMarshal(t *testing.T) { - t.Parallel() obs := CommitObservation{ Interval: cciptypes.CommitStoreInterval{ Min: 1, @@ -124,7 +120,6 @@ func TestCommitObservationMarshal(t *testing.T) { } func TestExecutionObservationJsonDeserialization(t *testing.T) { - t.Parallel() expectedObservation := ExecutionObservation{Messages: map[uint64]MsgData{ 2: {TokenData: tokenData("c")}, 1: {TokenData: tokenData("c")}, @@ -147,7 +142,6 @@ func TestExecutionObservationJsonDeserialization(t *testing.T) { } func TestObservationSize(t *testing.T) { - t.Parallel() testParams := gopter.DefaultTestParameters() testParams.MinSuccessfulTests = 100 p := gopter.NewProperties(testParams) @@ -172,7 +166,6 @@ func TestObservationSize(t *testing.T) { } func TestNewExecutionObservation(t *testing.T) { - t.Parallel() tests := []struct { name string observations []ObservedMessage @@ -229,7 +222,6 @@ func tokenData(value string) [][]byte { } func TestCommitObservationJsonSerializationDeserialization(t *testing.T) { - t.Parallel() jsonEncoded := `{ "interval": { "Min":1, @@ -284,7 +276,6 @@ func TestCommitObservationJsonSerializationDeserialization(t *testing.T) { } func TestAddressEncodingBackwardsCompatibility(t *testing.T) { - t.Parallel() // The intention of this test is to remind including proper formatting of addresses after config is updated. // // The following tests will fail when a new cciptypes.Address field is added or removed. diff --git a/core/services/ocr2/plugins/ccip/testhelpers/ccip_contracts.go b/core/services/ocr2/plugins/ccip/testhelpers/ccip_contracts.go index c2fec2903e8..eaa7b10b0df 100644 --- a/core/services/ocr2/plugins/ccip/testhelpers/ccip_contracts.go +++ b/core/services/ocr2/plugins/ccip/testhelpers/ccip_contracts.go @@ -5,7 +5,6 @@ import ( "fmt" "math" "math/big" - "sync" "testing" "time" @@ -169,32 +168,11 @@ type MaybeRevertReceiver struct { Strict bool } -// Backend wraps a simulated backend with a mutex to make it safe for concurrent use -// Commit() in particular has caused races. -type Backend struct { - mu sync.Mutex - *simulated.Backend -} - -func NewBackend(sim *simulated.Backend) *Backend { - return &Backend{ - mu: sync.Mutex{}, - Backend: sim, - } -} - -func (b *Backend) Commit() common.Hash { - b.mu.Lock() - defer b.mu.Unlock() - - return b.Backend.Commit() -} - type Common struct { ChainID uint64 ChainSelector uint64 User *bind.TransactOpts - Chain *Backend + Chain *simulated.Backend LinkToken *link_token_interface.LinkToken LinkTokenPool *lock_release_token_pool.LockReleaseTokenPool CustomToken *link_token_interface.LinkToken @@ -811,14 +789,10 @@ func SetupCCIPContracts(t *testing.T, sourceChainID, sourceChainSelector, destCh // │ Deploy Pools │ // ================================================================ - // All the tokens deployed above have 18 decimals - tokenDecimals := uint8(18) - sourcePoolLinkAddress, _, _, err := lock_release_token_pool.DeployLockReleaseTokenPool( sourceUser, sourceChain.Client(), sourceLinkTokenAddress, - tokenDecimals, []common.Address{}, armProxySourceAddress, true, @@ -835,7 +809,6 @@ func SetupCCIPContracts(t *testing.T, sourceChainID, sourceChainSelector, destCh sourceUser, sourceChain.Client(), sourceWeth9addr, - tokenDecimals, []common.Address{}, armProxySourceAddress, true, @@ -854,7 +827,6 @@ func SetupCCIPContracts(t *testing.T, sourceChainID, sourceChainSelector, destCh destUser, destChain.Client(), destLinkTokenAddress, - tokenDecimals, []common.Address{}, armProxyDestAddress, true, @@ -886,7 +858,6 @@ func SetupCCIPContracts(t *testing.T, sourceChainID, sourceChainSelector, destCh destUser, destChain.Client(), destWeth9addr, - tokenDecimals, []common.Address{}, armProxyDestAddress, true, @@ -921,11 +892,11 @@ func SetupCCIPContracts(t *testing.T, sourceChainID, sourceChainSelector, destCh require.NoError(t, err) _, err = sourceLinkPool.ApplyChainUpdates( sourceUser, - []uint64{}, []lock_release_token_pool.TokenPoolChainUpdate{{ RemoteChainSelector: DestChainSelector, - RemotePoolAddresses: [][]byte{abiEncodedDestLinkPool}, + RemotePoolAddress: abiEncodedDestLinkPool, RemoteTokenAddress: abiEncodedDestLinkTokenAddress, + Allowed: true, OutboundRateLimiterConfig: lock_release_token_pool.RateLimiterConfig{ IsEnabled: true, Capacity: HundredLink, @@ -946,11 +917,11 @@ func SetupCCIPContracts(t *testing.T, sourceChainID, sourceChainSelector, destCh require.NoError(t, err) _, err = sourceWeth9Pool.ApplyChainUpdates( sourceUser, - []uint64{}, []lock_release_token_pool.TokenPoolChainUpdate{{ RemoteChainSelector: DestChainSelector, - RemotePoolAddresses: [][]byte{abiEncodedDestWrappedPool}, + RemotePoolAddress: abiEncodedDestWrappedPool, RemoteTokenAddress: abiEncodedDestWrappedTokenAddr, + Allowed: true, OutboundRateLimiterConfig: lock_release_token_pool.RateLimiterConfig{ IsEnabled: true, Capacity: HundredLink, @@ -972,11 +943,11 @@ func SetupCCIPContracts(t *testing.T, sourceChainID, sourceChainSelector, destCh require.NoError(t, err) _, err = destLinkPool.ApplyChainUpdates( destUser, - []uint64{}, []lock_release_token_pool.TokenPoolChainUpdate{{ RemoteChainSelector: SourceChainSelector, - RemotePoolAddresses: [][]byte{abiEncodedSourceLinkPool}, + RemotePoolAddress: abiEncodedSourceLinkPool, RemoteTokenAddress: abiEncodedSourceLinkTokenAddr, + Allowed: true, OutboundRateLimiterConfig: lock_release_token_pool.RateLimiterConfig{ IsEnabled: true, Capacity: HundredLink, @@ -997,11 +968,11 @@ func SetupCCIPContracts(t *testing.T, sourceChainID, sourceChainSelector, destCh require.NoError(t, err) _, err = destWrappedPool.ApplyChainUpdates( destUser, - []uint64{}, []lock_release_token_pool.TokenPoolChainUpdate{{ RemoteChainSelector: SourceChainSelector, - RemotePoolAddresses: [][]byte{abiEncodedSourceWrappedPool}, + RemotePoolAddress: abiEncodedSourceWrappedPool, RemoteTokenAddress: abiEncodedSourceWrappedTokenAddr, + Allowed: true, OutboundRateLimiterConfig: lock_release_token_pool.RateLimiterConfig{ IsEnabled: true, Capacity: HundredLink, @@ -1216,7 +1187,7 @@ func SetupCCIPContracts(t *testing.T, sourceChainID, sourceChainSelector, destCh ChainID: sourceChainID, ChainSelector: sourceChainSelector, User: sourceUser, - Chain: NewBackend(sourceChain), + Chain: sourceChain, LinkToken: sourceLinkToken, LinkTokenPool: sourceLinkPool, CustomToken: sourceCustomToken, @@ -1236,7 +1207,7 @@ func SetupCCIPContracts(t *testing.T, sourceChainID, sourceChainSelector, destCh ChainID: destChainID, ChainSelector: destChainSelector, User: destUser, - Chain: NewBackend(destChain), + Chain: destChain, LinkToken: destLinkToken, LinkTokenPool: destLinkPool, CustomToken: destCustomToken, diff --git a/core/services/ocr2/plugins/ccip/testhelpers/integration/chainlink.go b/core/services/ocr2/plugins/ccip/testhelpers/integration/chainlink.go index d21c5b12513..fb59c0d0783 100644 --- a/core/services/ocr2/plugins/ccip/testhelpers/integration/chainlink.go +++ b/core/services/ocr2/plugins/ccip/testhelpers/integration/chainlink.go @@ -17,16 +17,17 @@ import ( "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" types3 "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/ethclient/simulated" "github.com/google/uuid" "github.com/hashicorp/consul/sdk/freeport" "github.com/jmoiron/sqlx" "github.com/onsi/gomega" "github.com/pkg/errors" - "k8s.io/utils/ptr" "github.com/stretchr/testify/mock" "github.com/stretchr/testify/require" "go.uber.org/zap" + "k8s.io/utils/pointer" //nolint:staticcheck "github.com/smartcontractkit/libocr/commontypes" "github.com/smartcontractkit/libocr/offchainreporting2/confighelper" @@ -368,7 +369,7 @@ func setupNodeCCIP( owner *bind.TransactOpts, port int64, dbName string, - sourceChain *testhelpers.Backend, destChain *testhelpers.Backend, + sourceChain *simulated.Backend, destChain *simulated.Backend, sourceChainID *big.Int, destChainID *big.Int, bootstrapPeerID string, bootstrapPort int64, @@ -386,7 +387,7 @@ func setupNodeCCIP( c.Feature.UICSAKeys = &trueRef c.Feature.FeedsManager = &trueRef c.OCR.Enabled = &falseRef - c.OCR.DefaultTransactionQueueDepth = ptr.To[uint32](200) + c.OCR.DefaultTransactionQueueDepth = pointer.Uint32(200) c.OCR2.Enabled = &trueRef c.Feature.LogPoller = &trueRef c.P2P.V2.Enabled = &trueRef diff --git a/core/services/ocr2/plugins/ccip/testhelpers/integration/jobspec.go b/core/services/ocr2/plugins/ccip/testhelpers/integration/jobspec.go index a520580e614..b10f51a9426 100644 --- a/core/services/ocr2/plugins/ccip/testhelpers/integration/jobspec.go +++ b/core/services/ocr2/plugins/ccip/testhelpers/integration/jobspec.go @@ -2,13 +2,11 @@ package integrationtesthelpers import ( "bytes" - "crypto/sha256" "fmt" "text/template" "time" "github.com/ethereum/go-ethereum/common" - "github.com/google/uuid" "github.com/lib/pq" "github.com/smartcontractkit/chainlink-common/pkg/types" @@ -30,7 +28,6 @@ type OCR2TaskJobSpec struct { ForwardingAllowed bool `toml:"forwardingAllowed"` OCR2OracleSpec job.OCR2OracleSpec ObservationSource string `toml:"observationSource"` // List of commands for the Chainlink node - ExternalJobID string `toml:"externalJobID"` } // Type returns the type of the job @@ -42,14 +39,9 @@ func (o *OCR2TaskJobSpec) String() (string, error) { if o.OCR2OracleSpec.FeedID != nil { feedID = o.OCR2OracleSpec.FeedID.Hex() } - externalID, err := ExternalJobID(o.Name) - if err != nil { - return "", err - } specWrap := struct { Name string JobType string - ExternalJobID string MaxTaskDuration string ForwardingAllowed bool ContractID string @@ -70,7 +62,6 @@ func (o *OCR2TaskJobSpec) String() (string, error) { }{ Name: o.Name, JobType: o.JobType, - ExternalJobID: externalID, ForwardingAllowed: o.ForwardingAllowed, MaxTaskDuration: o.MaxTaskDuration, ContractID: o.OCR2OracleSpec.ContractID, @@ -91,7 +82,6 @@ func (o *OCR2TaskJobSpec) String() (string, error) { ocr2TemplateString := ` type = "{{ .JobType }}" name = "{{.Name}}" -externalJobID = "{{.ExternalJobID}}" forwardingAllowed = {{.ForwardingAllowed}} {{if .MaxTaskDuration}} maxTaskDuration = "{{ .MaxTaskDuration }}" {{end}} @@ -342,18 +332,3 @@ func (c *CCIPIntegrationTestHarness) NewCCIPJobSpecParams(tokenPricesUSDPipeline USDCAttestationAPI: usdcAttestationAPI, } } - -func ExternalJobID(jobName string) (string, error) { - in := []byte(jobName) - sha256Hash := sha256.New() - sha256Hash.Write(in) - in = sha256Hash.Sum(nil)[:16] - // tag as valid UUID v4 https://github.com/google/uuid/blob/0f11ee6918f41a04c201eceeadf612a377bc7fbc/version4.go#L53-L54 - in[6] = (in[6] & 0x0f) | 0x40 // Version 4 - in[8] = (in[8] & 0x3f) | 0x80 // Variant is 10 - id, err := uuid.FromBytes(in) - if err != nil { - return "", err - } - return id.String(), nil -} diff --git a/core/services/ocr2/plugins/ccip/testhelpers/simulated_backend.go b/core/services/ocr2/plugins/ccip/testhelpers/simulated_backend.go index 699af7e14dc..58206d37427 100644 --- a/core/services/ocr2/plugins/ccip/testhelpers/simulated_backend.go +++ b/core/services/ocr2/plugins/ccip/testhelpers/simulated_backend.go @@ -56,7 +56,7 @@ func (ks EthKeyStoreSim) Eth() keystore.Eth { var _ keystore.Eth = EthKeyStoreSim{}.ETHKS -func ConfirmTxs(t *testing.T, txs []*ethtypes.Transaction, chain *Backend) { +func ConfirmTxs(t *testing.T, txs []*ethtypes.Transaction, chain *simulated.Backend) { chain.Commit() ctx := tests.Context(t) for _, tx := range txs { diff --git a/core/services/ocr2/plugins/ccip/testhelpers/testhelpers_1_4_0/ccip_contracts_1_4_0.go b/core/services/ocr2/plugins/ccip/testhelpers/testhelpers_1_4_0/ccip_contracts_1_4_0.go new file mode 100644 index 00000000000..5ed20875498 --- /dev/null +++ b/core/services/ocr2/plugins/ccip/testhelpers/testhelpers_1_4_0/ccip_contracts_1_4_0.go @@ -0,0 +1,1620 @@ +package testhelpers_1_4_0 + +import ( + "context" + "fmt" + "math" + "math/big" + "testing" + "time" + + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/ethclient/simulated" + "github.com/pkg/errors" + "github.com/rs/zerolog/log" + "github.com/stretchr/testify/require" + + "github.com/smartcontractkit/libocr/offchainreporting2/confighelper" + ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2/types" + ocr2types "github.com/smartcontractkit/libocr/offchainreporting2plus/types" + + "github.com/smartcontractkit/chainlink-common/pkg/config" + "github.com/smartcontractkit/chainlink-common/pkg/hashutil" + "github.com/smartcontractkit/chainlink-common/pkg/merklemulti" + cciptypes "github.com/smartcontractkit/chainlink-common/pkg/types/ccip" + "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" + + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" + burn_mint_token_pool "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/burn_mint_token_pool_1_4_0" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/commit_store_1_2_0" + evm_2_evm_offramp "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/evm_2_evm_offramp_1_2_0" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/evm_2_evm_onramp_1_2_0" + evm_2_evm_onramp "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/evm_2_evm_onramp_1_2_0" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/lock_release_token_pool_1_0_0" + lock_release_token_pool "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/lock_release_token_pool_1_4_0" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/maybe_revert_message_receiver" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/mock_rmn_contract" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/price_registry_1_2_0" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/rmn_proxy_contract" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/router" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/weth9" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/link_token_interface" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/shared/generated/burn_mint_erc677" + "github.com/smartcontractkit/chainlink/v2/core/logger" + "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/abihelpers" + ccipconfig "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/config" + "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/ccipdata" + "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_2_0" + "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/testhelpers" +) + +var ( + // Source + SourcePool = "source Link pool" + SourcePriceRegistry = "source PriceRegistry" + OnRamp = "onramp" + OnRampNative = "onramp-native" + SourceRouter = "source router" + + // Dest + OffRamp = "offramp" + DestPool = "dest Link pool" + + Receiver = "receiver" + Sender = "sender" + Link = func(amount int64) *big.Int { return new(big.Int).Mul(big.NewInt(1e18), big.NewInt(amount)) } + HundredLink = Link(100) + LinkUSDValue = func(amount int64) *big.Int { return new(big.Int).Mul(big.NewInt(1e18), big.NewInt(amount)) } + SourceChainID = uint64(1000) + SourceChainSelector = uint64(11787463284727550157) + DestChainID = uint64(1337) + DestChainSelector = uint64(3379446385462418246) +) + +// Backwards compat, in principle these statuses are version dependent +// TODO: Adjust integration tests to be version agnostic using readers +var ( + ExecutionStateSuccess = MessageExecutionState(cciptypes.ExecutionStateSuccess) + ExecutionStateFailure = MessageExecutionState(cciptypes.ExecutionStateFailure) +) + +type MessageExecutionState cciptypes.MessageExecutionState +type CommitOffchainConfig struct { + v1_2_0.JSONCommitOffchainConfig +} + +func (c CommitOffchainConfig) Encode() ([]byte, error) { + return ccipconfig.EncodeOffchainConfig(c.JSONCommitOffchainConfig) +} + +func NewCommitOffchainConfig( + GasPriceHeartBeat config.Duration, + DAGasPriceDeviationPPB uint32, + ExecGasPriceDeviationPPB uint32, + TokenPriceHeartBeat config.Duration, + TokenPriceDeviationPPB uint32, + InflightCacheExpiry config.Duration, + priceReportingDisabled bool) CommitOffchainConfig { + return CommitOffchainConfig{v1_2_0.JSONCommitOffchainConfig{ + GasPriceHeartBeat: GasPriceHeartBeat, + DAGasPriceDeviationPPB: DAGasPriceDeviationPPB, + ExecGasPriceDeviationPPB: ExecGasPriceDeviationPPB, + TokenPriceHeartBeat: TokenPriceHeartBeat, + TokenPriceDeviationPPB: TokenPriceDeviationPPB, + InflightCacheExpiry: InflightCacheExpiry, + PriceReportingDisabled: priceReportingDisabled, + }} +} + +type CommitOnchainConfig struct { + ccipdata.CommitOnchainConfig +} + +func NewCommitOnchainConfig( + PriceRegistry common.Address, +) CommitOnchainConfig { + return CommitOnchainConfig{ccipdata.CommitOnchainConfig{ + PriceRegistry: PriceRegistry, + }} +} + +type ExecOnchainConfig struct { + v1_2_0.ExecOnchainConfig +} + +func NewExecOnchainConfig( + PermissionLessExecutionThresholdSeconds uint32, + Router common.Address, + PriceRegistry common.Address, + MaxNumberOfTokensPerMsg uint16, + MaxDataBytes uint32, + MaxPoolReleaseOrMintGas uint32, +) ExecOnchainConfig { + return ExecOnchainConfig{v1_2_0.ExecOnchainConfig{ + PermissionLessExecutionThresholdSeconds: PermissionLessExecutionThresholdSeconds, + Router: Router, + PriceRegistry: PriceRegistry, + MaxNumberOfTokensPerMsg: MaxNumberOfTokensPerMsg, + MaxDataBytes: MaxDataBytes, + MaxPoolReleaseOrMintGas: MaxPoolReleaseOrMintGas, + }} +} + +type ExecOffchainConfig struct { + v1_2_0.JSONExecOffchainConfig +} + +func (c ExecOffchainConfig) Encode() ([]byte, error) { + return ccipconfig.EncodeOffchainConfig(c.JSONExecOffchainConfig) +} + +func NewExecOffchainConfig( + DestOptimisticConfirmations uint32, + BatchGasLimit uint32, + RelativeBoostPerWaitHour float64, + InflightCacheExpiry config.Duration, + RootSnoozeTime config.Duration, + BatchingStrategyID uint32, +) ExecOffchainConfig { + return ExecOffchainConfig{v1_2_0.JSONExecOffchainConfig{ + DestOptimisticConfirmations: DestOptimisticConfirmations, + BatchGasLimit: BatchGasLimit, + RelativeBoostPerWaitHour: RelativeBoostPerWaitHour, + InflightCacheExpiry: InflightCacheExpiry, + RootSnoozeTime: RootSnoozeTime, + BatchingStrategyID: BatchingStrategyID, + }} +} + +type MaybeRevertReceiver struct { + Receiver *maybe_revert_message_receiver.MaybeRevertMessageReceiver + Strict bool +} + +type Common struct { + ChainID uint64 + ChainSelector uint64 + User *bind.TransactOpts + Chain *simulated.Backend + LinkToken *link_token_interface.LinkToken + LinkTokenPool *lock_release_token_pool.LockReleaseTokenPool + CustomToken *link_token_interface.LinkToken + WrappedNative *weth9.WETH9 + WrappedNativePool *lock_release_token_pool_1_0_0.LockReleaseTokenPool + ARM *mock_rmn_contract.MockRMNContract + ARMProxy *rmn_proxy_contract.RMNProxyContract + PriceRegistry *price_registry_1_2_0.PriceRegistry +} + +type SourceChain struct { + Common + Router *router.Router + OnRamp *evm_2_evm_onramp.EVM2EVMOnRamp +} + +type DestinationChain struct { + Common + + CommitStore *commit_store_1_2_0.CommitStore + Router *router.Router + OffRamp *evm_2_evm_offramp.EVM2EVMOffRamp + Receivers []MaybeRevertReceiver +} + +type OCR2Config struct { + Signers []common.Address + Transmitters []common.Address + F uint8 + OnchainConfig []byte + OffchainConfigVersion uint64 + OffchainConfig []byte +} + +type BalanceAssertion struct { + Name string + Address common.Address + Expected string + Getter func(t *testing.T, addr common.Address) *big.Int + Within string +} + +type BalanceReq struct { + Name string + Addr common.Address + Getter func(t *testing.T, addr common.Address) *big.Int +} + +type CCIPContracts struct { + Source SourceChain + Dest DestinationChain + Oracles []confighelper.OracleIdentityExtra + + commitOCRConfig, execOCRConfig *OCR2Config +} + +func (c *CCIPContracts) DeployNewOffRamp(t *testing.T) { + prevOffRamp := common.HexToAddress("") + if c.Dest.OffRamp != nil { + prevOffRamp = c.Dest.OffRamp.Address() + } + offRampAddress, _, _, err := evm_2_evm_offramp.DeployEVM2EVMOffRamp( + c.Dest.User, + c.Dest.Chain.Client(), + evm_2_evm_offramp.EVM2EVMOffRampStaticConfig{ + CommitStore: c.Dest.CommitStore.Address(), + ChainSelector: c.Dest.ChainSelector, + SourceChainSelector: c.Source.ChainSelector, + OnRamp: c.Source.OnRamp.Address(), + PrevOffRamp: prevOffRamp, + ArmProxy: c.Dest.ARMProxy.Address(), + }, + []common.Address{c.Source.LinkToken.Address()}, // source tokens + []common.Address{c.Dest.LinkTokenPool.Address()}, // pools + evm_2_evm_offramp.RateLimiterConfig{ + IsEnabled: true, + Capacity: LinkUSDValue(100), + Rate: LinkUSDValue(1), + }, + ) + require.NoError(t, err) + c.Dest.Chain.Commit() + + c.Dest.OffRamp, err = evm_2_evm_offramp.NewEVM2EVMOffRamp(offRampAddress, c.Dest.Chain.Client()) + require.NoError(t, err) + + c.Dest.Chain.Commit() + c.Source.Chain.Commit() +} + +func (c *CCIPContracts) EnableOffRamp(t *testing.T) { + _, err := c.Dest.Router.ApplyRampUpdates(c.Dest.User, nil, nil, []router.RouterOffRamp{{SourceChainSelector: SourceChainSelector, OffRamp: c.Dest.OffRamp.Address()}}) + require.NoError(t, err) + c.Dest.Chain.Commit() + + onChainConfig := c.CreateDefaultExecOnchainConfig(t) + offChainConfig := c.CreateDefaultExecOffchainConfig(t) + + c.SetupExecOCR2Config(t, onChainConfig, offChainConfig) +} + +func (c *CCIPContracts) EnableCommitStore(t *testing.T) { + onChainConfig := c.CreateDefaultCommitOnchainConfig(t) + offChainConfig := c.CreateDefaultCommitOffchainConfig(t) + + c.SetupCommitOCR2Config(t, onChainConfig, offChainConfig) + + _, err := c.Dest.PriceRegistry.ApplyPriceUpdatersUpdates(c.Dest.User, []common.Address{c.Dest.CommitStore.Address()}, []common.Address{}) + require.NoError(t, err) + c.Dest.Chain.Commit() +} + +func (c *CCIPContracts) DeployNewOnRamp(t *testing.T) { + t.Log("Deploying new onRamp") + // find the last onRamp + prevOnRamp := common.HexToAddress("") + if c.Source.OnRamp != nil { + prevOnRamp = c.Source.OnRamp.Address() + } + onRampAddress, _, _, err := evm_2_evm_onramp.DeployEVM2EVMOnRamp( + c.Source.User, // user + c.Source.Chain.Client(), // client + evm_2_evm_onramp.EVM2EVMOnRampStaticConfig{ + LinkToken: c.Source.LinkToken.Address(), + ChainSelector: c.Source.ChainSelector, + DestChainSelector: c.Dest.ChainSelector, + DefaultTxGasLimit: 200_000, + MaxNopFeesJuels: big.NewInt(0).Mul(big.NewInt(100_000_000), big.NewInt(1e18)), + PrevOnRamp: prevOnRamp, + ArmProxy: c.Source.ARM.Address(), // ARM + }, + evm_2_evm_onramp.EVM2EVMOnRampDynamicConfig{ + Router: c.Source.Router.Address(), + MaxNumberOfTokensPerMsg: 5, + DestGasOverhead: 350_000, + DestGasPerPayloadByte: 16, + DestDataAvailabilityOverheadGas: 33_596, + DestGasPerDataAvailabilityByte: 16, + DestDataAvailabilityMultiplierBps: 6840, // 0.684 + PriceRegistry: c.Source.PriceRegistry.Address(), + MaxDataBytes: 1e5, + MaxPerMsgGasLimit: 4_000_000, + }, + []evm_2_evm_onramp.InternalPoolUpdate{ + { + Token: c.Source.LinkToken.Address(), + Pool: c.Source.LinkTokenPool.Address(), + }, + }, + evm_2_evm_onramp.RateLimiterConfig{ + IsEnabled: true, + Capacity: LinkUSDValue(100), + Rate: LinkUSDValue(1), + }, + []evm_2_evm_onramp.EVM2EVMOnRampFeeTokenConfigArgs{ + { + Token: c.Source.LinkToken.Address(), + NetworkFeeUSDCents: 1_00, + GasMultiplierWeiPerEth: 1e18, + PremiumMultiplierWeiPerEth: 9e17, + Enabled: true, + }, + { + Token: c.Source.WrappedNative.Address(), + NetworkFeeUSDCents: 1_00, + GasMultiplierWeiPerEth: 1e18, + PremiumMultiplierWeiPerEth: 1e18, + Enabled: true, + }, + }, + []evm_2_evm_onramp.EVM2EVMOnRampTokenTransferFeeConfigArgs{ + { + Token: c.Source.LinkToken.Address(), + MinFeeUSDCents: 50, // $0.5 + MaxFeeUSDCents: 1_000_000_00, // $ 1 million + DeciBps: 5_0, // 5 bps + DestGasOverhead: 34_000, + DestBytesOverhead: 32, + }, + }, + []evm_2_evm_onramp.EVM2EVMOnRampNopAndWeight{}, + ) + + require.NoError(t, err) + c.Source.Chain.Commit() + c.Dest.Chain.Commit() + c.Source.OnRamp, err = evm_2_evm_onramp.NewEVM2EVMOnRamp(onRampAddress, c.Source.Chain.Client()) + require.NoError(t, err) + c.Source.Chain.Commit() + c.Dest.Chain.Commit() +} + +func (c *CCIPContracts) EnableOnRamp(t *testing.T) { + t.Log("Setting onRamp on source router") + _, err := c.Source.Router.ApplyRampUpdates(c.Source.User, []router.RouterOnRamp{{DestChainSelector: c.Dest.ChainSelector, OnRamp: c.Source.OnRamp.Address()}}, nil, nil) + require.NoError(t, err) + c.Source.Chain.Commit() + c.Dest.Chain.Commit() +} + +func (c *CCIPContracts) DeployNewCommitStore(t *testing.T) { + commitStoreAddress, _, _, err := commit_store_1_2_0.DeployCommitStore( + c.Dest.User, // user + c.Dest.Chain.Client(), // client + commit_store_1_2_0.CommitStoreStaticConfig{ + ChainSelector: c.Dest.ChainSelector, + SourceChainSelector: c.Source.ChainSelector, + OnRamp: c.Source.OnRamp.Address(), + ArmProxy: c.Dest.ARMProxy.Address(), + }, + ) + require.NoError(t, err) + c.Dest.Chain.Commit() + // since CommitStoreHelper derives from CommitStore, it's safe to instantiate both on same address + c.Dest.CommitStore, err = commit_store_1_2_0.NewCommitStore(commitStoreAddress, c.Dest.Chain.Client()) + require.NoError(t, err) +} + +func (c *CCIPContracts) DeployNewPriceRegistry(t *testing.T) { + t.Log("Deploying new Price Registry") + destPricesAddress, _, _, err := price_registry_1_2_0.DeployPriceRegistry( + c.Dest.User, + c.Dest.Chain.Client(), + []common.Address{c.Dest.CommitStore.Address()}, + []common.Address{c.Dest.LinkToken.Address()}, + 60*60*24*14, // two weeks + ) + require.NoError(t, err) + c.Source.Chain.Commit() + c.Dest.Chain.Commit() + c.Dest.PriceRegistry, err = price_registry_1_2_0.NewPriceRegistry(destPricesAddress, c.Dest.Chain.Client()) + require.NoError(t, err) + + priceUpdates := price_registry_1_2_0.InternalPriceUpdates{ + TokenPriceUpdates: []price_registry_1_2_0.InternalTokenPriceUpdate{ + { + SourceToken: c.Dest.LinkToken.Address(), + UsdPerToken: big.NewInt(8e18), // 8usd + }, + { + SourceToken: c.Dest.WrappedNative.Address(), + UsdPerToken: big.NewInt(1e18), // 1usd + }, + }, + GasPriceUpdates: []price_registry_1_2_0.InternalGasPriceUpdate{ + { + DestChainSelector: c.Source.ChainSelector, + UsdPerUnitGas: big.NewInt(2000e9), // $2000 per eth * 1gwei = 2000e9 + }, + }, + } + _, err = c.Dest.PriceRegistry.UpdatePrices(c.Dest.User, priceUpdates) + require.NoError(t, err) + + c.Source.Chain.Commit() + c.Dest.Chain.Commit() + + t.Logf("New Price Registry deployed at %s", destPricesAddress.String()) +} + +func (c *CCIPContracts) SetNopsOnRamp(t *testing.T, nopsAndWeights []evm_2_evm_onramp.EVM2EVMOnRampNopAndWeight) { + tx, err := c.Source.OnRamp.SetNops(c.Source.User, nopsAndWeights) + require.NoError(t, err) + c.Source.Chain.Commit() + _, err = bind.WaitMined(tests.Context(t), c.Source.Chain.Client(), tx) + require.NoError(t, err) +} + +func (c *CCIPContracts) GetSourceLinkBalance(t *testing.T, addr common.Address) *big.Int { + return GetBalance(t, c.Source.Chain.Client(), c.Source.LinkToken.Address(), addr) +} + +func (c *CCIPContracts) GetDestLinkBalance(t *testing.T, addr common.Address) *big.Int { + return GetBalance(t, c.Dest.Chain.Client(), c.Dest.LinkToken.Address(), addr) +} + +func (c *CCIPContracts) GetSourceWrappedTokenBalance(t *testing.T, addr common.Address) *big.Int { + return GetBalance(t, c.Source.Chain.Client(), c.Source.WrappedNative.Address(), addr) +} + +func (c *CCIPContracts) GetDestWrappedTokenBalance(t *testing.T, addr common.Address) *big.Int { + return GetBalance(t, c.Dest.Chain.Client(), c.Dest.WrappedNative.Address(), addr) +} + +func (c *CCIPContracts) AssertBalances(t *testing.T, bas []BalanceAssertion) { + for _, b := range bas { + actual := b.Getter(t, b.Address) + t.Log("Checking balance for", b.Name, "at", b.Address.Hex(), "got", actual) + require.NotNil(t, actual, "%v getter return nil", b.Name) + if b.Within == "" { + require.Equal(t, b.Expected, actual.String(), "wrong balance for %s got %s want %s", b.Name, actual, b.Expected) + } else { + bi, _ := big.NewInt(0).SetString(b.Expected, 10) + withinI, _ := big.NewInt(0).SetString(b.Within, 10) + high := big.NewInt(0).Add(bi, withinI) + low := big.NewInt(0).Sub(bi, withinI) + require.Equal(t, -1, actual.Cmp(high), "wrong balance for %s got %s outside expected range [%s, %s]", b.Name, actual, low, high) + require.Equal(t, 1, actual.Cmp(low), "wrong balance for %s got %s outside expected range [%s, %s]", b.Name, actual, low, high) + } + } +} + +func AccountToAddress(accounts []ocr2types.Account) (addresses []common.Address, err error) { + for _, signer := range accounts { + bytes, err := hexutil.Decode(string(signer)) + if err != nil { + return []common.Address{}, errors.Wrap(err, fmt.Sprintf("given address is not valid %s", signer)) + } + if len(bytes) != 20 { + return []common.Address{}, errors.Errorf("address is not 20 bytes %s", signer) + } + addresses = append(addresses, common.BytesToAddress(bytes)) + } + return addresses, nil +} + +func OnchainPublicKeyToAddress(publicKeys []ocrtypes.OnchainPublicKey) (addresses []common.Address, err error) { + for _, signer := range publicKeys { + if len(signer) != 20 { + return []common.Address{}, errors.Errorf("address is not 20 bytes %s", signer) + } + addresses = append(addresses, common.BytesToAddress(signer)) + } + return addresses, nil +} + +func (c *CCIPContracts) DeriveOCR2Config(t *testing.T, oracles []confighelper.OracleIdentityExtra, rawOnchainConfig []byte, rawOffchainConfig []byte) *OCR2Config { + signers, transmitters, threshold, onchainConfig, offchainConfigVersion, offchainConfig, err := confighelper.ContractSetConfigArgsForTests( + 2*time.Second, // deltaProgress + 1*time.Second, // deltaResend + 1*time.Second, // deltaRound + 500*time.Millisecond, // deltaGrace + 2*time.Second, // deltaStage + 3, + []int{1, 1, 1, 1}, + oracles, + rawOffchainConfig, + nil, + 50*time.Millisecond, // Max duration query + 1*time.Second, // Max duration observation + 100*time.Millisecond, + 100*time.Millisecond, + 100*time.Millisecond, + 1, // faults + rawOnchainConfig, + ) + require.NoError(t, err) + lggr := logger.TestLogger(t) + lggr.Infow("Setting Config on Oracle Contract", + "signers", signers, + "transmitters", transmitters, + "threshold", threshold, + "onchainConfig", onchainConfig, + "encodedConfigVersion", offchainConfigVersion, + ) + signerAddresses, err := OnchainPublicKeyToAddress(signers) + require.NoError(t, err) + transmitterAddresses, err := AccountToAddress(transmitters) + require.NoError(t, err) + + return &OCR2Config{ + Signers: signerAddresses, + Transmitters: transmitterAddresses, + F: threshold, + OnchainConfig: onchainConfig, + OffchainConfigVersion: offchainConfigVersion, + OffchainConfig: offchainConfig, + } +} + +func (c *CCIPContracts) SetupCommitOCR2Config(t *testing.T, commitOnchainConfig, commitOffchainConfig []byte) { + c.commitOCRConfig = c.DeriveOCR2Config(t, c.Oracles, commitOnchainConfig, commitOffchainConfig) + // Set the DON on the commit store + _, err := c.Dest.CommitStore.SetOCR2Config( + c.Dest.User, + c.commitOCRConfig.Signers, + c.commitOCRConfig.Transmitters, + c.commitOCRConfig.F, + c.commitOCRConfig.OnchainConfig, + c.commitOCRConfig.OffchainConfigVersion, + c.commitOCRConfig.OffchainConfig, + ) + require.NoError(t, err) + c.Dest.Chain.Commit() +} + +func (c *CCIPContracts) SetupExecOCR2Config(t *testing.T, execOnchainConfig, execOffchainConfig []byte) { + c.execOCRConfig = c.DeriveOCR2Config(t, c.Oracles, execOnchainConfig, execOffchainConfig) + // Same DON on the offramp + _, err := c.Dest.OffRamp.SetOCR2Config( + c.Dest.User, + c.execOCRConfig.Signers, + c.execOCRConfig.Transmitters, + c.execOCRConfig.F, + c.execOCRConfig.OnchainConfig, + c.execOCRConfig.OffchainConfigVersion, + c.execOCRConfig.OffchainConfig, + ) + require.NoError(t, err) + c.Dest.Chain.Commit() +} + +func (c *CCIPContracts) SetupOnchainConfig(t *testing.T, commitOnchainConfig, commitOffchainConfig, execOnchainConfig, execOffchainConfig []byte) int64 { + // Note We do NOT set the payees, payment is done in the OCR2Base implementation + blockBeforeConfig, err := c.Dest.Chain.Client().BlockByNumber(tests.Context(t), nil) + require.NoError(t, err) + + c.SetupCommitOCR2Config(t, commitOnchainConfig, commitOffchainConfig) + c.SetupExecOCR2Config(t, execOnchainConfig, execOffchainConfig) + + return blockBeforeConfig.Number().Int64() +} + +func (c *CCIPContracts) SetupLockAndMintTokenPool( + sourceTokenAddress common.Address, + wrappedTokenName, + wrappedTokenSymbol string) (common.Address, *burn_mint_erc677.BurnMintERC677, error) { + // Deploy dest token & pool + destTokenAddress, _, _, err := burn_mint_erc677.DeployBurnMintERC677(c.Dest.User, c.Dest.Chain.Client(), wrappedTokenName, wrappedTokenSymbol, 18, big.NewInt(0)) + if err != nil { + return [20]byte{}, nil, err + } + c.Dest.Chain.Commit() + + destToken, err := burn_mint_erc677.NewBurnMintERC677(destTokenAddress, c.Dest.Chain.Client()) + if err != nil { + return [20]byte{}, nil, err + } + + destPoolAddress, _, destPool, err := burn_mint_token_pool.DeployBurnMintTokenPool( + c.Dest.User, + c.Dest.Chain.Client(), + destTokenAddress, + []common.Address{}, // pool originalSender allowList + c.Dest.ARMProxy.Address(), + c.Dest.Router.Address(), + ) + if err != nil { + return [20]byte{}, nil, err + } + c.Dest.Chain.Commit() + + _, err = destToken.GrantMintAndBurnRoles(c.Dest.User, destPoolAddress) + if err != nil { + return [20]byte{}, nil, err + } + + _, err = destPool.ApplyChainUpdates(c.Dest.User, + []burn_mint_token_pool.TokenPoolChainUpdate{ + { + RemoteChainSelector: c.Source.ChainSelector, + Allowed: true, + OutboundRateLimiterConfig: burn_mint_token_pool.RateLimiterConfig{ + IsEnabled: true, + Capacity: HundredLink, + Rate: big.NewInt(1e18), + }, + InboundRateLimiterConfig: burn_mint_token_pool.RateLimiterConfig{ + IsEnabled: true, + Capacity: HundredLink, + Rate: big.NewInt(1e18), + }, + }, + }) + if err != nil { + return [20]byte{}, nil, err + } + c.Dest.Chain.Commit() + + sourcePoolAddress, _, sourcePool, err := lock_release_token_pool.DeployLockReleaseTokenPool( + c.Source.User, + c.Source.Chain.Client(), + sourceTokenAddress, + []common.Address{}, // empty allowList at deploy time indicates pool has no original sender restrictions + c.Source.ARMProxy.Address(), + true, + c.Source.Router.Address(), + ) + if err != nil { + return [20]byte{}, nil, err + } + c.Source.Chain.Commit() + + // set onRamp as valid caller for source pool + _, err = sourcePool.ApplyChainUpdates(c.Source.User, []lock_release_token_pool.TokenPoolChainUpdate{ + { + RemoteChainSelector: c.Dest.ChainSelector, + Allowed: true, + OutboundRateLimiterConfig: lock_release_token_pool.RateLimiterConfig{ + IsEnabled: true, + Capacity: HundredLink, + Rate: big.NewInt(1e18), + }, + InboundRateLimiterConfig: lock_release_token_pool.RateLimiterConfig{ + IsEnabled: true, + Capacity: HundredLink, + Rate: big.NewInt(1e18), + }, + }, + }) + if err != nil { + return [20]byte{}, nil, err + } + c.Source.Chain.Commit() + + wrappedNativeAddress, err := c.Source.Router.GetWrappedNative(nil) + if err != nil { + return [20]byte{}, nil, err + } + + // native token is used as fee token + _, err = c.Source.PriceRegistry.UpdatePrices(c.Source.User, price_registry_1_2_0.InternalPriceUpdates{ + TokenPriceUpdates: []price_registry_1_2_0.InternalTokenPriceUpdate{ + { + SourceToken: sourceTokenAddress, + UsdPerToken: big.NewInt(5), + }, + }, + GasPriceUpdates: []price_registry_1_2_0.InternalGasPriceUpdate{}, + }) + if err != nil { + return [20]byte{}, nil, err + } + c.Source.Chain.Commit() + + _, err = c.Source.PriceRegistry.ApplyFeeTokensUpdates(c.Source.User, []common.Address{wrappedNativeAddress}, nil) + if err != nil { + return [20]byte{}, nil, err + } + c.Source.Chain.Commit() + + // add new token pool created above + _, err = c.Source.OnRamp.ApplyPoolUpdates(c.Source.User, nil, []evm_2_evm_onramp.InternalPoolUpdate{ + { + Token: sourceTokenAddress, + Pool: sourcePoolAddress, + }, + }) + if err != nil { + return [20]byte{}, nil, err + } + + _, err = c.Dest.OffRamp.ApplyPoolUpdates(c.Dest.User, nil, []evm_2_evm_offramp.InternalPoolUpdate{ + { + Token: sourceTokenAddress, + Pool: destPoolAddress, + }, + }) + if err != nil { + return [20]byte{}, nil, err + } + c.Dest.Chain.Commit() + + return sourcePoolAddress, destToken, err +} + +func (c *CCIPContracts) SendMessage(t *testing.T, gasLimit, tokenAmount *big.Int, receiverAddr common.Address) { + extraArgs, err := GetEVMExtraArgsV1(gasLimit, false) + require.NoError(t, err) + msg := router.ClientEVM2AnyMessage{ + Receiver: MustEncodeAddress(t, receiverAddr), + Data: []byte("hello"), + TokenAmounts: []router.ClientEVMTokenAmount{ + { + Token: c.Source.LinkToken.Address(), + Amount: tokenAmount, + }, + }, + FeeToken: c.Source.LinkToken.Address(), + ExtraArgs: extraArgs, + } + fee, err := c.Source.Router.GetFee(nil, c.Dest.ChainSelector, msg) + require.NoError(t, err) + // Currently no overhead and 1gwei dest gas price. So fee is simply gasLimit * gasPrice. + // require.Equal(t, new(big.Int).Mul(gasLimit, gasPrice).String(), fee.String()) + // Approve the fee amount + the token amount + _, err = c.Source.LinkToken.Approve(c.Source.User, c.Source.Router.Address(), new(big.Int).Add(fee, tokenAmount)) + require.NoError(t, err) + c.Source.Chain.Commit() + c.SendRequest(t, msg) +} + +func GetBalances(t *testing.T, brs []BalanceReq) (map[string]*big.Int, error) { + m := make(map[string]*big.Int) + for _, br := range brs { + m[br.Name] = br.Getter(t, br.Addr) + if m[br.Name] == nil { + return nil, fmt.Errorf("%v getter return nil", br.Name) + } + } + return m, nil +} + +func MustAddBigInt(a *big.Int, b string) *big.Int { + bi, _ := big.NewInt(0).SetString(b, 10) + return big.NewInt(0).Add(a, bi) +} + +func MustSubBigInt(a *big.Int, b string) *big.Int { + bi, _ := big.NewInt(0).SetString(b, 10) + return big.NewInt(0).Sub(a, bi) +} + +func MustEncodeAddress(t *testing.T, address common.Address) []byte { + bts, err := utils.ABIEncode(`[{"type":"address"}]`, address) + require.NoError(t, err) + return bts +} + +func SetupCCIPContracts(t *testing.T, sourceChainID, sourceChainSelector, destChainID, destChainSelector uint64) CCIPContracts { + sourceChain, sourceUser := testhelpers.SetupChain(t) + destChain, destUser := testhelpers.SetupChain(t) + + sourceChain.Commit() + destChain.Commit() + + armSourceAddress, _, _, err := mock_rmn_contract.DeployMockRMNContract( + sourceUser, + sourceChain.Client(), + ) + require.NoError(t, err) + sourceChain.Commit() + + sourceARM, err := mock_rmn_contract.NewMockRMNContract(armSourceAddress, sourceChain.Client()) + require.NoError(t, err) + armProxySourceAddress, _, _, err := rmn_proxy_contract.DeployRMNProxyContract( + sourceUser, + sourceChain.Client(), + armSourceAddress, + ) + require.NoError(t, err) + sourceChain.Commit() + + sourceARMProxy, err := rmn_proxy_contract.NewRMNProxyContract(armProxySourceAddress, sourceChain.Client()) + require.NoError(t, err) + + armDestAddress, _, _, err := mock_rmn_contract.DeployMockRMNContract( + destUser, + destChain.Client(), + ) + require.NoError(t, err) + destChain.Commit() + + armProxyDestAddress, _, _, err := rmn_proxy_contract.DeployRMNProxyContract( + destUser, + destChain.Client(), + armDestAddress, + ) + require.NoError(t, err) + destChain.Commit() + + destARM, err := mock_rmn_contract.NewMockRMNContract(armDestAddress, destChain.Client()) + require.NoError(t, err) + destARMProxy, err := rmn_proxy_contract.NewRMNProxyContract(armProxyDestAddress, destChain.Client()) + require.NoError(t, err) + + // Deploy link token and pool on source chain + sourceLinkTokenAddress, _, _, err := link_token_interface.DeployLinkToken(sourceUser, sourceChain.Client()) + require.NoError(t, err) + sourceChain.Commit() + sourceLinkToken, err := link_token_interface.NewLinkToken(sourceLinkTokenAddress, sourceChain.Client()) + require.NoError(t, err) + + // Create router + sourceWeth9addr, _, _, err := weth9.DeployWETH9(sourceUser, sourceChain.Client()) + require.NoError(t, err) + sourceChain.Commit() + + sourceWrapped, err := weth9.NewWETH9(sourceWeth9addr, sourceChain.Client()) + require.NoError(t, err) + + sourceRouterAddress, _, _, err := router.DeployRouter(sourceUser, sourceChain.Client(), sourceWeth9addr, armProxySourceAddress) + require.NoError(t, err) + sourceChain.Commit() + + sourceRouter, err := router.NewRouter(sourceRouterAddress, sourceChain.Client()) + require.NoError(t, err) + + sourceWeth9PoolAddress, _, _, err := lock_release_token_pool_1_0_0.DeployLockReleaseTokenPool( + sourceUser, + sourceChain.Client(), + sourceWeth9addr, + []common.Address{}, + armProxySourceAddress, + ) + require.NoError(t, err) + sourceChain.Commit() + + sourceWeth9Pool, err := lock_release_token_pool_1_0_0.NewLockReleaseTokenPool(sourceWeth9PoolAddress, sourceChain.Client()) + require.NoError(t, err) + + sourcePoolAddress, _, _, err := lock_release_token_pool.DeployLockReleaseTokenPool( + sourceUser, + sourceChain.Client(), + sourceLinkTokenAddress, + []common.Address{}, + armProxySourceAddress, + true, + sourceRouterAddress, + ) + require.NoError(t, err) + sourceChain.Commit() + sourcePool, err := lock_release_token_pool.NewLockReleaseTokenPool(sourcePoolAddress, sourceChain.Client()) + require.NoError(t, err) + + // Deploy custom token pool source + sourceCustomTokenAddress, _, _, err := link_token_interface.DeployLinkToken(sourceUser, sourceChain.Client()) // Just re-use this, it's an ERC20. + require.NoError(t, err) + sourceCustomToken, err := link_token_interface.NewLinkToken(sourceCustomTokenAddress, sourceChain.Client()) + require.NoError(t, err) + destChain.Commit() + + // Deploy custom token pool dest + destCustomTokenAddress, _, _, err := link_token_interface.DeployLinkToken(destUser, destChain.Client()) // Just re-use this, it's an ERC20. + require.NoError(t, err) + destCustomToken, err := link_token_interface.NewLinkToken(destCustomTokenAddress, destChain.Client()) + require.NoError(t, err) + destChain.Commit() + + // Deploy and configure onramp + sourcePricesAddress, _, _, err := price_registry_1_2_0.DeployPriceRegistry( + sourceUser, + sourceChain.Client(), + nil, + []common.Address{sourceLinkTokenAddress, sourceWeth9addr}, + 60*60*24*14, // two weeks + ) + require.NoError(t, err) + sourceChain.Commit() + + srcPriceRegistry, err := price_registry_1_2_0.NewPriceRegistry(sourcePricesAddress, sourceChain.Client()) + require.NoError(t, err) + + _, err = srcPriceRegistry.UpdatePrices(sourceUser, price_registry_1_2_0.InternalPriceUpdates{ + TokenPriceUpdates: []price_registry_1_2_0.InternalTokenPriceUpdate{ + { + SourceToken: sourceLinkTokenAddress, + UsdPerToken: new(big.Int).Mul(big.NewInt(1e18), big.NewInt(20)), + }, + { + SourceToken: sourceWeth9addr, + UsdPerToken: new(big.Int).Mul(big.NewInt(1e18), big.NewInt(2000)), + }, + }, + GasPriceUpdates: []price_registry_1_2_0.InternalGasPriceUpdate{ + { + DestChainSelector: destChainSelector, + UsdPerUnitGas: big.NewInt(20000e9), + }, + }, + }) + require.NoError(t, err) + sourceChain.Commit() + + onRampAddress, _, _, err := evm_2_evm_onramp.DeployEVM2EVMOnRamp( + sourceUser, // user + sourceChain.Client(), // client + evm_2_evm_onramp.EVM2EVMOnRampStaticConfig{ + LinkToken: sourceLinkTokenAddress, + ChainSelector: sourceChainSelector, + DestChainSelector: destChainSelector, + DefaultTxGasLimit: 200_000, + MaxNopFeesJuels: big.NewInt(0).Mul(big.NewInt(100_000_000), big.NewInt(1e18)), + PrevOnRamp: common.HexToAddress(""), + ArmProxy: armProxySourceAddress, // ARM + }, + evm_2_evm_onramp.EVM2EVMOnRampDynamicConfig{ + Router: sourceRouterAddress, + MaxNumberOfTokensPerMsg: 5, + DestGasOverhead: 350_000, + DestGasPerPayloadByte: 16, + DestDataAvailabilityOverheadGas: 33_596, + DestGasPerDataAvailabilityByte: 16, + DestDataAvailabilityMultiplierBps: 6840, // 0.684 + PriceRegistry: sourcePricesAddress, + MaxDataBytes: 1e5, + MaxPerMsgGasLimit: 4_000_000, + }, + []evm_2_evm_onramp.InternalPoolUpdate{ + { + Token: sourceLinkTokenAddress, + Pool: sourcePoolAddress, + }, + { + Token: sourceWeth9addr, + Pool: sourceWeth9PoolAddress, + }, + }, + evm_2_evm_onramp.RateLimiterConfig{ + IsEnabled: true, + Capacity: LinkUSDValue(100), + Rate: LinkUSDValue(1), + }, + []evm_2_evm_onramp.EVM2EVMOnRampFeeTokenConfigArgs{ + { + Token: sourceLinkTokenAddress, + NetworkFeeUSDCents: 1_00, + GasMultiplierWeiPerEth: 1e18, + PremiumMultiplierWeiPerEth: 9e17, + Enabled: true, + }, + { + Token: sourceWeth9addr, + NetworkFeeUSDCents: 1_00, + GasMultiplierWeiPerEth: 1e18, + PremiumMultiplierWeiPerEth: 1e18, + Enabled: true, + }, + }, + []evm_2_evm_onramp.EVM2EVMOnRampTokenTransferFeeConfigArgs{ + { + Token: sourceLinkTokenAddress, + MinFeeUSDCents: 50, // $0.5 + MaxFeeUSDCents: 1_000_000_00, // $ 1 million + DeciBps: 5_0, // 5 bps + DestGasOverhead: 34_000, + DestBytesOverhead: 32, + }, + }, + []evm_2_evm_onramp.EVM2EVMOnRampNopAndWeight{}, + ) + require.NoError(t, err) + sourceChain.Commit() + + onRamp, err := evm_2_evm_onramp.NewEVM2EVMOnRamp(onRampAddress, sourceChain.Client()) + require.NoError(t, err) + _, err = sourcePool.ApplyChainUpdates( + sourceUser, + []lock_release_token_pool.TokenPoolChainUpdate{{ + RemoteChainSelector: DestChainSelector, + Allowed: true, + OutboundRateLimiterConfig: lock_release_token_pool.RateLimiterConfig{ + IsEnabled: true, + Capacity: HundredLink, + Rate: big.NewInt(1e18), + }, + InboundRateLimiterConfig: lock_release_token_pool.RateLimiterConfig{ + IsEnabled: true, + Capacity: HundredLink, + Rate: big.NewInt(1e18), + }, + }}, + ) + require.NoError(t, err) + _, err = sourceWeth9Pool.ApplyRampUpdates(sourceUser, + []lock_release_token_pool_1_0_0.TokenPoolRampUpdate{{Ramp: onRampAddress, Allowed: true, + RateLimiterConfig: lock_release_token_pool_1_0_0.RateLimiterConfig{ + IsEnabled: true, + Capacity: HundredLink, + Rate: big.NewInt(1e18), + }, + }}, + []lock_release_token_pool_1_0_0.TokenPoolRampUpdate{}, + ) + require.NoError(t, err) + sourceChain.Commit() + _, err = sourceRouter.ApplyRampUpdates(sourceUser, []router.RouterOnRamp{{DestChainSelector: destChainSelector, OnRamp: onRampAddress}}, nil, nil) + require.NoError(t, err) + sourceChain.Commit() + + destWethaddr, _, _, err := weth9.DeployWETH9(destUser, destChain.Client()) + require.NoError(t, err) + destChain.Commit() + destWrapped, err := weth9.NewWETH9(destWethaddr, destChain.Client()) + require.NoError(t, err) + + // Create dest router + destRouterAddress, _, _, err := router.DeployRouter(destUser, destChain.Client(), destWethaddr, armProxyDestAddress) + require.NoError(t, err) + destChain.Commit() + destRouter, err := router.NewRouter(destRouterAddress, destChain.Client()) + require.NoError(t, err) + + // Deploy link token and pool on destination chain + destLinkTokenAddress, _, _, err := link_token_interface.DeployLinkToken(destUser, destChain.Client()) + require.NoError(t, err) + destChain.Commit() + destLinkToken, err := link_token_interface.NewLinkToken(destLinkTokenAddress, destChain.Client()) + require.NoError(t, err) + destPoolAddress, _, _, err := lock_release_token_pool.DeployLockReleaseTokenPool( + destUser, + destChain.Client(), + destLinkTokenAddress, + []common.Address{}, + armProxyDestAddress, + true, + destRouterAddress, + ) + require.NoError(t, err) + destChain.Commit() + destPool, err := lock_release_token_pool.NewLockReleaseTokenPool(destPoolAddress, destChain.Client()) + require.NoError(t, err) + destChain.Commit() + + // Float the offramp pool + o, err := destPool.Owner(nil) + require.NoError(t, err) + require.Equal(t, destUser.From.String(), o.String()) + _, err = destPool.SetRebalancer(destUser, destUser.From) + require.NoError(t, err) + _, err = destLinkToken.Approve(destUser, destPoolAddress, Link(200)) + require.NoError(t, err) + destChain.Commit() + _, err = destPool.ProvideLiquidity(destUser, Link(200)) + require.NoError(t, err) + destChain.Commit() + + destWrappedPoolAddress, _, _, err := lock_release_token_pool_1_0_0.DeployLockReleaseTokenPool( + destUser, + destChain.Client(), + destWethaddr, + []common.Address{}, + armProxyDestAddress, + ) + require.NoError(t, err) + destChain.Commit() + destWrappedPool, err := lock_release_token_pool_1_0_0.NewLockReleaseTokenPool(destWrappedPoolAddress, destChain.Client()) + require.NoError(t, err) + + poolFloatValue := big.NewInt(1e18) + + destUser.Value = poolFloatValue + _, err = destWrapped.Deposit(destUser) + require.NoError(t, err) + destChain.Commit() + destUser.Value = nil + + _, err = destWrapped.Transfer(destUser, destWrappedPool.Address(), poolFloatValue) + require.NoError(t, err) + destChain.Commit() + + // Deploy and configure ge offramp. + destPricesAddress, _, _, err := price_registry_1_2_0.DeployPriceRegistry( + destUser, + destChain.Client(), + nil, + []common.Address{destLinkTokenAddress}, + 60*60*24*14, // two weeks + ) + require.NoError(t, err) + destChain.Commit() + + destPriceRegistry, err := price_registry_1_2_0.NewPriceRegistry(destPricesAddress, destChain.Client()) + require.NoError(t, err) + + // Deploy commit store. + commitStoreAddress, _, _, err := commit_store_1_2_0.DeployCommitStore( + destUser, // user + destChain.Client(), // client + commit_store_1_2_0.CommitStoreStaticConfig{ + ChainSelector: destChainSelector, + SourceChainSelector: sourceChainSelector, + OnRamp: onRamp.Address(), + ArmProxy: destARMProxy.Address(), + }, + ) + require.NoError(t, err) + destChain.Commit() + commitStore, err := commit_store_1_2_0.NewCommitStore(commitStoreAddress, destChain.Client()) + require.NoError(t, err) + + offRampAddress, _, _, err := evm_2_evm_offramp.DeployEVM2EVMOffRamp( + destUser, + destChain.Client(), + evm_2_evm_offramp.EVM2EVMOffRampStaticConfig{ + CommitStore: commitStore.Address(), + ChainSelector: destChainSelector, + SourceChainSelector: sourceChainSelector, + OnRamp: onRampAddress, + PrevOffRamp: common.HexToAddress(""), + ArmProxy: armProxyDestAddress, + }, + []common.Address{sourceLinkTokenAddress, sourceWeth9addr}, + []common.Address{destPoolAddress, destWrappedPool.Address()}, + evm_2_evm_offramp.RateLimiterConfig{ + IsEnabled: true, + Capacity: LinkUSDValue(100), + Rate: LinkUSDValue(1), + }, + ) + require.NoError(t, err) + destChain.Commit() + + offRamp, err := evm_2_evm_offramp.NewEVM2EVMOffRamp(offRampAddress, destChain.Client()) + require.NoError(t, err) + _, err = destPool.ApplyChainUpdates(destUser, + []lock_release_token_pool.TokenPoolChainUpdate{{ + RemoteChainSelector: sourceChainSelector, + Allowed: true, + OutboundRateLimiterConfig: lock_release_token_pool.RateLimiterConfig{ + IsEnabled: true, + Capacity: HundredLink, + Rate: big.NewInt(1e18), + }, + InboundRateLimiterConfig: lock_release_token_pool.RateLimiterConfig{ + IsEnabled: true, + Capacity: HundredLink, + Rate: big.NewInt(1e18), + }, + }}, + ) + require.NoError(t, err) + + _, err = destWrappedPool.ApplyRampUpdates(destUser, + []lock_release_token_pool_1_0_0.TokenPoolRampUpdate{}, + []lock_release_token_pool_1_0_0.TokenPoolRampUpdate{{ + Ramp: offRampAddress, + Allowed: true, + RateLimiterConfig: lock_release_token_pool_1_0_0.RateLimiterConfig{ + IsEnabled: true, + Capacity: HundredLink, + Rate: big.NewInt(1e18), + }, + }}, + ) + require.NoError(t, err) + + destChain.Commit() + _, err = destPriceRegistry.ApplyPriceUpdatersUpdates(destUser, []common.Address{commitStoreAddress}, []common.Address{}) + require.NoError(t, err) + destChain.Commit() + + _, err = destRouter.ApplyRampUpdates(destUser, nil, + nil, []router.RouterOffRamp{{SourceChainSelector: sourceChainSelector, OffRamp: offRampAddress}}) + require.NoError(t, err) + destChain.Commit() + + // Deploy 2 revertable (one SS one non-SS) + revertingMessageReceiver1Address, _, _, err := maybe_revert_message_receiver.DeployMaybeRevertMessageReceiver(destUser, destChain.Client(), false) + require.NoError(t, err) + revertingMessageReceiver1, _ := maybe_revert_message_receiver.NewMaybeRevertMessageReceiver(revertingMessageReceiver1Address, destChain.Client()) + revertingMessageReceiver2Address, _, _, err := maybe_revert_message_receiver.DeployMaybeRevertMessageReceiver(destUser, destChain.Client(), false) + require.NoError(t, err) + revertingMessageReceiver2, _ := maybe_revert_message_receiver.NewMaybeRevertMessageReceiver(revertingMessageReceiver2Address, destChain.Client()) + // Need to commit here, or we will hit the block gas limit when deploying the executor + sourceChain.Commit() + destChain.Commit() + + // Ensure we have at least finality blocks. + for i := 0; i < 50; i++ { + sourceChain.Commit() + destChain.Commit() + } + + source := SourceChain{ + Common: Common{ + ChainID: sourceChainID, + ChainSelector: sourceChainSelector, + User: sourceUser, + Chain: sourceChain, + LinkToken: sourceLinkToken, + LinkTokenPool: sourcePool, + CustomToken: sourceCustomToken, + ARM: sourceARM, + ARMProxy: sourceARMProxy, + PriceRegistry: srcPriceRegistry, + WrappedNative: sourceWrapped, + WrappedNativePool: sourceWeth9Pool, + }, + Router: sourceRouter, + OnRamp: onRamp, + } + dest := DestinationChain{ + Common: Common{ + ChainID: destChainID, + ChainSelector: destChainSelector, + User: destUser, + Chain: destChain, + LinkToken: destLinkToken, + LinkTokenPool: destPool, + CustomToken: destCustomToken, + ARM: destARM, + ARMProxy: destARMProxy, + PriceRegistry: destPriceRegistry, + WrappedNative: destWrapped, + WrappedNativePool: destWrappedPool, + }, + CommitStore: commitStore, + Router: destRouter, + OffRamp: offRamp, + Receivers: []MaybeRevertReceiver{{Receiver: revertingMessageReceiver1, Strict: false}, {Receiver: revertingMessageReceiver2, Strict: true}}, + } + + return CCIPContracts{ + Source: source, + Dest: dest, + } +} + +func (c *CCIPContracts) SendRequest(t *testing.T, msg router.ClientEVM2AnyMessage) *types.Transaction { + tx, err := c.Source.Router.CcipSend(c.Source.User, c.Dest.ChainSelector, msg) + require.NoError(t, err) + testhelpers.ConfirmTxs(t, []*types.Transaction{tx}, c.Source.Chain) + return tx +} + +func (c *CCIPContracts) AssertExecState(t *testing.T, log logpoller.Log, state MessageExecutionState, offRampOpts ...common.Address) { + var offRamp *evm_2_evm_offramp.EVM2EVMOffRamp + var err error + if len(offRampOpts) > 0 { + offRamp, err = evm_2_evm_offramp.NewEVM2EVMOffRamp(offRampOpts[0], c.Dest.Chain.Client()) + require.NoError(t, err) + } else { + require.NotNil(t, c.Dest.OffRamp, "no offRamp configured") + offRamp = c.Dest.OffRamp + } + executionStateChanged, err := offRamp.ParseExecutionStateChanged(log.ToGethLog()) + require.NoError(t, err) + if MessageExecutionState(executionStateChanged.State) != state { + t.Log("Execution failed", hexutil.Encode(executionStateChanged.ReturnData)) + t.Fail() + } +} + +func GetEVMExtraArgsV1(gasLimit *big.Int, strict bool) ([]byte, error) { + EVMV1Tag := []byte{0x97, 0xa6, 0x57, 0xc9} + + encodedArgs, err := utils.ABIEncode(`[{"type":"uint256"},{"type":"bool"}]`, gasLimit, strict) + if err != nil { + return nil, err + } + + return append(EVMV1Tag, encodedArgs...), nil +} + +type ManualExecArgs struct { + SourceChainID, DestChainID uint64 + DestUser *bind.TransactOpts + SourceChain, DestChain bind.ContractBackend + SourceStartBlock *big.Int // the block in/after which failed ccip-send transaction was triggered + DestStartBlock uint64 // the start block for filtering ReportAccepted event (including the failed seq num) + // in destination chain. if not provided to be derived by ApproxDestStartBlock method + DestLatestBlockNum uint64 // current block number in destination + DestDeployedAt uint64 // destination block number for the initial destination contract deployment. + // Can be any number before the tx was reverted in destination chain. Preferably this needs to be set up with + // a value greater than zero to avoid performance issue in locating approximate destination block + SendReqLogIndex uint // log index of the CCIPSendRequested log in source chain + SendReqTxHash string // tx hash of the ccip-send transaction for which execution was reverted + CommitStore string + OnRamp string + OffRamp string + SeqNr uint64 + GasLimit *big.Int +} + +// ApproxDestStartBlock attempts to locate a block in destination chain with timestamp closest to the timestamp of the block +// in source chain in which ccip-send transaction was included +// it uses binary search to locate the block with the closest timestamp +// if the block located has a timestamp greater than the timestamp of mentioned source block +// it just returns the first block found with lesser timestamp of the source block +// providing a value of args.DestDeployedAt ensures better performance by reducing the range of block numbers to be traversed +func (args *ManualExecArgs) ApproxDestStartBlock(ctx context.Context) error { + sourceBlockHdr, err := args.SourceChain.HeaderByNumber(ctx, args.SourceStartBlock) + if err != nil { + return err + } + sendTxTime := sourceBlockHdr.Time + maxBlockNum := args.DestLatestBlockNum + // setting this to an approx value of 1000 considering destination chain would have at least 1000 blocks before the transaction started + minBlockNum := args.DestDeployedAt + closestBlockNum := uint64(math.Floor((float64(maxBlockNum) + float64(minBlockNum)) / 2)) + var closestBlockHdr *types.Header + closestBlockHdr, err = args.DestChain.HeaderByNumber(ctx, new(big.Int).SetUint64(closestBlockNum)) + if err != nil { + return err + } + // to reduce the number of RPC calls increase the value of blockOffset + blockOffset := uint64(10) + for { + blockNum := closestBlockHdr.Number.Uint64() + if minBlockNum > maxBlockNum { + break + } + timeDiff := math.Abs(float64(closestBlockHdr.Time - sendTxTime)) + // break if the difference in timestamp is lesser than 1 minute + if timeDiff < 60 { + break + } else if closestBlockHdr.Time > sendTxTime { + maxBlockNum = blockNum - 1 + } else { + minBlockNum = blockNum + 1 + } + closestBlockNum = uint64(math.Floor((float64(maxBlockNum) + float64(minBlockNum)) / 2)) + closestBlockHdr, err = args.DestChain.HeaderByNumber(ctx, new(big.Int).SetUint64(closestBlockNum)) + if err != nil { + return err + } + } + + for closestBlockHdr.Time > sendTxTime { + closestBlockNum = closestBlockNum - blockOffset + if closestBlockNum <= 0 { + return fmt.Errorf("approx destination blocknumber not found") + } + closestBlockHdr, err = args.DestChain.HeaderByNumber(ctx, new(big.Int).SetUint64(closestBlockNum)) + if err != nil { + return err + } + } + args.DestStartBlock = closestBlockHdr.Number.Uint64() + fmt.Println("using approx destination start block number", args.DestStartBlock) + return nil +} + +func (args *ManualExecArgs) FindSeqNrFromCCIPSendRequested() (uint64, error) { + var seqNr uint64 + onRampContract, err := evm_2_evm_onramp.NewEVM2EVMOnRamp(common.HexToAddress(args.OnRamp), args.SourceChain) + if err != nil { + return seqNr, err + } + iterator, err := onRampContract.FilterCCIPSendRequested(&bind.FilterOpts{ + Start: args.SourceStartBlock.Uint64(), + }) + if err != nil { + return seqNr, err + } + for iterator.Next() { + if iterator.Event.Raw.Index == args.SendReqLogIndex && + iterator.Event.Raw.TxHash.Hex() == args.SendReqTxHash { + seqNr = iterator.Event.Message.SequenceNumber + break + } + } + if seqNr == 0 { + return seqNr, + fmt.Errorf("no CCIPSendRequested logs found for logIndex %d starting from block number %d", args.SendReqLogIndex, args.SourceStartBlock) + } + return seqNr, nil +} + +func (args *ManualExecArgs) ExecuteManually(ctx context.Context) (*types.Transaction, error) { + if args.SourceChainID == 0 || + args.DestChainID == 0 || + args.DestUser == nil { + return nil, fmt.Errorf("chain ids and owners are mandatory for source and dest chain") + } + if !common.IsHexAddress(args.CommitStore) || + !common.IsHexAddress(args.OffRamp) || + !common.IsHexAddress(args.OnRamp) { + return nil, fmt.Errorf("contract addresses must be valid hex address") + } + if args.SendReqTxHash == "" { + return nil, fmt.Errorf("tx hash of ccip-send request are required") + } + if args.SourceStartBlock == nil { + return nil, fmt.Errorf("must provide the value of source block in/after which ccip-send tx was included") + } + if args.SeqNr == 0 { + if args.SendReqLogIndex == 0 { + return nil, fmt.Errorf("must provide the value of log index of ccip-send request") + } + // locate seq nr from CCIPSendRequested log + seqNr, err := args.FindSeqNrFromCCIPSendRequested() + if err != nil { + return nil, err + } + args.SeqNr = seqNr + } + commitStore, err := commit_store_1_2_0.NewCommitStore(common.HexToAddress(args.CommitStore), args.DestChain) + if err != nil { + return nil, err + } + if args.DestStartBlock < 1 { + err = args.ApproxDestStartBlock(ctx) + if err != nil { + return nil, err + } + } + iterator, err := commitStore.FilterReportAccepted(&bind.FilterOpts{Start: args.DestStartBlock}) + if err != nil { + return nil, err + } + + var commitReport *commit_store_1_2_0.CommitStoreCommitReport + for iterator.Next() { + if iterator.Event.Report.Interval.Min <= args.SeqNr && iterator.Event.Report.Interval.Max >= args.SeqNr { + commitReport = &iterator.Event.Report + fmt.Println("Found root") + break + } + } + if commitReport == nil { + return nil, fmt.Errorf("unable to find seq num %d in commit report", args.SeqNr) + } + + return args.execute(commitReport) +} + +func (args *ManualExecArgs) execute(report *commit_store_1_2_0.CommitStoreCommitReport) (*types.Transaction, error) { + log.Info().Msg("Executing request manually") + seqNr := args.SeqNr + // Build a merkle tree for the report + mctx := hashutil.NewKeccak() + onRampContract, err := evm_2_evm_onramp_1_2_0.NewEVM2EVMOnRamp(common.HexToAddress(args.OnRamp), args.SourceChain) + if err != nil { + return nil, err + } + leafHasher := v1_2_0.NewLeafHasher(args.SourceChainID, args.DestChainID, common.HexToAddress(args.OnRamp), mctx, onRampContract) + if leafHasher == nil { + return nil, fmt.Errorf("unable to create leaf hasher") + } + + var leaves [][32]byte + var curr, prove int + var msgs []evm_2_evm_offramp.InternalEVM2EVMMessage + var manualExecGasLimits []*big.Int + var tokenData [][][]byte + sendRequestedIterator, err := onRampContract.FilterCCIPSendRequested(&bind.FilterOpts{ + Start: args.SourceStartBlock.Uint64(), + }) + if err != nil { + return nil, err + } + for sendRequestedIterator.Next() { + if sendRequestedIterator.Event.Message.SequenceNumber <= report.Interval.Max && + sendRequestedIterator.Event.Message.SequenceNumber >= report.Interval.Min { + fmt.Println("Found seq num", sendRequestedIterator.Event.Message.SequenceNumber, report.Interval) + hash, err2 := leafHasher.HashLeaf(sendRequestedIterator.Event.Raw) + if err2 != nil { + return nil, err2 + } + leaves = append(leaves, hash) + if sendRequestedIterator.Event.Message.SequenceNumber == seqNr { + fmt.Printf("Found proving %d %+v\n", curr, sendRequestedIterator.Event.Message) + var tokensAndAmounts []evm_2_evm_offramp.ClientEVMTokenAmount + for _, tokenAndAmount := range sendRequestedIterator.Event.Message.TokenAmounts { + tokensAndAmounts = append(tokensAndAmounts, evm_2_evm_offramp.ClientEVMTokenAmount{ + Token: tokenAndAmount.Token, + Amount: tokenAndAmount.Amount, + }) + } + msg := evm_2_evm_offramp.InternalEVM2EVMMessage{ + SourceChainSelector: sendRequestedIterator.Event.Message.SourceChainSelector, + Sender: sendRequestedIterator.Event.Message.Sender, + Receiver: sendRequestedIterator.Event.Message.Receiver, + SequenceNumber: sendRequestedIterator.Event.Message.SequenceNumber, + GasLimit: sendRequestedIterator.Event.Message.GasLimit, + Strict: sendRequestedIterator.Event.Message.Strict, + Nonce: sendRequestedIterator.Event.Message.Nonce, + FeeToken: sendRequestedIterator.Event.Message.FeeToken, + FeeTokenAmount: sendRequestedIterator.Event.Message.FeeTokenAmount, + Data: sendRequestedIterator.Event.Message.Data, + TokenAmounts: tokensAndAmounts, + SourceTokenData: sendRequestedIterator.Event.Message.SourceTokenData, + MessageId: sendRequestedIterator.Event.Message.MessageId, + } + msgs = append(msgs, msg) + if args.GasLimit != nil { + msg.GasLimit = args.GasLimit + } + manualExecGasLimits = append(manualExecGasLimits, msg.GasLimit) + var msgTokenData [][]byte + for range sendRequestedIterator.Event.Message.TokenAmounts { + msgTokenData = append(msgTokenData, []byte{}) + } + + tokenData = append(tokenData, msgTokenData) + prove = curr + } + curr++ + } + } + sendRequestedIterator.Close() + if msgs == nil { + return nil, fmt.Errorf("unable to find msg with seqNr %d", seqNr) + } + tree, err := merklemulti.NewTree(mctx, leaves) + if err != nil { + return nil, err + } + if tree.Root() != report.MerkleRoot { + return nil, fmt.Errorf("root doesn't match") + } + + proof, err := tree.Prove([]int{prove}) + if err != nil { + return nil, err + } + + offRampProof := evm_2_evm_offramp.InternalExecutionReport{ + Messages: msgs, + OffchainTokenData: tokenData, + Proofs: proof.Hashes, + ProofFlagBits: abihelpers.ProofFlagsToBits(proof.SourceFlags), + } + offRamp, err := evm_2_evm_offramp.NewEVM2EVMOffRamp(common.HexToAddress(args.OffRamp), args.DestChain) + if err != nil { + return nil, err + } + // Execute. + return offRamp.ManuallyExecute(args.DestUser, offRampProof, manualExecGasLimits) +} + +func (c *CCIPContracts) ExecuteMessage( + t *testing.T, + req logpoller.Log, + txHash common.Hash, + destStartBlock uint64, +) uint64 { + t.Log("Executing request manually") + ctx := tests.Context(t) + sendReqReceipt, err := c.Source.Chain.Client().TransactionReceipt(ctx, txHash) + require.NoError(t, err) + destLatest, err := c.Dest.Chain.Client().BlockByNumber(context.Background(), nil) + require.NoError(t, err) + args := ManualExecArgs{ + SourceChainID: c.Source.ChainID, + DestChainID: c.Dest.ChainID, + DestUser: c.Dest.User, + SourceChain: c.Source.Chain.Client(), + DestChain: c.Dest.Chain.Client(), + SourceStartBlock: sendReqReceipt.BlockNumber, + DestStartBlock: destStartBlock, + DestLatestBlockNum: destLatest.NumberU64(), + SendReqLogIndex: uint(req.LogIndex), + SendReqTxHash: txHash.String(), + CommitStore: c.Dest.CommitStore.Address().String(), + OnRamp: c.Source.OnRamp.Address().String(), + OffRamp: c.Dest.OffRamp.Address().String(), + } + tx, err := args.ExecuteManually(ctx) + require.NoError(t, err) + c.Dest.Chain.Commit() + c.Source.Chain.Commit() + rec, err := c.Dest.Chain.Client().TransactionReceipt(tests.Context(t), tx.Hash()) + require.NoError(t, err) + require.Equal(t, uint64(1), rec.Status, "manual execution failed") + t.Logf("Manual Execution completed for seqNum %d", args.SeqNr) + return args.SeqNr +} + +func GetBalance(t *testing.T, chain bind.ContractBackend, tokenAddr common.Address, addr common.Address) *big.Int { + token, err := link_token_interface.NewLinkToken(tokenAddr, chain) + require.NoError(t, err) + bal, err := token.BalanceOf(nil, addr) + require.NoError(t, err) + return bal +} diff --git a/core/services/ocr2/plugins/ccip/testhelpers/testhelpers_1_4_0/chainlink.go b/core/services/ocr2/plugins/ccip/testhelpers/testhelpers_1_4_0/chainlink.go new file mode 100644 index 00000000000..c80b376a2af --- /dev/null +++ b/core/services/ocr2/plugins/ccip/testhelpers/testhelpers_1_4_0/chainlink.go @@ -0,0 +1,1053 @@ +package testhelpers_1_4_0 + +import ( + "context" + "encoding/hex" + "fmt" + "math" + "math/big" + "net/http" + "net/http/httptest" + "strconv" + "strings" + "testing" + "time" + + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + types3 "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/ethclient/simulated" + "github.com/google/uuid" + "github.com/hashicorp/consul/sdk/freeport" + "github.com/jmoiron/sqlx" + "github.com/onsi/gomega" + "github.com/pkg/errors" + + "github.com/stretchr/testify/mock" + "github.com/stretchr/testify/require" + "go.uber.org/zap" + "k8s.io/utils/pointer" //nolint:staticcheck + + "github.com/smartcontractkit/libocr/commontypes" + "github.com/smartcontractkit/libocr/offchainreporting2/confighelper" + types4 "github.com/smartcontractkit/libocr/offchainreporting2plus/types" + + "github.com/smartcontractkit/chainlink-common/pkg/config" + "github.com/smartcontractkit/chainlink-common/pkg/loop" + "github.com/smartcontractkit/chainlink-common/pkg/utils/mailbox" + "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" + + cciptypes "github.com/smartcontractkit/chainlink-common/pkg/types/ccip" + coretypes "github.com/smartcontractkit/chainlink-common/pkg/types/core/mocks" + + pb "github.com/smartcontractkit/chainlink-protos/orchestrator/feedsmanager" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" + v2 "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/toml" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" + evmUtils "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" + "github.com/smartcontractkit/chainlink/v2/core/chains/legacyevm" + configv2 "github.com/smartcontractkit/chainlink/v2/core/config/toml" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/commit_store_1_2_0" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/evm_2_evm_offramp_1_2_0" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/evm_2_evm_onramp_1_2_0" + "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" + "github.com/smartcontractkit/chainlink/v2/core/logger" + "github.com/smartcontractkit/chainlink/v2/core/logger/audit" + "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" + feeds2 "github.com/smartcontractkit/chainlink/v2/core/services/feeds" + feedsMocks "github.com/smartcontractkit/chainlink/v2/core/services/feeds/mocks" + "github.com/smartcontractkit/chainlink/v2/core/services/job" + "github.com/smartcontractkit/chainlink/v2/core/services/keystore" + "github.com/smartcontractkit/chainlink/v2/core/services/keystore/chaintype" + "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/csakey" + "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/ocr2key" + ksMocks "github.com/smartcontractkit/chainlink/v2/core/services/keystore/mocks" + "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/abihelpers" + "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/ccipdata" + "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_2_0" + "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/testhelpers" + integrationtesthelpers "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/testhelpers/integration" + "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/validate" + "github.com/smartcontractkit/chainlink/v2/core/services/ocrbootstrap" + evmrelay "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm" + clutils "github.com/smartcontractkit/chainlink/v2/core/utils" + "github.com/smartcontractkit/chainlink/v2/core/utils/crypto" + "github.com/smartcontractkit/chainlink/v2/core/utils/testutils/heavyweight" + "github.com/smartcontractkit/chainlink/v2/plugins" +) + +const ( + execSpecTemplate = ` + type = "offchainreporting2" + schemaVersion = 1 + name = "ccip-exec-1" + externalJobID = "67ffad71-d90f-4fe3-b4e4-494924b707fb" + forwardingAllowed = false + maxTaskDuration = "0s" + contractID = "%s" + contractConfigConfirmations = 1 + contractConfigTrackerPollInterval = "20s" + ocrKeyBundleID = "%s" + relay = "evm" + pluginType = "ccip-execution" + transmitterID = "%s" + + [relayConfig] + chainID = 1_337 + + [pluginConfig] + destStartBlock = 50 + + [pluginConfig.USDCConfig] + AttestationAPI = "http://blah.com" + SourceMessageTransmitterAddress = "%s" + SourceTokenAddress = "%s" + AttestationAPITimeoutSeconds = 10 + ` + commitSpecTemplatePipeline = ` + type = "offchainreporting2" + schemaVersion = 1 + name = "ccip-commit-1" + externalJobID = "13c997cf-1a14-4ab7-9068-07ee6d2afa55" + forwardingAllowed = false + maxTaskDuration = "0s" + contractID = "%s" + contractConfigConfirmations = 1 + contractConfigTrackerPollInterval = "20s" + ocrKeyBundleID = "%s" + relay = "evm" + pluginType = "ccip-commit" + transmitterID = "%s" + + [relayConfig] + chainID = 1_337 + + [pluginConfig] + destStartBlock = 50 + offRamp = "%s" + tokenPricesUSDPipeline = """ + %s + """ + ` + commitSpecTemplateDynamicPriceGetter = ` + type = "offchainreporting2" + schemaVersion = 1 + name = "ccip-commit-1" + externalJobID = "13c997cf-1a14-4ab7-9068-07ee6d2afa55" + forwardingAllowed = false + maxTaskDuration = "0s" + contractID = "%s" + contractConfigConfirmations = 1 + contractConfigTrackerPollInterval = "20s" + ocrKeyBundleID = "%s" + relay = "evm" + pluginType = "ccip-commit" + transmitterID = "%s" + + [relayConfig] + chainID = 1_337 + + [pluginConfig] + destStartBlock = 50 + offRamp = "%s" + priceGetterConfig = """ + %s + """ + ` +) + +type Node struct { + App chainlink.Application + Transmitter common.Address + PaymentReceiver common.Address + KeyBundle ocr2key.KeyBundle +} + +func (node *Node) FindJobIDForContract(t *testing.T, addr common.Address) int32 { + jobs := node.App.JobSpawner().ActiveJobs() + for _, j := range jobs { + if j.Type == job.OffchainReporting2 && j.OCR2OracleSpec.ContractID == addr.Hex() { + return j.ID + } + } + t.Fatalf("Could not find job for contract %s", addr.Hex()) + return 0 +} + +func (node *Node) EventuallyNodeUsesUpdatedPriceRegistry(t *testing.T, ccipContracts CCIPIntegrationTestHarness) logpoller.Log { + c, err := node.App.GetRelayers().LegacyEVMChains().Get(strconv.FormatUint(ccipContracts.Dest.ChainID, 10)) + require.NoError(t, err) + var log logpoller.Log + gomega.NewGomegaWithT(t).Eventually(func() bool { + ccipContracts.Source.Chain.Commit() + ccipContracts.Dest.Chain.Commit() + log, err := c.LogPoller().LatestLogByEventSigWithConfs( + testutils.Context(t), + v1_2_0.UsdPerUnitGasUpdated, + ccipContracts.Dest.PriceRegistry.Address(), + 0, + ) + // err can be transient errors such as sql row set empty + if err != nil { + return false + } + return log != nil + }, testutils.WaitTimeout(t), 1*time.Second).Should(gomega.BeTrue(), "node is not using updated price registry %s", ccipContracts.Dest.PriceRegistry.Address().Hex()) + return log +} + +func (node *Node) EventuallyNodeUsesNewCommitConfig(t *testing.T, ccipContracts CCIPIntegrationTestHarness, commitCfg ccipdata.CommitOnchainConfig) logpoller.Log { + c, err := node.App.GetRelayers().LegacyEVMChains().Get(strconv.FormatUint(ccipContracts.Dest.ChainID, 10)) + require.NoError(t, err) + var log logpoller.Log + gomega.NewGomegaWithT(t).Eventually(func() bool { + ccipContracts.Source.Chain.Commit() + ccipContracts.Dest.Chain.Commit() + log, err := c.LogPoller().LatestLogByEventSigWithConfs( + testutils.Context(t), + evmrelay.OCR2AggregatorLogDecoder.EventSig(), + ccipContracts.Dest.CommitStore.Address(), + 0, + ) + require.NoError(t, err) + var latestCfg ccipdata.CommitOnchainConfig + if log != nil { + latestCfg, err = DecodeCommitOnChainConfig(log.Data) + require.NoError(t, err) + return latestCfg == commitCfg + } + return false + }, testutils.WaitTimeout(t), 1*time.Second).Should(gomega.BeTrue(), "node is using old cfg") + return log +} + +func (node *Node) EventuallyNodeUsesNewExecConfig(t *testing.T, ccipContracts CCIPIntegrationTestHarness, execCfg v1_2_0.ExecOnchainConfig) logpoller.Log { + c, err := node.App.GetRelayers().LegacyEVMChains().Get(strconv.FormatUint(ccipContracts.Dest.ChainID, 10)) + require.NoError(t, err) + var log logpoller.Log + gomega.NewGomegaWithT(t).Eventually(func() bool { + ccipContracts.Source.Chain.Commit() + ccipContracts.Dest.Chain.Commit() + log, err := c.LogPoller().LatestLogByEventSigWithConfs( + testutils.Context(t), + evmrelay.OCR2AggregatorLogDecoder.EventSig(), + ccipContracts.Dest.OffRamp.Address(), + 0, + ) + require.NoError(t, err) + var latestCfg v1_2_0.ExecOnchainConfig + if log != nil { + latestCfg, err = DecodeExecOnChainConfig(log.Data) + require.NoError(t, err) + return latestCfg == execCfg + } + return false + }, testutils.WaitTimeout(t), 1*time.Second).Should(gomega.BeTrue(), "node is using old cfg") + return log +} + +func (node *Node) EventuallyHasReqSeqNum(t *testing.T, ccipContracts *CCIPIntegrationTestHarness, onRamp common.Address, seqNum int) logpoller.Log { + c, err := node.App.GetRelayers().LegacyEVMChains().Get(strconv.FormatUint(ccipContracts.Source.ChainID, 10)) + require.NoError(t, err) + var log logpoller.Log + gomega.NewGomegaWithT(t).Eventually(func() bool { + ccipContracts.Source.Chain.Commit() + ccipContracts.Dest.Chain.Commit() + lgs, err := c.LogPoller().LogsDataWordRange( + testutils.Context(t), + v1_2_0.CCIPSendRequestEventSig, + onRamp, + v1_2_0.CCIPSendRequestSeqNumIndex, + abihelpers.EvmWord(uint64(seqNum)), + abihelpers.EvmWord(uint64(seqNum)), + 1, + ) + require.NoError(t, err) + t.Log("Send requested", len(lgs)) + if len(lgs) == 1 { + log = lgs[0] + return true + } + return false + }, testutils.WaitTimeout(t), 1*time.Second).Should(gomega.BeTrue(), "eventually has seq num") + return log +} + +func (node *Node) EventuallyHasExecutedSeqNums(t *testing.T, ccipContracts *CCIPIntegrationTestHarness, offRamp common.Address, minSeqNum int, maxSeqNum int) []logpoller.Log { + c, err := node.App.GetRelayers().LegacyEVMChains().Get(strconv.FormatUint(ccipContracts.Dest.ChainID, 10)) + require.NoError(t, err) + var logs []logpoller.Log + gomega.NewGomegaWithT(t).Eventually(func() bool { + ccipContracts.Source.Chain.Commit() + ccipContracts.Dest.Chain.Commit() + lgs, err := c.LogPoller().IndexedLogsTopicRange( + testutils.Context(t), + v1_2_0.ExecutionStateChangedEvent, + offRamp, + v1_2_0.ExecutionStateChangedSeqNrIndex, + abihelpers.EvmWord(uint64(minSeqNum)), + abihelpers.EvmWord(uint64(maxSeqNum)), + 1, + ) + require.NoError(t, err) + t.Logf("Have executed logs %d want %d", len(lgs), maxSeqNum-minSeqNum+1) + if len(lgs) == maxSeqNum-minSeqNum+1 { + logs = lgs + t.Logf("Seq Num %d-%d executed", minSeqNum, maxSeqNum) + return true + } + return false + }, testutils.WaitTimeout(t), 1*time.Second).Should(gomega.BeTrue(), "eventually has not executed seq num") + return logs +} + +func (node *Node) ConsistentlySeqNumHasNotBeenExecuted(t *testing.T, ccipContracts *CCIPIntegrationTestHarness, offRamp common.Address, seqNum int) logpoller.Log { + c, err := node.App.GetRelayers().LegacyEVMChains().Get(strconv.FormatUint(ccipContracts.Dest.ChainID, 10)) + require.NoError(t, err) + var log logpoller.Log + gomega.NewGomegaWithT(t).Consistently(func() bool { + ccipContracts.Source.Chain.Commit() + ccipContracts.Dest.Chain.Commit() + lgs, err := c.LogPoller().IndexedLogsTopicRange( + testutils.Context(t), + v1_2_0.ExecutionStateChangedEvent, + offRamp, + v1_2_0.ExecutionStateChangedSeqNrIndex, + abihelpers.EvmWord(uint64(seqNum)), + abihelpers.EvmWord(uint64(seqNum)), + 1, + ) + require.NoError(t, err) + t.Log("Executed logs", lgs) + if len(lgs) == 1 { + log = lgs[0] + return true + } + return false + }, 10*time.Second, 1*time.Second).Should(gomega.BeFalse(), "seq number got executed") + return log +} + +func (node *Node) AddJob(t *testing.T, spec *integrationtesthelpers.OCR2TaskJobSpec) { + specString, err := spec.String() + require.NoError(t, err) + ccipJob, err := validate.ValidatedOracleSpecToml( + testutils.Context(t), + node.App.GetConfig().OCR2(), + node.App.GetConfig().Insecure(), + specString, + // FIXME Ani + nil, + ) + require.NoError(t, err) + err = node.App.AddJobV2(tests.Context(t), &ccipJob) + require.NoError(t, err) +} + +func (node *Node) AddBootstrapJob(t *testing.T, spec *integrationtesthelpers.OCR2TaskJobSpec) { + specString, err := spec.String() + require.NoError(t, err) + ccipJob, err := ocrbootstrap.ValidatedBootstrapSpecToml(specString) + require.NoError(t, err) + err = node.App.AddJobV2(tests.Context(t), &ccipJob) + require.NoError(t, err) +} + +func (node *Node) AddJobsWithSpec(t *testing.T, jobSpec *integrationtesthelpers.OCR2TaskJobSpec) { + // set node specific values + jobSpec.OCR2OracleSpec.OCRKeyBundleID.SetValid(node.KeyBundle.ID()) + jobSpec.OCR2OracleSpec.TransmitterID.SetValid(node.Transmitter.Hex()) + node.AddJob(t, jobSpec) +} + +func setupNodeCCIP( + t *testing.T, + owner *bind.TransactOpts, + port int64, + dbName string, + sourceChain *simulated.Backend, destChain *simulated.Backend, + sourceChainID *big.Int, destChainID *big.Int, + bootstrapPeerID string, + bootstrapPort int64, +) (chainlink.Application, string, common.Address, ocr2key.KeyBundle) { + trueRef, falseRef := true, false + + // Do not want to load fixtures as they contain a dummy chainID. + loglevel := configv2.LogLevel(zap.DebugLevel) + config, db := heavyweight.FullTestDBNoFixturesV2(t, func(c *chainlink.Config, _ *chainlink.Secrets) { + p2pAddresses := []string{ + fmt.Sprintf("127.0.0.1:%d", port), + } + c.Log.Level = &loglevel + c.Feature.UICSAKeys = &trueRef + c.Feature.FeedsManager = &trueRef + c.OCR.Enabled = &falseRef + c.OCR.DefaultTransactionQueueDepth = pointer.Uint32(200) + c.OCR2.Enabled = &trueRef + c.Feature.LogPoller = &trueRef + c.P2P.V2.Enabled = &trueRef + + dur, err := config.NewDuration(500 * time.Millisecond) + if err != nil { + panic(err) + } + c.P2P.V2.DeltaDial = &dur + + dur2, err := config.NewDuration(5 * time.Second) + if err != nil { + panic(err) + } + + c.P2P.V2.DeltaReconcile = &dur2 + c.P2P.V2.ListenAddresses = &p2pAddresses + c.P2P.V2.AnnounceAddresses = &p2pAddresses + + c.EVM = []*v2.EVMConfig{createConfigV2Chain(sourceChainID), createConfigV2Chain(destChainID)} + + if bootstrapPeerID != "" { + // Supply the bootstrap IP and port as a V2 peer address + c.P2P.V2.DefaultBootstrappers = &[]commontypes.BootstrapperLocator{ + { + PeerID: bootstrapPeerID, Addrs: []string{ + fmt.Sprintf("127.0.0.1:%d", bootstrapPort), + }, + }, + } + } + }) + + lggr := logger.TestLogger(t) + + // The in-memory geth sim does not let you create a custom ChainID, it will always be 1337. + // In particular this means that if you sign an eip155 tx, the chainID used MUST be 1337 + // and the CHAINID op code will always emit 1337. To work around this to simulate a "multichain" + // test, we fake different chainIDs using the wrapped sim cltest.SimulatedBackend so the RPC + // appears to operate on different chainIDs and we use an EthKeyStoreSim wrapper which always + // signs 1337 see https://github.com/smartcontractkit/chainlink-ccip/blob/a24dd436810250a458d27d8bb3fb78096afeb79c/core/services/ocr2/plugins/ccip/testhelpers/simulated_backend.go#L35 + sourceClient := client.NewSimulatedBackendClient(t, sourceChain, sourceChainID) + destClient := client.NewSimulatedBackendClient(t, destChain, destChainID) + csaKeyStore := ksMocks.NewCSA(t) + + key, err := csakey.NewV2() + require.NoError(t, err) + csaKeyStore.On("GetAll").Return([]csakey.KeyV2{key}, nil) + keyStore := NewKsa(db, lggr, csaKeyStore) + + simEthKeyStore := testhelpers.EthKeyStoreSim{ + ETHKS: keyStore.Eth(), + CSAKS: keyStore.CSA(), + } + mailMon := mailbox.NewMonitor("CCIP", lggr.Named("Mailbox")) + evmOpts := chainlink.EVMFactoryConfig{ + ChainOpts: legacyevm.ChainOpts{ + AppConfig: config, + GenEthClient: func(chainID *big.Int) client.Client { + if chainID.String() == sourceChainID.String() { + return sourceClient + } else if chainID.String() == destChainID.String() { + return destClient + } + t.Fatalf("invalid chain ID %v", chainID.String()) + return nil + }, + MailMon: mailMon, + DS: db, + }, + CSAETHKeystore: simEthKeyStore, + } + + beholderAuthHeaders, csaPubKeyHex, err := keystore.BuildBeholderAuth(keyStore) + require.NoError(t, err) + + loopRegistry := plugins.NewLoopRegistry(lggr.Named("LoopRegistry"), config.Tracing(), config.Telemetry(), beholderAuthHeaders, csaPubKeyHex) + relayerFactory := chainlink.RelayerFactory{ + Logger: lggr, + LoopRegistry: loopRegistry, + GRPCOpts: loop.GRPCOpts{}, + CapabilitiesRegistry: coretypes.NewCapabilitiesRegistry(t), + } + testCtx := testutils.Context(t) + // evm alway enabled for backward compatibility + initOps := []chainlink.CoreRelayerChainInitFunc{ + chainlink.InitEVM(testCtx, relayerFactory, evmOpts), + } + + relayChainInterops, err := chainlink.NewCoreRelayerChainInteroperators(initOps...) + if err != nil { + t.Fatal(err) + } + + app, err := chainlink.NewApplication(chainlink.ApplicationOpts{ + Config: config, + DS: db, + KeyStore: keyStore, + RelayerChainInteroperators: relayChainInterops, + Logger: lggr, + ExternalInitiatorManager: nil, + CloseLogger: lggr.Sync, + UnrestrictedHTTPClient: &http.Client{}, + RestrictedHTTPClient: &http.Client{}, + AuditLogger: audit.NoopLogger, + MailMon: mailMon, + LoopRegistry: plugins.NewLoopRegistry(lggr, config.Tracing(), config.Telemetry(), beholderAuthHeaders, csaPubKeyHex), + }) + ctx := testutils.Context(t) + require.NoError(t, err) + require.NoError(t, app.GetKeyStore().Unlock(ctx, "password")) + _, err = app.GetKeyStore().P2P().Create(ctx) + require.NoError(t, err) + + p2pIDs, err := app.GetKeyStore().P2P().GetAll() + require.NoError(t, err) + require.Len(t, p2pIDs, 1) + peerID := p2pIDs[0].PeerID() + + _, err = app.GetKeyStore().Eth().Create(testCtx, destChainID) + require.NoError(t, err) + sendingKeys, err := app.GetKeyStore().Eth().EnabledKeysForChain(testCtx, destChainID) + require.NoError(t, err) + require.Len(t, sendingKeys, 1) + transmitter := sendingKeys[0].Address + s, err := app.GetKeyStore().Eth().GetState(testCtx, sendingKeys[0].ID(), destChainID) + require.NoError(t, err) + lggr.Debug(fmt.Sprintf("Transmitter address %s chainID %s", transmitter, s.EVMChainID.String())) + + // Fund the commitTransmitter address with some ETH + destChain.Commit() + n, err := destChain.Client().NonceAt(tests.Context(t), owner.From, nil) + require.NoError(t, err) + tx := types3.NewTransaction(n, transmitter, big.NewInt(1000000000000000000), 21000, big.NewInt(1000000000), nil) + signedTx, err := owner.Signer(owner.From, tx) + require.NoError(t, err) + err = destChain.Client().SendTransaction(tests.Context(t), signedTx) + require.NoError(t, err) + destChain.Commit() + + kb, err := app.GetKeyStore().OCR2().Create(ctx, chaintype.EVM) + require.NoError(t, err) + return app, peerID.Raw(), transmitter, kb +} + +func createConfigV2Chain(chainId *big.Int) *v2.EVMConfig { + // NOTE: For the executor jobs, the default of 500k is insufficient for a 3 message batch + defaultGasLimit := uint64(5000000) + tr := true + + sourceC := v2.Defaults((*evmUtils.Big)(chainId)) + sourceC.GasEstimator.LimitDefault = &defaultGasLimit + fixedPrice := "FixedPrice" + sourceC.GasEstimator.Mode = &fixedPrice + d, _ := config.NewDuration(100 * time.Millisecond) + sourceC.LogPollInterval = &d + fd := uint32(2) + sourceC.FinalityDepth = &fd + return &v2.EVMConfig{ + ChainID: (*evmUtils.Big)(chainId), + Enabled: &tr, + Chain: sourceC, + Nodes: v2.EVMNodes{&v2.Node{}}, + } +} + +type CCIPIntegrationTestHarness struct { + CCIPContracts + Nodes []Node + Bootstrap Node +} + +func SetupCCIPIntegrationTH(t *testing.T, sourceChainID, sourceChainSelector, destChainId, destChainSelector uint64) CCIPIntegrationTestHarness { + return CCIPIntegrationTestHarness{ + CCIPContracts: SetupCCIPContracts(t, sourceChainID, sourceChainSelector, destChainId, destChainSelector), + } +} + +func (c *CCIPIntegrationTestHarness) CreatePricesPipeline(t *testing.T) (string, *httptest.Server, *httptest.Server) { + linkUSD := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { + _, err := w.Write([]byte(`{"UsdPerLink": "8000000000000000000"}`)) + require.NoError(t, err) + })) + ethUSD := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { + _, err := w.Write([]byte(`{"UsdPerETH": "1700000000000000000000"}`)) + require.NoError(t, err) + })) + sourceWrappedNative, err := c.Source.Router.GetWrappedNative(nil) + require.NoError(t, err) + destWrappedNative, err := c.Dest.Router.GetWrappedNative(nil) + require.NoError(t, err) + tokenPricesUSDPipeline := fmt.Sprintf(` +// Price 1 +link [type=http method=GET url="%s"]; +link_parse [type=jsonparse path="UsdPerLink"]; +link->link_parse; +eth [type=http method=GET url="%s"]; +eth_parse [type=jsonparse path="UsdPerETH"]; +eth->eth_parse; +merge [type=merge left="{}" right="{\\\"%s\\\":$(link_parse), \\\"%s\\\":$(eth_parse), \\\"%s\\\":$(eth_parse)}"];`, + linkUSD.URL, ethUSD.URL, c.Dest.LinkToken.Address(), sourceWrappedNative, destWrappedNative) + + return tokenPricesUSDPipeline, linkUSD, ethUSD +} + +func (c *CCIPIntegrationTestHarness) AddAllJobs(t *testing.T, jobParams integrationtesthelpers.CCIPJobSpecParams) { + jobParams.OffRamp = c.Dest.OffRamp.Address() + + commitSpec, err := jobParams.CommitJobSpec() + require.NoError(t, err) + geExecutionSpec, err := jobParams.ExecutionJobSpec() + require.NoError(t, err) + nodes := c.Nodes + for _, node := range nodes { + node.AddJobsWithSpec(t, commitSpec) + node.AddJobsWithSpec(t, geExecutionSpec) + } +} + +func (c *CCIPIntegrationTestHarness) jobSpecProposal(t *testing.T, specTemplate string, f func() (*integrationtesthelpers.OCR2TaskJobSpec, error), feedsManagerId int64, version int32, opts ...any) feeds2.ProposeJobArgs { + spec, err := f() + require.NoError(t, err) + + args := []any{spec.OCR2OracleSpec.ContractID} + args = append(args, opts...) + + return feeds2.ProposeJobArgs{ + FeedsManagerID: feedsManagerId, + RemoteUUID: uuid.New(), + Multiaddrs: nil, + Version: version, + Spec: fmt.Sprintf(specTemplate, args...), + } +} + +func (c *CCIPIntegrationTestHarness) SetupFeedsManager(t *testing.T) { + ctx := testutils.Context(t) + for _, node := range c.Nodes { + f := node.App.GetFeedsService() + + managers, err := f.ListManagers(ctx) + require.NoError(t, err) + if len(managers) > 0 { + // Use at most one feeds manager, don't register if one already exists + continue + } + + secret := utils.RandomBytes32() + pkey, err := crypto.PublicKeyFromHex(hex.EncodeToString(secret[:])) + require.NoError(t, err) + + m := feeds2.RegisterManagerParams{ + Name: "CCIP", + URI: "http://localhost:8080", + PublicKey: *pkey, + } + + _, err = f.RegisterManager(testutils.Context(t), m) + require.NoError(t, err) + + connManager := feedsMocks.NewConnectionsManager(t) + connManager.On("GetClient", mock.Anything).Maybe().Return(NoopFeedsClient{}, nil) + connManager.On("Close").Maybe().Return() + connManager.On("IsConnected", mock.Anything).Maybe().Return(true) + f.Unsafe_SetConnectionsManager(connManager) + } +} + +func (c *CCIPIntegrationTestHarness) ApproveJobSpecs(t *testing.T, jobParams integrationtesthelpers.CCIPJobSpecParams) { + ctx := testutils.Context(t) + + for _, node := range c.Nodes { + f := node.App.GetFeedsService() + managers, err := f.ListManagers(ctx) + require.NoError(t, err) + require.Len(t, managers, 1, "expected exactly one feeds manager") + + execSpec := c.jobSpecProposal( + t, + execSpecTemplate, + jobParams.ExecutionJobSpec, + managers[0].ID, + 1, + node.KeyBundle.ID(), + node.Transmitter.Hex(), + utils.RandomAddress().String(), + utils.RandomAddress().String(), + ) + execId, err := f.ProposeJob(ctx, &execSpec) + require.NoError(t, err) + + err = f.ApproveSpec(ctx, execId, true) + require.NoError(t, err) + + var commitSpec feeds2.ProposeJobArgs + if jobParams.TokenPricesUSDPipeline != "" { + commitSpec = c.jobSpecProposal( + t, + commitSpecTemplatePipeline, + jobParams.CommitJobSpec, + managers[0].ID, + 2, + node.KeyBundle.ID(), + node.Transmitter.Hex(), + jobParams.OffRamp.String(), + jobParams.TokenPricesUSDPipeline, + ) + } else { + commitSpec = c.jobSpecProposal( + t, + commitSpecTemplateDynamicPriceGetter, + jobParams.CommitJobSpec, + managers[0].ID, + 2, + node.KeyBundle.ID(), + node.Transmitter.Hex(), + jobParams.OffRamp.String(), + jobParams.PriceGetterConfig, + ) + } + + commitId, err := f.ProposeJob(ctx, &commitSpec) + require.NoError(t, err) + + err = f.ApproveSpec(ctx, commitId, true) + require.NoError(t, err) + } +} + +func (c *CCIPIntegrationTestHarness) AllNodesHaveReqSeqNum(t *testing.T, seqNum int, onRampOpts ...common.Address) logpoller.Log { + var log logpoller.Log + nodes := c.Nodes + var onRamp common.Address + if len(onRampOpts) > 0 { + onRamp = onRampOpts[0] + } else { + require.NotNil(t, c.Source.OnRamp, "no onramp configured") + onRamp = c.Source.OnRamp.Address() + } + for _, node := range nodes { + log = node.EventuallyHasReqSeqNum(t, c, onRamp, seqNum) + } + return log +} + +func (c *CCIPIntegrationTestHarness) AllNodesHaveExecutedSeqNums(t *testing.T, minSeqNum int, maxSeqNum int, offRampOpts ...common.Address) []logpoller.Log { + var logs []logpoller.Log + nodes := c.Nodes + var offRamp common.Address + + if len(offRampOpts) > 0 { + offRamp = offRampOpts[0] + } else { + require.NotNil(t, c.Dest.OffRamp, "no offramp configured") + offRamp = c.Dest.OffRamp.Address() + } + for _, node := range nodes { + logs = node.EventuallyHasExecutedSeqNums(t, c, offRamp, minSeqNum, maxSeqNum) + } + return logs +} + +func (c *CCIPIntegrationTestHarness) NoNodesHaveExecutedSeqNum(t *testing.T, seqNum int, offRampOpts ...common.Address) logpoller.Log { + var log logpoller.Log + nodes := c.Nodes + var offRamp common.Address + if len(offRampOpts) > 0 { + offRamp = offRampOpts[0] + } else { + require.NotNil(t, c.Dest.OffRamp, "no offramp configured") + offRamp = c.Dest.OffRamp.Address() + } + for _, node := range nodes { + log = node.ConsistentlySeqNumHasNotBeenExecuted(t, c, offRamp, seqNum) + } + return log +} + +func (c *CCIPIntegrationTestHarness) EventuallyCommitReportAccepted(t *testing.T, currentBlock uint64, commitStoreOpts ...common.Address) commit_store_1_2_0.CommitStoreCommitReport { + var commitStore *commit_store_1_2_0.CommitStore + var err error + if len(commitStoreOpts) > 0 { + commitStore, err = commit_store_1_2_0.NewCommitStore(commitStoreOpts[0], c.Dest.Chain.Client()) + require.NoError(t, err) + } else { + require.NotNil(t, c.Dest.CommitStore, "no commitStore configured") + commitStore = c.Dest.CommitStore + } + g := gomega.NewGomegaWithT(t) + var report commit_store_1_2_0.CommitStoreCommitReport + g.Eventually(func() bool { + it, err := commitStore.FilterReportAccepted(&bind.FilterOpts{Start: currentBlock}) + g.Expect(err).NotTo(gomega.HaveOccurred(), "Error filtering ReportAccepted event") + g.Expect(it.Next()).To(gomega.BeTrue(), "No ReportAccepted event found") + report = it.Event.Report + if report.MerkleRoot != [32]byte{} { + t.Log("Report Accepted by commitStore") + return true + } + return false + }, testutils.WaitTimeout(t), 1*time.Second).Should(gomega.BeTrue(), "report has not been committed") + return report +} + +func (c *CCIPIntegrationTestHarness) EventuallyExecutionStateChangedToSuccess(t *testing.T, seqNum []uint64, blockNum uint64, offRampOpts ...common.Address) { + var offRamp *evm_2_evm_offramp_1_2_0.EVM2EVMOffRamp + var err error + if len(offRampOpts) > 0 { + offRamp, err = evm_2_evm_offramp_1_2_0.NewEVM2EVMOffRamp(offRampOpts[0], c.Dest.Chain.Client()) + require.NoError(t, err) + } else { + require.NotNil(t, c.Dest.OffRamp, "no offRamp configured") + offRamp = c.Dest.OffRamp + } + gomega.NewGomegaWithT(t).Eventually(func() bool { + it, err := offRamp.FilterExecutionStateChanged(&bind.FilterOpts{Start: blockNum}, seqNum, [][32]byte{}) + require.NoError(t, err) + for it.Next() { + if cciptypes.MessageExecutionState(it.Event.State) == cciptypes.ExecutionStateSuccess { + t.Logf("ExecutionStateChanged event found for seqNum %d", it.Event.SequenceNumber) + return true + } + } + c.Source.Chain.Commit() + c.Dest.Chain.Commit() + return false + }, testutils.WaitTimeout(t), time.Second). + Should(gomega.BeTrue(), "ExecutionStateChanged Event") +} + +func (c *CCIPIntegrationTestHarness) EventuallyReportCommitted(t *testing.T, max int, commitStoreOpts ...common.Address) uint64 { + var commitStore *commit_store_1_2_0.CommitStore + var err error + var committedSeqNum uint64 + if len(commitStoreOpts) > 0 { + commitStore, err = commit_store_1_2_0.NewCommitStore(commitStoreOpts[0], c.Dest.Chain.Client()) + require.NoError(t, err) + } else { + require.NotNil(t, c.Dest.CommitStore, "no commitStore configured") + commitStore = c.Dest.CommitStore + } + gomega.NewGomegaWithT(t).Eventually(func() bool { + minSeqNum, err := commitStore.GetExpectedNextSequenceNumber(nil) + require.NoError(t, err) + c.Source.Chain.Commit() + c.Dest.Chain.Commit() + t.Log("next expected seq num reported", minSeqNum) + committedSeqNum = minSeqNum + return minSeqNum > uint64(max) + }, testutils.WaitTimeout(t), time.Second).Should(gomega.BeTrue(), "report has not been committed") + return committedSeqNum +} + +func (c *CCIPIntegrationTestHarness) EventuallySendRequested(t *testing.T, seqNum uint64, onRampOpts ...common.Address) { + var onRamp *evm_2_evm_onramp_1_2_0.EVM2EVMOnRamp + var err error + if len(onRampOpts) > 0 { + onRamp, err = evm_2_evm_onramp_1_2_0.NewEVM2EVMOnRamp(onRampOpts[0], c.Source.Chain.Client()) + require.NoError(t, err) + } else { + require.NotNil(t, c.Source.OnRamp, "no onRamp configured") + onRamp = c.Source.OnRamp + } + gomega.NewGomegaWithT(t).Eventually(func() bool { + it, err := onRamp.FilterCCIPSendRequested(nil) + require.NoError(t, err) + for it.Next() { + if it.Event.Message.SequenceNumber == seqNum { + t.Log("sendRequested generated for", seqNum) + return true + } + } + c.Source.Chain.Commit() + c.Dest.Chain.Commit() + return false + }, testutils.WaitTimeout(t), time.Second).Should(gomega.BeTrue(), "sendRequested has not been generated") +} + +func (c *CCIPIntegrationTestHarness) ConsistentlyReportNotCommitted(t *testing.T, max int, commitStoreOpts ...common.Address) { + var commitStore *commit_store_1_2_0.CommitStore + var err error + if len(commitStoreOpts) > 0 { + commitStore, err = commit_store_1_2_0.NewCommitStore(commitStoreOpts[0], c.Dest.Chain.Client()) + require.NoError(t, err) + } else { + require.NotNil(t, c.Dest.CommitStore, "no commitStore configured") + commitStore = c.Dest.CommitStore + } + gomega.NewGomegaWithT(t).Consistently(func() bool { + minSeqNum, err := commitStore.GetExpectedNextSequenceNumber(nil) + require.NoError(t, err) + c.Source.Chain.Commit() + c.Dest.Chain.Commit() + t.Log("min seq num reported", minSeqNum) + require.GreaterOrEqual(t, max, 0) + return minSeqNum > uint64(max) //nolint:gosec // G115 false positive + }, testutils.WaitTimeout(t), time.Second).Should(gomega.BeFalse(), "report has been committed") +} + +func (c *CCIPIntegrationTestHarness) SetupAndStartNodes(ctx context.Context, t *testing.T, bootstrapNodePort int64) (Node, []Node, uint64) { + appBootstrap, bootstrapPeerID, bootstrapTransmitter, bootstrapKb := setupNodeCCIP(t, c.Dest.User, bootstrapNodePort, + "bootstrap_ccip", c.Source.Chain, c.Dest.Chain, big.NewInt(0).SetUint64(c.Source.ChainID), + big.NewInt(0).SetUint64(c.Dest.ChainID), "", 0) + var ( + oracles []confighelper.OracleIdentityExtra + nodes []Node + ) + err := appBootstrap.Start(ctx) + require.NoError(t, err) + t.Cleanup(func() { + require.NoError(t, appBootstrap.Stop()) + }) + bootstrapNode := Node{ + App: appBootstrap, + Transmitter: bootstrapTransmitter, + KeyBundle: bootstrapKb, + } + // Set up the minimum 4 oracles all funded with destination ETH + for i := int64(0); i < 4; i++ { + app, peerID, transmitter, kb := setupNodeCCIP( + t, + c.Dest.User, + int64(freeport.GetOne(t)), + fmt.Sprintf("oracle_ccip%d", i), + c.Source.Chain, + c.Dest.Chain, + big.NewInt(0).SetUint64(c.Source.ChainID), + big.NewInt(0).SetUint64(c.Dest.ChainID), + bootstrapPeerID, + bootstrapNodePort, + ) + nodes = append(nodes, Node{ + App: app, + Transmitter: transmitter, + KeyBundle: kb, + }) + offchainPublicKey, _ := hex.DecodeString(strings.TrimPrefix(kb.OnChainPublicKey(), "0x")) + oracles = append(oracles, confighelper.OracleIdentityExtra{ + OracleIdentity: confighelper.OracleIdentity{ + OnchainPublicKey: offchainPublicKey, + TransmitAccount: types4.Account(transmitter.String()), + OffchainPublicKey: kb.OffchainPublicKey(), + PeerID: peerID, + }, + ConfigEncryptionPublicKey: kb.ConfigEncryptionPublicKey(), + }) + err = app.Start(ctx) + require.NoError(t, err) + t.Cleanup(func() { + require.NoError(t, app.Stop()) + }) + } + + c.Oracles = oracles + commitOnchainConfig := c.CreateDefaultCommitOnchainConfig(t) + commitOffchainConfig := c.CreateDefaultCommitOffchainConfig(t) + execOnchainConfig := c.CreateDefaultExecOnchainConfig(t) + execOffchainConfig := c.CreateDefaultExecOffchainConfig(t) + + configBlock := c.SetupOnchainConfig(t, commitOnchainConfig, commitOffchainConfig, execOnchainConfig, execOffchainConfig) + c.Nodes = nodes + c.Bootstrap = bootstrapNode + //nolint:gosec // G115 + return bootstrapNode, nodes, uint64(configBlock) +} + +func (c *CCIPIntegrationTestHarness) SetUpNodesAndJobs(t *testing.T, pricePipeline string, priceGetterConfig string, usdcAttestationAPI string) integrationtesthelpers.CCIPJobSpecParams { + // setup Jobs + ctx := tests.Context(t) + // Starts nodes and configures them in the OCR contracts. + bootstrapNode, _, configBlock := c.SetupAndStartNodes(ctx, t, int64(freeport.GetOne(t))) + + jobParams := c.NewCCIPJobSpecParams(pricePipeline, priceGetterConfig, configBlock, usdcAttestationAPI) + + // Add the bootstrap job + c.Bootstrap.AddBootstrapJob(t, jobParams.BootstrapJob(c.Dest.CommitStore.Address().Hex())) + c.AddAllJobs(t, jobParams) + + // Replay for bootstrap. + bc, err := bootstrapNode.App.GetRelayers().LegacyEVMChains().Get(strconv.FormatUint(c.Dest.ChainID, 10)) + require.NoError(t, err) + require.LessOrEqual(t, configBlock, uint64(math.MaxInt64)) + require.NoError(t, bc.LogPoller().Replay(tests.Context(t), int64(configBlock))) //nolint:gosec // G115 false positive + c.Dest.Chain.Commit() + + return jobParams +} + +func (c *CCIPIntegrationTestHarness) NewCCIPJobSpecParams(tokenPricesUSDPipeline string, priceGetterConfig string, configBlock uint64, usdcAttestationAPI string) integrationtesthelpers.CCIPJobSpecParams { + return integrationtesthelpers.CCIPJobSpecParams{ + CommitStore: c.Dest.CommitStore.Address(), + OffRamp: c.Dest.OffRamp.Address(), + DestEvmChainId: c.Dest.ChainID, + SourceChainName: "SimulatedSource", + DestChainName: "SimulatedDest", + TokenPricesUSDPipeline: tokenPricesUSDPipeline, + PriceGetterConfig: priceGetterConfig, + DestStartBlock: configBlock, + USDCAttestationAPI: usdcAttestationAPI, + } +} + +func DecodeCommitOnChainConfig(encoded []byte) (ccipdata.CommitOnchainConfig, error) { + var onchainConfig ccipdata.CommitOnchainConfig + unpacked, err := abihelpers.DecodeOCR2Config(encoded) + if err != nil { + return onchainConfig, err + } + onChainCfg := unpacked.OnchainConfig + onchainConfig, err = abihelpers.DecodeAbiStruct[ccipdata.CommitOnchainConfig](onChainCfg) + if err != nil { + return onchainConfig, err + } + return onchainConfig, nil +} + +func DecodeExecOnChainConfig(encoded []byte) (v1_2_0.ExecOnchainConfig, error) { + var onchainConfig v1_2_0.ExecOnchainConfig + unpacked, err := abihelpers.DecodeOCR2Config(encoded) + if err != nil { + return onchainConfig, errors.Wrap(err, "failed to unpack log data") + } + onChainCfg := unpacked.OnchainConfig + onchainConfig, err = abihelpers.DecodeAbiStruct[v1_2_0.ExecOnchainConfig](onChainCfg) + if err != nil { + return onchainConfig, err + } + return onchainConfig, nil +} + +type ksa struct { + keystore.Master + csa keystore.CSA +} + +func (k *ksa) CSA() keystore.CSA { + return k.csa +} + +func NewKsa(db *sqlx.DB, lggr logger.Logger, csa keystore.CSA) *ksa { + return &ksa{ + Master: keystore.New(db, clutils.FastScryptParams, lggr), + csa: csa, + } +} + +type NoopFeedsClient struct{} + +func (n NoopFeedsClient) ApprovedJob(context.Context, *pb.ApprovedJobRequest) (*pb.ApprovedJobResponse, error) { + return &pb.ApprovedJobResponse{}, nil +} + +func (n NoopFeedsClient) Healthcheck(context.Context, *pb.HealthcheckRequest) (*pb.HealthcheckResponse, error) { + return &pb.HealthcheckResponse{}, nil +} + +func (n NoopFeedsClient) UpdateNode(context.Context, *pb.UpdateNodeRequest) (*pb.UpdateNodeResponse, error) { + return &pb.UpdateNodeResponse{}, nil +} + +func (n NoopFeedsClient) RejectedJob(context.Context, *pb.RejectedJobRequest) (*pb.RejectedJobResponse, error) { + return &pb.RejectedJobResponse{}, nil +} + +func (n NoopFeedsClient) CancelledJob(context.Context, *pb.CancelledJobRequest) (*pb.CancelledJobResponse, error) { + return &pb.CancelledJobResponse{}, nil +} diff --git a/core/services/ocr2/plugins/ccip/testhelpers/testhelpers_1_4_0/config_1_4_0.go b/core/services/ocr2/plugins/ccip/testhelpers/testhelpers_1_4_0/config_1_4_0.go new file mode 100644 index 00000000000..087c21e9333 --- /dev/null +++ b/core/services/ocr2/plugins/ccip/testhelpers/testhelpers_1_4_0/config_1_4_0.go @@ -0,0 +1,75 @@ +// Package with set of configs that should be used only within tests suites + +package testhelpers_1_4_0 + +import ( + "testing" + "time" + + "github.com/stretchr/testify/require" + + "github.com/smartcontractkit/chainlink-common/pkg/config" + + "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/abihelpers" + "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/ccipdata" + "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_2_0" + "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/testhelpers" +) + +var PermissionLessExecutionThresholdSeconds = uint32(testhelpers.FirstBlockAge.Seconds()) + +func (c *CCIPContracts) CreateDefaultCommitOnchainConfig(t *testing.T) []byte { + config, err := abihelpers.EncodeAbiStruct(ccipdata.CommitOnchainConfig{ + PriceRegistry: c.Dest.PriceRegistry.Address(), + }) + require.NoError(t, err) + return config +} + +func (c *CCIPContracts) CreateDefaultCommitOffchainConfig(t *testing.T) []byte { + return c.createCommitOffchainConfig(t, 10*time.Second, 5*time.Second) +} + +func (c *CCIPContracts) createCommitOffchainConfig(t *testing.T, feeUpdateHearBeat time.Duration, inflightCacheExpiry time.Duration) []byte { + config, err := NewCommitOffchainConfig( + *config.MustNewDuration(feeUpdateHearBeat), + 1, + 1, + *config.MustNewDuration(feeUpdateHearBeat), + 1, + *config.MustNewDuration(inflightCacheExpiry), + false, + ).Encode() + require.NoError(t, err) + return config +} + +func (c *CCIPContracts) CreateDefaultExecOnchainConfig(t *testing.T) []byte { + config, err := abihelpers.EncodeAbiStruct(v1_2_0.ExecOnchainConfig{ + PermissionLessExecutionThresholdSeconds: PermissionLessExecutionThresholdSeconds, + Router: c.Dest.Router.Address(), + PriceRegistry: c.Dest.PriceRegistry.Address(), + MaxDataBytes: 1e5, + MaxNumberOfTokensPerMsg: 5, + MaxPoolReleaseOrMintGas: 200_000, + }) + require.NoError(t, err) + return config +} + +func (c *CCIPContracts) CreateDefaultExecOffchainConfig(t *testing.T) []byte { + return c.createExecOffchainConfig(t, 1*time.Minute, 1*time.Minute) +} + +func (c *CCIPContracts) createExecOffchainConfig(t *testing.T, inflightCacheExpiry time.Duration, rootSnoozeTime time.Duration) []byte { + config, err := NewExecOffchainConfig( + 1, + 5_000_000, + 0.07, + *config.MustNewDuration(inflightCacheExpiry), + *config.MustNewDuration(rootSnoozeTime), + uint32(0), + ).Encode() + require.NoError(t, err) + return config +} diff --git a/core/services/ocr2/plugins/functions/integration_tests/v1/internal/testutils.go b/core/services/ocr2/plugins/functions/integration_tests/v1/internal/testutils.go index 98aea240134..a42997add2d 100644 --- a/core/services/ocr2/plugins/functions/integration_tests/v1/internal/testutils.go +++ b/core/services/ocr2/plugins/functions/integration_tests/v1/internal/testutils.go @@ -45,8 +45,8 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" "github.com/smartcontractkit/chainlink/v2/core/services/functions" "github.com/smartcontractkit/chainlink/v2/core/services/job" + "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/keystest" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/ocr2key" - "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/p2pkey" functionsConfig "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/functions/config" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/validate" "github.com/smartcontractkit/chainlink/v2/core/services/ocrbootstrap" @@ -321,7 +321,7 @@ func StartNewNode( thresholdKeyShare string, ) *Node { ctx := testutils.Context(t) - p2pKey := p2pkey.MustNewV2XXXTestingOnly(big.NewInt(int64(port))) + p2pKey := keystest.NewP2PKeyV2(t) config, _ := heavyweight.FullTestDBV2(t, func(c *chainlink.Config, s *chainlink.Secrets) { c.Insecure.OCRDevelopmentMode = ptr(true) diff --git a/core/services/ocr2/plugins/generic/relayerset_test.go b/core/services/ocr2/plugins/generic/relayerset_test.go index cd9d28ffd60..44ed216520f 100644 --- a/core/services/ocr2/plugins/generic/relayerset_test.go +++ b/core/services/ocr2/plugins/generic/relayerset_test.go @@ -150,7 +150,7 @@ func (t *TestRelayer) Ready() error { panic("implement me") } func (t *TestRelayer) HealthReport() map[string]error { panic("implement me") } -func (t *TestRelayer) NewContractWriter(_ context.Context, _ []byte) (types.ContractWriter, error) { +func (t *TestRelayer) NewChainWriter(_ context.Context, _ []byte) (types.ChainWriter, error) { panic("implement me") } diff --git a/core/services/ocr2/plugins/llo/config/config.go b/core/services/ocr2/plugins/llo/config/config.go index ca272b73d55..7bd36b4ff8b 100644 --- a/core/services/ocr2/plugins/llo/config/config.go +++ b/core/services/ocr2/plugins/llo/config/config.go @@ -88,6 +88,8 @@ func (p PluginConfig) Validate() (merr error) { if err := json.Unmarshal([]byte(p.ChannelDefinitions), &cd); err != nil { merr = errors.Join(merr, fmt.Errorf("channelDefinitions is invalid JSON: %w", err)) } + // TODO: Verify Opts format here? + // MERC-3524 } else { if p.ChannelDefinitionsContractAddress == (common.Address{}) { merr = errors.Join(merr, errors.New("llo: ChannelDefinitionsContractAddress is required if ChannelDefinitions is not specified")) diff --git a/core/services/ocr2/plugins/llo/helpers_test.go b/core/services/ocr2/plugins/llo/helpers_test.go index 9cd8742ffa8..0ca6eeb60cb 100644 --- a/core/services/ocr2/plugins/llo/helpers_test.go +++ b/core/services/ocr2/plugins/llo/helpers_test.go @@ -185,7 +185,6 @@ func setupNode( // [Mercury] c.Mercury.VerboseLogging = ptr(true) - c.Mercury.Transmitter.TransmitConcurrency = ptr(uint32(5)) // Avoid a ridiculous number of goroutines }) lggr, observedLogs := logger.TestLoggerObserved(t, zapcore.DebugLevel) diff --git a/core/services/ocr2/plugins/llo/integration_test.go b/core/services/ocr2/plugins/llo/integration_test.go index 0491c29b39c..bdd773910f4 100644 --- a/core/services/ocr2/plugins/llo/integration_test.go +++ b/core/services/ocr2/plugins/llo/integration_test.go @@ -342,6 +342,11 @@ func TestIntegration_LLO(t *testing.T) { multiplier := decimal.New(1, 18) expirationWindow := time.Hour / time.Second + reqs := make(chan request, 100000) + serverKey := csakey.MustNewV2XXXTestingOnly(big.NewInt(-1)) + serverPubKey := serverKey.PublicKey + srv := NewMercuryServer(t, ed25519.PrivateKey(serverKey.Raw()), reqs) + clientCSAKeys := make([]csakey.KeyV2, nNodes) clientPubKeys := make([]ed25519.PublicKey, nNodes) for i := 0; i < nNodes; i++ { @@ -361,11 +366,6 @@ func TestIntegration_LLO(t *testing.T) { bootstrapNode := Node{App: appBootstrap, KeyBundle: bootstrapKb} t.Run("using legacy verifier configuration contract, produces reports in v0.3 format", func(t *testing.T) { - reqs := make(chan request, 100000) - serverKey := csakey.MustNewV2XXXTestingOnly(big.NewInt(-1)) - serverPubKey := serverKey.PublicKey - srv := NewMercuryServer(t, ed25519.PrivateKey(serverKey.Raw()), reqs) - serverURL := startMercuryServer(t, srv, clientPubKeys) donID := uint32(995544) @@ -509,8 +509,7 @@ channelDefinitionsContractFromBlock = %d`, serverURL, serverPubKey, donID, confi assert.Equal(t, expectedBid.String(), reportElems["bid"].(*big.Int).String()) assert.Equal(t, expectedAsk.String(), reportElems["ask"].(*big.Int).String()) - // emulate mercury server verifying report (local verification) - { + t.Run(fmt.Sprintf("emulate mercury server verifying report (local verification) - node %x", req.pk), func(t *testing.T) { rv := mercuryverifier.NewVerifier() reportSigners, err := rv.Verify(mercuryverifier.SignedReport{ @@ -523,16 +522,13 @@ channelDefinitionsContractFromBlock = %d`, serverURL, serverPubKey, donID, confi require.NoError(t, err) assert.GreaterOrEqual(t, len(reportSigners), int(fNodes+1)) assert.Subset(t, signerAddresses, reportSigners) - } + }) - // test on-chain verification - t.Run("on-chain verification", func(t *testing.T) { - t.Skip("SKIP - MERC-6637") - // Disabled because it flakes, sometimes returns "execution reverted" - // No idea why - // https://smartcontract-it.atlassian.net/browse/MERC-6637 - _, err = verifierProxy.Verify(steve, req.req.Payload, []byte{}) - require.NoError(t, err) + t.Run(fmt.Sprintf("test on-chain verification - node %x", req.pk), func(t *testing.T) { + t.Run("destination verifier", func(t *testing.T) { + _, err = verifierProxy.Verify(steve, req.req.Payload, []byte{}) + require.NoError(t, err) + }) }) t.Logf("oracle %x reported for 0x%x", req.pk[:], feedID[:]) @@ -550,11 +546,6 @@ channelDefinitionsContractFromBlock = %d`, serverURL, serverPubKey, donID, confi }) t.Run("Blue/Green lifecycle (using JSON report format)", func(t *testing.T) { - reqs := make(chan request, 100000) - serverKey := csakey.MustNewV2XXXTestingOnly(big.NewInt(-2)) - serverPubKey := serverKey.PublicKey - srv := NewMercuryServer(t, ed25519.PrivateKey(serverKey.Raw()), reqs) - serverURL := startMercuryServer(t, srv, clientPubKeys) donID := uint32(888333) @@ -606,8 +597,7 @@ channelDefinitionsContractFromBlock = %d`, serverURL, serverPubKey, donID, confi var greenDigest ocr2types.ConfigDigest allReports := make(map[types.ConfigDigest][]datastreamsllo.Report) - // start off with blue=production, green=staging (specimen reports) - { + t.Run("start off with blue=production, green=staging (specimen reports)", func(t *testing.T) { // Set config on configurator blueDigest = setProductionConfig( t, donID, steve, backend, configurator, configuratorAddress, nodes, oracles, @@ -627,9 +617,8 @@ channelDefinitionsContractFromBlock = %d`, serverURL, serverPubKey, donID, confi assert.Equal(t, "2976.39", r.Values[0].(*datastreamsllo.Decimal).String()) break } - } - // setStagingConfig does not affect production - { + }) + t.Run("setStagingConfig does not affect production", func(t *testing.T) { greenDigest = setStagingConfig( t, donID, steve, backend, configurator, configuratorAddress, nodes, oracles, blueDigest, ) @@ -650,9 +639,8 @@ channelDefinitionsContractFromBlock = %d`, serverURL, serverPubKey, donID, confi } assert.Equal(t, blueDigest, r.ConfigDigest) } - } - // promoteStagingConfig flow has clean and gapless hand off from old production to newly promoted staging instance, leaving old production instance in 'retired' state - { + }) + t.Run("promoteStagingConfig flow has clean and gapless hand off from old production to newly promoted staging instance, leaving old production instance in 'retired' state", func(t *testing.T) { promoteStagingConfig(t, donID, steve, backend, configurator, configuratorAddress, false) // NOTE: Wait for first non-specimen report for the newly promoted (green) instance @@ -716,9 +704,8 @@ channelDefinitionsContractFromBlock = %d`, serverURL, serverPubKey, donID, confi assert.Less(t, finalBlueReport.ValidAfterSeconds, finalBlueReport.ObservationTimestampSeconds) assert.Equal(t, finalBlueReport.ObservationTimestampSeconds, initialPromotedGreenReport.ValidAfterSeconds) assert.Less(t, initialPromotedGreenReport.ValidAfterSeconds, initialPromotedGreenReport.ObservationTimestampSeconds) - } - // retired instance does not produce reports - { + }) + t.Run("retired instance does not produce reports", func(t *testing.T) { // NOTE: Wait for five "green" reports to be produced and assert no "blue" reports i := 0 @@ -734,9 +721,8 @@ channelDefinitionsContractFromBlock = %d`, serverURL, serverPubKey, donID, confi assert.False(t, r.Specimen) assert.Equal(t, greenDigest, r.ConfigDigest) } - } - // setStagingConfig replaces 'retired' instance with new config and starts producing specimen reports again - { + }) + t.Run("setStagingConfig replaces 'retired' instance with new config and starts producing specimen reports again", func(t *testing.T) { blueDigest = setStagingConfig( t, donID, steve, backend, configurator, configuratorAddress, nodes, oracles, greenDigest, ) @@ -754,9 +740,8 @@ channelDefinitionsContractFromBlock = %d`, serverURL, serverPubKey, donID, confi } assert.Equal(t, greenDigest, r.ConfigDigest) } - } - // promoteStagingConfig swaps the instances again - { + }) + t.Run("promoteStagingConfig swaps the instances again", func(t *testing.T) { // TODO: Check that once an instance enters 'retired' state, it // doesn't produce reports or bother making observations promoteStagingConfig(t, donID, steve, backend, configurator, configuratorAddress, true) @@ -781,9 +766,8 @@ channelDefinitionsContractFromBlock = %d`, serverURL, serverPubKey, donID, confi assert.Less(t, finalGreenReport.ValidAfterSeconds, finalGreenReport.ObservationTimestampSeconds) assert.Equal(t, finalGreenReport.ObservationTimestampSeconds, initialPromotedBlueReport.ValidAfterSeconds) assert.Less(t, initialPromotedBlueReport.ValidAfterSeconds, initialPromotedBlueReport.ObservationTimestampSeconds) - } - // adding a new channel definition is picked up on the fly - { + }) + t.Run("adding a new channel definition is picked up on the fly", func(t *testing.T) { channelDefinitions[2] = llotypes.ChannelDefinition{ ReportFormat: llotypes.ReportFormatJSON, Streams: []llotypes.Stream{ @@ -821,7 +805,7 @@ channelDefinitionsContractFromBlock = %d`, serverURL, serverPubKey, donID, confi assert.Len(t, r.Values, 1) assert.Equal(t, "2976.39", r.Values[0].(*datastreamsllo.Decimal).String()) } - } + }) t.Run("deleting the jobs turns off oracles and cleans up resources", func(t *testing.T) { t.Skip("TODO - MERC-3524") }) diff --git a/core/services/ocr2/plugins/mercury/plugin.go b/core/services/ocr2/plugins/mercury/plugin.go index b0983e55c89..8a4101804dd 100644 --- a/core/services/ocr2/plugins/mercury/plugin.go +++ b/core/services/ocr2/plugins/mercury/plugin.go @@ -1,7 +1,6 @@ package mercury import ( - "context" "encoding/json" "fmt" "os/exec" @@ -80,13 +79,14 @@ func NewServices( return nil, errors.New("expected job to have a non-nil PipelineSpec") } + var err error var pluginConfig config.PluginConfig if len(jb.OCR2OracleSpec.PluginConfig) == 0 { if !enableTriggerCapability { return nil, fmt.Errorf("at least one transmission option must be configured") } } else { - err := json.Unmarshal(jb.OCR2OracleSpec.PluginConfig.Bytes(), &pluginConfig) + err = json.Unmarshal(jb.OCR2OracleSpec.PluginConfig.Bytes(), &pluginConfig) if err != nil { return nil, errors.WithStack(err) } @@ -101,8 +101,8 @@ func NewServices( // encapsulate all the subservices and ensure we close them all if any fail to start srvs := []job.ServiceCtx{ocr2Provider} abort := func() { - if cerr := services.MultiCloser(srvs).Close(); cerr != nil { - lggr.Errorw("Error closing unused services", "err", cerr) + if err = services.MultiCloser(srvs).Close(); err != nil { + lggr.Errorw("Error closing unused services", "err", err) } } saver := ocrcommon.NewResultRunSaver(pipelineRunner, lggr, cfg.MaxSuccessfulRuns(), cfg.ResultWriteQueueDepth()) @@ -112,7 +112,6 @@ func NewServices( var ( factory ocr3types.MercuryPluginFactory factoryServices []job.ServiceCtx - fErr error ) fCfg := factoryCfg{ orm: orm, @@ -128,31 +127,31 @@ func NewServices( } switch feedID.Version() { case 1: - factory, factoryServices, fErr = newv1factory(fCfg) - if fErr != nil { + factory, factoryServices, err = newv1factory(fCfg) + if err != nil { abort() - return nil, fmt.Errorf("failed to create mercury v1 factory: %w", fErr) + return nil, fmt.Errorf("failed to create mercury v1 factory: %w", err) } srvs = append(srvs, factoryServices...) case 2: - factory, factoryServices, fErr = newv2factory(fCfg) - if fErr != nil { + factory, factoryServices, err = newv2factory(fCfg) + if err != nil { abort() - return nil, fmt.Errorf("failed to create mercury v2 factory: %w", fErr) + return nil, fmt.Errorf("failed to create mercury v2 factory: %w", err) } srvs = append(srvs, factoryServices...) case 3: - factory, factoryServices, fErr = newv3factory(fCfg) - if fErr != nil { + factory, factoryServices, err = newv3factory(fCfg) + if err != nil { abort() - return nil, fmt.Errorf("failed to create mercury v3 factory: %w", fErr) + return nil, fmt.Errorf("failed to create mercury v3 factory: %w", err) } srvs = append(srvs, factoryServices...) case 4: - factory, factoryServices, fErr = newv4factory(fCfg) - if fErr != nil { + factory, factoryServices, err = newv4factory(fCfg) + if err != nil { abort() - return nil, fmt.Errorf("failed to create mercury v4 factory: %w", fErr) + return nil, fmt.Errorf("failed to create mercury v4 factory: %w", err) } srvs = append(srvs, factoryServices...) default: @@ -215,14 +214,13 @@ func newv4factory(factoryCfg factoryCfg) (ocr3types.MercuryPluginFactory, []job. loopEnabled := loopCmd != "" if loopEnabled { - cmdFn, unregisterer, opts, mercuryLggr, err := initLoop(loopCmd, factoryCfg.cfg, factoryCfg.feedID, factoryCfg.lggr) + cmdFn, opts, mercuryLggr, err := initLoop(loopCmd, factoryCfg.cfg, factoryCfg.feedID, factoryCfg.lggr) if err != nil { return nil, nil, fmt.Errorf("failed to init loop for feed %s: %w", factoryCfg.feedID, err) } // in loop mode, the factory is grpc server, and we need to handle the server lifecycle - // and unregistration of the loop factoryServer := loop.NewMercuryV4Service(mercuryLggr, opts, cmdFn, factoryCfg.ocr2Provider, ds) - srvs = append(srvs, factoryServer, unregisterer) + srvs = append(srvs, factoryServer) // adapt the grpc server to the vanilla mercury plugin factory interface used by the oracle factory = factoryServer } else { @@ -255,14 +253,13 @@ func newv3factory(factoryCfg factoryCfg) (ocr3types.MercuryPluginFactory, []job. loopEnabled := loopCmd != "" if loopEnabled { - cmdFn, unregisterer, opts, mercuryLggr, err := initLoop(loopCmd, factoryCfg.cfg, factoryCfg.feedID, factoryCfg.lggr) + cmdFn, opts, mercuryLggr, err := initLoop(loopCmd, factoryCfg.cfg, factoryCfg.feedID, factoryCfg.lggr) if err != nil { return nil, nil, fmt.Errorf("failed to init loop for feed %s: %w", factoryCfg.feedID, err) } // in loopp mode, the factory is grpc server, and we need to handle the server lifecycle - // and unregistration of the loop factoryServer := loop.NewMercuryV3Service(mercuryLggr, opts, cmdFn, factoryCfg.ocr2Provider, ds) - srvs = append(srvs, factoryServer, unregisterer) + srvs = append(srvs, factoryServer) // adapt the grpc server to the vanilla mercury plugin factory interface used by the oracle factory = factoryServer } else { @@ -295,14 +292,13 @@ func newv2factory(factoryCfg factoryCfg) (ocr3types.MercuryPluginFactory, []job. loopEnabled := loopCmd != "" if loopEnabled { - cmdFn, unregisterer, opts, mercuryLggr, err := initLoop(loopCmd, factoryCfg.cfg, factoryCfg.feedID, factoryCfg.lggr) + cmdFn, opts, mercuryLggr, err := initLoop(loopCmd, factoryCfg.cfg, factoryCfg.feedID, factoryCfg.lggr) if err != nil { return nil, nil, fmt.Errorf("failed to init loop for feed %s: %w", factoryCfg.feedID, err) } // in loopp mode, the factory is grpc server, and we need to handle the server lifecycle - // and unregistration of the loop factoryServer := loop.NewMercuryV2Service(mercuryLggr, opts, cmdFn, factoryCfg.ocr2Provider, ds) - srvs = append(srvs, factoryServer, unregisterer) + srvs = append(srvs, factoryServer) // adapt the grpc server to the vanilla mercury plugin factory interface used by the oracle factory = factoryServer } else { @@ -333,14 +329,13 @@ func newv1factory(factoryCfg factoryCfg) (ocr3types.MercuryPluginFactory, []job. loopEnabled := loopCmd != "" if loopEnabled { - cmdFn, unregisterer, opts, mercuryLggr, err := initLoop(loopCmd, factoryCfg.cfg, factoryCfg.feedID, factoryCfg.lggr) + cmdFn, opts, mercuryLggr, err := initLoop(loopCmd, factoryCfg.cfg, factoryCfg.feedID, factoryCfg.lggr) if err != nil { return nil, nil, fmt.Errorf("failed to init loop for feed %s: %w", factoryCfg.feedID, err) } // in loopp mode, the factory is grpc server, and we need to handle the server lifecycle - // and unregistration of the loop factoryServer := loop.NewMercuryV1Service(mercuryLggr, opts, cmdFn, factoryCfg.ocr2Provider, ds) - srvs = append(srvs, factoryServer, unregisterer) + srvs = append(srvs, factoryServer) // adapt the grpc server to the vanilla mercury plugin factory interface used by the oracle factory = factoryServer } else { @@ -349,46 +344,20 @@ func newv1factory(factoryCfg factoryCfg) (ocr3types.MercuryPluginFactory, []job. return factory, srvs, nil } -func initLoop(cmd string, cfg Config, feedID utils.FeedID, lggr logger.Logger) (func() *exec.Cmd, *loopUnregisterCloser, loop.GRPCOpts, logger.Logger, error) { +func initLoop(cmd string, cfg Config, feedID utils.FeedID, lggr logger.Logger) (func() *exec.Cmd, loop.GRPCOpts, logger.Logger, error) { lggr.Debugw("Initializing Mercury loop", "command", cmd) mercuryLggr := lggr.Named(fmt.Sprintf("MercuryV%d", feedID.Version())).Named(feedID.String()) envVars, err := plugins.ParseEnvFile(env.MercuryPlugin.Env.Get()) if err != nil { - return nil, nil, loop.GRPCOpts{}, nil, fmt.Errorf("failed to parse mercury env file: %w", err) + return nil, loop.GRPCOpts{}, nil, fmt.Errorf("failed to parse mercury env file: %w", err) } - loopID := mercuryLggr.Name() cmdFn, opts, err := cfg.RegisterLOOP(plugins.CmdConfig{ - ID: loopID, + ID: mercuryLggr.Name(), Cmd: cmd, Env: envVars, }) if err != nil { - return nil, nil, loop.GRPCOpts{}, nil, fmt.Errorf("failed to register loop: %w", err) - } - return cmdFn, newLoopUnregister(cfg, loopID), opts, mercuryLggr, nil -} - -// loopUnregisterCloser is a helper to unregister a loop -// as a service -// TODO BCF-3451 all other jobs that use custom plugin providers that should be refactored to use this pattern -// perhaps it can be implemented in the delegate on job delete. -type loopUnregisterCloser struct { - r plugins.RegistrarConfig - id string -} - -func (l *loopUnregisterCloser) Close() error { - l.r.UnregisterLOOP(l.id) - return nil -} - -func (l *loopUnregisterCloser) Start(ctx context.Context) error { - return nil -} - -func newLoopUnregister(r plugins.RegistrarConfig, id string) *loopUnregisterCloser { - return &loopUnregisterCloser{ - r: r, - id: id, + return nil, loop.GRPCOpts{}, nil, fmt.Errorf("failed to register loop: %w", err) } + return cmdFn, opts, mercuryLggr, nil } diff --git a/core/services/ocr2/plugins/mercury/plugin_test.go b/core/services/ocr2/plugins/mercury/plugin_test.go index eb67da53100..22aaf7522de 100644 --- a/core/services/ocr2/plugins/mercury/plugin_test.go +++ b/core/services/ocr2/plugins/mercury/plugin_test.go @@ -2,7 +2,6 @@ package mercury_test import ( "context" - "errors" "os/exec" "reflect" "testing" @@ -10,7 +9,6 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/google/uuid" "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" "github.com/smartcontractkit/chainlink/v2/core/config/env" "github.com/smartcontractkit/chainlink/v2/core/logger" @@ -24,7 +22,6 @@ import ( v2 "github.com/smartcontractkit/chainlink-common/pkg/types/mercury/v2" v3 "github.com/smartcontractkit/chainlink-common/pkg/types/mercury/v3" v4 "github.com/smartcontractkit/chainlink-common/pkg/types/mercury/v4" - "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" mercuryocr2 "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/mercury" @@ -95,23 +92,21 @@ var ( // this is kind of gross, but it's the best way to test return values of the services expectedEmbeddedServiceCnt = 3 - expectedLoopServiceCnt = expectedEmbeddedServiceCnt + 2 // factory server and loop unregisterer + expectedLoopServiceCnt = expectedEmbeddedServiceCnt + 1 ) func TestNewServices(t *testing.T) { type args struct { pluginConfig job.JSONConfig feedID utils.FeedID - cfg mercuryocr2.Config } - testCases := []struct { + tests := []struct { name string args args loopMode bool wantLoopFactory any wantServiceCnt int wantErr bool - wantErrStr string }{ { name: "no plugin config error ", @@ -191,19 +186,6 @@ func TestNewServices(t *testing.T) { wantErr: false, wantLoopFactory: &loop.MercuryV3Service{}, }, - { - name: "v3 loop err", - loopMode: true, - args: args{ - pluginConfig: v3jsonCfg, - feedID: v3FeedId, - cfg: mercuryocr2.NewMercuryConfig(1, 1, &testRegistrarConfig{failRegister: true}), - }, - wantServiceCnt: expectedLoopServiceCnt, - wantErr: true, - wantLoopFactory: &loop.MercuryV3Service{}, - wantErrStr: "failed to init loop for feed", - }, { name: "v4 loop", loopMode: true, @@ -216,27 +198,17 @@ func TestNewServices(t *testing.T) { wantLoopFactory: &loop.MercuryV4Service{}, }, } - for _, tt := range testCases { + for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if tt.loopMode { t.Setenv(string(env.MercuryPlugin.Cmd), "fake_cmd") assert.NotEmpty(t, env.MercuryPlugin.Cmd.Get()) } - // use default config if not provided - if tt.args.cfg == nil { - tt.args.cfg = testCfg - } - got, err := newServicesTestWrapper(t, tt.args.pluginConfig, tt.args.feedID, tt.args.cfg) + got, err := newServicesTestWrapper(t, tt.args.pluginConfig, tt.args.feedID) if (err != nil) != tt.wantErr { t.Errorf("NewServices() error = %v, wantErr %v", err, tt.wantErr) return } - if err != nil { - if tt.wantErrStr != "" { - assert.Contains(t, err.Error(), tt.wantErrStr) - } - return - } assert.Len(t, got, tt.wantServiceCnt) if tt.loopMode { foundLoopFactory := false @@ -250,97 +222,15 @@ func TestNewServices(t *testing.T) { } }) } - - t.Run("restartable loop", func(t *testing.T) { - // setup a real loop registry to test restartability - registry := plugins.NewLoopRegistry(logger.TestLogger(t), nil, nil, nil, "") - loopRegistrarConfig := plugins.NewRegistrarConfig(loop.GRPCOpts{}, registry.Register, registry.Unregister) - prodCfg := mercuryocr2.NewMercuryConfig(1, 1, loopRegistrarConfig) - type args struct { - pluginConfig job.JSONConfig - feedID utils.FeedID - cfg mercuryocr2.Config - } - testCases := []struct { - name string - args args - wantErr bool - }{ - { - name: "v1 loop", - args: args{ - pluginConfig: v1jsonCfg, - feedID: v1FeedId, - cfg: prodCfg, - }, - wantErr: false, - }, - { - name: "v2 loop", - args: args{ - pluginConfig: v2jsonCfg, - feedID: v2FeedId, - cfg: prodCfg, - }, - wantErr: false, - }, - { - name: "v3 loop", - args: args{ - pluginConfig: v3jsonCfg, - feedID: v3FeedId, - cfg: prodCfg, - }, - wantErr: false, - }, - { - name: "v4 loop", - args: args{ - pluginConfig: v4jsonCfg, - feedID: v4FeedId, - cfg: prodCfg, - }, - wantErr: false, - }, - } - - for _, tt := range testCases { - t.Run(tt.name, func(t *testing.T) { - t.Setenv(string(env.MercuryPlugin.Cmd), "fake_cmd") - assert.NotEmpty(t, env.MercuryPlugin.Cmd.Get()) - - got, err := newServicesTestWrapper(t, tt.args.pluginConfig, tt.args.feedID, tt.args.cfg) - if (err != nil) != tt.wantErr { - t.Errorf("NewServices() error = %v, wantErr %v", err, tt.wantErr) - return - } - // hack to simulate a restart. we don't have enough boilerplate to start the oracle service - // only care about the subservices so we start all except the oracle, which happens to be the last one - for i := 0; i < len(got)-1; i++ { - require.NoError(t, got[i].Start(tests.Context(t))) - } - // if we don't close the services, we get conflicts with the loop registry - _, err = newServicesTestWrapper(t, tt.args.pluginConfig, tt.args.feedID, tt.args.cfg) - require.ErrorContains(t, err, "plugin already registered") - - // close all services and try again - for i := len(got) - 2; i >= 0; i-- { - require.NoError(t, got[i].Close()) - } - _, err = newServicesTestWrapper(t, tt.args.pluginConfig, tt.args.feedID, tt.args.cfg) - require.NoError(t, err) - }) - } - }) } // we are only varying the version via feedID (and the plugin config) // this wrapper supplies dummy values for the rest of the arguments -func newServicesTestWrapper(t *testing.T, pluginConfig job.JSONConfig, feedID utils.FeedID, cfg mercuryocr2.Config) ([]job.ServiceCtx, error) { +func newServicesTestWrapper(t *testing.T, pluginConfig job.JSONConfig, feedID utils.FeedID) ([]job.ServiceCtx, error) { t.Helper() jb := testJob jb.OCR2OracleSpec.PluginConfig = pluginConfig - return mercuryocr2.NewServices(jb, &testProvider{}, nil, logger.TestLogger(t), testArgsNoPlugin, cfg, nil, &testDataSourceORM{}, feedID, false) + return mercuryocr2.NewServices(jb, &testProvider{}, nil, logger.TestLogger(t), testArgsNoPlugin, testCfg, nil, &testDataSourceORM{}, feedID, false) } type testProvider struct{} @@ -402,21 +292,16 @@ func (*testProvider) ReportCodecV3() v3.ReportCodec { return nil } func (*testProvider) ReportCodecV4() v4.ReportCodec { return nil } // Start implements types.MercuryProvider. -func (*testProvider) Start(context.Context) error { return nil } +func (*testProvider) Start(context.Context) error { panic("unimplemented") } var _ commontypes.MercuryProvider = (*testProvider)(nil) -type testRegistrarConfig struct { - failRegister bool -} +type testRegistrarConfig struct{} func (c *testRegistrarConfig) UnregisterLOOP(ID string) {} // RegisterLOOP implements plugins.RegistrarConfig. -func (c *testRegistrarConfig) RegisterLOOP(config plugins.CmdConfig) (func() *exec.Cmd, loop.GRPCOpts, error) { - if c.failRegister { - return nil, loop.GRPCOpts{}, errors.New("failed to register") - } +func (*testRegistrarConfig) RegisterLOOP(config plugins.CmdConfig) (func() *exec.Cmd, loop.GRPCOpts, error) { return nil, loop.GRPCOpts{}, nil } diff --git a/core/services/ocr2/plugins/ocr2keeper/integration_test.go b/core/services/ocr2/plugins/ocr2keeper/integration_test.go index 2283559365c..c08cc3265e8 100644 --- a/core/services/ocr2/plugins/ocr2keeper/integration_test.go +++ b/core/services/ocr2/plugins/ocr2keeper/integration_test.go @@ -29,8 +29,6 @@ import ( "github.com/smartcontractkit/chainlink-automation/pkg/v2/config" commonconfig "github.com/smartcontractkit/chainlink-common/pkg/config" "github.com/smartcontractkit/chainlink-common/pkg/types" - "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" - evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" @@ -51,8 +49,8 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/services/job" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/chaintype" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/ethkey" + "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/keystest" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/ocr2key" - "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/p2pkey" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/mercury" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/validate" @@ -114,7 +112,7 @@ func setupNode( mercury mercury.MercuryEndpointMock, ) (chainlink.Application, string, common.Address, ocr2key.KeyBundle) { ctx := testutils.Context(t) - p2pKey := p2pkey.MustNewV2XXXTestingOnly(big.NewInt(int64(port))) + p2pKey := keystest.NewP2PKeyV2(t) p2paddresses := []string{fmt.Sprintf("127.0.0.1:%d", port)} cfg, _ := heavyweight.FullTestDBV2(t, func(c *chainlink.Config, s *chainlink.Secrets) { c.Feature.LogPoller = ptr(true) @@ -202,7 +200,7 @@ func getUpkeepIDFromTx(t *testing.T, registry *keeper_registry_wrapper2_0.Keeper } func TestIntegration_KeeperPluginBasic(t *testing.T) { - tests.SkipFlakey(t, "https://smartcontract-it.atlassian.net/browse/AUTO-11072") + testutils.SkipFlakey(t, "https://smartcontract-it.atlassian.net/browse/AUTO-11072") runKeeperPluginBasic(t) } diff --git a/core/services/ocr2/validate/validate.go b/core/services/ocr2/validate/validate.go index 27a5a885369..c2f3e455232 100644 --- a/core/services/ocr2/validate/validate.go +++ b/core/services/ocr2/validate/validate.go @@ -269,8 +269,8 @@ func validateGenericPluginSpec(ctx context.Context, spec *job.OCR2OracleSpec, rc loopID := fmt.Sprintf("%s-%s-%s", p.PluginName, spec.ContractID, spec.GetID()) // Starting and stopping a LOOPP isn't efficient; ideally, we'd initiate the LOOPP once and then reference - // it later to conserve resources. This code will be revisited once BCF-3126 is implemented, and we have - // the ability to reference the LOOPP for future use. + //it later to conserve resources. This code will be revisited once BCF-3126 is implemented, and we have + //the ability to reference the LOOPP for future use. cmdFn, grpcOpts, err := rc.RegisterLOOP(plugins.CmdConfig{ ID: loopID, Cmd: command, diff --git a/core/services/ocr3/promwrapper/factory.go b/core/services/ocr3/promwrapper/factory.go deleted file mode 100644 index e369b3260ef..00000000000 --- a/core/services/ocr3/promwrapper/factory.go +++ /dev/null @@ -1,54 +0,0 @@ -package promwrapper - -import ( - "context" - - "github.com/smartcontractkit/chainlink-common/pkg/logger" - - "github.com/smartcontractkit/libocr/offchainreporting2plus/ocr3types" -) - -var _ ocr3types.ReportingPluginFactory[any] = &ReportingPluginFactory[any]{} - -type ReportingPluginFactory[RI any] struct { - origin ocr3types.ReportingPluginFactory[RI] - lggr logger.Logger - chainID string - plugin string -} - -func NewReportingPluginFactory[RI any]( - origin ocr3types.ReportingPluginFactory[RI], - lggr logger.Logger, - chainID string, - plugin string, -) *ReportingPluginFactory[RI] { - return &ReportingPluginFactory[RI]{ - origin: origin, - lggr: lggr, - chainID: chainID, - plugin: plugin, - } -} - -func (r ReportingPluginFactory[RI]) NewReportingPlugin(ctx context.Context, config ocr3types.ReportingPluginConfig) (ocr3types.ReportingPlugin[RI], ocr3types.ReportingPluginInfo, error) { - plugin, info, err := r.origin.NewReportingPlugin(ctx, config) - if err != nil { - return nil, ocr3types.ReportingPluginInfo{}, err - } - r.lggr.Infow("Wrapping ReportingPlugin with prometheus metrics reporter", - "configDigest", config.ConfigDigest, - "oracleID", config.OracleID, - ) - wrapped := newReportingPlugin( - plugin, - r.chainID, - r.plugin, - config.ConfigDigest.String(), - promOCR3ReportsGenerated, - promOCR3Durations, - promOCR3Sizes, - promOCR3PluginStatus, - ) - return wrapped, info, err -} diff --git a/core/services/ocr3/promwrapper/factory_test.go b/core/services/ocr3/promwrapper/factory_test.go deleted file mode 100644 index fb68c039b78..00000000000 --- a/core/services/ocr3/promwrapper/factory_test.go +++ /dev/null @@ -1,43 +0,0 @@ -package promwrapper - -import ( - "context" - "errors" - "testing" - - "github.com/stretchr/testify/require" - - "github.com/smartcontractkit/libocr/offchainreporting2plus/ocr3types" - - "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" - - "github.com/smartcontractkit/chainlink/v2/core/logger" -) - -func Test_WrapperFactory(t *testing.T) { - validFactory := NewReportingPluginFactory(fakeFactory[uint]{}, logger.TestLogger(t), "solana", "plugin") - failingFactory := NewReportingPluginFactory(fakeFactory[uint]{err: errors.New("error")}, logger.TestLogger(t), "123", "plugin") - - plugin, _, err := validFactory.NewReportingPlugin(tests.Context(t), ocr3types.ReportingPluginConfig{}) - require.NoError(t, err) - - _, err = plugin.Outcome(tests.Context(t), ocr3types.OutcomeContext{}, nil, nil) - require.NoError(t, err) - - require.Equal(t, 1, counterFromHistogramByLabels(t, promOCR3Durations, "solana", "plugin", "outcome", "true")) - require.Equal(t, 0, counterFromHistogramByLabels(t, promOCR3Durations, "solana", "plugin", "outcome", "false")) - - _, _, err = failingFactory.NewReportingPlugin(tests.Context(t), ocr3types.ReportingPluginConfig{}) - require.Error(t, err) -} - -type fakeFactory[RI any] struct { - err error -} - -func (f fakeFactory[RI]) NewReportingPlugin(context.Context, ocr3types.ReportingPluginConfig) (ocr3types.ReportingPlugin[RI], ocr3types.ReportingPluginInfo, error) { - if f.err != nil { - return nil, ocr3types.ReportingPluginInfo{}, f.err - } - return fakePlugin[RI]{}, ocr3types.ReportingPluginInfo{}, nil -} diff --git a/core/services/ocr3/promwrapper/plugin.go b/core/services/ocr3/promwrapper/plugin.go deleted file mode 100644 index aa5fb87a6ee..00000000000 --- a/core/services/ocr3/promwrapper/plugin.go +++ /dev/null @@ -1,154 +0,0 @@ -package promwrapper - -import ( - "context" - "strconv" - "time" - - "github.com/prometheus/client_golang/prometheus" - "github.com/smartcontractkit/libocr/offchainreporting2plus/ocr3types" - ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types" -) - -var _ ocr3types.ReportingPlugin[any] = &reportingPlugin[any]{} - -type reportingPlugin[RI any] struct { - ocr3types.ReportingPlugin[RI] - chainID string - plugin string - configDigest string - - // Prometheus components for tracking metrics - reportsGenerated *prometheus.CounterVec - durations *prometheus.HistogramVec - sizes *prometheus.CounterVec - status *prometheus.GaugeVec -} - -func newReportingPlugin[RI any]( - origin ocr3types.ReportingPlugin[RI], - chainID string, - plugin string, - configDigest string, - reportsGenerated *prometheus.CounterVec, - durations *prometheus.HistogramVec, - sizes *prometheus.CounterVec, - status *prometheus.GaugeVec, -) *reportingPlugin[RI] { - return &reportingPlugin[RI]{ - ReportingPlugin: origin, - chainID: chainID, - plugin: plugin, - configDigest: configDigest, - reportsGenerated: reportsGenerated, - durations: durations, - sizes: sizes, - status: status, - } -} - -func (p *reportingPlugin[RI]) Query(ctx context.Context, outctx ocr3types.OutcomeContext) (ocrtypes.Query, error) { - return withObservedExecution(p, query, func() (ocrtypes.Query, error) { - return p.ReportingPlugin.Query(ctx, outctx) - }) -} - -func (p *reportingPlugin[RI]) Observation(ctx context.Context, outctx ocr3types.OutcomeContext, query ocrtypes.Query) (ocrtypes.Observation, error) { - result, err := withObservedExecution(p, observation, func() (ocrtypes.Observation, error) { - return p.ReportingPlugin.Observation(ctx, outctx, query) - }) - p.trackSize(observation, len(result), err) - return result, err -} - -func (p *reportingPlugin[RI]) ValidateObservation(ctx context.Context, outctx ocr3types.OutcomeContext, query ocrtypes.Query, ao ocrtypes.AttributedObservation) error { - _, err := withObservedExecution(p, validateObservation, func() (any, error) { - err := p.ReportingPlugin.ValidateObservation(ctx, outctx, query, ao) - return nil, err - }) - return err -} - -func (p *reportingPlugin[RI]) Outcome(ctx context.Context, outctx ocr3types.OutcomeContext, query ocrtypes.Query, aos []ocrtypes.AttributedObservation) (ocr3types.Outcome, error) { - result, err := withObservedExecution(p, outcome, func() (ocr3types.Outcome, error) { - return p.ReportingPlugin.Outcome(ctx, outctx, query, aos) - }) - p.trackSize(outcome, len(result), err) - return result, err -} - -func (p *reportingPlugin[RI]) Reports(ctx context.Context, seqNr uint64, outcome ocr3types.Outcome) ([]ocr3types.ReportPlus[RI], error) { - result, err := withObservedExecution(p, reports, func() ([]ocr3types.ReportPlus[RI], error) { - return p.ReportingPlugin.Reports(ctx, seqNr, outcome) - }) - p.trackReports(reports, len(result)) - return result, err -} - -func (p *reportingPlugin[RI]) ShouldAcceptAttestedReport(ctx context.Context, seqNr uint64, reportWithInfo ocr3types.ReportWithInfo[RI]) (bool, error) { - result, err := withObservedExecution(p, shouldAccept, func() (bool, error) { - return p.ReportingPlugin.ShouldAcceptAttestedReport(ctx, seqNr, reportWithInfo) - }) - p.trackReports(shouldAccept, boolToInt(result)) - return result, err -} - -func (p *reportingPlugin[RI]) ShouldTransmitAcceptedReport(ctx context.Context, seqNr uint64, reportWithInfo ocr3types.ReportWithInfo[RI]) (bool, error) { - result, err := withObservedExecution(p, shouldTransmit, func() (bool, error) { - return p.ReportingPlugin.ShouldTransmitAcceptedReport(ctx, seqNr, reportWithInfo) - }) - p.trackReports(shouldTransmit, boolToInt(result)) - return result, err -} - -func (p *reportingPlugin[RI]) Close() error { - p.updateStatus(false) - return p.ReportingPlugin.Close() -} - -func (p *reportingPlugin[RI]) trackReports(function functionType, count int) { - p.reportsGenerated. - WithLabelValues(p.chainID, p.plugin, string(function)). - Add(float64(count)) -} - -func (p *reportingPlugin[RI]) updateStatus(status bool) { - p.status. - WithLabelValues(p.chainID, p.plugin, p.configDigest). - Set(float64(boolToInt(status))) -} - -func (p *reportingPlugin[RI]) trackSize(function functionType, size int, err error) { - if err != nil { - return - } - p.sizes. - WithLabelValues(p.chainID, p.plugin, string(function)). - Add(float64(size)) -} - -func boolToInt(arg bool) int { - if arg { - return 1 - } - return 0 -} - -func withObservedExecution[RI, R any]( - p *reportingPlugin[RI], - function functionType, - exec func() (R, error), -) (R, error) { - start := time.Now() - result, err := exec() - - success := err == nil - - p.durations. - WithLabelValues(p.chainID, p.plugin, string(function), strconv.FormatBool(success)). - Observe(float64(time.Since(start))) - - p.updateStatus(true) - - return result, err -} diff --git a/core/services/ocr3/promwrapper/plugin_test.go b/core/services/ocr3/promwrapper/plugin_test.go deleted file mode 100644 index a10a467799f..00000000000 --- a/core/services/ocr3/promwrapper/plugin_test.go +++ /dev/null @@ -1,196 +0,0 @@ -package promwrapper - -import ( - "context" - "errors" - "testing" - - "github.com/prometheus/client_golang/prometheus" - "github.com/prometheus/client_golang/prometheus/testutil" - io_prometheus_client "github.com/prometheus/client_model/go" - "github.com/stretchr/testify/require" - - "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" - - "github.com/smartcontractkit/libocr/offchainreporting2plus/ocr3types" - ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types" -) - -func Test_ReportsGeneratedGauge(t *testing.T) { - pluginObservationSize := 5 - pluginOutcomeSize := 3 - - plugin1 := newReportingPlugin( - fakePlugin[uint]{reports: make([]ocr3types.ReportPlus[uint], 2)}, - "123", "empty", "abc", promOCR3ReportsGenerated, promOCR3Durations, promOCR3Sizes, promOCR3PluginStatus, - ) - plugin2 := newReportingPlugin( - fakePlugin[bool]{reports: make([]ocr3types.ReportPlus[bool], 10), observationSize: pluginObservationSize, outcomeSize: pluginOutcomeSize}, - "solana", "different_plugin", "abc", promOCR3ReportsGenerated, promOCR3Durations, promOCR3Sizes, promOCR3PluginStatus, - ) - plugin3 := newReportingPlugin( - fakePlugin[string]{err: errors.New("error")}, - "1234", "empty", "abc", promOCR3ReportsGenerated, promOCR3Durations, promOCR3Sizes, promOCR3PluginStatus, - ) - - r1, err := plugin1.Reports(tests.Context(t), 1, nil) - require.NoError(t, err) - require.Len(t, r1, 2) - - for i := 0; i < 10; i++ { - r2, err1 := plugin2.Reports(tests.Context(t), 1, nil) - require.NoError(t, err1) - require.Len(t, r2, 10) - } - - _, err = plugin2.ShouldAcceptAttestedReport(tests.Context(t), 1, ocr3types.ReportWithInfo[bool]{}) - require.NoError(t, err) - - _, err = plugin3.Reports(tests.Context(t), 1, nil) - require.Error(t, err) - - g1 := testutil.ToFloat64(promOCR3ReportsGenerated.WithLabelValues("123", "empty", "reports")) - require.Equal(t, 2, int(g1)) - - g2 := testutil.ToFloat64(promOCR3ReportsGenerated.WithLabelValues("solana", "different_plugin", "reports")) - require.Equal(t, 100, int(g2)) - - g3 := testutil.ToFloat64(promOCR3ReportsGenerated.WithLabelValues("solana", "different_plugin", "shouldAccept")) - require.Equal(t, 1, int(g3)) - - g4 := testutil.ToFloat64(promOCR3ReportsGenerated.WithLabelValues("1234", "empty", "reports")) - require.Equal(t, 0, int(g4)) - - pluginHealth := testutil.ToFloat64(promOCR3PluginStatus.WithLabelValues("123", "empty", "abc")) - require.Equal(t, 1, int(pluginHealth)) - - require.NoError(t, plugin1.Close()) - pluginHealth = testutil.ToFloat64(promOCR3PluginStatus.WithLabelValues("123", "empty", "abc")) - require.Equal(t, 0, int(pluginHealth)) - - iterations := 10 - for i := 0; i < iterations; i++ { - _, err1 := plugin2.Outcome(tests.Context(t), ocr3types.OutcomeContext{}, nil, nil) - require.NoError(t, err1) - } - _, err1 := plugin2.Observation(tests.Context(t), ocr3types.OutcomeContext{}, nil) - require.NoError(t, err1) - - outcomesLen := testutil.ToFloat64(promOCR3Sizes.WithLabelValues("solana", "different_plugin", "outcome")) - require.Equal(t, pluginOutcomeSize*iterations, int(outcomesLen)) - observationLen := testutil.ToFloat64(promOCR3Sizes.WithLabelValues("solana", "different_plugin", "observation")) - require.Equal(t, pluginObservationSize, int(observationLen)) -} - -func Test_DurationHistograms(t *testing.T) { - plugin1 := newReportingPlugin( - fakePlugin[uint]{}, - "123", "empty", "abc", promOCR3ReportsGenerated, promOCR3Durations, promOCR3Sizes, promOCR3PluginStatus, - ) - plugin2 := newReportingPlugin( - fakePlugin[uint]{err: errors.New("error")}, - "123", "empty", "abc", promOCR3ReportsGenerated, promOCR3Durations, promOCR3Sizes, promOCR3PluginStatus, - ) - plugin3 := newReportingPlugin( - fakePlugin[uint]{}, - "solana", "commit", "abc", promOCR3ReportsGenerated, promOCR3Durations, promOCR3Sizes, promOCR3PluginStatus, - ) - - for _, p := range []*reportingPlugin[uint]{plugin1, plugin2, plugin3} { - _, _ = p.Query(tests.Context(t), ocr3types.OutcomeContext{}) - for i := 0; i < 2; i++ { - _, _ = p.Observation(tests.Context(t), ocr3types.OutcomeContext{}, nil) - } - _ = p.ValidateObservation(tests.Context(t), ocr3types.OutcomeContext{}, nil, ocrtypes.AttributedObservation{}) - _, _ = p.Outcome(tests.Context(t), ocr3types.OutcomeContext{}, nil, nil) - _, _ = p.Reports(tests.Context(t), 0, nil) - _, _ = p.ShouldAcceptAttestedReport(tests.Context(t), 0, ocr3types.ReportWithInfo[uint]{}) - _, _ = p.ShouldTransmitAcceptedReport(tests.Context(t), 0, ocr3types.ReportWithInfo[uint]{}) - } - - require.Equal(t, 1, counterFromHistogramByLabels(t, promOCR3Durations, "123", "empty", "query", "true")) - require.Equal(t, 1, counterFromHistogramByLabels(t, promOCR3Durations, "123", "empty", "query", "false")) - require.Equal(t, 1, counterFromHistogramByLabels(t, promOCR3Durations, "solana", "commit", "query", "true")) - - require.Equal(t, 2, counterFromHistogramByLabels(t, promOCR3Durations, "123", "empty", "observation", "true")) - require.Equal(t, 2, counterFromHistogramByLabels(t, promOCR3Durations, "123", "empty", "observation", "false")) - require.Equal(t, 2, counterFromHistogramByLabels(t, promOCR3Durations, "solana", "commit", "observation", "true")) -} - -type fakePlugin[RI any] struct { - reports []ocr3types.ReportPlus[RI] - observationSize int - outcomeSize int - err error -} - -func (f fakePlugin[RI]) Query(context.Context, ocr3types.OutcomeContext) (ocrtypes.Query, error) { - if f.err != nil { - return nil, f.err - } - return ocrtypes.Query{}, nil -} - -func (f fakePlugin[RI]) Observation(context.Context, ocr3types.OutcomeContext, ocrtypes.Query) (ocrtypes.Observation, error) { - if f.err != nil { - return nil, f.err - } - return make([]byte, f.observationSize), nil -} - -func (f fakePlugin[RI]) ValidateObservation(context.Context, ocr3types.OutcomeContext, ocrtypes.Query, ocrtypes.AttributedObservation) error { - return f.err -} - -func (f fakePlugin[RI]) ObservationQuorum(context.Context, ocr3types.OutcomeContext, ocrtypes.Query, []ocrtypes.AttributedObservation) (quorumReached bool, err error) { - return false, f.err -} - -func (f fakePlugin[RI]) Outcome(context.Context, ocr3types.OutcomeContext, ocrtypes.Query, []ocrtypes.AttributedObservation) (ocr3types.Outcome, error) { - if f.err != nil { - return nil, f.err - } - return make([]byte, f.outcomeSize), nil -} - -func (f fakePlugin[RI]) Reports(context.Context, uint64, ocr3types.Outcome) ([]ocr3types.ReportPlus[RI], error) { - if f.err != nil { - return nil, f.err - } - return f.reports, nil -} - -func (f fakePlugin[RI]) ShouldAcceptAttestedReport(context.Context, uint64, ocr3types.ReportWithInfo[RI]) (bool, error) { - if f.err != nil { - return false, f.err - } - return true, nil -} - -func (f fakePlugin[RI]) ShouldTransmitAcceptedReport(context.Context, uint64, ocr3types.ReportWithInfo[RI]) (bool, error) { - if f.err != nil { - return false, f.err - } - return true, nil -} - -func (f fakePlugin[RI]) Close() error { - return f.err -} - -func counterFromHistogramByLabels(t *testing.T, histogramVec *prometheus.HistogramVec, labels ...string) int { - observer, err := histogramVec.GetMetricWithLabelValues(labels...) - require.NoError(t, err) - - metricCh := make(chan prometheus.Metric, 1) - observer.(prometheus.Histogram).Collect(metricCh) - close(metricCh) - - metric := <-metricCh - pb := &io_prometheus_client.Metric{} - err = metric.Write(pb) - require.NoError(t, err) - - //nolint:gosec // we don't care about that in tests - return int(pb.GetHistogram().GetSampleCount()) -} diff --git a/core/services/ocr3/promwrapper/types.go b/core/services/ocr3/promwrapper/types.go deleted file mode 100644 index 59468358783..00000000000 --- a/core/services/ocr3/promwrapper/types.go +++ /dev/null @@ -1,65 +0,0 @@ -package promwrapper - -import ( - "time" - - "github.com/prometheus/client_golang/prometheus" - "github.com/prometheus/client_golang/prometheus/promauto" -) - -type functionType string - -const ( - query functionType = "query" - observation functionType = "observation" - validateObservation functionType = "validateObservation" - outcome functionType = "outcome" - reports functionType = "reports" - shouldAccept functionType = "shouldAccept" - shouldTransmit functionType = "shouldTransmit" -) - -var ( - buckets = []float64{ - float64(10 * time.Millisecond), - float64(50 * time.Millisecond), - float64(100 * time.Millisecond), - float64(200 * time.Millisecond), - float64(500 * time.Millisecond), - float64(700 * time.Millisecond), - float64(time.Second), - float64(2 * time.Second), - float64(5 * time.Second), - float64(10 * time.Second), - } - - promOCR3ReportsGenerated = promauto.NewCounterVec( - prometheus.CounterOpts{ - Name: "ocr3_reporting_plugin_reports_processed", - Help: "Tracks number of reports processed/generated within by different OCR3 functions", - }, - []string{"chainID", "plugin", "function"}, - ) - promOCR3Durations = promauto.NewHistogramVec( - prometheus.HistogramOpts{ - Name: "ocr3_reporting_plugin_duration", - Help: "The amount of time elapsed during the OCR3 plugin's function", - Buckets: buckets, - }, - []string{"chainID", "plugin", "function", "success"}, - ) - promOCR3Sizes = promauto.NewCounterVec( - prometheus.CounterOpts{ - Name: "ocr3_reporting_plugin_data_sizes", - Help: "Tracks the size of the data produced by OCR3 plugin in bytes (e.g. reports, observations etc.)", - }, - []string{"chainID", "plugin", "function"}, - ) - promOCR3PluginStatus = promauto.NewGaugeVec( - prometheus.GaugeOpts{ - Name: "ocr3_reporting_plugin_status", - Help: "Gauge indicating whether plugin is up and running or not", - }, - []string{"chainID", "plugin", "configDigest"}, - ) -) diff --git a/core/services/ocrcommon/adapters.go b/core/services/ocrcommon/adapters.go index c27a276669b..33e4971bc82 100644 --- a/core/services/ocrcommon/adapters.go +++ b/core/services/ocrcommon/adapters.go @@ -112,7 +112,7 @@ func MarshalMultichainPublicKey(ost map[string]ocrtypes.OnchainPublicKey) (ocrty if length < 0 || length > math.MaxUint16 { return nil, fmt.Errorf("pubKey doesn't fit into uint16") } - if err = binary.Write(buf, binary.LittleEndian, uint16(length)); err != nil { + if err = binary.Write(buf, binary.LittleEndian, uint16(length)); err != nil { //nolint:gosec return nil, err } _, _ = buf.Write(pubKey) diff --git a/core/services/ocrcommon/telemetry.go b/core/services/ocrcommon/telemetry.go index 5e4a65180d5..e20b2485d86 100644 --- a/core/services/ocrcommon/telemetry.go +++ b/core/services/ocrcommon/telemetry.go @@ -164,6 +164,7 @@ func ParseMercuryEATelemetry(lggr logger.Logger, trrs pipeline.TaskRunResults, f bridgeRawResponse, ok := trr.Result.Value.(string) if !ok { + lggr.Warnw(fmt.Sprintf("cannot get bridge response from bridge task, id=%s, name=%q, expected string got %T", trr.Task.DotID(), bridgeName, trr.Result.Value), "dotID", trr.Task.DotID(), "bridgeName", bridgeName) continue } eaTelem, err := parseEATelemetry([]byte(bridgeRawResponse)) @@ -653,6 +654,7 @@ func getPricesFromResultsByOrder(lggr logger.Logger, startTask pipeline.TaskRunR // We rely on task results to be sorted in the correct order benchmarkPriceTask := allTasks.GetNextTaskOf(startTask) if benchmarkPriceTask == nil { + lggr.Warn("cannot parse enhanced EA telemetry benchmark price, task is nil") return 0, 0, 0 } if benchmarkPriceTask.Task.Type() == pipeline.TaskTypeJSONParse { @@ -666,6 +668,7 @@ func getPricesFromResultsByOrder(lggr logger.Logger, startTask pipeline.TaskRunR bidTask := allTasks.GetNextTaskOf(*benchmarkPriceTask) if bidTask == nil { + lggr.Warnf("cannot parse enhanced EA telemetry bid price, task is nil, id %s", benchmarkPriceTask.Task.DotID()) return benchmarkPrice, 0, 0 } @@ -675,6 +678,7 @@ func getPricesFromResultsByOrder(lggr logger.Logger, startTask pipeline.TaskRunR askTask := allTasks.GetNextTaskOf(*bidTask) if askTask == nil { + lggr.Warnf("cannot parse enhanced EA telemetry ask price, task is nil, id %s", benchmarkPriceTask.Task.DotID()) return benchmarkPrice, bidPrice, 0 } if askTask.Task.Type() == pipeline.TaskTypeJSONParse { diff --git a/core/services/ocrcommon/telemetry_test.go b/core/services/ocrcommon/telemetry_test.go index 4c8f0eb1127..8fac0ab2cbf 100644 --- a/core/services/ocrcommon/telemetry_test.go +++ b/core/services/ocrcommon/telemetry_test.go @@ -1,7 +1,6 @@ package ocrcommon import ( - "fmt" "math/big" "sync" "testing" @@ -659,15 +658,18 @@ func TestGetPricesFromBridgeTaskByOrder(t *testing.T) { require.Equal(t, float64(0), benchmarkPrice) require.Equal(t, float64(0), bid) require.Equal(t, float64(0), ask) - require.Equal(t, 0, logs.Len()) + require.Equal(t, 1, logs.Len()) + require.Contains(t, logs.All()[0].Message, "cannot parse enhanced EA telemetry") tt := trrsMercuryV1[:2] getPricesFromBridgeTask(lggr, trrsMercuryV1[0], tt, 1) - require.Equal(t, 0, logs.Len()) + require.Equal(t, 2, logs.Len()) + require.Contains(t, logs.All()[1].Message, "cannot parse enhanced EA telemetry bid price, task is nil") tt = trrsMercuryV1[:3] getPricesFromBridgeTask(lggr, trrsMercuryV1[0], tt, 1) - require.Equal(t, 0, logs.Len()) + require.Equal(t, 3, logs.Len()) + require.Contains(t, logs.All()[2].Message, "cannot parse enhanced EA telemetry ask price, task is nil") trrs2 := pipeline.TaskRunResults{ pipeline.TaskRunResult{ @@ -707,10 +709,10 @@ func TestGetPricesFromBridgeTaskByOrder(t *testing.T) { require.Equal(t, benchmarkPrice, float64(0)) require.Equal(t, bid, float64(0)) require.Equal(t, ask, float64(0)) - require.Equal(t, 3, logs.Len()) - require.Contains(t, logs.All()[0].Message, "cannot parse EA telemetry price to float64, DOT id ds1_benchmark") - require.Contains(t, logs.All()[1].Message, "cannot parse EA telemetry price to float64, DOT id ds2_bid") - require.Contains(t, logs.All()[2].Message, "cannot parse EA telemetry price to float64, DOT id ds3_ask") + require.Equal(t, logs.Len(), 6) + require.Contains(t, logs.All()[3].Message, "cannot parse EA telemetry price to float64, DOT id ds1_benchmark") + require.Contains(t, logs.All()[4].Message, "cannot parse EA telemetry price to float64, DOT id ds2_bid") + require.Contains(t, logs.All()[5].Message, "cannot parse EA telemetry price to float64, DOT id ds3_ask") benchmarkPrice, bid, ask = getPricesFromBridgeTask(lggr, trrsMercuryV1[0], trrsMercuryV2, 2) require.Equal(t, 123456.123456, benchmarkPrice) @@ -1022,8 +1024,9 @@ func TestCollectMercuryEnhancedTelemetryV1(t *testing.T) { } wg.Wait() - require.Equal(t, 1, logs.Len()) - require.Contains(t, logs.All()[0].Message, "cannot parse EA telemetry") + require.Equal(t, 2, logs.Len()) + require.Contains(t, logs.All()[0].Message, `cannot get bridge response from bridge task, id=ds1, name="test-mercury-bridge-1"`) + require.Contains(t, logs.All()[1].Message, "cannot parse EA telemetry") chDone <- struct{}{} } @@ -1137,9 +1140,11 @@ func TestCollectMercuryEnhancedTelemetryV2(t *testing.T) { } wg.Wait() - require.Equal(t, 1, logs.Len()) - fmt.Println(logs.All()) - require.Contains(t, logs.All()[0].Message, "cannot parse EA telemetry") + require.Equal(t, 4, logs.Len()) + require.Contains(t, logs.All()[0].Message, "cannot parse enhanced EA telemetry bid price") + require.Contains(t, logs.All()[1].Message, "cannot get bridge response from bridge task") + require.Contains(t, logs.All()[2].Message, "cannot parse EA telemetry") + require.Contains(t, logs.All()[3].Message, "cannot parse enhanced EA telemetry bid price") chDone <- struct{}{} } diff --git a/core/services/pg/connection.go b/core/services/pg/connection.go index bf3663e82ce..64a137762fc 100644 --- a/core/services/pg/connection.go +++ b/core/services/pg/connection.go @@ -19,7 +19,7 @@ import ( "go.opentelemetry.io/otel" semconv "go.opentelemetry.io/otel/semconv/v1.4.0" - pgcommon "github.com/smartcontractkit/chainlink-common/pkg/sqlutil/pg" + "github.com/smartcontractkit/chainlink/v2/core/store/dialects" ) // NOTE: This is the default level in Postgres anyway, we just make it @@ -51,7 +51,7 @@ type ConnectionConfig interface { MaxIdleConns() int } -func NewConnection(ctx context.Context, uri string, dialect pgcommon.DialectName, config ConnectionConfig) (*sqlx.DB, error) { +func NewConnection(ctx context.Context, uri string, dialect dialects.DialectName, config ConnectionConfig) (*sqlx.DB, error) { opts := []otelsql.Option{otelsql.WithAttributes(semconv.DBSystemPostgreSQL), otelsql.WithTracerProvider(otel.GetTracerProvider()), otelsql.WithSQLCommenter(true), @@ -70,7 +70,7 @@ func NewConnection(ctx context.Context, uri string, dialect pgcommon.DialectName lockTimeout, idleInTxSessionTimeout, defaultIsolation.String()) var sqldb *sql.DB - if dialect == pgcommon.TransactionWrappedPostgres { + if dialect == dialects.TransactionWrappedPostgres { // Dbtx uses the uri as a unique identifier for each transaction. Each ORM // should be encapsulated in it's own transaction, and thus needs its own // unique id. @@ -78,11 +78,7 @@ func NewConnection(ctx context.Context, uri string, dialect pgcommon.DialectName // We can happily throw away the original uri here because if we are using // txdb it should have already been set at the point where we called // txdb.Register - - err := pgcommon.RegisterTxDb(uri) - if err != nil { - return nil, fmt.Errorf("failed to register txdb: %w", err) - } + var err error sqldb, err = otelsql.Open(string(dialect), uuid.New().String(), opts...) if err != nil { return nil, fmt.Errorf("failed to open txdb: %w", err) diff --git a/core/services/pg/connection_test.go b/core/services/pg/connection_test.go index 3ae70d14637..c4314bfb309 100644 --- a/core/services/pg/connection_test.go +++ b/core/services/pg/connection_test.go @@ -4,13 +4,15 @@ import ( "testing" "time" + "github.com/google/uuid" _ "github.com/jackc/pgx/v4/stdlib" + "github.com/jmoiron/sqlx" "github.com/pkg/errors" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" - "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest" + "github.com/smartcontractkit/chainlink/v2/core/store/dialects" ) var _ Getter = &mockGetter{} @@ -65,9 +67,11 @@ func Test_checkVersion(t *testing.T) { func Test_disallowReplica(t *testing.T) { testutils.SkipShortDB(t) - db := pgtest.NewSqlxDB(t) + db, err := sqlx.Open(string(dialects.TransactionWrappedPostgres), uuid.New().String()) + require.NoError(t, err) + t.Cleanup(func() { require.NoError(t, db.Close()) }) - _, err := db.Exec("SET session_replication_role= 'origin'") + _, err = db.Exec("SET session_replication_role= 'origin'") require.NoError(t, err) err = disallowReplica(db) require.NoError(t, err) diff --git a/core/services/pg/locked_db.go b/core/services/pg/locked_db.go index baea01b43a5..14ddb2317a5 100644 --- a/core/services/pg/locked_db.go +++ b/core/services/pg/locked_db.go @@ -11,11 +11,10 @@ import ( "github.com/jmoiron/sqlx" "github.com/smartcontractkit/chainlink-common/pkg/services" - "github.com/smartcontractkit/chainlink-common/pkg/sqlutil/pg" - "github.com/smartcontractkit/chainlink/v2/core/config" "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/static" + "github.com/smartcontractkit/chainlink/v2/core/store/dialects" ) // LockedDB bounds DB connection and DB locks. @@ -29,7 +28,7 @@ type LockedDBConfig interface { ConnectionConfig URL() url.URL DefaultQueryTimeout() time.Duration - Dialect() pg.DialectName + Dialect() dialects.DialectName } type lockedDb struct { diff --git a/core/services/pipeline/runner.go b/core/services/pipeline/runner.go index 2194cb8be46..1fc2fc46336 100644 --- a/core/services/pipeline/runner.go +++ b/core/services/pipeline/runner.go @@ -510,23 +510,15 @@ func (r *runner) run(ctx context.Context, pipeline *Pipeline, run *Run, vars Var ) } l = l.With("run.State", run.State, "fatal", run.HasFatalErrors(), "runTime", runTime) - if run.HasFatalErrors() || run.HasErrors() { - var errorsWithID []string - for _, taskRun := range run.PipelineTaskRuns { - if taskRun.Error.Valid { - err := fmt.Sprintf("%s(%s); %s", taskRun.DotID, taskRun.Type, taskRun.Error.ValueOrZero()) - errorsWithID = append(errorsWithID, err) - } - } - l = l.With("run.Errors", errorsWithID) - if run.HasFatalErrors() { - l = l.With("run.FatalErrors", run.FatalErrors) - l.Debugw("Completed pipeline run with fatal errors") - } else if run.HasErrors() { - l = l.With("run.AllErrors", run.AllErrors) - l.Debugw("Completed pipeline run with errors") - } - } else if r.config.VerboseLogging() { + if run.HasFatalErrors() { + // This will also log at error level in OCR if it fails Observe so the + // level is appropriate + l = l.With("run.FatalErrors", run.FatalErrors) + l.Debugw("Completed pipeline run with fatal errors") + } else if run.HasErrors() { + l = l.With("run.AllErrors", run.AllErrors) + l.Debugw("Completed pipeline run with errors") + } else { l.Debugw("Completed pipeline run successfully") } diff --git a/core/services/registrysyncer/local_registry.go b/core/services/registrysyncer/local_registry.go index 3ac8927c028..5bec59412f4 100644 --- a/core/services/registrysyncer/local_registry.go +++ b/core/services/registrysyncer/local_registry.go @@ -7,7 +7,7 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/capabilities" - kcr "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry_1_1_0" + kcr "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry" "github.com/smartcontractkit/chainlink/v2/core/logger" p2ptypes "github.com/smartcontractkit/chainlink/v2/core/services/p2p/types" ) diff --git a/core/services/registrysyncer/orm.go b/core/services/registrysyncer/orm.go index 7992f45413a..9c666200752 100644 --- a/core/services/registrysyncer/orm.go +++ b/core/services/registrysyncer/orm.go @@ -9,7 +9,7 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" - kcr "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry_1_1_0" + kcr "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry" "github.com/smartcontractkit/chainlink/v2/core/logger" p2ptypes "github.com/smartcontractkit/chainlink/v2/core/services/p2p/types" ) diff --git a/core/services/registrysyncer/orm_test.go b/core/services/registrysyncer/orm_test.go index b527f1ad8d7..429bfff664b 100644 --- a/core/services/registrysyncer/orm_test.go +++ b/core/services/registrysyncer/orm_test.go @@ -17,7 +17,7 @@ import ( capabilitiespb "github.com/smartcontractkit/chainlink-common/pkg/capabilities/pb" "github.com/smartcontractkit/chainlink-common/pkg/values" - kcr "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry_1_1_0" + kcr "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest" "github.com/smartcontractkit/chainlink/v2/core/logger" diff --git a/core/services/registrysyncer/syncer.go b/core/services/registrysyncer/syncer.go index 02797b42dd2..461824b403b 100644 --- a/core/services/registrysyncer/syncer.go +++ b/core/services/registrysyncer/syncer.go @@ -13,7 +13,7 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/types" "github.com/smartcontractkit/chainlink-common/pkg/types/query/primitives" - kcr "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry_1_1_0" + kcr "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry" "github.com/smartcontractkit/chainlink/v2/core/logger" p2ptypes "github.com/smartcontractkit/chainlink/v2/core/services/p2p/types" evmrelaytypes "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/types" @@ -76,6 +76,7 @@ func New( registryAddress string, orm ORM, ) (RegistrySyncer, error) { + metricLabeler, err := newSyncerMetricLabeler() if err != nil { return nil, fmt.Errorf("failed to create syncer metric labeler: %w", err) diff --git a/core/services/registrysyncer/syncer_test.go b/core/services/registrysyncer/syncer_test.go index 33920c36a55..e4a1dce476c 100644 --- a/core/services/registrysyncer/syncer_test.go +++ b/core/services/registrysyncer/syncer_test.go @@ -31,7 +31,7 @@ import ( evmclient "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/headtracker" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller" - kcr "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry_1_1_0" + kcr "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest" "github.com/smartcontractkit/chainlink/v2/core/logger" diff --git a/core/services/relay/dummy/relayer.go b/core/services/relay/dummy/relayer.go index ba65d10e911..3275272b46f 100644 --- a/core/services/relay/dummy/relayer.go +++ b/core/services/relay/dummy/relayer.go @@ -31,7 +31,7 @@ func NewRelayer(lggr logger.Logger, chainID string) loop.Relayer { return &relayer{lggr, chainID} } -func (r *relayer) NewContractWriter(ctx context.Context, chainWriterConfig []byte) (types.ContractWriter, error) { +func (r *relayer) NewChainWriter(ctx context.Context, chainWriterConfig []byte) (types.ChainWriter, error) { return nil, nil } diff --git a/core/services/relay/evm/bindings/chain_reader_tester.go b/core/services/relay/evm/bindings/chain_reader_tester.go index e5299b0d59a..f15f1431679 100644 --- a/core/services/relay/evm/bindings/chain_reader_tester.go +++ b/core/services/relay/evm/bindings/chain_reader_tester.go @@ -13,7 +13,7 @@ import ( type ChainReaderTester struct { BoundContract types.BoundContract ContractReader types.ContractReader - ChainWriter types.ContractWriter + ChainWriter types.ChainWriter } type AccountStruct struct { diff --git a/core/services/relay/evm/cap_encoder.go b/core/services/relay/evm/cap_encoder.go index 713a9796dd2..2a6f288a5de 100644 --- a/core/services/relay/evm/cap_encoder.go +++ b/core/services/relay/evm/cap_encoder.go @@ -8,7 +8,6 @@ import ( "fmt" consensustypes "github.com/smartcontractkit/chainlink-common/pkg/capabilities/consensus/ocr3/types" - commoncodec "github.com/smartcontractkit/chainlink-common/pkg/codec" commontypes "github.com/smartcontractkit/chainlink-common/pkg/types" "github.com/smartcontractkit/chainlink-common/pkg/values" @@ -18,9 +17,8 @@ import ( ) const ( - abiConfigFieldName = "abi" - subabiConfigFieldName = "subabi" - encoderName = "user" + abiConfigFieldName = "abi" + encoderName = "user" ) type capEncoder struct { @@ -48,33 +46,9 @@ func NewEVMEncoder(config *values.Map) (consensustypes.Encoder, error) { return nil, err } - chainCodecConfig := types.ChainCodecConfig{ - TypeABI: string(jsonSelector), - } - - var subabi map[string]string - subabiConfig, ok := config.Underlying[subabiConfigFieldName] - if ok { - err2 := subabiConfig.UnwrapTo(&subabi) - if err2 != nil { - return nil, err2 - } - codecs, err2 := makePreCodecModifierCodecs(subabi) - if err2 != nil { - return nil, err2 - } - chainCodecConfig.ModifierConfigs = commoncodec.ModifiersConfig{ - &commoncodec.PreCodecModifierConfig{ - Fields: subabi, - Codecs: codecs, - }, - } - } - codecConfig := types.CodecConfig{Configs: map[string]types.ChainCodecConfig{ - encoderName: chainCodecConfig, + encoderName: {TypeABI: string(jsonSelector)}, }} - c, err := codec.NewCodec(codecConfig) if err != nil { return nil, err @@ -83,32 +57,6 @@ func NewEVMEncoder(config *values.Map) (consensustypes.Encoder, error) { return &capEncoder{codec: c}, nil } -func makePreCodecModifierCodecs(subabi map[string]string) (map[string]commontypes.RemoteCodec, error) { - codecs := map[string]commontypes.RemoteCodec{} - for _, abi := range subabi { - selector, err := abiutil.ParseSelector("inner(" + abi + ")") - if err != nil { - return nil, err - } - jsonSelector, err := json.Marshal(selector.Inputs) - if err != nil { - return nil, err - } - emptyName := "" - codecConfig := types.CodecConfig{Configs: map[string]types.ChainCodecConfig{ - emptyName: { - TypeABI: string(jsonSelector), - }, - }} - codec, err := codec.NewCodec(codecConfig) - if err != nil { - return nil, err - } - codecs[abi] = codec - } - return codecs, nil -} - func (c *capEncoder) Encode(ctx context.Context, input values.Map) ([]byte, error) { unwrappedInput, err := input.Unwrap() if err != nil { diff --git a/core/services/relay/evm/cap_encoder_test.go b/core/services/relay/evm/cap_encoder_test.go index 4c0285fc987..d290a7fd2b0 100644 --- a/core/services/relay/evm/cap_encoder_test.go +++ b/core/services/relay/evm/cap_encoder_test.go @@ -217,78 +217,6 @@ func TestEVMEncoder_InvalidIDs(t *testing.T) { assert.ErrorContains(t, err, "incorrect length for id") } -func TestEVMEncoder_SubABI(t *testing.T) { - config := map[string]any{ - "abi": "(bytes32 FeedID, bytes Bundle, uint32 Timestamp)[] Reports", - "subabi": map[string]string{ - "Reports.Bundle": "uint256 Ask, uint256 Bid", - }, - } - wrapped, err := values.NewMap(config) - require.NoError(t, err) - enc, err := evm.NewEVMEncoder(wrapped) - require.NoError(t, err) - - type SubReport struct { - Ask int - Bid int - } - type ReportStruct struct { - FeedID [32]byte - Bundle SubReport - Timestamp uint32 - } - reportOne := ReportStruct{ - FeedID: [32]byte{1}, - Bundle: SubReport{ - Ask: 5, - Bid: 6, - }, - Timestamp: 47890122, - } - reportTwo := ReportStruct{ - FeedID: [32]byte{2}, - Bundle: SubReport{ - Ask: 7, - Bid: 8, - }, - Timestamp: 47890122, - } - - // output of a reduce aggregator + metadata fields appended by OCR - input := map[string]any{ - "Reports": []any{reportOne, reportTwo}, - consensustypes.MetadataFieldName: getMetadata(workflowID), - } - wrapped, err = values.NewMap(input) - require.NoError(t, err) - encoded, err := enc.Encode(testutils.Context(t), *wrapped) - require.NoError(t, err) - - expected := - // start of the outer tuple - getHexMetadata() + - // start of the inner tuple (user_fields) - "0000000000000000000000000000000000000000000000000000000000000020" + // offset of Reports array - "0000000000000000000000000000000000000000000000000000000000000002" + // length of Reports array - "0000000000000000000000000000000000000000000000000000000000000040" + // offset of ReportOne - "0000000000000000000000000000000000000000000000000000000000000100" + // offset of ReportTwo - "0100000000000000000000000000000000000000000000000000000000000000" + // ReportOne FeedID - "0000000000000000000000000000000000000000000000000000000000000060" + // offset of ReportOne Bundle - "0000000000000000000000000000000000000000000000000000000002dabeca" + // ReportOne Timestamp - "0000000000000000000000000000000000000000000000000000000000000040" + // length of ReportOne Bundle - "0000000000000000000000000000000000000000000000000000000000000005" + // ReportOne Ask - "0000000000000000000000000000000000000000000000000000000000000006" + // ReportOne Bid - "0200000000000000000000000000000000000000000000000000000000000000" + // ReportTwo FeedID - "0000000000000000000000000000000000000000000000000000000000000060" + // offset of ReportTwo Bundle - "0000000000000000000000000000000000000000000000000000000002dabeca" + // ReportTwo Timestamp - "0000000000000000000000000000000000000000000000000000000000000040" + // length of ReportTwo Bundle - "0000000000000000000000000000000000000000000000000000000000000007" + // ReportTwo Ask - "0000000000000000000000000000000000000000000000000000000000000008" // ReportTwo Bid - - require.Equal(t, expected, hex.EncodeToString(encoded)) -} - func getHexMetadata() string { return "01" + executionID + timestampHex + donIDHex + configVersionHex + workflowID + workflowName + workflowOwnerID + reportID } diff --git a/core/services/relay/evm/capabilities/testutils/backend.go b/core/services/relay/evm/capabilities/testutils/backend.go index cd04373e29e..e76dbc3bc73 100644 --- a/core/services/relay/evm/capabilities/testutils/backend.go +++ b/core/services/relay/evm/capabilities/testutils/backend.go @@ -118,5 +118,5 @@ func (th *EVMBackendTH) NewContractReader(ctx context.Context, t *testing.T, cfg return nil, err } - return svc, err + return svc, svc.Start(ctx) } diff --git a/core/services/relay/evm/capabilities/workflows/syncer/workflow_syncer_test.go b/core/services/relay/evm/capabilities/workflows/syncer/workflow_syncer_test.go deleted file mode 100644 index 6b3f7c7018d..00000000000 --- a/core/services/relay/evm/capabilities/workflows/syncer/workflow_syncer_test.go +++ /dev/null @@ -1,726 +0,0 @@ -package workflow_registry_syncer_test - -import ( - "context" - "crypto/rand" - "encoding/base64" - "encoding/hex" - "fmt" - rand2 "math/rand/v2" - "strings" - "sync" - "testing" - "time" - - "github.com/ethereum/go-ethereum/accounts/abi/bind" - "github.com/ethereum/go-ethereum/common" - "github.com/jonboulle/clockwork" - "github.com/stretchr/testify/assert" - - "github.com/smartcontractkit/chainlink-common/pkg/capabilities" - "github.com/smartcontractkit/chainlink-common/pkg/custmsg" - "github.com/smartcontractkit/chainlink-common/pkg/services" - "github.com/smartcontractkit/chainlink-common/pkg/services/servicetest" - "github.com/smartcontractkit/chainlink-common/pkg/types" - "github.com/smartcontractkit/chainlink-common/pkg/workflows" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/workflow/generated/workflow_registry_wrapper" - coretestutils "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" - "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest" - "github.com/smartcontractkit/chainlink/v2/core/logger" - "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/workflowkey" - "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/capabilities/testutils" - "github.com/smartcontractkit/chainlink/v2/core/services/workflows/syncer" - "github.com/smartcontractkit/chainlink/v2/core/utils/crypto" - - "github.com/stretchr/testify/require" - - crypto2 "github.com/ethereum/go-ethereum/crypto" -) - -type testEvtHandler struct { - events []syncer.Event - mux sync.Mutex -} - -func (m *testEvtHandler) Handle(ctx context.Context, event syncer.Event) error { - m.mux.Lock() - defer m.mux.Unlock() - m.events = append(m.events, event) - return nil -} - -func (m *testEvtHandler) ClearEvents() { - m.mux.Lock() - defer m.mux.Unlock() - m.events = make([]syncer.Event, 0) -} - -func (m *testEvtHandler) GetEvents() []syncer.Event { - m.mux.Lock() - defer m.mux.Unlock() - - eventsCopy := make([]syncer.Event, len(m.events)) - copy(eventsCopy, m.events) - - return eventsCopy -} - -func newTestEvtHandler() *testEvtHandler { - return &testEvtHandler{ - events: make([]syncer.Event, 0), - } -} - -type testWorkflowRegistryContractLoader struct { -} - -type testDonNotifier struct { - don capabilities.DON - err error -} - -func (t *testDonNotifier) WaitForDon(ctx context.Context) (capabilities.DON, error) { - return t.don, t.err -} - -func (m *testWorkflowRegistryContractLoader) LoadWorkflows(ctx context.Context, don capabilities.DON) (*types.Head, error) { - return &types.Head{ - Height: "0", - Hash: nil, - Timestamp: 0, - }, nil -} - -func Test_EventHandlerStateSync(t *testing.T) { - lggr := logger.TestLogger(t) - backendTH := testutils.NewEVMBackendTH(t) - donID := uint32(1) - - eventPollTicker := time.NewTicker(50 * time.Millisecond) - defer eventPollTicker.Stop() - - // Deploy a test workflow_registry - wfRegistryAddr, _, wfRegistryC, err := workflow_registry_wrapper.DeployWorkflowRegistry(backendTH.ContractsOwner, backendTH.Backend.Client()) - backendTH.Backend.Commit() - require.NoError(t, err) - - // setup contract state to allow the secrets to be updated - updateAllowedDONs(t, backendTH, wfRegistryC, []uint32{donID}, true) - updateAuthorizedAddress(t, backendTH, wfRegistryC, []common.Address{backendTH.ContractsOwner.From}, true) - - // Create some initial static state - numberWorkflows := 20 - for i := 0; i < numberWorkflows; i++ { - var workflowID [32]byte - _, err = rand.Read((workflowID)[:]) - require.NoError(t, err) - workflow := RegisterWorkflowCMD{ - Name: fmt.Sprintf("test-wf-%d", i), - DonID: donID, - Status: uint8(1), - SecretsURL: "someurl", - } - workflow.ID = workflowID - registerWorkflow(t, backendTH, wfRegistryC, workflow) - } - - testEventHandler := newTestEvtHandler() - - // Create the registry - registry := syncer.NewWorkflowRegistry( - lggr, - func(ctx context.Context, bytes []byte) (syncer.ContractReader, error) { - return backendTH.NewContractReader(ctx, t, bytes) - }, - wfRegistryAddr.Hex(), - syncer.WorkflowEventPollerConfig{ - QueryCount: 20, - }, - testEventHandler, - &testDonNotifier{ - don: capabilities.DON{ - ID: donID, - }, - err: nil, - }, - syncer.WithTicker(eventPollTicker.C), - ) - - servicetest.Run(t, registry) - - require.Eventually(t, func() bool { - numEvents := len(testEventHandler.GetEvents()) - return numEvents == numberWorkflows - }, 5*time.Second, time.Second) - - for _, event := range testEventHandler.GetEvents() { - assert.Equal(t, syncer.WorkflowRegisteredEvent, event.GetEventType()) - } - - testEventHandler.ClearEvents() - - // Create different event types for a number of workflows and confirm that the event handler processes them in order - numberOfEventCycles := 50 - for i := 0; i < numberOfEventCycles; i++ { - var workflowID [32]byte - _, err = rand.Read((workflowID)[:]) - require.NoError(t, err) - workflow := RegisterWorkflowCMD{ - Name: "test-wf-register-event", - DonID: donID, - Status: uint8(1), - SecretsURL: "", - } - workflow.ID = workflowID - - // Generate events of different types with some jitter - registerWorkflow(t, backendTH, wfRegistryC, workflow) - time.Sleep(time.Millisecond * time.Duration(rand2.IntN(10))) - data := append(backendTH.ContractsOwner.From.Bytes(), []byte(workflow.Name)...) - workflowKey := crypto2.Keccak256Hash(data) - activateWorkflow(t, backendTH, wfRegistryC, workflowKey) - time.Sleep(time.Millisecond * time.Duration(rand2.IntN(10))) - pauseWorkflow(t, backendTH, wfRegistryC, workflowKey) - time.Sleep(time.Millisecond * time.Duration(rand2.IntN(10))) - var newWorkflowID [32]byte - _, err = rand.Read((newWorkflowID)[:]) - require.NoError(t, err) - updateWorkflow(t, backendTH, wfRegistryC, workflowKey, newWorkflowID, workflow.BinaryURL+"2", workflow.ConfigURL, workflow.SecretsURL) - time.Sleep(time.Millisecond * time.Duration(rand2.IntN(10))) - deleteWorkflow(t, backendTH, wfRegistryC, workflowKey) - } - - // Confirm the expected number of events are received in the correct order - require.Eventually(t, func() bool { - events := testEventHandler.GetEvents() - numEvents := len(events) - expectedNumEvents := 5 * numberOfEventCycles - - if numEvents == expectedNumEvents { - // verify the events are the expected types in the expected order - for idx, event := range events { - switch idx % 5 { - case 0: - assert.Equal(t, syncer.WorkflowRegisteredEvent, event.GetEventType()) - case 1: - assert.Equal(t, syncer.WorkflowActivatedEvent, event.GetEventType()) - case 2: - assert.Equal(t, syncer.WorkflowPausedEvent, event.GetEventType()) - case 3: - assert.Equal(t, syncer.WorkflowUpdatedEvent, event.GetEventType()) - case 4: - assert.Equal(t, syncer.WorkflowDeletedEvent, event.GetEventType()) - } - } - return true - } - - return false - }, 50*time.Second, time.Second) -} - -func Test_InitialStateSync(t *testing.T) { - lggr := logger.TestLogger(t) - backendTH := testutils.NewEVMBackendTH(t) - donID := uint32(1) - - // Deploy a test workflow_registry - wfRegistryAddr, _, wfRegistryC, err := workflow_registry_wrapper.DeployWorkflowRegistry(backendTH.ContractsOwner, backendTH.Backend.Client()) - backendTH.Backend.Commit() - require.NoError(t, err) - - // setup contract state to allow the secrets to be updated - updateAllowedDONs(t, backendTH, wfRegistryC, []uint32{donID}, true) - updateAuthorizedAddress(t, backendTH, wfRegistryC, []common.Address{backendTH.ContractsOwner.From}, true) - - // The number of workflows should be greater than the workflow registry contracts pagination limit to ensure - // that the syncer will query the contract multiple times to get the full list of workflows - numberWorkflows := 250 - for i := 0; i < numberWorkflows; i++ { - var workflowID [32]byte - _, err = rand.Read((workflowID)[:]) - require.NoError(t, err) - workflow := RegisterWorkflowCMD{ - Name: fmt.Sprintf("test-wf-%d", i), - DonID: donID, - Status: uint8(1), - SecretsURL: "someurl", - } - workflow.ID = workflowID - registerWorkflow(t, backendTH, wfRegistryC, workflow) - } - - testEventHandler := newTestEvtHandler() - - // Create the worker - worker := syncer.NewWorkflowRegistry( - lggr, - func(ctx context.Context, bytes []byte) (syncer.ContractReader, error) { - return backendTH.NewContractReader(ctx, t, bytes) - }, - wfRegistryAddr.Hex(), - syncer.WorkflowEventPollerConfig{ - QueryCount: 20, - }, - testEventHandler, - &testDonNotifier{ - don: capabilities.DON{ - ID: donID, - }, - err: nil, - }, - syncer.WithTicker(make(chan time.Time)), - ) - - servicetest.Run(t, worker) - - require.Eventually(t, func() bool { - return len(testEventHandler.GetEvents()) == numberWorkflows - }, 5*time.Second, time.Second) - - for _, event := range testEventHandler.GetEvents() { - assert.Equal(t, syncer.WorkflowRegisteredEvent, event.GetEventType()) - } -} - -func Test_SecretsWorker(t *testing.T) { - var ( - ctx = coretestutils.Context(t) - lggr = logger.TestLogger(t) - emitter = custmsg.NewLabeler() - backendTH = testutils.NewEVMBackendTH(t) - db = pgtest.NewSqlxDB(t) - orm = syncer.NewWorkflowRegistryDS(db, lggr) - - giveTicker = time.NewTicker(500 * time.Millisecond) - giveSecretsURL = "https://original-url.com" - donID = uint32(1) - giveWorkflow = RegisterWorkflowCMD{ - Name: "test-wf", - DonID: donID, - Status: uint8(1), - SecretsURL: giveSecretsURL, - } - giveContents = "contents" - wantContents = "updated contents" - fetcherFn = func(_ context.Context, _ string) ([]byte, error) { - return []byte(wantContents), nil - } - ) - - defer giveTicker.Stop() - - // fill ID with randomd data - var giveID [32]byte - _, err := rand.Read((giveID)[:]) - require.NoError(t, err) - giveWorkflow.ID = giveID - - // Deploy a test workflow_registry - wfRegistryAddr, _, wfRegistryC, err := workflow_registry_wrapper.DeployWorkflowRegistry(backendTH.ContractsOwner, backendTH.Backend.Client()) - backendTH.Backend.Commit() - require.NoError(t, err) - - // Seed the DB - hash, err := crypto.Keccak256(append(backendTH.ContractsOwner.From[:], []byte(giveSecretsURL)...)) - require.NoError(t, err) - giveHash := hex.EncodeToString(hash) - - gotID, err := orm.Create(ctx, giveSecretsURL, giveHash, giveContents) - require.NoError(t, err) - - gotSecretsURL, err := orm.GetSecretsURLByID(ctx, gotID) - require.NoError(t, err) - require.Equal(t, giveSecretsURL, gotSecretsURL) - - // verify the DB - contents, err := orm.GetContents(ctx, giveSecretsURL) - require.NoError(t, err) - require.Equal(t, contents, giveContents) - - handler := &testSecretsWorkEventHandler{ - wrappedHandler: syncer.NewEventHandler(lggr, orm, fetcherFn, nil, nil, - emitter, clockwork.NewFakeClock(), workflowkey.Key{}), - registeredCh: make(chan syncer.Event, 1), - } - - worker := syncer.NewWorkflowRegistry( - lggr, - func(ctx context.Context, bytes []byte) (syncer.ContractReader, error) { - return backendTH.NewContractReader(ctx, t, bytes) - }, - wfRegistryAddr.Hex(), - syncer.WorkflowEventPollerConfig{QueryCount: 20}, - handler, - &testDonNotifier{ - don: capabilities.DON{ - ID: donID, - }, - err: nil, - }, - syncer.WithTicker(giveTicker.C), - ) - - // setup contract state to allow the secrets to be updated - updateAllowedDONs(t, backendTH, wfRegistryC, []uint32{donID}, true) - updateAuthorizedAddress(t, backendTH, wfRegistryC, []common.Address{backendTH.ContractsOwner.From}, true) - registerWorkflow(t, backendTH, wfRegistryC, giveWorkflow) - - servicetest.Run(t, worker) - - // wait for the workflow to be registered - <-handler.registeredCh - - // generate a log event - requestForceUpdateSecrets(t, backendTH, wfRegistryC, giveSecretsURL) - - // Require the secrets contents to eventually be updated - require.Eventually(t, func() bool { - secrets, err := orm.GetContents(ctx, giveSecretsURL) - lggr.Debugf("got secrets %v", secrets) - require.NoError(t, err) - return secrets == wantContents - }, 15*time.Second, time.Second) -} - -func Test_RegistrySyncer_WorkflowRegistered_InitiallyPaused(t *testing.T) { - var ( - ctx = coretestutils.Context(t) - lggr = logger.TestLogger(t) - emitter = custmsg.NewLabeler() - backendTH = testutils.NewEVMBackendTH(t) - db = pgtest.NewSqlxDB(t) - orm = syncer.NewWorkflowRegistryDS(db, lggr) - - giveTicker = time.NewTicker(500 * time.Millisecond) - giveBinaryURL = "https://original-url.com" - donID = uint32(1) - giveWorkflow = RegisterWorkflowCMD{ - Name: "test-wf", - DonID: donID, - Status: uint8(1), - BinaryURL: giveBinaryURL, - } - wantContents = "updated contents" - fetcherFn = func(_ context.Context, _ string) ([]byte, error) { - return []byte(base64.StdEncoding.EncodeToString([]byte(wantContents))), nil - } - ) - - defer giveTicker.Stop() - - // Deploy a test workflow_registry - wfRegistryAddr, _, wfRegistryC, err := workflow_registry_wrapper.DeployWorkflowRegistry(backendTH.ContractsOwner, backendTH.Backend.Client()) - backendTH.Backend.Commit() - require.NoError(t, err) - - from := [20]byte(backendTH.ContractsOwner.From) - id, err := workflows.GenerateWorkflowID(from[:], "test-wf", []byte(wantContents), []byte(""), "") - require.NoError(t, err) - giveWorkflow.ID = id - - er := syncer.NewEngineRegistry() - handler := syncer.NewEventHandler(lggr, orm, fetcherFn, nil, nil, - emitter, clockwork.NewFakeClock(), workflowkey.Key{}, syncer.WithEngineRegistry(er)) - - worker := syncer.NewWorkflowRegistry( - lggr, - func(ctx context.Context, bytes []byte) (syncer.ContractReader, error) { - return backendTH.NewContractReader(ctx, t, bytes) - }, - wfRegistryAddr.Hex(), - syncer.WorkflowEventPollerConfig{QueryCount: 20}, - handler, - &testDonNotifier{ - don: capabilities.DON{ - ID: donID, - }, - err: nil, - }, - syncer.WithTicker(giveTicker.C), - ) - - // setup contract state to allow the secrets to be updated - updateAllowedDONs(t, backendTH, wfRegistryC, []uint32{donID}, true) - updateAuthorizedAddress(t, backendTH, wfRegistryC, []common.Address{backendTH.ContractsOwner.From}, true) - - servicetest.Run(t, worker) - - // generate a log event - registerWorkflow(t, backendTH, wfRegistryC, giveWorkflow) - - // Require the secrets contents to eventually be updated - require.Eventually(t, func() bool { - _, err = er.Get("test-wf") - if err == nil { - return false - } - - owner := strings.ToLower(backendTH.ContractsOwner.From.Hex()[2:]) - _, err := orm.GetWorkflowSpec(ctx, owner, "test-wf") - return err == nil - }, 15*time.Second, time.Second) -} - -type mockService struct{} - -func (m *mockService) Start(context.Context) error { return nil } - -func (m *mockService) Close() error { return nil } - -func (m *mockService) HealthReport() map[string]error { return map[string]error{"svc": nil} } - -func (m *mockService) Ready() error { return nil } - -func (m *mockService) Name() string { return "svc" } - -type mockEngineFactory struct{} - -func (m *mockEngineFactory) new(ctx context.Context, wfid string, owner string, name string, config []byte, binary []byte) (services.Service, error) { - return &mockService{}, nil -} - -func Test_RegistrySyncer_WorkflowRegistered_InitiallyActivated(t *testing.T) { - var ( - ctx = coretestutils.Context(t) - lggr = logger.TestLogger(t) - emitter = custmsg.NewLabeler() - backendTH = testutils.NewEVMBackendTH(t) - db = pgtest.NewSqlxDB(t) - orm = syncer.NewWorkflowRegistryDS(db, lggr) - - giveTicker = time.NewTicker(500 * time.Millisecond) - giveBinaryURL = "https://original-url.com" - donID = uint32(1) - giveWorkflow = RegisterWorkflowCMD{ - Name: "test-wf", - DonID: donID, - Status: uint8(0), - BinaryURL: giveBinaryURL, - } - wantContents = "updated contents" - fetcherFn = func(_ context.Context, _ string) ([]byte, error) { - return []byte(base64.StdEncoding.EncodeToString([]byte(wantContents))), nil - } - ) - - defer giveTicker.Stop() - - // Deploy a test workflow_registry - wfRegistryAddr, _, wfRegistryC, err := workflow_registry_wrapper.DeployWorkflowRegistry(backendTH.ContractsOwner, backendTH.Backend.Client()) - backendTH.Backend.Commit() - require.NoError(t, err) - - from := [20]byte(backendTH.ContractsOwner.From) - id, err := workflows.GenerateWorkflowID(from[:], "test-wf", []byte(wantContents), []byte(""), "") - require.NoError(t, err) - giveWorkflow.ID = id - - mf := &mockEngineFactory{} - er := syncer.NewEngineRegistry() - handler := syncer.NewEventHandler( - lggr, - orm, - fetcherFn, - nil, - nil, - emitter, - clockwork.NewFakeClock(), - workflowkey.Key{}, - syncer.WithEngineRegistry(er), - syncer.WithEngineFactoryFn(mf.new), - ) - - worker := syncer.NewWorkflowRegistry( - lggr, - func(ctx context.Context, bytes []byte) (syncer.ContractReader, error) { - return backendTH.NewContractReader(ctx, t, bytes) - }, - wfRegistryAddr.Hex(), - syncer.WorkflowEventPollerConfig{QueryCount: 20}, - handler, - &testDonNotifier{ - don: capabilities.DON{ - ID: donID, - }, - err: nil, - }, - syncer.WithTicker(giveTicker.C), - ) - - // setup contract state to allow the secrets to be updated - updateAllowedDONs(t, backendTH, wfRegistryC, []uint32{donID}, true) - updateAuthorizedAddress(t, backendTH, wfRegistryC, []common.Address{backendTH.ContractsOwner.From}, true) - - servicetest.Run(t, worker) - - // generate a log event - registerWorkflow(t, backendTH, wfRegistryC, giveWorkflow) - - // Require the secrets contents to eventually be updated - require.Eventually(t, func() bool { - _, err := er.Get("test-wf") - if err != nil { - return err != nil - } - - owner := strings.ToLower(backendTH.ContractsOwner.From.Hex()[2:]) - _, err = orm.GetWorkflowSpec(ctx, owner, "test-wf") - return err == nil - }, 15*time.Second, time.Second) -} - -func updateAuthorizedAddress( - t *testing.T, - th *testutils.EVMBackendTH, - wfRegC *workflow_registry_wrapper.WorkflowRegistry, - addresses []common.Address, - _ bool, -) { - t.Helper() - _, err := wfRegC.UpdateAuthorizedAddresses(th.ContractsOwner, addresses, true) - require.NoError(t, err, "failed to update authorised addresses") - th.Backend.Commit() - th.Backend.Commit() - th.Backend.Commit() - gotAddresses, err := wfRegC.GetAllAuthorizedAddresses(&bind.CallOpts{ - From: th.ContractsOwner.From, - }) - require.NoError(t, err) - require.ElementsMatch(t, addresses, gotAddresses) -} - -func updateAllowedDONs( - t *testing.T, - th *testutils.EVMBackendTH, - wfRegC *workflow_registry_wrapper.WorkflowRegistry, - donIDs []uint32, - allowed bool, -) { - t.Helper() - _, err := wfRegC.UpdateAllowedDONs(th.ContractsOwner, donIDs, allowed) - require.NoError(t, err, "failed to update DONs") - th.Backend.Commit() - th.Backend.Commit() - th.Backend.Commit() - gotDons, err := wfRegC.GetAllAllowedDONs(&bind.CallOpts{ - From: th.ContractsOwner.From, - }) - require.NoError(t, err) - require.ElementsMatch(t, donIDs, gotDons) -} - -type RegisterWorkflowCMD struct { - Name string - ID [32]byte - DonID uint32 - Status uint8 - BinaryURL string - ConfigURL string - SecretsURL string -} - -func registerWorkflow( - t *testing.T, - th *testutils.EVMBackendTH, - wfRegC *workflow_registry_wrapper.WorkflowRegistry, - input RegisterWorkflowCMD, -) { - t.Helper() - _, err := wfRegC.RegisterWorkflow(th.ContractsOwner, input.Name, input.ID, input.DonID, - input.Status, input.BinaryURL, input.ConfigURL, input.SecretsURL) - require.NoError(t, err, "failed to register workflow") - th.Backend.Commit() - th.Backend.Commit() - th.Backend.Commit() -} - -func requestForceUpdateSecrets( - t *testing.T, - th *testutils.EVMBackendTH, - wfRegC *workflow_registry_wrapper.WorkflowRegistry, - secretsURL string, -) { - _, err := wfRegC.RequestForceUpdateSecrets(th.ContractsOwner, secretsURL) - require.NoError(t, err) - th.Backend.Commit() - th.Backend.Commit() - th.Backend.Commit() -} - -func activateWorkflow( - t *testing.T, - th *testutils.EVMBackendTH, - wfRegC *workflow_registry_wrapper.WorkflowRegistry, - workflowKey [32]byte, -) { - t.Helper() - _, err := wfRegC.ActivateWorkflow(th.ContractsOwner, workflowKey) - require.NoError(t, err, "failed to activate workflow") - th.Backend.Commit() - th.Backend.Commit() - th.Backend.Commit() -} - -func pauseWorkflow( - t *testing.T, - th *testutils.EVMBackendTH, - wfRegC *workflow_registry_wrapper.WorkflowRegistry, - workflowKey [32]byte, -) { - t.Helper() - _, err := wfRegC.PauseWorkflow(th.ContractsOwner, workflowKey) - require.NoError(t, err, "failed to pause workflow") - th.Backend.Commit() - th.Backend.Commit() - th.Backend.Commit() -} - -func deleteWorkflow( - t *testing.T, - th *testutils.EVMBackendTH, - wfRegC *workflow_registry_wrapper.WorkflowRegistry, - workflowKey [32]byte, -) { - t.Helper() - _, err := wfRegC.DeleteWorkflow(th.ContractsOwner, workflowKey) - require.NoError(t, err, "failed to delete workflow") - th.Backend.Commit() - th.Backend.Commit() - th.Backend.Commit() -} - -func updateWorkflow( - t *testing.T, - th *testutils.EVMBackendTH, - wfRegC *workflow_registry_wrapper.WorkflowRegistry, - workflowKey [32]byte, newWorkflowID [32]byte, binaryURL string, configURL string, secretsURL string, -) { - t.Helper() - _, err := wfRegC.UpdateWorkflow(th.ContractsOwner, workflowKey, newWorkflowID, binaryURL, configURL, secretsURL) - require.NoError(t, err, "failed to update workflow") - th.Backend.Commit() - th.Backend.Commit() - th.Backend.Commit() -} - -type evtHandler interface { - Handle(ctx context.Context, event syncer.Event) error -} - -type testSecretsWorkEventHandler struct { - wrappedHandler evtHandler - registeredCh chan syncer.Event -} - -func (m *testSecretsWorkEventHandler) Handle(ctx context.Context, event syncer.Event) error { - switch { - case event.GetEventType() == syncer.ForceUpdateSecretsEvent: - return m.wrappedHandler.Handle(ctx, event) - case event.GetEventType() == syncer.WorkflowRegisteredEvent: - m.registeredCh <- event - return nil - default: - panic(fmt.Sprintf("unexpected event type: %v", event.GetEventType())) - } -} diff --git a/core/services/relay/evm/chain_components_test.go b/core/services/relay/evm/chain_components_test.go index 1e8c47c51ec..3efa50d1ec5 100644 --- a/core/services/relay/evm/chain_components_test.go +++ b/core/services/relay/evm/chain_components_test.go @@ -3,7 +3,6 @@ package evm_test import ( "context" "crypto/ecdsa" - "errors" "fmt" "math" "math/big" @@ -13,7 +12,6 @@ import ( "time" "github.com/ethereum/go-ethereum/accounts/abi/bind" - "github.com/ethereum/go-ethereum/common" evmtypes "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/ethclient/simulated" @@ -21,21 +19,14 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "github.com/smartcontractkit/chainlink-common/pkg/services" - commonconfig "github.com/smartcontractkit/chainlink-common/pkg/config" commontestutils "github.com/smartcontractkit/chainlink-common/pkg/loop/testutils" clcommontypes "github.com/smartcontractkit/chainlink-common/pkg/types" - "github.com/smartcontractkit/chainlink-common/pkg/types/interfacetests" - "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" - htMocks "github.com/smartcontractkit/chainlink/v2/common/headtracker/mocks" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller" - lpMocks "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller/mocks" evmtxmgr "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr" - clevmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest" @@ -44,9 +35,8 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/ethkey" "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm" + . "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/evmtesting" //nolint common practice to import test mods with . "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/types" - - . "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/evmtesting" //nolint:revive // dot-imports ) const commonGasLimitOnEvms = uint64(4712388) @@ -214,25 +204,9 @@ func TestContractReaderEventsInitValidation(t *testing.T) { } } -func TestChainReader_HealthReport(t *testing.T) { - lp := lpMocks.NewLogPoller(t) - lp.EXPECT().HealthReport().Return(map[string]error{"lp_name": clcommontypes.ErrFinalityViolated}).Once() - ht := htMocks.NewHeadTracker[*clevmtypes.Head, common.Hash](t) - htError := errors.New("head tracker error") - ht.EXPECT().HealthReport().Return(map[string]error{"ht_name": htError}).Once() - cr, err := evm.NewChainReaderService(testutils.Context(t), logger.NullLogger, lp, ht, nil, types.ChainReaderConfig{Contracts: nil}) - require.NoError(t, err) - healthReport := cr.HealthReport() - require.True(t, services.ContainsError(healthReport, clcommontypes.ErrFinalityViolated), "expected chain reader to propagate logpoller's error") - require.True(t, services.ContainsError(healthReport, htError), "expected chain reader to propagate headtracker's error") -} - func TestChainComponents(t *testing.T) { - tests.SkipFlakey(t, "https://smartcontract-it.atlassian.net/browse/BCFR-1083") t.Parallel() it := &EVMChainComponentsInterfaceTester[*testing.T]{Helper: &helper{}} - // TODO, generated binding tests are broken - it.DisableTests([]string{interfacetests.ContractReaderGetLatestValue}) it.Init(t) // add new subtests here so that it can be run on real chains too @@ -335,7 +309,7 @@ func (h *helper) ChainReaderEVMClient(ctx context.Context, t *testing.T, ht logp return cwh } -func (h *helper) WrappedChainWriter(cw clcommontypes.ContractWriter, client client.Client) clcommontypes.ContractWriter { +func (h *helper) WrappedChainWriter(cw clcommontypes.ChainWriter, client client.Client) clcommontypes.ChainWriter { cwhw := evm.NewChainWriterHistoricalWrapper(cw, client.(*evm.ClientWithContractHistory)) return cwhw } diff --git a/core/services/relay/evm/chain_reader.go b/core/services/relay/evm/chain_reader.go index ffe9cd19aea..4de739a44b4 100644 --- a/core/services/relay/evm/chain_reader.go +++ b/core/services/relay/evm/chain_reader.go @@ -4,7 +4,6 @@ import ( "context" "errors" "fmt" - "iter" "maps" "slices" "strings" @@ -20,7 +19,6 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/types/query" "github.com/smartcontractkit/chainlink-common/pkg/types/query/primitives" "github.com/smartcontractkit/chainlink-common/pkg/values" - evmclient "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller" evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" @@ -180,13 +178,7 @@ func (cr *chainReader) Close() error { func (cr *chainReader) Ready() error { return nil } func (cr *chainReader) HealthReport() map[string]error { - report := map[string]error{ - cr.Name(): cr.Healthy(), - } - - commonservices.CopyHealth(report, cr.lp.HealthReport()) - commonservices.CopyHealth(report, cr.ht.HealthReport()) - return report + return map[string]error{cr.Name(): nil} } func (cr *chainReader) Bind(ctx context.Context, bindings []commontypes.BoundContract) error { @@ -206,11 +198,7 @@ func (cr *chainReader) GetLatestValue(ctx context.Context, readName string, conf ptrToValue, isValue := returnVal.(*values.Value) if !isValue { _, err = binding.GetLatestValueWithHeadData(ctx, common.HexToAddress(address), confidenceLevel, params, returnVal) - if err != nil { - return err - } - - return nil + return err } contractType, err := cr.CreateContractType(readName, false) @@ -310,41 +298,6 @@ func (cr *chainReader) QueryKey( return sequenceOfValues, nil } -func (cr *chainReader) QueryKeys(ctx context.Context, filters []commontypes.ContractKeyFilter, - limitAndSort query.LimitAndSort) (iter.Seq2[string, commontypes.Sequence], error) { - eventQueries := make([]read.EventQuery, 0, len(filters)) - for _, filter := range filters { - binding, address, err := cr.bindings.GetReader(filter.Contract.ReadIdentifier(filter.KeyFilter.Key)) - if err != nil { - return nil, err - } - - sequenceDataType := filter.SequenceDataType - _, isValuePtr := filter.SequenceDataType.(*values.Value) - if isValuePtr { - sequenceDataType, err = cr.CreateContractType(filter.Contract.ReadIdentifier(filter.Key), false) - if err != nil { - return nil, err - } - } - - eventBinding, ok := binding.(*read.EventBinding) - if !ok { - return nil, fmt.Errorf("query key %s is not an event", filter.KeyFilter.Key) - } - - eventQueries = append(eventQueries, read.EventQuery{ - Filter: filter.KeyFilter, - SequenceDataType: sequenceDataType, - IsValuePtr: isValuePtr, - EventBinding: eventBinding, - Address: common.HexToAddress(address), - }) - } - - return read.MultiEventTypeQuery(ctx, cr.lp, eventQueries, limitAndSort) -} - func (cr *chainReader) CreateContractType(readIdentifier string, forEncoding bool) (any, error) { return cr.codec.CreateType(cr.bindings.ReadTypeIdentifier(readIdentifier, forEncoding), forEncoding) } diff --git a/core/services/relay/evm/chain_reader_historical_client_wrapper_test.go b/core/services/relay/evm/chain_reader_historical_client_wrapper_test.go index 31122c8a5c4..d0aa4a21332 100644 --- a/core/services/relay/evm/chain_reader_historical_client_wrapper_test.go +++ b/core/services/relay/evm/chain_reader_historical_client_wrapper_test.go @@ -13,13 +13,12 @@ import ( "github.com/ethereum/go-ethereum/common/hexutil" clcommontypes "github.com/smartcontractkit/chainlink-common/pkg/types" + . "github.com/smartcontractkit/chainlink-common/pkg/types/interfacetests" //nolint common practice to import test mods with . "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller" "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/codec" "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/types" - - . "github.com/smartcontractkit/chainlink-common/pkg/types/interfacetests" //nolint:revive // dot-imports ) // ClientWithContractHistory makes it possible to modify client.Client CallContract so that it returns historical data. diff --git a/core/services/relay/evm/chain_writer.go b/core/services/relay/evm/chain_writer.go index ab82a67084c..779a13de90c 100644 --- a/core/services/relay/evm/chain_writer.go +++ b/core/services/relay/evm/chain_writer.go @@ -26,7 +26,7 @@ import ( type ChainWriterService interface { services.ServiceCtx - commontypes.ContractWriter + commontypes.ChainWriter } // Compile-time assertion that chainWriter implements the ChainWriterService interface. diff --git a/core/services/relay/evm/chain_writer_historical_wrapper_test.go b/core/services/relay/evm/chain_writer_historical_wrapper_test.go index 3e661b553e2..233d7bc2e2f 100644 --- a/core/services/relay/evm/chain_writer_historical_wrapper_test.go +++ b/core/services/relay/evm/chain_writer_historical_wrapper_test.go @@ -2,6 +2,7 @@ package evm import ( "context" + "math/big" commontypes "github.com/smartcontractkit/chainlink-common/pkg/types" @@ -14,12 +15,12 @@ import ( // Since the geth simulated backend doesn't support historical data, we use this // thin wrapper. type ChainWriterHistoricalWrapper struct { - commontypes.ContractWriter + commontypes.ChainWriter cwh *ClientWithContractHistory } -func NewChainWriterHistoricalWrapper(cw commontypes.ContractWriter, cwh *ClientWithContractHistory) *ChainWriterHistoricalWrapper { - return &ChainWriterHistoricalWrapper{ContractWriter: cw, cwh: cwh} +func NewChainWriterHistoricalWrapper(cw commontypes.ChainWriter, cwh *ClientWithContractHistory) *ChainWriterHistoricalWrapper { + return &ChainWriterHistoricalWrapper{ChainWriter: cw, cwh: cwh} } func (cwhw *ChainWriterHistoricalWrapper) SubmitTransaction(ctx context.Context, contractName, method string, args any, transactionID string, toAddress string, meta *commontypes.TxMeta, value *big.Int) error { @@ -37,7 +38,7 @@ func (cwhw *ChainWriterHistoricalWrapper) SubmitTransaction(ctx context.Context, return err } } - return cwhw.ContractWriter.SubmitTransaction(ctx, contractName, method, args, transactionID, toAddress, meta, value) + return cwhw.ChainWriter.SubmitTransaction(ctx, contractName, method, args, transactionID, toAddress, meta, value) } func (cwhw *ChainWriterHistoricalWrapper) getPrimitiveValueIfPossible(args any) (bool, uint64) { diff --git a/core/services/relay/evm/codec/codec_test.go b/core/services/relay/evm/codec/codec_test.go index 66fc45a3037..2da88abaac1 100644 --- a/core/services/relay/evm/codec/codec_test.go +++ b/core/services/relay/evm/codec/codec_test.go @@ -16,15 +16,14 @@ import ( commoncodec "github.com/smartcontractkit/chainlink-common/pkg/codec" "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/evmtesting" - looptestutils "github.com/smartcontractkit/chainlink-common/pkg/loop/testutils" + looptestutils "github.com/smartcontractkit/chainlink-common/pkg/loop/testutils" //nolint common practice to import test mods with . commontypes "github.com/smartcontractkit/chainlink-common/pkg/types" + . "github.com/smartcontractkit/chainlink-common/pkg/types/interfacetests" //nolint common practice to import test mods with . "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/chain_reader_tester" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/codec" "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/types" - - . "github.com/smartcontractkit/chainlink-common/pkg/types/interfacetests" //nolint:revive // dot-imports ) const anyExtraValue = 3 @@ -289,8 +288,8 @@ func packArgs(t *testing.T, allArgs []any, oargs abi.Arguments, request *EncodeR } if request.MissingField { - args = args[1:] - allArgs = allArgs[1:] + args = args[1:] //nolint we know it's non-zero len + allArgs = allArgs[1:] //nolint we know it's non-zero len } bytes, err := args.Pack(allArgs...) diff --git a/core/services/relay/evm/commit_provider.go b/core/services/relay/evm/commit_provider.go index 95d7371ab16..1a9260120f3 100644 --- a/core/services/relay/evm/commit_provider.go +++ b/core/services/relay/evm/commit_provider.go @@ -225,7 +225,7 @@ func (p *SrcCommitProvider) Start(ctx context.Context) error { if p.startBlock > math.MaxInt64 { return fmt.Errorf("start block overflows int64: %d", p.startBlock) } - return p.lp.Replay(ctx, int64(p.startBlock)) + return p.lp.Replay(ctx, int64(p.startBlock)) //nolint:gosec // G115 false positive } return nil } @@ -236,7 +236,7 @@ func (p *DstCommitProvider) Start(ctx context.Context) error { if p.startBlock > math.MaxInt64 { return fmt.Errorf("start block overflows int64: %d", p.startBlock) } - return p.lp.Replay(ctx, int64(p.startBlock)) + return p.lp.Replay(ctx, int64(p.startBlock)) //nolint:gosec // G115 false positive } return nil } diff --git a/core/services/relay/evm/evm.go b/core/services/relay/evm/evm.go index e60dbe1bfdb..db0fe90796b 100644 --- a/core/services/relay/evm/evm.go +++ b/core/services/relay/evm/evm.go @@ -12,13 +12,11 @@ import ( "net/http" "strings" "sync" - "time" "github.com/ethereum/go-ethereum/accounts/abi" "github.com/ethereum/go-ethereum/common" "github.com/google/uuid" pkgerrors "github.com/pkg/errors" - "github.com/prometheus/client_golang/prometheus" "golang.org/x/exp/maps" "github.com/smartcontractkit/libocr/gethwrappers2/ocr2aggregator" @@ -41,7 +39,6 @@ import ( txm "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr" evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" "github.com/smartcontractkit/chainlink/v2/core/chains/legacyevm" - coreconfig "github.com/smartcontractkit/chainlink/v2/core/config" "github.com/smartcontractkit/chainlink/v2/core/services/keystore" "github.com/smartcontractkit/chainlink/v2/core/services/llo" "github.com/smartcontractkit/chainlink/v2/core/services/llo/bm" @@ -88,7 +85,7 @@ func init() { } } -var _ commontypes.Relayer = &Relayer{} +var _ commontypes.Relayer = &Relayer{} //nolint:staticcheck // The current PluginProvider interface does not support an error return. This was fine up until CCIP. // CCIP is the first product to introduce the idea of incomplete implementations of a provider based on @@ -145,7 +142,6 @@ type Relayer struct { ds sqlutil.DataSource chain legacyevm.Chain lggr logger.SugaredLogger - registerer prometheus.Registerer ks CSAETHKeystore mercuryPool wsrpc.Pool codec commontypes.Codec @@ -153,7 +149,7 @@ type Relayer struct { // Mercury mercuryORM mercury.ORM - mercuryCfg MercuryConfig + transmitterCfg mercury.TransmitterConfig triggerCapability *triggers.MercuryTriggerService // LLO/data streams @@ -166,20 +162,14 @@ type CSAETHKeystore interface { Eth() keystore.Eth } -type MercuryConfig interface { - Transmitter() coreconfig.MercuryTransmitter - VerboseLogging() bool -} - type RelayerOpts struct { - DS sqlutil.DataSource - Registerer prometheus.Registerer + DS sqlutil.DataSource CSAETHKeystore MercuryPool wsrpc.Pool RetirementReportCache llo.RetirementReportCache - MercuryConfig - CapabilitiesRegistry coretypes.CapabilitiesRegistry - HTTPClient *http.Client + TransmitterConfig mercury.TransmitterConfig + CapabilitiesRegistry coretypes.CapabilitiesRegistry + HTTPClient *http.Client } func (c RelayerOpts) Validate() error { @@ -218,13 +208,12 @@ func NewRelayer(ctx context.Context, lggr logger.Logger, chain legacyevm.Chain, ds: opts.DS, chain: chain, lggr: sugared, - registerer: opts.Registerer, ks: opts.CSAETHKeystore, mercuryPool: opts.MercuryPool, cdcFactory: cdcFactory, retirementReportCache: opts.RetirementReportCache, mercuryORM: mercuryORM, - mercuryCfg: opts.MercuryConfig, + transmitterCfg: opts.TransmitterConfig, capabilitiesRegistry: opts.CapabilitiesRegistry, } @@ -260,14 +249,6 @@ func (r *Relayer) Close() error { cs := make([]io.Closer, 0, 2) if r.triggerCapability != nil { cs = append(cs, r.triggerCapability) - - ctx, cancel := context.WithTimeout(context.Background(), time.Second) - defer cancel() - - err := r.capabilitiesRegistry.Remove(ctx, r.triggerCapability.ID) - if err != nil { - return err - } } cs = append(cs, r.chain) return services.MultiCloser(cs).Close() @@ -465,6 +446,9 @@ func (r *Relayer) NewMercuryProvider(ctx context.Context, rargs commontypes.Rela } } + // FIXME: We actually know the version here since it's in the feed ID, can + // we use generics to avoid passing three of this? + // https://smartcontract-it.atlassian.net/browse/MERC-1414 reportCodecV1 := reportcodecv1.NewReportCodec(*relayConfig.FeedID, lggr.Named("ReportCodecV1")) reportCodecV2 := reportcodecv2.NewReportCodec(*relayConfig.FeedID, lggr.Named("ReportCodecV2")) reportCodecV3 := reportcodecv3.NewReportCodec(*relayConfig.FeedID, lggr.Named("ReportCodecV3")) @@ -500,7 +484,7 @@ func (r *Relayer) NewMercuryProvider(ctx context.Context, rargs commontypes.Rela return nil, err } - transmitter := mercury.NewTransmitter(lggr, r.mercuryCfg.Transmitter(), clients, privKey.PublicKey, rargs.JobID, *relayConfig.FeedID, r.mercuryORM, transmitterCodec, benchmarkPriceDecoder, r.triggerCapability) + transmitter := mercury.NewTransmitter(lggr, r.transmitterCfg, clients, privKey.PublicKey, rargs.JobID, *relayConfig.FeedID, r.mercuryORM, transmitterCodec, benchmarkPriceDecoder, r.triggerCapability) return NewMercuryProvider(cp, r.codec, NewMercuryChainReader(r.chain.HeadTracker()), transmitter, reportCodecV1, reportCodecV2, reportCodecV3, reportCodecV4, lggr), nil } @@ -552,6 +536,8 @@ func (r *Relayer) NewLLOProvider(ctx context.Context, rargs commontypes.RelayArg return nil, pkgerrors.Wrap(err, "failed to get CSA key for mercury connection") } + // FIXME: Remove after benchmarking is done + // https://smartcontract-it.atlassian.net/browse/MERC-3487 var transmitter LLOTransmitter if lloCfg.BenchmarkMode { r.lggr.Info("Benchmark mode enabled, using dummy transmitter. NOTE: THIS WILL NOT TRANSMIT ANYTHING") @@ -566,18 +552,15 @@ func (r *Relayer) NewLLOProvider(ctx context.Context, rargs commontypes.RelayArg clients[server.URL] = client } transmitter = llo.NewTransmitter(llo.TransmitterOpts{ - Lggr: r.lggr, - FromAccount: fmt.Sprintf("%x", privKey.PublicKey), // NOTE: This may need to change if we support e.g. multiple tranmsmitters, to be a composite of all keys - VerboseLogging: r.mercuryCfg.VerboseLogging(), + Lggr: r.lggr, + FromAccount: fmt.Sprintf("%x", privKey.PublicKey), // NOTE: This may need to change if we support e.g. multiple tranmsmitters, to be a composite of all keys MercuryTransmitterOpts: mercurytransmitter.Opts{ - Lggr: r.lggr, - Registerer: r.registerer, - VerboseLogging: r.mercuryCfg.VerboseLogging(), - Cfg: r.mercuryCfg.Transmitter(), - Clients: clients, - FromAccount: privKey.PublicKey, - DonID: relayConfig.LLODONID, - ORM: mercurytransmitter.NewORM(r.ds, relayConfig.LLODONID), + Lggr: r.lggr, + Cfg: r.transmitterCfg, + Clients: clients, + FromAccount: privKey.PublicKey, + DonID: relayConfig.LLODONID, + ORM: mercurytransmitter.NewORM(r.ds, relayConfig.LLODONID), }, RetirementReportCache: r.retirementReportCache, }) @@ -854,7 +837,7 @@ func generateTransmitterFrom(ctx context.Context, rargs commontypes.RelayArgs, e return transmitter, nil } -func (r *Relayer) NewContractWriter(_ context.Context, config []byte) (commontypes.ContractWriter, error) { +func (r *Relayer) NewChainWriter(_ context.Context, config []byte) (commontypes.ChainWriter, error) { var cfg types.ChainWriterConfig if err := json.Unmarshal(config, &cfg); err != nil { return nil, fmt.Errorf("failed to unmarshall chain writer config err: %s", err) diff --git a/core/services/relay/evm/evmtesting/bindings_test_adapter.go b/core/services/relay/evm/evmtesting/bindings_test_adapter.go index 408acb0d5a8..3dd625266ad 100644 --- a/core/services/relay/evm/evmtesting/bindings_test_adapter.go +++ b/core/services/relay/evm/evmtesting/bindings_test_adapter.go @@ -36,8 +36,6 @@ func WrapContractReaderTesterWithBindings(t *testing.T, wrapped *EVMChainCompone interfacetests.ContractReaderBatchGetLatestValueSetsErrorsProperly, interfacetests.ContractReaderBatchGetLatestValueNoArgumentsWithSliceReturn, interfacetests.ContractReaderBatchGetLatestValueWithModifiersOwnMapstructureOverride, interfacetests.ContractReaderQueryKeyNotFound, interfacetests.ContractReaderQueryKeyReturnsData, interfacetests.ContractReaderQueryKeyReturnsDataAsValuesDotValue, interfacetests.ContractReaderQueryKeyReturnsDataAsValuesDotValue, interfacetests.ContractReaderQueryKeyCanFilterWithValueComparator, interfacetests.ContractReaderQueryKeyCanLimitResultsWithCursor, - interfacetests.ContractReaderQueryKeysNotFound, interfacetests.ContractReaderQueryKeysReturnsData, interfacetests.ContractReaderQueryKeysReturnsDataTwoEventTypes, interfacetests.ContractReaderQueryKeysReturnsDataAsValuesDotValue, - interfacetests.ContractReaderQueryKeysCanFilterWithValueComparator, interfacetests.ContractReaderQueryKeysCanLimitResultsWithCursor, ContractReaderQueryKeyFilterOnDataWordsWithValueComparator, ContractReaderQueryKeyOnDataWordsWithValueComparatorOnNestedField, ContractReaderQueryKeyFilterOnDataWordsWithValueComparatorOnDynamicField, ContractReaderQueryKeyFilteringOnDataWordsUsingValueComparatorsOnFieldsWithManualIndex, // TODO BCFR-1073 - Fix flaky tests @@ -73,7 +71,6 @@ func newBindingsMapping() bindingsMapping { interfacetests.MethodSettingStruct: "AddTestStruct", interfacetests.MethodSettingUint64: "SetAlterablePrimitiveValue", interfacetests.MethodTriggeringEvent: "TriggerEvent", - interfacetests.MethodTriggeringEventWithDynamicTopic: "TriggerEventWithDynamicTopic", } methodNameMappingByContract[interfacetests.AnySecondContractName] = map[string]string{ interfacetests.MethodReturningUint64: "GetDifferentPrimitiveValue", @@ -149,23 +146,23 @@ func (b bindingClientTester) addDefaultBindings(t *testing.T) { if chainReaderTester == nil { chainReaderTester = &bindings.ChainReaderTester{ BoundContract: binding, - ChainWriter: b.bindingsMapping.chainWriterProxy.ContractWriter, + ChainWriter: b.bindingsMapping.chainWriterProxy.ChainWriter, } b.bindingsMapping.chainReaderTesters[binding.Address] = chainReaderTester } else { - chainReaderTester.ChainWriter = b.bindingsMapping.chainWriterProxy.ContractWriter + chainReaderTester.ChainWriter = b.bindingsMapping.chainWriterProxy.ChainWriter } } } -func (b bindingClientTester) GetChainWriter(t *testing.T) commontypes.ContractWriter { - chainWriter := b.ChainComponentsInterfaceTester.GetContractWriter(t) - if b.bindingsMapping.chainWriterProxy.ContractWriter == nil { +func (b bindingClientTester) GetChainWriter(t *testing.T) commontypes.ChainWriter { + chainWriter := b.ChainComponentsInterfaceTester.GetChainWriter(t) + if b.bindingsMapping.chainWriterProxy.ChainWriter == nil { b.addDefaultBindings(t) for _, tester := range b.bindingsMapping.chainReaderTesters { tester.ChainWriter = chainWriter } - b.bindingsMapping.chainWriterProxy.ContractWriter = chainWriter + b.bindingsMapping.chainWriterProxy.ChainWriter = chainWriter } return b.bindingsMapping.chainWriterProxy } @@ -185,7 +182,7 @@ type bindingContractReaderProxy struct { } type bindingChainWriterProxy struct { - commontypes.ContractWriter + commontypes.ChainWriter bm *bindingsMapping } @@ -195,7 +192,7 @@ func (b bindingContractReaderProxy) Bind(ctx context.Context, boundContracts []c b.bm.chainReaderTesters[updatedBinding.Address] = &bindings.ChainReaderTester{ BoundContract: updatedBinding, ContractReader: b.ContractReader, - ChainWriter: b.bm.chainWriterProxy.ContractWriter, + ChainWriter: b.bm.chainWriterProxy.ChainWriter, } } return b.ContractReader.Bind(ctx, updatedBindings) @@ -252,10 +249,6 @@ func (b bindingChainWriterProxy) SubmitTransaction(ctx context.Context, contract bindingsInput := bindings.TriggerEventInput{} _ = convertStruct(args, &bindingsInput) return chainReaderTesters.TriggerEvent(ctx, bindingsInput, transactionID, toAddress, meta) - case interfacetests.MethodTriggeringEventWithDynamicTopic: - bindingsInput := bindings.TriggerEventWithDynamicTopicInput{} - _ = convertStruct(args, &bindingsInput) - return chainReaderTesters.TriggerEventWithDynamicTopic(ctx, bindingsInput, transactionID, toAddress, meta) default: return errors.New("No logic implemented for method: " + method) } @@ -265,7 +258,7 @@ func (b bindingChainWriterProxy) SubmitTransaction(ctx context.Context, contract } func (b *bindingChainWriterProxy) GetTransactionStatus(ctx context.Context, transactionID string) (commontypes.TransactionStatus, error) { - return b.ContractWriter.GetTransactionStatus(ctx, transactionID) + return b.ChainWriter.GetTransactionStatus(ctx, transactionID) } func removeAddressFromReadIdentifier(s string) string { diff --git a/core/services/relay/evm/evmtesting/chain_components_interface_tester.go b/core/services/relay/evm/evmtesting/chain_components_interface_tester.go index 71bd94f0e9f..9655fb78457 100644 --- a/core/services/relay/evm/evmtesting/chain_components_interface_tester.go +++ b/core/services/relay/evm/evmtesting/chain_components_interface_tester.go @@ -16,6 +16,7 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/codec" clcommontypes "github.com/smartcontractkit/chainlink-common/pkg/types" + . "github.com/smartcontractkit/chainlink-common/pkg/types/interfacetests" //nolint common practice to import test mods with . "github.com/smartcontractkit/chainlink-common/pkg/types/query/primitives" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" @@ -31,8 +32,6 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm" "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/types" - - . "github.com/smartcontractkit/chainlink-common/pkg/types/interfacetests" //nolint:revive // dot-imports ) const ( @@ -57,7 +56,7 @@ type EVMChainComponentsInterfaceTesterHelper[T TestingT[T]] interface { TXM(T, client.Client) evmtxmgr.TxManager // To enable the historical wrappers required for Simulated Backend tests. ChainReaderEVMClient(ctx context.Context, t T, ht logpoller.HeadTracker, conf types.ChainReaderConfig) client.Client - WrappedChainWriter(cw clcommontypes.ContractWriter, client client.Client) clcommontypes.ContractWriter + WrappedChainWriter(cw clcommontypes.ChainWriter, client client.Client) clcommontypes.ChainWriter } type EVMChainComponentsInterfaceTester[T TestingT[T]] struct { @@ -395,7 +394,7 @@ func (it *EVMChainComponentsInterfaceTester[T]) GetContractReader(t T) clcommont func (it *EVMChainComponentsInterfaceTester[T]) GenerateBlocksTillConfidenceLevel(t T, contractName, readName string, confidenceLevel primitives.ConfidenceLevel) { } -func (it *EVMChainComponentsInterfaceTester[T]) GetContractWriter(t T) clcommontypes.ContractWriter { +func (it *EVMChainComponentsInterfaceTester[T]) GetChainWriter(t T) clcommontypes.ChainWriter { ctx := it.Helper.Context(t) if it.cw != nil { return it.cw diff --git a/core/services/relay/evm/evmtesting/run_tests.go b/core/services/relay/evm/evmtesting/run_tests.go index b6abffdcb2f..5f3cdbb2fd7 100644 --- a/core/services/relay/evm/evmtesting/run_tests.go +++ b/core/services/relay/evm/evmtesting/run_tests.go @@ -18,7 +18,7 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/read" - . "github.com/smartcontractkit/chainlink-common/pkg/types/interfacetests" //nolint:revive // dot-imports + . "github.com/smartcontractkit/chainlink-common/pkg/types/interfacetests" //nolint common practice to import test mods with . ) const ( diff --git a/core/services/relay/evm/llo/config_poller.go b/core/services/relay/evm/llo/config_poller.go index 1f328ab73c3..66d9c185e38 100644 --- a/core/services/relay/evm/llo/config_poller.go +++ b/core/services/relay/evm/llo/config_poller.go @@ -7,7 +7,6 @@ import ( "fmt" "math" "math/big" - "strconv" "github.com/ethereum/go-ethereum/common" "github.com/pkg/errors" @@ -15,8 +14,6 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink-common/pkg/services" - "github.com/smartcontractkit/chainlink-common/pkg/types/query" - "github.com/smartcontractkit/chainlink-common/pkg/types/query/primitives" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/llo-feeds/generated/configurator" @@ -29,18 +26,15 @@ const ( InstanceTypeGreen InstanceType = InstanceType("Green") ) -var ( - NoLimitSortAsc = query.NewLimitAndSort(query.Limit{}, query.NewSortBySequence(query.Asc)) -) - type ConfigPollerService interface { services.Service ocrtypes.ContractConfigTracker } type LogPoller interface { + IndexedLogsByBlockRange(ctx context.Context, start, end int64, eventSig common.Hash, address common.Address, topicIndex int, topicValues []common.Hash) ([]logpoller.Log, error) LatestBlock(ctx context.Context) (logpoller.LogPollerBlock, error) - FilteredLogs(ctx context.Context, filter []query.Expression, limitAndSort query.LimitAndSort, queryName string) ([]logpoller.Log, error) + LogsWithSigs(ctx context.Context, start, end int64, eventSigs []common.Hash, address common.Address) ([]logpoller.Log, error) } // ConfigCache is most likely the global RetirementReportCache. Every config @@ -53,12 +47,11 @@ type configPoller struct { services.Service eng *services.Engine - lp LogPoller - cc ConfigCache - addr common.Address - donID uint32 - donIDTopic [32]byte - filterExprs []query.Expression + lp LogPoller + cc ConfigCache + addr common.Address + donID uint32 + donIDHash [32]byte fromBlock uint64 @@ -77,28 +70,12 @@ func NewConfigPoller(lggr logger.Logger, lp LogPoller, cc ConfigCache, addr comm } func newConfigPoller(lggr logger.Logger, lp LogPoller, cc ConfigCache, addr common.Address, donID uint32, instanceType InstanceType, fromBlock uint64) *configPoller { - donIDTopic := DonIDToBytes32(donID) - exprs := []query.Expression{ - logpoller.NewAddressFilter(addr), - query.Or( - logpoller.NewEventSigFilter(ProductionConfigSet), - logpoller.NewEventSigFilter(StagingConfigSet), - ), - logpoller.NewEventByTopicFilter(1, []logpoller.HashedValueComparator{ - {Value: donIDTopic, Operator: primitives.Eq}, - }), - // NOTE: Optimize for fast config switches. On Arbitrum, finalization - // can take tens of minutes - // (https://grafana.ops.prod.cldev.sh/d/e0453cc9-4b4a-41e1-9f01-7c21de805b39/blockchain-finality-and-gas?orgId=1&var-env=All&var-network_name=ethereum-testnet-sepolia-arbitrum-1&var-network_name=ethereum-mainnet-arbitrum-1&from=1732460992641&to=1732547392641) - query.Confidence(primitives.Unconfirmed), - } cp := &configPoller{ lp: lp, cc: cc, addr: addr, donID: donID, - donIDTopic: DonIDToBytes32(donID), - filterExprs: exprs, + donIDHash: DonIDToBytes32(donID), instanceType: instanceType, fromBlock: fromBlock, } @@ -123,23 +100,18 @@ func (cp *configPoller) LatestConfigDetails(ctx context.Context) (changedInBlock } func (cp *configPoller) latestConfig(ctx context.Context, fromBlock, toBlock int64) (latestConfig FullConfigFromLog, latestLog logpoller.Log, err error) { - // Get all configset logs and run through them forwards - // NOTE: It's useful to get _all_ logs rather than just the latest since - // they are stored in the ConfigCache - exprs := make([]query.Expression, 0, len(cp.filterExprs)+2) - exprs = append(exprs, cp.filterExprs...) - exprs = append(exprs, - query.Block(strconv.FormatInt(fromBlock, 10), primitives.Gte), - query.Block(strconv.FormatInt(toBlock, 10), primitives.Lte), - ) - logs, err := cp.lp.FilteredLogs(ctx, exprs, NoLimitSortAsc, "LLOConfigPoller - latestConfig") + // Get all config set logs run through them forwards + // TODO: This could probably be optimized with a 'latestBlockNumber' cache or something to avoid reading from `fromBlock` on every call + // TODO: Actually we only care about the latest of each type here + // MERC-3524 + logs, err := cp.lp.LogsWithSigs(ctx, fromBlock, toBlock, []common.Hash{ProductionConfigSet, StagingConfigSet}, cp.addr) if err != nil { return latestConfig, latestLog, fmt.Errorf("failed to get logs: %w", err) } for _, log := range logs { - if !bytes.Equal(log.Topics[1], cp.donIDTopic[:]) { - // skip logs for other donIDs, shouldn't happen given the - // FilterLogs call, but belts and braces + // TODO: This can be optimized probably by adding donIDHash to the logpoller lookup + // MERC-3524 + if !bytes.Equal(log.Topics[1], cp.donIDHash[:]) { continue } switch log.EventSig { diff --git a/core/services/relay/evm/llo/config_poller_test.go b/core/services/relay/evm/llo/config_poller_test.go index f9870b22b9c..c1430b7c150 100644 --- a/core/services/relay/evm/llo/config_poller_test.go +++ b/core/services/relay/evm/llo/config_poller_test.go @@ -14,7 +14,6 @@ import ( ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types" "github.com/smartcontractkit/chainlink-common/pkg/logger" - "github.com/smartcontractkit/chainlink-common/pkg/types/query" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" @@ -25,9 +24,6 @@ var _ LogPoller = (*mockLogPoller)(nil) type mockLogPoller struct { logs []logpoller.Log latestBlock int64 - - exprs []query.Expression - limitAndSort query.LimitAndSort } func (m *mockLogPoller) LatestBlock(ctx context.Context) (logpoller.LogPollerBlock, error) { @@ -39,10 +35,22 @@ func (m *mockLogPoller) RegisterFilter(ctx context.Context, filter logpoller.Fil func (m *mockLogPoller) Replay(ctx context.Context, fromBlock int64) error { return nil } -func (m *mockLogPoller) FilteredLogs(ctx context.Context, filter []query.Expression, limitAndSort query.LimitAndSort, queryName string) ([]logpoller.Log, error) { - m.exprs = filter - m.limitAndSort = limitAndSort - return m.logs, nil +func (m *mockLogPoller) LogsWithSigs(ctx context.Context, start, end int64, eventSigs []common.Hash, address common.Address) ([]logpoller.Log, error) { + logs := make([]logpoller.Log, 0) + for _, log := range m.logs { + if log.BlockNumber >= start && log.BlockNumber <= end && log.Address == address { + for _, sig := range eventSigs { + if log.EventSig == sig { + logs = append(logs, log) + } + } + } + } + + return logs, nil +} +func (m *mockLogPoller) IndexedLogsByBlockRange(ctx context.Context, start, end int64, eventSig common.Hash, address common.Address, topicIndex int, topicValues []common.Hash) ([]logpoller.Log, error) { + return m.LogsWithSigs(ctx, start, end, []common.Hash{eventSig}, address) } type cfg struct { @@ -63,7 +71,7 @@ func (m *mockConfigCache) StoreConfig(ctx context.Context, cd ocrtypes.ConfigDig func Test_ConfigPoller(t *testing.T) { ctx := testutils.Context(t) lggr := logger.Test(t) - lp := &mockLogPoller{make([]logpoller.Log, 0), 0, nil, query.LimitAndSort{}} + lp := &mockLogPoller{make([]logpoller.Log, 0), 0} addr := common.Address{1} donID := uint32(1) donIDHash := DonIDToBytes32(donID) @@ -320,6 +328,15 @@ func Test_ConfigPoller(t *testing.T) { }) }) t.Run("LatestConfig", func(t *testing.T) { + t.Run("changedInBlock in future, returns nothing", func(t *testing.T) { + cfg, err := cpBlue.LatestConfig(ctx, 200) + require.NoError(t, err) + assert.Zero(t, cfg) + + cfg, err = cpGreen.LatestConfig(ctx, 200) + require.NoError(t, err) + assert.Zero(t, cfg) + }) t.Run("changedInBlock corresponds to a block in which a log was emitted, returns the config", func(t *testing.T) { expectedSigners := []ocr2types.OnchainPublicKey{ocr2types.OnchainPublicKey{0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, ocr2types.OnchainPublicKey{0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}} expectedTransmitters := []ocr2types.Account{"0100000000000000000000000000000000000000000000000000000000000000", "0200000000000000000000000000000000000000000000000000000000000000"} diff --git a/core/services/relay/evm/llo/should_retire_cache.go b/core/services/relay/evm/llo/should_retire_cache.go index 96f317817b1..05b33a27fbb 100644 --- a/core/services/relay/evm/llo/should_retire_cache.go +++ b/core/services/relay/evm/llo/should_retire_cache.go @@ -3,7 +3,7 @@ package llo import ( "bytes" "context" - "strconv" + "math" "sync" "time" @@ -11,13 +11,9 @@ import ( ocr2types "github.com/smartcontractkit/libocr/offchainreporting2plus/types" ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types" - "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller" - "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink-common/pkg/services" llotypes "github.com/smartcontractkit/chainlink-common/pkg/types/llo" - "github.com/smartcontractkit/chainlink-common/pkg/types/query" - "github.com/smartcontractkit/chainlink-common/pkg/types/query/primitives" ) type ShouldRetireCacheService interface { @@ -29,11 +25,10 @@ type shouldRetireCache struct { services.Service eng *services.Engine - lp LogPoller - addr common.Address - donID uint32 - donIDTopic common.Hash - filterExprs []query.Expression + lp LogPoller + addr common.Address + donID uint32 + donIDHash common.Hash pollPeriod time.Duration @@ -47,26 +42,13 @@ func NewShouldRetireCache(lggr logger.Logger, lp LogPoller, addr common.Address, } func newShouldRetireCache(lggr logger.Logger, lp LogPoller, addr common.Address, donID uint32) *shouldRetireCache { - donIDTopic := DonIDToBytes32(donID) - exprs := []query.Expression{ - logpoller.NewAddressFilter(addr), - logpoller.NewEventSigFilter(PromoteStagingConfig), - logpoller.NewEventByTopicFilter(1, []logpoller.HashedValueComparator{ - {Value: donIDTopic, Operator: primitives.Eq}, - }), - // NOTE: Optimize for fast retirement detection. On Arbitrum, - // finalization can take tens of minutes - // (https://grafana.ops.prod.cldev.sh/d/e0453cc9-4b4a-41e1-9f01-7c21de805b39/blockchain-finality-and-gas?orgId=1&var-env=All&var-network_name=ethereum-testnet-sepolia-arbitrum-1&var-network_name=ethereum-mainnet-arbitrum-1&from=1732460992641&to=1732547392641) - query.Confidence(primitives.Unconfirmed), - } s := &shouldRetireCache{ - lp: lp, - addr: addr, - donID: donID, - donIDTopic: donIDTopic, - filterExprs: exprs, - m: make(map[ocrtypes.ConfigDigest]struct{}), - pollPeriod: 1 * time.Second, + lp: lp, + addr: addr, + donID: donID, + donIDHash: DonIDToBytes32(donID), + m: make(map[ocrtypes.ConfigDigest]struct{}), + pollPeriod: 1 * time.Second, } s.Service, s.eng = services.Config{ Name: "LLOShouldRetireCache", @@ -97,28 +79,16 @@ func (s *shouldRetireCache) start(ctx context.Context) error { func (s *shouldRetireCache) checkShouldRetire(ctx context.Context) { fromBlock := s.latestBlockNum + 1 - - exprs := make([]query.Expression, 0, len(s.filterExprs)+1) - exprs = append(exprs, s.filterExprs...) - exprs = append(exprs, - query.Block(strconv.FormatInt(fromBlock, 10), primitives.Gte), - ) - - logs, err := s.lp.FilteredLogs(ctx, exprs, NoLimitSortAsc, "ShouldRetireCache - PromoteStagingConfig") + logs, err := s.lp.LogsWithSigs(ctx, fromBlock, math.MaxInt64, []common.Hash{PromoteStagingConfig}, s.addr) if err != nil { s.eng.SugaredLogger.Errorw("checkShouldRetire: IndexedLogs", "err", err) return } for _, log := range logs { - if log.EventSig != PromoteStagingConfig { - // ignore unrecognized logs - continue - } - - if !bytes.Equal(log.Topics[1], s.donIDTopic[:]) { - // skip logs for other donIDs, shouldn't happen given the - // FilterLogs call, but belts and braces + // TODO: This can probably be optimized + // MERC-3524 + if !bytes.Equal(log.Topics[1], s.donIDHash[:]) { continue } digestBytes := log.Topics[2] diff --git a/core/services/relay/evm/llo/should_retire_cache_test.go b/core/services/relay/evm/llo/should_retire_cache_test.go index 25c0c92d017..2583ecc3c83 100644 --- a/core/services/relay/evm/llo/should_retire_cache_test.go +++ b/core/services/relay/evm/llo/should_retire_cache_test.go @@ -13,7 +13,6 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink-common/pkg/services/servicetest" - "github.com/smartcontractkit/chainlink-common/pkg/types/query" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" @@ -21,7 +20,7 @@ import ( func Test_ShouldRetireCache(t *testing.T) { lggr, observedLogs := logger.TestObserved(t, zapcore.DebugLevel) - lp := &mockLogPoller{make([]logpoller.Log, 0), 0, nil, query.LimitAndSort{}} + lp := &mockLogPoller{make([]logpoller.Log, 0), 0} addr := common.Address{1} donID := uint32(1) donIDHash := DonIDToBytes32(donID) diff --git a/core/services/relay/evm/llo_provider.go b/core/services/relay/evm/llo_provider.go index ab7cac6da0c..1f4bdbf6e0c 100644 --- a/core/services/relay/evm/llo_provider.go +++ b/core/services/relay/evm/llo_provider.go @@ -220,6 +220,8 @@ func (w *mercuryConfigPollerWrapper) close() error { func newLLOConfigPollers(ctx context.Context, lggr logger.Logger, cc llo.ConfigCache, lp logpoller.LogPoller, chainID *big.Int, configuratorAddress common.Address, relayConfig types.RelayConfig) (cps []llo.ConfigPollerService, configDigester ocrtypes.OffchainConfigDigester, err error) { donID := relayConfig.LLODONID donIDHash := llo.DonIDToBytes32(donID) + // TODO: Can we auto-detect or verify based on if the contract implements `setConfig` or `setProductionConfig` interfaces? + // MERC-3524 switch relayConfig.LLOConfigMode { case types.LLOConfigModeMercury: // NOTE: This uses the old config digest prefix for compatibility with legacy contracts diff --git a/core/services/relay/evm/mercury/transmitter.go b/core/services/relay/evm/mercury/transmitter.go index be500593bf3..4e57a3d07cf 100644 --- a/core/services/relay/evm/mercury/transmitter.go +++ b/core/services/relay/evm/mercury/transmitter.go @@ -106,6 +106,7 @@ type BenchmarkPriceDecoder func(ctx context.Context, feedID mercuryutils.FeedID, var _ Transmitter = (*mercuryTransmitter)(nil) type TransmitterConfig interface { + TransmitQueueMaxSize() uint32 TransmitTimeout() commonconfig.Duration } @@ -236,7 +237,7 @@ func (s *server) runQueueLoop(stopCh services.StopChan, wg *sync.WaitGroup, feed } res, err := func(ctx context.Context) (*pb.TransmitResponse, error) { ctx, cancel := context.WithTimeout(ctx, utils.WithJitter(s.transmitTimeout)) - defer cancel() + cancel() return s.c.Transmit(ctx, t.Req) }(ctx) if ctx.Err() != nil { @@ -286,16 +287,14 @@ func (s *server) runQueueLoop(stopCh services.StopChan, wg *sync.WaitGroup, feed } } -const TransmitQueueMaxSize = 10_000 // hardcode this for legacy transmitter since we want the config var to apply only to LLO - func newServer(lggr logger.Logger, cfg TransmitterConfig, client wsrpc.Client, pm *PersistenceManager, serverURL, feedIDHex string) *server { return &server{ logger.Sugared(lggr), cfg.TransmitTimeout().Duration(), client, pm, - NewTransmitQueue(lggr, serverURL, feedIDHex, TransmitQueueMaxSize, pm), - make(chan *pb.TransmitRequest, TransmitQueueMaxSize), + NewTransmitQueue(lggr, serverURL, feedIDHex, int(cfg.TransmitQueueMaxSize()), pm), + make(chan *pb.TransmitRequest, int(cfg.TransmitQueueMaxSize())), serverURL, transmitSuccessCount.WithLabelValues(feedIDHex, serverURL), transmitDuplicateCount.WithLabelValues(feedIDHex, serverURL), @@ -312,7 +311,7 @@ func NewTransmitter(lggr logger.Logger, cfg TransmitterConfig, clients map[strin servers := make(map[string]*server, len(clients)) for serverURL, client := range clients { cLggr := sugared.Named(serverURL).With("serverURL", serverURL) - pm := NewPersistenceManager(cLggr, serverURL, orm, jobID, TransmitQueueMaxSize, flushDeletesFrequency, pruneFrequency) + pm := NewPersistenceManager(cLggr, serverURL, orm, jobID, int(cfg.TransmitQueueMaxSize()), flushDeletesFrequency, pruneFrequency) servers[serverURL] = newServer(cLggr, cfg, client, pm, serverURL, feedIDHex) } return &mercuryTransmitter{ diff --git a/core/services/relay/evm/mercury/v1/reportcodec/report_codec_test.go b/core/services/relay/evm/mercury/v1/reportcodec/report_codec_test.go index f5e2c7453e8..b24e69ce387 100644 --- a/core/services/relay/evm/mercury/v1/reportcodec/report_codec_test.go +++ b/core/services/relay/evm/mercury/v1/reportcodec/report_codec_test.go @@ -157,7 +157,7 @@ func (r *ReportCodec) ValidFromBlockNumFromReport(report ocrtypes.Report) (int64 if n > math.MaxInt64 { return 0, fmt.Errorf("ValidFromBlockNum=%d overflows max int64", n) } - return int64(n), nil + return int64(n), nil //nolint:gosec // G115 } func Test_ReportCodec_ValidFromBlockNumFromReport(t *testing.T) { diff --git a/core/services/relay/evm/ocr3_capability_provider.go b/core/services/relay/evm/ocr3_capability_provider.go index f5bfdf46da4..00859befe4c 100644 --- a/core/services/relay/evm/ocr3_capability_provider.go +++ b/core/services/relay/evm/ocr3_capability_provider.go @@ -16,7 +16,7 @@ import ( "github.com/ethereum/go-ethereum/crypto" - ocr3_capability "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/ocr3_capability_1_0_0" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/ocr3_capability" "github.com/smartcontractkit/chainlink/v2/core/services/ocrcommon" ) diff --git a/core/services/relay/evm/read/batch.go b/core/services/relay/evm/read/batch.go index ce1c546ad73..dbe8c8be549 100644 --- a/core/services/relay/evm/read/batch.go +++ b/core/services/relay/evm/read/batch.go @@ -128,7 +128,7 @@ func newDefaultEvmBatchCaller( } // batchCall formats a batch, calls the rpc client, and unpacks results. -// this function only returns errors of type Error which should wrap lower errors. +// this function only returns errors of type ErrRead which should wrap lower errors. func (c *defaultEvmBatchCaller) batchCall(ctx context.Context, blockNumber uint64, batchCall BatchCall) ([]dataAndErr, error) { if len(batchCall) == 0 { return nil, nil @@ -147,9 +147,9 @@ func (c *defaultEvmBatchCaller) batchCall(ctx context.Context, blockNumber uint6 if err = c.evmClient.BatchCallContext(ctx, rpcBatchCalls); err != nil { // return a basic read error with no detail or result since this is a general client // error instead of an error for a specific batch call. - return nil, Error{ - Err: fmt.Errorf("%w: batch call context: %s", types.ErrInternal, err.Error()), - Type: batchReadType, + return nil, ErrRead{ + Err: fmt.Errorf("%w: batch call context: %s", types.ErrInternal, err.Error()), + Batch: true, } } @@ -176,7 +176,7 @@ func (c *defaultEvmBatchCaller) createBatchCalls( fmt.Errorf("%w: encode params: %s", types.ErrInvalidConfig, err.Error()), call, block, - batchReadType, + true, ) } @@ -217,7 +217,7 @@ func (c *defaultEvmBatchCaller) unpackBatchResults( if rpcBatchCalls[idx].Error != nil { results[idx].err = newErrorFromCall( fmt.Errorf("%w: rpc call error: %w", types.ErrInternal, rpcBatchCalls[idx].Error), - call, block, batchReadType, + call, block, true, ) continue @@ -233,7 +233,7 @@ func (c *defaultEvmBatchCaller) unpackBatchResults( if err != nil { callErr := newErrorFromCall( fmt.Errorf("%w: hex decode result: %s", types.ErrInternal, err.Error()), - call, block, batchReadType, + call, block, true, ) callErr.Result = &hexEncodedOutputs[idx] @@ -241,36 +241,32 @@ func (c *defaultEvmBatchCaller) unpackBatchResults( return nil, callErr } - // the codec can't do anything with no bytes, so skip decoding and allow - // the result to be the empty struct or value - if len(packedBytes) > 0 { - if err = c.codec.Decode( - ctx, - packedBytes, - call.ReturnVal, - codec.WrapItemType(call.ContractName, call.ReadName, false), - ); err != nil { - if len(packedBytes) == 0 { - callErr := newErrorFromCall( - fmt.Errorf("%w: %w: %s", types.ErrInternal, errEmptyOutput, err.Error()), - call, block, batchReadType, - ) - - callErr.Result = &hexEncodedOutputs[idx] - - results[idx].err = callErr - } else { - callErr := newErrorFromCall( - fmt.Errorf("%w: codec decode result: %s", types.ErrInvalidType, err.Error()), - call, block, batchReadType, - ) - - callErr.Result = &hexEncodedOutputs[idx] - results[idx].err = callErr - } - - continue + if err = c.codec.Decode( + ctx, + packedBytes, + call.ReturnVal, + codec.WrapItemType(call.ContractName, call.ReadName, false), + ); err != nil { + if len(packedBytes) == 0 { + callErr := newErrorFromCall( + fmt.Errorf("%w: %w: %s", types.ErrInternal, errEmptyOutput, err.Error()), + call, block, true, + ) + + callErr.Result = &hexEncodedOutputs[idx] + + results[idx].err = callErr + } else { + callErr := newErrorFromCall( + fmt.Errorf("%w: codec decode result: %s", types.ErrInvalidType, err.Error()), + call, block, true, + ) + + callErr.Result = &hexEncodedOutputs[idx] + results[idx].err = callErr } + + continue } results[idx].returnVal = call.ReturnVal @@ -294,9 +290,9 @@ func (c *defaultEvmBatchCaller) batchCallDynamicLimitRetries(ctx context.Context } if lim <= 1 { - return nil, Error{ - Err: fmt.Errorf("%w: limited call: call data: %+v", err, calls), - Type: batchReadType, + return nil, ErrRead{ + Err: fmt.Errorf("%w: limited call: call data: %+v", err, calls), + Batch: true, } } diff --git a/core/services/relay/evm/read/errors.go b/core/services/relay/evm/read/errors.go index e767da495e7..bec14d7dd4b 100644 --- a/core/services/relay/evm/read/errors.go +++ b/core/services/relay/evm/read/errors.go @@ -10,17 +10,9 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller" ) -type readType string - -const ( - batchReadType readType = "BatchGetLatestValue" - singleReadType readType = "GetLatestValue" - eventReadType readType = "QueryKey" -) - -type Error struct { +type ErrRead struct { Err error - Type readType + Batch bool Detail *readDetail Result *string } @@ -33,10 +25,10 @@ type readDetail struct { Block string } -func newErrorFromCall(err error, call Call, block string, tp readType) Error { - return Error{ - Err: err, - Type: tp, +func newErrorFromCall(err error, call Call, block string, batch bool) ErrRead { + return ErrRead{ + Err: err, + Batch: batch, Detail: &readDetail{ Address: call.ContractAddress.Hex(), Contract: call.ContractName, @@ -48,12 +40,12 @@ func newErrorFromCall(err error, call Call, block string, tp readType) Error { } } -func (e Error) Error() string { +func (e ErrRead) Error() string { var builder strings.Builder - builder.WriteString("[read error]") + builder.WriteString("[rpc error]") + builder.WriteString(fmt.Sprintf(" batch: %T;", e.Batch)) builder.WriteString(fmt.Sprintf(" err: %s;", e.Err.Error())) - builder.WriteString(fmt.Sprintf(" type: %s;", e.Type)) if e.Detail != nil { builder.WriteString(fmt.Sprintf(" block: %s;", e.Detail.Block)) @@ -71,59 +63,7 @@ func (e Error) Error() string { return builder.String() } -func (e Error) Unwrap() error { - return e.Err -} - -type MultiCallError struct { - Err error - Type readType - Detail *callsReadDetail - Result *string -} - -type callsReadDetail struct { - Calls []Call - Block string -} - -func newErrorFromCalls(err error, calls []Call, block string, tp readType) MultiCallError { - return MultiCallError{ - Err: err, - Type: tp, - Detail: &callsReadDetail{ - Calls: calls, - Block: block, - }, - } -} - -func (e MultiCallError) Error() string { - var builder strings.Builder - - builder.WriteString("[read error]") - builder.WriteString(fmt.Sprintf(" err: %s;", e.Err.Error())) - builder.WriteString(fmt.Sprintf(" type: %s;", e.Type)) - - if e.Detail != nil { - builder.WriteString(fmt.Sprintf(" block: %s;", e.Detail.Block)) - for _, call := range e.Detail.Calls { - builder.WriteString(fmt.Sprintf(" address: %s;", call.ContractAddress.Hex())) - builder.WriteString(fmt.Sprintf(" contract-name: %s;", call.ContractName)) - builder.WriteString(fmt.Sprintf(" read-name: %s;", call.ReadName)) - builder.WriteString(fmt.Sprintf(" params: %+v;", call.Params)) - builder.WriteString(fmt.Sprintf(" expected return type: %s;", reflect.TypeOf(call.ReturnVal))) - } - - if e.Result != nil { - builder.WriteString(fmt.Sprintf("encoded result: %s;", *e.Result)) - } - } - - return builder.String() -} - -func (e MultiCallError) Unwrap() error { +func (e ErrRead) Unwrap() error { return e.Err } diff --git a/core/services/relay/evm/read/event.go b/core/services/relay/evm/read/event.go index d2b54e5bd64..c37b979d7ea 100644 --- a/core/services/relay/evm/read/event.go +++ b/core/services/relay/evm/read/event.go @@ -247,7 +247,7 @@ func (b *EventBinding) GetLatestValueWithHeadData(ctx context.Context, address c ReadName: b.eventName, Params: params, ReturnVal: into, - }, strconv.Itoa(int(confs)), eventReadType) + }, strconv.Itoa(int(confs)), false) callErr.Result = result @@ -315,7 +315,7 @@ func (b *EventBinding) QueryKey(ctx context.Context, address common.Address, fil ContractName: b.contractName, ReadName: b.eventName, ReturnVal: sequenceDataType, - }, "", eventReadType) + }, "", false) } }() diff --git a/core/services/relay/evm/read/method.go b/core/services/relay/evm/read/method.go index ed44e1aa9ca..393077c6d3f 100644 --- a/core/services/relay/evm/read/method.go +++ b/core/services/relay/evm/read/method.go @@ -2,7 +2,6 @@ package read import ( "context" - "errors" "fmt" "math/big" "sync" @@ -23,8 +22,6 @@ import ( evmclient "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" ) -var ErrEmptyContractReturnValue = errors.New("the contract return value was empty") - type MethodBinding struct { // read-only properties contractName string @@ -71,9 +68,8 @@ func (b *MethodBinding) Bind(ctx context.Context, bindings ...common.Address) er // check for contract byte code at the latest block and provided address byteCode, err := b.client.CodeAt(ctx, binding, nil) if err != nil { - return Error{ - Err: fmt.Errorf("%w: code at call failure: %s", commontypes.ErrInternal, err.Error()), - Type: singleReadType, + return ErrRead{ + Err: fmt.Errorf("%w: code at call failure: %s", commontypes.ErrInternal, err.Error()), Detail: &readDetail{ Address: binding.Hex(), Contract: b.contractName, @@ -150,7 +146,7 @@ func (b *MethodBinding) GetLatestValueWithHeadData(ctx context.Context, addr com ReadName: b.method, Params: params, ReturnVal: returnVal, - }, blockNum.String(), singleReadType) + }, blockNum.String(), false) return nil, callErr } @@ -171,17 +167,11 @@ func (b *MethodBinding) GetLatestValueWithHeadData(ctx context.Context, addr com ReadName: b.method, Params: params, ReturnVal: returnVal, - }, blockNum.String(), singleReadType) + }, blockNum.String(), false) return nil, callErr } - // there may be cases where the contract value has not been set and the RPC returns with a value of 0x - // which is a set of empty bytes. there is no need for the codec to run in this case. - if len(bytes) == 0 { - return block.ToChainAgnosticHead(), nil - } - if err = b.codec.Decode(ctx, bytes, returnVal, codec.WrapItemType(b.contractName, b.method, false)); err != nil { callErr := newErrorFromCall( fmt.Errorf("%w: decode return data: %s", commontypes.ErrInvalidType, err.Error()), @@ -191,7 +181,7 @@ func (b *MethodBinding) GetLatestValueWithHeadData(ctx context.Context, addr com ReadName: b.method, Params: params, ReturnVal: returnVal, - }, blockNum.String(), singleReadType) + }, blockNum.String(), false) strResult := hexutil.Encode(bytes) callErr.Result = &strResult diff --git a/core/services/relay/evm/read/multieventtype.go b/core/services/relay/evm/read/multieventtype.go deleted file mode 100644 index 1b561912d18..00000000000 --- a/core/services/relay/evm/read/multieventtype.go +++ /dev/null @@ -1,216 +0,0 @@ -package read - -import ( - "context" - "errors" - "fmt" - "iter" - "reflect" - "sort" - "strconv" - "strings" - - "github.com/ethereum/go-ethereum/common" - - commontypes "github.com/smartcontractkit/chainlink-common/pkg/types" - "github.com/smartcontractkit/chainlink-common/pkg/types/query" - "github.com/smartcontractkit/chainlink-common/pkg/values" - "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller" -) - -type EventQuery struct { - Filter query.KeyFilter - EventBinding *EventBinding - SequenceDataType any - IsValuePtr bool - Address common.Address -} - -func MultiEventTypeQuery(ctx context.Context, lp logpoller.LogPoller, eventQueries []EventQuery, limitAndSort query.LimitAndSort) (iter.Seq2[string, commontypes.Sequence], error) { - seqIter, err := multiEventTypeQueryWithoutErrorWrapping(ctx, lp, eventQueries, limitAndSort) - if err != nil { - if len(eventQueries) > 0 { - var calls []Call - for _, eq := range eventQueries { - calls = append(calls, Call{ - ContractAddress: eq.Address, - ContractName: eq.EventBinding.contractName, - ReadName: eq.EventBinding.eventName, - ReturnVal: eq.SequenceDataType, - }) - } - - err = newErrorFromCalls(err, calls, "", eventReadType) - } else { - err = fmt.Errorf("no event queries provided: %w", err) - } - } - - return seqIter, err -} - -func multiEventTypeQueryWithoutErrorWrapping(ctx context.Context, lp logpoller.LogPoller, eventQueries []EventQuery, limitAndSort query.LimitAndSort) (iter.Seq2[string, commontypes.Sequence], error) { - if err := validateEventQueries(eventQueries); err != nil { - return nil, fmt.Errorf("error validating event queries: %w", err) - } - - for _, eq := range eventQueries { - if err := eq.EventBinding.validateBound(eq.Address); err != nil { - return nil, err - } - } - - allFilterExpressions := make([]query.Expression, 0, len(eventQueries)) - for _, eq := range eventQueries { - var expressions []query.Expression - - defaultExpressions := []query.Expression{ - logpoller.NewAddressFilter(eq.Address), - logpoller.NewEventSigFilter(eq.EventBinding.hash), - } - expressions = append(expressions, defaultExpressions...) - - remapped, remapErr := eq.EventBinding.remap(eq.Filter) - if remapErr != nil { - return nil, fmt.Errorf("error remapping filter: %w", remapErr) - } - expressions = append(expressions, remapped.Expressions...) - - filterExpression := query.And(expressions...) - - allFilterExpressions = append(allFilterExpressions, filterExpression) - } - - eventQuery := query.Or(allFilterExpressions...) - - queryName := createQueryName(eventQueries) - - logs, err := lp.FilteredLogs(ctx, []query.Expression{eventQuery}, limitAndSort, queryName) - if err != nil { - return nil, wrapInternalErr(err) - } - - seqIter, err := decodeMultiEventTypeLogsIntoSequences(ctx, logs, eventQueries) - if err != nil { - return nil, wrapInternalErr(err) - } - - return seqIter, nil -} - -func createQueryName(eventQueries []EventQuery) string { - queryName := "" - contractToEvents := map[string][]string{} - for _, eq := range eventQueries { - contractName := eq.EventBinding.contractName + "-" + eq.Address.String() - - if _, exists := contractToEvents[contractName]; !exists { - contractToEvents[contractName] = []string{} - } - contractToEvents[contractName] = append(contractToEvents[contractName], eq.EventBinding.eventName) - } - - contractNames := make([]string, 0, len(contractToEvents)) - for contractName := range contractToEvents { - contractNames = append(contractNames, contractName) - } - - sort.Strings(contractNames) - - for _, contractName := range contractNames { - queryName += contractName + "-" - for _, event := range contractToEvents[contractName] { - queryName += event + "-" - } - } - - queryName = strings.TrimSuffix(queryName, "-") - return queryName -} - -func validateEventQueries(eventQueries []EventQuery) error { - duplicateCheck := map[common.Hash]EventQuery{} - for _, eq := range eventQueries { - if eq.EventBinding == nil { - return errors.New("event binding is nil") - } - - if eq.SequenceDataType == nil { - return errors.New("sequence data type is nil") - } - - // TODO support queries with the same event signature but different filters - if _, exists := duplicateCheck[eq.EventBinding.hash]; exists { - return fmt.Errorf("duplicate event query for event signature %s, event name %s", eq.EventBinding.hash, eq.EventBinding.eventName) - } - duplicateCheck[eq.EventBinding.hash] = eq - } - return nil -} - -func decodeMultiEventTypeLogsIntoSequences(ctx context.Context, logs []logpoller.Log, eventQueries []EventQuery) (iter.Seq2[string, commontypes.Sequence], error) { - type sequenceWithKey struct { - Key string - Sequence commontypes.Sequence - } - sequenceWithKeys := make([]sequenceWithKey, 0, len(logs)) - eventSigToEventQuery := map[common.Hash]EventQuery{} - for _, eq := range eventQueries { - eventSigToEventQuery[eq.EventBinding.hash] = eq - } - - for _, logEntry := range logs { - eventSignatureHash := logEntry.EventSig - - eq, exists := eventSigToEventQuery[eventSignatureHash] - if !exists { - return nil, fmt.Errorf("no event query found for log with event signature %s", eventSignatureHash) - } - - seqWithKey := sequenceWithKey{ - Key: eq.Filter.Key, - Sequence: commontypes.Sequence{ - Cursor: logpoller.FormatContractReaderCursor(logEntry), - Head: commontypes.Head{ - Height: strconv.FormatInt(logEntry.BlockNumber, 10), - Hash: logEntry.BlockHash.Bytes(), - Timestamp: uint64(logEntry.BlockTimestamp.Unix()), //nolint:gosec // G115 false positive - }, - }, - } - - var typeVal reflect.Value - - typeInto := reflect.TypeOf(eq.SequenceDataType) - if typeInto.Kind() == reflect.Pointer { - typeVal = reflect.New(typeInto.Elem()) - } else { - typeVal = reflect.Indirect(reflect.New(typeInto)) - } - - // create a new value of the same type as 'into' for the data to be extracted to - seqWithKey.Sequence.Data = typeVal.Interface() - - if err := eq.EventBinding.decodeLog(ctx, &logEntry, seqWithKey.Sequence.Data); err != nil { - return nil, err - } - - if eq.IsValuePtr { - wrappedValue, err := values.Wrap(seqWithKey.Sequence.Data) - if err != nil { - return nil, err - } - seqWithKey.Sequence.Data = &wrappedValue - } - - sequenceWithKeys = append(sequenceWithKeys, seqWithKey) - } - - return func(yield func(string, commontypes.Sequence) bool) { - for _, s := range sequenceWithKeys { - if !yield(s.Key, s.Sequence) { - return - } - } - }, nil -} diff --git a/core/services/relay/evm/read/multieventtype_test.go b/core/services/relay/evm/read/multieventtype_test.go deleted file mode 100644 index 8fb39ecc526..00000000000 --- a/core/services/relay/evm/read/multieventtype_test.go +++ /dev/null @@ -1,119 +0,0 @@ -package read - -import ( - "github.com/ethereum/go-ethereum/common" - - "testing" - - "github.com/stretchr/testify/assert" - - "github.com/smartcontractkit/chainlink-common/pkg/types/query" -) - -func TestCreateQueryName(t *testing.T) { - eventQueries := []EventQuery{ - { - Filter: query.KeyFilter{Key: "key1"}, - EventBinding: &EventBinding{ - contractName: "ContractA", - eventName: "EventA", - hash: common.HexToHash("0x1"), - }, - SequenceDataType: "dataType1", - Address: common.HexToAddress("0x123"), - }, - { - Filter: query.KeyFilter{Key: "key2"}, - EventBinding: &EventBinding{ - contractName: "ContractB", - eventName: "EventB", - hash: common.HexToHash("0x2"), - }, - SequenceDataType: "dataType2", - Address: common.HexToAddress("0x456"), - }, - { - Filter: query.KeyFilter{Key: "key1"}, - EventBinding: &EventBinding{ - contractName: "ContractA", - eventName: "EventA1", - hash: common.HexToHash("0x1"), - }, - SequenceDataType: "dataType1", - Address: common.HexToAddress("0x123"), - }, - } - - expectedQueryName := "ContractA-0x0000000000000000000000000000000000000123-EventA-EventA1-ContractB-0x0000000000000000000000000000000000000456-EventB" - queryName := createQueryName(eventQueries) - - assert.Equal(t, expectedQueryName, queryName) -} - -func TestValidateEventQueries(t *testing.T) { - tests := []struct { - name string - eventQueries []EventQuery - expectedError string - }{ - { - name: "valid event queries", - eventQueries: []EventQuery{ - { - EventBinding: &EventBinding{hash: common.HexToHash("0x1")}, - SequenceDataType: "dataType1", - }, - { - EventBinding: &EventBinding{hash: common.HexToHash("0x2")}, - SequenceDataType: "dataType2", - }, - }, - expectedError: "", - }, - { - name: "nil event binding", - eventQueries: []EventQuery{ - { - EventBinding: nil, - SequenceDataType: "dataType1", - }, - }, - expectedError: "event binding is nil", - }, - { - name: "nil sequence data type", - eventQueries: []EventQuery{ - { - EventBinding: &EventBinding{hash: common.HexToHash("0x1")}, - SequenceDataType: nil, - }, - }, - expectedError: "sequence data type is nil", - }, - { - name: "duplicate event query", - eventQueries: []EventQuery{ - { - EventBinding: &EventBinding{hash: common.HexToHash("0x1")}, - SequenceDataType: "dataType1", - }, - { - EventBinding: &EventBinding{hash: common.HexToHash("0x1")}, - SequenceDataType: "dataType2", - }, - }, - expectedError: "duplicate event query for event signature 0x0000000000000000000000000000000000000000000000000000000000000001, event name ", - }, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - err := validateEventQueries(tt.eventQueries) - if tt.expectedError == "" { - assert.NoError(t, err) - } else { - assert.EqualError(t, err, tt.expectedError) - } - }) - } -} diff --git a/core/services/relay/evm/statuschecker/txm_status_checker_test.go b/core/services/relay/evm/statuschecker/txm_status_checker_test.go index 7a682d708e2..456d07e7a7d 100644 --- a/core/services/relay/evm/statuschecker/txm_status_checker_test.go +++ b/core/services/relay/evm/statuschecker/txm_status_checker_test.go @@ -10,13 +10,12 @@ import ( "github.com/stretchr/testify/mock" "github.com/smartcontractkit/chainlink-common/pkg/types" - "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" - "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr/mocks" + "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" ) func Test_CheckMessageStatus(t *testing.T) { - tests.SkipShort(t, "") + testutils.SkipShort(t, "") ctx := context.Background() mockTxManager := mocks.NewMockEvmTxManager(t) checker := NewTxmStatusChecker(mockTxManager.GetTransactionStatus) diff --git a/core/services/relay/evm/write_target.go b/core/services/relay/evm/write_target.go index f14c13e5daa..cd30e8ab3c3 100644 --- a/core/services/relay/evm/write_target.go +++ b/core/services/relay/evm/write_target.go @@ -11,7 +11,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/capabilities/targets" "github.com/smartcontractkit/chainlink/v2/core/chains/legacyevm" - forwarder "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/forwarder_1_0_0" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/forwarder" relayevmtypes "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/types" ) @@ -68,7 +68,7 @@ func NewWriteTarget(ctx context.Context, relayer *Relayer, chain legacyevm.Chain return nil, fmt.Errorf("failed to marshal chainwriter config: %w", err) } - cw, err := relayer.NewContractWriter(ctx, encodedWriterConfig) + cw, err := relayer.NewChainWriter(ctx, encodedWriterConfig) if err != nil { return nil, err } diff --git a/core/services/relay/evm/write_target_test.go b/core/services/relay/evm/write_target_test.go index c82c9ba81b9..24d7dd8646e 100644 --- a/core/services/relay/evm/write_target_test.go +++ b/core/services/relay/evm/write_target_test.go @@ -27,7 +27,7 @@ import ( txmmocks "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr/mocks" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" evmmocks "github.com/smartcontractkit/chainlink/v2/core/chains/legacyevm/mocks" - forwarder "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/forwarder_1_0_0" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/forwarder" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest" diff --git a/core/services/relay/relay.go b/core/services/relay/relay.go index 0b1293c8d79..913923a9b2f 100644 --- a/core/services/relay/relay.go +++ b/core/services/relay/relay.go @@ -37,7 +37,7 @@ type ServerAdapter struct { } // NewServerAdapter returns a new ServerAdapter. -func NewServerAdapter(r types.Relayer) *ServerAdapter { +func NewServerAdapter(r types.Relayer) *ServerAdapter { //nolint:staticcheck return &ServerAdapter{Relayer: r} } diff --git a/core/services/transmission/integration_test.go b/core/services/transmission/integration_test.go new file mode 100644 index 00000000000..6e38687313c --- /dev/null +++ b/core/services/transmission/integration_test.go @@ -0,0 +1,495 @@ +package transmission_test + +import ( + "math/big" + "testing" + + "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "github.com/stretchr/testify/require" + + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/link_token_interface" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/mock_v3_aggregator_contract" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/solidity_vrf_consumer_interface_v08" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/vrf_coordinator_mock" + + "github.com/ethereum/go-ethereum/core/types" + + evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/transmission/generated/entry_point" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/transmission/generated/greeter_wrapper" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/transmission/generated/paymaster_wrapper" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/transmission/generated/sca_wrapper" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/transmission/generated/smart_contract_account_factory" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/transmission/generated/smart_contract_account_helper" + "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" + "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" + "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/ethkey" + "github.com/smartcontractkit/chainlink/v2/core/services/transmission" +) + +var ( + greeterABI = evmtypes.MustGetABI(greeter_wrapper.GreeterABI) + consumerABI = evmtypes.MustGetABI(solidity_vrf_consumer_interface_v08.VRFConsumerABI) + entrypointABI = evmtypes.MustGetABI(entry_point.EntryPointABI) +) + +type EntryPointUniverse struct { + holder1 *bind.TransactOpts + holder1Key ethkey.KeyV2 + holder2 *bind.TransactOpts + backend evmtypes.Backend + entryPointAddress common.Address + entryPoint *entry_point.EntryPoint + factoryAddress common.Address + helper *smart_contract_account_helper.SmartContractAccountHelper + greeterAddress common.Address + greeter *greeter_wrapper.Greeter + linkTokenAddress common.Address + linkToken *link_token_interface.LinkToken + linkEthFeedAddress common.Address + vrfCoordinatorAddress common.Address + vrfCoordinator *vrf_coordinator_mock.VRFCoordinatorMock + vrfConsumerAddress common.Address +} + +func deployTransmissionUniverse(t *testing.T) *EntryPointUniverse { + // Create a key for holder1 that we can use to sign + holder1Key := cltest.MustGenerateRandomKey(t) + t.Log("Holder key:", holder1Key.String()) + + // Construct simulated blockchain environment. + holder1Transactor, err := bind.NewKeyedTransactorWithChainID(holder1Key.ToEcdsaPrivKey(), testutils.SimulatedChainID) + require.NoError(t, err) + var ( + holder1 = holder1Transactor + holder2 = testutils.MustNewSimTransactor(t) + ) + genesisData := types.GenesisAlloc{ + holder1.From: {Balance: assets.Ether(1000).ToInt()}, + holder2.From: {Balance: assets.Ether(1000).ToInt()}, + } + backend := cltest.NewSimulatedBackend(t, genesisData, 30e6) + backend.Commit() + + // Setup all contracts and addresses used by tests. + entryPointAddress, _, entryPoint, err := entry_point.DeployEntryPoint(holder1, backend.Client()) + require.NoError(t, err) + factoryAddress, _, _, _ := smart_contract_account_factory.DeploySmartContractAccountFactory(holder1, backend.Client()) + require.NoError(t, err) + _, _, helper, err := smart_contract_account_helper.DeploySmartContractAccountHelper(holder1, backend.Client()) + require.NoError(t, err) + greeterAddress, _, greeter, err := greeter_wrapper.DeployGreeter(holder1, backend.Client()) + require.NoError(t, err) + linkTokenAddress, _, linkToken, err := link_token_interface.DeployLinkToken(holder1, backend.Client()) + require.NoError(t, err) + linkEthFeedAddress, _, _, err := mock_v3_aggregator_contract.DeployMockV3AggregatorContract( + holder1, + backend.Client(), + 18, + (*big.Int)(assets.GWei(5000000)), // .005 ETH + ) + require.NoError(t, err) + vrfCoordinatorAddress, _, vrfCoordinator, err := vrf_coordinator_mock.DeployVRFCoordinatorMock(holder1, backend.Client(), linkTokenAddress) + require.NoError(t, err) + vrfConsumerAddress, _, _, err := solidity_vrf_consumer_interface_v08.DeployVRFConsumer(holder1, backend.Client(), vrfCoordinatorAddress, linkTokenAddress) + require.NoError(t, err) + backend.Commit() + + return &EntryPointUniverse{ + holder1: holder1, + holder1Key: holder1Key, + holder2: holder2, + backend: backend, + entryPointAddress: entryPointAddress, + entryPoint: entryPoint, + factoryAddress: factoryAddress, + helper: helper, + greeterAddress: greeterAddress, + greeter: greeter, + linkTokenAddress: linkTokenAddress, + linkToken: linkToken, + linkEthFeedAddress: linkEthFeedAddress, + vrfCoordinatorAddress: vrfCoordinatorAddress, + vrfCoordinator: vrfCoordinator, + vrfConsumerAddress: vrfConsumerAddress, + } +} + +func Test4337Basic(t *testing.T) { + // Deploy universe. + universe := deployTransmissionUniverse(t) + holder1 := universe.holder1 + holder2 := universe.holder2 + backend := universe.backend + + // Ensure no greeting is already set. + initialGreeting, err := universe.greeter.GetGreeting(nil) + require.NoError(t, err) + require.Equal(t, "", initialGreeting) + + // Get the address at which the Smart Contract Account will be deployed. + toDeployAddress, err := universe.helper.CalculateSmartContractAccountAddress( + nil, + holder1.From, + universe.entryPointAddress, + universe.factoryAddress, + ) + require.NoError(t, err) + t.Log("Smart Contract Account Address:", toDeployAddress) + + // Get the initialization code for the Smart Contract Account. + fullInitializeCode, err := universe.helper.GetInitCode(nil, universe.factoryAddress, holder1.From, universe.entryPointAddress) + require.NoError(t, err) + t.Log("Full initialization code:", common.Bytes2Hex(fullInitializeCode)) + + // Construct calldata for setGreeting. + encodedGreetingCall, err := greeterABI.Pack("setGreeting", "bye") + require.NoError(t, err) + t.Log("Encoded greeting call:", common.Bytes2Hex(encodedGreetingCall)) + + // Construct the calldata to be passed in the user operation. + var ( + value = big.NewInt(0) + nonce = big.NewInt(0) + deadline = big.NewInt(1000) + ) + fullEncoding, err := universe.helper.GetFullEndTxEncoding(nil, universe.greeterAddress, value, deadline, encodedGreetingCall) + require.NoError(t, err) + t.Log("Full user operation calldata:", common.Bytes2Hex(fullEncoding)) + + // Construct and execute user operation. + userOp := entry_point.UserOperation{ + Sender: toDeployAddress, + Nonce: nonce, + InitCode: fullInitializeCode, + CallData: fullEncoding, + CallGasLimit: big.NewInt(10_000_000), + VerificationGasLimit: big.NewInt(10_000_000), + PreVerificationGas: big.NewInt(10_000_000), + MaxFeePerGas: big.NewInt(100), + MaxPriorityFeePerGas: big.NewInt(200), + PaymasterAndData: []byte(""), + Signature: []byte(""), + } + + // Generate hash from user operation, sign it, and include it in the user operation. + userOpHash, err := universe.entryPoint.GetUserOpHash(nil, userOp) + require.NoError(t, err) + fullHash, err := universe.helper.GetFullHashForSigning(nil, userOpHash, toDeployAddress) + require.NoError(t, err) + t.Log("Full hash for signing:", common.Bytes2Hex(fullHash[:])) + sig, err := transmission.SignMessage(universe.holder1Key.ToEcdsaPrivKey(), fullHash[:]) + require.NoError(t, err) + t.Log("Signature:", common.Bytes2Hex(sig)) + userOp.Signature = sig + + // Deposit to the SCA's account to pay for this transaction. + holder1.Value = assets.Ether(10).ToInt() + tx, err := universe.entryPoint.DepositTo(holder1, toDeployAddress) + require.NoError(t, err) + backend.Commit() + _, err = bind.WaitMined(testutils.Context(t), backend.Client(), tx) + require.NoError(t, err) + holder1.Value = assets.Ether(0).ToInt() + balance, err := universe.entryPoint.BalanceOf(nil, toDeployAddress) + require.NoError(t, err) + require.Equal(t, assets.Ether(10).ToInt(), balance) + + // Run handleOps from holder2's account, to demonstrate that any account can execute this signed user operation. + tx, err = universe.entryPoint.HandleOps(holder2, []entry_point.UserOperation{userOp}, holder1.From) + require.NoError(t, err) + backend.Commit() + _, err = bind.WaitMined(testutils.Context(t), backend.Client(), tx) + require.NoError(t, err) + + // Ensure "bye" was successfully set as the greeting. + greetingResult, err := universe.greeter.GetGreeting(nil) + require.NoError(t, err) + require.Equal(t, "bye", greetingResult) + + // Assert smart contract account is created and nonce incremented. + sca, err := sca_wrapper.NewSCA(toDeployAddress, backend.Client()) + require.NoError(t, err) + onChainNonce, err := sca.SNonce(nil) + require.NoError(t, err) + require.Equal(t, big.NewInt(1), onChainNonce) +} + +func Test4337WithLinkTokenPaymaster(t *testing.T) { + // Deploy universe. + universe := deployTransmissionUniverse(t) + holder1 := universe.holder1 + holder2 := universe.holder2 + backend := universe.backend + + // Ensure no greeting is already set. + initialGreeting, err := universe.greeter.GetGreeting(nil) + require.NoError(t, err) + require.Equal(t, "", initialGreeting) + + // Get the address at which the Smart Contract Account will be deployed. + toDeployAddress, err := universe.helper.CalculateSmartContractAccountAddress( + nil, + holder1.From, + universe.entryPointAddress, + universe.factoryAddress, + ) + require.NoError(t, err) + t.Log("Smart Contract Account Address:", toDeployAddress) + + // Get the initialization code for the Smart Contract Account. + fullInitializeCode, err := universe.helper.GetInitCode(nil, universe.factoryAddress, holder1.From, universe.entryPointAddress) + require.NoError(t, err) + t.Log("Full initialization code:", common.Bytes2Hex(fullInitializeCode)) + + // Construct calldata for setGreeting. + encodedGreetingCall, err := greeterABI.Pack("setGreeting", "bye") + require.NoError(t, err) + t.Log("Encoded greeting call:", common.Bytes2Hex(encodedGreetingCall)) + + // Construct the calldata to be passed in the user operation. + var ( + value = big.NewInt(0) + nonce = big.NewInt(0) + deadline = big.NewInt(1000) + ) + fullEncoding, err := universe.helper.GetFullEndTxEncoding(nil, universe.greeterAddress, value, deadline, encodedGreetingCall) + require.NoError(t, err) + t.Log("Full user operation calldata:", common.Bytes2Hex(fullEncoding)) + + // Deposit to LINK paymaster. + linkTokenAddress, _, linkToken, err := link_token_interface.DeployLinkToken(holder1, backend.Client()) + require.NoError(t, err) + linkEthFeedAddress, _, _, err := mock_v3_aggregator_contract.DeployMockV3AggregatorContract( + holder1, + backend.Client(), + 18, + (*big.Int)(assets.GWei(5000000)), // .005 ETH + ) + require.NoError(t, err) + paymasterAddress, _, _, err := paymaster_wrapper.DeployPaymaster(holder1, backend.Client(), linkTokenAddress, linkEthFeedAddress, universe.entryPointAddress) + require.NoError(t, err) + backend.Commit() + tx, err := linkToken.TransferAndCall( + holder1, + paymasterAddress, + assets.Ether(1000).ToInt(), + common.LeftPadBytes(toDeployAddress.Bytes(), 32), + ) + require.NoError(t, err) + backend.Commit() + _, err = bind.WaitMined(testutils.Context(t), backend.Client(), tx) + require.NoError(t, err) + + // Construct and execute user operation. + userOp := entry_point.UserOperation{ + Sender: toDeployAddress, + Nonce: nonce, + InitCode: fullInitializeCode, + CallData: fullEncoding, + CallGasLimit: big.NewInt(10_000_000), + VerificationGasLimit: big.NewInt(10_000_000), + PreVerificationGas: big.NewInt(10_000_000), + MaxFeePerGas: big.NewInt(100), + MaxPriorityFeePerGas: big.NewInt(200), + PaymasterAndData: paymasterAddress.Bytes(), + Signature: []byte(""), + } + + // Generate hash from user operation, sign it, and include it in the user operation. + userOpHash, err := universe.entryPoint.GetUserOpHash(nil, userOp) + require.NoError(t, err) + fullHash, err := universe.helper.GetFullHashForSigning(nil, userOpHash, toDeployAddress) + require.NoError(t, err) + t.Log("Full hash for signing:", common.Bytes2Hex(fullHash[:])) + sig, err := transmission.SignMessage(universe.holder1Key.ToEcdsaPrivKey(), fullHash[:]) + require.NoError(t, err) + t.Log("Signature:", common.Bytes2Hex(sig)) + userOp.Signature = sig + + // Deposit to the Paymaster's account to pay for this transaction. + holder1.Value = assets.Ether(10).ToInt() + tx, err = universe.entryPoint.DepositTo(holder1, paymasterAddress) + require.NoError(t, err) + backend.Commit() + _, err = bind.WaitMined(testutils.Context(t), backend.Client(), tx) + require.NoError(t, err) + holder1.Value = assets.Ether(0).ToInt() + balance, err := universe.entryPoint.BalanceOf(nil, paymasterAddress) + require.NoError(t, err) + require.Equal(t, assets.Ether(10).ToInt(), balance) + + // Run handleOps from holder2's account, to demonstrate that any account can execute this signed user operation. + tx, err = universe.entryPoint.HandleOps(holder2, []entry_point.UserOperation{userOp}, holder1.From) + require.NoError(t, err) + backend.Commit() + _, err = bind.WaitMined(testutils.Context(t), backend.Client(), tx) + require.NoError(t, err) + + // Ensure "bye" was successfully set as the greeting. + greetingResult, err := universe.greeter.GetGreeting(nil) + require.NoError(t, err) + require.Equal(t, "bye", greetingResult) + + // Assert smart contract account is created and nonce incremented. + sca, err := sca_wrapper.NewSCA(toDeployAddress, backend.Client()) + require.NoError(t, err) + onChainNonce, err := sca.SNonce(nil) + require.NoError(t, err) + require.Equal(t, big.NewInt(1), onChainNonce) +} + +func Test4337WithLinkTokenVRFRequestAndPaymaster(t *testing.T) { + // Deploy universe. + universe := deployTransmissionUniverse(t) + holder1 := universe.holder1 + holder2 := universe.holder2 + backend := universe.backend + + // Get the address at which the Smart Contract Account will be deployed. + toDeployAddress, err := universe.helper.CalculateSmartContractAccountAddress( + nil, + holder1.From, + universe.entryPointAddress, + universe.factoryAddress, + ) + require.NoError(t, err) + t.Log("Smart Contract Account Address:", toDeployAddress) + + // Get the initialization code for the Smart Contract Account. + fullInitializeCode, err := universe.helper.GetInitCode(nil, universe.factoryAddress, holder1.From, universe.entryPointAddress) + require.NoError(t, err) + t.Log("Full initialization code:", common.Bytes2Hex(fullInitializeCode)) + + // Construct calldata for the vrf request. + var keyhash [32]byte + copy(keyhash[:], common.LeftPadBytes(big.NewInt(123).Bytes(), 32)) + var fee = assets.Ether(1).ToInt() + encodedVRFRequest, err := consumerABI.Pack("doRequestRandomness", keyhash, fee) + require.NoError(t, err) + t.Log("Encoded vrf request:", common.Bytes2Hex(encodedVRFRequest)) + + // Construct the calldata to be passed in the user operation. + var ( + value = big.NewInt(0) + nonce = big.NewInt(0) + deadline = big.NewInt(1000) + ) + fullEncoding, err := universe.helper.GetFullEndTxEncoding(nil, universe.vrfConsumerAddress, value, deadline, encodedVRFRequest) + require.NoError(t, err) + t.Log("Full user operation calldata:", common.Bytes2Hex(fullEncoding)) + + // Deposit to LINK paymaster. + paymasterAddress, _, _, err := paymaster_wrapper.DeployPaymaster(holder1, backend.Client(), universe.linkTokenAddress, universe.linkEthFeedAddress, universe.entryPointAddress) + require.NoError(t, err) + backend.Commit() + tx, err := universe.linkToken.TransferAndCall( + holder1, + paymasterAddress, + assets.Ether(1000).ToInt(), + common.LeftPadBytes(toDeployAddress.Bytes(), 32), + ) + require.NoError(t, err) + backend.Commit() + + ctx := testutils.Context(t) + _, err = bind.WaitMined(ctx, backend.Client(), tx) + require.NoError(t, err) + + // Generate encoded paymaster data to fund the VRF consumer. + encodedPaymasterData, err := universe.helper.GetAbiEncodedDirectRequestData(nil, universe.vrfConsumerAddress, fee, fee) + require.NoError(t, err) + + // Construct and execute user operation. + userOp := entry_point.UserOperation{ + Sender: toDeployAddress, + Nonce: nonce, + InitCode: fullInitializeCode, + CallData: fullEncoding, + CallGasLimit: big.NewInt(10_000_000), + VerificationGasLimit: big.NewInt(10_000_000), + PreVerificationGas: big.NewInt(10_000_000), + MaxFeePerGas: big.NewInt(100), + MaxPriorityFeePerGas: big.NewInt(200), + PaymasterAndData: append(append(paymasterAddress.Bytes(), byte(0)), encodedPaymasterData...), + Signature: []byte(""), + } + + // Generate hash from user operation, sign it, and include it in the user operation. + userOpHash, err := universe.entryPoint.GetUserOpHash(nil, userOp) + require.NoError(t, err) + fullHash, err := universe.helper.GetFullHashForSigning(nil, userOpHash, toDeployAddress) + require.NoError(t, err) + t.Log("Full hash for signing:", common.Bytes2Hex(fullHash[:])) + sig, err := transmission.SignMessage(universe.holder1Key.ToEcdsaPrivKey(), fullHash[:]) + require.NoError(t, err) + t.Log("Signature:", common.Bytes2Hex(sig)) + userOp.Signature = sig + + // Deposit to the Paymaster's account to pay for this transaction. + holder1.Value = assets.Ether(10).ToInt() + tx, err = universe.entryPoint.DepositTo(holder1, paymasterAddress) + require.NoError(t, err) + backend.Commit() + _, err = bind.WaitMined(ctx, backend.Client(), tx) + require.NoError(t, err) + holder1.Value = assets.Ether(0).ToInt() + balance, err := universe.entryPoint.BalanceOf(nil, paymasterAddress) + require.NoError(t, err) + require.Equal(t, assets.Ether(10).ToInt(), balance) + + // Run handleOps from holder2's account, to demonstrate that any account can execute this signed user operation. + // Manually execute transaction to test ABI packing. + gasPrice, err := backend.Client().SuggestGasPrice(ctx) + require.NoError(t, err) + accountNonce, err := backend.Client().PendingNonceAt(ctx, holder2.From) + require.NoError(t, err) + payload, err := entrypointABI.Pack("handleOps", []entry_point.UserOperation{userOp}, holder1.From) + require.NoError(t, err) + gas, err := backend.Client().EstimateGas(ctx, ethereum.CallMsg{ + From: holder2.From, + To: &universe.entryPointAddress, + Gas: 0, + Data: payload, + GasPrice: gasPrice, + }) + unsigned := types.NewTx(&types.LegacyTx{ + Nonce: accountNonce, + Gas: gas, + To: &universe.entryPointAddress, + Value: big.NewInt(0), + Data: payload, + GasPrice: gasPrice, + }) + require.NoError(t, err) + signedtx, err := holder2.Signer(holder2.From, unsigned) + require.NoError(t, err) + err = backend.Client().SendTransaction(ctx, signedtx) + require.NoError(t, err) + backend.Commit() + receipt, err := bind.WaitMined(ctx, backend.Client(), signedtx) + require.NoError(t, err) + t.Log("Receipt:", receipt.Status) + + // Assert the VRF request was correctly made. + logs, err := backend.Client().FilterLogs(ctx, ethereum.FilterQuery{ + Addresses: []common.Address{universe.vrfCoordinatorAddress}, + }) + require.NoError(t, err) + require.Equal(t, 1, len(logs)) + randomnessRequestLog, err := universe.vrfCoordinator.ParseRandomnessRequest(logs[0]) + require.NoError(t, err) + require.Equal(t, fee, randomnessRequestLog.Fee) + require.Equal(t, keyhash, randomnessRequestLog.KeyHash) + require.Equal(t, universe.vrfConsumerAddress, randomnessRequestLog.Sender) + + // Assert smart contract account is created and nonce incremented. + sca, err := sca_wrapper.NewSCA(toDeployAddress, backend.Client()) + require.NoError(t, err) + onChainNonce, err := sca.SNonce(nil) + require.NoError(t, err) + require.Equal(t, big.NewInt(1), onChainNonce) +} diff --git a/core/services/transmission/signature.go b/core/services/transmission/signature.go new file mode 100644 index 00000000000..50b7bc584dc --- /dev/null +++ b/core/services/transmission/signature.go @@ -0,0 +1,19 @@ +package transmission + +import ( + "crypto/ecdsa" + + "github.com/ethereum/go-ethereum/crypto" +) + +func SignMessage( + ownerPrivateKey *ecdsa.PrivateKey, + message []byte, +) ([]byte, error) { + sig, err := crypto.Sign(message, ownerPrivateKey) + if err != nil { + return nil, err + } + + return sig, nil +} diff --git a/core/services/vrf/solidity_cross_tests/vrf_v08_solidity_crosscheck_test.go b/core/services/vrf/solidity_cross_tests/vrf_v08_solidity_crosscheck_test.go index 8b88ad73ea9..98ca510a9ca 100644 --- a/core/services/vrf/solidity_cross_tests/vrf_v08_solidity_crosscheck_test.go +++ b/core/services/vrf/solidity_cross_tests/vrf_v08_solidity_crosscheck_test.go @@ -139,6 +139,23 @@ func TestVRFV08_CompareFieldHash(t *testing.T) { } } +// randomKey deterministically generates a secp256k1 key. +// +// Never use this if cryptographic security is required +//func randomKey(t *testing.T, r *mrand.Rand) *ecdsa.PrivateKey { +// secretKey := vrfkey.FieldSize +// for secretKey.Cmp(vrfkey.FieldSize) >= 0 { // Keep picking until secretKey < fieldSize +// secretKey = randomUint256(t, r) +// } +// cKey := crypto.ToECDSAUnsafe(secretKey.Bytes()) +// return cKey +//} +// +// pair returns the inputs as a length-2 big.Int array. Useful for translating +// coordinates to the uint256[2]'s VRF.sol uses to represent secp256k1 points. +//func pair(x, y *big.Int) [2]*big.Int { return [2]*big.Int{x, y} } +//func asPair(p kyber.Point) [2]*big.Int { return pair(secp256k1.Coordinates(p)) } + func TestVRFV08_CompareHashToCurve(t *testing.T) { t.Parallel() r := mrand.New(mrand.NewSource(4)) @@ -156,6 +173,40 @@ func TestVRFV08_CompareHashToCurve(t *testing.T) { } } +// randomPoint deterministically simulates a uniform sample of secp256k1 points, +// given r's seed +// +// Never use this if cryptographic security is required +//func randomPoint(t *testing.T, r *mrand.Rand) kyber.Point { +// p, err := vrfkey.HashToCurve(vrfkey.Generator, randomUint256(t, r), func(*big.Int) {}) +// require.NoError(t, err, +// "failed to hash random value to secp256k1 while generating random point") +// if r.Int63n(2) == 1 { // Uniform sample of ±p +// p.Neg(p) +// } +// return p +//} +// +//// randomPointWithPair returns a random secp256k1, both as a kyber.Point and as +//// a pair of *big.Int's. Useful for translating between the types needed by the +//// golang contract wrappers. +//func randomPointWithPair(t *testing.T, r *mrand.Rand) (kyber.Point, [2]*big.Int) { +// p := randomPoint(t, r) +// return p, asPair(p) +//} + +// randomScalar deterministically simulates a uniform sample of secp256k1 +// scalars, given r's seed +// +// Never use this if cryptographic security is required +//func randomScalar(t *testing.T, r *mrand.Rand) kyber.Scalar { +// s := randomUint256(t, r) +// for s.Cmp(secp256k1.GroupOrder) >= 0 { +// s = randomUint256(t, r) +// } +// return secp256k1.IntToScalar(s) +//} + func TestVRFV08_CheckSolidityPointAddition(t *testing.T) { t.Parallel() r := mrand.New(mrand.NewSource(5)) diff --git a/core/services/vrf/v2/integration_helpers_test.go b/core/services/vrf/v2/integration_helpers_test.go index 1a46fc1e334..48e1ffdd69c 100644 --- a/core/services/vrf/v2/integration_helpers_test.go +++ b/core/services/vrf/v2/integration_helpers_test.go @@ -445,13 +445,13 @@ func testMultipleConsumersNeedTrustedBHS( topUpSubscription(t, consumer, consumerContract, uni.backend, big.NewInt(5e18 /* 5 LINK */), nativePayment) // Wait for fulfillment to be queued. - require.Eventually(t, func() bool { + gomega.NewGomegaWithT(t).Eventually(func() bool { uni.backend.Commit() runs, err := app.PipelineORM().GetAllRuns(ctx) require.NoError(t, err) t.Log("runs", len(runs)) - return len(runs) >= 1 - }, testutils.WaitTimeout(t), time.Second) + return len(runs) == 1 + }, testutils.WaitTimeout(t), time.Second).Should(gomega.BeTrue()) mine(t, requestID, subID, uni.backend, db, vrfVersion, testutils.SimulatedChainID) @@ -1020,7 +1020,7 @@ func testSingleConsumerForcedFulfillment( uni.backend.Commit() // Wait for force-fulfillment to be queued. - require.Eventually(t, func() bool { + gomega.NewGomegaWithT(t).Eventually(func() bool { uni.backend.Commit() commitment, err2 := uni.oldRootContract.GetCommitment(nil, requestID) require.NoError(t, err2) @@ -1036,7 +1036,7 @@ func testSingleConsumerForcedFulfillment( } t.Log("num RandomWordsForced logs:", i) return utils.IsEmpty(commitment[:]) - }, testutils.WaitTimeout(t), time.Second) + }, testutils.WaitTimeout(t), time.Second).Should(gomega.BeTrue()) // Mine the fulfillment that was queued. mine(t, requestID, subID, uni.backend, db, vrfVersion, testutils.SimulatedChainID) diff --git a/core/services/vrf/v2/integration_v2_plus_test.go b/core/services/vrf/v2/integration_v2_plus_test.go index d1cc030043d..151bbced6dd 100644 --- a/core/services/vrf/v2/integration_v2_plus_test.go +++ b/core/services/vrf/v2/integration_v2_plus_test.go @@ -13,11 +13,11 @@ import ( "github.com/ethereum/go-ethereum/common/hexutil" gethtypes "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/eth/ethconfig" + "github.com/onsi/gomega" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" commonconfig "github.com/smartcontractkit/chainlink-common/pkg/config" - "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/toml" @@ -67,7 +67,7 @@ type coordinatorV2PlusUniverse struct { } func newVRFCoordinatorV2PlusUniverse(t *testing.T, key ethkey.KeyV2, numConsumers int, trusting bool) coordinatorV2PlusUniverse { - tests.SkipShort(t, "VRFCoordinatorV2Universe") + testutils.SkipShort(t, "VRFCoordinatorV2Universe") oracleTransactor, err := bind.NewKeyedTransactorWithChainID(key.ToEcdsaPrivKey(), testutils.SimulatedChainID) require.NoError(t, err) var ( @@ -1216,13 +1216,13 @@ func TestVRFV2PlusIntegration_Migration(t *testing.T) { requestID, _ := requestRandomnessAndAssertRandomWordsRequestedEvent(t, consumerContract, consumer, keyHash, subID, numWords, 500_000, uni.rootContract, uni.backend, false) // Wait for fulfillment to be queued. - require.Eventually(t, func() bool { + gomega.NewGomegaWithT(t).Eventually(func() bool { uni.backend.Commit() runs, err := app.PipelineORM().GetAllRuns(ctx) require.NoError(t, err) t.Log("runs", len(runs)) return len(runs) == 1 - }, testutils.WaitTimeout(t), time.Second) + }, testutils.WaitTimeout(t), time.Second).Should(gomega.BeTrue()) mine(t, requestID, subID, uni.backend, db, vrfcommon.V2Plus, testutils.SimulatedChainID) assertRandomWordsFulfilled(t, requestID, true, uni.rootContract, false) diff --git a/core/services/vrf/v2/integration_v2_reverted_txns_test.go b/core/services/vrf/v2/integration_v2_reverted_txns_test.go index 67716d440e3..af4a135ccd3 100644 --- a/core/services/vrf/v2/integration_v2_reverted_txns_test.go +++ b/core/services/vrf/v2/integration_v2_reverted_txns_test.go @@ -11,6 +11,7 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" "github.com/google/uuid" + "github.com/onsi/gomega" "github.com/pkg/errors" "github.com/stretchr/testify/require" @@ -198,14 +199,14 @@ func waitForForceFulfillment(t *testing.T, requestID := req.requestID // Wait for force-fulfillment to be queued. - require.Eventually(t, func() bool { + gomega.NewGomegaWithT(t).Eventually(func() bool { uni.backend.Commit() commitment, err := coordinator.GetCommitment(nil, requestID) require.NoError(t, err) t.Log("commitment is:", hexutil.Encode(commitment[:]), ", requestID: ", common.BigToHash(requestID).Hex()) checkForForceFulfilledEvent(t, th, req, sub, -1) return utils.IsEmpty(commitment[:]) - }, testutils.WaitTimeout(t), time.Second) + }, testutils.WaitTimeout(t), time.Second).Should(gomega.BeTrue()) // Mine the fulfillment that was queued. mineForceFulfilled(t, requestID, sub.subID, forceFulfilledCount, *uni, th.db) diff --git a/core/services/vrf/v2/integration_v2_test.go b/core/services/vrf/v2/integration_v2_test.go index 6cbcc799e1b..fcf894911dc 100644 --- a/core/services/vrf/v2/integration_v2_test.go +++ b/core/services/vrf/v2/integration_v2_test.go @@ -31,8 +31,6 @@ import ( commonassets "github.com/smartcontractkit/chainlink-common/pkg/assets" commonconfig "github.com/smartcontractkit/chainlink-common/pkg/config" "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" - "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" - txmgrcommon "github.com/smartcontractkit/chainlink/v2/common/txmgr" txmgrtypes "github.com/smartcontractkit/chainlink/v2/common/txmgr/types" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" @@ -147,7 +145,7 @@ func makeTestTxm(t *testing.T, txStore txmgr.TestEvmTxStore, keyStore keystore.M } func newVRFCoordinatorV2Universe(t *testing.T, key ethkey.KeyV2, numConsumers int) coordinatorV2Universe { - tests.SkipShort(t, "VRFCoordinatorV2Universe") + testutils.SkipShort(t, "VRFCoordinatorV2Universe") oracleTransactor, err := bind.NewKeyedTransactorWithChainID(key.ToEcdsaPrivKey(), testutils.SimulatedChainID) require.NoError(t, err) var ( @@ -810,12 +808,9 @@ func mine(t *testing.T, requestID, subID *big.Int, backend evmtypes.Backend, db return assert.Eventually(t, func() bool { backend.Commit() - txes, err := txstore.FindTxesByMetaFieldAndStates(testutils.Context(t), metaField, subID.String(), []txmgrtypes.TxState{txmgrcommon.TxConfirmed, txmgrcommon.TxFinalized}, chainID) + txes, err := txstore.FindTxesByMetaFieldAndStates(testutils.Context(t), metaField, subID.String(), []txmgrtypes.TxState{txmgrcommon.TxConfirmed}, chainID) require.NoError(t, err) for _, tx := range txes { - if !checkForReceipt(t, db, tx.ID) { - return false - } meta, err := tx.GetMeta() require.NoError(t, err) if meta.RequestID.String() == common.BytesToHash(requestID.Bytes()).String() { @@ -842,12 +837,9 @@ func mineBatch(t *testing.T, requestIDs []*big.Int, subID *big.Int, backend evmt } return assert.Eventually(t, func() bool { backend.Commit() - txes, err := txstore.FindTxesByMetaFieldAndStates(testutils.Context(t), metaField, subID.String(), []txmgrtypes.TxState{txmgrcommon.TxConfirmed, txmgrcommon.TxFinalized}, chainID) + txes, err := txstore.FindTxesByMetaFieldAndStates(testutils.Context(t), metaField, subID.String(), []txmgrtypes.TxState{txmgrcommon.TxConfirmed}, chainID) require.NoError(t, err) for _, tx := range txes { - if !checkForReceipt(t, db, tx.ID) { - return false - } meta, err := tx.GetMeta() require.NoError(t, err) for _, requestID := range meta.RequestIDs { @@ -871,40 +863,16 @@ func mineForceFulfilled(t *testing.T, requestID *big.Int, subID uint64, forceFul var txs []txmgr.DbEthTx err := db.Select(&txs, ` SELECT * FROM evm.txes - WHERE evm.txes.state IN ('confirmed', 'finalized') + WHERE evm.txes.state = 'confirmed' AND evm.txes.meta->>'RequestID' = $1 AND CAST(evm.txes.meta->>'SubId' AS NUMERIC) = $2 ORDER BY created_at DESC `, common.BytesToHash(requestID.Bytes()).String(), subID) require.NoError(t, err) t.Log("num txs", len(txs)) - for _, tx := range txs { - if !checkForReceipt(t, db, tx.ID) { - return false - } - } - return len(txs) >= int(forceFulfilledCount) + return len(txs) == int(forceFulfilledCount) }, testutils.WaitTimeout(t), time.Second) } -func checkForReceipt(t *testing.T, db *sqlx.DB, txID int64) bool { - // Confirm receipt is fetched and stored for transaction to consider it mined - var count uint32 - sql := ` - SELECT count(*) FROM evm.receipts - JOIN evm.tx_attempts ON evm.tx_attempts.hash = evm.receipts.tx_hash - JOIN evm.txes ON evm.txes.ID = evm.tx_attempts.eth_tx_id - WHERE evm.txes.ID = $1 AND evm.txes.state IN ('confirmed', 'finalized')` - if txID != -1 { - err := db.GetContext(testutils.Context(t), &count, sql, txID) - require.NoError(t, err) - } else { - sql = strings.Replace(sql, "evm.txes.ID = $1", "evm.txes.meta->>'ForceFulfilled' IS NOT NULL", 1) - err := db.GetContext(testutils.Context(t), &count, sql, txID) - require.NoError(t, err) - } - return count > 0 -} - func TestVRFV2Integration_SingleConsumer_ForceFulfillment(t *testing.T) { t.Parallel() ownerKey := cltest.MustGenerateRandomKey(t) @@ -1857,16 +1825,13 @@ func TestIntegrationVRFV2(t *testing.T) { linkWeiCharged.BigInt(), }) - // We should see the response count present after receipt is fetched and stored for transaction - // Check periodically for receipt in case it is fetched and stored after more than 1 block - require.Eventually(t, func() bool { - uni.backend.Commit() - var counts map[string]uint64 - counts, err = listenerV2.GetStartingResponseCountsV2(ctx) - require.NoError(t, err) - t.Log(counts, rf[0].RequestID().String()) - return uint64(1) == counts[rf[0].RequestID().String()] - }, testutils.WaitTimeout(t), 1*time.Second) + // We should see the response count present + require.NoError(t, err) + var counts map[string]uint64 + counts, err = listenerV2.GetStartingResponseCountsV2(ctx) + require.NoError(t, err) + t.Log(counts, rf[0].RequestID().String()) + assert.Equal(t, uint64(1), counts[rf[0].RequestID().String()]) } func TestMaliciousConsumer(t *testing.T) { diff --git a/core/services/vrf/v2/listener_v2_log_listener_test.go b/core/services/vrf/v2/listener_v2_log_listener_test.go index 06af4c83f19..736c95967d2 100644 --- a/core/services/vrf/v2/listener_v2_log_listener_test.go +++ b/core/services/vrf/v2/listener_v2_log_listener_test.go @@ -240,26 +240,25 @@ func TestLogPollerFilterRegistered(t *testing.T) { // Instantiate listener. th := setupVRFLogPollerListenerTH(t) - func() { - // Run the log listener. This should register the log poller filter. - go th.Listener.runLogListener(time.Second, 1) - // Close the listener to avoid an orphaned goroutine. - defer close(th.Listener.chStop) - - // Wait for the log poller filter to be registered. - filterName := th.Listener.getLogPollerFilterName() - require.Eventually(t, func() bool { - return th.Listener.chain.LogPoller().HasFilter(filterName) - }, testutils.WaitTimeout(t), time.Second) - - // Once registered, expect the filter to stay registered. - gomega.NewWithT(t).Consistently(func() bool { - return th.Listener.chain.LogPoller().HasFilter(filterName) - }, 5*time.Second, 1*time.Second).Should(gomega.BeTrue()) - }() + // Run the log listener. This should register the log poller filter. + go th.Listener.runLogListener(time.Second, 1) + + // Wait for the log poller filter to be registered. + filterName := th.Listener.getLogPollerFilterName() + require.Eventually(t, func() bool { + return th.Listener.chain.LogPoller().HasFilter(filterName) + }, testutils.WaitTimeout(t), time.Second) + + // Once registered, expect the filter to stay registered. + gomega.NewWithT(t).Consistently(func() bool { + return th.Listener.chain.LogPoller().HasFilter(filterName) + }, 5*time.Second, 1*time.Second).Should(gomega.BeTrue()) + + // Close the listener to avoid an orphaned goroutine. + close(th.Listener.chStop) // Assert channel is closed. - _, ok := <-th.Listener.chStop + _, ok := (<-th.Listener.chStop) assert.False(t, ok) } diff --git a/core/services/workflows/delegate.go b/core/services/workflows/delegate.go index fc8fe3fe840..1db26729ca6 100644 --- a/core/services/workflows/delegate.go +++ b/core/services/workflows/delegate.go @@ -79,22 +79,13 @@ func (d *Delegate) ServicesForSpec(ctx context.Context, spec job.Job) ([]job.Ser return []job.ServiceCtx{engine}, nil } -type noopSecretsFetcher struct{} - -func (n *noopSecretsFetcher) SecretsFor(ctx context.Context, workflowOwner, workflowName, workflowID string) (map[string]string, error) { - return map[string]string{}, nil -} - -func newNoopSecretsFetcher() *noopSecretsFetcher { - return &noopSecretsFetcher{} -} - func NewDelegate( logger logger.Logger, registry core.CapabilitiesRegistry, + secretsFetcher secretsFetcher, store store.Store, ) *Delegate { - return &Delegate{logger: logger, registry: registry, secretsFetcher: newNoopSecretsFetcher(), store: store} + return &Delegate{logger: logger, registry: registry, secretsFetcher: secretsFetcher, store: store} } func ValidatedWorkflowJobSpec(ctx context.Context, tomlString string) (job.Job, error) { diff --git a/core/services/workflows/engine.go b/core/services/workflows/engine.go index d153e53bc07..b958e171c0c 100644 --- a/core/services/workflows/engine.go +++ b/core/services/workflows/engine.go @@ -27,11 +27,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/services/workflows/store" ) -const ( - fifteenMinutesSec = 15 * 60 - reservedFieldNameStepTimeout = "cre_step_timeout" - maxStepTimeoutOverrideSec = 10 * 60 // 10 minutes -) +const fifteenMinutesMs = 15 * 60 * 1000 type stepRequest struct { stepRef string @@ -96,7 +92,7 @@ func (sucm *stepUpdateManager) len() int64 { } type secretsFetcher interface { - SecretsFor(ctx context.Context, workflowOwner, workflowName, workflowID string) (map[string]string, error) + SecretsFor(workflowOwner, workflowName string) (map[string]string, error) } // Engine handles the lifecycle of a single workflow and its executions. @@ -142,7 +138,11 @@ func (e *Engine) Start(_ context.Context) error { // create a new context, since the one passed in via Start is short-lived. ctx, _ := e.stopCh.NewCtx() - e.metrics.incrementWorkflowInitializationCounter(ctx) + // spin up monitoring resources + err := initMonitoringResources() + if err != nil { + return fmt.Errorf("could not initialize monitoring resources: %w", err) + } e.wg.Add(e.maxWorkerLimit) for i := 0; i < e.maxWorkerLimit; i++ { @@ -354,7 +354,6 @@ func (e *Engine) init(ctx context.Context) { e.logger.Info("engine initialized") logCustMsg(ctx, e.cma, "workflow registered", e.logger) - e.metrics.incrementWorkflowRegisteredCounter(ctx) e.afterInit(true) } @@ -436,7 +435,7 @@ func (e *Engine) registerTrigger(ctx context.Context, t *triggerCapability, trig Metadata: capabilities.RequestMetadata{ WorkflowID: e.workflow.id, WorkflowOwner: e.workflow.owner, - WorkflowName: e.workflow.hexName, + WorkflowName: e.workflow.name, WorkflowDonID: e.localNode.WorkflowDON.ID, WorkflowDonConfigVersion: e.localNode.WorkflowDON.ConfigVersion, ReferenceID: t.Ref, @@ -446,7 +445,7 @@ func (e *Engine) registerTrigger(ctx context.Context, t *triggerCapability, trig } eventsCh, err := t.trigger.RegisterTrigger(ctx, triggerRegRequest) if err != nil { - e.metrics.with(platform.KeyTriggerID, triggerID).incrementRegisterTriggerFailureCounter(ctx) + e.metrics.incrementRegisterTriggerFailureCounter(ctx) // It's confusing that t.ID is different from triggerID, but // t.ID is the capability ID, and triggerID is the trigger ID. // @@ -675,6 +674,7 @@ func (e *Engine) queueIfReady(state store.WorkflowExecution, step *step) { func (e *Engine) finishExecution(ctx context.Context, cma custmsg.MessageEmitter, executionID string, status string) error { l := e.logger.With(platform.KeyWorkflowExecutionID, executionID, "status", status) + metrics := e.metrics.with("status", status) l.Info("finishing execution") @@ -688,28 +688,18 @@ func (e *Engine) finishExecution(ctx context.Context, cma custmsg.MessageEmitter return err } + executionDuration := execState.FinishedAt.Sub(*execState.CreatedAt).Milliseconds() + e.stepUpdatesChMap.remove(executionID) + metrics.updateTotalWorkflowsGauge(ctx, e.stepUpdatesChMap.len()) + metrics.updateWorkflowExecutionLatencyGauge(ctx, executionDuration) - executionDuration := int64(execState.FinishedAt.Sub(*execState.CreatedAt).Seconds()) - switch status { - case store.StatusCompleted: - e.metrics.updateWorkflowCompletedDurationHistogram(ctx, executionDuration) - case store.StatusCompletedEarlyExit: - e.metrics.updateWorkflowEarlyExitDurationHistogram(ctx, executionDuration) - case store.StatusErrored: - e.metrics.updateWorkflowErrorDurationHistogram(ctx, executionDuration) - case store.StatusTimeout: - // should expect the same values unless the timeout is adjusted. - // using histogram as it gives count of executions for free - e.metrics.updateWorkflowTimeoutDurationHistogram(ctx, executionDuration) - } - - if executionDuration > fifteenMinutesSec { - logCustMsg(ctx, cma, fmt.Sprintf("execution duration exceeded 15 minutes: %d (seconds)", executionDuration), l) - l.Warnf("execution duration exceeded 15 minutes: %d (seconds)", executionDuration) - } - logCustMsg(ctx, cma, fmt.Sprintf("execution duration: %d (seconds)", executionDuration), l) - l.Infof("execution duration: %d (seconds)", executionDuration) + if executionDuration > fifteenMinutesMs { + logCustMsg(ctx, cma, fmt.Sprintf("execution duration exceeded 15 minutes: %d", executionDuration), l) + l.Warnf("execution duration exceeded 15 minutes: %d", executionDuration) + } + logCustMsg(ctx, cma, fmt.Sprintf("execution duration: %d", executionDuration), l) + l.Infof("execution duration: %d", executionDuration) e.onExecutionFinished(executionID) return nil } @@ -753,7 +743,6 @@ func (e *Engine) worker(ctx context.Context) { if err != nil { e.logger.With(platform.KeyWorkflowExecutionID, executionID).Errorf("failed to start execution: %v", err) logCustMsg(ctx, cma, fmt.Sprintf("failed to start execution: %s", err), e.logger) - e.metrics.with(platform.KeyTriggerID, te.ID).incrementTriggerWorkflowStarterErrorCounter(ctx) } else { e.logger.With(platform.KeyWorkflowExecutionID, executionID).Debug("execution started") logCustMsg(ctx, cma, "execution started", e.logger) @@ -777,21 +766,13 @@ func (e *Engine) workerForStepRequest(ctx context.Context, msg stepRequest) { Ref: msg.stepRef, } + // TODO ks-462 inputs logCustMsg(ctx, cma, "executing step", l) - stepExecutionStartTime := time.Now() - inputs, outputs, err := e.executeStep(ctx, l, msg) - stepExecutionDuration := time.Since(stepExecutionStartTime).Seconds() - - curStepID := "UNSET" - curStep, verr := e.workflow.Vertex(msg.stepRef) - if verr == nil { - curStepID = curStep.ID - } else { - l.Errorf("failed to resolve step in workflow; error %v", verr) - } - e.metrics.with(platform.KeyCapabilityID, curStepID).updateWorkflowStepDurationHistogram(ctx, int64(stepExecutionDuration)) + stepCtx, cancel := context.WithTimeout(ctx, e.stepTimeoutDuration) + defer cancel() + inputs, outputs, err := e.executeStep(stepCtx, l, msg) var stepStatus string switch { case errors.Is(capabilities.ErrStopExecution, err): @@ -868,7 +849,7 @@ func (e *Engine) interpolateEnvVars(config map[string]any, env exec.Env) (*value // registry (for capability-level configuration). It doesn't perform any caching of the config values, since // the two registries perform their own caching. func (e *Engine) configForStep(ctx context.Context, lggr logger.Logger, step *step) (*values.Map, error) { - secrets, err := e.secretsFetcher.SecretsFor(ctx, e.workflow.owner, e.workflow.hexName, e.workflow.id) + secrets, err := e.secretsFetcher.SecretsFor(e.workflow.owner, e.workflow.name) if err != nil { return nil, fmt.Errorf("failed to fetch secrets: %w", err) } @@ -912,16 +893,16 @@ func (e *Engine) configForStep(ctx context.Context, lggr logger.Logger, step *st // executeStep executes the referenced capability within a step and returns the result. func (e *Engine) executeStep(ctx context.Context, lggr logger.Logger, msg stepRequest) (*values.Map, values.Value, error) { - curStep, err := e.workflow.Vertex(msg.stepRef) + step, err := e.workflow.Vertex(msg.stepRef) if err != nil { return nil, nil, err } var inputs any - if curStep.Inputs.OutputRef != "" { - inputs = curStep.Inputs.OutputRef + if step.Inputs.OutputRef != "" { + inputs = step.Inputs.OutputRef } else { - inputs = curStep.Inputs.Mapping + inputs = step.Inputs.Mapping } i, err := exec.FindAndInterpolateAllKeys(inputs, msg.state) @@ -934,24 +915,10 @@ func (e *Engine) executeStep(ctx context.Context, lggr logger.Logger, msg stepRe return nil, nil, err } - config, err := e.configForStep(ctx, lggr, curStep) + config, err := e.configForStep(ctx, lggr, step) if err != nil { return nil, nil, err } - stepTimeoutDuration := e.stepTimeoutDuration - if timeoutOverride, ok := config.Underlying[reservedFieldNameStepTimeout]; ok { - var desiredTimeout int64 - err2 := timeoutOverride.UnwrapTo(&desiredTimeout) - if err2 != nil { - e.logger.Warnw("couldn't decode step timeout override, using default", "error", err2, "default", stepTimeoutDuration) - } else { - if desiredTimeout > maxStepTimeoutOverrideSec { - e.logger.Warnw("desired step timeout is too large, limiting to max value", "maxValue", maxStepTimeoutOverrideSec) - desiredTimeout = maxStepTimeoutOverrideSec - } - stepTimeoutDuration = time.Duration(desiredTimeout) * time.Second - } - } tr := capabilities.CapabilityRequest{ Inputs: inputsMap, @@ -960,20 +927,16 @@ func (e *Engine) executeStep(ctx context.Context, lggr logger.Logger, msg stepRe WorkflowID: msg.state.WorkflowID, WorkflowExecutionID: msg.state.ExecutionID, WorkflowOwner: e.workflow.owner, - WorkflowName: e.workflow.hexName, + WorkflowName: e.workflow.name, WorkflowDonID: e.localNode.WorkflowDON.ID, WorkflowDonConfigVersion: e.localNode.WorkflowDON.ConfigVersion, ReferenceID: msg.stepRef, }, } - stepCtx, cancel := context.WithTimeout(ctx, stepTimeoutDuration) - defer cancel() - - e.metrics.with(platform.KeyCapabilityID, curStep.ID).incrementCapabilityInvocationCounter(ctx) - output, err := curStep.capability.Execute(stepCtx, tr) + e.metrics.incrementCapabilityInvocationCounter(ctx) + output, err := step.capability.Execute(ctx, tr) if err != nil { - e.metrics.with(platform.KeyStepRef, msg.stepRef, platform.KeyCapabilityID, curStep.ID).incrementCapabilityFailureCounter(ctx) return inputsMap, nil, err } @@ -986,7 +949,7 @@ func (e *Engine) deregisterTrigger(ctx context.Context, t *triggerCapability, tr WorkflowID: e.workflow.id, WorkflowDonID: e.localNode.WorkflowDON.ID, WorkflowDonConfigVersion: e.localNode.WorkflowDON.ConfigVersion, - WorkflowName: e.workflow.hexName, + WorkflowName: e.workflow.name, WorkflowOwner: e.workflow.owner, ReferenceID: t.Ref, }, @@ -1093,7 +1056,6 @@ func (e *Engine) isWorkflowFullyProcessed(ctx context.Context, state store.Workf return workflowProcessed, store.StatusCompleted, nil } -// heartbeat runs by default every defaultHeartbeatCadence minutes func (e *Engine) heartbeat(ctx context.Context) { defer e.wg.Done() @@ -1107,7 +1069,6 @@ func (e *Engine) heartbeat(ctx context.Context) { return case <-ticker.C: e.metrics.incrementEngineHeartbeatCounter(ctx) - e.metrics.updateTotalWorkflowsGauge(ctx, e.stepUpdatesChMap.len()) logCustMsg(ctx, e.cma, "engine heartbeat at: "+e.clock.Now().Format(time.RFC3339), e.logger) } } @@ -1174,19 +1135,10 @@ func (e *Engine) Close() error { return err } logCustMsg(ctx, e.cma, "workflow unregistered", e.logger) - e.metrics.incrementWorkflowUnregisteredCounter(ctx) return nil }) } -func (e *Engine) HealthReport() map[string]error { - return map[string]error{e.Name(): nil} -} - -func (e *Engine) Name() string { - return e.logger.Name() -} - type Config struct { Workflow sdk.WorkflowSpec WorkflowID string @@ -1279,12 +1231,6 @@ func NewEngine(ctx context.Context, cfg Config) (engine *Engine, err error) { // - that the resulting graph is strongly connected (i.e. no disjointed subgraphs exist) // - etc. - // spin up monitoring resources - em, err := initMonitoringResources() - if err != nil { - return nil, fmt.Errorf("could not initialize monitoring resources: %w", err) - } - cma := custmsg.NewLabeler().With(platform.KeyWorkflowID, cfg.WorkflowID, platform.KeyWorkflowOwner, cfg.WorkflowOwner, platform.KeyWorkflowName, cfg.WorkflowName) workflow, err := Parse(cfg.Workflow) if err != nil { @@ -1294,12 +1240,12 @@ func NewEngine(ctx context.Context, cfg Config) (engine *Engine, err error) { workflow.id = cfg.WorkflowID workflow.owner = cfg.WorkflowOwner - workflow.hexName = hex.EncodeToString([]byte(cfg.WorkflowName)) + workflow.name = hex.EncodeToString([]byte(cfg.WorkflowName)) engine = &Engine{ cma: cma, logger: cfg.Lggr.Named("WorkflowEngine").With("workflowID", cfg.WorkflowID), - metrics: workflowsMetricLabeler{metrics.NewLabeler().With(platform.KeyWorkflowID, cfg.WorkflowID, platform.KeyWorkflowOwner, cfg.WorkflowOwner, platform.KeyWorkflowName, cfg.WorkflowName), *em}, + metrics: workflowsMetricLabeler{metrics.NewLabeler().With(platform.KeyWorkflowID, cfg.WorkflowID, platform.KeyWorkflowOwner, cfg.WorkflowOwner, platform.KeyWorkflowName, workflow.name)}, registry: cfg.Registry, workflow: workflow, secretsFetcher: cfg.SecretsFetcher, @@ -1348,7 +1294,7 @@ func (e *workflowError) Error() string { } // prefix the error with the labels - for label := range platform.LabelKeysSorted() { + for _, label := range platform.OrderedLabelKeys { // This will silently ignore any labels that are not present in the map // are we ok with this? if value, ok := e.labels[label]; ok { diff --git a/core/services/workflows/engine_test.go b/core/services/workflows/engine_test.go index 95ac74f0c76..3a2bc17bc36 100644 --- a/core/services/workflows/engine_test.go +++ b/core/services/workflows/engine_test.go @@ -86,7 +86,6 @@ targets: address: "0x54e220867af6683aE6DcBF535B4f952cB5116510" params: ["$(report)"] abi: "receive(report bytes)" - cre_step_timeout: 610 ` type testHooks struct { @@ -153,7 +152,7 @@ func newTestEngineWithYAMLSpec(t *testing.T, reg *coreCap.Registry, spec string, type mockSecretsFetcher struct{} -func (s mockSecretsFetcher) SecretsFor(ctx context.Context, workflowOwner, workflowName, workflowID string) (map[string]string, error) { +func (s mockSecretsFetcher) SecretsFor(workflowOwner, workflowName string) (map[string]string, error) { return map[string]string{}, nil } @@ -1128,8 +1127,8 @@ triggers: - "0x3333333333333333333300000000000000000000000000000000000000000000" # BTCUSD actions: - - id: custom-compute@1.0.0 - ref: custom-compute + - id: custom_compute@1.0.0 + ref: custom_compute config: maxMemoryMBs: 128 tickInterval: 100ms @@ -1174,7 +1173,7 @@ targets: func TestEngine_MergesWorkflowConfigAndCRConfig_CRConfigPrecedence(t *testing.T) { var ( ctx = testutils.Context(t) - actionID = "custom-compute@1.0.0" + actionID = "custom_compute@1.0.0" giveTimeout = 300 * time.Millisecond giveTickInterval = 100 * time.Millisecond registryConfig = map[string]any{ @@ -1563,8 +1562,8 @@ triggers: - "0x3333333333333333333300000000000000000000000000000000000000000000" # BTCUSD actions: - - id: custom-compute@1.0.0 - ref: custom-compute + - id: custom_compute@1.0.0 + ref: custom_compute config: fidelityToken: $(ENV.secrets.fidelity) inputs: @@ -1606,7 +1605,7 @@ type mockFetcher struct { retval map[string]string } -func (m *mockFetcher) SecretsFor(ctx context.Context, workflowOwner, workflowName, workflowID string) (map[string]string, error) { +func (m *mockFetcher) SecretsFor(workflowOwner, workflowName string) (map[string]string, error) { return m.retval, nil } @@ -1626,7 +1625,7 @@ func TestEngine_FetchesSecrets(t *testing.T) { action := newMockCapability( // Create a remote capability so we don't use the local transmission protocol. capabilities.MustNewRemoteCapabilityInfo( - "custom-compute@1.0.0", + "custom_compute@1.0.0", capabilities.CapabilityTypeAction, "a custom compute action with custom config", &capabilities.DON{ID: 1}, diff --git a/core/services/workflows/models.go b/core/services/workflows/models.go index e5d26a474f6..0faf66d9883 100644 --- a/core/services/workflows/models.go +++ b/core/services/workflows/models.go @@ -20,9 +20,9 @@ import ( // treated differently due to their nature of being the starting // point of a workflow. type workflow struct { - id string - owner string - hexName string + id string + owner string + name string graph.Graph[string, *step] triggers []*triggerCapability diff --git a/core/services/workflows/monitoring.go b/core/services/workflows/monitoring.go index b73ee6e5eda..d498ff354c9 100644 --- a/core/services/workflows/monitoring.go +++ b/core/services/workflows/monitoring.go @@ -5,255 +5,90 @@ import ( "fmt" "go.opentelemetry.io/otel/metric" - sdkmetric "go.opentelemetry.io/otel/sdk/metric" "github.com/smartcontractkit/chainlink-common/pkg/beholder" "github.com/smartcontractkit/chainlink-common/pkg/metrics" - monutils "github.com/smartcontractkit/chainlink/v2/core/monitoring" + localMonitoring "github.com/smartcontractkit/chainlink/v2/core/monitoring" ) -// em AKA "engine metrics" is to locally scope these instruments to avoid -// data races in testing -type engineMetrics struct { - registerTriggerFailureCounter metric.Int64Counter - triggerWorkflowStarterErrorCounter metric.Int64Counter - workflowsRunningGauge metric.Int64Gauge - capabilityInvocationCounter metric.Int64Counter - capabilityFailureCounter metric.Int64Counter - workflowRegisteredCounter metric.Int64Counter - workflowUnregisteredCounter metric.Int64Counter - workflowExecutionLatencyGauge metric.Int64Gauge // ms - workflowStepErrorCounter metric.Int64Counter - workflowInitializationCounter metric.Int64Counter - engineHeartbeatCounter metric.Int64Counter - workflowCompletedDurationSeconds metric.Int64Histogram - workflowEarlyExitDurationSeconds metric.Int64Histogram - workflowErrorDurationSeconds metric.Int64Histogram - workflowTimeoutDurationSeconds metric.Int64Histogram - workflowStepDurationSeconds metric.Int64Histogram -} - -func initMonitoringResources() (em *engineMetrics, err error) { - em = &engineMetrics{} - em.registerTriggerFailureCounter, err = beholder.GetMeter().Int64Counter("platform_engine_registertrigger_failures") - if err != nil { - return nil, fmt.Errorf("failed to register trigger failure counter: %w", err) - } - - em.triggerWorkflowStarterErrorCounter, err = beholder.GetMeter().Int64Counter("platform_engine_triggerworkflow_starter_errors") - if err != nil { - return nil, fmt.Errorf("failed to register trigger workflow starter error counter: %w", err) - } - - em.workflowsRunningGauge, err = beholder.GetMeter().Int64Gauge("platform_engine_workflow_count") - if err != nil { - return nil, fmt.Errorf("failed to register workflows running gauge: %w", err) - } - - em.capabilityInvocationCounter, err = beholder.GetMeter().Int64Counter("platform_engine_capabilities_count") - if err != nil { - return nil, fmt.Errorf("failed to register capability invocation counter: %w", err) - } - - em.capabilityFailureCounter, err = beholder.GetMeter().Int64Counter("platform_engine_capabilities_failures") - if err != nil { - return nil, fmt.Errorf("failed to register capability failure counter: %w", err) - } - - em.workflowRegisteredCounter, err = beholder.GetMeter().Int64Counter("platform_engine_workflow_registered_count") - if err != nil { - return nil, fmt.Errorf("failed to register workflow registered counter: %w", err) - } - - em.workflowUnregisteredCounter, err = beholder.GetMeter().Int64Counter("platform_engine_workflow_unregistered_count") - if err != nil { - return nil, fmt.Errorf("failed to register workflow unregistered counter: %w", err) - } - - em.workflowExecutionLatencyGauge, err = beholder.GetMeter().Int64Gauge( - "platform_engine_workflow_time", - metric.WithUnit("ms")) - if err != nil { - return nil, fmt.Errorf("failed to register workflow execution latency gauge: %w", err) - } - - em.workflowInitializationCounter, err = beholder.GetMeter().Int64Counter("platform_engine_workflow_initializations") - if err != nil { - return nil, fmt.Errorf("failed to register workflow initialization counter: %w", err) - } - - em.workflowStepErrorCounter, err = beholder.GetMeter().Int64Counter("platform_engine_workflow_errors") - if err != nil { - return nil, fmt.Errorf("failed to register workflow step error counter: %w", err) - } +var registerTriggerFailureCounter metric.Int64Counter +var workflowsRunningGauge metric.Int64Gauge +var capabilityInvocationCounter metric.Int64Counter +var workflowExecutionLatencyGauge metric.Int64Gauge // ms +var workflowStepErrorCounter metric.Int64Counter +var engineHeartbeatCounter metric.Int64UpDownCounter - em.engineHeartbeatCounter, err = beholder.GetMeter().Int64Counter("platform_engine_heartbeat") +func initMonitoringResources() (err error) { + registerTriggerFailureCounter, err = beholder.GetMeter().Int64Counter("platform_engine_registertrigger_failures") if err != nil { - return nil, fmt.Errorf("failed to register engine heartbeat counter: %w", err) + return fmt.Errorf("failed to register trigger failure counter: %w", err) } - em.workflowCompletedDurationSeconds, err = beholder.GetMeter().Int64Histogram( - "platform_engine_workflow_completed_time_seconds", - metric.WithDescription("Distribution of completed execution latencies"), - metric.WithUnit("seconds")) + workflowsRunningGauge, err = beholder.GetMeter().Int64Gauge("platform_engine_workflow_count") if err != nil { - return nil, fmt.Errorf("failed to register completed duration histogram: %w", err) + return fmt.Errorf("failed to register workflows running gauge: %w", err) } - em.workflowEarlyExitDurationSeconds, err = beholder.GetMeter().Int64Histogram( - "platform_engine_workflow_earlyexit_time_seconds", - metric.WithDescription("Distribution of earlyexit execution latencies"), - metric.WithUnit("seconds")) + capabilityInvocationCounter, err = beholder.GetMeter().Int64Counter("platform_engine_capabilities_count") if err != nil { - return nil, fmt.Errorf("failed to register early exit duration histogram: %w", err) + return fmt.Errorf("failed to register capability invocation counter: %w", err) } - em.workflowErrorDurationSeconds, err = beholder.GetMeter().Int64Histogram( - "platform_engine_workflow_error_time_seconds", - metric.WithDescription("Distribution of error execution latencies"), - metric.WithUnit("seconds")) + workflowExecutionLatencyGauge, err = beholder.GetMeter().Int64Gauge("platform_engine_workflow_time") if err != nil { - return nil, fmt.Errorf("failed to register error duration histogram: %w", err) + return fmt.Errorf("failed to register workflow execution latency gauge: %w", err) } - em.workflowTimeoutDurationSeconds, err = beholder.GetMeter().Int64Histogram( - "platform_engine_workflow_timeout_time_seconds", - metric.WithDescription("Distribution of timeout execution latencies"), - metric.WithUnit("seconds")) + workflowStepErrorCounter, err = beholder.GetMeter().Int64Counter("platform_engine_workflow_errors") if err != nil { - return nil, fmt.Errorf("failed to register timeout duration histogram: %w", err) + return fmt.Errorf("failed to register workflow step error counter: %w", err) } - em.workflowStepDurationSeconds, err = beholder.GetMeter().Int64Histogram( - "platform_engine_workflow_step_time_seconds", - metric.WithDescription("Distribution of step execution times"), - metric.WithUnit("seconds")) + engineHeartbeatCounter, err = beholder.GetMeter().Int64UpDownCounter("platform_engine_heartbeat") if err != nil { - return nil, fmt.Errorf("failed to register step execution time histogram: %w", err) + return fmt.Errorf("failed to register engine heartbeat counter: %w", err) } - return em, nil -} - -// Note: due to the OTEL specification, all histogram buckets -// Must be defined when the beholder client is created -func MetricViews() []sdkmetric.View { - return []sdkmetric.View{ - sdkmetric.NewView( - sdkmetric.Instrument{Name: "platform_engine_workflow_earlyexit_time_seconds"}, - sdkmetric.Stream{Aggregation: sdkmetric.AggregationExplicitBucketHistogram{ - Boundaries: []float64{0, 1, 10, 30, 120}, - }}, - ), - sdkmetric.NewView( - sdkmetric.Instrument{Name: "platform_engine_workflow_completed_time_seconds"}, - sdkmetric.Stream{Aggregation: sdkmetric.AggregationExplicitBucketHistogram{ - Boundaries: []float64{0, 10, 30, 60, 120, 300, 600, 900, 1200}, - }}, - ), - sdkmetric.NewView( - sdkmetric.Instrument{Name: "platform_engine_workflow_error_time_seconds"}, - sdkmetric.Stream{Aggregation: sdkmetric.AggregationExplicitBucketHistogram{ - Boundaries: []float64{0, 30, 60, 120, 240, 600}, - }}, - ), - sdkmetric.NewView( - sdkmetric.Instrument{Name: "platform_engine_workflow_step_time_seconds"}, - sdkmetric.Stream{Aggregation: sdkmetric.AggregationExplicitBucketHistogram{ - Boundaries: []float64{0, 20, 60, 120, 240}, - }}, - ), - } + return nil } // workflowsMetricLabeler wraps monitoring.MetricsLabeler to provide workflow specific utilities // for monitoring resources type workflowsMetricLabeler struct { metrics.Labeler - em engineMetrics } func (c workflowsMetricLabeler) with(keyValues ...string) workflowsMetricLabeler { - return workflowsMetricLabeler{c.With(keyValues...), c.em} + return workflowsMetricLabeler{c.With(keyValues...)} } func (c workflowsMetricLabeler) incrementRegisterTriggerFailureCounter(ctx context.Context) { - otelLabels := monutils.KvMapToOtelAttributes(c.Labels) - c.em.registerTriggerFailureCounter.Add(ctx, 1, metric.WithAttributes(otelLabels...)) -} - -func (c workflowsMetricLabeler) incrementTriggerWorkflowStarterErrorCounter(ctx context.Context) { - otelLabels := monutils.KvMapToOtelAttributes(c.Labels) - c.em.triggerWorkflowStarterErrorCounter.Add(ctx, 1, metric.WithAttributes(otelLabels...)) + otelLabels := localMonitoring.KvMapToOtelAttributes(c.Labels) + registerTriggerFailureCounter.Add(ctx, 1, metric.WithAttributes(otelLabels...)) } func (c workflowsMetricLabeler) incrementCapabilityInvocationCounter(ctx context.Context) { - otelLabels := monutils.KvMapToOtelAttributes(c.Labels) - c.em.capabilityInvocationCounter.Add(ctx, 1, metric.WithAttributes(otelLabels...)) + otelLabels := localMonitoring.KvMapToOtelAttributes(c.Labels) + capabilityInvocationCounter.Add(ctx, 1, metric.WithAttributes(otelLabels...)) } func (c workflowsMetricLabeler) updateWorkflowExecutionLatencyGauge(ctx context.Context, val int64) { - otelLabels := monutils.KvMapToOtelAttributes(c.Labels) - c.em.workflowExecutionLatencyGauge.Record(ctx, val, metric.WithAttributes(otelLabels...)) + otelLabels := localMonitoring.KvMapToOtelAttributes(c.Labels) + workflowExecutionLatencyGauge.Record(ctx, val, metric.WithAttributes(otelLabels...)) } func (c workflowsMetricLabeler) incrementTotalWorkflowStepErrorsCounter(ctx context.Context) { - otelLabels := monutils.KvMapToOtelAttributes(c.Labels) - c.em.workflowStepErrorCounter.Add(ctx, 1, metric.WithAttributes(otelLabels...)) + otelLabels := localMonitoring.KvMapToOtelAttributes(c.Labels) + workflowStepErrorCounter.Add(ctx, 1, metric.WithAttributes(otelLabels...)) } func (c workflowsMetricLabeler) updateTotalWorkflowsGauge(ctx context.Context, val int64) { - otelLabels := monutils.KvMapToOtelAttributes(c.Labels) - c.em.workflowsRunningGauge.Record(ctx, val, metric.WithAttributes(otelLabels...)) + otelLabels := localMonitoring.KvMapToOtelAttributes(c.Labels) + workflowsRunningGauge.Record(ctx, val, metric.WithAttributes(otelLabels...)) } func (c workflowsMetricLabeler) incrementEngineHeartbeatCounter(ctx context.Context) { - otelLabels := monutils.KvMapToOtelAttributes(c.Labels) - c.em.engineHeartbeatCounter.Add(ctx, 1, metric.WithAttributes(otelLabels...)) -} - -func (c workflowsMetricLabeler) incrementCapabilityFailureCounter(ctx context.Context) { - otelLabels := monutils.KvMapToOtelAttributes(c.Labels) - c.em.capabilityFailureCounter.Add(ctx, 1, metric.WithAttributes(otelLabels...)) -} - -func (c workflowsMetricLabeler) incrementWorkflowRegisteredCounter(ctx context.Context) { - otelLabels := monutils.KvMapToOtelAttributes(c.Labels) - c.em.workflowRegisteredCounter.Add(ctx, 1, metric.WithAttributes(otelLabels...)) -} - -func (c workflowsMetricLabeler) incrementWorkflowUnregisteredCounter(ctx context.Context) { - otelLabels := monutils.KvMapToOtelAttributes(c.Labels) - c.em.workflowUnregisteredCounter.Add(ctx, 1, metric.WithAttributes(otelLabels...)) -} - -func (c workflowsMetricLabeler) incrementWorkflowInitializationCounter(ctx context.Context) { - otelLabels := monutils.KvMapToOtelAttributes(c.Labels) - c.em.workflowInitializationCounter.Add(ctx, 1, metric.WithAttributes(otelLabels...)) -} - -func (c workflowsMetricLabeler) updateWorkflowCompletedDurationHistogram(ctx context.Context, duration int64) { - otelLabels := monutils.KvMapToOtelAttributes(c.Labels) - c.em.workflowCompletedDurationSeconds.Record(ctx, duration, metric.WithAttributes(otelLabels...)) -} - -func (c workflowsMetricLabeler) updateWorkflowEarlyExitDurationHistogram(ctx context.Context, duration int64) { - otelLabels := monutils.KvMapToOtelAttributes(c.Labels) - c.em.workflowEarlyExitDurationSeconds.Record(ctx, duration, metric.WithAttributes(otelLabels...)) -} - -func (c workflowsMetricLabeler) updateWorkflowErrorDurationHistogram(ctx context.Context, duration int64) { - otelLabels := monutils.KvMapToOtelAttributes(c.Labels) - c.em.workflowErrorDurationSeconds.Record(ctx, duration, metric.WithAttributes(otelLabels...)) -} - -func (c workflowsMetricLabeler) updateWorkflowTimeoutDurationHistogram(ctx context.Context, duration int64) { - otelLabels := monutils.KvMapToOtelAttributes(c.Labels) - c.em.workflowTimeoutDurationSeconds.Record(ctx, duration, metric.WithAttributes(otelLabels...)) -} - -func (c workflowsMetricLabeler) updateWorkflowStepDurationHistogram(ctx context.Context, duration int64) { - otelLabels := monutils.KvMapToOtelAttributes(c.Labels) - c.em.workflowStepDurationSeconds.Record(ctx, duration, metric.WithAttributes(otelLabels...)) + otelLabels := localMonitoring.KvMapToOtelAttributes(c.Labels) + engineHeartbeatCounter.Add(ctx, 1, metric.WithAttributes(otelLabels...)) } diff --git a/core/services/workflows/monitoring_test.go b/core/services/workflows/monitoring_test.go index 5b7177e51dc..5910e583c95 100644 --- a/core/services/workflows/monitoring_test.go +++ b/core/services/workflows/monitoring_test.go @@ -9,12 +9,11 @@ import ( ) func Test_InitMonitoringResources(t *testing.T) { - _, err := initMonitoringResources() - require.NoError(t, err) + require.NoError(t, initMonitoringResources()) } func Test_WorkflowMetricsLabeler(t *testing.T) { - testWorkflowsMetricLabeler := workflowsMetricLabeler{metrics.NewLabeler(), engineMetrics{}} + testWorkflowsMetricLabeler := workflowsMetricLabeler{metrics.NewLabeler()} testWorkflowsMetricLabeler2 := testWorkflowsMetricLabeler.with("foo", "baz") require.EqualValues(t, testWorkflowsMetricLabeler2.Labels["foo"], "baz") } diff --git a/core/services/workflows/store/store_db.go b/core/services/workflows/store/store_db.go index 66c78493417..f15a6928e7e 100644 --- a/core/services/workflows/store/store_db.go +++ b/core/services/workflows/store/store_db.go @@ -111,23 +111,15 @@ func (d *DBStore) pruneDBEntries() { return case <-ticker.C: ctx, cancel := d.chStop.CtxWithTimeout(defaultPruneTimeoutSec * time.Second) - nPruned := int64(0) err := sqlutil.TransactDataSource(ctx, d.db, nil, func(tx sqlutil.DataSource) error { stmt := fmt.Sprintf("DELETE FROM workflow_executions WHERE (id) IN (SELECT id FROM workflow_executions WHERE (created_at < now() - interval '%d hours') LIMIT %d);", defaultPruneRecordAgeHours, defaultPruneBatchSize) - res, err := tx.ExecContext(ctx, stmt) - if err != nil { - return err - } - nPruned, err = res.RowsAffected() - if err != nil { - d.lggr.Warnw("Failed to get number of pruned workflow_executions", "err", err) - } - return nil + _, err := tx.ExecContext(ctx, stmt) + return err }) if err != nil { d.lggr.Errorw("Failed to prune workflow_executions", "err", err) - } else if nPruned > 0 { - d.lggr.Debugw("Pruned oldest workflow_executions", "nPruned", nPruned, "batchSize", defaultPruneBatchSize, "ageLimitHours", defaultPruneRecordAgeHours) + } else { + d.lggr.Infow("Pruned oldest workflow_executions", "batchSize", defaultPruneBatchSize, "ageLimitHours", defaultPruneRecordAgeHours) } cancel() } diff --git a/core/services/workflows/syncer/engine_registry.go b/core/services/workflows/syncer/engine_registry.go deleted file mode 100644 index fa3771c5a0f..00000000000 --- a/core/services/workflows/syncer/engine_registry.go +++ /dev/null @@ -1,76 +0,0 @@ -package syncer - -import ( - "errors" - "sync" - - "github.com/smartcontractkit/chainlink-common/pkg/services" -) - -type EngineRegistry struct { - engines map[string]services.Service - mu sync.RWMutex -} - -func NewEngineRegistry() *EngineRegistry { - return &EngineRegistry{ - engines: make(map[string]services.Service), - } -} - -// Add adds an engine to the registry. -func (r *EngineRegistry) Add(id string, engine services.Service) { - r.mu.Lock() - defer r.mu.Unlock() - r.engines[id] = engine -} - -// Get retrieves an engine from the registry. -func (r *EngineRegistry) Get(id string) (services.Service, error) { - r.mu.RLock() - defer r.mu.RUnlock() - engine, found := r.engines[id] - if !found { - return nil, errors.New("engine not found") - } - return engine, nil -} - -// IsRunning is true if the engine exists and is ready. -func (r *EngineRegistry) IsRunning(id string) bool { - r.mu.RLock() - defer r.mu.RUnlock() - engine, found := r.engines[id] - if !found { - return false - } - - return engine.Ready() == nil -} - -// Pop removes an engine from the registry and returns the engine if found. -func (r *EngineRegistry) Pop(id string) (services.Service, error) { - r.mu.Lock() - defer r.mu.Unlock() - engine, ok := r.engines[id] - if !ok { - return nil, errors.New("remove failed: engine not found") - } - delete(r.engines, id) - return engine, nil -} - -// Close closes all engines in the registry. -func (r *EngineRegistry) Close() error { - r.mu.Lock() - defer r.mu.Unlock() - var err error - for id, engine := range r.engines { - closeErr := engine.Close() - if closeErr != nil { - err = errors.Join(err, closeErr) - } - delete(r.engines, id) - } - return err -} diff --git a/core/services/workflows/syncer/fetcher.go b/core/services/workflows/syncer/fetcher.go deleted file mode 100644 index 5c8856d58c1..00000000000 --- a/core/services/workflows/syncer/fetcher.go +++ /dev/null @@ -1,108 +0,0 @@ -package syncer - -import ( - "context" - "crypto/sha256" - "encoding/hex" - "encoding/json" - "fmt" - "net/http" - "strings" - - "github.com/smartcontractkit/chainlink-common/pkg/services" - "github.com/smartcontractkit/chainlink/v2/core/capabilities/webapi" - "github.com/smartcontractkit/chainlink/v2/core/logger" - "github.com/smartcontractkit/chainlink/v2/core/services/gateway/connector" - "github.com/smartcontractkit/chainlink/v2/core/services/gateway/handlers/capabilities" - ghcapabilities "github.com/smartcontractkit/chainlink/v2/core/services/gateway/handlers/capabilities" - "github.com/smartcontractkit/chainlink/v2/core/services/gateway/handlers/common" -) - -type FetcherService struct { - services.StateMachine - lggr logger.Logger - och *webapi.OutgoingConnectorHandler - wrapper gatewayConnector -} - -type gatewayConnector interface { - GetGatewayConnector() connector.GatewayConnector -} - -func NewFetcherService(lggr logger.Logger, wrapper gatewayConnector) *FetcherService { - return &FetcherService{ - lggr: lggr.Named("FetcherService"), - wrapper: wrapper, - } -} - -func (s *FetcherService) Start(ctx context.Context) error { - return s.StartOnce("FetcherService", func() error { - connector := s.wrapper.GetGatewayConnector() - - outgoingConnectorLggr := s.lggr.Named("OutgoingConnectorHandler") - - webAPIConfig := webapi.ServiceConfig{ - RateLimiter: common.RateLimiterConfig{ - GlobalRPS: 100.0, - GlobalBurst: 100, - PerSenderRPS: 100.0, - PerSenderBurst: 100, - }, - } - - och, err := webapi.NewOutgoingConnectorHandler(connector, - webAPIConfig, - capabilities.MethodWorkflowSyncer, outgoingConnectorLggr) - if err != nil { - return fmt.Errorf("could not create outgoing connector handler: %w", err) - } - - s.och = och - return och.Start(ctx) - }) -} - -func (s *FetcherService) Close() error { - return s.StopOnce("FetcherService", func() error { - return s.och.Close() - }) -} - -func (s *FetcherService) HealthReport() map[string]error { - return map[string]error{s.Name(): s.Healthy()} -} - -func (s *FetcherService) Name() string { - return s.lggr.Name() -} - -func hash(url string) string { - h := sha256.New() - h.Write([]byte(url)) - return hex.EncodeToString(h.Sum(nil)) -} - -func (s *FetcherService) Fetch(ctx context.Context, url string) ([]byte, error) { - messageID := strings.Join([]string{ghcapabilities.MethodWorkflowSyncer, hash(url)}, "/") - resp, err := s.och.HandleSingleNodeRequest(ctx, messageID, ghcapabilities.Request{ - URL: url, - Method: http.MethodGet, - }) - if err != nil { - return nil, err - } - - s.lggr.Debugw("received gateway response") - var payload ghcapabilities.Response - err = json.Unmarshal(resp.Body.Payload, &payload) - if err != nil { - return nil, err - } - - if payload.ExecutionError { - return nil, fmt.Errorf("execution error from gateway: %s", payload.ErrorMessage) - } - - return payload.Body, nil -} diff --git a/core/services/workflows/syncer/fetcher_test.go b/core/services/workflows/syncer/fetcher_test.go deleted file mode 100644 index 017b052f8ab..00000000000 --- a/core/services/workflows/syncer/fetcher_test.go +++ /dev/null @@ -1,114 +0,0 @@ -package syncer - -import ( - "context" - "encoding/json" - "strings" - "testing" - - "github.com/stretchr/testify/mock" - "github.com/stretchr/testify/require" - - "github.com/smartcontractkit/chainlink/v2/core/logger" - "github.com/smartcontractkit/chainlink/v2/core/services/gateway/api" - "github.com/smartcontractkit/chainlink/v2/core/services/gateway/connector" - gcmocks "github.com/smartcontractkit/chainlink/v2/core/services/gateway/connector/mocks" - "github.com/smartcontractkit/chainlink/v2/core/services/gateway/handlers/capabilities" - ghcapabilities "github.com/smartcontractkit/chainlink/v2/core/services/gateway/handlers/capabilities" - "github.com/smartcontractkit/chainlink/v2/core/utils/matches" -) - -type wrapper struct { - c connector.GatewayConnector -} - -func (w *wrapper) GetGatewayConnector() connector.GatewayConnector { - return w.c -} - -func TestNewFetcherService(t *testing.T) { - ctx := context.Background() - lggr := logger.TestLogger(t) - - connector := gcmocks.NewGatewayConnector(t) - wrapper := &wrapper{c: connector} - - url := "http://example.com" - - msgID := strings.Join([]string{ghcapabilities.MethodWorkflowSyncer, hash(url)}, "/") - - t.Run("OK-valid_request", func(t *testing.T) { - connector.EXPECT().AddHandler([]string{capabilities.MethodWorkflowSyncer}, mock.Anything).Return(nil) - - fetcher := NewFetcherService(lggr, wrapper) - require.NoError(t, fetcher.Start(ctx)) - defer fetcher.Close() - - gatewayResp := gatewayResponse(t, msgID) - connector.EXPECT().SignAndSendToGateway(mock.Anything, "gateway1", mock.Anything).Run(func(ctx context.Context, gatewayID string, msg *api.MessageBody) { - fetcher.och.HandleGatewayMessage(ctx, "gateway1", gatewayResp) - }).Return(nil).Times(1) - connector.EXPECT().DonID().Return("don-id") - connector.EXPECT().AwaitConnection(matches.AnyContext, "gateway1").Return(nil) - connector.EXPECT().GatewayIDs().Return([]string{"gateway1", "gateway2"}) - - payload, err := fetcher.Fetch(ctx, url) - require.NoError(t, err) - - expectedPayload := []byte("response body") - require.Equal(t, expectedPayload, payload) - }) - - t.Run("NOK-response_payload_too_large", func(t *testing.T) { - headers := map[string]string{"Content-Type": "application/json"} - responsePayload, err := json.Marshal(ghcapabilities.Response{ - StatusCode: 400, - Headers: headers, - ErrorMessage: "http: request body too large", - ExecutionError: true, - }) - require.NoError(t, err) - gatewayResponse := &api.Message{ - Body: api.MessageBody{ - MessageId: msgID, - Method: ghcapabilities.MethodWebAPITarget, - Payload: responsePayload, - }, - } - - connector.EXPECT().AddHandler([]string{capabilities.MethodWorkflowSyncer}, mock.Anything).Return(nil) - - fetcher := NewFetcherService(lggr, wrapper) - require.NoError(t, fetcher.Start(ctx)) - defer fetcher.Close() - - connector.EXPECT().SignAndSendToGateway(mock.Anything, "gateway1", mock.Anything).Run(func(ctx context.Context, gatewayID string, msg *api.MessageBody) { - fetcher.och.HandleGatewayMessage(ctx, "gateway1", gatewayResponse) - }).Return(nil).Times(1) - connector.EXPECT().DonID().Return("don-id") - connector.EXPECT().AwaitConnection(matches.AnyContext, "gateway1").Return(nil) - connector.EXPECT().GatewayIDs().Return([]string{"gateway1", "gateway2"}) - - _, err = fetcher.Fetch(ctx, url) - require.Error(t, err, "execution error from gateway: http: request body too large") - }) -} - -func gatewayResponse(t *testing.T, msgID string) *api.Message { - headers := map[string]string{"Content-Type": "application/json"} - body := []byte("response body") - responsePayload, err := json.Marshal(ghcapabilities.Response{ - StatusCode: 200, - Headers: headers, - Body: body, - ExecutionError: false, - }) - require.NoError(t, err) - return &api.Message{ - Body: api.MessageBody{ - MessageId: msgID, - Method: ghcapabilities.MethodWebAPITarget, - Payload: responsePayload, - }, - } -} diff --git a/core/services/workflows/syncer/handler.go b/core/services/workflows/syncer/handler.go deleted file mode 100644 index cb4f013d502..00000000000 --- a/core/services/workflows/syncer/handler.go +++ /dev/null @@ -1,715 +0,0 @@ -package syncer - -import ( - "bytes" - "context" - "database/sql" - "encoding/base64" - "encoding/hex" - "encoding/json" - "errors" - "fmt" - "sync" - "time" - - "github.com/jonboulle/clockwork" - - "github.com/smartcontractkit/chainlink-common/pkg/custmsg" - "github.com/smartcontractkit/chainlink-common/pkg/services" - "github.com/smartcontractkit/chainlink-common/pkg/types/core" - pkgworkflows "github.com/smartcontractkit/chainlink-common/pkg/workflows" - "github.com/smartcontractkit/chainlink-common/pkg/workflows/secrets" - "github.com/smartcontractkit/chainlink-common/pkg/workflows/wasm/host" - "github.com/smartcontractkit/chainlink/v2/core/logger" - "github.com/smartcontractkit/chainlink/v2/core/platform" - "github.com/smartcontractkit/chainlink/v2/core/services/job" - "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/workflowkey" - "github.com/smartcontractkit/chainlink/v2/core/services/workflows" - "github.com/smartcontractkit/chainlink/v2/core/services/workflows/store" -) - -var ErrNotImplemented = errors.New("not implemented") - -// WorkflowRegistryrEventType is the type of event that is emitted by the WorkflowRegistry -type WorkflowRegistryEventType string - -var ( - // ForceUpdateSecretsEvent is emitted when a request to force update a workflows secrets is made - ForceUpdateSecretsEvent WorkflowRegistryEventType = "WorkflowForceUpdateSecretsRequestedV1" - - // WorkflowRegisteredEvent is emitted when a workflow is registered - WorkflowRegisteredEvent WorkflowRegistryEventType = "WorkflowRegisteredV1" - - // WorkflowUpdatedEvent is emitted when a workflow is updated - WorkflowUpdatedEvent WorkflowRegistryEventType = "WorkflowUpdatedV1" - - // WorkflowPausedEvent is emitted when a workflow is paused - WorkflowPausedEvent WorkflowRegistryEventType = "WorkflowPausedV1" - - // WorkflowActivatedEvent is emitted when a workflow is activated - WorkflowActivatedEvent WorkflowRegistryEventType = "WorkflowActivatedV1" - - // WorkflowDeletedEvent is emitted when a workflow is deleted - WorkflowDeletedEvent WorkflowRegistryEventType = "WorkflowDeletedV1" -) - -// WorkflowRegistryForceUpdateSecretsRequestedV1 is a chain agnostic definition of the WorkflowRegistry -// ForceUpdateSecretsRequested event. -type WorkflowRegistryForceUpdateSecretsRequestedV1 struct { - SecretsURLHash []byte - Owner []byte - WorkflowName string -} - -type WorkflowRegistryWorkflowRegisteredV1 struct { - WorkflowID [32]byte - WorkflowOwner []byte - DonID uint32 - Status uint8 - WorkflowName string - BinaryURL string - ConfigURL string - SecretsURL string -} - -type WorkflowRegistryWorkflowUpdatedV1 struct { - OldWorkflowID [32]byte - WorkflowOwner []byte - DonID uint32 - NewWorkflowID [32]byte - WorkflowName string - BinaryURL string - ConfigURL string - SecretsURL string -} - -type WorkflowRegistryWorkflowPausedV1 struct { - WorkflowID [32]byte - WorkflowOwner []byte - DonID uint32 - WorkflowName string -} - -type WorkflowRegistryWorkflowActivatedV1 struct { - WorkflowID [32]byte - WorkflowOwner []byte - DonID uint32 - WorkflowName string -} - -type WorkflowRegistryWorkflowDeletedV1 struct { - WorkflowID [32]byte - WorkflowOwner []byte - DonID uint32 - WorkflowName string -} - -type lastFetchedAtMap struct { - m map[string]time.Time - sync.RWMutex -} - -func (l *lastFetchedAtMap) Set(url string, at time.Time) { - l.Lock() - defer l.Unlock() - l.m[url] = at -} - -func (l *lastFetchedAtMap) Get(url string) (time.Time, bool) { - l.RLock() - defer l.RUnlock() - got, ok := l.m[url] - return got, ok -} - -func newLastFetchedAtMap() *lastFetchedAtMap { - return &lastFetchedAtMap{ - m: map[string]time.Time{}, - } -} - -type engineFactoryFn func(ctx context.Context, wfid string, owner string, name string, config []byte, binary []byte) (services.Service, error) - -// eventHandler is a handler for WorkflowRegistryEvent events. Each event type has a corresponding -// method that handles the event. -type eventHandler struct { - lggr logger.Logger - orm WorkflowRegistryDS - fetcher FetcherFunc - workflowStore store.Store - capRegistry core.CapabilitiesRegistry - engineRegistry *EngineRegistry - emitter custmsg.MessageEmitter - lastFetchedAtMap *lastFetchedAtMap - clock clockwork.Clock - secretsFreshnessDuration time.Duration - encryptionKey workflowkey.Key - engineFactory engineFactoryFn -} - -type Event interface { - GetEventType() WorkflowRegistryEventType - GetData() any -} - -var defaultSecretsFreshnessDuration = 24 * time.Hour - -func WithEngineRegistry(er *EngineRegistry) func(*eventHandler) { - return func(e *eventHandler) { - e.engineRegistry = er - } -} - -func WithEngineFactoryFn(efn engineFactoryFn) func(*eventHandler) { - return func(e *eventHandler) { - e.engineFactory = efn - } -} - -// NewEventHandler returns a new eventHandler instance. -func NewEventHandler( - lggr logger.Logger, - orm ORM, - gateway FetcherFunc, - workflowStore store.Store, - capRegistry core.CapabilitiesRegistry, - emitter custmsg.MessageEmitter, - clock clockwork.Clock, - encryptionKey workflowkey.Key, - opts ...func(*eventHandler), -) *eventHandler { - eh := &eventHandler{ - lggr: lggr, - orm: orm, - fetcher: gateway, - workflowStore: workflowStore, - capRegistry: capRegistry, - engineRegistry: NewEngineRegistry(), - emitter: emitter, - lastFetchedAtMap: newLastFetchedAtMap(), - clock: clock, - secretsFreshnessDuration: defaultSecretsFreshnessDuration, - encryptionKey: encryptionKey, - } - eh.engineFactory = eh.engineFactoryFn - for _, o := range opts { - o(eh) - } - return eh -} - -func (h *eventHandler) refreshSecrets(ctx context.Context, workflowOwner, workflowName, workflowID, secretsURLHash string) (string, error) { - owner, err := hex.DecodeString(workflowOwner) - if err != nil { - return "", err - } - - decodedHash, err := hex.DecodeString(secretsURLHash) - if err != nil { - return "", err - } - - updatedSecrets, err := h.forceUpdateSecretsEvent( - ctx, - WorkflowRegistryForceUpdateSecretsRequestedV1{ - SecretsURLHash: decodedHash, - Owner: owner, - WorkflowName: name, - }, - ) - if err != nil { - return "", err - } - - return updatedSecrets, nil -} - -func (h *eventHandler) SecretsFor(ctx context.Context, workflowOwner, workflowName, workflowID string) (map[string]string, error) { - secretsURLHash, secretsPayload, err := h.orm.GetContentsByWorkflowID(ctx, workflowID) - if err != nil { - // The workflow record was found, but secrets_id was empty. - // Let's just stub out the response. - if errors.Is(err, ErrEmptySecrets) { - return map[string]string{}, nil - } - - return nil, fmt.Errorf("failed to fetch secrets by workflow ID: %w", err) - } - - lastFetchedAt, ok := h.lastFetchedAtMap.Get(secretsURLHash) - if !ok || h.clock.Now().Sub(lastFetchedAt) > h.secretsFreshnessDuration { - updatedSecrets, innerErr := h.refreshSecrets(ctx, workflowOwner, workflowName, workflowID, secretsURLHash) - if innerErr != nil { - msg := fmt.Sprintf("could not refresh secrets: proceeding with stale secrets for workflowID %s: %s", workflowID, innerErr) - h.lggr.Error(msg) - logCustMsg( - ctx, - h.emitter.With( - platform.KeyWorkflowID, workflowID, - platform.KeyWorkflowName, workflowName, - platform.KeyWorkflowOwner, workflowOwner, - ), - msg, - h.lggr, - ) - } else { - secretsPayload = updatedSecrets - } - } - - res := secrets.EncryptedSecretsResult{} - err = json.Unmarshal([]byte(secretsPayload), &res) - if err != nil { - return nil, fmt.Errorf("could not unmarshal secrets: %w", err) - } - - return secrets.DecryptSecretsForNode( - res, - h.encryptionKey, - workflowOwner, - ) -} - -func (h *eventHandler) Handle(ctx context.Context, event Event) error { - switch event.GetEventType() { - case ForceUpdateSecretsEvent: - payload, ok := event.GetData().(WorkflowRegistryForceUpdateSecretsRequestedV1) - if !ok { - return newHandlerTypeError(event.GetData()) - } - - cma := h.emitter.With( - platform.KeyWorkflowName, payload.WorkflowName, - platform.KeyWorkflowOwner, hex.EncodeToString(payload.Owner), - ) - - if _, err := h.forceUpdateSecretsEvent(ctx, payload); err != nil { - logCustMsg(ctx, cma, fmt.Sprintf("failed to handle force update secrets event: %v", err), h.lggr) - return err - } - - h.lggr.Debugw("handled force update secrets events for URL hash", "urlHash", payload.SecretsURLHash) - return nil - case WorkflowRegisteredEvent: - payload, ok := event.GetData().(WorkflowRegistryWorkflowRegisteredV1) - if !ok { - return newHandlerTypeError(event.GetData()) - } - wfID := hex.EncodeToString(payload.WorkflowID[:]) - - cma := h.emitter.With( - platform.KeyWorkflowID, wfID, - platform.KeyWorkflowName, payload.WorkflowName, - platform.KeyWorkflowOwner, hex.EncodeToString(payload.WorkflowOwner), - ) - - if err := h.workflowRegisteredEvent(ctx, payload); err != nil { - logCustMsg(ctx, cma, fmt.Sprintf("failed to handle workflow registered event: %v", err), h.lggr) - return err - } - - h.lggr.Debugw("handled workflow registration event", "workflowID", wfID) - return nil - case WorkflowUpdatedEvent: - payload, ok := event.GetData().(WorkflowRegistryWorkflowUpdatedV1) - if !ok { - return fmt.Errorf("invalid data type %T for event", event.GetData()) - } - - newWorkflowID := hex.EncodeToString(payload.NewWorkflowID[:]) - cma := h.emitter.With( - platform.KeyWorkflowID, newWorkflowID, - platform.KeyWorkflowName, payload.WorkflowName, - platform.KeyWorkflowOwner, hex.EncodeToString(payload.WorkflowOwner), - ) - - if err := h.workflowUpdatedEvent(ctx, payload); err != nil { - logCustMsg(ctx, cma, fmt.Sprintf("failed to handle workflow updated event: %v", err), h.lggr) - return err - } - - h.lggr.Debugw("handled workflow updated event", "workflowID", newWorkflowID) - return nil - case WorkflowPausedEvent: - payload, ok := event.GetData().(WorkflowRegistryWorkflowPausedV1) - if !ok { - return fmt.Errorf("invalid data type %T for event", event.GetData()) - } - - wfID := hex.EncodeToString(payload.WorkflowID[:]) - - cma := h.emitter.With( - platform.KeyWorkflowID, wfID, - platform.KeyWorkflowName, payload.WorkflowName, - platform.KeyWorkflowOwner, hex.EncodeToString(payload.WorkflowOwner), - ) - - if err := h.workflowPausedEvent(ctx, payload); err != nil { - logCustMsg(ctx, cma, fmt.Sprintf("failed to handle workflow paused event: %v", err), h.lggr) - return err - } - h.lggr.Debugw("handled workflow paused event", "workflowID", wfID) - return nil - case WorkflowActivatedEvent: - payload, ok := event.GetData().(WorkflowRegistryWorkflowActivatedV1) - if !ok { - return fmt.Errorf("invalid data type %T for event", event.GetData()) - } - - wfID := hex.EncodeToString(payload.WorkflowID[:]) - - cma := h.emitter.With( - platform.KeyWorkflowID, wfID, - platform.KeyWorkflowName, payload.WorkflowName, - platform.KeyWorkflowOwner, hex.EncodeToString(payload.WorkflowOwner), - ) - if err := h.workflowActivatedEvent(ctx, payload); err != nil { - logCustMsg(ctx, cma, fmt.Sprintf("failed to handle workflow activated event: %v", err), h.lggr) - return err - } - - h.lggr.Debugw("handled workflow activated event", "workflowID", wfID) - return nil - case WorkflowDeletedEvent: - payload, ok := event.GetData().(WorkflowRegistryWorkflowDeletedV1) - if !ok { - return fmt.Errorf("invalid data type %T for event", event.GetData()) - } - - wfID := hex.EncodeToString(payload.WorkflowID[:]) - - cma := h.emitter.With( - platform.KeyWorkflowID, wfID, - platform.KeyWorkflowName, payload.WorkflowName, - platform.KeyWorkflowOwner, hex.EncodeToString(payload.WorkflowOwner), - ) - - if err := h.workflowDeletedEvent(ctx, payload); err != nil { - logCustMsg(ctx, cma, fmt.Sprintf("failed to handle workflow deleted event: %v", err), h.lggr) - return err - } - - h.lggr.Debugw("handled workflow deleted event", "workflowID", wfID) - return nil - default: - return fmt.Errorf("event type unsupported: %v", event.GetEventType()) - } -} - -// workflowRegisteredEvent handles the WorkflowRegisteredEvent event type. -func (h *eventHandler) workflowRegisteredEvent( - ctx context.Context, - payload WorkflowRegistryWorkflowRegisteredV1, -) error { - // Fetch the workflow artifacts from the database or download them from the specified URLs - decodedBinary, config, err := h.getWorkflowArtifacts(ctx, payload) - if err != nil { - return err - } - - // Always fetch secrets from the SecretsURL - var secrets []byte - if payload.SecretsURL != "" { - secrets, err = h.fetcher(ctx, payload.SecretsURL) - if err != nil { - return fmt.Errorf("failed to fetch secrets from %s : %w", payload.SecretsURL, err) - } - } - - // Calculate the hash of the binary and config files - hash, err := pkgworkflows.GenerateWorkflowID(payload.WorkflowOwner, payload.WorkflowName, decodedBinary, config, payload.SecretsURL) - if err != nil { - return fmt.Errorf("failed to generate workflow id: %w", err) - } - - // Pre-check: verify that the workflowID matches; if it doesn’t abort and log an error via Beholder. - if !bytes.Equal(hash[:], payload.WorkflowID[:]) { - return fmt.Errorf("workflowID mismatch: %x != %x", hash, payload.WorkflowID) - } - - // Ensure that there is no running workflow engine for the given workflow ID. - if h.engineRegistry.IsRunning(hex.EncodeToString(payload.WorkflowID[:])) { - return fmt.Errorf("workflow is already running, so not starting it : %s", hex.EncodeToString(payload.WorkflowID[:])) - } - - // Save the workflow secrets - urlHash, err := h.orm.GetSecretsURLHash(payload.WorkflowOwner, []byte(payload.SecretsURL)) - if err != nil { - return fmt.Errorf("failed to get secrets URL hash: %w", err) - } - - // Create a new entry in the workflow_spec table corresponding for the new workflow, with the contents of the binaryURL + configURL in the table - status := job.WorkflowSpecStatusActive - if payload.Status == 1 { - status = job.WorkflowSpecStatusPaused - } - - wfID := hex.EncodeToString(payload.WorkflowID[:]) - owner := hex.EncodeToString(payload.WorkflowOwner) - entry := &job.WorkflowSpec{ - Workflow: hex.EncodeToString(decodedBinary), - Config: string(config), - WorkflowID: wfID, - Status: status, - WorkflowOwner: owner, - WorkflowName: payload.WorkflowName, - SpecType: job.WASMFile, - BinaryURL: payload.BinaryURL, - ConfigURL: payload.ConfigURL, - } - if _, err = h.orm.UpsertWorkflowSpecWithSecrets(ctx, entry, payload.SecretsURL, hex.EncodeToString(urlHash), string(secrets)); err != nil { - return fmt.Errorf("failed to upsert workflow spec with secrets: %w", err) - } - - if status != job.WorkflowSpecStatusActive { - h.lggr.Debugw("workflow is marked as paused, so not starting it", "workflow", wfID) - return nil - } - - // If status == active, start a new WorkflowEngine instance, and add it to local engine registry - engine, err := h.engineFactory( - ctx, - wfID, - owner, - payload.WorkflowName, - config, - decodedBinary, - ) - if err != nil { - return fmt.Errorf("failed to create workflow engine: %w", err) - } - - if err := engine.Start(ctx); err != nil { - return fmt.Errorf("failed to start workflow engine: %w", err) - } - - h.engineRegistry.Add(wfID, engine) - - return nil -} - -// getWorkflowArtifacts retrieves the workflow artifacts from the database if they exist, -// or downloads them from the specified URLs if they are not found in the database. -func (h *eventHandler) getWorkflowArtifacts( - ctx context.Context, - payload WorkflowRegistryWorkflowRegisteredV1, -) ([]byte, []byte, error) { - spec, err := h.orm.GetWorkflowSpecByID(ctx, hex.EncodeToString(payload.WorkflowID[:])) - if err != nil { - binary, err2 := h.fetcher(ctx, payload.BinaryURL) - if err2 != nil { - return nil, nil, fmt.Errorf("failed to fetch binary from %s : %w", payload.BinaryURL, err2) - } - - decodedBinary, err2 := base64.StdEncoding.DecodeString(string(binary)) - if err2 != nil { - return nil, nil, fmt.Errorf("failed to decode binary: %w", err2) - } - - var config []byte - if payload.ConfigURL != "" { - config, err2 = h.fetcher(ctx, payload.ConfigURL) - if err2 != nil { - return nil, nil, fmt.Errorf("failed to fetch config from %s : %w", payload.ConfigURL, err2) - } - } - return decodedBinary, config, nil - } - - // there is no update in the BinaryURL or ConfigURL, lets decode the stored artifacts - decodedBinary, err := hex.DecodeString(spec.Workflow) - if err != nil { - return nil, nil, fmt.Errorf("failed to decode stored workflow spec: %w", err) - } - return decodedBinary, []byte(spec.Config), nil -} - -func (h *eventHandler) engineFactoryFn(ctx context.Context, id string, owner string, name string, config []byte, binary []byte) (services.Service, error) { - moduleConfig := &host.ModuleConfig{Logger: h.lggr, Labeler: h.emitter} - sdkSpec, err := host.GetWorkflowSpec(ctx, moduleConfig, binary, config) - if err != nil { - return nil, fmt.Errorf("failed to get workflow sdk spec: %w", err) - } - - cfg := workflows.Config{ - Lggr: h.lggr, - Workflow: *sdkSpec, - WorkflowID: id, - WorkflowOwner: owner, // this gets hex encoded in the engine. - WorkflowName: name, - Registry: h.capRegistry, - Store: h.workflowStore, - Config: config, - Binary: binary, - SecretsFetcher: h, - } - return workflows.NewEngine(ctx, cfg) -} - -// workflowUpdatedEvent handles the WorkflowUpdatedEvent event type by first finding the -// current workflow engine, stopping it, and then starting a new workflow engine with the -// updated workflow spec. -func (h *eventHandler) workflowUpdatedEvent( - ctx context.Context, - payload WorkflowRegistryWorkflowUpdatedV1, -) error { - // Remove the old workflow engine from the local registry if it exists - if err := h.tryEngineCleanup(hex.EncodeToString(payload.OldWorkflowID[:])); err != nil { - return err - } - - registeredEvent := WorkflowRegistryWorkflowRegisteredV1{ - WorkflowID: payload.NewWorkflowID, - WorkflowOwner: payload.WorkflowOwner, - DonID: payload.DonID, - Status: 0, - WorkflowName: payload.WorkflowName, - BinaryURL: payload.BinaryURL, - ConfigURL: payload.ConfigURL, - SecretsURL: payload.SecretsURL, - } - - return h.workflowRegisteredEvent(ctx, registeredEvent) -} - -// workflowPausedEvent handles the WorkflowPausedEvent event type. -func (h *eventHandler) workflowPausedEvent( - ctx context.Context, - payload WorkflowRegistryWorkflowPausedV1, -) error { - // Remove the workflow engine from the local registry if it exists - if err := h.tryEngineCleanup(hex.EncodeToString(payload.WorkflowID[:])); err != nil { - return err - } - - // get existing workflow spec from DB - spec, err := h.orm.GetWorkflowSpec(ctx, hex.EncodeToString(payload.WorkflowOwner), payload.WorkflowName) - if err != nil { - return fmt.Errorf("failed to get workflow spec: %w", err) - } - - // update the status of the workflow spec - spec.Status = job.WorkflowSpecStatusPaused - if _, err := h.orm.UpsertWorkflowSpec(ctx, spec); err != nil { - return fmt.Errorf("failed to update workflow spec: %w", err) - } - - return nil -} - -// workflowActivatedEvent handles the WorkflowActivatedEvent event type. -func (h *eventHandler) workflowActivatedEvent( - ctx context.Context, - payload WorkflowRegistryWorkflowActivatedV1, -) error { - // fetch the workflow spec from the DB - spec, err := h.orm.GetWorkflowSpec(ctx, hex.EncodeToString(payload.WorkflowOwner), payload.WorkflowName) - if err != nil { - return fmt.Errorf("failed to get workflow spec: %w", err) - } - - // Do nothing if the workflow is already active - if spec.Status == job.WorkflowSpecStatusActive && h.engineRegistry.IsRunning(hex.EncodeToString(payload.WorkflowID[:])) { - return nil - } - - // get the secrets url by the secrets id - secretsURL, err := h.orm.GetSecretsURLByID(ctx, spec.SecretsID.Int64) - if err != nil { - return fmt.Errorf("failed to get secrets URL by ID: %w", err) - } - - // start a new workflow engine - registeredEvent := WorkflowRegistryWorkflowRegisteredV1{ - WorkflowID: payload.WorkflowID, - WorkflowOwner: payload.WorkflowOwner, - DonID: payload.DonID, - Status: 0, - WorkflowName: payload.WorkflowName, - BinaryURL: spec.BinaryURL, - ConfigURL: spec.ConfigURL, - SecretsURL: secretsURL, - } - - return h.workflowRegisteredEvent(ctx, registeredEvent) -} - -// workflowDeletedEvent handles the WorkflowDeletedEvent event type. -func (h *eventHandler) workflowDeletedEvent( - ctx context.Context, - payload WorkflowRegistryWorkflowDeletedV1, -) error { - if err := h.tryEngineCleanup(hex.EncodeToString(payload.WorkflowID[:])); err != nil { - return err - } - - err := h.orm.DeleteWorkflowSpec(ctx, hex.EncodeToString(payload.WorkflowOwner), payload.WorkflowName) - if err != nil { - if errors.Is(err, sql.ErrNoRows) { - h.lggr.Warnw("workflow spec not found", "workflowID", hex.EncodeToString(payload.WorkflowID[:])) - return nil - } - return fmt.Errorf("failed to delete workflow spec: %w", err) - } - - return nil -} - -// forceUpdateSecretsEvent handles the ForceUpdateSecretsEvent event type. -func (h *eventHandler) forceUpdateSecretsEvent( - ctx context.Context, - payload WorkflowRegistryForceUpdateSecretsRequestedV1, -) (string, error) { - // Get the URL of the secrets file from the event data - hash := hex.EncodeToString(payload.SecretsURLHash) - - url, err := h.orm.GetSecretsURLByHash(ctx, hash) - if err != nil { - return "", fmt.Errorf("failed to get URL by hash %s : %w", hash, err) - } - - // Fetch the contents of the secrets file from the url via the fetcher - secrets, err := h.fetcher(ctx, url) - if err != nil { - return "", err - } - - h.lastFetchedAtMap.Set(hash, h.clock.Now()) - - // Update the secrets in the ORM - if _, err := h.orm.Update(ctx, hash, string(secrets)); err != nil { - return "", fmt.Errorf("failed to update secrets: %w", err) - } - - return string(secrets), nil -} - -// tryEngineCleanup attempts to stop the workflow engine for the given workflow ID. Does nothing if the -// workflow engine is not running. -func (h *eventHandler) tryEngineCleanup(wfID string) error { - if h.engineRegistry.IsRunning(wfID) { - // Remove the engine from the registry - e, err := h.engineRegistry.Pop(wfID) - if err != nil { - return fmt.Errorf("failed to get workflow engine: %w", err) - } - - // Stop the engine - if err := e.Close(); err != nil { - return fmt.Errorf("failed to close workflow engine: %w", err) - } - } - return nil -} - -// logCustMsg emits a custom message to the external sink and logs an error if that fails. -func logCustMsg(ctx context.Context, cma custmsg.MessageEmitter, msg string, log logger.Logger) { - err := cma.Emit(ctx, msg) - if err != nil { - log.Helper(1).Errorf("failed to send custom message with msg: %s, err: %v", msg, err) - } -} - -func newHandlerTypeError(data any) error { - return fmt.Errorf("invalid data type %T for event", data) -} diff --git a/core/services/workflows/syncer/handler_test.go b/core/services/workflows/syncer/handler_test.go deleted file mode 100644 index 994b820b5ce..00000000000 --- a/core/services/workflows/syncer/handler_test.go +++ /dev/null @@ -1,992 +0,0 @@ -package syncer - -import ( - "context" - "database/sql" - "encoding/base64" - "encoding/hex" - "encoding/json" - "errors" - "testing" - "time" - - "github.com/smartcontractkit/chainlink-common/pkg/custmsg" - "github.com/smartcontractkit/chainlink-common/pkg/services" - pkgworkflows "github.com/smartcontractkit/chainlink-common/pkg/workflows" - "github.com/smartcontractkit/chainlink-common/pkg/workflows/secrets" - "github.com/smartcontractkit/chainlink/v2/core/capabilities" - "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" - "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest" - "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/wasmtest" - "github.com/smartcontractkit/chainlink/v2/core/logger" - "github.com/smartcontractkit/chainlink/v2/core/services/job" - "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/workflowkey" - wfstore "github.com/smartcontractkit/chainlink/v2/core/services/workflows/store" - "github.com/smartcontractkit/chainlink/v2/core/services/workflows/syncer/mocks" - "github.com/smartcontractkit/chainlink/v2/core/utils/crypto" - "github.com/smartcontractkit/chainlink/v2/core/utils/matches" - - "github.com/jonboulle/clockwork" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" -) - -type mockFetchResp struct { - Body []byte - Err error -} - -type mockFetcher struct { - responseMap map[string]mockFetchResp -} - -func (m *mockFetcher) Fetch(_ context.Context, url string) ([]byte, error) { - return m.responseMap[url].Body, m.responseMap[url].Err -} - -func newMockFetcher(m map[string]mockFetchResp) FetcherFunc { - return (&mockFetcher{responseMap: m}).Fetch -} - -type mockEngine struct { - CloseErr error - ReadyErr error - StartErr error -} - -func (m *mockEngine) Ready() error { - return m.ReadyErr -} - -func (m *mockEngine) Close() error { - return m.CloseErr -} - -func (m *mockEngine) Start(_ context.Context) error { - return m.StartErr -} - -func (m *mockEngine) HealthReport() map[string]error { return nil } - -func (m *mockEngine) Name() string { return "mockEngine" } - -func Test_Handler(t *testing.T) { - lggr := logger.TestLogger(t) - emitter := custmsg.NewLabeler() - t.Run("success", func(t *testing.T) { - mockORM := mocks.NewORM(t) - ctx := testutils.Context(t) - giveURL := "https://original-url.com" - giveBytes, err := crypto.Keccak256([]byte(giveURL)) - require.NoError(t, err) - - giveHash := hex.EncodeToString(giveBytes) - - giveEvent := WorkflowRegistryEvent{ - EventType: ForceUpdateSecretsEvent, - Data: WorkflowRegistryForceUpdateSecretsRequestedV1{ - SecretsURLHash: giveBytes, - }, - } - - fetcher := func(_ context.Context, _ string) ([]byte, error) { - return []byte("contents"), nil - } - mockORM.EXPECT().GetSecretsURLByHash(matches.AnyContext, giveHash).Return(giveURL, nil) - mockORM.EXPECT().Update(matches.AnyContext, giveHash, "contents").Return(int64(1), nil) - h := NewEventHandler(lggr, mockORM, fetcher, nil, nil, emitter, clockwork.NewFakeClock(), workflowkey.Key{}) - err = h.Handle(ctx, giveEvent) - require.NoError(t, err) - }) - - t.Run("fails with unsupported event type", func(t *testing.T) { - mockORM := mocks.NewORM(t) - ctx := testutils.Context(t) - - giveEvent := WorkflowRegistryEvent{} - fetcher := func(_ context.Context, _ string) ([]byte, error) { - return []byte("contents"), nil - } - - h := NewEventHandler(lggr, mockORM, fetcher, nil, nil, emitter, clockwork.NewFakeClock(), workflowkey.Key{}) - err := h.Handle(ctx, giveEvent) - require.Error(t, err) - require.Contains(t, err.Error(), "event type unsupported") - }) - - t.Run("fails to get secrets url", func(t *testing.T) { - mockORM := mocks.NewORM(t) - ctx := testutils.Context(t) - h := NewEventHandler(lggr, mockORM, nil, nil, nil, emitter, clockwork.NewFakeClock(), workflowkey.Key{}) - giveURL := "https://original-url.com" - giveBytes, err := crypto.Keccak256([]byte(giveURL)) - require.NoError(t, err) - - giveHash := hex.EncodeToString(giveBytes) - - giveEvent := WorkflowRegistryEvent{ - EventType: ForceUpdateSecretsEvent, - Data: WorkflowRegistryForceUpdateSecretsRequestedV1{ - SecretsURLHash: giveBytes, - }, - } - mockORM.EXPECT().GetSecretsURLByHash(matches.AnyContext, giveHash).Return("", assert.AnError) - err = h.Handle(ctx, giveEvent) - require.Error(t, err) - require.ErrorContains(t, err, assert.AnError.Error()) - }) - - t.Run("fails to fetch contents", func(t *testing.T) { - mockORM := mocks.NewORM(t) - ctx := testutils.Context(t) - giveURL := "http://example.com" - - giveBytes, err := crypto.Keccak256([]byte(giveURL)) - require.NoError(t, err) - - giveHash := hex.EncodeToString(giveBytes) - - giveEvent := WorkflowRegistryEvent{ - EventType: ForceUpdateSecretsEvent, - Data: WorkflowRegistryForceUpdateSecretsRequestedV1{ - SecretsURLHash: giveBytes, - }, - } - - fetcher := func(_ context.Context, _ string) ([]byte, error) { - return nil, assert.AnError - } - mockORM.EXPECT().GetSecretsURLByHash(matches.AnyContext, giveHash).Return(giveURL, nil) - h := NewEventHandler(lggr, mockORM, fetcher, nil, nil, emitter, clockwork.NewFakeClock(), workflowkey.Key{}) - err = h.Handle(ctx, giveEvent) - require.Error(t, err) - require.ErrorIs(t, err, assert.AnError) - }) - - t.Run("fails to update secrets", func(t *testing.T) { - mockORM := mocks.NewORM(t) - ctx := testutils.Context(t) - giveURL := "http://example.com" - giveBytes, err := crypto.Keccak256([]byte(giveURL)) - require.NoError(t, err) - - giveHash := hex.EncodeToString(giveBytes) - - giveEvent := WorkflowRegistryEvent{ - EventType: ForceUpdateSecretsEvent, - Data: WorkflowRegistryForceUpdateSecretsRequestedV1{ - SecretsURLHash: giveBytes, - }, - } - - fetcher := func(_ context.Context, _ string) ([]byte, error) { - return []byte("contents"), nil - } - mockORM.EXPECT().GetSecretsURLByHash(matches.AnyContext, giveHash).Return(giveURL, nil) - mockORM.EXPECT().Update(matches.AnyContext, giveHash, "contents").Return(0, assert.AnError) - h := NewEventHandler(lggr, mockORM, fetcher, nil, nil, emitter, clockwork.NewFakeClock(), workflowkey.Key{}) - err = h.Handle(ctx, giveEvent) - require.Error(t, err) - require.ErrorIs(t, err, assert.AnError) - }) -} - -const ( - binaryLocation = "test/simple/cmd/testmodule.wasm" - binaryCmd = "core/capabilities/compute/test/simple/cmd" -) - -func Test_workflowRegisteredHandler(t *testing.T) { - var binaryURL = "http://example.com/binary" - var secretsURL = "http://example.com/secrets" - var configURL = "http://example.com/config" - var config = []byte("") - var wfOwner = []byte("0xOwner") - var binary = wasmtest.CreateTestBinary(binaryCmd, binaryLocation, true, t) - var encodedBinary = []byte(base64.StdEncoding.EncodeToString(binary)) - - defaultValidationFn := func(t *testing.T, ctx context.Context, event WorkflowRegistryWorkflowRegisteredV1, h *eventHandler, wfOwner []byte, wfName string, wfID string) { - err := h.workflowRegisteredEvent(ctx, event) - require.NoError(t, err) - - // Verify the record is updated in the database - dbSpec, err := h.orm.GetWorkflowSpec(ctx, hex.EncodeToString(wfOwner), "workflow-name") - require.NoError(t, err) - require.Equal(t, hex.EncodeToString(wfOwner), dbSpec.WorkflowOwner) - require.Equal(t, "workflow-name", dbSpec.WorkflowName) - require.Equal(t, job.WorkflowSpecStatusActive, dbSpec.Status) - - // Verify the engine is started - engine, err := h.engineRegistry.Get(wfID) - require.NoError(t, err) - err = engine.Ready() - require.NoError(t, err) - } - - var tt = []testCase{ - { - Name: "success with active workflow registered", - fetcher: newMockFetcher(map[string]mockFetchResp{ - binaryURL: {Body: encodedBinary, Err: nil}, - configURL: {Body: config, Err: nil}, - secretsURL: {Body: []byte("secrets"), Err: nil}, - }), - engineFactoryFn: func(ctx context.Context, wfid string, owner string, name string, config []byte, binary []byte) (services.Service, error) { - return &mockEngine{}, nil - }, - GiveConfig: config, - ConfigURL: configURL, - SecretsURL: secretsURL, - BinaryURL: binaryURL, - GiveBinary: binary, - WFOwner: wfOwner, - Event: func(wfID []byte) WorkflowRegistryWorkflowRegisteredV1 { - return WorkflowRegistryWorkflowRegisteredV1{ - Status: uint8(0), - WorkflowID: [32]byte(wfID), - WorkflowOwner: wfOwner, - WorkflowName: "workflow-name", - BinaryURL: binaryURL, - ConfigURL: configURL, - SecretsURL: secretsURL, - } - }, - validationFn: defaultValidationFn, - }, - { - Name: "fails to start engine", - fetcher: newMockFetcher(map[string]mockFetchResp{ - binaryURL: {Body: encodedBinary, Err: nil}, - configURL: {Body: config, Err: nil}, - secretsURL: {Body: []byte("secrets"), Err: nil}, - }), - engineFactoryFn: func(ctx context.Context, wfid string, owner string, name string, config []byte, binary []byte) (services.Service, error) { - return &mockEngine{StartErr: assert.AnError}, nil - }, - GiveConfig: config, - ConfigURL: configURL, - SecretsURL: secretsURL, - BinaryURL: binaryURL, - GiveBinary: binary, - WFOwner: wfOwner, - Event: func(wfID []byte) WorkflowRegistryWorkflowRegisteredV1 { - return WorkflowRegistryWorkflowRegisteredV1{ - Status: uint8(0), - WorkflowID: [32]byte(wfID), - WorkflowOwner: wfOwner, - WorkflowName: "workflow-name", - BinaryURL: binaryURL, - ConfigURL: configURL, - SecretsURL: secretsURL, - } - }, - validationFn: func(t *testing.T, ctx context.Context, event WorkflowRegistryWorkflowRegisteredV1, h *eventHandler, wfOwner []byte, wfName string, wfID string) { - err := h.workflowRegisteredEvent(ctx, event) - require.Error(t, err) - require.ErrorIs(t, err, assert.AnError) - }, - }, - { - Name: "fails if running engine exists", - fetcher: newMockFetcher(map[string]mockFetchResp{ - binaryURL: {Body: encodedBinary, Err: nil}, - configURL: {Body: config, Err: nil}, - secretsURL: {Body: []byte("secrets"), Err: nil}, - }), - GiveConfig: config, - ConfigURL: configURL, - SecretsURL: secretsURL, - BinaryURL: binaryURL, - GiveBinary: binary, - WFOwner: wfOwner, - Event: func(wfID []byte) WorkflowRegistryWorkflowRegisteredV1 { - return WorkflowRegistryWorkflowRegisteredV1{ - Status: uint8(0), - WorkflowID: [32]byte(wfID), - WorkflowOwner: wfOwner, - WorkflowName: "workflow-name", - BinaryURL: binaryURL, - ConfigURL: configURL, - SecretsURL: secretsURL, - } - }, - validationFn: func(t *testing.T, ctx context.Context, event WorkflowRegistryWorkflowRegisteredV1, h *eventHandler, wfOwner []byte, wfName string, wfID string) { - me := &mockEngine{} - h.engineRegistry.Add(wfID, me) - err := h.workflowRegisteredEvent(ctx, event) - require.Error(t, err) - require.ErrorContains(t, err, "workflow is already running") - }, - }, - { - Name: "success with paused workflow registered", - fetcher: newMockFetcher(map[string]mockFetchResp{ - binaryURL: {Body: encodedBinary, Err: nil}, - configURL: {Body: config, Err: nil}, - secretsURL: {Body: []byte("secrets"), Err: nil}, - }), - GiveConfig: config, - ConfigURL: configURL, - SecretsURL: secretsURL, - BinaryURL: binaryURL, - GiveBinary: binary, - WFOwner: wfOwner, - Event: func(wfID []byte) WorkflowRegistryWorkflowRegisteredV1 { - return WorkflowRegistryWorkflowRegisteredV1{ - Status: uint8(1), - WorkflowID: [32]byte(wfID), - WorkflowOwner: wfOwner, - WorkflowName: "workflow-name", - BinaryURL: binaryURL, - ConfigURL: configURL, - SecretsURL: secretsURL, - } - }, - validationFn: func(t *testing.T, ctx context.Context, event WorkflowRegistryWorkflowRegisteredV1, h *eventHandler, wfOwner []byte, wfName string, wfID string) { - err := h.workflowRegisteredEvent(ctx, event) - require.NoError(t, err) - - // Verify the record is updated in the database - dbSpec, err := h.orm.GetWorkflowSpec(ctx, hex.EncodeToString(wfOwner), "workflow-name") - require.NoError(t, err) - require.Equal(t, hex.EncodeToString(wfOwner), dbSpec.WorkflowOwner) - require.Equal(t, "workflow-name", dbSpec.WorkflowName) - require.Equal(t, job.WorkflowSpecStatusPaused, dbSpec.Status) - - // Verify there is no running engine - _, err = h.engineRegistry.Get(wfID) - require.Error(t, err) - }, - }, - { - Name: "skips fetch if config url is missing", - GiveConfig: make([]byte, 0), - ConfigURL: "", - SecretsURL: secretsURL, - BinaryURL: binaryURL, - GiveBinary: binary, - WFOwner: wfOwner, - fetcher: newMockFetcher(map[string]mockFetchResp{ - binaryURL: {Body: encodedBinary, Err: nil}, - secretsURL: {Body: []byte("secrets"), Err: nil}, - }), - validationFn: defaultValidationFn, - Event: func(wfID []byte) WorkflowRegistryWorkflowRegisteredV1 { - return WorkflowRegistryWorkflowRegisteredV1{ - Status: uint8(0), - WorkflowID: [32]byte(wfID), - WorkflowOwner: wfOwner, - WorkflowName: "workflow-name", - BinaryURL: binaryURL, - SecretsURL: secretsURL, - } - }, - }, - { - Name: "skips fetch if secrets url is missing", - GiveConfig: config, - ConfigURL: configURL, - BinaryURL: binaryURL, - GiveBinary: binary, - WFOwner: wfOwner, - fetcher: newMockFetcher(map[string]mockFetchResp{ - binaryURL: {Body: encodedBinary, Err: nil}, - configURL: {Body: config, Err: nil}, - }), - validationFn: defaultValidationFn, - Event: func(wfID []byte) WorkflowRegistryWorkflowRegisteredV1 { - return WorkflowRegistryWorkflowRegisteredV1{ - Status: uint8(0), - WorkflowID: [32]byte(wfID), - WorkflowOwner: wfOwner, - WorkflowName: "workflow-name", - BinaryURL: binaryURL, - ConfigURL: configURL, - } - }, - }, - } - - for _, tc := range tt { - testRunningWorkflow(t, tc) - } -} - -type testCase struct { - Name string - SecretsURL string - BinaryURL string - GiveBinary []byte - GiveConfig []byte - ConfigURL string - WFOwner []byte - fetcher FetcherFunc - Event func([]byte) WorkflowRegistryWorkflowRegisteredV1 - validationFn func(t *testing.T, ctx context.Context, event WorkflowRegistryWorkflowRegisteredV1, h *eventHandler, wfOwner []byte, wfName string, wfID string) - engineFactoryFn func(ctx context.Context, wfid string, owner string, name string, config []byte, binary []byte) (services.Service, error) -} - -func testRunningWorkflow(t *testing.T, tc testCase) { - t.Helper() - t.Run(tc.Name, func(t *testing.T) { - var ( - ctx = testutils.Context(t) - lggr = logger.TestLogger(t) - db = pgtest.NewSqlxDB(t) - orm = NewWorkflowRegistryDS(db, lggr) - emitter = custmsg.NewLabeler() - - binary = tc.GiveBinary - config = tc.GiveConfig - secretsURL = tc.SecretsURL - wfOwner = tc.WFOwner - - fetcher = tc.fetcher - ) - - giveWFID, err := pkgworkflows.GenerateWorkflowID(wfOwner, "workflow-name", binary, config, secretsURL) - require.NoError(t, err) - - wfID := hex.EncodeToString(giveWFID[:]) - - event := tc.Event(giveWFID[:]) - - er := NewEngineRegistry() - opts := []func(*eventHandler){ - WithEngineRegistry(er), - } - if tc.engineFactoryFn != nil { - opts = append(opts, WithEngineFactoryFn(tc.engineFactoryFn)) - } - store := wfstore.NewDBStore(db, lggr, clockwork.NewFakeClock()) - registry := capabilities.NewRegistry(lggr) - registry.SetLocalRegistry(&capabilities.TestMetadataRegistry{}) - h := NewEventHandler(lggr, orm, fetcher, store, registry, emitter, clockwork.NewFakeClock(), - workflowkey.Key{}, opts...) - - tc.validationFn(t, ctx, event, h, wfOwner, "workflow-name", wfID) - }) -} - -func Test_workflowDeletedHandler(t *testing.T) { - t.Run("success deleting existing engine and spec", func(t *testing.T) { - var ( - ctx = testutils.Context(t) - lggr = logger.TestLogger(t) - db = pgtest.NewSqlxDB(t) - orm = NewWorkflowRegistryDS(db, lggr) - emitter = custmsg.NewLabeler() - - binary = wasmtest.CreateTestBinary(binaryCmd, binaryLocation, true, t) - encodedBinary = []byte(base64.StdEncoding.EncodeToString(binary)) - config = []byte("") - secretsURL = "http://example.com" - binaryURL = "http://example.com/binary" - configURL = "http://example.com/config" - wfOwner = []byte("0xOwner") - - fetcher = newMockFetcher(map[string]mockFetchResp{ - binaryURL: {Body: encodedBinary, Err: nil}, - configURL: {Body: config, Err: nil}, - secretsURL: {Body: []byte("secrets"), Err: nil}, - }) - ) - - giveWFID, err := pkgworkflows.GenerateWorkflowID(wfOwner, "workflow-name", binary, config, secretsURL) - - require.NoError(t, err) - wfIDs := hex.EncodeToString(giveWFID[:]) - - active := WorkflowRegistryWorkflowRegisteredV1{ - Status: uint8(0), - WorkflowID: giveWFID, - WorkflowOwner: wfOwner, - WorkflowName: "workflow-name", - BinaryURL: binaryURL, - ConfigURL: configURL, - SecretsURL: secretsURL, - } - - er := NewEngineRegistry() - store := wfstore.NewDBStore(db, lggr, clockwork.NewFakeClock()) - registry := capabilities.NewRegistry(lggr) - registry.SetLocalRegistry(&capabilities.TestMetadataRegistry{}) - h := NewEventHandler( - lggr, - orm, - fetcher, - store, - registry, - emitter, - clockwork.NewFakeClock(), - workflowkey.Key{}, - WithEngineRegistry(er), - ) - err = h.workflowRegisteredEvent(ctx, active) - require.NoError(t, err) - - // Verify the record is updated in the database - dbSpec, err := orm.GetWorkflowSpec(ctx, hex.EncodeToString(wfOwner), "workflow-name") - require.NoError(t, err) - require.Equal(t, hex.EncodeToString(wfOwner), dbSpec.WorkflowOwner) - require.Equal(t, "workflow-name", dbSpec.WorkflowName) - require.Equal(t, job.WorkflowSpecStatusActive, dbSpec.Status) - - // Verify the engine is started - engine, err := h.engineRegistry.Get(wfIDs) - require.NoError(t, err) - err = engine.Ready() - require.NoError(t, err) - - deleteEvent := WorkflowRegistryWorkflowDeletedV1{ - WorkflowID: giveWFID, - WorkflowOwner: wfOwner, - WorkflowName: "workflow-name", - DonID: 1, - } - err = h.workflowDeletedEvent(ctx, deleteEvent) - require.NoError(t, err) - - // Verify the record is deleted in the database - _, err = orm.GetWorkflowSpec(ctx, hex.EncodeToString(wfOwner), "workflow-name") - require.Error(t, err) - - // Verify the engine is deleted - _, err = h.engineRegistry.Get(wfIDs) - require.Error(t, err) - }) - t.Run("success deleting non-existing workflow spec", func(t *testing.T) { - var ( - ctx = testutils.Context(t) - lggr = logger.TestLogger(t) - db = pgtest.NewSqlxDB(t) - orm = NewWorkflowRegistryDS(db, lggr) - emitter = custmsg.NewLabeler() - - binary = wasmtest.CreateTestBinary(binaryCmd, binaryLocation, true, t) - encodedBinary = []byte(base64.StdEncoding.EncodeToString(binary)) - config = []byte("") - secretsURL = "http://example.com" - binaryURL = "http://example.com/binary" - configURL = "http://example.com/config" - wfOwner = []byte("0xOwner") - - fetcher = newMockFetcher(map[string]mockFetchResp{ - binaryURL: {Body: encodedBinary, Err: nil}, - configURL: {Body: config, Err: nil}, - secretsURL: {Body: []byte("secrets"), Err: nil}, - }) - ) - - giveWFID, err := pkgworkflows.GenerateWorkflowID(wfOwner, "workflow-name", binary, config, secretsURL) - require.NoError(t, err) - - er := NewEngineRegistry() - store := wfstore.NewDBStore(db, lggr, clockwork.NewFakeClock()) - registry := capabilities.NewRegistry(lggr) - registry.SetLocalRegistry(&capabilities.TestMetadataRegistry{}) - h := NewEventHandler( - lggr, - orm, - fetcher, - store, - registry, - emitter, - clockwork.NewFakeClock(), - workflowkey.Key{}, - WithEngineRegistry(er), - ) - - deleteEvent := WorkflowRegistryWorkflowDeletedV1{ - WorkflowID: giveWFID, - WorkflowOwner: wfOwner, - WorkflowName: "workflow-name", - DonID: 1, - } - err = h.workflowDeletedEvent(ctx, deleteEvent) - require.NoError(t, err) - - // Verify the record is deleted in the database - _, err = orm.GetWorkflowSpec(ctx, hex.EncodeToString(wfOwner), "workflow-name") - require.Error(t, err) - }) -} - -func Test_workflowPausedActivatedUpdatedHandler(t *testing.T) { - t.Run("success pausing activating and updating existing engine and spec", func(t *testing.T) { - var ( - ctx = testutils.Context(t) - lggr = logger.TestLogger(t) - db = pgtest.NewSqlxDB(t) - orm = NewWorkflowRegistryDS(db, lggr) - emitter = custmsg.NewLabeler() - - binary = wasmtest.CreateTestBinary(binaryCmd, binaryLocation, true, t) - encodedBinary = []byte(base64.StdEncoding.EncodeToString(binary)) - config = []byte("") - updateConfig = []byte("updated") - secretsURL = "http://example.com" - binaryURL = "http://example.com/binary" - configURL = "http://example.com/config" - newConfigURL = "http://example.com/new-config" - wfOwner = []byte("0xOwner") - - fetcher = newMockFetcher(map[string]mockFetchResp{ - binaryURL: {Body: encodedBinary, Err: nil}, - configURL: {Body: config, Err: nil}, - newConfigURL: {Body: updateConfig, Err: nil}, - secretsURL: {Body: []byte("secrets"), Err: nil}, - }) - ) - - giveWFID, err := pkgworkflows.GenerateWorkflowID(wfOwner, "workflow-name", binary, config, secretsURL) - require.NoError(t, err) - updatedWFID, err := pkgworkflows.GenerateWorkflowID(wfOwner, "workflow-name", binary, updateConfig, secretsURL) - require.NoError(t, err) - - require.NoError(t, err) - wfIDs := hex.EncodeToString(giveWFID[:]) - - require.NoError(t, err) - newWFIDs := hex.EncodeToString(updatedWFID[:]) - - active := WorkflowRegistryWorkflowRegisteredV1{ - Status: uint8(0), - WorkflowID: giveWFID, - WorkflowOwner: wfOwner, - WorkflowName: "workflow-name", - BinaryURL: binaryURL, - ConfigURL: configURL, - SecretsURL: secretsURL, - } - - er := NewEngineRegistry() - store := wfstore.NewDBStore(db, lggr, clockwork.NewFakeClock()) - registry := capabilities.NewRegistry(lggr) - registry.SetLocalRegistry(&capabilities.TestMetadataRegistry{}) - h := NewEventHandler( - lggr, - orm, - fetcher, - store, - registry, - emitter, - clockwork.NewFakeClock(), - workflowkey.Key{}, - WithEngineRegistry(er), - ) - err = h.workflowRegisteredEvent(ctx, active) - require.NoError(t, err) - - // Verify the record is updated in the database - dbSpec, err := orm.GetWorkflowSpec(ctx, hex.EncodeToString(wfOwner), "workflow-name") - require.NoError(t, err) - require.Equal(t, hex.EncodeToString(wfOwner), dbSpec.WorkflowOwner) - require.Equal(t, "workflow-name", dbSpec.WorkflowName) - require.Equal(t, job.WorkflowSpecStatusActive, dbSpec.Status) - - // Verify the engine is started - engine, err := h.engineRegistry.Get(wfIDs) - require.NoError(t, err) - err = engine.Ready() - require.NoError(t, err) - - // create a paused event - pauseEvent := WorkflowRegistryWorkflowPausedV1{ - WorkflowID: giveWFID, - WorkflowOwner: wfOwner, - WorkflowName: "workflow-name", - DonID: 1, - } - err = h.workflowPausedEvent(ctx, pauseEvent) - require.NoError(t, err) - - // Verify the record is updated in the database - dbSpec, err = orm.GetWorkflowSpec(ctx, hex.EncodeToString(wfOwner), "workflow-name") - require.NoError(t, err) - require.Equal(t, hex.EncodeToString(wfOwner), dbSpec.WorkflowOwner) - require.Equal(t, "workflow-name", dbSpec.WorkflowName) - require.Equal(t, job.WorkflowSpecStatusPaused, dbSpec.Status) - - // Verify the engine is removed - _, err = h.engineRegistry.Get(wfIDs) - require.Error(t, err) - - // create an activated workflow event - activatedEvent := WorkflowRegistryWorkflowActivatedV1{ - WorkflowID: giveWFID, - WorkflowOwner: wfOwner, - WorkflowName: "workflow-name", - DonID: 1, - } - - err = h.workflowActivatedEvent(ctx, activatedEvent) - require.NoError(t, err) - - // Verify the record is updated in the database - dbSpec, err = orm.GetWorkflowSpec(ctx, hex.EncodeToString(wfOwner), "workflow-name") - require.NoError(t, err) - require.Equal(t, hex.EncodeToString(wfOwner), dbSpec.WorkflowOwner) - require.Equal(t, "workflow-name", dbSpec.WorkflowName) - require.Equal(t, job.WorkflowSpecStatusActive, dbSpec.Status) - - // Verify the engine is started - engine, err = h.engineRegistry.Get(wfIDs) - require.NoError(t, err) - err = engine.Ready() - require.NoError(t, err) - - // create an updated event - updatedEvent := WorkflowRegistryWorkflowUpdatedV1{ - OldWorkflowID: giveWFID, - NewWorkflowID: updatedWFID, - WorkflowOwner: wfOwner, - WorkflowName: "workflow-name", - BinaryURL: binaryURL, - ConfigURL: newConfigURL, - SecretsURL: secretsURL, - DonID: 1, - } - err = h.workflowUpdatedEvent(ctx, updatedEvent) - require.NoError(t, err) - - // Verify the record is updated in the database - dbSpec, err = orm.GetWorkflowSpec(ctx, hex.EncodeToString(wfOwner), "workflow-name") - require.NoError(t, err) - require.Equal(t, hex.EncodeToString(wfOwner), dbSpec.WorkflowOwner) - require.Equal(t, "workflow-name", dbSpec.WorkflowName) - require.Equal(t, job.WorkflowSpecStatusActive, dbSpec.Status) - require.Equal(t, newWFIDs, dbSpec.WorkflowID) - require.Equal(t, newConfigURL, dbSpec.ConfigURL) - require.Equal(t, string(updateConfig), dbSpec.Config) - - // old engine is no longer running - _, err = h.engineRegistry.Get(wfIDs) - require.Error(t, err) - - // new engine is started - engine, err = h.engineRegistry.Get(newWFIDs) - require.NoError(t, err) - err = engine.Ready() - require.NoError(t, err) - }) -} - -func Test_Handler_SecretsFor(t *testing.T) { - lggr := logger.TestLogger(t) - db := pgtest.NewSqlxDB(t) - orm := &orm{ds: db, lggr: lggr} - - workflowOwner := hex.EncodeToString([]byte("anOwner")) - workflowName := "aName" - workflowID := "anID" - encryptionKey, err := workflowkey.New() - require.NoError(t, err) - - url := "http://example.com" - hash := hex.EncodeToString([]byte(url)) - secretsPayload, err := generateSecrets(workflowOwner, map[string][]string{"Foo": []string{"Bar"}}, encryptionKey) - require.NoError(t, err) - secretsID, err := orm.Create(testutils.Context(t), url, hash, string(secretsPayload)) - require.NoError(t, err) - - _, err = orm.UpsertWorkflowSpec(testutils.Context(t), &job.WorkflowSpec{ - Workflow: "", - Config: "", - SecretsID: sql.NullInt64{Int64: secretsID, Valid: true}, - WorkflowID: workflowID, - WorkflowOwner: workflowOwner, - WorkflowName: workflowName, - BinaryURL: "", - ConfigURL: "", - CreatedAt: time.Now(), - SpecType: job.DefaultSpecType, - }) - require.NoError(t, err) - - fetcher := &mockFetcher{ - responseMap: map[string]mockFetchResp{ - url: mockFetchResp{Err: errors.New("could not fetch")}, - }, - } - h := NewEventHandler( - lggr, - orm, - fetcher.Fetch, - wfstore.NewDBStore(db, lggr, clockwork.NewFakeClock()), - capabilities.NewRegistry(lggr), - custmsg.NewLabeler(), - clockwork.NewFakeClock(), - encryptionKey, - ) - - gotSecrets, err := h.SecretsFor(testutils.Context(t), workflowOwner, workflowName, workflowID) - require.NoError(t, err) - - expectedSecrets := map[string]string{ - "Foo": "Bar", - } - assert.Equal(t, expectedSecrets, gotSecrets) -} - -func Test_Handler_SecretsFor_RefreshesSecrets(t *testing.T) { - lggr := logger.TestLogger(t) - db := pgtest.NewSqlxDB(t) - orm := &orm{ds: db, lggr: lggr} - - workflowOwner := hex.EncodeToString([]byte("anOwner")) - workflowName := "aName" - workflowID := "anID" - encryptionKey, err := workflowkey.New() - require.NoError(t, err) - - secretsPayload, err := generateSecrets(workflowOwner, map[string][]string{"Foo": []string{"Bar"}}, encryptionKey) - require.NoError(t, err) - - url := "http://example.com" - hash := hex.EncodeToString([]byte(url)) - - secretsID, err := orm.Create(testutils.Context(t), url, hash, string(secretsPayload)) - require.NoError(t, err) - - _, err = orm.UpsertWorkflowSpec(testutils.Context(t), &job.WorkflowSpec{ - Workflow: "", - Config: "", - SecretsID: sql.NullInt64{Int64: secretsID, Valid: true}, - WorkflowID: workflowID, - WorkflowOwner: workflowOwner, - WorkflowName: workflowName, - BinaryURL: "", - ConfigURL: "", - CreatedAt: time.Now(), - SpecType: job.DefaultSpecType, - }) - require.NoError(t, err) - - secretsPayload, err = generateSecrets(workflowOwner, map[string][]string{"Baz": []string{"Bar"}}, encryptionKey) - require.NoError(t, err) - fetcher := &mockFetcher{ - responseMap: map[string]mockFetchResp{ - url: mockFetchResp{Body: secretsPayload}, - }, - } - h := NewEventHandler( - lggr, - orm, - fetcher.Fetch, - wfstore.NewDBStore(db, lggr, clockwork.NewFakeClock()), - capabilities.NewRegistry(lggr), - custmsg.NewLabeler(), - clockwork.NewFakeClock(), - encryptionKey, - ) - - gotSecrets, err := h.SecretsFor(testutils.Context(t), workflowOwner, workflowName, workflowID) - require.NoError(t, err) - - expectedSecrets := map[string]string{ - "Baz": "Bar", - } - assert.Equal(t, expectedSecrets, gotSecrets) -} - -func Test_Handler_SecretsFor_RefreshLogic(t *testing.T) { - lggr := logger.TestLogger(t) - db := pgtest.NewSqlxDB(t) - orm := &orm{ds: db, lggr: lggr} - - workflowOwner := hex.EncodeToString([]byte("anOwner")) - workflowName := "aName" - workflowID := "anID" - encryptionKey, err := workflowkey.New() - require.NoError(t, err) - - secretsPayload, err := generateSecrets(workflowOwner, map[string][]string{"Foo": []string{"Bar"}}, encryptionKey) - require.NoError(t, err) - - url := "http://example.com" - hash := hex.EncodeToString([]byte(url)) - - secretsID, err := orm.Create(testutils.Context(t), url, hash, string(secretsPayload)) - require.NoError(t, err) - - _, err = orm.UpsertWorkflowSpec(testutils.Context(t), &job.WorkflowSpec{ - Workflow: "", - Config: "", - SecretsID: sql.NullInt64{Int64: secretsID, Valid: true}, - WorkflowID: workflowID, - WorkflowOwner: workflowOwner, - WorkflowName: workflowName, - BinaryURL: "", - ConfigURL: "", - CreatedAt: time.Now(), - SpecType: job.DefaultSpecType, - }) - require.NoError(t, err) - - fetcher := &mockFetcher{ - responseMap: map[string]mockFetchResp{ - url: mockFetchResp{ - Body: secretsPayload, - }, - }, - } - clock := clockwork.NewFakeClock() - h := NewEventHandler( - lggr, - orm, - fetcher.Fetch, - wfstore.NewDBStore(db, lggr, clockwork.NewFakeClock()), - capabilities.NewRegistry(lggr), - custmsg.NewLabeler(), - clock, - encryptionKey, - ) - - gotSecrets, err := h.SecretsFor(testutils.Context(t), workflowOwner, workflowName, workflowID) - require.NoError(t, err) - - expectedSecrets := map[string]string{ - "Foo": "Bar", - } - assert.Equal(t, expectedSecrets, gotSecrets) - - // Now stub out an unparseable response, since we already fetched it recently above, we shouldn't need to refetch - // SecretsFor should still succeed. - fetcher.responseMap[url] = mockFetchResp{} - - gotSecrets, err = h.SecretsFor(testutils.Context(t), workflowOwner, workflowName, workflowID) - require.NoError(t, err) - - assert.Equal(t, expectedSecrets, gotSecrets) - - // Now advance so that we hit the freshness limit - clock.Advance(48 * time.Hour) - - _, err = h.SecretsFor(testutils.Context(t), workflowOwner, workflowName, workflowID) - assert.ErrorContains(t, err, "unexpected end of JSON input") -} - -func generateSecrets(workflowOwner string, secretsMap map[string][]string, encryptionKey workflowkey.Key) ([]byte, error) { - sm, secretsEnvVars, err := secrets.EncryptSecretsForNodes( - workflowOwner, - secretsMap, - map[string][32]byte{ - "p2pId": encryptionKey.PublicKey(), - }, - secrets.SecretsConfig{}, - ) - if err != nil { - return nil, err - } - return json.Marshal(secrets.EncryptedSecretsResult{ - EncryptedSecrets: sm, - Metadata: secrets.Metadata{ - WorkflowOwner: workflowOwner, - EnvVarsAssignedToNodes: secretsEnvVars, - NodePublicEncryptionKeys: map[string]string{ - "p2pId": encryptionKey.PublicKeyString(), - }, - }, - }) -} diff --git a/core/services/workflows/syncer/mocks/orm.go b/core/services/workflows/syncer/mocks/orm.go deleted file mode 100644 index 09a543d65e3..00000000000 --- a/core/services/workflows/syncer/mocks/orm.go +++ /dev/null @@ -1,789 +0,0 @@ -// Code generated by mockery v2.46.3. DO NOT EDIT. - -package mocks - -import ( - context "context" - - job "github.com/smartcontractkit/chainlink/v2/core/services/job" - mock "github.com/stretchr/testify/mock" -) - -// ORM is an autogenerated mock type for the ORM type -type ORM struct { - mock.Mock -} - -type ORM_Expecter struct { - mock *mock.Mock -} - -func (_m *ORM) EXPECT() *ORM_Expecter { - return &ORM_Expecter{mock: &_m.Mock} -} - -// Create provides a mock function with given fields: ctx, secretsURL, hash, contents -func (_m *ORM) Create(ctx context.Context, secretsURL string, hash string, contents string) (int64, error) { - ret := _m.Called(ctx, secretsURL, hash, contents) - - if len(ret) == 0 { - panic("no return value specified for Create") - } - - var r0 int64 - var r1 error - if rf, ok := ret.Get(0).(func(context.Context, string, string, string) (int64, error)); ok { - return rf(ctx, secretsURL, hash, contents) - } - if rf, ok := ret.Get(0).(func(context.Context, string, string, string) int64); ok { - r0 = rf(ctx, secretsURL, hash, contents) - } else { - r0 = ret.Get(0).(int64) - } - - if rf, ok := ret.Get(1).(func(context.Context, string, string, string) error); ok { - r1 = rf(ctx, secretsURL, hash, contents) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// ORM_Create_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Create' -type ORM_Create_Call struct { - *mock.Call -} - -// Create is a helper method to define mock.On call -// - ctx context.Context -// - secretsURL string -// - hash string -// - contents string -func (_e *ORM_Expecter) Create(ctx interface{}, secretsURL interface{}, hash interface{}, contents interface{}) *ORM_Create_Call { - return &ORM_Create_Call{Call: _e.mock.On("Create", ctx, secretsURL, hash, contents)} -} - -func (_c *ORM_Create_Call) Run(run func(ctx context.Context, secretsURL string, hash string, contents string)) *ORM_Create_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context), args[1].(string), args[2].(string), args[3].(string)) - }) - return _c -} - -func (_c *ORM_Create_Call) Return(_a0 int64, _a1 error) *ORM_Create_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *ORM_Create_Call) RunAndReturn(run func(context.Context, string, string, string) (int64, error)) *ORM_Create_Call { - _c.Call.Return(run) - return _c -} - -// DeleteWorkflowSpec provides a mock function with given fields: ctx, owner, name -func (_m *ORM) DeleteWorkflowSpec(ctx context.Context, owner string, name string) error { - ret := _m.Called(ctx, owner, name) - - if len(ret) == 0 { - panic("no return value specified for DeleteWorkflowSpec") - } - - var r0 error - if rf, ok := ret.Get(0).(func(context.Context, string, string) error); ok { - r0 = rf(ctx, owner, name) - } else { - r0 = ret.Error(0) - } - - return r0 -} - -// ORM_DeleteWorkflowSpec_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'DeleteWorkflowSpec' -type ORM_DeleteWorkflowSpec_Call struct { - *mock.Call -} - -// DeleteWorkflowSpec is a helper method to define mock.On call -// - ctx context.Context -// - owner string -// - name string -func (_e *ORM_Expecter) DeleteWorkflowSpec(ctx interface{}, owner interface{}, name interface{}) *ORM_DeleteWorkflowSpec_Call { - return &ORM_DeleteWorkflowSpec_Call{Call: _e.mock.On("DeleteWorkflowSpec", ctx, owner, name)} -} - -func (_c *ORM_DeleteWorkflowSpec_Call) Run(run func(ctx context.Context, owner string, name string)) *ORM_DeleteWorkflowSpec_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context), args[1].(string), args[2].(string)) - }) - return _c -} - -func (_c *ORM_DeleteWorkflowSpec_Call) Return(_a0 error) *ORM_DeleteWorkflowSpec_Call { - _c.Call.Return(_a0) - return _c -} - -func (_c *ORM_DeleteWorkflowSpec_Call) RunAndReturn(run func(context.Context, string, string) error) *ORM_DeleteWorkflowSpec_Call { - _c.Call.Return(run) - return _c -} - -// GetContents provides a mock function with given fields: ctx, url -func (_m *ORM) GetContents(ctx context.Context, url string) (string, error) { - ret := _m.Called(ctx, url) - - if len(ret) == 0 { - panic("no return value specified for GetContents") - } - - var r0 string - var r1 error - if rf, ok := ret.Get(0).(func(context.Context, string) (string, error)); ok { - return rf(ctx, url) - } - if rf, ok := ret.Get(0).(func(context.Context, string) string); ok { - r0 = rf(ctx, url) - } else { - r0 = ret.Get(0).(string) - } - - if rf, ok := ret.Get(1).(func(context.Context, string) error); ok { - r1 = rf(ctx, url) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// ORM_GetContents_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetContents' -type ORM_GetContents_Call struct { - *mock.Call -} - -// GetContents is a helper method to define mock.On call -// - ctx context.Context -// - url string -func (_e *ORM_Expecter) GetContents(ctx interface{}, url interface{}) *ORM_GetContents_Call { - return &ORM_GetContents_Call{Call: _e.mock.On("GetContents", ctx, url)} -} - -func (_c *ORM_GetContents_Call) Run(run func(ctx context.Context, url string)) *ORM_GetContents_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context), args[1].(string)) - }) - return _c -} - -func (_c *ORM_GetContents_Call) Return(_a0 string, _a1 error) *ORM_GetContents_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *ORM_GetContents_Call) RunAndReturn(run func(context.Context, string) (string, error)) *ORM_GetContents_Call { - _c.Call.Return(run) - return _c -} - -// GetContentsByHash provides a mock function with given fields: ctx, hash -func (_m *ORM) GetContentsByHash(ctx context.Context, hash string) (string, error) { - ret := _m.Called(ctx, hash) - - if len(ret) == 0 { - panic("no return value specified for GetContentsByHash") - } - - var r0 string - var r1 error - if rf, ok := ret.Get(0).(func(context.Context, string) (string, error)); ok { - return rf(ctx, hash) - } - if rf, ok := ret.Get(0).(func(context.Context, string) string); ok { - r0 = rf(ctx, hash) - } else { - r0 = ret.Get(0).(string) - } - - if rf, ok := ret.Get(1).(func(context.Context, string) error); ok { - r1 = rf(ctx, hash) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// ORM_GetContentsByHash_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetContentsByHash' -type ORM_GetContentsByHash_Call struct { - *mock.Call -} - -// GetContentsByHash is a helper method to define mock.On call -// - ctx context.Context -// - hash string -func (_e *ORM_Expecter) GetContentsByHash(ctx interface{}, hash interface{}) *ORM_GetContentsByHash_Call { - return &ORM_GetContentsByHash_Call{Call: _e.mock.On("GetContentsByHash", ctx, hash)} -} - -func (_c *ORM_GetContentsByHash_Call) Run(run func(ctx context.Context, hash string)) *ORM_GetContentsByHash_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context), args[1].(string)) - }) - return _c -} - -func (_c *ORM_GetContentsByHash_Call) Return(_a0 string, _a1 error) *ORM_GetContentsByHash_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *ORM_GetContentsByHash_Call) RunAndReturn(run func(context.Context, string) (string, error)) *ORM_GetContentsByHash_Call { - _c.Call.Return(run) - return _c -} - -// GetContentsByWorkflowID provides a mock function with given fields: ctx, workflowID -func (_m *ORM) GetContentsByWorkflowID(ctx context.Context, workflowID string) (string, string, error) { - ret := _m.Called(ctx, workflowID) - - if len(ret) == 0 { - panic("no return value specified for GetContentsByWorkflowID") - } - - var r0 string - var r1 string - var r2 error - if rf, ok := ret.Get(0).(func(context.Context, string) (string, string, error)); ok { - return rf(ctx, workflowID) - } - if rf, ok := ret.Get(0).(func(context.Context, string) string); ok { - r0 = rf(ctx, workflowID) - } else { - r0 = ret.Get(0).(string) - } - - if rf, ok := ret.Get(1).(func(context.Context, string) string); ok { - r1 = rf(ctx, workflowID) - } else { - r1 = ret.Get(1).(string) - } - - if rf, ok := ret.Get(2).(func(context.Context, string) error); ok { - r2 = rf(ctx, workflowID) - } else { - r2 = ret.Error(2) - } - - return r0, r1, r2 -} - -// ORM_GetContentsByWorkflowID_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetContentsByWorkflowID' -type ORM_GetContentsByWorkflowID_Call struct { - *mock.Call -} - -// GetContentsByWorkflowID is a helper method to define mock.On call -// - ctx context.Context -// - workflowID string -func (_e *ORM_Expecter) GetContentsByWorkflowID(ctx interface{}, workflowID interface{}) *ORM_GetContentsByWorkflowID_Call { - return &ORM_GetContentsByWorkflowID_Call{Call: _e.mock.On("GetContentsByWorkflowID", ctx, workflowID)} -} - -func (_c *ORM_GetContentsByWorkflowID_Call) Run(run func(ctx context.Context, workflowID string)) *ORM_GetContentsByWorkflowID_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context), args[1].(string)) - }) - return _c -} - -func (_c *ORM_GetContentsByWorkflowID_Call) Return(_a0 string, _a1 string, _a2 error) *ORM_GetContentsByWorkflowID_Call { - _c.Call.Return(_a0, _a1, _a2) - return _c -} - -func (_c *ORM_GetContentsByWorkflowID_Call) RunAndReturn(run func(context.Context, string) (string, string, error)) *ORM_GetContentsByWorkflowID_Call { - _c.Call.Return(run) - return _c -} - -// GetSecretsURLByHash provides a mock function with given fields: ctx, hash -func (_m *ORM) GetSecretsURLByHash(ctx context.Context, hash string) (string, error) { - ret := _m.Called(ctx, hash) - - if len(ret) == 0 { - panic("no return value specified for GetSecretsURLByHash") - } - - var r0 string - var r1 error - if rf, ok := ret.Get(0).(func(context.Context, string) (string, error)); ok { - return rf(ctx, hash) - } - if rf, ok := ret.Get(0).(func(context.Context, string) string); ok { - r0 = rf(ctx, hash) - } else { - r0 = ret.Get(0).(string) - } - - if rf, ok := ret.Get(1).(func(context.Context, string) error); ok { - r1 = rf(ctx, hash) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// ORM_GetSecretsURLByHash_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetSecretsURLByHash' -type ORM_GetSecretsURLByHash_Call struct { - *mock.Call -} - -// GetSecretsURLByHash is a helper method to define mock.On call -// - ctx context.Context -// - hash string -func (_e *ORM_Expecter) GetSecretsURLByHash(ctx interface{}, hash interface{}) *ORM_GetSecretsURLByHash_Call { - return &ORM_GetSecretsURLByHash_Call{Call: _e.mock.On("GetSecretsURLByHash", ctx, hash)} -} - -func (_c *ORM_GetSecretsURLByHash_Call) Run(run func(ctx context.Context, hash string)) *ORM_GetSecretsURLByHash_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context), args[1].(string)) - }) - return _c -} - -func (_c *ORM_GetSecretsURLByHash_Call) Return(_a0 string, _a1 error) *ORM_GetSecretsURLByHash_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *ORM_GetSecretsURLByHash_Call) RunAndReturn(run func(context.Context, string) (string, error)) *ORM_GetSecretsURLByHash_Call { - _c.Call.Return(run) - return _c -} - -// GetSecretsURLByID provides a mock function with given fields: ctx, id -func (_m *ORM) GetSecretsURLByID(ctx context.Context, id int64) (string, error) { - ret := _m.Called(ctx, id) - - if len(ret) == 0 { - panic("no return value specified for GetSecretsURLByID") - } - - var r0 string - var r1 error - if rf, ok := ret.Get(0).(func(context.Context, int64) (string, error)); ok { - return rf(ctx, id) - } - if rf, ok := ret.Get(0).(func(context.Context, int64) string); ok { - r0 = rf(ctx, id) - } else { - r0 = ret.Get(0).(string) - } - - if rf, ok := ret.Get(1).(func(context.Context, int64) error); ok { - r1 = rf(ctx, id) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// ORM_GetSecretsURLByID_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetSecretsURLByID' -type ORM_GetSecretsURLByID_Call struct { - *mock.Call -} - -// GetSecretsURLByID is a helper method to define mock.On call -// - ctx context.Context -// - id int64 -func (_e *ORM_Expecter) GetSecretsURLByID(ctx interface{}, id interface{}) *ORM_GetSecretsURLByID_Call { - return &ORM_GetSecretsURLByID_Call{Call: _e.mock.On("GetSecretsURLByID", ctx, id)} -} - -func (_c *ORM_GetSecretsURLByID_Call) Run(run func(ctx context.Context, id int64)) *ORM_GetSecretsURLByID_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context), args[1].(int64)) - }) - return _c -} - -func (_c *ORM_GetSecretsURLByID_Call) Return(_a0 string, _a1 error) *ORM_GetSecretsURLByID_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *ORM_GetSecretsURLByID_Call) RunAndReturn(run func(context.Context, int64) (string, error)) *ORM_GetSecretsURLByID_Call { - _c.Call.Return(run) - return _c -} - -// GetSecretsURLHash provides a mock function with given fields: owner, secretsURL -func (_m *ORM) GetSecretsURLHash(owner []byte, secretsURL []byte) ([]byte, error) { - ret := _m.Called(owner, secretsURL) - - if len(ret) == 0 { - panic("no return value specified for GetSecretsURLHash") - } - - var r0 []byte - var r1 error - if rf, ok := ret.Get(0).(func([]byte, []byte) ([]byte, error)); ok { - return rf(owner, secretsURL) - } - if rf, ok := ret.Get(0).(func([]byte, []byte) []byte); ok { - r0 = rf(owner, secretsURL) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).([]byte) - } - } - - if rf, ok := ret.Get(1).(func([]byte, []byte) error); ok { - r1 = rf(owner, secretsURL) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// ORM_GetSecretsURLHash_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetSecretsURLHash' -type ORM_GetSecretsURLHash_Call struct { - *mock.Call -} - -// GetSecretsURLHash is a helper method to define mock.On call -// - owner []byte -// - secretsURL []byte -func (_e *ORM_Expecter) GetSecretsURLHash(owner interface{}, secretsURL interface{}) *ORM_GetSecretsURLHash_Call { - return &ORM_GetSecretsURLHash_Call{Call: _e.mock.On("GetSecretsURLHash", owner, secretsURL)} -} - -func (_c *ORM_GetSecretsURLHash_Call) Run(run func(owner []byte, secretsURL []byte)) *ORM_GetSecretsURLHash_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].([]byte), args[1].([]byte)) - }) - return _c -} - -func (_c *ORM_GetSecretsURLHash_Call) Return(_a0 []byte, _a1 error) *ORM_GetSecretsURLHash_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *ORM_GetSecretsURLHash_Call) RunAndReturn(run func([]byte, []byte) ([]byte, error)) *ORM_GetSecretsURLHash_Call { - _c.Call.Return(run) - return _c -} - -// GetWorkflowSpec provides a mock function with given fields: ctx, owner, name -func (_m *ORM) GetWorkflowSpec(ctx context.Context, owner string, name string) (*job.WorkflowSpec, error) { - ret := _m.Called(ctx, owner, name) - - if len(ret) == 0 { - panic("no return value specified for GetWorkflowSpec") - } - - var r0 *job.WorkflowSpec - var r1 error - if rf, ok := ret.Get(0).(func(context.Context, string, string) (*job.WorkflowSpec, error)); ok { - return rf(ctx, owner, name) - } - if rf, ok := ret.Get(0).(func(context.Context, string, string) *job.WorkflowSpec); ok { - r0 = rf(ctx, owner, name) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*job.WorkflowSpec) - } - } - - if rf, ok := ret.Get(1).(func(context.Context, string, string) error); ok { - r1 = rf(ctx, owner, name) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// ORM_GetWorkflowSpec_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetWorkflowSpec' -type ORM_GetWorkflowSpec_Call struct { - *mock.Call -} - -// GetWorkflowSpec is a helper method to define mock.On call -// - ctx context.Context -// - owner string -// - name string -func (_e *ORM_Expecter) GetWorkflowSpec(ctx interface{}, owner interface{}, name interface{}) *ORM_GetWorkflowSpec_Call { - return &ORM_GetWorkflowSpec_Call{Call: _e.mock.On("GetWorkflowSpec", ctx, owner, name)} -} - -func (_c *ORM_GetWorkflowSpec_Call) Run(run func(ctx context.Context, owner string, name string)) *ORM_GetWorkflowSpec_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context), args[1].(string), args[2].(string)) - }) - return _c -} - -func (_c *ORM_GetWorkflowSpec_Call) Return(_a0 *job.WorkflowSpec, _a1 error) *ORM_GetWorkflowSpec_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *ORM_GetWorkflowSpec_Call) RunAndReturn(run func(context.Context, string, string) (*job.WorkflowSpec, error)) *ORM_GetWorkflowSpec_Call { - _c.Call.Return(run) - return _c -} - -// GetWorkflowSpecByID provides a mock function with given fields: ctx, id -func (_m *ORM) GetWorkflowSpecByID(ctx context.Context, id string) (*job.WorkflowSpec, error) { - ret := _m.Called(ctx, id) - - if len(ret) == 0 { - panic("no return value specified for GetWorkflowSpecByID") - } - - var r0 *job.WorkflowSpec - var r1 error - if rf, ok := ret.Get(0).(func(context.Context, string) (*job.WorkflowSpec, error)); ok { - return rf(ctx, id) - } - if rf, ok := ret.Get(0).(func(context.Context, string) *job.WorkflowSpec); ok { - r0 = rf(ctx, id) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*job.WorkflowSpec) - } - } - - if rf, ok := ret.Get(1).(func(context.Context, string) error); ok { - r1 = rf(ctx, id) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// ORM_GetWorkflowSpecByID_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetWorkflowSpecByID' -type ORM_GetWorkflowSpecByID_Call struct { - *mock.Call -} - -// GetWorkflowSpecByID is a helper method to define mock.On call -// - ctx context.Context -// - id string -func (_e *ORM_Expecter) GetWorkflowSpecByID(ctx interface{}, id interface{}) *ORM_GetWorkflowSpecByID_Call { - return &ORM_GetWorkflowSpecByID_Call{Call: _e.mock.On("GetWorkflowSpecByID", ctx, id)} -} - -func (_c *ORM_GetWorkflowSpecByID_Call) Run(run func(ctx context.Context, id string)) *ORM_GetWorkflowSpecByID_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context), args[1].(string)) - }) - return _c -} - -func (_c *ORM_GetWorkflowSpecByID_Call) Return(_a0 *job.WorkflowSpec, _a1 error) *ORM_GetWorkflowSpecByID_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *ORM_GetWorkflowSpecByID_Call) RunAndReturn(run func(context.Context, string) (*job.WorkflowSpec, error)) *ORM_GetWorkflowSpecByID_Call { - _c.Call.Return(run) - return _c -} - -// Update provides a mock function with given fields: ctx, secretsURL, contents -func (_m *ORM) Update(ctx context.Context, secretsURL string, contents string) (int64, error) { - ret := _m.Called(ctx, secretsURL, contents) - - if len(ret) == 0 { - panic("no return value specified for Update") - } - - var r0 int64 - var r1 error - if rf, ok := ret.Get(0).(func(context.Context, string, string) (int64, error)); ok { - return rf(ctx, secretsURL, contents) - } - if rf, ok := ret.Get(0).(func(context.Context, string, string) int64); ok { - r0 = rf(ctx, secretsURL, contents) - } else { - r0 = ret.Get(0).(int64) - } - - if rf, ok := ret.Get(1).(func(context.Context, string, string) error); ok { - r1 = rf(ctx, secretsURL, contents) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// ORM_Update_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Update' -type ORM_Update_Call struct { - *mock.Call -} - -// Update is a helper method to define mock.On call -// - ctx context.Context -// - secretsURL string -// - contents string -func (_e *ORM_Expecter) Update(ctx interface{}, secretsURL interface{}, contents interface{}) *ORM_Update_Call { - return &ORM_Update_Call{Call: _e.mock.On("Update", ctx, secretsURL, contents)} -} - -func (_c *ORM_Update_Call) Run(run func(ctx context.Context, secretsURL string, contents string)) *ORM_Update_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context), args[1].(string), args[2].(string)) - }) - return _c -} - -func (_c *ORM_Update_Call) Return(_a0 int64, _a1 error) *ORM_Update_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *ORM_Update_Call) RunAndReturn(run func(context.Context, string, string) (int64, error)) *ORM_Update_Call { - _c.Call.Return(run) - return _c -} - -// UpsertWorkflowSpec provides a mock function with given fields: ctx, spec -func (_m *ORM) UpsertWorkflowSpec(ctx context.Context, spec *job.WorkflowSpec) (int64, error) { - ret := _m.Called(ctx, spec) - - if len(ret) == 0 { - panic("no return value specified for UpsertWorkflowSpec") - } - - var r0 int64 - var r1 error - if rf, ok := ret.Get(0).(func(context.Context, *job.WorkflowSpec) (int64, error)); ok { - return rf(ctx, spec) - } - if rf, ok := ret.Get(0).(func(context.Context, *job.WorkflowSpec) int64); ok { - r0 = rf(ctx, spec) - } else { - r0 = ret.Get(0).(int64) - } - - if rf, ok := ret.Get(1).(func(context.Context, *job.WorkflowSpec) error); ok { - r1 = rf(ctx, spec) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// ORM_UpsertWorkflowSpec_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'UpsertWorkflowSpec' -type ORM_UpsertWorkflowSpec_Call struct { - *mock.Call -} - -// UpsertWorkflowSpec is a helper method to define mock.On call -// - ctx context.Context -// - spec *job.WorkflowSpec -func (_e *ORM_Expecter) UpsertWorkflowSpec(ctx interface{}, spec interface{}) *ORM_UpsertWorkflowSpec_Call { - return &ORM_UpsertWorkflowSpec_Call{Call: _e.mock.On("UpsertWorkflowSpec", ctx, spec)} -} - -func (_c *ORM_UpsertWorkflowSpec_Call) Run(run func(ctx context.Context, spec *job.WorkflowSpec)) *ORM_UpsertWorkflowSpec_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context), args[1].(*job.WorkflowSpec)) - }) - return _c -} - -func (_c *ORM_UpsertWorkflowSpec_Call) Return(_a0 int64, _a1 error) *ORM_UpsertWorkflowSpec_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *ORM_UpsertWorkflowSpec_Call) RunAndReturn(run func(context.Context, *job.WorkflowSpec) (int64, error)) *ORM_UpsertWorkflowSpec_Call { - _c.Call.Return(run) - return _c -} - -// UpsertWorkflowSpecWithSecrets provides a mock function with given fields: ctx, spec, url, hash, contents -func (_m *ORM) UpsertWorkflowSpecWithSecrets(ctx context.Context, spec *job.WorkflowSpec, url string, hash string, contents string) (int64, error) { - ret := _m.Called(ctx, spec, url, hash, contents) - - if len(ret) == 0 { - panic("no return value specified for UpsertWorkflowSpecWithSecrets") - } - - var r0 int64 - var r1 error - if rf, ok := ret.Get(0).(func(context.Context, *job.WorkflowSpec, string, string, string) (int64, error)); ok { - return rf(ctx, spec, url, hash, contents) - } - if rf, ok := ret.Get(0).(func(context.Context, *job.WorkflowSpec, string, string, string) int64); ok { - r0 = rf(ctx, spec, url, hash, contents) - } else { - r0 = ret.Get(0).(int64) - } - - if rf, ok := ret.Get(1).(func(context.Context, *job.WorkflowSpec, string, string, string) error); ok { - r1 = rf(ctx, spec, url, hash, contents) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// ORM_UpsertWorkflowSpecWithSecrets_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'UpsertWorkflowSpecWithSecrets' -type ORM_UpsertWorkflowSpecWithSecrets_Call struct { - *mock.Call -} - -// UpsertWorkflowSpecWithSecrets is a helper method to define mock.On call -// - ctx context.Context -// - spec *job.WorkflowSpec -// - url string -// - hash string -// - contents string -func (_e *ORM_Expecter) UpsertWorkflowSpecWithSecrets(ctx interface{}, spec interface{}, url interface{}, hash interface{}, contents interface{}) *ORM_UpsertWorkflowSpecWithSecrets_Call { - return &ORM_UpsertWorkflowSpecWithSecrets_Call{Call: _e.mock.On("UpsertWorkflowSpecWithSecrets", ctx, spec, url, hash, contents)} -} - -func (_c *ORM_UpsertWorkflowSpecWithSecrets_Call) Run(run func(ctx context.Context, spec *job.WorkflowSpec, url string, hash string, contents string)) *ORM_UpsertWorkflowSpecWithSecrets_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context), args[1].(*job.WorkflowSpec), args[2].(string), args[3].(string), args[4].(string)) - }) - return _c -} - -func (_c *ORM_UpsertWorkflowSpecWithSecrets_Call) Return(_a0 int64, _a1 error) *ORM_UpsertWorkflowSpecWithSecrets_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *ORM_UpsertWorkflowSpecWithSecrets_Call) RunAndReturn(run func(context.Context, *job.WorkflowSpec, string, string, string) (int64, error)) *ORM_UpsertWorkflowSpecWithSecrets_Call { - _c.Call.Return(run) - return _c -} - -// NewORM creates a new instance of ORM. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. -// The first argument is typically a *testing.T value. -func NewORM(t interface { - mock.TestingT - Cleanup(func()) -}) *ORM { - mock := &ORM{} - mock.Mock.Test(t) - - t.Cleanup(func() { mock.AssertExpectations(t) }) - - return mock -} diff --git a/core/services/workflows/syncer/orm.go b/core/services/workflows/syncer/orm.go deleted file mode 100644 index ff9336a0893..00000000000 --- a/core/services/workflows/syncer/orm.go +++ /dev/null @@ -1,429 +0,0 @@ -package syncer - -import ( - "context" - "database/sql" - "errors" - "fmt" - "time" - - "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" - "github.com/smartcontractkit/chainlink/v2/core/logger" - "github.com/smartcontractkit/chainlink/v2/core/services/job" - "github.com/smartcontractkit/chainlink/v2/core/utils/crypto" -) - -type WorkflowSecretsDS interface { - // GetSecretsURLByID returns the secrets URL for the given ID. - GetSecretsURLByID(ctx context.Context, id int64) (string, error) - - // GetSecretsURLByID returns the secrets URL for the given ID. - GetSecretsURLByHash(ctx context.Context, hash string) (string, error) - - // GetContents returns the contents of the secret at the given plain URL. - GetContents(ctx context.Context, url string) (string, error) - - // GetContentsByHash returns the contents of the secret at the given hashed URL. - GetContentsByHash(ctx context.Context, hash string) (string, error) - - // GetContentsByWorkflowID returns the contents and secrets_url of the secret for the given workflow. - GetContentsByWorkflowID(ctx context.Context, workflowID string) (string, string, error) - - // GetSecretsURLHash returns the keccak256 hash of the owner and secrets URL. - GetSecretsURLHash(owner, secretsURL []byte) ([]byte, error) - - // Update updates the contents of the secrets at the given plain URL or inserts a new record if not found. - Update(ctx context.Context, secretsURL, contents string) (int64, error) - - Create(ctx context.Context, secretsURL, hash, contents string) (int64, error) -} - -type WorkflowSpecsDS interface { - // UpsertWorkflowSpec inserts or updates a workflow spec. Updates on conflict of workflow name - // and owner - UpsertWorkflowSpec(ctx context.Context, spec *job.WorkflowSpec) (int64, error) - - // UpsertWorkflowSpecWithSecrets inserts or updates a workflow spec with secrets in a transaction. - // Updates on conflict of workflow name and owner. - UpsertWorkflowSpecWithSecrets(ctx context.Context, spec *job.WorkflowSpec, url, hash, contents string) (int64, error) - - // GetWorkflowSpec returns the workflow spec for the given owner and name. - GetWorkflowSpec(ctx context.Context, owner, name string) (*job.WorkflowSpec, error) - - // DeleteWorkflowSpec deletes the workflow spec for the given owner and name. - DeleteWorkflowSpec(ctx context.Context, owner, name string) error - - // GetWorkflowSpecByID returns the workflow spec for the given workflowID. - GetWorkflowSpecByID(ctx context.Context, id string) (*job.WorkflowSpec, error) -} - -type ORM interface { - WorkflowSecretsDS - WorkflowSpecsDS -} - -type WorkflowRegistryDS = ORM - -type orm struct { - ds sqlutil.DataSource - lggr logger.Logger -} - -var _ WorkflowRegistryDS = (*orm)(nil) - -func NewWorkflowRegistryDS(ds sqlutil.DataSource, lggr logger.Logger) *orm { - return &orm{ - ds: ds, - lggr: lggr, - } -} - -func (orm *orm) GetSecretsURLByID(ctx context.Context, id int64) (string, error) { - var secretsURL string - err := orm.ds.GetContext(ctx, &secretsURL, - `SELECT secrets_url FROM workflow_secrets WHERE workflow_secrets.id = $1`, - id, - ) - - return secretsURL, err -} - -func (orm *orm) GetSecretsURLByHash(ctx context.Context, hash string) (string, error) { - var secretsURL string - err := orm.ds.GetContext(ctx, &secretsURL, - `SELECT secrets_url FROM workflow_secrets WHERE workflow_secrets.secrets_url_hash = $1`, - hash, - ) - - return secretsURL, err -} - -func (orm *orm) GetContentsByHash(ctx context.Context, hash string) (string, error) { - var contents string - err := orm.ds.GetContext(ctx, &contents, - `SELECT contents - FROM workflow_secrets - WHERE secrets_url_hash = $1`, - hash, - ) - - if err != nil { - return "", err // Return an empty Artifact struct and the error - } - - return contents, nil // Return the populated Artifact struct -} - -func (orm *orm) GetContents(ctx context.Context, url string) (string, error) { - var contents string - err := orm.ds.GetContext(ctx, &contents, - `SELECT contents - FROM workflow_secrets - WHERE secrets_url = $1`, - url, - ) - - if err != nil { - return "", err // Return an empty Artifact struct and the error - } - - return contents, nil // Return the populated Artifact struct -} - -type Int struct { - sql.NullInt64 -} - -type joinRecord struct { - SecretsID sql.NullString `db:"wspec_secrets_id"` - SecretsURLHash sql.NullString `db:"wsec_secrets_url_hash"` - Contents sql.NullString `db:"wsec_contents"` -} - -var ErrEmptySecrets = errors.New("secrets field is empty") - -// GetContentsByWorkflowID joins the workflow_secrets on the workflow_specs table and gets -// the associated secrets contents. -func (orm *orm) GetContentsByWorkflowID(ctx context.Context, workflowID string) (string, string, error) { - var jr joinRecord - err := orm.ds.GetContext( - ctx, - &jr, - `SELECT wsec.secrets_url_hash AS wsec_secrets_url_hash, wsec.contents AS wsec_contents, wspec.secrets_id AS wspec_secrets_id - FROM workflow_specs AS wspec - LEFT JOIN - workflow_secrets AS wsec ON wspec.secrets_id = wsec.id - WHERE wspec.workflow_id = $1`, - workflowID, - ) - if err != nil { - return "", "", err - } - - if !jr.SecretsID.Valid { - return "", "", ErrEmptySecrets - } - - if jr.Contents.String == "" { - return "", "", ErrEmptySecrets - } - - return jr.SecretsURLHash.String, jr.Contents.String, nil -} - -// Update updates the secrets content at the given hash or inserts a new record if not found. -func (orm *orm) Update(ctx context.Context, hash, contents string) (int64, error) { - var id int64 - err := orm.ds.QueryRowxContext(ctx, - `INSERT INTO workflow_secrets (secrets_url_hash, contents) - VALUES ($1, $2) - ON CONFLICT (secrets_url_hash) DO UPDATE - SET secrets_url_hash = EXCLUDED.secrets_url_hash, contents = EXCLUDED.contents - RETURNING id`, - hash, contents, - ).Scan(&id) - - if err != nil { - return 0, err - } - - return id, nil -} - -// Update updates the secrets content at the given hash or inserts a new record if not found. -func (orm *orm) Create(ctx context.Context, url, hash, contents string) (int64, error) { - var id int64 - err := orm.ds.QueryRowxContext(ctx, - `INSERT INTO workflow_secrets (secrets_url, secrets_url_hash, contents) - VALUES ($1, $2, $3) - RETURNING id`, - url, hash, contents, - ).Scan(&id) - - if err != nil { - return 0, err - } - - return id, nil -} - -func (orm *orm) GetSecretsURLHash(owner, secretsURL []byte) ([]byte, error) { - return crypto.Keccak256(append(owner, secretsURL...)) -} - -func (orm *orm) UpsertWorkflowSpec(ctx context.Context, spec *job.WorkflowSpec) (int64, error) { - var id int64 - err := sqlutil.TransactDataSource(ctx, orm.ds, nil, func(tx sqlutil.DataSource) error { - txErr := tx.QueryRowxContext( - ctx, - `DELETE FROM workflow_specs WHERE workflow_owner = $1 AND workflow_name = $2 AND workflow_id != $3`, - spec.WorkflowOwner, - spec.WorkflowName, - spec.WorkflowID, - ).Scan(nil) - if txErr != nil && !errors.Is(txErr, sql.ErrNoRows) { - return fmt.Errorf("failed to clean up previous workflow specs: %w", txErr) - } - - query := ` - INSERT INTO workflow_specs ( - workflow, - config, - workflow_id, - workflow_owner, - workflow_name, - status, - binary_url, - config_url, - secrets_id, - created_at, - updated_at, - spec_type - ) VALUES ( - :workflow, - :config, - :workflow_id, - :workflow_owner, - :workflow_name, - :status, - :binary_url, - :config_url, - :secrets_id, - :created_at, - :updated_at, - :spec_type - ) ON CONFLICT (workflow_owner, workflow_name) DO UPDATE - SET - workflow = EXCLUDED.workflow, - config = EXCLUDED.config, - workflow_id = EXCLUDED.workflow_id, - workflow_owner = EXCLUDED.workflow_owner, - workflow_name = EXCLUDED.workflow_name, - status = EXCLUDED.status, - binary_url = EXCLUDED.binary_url, - config_url = EXCLUDED.config_url, - secrets_id = EXCLUDED.secrets_id, - created_at = EXCLUDED.created_at, - updated_at = EXCLUDED.updated_at, - spec_type = EXCLUDED.spec_type - RETURNING id - ` - - stmt, err := orm.ds.PrepareNamedContext(ctx, query) - if err != nil { - return err - } - defer stmt.Close() - - spec.UpdatedAt = time.Now() - return stmt.QueryRowxContext(ctx, spec).Scan(&id) - }) - - return id, err -} - -func (orm *orm) UpsertWorkflowSpecWithSecrets( - ctx context.Context, - spec *job.WorkflowSpec, url, hash, contents string) (int64, error) { - var id int64 - err := sqlutil.TransactDataSource(ctx, orm.ds, nil, func(tx sqlutil.DataSource) error { - var sid int64 - txErr := tx.QueryRowxContext(ctx, - `INSERT INTO workflow_secrets (secrets_url, secrets_url_hash, contents) - VALUES ($1, $2, $3) - ON CONFLICT (secrets_url_hash) DO UPDATE - SET - secrets_url_hash = EXCLUDED.secrets_url_hash, - contents = EXCLUDED.contents, - secrets_url = EXCLUDED.secrets_url - RETURNING id`, - url, hash, contents, - ).Scan(&sid) - - if txErr != nil { - return fmt.Errorf("failed to create workflow secrets: %w", txErr) - } - - txErr = tx.QueryRowxContext( - ctx, - `DELETE FROM workflow_specs WHERE workflow_owner = $1 AND workflow_name = $2 AND workflow_id != $3`, - spec.WorkflowOwner, - spec.WorkflowName, - spec.WorkflowID, - ).Scan(nil) - if txErr != nil && !errors.Is(txErr, sql.ErrNoRows) { - return fmt.Errorf("failed to clean up previous workflow specs: %w", txErr) - } - - spec.SecretsID = sql.NullInt64{Int64: sid, Valid: true} - - query := ` - INSERT INTO workflow_specs ( - workflow, - config, - workflow_id, - workflow_owner, - workflow_name, - status, - binary_url, - config_url, - secrets_id, - created_at, - updated_at, - spec_type - ) VALUES ( - :workflow, - :config, - :workflow_id, - :workflow_owner, - :workflow_name, - :status, - :binary_url, - :config_url, - :secrets_id, - :created_at, - :updated_at, - :spec_type - ) ON CONFLICT (workflow_owner, workflow_name) DO UPDATE - SET - workflow = EXCLUDED.workflow, - config = EXCLUDED.config, - workflow_id = EXCLUDED.workflow_id, - workflow_owner = EXCLUDED.workflow_owner, - workflow_name = EXCLUDED.workflow_name, - status = EXCLUDED.status, - binary_url = EXCLUDED.binary_url, - config_url = EXCLUDED.config_url, - created_at = EXCLUDED.created_at, - updated_at = EXCLUDED.updated_at, - spec_type = EXCLUDED.spec_type, - secrets_id = EXCLUDED.secrets_id - RETURNING id - ` - - stmt, txErr := tx.PrepareNamedContext(ctx, query) - if txErr != nil { - return txErr - } - defer stmt.Close() - - spec.UpdatedAt = time.Now() - return stmt.QueryRowxContext(ctx, spec).Scan(&id) - }) - return id, err -} - -func (orm *orm) GetWorkflowSpec(ctx context.Context, owner, name string) (*job.WorkflowSpec, error) { - query := ` - SELECT * - FROM workflow_specs - WHERE workflow_owner = $1 AND workflow_name = $2 - ` - - var spec job.WorkflowSpec - err := orm.ds.GetContext(ctx, &spec, query, owner, name) - if err != nil { - return nil, err - } - - return &spec, nil -} - -func (orm *orm) GetWorkflowSpecByID(ctx context.Context, id string) (*job.WorkflowSpec, error) { - query := ` - SELECT * - FROM workflow_specs - WHERE workflow_id = $1 - ` - - var spec job.WorkflowSpec - err := orm.ds.GetContext(ctx, &spec, query, id) - if err != nil { - return nil, err - } - - return &spec, nil -} - -func (orm *orm) DeleteWorkflowSpec(ctx context.Context, owner, name string) error { - query := ` - DELETE FROM workflow_specs - WHERE workflow_owner = $1 AND workflow_name = $2 - ` - - result, err := orm.ds.ExecContext(ctx, query, owner, name) - if err != nil { - return err - } - - rowsAffected, err := result.RowsAffected() - if err != nil { - return err - } - - if rowsAffected == 0 { - return sql.ErrNoRows // No spec deleted - } - - return nil -} diff --git a/core/services/workflows/syncer/orm_test.go b/core/services/workflows/syncer/orm_test.go deleted file mode 100644 index f47bd6c3731..00000000000 --- a/core/services/workflows/syncer/orm_test.go +++ /dev/null @@ -1,456 +0,0 @@ -package syncer - -import ( - "database/sql" - "encoding/hex" - "testing" - "time" - - "github.com/google/uuid" - - "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" - "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest" - "github.com/smartcontractkit/chainlink/v2/core/logger" - "github.com/smartcontractkit/chainlink/v2/core/services/job" - "github.com/smartcontractkit/chainlink/v2/core/utils/crypto" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" -) - -func TestWorkflowArtifactsORM_GetAndUpdate(t *testing.T) { - db := pgtest.NewSqlxDB(t) - ctx := testutils.Context(t) - lggr := logger.TestLogger(t) - orm := &orm{ds: db, lggr: lggr} - - giveURL := "https://example.com" - giveBytes, err := crypto.Keccak256([]byte(giveURL)) - require.NoError(t, err) - giveHash := hex.EncodeToString(giveBytes) - giveContent := "some contents" - - gotID, err := orm.Create(ctx, giveURL, giveHash, giveContent) - require.NoError(t, err) - - url, err := orm.GetSecretsURLByID(ctx, gotID) - require.NoError(t, err) - assert.Equal(t, giveURL, url) - - contents, err := orm.GetContents(ctx, giveURL) - require.NoError(t, err) - assert.Equal(t, "some contents", contents) - - contents, err = orm.GetContentsByHash(ctx, giveHash) - require.NoError(t, err) - assert.Equal(t, "some contents", contents) - - _, err = orm.Update(ctx, giveHash, "new contents") - require.NoError(t, err) - - contents, err = orm.GetContents(ctx, giveURL) - require.NoError(t, err) - assert.Equal(t, "new contents", contents) - - contents, err = orm.GetContentsByHash(ctx, giveHash) - require.NoError(t, err) - assert.Equal(t, "new contents", contents) -} - -func Test_UpsertWorkflowSpec(t *testing.T) { - db := pgtest.NewSqlxDB(t) - ctx := testutils.Context(t) - lggr := logger.TestLogger(t) - orm := &orm{ds: db, lggr: lggr} - - t.Run("inserts new spec", func(t *testing.T) { - spec := &job.WorkflowSpec{ - Workflow: "test_workflow", - Config: "test_config", - WorkflowID: "cid-123", - WorkflowOwner: "owner-123", - WorkflowName: "Test Workflow", - Status: job.WorkflowSpecStatusActive, - BinaryURL: "http://example.com/binary", - ConfigURL: "http://example.com/config", - CreatedAt: time.Now(), - SpecType: job.WASMFile, - } - - _, err := orm.UpsertWorkflowSpec(ctx, spec) - require.NoError(t, err) - - // Verify the record exists in the database - var dbSpec job.WorkflowSpec - err = db.Get(&dbSpec, `SELECT * FROM workflow_specs WHERE workflow_owner = $1 AND workflow_name = $2`, spec.WorkflowOwner, spec.WorkflowName) - require.NoError(t, err) - require.Equal(t, spec.Workflow, dbSpec.Workflow) - }) - - t.Run("updates existing spec", func(t *testing.T) { - spec := &job.WorkflowSpec{ - Workflow: "test_workflow", - Config: "test_config", - WorkflowID: "cid-123", - WorkflowOwner: "owner-123", - WorkflowName: "Test Workflow", - Status: job.WorkflowSpecStatusActive, - BinaryURL: "http://example.com/binary", - ConfigURL: "http://example.com/config", - CreatedAt: time.Now(), - SpecType: job.WASMFile, - } - - _, err := orm.UpsertWorkflowSpec(ctx, spec) - require.NoError(t, err) - - // Update the status - spec.Status = job.WorkflowSpecStatusPaused - - _, err = orm.UpsertWorkflowSpec(ctx, spec) - require.NoError(t, err) - - // Verify the record is updated in the database - var dbSpec job.WorkflowSpec - err = db.Get(&dbSpec, `SELECT * FROM workflow_specs WHERE workflow_owner = $1 AND workflow_name = $2`, spec.WorkflowOwner, spec.WorkflowName) - require.NoError(t, err) - require.Equal(t, spec.Config, dbSpec.Config) - require.Equal(t, spec.Status, dbSpec.Status) - }) -} - -func Test_DeleteWorkflowSpec(t *testing.T) { - db := pgtest.NewSqlxDB(t) - ctx := testutils.Context(t) - lggr := logger.TestLogger(t) - orm := &orm{ds: db, lggr: lggr} - - t.Run("deletes a workflow spec", func(t *testing.T) { - spec := &job.WorkflowSpec{ - Workflow: "test_workflow", - Config: "test_config", - WorkflowID: "cid-123", - WorkflowOwner: "owner-123", - WorkflowName: "Test Workflow", - Status: job.WorkflowSpecStatusActive, - BinaryURL: "http://example.com/binary", - ConfigURL: "http://example.com/config", - CreatedAt: time.Now(), - SpecType: job.WASMFile, - } - - id, err := orm.UpsertWorkflowSpec(ctx, spec) - require.NoError(t, err) - require.NotZero(t, id) - - err = orm.DeleteWorkflowSpec(ctx, spec.WorkflowOwner, spec.WorkflowName) - require.NoError(t, err) - - // Verify the record is deleted from the database - var dbSpec job.WorkflowSpec - err = db.Get(&dbSpec, `SELECT * FROM workflow_specs WHERE id = $1`, id) - require.Error(t, err) - require.Equal(t, sql.ErrNoRows, err) - }) - - t.Run("fails if no workflow spec exists", func(t *testing.T) { - err := orm.DeleteWorkflowSpec(ctx, "owner-123", "Test Workflow") - require.Error(t, err) - require.Equal(t, sql.ErrNoRows, err) - }) -} - -func Test_GetWorkflowSpec(t *testing.T) { - db := pgtest.NewSqlxDB(t) - ctx := testutils.Context(t) - lggr := logger.TestLogger(t) - orm := &orm{ds: db, lggr: lggr} - - t.Run("gets a workflow spec", func(t *testing.T) { - spec := &job.WorkflowSpec{ - Workflow: "test_workflow", - Config: "test_config", - WorkflowID: "cid-123", - WorkflowOwner: "owner-123", - WorkflowName: "Test Workflow", - Status: job.WorkflowSpecStatusActive, - BinaryURL: "http://example.com/binary", - ConfigURL: "http://example.com/config", - CreatedAt: time.Now(), - SpecType: job.WASMFile, - } - - id, err := orm.UpsertWorkflowSpec(ctx, spec) - require.NoError(t, err) - require.NotZero(t, id) - - dbSpec, err := orm.GetWorkflowSpec(ctx, spec.WorkflowOwner, spec.WorkflowName) - require.NoError(t, err) - require.Equal(t, spec.Workflow, dbSpec.Workflow) - - err = orm.DeleteWorkflowSpec(ctx, spec.WorkflowOwner, spec.WorkflowName) - require.NoError(t, err) - }) - - t.Run("fails if no workflow spec exists", func(t *testing.T) { - dbSpec, err := orm.GetWorkflowSpec(ctx, "owner-123", "Test Workflow") - require.Error(t, err) - require.Nil(t, dbSpec) - }) -} - -func Test_GetWorkflowSpecByID(t *testing.T) { - db := pgtest.NewSqlxDB(t) - ctx := testutils.Context(t) - lggr := logger.TestLogger(t) - orm := &orm{ds: db, lggr: lggr} - - t.Run("gets a workflow spec by ID", func(t *testing.T) { - spec := &job.WorkflowSpec{ - Workflow: "test_workflow", - Config: "test_config", - WorkflowID: "cid-123", - WorkflowOwner: "owner-123", - WorkflowName: "Test Workflow", - Status: job.WorkflowSpecStatusActive, - BinaryURL: "http://example.com/binary", - ConfigURL: "http://example.com/config", - CreatedAt: time.Now(), - SpecType: job.WASMFile, - } - - id, err := orm.UpsertWorkflowSpec(ctx, spec) - require.NoError(t, err) - require.NotZero(t, id) - - dbSpec, err := orm.GetWorkflowSpecByID(ctx, spec.WorkflowID) - require.NoError(t, err) - require.Equal(t, spec.Workflow, dbSpec.Workflow) - - err = orm.DeleteWorkflowSpec(ctx, spec.WorkflowOwner, spec.WorkflowName) - require.NoError(t, err) - }) - - t.Run("fails if no workflow spec exists", func(t *testing.T) { - dbSpec, err := orm.GetWorkflowSpecByID(ctx, "inexistent-workflow-id") - require.Error(t, err) - require.Nil(t, dbSpec) - }) -} - -func Test_GetContentsByWorkflowID(t *testing.T) { - db := pgtest.NewSqlxDB(t) - ctx := testutils.Context(t) - lggr := logger.TestLogger(t) - orm := &orm{ds: db, lggr: lggr} - - // workflow_id is missing - _, _, err := orm.GetContentsByWorkflowID(ctx, "doesnt-exist") - require.ErrorContains(t, err, "no rows in result set") - - // secrets_id is nil; should return EmptySecrets - workflowID := "aWorkflowID" - _, err = orm.UpsertWorkflowSpec(ctx, &job.WorkflowSpec{ - Workflow: "", - Config: "", - WorkflowID: workflowID, - WorkflowOwner: "aWorkflowOwner", - WorkflowName: "aWorkflowName", - BinaryURL: "", - ConfigURL: "", - CreatedAt: time.Now(), - SpecType: job.DefaultSpecType, - }) - require.NoError(t, err) - - _, _, err = orm.GetContentsByWorkflowID(ctx, workflowID) - require.ErrorIs(t, err, ErrEmptySecrets) - - // retrieves the artifact if provided - giveURL := "https://example.com" - giveBytes, err := crypto.Keccak256([]byte(giveURL)) - require.NoError(t, err) - giveHash := hex.EncodeToString(giveBytes) - giveContent := "some contents" - - secretsID, err := orm.Create(ctx, giveURL, giveHash, giveContent) - require.NoError(t, err) - - _, err = orm.UpsertWorkflowSpec(ctx, &job.WorkflowSpec{ - Workflow: "", - Config: "", - SecretsID: sql.NullInt64{Int64: secretsID, Valid: true}, - WorkflowID: workflowID, - WorkflowOwner: "aWorkflowOwner", - WorkflowName: "aWorkflowName", - BinaryURL: "", - ConfigURL: "", - CreatedAt: time.Now(), - SpecType: job.DefaultSpecType, - }) - require.NoError(t, err) - _, err = orm.GetWorkflowSpec(ctx, "aWorkflowOwner", "aWorkflowName") - require.NoError(t, err) - - gotHash, gotContent, err := orm.GetContentsByWorkflowID(ctx, workflowID) - require.NoError(t, err) - assert.Equal(t, giveHash, gotHash) - assert.Equal(t, giveContent, gotContent) -} - -func Test_GetContentsByWorkflowID_SecretsProvidedButEmpty(t *testing.T) { - db := pgtest.NewSqlxDB(t) - ctx := testutils.Context(t) - lggr := logger.TestLogger(t) - orm := &orm{ds: db, lggr: lggr} - - // workflow_id is missing - _, _, err := orm.GetContentsByWorkflowID(ctx, "doesnt-exist") - require.ErrorContains(t, err, "no rows in result set") - - // secrets_id is nil; should return EmptySecrets - workflowID := "aWorkflowID" - giveURL := "https://example.com" - giveBytes, err := crypto.Keccak256([]byte(giveURL)) - require.NoError(t, err) - giveHash := hex.EncodeToString(giveBytes) - giveContent := "" - _, err = orm.UpsertWorkflowSpecWithSecrets(ctx, &job.WorkflowSpec{ - Workflow: "", - Config: "", - WorkflowID: workflowID, - WorkflowOwner: "aWorkflowOwner", - WorkflowName: "aWorkflowName", - BinaryURL: "", - ConfigURL: "", - CreatedAt: time.Now(), - SpecType: job.DefaultSpecType, - }, giveURL, giveHash, giveContent) - require.NoError(t, err) - - _, _, err = orm.GetContentsByWorkflowID(ctx, workflowID) - require.ErrorIs(t, err, ErrEmptySecrets) -} - -func Test_UpsertWorkflowSpecWithSecrets(t *testing.T) { - db := pgtest.NewSqlxDB(t) - ctx := testutils.Context(t) - lggr := logger.TestLogger(t) - orm := &orm{ds: db, lggr: lggr} - - t.Run("inserts new spec and new secrets", func(t *testing.T) { - giveURL := "https://example.com" - giveBytes, err := crypto.Keccak256([]byte(giveURL)) - require.NoError(t, err) - giveHash := hex.EncodeToString(giveBytes) - giveContent := "some contents" - - spec := &job.WorkflowSpec{ - Workflow: "test_workflow", - Config: "test_config", - WorkflowID: "cid-123", - WorkflowOwner: "owner-123", - WorkflowName: "Test Workflow", - Status: job.WorkflowSpecStatusActive, - BinaryURL: "http://example.com/binary", - ConfigURL: "http://example.com/config", - CreatedAt: time.Now(), - SpecType: job.WASMFile, - } - - _, err = orm.UpsertWorkflowSpecWithSecrets(ctx, spec, giveURL, giveHash, giveContent) - require.NoError(t, err) - - // Verify the record exists in the database - var dbSpec job.WorkflowSpec - err = db.Get(&dbSpec, `SELECT * FROM workflow_specs WHERE workflow_owner = $1 AND workflow_name = $2`, spec.WorkflowOwner, spec.WorkflowName) - require.NoError(t, err) - require.Equal(t, spec.Workflow, dbSpec.Workflow) - - // Verify the secrets exists in the database - contents, err := orm.GetContents(ctx, giveURL) - require.NoError(t, err) - require.Equal(t, giveContent, contents) - }) - - t.Run("updates existing spec and secrets", func(t *testing.T) { - giveURL := "https://example.com" - giveBytes, err := crypto.Keccak256([]byte(giveURL)) - require.NoError(t, err) - giveHash := hex.EncodeToString(giveBytes) - giveContent := "some contents" - - spec := &job.WorkflowSpec{ - Workflow: "test_workflow", - Config: "test_config", - WorkflowID: "cid-123", - WorkflowOwner: "owner-123", - WorkflowName: "Test Workflow", - Status: job.WorkflowSpecStatusActive, - BinaryURL: "http://example.com/binary", - ConfigURL: "http://example.com/config", - CreatedAt: time.Now(), - SpecType: job.WASMFile, - } - - _, err = orm.UpsertWorkflowSpecWithSecrets(ctx, spec, giveURL, giveHash, giveContent) - require.NoError(t, err) - - // Update the status - spec.Status = job.WorkflowSpecStatusPaused - - _, err = orm.UpsertWorkflowSpecWithSecrets(ctx, spec, giveURL, giveHash, "new contents") - require.NoError(t, err) - - // Verify the record is updated in the database - var dbSpec job.WorkflowSpec - err = db.Get(&dbSpec, `SELECT * FROM workflow_specs WHERE workflow_owner = $1 AND workflow_name = $2`, spec.WorkflowOwner, spec.WorkflowName) - require.NoError(t, err) - require.Equal(t, spec.Config, dbSpec.Config) - - // Verify the secrets is updated in the database - contents, err := orm.GetContents(ctx, giveURL) - require.NoError(t, err) - require.Equal(t, "new contents", contents) - }) - - t.Run("updates existing spec and secrets if spec has executions", func(t *testing.T) { - giveURL := "https://example.com" - giveBytes, err := crypto.Keccak256([]byte(giveURL)) - require.NoError(t, err) - giveHash := hex.EncodeToString(giveBytes) - giveContent := "some contents" - - spec := &job.WorkflowSpec{ - Workflow: "test_workflow", - Config: "test_config", - WorkflowID: "cid-123", - WorkflowOwner: "owner-123", - WorkflowName: "Test Workflow", - Status: job.WorkflowSpecStatusActive, - BinaryURL: "http://example.com/binary", - ConfigURL: "http://example.com/config", - CreatedAt: time.Now(), - SpecType: job.WASMFile, - } - - _, err = orm.UpsertWorkflowSpecWithSecrets(ctx, spec, giveURL, giveHash, giveContent) - require.NoError(t, err) - - _, err = db.ExecContext( - ctx, - `INSERT INTO workflow_executions (id, workflow_id, status, created_at) VALUES ($1, $2, $3, $4)`, - uuid.New().String(), - "cid-123", - "started", - time.Now(), - ) - require.NoError(t, err) - - // Update the status - spec.WorkflowID = "cid-456" - - _, err = orm.UpsertWorkflowSpecWithSecrets(ctx, spec, giveURL, giveHash, "new contents") - require.NoError(t, err) - }) -} diff --git a/core/services/workflows/syncer/workflow_registry.go b/core/services/workflows/syncer/workflow_registry.go index 26c23411d67..1d42e9d5deb 100644 --- a/core/services/workflows/syncer/workflow_registry.go +++ b/core/services/workflows/syncer/workflow_registry.go @@ -2,585 +2,39 @@ package syncer import ( "context" - "encoding/hex" - "encoding/json" - "fmt" - "iter" - "strings" - "sync" - "time" - "github.com/smartcontractkit/chainlink-common/pkg/capabilities" "github.com/smartcontractkit/chainlink-common/pkg/services" - "github.com/smartcontractkit/chainlink-common/pkg/types" - "github.com/smartcontractkit/chainlink-common/pkg/types/query" - "github.com/smartcontractkit/chainlink-common/pkg/types/query/primitives" - "github.com/smartcontractkit/chainlink-common/pkg/values" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/workflow/generated/workflow_registry_wrapper" - "github.com/smartcontractkit/chainlink/v2/core/logger" - evmtypes "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/types" ) -const name = "WorkflowRegistrySyncer" - -var ( - defaultTickInterval = 12 * time.Second - WorkflowRegistryContractName = "WorkflowRegistry" - GetWorkflowMetadataListByDONMethodName = "getWorkflowMetadataListByDON" -) - -type Head struct { - Hash string - Height string - Timestamp uint64 -} - -type GetWorkflowMetadataListByDONParams struct { - DonID uint32 - Start uint64 - Limit uint64 -} - -type GetWorkflowMetadata struct { - WorkflowID [32]byte - Owner []byte - DonID uint32 - Status uint8 - WorkflowName string - BinaryURL string - ConfigURL string - SecretsURL string -} - -type GetWorkflowMetadataListByDONReturnVal struct { - WorkflowMetadataList []GetWorkflowMetadata -} - -// WorkflowRegistryEvent is an event emitted by the WorkflowRegistry. Each event is typed -// so that the consumer can determine how to handle the event. -type WorkflowRegistryEvent struct { - Cursor string - Data any - EventType WorkflowRegistryEventType - Head Head -} - -func (we WorkflowRegistryEvent) GetEventType() WorkflowRegistryEventType { - return we.EventType -} - -func (we WorkflowRegistryEvent) GetData() any { - return we.Data -} - -// WorkflowRegistryEventResponse is a response to either parsing a queried event or handling the event. -type WorkflowRegistryEventResponse struct { - Err error - Event *WorkflowRegistryEvent -} - -// WorkflowEventPollerConfig is the configuration needed to poll for events on a contract. Currently -// requires the ContractEventName. -type WorkflowEventPollerConfig struct { - QueryCount uint64 -} - -type WorkflowLoadConfig struct { - FetchBatchSize int -} - -// FetcherFunc is an abstraction for fetching the contents stored at a URL. -type FetcherFunc func(ctx context.Context, url string) ([]byte, error) - -// ContractReader is a subset of types.ContractReader defined locally to enable mocking. -type ContractReader interface { - Start(ctx context.Context) error - Close() error - Bind(context.Context, []types.BoundContract) error - QueryKeys(ctx context.Context, keyQueries []types.ContractKeyFilter, limitAndSort query.LimitAndSort) (iter.Seq2[string, types.Sequence], error) - GetLatestValueWithHeadData(ctx context.Context, readName string, confidenceLevel primitives.ConfidenceLevel, params any, returnVal any) (head *types.Head, err error) -} - -type ContractReaderFactory interface { - NewContractReader(context.Context, []byte) (types.ContractReader, error) -} - -// WorkflowRegistrySyncer is the public interface of the package. -type WorkflowRegistrySyncer interface { - services.Service -} - -var _ WorkflowRegistrySyncer = (*workflowRegistry)(nil) - -// workflowRegistry is the implementation of the WorkflowRegistrySyncer interface. -type workflowRegistry struct { +type WorkflowRegistry struct { services.StateMachine - - // close stopCh to stop the workflowRegistry. - stopCh services.StopChan - - // all goroutines are waited on with wg. - wg sync.WaitGroup - - // ticker is the interval at which the workflowRegistry will poll the contract for events. - ticker <-chan time.Time - - lggr logger.Logger - workflowRegistryAddress string - - newContractReaderFn newContractReaderFn - - eventPollerCfg WorkflowEventPollerConfig - eventTypes []WorkflowRegistryEventType - handler evtHandler - - workflowDonNotifier donNotifier -} - -// WithTicker allows external callers to provide a ticker to the workflowRegistry. This is useful -// for overriding the default tick interval. -func WithTicker(ticker <-chan time.Time) func(*workflowRegistry) { - return func(wr *workflowRegistry) { - wr.ticker = ticker - } -} - -type evtHandler interface { - Handle(ctx context.Context, event Event) error -} - -type donNotifier interface { - WaitForDon(ctx context.Context) (capabilities.DON, error) -} - -type newContractReaderFn func(context.Context, []byte) (ContractReader, error) - -// NewWorkflowRegistry returns a new workflowRegistry. -// Only queries for WorkflowRegistryForceUpdateSecretsRequestedV1 events. -func NewWorkflowRegistry( - lggr logger.Logger, - newContractReaderFn newContractReaderFn, - addr string, - eventPollerConfig WorkflowEventPollerConfig, - handler evtHandler, - workflowDonNotifier donNotifier, - opts ...func(*workflowRegistry), -) *workflowRegistry { - ets := []WorkflowRegistryEventType{ - ForceUpdateSecretsEvent, - WorkflowActivatedEvent, - WorkflowDeletedEvent, - WorkflowPausedEvent, - WorkflowRegisteredEvent, - WorkflowUpdatedEvent, - } - - wr := &workflowRegistry{ - lggr: lggr, - newContractReaderFn: newContractReaderFn, - workflowRegistryAddress: addr, - eventPollerCfg: eventPollerConfig, - stopCh: make(services.StopChan), - eventTypes: ets, - handler: handler, - workflowDonNotifier: workflowDonNotifier, - } - - for _, opt := range opts { - opt(wr) - } - return wr -} - -// Start starts the workflowRegistry. It starts two goroutines, one for querying the contract -// and one for handling the events. -func (w *workflowRegistry) Start(_ context.Context) error { - return w.StartOnce(w.Name(), func() error { - ctx, cancel := w.stopCh.NewCtx() - - w.wg.Add(1) - go func() { - defer w.wg.Done() - defer cancel() - - w.lggr.Debugw("Waiting for DON...") - don, err := w.workflowDonNotifier.WaitForDon(ctx) - if err != nil { - w.lggr.Errorw("failed to wait for don", "err", err) - return - } - - reader, err := w.newWorkflowRegistryContractReader(ctx) - if err != nil { - w.lggr.Criticalf("contract reader unavailable : %s", err) - return - } - - w.lggr.Debugw("Loading initial workflows for DON", "DON", don.ID) - loadWorkflowsHead, err := w.loadWorkflows(ctx, don, reader) - if err != nil { - // TODO - this is a temporary fix to handle the case where the chainreader errors because the contract - // contains no workflows. To track: https://smartcontract-it.atlassian.net/browse/CAPPL-393 - if !strings.Contains(err.Error(), "attempting to unmarshal an empty string while arguments are expected") { - w.lggr.Errorw("failed to load workflows", "err", err) - return - } - - loadWorkflowsHead = &types.Head{ - Height: "0", - } - } - - w.readRegistryEvents(ctx, reader, loadWorkflowsHead.Height) - }() - - return nil - }) -} - -func (w *workflowRegistry) Close() error { - return w.StopOnce(w.Name(), func() error { - close(w.stopCh) - w.wg.Wait() - return nil - }) } -func (w *workflowRegistry) Ready() error { +func (w *WorkflowRegistry) Start(ctx context.Context) error { return nil } -func (w *workflowRegistry) HealthReport() map[string]error { +func (w *WorkflowRegistry) Close() error { return nil } -func (w *workflowRegistry) Name() string { - return name -} - -// readRegistryEvents polls the contract for events and send them to the events channel. -func (w *workflowRegistry) readRegistryEvents(ctx context.Context, reader ContractReader, lastReadBlockNumber string) { - ticker := w.getTicker() - - var keyQueries = make([]types.ContractKeyFilter, 0, len(w.eventTypes)) - for _, et := range w.eventTypes { - var logData values.Value - keyQueries = append(keyQueries, types.ContractKeyFilter{ - KeyFilter: query.KeyFilter{ - Key: string(et), - Expressions: []query.Expression{ - query.Confidence(primitives.Finalized), - query.Block(lastReadBlockNumber, primitives.Gt), - }, - }, - Contract: types.BoundContract{ - Name: WorkflowRegistryContractName, - Address: w.workflowRegistryAddress, - }, - SequenceDataType: &logData, - }) - } - - cursor := "" - for { - select { - case <-ctx.Done(): - return - case <-ticker: - limitAndSort := query.LimitAndSort{ - SortBy: []query.SortBy{query.NewSortByTimestamp(query.Asc)}, - Limit: query.Limit{Count: w.eventPollerCfg.QueryCount}, - } - if cursor != "" { - limitAndSort.Limit = query.CursorLimit(cursor, query.CursorFollowing, w.eventPollerCfg.QueryCount) - } - - logsIter, err := reader.QueryKeys(ctx, keyQueries, limitAndSort) - if err != nil { - w.lggr.Errorw("failed to query keys", "err", err) - continue - } - - var logs []sequenceWithEventType - for eventType, log := range logsIter { - logs = append(logs, sequenceWithEventType{ - Sequence: log, - EventType: WorkflowRegistryEventType(eventType), - }) - } - w.lggr.Debugw("QueryKeys called", "logs", len(logs), "eventTypes", w.eventTypes, "lastReadBlockNumber", lastReadBlockNumber, "logCursor", cursor) - - // ChainReader QueryKey API provides logs including the cursor value and not - // after the cursor value. If the response only consists of the log corresponding - // to the cursor and no log after it, then we understand that there are no new - // logs - if len(logs) == 1 && logs[0].Sequence.Cursor == cursor { - w.lggr.Infow("No new logs since", "cursor", cursor) - continue - } - - var events []WorkflowRegistryEventResponse - for _, log := range logs { - if log.Sequence.Cursor == cursor { - continue - } - - events = append(events, toWorkflowRegistryEventResponse(log.Sequence, log.EventType, w.lggr)) - cursor = log.Sequence.Cursor - } - - for _, event := range events { - err := w.handler.Handle(ctx, event.Event) - if err != nil { - w.lggr.Errorw("failed to handle event", "err", err, "type", event.Event.EventType) - } - } - } - } -} - -// getTicker returns the ticker that the workflowRegistry will use to poll for events. If the ticker -// is nil, then a default ticker is returned. -func (w *workflowRegistry) getTicker() <-chan time.Time { - if w.ticker == nil { - return time.NewTicker(defaultTickInterval).C - } - - return w.ticker -} - -type sequenceWithEventType struct { - Sequence types.Sequence - EventType WorkflowRegistryEventType -} - -func (w *workflowRegistry) newWorkflowRegistryContractReader( - ctx context.Context, -) (ContractReader, error) { - bc := types.BoundContract{ - Name: WorkflowRegistryContractName, - Address: w.workflowRegistryAddress, - } - - contractReaderCfg := evmtypes.ChainReaderConfig{ - Contracts: map[string]evmtypes.ChainContractReader{ - WorkflowRegistryContractName: { - ContractPollingFilter: evmtypes.ContractPollingFilter{ - GenericEventNames: []string{ - string(ForceUpdateSecretsEvent), - string(WorkflowActivatedEvent), - string(WorkflowDeletedEvent), - string(WorkflowPausedEvent), - string(WorkflowRegisteredEvent), - string(WorkflowUpdatedEvent), - }, - }, - ContractABI: workflow_registry_wrapper.WorkflowRegistryABI, - Configs: map[string]*evmtypes.ChainReaderDefinition{ - GetWorkflowMetadataListByDONMethodName: { - ChainSpecificName: GetWorkflowMetadataListByDONMethodName, - }, - string(ForceUpdateSecretsEvent): { - ChainSpecificName: string(ForceUpdateSecretsEvent), - ReadType: evmtypes.Event, - }, - string(WorkflowActivatedEvent): { - ChainSpecificName: string(WorkflowActivatedEvent), - ReadType: evmtypes.Event, - }, - string(WorkflowDeletedEvent): { - ChainSpecificName: string(WorkflowDeletedEvent), - ReadType: evmtypes.Event, - }, - string(WorkflowPausedEvent): { - ChainSpecificName: string(WorkflowPausedEvent), - ReadType: evmtypes.Event, - }, - string(WorkflowRegisteredEvent): { - ChainSpecificName: string(WorkflowRegisteredEvent), - ReadType: evmtypes.Event, - }, - string(WorkflowUpdatedEvent): { - ChainSpecificName: string(WorkflowUpdatedEvent), - ReadType: evmtypes.Event, - }, - }, - }, - }, - } - - marshalledCfg, err := json.Marshal(contractReaderCfg) - if err != nil { - return nil, err - } - - reader, err := w.newContractReaderFn(ctx, marshalledCfg) - if err != nil { - return nil, err - } - - // bind contract to contract reader - if err := reader.Bind(ctx, []types.BoundContract{bc}); err != nil { - return nil, err - } - - if err := reader.Start(ctx); err != nil { - return nil, err - } - - return reader, nil -} - -type workflowAsEvent struct { - Data WorkflowRegistryWorkflowRegisteredV1 - EventType WorkflowRegistryEventType +func (w *WorkflowRegistry) Ready() error { + return nil } -func (r workflowAsEvent) GetEventType() WorkflowRegistryEventType { - return r.EventType +func (w *WorkflowRegistry) HealthReport() map[string]error { + return nil } -func (r workflowAsEvent) GetData() any { - return r.Data +func (w *WorkflowRegistry) Name() string { + return "WorkflowRegistrySyncer" } -func (w *workflowRegistry) loadWorkflows(ctx context.Context, don capabilities.DON, contractReader ContractReader) (*types.Head, error) { - contractBinding := types.BoundContract{ - Address: w.workflowRegistryAddress, - Name: WorkflowRegistryContractName, - } - - readIdentifier := contractBinding.ReadIdentifier(GetWorkflowMetadataListByDONMethodName) - params := GetWorkflowMetadataListByDONParams{ - DonID: don.ID, - Start: 0, - Limit: 0, // 0 tells the contract to return max pagination limit workflows on each call - } - - var headAtLastRead *types.Head - for { - var err error - var workflows GetWorkflowMetadataListByDONReturnVal - headAtLastRead, err = contractReader.GetLatestValueWithHeadData(ctx, readIdentifier, primitives.Finalized, params, &workflows) - if err != nil { - return nil, fmt.Errorf("failed to get lastest value with head data %w", err) - } - - w.lggr.Debugw("Rehydrating existing workflows", "len", len(workflows.WorkflowMetadataList)) - for _, workflow := range workflows.WorkflowMetadataList { - toRegisteredEvent := WorkflowRegistryWorkflowRegisteredV1{ - WorkflowID: workflow.WorkflowID, - WorkflowOwner: workflow.Owner, - DonID: workflow.DonID, - Status: workflow.Status, - WorkflowName: workflow.WorkflowName, - BinaryURL: workflow.BinaryURL, - ConfigURL: workflow.ConfigURL, - SecretsURL: workflow.SecretsURL, - } - if err = w.handler.Handle(ctx, workflowAsEvent{ - Data: toRegisteredEvent, - EventType: WorkflowRegisteredEvent, - }); err != nil { - w.lggr.Errorf("failed to handle workflow registration: %s", err) - } - } - - if len(workflows.WorkflowMetadataList) == 0 { - break - } - - params.Start += uint64(len(workflows.WorkflowMetadataList)) - } - - return headAtLastRead, nil +func (w *WorkflowRegistry) SecretsFor(workflowOwner, workflowName string) (map[string]string, error) { + // TODO: actually get this from the right place. + return map[string]string{}, nil } -// toWorkflowRegistryEventResponse converts a types.Sequence to a WorkflowRegistryEventResponse. -func toWorkflowRegistryEventResponse( - log types.Sequence, - evt WorkflowRegistryEventType, - lggr logger.Logger, -) WorkflowRegistryEventResponse { - resp := WorkflowRegistryEventResponse{ - Event: &WorkflowRegistryEvent{ - Cursor: log.Cursor, - EventType: evt, - Head: Head{ - Hash: hex.EncodeToString(log.Hash), - Height: log.Height, - Timestamp: log.Timestamp, - }, - }, - } - - dataAsValuesMap, err := values.WrapMap(log.Data) - if err != nil { - return WorkflowRegistryEventResponse{ - Err: err, - } - } - - switch evt { - case ForceUpdateSecretsEvent: - var data WorkflowRegistryForceUpdateSecretsRequestedV1 - if err := dataAsValuesMap.UnwrapTo(&data); err != nil { - lggr.Errorf("failed to unwrap data: %+v", log.Data) - resp.Event = nil - resp.Err = err - return resp - } - resp.Event.Data = data - case WorkflowRegisteredEvent: - var data WorkflowRegistryWorkflowRegisteredV1 - if err := dataAsValuesMap.UnwrapTo(&data); err != nil { - lggr.Errorf("failed to unwrap data: %+v", log.Data) - resp.Event = nil - resp.Err = err - return resp - } - resp.Event.Data = data - case WorkflowUpdatedEvent: - var data WorkflowRegistryWorkflowUpdatedV1 - if err := dataAsValuesMap.UnwrapTo(&data); err != nil { - lggr.Errorf("failed to unwrap data: %+v", log.Data) - resp.Event = nil - resp.Err = err - return resp - } - resp.Event.Data = data - case WorkflowPausedEvent: - var data WorkflowRegistryWorkflowPausedV1 - if err := dataAsValuesMap.UnwrapTo(&data); err != nil { - lggr.Errorf("failed to unwrap data: %+v", log.Data) - resp.Event = nil - resp.Err = err - return resp - } - resp.Event.Data = data - case WorkflowActivatedEvent: - var data WorkflowRegistryWorkflowActivatedV1 - if err := dataAsValuesMap.UnwrapTo(&data); err != nil { - lggr.Errorf("failed to unwrap data: %+v", log.Data) - resp.Event = nil - resp.Err = err - return resp - } - resp.Event.Data = data - case WorkflowDeletedEvent: - var data WorkflowRegistryWorkflowDeletedV1 - if err := dataAsValuesMap.UnwrapTo(&data); err != nil { - lggr.Errorf("failed to unwrap data: %+v", log.Data) - resp.Event = nil - resp.Err = err - return resp - } - resp.Event.Data = data - default: - lggr.Errorf("unknown event type: %s", evt) - resp.Event = nil - resp.Err = fmt.Errorf("unknown event type: %s", evt) - } - - return resp +func NewWorkflowRegistry() *WorkflowRegistry { + return &WorkflowRegistry{} } diff --git a/core/services/workflows/test/break/cmd/main.go b/core/services/workflows/test/break/cmd/main.go index bf759f516c9..498d3b7b906 100644 --- a/core/services/workflows/test/break/cmd/main.go +++ b/core/services/workflows/test/break/cmd/main.go @@ -10,7 +10,12 @@ import ( ) func BuildWorkflow(config []byte) *sdk.WorkflowSpecFactory { - workflow := sdk.NewWorkflowSpecFactory() + workflow := sdk.NewWorkflowSpecFactory( + sdk.NewWorkflowParams{ + Name: "tester", + Owner: "ryan", + }, + ) triggerCfg := basictrigger.TriggerConfig{Name: "trigger", Number: 100} trigger := triggerCfg.New(workflow) diff --git a/core/services/workflows/test/wasm/cmd/main.go b/core/services/workflows/test/wasm/cmd/main.go index ed077365bcf..e496ab6ffa6 100644 --- a/core/services/workflows/test/wasm/cmd/main.go +++ b/core/services/workflows/test/wasm/cmd/main.go @@ -10,7 +10,12 @@ import ( ) func BuildWorkflow(config []byte) *sdk.WorkflowSpecFactory { - workflow := sdk.NewWorkflowSpecFactory() + workflow := sdk.NewWorkflowSpecFactory( + sdk.NewWorkflowParams{ + Name: "tester", + Owner: "ryan", + }, + ) triggerCfg := basictrigger.TriggerConfig{Name: "trigger", Number: 100} trigger := triggerCfg.New(workflow) diff --git a/core/store/dialects/dialects.go b/core/store/dialects/dialects.go new file mode 100644 index 00000000000..d250fa1b99b --- /dev/null +++ b/core/store/dialects/dialects.go @@ -0,0 +1,18 @@ +package dialects + +import ( + // need to make sure pgx driver is registered before opening connection + _ "github.com/jackc/pgx/v4/stdlib" +) + +// DialectName is a compiler enforced type used that maps to database dialect names +type DialectName string + +const ( + // Postgres represents the postgres dialect. + Postgres DialectName = "pgx" + // TransactionWrappedPostgres is useful for tests. + // When the connection is opened, it starts a transaction and all + // operations performed on the DB will be within that transaction. + TransactionWrappedPostgres DialectName = "txdb" +) diff --git a/core/store/migrate/migrate.go b/core/store/migrate/migrate.go index c8d4a0e9621..7c3d3deaaf0 100644 --- a/core/store/migrate/migrate.go +++ b/core/store/migrate/migrate.go @@ -105,6 +105,8 @@ func ensureMigrated(ctx context.Context, db *sql.DB, p *goose.Provider, provider } // insert records for existing migrations + //nolint + sql := fmt.Sprintf(`INSERT INTO %s (version_id, is_applied) VALUES ($1, true);`, providerTableName) return sqlutil.TransactDataSource(ctx, sqlxDB, nil, func(tx sqlutil.DataSource) error { for _, name := range names { diff --git a/core/store/migrate/migrations/0036_external_job_id.go b/core/store/migrate/migrations/0036_external_job_id.go index a32ff470d67..e8012da5e78 100644 --- a/core/store/migrate/migrations/0036_external_job_id.go +++ b/core/store/migrate/migrations/0036_external_job_id.go @@ -31,6 +31,7 @@ const ( ` ) +// nolint func Up36(ctx context.Context, tx *sql.Tx) error { // Add the external ID column and remove type specific ones. if _, err := tx.ExecContext(ctx, up36_1); err != nil { @@ -56,6 +57,7 @@ func Up36(ctx context.Context, tx *sql.Tx) error { stmt += ` AS vals(external_job_id, id) WHERE vals.id = j.id` if _, err := tx.ExecContext(ctx, stmt); err != nil { return err + } } @@ -66,6 +68,7 @@ func Up36(ctx context.Context, tx *sql.Tx) error { return nil } +// nolint func Down36(ctx context.Context, tx *sql.Tx) error { if _, err := tx.ExecContext(ctx, down36); err != nil { return err diff --git a/core/store/migrate/migrations/0054_remove_legacy_pipeline.go b/core/store/migrate/migrations/0054_remove_legacy_pipeline.go index fb4c473bdb2..6d3cb20b73d 100644 --- a/core/store/migrate/migrations/0054_remove_legacy_pipeline.go +++ b/core/store/migrate/migrations/0054_remove_legacy_pipeline.go @@ -32,6 +32,7 @@ type queryer interface { QueryRowContext(ctx context.Context, query string, args ...interface{}) *sql.Row } +// nolint func Up54(ctx context.Context, tx *sql.Tx) error { if err := CheckNoLegacyJobs(ctx, tx); err != nil { return err @@ -42,6 +43,7 @@ func Up54(ctx context.Context, tx *sql.Tx) error { return nil } +// nolint func Down54(ctx context.Context, tx *sql.Tx) error { return errors.New("irreversible migration") } diff --git a/core/store/migrate/migrations/0056_multichain.go b/core/store/migrate/migrations/0056_multichain.go index 39d7ec70b2b..c56ff0397f1 100644 --- a/core/store/migrate/migrations/0056_multichain.go +++ b/core/store/migrate/migrations/0056_multichain.go @@ -44,6 +44,7 @@ DROP TABLE nodes; DROP TABLE evm_chains; ` +// nolint func Up56(ctx context.Context, tx *sql.Tx) error { if _, err := tx.ExecContext(ctx, up56); err != nil { return err @@ -70,6 +71,7 @@ func Up56(ctx context.Context, tx *sql.Tx) error { return nil } +// nolint func Down56(ctx context.Context, tx *sql.Tx) error { _, err := tx.ExecContext(ctx, down56) if err != nil { diff --git a/core/store/migrate/migrations/0195_add_not_null_to_evm_chain_id_in_job_specs.go b/core/store/migrate/migrations/0195_add_not_null_to_evm_chain_id_in_job_specs.go index a689cd750eb..a2ecb50a1c9 100644 --- a/core/store/migrate/migrations/0195_add_not_null_to_evm_chain_id_in_job_specs.go +++ b/core/store/migrate/migrations/0195_add_not_null_to_evm_chain_id_in_job_specs.go @@ -33,6 +33,7 @@ const ( ` ) +// nolint func Up195(ctx context.Context, tx *sql.Tx) error { chainID, set := os.LookupEnv(env.EVMChainIDNotNullMigration0195) if set { @@ -57,6 +58,7 @@ func Up195(ctx context.Context, tx *sql.Tx) error { return errors.Wrap(err, "failed to add null constraints") } +// nolint func Down195(ctx context.Context, tx *sql.Tx) error { if _, err := tx.ExecContext(ctx, dropNullConstraintsFromSpecs); err != nil { return err diff --git a/core/store/migrate/migrations/0259_add_workflow_secrets.sql b/core/store/migrate/migrations/0259_add_workflow_secrets.sql deleted file mode 100644 index 420f7ed6e49..00000000000 --- a/core/store/migrate/migrations/0259_add_workflow_secrets.sql +++ /dev/null @@ -1,42 +0,0 @@ --- +goose Up --- +goose StatementBegin --- Create the workflow_artifacts table -CREATE TABLE workflow_secrets ( - id SERIAL PRIMARY KEY, - secrets_url TEXT, - secrets_url_hash TEXT UNIQUE, - contents TEXT -); - --- Create an index on the secrets_url_hash column -CREATE INDEX idx_secrets_url ON workflow_secrets(secrets_url); - --- Alter the workflow_specs table -ALTER TABLE workflow_specs -ADD COLUMN binary_url TEXT DEFAULT '', -ADD COLUMN config_url TEXT DEFAULT '', -ADD COLUMN secrets_id INT UNIQUE REFERENCES workflow_secrets(id) ON DELETE CASCADE; - --- Alter the config column type -ALTER TABLE workflow_specs -ALTER COLUMN config TYPE TEXT; --- +goose StatementEnd - --- +goose Down --- +goose StatementBegin -ALTER TABLE workflow_specs -DROP COLUMN IF EXISTS secrets_id, -DROP COLUMN IF EXISTS config_url, -DROP COLUMN IF EXISTS binary_url; - --- Change the config column back to character varying(255) -ALTER TABLE workflow_specs -ALTER COLUMN config TYPE CHARACTER VARYING(255); - --- Drop the index on the secrets_url_hash column -DROP INDEX IF EXISTS idx_secrets_url_hash; - --- Drop the workflow_artifacts table -DROP TABLE IF EXISTS workflow_secrets; --- +goose StatementEnd - diff --git a/core/store/migrate/migrations/0260_add_status_workflow_spec.sql b/core/store/migrate/migrations/0260_add_status_workflow_spec.sql deleted file mode 100644 index 66c38eef2f7..00000000000 --- a/core/store/migrate/migrations/0260_add_status_workflow_spec.sql +++ /dev/null @@ -1,9 +0,0 @@ --- +goose Up --- Add a `status` column to the `workflow_specs` table. -ALTER TABLE workflow_specs -ADD COLUMN status TEXT DEFAULT '' NOT NULL; - --- +goose Down --- Remove the `status` column from the `workflow_specs` table. -ALTER TABLE workflow_specs -DROP COLUMN status; \ No newline at end of file diff --git a/core/store/migrate/migrations/0261_remove_unique_constraint_secrets.sql b/core/store/migrate/migrations/0261_remove_unique_constraint_secrets.sql deleted file mode 100644 index 15f59d8ae28..00000000000 --- a/core/store/migrate/migrations/0261_remove_unique_constraint_secrets.sql +++ /dev/null @@ -1,10 +0,0 @@ --- +goose Up --- +goose StatementBegin --- unique constraint on workflow_owner and workflow_name -ALTER TABLE workflow_specs DROP CONSTRAINT workflow_specs_secrets_id_key; --- +goose StatementEnd - --- +goose Down --- +goose StatementBegin -ALTER TABLE workflow_specs ADD CONSTRAINT workflow_specs_secrets_id_key unique (secrets_id); --- +goose StatementEnd diff --git a/core/store/migrate/migrations/0262_add_solana_schema.sql b/core/store/migrate/migrations/0262_add_solana_schema.sql deleted file mode 100644 index 035d3ff3d61..00000000000 --- a/core/store/migrate/migrations/0262_add_solana_schema.sql +++ /dev/null @@ -1,72 +0,0 @@ --- +goose Up --- +goose StatementBegin --- This removes evm from the search path, to avoid risk of an unqualified query intended to act on a Solana table accidentally --- acting on the corresponding evm table. This makes schema qualification mandatory for all chain-specific queries. -SET search_path TO public; -CREATE SCHEMA solana; - -CREATE TABLE solana.log_poller_filters ( - id BIGSERIAL PRIMARY KEY, - chain_id TEXT NOT NULL, -- use human-readable name instead of genesis block hash to reduce index size by 50% - name TEXT NOT NULL, - address BYTEA NOT NULL, - event_name TEXT NOT NULL, - event_sig BYTEA NOT NULL, - starting_block BIGINT NOT NULL, - event_idl TEXT, - subkey_paths json, -- A list of subkeys to be indexed, represented by their json paths in the event struct. Forced to use json's 2d array as text[][] requires all paths to have equal length. - retention BIGINT NOT NULL DEFAULT 0, -- we don’t have to implement this initially, but good to include it in the schema - max_logs_kept BIGINT NOT NULL DEFAULT 0, -- same as retention, no need to implement yet - is_deleted BOOLEAN NOT NULL DEFAULT FALSE -); - -CREATE UNIQUE INDEX IF NOT EXISTS solana_log_poller_filter_name ON solana.log_poller_filters (chain_id, name) WHERE NOT is_deleted; - -CREATE TABLE solana.logs ( - id BIGSERIAL PRIMARY KEY, - filter_id BIGINT NOT NULL REFERENCES solana.log_poller_filters (id) ON DELETE CASCADE, - chain_id TEXT not null, -- use human-readable name instead of genesis block hash to reduce index size by 50% - log_index bigint not null, - block_hash bytea not null, - block_number bigint not null CHECK (block_number > 0), - block_timestamp timestamp with time zone not null, - address bytea not null, - event_sig bytea not null, - subkey_values bytea[] not null, - tx_hash bytea not null, - data bytea not null, - created_at timestamp with time zone not null, - expires_at timestamp with time zone null, -- null to indicate no timebase expiry - sequence_num bigint not null -); - -CREATE INDEX IF NOT EXISTS solana_logs_idx_by_timestamp ON solana.logs (chain_id, address, event_sig, block_timestamp, block_number); - -CREATE INDEX IF NOT EXISTS solana_logs_idx ON solana.logs (chain_id, block_number, address, event_sig); - -CREATE INDEX IF NOT EXISTS solana_logs_idx_subkey_one ON solana.logs ((subkey_values[1])); -CREATE INDEX IF NOT EXISTS solana_logs_idx_subkey_two ON solana.logs ((subkey_values[2])); -CREATE INDEX IF NOT EXISTS solana_logs_idx_subkey_three ON solana.logs ((subkey_values[3])); -CREATE INDEX IF NOT EXISTS solana_logs_idx_subkey_four ON solana.logs ((subkey_values[4])); - -CREATE INDEX IF NOT EXISTS solana_logs_idx_tx_hash ON solana.logs (tx_hash); - --- Useful for the current form of those queries: WHERE chain_id = $1 AND address = $2 AND event_sig = $3 ... ORDER BY block_number, log_index --- log_index is not included in this index because it increases the index size by ~ 10% for a likely negligible performance benefit -CREATE INDEX IF NOT EXISTS solana_logs_idx_chain_address_event_block ON solana.logs (chain_id, address, event_sig, block_number); - -CREATE UNIQUE INDEX IF NOT EXISTS solana_logs_idx_chain_filter_block_logindex ON solana.logs USING btree (chain_id, filter_id, block_number, log_index); - --- +goose StatementEnd - - --- +goose Down --- +goose StatementBegin - -DROP TABLE IF EXISTS solana.logs; -DROP TABLE IF EXISTS solana.log_poller_filters; - -DROP SCHEMA solana; - -SET search_path TO public,evm; --- +goose StatementEnd diff --git a/core/utils/big_math/big_math.go b/core/utils/big_math/big_math.go index 013991480ca..a82621b92f5 100644 --- a/core/utils/big_math/big_math.go +++ b/core/utils/big_math/big_math.go @@ -58,6 +58,7 @@ func Accumulate(s []*big.Int) (r *big.Int) { return } +// nolint var ( Zero = big.NewInt(0) One = big.NewInt(1) diff --git a/core/utils/crypto/keccak_256.go b/core/utils/crypto/keccak_256.go deleted file mode 100644 index b6218d72cf0..00000000000 --- a/core/utils/crypto/keccak_256.go +++ /dev/null @@ -1,16 +0,0 @@ -package crypto - -import ( - "golang.org/x/crypto/sha3" -) - -func Keccak256(input []byte) ([]byte, error) { - // Create a Keccak-256 hash - hash := sha3.NewLegacyKeccak256() - _, err := hash.Write(input) - if err != nil { - return nil, err - } - - return hash.Sum(nil), nil -} diff --git a/core/utils/files.go b/core/utils/files.go index 9736e1f6926..71b52a0ea0a 100644 --- a/core/utils/files.go +++ b/core/utils/files.go @@ -104,6 +104,7 @@ func EnsureFilepathMaxPerms(filepath string, perms os.FileMode) (err error) { // FileSize repesents a file size in bytes. type FileSize uint64 +// nolint const ( KB = 1000 MB = 1000 * KB diff --git a/core/utils/matches/matches.go b/core/utils/matches/matches.go deleted file mode 100644 index 90606af57e2..00000000000 --- a/core/utils/matches/matches.go +++ /dev/null @@ -1,21 +0,0 @@ -package matches - -import ( - "context" - - "github.com/stretchr/testify/mock" -) - -func anyContext(_ context.Context) bool { - return true -} - -func anyString(_ string) bool { - return true -} - -// AnyContext is an argument matcher that matches any argument of type context.Context. -var AnyContext = mock.MatchedBy(anyContext) - -// AnyString is an argument matcher that matches any argument of type string. -var AnyString = mock.MatchedBy(anyString) diff --git a/core/utils/testutils/heavyweight/orm.go b/core/utils/testutils/heavyweight/orm.go index 775eabab0c8..536515e02e4 100644 --- a/core/utils/testutils/heavyweight/orm.go +++ b/core/utils/testutils/heavyweight/orm.go @@ -14,13 +14,12 @@ import ( "github.com/jmoiron/sqlx" - pgcommon "github.com/smartcontractkit/chainlink-common/pkg/sqlutil/pg" "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" - "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest" "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" "github.com/smartcontractkit/chainlink/v2/core/services/pg" + "github.com/smartcontractkit/chainlink/v2/core/store/dialects" "github.com/smartcontractkit/chainlink/v2/core/store/models" "github.com/smartcontractkit/chainlink/v2/internal/testdb" ) @@ -54,10 +53,10 @@ const ( ) func (c Kind) PrepareDB(t testing.TB, overrideFn func(c *chainlink.Config, s *chainlink.Secrets)) (chainlink.GeneralConfig, *sqlx.DB) { - tests.SkipShort(t, "FullTestDB") + testutils.SkipShort(t, "FullTestDB") gcfg := configtest.NewGeneralConfigSimulated(t, func(c *chainlink.Config, s *chainlink.Secrets) { - c.Database.Dialect = pgcommon.Postgres + c.Database.Dialect = dialects.Postgres if overrideFn != nil { overrideFn(c, s) } @@ -66,7 +65,7 @@ func (c Kind) PrepareDB(t testing.TB, overrideFn func(c *chainlink.Config, s *ch require.NoError(t, os.MkdirAll(gcfg.RootDir(), 0700)) migrationTestDBURL, err := testdb.CreateOrReplace(gcfg.Database().URL(), generateName(), c != KindEmpty) require.NoError(t, err) - db, err := pg.NewConnection(tests.Context(t), migrationTestDBURL, pgcommon.Postgres, gcfg.Database()) + db, err := pg.NewConnection(tests.Context(t), migrationTestDBURL, dialects.Postgres, gcfg.Database()) require.NoError(t, err) t.Cleanup(func() { require.NoError(t, db.Close()) // must close before dropping @@ -75,7 +74,7 @@ func (c Kind) PrepareDB(t testing.TB, overrideFn func(c *chainlink.Config, s *ch }) gcfg = configtest.NewGeneralConfigSimulated(t, func(c *chainlink.Config, s *chainlink.Secrets) { - c.Database.Dialect = pgcommon.Postgres + c.Database.Dialect = dialects.Postgres s.Database.URL = models.MustSecretURL(migrationTestDBURL) if overrideFn != nil { overrideFn(c, s) diff --git a/core/utils/utils.go b/core/utils/utils.go index 98c2607baff..7ac97fabb21 100644 --- a/core/utils/utils.go +++ b/core/utils/utils.go @@ -595,6 +595,8 @@ func (eb *ErrorBuffer) SetCap(cap int) { } // UnwrapError returns a list of underlying errors if passed error implements joinedError or return the err in a single-element list otherwise. +// +//nolint:errorlint // error type checks will fail on wrapped errors. Disabled since we are not doing checks on error types. func UnwrapError(err error) []error { joined, ok := err.(interface{ Unwrap() []error }) if !ok { diff --git a/core/web/assets/index.html b/core/web/assets/index.html index ae1aac9ede0..d5b24848b5d 100644 --- a/core/web/assets/index.html +++ b/core/web/assets/index.html @@ -1 +1 @@ -Operator UIChainlink
\ No newline at end of file +Operator UIChainlink
\ No newline at end of file diff --git a/core/web/assets/index.html.gz b/core/web/assets/index.html.gz index a65173c97c81ceb7da51eee8443c4d0395a6644d..6ab5d6b95afa8044415a00b2530b1911615be8db 100644 GIT binary patch literal 421 zcmV;W0b2eaiwFP!000021C^3NYa1~Th5w2w$f@>f<2a2Iq|G5vNTC#(=8)r9JL{cR z(k#+=6aV|NYsXM1lwKtCV7@o=H1{9&$l(`uWG_$+ZC*R?)1 zDu;ljNBl4HG}Sx$D+p$S@bS@eD*wWo4#uf^8d3i>tLa0XrU*MUZ_8ObhyL)M&^hwr zGYz6z>@Yh$Us{#yoiv@MN_TBkF!Og=4*jWtKS PnOF5Uxc_T2zybgOcM8mr literal 420 zcmV;V0bBkbiwFP!000021C^3bYa1~T#lMOw=&A8)Z70niq|G5vNTC#(=FsC{g|oXF$i@VKB%LJ$|#LqxZn8A1}V`#NF);i8@&tvO0I zQvRh1MyKn*Mf^?_dCpo51$(Clk+I$xQxg=KO$&HwC~fJr$tcDTKzU{~phNJxp`;Jfi+&8)#A#oG#2V`vjUgYmRtx OSk>QPQcP380ssJ`k;5qf diff --git a/core/web/assets/main.008c37495ba29761321d.js b/core/web/assets/main.57f94389bc8271642420.js similarity index 90% rename from core/web/assets/main.008c37495ba29761321d.js rename to core/web/assets/main.57f94389bc8271642420.js index b9feeec3d83..99b5c06781a 100644 --- a/core/web/assets/main.008c37495ba29761321d.js +++ b/core/web/assets/main.57f94389bc8271642420.js @@ -168,7 +168,7 @@ object-assign * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. - */ Object.defineProperty(t,"__esModule",{value:!0}),"undefined"==typeof window||"function"!=typeof MessageChannel){var n,r,i,a,o,s=null,u=null,c=function(){if(null!==s)try{var e=t.unstable_now();s(!0,e),s=null}catch(n){throw setTimeout(c,0),n}},l=Date.now();t.unstable_now=function(){return Date.now()-l},n=function(e){null!==s?setTimeout(n,0,e):(s=e,setTimeout(c,0))},r=function(e,t){u=setTimeout(e,t)},i=function(){clearTimeout(u)},a=function(){return!1},o=t.unstable_forceFrameRate=function(){}}else{var f=window.performance,d=window.Date,h=window.setTimeout,p=window.clearTimeout;if("undefined"!=typeof console){var b=window.cancelAnimationFrame;"function"!=typeof window.requestAnimationFrame&&console.error("This browser doesn't support requestAnimationFrame. Make sure that you load a polyfill in older browsers. https://fb.me/react-polyfills"),"function"!=typeof b&&console.error("This browser doesn't support cancelAnimationFrame. Make sure that you load a polyfill in older browsers. https://fb.me/react-polyfills")}if("object"==typeof f&&"function"==typeof f.now)t.unstable_now=function(){return f.now()};else{var m=d.now();t.unstable_now=function(){return d.now()-m}}var g=!1,v=null,y=-1,w=5,_=0;a=function(){return t.unstable_now()>=_},o=function(){},t.unstable_forceFrameRate=function(e){0>e||125M(o,n))void 0!==u&&0>M(u,o)?(e[r]=u,e[s]=n,r=s):(e[r]=o,e[a]=n,r=a);else if(void 0!==u&&0>M(u,n))e[r]=u,e[s]=n,r=s;else break a}}return t}return null}function M(e,t){var n=e.sortIndex-t.sortIndex;return 0!==n?n:e.id-t.id}var O=[],A=[],L=1,C=null,I=3,D=!1,N=!1,P=!1;function R(e){for(var t=x(A);null!==t;){if(null===t.callback)T(A);else if(t.startTime<=e)T(A),t.sortIndex=t.expirationTime,k(O,t);else break;t=x(A)}}function j(e){if(P=!1,R(e),!N){if(null!==x(O))N=!0,n(F);else{var t=x(A);null!==t&&r(j,t.startTime-e)}}}function F(e,n){N=!1,P&&(P=!1,i()),D=!0;var o=I;try{for(R(n),C=x(O);null!==C&&(!(C.expirationTime>n)||e&&!a());){var s=C.callback;if(null!==s){C.callback=null,I=C.priorityLevel;var u=s(C.expirationTime<=n);n=t.unstable_now(),"function"==typeof u?C.callback=u:C===x(O)&&T(O),R(n)}else T(O);C=x(O)}if(null!==C)var c=!0;else{var l=x(A);null!==l&&r(j,l.startTime-n),c=!1}return c}finally{C=null,I=o,D=!1}}function Y(e){switch(e){case 1:return -1;case 2:return 250;case 5:return 1073741823;case 4:return 1e4;default:return 5e3}}var B=o;t.unstable_ImmediatePriority=1,t.unstable_UserBlockingPriority=2,t.unstable_NormalPriority=3,t.unstable_IdlePriority=5,t.unstable_LowPriority=4,t.unstable_runWithPriority=function(e,t){switch(e){case 1:case 2:case 3:case 4:case 5:break;default:e=3}var n=I;I=e;try{return t()}finally{I=n}},t.unstable_next=function(e){switch(I){case 1:case 2:case 3:var t=3;break;default:t=I}var n=I;I=t;try{return e()}finally{I=n}},t.unstable_scheduleCallback=function(e,a,o){var s=t.unstable_now();if("object"==typeof o&&null!==o){var u=o.delay;u="number"==typeof u&&0s?(e.sortIndex=u,k(A,e),null===x(O)&&e===x(A)&&(P?i():P=!0,r(j,u-s))):(e.sortIndex=o,k(O,e),N||D||(N=!0,n(F))),e},t.unstable_cancelCallback=function(e){e.callback=null},t.unstable_wrapCallback=function(e){var t=I;return function(){var n=I;I=t;try{return e.apply(this,arguments)}finally{I=n}}},t.unstable_getCurrentPriorityLevel=function(){return I},t.unstable_shouldYield=function(){var e=t.unstable_now();R(e);var n=x(O);return n!==C&&null!==C&&null!==n&&null!==n.callback&&n.startTime<=e&&n.expirationTime>5==6?2:e>>4==14?3:e>>3==30?4:e>>6==2?-1:-2}function c(e,t,n){var r=t.length-1;if(r=0?(i>0&&(e.lastNeed=i-1),i):--r=0?(i>0&&(e.lastNeed=i-2),i):--r=0?(i>0&&(2===i?i=0:e.lastNeed=i-3),i):0}function l(e,t,n){if((192&t[0])!=128)return e.lastNeed=0,"�";if(e.lastNeed>1&&t.length>1){if((192&t[1])!=128)return e.lastNeed=1,"�";if(e.lastNeed>2&&t.length>2&&(192&t[2])!=128)return e.lastNeed=2,"�"}}function f(e){var t=this.lastTotal-this.lastNeed,n=l(this,e,t);return void 0!==n?n:this.lastNeed<=e.length?(e.copy(this.lastChar,t,0,this.lastNeed),this.lastChar.toString(this.encoding,0,this.lastTotal)):void(e.copy(this.lastChar,t,0,e.length),this.lastNeed-=e.length)}function d(e,t){var n=c(this,e,t);if(!this.lastNeed)return e.toString("utf8",t);this.lastTotal=n;var r=e.length-(n-this.lastNeed);return e.copy(this.lastChar,0,r),e.toString("utf8",t,r)}function h(e){var t=e&&e.length?this.write(e):"";return this.lastNeed?t+"�":t}function p(e,t){if((e.length-t)%2==0){var n=e.toString("utf16le",t);if(n){var r=n.charCodeAt(n.length-1);if(r>=55296&&r<=56319)return this.lastNeed=2,this.lastTotal=4,this.lastChar[0]=e[e.length-2],this.lastChar[1]=e[e.length-1],n.slice(0,-1)}return n}return this.lastNeed=1,this.lastTotal=2,this.lastChar[0]=e[e.length-1],e.toString("utf16le",t,e.length-1)}function b(e){var t=e&&e.length?this.write(e):"";if(this.lastNeed){var n=this.lastTotal-this.lastNeed;return t+this.lastChar.toString("utf16le",0,n)}return t}function m(e,t){var n=(e.length-t)%3;return 0===n?e.toString("base64",t):(this.lastNeed=3-n,this.lastTotal=3,1===n?this.lastChar[0]=e[e.length-1]:(this.lastChar[0]=e[e.length-2],this.lastChar[1]=e[e.length-1]),e.toString("base64",t,e.length-n))}function g(e){var t=e&&e.length?this.write(e):"";return this.lastNeed?t+this.lastChar.toString("base64",0,3-this.lastNeed):t}function v(e){return e.toString(this.encoding)}function y(e){return e&&e.length?this.write(e):""}t.s=s,s.prototype.write=function(e){var t,n;if(0===e.length)return"";if(this.lastNeed){if(void 0===(t=this.fillLast(e)))return"";n=this.lastNeed,this.lastNeed=0}else n=0;return n */ var r=n(48764),i=r.Buffer;function a(e,t){for(var n in e)t[n]=e[n]}function o(e,t,n){return i(e,t,n)}i.from&&i.alloc&&i.allocUnsafe&&i.allocUnsafeSlow?e.exports=r:(a(r,t),t.Buffer=o),o.prototype=Object.create(i.prototype),a(i,o),o.from=function(e,t,n){if("number"==typeof e)throw TypeError("Argument must not be a number");return i(e,t,n)},o.alloc=function(e,t,n){if("number"!=typeof e)throw TypeError("Argument must be a number");var r=i(e);return void 0!==t?"string"==typeof n?r.fill(t,n):r.fill(t):r.fill(0),r},o.allocUnsafe=function(e){if("number"!=typeof e)throw TypeError("Argument must be a number");return i(e)},o.allocUnsafeSlow=function(e){if("number"!=typeof e)throw TypeError("Argument must be a number");return r.SlowBuffer(e)}},93379(e,t,n){"use strict";var r,i,a=function(){return void 0===r&&(r=Boolean(window&&document&&document.all&&!window.atob)),r},o=(i={},function(e){if(void 0===i[e]){var t=document.querySelector(e);if(window.HTMLIFrameElement&&t instanceof window.HTMLIFrameElement)try{t=t.contentDocument.head}catch(n){t=null}i[e]=t}return i[e]}),s=[];function u(e){for(var t=-1,n=0;nAp});var r,i,a,o,s,u,c,l=n(67294),f=n.t(l,2),d=n(39814),h=n(5977),p=n(57209),b=n(32316),m=n(95880),g=n(17051),v=n(71381),y=n(81701),w=n(3022),_=n(60323),E=n(87591),S=n(25649),k=n(28902),x=n(71426),T=n(48884),M=n(94184),O=n.n(M),A=n(37703),L=n(73935),C=function(){if("undefined"!=typeof Map)return Map;function e(e,t){var n=-1;return e.some(function(e,r){return e[0]===t&&(n=r,!0)}),n}return function(){function t(){this.__entries__=[]}return Object.defineProperty(t.prototype,"size",{get:function(){return this.__entries__.length},enumerable:!0,configurable:!0}),t.prototype.get=function(t){var n=e(this.__entries__,t),r=this.__entries__[n];return r&&r[1]},t.prototype.set=function(t,n){var r=e(this.__entries__,t);~r?this.__entries__[r][1]=n:this.__entries__.push([t,n])},t.prototype.delete=function(t){var n=this.__entries__,r=e(n,t);~r&&n.splice(r,1)},t.prototype.has=function(t){return!!~e(this.__entries__,t)},t.prototype.clear=function(){this.__entries__.splice(0)},t.prototype.forEach=function(e,t){void 0===t&&(t=null);for(var n=0,r=this.__entries__;n0},e.prototype.connect_=function(){I&&!this.connected_&&(document.addEventListener("transitionend",this.onTransitionEnd_),window.addEventListener("resize",this.refresh),Y?(this.mutationsObserver_=new MutationObserver(this.refresh),this.mutationsObserver_.observe(document,{attributes:!0,childList:!0,characterData:!0,subtree:!0})):(document.addEventListener("DOMSubtreeModified",this.refresh),this.mutationEventsAdded_=!0),this.connected_=!0)},e.prototype.disconnect_=function(){I&&this.connected_&&(document.removeEventListener("transitionend",this.onTransitionEnd_),window.removeEventListener("resize",this.refresh),this.mutationsObserver_&&this.mutationsObserver_.disconnect(),this.mutationEventsAdded_&&document.removeEventListener("DOMSubtreeModified",this.refresh),this.mutationsObserver_=null,this.mutationEventsAdded_=!1,this.connected_=!1)},e.prototype.onTransitionEnd_=function(e){var t=e.propertyName,n=void 0===t?"":t;F.some(function(e){return!!~n.indexOf(e)})&&this.refresh()},e.getInstance=function(){return this.instance_||(this.instance_=new e),this.instance_},e.instance_=null,e}(),U=function(e,t){for(var n=0,r=Object.keys(t);n0},e}(),er="undefined"!=typeof WeakMap?new WeakMap:new C,ei=function(){function e(t){if(!(this instanceof e))throw TypeError("Cannot call a class as a function.");if(!arguments.length)throw TypeError("1 argument required, but only 0 present.");var n=B.getInstance(),r=new en(t,n,this);er.set(this,r)}return e}();["observe","unobserve","disconnect"].forEach(function(e){ei.prototype[e]=function(){var t;return(t=er.get(this))[e].apply(t,arguments)}});var ea=void 0!==D.ResizeObserver?D.ResizeObserver:ei;let eo=ea;var es=function(e){var t=[],n=null,r=function(){for(var r=arguments.length,i=Array(r),a=0;a=t||n<0||f&&r>=a}function g(){var e=eb();if(m(e))return v(e);s=setTimeout(g,b(e))}function v(e){return(s=void 0,d&&r)?h(e):(r=i=void 0,o)}function y(){void 0!==s&&clearTimeout(s),c=0,r=u=i=s=void 0}function w(){return void 0===s?o:v(eb())}function _(){var e=eb(),n=m(e);if(r=arguments,i=this,u=e,n){if(void 0===s)return p(u);if(f)return clearTimeout(s),s=setTimeout(g,t),h(u)}return void 0===s&&(s=setTimeout(g,t)),o}return t=ez(t)||0,ed(n)&&(l=!!n.leading,a=(f="maxWait"in n)?eW(ez(n.maxWait)||0,t):a,d="trailing"in n?!!n.trailing:d),_.cancel=y,_.flush=w,_}let eq=eV;var eZ="Expected a function";function eX(e,t,n){var r=!0,i=!0;if("function"!=typeof e)throw TypeError(eZ);return ed(n)&&(r="leading"in n?!!n.leading:r,i="trailing"in n?!!n.trailing:i),eq(e,t,{leading:r,maxWait:t,trailing:i})}let eJ=eX;var eQ={debounce:eq,throttle:eJ},e1=function(e){return eQ[e]},e0=function(e){return"function"==typeof e},e2=function(){return"undefined"==typeof window},e3=function(e){return e instanceof Element||e instanceof HTMLDocument};function e4(e){return(e4="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e})(e)}function e6(e,t){if(!(e instanceof t))throw TypeError("Cannot call a class as a function")}function e5(e,t){for(var n=0;ne.length)&&(t=e.length);for(var n=0,r=Array(t);ne.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&l.createElement(tG.Z,{variant:"indeterminate",classes:r}))};tK.propTypes={fetchCount:el().number.isRequired};let tV=(0,b.withStyles)(tW)(tK);var tq=n(5536);let tZ=n.p+"ba8bbf16ebf8e1d05bef.svg";function tX(){return(tX=Object.assign||function(e){for(var t=1;t120){for(var d=Math.floor(u/80),h=u%80,p=[],b=0;b0},name:{enumerable:!1},nodes:{enumerable:!1},source:{enumerable:!1},positions:{enumerable:!1},originalError:{enumerable:!1}}),null!=s&&s.stack)?(Object.defineProperty(nf(b),"stack",{value:s.stack,writable:!0,configurable:!0}),nl(b)):(Error.captureStackTrace?Error.captureStackTrace(nf(b),n):Object.defineProperty(nf(b),"stack",{value:Error().stack,writable:!0,configurable:!0}),b)}return ns(n,[{key:"toString",value:function(){return nw(this)}},{key:t4.YF,get:function(){return"Object"}}]),n}(nd(Error));function ny(e){return void 0===e||0===e.length?void 0:e}function nw(e){var t=e.message;if(e.nodes)for(var n=0,r=e.nodes;n",EOF:"",BANG:"!",DOLLAR:"$",AMP:"&",PAREN_L:"(",PAREN_R:")",SPREAD:"...",COLON:":",EQUALS:"=",AT:"@",BRACKET_L:"[",BRACKET_R:"]",BRACE_L:"{",PIPE:"|",BRACE_R:"}",NAME:"Name",INT:"Int",FLOAT:"Float",STRING:"String",BLOCK_STRING:"BlockString",COMMENT:"Comment"}),nx=n(10143),nT=Object.freeze({QUERY:"QUERY",MUTATION:"MUTATION",SUBSCRIPTION:"SUBSCRIPTION",FIELD:"FIELD",FRAGMENT_DEFINITION:"FRAGMENT_DEFINITION",FRAGMENT_SPREAD:"FRAGMENT_SPREAD",INLINE_FRAGMENT:"INLINE_FRAGMENT",VARIABLE_DEFINITION:"VARIABLE_DEFINITION",SCHEMA:"SCHEMA",SCALAR:"SCALAR",OBJECT:"OBJECT",FIELD_DEFINITION:"FIELD_DEFINITION",ARGUMENT_DEFINITION:"ARGUMENT_DEFINITION",INTERFACE:"INTERFACE",UNION:"UNION",ENUM:"ENUM",ENUM_VALUE:"ENUM_VALUE",INPUT_OBJECT:"INPUT_OBJECT",INPUT_FIELD_DEFINITION:"INPUT_FIELD_DEFINITION"}),nM=n(87392),nO=function(){function e(e){var t=new nS.WU(nk.SOF,0,0,0,0,null);this.source=e,this.lastToken=t,this.token=t,this.line=1,this.lineStart=0}var t=e.prototype;return t.advance=function(){return this.lastToken=this.token,this.token=this.lookahead()},t.lookahead=function(){var e,t=this.token;if(t.kind!==nk.EOF)do t=null!==(e=t.next)&&void 0!==e?e:t.next=nC(this,t);while(t.kind===nk.COMMENT)return t},e}();function nA(e){return e===nk.BANG||e===nk.DOLLAR||e===nk.AMP||e===nk.PAREN_L||e===nk.PAREN_R||e===nk.SPREAD||e===nk.COLON||e===nk.EQUALS||e===nk.AT||e===nk.BRACKET_L||e===nk.BRACKET_R||e===nk.BRACE_L||e===nk.PIPE||e===nk.BRACE_R}function nL(e){return isNaN(e)?nk.EOF:e<127?JSON.stringify(String.fromCharCode(e)):'"\\u'.concat(("00"+e.toString(16).toUpperCase()).slice(-4),'"')}function nC(e,t){for(var n=e.source,r=n.body,i=r.length,a=t.end;a31||9===a))return new nS.WU(nk.COMMENT,t,s,n,r,i,o.slice(t+1,s))}function nN(e,t,n,r,i,a){var o=e.body,s=n,u=t,c=!1;if(45===s&&(s=o.charCodeAt(++u)),48===s){if((s=o.charCodeAt(++u))>=48&&s<=57)throw n_(e,u,"Invalid number, unexpected digit after 0: ".concat(nL(s),"."))}else u=nP(e,u,s),s=o.charCodeAt(u);if(46===s&&(c=!0,s=o.charCodeAt(++u),u=nP(e,u,s),s=o.charCodeAt(u)),(69===s||101===s)&&(c=!0,(43===(s=o.charCodeAt(++u))||45===s)&&(s=o.charCodeAt(++u)),u=nP(e,u,s),s=o.charCodeAt(u)),46===s||nU(s))throw n_(e,u,"Invalid number, expected digit but got: ".concat(nL(s),"."));return new nS.WU(c?nk.FLOAT:nk.INT,t,u,r,i,a,o.slice(t,u))}function nP(e,t,n){var r=e.body,i=t,a=n;if(a>=48&&a<=57){do a=r.charCodeAt(++i);while(a>=48&&a<=57)return i}throw n_(e,i,"Invalid number, expected digit but got: ".concat(nL(a),"."))}function nR(e,t,n,r,i){for(var a=e.body,o=t+1,s=o,u=0,c="";o=48&&e<=57?e-48:e>=65&&e<=70?e-55:e>=97&&e<=102?e-87:-1}function nB(e,t,n,r,i){for(var a=e.body,o=a.length,s=t+1,u=0;s!==o&&!isNaN(u=a.charCodeAt(s))&&(95===u||u>=48&&u<=57||u>=65&&u<=90||u>=97&&u<=122);)++s;return new nS.WU(nk.NAME,t,s,n,r,i,a.slice(t,s))}function nU(e){return 95===e||e>=65&&e<=90||e>=97&&e<=122}function nH(e,t){return new n$(e,t).parseDocument()}var n$=function(){function e(e,t){var n=(0,nx.T)(e)?e:new nx.H(e);this._lexer=new nO(n),this._options=t}var t=e.prototype;return t.parseName=function(){var e=this.expectToken(nk.NAME);return{kind:nE.h.NAME,value:e.value,loc:this.loc(e)}},t.parseDocument=function(){var e=this._lexer.token;return{kind:nE.h.DOCUMENT,definitions:this.many(nk.SOF,this.parseDefinition,nk.EOF),loc:this.loc(e)}},t.parseDefinition=function(){if(this.peek(nk.NAME))switch(this._lexer.token.value){case"query":case"mutation":case"subscription":return this.parseOperationDefinition();case"fragment":return this.parseFragmentDefinition();case"schema":case"scalar":case"type":case"interface":case"union":case"enum":case"input":case"directive":return this.parseTypeSystemDefinition();case"extend":return this.parseTypeSystemExtension()}else if(this.peek(nk.BRACE_L))return this.parseOperationDefinition();else if(this.peekDescription())return this.parseTypeSystemDefinition();throw this.unexpected()},t.parseOperationDefinition=function(){var e,t=this._lexer.token;if(this.peek(nk.BRACE_L))return{kind:nE.h.OPERATION_DEFINITION,operation:"query",name:void 0,variableDefinitions:[],directives:[],selectionSet:this.parseSelectionSet(),loc:this.loc(t)};var n=this.parseOperationType();return this.peek(nk.NAME)&&(e=this.parseName()),{kind:nE.h.OPERATION_DEFINITION,operation:n,name:e,variableDefinitions:this.parseVariableDefinitions(),directives:this.parseDirectives(!1),selectionSet:this.parseSelectionSet(),loc:this.loc(t)}},t.parseOperationType=function(){var e=this.expectToken(nk.NAME);switch(e.value){case"query":return"query";case"mutation":return"mutation";case"subscription":return"subscription"}throw this.unexpected(e)},t.parseVariableDefinitions=function(){return this.optionalMany(nk.PAREN_L,this.parseVariableDefinition,nk.PAREN_R)},t.parseVariableDefinition=function(){var e=this._lexer.token;return{kind:nE.h.VARIABLE_DEFINITION,variable:this.parseVariable(),type:(this.expectToken(nk.COLON),this.parseTypeReference()),defaultValue:this.expectOptionalToken(nk.EQUALS)?this.parseValueLiteral(!0):void 0,directives:this.parseDirectives(!0),loc:this.loc(e)}},t.parseVariable=function(){var e=this._lexer.token;return this.expectToken(nk.DOLLAR),{kind:nE.h.VARIABLE,name:this.parseName(),loc:this.loc(e)}},t.parseSelectionSet=function(){var e=this._lexer.token;return{kind:nE.h.SELECTION_SET,selections:this.many(nk.BRACE_L,this.parseSelection,nk.BRACE_R),loc:this.loc(e)}},t.parseSelection=function(){return this.peek(nk.SPREAD)?this.parseFragment():this.parseField()},t.parseField=function(){var e,t,n=this._lexer.token,r=this.parseName();return this.expectOptionalToken(nk.COLON)?(e=r,t=this.parseName()):t=r,{kind:nE.h.FIELD,alias:e,name:t,arguments:this.parseArguments(!1),directives:this.parseDirectives(!1),selectionSet:this.peek(nk.BRACE_L)?this.parseSelectionSet():void 0,loc:this.loc(n)}},t.parseArguments=function(e){var t=e?this.parseConstArgument:this.parseArgument;return this.optionalMany(nk.PAREN_L,t,nk.PAREN_R)},t.parseArgument=function(){var e=this._lexer.token,t=this.parseName();return this.expectToken(nk.COLON),{kind:nE.h.ARGUMENT,name:t,value:this.parseValueLiteral(!1),loc:this.loc(e)}},t.parseConstArgument=function(){var e=this._lexer.token;return{kind:nE.h.ARGUMENT,name:this.parseName(),value:(this.expectToken(nk.COLON),this.parseValueLiteral(!0)),loc:this.loc(e)}},t.parseFragment=function(){var e=this._lexer.token;this.expectToken(nk.SPREAD);var t=this.expectOptionalKeyword("on");return!t&&this.peek(nk.NAME)?{kind:nE.h.FRAGMENT_SPREAD,name:this.parseFragmentName(),directives:this.parseDirectives(!1),loc:this.loc(e)}:{kind:nE.h.INLINE_FRAGMENT,typeCondition:t?this.parseNamedType():void 0,directives:this.parseDirectives(!1),selectionSet:this.parseSelectionSet(),loc:this.loc(e)}},t.parseFragmentDefinition=function(){var e,t=this._lexer.token;return(this.expectKeyword("fragment"),(null===(e=this._options)||void 0===e?void 0:e.experimentalFragmentVariables)===!0)?{kind:nE.h.FRAGMENT_DEFINITION,name:this.parseFragmentName(),variableDefinitions:this.parseVariableDefinitions(),typeCondition:(this.expectKeyword("on"),this.parseNamedType()),directives:this.parseDirectives(!1),selectionSet:this.parseSelectionSet(),loc:this.loc(t)}:{kind:nE.h.FRAGMENT_DEFINITION,name:this.parseFragmentName(),typeCondition:(this.expectKeyword("on"),this.parseNamedType()),directives:this.parseDirectives(!1),selectionSet:this.parseSelectionSet(),loc:this.loc(t)}},t.parseFragmentName=function(){if("on"===this._lexer.token.value)throw this.unexpected();return this.parseName()},t.parseValueLiteral=function(e){var t=this._lexer.token;switch(t.kind){case nk.BRACKET_L:return this.parseList(e);case nk.BRACE_L:return this.parseObject(e);case nk.INT:return this._lexer.advance(),{kind:nE.h.INT,value:t.value,loc:this.loc(t)};case nk.FLOAT:return this._lexer.advance(),{kind:nE.h.FLOAT,value:t.value,loc:this.loc(t)};case nk.STRING:case nk.BLOCK_STRING:return this.parseStringLiteral();case nk.NAME:switch(this._lexer.advance(),t.value){case"true":return{kind:nE.h.BOOLEAN,value:!0,loc:this.loc(t)};case"false":return{kind:nE.h.BOOLEAN,value:!1,loc:this.loc(t)};case"null":return{kind:nE.h.NULL,loc:this.loc(t)};default:return{kind:nE.h.ENUM,value:t.value,loc:this.loc(t)}}case nk.DOLLAR:if(!e)return this.parseVariable()}throw this.unexpected()},t.parseStringLiteral=function(){var e=this._lexer.token;return this._lexer.advance(),{kind:nE.h.STRING,value:e.value,block:e.kind===nk.BLOCK_STRING,loc:this.loc(e)}},t.parseList=function(e){var t=this,n=this._lexer.token,r=function(){return t.parseValueLiteral(e)};return{kind:nE.h.LIST,values:this.any(nk.BRACKET_L,r,nk.BRACKET_R),loc:this.loc(n)}},t.parseObject=function(e){var t=this,n=this._lexer.token,r=function(){return t.parseObjectField(e)};return{kind:nE.h.OBJECT,fields:this.any(nk.BRACE_L,r,nk.BRACE_R),loc:this.loc(n)}},t.parseObjectField=function(e){var t=this._lexer.token,n=this.parseName();return this.expectToken(nk.COLON),{kind:nE.h.OBJECT_FIELD,name:n,value:this.parseValueLiteral(e),loc:this.loc(t)}},t.parseDirectives=function(e){for(var t=[];this.peek(nk.AT);)t.push(this.parseDirective(e));return t},t.parseDirective=function(e){var t=this._lexer.token;return this.expectToken(nk.AT),{kind:nE.h.DIRECTIVE,name:this.parseName(),arguments:this.parseArguments(e),loc:this.loc(t)}},t.parseTypeReference=function(){var e,t=this._lexer.token;return(this.expectOptionalToken(nk.BRACKET_L)?(e=this.parseTypeReference(),this.expectToken(nk.BRACKET_R),e={kind:nE.h.LIST_TYPE,type:e,loc:this.loc(t)}):e=this.parseNamedType(),this.expectOptionalToken(nk.BANG))?{kind:nE.h.NON_NULL_TYPE,type:e,loc:this.loc(t)}:e},t.parseNamedType=function(){var e=this._lexer.token;return{kind:nE.h.NAMED_TYPE,name:this.parseName(),loc:this.loc(e)}},t.parseTypeSystemDefinition=function(){var e=this.peekDescription()?this._lexer.lookahead():this._lexer.token;if(e.kind===nk.NAME)switch(e.value){case"schema":return this.parseSchemaDefinition();case"scalar":return this.parseScalarTypeDefinition();case"type":return this.parseObjectTypeDefinition();case"interface":return this.parseInterfaceTypeDefinition();case"union":return this.parseUnionTypeDefinition();case"enum":return this.parseEnumTypeDefinition();case"input":return this.parseInputObjectTypeDefinition();case"directive":return this.parseDirectiveDefinition()}throw this.unexpected(e)},t.peekDescription=function(){return this.peek(nk.STRING)||this.peek(nk.BLOCK_STRING)},t.parseDescription=function(){if(this.peekDescription())return this.parseStringLiteral()},t.parseSchemaDefinition=function(){var e=this._lexer.token,t=this.parseDescription();this.expectKeyword("schema");var n=this.parseDirectives(!0),r=this.many(nk.BRACE_L,this.parseOperationTypeDefinition,nk.BRACE_R);return{kind:nE.h.SCHEMA_DEFINITION,description:t,directives:n,operationTypes:r,loc:this.loc(e)}},t.parseOperationTypeDefinition=function(){var e=this._lexer.token,t=this.parseOperationType();this.expectToken(nk.COLON);var n=this.parseNamedType();return{kind:nE.h.OPERATION_TYPE_DEFINITION,operation:t,type:n,loc:this.loc(e)}},t.parseScalarTypeDefinition=function(){var e=this._lexer.token,t=this.parseDescription();this.expectKeyword("scalar");var n=this.parseName(),r=this.parseDirectives(!0);return{kind:nE.h.SCALAR_TYPE_DEFINITION,description:t,name:n,directives:r,loc:this.loc(e)}},t.parseObjectTypeDefinition=function(){var e=this._lexer.token,t=this.parseDescription();this.expectKeyword("type");var n=this.parseName(),r=this.parseImplementsInterfaces(),i=this.parseDirectives(!0),a=this.parseFieldsDefinition();return{kind:nE.h.OBJECT_TYPE_DEFINITION,description:t,name:n,interfaces:r,directives:i,fields:a,loc:this.loc(e)}},t.parseImplementsInterfaces=function(){var e;if(!this.expectOptionalKeyword("implements"))return[];if((null===(e=this._options)||void 0===e?void 0:e.allowLegacySDLImplementsInterfaces)===!0){var t=[];this.expectOptionalToken(nk.AMP);do t.push(this.parseNamedType());while(this.expectOptionalToken(nk.AMP)||this.peek(nk.NAME))return t}return this.delimitedMany(nk.AMP,this.parseNamedType)},t.parseFieldsDefinition=function(){var e;return(null===(e=this._options)||void 0===e?void 0:e.allowLegacySDLEmptyFields)===!0&&this.peek(nk.BRACE_L)&&this._lexer.lookahead().kind===nk.BRACE_R?(this._lexer.advance(),this._lexer.advance(),[]):this.optionalMany(nk.BRACE_L,this.parseFieldDefinition,nk.BRACE_R)},t.parseFieldDefinition=function(){var e=this._lexer.token,t=this.parseDescription(),n=this.parseName(),r=this.parseArgumentDefs();this.expectToken(nk.COLON);var i=this.parseTypeReference(),a=this.parseDirectives(!0);return{kind:nE.h.FIELD_DEFINITION,description:t,name:n,arguments:r,type:i,directives:a,loc:this.loc(e)}},t.parseArgumentDefs=function(){return this.optionalMany(nk.PAREN_L,this.parseInputValueDef,nk.PAREN_R)},t.parseInputValueDef=function(){var e,t=this._lexer.token,n=this.parseDescription(),r=this.parseName();this.expectToken(nk.COLON);var i=this.parseTypeReference();this.expectOptionalToken(nk.EQUALS)&&(e=this.parseValueLiteral(!0));var a=this.parseDirectives(!0);return{kind:nE.h.INPUT_VALUE_DEFINITION,description:n,name:r,type:i,defaultValue:e,directives:a,loc:this.loc(t)}},t.parseInterfaceTypeDefinition=function(){var e=this._lexer.token,t=this.parseDescription();this.expectKeyword("interface");var n=this.parseName(),r=this.parseImplementsInterfaces(),i=this.parseDirectives(!0),a=this.parseFieldsDefinition();return{kind:nE.h.INTERFACE_TYPE_DEFINITION,description:t,name:n,interfaces:r,directives:i,fields:a,loc:this.loc(e)}},t.parseUnionTypeDefinition=function(){var e=this._lexer.token,t=this.parseDescription();this.expectKeyword("union");var n=this.parseName(),r=this.parseDirectives(!0),i=this.parseUnionMemberTypes();return{kind:nE.h.UNION_TYPE_DEFINITION,description:t,name:n,directives:r,types:i,loc:this.loc(e)}},t.parseUnionMemberTypes=function(){return this.expectOptionalToken(nk.EQUALS)?this.delimitedMany(nk.PIPE,this.parseNamedType):[]},t.parseEnumTypeDefinition=function(){var e=this._lexer.token,t=this.parseDescription();this.expectKeyword("enum");var n=this.parseName(),r=this.parseDirectives(!0),i=this.parseEnumValuesDefinition();return{kind:nE.h.ENUM_TYPE_DEFINITION,description:t,name:n,directives:r,values:i,loc:this.loc(e)}},t.parseEnumValuesDefinition=function(){return this.optionalMany(nk.BRACE_L,this.parseEnumValueDefinition,nk.BRACE_R)},t.parseEnumValueDefinition=function(){var e=this._lexer.token,t=this.parseDescription(),n=this.parseName(),r=this.parseDirectives(!0);return{kind:nE.h.ENUM_VALUE_DEFINITION,description:t,name:n,directives:r,loc:this.loc(e)}},t.parseInputObjectTypeDefinition=function(){var e=this._lexer.token,t=this.parseDescription();this.expectKeyword("input");var n=this.parseName(),r=this.parseDirectives(!0),i=this.parseInputFieldsDefinition();return{kind:nE.h.INPUT_OBJECT_TYPE_DEFINITION,description:t,name:n,directives:r,fields:i,loc:this.loc(e)}},t.parseInputFieldsDefinition=function(){return this.optionalMany(nk.BRACE_L,this.parseInputValueDef,nk.BRACE_R)},t.parseTypeSystemExtension=function(){var e=this._lexer.lookahead();if(e.kind===nk.NAME)switch(e.value){case"schema":return this.parseSchemaExtension();case"scalar":return this.parseScalarTypeExtension();case"type":return this.parseObjectTypeExtension();case"interface":return this.parseInterfaceTypeExtension();case"union":return this.parseUnionTypeExtension();case"enum":return this.parseEnumTypeExtension();case"input":return this.parseInputObjectTypeExtension()}throw this.unexpected(e)},t.parseSchemaExtension=function(){var e=this._lexer.token;this.expectKeyword("extend"),this.expectKeyword("schema");var t=this.parseDirectives(!0),n=this.optionalMany(nk.BRACE_L,this.parseOperationTypeDefinition,nk.BRACE_R);if(0===t.length&&0===n.length)throw this.unexpected();return{kind:nE.h.SCHEMA_EXTENSION,directives:t,operationTypes:n,loc:this.loc(e)}},t.parseScalarTypeExtension=function(){var e=this._lexer.token;this.expectKeyword("extend"),this.expectKeyword("scalar");var t=this.parseName(),n=this.parseDirectives(!0);if(0===n.length)throw this.unexpected();return{kind:nE.h.SCALAR_TYPE_EXTENSION,name:t,directives:n,loc:this.loc(e)}},t.parseObjectTypeExtension=function(){var e=this._lexer.token;this.expectKeyword("extend"),this.expectKeyword("type");var t=this.parseName(),n=this.parseImplementsInterfaces(),r=this.parseDirectives(!0),i=this.parseFieldsDefinition();if(0===n.length&&0===r.length&&0===i.length)throw this.unexpected();return{kind:nE.h.OBJECT_TYPE_EXTENSION,name:t,interfaces:n,directives:r,fields:i,loc:this.loc(e)}},t.parseInterfaceTypeExtension=function(){var e=this._lexer.token;this.expectKeyword("extend"),this.expectKeyword("interface");var t=this.parseName(),n=this.parseImplementsInterfaces(),r=this.parseDirectives(!0),i=this.parseFieldsDefinition();if(0===n.length&&0===r.length&&0===i.length)throw this.unexpected();return{kind:nE.h.INTERFACE_TYPE_EXTENSION,name:t,interfaces:n,directives:r,fields:i,loc:this.loc(e)}},t.parseUnionTypeExtension=function(){var e=this._lexer.token;this.expectKeyword("extend"),this.expectKeyword("union");var t=this.parseName(),n=this.parseDirectives(!0),r=this.parseUnionMemberTypes();if(0===n.length&&0===r.length)throw this.unexpected();return{kind:nE.h.UNION_TYPE_EXTENSION,name:t,directives:n,types:r,loc:this.loc(e)}},t.parseEnumTypeExtension=function(){var e=this._lexer.token;this.expectKeyword("extend"),this.expectKeyword("enum");var t=this.parseName(),n=this.parseDirectives(!0),r=this.parseEnumValuesDefinition();if(0===n.length&&0===r.length)throw this.unexpected();return{kind:nE.h.ENUM_TYPE_EXTENSION,name:t,directives:n,values:r,loc:this.loc(e)}},t.parseInputObjectTypeExtension=function(){var e=this._lexer.token;this.expectKeyword("extend"),this.expectKeyword("input");var t=this.parseName(),n=this.parseDirectives(!0),r=this.parseInputFieldsDefinition();if(0===n.length&&0===r.length)throw this.unexpected();return{kind:nE.h.INPUT_OBJECT_TYPE_EXTENSION,name:t,directives:n,fields:r,loc:this.loc(e)}},t.parseDirectiveDefinition=function(){var e=this._lexer.token,t=this.parseDescription();this.expectKeyword("directive"),this.expectToken(nk.AT);var n=this.parseName(),r=this.parseArgumentDefs(),i=this.expectOptionalKeyword("repeatable");this.expectKeyword("on");var a=this.parseDirectiveLocations();return{kind:nE.h.DIRECTIVE_DEFINITION,description:t,name:n,arguments:r,repeatable:i,locations:a,loc:this.loc(e)}},t.parseDirectiveLocations=function(){return this.delimitedMany(nk.PIPE,this.parseDirectiveLocation)},t.parseDirectiveLocation=function(){var e=this._lexer.token,t=this.parseName();if(void 0!==nT[t.value])return t;throw this.unexpected(e)},t.loc=function(e){var t;if((null===(t=this._options)||void 0===t?void 0:t.noLocation)!==!0)return new nS.Ye(e,this._lexer.lastToken,this._lexer.source)},t.peek=function(e){return this._lexer.token.kind===e},t.expectToken=function(e){var t=this._lexer.token;if(t.kind===e)return this._lexer.advance(),t;throw n_(this._lexer.source,t.start,"Expected ".concat(nG(e),", found ").concat(nz(t),"."))},t.expectOptionalToken=function(e){var t=this._lexer.token;if(t.kind===e)return this._lexer.advance(),t},t.expectKeyword=function(e){var t=this._lexer.token;if(t.kind===nk.NAME&&t.value===e)this._lexer.advance();else throw n_(this._lexer.source,t.start,'Expected "'.concat(e,'", found ').concat(nz(t),"."))},t.expectOptionalKeyword=function(e){var t=this._lexer.token;return t.kind===nk.NAME&&t.value===e&&(this._lexer.advance(),!0)},t.unexpected=function(e){var t=null!=e?e:this._lexer.token;return n_(this._lexer.source,t.start,"Unexpected ".concat(nz(t),"."))},t.any=function(e,t,n){this.expectToken(e);for(var r=[];!this.expectOptionalToken(n);)r.push(t.call(this));return r},t.optionalMany=function(e,t,n){if(this.expectOptionalToken(e)){var r=[];do r.push(t.call(this));while(!this.expectOptionalToken(n))return r}return[]},t.many=function(e,t,n){this.expectToken(e);var r=[];do r.push(t.call(this));while(!this.expectOptionalToken(n))return r},t.delimitedMany=function(e,t){this.expectOptionalToken(e);var n=[];do n.push(t.call(this));while(this.expectOptionalToken(e))return n},e}();function nz(e){var t=e.value;return nG(e.kind)+(null!=t?' "'.concat(t,'"'):"")}function nG(e){return nA(e)?'"'.concat(e,'"'):e}var nW=new Map,nK=new Map,nV=!0,nq=!1;function nZ(e){return e.replace(/[\s,]+/g," ").trim()}function nX(e){return nZ(e.source.body.substring(e.start,e.end))}function nJ(e){var t=new Set,n=[];return e.definitions.forEach(function(e){if("FragmentDefinition"===e.kind){var r=e.name.value,i=nX(e.loc),a=nK.get(r);a&&!a.has(i)?nV&&console.warn("Warning: fragment with name "+r+" already exists.\ngraphql-tag enforces all fragment names across your application to be unique; read more about\nthis in the docs: http://dev.apollodata.com/core/fragments.html#unique-names"):a||nK.set(r,a=new Set),a.add(i),t.has(i)||(t.add(i),n.push(e))}else n.push(e)}),(0,t0.pi)((0,t0.pi)({},e),{definitions:n})}function nQ(e){var t=new Set(e.definitions);t.forEach(function(e){e.loc&&delete e.loc,Object.keys(e).forEach(function(n){var r=e[n];r&&"object"==typeof r&&t.add(r)})});var n=e.loc;return n&&(delete n.startToken,delete n.endToken),e}function n1(e){var t=nZ(e);if(!nW.has(t)){var n=nH(e,{experimentalFragmentVariables:nq,allowLegacyFragmentVariables:nq});if(!n||"Document"!==n.kind)throw Error("Not a valid GraphQL document.");nW.set(t,nQ(nJ(n)))}return nW.get(t)}function n0(e){for(var t=[],n=1;n, or pass an ApolloClient instance in via options.'):(0,n9.kG)(!!n,32),n}var rp=n(10542),rb=n(53712),rm=n(21436),rg=Object.prototype.hasOwnProperty;function rv(e,t){return void 0===t&&(t=Object.create(null)),ry(rh(t.client),e).useQuery(t)}function ry(e,t){var n=(0,l.useRef)();n.current&&e===n.current.client&&t===n.current.query||(n.current=new rw(e,t,n.current));var r=n.current,i=(0,l.useState)(0),a=(i[0],i[1]);return r.forceUpdate=function(){a(function(e){return e+1})},r}var rw=function(){function e(e,t,n){this.client=e,this.query=t,this.ssrDisabledResult=(0,rp.J)({loading:!0,data:void 0,error:void 0,networkStatus:ru.I.loading}),this.skipStandbyResult=(0,rp.J)({loading:!1,data:void 0,error:void 0,networkStatus:ru.I.ready}),this.toQueryResultCache=new(n7.mr?WeakMap:Map),rd(t,r.Query);var i=n&&n.result,a=i&&i.data;a&&(this.previousData=a)}return e.prototype.forceUpdate=function(){__DEV__&&n9.kG.warn("Calling default no-op implementation of InternalState#forceUpdate")},e.prototype.executeQuery=function(e){var t,n=this;e.query&&Object.assign(this,{query:e.query}),this.watchQueryOptions=this.createWatchQueryOptions(this.queryHookOptions=e);var r=this.observable.reobserveAsConcast(this.getObsQueryOptions());return this.previousData=(null===(t=this.result)||void 0===t?void 0:t.data)||this.previousData,this.result=void 0,this.forceUpdate(),new Promise(function(e){var t;r.subscribe({next:function(e){t=e},error:function(){e(n.toQueryResult(n.observable.getCurrentResult()))},complete:function(){e(n.toQueryResult(t))}})})},e.prototype.useQuery=function(e){var t=this;this.renderPromises=(0,l.useContext)((0,ro.K)()).renderPromises,this.useOptions(e);var n=this.useObservableQuery(),r=rt((0,l.useCallback)(function(){if(t.renderPromises)return function(){};var e=function(){var e=t.result,r=n.getCurrentResult();!(e&&e.loading===r.loading&&e.networkStatus===r.networkStatus&&(0,ri.D)(e.data,r.data))&&t.setResult(r)},r=function(a){var o=n.last;i.unsubscribe();try{n.resetLastResults(),i=n.subscribe(e,r)}finally{n.last=o}if(!rg.call(a,"graphQLErrors"))throw a;var s=t.result;(!s||s&&s.loading||!(0,ri.D)(a,s.error))&&t.setResult({data:s&&s.data,error:a,loading:!1,networkStatus:ru.I.error})},i=n.subscribe(e,r);return function(){return setTimeout(function(){return i.unsubscribe()})}},[n,this.renderPromises,this.client.disableNetworkFetches,]),function(){return t.getCurrentResult()},function(){return t.getCurrentResult()});return this.unsafeHandlePartialRefetch(r),this.toQueryResult(r)},e.prototype.useOptions=function(t){var n,r=this.createWatchQueryOptions(this.queryHookOptions=t),i=this.watchQueryOptions;!(0,ri.D)(r,i)&&(this.watchQueryOptions=r,i&&this.observable&&(this.observable.reobserve(this.getObsQueryOptions()),this.previousData=(null===(n=this.result)||void 0===n?void 0:n.data)||this.previousData,this.result=void 0)),this.onCompleted=t.onCompleted||e.prototype.onCompleted,this.onError=t.onError||e.prototype.onError,(this.renderPromises||this.client.disableNetworkFetches)&&!1===this.queryHookOptions.ssr&&!this.queryHookOptions.skip?this.result=this.ssrDisabledResult:this.queryHookOptions.skip||"standby"===this.watchQueryOptions.fetchPolicy?this.result=this.skipStandbyResult:(this.result===this.ssrDisabledResult||this.result===this.skipStandbyResult)&&(this.result=void 0)},e.prototype.getObsQueryOptions=function(){var e=[],t=this.client.defaultOptions.watchQuery;return t&&e.push(t),this.queryHookOptions.defaultOptions&&e.push(this.queryHookOptions.defaultOptions),e.push((0,rb.o)(this.observable&&this.observable.options,this.watchQueryOptions)),e.reduce(ra.J)},e.prototype.createWatchQueryOptions=function(e){void 0===e&&(e={});var t,n=e.skip,r=Object.assign((e.ssr,e.onCompleted,e.onError,e.defaultOptions,(0,t0._T)(e,["skip","ssr","onCompleted","onError","defaultOptions"])),{query:this.query});if(this.renderPromises&&("network-only"===r.fetchPolicy||"cache-and-network"===r.fetchPolicy)&&(r.fetchPolicy="cache-first"),r.variables||(r.variables={}),n){var i=r.fetchPolicy,a=void 0===i?this.getDefaultFetchPolicy():i,o=r.initialFetchPolicy;Object.assign(r,{initialFetchPolicy:void 0===o?a:o,fetchPolicy:"standby"})}else r.fetchPolicy||(r.fetchPolicy=(null===(t=this.observable)||void 0===t?void 0:t.options.initialFetchPolicy)||this.getDefaultFetchPolicy());return r},e.prototype.getDefaultFetchPolicy=function(){var e,t;return(null===(e=this.queryHookOptions.defaultOptions)||void 0===e?void 0:e.fetchPolicy)||(null===(t=this.client.defaultOptions.watchQuery)||void 0===t?void 0:t.fetchPolicy)||"cache-first"},e.prototype.onCompleted=function(e){},e.prototype.onError=function(e){},e.prototype.useObservableQuery=function(){var e=this.observable=this.renderPromises&&this.renderPromises.getSSRObservable(this.watchQueryOptions)||this.observable||this.client.watchQuery(this.getObsQueryOptions());this.obsQueryFields=(0,l.useMemo)(function(){return{refetch:e.refetch.bind(e),reobserve:e.reobserve.bind(e),fetchMore:e.fetchMore.bind(e),updateQuery:e.updateQuery.bind(e),startPolling:e.startPolling.bind(e),stopPolling:e.stopPolling.bind(e),subscribeToMore:e.subscribeToMore.bind(e)}},[e]);var t=!(!1===this.queryHookOptions.ssr||this.queryHookOptions.skip);return this.renderPromises&&t&&(this.renderPromises.registerSSRObservable(e),e.getCurrentResult().loading&&this.renderPromises.addObservableQueryPromise(e)),e},e.prototype.setResult=function(e){var t=this.result;t&&t.data&&(this.previousData=t.data),this.result=e,this.forceUpdate(),this.handleErrorOrCompleted(e)},e.prototype.handleErrorOrCompleted=function(e){var t=this;if(!e.loading){var n=this.toApolloError(e);Promise.resolve().then(function(){n?t.onError(n):e.data&&t.onCompleted(e.data)}).catch(function(e){__DEV__&&n9.kG.warn(e)})}},e.prototype.toApolloError=function(e){return(0,rm.O)(e.errors)?new rs.cA({graphQLErrors:e.errors}):e.error},e.prototype.getCurrentResult=function(){return this.result||this.handleErrorOrCompleted(this.result=this.observable.getCurrentResult()),this.result},e.prototype.toQueryResult=function(e){var t=this.toQueryResultCache.get(e);if(t)return t;var n=e.data,r=(e.partial,(0,t0._T)(e,["data","partial"]));return this.toQueryResultCache.set(e,t=(0,t0.pi)((0,t0.pi)((0,t0.pi)({data:n},r),this.obsQueryFields),{client:this.client,observable:this.observable,variables:this.observable.variables,called:!this.queryHookOptions.skip,previousData:this.previousData})),!t.error&&(0,rm.O)(e.errors)&&(t.error=new rs.cA({graphQLErrors:e.errors})),t},e.prototype.unsafeHandlePartialRefetch=function(e){e.partial&&this.queryHookOptions.partialRefetch&&!e.loading&&(!e.data||0===Object.keys(e.data).length)&&"cache-only"!==this.observable.options.fetchPolicy&&(Object.assign(e,{loading:!0,networkStatus:ru.I.refetch}),this.observable.refetch())},e}();function r_(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);ne.length)&&(t=e.length);for(var n=0,r=Array(t);ne.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&void 0!==arguments[0]?arguments[0]:{};return rv(iH,e)},iz=function(){var e=ij(),t=parseInt(e.get("page")||"1",10),n=parseInt(e.get("per")||"50",10),r=i$({variables:{offset:(t-1)*n,limit:n},fetchPolicy:"network-only"}),i=r.data,a=r.loading,o=r.error;return a?l.createElement(iR,null):o?l.createElement(iD,{error:o}):i?l.createElement(iI,{chains:i.chains.results,page:t,pageSize:n,total:i.chains.metadata.total}):null},iG=n(67932),iW=n(8126),iK="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e};function iV(e){if(iq())return Intl.DateTimeFormat.supportedLocalesOf(e)[0]}function iq(){return("undefined"==typeof Intl?"undefined":iK(Intl))==="object"&&"function"==typeof Intl.DateTimeFormat}var iZ="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},iX=function(){function e(e,t){for(var n=0;n=i.length)break;s=i[o++]}else{if((o=i.next()).done)break;s=o.value}var s,u=s;if((void 0===e?"undefined":iZ(e))!=="object")return;e=e[u]}return e}},{key:"put",value:function(){for(var e=arguments.length,t=Array(e),n=0;n=o.length)break;c=o[u++]}else{if((u=o.next()).done)break;c=u.value}var c,l=c;"object"!==iZ(a[l])&&(a[l]={}),a=a[l]}return a[i]=r}}]),e}();let i1=iQ;var i0=new i1;function i2(e,t){if(!iq())return function(e){return e.toString()};var n=i4(e),r=JSON.stringify(t),i=i0.get(String(n),r)||i0.put(String(n),r,new Intl.DateTimeFormat(n,t));return function(e){return i.format(e)}}var i3={};function i4(e){var t=e.toString();return i3[t]?i3[t]:i3[t]=iV(e)}var i6="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e};function i5(e){return i8(e)?e:new Date(e)}function i8(e){return e instanceof Date||i9(e)}function i9(e){return(void 0===e?"undefined":i6(e))==="object"&&"function"==typeof e.getTime}var i7=n(54087),ae=n.n(i7);function at(e,t){if(0===e.length)return 0;for(var n=0,r=e.length-1,i=void 0;n<=r;){var a=t(e[i=Math.floor((r+n)/2)]);if(0===a)return i;if(a<0){if((n=i+1)>r)return n}else if((r=i-1)=t.nextUpdateTime)aa(t,this.instances);else break}},scheduleNextTick:function(){var e=this;this.scheduledTick=ae()(function(){e.tick(),e.scheduleNextTick()})},start:function(){this.scheduleNextTick()},stop:function(){ae().cancel(this.scheduledTick)}};function ai(e){var t=an(e.getNextValue(),2),n=t[0],r=t[1];e.setValue(n),e.nextUpdateTime=r}function aa(e,t){ai(e),as(t,e),ao(t,e)}function ao(e,t){var n=au(e,t);e.splice(n,0,t)}function as(e,t){var n=e.indexOf(t);e.splice(n,1)}function au(e,t){var n=t.nextUpdateTime;return at(e,function(e){return e.nextUpdateTime===n?0:e.nextUpdateTime>n?1:-1})}var ac=(0,ec.oneOfType)([(0,ec.shape)({minTime:ec.number,formatAs:ec.string.isRequired}),(0,ec.shape)({test:ec.func,formatAs:ec.string.isRequired}),(0,ec.shape)({minTime:ec.number,format:ec.func.isRequired}),(0,ec.shape)({test:ec.func,format:ec.func.isRequired})]),al=(0,ec.oneOfType)([ec.string,(0,ec.shape)({steps:(0,ec.arrayOf)(ac).isRequired,labels:(0,ec.oneOfType)([ec.string,(0,ec.arrayOf)(ec.string)]).isRequired,round:ec.string})]),af=Object.assign||function(e){for(var t=1;t=0)&&Object.prototype.hasOwnProperty.call(e,r)&&(n[r]=e[r]);return n}function ap(e){var t=e.date,n=e.future,r=e.timeStyle,i=e.round,a=e.minTimeLeft,o=e.tooltip,s=e.component,u=e.container,c=e.wrapperComponent,f=e.wrapperProps,d=e.locale,h=e.locales,p=e.formatVerboseDate,b=e.verboseDateFormat,m=e.updateInterval,g=e.tick,v=ah(e,["date","future","timeStyle","round","minTimeLeft","tooltip","component","container","wrapperComponent","wrapperProps","locale","locales","formatVerboseDate","verboseDateFormat","updateInterval","tick"]),y=(0,l.useMemo)(function(){return d&&(h=[d]),h.concat(iW.Z.getDefaultLocale())},[d,h]),w=(0,l.useMemo)(function(){return new iW.Z(y)},[y]);t=(0,l.useMemo)(function(){return i5(t)},[t]);var _=(0,l.useCallback)(function(){var e=Date.now(),o=void 0;if(n&&e>=t.getTime()&&(e=t.getTime(),o=!0),void 0!==a){var s=t.getTime()-1e3*a;e>s&&(e=s,o=!0)}var u=w.format(t,r,{getTimeToNextUpdate:!0,now:e,future:n,round:i}),c=ad(u,2),l=c[0],f=c[1];return f=o?ag:m||f||6e4,[l,e+f]},[t,n,r,m,i,a,w]),E=(0,l.useRef)();E.current=_;var S=(0,l.useMemo)(_,[]),k=ad(S,2),x=k[0],T=k[1],M=(0,l.useState)(x),O=ad(M,2),A=O[0],L=O[1],C=ad((0,l.useState)(),2),I=C[0],D=C[1],N=(0,l.useRef)();(0,l.useEffect)(function(){if(g)return N.current=ar.add({getNextValue:function(){return E.current()},setValue:L,nextUpdateTime:T}),function(){return N.current.stop()}},[g]),(0,l.useEffect)(function(){if(N.current)N.current.forceUpdate();else{var e=_(),t=ad(e,1)[0];L(t)}},[_]),(0,l.useEffect)(function(){D(!0)},[]);var P=(0,l.useMemo)(function(){if("undefined"!=typeof window)return i2(y,b)},[y,b]),R=(0,l.useMemo)(function(){if("undefined"!=typeof window)return p?p(t):P(t)},[t,p,P]),j=l.createElement(s,af({date:t,verboseDate:I?R:void 0,tooltip:o},v),A),F=c||u;return F?l.createElement(F,af({},f,{verboseDate:I?R:void 0}),j):j}ap.propTypes={date:el().oneOfType([el().instanceOf(Date),el().number]).isRequired,locale:el().string,locales:el().arrayOf(el().string),future:el().bool,timeStyle:al,round:el().string,minTimeLeft:el().number,component:el().elementType.isRequired,tooltip:el().bool.isRequired,formatVerboseDate:el().func,verboseDateFormat:el().object,updateInterval:el().oneOfType([el().number,el().arrayOf(el().shape({threshold:el().number,interval:el().number.isRequired}))]),tick:el().bool,wrapperComponent:el().func,wrapperProps:el().object},ap.defaultProps={locales:[],component:av,tooltip:!0,verboseDateFormat:{weekday:"long",day:"numeric",month:"long",year:"numeric",hour:"numeric",minute:"2-digit",second:"2-digit"},tick:!0},ap=l.memo(ap);let ab=ap;var am,ag=31536e9;function av(e){var t=e.date,n=e.verboseDate,r=e.tooltip,i=e.children,a=ah(e,["date","verboseDate","tooltip","children"]),o=(0,l.useMemo)(function(){return t.toISOString()},[t]);return l.createElement("time",af({},a,{dateTime:o,title:r?n:void 0}),i)}av.propTypes={date:el().instanceOf(Date).isRequired,verboseDate:el().string,tooltip:el().bool.isRequired,children:el().string.isRequired};var ay=n(30381),aw=n.n(ay),a_=n(31657);function aE(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function aS(e){for(var t=1;te.length)&&(t=e.length);for(var n=0,r=Array(t);ne.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]0?new rs.cA({graphQLErrors:i}):void 0;if(u===s.current.mutationId&&!c.ignoreResults){var f={called:!0,loading:!1,data:r,error:l,client:a};s.current.isMounted&&!(0,ri.D)(s.current.result,f)&&o(s.current.result=f)}var d=e.onCompleted||(null===(n=s.current.options)||void 0===n?void 0:n.onCompleted);return null==d||d(t.data,c),t}).catch(function(t){if(u===s.current.mutationId&&s.current.isMounted){var n,r={loading:!1,error:t,data:void 0,called:!0,client:a};(0,ri.D)(s.current.result,r)||o(s.current.result=r)}var i=e.onError||(null===(n=s.current.options)||void 0===n?void 0:n.onError);if(i)return i(t,c),{data:void 0,errors:t};throw t})},[]),c=(0,l.useCallback)(function(){s.current.isMounted&&o({called:!1,loading:!1,client:n})},[]);return(0,l.useEffect)(function(){return s.current.isMounted=!0,function(){s.current.isMounted=!1}},[]),[u,(0,t0.pi)({reset:c},a)]}var os=n(59067),ou=n(28428),oc=n(11186),ol=n(78513);function of(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}var od=function(e){return(0,b.createStyles)({paper:{display:"flex",margin:"".concat(2.5*e.spacing.unit,"px 0"),padding:"".concat(3*e.spacing.unit,"px ").concat(3.5*e.spacing.unit,"px")},content:{flex:1,width:"100%"},actions:of({marginTop:-(1.5*e.spacing.unit),marginLeft:-(4*e.spacing.unit)},e.breakpoints.up("sm"),{marginLeft:0,marginRight:-(1.5*e.spacing.unit)}),itemBlock:{border:"1px solid rgba(224, 224, 224, 1)",borderRadius:e.shape.borderRadius,padding:2*e.spacing.unit,marginTop:e.spacing.unit},itemBlockText:{overflowWrap:"anywhere"}})},oh=(0,b.withStyles)(od)(function(e){var t=e.actions,n=e.children,r=e.classes;return l.createElement(ii.default,{className:r.paper},l.createElement("div",{className:r.content},n),t&&l.createElement("div",{className:r.actions},t))}),op=function(e){var t=e.title;return l.createElement(x.default,{variant:"subtitle2",gutterBottom:!0},t)},ob=function(e){var t=e.children,n=e.value;return l.createElement(x.default,{variant:"body1",noWrap:!0},t||n)},om=(0,b.withStyles)(od)(function(e){var t=e.children,n=e.classes,r=e.value;return l.createElement("div",{className:n.itemBlock},l.createElement(x.default,{variant:"body1",className:n.itemBlockText},t||r))});function og(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);ne.length)&&(t=e.length);for(var n=0,r=Array(t);ne.length)&&(t=e.length);for(var n=0,r=Array(t);ne.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]-1}let sq=sV;function sZ(e,t){var n=this.__data__,r=sH(n,e);return r<0?(++this.size,n.push([e,t])):n[r][1]=t,this}let sX=sZ;function sJ(e){var t=-1,n=null==e?0:e.length;for(this.clear();++t-1&&e%1==0&&e-1&&e%1==0&&e<=cC}let cD=cI;var cN="[object Arguments]",cP="[object Array]",cR="[object Boolean]",cj="[object Date]",cF="[object Error]",cY="[object Function]",cB="[object Map]",cU="[object Number]",cH="[object Object]",c$="[object RegExp]",cz="[object Set]",cG="[object String]",cW="[object WeakMap]",cK="[object ArrayBuffer]",cV="[object DataView]",cq="[object Float64Array]",cZ="[object Int8Array]",cX="[object Int16Array]",cJ="[object Int32Array]",cQ="[object Uint8Array]",c1="[object Uint8ClampedArray]",c0="[object Uint16Array]",c2="[object Uint32Array]",c3={};function c4(e){return eD(e)&&cD(e.length)&&!!c3[eC(e)]}c3["[object Float32Array]"]=c3[cq]=c3[cZ]=c3[cX]=c3[cJ]=c3[cQ]=c3[c1]=c3[c0]=c3[c2]=!0,c3[cN]=c3[cP]=c3[cK]=c3[cR]=c3[cV]=c3[cj]=c3[cF]=c3[cY]=c3[cB]=c3[cU]=c3[cH]=c3[c$]=c3[cz]=c3[cG]=c3[cW]=!1;let c6=c4;function c5(e){return function(t){return e(t)}}let c8=c5;var c9=n(79730),c7=c9.Z&&c9.Z.isTypedArray,le=c7?c8(c7):c6;let lt=le;var ln=Object.prototype.hasOwnProperty;function lr(e,t){var n=cx(e),r=!n&&cS(e),i=!n&&!r&&(0,cT.Z)(e),a=!n&&!r&&!i&<(e),o=n||r||i||a,s=o?cb(e.length,String):[],u=s.length;for(var c in e)(t||ln.call(e,c))&&!(o&&("length"==c||i&&("offset"==c||"parent"==c)||a&&("buffer"==c||"byteLength"==c||"byteOffset"==c)||cL(c,u)))&&s.push(c);return s}let li=lr;var la=Object.prototype;function lo(e){var t=e&&e.constructor;return e===("function"==typeof t&&t.prototype||la)}let ls=lo;var lu=sT(Object.keys,Object);let lc=lu;var ll=Object.prototype.hasOwnProperty;function lf(e){if(!ls(e))return lc(e);var t=[];for(var n in Object(e))ll.call(e,n)&&"constructor"!=n&&t.push(n);return t}let ld=lf;function lh(e){return null!=e&&cD(e.length)&&!ur(e)}let lp=lh;function lb(e){return lp(e)?li(e):ld(e)}let lm=lb;function lg(e,t){return e&&ch(t,lm(t),e)}let lv=lg;function ly(e){var t=[];if(null!=e)for(var n in Object(e))t.push(n);return t}let lw=ly;var l_=Object.prototype.hasOwnProperty;function lE(e){if(!ed(e))return lw(e);var t=ls(e),n=[];for(var r in e)"constructor"==r&&(t||!l_.call(e,r))||n.push(r);return n}let lS=lE;function lk(e){return lp(e)?li(e,!0):lS(e)}let lx=lk;function lT(e,t){return e&&ch(t,lx(t),e)}let lM=lT;var lO=n(42896);function lA(e,t){var n=-1,r=e.length;for(t||(t=Array(r));++n=0||(i[n]=e[n]);return i}function hu(e){if(void 0===e)throw ReferenceError("this hasn't been initialised - super() hasn't been called");return e}var hc=function(e){return Array.isArray(e)&&0===e.length},hl=function(e){return"function"==typeof e},hf=function(e){return null!==e&&"object"==typeof e},hd=function(e){return String(Math.floor(Number(e)))===e},hh=function(e){return"[object String]"===Object.prototype.toString.call(e)},hp=function(e){return 0===l.Children.count(e)},hb=function(e){return hf(e)&&hl(e.then)};function hm(e,t,n,r){void 0===r&&(r=0);for(var i=d8(t);e&&r=0?[]:{}}}return(0===a?e:i)[o[a]]===n?e:(void 0===n?delete i[o[a]]:i[o[a]]=n,0===a&&void 0===n&&delete r[o[a]],r)}function hv(e,t,n,r){void 0===n&&(n=new WeakMap),void 0===r&&(r={});for(var i=0,a=Object.keys(e);i0?t.map(function(t){return x(t,hm(e,t))}):[Promise.resolve("DO_NOT_DELETE_YOU_WILL_BE_FIRED")]).then(function(e){return e.reduce(function(e,n,r){return"DO_NOT_DELETE_YOU_WILL_BE_FIRED"===n||n&&(e=hg(e,t[r],n)),e},{})})},[x]),M=(0,l.useCallback)(function(e){return Promise.all([T(e),h.validationSchema?k(e):{},h.validate?S(e):{}]).then(function(e){var t=e[0],n=e[1],r=e[2];return sk.all([t,n,r],{arrayMerge:hL})})},[h.validate,h.validationSchema,T,S,k]),O=hN(function(e){return void 0===e&&(e=_.values),E({type:"SET_ISVALIDATING",payload:!0}),M(e).then(function(e){return v.current&&(E({type:"SET_ISVALIDATING",payload:!1}),sd()(_.errors,e)||E({type:"SET_ERRORS",payload:e})),e})});(0,l.useEffect)(function(){o&&!0===v.current&&sd()(p.current,h.initialValues)&&O(p.current)},[o,O]);var A=(0,l.useCallback)(function(e){var t=e&&e.values?e.values:p.current,n=e&&e.errors?e.errors:b.current?b.current:h.initialErrors||{},r=e&&e.touched?e.touched:m.current?m.current:h.initialTouched||{},i=e&&e.status?e.status:g.current?g.current:h.initialStatus;p.current=t,b.current=n,m.current=r,g.current=i;var a=function(){E({type:"RESET_FORM",payload:{isSubmitting:!!e&&!!e.isSubmitting,errors:n,touched:r,status:i,values:t,isValidating:!!e&&!!e.isValidating,submitCount:e&&e.submitCount&&"number"==typeof e.submitCount?e.submitCount:0}})};if(h.onReset){var o=h.onReset(_.values,V);hb(o)?o.then(a):a()}else a()},[h.initialErrors,h.initialStatus,h.initialTouched]);(0,l.useEffect)(function(){!0===v.current&&!sd()(p.current,h.initialValues)&&(c&&(p.current=h.initialValues,A()),o&&O(p.current))},[c,h.initialValues,A,o,O]),(0,l.useEffect)(function(){c&&!0===v.current&&!sd()(b.current,h.initialErrors)&&(b.current=h.initialErrors||hS,E({type:"SET_ERRORS",payload:h.initialErrors||hS}))},[c,h.initialErrors]),(0,l.useEffect)(function(){c&&!0===v.current&&!sd()(m.current,h.initialTouched)&&(m.current=h.initialTouched||hk,E({type:"SET_TOUCHED",payload:h.initialTouched||hk}))},[c,h.initialTouched]),(0,l.useEffect)(function(){c&&!0===v.current&&!sd()(g.current,h.initialStatus)&&(g.current=h.initialStatus,E({type:"SET_STATUS",payload:h.initialStatus}))},[c,h.initialStatus,h.initialTouched]);var L=hN(function(e){if(y.current[e]&&hl(y.current[e].validate)){var t=hm(_.values,e),n=y.current[e].validate(t);return hb(n)?(E({type:"SET_ISVALIDATING",payload:!0}),n.then(function(e){return e}).then(function(t){E({type:"SET_FIELD_ERROR",payload:{field:e,value:t}}),E({type:"SET_ISVALIDATING",payload:!1})})):(E({type:"SET_FIELD_ERROR",payload:{field:e,value:n}}),Promise.resolve(n))}return h.validationSchema?(E({type:"SET_ISVALIDATING",payload:!0}),k(_.values,e).then(function(e){return e}).then(function(t){E({type:"SET_FIELD_ERROR",payload:{field:e,value:t[e]}}),E({type:"SET_ISVALIDATING",payload:!1})})):Promise.resolve()}),C=(0,l.useCallback)(function(e,t){var n=t.validate;y.current[e]={validate:n}},[]),I=(0,l.useCallback)(function(e){delete y.current[e]},[]),D=hN(function(e,t){return E({type:"SET_TOUCHED",payload:e}),(void 0===t?i:t)?O(_.values):Promise.resolve()}),N=(0,l.useCallback)(function(e){E({type:"SET_ERRORS",payload:e})},[]),P=hN(function(e,t){var r=hl(e)?e(_.values):e;return E({type:"SET_VALUES",payload:r}),(void 0===t?n:t)?O(r):Promise.resolve()}),R=(0,l.useCallback)(function(e,t){E({type:"SET_FIELD_ERROR",payload:{field:e,value:t}})},[]),j=hN(function(e,t,r){return E({type:"SET_FIELD_VALUE",payload:{field:e,value:t}}),(void 0===r?n:r)?O(hg(_.values,e,t)):Promise.resolve()}),F=(0,l.useCallback)(function(e,t){var n,r=t,i=e;if(!hh(e)){e.persist&&e.persist();var a=e.target?e.target:e.currentTarget,o=a.type,s=a.name,u=a.id,c=a.value,l=a.checked,f=(a.outerHTML,a.options),d=a.multiple;r=t||s||u,i=/number|range/.test(o)?(n=parseFloat(c),isNaN(n)?"":n):/checkbox/.test(o)?hI(hm(_.values,r),l,c):d?hC(f):c}r&&j(r,i)},[j,_.values]),Y=hN(function(e){if(hh(e))return function(t){return F(t,e)};F(e)}),B=hN(function(e,t,n){return void 0===t&&(t=!0),E({type:"SET_FIELD_TOUCHED",payload:{field:e,value:t}}),(void 0===n?i:n)?O(_.values):Promise.resolve()}),U=(0,l.useCallback)(function(e,t){e.persist&&e.persist();var n,r=e.target,i=r.name,a=r.id;r.outerHTML,B(t||i||a,!0)},[B]),H=hN(function(e){if(hh(e))return function(t){return U(t,e)};U(e)}),$=(0,l.useCallback)(function(e){hl(e)?E({type:"SET_FORMIK_STATE",payload:e}):E({type:"SET_FORMIK_STATE",payload:function(){return e}})},[]),z=(0,l.useCallback)(function(e){E({type:"SET_STATUS",payload:e})},[]),G=(0,l.useCallback)(function(e){E({type:"SET_ISSUBMITTING",payload:e})},[]),W=hN(function(){return E({type:"SUBMIT_ATTEMPT"}),O().then(function(e){var t,n=e instanceof Error;if(!n&&0===Object.keys(e).length){try{if(void 0===(t=q()))return}catch(r){throw r}return Promise.resolve(t).then(function(e){return v.current&&E({type:"SUBMIT_SUCCESS"}),e}).catch(function(e){if(v.current)throw E({type:"SUBMIT_FAILURE"}),e})}if(v.current&&(E({type:"SUBMIT_FAILURE"}),n))throw e})}),K=hN(function(e){e&&e.preventDefault&&hl(e.preventDefault)&&e.preventDefault(),e&&e.stopPropagation&&hl(e.stopPropagation)&&e.stopPropagation(),W().catch(function(e){console.warn("Warning: An unhandled error was caught from submitForm()",e)})}),V={resetForm:A,validateForm:O,validateField:L,setErrors:N,setFieldError:R,setFieldTouched:B,setFieldValue:j,setStatus:z,setSubmitting:G,setTouched:D,setValues:P,setFormikState:$,submitForm:W},q=hN(function(){return f(_.values,V)}),Z=hN(function(e){e&&e.preventDefault&&hl(e.preventDefault)&&e.preventDefault(),e&&e.stopPropagation&&hl(e.stopPropagation)&&e.stopPropagation(),A()}),X=(0,l.useCallback)(function(e){return{value:hm(_.values,e),error:hm(_.errors,e),touched:!!hm(_.touched,e),initialValue:hm(p.current,e),initialTouched:!!hm(m.current,e),initialError:hm(b.current,e)}},[_.errors,_.touched,_.values]),J=(0,l.useCallback)(function(e){return{setValue:function(t,n){return j(e,t,n)},setTouched:function(t,n){return B(e,t,n)},setError:function(t){return R(e,t)}}},[j,B,R]),Q=(0,l.useCallback)(function(e){var t=hf(e),n=t?e.name:e,r=hm(_.values,n),i={name:n,value:r,onChange:Y,onBlur:H};if(t){var a=e.type,o=e.value,s=e.as,u=e.multiple;"checkbox"===a?void 0===o?i.checked=!!r:(i.checked=!!(Array.isArray(r)&&~r.indexOf(o)),i.value=o):"radio"===a?(i.checked=r===o,i.value=o):"select"===s&&u&&(i.value=i.value||[],i.multiple=!0)}return i},[H,Y,_.values]),ee=(0,l.useMemo)(function(){return!sd()(p.current,_.values)},[p.current,_.values]),et=(0,l.useMemo)(function(){return void 0!==s?ee?_.errors&&0===Object.keys(_.errors).length:!1!==s&&hl(s)?s(h):s:_.errors&&0===Object.keys(_.errors).length},[s,ee,_.errors,h]);return ha({},_,{initialValues:p.current,initialErrors:b.current,initialTouched:m.current,initialStatus:g.current,handleBlur:H,handleChange:Y,handleReset:Z,handleSubmit:K,resetForm:A,setErrors:N,setFormikState:$,setFieldTouched:B,setFieldValue:j,setFieldError:R,setStatus:z,setSubmitting:G,setTouched:D,setValues:P,submitForm:W,validateForm:O,validateField:L,isValid:et,dirty:ee,unregisterField:I,registerField:C,getFieldProps:Q,getFieldMeta:X,getFieldHelpers:J,validateOnBlur:i,validateOnChange:n,validateOnMount:o})}function hT(e){var t=hx(e),n=e.component,r=e.children,i=e.render,a=e.innerRef;return(0,l.useImperativeHandle)(a,function(){return t}),(0,l.createElement)(hw,{value:t},n?(0,l.createElement)(n,t):i?i(t):r?hl(r)?r(t):hp(r)?null:l.Children.only(r):null)}function hM(e){var t={};if(e.inner){if(0===e.inner.length)return hg(t,e.path,e.message);for(var n=e.inner,r=Array.isArray(n),i=0,n=r?n:n[Symbol.iterator]();;){if(r){if(i>=n.length)break;a=n[i++]}else{if((i=n.next()).done)break;a=i.value}var a,o=a;hm(t,o.path)||(t=hg(t,o.path,o.message))}}return t}function hO(e,t,n,r){void 0===n&&(n=!1),void 0===r&&(r={});var i=hA(e);return t[n?"validateSync":"validate"](i,{abortEarly:!1,context:r})}function hA(e){var t=Array.isArray(e)?[]:{};for(var n in e)if(Object.prototype.hasOwnProperty.call(e,n)){var r=String(n);!0===Array.isArray(e[r])?t[r]=e[r].map(function(e){return!0===Array.isArray(e)||sR(e)?hA(e):""!==e?e:void 0}):sR(e[r])?t[r]=hA(e[r]):t[r]=""!==e[r]?e[r]:void 0}return t}function hL(e,t,n){var r=e.slice();return t.forEach(function(t,i){if(void 0===r[i]){var a=!1!==n.clone&&n.isMergeableObject(t);r[i]=a?sk(Array.isArray(t)?[]:{},t,n):t}else n.isMergeableObject(t)?r[i]=sk(e[i],t,n):-1===e.indexOf(t)&&r.push(t)}),r}function hC(e){return Array.from(e).filter(function(e){return e.selected}).map(function(e){return e.value})}function hI(e,t,n){if("boolean"==typeof e)return Boolean(t);var r=[],i=!1,a=-1;if(Array.isArray(e))r=e,i=(a=e.indexOf(n))>=0;else if(!n||"true"==n||"false"==n)return Boolean(t);return t&&n&&!i?r.concat(n):i?r.slice(0,a).concat(r.slice(a+1)):r}var hD="undefined"!=typeof window&&void 0!==window.document&&void 0!==window.document.createElement?l.useLayoutEffect:l.useEffect;function hN(e){var t=(0,l.useRef)(e);return hD(function(){t.current=e}),(0,l.useCallback)(function(){for(var e=arguments.length,n=Array(e),r=0;re?t:e},0);return Array.from(ha({},e,{length:t+1}))};(function(e){function t(t){var n;return(n=e.call(this,t)||this).updateArrayField=function(e,t,r){var i=n.props,a=i.name;(0,i.formik.setFormikState)(function(n){var i="function"==typeof r?r:e,o="function"==typeof t?t:e,s=hg(n.values,a,e(hm(n.values,a))),u=r?i(hm(n.errors,a)):void 0,c=t?o(hm(n.touched,a)):void 0;return hc(u)&&(u=void 0),hc(c)&&(c=void 0),ha({},n,{values:s,errors:r?hg(n.errors,a,u):n.errors,touched:t?hg(n.touched,a,c):n.touched})})},n.push=function(e){return n.updateArrayField(function(t){return[].concat(hU(t),[hi(e)])},!1,!1)},n.handlePush=function(e){return function(){return n.push(e)}},n.swap=function(e,t){return n.updateArrayField(function(n){return hF(n,e,t)},!0,!0)},n.handleSwap=function(e,t){return function(){return n.swap(e,t)}},n.move=function(e,t){return n.updateArrayField(function(n){return hj(n,e,t)},!0,!0)},n.handleMove=function(e,t){return function(){return n.move(e,t)}},n.insert=function(e,t){return n.updateArrayField(function(n){return hY(n,e,t)},function(t){return hY(t,e,null)},function(t){return hY(t,e,null)})},n.handleInsert=function(e,t){return function(){return n.insert(e,t)}},n.replace=function(e,t){return n.updateArrayField(function(n){return hB(n,e,t)},!1,!1)},n.handleReplace=function(e,t){return function(){return n.replace(e,t)}},n.unshift=function(e){var t=-1;return n.updateArrayField(function(n){var r=n?[e].concat(n):[e];return t<0&&(t=r.length),r},function(e){var n=e?[null].concat(e):[null];return t<0&&(t=n.length),n},function(e){var n=e?[null].concat(e):[null];return t<0&&(t=n.length),n}),t},n.handleUnshift=function(e){return function(){return n.unshift(e)}},n.handleRemove=function(e){return function(){return n.remove(e)}},n.handlePop=function(){return function(){return n.pop()}},n.remove=n.remove.bind(hu(n)),n.pop=n.pop.bind(hu(n)),n}ho(t,e);var n=t.prototype;return n.componentDidUpdate=function(e){this.props.validateOnChange&&this.props.formik.validateOnChange&&!sd()(hm(e.formik.values,e.name),hm(this.props.formik.values,this.props.name))&&this.props.formik.validateForm(this.props.formik.values)},n.remove=function(e){var t;return this.updateArrayField(function(n){var r=n?hU(n):[];return t||(t=r[e]),hl(r.splice)&&r.splice(e,1),r},!0,!0),t},n.pop=function(){var e;return this.updateArrayField(function(t){var n=t;return e||(e=n&&n.pop&&n.pop()),n},!0,!0),e},n.render=function(){var e={push:this.push,pop:this.pop,swap:this.swap,move:this.move,insert:this.insert,replace:this.replace,unshift:this.unshift,remove:this.remove,handlePush:this.handlePush,handlePop:this.handlePop,handleSwap:this.handleSwap,handleMove:this.handleMove,handleInsert:this.handleInsert,handleReplace:this.handleReplace,handleUnshift:this.handleUnshift,handleRemove:this.handleRemove},t=this.props,n=t.component,r=t.render,i=t.children,a=t.name,o=hs(t.formik,["validate","validationSchema"]),s=ha({},e,{form:o,name:a});return n?(0,l.createElement)(n,s):r?r(s):i?"function"==typeof i?i(s):hp(i)?null:l.Children.only(i):null},t})(l.Component).defaultProps={validateOnChange:!0},l.Component,l.Component;var hH=n(24802),h$=n(71209),hz=n(91750),hG=n(11970),hW=n(4689),hK=n(67598),hV=function(){return(hV=Object.assign||function(e){for(var t,n=1,r=arguments.length;nt.indexOf(r)&&(n[r]=e[r]);if(null!=e&&"function"==typeof Object.getOwnPropertySymbols)for(var i=0,r=Object.getOwnPropertySymbols(e);it.indexOf(r[i])&&(n[r[i]]=e[r[i]]);return n}function hZ(e){var t=e.disabled,n=e.field,r=n.onBlur,i=hq(n,["onBlur"]),a=e.form,o=a.isSubmitting,s=a.touched,u=a.errors,c=e.onBlur,l=e.helperText,f=hq(e,["disabled","field","form","onBlur","helperText"]),d=hm(u,i.name),h=hm(s,i.name)&&!!d;return hV(hV({variant:f.variant,error:h,helperText:h?d:l,disabled:null!=t?t:o,onBlur:null!=c?c:function(e){r(null!=e?e:i.name)}},i),f)}function hX(e){var t=e.children,n=hq(e,["children"]);return(0,l.createElement)(iw.Z,hV({},hZ(n)),t)}function hJ(e){var t=e.disabled,n=e.field,r=n.onBlur,i=hq(n,["onBlur"]),a=e.form.isSubmitting,o=(e.type,e.onBlur),s=hq(e,["disabled","field","form","type","onBlur"]);return hV(hV({disabled:null!=t?t:a,onBlur:null!=o?o:function(e){r(null!=e?e:i.name)}},i),s)}function hQ(e){return(0,l.createElement)(hH.Z,hV({},hJ(e)))}function h1(e){var t,n=e.disabled,r=e.field,i=r.onBlur,a=hq(r,["onBlur"]),o=e.form.isSubmitting,s=(e.type,e.onBlur),u=hq(e,["disabled","field","form","type","onBlur"]);return hV(hV({disabled:null!=n?n:o,indeterminate:!Array.isArray(a.value)&&null==a.value,onBlur:null!=s?s:function(e){i(null!=e?e:a.name)}},a),u)}function h0(e){return(0,l.createElement)(h$.Z,hV({},h1(e)))}function h2(e){var t=e.Label,n=hq(e,["Label"]);return(0,l.createElement)(hz.Z,hV({control:(0,l.createElement)(h$.Z,hV({},h1(n)))},t))}function h3(e){var t=e.disabled,n=e.field,r=n.onBlur,i=hq(n,["onBlur"]),a=e.form.isSubmitting,o=e.onBlur,s=hq(e,["disabled","field","form","onBlur"]);return hV(hV({disabled:null!=t?t:a,onBlur:null!=o?o:function(e){r(null!=e?e:i.name)}},i),s)}function h4(e){return(0,l.createElement)(hG.default,hV({},h3(e)))}function h6(e){var t=e.field,n=t.onBlur,r=hq(t,["onBlur"]),i=(e.form,e.onBlur),a=hq(e,["field","form","onBlur"]);return hV(hV({onBlur:null!=i?i:function(e){n(null!=e?e:r.name)}},r),a)}function h5(e){return(0,l.createElement)(hW.Z,hV({},h6(e)))}function h8(e){var t=e.disabled,n=e.field,r=n.onBlur,i=hq(n,["onBlur"]),a=e.form.isSubmitting,o=e.onBlur,s=hq(e,["disabled","field","form","onBlur"]);return hV(hV({disabled:null!=t?t:a,onBlur:null!=o?o:function(e){r(null!=e?e:i.name)}},i),s)}function h9(e){return(0,l.createElement)(hK.default,hV({},h8(e)))}hX.displayName="FormikMaterialUITextField",hQ.displayName="FormikMaterialUISwitch",h0.displayName="FormikMaterialUICheckbox",h2.displayName="FormikMaterialUICheckboxWithLabel",h4.displayName="FormikMaterialUISelect",h5.displayName="FormikMaterialUIRadioGroup",h9.displayName="FormikMaterialUIInputBase";try{a=Map}catch(h7){}try{o=Set}catch(pe){}function pt(e,t,n){if(!e||"object"!=typeof e||"function"==typeof e)return e;if(e.nodeType&&"cloneNode"in e)return e.cloneNode(!0);if(e instanceof Date)return new Date(e.getTime());if(e instanceof RegExp)return RegExp(e);if(Array.isArray(e))return e.map(pn);if(a&&e instanceof a)return new Map(Array.from(e.entries()));if(o&&e instanceof o)return new Set(Array.from(e.values()));if(e instanceof Object){t.push(e);var r=Object.create(e);for(var i in n.push(r),e){var s=t.findIndex(function(t){return t===e[i]});r[i]=s>-1?n[s]:pt(e[i],t,n)}return r}return e}function pn(e){return pt(e,[],[])}let pr=Object.prototype.toString,pi=Error.prototype.toString,pa=RegExp.prototype.toString,po="undefined"!=typeof Symbol?Symbol.prototype.toString:()=>"",ps=/^Symbol\((.*)\)(.*)$/;function pu(e){if(e!=+e)return"NaN";let t=0===e&&1/e<0;return t?"-0":""+e}function pc(e,t=!1){if(null==e||!0===e||!1===e)return""+e;let n=typeof e;if("number"===n)return pu(e);if("string"===n)return t?`"${e}"`:e;if("function"===n)return"[Function "+(e.name||"anonymous")+"]";if("symbol"===n)return po.call(e).replace(ps,"Symbol($1)");let r=pr.call(e).slice(8,-1);return"Date"===r?isNaN(e.getTime())?""+e:e.toISOString(e):"Error"===r||e instanceof Error?"["+pi.call(e)+"]":"RegExp"===r?pa.call(e):null}function pl(e,t){let n=pc(e,t);return null!==n?n:JSON.stringify(e,function(e,n){let r=pc(this[e],t);return null!==r?r:n},2)}let pf={default:"${path} is invalid",required:"${path} is a required field",oneOf:"${path} must be one of the following values: ${values}",notOneOf:"${path} must not be one of the following values: ${values}",notType({path:e,type:t,value:n,originalValue:r}){let i=null!=r&&r!==n,a=`${e} must be a \`${t}\` type, but the final value was: \`${pl(n,!0)}\``+(i?` (cast from the value \`${pl(r,!0)}\`).`:".");return null===n&&(a+='\n If "null" is intended as an empty value be sure to mark the schema as `.nullable()`'),a},defined:"${path} must be defined"},pd={length:"${path} must be exactly ${length} characters",min:"${path} must be at least ${min} characters",max:"${path} must be at most ${max} characters",matches:'${path} must match the following: "${regex}"',email:"${path} must be a valid email",url:"${path} must be a valid URL",uuid:"${path} must be a valid UUID",trim:"${path} must be a trimmed string",lowercase:"${path} must be a lowercase string",uppercase:"${path} must be a upper case string"},ph={min:"${path} must be greater than or equal to ${min}",max:"${path} must be less than or equal to ${max}",lessThan:"${path} must be less than ${less}",moreThan:"${path} must be greater than ${more}",positive:"${path} must be a positive number",negative:"${path} must be a negative number",integer:"${path} must be an integer"},pp={min:"${path} field must be later than ${min}",max:"${path} field must be at earlier than ${max}"},pb={isValue:"${path} field must be ${value}"},pm={noUnknown:"${path} field has unspecified keys: ${unknown}"},pg={min:"${path} field must have at least ${min} items",max:"${path} field must have less than or equal to ${max} items",length:"${path} must be have ${length} items"};Object.assign(Object.create(null),{mixed:pf,string:pd,number:ph,date:pp,object:pm,array:pg,boolean:pb});var pv=n(18721),py=n.n(pv);let pw=e=>e&&e.__isYupSchema__;class p_{constructor(e,t){if(this.refs=e,this.refs=e,"function"==typeof t){this.fn=t;return}if(!py()(t,"is"))throw TypeError("`is:` is required for `when()` conditions");if(!t.then&&!t.otherwise)throw TypeError("either `then:` or `otherwise:` is required for `when()` conditions");let{is:n,then:r,otherwise:i}=t,a="function"==typeof n?n:(...e)=>e.every(e=>e===n);this.fn=function(...e){let t=e.pop(),n=e.pop(),o=a(...e)?r:i;if(o)return"function"==typeof o?o(n):n.concat(o.resolve(t))}}resolve(e,t){let n=this.refs.map(e=>e.getValue(null==t?void 0:t.value,null==t?void 0:t.parent,null==t?void 0:t.context)),r=this.fn.apply(e,n.concat(e,t));if(void 0===r||r===e)return e;if(!pw(r))throw TypeError("conditions must return a schema object");return r.resolve(t)}}let pE=p_;function pS(e){return null==e?[]:[].concat(e)}function pk(){return(pk=Object.assign||function(e){for(var t=1;tpl(t[n])):"function"==typeof e?e(t):e}static isError(e){return e&&"ValidationError"===e.name}constructor(e,t,n,r){super(),this.name="ValidationError",this.value=t,this.path=n,this.type=r,this.errors=[],this.inner=[],pS(e).forEach(e=>{pT.isError(e)?(this.errors.push(...e.errors),this.inner=this.inner.concat(e.inner.length?e.inner:e)):this.errors.push(e)}),this.message=this.errors.length>1?`${this.errors.length} errors occurred`:this.errors[0],Error.captureStackTrace&&Error.captureStackTrace(this,pT)}}let pM=e=>{let t=!1;return(...n)=>{t||(t=!0,e(...n))}};function pO(e,t){let{endEarly:n,tests:r,args:i,value:a,errors:o,sort:s,path:u}=e,c=pM(t),l=r.length,f=[];if(o=o||[],!l)return o.length?c(new pT(o,a,u)):c(null,a);for(let d=0;d=0||(i[n]=e[n]);return i}function pR(e){function t(t,n){let{value:r,path:i="",label:a,options:o,originalValue:s,sync:u}=t,c=pP(t,["value","path","label","options","originalValue","sync"]),{name:l,test:f,params:d,message:h}=e,{parent:p,context:b}=o;function m(e){return pD.isRef(e)?e.getValue(r,p,b):e}function g(e={}){let t=pL()(pN({value:r,originalValue:s,label:a,path:e.path||i},d,e.params),m),n=new pT(pT.formatError(e.message||h,t),r,t.path,e.type||l);return n.params=t,n}let v=pN({path:i,parent:p,type:l,createError:g,resolve:m,options:o,originalValue:s},c);if(!u){try{Promise.resolve(f.call(v,r,v)).then(e=>{pT.isError(e)?n(e):e?n(null,e):n(g())})}catch(y){n(y)}return}let w;try{var _;if(w=f.call(v,r,v),"function"==typeof(null==(_=w)?void 0:_.then))throw Error(`Validation test of type: "${v.type}" returned a Promise during a synchronous validate. This test will finish after the validate call has returned`)}catch(E){n(E);return}pT.isError(w)?n(w):w?n(null,w):n(g())}return t.OPTIONS=e,t}pD.prototype.__isYupRef=!0;let pj=e=>e.substr(0,e.length-1).substr(1);function pF(e,t,n,r=n){let i,a,o;return t?((0,pC.forEach)(t,(s,u,c)=>{let l=u?pj(s):s;if((e=e.resolve({context:r,parent:i,value:n})).innerType){let f=c?parseInt(l,10):0;if(n&&f>=n.length)throw Error(`Yup.reach cannot resolve an array item at index: ${s}, in the path: ${t}. because there is no value at that index. `);i=n,n=n&&n[f],e=e.innerType}if(!c){if(!e.fields||!e.fields[l])throw Error(`The schema does not contain the path: ${t}. (failed at: ${o} which is a type: "${e._type}")`);i=n,n=n&&n[l],e=e.fields[l]}a=l,o=u?"["+s+"]":"."+s}),{schema:e,parent:i,parentPath:a}):{parent:i,parentPath:t,schema:e}}class pY{constructor(){this.list=new Set,this.refs=new Map}get size(){return this.list.size+this.refs.size}describe(){let e=[];for(let t of this.list)e.push(t);for(let[,n]of this.refs)e.push(n.describe());return e}toArray(){return Array.from(this.list).concat(Array.from(this.refs.values()))}add(e){pD.isRef(e)?this.refs.set(e.key,e):this.list.add(e)}delete(e){pD.isRef(e)?this.refs.delete(e.key):this.list.delete(e)}has(e,t){if(this.list.has(e))return!0;let n,r=this.refs.values();for(;!(n=r.next()).done;)if(t(n.value)===e)return!0;return!1}clone(){let e=new pY;return e.list=new Set(this.list),e.refs=new Map(this.refs),e}merge(e,t){let n=this.clone();return e.list.forEach(e=>n.add(e)),e.refs.forEach(e=>n.add(e)),t.list.forEach(e=>n.delete(e)),t.refs.forEach(e=>n.delete(e)),n}}function pB(){return(pB=Object.assign||function(e){for(var t=1;t{this.typeError(pf.notType)}),this.type=(null==e?void 0:e.type)||"mixed",this.spec=pB({strip:!1,strict:!1,abortEarly:!0,recursive:!0,nullable:!1,presence:"optional"},null==e?void 0:e.spec)}get _type(){return this.type}_typeCheck(e){return!0}clone(e){if(this._mutate)return e&&Object.assign(this.spec,e),this;let t=Object.create(Object.getPrototypeOf(this));return t.type=this.type,t._typeError=this._typeError,t._whitelistError=this._whitelistError,t._blacklistError=this._blacklistError,t._whitelist=this._whitelist.clone(),t._blacklist=this._blacklist.clone(),t.exclusiveTests=pB({},this.exclusiveTests),t.deps=[...this.deps],t.conditions=[...this.conditions],t.tests=[...this.tests],t.transforms=[...this.transforms],t.spec=pn(pB({},this.spec,e)),t}label(e){var t=this.clone();return t.spec.label=e,t}meta(...e){if(0===e.length)return this.spec.meta;let t=this.clone();return t.spec.meta=Object.assign(t.spec.meta||{},e[0]),t}withMutation(e){let t=this._mutate;this._mutate=!0;let n=e(this);return this._mutate=t,n}concat(e){if(!e||e===this)return this;if(e.type!==this.type&&"mixed"!==this.type)throw TypeError(`You cannot \`concat()\` schema's of different types: ${this.type} and ${e.type}`);let t=this,n=e.clone(),r=pB({},t.spec,n.spec);return n.spec=r,n._typeError||(n._typeError=t._typeError),n._whitelistError||(n._whitelistError=t._whitelistError),n._blacklistError||(n._blacklistError=t._blacklistError),n._whitelist=t._whitelist.merge(e._whitelist,e._blacklist),n._blacklist=t._blacklist.merge(e._blacklist,e._whitelist),n.tests=t.tests,n.exclusiveTests=t.exclusiveTests,n.withMutation(t=>{e.tests.forEach(e=>{t.test(e.OPTIONS)})}),n}isType(e){return!!this.spec.nullable&&null===e||this._typeCheck(e)}resolve(e){let t=this;if(t.conditions.length){let n=t.conditions;(t=t.clone()).conditions=[],t=(t=n.reduce((t,n)=>n.resolve(t,e),t)).resolve(e)}return t}cast(e,t={}){let n=this.resolve(pB({value:e},t)),r=n._cast(e,t);if(void 0!==e&&!1!==t.assert&&!0!==n.isType(r)){let i=pl(e),a=pl(r);throw TypeError(`The value of ${t.path||"field"} could not be cast to a value that satisfies the schema type: "${n._type}". + */ Object.defineProperty(t,"__esModule",{value:!0}),"undefined"==typeof window||"function"!=typeof MessageChannel){var n,r,i,a,o,s=null,u=null,c=function(){if(null!==s)try{var e=t.unstable_now();s(!0,e),s=null}catch(n){throw setTimeout(c,0),n}},l=Date.now();t.unstable_now=function(){return Date.now()-l},n=function(e){null!==s?setTimeout(n,0,e):(s=e,setTimeout(c,0))},r=function(e,t){u=setTimeout(e,t)},i=function(){clearTimeout(u)},a=function(){return!1},o=t.unstable_forceFrameRate=function(){}}else{var f=window.performance,d=window.Date,h=window.setTimeout,p=window.clearTimeout;if("undefined"!=typeof console){var b=window.cancelAnimationFrame;"function"!=typeof window.requestAnimationFrame&&console.error("This browser doesn't support requestAnimationFrame. Make sure that you load a polyfill in older browsers. https://fb.me/react-polyfills"),"function"!=typeof b&&console.error("This browser doesn't support cancelAnimationFrame. Make sure that you load a polyfill in older browsers. https://fb.me/react-polyfills")}if("object"==typeof f&&"function"==typeof f.now)t.unstable_now=function(){return f.now()};else{var m=d.now();t.unstable_now=function(){return d.now()-m}}var g=!1,v=null,y=-1,w=5,_=0;a=function(){return t.unstable_now()>=_},o=function(){},t.unstable_forceFrameRate=function(e){0>e||125M(o,n))void 0!==u&&0>M(u,o)?(e[r]=u,e[s]=n,r=s):(e[r]=o,e[a]=n,r=a);else if(void 0!==u&&0>M(u,n))e[r]=u,e[s]=n,r=s;else break a}}return t}return null}function M(e,t){var n=e.sortIndex-t.sortIndex;return 0!==n?n:e.id-t.id}var O=[],A=[],L=1,C=null,I=3,D=!1,N=!1,P=!1;function R(e){for(var t=x(A);null!==t;){if(null===t.callback)T(A);else if(t.startTime<=e)T(A),t.sortIndex=t.expirationTime,k(O,t);else break;t=x(A)}}function j(e){if(P=!1,R(e),!N){if(null!==x(O))N=!0,n(F);else{var t=x(A);null!==t&&r(j,t.startTime-e)}}}function F(e,n){N=!1,P&&(P=!1,i()),D=!0;var o=I;try{for(R(n),C=x(O);null!==C&&(!(C.expirationTime>n)||e&&!a());){var s=C.callback;if(null!==s){C.callback=null,I=C.priorityLevel;var u=s(C.expirationTime<=n);n=t.unstable_now(),"function"==typeof u?C.callback=u:C===x(O)&&T(O),R(n)}else T(O);C=x(O)}if(null!==C)var c=!0;else{var l=x(A);null!==l&&r(j,l.startTime-n),c=!1}return c}finally{C=null,I=o,D=!1}}function Y(e){switch(e){case 1:return -1;case 2:return 250;case 5:return 1073741823;case 4:return 1e4;default:return 5e3}}var B=o;t.unstable_ImmediatePriority=1,t.unstable_UserBlockingPriority=2,t.unstable_NormalPriority=3,t.unstable_IdlePriority=5,t.unstable_LowPriority=4,t.unstable_runWithPriority=function(e,t){switch(e){case 1:case 2:case 3:case 4:case 5:break;default:e=3}var n=I;I=e;try{return t()}finally{I=n}},t.unstable_next=function(e){switch(I){case 1:case 2:case 3:var t=3;break;default:t=I}var n=I;I=t;try{return e()}finally{I=n}},t.unstable_scheduleCallback=function(e,a,o){var s=t.unstable_now();if("object"==typeof o&&null!==o){var u=o.delay;u="number"==typeof u&&0s?(e.sortIndex=u,k(A,e),null===x(O)&&e===x(A)&&(P?i():P=!0,r(j,u-s))):(e.sortIndex=o,k(O,e),N||D||(N=!0,n(F))),e},t.unstable_cancelCallback=function(e){e.callback=null},t.unstable_wrapCallback=function(e){var t=I;return function(){var n=I;I=t;try{return e.apply(this,arguments)}finally{I=n}}},t.unstable_getCurrentPriorityLevel=function(){return I},t.unstable_shouldYield=function(){var e=t.unstable_now();R(e);var n=x(O);return n!==C&&null!==C&&null!==n&&null!==n.callback&&n.startTime<=e&&n.expirationTime>5==6?2:e>>4==14?3:e>>3==30?4:e>>6==2?-1:-2}function c(e,t,n){var r=t.length-1;if(r=0?(i>0&&(e.lastNeed=i-1),i):--r=0?(i>0&&(e.lastNeed=i-2),i):--r=0?(i>0&&(2===i?i=0:e.lastNeed=i-3),i):0}function l(e,t,n){if((192&t[0])!=128)return e.lastNeed=0,"�";if(e.lastNeed>1&&t.length>1){if((192&t[1])!=128)return e.lastNeed=1,"�";if(e.lastNeed>2&&t.length>2&&(192&t[2])!=128)return e.lastNeed=2,"�"}}function f(e){var t=this.lastTotal-this.lastNeed,n=l(this,e,t);return void 0!==n?n:this.lastNeed<=e.length?(e.copy(this.lastChar,t,0,this.lastNeed),this.lastChar.toString(this.encoding,0,this.lastTotal)):void(e.copy(this.lastChar,t,0,e.length),this.lastNeed-=e.length)}function d(e,t){var n=c(this,e,t);if(!this.lastNeed)return e.toString("utf8",t);this.lastTotal=n;var r=e.length-(n-this.lastNeed);return e.copy(this.lastChar,0,r),e.toString("utf8",t,r)}function h(e){var t=e&&e.length?this.write(e):"";return this.lastNeed?t+"�":t}function p(e,t){if((e.length-t)%2==0){var n=e.toString("utf16le",t);if(n){var r=n.charCodeAt(n.length-1);if(r>=55296&&r<=56319)return this.lastNeed=2,this.lastTotal=4,this.lastChar[0]=e[e.length-2],this.lastChar[1]=e[e.length-1],n.slice(0,-1)}return n}return this.lastNeed=1,this.lastTotal=2,this.lastChar[0]=e[e.length-1],e.toString("utf16le",t,e.length-1)}function b(e){var t=e&&e.length?this.write(e):"";if(this.lastNeed){var n=this.lastTotal-this.lastNeed;return t+this.lastChar.toString("utf16le",0,n)}return t}function m(e,t){var n=(e.length-t)%3;return 0===n?e.toString("base64",t):(this.lastNeed=3-n,this.lastTotal=3,1===n?this.lastChar[0]=e[e.length-1]:(this.lastChar[0]=e[e.length-2],this.lastChar[1]=e[e.length-1]),e.toString("base64",t,e.length-n))}function g(e){var t=e&&e.length?this.write(e):"";return this.lastNeed?t+this.lastChar.toString("base64",0,3-this.lastNeed):t}function v(e){return e.toString(this.encoding)}function y(e){return e&&e.length?this.write(e):""}t.s=s,s.prototype.write=function(e){var t,n;if(0===e.length)return"";if(this.lastNeed){if(void 0===(t=this.fillLast(e)))return"";n=this.lastNeed,this.lastNeed=0}else n=0;return n */ var r=n(48764),i=r.Buffer;function a(e,t){for(var n in e)t[n]=e[n]}function o(e,t,n){return i(e,t,n)}i.from&&i.alloc&&i.allocUnsafe&&i.allocUnsafeSlow?e.exports=r:(a(r,t),t.Buffer=o),o.prototype=Object.create(i.prototype),a(i,o),o.from=function(e,t,n){if("number"==typeof e)throw TypeError("Argument must not be a number");return i(e,t,n)},o.alloc=function(e,t,n){if("number"!=typeof e)throw TypeError("Argument must be a number");var r=i(e);return void 0!==t?"string"==typeof n?r.fill(t,n):r.fill(t):r.fill(0),r},o.allocUnsafe=function(e){if("number"!=typeof e)throw TypeError("Argument must be a number");return i(e)},o.allocUnsafeSlow=function(e){if("number"!=typeof e)throw TypeError("Argument must be a number");return r.SlowBuffer(e)}},93379(e,t,n){"use strict";var r,i,a=function(){return void 0===r&&(r=Boolean(window&&document&&document.all&&!window.atob)),r},o=(i={},function(e){if(void 0===i[e]){var t=document.querySelector(e);if(window.HTMLIFrameElement&&t instanceof window.HTMLIFrameElement)try{t=t.contentDocument.head}catch(n){t=null}i[e]=t}return i[e]}),s=[];function u(e){for(var t=-1,n=0;nAl});var r,i,a,o,s,u,c,l=n(67294),f=n.t(l,2),d=n(39814),h=n(5977),p=n(57209),b=n(32316),m=n(95880),g=n(17051),v=n(71381),y=n(81701),w=n(3022),_=n(60323),E=n(87591),S=n(25649),k=n(28902),x=n(71426),T=n(48884),M=n(94184),O=n.n(M),A=n(37703),L=n(73935),C=function(){if("undefined"!=typeof Map)return Map;function e(e,t){var n=-1;return e.some(function(e,r){return e[0]===t&&(n=r,!0)}),n}return function(){function t(){this.__entries__=[]}return Object.defineProperty(t.prototype,"size",{get:function(){return this.__entries__.length},enumerable:!0,configurable:!0}),t.prototype.get=function(t){var n=e(this.__entries__,t),r=this.__entries__[n];return r&&r[1]},t.prototype.set=function(t,n){var r=e(this.__entries__,t);~r?this.__entries__[r][1]=n:this.__entries__.push([t,n])},t.prototype.delete=function(t){var n=this.__entries__,r=e(n,t);~r&&n.splice(r,1)},t.prototype.has=function(t){return!!~e(this.__entries__,t)},t.prototype.clear=function(){this.__entries__.splice(0)},t.prototype.forEach=function(e,t){void 0===t&&(t=null);for(var n=0,r=this.__entries__;n0},e.prototype.connect_=function(){I&&!this.connected_&&(document.addEventListener("transitionend",this.onTransitionEnd_),window.addEventListener("resize",this.refresh),Y?(this.mutationsObserver_=new MutationObserver(this.refresh),this.mutationsObserver_.observe(document,{attributes:!0,childList:!0,characterData:!0,subtree:!0})):(document.addEventListener("DOMSubtreeModified",this.refresh),this.mutationEventsAdded_=!0),this.connected_=!0)},e.prototype.disconnect_=function(){I&&this.connected_&&(document.removeEventListener("transitionend",this.onTransitionEnd_),window.removeEventListener("resize",this.refresh),this.mutationsObserver_&&this.mutationsObserver_.disconnect(),this.mutationEventsAdded_&&document.removeEventListener("DOMSubtreeModified",this.refresh),this.mutationsObserver_=null,this.mutationEventsAdded_=!1,this.connected_=!1)},e.prototype.onTransitionEnd_=function(e){var t=e.propertyName,n=void 0===t?"":t;F.some(function(e){return!!~n.indexOf(e)})&&this.refresh()},e.getInstance=function(){return this.instance_||(this.instance_=new e),this.instance_},e.instance_=null,e}(),U=function(e,t){for(var n=0,r=Object.keys(t);n0},e}(),er="undefined"!=typeof WeakMap?new WeakMap:new C,ei=function(){function e(t){if(!(this instanceof e))throw TypeError("Cannot call a class as a function.");if(!arguments.length)throw TypeError("1 argument required, but only 0 present.");var n=B.getInstance(),r=new en(t,n,this);er.set(this,r)}return e}();["observe","unobserve","disconnect"].forEach(function(e){ei.prototype[e]=function(){var t;return(t=er.get(this))[e].apply(t,arguments)}});var ea=void 0!==D.ResizeObserver?D.ResizeObserver:ei;let eo=ea;var es=function(e){var t=[],n=null,r=function(){for(var r=arguments.length,i=Array(r),a=0;a=t||n<0||f&&r>=a}function g(){var e=eb();if(m(e))return v(e);s=setTimeout(g,b(e))}function v(e){return(s=void 0,d&&r)?h(e):(r=i=void 0,o)}function y(){void 0!==s&&clearTimeout(s),c=0,r=u=i=s=void 0}function w(){return void 0===s?o:v(eb())}function _(){var e=eb(),n=m(e);if(r=arguments,i=this,u=e,n){if(void 0===s)return p(u);if(f)return clearTimeout(s),s=setTimeout(g,t),h(u)}return void 0===s&&(s=setTimeout(g,t)),o}return t=ez(t)||0,ed(n)&&(l=!!n.leading,a=(f="maxWait"in n)?eW(ez(n.maxWait)||0,t):a,d="trailing"in n?!!n.trailing:d),_.cancel=y,_.flush=w,_}let eq=eV;var eZ="Expected a function";function eX(e,t,n){var r=!0,i=!0;if("function"!=typeof e)throw TypeError(eZ);return ed(n)&&(r="leading"in n?!!n.leading:r,i="trailing"in n?!!n.trailing:i),eq(e,t,{leading:r,maxWait:t,trailing:i})}let eJ=eX;var eQ={debounce:eq,throttle:eJ},e1=function(e){return eQ[e]},e0=function(e){return"function"==typeof e},e2=function(){return"undefined"==typeof window},e3=function(e){return e instanceof Element||e instanceof HTMLDocument};function e4(e){return(e4="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e})(e)}function e6(e,t){if(!(e instanceof t))throw TypeError("Cannot call a class as a function")}function e5(e,t){for(var n=0;ne.length)&&(t=e.length);for(var n=0,r=Array(t);ne.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&l.createElement(tG.Z,{variant:"indeterminate",classes:r}))};tK.propTypes={fetchCount:el().number.isRequired};let tV=(0,b.withStyles)(tW)(tK);var tq=n(5536);let tZ=n.p+"ba8bbf16ebf8e1d05bef.svg";function tX(){return(tX=Object.assign||function(e){for(var t=1;t120){for(var d=Math.floor(u/80),h=u%80,p=[],b=0;b0},name:{enumerable:!1},nodes:{enumerable:!1},source:{enumerable:!1},positions:{enumerable:!1},originalError:{enumerable:!1}}),null!=s&&s.stack)?(Object.defineProperty(nf(b),"stack",{value:s.stack,writable:!0,configurable:!0}),nl(b)):(Error.captureStackTrace?Error.captureStackTrace(nf(b),n):Object.defineProperty(nf(b),"stack",{value:Error().stack,writable:!0,configurable:!0}),b)}return ns(n,[{key:"toString",value:function(){return nw(this)}},{key:t4.YF,get:function(){return"Object"}}]),n}(nd(Error));function ny(e){return void 0===e||0===e.length?void 0:e}function nw(e){var t=e.message;if(e.nodes)for(var n=0,r=e.nodes;n",EOF:"",BANG:"!",DOLLAR:"$",AMP:"&",PAREN_L:"(",PAREN_R:")",SPREAD:"...",COLON:":",EQUALS:"=",AT:"@",BRACKET_L:"[",BRACKET_R:"]",BRACE_L:"{",PIPE:"|",BRACE_R:"}",NAME:"Name",INT:"Int",FLOAT:"Float",STRING:"String",BLOCK_STRING:"BlockString",COMMENT:"Comment"}),nx=n(10143),nT=Object.freeze({QUERY:"QUERY",MUTATION:"MUTATION",SUBSCRIPTION:"SUBSCRIPTION",FIELD:"FIELD",FRAGMENT_DEFINITION:"FRAGMENT_DEFINITION",FRAGMENT_SPREAD:"FRAGMENT_SPREAD",INLINE_FRAGMENT:"INLINE_FRAGMENT",VARIABLE_DEFINITION:"VARIABLE_DEFINITION",SCHEMA:"SCHEMA",SCALAR:"SCALAR",OBJECT:"OBJECT",FIELD_DEFINITION:"FIELD_DEFINITION",ARGUMENT_DEFINITION:"ARGUMENT_DEFINITION",INTERFACE:"INTERFACE",UNION:"UNION",ENUM:"ENUM",ENUM_VALUE:"ENUM_VALUE",INPUT_OBJECT:"INPUT_OBJECT",INPUT_FIELD_DEFINITION:"INPUT_FIELD_DEFINITION"}),nM=n(87392),nO=function(){function e(e){var t=new nS.WU(nk.SOF,0,0,0,0,null);this.source=e,this.lastToken=t,this.token=t,this.line=1,this.lineStart=0}var t=e.prototype;return t.advance=function(){return this.lastToken=this.token,this.token=this.lookahead()},t.lookahead=function(){var e,t=this.token;if(t.kind!==nk.EOF)do t=null!==(e=t.next)&&void 0!==e?e:t.next=nC(this,t);while(t.kind===nk.COMMENT)return t},e}();function nA(e){return e===nk.BANG||e===nk.DOLLAR||e===nk.AMP||e===nk.PAREN_L||e===nk.PAREN_R||e===nk.SPREAD||e===nk.COLON||e===nk.EQUALS||e===nk.AT||e===nk.BRACKET_L||e===nk.BRACKET_R||e===nk.BRACE_L||e===nk.PIPE||e===nk.BRACE_R}function nL(e){return isNaN(e)?nk.EOF:e<127?JSON.stringify(String.fromCharCode(e)):'"\\u'.concat(("00"+e.toString(16).toUpperCase()).slice(-4),'"')}function nC(e,t){for(var n=e.source,r=n.body,i=r.length,a=t.end;a31||9===a))return new nS.WU(nk.COMMENT,t,s,n,r,i,o.slice(t+1,s))}function nN(e,t,n,r,i,a){var o=e.body,s=n,u=t,c=!1;if(45===s&&(s=o.charCodeAt(++u)),48===s){if((s=o.charCodeAt(++u))>=48&&s<=57)throw n_(e,u,"Invalid number, unexpected digit after 0: ".concat(nL(s),"."))}else u=nP(e,u,s),s=o.charCodeAt(u);if(46===s&&(c=!0,s=o.charCodeAt(++u),u=nP(e,u,s),s=o.charCodeAt(u)),(69===s||101===s)&&(c=!0,(43===(s=o.charCodeAt(++u))||45===s)&&(s=o.charCodeAt(++u)),u=nP(e,u,s),s=o.charCodeAt(u)),46===s||nU(s))throw n_(e,u,"Invalid number, expected digit but got: ".concat(nL(s),"."));return new nS.WU(c?nk.FLOAT:nk.INT,t,u,r,i,a,o.slice(t,u))}function nP(e,t,n){var r=e.body,i=t,a=n;if(a>=48&&a<=57){do a=r.charCodeAt(++i);while(a>=48&&a<=57)return i}throw n_(e,i,"Invalid number, expected digit but got: ".concat(nL(a),"."))}function nR(e,t,n,r,i){for(var a=e.body,o=t+1,s=o,u=0,c="";o=48&&e<=57?e-48:e>=65&&e<=70?e-55:e>=97&&e<=102?e-87:-1}function nB(e,t,n,r,i){for(var a=e.body,o=a.length,s=t+1,u=0;s!==o&&!isNaN(u=a.charCodeAt(s))&&(95===u||u>=48&&u<=57||u>=65&&u<=90||u>=97&&u<=122);)++s;return new nS.WU(nk.NAME,t,s,n,r,i,a.slice(t,s))}function nU(e){return 95===e||e>=65&&e<=90||e>=97&&e<=122}function nH(e,t){return new n$(e,t).parseDocument()}var n$=function(){function e(e,t){var n=(0,nx.T)(e)?e:new nx.H(e);this._lexer=new nO(n),this._options=t}var t=e.prototype;return t.parseName=function(){var e=this.expectToken(nk.NAME);return{kind:nE.h.NAME,value:e.value,loc:this.loc(e)}},t.parseDocument=function(){var e=this._lexer.token;return{kind:nE.h.DOCUMENT,definitions:this.many(nk.SOF,this.parseDefinition,nk.EOF),loc:this.loc(e)}},t.parseDefinition=function(){if(this.peek(nk.NAME))switch(this._lexer.token.value){case"query":case"mutation":case"subscription":return this.parseOperationDefinition();case"fragment":return this.parseFragmentDefinition();case"schema":case"scalar":case"type":case"interface":case"union":case"enum":case"input":case"directive":return this.parseTypeSystemDefinition();case"extend":return this.parseTypeSystemExtension()}else if(this.peek(nk.BRACE_L))return this.parseOperationDefinition();else if(this.peekDescription())return this.parseTypeSystemDefinition();throw this.unexpected()},t.parseOperationDefinition=function(){var e,t=this._lexer.token;if(this.peek(nk.BRACE_L))return{kind:nE.h.OPERATION_DEFINITION,operation:"query",name:void 0,variableDefinitions:[],directives:[],selectionSet:this.parseSelectionSet(),loc:this.loc(t)};var n=this.parseOperationType();return this.peek(nk.NAME)&&(e=this.parseName()),{kind:nE.h.OPERATION_DEFINITION,operation:n,name:e,variableDefinitions:this.parseVariableDefinitions(),directives:this.parseDirectives(!1),selectionSet:this.parseSelectionSet(),loc:this.loc(t)}},t.parseOperationType=function(){var e=this.expectToken(nk.NAME);switch(e.value){case"query":return"query";case"mutation":return"mutation";case"subscription":return"subscription"}throw this.unexpected(e)},t.parseVariableDefinitions=function(){return this.optionalMany(nk.PAREN_L,this.parseVariableDefinition,nk.PAREN_R)},t.parseVariableDefinition=function(){var e=this._lexer.token;return{kind:nE.h.VARIABLE_DEFINITION,variable:this.parseVariable(),type:(this.expectToken(nk.COLON),this.parseTypeReference()),defaultValue:this.expectOptionalToken(nk.EQUALS)?this.parseValueLiteral(!0):void 0,directives:this.parseDirectives(!0),loc:this.loc(e)}},t.parseVariable=function(){var e=this._lexer.token;return this.expectToken(nk.DOLLAR),{kind:nE.h.VARIABLE,name:this.parseName(),loc:this.loc(e)}},t.parseSelectionSet=function(){var e=this._lexer.token;return{kind:nE.h.SELECTION_SET,selections:this.many(nk.BRACE_L,this.parseSelection,nk.BRACE_R),loc:this.loc(e)}},t.parseSelection=function(){return this.peek(nk.SPREAD)?this.parseFragment():this.parseField()},t.parseField=function(){var e,t,n=this._lexer.token,r=this.parseName();return this.expectOptionalToken(nk.COLON)?(e=r,t=this.parseName()):t=r,{kind:nE.h.FIELD,alias:e,name:t,arguments:this.parseArguments(!1),directives:this.parseDirectives(!1),selectionSet:this.peek(nk.BRACE_L)?this.parseSelectionSet():void 0,loc:this.loc(n)}},t.parseArguments=function(e){var t=e?this.parseConstArgument:this.parseArgument;return this.optionalMany(nk.PAREN_L,t,nk.PAREN_R)},t.parseArgument=function(){var e=this._lexer.token,t=this.parseName();return this.expectToken(nk.COLON),{kind:nE.h.ARGUMENT,name:t,value:this.parseValueLiteral(!1),loc:this.loc(e)}},t.parseConstArgument=function(){var e=this._lexer.token;return{kind:nE.h.ARGUMENT,name:this.parseName(),value:(this.expectToken(nk.COLON),this.parseValueLiteral(!0)),loc:this.loc(e)}},t.parseFragment=function(){var e=this._lexer.token;this.expectToken(nk.SPREAD);var t=this.expectOptionalKeyword("on");return!t&&this.peek(nk.NAME)?{kind:nE.h.FRAGMENT_SPREAD,name:this.parseFragmentName(),directives:this.parseDirectives(!1),loc:this.loc(e)}:{kind:nE.h.INLINE_FRAGMENT,typeCondition:t?this.parseNamedType():void 0,directives:this.parseDirectives(!1),selectionSet:this.parseSelectionSet(),loc:this.loc(e)}},t.parseFragmentDefinition=function(){var e,t=this._lexer.token;return(this.expectKeyword("fragment"),(null===(e=this._options)||void 0===e?void 0:e.experimentalFragmentVariables)===!0)?{kind:nE.h.FRAGMENT_DEFINITION,name:this.parseFragmentName(),variableDefinitions:this.parseVariableDefinitions(),typeCondition:(this.expectKeyword("on"),this.parseNamedType()),directives:this.parseDirectives(!1),selectionSet:this.parseSelectionSet(),loc:this.loc(t)}:{kind:nE.h.FRAGMENT_DEFINITION,name:this.parseFragmentName(),typeCondition:(this.expectKeyword("on"),this.parseNamedType()),directives:this.parseDirectives(!1),selectionSet:this.parseSelectionSet(),loc:this.loc(t)}},t.parseFragmentName=function(){if("on"===this._lexer.token.value)throw this.unexpected();return this.parseName()},t.parseValueLiteral=function(e){var t=this._lexer.token;switch(t.kind){case nk.BRACKET_L:return this.parseList(e);case nk.BRACE_L:return this.parseObject(e);case nk.INT:return this._lexer.advance(),{kind:nE.h.INT,value:t.value,loc:this.loc(t)};case nk.FLOAT:return this._lexer.advance(),{kind:nE.h.FLOAT,value:t.value,loc:this.loc(t)};case nk.STRING:case nk.BLOCK_STRING:return this.parseStringLiteral();case nk.NAME:switch(this._lexer.advance(),t.value){case"true":return{kind:nE.h.BOOLEAN,value:!0,loc:this.loc(t)};case"false":return{kind:nE.h.BOOLEAN,value:!1,loc:this.loc(t)};case"null":return{kind:nE.h.NULL,loc:this.loc(t)};default:return{kind:nE.h.ENUM,value:t.value,loc:this.loc(t)}}case nk.DOLLAR:if(!e)return this.parseVariable()}throw this.unexpected()},t.parseStringLiteral=function(){var e=this._lexer.token;return this._lexer.advance(),{kind:nE.h.STRING,value:e.value,block:e.kind===nk.BLOCK_STRING,loc:this.loc(e)}},t.parseList=function(e){var t=this,n=this._lexer.token,r=function(){return t.parseValueLiteral(e)};return{kind:nE.h.LIST,values:this.any(nk.BRACKET_L,r,nk.BRACKET_R),loc:this.loc(n)}},t.parseObject=function(e){var t=this,n=this._lexer.token,r=function(){return t.parseObjectField(e)};return{kind:nE.h.OBJECT,fields:this.any(nk.BRACE_L,r,nk.BRACE_R),loc:this.loc(n)}},t.parseObjectField=function(e){var t=this._lexer.token,n=this.parseName();return this.expectToken(nk.COLON),{kind:nE.h.OBJECT_FIELD,name:n,value:this.parseValueLiteral(e),loc:this.loc(t)}},t.parseDirectives=function(e){for(var t=[];this.peek(nk.AT);)t.push(this.parseDirective(e));return t},t.parseDirective=function(e){var t=this._lexer.token;return this.expectToken(nk.AT),{kind:nE.h.DIRECTIVE,name:this.parseName(),arguments:this.parseArguments(e),loc:this.loc(t)}},t.parseTypeReference=function(){var e,t=this._lexer.token;return(this.expectOptionalToken(nk.BRACKET_L)?(e=this.parseTypeReference(),this.expectToken(nk.BRACKET_R),e={kind:nE.h.LIST_TYPE,type:e,loc:this.loc(t)}):e=this.parseNamedType(),this.expectOptionalToken(nk.BANG))?{kind:nE.h.NON_NULL_TYPE,type:e,loc:this.loc(t)}:e},t.parseNamedType=function(){var e=this._lexer.token;return{kind:nE.h.NAMED_TYPE,name:this.parseName(),loc:this.loc(e)}},t.parseTypeSystemDefinition=function(){var e=this.peekDescription()?this._lexer.lookahead():this._lexer.token;if(e.kind===nk.NAME)switch(e.value){case"schema":return this.parseSchemaDefinition();case"scalar":return this.parseScalarTypeDefinition();case"type":return this.parseObjectTypeDefinition();case"interface":return this.parseInterfaceTypeDefinition();case"union":return this.parseUnionTypeDefinition();case"enum":return this.parseEnumTypeDefinition();case"input":return this.parseInputObjectTypeDefinition();case"directive":return this.parseDirectiveDefinition()}throw this.unexpected(e)},t.peekDescription=function(){return this.peek(nk.STRING)||this.peek(nk.BLOCK_STRING)},t.parseDescription=function(){if(this.peekDescription())return this.parseStringLiteral()},t.parseSchemaDefinition=function(){var e=this._lexer.token,t=this.parseDescription();this.expectKeyword("schema");var n=this.parseDirectives(!0),r=this.many(nk.BRACE_L,this.parseOperationTypeDefinition,nk.BRACE_R);return{kind:nE.h.SCHEMA_DEFINITION,description:t,directives:n,operationTypes:r,loc:this.loc(e)}},t.parseOperationTypeDefinition=function(){var e=this._lexer.token,t=this.parseOperationType();this.expectToken(nk.COLON);var n=this.parseNamedType();return{kind:nE.h.OPERATION_TYPE_DEFINITION,operation:t,type:n,loc:this.loc(e)}},t.parseScalarTypeDefinition=function(){var e=this._lexer.token,t=this.parseDescription();this.expectKeyword("scalar");var n=this.parseName(),r=this.parseDirectives(!0);return{kind:nE.h.SCALAR_TYPE_DEFINITION,description:t,name:n,directives:r,loc:this.loc(e)}},t.parseObjectTypeDefinition=function(){var e=this._lexer.token,t=this.parseDescription();this.expectKeyword("type");var n=this.parseName(),r=this.parseImplementsInterfaces(),i=this.parseDirectives(!0),a=this.parseFieldsDefinition();return{kind:nE.h.OBJECT_TYPE_DEFINITION,description:t,name:n,interfaces:r,directives:i,fields:a,loc:this.loc(e)}},t.parseImplementsInterfaces=function(){var e;if(!this.expectOptionalKeyword("implements"))return[];if((null===(e=this._options)||void 0===e?void 0:e.allowLegacySDLImplementsInterfaces)===!0){var t=[];this.expectOptionalToken(nk.AMP);do t.push(this.parseNamedType());while(this.expectOptionalToken(nk.AMP)||this.peek(nk.NAME))return t}return this.delimitedMany(nk.AMP,this.parseNamedType)},t.parseFieldsDefinition=function(){var e;return(null===(e=this._options)||void 0===e?void 0:e.allowLegacySDLEmptyFields)===!0&&this.peek(nk.BRACE_L)&&this._lexer.lookahead().kind===nk.BRACE_R?(this._lexer.advance(),this._lexer.advance(),[]):this.optionalMany(nk.BRACE_L,this.parseFieldDefinition,nk.BRACE_R)},t.parseFieldDefinition=function(){var e=this._lexer.token,t=this.parseDescription(),n=this.parseName(),r=this.parseArgumentDefs();this.expectToken(nk.COLON);var i=this.parseTypeReference(),a=this.parseDirectives(!0);return{kind:nE.h.FIELD_DEFINITION,description:t,name:n,arguments:r,type:i,directives:a,loc:this.loc(e)}},t.parseArgumentDefs=function(){return this.optionalMany(nk.PAREN_L,this.parseInputValueDef,nk.PAREN_R)},t.parseInputValueDef=function(){var e,t=this._lexer.token,n=this.parseDescription(),r=this.parseName();this.expectToken(nk.COLON);var i=this.parseTypeReference();this.expectOptionalToken(nk.EQUALS)&&(e=this.parseValueLiteral(!0));var a=this.parseDirectives(!0);return{kind:nE.h.INPUT_VALUE_DEFINITION,description:n,name:r,type:i,defaultValue:e,directives:a,loc:this.loc(t)}},t.parseInterfaceTypeDefinition=function(){var e=this._lexer.token,t=this.parseDescription();this.expectKeyword("interface");var n=this.parseName(),r=this.parseImplementsInterfaces(),i=this.parseDirectives(!0),a=this.parseFieldsDefinition();return{kind:nE.h.INTERFACE_TYPE_DEFINITION,description:t,name:n,interfaces:r,directives:i,fields:a,loc:this.loc(e)}},t.parseUnionTypeDefinition=function(){var e=this._lexer.token,t=this.parseDescription();this.expectKeyword("union");var n=this.parseName(),r=this.parseDirectives(!0),i=this.parseUnionMemberTypes();return{kind:nE.h.UNION_TYPE_DEFINITION,description:t,name:n,directives:r,types:i,loc:this.loc(e)}},t.parseUnionMemberTypes=function(){return this.expectOptionalToken(nk.EQUALS)?this.delimitedMany(nk.PIPE,this.parseNamedType):[]},t.parseEnumTypeDefinition=function(){var e=this._lexer.token,t=this.parseDescription();this.expectKeyword("enum");var n=this.parseName(),r=this.parseDirectives(!0),i=this.parseEnumValuesDefinition();return{kind:nE.h.ENUM_TYPE_DEFINITION,description:t,name:n,directives:r,values:i,loc:this.loc(e)}},t.parseEnumValuesDefinition=function(){return this.optionalMany(nk.BRACE_L,this.parseEnumValueDefinition,nk.BRACE_R)},t.parseEnumValueDefinition=function(){var e=this._lexer.token,t=this.parseDescription(),n=this.parseName(),r=this.parseDirectives(!0);return{kind:nE.h.ENUM_VALUE_DEFINITION,description:t,name:n,directives:r,loc:this.loc(e)}},t.parseInputObjectTypeDefinition=function(){var e=this._lexer.token,t=this.parseDescription();this.expectKeyword("input");var n=this.parseName(),r=this.parseDirectives(!0),i=this.parseInputFieldsDefinition();return{kind:nE.h.INPUT_OBJECT_TYPE_DEFINITION,description:t,name:n,directives:r,fields:i,loc:this.loc(e)}},t.parseInputFieldsDefinition=function(){return this.optionalMany(nk.BRACE_L,this.parseInputValueDef,nk.BRACE_R)},t.parseTypeSystemExtension=function(){var e=this._lexer.lookahead();if(e.kind===nk.NAME)switch(e.value){case"schema":return this.parseSchemaExtension();case"scalar":return this.parseScalarTypeExtension();case"type":return this.parseObjectTypeExtension();case"interface":return this.parseInterfaceTypeExtension();case"union":return this.parseUnionTypeExtension();case"enum":return this.parseEnumTypeExtension();case"input":return this.parseInputObjectTypeExtension()}throw this.unexpected(e)},t.parseSchemaExtension=function(){var e=this._lexer.token;this.expectKeyword("extend"),this.expectKeyword("schema");var t=this.parseDirectives(!0),n=this.optionalMany(nk.BRACE_L,this.parseOperationTypeDefinition,nk.BRACE_R);if(0===t.length&&0===n.length)throw this.unexpected();return{kind:nE.h.SCHEMA_EXTENSION,directives:t,operationTypes:n,loc:this.loc(e)}},t.parseScalarTypeExtension=function(){var e=this._lexer.token;this.expectKeyword("extend"),this.expectKeyword("scalar");var t=this.parseName(),n=this.parseDirectives(!0);if(0===n.length)throw this.unexpected();return{kind:nE.h.SCALAR_TYPE_EXTENSION,name:t,directives:n,loc:this.loc(e)}},t.parseObjectTypeExtension=function(){var e=this._lexer.token;this.expectKeyword("extend"),this.expectKeyword("type");var t=this.parseName(),n=this.parseImplementsInterfaces(),r=this.parseDirectives(!0),i=this.parseFieldsDefinition();if(0===n.length&&0===r.length&&0===i.length)throw this.unexpected();return{kind:nE.h.OBJECT_TYPE_EXTENSION,name:t,interfaces:n,directives:r,fields:i,loc:this.loc(e)}},t.parseInterfaceTypeExtension=function(){var e=this._lexer.token;this.expectKeyword("extend"),this.expectKeyword("interface");var t=this.parseName(),n=this.parseImplementsInterfaces(),r=this.parseDirectives(!0),i=this.parseFieldsDefinition();if(0===n.length&&0===r.length&&0===i.length)throw this.unexpected();return{kind:nE.h.INTERFACE_TYPE_EXTENSION,name:t,interfaces:n,directives:r,fields:i,loc:this.loc(e)}},t.parseUnionTypeExtension=function(){var e=this._lexer.token;this.expectKeyword("extend"),this.expectKeyword("union");var t=this.parseName(),n=this.parseDirectives(!0),r=this.parseUnionMemberTypes();if(0===n.length&&0===r.length)throw this.unexpected();return{kind:nE.h.UNION_TYPE_EXTENSION,name:t,directives:n,types:r,loc:this.loc(e)}},t.parseEnumTypeExtension=function(){var e=this._lexer.token;this.expectKeyword("extend"),this.expectKeyword("enum");var t=this.parseName(),n=this.parseDirectives(!0),r=this.parseEnumValuesDefinition();if(0===n.length&&0===r.length)throw this.unexpected();return{kind:nE.h.ENUM_TYPE_EXTENSION,name:t,directives:n,values:r,loc:this.loc(e)}},t.parseInputObjectTypeExtension=function(){var e=this._lexer.token;this.expectKeyword("extend"),this.expectKeyword("input");var t=this.parseName(),n=this.parseDirectives(!0),r=this.parseInputFieldsDefinition();if(0===n.length&&0===r.length)throw this.unexpected();return{kind:nE.h.INPUT_OBJECT_TYPE_EXTENSION,name:t,directives:n,fields:r,loc:this.loc(e)}},t.parseDirectiveDefinition=function(){var e=this._lexer.token,t=this.parseDescription();this.expectKeyword("directive"),this.expectToken(nk.AT);var n=this.parseName(),r=this.parseArgumentDefs(),i=this.expectOptionalKeyword("repeatable");this.expectKeyword("on");var a=this.parseDirectiveLocations();return{kind:nE.h.DIRECTIVE_DEFINITION,description:t,name:n,arguments:r,repeatable:i,locations:a,loc:this.loc(e)}},t.parseDirectiveLocations=function(){return this.delimitedMany(nk.PIPE,this.parseDirectiveLocation)},t.parseDirectiveLocation=function(){var e=this._lexer.token,t=this.parseName();if(void 0!==nT[t.value])return t;throw this.unexpected(e)},t.loc=function(e){var t;if((null===(t=this._options)||void 0===t?void 0:t.noLocation)!==!0)return new nS.Ye(e,this._lexer.lastToken,this._lexer.source)},t.peek=function(e){return this._lexer.token.kind===e},t.expectToken=function(e){var t=this._lexer.token;if(t.kind===e)return this._lexer.advance(),t;throw n_(this._lexer.source,t.start,"Expected ".concat(nG(e),", found ").concat(nz(t),"."))},t.expectOptionalToken=function(e){var t=this._lexer.token;if(t.kind===e)return this._lexer.advance(),t},t.expectKeyword=function(e){var t=this._lexer.token;if(t.kind===nk.NAME&&t.value===e)this._lexer.advance();else throw n_(this._lexer.source,t.start,'Expected "'.concat(e,'", found ').concat(nz(t),"."))},t.expectOptionalKeyword=function(e){var t=this._lexer.token;return t.kind===nk.NAME&&t.value===e&&(this._lexer.advance(),!0)},t.unexpected=function(e){var t=null!=e?e:this._lexer.token;return n_(this._lexer.source,t.start,"Unexpected ".concat(nz(t),"."))},t.any=function(e,t,n){this.expectToken(e);for(var r=[];!this.expectOptionalToken(n);)r.push(t.call(this));return r},t.optionalMany=function(e,t,n){if(this.expectOptionalToken(e)){var r=[];do r.push(t.call(this));while(!this.expectOptionalToken(n))return r}return[]},t.many=function(e,t,n){this.expectToken(e);var r=[];do r.push(t.call(this));while(!this.expectOptionalToken(n))return r},t.delimitedMany=function(e,t){this.expectOptionalToken(e);var n=[];do n.push(t.call(this));while(this.expectOptionalToken(e))return n},e}();function nz(e){var t=e.value;return nG(e.kind)+(null!=t?' "'.concat(t,'"'):"")}function nG(e){return nA(e)?'"'.concat(e,'"'):e}var nW=new Map,nK=new Map,nV=!0,nq=!1;function nZ(e){return e.replace(/[\s,]+/g," ").trim()}function nX(e){return nZ(e.source.body.substring(e.start,e.end))}function nJ(e){var t=new Set,n=[];return e.definitions.forEach(function(e){if("FragmentDefinition"===e.kind){var r=e.name.value,i=nX(e.loc),a=nK.get(r);a&&!a.has(i)?nV&&console.warn("Warning: fragment with name "+r+" already exists.\ngraphql-tag enforces all fragment names across your application to be unique; read more about\nthis in the docs: http://dev.apollodata.com/core/fragments.html#unique-names"):a||nK.set(r,a=new Set),a.add(i),t.has(i)||(t.add(i),n.push(e))}else n.push(e)}),(0,t0.pi)((0,t0.pi)({},e),{definitions:n})}function nQ(e){var t=new Set(e.definitions);t.forEach(function(e){e.loc&&delete e.loc,Object.keys(e).forEach(function(n){var r=e[n];r&&"object"==typeof r&&t.add(r)})});var n=e.loc;return n&&(delete n.startToken,delete n.endToken),e}function n1(e){var t=nZ(e);if(!nW.has(t)){var n=nH(e,{experimentalFragmentVariables:nq,allowLegacyFragmentVariables:nq});if(!n||"Document"!==n.kind)throw Error("Not a valid GraphQL document.");nW.set(t,nQ(nJ(n)))}return nW.get(t)}function n0(e){for(var t=[],n=1;n, or pass an ApolloClient instance in via options.'):(0,n9.kG)(!!n,32),n}var rp=n(10542),rb=n(53712),rm=n(21436),rg=Object.prototype.hasOwnProperty;function rv(e,t){return void 0===t&&(t=Object.create(null)),ry(rh(t.client),e).useQuery(t)}function ry(e,t){var n=(0,l.useRef)();n.current&&e===n.current.client&&t===n.current.query||(n.current=new rw(e,t,n.current));var r=n.current,i=(0,l.useState)(0),a=(i[0],i[1]);return r.forceUpdate=function(){a(function(e){return e+1})},r}var rw=function(){function e(e,t,n){this.client=e,this.query=t,this.ssrDisabledResult=(0,rp.J)({loading:!0,data:void 0,error:void 0,networkStatus:ru.I.loading}),this.skipStandbyResult=(0,rp.J)({loading:!1,data:void 0,error:void 0,networkStatus:ru.I.ready}),this.toQueryResultCache=new(n7.mr?WeakMap:Map),rd(t,r.Query);var i=n&&n.result,a=i&&i.data;a&&(this.previousData=a)}return e.prototype.forceUpdate=function(){__DEV__&&n9.kG.warn("Calling default no-op implementation of InternalState#forceUpdate")},e.prototype.executeQuery=function(e){var t,n=this;e.query&&Object.assign(this,{query:e.query}),this.watchQueryOptions=this.createWatchQueryOptions(this.queryHookOptions=e);var r=this.observable.reobserveAsConcast(this.getObsQueryOptions());return this.previousData=(null===(t=this.result)||void 0===t?void 0:t.data)||this.previousData,this.result=void 0,this.forceUpdate(),new Promise(function(e){var t;r.subscribe({next:function(e){t=e},error:function(){e(n.toQueryResult(n.observable.getCurrentResult()))},complete:function(){e(n.toQueryResult(t))}})})},e.prototype.useQuery=function(e){var t=this;this.renderPromises=(0,l.useContext)((0,ro.K)()).renderPromises,this.useOptions(e);var n=this.useObservableQuery(),r=rt((0,l.useCallback)(function(){if(t.renderPromises)return function(){};var e=function(){var e=t.result,r=n.getCurrentResult();!(e&&e.loading===r.loading&&e.networkStatus===r.networkStatus&&(0,ri.D)(e.data,r.data))&&t.setResult(r)},r=function(a){var o=n.last;i.unsubscribe();try{n.resetLastResults(),i=n.subscribe(e,r)}finally{n.last=o}if(!rg.call(a,"graphQLErrors"))throw a;var s=t.result;(!s||s&&s.loading||!(0,ri.D)(a,s.error))&&t.setResult({data:s&&s.data,error:a,loading:!1,networkStatus:ru.I.error})},i=n.subscribe(e,r);return function(){return setTimeout(function(){return i.unsubscribe()})}},[n,this.renderPromises,this.client.disableNetworkFetches,]),function(){return t.getCurrentResult()},function(){return t.getCurrentResult()});return this.unsafeHandlePartialRefetch(r),this.toQueryResult(r)},e.prototype.useOptions=function(t){var n,r=this.createWatchQueryOptions(this.queryHookOptions=t),i=this.watchQueryOptions;!(0,ri.D)(r,i)&&(this.watchQueryOptions=r,i&&this.observable&&(this.observable.reobserve(this.getObsQueryOptions()),this.previousData=(null===(n=this.result)||void 0===n?void 0:n.data)||this.previousData,this.result=void 0)),this.onCompleted=t.onCompleted||e.prototype.onCompleted,this.onError=t.onError||e.prototype.onError,(this.renderPromises||this.client.disableNetworkFetches)&&!1===this.queryHookOptions.ssr&&!this.queryHookOptions.skip?this.result=this.ssrDisabledResult:this.queryHookOptions.skip||"standby"===this.watchQueryOptions.fetchPolicy?this.result=this.skipStandbyResult:(this.result===this.ssrDisabledResult||this.result===this.skipStandbyResult)&&(this.result=void 0)},e.prototype.getObsQueryOptions=function(){var e=[],t=this.client.defaultOptions.watchQuery;return t&&e.push(t),this.queryHookOptions.defaultOptions&&e.push(this.queryHookOptions.defaultOptions),e.push((0,rb.o)(this.observable&&this.observable.options,this.watchQueryOptions)),e.reduce(ra.J)},e.prototype.createWatchQueryOptions=function(e){void 0===e&&(e={});var t,n=e.skip,r=Object.assign((e.ssr,e.onCompleted,e.onError,e.defaultOptions,(0,t0._T)(e,["skip","ssr","onCompleted","onError","defaultOptions"])),{query:this.query});if(this.renderPromises&&("network-only"===r.fetchPolicy||"cache-and-network"===r.fetchPolicy)&&(r.fetchPolicy="cache-first"),r.variables||(r.variables={}),n){var i=r.fetchPolicy,a=void 0===i?this.getDefaultFetchPolicy():i,o=r.initialFetchPolicy;Object.assign(r,{initialFetchPolicy:void 0===o?a:o,fetchPolicy:"standby"})}else r.fetchPolicy||(r.fetchPolicy=(null===(t=this.observable)||void 0===t?void 0:t.options.initialFetchPolicy)||this.getDefaultFetchPolicy());return r},e.prototype.getDefaultFetchPolicy=function(){var e,t;return(null===(e=this.queryHookOptions.defaultOptions)||void 0===e?void 0:e.fetchPolicy)||(null===(t=this.client.defaultOptions.watchQuery)||void 0===t?void 0:t.fetchPolicy)||"cache-first"},e.prototype.onCompleted=function(e){},e.prototype.onError=function(e){},e.prototype.useObservableQuery=function(){var e=this.observable=this.renderPromises&&this.renderPromises.getSSRObservable(this.watchQueryOptions)||this.observable||this.client.watchQuery(this.getObsQueryOptions());this.obsQueryFields=(0,l.useMemo)(function(){return{refetch:e.refetch.bind(e),reobserve:e.reobserve.bind(e),fetchMore:e.fetchMore.bind(e),updateQuery:e.updateQuery.bind(e),startPolling:e.startPolling.bind(e),stopPolling:e.stopPolling.bind(e),subscribeToMore:e.subscribeToMore.bind(e)}},[e]);var t=!(!1===this.queryHookOptions.ssr||this.queryHookOptions.skip);return this.renderPromises&&t&&(this.renderPromises.registerSSRObservable(e),e.getCurrentResult().loading&&this.renderPromises.addObservableQueryPromise(e)),e},e.prototype.setResult=function(e){var t=this.result;t&&t.data&&(this.previousData=t.data),this.result=e,this.forceUpdate(),this.handleErrorOrCompleted(e)},e.prototype.handleErrorOrCompleted=function(e){var t=this;if(!e.loading){var n=this.toApolloError(e);Promise.resolve().then(function(){n?t.onError(n):e.data&&t.onCompleted(e.data)}).catch(function(e){__DEV__&&n9.kG.warn(e)})}},e.prototype.toApolloError=function(e){return(0,rm.O)(e.errors)?new rs.cA({graphQLErrors:e.errors}):e.error},e.prototype.getCurrentResult=function(){return this.result||this.handleErrorOrCompleted(this.result=this.observable.getCurrentResult()),this.result},e.prototype.toQueryResult=function(e){var t=this.toQueryResultCache.get(e);if(t)return t;var n=e.data,r=(e.partial,(0,t0._T)(e,["data","partial"]));return this.toQueryResultCache.set(e,t=(0,t0.pi)((0,t0.pi)((0,t0.pi)({data:n},r),this.obsQueryFields),{client:this.client,observable:this.observable,variables:this.observable.variables,called:!this.queryHookOptions.skip,previousData:this.previousData})),!t.error&&(0,rm.O)(e.errors)&&(t.error=new rs.cA({graphQLErrors:e.errors})),t},e.prototype.unsafeHandlePartialRefetch=function(e){e.partial&&this.queryHookOptions.partialRefetch&&!e.loading&&(!e.data||0===Object.keys(e.data).length)&&"cache-only"!==this.observable.options.fetchPolicy&&(Object.assign(e,{loading:!0,networkStatus:ru.I.refetch}),this.observable.refetch())},e}();function r_(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);ne.length)&&(t=e.length);for(var n=0,r=Array(t);ne.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&void 0!==arguments[0]?arguments[0]:{};return rv(iH,e)},iz=function(){var e=ij(),t=parseInt(e.get("page")||"1",10),n=parseInt(e.get("per")||"50",10),r=i$({variables:{offset:(t-1)*n,limit:n},fetchPolicy:"network-only"}),i=r.data,a=r.loading,o=r.error;return a?l.createElement(iR,null):o?l.createElement(iD,{error:o}):i?l.createElement(iI,{chains:i.chains.results,page:t,pageSize:n,total:i.chains.metadata.total}):null},iG=n(67932),iW=n(8126),iK="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e};function iV(e){if(iq())return Intl.DateTimeFormat.supportedLocalesOf(e)[0]}function iq(){return("undefined"==typeof Intl?"undefined":iK(Intl))==="object"&&"function"==typeof Intl.DateTimeFormat}var iZ="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},iX=function(){function e(e,t){for(var n=0;n=i.length)break;s=i[o++]}else{if((o=i.next()).done)break;s=o.value}var s,u=s;if((void 0===e?"undefined":iZ(e))!=="object")return;e=e[u]}return e}},{key:"put",value:function(){for(var e=arguments.length,t=Array(e),n=0;n=o.length)break;c=o[u++]}else{if((u=o.next()).done)break;c=u.value}var c,l=c;"object"!==iZ(a[l])&&(a[l]={}),a=a[l]}return a[i]=r}}]),e}();let i1=iQ;var i0=new i1;function i2(e,t){if(!iq())return function(e){return e.toString()};var n=i4(e),r=JSON.stringify(t),i=i0.get(String(n),r)||i0.put(String(n),r,new Intl.DateTimeFormat(n,t));return function(e){return i.format(e)}}var i3={};function i4(e){var t=e.toString();return i3[t]?i3[t]:i3[t]=iV(e)}var i6="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e};function i5(e){return i8(e)?e:new Date(e)}function i8(e){return e instanceof Date||i9(e)}function i9(e){return(void 0===e?"undefined":i6(e))==="object"&&"function"==typeof e.getTime}var i7=n(54087),ae=n.n(i7);function at(e,t){if(0===e.length)return 0;for(var n=0,r=e.length-1,i=void 0;n<=r;){var a=t(e[i=Math.floor((r+n)/2)]);if(0===a)return i;if(a<0){if((n=i+1)>r)return n}else if((r=i-1)=t.nextUpdateTime)aa(t,this.instances);else break}},scheduleNextTick:function(){var e=this;this.scheduledTick=ae()(function(){e.tick(),e.scheduleNextTick()})},start:function(){this.scheduleNextTick()},stop:function(){ae().cancel(this.scheduledTick)}};function ai(e){var t=an(e.getNextValue(),2),n=t[0],r=t[1];e.setValue(n),e.nextUpdateTime=r}function aa(e,t){ai(e),as(t,e),ao(t,e)}function ao(e,t){var n=au(e,t);e.splice(n,0,t)}function as(e,t){var n=e.indexOf(t);e.splice(n,1)}function au(e,t){var n=t.nextUpdateTime;return at(e,function(e){return e.nextUpdateTime===n?0:e.nextUpdateTime>n?1:-1})}var ac=(0,ec.oneOfType)([(0,ec.shape)({minTime:ec.number,formatAs:ec.string.isRequired}),(0,ec.shape)({test:ec.func,formatAs:ec.string.isRequired}),(0,ec.shape)({minTime:ec.number,format:ec.func.isRequired}),(0,ec.shape)({test:ec.func,format:ec.func.isRequired})]),al=(0,ec.oneOfType)([ec.string,(0,ec.shape)({steps:(0,ec.arrayOf)(ac).isRequired,labels:(0,ec.oneOfType)([ec.string,(0,ec.arrayOf)(ec.string)]).isRequired,round:ec.string})]),af=Object.assign||function(e){for(var t=1;t=0)&&Object.prototype.hasOwnProperty.call(e,r)&&(n[r]=e[r]);return n}function ap(e){var t=e.date,n=e.future,r=e.timeStyle,i=e.round,a=e.minTimeLeft,o=e.tooltip,s=e.component,u=e.container,c=e.wrapperComponent,f=e.wrapperProps,d=e.locale,h=e.locales,p=e.formatVerboseDate,b=e.verboseDateFormat,m=e.updateInterval,g=e.tick,v=ah(e,["date","future","timeStyle","round","minTimeLeft","tooltip","component","container","wrapperComponent","wrapperProps","locale","locales","formatVerboseDate","verboseDateFormat","updateInterval","tick"]),y=(0,l.useMemo)(function(){return d&&(h=[d]),h.concat(iW.Z.getDefaultLocale())},[d,h]),w=(0,l.useMemo)(function(){return new iW.Z(y)},[y]);t=(0,l.useMemo)(function(){return i5(t)},[t]);var _=(0,l.useCallback)(function(){var e=Date.now(),o=void 0;if(n&&e>=t.getTime()&&(e=t.getTime(),o=!0),void 0!==a){var s=t.getTime()-1e3*a;e>s&&(e=s,o=!0)}var u=w.format(t,r,{getTimeToNextUpdate:!0,now:e,future:n,round:i}),c=ad(u,2),l=c[0],f=c[1];return f=o?ag:m||f||6e4,[l,e+f]},[t,n,r,m,i,a,w]),E=(0,l.useRef)();E.current=_;var S=(0,l.useMemo)(_,[]),k=ad(S,2),x=k[0],T=k[1],M=(0,l.useState)(x),O=ad(M,2),A=O[0],L=O[1],C=ad((0,l.useState)(),2),I=C[0],D=C[1],N=(0,l.useRef)();(0,l.useEffect)(function(){if(g)return N.current=ar.add({getNextValue:function(){return E.current()},setValue:L,nextUpdateTime:T}),function(){return N.current.stop()}},[g]),(0,l.useEffect)(function(){if(N.current)N.current.forceUpdate();else{var e=_(),t=ad(e,1)[0];L(t)}},[_]),(0,l.useEffect)(function(){D(!0)},[]);var P=(0,l.useMemo)(function(){if("undefined"!=typeof window)return i2(y,b)},[y,b]),R=(0,l.useMemo)(function(){if("undefined"!=typeof window)return p?p(t):P(t)},[t,p,P]),j=l.createElement(s,af({date:t,verboseDate:I?R:void 0,tooltip:o},v),A),F=c||u;return F?l.createElement(F,af({},f,{verboseDate:I?R:void 0}),j):j}ap.propTypes={date:el().oneOfType([el().instanceOf(Date),el().number]).isRequired,locale:el().string,locales:el().arrayOf(el().string),future:el().bool,timeStyle:al,round:el().string,minTimeLeft:el().number,component:el().elementType.isRequired,tooltip:el().bool.isRequired,formatVerboseDate:el().func,verboseDateFormat:el().object,updateInterval:el().oneOfType([el().number,el().arrayOf(el().shape({threshold:el().number,interval:el().number.isRequired}))]),tick:el().bool,wrapperComponent:el().func,wrapperProps:el().object},ap.defaultProps={locales:[],component:av,tooltip:!0,verboseDateFormat:{weekday:"long",day:"numeric",month:"long",year:"numeric",hour:"numeric",minute:"2-digit",second:"2-digit"},tick:!0},ap=l.memo(ap);let ab=ap;var am,ag=31536e9;function av(e){var t=e.date,n=e.verboseDate,r=e.tooltip,i=e.children,a=ah(e,["date","verboseDate","tooltip","children"]),o=(0,l.useMemo)(function(){return t.toISOString()},[t]);return l.createElement("time",af({},a,{dateTime:o,title:r?n:void 0}),i)}av.propTypes={date:el().instanceOf(Date).isRequired,verboseDate:el().string,tooltip:el().bool.isRequired,children:el().string.isRequired};var ay=n(30381),aw=n.n(ay),a_=n(31657);function aE(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function aS(e){for(var t=1;te.length)&&(t=e.length);for(var n=0,r=Array(t);ne.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]0?new rs.cA({graphQLErrors:i}):void 0;if(u===s.current.mutationId&&!c.ignoreResults){var f={called:!0,loading:!1,data:r,error:l,client:a};s.current.isMounted&&!(0,ri.D)(s.current.result,f)&&o(s.current.result=f)}var d=e.onCompleted||(null===(n=s.current.options)||void 0===n?void 0:n.onCompleted);return null==d||d(t.data,c),t}).catch(function(t){if(u===s.current.mutationId&&s.current.isMounted){var n,r={loading:!1,error:t,data:void 0,called:!0,client:a};(0,ri.D)(s.current.result,r)||o(s.current.result=r)}var i=e.onError||(null===(n=s.current.options)||void 0===n?void 0:n.onError);if(i)return i(t,c),{data:void 0,errors:t};throw t})},[]),c=(0,l.useCallback)(function(){s.current.isMounted&&o({called:!1,loading:!1,client:n})},[]);return(0,l.useEffect)(function(){return s.current.isMounted=!0,function(){s.current.isMounted=!1}},[]),[u,(0,t0.pi)({reset:c},a)]}var os=n(59067),ou=n(28428),oc=n(11186),ol=n(78513);function of(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}var od=function(e){return(0,b.createStyles)({paper:{display:"flex",margin:"".concat(2.5*e.spacing.unit,"px 0"),padding:"".concat(3*e.spacing.unit,"px ").concat(3.5*e.spacing.unit,"px")},content:{flex:1,width:"100%"},actions:of({marginTop:-(1.5*e.spacing.unit),marginLeft:-(4*e.spacing.unit)},e.breakpoints.up("sm"),{marginLeft:0,marginRight:-(1.5*e.spacing.unit)}),itemBlock:{border:"1px solid rgba(224, 224, 224, 1)",borderRadius:e.shape.borderRadius,padding:2*e.spacing.unit,marginTop:e.spacing.unit},itemBlockText:{overflowWrap:"anywhere"}})},oh=(0,b.withStyles)(od)(function(e){var t=e.actions,n=e.children,r=e.classes;return l.createElement(ii.default,{className:r.paper},l.createElement("div",{className:r.content},n),t&&l.createElement("div",{className:r.actions},t))}),op=function(e){var t=e.title;return l.createElement(x.default,{variant:"subtitle2",gutterBottom:!0},t)},ob=function(e){var t=e.children,n=e.value;return l.createElement(x.default,{variant:"body1",noWrap:!0},t||n)},om=(0,b.withStyles)(od)(function(e){var t=e.children,n=e.classes,r=e.value;return l.createElement("div",{className:n.itemBlock},l.createElement(x.default,{variant:"body1",className:n.itemBlockText},t||r))});function og(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);ne.length)&&(t=e.length);for(var n=0,r=Array(t);ne.length)&&(t=e.length);for(var n=0,r=Array(t);ne.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]-1}let sq=sV;function sZ(e,t){var n=this.__data__,r=sH(n,e);return r<0?(++this.size,n.push([e,t])):n[r][1]=t,this}let sX=sZ;function sJ(e){var t=-1,n=null==e?0:e.length;for(this.clear();++t-1&&e%1==0&&e-1&&e%1==0&&e<=cC}let cD=cI;var cN="[object Arguments]",cP="[object Array]",cR="[object Boolean]",cj="[object Date]",cF="[object Error]",cY="[object Function]",cB="[object Map]",cU="[object Number]",cH="[object Object]",c$="[object RegExp]",cz="[object Set]",cG="[object String]",cW="[object WeakMap]",cK="[object ArrayBuffer]",cV="[object DataView]",cq="[object Float64Array]",cZ="[object Int8Array]",cX="[object Int16Array]",cJ="[object Int32Array]",cQ="[object Uint8Array]",c1="[object Uint8ClampedArray]",c0="[object Uint16Array]",c2="[object Uint32Array]",c3={};function c4(e){return eD(e)&&cD(e.length)&&!!c3[eC(e)]}c3["[object Float32Array]"]=c3[cq]=c3[cZ]=c3[cX]=c3[cJ]=c3[cQ]=c3[c1]=c3[c0]=c3[c2]=!0,c3[cN]=c3[cP]=c3[cK]=c3[cR]=c3[cV]=c3[cj]=c3[cF]=c3[cY]=c3[cB]=c3[cU]=c3[cH]=c3[c$]=c3[cz]=c3[cG]=c3[cW]=!1;let c6=c4;function c5(e){return function(t){return e(t)}}let c8=c5;var c9=n(79730),c7=c9.Z&&c9.Z.isTypedArray,le=c7?c8(c7):c6;let lt=le;var ln=Object.prototype.hasOwnProperty;function lr(e,t){var n=cx(e),r=!n&&cS(e),i=!n&&!r&&(0,cT.Z)(e),a=!n&&!r&&!i&<(e),o=n||r||i||a,s=o?cb(e.length,String):[],u=s.length;for(var c in e)(t||ln.call(e,c))&&!(o&&("length"==c||i&&("offset"==c||"parent"==c)||a&&("buffer"==c||"byteLength"==c||"byteOffset"==c)||cL(c,u)))&&s.push(c);return s}let li=lr;var la=Object.prototype;function lo(e){var t=e&&e.constructor;return e===("function"==typeof t&&t.prototype||la)}let ls=lo;var lu=sT(Object.keys,Object);let lc=lu;var ll=Object.prototype.hasOwnProperty;function lf(e){if(!ls(e))return lc(e);var t=[];for(var n in Object(e))ll.call(e,n)&&"constructor"!=n&&t.push(n);return t}let ld=lf;function lh(e){return null!=e&&cD(e.length)&&!ur(e)}let lp=lh;function lb(e){return lp(e)?li(e):ld(e)}let lm=lb;function lg(e,t){return e&&ch(t,lm(t),e)}let lv=lg;function ly(e){var t=[];if(null!=e)for(var n in Object(e))t.push(n);return t}let lw=ly;var l_=Object.prototype.hasOwnProperty;function lE(e){if(!ed(e))return lw(e);var t=ls(e),n=[];for(var r in e)"constructor"==r&&(t||!l_.call(e,r))||n.push(r);return n}let lS=lE;function lk(e){return lp(e)?li(e,!0):lS(e)}let lx=lk;function lT(e,t){return e&&ch(t,lx(t),e)}let lM=lT;var lO=n(42896);function lA(e,t){var n=-1,r=e.length;for(t||(t=Array(r));++n=0||(i[n]=e[n]);return i}function hu(e){if(void 0===e)throw ReferenceError("this hasn't been initialised - super() hasn't been called");return e}var hc=function(e){return Array.isArray(e)&&0===e.length},hl=function(e){return"function"==typeof e},hf=function(e){return null!==e&&"object"==typeof e},hd=function(e){return String(Math.floor(Number(e)))===e},hh=function(e){return"[object String]"===Object.prototype.toString.call(e)},hp=function(e){return 0===l.Children.count(e)},hb=function(e){return hf(e)&&hl(e.then)};function hm(e,t,n,r){void 0===r&&(r=0);for(var i=d8(t);e&&r=0?[]:{}}}return(0===a?e:i)[o[a]]===n?e:(void 0===n?delete i[o[a]]:i[o[a]]=n,0===a&&void 0===n&&delete r[o[a]],r)}function hv(e,t,n,r){void 0===n&&(n=new WeakMap),void 0===r&&(r={});for(var i=0,a=Object.keys(e);i0?t.map(function(t){return x(t,hm(e,t))}):[Promise.resolve("DO_NOT_DELETE_YOU_WILL_BE_FIRED")]).then(function(e){return e.reduce(function(e,n,r){return"DO_NOT_DELETE_YOU_WILL_BE_FIRED"===n||n&&(e=hg(e,t[r],n)),e},{})})},[x]),M=(0,l.useCallback)(function(e){return Promise.all([T(e),h.validationSchema?k(e):{},h.validate?S(e):{}]).then(function(e){var t=e[0],n=e[1],r=e[2];return sk.all([t,n,r],{arrayMerge:hL})})},[h.validate,h.validationSchema,T,S,k]),O=hN(function(e){return void 0===e&&(e=_.values),E({type:"SET_ISVALIDATING",payload:!0}),M(e).then(function(e){return v.current&&(E({type:"SET_ISVALIDATING",payload:!1}),sd()(_.errors,e)||E({type:"SET_ERRORS",payload:e})),e})});(0,l.useEffect)(function(){o&&!0===v.current&&sd()(p.current,h.initialValues)&&O(p.current)},[o,O]);var A=(0,l.useCallback)(function(e){var t=e&&e.values?e.values:p.current,n=e&&e.errors?e.errors:b.current?b.current:h.initialErrors||{},r=e&&e.touched?e.touched:m.current?m.current:h.initialTouched||{},i=e&&e.status?e.status:g.current?g.current:h.initialStatus;p.current=t,b.current=n,m.current=r,g.current=i;var a=function(){E({type:"RESET_FORM",payload:{isSubmitting:!!e&&!!e.isSubmitting,errors:n,touched:r,status:i,values:t,isValidating:!!e&&!!e.isValidating,submitCount:e&&e.submitCount&&"number"==typeof e.submitCount?e.submitCount:0}})};if(h.onReset){var o=h.onReset(_.values,V);hb(o)?o.then(a):a()}else a()},[h.initialErrors,h.initialStatus,h.initialTouched]);(0,l.useEffect)(function(){!0===v.current&&!sd()(p.current,h.initialValues)&&(c&&(p.current=h.initialValues,A()),o&&O(p.current))},[c,h.initialValues,A,o,O]),(0,l.useEffect)(function(){c&&!0===v.current&&!sd()(b.current,h.initialErrors)&&(b.current=h.initialErrors||hS,E({type:"SET_ERRORS",payload:h.initialErrors||hS}))},[c,h.initialErrors]),(0,l.useEffect)(function(){c&&!0===v.current&&!sd()(m.current,h.initialTouched)&&(m.current=h.initialTouched||hk,E({type:"SET_TOUCHED",payload:h.initialTouched||hk}))},[c,h.initialTouched]),(0,l.useEffect)(function(){c&&!0===v.current&&!sd()(g.current,h.initialStatus)&&(g.current=h.initialStatus,E({type:"SET_STATUS",payload:h.initialStatus}))},[c,h.initialStatus,h.initialTouched]);var L=hN(function(e){if(y.current[e]&&hl(y.current[e].validate)){var t=hm(_.values,e),n=y.current[e].validate(t);return hb(n)?(E({type:"SET_ISVALIDATING",payload:!0}),n.then(function(e){return e}).then(function(t){E({type:"SET_FIELD_ERROR",payload:{field:e,value:t}}),E({type:"SET_ISVALIDATING",payload:!1})})):(E({type:"SET_FIELD_ERROR",payload:{field:e,value:n}}),Promise.resolve(n))}return h.validationSchema?(E({type:"SET_ISVALIDATING",payload:!0}),k(_.values,e).then(function(e){return e}).then(function(t){E({type:"SET_FIELD_ERROR",payload:{field:e,value:t[e]}}),E({type:"SET_ISVALIDATING",payload:!1})})):Promise.resolve()}),C=(0,l.useCallback)(function(e,t){var n=t.validate;y.current[e]={validate:n}},[]),I=(0,l.useCallback)(function(e){delete y.current[e]},[]),D=hN(function(e,t){return E({type:"SET_TOUCHED",payload:e}),(void 0===t?i:t)?O(_.values):Promise.resolve()}),N=(0,l.useCallback)(function(e){E({type:"SET_ERRORS",payload:e})},[]),P=hN(function(e,t){var r=hl(e)?e(_.values):e;return E({type:"SET_VALUES",payload:r}),(void 0===t?n:t)?O(r):Promise.resolve()}),R=(0,l.useCallback)(function(e,t){E({type:"SET_FIELD_ERROR",payload:{field:e,value:t}})},[]),j=hN(function(e,t,r){return E({type:"SET_FIELD_VALUE",payload:{field:e,value:t}}),(void 0===r?n:r)?O(hg(_.values,e,t)):Promise.resolve()}),F=(0,l.useCallback)(function(e,t){var n,r=t,i=e;if(!hh(e)){e.persist&&e.persist();var a=e.target?e.target:e.currentTarget,o=a.type,s=a.name,u=a.id,c=a.value,l=a.checked,f=(a.outerHTML,a.options),d=a.multiple;r=t||s||u,i=/number|range/.test(o)?(n=parseFloat(c),isNaN(n)?"":n):/checkbox/.test(o)?hI(hm(_.values,r),l,c):d?hC(f):c}r&&j(r,i)},[j,_.values]),Y=hN(function(e){if(hh(e))return function(t){return F(t,e)};F(e)}),B=hN(function(e,t,n){return void 0===t&&(t=!0),E({type:"SET_FIELD_TOUCHED",payload:{field:e,value:t}}),(void 0===n?i:n)?O(_.values):Promise.resolve()}),U=(0,l.useCallback)(function(e,t){e.persist&&e.persist();var n,r=e.target,i=r.name,a=r.id;r.outerHTML,B(t||i||a,!0)},[B]),H=hN(function(e){if(hh(e))return function(t){return U(t,e)};U(e)}),$=(0,l.useCallback)(function(e){hl(e)?E({type:"SET_FORMIK_STATE",payload:e}):E({type:"SET_FORMIK_STATE",payload:function(){return e}})},[]),z=(0,l.useCallback)(function(e){E({type:"SET_STATUS",payload:e})},[]),G=(0,l.useCallback)(function(e){E({type:"SET_ISSUBMITTING",payload:e})},[]),W=hN(function(){return E({type:"SUBMIT_ATTEMPT"}),O().then(function(e){var t,n=e instanceof Error;if(!n&&0===Object.keys(e).length){try{if(void 0===(t=q()))return}catch(r){throw r}return Promise.resolve(t).then(function(e){return v.current&&E({type:"SUBMIT_SUCCESS"}),e}).catch(function(e){if(v.current)throw E({type:"SUBMIT_FAILURE"}),e})}if(v.current&&(E({type:"SUBMIT_FAILURE"}),n))throw e})}),K=hN(function(e){e&&e.preventDefault&&hl(e.preventDefault)&&e.preventDefault(),e&&e.stopPropagation&&hl(e.stopPropagation)&&e.stopPropagation(),W().catch(function(e){console.warn("Warning: An unhandled error was caught from submitForm()",e)})}),V={resetForm:A,validateForm:O,validateField:L,setErrors:N,setFieldError:R,setFieldTouched:B,setFieldValue:j,setStatus:z,setSubmitting:G,setTouched:D,setValues:P,setFormikState:$,submitForm:W},q=hN(function(){return f(_.values,V)}),Z=hN(function(e){e&&e.preventDefault&&hl(e.preventDefault)&&e.preventDefault(),e&&e.stopPropagation&&hl(e.stopPropagation)&&e.stopPropagation(),A()}),X=(0,l.useCallback)(function(e){return{value:hm(_.values,e),error:hm(_.errors,e),touched:!!hm(_.touched,e),initialValue:hm(p.current,e),initialTouched:!!hm(m.current,e),initialError:hm(b.current,e)}},[_.errors,_.touched,_.values]),J=(0,l.useCallback)(function(e){return{setValue:function(t,n){return j(e,t,n)},setTouched:function(t,n){return B(e,t,n)},setError:function(t){return R(e,t)}}},[j,B,R]),Q=(0,l.useCallback)(function(e){var t=hf(e),n=t?e.name:e,r=hm(_.values,n),i={name:n,value:r,onChange:Y,onBlur:H};if(t){var a=e.type,o=e.value,s=e.as,u=e.multiple;"checkbox"===a?void 0===o?i.checked=!!r:(i.checked=!!(Array.isArray(r)&&~r.indexOf(o)),i.value=o):"radio"===a?(i.checked=r===o,i.value=o):"select"===s&&u&&(i.value=i.value||[],i.multiple=!0)}return i},[H,Y,_.values]),ee=(0,l.useMemo)(function(){return!sd()(p.current,_.values)},[p.current,_.values]),et=(0,l.useMemo)(function(){return void 0!==s?ee?_.errors&&0===Object.keys(_.errors).length:!1!==s&&hl(s)?s(h):s:_.errors&&0===Object.keys(_.errors).length},[s,ee,_.errors,h]);return ha({},_,{initialValues:p.current,initialErrors:b.current,initialTouched:m.current,initialStatus:g.current,handleBlur:H,handleChange:Y,handleReset:Z,handleSubmit:K,resetForm:A,setErrors:N,setFormikState:$,setFieldTouched:B,setFieldValue:j,setFieldError:R,setStatus:z,setSubmitting:G,setTouched:D,setValues:P,submitForm:W,validateForm:O,validateField:L,isValid:et,dirty:ee,unregisterField:I,registerField:C,getFieldProps:Q,getFieldMeta:X,getFieldHelpers:J,validateOnBlur:i,validateOnChange:n,validateOnMount:o})}function hT(e){var t=hx(e),n=e.component,r=e.children,i=e.render,a=e.innerRef;return(0,l.useImperativeHandle)(a,function(){return t}),(0,l.createElement)(hw,{value:t},n?(0,l.createElement)(n,t):i?i(t):r?hl(r)?r(t):hp(r)?null:l.Children.only(r):null)}function hM(e){var t={};if(e.inner){if(0===e.inner.length)return hg(t,e.path,e.message);for(var n=e.inner,r=Array.isArray(n),i=0,n=r?n:n[Symbol.iterator]();;){if(r){if(i>=n.length)break;a=n[i++]}else{if((i=n.next()).done)break;a=i.value}var a,o=a;hm(t,o.path)||(t=hg(t,o.path,o.message))}}return t}function hO(e,t,n,r){void 0===n&&(n=!1),void 0===r&&(r={});var i=hA(e);return t[n?"validateSync":"validate"](i,{abortEarly:!1,context:r})}function hA(e){var t=Array.isArray(e)?[]:{};for(var n in e)if(Object.prototype.hasOwnProperty.call(e,n)){var r=String(n);!0===Array.isArray(e[r])?t[r]=e[r].map(function(e){return!0===Array.isArray(e)||sR(e)?hA(e):""!==e?e:void 0}):sR(e[r])?t[r]=hA(e[r]):t[r]=""!==e[r]?e[r]:void 0}return t}function hL(e,t,n){var r=e.slice();return t.forEach(function(t,i){if(void 0===r[i]){var a=!1!==n.clone&&n.isMergeableObject(t);r[i]=a?sk(Array.isArray(t)?[]:{},t,n):t}else n.isMergeableObject(t)?r[i]=sk(e[i],t,n):-1===e.indexOf(t)&&r.push(t)}),r}function hC(e){return Array.from(e).filter(function(e){return e.selected}).map(function(e){return e.value})}function hI(e,t,n){if("boolean"==typeof e)return Boolean(t);var r=[],i=!1,a=-1;if(Array.isArray(e))r=e,i=(a=e.indexOf(n))>=0;else if(!n||"true"==n||"false"==n)return Boolean(t);return t&&n&&!i?r.concat(n):i?r.slice(0,a).concat(r.slice(a+1)):r}var hD="undefined"!=typeof window&&void 0!==window.document&&void 0!==window.document.createElement?l.useLayoutEffect:l.useEffect;function hN(e){var t=(0,l.useRef)(e);return hD(function(){t.current=e}),(0,l.useCallback)(function(){for(var e=arguments.length,n=Array(e),r=0;re?t:e},0);return Array.from(ha({},e,{length:t+1}))};(function(e){function t(t){var n;return(n=e.call(this,t)||this).updateArrayField=function(e,t,r){var i=n.props,a=i.name;(0,i.formik.setFormikState)(function(n){var i="function"==typeof r?r:e,o="function"==typeof t?t:e,s=hg(n.values,a,e(hm(n.values,a))),u=r?i(hm(n.errors,a)):void 0,c=t?o(hm(n.touched,a)):void 0;return hc(u)&&(u=void 0),hc(c)&&(c=void 0),ha({},n,{values:s,errors:r?hg(n.errors,a,u):n.errors,touched:t?hg(n.touched,a,c):n.touched})})},n.push=function(e){return n.updateArrayField(function(t){return[].concat(hU(t),[hi(e)])},!1,!1)},n.handlePush=function(e){return function(){return n.push(e)}},n.swap=function(e,t){return n.updateArrayField(function(n){return hF(n,e,t)},!0,!0)},n.handleSwap=function(e,t){return function(){return n.swap(e,t)}},n.move=function(e,t){return n.updateArrayField(function(n){return hj(n,e,t)},!0,!0)},n.handleMove=function(e,t){return function(){return n.move(e,t)}},n.insert=function(e,t){return n.updateArrayField(function(n){return hY(n,e,t)},function(t){return hY(t,e,null)},function(t){return hY(t,e,null)})},n.handleInsert=function(e,t){return function(){return n.insert(e,t)}},n.replace=function(e,t){return n.updateArrayField(function(n){return hB(n,e,t)},!1,!1)},n.handleReplace=function(e,t){return function(){return n.replace(e,t)}},n.unshift=function(e){var t=-1;return n.updateArrayField(function(n){var r=n?[e].concat(n):[e];return t<0&&(t=r.length),r},function(e){var n=e?[null].concat(e):[null];return t<0&&(t=n.length),n},function(e){var n=e?[null].concat(e):[null];return t<0&&(t=n.length),n}),t},n.handleUnshift=function(e){return function(){return n.unshift(e)}},n.handleRemove=function(e){return function(){return n.remove(e)}},n.handlePop=function(){return function(){return n.pop()}},n.remove=n.remove.bind(hu(n)),n.pop=n.pop.bind(hu(n)),n}ho(t,e);var n=t.prototype;return n.componentDidUpdate=function(e){this.props.validateOnChange&&this.props.formik.validateOnChange&&!sd()(hm(e.formik.values,e.name),hm(this.props.formik.values,this.props.name))&&this.props.formik.validateForm(this.props.formik.values)},n.remove=function(e){var t;return this.updateArrayField(function(n){var r=n?hU(n):[];return t||(t=r[e]),hl(r.splice)&&r.splice(e,1),r},!0,!0),t},n.pop=function(){var e;return this.updateArrayField(function(t){var n=t;return e||(e=n&&n.pop&&n.pop()),n},!0,!0),e},n.render=function(){var e={push:this.push,pop:this.pop,swap:this.swap,move:this.move,insert:this.insert,replace:this.replace,unshift:this.unshift,remove:this.remove,handlePush:this.handlePush,handlePop:this.handlePop,handleSwap:this.handleSwap,handleMove:this.handleMove,handleInsert:this.handleInsert,handleReplace:this.handleReplace,handleUnshift:this.handleUnshift,handleRemove:this.handleRemove},t=this.props,n=t.component,r=t.render,i=t.children,a=t.name,o=hs(t.formik,["validate","validationSchema"]),s=ha({},e,{form:o,name:a});return n?(0,l.createElement)(n,s):r?r(s):i?"function"==typeof i?i(s):hp(i)?null:l.Children.only(i):null},t})(l.Component).defaultProps={validateOnChange:!0},l.Component,l.Component;var hH=n(24802),h$=n(71209),hz=n(91750),hG=n(11970),hW=n(4689),hK=n(67598),hV=function(){return(hV=Object.assign||function(e){for(var t,n=1,r=arguments.length;nt.indexOf(r)&&(n[r]=e[r]);if(null!=e&&"function"==typeof Object.getOwnPropertySymbols)for(var i=0,r=Object.getOwnPropertySymbols(e);it.indexOf(r[i])&&(n[r[i]]=e[r[i]]);return n}function hZ(e){var t=e.disabled,n=e.field,r=n.onBlur,i=hq(n,["onBlur"]),a=e.form,o=a.isSubmitting,s=a.touched,u=a.errors,c=e.onBlur,l=e.helperText,f=hq(e,["disabled","field","form","onBlur","helperText"]),d=hm(u,i.name),h=hm(s,i.name)&&!!d;return hV(hV({variant:f.variant,error:h,helperText:h?d:l,disabled:null!=t?t:o,onBlur:null!=c?c:function(e){r(null!=e?e:i.name)}},i),f)}function hX(e){var t=e.children,n=hq(e,["children"]);return(0,l.createElement)(iw.Z,hV({},hZ(n)),t)}function hJ(e){var t=e.disabled,n=e.field,r=n.onBlur,i=hq(n,["onBlur"]),a=e.form.isSubmitting,o=(e.type,e.onBlur),s=hq(e,["disabled","field","form","type","onBlur"]);return hV(hV({disabled:null!=t?t:a,onBlur:null!=o?o:function(e){r(null!=e?e:i.name)}},i),s)}function hQ(e){return(0,l.createElement)(hH.Z,hV({},hJ(e)))}function h1(e){var t,n=e.disabled,r=e.field,i=r.onBlur,a=hq(r,["onBlur"]),o=e.form.isSubmitting,s=(e.type,e.onBlur),u=hq(e,["disabled","field","form","type","onBlur"]);return hV(hV({disabled:null!=n?n:o,indeterminate:!Array.isArray(a.value)&&null==a.value,onBlur:null!=s?s:function(e){i(null!=e?e:a.name)}},a),u)}function h0(e){return(0,l.createElement)(h$.Z,hV({},h1(e)))}function h2(e){var t=e.Label,n=hq(e,["Label"]);return(0,l.createElement)(hz.Z,hV({control:(0,l.createElement)(h$.Z,hV({},h1(n)))},t))}function h3(e){var t=e.disabled,n=e.field,r=n.onBlur,i=hq(n,["onBlur"]),a=e.form.isSubmitting,o=e.onBlur,s=hq(e,["disabled","field","form","onBlur"]);return hV(hV({disabled:null!=t?t:a,onBlur:null!=o?o:function(e){r(null!=e?e:i.name)}},i),s)}function h4(e){return(0,l.createElement)(hG.default,hV({},h3(e)))}function h6(e){var t=e.field,n=t.onBlur,r=hq(t,["onBlur"]),i=(e.form,e.onBlur),a=hq(e,["field","form","onBlur"]);return hV(hV({onBlur:null!=i?i:function(e){n(null!=e?e:r.name)}},r),a)}function h5(e){return(0,l.createElement)(hW.Z,hV({},h6(e)))}function h8(e){var t=e.disabled,n=e.field,r=n.onBlur,i=hq(n,["onBlur"]),a=e.form.isSubmitting,o=e.onBlur,s=hq(e,["disabled","field","form","onBlur"]);return hV(hV({disabled:null!=t?t:a,onBlur:null!=o?o:function(e){r(null!=e?e:i.name)}},i),s)}function h9(e){return(0,l.createElement)(hK.default,hV({},h8(e)))}hX.displayName="FormikMaterialUITextField",hQ.displayName="FormikMaterialUISwitch",h0.displayName="FormikMaterialUICheckbox",h2.displayName="FormikMaterialUICheckboxWithLabel",h4.displayName="FormikMaterialUISelect",h5.displayName="FormikMaterialUIRadioGroup",h9.displayName="FormikMaterialUIInputBase";try{a=Map}catch(h7){}try{o=Set}catch(pe){}function pt(e,t,n){if(!e||"object"!=typeof e||"function"==typeof e)return e;if(e.nodeType&&"cloneNode"in e)return e.cloneNode(!0);if(e instanceof Date)return new Date(e.getTime());if(e instanceof RegExp)return RegExp(e);if(Array.isArray(e))return e.map(pn);if(a&&e instanceof a)return new Map(Array.from(e.entries()));if(o&&e instanceof o)return new Set(Array.from(e.values()));if(e instanceof Object){t.push(e);var r=Object.create(e);for(var i in n.push(r),e){var s=t.findIndex(function(t){return t===e[i]});r[i]=s>-1?n[s]:pt(e[i],t,n)}return r}return e}function pn(e){return pt(e,[],[])}let pr=Object.prototype.toString,pi=Error.prototype.toString,pa=RegExp.prototype.toString,po="undefined"!=typeof Symbol?Symbol.prototype.toString:()=>"",ps=/^Symbol\((.*)\)(.*)$/;function pu(e){if(e!=+e)return"NaN";let t=0===e&&1/e<0;return t?"-0":""+e}function pc(e,t=!1){if(null==e||!0===e||!1===e)return""+e;let n=typeof e;if("number"===n)return pu(e);if("string"===n)return t?`"${e}"`:e;if("function"===n)return"[Function "+(e.name||"anonymous")+"]";if("symbol"===n)return po.call(e).replace(ps,"Symbol($1)");let r=pr.call(e).slice(8,-1);return"Date"===r?isNaN(e.getTime())?""+e:e.toISOString(e):"Error"===r||e instanceof Error?"["+pi.call(e)+"]":"RegExp"===r?pa.call(e):null}function pl(e,t){let n=pc(e,t);return null!==n?n:JSON.stringify(e,function(e,n){let r=pc(this[e],t);return null!==r?r:n},2)}let pf={default:"${path} is invalid",required:"${path} is a required field",oneOf:"${path} must be one of the following values: ${values}",notOneOf:"${path} must not be one of the following values: ${values}",notType({path:e,type:t,value:n,originalValue:r}){let i=null!=r&&r!==n,a=`${e} must be a \`${t}\` type, but the final value was: \`${pl(n,!0)}\``+(i?` (cast from the value \`${pl(r,!0)}\`).`:".");return null===n&&(a+='\n If "null" is intended as an empty value be sure to mark the schema as `.nullable()`'),a},defined:"${path} must be defined"},pd={length:"${path} must be exactly ${length} characters",min:"${path} must be at least ${min} characters",max:"${path} must be at most ${max} characters",matches:'${path} must match the following: "${regex}"',email:"${path} must be a valid email",url:"${path} must be a valid URL",uuid:"${path} must be a valid UUID",trim:"${path} must be a trimmed string",lowercase:"${path} must be a lowercase string",uppercase:"${path} must be a upper case string"},ph={min:"${path} must be greater than or equal to ${min}",max:"${path} must be less than or equal to ${max}",lessThan:"${path} must be less than ${less}",moreThan:"${path} must be greater than ${more}",positive:"${path} must be a positive number",negative:"${path} must be a negative number",integer:"${path} must be an integer"},pp={min:"${path} field must be later than ${min}",max:"${path} field must be at earlier than ${max}"},pb={isValue:"${path} field must be ${value}"},pm={noUnknown:"${path} field has unspecified keys: ${unknown}"},pg={min:"${path} field must have at least ${min} items",max:"${path} field must have less than or equal to ${max} items",length:"${path} must be have ${length} items"};Object.assign(Object.create(null),{mixed:pf,string:pd,number:ph,date:pp,object:pm,array:pg,boolean:pb});var pv=n(18721),py=n.n(pv);let pw=e=>e&&e.__isYupSchema__;class p_{constructor(e,t){if(this.refs=e,this.refs=e,"function"==typeof t){this.fn=t;return}if(!py()(t,"is"))throw TypeError("`is:` is required for `when()` conditions");if(!t.then&&!t.otherwise)throw TypeError("either `then:` or `otherwise:` is required for `when()` conditions");let{is:n,then:r,otherwise:i}=t,a="function"==typeof n?n:(...e)=>e.every(e=>e===n);this.fn=function(...e){let t=e.pop(),n=e.pop(),o=a(...e)?r:i;if(o)return"function"==typeof o?o(n):n.concat(o.resolve(t))}}resolve(e,t){let n=this.refs.map(e=>e.getValue(null==t?void 0:t.value,null==t?void 0:t.parent,null==t?void 0:t.context)),r=this.fn.apply(e,n.concat(e,t));if(void 0===r||r===e)return e;if(!pw(r))throw TypeError("conditions must return a schema object");return r.resolve(t)}}let pE=p_;function pS(e){return null==e?[]:[].concat(e)}function pk(){return(pk=Object.assign||function(e){for(var t=1;tpl(t[n])):"function"==typeof e?e(t):e}static isError(e){return e&&"ValidationError"===e.name}constructor(e,t,n,r){super(),this.name="ValidationError",this.value=t,this.path=n,this.type=r,this.errors=[],this.inner=[],pS(e).forEach(e=>{pT.isError(e)?(this.errors.push(...e.errors),this.inner=this.inner.concat(e.inner.length?e.inner:e)):this.errors.push(e)}),this.message=this.errors.length>1?`${this.errors.length} errors occurred`:this.errors[0],Error.captureStackTrace&&Error.captureStackTrace(this,pT)}}let pM=e=>{let t=!1;return(...n)=>{t||(t=!0,e(...n))}};function pO(e,t){let{endEarly:n,tests:r,args:i,value:a,errors:o,sort:s,path:u}=e,c=pM(t),l=r.length,f=[];if(o=o||[],!l)return o.length?c(new pT(o,a,u)):c(null,a);for(let d=0;d=0||(i[n]=e[n]);return i}function pR(e){function t(t,n){let{value:r,path:i="",label:a,options:o,originalValue:s,sync:u}=t,c=pP(t,["value","path","label","options","originalValue","sync"]),{name:l,test:f,params:d,message:h}=e,{parent:p,context:b}=o;function m(e){return pD.isRef(e)?e.getValue(r,p,b):e}function g(e={}){let t=pL()(pN({value:r,originalValue:s,label:a,path:e.path||i},d,e.params),m),n=new pT(pT.formatError(e.message||h,t),r,t.path,e.type||l);return n.params=t,n}let v=pN({path:i,parent:p,type:l,createError:g,resolve:m,options:o,originalValue:s},c);if(!u){try{Promise.resolve(f.call(v,r,v)).then(e=>{pT.isError(e)?n(e):e?n(null,e):n(g())})}catch(y){n(y)}return}let w;try{var _;if(w=f.call(v,r,v),"function"==typeof(null==(_=w)?void 0:_.then))throw Error(`Validation test of type: "${v.type}" returned a Promise during a synchronous validate. This test will finish after the validate call has returned`)}catch(E){n(E);return}pT.isError(w)?n(w):w?n(null,w):n(g())}return t.OPTIONS=e,t}pD.prototype.__isYupRef=!0;let pj=e=>e.substr(0,e.length-1).substr(1);function pF(e,t,n,r=n){let i,a,o;return t?((0,pC.forEach)(t,(s,u,c)=>{let l=u?pj(s):s;if((e=e.resolve({context:r,parent:i,value:n})).innerType){let f=c?parseInt(l,10):0;if(n&&f>=n.length)throw Error(`Yup.reach cannot resolve an array item at index: ${s}, in the path: ${t}. because there is no value at that index. `);i=n,n=n&&n[f],e=e.innerType}if(!c){if(!e.fields||!e.fields[l])throw Error(`The schema does not contain the path: ${t}. (failed at: ${o} which is a type: "${e._type}")`);i=n,n=n&&n[l],e=e.fields[l]}a=l,o=u?"["+s+"]":"."+s}),{schema:e,parent:i,parentPath:a}):{parent:i,parentPath:t,schema:e}}class pY{constructor(){this.list=new Set,this.refs=new Map}get size(){return this.list.size+this.refs.size}describe(){let e=[];for(let t of this.list)e.push(t);for(let[,n]of this.refs)e.push(n.describe());return e}toArray(){return Array.from(this.list).concat(Array.from(this.refs.values()))}add(e){pD.isRef(e)?this.refs.set(e.key,e):this.list.add(e)}delete(e){pD.isRef(e)?this.refs.delete(e.key):this.list.delete(e)}has(e,t){if(this.list.has(e))return!0;let n,r=this.refs.values();for(;!(n=r.next()).done;)if(t(n.value)===e)return!0;return!1}clone(){let e=new pY;return e.list=new Set(this.list),e.refs=new Map(this.refs),e}merge(e,t){let n=this.clone();return e.list.forEach(e=>n.add(e)),e.refs.forEach(e=>n.add(e)),t.list.forEach(e=>n.delete(e)),t.refs.forEach(e=>n.delete(e)),n}}function pB(){return(pB=Object.assign||function(e){for(var t=1;t{this.typeError(pf.notType)}),this.type=(null==e?void 0:e.type)||"mixed",this.spec=pB({strip:!1,strict:!1,abortEarly:!0,recursive:!0,nullable:!1,presence:"optional"},null==e?void 0:e.spec)}get _type(){return this.type}_typeCheck(e){return!0}clone(e){if(this._mutate)return e&&Object.assign(this.spec,e),this;let t=Object.create(Object.getPrototypeOf(this));return t.type=this.type,t._typeError=this._typeError,t._whitelistError=this._whitelistError,t._blacklistError=this._blacklistError,t._whitelist=this._whitelist.clone(),t._blacklist=this._blacklist.clone(),t.exclusiveTests=pB({},this.exclusiveTests),t.deps=[...this.deps],t.conditions=[...this.conditions],t.tests=[...this.tests],t.transforms=[...this.transforms],t.spec=pn(pB({},this.spec,e)),t}label(e){var t=this.clone();return t.spec.label=e,t}meta(...e){if(0===e.length)return this.spec.meta;let t=this.clone();return t.spec.meta=Object.assign(t.spec.meta||{},e[0]),t}withMutation(e){let t=this._mutate;this._mutate=!0;let n=e(this);return this._mutate=t,n}concat(e){if(!e||e===this)return this;if(e.type!==this.type&&"mixed"!==this.type)throw TypeError(`You cannot \`concat()\` schema's of different types: ${this.type} and ${e.type}`);let t=this,n=e.clone(),r=pB({},t.spec,n.spec);return n.spec=r,n._typeError||(n._typeError=t._typeError),n._whitelistError||(n._whitelistError=t._whitelistError),n._blacklistError||(n._blacklistError=t._blacklistError),n._whitelist=t._whitelist.merge(e._whitelist,e._blacklist),n._blacklist=t._blacklist.merge(e._blacklist,e._whitelist),n.tests=t.tests,n.exclusiveTests=t.exclusiveTests,n.withMutation(t=>{e.tests.forEach(e=>{t.test(e.OPTIONS)})}),n}isType(e){return!!this.spec.nullable&&null===e||this._typeCheck(e)}resolve(e){let t=this;if(t.conditions.length){let n=t.conditions;(t=t.clone()).conditions=[],t=(t=n.reduce((t,n)=>n.resolve(t,e),t)).resolve(e)}return t}cast(e,t={}){let n=this.resolve(pB({value:e},t)),r=n._cast(e,t);if(void 0!==e&&!1!==t.assert&&!0!==n.isType(r)){let i=pl(e),a=pl(r);throw TypeError(`The value of ${t.path||"field"} could not be cast to a value that satisfies the schema type: "${n._type}". attempted value: ${i} -`+(a!==i?`result of cast: ${a}`:""))}return r}_cast(e,t){let n=void 0===e?e:this.transforms.reduce((t,n)=>n.call(this,t,e,this),e);return void 0===n&&(n=this.getDefault()),n}_validate(e,t={},n){let{sync:r,path:i,from:a=[],originalValue:o=e,strict:s=this.spec.strict,abortEarly:u=this.spec.abortEarly}=t,c=e;s||(c=this._cast(c,pB({assert:!1},t)));let l={value:c,path:i,options:t,originalValue:o,schema:this,label:this.spec.label,sync:r,from:a},f=[];this._typeError&&f.push(this._typeError),this._whitelistError&&f.push(this._whitelistError),this._blacklistError&&f.push(this._blacklistError),pO({args:l,value:c,path:i,sync:r,tests:f,endEarly:u},e=>{if(e)return void n(e,c);pO({tests:this.tests,args:l,path:i,sync:r,value:c,endEarly:u},n)})}validate(e,t,n){let r=this.resolve(pB({},t,{value:e}));return"function"==typeof n?r._validate(e,t,n):new Promise((n,i)=>r._validate(e,t,(e,t)=>{e?i(e):n(t)}))}validateSync(e,t){let n;return this.resolve(pB({},t,{value:e}))._validate(e,pB({},t,{sync:!0}),(e,t)=>{if(e)throw e;n=t}),n}isValid(e,t){return this.validate(e,t).then(()=>!0,e=>{if(pT.isError(e))return!1;throw e})}isValidSync(e,t){try{return this.validateSync(e,t),!0}catch(n){if(pT.isError(n))return!1;throw n}}_getDefault(){let e=this.spec.default;return null==e?e:"function"==typeof e?e.call(this):pn(e)}getDefault(e){return this.resolve(e||{})._getDefault()}default(e){return 0===arguments.length?this._getDefault():this.clone({default:e})}strict(e=!0){var t=this.clone();return t.spec.strict=e,t}_isPresent(e){return null!=e}defined(e=pf.defined){return this.test({message:e,name:"defined",exclusive:!0,test:e=>void 0!==e})}required(e=pf.required){return this.clone({presence:"required"}).withMutation(t=>t.test({message:e,name:"required",exclusive:!0,test(e){return this.schema._isPresent(e)}}))}notRequired(){var e=this.clone({presence:"optional"});return e.tests=e.tests.filter(e=>"required"!==e.OPTIONS.name),e}nullable(e=!0){return this.clone({nullable:!1!==e})}transform(e){var t=this.clone();return t.transforms.push(e),t}test(...e){let t;if(void 0===(t=1===e.length?"function"==typeof e[0]?{test:e[0]}:e[0]:2===e.length?{name:e[0],test:e[1]}:{name:e[0],message:e[1],test:e[2]}).message&&(t.message=pf.default),"function"!=typeof t.test)throw TypeError("`test` is a required parameters");let n=this.clone(),r=pR(t),i=t.exclusive||t.name&&!0===n.exclusiveTests[t.name];if(t.exclusive&&!t.name)throw TypeError("Exclusive tests must provide a unique `name` identifying the test");return t.name&&(n.exclusiveTests[t.name]=!!t.exclusive),n.tests=n.tests.filter(e=>e.OPTIONS.name!==t.name||!i&&e.OPTIONS.test!==r.OPTIONS.test),n.tests.push(r),n}when(e,t){Array.isArray(e)||"string"==typeof e||(t=e,e=".");let n=this.clone(),r=pS(e).map(e=>new pD(e));return r.forEach(e=>{e.isSibling&&n.deps.push(e.key)}),n.conditions.push(new pE(r,t)),n}typeError(e){var t=this.clone();return t._typeError=pR({message:e,name:"typeError",test(e){return!!(void 0===e||this.schema.isType(e))||this.createError({params:{type:this.schema._type}})}}),t}oneOf(e,t=pf.oneOf){var n=this.clone();return e.forEach(e=>{n._whitelist.add(e),n._blacklist.delete(e)}),n._whitelistError=pR({message:t,name:"oneOf",test(e){if(void 0===e)return!0;let t=this.schema._whitelist;return!!t.has(e,this.resolve)||this.createError({params:{values:t.toArray().join(", ")}})}}),n}notOneOf(e,t=pf.notOneOf){var n=this.clone();return e.forEach(e=>{n._blacklist.add(e),n._whitelist.delete(e)}),n._blacklistError=pR({message:t,name:"notOneOf",test(e){let t=this.schema._blacklist;return!t.has(e,this.resolve)||this.createError({params:{values:t.toArray().join(", ")}})}}),n}strip(e=!0){let t=this.clone();return t.spec.strip=e,t}describe(){let e=this.clone(),{label:t,meta:n}=e.spec,r={meta:n,label:t,type:e.type,oneOf:e._whitelist.describe(),notOneOf:e._blacklist.describe(),tests:e.tests.map(e=>({name:e.OPTIONS.name,params:e.OPTIONS.params})).filter((e,t,n)=>n.findIndex(t=>t.name===e.name)===t)};return r}}for(let pH of(pU.prototype.__isYupSchema__=!0,["validate","validateSync"]))pU.prototype[`${pH}At`]=function(e,t,n={}){let{parent:r,parentPath:i,schema:a}=pF(this,e,t,n.context);return a[pH](r&&r[i],pB({},n,{parent:r,path:e}))};for(let p$ of["equals","is"])pU.prototype[p$]=pU.prototype.oneOf;for(let pz of["not","nope"])pU.prototype[pz]=pU.prototype.notOneOf;pU.prototype.optional=pU.prototype.notRequired;let pG=pU;function pW(){return new pG}pW.prototype=pG.prototype;let pK=e=>null==e;function pV(){return new pq}class pq extends pU{constructor(){super({type:"boolean"}),this.withMutation(()=>{this.transform(function(e){if(!this.isType(e)){if(/^(true|1)$/i.test(String(e)))return!0;if(/^(false|0)$/i.test(String(e)))return!1}return e})})}_typeCheck(e){return e instanceof Boolean&&(e=e.valueOf()),"boolean"==typeof e}isTrue(e=pb.isValue){return this.test({message:e,name:"is-value",exclusive:!0,params:{value:"true"},test:e=>pK(e)||!0===e})}isFalse(e=pb.isValue){return this.test({message:e,name:"is-value",exclusive:!0,params:{value:"false"},test:e=>pK(e)||!1===e})}}pV.prototype=pq.prototype;let pZ=/^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))$/i,pX=/^((https?|ftp):)?\/\/(((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:)*@)?(((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5]))|((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?)(:\d*)?)(\/((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)+(\/(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*)?)?(\?((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|[\uE000-\uF8FF]|\/|\?)*)?(\#((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|\/|\?)*)?$/i,pJ=/^(?:[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}|00000000-0000-0000-0000-000000000000)$/i,pQ=e=>pK(e)||e===e.trim(),p1=({}).toString();function p0(){return new p2}class p2 extends pU{constructor(){super({type:"string"}),this.withMutation(()=>{this.transform(function(e){if(this.isType(e)||Array.isArray(e))return e;let t=null!=e&&e.toString?e.toString():e;return t===p1?e:t})})}_typeCheck(e){return e instanceof String&&(e=e.valueOf()),"string"==typeof e}_isPresent(e){return super._isPresent(e)&&!!e.length}length(e,t=pd.length){return this.test({message:t,name:"length",exclusive:!0,params:{length:e},test(t){return pK(t)||t.length===this.resolve(e)}})}min(e,t=pd.min){return this.test({message:t,name:"min",exclusive:!0,params:{min:e},test(t){return pK(t)||t.length>=this.resolve(e)}})}max(e,t=pd.max){return this.test({name:"max",exclusive:!0,message:t,params:{max:e},test(t){return pK(t)||t.length<=this.resolve(e)}})}matches(e,t){let n=!1,r,i;return t&&("object"==typeof t?{excludeEmptyString:n=!1,message:r,name:i}=t:r=t),this.test({name:i||"matches",message:r||pd.matches,params:{regex:e},test:t=>pK(t)||""===t&&n||-1!==t.search(e)})}email(e=pd.email){return this.matches(pZ,{name:"email",message:e,excludeEmptyString:!0})}url(e=pd.url){return this.matches(pX,{name:"url",message:e,excludeEmptyString:!0})}uuid(e=pd.uuid){return this.matches(pJ,{name:"uuid",message:e,excludeEmptyString:!1})}ensure(){return this.default("").transform(e=>null===e?"":e)}trim(e=pd.trim){return this.transform(e=>null!=e?e.trim():e).test({message:e,name:"trim",test:pQ})}lowercase(e=pd.lowercase){return this.transform(e=>pK(e)?e:e.toLowerCase()).test({message:e,name:"string_case",exclusive:!0,test:e=>pK(e)||e===e.toLowerCase()})}uppercase(e=pd.uppercase){return this.transform(e=>pK(e)?e:e.toUpperCase()).test({message:e,name:"string_case",exclusive:!0,test:e=>pK(e)||e===e.toUpperCase()})}}p0.prototype=p2.prototype;let p3=e=>e!=+e;function p4(){return new p6}class p6 extends pU{constructor(){super({type:"number"}),this.withMutation(()=>{this.transform(function(e){let t=e;if("string"==typeof t){if(""===(t=t.replace(/\s/g,"")))return NaN;t=+t}return this.isType(t)?t:parseFloat(t)})})}_typeCheck(e){return e instanceof Number&&(e=e.valueOf()),"number"==typeof e&&!p3(e)}min(e,t=ph.min){return this.test({message:t,name:"min",exclusive:!0,params:{min:e},test(t){return pK(t)||t>=this.resolve(e)}})}max(e,t=ph.max){return this.test({message:t,name:"max",exclusive:!0,params:{max:e},test(t){return pK(t)||t<=this.resolve(e)}})}lessThan(e,t=ph.lessThan){return this.test({message:t,name:"max",exclusive:!0,params:{less:e},test(t){return pK(t)||tthis.resolve(e)}})}positive(e=ph.positive){return this.moreThan(0,e)}negative(e=ph.negative){return this.lessThan(0,e)}integer(e=ph.integer){return this.test({name:"integer",message:e,test:e=>pK(e)||Number.isInteger(e)})}truncate(){return this.transform(e=>pK(e)?e:0|e)}round(e){var t,n=["ceil","floor","round","trunc"];if("trunc"===(e=(null==(t=e)?void 0:t.toLowerCase())||"round"))return this.truncate();if(-1===n.indexOf(e.toLowerCase()))throw TypeError("Only valid options for round() are: "+n.join(", "));return this.transform(t=>pK(t)?t:Math[e](t))}}p4.prototype=p6.prototype;var p5=/^(\d{4}|[+\-]\d{6})(?:-?(\d{2})(?:-?(\d{2}))?)?(?:[ T]?(\d{2}):?(\d{2})(?::?(\d{2})(?:[,\.](\d{1,}))?)?(?:(Z)|([+\-])(\d{2})(?::?(\d{2}))?)?)?$/;function p8(e){var t,n,r=[1,4,5,6,7,10,11],i=0;if(n=p5.exec(e)){for(var a,o=0;a=r[o];++o)n[a]=+n[a]||0;n[2]=(+n[2]||1)-1,n[3]=+n[3]||1,n[7]=n[7]?String(n[7]).substr(0,3):0,(void 0===n[8]||""===n[8])&&(void 0===n[9]||""===n[9])?t=+new Date(n[1],n[2],n[3],n[4],n[5],n[6],n[7]):("Z"!==n[8]&&void 0!==n[9]&&(i=60*n[10]+n[11],"+"===n[9]&&(i=0-i)),t=Date.UTC(n[1],n[2],n[3],n[4],n[5]+i,n[6],n[7]))}else t=Date.parse?Date.parse(e):NaN;return t}let p9=new Date(""),p7=e=>"[object Date]"===Object.prototype.toString.call(e);function be(){return new bt}class bt extends pU{constructor(){super({type:"date"}),this.withMutation(()=>{this.transform(function(e){return this.isType(e)?e:(e=p8(e),isNaN(e)?p9:new Date(e))})})}_typeCheck(e){return p7(e)&&!isNaN(e.getTime())}prepareParam(e,t){let n;if(pD.isRef(e))n=e;else{let r=this.cast(e);if(!this._typeCheck(r))throw TypeError(`\`${t}\` must be a Date or a value that can be \`cast()\` to a Date`);n=r}return n}min(e,t=pp.min){let n=this.prepareParam(e,"min");return this.test({message:t,name:"min",exclusive:!0,params:{min:e},test(e){return pK(e)||e>=this.resolve(n)}})}max(e,t=pp.max){var n=this.prepareParam(e,"max");return this.test({message:t,name:"max",exclusive:!0,params:{max:e},test(e){return pK(e)||e<=this.resolve(n)}})}}bt.INVALID_DATE=p9,be.prototype=bt.prototype,be.INVALID_DATE=p9;var bn=n(11865),br=n.n(bn),bi=n(68929),ba=n.n(bi),bo=n(67523),bs=n.n(bo),bu=n(94633),bc=n.n(bu);function bl(e,t=[]){let n=[],r=[];function i(e,i){var a=(0,pC.split)(e)[0];~r.indexOf(a)||r.push(a),~t.indexOf(`${i}-${a}`)||n.push([i,a])}for(let a in e)if(py()(e,a)){let o=e[a];~r.indexOf(a)||r.push(a),pD.isRef(o)&&o.isSibling?i(o.path,a):pw(o)&&"deps"in o&&o.deps.forEach(e=>i(e,a))}return bc().array(r,n).reverse()}function bf(e,t){let n=1/0;return e.some((e,r)=>{var i;if((null==(i=t.path)?void 0:i.indexOf(e))!==-1)return n=r,!0}),n}function bd(e){return(t,n)=>bf(e,t)-bf(e,n)}function bh(){return(bh=Object.assign||function(e){for(var t=1;t"[object Object]"===Object.prototype.toString.call(e);function bb(e,t){let n=Object.keys(e.fields);return Object.keys(t).filter(e=>-1===n.indexOf(e))}let bm=bd([]);class bg extends pU{constructor(e){super({type:"object"}),this.fields=Object.create(null),this._sortErrors=bm,this._nodes=[],this._excludedEdges=[],this.withMutation(()=>{this.transform(function(e){if("string"==typeof e)try{e=JSON.parse(e)}catch(t){e=null}return this.isType(e)?e:null}),e&&this.shape(e)})}_typeCheck(e){return bp(e)||"function"==typeof e}_cast(e,t={}){var n;let r=super._cast(e,t);if(void 0===r)return this.getDefault();if(!this._typeCheck(r))return r;let i=this.fields,a=null!=(n=t.stripUnknown)?n:this.spec.noUnknown,o=this._nodes.concat(Object.keys(r).filter(e=>-1===this._nodes.indexOf(e))),s={},u=bh({},t,{parent:s,__validating:t.__validating||!1}),c=!1;for(let l of o){let f=i[l],d=py()(r,l);if(f){let h,p=r[l];u.path=(t.path?`${t.path}.`:"")+l;let b="spec"in(f=f.resolve({value:p,context:t.context,parent:s}))?f.spec:void 0,m=null==b?void 0:b.strict;if(null==b?void 0:b.strip){c=c||l in r;continue}void 0!==(h=t.__validating&&m?r[l]:f.cast(r[l],u))&&(s[l]=h)}else d&&!a&&(s[l]=r[l]);s[l]!==r[l]&&(c=!0)}return c?s:r}_validate(e,t={},n){let r=[],{sync:i,from:a=[],originalValue:o=e,abortEarly:s=this.spec.abortEarly,recursive:u=this.spec.recursive}=t;a=[{schema:this,value:o},...a],t.__validating=!0,t.originalValue=o,t.from=a,super._validate(e,t,(e,c)=>{if(e){if(!pT.isError(e)||s)return void n(e,c);r.push(e)}if(!u||!bp(c)){n(r[0]||null,c);return}o=o||c;let l=this._nodes.map(e=>(n,r)=>{let i=-1===e.indexOf(".")?(t.path?`${t.path}.`:"")+e:`${t.path||""}["${e}"]`,s=this.fields[e];if(s&&"validate"in s){s.validate(c[e],bh({},t,{path:i,from:a,strict:!0,parent:c,originalValue:o[e]}),r);return}r(null)});pO({sync:i,tests:l,value:c,errors:r,endEarly:s,sort:this._sortErrors,path:t.path},n)})}clone(e){let t=super.clone(e);return t.fields=bh({},this.fields),t._nodes=this._nodes,t._excludedEdges=this._excludedEdges,t._sortErrors=this._sortErrors,t}concat(e){let t=super.concat(e),n=t.fields;for(let[r,i]of Object.entries(this.fields)){let a=n[r];void 0===a?n[r]=i:a instanceof pU&&i instanceof pU&&(n[r]=i.concat(a))}return t.withMutation(()=>t.shape(n))}getDefaultFromShape(){let e={};return this._nodes.forEach(t=>{let n=this.fields[t];e[t]="default"in n?n.getDefault():void 0}),e}_getDefault(){return"default"in this.spec?super._getDefault():this._nodes.length?this.getDefaultFromShape():void 0}shape(e,t=[]){let n=this.clone(),r=Object.assign(n.fields,e);if(n.fields=r,n._sortErrors=bd(Object.keys(r)),t.length){Array.isArray(t[0])||(t=[t]);let i=t.map(([e,t])=>`${e}-${t}`);n._excludedEdges=n._excludedEdges.concat(i)}return n._nodes=bl(r,n._excludedEdges),n}pick(e){let t={};for(let n of e)this.fields[n]&&(t[n]=this.fields[n]);return this.clone().withMutation(e=>(e.fields={},e.shape(t)))}omit(e){let t=this.clone(),n=t.fields;for(let r of(t.fields={},e))delete n[r];return t.withMutation(()=>t.shape(n))}from(e,t,n){let r=(0,pC.getter)(e,!0);return this.transform(i=>{if(null==i)return i;let a=i;return py()(i,e)&&(a=bh({},i),n||delete a[e],a[t]=r(i)),a})}noUnknown(e=!0,t=pm.noUnknown){"string"==typeof e&&(t=e,e=!0);let n=this.test({name:"noUnknown",exclusive:!0,message:t,test(t){if(null==t)return!0;let n=bb(this.schema,t);return!e||0===n.length||this.createError({params:{unknown:n.join(", ")}})}});return n.spec.noUnknown=e,n}unknown(e=!0,t=pm.noUnknown){return this.noUnknown(!e,t)}transformKeys(e){return this.transform(t=>t&&bs()(t,(t,n)=>e(n)))}camelCase(){return this.transformKeys(ba())}snakeCase(){return this.transformKeys(br())}constantCase(){return this.transformKeys(e=>br()(e).toUpperCase())}describe(){let e=super.describe();return e.fields=pL()(this.fields,e=>e.describe()),e}}function bv(e){return new bg(e)}function by(){return(by=Object.assign||function(e){for(var t=1;t{this.transform(function(e){if("string"==typeof e)try{e=JSON.parse(e)}catch(t){e=null}return this.isType(e)?e:null})})}_typeCheck(e){return Array.isArray(e)}get _subType(){return this.innerType}_cast(e,t){let n=super._cast(e,t);if(!this._typeCheck(n)||!this.innerType)return n;let r=!1,i=n.map((e,n)=>{let i=this.innerType.cast(e,by({},t,{path:`${t.path||""}[${n}]`}));return i!==e&&(r=!0),i});return r?i:n}_validate(e,t={},n){var r,i;let a=[],o=t.sync,s=t.path,u=this.innerType,c=null!=(r=t.abortEarly)?r:this.spec.abortEarly,l=null!=(i=t.recursive)?i:this.spec.recursive,f=null!=t.originalValue?t.originalValue:e;super._validate(e,t,(e,r)=>{if(e){if(!pT.isError(e)||c)return void n(e,r);a.push(e)}if(!l||!u||!this._typeCheck(r)){n(a[0]||null,r);return}f=f||r;let i=Array(r.length);for(let d=0;du.validate(h,b,t)}pO({sync:o,path:s,value:r,errors:a,endEarly:c,tests:i},n)})}clone(e){let t=super.clone(e);return t.innerType=this.innerType,t}concat(e){let t=super.concat(e);return t.innerType=this.innerType,e.innerType&&(t.innerType=t.innerType?t.innerType.concat(e.innerType):e.innerType),t}of(e){let t=this.clone();if(!pw(e))throw TypeError("`array.of()` sub-schema must be a valid yup schema not: "+pl(e));return t.innerType=e,t}length(e,t=pg.length){return this.test({message:t,name:"length",exclusive:!0,params:{length:e},test(t){return pK(t)||t.length===this.resolve(e)}})}min(e,t){return t=t||pg.min,this.test({message:t,name:"min",exclusive:!0,params:{min:e},test(t){return pK(t)||t.length>=this.resolve(e)}})}max(e,t){return t=t||pg.max,this.test({message:t,name:"max",exclusive:!0,params:{max:e},test(t){return pK(t)||t.length<=this.resolve(e)}})}ensure(){return this.default(()=>[]).transform((e,t)=>this._typeCheck(e)?e:null==t?[]:[].concat(t))}compact(e){let t=e?(t,n,r)=>!e(t,n,r):e=>!!e;return this.transform(e=>null!=e?e.filter(t):e)}describe(){let e=super.describe();return this.innerType&&(e.innerType=this.innerType.describe()),e}nullable(e=!0){return super.nullable(e)}defined(){return super.defined()}required(e){return super.required(e)}}bw.prototype=b_.prototype;var bE=bv().shape({name:p0().required("Required"),url:p0().required("Required")}),bS=function(e){var t=e.initialValues,n=e.onSubmit,r=e.submitButtonText,i=e.nameDisabled,a=void 0!==i&&i;return l.createElement(hT,{initialValues:t,validationSchema:bE,onSubmit:n},function(e){var t=e.isSubmitting;return l.createElement(l.Fragment,null,l.createElement(hR,{"data-testid":"bridge-form",noValidate:!0},l.createElement(d.Z,{container:!0,spacing:16},l.createElement(d.Z,{item:!0,xs:12,md:7},l.createElement(hP,{component:hX,id:"name",name:"name",label:"Name",disabled:a,required:!0,fullWidth:!0,FormHelperTextProps:{"data-testid":"name-helper-text"}})),l.createElement(d.Z,{item:!0,xs:12,md:7},l.createElement(hP,{component:hX,id:"url",name:"url",label:"Bridge URL",placeholder:"https://",required:!0,fullWidth:!0,FormHelperTextProps:{"data-testid":"url-helper-text"}})),l.createElement(d.Z,{item:!0,xs:12,md:7},l.createElement(d.Z,{container:!0,spacing:16},l.createElement(d.Z,{item:!0,xs:7},l.createElement(hP,{component:hX,id:"minimumContractPayment",name:"minimumContractPayment",label:"Minimum Contract Payment",placeholder:"0",fullWidth:!0,inputProps:{min:0},FormHelperTextProps:{"data-testid":"minimumContractPayment-helper-text"}})),l.createElement(d.Z,{item:!0,xs:7},l.createElement(hP,{component:hX,id:"confirmations",name:"confirmations",label:"Confirmations",placeholder:"0",type:"number",fullWidth:!0,inputProps:{min:0},FormHelperTextProps:{"data-testid":"confirmations-helper-text"}})))),l.createElement(d.Z,{item:!0,xs:12,md:7},l.createElement(ok.default,{variant:"contained",color:"primary",type:"submit",disabled:t,size:"large"},r)))))})},bk=function(e){var t=e.bridge,n=e.onSubmit,r={name:t.name,url:t.url,minimumContractPayment:t.minimumContractPayment,confirmations:t.confirmations};return l.createElement(ig,null,l.createElement(d.Z,{container:!0,spacing:40},l.createElement(d.Z,{item:!0,xs:12,md:11,lg:9},l.createElement(r5.Z,null,l.createElement(sl.Z,{title:"Edit Bridge",action:l.createElement(aA.Z,{component:tz,href:"/bridges/".concat(t.id)},"Cancel")}),l.createElement(aW.Z,null,l.createElement(bS,{nameDisabled:!0,initialValues:r,onSubmit:n,submitButtonText:"Save Bridge"}))))))};function bx(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]e.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]e.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&void 0!==arguments[0]&&arguments[0],t=e?function(){return l.createElement(x.default,{variant:"body1"},"Loading...")}:function(){return null};return{isLoading:e,LoadingPlaceholder:t}},mc=n(76023);function ml(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]e.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]=0)&&Object.prototype.propertyIsEnumerable.call(e,n)&&(i[n]=e[n])}return i}function mB(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n=4?[e[0],e[1],e[2],e[3],"".concat(e[0],".").concat(e[1]),"".concat(e[0],".").concat(e[2]),"".concat(e[0],".").concat(e[3]),"".concat(e[1],".").concat(e[0]),"".concat(e[1],".").concat(e[2]),"".concat(e[1],".").concat(e[3]),"".concat(e[2],".").concat(e[0]),"".concat(e[2],".").concat(e[1]),"".concat(e[2],".").concat(e[3]),"".concat(e[3],".").concat(e[0]),"".concat(e[3],".").concat(e[1]),"".concat(e[3],".").concat(e[2]),"".concat(e[0],".").concat(e[1],".").concat(e[2]),"".concat(e[0],".").concat(e[1],".").concat(e[3]),"".concat(e[0],".").concat(e[2],".").concat(e[1]),"".concat(e[0],".").concat(e[2],".").concat(e[3]),"".concat(e[0],".").concat(e[3],".").concat(e[1]),"".concat(e[0],".").concat(e[3],".").concat(e[2]),"".concat(e[1],".").concat(e[0],".").concat(e[2]),"".concat(e[1],".").concat(e[0],".").concat(e[3]),"".concat(e[1],".").concat(e[2],".").concat(e[0]),"".concat(e[1],".").concat(e[2],".").concat(e[3]),"".concat(e[1],".").concat(e[3],".").concat(e[0]),"".concat(e[1],".").concat(e[3],".").concat(e[2]),"".concat(e[2],".").concat(e[0],".").concat(e[1]),"".concat(e[2],".").concat(e[0],".").concat(e[3]),"".concat(e[2],".").concat(e[1],".").concat(e[0]),"".concat(e[2],".").concat(e[1],".").concat(e[3]),"".concat(e[2],".").concat(e[3],".").concat(e[0]),"".concat(e[2],".").concat(e[3],".").concat(e[1]),"".concat(e[3],".").concat(e[0],".").concat(e[1]),"".concat(e[3],".").concat(e[0],".").concat(e[2]),"".concat(e[3],".").concat(e[1],".").concat(e[0]),"".concat(e[3],".").concat(e[1],".").concat(e[2]),"".concat(e[3],".").concat(e[2],".").concat(e[0]),"".concat(e[3],".").concat(e[2],".").concat(e[1]),"".concat(e[0],".").concat(e[1],".").concat(e[2],".").concat(e[3]),"".concat(e[0],".").concat(e[1],".").concat(e[3],".").concat(e[2]),"".concat(e[0],".").concat(e[2],".").concat(e[1],".").concat(e[3]),"".concat(e[0],".").concat(e[2],".").concat(e[3],".").concat(e[1]),"".concat(e[0],".").concat(e[3],".").concat(e[1],".").concat(e[2]),"".concat(e[0],".").concat(e[3],".").concat(e[2],".").concat(e[1]),"".concat(e[1],".").concat(e[0],".").concat(e[2],".").concat(e[3]),"".concat(e[1],".").concat(e[0],".").concat(e[3],".").concat(e[2]),"".concat(e[1],".").concat(e[2],".").concat(e[0],".").concat(e[3]),"".concat(e[1],".").concat(e[2],".").concat(e[3],".").concat(e[0]),"".concat(e[1],".").concat(e[3],".").concat(e[0],".").concat(e[2]),"".concat(e[1],".").concat(e[3],".").concat(e[2],".").concat(e[0]),"".concat(e[2],".").concat(e[0],".").concat(e[1],".").concat(e[3]),"".concat(e[2],".").concat(e[0],".").concat(e[3],".").concat(e[1]),"".concat(e[2],".").concat(e[1],".").concat(e[0],".").concat(e[3]),"".concat(e[2],".").concat(e[1],".").concat(e[3],".").concat(e[0]),"".concat(e[2],".").concat(e[3],".").concat(e[0],".").concat(e[1]),"".concat(e[2],".").concat(e[3],".").concat(e[1],".").concat(e[0]),"".concat(e[3],".").concat(e[0],".").concat(e[1],".").concat(e[2]),"".concat(e[3],".").concat(e[0],".").concat(e[2],".").concat(e[1]),"".concat(e[3],".").concat(e[1],".").concat(e[0],".").concat(e[2]),"".concat(e[3],".").concat(e[1],".").concat(e[2],".").concat(e[0]),"".concat(e[3],".").concat(e[2],".").concat(e[0],".").concat(e[1]),"".concat(e[3],".").concat(e[2],".").concat(e[1],".").concat(e[0])]:void 0}var mZ={};function mX(e){if(0===e.length||1===e.length)return e;var t=e.join(".");return mZ[t]||(mZ[t]=mq(e)),mZ[t]}function mJ(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},n=arguments.length>2?arguments[2]:void 0;return mX(e.filter(function(e){return"token"!==e})).reduce(function(e,t){return mK({},e,n[t])},t)}function mQ(e){return e.join(" ")}function m1(e,t){var n=0;return function(r){return n+=1,r.map(function(r,i){return m0({node:r,stylesheet:e,useInlineStyles:t,key:"code-segment-".concat(n,"-").concat(i)})})}}function m0(e){var t=e.node,n=e.stylesheet,r=e.style,i=void 0===r?{}:r,a=e.useInlineStyles,o=e.key,s=t.properties,u=t.type,c=t.tagName,f=t.value;if("text"===u)return f;if(c){var d,h=m1(n,a);if(a){var p=Object.keys(n).reduce(function(e,t){return t.split(".").forEach(function(t){e.includes(t)||e.push(t)}),e},[]),b=s.className&&s.className.includes("token")?["token"]:[],m=s.className&&b.concat(s.className.filter(function(e){return!p.includes(e)}));d=mK({},s,{className:mQ(m)||void 0,style:mJ(s.className,Object.assign({},s.style,i),n)})}else d=mK({},s,{className:mQ(s.className)});var g=h(t.children);return l.createElement(c,(0,mV.Z)({key:o},d),g)}}let m2=function(e,t){return -1!==e.listLanguages().indexOf(t)};var m3=/\n/g;function m4(e){return e.match(m3)}function m6(e){var t=e.lines,n=e.startingLineNumber,r=e.style;return t.map(function(e,t){var i=t+n;return l.createElement("span",{key:"line-".concat(t),className:"react-syntax-highlighter-line-number",style:"function"==typeof r?r(i):r},"".concat(i,"\n"))})}function m5(e){var t=e.codeString,n=e.codeStyle,r=e.containerStyle,i=void 0===r?{float:"left",paddingRight:"10px"}:r,a=e.numberStyle,o=void 0===a?{}:a,s=e.startingLineNumber;return l.createElement("code",{style:Object.assign({},n,i)},m6({lines:t.replace(/\n$/,"").split("\n"),style:o,startingLineNumber:s}))}function m8(e){return"".concat(e.toString().length,".25em")}function m9(e,t){return{type:"element",tagName:"span",properties:{key:"line-number--".concat(e),className:["comment","linenumber","react-syntax-highlighter-line-number"],style:t},children:[{type:"text",value:e}]}}function m7(e,t,n){var r,i={display:"inline-block",minWidth:m8(n),paddingRight:"1em",textAlign:"right",userSelect:"none"};return mK({},i,"function"==typeof e?e(t):e)}function ge(e){var t=e.children,n=e.lineNumber,r=e.lineNumberStyle,i=e.largestLineNumber,a=e.showInlineLineNumbers,o=e.lineProps,s=void 0===o?{}:o,u=e.className,c=void 0===u?[]:u,l=e.showLineNumbers,f=e.wrapLongLines,d="function"==typeof s?s(n):s;if(d.className=c,n&&a){var h=m7(r,n,i);t.unshift(m9(n,h))}return f&l&&(d.style=mK({},d.style,{display:"flex"})),{type:"element",tagName:"span",properties:d,children:t}}function gt(e){for(var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:[],n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:[],r=0;r2&&void 0!==arguments[2]?arguments[2]:[];return ge({children:e,lineNumber:t,lineNumberStyle:s,largestLineNumber:o,showInlineLineNumbers:i,lineProps:n,className:a,showLineNumbers:r,wrapLongLines:u})}function b(e,t){if(r&&t&&i){var n=m7(s,t,o);e.unshift(m9(t,n))}return e}function m(e,n){var r=arguments.length>2&&void 0!==arguments[2]?arguments[2]:[];return t||r.length>0?p(e,n,r):b(e,n)}for(var g=function(){var e=l[h],t=e.children[0].value;if(m4(t)){var n=t.split("\n");n.forEach(function(t,i){var o=r&&f.length+a,s={type:"text",value:"".concat(t,"\n")};if(0===i){var u=l.slice(d+1,h).concat(ge({children:[s],className:e.properties.className})),c=m(u,o);f.push(c)}else if(i===n.length-1){if(l[h+1]&&l[h+1].children&&l[h+1].children[0]){var p={type:"text",value:"".concat(t)},b=ge({children:[p],className:e.properties.className});l.splice(h+1,0,b)}else{var g=[s],v=m(g,o,e.properties.className);f.push(v)}}else{var y=[s],w=m(y,o,e.properties.className);f.push(w)}}),d=h}h++};h code[class*="language-"]':{background:"#f5f2f0",padding:".1em",borderRadius:".3em",whiteSpace:"normal"},comment:{color:"slategray"},prolog:{color:"slategray"},doctype:{color:"slategray"},cdata:{color:"slategray"},punctuation:{color:"#999"},namespace:{Opacity:".7"},property:{color:"#905"},tag:{color:"#905"},boolean:{color:"#905"},number:{color:"#905"},constant:{color:"#905"},symbol:{color:"#905"},deleted:{color:"#905"},selector:{color:"#690"},"attr-name":{color:"#690"},string:{color:"#690"},char:{color:"#690"},builtin:{color:"#690"},inserted:{color:"#690"},operator:{color:"#9a6e3a",background:"hsla(0, 0%, 100%, .5)"},entity:{color:"#9a6e3a",background:"hsla(0, 0%, 100%, .5)",cursor:"help"},url:{color:"#9a6e3a",background:"hsla(0, 0%, 100%, .5)"},".language-css .token.string":{color:"#9a6e3a",background:"hsla(0, 0%, 100%, .5)"},".style .token.string":{color:"#9a6e3a",background:"hsla(0, 0%, 100%, .5)"},atrule:{color:"#07a"},"attr-value":{color:"#07a"},keyword:{color:"#07a"},function:{color:"#DD4A68"},"class-name":{color:"#DD4A68"},regex:{color:"#e90"},important:{color:"#e90",fontWeight:"bold"},variable:{color:"#e90"},bold:{fontWeight:"bold"},italic:{fontStyle:"italic"}};var gu=n(98695),gc=n.n(gu);let gl=["abap","abnf","actionscript","ada","agda","al","antlr4","apacheconf","apl","applescript","aql","arduino","arff","asciidoc","asm6502","aspnet","autohotkey","autoit","bash","basic","batch","bbcode","birb","bison","bnf","brainfuck","brightscript","bro","bsl","c","cil","clike","clojure","cmake","coffeescript","concurnas","cpp","crystal","csharp","csp","css-extras","css","cypher","d","dart","dax","dhall","diff","django","dns-zone-file","docker","ebnf","editorconfig","eiffel","ejs","elixir","elm","erb","erlang","etlua","excel-formula","factor","firestore-security-rules","flow","fortran","fsharp","ftl","gcode","gdscript","gedcom","gherkin","git","glsl","gml","go","graphql","groovy","haml","handlebars","haskell","haxe","hcl","hlsl","hpkp","hsts","http","ichigojam","icon","iecst","ignore","inform7","ini","io","j","java","javadoc","javadoclike","javascript","javastacktrace","jolie","jq","js-extras","js-templates","jsdoc","json","json5","jsonp","jsstacktrace","jsx","julia","keyman","kotlin","latex","latte","less","lilypond","liquid","lisp","livescript","llvm","lolcode","lua","makefile","markdown","markup-templating","markup","matlab","mel","mizar","mongodb","monkey","moonscript","n1ql","n4js","nand2tetris-hdl","naniscript","nasm","neon","nginx","nim","nix","nsis","objectivec","ocaml","opencl","oz","parigp","parser","pascal","pascaligo","pcaxis","peoplecode","perl","php-extras","php","phpdoc","plsql","powerquery","powershell","processing","prolog","properties","protobuf","pug","puppet","pure","purebasic","purescript","python","q","qml","qore","r","racket","reason","regex","renpy","rest","rip","roboconf","robotframework","ruby","rust","sas","sass","scala","scheme","scss","shell-session","smali","smalltalk","smarty","sml","solidity","solution-file","soy","sparql","splunk-spl","sqf","sql","stan","stylus","swift","t4-cs","t4-templating","t4-vb","tap","tcl","textile","toml","tsx","tt2","turtle","twig","typescript","typoscript","unrealscript","vala","vbnet","velocity","verilog","vhdl","vim","visual-basic","warpscript","wasm","wiki","xeora","xml-doc","xojo","xquery","yaml","yang","zig"];var gf=go(gc(),gs);gf.supportedLanguages=gl;let gd=gf;var gh=n(64566);function gp(e,t){return t||(t=e.slice(0)),Object.freeze(Object.defineProperties(e,{raw:{value:Object.freeze(t)}}))}function gb(){var e=gp(["\n query FetchConfigV2 {\n configv2 {\n user\n effective\n }\n }\n"]);return gb=function(){return e},e}var gm=n0(gb()),gg=function(e){var t=e.children;return l.createElement(ir.Z,null,l.createElement(r7.default,{component:"th",scope:"row",colSpan:3},t))},gv=function(){return l.createElement(gg,null,"...")},gy=function(e){var t=e.children;return l.createElement(gg,null,t)},gw=function(e){var t=e.loading,n=e.toml,r=e.error,i=void 0===r?"":r,a=e.title,o=e.expanded;if(i)return l.createElement(gy,null,i);if(t)return l.createElement(gv,null);a||(a="TOML");var s={display:"block"};return l.createElement(x.default,null,l.createElement(mP.Z,{defaultExpanded:o},l.createElement(mR.Z,{expandIcon:l.createElement(gh.Z,null)},a),l.createElement(mj.Z,{style:s},l.createElement(gd,{language:"toml",style:gs},n))))},g_=function(){var e=rv(gm,{fetchPolicy:"cache-and-network"}),t=e.data,n=e.loading,r=e.error;return(null==t?void 0:t.configv2.effective)=="N/A"?l.createElement(l.Fragment,null,l.createElement(d.Z,{item:!0,xs:12},l.createElement(r5.Z,null,l.createElement(sl.Z,{title:"TOML Configuration"}),l.createElement(gw,{title:"V2 config dump:",error:null==r?void 0:r.message,loading:n,toml:null==t?void 0:t.configv2.user,showHead:!0})))):l.createElement(l.Fragment,null,l.createElement(d.Z,{container:!0},l.createElement(d.Z,{item:!0,xs:12},l.createElement(r5.Z,null,l.createElement(sl.Z,{title:"TOML Configuration"}),l.createElement(gw,{title:"User specified:",error:null==r?void 0:r.message,loading:n,toml:null==t?void 0:t.configv2.user,showHead:!0,expanded:!0}),l.createElement(gw,{title:"Effective (with defaults):",error:null==r?void 0:r.message,loading:n,toml:null==t?void 0:t.configv2.effective,showHead:!0})))))},gE=n(34823),gS=function(e){return(0,b.createStyles)({cell:{paddingTop:1.5*e.spacing.unit,paddingBottom:1.5*e.spacing.unit}})},gk=(0,b.withStyles)(gS)(function(e){var t=e.classes,n=(0,A.I0)();(0,l.useEffect)(function(){n((0,ty.DQ)())});var r=(0,A.v9)(gE.N,A.wU);return l.createElement(r5.Z,null,l.createElement(sl.Z,{title:"Node"}),l.createElement(r8.Z,null,l.createElement(r9.Z,null,l.createElement(ir.Z,null,l.createElement(r7.default,{className:t.cell},l.createElement(x.default,null,"Version"),l.createElement(x.default,{variant:"subtitle1",color:"textSecondary"},r.version))),l.createElement(ir.Z,null,l.createElement(r7.default,{className:t.cell},l.createElement(x.default,null,"SHA"),l.createElement(x.default,{variant:"subtitle1",color:"textSecondary"},r.commitSHA))))))}),gx=function(){return l.createElement(ig,null,l.createElement(d.Z,{container:!0},l.createElement(d.Z,{item:!0,sm:12,md:8},l.createElement(d.Z,{container:!0},l.createElement(g_,null))),l.createElement(d.Z,{item:!0,sm:12,md:4},l.createElement(d.Z,{container:!0},l.createElement(d.Z,{item:!0,xs:12},l.createElement(gk,null)),l.createElement(d.Z,{item:!0,xs:12},l.createElement(mN,null)),l.createElement(d.Z,{item:!0,xs:12},l.createElement(mE,null))))))},gT=function(){return l.createElement(gx,null)},gM=function(){return l.createElement(gT,null)},gO=n(44431),gA=1e18,gL=function(e){return new gO.BigNumber(e).dividedBy(gA).toFixed(8)},gC=function(e){var t=e.keys,n=e.chainID,r=e.hideHeaderTitle;return l.createElement(l.Fragment,null,l.createElement(sl.Z,{title:!r&&"Account Balances",subheader:"Chain ID "+n}),l.createElement(aW.Z,null,l.createElement(w.default,{dense:!1,disablePadding:!0},t&&t.map(function(e,r){return l.createElement(l.Fragment,null,l.createElement(_.default,{disableGutters:!0,key:["acc-balance",n.toString(),r.toString()].join("-")},l.createElement(E.Z,{primary:l.createElement(l.Fragment,null,l.createElement(d.Z,{container:!0,spacing:16},l.createElement(d.Z,{item:!0,xs:12},l.createElement(op,{title:"Address"}),l.createElement(ob,{value:e.address})),l.createElement(d.Z,{item:!0,xs:6},l.createElement(op,{title:"Native Token Balance"}),l.createElement(ob,{value:e.ethBalance||"--"})),l.createElement(d.Z,{item:!0,xs:6},l.createElement(op,{title:"LINK Balance"}),l.createElement(ob,{value:e.linkBalance?gL(e.linkBalance):"--"}))))})),r+1s&&l.createElement(gB.Z,null,l.createElement(ir.Z,null,l.createElement(r7.default,{className:r.footer},l.createElement(aA.Z,{href:"/runs",component:tz},"View More"))))))});function vt(e,t){return t||(t=e.slice(0)),Object.freeze(Object.defineProperties(e,{raw:{value:Object.freeze(t)}}))}function vn(){var e=vt(["\n ","\n query FetchRecentJobRuns($offset: Int, $limit: Int) {\n jobRuns(offset: $offset, limit: $limit) {\n results {\n ...RecentJobRunsPayload_ResultsFields\n }\n metadata {\n total\n }\n }\n }\n"]);return vn=function(){return e},e}var vr=5,vi=n0(vn(),g9),va=function(){var e=rv(vi,{variables:{offset:0,limit:vr},fetchPolicy:"cache-and-network"}),t=e.data,n=e.loading,r=e.error;return l.createElement(ve,{data:t,errorMsg:null==r?void 0:r.message,loading:n,maxRunsSize:vr})},vo=function(e){return(0,b.createStyles)({style:{textAlign:"center",padding:2.5*e.spacing.unit,position:"fixed",left:"0",bottom:"0",width:"100%",borderRadius:0},bareAnchor:{color:e.palette.common.black,textDecoration:"none"}})},vs=(0,b.withStyles)(vo)(function(e){var t=e.classes,n=(0,A.v9)(gE.N,A.wU),r=(0,A.I0)();return(0,l.useEffect)(function(){r((0,ty.DQ)())}),l.createElement(ii.default,{className:t.style},l.createElement(x.default,null,"Chainlink Node ",n.version," at commit"," ",l.createElement("a",{target:"_blank",rel:"noopener noreferrer",href:"https://github.com/smartcontractkit/chainlink/commit/".concat(n.commitSHA),className:t.bareAnchor},n.commitSHA)))}),vu=function(e){return(0,b.createStyles)({cell:{borderColor:e.palette.divider,borderTop:"1px solid",borderBottom:"none",paddingTop:2*e.spacing.unit,paddingBottom:2*e.spacing.unit,paddingLeft:2*e.spacing.unit},block:{display:"block"},overflowEllipsis:{textOverflow:"ellipsis",overflow:"hidden"}})},vc=(0,b.withStyles)(vu)(function(e){var t=e.classes,n=e.job;return l.createElement(ir.Z,null,l.createElement(r7.default,{scope:"row",className:t.cell},l.createElement(d.Z,{container:!0,spacing:0},l.createElement(d.Z,{item:!0,xs:12},l.createElement(ih,{href:"/jobs/".concat(n.id),classes:{linkContent:t.block}},l.createElement(x.default,{className:t.overflowEllipsis,variant:"body1",component:"span",color:"primary"},n.name||n.id))),l.createElement(d.Z,{item:!0,xs:12},l.createElement(x.default,{variant:"body1",color:"textSecondary"},"Created ",l.createElement(aO,{tooltip:!0},n.createdAt))))))});function vl(e,t){return t||(t=e.slice(0)),Object.freeze(Object.defineProperties(e,{raw:{value:Object.freeze(t)}}))}function vf(){var e=vl(["\n fragment RecentJobsPayload_ResultsFields on Job {\n id\n name\n createdAt\n }\n"]);return vf=function(){return e},e}var vd=n0(vf()),vh=function(){return(0,b.createStyles)({cardHeader:{borderBottom:0},table:{tableLayout:"fixed"}})},vp=(0,b.withStyles)(vh)(function(e){var t,n,r=e.classes,i=e.data,a=e.errorMsg,o=e.loading;return l.createElement(r5.Z,null,l.createElement(sl.Z,{title:"Recent Jobs",className:r.cardHeader}),l.createElement(r8.Z,{className:r.table},l.createElement(r9.Z,null,l.createElement(g$,{visible:o}),l.createElement(gz,{visible:(null===(t=null==i?void 0:i.jobs.results)||void 0===t?void 0:t.length)===0},"No recently created jobs"),l.createElement(gU,{msg:a}),null===(n=null==i?void 0:i.jobs.results)||void 0===n?void 0:n.map(function(e,t){return l.createElement(vc,{job:e,key:t})}))))});function vb(e,t){return t||(t=e.slice(0)),Object.freeze(Object.defineProperties(e,{raw:{value:Object.freeze(t)}}))}function vm(){var e=vb(["\n ","\n query FetchRecentJobs($offset: Int, $limit: Int) {\n jobs(offset: $offset, limit: $limit) {\n results {\n ...RecentJobsPayload_ResultsFields\n }\n }\n }\n"]);return vm=function(){return e},e}var vg=5,vv=n0(vm(),vd),vy=function(){var e=rv(vv,{variables:{offset:0,limit:vg},fetchPolicy:"cache-and-network"}),t=e.data,n=e.loading,r=e.error;return l.createElement(vp,{data:t,errorMsg:null==r?void 0:r.message,loading:n})},vw=function(){return l.createElement(ig,null,l.createElement(d.Z,{container:!0},l.createElement(d.Z,{item:!0,xs:8},l.createElement(va,null)),l.createElement(d.Z,{item:!0,xs:4},l.createElement(d.Z,{container:!0},l.createElement(d.Z,{item:!0,xs:12},l.createElement(gY,null)),l.createElement(d.Z,{item:!0,xs:12},l.createElement(vy,null))))),l.createElement(vs,null))},v_=function(){return l.createElement(vw,null)},vE=function(){return l.createElement(v_,null)},vS=n(87239),vk=function(e){switch(e){case"DirectRequestSpec":return"Direct Request";case"FluxMonitorSpec":return"Flux Monitor";default:return e.replace(/Spec$/,"")}},vx=n(5022),vT=n(78718),vM=n.n(vT);function vO(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n1?t-1:0),r=1;r1?t-1:0),r=1;re.length)&&(t=e.length);for(var n=0,r=Array(t);ne.length)&&(t=e.length);for(var n=0,r=Array(t);ne.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&n.map(function(e){return l.createElement(ir.Z,{key:e.id,style:{cursor:"pointer"},onClick:function(){return r.push("/runs/".concat(e.id))}},l.createElement(r7.default,{className:t.idCell,scope:"row"},l.createElement("div",{className:t.runDetails},l.createElement(x.default,{variant:"h5",color:"primary",component:"span"},e.id))),l.createElement(r7.default,{className:t.stampCell},l.createElement(x.default,{variant:"body1",color:"textSecondary",className:t.stamp},"Created ",l.createElement(aO,{tooltip:!0},e.createdAt))),l.createElement(r7.default,{className:t.statusCell,scope:"row"},l.createElement(x.default,{variant:"body1",className:O()(t.status,yh(t,e.status))},e.status.toLowerCase())))})))}),yb=n(16839),ym=n.n(yb);function yg(e){var t=e.replace(/\w+\s*=\s*<([^>]|[\r\n])*>/g,""),n=ym().read(t),r=n.edges();return n.nodes().map(function(e){var t={id:e,parentIds:r.filter(function(t){return t.w===e}).map(function(e){return e.v})};return Object.keys(n.node(e)).length>0&&(t.attributes=n.node(e)),t})}var yv=n(94164),yy=function(e){var t=e.data,n=[];return(null==t?void 0:t.attributes)&&Object.keys(t.attributes).forEach(function(e){var r;n.push(l.createElement("div",{key:e},l.createElement(x.default,{variant:"body1",color:"textSecondary",component:"div"},l.createElement("b",null,e,":")," ",null===(r=t.attributes)||void 0===r?void 0:r[e])))}),l.createElement("div",null,t&&l.createElement(x.default,{variant:"body1",color:"textPrimary"},l.createElement("b",null,t.id)),n)},yw=n(73343),y_=n(3379),yE=n.n(y_);function yS(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);nwindow.innerWidth?u-r.getBoundingClientRect().width-a:u+a,n=c+r.getBoundingClientRect().height+i>window.innerHeight?c-r.getBoundingClientRect().height-a:c+a,r.style.opacity=String(1),r.style.top="".concat(n,"px"),r.style.left="".concat(t,"px"),r.style.zIndex=String(1)}},h=function(e){var t=document.getElementById("tooltip-d3-chart-".concat(e));t&&(t.style.opacity=String(0),t.style.zIndex=String(-1))};return l.createElement("div",{style:{fontFamily:"sans-serif",fontWeight:"normal"}},l.createElement(yv.kJ,{id:"task-list-graph-d3",data:i,config:s,onMouseOverNode:d,onMouseOutNode:h},"D3 chart"),n.map(function(e){return l.createElement("div",{key:"d3-tooltip-key-".concat(e.id),id:"tooltip-d3-chart-".concat(e.id),style:{position:"absolute",opacity:"0",border:"1px solid rgba(0, 0, 0, 0.1)",padding:yw.r.spacing.unit,background:"white",borderRadius:5,zIndex:-1,inlineSize:"min-content"}},l.createElement(yy,{data:e}))}))};function yL(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);nyY&&l.createElement("div",{className:t.runDetails},l.createElement(aA.Z,{href:"/jobs/".concat(n.id,"/runs"),component:tz},"View more")))),l.createElement(d.Z,{item:!0,xs:12,sm:6},l.createElement(yF,{observationSource:n.observationSource})))});function yH(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);ne.length)&&(t=e.length);for(var n=0,r=Array(t);ne.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]e.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&void 0!==arguments[0]?arguments[0]:"";try{return vx.parse(e),!0}catch(t){return!1}})}),wW=function(e){var t=e.initialValues,n=e.onSubmit,r=e.onTOMLChange;return l.createElement(hT,{initialValues:t,validationSchema:wG,onSubmit:n},function(e){var t=e.isSubmitting,n=e.values;return r&&r(n.toml),l.createElement(hR,{"data-testid":"job-form",noValidate:!0},l.createElement(d.Z,{container:!0,spacing:16},l.createElement(d.Z,{item:!0,xs:12},l.createElement(hP,{component:hX,id:"toml",name:"toml",label:"Job Spec (TOML)",required:!0,fullWidth:!0,multiline:!0,rows:10,rowsMax:25,variant:"outlined",autoComplete:"off",FormHelperTextProps:{"data-testid":"toml-helper-text"}})),l.createElement(d.Z,{item:!0,xs:12,md:7},l.createElement(ok.default,{variant:"contained",color:"primary",type:"submit",disabled:t,size:"large"},"Create Job"))))})},wK=n(50109),wV="persistSpec";function wq(e){var t=e.query,n=new URLSearchParams(t).get("definition");return n?(wK.t8(wV,n),{toml:n}):{toml:wK.U2(wV)||""}}var wZ=function(e){var t=e.onSubmit,n=e.onTOMLChange,r=wq({query:(0,h.TH)().search}),i=function(e){var t=e.replace(/[\u200B-\u200D\uFEFF]/g,"");wK.t8("".concat(wV),t),n&&n(t)};return l.createElement(r5.Z,null,l.createElement(sl.Z,{title:"New Job"}),l.createElement(aW.Z,null,l.createElement(wW,{initialValues:r,onSubmit:t,onTOMLChange:i})))};function wX(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);ne.length)&&(t=e.length);for(var n=0,r=Array(t);ne.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]e.length)&&(t=e.length);for(var n=0,r=Array(t);n1&&void 0!==arguments[1]?arguments[1]:{},n=t.start,r=void 0===n?6:n,i=t.end,a=void 0===i?4:i;return e.substring(0,r)+"..."+e.substring(e.length-a)}function _M(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]0&&void 0!==arguments[0]?arguments[0]:{};return rv(_W,e)},_V=function(){var e=_K({fetchPolicy:"cache-and-network"}),t=e.data,n=e.loading,r=e.error,i=e.refetch;return l.createElement(_U,{loading:n,data:t,errorMsg:null==r?void 0:r.message,refetch:i})},_q=function(e){var t=e.csaKey;return l.createElement(ir.Z,{hover:!0},l.createElement(r7.default,null,l.createElement(x.default,{variant:"body1"},t.publicKey," ",l.createElement(_x,{data:t.publicKey}))))};function _Z(e,t){return t||(t=e.slice(0)),Object.freeze(Object.defineProperties(e,{raw:{value:Object.freeze(t)}}))}function _X(){var e=_Z(["\n fragment CSAKeysPayload_ResultsFields on CSAKey {\n id\n publicKey\n }\n"]);return _X=function(){return e},e}var _J=n0(_X()),_Q=function(e){var t,n,r,i=e.data,a=e.errorMsg,o=e.loading,s=e.onCreate;return l.createElement(r5.Z,null,l.createElement(sl.Z,{action:(null===(t=null==i?void 0:i.csaKeys.results)||void 0===t?void 0:t.length)===0&&l.createElement(ok.default,{variant:"outlined",color:"primary",onClick:s},"New CSA Key"),title:"CSA Key",subheader:"Manage your CSA Key"}),l.createElement(r8.Z,null,l.createElement(ie.Z,null,l.createElement(ir.Z,null,l.createElement(r7.default,null,"Public Key"))),l.createElement(r9.Z,null,l.createElement(g$,{visible:o}),l.createElement(gz,{visible:(null===(n=null==i?void 0:i.csaKeys.results)||void 0===n?void 0:n.length)===0}),l.createElement(gU,{msg:a}),null===(r=null==i?void 0:i.csaKeys.results)||void 0===r?void 0:r.map(function(e,t){return l.createElement(_q,{csaKey:e,key:t})}))))};function _1(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]e.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]0&&void 0!==arguments[0]?arguments[0]:{};return rv(EM,e)};function EA(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]0&&void 0!==arguments[0]?arguments[0]:{};return rv(EJ,e)},E3=function(){return oo(EQ)},E4=function(){return oo(E1)},E6=function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};return rv(E0,e)};function E5(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);ne.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]e.length)&&(t=e.length);for(var n=0,r=Array(t);ne.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]e.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]0&&void 0!==arguments[0]?arguments[0]:{};return rv(SK,e)};function Sq(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]e.length)&&(t=e.length);for(var n=0,r=Array(t);n=0)&&Object.prototype.propertyIsEnumerable.call(e,n)&&(i[n]=e[n])}return i}function kV(e,t){if(null==e)return{};var n,r,i={},a=Object.keys(e);for(r=0;r=0||(i[n]=e[n]);return i}var kq=function(e){var t=e.run,n=l.useMemo(function(){var e=t.inputs,n=t.outputs,r=t.taskRuns,i=kK(t,["inputs","outputs","taskRuns"]),a={};try{a=JSON.parse(e)}catch(o){a={}}return kW(kz({},i),{inputs:a,outputs:n,taskRuns:r})},[t]);return l.createElement(r5.Z,null,l.createElement(aW.Z,null,l.createElement(kH,{object:n})))};function kZ(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function kX(e){for(var t=1;t0&&l.createElement(kr,{errors:t.allErrors})),l.createElement(d.Z,{item:!0,xs:12},l.createElement(h.rs,null,l.createElement(h.AW,{path:"".concat(n,"/json")},l.createElement(kq,{run:t})),l.createElement(h.AW,{path:n},t.taskRuns.length>0&&l.createElement(kN,{taskRuns:t.taskRuns,observationSource:t.job.observationSource}))))))))};function k5(e,t){return t||(t=e.slice(0)),Object.freeze(Object.defineProperties(e,{raw:{value:Object.freeze(t)}}))}function k8(){var e=k5(["\n ","\n query FetchJobRun($id: ID!) {\n jobRun(id: $id) {\n __typename\n ... on JobRun {\n ...JobRunPayload_Fields\n }\n ... on NotFoundError {\n message\n }\n }\n }\n"]);return k8=function(){return e},e}var k9=n0(k8(),k4),k7=function(){var e=rv(k9,{variables:{id:(0,h.UO)().id}}),t=e.data,n=e.loading,r=e.error;if(n)return l.createElement(iR,null);if(r)return l.createElement(iD,{error:r});var i=null==t?void 0:t.jobRun;switch(null==i?void 0:i.__typename){case"JobRun":return l.createElement(k6,{run:i});case"NotFoundError":return l.createElement(oa,null);default:return null}};function xe(e,t){return t||(t=e.slice(0)),Object.freeze(Object.defineProperties(e,{raw:{value:Object.freeze(t)}}))}function xt(){var e=xe(["\n fragment JobRunsPayload_ResultsFields on JobRun {\n id\n allErrors\n createdAt\n finishedAt\n status\n job {\n id\n }\n }\n"]);return xt=function(){return e},e}var xn=n0(xt()),xr=function(e){var t=e.loading,n=e.data,r=e.page,i=e.pageSize,a=(0,h.k6)(),o=l.useMemo(function(){return null==n?void 0:n.jobRuns.results.map(function(e){var t,n=e.allErrors,r=e.id,i=e.createdAt;return{id:r,createdAt:i,errors:n,finishedAt:e.finishedAt,status:e.status}})},[n]);return l.createElement(ig,null,l.createElement(d.Z,{container:!0,spacing:32},l.createElement(d.Z,{item:!0,xs:12},l.createElement(iy,null,"Job Runs")),t&&l.createElement(iR,null),n&&o&&l.createElement(d.Z,{item:!0,xs:12},l.createElement(r5.Z,null,l.createElement(yp,{runs:o}),l.createElement(it.Z,{component:"div",count:n.jobRuns.metadata.total,rowsPerPage:i,rowsPerPageOptions:[i],page:r-1,onChangePage:function(e,t){a.push("/runs?page=".concat(t+1,"&per=").concat(i))},onChangeRowsPerPage:function(){},backIconButtonProps:{"aria-label":"prev-page"},nextIconButtonProps:{"aria-label":"next-page"}})))))};function xi(e,t){return t||(t=e.slice(0)),Object.freeze(Object.defineProperties(e,{raw:{value:Object.freeze(t)}}))}function xa(){var e=xi(["\n ","\n query FetchJobRuns($offset: Int, $limit: Int) {\n jobRuns(offset: $offset, limit: $limit) {\n results {\n ...JobRunsPayload_ResultsFields\n }\n metadata {\n total\n }\n }\n }\n"]);return xa=function(){return e},e}var xo=n0(xa(),xn),xs=function(){var e=ij(),t=parseInt(e.get("page")||"1",10),n=parseInt(e.get("per")||"25",10),r=rv(xo,{variables:{offset:(t-1)*n,limit:n},fetchPolicy:"cache-and-network"}),i=r.data,a=r.loading,o=r.error;return o?l.createElement(iD,{error:o}):l.createElement(xr,{loading:a,data:i,page:t,pageSize:n})},xu=function(){var e=(0,h.$B)().path;return l.createElement(h.rs,null,l.createElement(h.AW,{exact:!0,path:e},l.createElement(xs,null)),l.createElement(h.AW,{path:"".concat(e,"/:id")},l.createElement(k7,null)))};function xc(e,t){return t||(t=e.slice(0)),Object.freeze(Object.defineProperties(e,{raw:{value:Object.freeze(t)}}))}function xl(){var e=xc(["\n fragment FetchFeedsManagersPayload_ResultsFields on FeedsManager {\n __typename\n id\n name\n uri\n publicKey\n isConnectionActive\n createdAt\n disabledAt\n }\n query FetchFeedsManagers {\n feedsManagers {\n results {\n ...FetchFeedsManagersPayload_ResultsFields\n }\n }\n }\n"]);return xl=function(){return e},e}var xf=n0(xl()),xd=function(e){return rv(xf,e)},xh=n(47559),xp=n(83165),xb=n(47298),xm=n(81395),xg=function(){return(0,b.createStyles)({root:{display:"flex"},activeIcon:{color:xh.default[500]},inactiveIcon:{color:xp.default[500]},text:{marginLeft:4}})},xv=(0,b.withStyles)(xg)(function(e){var t=e.isActive,n=e.activeText,r=e.inactiveText,i=e.classes;return l.createElement("div",{className:i.root},t?l.createElement(xm.Z,{fontSize:"small",className:i.activeIcon}):l.createElement(xb.Z,{fontSize:"small",className:i.inactiveIcon}),l.createElement(x.default,{variant:"body1",inline:!0,className:i.text},t?n:r))}),xy=(0,b.withStyles)(iu)(function(e){var t=e.jobDistributor,n=e.classes;return l.createElement(ir.Z,{className:n.row,hover:!0},l.createElement(r7.default,{className:n.cell,component:"th",scope:"row"},l.createElement(ih,{className:n.link,href:"/job_distributors/".concat(t.id)},t.name)),l.createElement(r7.default,null,l.createElement(xv,{isActive:t.isConnectionActive,activeText:"Connected",inactiveText:"Disconnected"})),l.createElement(r7.default,null,l.createElement(xv,{isActive:!t.disabledAt,activeText:"Enabled",inactiveText:"Disabled"})),l.createElement(r7.default,null,_T(t.publicKey,{start:6,end:6}),l.createElement(_x,{data:t.publicKey})),l.createElement(r7.default,null,t.uri))}),xw=function(e){var t=e.jobDistributors;return l.createElement(ig,null,l.createElement(d.Z,{container:!0},l.createElement(d.Z,{item:!0,xs:9},l.createElement(iy,null,"Job Distributors")),l.createElement(d.Z,{item:!0,xs:3},l.createElement(d.Z,{container:!0,justify:"flex-end"},l.createElement(d.Z,{item:!0},l.createElement(aA.Z,{variant:"secondary",component:tz,href:"/job_distributors/new"},"New Job Distributor")))),l.createElement(d.Z,{item:!0,xs:12},l.createElement(r5.Z,null,l.createElement(r8.Z,null,l.createElement(ie.Z,null,l.createElement(ir.Z,null,l.createElement(r7.default,null,"Name"),l.createElement(r7.default,null,"Connection Status"),l.createElement(r7.default,null,"Status"),l.createElement(r7.default,null,"CSA Public Key"),l.createElement(r7.default,null,"RPC URL"))),l.createElement(r9.Z,null,0===t.length&&l.createElement(ir.Z,null,l.createElement(r7.default,{component:"th",scope:"row",colSpan:3},"Job Distributors have not been registered")),t.map(function(e){return l.createElement(xy,{key:e.id,jobDistributor:e})})))))))},x_=function(){var e,t=xd({fetchPolicy:"cache-and-network"}),n=t.data,r=t.loading,i=t.error;return r?l.createElement(iR,null):i?l.createElement(iD,{error:i}):l.createElement(xw,{jobDistributors:null!==(e=null==n?void 0:n.feedsManagers.results)&&void 0!==e?e:[]})},xE=bv().shape({name:p0().required("Required"),uri:p0().required("Required"),publicKey:p0().required("Required")}),xS=function(e){var t=e.initialValues,n=e.onSubmit;return l.createElement(hT,{initialValues:t,validationSchema:xE,onSubmit:n},function(e){var t=e.isSubmitting,n=e.submitForm;return l.createElement(hR,{"data-testid":"feeds-manager-form"},l.createElement(d.Z,{container:!0,spacing:16},l.createElement(d.Z,{item:!0,xs:12,md:6},l.createElement(hP,{component:hX,id:"name",name:"name",label:"Name",required:!0,fullWidth:!0,FormHelperTextProps:{"data-testid":"name-helper-text"}})),l.createElement(d.Z,{item:!0,xs:!1,md:6}),l.createElement(d.Z,{item:!0,xs:12,md:6},l.createElement(hP,{component:hX,id:"uri",name:"uri",label:"URI",required:!0,fullWidth:!0,helperText:"Provided by the Job Distributor operator",FormHelperTextProps:{"data-testid":"uri-helper-text"}})),l.createElement(d.Z,{item:!0,xs:12,md:6},l.createElement(hP,{component:hX,id:"publicKey",name:"publicKey",label:"Public Key",required:!0,fullWidth:!0,helperText:"Provided by the Job Distributor operator",FormHelperTextProps:{"data-testid":"publicKey-helper-text"}})),l.createElement(d.Z,{item:!0,xs:12},l.createElement(ok.default,{variant:"contained",color:"primary",disabled:t,onClick:n},"Submit"))))})},xk=function(e){var t=e.data,n=e.onSubmit,r={name:t.name,uri:t.uri,publicKey:t.publicKey};return l.createElement(d.Z,{container:!0},l.createElement(d.Z,{item:!0,xs:12,md:11,lg:9},l.createElement(r5.Z,null,l.createElement(sl.Z,{title:"Edit Job Distributor"}),l.createElement(aW.Z,null,l.createElement(xS,{initialValues:r,onSubmit:n})))))};function xx(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]0&&void 0!==arguments[0]?arguments[0]:{};return rv(xZ,e)},xJ=function(){return(0,b.createStyles)({root:{fontSize:24}})},xQ=(0,b.withStyles)(xJ)(function(e){var t=e.children,n=e.classes;return l.createElement(x.default,{variant:"h2",className:n.root},t)}),x1=n(9290),x0=n(74923);function x2(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);ne.length)&&(t=e.length);for(var n=0,r=Array(t);ne.length)&&(t=e.length);for(var n=0,r=Array(t);n=0)&&Object.prototype.propertyIsEnumerable.call(e,n)&&(i[n]=e[n])}return i}function TT(e,t){if(null==e)return{};var n,r,i={},a=Object.keys(e);for(r=0;r=0||(i[n]=e[n]);return i}function TM(e,t){return Tv(e)||TE(e,t)||TA(e,t)||TS()}function TO(e){return Ty(e)||T_(e)||TA(e)||Tk()}function TA(e,t){if(e){if("string"==typeof e)return Tg(e,t);var n=Object.prototype.toString.call(e).slice(8,-1);if("Object"===n&&e.constructor&&(n=e.constructor.name),"Map"===n||"Set"===n)return Array.from(n);if("Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n))return Tg(e,t)}}var TL=function(e){return"SN_MAIN"===e||"SN_SEPOLIA"===e},TC=bv().shape({chainID:p0().required("Required"),chainType:p0().required("Required"),accountAddr:p0().required("Required"),accountAddrPubKey:p0().nullable(),adminAddr:p0(),ocr1Multiaddr:p0().when(["ocr1Enabled","ocr1IsBootstrap"],{is:function(e,t){return e&&t},then:p0().required("Required").nullable()}).nullable(),ocr1P2PPeerID:p0().when(["ocr1Enabled","ocr1IsBootstrap"],{is:function(e,t){return e&&!t},then:p0().required("Required").nullable()}).nullable(),ocr1KeyBundleID:p0().when(["ocr1Enabled","ocr1IsBootstrap"],{is:function(e,t){return e&&!t},then:p0().required("Required").nullable()}).nullable(),ocr2Multiaddr:p0().when(["ocr2Enabled","ocr2IsBootstrap"],{is:function(e,t){return e&&t},then:p0().required("Required").nullable()}).nullable(),ocr2P2PPeerID:p0().when(["ocr2Enabled","ocr2IsBootstrap"],{is:function(e,t){return e&&!t},then:p0().required("Required").nullable()}).nullable(),ocr2KeyBundleID:p0().when(["ocr2Enabled","ocr2IsBootstrap"],{is:function(e,t){return e&&!t},then:p0().required("Required").nullable()}).nullable(),ocr2CommitPluginEnabled:pV().required("Required"),ocr2ExecutePluginEnabled:pV().required("Required"),ocr2MedianPluginEnabled:pV().required("Required"),ocr2MercuryPluginEnabled:pV().required("Required"),ocr2ForwarderAddress:p0().nullable()}),TI=function(e){return(0,b.createStyles)({supportedJobOptionsPaper:{padding:2*e.spacing.unit}})},TD=function(e){var t=e.addresses,n=Tx(e,["addresses"]),r=h_(),i=r.values,a=i.chainID,o=i.accountAddr,s=r.setFieldValue,u=TM(l.useState(!1),2),c=u[0],f=u[1],d=l.useRef();l.useEffect(function(){d.current=a},[a]),l.useEffect(function(){a!==d.current&&(s(n.name,""),f(!1))},[a,s,n.name]);var h=function(e){var t=e.target.value;"custom"===t?(f(!0),s(n.name,"")):(f(!1),s(n.name,t))};return l.createElement(l.Fragment,null,!TL(a)&&l.createElement(hP,Tw({},n,{select:!0,value:c?"custom":o,onChange:h}),t.map(function(e){return l.createElement(tE.default,{key:e,value:e},e)})),TL(a)&&l.createElement(hP,{component:hX,id:"accountAddr",name:"accountAddr",label:"Enter your account address",inputProps:{"data-testid":"customAccountAddr-input"},helperText:"The account address used for this chain",required:!0,fullWidth:!0}),TL(a)&&l.createElement("div",null,l.createElement(hP,{component:hX,id:"accountAddrPubKey",name:"accountAddrPubKey",label:"Account Address Public Key",required:!0,fullWidth:!0,helperText:"The public key for your account address",FormHelperTextProps:{"data-testid":"accountAddrPubKey-helper-text"}})))},TN=(0,b.withStyles)(TI)(function(e){var t=e.classes,n=e.editing,r=void 0!==n&&n,i=e.innerRef,a=e.initialValues,o=e.onSubmit,s=e.chains,u=void 0===s?[]:s,c=e.accountsEVM,f=void 0===c?[]:c,h=e.accountsNonEvm,p=e.p2pKeys,b=void 0===p?[]:p,m=e.ocrKeys,g=void 0===m?[]:m,v=e.ocr2Keys,y=void 0===v?[]:v,w=e.showSubmit,_=void 0!==w&&w,E=TO(y).sort(function(e,t){var n,r,i;return e.chainType===t.chainType?e.id.localeCompare(t.id):null!==(i=null===(n=e.chainType)||void 0===n?void 0:n.localeCompare(null!==(r=t.chainType)&&void 0!==r?r:""))&&void 0!==i?i:0});return l.createElement(hT,{innerRef:i,initialValues:a,validationSchema:TC,onSubmit:o},function(e){var n,i,a=e.values,o=[];switch(a.chainType){case Tm.EVM:o=f.filter(function(e){return e.chain.id==a.chainID&&!e.isDisabled}).map(function(e){return e.address});break;case Tm.APTOS:o=null!==(n=null==h?void 0:h.aptosKeys.results.map(function(e){return e.account}))&&void 0!==n?n:[];break;case Tm.SOLANA:o=null!==(i=null==h?void 0:h.solanaKeys.results.map(function(e){return e.id}))&&void 0!==i?i:[];break;default:o=[]}var s=u.filter(function(e){return e.network.toUpperCase()===a.chainType});return l.createElement(hR,{"data-testid":"feeds-manager-form",id:"chain-configuration-form",noValidate:!0},l.createElement(d.Z,{container:!0,spacing:16},l.createElement(d.Z,{item:!0,xs:12,md:6},l.createElement(hP,{component:hX,id:"chainType",name:"chainType",label:"Chain Type",select:!0,required:!0,fullWidth:!0,disabled:r},l.createElement(tE.default,{key:Tm.EVM,value:Tm.EVM},"EVM"),l.createElement(tE.default,{key:Tm.APTOS,value:Tm.APTOS},"APTOS"),l.createElement(tE.default,{key:Tm.SOLANA,value:Tm.SOLANA},"SOLANA"))),l.createElement(d.Z,{item:!0,xs:12,md:6},s.length>0&&!r?l.createElement(hP,{component:hX,id:"chainID",name:"chainID",label:"Chain ID",required:!0,fullWidth:!0,select:!0,disabled:r,inputProps:{"data-testid":"chainID-input"},FormHelperTextProps:{"data-testid":"chainID-helper-text"}},s.map(function(e){return l.createElement(tE.default,{key:e.id,value:e.id},e.id)})):l.createElement(hP,{component:hX,id:"chainID",name:"chainID",label:"Chain ID",required:!0,fullWidth:!0,disabled:r,inputProps:{"data-testid":"chainID-manual-input"},FormHelperTextProps:{"data-testid":"chainID-helper-manual-text"}})),l.createElement(d.Z,{item:!0,xs:12,md:6},o.length>0?l.createElement(TD,{component:hX,id:"accountAddr",name:"accountAddr",label:"Account Address",inputProps:{"data-testid":"accountAddr-input"},required:!0,fullWidth:!0,select:!0,helperText:"The account address used for this chain",addresses:o,FormHelperTextProps:{"data-testid":"accountAddr-helper-text"}}):l.createElement(hP,{component:hX,id:"accountAddr",name:"accountAddr",label:"Account Address",inputProps:{"data-testid":"accountAddr-manual-input"},required:!0,fullWidth:!0,helperText:"The account address used for this chain",FormHelperTextProps:{"data-testid":"accountAddr-helper-manual-text"}})),l.createElement(d.Z,{item:!0,xs:12,md:6},l.createElement(hP,{component:hX,id:"adminAddr",name:"adminAddr",label:"Admin Address",fullWidth:!0,helperText:"The address used for LINK payments",FormHelperTextProps:{"data-testid":"adminAddr-helper-text"}})),l.createElement(d.Z,{item:!0,xs:12},l.createElement(x.default,null,"Supported Job Types")),l.createElement(d.Z,{item:!0,xs:12},l.createElement(hP,{component:h2,name:"fluxMonitorEnabled",type:"checkbox",Label:{label:"Flux Monitor"}})),l.createElement(d.Z,{item:!0,xs:12},l.createElement(hP,{component:h2,name:"ocr1Enabled",type:"checkbox",Label:{label:"OCR"}}),a.ocr1Enabled&&l.createElement(ii.default,{className:t.supportedJobOptionsPaper},l.createElement(d.Z,{container:!0,spacing:8},l.createElement(l.Fragment,null,l.createElement(d.Z,{item:!0,xs:12},l.createElement(hP,{component:h2,name:"ocr1IsBootstrap",type:"checkbox",Label:{label:"Is this node running as a bootstrap peer?"}})),a.ocr1IsBootstrap?l.createElement(d.Z,{item:!0,xs:12},l.createElement(hP,{component:hX,id:"ocr1Multiaddr",name:"ocr1Multiaddr",label:"Multiaddr",required:!0,fullWidth:!0,helperText:"The OCR Multiaddr which oracles use to query for network information",FormHelperTextProps:{"data-testid":"ocr1Multiaddr-helper-text"}})):l.createElement(l.Fragment,null,l.createElement(d.Z,{item:!0,xs:12,md:6},l.createElement(hP,{component:hX,id:"ocr1P2PPeerID",name:"ocr1P2PPeerID",label:"Peer ID",select:!0,required:!0,fullWidth:!0,helperText:"The Peer ID used for this chain",FormHelperTextProps:{"data-testid":"ocr1P2PPeerID-helper-text"}},b.map(function(e){return l.createElement(tE.default,{key:e.peerID,value:e.peerID},e.peerID)}))),l.createElement(d.Z,{item:!0,xs:12,md:6},l.createElement(hP,{component:hX,id:"ocr1KeyBundleID",name:"ocr1KeyBundleID",label:"Key Bundle ID",select:!0,required:!0,fullWidth:!0,helperText:"The OCR Key Bundle ID used for this chain",FormHelperTextProps:{"data-testid":"ocr1KeyBundleID-helper-text"}},g.map(function(e){return l.createElement(tE.default,{key:e.id,value:e.id},e.id)})))))))),l.createElement(d.Z,{item:!0,xs:12},l.createElement(hP,{component:h2,name:"ocr2Enabled",type:"checkbox",Label:{label:"OCR2"}}),a.ocr2Enabled&&l.createElement(ii.default,{className:t.supportedJobOptionsPaper},l.createElement(d.Z,{container:!0,spacing:8},l.createElement(l.Fragment,null,l.createElement(d.Z,{item:!0,xs:12},l.createElement(hP,{component:h2,name:"ocr2IsBootstrap",type:"checkbox",Label:{label:"Is this node running as a bootstrap peer?"}})),l.createElement(d.Z,{item:!0,xs:12,md:6},l.createElement(hP,{component:hX,id:"ocr2P2PPeerID",name:"ocr2P2PPeerID",label:"Peer ID",select:!0,required:!a.ocr2IsBootstrap,fullWidth:!0,helperText:"The Peer ID used for this chain",FormHelperTextProps:{"data-testid":"ocr2P2PPeerID-helper-text"}},b.map(function(e){return l.createElement(tE.default,{key:e.peerID,value:e.peerID},e.peerID)}))),a.ocr2IsBootstrap?l.createElement(d.Z,{item:!0,xs:12},l.createElement(hP,{component:hX,id:"ocr2Multiaddr",name:"ocr2Multiaddr",label:"Multiaddr",required:!0,fullWidth:!0,helperText:"The OCR2 Multiaddr which oracles use to query for network information",FormHelperTextProps:{"data-testid":"ocr2Multiaddr-helper-text"}})):l.createElement(l.Fragment,null,l.createElement(d.Z,{item:!0,xs:12,md:6},l.createElement(hP,{component:hX,id:"ocr2KeyBundleID",name:"ocr2KeyBundleID",label:"Key Bundle ID",select:!0,required:!0,fullWidth:!0,helperText:"The OCR2 Key Bundle ID used for this chain",FormHelperTextProps:{"data-testid":"ocr2KeyBundleID-helper-text"}},E.map(function(e){return l.createElement(tE.default,{key:e.id,value:e.id},e.id," (",e.chainType,")")}))),l.createElement(d.Z,{item:!0,xs:12},l.createElement(x.default,null,"Supported Plugins")),l.createElement(d.Z,{item:!0,xs:6},l.createElement(hP,{component:h2,name:"ocr2CommitPluginEnabled",type:"checkbox",Label:{label:"Commit"}})),l.createElement(d.Z,{item:!0,xs:6},l.createElement(hP,{component:h2,name:"ocr2ExecutePluginEnabled",type:"checkbox",Label:{label:"Execute"}})),l.createElement(d.Z,{item:!0,xs:6},l.createElement(hP,{component:h2,name:"ocr2RebalancerPluginEnabled",type:"checkbox",Label:{label:"Rebalancer"}})),l.createElement(d.Z,{item:!0,xs:6},l.createElement(hP,{component:h2,name:"ocr2MedianPluginEnabled",type:"checkbox",Label:{label:"Median"}})),l.createElement(d.Z,{item:!0,xs:6},l.createElement(hP,{component:h2,name:"ocr2MercuryPluginEnabled",type:"checkbox",Label:{label:"Mercury"}})),l.createElement(d.Z,{item:!0,xs:12,md:12},l.createElement(hP,{component:hX,id:"ocr2ForwarderAddress",name:"ocr2ForwarderAddress",label:"Forwarder Address (optional)",fullWidth:!0,helperText:"The forwarder address from the Operator Forwarder Contract",FormHelperTextProps:{"data-testid":"ocr2ForwarderAddress-helper-text"}}))))))),_&&l.createElement(d.Z,{item:!0,xs:12,md:7},l.createElement(ok.default,{variant:"contained",color:"primary",type:"submit",size:"large"},"Submit"))))})});function TP(e,t){return t||(t=e.slice(0)),Object.freeze(Object.defineProperties(e,{raw:{value:Object.freeze(t)}}))}function TR(){var e=TP(["\n fragment AptosKeysPayload_ResultsFields on AptosKey {\n account\n id\n }\n"]);return TR=function(){return e},e}function Tj(){var e=TP(["\n fragment SolanaKeysPayload_ResultsFields on SolanaKey {\n id\n }\n"]);return Tj=function(){return e},e}function TF(){var e=TP(["\n ","\n ","\n query FetchNonEvmKeys {\n aptosKeys {\n results {\n ...AptosKeysPayload_ResultsFields\n }\n }\n solanaKeys {\n results {\n ...SolanaKeysPayload_ResultsFields\n }\n }\n }\n"]);return TF=function(){return e},e}var TY=n0(TR()),TB=n0(Tj()),TU=n0(TF(),TY,TB),TH=function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};return rv(TU,e)},T$=function(e){var t=e.onClose,n=e.open,r=e.onSubmit,i=l.useRef(),a=i$({fetchPolicy:"network-only"}).data,o=_K({fetchPolicy:"cache-and-network"}).data,s=TH({fetchPolicy:"cache-and-network"}).data,u=SV({fetchPolicy:"cache-and-network"}).data,c=EO({fetchPolicy:"cache-and-network"}).data,f=E2({fetchPolicy:"cache-and-network"}).data,d={chainID:"",chainType:Tm.EVM,accountAddr:"",adminAddr:"",accountAddrPubKey:"",fluxMonitorEnabled:!1,ocr1Enabled:!1,ocr1IsBootstrap:!1,ocr1Multiaddr:"",ocr1P2PPeerID:"",ocr1KeyBundleID:"",ocr2Enabled:!1,ocr2IsBootstrap:!1,ocr2Multiaddr:"",ocr2P2PPeerID:"",ocr2KeyBundleID:"",ocr2CommitPluginEnabled:!1,ocr2ExecutePluginEnabled:!1,ocr2MedianPluginEnabled:!1,ocr2MercuryPluginEnabled:!1,ocr2RebalancerPluginEnabled:!1,ocr2ForwarderAddress:""},h=a?a.chains.results:[],p=o?o.ethKeys.results:[],b=u?u.p2pKeys.results:[],m=c?c.ocrKeyBundles.results:[],g=f?f.ocr2KeyBundles.results:[];return l.createElement(aD.Z,{onClose:t,open:n,disableBackdropClick:!0},l.createElement(oO.Z,{disableTypography:!0},l.createElement(x.default,{variant:"body2"},"New Supported Chain")),l.createElement(oT.Z,null,l.createElement(TN,{innerRef:i,initialValues:d,onSubmit:r,chains:h,accountsEVM:p,accountsNonEvm:s,p2pKeys:b,ocrKeys:m,ocr2Keys:g})),l.createElement(ox.Z,null,l.createElement(ok.default,{onClick:t},"Cancel"),l.createElement(ok.default,{color:"primary",type:"submit",form:"chain-configuration-form",variant:"contained"},"Submit")))},Tz=function(e){var t=e.cfg,n=e.onClose,r=e.open,i=e.onSubmit,a=l.useRef(),o=i$({fetchPolicy:"network-only"}).data,s=_K({fetchPolicy:"cache-and-network"}).data,u=TH({fetchPolicy:"cache-and-network"}).data,c=SV({fetchPolicy:"cache-and-network"}).data,f=EO({fetchPolicy:"cache-and-network"}).data,d=E2({fetchPolicy:"cache-and-network"}).data;if(!t)return null;var h={chainID:t.chainID,chainType:t.chainType,accountAddr:t.accountAddr,adminAddr:t.adminAddr,accountAddrPubKey:t.accountAddrPubKey,fluxMonitorEnabled:t.fluxMonitorJobConfig.enabled,ocr1Enabled:t.ocr1JobConfig.enabled,ocr1IsBootstrap:t.ocr1JobConfig.isBootstrap,ocr1Multiaddr:t.ocr1JobConfig.multiaddr,ocr1P2PPeerID:t.ocr1JobConfig.p2pPeerID,ocr1KeyBundleID:t.ocr1JobConfig.keyBundleID,ocr2Enabled:t.ocr2JobConfig.enabled,ocr2IsBootstrap:t.ocr2JobConfig.isBootstrap,ocr2Multiaddr:t.ocr2JobConfig.multiaddr,ocr2P2PPeerID:t.ocr2JobConfig.p2pPeerID,ocr2KeyBundleID:t.ocr2JobConfig.keyBundleID,ocr2CommitPluginEnabled:t.ocr2JobConfig.plugins.commit,ocr2ExecutePluginEnabled:t.ocr2JobConfig.plugins.execute,ocr2MedianPluginEnabled:t.ocr2JobConfig.plugins.median,ocr2MercuryPluginEnabled:t.ocr2JobConfig.plugins.mercury,ocr2RebalancerPluginEnabled:t.ocr2JobConfig.plugins.rebalancer,ocr2ForwarderAddress:t.ocr2JobConfig.forwarderAddress},p=o?o.chains.results:[],b=s?s.ethKeys.results:[],m=c?c.p2pKeys.results:[],g=f?f.ocrKeyBundles.results:[],v=d?d.ocr2KeyBundles.results:[];return l.createElement(aD.Z,{onClose:n,open:r,disableBackdropClick:!0},l.createElement(oO.Z,{disableTypography:!0},l.createElement(x.default,{variant:"body2"},"Edit Supported Chain")),l.createElement(oT.Z,null,l.createElement(TN,{innerRef:a,initialValues:h,onSubmit:i,chains:p,accountsEVM:b,accountsNonEvm:u,p2pKeys:m,ocrKeys:g,ocr2Keys:v,editing:!0})),l.createElement(ox.Z,null,l.createElement(ok.default,{onClick:n},"Cancel"),l.createElement(ok.default,{color:"primary",type:"submit",form:"chain-configuration-form",variant:"contained"},"Submit")))};function TG(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]e.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]e.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]e.length)&&(t=e.length);for(var n=0,r=Array(t);nt.version?e:t})},[o]),g=l.useMemo(function(){return M1(o).sort(function(e,t){return t.version-e.version})},[o]),v=function(e,t,n){switch(e){case"PENDING":return l.createElement(l.Fragment,null,l.createElement(ok.default,{variant:"text",color:"secondary",onClick:function(){return b("reject",t)}},"Reject"),m.id===t&&"DELETED"!==n.status&&"REVOKED"!==n.status&&l.createElement(ok.default,{variant:"contained",color:"primary",onClick:function(){return b("approve",t)}},"Approve"),m.id===t&&"DELETED"===n.status&&n.pendingUpdate&&l.createElement(l.Fragment,null,l.createElement(ok.default,{variant:"contained",color:"primary",onClick:function(){return b("cancel",t)}},"Cancel"),l.createElement(x.default,{color:"error"},"This proposal was deleted. Cancel the spec to delete any running jobs")));case"APPROVED":return l.createElement(l.Fragment,null,l.createElement(ok.default,{variant:"contained",onClick:function(){return b("cancel",t)}},"Cancel"),"DELETED"===n.status&&n.pendingUpdate&&l.createElement(x.default,{color:"error"},"This proposal was deleted. Cancel the spec to delete any running jobs"));case"CANCELLED":if(m.id===t&&"DELETED"!==n.status&&"REVOKED"!==n.status)return l.createElement(ok.default,{variant:"contained",color:"primary",onClick:function(){return b("approve",t)}},"Approve");return null;default:return null}};return l.createElement("div",null,g.map(function(e,n){return l.createElement(mP.Z,{defaultExpanded:0===n,key:n},l.createElement(mR.Z,{expandIcon:l.createElement(gh.Z,null)},l.createElement(x.default,{className:t.versionText},"Version ",e.version),l.createElement(Es.Z,{label:e.status,color:"APPROVED"===e.status?"primary":"default",variant:"REJECTED"===e.status||"CANCELLED"===e.status?"outlined":"default"}),l.createElement("div",{className:t.proposedAtContainer},l.createElement(x.default,null,"Proposed ",l.createElement(aO,{tooltip:!0},e.createdAt)))),l.createElement(mj.Z,{className:t.expansionPanelDetails},l.createElement("div",{className:t.actions},l.createElement("div",{className:t.editContainer},0===n&&("PENDING"===e.status||"CANCELLED"===e.status)&&"DELETED"!==s.status&&"REVOKED"!==s.status&&l.createElement(ok.default,{variant:"contained",onClick:function(){return p(!0)}},"Edit")),l.createElement("div",{className:t.actionsContainer},v(e.status,e.id,s))),l.createElement(gd,{language:"toml",style:gs,"data-testid":"codeblock"},e.definition)))}),l.createElement(oC,{open:null!=c,title:c?M6[c.action].title:"",body:c?M6[c.action].body:"",onConfirm:function(){if(c){switch(c.action){case"approve":n(c.id);break;case"cancel":r(c.id);break;case"reject":i(c.id)}f(null)}},cancelButtonText:"Cancel",onCancel:function(){return f(null)}}),l.createElement(Mz,{open:h,onClose:function(){return p(!1)},initialValues:{definition:m.definition,id:m.id},onSubmit:a}))});function M8(e,t){return t||(t=e.slice(0)),Object.freeze(Object.defineProperties(e,{raw:{value:Object.freeze(t)}}))}function M9(){var e=M8(["\n ","\n fragment JobProposalPayloadFields on JobProposal {\n id\n externalJobID\n remoteUUID\n jobID\n specs {\n ...JobProposal_SpecsFields\n }\n status\n pendingUpdate\n }\n"]);return M9=function(){return e},e}var M7=n0(M9(),M3),Oe=function(e){var t=e.onApprove,n=e.onCancel,r=e.onReject,i=e.onUpdateSpec,a=e.proposal;return l.createElement(ig,null,l.createElement(d.Z,{container:!0,spacing:32},l.createElement(d.Z,{item:!0,xs:9},l.createElement(iy,null,"Job Proposal #",a.id))),l.createElement(MF,{proposal:a}),l.createElement(d.Z,{container:!0,spacing:32},l.createElement(d.Z,{item:!0,xs:9},l.createElement(xQ,null,"Specs"))),l.createElement(d.Z,{container:!0,spacing:32},l.createElement(d.Z,{item:!0,xs:12},l.createElement(M5,{proposal:a,specs:a.specs,onReject:r,onApprove:t,onCancel:n,onUpdateSpec:i}))))};function Ot(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]e.length)&&(t=e.length);for(var n=0,r=Array(t);ne.length)&&(t=e.length);for(var n=0,r=Array(t);nU,tA:()=>$,KL:()=>H,Iw:()=>V,DQ:()=>W,cB:()=>T,LO:()=>M,t5:()=>k,qt:()=>x,Jc:()=>C,L7:()=>Y,EO:()=>B});var r,i,a=n(66289),o=n(41800),s=n.n(o),u=n(67932);(i=r||(r={})).IN_PROGRESS="in_progress",i.PENDING_INCOMING_CONFIRMATIONS="pending_incoming_confirmations",i.PENDING_CONNECTION="pending_connection",i.PENDING_BRIDGE="pending_bridge",i.PENDING_SLEEP="pending_sleep",i.ERRORED="errored",i.COMPLETED="completed";var c=n(87013),l=n(19084),f=n(34823);function d(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]j,v2:()=>F});var r=n(66289);function i(e,t){if(!(e instanceof t))throw TypeError("Cannot call a class as a function")}var a="/sessions",o="/sessions",s=function e(t){var n=this;i(this,e),this.api=t,this.createSession=function(e){return n.create(e)},this.destroySession=function(){return n.destroy()},this.create=this.api.createResource(a),this.destroy=this.api.deleteResource(o)};function u(e,t){if(!(e instanceof t))throw TypeError("Cannot call a class as a function")}var c="/v2/bulk_delete_runs",l=function e(t){var n=this;u(this,e),this.api=t,this.bulkDeleteJobRuns=function(e){return n.destroy(e)},this.destroy=this.api.deleteResource(c)};function f(e,t){if(!(e instanceof t))throw TypeError("Cannot call a class as a function")}var d="/v2/chains/evm",h="".concat(d,"/:id"),p=function e(t){var n=this;f(this,e),this.api=t,this.getChains=function(){return n.index()},this.createChain=function(e){return n.create(e)},this.destroyChain=function(e){return n.destroy(void 0,{id:e})},this.updateChain=function(e,t){return n.update(t,{id:e})},this.index=this.api.fetchResource(d),this.create=this.api.createResource(d),this.destroy=this.api.deleteResource(h),this.update=this.api.updateResource(h)};function b(e,t){if(!(e instanceof t))throw TypeError("Cannot call a class as a function")}var m="/v2/keys/evm/chain",g=function e(t){var n=this;b(this,e),this.api=t,this.chain=function(e){var t=new URLSearchParams;t.append("address",e.address),t.append("evmChainID",e.evmChainID),null!==e.abandon&&t.append("abandon",String(e.abandon)),null!==e.enabled&&t.append("enabled",String(e.enabled));var r=m+"?"+t.toString();return n.api.createResource(r)()}};function v(e,t){if(!(e instanceof t))throw TypeError("Cannot call a class as a function")}var y="/v2/jobs",w="".concat(y,"/:specId/runs"),_=function e(t){var n=this;v(this,e),this.api=t,this.createJobRunV2=function(e,t){return n.post(t,{specId:e})},this.post=this.api.createResource(w,!0)};function E(e,t){if(!(e instanceof t))throw TypeError("Cannot call a class as a function")}var S="/v2/log",k=function e(t){var n=this;E(this,e),this.api=t,this.getLogConfig=function(){return n.show()},this.updateLogConfig=function(e){return n.update(e)},this.show=this.api.fetchResource(S),this.update=this.api.updateResource(S)};function x(e,t){if(!(e instanceof t))throw TypeError("Cannot call a class as a function")}var T="/v2/nodes",M=function e(t){var n=this;x(this,e),this.api=t,this.getNodes=function(){return n.index()},this.createNode=function(e){return n.create(e)},this.index=this.api.fetchResource(T),this.create=this.api.createResource(T)};function O(e,t){if(!(e instanceof t))throw TypeError("Cannot call a class as a function")}var A="/v2/enroll_webauthn",L=function e(t){var n=this;O(this,e),this.api=t,this.beginKeyRegistration=function(e){return n.create(e)},this.finishKeyRegistration=function(e){return n.put(e)},this.create=this.api.fetchResource(A),this.put=this.api.createResource(A)};function C(e,t){if(!(e instanceof t))throw TypeError("Cannot call a class as a function")}var I="/v2/build_info",D=function e(t){var n=this;C(this,e),this.api=t,this.show=function(){return n.api.GET(I)()}};function N(e,t){if(!(e instanceof t))throw TypeError("Cannot call a class as a function")}var P=function e(t){N(this,e),this.api=t,this.buildInfo=new D(this.api),this.bulkDeleteRuns=new l(this.api),this.chains=new p(this.api),this.logConfig=new k(this.api),this.nodes=new M(this.api),this.jobs=new _(this.api),this.webauthn=new L(this.api),this.evmKeys=new g(this.api)},R=new r.V0({base:void 0}),j=new s(R),F=new P(R)},1398(e,t,n){"use strict";n.d(t,{Z:()=>d});var r=n(67294),i=n(32316),a=n(83638),o=n(94184),s=n.n(o);function u(){return(u=Object.assign||function(e){for(var t=1;tc});var r=n(67294),i=n(32316);function a(){return(a=Object.assign||function(e){for(var t=1;tx,jK:()=>v});var r=n(67294),i=n(37703),a=n(45697),o=n.n(a),s=n(82204),u=n(71426),c=n(94184),l=n.n(c),f=n(32316),d=function(e){var t=e.palette.success||{},n=e.palette.warning||{};return{base:{paddingLeft:5*e.spacing.unit,paddingRight:5*e.spacing.unit},success:{backgroundColor:t.main,color:t.contrastText},error:{backgroundColor:e.palette.error.dark,color:e.palette.error.contrastText},warning:{backgroundColor:n.contrastText,color:n.main}}},h=function(e){var t,n=e.success,r=e.error,i=e.warning,a=e.classes,o=e.className;return n?t=a.success:r?t=a.error:i&&(t=a.warning),l()(a.base,o,t)},p=function(e){return r.createElement(s.Z,{className:h(e),square:!0},r.createElement(u.default,{variant:"body2",color:"inherit",component:"div"},e.children))};p.defaultProps={success:!1,error:!1,warning:!1},p.propTypes={success:o().bool,error:o().bool,warning:o().bool};let b=(0,f.withStyles)(d)(p);var m=function(){return r.createElement(r.Fragment,null,"Unhandled error. Please help us by opening a"," ",r.createElement("a",{href:"https://github.com/smartcontractkit/chainlink/issues/new"},"bug report"))};let g=m;function v(e){return"string"==typeof e?e:e.component?e.component(e.props):r.createElement(g,null)}function y(e,t){var n;return n="string"==typeof e?e:e.component?e.component(e.props):r.createElement(g,null),r.createElement("p",{key:t},n)}var w=function(e){var t=e.notifications;return r.createElement(b,{error:!0},t.map(y))},_=function(e){var t=e.notifications;return r.createElement(b,{success:!0},t.map(y))},E=function(e){var t=e.errors,n=e.successes;return r.createElement("div",null,(null==t?void 0:t.length)>0&&r.createElement(w,{notifications:t}),n.length>0&&r.createElement(_,{notifications:n}))},S=function(e){return{errors:e.notifications.errors,successes:e.notifications.successes}},k=(0,i.$j)(S)(E);let x=k},9409(e,t,n){"use strict";n.d(t,{ZP:()=>j});var r=n(67294),i=n(37703),a=n(5977),o=n(32316),s=n(1398),u=n(82204),c=n(30060),l=n(71426),f=n(60520),d=n(39814),h=n(57209),p=n(26842),b=n(3950),m=n(5536),g=n(45697),v=n.n(g);let y=n.p+"9f6d832ef97e8493764e.svg";function w(){return(w=Object.assign||function(e){for(var t=1;te.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&_.map(function(e,t){return r.createElement(d.Z,{item:!0,xs:12,key:t},r.createElement(u.Z,{raised:!1,className:v.error},r.createElement(c.Z,null,r.createElement(l.default,{variant:"body1",className:v.errorText},(0,b.jK)(e)))))}),r.createElement(d.Z,{item:!0,xs:12},r.createElement(f.Z,{id:"email",label:"Email",margin:"normal",value:n,onChange:m("email"),error:_.length>0,variant:"outlined",fullWidth:!0})),r.createElement(d.Z,{item:!0,xs:12},r.createElement(f.Z,{id:"password",label:"Password",type:"password",autoComplete:"password",margin:"normal",value:h,onChange:m("password"),error:_.length>0,variant:"outlined",fullWidth:!0})),r.createElement(d.Z,{item:!0,xs:12},r.createElement(d.Z,{container:!0,spacing:0,justify:"center"},r.createElement(d.Z,{item:!0},r.createElement(s.Z,{type:"submit",variant:"primary"},"Access Account")))),y&&r.createElement(l.default,{variant:"body1",color:"textSecondary"},"Signing in...")))))))},P=function(e){return{fetching:e.authentication.fetching,authenticated:e.authentication.allowed,errors:e.notifications.errors}},R=(0,i.$j)(P,x({submitSignIn:p.L7}))(N);let j=(0,h.wU)(e)((0,o.withStyles)(D)(R))},16353(e,t,n){"use strict";n.d(t,{ZP:()=>H,rH:()=>U});var r,i=n(37703),a=n(97779),o=n(9541),s=n(19084);function u(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function c(e){for(var t=1;t0&&void 0!==arguments[0]?arguments[0]:h,t=arguments.length>1?arguments[1]:void 0;switch(t.type){case s.Mk.RECEIVE_SIGNOUT_SUCCESS:case s.Mk.RECEIVE_SIGNIN_SUCCESS:var n={allowed:t.authenticated};return o.Ks(n),f(c({},e,n),{errors:[]});case s.Mk.RECEIVE_SIGNIN_FAIL:var r={allowed:!1};return o.Ks(r),f(c({},e,r),{errors:[]});case s.Mk.RECEIVE_SIGNIN_ERROR:case s.Mk.RECEIVE_SIGNOUT_ERROR:var i={allowed:!1};return o.Ks(i),f(c({},e,i),{errors:t.errors||[]});default:return e}};let b=p;function m(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function g(e){for(var t=1;t0&&void 0!==arguments[0]?arguments[0]:_,t=arguments.length>1?arguments[1]:void 0;return t.type?t.type.startsWith(r.REQUEST)?y(g({},e),{count:e.count+1}):t.type.startsWith(r.RECEIVE)?y(g({},e),{count:Math.max(e.count-1,0)}):t.type.startsWith(r.RESPONSE)?y(g({},e),{count:Math.max(e.count-1,0)}):t.type===s.di.REDIRECT?y(g({},e),{count:0}):e:e};let S=E;function k(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function x(e){for(var t=1;t0&&void 0!==arguments[0]?arguments[0]:O,t=arguments.length>1?arguments[1]:void 0;switch(t.type){case s.di.MATCH_ROUTE:return M(x({},O),{currentUrl:t.pathname});case s.Ih.NOTIFY_SUCCESS:var n={component:t.component,props:t.props};return M(x({},e),{successes:[n],errors:[]});case s.Ih.NOTIFY_SUCCESS_MSG:return M(x({},e),{successes:[t.msg],errors:[]});case s.Ih.NOTIFY_ERROR:var r=t.error.errors,i=null==r?void 0:r.map(function(e){return L(t,e)});return M(x({},e),{successes:[],errors:i});case s.Ih.NOTIFY_ERROR_MSG:return M(x({},e),{successes:[],errors:[t.msg]});case s.Mk.RECEIVE_SIGNIN_FAIL:return M(x({},e),{successes:[],errors:["Your email or password is incorrect. Please try again"]});default:return e}};function L(e,t){return{component:e.component,props:{msg:t.detail}}}let C=A;function I(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function D(e){for(var t=1;t0&&void 0!==arguments[0]?arguments[0]:R,t=arguments.length>1?arguments[1]:void 0;switch(t.type){case s.di.REDIRECT:return P(D({},e),{to:t.to});case s.di.MATCH_ROUTE:return P(D({},e),{to:void 0});default:return e}};let F=j;var Y=n(87013),B=(0,a.UY)({authentication:b,fetching:S,notifications:C,redirect:F,buildInfo:Y.Z});B(void 0,{type:"INITIAL_STATE"});var U=i.v9;let H=B},19084(e,t,n){"use strict";var r,i,a,o,s,u,c,l,f,d;n.d(t,{Ih:()=>i,Mk:()=>a,Y0:()=>s,di:()=>r,jp:()=>o}),n(67294),(u=r||(r={})).REDIRECT="REDIRECT",u.MATCH_ROUTE="MATCH_ROUTE",(c=i||(i={})).NOTIFY_SUCCESS="NOTIFY_SUCCESS",c.NOTIFY_SUCCESS_MSG="NOTIFY_SUCCESS_MSG",c.NOTIFY_ERROR="NOTIFY_ERROR",c.NOTIFY_ERROR_MSG="NOTIFY_ERROR_MSG",(l=a||(a={})).REQUEST_SIGNIN="REQUEST_SIGNIN",l.RECEIVE_SIGNIN_SUCCESS="RECEIVE_SIGNIN_SUCCESS",l.RECEIVE_SIGNIN_FAIL="RECEIVE_SIGNIN_FAIL",l.RECEIVE_SIGNIN_ERROR="RECEIVE_SIGNIN_ERROR",l.RECEIVE_SIGNOUT_SUCCESS="RECEIVE_SIGNOUT_SUCCESS",l.RECEIVE_SIGNOUT_ERROR="RECEIVE_SIGNOUT_ERROR",(f=o||(o={})).RECEIVE_CREATE_ERROR="RECEIVE_CREATE_ERROR",f.RECEIVE_CREATE_SUCCESS="RECEIVE_CREATE_SUCCESS",f.RECEIVE_DELETE_ERROR="RECEIVE_DELETE_ERROR",f.RECEIVE_DELETE_SUCCESS="RECEIVE_DELETE_SUCCESS",f.RECEIVE_UPDATE_ERROR="RECEIVE_UPDATE_ERROR",f.RECEIVE_UPDATE_SUCCESS="RECEIVE_UPDATE_SUCCESS",f.REQUEST_CREATE="REQUEST_CREATE",f.REQUEST_DELETE="REQUEST_DELETE",f.REQUEST_UPDATE="REQUEST_UPDATE",f.UPSERT_CONFIGURATION="UPSERT_CONFIGURATION",f.UPSERT_JOB_RUN="UPSERT_JOB_RUN",f.UPSERT_JOB_RUNS="UPSERT_JOB_RUNS",f.UPSERT_TRANSACTION="UPSERT_TRANSACTION",f.UPSERT_TRANSACTIONS="UPSERT_TRANSACTIONS",f.UPSERT_BUILD_INFO="UPSERT_BUILD_INFO",(d=s||(s={})).FETCH_BUILD_INFO_REQUESTED="FETCH_BUILD_INFO_REQUESTED",d.FETCH_BUILD_INFO_SUCCEEDED="FETCH_BUILD_INFO_SUCCEEDED",d.FETCH_BUILD_INFO_FAILED="FETCH_BUILD_INFO_FAILED"},87013(e,t,n){"use strict";n.d(t,{Y:()=>o,Z:()=>u});var r=n(19084);function i(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function a(e){for(var t=1;t0&&void 0!==arguments[0]?arguments[0]:o,t=arguments.length>1?arguments[1]:void 0;return t.type===r.Y0.FETCH_BUILD_INFO_SUCCEEDED?a({},t.buildInfo):e};let u=s},34823(e,t,n){"use strict";n.d(t,{N:()=>r});var r=function(e){return e.buildInfo}},73343(e,t,n){"use strict";n.d(t,{r:()=>u});var r=n(19350),i=n(32316),a=n(59114),o=n(5324),s={props:{MuiGrid:{spacing:3*o.default.unit},MuiCardHeader:{titleTypographyProps:{color:"secondary"}}},palette:{action:{hoverOpacity:.3},primary:{light:"#E5F1FF",main:"#3c40c6",contrastText:"#fff"},secondary:{main:"#3d5170"},success:{light:"#e8faf1",main:r.ek.A700,dark:r.ek[700],contrastText:r.y0.white},warning:{light:"#FFFBF1",main:"#fff6b6",contrastText:"#fad27a"},error:{light:"#ffdada",main:"#f44336",dark:"#d32f2f",contrastText:"#fff"},background:{default:"#f5f6f8",appBar:"#3c40c6"},text:{primary:(0,a.darken)(r.BA.A700,.7),secondary:"#818ea3"},listPendingStatus:{background:"#fef7e5",color:"#fecb4c"},listCompletedStatus:{background:"#e9faf2",color:"#4ed495"}},shape:{borderRadius:o.default.unit},overrides:{MuiButton:{root:{borderRadius:o.default.unit/2,textTransform:"none"},sizeLarge:{padding:void 0,fontSize:void 0,paddingTop:o.default.unit,paddingBottom:o.default.unit,paddingLeft:5*o.default.unit,paddingRight:5*o.default.unit}},MuiTableCell:{body:{fontSize:"1rem"},head:{fontSize:"1rem",fontWeight:400}},MuiCardHeader:{root:{borderBottom:"1px solid rgba(0, 0, 0, 0.12)"},action:{marginTop:-2,marginRight:0,"& >*":{marginLeft:2*o.default.unit}},subheader:{marginTop:.5*o.default.unit}}},typography:{useNextVariants:!0,fontFamily:"-apple-system,BlinkMacSystemFont,Roboto,Helvetica,Arial,sans-serif",button:{textTransform:"none",fontSize:"1.2em"},body1:{fontSize:"1.0rem",fontWeight:400,lineHeight:"1.46429em",color:"rgba(0, 0, 0, 0.87)",letterSpacing:-.4},body2:{fontSize:"1.0rem",fontWeight:500,lineHeight:"1.71429em",color:"rgba(0, 0, 0, 0.87)",letterSpacing:-.4},body1Next:{color:"rgb(29, 29, 29)",fontWeight:400,fontSize:"1rem",lineHeight:1.5,letterSpacing:-.4},body2Next:{color:"rgb(29, 29, 29)",fontWeight:400,fontSize:"0.875rem",lineHeight:1.5,letterSpacing:-.4},display1:{color:"#818ea3",fontSize:"2.125rem",fontWeight:400,lineHeight:"1.20588em",letterSpacing:-.4},display2:{color:"#818ea3",fontSize:"2.8125rem",fontWeight:400,lineHeight:"1.13333em",marginLeft:"-.02em",letterSpacing:-.4},display3:{color:"#818ea3",fontSize:"3.5rem",fontWeight:400,lineHeight:"1.30357em",marginLeft:"-.02em",letterSpacing:-.4},display4:{fontSize:14,fontWeightLight:300,fontWeightMedium:500,fontWeightRegular:400,letterSpacing:-.4},h1:{color:"rgb(29, 29, 29)",fontSize:"6rem",fontWeight:300,lineHeight:1},h2:{color:"rgb(29, 29, 29)",fontSize:"3.75rem",fontWeight:300,lineHeight:1},h3:{color:"rgb(29, 29, 29)",fontSize:"3rem",fontWeight:400,lineHeight:1.04},h4:{color:"rgb(29, 29, 29)",fontSize:"2.125rem",fontWeight:400,lineHeight:1.17},h5:{color:"rgb(29, 29, 29)",fontSize:"1.5rem",fontWeight:400,lineHeight:1.33,letterSpacing:-.4},h6:{fontSize:"0.8rem",fontWeight:450,lineHeight:"1.71429em",color:"rgba(0, 0, 0, 0.87)",letterSpacing:-.4},subheading:{color:"rgb(29, 29, 29)",fontSize:"1rem",fontWeight:400,lineHeight:"1.5em",letterSpacing:-.4},subtitle1:{color:"rgb(29, 29, 29)",fontSize:"1rem",fontWeight:400,lineHeight:1.75,letterSpacing:-.4},subtitle2:{color:"rgb(29, 29, 29)",fontSize:"0.875rem",fontWeight:500,lineHeight:1.57,letterSpacing:-.4}},shadows:["none","0px 1px 3px 0px rgba(0, 0, 0, 0.1),0px 1px 1px 0px rgba(0, 0, 0, 0.04),0px 2px 1px -1px rgba(0, 0, 0, 0.02)","0px 1px 5px 0px rgba(0, 0, 0, 0.1),0px 2px 2px 0px rgba(0, 0, 0, 0.04),0px 3px 1px -2px rgba(0, 0, 0, 0.02)","0px 1px 8px 0px rgba(0, 0, 0, 0.1),0px 3px 4px 0px rgba(0, 0, 0, 0.04),0px 3px 3px -2px rgba(0, 0, 0, 0.02)","0px 2px 4px -1px rgba(0, 0, 0, 0.1),0px 4px 5px 0px rgba(0, 0, 0, 0.04),0px 1px 10px 0px rgba(0, 0, 0, 0.02)","0px 3px 5px -1px rgba(0, 0, 0, 0.1),0px 5px 8px 0px rgba(0, 0, 0, 0.04),0px 1px 14px 0px rgba(0, 0, 0, 0.02)","0px 3px 5px -1px rgba(0, 0, 0, 0.1),0px 6px 10px 0px rgba(0, 0, 0, 0.04),0px 1px 18px 0px rgba(0, 0, 0, 0.02)","0px 4px 5px -2px rgba(0, 0, 0, 0.1),0px 7px 10px 1px rgba(0, 0, 0, 0.04),0px 2px 16px 1px rgba(0, 0, 0, 0.02)","0px 5px 5px -3px rgba(0, 0, 0, 0.1),0px 8px 10px 1px rgba(0, 0, 0, 0.04),0px 3px 14px 2px rgba(0, 0, 0, 0.02)","0px 5px 6px -3px rgba(0, 0, 0, 0.1),0px 9px 12px 1px rgba(0, 0, 0, 0.04),0px 3px 16px 2px rgba(0, 0, 0, 0.02)","0px 6px 6px -3px rgba(0, 0, 0, 0.1),0px 10px 14px 1px rgba(0, 0, 0, 0.04),0px 4px 18px 3px rgba(0, 0, 0, 0.02)","0px 6px 7px -4px rgba(0, 0, 0, 0.1),0px 11px 15px 1px rgba(0, 0, 0, 0.04),0px 4px 20px 3px rgba(0, 0, 0, 0.02)","0px 7px 8px -4px rgba(0, 0, 0, 0.1),0px 12px 17px 2px rgba(0, 0, 0, 0.04),0px 5px 22px 4px rgba(0, 0, 0, 0.02)","0px 7px 8px -4px rgba(0, 0, 0, 0.1),0px 13px 19px 2px rgba(0, 0, 0, 0.04),0px 5px 24px 4px rgba(0, 0, 0, 0.02)","0px 7px 9px -4px rgba(0, 0, 0, 0.1),0px 14px 21px 2px rgba(0, 0, 0, 0.04),0px 5px 26px 4px rgba(0, 0, 0, 0.02)","0px 8px 9px -5px rgba(0, 0, 0, 0.1),0px 15px 22px 2px rgba(0, 0, 0, 0.04),0px 6px 28px 5px rgba(0, 0, 0, 0.02)","0px 8px 10px -5px rgba(0, 0, 0, 0.1),0px 16px 24px 2px rgba(0, 0, 0, 0.04),0px 6px 30px 5px rgba(0, 0, 0, 0.02)","0px 8px 11px -5px rgba(0, 0, 0, 0.1),0px 17px 26px 2px rgba(0, 0, 0, 0.04),0px 6px 32px 5px rgba(0, 0, 0, 0.02)","0px 9px 11px -5px rgba(0, 0, 0, 0.1),0px 18px 28px 2px rgba(0, 0, 0, 0.04),0px 7px 34px 6px rgba(0, 0, 0, 0.02)","0px 9px 12px -6px rgba(0, 0, 0, 0.1),0px 19px 29px 2px rgba(0, 0, 0, 0.04),0px 7px 36px 6px rgba(0, 0, 0, 0.02)","0px 10px 13px -6px rgba(0, 0, 0, 0.1),0px 20px 31px 3px rgba(0, 0, 0, 0.04),0px 8px 38px 7px rgba(0, 0, 0, 0.02)","0px 10px 13px -6px rgba(0, 0, 0, 0.1),0px 21px 33px 3px rgba(0, 0, 0, 0.04),0px 8px 40px 7px rgba(0, 0, 0, 0.02)","0px 10px 14px -6px rgba(0, 0, 0, 0.1),0px 22px 35px 3px rgba(0, 0, 0, 0.04),0px 8px 42px 7px rgba(0, 0, 0, 0.02)","0px 11px 14px -7px rgba(0, 0, 0, 0.1),0px 23px 36px 3px rgba(0, 0, 0, 0.04),0px 9px 44px 8px rgba(0, 0, 0, 0.02)","0px 11px 15px -7px rgba(0, 0, 0, 0.1),0px 24px 38px 3px rgba(0, 0, 0, 0.04),0px 9px 46px 8px rgba(0, 0, 0, 0.02)",]},u=(0,i.createMuiTheme)(s)},66289(e,t,n){"use strict";function r(e){if(void 0===e)throw ReferenceError("this hasn't been initialised - super() hasn't been called");return e}function i(e,t){if(!(e instanceof t))throw TypeError("Cannot call a class as a function")}function a(){if("undefined"==typeof Reflect||!Reflect.construct||Reflect.construct.sham)return!1;if("function"==typeof Proxy)return!0;try{return Date.prototype.toString.call(Reflect.construct(Date,[],function(){})),!0}catch(e){return!1}}function o(e,t,n){return(o=a()?Reflect.construct:function(e,t,n){var r=[null];r.push.apply(r,t);var i=new(Function.bind.apply(e,r));return n&&f(i,n.prototype),i}).apply(null,arguments)}function s(e){return(s=Object.setPrototypeOf?Object.getPrototypeOf:function(e){return e.__proto__||Object.getPrototypeOf(e)})(e)}function u(e,t){if("function"!=typeof t&&null!==t)throw TypeError("Super expression must either be null or a function");e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,writable:!0,configurable:!0}}),t&&f(e,t)}function c(e){return -1!==Function.toString.call(e).indexOf("[native code]")}function l(e,t){return t&&("object"===p(t)||"function"==typeof t)?t:r(e)}function f(e,t){return(f=Object.setPrototypeOf||function(e,t){return e.__proto__=t,e})(e,t)}n.d(t,{V0:()=>B,_7:()=>v});var d,h,p=function(e){return e&&"undefined"!=typeof Symbol&&e.constructor===Symbol?"symbol":typeof e};function b(e){var t="function"==typeof Map?new Map:void 0;return(b=function(e){if(null===e||!c(e))return e;if("function"!=typeof e)throw TypeError("Super expression must either be null or a function");if(void 0!==t){if(t.has(e))return t.get(e);t.set(e,n)}function n(){return o(e,arguments,s(this).constructor)}return n.prototype=Object.create(e.prototype,{constructor:{value:n,enumerable:!1,writable:!0,configurable:!0}}),f(n,e)})(e)}function m(){if("undefined"==typeof Reflect||!Reflect.construct||Reflect.construct.sham)return!1;if("function"==typeof Proxy)return!0;try{return Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],function(){})),!0}catch(e){return!1}}function g(e){var t=m();return function(){var n,r=s(e);if(t){var i=s(this).constructor;n=Reflect.construct(r,arguments,i)}else n=r.apply(this,arguments);return l(this,n)}}var v=function(e){u(n,e);var t=g(n);function n(e){var r;return i(this,n),(r=t.call(this,"AuthenticationError(".concat(e.statusText,")"))).errors=[{status:e.status,detail:e},],r}return n}(b(Error)),y=function(e){u(n,e);var t=g(n);function n(e){var r,a=e.errors;return i(this,n),(r=t.call(this,"BadRequestError")).errors=a,r}return n}(b(Error)),w=function(e){u(n,e);var t=g(n);function n(e){var r;return i(this,n),(r=t.call(this,"UnprocessableEntityError")).errors=e,r}return n}(b(Error)),_=function(e){u(n,e);var t=g(n);function n(e){var r;return i(this,n),(r=t.call(this,"ServerError")).errors=e,r}return n}(b(Error)),E=function(e){u(n,e);var t=g(n);function n(e){var r,a=e.errors;return i(this,n),(r=t.call(this,"ConflictError")).errors=a,r}return n}(b(Error)),S=function(e){u(n,e);var t=g(n);function n(e){var r;return i(this,n),(r=t.call(this,"UnknownResponseError(".concat(e.statusText,")"))).errors=[{status:e.status,detail:e.statusText},],r}return n}(b(Error));function k(e,t){var n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:2e4;return Promise.race([fetch(e,t),new Promise(function(e,t){return setTimeout(function(){return t(Error("timeout"))},n)}),])}function x(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]=200&&e.status<300))return[3,2];return[2,e.json()];case 2:if(400!==e.status)return[3,3];return[2,e.json().then(function(e){throw new y(e)})];case 3:if(401!==e.status)return[3,4];throw new v(e);case 4:if(422!==e.status)return[3,6];return[4,$(e)];case 5:throw n=i.sent(),new w(n);case 6:if(409!==e.status)return[3,7];return[2,e.json().then(function(e){throw new E(e)})];case 7:if(!(e.status>=500))return[3,9];return[4,$(e)];case 8:throw r=i.sent(),new _(r);case 9:throw new S(e);case 10:return[2]}})})).apply(this,arguments)}function $(e){return z.apply(this,arguments)}function z(){return(z=j(function(e){return Y(this,function(t){return[2,e.json().then(function(t){return t.errors?t.errors.map(function(t){return{status:e.status,detail:t.detail}}):G(e)}).catch(function(){return G(e)})]})})).apply(this,arguments)}function G(e){return[{status:e.status,detail:e.statusText},]}},50109(e,t,n){"use strict";n.d(t,{LK:()=>o,U2:()=>i,eT:()=>s,t8:()=>a});var r=n(12795);function i(e){return r.ZP.getItem("chainlink.".concat(e))}function a(e,t){r.ZP.setItem("chainlink.".concat(e),t)}function o(e){var t=i(e),n={};if(t)try{return JSON.parse(t)}catch(r){}return n}function s(e,t){a(e,JSON.stringify(t))}},9541(e,t,n){"use strict";n.d(t,{Ks:()=>u,Tp:()=>a,iR:()=>o,pm:()=>s});var r=n(50109),i="persistURL";function a(){return r.U2(i)||""}function o(e){r.t8(i,e)}function s(){return r.LK("authentication")}function u(e){r.eT("authentication",e)}},67121(e,t,n){"use strict";function r(e){var t,n=e.Symbol;return"function"==typeof n?n.observable?t=n.observable:(t=n("observable"),n.observable=t):t="@@observable",t}n.r(t),n.d(t,{default:()=>o}),e=n.hmd(e),i="undefined"!=typeof self?self:"undefined"!=typeof window?window:void 0!==n.g?n.g:e;var i,a=r(i);let o=a},2177(e,t,n){"use strict";n.d(t,{Z:()=>o});var r=!0,i="Invariant failed";function a(e,t){if(!e){if(r)throw Error(i);throw Error(i+": "+(t||""))}}let o=a},11742(e){e.exports=function(){var e=document.getSelection();if(!e.rangeCount)return function(){};for(var t=document.activeElement,n=[],r=0;ru,ZT:()=>i,_T:()=>o,ev:()=>c,mG:()=>s,pi:()=>a});var r=function(e,t){return(r=Object.setPrototypeOf||({__proto__:[]})instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)Object.prototype.hasOwnProperty.call(t,n)&&(e[n]=t[n])})(e,t)};function i(e,t){if("function"!=typeof t&&null!==t)throw TypeError("Class extends value "+String(t)+" is not a constructor or null");function n(){this.constructor=e}r(e,t),e.prototype=null===t?Object.create(t):(n.prototype=t.prototype,new n)}var a=function(){return(a=Object.assign||function(e){for(var t,n=1,r=arguments.length;nt.indexOf(r)&&(n[r]=e[r]);if(null!=e&&"function"==typeof Object.getOwnPropertySymbols)for(var i=0,r=Object.getOwnPropertySymbols(e);it.indexOf(r[i])&&Object.prototype.propertyIsEnumerable.call(e,r[i])&&(n[r[i]]=e[r[i]]);return n}function s(e,t,n,r){function i(e){return e instanceof n?e:new n(function(t){t(e)})}return new(n||(n=Promise))(function(n,a){function o(e){try{u(r.next(e))}catch(t){a(t)}}function s(e){try{u(r.throw(e))}catch(t){a(t)}}function u(e){e.done?n(e.value):i(e.value).then(o,s)}u((r=r.apply(e,t||[])).next())})}function u(e,t){var n,r,i,a,o={label:0,sent:function(){if(1&i[0])throw i[1];return i[1]},trys:[],ops:[]};return a={next:s(0),throw:s(1),return:s(2)},"function"==typeof Symbol&&(a[Symbol.iterator]=function(){return this}),a;function s(e){return function(t){return u([e,t])}}function u(a){if(n)throw TypeError("Generator is already executing.");for(;o;)try{if(n=1,r&&(i=2&a[0]?r.return:a[0]?r.throw||((i=r.return)&&i.call(r),0):r.next)&&!(i=i.call(r,a[1])).done)return i;switch(r=0,i&&(a=[2&a[0],i.value]),a[0]){case 0:case 1:i=a;break;case 4:return o.label++,{value:a[1],done:!1};case 5:o.label++,r=a[1],a=[0];continue;case 7:a=o.ops.pop(),o.trys.pop();continue;default:if(!(i=(i=o.trys).length>0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]r})},94927(e,t,n){function r(e,t){if(i("noDeprecation"))return e;var n=!1;function r(){if(!n){if(i("throwDeprecation"))throw Error(t);i("traceDeprecation")?console.trace(t):console.warn(t),n=!0}return e.apply(this,arguments)}return r}function i(e){try{if(!n.g.localStorage)return!1}catch(t){return!1}var r=n.g.localStorage[e];return null!=r&&"true"===String(r).toLowerCase()}e.exports=r},42473(e){"use strict";var t=function(){};e.exports=t},84763(e){e.exports=Worker},47529(e){e.exports=n;var t=Object.prototype.hasOwnProperty;function n(){for(var e={},n=0;ne.length)&&(t=e.length);for(var n=0,r=Array(t);n=0)&&Object.prototype.propertyIsEnumerable.call(e,n)&&(a[n]=e[n])}return a}e.exports=i,e.exports.__esModule=!0,e.exports.default=e.exports},7071(e){function t(e,t){if(null==e)return{};var n,r,i={},a=Object.keys(e);for(r=0;r=0||(i[n]=e[n]);return i}e.exports=t,e.exports.__esModule=!0,e.exports.default=e.exports},94993(e,t,n){var r=n(18698).default,i=n(66115);function a(e,t){if(t&&("object"===r(t)||"function"==typeof t))return t;if(void 0!==t)throw TypeError("Derived constructors may only return object or undefined");return i(e)}e.exports=a,e.exports.__esModule=!0,e.exports.default=e.exports},6015(e){function t(n,r){return e.exports=t=Object.setPrototypeOf?Object.setPrototypeOf.bind():function(e,t){return e.__proto__=t,e},e.exports.__esModule=!0,e.exports.default=e.exports,t(n,r)}e.exports=t,e.exports.__esModule=!0,e.exports.default=e.exports},861(e,t,n){var r=n(63405),i=n(79498),a=n(86116),o=n(42281);function s(e){return r(e)||i(e)||a(e)||o()}e.exports=s,e.exports.__esModule=!0,e.exports.default=e.exports},18698(e){function t(n){return e.exports=t="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},e.exports.__esModule=!0,e.exports.default=e.exports,t(n)}e.exports=t,e.exports.__esModule=!0,e.exports.default=e.exports},86116(e,t,n){var r=n(73897);function i(e,t){if(e){if("string"==typeof e)return r(e,t);var n=Object.prototype.toString.call(e).slice(8,-1);if("Object"===n&&e.constructor&&(n=e.constructor.name),"Map"===n||"Set"===n)return Array.from(e);if("Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n))return r(e,t)}}e.exports=i,e.exports.__esModule=!0,e.exports.default=e.exports},1644(e,t,n){"use strict";var r,i;function a(e){return!!e&&e<7}n.d(t,{I:()=>r,O:()=>a}),(i=r||(r={}))[i.loading=1]="loading",i[i.setVariables=2]="setVariables",i[i.fetchMore=3]="fetchMore",i[i.refetch=4]="refetch",i[i.poll=6]="poll",i[i.ready=7]="ready",i[i.error=8]="error"},30990(e,t,n){"use strict";n.d(t,{MS:()=>s,YG:()=>a,cA:()=>c,ls:()=>o});var r=n(70655);n(83952);var i=n(13154),a=Symbol();function o(e){return!!e.extensions&&Array.isArray(e.extensions[a])}function s(e){return e.hasOwnProperty("graphQLErrors")}var u=function(e){var t=(0,r.ev)((0,r.ev)((0,r.ev)([],e.graphQLErrors,!0),e.clientErrors,!0),e.protocolErrors,!0);return e.networkError&&t.push(e.networkError),t.map(function(e){return(0,i.s)(e)&&e.message||"Error message not found."}).join("\n")},c=function(e){function t(n){var r=n.graphQLErrors,i=n.protocolErrors,a=n.clientErrors,o=n.networkError,s=n.errorMessage,c=n.extraInfo,l=e.call(this,s)||this;return l.name="ApolloError",l.graphQLErrors=r||[],l.protocolErrors=i||[],l.clientErrors=a||[],l.networkError=o||null,l.message=s||u(l),l.extraInfo=c,l.__proto__=t.prototype,l}return(0,r.ZT)(t,e),t}(Error)},85317(e,t,n){"use strict";n.d(t,{K:()=>a});var r=n(67294),i=n(30320).aS?Symbol.for("__APOLLO_CONTEXT__"):"__APOLLO_CONTEXT__";function a(){var e=r.createContext[i];return e||(Object.defineProperty(r.createContext,i,{value:e=r.createContext({}),enumerable:!1,writable:!1,configurable:!0}),e.displayName="ApolloContext"),e}},21436(e,t,n){"use strict";n.d(t,{O:()=>i,k:()=>r});var r=Array.isArray;function i(e){return Array.isArray(e)&&e.length>0}},30320(e,t,n){"use strict";n.d(t,{DN:()=>s,JC:()=>l,aS:()=>o,mr:()=>i,sy:()=>a});var r=n(83952),i="function"==typeof WeakMap&&"ReactNative"!==(0,r.wY)(function(){return navigator.product}),a="function"==typeof WeakSet,o="function"==typeof Symbol&&"function"==typeof Symbol.for,s=o&&Symbol.asyncIterator,u="function"==typeof(0,r.wY)(function(){return window.document.createElement}),c=(0,r.wY)(function(){return navigator.userAgent.indexOf("jsdom")>=0})||!1,l=u&&!c},53712(e,t,n){"use strict";function r(){for(var e=[],t=0;tr})},10542(e,t,n){"use strict";n.d(t,{J:()=>o}),n(83952);var r=n(13154);function i(e){var t=new Set([e]);return t.forEach(function(e){(0,r.s)(e)&&a(e)===e&&Object.getOwnPropertyNames(e).forEach(function(n){(0,r.s)(e[n])&&t.add(e[n])})}),e}function a(e){if(__DEV__&&!Object.isFrozen(e))try{Object.freeze(e)}catch(t){if(t instanceof TypeError)return null;throw t}return e}function o(e){return __DEV__&&i(e),e}},14012(e,t,n){"use strict";n.d(t,{J:()=>a});var r=n(70655),i=n(53712);function a(e,t){return(0,i.o)(e,t,t.variables&&{variables:(0,r.pi)((0,r.pi)({},e&&e.variables),t.variables)})}},13154(e,t,n){"use strict";function r(e){return null!==e&&"object"==typeof e}n.d(t,{s:()=>r})},83952(e,t,n){"use strict";n.d(t,{ej:()=>u,kG:()=>c,wY:()=>h});var r,i=n(70655),a="Invariant Violation",o=Object.setPrototypeOf,s=void 0===o?function(e,t){return e.__proto__=t,e}:o,u=function(e){function t(n){void 0===n&&(n=a);var r=e.call(this,"number"==typeof n?a+": "+n+" (see https://github.com/apollographql/invariant-packages)":n)||this;return r.framesToPop=1,r.name=a,s(r,t.prototype),r}return(0,i.ZT)(t,e),t}(Error);function c(e,t){if(!e)throw new u(t)}var l=["debug","log","warn","error","silent"],f=l.indexOf("log");function d(e){return function(){if(l.indexOf(e)>=f)return(console[e]||console.log).apply(console,arguments)}}function h(e){try{return e()}catch(t){}}(r=c||(c={})).debug=d("debug"),r.log=d("log"),r.warn=d("warn"),r.error=d("error");let p=h(function(){return globalThis})||h(function(){return window})||h(function(){return self})||h(function(){return global})||h(function(){return h.constructor("return this")()});var b="__",m=[b,b].join("DEV");function g(){try{return Boolean(__DEV__)}catch(e){return Object.defineProperty(p,m,{value:"production"!==h(function(){return"production"}),enumerable:!1,configurable:!0,writable:!0}),p[m]}}let v=g();function y(e){try{return e()}catch(t){}}var w=y(function(){return globalThis})||y(function(){return window})||y(function(){return self})||y(function(){return global})||y(function(){return y.constructor("return this")()}),_=!1;function E(){!w||y(function(){return"production"})||y(function(){return process})||(Object.defineProperty(w,"process",{value:{env:{NODE_ENV:"production"}},configurable:!0,enumerable:!1,writable:!0}),_=!0)}function S(){_&&(delete w.process,_=!1)}E();var k=n(10143);function x(){return k.H,S()}function T(){__DEV__?c("boolean"==typeof v,v):c("boolean"==typeof v,39)}x(),T()},4942(e,t,n){"use strict";function r(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}n.d(t,{Z:()=>r})},87462(e,t,n){"use strict";function r(){return(r=Object.assign?Object.assign.bind():function(e){for(var t=1;tr})},51721(e,t,n){"use strict";function r(e,t){return(r=Object.setPrototypeOf?Object.setPrototypeOf.bind():function(e,t){return e.__proto__=t,e})(e,t)}function i(e,t){e.prototype=Object.create(t.prototype),e.prototype.constructor=e,r(e,t)}n.d(t,{Z:()=>i})},63366(e,t,n){"use strict";function r(e,t){if(null==e)return{};var n,r,i={},a=Object.keys(e);for(r=0;r=0||(i[n]=e[n]);return i}n.d(t,{Z:()=>r})},25821(e,t,n){"use strict";n.d(t,{Z:()=>s});var r=n(45695);function i(e){return(i="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e})(e)}var a=10,o=2;function s(e){return u(e,[])}function u(e,t){switch(i(e)){case"string":return JSON.stringify(e);case"function":return e.name?"[function ".concat(e.name,"]"):"[function]";case"object":if(null===e)return"null";return c(e,t);default:return String(e)}}function c(e,t){if(-1!==t.indexOf(e))return"[Circular]";var n=[].concat(t,[e]),r=d(e);if(void 0!==r){var i=r.call(e);if(i!==e)return"string"==typeof i?i:u(i,n)}else if(Array.isArray(e))return f(e,n);return l(e,n)}function l(e,t){var n=Object.keys(e);return 0===n.length?"{}":t.length>o?"["+h(e)+"]":"{ "+n.map(function(n){var r=u(e[n],t);return n+": "+r}).join(", ")+" }"}function f(e,t){if(0===e.length)return"[]";if(t.length>o)return"[Array]";for(var n=Math.min(a,e.length),r=e.length-n,i=[],s=0;s1&&i.push("... ".concat(r," more items")),"["+i.join(", ")+"]"}function d(e){var t=e[String(r.Z)];return"function"==typeof t?t:"function"==typeof e.inspect?e.inspect:void 0}function h(e){var t=Object.prototype.toString.call(e).replace(/^\[object /,"").replace(/]$/,"");if("Object"===t&&"function"==typeof e.constructor){var n=e.constructor.name;if("string"==typeof n&&""!==n)return n}return t}},45695(e,t,n){"use strict";n.d(t,{Z:()=>i});var r="function"==typeof Symbol&&"function"==typeof Symbol.for?Symbol.for("nodejs.util.inspect.custom"):void 0;let i=r},25217(e,t,n){"use strict";function r(e,t){if(!Boolean(e))throw Error(null!=t?t:"Unexpected invariant triggered.")}n.d(t,{Ye:()=>o,WU:()=>s,UG:()=>u});var i=n(45695);function a(e){var t=e.prototype.toJSON;"function"==typeof t||r(0),e.prototype.inspect=t,i.Z&&(e.prototype[i.Z]=t)}var o=function(){function e(e,t,n){this.start=e.start,this.end=t.end,this.startToken=e,this.endToken=t,this.source=n}return e.prototype.toJSON=function(){return{start:this.start,end:this.end}},e}();a(o);var s=function(){function e(e,t,n,r,i,a,o){this.kind=e,this.start=t,this.end=n,this.line=r,this.column=i,this.value=o,this.prev=a,this.next=null}return e.prototype.toJSON=function(){return{kind:this.kind,value:this.value,line:this.line,column:this.column}},e}();function u(e){return null!=e&&"string"==typeof e.kind}a(s)},87392(e,t,n){"use strict";function r(e){var t=e.split(/\r\n|[\n\r]/g),n=a(e);if(0!==n)for(var r=1;ro&&i(t[s-1]);)--s;return t.slice(o,s).join("\n")}function i(e){for(var t=0;t1&&void 0!==arguments[1]?arguments[1]:"",n=arguments.length>2&&void 0!==arguments[2]&&arguments[2],r=-1===e.indexOf("\n"),i=" "===e[0]||" "===e[0],a='"'===e[e.length-1],o="\\"===e[e.length-1],s=!r||a||o||n,u="";return s&&!(r&&i)&&(u+="\n"+t),u+=t?e.replace(/\n/g,"\n"+t):e,s&&(u+="\n"),'"""'+u.replace(/"""/g,'\\"""')+'"""'}n.d(t,{LZ:()=>o,W7:()=>r})},97359(e,t,n){"use strict";n.d(t,{h:()=>r});var r=Object.freeze({NAME:"Name",DOCUMENT:"Document",OPERATION_DEFINITION:"OperationDefinition",VARIABLE_DEFINITION:"VariableDefinition",SELECTION_SET:"SelectionSet",FIELD:"Field",ARGUMENT:"Argument",FRAGMENT_SPREAD:"FragmentSpread",INLINE_FRAGMENT:"InlineFragment",FRAGMENT_DEFINITION:"FragmentDefinition",VARIABLE:"Variable",INT:"IntValue",FLOAT:"FloatValue",STRING:"StringValue",BOOLEAN:"BooleanValue",NULL:"NullValue",ENUM:"EnumValue",LIST:"ListValue",OBJECT:"ObjectValue",OBJECT_FIELD:"ObjectField",DIRECTIVE:"Directive",NAMED_TYPE:"NamedType",LIST_TYPE:"ListType",NON_NULL_TYPE:"NonNullType",SCHEMA_DEFINITION:"SchemaDefinition",OPERATION_TYPE_DEFINITION:"OperationTypeDefinition",SCALAR_TYPE_DEFINITION:"ScalarTypeDefinition",OBJECT_TYPE_DEFINITION:"ObjectTypeDefinition",FIELD_DEFINITION:"FieldDefinition",INPUT_VALUE_DEFINITION:"InputValueDefinition",INTERFACE_TYPE_DEFINITION:"InterfaceTypeDefinition",UNION_TYPE_DEFINITION:"UnionTypeDefinition",ENUM_TYPE_DEFINITION:"EnumTypeDefinition",ENUM_VALUE_DEFINITION:"EnumValueDefinition",INPUT_OBJECT_TYPE_DEFINITION:"InputObjectTypeDefinition",DIRECTIVE_DEFINITION:"DirectiveDefinition",SCHEMA_EXTENSION:"SchemaExtension",SCALAR_TYPE_EXTENSION:"ScalarTypeExtension",OBJECT_TYPE_EXTENSION:"ObjectTypeExtension",INTERFACE_TYPE_EXTENSION:"InterfaceTypeExtension",UNION_TYPE_EXTENSION:"UnionTypeExtension",ENUM_TYPE_EXTENSION:"EnumTypeExtension",INPUT_OBJECT_TYPE_EXTENSION:"InputObjectTypeExtension"})},10143(e,t,n){"use strict";n.d(t,{H:()=>c,T:()=>l});var r=n(99763),i=n(25821);function a(e,t){if(!Boolean(e))throw Error(t)}let o=function(e,t){return e instanceof t};function s(e,t){for(var n=0;n1&&void 0!==arguments[1]?arguments[1]:"GraphQL request",n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{line:1,column:1};"string"==typeof e||a(0,"Body must be a string. Received: ".concat((0,i.Z)(e),".")),this.body=e,this.name=t,this.locationOffset=n,this.locationOffset.line>0||a(0,"line in locationOffset is 1-indexed and must be positive."),this.locationOffset.column>0||a(0,"column in locationOffset is 1-indexed and must be positive.")}return u(e,[{key:r.YF,get:function(){return"Source"}}]),e}();function l(e){return o(e,c)}},99763(e,t,n){"use strict";n.d(t,{YF:()=>r});var r="function"==typeof Symbol&&null!=Symbol.toStringTag?Symbol.toStringTag:"@@toStringTag"},37452(e){"use strict";e.exports=JSON.parse('{"AElig":"\xc6","AMP":"&","Aacute":"\xc1","Acirc":"\xc2","Agrave":"\xc0","Aring":"\xc5","Atilde":"\xc3","Auml":"\xc4","COPY":"\xa9","Ccedil":"\xc7","ETH":"\xd0","Eacute":"\xc9","Ecirc":"\xca","Egrave":"\xc8","Euml":"\xcb","GT":">","Iacute":"\xcd","Icirc":"\xce","Igrave":"\xcc","Iuml":"\xcf","LT":"<","Ntilde":"\xd1","Oacute":"\xd3","Ocirc":"\xd4","Ograve":"\xd2","Oslash":"\xd8","Otilde":"\xd5","Ouml":"\xd6","QUOT":"\\"","REG":"\xae","THORN":"\xde","Uacute":"\xda","Ucirc":"\xdb","Ugrave":"\xd9","Uuml":"\xdc","Yacute":"\xdd","aacute":"\xe1","acirc":"\xe2","acute":"\xb4","aelig":"\xe6","agrave":"\xe0","amp":"&","aring":"\xe5","atilde":"\xe3","auml":"\xe4","brvbar":"\xa6","ccedil":"\xe7","cedil":"\xb8","cent":"\xa2","copy":"\xa9","curren":"\xa4","deg":"\xb0","divide":"\xf7","eacute":"\xe9","ecirc":"\xea","egrave":"\xe8","eth":"\xf0","euml":"\xeb","frac12":"\xbd","frac14":"\xbc","frac34":"\xbe","gt":">","iacute":"\xed","icirc":"\xee","iexcl":"\xa1","igrave":"\xec","iquest":"\xbf","iuml":"\xef","laquo":"\xab","lt":"<","macr":"\xaf","micro":"\xb5","middot":"\xb7","nbsp":"\xa0","not":"\xac","ntilde":"\xf1","oacute":"\xf3","ocirc":"\xf4","ograve":"\xf2","ordf":"\xaa","ordm":"\xba","oslash":"\xf8","otilde":"\xf5","ouml":"\xf6","para":"\xb6","plusmn":"\xb1","pound":"\xa3","quot":"\\"","raquo":"\xbb","reg":"\xae","sect":"\xa7","shy":"\xad","sup1":"\xb9","sup2":"\xb2","sup3":"\xb3","szlig":"\xdf","thorn":"\xfe","times":"\xd7","uacute":"\xfa","ucirc":"\xfb","ugrave":"\xf9","uml":"\xa8","uuml":"\xfc","yacute":"\xfd","yen":"\xa5","yuml":"\xff"}')},93580(e){"use strict";e.exports=JSON.parse('{"0":"�","128":"€","130":"‚","131":"ƒ","132":"„","133":"…","134":"†","135":"‡","136":"ˆ","137":"‰","138":"Š","139":"‹","140":"Œ","142":"Ž","145":"‘","146":"’","147":"“","148":"”","149":"•","150":"–","151":"—","152":"˜","153":"™","154":"š","155":"›","156":"œ","158":"ž","159":"Ÿ"}')},67946(e){"use strict";e.exports=JSON.parse('{"locale":"en","long":{"year":{"previous":"last year","current":"this year","next":"next year","past":{"one":"{0} year ago","other":"{0} years ago"},"future":{"one":"in {0} year","other":"in {0} years"}},"quarter":{"previous":"last quarter","current":"this quarter","next":"next quarter","past":{"one":"{0} quarter ago","other":"{0} quarters ago"},"future":{"one":"in {0} quarter","other":"in {0} quarters"}},"month":{"previous":"last month","current":"this month","next":"next month","past":{"one":"{0} month ago","other":"{0} months ago"},"future":{"one":"in {0} month","other":"in {0} months"}},"week":{"previous":"last week","current":"this week","next":"next week","past":{"one":"{0} week ago","other":"{0} weeks ago"},"future":{"one":"in {0} week","other":"in {0} weeks"}},"day":{"previous":"yesterday","current":"today","next":"tomorrow","past":{"one":"{0} day ago","other":"{0} days ago"},"future":{"one":"in {0} day","other":"in {0} days"}},"hour":{"current":"this hour","past":{"one":"{0} hour ago","other":"{0} hours ago"},"future":{"one":"in {0} hour","other":"in {0} hours"}},"minute":{"current":"this minute","past":{"one":"{0} minute ago","other":"{0} minutes ago"},"future":{"one":"in {0} minute","other":"in {0} minutes"}},"second":{"current":"now","past":{"one":"{0} second ago","other":"{0} seconds ago"},"future":{"one":"in {0} second","other":"in {0} seconds"}}},"short":{"year":{"previous":"last yr.","current":"this yr.","next":"next yr.","past":"{0} yr. ago","future":"in {0} yr."},"quarter":{"previous":"last qtr.","current":"this qtr.","next":"next qtr.","past":{"one":"{0} qtr. ago","other":"{0} qtrs. ago"},"future":{"one":"in {0} qtr.","other":"in {0} qtrs."}},"month":{"previous":"last mo.","current":"this mo.","next":"next mo.","past":"{0} mo. ago","future":"in {0} mo."},"week":{"previous":"last wk.","current":"this wk.","next":"next wk.","past":"{0} wk. ago","future":"in {0} wk."},"day":{"previous":"yesterday","current":"today","next":"tomorrow","past":{"one":"{0} day ago","other":"{0} days ago"},"future":{"one":"in {0} day","other":"in {0} days"}},"hour":{"current":"this hour","past":"{0} hr. ago","future":"in {0} hr."},"minute":{"current":"this minute","past":"{0} min. ago","future":"in {0} min."},"second":{"current":"now","past":"{0} sec. ago","future":"in {0} sec."}},"narrow":{"year":{"previous":"last yr.","current":"this yr.","next":"next yr.","past":"{0} yr. ago","future":"in {0} yr."},"quarter":{"previous":"last qtr.","current":"this qtr.","next":"next qtr.","past":{"one":"{0} qtr. ago","other":"{0} qtrs. ago"},"future":{"one":"in {0} qtr.","other":"in {0} qtrs."}},"month":{"previous":"last mo.","current":"this mo.","next":"next mo.","past":"{0} mo. ago","future":"in {0} mo."},"week":{"previous":"last wk.","current":"this wk.","next":"next wk.","past":"{0} wk. ago","future":"in {0} wk."},"day":{"previous":"yesterday","current":"today","next":"tomorrow","past":{"one":"{0} day ago","other":"{0} days ago"},"future":{"one":"in {0} day","other":"in {0} days"}},"hour":{"current":"this hour","past":"{0} hr. ago","future":"in {0} hr."},"minute":{"current":"this minute","past":"{0} min. ago","future":"in {0} min."},"second":{"current":"now","past":"{0} sec. ago","future":"in {0} sec."}},"now":{"now":{"current":"now","future":"in a moment","past":"just now"}},"mini":{"year":"{0}yr","month":"{0}mo","week":"{0}wk","day":"{0}d","hour":"{0}h","minute":"{0}m","second":"{0}s","now":"now"},"short-time":{"year":"{0} yr.","month":"{0} mo.","week":"{0} wk.","day":{"one":"{0} day","other":"{0} days"},"hour":"{0} hr.","minute":"{0} min.","second":"{0} sec."},"long-time":{"year":{"one":"{0} year","other":"{0} years"},"month":{"one":"{0} month","other":"{0} months"},"week":{"one":"{0} week","other":"{0} weeks"},"day":{"one":"{0} day","other":"{0} days"},"hour":{"one":"{0} hour","other":"{0} hours"},"minute":{"one":"{0} minute","other":"{0} minutes"},"second":{"one":"{0} second","other":"{0} seconds"}}}')}},__webpack_module_cache__={};function __webpack_require__(e){var t=__webpack_module_cache__[e];if(void 0!==t)return t.exports;var n=__webpack_module_cache__[e]={id:e,loaded:!1,exports:{}};return __webpack_modules__[e].call(n.exports,n,n.exports,__webpack_require__),n.loaded=!0,n.exports}__webpack_require__.n=e=>{var t=e&&e.__esModule?()=>e.default:()=>e;return __webpack_require__.d(t,{a:t}),t},(()=>{var e,t=Object.getPrototypeOf?e=>Object.getPrototypeOf(e):e=>e.__proto__;__webpack_require__.t=function(n,r){if(1&r&&(n=this(n)),8&r||"object"==typeof n&&n&&(4&r&&n.__esModule||16&r&&"function"==typeof n.then))return n;var i=Object.create(null);__webpack_require__.r(i);var a={};e=e||[null,t({}),t([]),t(t)];for(var o=2&r&&n;"object"==typeof o&&!~e.indexOf(o);o=t(o))Object.getOwnPropertyNames(o).forEach(e=>a[e]=()=>n[e]);return a.default=()=>n,__webpack_require__.d(i,a),i}})(),__webpack_require__.d=(e,t)=>{for(var n in t)__webpack_require__.o(t,n)&&!__webpack_require__.o(e,n)&&Object.defineProperty(e,n,{enumerable:!0,get:t[n]})},__webpack_require__.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||Function("return this")()}catch(e){if("object"==typeof window)return window}}(),__webpack_require__.hmd=e=>((e=Object.create(e)).children||(e.children=[]),Object.defineProperty(e,"exports",{enumerable:!0,set(){throw Error("ES Modules may not assign module.exports or exports.*, Use ESM export syntax, instead: "+e.id)}}),e),__webpack_require__.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),__webpack_require__.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},__webpack_require__.nmd=e=>(e.paths=[],e.children||(e.children=[]),e),__webpack_require__.p="/assets/",__webpack_require__.nc=void 0;var __webpack_exports__={};(()=>{"use strict";var e,t,n,r,i=__webpack_require__(32316),a=__webpack_require__(8126),o=__webpack_require__(5690),s=__webpack_require__(30381),u=__webpack_require__.n(s),c=__webpack_require__(67294),l=__webpack_require__(73935),f=__webpack_require__.n(l),d=__webpack_require__(57209),h=__webpack_require__(37703),p=__webpack_require__(97779),b=__webpack_require__(28500);function m(e){return function(t){var n=t.dispatch,r=t.getState;return function(t){return function(i){return"function"==typeof i?i(n,r,e):t(i)}}}}var g=m();g.withExtraArgument=m;let v=g;var y=__webpack_require__(76489);function w(e){return function(t){return function(n){return function(r){n(r);var i=e||document&&document.cookie||"",a=t.getState();if("MATCH_ROUTE"===r.type&&"/signin"!==a.notifications.currentUrl){var o=(0,y.Q)(i);if(o.explorer)try{var s=JSON.parse(o.explorer);if("error"===s.status){var u=_(s.url);n({type:"NOTIFY_ERROR_MSG",msg:u})}}catch(c){n({type:"NOTIFY_ERROR_MSG",msg:"Invalid explorer status"})}}}}}}function _(e){var t="Can't connect to explorer: ".concat(e);return e.match(/^wss?:.+/)?t:"".concat(t,". You must use a websocket.")}var E=__webpack_require__(16353);function S(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n=e.length?{done:!0}:{done:!1,value:e[r++]}}}throw TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}function ei(e,t){if(e){if("string"==typeof e)return ea(e,t);var n=Object.prototype.toString.call(e).slice(8,-1);if("Object"===n&&e.constructor&&(n=e.constructor.name),"Map"===n||"Set"===n)return Array.from(e);if("Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n))return ea(e,t)}}function ea(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n1,i=!1,a=arguments[1],o=a;return new n(function(n){return t.subscribe({next:function(t){var a=!i;if(i=!0,!a||r)try{o=e(o,t)}catch(s){return n.error(s)}else o=t},error:function(e){n.error(e)},complete:function(){if(!i&&!r)return n.error(TypeError("Cannot reduce an empty sequence"));n.next(o),n.complete()}})})},t.concat=function(){for(var e=this,t=arguments.length,n=Array(t),r=0;r=0&&i.splice(e,1),o()}});i.push(s)},error:function(e){r.error(e)},complete:function(){o()}});function o(){a.closed&&0===i.length&&r.complete()}return function(){i.forEach(function(e){return e.unsubscribe()}),a.unsubscribe()}})},t[ed]=function(){return this},e.from=function(t){var n="function"==typeof this?this:e;if(null==t)throw TypeError(t+" is not an object");var r=ep(t,ed);if(r){var i=r.call(t);if(Object(i)!==i)throw TypeError(i+" is not an object");return em(i)&&i.constructor===n?i:new n(function(e){return i.subscribe(e)})}if(ec("iterator")&&(r=ep(t,ef)))return new n(function(e){ev(function(){if(!e.closed){for(var n,i=er(r.call(t));!(n=i()).done;){var a=n.value;if(e.next(a),e.closed)return}e.complete()}})});if(Array.isArray(t))return new n(function(e){ev(function(){if(!e.closed){for(var n=0;n0))return n.connection.key;var r=n.connection.filter?n.connection.filter:[];r.sort();var i={};return r.forEach(function(e){i[e]=t[e]}),"".concat(n.connection.key,"(").concat(eV(i),")")}var a=e;if(t){var o=eV(t);a+="(".concat(o,")")}return n&&Object.keys(n).forEach(function(e){-1===eW.indexOf(e)&&(n[e]&&Object.keys(n[e]).length?a+="@".concat(e,"(").concat(eV(n[e]),")"):a+="@".concat(e))}),a},{setStringify:function(e){var t=eV;return eV=e,t}}),eV=function(e){return JSON.stringify(e,eq)};function eq(e,t){return(0,eO.s)(t)&&!Array.isArray(t)&&(t=Object.keys(t).sort().reduce(function(e,n){return e[n]=t[n],e},{})),t}function eZ(e,t){if(e.arguments&&e.arguments.length){var n={};return e.arguments.forEach(function(e){var r;return ez(n,e.name,e.value,t)}),n}return null}function eX(e){return e.alias?e.alias.value:e.name.value}function eJ(e,t,n){for(var r,i=0,a=t.selections;it.indexOf(i))throw __DEV__?new Q.ej("illegal argument: ".concat(i)):new Q.ej(27)}return e}function tt(e,t){return t?t(e):eT.of()}function tn(e){return"function"==typeof e?new ta(e):e}function tr(e){return e.request.length<=1}var ti=function(e){function t(t,n){var r=e.call(this,t)||this;return r.link=n,r}return(0,en.ZT)(t,e),t}(Error),ta=function(){function e(e){e&&(this.request=e)}return e.empty=function(){return new e(function(){return eT.of()})},e.from=function(t){return 0===t.length?e.empty():t.map(tn).reduce(function(e,t){return e.concat(t)})},e.split=function(t,n,r){var i=tn(n),a=tn(r||new e(tt));return new e(tr(i)&&tr(a)?function(e){return t(e)?i.request(e)||eT.of():a.request(e)||eT.of()}:function(e,n){return t(e)?i.request(e,n)||eT.of():a.request(e,n)||eT.of()})},e.execute=function(e,t){return e.request(eM(t.context,e7(te(t))))||eT.of()},e.concat=function(t,n){var r=tn(t);if(tr(r))return __DEV__&&Q.kG.warn(new ti("You are calling concat on a terminating link, which will have no effect",r)),r;var i=tn(n);return new e(tr(i)?function(e){return r.request(e,function(e){return i.request(e)||eT.of()})||eT.of()}:function(e,t){return r.request(e,function(e){return i.request(e,t)||eT.of()})||eT.of()})},e.prototype.split=function(t,n,r){return this.concat(e.split(t,n,r||new e(tt)))},e.prototype.concat=function(t){return e.concat(this,t)},e.prototype.request=function(e,t){throw __DEV__?new Q.ej("request is not implemented"):new Q.ej(22)},e.prototype.onError=function(e,t){if(t&&t.error)return t.error(e),!1;throw e},e.prototype.setOnError=function(e){return this.onError=e,this},e}(),to=__webpack_require__(25821),ts=__webpack_require__(25217),tu={Name:[],Document:["definitions"],OperationDefinition:["name","variableDefinitions","directives","selectionSet"],VariableDefinition:["variable","type","defaultValue","directives"],Variable:["name"],SelectionSet:["selections"],Field:["alias","name","arguments","directives","selectionSet"],Argument:["name","value"],FragmentSpread:["name","directives"],InlineFragment:["typeCondition","directives","selectionSet"],FragmentDefinition:["name","variableDefinitions","typeCondition","directives","selectionSet"],IntValue:[],FloatValue:[],StringValue:[],BooleanValue:[],NullValue:[],EnumValue:[],ListValue:["values"],ObjectValue:["fields"],ObjectField:["name","value"],Directive:["name","arguments"],NamedType:["name"],ListType:["type"],NonNullType:["type"],SchemaDefinition:["description","directives","operationTypes"],OperationTypeDefinition:["type"],ScalarTypeDefinition:["description","name","directives"],ObjectTypeDefinition:["description","name","interfaces","directives","fields"],FieldDefinition:["description","name","arguments","type","directives"],InputValueDefinition:["description","name","type","defaultValue","directives"],InterfaceTypeDefinition:["description","name","interfaces","directives","fields"],UnionTypeDefinition:["description","name","directives","types"],EnumTypeDefinition:["description","name","directives","values"],EnumValueDefinition:["description","name","directives"],InputObjectTypeDefinition:["description","name","directives","fields"],DirectiveDefinition:["description","name","arguments","locations"],SchemaExtension:["directives","operationTypes"],ScalarTypeExtension:["name","directives"],ObjectTypeExtension:["name","interfaces","directives","fields"],InterfaceTypeExtension:["name","interfaces","directives","fields"],UnionTypeExtension:["name","directives","types"],EnumTypeExtension:["name","directives","values"],InputObjectTypeExtension:["name","directives","fields"]},tc=Object.freeze({});function tl(e,t){var n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:tu,r=void 0,i=Array.isArray(e),a=[e],o=-1,s=[],u=void 0,c=void 0,l=void 0,f=[],d=[],h=e;do{var p,b=++o===a.length,m=b&&0!==s.length;if(b){if(c=0===d.length?void 0:f[f.length-1],u=l,l=d.pop(),m){if(i)u=u.slice();else{for(var g={},v=0,y=Object.keys(u);v1)for(var r=new tB,i=1;i=0;--a){var o=i[a],s=isNaN(+o)?{}:[];s[o]=t,t=s}n=r.merge(n,t)}),n}var tW=Object.prototype.hasOwnProperty;function tK(e,t){var n,r,i,a,o;return(0,en.mG)(this,void 0,void 0,function(){var s,u,c,l,f,d,h,p,b,m,g,v,y,w,_,E,S,k,x,T,M,O,A;return(0,en.Jh)(this,function(L){switch(L.label){case 0:if(void 0===TextDecoder)throw Error("TextDecoder must be defined in the environment: please import a polyfill.");s=new TextDecoder("utf-8"),u=null===(n=e.headers)||void 0===n?void 0:n.get("content-type"),c="boundary=",l=(null==u?void 0:u.includes(c))?null==u?void 0:u.substring((null==u?void 0:u.indexOf(c))+c.length).replace(/['"]/g,"").replace(/\;(.*)/gm,"").trim():"-",f="\r\n--".concat(l),d="",h=tI(e),p=!0,L.label=1;case 1:if(!p)return[3,3];return[4,h.next()];case 2:for(m=(b=L.sent()).value,g=b.done,v="string"==typeof m?m:s.decode(m),y=d.length-f.length+1,p=!g,d+=v,w=d.indexOf(f,y);w>-1;){if(_=void 0,_=(O=[d.slice(0,w),d.slice(w+f.length),])[0],d=O[1],E=_.indexOf("\r\n\r\n"),(k=(S=tV(_.slice(0,E)))["content-type"])&&-1===k.toLowerCase().indexOf("application/json"))throw Error("Unsupported patch content type: application/json is required.");if(x=_.slice(E))try{T=tq(e,x),Object.keys(T).length>1||"data"in T||"incremental"in T||"errors"in T||"payload"in T?tz(T)?(M={},"payload"in T&&(M=(0,en.pi)({},T.payload)),"errors"in T&&(M=(0,en.pi)((0,en.pi)({},M),{extensions:(0,en.pi)((0,en.pi)({},"extensions"in M?M.extensions:null),((A={})[tN.YG]=T.errors,A))})),null===(r=t.next)||void 0===r||r.call(t,M)):null===(i=t.next)||void 0===i||i.call(t,T):1===Object.keys(T).length&&"hasNext"in T&&!T.hasNext&&(null===(a=t.complete)||void 0===a||a.call(t))}catch(C){tZ(C,t)}w=d.indexOf(f)}return[3,1];case 3:return null===(o=t.complete)||void 0===o||o.call(t),[2]}})})}function tV(e){var t={};return e.split("\n").forEach(function(e){var n=e.indexOf(":");if(n>-1){var r=e.slice(0,n).trim().toLowerCase(),i=e.slice(n+1).trim();t[r]=i}}),t}function tq(e,t){e.status>=300&&tD(e,function(){try{return JSON.parse(t)}catch(e){return t}}(),"Response not successful: Received status code ".concat(e.status));try{return JSON.parse(t)}catch(n){var r=n;throw r.name="ServerParseError",r.response=e,r.statusCode=e.status,r.bodyText=t,r}}function tZ(e,t){var n,r;"AbortError"!==e.name&&(e.result&&e.result.errors&&e.result.data&&(null===(n=t.next)||void 0===n||n.call(t,e.result)),null===(r=t.error)||void 0===r||r.call(t,e))}function tX(e,t,n){tJ(t)(e).then(function(e){var t,r;null===(t=n.next)||void 0===t||t.call(n,e),null===(r=n.complete)||void 0===r||r.call(n)}).catch(function(e){return tZ(e,n)})}function tJ(e){return function(t){return t.text().then(function(e){return tq(t,e)}).then(function(n){return t.status>=300&&tD(t,n,"Response not successful: Received status code ".concat(t.status)),Array.isArray(n)||tW.call(n,"data")||tW.call(n,"errors")||tD(t,n,"Server response was missing for query '".concat(Array.isArray(e)?e.map(function(e){return e.operationName}):e.operationName,"'.")),n})}}var tQ=function(e){if(!e&&"undefined"==typeof fetch)throw __DEV__?new Q.ej("\n\"fetch\" has not been found globally and no fetcher has been configured. To fix this, install a fetch package (like https://www.npmjs.com/package/cross-fetch), instantiate the fetcher, and pass it into your HttpLink constructor. For example:\n\nimport fetch from 'cross-fetch';\nimport { ApolloClient, HttpLink } from '@apollo/client';\nconst client = new ApolloClient({\n link: new HttpLink({ uri: '/graphql', fetch })\n});\n "):new Q.ej(23)},t1=__webpack_require__(87392);function t0(e){return tl(e,{leave:t3})}var t2=80,t3={Name:function(e){return e.value},Variable:function(e){return"$"+e.name},Document:function(e){return t6(e.definitions,"\n\n")+"\n"},OperationDefinition:function(e){var t=e.operation,n=e.name,r=t8("(",t6(e.variableDefinitions,", "),")"),i=t6(e.directives," "),a=e.selectionSet;return n||i||r||"query"!==t?t6([t,t6([n,r]),i,a]," "):a},VariableDefinition:function(e){var t=e.variable,n=e.type,r=e.defaultValue,i=e.directives;return t+": "+n+t8(" = ",r)+t8(" ",t6(i," "))},SelectionSet:function(e){return t5(e.selections)},Field:function(e){var t=e.alias,n=e.name,r=e.arguments,i=e.directives,a=e.selectionSet,o=t8("",t,": ")+n,s=o+t8("(",t6(r,", "),")");return s.length>t2&&(s=o+t8("(\n",t9(t6(r,"\n")),"\n)")),t6([s,t6(i," "),a]," ")},Argument:function(e){var t;return e.name+": "+e.value},FragmentSpread:function(e){var t;return"..."+e.name+t8(" ",t6(e.directives," "))},InlineFragment:function(e){var t=e.typeCondition,n=e.directives,r=e.selectionSet;return t6(["...",t8("on ",t),t6(n," "),r]," ")},FragmentDefinition:function(e){var t=e.name,n=e.typeCondition,r=e.variableDefinitions,i=e.directives,a=e.selectionSet;return"fragment ".concat(t).concat(t8("(",t6(r,", "),")")," ")+"on ".concat(n," ").concat(t8("",t6(i," ")," "))+a},IntValue:function(e){return e.value},FloatValue:function(e){return e.value},StringValue:function(e,t){var n=e.value;return e.block?(0,t1.LZ)(n,"description"===t?"":" "):JSON.stringify(n)},BooleanValue:function(e){return e.value?"true":"false"},NullValue:function(){return"null"},EnumValue:function(e){return e.value},ListValue:function(e){return"["+t6(e.values,", ")+"]"},ObjectValue:function(e){return"{"+t6(e.fields,", ")+"}"},ObjectField:function(e){var t;return e.name+": "+e.value},Directive:function(e){var t;return"@"+e.name+t8("(",t6(e.arguments,", "),")")},NamedType:function(e){return e.name},ListType:function(e){return"["+e.type+"]"},NonNullType:function(e){return e.type+"!"},SchemaDefinition:t4(function(e){var t=e.directives,n=e.operationTypes;return t6(["schema",t6(t," "),t5(n)]," ")}),OperationTypeDefinition:function(e){var t;return e.operation+": "+e.type},ScalarTypeDefinition:t4(function(e){var t;return t6(["scalar",e.name,t6(e.directives," ")]," ")}),ObjectTypeDefinition:t4(function(e){var t=e.name,n=e.interfaces,r=e.directives,i=e.fields;return t6(["type",t,t8("implements ",t6(n," & ")),t6(r," "),t5(i)]," ")}),FieldDefinition:t4(function(e){var t=e.name,n=e.arguments,r=e.type,i=e.directives;return t+(ne(n)?t8("(\n",t9(t6(n,"\n")),"\n)"):t8("(",t6(n,", "),")"))+": "+r+t8(" ",t6(i," "))}),InputValueDefinition:t4(function(e){var t=e.name,n=e.type,r=e.defaultValue,i=e.directives;return t6([t+": "+n,t8("= ",r),t6(i," ")]," ")}),InterfaceTypeDefinition:t4(function(e){var t=e.name,n=e.interfaces,r=e.directives,i=e.fields;return t6(["interface",t,t8("implements ",t6(n," & ")),t6(r," "),t5(i)]," ")}),UnionTypeDefinition:t4(function(e){var t=e.name,n=e.directives,r=e.types;return t6(["union",t,t6(n," "),r&&0!==r.length?"= "+t6(r," | "):""]," ")}),EnumTypeDefinition:t4(function(e){var t=e.name,n=e.directives,r=e.values;return t6(["enum",t,t6(n," "),t5(r)]," ")}),EnumValueDefinition:t4(function(e){var t;return t6([e.name,t6(e.directives," ")]," ")}),InputObjectTypeDefinition:t4(function(e){var t=e.name,n=e.directives,r=e.fields;return t6(["input",t,t6(n," "),t5(r)]," ")}),DirectiveDefinition:t4(function(e){var t=e.name,n=e.arguments,r=e.repeatable,i=e.locations;return"directive @"+t+(ne(n)?t8("(\n",t9(t6(n,"\n")),"\n)"):t8("(",t6(n,", "),")"))+(r?" repeatable":"")+" on "+t6(i," | ")}),SchemaExtension:function(e){var t=e.directives,n=e.operationTypes;return t6(["extend schema",t6(t," "),t5(n)]," ")},ScalarTypeExtension:function(e){var t;return t6(["extend scalar",e.name,t6(e.directives," ")]," ")},ObjectTypeExtension:function(e){var t=e.name,n=e.interfaces,r=e.directives,i=e.fields;return t6(["extend type",t,t8("implements ",t6(n," & ")),t6(r," "),t5(i)]," ")},InterfaceTypeExtension:function(e){var t=e.name,n=e.interfaces,r=e.directives,i=e.fields;return t6(["extend interface",t,t8("implements ",t6(n," & ")),t6(r," "),t5(i)]," ")},UnionTypeExtension:function(e){var t=e.name,n=e.directives,r=e.types;return t6(["extend union",t,t6(n," "),r&&0!==r.length?"= "+t6(r," | "):""]," ")},EnumTypeExtension:function(e){var t=e.name,n=e.directives,r=e.values;return t6(["extend enum",t,t6(n," "),t5(r)]," ")},InputObjectTypeExtension:function(e){var t=e.name,n=e.directives,r=e.fields;return t6(["extend input",t,t6(n," "),t5(r)]," ")}};function t4(e){return function(t){return t6([t.description,e(t)],"\n")}}function t6(e){var t,n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"";return null!==(t=null==e?void 0:e.filter(function(e){return e}).join(n))&&void 0!==t?t:""}function t5(e){return t8("{\n",t9(t6(e,"\n")),"\n}")}function t8(e,t){var n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:"";return null!=t&&""!==t?e+t+n:""}function t9(e){return t8(" ",e.replace(/\n/g,"\n "))}function t7(e){return -1!==e.indexOf("\n")}function ne(e){return null!=e&&e.some(t7)}var nt,nn,nr,ni={http:{includeQuery:!0,includeExtensions:!1,preserveHeaderCase:!1},headers:{accept:"*/*","content-type":"application/json"},options:{method:"POST"}},na=function(e,t){return t(e)};function no(e,t){for(var n=[],r=2;rObject.create(null),{forEach:nv,slice:ny}=Array.prototype,{hasOwnProperty:nw}=Object.prototype;class n_{constructor(e=!0,t=ng){this.weakness=e,this.makeData=t}lookup(...e){return this.lookupArray(e)}lookupArray(e){let t=this;return nv.call(e,e=>t=t.getChildTrie(e)),nw.call(t,"data")?t.data:t.data=this.makeData(ny.call(e))}peek(...e){return this.peekArray(e)}peekArray(e){let t=this;for(let n=0,r=e.length;t&&n=0;--o)t.definitions[o].kind===nL.h.OPERATION_DEFINITION&&++a;var s=nN(e),u=e.some(function(e){return e.remove}),c=function(e){return u&&e&&e.some(s)},l=new Map,f=!1,d={enter:function(e){if(c(e.directives))return f=!0,null}},h=tl(t,{Field:d,InlineFragment:d,VariableDefinition:{enter:function(){return!1}},Variable:{enter:function(e,t,n,r,a){var o=i(a);o&&o.variables.add(e.name.value)}},FragmentSpread:{enter:function(e,t,n,r,a){if(c(e.directives))return f=!0,null;var o=i(a);o&&o.fragmentSpreads.add(e.name.value)}},FragmentDefinition:{enter:function(e,t,n,r){l.set(JSON.stringify(r),e)},leave:function(e,t,n,i){return e===l.get(JSON.stringify(i))?e:a>0&&e.selectionSet.selections.every(function(e){return e.kind===nL.h.FIELD&&"__typename"===e.name.value})?(r(e.name.value).removed=!0,f=!0,null):void 0}},Directive:{leave:function(e){if(s(e))return f=!0,null}}});if(!f)return t;var p=function(e){return e.transitiveVars||(e.transitiveVars=new Set(e.variables),e.removed||e.fragmentSpreads.forEach(function(t){p(r(t)).transitiveVars.forEach(function(t){e.transitiveVars.add(t)})})),e},b=new Set;h.definitions.forEach(function(e){e.kind===nL.h.OPERATION_DEFINITION?p(n(e.name&&e.name.value)).fragmentSpreads.forEach(function(e){b.add(e)}):e.kind!==nL.h.FRAGMENT_DEFINITION||0!==a||r(e.name.value).removed||b.add(e.name.value)}),b.forEach(function(e){p(r(e)).fragmentSpreads.forEach(function(e){b.add(e)})});var m=function(e){return!!(!b.has(e)||r(e).removed)},g={enter:function(e){if(m(e.name.value))return null}};return nD(tl(h,{FragmentSpread:g,FragmentDefinition:g,OperationDefinition:{leave:function(e){if(e.variableDefinitions){var t=p(n(e.name&&e.name.value)).transitiveVars;if(t.size0},t.prototype.tearDownQuery=function(){this.isTornDown||(this.concast&&this.observer&&(this.concast.removeObserver(this.observer),delete this.concast,delete this.observer),this.stopPolling(),this.subscriptions.forEach(function(e){return e.unsubscribe()}),this.subscriptions.clear(),this.queryManager.stopQuery(this.queryId),this.observers.clear(),this.isTornDown=!0)},t}(eT);function n4(e){var t=e.options,n=t.fetchPolicy,r=t.nextFetchPolicy;return"cache-and-network"===n||"network-only"===n?e.reobserve({fetchPolicy:"cache-first",nextFetchPolicy:function(){return(this.nextFetchPolicy=r,"function"==typeof r)?r.apply(this,arguments):n}}):e.reobserve()}function n6(e){__DEV__&&Q.kG.error("Unhandled error",e.message,e.stack)}function n5(e){__DEV__&&e&&__DEV__&&Q.kG.debug("Missing cache result fields: ".concat(JSON.stringify(e)),e)}function n8(e){return"network-only"===e||"no-cache"===e||"standby"===e}nK(n3);function n9(e){return e.kind===nL.h.FIELD||e.kind===nL.h.FRAGMENT_SPREAD||e.kind===nL.h.INLINE_FRAGMENT}function n7(e){return e.kind===Kind.SCALAR_TYPE_DEFINITION||e.kind===Kind.OBJECT_TYPE_DEFINITION||e.kind===Kind.INTERFACE_TYPE_DEFINITION||e.kind===Kind.UNION_TYPE_DEFINITION||e.kind===Kind.ENUM_TYPE_DEFINITION||e.kind===Kind.INPUT_OBJECT_TYPE_DEFINITION}function re(e){return e.kind===Kind.SCALAR_TYPE_EXTENSION||e.kind===Kind.OBJECT_TYPE_EXTENSION||e.kind===Kind.INTERFACE_TYPE_EXTENSION||e.kind===Kind.UNION_TYPE_EXTENSION||e.kind===Kind.ENUM_TYPE_EXTENSION||e.kind===Kind.INPUT_OBJECT_TYPE_EXTENSION}var rt=function(){return Object.create(null)},rn=Array.prototype,rr=rn.forEach,ri=rn.slice,ra=function(){function e(e,t){void 0===e&&(e=!0),void 0===t&&(t=rt),this.weakness=e,this.makeData=t}return e.prototype.lookup=function(){for(var e=[],t=0;tclass{constructor(){this.id=["slot",rc++,Date.now(),Math.random().toString(36).slice(2),].join(":")}hasValue(){for(let e=rs;e;e=e.parent)if(this.id in e.slots){let t=e.slots[this.id];if(t===ru)break;return e!==rs&&(rs.slots[this.id]=t),!0}return rs&&(rs.slots[this.id]=ru),!1}getValue(){if(this.hasValue())return rs.slots[this.id]}withValue(e,t,n,r){let i={__proto__:null,[this.id]:e},a=rs;rs={parent:a,slots:i};try{return t.apply(r,n)}finally{rs=a}}static bind(e){let t=rs;return function(){let n=rs;try{return rs=t,e.apply(this,arguments)}finally{rs=n}}}static noContext(e,t,n){if(!rs)return e.apply(n,t);{let r=rs;try{return rs=null,e.apply(n,t)}finally{rs=r}}}};function rf(e){try{return e()}catch(t){}}let rd="@wry/context:Slot",rh=rf(()=>globalThis)||rf(()=>global)||Object.create(null),rp=rh,rb=rp[rd]||Array[rd]||function(e){try{Object.defineProperty(rp,rd,{value:e,enumerable:!1,writable:!1,configurable:!0})}finally{return e}}(rl()),{bind:rm,noContext:rg}=rb;function rv(){}var ry=function(){function e(e,t){void 0===e&&(e=1/0),void 0===t&&(t=rv),this.max=e,this.dispose=t,this.map=new Map,this.newest=null,this.oldest=null}return e.prototype.has=function(e){return this.map.has(e)},e.prototype.get=function(e){var t=this.getNode(e);return t&&t.value},e.prototype.getNode=function(e){var t=this.map.get(e);if(t&&t!==this.newest){var n=t.older,r=t.newer;r&&(r.older=n),n&&(n.newer=r),t.older=this.newest,t.older.newer=t,t.newer=null,this.newest=t,t===this.oldest&&(this.oldest=r)}return t},e.prototype.set=function(e,t){var n=this.getNode(e);return n?n.value=t:(n={key:e,value:t,newer:null,older:this.newest},this.newest&&(this.newest.newer=n),this.newest=n,this.oldest=this.oldest||n,this.map.set(e,n),n.value)},e.prototype.clean=function(){for(;this.oldest&&this.map.size>this.max;)this.delete(this.oldest.key)},e.prototype.delete=function(e){var t=this.map.get(e);return!!t&&(t===this.newest&&(this.newest=t.older),t===this.oldest&&(this.oldest=t.newer),t.newer&&(t.newer.older=t.older),t.older&&(t.older.newer=t.newer),this.map.delete(e),this.dispose(t.value,e),!0)},e}(),rw=new rb,r_=Object.prototype.hasOwnProperty,rE=void 0===(n=Array.from)?function(e){var t=[];return e.forEach(function(e){return t.push(e)}),t}:n;function rS(e){var t=e.unsubscribe;"function"==typeof t&&(e.unsubscribe=void 0,t())}var rk=[],rx=100;function rT(e,t){if(!e)throw Error(t||"assertion failure")}function rM(e,t){var n=e.length;return n>0&&n===t.length&&e[n-1]===t[n-1]}function rO(e){switch(e.length){case 0:throw Error("unknown value");case 1:return e[0];case 2:throw e[1]}}function rA(e){return e.slice(0)}var rL=function(){function e(t){this.fn=t,this.parents=new Set,this.childValues=new Map,this.dirtyChildren=null,this.dirty=!0,this.recomputing=!1,this.value=[],this.deps=null,++e.count}return e.prototype.peek=function(){if(1===this.value.length&&!rN(this))return rC(this),this.value[0]},e.prototype.recompute=function(e){return rT(!this.recomputing,"already recomputing"),rC(this),rN(this)?rI(this,e):rO(this.value)},e.prototype.setDirty=function(){this.dirty||(this.dirty=!0,this.value.length=0,rR(this),rS(this))},e.prototype.dispose=function(){var e=this;this.setDirty(),rH(this),rF(this,function(t,n){t.setDirty(),r$(t,e)})},e.prototype.forget=function(){this.dispose()},e.prototype.dependOn=function(e){e.add(this),this.deps||(this.deps=rk.pop()||new Set),this.deps.add(e)},e.prototype.forgetDeps=function(){var e=this;this.deps&&(rE(this.deps).forEach(function(t){return t.delete(e)}),this.deps.clear(),rk.push(this.deps),this.deps=null)},e.count=0,e}();function rC(e){var t=rw.getValue();if(t)return e.parents.add(t),t.childValues.has(e)||t.childValues.set(e,[]),rN(e)?rY(t,e):rB(t,e),t}function rI(e,t){return rH(e),rw.withValue(e,rD,[e,t]),rz(e,t)&&rP(e),rO(e.value)}function rD(e,t){e.recomputing=!0,e.value.length=0;try{e.value[0]=e.fn.apply(null,t)}catch(n){e.value[1]=n}e.recomputing=!1}function rN(e){return e.dirty||!!(e.dirtyChildren&&e.dirtyChildren.size)}function rP(e){e.dirty=!1,!rN(e)&&rj(e)}function rR(e){rF(e,rY)}function rj(e){rF(e,rB)}function rF(e,t){var n=e.parents.size;if(n)for(var r=rE(e.parents),i=0;i0&&e.childValues.forEach(function(t,n){r$(e,n)}),e.forgetDeps(),rT(null===e.dirtyChildren)}function r$(e,t){t.parents.delete(e),e.childValues.delete(t),rU(e,t)}function rz(e,t){if("function"==typeof e.subscribe)try{rS(e),e.unsubscribe=e.subscribe.apply(null,t)}catch(n){return e.setDirty(),!1}return!0}var rG={setDirty:!0,dispose:!0,forget:!0};function rW(e){var t=new Map,n=e&&e.subscribe;function r(e){var r=rw.getValue();if(r){var i=t.get(e);i||t.set(e,i=new Set),r.dependOn(i),"function"==typeof n&&(rS(i),i.unsubscribe=n(e))}}return r.dirty=function(e,n){var r=t.get(e);if(r){var i=n&&r_.call(rG,n)?n:"setDirty";rE(r).forEach(function(e){return e[i]()}),t.delete(e),rS(r)}},r}function rK(){var e=new ra("function"==typeof WeakMap);return function(){return e.lookupArray(arguments)}}var rV=rK(),rq=new Set;function rZ(e,t){void 0===t&&(t=Object.create(null));var n=new ry(t.max||65536,function(e){return e.dispose()}),r=t.keyArgs,i=t.makeCacheKey||rK(),a=function(){var a=i.apply(null,r?r.apply(null,arguments):arguments);if(void 0===a)return e.apply(null,arguments);var o=n.get(a);o||(n.set(a,o=new rL(e)),o.subscribe=t.subscribe,o.forget=function(){return n.delete(a)});var s=o.recompute(Array.prototype.slice.call(arguments));return n.set(a,o),rq.add(n),rw.hasValue()||(rq.forEach(function(e){return e.clean()}),rq.clear()),s};function o(e){var t=n.get(e);t&&t.setDirty()}function s(e){var t=n.get(e);if(t)return t.peek()}function u(e){return n.delete(e)}return Object.defineProperty(a,"size",{get:function(){return n.map.size},configurable:!1,enumerable:!1}),a.dirtyKey=o,a.dirty=function(){o(i.apply(null,arguments))},a.peekKey=s,a.peek=function(){return s(i.apply(null,arguments))},a.forgetKey=u,a.forget=function(){return u(i.apply(null,arguments))},a.makeCacheKey=i,a.getKey=r?function(){return i.apply(null,r.apply(null,arguments))}:i,Object.freeze(a)}var rX=new rb,rJ=new WeakMap;function rQ(e){var t=rJ.get(e);return t||rJ.set(e,t={vars:new Set,dep:rW()}),t}function r1(e){rQ(e).vars.forEach(function(t){return t.forgetCache(e)})}function r0(e){rQ(e).vars.forEach(function(t){return t.attachCache(e)})}function r2(e){var t=new Set,n=new Set,r=function(a){if(arguments.length>0){if(e!==a){e=a,t.forEach(function(e){rQ(e).dep.dirty(r),r3(e)});var o=Array.from(n);n.clear(),o.forEach(function(t){return t(e)})}}else{var s=rX.getValue();s&&(i(s),rQ(s).dep(r))}return e};r.onNextChange=function(e){return n.add(e),function(){n.delete(e)}};var i=r.attachCache=function(e){return t.add(e),rQ(e).vars.add(r),r};return r.forgetCache=function(e){return t.delete(e)},r}function r3(e){e.broadcastWatches&&e.broadcastWatches()}var r4=function(){function e(e){var t=e.cache,n=e.client,r=e.resolvers,i=e.fragmentMatcher;this.selectionsToResolveCache=new WeakMap,this.cache=t,n&&(this.client=n),r&&this.addResolvers(r),i&&this.setFragmentMatcher(i)}return e.prototype.addResolvers=function(e){var t=this;this.resolvers=this.resolvers||{},Array.isArray(e)?e.forEach(function(e){t.resolvers=tj(t.resolvers,e)}):this.resolvers=tj(this.resolvers,e)},e.prototype.setResolvers=function(e){this.resolvers={},this.addResolvers(e)},e.prototype.getResolvers=function(){return this.resolvers||{}},e.prototype.runResolvers=function(e){var t=e.document,n=e.remoteResult,r=e.context,i=e.variables,a=e.onlyRunForcedResolvers,o=void 0!==a&&a;return(0,en.mG)(this,void 0,void 0,function(){return(0,en.Jh)(this,function(e){return t?[2,this.resolveDocument(t,n.data,r,i,this.fragmentMatcher,o).then(function(e){return(0,en.pi)((0,en.pi)({},n),{data:e.result})})]:[2,n]})})},e.prototype.setFragmentMatcher=function(e){this.fragmentMatcher=e},e.prototype.getFragmentMatcher=function(){return this.fragmentMatcher},e.prototype.clientQuery=function(e){return tb(["client"],e)&&this.resolvers?e:null},e.prototype.serverQuery=function(e){return n$(e)},e.prototype.prepareContext=function(e){var t=this.cache;return(0,en.pi)((0,en.pi)({},e),{cache:t,getCacheKey:function(e){return t.identify(e)}})},e.prototype.addExportedVariables=function(e,t,n){return void 0===t&&(t={}),void 0===n&&(n={}),(0,en.mG)(this,void 0,void 0,function(){return(0,en.Jh)(this,function(r){return e?[2,this.resolveDocument(e,this.buildRootValueFromCache(e,t)||{},this.prepareContext(n),t).then(function(e){return(0,en.pi)((0,en.pi)({},t),e.exportedVariables)})]:[2,(0,en.pi)({},t)]})})},e.prototype.shouldForceResolvers=function(e){var t=!1;return tl(e,{Directive:{enter:function(e){if("client"===e.name.value&&e.arguments&&(t=e.arguments.some(function(e){return"always"===e.name.value&&"BooleanValue"===e.value.kind&&!0===e.value.value})))return tc}}}),t},e.prototype.buildRootValueFromCache=function(e,t){return this.cache.diff({query:nH(e),variables:t,returnPartialData:!0,optimistic:!1}).result},e.prototype.resolveDocument=function(e,t,n,r,i,a){return void 0===n&&(n={}),void 0===r&&(r={}),void 0===i&&(i=function(){return!0}),void 0===a&&(a=!1),(0,en.mG)(this,void 0,void 0,function(){var o,s,u,c,l,f,d,h,p,b,m;return(0,en.Jh)(this,function(g){return o=e8(e),s=e4(e),u=eL(s),c=this.collectSelectionsToResolve(o,u),f=(l=o.operation)?l.charAt(0).toUpperCase()+l.slice(1):"Query",d=this,h=d.cache,p=d.client,b={fragmentMap:u,context:(0,en.pi)((0,en.pi)({},n),{cache:h,client:p}),variables:r,fragmentMatcher:i,defaultOperationType:f,exportedVariables:{},selectionsToResolve:c,onlyRunForcedResolvers:a},m=!1,[2,this.resolveSelectionSet(o.selectionSet,m,t,b).then(function(e){return{result:e,exportedVariables:b.exportedVariables}})]})})},e.prototype.resolveSelectionSet=function(e,t,n,r){return(0,en.mG)(this,void 0,void 0,function(){var i,a,o,s,u,c=this;return(0,en.Jh)(this,function(l){return i=r.fragmentMap,a=r.context,o=r.variables,s=[n],u=function(e){return(0,en.mG)(c,void 0,void 0,function(){var u,c;return(0,en.Jh)(this,function(l){return(t||r.selectionsToResolve.has(e))&&td(e,o)?eQ(e)?[2,this.resolveField(e,t,n,r).then(function(t){var n;void 0!==t&&s.push(((n={})[eX(e)]=t,n))})]:(e1(e)?u=e:(u=i[e.name.value],__DEV__?(0,Q.kG)(u,"No fragment named ".concat(e.name.value)):(0,Q.kG)(u,11)),u&&u.typeCondition&&(c=u.typeCondition.name.value,r.fragmentMatcher(n,c,a)))?[2,this.resolveSelectionSet(u.selectionSet,t,n,r).then(function(e){s.push(e)})]:[2]:[2]})})},[2,Promise.all(e.selections.map(u)).then(function(){return tF(s)})]})})},e.prototype.resolveField=function(e,t,n,r){return(0,en.mG)(this,void 0,void 0,function(){var i,a,o,s,u,c,l,f,d,h=this;return(0,en.Jh)(this,function(p){return n?(i=r.variables,a=e.name.value,o=eX(e),s=a!==o,c=Promise.resolve(u=n[o]||n[a]),(!r.onlyRunForcedResolvers||this.shouldForceResolvers(e))&&(l=n.__typename||r.defaultOperationType,(f=this.resolvers&&this.resolvers[l])&&(d=f[s?a:o])&&(c=Promise.resolve(rX.withValue(this.cache,d,[n,eZ(e,i),r.context,{field:e,fragmentMap:r.fragmentMap},])))),[2,c.then(function(n){if(void 0===n&&(n=u),e.directives&&e.directives.forEach(function(e){"export"===e.name.value&&e.arguments&&e.arguments.forEach(function(e){"as"===e.name.value&&"StringValue"===e.value.kind&&(r.exportedVariables[e.value.value]=n)})}),!e.selectionSet||null==n)return n;var i,a,o=null!==(a=null===(i=e.directives)||void 0===i?void 0:i.some(function(e){return"client"===e.name.value}))&&void 0!==a&&a;return Array.isArray(n)?h.resolveSubSelectedArray(e,t||o,n,r):e.selectionSet?h.resolveSelectionSet(e.selectionSet,t||o,n,r):void 0})]):[2,null]})})},e.prototype.resolveSubSelectedArray=function(e,t,n,r){var i=this;return Promise.all(n.map(function(n){return null===n?null:Array.isArray(n)?i.resolveSubSelectedArray(e,t,n,r):e.selectionSet?i.resolveSelectionSet(e.selectionSet,t,n,r):void 0}))},e.prototype.collectSelectionsToResolve=function(e,t){var n=function(e){return!Array.isArray(e)},r=this.selectionsToResolveCache;function i(e){if(!r.has(e)){var a=new Set;r.set(e,a),tl(e,{Directive:function(e,t,r,i,o){"client"===e.name.value&&o.forEach(function(e){n(e)&&n9(e)&&a.add(e)})},FragmentSpread:function(e,r,o,s,u){var c=t[e.name.value];__DEV__?(0,Q.kG)(c,"No fragment named ".concat(e.name.value)):(0,Q.kG)(c,12);var l=i(c);l.size>0&&(u.forEach(function(e){n(e)&&n9(e)&&a.add(e)}),a.add(e),l.forEach(function(e){a.add(e)}))}})}return r.get(e)}return i(e)},e}(),r6=new(t_.mr?WeakMap:Map);function r5(e,t){var n=e[t];"function"==typeof n&&(e[t]=function(){return r6.set(e,(r6.get(e)+1)%1e15),n.apply(this,arguments)})}function r8(e){e.notifyTimeout&&(clearTimeout(e.notifyTimeout),e.notifyTimeout=void 0)}var r9=function(){function e(e,t){void 0===t&&(t=e.generateQueryId()),this.queryId=t,this.listeners=new Set,this.document=null,this.lastRequestId=1,this.subscriptions=new Set,this.stopped=!1,this.dirty=!1,this.observableQuery=null;var n=this.cache=e.cache;r6.has(n)||(r6.set(n,0),r5(n,"evict"),r5(n,"modify"),r5(n,"reset"))}return e.prototype.init=function(e){var t=e.networkStatus||nZ.I.loading;return this.variables&&this.networkStatus!==nZ.I.loading&&!(0,nm.D)(this.variables,e.variables)&&(t=nZ.I.setVariables),(0,nm.D)(e.variables,this.variables)||(this.lastDiff=void 0),Object.assign(this,{document:e.document,variables:e.variables,networkError:null,graphQLErrors:this.graphQLErrors||[],networkStatus:t}),e.observableQuery&&this.setObservableQuery(e.observableQuery),e.lastRequestId&&(this.lastRequestId=e.lastRequestId),this},e.prototype.reset=function(){r8(this),this.dirty=!1},e.prototype.getDiff=function(e){void 0===e&&(e=this.variables);var t=this.getDiffOptions(e);if(this.lastDiff&&(0,nm.D)(t,this.lastDiff.options))return this.lastDiff.diff;this.updateWatch(this.variables=e);var n=this.observableQuery;if(n&&"no-cache"===n.options.fetchPolicy)return{complete:!1};var r=this.cache.diff(t);return this.updateLastDiff(r,t),r},e.prototype.updateLastDiff=function(e,t){this.lastDiff=e?{diff:e,options:t||this.getDiffOptions()}:void 0},e.prototype.getDiffOptions=function(e){var t;return void 0===e&&(e=this.variables),{query:this.document,variables:e,returnPartialData:!0,optimistic:!0,canonizeResults:null===(t=this.observableQuery)||void 0===t?void 0:t.options.canonizeResults}},e.prototype.setDiff=function(e){var t=this,n=this.lastDiff&&this.lastDiff.diff;this.updateLastDiff(e),this.dirty||(0,nm.D)(n&&n.result,e&&e.result)||(this.dirty=!0,this.notifyTimeout||(this.notifyTimeout=setTimeout(function(){return t.notify()},0)))},e.prototype.setObservableQuery=function(e){var t=this;e!==this.observableQuery&&(this.oqListener&&this.listeners.delete(this.oqListener),this.observableQuery=e,e?(e.queryInfo=this,this.listeners.add(this.oqListener=function(){t.getDiff().fromOptimisticTransaction?e.observe():n4(e)})):delete this.oqListener)},e.prototype.notify=function(){var e=this;r8(this),this.shouldNotify()&&this.listeners.forEach(function(t){return t(e)}),this.dirty=!1},e.prototype.shouldNotify=function(){if(!this.dirty||!this.listeners.size)return!1;if((0,nZ.O)(this.networkStatus)&&this.observableQuery){var e=this.observableQuery.options.fetchPolicy;if("cache-only"!==e&&"cache-and-network"!==e)return!1}return!0},e.prototype.stop=function(){if(!this.stopped){this.stopped=!0,this.reset(),this.cancel(),this.cancel=e.prototype.cancel,this.subscriptions.forEach(function(e){return e.unsubscribe()});var t=this.observableQuery;t&&t.stopPolling()}},e.prototype.cancel=function(){},e.prototype.updateWatch=function(e){var t=this;void 0===e&&(e=this.variables);var n=this.observableQuery;if(!n||"no-cache"!==n.options.fetchPolicy){var r=(0,en.pi)((0,en.pi)({},this.getDiffOptions(e)),{watcher:this,callback:function(e){return t.setDiff(e)}});this.lastWatch&&(0,nm.D)(r,this.lastWatch)||(this.cancel(),this.cancel=this.cache.watch(this.lastWatch=r))}},e.prototype.resetLastWrite=function(){this.lastWrite=void 0},e.prototype.shouldWrite=function(e,t){var n=this.lastWrite;return!(n&&n.dmCount===r6.get(this.cache)&&(0,nm.D)(t,n.variables)&&(0,nm.D)(e.data,n.result.data))},e.prototype.markResult=function(e,t,n,r){var i=this,a=new tB,o=(0,tP.O)(e.errors)?e.errors.slice(0):[];if(this.reset(),"incremental"in e&&(0,tP.O)(e.incremental)){var s=tG(this.getDiff().result,e);e.data=s}else if("hasNext"in e&&e.hasNext){var u=this.getDiff();e.data=a.merge(u.result,e.data)}this.graphQLErrors=o,"no-cache"===n.fetchPolicy?this.updateLastDiff({result:e.data,complete:!0},this.getDiffOptions(n.variables)):0!==r&&(r7(e,n.errorPolicy)?this.cache.performTransaction(function(a){if(i.shouldWrite(e,n.variables))a.writeQuery({query:t,data:e.data,variables:n.variables,overwrite:1===r}),i.lastWrite={result:e,variables:n.variables,dmCount:r6.get(i.cache)};else if(i.lastDiff&&i.lastDiff.diff.complete){e.data=i.lastDiff.diff.result;return}var o=i.getDiffOptions(n.variables),s=a.diff(o);i.stopped||i.updateWatch(n.variables),i.updateLastDiff(s,o),s.complete&&(e.data=s.result)}):this.lastWrite=void 0)},e.prototype.markReady=function(){return this.networkError=null,this.networkStatus=nZ.I.ready},e.prototype.markError=function(e){return this.networkStatus=nZ.I.error,this.lastWrite=void 0,this.reset(),e.graphQLErrors&&(this.graphQLErrors=e.graphQLErrors),e.networkError&&(this.networkError=e.networkError),e},e}();function r7(e,t){void 0===t&&(t="none");var n="ignore"===t||"all"===t,r=!nO(e);return!r&&n&&e.data&&(r=!0),r}var ie=Object.prototype.hasOwnProperty,it=function(){function e(e){var t=e.cache,n=e.link,r=e.defaultOptions,i=e.queryDeduplication,a=void 0!==i&&i,o=e.onBroadcast,s=e.ssrMode,u=void 0!==s&&s,c=e.clientAwareness,l=void 0===c?{}:c,f=e.localState,d=e.assumeImmutableResults;this.clientAwareness={},this.queries=new Map,this.fetchCancelFns=new Map,this.transformCache=new(t_.mr?WeakMap:Map),this.queryIdCounter=1,this.requestIdCounter=1,this.mutationIdCounter=1,this.inFlightLinkObservables=new Map,this.cache=t,this.link=n,this.defaultOptions=r||Object.create(null),this.queryDeduplication=a,this.clientAwareness=l,this.localState=f||new r4({cache:t}),this.ssrMode=u,this.assumeImmutableResults=!!d,(this.onBroadcast=o)&&(this.mutationStore=Object.create(null))}return e.prototype.stop=function(){var e=this;this.queries.forEach(function(t,n){e.stopQueryNoBroadcast(n)}),this.cancelPendingFetches(__DEV__?new Q.ej("QueryManager stopped while query was in flight"):new Q.ej(14))},e.prototype.cancelPendingFetches=function(e){this.fetchCancelFns.forEach(function(t){return t(e)}),this.fetchCancelFns.clear()},e.prototype.mutate=function(e){var t,n,r=e.mutation,i=e.variables,a=e.optimisticResponse,o=e.updateQueries,s=e.refetchQueries,u=void 0===s?[]:s,c=e.awaitRefetchQueries,l=void 0!==c&&c,f=e.update,d=e.onQueryUpdated,h=e.fetchPolicy,p=void 0===h?(null===(t=this.defaultOptions.mutate)||void 0===t?void 0:t.fetchPolicy)||"network-only":h,b=e.errorPolicy,m=void 0===b?(null===(n=this.defaultOptions.mutate)||void 0===n?void 0:n.errorPolicy)||"none":b,g=e.keepRootFields,v=e.context;return(0,en.mG)(this,void 0,void 0,function(){var e,t,n,s,c,h;return(0,en.Jh)(this,function(b){switch(b.label){case 0:if(__DEV__?(0,Q.kG)(r,"mutation option is required. You must specify your GraphQL document in the mutation option."):(0,Q.kG)(r,15),__DEV__?(0,Q.kG)("network-only"===p||"no-cache"===p,"Mutations support only 'network-only' or 'no-cache' fetchPolicy strings. The default `network-only` behavior automatically writes mutation results to the cache. Passing `no-cache` skips the cache write."):(0,Q.kG)("network-only"===p||"no-cache"===p,16),e=this.generateMutationId(),n=(t=this.transform(r)).document,s=t.hasClientExports,r=this.cache.transformForLink(n),i=this.getVariables(r,i),!s)return[3,2];return[4,this.localState.addExportedVariables(r,i,v)];case 1:i=b.sent(),b.label=2;case 2:return c=this.mutationStore&&(this.mutationStore[e]={mutation:r,variables:i,loading:!0,error:null}),a&&this.markMutationOptimistic(a,{mutationId:e,document:r,variables:i,fetchPolicy:p,errorPolicy:m,context:v,updateQueries:o,update:f,keepRootFields:g}),this.broadcastQueries(),h=this,[2,new Promise(function(t,n){return nM(h.getObservableFromLink(r,(0,en.pi)((0,en.pi)({},v),{optimisticResponse:a}),i,!1),function(t){if(nO(t)&&"none"===m)throw new tN.cA({graphQLErrors:nA(t)});c&&(c.loading=!1,c.error=null);var n=(0,en.pi)({},t);return"function"==typeof u&&(u=u(n)),"ignore"===m&&nO(n)&&delete n.errors,h.markMutationResult({mutationId:e,result:n,document:r,variables:i,fetchPolicy:p,errorPolicy:m,context:v,update:f,updateQueries:o,awaitRefetchQueries:l,refetchQueries:u,removeOptimistic:a?e:void 0,onQueryUpdated:d,keepRootFields:g})}).subscribe({next:function(e){h.broadcastQueries(),"hasNext"in e&&!1!==e.hasNext||t(e)},error:function(t){c&&(c.loading=!1,c.error=t),a&&h.cache.removeOptimistic(e),h.broadcastQueries(),n(t instanceof tN.cA?t:new tN.cA({networkError:t}))}})})]}})})},e.prototype.markMutationResult=function(e,t){var n=this;void 0===t&&(t=this.cache);var r=e.result,i=[],a="no-cache"===e.fetchPolicy;if(!a&&r7(r,e.errorPolicy)){if(tU(r)||i.push({result:r.data,dataId:"ROOT_MUTATION",query:e.document,variables:e.variables}),tU(r)&&(0,tP.O)(r.incremental)){var o=t.diff({id:"ROOT_MUTATION",query:this.transform(e.document).asQuery,variables:e.variables,optimistic:!1,returnPartialData:!0}),s=void 0;o.result&&(s=tG(o.result,r)),void 0!==s&&(r.data=s,i.push({result:s,dataId:"ROOT_MUTATION",query:e.document,variables:e.variables}))}var u=e.updateQueries;u&&this.queries.forEach(function(e,a){var o=e.observableQuery,s=o&&o.queryName;if(s&&ie.call(u,s)){var c,l=u[s],f=n.queries.get(a),d=f.document,h=f.variables,p=t.diff({query:d,variables:h,returnPartialData:!0,optimistic:!1}),b=p.result;if(p.complete&&b){var m=l(b,{mutationResult:r,queryName:d&&e3(d)||void 0,queryVariables:h});m&&i.push({result:m,dataId:"ROOT_QUERY",query:d,variables:h})}}})}if(i.length>0||e.refetchQueries||e.update||e.onQueryUpdated||e.removeOptimistic){var c=[];if(this.refetchQueries({updateCache:function(t){a||i.forEach(function(e){return t.write(e)});var o=e.update,s=!t$(r)||tU(r)&&!r.hasNext;if(o){if(!a){var u=t.diff({id:"ROOT_MUTATION",query:n.transform(e.document).asQuery,variables:e.variables,optimistic:!1,returnPartialData:!0});u.complete&&("incremental"in(r=(0,en.pi)((0,en.pi)({},r),{data:u.result}))&&delete r.incremental,"hasNext"in r&&delete r.hasNext)}s&&o(t,r,{context:e.context,variables:e.variables})}a||e.keepRootFields||!s||t.modify({id:"ROOT_MUTATION",fields:function(e,t){var n=t.fieldName,r=t.DELETE;return"__typename"===n?e:r}})},include:e.refetchQueries,optimistic:!1,removeOptimistic:e.removeOptimistic,onQueryUpdated:e.onQueryUpdated||null}).forEach(function(e){return c.push(e)}),e.awaitRefetchQueries||e.onQueryUpdated)return Promise.all(c).then(function(){return r})}return Promise.resolve(r)},e.prototype.markMutationOptimistic=function(e,t){var n=this,r="function"==typeof e?e(t.variables):e;return this.cache.recordOptimisticTransaction(function(e){try{n.markMutationResult((0,en.pi)((0,en.pi)({},t),{result:{data:r}}),e)}catch(i){__DEV__&&Q.kG.error(i)}},t.mutationId)},e.prototype.fetchQuery=function(e,t,n){return this.fetchQueryObservable(e,t,n).promise},e.prototype.getQueryStore=function(){var e=Object.create(null);return this.queries.forEach(function(t,n){e[n]={variables:t.variables,networkStatus:t.networkStatus,networkError:t.networkError,graphQLErrors:t.graphQLErrors}}),e},e.prototype.resetErrors=function(e){var t=this.queries.get(e);t&&(t.networkError=void 0,t.graphQLErrors=[])},e.prototype.transform=function(e){var t=this.transformCache;if(!t.has(e)){var n=this.cache.transformDocument(e),r=nY(n),i=this.localState.clientQuery(n),a=r&&this.localState.serverQuery(r),o={document:n,hasClientExports:tm(n),hasForcedResolvers:this.localState.shouldForceResolvers(n),clientQuery:i,serverQuery:a,defaultVars:e9(e2(n)),asQuery:(0,en.pi)((0,en.pi)({},n),{definitions:n.definitions.map(function(e){return"OperationDefinition"===e.kind&&"query"!==e.operation?(0,en.pi)((0,en.pi)({},e),{operation:"query"}):e})})},s=function(e){e&&!t.has(e)&&t.set(e,o)};s(e),s(n),s(i),s(a)}return t.get(e)},e.prototype.getVariables=function(e,t){return(0,en.pi)((0,en.pi)({},this.transform(e).defaultVars),t)},e.prototype.watchQuery=function(e){void 0===(e=(0,en.pi)((0,en.pi)({},e),{variables:this.getVariables(e.query,e.variables)})).notifyOnNetworkStatusChange&&(e.notifyOnNetworkStatusChange=!1);var t=new r9(this),n=new n3({queryManager:this,queryInfo:t,options:e});return this.queries.set(n.queryId,t),t.init({document:n.query,observableQuery:n,variables:n.variables}),n},e.prototype.query=function(e,t){var n=this;return void 0===t&&(t=this.generateQueryId()),__DEV__?(0,Q.kG)(e.query,"query option is required. You must specify your GraphQL document in the query option."):(0,Q.kG)(e.query,17),__DEV__?(0,Q.kG)("Document"===e.query.kind,'You must wrap the query string in a "gql" tag.'):(0,Q.kG)("Document"===e.query.kind,18),__DEV__?(0,Q.kG)(!e.returnPartialData,"returnPartialData option only supported on watchQuery."):(0,Q.kG)(!e.returnPartialData,19),__DEV__?(0,Q.kG)(!e.pollInterval,"pollInterval option only supported on watchQuery."):(0,Q.kG)(!e.pollInterval,20),this.fetchQuery(t,e).finally(function(){return n.stopQuery(t)})},e.prototype.generateQueryId=function(){return String(this.queryIdCounter++)},e.prototype.generateRequestId=function(){return this.requestIdCounter++},e.prototype.generateMutationId=function(){return String(this.mutationIdCounter++)},e.prototype.stopQueryInStore=function(e){this.stopQueryInStoreNoBroadcast(e),this.broadcastQueries()},e.prototype.stopQueryInStoreNoBroadcast=function(e){var t=this.queries.get(e);t&&t.stop()},e.prototype.clearStore=function(e){return void 0===e&&(e={discardWatches:!0}),this.cancelPendingFetches(__DEV__?new Q.ej("Store reset while query was in flight (not completed in link chain)"):new Q.ej(21)),this.queries.forEach(function(e){e.observableQuery?e.networkStatus=nZ.I.loading:e.stop()}),this.mutationStore&&(this.mutationStore=Object.create(null)),this.cache.reset(e)},e.prototype.getObservableQueries=function(e){var t=this;void 0===e&&(e="active");var n=new Map,r=new Map,i=new Set;return Array.isArray(e)&&e.forEach(function(e){"string"==typeof e?r.set(e,!1):eN(e)?r.set(t.transform(e).document,!1):(0,eO.s)(e)&&e.query&&i.add(e)}),this.queries.forEach(function(t,i){var a=t.observableQuery,o=t.document;if(a){if("all"===e){n.set(i,a);return}var s=a.queryName;if("standby"===a.options.fetchPolicy||"active"===e&&!a.hasObservers())return;("active"===e||s&&r.has(s)||o&&r.has(o))&&(n.set(i,a),s&&r.set(s,!0),o&&r.set(o,!0))}}),i.size&&i.forEach(function(e){var r=nG("legacyOneTimeQuery"),i=t.getQuery(r).init({document:e.query,variables:e.variables}),a=new n3({queryManager:t,queryInfo:i,options:(0,en.pi)((0,en.pi)({},e),{fetchPolicy:"network-only"})});(0,Q.kG)(a.queryId===r),i.setObservableQuery(a),n.set(r,a)}),__DEV__&&r.size&&r.forEach(function(e,t){!e&&__DEV__&&Q.kG.warn("Unknown query ".concat("string"==typeof t?"named ":"").concat(JSON.stringify(t,null,2)," requested in refetchQueries options.include array"))}),n},e.prototype.reFetchObservableQueries=function(e){var t=this;void 0===e&&(e=!1);var n=[];return this.getObservableQueries(e?"all":"active").forEach(function(r,i){var a=r.options.fetchPolicy;r.resetLastResults(),(e||"standby"!==a&&"cache-only"!==a)&&n.push(r.refetch()),t.getQuery(i).setDiff(null)}),this.broadcastQueries(),Promise.all(n)},e.prototype.setObservableQuery=function(e){this.getQuery(e.queryId).setObservableQuery(e)},e.prototype.startGraphQLSubscription=function(e){var t=this,n=e.query,r=e.fetchPolicy,i=e.errorPolicy,a=e.variables,o=e.context,s=void 0===o?{}:o;n=this.transform(n).document,a=this.getVariables(n,a);var u=function(e){return t.getObservableFromLink(n,s,e).map(function(a){"no-cache"!==r&&(r7(a,i)&&t.cache.write({query:n,result:a.data,dataId:"ROOT_SUBSCRIPTION",variables:e}),t.broadcastQueries());var o=nO(a),s=(0,tN.ls)(a);if(o||s){var u={};throw o&&(u.graphQLErrors=a.errors),s&&(u.protocolErrors=a.extensions[tN.YG]),new tN.cA(u)}return a})};if(this.transform(n).hasClientExports){var c=this.localState.addExportedVariables(n,a,s).then(u);return new eT(function(e){var t=null;return c.then(function(n){return t=n.subscribe(e)},e.error),function(){return t&&t.unsubscribe()}})}return u(a)},e.prototype.stopQuery=function(e){this.stopQueryNoBroadcast(e),this.broadcastQueries()},e.prototype.stopQueryNoBroadcast=function(e){this.stopQueryInStoreNoBroadcast(e),this.removeQuery(e)},e.prototype.removeQuery=function(e){this.fetchCancelFns.delete(e),this.queries.has(e)&&(this.getQuery(e).stop(),this.queries.delete(e))},e.prototype.broadcastQueries=function(){this.onBroadcast&&this.onBroadcast(),this.queries.forEach(function(e){return e.notify()})},e.prototype.getLocalState=function(){return this.localState},e.prototype.getObservableFromLink=function(e,t,n,r){var i,a,o=this;void 0===r&&(r=null!==(i=null==t?void 0:t.queryDeduplication)&&void 0!==i?i:this.queryDeduplication);var s=this.transform(e).serverQuery;if(s){var u=this,c=u.inFlightLinkObservables,l=u.link,f={query:s,variables:n,operationName:e3(s)||void 0,context:this.prepareContext((0,en.pi)((0,en.pi)({},t),{forceFetch:!r}))};if(t=f.context,r){var d=c.get(s)||new Map;c.set(s,d);var h=nx(n);if(!(a=d.get(h))){var p=new nq([np(l,f)]);d.set(h,a=p),p.beforeNext(function(){d.delete(h)&&d.size<1&&c.delete(s)})}}else a=new nq([np(l,f)])}else a=new nq([eT.of({data:{}})]),t=this.prepareContext(t);var b=this.transform(e).clientQuery;return b&&(a=nM(a,function(e){return o.localState.runResolvers({document:b,remoteResult:e,context:t,variables:n})})),a},e.prototype.getResultsFromLink=function(e,t,n){var r=e.lastRequestId=this.generateRequestId(),i=this.cache.transformForLink(this.transform(e.document).document);return nM(this.getObservableFromLink(i,n.context,n.variables),function(a){var o=nA(a),s=o.length>0;if(r>=e.lastRequestId){if(s&&"none"===n.errorPolicy)throw e.markError(new tN.cA({graphQLErrors:o}));e.markResult(a,i,n,t),e.markReady()}var u={data:a.data,loading:!1,networkStatus:nZ.I.ready};return s&&"ignore"!==n.errorPolicy&&(u.errors=o,u.networkStatus=nZ.I.error),u},function(t){var n=(0,tN.MS)(t)?t:new tN.cA({networkError:t});throw r>=e.lastRequestId&&e.markError(n),n})},e.prototype.fetchQueryObservable=function(e,t,n){return this.fetchConcastWithInfo(e,t,n).concast},e.prototype.fetchConcastWithInfo=function(e,t,n){var r,i,a=this;void 0===n&&(n=nZ.I.loading);var o=this.transform(t.query).document,s=this.getVariables(o,t.variables),u=this.getQuery(e),c=this.defaultOptions.watchQuery,l=t.fetchPolicy,f=void 0===l?c&&c.fetchPolicy||"cache-first":l,d=t.errorPolicy,h=void 0===d?c&&c.errorPolicy||"none":d,p=t.returnPartialData,b=void 0!==p&&p,m=t.notifyOnNetworkStatusChange,g=void 0!==m&&m,v=t.context,y=void 0===v?{}:v,w=Object.assign({},t,{query:o,variables:s,fetchPolicy:f,errorPolicy:h,returnPartialData:b,notifyOnNetworkStatusChange:g,context:y}),_=function(e){w.variables=e;var r=a.fetchQueryByPolicy(u,w,n);return"standby"!==w.fetchPolicy&&r.sources.length>0&&u.observableQuery&&u.observableQuery.applyNextFetchPolicy("after-fetch",t),r},E=function(){return a.fetchCancelFns.delete(e)};if(this.fetchCancelFns.set(e,function(e){E(),setTimeout(function(){return r.cancel(e)})}),this.transform(w.query).hasClientExports)r=new nq(this.localState.addExportedVariables(w.query,w.variables,w.context).then(_).then(function(e){return e.sources})),i=!0;else{var S=_(w.variables);i=S.fromLink,r=new nq(S.sources)}return r.promise.then(E,E),{concast:r,fromLink:i}},e.prototype.refetchQueries=function(e){var t=this,n=e.updateCache,r=e.include,i=e.optimistic,a=void 0!==i&&i,o=e.removeOptimistic,s=void 0===o?a?nG("refetchQueries"):void 0:o,u=e.onQueryUpdated,c=new Map;r&&this.getObservableQueries(r).forEach(function(e,n){c.set(n,{oq:e,lastDiff:t.getQuery(n).getDiff()})});var l=new Map;return n&&this.cache.batch({update:n,optimistic:a&&s||!1,removeOptimistic:s,onWatchUpdated:function(e,t,n){var r=e.watcher instanceof r9&&e.watcher.observableQuery;if(r){if(u){c.delete(r.queryId);var i=u(r,t,n);return!0===i&&(i=r.refetch()),!1!==i&&l.set(r,i),i}null!==u&&c.set(r.queryId,{oq:r,lastDiff:n,diff:t})}}}),c.size&&c.forEach(function(e,n){var r,i=e.oq,a=e.lastDiff,o=e.diff;if(u){if(!o){var s=i.queryInfo;s.reset(),o=s.getDiff()}r=u(i,o,a)}u&&!0!==r||(r=i.refetch()),!1!==r&&l.set(i,r),n.indexOf("legacyOneTimeQuery")>=0&&t.stopQueryNoBroadcast(n)}),s&&this.cache.removeOptimistic(s),l},e.prototype.fetchQueryByPolicy=function(e,t,n){var r=this,i=t.query,a=t.variables,o=t.fetchPolicy,s=t.refetchWritePolicy,u=t.errorPolicy,c=t.returnPartialData,l=t.context,f=t.notifyOnNetworkStatusChange,d=e.networkStatus;e.init({document:this.transform(i).document,variables:a,networkStatus:n});var h=function(){return e.getDiff(a)},p=function(t,n){void 0===n&&(n=e.networkStatus||nZ.I.loading);var o=t.result;!__DEV__||c||(0,nm.D)(o,{})||n5(t.missing);var s=function(e){return eT.of((0,en.pi)({data:e,loading:(0,nZ.O)(n),networkStatus:n},t.complete?null:{partial:!0}))};return o&&r.transform(i).hasForcedResolvers?r.localState.runResolvers({document:i,remoteResult:{data:o},context:l,variables:a,onlyRunForcedResolvers:!0}).then(function(e){return s(e.data||void 0)}):"none"===u&&n===nZ.I.refetch&&Array.isArray(t.missing)?s(void 0):s(o)},b="no-cache"===o?0:n===nZ.I.refetch&&"merge"!==s?1:2,m=function(){return r.getResultsFromLink(e,b,{variables:a,context:l,fetchPolicy:o,errorPolicy:u})},g=f&&"number"==typeof d&&d!==n&&(0,nZ.O)(n);switch(o){default:case"cache-first":var v=h();if(v.complete)return{fromLink:!1,sources:[p(v,e.markReady())]};if(c||g)return{fromLink:!0,sources:[p(v),m()]};return{fromLink:!0,sources:[m()]};case"cache-and-network":var v=h();if(v.complete||c||g)return{fromLink:!0,sources:[p(v),m()]};return{fromLink:!0,sources:[m()]};case"cache-only":return{fromLink:!1,sources:[p(h(),e.markReady())]};case"network-only":if(g)return{fromLink:!0,sources:[p(h()),m()]};return{fromLink:!0,sources:[m()]};case"no-cache":if(g)return{fromLink:!0,sources:[p(e.getDiff()),m(),]};return{fromLink:!0,sources:[m()]};case"standby":return{fromLink:!1,sources:[]}}},e.prototype.getQuery=function(e){return e&&!this.queries.has(e)&&this.queries.set(e,new r9(this,e)),this.queries.get(e)},e.prototype.prepareContext=function(e){void 0===e&&(e={});var t=this.localState.prepareContext(e);return(0,en.pi)((0,en.pi)({},t),{clientAwareness:this.clientAwareness})},e}(),ir=__webpack_require__(14012),ii=!1,ia=function(){function e(e){var t=this;this.resetStoreCallbacks=[],this.clearStoreCallbacks=[];var n=e.uri,r=e.credentials,i=e.headers,a=e.cache,o=e.ssrMode,s=void 0!==o&&o,u=e.ssrForceFetchDelay,c=void 0===u?0:u,l=e.connectToDevTools,f=void 0===l?"object"==typeof window&&!window.__APOLLO_CLIENT__&&__DEV__:l,d=e.queryDeduplication,h=void 0===d||d,p=e.defaultOptions,b=e.assumeImmutableResults,m=void 0!==b&&b,g=e.resolvers,v=e.typeDefs,y=e.fragmentMatcher,w=e.name,_=e.version,E=e.link;if(E||(E=n?new nh({uri:n,credentials:r,headers:i}):ta.empty()),!a)throw __DEV__?new Q.ej("To initialize Apollo Client, you must specify a 'cache' property in the options object. \nFor more information, please visit: https://go.apollo.dev/c/docs"):new Q.ej(9);if(this.link=E,this.cache=a,this.disableNetworkFetches=s||c>0,this.queryDeduplication=h,this.defaultOptions=p||Object.create(null),this.typeDefs=v,c&&setTimeout(function(){return t.disableNetworkFetches=!1},c),this.watchQuery=this.watchQuery.bind(this),this.query=this.query.bind(this),this.mutate=this.mutate.bind(this),this.resetStore=this.resetStore.bind(this),this.reFetchObservableQueries=this.reFetchObservableQueries.bind(this),f&&"object"==typeof window&&(window.__APOLLO_CLIENT__=this),!ii&&f&&__DEV__&&(ii=!0,"undefined"!=typeof window&&window.document&&window.top===window.self&&!window.__APOLLO_DEVTOOLS_GLOBAL_HOOK__)){var S=window.navigator,k=S&&S.userAgent,x=void 0;"string"==typeof k&&(k.indexOf("Chrome/")>-1?x="https://chrome.google.com/webstore/detail/apollo-client-developer-t/jdkknkkbebbapilgoeccciglkfbmbnfm":k.indexOf("Firefox/")>-1&&(x="https://addons.mozilla.org/en-US/firefox/addon/apollo-developer-tools/")),x&&__DEV__&&Q.kG.log("Download the Apollo DevTools for a better development experience: "+x)}this.version=nb,this.localState=new r4({cache:a,client:this,resolvers:g,fragmentMatcher:y}),this.queryManager=new it({cache:this.cache,link:this.link,defaultOptions:this.defaultOptions,queryDeduplication:h,ssrMode:s,clientAwareness:{name:w,version:_},localState:this.localState,assumeImmutableResults:m,onBroadcast:f?function(){t.devToolsHookCb&&t.devToolsHookCb({action:{},state:{queries:t.queryManager.getQueryStore(),mutations:t.queryManager.mutationStore||{}},dataWithOptimisticResults:t.cache.extract(!0)})}:void 0})}return e.prototype.stop=function(){this.queryManager.stop()},e.prototype.watchQuery=function(e){return this.defaultOptions.watchQuery&&(e=(0,ir.J)(this.defaultOptions.watchQuery,e)),this.disableNetworkFetches&&("network-only"===e.fetchPolicy||"cache-and-network"===e.fetchPolicy)&&(e=(0,en.pi)((0,en.pi)({},e),{fetchPolicy:"cache-first"})),this.queryManager.watchQuery(e)},e.prototype.query=function(e){return this.defaultOptions.query&&(e=(0,ir.J)(this.defaultOptions.query,e)),__DEV__?(0,Q.kG)("cache-and-network"!==e.fetchPolicy,"The cache-and-network fetchPolicy does not work with client.query, because client.query can only return a single result. Please use client.watchQuery to receive multiple results from the cache and the network, or consider using a different fetchPolicy, such as cache-first or network-only."):(0,Q.kG)("cache-and-network"!==e.fetchPolicy,10),this.disableNetworkFetches&&"network-only"===e.fetchPolicy&&(e=(0,en.pi)((0,en.pi)({},e),{fetchPolicy:"cache-first"})),this.queryManager.query(e)},e.prototype.mutate=function(e){return this.defaultOptions.mutate&&(e=(0,ir.J)(this.defaultOptions.mutate,e)),this.queryManager.mutate(e)},e.prototype.subscribe=function(e){return this.queryManager.startGraphQLSubscription(e)},e.prototype.readQuery=function(e,t){return void 0===t&&(t=!1),this.cache.readQuery(e,t)},e.prototype.readFragment=function(e,t){return void 0===t&&(t=!1),this.cache.readFragment(e,t)},e.prototype.writeQuery=function(e){var t=this.cache.writeQuery(e);return!1!==e.broadcast&&this.queryManager.broadcastQueries(),t},e.prototype.writeFragment=function(e){var t=this.cache.writeFragment(e);return!1!==e.broadcast&&this.queryManager.broadcastQueries(),t},e.prototype.__actionHookForDevTools=function(e){this.devToolsHookCb=e},e.prototype.__requestRaw=function(e){return np(this.link,e)},e.prototype.resetStore=function(){var e=this;return Promise.resolve().then(function(){return e.queryManager.clearStore({discardWatches:!1})}).then(function(){return Promise.all(e.resetStoreCallbacks.map(function(e){return e()}))}).then(function(){return e.reFetchObservableQueries()})},e.prototype.clearStore=function(){var e=this;return Promise.resolve().then(function(){return e.queryManager.clearStore({discardWatches:!0})}).then(function(){return Promise.all(e.clearStoreCallbacks.map(function(e){return e()}))})},e.prototype.onResetStore=function(e){var t=this;return this.resetStoreCallbacks.push(e),function(){t.resetStoreCallbacks=t.resetStoreCallbacks.filter(function(t){return t!==e})}},e.prototype.onClearStore=function(e){var t=this;return this.clearStoreCallbacks.push(e),function(){t.clearStoreCallbacks=t.clearStoreCallbacks.filter(function(t){return t!==e})}},e.prototype.reFetchObservableQueries=function(e){return this.queryManager.reFetchObservableQueries(e)},e.prototype.refetchQueries=function(e){var t=this.queryManager.refetchQueries(e),n=[],r=[];t.forEach(function(e,t){n.push(t),r.push(e)});var i=Promise.all(r);return i.queries=n,i.results=r,i.catch(function(e){__DEV__&&Q.kG.debug("In client.refetchQueries, Promise.all promise rejected with error ".concat(e))}),i},e.prototype.getObservableQueries=function(e){return void 0===e&&(e="active"),this.queryManager.getObservableQueries(e)},e.prototype.extract=function(e){return this.cache.extract(e)},e.prototype.restore=function(e){return this.cache.restore(e)},e.prototype.addResolvers=function(e){this.localState.addResolvers(e)},e.prototype.setResolvers=function(e){this.localState.setResolvers(e)},e.prototype.getResolvers=function(){return this.localState.getResolvers()},e.prototype.setLocalStateFragmentMatcher=function(e){this.localState.setFragmentMatcher(e)},e.prototype.setLink=function(e){this.link=this.queryManager.link=e},e}(),io=function(){function e(){this.getFragmentDoc=rZ(eA)}return e.prototype.batch=function(e){var t,n=this,r="string"==typeof e.optimistic?e.optimistic:!1===e.optimistic?null:void 0;return this.performTransaction(function(){return t=e.update(n)},r),t},e.prototype.recordOptimisticTransaction=function(e,t){this.performTransaction(e,t)},e.prototype.transformDocument=function(e){return e},e.prototype.transformForLink=function(e){return e},e.prototype.identify=function(e){},e.prototype.gc=function(){return[]},e.prototype.modify=function(e){return!1},e.prototype.readQuery=function(e,t){return void 0===t&&(t=!!e.optimistic),this.read((0,en.pi)((0,en.pi)({},e),{rootId:e.id||"ROOT_QUERY",optimistic:t}))},e.prototype.readFragment=function(e,t){return void 0===t&&(t=!!e.optimistic),this.read((0,en.pi)((0,en.pi)({},e),{query:this.getFragmentDoc(e.fragment,e.fragmentName),rootId:e.id,optimistic:t}))},e.prototype.writeQuery=function(e){var t=e.id,n=e.data,r=(0,en._T)(e,["id","data"]);return this.write(Object.assign(r,{dataId:t||"ROOT_QUERY",result:n}))},e.prototype.writeFragment=function(e){var t=e.id,n=e.data,r=e.fragment,i=e.fragmentName,a=(0,en._T)(e,["id","data","fragment","fragmentName"]);return this.write(Object.assign(a,{query:this.getFragmentDoc(r,i),dataId:t,result:n}))},e.prototype.updateQuery=function(e,t){return this.batch({update:function(n){var r=n.readQuery(e),i=t(r);return null==i?r:(n.writeQuery((0,en.pi)((0,en.pi)({},e),{data:i})),i)}})},e.prototype.updateFragment=function(e,t){return this.batch({update:function(n){var r=n.readFragment(e),i=t(r);return null==i?r:(n.writeFragment((0,en.pi)((0,en.pi)({},e),{data:i})),i)}})},e}(),is=function(e){function t(n,r,i,a){var o,s=e.call(this,n)||this;if(s.message=n,s.path=r,s.query=i,s.variables=a,Array.isArray(s.path)){s.missing=s.message;for(var u=s.path.length-1;u>=0;--u)s.missing=((o={})[s.path[u]]=s.missing,o)}else s.missing=s.path;return s.__proto__=t.prototype,s}return(0,en.ZT)(t,e),t}(Error),iu=__webpack_require__(10542),ic=Object.prototype.hasOwnProperty;function il(e){return null==e}function id(e,t){var n=e.__typename,r=e.id,i=e._id;if("string"==typeof n&&(t&&(t.keyObject=il(r)?il(i)?void 0:{_id:i}:{id:r}),il(r)&&!il(i)&&(r=i),!il(r)))return"".concat(n,":").concat("number"==typeof r||"string"==typeof r?r:JSON.stringify(r))}var ih={dataIdFromObject:id,addTypename:!0,resultCaching:!0,canonizeResults:!1};function ip(e){return(0,n1.o)(ih,e)}function ib(e){var t=e.canonizeResults;return void 0===t?ih.canonizeResults:t}function im(e,t){return eD(t)?e.get(t.__ref,"__typename"):t&&t.__typename}var ig=/^[_a-z][_0-9a-z]*/i;function iv(e){var t=e.match(ig);return t?t[0]:e}function iy(e,t,n){return!!(0,eO.s)(t)&&((0,tP.k)(t)?t.every(function(t){return iy(e,t,n)}):e.selections.every(function(e){if(eQ(e)&&td(e,n)){var r=eX(e);return ic.call(t,r)&&(!e.selectionSet||iy(e.selectionSet,t[r],n))}return!0}))}function iw(e){return(0,eO.s)(e)&&!eD(e)&&!(0,tP.k)(e)}function i_(){return new tB}function iE(e,t){var n=eL(e4(e));return{fragmentMap:n,lookupFragment:function(e){var r=n[e];return!r&&t&&(r=t.lookup(e)),r||null}}}var iS=Object.create(null),ik=function(){return iS},ix=Object.create(null),iT=function(){function e(e,t){var n=this;this.policies=e,this.group=t,this.data=Object.create(null),this.rootIds=Object.create(null),this.refs=Object.create(null),this.getFieldValue=function(e,t){return(0,iu.J)(eD(e)?n.get(e.__ref,t):e&&e[t])},this.canRead=function(e){return eD(e)?n.has(e.__ref):"object"==typeof e},this.toReference=function(e,t){if("string"==typeof e)return eI(e);if(eD(e))return e;var r=n.policies.identify(e)[0];if(r){var i=eI(r);return t&&n.merge(r,e),i}}}return e.prototype.toObject=function(){return(0,en.pi)({},this.data)},e.prototype.has=function(e){return void 0!==this.lookup(e,!0)},e.prototype.get=function(e,t){if(this.group.depend(e,t),ic.call(this.data,e)){var n=this.data[e];if(n&&ic.call(n,t))return n[t]}return"__typename"===t&&ic.call(this.policies.rootTypenamesById,e)?this.policies.rootTypenamesById[e]:this instanceof iL?this.parent.get(e,t):void 0},e.prototype.lookup=function(e,t){return(t&&this.group.depend(e,"__exists"),ic.call(this.data,e))?this.data[e]:this instanceof iL?this.parent.lookup(e,t):this.policies.rootTypenamesById[e]?Object.create(null):void 0},e.prototype.merge=function(e,t){var n,r=this;eD(e)&&(e=e.__ref),eD(t)&&(t=t.__ref);var i="string"==typeof e?this.lookup(n=e):e,a="string"==typeof t?this.lookup(n=t):t;if(a){__DEV__?(0,Q.kG)("string"==typeof n,"store.merge expects a string ID"):(0,Q.kG)("string"==typeof n,1);var o=new tB(iI).merge(i,a);if(this.data[n]=o,o!==i&&(delete this.refs[n],this.group.caching)){var s=Object.create(null);i||(s.__exists=1),Object.keys(a).forEach(function(e){if(!i||i[e]!==o[e]){s[e]=1;var t=iv(e);t===e||r.policies.hasKeyArgs(o.__typename,t)||(s[t]=1),void 0!==o[e]||r instanceof iL||delete o[e]}}),s.__typename&&!(i&&i.__typename)&&this.policies.rootTypenamesById[n]===o.__typename&&delete s.__typename,Object.keys(s).forEach(function(e){return r.group.dirty(n,e)})}}},e.prototype.modify=function(e,t){var n=this,r=this.lookup(e);if(r){var i=Object.create(null),a=!1,o=!0,s={DELETE:iS,INVALIDATE:ix,isReference:eD,toReference:this.toReference,canRead:this.canRead,readField:function(t,r){return n.policies.readField("string"==typeof t?{fieldName:t,from:r||eI(e)}:t,{store:n})}};if(Object.keys(r).forEach(function(u){var c=iv(u),l=r[u];if(void 0!==l){var f="function"==typeof t?t:t[u]||t[c];if(f){var d=f===ik?iS:f((0,iu.J)(l),(0,en.pi)((0,en.pi)({},s),{fieldName:c,storeFieldName:u,storage:n.getStorage(e,u)}));d===ix?n.group.dirty(e,u):(d===iS&&(d=void 0),d!==l&&(i[u]=d,a=!0,l=d))}void 0!==l&&(o=!1)}}),a)return this.merge(e,i),o&&(this instanceof iL?this.data[e]=void 0:delete this.data[e],this.group.dirty(e,"__exists")),!0}return!1},e.prototype.delete=function(e,t,n){var r,i=this.lookup(e);if(i){var a=this.getFieldValue(i,"__typename"),o=t&&n?this.policies.getStoreFieldName({typename:a,fieldName:t,args:n}):t;return this.modify(e,o?((r={})[o]=ik,r):ik)}return!1},e.prototype.evict=function(e,t){var n=!1;return e.id&&(ic.call(this.data,e.id)&&(n=this.delete(e.id,e.fieldName,e.args)),this instanceof iL&&this!==t&&(n=this.parent.evict(e,t)||n),(e.fieldName||n)&&this.group.dirty(e.id,e.fieldName||"__exists")),n},e.prototype.clear=function(){this.replace(null)},e.prototype.extract=function(){var e=this,t=this.toObject(),n=[];return this.getRootIdSet().forEach(function(t){ic.call(e.policies.rootTypenamesById,t)||n.push(t)}),n.length&&(t.__META={extraRootIds:n.sort()}),t},e.prototype.replace=function(e){var t=this;if(Object.keys(this.data).forEach(function(n){e&&ic.call(e,n)||t.delete(n)}),e){var n=e.__META,r=(0,en._T)(e,["__META"]);Object.keys(r).forEach(function(e){t.merge(e,r[e])}),n&&n.extraRootIds.forEach(this.retain,this)}},e.prototype.retain=function(e){return this.rootIds[e]=(this.rootIds[e]||0)+1},e.prototype.release=function(e){if(this.rootIds[e]>0){var t=--this.rootIds[e];return t||delete this.rootIds[e],t}return 0},e.prototype.getRootIdSet=function(e){return void 0===e&&(e=new Set),Object.keys(this.rootIds).forEach(e.add,e),this instanceof iL?this.parent.getRootIdSet(e):Object.keys(this.policies.rootTypenamesById).forEach(e.add,e),e},e.prototype.gc=function(){var e=this,t=this.getRootIdSet(),n=this.toObject();t.forEach(function(r){ic.call(n,r)&&(Object.keys(e.findChildRefIds(r)).forEach(t.add,t),delete n[r])});var r=Object.keys(n);if(r.length){for(var i=this;i instanceof iL;)i=i.parent;r.forEach(function(e){return i.delete(e)})}return r},e.prototype.findChildRefIds=function(e){if(!ic.call(this.refs,e)){var t=this.refs[e]=Object.create(null),n=this.data[e];if(!n)return t;var r=new Set([n]);r.forEach(function(e){eD(e)&&(t[e.__ref]=!0),(0,eO.s)(e)&&Object.keys(e).forEach(function(t){var n=e[t];(0,eO.s)(n)&&r.add(n)})})}return this.refs[e]},e.prototype.makeCacheKey=function(){return this.group.keyMaker.lookupArray(arguments)},e}(),iM=function(){function e(e,t){void 0===t&&(t=null),this.caching=e,this.parent=t,this.d=null,this.resetCaching()}return e.prototype.resetCaching=function(){this.d=this.caching?rW():null,this.keyMaker=new n_(t_.mr)},e.prototype.depend=function(e,t){if(this.d){this.d(iO(e,t));var n=iv(t);n!==t&&this.d(iO(e,n)),this.parent&&this.parent.depend(e,t)}},e.prototype.dirty=function(e,t){this.d&&this.d.dirty(iO(e,t),"__exists"===t?"forget":"setDirty")},e}();function iO(e,t){return t+"#"+e}function iA(e,t){iD(e)&&e.group.depend(t,"__exists")}!function(e){var t=function(e){function t(t){var n=t.policies,r=t.resultCaching,i=void 0===r||r,a=t.seed,o=e.call(this,n,new iM(i))||this;return o.stump=new iC(o),o.storageTrie=new n_(t_.mr),a&&o.replace(a),o}return(0,en.ZT)(t,e),t.prototype.addLayer=function(e,t){return this.stump.addLayer(e,t)},t.prototype.removeLayer=function(){return this},t.prototype.getStorage=function(){return this.storageTrie.lookupArray(arguments)},t}(e);e.Root=t}(iT||(iT={}));var iL=function(e){function t(t,n,r,i){var a=e.call(this,n.policies,i)||this;return a.id=t,a.parent=n,a.replay=r,a.group=i,r(a),a}return(0,en.ZT)(t,e),t.prototype.addLayer=function(e,n){return new t(e,this,n,this.group)},t.prototype.removeLayer=function(e){var t=this,n=this.parent.removeLayer(e);return e===this.id?(this.group.caching&&Object.keys(this.data).forEach(function(e){var r=t.data[e],i=n.lookup(e);i?r?r!==i&&Object.keys(r).forEach(function(n){(0,nm.D)(r[n],i[n])||t.group.dirty(e,n)}):(t.group.dirty(e,"__exists"),Object.keys(i).forEach(function(n){t.group.dirty(e,n)})):t.delete(e)}),n):n===this.parent?this:n.addLayer(this.id,this.replay)},t.prototype.toObject=function(){return(0,en.pi)((0,en.pi)({},this.parent.toObject()),this.data)},t.prototype.findChildRefIds=function(t){var n=this.parent.findChildRefIds(t);return ic.call(this.data,t)?(0,en.pi)((0,en.pi)({},n),e.prototype.findChildRefIds.call(this,t)):n},t.prototype.getStorage=function(){for(var e=this.parent;e.parent;)e=e.parent;return e.getStorage.apply(e,arguments)},t}(iT),iC=function(e){function t(t){return e.call(this,"EntityStore.Stump",t,function(){},new iM(t.group.caching,t.group))||this}return(0,en.ZT)(t,e),t.prototype.removeLayer=function(){return this},t.prototype.merge=function(){return this.parent.merge.apply(this.parent,arguments)},t}(iL);function iI(e,t,n){var r=e[n],i=t[n];return(0,nm.D)(r,i)?r:i}function iD(e){return!!(e instanceof iT&&e.group.caching)}function iN(e){return[e.selectionSet,e.objectOrReference,e.context,e.context.canonizeResults,]}var iP=function(){function e(e){var t=this;this.knownResults=new(t_.mr?WeakMap:Map),this.config=(0,n1.o)(e,{addTypename:!1!==e.addTypename,canonizeResults:ib(e)}),this.canon=e.canon||new nk,this.executeSelectionSet=rZ(function(e){var n,r=e.context.canonizeResults,i=iN(e);i[3]=!r;var a=(n=t.executeSelectionSet).peek.apply(n,i);return a?r?(0,en.pi)((0,en.pi)({},a),{result:t.canon.admit(a.result)}):a:(iA(e.context.store,e.enclosingRef.__ref),t.execSelectionSetImpl(e))},{max:this.config.resultCacheMaxSize,keyArgs:iN,makeCacheKey:function(e,t,n,r){if(iD(n.store))return n.store.makeCacheKey(e,eD(t)?t.__ref:t,n.varString,r)}}),this.executeSubSelectedArray=rZ(function(e){return iA(e.context.store,e.enclosingRef.__ref),t.execSubSelectedArrayImpl(e)},{max:this.config.resultCacheMaxSize,makeCacheKey:function(e){var t=e.field,n=e.array,r=e.context;if(iD(r.store))return r.store.makeCacheKey(t,n,r.varString)}})}return e.prototype.resetCanon=function(){this.canon=new nk},e.prototype.diffQueryAgainstStore=function(e){var t,n=e.store,r=e.query,i=e.rootId,a=void 0===i?"ROOT_QUERY":i,o=e.variables,s=e.returnPartialData,u=void 0===s||s,c=e.canonizeResults,l=void 0===c?this.config.canonizeResults:c,f=this.config.cache.policies;o=(0,en.pi)((0,en.pi)({},e9(e6(r))),o);var d=eI(a),h=this.executeSelectionSet({selectionSet:e8(r).selectionSet,objectOrReference:d,enclosingRef:d,context:(0,en.pi)({store:n,query:r,policies:f,variables:o,varString:nx(o),canonizeResults:l},iE(r,this.config.fragments))});if(h.missing&&(t=[new is(iR(h.missing),h.missing,r,o)],!u))throw t[0];return{result:h.result,complete:!t,missing:t}},e.prototype.isFresh=function(e,t,n,r){if(iD(r.store)&&this.knownResults.get(e)===n){var i=this.executeSelectionSet.peek(n,t,r,this.canon.isKnown(e));if(i&&e===i.result)return!0}return!1},e.prototype.execSelectionSetImpl=function(e){var t,n=this,r=e.selectionSet,i=e.objectOrReference,a=e.enclosingRef,o=e.context;if(eD(i)&&!o.policies.rootTypenamesById[i.__ref]&&!o.store.has(i.__ref))return{result:this.canon.empty,missing:"Dangling reference to missing ".concat(i.__ref," object")};var s=o.variables,u=o.policies,c=o.store.getFieldValue(i,"__typename"),l=[],f=new tB;function d(e,n){var r;return e.missing&&(t=f.merge(t,((r={})[n]=e.missing,r))),e.result}this.config.addTypename&&"string"==typeof c&&!u.rootIdsByTypename[c]&&l.push({__typename:c});var h=new Set(r.selections);h.forEach(function(e){var r,p;if(td(e,s)){if(eQ(e)){var b=u.readField({fieldName:e.name.value,field:e,variables:o.variables,from:i},o),m=eX(e);void 0===b?nj.added(e)||(t=f.merge(t,((r={})[m]="Can't find field '".concat(e.name.value,"' on ").concat(eD(i)?i.__ref+" object":"object "+JSON.stringify(i,null,2)),r))):(0,tP.k)(b)?b=d(n.executeSubSelectedArray({field:e,array:b,enclosingRef:a,context:o}),m):e.selectionSet?null!=b&&(b=d(n.executeSelectionSet({selectionSet:e.selectionSet,objectOrReference:b,enclosingRef:eD(b)?b:a,context:o}),m)):o.canonizeResults&&(b=n.canon.pass(b)),void 0!==b&&l.push(((p={})[m]=b,p))}else{var g=eC(e,o.lookupFragment);if(!g&&e.kind===nL.h.FRAGMENT_SPREAD)throw __DEV__?new Q.ej("No fragment named ".concat(e.name.value)):new Q.ej(5);g&&u.fragmentMatches(g,c)&&g.selectionSet.selections.forEach(h.add,h)}}});var p={result:tF(l),missing:t},b=o.canonizeResults?this.canon.admit(p):(0,iu.J)(p);return b.result&&this.knownResults.set(b.result,r),b},e.prototype.execSubSelectedArrayImpl=function(e){var t,n=this,r=e.field,i=e.array,a=e.enclosingRef,o=e.context,s=new tB;function u(e,n){var r;return e.missing&&(t=s.merge(t,((r={})[n]=e.missing,r))),e.result}return r.selectionSet&&(i=i.filter(o.store.canRead)),i=i.map(function(e,t){return null===e?null:(0,tP.k)(e)?u(n.executeSubSelectedArray({field:r,array:e,enclosingRef:a,context:o}),t):r.selectionSet?u(n.executeSelectionSet({selectionSet:r.selectionSet,objectOrReference:e,enclosingRef:eD(e)?e:a,context:o}),t):(__DEV__&&ij(o.store,r,e),e)}),{result:o.canonizeResults?this.canon.admit(i):i,missing:t}},e}();function iR(e){try{JSON.stringify(e,function(e,t){if("string"==typeof t)throw t;return t})}catch(t){return t}}function ij(e,t,n){if(!t.selectionSet){var r=new Set([n]);r.forEach(function(n){(0,eO.s)(n)&&(__DEV__?(0,Q.kG)(!eD(n),"Missing selection set for object of type ".concat(im(e,n)," returned for query field ").concat(t.name.value)):(0,Q.kG)(!eD(n),6),Object.values(n).forEach(r.add,r))})}}function iF(e){var t=nG("stringifyForDisplay");return JSON.stringify(e,function(e,n){return void 0===n?t:n}).split(JSON.stringify(t)).join("")}var iY=Object.create(null);function iB(e){var t=JSON.stringify(e);return iY[t]||(iY[t]=Object.create(null))}function iU(e){var t=iB(e);return t.keyFieldsFn||(t.keyFieldsFn=function(t,n){var r=function(e,t){return n.readField(t,e)},i=n.keyObject=i$(e,function(e){var i=iW(n.storeObject,e,r);return void 0===i&&t!==n.storeObject&&ic.call(t,e[0])&&(i=iW(t,e,iG)),__DEV__?(0,Q.kG)(void 0!==i,"Missing field '".concat(e.join("."),"' while extracting keyFields from ").concat(JSON.stringify(t))):(0,Q.kG)(void 0!==i,2),i});return"".concat(n.typename,":").concat(JSON.stringify(i))})}function iH(e){var t=iB(e);return t.keyArgsFn||(t.keyArgsFn=function(t,n){var r=n.field,i=n.variables,a=n.fieldName,o=JSON.stringify(i$(e,function(e){var n=e[0],a=n.charAt(0);if("@"===a){if(r&&(0,tP.O)(r.directives)){var o=n.slice(1),s=r.directives.find(function(e){return e.name.value===o}),u=s&&eZ(s,i);return u&&iW(u,e.slice(1))}return}if("$"===a){var c=n.slice(1);if(i&&ic.call(i,c)){var l=e.slice(0);return l[0]=c,iW(i,l)}return}if(t)return iW(t,e)}));return(t||"{}"!==o)&&(a+=":"+o),a})}function i$(e,t){var n=new tB;return iz(e).reduce(function(e,r){var i,a=t(r);if(void 0!==a){for(var o=r.length-1;o>=0;--o)a=((i={})[r[o]]=a,i);e=n.merge(e,a)}return e},Object.create(null))}function iz(e){var t=iB(e);if(!t.paths){var n=t.paths=[],r=[];e.forEach(function(t,i){(0,tP.k)(t)?(iz(t).forEach(function(e){return n.push(r.concat(e))}),r.length=0):(r.push(t),(0,tP.k)(e[i+1])||(n.push(r.slice(0)),r.length=0))})}return t.paths}function iG(e,t){return e[t]}function iW(e,t,n){return n=n||iG,iK(t.reduce(function e(t,r){return(0,tP.k)(t)?t.map(function(t){return e(t,r)}):t&&n(t,r)},e))}function iK(e){return(0,eO.s)(e)?(0,tP.k)(e)?e.map(iK):i$(Object.keys(e).sort(),function(t){return iW(e,t)}):e}function iV(e){return void 0!==e.args?e.args:e.field?eZ(e.field,e.variables):null}eK.setStringify(nx);var iq=function(){},iZ=function(e,t){return t.fieldName},iX=function(e,t,n){return(0,n.mergeObjects)(e,t)},iJ=function(e,t){return t},iQ=function(){function e(e){this.config=e,this.typePolicies=Object.create(null),this.toBeAdded=Object.create(null),this.supertypeMap=new Map,this.fuzzySubtypes=new Map,this.rootIdsByTypename=Object.create(null),this.rootTypenamesById=Object.create(null),this.usingPossibleTypes=!1,this.config=(0,en.pi)({dataIdFromObject:id},e),this.cache=this.config.cache,this.setRootTypename("Query"),this.setRootTypename("Mutation"),this.setRootTypename("Subscription"),e.possibleTypes&&this.addPossibleTypes(e.possibleTypes),e.typePolicies&&this.addTypePolicies(e.typePolicies)}return e.prototype.identify=function(e,t){var n,r,i=this,a=t&&(t.typename||(null===(n=t.storeObject)||void 0===n?void 0:n.__typename))||e.__typename;if(a===this.rootTypenamesById.ROOT_QUERY)return["ROOT_QUERY"];for(var o=t&&t.storeObject||e,s=(0,en.pi)((0,en.pi)({},t),{typename:a,storeObject:o,readField:t&&t.readField||function(){var e=i0(arguments,o);return i.readField(e,{store:i.cache.data,variables:e.variables})}}),u=a&&this.getTypePolicy(a),c=u&&u.keyFn||this.config.dataIdFromObject;c;){var l=c((0,en.pi)((0,en.pi)({},e),o),s);if((0,tP.k)(l))c=iU(l);else{r=l;break}}return r=r?String(r):void 0,s.keyObject?[r,s.keyObject]:[r]},e.prototype.addTypePolicies=function(e){var t=this;Object.keys(e).forEach(function(n){var r=e[n],i=r.queryType,a=r.mutationType,o=r.subscriptionType,s=(0,en._T)(r,["queryType","mutationType","subscriptionType"]);i&&t.setRootTypename("Query",n),a&&t.setRootTypename("Mutation",n),o&&t.setRootTypename("Subscription",n),ic.call(t.toBeAdded,n)?t.toBeAdded[n].push(s):t.toBeAdded[n]=[s]})},e.prototype.updateTypePolicy=function(e,t){var n=this,r=this.getTypePolicy(e),i=t.keyFields,a=t.fields;function o(e,t){e.merge="function"==typeof t?t:!0===t?iX:!1===t?iJ:e.merge}o(r,t.merge),r.keyFn=!1===i?iq:(0,tP.k)(i)?iU(i):"function"==typeof i?i:r.keyFn,a&&Object.keys(a).forEach(function(t){var r=n.getFieldPolicy(e,t,!0),i=a[t];if("function"==typeof i)r.read=i;else{var s=i.keyArgs,u=i.read,c=i.merge;r.keyFn=!1===s?iZ:(0,tP.k)(s)?iH(s):"function"==typeof s?s:r.keyFn,"function"==typeof u&&(r.read=u),o(r,c)}r.read&&r.merge&&(r.keyFn=r.keyFn||iZ)})},e.prototype.setRootTypename=function(e,t){void 0===t&&(t=e);var n="ROOT_"+e.toUpperCase(),r=this.rootTypenamesById[n];t!==r&&(__DEV__?(0,Q.kG)(!r||r===e,"Cannot change root ".concat(e," __typename more than once")):(0,Q.kG)(!r||r===e,3),r&&delete this.rootIdsByTypename[r],this.rootIdsByTypename[t]=n,this.rootTypenamesById[n]=t)},e.prototype.addPossibleTypes=function(e){var t=this;this.usingPossibleTypes=!0,Object.keys(e).forEach(function(n){t.getSupertypeSet(n,!0),e[n].forEach(function(e){t.getSupertypeSet(e,!0).add(n);var r=e.match(ig);r&&r[0]===e||t.fuzzySubtypes.set(e,RegExp(e))})})},e.prototype.getTypePolicy=function(e){var t=this;if(!ic.call(this.typePolicies,e)){var n=this.typePolicies[e]=Object.create(null);n.fields=Object.create(null);var r=this.supertypeMap.get(e);r&&r.size&&r.forEach(function(e){var r=t.getTypePolicy(e),i=r.fields;Object.assign(n,(0,en._T)(r,["fields"])),Object.assign(n.fields,i)})}var i=this.toBeAdded[e];return i&&i.length&&i.splice(0).forEach(function(n){t.updateTypePolicy(e,n)}),this.typePolicies[e]},e.prototype.getFieldPolicy=function(e,t,n){if(e){var r=this.getTypePolicy(e).fields;return r[t]||n&&(r[t]=Object.create(null))}},e.prototype.getSupertypeSet=function(e,t){var n=this.supertypeMap.get(e);return!n&&t&&this.supertypeMap.set(e,n=new Set),n},e.prototype.fragmentMatches=function(e,t,n,r){var i=this;if(!e.typeCondition)return!0;if(!t)return!1;var a=e.typeCondition.name.value;if(t===a)return!0;if(this.usingPossibleTypes&&this.supertypeMap.has(a))for(var o=this.getSupertypeSet(t,!0),s=[o],u=function(e){var t=i.getSupertypeSet(e,!1);t&&t.size&&0>s.indexOf(t)&&s.push(t)},c=!!(n&&this.fuzzySubtypes.size),l=!1,f=0;f1?a:t}:(r=(0,en.pi)({},i),ic.call(r,"from")||(r.from=t)),__DEV__&&void 0===r.from&&__DEV__&&Q.kG.warn("Undefined 'from' passed to readField with arguments ".concat(iF(Array.from(e)))),void 0===r.variables&&(r.variables=n),r}function i2(e){return function(t,n){if((0,tP.k)(t)||(0,tP.k)(n))throw __DEV__?new Q.ej("Cannot automatically merge arrays"):new Q.ej(4);if((0,eO.s)(t)&&(0,eO.s)(n)){var r=e.getFieldValue(t,"__typename"),i=e.getFieldValue(n,"__typename");if(r&&i&&r!==i)return n;if(eD(t)&&iw(n))return e.merge(t.__ref,n),t;if(iw(t)&&eD(n))return e.merge(t,n.__ref),n;if(iw(t)&&iw(n))return(0,en.pi)((0,en.pi)({},t),n)}return n}}function i3(e,t,n){var r="".concat(t).concat(n),i=e.flavors.get(r);return i||e.flavors.set(r,i=e.clientOnly===t&&e.deferred===n?e:(0,en.pi)((0,en.pi)({},e),{clientOnly:t,deferred:n})),i}var i4=function(){function e(e,t,n){this.cache=e,this.reader=t,this.fragments=n}return e.prototype.writeToStore=function(e,t){var n=this,r=t.query,i=t.result,a=t.dataId,o=t.variables,s=t.overwrite,u=e2(r),c=i_();o=(0,en.pi)((0,en.pi)({},e9(u)),o);var l=(0,en.pi)((0,en.pi)({store:e,written:Object.create(null),merge:function(e,t){return c.merge(e,t)},variables:o,varString:nx(o)},iE(r,this.fragments)),{overwrite:!!s,incomingById:new Map,clientOnly:!1,deferred:!1,flavors:new Map}),f=this.processSelectionSet({result:i||Object.create(null),dataId:a,selectionSet:u.selectionSet,mergeTree:{map:new Map},context:l});if(!eD(f))throw __DEV__?new Q.ej("Could not identify object ".concat(JSON.stringify(i))):new Q.ej(7);return l.incomingById.forEach(function(t,r){var i=t.storeObject,a=t.mergeTree,o=t.fieldNodeSet,s=eI(r);if(a&&a.map.size){var u=n.applyMerges(a,s,i,l);if(eD(u))return;i=u}if(__DEV__&&!l.overwrite){var c=Object.create(null);o.forEach(function(e){e.selectionSet&&(c[e.name.value]=!0)});var f=function(e){return!0===c[iv(e)]},d=function(e){var t=a&&a.map.get(e);return Boolean(t&&t.info&&t.info.merge)};Object.keys(i).forEach(function(e){f(e)&&!d(e)&&at(s,i,e,l.store)})}e.merge(r,i)}),e.retain(f.__ref),f},e.prototype.processSelectionSet=function(e){var t=this,n=e.dataId,r=e.result,i=e.selectionSet,a=e.context,o=e.mergeTree,s=this.cache.policies,u=Object.create(null),c=n&&s.rootTypenamesById[n]||eJ(r,i,a.fragmentMap)||n&&a.store.get(n,"__typename");"string"==typeof c&&(u.__typename=c);var l=function(){var e=i0(arguments,u,a.variables);if(eD(e.from)){var t=a.incomingById.get(e.from.__ref);if(t){var n=s.readField((0,en.pi)((0,en.pi)({},e),{from:t.storeObject}),a);if(void 0!==n)return n}}return s.readField(e,a)},f=new Set;this.flattenFields(i,r,a,c).forEach(function(e,n){var i,a=r[eX(n)];if(f.add(n),void 0!==a){var d=s.getStoreFieldName({typename:c,fieldName:n.name.value,field:n,variables:e.variables}),h=i5(o,d),p=t.processFieldValue(a,n,n.selectionSet?i3(e,!1,!1):e,h),b=void 0;n.selectionSet&&(eD(p)||iw(p))&&(b=l("__typename",p));var m=s.getMergeFunction(c,n.name.value,b);m?h.info={field:n,typename:c,merge:m}:i7(o,d),u=e.merge(u,((i={})[d]=p,i))}else __DEV__&&!e.clientOnly&&!e.deferred&&!nj.added(n)&&!s.getReadFunction(c,n.name.value)&&__DEV__&&Q.kG.error("Missing field '".concat(eX(n),"' while writing result ").concat(JSON.stringify(r,null,2)).substring(0,1e3))});try{var d=s.identify(r,{typename:c,selectionSet:i,fragmentMap:a.fragmentMap,storeObject:u,readField:l}),h=d[0],p=d[1];n=n||h,p&&(u=a.merge(u,p))}catch(b){if(!n)throw b}if("string"==typeof n){var m=eI(n),g=a.written[n]||(a.written[n]=[]);if(g.indexOf(i)>=0||(g.push(i),this.reader&&this.reader.isFresh(r,m,i,a)))return m;var v=a.incomingById.get(n);return v?(v.storeObject=a.merge(v.storeObject,u),v.mergeTree=i8(v.mergeTree,o),f.forEach(function(e){return v.fieldNodeSet.add(e)})):a.incomingById.set(n,{storeObject:u,mergeTree:i9(o)?void 0:o,fieldNodeSet:f}),m}return u},e.prototype.processFieldValue=function(e,t,n,r){var i=this;return t.selectionSet&&null!==e?(0,tP.k)(e)?e.map(function(e,a){var o=i.processFieldValue(e,t,n,i5(r,a));return i7(r,a),o}):this.processSelectionSet({result:e,selectionSet:t.selectionSet,context:n,mergeTree:r}):__DEV__?nJ(e):e},e.prototype.flattenFields=function(e,t,n,r){void 0===r&&(r=eJ(t,e,n.fragmentMap));var i=new Map,a=this.cache.policies,o=new n_(!1);return function e(s,u){var c=o.lookup(s,u.clientOnly,u.deferred);c.visited||(c.visited=!0,s.selections.forEach(function(o){if(td(o,n.variables)){var s=u.clientOnly,c=u.deferred;if(!(s&&c)&&(0,tP.O)(o.directives)&&o.directives.forEach(function(e){var t=e.name.value;if("client"===t&&(s=!0),"defer"===t){var r=eZ(e,n.variables);r&&!1===r.if||(c=!0)}}),eQ(o)){var l=i.get(o);l&&(s=s&&l.clientOnly,c=c&&l.deferred),i.set(o,i3(n,s,c))}else{var f=eC(o,n.lookupFragment);if(!f&&o.kind===nL.h.FRAGMENT_SPREAD)throw __DEV__?new Q.ej("No fragment named ".concat(o.name.value)):new Q.ej(8);f&&a.fragmentMatches(f,r,t,n.variables)&&e(f.selectionSet,i3(n,s,c))}}}))}(e,n),i},e.prototype.applyMerges=function(e,t,n,r,i){var a=this;if(e.map.size&&!eD(n)){var o,s,u=!(0,tP.k)(n)&&(eD(t)||iw(t))?t:void 0,c=n;u&&!i&&(i=[eD(u)?u.__ref:u]);var l=function(e,t){return(0,tP.k)(e)?"number"==typeof t?e[t]:void 0:r.store.getFieldValue(e,String(t))};e.map.forEach(function(e,t){var n=l(u,t),o=l(c,t);if(void 0!==o){i&&i.push(t);var f=a.applyMerges(e,n,o,r,i);f!==o&&(s=s||new Map).set(t,f),i&&(0,Q.kG)(i.pop()===t)}}),s&&(n=(0,tP.k)(c)?c.slice(0):(0,en.pi)({},c),s.forEach(function(e,t){n[t]=e}))}return e.info?this.cache.policies.runMergeFunction(t,n,e.info,r,i&&(o=r.store).getStorage.apply(o,i)):n},e}(),i6=[];function i5(e,t){var n=e.map;return n.has(t)||n.set(t,i6.pop()||{map:new Map}),n.get(t)}function i8(e,t){if(e===t||!t||i9(t))return e;if(!e||i9(e))return t;var n=e.info&&t.info?(0,en.pi)((0,en.pi)({},e.info),t.info):e.info||t.info,r=e.map.size&&t.map.size,i=r?new Map:e.map.size?e.map:t.map,a={info:n,map:i};if(r){var o=new Set(t.map.keys());e.map.forEach(function(e,n){a.map.set(n,i8(e,t.map.get(n))),o.delete(n)}),o.forEach(function(n){a.map.set(n,i8(t.map.get(n),e.map.get(n)))})}return a}function i9(e){return!e||!(e.info||e.map.size)}function i7(e,t){var n=e.map,r=n.get(t);r&&i9(r)&&(i6.push(r),n.delete(t))}var ae=new Set;function at(e,t,n,r){var i=function(e){var t=r.getFieldValue(e,n);return"object"==typeof t&&t},a=i(e);if(a){var o=i(t);if(!(!o||eD(a)||(0,nm.D)(a,o)||Object.keys(a).every(function(e){return void 0!==r.getFieldValue(o,e)}))){var s=r.getFieldValue(e,"__typename")||r.getFieldValue(t,"__typename"),u=iv(n),c="".concat(s,".").concat(u);if(!ae.has(c)){ae.add(c);var l=[];(0,tP.k)(a)||(0,tP.k)(o)||[a,o].forEach(function(e){var t=r.getFieldValue(e,"__typename");"string"!=typeof t||l.includes(t)||l.push(t)}),__DEV__&&Q.kG.warn("Cache data may be lost when replacing the ".concat(u," field of a ").concat(s," object.\n\nThis could cause additional (usually avoidable) network requests to fetch data that were otherwise cached.\n\nTo address this problem (which is not a bug in Apollo Client), ").concat(l.length?"either ensure all objects of type "+l.join(" and ")+" have an ID or a custom merge function, or ":"","define a custom merge function for the ").concat(c," field, so InMemoryCache can safely merge these objects:\n\n existing: ").concat(JSON.stringify(a).slice(0,1e3),"\n incoming: ").concat(JSON.stringify(o).slice(0,1e3),"\n\nFor more information about these options, please refer to the documentation:\n\n * Ensuring entity objects have IDs: https://go.apollo.dev/c/generating-unique-identifiers\n * Defining custom merge functions: https://go.apollo.dev/c/merging-non-normalized-objects\n"))}}}}var an=function(e){function t(t){void 0===t&&(t={});var n=e.call(this)||this;return n.watches=new Set,n.typenameDocumentCache=new Map,n.makeVar=r2,n.txCount=0,n.config=ip(t),n.addTypename=!!n.config.addTypename,n.policies=new iQ({cache:n,dataIdFromObject:n.config.dataIdFromObject,possibleTypes:n.config.possibleTypes,typePolicies:n.config.typePolicies}),n.init(),n}return(0,en.ZT)(t,e),t.prototype.init=function(){var e=this.data=new iT.Root({policies:this.policies,resultCaching:this.config.resultCaching});this.optimisticData=e.stump,this.resetResultCache()},t.prototype.resetResultCache=function(e){var t=this,n=this.storeReader,r=this.config.fragments;this.storeWriter=new i4(this,this.storeReader=new iP({cache:this,addTypename:this.addTypename,resultCacheMaxSize:this.config.resultCacheMaxSize,canonizeResults:ib(this.config),canon:e?void 0:n&&n.canon,fragments:r}),r),this.maybeBroadcastWatch=rZ(function(e,n){return t.broadcastWatch(e,n)},{max:this.config.resultCacheMaxSize,makeCacheKey:function(e){var n=e.optimistic?t.optimisticData:t.data;if(iD(n)){var r=e.optimistic,i=e.id,a=e.variables;return n.makeCacheKey(e.query,e.callback,nx({optimistic:r,id:i,variables:a}))}}}),new Set([this.data.group,this.optimisticData.group,]).forEach(function(e){return e.resetCaching()})},t.prototype.restore=function(e){return this.init(),e&&this.data.replace(e),this},t.prototype.extract=function(e){return void 0===e&&(e=!1),(e?this.optimisticData:this.data).extract()},t.prototype.read=function(e){var t=e.returnPartialData,n=void 0!==t&&t;try{return this.storeReader.diffQueryAgainstStore((0,en.pi)((0,en.pi)({},e),{store:e.optimistic?this.optimisticData:this.data,config:this.config,returnPartialData:n})).result||null}catch(r){if(r instanceof is)return null;throw r}},t.prototype.write=function(e){try{return++this.txCount,this.storeWriter.writeToStore(this.data,e)}finally{--this.txCount||!1===e.broadcast||this.broadcastWatches()}},t.prototype.modify=function(e){if(ic.call(e,"id")&&!e.id)return!1;var t=e.optimistic?this.optimisticData:this.data;try{return++this.txCount,t.modify(e.id||"ROOT_QUERY",e.fields)}finally{--this.txCount||!1===e.broadcast||this.broadcastWatches()}},t.prototype.diff=function(e){return this.storeReader.diffQueryAgainstStore((0,en.pi)((0,en.pi)({},e),{store:e.optimistic?this.optimisticData:this.data,rootId:e.id||"ROOT_QUERY",config:this.config}))},t.prototype.watch=function(e){var t=this;return this.watches.size||r0(this),this.watches.add(e),e.immediate&&this.maybeBroadcastWatch(e),function(){t.watches.delete(e)&&!t.watches.size&&r1(t),t.maybeBroadcastWatch.forget(e)}},t.prototype.gc=function(e){nx.reset();var t=this.optimisticData.gc();return e&&!this.txCount&&(e.resetResultCache?this.resetResultCache(e.resetResultIdentities):e.resetResultIdentities&&this.storeReader.resetCanon()),t},t.prototype.retain=function(e,t){return(t?this.optimisticData:this.data).retain(e)},t.prototype.release=function(e,t){return(t?this.optimisticData:this.data).release(e)},t.prototype.identify=function(e){if(eD(e))return e.__ref;try{return this.policies.identify(e)[0]}catch(t){__DEV__&&Q.kG.warn(t)}},t.prototype.evict=function(e){if(!e.id){if(ic.call(e,"id"))return!1;e=(0,en.pi)((0,en.pi)({},e),{id:"ROOT_QUERY"})}try{return++this.txCount,this.optimisticData.evict(e,this.data)}finally{--this.txCount||!1===e.broadcast||this.broadcastWatches()}},t.prototype.reset=function(e){var t=this;return this.init(),nx.reset(),e&&e.discardWatches?(this.watches.forEach(function(e){return t.maybeBroadcastWatch.forget(e)}),this.watches.clear(),r1(this)):this.broadcastWatches(),Promise.resolve()},t.prototype.removeOptimistic=function(e){var t=this.optimisticData.removeLayer(e);t!==this.optimisticData&&(this.optimisticData=t,this.broadcastWatches())},t.prototype.batch=function(e){var t,n=this,r=e.update,i=e.optimistic,a=void 0===i||i,o=e.removeOptimistic,s=e.onWatchUpdated,u=function(e){var i=n,a=i.data,o=i.optimisticData;++n.txCount,e&&(n.data=n.optimisticData=e);try{return t=r(n)}finally{--n.txCount,n.data=a,n.optimisticData=o}},c=new Set;return s&&!this.txCount&&this.broadcastWatches((0,en.pi)((0,en.pi)({},e),{onWatchUpdated:function(e){return c.add(e),!1}})),"string"==typeof a?this.optimisticData=this.optimisticData.addLayer(a,u):!1===a?u(this.data):u(),"string"==typeof o&&(this.optimisticData=this.optimisticData.removeLayer(o)),s&&c.size?(this.broadcastWatches((0,en.pi)((0,en.pi)({},e),{onWatchUpdated:function(e,t){var n=s.call(this,e,t);return!1!==n&&c.delete(e),n}})),c.size&&c.forEach(function(e){return n.maybeBroadcastWatch.dirty(e)})):this.broadcastWatches(e),t},t.prototype.performTransaction=function(e,t){return this.batch({update:e,optimistic:t||null!==t})},t.prototype.transformDocument=function(e){if(this.addTypename){var t=this.typenameDocumentCache.get(e);return t||(t=nj(e),this.typenameDocumentCache.set(e,t),this.typenameDocumentCache.set(t,t)),t}return e},t.prototype.transformForLink=function(e){var t=this.config.fragments;return t?t.transform(e):e},t.prototype.broadcastWatches=function(e){var t=this;this.txCount||this.watches.forEach(function(n){return t.maybeBroadcastWatch(n,e)})},t.prototype.broadcastWatch=function(e,t){var n=e.lastDiff,r=this.diff(e);(!t||(e.optimistic&&"string"==typeof t.optimistic&&(r.fromOptimisticTransaction=!0),!t.onWatchUpdated||!1!==t.onWatchUpdated.call(this,e,r,n)))&&(n&&(0,nm.D)(n.result,r.result)||e.callback(e.lastDiff=r,n))},t}(io),ar={possibleTypes:{ApproveJobProposalSpecPayload:["ApproveJobProposalSpecSuccess","JobAlreadyExistsError","NotFoundError"],BridgePayload:["Bridge","NotFoundError"],CancelJobProposalSpecPayload:["CancelJobProposalSpecSuccess","NotFoundError"],ChainPayload:["Chain","NotFoundError"],CreateAPITokenPayload:["CreateAPITokenSuccess","InputErrors"],CreateBridgePayload:["CreateBridgeSuccess"],CreateCSAKeyPayload:["CSAKeyExistsError","CreateCSAKeySuccess"],CreateFeedsManagerChainConfigPayload:["CreateFeedsManagerChainConfigSuccess","InputErrors","NotFoundError"],CreateFeedsManagerPayload:["CreateFeedsManagerSuccess","DuplicateFeedsManagerError","InputErrors","NotFoundError","SingleFeedsManagerError"],CreateJobPayload:["CreateJobSuccess","InputErrors"],CreateOCR2KeyBundlePayload:["CreateOCR2KeyBundleSuccess"],CreateOCRKeyBundlePayload:["CreateOCRKeyBundleSuccess"],CreateP2PKeyPayload:["CreateP2PKeySuccess"],DeleteAPITokenPayload:["DeleteAPITokenSuccess","InputErrors"],DeleteBridgePayload:["DeleteBridgeConflictError","DeleteBridgeInvalidNameError","DeleteBridgeSuccess","NotFoundError"],DeleteCSAKeyPayload:["DeleteCSAKeySuccess","NotFoundError"],DeleteFeedsManagerChainConfigPayload:["DeleteFeedsManagerChainConfigSuccess","NotFoundError"],DeleteJobPayload:["DeleteJobSuccess","NotFoundError"],DeleteOCR2KeyBundlePayload:["DeleteOCR2KeyBundleSuccess","NotFoundError"],DeleteOCRKeyBundlePayload:["DeleteOCRKeyBundleSuccess","NotFoundError"],DeleteP2PKeyPayload:["DeleteP2PKeySuccess","NotFoundError"],DeleteVRFKeyPayload:["DeleteVRFKeySuccess","NotFoundError"],DisableFeedsManagerPayload:["DisableFeedsManagerSuccess","NotFoundError"],DismissJobErrorPayload:["DismissJobErrorSuccess","NotFoundError"],EnableFeedsManagerPayload:["EnableFeedsManagerSuccess","NotFoundError"],Error:["CSAKeyExistsError","DeleteBridgeConflictError","DeleteBridgeInvalidNameError","DuplicateFeedsManagerError","InputError","JobAlreadyExistsError","NotFoundError","RunJobCannotRunError","SingleFeedsManagerError"],EthTransactionPayload:["EthTransaction","NotFoundError"],FeaturesPayload:["Features"],FeedsManagerPayload:["FeedsManager","NotFoundError"],GetSQLLoggingPayload:["SQLLogging"],GlobalLogLevelPayload:["GlobalLogLevel"],JobPayload:["Job","NotFoundError"],JobProposalPayload:["JobProposal","NotFoundError"],JobRunPayload:["JobRun","NotFoundError"],JobSpec:["BlockHeaderFeederSpec","BlockhashStoreSpec","BootstrapSpec","CronSpec","DirectRequestSpec","FluxMonitorSpec","GatewaySpec","KeeperSpec","OCR2Spec","OCRSpec","StandardCapabilitiesSpec","StreamSpec","VRFSpec","WebhookSpec","WorkflowSpec"],NodePayload:["Node","NotFoundError"],PaginatedPayload:["BridgesPayload","ChainsPayload","EthTransactionAttemptsPayload","EthTransactionsPayload","JobRunsPayload","JobsPayload","NodesPayload"],RejectJobProposalSpecPayload:["NotFoundError","RejectJobProposalSpecSuccess"],RunJobPayload:["NotFoundError","RunJobCannotRunError","RunJobSuccess"],SetGlobalLogLevelPayload:["InputErrors","SetGlobalLogLevelSuccess"],SetSQLLoggingPayload:["SetSQLLoggingSuccess"],SetServicesLogLevelsPayload:["InputErrors","SetServicesLogLevelsSuccess"],UpdateBridgePayload:["NotFoundError","UpdateBridgeSuccess"],UpdateFeedsManagerChainConfigPayload:["InputErrors","NotFoundError","UpdateFeedsManagerChainConfigSuccess"],UpdateFeedsManagerPayload:["InputErrors","NotFoundError","UpdateFeedsManagerSuccess"],UpdateJobProposalSpecDefinitionPayload:["NotFoundError","UpdateJobProposalSpecDefinitionSuccess"],UpdatePasswordPayload:["InputErrors","UpdatePasswordSuccess"],VRFKeyPayload:["NotFoundError","VRFKeySuccess"]}};let ai=ar;var aa=(r=void 0,location.origin),ao=new nh({uri:"".concat(aa,"/query"),credentials:"include"}),as=new ia({cache:new an({possibleTypes:ai.possibleTypes,dataIdFromObject:function(e){if("Chain"===e.__typename){if(!e.network)throw Error("Due to Chain ID not being unique across chain, ensure network is fetched too");return"Chain:".concat(e.network,":").concat(e.id)}return id(e)}}),link:ao});if(a.Z.locale(o),u().defaultFormat="YYYY-MM-DD h:mm:ss A","undefined"!=typeof document){var au,ac,al=f().hydrate;ac=X,al(c.createElement(et,{client:as},c.createElement(d.zj,null,c.createElement(i.MuiThemeProvider,{theme:J.r},c.createElement(ac,null)))),document.getElementById("root"))}})()})(); \ No newline at end of file +`+(a!==i?`result of cast: ${a}`:""))}return r}_cast(e,t){let n=void 0===e?e:this.transforms.reduce((t,n)=>n.call(this,t,e,this),e);return void 0===n&&(n=this.getDefault()),n}_validate(e,t={},n){let{sync:r,path:i,from:a=[],originalValue:o=e,strict:s=this.spec.strict,abortEarly:u=this.spec.abortEarly}=t,c=e;s||(c=this._cast(c,pB({assert:!1},t)));let l={value:c,path:i,options:t,originalValue:o,schema:this,label:this.spec.label,sync:r,from:a},f=[];this._typeError&&f.push(this._typeError),this._whitelistError&&f.push(this._whitelistError),this._blacklistError&&f.push(this._blacklistError),pO({args:l,value:c,path:i,sync:r,tests:f,endEarly:u},e=>{if(e)return void n(e,c);pO({tests:this.tests,args:l,path:i,sync:r,value:c,endEarly:u},n)})}validate(e,t,n){let r=this.resolve(pB({},t,{value:e}));return"function"==typeof n?r._validate(e,t,n):new Promise((n,i)=>r._validate(e,t,(e,t)=>{e?i(e):n(t)}))}validateSync(e,t){let n;return this.resolve(pB({},t,{value:e}))._validate(e,pB({},t,{sync:!0}),(e,t)=>{if(e)throw e;n=t}),n}isValid(e,t){return this.validate(e,t).then(()=>!0,e=>{if(pT.isError(e))return!1;throw e})}isValidSync(e,t){try{return this.validateSync(e,t),!0}catch(n){if(pT.isError(n))return!1;throw n}}_getDefault(){let e=this.spec.default;return null==e?e:"function"==typeof e?e.call(this):pn(e)}getDefault(e){return this.resolve(e||{})._getDefault()}default(e){return 0===arguments.length?this._getDefault():this.clone({default:e})}strict(e=!0){var t=this.clone();return t.spec.strict=e,t}_isPresent(e){return null!=e}defined(e=pf.defined){return this.test({message:e,name:"defined",exclusive:!0,test:e=>void 0!==e})}required(e=pf.required){return this.clone({presence:"required"}).withMutation(t=>t.test({message:e,name:"required",exclusive:!0,test(e){return this.schema._isPresent(e)}}))}notRequired(){var e=this.clone({presence:"optional"});return e.tests=e.tests.filter(e=>"required"!==e.OPTIONS.name),e}nullable(e=!0){return this.clone({nullable:!1!==e})}transform(e){var t=this.clone();return t.transforms.push(e),t}test(...e){let t;if(void 0===(t=1===e.length?"function"==typeof e[0]?{test:e[0]}:e[0]:2===e.length?{name:e[0],test:e[1]}:{name:e[0],message:e[1],test:e[2]}).message&&(t.message=pf.default),"function"!=typeof t.test)throw TypeError("`test` is a required parameters");let n=this.clone(),r=pR(t),i=t.exclusive||t.name&&!0===n.exclusiveTests[t.name];if(t.exclusive&&!t.name)throw TypeError("Exclusive tests must provide a unique `name` identifying the test");return t.name&&(n.exclusiveTests[t.name]=!!t.exclusive),n.tests=n.tests.filter(e=>e.OPTIONS.name!==t.name||!i&&e.OPTIONS.test!==r.OPTIONS.test),n.tests.push(r),n}when(e,t){Array.isArray(e)||"string"==typeof e||(t=e,e=".");let n=this.clone(),r=pS(e).map(e=>new pD(e));return r.forEach(e=>{e.isSibling&&n.deps.push(e.key)}),n.conditions.push(new pE(r,t)),n}typeError(e){var t=this.clone();return t._typeError=pR({message:e,name:"typeError",test(e){return!!(void 0===e||this.schema.isType(e))||this.createError({params:{type:this.schema._type}})}}),t}oneOf(e,t=pf.oneOf){var n=this.clone();return e.forEach(e=>{n._whitelist.add(e),n._blacklist.delete(e)}),n._whitelistError=pR({message:t,name:"oneOf",test(e){if(void 0===e)return!0;let t=this.schema._whitelist;return!!t.has(e,this.resolve)||this.createError({params:{values:t.toArray().join(", ")}})}}),n}notOneOf(e,t=pf.notOneOf){var n=this.clone();return e.forEach(e=>{n._blacklist.add(e),n._whitelist.delete(e)}),n._blacklistError=pR({message:t,name:"notOneOf",test(e){let t=this.schema._blacklist;return!t.has(e,this.resolve)||this.createError({params:{values:t.toArray().join(", ")}})}}),n}strip(e=!0){let t=this.clone();return t.spec.strip=e,t}describe(){let e=this.clone(),{label:t,meta:n}=e.spec,r={meta:n,label:t,type:e.type,oneOf:e._whitelist.describe(),notOneOf:e._blacklist.describe(),tests:e.tests.map(e=>({name:e.OPTIONS.name,params:e.OPTIONS.params})).filter((e,t,n)=>n.findIndex(t=>t.name===e.name)===t)};return r}}for(let pH of(pU.prototype.__isYupSchema__=!0,["validate","validateSync"]))pU.prototype[`${pH}At`]=function(e,t,n={}){let{parent:r,parentPath:i,schema:a}=pF(this,e,t,n.context);return a[pH](r&&r[i],pB({},n,{parent:r,path:e}))};for(let p$ of["equals","is"])pU.prototype[p$]=pU.prototype.oneOf;for(let pz of["not","nope"])pU.prototype[pz]=pU.prototype.notOneOf;pU.prototype.optional=pU.prototype.notRequired;let pG=pU;function pW(){return new pG}pW.prototype=pG.prototype;let pK=e=>null==e;function pV(){return new pq}class pq extends pU{constructor(){super({type:"boolean"}),this.withMutation(()=>{this.transform(function(e){if(!this.isType(e)){if(/^(true|1)$/i.test(String(e)))return!0;if(/^(false|0)$/i.test(String(e)))return!1}return e})})}_typeCheck(e){return e instanceof Boolean&&(e=e.valueOf()),"boolean"==typeof e}isTrue(e=pb.isValue){return this.test({message:e,name:"is-value",exclusive:!0,params:{value:"true"},test:e=>pK(e)||!0===e})}isFalse(e=pb.isValue){return this.test({message:e,name:"is-value",exclusive:!0,params:{value:"false"},test:e=>pK(e)||!1===e})}}pV.prototype=pq.prototype;let pZ=/^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))$/i,pX=/^((https?|ftp):)?\/\/(((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:)*@)?(((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5]))|((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?)(:\d*)?)(\/((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)+(\/(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*)?)?(\?((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|[\uE000-\uF8FF]|\/|\?)*)?(\#((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|\/|\?)*)?$/i,pJ=/^(?:[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}|00000000-0000-0000-0000-000000000000)$/i,pQ=e=>pK(e)||e===e.trim(),p1=({}).toString();function p0(){return new p2}class p2 extends pU{constructor(){super({type:"string"}),this.withMutation(()=>{this.transform(function(e){if(this.isType(e)||Array.isArray(e))return e;let t=null!=e&&e.toString?e.toString():e;return t===p1?e:t})})}_typeCheck(e){return e instanceof String&&(e=e.valueOf()),"string"==typeof e}_isPresent(e){return super._isPresent(e)&&!!e.length}length(e,t=pd.length){return this.test({message:t,name:"length",exclusive:!0,params:{length:e},test(t){return pK(t)||t.length===this.resolve(e)}})}min(e,t=pd.min){return this.test({message:t,name:"min",exclusive:!0,params:{min:e},test(t){return pK(t)||t.length>=this.resolve(e)}})}max(e,t=pd.max){return this.test({name:"max",exclusive:!0,message:t,params:{max:e},test(t){return pK(t)||t.length<=this.resolve(e)}})}matches(e,t){let n=!1,r,i;return t&&("object"==typeof t?{excludeEmptyString:n=!1,message:r,name:i}=t:r=t),this.test({name:i||"matches",message:r||pd.matches,params:{regex:e},test:t=>pK(t)||""===t&&n||-1!==t.search(e)})}email(e=pd.email){return this.matches(pZ,{name:"email",message:e,excludeEmptyString:!0})}url(e=pd.url){return this.matches(pX,{name:"url",message:e,excludeEmptyString:!0})}uuid(e=pd.uuid){return this.matches(pJ,{name:"uuid",message:e,excludeEmptyString:!1})}ensure(){return this.default("").transform(e=>null===e?"":e)}trim(e=pd.trim){return this.transform(e=>null!=e?e.trim():e).test({message:e,name:"trim",test:pQ})}lowercase(e=pd.lowercase){return this.transform(e=>pK(e)?e:e.toLowerCase()).test({message:e,name:"string_case",exclusive:!0,test:e=>pK(e)||e===e.toLowerCase()})}uppercase(e=pd.uppercase){return this.transform(e=>pK(e)?e:e.toUpperCase()).test({message:e,name:"string_case",exclusive:!0,test:e=>pK(e)||e===e.toUpperCase()})}}p0.prototype=p2.prototype;let p3=e=>e!=+e;function p4(){return new p6}class p6 extends pU{constructor(){super({type:"number"}),this.withMutation(()=>{this.transform(function(e){let t=e;if("string"==typeof t){if(""===(t=t.replace(/\s/g,"")))return NaN;t=+t}return this.isType(t)?t:parseFloat(t)})})}_typeCheck(e){return e instanceof Number&&(e=e.valueOf()),"number"==typeof e&&!p3(e)}min(e,t=ph.min){return this.test({message:t,name:"min",exclusive:!0,params:{min:e},test(t){return pK(t)||t>=this.resolve(e)}})}max(e,t=ph.max){return this.test({message:t,name:"max",exclusive:!0,params:{max:e},test(t){return pK(t)||t<=this.resolve(e)}})}lessThan(e,t=ph.lessThan){return this.test({message:t,name:"max",exclusive:!0,params:{less:e},test(t){return pK(t)||tthis.resolve(e)}})}positive(e=ph.positive){return this.moreThan(0,e)}negative(e=ph.negative){return this.lessThan(0,e)}integer(e=ph.integer){return this.test({name:"integer",message:e,test:e=>pK(e)||Number.isInteger(e)})}truncate(){return this.transform(e=>pK(e)?e:0|e)}round(e){var t,n=["ceil","floor","round","trunc"];if("trunc"===(e=(null==(t=e)?void 0:t.toLowerCase())||"round"))return this.truncate();if(-1===n.indexOf(e.toLowerCase()))throw TypeError("Only valid options for round() are: "+n.join(", "));return this.transform(t=>pK(t)?t:Math[e](t))}}p4.prototype=p6.prototype;var p5=/^(\d{4}|[+\-]\d{6})(?:-?(\d{2})(?:-?(\d{2}))?)?(?:[ T]?(\d{2}):?(\d{2})(?::?(\d{2})(?:[,\.](\d{1,}))?)?(?:(Z)|([+\-])(\d{2})(?::?(\d{2}))?)?)?$/;function p8(e){var t,n,r=[1,4,5,6,7,10,11],i=0;if(n=p5.exec(e)){for(var a,o=0;a=r[o];++o)n[a]=+n[a]||0;n[2]=(+n[2]||1)-1,n[3]=+n[3]||1,n[7]=n[7]?String(n[7]).substr(0,3):0,(void 0===n[8]||""===n[8])&&(void 0===n[9]||""===n[9])?t=+new Date(n[1],n[2],n[3],n[4],n[5],n[6],n[7]):("Z"!==n[8]&&void 0!==n[9]&&(i=60*n[10]+n[11],"+"===n[9]&&(i=0-i)),t=Date.UTC(n[1],n[2],n[3],n[4],n[5]+i,n[6],n[7]))}else t=Date.parse?Date.parse(e):NaN;return t}let p9=new Date(""),p7=e=>"[object Date]"===Object.prototype.toString.call(e);function be(){return new bt}class bt extends pU{constructor(){super({type:"date"}),this.withMutation(()=>{this.transform(function(e){return this.isType(e)?e:(e=p8(e),isNaN(e)?p9:new Date(e))})})}_typeCheck(e){return p7(e)&&!isNaN(e.getTime())}prepareParam(e,t){let n;if(pD.isRef(e))n=e;else{let r=this.cast(e);if(!this._typeCheck(r))throw TypeError(`\`${t}\` must be a Date or a value that can be \`cast()\` to a Date`);n=r}return n}min(e,t=pp.min){let n=this.prepareParam(e,"min");return this.test({message:t,name:"min",exclusive:!0,params:{min:e},test(e){return pK(e)||e>=this.resolve(n)}})}max(e,t=pp.max){var n=this.prepareParam(e,"max");return this.test({message:t,name:"max",exclusive:!0,params:{max:e},test(e){return pK(e)||e<=this.resolve(n)}})}}bt.INVALID_DATE=p9,be.prototype=bt.prototype,be.INVALID_DATE=p9;var bn=n(11865),br=n.n(bn),bi=n(68929),ba=n.n(bi),bo=n(67523),bs=n.n(bo),bu=n(94633),bc=n.n(bu);function bl(e,t=[]){let n=[],r=[];function i(e,i){var a=(0,pC.split)(e)[0];~r.indexOf(a)||r.push(a),~t.indexOf(`${i}-${a}`)||n.push([i,a])}for(let a in e)if(py()(e,a)){let o=e[a];~r.indexOf(a)||r.push(a),pD.isRef(o)&&o.isSibling?i(o.path,a):pw(o)&&"deps"in o&&o.deps.forEach(e=>i(e,a))}return bc().array(r,n).reverse()}function bf(e,t){let n=1/0;return e.some((e,r)=>{var i;if((null==(i=t.path)?void 0:i.indexOf(e))!==-1)return n=r,!0}),n}function bd(e){return(t,n)=>bf(e,t)-bf(e,n)}function bh(){return(bh=Object.assign||function(e){for(var t=1;t"[object Object]"===Object.prototype.toString.call(e);function bb(e,t){let n=Object.keys(e.fields);return Object.keys(t).filter(e=>-1===n.indexOf(e))}let bm=bd([]);class bg extends pU{constructor(e){super({type:"object"}),this.fields=Object.create(null),this._sortErrors=bm,this._nodes=[],this._excludedEdges=[],this.withMutation(()=>{this.transform(function(e){if("string"==typeof e)try{e=JSON.parse(e)}catch(t){e=null}return this.isType(e)?e:null}),e&&this.shape(e)})}_typeCheck(e){return bp(e)||"function"==typeof e}_cast(e,t={}){var n;let r=super._cast(e,t);if(void 0===r)return this.getDefault();if(!this._typeCheck(r))return r;let i=this.fields,a=null!=(n=t.stripUnknown)?n:this.spec.noUnknown,o=this._nodes.concat(Object.keys(r).filter(e=>-1===this._nodes.indexOf(e))),s={},u=bh({},t,{parent:s,__validating:t.__validating||!1}),c=!1;for(let l of o){let f=i[l],d=py()(r,l);if(f){let h,p=r[l];u.path=(t.path?`${t.path}.`:"")+l;let b="spec"in(f=f.resolve({value:p,context:t.context,parent:s}))?f.spec:void 0,m=null==b?void 0:b.strict;if(null==b?void 0:b.strip){c=c||l in r;continue}void 0!==(h=t.__validating&&m?r[l]:f.cast(r[l],u))&&(s[l]=h)}else d&&!a&&(s[l]=r[l]);s[l]!==r[l]&&(c=!0)}return c?s:r}_validate(e,t={},n){let r=[],{sync:i,from:a=[],originalValue:o=e,abortEarly:s=this.spec.abortEarly,recursive:u=this.spec.recursive}=t;a=[{schema:this,value:o},...a],t.__validating=!0,t.originalValue=o,t.from=a,super._validate(e,t,(e,c)=>{if(e){if(!pT.isError(e)||s)return void n(e,c);r.push(e)}if(!u||!bp(c)){n(r[0]||null,c);return}o=o||c;let l=this._nodes.map(e=>(n,r)=>{let i=-1===e.indexOf(".")?(t.path?`${t.path}.`:"")+e:`${t.path||""}["${e}"]`,s=this.fields[e];if(s&&"validate"in s){s.validate(c[e],bh({},t,{path:i,from:a,strict:!0,parent:c,originalValue:o[e]}),r);return}r(null)});pO({sync:i,tests:l,value:c,errors:r,endEarly:s,sort:this._sortErrors,path:t.path},n)})}clone(e){let t=super.clone(e);return t.fields=bh({},this.fields),t._nodes=this._nodes,t._excludedEdges=this._excludedEdges,t._sortErrors=this._sortErrors,t}concat(e){let t=super.concat(e),n=t.fields;for(let[r,i]of Object.entries(this.fields)){let a=n[r];void 0===a?n[r]=i:a instanceof pU&&i instanceof pU&&(n[r]=i.concat(a))}return t.withMutation(()=>t.shape(n))}getDefaultFromShape(){let e={};return this._nodes.forEach(t=>{let n=this.fields[t];e[t]="default"in n?n.getDefault():void 0}),e}_getDefault(){return"default"in this.spec?super._getDefault():this._nodes.length?this.getDefaultFromShape():void 0}shape(e,t=[]){let n=this.clone(),r=Object.assign(n.fields,e);if(n.fields=r,n._sortErrors=bd(Object.keys(r)),t.length){Array.isArray(t[0])||(t=[t]);let i=t.map(([e,t])=>`${e}-${t}`);n._excludedEdges=n._excludedEdges.concat(i)}return n._nodes=bl(r,n._excludedEdges),n}pick(e){let t={};for(let n of e)this.fields[n]&&(t[n]=this.fields[n]);return this.clone().withMutation(e=>(e.fields={},e.shape(t)))}omit(e){let t=this.clone(),n=t.fields;for(let r of(t.fields={},e))delete n[r];return t.withMutation(()=>t.shape(n))}from(e,t,n){let r=(0,pC.getter)(e,!0);return this.transform(i=>{if(null==i)return i;let a=i;return py()(i,e)&&(a=bh({},i),n||delete a[e],a[t]=r(i)),a})}noUnknown(e=!0,t=pm.noUnknown){"string"==typeof e&&(t=e,e=!0);let n=this.test({name:"noUnknown",exclusive:!0,message:t,test(t){if(null==t)return!0;let n=bb(this.schema,t);return!e||0===n.length||this.createError({params:{unknown:n.join(", ")}})}});return n.spec.noUnknown=e,n}unknown(e=!0,t=pm.noUnknown){return this.noUnknown(!e,t)}transformKeys(e){return this.transform(t=>t&&bs()(t,(t,n)=>e(n)))}camelCase(){return this.transformKeys(ba())}snakeCase(){return this.transformKeys(br())}constantCase(){return this.transformKeys(e=>br()(e).toUpperCase())}describe(){let e=super.describe();return e.fields=pL()(this.fields,e=>e.describe()),e}}function bv(e){return new bg(e)}function by(){return(by=Object.assign||function(e){for(var t=1;t{this.transform(function(e){if("string"==typeof e)try{e=JSON.parse(e)}catch(t){e=null}return this.isType(e)?e:null})})}_typeCheck(e){return Array.isArray(e)}get _subType(){return this.innerType}_cast(e,t){let n=super._cast(e,t);if(!this._typeCheck(n)||!this.innerType)return n;let r=!1,i=n.map((e,n)=>{let i=this.innerType.cast(e,by({},t,{path:`${t.path||""}[${n}]`}));return i!==e&&(r=!0),i});return r?i:n}_validate(e,t={},n){var r,i;let a=[],o=t.sync,s=t.path,u=this.innerType,c=null!=(r=t.abortEarly)?r:this.spec.abortEarly,l=null!=(i=t.recursive)?i:this.spec.recursive,f=null!=t.originalValue?t.originalValue:e;super._validate(e,t,(e,r)=>{if(e){if(!pT.isError(e)||c)return void n(e,r);a.push(e)}if(!l||!u||!this._typeCheck(r)){n(a[0]||null,r);return}f=f||r;let i=Array(r.length);for(let d=0;du.validate(h,b,t)}pO({sync:o,path:s,value:r,errors:a,endEarly:c,tests:i},n)})}clone(e){let t=super.clone(e);return t.innerType=this.innerType,t}concat(e){let t=super.concat(e);return t.innerType=this.innerType,e.innerType&&(t.innerType=t.innerType?t.innerType.concat(e.innerType):e.innerType),t}of(e){let t=this.clone();if(!pw(e))throw TypeError("`array.of()` sub-schema must be a valid yup schema not: "+pl(e));return t.innerType=e,t}length(e,t=pg.length){return this.test({message:t,name:"length",exclusive:!0,params:{length:e},test(t){return pK(t)||t.length===this.resolve(e)}})}min(e,t){return t=t||pg.min,this.test({message:t,name:"min",exclusive:!0,params:{min:e},test(t){return pK(t)||t.length>=this.resolve(e)}})}max(e,t){return t=t||pg.max,this.test({message:t,name:"max",exclusive:!0,params:{max:e},test(t){return pK(t)||t.length<=this.resolve(e)}})}ensure(){return this.default(()=>[]).transform((e,t)=>this._typeCheck(e)?e:null==t?[]:[].concat(t))}compact(e){let t=e?(t,n,r)=>!e(t,n,r):e=>!!e;return this.transform(e=>null!=e?e.filter(t):e)}describe(){let e=super.describe();return this.innerType&&(e.innerType=this.innerType.describe()),e}nullable(e=!0){return super.nullable(e)}defined(){return super.defined()}required(e){return super.required(e)}}bw.prototype=b_.prototype;var bE=bv().shape({name:p0().required("Required"),url:p0().required("Required")}),bS=function(e){var t=e.initialValues,n=e.onSubmit,r=e.submitButtonText,i=e.nameDisabled,a=void 0!==i&&i;return l.createElement(hT,{initialValues:t,validationSchema:bE,onSubmit:n},function(e){var t=e.isSubmitting;return l.createElement(l.Fragment,null,l.createElement(hR,{"data-testid":"bridge-form",noValidate:!0},l.createElement(d.Z,{container:!0,spacing:16},l.createElement(d.Z,{item:!0,xs:12,md:7},l.createElement(hP,{component:hX,id:"name",name:"name",label:"Name",disabled:a,required:!0,fullWidth:!0,FormHelperTextProps:{"data-testid":"name-helper-text"}})),l.createElement(d.Z,{item:!0,xs:12,md:7},l.createElement(hP,{component:hX,id:"url",name:"url",label:"Bridge URL",placeholder:"https://",required:!0,fullWidth:!0,FormHelperTextProps:{"data-testid":"url-helper-text"}})),l.createElement(d.Z,{item:!0,xs:12,md:7},l.createElement(d.Z,{container:!0,spacing:16},l.createElement(d.Z,{item:!0,xs:7},l.createElement(hP,{component:hX,id:"minimumContractPayment",name:"minimumContractPayment",label:"Minimum Contract Payment",placeholder:"0",fullWidth:!0,inputProps:{min:0},FormHelperTextProps:{"data-testid":"minimumContractPayment-helper-text"}})),l.createElement(d.Z,{item:!0,xs:7},l.createElement(hP,{component:hX,id:"confirmations",name:"confirmations",label:"Confirmations",placeholder:"0",type:"number",fullWidth:!0,inputProps:{min:0},FormHelperTextProps:{"data-testid":"confirmations-helper-text"}})))),l.createElement(d.Z,{item:!0,xs:12,md:7},l.createElement(ok.default,{variant:"contained",color:"primary",type:"submit",disabled:t,size:"large"},r)))))})},bk=function(e){var t=e.bridge,n=e.onSubmit,r={name:t.name,url:t.url,minimumContractPayment:t.minimumContractPayment,confirmations:t.confirmations};return l.createElement(ig,null,l.createElement(d.Z,{container:!0,spacing:40},l.createElement(d.Z,{item:!0,xs:12,md:11,lg:9},l.createElement(r5.Z,null,l.createElement(sl.Z,{title:"Edit Bridge",action:l.createElement(aA.Z,{component:tz,href:"/bridges/".concat(t.id)},"Cancel")}),l.createElement(aW.Z,null,l.createElement(bS,{nameDisabled:!0,initialValues:r,onSubmit:n,submitButtonText:"Save Bridge"}))))))};function bx(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]e.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]e.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&void 0!==arguments[0]&&arguments[0],t=e?function(){return l.createElement(x.default,{variant:"body1"},"Loading...")}:function(){return null};return{isLoading:e,LoadingPlaceholder:t}},mc=n(76023);function ml(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]e.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]=0)&&Object.prototype.propertyIsEnumerable.call(e,n)&&(i[n]=e[n])}return i}function mB(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n=4?[e[0],e[1],e[2],e[3],"".concat(e[0],".").concat(e[1]),"".concat(e[0],".").concat(e[2]),"".concat(e[0],".").concat(e[3]),"".concat(e[1],".").concat(e[0]),"".concat(e[1],".").concat(e[2]),"".concat(e[1],".").concat(e[3]),"".concat(e[2],".").concat(e[0]),"".concat(e[2],".").concat(e[1]),"".concat(e[2],".").concat(e[3]),"".concat(e[3],".").concat(e[0]),"".concat(e[3],".").concat(e[1]),"".concat(e[3],".").concat(e[2]),"".concat(e[0],".").concat(e[1],".").concat(e[2]),"".concat(e[0],".").concat(e[1],".").concat(e[3]),"".concat(e[0],".").concat(e[2],".").concat(e[1]),"".concat(e[0],".").concat(e[2],".").concat(e[3]),"".concat(e[0],".").concat(e[3],".").concat(e[1]),"".concat(e[0],".").concat(e[3],".").concat(e[2]),"".concat(e[1],".").concat(e[0],".").concat(e[2]),"".concat(e[1],".").concat(e[0],".").concat(e[3]),"".concat(e[1],".").concat(e[2],".").concat(e[0]),"".concat(e[1],".").concat(e[2],".").concat(e[3]),"".concat(e[1],".").concat(e[3],".").concat(e[0]),"".concat(e[1],".").concat(e[3],".").concat(e[2]),"".concat(e[2],".").concat(e[0],".").concat(e[1]),"".concat(e[2],".").concat(e[0],".").concat(e[3]),"".concat(e[2],".").concat(e[1],".").concat(e[0]),"".concat(e[2],".").concat(e[1],".").concat(e[3]),"".concat(e[2],".").concat(e[3],".").concat(e[0]),"".concat(e[2],".").concat(e[3],".").concat(e[1]),"".concat(e[3],".").concat(e[0],".").concat(e[1]),"".concat(e[3],".").concat(e[0],".").concat(e[2]),"".concat(e[3],".").concat(e[1],".").concat(e[0]),"".concat(e[3],".").concat(e[1],".").concat(e[2]),"".concat(e[3],".").concat(e[2],".").concat(e[0]),"".concat(e[3],".").concat(e[2],".").concat(e[1]),"".concat(e[0],".").concat(e[1],".").concat(e[2],".").concat(e[3]),"".concat(e[0],".").concat(e[1],".").concat(e[3],".").concat(e[2]),"".concat(e[0],".").concat(e[2],".").concat(e[1],".").concat(e[3]),"".concat(e[0],".").concat(e[2],".").concat(e[3],".").concat(e[1]),"".concat(e[0],".").concat(e[3],".").concat(e[1],".").concat(e[2]),"".concat(e[0],".").concat(e[3],".").concat(e[2],".").concat(e[1]),"".concat(e[1],".").concat(e[0],".").concat(e[2],".").concat(e[3]),"".concat(e[1],".").concat(e[0],".").concat(e[3],".").concat(e[2]),"".concat(e[1],".").concat(e[2],".").concat(e[0],".").concat(e[3]),"".concat(e[1],".").concat(e[2],".").concat(e[3],".").concat(e[0]),"".concat(e[1],".").concat(e[3],".").concat(e[0],".").concat(e[2]),"".concat(e[1],".").concat(e[3],".").concat(e[2],".").concat(e[0]),"".concat(e[2],".").concat(e[0],".").concat(e[1],".").concat(e[3]),"".concat(e[2],".").concat(e[0],".").concat(e[3],".").concat(e[1]),"".concat(e[2],".").concat(e[1],".").concat(e[0],".").concat(e[3]),"".concat(e[2],".").concat(e[1],".").concat(e[3],".").concat(e[0]),"".concat(e[2],".").concat(e[3],".").concat(e[0],".").concat(e[1]),"".concat(e[2],".").concat(e[3],".").concat(e[1],".").concat(e[0]),"".concat(e[3],".").concat(e[0],".").concat(e[1],".").concat(e[2]),"".concat(e[3],".").concat(e[0],".").concat(e[2],".").concat(e[1]),"".concat(e[3],".").concat(e[1],".").concat(e[0],".").concat(e[2]),"".concat(e[3],".").concat(e[1],".").concat(e[2],".").concat(e[0]),"".concat(e[3],".").concat(e[2],".").concat(e[0],".").concat(e[1]),"".concat(e[3],".").concat(e[2],".").concat(e[1],".").concat(e[0])]:void 0}var mZ={};function mX(e){if(0===e.length||1===e.length)return e;var t=e.join(".");return mZ[t]||(mZ[t]=mq(e)),mZ[t]}function mJ(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},n=arguments.length>2?arguments[2]:void 0;return mX(e.filter(function(e){return"token"!==e})).reduce(function(e,t){return mK({},e,n[t])},t)}function mQ(e){return e.join(" ")}function m1(e,t){var n=0;return function(r){return n+=1,r.map(function(r,i){return m0({node:r,stylesheet:e,useInlineStyles:t,key:"code-segment-".concat(n,"-").concat(i)})})}}function m0(e){var t=e.node,n=e.stylesheet,r=e.style,i=void 0===r?{}:r,a=e.useInlineStyles,o=e.key,s=t.properties,u=t.type,c=t.tagName,f=t.value;if("text"===u)return f;if(c){var d,h=m1(n,a);if(a){var p=Object.keys(n).reduce(function(e,t){return t.split(".").forEach(function(t){e.includes(t)||e.push(t)}),e},[]),b=s.className&&s.className.includes("token")?["token"]:[],m=s.className&&b.concat(s.className.filter(function(e){return!p.includes(e)}));d=mK({},s,{className:mQ(m)||void 0,style:mJ(s.className,Object.assign({},s.style,i),n)})}else d=mK({},s,{className:mQ(s.className)});var g=h(t.children);return l.createElement(c,(0,mV.Z)({key:o},d),g)}}let m2=function(e,t){return -1!==e.listLanguages().indexOf(t)};var m3=/\n/g;function m4(e){return e.match(m3)}function m6(e){var t=e.lines,n=e.startingLineNumber,r=e.style;return t.map(function(e,t){var i=t+n;return l.createElement("span",{key:"line-".concat(t),className:"react-syntax-highlighter-line-number",style:"function"==typeof r?r(i):r},"".concat(i,"\n"))})}function m5(e){var t=e.codeString,n=e.codeStyle,r=e.containerStyle,i=void 0===r?{float:"left",paddingRight:"10px"}:r,a=e.numberStyle,o=void 0===a?{}:a,s=e.startingLineNumber;return l.createElement("code",{style:Object.assign({},n,i)},m6({lines:t.replace(/\n$/,"").split("\n"),style:o,startingLineNumber:s}))}function m8(e){return"".concat(e.toString().length,".25em")}function m9(e,t){return{type:"element",tagName:"span",properties:{key:"line-number--".concat(e),className:["comment","linenumber","react-syntax-highlighter-line-number"],style:t},children:[{type:"text",value:e}]}}function m7(e,t,n){var r,i={display:"inline-block",minWidth:m8(n),paddingRight:"1em",textAlign:"right",userSelect:"none"};return mK({},i,"function"==typeof e?e(t):e)}function ge(e){var t=e.children,n=e.lineNumber,r=e.lineNumberStyle,i=e.largestLineNumber,a=e.showInlineLineNumbers,o=e.lineProps,s=void 0===o?{}:o,u=e.className,c=void 0===u?[]:u,l=e.showLineNumbers,f=e.wrapLongLines,d="function"==typeof s?s(n):s;if(d.className=c,n&&a){var h=m7(r,n,i);t.unshift(m9(n,h))}return f&l&&(d.style=mK({},d.style,{display:"flex"})),{type:"element",tagName:"span",properties:d,children:t}}function gt(e){for(var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:[],n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:[],r=0;r2&&void 0!==arguments[2]?arguments[2]:[];return ge({children:e,lineNumber:t,lineNumberStyle:s,largestLineNumber:o,showInlineLineNumbers:i,lineProps:n,className:a,showLineNumbers:r,wrapLongLines:u})}function b(e,t){if(r&&t&&i){var n=m7(s,t,o);e.unshift(m9(t,n))}return e}function m(e,n){var r=arguments.length>2&&void 0!==arguments[2]?arguments[2]:[];return t||r.length>0?p(e,n,r):b(e,n)}for(var g=function(){var e=l[h],t=e.children[0].value;if(m4(t)){var n=t.split("\n");n.forEach(function(t,i){var o=r&&f.length+a,s={type:"text",value:"".concat(t,"\n")};if(0===i){var u=l.slice(d+1,h).concat(ge({children:[s],className:e.properties.className})),c=m(u,o);f.push(c)}else if(i===n.length-1){if(l[h+1]&&l[h+1].children&&l[h+1].children[0]){var p={type:"text",value:"".concat(t)},b=ge({children:[p],className:e.properties.className});l.splice(h+1,0,b)}else{var g=[s],v=m(g,o,e.properties.className);f.push(v)}}else{var y=[s],w=m(y,o,e.properties.className);f.push(w)}}),d=h}h++};h code[class*="language-"]':{background:"#f5f2f0",padding:".1em",borderRadius:".3em",whiteSpace:"normal"},comment:{color:"slategray"},prolog:{color:"slategray"},doctype:{color:"slategray"},cdata:{color:"slategray"},punctuation:{color:"#999"},namespace:{Opacity:".7"},property:{color:"#905"},tag:{color:"#905"},boolean:{color:"#905"},number:{color:"#905"},constant:{color:"#905"},symbol:{color:"#905"},deleted:{color:"#905"},selector:{color:"#690"},"attr-name":{color:"#690"},string:{color:"#690"},char:{color:"#690"},builtin:{color:"#690"},inserted:{color:"#690"},operator:{color:"#9a6e3a",background:"hsla(0, 0%, 100%, .5)"},entity:{color:"#9a6e3a",background:"hsla(0, 0%, 100%, .5)",cursor:"help"},url:{color:"#9a6e3a",background:"hsla(0, 0%, 100%, .5)"},".language-css .token.string":{color:"#9a6e3a",background:"hsla(0, 0%, 100%, .5)"},".style .token.string":{color:"#9a6e3a",background:"hsla(0, 0%, 100%, .5)"},atrule:{color:"#07a"},"attr-value":{color:"#07a"},keyword:{color:"#07a"},function:{color:"#DD4A68"},"class-name":{color:"#DD4A68"},regex:{color:"#e90"},important:{color:"#e90",fontWeight:"bold"},variable:{color:"#e90"},bold:{fontWeight:"bold"},italic:{fontStyle:"italic"}};var gu=n(98695),gc=n.n(gu);let gl=["abap","abnf","actionscript","ada","agda","al","antlr4","apacheconf","apl","applescript","aql","arduino","arff","asciidoc","asm6502","aspnet","autohotkey","autoit","bash","basic","batch","bbcode","birb","bison","bnf","brainfuck","brightscript","bro","bsl","c","cil","clike","clojure","cmake","coffeescript","concurnas","cpp","crystal","csharp","csp","css-extras","css","cypher","d","dart","dax","dhall","diff","django","dns-zone-file","docker","ebnf","editorconfig","eiffel","ejs","elixir","elm","erb","erlang","etlua","excel-formula","factor","firestore-security-rules","flow","fortran","fsharp","ftl","gcode","gdscript","gedcom","gherkin","git","glsl","gml","go","graphql","groovy","haml","handlebars","haskell","haxe","hcl","hlsl","hpkp","hsts","http","ichigojam","icon","iecst","ignore","inform7","ini","io","j","java","javadoc","javadoclike","javascript","javastacktrace","jolie","jq","js-extras","js-templates","jsdoc","json","json5","jsonp","jsstacktrace","jsx","julia","keyman","kotlin","latex","latte","less","lilypond","liquid","lisp","livescript","llvm","lolcode","lua","makefile","markdown","markup-templating","markup","matlab","mel","mizar","mongodb","monkey","moonscript","n1ql","n4js","nand2tetris-hdl","naniscript","nasm","neon","nginx","nim","nix","nsis","objectivec","ocaml","opencl","oz","parigp","parser","pascal","pascaligo","pcaxis","peoplecode","perl","php-extras","php","phpdoc","plsql","powerquery","powershell","processing","prolog","properties","protobuf","pug","puppet","pure","purebasic","purescript","python","q","qml","qore","r","racket","reason","regex","renpy","rest","rip","roboconf","robotframework","ruby","rust","sas","sass","scala","scheme","scss","shell-session","smali","smalltalk","smarty","sml","solidity","solution-file","soy","sparql","splunk-spl","sqf","sql","stan","stylus","swift","t4-cs","t4-templating","t4-vb","tap","tcl","textile","toml","tsx","tt2","turtle","twig","typescript","typoscript","unrealscript","vala","vbnet","velocity","verilog","vhdl","vim","visual-basic","warpscript","wasm","wiki","xeora","xml-doc","xojo","xquery","yaml","yang","zig"];var gf=go(gc(),gs);gf.supportedLanguages=gl;let gd=gf;var gh=n(64566);function gp(e,t){return t||(t=e.slice(0)),Object.freeze(Object.defineProperties(e,{raw:{value:Object.freeze(t)}}))}function gb(){var e=gp(["\n query FetchConfigV2 {\n configv2 {\n user\n effective\n }\n }\n"]);return gb=function(){return e},e}var gm=n0(gb()),gg=function(e){var t=e.children;return l.createElement(ir.Z,null,l.createElement(r7.default,{component:"th",scope:"row",colSpan:3},t))},gv=function(){return l.createElement(gg,null,"...")},gy=function(e){var t=e.children;return l.createElement(gg,null,t)},gw=function(e){var t=e.loading,n=e.toml,r=e.error,i=void 0===r?"":r,a=e.title,o=e.expanded;if(i)return l.createElement(gy,null,i);if(t)return l.createElement(gv,null);a||(a="TOML");var s={display:"block"};return l.createElement(x.default,null,l.createElement(mP.Z,{defaultExpanded:o},l.createElement(mR.Z,{expandIcon:l.createElement(gh.Z,null)},a),l.createElement(mj.Z,{style:s},l.createElement(gd,{language:"toml",style:gs},n))))},g_=function(){var e=rv(gm,{fetchPolicy:"cache-and-network"}),t=e.data,n=e.loading,r=e.error;return(null==t?void 0:t.configv2.effective)=="N/A"?l.createElement(l.Fragment,null,l.createElement(d.Z,{item:!0,xs:12},l.createElement(r5.Z,null,l.createElement(sl.Z,{title:"TOML Configuration"}),l.createElement(gw,{title:"V2 config dump:",error:null==r?void 0:r.message,loading:n,toml:null==t?void 0:t.configv2.user,showHead:!0})))):l.createElement(l.Fragment,null,l.createElement(d.Z,{container:!0},l.createElement(d.Z,{item:!0,xs:12},l.createElement(r5.Z,null,l.createElement(sl.Z,{title:"TOML Configuration"}),l.createElement(gw,{title:"User specified:",error:null==r?void 0:r.message,loading:n,toml:null==t?void 0:t.configv2.user,showHead:!0,expanded:!0}),l.createElement(gw,{title:"Effective (with defaults):",error:null==r?void 0:r.message,loading:n,toml:null==t?void 0:t.configv2.effective,showHead:!0})))))},gE=n(34823),gS=function(e){return(0,b.createStyles)({cell:{paddingTop:1.5*e.spacing.unit,paddingBottom:1.5*e.spacing.unit}})},gk=(0,b.withStyles)(gS)(function(e){var t=e.classes,n=(0,A.I0)();(0,l.useEffect)(function(){n((0,ty.DQ)())});var r=(0,A.v9)(gE.N,A.wU);return l.createElement(r5.Z,null,l.createElement(sl.Z,{title:"Node"}),l.createElement(r8.Z,null,l.createElement(r9.Z,null,l.createElement(ir.Z,null,l.createElement(r7.default,{className:t.cell},l.createElement(x.default,null,"Version"),l.createElement(x.default,{variant:"subtitle1",color:"textSecondary"},r.version))),l.createElement(ir.Z,null,l.createElement(r7.default,{className:t.cell},l.createElement(x.default,null,"SHA"),l.createElement(x.default,{variant:"subtitle1",color:"textSecondary"},r.commitSHA))))))}),gx=function(){return l.createElement(ig,null,l.createElement(d.Z,{container:!0},l.createElement(d.Z,{item:!0,sm:12,md:8},l.createElement(d.Z,{container:!0},l.createElement(g_,null))),l.createElement(d.Z,{item:!0,sm:12,md:4},l.createElement(d.Z,{container:!0},l.createElement(d.Z,{item:!0,xs:12},l.createElement(gk,null)),l.createElement(d.Z,{item:!0,xs:12},l.createElement(mN,null)),l.createElement(d.Z,{item:!0,xs:12},l.createElement(mE,null))))))},gT=function(){return l.createElement(gx,null)},gM=function(){return l.createElement(gT,null)},gO=n(44431),gA=1e18,gL=function(e){return new gO.BigNumber(e).dividedBy(gA).toFixed(8)},gC=function(e){var t=e.keys,n=e.chainID,r=e.hideHeaderTitle;return l.createElement(l.Fragment,null,l.createElement(sl.Z,{title:!r&&"Account Balances",subheader:"Chain ID "+n}),l.createElement(aW.Z,null,l.createElement(w.default,{dense:!1,disablePadding:!0},t&&t.map(function(e,r){return l.createElement(l.Fragment,null,l.createElement(_.default,{disableGutters:!0,key:["acc-balance",n.toString(),r.toString()].join("-")},l.createElement(E.Z,{primary:l.createElement(l.Fragment,null,l.createElement(d.Z,{container:!0,spacing:16},l.createElement(d.Z,{item:!0,xs:12},l.createElement(op,{title:"Address"}),l.createElement(ob,{value:e.address})),l.createElement(d.Z,{item:!0,xs:6},l.createElement(op,{title:"Native Token Balance"}),l.createElement(ob,{value:e.ethBalance||"--"})),l.createElement(d.Z,{item:!0,xs:6},l.createElement(op,{title:"LINK Balance"}),l.createElement(ob,{value:e.linkBalance?gL(e.linkBalance):"--"}))))})),r+1s&&l.createElement(gB.Z,null,l.createElement(ir.Z,null,l.createElement(r7.default,{className:r.footer},l.createElement(aA.Z,{href:"/runs",component:tz},"View More"))))))});function vt(e,t){return t||(t=e.slice(0)),Object.freeze(Object.defineProperties(e,{raw:{value:Object.freeze(t)}}))}function vn(){var e=vt(["\n ","\n query FetchRecentJobRuns($offset: Int, $limit: Int) {\n jobRuns(offset: $offset, limit: $limit) {\n results {\n ...RecentJobRunsPayload_ResultsFields\n }\n metadata {\n total\n }\n }\n }\n"]);return vn=function(){return e},e}var vr=5,vi=n0(vn(),g9),va=function(){var e=rv(vi,{variables:{offset:0,limit:vr},fetchPolicy:"cache-and-network"}),t=e.data,n=e.loading,r=e.error;return l.createElement(ve,{data:t,errorMsg:null==r?void 0:r.message,loading:n,maxRunsSize:vr})},vo=function(e){return(0,b.createStyles)({style:{textAlign:"center",padding:2.5*e.spacing.unit,position:"fixed",left:"0",bottom:"0",width:"100%",borderRadius:0},bareAnchor:{color:e.palette.common.black,textDecoration:"none"}})},vs=(0,b.withStyles)(vo)(function(e){var t=e.classes,n=(0,A.v9)(gE.N,A.wU),r=(0,A.I0)();return(0,l.useEffect)(function(){r((0,ty.DQ)())}),l.createElement(ii.default,{className:t.style},l.createElement(x.default,null,"Chainlink Node ",n.version," at commit"," ",l.createElement("a",{target:"_blank",rel:"noopener noreferrer",href:"https://github.com/smartcontractkit/chainlink/commit/".concat(n.commitSHA),className:t.bareAnchor},n.commitSHA)))}),vu=function(e){return(0,b.createStyles)({cell:{borderColor:e.palette.divider,borderTop:"1px solid",borderBottom:"none",paddingTop:2*e.spacing.unit,paddingBottom:2*e.spacing.unit,paddingLeft:2*e.spacing.unit},block:{display:"block"},overflowEllipsis:{textOverflow:"ellipsis",overflow:"hidden"}})},vc=(0,b.withStyles)(vu)(function(e){var t=e.classes,n=e.job;return l.createElement(ir.Z,null,l.createElement(r7.default,{scope:"row",className:t.cell},l.createElement(d.Z,{container:!0,spacing:0},l.createElement(d.Z,{item:!0,xs:12},l.createElement(ih,{href:"/jobs/".concat(n.id),classes:{linkContent:t.block}},l.createElement(x.default,{className:t.overflowEllipsis,variant:"body1",component:"span",color:"primary"},n.name||n.id))),l.createElement(d.Z,{item:!0,xs:12},l.createElement(x.default,{variant:"body1",color:"textSecondary"},"Created ",l.createElement(aO,{tooltip:!0},n.createdAt))))))});function vl(e,t){return t||(t=e.slice(0)),Object.freeze(Object.defineProperties(e,{raw:{value:Object.freeze(t)}}))}function vf(){var e=vl(["\n fragment RecentJobsPayload_ResultsFields on Job {\n id\n name\n createdAt\n }\n"]);return vf=function(){return e},e}var vd=n0(vf()),vh=function(){return(0,b.createStyles)({cardHeader:{borderBottom:0},table:{tableLayout:"fixed"}})},vp=(0,b.withStyles)(vh)(function(e){var t,n,r=e.classes,i=e.data,a=e.errorMsg,o=e.loading;return l.createElement(r5.Z,null,l.createElement(sl.Z,{title:"Recent Jobs",className:r.cardHeader}),l.createElement(r8.Z,{className:r.table},l.createElement(r9.Z,null,l.createElement(g$,{visible:o}),l.createElement(gz,{visible:(null===(t=null==i?void 0:i.jobs.results)||void 0===t?void 0:t.length)===0},"No recently created jobs"),l.createElement(gU,{msg:a}),null===(n=null==i?void 0:i.jobs.results)||void 0===n?void 0:n.map(function(e,t){return l.createElement(vc,{job:e,key:t})}))))});function vb(e,t){return t||(t=e.slice(0)),Object.freeze(Object.defineProperties(e,{raw:{value:Object.freeze(t)}}))}function vm(){var e=vb(["\n ","\n query FetchRecentJobs($offset: Int, $limit: Int) {\n jobs(offset: $offset, limit: $limit) {\n results {\n ...RecentJobsPayload_ResultsFields\n }\n }\n }\n"]);return vm=function(){return e},e}var vg=5,vv=n0(vm(),vd),vy=function(){var e=rv(vv,{variables:{offset:0,limit:vg},fetchPolicy:"cache-and-network"}),t=e.data,n=e.loading,r=e.error;return l.createElement(vp,{data:t,errorMsg:null==r?void 0:r.message,loading:n})},vw=function(){return l.createElement(ig,null,l.createElement(d.Z,{container:!0},l.createElement(d.Z,{item:!0,xs:8},l.createElement(va,null)),l.createElement(d.Z,{item:!0,xs:4},l.createElement(d.Z,{container:!0},l.createElement(d.Z,{item:!0,xs:12},l.createElement(gY,null)),l.createElement(d.Z,{item:!0,xs:12},l.createElement(vy,null))))),l.createElement(vs,null))},v_=function(){return l.createElement(vw,null)},vE=function(){return l.createElement(v_,null)},vS=n(87239),vk=function(e){switch(e){case"DirectRequestSpec":return"Direct Request";case"FluxMonitorSpec":return"Flux Monitor";default:return e.replace(/Spec$/,"")}},vx=n(5022),vT=n(78718),vM=n.n(vT);function vO(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n1?t-1:0),r=1;r1?t-1:0),r=1;re.length)&&(t=e.length);for(var n=0,r=Array(t);ne.length)&&(t=e.length);for(var n=0,r=Array(t);ne.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&n.map(function(e){return l.createElement(ir.Z,{key:e.id,style:{cursor:"pointer"},onClick:function(){return r.push("/runs/".concat(e.id))}},l.createElement(r7.default,{className:t.idCell,scope:"row"},l.createElement("div",{className:t.runDetails},l.createElement(x.default,{variant:"h5",color:"primary",component:"span"},e.id))),l.createElement(r7.default,{className:t.stampCell},l.createElement(x.default,{variant:"body1",color:"textSecondary",className:t.stamp},"Created ",l.createElement(aO,{tooltip:!0},e.createdAt))),l.createElement(r7.default,{className:t.statusCell,scope:"row"},l.createElement(x.default,{variant:"body1",className:O()(t.status,yh(t,e.status))},e.status.toLowerCase())))})))}),yb=n(16839),ym=n.n(yb);function yg(e){var t=e.replace(/\w+\s*=\s*<([^>]|[\r\n])*>/g,""),n=ym().read(t),r=n.edges();return n.nodes().map(function(e){var t={id:e,parentIds:r.filter(function(t){return t.w===e}).map(function(e){return e.v})};return Object.keys(n.node(e)).length>0&&(t.attributes=n.node(e)),t})}var yv=n(94164),yy=function(e){var t=e.data,n=[];return(null==t?void 0:t.attributes)&&Object.keys(t.attributes).forEach(function(e){var r;n.push(l.createElement("div",{key:e},l.createElement(x.default,{variant:"body1",color:"textSecondary",component:"div"},l.createElement("b",null,e,":")," ",null===(r=t.attributes)||void 0===r?void 0:r[e])))}),l.createElement("div",null,t&&l.createElement(x.default,{variant:"body1",color:"textPrimary"},l.createElement("b",null,t.id)),n)},yw=n(73343),y_=n(3379),yE=n.n(y_);function yS(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);nwindow.innerWidth?u-r.getBoundingClientRect().width-a:u+a,n=c+r.getBoundingClientRect().height+i>window.innerHeight?c-r.getBoundingClientRect().height-a:c+a,r.style.opacity=String(1),r.style.top="".concat(n,"px"),r.style.left="".concat(t,"px"),r.style.zIndex=String(1)}},h=function(e){var t=document.getElementById("tooltip-d3-chart-".concat(e));t&&(t.style.opacity=String(0),t.style.zIndex=String(-1))};return l.createElement("div",{style:{fontFamily:"sans-serif",fontWeight:"normal"}},l.createElement(yv.kJ,{id:"task-list-graph-d3",data:i,config:s,onMouseOverNode:d,onMouseOutNode:h},"D3 chart"),n.map(function(e){return l.createElement("div",{key:"d3-tooltip-key-".concat(e.id),id:"tooltip-d3-chart-".concat(e.id),style:{position:"absolute",opacity:"0",border:"1px solid rgba(0, 0, 0, 0.1)",padding:yw.r.spacing.unit,background:"white",borderRadius:5,zIndex:-1,inlineSize:"min-content"}},l.createElement(yy,{data:e}))}))};function yL(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);nyY&&l.createElement("div",{className:t.runDetails},l.createElement(aA.Z,{href:"/jobs/".concat(n.id,"/runs"),component:tz},"View more")))),l.createElement(d.Z,{item:!0,xs:12,sm:6},l.createElement(yF,{observationSource:n.observationSource})))});function yH(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);ne.length)&&(t=e.length);for(var n=0,r=Array(t);ne.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]e.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&void 0!==arguments[0]?arguments[0]:"";try{return vx.parse(e),!0}catch(t){return!1}})}),wW=function(e){var t=e.initialValues,n=e.onSubmit,r=e.onTOMLChange;return l.createElement(hT,{initialValues:t,validationSchema:wG,onSubmit:n},function(e){var t=e.isSubmitting,n=e.values;return r&&r(n.toml),l.createElement(hR,{"data-testid":"job-form",noValidate:!0},l.createElement(d.Z,{container:!0,spacing:16},l.createElement(d.Z,{item:!0,xs:12},l.createElement(hP,{component:hX,id:"toml",name:"toml",label:"Job Spec (TOML)",required:!0,fullWidth:!0,multiline:!0,rows:10,rowsMax:25,variant:"outlined",autoComplete:"off",FormHelperTextProps:{"data-testid":"toml-helper-text"}})),l.createElement(d.Z,{item:!0,xs:12,md:7},l.createElement(ok.default,{variant:"contained",color:"primary",type:"submit",disabled:t,size:"large"},"Create Job"))))})},wK=n(50109),wV="persistSpec";function wq(e){var t=e.query,n=new URLSearchParams(t).get("definition");return n?(wK.t8(wV,n),{toml:n}):{toml:wK.U2(wV)||""}}var wZ=function(e){var t=e.onSubmit,n=e.onTOMLChange,r=wq({query:(0,h.TH)().search}),i=function(e){var t=e.replace(/[\u200B-\u200D\uFEFF]/g,"");wK.t8("".concat(wV),t),n&&n(t)};return l.createElement(r5.Z,null,l.createElement(sl.Z,{title:"New Job"}),l.createElement(aW.Z,null,l.createElement(wW,{initialValues:r,onSubmit:t,onTOMLChange:i})))};function wX(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);ne.length)&&(t=e.length);for(var n=0,r=Array(t);ne.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]e.length)&&(t=e.length);for(var n=0,r=Array(t);n1&&void 0!==arguments[1]?arguments[1]:{},n=t.start,r=void 0===n?6:n,i=t.end,a=void 0===i?4:i;return e.substring(0,r)+"..."+e.substring(e.length-a)}function _M(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]0&&void 0!==arguments[0]?arguments[0]:{};return rv(_W,e)},_V=function(){var e=_K({fetchPolicy:"cache-and-network"}),t=e.data,n=e.loading,r=e.error,i=e.refetch;return l.createElement(_U,{loading:n,data:t,errorMsg:null==r?void 0:r.message,refetch:i})},_q=function(e){var t=e.csaKey;return l.createElement(ir.Z,{hover:!0},l.createElement(r7.default,null,l.createElement(x.default,{variant:"body1"},t.publicKey," ",l.createElement(_x,{data:t.publicKey}))))};function _Z(e,t){return t||(t=e.slice(0)),Object.freeze(Object.defineProperties(e,{raw:{value:Object.freeze(t)}}))}function _X(){var e=_Z(["\n fragment CSAKeysPayload_ResultsFields on CSAKey {\n id\n publicKey\n }\n"]);return _X=function(){return e},e}var _J=n0(_X()),_Q=function(e){var t,n,r,i=e.data,a=e.errorMsg,o=e.loading,s=e.onCreate;return l.createElement(r5.Z,null,l.createElement(sl.Z,{action:(null===(t=null==i?void 0:i.csaKeys.results)||void 0===t?void 0:t.length)===0&&l.createElement(ok.default,{variant:"outlined",color:"primary",onClick:s},"New CSA Key"),title:"CSA Key",subheader:"Manage your CSA Key"}),l.createElement(r8.Z,null,l.createElement(ie.Z,null,l.createElement(ir.Z,null,l.createElement(r7.default,null,"Public Key"))),l.createElement(r9.Z,null,l.createElement(g$,{visible:o}),l.createElement(gz,{visible:(null===(n=null==i?void 0:i.csaKeys.results)||void 0===n?void 0:n.length)===0}),l.createElement(gU,{msg:a}),null===(r=null==i?void 0:i.csaKeys.results)||void 0===r?void 0:r.map(function(e,t){return l.createElement(_q,{csaKey:e,key:t})}))))};function _1(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]e.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]0&&void 0!==arguments[0]?arguments[0]:{};return rv(EM,e)};function EA(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]0&&void 0!==arguments[0]?arguments[0]:{};return rv(EJ,e)},E3=function(){return oo(EQ)},E4=function(){return oo(E1)},E6=function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};return rv(E0,e)};function E5(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);ne.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]e.length)&&(t=e.length);for(var n=0,r=Array(t);ne.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]e.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]0&&void 0!==arguments[0]?arguments[0]:{};return rv(SK,e)};function Sq(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]e.length)&&(t=e.length);for(var n=0,r=Array(t);n=0)&&Object.prototype.propertyIsEnumerable.call(e,n)&&(i[n]=e[n])}return i}function kV(e,t){if(null==e)return{};var n,r,i={},a=Object.keys(e);for(r=0;r=0||(i[n]=e[n]);return i}var kq=function(e){var t=e.run,n=l.useMemo(function(){var e=t.inputs,n=t.outputs,r=t.taskRuns,i=kK(t,["inputs","outputs","taskRuns"]),a={};try{a=JSON.parse(e)}catch(o){a={}}return kW(kz({},i),{inputs:a,outputs:n,taskRuns:r})},[t]);return l.createElement(r5.Z,null,l.createElement(aW.Z,null,l.createElement(kH,{object:n})))};function kZ(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function kX(e){for(var t=1;t0&&l.createElement(kr,{errors:t.allErrors})),l.createElement(d.Z,{item:!0,xs:12},l.createElement(h.rs,null,l.createElement(h.AW,{path:"".concat(n,"/json")},l.createElement(kq,{run:t})),l.createElement(h.AW,{path:n},t.taskRuns.length>0&&l.createElement(kN,{taskRuns:t.taskRuns,observationSource:t.job.observationSource}))))))))};function k5(e,t){return t||(t=e.slice(0)),Object.freeze(Object.defineProperties(e,{raw:{value:Object.freeze(t)}}))}function k8(){var e=k5(["\n ","\n query FetchJobRun($id: ID!) {\n jobRun(id: $id) {\n __typename\n ... on JobRun {\n ...JobRunPayload_Fields\n }\n ... on NotFoundError {\n message\n }\n }\n }\n"]);return k8=function(){return e},e}var k9=n0(k8(),k4),k7=function(){var e=rv(k9,{variables:{id:(0,h.UO)().id}}),t=e.data,n=e.loading,r=e.error;if(n)return l.createElement(iR,null);if(r)return l.createElement(iD,{error:r});var i=null==t?void 0:t.jobRun;switch(null==i?void 0:i.__typename){case"JobRun":return l.createElement(k6,{run:i});case"NotFoundError":return l.createElement(oa,null);default:return null}};function xe(e,t){return t||(t=e.slice(0)),Object.freeze(Object.defineProperties(e,{raw:{value:Object.freeze(t)}}))}function xt(){var e=xe(["\n fragment JobRunsPayload_ResultsFields on JobRun {\n id\n allErrors\n createdAt\n finishedAt\n status\n job {\n id\n }\n }\n"]);return xt=function(){return e},e}var xn=n0(xt()),xr=function(e){var t=e.loading,n=e.data,r=e.page,i=e.pageSize,a=(0,h.k6)(),o=l.useMemo(function(){return null==n?void 0:n.jobRuns.results.map(function(e){var t,n=e.allErrors,r=e.id,i=e.createdAt;return{id:r,createdAt:i,errors:n,finishedAt:e.finishedAt,status:e.status}})},[n]);return l.createElement(ig,null,l.createElement(d.Z,{container:!0,spacing:32},l.createElement(d.Z,{item:!0,xs:12},l.createElement(iy,null,"Job Runs")),t&&l.createElement(iR,null),n&&o&&l.createElement(d.Z,{item:!0,xs:12},l.createElement(r5.Z,null,l.createElement(yp,{runs:o}),l.createElement(it.Z,{component:"div",count:n.jobRuns.metadata.total,rowsPerPage:i,rowsPerPageOptions:[i],page:r-1,onChangePage:function(e,t){a.push("/runs?page=".concat(t+1,"&per=").concat(i))},onChangeRowsPerPage:function(){},backIconButtonProps:{"aria-label":"prev-page"},nextIconButtonProps:{"aria-label":"next-page"}})))))};function xi(e,t){return t||(t=e.slice(0)),Object.freeze(Object.defineProperties(e,{raw:{value:Object.freeze(t)}}))}function xa(){var e=xi(["\n ","\n query FetchJobRuns($offset: Int, $limit: Int) {\n jobRuns(offset: $offset, limit: $limit) {\n results {\n ...JobRunsPayload_ResultsFields\n }\n metadata {\n total\n }\n }\n }\n"]);return xa=function(){return e},e}var xo=n0(xa(),xn),xs=function(){var e=ij(),t=parseInt(e.get("page")||"1",10),n=parseInt(e.get("per")||"25",10),r=rv(xo,{variables:{offset:(t-1)*n,limit:n},fetchPolicy:"cache-and-network"}),i=r.data,a=r.loading,o=r.error;return o?l.createElement(iD,{error:o}):l.createElement(xr,{loading:a,data:i,page:t,pageSize:n})},xu=function(){var e=(0,h.$B)().path;return l.createElement(h.rs,null,l.createElement(h.AW,{exact:!0,path:e},l.createElement(xs,null)),l.createElement(h.AW,{path:"".concat(e,"/:id")},l.createElement(k7,null)))};function xc(e,t){return t||(t=e.slice(0)),Object.freeze(Object.defineProperties(e,{raw:{value:Object.freeze(t)}}))}function xl(){var e=xc(["\n fragment FetchFeedsManagersPayload_ResultsFields on FeedsManager {\n __typename\n id\n name\n uri\n publicKey\n isConnectionActive\n createdAt\n disabledAt\n }\n query FetchFeedsManagers {\n feedsManagers {\n results {\n ...FetchFeedsManagersPayload_ResultsFields\n }\n }\n }\n"]);return xl=function(){return e},e}var xf=n0(xl()),xd=function(e){return rv(xf,e)},xh=n(47559),xp=n(83165),xb=n(47298),xm=n(81395),xg=function(){return(0,b.createStyles)({root:{display:"flex"},activeIcon:{color:xh.default[500]},inactiveIcon:{color:xp.default[500]},text:{marginLeft:4}})},xv=(0,b.withStyles)(xg)(function(e){var t=e.isActive,n=e.activeText,r=e.inactiveText,i=e.classes;return l.createElement("div",{className:i.root},t?l.createElement(xm.Z,{fontSize:"small",className:i.activeIcon}):l.createElement(xb.Z,{fontSize:"small",className:i.inactiveIcon}),l.createElement(x.default,{variant:"body1",inline:!0,className:i.text},t?n:r))}),xy=(0,b.withStyles)(iu)(function(e){var t=e.jobDistributor,n=e.classes;return l.createElement(ir.Z,{className:n.row,hover:!0},l.createElement(r7.default,{className:n.cell,component:"th",scope:"row"},l.createElement(ih,{className:n.link,href:"/job_distributors/".concat(t.id)},t.name)),l.createElement(r7.default,null,l.createElement(xv,{isActive:t.isConnectionActive,activeText:"Connected",inactiveText:"Disconnected"})),l.createElement(r7.default,null,l.createElement(xv,{isActive:!t.disabledAt,activeText:"Enabled",inactiveText:"Disabled"})),l.createElement(r7.default,null,_T(t.publicKey,{start:6,end:6}),l.createElement(_x,{data:t.publicKey})),l.createElement(r7.default,null,t.uri))}),xw=function(e){var t=e.jobDistributors;return l.createElement(ig,null,l.createElement(d.Z,{container:!0},l.createElement(d.Z,{item:!0,xs:9},l.createElement(iy,null,"Job Distributors")),l.createElement(d.Z,{item:!0,xs:3},l.createElement(d.Z,{container:!0,justify:"flex-end"},l.createElement(d.Z,{item:!0},l.createElement(aA.Z,{variant:"secondary",component:tz,href:"/job_distributors/new"},"New Job Distributor")))),l.createElement(d.Z,{item:!0,xs:12},l.createElement(r5.Z,null,l.createElement(r8.Z,null,l.createElement(ie.Z,null,l.createElement(ir.Z,null,l.createElement(r7.default,null,"Name"),l.createElement(r7.default,null,"Connection Status"),l.createElement(r7.default,null,"Status"),l.createElement(r7.default,null,"CSA Public Key"),l.createElement(r7.default,null,"RPC URL"))),l.createElement(r9.Z,null,0===t.length&&l.createElement(ir.Z,null,l.createElement(r7.default,{component:"th",scope:"row",colSpan:3},"Job Distributors have not been registered")),t.map(function(e){return l.createElement(xy,{key:e.id,jobDistributor:e})})))))))},x_=function(){var e,t=xd({fetchPolicy:"cache-and-network"}),n=t.data,r=t.loading,i=t.error;return r?l.createElement(iR,null):i?l.createElement(iD,{error:i}):l.createElement(xw,{jobDistributors:null!==(e=null==n?void 0:n.feedsManagers.results)&&void 0!==e?e:[]})},xE=bv().shape({name:p0().required("Required"),uri:p0().required("Required"),publicKey:p0().required("Required")}),xS=function(e){var t=e.initialValues,n=e.onSubmit;return l.createElement(hT,{initialValues:t,validationSchema:xE,onSubmit:n},function(e){var t=e.isSubmitting,n=e.submitForm;return l.createElement(hR,{"data-testid":"feeds-manager-form"},l.createElement(d.Z,{container:!0,spacing:16},l.createElement(d.Z,{item:!0,xs:12,md:6},l.createElement(hP,{component:hX,id:"name",name:"name",label:"Name",required:!0,fullWidth:!0,FormHelperTextProps:{"data-testid":"name-helper-text"}})),l.createElement(d.Z,{item:!0,xs:!1,md:6}),l.createElement(d.Z,{item:!0,xs:12,md:6},l.createElement(hP,{component:hX,id:"uri",name:"uri",label:"URI",required:!0,fullWidth:!0,helperText:"Provided by the Job Distributor operator",FormHelperTextProps:{"data-testid":"uri-helper-text"}})),l.createElement(d.Z,{item:!0,xs:12,md:6},l.createElement(hP,{component:hX,id:"publicKey",name:"publicKey",label:"Public Key",required:!0,fullWidth:!0,helperText:"Provided by the Job Distributor operator",FormHelperTextProps:{"data-testid":"publicKey-helper-text"}})),l.createElement(d.Z,{item:!0,xs:12},l.createElement(ok.default,{variant:"contained",color:"primary",disabled:t,onClick:n},"Submit"))))})},xk=function(e){var t=e.data,n=e.onSubmit,r={name:t.name,uri:t.uri,publicKey:t.publicKey};return l.createElement(d.Z,{container:!0},l.createElement(d.Z,{item:!0,xs:12,md:11,lg:9},l.createElement(r5.Z,null,l.createElement(sl.Z,{title:"Edit Job Distributor"}),l.createElement(aW.Z,null,l.createElement(xS,{initialValues:r,onSubmit:n})))))};function xx(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]0&&void 0!==arguments[0]?arguments[0]:{};return rv(xZ,e)},xJ=function(){return(0,b.createStyles)({root:{fontSize:24}})},xQ=(0,b.withStyles)(xJ)(function(e){var t=e.children,n=e.classes;return l.createElement(x.default,{variant:"h2",className:n.root},t)}),x1=n(9290),x0=n(74923);function x2(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);ne.length)&&(t=e.length);for(var n=0,r=Array(t);ne.length)&&(t=e.length);for(var n=0,r=Array(t);n=0)&&Object.prototype.propertyIsEnumerable.call(e,n)&&(i[n]=e[n])}return i}function TS(e,t){if(null==e)return{};var n,r,i={},a=Object.keys(e);for(r=0;r=0||(i[n]=e[n]);return i}function Tk(e,t){return Tv(e)||Tw(e,t)||Tx(e,t)||T_()}function Tx(e,t){if(e){if("string"==typeof e)return Tg(e,t);var n=Object.prototype.toString.call(e).slice(8,-1);if("Object"===n&&e.constructor&&(n=e.constructor.name),"Map"===n||"Set"===n)return Array.from(n);if("Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n))return Tg(e,t)}}var TT=function(e){return"SN_MAIN"===e||"SN_SEPOLIA"===e},TM=bv().shape({chainID:p0().required("Required"),chainType:p0().required("Required"),accountAddr:p0().required("Required"),accountAddrPubKey:p0().nullable(),adminAddr:p0(),ocr1Multiaddr:p0().when(["ocr1Enabled","ocr1IsBootstrap"],{is:function(e,t){return e&&t},then:p0().required("Required").nullable()}).nullable(),ocr1P2PPeerID:p0().when(["ocr1Enabled","ocr1IsBootstrap"],{is:function(e,t){return e&&!t},then:p0().required("Required").nullable()}).nullable(),ocr1KeyBundleID:p0().when(["ocr1Enabled","ocr1IsBootstrap"],{is:function(e,t){return e&&!t},then:p0().required("Required").nullable()}).nullable(),ocr2Multiaddr:p0().when(["ocr2Enabled","ocr2IsBootstrap"],{is:function(e,t){return e&&t},then:p0().required("Required").nullable()}).nullable(),ocr2P2PPeerID:p0().when(["ocr2Enabled","ocr2IsBootstrap"],{is:function(e,t){return e&&!t},then:p0().required("Required").nullable()}).nullable(),ocr2KeyBundleID:p0().when(["ocr2Enabled","ocr2IsBootstrap"],{is:function(e,t){return e&&!t},then:p0().required("Required").nullable()}).nullable(),ocr2CommitPluginEnabled:pV().required("Required"),ocr2ExecutePluginEnabled:pV().required("Required"),ocr2MedianPluginEnabled:pV().required("Required"),ocr2MercuryPluginEnabled:pV().required("Required"),ocr2ForwarderAddress:p0().nullable()}),TO=function(e){return(0,b.createStyles)({supportedJobOptionsPaper:{padding:2*e.spacing.unit}})},TA=function(e){var t=e.addresses,n=TE(e,["addresses"]),r=h_(),i=r.values,a=i.chainID,o=i.accountAddr,s=r.setFieldValue,u=Tk(l.useState(!1),2),c=u[0],f=u[1],d=l.useRef();l.useEffect(function(){d.current=a},[a]),l.useEffect(function(){a!==d.current&&(s(n.name,""),f(!1))},[a,s,n.name]);var h=function(e){var t=e.target.value;"custom"===t?(f(!0),s(n.name,"")):(f(!1),s(n.name,t))};return l.createElement(l.Fragment,null,!TT(a)&&l.createElement(hP,Ty({},n,{select:!0,value:c?"custom":o,onChange:h}),t.map(function(e){return l.createElement(tE.default,{key:e,value:e},e)})),TT(a)&&l.createElement(hP,{component:hX,id:"accountAddr",name:"accountAddr",label:"Enter your account address",inputProps:{"data-testid":"customAccountAddr-input"},helperText:"The account address used for this chain",required:!0,fullWidth:!0}),TT(a)&&l.createElement("div",null,l.createElement(hP,{component:hX,id:"accountAddrPubKey",name:"accountAddrPubKey",label:"Account Address Public Key",required:!0,fullWidth:!0,helperText:"The public key for your account address",FormHelperTextProps:{"data-testid":"accountAddrPubKey-helper-text"}})))},TL=(0,b.withStyles)(TO)(function(e){var t=e.classes,n=e.editing,r=void 0!==n&&n,i=e.innerRef,a=e.initialValues,o=e.onSubmit,s=e.chains,u=void 0===s?[]:s,c=e.accountsEVM,f=void 0===c?[]:c,h=e.accountsNonEvm,p=e.p2pKeys,b=void 0===p?[]:p,m=e.ocrKeys,g=void 0===m?[]:m,v=e.ocr2Keys,y=void 0===v?[]:v,w=e.showSubmit,_=void 0!==w&&w;return l.createElement(hT,{innerRef:i,initialValues:a,validationSchema:TM,onSubmit:o},function(e){var n,i,a=e.values,o=[];switch(a.chainType){case Tm.EVM:o=f.filter(function(e){return e.chain.id==a.chainID&&!e.isDisabled}).map(function(e){return e.address});break;case Tm.APTOS:o=null!==(n=null==h?void 0:h.aptosKeys.results.map(function(e){return e.account}))&&void 0!==n?n:[];break;case Tm.SOLANA:o=null!==(i=null==h?void 0:h.solanaKeys.results.map(function(e){return e.id}))&&void 0!==i?i:[];break;default:o=[]}return l.createElement(hR,{"data-testid":"feeds-manager-form",id:"chain-configuration-form",noValidate:!0},l.createElement(d.Z,{container:!0,spacing:16},l.createElement(d.Z,{item:!0,xs:12,md:6},l.createElement(hP,{component:hX,id:"chainType",name:"chainType",label:"Chain Type",select:!0,required:!0,fullWidth:!0,disabled:r},l.createElement(tE.default,{key:Tm.EVM,value:Tm.EVM},"EVM"),l.createElement(tE.default,{key:Tm.APTOS,value:Tm.APTOS},"APTOS"),l.createElement(tE.default,{key:Tm.SOLANA,value:Tm.SOLANA},"SOLANA"))),l.createElement(d.Z,{item:!0,xs:12,md:6},l.createElement(hP,{component:hX,id:"chainID",name:"chainID",label:"Chain ID",required:!0,fullWidth:!0,select:!0,disabled:r,inputProps:{"data-testid":"chainID-input"},FormHelperTextProps:{"data-testid":"chainID-helper-text"}},u.filter(function(e){return e.network.toUpperCase()===a.chainType}).map(function(e){return l.createElement(tE.default,{key:e.id,value:e.id},e.id)}))),l.createElement(d.Z,{item:!0,xs:12,md:6},l.createElement(TA,{component:hX,id:"accountAddr",name:"accountAddr",label:"Account Address",inputProps:{"data-testid":"accountAddr-input"},required:!0,fullWidth:!0,select:!0,helperText:"The account address used for this chain",addresses:o,FormHelperTextProps:{"data-testid":"accountAddr-helper-text"}})),l.createElement(d.Z,{item:!0,xs:12,md:6},l.createElement(hP,{component:hX,id:"adminAddr",name:"adminAddr",label:"Admin Address",fullWidth:!0,helperText:"The address used for LINK payments",FormHelperTextProps:{"data-testid":"adminAddr-helper-text"}})),l.createElement(d.Z,{item:!0,xs:12},l.createElement(x.default,null,"Supported Job Types")),l.createElement(d.Z,{item:!0,xs:12},l.createElement(hP,{component:h2,name:"fluxMonitorEnabled",type:"checkbox",Label:{label:"Flux Monitor"}})),l.createElement(d.Z,{item:!0,xs:12},l.createElement(hP,{component:h2,name:"ocr1Enabled",type:"checkbox",Label:{label:"OCR"}}),a.ocr1Enabled&&l.createElement(ii.default,{className:t.supportedJobOptionsPaper},l.createElement(d.Z,{container:!0,spacing:8},l.createElement(l.Fragment,null,l.createElement(d.Z,{item:!0,xs:12},l.createElement(hP,{component:h2,name:"ocr1IsBootstrap",type:"checkbox",Label:{label:"Is this node running as a bootstrap peer?"}})),a.ocr1IsBootstrap?l.createElement(d.Z,{item:!0,xs:12},l.createElement(hP,{component:hX,id:"ocr1Multiaddr",name:"ocr1Multiaddr",label:"Multiaddr",required:!0,fullWidth:!0,helperText:"The OCR Multiaddr which oracles use to query for network information",FormHelperTextProps:{"data-testid":"ocr1Multiaddr-helper-text"}})):l.createElement(l.Fragment,null,l.createElement(d.Z,{item:!0,xs:12,md:6},l.createElement(hP,{component:hX,id:"ocr1P2PPeerID",name:"ocr1P2PPeerID",label:"Peer ID",select:!0,required:!0,fullWidth:!0,helperText:"The Peer ID used for this chain",FormHelperTextProps:{"data-testid":"ocr1P2PPeerID-helper-text"}},b.map(function(e){return l.createElement(tE.default,{key:e.peerID,value:e.peerID},e.peerID)}))),l.createElement(d.Z,{item:!0,xs:12,md:6},l.createElement(hP,{component:hX,id:"ocr1KeyBundleID",name:"ocr1KeyBundleID",label:"Key Bundle ID",select:!0,required:!0,fullWidth:!0,helperText:"The OCR Key Bundle ID used for this chain",FormHelperTextProps:{"data-testid":"ocr1KeyBundleID-helper-text"}},g.map(function(e){return l.createElement(tE.default,{key:e.id,value:e.id},e.id)})))))))),l.createElement(d.Z,{item:!0,xs:12},l.createElement(hP,{component:h2,name:"ocr2Enabled",type:"checkbox",Label:{label:"OCR2"}}),a.ocr2Enabled&&l.createElement(ii.default,{className:t.supportedJobOptionsPaper},l.createElement(d.Z,{container:!0,spacing:8},l.createElement(l.Fragment,null,l.createElement(d.Z,{item:!0,xs:12},l.createElement(hP,{component:h2,name:"ocr2IsBootstrap",type:"checkbox",Label:{label:"Is this node running as a bootstrap peer?"}})),l.createElement(d.Z,{item:!0,xs:12,md:6},l.createElement(hP,{component:hX,id:"ocr2P2PPeerID",name:"ocr2P2PPeerID",label:"Peer ID",select:!0,required:!a.ocr2IsBootstrap,fullWidth:!0,helperText:"The Peer ID used for this chain",FormHelperTextProps:{"data-testid":"ocr2P2PPeerID-helper-text"}},b.map(function(e){return l.createElement(tE.default,{key:e.peerID,value:e.peerID},e.peerID)}))),a.ocr2IsBootstrap?l.createElement(d.Z,{item:!0,xs:12},l.createElement(hP,{component:hX,id:"ocr2Multiaddr",name:"ocr2Multiaddr",label:"Multiaddr",required:!0,fullWidth:!0,helperText:"The OCR2 Multiaddr which oracles use to query for network information",FormHelperTextProps:{"data-testid":"ocr2Multiaddr-helper-text"}})):l.createElement(l.Fragment,null,l.createElement(d.Z,{item:!0,xs:12,md:6},l.createElement(hP,{component:hX,id:"ocr2KeyBundleID",name:"ocr2KeyBundleID",label:"Key Bundle ID",select:!0,required:!0,fullWidth:!0,helperText:"The OCR2 Key Bundle ID used for this chain",FormHelperTextProps:{"data-testid":"ocr2KeyBundleID-helper-text"}},y.map(function(e){return l.createElement(tE.default,{key:e.id,value:e.id},e.id)}))),l.createElement(d.Z,{item:!0,xs:12},l.createElement(x.default,null,"Supported Plugins")),l.createElement(d.Z,{item:!0,xs:6},l.createElement(hP,{component:h2,name:"ocr2CommitPluginEnabled",type:"checkbox",Label:{label:"Commit"}})),l.createElement(d.Z,{item:!0,xs:6},l.createElement(hP,{component:h2,name:"ocr2ExecutePluginEnabled",type:"checkbox",Label:{label:"Execute"}})),l.createElement(d.Z,{item:!0,xs:6},l.createElement(hP,{component:h2,name:"ocr2RebalancerPluginEnabled",type:"checkbox",Label:{label:"Rebalancer"}})),l.createElement(d.Z,{item:!0,xs:6},l.createElement(hP,{component:h2,name:"ocr2MedianPluginEnabled",type:"checkbox",Label:{label:"Median"}})),l.createElement(d.Z,{item:!0,xs:6},l.createElement(hP,{component:h2,name:"ocr2MercuryPluginEnabled",type:"checkbox",Label:{label:"Mercury"}})),l.createElement(d.Z,{item:!0,xs:12,md:12},l.createElement(hP,{component:hX,id:"ocr2ForwarderAddress",name:"ocr2ForwarderAddress",label:"Forwarder Address (optional)",fullWidth:!0,helperText:"The forwarder address from the Operator Forwarder Contract",FormHelperTextProps:{"data-testid":"ocr2ForwarderAddress-helper-text"}}))))))),_&&l.createElement(d.Z,{item:!0,xs:12,md:7},l.createElement(ok.default,{variant:"contained",color:"primary",type:"submit",size:"large"},"Submit"))))})});function TC(e,t){return t||(t=e.slice(0)),Object.freeze(Object.defineProperties(e,{raw:{value:Object.freeze(t)}}))}function TI(){var e=TC(["\n fragment AptosKeysPayload_ResultsFields on AptosKey {\n account\n id\n }\n"]);return TI=function(){return e},e}function TD(){var e=TC(["\n fragment SolanaKeysPayload_ResultsFields on SolanaKey {\n id\n }\n"]);return TD=function(){return e},e}function TN(){var e=TC(["\n ","\n ","\n query FetchNonEvmKeys {\n aptosKeys {\n results {\n ...AptosKeysPayload_ResultsFields\n }\n }\n solanaKeys {\n results {\n ...SolanaKeysPayload_ResultsFields\n }\n }\n }\n"]);return TN=function(){return e},e}var TP=n0(TI()),TR=n0(TD()),Tj=n0(TN(),TP,TR),TF=function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};return rv(Tj,e)},TY=function(e){var t=e.onClose,n=e.open,r=e.onSubmit,i=l.useRef(),a=i$({fetchPolicy:"network-only"}).data,o=_K({fetchPolicy:"cache-and-network"}).data,s=TF({fetchPolicy:"cache-and-network"}).data,u=SV({fetchPolicy:"cache-and-network"}).data,c=EO({fetchPolicy:"cache-and-network"}).data,f=E2({fetchPolicy:"cache-and-network"}).data,d={chainID:"",chainType:Tm.EVM,accountAddr:"",adminAddr:"",accountAddrPubKey:"",fluxMonitorEnabled:!1,ocr1Enabled:!1,ocr1IsBootstrap:!1,ocr1Multiaddr:"",ocr1P2PPeerID:"",ocr1KeyBundleID:"",ocr2Enabled:!1,ocr2IsBootstrap:!1,ocr2Multiaddr:"",ocr2P2PPeerID:"",ocr2KeyBundleID:"",ocr2CommitPluginEnabled:!1,ocr2ExecutePluginEnabled:!1,ocr2MedianPluginEnabled:!1,ocr2MercuryPluginEnabled:!1,ocr2RebalancerPluginEnabled:!1,ocr2ForwarderAddress:""},h=a?a.chains.results:[],p=o?o.ethKeys.results:[],b=u?u.p2pKeys.results:[],m=c?c.ocrKeyBundles.results:[],g=f?f.ocr2KeyBundles.results:[];return l.createElement(aD.Z,{onClose:t,open:n,disableBackdropClick:!0},l.createElement(oO.Z,{disableTypography:!0},l.createElement(x.default,{variant:"body2"},"New Supported Chain")),l.createElement(oT.Z,null,l.createElement(TL,{innerRef:i,initialValues:d,onSubmit:r,chains:h,accountsEVM:p,accountsNonEvm:s,p2pKeys:b,ocrKeys:m,ocr2Keys:g})),l.createElement(ox.Z,null,l.createElement(ok.default,{onClick:t},"Cancel"),l.createElement(ok.default,{color:"primary",type:"submit",form:"chain-configuration-form",variant:"contained"},"Submit")))},TB=function(e){var t=e.cfg,n=e.onClose,r=e.open,i=e.onSubmit,a=l.useRef(),o=i$({fetchPolicy:"network-only"}).data,s=_K({fetchPolicy:"cache-and-network"}).data,u=TF({fetchPolicy:"cache-and-network"}).data,c=SV({fetchPolicy:"cache-and-network"}).data,f=EO({fetchPolicy:"cache-and-network"}).data,d=E2({fetchPolicy:"cache-and-network"}).data;if(!t)return null;var h={chainID:t.chainID,chainType:Tm.EVM,accountAddr:t.accountAddr,adminAddr:t.adminAddr,accountAddrPubKey:t.accountAddrPubKey,fluxMonitorEnabled:t.fluxMonitorJobConfig.enabled,ocr1Enabled:t.ocr1JobConfig.enabled,ocr1IsBootstrap:t.ocr1JobConfig.isBootstrap,ocr1Multiaddr:t.ocr1JobConfig.multiaddr,ocr1P2PPeerID:t.ocr1JobConfig.p2pPeerID,ocr1KeyBundleID:t.ocr1JobConfig.keyBundleID,ocr2Enabled:t.ocr2JobConfig.enabled,ocr2IsBootstrap:t.ocr2JobConfig.isBootstrap,ocr2Multiaddr:t.ocr2JobConfig.multiaddr,ocr2P2PPeerID:t.ocr2JobConfig.p2pPeerID,ocr2KeyBundleID:t.ocr2JobConfig.keyBundleID,ocr2CommitPluginEnabled:t.ocr2JobConfig.plugins.commit,ocr2ExecutePluginEnabled:t.ocr2JobConfig.plugins.execute,ocr2MedianPluginEnabled:t.ocr2JobConfig.plugins.median,ocr2MercuryPluginEnabled:t.ocr2JobConfig.plugins.mercury,ocr2RebalancerPluginEnabled:t.ocr2JobConfig.plugins.rebalancer,ocr2ForwarderAddress:t.ocr2JobConfig.forwarderAddress},p=o?o.chains.results:[],b=s?s.ethKeys.results:[],m=c?c.p2pKeys.results:[],g=f?f.ocrKeyBundles.results:[],v=d?d.ocr2KeyBundles.results:[];return l.createElement(aD.Z,{onClose:n,open:r,disableBackdropClick:!0},l.createElement(oO.Z,{disableTypography:!0},l.createElement(x.default,{variant:"body2"},"Edit Supported Chain")),l.createElement(oT.Z,null,l.createElement(TL,{innerRef:a,initialValues:h,onSubmit:i,chains:p,accountsEVM:b,accountsNonEvm:u,p2pKeys:m,ocrKeys:g,ocr2Keys:v,editing:!0})),l.createElement(ox.Z,null,l.createElement(ok.default,{onClick:n},"Cancel"),l.createElement(ok.default,{color:"primary",type:"submit",form:"chain-configuration-form",variant:"contained"},"Submit")))};function TU(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]e.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]e.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]e.length)&&(t=e.length);for(var n=0,r=Array(t);nt.version?e:t})},[o]),g=l.useMemo(function(){return MZ(o).sort(function(e,t){return t.version-e.version})},[o]),v=function(e,t,n){switch(e){case"PENDING":return l.createElement(l.Fragment,null,l.createElement(ok.default,{variant:"text",color:"secondary",onClick:function(){return b("reject",t)}},"Reject"),m.id===t&&"DELETED"!==n.status&&"REVOKED"!==n.status&&l.createElement(ok.default,{variant:"contained",color:"primary",onClick:function(){return b("approve",t)}},"Approve"),m.id===t&&"DELETED"===n.status&&n.pendingUpdate&&l.createElement(l.Fragment,null,l.createElement(ok.default,{variant:"contained",color:"primary",onClick:function(){return b("cancel",t)}},"Cancel"),l.createElement(x.default,{color:"error"},"This proposal was deleted. Cancel the spec to delete any running jobs")));case"APPROVED":return l.createElement(l.Fragment,null,l.createElement(ok.default,{variant:"contained",onClick:function(){return b("cancel",t)}},"Cancel"),"DELETED"===n.status&&n.pendingUpdate&&l.createElement(x.default,{color:"error"},"This proposal was deleted. Cancel the spec to delete any running jobs"));case"CANCELLED":if(m.id===t&&"DELETED"!==n.status&&"REVOKED"!==n.status)return l.createElement(ok.default,{variant:"contained",color:"primary",onClick:function(){return b("approve",t)}},"Approve");return null;default:return null}};return l.createElement("div",null,g.map(function(e,n){return l.createElement(mP.Z,{defaultExpanded:0===n,key:n},l.createElement(mR.Z,{expandIcon:l.createElement(gh.Z,null)},l.createElement(x.default,{className:t.versionText},"Version ",e.version),l.createElement(Es.Z,{label:e.status,color:"APPROVED"===e.status?"primary":"default",variant:"REJECTED"===e.status||"CANCELLED"===e.status?"outlined":"default"}),l.createElement("div",{className:t.proposedAtContainer},l.createElement(x.default,null,"Proposed ",l.createElement(aO,{tooltip:!0},e.createdAt)))),l.createElement(mj.Z,{className:t.expansionPanelDetails},l.createElement("div",{className:t.actions},l.createElement("div",{className:t.editContainer},0===n&&("PENDING"===e.status||"CANCELLED"===e.status)&&"DELETED"!==s.status&&"REVOKED"!==s.status&&l.createElement(ok.default,{variant:"contained",onClick:function(){return p(!0)}},"Edit")),l.createElement("div",{className:t.actionsContainer},v(e.status,e.id,s))),l.createElement(gd,{language:"toml",style:gs,"data-testid":"codeblock"},e.definition)))}),l.createElement(oC,{open:null!=c,title:c?M0[c.action].title:"",body:c?M0[c.action].body:"",onConfirm:function(){if(c){switch(c.action){case"approve":n(c.id);break;case"cancel":r(c.id);break;case"reject":i(c.id)}f(null)}},cancelButtonText:"Cancel",onCancel:function(){return f(null)}}),l.createElement(MB,{open:h,onClose:function(){return p(!1)},initialValues:{definition:m.definition,id:m.id},onSubmit:a}))});function M3(e,t){return t||(t=e.slice(0)),Object.freeze(Object.defineProperties(e,{raw:{value:Object.freeze(t)}}))}function M4(){var e=M3(["\n ","\n fragment JobProposalPayloadFields on JobProposal {\n id\n externalJobID\n remoteUUID\n jobID\n specs {\n ...JobProposal_SpecsFields\n }\n status\n pendingUpdate\n }\n"]);return M4=function(){return e},e}var M6=n0(M4(),MQ),M5=function(e){var t=e.onApprove,n=e.onCancel,r=e.onReject,i=e.onUpdateSpec,a=e.proposal;return l.createElement(ig,null,l.createElement(d.Z,{container:!0,spacing:32},l.createElement(d.Z,{item:!0,xs:9},l.createElement(iy,null,"Job Proposal #",a.id))),l.createElement(MN,{proposal:a}),l.createElement(d.Z,{container:!0,spacing:32},l.createElement(d.Z,{item:!0,xs:9},l.createElement(xQ,null,"Specs"))),l.createElement(d.Z,{container:!0,spacing:32},l.createElement(d.Z,{item:!0,xs:12},l.createElement(M2,{proposal:a,specs:a.specs,onReject:r,onApprove:t,onCancel:n,onUpdateSpec:i}))))};function M8(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]e.length)&&(t=e.length);for(var n=0,r=Array(t);ne.length)&&(t=e.length);for(var n=0,r=Array(t);nU,tA:()=>$,KL:()=>H,Iw:()=>V,DQ:()=>W,cB:()=>T,LO:()=>M,t5:()=>k,qt:()=>x,Jc:()=>C,L7:()=>Y,EO:()=>B});var r,i,a=n(66289),o=n(41800),s=n.n(o),u=n(67932);(i=r||(r={})).IN_PROGRESS="in_progress",i.PENDING_INCOMING_CONFIRMATIONS="pending_incoming_confirmations",i.PENDING_CONNECTION="pending_connection",i.PENDING_BRIDGE="pending_bridge",i.PENDING_SLEEP="pending_sleep",i.ERRORED="errored",i.COMPLETED="completed";var c=n(87013),l=n(19084),f=n(34823);function d(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]j,v2:()=>F});var r=n(66289);function i(e,t){if(!(e instanceof t))throw TypeError("Cannot call a class as a function")}var a="/sessions",o="/sessions",s=function e(t){var n=this;i(this,e),this.api=t,this.createSession=function(e){return n.create(e)},this.destroySession=function(){return n.destroy()},this.create=this.api.createResource(a),this.destroy=this.api.deleteResource(o)};function u(e,t){if(!(e instanceof t))throw TypeError("Cannot call a class as a function")}var c="/v2/bulk_delete_runs",l=function e(t){var n=this;u(this,e),this.api=t,this.bulkDeleteJobRuns=function(e){return n.destroy(e)},this.destroy=this.api.deleteResource(c)};function f(e,t){if(!(e instanceof t))throw TypeError("Cannot call a class as a function")}var d="/v2/chains/evm",h="".concat(d,"/:id"),p=function e(t){var n=this;f(this,e),this.api=t,this.getChains=function(){return n.index()},this.createChain=function(e){return n.create(e)},this.destroyChain=function(e){return n.destroy(void 0,{id:e})},this.updateChain=function(e,t){return n.update(t,{id:e})},this.index=this.api.fetchResource(d),this.create=this.api.createResource(d),this.destroy=this.api.deleteResource(h),this.update=this.api.updateResource(h)};function b(e,t){if(!(e instanceof t))throw TypeError("Cannot call a class as a function")}var m="/v2/keys/evm/chain",g=function e(t){var n=this;b(this,e),this.api=t,this.chain=function(e){var t=new URLSearchParams;t.append("address",e.address),t.append("evmChainID",e.evmChainID),null!==e.abandon&&t.append("abandon",String(e.abandon)),null!==e.enabled&&t.append("enabled",String(e.enabled));var r=m+"?"+t.toString();return n.api.createResource(r)()}};function v(e,t){if(!(e instanceof t))throw TypeError("Cannot call a class as a function")}var y="/v2/jobs",w="".concat(y,"/:specId/runs"),_=function e(t){var n=this;v(this,e),this.api=t,this.createJobRunV2=function(e,t){return n.post(t,{specId:e})},this.post=this.api.createResource(w,!0)};function E(e,t){if(!(e instanceof t))throw TypeError("Cannot call a class as a function")}var S="/v2/log",k=function e(t){var n=this;E(this,e),this.api=t,this.getLogConfig=function(){return n.show()},this.updateLogConfig=function(e){return n.update(e)},this.show=this.api.fetchResource(S),this.update=this.api.updateResource(S)};function x(e,t){if(!(e instanceof t))throw TypeError("Cannot call a class as a function")}var T="/v2/nodes",M=function e(t){var n=this;x(this,e),this.api=t,this.getNodes=function(){return n.index()},this.createNode=function(e){return n.create(e)},this.index=this.api.fetchResource(T),this.create=this.api.createResource(T)};function O(e,t){if(!(e instanceof t))throw TypeError("Cannot call a class as a function")}var A="/v2/enroll_webauthn",L=function e(t){var n=this;O(this,e),this.api=t,this.beginKeyRegistration=function(e){return n.create(e)},this.finishKeyRegistration=function(e){return n.put(e)},this.create=this.api.fetchResource(A),this.put=this.api.createResource(A)};function C(e,t){if(!(e instanceof t))throw TypeError("Cannot call a class as a function")}var I="/v2/build_info",D=function e(t){var n=this;C(this,e),this.api=t,this.show=function(){return n.api.GET(I)()}};function N(e,t){if(!(e instanceof t))throw TypeError("Cannot call a class as a function")}var P=function e(t){N(this,e),this.api=t,this.buildInfo=new D(this.api),this.bulkDeleteRuns=new l(this.api),this.chains=new p(this.api),this.logConfig=new k(this.api),this.nodes=new M(this.api),this.jobs=new _(this.api),this.webauthn=new L(this.api),this.evmKeys=new g(this.api)},R=new r.V0({base:void 0}),j=new s(R),F=new P(R)},1398(e,t,n){"use strict";n.d(t,{Z:()=>d});var r=n(67294),i=n(32316),a=n(83638),o=n(94184),s=n.n(o);function u(){return(u=Object.assign||function(e){for(var t=1;tc});var r=n(67294),i=n(32316);function a(){return(a=Object.assign||function(e){for(var t=1;tx,jK:()=>v});var r=n(67294),i=n(37703),a=n(45697),o=n.n(a),s=n(82204),u=n(71426),c=n(94184),l=n.n(c),f=n(32316),d=function(e){var t=e.palette.success||{},n=e.palette.warning||{};return{base:{paddingLeft:5*e.spacing.unit,paddingRight:5*e.spacing.unit},success:{backgroundColor:t.main,color:t.contrastText},error:{backgroundColor:e.palette.error.dark,color:e.palette.error.contrastText},warning:{backgroundColor:n.contrastText,color:n.main}}},h=function(e){var t,n=e.success,r=e.error,i=e.warning,a=e.classes,o=e.className;return n?t=a.success:r?t=a.error:i&&(t=a.warning),l()(a.base,o,t)},p=function(e){return r.createElement(s.Z,{className:h(e),square:!0},r.createElement(u.default,{variant:"body2",color:"inherit",component:"div"},e.children))};p.defaultProps={success:!1,error:!1,warning:!1},p.propTypes={success:o().bool,error:o().bool,warning:o().bool};let b=(0,f.withStyles)(d)(p);var m=function(){return r.createElement(r.Fragment,null,"Unhandled error. Please help us by opening a"," ",r.createElement("a",{href:"https://github.com/smartcontractkit/chainlink/issues/new"},"bug report"))};let g=m;function v(e){return"string"==typeof e?e:e.component?e.component(e.props):r.createElement(g,null)}function y(e,t){var n;return n="string"==typeof e?e:e.component?e.component(e.props):r.createElement(g,null),r.createElement("p",{key:t},n)}var w=function(e){var t=e.notifications;return r.createElement(b,{error:!0},t.map(y))},_=function(e){var t=e.notifications;return r.createElement(b,{success:!0},t.map(y))},E=function(e){var t=e.errors,n=e.successes;return r.createElement("div",null,(null==t?void 0:t.length)>0&&r.createElement(w,{notifications:t}),n.length>0&&r.createElement(_,{notifications:n}))},S=function(e){return{errors:e.notifications.errors,successes:e.notifications.successes}},k=(0,i.$j)(S)(E);let x=k},9409(e,t,n){"use strict";n.d(t,{ZP:()=>j});var r=n(67294),i=n(37703),a=n(5977),o=n(32316),s=n(1398),u=n(82204),c=n(30060),l=n(71426),f=n(60520),d=n(39814),h=n(57209),p=n(26842),b=n(3950),m=n(5536),g=n(45697),v=n.n(g);let y=n.p+"9f6d832ef97e8493764e.svg";function w(){return(w=Object.assign||function(e){for(var t=1;te.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&_.map(function(e,t){return r.createElement(d.Z,{item:!0,xs:12,key:t},r.createElement(u.Z,{raised:!1,className:v.error},r.createElement(c.Z,null,r.createElement(l.default,{variant:"body1",className:v.errorText},(0,b.jK)(e)))))}),r.createElement(d.Z,{item:!0,xs:12},r.createElement(f.Z,{id:"email",label:"Email",margin:"normal",value:n,onChange:m("email"),error:_.length>0,variant:"outlined",fullWidth:!0})),r.createElement(d.Z,{item:!0,xs:12},r.createElement(f.Z,{id:"password",label:"Password",type:"password",autoComplete:"password",margin:"normal",value:h,onChange:m("password"),error:_.length>0,variant:"outlined",fullWidth:!0})),r.createElement(d.Z,{item:!0,xs:12},r.createElement(d.Z,{container:!0,spacing:0,justify:"center"},r.createElement(d.Z,{item:!0},r.createElement(s.Z,{type:"submit",variant:"primary"},"Access Account")))),y&&r.createElement(l.default,{variant:"body1",color:"textSecondary"},"Signing in...")))))))},P=function(e){return{fetching:e.authentication.fetching,authenticated:e.authentication.allowed,errors:e.notifications.errors}},R=(0,i.$j)(P,x({submitSignIn:p.L7}))(N);let j=(0,h.wU)(e)((0,o.withStyles)(D)(R))},16353(e,t,n){"use strict";n.d(t,{ZP:()=>H,rH:()=>U});var r,i=n(37703),a=n(97779),o=n(9541),s=n(19084);function u(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function c(e){for(var t=1;t0&&void 0!==arguments[0]?arguments[0]:h,t=arguments.length>1?arguments[1]:void 0;switch(t.type){case s.Mk.RECEIVE_SIGNOUT_SUCCESS:case s.Mk.RECEIVE_SIGNIN_SUCCESS:var n={allowed:t.authenticated};return o.Ks(n),f(c({},e,n),{errors:[]});case s.Mk.RECEIVE_SIGNIN_FAIL:var r={allowed:!1};return o.Ks(r),f(c({},e,r),{errors:[]});case s.Mk.RECEIVE_SIGNIN_ERROR:case s.Mk.RECEIVE_SIGNOUT_ERROR:var i={allowed:!1};return o.Ks(i),f(c({},e,i),{errors:t.errors||[]});default:return e}};let b=p;function m(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function g(e){for(var t=1;t0&&void 0!==arguments[0]?arguments[0]:_,t=arguments.length>1?arguments[1]:void 0;return t.type?t.type.startsWith(r.REQUEST)?y(g({},e),{count:e.count+1}):t.type.startsWith(r.RECEIVE)?y(g({},e),{count:Math.max(e.count-1,0)}):t.type.startsWith(r.RESPONSE)?y(g({},e),{count:Math.max(e.count-1,0)}):t.type===s.di.REDIRECT?y(g({},e),{count:0}):e:e};let S=E;function k(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function x(e){for(var t=1;t0&&void 0!==arguments[0]?arguments[0]:O,t=arguments.length>1?arguments[1]:void 0;switch(t.type){case s.di.MATCH_ROUTE:return M(x({},O),{currentUrl:t.pathname});case s.Ih.NOTIFY_SUCCESS:var n={component:t.component,props:t.props};return M(x({},e),{successes:[n],errors:[]});case s.Ih.NOTIFY_SUCCESS_MSG:return M(x({},e),{successes:[t.msg],errors:[]});case s.Ih.NOTIFY_ERROR:var r=t.error.errors,i=null==r?void 0:r.map(function(e){return L(t,e)});return M(x({},e),{successes:[],errors:i});case s.Ih.NOTIFY_ERROR_MSG:return M(x({},e),{successes:[],errors:[t.msg]});case s.Mk.RECEIVE_SIGNIN_FAIL:return M(x({},e),{successes:[],errors:["Your email or password is incorrect. Please try again"]});default:return e}};function L(e,t){return{component:e.component,props:{msg:t.detail}}}let C=A;function I(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function D(e){for(var t=1;t0&&void 0!==arguments[0]?arguments[0]:R,t=arguments.length>1?arguments[1]:void 0;switch(t.type){case s.di.REDIRECT:return P(D({},e),{to:t.to});case s.di.MATCH_ROUTE:return P(D({},e),{to:void 0});default:return e}};let F=j;var Y=n(87013),B=(0,a.UY)({authentication:b,fetching:S,notifications:C,redirect:F,buildInfo:Y.Z});B(void 0,{type:"INITIAL_STATE"});var U=i.v9;let H=B},19084(e,t,n){"use strict";var r,i,a,o,s,u,c,l,f,d;n.d(t,{Ih:()=>i,Mk:()=>a,Y0:()=>s,di:()=>r,jp:()=>o}),n(67294),(u=r||(r={})).REDIRECT="REDIRECT",u.MATCH_ROUTE="MATCH_ROUTE",(c=i||(i={})).NOTIFY_SUCCESS="NOTIFY_SUCCESS",c.NOTIFY_SUCCESS_MSG="NOTIFY_SUCCESS_MSG",c.NOTIFY_ERROR="NOTIFY_ERROR",c.NOTIFY_ERROR_MSG="NOTIFY_ERROR_MSG",(l=a||(a={})).REQUEST_SIGNIN="REQUEST_SIGNIN",l.RECEIVE_SIGNIN_SUCCESS="RECEIVE_SIGNIN_SUCCESS",l.RECEIVE_SIGNIN_FAIL="RECEIVE_SIGNIN_FAIL",l.RECEIVE_SIGNIN_ERROR="RECEIVE_SIGNIN_ERROR",l.RECEIVE_SIGNOUT_SUCCESS="RECEIVE_SIGNOUT_SUCCESS",l.RECEIVE_SIGNOUT_ERROR="RECEIVE_SIGNOUT_ERROR",(f=o||(o={})).RECEIVE_CREATE_ERROR="RECEIVE_CREATE_ERROR",f.RECEIVE_CREATE_SUCCESS="RECEIVE_CREATE_SUCCESS",f.RECEIVE_DELETE_ERROR="RECEIVE_DELETE_ERROR",f.RECEIVE_DELETE_SUCCESS="RECEIVE_DELETE_SUCCESS",f.RECEIVE_UPDATE_ERROR="RECEIVE_UPDATE_ERROR",f.RECEIVE_UPDATE_SUCCESS="RECEIVE_UPDATE_SUCCESS",f.REQUEST_CREATE="REQUEST_CREATE",f.REQUEST_DELETE="REQUEST_DELETE",f.REQUEST_UPDATE="REQUEST_UPDATE",f.UPSERT_CONFIGURATION="UPSERT_CONFIGURATION",f.UPSERT_JOB_RUN="UPSERT_JOB_RUN",f.UPSERT_JOB_RUNS="UPSERT_JOB_RUNS",f.UPSERT_TRANSACTION="UPSERT_TRANSACTION",f.UPSERT_TRANSACTIONS="UPSERT_TRANSACTIONS",f.UPSERT_BUILD_INFO="UPSERT_BUILD_INFO",(d=s||(s={})).FETCH_BUILD_INFO_REQUESTED="FETCH_BUILD_INFO_REQUESTED",d.FETCH_BUILD_INFO_SUCCEEDED="FETCH_BUILD_INFO_SUCCEEDED",d.FETCH_BUILD_INFO_FAILED="FETCH_BUILD_INFO_FAILED"},87013(e,t,n){"use strict";n.d(t,{Y:()=>o,Z:()=>u});var r=n(19084);function i(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function a(e){for(var t=1;t0&&void 0!==arguments[0]?arguments[0]:o,t=arguments.length>1?arguments[1]:void 0;return t.type===r.Y0.FETCH_BUILD_INFO_SUCCEEDED?a({},t.buildInfo):e};let u=s},34823(e,t,n){"use strict";n.d(t,{N:()=>r});var r=function(e){return e.buildInfo}},73343(e,t,n){"use strict";n.d(t,{r:()=>u});var r=n(19350),i=n(32316),a=n(59114),o=n(5324),s={props:{MuiGrid:{spacing:3*o.default.unit},MuiCardHeader:{titleTypographyProps:{color:"secondary"}}},palette:{action:{hoverOpacity:.3},primary:{light:"#E5F1FF",main:"#3c40c6",contrastText:"#fff"},secondary:{main:"#3d5170"},success:{light:"#e8faf1",main:r.ek.A700,dark:r.ek[700],contrastText:r.y0.white},warning:{light:"#FFFBF1",main:"#fff6b6",contrastText:"#fad27a"},error:{light:"#ffdada",main:"#f44336",dark:"#d32f2f",contrastText:"#fff"},background:{default:"#f5f6f8",appBar:"#3c40c6"},text:{primary:(0,a.darken)(r.BA.A700,.7),secondary:"#818ea3"},listPendingStatus:{background:"#fef7e5",color:"#fecb4c"},listCompletedStatus:{background:"#e9faf2",color:"#4ed495"}},shape:{borderRadius:o.default.unit},overrides:{MuiButton:{root:{borderRadius:o.default.unit/2,textTransform:"none"},sizeLarge:{padding:void 0,fontSize:void 0,paddingTop:o.default.unit,paddingBottom:o.default.unit,paddingLeft:5*o.default.unit,paddingRight:5*o.default.unit}},MuiTableCell:{body:{fontSize:"1rem"},head:{fontSize:"1rem",fontWeight:400}},MuiCardHeader:{root:{borderBottom:"1px solid rgba(0, 0, 0, 0.12)"},action:{marginTop:-2,marginRight:0,"& >*":{marginLeft:2*o.default.unit}},subheader:{marginTop:.5*o.default.unit}}},typography:{useNextVariants:!0,fontFamily:"-apple-system,BlinkMacSystemFont,Roboto,Helvetica,Arial,sans-serif",button:{textTransform:"none",fontSize:"1.2em"},body1:{fontSize:"1.0rem",fontWeight:400,lineHeight:"1.46429em",color:"rgba(0, 0, 0, 0.87)",letterSpacing:-.4},body2:{fontSize:"1.0rem",fontWeight:500,lineHeight:"1.71429em",color:"rgba(0, 0, 0, 0.87)",letterSpacing:-.4},body1Next:{color:"rgb(29, 29, 29)",fontWeight:400,fontSize:"1rem",lineHeight:1.5,letterSpacing:-.4},body2Next:{color:"rgb(29, 29, 29)",fontWeight:400,fontSize:"0.875rem",lineHeight:1.5,letterSpacing:-.4},display1:{color:"#818ea3",fontSize:"2.125rem",fontWeight:400,lineHeight:"1.20588em",letterSpacing:-.4},display2:{color:"#818ea3",fontSize:"2.8125rem",fontWeight:400,lineHeight:"1.13333em",marginLeft:"-.02em",letterSpacing:-.4},display3:{color:"#818ea3",fontSize:"3.5rem",fontWeight:400,lineHeight:"1.30357em",marginLeft:"-.02em",letterSpacing:-.4},display4:{fontSize:14,fontWeightLight:300,fontWeightMedium:500,fontWeightRegular:400,letterSpacing:-.4},h1:{color:"rgb(29, 29, 29)",fontSize:"6rem",fontWeight:300,lineHeight:1},h2:{color:"rgb(29, 29, 29)",fontSize:"3.75rem",fontWeight:300,lineHeight:1},h3:{color:"rgb(29, 29, 29)",fontSize:"3rem",fontWeight:400,lineHeight:1.04},h4:{color:"rgb(29, 29, 29)",fontSize:"2.125rem",fontWeight:400,lineHeight:1.17},h5:{color:"rgb(29, 29, 29)",fontSize:"1.5rem",fontWeight:400,lineHeight:1.33,letterSpacing:-.4},h6:{fontSize:"0.8rem",fontWeight:450,lineHeight:"1.71429em",color:"rgba(0, 0, 0, 0.87)",letterSpacing:-.4},subheading:{color:"rgb(29, 29, 29)",fontSize:"1rem",fontWeight:400,lineHeight:"1.5em",letterSpacing:-.4},subtitle1:{color:"rgb(29, 29, 29)",fontSize:"1rem",fontWeight:400,lineHeight:1.75,letterSpacing:-.4},subtitle2:{color:"rgb(29, 29, 29)",fontSize:"0.875rem",fontWeight:500,lineHeight:1.57,letterSpacing:-.4}},shadows:["none","0px 1px 3px 0px rgba(0, 0, 0, 0.1),0px 1px 1px 0px rgba(0, 0, 0, 0.04),0px 2px 1px -1px rgba(0, 0, 0, 0.02)","0px 1px 5px 0px rgba(0, 0, 0, 0.1),0px 2px 2px 0px rgba(0, 0, 0, 0.04),0px 3px 1px -2px rgba(0, 0, 0, 0.02)","0px 1px 8px 0px rgba(0, 0, 0, 0.1),0px 3px 4px 0px rgba(0, 0, 0, 0.04),0px 3px 3px -2px rgba(0, 0, 0, 0.02)","0px 2px 4px -1px rgba(0, 0, 0, 0.1),0px 4px 5px 0px rgba(0, 0, 0, 0.04),0px 1px 10px 0px rgba(0, 0, 0, 0.02)","0px 3px 5px -1px rgba(0, 0, 0, 0.1),0px 5px 8px 0px rgba(0, 0, 0, 0.04),0px 1px 14px 0px rgba(0, 0, 0, 0.02)","0px 3px 5px -1px rgba(0, 0, 0, 0.1),0px 6px 10px 0px rgba(0, 0, 0, 0.04),0px 1px 18px 0px rgba(0, 0, 0, 0.02)","0px 4px 5px -2px rgba(0, 0, 0, 0.1),0px 7px 10px 1px rgba(0, 0, 0, 0.04),0px 2px 16px 1px rgba(0, 0, 0, 0.02)","0px 5px 5px -3px rgba(0, 0, 0, 0.1),0px 8px 10px 1px rgba(0, 0, 0, 0.04),0px 3px 14px 2px rgba(0, 0, 0, 0.02)","0px 5px 6px -3px rgba(0, 0, 0, 0.1),0px 9px 12px 1px rgba(0, 0, 0, 0.04),0px 3px 16px 2px rgba(0, 0, 0, 0.02)","0px 6px 6px -3px rgba(0, 0, 0, 0.1),0px 10px 14px 1px rgba(0, 0, 0, 0.04),0px 4px 18px 3px rgba(0, 0, 0, 0.02)","0px 6px 7px -4px rgba(0, 0, 0, 0.1),0px 11px 15px 1px rgba(0, 0, 0, 0.04),0px 4px 20px 3px rgba(0, 0, 0, 0.02)","0px 7px 8px -4px rgba(0, 0, 0, 0.1),0px 12px 17px 2px rgba(0, 0, 0, 0.04),0px 5px 22px 4px rgba(0, 0, 0, 0.02)","0px 7px 8px -4px rgba(0, 0, 0, 0.1),0px 13px 19px 2px rgba(0, 0, 0, 0.04),0px 5px 24px 4px rgba(0, 0, 0, 0.02)","0px 7px 9px -4px rgba(0, 0, 0, 0.1),0px 14px 21px 2px rgba(0, 0, 0, 0.04),0px 5px 26px 4px rgba(0, 0, 0, 0.02)","0px 8px 9px -5px rgba(0, 0, 0, 0.1),0px 15px 22px 2px rgba(0, 0, 0, 0.04),0px 6px 28px 5px rgba(0, 0, 0, 0.02)","0px 8px 10px -5px rgba(0, 0, 0, 0.1),0px 16px 24px 2px rgba(0, 0, 0, 0.04),0px 6px 30px 5px rgba(0, 0, 0, 0.02)","0px 8px 11px -5px rgba(0, 0, 0, 0.1),0px 17px 26px 2px rgba(0, 0, 0, 0.04),0px 6px 32px 5px rgba(0, 0, 0, 0.02)","0px 9px 11px -5px rgba(0, 0, 0, 0.1),0px 18px 28px 2px rgba(0, 0, 0, 0.04),0px 7px 34px 6px rgba(0, 0, 0, 0.02)","0px 9px 12px -6px rgba(0, 0, 0, 0.1),0px 19px 29px 2px rgba(0, 0, 0, 0.04),0px 7px 36px 6px rgba(0, 0, 0, 0.02)","0px 10px 13px -6px rgba(0, 0, 0, 0.1),0px 20px 31px 3px rgba(0, 0, 0, 0.04),0px 8px 38px 7px rgba(0, 0, 0, 0.02)","0px 10px 13px -6px rgba(0, 0, 0, 0.1),0px 21px 33px 3px rgba(0, 0, 0, 0.04),0px 8px 40px 7px rgba(0, 0, 0, 0.02)","0px 10px 14px -6px rgba(0, 0, 0, 0.1),0px 22px 35px 3px rgba(0, 0, 0, 0.04),0px 8px 42px 7px rgba(0, 0, 0, 0.02)","0px 11px 14px -7px rgba(0, 0, 0, 0.1),0px 23px 36px 3px rgba(0, 0, 0, 0.04),0px 9px 44px 8px rgba(0, 0, 0, 0.02)","0px 11px 15px -7px rgba(0, 0, 0, 0.1),0px 24px 38px 3px rgba(0, 0, 0, 0.04),0px 9px 46px 8px rgba(0, 0, 0, 0.02)",]},u=(0,i.createMuiTheme)(s)},66289(e,t,n){"use strict";function r(e){if(void 0===e)throw ReferenceError("this hasn't been initialised - super() hasn't been called");return e}function i(e,t){if(!(e instanceof t))throw TypeError("Cannot call a class as a function")}function a(){if("undefined"==typeof Reflect||!Reflect.construct||Reflect.construct.sham)return!1;if("function"==typeof Proxy)return!0;try{return Date.prototype.toString.call(Reflect.construct(Date,[],function(){})),!0}catch(e){return!1}}function o(e,t,n){return(o=a()?Reflect.construct:function(e,t,n){var r=[null];r.push.apply(r,t);var i=new(Function.bind.apply(e,r));return n&&f(i,n.prototype),i}).apply(null,arguments)}function s(e){return(s=Object.setPrototypeOf?Object.getPrototypeOf:function(e){return e.__proto__||Object.getPrototypeOf(e)})(e)}function u(e,t){if("function"!=typeof t&&null!==t)throw TypeError("Super expression must either be null or a function");e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,writable:!0,configurable:!0}}),t&&f(e,t)}function c(e){return -1!==Function.toString.call(e).indexOf("[native code]")}function l(e,t){return t&&("object"===p(t)||"function"==typeof t)?t:r(e)}function f(e,t){return(f=Object.setPrototypeOf||function(e,t){return e.__proto__=t,e})(e,t)}n.d(t,{V0:()=>B,_7:()=>v});var d,h,p=function(e){return e&&"undefined"!=typeof Symbol&&e.constructor===Symbol?"symbol":typeof e};function b(e){var t="function"==typeof Map?new Map:void 0;return(b=function(e){if(null===e||!c(e))return e;if("function"!=typeof e)throw TypeError("Super expression must either be null or a function");if(void 0!==t){if(t.has(e))return t.get(e);t.set(e,n)}function n(){return o(e,arguments,s(this).constructor)}return n.prototype=Object.create(e.prototype,{constructor:{value:n,enumerable:!1,writable:!0,configurable:!0}}),f(n,e)})(e)}function m(){if("undefined"==typeof Reflect||!Reflect.construct||Reflect.construct.sham)return!1;if("function"==typeof Proxy)return!0;try{return Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],function(){})),!0}catch(e){return!1}}function g(e){var t=m();return function(){var n,r=s(e);if(t){var i=s(this).constructor;n=Reflect.construct(r,arguments,i)}else n=r.apply(this,arguments);return l(this,n)}}var v=function(e){u(n,e);var t=g(n);function n(e){var r;return i(this,n),(r=t.call(this,"AuthenticationError(".concat(e.statusText,")"))).errors=[{status:e.status,detail:e},],r}return n}(b(Error)),y=function(e){u(n,e);var t=g(n);function n(e){var r,a=e.errors;return i(this,n),(r=t.call(this,"BadRequestError")).errors=a,r}return n}(b(Error)),w=function(e){u(n,e);var t=g(n);function n(e){var r;return i(this,n),(r=t.call(this,"UnprocessableEntityError")).errors=e,r}return n}(b(Error)),_=function(e){u(n,e);var t=g(n);function n(e){var r;return i(this,n),(r=t.call(this,"ServerError")).errors=e,r}return n}(b(Error)),E=function(e){u(n,e);var t=g(n);function n(e){var r,a=e.errors;return i(this,n),(r=t.call(this,"ConflictError")).errors=a,r}return n}(b(Error)),S=function(e){u(n,e);var t=g(n);function n(e){var r;return i(this,n),(r=t.call(this,"UnknownResponseError(".concat(e.statusText,")"))).errors=[{status:e.status,detail:e.statusText},],r}return n}(b(Error));function k(e,t){var n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:2e4;return Promise.race([fetch(e,t),new Promise(function(e,t){return setTimeout(function(){return t(Error("timeout"))},n)}),])}function x(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]=200&&e.status<300))return[3,2];return[2,e.json()];case 2:if(400!==e.status)return[3,3];return[2,e.json().then(function(e){throw new y(e)})];case 3:if(401!==e.status)return[3,4];throw new v(e);case 4:if(422!==e.status)return[3,6];return[4,$(e)];case 5:throw n=i.sent(),new w(n);case 6:if(409!==e.status)return[3,7];return[2,e.json().then(function(e){throw new E(e)})];case 7:if(!(e.status>=500))return[3,9];return[4,$(e)];case 8:throw r=i.sent(),new _(r);case 9:throw new S(e);case 10:return[2]}})})).apply(this,arguments)}function $(e){return z.apply(this,arguments)}function z(){return(z=j(function(e){return Y(this,function(t){return[2,e.json().then(function(t){return t.errors?t.errors.map(function(t){return{status:e.status,detail:t.detail}}):G(e)}).catch(function(){return G(e)})]})})).apply(this,arguments)}function G(e){return[{status:e.status,detail:e.statusText},]}},50109(e,t,n){"use strict";n.d(t,{LK:()=>o,U2:()=>i,eT:()=>s,t8:()=>a});var r=n(12795);function i(e){return r.ZP.getItem("chainlink.".concat(e))}function a(e,t){r.ZP.setItem("chainlink.".concat(e),t)}function o(e){var t=i(e),n={};if(t)try{return JSON.parse(t)}catch(r){}return n}function s(e,t){a(e,JSON.stringify(t))}},9541(e,t,n){"use strict";n.d(t,{Ks:()=>u,Tp:()=>a,iR:()=>o,pm:()=>s});var r=n(50109),i="persistURL";function a(){return r.U2(i)||""}function o(e){r.t8(i,e)}function s(){return r.LK("authentication")}function u(e){r.eT("authentication",e)}},67121(e,t,n){"use strict";function r(e){var t,n=e.Symbol;return"function"==typeof n?n.observable?t=n.observable:(t=n("observable"),n.observable=t):t="@@observable",t}n.r(t),n.d(t,{default:()=>o}),e=n.hmd(e),i="undefined"!=typeof self?self:"undefined"!=typeof window?window:void 0!==n.g?n.g:e;var i,a=r(i);let o=a},2177(e,t,n){"use strict";n.d(t,{Z:()=>o});var r=!0,i="Invariant failed";function a(e,t){if(!e){if(r)throw Error(i);throw Error(i+": "+(t||""))}}let o=a},11742(e){e.exports=function(){var e=document.getSelection();if(!e.rangeCount)return function(){};for(var t=document.activeElement,n=[],r=0;ru,ZT:()=>i,_T:()=>o,ev:()=>c,mG:()=>s,pi:()=>a});var r=function(e,t){return(r=Object.setPrototypeOf||({__proto__:[]})instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)Object.prototype.hasOwnProperty.call(t,n)&&(e[n]=t[n])})(e,t)};function i(e,t){if("function"!=typeof t&&null!==t)throw TypeError("Class extends value "+String(t)+" is not a constructor or null");function n(){this.constructor=e}r(e,t),e.prototype=null===t?Object.create(t):(n.prototype=t.prototype,new n)}var a=function(){return(a=Object.assign||function(e){for(var t,n=1,r=arguments.length;nt.indexOf(r)&&(n[r]=e[r]);if(null!=e&&"function"==typeof Object.getOwnPropertySymbols)for(var i=0,r=Object.getOwnPropertySymbols(e);it.indexOf(r[i])&&Object.prototype.propertyIsEnumerable.call(e,r[i])&&(n[r[i]]=e[r[i]]);return n}function s(e,t,n,r){function i(e){return e instanceof n?e:new n(function(t){t(e)})}return new(n||(n=Promise))(function(n,a){function o(e){try{u(r.next(e))}catch(t){a(t)}}function s(e){try{u(r.throw(e))}catch(t){a(t)}}function u(e){e.done?n(e.value):i(e.value).then(o,s)}u((r=r.apply(e,t||[])).next())})}function u(e,t){var n,r,i,a,o={label:0,sent:function(){if(1&i[0])throw i[1];return i[1]},trys:[],ops:[]};return a={next:s(0),throw:s(1),return:s(2)},"function"==typeof Symbol&&(a[Symbol.iterator]=function(){return this}),a;function s(e){return function(t){return u([e,t])}}function u(a){if(n)throw TypeError("Generator is already executing.");for(;o;)try{if(n=1,r&&(i=2&a[0]?r.return:a[0]?r.throw||((i=r.return)&&i.call(r),0):r.next)&&!(i=i.call(r,a[1])).done)return i;switch(r=0,i&&(a=[2&a[0],i.value]),a[0]){case 0:case 1:i=a;break;case 4:return o.label++,{value:a[1],done:!1};case 5:o.label++,r=a[1],a=[0];continue;case 7:a=o.ops.pop(),o.trys.pop();continue;default:if(!(i=(i=o.trys).length>0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]r})},94927(e,t,n){function r(e,t){if(i("noDeprecation"))return e;var n=!1;function r(){if(!n){if(i("throwDeprecation"))throw Error(t);i("traceDeprecation")?console.trace(t):console.warn(t),n=!0}return e.apply(this,arguments)}return r}function i(e){try{if(!n.g.localStorage)return!1}catch(t){return!1}var r=n.g.localStorage[e];return null!=r&&"true"===String(r).toLowerCase()}e.exports=r},42473(e){"use strict";var t=function(){};e.exports=t},84763(e){e.exports=Worker},47529(e){e.exports=n;var t=Object.prototype.hasOwnProperty;function n(){for(var e={},n=0;ne.length)&&(t=e.length);for(var n=0,r=Array(t);n=0)&&Object.prototype.propertyIsEnumerable.call(e,n)&&(a[n]=e[n])}return a}e.exports=i,e.exports.__esModule=!0,e.exports.default=e.exports},7071(e){function t(e,t){if(null==e)return{};var n,r,i={},a=Object.keys(e);for(r=0;r=0||(i[n]=e[n]);return i}e.exports=t,e.exports.__esModule=!0,e.exports.default=e.exports},94993(e,t,n){var r=n(18698).default,i=n(66115);function a(e,t){if(t&&("object"===r(t)||"function"==typeof t))return t;if(void 0!==t)throw TypeError("Derived constructors may only return object or undefined");return i(e)}e.exports=a,e.exports.__esModule=!0,e.exports.default=e.exports},6015(e){function t(n,r){return e.exports=t=Object.setPrototypeOf?Object.setPrototypeOf.bind():function(e,t){return e.__proto__=t,e},e.exports.__esModule=!0,e.exports.default=e.exports,t(n,r)}e.exports=t,e.exports.__esModule=!0,e.exports.default=e.exports},861(e,t,n){var r=n(63405),i=n(79498),a=n(86116),o=n(42281);function s(e){return r(e)||i(e)||a(e)||o()}e.exports=s,e.exports.__esModule=!0,e.exports.default=e.exports},18698(e){function t(n){return e.exports=t="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},e.exports.__esModule=!0,e.exports.default=e.exports,t(n)}e.exports=t,e.exports.__esModule=!0,e.exports.default=e.exports},86116(e,t,n){var r=n(73897);function i(e,t){if(e){if("string"==typeof e)return r(e,t);var n=Object.prototype.toString.call(e).slice(8,-1);if("Object"===n&&e.constructor&&(n=e.constructor.name),"Map"===n||"Set"===n)return Array.from(e);if("Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n))return r(e,t)}}e.exports=i,e.exports.__esModule=!0,e.exports.default=e.exports},1644(e,t,n){"use strict";var r,i;function a(e){return!!e&&e<7}n.d(t,{I:()=>r,O:()=>a}),(i=r||(r={}))[i.loading=1]="loading",i[i.setVariables=2]="setVariables",i[i.fetchMore=3]="fetchMore",i[i.refetch=4]="refetch",i[i.poll=6]="poll",i[i.ready=7]="ready",i[i.error=8]="error"},30990(e,t,n){"use strict";n.d(t,{MS:()=>s,YG:()=>a,cA:()=>c,ls:()=>o});var r=n(70655);n(83952);var i=n(13154),a=Symbol();function o(e){return!!e.extensions&&Array.isArray(e.extensions[a])}function s(e){return e.hasOwnProperty("graphQLErrors")}var u=function(e){var t=(0,r.ev)((0,r.ev)((0,r.ev)([],e.graphQLErrors,!0),e.clientErrors,!0),e.protocolErrors,!0);return e.networkError&&t.push(e.networkError),t.map(function(e){return(0,i.s)(e)&&e.message||"Error message not found."}).join("\n")},c=function(e){function t(n){var r=n.graphQLErrors,i=n.protocolErrors,a=n.clientErrors,o=n.networkError,s=n.errorMessage,c=n.extraInfo,l=e.call(this,s)||this;return l.name="ApolloError",l.graphQLErrors=r||[],l.protocolErrors=i||[],l.clientErrors=a||[],l.networkError=o||null,l.message=s||u(l),l.extraInfo=c,l.__proto__=t.prototype,l}return(0,r.ZT)(t,e),t}(Error)},85317(e,t,n){"use strict";n.d(t,{K:()=>a});var r=n(67294),i=n(30320).aS?Symbol.for("__APOLLO_CONTEXT__"):"__APOLLO_CONTEXT__";function a(){var e=r.createContext[i];return e||(Object.defineProperty(r.createContext,i,{value:e=r.createContext({}),enumerable:!1,writable:!1,configurable:!0}),e.displayName="ApolloContext"),e}},21436(e,t,n){"use strict";n.d(t,{O:()=>i,k:()=>r});var r=Array.isArray;function i(e){return Array.isArray(e)&&e.length>0}},30320(e,t,n){"use strict";n.d(t,{DN:()=>s,JC:()=>l,aS:()=>o,mr:()=>i,sy:()=>a});var r=n(83952),i="function"==typeof WeakMap&&"ReactNative"!==(0,r.wY)(function(){return navigator.product}),a="function"==typeof WeakSet,o="function"==typeof Symbol&&"function"==typeof Symbol.for,s=o&&Symbol.asyncIterator,u="function"==typeof(0,r.wY)(function(){return window.document.createElement}),c=(0,r.wY)(function(){return navigator.userAgent.indexOf("jsdom")>=0})||!1,l=u&&!c},53712(e,t,n){"use strict";function r(){for(var e=[],t=0;tr})},10542(e,t,n){"use strict";n.d(t,{J:()=>o}),n(83952);var r=n(13154);function i(e){var t=new Set([e]);return t.forEach(function(e){(0,r.s)(e)&&a(e)===e&&Object.getOwnPropertyNames(e).forEach(function(n){(0,r.s)(e[n])&&t.add(e[n])})}),e}function a(e){if(__DEV__&&!Object.isFrozen(e))try{Object.freeze(e)}catch(t){if(t instanceof TypeError)return null;throw t}return e}function o(e){return __DEV__&&i(e),e}},14012(e,t,n){"use strict";n.d(t,{J:()=>a});var r=n(70655),i=n(53712);function a(e,t){return(0,i.o)(e,t,t.variables&&{variables:(0,r.pi)((0,r.pi)({},e&&e.variables),t.variables)})}},13154(e,t,n){"use strict";function r(e){return null!==e&&"object"==typeof e}n.d(t,{s:()=>r})},83952(e,t,n){"use strict";n.d(t,{ej:()=>u,kG:()=>c,wY:()=>h});var r,i=n(70655),a="Invariant Violation",o=Object.setPrototypeOf,s=void 0===o?function(e,t){return e.__proto__=t,e}:o,u=function(e){function t(n){void 0===n&&(n=a);var r=e.call(this,"number"==typeof n?a+": "+n+" (see https://github.com/apollographql/invariant-packages)":n)||this;return r.framesToPop=1,r.name=a,s(r,t.prototype),r}return(0,i.ZT)(t,e),t}(Error);function c(e,t){if(!e)throw new u(t)}var l=["debug","log","warn","error","silent"],f=l.indexOf("log");function d(e){return function(){if(l.indexOf(e)>=f)return(console[e]||console.log).apply(console,arguments)}}function h(e){try{return e()}catch(t){}}(r=c||(c={})).debug=d("debug"),r.log=d("log"),r.warn=d("warn"),r.error=d("error");let p=h(function(){return globalThis})||h(function(){return window})||h(function(){return self})||h(function(){return global})||h(function(){return h.constructor("return this")()});var b="__",m=[b,b].join("DEV");function g(){try{return Boolean(__DEV__)}catch(e){return Object.defineProperty(p,m,{value:"production"!==h(function(){return"production"}),enumerable:!1,configurable:!0,writable:!0}),p[m]}}let v=g();function y(e){try{return e()}catch(t){}}var w=y(function(){return globalThis})||y(function(){return window})||y(function(){return self})||y(function(){return global})||y(function(){return y.constructor("return this")()}),_=!1;function E(){!w||y(function(){return"production"})||y(function(){return process})||(Object.defineProperty(w,"process",{value:{env:{NODE_ENV:"production"}},configurable:!0,enumerable:!1,writable:!0}),_=!0)}function S(){_&&(delete w.process,_=!1)}E();var k=n(10143);function x(){return k.H,S()}function T(){__DEV__?c("boolean"==typeof v,v):c("boolean"==typeof v,39)}x(),T()},4942(e,t,n){"use strict";function r(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}n.d(t,{Z:()=>r})},87462(e,t,n){"use strict";function r(){return(r=Object.assign?Object.assign.bind():function(e){for(var t=1;tr})},51721(e,t,n){"use strict";function r(e,t){return(r=Object.setPrototypeOf?Object.setPrototypeOf.bind():function(e,t){return e.__proto__=t,e})(e,t)}function i(e,t){e.prototype=Object.create(t.prototype),e.prototype.constructor=e,r(e,t)}n.d(t,{Z:()=>i})},63366(e,t,n){"use strict";function r(e,t){if(null==e)return{};var n,r,i={},a=Object.keys(e);for(r=0;r=0||(i[n]=e[n]);return i}n.d(t,{Z:()=>r})},25821(e,t,n){"use strict";n.d(t,{Z:()=>s});var r=n(45695);function i(e){return(i="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e})(e)}var a=10,o=2;function s(e){return u(e,[])}function u(e,t){switch(i(e)){case"string":return JSON.stringify(e);case"function":return e.name?"[function ".concat(e.name,"]"):"[function]";case"object":if(null===e)return"null";return c(e,t);default:return String(e)}}function c(e,t){if(-1!==t.indexOf(e))return"[Circular]";var n=[].concat(t,[e]),r=d(e);if(void 0!==r){var i=r.call(e);if(i!==e)return"string"==typeof i?i:u(i,n)}else if(Array.isArray(e))return f(e,n);return l(e,n)}function l(e,t){var n=Object.keys(e);return 0===n.length?"{}":t.length>o?"["+h(e)+"]":"{ "+n.map(function(n){var r=u(e[n],t);return n+": "+r}).join(", ")+" }"}function f(e,t){if(0===e.length)return"[]";if(t.length>o)return"[Array]";for(var n=Math.min(a,e.length),r=e.length-n,i=[],s=0;s1&&i.push("... ".concat(r," more items")),"["+i.join(", ")+"]"}function d(e){var t=e[String(r.Z)];return"function"==typeof t?t:"function"==typeof e.inspect?e.inspect:void 0}function h(e){var t=Object.prototype.toString.call(e).replace(/^\[object /,"").replace(/]$/,"");if("Object"===t&&"function"==typeof e.constructor){var n=e.constructor.name;if("string"==typeof n&&""!==n)return n}return t}},45695(e,t,n){"use strict";n.d(t,{Z:()=>i});var r="function"==typeof Symbol&&"function"==typeof Symbol.for?Symbol.for("nodejs.util.inspect.custom"):void 0;let i=r},25217(e,t,n){"use strict";function r(e,t){if(!Boolean(e))throw Error(null!=t?t:"Unexpected invariant triggered.")}n.d(t,{Ye:()=>o,WU:()=>s,UG:()=>u});var i=n(45695);function a(e){var t=e.prototype.toJSON;"function"==typeof t||r(0),e.prototype.inspect=t,i.Z&&(e.prototype[i.Z]=t)}var o=function(){function e(e,t,n){this.start=e.start,this.end=t.end,this.startToken=e,this.endToken=t,this.source=n}return e.prototype.toJSON=function(){return{start:this.start,end:this.end}},e}();a(o);var s=function(){function e(e,t,n,r,i,a,o){this.kind=e,this.start=t,this.end=n,this.line=r,this.column=i,this.value=o,this.prev=a,this.next=null}return e.prototype.toJSON=function(){return{kind:this.kind,value:this.value,line:this.line,column:this.column}},e}();function u(e){return null!=e&&"string"==typeof e.kind}a(s)},87392(e,t,n){"use strict";function r(e){var t=e.split(/\r\n|[\n\r]/g),n=a(e);if(0!==n)for(var r=1;ro&&i(t[s-1]);)--s;return t.slice(o,s).join("\n")}function i(e){for(var t=0;t1&&void 0!==arguments[1]?arguments[1]:"",n=arguments.length>2&&void 0!==arguments[2]&&arguments[2],r=-1===e.indexOf("\n"),i=" "===e[0]||" "===e[0],a='"'===e[e.length-1],o="\\"===e[e.length-1],s=!r||a||o||n,u="";return s&&!(r&&i)&&(u+="\n"+t),u+=t?e.replace(/\n/g,"\n"+t):e,s&&(u+="\n"),'"""'+u.replace(/"""/g,'\\"""')+'"""'}n.d(t,{LZ:()=>o,W7:()=>r})},97359(e,t,n){"use strict";n.d(t,{h:()=>r});var r=Object.freeze({NAME:"Name",DOCUMENT:"Document",OPERATION_DEFINITION:"OperationDefinition",VARIABLE_DEFINITION:"VariableDefinition",SELECTION_SET:"SelectionSet",FIELD:"Field",ARGUMENT:"Argument",FRAGMENT_SPREAD:"FragmentSpread",INLINE_FRAGMENT:"InlineFragment",FRAGMENT_DEFINITION:"FragmentDefinition",VARIABLE:"Variable",INT:"IntValue",FLOAT:"FloatValue",STRING:"StringValue",BOOLEAN:"BooleanValue",NULL:"NullValue",ENUM:"EnumValue",LIST:"ListValue",OBJECT:"ObjectValue",OBJECT_FIELD:"ObjectField",DIRECTIVE:"Directive",NAMED_TYPE:"NamedType",LIST_TYPE:"ListType",NON_NULL_TYPE:"NonNullType",SCHEMA_DEFINITION:"SchemaDefinition",OPERATION_TYPE_DEFINITION:"OperationTypeDefinition",SCALAR_TYPE_DEFINITION:"ScalarTypeDefinition",OBJECT_TYPE_DEFINITION:"ObjectTypeDefinition",FIELD_DEFINITION:"FieldDefinition",INPUT_VALUE_DEFINITION:"InputValueDefinition",INTERFACE_TYPE_DEFINITION:"InterfaceTypeDefinition",UNION_TYPE_DEFINITION:"UnionTypeDefinition",ENUM_TYPE_DEFINITION:"EnumTypeDefinition",ENUM_VALUE_DEFINITION:"EnumValueDefinition",INPUT_OBJECT_TYPE_DEFINITION:"InputObjectTypeDefinition",DIRECTIVE_DEFINITION:"DirectiveDefinition",SCHEMA_EXTENSION:"SchemaExtension",SCALAR_TYPE_EXTENSION:"ScalarTypeExtension",OBJECT_TYPE_EXTENSION:"ObjectTypeExtension",INTERFACE_TYPE_EXTENSION:"InterfaceTypeExtension",UNION_TYPE_EXTENSION:"UnionTypeExtension",ENUM_TYPE_EXTENSION:"EnumTypeExtension",INPUT_OBJECT_TYPE_EXTENSION:"InputObjectTypeExtension"})},10143(e,t,n){"use strict";n.d(t,{H:()=>c,T:()=>l});var r=n(99763),i=n(25821);function a(e,t){if(!Boolean(e))throw Error(t)}let o=function(e,t){return e instanceof t};function s(e,t){for(var n=0;n1&&void 0!==arguments[1]?arguments[1]:"GraphQL request",n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{line:1,column:1};"string"==typeof e||a(0,"Body must be a string. Received: ".concat((0,i.Z)(e),".")),this.body=e,this.name=t,this.locationOffset=n,this.locationOffset.line>0||a(0,"line in locationOffset is 1-indexed and must be positive."),this.locationOffset.column>0||a(0,"column in locationOffset is 1-indexed and must be positive.")}return u(e,[{key:r.YF,get:function(){return"Source"}}]),e}();function l(e){return o(e,c)}},99763(e,t,n){"use strict";n.d(t,{YF:()=>r});var r="function"==typeof Symbol&&null!=Symbol.toStringTag?Symbol.toStringTag:"@@toStringTag"},37452(e){"use strict";e.exports=JSON.parse('{"AElig":"\xc6","AMP":"&","Aacute":"\xc1","Acirc":"\xc2","Agrave":"\xc0","Aring":"\xc5","Atilde":"\xc3","Auml":"\xc4","COPY":"\xa9","Ccedil":"\xc7","ETH":"\xd0","Eacute":"\xc9","Ecirc":"\xca","Egrave":"\xc8","Euml":"\xcb","GT":">","Iacute":"\xcd","Icirc":"\xce","Igrave":"\xcc","Iuml":"\xcf","LT":"<","Ntilde":"\xd1","Oacute":"\xd3","Ocirc":"\xd4","Ograve":"\xd2","Oslash":"\xd8","Otilde":"\xd5","Ouml":"\xd6","QUOT":"\\"","REG":"\xae","THORN":"\xde","Uacute":"\xda","Ucirc":"\xdb","Ugrave":"\xd9","Uuml":"\xdc","Yacute":"\xdd","aacute":"\xe1","acirc":"\xe2","acute":"\xb4","aelig":"\xe6","agrave":"\xe0","amp":"&","aring":"\xe5","atilde":"\xe3","auml":"\xe4","brvbar":"\xa6","ccedil":"\xe7","cedil":"\xb8","cent":"\xa2","copy":"\xa9","curren":"\xa4","deg":"\xb0","divide":"\xf7","eacute":"\xe9","ecirc":"\xea","egrave":"\xe8","eth":"\xf0","euml":"\xeb","frac12":"\xbd","frac14":"\xbc","frac34":"\xbe","gt":">","iacute":"\xed","icirc":"\xee","iexcl":"\xa1","igrave":"\xec","iquest":"\xbf","iuml":"\xef","laquo":"\xab","lt":"<","macr":"\xaf","micro":"\xb5","middot":"\xb7","nbsp":"\xa0","not":"\xac","ntilde":"\xf1","oacute":"\xf3","ocirc":"\xf4","ograve":"\xf2","ordf":"\xaa","ordm":"\xba","oslash":"\xf8","otilde":"\xf5","ouml":"\xf6","para":"\xb6","plusmn":"\xb1","pound":"\xa3","quot":"\\"","raquo":"\xbb","reg":"\xae","sect":"\xa7","shy":"\xad","sup1":"\xb9","sup2":"\xb2","sup3":"\xb3","szlig":"\xdf","thorn":"\xfe","times":"\xd7","uacute":"\xfa","ucirc":"\xfb","ugrave":"\xf9","uml":"\xa8","uuml":"\xfc","yacute":"\xfd","yen":"\xa5","yuml":"\xff"}')},93580(e){"use strict";e.exports=JSON.parse('{"0":"�","128":"€","130":"‚","131":"ƒ","132":"„","133":"…","134":"†","135":"‡","136":"ˆ","137":"‰","138":"Š","139":"‹","140":"Œ","142":"Ž","145":"‘","146":"’","147":"“","148":"”","149":"•","150":"–","151":"—","152":"˜","153":"™","154":"š","155":"›","156":"œ","158":"ž","159":"Ÿ"}')},67946(e){"use strict";e.exports=JSON.parse('{"locale":"en","long":{"year":{"previous":"last year","current":"this year","next":"next year","past":{"one":"{0} year ago","other":"{0} years ago"},"future":{"one":"in {0} year","other":"in {0} years"}},"quarter":{"previous":"last quarter","current":"this quarter","next":"next quarter","past":{"one":"{0} quarter ago","other":"{0} quarters ago"},"future":{"one":"in {0} quarter","other":"in {0} quarters"}},"month":{"previous":"last month","current":"this month","next":"next month","past":{"one":"{0} month ago","other":"{0} months ago"},"future":{"one":"in {0} month","other":"in {0} months"}},"week":{"previous":"last week","current":"this week","next":"next week","past":{"one":"{0} week ago","other":"{0} weeks ago"},"future":{"one":"in {0} week","other":"in {0} weeks"}},"day":{"previous":"yesterday","current":"today","next":"tomorrow","past":{"one":"{0} day ago","other":"{0} days ago"},"future":{"one":"in {0} day","other":"in {0} days"}},"hour":{"current":"this hour","past":{"one":"{0} hour ago","other":"{0} hours ago"},"future":{"one":"in {0} hour","other":"in {0} hours"}},"minute":{"current":"this minute","past":{"one":"{0} minute ago","other":"{0} minutes ago"},"future":{"one":"in {0} minute","other":"in {0} minutes"}},"second":{"current":"now","past":{"one":"{0} second ago","other":"{0} seconds ago"},"future":{"one":"in {0} second","other":"in {0} seconds"}}},"short":{"year":{"previous":"last yr.","current":"this yr.","next":"next yr.","past":"{0} yr. ago","future":"in {0} yr."},"quarter":{"previous":"last qtr.","current":"this qtr.","next":"next qtr.","past":{"one":"{0} qtr. ago","other":"{0} qtrs. ago"},"future":{"one":"in {0} qtr.","other":"in {0} qtrs."}},"month":{"previous":"last mo.","current":"this mo.","next":"next mo.","past":"{0} mo. ago","future":"in {0} mo."},"week":{"previous":"last wk.","current":"this wk.","next":"next wk.","past":"{0} wk. ago","future":"in {0} wk."},"day":{"previous":"yesterday","current":"today","next":"tomorrow","past":{"one":"{0} day ago","other":"{0} days ago"},"future":{"one":"in {0} day","other":"in {0} days"}},"hour":{"current":"this hour","past":"{0} hr. ago","future":"in {0} hr."},"minute":{"current":"this minute","past":"{0} min. ago","future":"in {0} min."},"second":{"current":"now","past":"{0} sec. ago","future":"in {0} sec."}},"narrow":{"year":{"previous":"last yr.","current":"this yr.","next":"next yr.","past":"{0} yr. ago","future":"in {0} yr."},"quarter":{"previous":"last qtr.","current":"this qtr.","next":"next qtr.","past":{"one":"{0} qtr. ago","other":"{0} qtrs. ago"},"future":{"one":"in {0} qtr.","other":"in {0} qtrs."}},"month":{"previous":"last mo.","current":"this mo.","next":"next mo.","past":"{0} mo. ago","future":"in {0} mo."},"week":{"previous":"last wk.","current":"this wk.","next":"next wk.","past":"{0} wk. ago","future":"in {0} wk."},"day":{"previous":"yesterday","current":"today","next":"tomorrow","past":{"one":"{0} day ago","other":"{0} days ago"},"future":{"one":"in {0} day","other":"in {0} days"}},"hour":{"current":"this hour","past":"{0} hr. ago","future":"in {0} hr."},"minute":{"current":"this minute","past":"{0} min. ago","future":"in {0} min."},"second":{"current":"now","past":"{0} sec. ago","future":"in {0} sec."}},"now":{"now":{"current":"now","future":"in a moment","past":"just now"}},"mini":{"year":"{0}yr","month":"{0}mo","week":"{0}wk","day":"{0}d","hour":"{0}h","minute":"{0}m","second":"{0}s","now":"now"},"short-time":{"year":"{0} yr.","month":"{0} mo.","week":"{0} wk.","day":{"one":"{0} day","other":"{0} days"},"hour":"{0} hr.","minute":"{0} min.","second":"{0} sec."},"long-time":{"year":{"one":"{0} year","other":"{0} years"},"month":{"one":"{0} month","other":"{0} months"},"week":{"one":"{0} week","other":"{0} weeks"},"day":{"one":"{0} day","other":"{0} days"},"hour":{"one":"{0} hour","other":"{0} hours"},"minute":{"one":"{0} minute","other":"{0} minutes"},"second":{"one":"{0} second","other":"{0} seconds"}}}')}},__webpack_module_cache__={};function __webpack_require__(e){var t=__webpack_module_cache__[e];if(void 0!==t)return t.exports;var n=__webpack_module_cache__[e]={id:e,loaded:!1,exports:{}};return __webpack_modules__[e].call(n.exports,n,n.exports,__webpack_require__),n.loaded=!0,n.exports}__webpack_require__.n=e=>{var t=e&&e.__esModule?()=>e.default:()=>e;return __webpack_require__.d(t,{a:t}),t},(()=>{var e,t=Object.getPrototypeOf?e=>Object.getPrototypeOf(e):e=>e.__proto__;__webpack_require__.t=function(n,r){if(1&r&&(n=this(n)),8&r||"object"==typeof n&&n&&(4&r&&n.__esModule||16&r&&"function"==typeof n.then))return n;var i=Object.create(null);__webpack_require__.r(i);var a={};e=e||[null,t({}),t([]),t(t)];for(var o=2&r&&n;"object"==typeof o&&!~e.indexOf(o);o=t(o))Object.getOwnPropertyNames(o).forEach(e=>a[e]=()=>n[e]);return a.default=()=>n,__webpack_require__.d(i,a),i}})(),__webpack_require__.d=(e,t)=>{for(var n in t)__webpack_require__.o(t,n)&&!__webpack_require__.o(e,n)&&Object.defineProperty(e,n,{enumerable:!0,get:t[n]})},__webpack_require__.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||Function("return this")()}catch(e){if("object"==typeof window)return window}}(),__webpack_require__.hmd=e=>((e=Object.create(e)).children||(e.children=[]),Object.defineProperty(e,"exports",{enumerable:!0,set(){throw Error("ES Modules may not assign module.exports or exports.*, Use ESM export syntax, instead: "+e.id)}}),e),__webpack_require__.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),__webpack_require__.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},__webpack_require__.nmd=e=>(e.paths=[],e.children||(e.children=[]),e),__webpack_require__.p="/assets/",__webpack_require__.nc=void 0;var __webpack_exports__={};(()=>{"use strict";var e,t,n,r,i=__webpack_require__(32316),a=__webpack_require__(8126),o=__webpack_require__(5690),s=__webpack_require__(30381),u=__webpack_require__.n(s),c=__webpack_require__(67294),l=__webpack_require__(73935),f=__webpack_require__.n(l),d=__webpack_require__(57209),h=__webpack_require__(37703),p=__webpack_require__(97779),b=__webpack_require__(28500);function m(e){return function(t){var n=t.dispatch,r=t.getState;return function(t){return function(i){return"function"==typeof i?i(n,r,e):t(i)}}}}var g=m();g.withExtraArgument=m;let v=g;var y=__webpack_require__(76489);function w(e){return function(t){return function(n){return function(r){n(r);var i=e||document&&document.cookie||"",a=t.getState();if("MATCH_ROUTE"===r.type&&"/signin"!==a.notifications.currentUrl){var o=(0,y.Q)(i);if(o.explorer)try{var s=JSON.parse(o.explorer);if("error"===s.status){var u=_(s.url);n({type:"NOTIFY_ERROR_MSG",msg:u})}}catch(c){n({type:"NOTIFY_ERROR_MSG",msg:"Invalid explorer status"})}}}}}}function _(e){var t="Can't connect to explorer: ".concat(e);return e.match(/^wss?:.+/)?t:"".concat(t,". You must use a websocket.")}var E=__webpack_require__(16353);function S(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n=e.length?{done:!0}:{done:!1,value:e[r++]}}}throw TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}function ei(e,t){if(e){if("string"==typeof e)return ea(e,t);var n=Object.prototype.toString.call(e).slice(8,-1);if("Object"===n&&e.constructor&&(n=e.constructor.name),"Map"===n||"Set"===n)return Array.from(e);if("Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n))return ea(e,t)}}function ea(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n1,i=!1,a=arguments[1],o=a;return new n(function(n){return t.subscribe({next:function(t){var a=!i;if(i=!0,!a||r)try{o=e(o,t)}catch(s){return n.error(s)}else o=t},error:function(e){n.error(e)},complete:function(){if(!i&&!r)return n.error(TypeError("Cannot reduce an empty sequence"));n.next(o),n.complete()}})})},t.concat=function(){for(var e=this,t=arguments.length,n=Array(t),r=0;r=0&&i.splice(e,1),o()}});i.push(s)},error:function(e){r.error(e)},complete:function(){o()}});function o(){a.closed&&0===i.length&&r.complete()}return function(){i.forEach(function(e){return e.unsubscribe()}),a.unsubscribe()}})},t[ed]=function(){return this},e.from=function(t){var n="function"==typeof this?this:e;if(null==t)throw TypeError(t+" is not an object");var r=ep(t,ed);if(r){var i=r.call(t);if(Object(i)!==i)throw TypeError(i+" is not an object");return em(i)&&i.constructor===n?i:new n(function(e){return i.subscribe(e)})}if(ec("iterator")&&(r=ep(t,ef)))return new n(function(e){ev(function(){if(!e.closed){for(var n,i=er(r.call(t));!(n=i()).done;){var a=n.value;if(e.next(a),e.closed)return}e.complete()}})});if(Array.isArray(t))return new n(function(e){ev(function(){if(!e.closed){for(var n=0;n0))return n.connection.key;var r=n.connection.filter?n.connection.filter:[];r.sort();var i={};return r.forEach(function(e){i[e]=t[e]}),"".concat(n.connection.key,"(").concat(eV(i),")")}var a=e;if(t){var o=eV(t);a+="(".concat(o,")")}return n&&Object.keys(n).forEach(function(e){-1===eW.indexOf(e)&&(n[e]&&Object.keys(n[e]).length?a+="@".concat(e,"(").concat(eV(n[e]),")"):a+="@".concat(e))}),a},{setStringify:function(e){var t=eV;return eV=e,t}}),eV=function(e){return JSON.stringify(e,eq)};function eq(e,t){return(0,eO.s)(t)&&!Array.isArray(t)&&(t=Object.keys(t).sort().reduce(function(e,n){return e[n]=t[n],e},{})),t}function eZ(e,t){if(e.arguments&&e.arguments.length){var n={};return e.arguments.forEach(function(e){var r;return ez(n,e.name,e.value,t)}),n}return null}function eX(e){return e.alias?e.alias.value:e.name.value}function eJ(e,t,n){for(var r,i=0,a=t.selections;it.indexOf(i))throw __DEV__?new Q.ej("illegal argument: ".concat(i)):new Q.ej(27)}return e}function tt(e,t){return t?t(e):eT.of()}function tn(e){return"function"==typeof e?new ta(e):e}function tr(e){return e.request.length<=1}var ti=function(e){function t(t,n){var r=e.call(this,t)||this;return r.link=n,r}return(0,en.ZT)(t,e),t}(Error),ta=function(){function e(e){e&&(this.request=e)}return e.empty=function(){return new e(function(){return eT.of()})},e.from=function(t){return 0===t.length?e.empty():t.map(tn).reduce(function(e,t){return e.concat(t)})},e.split=function(t,n,r){var i=tn(n),a=tn(r||new e(tt));return new e(tr(i)&&tr(a)?function(e){return t(e)?i.request(e)||eT.of():a.request(e)||eT.of()}:function(e,n){return t(e)?i.request(e,n)||eT.of():a.request(e,n)||eT.of()})},e.execute=function(e,t){return e.request(eM(t.context,e7(te(t))))||eT.of()},e.concat=function(t,n){var r=tn(t);if(tr(r))return __DEV__&&Q.kG.warn(new ti("You are calling concat on a terminating link, which will have no effect",r)),r;var i=tn(n);return new e(tr(i)?function(e){return r.request(e,function(e){return i.request(e)||eT.of()})||eT.of()}:function(e,t){return r.request(e,function(e){return i.request(e,t)||eT.of()})||eT.of()})},e.prototype.split=function(t,n,r){return this.concat(e.split(t,n,r||new e(tt)))},e.prototype.concat=function(t){return e.concat(this,t)},e.prototype.request=function(e,t){throw __DEV__?new Q.ej("request is not implemented"):new Q.ej(22)},e.prototype.onError=function(e,t){if(t&&t.error)return t.error(e),!1;throw e},e.prototype.setOnError=function(e){return this.onError=e,this},e}(),to=__webpack_require__(25821),ts=__webpack_require__(25217),tu={Name:[],Document:["definitions"],OperationDefinition:["name","variableDefinitions","directives","selectionSet"],VariableDefinition:["variable","type","defaultValue","directives"],Variable:["name"],SelectionSet:["selections"],Field:["alias","name","arguments","directives","selectionSet"],Argument:["name","value"],FragmentSpread:["name","directives"],InlineFragment:["typeCondition","directives","selectionSet"],FragmentDefinition:["name","variableDefinitions","typeCondition","directives","selectionSet"],IntValue:[],FloatValue:[],StringValue:[],BooleanValue:[],NullValue:[],EnumValue:[],ListValue:["values"],ObjectValue:["fields"],ObjectField:["name","value"],Directive:["name","arguments"],NamedType:["name"],ListType:["type"],NonNullType:["type"],SchemaDefinition:["description","directives","operationTypes"],OperationTypeDefinition:["type"],ScalarTypeDefinition:["description","name","directives"],ObjectTypeDefinition:["description","name","interfaces","directives","fields"],FieldDefinition:["description","name","arguments","type","directives"],InputValueDefinition:["description","name","type","defaultValue","directives"],InterfaceTypeDefinition:["description","name","interfaces","directives","fields"],UnionTypeDefinition:["description","name","directives","types"],EnumTypeDefinition:["description","name","directives","values"],EnumValueDefinition:["description","name","directives"],InputObjectTypeDefinition:["description","name","directives","fields"],DirectiveDefinition:["description","name","arguments","locations"],SchemaExtension:["directives","operationTypes"],ScalarTypeExtension:["name","directives"],ObjectTypeExtension:["name","interfaces","directives","fields"],InterfaceTypeExtension:["name","interfaces","directives","fields"],UnionTypeExtension:["name","directives","types"],EnumTypeExtension:["name","directives","values"],InputObjectTypeExtension:["name","directives","fields"]},tc=Object.freeze({});function tl(e,t){var n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:tu,r=void 0,i=Array.isArray(e),a=[e],o=-1,s=[],u=void 0,c=void 0,l=void 0,f=[],d=[],h=e;do{var p,b=++o===a.length,m=b&&0!==s.length;if(b){if(c=0===d.length?void 0:f[f.length-1],u=l,l=d.pop(),m){if(i)u=u.slice();else{for(var g={},v=0,y=Object.keys(u);v1)for(var r=new tB,i=1;i=0;--a){var o=i[a],s=isNaN(+o)?{}:[];s[o]=t,t=s}n=r.merge(n,t)}),n}var tW=Object.prototype.hasOwnProperty;function tK(e,t){var n,r,i,a,o;return(0,en.mG)(this,void 0,void 0,function(){var s,u,c,l,f,d,h,p,b,m,g,v,y,w,_,E,S,k,x,T,M,O,A;return(0,en.Jh)(this,function(L){switch(L.label){case 0:if(void 0===TextDecoder)throw Error("TextDecoder must be defined in the environment: please import a polyfill.");s=new TextDecoder("utf-8"),u=null===(n=e.headers)||void 0===n?void 0:n.get("content-type"),c="boundary=",l=(null==u?void 0:u.includes(c))?null==u?void 0:u.substring((null==u?void 0:u.indexOf(c))+c.length).replace(/['"]/g,"").replace(/\;(.*)/gm,"").trim():"-",f="\r\n--".concat(l),d="",h=tI(e),p=!0,L.label=1;case 1:if(!p)return[3,3];return[4,h.next()];case 2:for(m=(b=L.sent()).value,g=b.done,v="string"==typeof m?m:s.decode(m),y=d.length-f.length+1,p=!g,d+=v,w=d.indexOf(f,y);w>-1;){if(_=void 0,_=(O=[d.slice(0,w),d.slice(w+f.length),])[0],d=O[1],E=_.indexOf("\r\n\r\n"),(k=(S=tV(_.slice(0,E)))["content-type"])&&-1===k.toLowerCase().indexOf("application/json"))throw Error("Unsupported patch content type: application/json is required.");if(x=_.slice(E))try{T=tq(e,x),Object.keys(T).length>1||"data"in T||"incremental"in T||"errors"in T||"payload"in T?tz(T)?(M={},"payload"in T&&(M=(0,en.pi)({},T.payload)),"errors"in T&&(M=(0,en.pi)((0,en.pi)({},M),{extensions:(0,en.pi)((0,en.pi)({},"extensions"in M?M.extensions:null),((A={})[tN.YG]=T.errors,A))})),null===(r=t.next)||void 0===r||r.call(t,M)):null===(i=t.next)||void 0===i||i.call(t,T):1===Object.keys(T).length&&"hasNext"in T&&!T.hasNext&&(null===(a=t.complete)||void 0===a||a.call(t))}catch(C){tZ(C,t)}w=d.indexOf(f)}return[3,1];case 3:return null===(o=t.complete)||void 0===o||o.call(t),[2]}})})}function tV(e){var t={};return e.split("\n").forEach(function(e){var n=e.indexOf(":");if(n>-1){var r=e.slice(0,n).trim().toLowerCase(),i=e.slice(n+1).trim();t[r]=i}}),t}function tq(e,t){e.status>=300&&tD(e,function(){try{return JSON.parse(t)}catch(e){return t}}(),"Response not successful: Received status code ".concat(e.status));try{return JSON.parse(t)}catch(n){var r=n;throw r.name="ServerParseError",r.response=e,r.statusCode=e.status,r.bodyText=t,r}}function tZ(e,t){var n,r;"AbortError"!==e.name&&(e.result&&e.result.errors&&e.result.data&&(null===(n=t.next)||void 0===n||n.call(t,e.result)),null===(r=t.error)||void 0===r||r.call(t,e))}function tX(e,t,n){tJ(t)(e).then(function(e){var t,r;null===(t=n.next)||void 0===t||t.call(n,e),null===(r=n.complete)||void 0===r||r.call(n)}).catch(function(e){return tZ(e,n)})}function tJ(e){return function(t){return t.text().then(function(e){return tq(t,e)}).then(function(n){return t.status>=300&&tD(t,n,"Response not successful: Received status code ".concat(t.status)),Array.isArray(n)||tW.call(n,"data")||tW.call(n,"errors")||tD(t,n,"Server response was missing for query '".concat(Array.isArray(e)?e.map(function(e){return e.operationName}):e.operationName,"'.")),n})}}var tQ=function(e){if(!e&&"undefined"==typeof fetch)throw __DEV__?new Q.ej("\n\"fetch\" has not been found globally and no fetcher has been configured. To fix this, install a fetch package (like https://www.npmjs.com/package/cross-fetch), instantiate the fetcher, and pass it into your HttpLink constructor. For example:\n\nimport fetch from 'cross-fetch';\nimport { ApolloClient, HttpLink } from '@apollo/client';\nconst client = new ApolloClient({\n link: new HttpLink({ uri: '/graphql', fetch })\n});\n "):new Q.ej(23)},t1=__webpack_require__(87392);function t0(e){return tl(e,{leave:t3})}var t2=80,t3={Name:function(e){return e.value},Variable:function(e){return"$"+e.name},Document:function(e){return t6(e.definitions,"\n\n")+"\n"},OperationDefinition:function(e){var t=e.operation,n=e.name,r=t8("(",t6(e.variableDefinitions,", "),")"),i=t6(e.directives," "),a=e.selectionSet;return n||i||r||"query"!==t?t6([t,t6([n,r]),i,a]," "):a},VariableDefinition:function(e){var t=e.variable,n=e.type,r=e.defaultValue,i=e.directives;return t+": "+n+t8(" = ",r)+t8(" ",t6(i," "))},SelectionSet:function(e){return t5(e.selections)},Field:function(e){var t=e.alias,n=e.name,r=e.arguments,i=e.directives,a=e.selectionSet,o=t8("",t,": ")+n,s=o+t8("(",t6(r,", "),")");return s.length>t2&&(s=o+t8("(\n",t9(t6(r,"\n")),"\n)")),t6([s,t6(i," "),a]," ")},Argument:function(e){var t;return e.name+": "+e.value},FragmentSpread:function(e){var t;return"..."+e.name+t8(" ",t6(e.directives," "))},InlineFragment:function(e){var t=e.typeCondition,n=e.directives,r=e.selectionSet;return t6(["...",t8("on ",t),t6(n," "),r]," ")},FragmentDefinition:function(e){var t=e.name,n=e.typeCondition,r=e.variableDefinitions,i=e.directives,a=e.selectionSet;return"fragment ".concat(t).concat(t8("(",t6(r,", "),")")," ")+"on ".concat(n," ").concat(t8("",t6(i," ")," "))+a},IntValue:function(e){return e.value},FloatValue:function(e){return e.value},StringValue:function(e,t){var n=e.value;return e.block?(0,t1.LZ)(n,"description"===t?"":" "):JSON.stringify(n)},BooleanValue:function(e){return e.value?"true":"false"},NullValue:function(){return"null"},EnumValue:function(e){return e.value},ListValue:function(e){return"["+t6(e.values,", ")+"]"},ObjectValue:function(e){return"{"+t6(e.fields,", ")+"}"},ObjectField:function(e){var t;return e.name+": "+e.value},Directive:function(e){var t;return"@"+e.name+t8("(",t6(e.arguments,", "),")")},NamedType:function(e){return e.name},ListType:function(e){return"["+e.type+"]"},NonNullType:function(e){return e.type+"!"},SchemaDefinition:t4(function(e){var t=e.directives,n=e.operationTypes;return t6(["schema",t6(t," "),t5(n)]," ")}),OperationTypeDefinition:function(e){var t;return e.operation+": "+e.type},ScalarTypeDefinition:t4(function(e){var t;return t6(["scalar",e.name,t6(e.directives," ")]," ")}),ObjectTypeDefinition:t4(function(e){var t=e.name,n=e.interfaces,r=e.directives,i=e.fields;return t6(["type",t,t8("implements ",t6(n," & ")),t6(r," "),t5(i)]," ")}),FieldDefinition:t4(function(e){var t=e.name,n=e.arguments,r=e.type,i=e.directives;return t+(ne(n)?t8("(\n",t9(t6(n,"\n")),"\n)"):t8("(",t6(n,", "),")"))+": "+r+t8(" ",t6(i," "))}),InputValueDefinition:t4(function(e){var t=e.name,n=e.type,r=e.defaultValue,i=e.directives;return t6([t+": "+n,t8("= ",r),t6(i," ")]," ")}),InterfaceTypeDefinition:t4(function(e){var t=e.name,n=e.interfaces,r=e.directives,i=e.fields;return t6(["interface",t,t8("implements ",t6(n," & ")),t6(r," "),t5(i)]," ")}),UnionTypeDefinition:t4(function(e){var t=e.name,n=e.directives,r=e.types;return t6(["union",t,t6(n," "),r&&0!==r.length?"= "+t6(r," | "):""]," ")}),EnumTypeDefinition:t4(function(e){var t=e.name,n=e.directives,r=e.values;return t6(["enum",t,t6(n," "),t5(r)]," ")}),EnumValueDefinition:t4(function(e){var t;return t6([e.name,t6(e.directives," ")]," ")}),InputObjectTypeDefinition:t4(function(e){var t=e.name,n=e.directives,r=e.fields;return t6(["input",t,t6(n," "),t5(r)]," ")}),DirectiveDefinition:t4(function(e){var t=e.name,n=e.arguments,r=e.repeatable,i=e.locations;return"directive @"+t+(ne(n)?t8("(\n",t9(t6(n,"\n")),"\n)"):t8("(",t6(n,", "),")"))+(r?" repeatable":"")+" on "+t6(i," | ")}),SchemaExtension:function(e){var t=e.directives,n=e.operationTypes;return t6(["extend schema",t6(t," "),t5(n)]," ")},ScalarTypeExtension:function(e){var t;return t6(["extend scalar",e.name,t6(e.directives," ")]," ")},ObjectTypeExtension:function(e){var t=e.name,n=e.interfaces,r=e.directives,i=e.fields;return t6(["extend type",t,t8("implements ",t6(n," & ")),t6(r," "),t5(i)]," ")},InterfaceTypeExtension:function(e){var t=e.name,n=e.interfaces,r=e.directives,i=e.fields;return t6(["extend interface",t,t8("implements ",t6(n," & ")),t6(r," "),t5(i)]," ")},UnionTypeExtension:function(e){var t=e.name,n=e.directives,r=e.types;return t6(["extend union",t,t6(n," "),r&&0!==r.length?"= "+t6(r," | "):""]," ")},EnumTypeExtension:function(e){var t=e.name,n=e.directives,r=e.values;return t6(["extend enum",t,t6(n," "),t5(r)]," ")},InputObjectTypeExtension:function(e){var t=e.name,n=e.directives,r=e.fields;return t6(["extend input",t,t6(n," "),t5(r)]," ")}};function t4(e){return function(t){return t6([t.description,e(t)],"\n")}}function t6(e){var t,n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"";return null!==(t=null==e?void 0:e.filter(function(e){return e}).join(n))&&void 0!==t?t:""}function t5(e){return t8("{\n",t9(t6(e,"\n")),"\n}")}function t8(e,t){var n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:"";return null!=t&&""!==t?e+t+n:""}function t9(e){return t8(" ",e.replace(/\n/g,"\n "))}function t7(e){return -1!==e.indexOf("\n")}function ne(e){return null!=e&&e.some(t7)}var nt,nn,nr,ni={http:{includeQuery:!0,includeExtensions:!1,preserveHeaderCase:!1},headers:{accept:"*/*","content-type":"application/json"},options:{method:"POST"}},na=function(e,t){return t(e)};function no(e,t){for(var n=[],r=2;rObject.create(null),{forEach:nv,slice:ny}=Array.prototype,{hasOwnProperty:nw}=Object.prototype;class n_{constructor(e=!0,t=ng){this.weakness=e,this.makeData=t}lookup(...e){return this.lookupArray(e)}lookupArray(e){let t=this;return nv.call(e,e=>t=t.getChildTrie(e)),nw.call(t,"data")?t.data:t.data=this.makeData(ny.call(e))}peek(...e){return this.peekArray(e)}peekArray(e){let t=this;for(let n=0,r=e.length;t&&n=0;--o)t.definitions[o].kind===nL.h.OPERATION_DEFINITION&&++a;var s=nN(e),u=e.some(function(e){return e.remove}),c=function(e){return u&&e&&e.some(s)},l=new Map,f=!1,d={enter:function(e){if(c(e.directives))return f=!0,null}},h=tl(t,{Field:d,InlineFragment:d,VariableDefinition:{enter:function(){return!1}},Variable:{enter:function(e,t,n,r,a){var o=i(a);o&&o.variables.add(e.name.value)}},FragmentSpread:{enter:function(e,t,n,r,a){if(c(e.directives))return f=!0,null;var o=i(a);o&&o.fragmentSpreads.add(e.name.value)}},FragmentDefinition:{enter:function(e,t,n,r){l.set(JSON.stringify(r),e)},leave:function(e,t,n,i){return e===l.get(JSON.stringify(i))?e:a>0&&e.selectionSet.selections.every(function(e){return e.kind===nL.h.FIELD&&"__typename"===e.name.value})?(r(e.name.value).removed=!0,f=!0,null):void 0}},Directive:{leave:function(e){if(s(e))return f=!0,null}}});if(!f)return t;var p=function(e){return e.transitiveVars||(e.transitiveVars=new Set(e.variables),e.removed||e.fragmentSpreads.forEach(function(t){p(r(t)).transitiveVars.forEach(function(t){e.transitiveVars.add(t)})})),e},b=new Set;h.definitions.forEach(function(e){e.kind===nL.h.OPERATION_DEFINITION?p(n(e.name&&e.name.value)).fragmentSpreads.forEach(function(e){b.add(e)}):e.kind!==nL.h.FRAGMENT_DEFINITION||0!==a||r(e.name.value).removed||b.add(e.name.value)}),b.forEach(function(e){p(r(e)).fragmentSpreads.forEach(function(e){b.add(e)})});var m=function(e){return!!(!b.has(e)||r(e).removed)},g={enter:function(e){if(m(e.name.value))return null}};return nD(tl(h,{FragmentSpread:g,FragmentDefinition:g,OperationDefinition:{leave:function(e){if(e.variableDefinitions){var t=p(n(e.name&&e.name.value)).transitiveVars;if(t.size0},t.prototype.tearDownQuery=function(){this.isTornDown||(this.concast&&this.observer&&(this.concast.removeObserver(this.observer),delete this.concast,delete this.observer),this.stopPolling(),this.subscriptions.forEach(function(e){return e.unsubscribe()}),this.subscriptions.clear(),this.queryManager.stopQuery(this.queryId),this.observers.clear(),this.isTornDown=!0)},t}(eT);function n4(e){var t=e.options,n=t.fetchPolicy,r=t.nextFetchPolicy;return"cache-and-network"===n||"network-only"===n?e.reobserve({fetchPolicy:"cache-first",nextFetchPolicy:function(){return(this.nextFetchPolicy=r,"function"==typeof r)?r.apply(this,arguments):n}}):e.reobserve()}function n6(e){__DEV__&&Q.kG.error("Unhandled error",e.message,e.stack)}function n5(e){__DEV__&&e&&__DEV__&&Q.kG.debug("Missing cache result fields: ".concat(JSON.stringify(e)),e)}function n8(e){return"network-only"===e||"no-cache"===e||"standby"===e}nK(n3);function n9(e){return e.kind===nL.h.FIELD||e.kind===nL.h.FRAGMENT_SPREAD||e.kind===nL.h.INLINE_FRAGMENT}function n7(e){return e.kind===Kind.SCALAR_TYPE_DEFINITION||e.kind===Kind.OBJECT_TYPE_DEFINITION||e.kind===Kind.INTERFACE_TYPE_DEFINITION||e.kind===Kind.UNION_TYPE_DEFINITION||e.kind===Kind.ENUM_TYPE_DEFINITION||e.kind===Kind.INPUT_OBJECT_TYPE_DEFINITION}function re(e){return e.kind===Kind.SCALAR_TYPE_EXTENSION||e.kind===Kind.OBJECT_TYPE_EXTENSION||e.kind===Kind.INTERFACE_TYPE_EXTENSION||e.kind===Kind.UNION_TYPE_EXTENSION||e.kind===Kind.ENUM_TYPE_EXTENSION||e.kind===Kind.INPUT_OBJECT_TYPE_EXTENSION}var rt=function(){return Object.create(null)},rn=Array.prototype,rr=rn.forEach,ri=rn.slice,ra=function(){function e(e,t){void 0===e&&(e=!0),void 0===t&&(t=rt),this.weakness=e,this.makeData=t}return e.prototype.lookup=function(){for(var e=[],t=0;tclass{constructor(){this.id=["slot",rc++,Date.now(),Math.random().toString(36).slice(2),].join(":")}hasValue(){for(let e=rs;e;e=e.parent)if(this.id in e.slots){let t=e.slots[this.id];if(t===ru)break;return e!==rs&&(rs.slots[this.id]=t),!0}return rs&&(rs.slots[this.id]=ru),!1}getValue(){if(this.hasValue())return rs.slots[this.id]}withValue(e,t,n,r){let i={__proto__:null,[this.id]:e},a=rs;rs={parent:a,slots:i};try{return t.apply(r,n)}finally{rs=a}}static bind(e){let t=rs;return function(){let n=rs;try{return rs=t,e.apply(this,arguments)}finally{rs=n}}}static noContext(e,t,n){if(!rs)return e.apply(n,t);{let r=rs;try{return rs=null,e.apply(n,t)}finally{rs=r}}}};function rf(e){try{return e()}catch(t){}}let rd="@wry/context:Slot",rh=rf(()=>globalThis)||rf(()=>global)||Object.create(null),rp=rh,rb=rp[rd]||Array[rd]||function(e){try{Object.defineProperty(rp,rd,{value:e,enumerable:!1,writable:!1,configurable:!0})}finally{return e}}(rl()),{bind:rm,noContext:rg}=rb;function rv(){}var ry=function(){function e(e,t){void 0===e&&(e=1/0),void 0===t&&(t=rv),this.max=e,this.dispose=t,this.map=new Map,this.newest=null,this.oldest=null}return e.prototype.has=function(e){return this.map.has(e)},e.prototype.get=function(e){var t=this.getNode(e);return t&&t.value},e.prototype.getNode=function(e){var t=this.map.get(e);if(t&&t!==this.newest){var n=t.older,r=t.newer;r&&(r.older=n),n&&(n.newer=r),t.older=this.newest,t.older.newer=t,t.newer=null,this.newest=t,t===this.oldest&&(this.oldest=r)}return t},e.prototype.set=function(e,t){var n=this.getNode(e);return n?n.value=t:(n={key:e,value:t,newer:null,older:this.newest},this.newest&&(this.newest.newer=n),this.newest=n,this.oldest=this.oldest||n,this.map.set(e,n),n.value)},e.prototype.clean=function(){for(;this.oldest&&this.map.size>this.max;)this.delete(this.oldest.key)},e.prototype.delete=function(e){var t=this.map.get(e);return!!t&&(t===this.newest&&(this.newest=t.older),t===this.oldest&&(this.oldest=t.newer),t.newer&&(t.newer.older=t.older),t.older&&(t.older.newer=t.newer),this.map.delete(e),this.dispose(t.value,e),!0)},e}(),rw=new rb,r_=Object.prototype.hasOwnProperty,rE=void 0===(n=Array.from)?function(e){var t=[];return e.forEach(function(e){return t.push(e)}),t}:n;function rS(e){var t=e.unsubscribe;"function"==typeof t&&(e.unsubscribe=void 0,t())}var rk=[],rx=100;function rT(e,t){if(!e)throw Error(t||"assertion failure")}function rM(e,t){var n=e.length;return n>0&&n===t.length&&e[n-1]===t[n-1]}function rO(e){switch(e.length){case 0:throw Error("unknown value");case 1:return e[0];case 2:throw e[1]}}function rA(e){return e.slice(0)}var rL=function(){function e(t){this.fn=t,this.parents=new Set,this.childValues=new Map,this.dirtyChildren=null,this.dirty=!0,this.recomputing=!1,this.value=[],this.deps=null,++e.count}return e.prototype.peek=function(){if(1===this.value.length&&!rN(this))return rC(this),this.value[0]},e.prototype.recompute=function(e){return rT(!this.recomputing,"already recomputing"),rC(this),rN(this)?rI(this,e):rO(this.value)},e.prototype.setDirty=function(){this.dirty||(this.dirty=!0,this.value.length=0,rR(this),rS(this))},e.prototype.dispose=function(){var e=this;this.setDirty(),rH(this),rF(this,function(t,n){t.setDirty(),r$(t,e)})},e.prototype.forget=function(){this.dispose()},e.prototype.dependOn=function(e){e.add(this),this.deps||(this.deps=rk.pop()||new Set),this.deps.add(e)},e.prototype.forgetDeps=function(){var e=this;this.deps&&(rE(this.deps).forEach(function(t){return t.delete(e)}),this.deps.clear(),rk.push(this.deps),this.deps=null)},e.count=0,e}();function rC(e){var t=rw.getValue();if(t)return e.parents.add(t),t.childValues.has(e)||t.childValues.set(e,[]),rN(e)?rY(t,e):rB(t,e),t}function rI(e,t){return rH(e),rw.withValue(e,rD,[e,t]),rz(e,t)&&rP(e),rO(e.value)}function rD(e,t){e.recomputing=!0,e.value.length=0;try{e.value[0]=e.fn.apply(null,t)}catch(n){e.value[1]=n}e.recomputing=!1}function rN(e){return e.dirty||!!(e.dirtyChildren&&e.dirtyChildren.size)}function rP(e){e.dirty=!1,!rN(e)&&rj(e)}function rR(e){rF(e,rY)}function rj(e){rF(e,rB)}function rF(e,t){var n=e.parents.size;if(n)for(var r=rE(e.parents),i=0;i0&&e.childValues.forEach(function(t,n){r$(e,n)}),e.forgetDeps(),rT(null===e.dirtyChildren)}function r$(e,t){t.parents.delete(e),e.childValues.delete(t),rU(e,t)}function rz(e,t){if("function"==typeof e.subscribe)try{rS(e),e.unsubscribe=e.subscribe.apply(null,t)}catch(n){return e.setDirty(),!1}return!0}var rG={setDirty:!0,dispose:!0,forget:!0};function rW(e){var t=new Map,n=e&&e.subscribe;function r(e){var r=rw.getValue();if(r){var i=t.get(e);i||t.set(e,i=new Set),r.dependOn(i),"function"==typeof n&&(rS(i),i.unsubscribe=n(e))}}return r.dirty=function(e,n){var r=t.get(e);if(r){var i=n&&r_.call(rG,n)?n:"setDirty";rE(r).forEach(function(e){return e[i]()}),t.delete(e),rS(r)}},r}function rK(){var e=new ra("function"==typeof WeakMap);return function(){return e.lookupArray(arguments)}}var rV=rK(),rq=new Set;function rZ(e,t){void 0===t&&(t=Object.create(null));var n=new ry(t.max||65536,function(e){return e.dispose()}),r=t.keyArgs,i=t.makeCacheKey||rK(),a=function(){var a=i.apply(null,r?r.apply(null,arguments):arguments);if(void 0===a)return e.apply(null,arguments);var o=n.get(a);o||(n.set(a,o=new rL(e)),o.subscribe=t.subscribe,o.forget=function(){return n.delete(a)});var s=o.recompute(Array.prototype.slice.call(arguments));return n.set(a,o),rq.add(n),rw.hasValue()||(rq.forEach(function(e){return e.clean()}),rq.clear()),s};function o(e){var t=n.get(e);t&&t.setDirty()}function s(e){var t=n.get(e);if(t)return t.peek()}function u(e){return n.delete(e)}return Object.defineProperty(a,"size",{get:function(){return n.map.size},configurable:!1,enumerable:!1}),a.dirtyKey=o,a.dirty=function(){o(i.apply(null,arguments))},a.peekKey=s,a.peek=function(){return s(i.apply(null,arguments))},a.forgetKey=u,a.forget=function(){return u(i.apply(null,arguments))},a.makeCacheKey=i,a.getKey=r?function(){return i.apply(null,r.apply(null,arguments))}:i,Object.freeze(a)}var rX=new rb,rJ=new WeakMap;function rQ(e){var t=rJ.get(e);return t||rJ.set(e,t={vars:new Set,dep:rW()}),t}function r1(e){rQ(e).vars.forEach(function(t){return t.forgetCache(e)})}function r0(e){rQ(e).vars.forEach(function(t){return t.attachCache(e)})}function r2(e){var t=new Set,n=new Set,r=function(a){if(arguments.length>0){if(e!==a){e=a,t.forEach(function(e){rQ(e).dep.dirty(r),r3(e)});var o=Array.from(n);n.clear(),o.forEach(function(t){return t(e)})}}else{var s=rX.getValue();s&&(i(s),rQ(s).dep(r))}return e};r.onNextChange=function(e){return n.add(e),function(){n.delete(e)}};var i=r.attachCache=function(e){return t.add(e),rQ(e).vars.add(r),r};return r.forgetCache=function(e){return t.delete(e)},r}function r3(e){e.broadcastWatches&&e.broadcastWatches()}var r4=function(){function e(e){var t=e.cache,n=e.client,r=e.resolvers,i=e.fragmentMatcher;this.selectionsToResolveCache=new WeakMap,this.cache=t,n&&(this.client=n),r&&this.addResolvers(r),i&&this.setFragmentMatcher(i)}return e.prototype.addResolvers=function(e){var t=this;this.resolvers=this.resolvers||{},Array.isArray(e)?e.forEach(function(e){t.resolvers=tj(t.resolvers,e)}):this.resolvers=tj(this.resolvers,e)},e.prototype.setResolvers=function(e){this.resolvers={},this.addResolvers(e)},e.prototype.getResolvers=function(){return this.resolvers||{}},e.prototype.runResolvers=function(e){var t=e.document,n=e.remoteResult,r=e.context,i=e.variables,a=e.onlyRunForcedResolvers,o=void 0!==a&&a;return(0,en.mG)(this,void 0,void 0,function(){return(0,en.Jh)(this,function(e){return t?[2,this.resolveDocument(t,n.data,r,i,this.fragmentMatcher,o).then(function(e){return(0,en.pi)((0,en.pi)({},n),{data:e.result})})]:[2,n]})})},e.prototype.setFragmentMatcher=function(e){this.fragmentMatcher=e},e.prototype.getFragmentMatcher=function(){return this.fragmentMatcher},e.prototype.clientQuery=function(e){return tb(["client"],e)&&this.resolvers?e:null},e.prototype.serverQuery=function(e){return n$(e)},e.prototype.prepareContext=function(e){var t=this.cache;return(0,en.pi)((0,en.pi)({},e),{cache:t,getCacheKey:function(e){return t.identify(e)}})},e.prototype.addExportedVariables=function(e,t,n){return void 0===t&&(t={}),void 0===n&&(n={}),(0,en.mG)(this,void 0,void 0,function(){return(0,en.Jh)(this,function(r){return e?[2,this.resolveDocument(e,this.buildRootValueFromCache(e,t)||{},this.prepareContext(n),t).then(function(e){return(0,en.pi)((0,en.pi)({},t),e.exportedVariables)})]:[2,(0,en.pi)({},t)]})})},e.prototype.shouldForceResolvers=function(e){var t=!1;return tl(e,{Directive:{enter:function(e){if("client"===e.name.value&&e.arguments&&(t=e.arguments.some(function(e){return"always"===e.name.value&&"BooleanValue"===e.value.kind&&!0===e.value.value})))return tc}}}),t},e.prototype.buildRootValueFromCache=function(e,t){return this.cache.diff({query:nH(e),variables:t,returnPartialData:!0,optimistic:!1}).result},e.prototype.resolveDocument=function(e,t,n,r,i,a){return void 0===n&&(n={}),void 0===r&&(r={}),void 0===i&&(i=function(){return!0}),void 0===a&&(a=!1),(0,en.mG)(this,void 0,void 0,function(){var o,s,u,c,l,f,d,h,p,b,m;return(0,en.Jh)(this,function(g){return o=e8(e),s=e4(e),u=eL(s),c=this.collectSelectionsToResolve(o,u),f=(l=o.operation)?l.charAt(0).toUpperCase()+l.slice(1):"Query",d=this,h=d.cache,p=d.client,b={fragmentMap:u,context:(0,en.pi)((0,en.pi)({},n),{cache:h,client:p}),variables:r,fragmentMatcher:i,defaultOperationType:f,exportedVariables:{},selectionsToResolve:c,onlyRunForcedResolvers:a},m=!1,[2,this.resolveSelectionSet(o.selectionSet,m,t,b).then(function(e){return{result:e,exportedVariables:b.exportedVariables}})]})})},e.prototype.resolveSelectionSet=function(e,t,n,r){return(0,en.mG)(this,void 0,void 0,function(){var i,a,o,s,u,c=this;return(0,en.Jh)(this,function(l){return i=r.fragmentMap,a=r.context,o=r.variables,s=[n],u=function(e){return(0,en.mG)(c,void 0,void 0,function(){var u,c;return(0,en.Jh)(this,function(l){return(t||r.selectionsToResolve.has(e))&&td(e,o)?eQ(e)?[2,this.resolveField(e,t,n,r).then(function(t){var n;void 0!==t&&s.push(((n={})[eX(e)]=t,n))})]:(e1(e)?u=e:(u=i[e.name.value],__DEV__?(0,Q.kG)(u,"No fragment named ".concat(e.name.value)):(0,Q.kG)(u,11)),u&&u.typeCondition&&(c=u.typeCondition.name.value,r.fragmentMatcher(n,c,a)))?[2,this.resolveSelectionSet(u.selectionSet,t,n,r).then(function(e){s.push(e)})]:[2]:[2]})})},[2,Promise.all(e.selections.map(u)).then(function(){return tF(s)})]})})},e.prototype.resolveField=function(e,t,n,r){return(0,en.mG)(this,void 0,void 0,function(){var i,a,o,s,u,c,l,f,d,h=this;return(0,en.Jh)(this,function(p){return n?(i=r.variables,a=e.name.value,o=eX(e),s=a!==o,c=Promise.resolve(u=n[o]||n[a]),(!r.onlyRunForcedResolvers||this.shouldForceResolvers(e))&&(l=n.__typename||r.defaultOperationType,(f=this.resolvers&&this.resolvers[l])&&(d=f[s?a:o])&&(c=Promise.resolve(rX.withValue(this.cache,d,[n,eZ(e,i),r.context,{field:e,fragmentMap:r.fragmentMap},])))),[2,c.then(function(n){if(void 0===n&&(n=u),e.directives&&e.directives.forEach(function(e){"export"===e.name.value&&e.arguments&&e.arguments.forEach(function(e){"as"===e.name.value&&"StringValue"===e.value.kind&&(r.exportedVariables[e.value.value]=n)})}),!e.selectionSet||null==n)return n;var i,a,o=null!==(a=null===(i=e.directives)||void 0===i?void 0:i.some(function(e){return"client"===e.name.value}))&&void 0!==a&&a;return Array.isArray(n)?h.resolveSubSelectedArray(e,t||o,n,r):e.selectionSet?h.resolveSelectionSet(e.selectionSet,t||o,n,r):void 0})]):[2,null]})})},e.prototype.resolveSubSelectedArray=function(e,t,n,r){var i=this;return Promise.all(n.map(function(n){return null===n?null:Array.isArray(n)?i.resolveSubSelectedArray(e,t,n,r):e.selectionSet?i.resolveSelectionSet(e.selectionSet,t,n,r):void 0}))},e.prototype.collectSelectionsToResolve=function(e,t){var n=function(e){return!Array.isArray(e)},r=this.selectionsToResolveCache;function i(e){if(!r.has(e)){var a=new Set;r.set(e,a),tl(e,{Directive:function(e,t,r,i,o){"client"===e.name.value&&o.forEach(function(e){n(e)&&n9(e)&&a.add(e)})},FragmentSpread:function(e,r,o,s,u){var c=t[e.name.value];__DEV__?(0,Q.kG)(c,"No fragment named ".concat(e.name.value)):(0,Q.kG)(c,12);var l=i(c);l.size>0&&(u.forEach(function(e){n(e)&&n9(e)&&a.add(e)}),a.add(e),l.forEach(function(e){a.add(e)}))}})}return r.get(e)}return i(e)},e}(),r6=new(t_.mr?WeakMap:Map);function r5(e,t){var n=e[t];"function"==typeof n&&(e[t]=function(){return r6.set(e,(r6.get(e)+1)%1e15),n.apply(this,arguments)})}function r8(e){e.notifyTimeout&&(clearTimeout(e.notifyTimeout),e.notifyTimeout=void 0)}var r9=function(){function e(e,t){void 0===t&&(t=e.generateQueryId()),this.queryId=t,this.listeners=new Set,this.document=null,this.lastRequestId=1,this.subscriptions=new Set,this.stopped=!1,this.dirty=!1,this.observableQuery=null;var n=this.cache=e.cache;r6.has(n)||(r6.set(n,0),r5(n,"evict"),r5(n,"modify"),r5(n,"reset"))}return e.prototype.init=function(e){var t=e.networkStatus||nZ.I.loading;return this.variables&&this.networkStatus!==nZ.I.loading&&!(0,nm.D)(this.variables,e.variables)&&(t=nZ.I.setVariables),(0,nm.D)(e.variables,this.variables)||(this.lastDiff=void 0),Object.assign(this,{document:e.document,variables:e.variables,networkError:null,graphQLErrors:this.graphQLErrors||[],networkStatus:t}),e.observableQuery&&this.setObservableQuery(e.observableQuery),e.lastRequestId&&(this.lastRequestId=e.lastRequestId),this},e.prototype.reset=function(){r8(this),this.dirty=!1},e.prototype.getDiff=function(e){void 0===e&&(e=this.variables);var t=this.getDiffOptions(e);if(this.lastDiff&&(0,nm.D)(t,this.lastDiff.options))return this.lastDiff.diff;this.updateWatch(this.variables=e);var n=this.observableQuery;if(n&&"no-cache"===n.options.fetchPolicy)return{complete:!1};var r=this.cache.diff(t);return this.updateLastDiff(r,t),r},e.prototype.updateLastDiff=function(e,t){this.lastDiff=e?{diff:e,options:t||this.getDiffOptions()}:void 0},e.prototype.getDiffOptions=function(e){var t;return void 0===e&&(e=this.variables),{query:this.document,variables:e,returnPartialData:!0,optimistic:!0,canonizeResults:null===(t=this.observableQuery)||void 0===t?void 0:t.options.canonizeResults}},e.prototype.setDiff=function(e){var t=this,n=this.lastDiff&&this.lastDiff.diff;this.updateLastDiff(e),this.dirty||(0,nm.D)(n&&n.result,e&&e.result)||(this.dirty=!0,this.notifyTimeout||(this.notifyTimeout=setTimeout(function(){return t.notify()},0)))},e.prototype.setObservableQuery=function(e){var t=this;e!==this.observableQuery&&(this.oqListener&&this.listeners.delete(this.oqListener),this.observableQuery=e,e?(e.queryInfo=this,this.listeners.add(this.oqListener=function(){t.getDiff().fromOptimisticTransaction?e.observe():n4(e)})):delete this.oqListener)},e.prototype.notify=function(){var e=this;r8(this),this.shouldNotify()&&this.listeners.forEach(function(t){return t(e)}),this.dirty=!1},e.prototype.shouldNotify=function(){if(!this.dirty||!this.listeners.size)return!1;if((0,nZ.O)(this.networkStatus)&&this.observableQuery){var e=this.observableQuery.options.fetchPolicy;if("cache-only"!==e&&"cache-and-network"!==e)return!1}return!0},e.prototype.stop=function(){if(!this.stopped){this.stopped=!0,this.reset(),this.cancel(),this.cancel=e.prototype.cancel,this.subscriptions.forEach(function(e){return e.unsubscribe()});var t=this.observableQuery;t&&t.stopPolling()}},e.prototype.cancel=function(){},e.prototype.updateWatch=function(e){var t=this;void 0===e&&(e=this.variables);var n=this.observableQuery;if(!n||"no-cache"!==n.options.fetchPolicy){var r=(0,en.pi)((0,en.pi)({},this.getDiffOptions(e)),{watcher:this,callback:function(e){return t.setDiff(e)}});this.lastWatch&&(0,nm.D)(r,this.lastWatch)||(this.cancel(),this.cancel=this.cache.watch(this.lastWatch=r))}},e.prototype.resetLastWrite=function(){this.lastWrite=void 0},e.prototype.shouldWrite=function(e,t){var n=this.lastWrite;return!(n&&n.dmCount===r6.get(this.cache)&&(0,nm.D)(t,n.variables)&&(0,nm.D)(e.data,n.result.data))},e.prototype.markResult=function(e,t,n,r){var i=this,a=new tB,o=(0,tP.O)(e.errors)?e.errors.slice(0):[];if(this.reset(),"incremental"in e&&(0,tP.O)(e.incremental)){var s=tG(this.getDiff().result,e);e.data=s}else if("hasNext"in e&&e.hasNext){var u=this.getDiff();e.data=a.merge(u.result,e.data)}this.graphQLErrors=o,"no-cache"===n.fetchPolicy?this.updateLastDiff({result:e.data,complete:!0},this.getDiffOptions(n.variables)):0!==r&&(r7(e,n.errorPolicy)?this.cache.performTransaction(function(a){if(i.shouldWrite(e,n.variables))a.writeQuery({query:t,data:e.data,variables:n.variables,overwrite:1===r}),i.lastWrite={result:e,variables:n.variables,dmCount:r6.get(i.cache)};else if(i.lastDiff&&i.lastDiff.diff.complete){e.data=i.lastDiff.diff.result;return}var o=i.getDiffOptions(n.variables),s=a.diff(o);i.stopped||i.updateWatch(n.variables),i.updateLastDiff(s,o),s.complete&&(e.data=s.result)}):this.lastWrite=void 0)},e.prototype.markReady=function(){return this.networkError=null,this.networkStatus=nZ.I.ready},e.prototype.markError=function(e){return this.networkStatus=nZ.I.error,this.lastWrite=void 0,this.reset(),e.graphQLErrors&&(this.graphQLErrors=e.graphQLErrors),e.networkError&&(this.networkError=e.networkError),e},e}();function r7(e,t){void 0===t&&(t="none");var n="ignore"===t||"all"===t,r=!nO(e);return!r&&n&&e.data&&(r=!0),r}var ie=Object.prototype.hasOwnProperty,it=function(){function e(e){var t=e.cache,n=e.link,r=e.defaultOptions,i=e.queryDeduplication,a=void 0!==i&&i,o=e.onBroadcast,s=e.ssrMode,u=void 0!==s&&s,c=e.clientAwareness,l=void 0===c?{}:c,f=e.localState,d=e.assumeImmutableResults;this.clientAwareness={},this.queries=new Map,this.fetchCancelFns=new Map,this.transformCache=new(t_.mr?WeakMap:Map),this.queryIdCounter=1,this.requestIdCounter=1,this.mutationIdCounter=1,this.inFlightLinkObservables=new Map,this.cache=t,this.link=n,this.defaultOptions=r||Object.create(null),this.queryDeduplication=a,this.clientAwareness=l,this.localState=f||new r4({cache:t}),this.ssrMode=u,this.assumeImmutableResults=!!d,(this.onBroadcast=o)&&(this.mutationStore=Object.create(null))}return e.prototype.stop=function(){var e=this;this.queries.forEach(function(t,n){e.stopQueryNoBroadcast(n)}),this.cancelPendingFetches(__DEV__?new Q.ej("QueryManager stopped while query was in flight"):new Q.ej(14))},e.prototype.cancelPendingFetches=function(e){this.fetchCancelFns.forEach(function(t){return t(e)}),this.fetchCancelFns.clear()},e.prototype.mutate=function(e){var t,n,r=e.mutation,i=e.variables,a=e.optimisticResponse,o=e.updateQueries,s=e.refetchQueries,u=void 0===s?[]:s,c=e.awaitRefetchQueries,l=void 0!==c&&c,f=e.update,d=e.onQueryUpdated,h=e.fetchPolicy,p=void 0===h?(null===(t=this.defaultOptions.mutate)||void 0===t?void 0:t.fetchPolicy)||"network-only":h,b=e.errorPolicy,m=void 0===b?(null===(n=this.defaultOptions.mutate)||void 0===n?void 0:n.errorPolicy)||"none":b,g=e.keepRootFields,v=e.context;return(0,en.mG)(this,void 0,void 0,function(){var e,t,n,s,c,h;return(0,en.Jh)(this,function(b){switch(b.label){case 0:if(__DEV__?(0,Q.kG)(r,"mutation option is required. You must specify your GraphQL document in the mutation option."):(0,Q.kG)(r,15),__DEV__?(0,Q.kG)("network-only"===p||"no-cache"===p,"Mutations support only 'network-only' or 'no-cache' fetchPolicy strings. The default `network-only` behavior automatically writes mutation results to the cache. Passing `no-cache` skips the cache write."):(0,Q.kG)("network-only"===p||"no-cache"===p,16),e=this.generateMutationId(),n=(t=this.transform(r)).document,s=t.hasClientExports,r=this.cache.transformForLink(n),i=this.getVariables(r,i),!s)return[3,2];return[4,this.localState.addExportedVariables(r,i,v)];case 1:i=b.sent(),b.label=2;case 2:return c=this.mutationStore&&(this.mutationStore[e]={mutation:r,variables:i,loading:!0,error:null}),a&&this.markMutationOptimistic(a,{mutationId:e,document:r,variables:i,fetchPolicy:p,errorPolicy:m,context:v,updateQueries:o,update:f,keepRootFields:g}),this.broadcastQueries(),h=this,[2,new Promise(function(t,n){return nM(h.getObservableFromLink(r,(0,en.pi)((0,en.pi)({},v),{optimisticResponse:a}),i,!1),function(t){if(nO(t)&&"none"===m)throw new tN.cA({graphQLErrors:nA(t)});c&&(c.loading=!1,c.error=null);var n=(0,en.pi)({},t);return"function"==typeof u&&(u=u(n)),"ignore"===m&&nO(n)&&delete n.errors,h.markMutationResult({mutationId:e,result:n,document:r,variables:i,fetchPolicy:p,errorPolicy:m,context:v,update:f,updateQueries:o,awaitRefetchQueries:l,refetchQueries:u,removeOptimistic:a?e:void 0,onQueryUpdated:d,keepRootFields:g})}).subscribe({next:function(e){h.broadcastQueries(),"hasNext"in e&&!1!==e.hasNext||t(e)},error:function(t){c&&(c.loading=!1,c.error=t),a&&h.cache.removeOptimistic(e),h.broadcastQueries(),n(t instanceof tN.cA?t:new tN.cA({networkError:t}))}})})]}})})},e.prototype.markMutationResult=function(e,t){var n=this;void 0===t&&(t=this.cache);var r=e.result,i=[],a="no-cache"===e.fetchPolicy;if(!a&&r7(r,e.errorPolicy)){if(tU(r)||i.push({result:r.data,dataId:"ROOT_MUTATION",query:e.document,variables:e.variables}),tU(r)&&(0,tP.O)(r.incremental)){var o=t.diff({id:"ROOT_MUTATION",query:this.transform(e.document).asQuery,variables:e.variables,optimistic:!1,returnPartialData:!0}),s=void 0;o.result&&(s=tG(o.result,r)),void 0!==s&&(r.data=s,i.push({result:s,dataId:"ROOT_MUTATION",query:e.document,variables:e.variables}))}var u=e.updateQueries;u&&this.queries.forEach(function(e,a){var o=e.observableQuery,s=o&&o.queryName;if(s&&ie.call(u,s)){var c,l=u[s],f=n.queries.get(a),d=f.document,h=f.variables,p=t.diff({query:d,variables:h,returnPartialData:!0,optimistic:!1}),b=p.result;if(p.complete&&b){var m=l(b,{mutationResult:r,queryName:d&&e3(d)||void 0,queryVariables:h});m&&i.push({result:m,dataId:"ROOT_QUERY",query:d,variables:h})}}})}if(i.length>0||e.refetchQueries||e.update||e.onQueryUpdated||e.removeOptimistic){var c=[];if(this.refetchQueries({updateCache:function(t){a||i.forEach(function(e){return t.write(e)});var o=e.update,s=!t$(r)||tU(r)&&!r.hasNext;if(o){if(!a){var u=t.diff({id:"ROOT_MUTATION",query:n.transform(e.document).asQuery,variables:e.variables,optimistic:!1,returnPartialData:!0});u.complete&&("incremental"in(r=(0,en.pi)((0,en.pi)({},r),{data:u.result}))&&delete r.incremental,"hasNext"in r&&delete r.hasNext)}s&&o(t,r,{context:e.context,variables:e.variables})}a||e.keepRootFields||!s||t.modify({id:"ROOT_MUTATION",fields:function(e,t){var n=t.fieldName,r=t.DELETE;return"__typename"===n?e:r}})},include:e.refetchQueries,optimistic:!1,removeOptimistic:e.removeOptimistic,onQueryUpdated:e.onQueryUpdated||null}).forEach(function(e){return c.push(e)}),e.awaitRefetchQueries||e.onQueryUpdated)return Promise.all(c).then(function(){return r})}return Promise.resolve(r)},e.prototype.markMutationOptimistic=function(e,t){var n=this,r="function"==typeof e?e(t.variables):e;return this.cache.recordOptimisticTransaction(function(e){try{n.markMutationResult((0,en.pi)((0,en.pi)({},t),{result:{data:r}}),e)}catch(i){__DEV__&&Q.kG.error(i)}},t.mutationId)},e.prototype.fetchQuery=function(e,t,n){return this.fetchQueryObservable(e,t,n).promise},e.prototype.getQueryStore=function(){var e=Object.create(null);return this.queries.forEach(function(t,n){e[n]={variables:t.variables,networkStatus:t.networkStatus,networkError:t.networkError,graphQLErrors:t.graphQLErrors}}),e},e.prototype.resetErrors=function(e){var t=this.queries.get(e);t&&(t.networkError=void 0,t.graphQLErrors=[])},e.prototype.transform=function(e){var t=this.transformCache;if(!t.has(e)){var n=this.cache.transformDocument(e),r=nY(n),i=this.localState.clientQuery(n),a=r&&this.localState.serverQuery(r),o={document:n,hasClientExports:tm(n),hasForcedResolvers:this.localState.shouldForceResolvers(n),clientQuery:i,serverQuery:a,defaultVars:e9(e2(n)),asQuery:(0,en.pi)((0,en.pi)({},n),{definitions:n.definitions.map(function(e){return"OperationDefinition"===e.kind&&"query"!==e.operation?(0,en.pi)((0,en.pi)({},e),{operation:"query"}):e})})},s=function(e){e&&!t.has(e)&&t.set(e,o)};s(e),s(n),s(i),s(a)}return t.get(e)},e.prototype.getVariables=function(e,t){return(0,en.pi)((0,en.pi)({},this.transform(e).defaultVars),t)},e.prototype.watchQuery=function(e){void 0===(e=(0,en.pi)((0,en.pi)({},e),{variables:this.getVariables(e.query,e.variables)})).notifyOnNetworkStatusChange&&(e.notifyOnNetworkStatusChange=!1);var t=new r9(this),n=new n3({queryManager:this,queryInfo:t,options:e});return this.queries.set(n.queryId,t),t.init({document:n.query,observableQuery:n,variables:n.variables}),n},e.prototype.query=function(e,t){var n=this;return void 0===t&&(t=this.generateQueryId()),__DEV__?(0,Q.kG)(e.query,"query option is required. You must specify your GraphQL document in the query option."):(0,Q.kG)(e.query,17),__DEV__?(0,Q.kG)("Document"===e.query.kind,'You must wrap the query string in a "gql" tag.'):(0,Q.kG)("Document"===e.query.kind,18),__DEV__?(0,Q.kG)(!e.returnPartialData,"returnPartialData option only supported on watchQuery."):(0,Q.kG)(!e.returnPartialData,19),__DEV__?(0,Q.kG)(!e.pollInterval,"pollInterval option only supported on watchQuery."):(0,Q.kG)(!e.pollInterval,20),this.fetchQuery(t,e).finally(function(){return n.stopQuery(t)})},e.prototype.generateQueryId=function(){return String(this.queryIdCounter++)},e.prototype.generateRequestId=function(){return this.requestIdCounter++},e.prototype.generateMutationId=function(){return String(this.mutationIdCounter++)},e.prototype.stopQueryInStore=function(e){this.stopQueryInStoreNoBroadcast(e),this.broadcastQueries()},e.prototype.stopQueryInStoreNoBroadcast=function(e){var t=this.queries.get(e);t&&t.stop()},e.prototype.clearStore=function(e){return void 0===e&&(e={discardWatches:!0}),this.cancelPendingFetches(__DEV__?new Q.ej("Store reset while query was in flight (not completed in link chain)"):new Q.ej(21)),this.queries.forEach(function(e){e.observableQuery?e.networkStatus=nZ.I.loading:e.stop()}),this.mutationStore&&(this.mutationStore=Object.create(null)),this.cache.reset(e)},e.prototype.getObservableQueries=function(e){var t=this;void 0===e&&(e="active");var n=new Map,r=new Map,i=new Set;return Array.isArray(e)&&e.forEach(function(e){"string"==typeof e?r.set(e,!1):eN(e)?r.set(t.transform(e).document,!1):(0,eO.s)(e)&&e.query&&i.add(e)}),this.queries.forEach(function(t,i){var a=t.observableQuery,o=t.document;if(a){if("all"===e){n.set(i,a);return}var s=a.queryName;if("standby"===a.options.fetchPolicy||"active"===e&&!a.hasObservers())return;("active"===e||s&&r.has(s)||o&&r.has(o))&&(n.set(i,a),s&&r.set(s,!0),o&&r.set(o,!0))}}),i.size&&i.forEach(function(e){var r=nG("legacyOneTimeQuery"),i=t.getQuery(r).init({document:e.query,variables:e.variables}),a=new n3({queryManager:t,queryInfo:i,options:(0,en.pi)((0,en.pi)({},e),{fetchPolicy:"network-only"})});(0,Q.kG)(a.queryId===r),i.setObservableQuery(a),n.set(r,a)}),__DEV__&&r.size&&r.forEach(function(e,t){!e&&__DEV__&&Q.kG.warn("Unknown query ".concat("string"==typeof t?"named ":"").concat(JSON.stringify(t,null,2)," requested in refetchQueries options.include array"))}),n},e.prototype.reFetchObservableQueries=function(e){var t=this;void 0===e&&(e=!1);var n=[];return this.getObservableQueries(e?"all":"active").forEach(function(r,i){var a=r.options.fetchPolicy;r.resetLastResults(),(e||"standby"!==a&&"cache-only"!==a)&&n.push(r.refetch()),t.getQuery(i).setDiff(null)}),this.broadcastQueries(),Promise.all(n)},e.prototype.setObservableQuery=function(e){this.getQuery(e.queryId).setObservableQuery(e)},e.prototype.startGraphQLSubscription=function(e){var t=this,n=e.query,r=e.fetchPolicy,i=e.errorPolicy,a=e.variables,o=e.context,s=void 0===o?{}:o;n=this.transform(n).document,a=this.getVariables(n,a);var u=function(e){return t.getObservableFromLink(n,s,e).map(function(a){"no-cache"!==r&&(r7(a,i)&&t.cache.write({query:n,result:a.data,dataId:"ROOT_SUBSCRIPTION",variables:e}),t.broadcastQueries());var o=nO(a),s=(0,tN.ls)(a);if(o||s){var u={};throw o&&(u.graphQLErrors=a.errors),s&&(u.protocolErrors=a.extensions[tN.YG]),new tN.cA(u)}return a})};if(this.transform(n).hasClientExports){var c=this.localState.addExportedVariables(n,a,s).then(u);return new eT(function(e){var t=null;return c.then(function(n){return t=n.subscribe(e)},e.error),function(){return t&&t.unsubscribe()}})}return u(a)},e.prototype.stopQuery=function(e){this.stopQueryNoBroadcast(e),this.broadcastQueries()},e.prototype.stopQueryNoBroadcast=function(e){this.stopQueryInStoreNoBroadcast(e),this.removeQuery(e)},e.prototype.removeQuery=function(e){this.fetchCancelFns.delete(e),this.queries.has(e)&&(this.getQuery(e).stop(),this.queries.delete(e))},e.prototype.broadcastQueries=function(){this.onBroadcast&&this.onBroadcast(),this.queries.forEach(function(e){return e.notify()})},e.prototype.getLocalState=function(){return this.localState},e.prototype.getObservableFromLink=function(e,t,n,r){var i,a,o=this;void 0===r&&(r=null!==(i=null==t?void 0:t.queryDeduplication)&&void 0!==i?i:this.queryDeduplication);var s=this.transform(e).serverQuery;if(s){var u=this,c=u.inFlightLinkObservables,l=u.link,f={query:s,variables:n,operationName:e3(s)||void 0,context:this.prepareContext((0,en.pi)((0,en.pi)({},t),{forceFetch:!r}))};if(t=f.context,r){var d=c.get(s)||new Map;c.set(s,d);var h=nx(n);if(!(a=d.get(h))){var p=new nq([np(l,f)]);d.set(h,a=p),p.beforeNext(function(){d.delete(h)&&d.size<1&&c.delete(s)})}}else a=new nq([np(l,f)])}else a=new nq([eT.of({data:{}})]),t=this.prepareContext(t);var b=this.transform(e).clientQuery;return b&&(a=nM(a,function(e){return o.localState.runResolvers({document:b,remoteResult:e,context:t,variables:n})})),a},e.prototype.getResultsFromLink=function(e,t,n){var r=e.lastRequestId=this.generateRequestId(),i=this.cache.transformForLink(this.transform(e.document).document);return nM(this.getObservableFromLink(i,n.context,n.variables),function(a){var o=nA(a),s=o.length>0;if(r>=e.lastRequestId){if(s&&"none"===n.errorPolicy)throw e.markError(new tN.cA({graphQLErrors:o}));e.markResult(a,i,n,t),e.markReady()}var u={data:a.data,loading:!1,networkStatus:nZ.I.ready};return s&&"ignore"!==n.errorPolicy&&(u.errors=o,u.networkStatus=nZ.I.error),u},function(t){var n=(0,tN.MS)(t)?t:new tN.cA({networkError:t});throw r>=e.lastRequestId&&e.markError(n),n})},e.prototype.fetchQueryObservable=function(e,t,n){return this.fetchConcastWithInfo(e,t,n).concast},e.prototype.fetchConcastWithInfo=function(e,t,n){var r,i,a=this;void 0===n&&(n=nZ.I.loading);var o=this.transform(t.query).document,s=this.getVariables(o,t.variables),u=this.getQuery(e),c=this.defaultOptions.watchQuery,l=t.fetchPolicy,f=void 0===l?c&&c.fetchPolicy||"cache-first":l,d=t.errorPolicy,h=void 0===d?c&&c.errorPolicy||"none":d,p=t.returnPartialData,b=void 0!==p&&p,m=t.notifyOnNetworkStatusChange,g=void 0!==m&&m,v=t.context,y=void 0===v?{}:v,w=Object.assign({},t,{query:o,variables:s,fetchPolicy:f,errorPolicy:h,returnPartialData:b,notifyOnNetworkStatusChange:g,context:y}),_=function(e){w.variables=e;var r=a.fetchQueryByPolicy(u,w,n);return"standby"!==w.fetchPolicy&&r.sources.length>0&&u.observableQuery&&u.observableQuery.applyNextFetchPolicy("after-fetch",t),r},E=function(){return a.fetchCancelFns.delete(e)};if(this.fetchCancelFns.set(e,function(e){E(),setTimeout(function(){return r.cancel(e)})}),this.transform(w.query).hasClientExports)r=new nq(this.localState.addExportedVariables(w.query,w.variables,w.context).then(_).then(function(e){return e.sources})),i=!0;else{var S=_(w.variables);i=S.fromLink,r=new nq(S.sources)}return r.promise.then(E,E),{concast:r,fromLink:i}},e.prototype.refetchQueries=function(e){var t=this,n=e.updateCache,r=e.include,i=e.optimistic,a=void 0!==i&&i,o=e.removeOptimistic,s=void 0===o?a?nG("refetchQueries"):void 0:o,u=e.onQueryUpdated,c=new Map;r&&this.getObservableQueries(r).forEach(function(e,n){c.set(n,{oq:e,lastDiff:t.getQuery(n).getDiff()})});var l=new Map;return n&&this.cache.batch({update:n,optimistic:a&&s||!1,removeOptimistic:s,onWatchUpdated:function(e,t,n){var r=e.watcher instanceof r9&&e.watcher.observableQuery;if(r){if(u){c.delete(r.queryId);var i=u(r,t,n);return!0===i&&(i=r.refetch()),!1!==i&&l.set(r,i),i}null!==u&&c.set(r.queryId,{oq:r,lastDiff:n,diff:t})}}}),c.size&&c.forEach(function(e,n){var r,i=e.oq,a=e.lastDiff,o=e.diff;if(u){if(!o){var s=i.queryInfo;s.reset(),o=s.getDiff()}r=u(i,o,a)}u&&!0!==r||(r=i.refetch()),!1!==r&&l.set(i,r),n.indexOf("legacyOneTimeQuery")>=0&&t.stopQueryNoBroadcast(n)}),s&&this.cache.removeOptimistic(s),l},e.prototype.fetchQueryByPolicy=function(e,t,n){var r=this,i=t.query,a=t.variables,o=t.fetchPolicy,s=t.refetchWritePolicy,u=t.errorPolicy,c=t.returnPartialData,l=t.context,f=t.notifyOnNetworkStatusChange,d=e.networkStatus;e.init({document:this.transform(i).document,variables:a,networkStatus:n});var h=function(){return e.getDiff(a)},p=function(t,n){void 0===n&&(n=e.networkStatus||nZ.I.loading);var o=t.result;!__DEV__||c||(0,nm.D)(o,{})||n5(t.missing);var s=function(e){return eT.of((0,en.pi)({data:e,loading:(0,nZ.O)(n),networkStatus:n},t.complete?null:{partial:!0}))};return o&&r.transform(i).hasForcedResolvers?r.localState.runResolvers({document:i,remoteResult:{data:o},context:l,variables:a,onlyRunForcedResolvers:!0}).then(function(e){return s(e.data||void 0)}):"none"===u&&n===nZ.I.refetch&&Array.isArray(t.missing)?s(void 0):s(o)},b="no-cache"===o?0:n===nZ.I.refetch&&"merge"!==s?1:2,m=function(){return r.getResultsFromLink(e,b,{variables:a,context:l,fetchPolicy:o,errorPolicy:u})},g=f&&"number"==typeof d&&d!==n&&(0,nZ.O)(n);switch(o){default:case"cache-first":var v=h();if(v.complete)return{fromLink:!1,sources:[p(v,e.markReady())]};if(c||g)return{fromLink:!0,sources:[p(v),m()]};return{fromLink:!0,sources:[m()]};case"cache-and-network":var v=h();if(v.complete||c||g)return{fromLink:!0,sources:[p(v),m()]};return{fromLink:!0,sources:[m()]};case"cache-only":return{fromLink:!1,sources:[p(h(),e.markReady())]};case"network-only":if(g)return{fromLink:!0,sources:[p(h()),m()]};return{fromLink:!0,sources:[m()]};case"no-cache":if(g)return{fromLink:!0,sources:[p(e.getDiff()),m(),]};return{fromLink:!0,sources:[m()]};case"standby":return{fromLink:!1,sources:[]}}},e.prototype.getQuery=function(e){return e&&!this.queries.has(e)&&this.queries.set(e,new r9(this,e)),this.queries.get(e)},e.prototype.prepareContext=function(e){void 0===e&&(e={});var t=this.localState.prepareContext(e);return(0,en.pi)((0,en.pi)({},t),{clientAwareness:this.clientAwareness})},e}(),ir=__webpack_require__(14012),ii=!1,ia=function(){function e(e){var t=this;this.resetStoreCallbacks=[],this.clearStoreCallbacks=[];var n=e.uri,r=e.credentials,i=e.headers,a=e.cache,o=e.ssrMode,s=void 0!==o&&o,u=e.ssrForceFetchDelay,c=void 0===u?0:u,l=e.connectToDevTools,f=void 0===l?"object"==typeof window&&!window.__APOLLO_CLIENT__&&__DEV__:l,d=e.queryDeduplication,h=void 0===d||d,p=e.defaultOptions,b=e.assumeImmutableResults,m=void 0!==b&&b,g=e.resolvers,v=e.typeDefs,y=e.fragmentMatcher,w=e.name,_=e.version,E=e.link;if(E||(E=n?new nh({uri:n,credentials:r,headers:i}):ta.empty()),!a)throw __DEV__?new Q.ej("To initialize Apollo Client, you must specify a 'cache' property in the options object. \nFor more information, please visit: https://go.apollo.dev/c/docs"):new Q.ej(9);if(this.link=E,this.cache=a,this.disableNetworkFetches=s||c>0,this.queryDeduplication=h,this.defaultOptions=p||Object.create(null),this.typeDefs=v,c&&setTimeout(function(){return t.disableNetworkFetches=!1},c),this.watchQuery=this.watchQuery.bind(this),this.query=this.query.bind(this),this.mutate=this.mutate.bind(this),this.resetStore=this.resetStore.bind(this),this.reFetchObservableQueries=this.reFetchObservableQueries.bind(this),f&&"object"==typeof window&&(window.__APOLLO_CLIENT__=this),!ii&&f&&__DEV__&&(ii=!0,"undefined"!=typeof window&&window.document&&window.top===window.self&&!window.__APOLLO_DEVTOOLS_GLOBAL_HOOK__)){var S=window.navigator,k=S&&S.userAgent,x=void 0;"string"==typeof k&&(k.indexOf("Chrome/")>-1?x="https://chrome.google.com/webstore/detail/apollo-client-developer-t/jdkknkkbebbapilgoeccciglkfbmbnfm":k.indexOf("Firefox/")>-1&&(x="https://addons.mozilla.org/en-US/firefox/addon/apollo-developer-tools/")),x&&__DEV__&&Q.kG.log("Download the Apollo DevTools for a better development experience: "+x)}this.version=nb,this.localState=new r4({cache:a,client:this,resolvers:g,fragmentMatcher:y}),this.queryManager=new it({cache:this.cache,link:this.link,defaultOptions:this.defaultOptions,queryDeduplication:h,ssrMode:s,clientAwareness:{name:w,version:_},localState:this.localState,assumeImmutableResults:m,onBroadcast:f?function(){t.devToolsHookCb&&t.devToolsHookCb({action:{},state:{queries:t.queryManager.getQueryStore(),mutations:t.queryManager.mutationStore||{}},dataWithOptimisticResults:t.cache.extract(!0)})}:void 0})}return e.prototype.stop=function(){this.queryManager.stop()},e.prototype.watchQuery=function(e){return this.defaultOptions.watchQuery&&(e=(0,ir.J)(this.defaultOptions.watchQuery,e)),this.disableNetworkFetches&&("network-only"===e.fetchPolicy||"cache-and-network"===e.fetchPolicy)&&(e=(0,en.pi)((0,en.pi)({},e),{fetchPolicy:"cache-first"})),this.queryManager.watchQuery(e)},e.prototype.query=function(e){return this.defaultOptions.query&&(e=(0,ir.J)(this.defaultOptions.query,e)),__DEV__?(0,Q.kG)("cache-and-network"!==e.fetchPolicy,"The cache-and-network fetchPolicy does not work with client.query, because client.query can only return a single result. Please use client.watchQuery to receive multiple results from the cache and the network, or consider using a different fetchPolicy, such as cache-first or network-only."):(0,Q.kG)("cache-and-network"!==e.fetchPolicy,10),this.disableNetworkFetches&&"network-only"===e.fetchPolicy&&(e=(0,en.pi)((0,en.pi)({},e),{fetchPolicy:"cache-first"})),this.queryManager.query(e)},e.prototype.mutate=function(e){return this.defaultOptions.mutate&&(e=(0,ir.J)(this.defaultOptions.mutate,e)),this.queryManager.mutate(e)},e.prototype.subscribe=function(e){return this.queryManager.startGraphQLSubscription(e)},e.prototype.readQuery=function(e,t){return void 0===t&&(t=!1),this.cache.readQuery(e,t)},e.prototype.readFragment=function(e,t){return void 0===t&&(t=!1),this.cache.readFragment(e,t)},e.prototype.writeQuery=function(e){var t=this.cache.writeQuery(e);return!1!==e.broadcast&&this.queryManager.broadcastQueries(),t},e.prototype.writeFragment=function(e){var t=this.cache.writeFragment(e);return!1!==e.broadcast&&this.queryManager.broadcastQueries(),t},e.prototype.__actionHookForDevTools=function(e){this.devToolsHookCb=e},e.prototype.__requestRaw=function(e){return np(this.link,e)},e.prototype.resetStore=function(){var e=this;return Promise.resolve().then(function(){return e.queryManager.clearStore({discardWatches:!1})}).then(function(){return Promise.all(e.resetStoreCallbacks.map(function(e){return e()}))}).then(function(){return e.reFetchObservableQueries()})},e.prototype.clearStore=function(){var e=this;return Promise.resolve().then(function(){return e.queryManager.clearStore({discardWatches:!0})}).then(function(){return Promise.all(e.clearStoreCallbacks.map(function(e){return e()}))})},e.prototype.onResetStore=function(e){var t=this;return this.resetStoreCallbacks.push(e),function(){t.resetStoreCallbacks=t.resetStoreCallbacks.filter(function(t){return t!==e})}},e.prototype.onClearStore=function(e){var t=this;return this.clearStoreCallbacks.push(e),function(){t.clearStoreCallbacks=t.clearStoreCallbacks.filter(function(t){return t!==e})}},e.prototype.reFetchObservableQueries=function(e){return this.queryManager.reFetchObservableQueries(e)},e.prototype.refetchQueries=function(e){var t=this.queryManager.refetchQueries(e),n=[],r=[];t.forEach(function(e,t){n.push(t),r.push(e)});var i=Promise.all(r);return i.queries=n,i.results=r,i.catch(function(e){__DEV__&&Q.kG.debug("In client.refetchQueries, Promise.all promise rejected with error ".concat(e))}),i},e.prototype.getObservableQueries=function(e){return void 0===e&&(e="active"),this.queryManager.getObservableQueries(e)},e.prototype.extract=function(e){return this.cache.extract(e)},e.prototype.restore=function(e){return this.cache.restore(e)},e.prototype.addResolvers=function(e){this.localState.addResolvers(e)},e.prototype.setResolvers=function(e){this.localState.setResolvers(e)},e.prototype.getResolvers=function(){return this.localState.getResolvers()},e.prototype.setLocalStateFragmentMatcher=function(e){this.localState.setFragmentMatcher(e)},e.prototype.setLink=function(e){this.link=this.queryManager.link=e},e}(),io=function(){function e(){this.getFragmentDoc=rZ(eA)}return e.prototype.batch=function(e){var t,n=this,r="string"==typeof e.optimistic?e.optimistic:!1===e.optimistic?null:void 0;return this.performTransaction(function(){return t=e.update(n)},r),t},e.prototype.recordOptimisticTransaction=function(e,t){this.performTransaction(e,t)},e.prototype.transformDocument=function(e){return e},e.prototype.transformForLink=function(e){return e},e.prototype.identify=function(e){},e.prototype.gc=function(){return[]},e.prototype.modify=function(e){return!1},e.prototype.readQuery=function(e,t){return void 0===t&&(t=!!e.optimistic),this.read((0,en.pi)((0,en.pi)({},e),{rootId:e.id||"ROOT_QUERY",optimistic:t}))},e.prototype.readFragment=function(e,t){return void 0===t&&(t=!!e.optimistic),this.read((0,en.pi)((0,en.pi)({},e),{query:this.getFragmentDoc(e.fragment,e.fragmentName),rootId:e.id,optimistic:t}))},e.prototype.writeQuery=function(e){var t=e.id,n=e.data,r=(0,en._T)(e,["id","data"]);return this.write(Object.assign(r,{dataId:t||"ROOT_QUERY",result:n}))},e.prototype.writeFragment=function(e){var t=e.id,n=e.data,r=e.fragment,i=e.fragmentName,a=(0,en._T)(e,["id","data","fragment","fragmentName"]);return this.write(Object.assign(a,{query:this.getFragmentDoc(r,i),dataId:t,result:n}))},e.prototype.updateQuery=function(e,t){return this.batch({update:function(n){var r=n.readQuery(e),i=t(r);return null==i?r:(n.writeQuery((0,en.pi)((0,en.pi)({},e),{data:i})),i)}})},e.prototype.updateFragment=function(e,t){return this.batch({update:function(n){var r=n.readFragment(e),i=t(r);return null==i?r:(n.writeFragment((0,en.pi)((0,en.pi)({},e),{data:i})),i)}})},e}(),is=function(e){function t(n,r,i,a){var o,s=e.call(this,n)||this;if(s.message=n,s.path=r,s.query=i,s.variables=a,Array.isArray(s.path)){s.missing=s.message;for(var u=s.path.length-1;u>=0;--u)s.missing=((o={})[s.path[u]]=s.missing,o)}else s.missing=s.path;return s.__proto__=t.prototype,s}return(0,en.ZT)(t,e),t}(Error),iu=__webpack_require__(10542),ic=Object.prototype.hasOwnProperty;function il(e){return null==e}function id(e,t){var n=e.__typename,r=e.id,i=e._id;if("string"==typeof n&&(t&&(t.keyObject=il(r)?il(i)?void 0:{_id:i}:{id:r}),il(r)&&!il(i)&&(r=i),!il(r)))return"".concat(n,":").concat("number"==typeof r||"string"==typeof r?r:JSON.stringify(r))}var ih={dataIdFromObject:id,addTypename:!0,resultCaching:!0,canonizeResults:!1};function ip(e){return(0,n1.o)(ih,e)}function ib(e){var t=e.canonizeResults;return void 0===t?ih.canonizeResults:t}function im(e,t){return eD(t)?e.get(t.__ref,"__typename"):t&&t.__typename}var ig=/^[_a-z][_0-9a-z]*/i;function iv(e){var t=e.match(ig);return t?t[0]:e}function iy(e,t,n){return!!(0,eO.s)(t)&&((0,tP.k)(t)?t.every(function(t){return iy(e,t,n)}):e.selections.every(function(e){if(eQ(e)&&td(e,n)){var r=eX(e);return ic.call(t,r)&&(!e.selectionSet||iy(e.selectionSet,t[r],n))}return!0}))}function iw(e){return(0,eO.s)(e)&&!eD(e)&&!(0,tP.k)(e)}function i_(){return new tB}function iE(e,t){var n=eL(e4(e));return{fragmentMap:n,lookupFragment:function(e){var r=n[e];return!r&&t&&(r=t.lookup(e)),r||null}}}var iS=Object.create(null),ik=function(){return iS},ix=Object.create(null),iT=function(){function e(e,t){var n=this;this.policies=e,this.group=t,this.data=Object.create(null),this.rootIds=Object.create(null),this.refs=Object.create(null),this.getFieldValue=function(e,t){return(0,iu.J)(eD(e)?n.get(e.__ref,t):e&&e[t])},this.canRead=function(e){return eD(e)?n.has(e.__ref):"object"==typeof e},this.toReference=function(e,t){if("string"==typeof e)return eI(e);if(eD(e))return e;var r=n.policies.identify(e)[0];if(r){var i=eI(r);return t&&n.merge(r,e),i}}}return e.prototype.toObject=function(){return(0,en.pi)({},this.data)},e.prototype.has=function(e){return void 0!==this.lookup(e,!0)},e.prototype.get=function(e,t){if(this.group.depend(e,t),ic.call(this.data,e)){var n=this.data[e];if(n&&ic.call(n,t))return n[t]}return"__typename"===t&&ic.call(this.policies.rootTypenamesById,e)?this.policies.rootTypenamesById[e]:this instanceof iL?this.parent.get(e,t):void 0},e.prototype.lookup=function(e,t){return(t&&this.group.depend(e,"__exists"),ic.call(this.data,e))?this.data[e]:this instanceof iL?this.parent.lookup(e,t):this.policies.rootTypenamesById[e]?Object.create(null):void 0},e.prototype.merge=function(e,t){var n,r=this;eD(e)&&(e=e.__ref),eD(t)&&(t=t.__ref);var i="string"==typeof e?this.lookup(n=e):e,a="string"==typeof t?this.lookup(n=t):t;if(a){__DEV__?(0,Q.kG)("string"==typeof n,"store.merge expects a string ID"):(0,Q.kG)("string"==typeof n,1);var o=new tB(iI).merge(i,a);if(this.data[n]=o,o!==i&&(delete this.refs[n],this.group.caching)){var s=Object.create(null);i||(s.__exists=1),Object.keys(a).forEach(function(e){if(!i||i[e]!==o[e]){s[e]=1;var t=iv(e);t===e||r.policies.hasKeyArgs(o.__typename,t)||(s[t]=1),void 0!==o[e]||r instanceof iL||delete o[e]}}),s.__typename&&!(i&&i.__typename)&&this.policies.rootTypenamesById[n]===o.__typename&&delete s.__typename,Object.keys(s).forEach(function(e){return r.group.dirty(n,e)})}}},e.prototype.modify=function(e,t){var n=this,r=this.lookup(e);if(r){var i=Object.create(null),a=!1,o=!0,s={DELETE:iS,INVALIDATE:ix,isReference:eD,toReference:this.toReference,canRead:this.canRead,readField:function(t,r){return n.policies.readField("string"==typeof t?{fieldName:t,from:r||eI(e)}:t,{store:n})}};if(Object.keys(r).forEach(function(u){var c=iv(u),l=r[u];if(void 0!==l){var f="function"==typeof t?t:t[u]||t[c];if(f){var d=f===ik?iS:f((0,iu.J)(l),(0,en.pi)((0,en.pi)({},s),{fieldName:c,storeFieldName:u,storage:n.getStorage(e,u)}));d===ix?n.group.dirty(e,u):(d===iS&&(d=void 0),d!==l&&(i[u]=d,a=!0,l=d))}void 0!==l&&(o=!1)}}),a)return this.merge(e,i),o&&(this instanceof iL?this.data[e]=void 0:delete this.data[e],this.group.dirty(e,"__exists")),!0}return!1},e.prototype.delete=function(e,t,n){var r,i=this.lookup(e);if(i){var a=this.getFieldValue(i,"__typename"),o=t&&n?this.policies.getStoreFieldName({typename:a,fieldName:t,args:n}):t;return this.modify(e,o?((r={})[o]=ik,r):ik)}return!1},e.prototype.evict=function(e,t){var n=!1;return e.id&&(ic.call(this.data,e.id)&&(n=this.delete(e.id,e.fieldName,e.args)),this instanceof iL&&this!==t&&(n=this.parent.evict(e,t)||n),(e.fieldName||n)&&this.group.dirty(e.id,e.fieldName||"__exists")),n},e.prototype.clear=function(){this.replace(null)},e.prototype.extract=function(){var e=this,t=this.toObject(),n=[];return this.getRootIdSet().forEach(function(t){ic.call(e.policies.rootTypenamesById,t)||n.push(t)}),n.length&&(t.__META={extraRootIds:n.sort()}),t},e.prototype.replace=function(e){var t=this;if(Object.keys(this.data).forEach(function(n){e&&ic.call(e,n)||t.delete(n)}),e){var n=e.__META,r=(0,en._T)(e,["__META"]);Object.keys(r).forEach(function(e){t.merge(e,r[e])}),n&&n.extraRootIds.forEach(this.retain,this)}},e.prototype.retain=function(e){return this.rootIds[e]=(this.rootIds[e]||0)+1},e.prototype.release=function(e){if(this.rootIds[e]>0){var t=--this.rootIds[e];return t||delete this.rootIds[e],t}return 0},e.prototype.getRootIdSet=function(e){return void 0===e&&(e=new Set),Object.keys(this.rootIds).forEach(e.add,e),this instanceof iL?this.parent.getRootIdSet(e):Object.keys(this.policies.rootTypenamesById).forEach(e.add,e),e},e.prototype.gc=function(){var e=this,t=this.getRootIdSet(),n=this.toObject();t.forEach(function(r){ic.call(n,r)&&(Object.keys(e.findChildRefIds(r)).forEach(t.add,t),delete n[r])});var r=Object.keys(n);if(r.length){for(var i=this;i instanceof iL;)i=i.parent;r.forEach(function(e){return i.delete(e)})}return r},e.prototype.findChildRefIds=function(e){if(!ic.call(this.refs,e)){var t=this.refs[e]=Object.create(null),n=this.data[e];if(!n)return t;var r=new Set([n]);r.forEach(function(e){eD(e)&&(t[e.__ref]=!0),(0,eO.s)(e)&&Object.keys(e).forEach(function(t){var n=e[t];(0,eO.s)(n)&&r.add(n)})})}return this.refs[e]},e.prototype.makeCacheKey=function(){return this.group.keyMaker.lookupArray(arguments)},e}(),iM=function(){function e(e,t){void 0===t&&(t=null),this.caching=e,this.parent=t,this.d=null,this.resetCaching()}return e.prototype.resetCaching=function(){this.d=this.caching?rW():null,this.keyMaker=new n_(t_.mr)},e.prototype.depend=function(e,t){if(this.d){this.d(iO(e,t));var n=iv(t);n!==t&&this.d(iO(e,n)),this.parent&&this.parent.depend(e,t)}},e.prototype.dirty=function(e,t){this.d&&this.d.dirty(iO(e,t),"__exists"===t?"forget":"setDirty")},e}();function iO(e,t){return t+"#"+e}function iA(e,t){iD(e)&&e.group.depend(t,"__exists")}!function(e){var t=function(e){function t(t){var n=t.policies,r=t.resultCaching,i=void 0===r||r,a=t.seed,o=e.call(this,n,new iM(i))||this;return o.stump=new iC(o),o.storageTrie=new n_(t_.mr),a&&o.replace(a),o}return(0,en.ZT)(t,e),t.prototype.addLayer=function(e,t){return this.stump.addLayer(e,t)},t.prototype.removeLayer=function(){return this},t.prototype.getStorage=function(){return this.storageTrie.lookupArray(arguments)},t}(e);e.Root=t}(iT||(iT={}));var iL=function(e){function t(t,n,r,i){var a=e.call(this,n.policies,i)||this;return a.id=t,a.parent=n,a.replay=r,a.group=i,r(a),a}return(0,en.ZT)(t,e),t.prototype.addLayer=function(e,n){return new t(e,this,n,this.group)},t.prototype.removeLayer=function(e){var t=this,n=this.parent.removeLayer(e);return e===this.id?(this.group.caching&&Object.keys(this.data).forEach(function(e){var r=t.data[e],i=n.lookup(e);i?r?r!==i&&Object.keys(r).forEach(function(n){(0,nm.D)(r[n],i[n])||t.group.dirty(e,n)}):(t.group.dirty(e,"__exists"),Object.keys(i).forEach(function(n){t.group.dirty(e,n)})):t.delete(e)}),n):n===this.parent?this:n.addLayer(this.id,this.replay)},t.prototype.toObject=function(){return(0,en.pi)((0,en.pi)({},this.parent.toObject()),this.data)},t.prototype.findChildRefIds=function(t){var n=this.parent.findChildRefIds(t);return ic.call(this.data,t)?(0,en.pi)((0,en.pi)({},n),e.prototype.findChildRefIds.call(this,t)):n},t.prototype.getStorage=function(){for(var e=this.parent;e.parent;)e=e.parent;return e.getStorage.apply(e,arguments)},t}(iT),iC=function(e){function t(t){return e.call(this,"EntityStore.Stump",t,function(){},new iM(t.group.caching,t.group))||this}return(0,en.ZT)(t,e),t.prototype.removeLayer=function(){return this},t.prototype.merge=function(){return this.parent.merge.apply(this.parent,arguments)},t}(iL);function iI(e,t,n){var r=e[n],i=t[n];return(0,nm.D)(r,i)?r:i}function iD(e){return!!(e instanceof iT&&e.group.caching)}function iN(e){return[e.selectionSet,e.objectOrReference,e.context,e.context.canonizeResults,]}var iP=function(){function e(e){var t=this;this.knownResults=new(t_.mr?WeakMap:Map),this.config=(0,n1.o)(e,{addTypename:!1!==e.addTypename,canonizeResults:ib(e)}),this.canon=e.canon||new nk,this.executeSelectionSet=rZ(function(e){var n,r=e.context.canonizeResults,i=iN(e);i[3]=!r;var a=(n=t.executeSelectionSet).peek.apply(n,i);return a?r?(0,en.pi)((0,en.pi)({},a),{result:t.canon.admit(a.result)}):a:(iA(e.context.store,e.enclosingRef.__ref),t.execSelectionSetImpl(e))},{max:this.config.resultCacheMaxSize,keyArgs:iN,makeCacheKey:function(e,t,n,r){if(iD(n.store))return n.store.makeCacheKey(e,eD(t)?t.__ref:t,n.varString,r)}}),this.executeSubSelectedArray=rZ(function(e){return iA(e.context.store,e.enclosingRef.__ref),t.execSubSelectedArrayImpl(e)},{max:this.config.resultCacheMaxSize,makeCacheKey:function(e){var t=e.field,n=e.array,r=e.context;if(iD(r.store))return r.store.makeCacheKey(t,n,r.varString)}})}return e.prototype.resetCanon=function(){this.canon=new nk},e.prototype.diffQueryAgainstStore=function(e){var t,n=e.store,r=e.query,i=e.rootId,a=void 0===i?"ROOT_QUERY":i,o=e.variables,s=e.returnPartialData,u=void 0===s||s,c=e.canonizeResults,l=void 0===c?this.config.canonizeResults:c,f=this.config.cache.policies;o=(0,en.pi)((0,en.pi)({},e9(e6(r))),o);var d=eI(a),h=this.executeSelectionSet({selectionSet:e8(r).selectionSet,objectOrReference:d,enclosingRef:d,context:(0,en.pi)({store:n,query:r,policies:f,variables:o,varString:nx(o),canonizeResults:l},iE(r,this.config.fragments))});if(h.missing&&(t=[new is(iR(h.missing),h.missing,r,o)],!u))throw t[0];return{result:h.result,complete:!t,missing:t}},e.prototype.isFresh=function(e,t,n,r){if(iD(r.store)&&this.knownResults.get(e)===n){var i=this.executeSelectionSet.peek(n,t,r,this.canon.isKnown(e));if(i&&e===i.result)return!0}return!1},e.prototype.execSelectionSetImpl=function(e){var t,n=this,r=e.selectionSet,i=e.objectOrReference,a=e.enclosingRef,o=e.context;if(eD(i)&&!o.policies.rootTypenamesById[i.__ref]&&!o.store.has(i.__ref))return{result:this.canon.empty,missing:"Dangling reference to missing ".concat(i.__ref," object")};var s=o.variables,u=o.policies,c=o.store.getFieldValue(i,"__typename"),l=[],f=new tB;function d(e,n){var r;return e.missing&&(t=f.merge(t,((r={})[n]=e.missing,r))),e.result}this.config.addTypename&&"string"==typeof c&&!u.rootIdsByTypename[c]&&l.push({__typename:c});var h=new Set(r.selections);h.forEach(function(e){var r,p;if(td(e,s)){if(eQ(e)){var b=u.readField({fieldName:e.name.value,field:e,variables:o.variables,from:i},o),m=eX(e);void 0===b?nj.added(e)||(t=f.merge(t,((r={})[m]="Can't find field '".concat(e.name.value,"' on ").concat(eD(i)?i.__ref+" object":"object "+JSON.stringify(i,null,2)),r))):(0,tP.k)(b)?b=d(n.executeSubSelectedArray({field:e,array:b,enclosingRef:a,context:o}),m):e.selectionSet?null!=b&&(b=d(n.executeSelectionSet({selectionSet:e.selectionSet,objectOrReference:b,enclosingRef:eD(b)?b:a,context:o}),m)):o.canonizeResults&&(b=n.canon.pass(b)),void 0!==b&&l.push(((p={})[m]=b,p))}else{var g=eC(e,o.lookupFragment);if(!g&&e.kind===nL.h.FRAGMENT_SPREAD)throw __DEV__?new Q.ej("No fragment named ".concat(e.name.value)):new Q.ej(5);g&&u.fragmentMatches(g,c)&&g.selectionSet.selections.forEach(h.add,h)}}});var p={result:tF(l),missing:t},b=o.canonizeResults?this.canon.admit(p):(0,iu.J)(p);return b.result&&this.knownResults.set(b.result,r),b},e.prototype.execSubSelectedArrayImpl=function(e){var t,n=this,r=e.field,i=e.array,a=e.enclosingRef,o=e.context,s=new tB;function u(e,n){var r;return e.missing&&(t=s.merge(t,((r={})[n]=e.missing,r))),e.result}return r.selectionSet&&(i=i.filter(o.store.canRead)),i=i.map(function(e,t){return null===e?null:(0,tP.k)(e)?u(n.executeSubSelectedArray({field:r,array:e,enclosingRef:a,context:o}),t):r.selectionSet?u(n.executeSelectionSet({selectionSet:r.selectionSet,objectOrReference:e,enclosingRef:eD(e)?e:a,context:o}),t):(__DEV__&&ij(o.store,r,e),e)}),{result:o.canonizeResults?this.canon.admit(i):i,missing:t}},e}();function iR(e){try{JSON.stringify(e,function(e,t){if("string"==typeof t)throw t;return t})}catch(t){return t}}function ij(e,t,n){if(!t.selectionSet){var r=new Set([n]);r.forEach(function(n){(0,eO.s)(n)&&(__DEV__?(0,Q.kG)(!eD(n),"Missing selection set for object of type ".concat(im(e,n)," returned for query field ").concat(t.name.value)):(0,Q.kG)(!eD(n),6),Object.values(n).forEach(r.add,r))})}}function iF(e){var t=nG("stringifyForDisplay");return JSON.stringify(e,function(e,n){return void 0===n?t:n}).split(JSON.stringify(t)).join("")}var iY=Object.create(null);function iB(e){var t=JSON.stringify(e);return iY[t]||(iY[t]=Object.create(null))}function iU(e){var t=iB(e);return t.keyFieldsFn||(t.keyFieldsFn=function(t,n){var r=function(e,t){return n.readField(t,e)},i=n.keyObject=i$(e,function(e){var i=iW(n.storeObject,e,r);return void 0===i&&t!==n.storeObject&&ic.call(t,e[0])&&(i=iW(t,e,iG)),__DEV__?(0,Q.kG)(void 0!==i,"Missing field '".concat(e.join("."),"' while extracting keyFields from ").concat(JSON.stringify(t))):(0,Q.kG)(void 0!==i,2),i});return"".concat(n.typename,":").concat(JSON.stringify(i))})}function iH(e){var t=iB(e);return t.keyArgsFn||(t.keyArgsFn=function(t,n){var r=n.field,i=n.variables,a=n.fieldName,o=JSON.stringify(i$(e,function(e){var n=e[0],a=n.charAt(0);if("@"===a){if(r&&(0,tP.O)(r.directives)){var o=n.slice(1),s=r.directives.find(function(e){return e.name.value===o}),u=s&&eZ(s,i);return u&&iW(u,e.slice(1))}return}if("$"===a){var c=n.slice(1);if(i&&ic.call(i,c)){var l=e.slice(0);return l[0]=c,iW(i,l)}return}if(t)return iW(t,e)}));return(t||"{}"!==o)&&(a+=":"+o),a})}function i$(e,t){var n=new tB;return iz(e).reduce(function(e,r){var i,a=t(r);if(void 0!==a){for(var o=r.length-1;o>=0;--o)a=((i={})[r[o]]=a,i);e=n.merge(e,a)}return e},Object.create(null))}function iz(e){var t=iB(e);if(!t.paths){var n=t.paths=[],r=[];e.forEach(function(t,i){(0,tP.k)(t)?(iz(t).forEach(function(e){return n.push(r.concat(e))}),r.length=0):(r.push(t),(0,tP.k)(e[i+1])||(n.push(r.slice(0)),r.length=0))})}return t.paths}function iG(e,t){return e[t]}function iW(e,t,n){return n=n||iG,iK(t.reduce(function e(t,r){return(0,tP.k)(t)?t.map(function(t){return e(t,r)}):t&&n(t,r)},e))}function iK(e){return(0,eO.s)(e)?(0,tP.k)(e)?e.map(iK):i$(Object.keys(e).sort(),function(t){return iW(e,t)}):e}function iV(e){return void 0!==e.args?e.args:e.field?eZ(e.field,e.variables):null}eK.setStringify(nx);var iq=function(){},iZ=function(e,t){return t.fieldName},iX=function(e,t,n){return(0,n.mergeObjects)(e,t)},iJ=function(e,t){return t},iQ=function(){function e(e){this.config=e,this.typePolicies=Object.create(null),this.toBeAdded=Object.create(null),this.supertypeMap=new Map,this.fuzzySubtypes=new Map,this.rootIdsByTypename=Object.create(null),this.rootTypenamesById=Object.create(null),this.usingPossibleTypes=!1,this.config=(0,en.pi)({dataIdFromObject:id},e),this.cache=this.config.cache,this.setRootTypename("Query"),this.setRootTypename("Mutation"),this.setRootTypename("Subscription"),e.possibleTypes&&this.addPossibleTypes(e.possibleTypes),e.typePolicies&&this.addTypePolicies(e.typePolicies)}return e.prototype.identify=function(e,t){var n,r,i=this,a=t&&(t.typename||(null===(n=t.storeObject)||void 0===n?void 0:n.__typename))||e.__typename;if(a===this.rootTypenamesById.ROOT_QUERY)return["ROOT_QUERY"];for(var o=t&&t.storeObject||e,s=(0,en.pi)((0,en.pi)({},t),{typename:a,storeObject:o,readField:t&&t.readField||function(){var e=i0(arguments,o);return i.readField(e,{store:i.cache.data,variables:e.variables})}}),u=a&&this.getTypePolicy(a),c=u&&u.keyFn||this.config.dataIdFromObject;c;){var l=c((0,en.pi)((0,en.pi)({},e),o),s);if((0,tP.k)(l))c=iU(l);else{r=l;break}}return r=r?String(r):void 0,s.keyObject?[r,s.keyObject]:[r]},e.prototype.addTypePolicies=function(e){var t=this;Object.keys(e).forEach(function(n){var r=e[n],i=r.queryType,a=r.mutationType,o=r.subscriptionType,s=(0,en._T)(r,["queryType","mutationType","subscriptionType"]);i&&t.setRootTypename("Query",n),a&&t.setRootTypename("Mutation",n),o&&t.setRootTypename("Subscription",n),ic.call(t.toBeAdded,n)?t.toBeAdded[n].push(s):t.toBeAdded[n]=[s]})},e.prototype.updateTypePolicy=function(e,t){var n=this,r=this.getTypePolicy(e),i=t.keyFields,a=t.fields;function o(e,t){e.merge="function"==typeof t?t:!0===t?iX:!1===t?iJ:e.merge}o(r,t.merge),r.keyFn=!1===i?iq:(0,tP.k)(i)?iU(i):"function"==typeof i?i:r.keyFn,a&&Object.keys(a).forEach(function(t){var r=n.getFieldPolicy(e,t,!0),i=a[t];if("function"==typeof i)r.read=i;else{var s=i.keyArgs,u=i.read,c=i.merge;r.keyFn=!1===s?iZ:(0,tP.k)(s)?iH(s):"function"==typeof s?s:r.keyFn,"function"==typeof u&&(r.read=u),o(r,c)}r.read&&r.merge&&(r.keyFn=r.keyFn||iZ)})},e.prototype.setRootTypename=function(e,t){void 0===t&&(t=e);var n="ROOT_"+e.toUpperCase(),r=this.rootTypenamesById[n];t!==r&&(__DEV__?(0,Q.kG)(!r||r===e,"Cannot change root ".concat(e," __typename more than once")):(0,Q.kG)(!r||r===e,3),r&&delete this.rootIdsByTypename[r],this.rootIdsByTypename[t]=n,this.rootTypenamesById[n]=t)},e.prototype.addPossibleTypes=function(e){var t=this;this.usingPossibleTypes=!0,Object.keys(e).forEach(function(n){t.getSupertypeSet(n,!0),e[n].forEach(function(e){t.getSupertypeSet(e,!0).add(n);var r=e.match(ig);r&&r[0]===e||t.fuzzySubtypes.set(e,RegExp(e))})})},e.prototype.getTypePolicy=function(e){var t=this;if(!ic.call(this.typePolicies,e)){var n=this.typePolicies[e]=Object.create(null);n.fields=Object.create(null);var r=this.supertypeMap.get(e);r&&r.size&&r.forEach(function(e){var r=t.getTypePolicy(e),i=r.fields;Object.assign(n,(0,en._T)(r,["fields"])),Object.assign(n.fields,i)})}var i=this.toBeAdded[e];return i&&i.length&&i.splice(0).forEach(function(n){t.updateTypePolicy(e,n)}),this.typePolicies[e]},e.prototype.getFieldPolicy=function(e,t,n){if(e){var r=this.getTypePolicy(e).fields;return r[t]||n&&(r[t]=Object.create(null))}},e.prototype.getSupertypeSet=function(e,t){var n=this.supertypeMap.get(e);return!n&&t&&this.supertypeMap.set(e,n=new Set),n},e.prototype.fragmentMatches=function(e,t,n,r){var i=this;if(!e.typeCondition)return!0;if(!t)return!1;var a=e.typeCondition.name.value;if(t===a)return!0;if(this.usingPossibleTypes&&this.supertypeMap.has(a))for(var o=this.getSupertypeSet(t,!0),s=[o],u=function(e){var t=i.getSupertypeSet(e,!1);t&&t.size&&0>s.indexOf(t)&&s.push(t)},c=!!(n&&this.fuzzySubtypes.size),l=!1,f=0;f1?a:t}:(r=(0,en.pi)({},i),ic.call(r,"from")||(r.from=t)),__DEV__&&void 0===r.from&&__DEV__&&Q.kG.warn("Undefined 'from' passed to readField with arguments ".concat(iF(Array.from(e)))),void 0===r.variables&&(r.variables=n),r}function i2(e){return function(t,n){if((0,tP.k)(t)||(0,tP.k)(n))throw __DEV__?new Q.ej("Cannot automatically merge arrays"):new Q.ej(4);if((0,eO.s)(t)&&(0,eO.s)(n)){var r=e.getFieldValue(t,"__typename"),i=e.getFieldValue(n,"__typename");if(r&&i&&r!==i)return n;if(eD(t)&&iw(n))return e.merge(t.__ref,n),t;if(iw(t)&&eD(n))return e.merge(t,n.__ref),n;if(iw(t)&&iw(n))return(0,en.pi)((0,en.pi)({},t),n)}return n}}function i3(e,t,n){var r="".concat(t).concat(n),i=e.flavors.get(r);return i||e.flavors.set(r,i=e.clientOnly===t&&e.deferred===n?e:(0,en.pi)((0,en.pi)({},e),{clientOnly:t,deferred:n})),i}var i4=function(){function e(e,t,n){this.cache=e,this.reader=t,this.fragments=n}return e.prototype.writeToStore=function(e,t){var n=this,r=t.query,i=t.result,a=t.dataId,o=t.variables,s=t.overwrite,u=e2(r),c=i_();o=(0,en.pi)((0,en.pi)({},e9(u)),o);var l=(0,en.pi)((0,en.pi)({store:e,written:Object.create(null),merge:function(e,t){return c.merge(e,t)},variables:o,varString:nx(o)},iE(r,this.fragments)),{overwrite:!!s,incomingById:new Map,clientOnly:!1,deferred:!1,flavors:new Map}),f=this.processSelectionSet({result:i||Object.create(null),dataId:a,selectionSet:u.selectionSet,mergeTree:{map:new Map},context:l});if(!eD(f))throw __DEV__?new Q.ej("Could not identify object ".concat(JSON.stringify(i))):new Q.ej(7);return l.incomingById.forEach(function(t,r){var i=t.storeObject,a=t.mergeTree,o=t.fieldNodeSet,s=eI(r);if(a&&a.map.size){var u=n.applyMerges(a,s,i,l);if(eD(u))return;i=u}if(__DEV__&&!l.overwrite){var c=Object.create(null);o.forEach(function(e){e.selectionSet&&(c[e.name.value]=!0)});var f=function(e){return!0===c[iv(e)]},d=function(e){var t=a&&a.map.get(e);return Boolean(t&&t.info&&t.info.merge)};Object.keys(i).forEach(function(e){f(e)&&!d(e)&&at(s,i,e,l.store)})}e.merge(r,i)}),e.retain(f.__ref),f},e.prototype.processSelectionSet=function(e){var t=this,n=e.dataId,r=e.result,i=e.selectionSet,a=e.context,o=e.mergeTree,s=this.cache.policies,u=Object.create(null),c=n&&s.rootTypenamesById[n]||eJ(r,i,a.fragmentMap)||n&&a.store.get(n,"__typename");"string"==typeof c&&(u.__typename=c);var l=function(){var e=i0(arguments,u,a.variables);if(eD(e.from)){var t=a.incomingById.get(e.from.__ref);if(t){var n=s.readField((0,en.pi)((0,en.pi)({},e),{from:t.storeObject}),a);if(void 0!==n)return n}}return s.readField(e,a)},f=new Set;this.flattenFields(i,r,a,c).forEach(function(e,n){var i,a=r[eX(n)];if(f.add(n),void 0!==a){var d=s.getStoreFieldName({typename:c,fieldName:n.name.value,field:n,variables:e.variables}),h=i5(o,d),p=t.processFieldValue(a,n,n.selectionSet?i3(e,!1,!1):e,h),b=void 0;n.selectionSet&&(eD(p)||iw(p))&&(b=l("__typename",p));var m=s.getMergeFunction(c,n.name.value,b);m?h.info={field:n,typename:c,merge:m}:i7(o,d),u=e.merge(u,((i={})[d]=p,i))}else __DEV__&&!e.clientOnly&&!e.deferred&&!nj.added(n)&&!s.getReadFunction(c,n.name.value)&&__DEV__&&Q.kG.error("Missing field '".concat(eX(n),"' while writing result ").concat(JSON.stringify(r,null,2)).substring(0,1e3))});try{var d=s.identify(r,{typename:c,selectionSet:i,fragmentMap:a.fragmentMap,storeObject:u,readField:l}),h=d[0],p=d[1];n=n||h,p&&(u=a.merge(u,p))}catch(b){if(!n)throw b}if("string"==typeof n){var m=eI(n),g=a.written[n]||(a.written[n]=[]);if(g.indexOf(i)>=0||(g.push(i),this.reader&&this.reader.isFresh(r,m,i,a)))return m;var v=a.incomingById.get(n);return v?(v.storeObject=a.merge(v.storeObject,u),v.mergeTree=i8(v.mergeTree,o),f.forEach(function(e){return v.fieldNodeSet.add(e)})):a.incomingById.set(n,{storeObject:u,mergeTree:i9(o)?void 0:o,fieldNodeSet:f}),m}return u},e.prototype.processFieldValue=function(e,t,n,r){var i=this;return t.selectionSet&&null!==e?(0,tP.k)(e)?e.map(function(e,a){var o=i.processFieldValue(e,t,n,i5(r,a));return i7(r,a),o}):this.processSelectionSet({result:e,selectionSet:t.selectionSet,context:n,mergeTree:r}):__DEV__?nJ(e):e},e.prototype.flattenFields=function(e,t,n,r){void 0===r&&(r=eJ(t,e,n.fragmentMap));var i=new Map,a=this.cache.policies,o=new n_(!1);return function e(s,u){var c=o.lookup(s,u.clientOnly,u.deferred);c.visited||(c.visited=!0,s.selections.forEach(function(o){if(td(o,n.variables)){var s=u.clientOnly,c=u.deferred;if(!(s&&c)&&(0,tP.O)(o.directives)&&o.directives.forEach(function(e){var t=e.name.value;if("client"===t&&(s=!0),"defer"===t){var r=eZ(e,n.variables);r&&!1===r.if||(c=!0)}}),eQ(o)){var l=i.get(o);l&&(s=s&&l.clientOnly,c=c&&l.deferred),i.set(o,i3(n,s,c))}else{var f=eC(o,n.lookupFragment);if(!f&&o.kind===nL.h.FRAGMENT_SPREAD)throw __DEV__?new Q.ej("No fragment named ".concat(o.name.value)):new Q.ej(8);f&&a.fragmentMatches(f,r,t,n.variables)&&e(f.selectionSet,i3(n,s,c))}}}))}(e,n),i},e.prototype.applyMerges=function(e,t,n,r,i){var a=this;if(e.map.size&&!eD(n)){var o,s,u=!(0,tP.k)(n)&&(eD(t)||iw(t))?t:void 0,c=n;u&&!i&&(i=[eD(u)?u.__ref:u]);var l=function(e,t){return(0,tP.k)(e)?"number"==typeof t?e[t]:void 0:r.store.getFieldValue(e,String(t))};e.map.forEach(function(e,t){var n=l(u,t),o=l(c,t);if(void 0!==o){i&&i.push(t);var f=a.applyMerges(e,n,o,r,i);f!==o&&(s=s||new Map).set(t,f),i&&(0,Q.kG)(i.pop()===t)}}),s&&(n=(0,tP.k)(c)?c.slice(0):(0,en.pi)({},c),s.forEach(function(e,t){n[t]=e}))}return e.info?this.cache.policies.runMergeFunction(t,n,e.info,r,i&&(o=r.store).getStorage.apply(o,i)):n},e}(),i6=[];function i5(e,t){var n=e.map;return n.has(t)||n.set(t,i6.pop()||{map:new Map}),n.get(t)}function i8(e,t){if(e===t||!t||i9(t))return e;if(!e||i9(e))return t;var n=e.info&&t.info?(0,en.pi)((0,en.pi)({},e.info),t.info):e.info||t.info,r=e.map.size&&t.map.size,i=r?new Map:e.map.size?e.map:t.map,a={info:n,map:i};if(r){var o=new Set(t.map.keys());e.map.forEach(function(e,n){a.map.set(n,i8(e,t.map.get(n))),o.delete(n)}),o.forEach(function(n){a.map.set(n,i8(t.map.get(n),e.map.get(n)))})}return a}function i9(e){return!e||!(e.info||e.map.size)}function i7(e,t){var n=e.map,r=n.get(t);r&&i9(r)&&(i6.push(r),n.delete(t))}var ae=new Set;function at(e,t,n,r){var i=function(e){var t=r.getFieldValue(e,n);return"object"==typeof t&&t},a=i(e);if(a){var o=i(t);if(!(!o||eD(a)||(0,nm.D)(a,o)||Object.keys(a).every(function(e){return void 0!==r.getFieldValue(o,e)}))){var s=r.getFieldValue(e,"__typename")||r.getFieldValue(t,"__typename"),u=iv(n),c="".concat(s,".").concat(u);if(!ae.has(c)){ae.add(c);var l=[];(0,tP.k)(a)||(0,tP.k)(o)||[a,o].forEach(function(e){var t=r.getFieldValue(e,"__typename");"string"!=typeof t||l.includes(t)||l.push(t)}),__DEV__&&Q.kG.warn("Cache data may be lost when replacing the ".concat(u," field of a ").concat(s," object.\n\nThis could cause additional (usually avoidable) network requests to fetch data that were otherwise cached.\n\nTo address this problem (which is not a bug in Apollo Client), ").concat(l.length?"either ensure all objects of type "+l.join(" and ")+" have an ID or a custom merge function, or ":"","define a custom merge function for the ").concat(c," field, so InMemoryCache can safely merge these objects:\n\n existing: ").concat(JSON.stringify(a).slice(0,1e3),"\n incoming: ").concat(JSON.stringify(o).slice(0,1e3),"\n\nFor more information about these options, please refer to the documentation:\n\n * Ensuring entity objects have IDs: https://go.apollo.dev/c/generating-unique-identifiers\n * Defining custom merge functions: https://go.apollo.dev/c/merging-non-normalized-objects\n"))}}}}var an=function(e){function t(t){void 0===t&&(t={});var n=e.call(this)||this;return n.watches=new Set,n.typenameDocumentCache=new Map,n.makeVar=r2,n.txCount=0,n.config=ip(t),n.addTypename=!!n.config.addTypename,n.policies=new iQ({cache:n,dataIdFromObject:n.config.dataIdFromObject,possibleTypes:n.config.possibleTypes,typePolicies:n.config.typePolicies}),n.init(),n}return(0,en.ZT)(t,e),t.prototype.init=function(){var e=this.data=new iT.Root({policies:this.policies,resultCaching:this.config.resultCaching});this.optimisticData=e.stump,this.resetResultCache()},t.prototype.resetResultCache=function(e){var t=this,n=this.storeReader,r=this.config.fragments;this.storeWriter=new i4(this,this.storeReader=new iP({cache:this,addTypename:this.addTypename,resultCacheMaxSize:this.config.resultCacheMaxSize,canonizeResults:ib(this.config),canon:e?void 0:n&&n.canon,fragments:r}),r),this.maybeBroadcastWatch=rZ(function(e,n){return t.broadcastWatch(e,n)},{max:this.config.resultCacheMaxSize,makeCacheKey:function(e){var n=e.optimistic?t.optimisticData:t.data;if(iD(n)){var r=e.optimistic,i=e.id,a=e.variables;return n.makeCacheKey(e.query,e.callback,nx({optimistic:r,id:i,variables:a}))}}}),new Set([this.data.group,this.optimisticData.group,]).forEach(function(e){return e.resetCaching()})},t.prototype.restore=function(e){return this.init(),e&&this.data.replace(e),this},t.prototype.extract=function(e){return void 0===e&&(e=!1),(e?this.optimisticData:this.data).extract()},t.prototype.read=function(e){var t=e.returnPartialData,n=void 0!==t&&t;try{return this.storeReader.diffQueryAgainstStore((0,en.pi)((0,en.pi)({},e),{store:e.optimistic?this.optimisticData:this.data,config:this.config,returnPartialData:n})).result||null}catch(r){if(r instanceof is)return null;throw r}},t.prototype.write=function(e){try{return++this.txCount,this.storeWriter.writeToStore(this.data,e)}finally{--this.txCount||!1===e.broadcast||this.broadcastWatches()}},t.prototype.modify=function(e){if(ic.call(e,"id")&&!e.id)return!1;var t=e.optimistic?this.optimisticData:this.data;try{return++this.txCount,t.modify(e.id||"ROOT_QUERY",e.fields)}finally{--this.txCount||!1===e.broadcast||this.broadcastWatches()}},t.prototype.diff=function(e){return this.storeReader.diffQueryAgainstStore((0,en.pi)((0,en.pi)({},e),{store:e.optimistic?this.optimisticData:this.data,rootId:e.id||"ROOT_QUERY",config:this.config}))},t.prototype.watch=function(e){var t=this;return this.watches.size||r0(this),this.watches.add(e),e.immediate&&this.maybeBroadcastWatch(e),function(){t.watches.delete(e)&&!t.watches.size&&r1(t),t.maybeBroadcastWatch.forget(e)}},t.prototype.gc=function(e){nx.reset();var t=this.optimisticData.gc();return e&&!this.txCount&&(e.resetResultCache?this.resetResultCache(e.resetResultIdentities):e.resetResultIdentities&&this.storeReader.resetCanon()),t},t.prototype.retain=function(e,t){return(t?this.optimisticData:this.data).retain(e)},t.prototype.release=function(e,t){return(t?this.optimisticData:this.data).release(e)},t.prototype.identify=function(e){if(eD(e))return e.__ref;try{return this.policies.identify(e)[0]}catch(t){__DEV__&&Q.kG.warn(t)}},t.prototype.evict=function(e){if(!e.id){if(ic.call(e,"id"))return!1;e=(0,en.pi)((0,en.pi)({},e),{id:"ROOT_QUERY"})}try{return++this.txCount,this.optimisticData.evict(e,this.data)}finally{--this.txCount||!1===e.broadcast||this.broadcastWatches()}},t.prototype.reset=function(e){var t=this;return this.init(),nx.reset(),e&&e.discardWatches?(this.watches.forEach(function(e){return t.maybeBroadcastWatch.forget(e)}),this.watches.clear(),r1(this)):this.broadcastWatches(),Promise.resolve()},t.prototype.removeOptimistic=function(e){var t=this.optimisticData.removeLayer(e);t!==this.optimisticData&&(this.optimisticData=t,this.broadcastWatches())},t.prototype.batch=function(e){var t,n=this,r=e.update,i=e.optimistic,a=void 0===i||i,o=e.removeOptimistic,s=e.onWatchUpdated,u=function(e){var i=n,a=i.data,o=i.optimisticData;++n.txCount,e&&(n.data=n.optimisticData=e);try{return t=r(n)}finally{--n.txCount,n.data=a,n.optimisticData=o}},c=new Set;return s&&!this.txCount&&this.broadcastWatches((0,en.pi)((0,en.pi)({},e),{onWatchUpdated:function(e){return c.add(e),!1}})),"string"==typeof a?this.optimisticData=this.optimisticData.addLayer(a,u):!1===a?u(this.data):u(),"string"==typeof o&&(this.optimisticData=this.optimisticData.removeLayer(o)),s&&c.size?(this.broadcastWatches((0,en.pi)((0,en.pi)({},e),{onWatchUpdated:function(e,t){var n=s.call(this,e,t);return!1!==n&&c.delete(e),n}})),c.size&&c.forEach(function(e){return n.maybeBroadcastWatch.dirty(e)})):this.broadcastWatches(e),t},t.prototype.performTransaction=function(e,t){return this.batch({update:e,optimistic:t||null!==t})},t.prototype.transformDocument=function(e){if(this.addTypename){var t=this.typenameDocumentCache.get(e);return t||(t=nj(e),this.typenameDocumentCache.set(e,t),this.typenameDocumentCache.set(t,t)),t}return e},t.prototype.transformForLink=function(e){var t=this.config.fragments;return t?t.transform(e):e},t.prototype.broadcastWatches=function(e){var t=this;this.txCount||this.watches.forEach(function(n){return t.maybeBroadcastWatch(n,e)})},t.prototype.broadcastWatch=function(e,t){var n=e.lastDiff,r=this.diff(e);(!t||(e.optimistic&&"string"==typeof t.optimistic&&(r.fromOptimisticTransaction=!0),!t.onWatchUpdated||!1!==t.onWatchUpdated.call(this,e,r,n)))&&(n&&(0,nm.D)(n.result,r.result)||e.callback(e.lastDiff=r,n))},t}(io),ar={possibleTypes:{ApproveJobProposalSpecPayload:["ApproveJobProposalSpecSuccess","JobAlreadyExistsError","NotFoundError"],BridgePayload:["Bridge","NotFoundError"],CancelJobProposalSpecPayload:["CancelJobProposalSpecSuccess","NotFoundError"],ChainPayload:["Chain","NotFoundError"],CreateAPITokenPayload:["CreateAPITokenSuccess","InputErrors"],CreateBridgePayload:["CreateBridgeSuccess"],CreateCSAKeyPayload:["CSAKeyExistsError","CreateCSAKeySuccess"],CreateFeedsManagerChainConfigPayload:["CreateFeedsManagerChainConfigSuccess","InputErrors","NotFoundError"],CreateFeedsManagerPayload:["CreateFeedsManagerSuccess","DuplicateFeedsManagerError","InputErrors","NotFoundError","SingleFeedsManagerError"],CreateJobPayload:["CreateJobSuccess","InputErrors"],CreateOCR2KeyBundlePayload:["CreateOCR2KeyBundleSuccess"],CreateOCRKeyBundlePayload:["CreateOCRKeyBundleSuccess"],CreateP2PKeyPayload:["CreateP2PKeySuccess"],DeleteAPITokenPayload:["DeleteAPITokenSuccess","InputErrors"],DeleteBridgePayload:["DeleteBridgeConflictError","DeleteBridgeInvalidNameError","DeleteBridgeSuccess","NotFoundError"],DeleteCSAKeyPayload:["DeleteCSAKeySuccess","NotFoundError"],DeleteFeedsManagerChainConfigPayload:["DeleteFeedsManagerChainConfigSuccess","NotFoundError"],DeleteJobPayload:["DeleteJobSuccess","NotFoundError"],DeleteOCR2KeyBundlePayload:["DeleteOCR2KeyBundleSuccess","NotFoundError"],DeleteOCRKeyBundlePayload:["DeleteOCRKeyBundleSuccess","NotFoundError"],DeleteP2PKeyPayload:["DeleteP2PKeySuccess","NotFoundError"],DeleteVRFKeyPayload:["DeleteVRFKeySuccess","NotFoundError"],DisableFeedsManagerPayload:["DisableFeedsManagerSuccess","NotFoundError"],DismissJobErrorPayload:["DismissJobErrorSuccess","NotFoundError"],EnableFeedsManagerPayload:["EnableFeedsManagerSuccess","NotFoundError"],Error:["CSAKeyExistsError","DeleteBridgeConflictError","DeleteBridgeInvalidNameError","DuplicateFeedsManagerError","InputError","JobAlreadyExistsError","NotFoundError","RunJobCannotRunError","SingleFeedsManagerError"],EthTransactionPayload:["EthTransaction","NotFoundError"],FeaturesPayload:["Features"],FeedsManagerPayload:["FeedsManager","NotFoundError"],GetSQLLoggingPayload:["SQLLogging"],GlobalLogLevelPayload:["GlobalLogLevel"],JobPayload:["Job","NotFoundError"],JobProposalPayload:["JobProposal","NotFoundError"],JobRunPayload:["JobRun","NotFoundError"],JobSpec:["BlockHeaderFeederSpec","BlockhashStoreSpec","BootstrapSpec","CronSpec","DirectRequestSpec","FluxMonitorSpec","GatewaySpec","KeeperSpec","OCR2Spec","OCRSpec","StandardCapabilitiesSpec","StreamSpec","VRFSpec","WebhookSpec","WorkflowSpec"],NodePayload:["Node","NotFoundError"],PaginatedPayload:["BridgesPayload","ChainsPayload","EthTransactionAttemptsPayload","EthTransactionsPayload","JobRunsPayload","JobsPayload","NodesPayload"],RejectJobProposalSpecPayload:["NotFoundError","RejectJobProposalSpecSuccess"],RunJobPayload:["NotFoundError","RunJobCannotRunError","RunJobSuccess"],SetGlobalLogLevelPayload:["InputErrors","SetGlobalLogLevelSuccess"],SetSQLLoggingPayload:["SetSQLLoggingSuccess"],SetServicesLogLevelsPayload:["InputErrors","SetServicesLogLevelsSuccess"],UpdateBridgePayload:["NotFoundError","UpdateBridgeSuccess"],UpdateFeedsManagerChainConfigPayload:["InputErrors","NotFoundError","UpdateFeedsManagerChainConfigSuccess"],UpdateFeedsManagerPayload:["InputErrors","NotFoundError","UpdateFeedsManagerSuccess"],UpdateJobProposalSpecDefinitionPayload:["NotFoundError","UpdateJobProposalSpecDefinitionSuccess"],UpdatePasswordPayload:["InputErrors","UpdatePasswordSuccess"],VRFKeyPayload:["NotFoundError","VRFKeySuccess"]}};let ai=ar;var aa=(r=void 0,location.origin),ao=new nh({uri:"".concat(aa,"/query"),credentials:"include"}),as=new ia({cache:new an({possibleTypes:ai.possibleTypes}),link:ao});if(a.Z.locale(o),u().defaultFormat="YYYY-MM-DD h:mm:ss A","undefined"!=typeof document){var au,ac,al=f().hydrate;ac=X,al(c.createElement(et,{client:as},c.createElement(d.zj,null,c.createElement(i.MuiThemeProvider,{theme:J.r},c.createElement(ac,null)))),document.getElementById("root"))}})()})(); \ No newline at end of file diff --git a/core/web/assets/main.008c37495ba29761321d.js.gz b/core/web/assets/main.57f94389bc8271642420.js.gz similarity index 86% rename from core/web/assets/main.008c37495ba29761321d.js.gz rename to core/web/assets/main.57f94389bc8271642420.js.gz index c5cb981d0055351233b5b95ad14604dc0c02467b..82b42bc1d0a6aee0172faacc2bade75737e4d354 100644 GIT binary patch delta 166151 zcmV)3K+C_|kV({vNq~d_gaU*Egam{Iga(8Mgb0KQgbIWUgbaiYgbuV1K*4_q)@A`J z;@*d~v|K9y5B%xT^GBvNh3XO`u#NyOM8@&+XWd7pH7EY{)2F7jfbZ#1=ecQ3@c!ty z`^2=s9e@7#*|Uym&4^jwdE7N2hip9U9)sO}3!ZrQX{T#iD}2^DIx?+G5?DAsIySA> zc>nbA^R8)K*pYGc_{pQ^rgeV>@3ZHfBh$K}ydE7rF|AL8<~@7%$h6*}+(%t_-{X)s z-kH`55i zuH>FpaxYG`o%#2FPX=2BBxBI#6r-TrSOPhRnH7!AYMHE%V@IR5ibOpkE|_GJcoimA zcO%ESlUB0RI@^BV*^Gbcw{(}MJW;nAqKfToe5fGTO#u=O4PzQIGE}I6V%?mZ1@xnn zq>S^ZeJ;V+39WAoDlTVumc&`eZ_P4 z4JbOcUzxjfcb2ZD?a(-H6u08cwS^lgPcSt;*hdv%_hR?j>skp3e3!u#5(}c8YOiZS zO2SGSjkGK{6hj(rL!L`Z{gp29F=GbjZp%OUpc(lIIQ9xsfxIP3DK#r5mX0m-PM5A( zd%{u2dSl}X`l5es)f3jSRG-9I7Ke4K9*8NzE8olJb*nxXDgkeT^%aN5)<1Sm%XiC+ zy8r!z45cR4Pxh`oS?DF`#!*BDtuIk|iV9U0B$1ZB@Vs3wQ(eF%Lx=P-R&gozcNG

?1%M*UbZ$9v#_ zQf|JZJynZ16dj}zs)$QSVwQ_$czb8*B_456j1`fFV_l8@?-4lCY8#ATC2UVKs2h!q zs;CIhPw%e{ci`rh%kb9wycSSCR_@}>d^XeXkd58wJ%#G-)Ydz5vbjiDl?0B$!Tzr|6>Q6h>>g(<)SNjZFYB&4Sc;LQ!md{lZ2irM=O-s`h zw?0n;u~Gf{o=^2S6gnsGN}4SI1p(zl)i~hb`oBnC0h!(F zSm| z2k@RDP!-%UHbs++2fC+3tKM0eKiTs;_vr_B_{xc}F)CZT`SvbH$q9yso}kamkpq^ z3SWPgDXf|K5OjH;a&liQJ;*>8FJmiRON&9nzlFKv2jANItG#QB1T`*RMIw2X1EL!d zZ6z)DH(#uze6_Z|xBt!PSoFU{ko;Q8l@zVKfrSM+G)sbAf7zjFsN0WD^7|U)p2>z$ zt2?&ycO~2jGu~Ue!l>d(xiH38Lk#N^vekdysyCx%y~RKhP@hf-g8Ox&J`X}#s4THA za49vzZPYDl2vq4MW4e-BUpO8(%&mIU8TUz@`d1?^Ny6ln__@3!W+MCPr}(D0QNW#@ zwW$Fx%1KaNsSSTCf9?jph_YWPZIp-qO5d=2Rim+&3kiO&c#waE9(`PgiNnP*gPDKu z+W=AxmT&)RKusj{)rx7>^xM=mR!nLq7frv-U1X*9S0mv%;;s_{s-h%~s)k|`-_(gQ zF^O+3{I7llohWo|Ie``tBW*e+-`_OSmi-qa$zfa`5wq!-Rw@0m8Jm1(##pNKJb-H8 z%qFxa?fsJ|S$vamqqG(j({AM0iu!-x{!pwlNe$QJ`naZ5i4ROJw_xM^o5B5LQSX4T z#I*n4b^_oRfBVZ{{y+AhSdBjCCb=x}1u^W2f>QsU`x;s=%DG_dX?)Pmv^# zks#Q4loHi-#EDEsks!DSBe{Q;61BY|z9tAPcO)TSX)&uG3gwJye)1_|t=mTm?mqDay=Zl1rsPq#U?{yf|zv zF78;vI23~J^q%)vuR$|QG1@XwKWHwU1r4bJwEpzk4p*Bdg8|TsIy9oGb09xm$HKM6 zG}BSF6m_WjU|ItoGl8R?9jxtu_Jq?P)Ie>E zEo>=>T_vZ2K{Q$7(8a&uUxj}O{7Mpz0-X>Txk8R(0oRt@s3m`>!nt7IYC;v1Zs$^s z`gl|Y-?^&wj?3NJA`>^dY%ezkS4d5nUk^UIlsS-89!)!#gU9PbGbqmz?v&BHg;9uJ zKUdF?iON9&;X#57Lkd5W%AEoyq>A3O<`XQJ%_7*~s;sp2uC~;!aayViR@Rr)8?kRQ zS6h}C3vZXyNo0S1VD#e&9btwq{X0_E2IF(CBXbThMxS*QS^fNZ2UNhB1E4jiiVg~Q zO8El$(=m*?fnV7yzK;<-VZD(T#H9<`EJc)xmvmaXjoX)=Mur|l5iEWehu4*J4#F8& zR;ggLQ#olS60R>}mcj@%j(~9UIzoXRo48&0p<5Vm+lsY~3EI<5Zn z7)*QyHBC_a1(qp>4#a1V6PkBLpMzjLLPz%^=}bXl95dz4&$^%)-`;t#8xS@?eK_k{ zatda#P3IEMTX#^CBQ@^3jCptq3% zyakCPi}`vqc#mBJblD}lzQX7l_)G6iEiG7SYV&_m9!zv_W%gh!Ml9{NFFWdM5$T){ z_z0{LPV+owM{1fM=Ubv!*Rt;)?ud+JBir->MGj@V|q0aV0hU%FuUv`ALBvH-dGJER~p8hR|{3c z)VF_!F*{cCds|FK?U^epZ#R2aH0ove+G=V#Wrs-Wumhh3am?PT#?NB*PBs2p+~;M7Z@*@1(_gc-ub$r$_H+FFZUmd))>F4ScqHp`nfYS=uaVXN?w2R8y59)Nsf%25)2fRp7uNWFF%MFWRdG( z%E~p6E6-g1(Rtr`S)(=lERT-OUPJaHee;Ciz`=CTlL;8uZ@AYpkEP(!4vVgR$nqq&j zkX~t#KK$v$D%IXn{383N6qq_^dm+^cFET}PjT%TdmT2v%1Db>Hgl(*v@ANK&qO}9f z-h!dbpaW{uC~-LLiI}aAK_;}`1+nY8$j#h3?0cURx}F9RFZt8eK5SQ=0LIg)_!@A# zc-fpz`>U(z*Dbe<^aPDoGxa5Wk z7EKgw8aRv~ogSoMF$LAp*4OzC;s)0S3F6giRmdBd$JAkeV5ZL|VLe{}t2Td#S60A` z5QCHx8vFg&8`4i7D95CnBIvLWKKsKLp)SR*We`!)i$TwaQH8K-2U;>EQ7<6Zh8B4w z*I|D!&hFv|a;;A5?=kyPoz`F6r`0-@Kb7s0A>Z|99l&1-Ew`R^8hd)m#mIF*1TjGt zO$Gh?7JCZEvH)P z2XHVUtm$~^LfbRKHtM9){NUa*!ZzclMBbYHpH9p2go~3mMzv+hx!IO=V%e7Ka#6SK z>T2y?RWCv=Rl;nS5I>)2R5oNe;*74y5GnmT4|QQm)H0OUt8&7IsD zyCP?iU&7pZcGKH6-Dg|8lr>dn8cS5=sR@>#C}vf+Ps6r*zAKrm-6xa4%eAtwJi1nLH(=u!<>F$mb4BaotB6mOZ0 zE^~*=jLCNf0H^(qF1;<4&P%I}kh{Llb8DBsLj8Pc>Qd&L(18hM9sp0)cjP%tw!uDu zEFi<%9vlZ52f-Kk55kv?BrR>xHk<2T3chyM!cVM|7HN$;vlM^qb<<$54PIT9O6_mW zu;kn0OW_8y9kVuKjJ%XV#s`lmNX!vUfelBdoP1IyX0xjR%wY%NyK%~L@09=7hNTojX-e9WIHD;Zf> z$)MvH^ye7wnZ51Ydmw{m!OsG#!RNE_y^$H|AlG!yi zpmV(9*1)fkFm1{BUWWImF z93{+!ISeBAtLpWn^xR4HGPay+WlwQ)a$In8U9;;Cc@L-NVC(5l{bQ3j|_imV!5^Jv4!ME&3%?{ zPfN{e)%|2yyF#Fj*l52o+n0aSpxuZ`E-T`htLcDoZ-(;J!xaeaQaj1VmrDVgAY{;a6 z!TQHt3278XBGwT)H-kb%6#n|FI2H}`oq!K+Si{sI_yvXKYbbF@rugzZdJkdLYAfIe zjUkhF3B)|I#(Gkgu6$Hpu4?J0Q+aBBT-ct_x)`0D-D$jYZMxprT5tYjyb-N5-y=GD zt#_J>dPGGmhsH;xk`NtoA_v4fp(FfYI`z((`qm6b?Ry9y=nK_>2|<_Xmzx9-9e<}2 zd4Kg>Y4b%;nW{4Bm-`O=)P#1sfZ<+^rA$OL=_f*-10veoAl+mDSUDWg0h1EMCwxfL z$8bown2{k9WAw$GXs@D+WE3@tet4za5t^9a=1uH3$xZmc zH6su(G%~RdAwHMD9OqF+G)(r#GI^bJ$Jw!DLjcW*-g$V9M@z5l-~LUBd>JM3`k#mr`MFGqoGD7=H$#BDGCy9ID3MpoQzGyF?@%J|Y)a(4ixT18 zMEs>>$hQtM-WE50LSzzo&mn4pHzVHn?6Gk|1-(@| zm|&T2m97oGJ}_E0rJhs-#8=Lk6uF!i&h%Z%`Y3ngJrp)hzk@@`_U4YZ znfV125^LTK-MhKzw|3Y~e~-0#&Fvf353~DQ%i>i2WKq07{gYF?-z`P){vKWs`IA4% z(rzSwA#@-k@8FJdG2r53<8-8nycuZ1XKneNy=qi z*BvPbSbH`4Cd&JEwzqADWW%;T+4z?=ciOaUeG6}v4Rk!wRwmlMVGB99-JMMvN;?&k zCX&X_e@%ZC(@V(8diDI4@VEs^xV2Ur+|NSxiFJJz-Xy)p0CRt0V4#<>9q=_%bKTd) zYd}fl41bJ9rjVR8;(#W{LlKoI=xrOqd%g+xOJJDhH&e-ZZ4-OBXNL-4;UH15pHKV! zj3H(l55+pfA(Xqm2-ei_QO^j2S#RO}Qu#{1Npz((O0rmG9)-t_h?-;^o5t5N(zRma zGbBlg7Zu^ZlhV_eV2p7xh*O=pwhVQMiaWUE$bT;N^So*s&0?i`$~C1wNRreaKZiKD zck%c?_nKq`9Mw(SY~Q>zpSEw-;=N`tQv6b1Q`W^Jz-}XjW|cSpnU8bv+vBF~zQOHKvODy5^@HuQ6?SYiZ;)rVx_ej!$3AZP)5tbM~-2 zs&2!sDp;BC+x6MHF<=bVtdKH7TIf^Ae}7ftNdN;RguNol8WWJeBSHz7irC-{e@yj-9 z4m8~SDv5}S*OSXSF~kO3Y9@G+4SCCU70knn-Qn6&R>Jpr$Adj_HpJZEoX(RXhQ1&* z9|0Vyg-LvIhi9f!+wf5}E1klFmjFw^gw~Cm8re4o>oMQh24b9ST?KMC6o01z4>2dg zPQk}>o?Xcu3!c3g{HT^&BHwX({L|@5Z6?!ctq5$JhDCm*(niahe3vGl9)moWJSb1} z1Tf^rJo$bdbwG7uCua&KK-J{2E((*zmW?KEEGiLmhUI{*DHKe+TJKU&i00FP6hBv` zn{HTgVGzSV)rA4^YTowkKY!5s1u^@538#oL?tC4WOLRdAVjWvXtS|<_L{NjGiGKqu zuI=G~oNer3NX#GJAhz+yO_-oqn+~u*Q<7OHHx#=;L$xdxkABURIE~WIWqPHn7JAMu z@Uf8iy|3Gg{b8&d3RYKhOf~Ebqsy!Ipx|}~hDhm=J2E0SWJqq~K7VAj86@4dYV3A( zwX4|S+hEp(fpr6NqlFB*L*C($#>IXw?grCoey8+wRFbF%%$^oa+=Qb<#bC}1G2Nkg z3wPxf?o11JbNNUm>6pQ|jBp~0>FO%)(0Sj;9iJnP%ex(wyB(QsM+=&$30rUsBgjyp z=9NICgCa`Jz19(DrhoA)WS=Ax8JYo`Lx5GrtE+O;zYjV$R+U(!{$xh(gQ#4JeT_Tg zXfh-7I0Vu6ZvrwIvMi&wESi)k>lw)bS9+sbw!k_gFgs@*crhczu$+~O*Q={G8)?4@ ztRP}=ippbc&CmcctCgyys1@g1t@fsL7OQXJ9#p4ubv1+4?SFm@I=-9oR-pB;l4p1q z{n5h9HXvf)-$1B(97EWpBhYrA!-p3s?Xu3Ca^0oKImTs1q)47%sd3#DWJl%;W2|j% zkNL*U;z7p%)Yi~)EByI2aV9=8x@)v(7BgS;6chp*=h|tm3qo}|wbN9a!(KxEG7Mrwvxzd*PcW8Q(T^qI&0L8f#dU?p1NvFq``-DZko1#EUKtf>7e$~YcZ3m? zJ0KvA&|r9T`$a&6O7ykS+6{=vqhR$@#{OXb6IDK>a zHu55m9R2Wq|IK;i#U9zeh`j&y$g8vcgYS1jzW)|AAEasvLAWsKRoZ_E>QnHa{B7Kql1gcQ~&j>%9E&+ zcx3KaU)}eSZ>p@K^o5{&D}!`y*ANenUI& z-hW?Qo3YwY=3RZ!nK61R%q=Rl&w&6$Sj>^nZ2GOByn#X&E@Uu}{(_X(1w-DviZ~@jPxn z-0=a^jm6lQKCwA>u7Z*c^@Bob`Q!e{yZpCCZI$Put~zV^BOLf|vDMJ3%Ou_oER@4`>F#bG15beJdc(yk|D| zcTkn0=2so$%+=~gb19>fBNM$geaYKu6D4sPcJ^#`ttJ$bwKd(o)pA^`yBW1qvTJ*A zYptL|*W!)k+u7WV>^t2c2iTj061vvHfO;~}wYT%yhdv~tExp`vHl=p9tFb+2{r!`7 zj>=n2XJvghTpzR+eBc_+)=tFx{??8QsH>~4@{L>?S4OOO9h5=S_q)2iUESWUZf{q&XHeUo zZf{Swx2N0N)9vl)_V#ppd%C?n-QJ#VZ_l7g-QEjb|AnsiLf3nt>$RFq^P^>cY?vRL z=Es)#v2A|rm>;|5$Da9NT5g$^Tc+ifX}M)uZkd)_rsbAtxn){znSYjBrsWOO@`h=7 zVVqBwm`IN^}#xhxj7|4k%-a;+s8#&V$3K+mac>GS+}7Vif{0P#XEh&EqfOj+-}U?yawO6T49eVj;U zeeFLBNTbJljmKo%7=JPf(W4rW$(lBL$@nJ!!vEC^I$mUkgh6(3K;xo|g=4bje`vDR z5aR%Wyfab+SuESVq(S4v#sX_=nW6nw6nR6@`Qhu$)^rMUrS1zs6Nf~SO!Y?+O|MA6 zOSS=(cw3B$P(y*_qY_~0M7puk3v6xYQA8`_90vi}+QXowpnsHbR`@#J+FM=CUdG$I zLB7`*8I#;oLYoKL!0qu{E*rED;B7`F2xkhyT2?WR#XD>byJu{)17`P-acS?oE33l_<2nfU0x+j)%_*+=1UGnEh5GG(IHvYQ60nFw zJT}&NY~03^fLHrC58S&JQw__EBmpUtaVVJ~k|b*_eSaXkxO2xjvK-r6ASnP+pdhez z=AxnamNF#9X6rBK{27sJ(vlEX^zmMTsw#XDI1|0<=s5v=hb7O(yCoWN+XQnFDi z*{qdpDSt2yUN+U{@8__C#Y@(a3@7gCd`^=NtH76B0?rsMN0kXD66&Xe??m7#i)~2e1 zb!&j=WQseV|2?9C&jzHsd^70y70|9d^E~ev$=2d6SnB}BGAqO8$({7Nn&+<}e)d`L z@_%J(V=8|3W$^Ol9{do&%a>d5BelQ&*`_9F;!y@-7s?`&hqZnMMIx3{6> z#V(e#nj0OqzPB5#x2*PFJ#l@Qy8<_O3vQ8iwh}|MG56h(!QJ7%*jC~4$7+OQ7$H8v z=*BPO7fpPEk&R!*t&NSK9jvWoP7)ln1Ai9rNAv5uO!~dI0E68_;))y`(4hs2jScI| zZ%YOd*!Ne;Ruw5^6ZhNKikPpS&hiIG>r;3UVAcjqoFqPl-=e({2vn~J?30eiBu+uy zqe>GMlqQyoB)~W%P?gL{ZK$XS6apLI>l(5p3KY?<+Ou6K1JY>XMG1)2;!?OKU1OR$ehzF8ve2V)(`BtTlgX` z^jBKJ7eb`I7XT8UgJ3m!VJ>u{ttr$~yMkQw%e;yksXx_Ic| zM5AP*7Fe_*q|gQ|>hp^(4S$FJI^QvlZ35B$Al#boS|3yl1f+~6atmtMz9v&W-iB5a zry44GQ%Y$NbnFof#_SC`2o3y|W?)Y5lUud9;94`&S{`%_*Tj|LsB}6FT-7P89_0BW zvX9RfE$I2to1+6n3+G1{#UZUw0!E|ZIJczGM=UeWc^lneGo@p)SAWu6#eQJHMca$K^mo9SGp0Spl$PwQ74zZP$*^;?!I^Hm;2zvZw`EG-@Dpz-bmSy{v_SwKbJI zObDXMFGQu4i>@;d!J1=GS}0*HR6ZJ)tH0Ik0T^1F%8uEzm%?IBRAri2Vm~_;V$s3V z7{^*AV-aH(=)OQT4u3S#TCl@Q0QsV$SQ$$d2dJSfhe@m0Z^5|D@mglcuDm{DukEOTnA5QwbaD#lxQX&oe@hZkie zJLSdbDQax#E9J|mAJ-y%E+L%fPRLg!UyYpk35f9qG9;v7cYkf8ZkC&hVnZp1Z|T4c z%-oDw5XazX=UhsQW>~zOUqXYHm&`e3*nq^jlz$}&8~t6N_+LA%+TN^6KES^RJ$vGL ztojEDj4+O%@PHV3IQ&k)ZDghF=JBUi;dJ#1bT%w+9q zdL-ID&@Wv-pnv|-SB^{811zCwR;kREZ5V4W+q5>-&F5;{@75-)nL`|w7R@%mx#svi=Z7y z%N%fTLhPqIOI#|y&4;v9|~k; z=L%nlYwFesVsYgFUSItD?np^{>S!>Cs?teKp^$|`-GBQ{P$DJYp1!>XB)zb+h~*&6 zd-@`V46d|8)zxQ;Wn2R9IYX$4&pYr`r=y%$ZSI@kr)r>4G$GGj-idl za?!jNX>)Q+WPi3;YFyqUPs-5na)#KtCE1X5aR-*B&e`l|D0eCZVL_-=w$|s0b4uN| zU4M*^-qk@(ZBmivYI)y$VP;9WP!^<{yVoH(MQ<&elj{{Dj-<_ci9*qWu?nMfKI)h= zmd}M=RdY1|UavvVLeK353NyfqZe5a8m{}|k2RpFHU$H+BiMeO!2PHXhdCRy~8+`F< zlP)j0ri84OU$oE;^zrAz0CDnC5I7!=RDTrCEJwT`SK;%|6^$zb`K*Kp=a9S0!7#rV z0EQMoxuKTne8{?HQiCjJZd@d;7feB&CMmYGe; z)b1RjX#eD004Cfu`q!5G7)QP*+NsQYIPZoDIb{9p=?j7{U=`?R;L)nDulw{DOjD}v5^m#w1xMeW)R*hjk-S6x^^o{+HaHxoiGke|I6L7LRpNDUjv016zujmo#x?rQrt9%4?#`Vu%DCC*{-gSb3;z@sEmw#hCiO*ju zE&E-tR;~dodq32#^1QVtu5(Adzw}Cf3QZT`I{qXcX09CMufWJ4iurptA`W;td|SjX z`GOs(u`GWAbc=}O&)bqUlBKp89rnPBSIHui|1?RXWs1DCpt1JNlXAw|7fXv7YhOMo zWvqSigpkoOwxwi@wh{M}7JsG{V1K44|?f=>&T}xDYYB-FM+4U zAALDE=kP~=5=aZKYB5AL8?`*W|5sy>g5v*j(9Way|0LMf`GmzV)_7n6j2-IXKcAZ_ z^wVxj4=}M=g3~I?kbezIo}*An*@#gLoa?yh>J^Yqj;5Tc-o8jh(Xe=TS}GGUvj>}MjC~U z3`LSpa0S&|Wk>R#(L3AbI!&O=QmKk;m>Wa5atYS0j5WWC=6^ue{$9!eERU&)**zB8 zP|6|%M}5dds`%!_J2F9JiUoAMuC258R;pyfd`8F`k2?AdZ4`EldP~~-kkYU@fcTgiPZ2sD>5OZpmtuFFRl*SL8=wbMY4v%%rb>O zZ4STIxiKhmwa$V((a9C4ww*oc@MH^y803R7+WHx0&|4A|f9eQ`EMEX|Im5>SQ0Qw{ zjYG^I$0BIviQ1~cdjGIvyW@7wx7;^cz!$9fYKO|sGk@#UNen+5d8K$M-&p7u0|9rQ zmCxz3AX2G8#fMm@CL-ed;^&VL)=c~kVc&{Ye<>xXNZDurVf&w7{+f}iwdc14@(qSE zC50~&^8j%!|n4pK&Yj}7*TXEFX8cqR+I|03}_u`G04 z?`OL8>C`jfYdoM&)e%udfzB}YHjxe5P=E2PbT%N^TKG-q1#R&GH;5$S2VZ;#__s*C z@c|D~DK2QU>Qz8Q+-i$@!b(VBAuq*x>&i-1DX!X{!Xd?qFf^pNWLM_)fK00e1yN5D ziFeQHYB6(^Wy8!n=~|3Lw~eRRcq&8J%5f!nqk;cJd4r5 z`+P9vD)tbdT4_j*Ohaiu9}E!?D=$vFCetMZur)M0HK(rwk?P=t1^&tkTU}jQQB)-H zjL;1ZT9FT)c#RRwGIhRC3Y0b;Xx0#pOVkV2@+;_V(qm!cX9!PC9~*+H1|UTBGmBz; zhM7D?g2_FHOx`6}t$&+{dzMN?Eaqy{1{ZL~^Sjy$qIr|q+$?y|1g_)^{*2*|m7K3c zbh*>;Ve-B9d=k8;N$^C`guNh77cqm69HGXnuk`Neh4~cAaip@m(PEESk)+11*X2M` zT~lQ?bF9A!Ryv(#`LA*Qt83ywdhY-QiQ7gZ29J<;)e!bF$$uB~S%a%R@yI0PpB*Ks zWIeqBAb~3v-NCpA0m^Z5q+t&fc7d4}BzS&cgF$(9mmKQmRzT_#HJ_}RFV@TlFXI;R zQbxOSUGWlXj(P%_d$dHQpUnph`D(vCJqR1#npZkFchr`?WjQ>tQO+`Ay)B@P$H?w4 zYfxc{WX45JGk=6E#E$^jT`JTm>n6idlCfv7O1~u>^5_mE9}SpwpitL^7iR;ji|VOb z47ts1P?wlG9fSP}L`PhUz{`qxcSJei@HKN7Rz(^ndaStKGyC)Iacegxvq?s!FN` z=`xi#0GWW1B^ro4;Fmq)OLd=9#d4O5-MTtQ@=ZW)th=UXM?A%whoo^j00|+7|02Zn zzm5e{Z-6Ty-q~0HN!*~tDx}0~r0n-GPeD-7&^V>MC@Dy^Aw)X0P7Nm>-bQ1%pn!Z~ zvlMOOt!v zW9iq#GzBl!y94YJfdSHE`0$=n-F_B6D_@#|Y<~iQuV}InX3X2(0wU}t7XJ3;E)rxz zNIuxw+T009n&$&9QYPQg?DRpHOqUj+bYBXyTWE1W&Rt2EjS1BPl0Nz=$|Z3U0bv0w z3!;@0)15w6g74z;ow0u42W=5{$7#xhTwTS?Tjo)>y1FV$rHJ7HEtwJ|`O*i)z?j0o z@PFcY3E_Fi$WjD8+TZ)YHxOVL3NdzwVzKw59+f4Raq3K-yVe2%JXLG*FhBNiE^$`# zGAZbAJ|^Q_mZgV^0qmV28wF!dN8xvYKN%#n2g1IUCIOUS;!YvwWgY~R4@vqFCOFQb zbQ~Us`m>qV@Ma(R=v-3KyLp`7L+i78Kz|9NXTOx++4&Kmtp*y2?Ws3CKaUk6X&_c{0upsiZN@1wD33@HvZDVOW&_ z^?(irfZQ}U-4MxoGHT>Lf9gs|`VF*3LZ+EY_8(RcUN9qe=j;>fj-@&Rb*+!KR)1(S zwd#2WU(GXObdd?ZigXnN)(7Cru+>u&gc`RJ9>)*WmwvIczD<&k=965#p-eGvGM3)M zUJFyE9@u_%0GK+Hs)bu7Pj9kP%RwbDlf52Qov>QSIT~SD*WC5cYK2&z#(L9Xkp*>M zh0uSOCPSVvzpkK8Lrsz0Fn=)vmTS2!p%F-o3uCVRXynfx;yEEyx)O zV0;j&E^bH$!A$Y#_Fgfla*jf>tpOo=EY&m37G8aox(aGzu&7l_$4bT=@FJg`LfJ?k zNI&m`4hA=nw%MsoG}X`3W?V?j{9%U5qWyLnP4bpv}XvD7H_4ViKWbif?G98&QTX z!rEtyfJ_$hVGp1_G!-YnR<5MCN^?hvcWb4y2ajSU>85R!xY$6a?XP6hDJIU=v!6~^ z^0`rxDS2CUUK7OH_!-V#ZGUmFW6ANl1ASvH*qim~wCgLYOEM-e_>d)Imk6r@z!_N1 zTnggY&&0YAjp*~O8scjvQGRTd$14#v-GA_AM2?0eeSN$>{+6D3ut@ zai`(#sT^a2U<(nyrge;&)aT)8ncGm+(0;qv29OZKT#NPVAthY9JAW5A%+z*a{sjo1 zEWq?)9;O!t(~Hl+^ro{!9B9Pai>3WEo!X$cUYPIjWZ^gXt6ComiSO8odVq`eVz9cp z(lU_@tE&dI+v@7doOd7jsAEspP3=YVzn)GZ89k6~c`U`+qKCL`-z5XyeRT9zrTik_ zt`pB0lZH#BR<*5sCx4cgvwTwOyQ_XdTwWO)HnS3nG&55yCY_&RxEYjzL_pjCEVohA zU!rnAbY(bqH(?U^wL?`sQ<`_1L%0RdV#<2sF7s0wepi9f986KB5%P!#sCk@dEwDrZ zKP(MN<1%Fl1`kR1S#awgC;%VWm)PG&wpwGpRfgwc;yznE66*b zNZA6+O6%)5e5~}U5D9sBxm(+LI`vR*v`$5DUDvEtLhY1Y5bKZnJk21)ZJJAG zGEhepPXI%s{o>_D35|1j^NzuihibO3i+X+#aRS+tQR+hn)~j}TF;X(A*NO5@k`9d$ zVvQimPyS4sG=Ee;Q<-#?3@^6k98%l}8|tGnXnW3#ZOgC9L9bVL#7CGD{Nt%3>5d7~ zFAcj2gr~5{9MF^-Ep4arlVBGEqfVC3G5al6HFh2-MXhRoRg_l*7!rSfg*ROEP;zMqmB=Dm z^0!#`BuSas2k<+8J4UAQ2hCSoPk9YAl6jY)Fd)*#VfxXklZ@;t`BPED(7YFk9!sUf z)SM}Wt@deH@fTAS8u(7KpiIlw_CRqfm-a!*Zh0nITHXu{Zl*fDTrgm+rf9EM*{_Bx zXK>S%H+Rme%(H*N)$9)l{g7;QihZ=~phP}0my7_5?vS#_V|SY7XB5rbSxGADsy2@` z#{j+tFh;Jac?BicRmMv!Xlro5K$F2e^Mg>{F=6k0(aFhGUjz};GcVD-nxPG5L8w&p z_P|`CEvDEmdy1u@Ic(>F!Wo9Az&s;Qm<1gat!80&-=BY!IM>Kjfta3}gRI^FrEN6N zKO(hh%sER{qhuFLW$b-X1%SoJ&D(-?0j8y(mxb4avAa`phS+D|bOG0Ag?Lix8&AIk zx~Ozy9o;Eq4hm*##)_8NA~O48Mhur)MzsN%C~O^Bn41)kiz<+`HA@v3=Whr|F<38J zz~m77q(*D6?~F1`Q$Z}aS-MTjzIH@VP(&rDQi?v)lw_+X+u=1Nk>KoXgNc!P%^ zJ_dj3YA+EC^Pww#(4;RQD{?wDNjPDZgEllAw6!f2q&$X>(s-Op2cf@YI#pBTp#sNr zYJT~J9Fh0^ObZFqnbCI8nFY9yKB$$T0{UVqJ3N#Bl}gEmBQ*W!u}r4pt{kVVAri5U z(1FzRM)er}`l~nw+m0SfwVAi6L+}d<%h!KU_Q;ts6S<@JU?Wmn0YA{@L8Z*9>8Fy0 z5%usfny+_ttc%gWw#=IMJUkrZ~ zsHxhU?=12RG+x(UG#Y=`*8o76aZ%RIXz|czte2foL2p@VN@wZ^{+sL5WFVn#ZQ`E=@YWmtT0z8`ztjCzC)!`D_Hv4=fg57nc#INXm#(+4=%`1MUe zQ>6EPx=$u0cD^L(m<5W25OMm+w=7;ECktrvV*v_k8Vk#&b&dsT;g(tAU=@FC!vdf| z9D4@jUQjWL3pQI16i>IW8zq{pD_E&j)%o0Ru%vGA4tg~c+Z zBBLsas7JgD`|*lgk@VX*{n=07=ca)$D&V3#;(ZVQ)F2Yk=eIBj{4sx4Hk!~tK+><` zjjbk0|8S+K3`capq*N{s*@$+zxNYZBjvK9IIhT)+tInScnHY1)hS6k1d&q2U{+9^H zfTxh4~i(8;M+&>sqbN6Jjf zzYTvO6DqoQNg8=6zrB+lginKb8@e-?AwZ0W7W`%;5eI`LV<3OVsJ7|#_`OFalHMGP z9{Uu5oy&kl-pyD_a0-D>dH191(+4Bw2N?*>vbSh+8y4`Mk@VYeNJkEUBBt8FxH3R@ zrLip0UFD9hi;h0B$4C%0IAGOtQ_!eRc2=8_e~`&t%KEOk906!YDIZcW)t;fvku@i? zbHTcZB&(|nM)-esjt!Bn-PjZZfdi%Ymuj$0j&AG18aV8W6d&F z6c$!YpTL32j`%LT_%`r^a75)DT<`NR#HV5lqZn1l$OE6=mS>$pM0HD|F%gz_#*C!z zpTK0P!eoE+b1+#-=Jt5(JY|3;)Q5;H?C(!~u7_aXuvs%IvNDQb$w2Q(D4*xZ8YHmR`ZS$q7-)DGF*w3rlZ*(wde~$3G_>? z%18IM)?1+7WDlopRstvjI^eegc77IlT?Ur=-ki^n#$RcYPg&Gzk!%?4kYO*{T8JfF z!1{qq6dAwKYyu(ibZ>cQd&|t|w{a$U|1p2^`UCc99bzLco>2YmJ-i+E-jAGb9}Ad! za4W43=nWfqkq1P3Lv8kg!XDKdxCnnSn8V$5HatuogtPPXdon2)hHrIRL4n&u_?NaUaBHoT3pa*s7>Ys>3av_6RhQh(3RDDAg-dE#V#TAj3E*tVe&W zQzBbvw2}@Y7K%jjzOI`YSEl#rU^XM^Pi`H)yblkL0)J8-q;HSR_?E#aG^anQrO~2EwBQ0?7f3Xez{Y~`m-`w5|NV);PUo`i&Y$^C= z&Qil}AaG$(>59Nm;CN01cr-dv_vvA9gH z3J;=L00?xTOqz=Lkbx4LY&mX51mbZsz$m2iX+nRFv|joXbm~ku!X6J#_Ad^;y*@jA ze{n=i0~m)0pZF#R@gI-$+kR{fTVk{_S;(+{{f6V={8vuZR3tute7zar-9&#xlOauSxllAm`2(apcve3+JaJPVn$DPauXFCY5g{lj zicD(NX_*d?Aq?1Y(H5)-l9%2II6tqWoG*9qpaU)+8!Cj?D<-Ljh>eezT!Jne3`*Q@ z4Y*~-wEB8R(&QnUpzyGtq`-D|>45pI04_je553hWx?%k!WnP3h9~pnBXV08;4w1-# z4}g4ZYRQ||YBvAVBX^2uQBO0qhF!#Bn}FT;psp@-&3It(th^h(+P{3!Y+kt;Z8e1h zJ?4pNV1qtr-lI?$H{c+adF2| zF1_|s0w7*vk6=3B^hAG_;CeGnmyS!Er3H`~0WUd3H2ltSmi z+W?z;?9wVdohAMd};-1!8z{Akiogggh9WmC!5`Jm_k4pcXXoGk4NlT#Av?i`8sxk?P&(Ap>qCdS|r9$62(cKy>5) z(e=U$4Iz|>gFAmJZW-bwjM;gY40d`2*6{2O46be-%j1$+*Tu_d>Gj6`zo4bpQ&n1ezVEzbW%4EgF(l23 zr0fkRH(07!h^#S*Du3gOn{T@=t0E6$7Eh=Az?UF5u!0Nn1M76_fn2hX_pZV$88V;m zW5@%X%5i@@mn>5^#)z8Rg5EN?rSYneiKGLF&jNh)#~om@lbD~_QdQ4GscIG{AXOd5 z2}o7DPx%-@L{>hKEcN*tKhqJUK`(ikK^Vum6X2p#)E?sr{o@;3H5C@x?Zfn_K{mp;gyf>W9eUr{@twQXoxi^jvy{8Fd zPmBFLmrOBzVY&nZ|8AZc=8J|lna>FTLv%i(BHEmRMU4ijN@)Nq*sbaH=55W9(!Id} zB-l#Cz#hOcH!jt7EomM}7sZYonD6Wz*k;^9*i!3B`$a^T=@o%f8j1B*zC*BjIk3IH zQVoCq(t&T{f{9sc5pQ(_7PYzgPYNf{w0LHX!wxEf^y_gq5wFl1KoezU2{w3}tV4g^ zjKEF*M0Kd5t80q@!VjGo3!P4kpid#B)Di*aPCXr8h9!p;XKZj4rp9toh0sAdjncdv zD&3@qrn~Ro?!UkI_Vn!dm!m@uT%OS@=rMo%uB!r|8Q^R29ddkb9!wtw3=`7uAWZ_x zGI|SQL3lMI{4EA_-P_p-2!H2d8Wn@3I1vXAa+~sA#l!){YDUFjq#?QD1}>;G2kY_f zi)3kap28;c6)Uy`XJLP2X5>JhZ{bUH_*#eCo%g)R)80Gl*@z1P6Vx2|Z*{j`ON4){ z_=b|XH(Y0q+YH>K-k-fuX!#vY=`cgzM({7SZ|v9qa3>1>b3QZvS~~~iu}IZL^^QIQ ze6Dp!9p$+O4gm_6Yi|JFQ~$LvLp^94`nsV%|9PIFe=)LG^^tj`>b;;`x%oF z!~i3WuP~bjJ_Kfb3d#AVp8kL|bX9-#Nl^GUDA&Z2vqKn$3m{VQZfF24PGOtbO(4Pa zv>yb2H4i*Ut-S|#23Wa(@Ne<=D+qM-J|O(7`i`xtYQAo+uI9O>3SCX}s$)MylOlBG zz0bczr4;|8-aP*eoOolCv(i_dm>!~Q@WyX>q=l(vYc*Jk6}FqIMjG?4{7HY|;W*K2 z<;(R}@Lz(cl@c?u$V~%+W-3<=T12J7h!1!*m?_bk!iAqH+Ad1!uMWvXMQKWALB#9t zkI6)BuZU}!S$no->LQlJP|c7F5w<{4(d-gMOV4tg{tZZ-c3(gwN&W#8Ijs#q@88Fs zS%HETGfcUc;g9NzoI~umQgMH2Zf@q1dO+;c`Q4Q`vpA0P@)h&DU;{g5Y*F5!h4+5c zOeX)`&v~t5AqU|hl?*~yy-w00m0=zP8S<13Sau5B>1FfE!WzF9l158@k&hi(?N~1& z{=E-nK@i8WN#o(1wPQT$H2(6hvm}K7G(R+Ep#m0h6J$|#4i1x&0EK^2Atc&VLX6mc zm`)+hLD)5R;_!Z@Nj$u$JT4$@il2rLDVO?Pe&v-eIS5pmf;%thHD)#5n1KFxQlwd7 zz9o+!0&Ue8gtY|MgctcJuYo z-1QH0fErBrcS@7Zv}b=X`Xa}Zd{X=;a8F0Z!MkPBNG|Q>^qS}ZBiI0uHKb2OE=DA2 z+-#>WWjkG43qZYYT>@#Lu;;NLG%iaKIq>&Q!eiRu5qAin+HC|L#lOkdMcQ8FMV7_< zGFe-@!T>qw371r5eWqffBz*|LjErLp=ipl*WlDz_GT}hZLUVtDH4o_UHw;Lyy;}U$wapHn+Hy&H??UF&e@zj7I9f;=TZ-<^o9_2j&neG9&rhj3@T> zwN;k?nX%{8+~%dc>fql9|HgRXsit=RB`@@C8+?0^ZH|9M0Dgdc$^Q{w=A*MQE>xXP z`HOP(7na^_9x~VgWbo8=jzlPI0<{ca2eZA^+}jNZWw8i_&v&hh0i)Wh-HRQXW2Xn+ ztY~b^`}G##IxtyVyo}SfQG`gJUGn&Z%Db>XNRrg|(=`!1-w3YqY{z+;5spbmUN*Js zaLm_Q!PkFjkvI^8jlrul=IgECr6^wE+^AS|r<)XpB!#P(Ln0y*OD)&XVBl4-pmkxS z6+eyrB+hCo8!h5UY?X~Dsch1U%7()bXhmhSl0v9dHKpQLSzE(Rh}Qh#6fUyBp%;@u z5iExH{mT5n!bTAwRz-$Qwf_|Lj~C1g_M~Y%F~xsbba_Q+uNS$)-@p}QVo~Lv7;4NQ z=)^C-2O2}@SSo1K?+0W80kZ5H5R%B1Kf#V_yuxq98KkosL#)tG z@}hq-h=P1l;m}Oo9#o7e^GgZ}7Q!Ta2*Xuv6r<>>FlBc8rADo~qy~M^19f5eDuHNu zBqikz<;9kuLb24)G-jsvgSvAZMl4cqA){agg0ZDRRtpzQunPh^0`>vyCt{;wn%D@0 zj+GJ+M2je{5~NA&>;g2itFw@UJHaUgYqEd8Y1v!E!qa5P1$-B=ZYajX8gRXEowAxAb$~Dm0Cipm;zX8xc&eAR?CF;{(T4kFTaBeymM!-3K07CW?;bz zUXcoWrNP&6Gssg!EZ!hYZ4hL+VVC3#g0PU@sN^49-p*t=&i2$ckyNKDj;`x;-wGaFIH4uCF8`%aF;!DcNLI_C!0mC`$PDP{|H|_ zUIlIWR6}O@xt5^RdS6a233K**XkS1#wAI~M1OOUyv=WQ48fN?L_ih5Mv8>KHuwyj`)JP} z19dcryUNY4YdPHZA+GanG@MTR)9DV|B9{Zg*7{eECH z2*&dY;IGN$RX{$%0M20mpW=@&fQ$GeSj3!E^B#Q)$SKr4fx7$gDb#;`6Q4re11PUl zM~d$_K7eY6@c~qOTOFZ!R9-ICgdw*Ex4z9MLQ~9PJ+Wy^M>K+b=19|ODl>XR%9K`g zF>@t}$a^#V#Ee|tDo>gPgU!DRitkHdWs&;Vd-WO>R1`9;wLn|Yexq!xF0U8&bLhji zgJr`7eK-Fk%?TOxz(s#AdC2+r4gZnc;JG9>R{=TuJKGy|M!pQ9clz{_5qWnNkl*5} zdMYEdkAX-*5oMvV=(uxc5=Lo68YMGwACUckypFrm>DZi$*EOBjYix8z`efp6au$%^ zg6Ovy9l@>T`Mz<(QIFFB382`0uv%pq*ol><#Y=6f!V+Hqlr}Q&1q7>Ct2GV#inV7jBXne} zuJC0%F-r$oWb=QP=zR{tm8JtIlLy8=_P|bMkceB4;7?RD@vcXPi2xTO_3Dw))OvT9 zjP1uE7h}mHZ)3g3Z@Kh{3foZ>Xpse24AN0N2!~+cK}T9-a}(1M;s!b-^fumXZEx2c0_U9c`&2*?!#U^-1c#}uO0+_0vDbkGimz^d%vnhc~mLZ_gVp= z4=B{7j{%|AP~6(tE(v&#O!hwmC?xhf^VE;h7-0%h=r>i^oA$ee zT79GW?O+SAOSw=~Ylen=rnxZ)zvE(kPvv_`tn86Qql3C@mXNp=~N@5I`6Lx(^0vX|Z8dW60K zkseS*lkPap!24{Ja2>5fyXJ1~6pp#@`<}ChSIMWyYc`sVt(^vx^*Q(tsmN8Ih69mB z-kp@A==t-9hllWCGfdLk=Nrvt^Eq@2KJI_@mFn`e3yk?Bjl7Kwk5~@JLn>4L$!|5F z%k@@cW3#cb8F(aF# zcbmJd=5C|@V?F=X+6h~mo12Y|y>M@HD=?7wkDa}p*Lw>G^eOT-o8ji>=B7s;BTs)d z;E~T5XPThLMQd}rp<9|i4DG>5k7IhEF3UqOGTYp2+Na=cNuWN=ZmoOk-9N;gjh-#< z&PIRxw>#SxxwFyN|2*z&^yiX|H13b-R4@H>N==Yjn3MI@@>>r z8$Tkq)L#(B!xdq*=Bi$gx(Hzc&me!g#1mfAI!bMXj@J7STFQhpoe{{J1VJ+1(tG7o zVp>zoe0c;5B8CumyvWZA5lQUWXw7m^w5BtDq=A)}d*WlD!BuhjX@eds4lmgO?$SR?#Zf%r_NV;zg7F| zLa^cT$yE^hj21!qFI z%t((x%B=DXVG>*QKs#gcU2;>dnTLyYS3W8AU0ZAn8$rKyGHrZr=;&(HOYeN#?XoO` zcn6OSHJ_exu>lV?=;EvRsUQ^km?{Pr1Hgd%OErdmHXs7~xvJ>UQ5t`fn1ZS!iz%o& z#`7zd!#R#D|1EM8kMb~JArn0nv2d~dK<6YtgfyM$$e?o z+%`=qNS1H?3GbozC!ucx(nmGJvY@YVyobR1V;t|K8pj(lBd@)_~g8!E9i7q<<0$23kE(nnw=Xaj#T$E6LGlg$hMithKp znIp@RE{9N%jk9+L4NRoac;JHp3}VF6Aq6c(f%*QTksyi%E()YN4R9gL2Qf$>Rq|3x zo}XA(2-f0MEfHZFoeGZrz{X3Vi6z zk2s3q4a#T9faHJAL~?T?G<@zFlyIeDfR^jn5p(;?(3`%BXC^*_N79h@rc)6FOGc^C zVxZJG!lxmXDwa0nqQcL6`;dTsnE_|x8x-PhN{NRBkUB zEQtPY1q*^!OspWSwfQNgzbFj)-4i=lG1h794o81oJ4zr?4ta0(RDdl}2i|QP?7|w z@=?~Z?2=w7Z{bY)@hU}8H<$>&Yw*)7LxodE`r{y~rnn#L9QP?0?i8JFxWdgIv zbK8G1JJ#(N+Z!6ziZW)@(_plp_mx0bwCPivVL~#3k)FJgn^9J;gqkX>m1rMOFsZQS zu=#I2;FswExBiLrfIDS9U`y!%H;wvl+x*xn=>fNw*8~3We@74agRKYLi_3B1@?!)@ zD4w7j=e*}T$Qj9Yf~@OytoWcrA9o?sMud6nNWG@ih*h%&zkQ7|C5 zeCD?TqFzUtzX6QMe6Mw%*0zizdJ>>6Ao<#5%rZByW@GGMGKe*4osY2&Y$58gK)zwZ zxGQB1I)F5;j}7*Tb;t7mv-d9SZQDr0=wFd_^7^_Mp5(IG>0E4+<1|~_Lc8!DVK!^1TWpE3a z1uf?GK8Ug>xmd7c@q|^ZR+ zJ^HTj;TZj~d9qsB;!fAEGH%wzuH(7ph*$gj+Fra`K|B8*<1^fTA0IpT6?K0FyFn0v zZ~gjP@&0?5=}m5UVl@omi&)KSx3bzNOuzxQ1R1@14KLuM8z8g}c`1*XWxCie3jHeN z$383IXrWne1SyZX39a#P4#IzH-Uv&|SdYXTj=M(@h2bg6WS>WhQmlxTHhxXRtq#CgVWDln^CxV_dr8y5upd*?g^}`JqWskAGxClJG)Z5i_N>|xF|ZskBanuO zp6weRB(%&xhku-@2!=+Gh^OAr?_nw=UY-qx_Q3TG+e(IZ&$SG1)Poebd25?iGN31aK(GB};22hL zd1hOV;aG#AZ;Y&D;F^Xx9N3Owxl1h0PnsmBhxa|aU*g-#vw?r(<9p9=-30G@wrK=T zPo%^B5^MI8fs!^*@-Ff9rRcR~dze|N_^r3m6nCpB!*)}i%Cf9Psr0QE7@jZQIYVRU zCQ3VOY=?Jw6qrUZ>e=Sdu-&IFyy;niYgpSLai3bY)w7(T5x4>(N3KgBSVo`%L0~(%z;~18$ciI}O%gXYN!0$nS96t;U$Liq)mal&`aE+nYvkcqsjf^0m3%&6S zGZfO((?@8fp<=C zWDG63$Tv{0Gy2^&T(@T#p4GDr&+j>gH7p0VVFo>CF)+*^fl8qQXBa|5dU!FZ7;0G1 zvkhlR7kqyKjdkIL*YgZ}L>GGF7>+kEhP}YB9lFSL-v&TfP@fMi^6k(uf?*FYl*#Vd z04mEExpa}uu%LG6lry3Wy|9fDe(f2aN0&N%UJZRMjfB|2aUeA9qhE5N@g|=HgNE={Uo$vAtKK6UA z;d#lxGn@bb;|yGw8J6J;Y{Rh;iajfU#o`%`4_zF>TW=5;!yyc`7eG!2b6%beY$F)B zhGiu#E&#)`p#`IXYXtri8?p>>d7H-2PBwbt4+6s-Z8XvE1%}(o>KG$$V3}fSSSIu{ zxS@ZjfrA5PF5nx>1h58bMS~$i)*2a>m-vQ*wcx~pVYb{sVE7(@z}?Z(!0`Rv(D2nE^)M+0jBGr=FW8yDD6>QE`w!#&J^3GP@hb1c)ayn!)- zc|U~Z;Rgd4^x4IIM`J(vJ^k$BSz z2o>TCb7~w14Xan+(4vcc1526^m+#S~E)D0Cy`;K^(86JZyy>mCSz^xt>@QclxX3qF zjU+vvE)5QbmLm-9%QFw4081wv8Ww+m!jhl>g3vVrSY|d|C>2W*UW!t+XA9-)N>5a zrArN4AR@6;l_augf3jfNcrat|BHsiEo&XBMKV_U?aF&KSTnt1{0+?-q#6U!vBEX%1 zE^;7-&`lUMhb}VRw+$DukGM#X_(bMefF4`&k>g;wfcR@jVGnyqQq_=x zFGnZhW>!)^wv!289t6Skw7@y{sI@wTgR~$I5;+N>OKy1^XiFb zjp{eP`bPO^5V*!@*z>S>X0H!n0!&7r$xiDfQj9}As5%Ixx1bHoo?u&tCAprru zm;$&}-eSi3e&Bx_0sP?e<(X^2thQXk32qI%;iwCG)@`9TupH#H+`upaf%_vu;6uar z7QQhGeZT~MgAQC+g2?-M2Cg2FPCM_&PJkvh%m6+F+Q+Nsy7+K0aG_Pe+AiGC0d~%* zc{*6v{(u-K3;*hgk33~F!2ylqj_EE2?$S4G=km-p0p)*;4AToouuAblwIh1(AzO_X zk!raEB*DZ*EtK1fRefL%PVdo4s!U^n~rx zMMBmFuFUioK;AFmYcE7<(XRK90j*wNu+$A-4cO6<=+UQ3jUEB5V}C3;j({B@&Grxr zyNGRIFaUpB+g=;>BW@1@y3`0Ba2L{#7G3H+x`$hWYgqUvOL7rkc}w6QLYSL9yolko z5GcT9StGiL7Y-m!7pMvl*g)@rRt{B+Y4&Wy^)1o}cOPis5CA!Hp_`5yHq*!Mk;q`= z&_&V*@CbF{9#L=61VKRjH7*8{7MBpvAp_U2hhcvJ;0;<^=WyWB@^|G>(e60FN?jC8 z!KER645WF6bgAbHf)L3m7->McuD7%tfQ8rdnu+TZ>5W5<7rFRoCkT3o^zkC6G*DYM zAWh$+OHJzy?F58DHj$4i32Y*1jnZ4g59m_wL_kZxVEc5D3)^uAM7|7Nx=0!ad7>o} zq@jOH_)=2%uo?OUc^65~X0IJN1Xj=sOI%d4AW zOES;HznVS+;DLCnr_yo*qEbc{UCd_HJIete+0Y?@j@7J16DTj@2?Dw_ROUb|X`3!J zVT#f|#HAixnz`y24iNbZ!vyjWIUk^QLzREGpwWko#J<<&M_mA*1EhvK3LBQx0y&{e z%ihL6iJ)MoBN7HFP00`ST;eBvz_9j+F3Q3O5!Dh9)Dzcrmxk$wDt0h?B(3m}G{nDp z$~e8vB5}22fpAoZ7LpYl0O4c-(_jU3k<&i_vhDJ00Q1uVj2M3c zmhaheKS0zvf?m6Tt6hn(P28qz!-ftmJOgJ|h@xgku4us5E{Y%>agim0Fwwa@vwQ=j zF_xVWp&E=r7uJ$17Zi>LK;1)(VADln3qpJ@O1+!W0FE1`3~-~~kS;at>Y;FS85p*^ z7&vcT#|k$&9)V@ss{jVxACQ>A9MONJp1MG>K(*phixTXfwHz6qMKpzDn1Hy3muDbN z1ggSy|E*Yk|NnAU|HvJoI>dHBYBXBdu;JQ<72xjYEr(E_CFroAwZ&RKAsM{LRp}7B z*5+1;XSRWevLz)2sV;yo0hRoO-Vt*oJ=xG?^=C zh?-Ix*)WHOM6oOf*em<3YdgSwxX2qLjco@=`r?i+vn^3661GVa*YJQQ1q3(r=^`lE z0MtE+)dRtmffD#&0IdS5)+0eyjh;z1LXy{JRDfk9eCFVv$cy}`=P#i(3)}FA_2BqJ zq~0B*b9|r=e8Ug^yEy(#IhcP15@{HAD|AV`Z{a$A3hI6xudW~VJ< zg#5P)WCvbq5(beYp&tvtA0VR*NHG}@N$%U>25_NEKy>85~1p(!{bg9W#tAl(EK$h!}?$Pw>bRtk)Bw#_Cs&L_evxg*Q z>>yt~LB6(ycF42~^3{JI(M2v!OOmgbXCQb({ij1>r6tM+Yr&HJm*|MR5vlS`AW|12 z5GgL*#Q<-vtx$OL8rUOaH0pW2i9!tDF-+gPu~rAZa(cG!g0RJ11~6106uC`}zS*+_ z0EpLfY$(9Fu|CTWaK{H532)(|(#^KMp+d_BJA$BRJFrM^u5W)hg5e(lP!{geaZnVv zUE7T|5H3s|8%RZOL5*IzPbm3TO?S+mHG-AdvxgvUx^>fSb7Z*AwV=AGAfW4e_6T^M z1wg=Fx=%3iTjrGojqZV3_U5Js9#R(`sFfEe2wd7vF!5G3dLC-+fJSqB00wh-i#kmt zdpz6;?4^ftn%jSkjW-05xC8jsM{6U;y?N#MzA^H9mJd>S?4!N3pJ3wc>U7YkW@NaQ zi{?spaC0C1A(kD=xhMI;uf2f#{0COVDqq<#ibr)M}J=)h1BhM$_f=2?9s z8d?3U|+7Ix_NEacLxnpXptoWj7z>IJ=^ zW+A|S!FHC08`h}A7|Ro?*q!U6uGQLBP%86-vv2c(ms-;;cyIk4;n5Due+ zNDDJq4h(frZVsDdZa@2m2 zxZi5@vF-p3oB%XdEjuIr+eh&){)xF}gFf3Q^|IA)3Wg8d6Icma4qfB|x19lq=t$z` z!IXaoU@Tw7{8kfFrqrR^I*0t>+aNhZ+EBZ0|ANUSHcNPtfEji9R_WKTzb zjd`k#);=y+d4SyBH=GcrN+8;ZGo)uO;RS!}A0rP<0Bck{91aZA`iq)I0x-~Ax=^P} z71O*8f&pmBQ6K6J!SY~)9CN+DP_sS53tC#0091*d1p^18;`^kT8==6u=@%>~SkRU; zaBMKLzXv+yVUMn2C4+X>>y4}_>~X^Zv2A#LUXuG2c7}esW6x@<$Zrz z=^&5;HBW)EY*#$ti{{(VLaSEGQ`ksLaK!#!1ANB?p~VQKYE!UFg{gqn3@%vGgJ=pw zb0B{ip#WyoNMHicZG*;rI0gO~@aD)NLscJ?zaSC|zyJ{h_GFGS0)t6V-+|e44;Pfx zYlK>8^y_(3w6q*x;g%1Ia&KUvb+mtHcp!=Z;Rpy0Y+)8M?D-+=*P|X?2^R$jOE9>f zHabcRZTtYLBN!W+CMYXFRd5vph}T2fdfFp%k@H9%3Bg7^Z99u$A3)$0OG z4NyHKQl*{Y02D8ORUbU37dSB2lsPf5&{}h-41(P=mr4?5>*3}-@D0aX!2azvFM$SG zY$o+=ltrPLqtmVr@DKh;yeurMd#w_C4T?8W;T4SNqBhDH{YAinQz14Q_WB!*w@mmi z1`Pi98o)ubE&MNt5qfMvQJjBJaa=pJhG>~RBT9Y3LnW{>V1<;_q{;; zV%nl8k@#NRVmDt6QQzRWX8o;M;QPT)uyRl}LIi&;nk_uB&?FE4 zY7n`&xekUvw}4#^-4Tpne-vK`p^B%T zjE0+dkMwmTV-!5`hlYP+Z=gzhXjogg67@3H$QXgR2x#SvZ#I$;y}EGH2o4l_?s8y{ z65AQr0od??dJPVWEgdi#Oa_<$)s8ODY#K__7$%l&3}GbQ;H~Y#nGJk?Y6HXLgT4W% zRqyg_01~tjlrjox!%G+y!ye+{HphYUWVU>Xd&mF}Zs5zF`jUSJ3Xbtyo&k)8Xl=P& zES{f)S?@X9#p27J`cf?xO9d)nxLNE|%SW}A-Bsu{ZH3J*AkrDA+^x2P6%iVE+Z}C1 z6C?Fy3j|=7#;c2i5k^Y5`?x^bxzdgvl;2bT^Zb9ewo!FPXrpS8nmH5)NTd=Lq#wZjI?6XB;q(GBP$9Em^++u$w(-pGrg4Bg zIOHHR>(Zrdfe12Y%co0S7^t>~XoYBlg$d?SOkeRe8mEwkxE5HWSx(O-oxQ85>tPmq z@`#Bagd~NL?L^fxG{)I7wuECS16sJP#g67vFb{uwjo2DZIF``nM%s;OTbM$A42ExD z`R5ou$QvC%K|`VNerubK5s<p9V19!nz%G9Y(5y`tvtAv;;gg|dg6hH(A^o26)+aKfUrjF`^JpT#g5uD<&{!4!% z{ZSIhMhUKq7C&f!=7Fgt`~a5#$}C5kAX>IG!h}@`x((-FWW)bt2m+D7ue6tMkv@(=`U z&_6il^a}-o9GJ#RMWSS+DK8!d_Hetqh=}3N_794<=YNLuafLz1~Hb;A#Usc z^jQM2!1^BCc30_{|HFC%$NV3?&(5A^- zfW`?oZs6-Rp7kLDU^zfvUz`X6qGD#&tO%VO1sbEY_n<@rMT&z5mO zAc|2OrKNt5&$Ni;#!*#bL_%_`8}p5*U02}rE}B8K=Oha;8sDD9sElz64qQ1n=VTfA z)-3ApUq*9XyUL>iyo84AOjLh!I2)TRE{?J)EumPmF00Nmju-_LD#qnnKWMrA(+Xo+ zpMv(yfYE>63QVyB~0+u1*3@)SNk7<@iFEM|;SgrP&yfp|{ zt4!N0f?w5RWwHny;?@pB!!nfja%Afv2y39-z1tMoj2t-lG+7=RKk8b{qS{$zNO>Y{ zy6M@n@m9=B^k~UqUK-e;#;a=Y=u7r(Iz{_yCGPb-$mVqA%Y9TttdC zgP-M!bKcdu{r$aZ8(>uVoL@D6Jyqr~f+82-Ng5a&bO0GV`kE|{jfeUcu-RPS-|rZM zIXQlu@yN*12ie&g6XSOJtI@OWK;F~8t7EYY_*zc0<=?|m22G~ zPqXR}Tnn_0-Zq1FrND~-Ro*m(4t4`7*E=U`PJoILP&nj&5J>nf`r?j%Ye&mk32?bm z8%@)1T&@qu&n|dTMW?RQ>yU+h)j2P+8!;r7eNcz*RXoSGN|({&wkrV#^Vc_n?^$c= z!g0kERFp?WRF0=>7V0PDg|y(Q=8a5$sI#o%sb&YR9q25Z@>H`dEAVxeB@p;0@GM8& zR^}A@pmE;~E>ok4K+fcUzh62^#jL_*amu2!IwMc>I8QK^V^u$Y$>UPouk~?sT%Pch zMby~YEdwA^aK$Fp?>vbx&?-ddR9w>9hSwFj*X-+TJIJrol~sxI>vR^@*VoWPiuDQ2 z7+ZC~c+>o!eiJA;n`=s>(Sc@dm8Z8t*KUOs*4HdD&?EJE7K5*U+v;5F7iWFgdz$ae zc8J@qYSub~xF7c+@~{jRJnmcPUwagHIRE$|)NI>jz2;)+8&PT_qgaIJk)bBmP_=i* ziQS44D_cULVr970cX@a|?uY5cmqnCE6f`wkbdW={?#N97>LLP*2wRokB9c?w6`3hF z&MAQBjf7urOl6pV%~WUQwm;;KFGO20eAQZK*?A`kit*TXHT#AbZXc_%tfNaqxE7d9 z*@v5heBqM*mP$o@pftk)#Ht{O-I`@*w;#M#6J)^J{HEq?K{hq&$+iBb;6_~~P~g#W zwaQ_T6g>IypAxnvTi!lwO?L6$=qrCH`bzfY-zWM?cG`-6zJl{(wGuVnlPwE|^6x0GkEt2%y z>oETq0V*z3=|)K9tXZX|rkc*=n_U<%Td*rhZggYEPIvwn4JwquVKdeTq&UDB4gGN+ zqFWEnqO|IN5?Um6bj5AUn^TA~7N*lhmOo0yF~cy~_p>aC!c>d(IwE$lU2geIgqbDK zw?Y}lGbTfScQk0aD{5I*>~88K`BDE7mfO*pN85m^zNz}^Hr3PQ>QlJS8)LlPCa@bT z&c-e~n~mL$)}FH~BooFIny|xsD*GU5`w|!G`d0COSnEoIYb$;8^65==R(bM`RbJoE z=T-SJgYed`v(FH}{QBB6ksC9AV>_H{+wlN6qx=jR^WvsvOx4VPYBP@F)aXHQ_&l7J zy%*sHWVoq0XK@;zRcG=u@fAh(VA*G$YJuZBz-WGj2(ykExH`*T0|RQqadws+0b?2r zU0Y{=*>j$1qaXkt_1-p_xXlw@W>3PRm%3jylc#}RVCtI11 z2q)JOQD5ZonT$s~E;~wpT8Ho~wi(3i^Y$)NG|}pzf<7{rxB0MYK9rlrtd8D#F51a| z1QciEy}fwN^3_VBrhYp_XLk6{;dLH<1F!S!zr4;L<8@yA8}T|X+q}+0;&q-$7U!|N zdC}r^KDE9oS1X*L#HX0L&IC_0&!gxv(z*njaa3p#yUN2aW3ltKzX6^>SF3z{d-m$^ zKZm_K6zo+4r(b2HIG%mdj{EP^UT-dcf|m8}Bf0+~ya3_)>Ek#`W<@VcMSAZFGWUA% zjDDeObXVmG-Lyz0N@@{tl+;bZz`OPPv|kJGd)coYu`Hvt6j|Trsi{GKbe6sO7S8dd z$~o>?+kE4$t@5V$ZZbmj?ZZP`{vQhu9bd@c?mJ?~-=>i46}uu3jY}p0G~Nb(d8qA~ zxZJw->j#2%h?yX2sTeV5Ky*F3829hxQSTzFdPOB}zJ#g3ahMyzxb>(llRn#`jcSU$ z&uS89oU%>AYTPGU2y@|GcW*309?JIm-uZ^@^|FOSX)i4I_pjSmONrGNVR0z- zh?B|QUT3-%>EmWA0s2a*{D=R4?(KhUZ-4i1w737%-rMic-u{E!(%;IPcdfns?d><( zC;vGc?Gsgw`TJIQSf2f~74@~`5o|drk3dwJQ>fU_zOLzH?sCsKGxE6EPoWLwhD5a1VGdl0D$MBuVs`Lo63LHs41I8I_Ld=H_z_9dHv-1 z%fsIuJ?!gOF&gGv7(Y&R*phQvm;LX+lqgR7vL9>Efr_k8pX*v_oJBTxiJB;(|wi$Ki>V>8#=fAv}TBrXZ%C)-Wy*Jx)rk(#JARZXOj`vW&D! z7!KtuR+sh9T@k@0DTPs1m4L3bVNCR;C(3VT78ESddL8?hrK;i%s>*)ULhND23f2d# z-e-~0pkg}{;#JI*X*3)4b&IyO{<~}av0cmjH`=xA_OA5{?OK+9+^k%AW43lJ=bz7! zy0_mbfBVnbD1TEoN?&2yS}Pau9=}2z*w|zcYh0z|RapbhbX1GdvVbVlROG%7rp3fG_6XQBz@Yb4zdFsPz030 zEe10o<~GK>pX35ZjKvdHv07&N=jImy9J4G=FFkUc(T+h}EoiE319N1RP)&3U&F>v5n>5 z0HJlrOM#16ri(4A(62&%?6U$$S+m}IQXX>?TI1my5VJXK7HmDJ=E($-YwKwoU~}Cf z*1U$Ec7*V%&+zB>D#|Zz$s$GJkKx zS-qZN7~66$@uEveCNr!z3V4>4kKxn-u3WVoLC$V`x9*UEdAnp_4OD_{s7R~h9!X<% zfn=t>-3E;4g<8g|YC4UILhZ|kEhsfI!WK~eLFjb0M-VBXK>tUI0hv+~Ps@K`pn_|K zl_L~Zda$JK>nt1MV*rd&5p8pe$bSmHd9G_Z*jtn;YnUpmAqX>n*L0(U%K?GrQp-j{ z@Ae^yit$xE8%Jw8M?z-o8IR==2v+czP7AP#XSSAQS~k>~r2`s`=US%kvfF$~h7|`$ zX70-LkX?~cdm#=!Oxc`kQ=a{-ZS)@Zepaw)4Ow49{-e&9=vQKoNeH9WTYpJiJ7FzA zZpS9G8FRp1+hvueX&Ib6F>0uAf(pxY{p3JwMWS>ft+j$n_BiHR$P)v|5hUirGE{lw zSn|kV$=b{F%-^`;hx&lG|9TJHqyu0lew9wZ&1NO0F{ zR+QUD4{_CPjjQM{ZZe+EQN^H`&*s?|_Bpx`hC^%t=G~nt`h3_ZuYZeab{+|vhiP_p zo~03Lz84+FXYrz4VG^gGneg@0VK;`Ou->h(P@2)HL)mRL424#C@~4;CQfB?>rFSdA z^tOp}k^a-!)*`QWp(5>85Ehd75of>t97W-6wSq-{-9}r)u(LuZbXJ7dXa(tj0-Od# za~!yN6<-oXyKmO`IrhyOztL`mpFm+n{}wtw=N3kc>{C^g@myFx z4We|`zrKCjZ^L`=x;gw1O|x`{)-4SRDK9rsLmGVnGoWYD7pW@j)GyvfkC}VB%s%sA z*PA%n`6l04+Qxz>v(1|k16o?%BHKfH>b0#CZ}H&~EuC#s!hbG^<|Em^(l`sxJ1p+D zW_eN8`(lKfN+hgN*IgCFB~7w=`#}5WDIA|0$1Kmj6fdIuMffoq=jzjQakBV0KVh&M z$LYWVJ?V-h8tAU1U}-;j&s*y{r&SO=gmQ~98DxekuQ~oC)E~+=&YFYRP#sP$kbUe!su zWPGKFp^FO@JMCGZn=+@kqle7<@QZf%|3STys?8YJJyE zg!QMO=4*;MmBj!YbADAz_tVY>?eB|`{2X0?9DZ9B4*i3}&`{ZNd4lyZ^`o-mqgcP{ zs(-IMjzJzA9mgk={5U@0#Ul+K7`$MqKBmMAO+2r4rl^UFN3w5P3VIfhRG`KTtKq5g zuv!&gSVs$ZN7`ytEDi`-?Ex=qq?qqoiCVL0;sd8bw9Jt*kq~St9<9Av>uc<4 z@roCZ(3eZ`nHR5=Rr0m9;noEz^HM{N)q0IzzvjhPD)ERHujK~(F)Ck3%vQQ|gcOZWFv)z}Oy@I|{*o%7-u0sAE{UML;-gnH>11ZS{UoSuTp9TST9GU6tE z^q3c)l#hOGjc-JlH`)WYGvyvH>3^I1y!ci5<_&$*Sa?XQkArkDIM6|~d0zwD4$xzj zwKg-A^K)QPu}^sMhKBx*SWeCUQJe!!r&M~`Y&NYy-pd0Fe7 zCMD@*#>E{uI4QGqHW<_pVqmz54f}x?mrB*|Zd-LP{obrif1v-?2^IJgFMr-C1-@00 z_7kmLXr%vL0_b;Myj4E?P4%GE{wRl*q)JQj@6CyJ_iod!D3in zuZtg*vBr;i@tCzzNh-{XAAj1(AES~NKef{qVZn>v+i3;l`-O1K&%F3i>6o>(P{1^& z_<4J=n7pu*5AEF(p%m?HNS$6&S}BHr3Uzp4D}}nsWN4L&WN;*=q|Xai`N-S((IPDB zj{;tJw7^CUZoOArq*IAh0mTlRcS>>OK zD5BOHOq>_P)vDyYitwix(Gww`D(6*7-k)L~EsWoe`=_VVERP1Ciqm2d=F#l*w10vF zU4^`gDR0KAf@@XAzdQb4|9vk9(zrW$&}>lePwsrjst;W|aCNr516Ln;^`Y5;tA8c0&Ng@8>VgyHul4`8 zf436sLABJ4JUUOpX{1#P)_?#0&VIj1`mSBbs-|mn<8Kpf!r#Atuj#AaJj7)3BYvu-`Xm*qefs<>uRhZ_zUI|e4VD2J zB@q!-9r5Zly?+kxX=qrVm{6JN9K>ilA78DvuwnIpS5K7!4mYqN zVV?bc<&;8Q_HlHwg%$_AoLFO%iFN*vSBKPxXS{!Untx=ouvnZf;8NQno}Ttu^RIi*OIiR{FC^Iz=@ZD`8lO+RdP!}6{0)u!bywqL zo%cjDfRThMtH(_vsN(y)`jskva~;r>N}uc`BDMzTt~#z0b8NBnI6C3gz5RW~)VX>y zR)~n|4u7wnDAis5g+xSkxkW@&4_GTz5E0eGb}|qV)u(nE5E0e=b{Y^7)g4+sKk!N+ z3afW=`Opes?WJ@DLof!iqWXcIh39aqRY$8;@w3jzv{Aez#;N*=R|$o_94o}LxKC2c=$lhE8uC;KRv}hoqwM8_c)Knf^iWW*6+MhsLZNGWk%bR z@^`J&C+Ts=iDQ{G?nCeUC*u?(6;#PDyi#b(N}(;QUr2o&>DQ1@8@S?UUMU1!WhvB< zQk+6RRVJ?#O0KfIzfg#$%Hfqlrd4hWW!ImuoTu2rMy>+W6!J1rB50?nOXUJ1stDEcMlDT1lB9wqnkwiBkMb z9()m&V0-fm*WnBy=dO_i<}gFblDn#sBmw3x|K@qwtuIu`1BFA z|8rXmO|QT5DKQIE^kXv`g7$2B#7Cw%v_>P_bBC@u8d+@moa5O9b9HPDMknuQf79=L zr$F*v3sbkrki9*v9Vv>`|K;GD(uIdM|RVMTu*So{0Y|5%)x`}@)N zw5d;@^65Ql_k*prDy=$f0Dq{EKcaQph4bkHD*hp#5`Qs$);WdP^o5$9hZm6cvPl!} zz##P#-_TgG>Ek8|CH9c^Yo}yodcR3N3eO?sO_TBry99|(I^^NgJA6xp#-^7|;;RU= z{h*{EQ3i?cn#6Ze_*vBb(?+lFSMxbF;BBjy;oCU+0?EHCy-KpM^ncwNTE8`~4%0HI z(|>8DTYmlG$JPtSu3!Azym%9B+GLWxej>kr|OodkXu z@F`Jx(-HV*9t|BpH$y%h8NcoC!_|ljIFUnR#FB_lhm&cbO^5n;O5|cv@+87SlJxdF zY?7-8YWh_}a(oZa%`3Q%@qQ0Z^O$V<+W1X})UZz7i}&{vz<)_B1B8{YR&dUQ6+D|v zKh)#RXaVVPLJCfjDs(vZns#fgT&%aU*lxC%5g z#qMw8WZZ$GAAiz16jmjuw(2rht0W|vB`J84QPq{A4+N=eOADAxc|t9H%mx9y1 zq)<)=Cm_fZlIG)+<{&Z*RITXN6De3l0<5K|!yQZ5l{b_K?NZ5%Cv&9<3uT=M`Rx|A zK!GBCea@4G^7RMRjtp!sCP@sgCX!kG#TidNC|`VR>woL^_klcS$(dH_QYe%xd7_Ay zlZ$3tkClVDk-h^myL$eGCl@qEr{6F}kGeDgz2r+XMmTsZRmUo)Mb#P=&S4>!tJPjo zQ%1S2uU0~{l{Z>AYVRwaC^FaNb0@4p={HVZ)!_chlh4XWue-thRR#AEPe}NhfPX;O z4o1ErY=2H#R1^}uZC)O2*oY3!bs~iG1HIflA1?;sDNpVxg+I6@3&&z^!YRKKSw6NW zqZ&#rLy{klY{qx*p72a>PCjF`hdg!0j{>z zn13X1dGeD|!td%j1pg?>8A~3Eyub0}cO~yHTY0~-aWCM=y_46lJ`U+{td*-e6Aj|5I7@6Sz)WI zirE=BwAylufTx`2H8InV(^>SjkM=JH-t&ll!Tv2huS$GAuS#9mBg|)fPDR~LJv7W=f-43YRieDkc`#=41z zby=rP;=`_zUeq~(1QILoEua5H%i?#rE08?~oByV2M{2M~aG<6`&9S8`7*-QORZzpQ9LSKGeta5mr1a`HaL^ zGjJm_%el>FF?ZQ4>=rrCifxhetm?v|v*{KVoh92M=h?hdOV5@aSbBERfu(0(x=7yH=`P$od(?@$XMeAD;_lh!ow$4UwHtTO zUhlx&v!fljd-i+>?w;Md9(T{4?!w)(2fIYrv%{7Md-hQEiYJ(TR`7Cvma+nkF<;dsg&G@rzJg6tDtkU!{hl$?VxEAjjz@R8J`39IcJ5wUWcod79wt)ir};h z9tvX6P7 z79X?v%UFJi%{u4PNi|7+94Ehxs|g5Q57TjS#y;>w+P9sn{Cli@Sgj(~uH(c0z6Q$c zn1heV>0HZLSA{HF&km1g;R%PIf__fv=Mnu>^fRTOSM>9le!kMrYx+5&p9TG#)6WO` zIisJC^nbIYp9}hVPCxhP=PCU>Kz$0_C6q9ypD(rUWA=>CNO(1S!4)OQ?4`0r%)pKN z>;-LYvrl~XQpx!E_F_0G>61dCm^9vvQH7j&RMD?|_L!P>pZ6bqJ&&ekH0y;mfuQVY zvp4lwqOLugydRQV&z78a_5+_?Qho2x1pWB^ z$$!b+)%#;@GS&u@_p`g&Wc=QEKf9|>^p$qp|34?X2Ja?&?`{3~f8W19S-pR6=zp8& z?`{44$x54W{9^U~`2C6A+^+8EVCg*jiGTP0z4rdSK7psVeD*_!la%9H?&yMtG>Bjr z<`1%2bg$G*z1Dg3`#Oti>+9J&rk*2Xh<_DC&U_L#`F;X>>%KltSE~pxf|QTUe&@5d z1dHFe^_>d)Uv_$XT&<#)TboSD!Q5RMLYidfV|^EKKA8PB=?~2QSb+aWJ|o%S>}RNw z&8%Ha_srxoYcjKH!}Tq$duHG0lM-h+Zh$gn2GZo2t=}cVRI4*Hb22j}%MOyOn}7QD zbE|I-pDBikGq*!D-tUiRj?`()d_GgLnyT6*nJqQ;M}3UVoPeou@>HAsuFYWo5#;^A9=Lf?XbzXR*9mU=7IZ;%y=1Ai=W@s`eNF3 ztbX$Z@BThEM)Yva7D>lf9e?WdXw4RLzC-l|7Tlc&^Vy;+F128`w4<l!#FSwyetF99TYu%OM_Qll$te%ZRb;d57?%{!;R3HDIC;rb)?=m`tCEs>169Ng ziijm_GaiCR0C4f1og6H{m*ONvq7wY@Yh=D%fNr1V$JxooVf{jQZeWY0R#20VGdL8B zd29VnPAmNaJX=YJ9^fDCw>TL0aFD{H1dA5vak-C?hs(=0|F&sht?c$=rCacwg z!s@6qPaGZ z49jZAH;1oYy??oXbol!9;jw+zJGh~>EXkByS{%5t{%hP-#w>-)-`LW+F`^G`S;>E)sC?AJ&yL2&7Sor4n-ca_-M_Bsv zmq%O0Hd91t#`Bj)hd<%yH!!R-N-2Av#`*N#>(`HtUVps41{})<+OXDJa{%1P;nM?j zrWF~=(_L%buIll4avJ`(;tMdGVB4<0;v_3DPXwg+WxxUY=X>&1luM`^*_g=o`P zKnN{9x8!t-uc{JwNfR)7E}U+$lsD(>R;yCRmKT}sCl!!a4L)71atwdjWI2M)vW(Y) zyl{U%#D7SbadAkb56*gwhZ$i6&6km+i7q2HZN9Ab_bZH#nWfZuHseVD9rrie-DmxF zD_aTJratSpThM3y?fUzyFKg?c=xo7Z1U73Mr>tGuIA$BQjWZ_88PC^jrnB=JE5D59 zy0$Rlx-C^y=b=VV5efY0|CrnjN1Ir}Ras16;-Ay0&=KV6iqhm_!iUP+;{^?C3oc z*nFeY8_U#UE!4YbwU({9*4Zil0wSeH{0q2kf7NWLVUmFVIn^JmdKkMa-imTwW>GH` zI)8sHf`d#_ZShJUFFt6oK8Y#(i%O!VT7=`jZcB=QngzLe3?^pmxGDTZXP<9uGBJzw zM{$d`}&U!S@T-Ekkk1%I%$Tl)T#0l zoxQ%csttE#NMhDS>c%`y$|&!0t+hzHtA>qGWRanR@PKw5{a~`;H?ryLSFL2k%b=+L zcr)}+|Kan~XU|`sK791_(d$R2zdnC+`tI=Q)6@HpP9Gn>geX!c`u6O+&IJ@qeSg8* z-BdP3E&=L2;=~96U!H_HNnJe^ zyJjmYSafXHd|mOGYD4<|gk3d0xyFm9o3l0QXb*eMUa`+7I(yC+&$>F*aE=J4Q$dR8 z?2&ebBF1g9lL=A>&ls{J@UXUP2!CtLy}z&Bra)^Aj{h`WJC#HnoFQy|DaiTyn`n&# zs$ajuWc&Mj&`YI3SkJk9W}DmR{{HjkExgGh= zj6cW>llpFZ&$?Q}Jb}-})-|c`#%FZ_XWIqT8{5?yY z)=sF8LyZ);J-C5o-5PYZNq>NBj_Jv@^M7;l@7*~2wdwwTlYwuNQ}-|mZ+nqIv!`q; zC&QJ)u4&zLdv#I+KWsOUzyS^Xu-!O?sJj+vbbPShY(BmEgAG61ZnzjHX!+T8%T2cBTRP_GV9G9vQ$vurf8$VgDAEbN8)gQ z34vU0xrwfIeXMhgk)MRg+6@Pp8g8AaXqd8?Y^e?If}=nK6zdbMR&iS-O$RL z$T4d2i|rGA z%d}ys3hq^eHNHi*t^fiO9bA43!rY{bYJ~a2x0KS-BW;)Ut_9!@+|*W1fcJB4mv{m= zRn?&t(#42JQnC%$@U||_)m({Kr1h-SO8&d1%OP$oVPu@*4JnJ9spYMt3!6QYY7cb4 zq#IP(#(#{fKbKC*H_DLu6e?q_e$f(VY~@a++jA64u%9+(J2ILOQ6x%B5duco3A7XS z?R;RdM_hY$4mLL7N2JEY=NqYdM@~&=@3by}w2YS;qo;e|2$#YQ&P3$(FJaM}hSkSK z*@KY5Jz|0%XZe|?W3X=M^jm(F1Ir7^<9oF-1AiZ%H;;(Mp0XmM*mK4B8Qfzs#cqFD zKMRIne7{aX26Oxgo{4)HU*dfuJoo{g<%bX9ftb?q3ntnYe}+$^@g3H5WBhK-e(zpE zbCrc(>+HAx%f|K|V)kEdCD0V1V>b9A3IT$NwFs`3vh3~Q3#q*YI}(N0hp!ruLi6&q z`hWFVM}|kT&JW5Fy?m^xk6POz1x)<@-@LYZ%XD4F zf99D!?&skw&Zu~$lpHE)f3Ayo14fV*dml2;ier-NR`KMsxHpUi*XdOD$S#h zaZyG&_`?-ETihs&*{7e1#Buaq#9{+fql|Y9jfiN6UgXt_@D;Vc1 zVH~iO6|vips-FrIM|A&@N9imgn~XS3qx@wwKWL6K!74aBJBPz~@iKaX};uw1aHj)r@nMh?Nx*k-I9#MdTEk)=%2q?3y$ntpJARZ|1vzw=bqOwoNqo}wq4`dF71gVs9wO0kHuG^#TS+=#}05ac;L zSe$7k%dpitdgsAzPy)-8pntxNCx`}8&v#luf^A2K@uM(CxTm^nIZh|F#muXVblM-+ zkNp!ZW>?{dEH590d2#^;6H~G*1Tl}&l6%dVbw{phyT*zjaLcVs(&1pWlt>Bd;#5CC zarj0>V6Q#_)iH7NT)zi&$?qs8@xOCVKf5qaqsX2tGlJo*@L8%P+)fw?hKfst);iUMiZHAW;R;d^- zsw90@cNrpB)@Knc3-S*vu?UHR02*2NLM}JLW-T6US*!yqg2BFa+CP9F;RMf~t#^hW z6GT#L4jxJf!|@r#C4c$G`5AG}8NfqB0dxxAvlzIq1$46&8w*Y)V1)5VIV%A6&uA>& zLl%3r>X&&H33sIPFe&i9qteE~3b+Q0C%Fu^mICt38{6$BI;KcNYwocy6@JLO&bWMu z(^>XK+EMRuP6@^=o8pO$-EZ2+e1bd1)9@mzO43M;744K_RDbxaS@xTtA%df!(vEpFa&8ARJ z)h=gK!2{Xne1B@R2p2ZvQ)7d;xrKQj_*iaqB4s-mJUBoCo@vfz5ZLWR9!j1XEgDG! zGL~4NHG>%4=SmKsnqb%cz=eEt!RA1%P1odCsSZ|8wD1RZ1u-ed=W9C4ut=2So$-!L zS@$Wrj7Im27d4f{J_39TcHEaKO-Rx%Dko!5Bg9NTTYs|!`>2C7`ljp~{bU7x1x;D< zaJA~Amn1yBx7Fk&HTgnq@|SOG^0IF71vL4~4Na!(kh5v#LMUqHS^g!=XSl|@lx&d^ zVjA$oH2dipCTNVf@&D0CKN^k6%;C~aZQi<0LVUT9h=jxYQx)tL1#-Q>^a66 zqgIULHGlYVTlunTlJa`B08DglH-?2R~(1IO#?7yuMJPAeh6 zTm6(Wlf|$Tvc=}Ytv*E8^O*k)-w?d+$vu-? zd2a8E;-%cDYA>4`lI9(IcoT$IU+Wzjx4 z&So9$EV`>%(2%BCaau%q`42Vh*ScXHGTp_mAOfJs**9lUI(2wW!@9af9cely{1W^_ zJ-gq4d}DIHysq@F=1DgRb^EHcSj6+P!|~<7I=EdkMQj{6u&*#IYOJ;IP1KFoa(@}v zR5mM2!Iv(8U)eOql(1P&EoEWppH>byim1W*rUNL~09C+Hu6#K(8%ynmaiR5~mhd7w z?}&QeiFY8Tte9?CtGqEj#OX|1RKS%o%*XNCPG2uFiXSVjp&GyJjgu3}emsn4Z*VrW zx`rWzaJSn!KeoTGycC3JkV0oUc*e1LftmH|>O?i?uA+1W zh+9jd6%XuIOJeZ`mqIi1P>`1&!*Lvtf(qIU#Uz4Ei;!HD*p+7Gd3z=x>wC+_G&XL^ zVP7o*VIY<(el(m1veJm40G#Mnz5EJxxiJB-Di-WKI~PycIfKoHp5TrF9DnH%?ie9Q zN}zit5E7+{2PPI2C5i_|qarh6dCd+z7BK?lGpmrHmfnk`g)1JA74#?)6wO-+YN z`_&ZI!p7=*k;GbfMa>|Rn2I#o1whK0iD+I#P@=mZMc`jHqK8ryJ(MJy$bjK0#YDeZ zT2SzsZbqgwW5}+D%^{;*LVx}Or2Dy6fVirIL;dh5QNALOj~D*I}jnnvdxjs7MDELM%K^+lJy6kYL+z` z!u>mNqVETgm>@?X8@&FmT40Z%M2U!2ecy_kV632O$PAc&P}h z(v#cyXaS)x`e=#4yL)`1I1Ab3qeT(d{jT!rid0?%LAa$z9#qKY-y6><=rtylqIX@1 z`=I*&s%OY`UgveyKSO@4gL-n7Wq{bq3i67U&{ z{pd(K1O?3GA?U^LT7Sxp`}7P;38a6phESlSs$AKzbNvM^|F5R88l)BHV74qG(Na~bo9Y6jlL)#wKjBCPNLyjZj)0;*PzGwze zQTfw=bU-<5Lphsdw}W!aG1JctRobc8ebT`1M{>c{d~3DL3mf?5HT=M)RKPC;5accR zWu5RVI^b9R*?;g$C+Rq2fDOthKZ{ckX79CSSi=5U-`}V6*wP-l1@vN4w16HfKo4u6 zhdM+hYyfB80Q5Tz(5+3N+v=2k8h(h9W=-JZ^$TKgDar;_ZJs6Ln;Vcq1MqNg(+cM= zSvWP~D{hVH{%H%vyWaodAH)APLUIn<)I+q8=&>m<~#`qW{Y38bq?|8qp*zf zI85Fg!jAixy0-ZF`mC?eT~nVe%By>YBF830}*&W@Mz zu=7W4>Bh&I`thr%Y=2Bb6!~rILlJ0C`fQD)jYZoNq+*tZd{7-#jYV~|U}GMqGmL7| z<`>X11Xb_sicCt_2O^y*XeRp+rRdpR~>1scQwK^M&of&eyv)yvGraRxLDv1*3 z!GE({rdNA0*@-=tyF&(~F?`>$NzPDKg z(nig5sUs0fKvC~&Om4W{s%{VlSF3QHsQP_%%x}_JP~cMgq3|A=3(2E|sBBiXdw-VB zV{FAv6z4ga_D!EOEOEj>=r7RkflD?tYLmD25az>%^?Q2qlIyI2URmzaCf;s$Ep>+K zNWC9zO1Ps2=7`8;Cl_L zuqi>4p)?QI9>(6n3xxSZoUz&R95ylW;b9DOOkC$Zz;8YVS2=xuZCHcw!3x$#bqR#Ie+3>ekT{bbf>9*rQG8=G6h_OyVI1$iAq*puv^4U6`#VK z+}o_Ypi;oStSzt#S$_Ajnm?T`X<~m>DubzIc(E1r-X^9CdYP$T5xR0czosDtpkZ(V4<=DDlG!8iO~%x_`|1$2|KwiuPy6 zkBXc>Bhk{?)UL+@&+}MGmu{ehu|j`eyFLIATc16P;?pFlE#h8gDuJ(WmTqueIRKdi z_U$T+X?^BW*Y0f~W2TZQOgzwluN%4ertou%1a#r<%PhX-nPFosXk3#wQ1~~P$*3}u zhy;rfmb$zm~+jtWBJAYF)iKm-CgUYbd~HM8J4*YMnnbs5DQjNU=@}- zJ1Q%Sl_^rx2q2r4cS&b_T>U%G--@_SEoX}ycyuSdeUj03| z&!2hd3P42)?jS{j-@|{ygVYGqC57nA>drURpyxEc(qQ6|96S>9lhZ($bHk`)$}US$h{2vh$7MN& zvF$Pa(!Czl!(j;b!GX|B2qhb7wBuke63vz`Co*)b5b9JS=Kd_2;j5gnl3u~>&8;RiMVtgoZdU#oF-purx*A2)8y;Z z?7>2yhBpem1Ok69VN3)1u=b{~b5<@h#4Ev-;e#Y+yG_xa2y7IVUZUoTj|Yy!zM!H^ zbf%$22%~`m@Yh!pg=APnYl$uivJTESk*`6dXXPaicvtGhGD#tpnbN$Jf zyR3o?nY|MapTIC-fTE;o4eT2;N=>=;h?_2*fIVY`ikN>rvwJzP1mRi>0Y$qIgu~o0 zhdSSEqBlm-|Dh(8W-<&w62jV3uB>>>A-H74Hsr51L<`%gmBqM04GU%v=EzyN|4(ZO z%*IZ7#@qoUN;pL$h}nC&esp$=(u}DarR$iUr0(?WP3%tT;o+VS3~-}2V(&hO1C683 z1EEg_GXZ~~v0>UU2PUB`NzbGU>F8w+uNxZ7n3Y*Tz#mLv$FMnaPl2{8luJXBgfS?2 zBcQG`2b@Po&q2e}&(+V!++k|Vp%bDl@`0ZRmJ@S6#rVL{8!bc?Ro$K)J$NjM^!=wj1XnJj6y8Cd#J>8 zF42G6tN>9KVG0p`m=Fo!_>5kG@qFy9G@Yob6p>|bWkDD;80X9T!RY}n;c*ijQS-=z zC>GIEag6dU&1mc0TtfL9hV{cLtm8d?u zI#YQa@Fdrv5*6xzn@?sQ=i^yt&q?IQ?kcfogrD&C63(>^17|zR?XD-86Bg&^O1{K+ zWC(a0N(@9yA~MnCXhRE)A|hrdcJzM?{A#?=@(HO9T1*QQjdDuT%g79^?V;B?Spl=e zPnhV9QKCl$&9dDtNve~Wq{2ua0B^hXr6`Q7J|`ssk{0IB^bzwDUP=8Kha;|fCR=YGGY(kq3*~L2ezz?*AhE9Ls*^T5C zT)JP0t%Ae2z`IO<`ghR&g;Q#&hJ)u@MtkR6=mLekW6`N}Ia1yGg635Kj!@POvjZZ_ zbDZByAg=b3rQ*(+bc*IV zF=83Yh(sIj#WXyIX?UDd8Pb0oUcek)==Oz}!;5?lb93F7uiiX;`Qijb9a;29LQ@6u zgt&l6hI~MI3ix!iVBGJ+%lJkk+A{>66dBi1QaT}(w&WQ3Tly`y54e=z%>XMA0w&{{8xRn&RlQ5JCox1CU zLV8R=5EF#_CcuST3Q>chyw{IB2lVnloqRMO6DoXZz)(=KH03w$Oy?unZu7^HKQ0g8 zO>wO-3u%HkH85*#O&5Q)x$A*LGdG2lFjFp;-gL?Ck#abv#ybY+dby)M>uBDM%yoPc zI%~XXOV|aQq25n2oorZ#Y+9@udw2z%aWmcC)O|>aD3@iNBdeL;&E_Vggv1jJe$1Us`;J z3gqH>xeUSrmt?8<9a9B=#xY7DL}jJ^;|v}hXaP9Ul$^U9fiII(m|yCW(Ck25u^(6& zs*B_ch9~8(`80o*07RNsjEq|VN-?Qmys-jT9XnD)-cGq{S%MMp85Nb+e@ko1ft zcZ*7&1DUY>Rw8V_{p%98e1E?!v$TAJ&uCOgj|ypMp7icw>7_JZ<>*(QJn`M>*-kRO zocim;JEw0z4C2(?R4@q^eim({u^S{ncoj((Ub=j~PMLqxK@Ej5Lh{9saWpsh&37(f zLa~@2*#+&vNHu-CRq=*|i`L*)$cetyHo!$k7)>dSy=e+hveO`w#B{ojVMOpE?vWu| z1ir+ADYZGl?D}d(b{dCr~RsqKAj&YoUB# z=uUCzC0u`Tro0G+S;8v;XD?X;y5!IYr!wy%N!dAtGtZKXclemYh@7LG2-$L&k+YQ( zOSM%i5-6fnSG5``Qw17fy|X$vg}iJZ7>1GW3Sije4I#c2X^?|MviOLvm@dI|{xMI3 z91I2lwdCF6s|Qwf$hs8zsdX5VRlx-1NN$1~5q^Igl=~Yidm77IF(5AokZbCOTuued ziZ2-C1wso!hf6y)zmJk3_eg#bG;rWBp{!n#yNFD{P36}nLNgNX!LW!_f+;@&P#!o1 z;2s|GT`wo@h}ho$8mr=Py(wBA<<5GFHkjzN-Bq~7o%x!A&r8_X0S=kV>l zE=_+dbAHD`G8Qn%Ryttlq2M7ABw`Xs+Y95g%DYc`0h8IvHe=bV`>~pW1+bFF=2*ut16elNYz8@?JpMuY^K!DYv-xDn1=) zFiRYC^y=B{pnW)ZJ%XYkpk(sPNjw8|-6%Rycy<$#$y}0>U*od80Hciaqi9)ydhqXZ zd1i6h%3^GzJ2ylRGzJl|iQe7#1jf2hI0IcjP?`q?Fc4Z-_TZabODvqj-V)b-Ox1rb zQ>NkCp9$SKR4z+HrgOBWjO9z*)Jx_bO=R`2oYe{ht7Rzv@gHuQf)Jg~Sb5mYUZ(uV z`}>-E0I?0<$23{{$dEu&@ZHVc+p4Ndin+y%@JW`z*NG=^jNuPfZ4iaE#Y!^VLEK&*`Drla>DPWr=$u!Vf`dTD2 zK_Wd$wp(q=u{_SllmPfJV1U>s06+{M`VNPxspy*!ccs<73FZ{%hY9hDPT)J?qh!O& z*p*p@GRd!%D(O0@BTy>2s|d4>Sg91LqRQx{w!v#apHv3UJJ0S4=On*ATxWj-kP=?S z$&dhgu2cO8Dr98}T7&Qw$~BAjMnmw53HlYLqD&&7!?Rr>zc@O5a0k%8p$j|q$Yx$CW0(` zCu0ZBsux>^D?1-m)KcgkoreNB={6c0WK!+4JURIRgI8iksUO*Frwrhbkm zu&hyt1e}!9(`W_a%uOzr(v|3JXF?Xrd`KIU_Oo|}6xY;+&axHDPx-~N+ z@!xz}^Aq+aR!KUFxsrbZNi&=jNqz395>3RCSg1OO5y1NlH*CE}<~YN@c2h3J?#eL! zD$i$)Gh0f{*AHT|@+{3U_>W~DK*1^3onhdK(H*3_ms}Tt!9zTH%SI)tK)Tx522zDT~44g>cGHaa! z5AMOmM<@o?C8dPC-rO`S$WS#DG5@Xy=Uq)TR6C-CI%pkHzceSpJt0UiK?3&(&YnU| zQD$;zq0#~FbU=T&!8ZZQoH4SX#F8+nI@I}Ci;)2cvO@57!#HM0W1LN?Uuw*&TvDfrHFpGGr1v%u8?}_#viCAY!ke9T_c8u4tw(G^1sp z%`-5jLL7hC9IJ3I$YoS0ls$@6mH@;zN1vPv04BFEghhe{m0g8$EL=CGdX{6XEE5-j z(f3L?*P^$(cjv;~0CY0z+(fY`0ApR33y;9+?ECCt`hHw-D=P#b;)XPqZ%94Cgu0m% zJz=ammdf?9MAzL>^!-=^Q#!ETWo$=40#0xp+x~tACZagc1U@SzLfDXK11ykziq#)X3I8 zf#Lr_jk8DuyRBQi^(^{XhPmIXF!!7D;J<%0O&ht5kK^s>Y&$ym$LYQQJpAhP>(l$E zjnfCt>G1Tw-@V_QZnOUxZ%3zV(|l+)PS=lmPoA8vpA1ZRdGhEOULHNcmnV;(jP?84 zsqqKYs(-C-HSP4W+0-=+AI$CPr8&^Q)=n?Y+3BU}>iSShzpoE9ZFG8RT8-07vwwej zX--Zr&FSf-NgJn^*8KFcHy>|LFPqkObb8rrHBK)(6X?=qXVy5q?9sb)Z>yc27L5(0 z#;~sWUFy}|Esi;cj)$~lq$+Jwx`DS-S&U(Q26UlX;Ift4gJ38>?e%x zPafP|Mt1LkN1}h>W?ZIelnl4?G}3=nC(*tNrKbbmlhZ<4rTux1)p8 zdxu}0YNtBvM{?whx3>QEf5A@CU_q?LV0=2;TBozq*|s?{8*O-Pc1C8SGuBUyKQ$Aq z-rqp|*97WQW2kHP>FjHLsA~wue=rnp{|gSD2Y*I8U+XZcp>{g_Q-%cu4}dvW6JR=T?+6tD=T*-Vw3Y-v{8dl;z>ze^dx_ zGxozIBD4JJem}u0#1<^)9&(ra0-%i2l{`g7KWZ4#gEz#rUgRtNOwU$cAo{cNg4=Xv zy>Kt{UbvTaz2I%TmzB1Q-sQb;FK_O}KkIveeo=qqJNW|(jCG{Q zWt#A-CIu$hV2@_>F&Nfy&sA7dbS`F72NwHw?4*(sBOjOt`h~1@wJ5dS;(TCoK0I{C zA_i!uxZz=BX#WSH)wbIP)2K+O8&8=9ZHCTSfYF*6_*kA|G4SX&ZkwZWXD$WjRWn4m z63x~zuXY{ptMp%@(sh4)yDHb-jMusLW_v3AA+K}|9+$4K)q)uaz{O8Rfl^#Bs;Vv_ zs9e_I(4nf@6t0Q973&f_Rp7H)4xK1+)N50H4-*UDnHbWJe#-PLcUHsN$zQK&3{m}% zIox^%`H!KvzOO}w#6Zo0?zwR+pB-|Yuq?uN4qqGbddm*Jh5UbCxPwxi$k3ZIL*J}2 z^ewcO0rzmy>DR8DeqC|;b#Hn4aW6QZboz0h8@0jDn7TghYE8swxgcRouUnCt zjtH+(fG?JYc&p%Z(OHvFJrk~_SPAh~u?-UQj3u~#DOP~L>?a?DH!A74s9+Wb_J)@{ z6&35KC9npi-W~P(I$URNL02+d2Q%4$_(+{nI8fEOAHsj-rHVPgvo}<&;)OSVh7F(F zA;3khUYK&1@%(nntI_pxw?uEDRt#AiGCf>965c6#HXhzNf@>W%fn0JNpsCMm9hgHeCXDMNS! z!yoC}p!ha`5YNv2++S}1$|TSWY@Y<9HvH+ppY9lYq1&4J8|dLc#ZqitsO#`h^PH~v zbuhBb@%>-~v!dP?E#X(Q;enZg1Facv-yH94@xCXusk3m+yciy9!{QMX0pTpn6_xSS zA2@&cs8m%aQ4gp9b;PK6Odmtf_By>4u15EL}^=pp(sK?mUU3aco6jQi`d~;Bd1mDf@yJpL*F7@FNB+r3tCRmJyl%V)E&m3p^6T3z_uM`5hzoJF z`MtW!q6xtU0gr>=)`;~fbm+*vrk#I$KZW|?VOS_!4LvPnP9t31jxO-C3L048ls$y3 zsE#G+&3LR;u@5FwO*hayUW-Wp79Hm_MvkeNzPT*&upXF&K28#@sD^QmoNrjzRy6$Q z#EHk9sO1!jSI`-{e&9F_D|e^vfZJZwdnwwTN#O*T&Ij*G1Aha#kITZCcCvr`YkRtz zM5Qx`HFf7xXd*9K$&m~<{Lc}F{4v!fHN`4zsPq1gOuF=ZD#${vT zXk-1@Z^ru$Jb6849_S`3o(2&JB>Q15&zU`*E$Gemz59gBHSYXChn_m<8eEVMTxCAh zHx$Lp*}mfzKk7upeoU5b#PomA>W|n-#56T)G=K{;Ak-#e;hEVv%B9IQhEw3BQm?p$ z%5~rO9l1hL>WJA>Nee_=E>s6oA*N}@ed6lE!4)%H6RvVe=tyfNd?3hR7Vm(WTtEUi z2p_e{$l94Kb03VT_mq%#!Wsi)c&Q=3f*MDrlPNge6R6i$Sd@F_Uc`R`Cm1sav2aX$ zoRv9uU`HY+9{J;=HS-~+F(igQ1o0^|&{pfdk5e^qR2aSL1=`%17yeF|nn~fFD0j3a zJZXSZ+i;FkC&Ev!9ELe30%16GW@ z@NhMR;n{OWguyeo_yd3Mc_V-9EIAcDJ3KsaMIvOY8nnAq_? zn=u7lMlwU0>rKWa!?2{*FibL-mo3Ng)XYhbTxYbAExg!Dgc&gm!v)i5c{)JXFEvU% zaYB-!uMWp0e3Mm;i>A4m&#p_u?KY{iu8L*vg$L{H_FxieQyqVt0mUP8yxpS5pWIwG zL+^}JZrUdA4xv98uv3?9*9NmC5IYAnyN7!Lm)h?o6G$~1vEUNp_au?`{fH^rCx?fH zE~FPIiN2AHmZlI8LE4;>RbcM)z!V@qtuFb9jx(La`Jh>tAw6TpXdGae`eds#g+m}-9{A3HNp%iSI@*(zIJkyz-|@{@^=tC$k>4ZuzyX-Ocld=Ax|O^``C z&vyEnN|xxQ&WThEn8mu0`>ctHH!k8vir6)BhgoGV(jQ0p@!$?ID5Yn+vQRgAdwA$o z6Il34PxQl;ol)%^vnfC8z?o@r=sbzT)d{8xo#ahcw#R>GkS(axl!J9pg2r@wL`Uh^ zQTeS5z+x~AN{1Uqq;U3DY}UAmp;R`<9z(v#cP+$tzhpbI+EIyS`9WXeH7b@BWp4+8 zIAR$qEMA$BzD)hhD#s@}qTv_B$GY|n=?qU`&k7_mc1kgczq5qXJ<$vXf-yRZuUkvZnv?3Hh)hli5{Lkn;Q zma>0{l2dm@eI{bBFN`%$T#&LQfqO=8&KpBsWWL-Wy)ip=zJU^8zqrd<5QdFlg;cuv3$OXk3TBeBDIF)qF)lPj6-tq|4sHbFLiU${3=Jm%0uivgz+ zufR_6(6j3uZXlczaRdO%1RVHPFa=7T$^F)qzLBZm*1^F}!8t*Ij#`e&7x_I@BjA6G zls@$A8vcsRdF~3&G_1Va^k@(36kp3aO?OzQSU+-0tdqapBKuS$!`K9xTkui^TQPU$ z+pUmnFi;bY>u>AOoh`p&ZPdopp#P!R31JuzV(M`soGXFi%ioJMan8#~;0#Jb?D zmSh5lP0k2~jGYnuY%KU7x8Q@OoL7JH?#AsDD5C;OH}WL6s6%pyiniub#^QOH%A2bc z1_HOKEx&-d?Yy3_6R}umT@)Y0lSVj)AUer<(%?RPsu9Mn){$`U6EL6p=v%0EtT08g z*5=~hN^4UJ3Yu=W(E{$d$p4P&=5ANqOY#Tk-dv}@d98{c9E_u}tmeme`cxzowHYr=>UE7q7GHqk*YdI z7To(a)5+w-ktrP!nA;1y)Z>2`nYq&o0~Tog4m2t!RgZeaXK1oU>D zT-fRz9_DOXCHl3td_y*+wpbKR?xdWV9@~@0M6?b8MQi&jg#+K$mTx?X-Nj0TdmuY~ zc}+H;W#Beo8+kL;RwuDHThImz93F(+eLC#CY^V6l_>FA1XKEV5=1hMgcM4*7tGg#R zxZZ}0mx*mP$!cczb~7$tL9MGO4B*gQ{)<2yNSJC>nCIg&Gf-Dw;7cCK+%2N29++gl z_WfVHS-ON5h@|~J^&=X?0s>*5*wx`f)r}=)YJiYl1xGbscqpjfEU7y4fqaWI&thMq z4(BrTXAmzD&Drb+57d9p8`?Vdzu?F|Z|!e8RVy#>R_hgnQGu|euiPuhs}|=}?N>gb z&)H{1d{^=erRg=*@?3flV4Y7PoOfn+tLd%p%-v`Fwo@|=gSiJmBv=#;HY1fpJ`u;| z)avL<3d&z(E=t|lnS##&yYNh$)ZmaU_S_)F<`4{LDw&3U7~6kp6niT-z7k_&$Xmh^ zDFHw6w(7g_0*t?7=oL`PWO7z}Ixw_YJr>we#5_*mxs!r@1E~iEJ2mP*kkWLq3&P?( z+lSn}MLkmAzcbtBZLzXt5r1J1cC*JF!^V1^dniubZ&pE57=ZU57eBZGQ63d5%n1EBYZr?cWV1(U&kgV%mzdp)C{iW12~or zTT(sfZS@4ArSicb_@axAT&%c5hPN=OTay!N?uV5g;_2pn8!O>STZIaL4^zfHMWAxwv&q&~yJV z)z-RQjRLdg-U(yk$>Ob-5{Z{@A=!%)kpyr@k{nFVN zIKq%5M1_C@DvrzN@F(-p26mNyA@BM zbH;PRwKM17<4lMaU3tZhF@#8k#eW(w7M?rc1>MgXWpY!9-wx63aCRnsVa#Hjo(4}L znDPul_=F${5P1leV6kJE>QW*HZ&r3zK+}~KO_$-!P~{!+^ls8>wq&x*dMLlxo2IUaYZwyHm4Tksya1_#GQjZ=mgV@=81$mvk3jl%)^M_Z<%hXzDuQBbdjO ze$2xcls3GFCZC(wy%4@*%4JgK)Us%@i0^;4SD-Ei!OjpC_U&fvKHlv)fQeO&N zQ*h*rf-`YRfPS4zDcldH`rM7Mz;>&iP*zso4Pg_o1|ABy<3-SN{jIlsst2hywEJ7D zyKObWCgRw4R}r1*L#*W9118tWoym%!vN)QP*Ckh368?i@%i&JSOaeyIwsfX=bIpG` z^x%S*6Rbw}!#94}EP?os(Hs-BGnIIj7PyoA`+n#-Fl4!uuMuF|kOD_7u%Skc)p0V~%NU{)SC#x0>cT;*)-O$Pa^9C#G(*kUn4l zP#hC6aYxozoDKOsb#mbW=8qkdcz8EGV$Bkdof%`Dz^lFi3r@wf@yD_~$32?F)IB@G zgtlD-qXjUye_tH7&?tc>!D5$X?$|}H*uf000}9(h5sqc+*{%~BA^4?aLCb#)fD`so zWEGBpL58e(a38|*=|a9~9v*rlFAt)I1~XmIrolUhCV$fP4H)s{s(9X9Yw=HqhuVR+ z-9kUV@$elU|LKidSc=EmfHXEEP_~i61QRwVb1&V4Cxq-^Q zseD#Ipm4?K8053nGU-RM*~|Fp=-EFblW(00PeDPWW@)^AscX97%^*~TNgf(cO&#@m z!rwLBSh~T?r{dC^MgD(@o%mb}2V8tG@o8djycqjLX_;#ok2w9(1}?n zaFRHaM_L$alP6>o(>YD2%b(U1RPF51=Jz#?uk3I@cIpMyMhneHJTT|j$IidTX~Xk2 z+?(kU*=T zKG~5T{7PV0Yc78QGQ1f`iKeXOf%?==d(bh z94(#$e05{Ym>S}Hy+`vz=a=-QX=K9?XEggf7oX?5Q^@5W_P*&kBb!`!G9|2bd!FgF z6SJq1(B+^nPF~4xewLBRTP|o*RTQ$R>OKh@NHfdAG&6rAlkaPhoapsmQM~qoUK9eU zJBq@}qOZx@LiUx`$i9xT{58_Adw-7f>*F1yU*G+2NWXshv!!3(-A4NL-JPUgKmKn? zzkdE(`t@njuiyVd(y!nCmVVtV{rd4H>DRx?(yxz9`t`FAdi^9GelJPCe)#jHUq9Vm z`gQOBj`V-)o-F;c{+53IE&cji`t`T;>z2|lvyguMP?df$LOqv$G1--zSdn>6<@`5@ zy5wp;N7SV#UN8+;Ua)u*p3&eIk}UIDNmdgjStd%dT6-i}sIpON_RGt*SiTvbh|^2g z{3J2g^({iRV8W5lq2jWYNMTU6qLKgwW$hh7*&TmGW0QZOe5=U?R>T7zW0POB>fAEf zQUcPYe66gCY-yg$mge=crTISDQd}!rVq&G=G&IR8i5qQERq?dU$w8u~G}gN=YGBA|)WTlQPhP&}m&34N1bIX))H@36F}ym+liD z?c0AQlkX*okB2H#-956|d*6a=7OWNaD#IFavPU)5c=!w1&`VcXP^3#+%{L4s>Vtq@ zsQRu5WzuHCBz;enH8t7Z>;av5X>E1ieoA$9H6`@=n#yCPH5E*G1u*9wC(zpcwh69| z`pnf4xK0{4f!1vIEqLyMlca95KagYxEBb$@$ZJ;V?d3JAvW)^aD>^*9j_pqcA-Z&v zr<{cy4-XD%)4}0e$!TdSH6H&hdiW&K!^->Xh#ppM3BnLKw_CpS+wCe851!04^W@ub zuzXkjU*KT*P#FiiN_H{-%GG>hozRmMeT$MN_;17zq=AFMM`Lz4oOOX3@g&mZ2+Myx zp3mttm5S96jCVcQ1|C0Wf0*hT%29Avs1Lv{7~J#e85wybCGnW8hwG%no6lo) z=A8>l3t`z-iK?gs+h&2bhk1Nd8!ccNGdG0ZGdfu>Af#_F4^^UGxN)Eo6{$>hOjZ}p?meYuk_o5&PSPu%Cc3s^wpoe2 znR!X%yH~b4_vxidKCF|}n_q!~4Jy_^YJ);3f|VODyx>h3*+%DUh#HN`FUC6X(v0}w z;u$@seqkU8hWesFqYq*zvU-2#U{^qzDLS&c(07E4Davlq3l2@t2)k^fE%Oe_5)kQjCgkvK~{g|-RiS&u>iU9 zu~6TT)M`yWZMJluKytrGQf1cag;>(%;%#oIS+P#_ z**KYv`>vSHyFi_-nXM+&r_;27i>Kz^I`E}rCCl=`6F0bh7A}-$EF<5}4Amzb5I9O@ z-d|$Dfj#4!hlIiL(hYwWG#>|hWsY8K*GR+lbV+Bdvcp3j$XRolnksKZC(B|JsxQxJ z9D6hHj!%_mFTZ>D?D5Z!pD8pr_u?>saVtXBu4wBZ^?W6!N$SR_t^&qES4cIhwR6ky zxZo$x=#@?R1kj93`pnOmkd%UV;_A?cs-p2ET?HSddY#GiWRQP1QZGCHXyg&ficN;9 zfoUB2_MP1%+{+gGzBp1ceUptg?c1rDm2b`J$;7)#e zrl8OTHw?_3Mn zRt=I;zw^V1>#G>g9qEW_O#6s1t>^{e5%C zB+%B5rcIHwsPxJ4$dr>CF`3GQMgrREwdZ!I`M0|`+~?a6!b6ZzIMzQ^k(rYmchh1{ z_88kn{%k4ay&^OuMv)A{ z3r%mV9)ZjBrzbCYh)obdt{zr7#sdra#So!{By1O~Azth1O$`HjC6?@G)sqkoe~?RFfS}qTal<DOcu-}7vT1012qz7;P`iH~ z3D;;4ywe>(OkyI~wG6kO-L2u6Y{G~Jc1So>v3;cQ)&We|tf>T4b8PitOqHu}t$-h6 ze7JA}PM5RDAHFXaW;4Eylr)re^w~eT>Z*GI@kDg6OIx`hikr=5M0x)F`E%t_sQmit zufGyyX|Gmxk|?gK6LqNS!rHoIGR%LHR1jOTM|(}C=((?yjrsC}T=-PKEEY2>)5+=; z1PJX8S_7S|UOR!-H(TAVPF5eBKx_4yowiO^Pe9|f1?duF|7%Y1b1sk*MVsuXU=THv ztezOZ>3P(E>#P9<+jp(SAY~L^?3hRKKLty76yLwE2aY?6$K*gOVul9#H;#X)A0F;- z84<7bY4SL?9~7s2fa-8U*pOQbdJ?zu?Vlsmczc6T1NtE|Vc!ep>l#j+`@XK>$HkWt zS6;&=m72VFd%o}6e^|aK(*b% zLc`BTO=sNfFQ6ztXg6h)@Z*1Hn&`Q2eSV47XK#X=OSEo= zh`YAY`UDj8*(F+^y_u~$&y{uK$jv*KXnuJVW8QfOTA#2b@7hM|&TZU%lbWAjqIol> zxI1pSYa7iwxA8@e;JbgKin~MiZ7|wrBgHR(!K_a>NdE|e2I zf$sPt$h*4}H+O~3+hFI!TmkAG}QZ@Jdck>Img+@=kLVPH%O*geRgCN>Ng^U8I5%^aS|iHnmIg_UW%d|(DdPmKS3-3#*pAO}iy&q8IQWji_es1&e21Kwn@8vtkDnky^{v z3u3!_PI`Z@J1Fja2}iF&dkx85lXU&4#?+mrjpTnSNZrfE(pxNjxS^zR0}F|;YHW3D zq`~np);!&gGwC$(huN*zX$(@Q zJve_2?mZx?stZ&A)57O6B)c83ladq4RbM(!inBVu!_kEH5K)b0hptNJ!axRX9%7xc z0jY#zM4LlNfjDgmVAvEk3c#T<;EdF1xMHbdChX2bB7uiu^T-L8Du78=G2Tk8NvZ*Cvbl{ z&Wc8yDG3e_`Ej{)Ry{4o{c)5U>mXTr^Hf_6w16ygfAY%w5R@Qi4CnEafWMK7T_;@f z+#Zx?1!$!b5G~U3_1Pyi%Gc!y20s-+@UNO5$@+IG;HUi!2?pI7B7i8}6r1tk|-pX`-aqX?98~ z+s;nN&ZYzOT({+HkK`N94y3tvNo6D1F)3{$do3S_ll(qEK0Hhh4?RJ_uX=x4LQ)dy zM^xT1DY{3jF|t5K3Wg3pf6~(JHqI4Nhp-?R=X-*UWMa!Kc5Ti4(GorO?$Mot3tR#hHJz%{b*0ENn5*X2|t-acTY0^1d}bJY>K5-0UQv;xgke zt{)+I&U4Bgk8acPBOfPyO10&Eiy1ikm34=d(R@#Dugzmuxe7xs+R+PNLk{8ZO zySlmL1!zK%nX}B6_wQ#%%YXU;_2~-@d92xiTNZ7MU`!49Jx zml|NCbNlxS`h*RhAkd-}< zDwgYr0bL14?_S2W$-|r)&Ob=A5ti0S)?8-DH7I7pgQGD&4ngsEm(4)mXpnE6q~VH@ zck3cU0t8w@rg+HC=o@#zXt;TiWjd6&;drQu<_mf}*6lL$jkJGLIQj~z9AV+F9jV;- ztMUG?U*)xuuhj8Z`dH8GDVaIJj>u(M^l`S`&PW6^P@y6xP7Z+4;bBBpJkKr-yC`Z~ zZMQ3Oj`O+06<-zE&WDzLPA*_Y^6$rGp7CAjBTIW+)bI{w{~bAT0!Hd0nR_PQa>Dnr z7{uA(;Td_uYh`~+^}ML>4b=CBymSI1rooKHG$s$7z<3qI%93YA&WA%aim7TpB*#u* z9J8e-Pm2u4L&j~|$K(+Q4)UV-{AgHKQuOp87<<^B{fNABg7P+g?W}&)0y4@MStY7~ zTa~B?G>}w)D7;DFs1miZ_)x68)I4QpVX=YgGICzAZq0v6pF~Q&I^tQZ4bLrlDP~y;nFEZUmHT5S>Xe|8?$#xr#zKY^KTXwtMOx)?&B8Es*$4n#pAM^QK&B(9L z!qZ;qLlu8&QPGJ&vigvyukf-Yda)Le_ew+jS)h6!f|{)rSR5@+@xK1{Q_PQz=~&9)n> z@MD8HX!63~D|;g^5^JlpmXp@3J)d4vrSds-?%U>nM4ieXFnHVk!c+N$XYor<;3t38 zX9r=bMKRTtZDgYKBg+5L?-smwstP^N} zAQdn>Y6jBhYSM)HGpi;u8nK#+#x#GfG;*Gvpov5^mD$J5b~58Khf?L;fe8kS;D@IH zV^XW1nE6mOb-HwSDw(W3KlOrYvKJ&YF7<__!!)_2z6{(hZMkJ|TPD7%nM5)FlPH!6 z09Qb$zkiJmcxt0T>Xjz>)@8|b9Vbu*+{URHMq2%(E~q(S*O(@WV&J7Z_m-}HYL!TT zOns5M+%#VM1;qcu?78_$Bh9H+zn#%5I3TOZLc&p`KYG-D*zH4YxZ|sUlYfrsf?gKs zl)=L)3ga>)!v{R{f8i(bB=l!$mPeSbRso-xEqtYbm%6?;bK&oT{rK=FNd34C50MKl z??P5A!f#RJ)1vI}m=@30UJ&Bb9J3}<&zpr)d|Y)qW)q*HfMTI_8ZN{1j9&2IAPb^R7)|=+GpA4nl>0QxBhf z?+m$oKm4$c@oD9!r!IqLme{@XKMDr4HnSRS&%e7h5>ENJ>>jn;q(k^plqZN;3kY& zXjXXj=5sK=RVlE$D)qff4|Dr}EA%5f!N0JR;UV?cu(K1f14WS#0C5_KKD73&O zUii2gixvKbQ7>XQS|SWB;xIf1fLOZtnR!Z_xF|?jy2%;!S@I>cww&UB3#)G#ok4$= zNs4*X6yCh)(p!Wd+!a0}$ar*`KsUTa5aQB<^WAvW!zT~^LYF?k|L(cVe;5?=Ck{OD zmX8)+Qg?a=p{((1=zIA4JN%JA<3rK_`%5^9*(puyg%<&TTt{Ls9>N$)!-v#&0sK}7pDXX93m~=%gGD%-uqU?lSD}Q30t>+) zXd^raZZK=6G>yHav7GrV#Vazq3G_CgICH_m3t;Ghhlw6OCmz&)!;DnDa|#n3P8n!{ zu|C32_)#Tl@Qp1 z$WL%&QFuY)-`5m;T(XyB$zVE)LkL2~=8;i*?1A4Vv6nQQtN{^3=r=lAM-d{^h+#4K z5vUWM^Qnri(k0G+5yFsL}3g#0vs z$8;XMD|!*efPUlk1oN*ke}YqyxCn$Wi!S~y>5Ae5ONR+)BrtYtJ6XBD$AA6Q_0QOI zoL=Dr^gRiEZ|1Rt&|kwrCNO3aVrt~ZINwR+uY8#8AyXQh_l%c0#V`Epo9e|j9_#U#I@Uqn3UCXQHnLeuGzxi0;=nTOTH z_w!~E4HJ~2#4|-tuHHG_8}V{6xh~@6Vg(T|p-Vb{SuAQJUW)69eX4l3auKtc<^hV- zbg7bL8iEuUy)I5e|0Hq)y9J8YdPWxK&dr{J77OlIhJ_L$i>puSyr>55@fR1hRrt)C zF5bYx*23FY=9Rak2dS!D&kF$z4 zg`N?&##i(QD9N+UvJnHNb0dN&9s?{>9b;&W}WBAYqvq*tNuP2sj4 zIEIEB%o+hr@o31<-!eMJWf$vwiSv~e{*t+WmlF}V6E(DOHyZiI(;Y{B@!+94ysHoJ z8M**Z=?dJuUnaKI%s$oWEx11(oTStEAsEKK4_ZIl^~tw5sqx7tdE^V^K!MkIMi02}xJN%hctCFSz}@+s4|Hwu*myx6 z8W(Rr*Yn#8AmIN@zirY@a%xO#ot;&Gy}12MW2B7l=D^L`>%c8G&RLChZp{9uL7aU5 z@CyzA1m#|O^8G{Rj4jj2;_?;*jJNnQxG!1RR+Fq|c0c=+x)$$52;f^b)6V`VbiFv+ z7tZ)LrB^RLtMp?r4Gf#TxeW<=DF~d!^V?*9lV^Vk9;DjsmZg)$L&u_4pDdn#)!EYpyl4pE>YiFa?@9(5WSzF(&(-ic`4@}ep9jWeg+L*ABsw9xC zfJiL8jJcI)qb`W|W0*i5YUJ|?CBlzJ+vu~XZOe-bmHt!FM zI27Nv{+V*+qupo{?vH|7(pd>fLh_XXHkohhm&pz#BE%r+QpbZ}CZ?1+j z`!~f9oYEkrv6|I{Tzdg^?u2Q>Rcs`Y7X)ZRiw?fqus;ttukVR}mGug*rf{$w{QJ$P z`XW?ZUaNcVdOmCt#5mxPUp9+(_5G#~J7mhSh_ePoZFfY+gcA-nB^9#4J~&7*oR5sK zUjO+B>qCLCUUP({lB#62g1H0&;v2ZYM|>w235sGE#%=JPD3I-!#(uaKKRrSG^Z^9h zFLbi_wO+vW}IWK;a-hs;rnYv3rD%zfpahMCO-Y-!7{5PH~3=%-#)I)M!S7%wUoBfR`93UP6kTT%>Qe^Tcc^7v^w}z zX@6A7+=DP#psxY9pp?DVM5pFLXu(`Ehy1eutdw~vZ`B#rC5;F=orwvWmv}G zYML7pY+yjAGf=($o=-9mw#v?DmfO(O{J+w&+X%8o>L@aRZ6@2 z8{GTF;Tg46Zu!7onI{poeG@8xO4`S*j$yVtJ*5qAiu4BEZ7WvO7Avm))^au9sne|-G-$<5s}%pMH7*F0`oMz1B_nu;|r+U<4+nrK_Sj$-wU zjtMi=GJ00Odu(-#PN&;ctd3z?gPvlw4YO@^6hMC6K4i1ny)IN^HV1teOtaJKD^1I= z238lUHJj!@X|{|`cQC+adi{>l>=^xjE*pERYbnjXVRiaVti9Xn0#giNb6_dWuF-Dy zabjD&b`#p|nu89Mhi)CWOrzH`J6M0eIZ#?nqYJarY8qy@+lBOj)r0O?O$!%)ylHjY z*!^DDf@-0Wj?wQATH>u`bUMfQY_*_+gF&asI@Ez9%xHHy9b9S4!sRfn!7=p5>UME8 z`c2lKcDn_$-t6_-&>yyH9mDGN+s7@-XtiNSz<6OireU`FxI9g>-)7^q`Y`=nt35bw z_6)1r?y=>ua5=iob{~Pl>H(C02k0C8aSyMs2?-|6+CA6CEBhZ$`3%|3%yvwv)V^^Km{!gf0? zfEd$g^`Ttb=(eDprqOJ+v7Khm>LUbopxu@+FyVX07<5^`%t0Ib-5r<+xqS)gB}8YXTZu02JId$FtqSYTGj%q zbRKr$V8hqk8p1Ssom(K9F3x$k{e81(41R95jb7_nb6{8&>+7?YsWf}fSjJ|{=(m5y z?6+%N9JIeVi{GV#_FvLL`>((FLHolU4%&Zd7~DOI>D;?~_wJd0dqv}SmdfKnF)e-- zQx)qD=kScq6SbbT5~kx^DN3|F^^-=69s2*6nDB2_8$f-bl2VV~cq`ff#h#k@R0WwX zmjGaEz&+_c(%poAWzJQNXn@=(Dnn;?>QHw4*_?q5HmX?NWz#yhI?G1W`q}C-ptuIvlxF89Y(x8VcW%`}_F~^00hWLf z+v+;@wSVM)^Q2!hS{M#c5|(21T+8T#e4sxNo84#*j81pjXad4$8iPj1XevNgHF}V% zZ4k>-_2FI^%T^fTq8w^W^Qx ztH&>Y9$nYd-)^ooStoGfvc8Jw$I?w@mXSrfcBvxQr)kO^Lo)&S(QSq5CR)_uecdJs z6Auj>)tLHt+n?JfKcn;1?wDW(3t%DVbth<70gfrc$TkVMCa_H+s}1%`)wE1u=FDss z(Lw{fC#Z5d^V^bgeVUl#zm6&9PX!xK(C}J+2ajm#dVW$;Rcw77)F~)dld(hXN+Ro* zNM+Xy-I{BL_Dvd$)QH!gshD5V#J}-YL7jQ$YDMRct?sSzvc;`Y{b~vDZS@5N1R{6c zsjyphu}s+=)MP$URn1$H%`&EQTYUhbR38-1){PJ0#PDW%b}RkDWhYlGnt#Yq#-Q$}yBI~;UdL6LtW7lgV*6t0t|0B^VZsD0D>0td}J z3{&vmz>sBo$yFX#mTkE(xvAvN^H zJ+k4~#I{>!!SJ#8&J}PVlKqY<&IbnYLdhx*ap06xvADvH<2WXaB~)VEEs859r=|mM z$!3)->@d@bXg|19`+>+6+(E~tOE&R3U^+H7)1U#JouZ)?Ow9Dqx0Z8 zTznoo9dhmgLWVgbi-Atg-CA{{bB`ai6L2%P;getzHu&>6BY%`K(mDNq6lEkLVO8iJ zVDa#l`aoRmQ1XK&6mD`Ip&ARNoKu;DD!$4X6x9T715XrqWYjI=DauZm%#2Ljm_7`q z%fd%beiWj4Nf;RDB@P|5J)+Z)nW+gUb2!9g_nNY!{VJ)jsQ}xMCf( zi;cW`QyrY@n{9Q_WB^oueibl}LMoD53=vgvQ-xXIsNnK)mrHO}vPr>@d}^!jCcYb- zsU)T-90iXHG*-av#+=6Jr`v1&FMTi-oqF*9 z*n1c4Hj!;z_*E2kjt{Jq)slQkf}7>z*h=Eu?6#bwyWQRz2uc=zkpv1CT_S0W|26*C zJ5O@PtP2!SNXSW?ofUWYXd@_!y4S2Zzxhr2c~O#1+<{WZsicdEyeaq$Ej2WbHo~ik z@=h{PR?9u~E)#Lmlz3DYTIqII^q8D(bFeu?oRIaLQ*z9**BlI-QQ!o0rk%yydzjr9 z`S^N{ZDW@Wa!WFQ$fNa#JPp&YqK|Q-zxLQYt&+~_kz`i) zHaug+=PECeFuw9kMcW_RI1p#OUrp*-bWBP~*QDOdTb`P{uRAr}^2jup@zDdqZ?NLv zWUf6peX~>3*h2G9UMF>G%FN)--Ou1*GJ`woPaGwW8{h7%aa%`)@o?n|aRbMPF30`SD@A^7wG`9gh#A+xjw$CwJ(;Jq={8+hen=JM(vR$o}hVT&l;j#HBj_ zFyQWvXxuK**y9Ozo*p;LByY#bTZXGXdED5618zShW-}urW=6&n$H!K9fj>t$2wNj; zabp{MQelr2YLk0Dh^B8n7bp-@iQ#^QJy5b{Hk`zNA%vG`B*Ntqji-jI?$sI%4UI1i zSAG2Cas7#g#%~F6=J--vn@Hl{c@dbPZK9sGoGm?~h1tN%3 zhn+4WM>F@zj;kq~Zce9Q`}L@xb`tvui%@mhqlcWVpU>Vbi; z={iM_Tu;?+w#+Jyo@N*z>(f<#IN{M5(SSr|#GUJ0q|i z4o4yJS{eD+v@5RXZj;PA16*+kyRe0;|NP^Bp1KtxDnZ%~uJAO7ykWw}E0iuUs0^bZ ztn|z=u9%fvHB=2WMLo~1it#4LC!4`!Xj6z_nM3gh1Z4Iz(RL3cVF+1@8ypHa8d~CD zYfJSFpPyb3-#B5EcAl@g2y4}3Tv5kUX~bVXZb_hLSva@xJK?)zRxB2O zWXvrV<8%7wR25tOJdPvB#w8;cPU2IFQwW8WP{uWKNF+`mKru*IV{*(Bv|T4uVG4bN z#B$o&B0*Y%(2syXb!$tdL0scIH3)6Qcqur$+IO5&UUit06)kFQg zvpChc<0fIKsAnMq}YT{H+S81J%_sRb5i);lhvuxw4}ZxqQ+3 zcl|KjuIn{WPt_0n-$N3f(Y^Aw>(|1N_2Z>%{8r`AEEbUI3RB)g&iZI_E*l{4Bpi@< z8e-oy2d})&=?M_Pn!y`~YL~j6KQVof5RL`|ZvtArYd(y}@1UZv*L;#1wY*M$fc-Ji z*tNXKx45lmo_nAx3K7p?CPIKrG=BbLT1ry4zfvU;LVt~?j6U1x!v4S_dnHo1MZ!}s zSxr@*o6Z2+WOd|k5&I(WX;lb!RoKIot_RKRxHlEbUR4pItZ7IAm+$d2No&uS96JO$ zDQs2SZRm3{_!*YS_guPRhsOAS1VXip!C_e$n$t@&=$~*3Fb$2LvrOoKu_MBuiO0iZ z>JAM_KEaN7(1G9=2SrlE2H)XIMoztv`W!IVx~Hz?4ITG}@Rj*Pl1D%v9kZ9u%^CFZ z8^`UxitvC2Vf=SBwDI{J%5j$+Iq9dDgn!pR_XdMguzZXuy|^q* zE9$_8+rdJ@bY}(6JTDA?Lf;&nW5Q$H$FpYI@uz>ouMUE0qmz1SfIr z$=#%b2p9jctVHC=^JoCzR9FF$6({@Tg&Dk!Ks7vY$l$bkk=qBWAxUfXy>9o^bwbA+ z@M5sLZ_O#c10sS62OEb_qL2OV*~DEvNT0!Y>zP5X1@!ji8~sCFoYBecM#1g#K@=p9 zCZ-dTFB1xO&+9{fUE&*^RGE^uLg3EE_OneMKZ9mw&6w(DKN4oxih)zuXjJF=9Amr0 zTKq%XjSRJ-R=ZWBKn#O0&JhPg5`Bm3X3mn1r==ksp(KVS4UbrALx!kTSX>I5<;Hio*jiUtJ^504uQZpnd=+ zC#a}nIQ(FLfAB!{zjK%;6cKaR_73IUnNUrOq| zY)sV-k&l0v^6N#)6hy|yV!^t8u^4~k7hh7!n~&vxl{fEy9p%k?QF-%Ps^s|Ob%=Gw zb5BS_G~^rO7b-ywwL&w*WKL+Pp&`fcuWHxGH2kYNOpJ802X&GtFg!>U86G6EQlB(c zT(u$}SY$2|7?VJXngiW|FmJB@j7GXs9Sy+; zy#VW7&Xfva+n;+@6r57SP5yh~JAg|F0O7-=<&0PZgIx$U^Zw%Wm;*x8o+fc0@T?*O z_qbJDuO@#g>`KHa=g(CHTK}}n3QZz3rRWvfj6-pNTO{{M~u)Gia z%Jr4(q^BpVIZ4B+V=qe??BWluCV?eq%$1)U_th|`Yum64dn?P(WO`WwcUjj0q&O)} z?xuy=U0E0gHYzBDbWCMYNMQzrl+WlG&B=5Q5c?_}aL@pUfaSAiy7JNV!AVfBT=txQ zph6d?ieGG$av&;g$kx1ijQ#g!dYXU?E;23pVRP z>Q!=wyh*O)ldeut5@`GZjG48ar(n$dY`AK@@%ZVkhQ@!x{k_L~Pese7z!ow7$=M>t zrPw0Ie^>uT<3B-0$08$Mcv|(}FEx~Zuf_w`;#5L*w1U(s6p{J)_Mzmb1dy?Ho$V(i9EVtyA zn4fTWWsbQgAE3R+^y2tppTluU=O`JlyM2R~h!1~_7mEHC3&iexZDGuRyccb@IN%nd zKZSp&N2*XP_$3yK{9aOI{tn%=c5C8BwR<-@jr|RD8hiITjoaxop8P~Qji+gy#y-_) z>~U4bV}9`@rPFv^UZ=79>*zFg1)atWmlSPm#~gS!$1$IUKtYjnf&n)L)5oUHm<@Jo zK!pKEaw<>DDK3cDyPlDMRe<**b1Um6Mg*a~TJ4%Z>StkIte9cBSOEtOrn(^t10q;> z?nUGhk%CJdrZIjhDryvkC~7>z1Vv3?n4qX(lEkq&7=WE5?I`AH2&N{w@{x6)Mji>>Jd+-{3&#c;L8yxN_=_qELc#7j!sj z%?&A^xYIaQp?eY6O1Kg+U?)~GNDhCOX$JzQni_Qy@1RNc1wQo95bT>!I}q=EZxZPH ziCd2sL7-+ZjY`Ctc$EoMT%|sAY{6d2j?><>NTEV~h~tlnq7-SKh;GN!?VRknGZzkr zyHED^ggtlW-^reTJ9EnKxij;A&%M>2JM(^?J$DwQ_FOVP77Nz(i^VMB7oNE1vfE|$ zTsE+Og*}&5mF>CK>i9b}imq?W0*QGbWkV?1M`mvI*c;6*z2kv1>UgGaBjRtWheYo+ znn`q5W`V-kYzvNI$KJ@n_5+3POirR{mt|L%W|v+RgM>bR$8+C$QGnlIbG#};3d)=f zByBi;rV?{Z8M8-8PdM>>S->wcv&80^DTsRBEVYf|yb0ShbH%5+BJd(y;f^};WsHQY zf(U21(FBbI2_!;Vx4Xj9b)}qH)Cfg_+{J2Pq`WbMu+qX9fW>dAcad_vc?T5JtvGl+ z^GDXLu22PkDSA1Rus^^pDP>|z{1u50A=5n-hBW(TVZryPV`8EMia%Z2bC8r}PQ3?+ zLLp6YbYe>ASN!}kcYyn?k*PxNaf&3QA=jZ_$WDu_J-bf0&A9m#6jLz}-U_@;85zhK z^%Ah5UC$qa^X141%>f|CmWUBs>T@{B-S}SQ+F8m8lB7C-LgWsl^x4pKT+*q;RJ9_j zffIy(=adh+MVh{vq|N1>PfSuQQB3i5YvvN8x0s0=pmtlv0L$fBeyccA)HMSFaE!4TU(`f*ktn|W*a8g zSdkwPg*BiiA%-C;MltyG^p<69#DryIxhx$Wo37aDP+MQgta*D3~&Z{|PvM zMbC!B$9UEel`S{o>JYmu|1){?Pw+3}pWt7=t5^U1@9V|YKmI@Nwf3)n|8@h8%*Zun zLshGS)2kYS1DadK_6-h_MZ~STo((s0vxoU_Ikt`w4H0%~2f$62aRL?S9jX(jxeLuuxf^Xq3?8}5C=w*1i>kW99hSPt3KVW@9%18Hd}Rk zz2XADnu`~kd_qeH=}bM6$BPB*!huUygMx|6WcaV2BFTh>j3o<2hhg3@QglTl1YDd5 z#5Yov5qLim=7lSKtw{;P1UOxo-zUmd=a~FKd2+epzC2gkH{25 zp5aOc#=!$MG*r{@(i7_dvZEP)2Zl-K7Bm?)3?qP5j$3k;$-MHR1WsmNg?wIl@x1b+ z^U7!Q%2_U#WPymcZ_;Y|)inYtI=BGNh^uSlz?PU7nM2ylbXg#KKf$jeIDIh@ApMRD z?~uINI{|f^cM;=xq!}!M?je;aI~6~T>HT+WtG)x1Cdoj-X`vg@uLk;m75uzr-wyPv z@EX3oq|-;`!sp5;=`GfuPoF?;YV5UDcNUv zT<kFP8@{o~W~?ssWIHZa_Hg=tv>ify!W;SfjV?9R+a^r|u&n4(rYmG}G|X*@*fS z%oRN7SIxnV=R09<2z~+nO%+3k(*RfD*#P1J5d|~+vI)%qsH=75P4oFByUh}jS#=IV zJG2APGngU1nJK!`I)zb^Nj(8~V_4i%3E#bV(`+|SUhvc=V7$YB3veD&bfsRcb-}Ya zQ%a@|P;})g^hU;B4OM^*mt0UbTyjZJ4#wVfrXXB*0<8peug`Ee!Pq6CkOKH9OaI05 zhL_%RCxpOX7w@z6fvpCpP~Uns9-P6ZEY|G&qWQdeL2A~@ycoGIhOut?vuBujGzR<| z%cWKgd)Up1W0`q@x2j$bh7@S4x;Uu5<7NZarW_pLvOV=CZ`Xh@N<9hxOd|BhHPO#s#W4gEmGf90~25l z2fpi!)n}t-tg&Wf*;1Nhv1J?VBQbI-^hQ8@>)BX;+MpxTJ#uZ*k|cAO1}|V^Ab5L$ z6MTsxqlPS_hSF9?i>PNE?1q1#D8Bx4d9aF;n{I~_$F;pl)wJ#AnDD^_A*>LpLYidg zLG-1rhJ+W{8$Nls>ZK){-L@eoX|+9z2zB0-r2T#rXMC-EBG7} z(UN3;-j+8T`<_Q?4+E4kykY?vQL+iTw1HudNc zC~K@0`O_sN^8q@o4z2BV?`@m9^~gj%B|EROL1)mTlv>x~C$Lv4B9I-N6XK_22TdM_ zna5vFT^mo6T$kYZm_KsdvQI*y7?W0@2DVs#SsAwLTB3I=P*gEJI4l&;&7m`x=}KU_ z!FGUsr>n>o5Q(OHHm>$xp+donU=SSU=b{H3Tmh(hvh&#SohT$XdP}67>{LiIfIhRV zj$cr|DfZ4bZ_z%UZD&pnq^QLWPEQxKX=LzFFOIv*DcwZ}8ULnZsx?$$|5fW+61ZT0 zHmUj7wcYtW1?O4{PCf+-DL7{rY2_zn-((YLv6y}07w=Na&rju* zpKpF0<>wnw`T1OG#7Y!T)Gr`QQwbV>(F;){x(bsiRg1#vw6&!u51`htHc&n3>;`sH zvVT|RqBsOW%b_7cE%xCxY6t%Be7hhVmrQU3SKWi~$^p$B^V}8fdb4wIw{^ryvc#IU zG}SrzI_zC+HS>T^VjdHS3;dPj$V>D`74nj@)RuS<;7Tg}JFfz?I~5}JSDwRvb_)s7 z6-dhFwZwj04wFeT1@WBftfp;D*WX>JG(h1-grpXpTCrCO7w8a>gSBxcg5K<}{D9mL>yi(l zn2N&_dml?<^YK92D|z7d6@}|F?)G8V)w%h#O^Qm((mnmq~8}mk@Wj9 zEw??Sa@!X!uD#|LFH&;b>+*8j%U?%sdnw9oAEY}a;eLQ%oWgFD;5d;ZkUt>PaPg$_ z{^Cswo4(aMH+^#$s7^H?Kf$ka_AzDj9)TA{tmQXB@K+VMsc4G@SZ3-q4Z&}sB*-QV z2pc6NtdW$i8l9=)p9P-746)lj`wyC%a-kGAWv<0^SGjk4~tAsaq_swczJf_C9AT?k)I zu?w*`>yqJ|_JyS*c}X;Br#)Wl9SzB*vvoQ z&1U}h2Albx_nZ0cHuG0M(PsWfdNco5#!Tl^=#~a$yZ*72aW?SVHRtWT(UrO)oK;)@^BhS{5c*gga1xQt%YE7@%y=W z8A(Q&Kn6wmRVqb1^TP9@*ceF^Jsu!KR>(|zjHHOU;1_Gko(Y4Iy)6X3$UbVVX;laS znhAuFdq7FYg;rs$!SCeaV&opAa|qM5PPbVSGUFCKDsZ2F%kpNSGLnpQoa1Z0xPoh3 zo)<`|h$JZ!&oC>lL*Oy1y$P_0t)FeSTGLLv94t_fme?!(q z`S2U!`jn3vA$!)yJWGN^@H^>95vfU)jR;ZPYe{T~QY$5vmsN;ok&OM~upTSZ#E~Tm zTQ(b`<9|rw76;_`4$WT>sUsGUio$i2>%L5*i_tuP@;hx(($sobyr4=}%C%d;hFhe3 zhY*96XDcZL{79;pitkY>8!_rfl1~!kBYTG|CE1&@jEiD^i2XrAdJL?O*TdvTw zG^t{LlUuyt0xbr;Ay9ru%N?_BNQ%9?zS#TuVzVIO=|8f%q-v3Ec{o(ks}$uqt5nu7 zB&}L17$&_H#sW|#Xbio{<6^Qd&4$Kg*``KpLJiOFRIAm@Au~1lK~4CzLC~e6I1~E3 zQsKHt@nxcxlm$tzFdmvDar!&rz$>1e`>SGqtIzfztU8>|H8gudu6M}wQ*ymat{;=@ zeN{uVJv4iQW=}OV!7C$kBrMRr7^lOD*&fY=KpJ^cGUlupTVy}Ai5$Hnz0Uz69f($vh#0WlMHIlJV(me6hv_cBL&t=Y8q$C-4 zzba#D`j=$;f%iacozu;-pOAnMX77`KVoGwEg)DM}wStwdOM^R*S+6^3i0&l36Z68v zEpJ|!_!J)qmIY)Yk47J+&PDjjyar-fFd-7t188HOa>XMuz2Rex@WL>2sIRdSv?J>t#3J3 zwQKH|FGyW*y+oluBX0R%YQDOEj(u}XV-7P>4~Q=hysHPqFNr+X1GS+okpy7QmkHI( zjZ%qd3#%o#p&q0cv+Uv;3K4{^Fak7qGI}D_q_ANvH!owq*9ycz8UXvytb(W5ib5D9 z3f-s({w?pj0ellt*jYJ~T#Qr8{B6asrzcDa|k zS0%&X(If7OLYUX#llp`Dk|y5MlT<#XW;czi+Vug5&5j#kn(VO-WD?#esE)jmsv)lm zjC`RmY%z=|t`%=gMKfw(Hlhpzj+7VTNBU8th8b=HPbBvt2q}b%#CL z+EO1liv^VP-wyc=m%lq#JLD}|6;ch_BJl2h{4RU`JB;)sHT*(x8^Rlon6!~f+PFrn z9bgwSHU837gXF)ag_fofvb6|#95)_lbJMumN5M7njat0-xQ1hY)SxtbWDKy;Y$g*n z?$p}#A>7vK&dxfxwiJV_PP(yPVG^bF3ZEnF&nnMB=6vOK)Q66(S58kJAbytCE2nOV z*h!lFh>z2syp9UVA3CN_tafcTVdhMvg@Z?5bFo<2%Xx@(m$ z6Fc8X!zd*Bj0!z}6p1aQB|0MhDBl>|c+Hcv7=4CNg-_{bNmMqehWHLGVy{vzOnSy1 znv6hu0D}k39&2dQAwO+UEKG)lv}R?G@d|5iT7uqk#KB8;$9q8Piug2bVc-|FNVHwe_~=4rYLxw~UA~)OC%h3iH!(Z;)+7^q7xEMieW6 zI>sbWJx`r~bTm}gVC!(YYF8`bxV)g@EFh6xnCJvizZgIb64`EuZqV3JhsMOok|y~e z@t^=j@wgt)KzngID`rx)=sF&6pzIBct<|ukU)4|pp`B|DUG1Wds;V9Yd#lE+N{I)T z$kVjz1GWLD7<$yeNZ9RE)3B-_gpnhR8Jcp6yK20DglPO;AO^{##68(XMA2Q&_X$o0 ziiQHrEu)g57^-Rwg|q7CP*c-WkA9s_J<+9GTcSp-mWmplT6Pqj=lSMLQvs|=mL83} z=3VWe9o9$<-qwy9B~5~a6gw=%Rf9yPNzo0kcZUUW6g4z6)SJ}UNZfRD!@-Y-gD)Kp zSG$ORS1UZyRE%6S86xwY(BU!NDy;{C4L@J*L~^|;EchfN$B)!GpRib*u)r*d+Tx;? zq^z+tlO7~$vf*d(kz|2lH_al|t^VEX*QVuv z^=q?VN53}9;+`j$$$79Z!4L$o&6paMZ*PCk8rs)e#HHZYLKLeMBw7slTzP7|TzP7I zOHPQF!#^j6=krSd$gt>uN0gCkWZijGxdM`uQ#54}6SalTEGYTw!q9ON6$#jr{6rpDn zq~yCqLDy1_Z$?|n4uK9~$tG;3fj7jeONq!Q$3>QY>WEI9>3nuUoar3WMIgeN;-T0x zCM`)&$Jj3qJn)dU@+dqxQiE#fJ3|!?7FR3W%}U$zzsiUYl5SASe7`J#Ecg_E1)g7lX*Cyu%Y76|s!hxTHy%TtyrtAs!<{+#vzB59Co) zg+YQ|$UN)6SA43qa_s3z38_^9>A6fgkTS}oYqAx9EcNAzzyp7k37PfXV`c3uk@A-p z5fR7zzyII=AIADO)1A@CCNms=Rx7m76_Y5kK6xFvS`H2=l5yF?l*#~woF2&1$`Ykb z#zH6*ICBEgimd5YIgvUkhf!bZFzPceQFpbMs41#iGLFIEIjU@purGK9``S7OQf+<* z{-9~d#_8S5nkR`2b-K#%5U8c>4c`LlCzsp44(^u`l1^3%N$-e|bfRj1X!2G=lk>c; z+WDkvC=|JJrTSqvpMvU#fhv^x&m*5GhTo+W!(7D_f{Mvy>LYiJP8dv_L?>(-eykJr z44>+RV?*&_k;+&14vQ7N-cr+@-1EsX(KiLULqrztHcuyPn0Q^gh;$53mexfrHA0rY zM3W2SN@2Pu1t~tJuve^qASH%eDM+CR-alY;Do6=J(+>fv4hJLzbVk%&>(ZmiuZ8LL zDRs&>IPvNQ?#8SN;tex<0~(W}i^D^;hJ3U7N>f7=-_-OF1&sO)PVbC^pDXjcDw$H+ z))u`1oLPsijt?B3f#D%Dz7EK#E;9U?>i5(TD5WW9tcC(=0f+*B+6+V+TC0v6O}Lta z4jj#cJ}6}3A_8EoYgn9WrbD&R1Mkuv}p!`bK|NO zn!_OzsGh~Ip8}lU!^BntzeHC6G5W+=SC@uDl#X^m*d70=aB}x|! zMIfGA_&pgmDhd97CD-;Y5vZ9QV{&oe{?4u7M9&ne4q@C*R*I|SSGpZ+)YH%vuQQLI zu4Rq}yuA3ZpzE-P=HhH;oFKekx=T$@J?}0L=;0wAm+_!NLdIkO>hTy`3S$>mtEfuR z7ORI<7!RxZQj<`rOWOsb9%un$nhmO+5;t27xzz4vUkm$x)AJw1>N)xAp73!k;Un*z zLc+(%Gw}>BRv#1n(5gx>^P#b_qL}g;L%S5m7h6|hC}O(8h+6L0Lg6AmuAD1W?tNNZ zV`CsZ457Ezd^9*L7T?yrs)m}TPoA;XgJ1dHakY8T9C6oufS_7IS;6F?mxfgT!yx58 zwj&Fx61<^4NYDcoiX45dgchLbBGPCk7^`z-RH>hv8^f>>`Kw7N|6PSjW*RFL%A^Ln)xAC-pN+duPH1##6laGhYgF3ZHPCiPt zKx{+)0P7he@N`>IXXtRp4=6c3z!Yg}dY5RP%0>?nsWtT_A`V0P$^zQ4ScDy4TW z9!7hAe=;6#7!lOUMz1MA6I4(YqQh08tu+PlVMT&hM1uhhCIA5!z&9GG0K7m$zqR29 zoMZJm{rlFO>W#gGaMO#z0Wl>Z2&cj0(dvrV?JDTG=MP`v!3g`8B={XYK&BfH3b@@P ziMGLEg&ZWykP!}T{c*lQyuKt5A8&Fy9{?0KDnc7Ne{^U#V&XLpk}u&D9{{V85{Kc8 z^7T`sMHN=eQ_jUK8*N0V5>I8-OEtKk!M z@&UOTqAP<7ViUQVyso})sFM$H7E>5z_iyPejOU!2nRCcDCZD-Tm4hUa1DPzpcrm>C zCu-Dcf6unbpOb&0=gsHOuW9_v16uUNF=g^W1F_59+Jb#;xp@%!6cH!aN3Nun&7Ji= zW|tB_SvJ5eDQOwvijq=n{CPJf-&Y%$eE+yN`QFatTmOknzO}T;_Z2ny{=qH14SrEi znS2}N?XQ3SI`-E;MgNAK0^8wmfLvozlbE7>f5RnEdBa`LDxMID#{yKS9Y_ew4;@u< zms_!P2R_cGg{#f!PoSEVuyxBxdHrQ-9oxN|b!>lwb!_i`9lPB+_T(p8$DXFwv3;-;I}Ydjl`!_K)yVZr`<+ za=VO|a(g2$<+hnxrIMc9=&8NZpSaxv&{LcE4!1{gdzAgvp2Njn!(fJCe+joq zLb(qWI8cF2u-(alva&A2g&x7a(T>0)w%ubMvB-ftlTQUOEbhNo$2)5vSTr}&P_fZ= zM2o0N%SilSk%b1Ri)_?GBh*2}br#LgB<`nf#v!sDJ4CkS{;{56Rs+n27WlX4`Qthf^8(jdN0aDf0w3NTB zFelUAvatkAQUDCyQztLguIN0wf1TN`dP!TSdSQ zcuq{z;fXpi@@^96IyA<)T!-0QZ;W9s*BhSbCeC%XwKdt=nz3E)_eqR@ZkuWk`9ak> z(hgIt2Zqx?wg_~huwr@9z^=GnSRv@W3MgG23+ol-Q7#o`(9>~0z_X|CcMSu`4 z^5rdByxLe$dzi$JcUZtqe~|Dc78=|)qshZaAz*9?-(0&xVVPR_oOH*Q3@pRDVBv!57c#L`&h*RNef9SX`lOLvk$xF;k=LJ)aA@smo<5-6Umw+#fa86m-IVa$7Q{Txmgai0wCkq8#&m1pdiBd>8xPTxa8$;uaI}$G;rMQNtB_g4TPHlY-v|SLQM^}1|ZDUtKAZDM%cky80 zi~=W6z(d;xe}8cLi8;%XoHH5)-=jy3+*9F%vR&|yzL|dtcz$-&QR+S(DobQL=D@o- zH%HJ=$w^4r*{_YJ3L2Wz>>bCYz68qtW1b{^Bi|?;vLRoXwi5;V&cCv!r-|vij(Y>1 z1oRN~k$!ToRugNxBd_eGH!6C>dMx`r3(hRh*nv=Nf3Xd|utbjA^^zi!b6>8(h05&i zr7E+Z%Wvq}<^ZCG!Uo6Asfy$FuQG^CBU1})UZZ0D~a$k9!bV}9|I|Yf~roNr) zz-0)!O3C(L#=7%44tuZhj8vABmpYBqasSb<5~R<_YLhh~~ya ze{4L%P6SJTSQR#cWvthkA%PTRfbGsq(G{{#ZPWh~y^z9E(HLhPNire&nS{*Vr=OFd@d$X^4k`u5`=*!v?A(6irYByxqa!1Y>t&o~Eh9pRKnS zJF1w4GveLX*^A9`h;ydjz~3I7E)8CI?g6Rz8%j67r{X^l=V*M>1w9X-j|&2 zk!|_1mIFREZ=mNgc?g+Mk4?6y9QUx*?|4%MS#X7I8aj#Mmv6w=jrw%5IJb%nf6;vB zWoL_HzU-rILaX{<2f2Fem>l3ocaY82oKD8?(68NsawnzAg_weh@9%}!td z#=bB&*^Lbr2T{UW%c^EWjs1+5=@KcFy@Pm?N?Ft>|8FV2Uunn6=5oigXLV(X+LvlF zE$2j&t?wi3+WP)dlLA`WQ#6M?e@u_xlg_WNDb&gZ;p;L^M2(iWbcUSu zvkajiDQh|M!FY15Px|Kc-RlY)!R4qGLuZUDmtG&co4gnEA(m(qy8Eo5PRu^Jd5Gp? zCvbp;$CUKs&6ni4$`MN;v;GLd8R)q&W*-x=Od(IjDH}DzFlw@Iy+`w5a08y}h=0o6 z=u>Wtt;$d+3J0~^KJg6Ae`%IFM!=>R#w`3ErBh5P2wvX3AH%~0bo(+(vE00T35`+6 zvfLy!;Z47zk@Y$u5ZaG=78D(?4KhfX9ZXrRvK3p4DsQo2h$vg)lt1T}y z8wu;^3|F;L3CQl3m5|*R1hV^(Kz2Wp>o0)ve4(NCYvWrH+RS5}e~~{{+aJMBi`pOZ z*|%S-DMm8IGOZroHeGw0!DL~z=BIn2@Znp8&-V_pi>%o!+V9bvy{Nm0NLeA`JCB~5 zu?$Wa&nt%@NIuJzQGxjy&sK++_&y?LSRF;3fn$OGYo$ObB+M-jf8YJ`@MqHfe`lA6 z0y(QO20K- z^9EODUgXCw+`Y_oPR0Z+?X4vYudIaOZq!@CwqH)dFa-(2f8Xd+;;L3!!uX8lG)pdF zNaTw8-GHTP8-S%6KLRYZbJt+0Mj5bFV@C|GKjW2Bz) zi~ST>>dD>92T#l6v+BPNKC3R`vmW2$v+nU(_xP-Pd{#L(=q65%Tu%y>73}O4J3UjO za-Fhb)roDrf3l*9*J@gtVZQJgAMW(2(30HCcxcmy5+`k1>09_|(;S;qCkTVvhi`6% zt4^y;7f!3tnW+6rLrtIjBr#W;&eym$`(w4~rn%!cj1++avI0^7PGq$Az*oBIbMI!0 zcsK8;xiXS1D?Y0~&cjI9qUaSkF&72-jnr&lS02gNe~F!4F`T8mLJwoiPfoZhjwmfT zb_tHfhG8g@p{2k{NDR@-&cj?=33jm{6EipVuy$25Dc*)rbvJit{UgzknN&mOWHn?$ zPztUg<5~~hB4KJxsfw(RXRr+u^<5v&2ovl$UxzhK8Dv;i^w-J3CJ_)U*s&-Px_}?`o(yD2aX@I6(-O z@pGzG$-n@!AV8kF#W4Z;+{z$jZ+twv+OO5Fm&hEOp}7)P%XB%_q3O896Rz3K8|<2c z^`3AnBcgbX0SiULX_Ba!Z0rVdqVD!;-KS?2f2nAiQ5I1_+adpnCeK5r18PDptXldC z&8zsKOlP8uR#prH9E?nWy0{R+oA+f-3*#1QVT1yJ4#q{YV#K2)DM%1?h;ptWD-71C zDrc#orY)U49TK;Y5m(cA&)-YA-Ru@OztT~dA`h0!(-Xa-kSNIOG~JF3$d#nQuhxQ4 ze~(F!k4mC1q@SX(KhC*kIX`;xXjbP2Kw1@M?WNfeK#t?GXY5gl%+9*qZE6e77R>8* z$pfKi*UQz=fH^_u=!y^M=e3r97v+#Ol%{=%Z6^YtI*VGbq*a2=-kqofo1^k7!Di*wzEbNBkWd;Q!>|H)?aE8vm*(VU4)B{Z60 z)^X|JmR>6*F$~`bbl@@2!P)Ue8g!7z#us?x`LH@bf}jwEQ1C*9#%TW$h|uKgf66A3 z`;Wm&dY1p12eiKv#N^r!-Uc_>w9%X%Ze!depEeS(b5{lKN^QxI4|(OpF>~K~@W4vk zZXeY77^NBWvCI1!ftDaQKbiqd9x4=AOO1w|^oP{@fw;BOLn=6C0cQ}o)SE*|aDZkz zqe8{83KeHms19*2jClzgd{wyGe?@_6CF)bm$p^b^HNkR5$XFX`f%G~^m7d%og(p|i z_9mGVQ?PKPY~8u}x!I4+4b4^-o_2P8kqpd2keZk(3suXg73j^}k)GX_=?)}DgZ_FO z$~0f8ya6axJ6`bATwG@iTHih;Y#`H>HjqnV^ym|#$6IneRW;PS)KK&6fBWE9n{VNq zEDXw{yU}yJ*+9>6{3G-nr+2OAI4+~-INnIladNNcxSgKk-A|fbz1h}yCX&}i%$Ii#N$mjQ+ z>iulxIp95!{r@88fS2U@8M%Ha0YV{HghKhnP$Tk^rn*y*86%1ehhY~8s}SgH zq9SCKuX;%xzZJ3y^`Pm*u8eiMq$g2;tis+L#JxF?_vWCeH@h*vk{E8o21UWJ>2<(ka| zEay?MoS6m71-w~;JXp?7G><(3$@+2+#YxByU^p-g4*Z6nB>*$u490Wj76EVEEbit% z62c3YWSN?FHyzy0bny7+F&(sU+H~-Qnhv44oXrN`g82&zsO4?KPgA5E@)^{t0k+>D}B6aQ2}uLZKX^g+=rev-ko2$uvM~3Q8MLdIm;w zU!^8duEMd5fT?i0EVLq2KUyp}Mk06SQfy~TPe!!+(*6{limRdN-{6qVx+Us~Yo$x* zn)$kDe*z1!sV&jSD2QKKO*W?t=0#9VKnEwsR&%lN)Dfsqi{UGw47@^{lL#y8(JRh` zka*g<0;1|ReYgz_-iXqb!fhtu5Mplx4p{7yV5k{j8cC4RmD2MPR9Qhx(VNhk+Ng&I zBkVI=Nv51s%29X>&^R9EsHnwqL1mk1ryI;le}HLKFm<4jBXmecO8OCF=+hsV0&u5y zJA{l&qj-tCV#~jiU9shq-xXWt4?rTcygNoBw9FDngmj{HNQ72!FHYP_oM=TqkvL(c z#0fI777Nz(i$!a|FQSwJnSY#O6=t82N(fw&WG4cyjk8^=D2aU#h4~@p= zJ{pZ*%}c}iIxmgJE!{L$yJ9rHgD=LHO?)w|^1c|+YF~`TX3iKFlIUx68x?75z}lTUzupaFKx+fWfL13p zaOs&T+}c`o{tCG$*E54tc9yt4eDFYeU&Wf9967vhB@{kBygvip?hJVI6P*Fa=`$ep zx@TR#ShQyR;wE(loRvQV{yJXwEz#?~HObqeT4PZHBl1^hV35CD1A~y}12V8zf9>xB zGEj^hm`G+(fScVewn8<1aHPG_>Zl>|gQ|6;@sB>JA=h|Nj|0@lGYcMjC@{k6jc<;6 zf4m_BHINLPg9m`b1C&~7;vGQd^fM8%43Ew}Xw+CThzzTWry+I&h^`@S)DhpPqpIcE z0MSz3zdL$=`SR@I^zY`0qRn{#f4nzmnyS2a%_!`7zVij!s4^O0*k1;1LiA35U&h@ zbYaDM8E>#wdE3BIVeQ_wT9*t4EhI{e~?L^=&lGN zZnf`bpK5NfPqlu8p0$71de&AMJ!@+tJ?r#-kGQ@*vH@r%pU z9(z`Pk8S@tdu&_WV~_6jtoM4>dp+yDo^`dJ^-T#coYo}v!bt=#aKUM;a=}5&S4a0( zIpZW$#I3h#b4N{xh~f9Hf0{VtsMu)r3w<^$G~g>y>nNkm>BiceuH0v%Tg*=U6+Ro? zjeIr|>yy*4au6~nQw4wCAW^V$eYIO5pQQY$(&D(uqRyWv=}E=?f3 z(w^m%)VFcUksyY(!agm=2-7}IIFj)rh3ZNBF`T9pSGBK3cj$l9f3hY1H;DpSaI^vM zn$~eiqGrqVZ5EImVzJvc4Q;G!=>szex2>KtuodCSvJC$+A!~jDWX+^3r+M<_)^Q2) z<;DoYy!m(J3KU1AXZ1@6me)H8on!1XFCn)&!q`7OSr_k^rrOk7DD6_?CPD7BZ|h0p zZ{$fM9AR50ccV6Vf470!;QU9Z4KD6lZE#*jZE(Jk+Thc@+TeC-gXcey+TgFW+Ta~k z8*qM@)-!(bJf${xR$gsz^6RJ#PDHiA`+K#)z1rYjZE&wPSgkgA`5g#xTYvqh5#pXV z&eL!!cB2?v#S+{T-j;(>(bLwQP~EQh)NO!Oty46oS^j5`f84e%WVovL|4}5jt%rBc zxX}8NAS51U85hnQ=PP5d)91Mu?Boo;HXeKH%Ub8|){A`M@@xsLl)M;h9$ID6>+{`c9RA)w?3!9QR6&dnHFXYTDL*BIh>Ja&Cs9HZ5^ml6x6CDEd&s14YH;G!Ils zvA7g>Q)_>{c)z#4+Vo&aOI1W2#-6U>4Eu2{vA6Q9fAEBy5BB-_;3@gJ$A3QlIuhH~ z2X#ZD+Exu{X_!x|sj(v^r{$WsGz~2sT0fMA zR_v%^8roc6{m-YNW!<<50j;bX)6}!)jr0Fm1hcJ|-5dBO8z21<->VC)~b>Hgk)|;<-`|;Pj-Ttu2 z+u_z$uIdgCQVyLJ=9NYM8`Y^Ew~h)&Odq3pL3iqy3;|cNALVkP>Uv1-OGgYDgF#Ut z)|o??+L(Gh$&3(6G+;2Iu)NM&88`}~YkCyse>-O?v9-`(?ZD9fXBCXK$0h=gq7HJ2WXJ{UJ-XL^Fq<1)$ zf6_h*wQpIp=Z@@E8E+OmZom*Gw!Wq-vM7ed??fZ5O-2O zZd?T9a#XPe)ube_QT%)2J0ZJXYC66OuML+8vV9NrgOd2l(Ch^Id}#VNj(h2i^xc2q zYA`Y_IOj*M15|YI=$RLW-cWB;_p;ABe?$|i7dG_oI2MpK3Itf_s^h!zVq0=Y)J>U-6*G4{s}o*1=jL*YLZ)c4@wtJc{& zqke5DaG?Ef`!&?>8aw;7nlQEOSpBJhf7TFhZIQnrQxqu*Q+M`zDwq*Y0Be9X6kms0+=Bg) z`qm74)$YLaeAWG}-_?+K8CDI0!5?CK}SyO3ClDYf7#fz37#V! zC`IE+wr%(J6=8(=OVqcCF($PL4wFTQ>!@P`2|mO+XrSMC6YL+G0amrDk4FR3!s>7B z-);b?EZk8K_5WV{6D+p1e_FrYASvZ$=)E6}cxFr13OA@fz76Qyc7oBsoast;fTv0k z@|-V_nU!m~M3y%kfz)rWe?p`O^dwXr0K{TRj}@!mAW3+7KXM@)>8kV-(}yJd4T1+? z>;4OL1>0iKn&?gBRDPqVzxU2&+02E#MAK7H{GD?`9oc?%#jnC1Lq6ofEl5N z97SFonvT0fcwmkKY}4#{;&3+dh#UT_%Dz~yl4k^{-=9fV?(zDSf16f>4Do=6u$OK6`uqrg_;sQHV}iXvybn9Wr18MsDD#EZ@xP@efPpp*af*s zy4IjQOm6VLH{wyicNW*@g-giMoTf5mz01wDMz;636ZnuqQq z1#}SGVEuAzMOXMbv+YOjwqtp&veXV({-hR#nZI72IazIFIkP4!%=?e^d5^FQD`+bB z%rwbm`}g{6Sr%fpqNcxpH~bO(4frGat$TFAtY#{hIXJJerU}fR5Q|H zI$PIsu|h;bCR@U{^*RE-!0y1C=!zMIUYvb_Tn1obBJ6=A_L8oC$x&cWes<<4Wb&dV z^M~96e@G(Hak-EcTdEKMT|u^BW*GWTCnDr>`n>D8f8j@3x|Cp-+5ApxLMyBeU+Ves?yIW)XOz9}lO04auH9wwVv zvLUaRdHgDjrzI+mM38&bpAaDi#HtX{ZEUy3_p#lYOj{`VEE_~6r7ge8dOss-IZ{7R zB^a86e?jJh$p~74VFq0Z&BR*sy6U*rAhL0w0+OR-$-H2ZD`0fLV^r2!UPeZkVpmu&P{gK73BmKwwo_pzQIPOn`tj` zIxLZ^Aq9M59je_Hz>58&yHyb;AAS>C9n}6Cf4)_i0nmai7Gjff0Vp);2jTBolH#ih(L#2UWYfJSFpD)gN~I)f1VvZxr+ ze>YEXVEN7{1Pv9!S~VFC#7V=ic0Ipo0vU#Y2;;-;3gBQu>n5#uDu|(}>SMBjuc`!n zD{eG-MX`1evUbT1nnC{}a_PC$>jc;z6O>BJi+l?s zU#VGm^_36&e-># z!Ha^ytcAl<*Tw$J%eQazdAr>Ue}@CTe*tOKy`**394q=Me`AO5HB66+x-4HP?16Oh4bK z9r(X<70`kI=#l0c=9Pbq9;ji}acw+3gZ2I2Moo)__(T#Mv0P7sX57IXe*g?fan<2E zwz!KOq1GSD)Ox-|W_EC|E_$Zmi-k~(*c*Uux1Wo!D#%@79yZ_$qbP*^IArHmIN65D zM(r5=*J_Ba6q-;$3QMLSg(p$~@D6(l=+sODEU49y=?7r$WEwaRz|-?sd)EJ`_P@X` z=V)k7a|XI5nzQaAo-;7Ie=X5fsclwje2^c2U!pnPsKBm}HWmK;qjr)%?{|{*JIUYc zc9K{B$vep(KXfN~b+wHND|l<&u?&MWlR=r>k* zYxH-(Jp+b}hWfkYx&cR}9S!yOS8T=v!S(PNM{uP!+p3T4$ik|`Wia+fHbSaY&MA=j z{w>!d_y17)f0ARRe}?*h!v#D4#;RbK95Ckz0KEoz#(mDVpsg+WDV#z%^Cx!{$8%gZxnb0(Dd43k<^_a@NbP>U1kjGMPoA=Xdq^m0s21qW=)o#S>SY;Ye*l>DZE}6Ubt=R^s0U! zAN9TJ(ML3g^+>SfC4f&!4}Xpasd@6_0T zvT~awUX0KzsK2YB{$q(B%UJC{Wr$Aj5z}FrBirQrGuS2_8-k97obbyPIKF&tVofP; zb1U!#i^%SDRlhLN37cxL7LZdrhrbBB3+*6|pIYTHe@O9qv?r7z7*T(p&LW55nUqv- z6u#z}tUgjOUo!ru_|C^apmbQbPO)5sE+!GWmDHILGDT5PDr8DV@HAXCf~PKwU;;lv zQ@IBeAC4{`qcAQ<;C<(?i-%+l!RKu}K-? zR^vYDe~t~ve12DV5Zh*4aZ64iRN02kk%dcY0V!6@Y%XE#G`@|5MPg1#JnHy50A_qI z|G3PjinUF%5t++@?#ZOhkXCv)@?1k=){8)&E3k-f6E_QLuNiN{_mm|91mBwEkc1^)X7}=` zbN6eRnXF~bn!P+wA9~$xfJ41<>V~NDaNrCb`XjTu2P#j<-ar+WmcFB{qbpmrisp8C ze?FwdJjm!;zpqctm8+shRz*|Q(A3q?G|2Dk&L12cGOZroHeGw0g$n_{J79nz zi?nI@0$Hff1PShqepoCZcuOr0+3^$ae{7R_XFGIqhKO$faKv7sX_RlOj8dRzNnIzv z+UD%Aep3AR^T8L^f|_MK#5QN zV%bAX#V1Qv>gFOuawqZ~3Ata&GBP(>qSgs9p0^*HLe=jpDORC_!e@tE3 z&7!5EWc^F51%s7qL6@ur10o^W5)>@Z5>C57Ylo&i!&P@5@9jO+&~#+D>XV)N{+@=W z9df_%^ofS1L%3hxc?$P$@?S0ss$C+Jv^{J)9CSMEacms}oI0)~(I}HhM5Pi`>@E?1 zrsF(pbb2Fq2yy~C5U7ksE{W#}e-YAL;f9moO4q(zVrPN_w%wXWSe|?mA(6{ZR z9w~2nAm>G4k=OjXNG{Vca6-_b2)e}FLWPo{NZ5DbArMfDV^mj8oWP2oEx)!L55j7) z6s8Km=qeRzqL>NxAr9iHV#4~yjA8qVKwp{I%4H6S?R$U+ySM^ z(=~@Bu{cTzt>R7z{U`bqe+8k_WsC4Oc5P*KL5pJT#H&T@x~T{gEc{Y9SzHYBjnJZJ zDyeANEp?~G2fy!3k`AkbvVQO>$vm#K$N{~~OXX7@w~i`FaHTSDT$~?Q-e0^?R@1c; z^G$49x>Y;Pi&tIn0&a~=7Y1%_z*EO5*9$8hjNOWlZ=4{+G!S%-e`}_YX=XZOJTstb zNzZUXvcuKVXxf$#xEWJB6WCCCW&x`oQ!It?nZ@Czz}W5Yut?*fJ1dSej%?eXpm}Dw z(ka>iSk`jdsgzV2^VSR8)!<}*bxmZZrqLOzS~cjIBdpG08`DQM;&cBwa(ry7$_2Yp zG!*&Hil_1NT$~10f8&;%=*o2zCiN~7?!m8_K-IEHaNg5%WrPZET9AGor|-s z_a|~}U4gDt5b02M&FD7B5{7v1K;GSGFkpcLY6$B65)Ve$e}~PTYlhO5h5WXAB+)j= zheSiPw)_w3wEWsPu4&{uyrSfi)${$u>56Lh;wtLOx$lh~8{3u6tP=KccAKieQJ8qm zmTH{HcQ$XE&1xLaG+uAv2CKcWJN$@7hzoR^rjU>}$-=Sli6n`~!sS;IT!V&YahFJ; z6P=PW!Q$7Ke=bF_U5l?A$T#T9NacL83=;8DSn@>av}oD59r4)E*6VdNxRHsEW$D~( zC(H?7l6hE+(VVuji>)s%tU3Mg^iJIAr8EdhK$L^&*&RnYn7%C$7rmPL-(7@S$DSe}iGav@DiAz@-3ICrN~0sFuBJNKRRmr4b_n0{Jm zJAO`V$DfGp_^$$F1jm7*P(;v`k9{$<%f!Bzo2ns{0(M-l45Tzz4=D{8q|{;u z3X`i&O}XlHg>M-c0D-e$$;%kWvXsC@25q2=f7a)mD_CMJ0Tl@;TNlE4bdBkm=zhXa zD&*icKwT6E0+?Q8;zaafw#r^6P6V`kfY}g4?5R=D#DD0CVI=Bk2ccaWMj}#Gbsz~N zVG(d6Sq!G9)U{=a2614ChMt1ys@*ugglDLM(JPEEA;gZzFGCuC*v+GT3s)Y6C~F7= ze=pbk8gf;&hQe9(bEv6VBL!Q{z$78;%2}K+&*9CPrgnMchx8l5B9KlWpVCMQFnyTn z%6uZTdF9f;2yJ_r;X`h*7twaZ8rx+ln&+h(Y@jlrG zpXH%P$tY+a_e_U|uf35Yj)Vj`2SRwne|-kYk4xqeSgDv6fsh{AHghC2?V;leKa=O@ zQ77J}x`Sx?)^nZE^Iv(L^k*v-Oik`-Z#&DcuS*IW-!sn(gU~leG5#w-=w+u#58h4-}q99!kz$Ac!I?!%4p4K!ptr@QRc=u^zN3fer z8+T)?+S$NXwR>;*xSi!=|0lA1r2S#Z_*g7h*Dn^+C;VbRrL%uhUV+~Dbrk3gQGxzc zYSw4i9A??4P*#HX_FM*Fe+Avdo=O}60g8uJ>Yvsi+6vIsdQ_p9j;7?PxN1edkKORn z^lvaQ<)xfTJe5Ukv&6e1$o9}xHQiT9aKq(_aAtGUqP}Ju&r#;6f?^=F5&PXww zT#PMr8?U7BYrT@foL5pjvVIc+EE1O_@@IWRW3nVH79>_>e~Hv7Elc^=64gqTDNr`| zQOX9}Oyw#B2wmA5=D@jeb;XC^3J_hkn$iPF!u|$ym&`;)WX6Tc(b#kbe2=9}{^%0l zuM+oD{y%5R|KxL*djn)AY%cz>FoVPU8JwGs_tWhzrrT{NPCRto`=R?|MAZBFaW8?U zCu3q_xb*MDf5dR_hWJK|8u~(R|fBh9J>s zS67aY-W@mJyn$bPx^mK_;iJ($B>Qmox_P23(dD3If9T54>;xCY^jZ|J^1tvC_*Vgb zIQs_2@yT_iR*Bc^hCD_jm~bz<^0-lAOzMLygg+g7T@2(dgaceI(WR7}C=aq!pzrWv zaoJNtFiQ(Kv&&v;6*DfoY6zTSgp?YAcOFN8Anq>@ql%0q!7A<^y1JsEcumdhGJyIg zOHk&%e}|r)1dN~qrC8SIoLq>f*J&(0jfrSqJ1%?NS zBEy43)~YZgbIwR!Lu}OQHN?lPUPFAu>NOOPSG|VVXe9~ASk-H>vC5VDEjeA#`HH7B zjiEqsm3{fqBNWqwQ`}}ed30Rm*N+~F=*eUff9bdy|465aXPu6#{5qY2Pd*)2*=05d zIw460C>!*GqKeAQuJK8cHt_Z19k;v(du) zf1`+<_cBEDczyu|2<=?n^o6gv($|tvl^uxbA(b9LMc=^EZzSWt2>g*v!fLIr;k5VQX%+`lRDV& zT@5*|?N}h)9A~`y<5FdaRq3{p`_kWue;O$F?1MzTOZUoS7L_@U-;gRKNm3NLo;+ln zM~W=m!B-cF4d3-eqLBF@DH2^hg6~r-K6KZY%N&h-Z;b7vU`OoE_bC~lxa&*i<4?qt zoRsW>-T6Kxi`S6#MYG`4Fc^qsJLb2(PvO{tw!UaK9^h1?ozNTKt2fEYTBb9{e_lV` zm*fT%OG7sJRS>Ni&|U65ZtU!8=yGVxn;+ilO7p{81s$DVp0z-rzdUOxsCD+{=-rX7 z(7y_5T^?P$e%HLz6@I0ljx)ePl`_QKrKV@r?rwaf~Q)wRMel1riIA~GaHK! z9K`$bAz9vK97eOd4Dj#WiW2i+KAU+E`0gjK&*HY6STpP=g7K^{oQlDBrDAZ4Hi$@Z z2~Tpa#IGO-vu}rn&O&*?>*b13Gjiig`&Xp!7rb9rxA=je>69HSE8hMr9mXU z19J|N-k~`sm@ibyc#4OrwoM)nhC_%8D~KFz?x0{=5jwXn;7TS9Jf(K)fMn*SD3yJP5rhk(=(QLv^LDA+dDLP)Yg8%TUuQ z%dl2@J=N0kCP3p8f7H7JFaj4X0zAPq9tV{=4R&~&3@;HWjiU#k4U4VA(%KU%T_>K6fauu}P;;_ysv2C++HPQs8TnScy^~puI89 zmRg$!*aoj{g5X5mhl?RaqryIyxTq{62jwm#MByJ8X;|-Se{7?uJs1NOx=)SG!TX$a zT2AOH5U9C!=AckvXE~CnjJnHJM&J}fL+&L?tkqSQgsX5|7yGAph^!p0vL~XN2E^~u za@+vT%@}VZ*g3y20yH3TF-Q-BgU=l_Oi~OW#Q=?k6vv)>a6LscP-Zn}AMss)`bmZv zWSF5TR6g*@f7em+bqZgn=$d|QlFxU^=WFwTs( z1sA(XJrk^VJj?iYD7;|XAi-{^(O1c#SGWPjSjm2bmK|_(PP0>v{)iBflxkJ-l3AJL zCO<*+e@~>Vl}e!VD=C8h254t0lGUCZYn!df6uIGNirDa?kif|pB&04qs%aJR0bS*= z;d#pf)WlZe>qpupE-tOc1rVMjX z$}CwDHmSn!K8llyZw!X_P`2V*!_3Fxo0zW2e+y1kc$3hyl(Wi_;pp)AV{K;LQDIuO z-t!hb4X*rcHUbO39}>%9SOAp*@kqmarzzTGBoxq|V#xr=HDL+k!ByY8RnQTkE%#h_ zH<{noSeD24w4gaDsZx16x_hTkJ+gEmlO#xtBey&*x_Uq4IF$r^UuMnlm9!D%HB0Do ze;Ckp?Rqw@`E%EG+)>R6YF4e!i>S>o_IKzYQZfqV?>s@%>AFqHSrwr-!b{d@;Z5Zm zQg`pP7U!$ojGe)_=K0oOg2~zjoeu@|fi=#~n404PD@B;9YAZd}-rQ<8zJ4A&WG75X zibaYFFL~e%jD5lnRA9Zblx2D42Srt)f5lD8G6Vg`ALTPrV0@g@pVS2lp1$%}FC@7j zR~3n#ddU374TUVrEIBLgzRUglAvYze%d2!xT7S?ED^X!C+i7W*YTM|;8Y9z=E^7_T^DUZl z8iUq8s6|P(Z_y};I(S)wXqIo&n7pQWd22|XhaAHX+V``nY;mW`f8+Om{vp}!2%5LVx}vTe?5xCmQ%ndb%N#N7D$$bWQz zX$VgR1td!P1QgLqF8-hBpu6|%c;&sr*dMF6mjy-M<+_?Uyv^EY{i-wkb}MMrqEpV}E%&j`QtE10)Ne!Bq7K?TSgkiI>3me=UC#ZL-q29Z1 z0}|Z(LO_Chze=q?81^HD+niySL2WYqts_{ifK|*7nYhc0F@5d16M$ynp+YV{R*26` z69;DRUFF1c^Xzlw!~^r7e_J{6&^%~XPHda80jHt}mYPiMCYog`ieOy{KXS&Hih}aO zW(dM7h;R8%;iki1B}RXWlChLzFGQ<1`l^{OwwW)snJu=NEw(8sR%Xn`%9C2H@wz1D zY4InC9UA*qz+3UpIeRn(jA%@2hpEkCtu};Oo0;B@r{i!es=MJsf8U(%%(=0I_+e@e zb_UE&g3=-Nd1MZEhI)!l;`bs$2x}h>T#m;YQlwUwDlQv=p$yGe_~AeL=23Pj1}~53!!JP^5C&y?58Esaf=zsc^SB&ml-KYxT6%y z6QSN)=}tWuju{xGZHYU!S8>M<9Z#x|sWjql zo=qo2e#x93*_3fWn9QM)O&7<5$(=RXltQ4G)FDLDHKl!N=K9hs>`OD#mu5jd z3;NQ`^`%+d7um^|E1e2pbQ%h$_*5*)$3o^59+^e?XaI#kdcS0y;^VY9A4yz#))wVW zg7wJH;%vTbw4sQd$bb2hx^D(Mf$XHF2eRa(j*nvbNqueFJNDO})Gj@#{qJy6lc4cW zcT`)Mqk5bi)eb+ZXQ`vQpFOJQ@lidEkLpo!R9_=z6-(@pzxLF2|0JijAf)*8JpRKU z9^gOx0}V{gqZ4byB^4?TOnh!#sGf%AW!8`>3$qi5saCsYcX;K!H@@4 z^?pz-(nAQlsDK}@0yp1uAmel*;z>(Vc`ChEgTzVb!}}LM<;VFc|MC~|Q~sECmHj|n zW#4lT+28rYFMlal+0V}}i~PO1ckZXZk9Y1T(L49Im#FM7QQ2RjvcE)SuNIZP_wPi9 z@i`lneUC7c1tDiusu1A8*-O*XIPH)jj(#{OEqh6{_R`8Ef!hc9NV)mA?f=~Y)qDS5 zuFv|ZWG+ykq@wZ4MZUC4lS@Nk)|S=s=NecUjelBBcWtapp&rr0q9WM)0I%$3`Ri8G9n)Kg9Wm+fCKauAqdH$I^w<^L43@qO^ z7E{X~IW7a?&EW{3ndO41NfA`90G~dyCO8bSZadeGjeU*fJ-D4&u8rfGjCzCyV`s*H zpF&^^Nq@yO+*J~u73*Ov7Sf5hN9W%VJp6)5K?TX^S7vu1Nkcxc7VqQGawdTR;;7lg zx-*pi#2Z{G5&Giwflb_tZFw18j_@!vlx7)Kn4m?UT8^tB+I5oc^(JB{4&>)%x)Hl9 zbYjw$;RN3*=*v6^o#7n^mm_aqW7k&D$eI~SC4ZFUwpqbI?{PMeYo#H~5)0ANAZ9p` zRD)oQSZv2KQUWBTCp%A7W1aGroitCl4e+wI#nN%+62JbvsQJh?KS|x(`(Sz1f{K6< zY)yh8&?>+XV7k6ch~^+o|67Gf0U>?$v%0Qa~n?|;S}PSZ4lz};%7xA_gp z@PD}J_Wh^?(@6}ZDp;~BYW%DzhN4iL;B=Z^TMad%x2}c)eYaldE7G_5VmmWNZ%L zu0G2oisK^p%^4({nlnf?DoS>3jv(2MIe&s=m#O{zMiM^xOyt~dc=+V2RKBT7jL*cB zQ=YOT;rtjNML$AaXr||>y#`wNm?-*xo@3v^fpLEO+eM_Ih6c?&;_2$;>GpWKW_h|p zQw`1DA4TJdteA8CjRKs;2?sIs`GCqrVu2LPF<`O}5RshMQ4^uog@(@CsH>`~Z+|W# zO(%+`{saf+g5EwBL*X`YxNmrf+bm#-%>qs^0aAtwxWI4$ml`hMYK99~&%aEWD`3$V zIcKDRvo5wd!?qQZqRu2QcQU`p;>_8<#rfiwJDJ}}zO+5t3d<18$$kb#;lSw|RgJiHSl!Pl34uQlcWTJ7Ea2 z-*)7$>2VSvU(+tOnZTOu9#jDrWAea$q`Kxn2c-p3`B|Z*-QUO9OCbmC34ircv7*M) zIl?`H1!$-uQdEpURqH6c(|->&RoS&|Y!iiT>>A2Esx%SjNJ)t)k}{6En(F9GgrIRK z-SZY|F?uwOSeaoZy+=Zd7E5v7ynq{?h9ozVumFo%L;FD0M{V?8ywQ8|jovHT=#Qiu zy$w)wl_!E%Wg?UcAj>8~6@L+AW+E^U`RAAh-eaeMTR07lP1S$uX#k3zz81G?o9js$ ze1K*1q=8xpwdp+BE0`yJa2I5Z!OQvna=yQu?|+^1z4-*&da2@~Y+J9QnNW-~6_8zp zt(|6j>aD$<*|_stJ5SNBu(kU|TYF)U+%*DF5z8LH_`tXG@`hjn>3^8SA!A}0D2QF_ z4VJ>u$=?WBq=651uD{D0H(nwIcK_Gp@BnAd8FpV!u{)PUfb}NKY*HfW3@@Q0mOB`G z{=vk!rq-%&J#T_7SH0E{w_`mk#}?%660YrI0ug+s%0fDMgF=(jesNk%zsKF88#ncGCDfZJ|N6fuopasq+8QdsDfrV97slbH0Hg_XBMNK ziTz!HJhKuyJV;D7YX$9RY-TS+nV&_;_O z$<^CWS-Oh4kL68Dfe0>Z1!p^DwfEN0VlW(~8OvDHB`LYL$up#UN@OXwgp^Gom+BMo&_$^7oUr8Mu;bETsu2TCu=ejJh3bgyLX%$$)adscLse=V%9B$)agJAgpTus$IvdbknfDa z5*}8ehB`CyY?J4H9!^ZHqp|*}tEn2uM#ExrGk;e!OY_a!f2)gF4{0!c^-|~+5>by} zwOFRF1GE~1!tzXCC%y$JFgpPlWOc^G`fP3jb{QI&!Fl5%PCn#`W+ahq4k6LZ914km z9kTB42lw|gtw2cNoKk@-B=rgt?V|;0n&Cy1@#~{08kuU}>^N$Mnv5Yr@x7}vc`|db zxqqsvmfT9fDzp;tVs(-a=VP(Ch|kqTzMkKEV;z#0*C7?|zKY?BN~4U}q{d-AOO-~h zpfvI-*#m@X@KCdmc=_}T%>k}Wb^55`p2x#Imk;;6Xt?bs818wM;g)RFW#e7ERWBKE z9une@B9ccWZef-VPUMGo ziOg^$h!U?OEoPF7Vyx+tOSA|*h@u*fDWvV2FJAxB7Db#uzX)}v=7OeB(A;<6PkfdV zB)!h408Wxhdn*fTs|H?cG|*&ZY~_;^Wv*1om{Q-K;*k?TNY2b$mFY38Uy6#nJ%0nJ z91$O6QQmU?262VZKa~}r--;tVp>`MM(iD_~GM zN2NmEJtEjWB7)t+oM0D)RJ41w4)WTJ@U~FM>zJJ$5v}g!9by+Gbcb;}j1tFK%T%%1 zxfEDDWYGq|{b`N{Xo7}ue}8r};xRiGkJ%aVm}gpgfEn$PUEnHX7rDwfs;Um;zO$WM zbrF&17lT48{7EcF3ruxx+J$nofJ=S?iI-h0Mw?V|t&62-A?=Su45Oh^2^%dlD_|>F ztcpR!d4)@lB`A^4O%nN>SfQ|J(&^({7D)j%W1f2RL7kL(0r=`Lp?`lhF97jAjvwj= z&>4Y=B@^CQ01?yKFHoBN@D`LNu<(ltb4GHJ(OCC`qA$C@fE~F-!`eaNAo9)0oGyzj z%w+d*iB^PqTwc;gb7i^mwMw+rAf1S{(^(x!6r>Z_?5 zvc_xGt-DF(?b6EMbc33VS&y%0mnC$0YAHpISbO^A?|wt^Un9`3KMhB{_n ze}We~lIBUr${FXezsEivQrUO#MnDH4HE9vbR3!AW_OE#O`e7 zd)L^mea3zO7thkMad%w(nkF<@Q_>RYlkXw^J$-KR?@1N$?@0ymFX6tvyhtKmBoQx? zh!;sjnIr;r-sKmW42E(BQPWSs`EYSVLV|A8>ja>%^Q+mvRy92sTQjUKh=AE4zNE9d zs_8uLv8tT1Cx3-F)V$5(QFY!)@u&nWD)6jHX);+DDH>bK5<^OPEYMUDmo)BWm7+c( z%s;tno(;x$Y8jnh6FsRKnw?WMy`}PNeuWU3gh9#5I* z=_ARE*WxfTz;>O@@Ze$bW2A9(lgZ1Y=ZbGw%-p!X#Es3HhZ7nymSADRGl}`_-2_I1 z{_R+|MsqC{2Hcv5-kvv|f#aK@c*CK>5JwHgg^1~sOa$Iwh9{Ff2rq0XLu(RX>j!L1{X_ zKffmXH{sGi7Ww@>S-Z56@aJQyiT|#y`TqL^v483CAT|k|l4t~--?LG^e@dKZFW~?c zqI(OU;7dBjHv}f&r!WhYO{7TlnaK@Atrt@gWpoukmFg;fCb|j&)81)Rgl1<|Lmc~M zIO$Z{2Q3p|$pH@BXdpOvcPGxsH54DRD-i|ufU-}@q0X%W;PEAJ@gTR%wIeRAN(%|+ zUw=0j7M1fD8M#kQ^uAUQpttjHjyock_}Uk*U*kg1+Kn@rz_9vZ&7Zq2B(jJs<%`$X zYrpKC9v>dRH)@B&nng0s16mHQ1=bYTfD7@hL0GdG@KZ~upv=DBL*9)3x9@n zgn{P|VJ1&${NWCsdTM@?@N^&B^8uD${xFwZ{ww59JD3)G?p2aB_<9gzfuTwok$)%I)@JP?zwuWi+C&Jbx!FQ%%Xs6}#Z*<4r9Ty+3oW};ycJ7o+% z|A{d`hC@F^Ll#bgUo_s%!;sx1`SFA}4=owSID4KrowtlQ;}Vp#8AVA;D?miu%~Ti! zV3XnO5m41E0*fYyZhu?PFT!ajqJ|a|H7KZ1;&5W!f#bDQLlztHgGM{{E7D zBKMb+HEn^QLolOEi!f5`hD37FE|pxY6Ujwe)llbW4RzKETpaoB%oT5EzIZ!xvbQr! zxRX89f~*+euGL&_c(k!li8%)@5-+#mydyWjcQi$I8=sIN( zb)BZzO+;p+VX<2^A6vsm@eH8q7`n3nmR~a9hLbbA*?b=`G8^B)7O0D#+ZJe} ziY?H_LtH_-;ftc^QHr9j``1wvb^WvkW{W5@*wEkKcR9LU*A>+pUFX@4Z`P7Z8kNnz zk49xv@FnbeFMk$%FBW_+7JM%jeARpjyFq*->N@Eg5pj&Fy#sG4;c}7(MHBFiC17ZU z5yT~Tsr*$abp!iax42@Tv~I8zJgz&>6DkwWJ)@A`k1xX&BDxpmEsW`2T-(y9?x`5= zh2=;*IrD@04aQ==d@KefV?i%3nO@~*tuIYh2<9g(RewUEK(Ivk1_AC%$TnC`wn+)u z*hR01Zm9Od(DMh_sIg!wF^MdB#&{C4Y&3hGu=0BURFs`8r|htVvh>=#bV3fK$qFZ= zwA4Qp*@k5jsICnXC^&skXI(>Gg6#-IA`tQW|0KD-nR#i6v74yqG?e- z5LE*kbjz_NUG4|%>Pyb!GT^~#N3ddqqKh=Kc7LOlE&(149}GO`KOAZ@xrfb4kO$TN zw3@myBz@pDQ*!FV`w)B`T z8|<=!S~l3Ug2|t3w2MJSFHLnM8*Mh$X#Nd$|Dmd?o@}%c#r8);5?h5o*@!Ri{l*aoWru ze}yFD7xqC4Wy6A|j(Nq=?0u4m)t1&?Tz11Nm%)OftdWf%@5T3E&K zU@Hx1z)FKcIA|3yd&|QKe(3d1YM)Mz%G*f-?}qv~3}>HCk9OiG;{iAeOPlh`S>=Y@ z1hg6CuM}aSd-MDnpv&Z0S7MTx>7N#rEvM%Wv7X@NjF3uMH;{QjOT-!sm7G z&;q(E0h#VzJ^zHeO(xt`p?nJ%mO(%-?{hjmq)e5VPIax7zt1I|L6 z;$S`rgL3A$oFz{9mIpJzr+=mV#TUX~oDwGZos@pjcih2b zZsUMVFx353;;Ah$AySC%#r=Kvtr~)Xq{xT96}Cy%kaMDWz+`fO7YaL)F7&{gVzv8D z4KcK&DL;S)SS57hPEug@3rR2Brs!p}FaS z{mP)!l{Dnh47$InfgbwKR3%b?^8k#ezS@5K>x{O^)O~CeZs&mCXThR*Zwx`>jX9c4 ztN|W-6LKV`mm016TfDa*Nq-%%lR58}REa8!VrCOO-p*#03xJ!-u}259HU$0~rp_Sa30UX{ z*zKYP`1_G%O!#>WLQP4}oRCiQxJAVKY2eM>&~OND(+T!Zz=6pZe|2XRcH!K=K(Mk6 z_jMzlnIw7IaMR)fV$!1>$YLg3@~Z|?R%h5Z6^+01Vd3%uPk)7G2+KY~eQR(9PK(re z2u|j}SSWC1drf5U3OI1$>(@}95+Pu_mL!KHEP4LM{^9w#h98pC@I&d1Jy3t}hQk1d zM(xlIQSFC`1Aa>IBXx%lRGy5bM>Up`<`C}oK0RP1w|My(oV(3WacIHqSS*2T{T1%- zKa`%Ye~|O_2YK1S0e_@q0gQ%f_`0F}(?yhmZYH`Wi>dkAgX`APz?!iQ@=lSY!0>iTV_zCh z?tAwWz0U`RLl0%04Juu=A>zlf;UY3JaXLPB^sJ6F;(uxwq3$n_miRA&)P8`7zw;2( zY6&=Z_r0Ja_$cSkZl6U%P%7Z=-MY08Rxn^z^bl3*eGq^))}E@` zW6vGnWqoxa(UWx)E;74eO??aQzS^?7L07pOK9$Pko$pPT)d)Aer>d{#Evqf`o{F%< ziFa9b)PE_in(mC$_%v;MZw0jz-&sD@Mpi)5Jrz-);v+bnDpX9;MUT9q2z8!XH?JVdFkOKO6UZ!p42h3N;SGanHBhfO^^I+_cl5V*}e# zxd!x_KEYz9PkeymUu2#!)u0uy&^Tj!%Xvk2kbek7LLPNUkduTS!=D2JNI1CPOF6jT z2nY8&k&yiRfhX|uD*+X82pFu!V=wdFk7yCzGL4`(FMoRedHHiPFMle$UZiKB`UA|C zv~m!qQ_ut?T@_WKe1@|GC9C5bY7c)dox2S(cYlW4$8Q?y*5%s6M(V~uX!7UOAErmI zx_>4yJv7BS#eb9e{=^!^W_68Xc>9;tCx!`qQ))%Bv?6rbW6x+opd*bZi39xZIvJQ#oCO=ocqaXpPcCY zn3f*snQgBWXQfMUR-kVh>dHY@q+1zL0e?863P2S6KQF9G)ia(P?yf|@%QjsU=D$^` z>$?fzV^Kl{Iru|_@Z>^SMF#IxNkwnt6%vxW^Ab_Ly5yjXWntVf!8FbKH@2X-05p~m_Ur8v#SJWPeM5>@faF!|&aJ9nyT+xEmIJEo`W|9RE7(=DcteDt* z{v&QHIpQ`e-W;l^C^EC_Yn2sM4%;VHTWpn{pc~`_-GYn5x`uY~H&9zN*F>$w#>2H1 z18XqGuPxVp&GZ-5RTs`J4Sy}5RKr26OvB16CIIevH~cfG9qM1HcG$(S+96rI zyY91C&h7fuE$4Qf7t6UvSco7?H(i3PWV#gdhyYO+Y?Q?}t4C@w{huMs)+r8P8<(=D4)7Jo_ARh)i))raRVq`< zaTS6JkmlY@95GPc#mutd3;}xjl89@5L;vlBUEeBz{<2Yu9uOMZU(b20y^#oft`CaN z5m^D`#vjP!Mt_tQlgj%V~wY{#-hcxAO{lukf8L@0D92FS7~EclehInZ;|7q>SCL ztc>Im=~?vJqD9*i9M*Oxz`xD(n@^gGH8m&8-JNUd?tu6JuWz=SJb%82G7oSKX2Kv; zwq4y;L$q*i3{^A#^$CT$#4hq-E!xj2H zBoDXfrvZ7`Lq{9r;a7A(6Tf9LbOJzVy6XCRb8`z!S6#K;*sRyVT-DWG3c%{B>l<6G zrnU{JdH46K4=&!Cet&p;d2-r)e|m6sW-5*g6LJIrdlcm83_tzy@OZD=frq{B@w>y* z&Tj9pdwgap3?})~aR=TM9tIS;+oFRbl(5%5K0erkY)P(x=en4R>V=eVPY?IsA0(;h zN*7a{9UUB;Bng5E#xwYSaC+K3J=iyC><2(ycl5n(=Y)W|n}5oH1$ML*LbHMCs+$}2 zMoU8z(^VT=_06`1hNi2w+MCUmAh5Ncg&!U-VTbKhjKSG=fZXjrGve;70^siKA$Ysf z)LBnieu&*sa(xIn^E$SIL&geU?5wOv->XLN?O+|YIo$x)~ts4fD}tO#9|)H=}*$NF)%clhqt%d<~= zdk1G{g1rJJkvandVwT^^q!&eHTz1ahqiHY#fI-x&Sbsm^Ayc(eia_n1O0|;`QgwGr z@^!BC(}TT(!_NnoXNT{P507ICSaV>(LT3OPIfJUQbt|NoP8{f|?;wuJ@14b!yxToI z5`FHD%D2=|O%?U?r-QQ|D=N~^Tz7aJRvZMho0NZ)cm{=P7ns^e)9FkX=MO|w<5P%l zw{?h|Mt|oa+atJSG=6_xztC-B0;erPbywA59ygyt{}KR!GR>oPuejO#oT>KBpU%3+ zI#F?`l4^;`lRlgGC(hs_z5_d!2{aa)`||f15?@=BiFdQ-V;jcPngsgL^A9YMI9OYN z>y){#ViK%KLkW7Cb?uDc0E02$C1?w4g8fic_J6$j1bDl!W>N6cBvCDx_k+72#M7GN zk|20}(2inXuXTWr>thzv6%cmLYMx)4cmr!P_JUAXG?byVtQABNw21p@2z`#^L%>Hi zI}mgbTttu5VCK02CYYhZD)9V$4j?+1IM@y0CyW~kAeVJ>XrqDY=z%kGEf930iRplR z(trOzz)I1Ojxyyco#CAd2peFIgh*!NSPe8p)`6?TAH-W?EON~-j#W!T>2?^$a4n0g zH;&bThLZY?W0k~@+KwG*JL*xsCAE(%P!nRU@WvLjQd&Zhn}Unn(kxb(5t@r&#N~hq`X$dSATEd z)us5#gg4^d?j&o9C7xda4uQjt1qETj{u#>mPw_RZA-X$C-lmh{TjH%QY__Yb<=?Ap z#`4{du2pdZ48;vFq0=e7g?;ZWolo<4L0vcFElBUh^Ecc*v+l5Zm6Qx{S326Q6b zoy6(OJ4Df;YlFC7BYG#pLeKQtr+)zZH5(5|WK57nVAuC1lN}{>NQ5R}^@PbG;U~bw zd>0StVZiosoZHJoxMPzJQbB-mth##ctz>t1GY5~Bgi}ou6A*}lah94s*^(vuFQd~( zd{^^@3^j_4UBfPkC*FCtdwF_txL>neoBimX9=<<3u3`7u@jaJVd&brmHGj*;wE&0u ze_Z7i_^%QAeKGl#{ACtza(kx-yS)RxBS+|62}3Jnqv15;jhsS#BPl=x@ShQSE4lt3 zM(C5|^{J{w=tC~tc9wd-KOK7?Ajo-Jxf!fz_TWJrAeBD5AH>5N4^G@ zWojJ_^1(9Z-cu47(9G0niW%ZK{@?ig9 zA9;Fz?o8}Mcj%c8U@W8a=EXManc3ig%Q5_~0N~s}Eri+(zJDKDV*?= zt9=qi{&emJ!hcV?3kN7rHBDX6aI?m_&-IoUh(#TEi-(?15mF*Vbhf41W}*rHg07q7 z;T=~A$Lio@*K}e9%8HuSQ)zj@_@3ngF9wpynpGo)C^ajnS@9O5Q0iEw@+P1cu0VmE zPxzGteyV}RE?wS4Rk-cYVF6Bl>;$?sbIg!Frmna$(to?0vnD`>kR^TZlduaePonZH zvINjehWI-ln%^(2wzVXG!~9oo14j^SutIPg>)I=kT86Kbn-Z^ zjc+qkhkqo0(DW?H!RgJ;Wg1(7XQ$gjHn*tBW=Y6)Am$|PPR5LwRmVeSYn4`lU2!Fh zHLUX&X$LDX`3L?O;jEZ>?2+aVk` z*tJ!~vTbTXgLU=@LJ0m9Ur)(c9_~Ye10S^A}^yvv$6n-?$nU4N0pd*6b@hnx*`CibP{4m}0!7gKkykh)|| z%H}Eb>it1aJusM z_3$gwL!$;s;y?Lv91xT;my{1Ym-_H zZ?zj>1Gi_&iOdSK&o$H|vAm z!qsvndt)o;-nh&)^p2X#fb?&5Re#0j{)OqD`xiXSQVmC1!OfrEr(|9$Gi!pwkV~f2 zI*L`T%>H}94Ve~wVhy?HO+4RF{_*x;Z+CxPLCUH@pg9y{0lu~)9}q=oqL4_7JXgON zJ0V8${C)5CY;4)yjiJ{a{F*edHoV~zA7zyr^XM1k}OGGsOQZGW7<#V zWX{~jjD_!c;N731MFjsrL+J`;^&!`c^{C;F!m=wyNDx14Cm@#}q#wHc_IYM;9oXdK_${H#Y+3=1(= z7ZDnXer4B@hGxtM#x}{uC%U~1GvUUt;<$Wb#WJ8F`%#7fQ*>#u#5c&6;6 zuv}+qg`i0$4-g?&34dmeTWbe3SP7u8a!C+cfLc)g_X^()eQSz?8l+N;1wj4&KZ>y+ zo=!v0p8{|PaiVOk*KIt4O(N1zAYBK6KOl%VH;x^S$)q1+XEY8G@wJ$QWa{&&9YBVe z6l6_8!+%1g0fvic^`L%=&^$lG zJPpjM1~N81Tl*YYFn=+zC~a-6)l0db6XrejVf(jJ?nU8ldw2ei5-~1oZul<-3kMg7@5# zm#~1`h4csy!+)F;E@B@~34L=ex`xnznWdH8advk#w~j7WP(BCH^!4$Z64J6 zcQtQ@p?@hgOF>Fa$q`hs6ttjdbr4`MFy6cwIpKKThhzRtFtz-U&bvW)<%Co^3SM>QYMJRg9MXm3a6G$rvW+9(n6`JwzzTN;=_&j+!sJ~F%M60SIOqP0Z4nH?SNy2T*1F3o8dB>!38KI zbS5*aVlEgN^6-Aeeaa<>zYymOa_au@MN`i-^*|%D`PRIO&{n&?RpAi*vh?g++uEQ< zCx1T&;qU|j1wA|2F$!mAt6pEPQ=eOQqQdF9USDh0;q-LX*4AdDt)VfLy3wp}fkw|& ziPyD;`Xs?xT|-m&zSdgT&?q^(ugQr#qCLDbU48aS*&43fo2@1uZf)Sr_Eu|Sy^ZzY zdZcU%o`o?-dh^%jNH41#QB%E#ZdAg>-G32gjUw#9E?Dc%n0qPZv$ikAQ-ZQ|*Q%zw z^JyRZoVQEf(4F$YyxgWr3Rm6Q*x1<8QVu{Rt|n?7o$31r8gpypGj*Fv>Rokft=$l= z5}oG>^7jCwq8Ff|M*$Tb{dI7P_R<0VC`u8-COTw)k3_%a!^(ckoxhFWaz~C&w0~a& zPeg%u7Hq$v7vu;HEZ^Sa;6(!3&U(R3iCm-FrPrw3S7p_hSV8!ju-Zyo4Fg76&jBN$ zF}7^%pL#dO0wi|36KCWa$^g3|CcA32`_+Wp*%LsfX6|}N(!te;K2r!DuwG%hF@Ft%H=|+jrpq>W1y3z!LSp`{t~vm}EMQb>NSRqd zaO3$lOEJr)h$6v$0}6z7fv>^Vp5A%D#!wIDeK5*&M(&}jE=ZMzi+I__7$gwa!Ugfp z#8lS@H^&4_hy<3n1^qaD9>}};eV{Y%!AMw z-o=vxSuj@)Lp%+VcY>%+k8_JiSpG63tU3y&#yW)NXrsxY_W&v}3t zL$p>0@bITAcp{MrjMv~+8h>+V09=GFg*(P&G3IWChOsN3Y)UMA%L$0*U8?zHVMNlo zBArB&0y#%R$rnonM+AcD%SUi7ATUkZqvpbpq_GXQ10jlnp&Za(bbmDz*Yl^=L_ySj z-c4d!PF0psV;grub0pDl4Cj-{FJw-vRGbqfEsi%u-sqF~1@5i6^ZvP*sEb_WDTny#n2{8hbd+EVcx zobhL|Mk_)JoIfC+a$H^46^((6p%WQv!%rV0b@n)(o19Bo9DqzZ;yaFQR4ONkz`7uo z0i2*)bs?UW#!Nrjh<`LqJ*F4uFBHl)fkN|ABEEf11z%UxSZ}ShDo77LApZkJL`&ex z($WKVNA&mwk4g^+B3H(`S}@iR;WmwTWZ=<6bjA@*T!h{ElwJW~s!{B}dHnmvcS80Y zX$C$IFH9E+SGvK&ZvOOwCf@&d#2>~YLO$p1!A2E$YY9jWOMfxKp&%Nd7nERiRrO7u zn?#nS1TS6|gIL0$NptSwVBkBm(DR8qn4S=iV6*#qf7no4u(3G@*d0Mq5z}xYT#Hkk z$K+yB)&-3rFqC!^Yuh2CO18UU-*Qz=9G`0Yjc5L0>WG zOpW^*X5dz0fN}jJtT8lH32iWPHMB^mLIVs*D*{(1gMZF!fuiYxeW75#YQe;t$S5WO z{Z73m3u|_Snw_L(X7Uo;-;*|EA|c_3YlUXpY0SOvuxpQAcI~CR_H@avef?j&Yu|m( zUHkgEcI_KlzOzS-iW}j%hWv}zR!e_J9x6q{<8XJ zALE6ScEBM6;$EweJrtRFRBWf^$7!g1OI(NfYjYu=(IZ3Z2IXhN3)~D93 z%8Gd1K!DCtPzt5egNrduGtg~EKRwt#JU!U!<@1xx&cJk|Ju?rIjrQt0ZM3&98|~7K z_G-yS+xsuxXgl9?qwPJ{M%y(L?o80ipI@NC+<*768-DU9+@L=V)%R7~X7_7(WZTg@ zyWoX?+Wpi!Fk5Hd*<$TTATVE&bj@Ub8hK5cev!7JN_>|=T5%oId}YA=iI3Y z%1(ZeeR;Bj?DPo^GR`#{F#_E_-|IpTIDc#}*(K%YUOET&zble+yfeR$ThOmbB#E~m zIk)srzk(Y;N>Fd~Q7r5~LuvEBJ>+BCfvweehhm3E<5&H+NZWoJgF;ZH#^Lc{?{N3% z@~pSpJ5ZQJ{gdhF*IT4jAI!HABC>O-Xg&@XLhzO5Xn-bYh-@yhKO7TDy@NVe7R$*CHrA-}R;Q>Daj6r@f}>;7J~QkQ0Sv?h0F`ddMh0)b+3p-#V- zD}L}9;Z$o94^T!zE#k$0A4Vc zK5pAk3Z<8%7vD-!=gLpN7jt|%*_X6md@D(vD?k07<`9AUlG#Iliz#T^k`x@2DoH_0 zPg2m|kb+{^(O5n2Kb`Kn1JIVq5tBpdypM2H+1Wy;fE z=_ZS)7x!GSz|Ja0o$tgETQ3~(QjXY>bHvnna1o;jf@ScP>)p5tV(@{6c>y?hx0!Fu`lkxPO##ZUzw|F}2F3`!QuM;%P300*wogBDB$JwM$F%B@3qo zo&y>9gSD*&_#1%n!CI?H&<_^uF4~zp?|sKM7Ti3g^-qr*gfJ`2&fM9veES2j<}wzc z6HajNZsv`AYc{^)PR&`zXE4iT#+t^0#;aprVSgg|j*aOQra|19M}1kw zH%&s2UgCD_dM@}VgA4i**yG0L&pfcq&~rl)6`TDQjIh&XqqN<${3CO7m4D=Ju9?n~ zCD?;)cn?n|&_DamSj6p88a|#X)G9monl%3xYE#~>*Q4BW7D>iht~6%1wZH?v1cu#E zWB=0|O-+dqUw_Vt?e^;?GsL4^s3T>y_OE{`JPGM_GvBXZ-XF7eBxUJ&0z_aA$Tl2f zF%R%Dz70Q9Yc+6_BfWfQO`XY|p}Ynm27XOZ;?Z01`RQ1LGxGDD=Z5Ii>wBSxKH$kU zhRZA3^&M-10?Q3v2iSLp3hJ{7C7UcrAhF&gq$l=rDSz7QbqVzm7#M!w2L5_`z1`e` zRBQ=kiM_d@DTwT#{u$eyU+ZmJTXRWmYq{FM745OLHI4-%e8{Obw@{7#U(59}I|YSy zH1xH?9zC)SX!%;jdTb|{O)MBHzU#1^PAIRbH=1k92d`OQ+uS6z7FN?NuV%ASJ&jhY z)q+&QN`F#b>-A=N-L0~^TY80xTlLo3#=|Ra3lp=^7OFTR1-IDP(RUqeJM$@-tjWt$ zJep4|pEfC9&$v-ONoW_>vmI=uJJ^WOxLKv3mcFr8p{!P=vX)T2q1T~_EdWjJAW?-Csv_L%P09-!DJ5ReZuE9o}!+H zzOhzTNu_z1Y;(oCd_!N`kW@rCD%-mOzRziSOb?qmqZoRbSVtt!S>*JJ?5}nnz!Ru=*o0;oHiQ@X!czvzn z`ZlZ7*W&bSF0F5UNqt*TRI^Hb>r3lfuTUTDTYE``Z9aglr4_;ey>6FONG8Ktg$kSX zr4??l5h|^aP;;Y*TJ2=nH2HG=$_mNwY=2d$uwALbtz{JwYBj1cpd^`$j7;<;Z|C0*2wqLtlFcHPz{tNW{~B(=3FRN1aqtg^kVN`Ihd zYpqI^&E-|b$Mx%tk}6w#n98bzv2M3n-OH+6TUKS857W{r*UPHBh{5xygCYpM#(0VW zJugBe(u-6W9&2lShCUIaV`2u#af*l7$L@fmZUC%IZEOYZ|3JV%?A8FO(6J`q1zdYw z3+6NIt6C}r08(IENkW%K-!A4%3V%itKq(STl~_k~iiZNNM#Q%c%Dq*Jeq;>whQ-2C=$2 zR2?vd;$78{6Jrq(pKk$+C~kO=bVv=jdN05LQb$Ya4tElDoAB0O&KSlMFQ=~eS54;GjB~&Yn zvKb;AF)%2m*85EDk=~-qjTEi`OF*>0CkYiNRU59Zmf|jns5qu+()T+`K>mL!2FK`0 zhppi_DiUgRtl17hjJIZKU8>qQ3qqmZ->(crJgIH@Y{gGBN8?j~%zJ1^2pD8S3&^q} z=9DmGU?(Vyt$^nU+fuyhQ9vNcG?Ac*rDWl{z)KcI+DxIbY>5nsc0RKSO#dWj#aqvt zU`wC{#kc7Wi%tuc;o%3yD4BnwQ&kppl0lT2-1s)+p)@6K*oT_8WP`BnQWDHR|i9^L_hQJa6p6)Nt_TgyJh zzt3?Hk{XqywN^okZoUOcKe;pC1DgR@Xa{cSgm>BY;DYvCev9^;VgDNYRhw||jRy%L zh)kS8!+CZLY~4Eka0lF;a_qiqo&k8sVUkgH7|@NZu6d=_}phq@fEf%0`;{#<-Hb z>bR1f7hK6l;YxP@I=GU%sY%=;xRRY1Pm=!ainx+Tm2o9+|2DXiw+vUZ0Id@Y8OIRj zYA3fdEa;FJ%KL+!f(Aaefrqdr0U)psCUYArQDhuuZeNF~;!}T7;!~w!V#Q&EJFfB5 zS@&3{L*)$b06j!n8N-nbj0Hed%|b%~#)>gDZ@vT&3sPYye6L}0E0PqE7=L>|B^01+ zDUW1HJs0Vcj5h&CpTdzp!rOESvE@Vl)NaNg_yHCkz^>;0qy`vKHEE^9g$0v^tlTbuWOsIaJrJUG^7xo8ax{Y< zOeKkg=$Kj(n9Gk`b+b;OtyS9`-`~?9+8WF-lTIXCKj{L<0{lyUf!~X%kU#L78~QT? zf3il8!B(|RAhAvep!KnE%%0LwB3fojfB zZLB)y^$UMivy)6)@*E)u>kdx2U^{$%5xYrS<^pJ81Zo{($@$)m5vUCf(a%PpHnj*z zuA`h2P_5iaBni;~!x?GF+Lnp%B#7O$xq6Nf*td%^H;c+Q^2B|QU0OG|6k8J?TlQTI z-{Qd>_7Pp74Ar)`t--v8GRy{obH*{7s}>lv`;31LFxW3r#r?giIwt?5t*$ao#n(_B zpjd%$+Un{`!o&E;I&WNX#)Z?Ldl&j<9YH`4%RHymB8M)i3k|_f=66`9KuZn7F|F;s zkFBe8fcl!JlWFkk6?eLTN)c2^FqcT;H6uyonnONDzFCjiOV@PFI<#hu%mFr= ztz^N*g9?roiSq;-;5yjmz7^M4I_l-Sbks|4M%+PpCocx^z^`F8Q3XWmN0g{5jcO} zR8k2_Hi@O0m?$S#Oib z=2Q~Fw(0X0idW!y6NTm?y4dC$F*)K{`hS_tdL6DT^yiPQdR-W<|#?AP8+f%Ep+37T|5xGxRD)%wG`R6(GrG3f*i8xz9q@P{E$!wiK$`z{0xBxN%2$;*hL@hmJGGRh0KKF`rl2%a>Td5P2LaTLTyqgo zO^KkMg^OdB=jG>z3?l3{-WdVxVqO5uzw9=xt-7ye;R6Nx}eVHFBHIa zNq(B4W`w5lzyB+wKw*F6>b?p>XF3L)yXN>8N%#_=v_uLU;K^_Y{*lUPZyeY5Zg%LO zSPWsh`e?`1M+T<$8OSny)uGVbo@qs>+1S`v9{AgfXTwSzS_e{3;uBUIS`L`&Y-bk; zY}-_n=xd_H$I(&(AmwIdfK*S=Zb_J0%$+xB0*(kP0LilOFH z__Q0UputE0Wvmf|A<#qb(`<(QJuASf#zH9{9-n;bvEazPgMasSPY-q#Bh>qoxv#P- zNPPLC=syX^>EnN?ca3)^6H;veJXz8!WzX`dgp`IP27V=&mll8SqB5M6_RlXrJ^|) z#sRe^fEyE7Hn3lC*-pt3nZ~N-dN$T;y)pJN5em4qx$u7lzzo7M2D`J_#DTz&_6P?c zIoGy>*RQuV?>xA;zn`f1Jh(ssVH(bG7&F6yAcI)90QU|voLf9lR-Q;h9aBNH&KoN* zlvkN;8Vk2Y$5fOk)tkM$!NeKVYz!hp><;dfSB@45N;DMWvGhWK+MiH#?8Ks?C(e0?2jR;@l5 zI)~0=Y6}BD;z@>hf`*u&kxDRPnY4U+!zj(&RBj_P%K?nUo3c`1vrC~H<0YiP+bT7>C+`Z7a723AMvh|^cg?mJ# zjBi8i+ChzokZQ^+c3%&*R|;%{AcD4Pf@TfOxS&iWWgq~zFc9ttHf%VeAa+Q!MP#OC z;ZDXVQ8QH0G)uHlggMB9z*>1hamCo}h{%6$bM^r7Oy&t4GB|>1fO}DOq#Qa@4vds@ zAs8VS-E+3nX0`nM6Zi`fsS{Ug049+->;DR4`$`hI6M}Y{5WZ7O)azi1_%KA9gg#^= zScZP+{OEH6JFi}8sYU^9Vg*~$r5P*bFgS?K?Bb5mJkXbO=Yn(x{w6lTncEE_vN3<@ zjV+~had)smW><=R38^G1Q6H)9{k`g%Oo^mv0-_5LlKL&G}5jt~@#^-+n*o4&)G?efEKU(ArSn*d^>ER0aoCKqjvdPI2 zK*@6gcfapWCfl0bmMdQB0X0#(y}Jez<`>6`zf>i^u) zjPw8VpR@nC7ynex{}cS@?Bbt0+7E9=QB_g4=4T-?sH*N#MSojOTog@7*SL%tdP0sV@t#2L9 z2a-nWBOP?Ble5tCtr35YT|5%LFn+^C?3o*p18fe>loT|{6-H>Yy|La(%Upl){3{FvZmc!8(w|&b-jbV5`i99@B8L6d zHS61M9_TZcocO6b+;-}I=W8M7q>@V;xnv~Jm=RiQw$>ZaQ4oJvHrC10Mr(6xLngZX zHYVBvg#}^Bs! zB9OMRqZ>3vAzXi?0&5CDZ*}ez2d4F?2>I6sTwM^;$hAEFcSA(lmNTeKv z1uJoS1uYW)yaovyAZ$L5qit)m-B{1l_W2Nxzj}5w>g`rL(*uD4ic3#R)OJ$8h-0>@ z8B!_RQt)LFX*n(Ba;r(XTq5OCL7-)VXiM0!A43z6-b;Va>93~sMr*U4U5RcPv8y!>9VmR+bEaxEIF?&_+W@zHm=k3LnpTEg z2%RWofu$i!n4Z=nr{`9CYg5WSmpNTBb&tgLl7C4#U`jmW@DuF(?Phbckz+fmxI+dr zkg^wfLVg=Z$gkf?>di*}&Q;%NNDn&ZK+9JiTX2Y4TM>83N)gGtr8+t4Ia}X$e)L4$ zoNIr2=gtLMQ40ze?BxI3|y>+7e-R(oq}$w5OxLy-HjCNqx9;NkeicsMbRN(O5s zxAyk2?|@m4aIgopDXbrNa#!PWR#GK!QOSRnlTaqTRXlQ=0}dt2Gz-_l%4~D6gl#T? z`FSjh3>Vt3zrU|Ha!ebDaA>p;atP39A)D(B2pj^@Ldf>2$(5cyF|cyTzZUt|ONsk} zM_wdhx>mZ}lqhvMv{B|mye;p@jE6W1l2L%LR9u}LU}<#~ukhz&r<1@geaD*<8S8%v zLcEGz`2L^O3m-qV7e2d~eEkvBSZ|kxG2BiEqhccZ72wQ&+~9~|hb(Skm)oQv(EG>H z3PH2&5!iIIabYU#SwW!k4loU*(VyVJY+jg(_<|-OZh9Th$7buoRN`OsqmRi8vwdMI z?3sR;d6S8`eqk!`z|&gxow-3$TK0b(eMuEXn-``+o|Fi+>RTWUEjHBaoG~N3U*9u7 zfx#}b&zl4p%W&Y2*4NgwZCBlFZLKw9L_oFCYOJ+k%cDzF&AMpEq}GWY8(jT^)zyq7 zTljWvUC2=ZYuU?$s*q47KOd1JGGNZubBTMNT1UQ)uQfIQ03nU_R5?Ubi1mNL#KCTu zdPUaYz?&p56P>qsaDUGL6xeTK=r;so zU|oqc{fpX* zuQH+DQk#a{-z%#jgZ0FXlOos?Tg}ovasQa@i9hX;hY7OInDO$|XUz)kazjk_L~x$T zvo}nJw7ROCVrvi{6GVSa5SNfScJr$y@xgPgYi9&37EDchJ_x~TuBdP@iT6tRxS~%m z{ZL?ftE=p{72LUlL&n~rxunpNMpN%3J$AUE6Nx$8MBoxqsmJpG`@173Aci6R64>5U zfjeKM5k1$$oUg8~3?j7F+GsSF*$;_|>GKN|n)Mw_T%$9vwBkg z73w)o?$dJT9Ws#YzygK}B$x%#L)Zu81aO6N;0h1NCUGF4X7ofSm}c9Yp?Z0_fAIP8 za&>iu)#e26eD8k`>=M5j|BeSRANm;offH98b}<)q!13)mB?_iD?@$tyUSMZxaWja+ zC+upCcD+$yOspJBMGgiskMptwfj#huUjYjBYtB}#t}fzdgHUqjFwO=ZAU-*4e{mX3 z%uHPQ5t$4XTq{%dD#SWHmTtuNFV@WDW_J!@R9kwrgzaa!?$M2Nwf@08c3BHyM=P_Ns@)MB#YZvDP0`Hi&U;h(q(%hwzxW@-1Rlh zr5hyMj5={eY3D+Sd6hnRa9)Uu#Tnp2Jjn5wL|*8(*@Hs2^8P#@U*_kuN}`n2_$l6- za#&g?<(qO2cFdB$%1H%?-L77UubpYs(aG@)mU^N2*V z68;6ls)(p72Z^d;Mwy64WSY(F?hRR;S|(wPsA3x1Z)oyWHdV_qR#sd?I$Eu?Mc1r6 z*G?NM$<+C2^vb z+F2Hzo<`&<8=jG~k-A>I*#FTTy7SoUOochD_vECGGu#PtpL24h`OQeNH&V$J>NYn= zgB88iEQ8F4S0m|j{2@Dc@1-}lPYURb>+FB#&LOh-`KK=wQx$bTG z&&#@~&55ts9gnu3d;*}v-TtS416@W^g9-f`TYPwJFQDy@cXuB@{-n15f1|x?j@Hhj zr#stsqgc3@CJ!GyZbO8Li+_JK9%z4aB8@t>w@8`ogjG!7LO2{XeF`<07J?ffUWL*~ zq%LHQixq&*Vzxc0m44<|bPx?q4Gx?*ydu#EBwFVED3T?qOGN6}!Kk?wp#!s?7LqYF z{%0yx*~-(T?g@o+7ekx~hojUb51$u&454vHk-FUvM;3+_?!E*#I_ihNFphsk+#p+n zv%-c$auZ6nNEZ+ZN5wq2#ejQ?`gt4sz>lLbbDfWCYfgQFw-UAJ2GMd2h$BkwRSu$I zv7 zVaPEruoFg+V|9O!i;Lb>0f2varWgm+;65XTbl=+QS6{OJ<|g>Kprm~vQ9XnWL$nQw z_knsH^?JR|cIT?(XoPYVB`N=E8$3DfYcpp#iEPd)N)iGcSa=;Ua@s$!5)?Yr4jjE- zl2JPVkr;?HkW708tLAhp2IiN>5cY30Exs8I)u44@dOuXg0S`zNIWK=kUtmH_aVUb@ zmbYD5FqpbJu^&=yvTip57T>59nZ>qP6Wp-x-s20i$N#m`PEYO*m?*ziy@e=dy1RSh zMI}Jis3Y>g^`QW#o1I5HErS2R!MUNYMl~=ODL}!|f5+%YsF6-O=Dyz%yf{CnoT8nR zYWmMq37~&^r)1Obq_lrzv9?;c`iYl2bJCk2u&4J!Gjg@!@s`h0s6NRA$PIw&vhRjP z@0U@gXJ zPsrkDrF@uk`XS5ZZ*V8C!9smPGl7`YkVWJL!d8Uwty4o1k+h@^T@75%MMLlh%uK^* z0qa}m7+vt`lig=KpNiB5lVLt9MEu}Af6rFK_v}3%Jvaw1y<8oyh;e2;m$U6Yx1KS; zS_-%az(2|ef?0nbE^sj~O>Pj>ieWiQ`pM>IY3*388+7$mDKk~zxZY3h-><9;T$T>d z4X)m`4U-4d3kHd2b5o$5YzKBfxTAHu(ZA5YZGb2p1ga+ScHvPl_yt0=f&VtDIb|cA zy2?axb+k9W$ocbf0^nt(V(>cKyXm$(q}{ih+exCNyF2OT zW>Ld3w>fLr8<@U+CW?&+bL{@PS$Y1klU9e;+lH zt89a>R{4Kw1^Q~xvl&*m0w4+S#D|_+Y-UjFrbx(QGXt)`oZIi&gL9%@rj%4RcS7z( zQFL!}VKYZj^x&M_d;cC@B%AnNA1|+e(Z|aZ$HDi>?xR}~IxlLfSzqh2Jls3jPa{zM zMC8TM^LGdPhbL+DLTLsga`a~Z?cT|&qr=k|`!9cA9lnB}X>>G)TUJrB7a$TTq;&ts zy|=ISzInax<fZPSWV*tju-N@yXj)hu@}=WbstuH%CXW_xBFdNHH8L`S9KA*J*UP zn9Wqe{^7fWGyMeBlkNau# zqTm$46(a%z|KjxI=QnEjCm3)9Yg4IErA&W3JUToDLUs0%0m1U!@$>KY5B9vCJRV=r ztK98JJBy%%@Kl20yjk*m@Acl><_E{)e3tWiZq@!~@z@jf+}KV2=tEz*Sr8ra^vAu| z@B9K^vH3!Fx}W=G|Lx1Y=le|xUNJ%WG#}GC5$_Iz9rBI^Is;}!Gb_xJV9qAlWFu@bXy=1A3^J$v$a zSE{Q~CKoh)Z@c-3M4`Wi#iE{X_PT#x$3p%m?i{_S3;4U;%5#ne>NbVX{RL3Bx?9tc!wbPbP>;87H_iF&;Y&x@;>e0m7s(2m~xj8FM9cpB45q24};NVI?Q9X?E; z+dK$l=i;<0(9wdd?yeeR~q6(N__PUOA;q;MtZ!;n68&49|b2lxakw*HFrr z5s40MqbATLN4C@nH1f!lI)PRm*-|IaWk=O4uP)>>(0b$)2Yq&=Yn{MI{P6Aw>V-=K ziQeviEBgzmJ^AkF?V-#FkMA5RpiACaDxeSEIaELgzB9EzOMiAghK|YYGleGRrZBpL zkNWKyv@oZ7@=zc-w^e^p7`yyxt|n7%W(S3q=ClszY%df$w)2C+ z{IHK_Pw|lnnHeY?m-8DtwZ;q1DU;7o^n^+(&Vam00l3ZhJcV+p({}in+O|W#Qm1uL zFBNhur%)C(Er33s@_f9#BWs%I=ZErnte$t(GYsLmQ1i5KNPvG23rhmzE9l3utR{!S zDIAKR*g~E-SS(E3!Vm>dv;4P3DL)1pXF|>Dt9-0F8**J0V=i-@J;KMyq*O&hAF;D) zE;B=`nR=B&?aU796sRk0Tc$9`rD@9)hN85@PhsFnKAFnGa`|*6YsDwKa;DJrrBfA9 zS?Y#PVZO|Bp38r4@oBcGuH+Or1G45|!Y?ZVs(xF@HsCVjri;#?i@2ICxaulYmBADA zLv^8M8H`f3m~YFkp2;UQ^gHrtS3W^))$e-2OrW#HMad;;Q>X$$-B$7~)Uj|n5PD%@ zI}oT_I2{P}>ORP!hZd$sU}$cfl7QeFy(XaZZcNr`w7!1_(udtgPq#k#0NIMt=>Pe@ z{*Q=6+dEIAH2Qb{@&63JcOm`X{hR+9e?#y5-~So@+`;7k4u9|B@BayZKg8evJ^p@# zzyAmP{WwaafBT=}&nKAtzu<4E=`S+(Gfe*9;P*qQ^eN^~$?Z-y|55id%mV%WwM|LCN74!g)QDj9!NvD{kYi%x!C;@Z2Q+)1u59nona zDzE*nU>%*u`OHbJz%VKLZIN?9gLLax4btrkmwKDpY=C+fXoGrlS2JwkwU+4bu`yRA zgHxf|6#1gj5S{EcL#H(xfo}p$!1TKspo^`MFTX|NuPMC@(T?d2(p9QUxk_ph4le?9 zL-K!JWUDf3RO6RO^d!Hj(R@QIK{=#*G?y|((JRWUl4C5=0J)R=CP3{ZzqyN8Sw)Rj z_zp?EC>J=*YaNNnAu`}afDTB$ix5?2jS~D)&eMY7fzTjEy$H@ed=;90_~Op_r%SF+ zK>0P2Rnc(?hqFr-YZ)Y&H$aYjaThtNss?{K>T8I|45xg_#jQIl?*%qiO!W3uOp$Gn z8z=86$~AdrW8}T)j$KiNDpjf8ekh!3z0FXV>b;#%@Tzy$HYm%i?}6~;T^nF8wEguO zn_sP`uFAHaf~>dgT9<(eWumudUDhhRzHF-yvi|$G%K_|6z^(hc)^i*62UgH7XaV`cp5={VeZXl~S9l>-ZJKxR6n? zErng`Q2z~dlA6%)d<NZaBmV`!m1Ju7+7ve|Fb-$}m3(9N|5X^q-zy(=+f4JiS72 zl+$rOzM!Y47?()v2y7Lc~Le#}|uaiy!>va+*;T##Nrn9f=VdFxXOBE+>Bm7c=^R+3Q8Cie&eqf+41bsK? z^FsxmXTD!;qi3xjW76^qK;Fuzu-m%6Zq+oAFI3{@gsArs#*a^2FK7grNlqH$dJ zccMws8($Q&38xU`i<*ZFrcx_{ui6Zvde;Hsr$)9^$a?$79l0zdo*stNLsz$s+?@2r z0Tnxv( z?KY6nrqZ^3vNiJ>UtQTt(QUxVc8@V`q2QYso~BHVIql7JaZzOm#ne95ExkC;q6c|Z zQBggJ!qtow4ghXUHisHZd2Y&myn!5M%)YbGdAhr^3lM*K@a2Eg?Hz>w3%z^v_!&eM z3KzPy`*b@Yi!9idxB?uN(02-DXcm0=WcS(bql8Rb3Y{fn5+?M?4g?3k2vhpx$<}T{ z=E0ZGo;-Q-EFovXmpe}%ZEZOQ4OcBu;3Tsl5K;)X8p1Of4qD{G9MXZXaVDuS))dX7 zt{4<>pc0y-A})U*?lIcsoM%^Y(m%&|JNtkbrA?&!x4pFVS1c71z% zJJ$oNp2U+S{G(1_x>{*qoo?4c?3CqY0Z3sHM)cBMBco(T2YV;azdL<<^zLLIVMtZf z=;#6LZUuVW=RH=6VyXhJS3Pw%ddFuPwKm=&H@zPcIM{!SXl*{ zUDlD7t;O*Hk7<`P0y-wd`U%5fz<5>C(rid-AAtX`tjd0a*e6w z@{Zs##~!lz$A2tPYtK*rk3&)aov^44l?Tp3zeF6@kNEEq{(IsA4;+0m5a{tgRUlCI zw*~?|RzRT8)V*x@fn3K48Ijkp{hamQl>lettc-u>HF%_X@8ASn>0ih5-ql0_0jPM1 z2k`*}8%z?p^j-zxl0J|3d%wIPd&wHN_!rqL?DNC$$+o)-C)=Brv-B__Z^LKl_QRcr z3Hi037p7FaJ!>iWYGn>9lY#S1v{TnQDW3IpzG)CO`OEP#tC_u^nZ;L8D31@ z&A)$XIsc#RJW0sAFk#Q0JW0rRVXgvDL=*BwxYVbQ;LG2`-SiMRhi~29mI!R|7TNFd z?~*teBZbom+I#l|fRAebZy!r8{-*ci_XO{i^*7)3e!&+>+StSmh@vj z7H~xXW;8WtbEjykro%_lw>yYnYfg?S9I> z#UcDY+@FsgZYSi&%uq&t%U;Au|F>SXID=pbXEbi~^=}SK(0bDMsYD$3vD=Ne$oIYC zEdmS3edm|Ja;dlKqW3!he~FUQ^tWb*{iJ$Jw(`%}FIe!OS|;l5!`+1Z5N4?*$|8TI z;kSUynGh-h0I(X)mEf+YZWV;XT%@%3eG<1$HQsw(vI?${a`FTwt&NTbKC;Ngx(3Vw2w=p*BP;QPt))A6Q4MZmCqj%wjfKF-CmJt|0g$ac5@kqjiO3?)tU8y2 zfx{_cV60X$R!alI&9GTZh9k+e1@%_HiDRZ2tgj4rHdyMAy{Y=Ot^9N8kZ*r(j@Ik- zr|>tjwe%l1)`lIfPlqq3`TuY5%T-gIi-k)0do%5{{Ab}9L#w7|43OS%jiFKq`qu>x z#Ir6C&bigWVNK{b7|Ll8C*7|0V3K)3a=a#V7R*16X)-YRz!f6er0c#cXM>JGDq2zg z0ew7S_|;;wsTwxj%P7|loo0V@7Dr~6O9-7{ikp?t3rqu~hJscuS|6ReJ1nBiDxjT> zjI~9_VvW!vfLmF}1ILTaW^g>5;Xd<@T)RyB-cc!!MCB(Afs%*xVk8%b%#aYzDV&}- zRk*Su&uz@hb&eps5P0`|Apd~2rJ~}bxT57kxU7M*r<+&QjoT-uW0+ctc}>lR+p2k~dVy?c{aar}9}b3)5pmK7d?7u~a}Yr+nBfYe zq>sU_RMd4XP2or^tX7BCYZ(OiRL(HUH6^rn`rCposPhbx6`DokSy|DEgN8#-z4qc~ z2mpiyx0E6S8T7-u8JvH)`!JPS;Dj}KzKvYoWCH>7!mh|0*?dyHWsdK>? z9AE~-)wH^=MOy{*CWo_3p(+RklqJnI3IGsNVTxJe;3O!q7vNf9my#lJGa?$4!dG>_ zf_ni#97d`7%9d}2EyrQYleKPlX4^f$xt5xiIj<1C#qVu*jvjyO?tw`b=uk{QTTG{v z*9x|yDxs95d`>6^hnYLv8cL8AZ`8h4RN3O~bQ{)-8xi^;09c8W&emmyTM88DWjm^i z!g8rEJ(*~hf$~iBr>{&>)a!u9zndu~BM8!u2uPUVobszuA+A+vEU^nyg;{`M_X`GS zCR;1)m@W-^Tmyf&G0uMA_JuRne!28ol1-=tRD^i+c$iDKMg3ii>!O{SPN~L`kjs1<`UmwZhf*INrUbC+_*IoK)G zYv>u}nYeAN15?=II@<7=)-~CH3d)N)%z=~=9M#lynkIU{QrG_((DPvhU&ea*TS9S0 zC`*HYyuk(PhB6c<5jQM3f-ydqJhuHw!|a#Y>l_fGWSP4QJqGlD4G`({UMxGpRYyra zMvy{pLco8q$1EYW0s$lndym^LV{5$jV{DtYu4rp%ee%#dcuhDL&(ww#2b5=bw^C%V zMC?{;Vx*cKm*JiQnN(ZdHtBq@C72#?79um-M2u{poF~OhQ2tN9ZxHxBHbDvhaXX3A z$zn|ZUY(?PW7R)|2hbHr0jO8G2dzNLEO*y2`}}{7mCJ9VK)6u2TW{p6mDHY=8DNT; z*;q9?x>CrYWhVZbeunWZy4?*M;6i=i?AFiazAt;flfwmTE^ay%fJd+~-bK||mtb%g z7&xi-^iCraZ3VHIn@|>n8EFTRfWbl{1p}O$?SDSf%5ODp?obrXNGc@Hw(8Nx0A;Ri zbbx=|kZq&Ec`WYe-`oXVjm>3AIK7mlWn3to*)ZSS93|Ls7Q7)LE+c@#7Jm!Z#o~9c znapx=@b}wk{e{vp_YD~Ca76ApT2Nrv*m-j+C{>-D%aaOXjA3_)W8mcE zER1PkmGtRX*%n;40FrPFH-qhjlsL=#3M7BF`m3r^WjM1EPHD;Nb-SQ7D9kmNyUQyO zAtM-y$1wZ;K^-`{VfqZ|WE9Zoz+giFP3ZZoX@L`xJ6sgi0RBmxFy>8eP&m^}$ES@< z+!PR1&mIp^0YtB;VQjNOk=CZO?Zv{Gb8w-ATPuG^ z@vICER;VI;npiv8MuGk{6;D<*>Wrouh#`_Ygd!;!?d!vXNm)l9g+w^* za~Yu!i_>@B`rh2sc8EVpuPP=>XK|$v<3i7hB z#F*%Z1@Qvh7K9Gx=Ns2*rIyE`gtiVku$9)TCjjA!I>@&7Xi(cq-1%L^aWvbP^7$5B z!wJzMc^i~8N=%d!iNc@K3ArdM@s@%SDbD1Sp0Aq$5v3&mC~WUl3&lqF+`)engl9t= z%u&)=NacO#AVAew06`OlbpX<<_D`*6hCSei9{n|rUIHRXCwEc%OI;9&I_7tj_^|$i zr~`i{oqILBe}y?5-2>GB2n^x?GySl%MOB@g(@s8{mDhCAxxS#Rvj966U`7;Trj$VZ zwxIl`*ExbH=lYHJaW6_z)0BUQ50icfa?|ty9I`SrD;$wtK(B`W9TDX97Na`Jg2bB_ zmaJaqU+drCjqtB61eny7tA>JW57m1fnw`vUI@_ig07Xl~L_B;1=*WDyHFCN+AuY>= zCS>VM8nvo0=&gi{4g;>5F-jxs{D@QzlxnIz_2E@bjw;n<*WpuvVEuow1cucz-8C7l zL9px2a0ssJX;EGypX*y%3`cT#39y^GH5{WDx)XDhQQQV>>Ce507;3plQGX5P)x^Az zBKuk^Q;mslE98D?FvWT+nA7?z#1~^L#{nDBbhsGIC=OuAzX^U>VY#5 zT-<5>E6V{bPft0WrlEh(8uW$3C>fN;P$c#;+-*jcspc+t*O zam##T%k*$^O-WAPw@zLUJvWs3S0}SU=?!Ik>11@!dqY`&cCs2E;84bIoQy6!Zz%6O zC$B~K4dwjK$!URsLpi^2a#~E`P|n{qP`|tfZ7wRIFGMhpGfl%8iX zU#*twWXRm@qwjo|+wb0m$!?M*HwkCY`aNbu5Fm;$^ZnZCnD6fDkuT~QVA(r*#>Sz4 z@8kmH^N5zIS>%6CbkA6^t8Tg%b;@Z6M!6H+Gsi!ZK?d#tn0TZPvT890R)|h|=o)1L zjcSi5D5q9m1*S^n2g=9g6-AD=Gb^qNfv1mmu0ML@uJUhPHc7U$H_<4;6&eY_@#mxk z4+T~`6!05E8<-y1i$>#n=e~;bD$lqY6K7EU3NUztz{r2L22>Y_Hz!w1-9`(}Ya|9+ zg}ves!Rs?0C`btX-sjaoF)fv)KV`#6IYS^n5EX1ZTOiV7by>^-zCfA`0zMt!%PMEP zh>QsRzGmj=qWvoUvOup?5GCq5{3oy?l9wzmRSMBptBp92Y+`)d8*Z&c-Qmq|2Z6K{ z81G(HauI)P2OPUxd6@kMUsExJbxW)_NSzE4#SRz!V_YO8N+PYK(S{Pz^M?KiQjmNz zi(*q=DYNTF`cbA?5~NJVG5E;|g@qxe>8SQKSUPEGCe-@1sKm^t2|+ z3Ji}`=&&?kk^7^Wqd$Ur9sMMK3>jI~qmU8$TjGB>y3^lkz5tSw5MY2+7k{9Mk=tev zGU6aB^@BTKt$-hF@X(Hq&^3Wbu^#XEi#3eAeFXlh*u;9jbu=9V0@{4?4p@}%7bONXGHP7d07mimyh2z~p zV3g?mw^`H?`S}1NSf>vjOv-W9lcB3Ck&iE(P}cY58S!9Ta@xBPSF?Y4{@cv6E)P@w z@QJ?C)dU{6EeDvp&~1Oi^k358z1pNC8+S=b?#TcH81Av-kS4{?N{~@7?6`tfy$*j0 z3{r=uqLyoNMHWx3#M*kiG)7uWUBAq>Nwjx$R-7-&Mb#M96#N)PUa-nu422a{Sow=5 zWN-_A_zYx8?t#k7Ap_}#9O#ei{;E1Ww336mOfEiH3qCos`>m-1-K zKhYiq_nLpE8%>DpN83Sn8+Uk})uzYOahuRmyOPni-fk=I(N1uO8*a7BeOhLekd2XZ zKw4I5N?T~Uy`V?C{xo=ss*f!l*;j`l+ro&P4(WaNC2u$$6dAZL^luSL7fOH1CRyLY z&PV*nOw@d}imn#&PN<(<%Q#F+O#I-M^FUU%T8Y&v7FmIcJu8Ciw@JqLb%@5s?3U9O zKmzo#BOOg9>3HUV034FL;$7!n`_SDFo;5;yx_~?2y9R9KheqrxYib5JDScgJL6*`W z9ib4X+oivQD$^9I*-JN5QWJlcKCxsj%{4!@WmF(CAy#>k0)&cwz;|Y-K@gle+6H(g z*qbTs;or42|MPOeIQl7>X3wl~qAX%ScVqQ4S*@fDIgKK(QHV6-=<%RZTIQ(er#}L?{kKLE(RL6+2Iy$mq6} z!i%~i1_CjtPI~3kbx;@XX%^DoK{X=BZ=J7r&5;*_0oa{ST6PxR70-T*07*-2iZ2!7 zXgmaNd5$$DhiEUC86$k{DlmUJNnjqsn8v7$ONhwZt&EN7w4ySjj@2|;Kn08>&=@pi ze6IR030hD%0h)DZ3{-y|agw6dWGq?@uKXP z2QiwU!O|o2Ni3*z_P3=G+AvXb=9*y2)I@+?W8xpd-7cJ)z3YD*yh>rt7jXp89-w}N zDGDr$EV~0iusVYBtAgdo55Y7go$HHYe9^fsW;4k+u(Cs^Q&5)>o+O0#oiPgxP-tYh z(`!K!meA<543zjQO2s7^C>ML$dK`qOsAIiguSGHpEaq@0Y^}h?AO@C)+%f#`^b+@* z-L}E1+*&S&Eeq#4FD9hzbw9trw;MlLhrmuQR7WQ>1^tC>!Rwo1s2;+S+8p%4t< zRVC#{3U>#++Hu%zGte|5z8=`V_h|LSJn0bI_q=2irFp-#?j~P*SI>V==~|}=qi@xg z@Z_jb;nCHU!n4r_!h=yG!h_L1;+TRW3?`6OU#7!Is_jg&9-Ug>ngEdYl^w7VF=0mS z6won7RTqClCL3JTCe|a0;&itci&~GBZb(sYG5B#T-SV3;MH_X5CQ2wgX4{8_4m#PG zyry?+QApcLa#w*~dH(cm#wcwo>l0RPO9azD(9S@N(@*GbNi2Nd41D@YpPR`Yh=%$} z!`&JZ^^>YM%?|`h{gk2BaSSW7B22_k`25x-5D0&!+Oqcr;*r{%pD?!J*s7mZL^I%O zkk;mWxGTSz0Bw<1TfWnjt%(@dBWSxe<6`D2y#LBzo?>BK2}qIEVNgh(4Jo+0+}|dM z#JSLUHF_qQ=^s;gKY@QPGTNV%NY|X4Wt*EN2xGLk`6@f>c7dqM=!vHB8FEGA4DLe{ zeII{Pck=0Q>cmK2WHU0$CcSw%j}vl*-xbLsTPVN~<@K)b?B}2y|B!8w8}H)1NctbX zywL=F&=>FP>}L33)IT3ykFv$^dbD0-=WAWmX|_f7v#tLAmxl6v{o!#|4fjV7@cmN$ z+8*@_0Cu>aoubFK@;SU5#0%|Aa171_r<;G9NxB#wkFv}4y3Dw|?W5fQ5K1b*<(L$r zA_cz0ks&b?6mffNroS7X%d9iMa#%L(;^yowT{ye@xK zlvljxoMd7e3$l>n#xuNjonS5T$LvI1`pJTf$&5_NBuU`TJWiyCJkSD)?2nSHvt&5{ zb3ly0l~bdyo3}QmIA%F~>~`Zyws<%uA4dteAO*HUN=V{(+`|IU^`5^23xH*w19QB5+A_gf_|Xe2)V2 zVybTs=xEpv82%{>A{_QXTu6IRo#+}8H8ccfxC>&IrM?t&IGs`s&U~n!{MxZiac#9b zhFsqO*(v(rR+6NJAya*bMnUKaXNwzuY!qp+mV1o22+MH98BVc{ZSYH)-=1g7wfInp zW^Tf*{Fn+v%*c4JDt@;< z>z%f_3}Eec&Ki~h=d43aW6H5^ciZuQgn2hEIdpVK;-`VZpSARxmK@c6cKY%5Iae?H z;kLHIVxT8$&{80!-ELG&rDn;U*ak{XTRDCfDYq5giBiaPYgF4n=jrXo-RpsZ@ z(~vyWzG#KSu9osNP6}gAwI<>^)S8U;tfNt!^cK7@vfI@vXzedGEwF@tADn{*@wXYc zxQWv?2>2Zr9$oC)eFcmf&dSM+v-*$yx93#6rTK(9XmR4w%@T{#-it#AS23?{*!Y#k z|8uvdkABgW;55H--k$* zb}$vgg|xc8x;yEf-AU1Z3s2e?6AsV-%H4T5s`;2BLxg{F&(cq1d9S)CrXmjdV#49R zWx%iDcdVf_iGqm)2UO#(WT~vAYaJ!Iz6v#WcMx$8w@1>?2^a}i!MA`e04#!A3IHvc zLzB8{Xe7%}sbgPN*1$Y*4|X;Hhn2K28Zli@p}WlXLCWpxIvFy5Ay+&(C1M1M2oH@w zjU*@nuF4M-WP_AZ9!Ha0Q~hvdSKXP>u165^OdiPv_CY-|(OTC*6`@$=foFcuiW zDKuvkW}A<@2M%3-p|z6qGN>=cwSB@Aco+B%mQ(u1mSBU4qFcEXAsOq zya_AUwjb_3PKbD$-4W!+IqiS-AXJ7UB3;Yta=*UV+ys{&*Tr2J?q9t0f+*mlo<(Tr z2>#Rtixwe&9KPB%=F;*~CB7j=w%sqjWc|&}A`uxdQv4i%qUf-&0kst8_j6-3T!p3l z5=`k4z7e>eZ`utsYM!3r=Y%MG4dCgDnZ@KQD%rCc*!{~Sh}`(RoENmxcf$}Q9uibz z?<~>*s*=G0n-tj&*t*wyzd(fE;{J}?|Ap><&kw;NHTQ$Yxm(C<*;^g;sW851 zRGHR`VKD+xueM%iPOqrY2aGt*zAzZYh;X=SC;bvW?RFv37VA|PXu15noZq}G`GFjw zBpDW?tW2al?XG-44aT@iMNNs_{3e9k=DL1v)P@h%NUYG?>JsY#RlLiVix;povGmfm zn0x4d7+tR@pG=@Z;Nal{DhSu1vS4G5)&Thou#sIh*7c^m$g4xJ1S{|oE)V)z_Agw0 z{yQ|)z#^P1zqk3v&hs0Hdsr{h^NItRlU%}mTZ@{D;!W=eY`&e=05j@72iZYu9Y=f6 zCO|L2&|M@qAU5~6`}tSdR{#EeGd+u8J|b0rR#b=iVZ2!;gXJ3BtEyo+$^;QvwPt2x zVcMew>-p(3HqGyy)_7FIxoysUt#29pur2;q3lD!OC}8g=knMrt}q^5-kF!Pn`tqd^`fLNH$tbxI9iD5 z{ihKG8q?|nI1VoG(63zm0n_Rk25Tvnc8*NkM-?wbBa6;UIkGSl0-?0&a*Rw^dTRzh7-}%;3}tHU<8fw*%r*~~tW>uh2=W=d|7{`FV)xBGZ%oN5)_X%-)4!-?J@$#p{X!}X>v zH6bJLc_5SQ2%zrvvr|(pb`|^|B_zJg;^R#G7@wNr_LC$T`V#@v6zFJp*%RgK@|yDJ zc?B0sQzV>BD*DKSUn|70tg(lG#)Y_p(cU_$0^}9bPW^k3`Y1*VKtSMR{FrGP_Y=e% zJIMsN2Yxh=F?j5rBnI?vwKCiDiIlIp8$2Z8y{ytt&fa@65WmMK$sj%e&7=3G+l>!= z@ST&MdY>f3EwYx=`{p2ls5Hikx+Rxugj}%B!QjBLwoawxcpUFRSdyWCIPCrW?I=5u z7HAdOOVAfsZvYTo4`#Hx`uS?5@u|oG$j?;XB9OOOtqPs@BuQa51iQW4b&trCZg=CP zrxM_rrfL9pLyeE*){?JQxk1cQ0>tOZQv4D>httDb9@?sRxJ$OxD&2KaFrc2YrJi!N zDs?>s;9%DtB8m9Xxe+>l9-Y#dF@mMj?w_66u(nYu=Pvu|{$aJv1dN`3Wb;tKs&+)G&IhZcobj ze>|pDHC@co&RaUB#Roc3vG+Q#ues1dDh^=MzoSO0-w9sh-WZvG?I+&l;Mxf%Al~Mj z?)k;z9Qx7TnMQPyPJvSXA5(Q11YL^!rB;!X09%POgIQpWu+>UK@e}=BZ3#+i(Uvs` z4%U|TKkJ*8_){!^J#0!!q-d4*ZMX&2APSoaAjC}m=(H&3{`(Y!)|ZY z{OR_9n4+g->Wy}P=nTJMC#>r^JUG_cJO|6-zjnR~Ghc~+0|A3|@ssW~d5ZW+YMX~d zMT4BVMvj4joUV!rfv-RoBAtpXnpWV>)9T6S`KhdvhF48=4^%+}(3&N8{X@kOgg%6s-c!W{3T&V>q0bw(-cOc5|k29}o|l|FcIeSO_y^Q&Jg^a)gX9*lWe zRre*~sw5@~h@J#&v!a0@O)@wZ1kVzsjF9!65cAgsyX?4ehB_}X{BsVgA$`x@GsS01 z+Q93hbI+-N^X{^58s`&bHQWJK#Y31;oxq&s}SOi5}Vt9{Wy~1m+?Gq`CJHw=ZO? z9*PWS{a`h47lavp8b@(Nu!?|nHHkm>8;yT>E+EyL*dSvAg=y|*&YYM1yqT}9d&F&9 zn&UTdTQ=9BB5YjX<4E<+X65)2OiILd@AWSUavRk1e-?u%N+aCaYbF*fS^F*$@y=`1wn9)@V)?`;Tw6_$wY6>@oqM=?v(UXZl9!`w0grZzncK>s@I zHxr`2Mjw0?X^5oIo@r?fIa{>!klDSgi-9~@ZP~D6$!X|OB%NRc?xMz#u#)>ZY&_kL zI%l})&%)AJ_u9FOJl}K=8GyF)K4yTkJgA+3%s&BBJHMGTs}ng^Jis9&VHcr)y9oa* zUIiE>#jjw$N_NFkVY;u)z36W~%I1T=eyBr^OLx&(JI6(1y)GEK{0R5pmi`zThhPA` zx2cF)br7uC&=hcn`b?7Kj_%O}kla2=;!(^KuhLJMK5n6(vfkT0tUj|%!SSCj#BGfV z`DK0HV&-&Ca}0TklhAl<=`+cH+Jt@`ZT`{a9rHodu{A~jm9ZItgFDWZLd}(R((o4h zW9JJ>ttXw^kC~vy+3n|oDfd&4hoG<8-*(SXH2skSqRk`j??UJw-s3{fcYkbqQ2p}9e@oB{)S7h-t zj+SI<}*n}OmR&5P0Hz zc7Gf77gnds+$J&VWR(Pep~py7UeQ=Qkpev?2xEkC!isE(U~EgJ&Hn*Gnl`qGdfvA> z$Bk|9bHm7~-=R4H=&Zm(lPK$gbeWIGbS~29A0GUJMo!X-@uOqmf*a9Co#uE4mCktuBWdp z(1KUCCm~DSC2hHlMFz3P8EXtB!|8;APd2c}!*-|=&5rScbB286Tocf)y z%07_1*Bn^o+gWCHg#(abHPK|@NP8*(Ta}1hWR@*`IIxmfP_czktmeJOL<2)+r-lq# z+H4g5@*pRvkkbt6gh4zIjol3%HwS-TVbaAQaxt+p2NRot+VI`mSI^6jUd{~)oAv5!>=@7SWE6EnRG zO2kH%jl113nX0qr^dx~e*wKO)fP4W&MkGQKZHR$=7f-QCOhlqODfZhMA<-!58x%M3 z147|{O=Uk$YOIXIx|AW#rLz3TRCe!?d?d~(n@-&`*Kj&heRi&0bT^R)Of-s2T%)}N z4v_0$NGjksifLT-q)vG6I_H$pN-e~3)_6gt*;w8jF0yg&1Le@Z{uESS!$|6z)x1#v zy7wh?QZ`M<#Vxs1Nzo{~kQ02~##>YgDJ}DVa;EycM0UgUXW8DLWw1ZzYjTw#HBJsK|%x3Jrarw?5bnu-o03$-cTV?&9wG=41uKq*<)FlVw0pEiG;U0->py z1%93>{OOyZcR5&R-Jt7ux9isH+Y7n`k(=P*D+}*9IWhPIZq^&;>HySeCu|WX}S{dn2bes3dZ63vut0E?lHN{J|B47!|Qd}!ZrB_rlbHYtk1r-qKN^A_oUkm07ga!I`4hA5mjeWx&d=KUrX{6@^Nsm z=@?V1mDhJaKAzKYw%ywzjXP3`rlgyh>pW9Gjl>r<9hNcmK|V_1?Y(^ z%XHVs*>jY!aa@oO3E9hzdh(Pcud^e^Z5n#~wF$j4i(e=GBHNRAEWjO{FKsU5Gz!VC8DyAM^|@8g1;*Db}QDWu(Am)aaF73!dca2KvYUce}x zYl#F88O7J+7)7`H;9r@U^IlG!2SrZ+o@S8@#P{gun2JAxZ5#PSqdL!c6Z|*wGYn;- zB8jq#R-|2r!w~35s5uPgLGQAE324-n<9!W=m+2ih6DIyh6Ny*k31Rb0+ zHH=RALL2X`{l_IVPzCMQo%%sLebMYIk)iL>^NV6OIpGERTM>4x?Ld{m;XoRlrt(kb zkruNXRbG;;=agOsNQ7iVp!?vG2T~Ip4u$=${SUic_9e$Kz?i$pyq@ZI**^OF0g;fH zqJL@0&iewEM1d;@Gw3CMkJA_$vaYq=EEk1hlPmZVHImp!|PK6m}U>QUy#*P2B8^Dv&FD zZQvu6rTWH}>Yt5mr~Kofd)PqwcU>lb)I%<%^8Rw!;-jgS1$y*Z!jW`oeASK3+Ij61&w&xs{q@OHRb)d;6jy2msDN8nyN5^ z%(2_|1WAoi?W@Uu$dwyfZLfsc*yt2BEv0}#8Xwycz;QvOaXrr7j#uc8*~q1{xW-(U z6@bU3dXW_-9ES->rf?981cZ8+OS*5sf=TgLeILK80cC5?0F+t@fP->pKo_L%6>7hN zdt3B?agwLx*a8|ZRPH8&&XT42RH*riJ6*EYkU`;2t8h$zH}am`BjnJ}GW}eW*OlPm z?)B&_A?-AwAZrG3>Z;**6Qz$W-99r*OV_+^na8%b0+ZQ~fIwJFqa|L!1_sEhK#1Z5 z-s5%9Ad&QAnKP^H7q}>RqBs@z1*}F+)K^PMaw-T6DMSP}94BT_SlaAkTPQ>3?*9V|U-5z3X;V1zoU`Ph=CEI9z1?7!fU^&vl_=;U0A#6MM2HNswy{md*%El}kd0ax z<-^t6#IQ(Q+3d`R{vWuXZEjYIa}D5efG<&hoQ>sw1%RP5Ro$)R{{4y|GlHBFhb?;n zD4DuZ5J12K9sxH9_=pCX^t{{6ZBc6vZQnK$2Ha*^O9`cf6#?E3R75Bh1vipBA(|G~ z4s!wg=|fzqOzEY#OQ4Kvs!Yg;SZqU`rw_bJ(G7Ml`+G0CUG^$}t_3ugVP!25Zm4dcXh#Nvc!c5GUdI^L zOgUq_Azav@Gwf1KMwkmJ*fIn_$v{XD1$+SaBe>l{6e5XVg^%8?)mabnuy&vlEtU4`le(A3 zB;*fNugvT}+iS02-JDfG$ZY@r(ADeOz zbH5MN{G329nyyrEcw1}NlVMqJBaRAQj+(P?Em`rY4UH$2JYjDGp0lceN`A~iOdi*h zEHtmH&d_UX0%v1=utT;D^O%EwHoaDOFl(IxoIEP#I)M9}X_EREel*YExpvo{GML9K z)*j;C@FaIPj3&!7g*$}qx=`6h`@Xwcp>^46)iM!QtFypLNyu5SX6Vw-r&3*BuL9Fy zVX0E5lyIl`2`%$C4$2P}#~SHSr5}<8VQZHykH~)yjQp?Tt%%6X=St za`Y{14j4C>b-uO~Iq=r>0|l9Cxj4T7|NKcwCAa{_(aSrR^rqK;fna=B`Az3K2biF; zv#6wp|0TVFfUWrz6_mq^YEH++^ak-HOO6?O7y;D1y8Z0ln%>4k_Hslp{;hkp`lco; zsog4I$Tl{F6zS*@_MciWHtd}$+q=uX`-BRM3c1A?)N~sg!kfskXv}2ff8mbR?aKDl zqusmpyU2DXDlZ0q2ezvC0Zrvz5!`*7d;guQ!<3w=I&u2DWPQodexzq`y!$v&vXUKdAb#>ePKTp@_&%;XWhh47E;smp(Fx&qWshr9@B60aSe+Tt zdQ&7kCS-($REskOu5Rg6=+{W7Y&EWEL$rS1 zq}sem)eO)@Wd6mYE(9^Cz{*Zg=aBjGFyzU%`${B$(7& z#Ie#~=kAmr=WI-8-m3IRSd9hPT-(0z#P4R^1mx}OgoMH^pjFFIsWC({N(lQg7GQ{Q z%gBj;oTF&br9)zIrTVQ%TCH7NofzZ|Tl7i|Bd$`VY?Q5+%2>byiZwcIpf3Qc$EjyR zXT=A~U+0xLkO400Dr;$mf}`y!nC-N{msRM*(6`m7O*FMhfPI5kx^0yloS1Hn za^(c0gL=u~BY z#=!n;jGLrY%}^?;rCq}at!rWd(01C!N1Ftg%~TmtXud$}r}`F1PFnvYq5h}PF$@3~ z6=AR&_dQBvgFly)x+_qd)k1?#?xUR2Bs^(`Op=U9?8p}O74Sl8RQ!^e3d4du+I_OU zlMuG$%MS?K(FwlM9bvn7GG)pa<{)Q(`8nl)za-dJdX;qC`EHa zUQJ2m8PL0irX#VW$}D(x31H%7;udKlmu6X34We;AzM%J~1+PSug6E1?zj0Rq=b*tN z1%H*IhZom;_R`5WvH7Nh2;c;NCuevOo(&f1ES*BXsorV#`&>2)PA9}6C!MVm)2ow= z>t7&PJBQ6V7t*uw)kN8tTx4`7&b8gUvDv|A@D$4~y4?#U#=LN2m*rtLCVahfHf^Ha z*Ouor81)5C6?Y;?ap|<=SMr!s-K0qFO%%Z2nt;zd<*29v6A}drDWA80)}KV01{qD+r<^tz(xQ4}N2cZB_JYn&fPKlXKXX(2BX+g{YW+U`t+_g9y6ts`nyM zZ^&}(WRsl)&R)8XL9ASpICzLa$<9lVNO{8m*Hjo%HC`a%cl%lbeygOC&2ZCIWcuZ} z6GNAlLCBNT(1A8nN*aym-r-(Rx!+Qp4xp7##lcT#H2lRCvs$r7aoJNCzSbUD-5TUj zIg_3z7)i)8SB61dR-XN~QhPsbFfTQ=l(TUln!(Md;j zb!^1>jR>ZHBuX6UZY$f5E#A7clk)J^wfC4X=57u962RoTz9_~QR`WHX<5|u@`Spcq znu-0|d(U1J6F{);TtW0#QFfq*O%v>DL_BPoPar_Ae!J}064%K9gnM=`tL-BV_KBco z)>;2qIA7~=9n1{|I!fAO4>hwyf8qrQVRTe5eMw?}L>&VX``ceQn08Qd+TwRXSQ~|k zsT$Dqc6^uCW+h~aC8V}J7&MDG_JyC@JI(`Gw=CU@gk6(x!Oxm|P2)PDSs{DxhGpj+ zvHc=+UI7YO(mI$>ndG;)*vv(C01|B5r9_So$?%_5FXa)wV zGGyzMv>xgflzHJZkdi=Y$)HBNx0!n-1%y-16kW>=(rs#hIKN+<&wTeI;^-JcG=hJ)3{M=Id7DDTcKN@P$>GtfELJ^F||7$S}-y{ ziTBt$+?=@NK=tPJPa`|lnkgt0}fa^G&pcx=6 zTp1e^%2cjKOS-E>`SFGAOOUD)<+LSm-X(+**Ppph72GOkoZPM1x85}&LxR4uz!Ep7cV1PCEBfjRaE#7o zigm6AG)4Widw8r-I$CpiT&?QTBIPY>p6db~HNtz9TEVSCxPDXYq`lbmC5CIUrD$Ah zoHQ8Cy7b!~&w0C8yo8>AW!t^dmj)0DFiGG_&j)47w)~f6(%<0P(4lr*5wsj}p}Gtw z=5pL%p>0l%jV$x1>UO=yOoq6YPz8bWFAi+@09aO=TuoL=3nc0?dR=q<`dmFs{Wdtje1ls>z0*XR@L{qv!*^Hon0hk z>KSiBLd!zCpU%c_Vi})#&%K{lh=v0WwZ zwCWYG1d!K3)(xtEl^vg;7z(R2pg1rR^lvquHEFX|bveCl)NR|guRsKmmzCaLwq4+r?Vir7yky)}GZbn_vTD3@O_5(B2*Jt1Z6-&qSj! z!|V~D*^##O6@SJ8bI&caUpQ&CrRZE(v?$iU*xzPv-mqnV4SbJ0MjYaIp=!$!Tb*~U zW4!|0V{^-zuvrVUhkjf@d3H7LKn=!U$KeQSQ`lzqTf<0jl9$^xaiM;ydg=KxnE==A*NS4EqVANAsgF(imB<< zRM{pNV3zvVYmjfrOcoOZ@j4wWNE`+82`CbB=m~H)ll_q91dC0JH3I${QK#f6IJm8U zDox&!S6RMZL*Vpc+&L@Q#6o!TDu75O!9{uH7R&)!mWKHiw<5MSHL+4-`Z`|eyh_YY zB?|-2zK?bCW}Vm%Zceu@4j$Ofx|nLibAvdhEy+c)T+0bQ$)c~X`OO2ZF+7$t_afud z80NVQkbVMU-POuVOIE88@-3fd{DSa*vy9J&d@@?CaPN~p>jv>*n^`_5d}91HYqqbT zMQOEzwVh!+1!6wKs~8M(%CCqSgp{AJGk)fD*N0f!*WY}`@wELQa6WxV^tSa;A5D{@ znwJ&Lgnl#k0Yn+S246!QV0lZJO>{!&FuTaxm5f*UJO~?lPTMd&;niU|p)Ov3DCmEc z8*;4>$k|p9)NSEEp^%L%b6RLMH_$+??km@ngTguHGBpEhSd=y4tBhk95`5znrPEX< zc$U9xC#qf*L}(W=*{%BCsXCck-AD~TlHM-dsP!2eFxh39NMn{QFX>H66(pM=NSxft zknYqWaqZG;eXih1H!ATbiZ@GtoZqVzGgHiU5mGQ4Ui0Ao$?6PI-|Ht^6bJ$ItnMe; z1r9Xh&IjP!Q>#Q~`h@wSp<3i3@@9?SBYN^AcMPlQxYeNnG~f2#9VUAyu_$PAG7VPEvJ$b8?lNeh)vm1mL02A1W>^o z^G)+&w&2u_|HcpepyN9FnObLnY{g*g4gMS*visX3NWvdZNkfygQ>^&yc?o+*pnUfy5&p}if^1UeKbgh#`-Zy zaToCG$R$<&xiKlYxIu27Q|9b^n2sp%QsN876YAF0IopKaA|n$PW~$*+6%zJsieW#rWgR_Ja-xU1JVk^8CgpdOBJ!qQ~G zf5wqa`8OJ<-BR(&x4;7g9Kx@A?mddXAVW$76!$yk?soZq8_ahU8^kSJ;tN?K_4kP_ zLTghSZzI&KU5Mw!^koEh9>-NxXWJfSY+Wnai4=g%wVS3|Wg8nY^|vkPGR-OI zjhv@yX>OAZEV|p}zj}_^{4G}a5_;)pH~m+e{*9ad(m#px;G)|tBHU{!63_U4Y%+k! z@>ak2lJz%#H;Y8Xd{~S;DKP(8jpIp78#6?Jq~j!p-7C>P;Ict|w3hU`LRnDy-J?oT zCMoE{Rm;*`vi*7?Y6i1z7rV_N{+qjr-|(pSvne6amV^P3k&tO)MF_(8G;0N(QU`G7 zHBJfC+xp%~U0>U%zw<}YYi3{GH8eMy5J{GTKj4>tioh@V$8J~eALtI*JbYb9BwU%x zTB}f%hF}y8X7(a%Wo`-A35FW$`*wpsr z+&PVTws7v%hAdc_rwU;GTf&k7OC#M;QJ?R(#YQzeZ83_KDA`O8ek{S-xib;Iw^&7R zqsc?_K?{Q0LESxhce0x9lJ6v!ZQVIBe6N~X{CM#M!mX!wE#I;pooQe3KX)qwGemVWCh84sz^R)mgFy= zwnEc__)%bTb+i7n5wiTr)kisd#}5wM{-;_TEwNhhKWT78#M8G>`V%@&`A>3xboRn+ zoFGsrSVvX2-$rErVOL0yVq4DE=aiERk&iEeb#6)nL41ymXTvwH?(y!RNczdytk z)(=r<9i^jhL9o4{=vY8gEx&N?#O;cfIduT{PkpD)IQG^)e8r=aAH8jlj0T#}+2tp&m zo|Fm+xqQ>1I3CzZ>8 z1p8kir)W`WUHu>|Jr!;#zsAlZ3Rlv4MZd;=3JD06!qnGF(x!x7cLlV6IDx|IW};5B zYa+G5>G zQlRNSO*1mg{ilnh6&O_vhC9S<`U}+xxJpT7XPIo_Oq0yUDdrp~Rk2!G&f1=ZC(ur8afbh-eDR;-YSN5o(bnz;lX z1{edyZylI2ww8%N$hF{woWhk<>0#USLb$2)??ht8Y^fl6!~LG#1Y=tD3Jlhb#(3-c z2<4N>K0>8C5!$mlhJ4t=1DpzKkk?D;b@4Zt-rNZ*);7JBdiiXBQOqW9%Tk`3U{kGF z1p=VkdSCIo9=LPyxpQB@4WHI~OV9sW*3fFWfM`3oN!+##Z5ZfkiQMf33<<_+XhG11 zv(qp+9{ z3PRqKRAfQMWJacBLN3UhoRO>k?Q84Yw4;=8@ubQy@E8PMdJPQcSZzcQj(#kTo9s|r zk_9-g#Ivk);=T`Nz41lP_e8t}R$lMsbIPCRAYj;>DW%|lc9KRvNT9ljbWgmp`!l;f|X85V~MBW$J6YD zbWFkrf10n!70BUhJC_@;BQAYt|0^QMS?i9ZJ>qD9xU=S-v|fkyp8yqEGbq#NF)4U` zAURR<@c-?9?c4j?wvl$filnngCEp;5o!++8%j%@LbkinH8oO7mj+de!3pGtDAZf?7 z^xe;I26qsYo!!3Yk2V$wf*>w~!OSzy*s#vN=~tN3Z_2G*dyCmCm68SdD~*y>r$CC@ zrhT#+8k!$&WlQq=HVl09Jah_B?6Bi;vx+FG;u&UtKk;`ck@7+HXgA9}TIr@*Hw1EV zVOfuaFqzX|BN{JKk?&Z0V5FO~Z&{wL=4 z{4r5~1PTcDwKI7@LgY5~t26t_iwHOF-bI2#_*btEC8h7PO14IioJGu844JbxlPbmO zLh3XdrfEg;)Tfnb({f%dcDr((En*T4dC!4GhMI-+6fx_gA}uE-&kwTh1!O3R*4`1+ z*Qe*j0;*f3>v=uPk_vxy8_s{VT)RdGAS*I|F9`*^I0OHKk{P!cjgnAeZyk<^*^@;K zv7+dn;XCI%kXhD|mqJ$vos~W40<5tR)NSU;;JWqk=`eyARAAm28n> z7Lk|?-OPBqop7mn3CnTfrZVY5l%Q53*>1;}(AwgSxgG9`){SAjH*gk}Rzspp~ z$dD&#F?<#c?>6iT&ILubD@@a0-3vtD$U}LD@Xz5^Tq$g1(aAj_z+39TYVeN*#!A0$ zY2CbBrN@ErUAGE|*xf?H(qjidd2EO5YMz@^XND~;Yn3v#Px%+PHcNDOej$@JAH{@! z9+hN7uUHQGgvGDRYQ@$!`X@4fNZS0CHW_cpnxMrt#6c}%$elnni=IKEsjcURKGX5A zmvYP^1?XX-AVHE0k5E9t2Vtmy4nUJNyO|$x+TN-mzMK3`e${iq84eS|3A-28d*{+_ z2kCvBX#8exh|Tq|8>fZOd(N)rvC(*zw8kX}G;9k6y~qBHq65&T2Zlg_qdOU-FFM^>e&e z8b@d>L(GCWW>eoD7aU)Ihv7A}g6_5&9+5mNtCIbxD2EcmA{-j29!_C3R9{uR1tSCydzVZOl5}o4dSlD$dfO9 z9#5)bt2%;8#=*Q-d6QHJ=`>1C=#DNHhqpUQ=**@96Jy}jr~u-BR&@^K+)(}_NZ^g0 zS*MVZAj?IjPD8<)AmPP6juVID!?e}yH9y6boA<(znc{5!gB*fR*W3wLI3#)Py1hV& zp*{14-b)e9tb&h0#%T(+?pEz)12gN*`eOgy9Te+GJ~2em5ugcy8@g=N@{6!TRSIa~Pn~MS8i^{F-BB^+I8@kzY|<${31ZHLsZ?@wj=s&zzK zGGAzoPA$L@D|1dkDaeWuLt=faD(j{+IMiwLZDh}*C^q>$rsCt$darWFj5b*fC@onv zIuYQvbW5avZcXa>Y;sBYIgMIfwdkgOSBFn4;;Dpdo1ZnH3TStd7zm>#9)%Z(J&th# zHahfjehC&8%6xr5tkYSX*4=;qjO~3$ZTiHCc!@m`LnNKUF%Zt|-SR6Nt{^ zkV?o}3dWJvLzyn7b|NP>le2oSGXXJ6@nWvlrL)$5U@Q&{qF+F~Tydoe>>xYT*m`Vctw@zaS! z4`&1F)_yokOrRc*z0+>IyUBV4bV^Hf*O6BUtvuEznMiEwGuY z5KAJz2FXaV~GVzGw#GMO7EUd z8>T^^0gI+%vqKp|xw5@+W#sU#L#v_hIyYGPqG0En2ADw2dB|&)!k$WPy1Y=t2<~_R zlXr-%#I)BLM*u;GdQaIFb^oVp5j)2}ixd=1Qw54)PFo4-3=UE{9Il8wHJNFWRBW1^j?)Y&+ z|A+*_MKU4|q|}C_K?POJ)>#dtMQa@9QJm;Uk3Z}9Tmr8Qz$l#weBXnd_msq~dxE(Y z!`)44h0;L{QwSET&$;hty{*a`oz+%a1BTEJf1Nl>U2+nI&KHRg5E+o~zH>_!Mv&y= zu@DiWdK3?p;OLYYPsk>v4q@chyk|3uJd2K(=T!7Uk6p(;e)y!4$%a7Uc}q(om*%}o z^WO5F?=97PUDXTEMkO63OLCsl$pxibK-VFVp(a-bzdZeT41-X-Ym$@A9k7L^=9^ef ze~N5L3r#n{)=`KBUQM5YILZxJJ&+lVSCheSkTa{Tn?b#$Ia}XA5-qM%o+wiuETm>b z2VPY^Mf~S+7b(-Bpxk;Clv^@-Evu~ub-M)z`v3|LKCvJDWKi+JC+fjZ2G)ca2r|ri zGC1APfgIhzzwD>~HCWP3cEu__$l9j5e+14fAafd^9$T9a6Z%>Wg!%BnLeCz&%>*&$ zztsExHK;Gxwl-x%MNWs@Tom)2{=B-Z4y$s9}S6jM$=#jQlZ zjBDbUp!I_2-T|jQ_Ha+c@SkfT5)PTt=;>g>iA}S*mab-kuu6BiPniYvz0^Cf00$qh$ zcpYtE^o-*2LXw(Cob*^_u3~cAf88x01qfjTFtJ|Fr1DJ!#12B@rD=L8DR$5n@WUj3 z65YCzfpixKJ$c7OheQ2q>Ie3+^nWzrJFfVn73y*wkHb$ghN$NbBP z6G!!k1wZ9a5s$%$fXGT^e-e>7gyDZLSIOwzn>VLtuYWpy0$ji&a=-LzAVHvV%Yw!O z7PKmDB#xi;y~*2G%!}hmR{!Ybu(B0T2kam8>|rtt(cM#(OL;tw(5$C^6CNvUzBr_+ ztjaa1C#!UAn!iccRyS|;5Q^_yS)aGLR~QCardwqZW9w*ZS*VtxX_sjc zEzM3S6D4w@KPp*`$Mn-^rPX6`%V6U-`*?Z@hB{}+F5Myf@u%nSepBP+dAO~F`9HQir>$+R^vv^7uWN^^*u+-HCYmkS5kt;i z!>uyPG{3LM;|e%<$ZaQ~WZyd8XUH+`?1j7C5Kz?<0d)#?f2L&65AF*Sya_WM={cS~ zfA#$Ixl%_A4qGNJNH~V~u`(~(6-_$FYQO8f9lkqJ{hhu$xrH`+Xh!B14`c8Q-(53t z041CELixEtB6i^82exDLmAzXs;c1BaXC^2wbrMH9?FOjJp4 zb+Qc~FxAb=MS2^~%j*H!T+e}vl4~6My^oi39Rk?b0UxZNLcW`#Q|+mOt|f9`svQ=d zJ7T`@#!1WDzE`=HYLOz)!Ah6G!?%g3MVk8GtW&skf2_7bsG&fXYGjQmV}(Qm*FlvU z@M1}PQ$W%HT?SnCyzbSR8)WfIvZ z<;42s0`*NygN}W9rppSITm)u}aJxh#i3ydQ9SH2!g%bHFq<|5J3wM&iDM^j5Bmu&x zwEeWke}Ew9q8fO&YG91fDuRS-`%5((|9w|Xw5O)W6RY22Ol)bt29XT`T$g75rRjl= z@p8jD79#1B@{_M0PJFI$-NE}1j5{^tGW;tEq!J7><)>2hm1cec9ML#2$Z;w$k8~fF zYY2|kSwN936Q)mOtr_`Io^tP`$#v3%lhW<)fA<}s?wmOfq;3qL(mU2u)#qZG{sk6X zyB^0{sor$_WypxD7h7 z542%OyP4Sl((YYSeS{WdX-=lAK~)aS%5XkBSnu&y;TG7*T*=7(_3ymbsqOKR?J<)1 zf4v9|=7=|xXeJd{$28*2uK=V#<_HP+RUbU)sm!3ud&yy3PwayS;fjo%`;LZnT)3UK z=}vfAdU_DGfPr=i+w(|!O|pmIV%2efy+pwOq5xAq?>0RQy}n(sI?wn@k~Ily%g1<5 z@kIkvtNIUfjT2%`WJA35AsdMf6CZ)r#?Qm!)aJg&}PScGNU21i8AI>)lV_G zr;8xyz9!Crp$_lLE*zTC`kv6rQHFtUBbyTvpaWe0#Z25>DAp2GiZDmiNJvlnNTed~ zhR1P21&gy_vGsHVWlMr`u)V*T)UkZidx73&CK~OoLjY6pe@(~wg$73XGEjpBf8I>t zY9Im*n+Kd8HW~}iR*uEYPCu80(53*^5gjdhewaB4CUx?kX=In%?I5`nYHknvchIBAyXAv~Bk&M?&Mx(eV9b$vg#N=^IMgzGQ z3GwBcY6d20INEXs87xVNjq7N5oT4oKcg2KKaZ4+&hElFObw+fCODNI8f2G@(+$>8T zMBa0QTb4+mC?=7e>QRJ%d+>b7b6W~q5?6*T43#t!n8g~IE!gb)-I-1R_Q%DbsNPZ0 zZz{oQFgC8UOJ}^1%I}E<;_najQA?0}&=uxEN-_t0Q(0_vwE>${fTOFXrSG&aEy?uocCVa)@RD_teQx-<&*s z_wuc{t_g+TfSjliG5*7(sAC`(1{?TpS1bGX?S3kJ$`yuDyQY~;AE@EOlh^;=1XZv`sodC{&_{I_)e?xvButP~QQcH_z zYdDG_#o%ewoog7_t2Cz z;!;QPbye0^7DhCDe+)D8_kg~u1W8}~2hx+cdz#>0QCLUokmh`}4 z6+?K}-ep-G(Z_0sbr9f9>H+hD+f`t!*Qu0swQbfR+6;)EPWowNxK=dKBSdX@z;&<& z3o7ah$&iERS!Bgr>&-&;?JCXjSXj&a7{Do=OFeWYx?+=-e;Rg=AI-~cRFHMNh^H&8U_-KW8Z2x^c9_Q+Ettpcw z?}zga{{}ssRO?81N^XG^4brBC`m7NjwG51}Wn)${a*0%ZLeQEckFqdtXLP-MbKD@6dQWYe??7#s*tX>H{K;C?VfaV7Yk+P z^+}95iw^;oq+-+UPB@2KeFcY&URR+R;JclMPvJ0BH@~oE1E)geG|a{2z#F^=!ZREw zIlT=)uy)zT8m01i(^zf=E?Bjr_*TUB^b!-Rr*>z>l<9%CjZu{psRIuuYom@AGr+8S z)&z0te_1nLH>0Egj!Z|--p+7(>vZB{|T>38T5?TF4fM1QqSyBDpb?>Je|b(#1_5A8>`)MNE(sbU*z8`I>Y`D$ zZYY0wt2c1AR6F z)Tar_;C>s}%fEu%PTmO74RBO0 zTKHhO-ncgQ$g~+P#P}P*F*Ib)j*SYT%xpX^q+t>=VeRE9r3D#|m$fGtI+mM`EeUey zGy;rBa%soRdxl4DjWF)-(JZ7Y!r6rEFyga7bFWlHJ2MO?Qxi2?rB-D6o~LcZe@F#( z)fOnf!F~fYUn%Q+ELR`P0F_rxSh=Df-mJrB=&#cw<$DT8-qp@b=^(l5m=t|lijwd> zIx;R$u!0Mj1g-?ziso+JHSVc+1p|%c<<{Gx^WfH7SX<}%j%|146Prz`Z<_anGmAqo zS8f-IG2&L#Pe^U}h1A(gH|!KHb-6$69b$ylrA=v{I8vfsQFw)O6UwT$6c1_21+*Jq$sB#4%W51g;#vFqG3e_cMSCFgCN zfd6SvmTq7{H9JbWwT+OR0u-crcAPvWmmy-tz)>}#WNG7gGOJH)rLc08!WK>;=jj^G zdF|zra^rPbjmN8@n3iS+Ol1gS72it5Jb}_68DdfYNnp4_o?29IPn^C|M#d9!NI;*?Dt{(Yfzv8b}wWB?m)ySvCwCP z`gn#An(t7a84s`Faza_M&9jhc4vGWjMUOKe2@whG6*ny7>Dk#ee_d{~{NhXk#?H>7 zn{McLQOu@9FHkEoUOZ6Q`IeCo2TY#fD}p z$m5i0UX02jv8au*4xu)vYS%S?p>3?sXpwd2?DlqgSU@Rn)Fs zU{v8j+K9PpR<5e+fAM%I{+OJdJ$d`))vGsWPhY)!{=+G_tmP()HiIBRhiy98?Z8CP zq4rqzQfla!^G5JH!IkmbnpZ) zZPh>=UkP9lU2tMH_(TS9ZzX4nLMBR2_CO5GWbjYeuLqZaRbnNm3!;w)+k!$6@fE9C zlMFUZv#paykIt(}hOeHi=+&eA(W=U88>RG>MKcNp-RCyLN2WOUY8VfxFDf30dbi8J zKI$d&*aR6tf3^o0LDVRwS0o>g@1SxFw+VOwb6K4Q`1O8ImaJUa)P(O%srSJGl8D0k zyHmsnfzg&OrO)Kok>WNbWMTZoegB;FAjwWUa}x*84rI%Sng z&D0lw@gz;t{O8j*Z(g08ef#RoH&0%jfBoaloA1xgq_^foJzQp2>^y5K zPA<}u@%UuY)|5XvhsE+iMND>pFBju+bYV_-PdB`}q>o1N*AI_pAJUOp136xwoLAL( z0Rr&y(KTJxFf@-=w8>cUNGy?uV#9d2qF1zlMfk9J^vCMrqP)0R(&aMSvf{j=d7iWL z;$pqLe_WR9%TZ!A;05D!U40NO7>^^X4cTgiIR5HSRutK!;^&WO`S7QcM{D^E7Eleb zS^y&Y(I}3|2OlI2@-e=t#sW>4U?0C)3f5e+{NnFfFVN&Xkh8$7I(45tL|QL|oyK z1Oy7{N}gmx50ao)n8ua^*>9Y6t>#g^?qq-psVdh!K{4_dMbS`!| zhiYb3(Ru*TXuJcda|UAV$#)NyG|$?ae>ztOc_sq`l)GU7mVtswx|zw~tx#&L2Tjib z7Y(O5WmiDJQ#5R=AFKy(OtM&LvQkJ$*>nP=IeAsqY(@E?MGl*602WHhK|b0aKd9S$ zGsx81QTpzgD9X8KNmr23e=c@W zLAiPx;|ZfM)G+{_%2q!H!j!_XNx%i;*n;K5_)NEAm73+>ty?`GsNS%X9?auvvzQtl zN5O5f^srb?2L@29O`rvVFYIfC`Ix`99cO1^Gli}7Ma7lk(}lvhd$6DB_v}m}qTglL z!F;+~b3!8BS)>*J9vbv;hrt~!B`NYPKe7f^4;{*<7TJ}7%6(9N(ac-eW2og z=yw;C7YgC||J6H3_wSv6ndYwEalaG8=R5PjH5Pff!aKtu=?aLWPlk+3!K;%sD;mm! zyo<2b_CASsRXz>JSM@YG)JMT4hiqQKs~_FudxaeIZVbJ%w!5V7;a&IZe|Bh8D8%Z{ z7lebcujz^VkU<52zA#i3(!Xm@Pp(mJ%uvV@CY@Y$$_bD~Hy&QrJuI&1vOSMRFH5CI zc?=!)dKgGd!hq91Fu9x1=g===cQw!} z9{N}hKB}sLtKB((m#H$}S3RbA6CtDC|E$VW{(D591kbh0aJ~p)I9NL2h8ARIX8%Zr z$7$*yYJ|U6TCVKwKSWM%MLa0v4h9MFj^=ZK<|ULDDe%&+UfE&ge+YVydY+M>-FrO3 z(5}9Al~->X=iSLWUwG#eBsK~qdOZG*)cm16irQkEt)c@5E?!j)P$*8=YPWN!y{swH zbaGmL{5j#@X`IDs=Pr%NI7^866EOcVvA*c=Hyk{S;N#%uLa?%;&pJDeBTD8Ywi=NU z+!-xgnhFty3@>w?jzQ+jcTi1+72fnfrWI zc4&AIuBAS@|1%ADU(XB|@k$QL%?`4Xk-GMY7Loau-XWq{*o-GpX&);O%sND#Foa5C z09K&Mho}BWwAwme-q~x~BxiHHc7Aq2=Pe~wg#0)!ch#B&&;Gr6R7 zot@LPB=uyQHJg+Z<$q$tPRExK7dIn{$B>m=0%%fQ+jL#=NJIySViF_#@OavOogPge zK5S$2SQJ&5>Rl9_w~IxpZvur6MzYv%fnqv{U~+bb;|TsFGoqy4+dlf=Ph;fhAk99K z*(q2XcDf&ZfBqRb-SfLrNLa~u3;Sq}158a)Rkm`nx>`BI1^jh|Yx|6?WRShP!2_B{ z&}3cE8_}Yafd)QfMZ{ti&UJgnRteiDz^aFNUJ5~Lh=ni`3`nE#stUs&X~nrDqr`-1 zcW^}<Al=>N{ovWI^z=4VF_zk)yh>k+fQ>&kBPrC_c*H)49$%#Rj{J)3Ua$dchu zb4LIRe{>|cW-mnG%Yfe<4uI-{>b$G~VPm3#IO)Ic`yi)lV;*p3HqKMEf3MWvK+FJ@sn`08%;^I4TRR4Vy^>FXXI>Hm z!ZZve3>5tpp4G~6;Pubw?2LY3byJUeI%;Nj(Os?61J=lNWe2}?7Feah@50#_qR5k( zDyCBQMl@CHjNry7xboyBX)p{>BiWO!Olh3JF($wsxjSWJ}ykl}%QEPj8;^^E#?*f2|bL9oO?_0Sz#?&N*G|cHEtmyPf=MxC;?EwN(-9 z(Ga?2T~e6d1Jku!0Mg#6M!v(Y+v%A4AnP($OA#{eMkT?JzWp7hn-2T2BPU}=s)zQ# z3?RD|pxEm4R&Z4(?1a4h;pZo>UOsyQzdjIF>zyc}&xo}#CH_uDT7HHN%)6c48h^*;WQ)?#;M))Osx5NEzpETqa*AqtIBf#J8`A}e7tLRzSRn*3$ zNcp@)nXji(Axf-6l+w+tNt$`P*zKBmj*qPs55pQF$}VQ?B*Ewxp*$3EUmg`mc5Xf_ zC-@mJ^o15LWal(N&ErJ;e~2h)!J9S(UM=1UK9pXuJe+xCcs$kW7hAz#cDLyXTOli*igXvD$8d(H z7C$|mK$9h)#2rZ?|AxYRDyxxuI<_nl;am$Z`wONMVvqcWiSt)>SKCHp~D_gu1TPMlh!0Oi=3Uk zet!BSy~Wmw*8vf5UGYY+Qu-Ed{N6tIvM1k+R^4rViKNr|1B6*k%?XUvq_)uqTG=r; zi_2h_y-TWsKS~P<4x2o51RNpk57*Dhv28LY5@B}z)^MxWf4?XXe;{ol@4{|(6hG)V zG!PY+dTNRHG6$-BaY1G;1sOw);bL<{|T}kulDpvNpOxL4(l+e&B z_D>3CmeV-t)Z9O_123b8{7&8F=Pof)`inB;>gQ(JmBLzMHyPwfxq7-`#p)ehzg*Rr z$4<{HY-bY_f0fN^&KC+Jz*D;(!H2}~) zj##XGUz(t-ZrV#h(Z-%eRZQRt9tBQ0qwWlVe;j(1)|j%GR6RZ>7mM>MyKw+2zDp5X zpbJVEMAP9^^r~^{aLb$HOy63zKCyQpH+xX^=>+zdwAn}ObhnGxDJa^~#Ph0m@CZ5} z)e*rN3NxI{8;fkhR%t^rwd_lhiO#-BImx8$nh_2?pZ$A1U%JkLNXQvdS_h~5^u14N ze`7CJ>jBF>LQ`pKWvf}#wFk^s%(G&t@||q zeg#^rdxS(UQPlJwEFEo%h2IpaG)@|OHz#F`{0dfgqNbIUW_8F;Brh$CB7SX z)e!kx3H7^W!pBNd&mis!Q8~a^M)rqwz0)(V>^=3R$I67OFKy=K!cYsyg-KXEf8z1Lwc6Zomiyr=*`^Ny~S^G3AHZr01oZ6U~% zZ!fbCi8T(E>P25?A5Pexlw1h^LBf6@_7NiK(iDTq@L5!f));@^L^^A%e}^L~d`dIv zPf8?1sz^0MI2ur$QEQjt3+M{97=PrHxc$gZ@oJSFbH9G+=?sJPK${&x{V<(@J+G#s ztGL%yJk(X#xu$b$V)4LPsI;ND@}M9Vg;)#z*-eihL#5IaRGq5Q7EnV+d-@Sz1B-P-asp??P*%n`XAft##|Jt32ori8LuBi%7F z^DHN-^~u_z(n5|=F)5Pr1DtF8t|<0|JqOM{t2-0~riMrgn1>q$f4aki`W(06I%4n4 z4agj>pn9BC@q!H7SW=Jxc1fXYq}bZ1oYIQ1DH%3IKA$w+>6XLFmiw;3a4 zVP`vrlaxI_?A#U-f0+VczhQOAzsjVw3CjtQ0=OA@S&19H&6o~BiWxmtqi0!pUVulP ztM)zqi+irD}}F9Y<fLT!;@jR!h`*`8D} zxs*6REn%0l@(<_<3aP1fyI_A_F4ED{to)=Iz)59*FB^PfBDL(6j6Q+fdj@}svv?-w z%>zAe6rgJ`e|q2nPnk+26ywk(8W^~YXUlXIm3@kW>>NO$z|UmqN?$|BSM6hR=>R29 zXfqS6r9go1zU9CkaF_h|T0o!SH*{JOCzZdoVJk|xRJU1ON6XkkZ!Gl`jH0a?q9xhJ z0$q(0=RBoP!JRsBv5z9J!8x2OAm<~9)K`=`1@f41FQ8Zdo_PfS=NjRz|Vq;-7;oVKIa zQpwP789;_i;FgkG1bo8HmRefKCC+`!GzX2RD=aQJU&QWYHlW58OaAM>(B@7o0iI6% zG3a%Jbpl{1(>pJ${8Hbl?q=&7V2EHf*f2+0svH`wvg_6^XBdGsska5|rr3+)$sZLf zf1}ZVYc92~M>0&~w;%-3H2NFUXunOyg!$XNS%6yr{tYJfw0hwuQz2HaCl}a_QCq2B zl%P=9zkTv$oJwKoVQD=Ll45{i+=`m{o0kPZ91GYl$|@ns5lRe3+ZWt5tKsx`4wY(@>*|( z=q8tr6CI%fGx|T6w-f~wM~39)Eifc=a7a)L_OD}|a%WN(ET_>iPi-|a@XdtimCU>0W&(or&cP=TM#9_+u_ zcsZ$Fs5<`ygaW6lHmCOPZZedKe=tZJ2bvi#M3r(AB3OwK!79$uC}OCG@OiaZq>vkN zO4CvUp)zCc+LJrP&!7HG62z5P__7bvi^9>Vwmx zIElDs-Y{ya z$^o^Z#cq_DqtIDz!zcC_87F|r5X@>1$@jq+ubHj+QLLSPA1CZ@k%xy77(WsUZ~H~K z(PJlc?&nYdi~wuS#6O8tvS;*ng})@0iBf<>_VoJ+lHDjlRDO^S@%O3YwPL^bc>Rr3 z+Y|O{PtGWCdx(iHJ{$T5f1v^FyPj(Ig#Fm>hOu2L)DYahRUu;iG`Q6_^a-5z`-{{q zhQw~^>ujr&YKvSv?Vo?%oU}{0S-ZD7mXgE4XpR}HzbJC&y{+n+Eem>zZyg@{{vW^xqi@x(0OIpn!$QEe`TD_qT3e}Yf* zsnQ(s1B3%rOlsU9wJ0v)I8WJ6Q4xzIQ#>uEOHQ*39kj?(J`*xA;wrq1)J6fH&AI(^ zk<9s`!&_v}(>{#$U8qRkt1kH@p=tt|xD`7sUI4|Tw$>hAf2=K-HYf9uettwo_R}LW z@}C7PH^V6x77%a>&4Tx}h=3whu!tihpqM^@7$Hqc*pl_ndAShULk(aX`*J$37hxI< zGr8`Jh;pZ*V7oBKH^k%NURRrgWhLrT;EJ9YprMS>|5XqfH8b{IA|KgT;IO2 zKE+~e#@-vle-W6Ge*!~E;2n_PRz3>jaaWw3v0`Yag!*REK-er{X$Bx%P~!t{i#aa+ zl$jK5kZ4Mtib$IZ(Li#rkHLpco$sn=?055Bbv$GLfB_A>sh-vPy8^dc2vZkLX=4H% zna6u^0Wib(YAhmN&Xr7Izjp`*z1itc6&K@66#`a>f9cT!z-j%o-BSKEtAR_J_egp` z#56KHde8?nqXtloWoIU%f!SF^rh;aJOusoDIVK)m;ioa-I`S~A zt^j{Q&z)wGmZbNC(xyw;=4vcGlCM|6IU@HEiWsVJqBOM=Ok4*u7sO;wz={6=Mu~4 z3ar66TopCN&{~Km$)1Vg?*kIANkX048AD4te|C;G;HtC}&UHFQb&66d(7p&HIK0=w z*lB=0WqWt9@OTPmeu;b@-BL0Ik%=PmLhL+;RbRGtGm(WR{ic2VJ{thmm22_&Rz%8?$R7H>3rM+3-(^+0!)WpB*@4TQol!_eC4O0T9ihKw-~ zuv}}i)_C0Iz>)D+Ieb_FVm$Ee2U1(6e~lEr)Rw)?c-&&-PhSkI3HOw!(N(qGBA66qeWdR*W~Oqiq|7&FI0V4Ttg z6{Rwi<1Hk#R!;k-awyI?tx8C@j>!LbSef(dNB zM~C}^OK(<6q$#{oAJ+M=6JQw@e~qzH!n9;wk$j=eCe=Q`c$=+W$kF&Wm)HOo7<^Et z_Sc}K2dj6Jx%RvOR1dA|s|C%*;}YFhQE*=_<5)k^p;+c^d8kQtB#`p+fQv;BVXX}M zn$i#E{I4_iSR?!d(+yt#Zq|Ugyt<+s=@T)mSMe~^_)0bE(gtCqLS;#Xf2@m!vdu5t z77CoOV4AQv?ncWUcfUFy6v2^P!2-x){C@p1U}&*%ak2-%#N+UR6ltqq6$)aB25j~- zR4u-zbOfIH^vdVL$efJy2WUxhO`5@o$d#nB0V;lyB1B5!5cMkqm}4VrfUW}^1h&CD zv1WknPCxSLDWuDf&W{&}e}R#@flguXq8r$Zrxq-Z3A9`F_3!KV`kyN zr&?W(K$YMqS<}Y2dBL_3VkvFv=&{7f1R~W1*!j_r)~y< zehDEtPI|x3)J|$~78=xt$x`m_1&s&&Wa(Y|k#O^}@fc&_bi9Ft$--;dHN4Q^pak+s z!d1(d2q6A7mc?zNQ8(JnIM-|SWBQyI!tIk={awj$SQA#} z)g>#>!Ss|U_nS4O!(%h1aJmvxN0r>iDqv#EtDM%gi;g-K~-C#oSNtiYSJ_Qo#ee!hf;`fHs7Ze?ln?@t$gWO@?$llJzFikzQ** zRdi>L_s4uwC0Tf?Ah9TFo!OmPfLu^a%mk_JlvFzOp$+=AbI9o)HYM+N^t%YTzAfX^ zHb#?KW{x|Z?J*R*5Ve;7HO-ZjJM7$SNoJj56+bGfCz?_vbJvvMd4&>+FcQH@QkvUb zb%!#_e}T^CtU#nybMQr)mZj8A%G&Y3LS*+^S@VQ-eO+WAwuS#HVuX{7v7oDy=5b=foTP#3An93dY3OD5a8ma9hRG&npGOs0#bhfO&|wl=s!;~~7cS}< z^^D;$90wChHZfVMl(wZW66muC<`cV)wr~iHf0k(x*>eeE2ymucitlrdf>BPKPg%y( z%h?83x>UiFl2|<;Hpa_+!oCz=)T%`jwM1dTR*Q5C2X(;`4Ks$pJMzSfVb7e zf6=7EoY*tQ*;yH}DXblV;2;@V>xfq1{8_>IX`8O*$BQX~z&2zH@*vH0=R>53K!7g= z$h(xA@p2!etrv6t5_Y{ZCg*83kqQwCt;qhF&KJ0D&$VHg#b2jKyIpiHjKeIp)kbL` z7C%&sV8qEKW<1bZ`Xx@vtB~+14Ze34e_h!!M1Qbzm9#OrGO{~me~+&0y*?)EL-4;V zM-xEtfZ)r-Yg&zR`qmvPqaU%aqDu4qD@%r`Gg(7ekdkq2a98VL0bE`kIV9f3K94wzlRmM0iN8s;S5(FaG)?Nxc(;*SXDqE=ny^mJvT zr-2;FhD!IiL%|g8dag#|os#A|f2xrPZG>;eYuYOCJ8ZkQy1~a|G?nuSTSGsf!V0S1 zk5Q!|(&&|ns(4yp72UIh;YzFs`!p&^4OnXvBe#YaIq14jjNBS};4hAm zt9oMO{vJ=)pyK&4a%+fUb~Welptpe%iCt^rcs~_i6HbyS)YKws!HiR-MU<1q)jMI0ftyNtHs$##b53}al%&Fr zoUY*!F*OA%35XP&gAG~7e}v(B6ZjN1*+O1(Tog#RjV!YI6zH<5-z&yL3SnsBJ(`BuE0k0EoS@eSPjat}e5! z_JyDaSJ1$UeqmpTp4jaivjK3!VultQW&U>^=!Ps@yWJ4-k$e?3e^wR;G%?^+!?@8* zRa5K}Y9BX?CP&P(W{t^LmKA~S zcEd<@m+1m~2*2!1e+?p`c*v(U9<#47-%$kf0%Ij$CdkidWMZOB)4!TYhv+az3F>ZF zydx^K0@+D20tSsexHe^giBX6mxk*Gr_{wJjkDy4NGE&9bh^9b@-Bdh&?1JC2N<{Uj z&Ai)i#|Qwfro(3T7CclX7$A%xx+V~rrhc{JqcTAv0bxlQf5O=!Z9bSIF{zMGne9=4 zFP>+lS{%?6?)U<2#u)1U-|f(XSF|fCBt~HoM~B=o$fYv?Th8DzyBRF$ps4C*aJ`}B zKu|rxQLfoon2?r?Id~S8JM!$v?|~mZv}*oTF(n&)S*}vXwyYWW^wA>lPg) z8H^_E)bXICf6aBpF9tIAcMUEf%!wALNT$vqLBWx*@!ZD(SVk9%jp0T z@rtjjO@!@(LWV02vJ!%5AB+Z@?1~Pua`5umpyGpUe~`CzQ(a1rkQ!qG_eRNRgo++3 zXQ;CA3l5~ zlb_;afAS0dYw#Qf1*RrN_B=f@*!wS^)yZJfG}}6P^ys{rWH{K6bpBEP=$w|6XYl2r~EM#{_wPF%O-`mD;X-p zwh)q6+QcvEa99TTU@T%&K_>fSbSpgMCFw*Nm3`qE#0lpy<($jJ24I>p_El7bSjmtR z{BBxAC>iD%7fHhKgHDkNHoDb(Qx3Vgm(MTEkH*S#uxr6Rlfo5PzK}w!z1&*l&hHGX ze_GVxWOeV~LClKU=sPqQDVVv>cQrKye*ssDU@KssNls0#7IE{f8ekC$Wf2qFL01Ce z)?tXdi$E?wWN1Ah*}M{}BdGu^gx9nUu*N))T$;`xh4m~W8OVTEeGXlV+5tRO5Au*O&enH9) z(XEv`m=j2vY1!4Yy*LpQ%~he-fZ)_5fw?R1EDnYMQ=hTCJEadMe3xsPDq3%NuOgzB z@rrJR2lCH*DG>k?7RlUP{)iYNVwI`B)9!2)Ok~_8@+(u5bZ$Iu(7f$)Qp*Jvf94)M z7P@KO9P_#p z9y}1>da(%+Um!U!2q$yge$7hIByVL_4Ozo(Co{n7#VjKO-NjAoDE3+z$YTy`QYSir zRMVJ<6SCnr5cMX#{|HR`KV7Hxf9Yl~m%!Efum5V8a=pv%|L@%FPu||0wU~U{nPVv1 zdxB@2?BAjz@T|St@gt#A5$B%pRe){d@{+Dt)+hlK*iWFK%`U1d(G1_?@vw1TJ0A06 zP_UX%eG`$J0DL7LpLOnhUim@D)+nA@89aO$okxa?9ok{d8ALAoI>juke~CB+U!vOF zFobW1Z>U%cYyKEARwNns<*ApK$IdKymyDM12HKI)es-RZs}!H^)EbBo7dAF0J*qI? zc4U1|vQ)z{6*#Fk{ygwgc?rKHN~M6nGLnj>2No+^CH9Kj$NR$~+M8!OiI?Gy|EmQR z&Y$}%aHaq2^#SSw2)a7YfA~sPFS8M-Re3;#xoeSnq65>7L13o zn-zJt6HLhdhaw?zRpPsU!dg~=s4E6}GEydX4sg7>pE7;$K%Z=3fBd6T9_czKu-I9p zDF^efnY*SESwTiRRX`*}u5GLeanq5u;jTTfCfzc^?-9KJ6P&d3p8G?eT>Z~KXBUyr0BoEQpAQNu+hdPb*JXFiH(sz|vI z)y*@uUMt%U=;tsn5xDsxTj~Zln;Yl04C*i<*q)OBN*FetK!$A`CY*QKS#cb)dtus8 z^yCVUPpQda6{9%#zLcdRGM|;=<06F!5VG;~)-@8|KG|-0bw$6cmT!5rt?H~e+0y)N zc2iW@Dw&VM_fOg!V1G6vGWxDsJ}KZJfAbvk`8)@(+lY*QsG1j5Tdu_K1^I@v)j2iw zir;~PPvJ~l^tLB>+cc+B+a_bB^)&np6+^`AleaHVs|#wEcdnb)yezkEgAdpGY5xoD ztLjNr_UXx!@9B+I7Js`vXqWV#e?jT0ew~%sIpz3GPjRvOFMsbT7XFUDUa>1V^a4}s zvlbWvyxZ!t4!x3$PFQ(f1fElkfr0nh@Ljb$JTPybzI*&Vz4@jsS4C%hoSS|(zj^xZ z(1X3ty?y-F9bW6IDfKz z^5?I8^{!{{oPWCqi``YbGePvFyPoQqB7vLtsOeBe_pZmELiW|Wp8fgVi@>wu>Vaoj z4TkLSau3`*SQBtde^)K>ic^byqrZmdWq(t;_YTwp|Mtk&|75A$Pr%)KdnBWGZTVfb z6v2@1+VXC3_`KOz`i0dy&hVI+jYM{n%X>;=9t5?-IIB(5U z<{FeKs%2KZs?J~0D_WRB?)A}vIP3SjY8iN+wfQ?m)y425@7mHS{jM#;1wo+z1*NF+ zi+`Zi4ZfdpxIQA{`X;M4Xu4GwtE#CRo^9ptr@SiVpU)7~`c9xS$NVY(I%%?UmGRZnY@01vf#yPei_`2<{`mRb3;EYCbh)Xj z3-znw7we+B#-9rUP;k>b@GHmRs;`La_C+E{tNtCz4;+vEv~c;SK9la z|Ax0&U0+vx)z@aXlzH0U;QeN}Tm53cpBA(kWGu~OV!;fkIwWwqsB#1cO)AdL88A%B zSbqbslyH_9^j?;c(WCd0sy62o&F@)JCnE`(8$lSIgs@~9!a}bHSs8f;&y2aalzmJJ zR$e4oC1Q57$?p?rSwSKHSR2KFvCrC~d4U+HboASAzy0>`_3MYvo((q1w1N6vk13#1RCcIlwmJ`JZLR53XMkMb;gikaA&mKac TVt@cd@$~-z&`5=-6=**I!o&;? delta 166937 zcmV)DK*7J%ib>m$Nq~d_gaU*Egam{Iga(8Mgb0KQgbIWUgbaiYgbuV1K*4`ltjz*c z#Jvw|X}MMa9{AIv=Z{Ql3e_b>U>yNmh>YXs&$^FHYfk*@r%z350pHW3&U4e6;Qi5Y z_laqNJO2Ffvu7RCnh~?U^SEn54%v9xJqEk|7CiCp(@xj4R`{%QbYxnWB(QLNbZlC$ z@&4)K=Uvmfup{H>@smf-P3wOO-e=D{N2YZ{c|AIMVp^XF&3pFjk!ig{xsST=zQ-YN zyfdvA$p7in&ar8|#Ye}_j~_#X@m|em#T6Mx-=BxKU%IndB2%@x1uYeJ^h(eIP9*&f zG$fM7G$K2pwF+VDZHbMS>lWI@)CL&tGWO;uLl+L*Q$S~q}k$bCMsIq z%4DQc)*3gr1ly#Axy!u{E{9J2*;0qe@>j7$W}-yOC}ehx&CChxvo~XhQK4h2(Eu53 zUCBMI^7sGbid7^GLL>1fF_)tNvn*t;n8pbqaWT;RB#kx5+3+P8D zNg3x+`&@#t6I$OGRA!KZ3^J9oHq5nQT4(nCmk)P?4+Y+-@H`!1+c{iiy|Sy<2yu%L z!v3~RGXI09J==Mw5!Vy>8e=6n-CBI8qN*z8Z`936ZGqXSmzIB2-87(#UYYR70o?vQxu#YOj?#1r4*R>K7_%4GfBo;(F)n3tsXmFbEDq~dJrGlbSH73c>sEa(R07@v>njeAt$*yCmhYAs zb^rSb8A?s8pX^+|$X`y9*zsWdxcD+B)t`2%)z{rquJ#$U)Nb~t@xXoeET5|+4z_a!o0g_2 zZhf8zUb^LOHm!dQjC&Up?%QpwW25@@J)i1vD0EKVl{8xb3IfW9s&T-<^?#AP0y4YT zvC`!P*S1+nTF-b`1;7O-eiwTnk9nKzdtfW+Y%PB+#8n5bG_^Oz?t!7>CHSw5-p(9$ z58ypRpendyY>Fls4|Gq7R=u+_f3oLy?$ZzM@Rbu`V^p?w^X*-Zk`oLMJ%?6g7qA+L zSy}(hCUQ}NB%{)XxZb%l%|v#l$msSxxPT_JUjoIhM9|988+#s$Y)eVdO9F7;FB?E- z6~2EgQ&=bCrdXRxGUdC3smKKACe+zTT55BeaS9{kM32I!tibV1%2Shg_ z+DcmPZ@ySb`D$%_Z~vRovFLw^Ao;bFD=Aue0}BguXqE)K{<1^UP`4kQ9?tCteDhJE}DLuyU0rIuSUXk#9b!@R7FV|RSm@?zNr&q zViMn6_+R}9I#KA_asn+PM%r{tzQ1XtE&DGB4*Puty21BGdB6ojImVdc>vYG znN4U<+WRL_viK(BMrkc5rrpS~74?6?{h?TAk{Yhb^>IzB5+9gcZo$U+H-r1hqTT^v ziE018?F7It{`Qx@{D16yYkS)^mhk8IU&!39L#|;)@;y{otz$c_+c-{br)leY{J;`q zqme+BgzUJI{`>o!1AqicNLDiK?9S|bu|*KXl?% ze!?C5h-xjh+c}0I!yQK}rU6dj)#2&M8S6^$bU77+$4=!rQcVPwRe?EW?|n)ppCU;f zBSEn9C?%@vh!dHNB0+EuMsj~GC2D&`d`%Eo?npwu(qdLW6v`RZ{Nz)_$YUgR%fhsr zDzQ0Zb2u-iN%5SH#e;1ukMmM>yiKvz2cIE9RG?}T$qqDV1*2(S*(Sh$opArjw>}O^ zR#~Oq7||;Shqyj)2-~G*UVE>mP$nVrm(cheZo=-qG_DHB%#LybF5iD-Y^LsWCg&|k zAw~EO?(+A_dUc{86Xk*BU_6nq?_X$D%x_hjl&HwBxC)9IQpSaVP}c={@hUUV~YNg>%8a)r2Z2-Oi;N z_3@|*zH?RU9hbYcMJ8@^*W>B6b+$p1X3!@Od zey*M&6P1Gm!h-}Eh7^7#l{*DaNEN+l%_mqcn?O7TzwYlgNMk!05*lI>HQJ`gf$R4aVnON9G)2j6UlqvikY+4yb@L2S9636&)1r zl=21gr(+m(1HZCad>fr*hIvBwSy{EQJwj90B3xb%X*tJb~6lGg|0)4#R&l6eF3l-l-NujJF3&Hdqof zsy@#g@)hK+QAknJrxhCg>Y5O)g0L%=ui2(A(>4X8KVV)9Hk@9yA#CxAQkS?Rbz1%D zF_`!aYMP+-3oKI%9f;2!Cp7PhJ_o^ggpTe-(wTz9IA+S7pLIbqzPr+ZS-?(f=S4u+$Z>wzUHD5_=!f)p zZ(=r5-w$J~asD{GNe1fWZOn%1<$cXWgRsY#-B&{D6ZQaw#(IOW>zLhk*lk{NL2n}k zcncCo7W4IJ@E*Gc=(0<8eTC6A@R#13T3WEu)aHMsJecU<%Iv{dj9A)jUv|{jBGNe@ z@DW%goaTAVj?^?i&bLId#%sqQV;@b2s;!HdeNt_m#JQo%+wov<vT6umbX63X|N zfzliMK0yOO*2x8xtiw(tb`r7u)m63+#`J0;!0@tjV0PI>KE{KXy|EfTt~880uNJC? zsc(M|V|J|O_qLdf+A~*H-fs4;Xw=K_wbj&g$_|m#VFx}7;+VZvji1Hroof8IxcR(E z*z5TD-+s;3roU!uUp>Di?C1FT-!9kJu9}}No9izyS^ZbfIbpBj=YP`~OY!+VJnPJ* zSnzF(vcO{@tucO8u@JZH^>b%v(4Ru&l)QiBH!SMqk{lU3B^W3sJ?(e$Uw#lV$RgLn zl$C2BSDv~2qw~J?vPNt8Ssopmy@u>Z`sQJ;bn3z)oXd2|-kZV>`_?!405$?5Ivdem z5V4<&_rFDJdSU;FnUcb>Z({H0(+K71*8S-b_Cbl9hV&C*-|OF8SOER8WC3YgHN}5m zA-&QfefZOhRjR$E_(k?jDKK@;_Cl%?USx{o8a0q^EYaFi2Q&xY3ENmT-|1ZlMQaC| zy#+&=K?l^RQQ~mg6ERyKgG^|>3u4!Gk(;@7*!MmsbUh6sUh=1_eb}x#0gR_p@ipLf z@v=Fc_E%TauVZSvrx_}g-6)m*(As~C;6K)`%mIcQI9<&A%z&u3x|#-RqP_*Wq~vR6 zELI>y-0Es6 zAqFWYH1_+kH>96FP>xACMbKd%eD;SgLS2eq%OIkp7lWP;qY7cw4zy%SqFz9*4K4CW zuEYLdoZZC_dPPsATgAINRjqE9Q4WHFeC`qP%~@0LYJGnmf5Q zc16x2zl6E-?54MCy3e+FDQl|EG?u8y3kx-7Y(Gq=V4oG*s!WW0g!egYY;@qtqd%dI zz&yQa3QAXC{H$T_RU8{Z!!hA8@#$ImD=B$ zVad10m%_{mndN z4|V}bj^;%ybrdBDPH;sGP=Xr7kuSj{op_3^(J8d7ELndlz9R^j^*bF3vnbFU5hgHl zz3^3xMeBu@&)VImw10p;Zk3*CAN!;IQZMJ}tmN>Fn3M_U%9d^${qM*|hba09elR+zuWoHzl> zcnUHkZ-Rf1r4hQcjXyUt8dbkZ-azEl-r?y9dL{d!NZt%CuR)$xxRh{uR+^$ZpzoEN zU1^qiAWXA{`J%9~?=tLE#ujN|S-}mA!bB)#Mw>N#9;~i%A7X4lxF{wu`ItXZRx+}% zl0nBY=+80UGke>)_do{Cf}>AvRwN6vBC~c$Ov8UWY(-hmW%+YqJ(o%R^9(+NDjiy@Wc^NbR#amp$qdX zsR@5_SWQ_1zVss2^wXf@VNK&-tt2tlH}!n(B2(^uo>{u~=9FBV-Iy zQ8ULnET#({`G$zlZY|AS)f8;R)9ITDeh;1{mG)LB(rO3 zK<9YHt$|-zVThfojWLpe>b)HLRn@aYT?FXqALMbmnZ2LUI#AoXoIvhIT0BEWBos&M z=hG1?&D(mh%u;CytX?TCP_3Mr)Vh91aXR$lSPY>S>p@6om4Se@d|v1UD%WDx$$Wo< zIZBuda~MSKSJmrD>A92YWo$Xu%AVrpzDzJ zr{=J-@&+*koZu{;Sa(Lmx*<676Z?PO$P2Aam6uuD70Q%Cj98l*N|maLl(#YS4zuRo? z!EbQ$-)yxub}R*(JlDY?l!jSOr?SY%j*iRuQ^k4Nq(%n59~u7C#ByubV++ZTn)@u@ zo|c-`s{6^Zc7;G4vC)2Gwl9CDLAw!?Tvo(0SJNrG^#1$5&9iq^WJ2P`bK(;GCcw1} zP^n41#ABXY7OeP5?2DLVzG*)IJ9L4Dd$f|1dPPpBRKp8-+BP&Cw6)p7IGAM033r@l z2Z8>Q=~PXThYB2!gI8ZoMII4|fTfw_G*9bgr%IC-zR5OcanZ*r;!uBsO38*J*^o&C zgY}QQ64EG&M64rpZU%*jDE#$TaV#3>I{_cuu!gBa@Cypd*HGe+O!4J+^d7>f)mFd{ z8bc=U5{P+ZjrF7~UHPcIT-DM~r}EVNxUfB;bul_QyVH2*+H}3Kwch;6cq3YAzDIQQ zTJJO$^@xgC4vmjWB_V(0L=K2|LPz+)bn2Zm^{p9>+V>DZ&=;x$6M`<&pFIDY--+Jy z>2V;W---67t)1!SM&Ng%g8?0mSWhSN{_45X=8K>*Rb|pI_Z|AF3GH?P!@U|ynTTl8 zPlP-NM6|giWL;gE7MBSR*}=!-egUPXTw$tY?P{qRb;BQ!C; z&70V7lAG{>%R6-A$pT;Q2Tm@{Bpny<$$og;4A6>Bp7?`soH50XsT_%zN)Up=5*kC) z3Oku43nmmIL#tdm>LLwhB(pVo)Yk@EC8j43AC&@VEze`*Pl0Q-MF^720zy z_d)nNrMKwGinxEf`u@>eNMxcji=Xk)NC{yQaWLTBk5MwKeI_5mU&sU@1zw7g3`>hR z3xfJ5*YFANMV_v@4$J2eD!O+`dNhbQK~e*m!F^MRgH}~eQ+~@uG`VM~*1KjS6cxUVu+*8xW$?N^bMe>meFIej1@r-zHlG{cy zmR=B`XyyR!-4|eYCyz14&F;poeWf1yg)s2YpdOlK{8p3`W)%K^t+uSYB1$7g7nTjA zyvpz4w1IyX2Q}PQHqlcU4t#ARHm zQSN`pdnj(q=YhgT-QB#Mg%>TE$RrYk_o9>(P~i5~k=iLh{t-)M3oO4;N%}Un0wO=S z&TpC|GMe-U?9(@C@({I*40Dqt_blxXl84B<IlDP*QWjE!c z2+*4m0Xd0ki}nqi!+V-?DrDqAkP*q!As19KkLa<3N-CJO<@dHAu$W5(T1zd=3wd^? zy_xhX|LDMs9|B)~ue}t12ZxgF%^hts^9v{>*1Q|KcXQKk?Xa8v9&7cQ+c&HqX7_)$ zmc^<3$)b3F`X{G&zgvpp{XM)O@+W_irQJyWLg+w7-oYK^V!*}6#_32Cc{9+2&)V`k zd%ctjz*;JEhO8pJWIx36I}6UOk`V~5J5mm?_GowZMtF^oGl!(tef%?W-uW#uHp%HkL z^>!4Nx3v}NN~E7heW-uy!lpqw_Cqw8wdH?qbcE1g0W*)4X5b89AaqV2NGC80q9s&Fc*w2ctWso=W>$wVY@op?`HL8<&ZWDi%v@NjlY+J-Xt?=R5)l=zCzo|%hz+>ZOzg; z!?mTXgzxi?2YY|wY>2tRIh`j(41GarJ_0yY3zPWb4$n-dw&9~{Ryu_TF9DW-39TDB zHL`CG)?>c04a7Lvx(eiOC{6_)Vorpef{*7syOKK=JbN+tQ7yMbzT@=xr_+_%Os3OX z5!f~ji~LHZjg~k0E=@i?26--dP@d=sV91Sm^8GsMfa-t5PRH{G!0!XSo!stW_+)x7Q7f1vjZV)pwIP7!0= z`8qC_=zi_6s)f1m}=M=MweIZLBZ_~ z43W|!cVt9v$dKH|eaLDvNV;v+*zM|SSFyvl!K@1d>jvaT3mJ5Wyu%}ni~U~Q4W`rl zPU-2WBvB8TJuRBJ2}g;F!JHXlxcd#xkROygO|K1n7rGy^t=0IQ5w zSLLREA9QZ4DzQlY$&B0wQMnZR8h6IgWJcz32%_)b1Y|N~Sw?SJG$~QmGm-S_k7+x-}Hd^hE-KsQt^e~kZTiw=7{rKX6J@HOU@WtuA4|ZSxe`H&>k5C5 z2lTVJ_r3E+A?YWTyfP}%E{Z@)?g%3&cR)ZKp~3Lx_KScBmFR1uwHpwTN5Sf+jQzp< z$@%H)$a{Hy`ub~+9O3UH{QYYG?KhFP;*rDCH*faOBJV4Y?4P`gyj739+dn&cd;KQz zeDnJ(@&b>XzdJkHKa9LE3_Wsi`sRQ1ZRABBIr`!K{+sj2i#@V`5qbaZkymH?2j3rE zKogh6(^=$Qsiz}&Gx5l~<9A1qH#LQ4kvH?m+x?TH$OA2#M~>fKMBXtt2E2ZA3XNk# zc#oW4oE^jX%?5w<=JeqEYg77akaRzqR|lsjCr8lCK{6a_e;xr@&|1yb)@FY|#6=Zk zKfFIW`#JLPpGQvKU+iBT!&J>LkDR}Mb$)Pm{7#kIPab)FeDvlp^6;NWUZ3rM1KnRA z9=$$(d#pZi6k0V6lq&@Qj5o(`kFHI5I;II09{p0?d_eZKk{f2hly}!6NW3`{myZX4@<+v+OFnQkQ3y8OMIzODY zrZ?f(o`)aa`{HAGe)^i|AlXEv2Sc9_O?NRn_4`LAOsr#RKY;!vZWVvO&w)gVn=>oV zg(8Xz(L3$kFUm||^_TZn>KH2}$wvw~bbU;PmOsW0ueRb_6s?3Gx#&UY{Ey+$>Fc1E zG-OWGGH`HXpQKIFLPRuG8jAztdE9=u;{&D}i?K0%Vsq|X1t+zxnf*#YdGRp>bT*yp z2Zhq|$NiIc`EQNdD$jpKU3J#-M?`Y@lR|VwyBGP-9O2bU&PpXmcGt)6jw&zDtZTxK z8OXD@^eqH^Q=pF6%htwjr;^Q8vx;C2c5nxF4LuD196j@X{dN4zTqnNQY0*!MV>233wPT&W^jG7x$qMg zU|SpWzd3St(%NuO0??1M`u2hjoLg@T)_QZxz1FUBYps8OD|SAyB4M7@4#d{BKJ0t? zzeWPvP5r;6|7)bMy{Z3i>Hqrs?H&DpH=pKP>?|p-yso~ZtMBaU|GN7f-Tkiaeph$D ztGnOT-S6t|cXfNay1iZ9-mY%Xpte2T-kxr6Pq(+H+uPIa?dkURbbEWcy*=IDowvl&Gj>=T|Z7l zar&BY!XeXhSuASD;bkv3H&$0)0Kv1m+G^_mn@E2EQamHEr~g@lF1P z|Em{tyvPg*gY4pf#zhwk$7Id_&}6G2#sLC(XQT+SShjmfgT{%C1=iLwL;I~L@`j@G z!`FYCt?3lzO5GQNCJu=tnd*-unqHBBmuv$n@wONhp@ssIbDmBW z%z}A9d!kP@=;>6vhX4|bp;mzzMD)K+q#I`SliLNlSqTut$M6_;&)8@O%s12eq( z94CgD>8{1kyk|C*xwQ+0-gD0`e6fFlg}?qFa%OQE=5E{3ZSC5M&bEmfRW zig&R1|5ZwNBUs}>EMEKNIf2n&rDUU4vRNzHQeYgsY^u%Q&tV6Pm#l4raAWaGv8+o+ ztdT)l2Z;FF`1RLuzFd91X}fE&i)9@IBw35M^c+oemoMls@6gqY*)X##UR!@lX0vkp z??rB}-)kriyL{jMR=!!xL9_3?wM{aPGaWwN^V(T1Jbryd_txZ)2>(&6#$rN`!|9eCOpAATN`DW1ZE1+F_=6T*T zlC8yCu+{;LWmbmGlRN2kHP2r|{Oq&f<;&K_RQ&AA;N{Cb_#uLqFSp=FYJdH+O?RqW zhQTewMSCLaMO2r59eqF3dJrsB~E z(p5-c>@2TFw2*nh!1B7T&I+-qYP=S z$Y_mX*ve;!C!!dWuj8KewV$ZtE8{|1|0wI;u^}~mcj{>cH;^l8^Tk3}(F zP?qP_Mq{ae_jt-MDVSq4V0Cx?m`OIQj|Y|iy@ekg8T$ag(6^QrLJO=48@wl=S8K%B zGUMxD+3_pvtiykS85&!uKIU~kR})g&>rc$jIs~Whj?PezXsMsTJ681@>3yecDYWJn zT?uan)*jEI%PW$vA3kLmv5F_+oXMyF#JN@MSI!T3jVc`F0KbkdSc0s5iohe!`VO!V z#8+8ZF19Hb&fMFY75mx&#Cd8%b@9-_iAKprEwE@sNTCf_)aMsn8V>z+zGEEQ1fu;x zxHaFkKByQ7NEuD!7SynPO{RLh4Xq|lHB|DZl+qyR*drK>*&B2a8u%;Cz?|MEw`z02 zwPvQZJm`NKu8AwfQR#FVxT;fFJ;?J%WFMa|TF~>OH%AAE7S4|@ibGnV1dK+*ac)VW zk631$^ESG{W=h9oucWz({lJ3DYt9DtRe{fr%YleG5Wq>Z0$|5#)%KX$t{tDnskwA) zTpK}TQ46qW)IjKf(=1|oSqlSeYbtq|5JZz-h)RDe7hPu_f;GpWv{1rYsC+aoSAVP7 z12D8Ul^wHbFNMXNsLC|4#C~=x#G-?zF^;uL#v;Zn(0zew9B8DqV276g@PEuM#mG`}mX%uBtFG zqt<`0S?1JKArM);RgAar(mF^)4=>6{cFK#ouy{GYga$1ynRCjp0f}=d z|4I@z`ny2!zjj)+y;+rffPW8q_Qdm8`#FF7U%SRXDp*)#Sb^Of*Hrx&7!d>7wQ1#o zZ4Odro*|wQ2!-sbN3M!_df2=wn917J^hmUQpkKOvK>ek!9G9#ISVGgRQkgB=FxFnS zX>F>T&(*fytxZ_TkR*(D+FRAZ`t=DI&kT69WjCe^sS8L7erfiUP^1L^&t*gw zZ5geHD2pC%z1a@Ck(Rh$D?=Fxwo4>jsTKe7jYw8XG0OwfFUNW|YsHmiXv!)czT7bQ>}9-jdN z{o_2=eKE_o2reaY$d}T4H8wUs6v)cX6}}MH)U6Z5;>rQMzWDjwk&^b*(O`cNRi%@f zLLm!>y8rf@phQZ(J$-u(NP1ys5z9fC_w+>!8C+?Hs;kcw%eVyIbB0h8pLgt$SsnqA zQ_gLpW@MtA@=l|)sNd%J!lmUHFtb=7 z4t8LXzhZwN5_8Yc4@z?2@|JO}Hu&PzCS6`~O$k{mzi6Qy=;P0a0pjGPAaFb!sVJOT zj(9d^Hw~A^)4}5 z;%AD>=wOgMykWPr`*?qT_{KFhEi;>xsogn5(f-N108F@R^sg=VF^+ssv{Shuls!gH zIop`N#|C`JCF>axJ~%Tu`mShXvISea9JJxfpm{VL$w$?b0%Aq1Z1f?zxK32rjIF}- zoq5s=XX)jYrpu}-j`}5o!*pLRWuW~@=zu(N-VGCS$okpS7X*J_z$(zsz@t@PU-#)R zn5I5BYB7X>mlnqbyTGqOYvr<6QKznl8e1 z{7F2_Tsg>JfssKJ^Y?B<9Po1ZwuoQy1v^q>S^fm*77>5RpSLAzBui~GI_!ZLuaZS3 z|7ns&%M^KOL1XQkC*_Q_FP0WF*1mjF%2@m22_d6nY)i=)Z6od{ElexG{!H7R0{1K1 z@{*L^Eq#;okDorQPjBI6q;S0NH&uoN?Y#w0!i1M!Y*0{_-5vdOarE{aPqbwxQ5DuL zCCB=!VQqg&vg$T(WWMmzKPy}pj*FuL zUbP|9(i8t|(A(Ee4fGai{{@$h3)lT6Yf|N){v{Ts!iD{*Yg4~b{*raE8L!X6B&D@* zFkTA*zC4I6c5N}%kxyw-YB%m*0#A!S`f_m2;g5g*B#;(d)nbThHfni#|F6a%1;zj6 zpq)qY|4Fc|^9hS#tnt7C7(3L%e?B)==%?M59$;d#1gBM&AsduDN1>9k5u+G5*K-dl z$4gGp;~NwE)wK+{70zdgmWvT7#H_)t)*aoCtv6ZVJBM<7nj;b z@hX4U@U$245rd>#x0EWWzvO&{jWh}y8HyyI;0mg_%8ukeqj$E=b(%n#rBW5yFgJ#9 zP5g5L~=uM>2hwPh; zB6pkk!GV&}3 z*|X(9_Bm6^O*j`!3xZiY!MM`I-iyQJ=u$;x#rUi9I)7p(Sz*V#IrFFDF|Otkso{B6 zWI{+m?YuHyTphH7R4bf|WDSLxWeR=T9Dc2HV^HL3odtQKlPgedJA2aM$rcPT$OnI8 zwDmL0ptmF_{?ri=S-t?`a)yrupwQQ@8i$xajz!SS6SY-?_5NYUcE|0UZ@F)@fG=3{ z)ee=NXV$5c7=AYLO7T*@vCuCD0`5F3pVMbSq*8;553x>7M8x;S&mSSInfM*Tz7?(h zQc6&fve5v-_CLS;H6vGR&uMCTmNd_!@psDb^4>T1R&d0cMVVIu=Gz`fc*SvoQ9i)u* z9vkcv&tw+o#${O@08OvVqhv5hdQ{S|n+%_K zlaxI--DcsP91i|NHN1{v@PdDcPN(8~%m9@FT-1U*b{3i zPi(6kb85p6CgMZb9Wa^#PyD_4Y1P?;IzPrMc5JCFDEmELXWgL! z8N9;V-v_bSgMUP9ht|NL)Ov)sbH)iZ=e&ZimY4#xutYU$3{N(($kjl&ycRrjV-72b-Z3^K0gB#f$LcHz8AJ_2P~-QkIPevXS%~w@jW3I?C=6 z*~spa@t_BHM;F$m2NwxN_K-q8L`0^nF-Ve;7Z~fN0ghQhhQ0};9yRIsQew3nNk}zB zV-ESTpcYADZs$1O4Zl0+U{i1CV=|UU{XY0=TFkUY$~1q=_^t3MnbS=`Qh_0H6FnR{ z3ufdJlA6h@Jdx1Tt>9SdqcBustq;OV)#_uwQCtNiofY&`Dr!U?fosAVjGb0b0`m0( zofR*SdsxTCl@X3dvfwnl1R9K>7A2(ot>?%pzWt= zoKB~HibsF zR9b)-6mkortJcoHdK{57!?2@x7Nddp`C!Ub>>)t4(vTdPhSGjM7$P86UYvGKrb`H5 zYiM?APG1Ki)xil1{FN29y1KHWs7T@&p&J~uA|HP|@fstVW$JvP6ew*x(5xXGm#7!4 z&k&xPJ~jkX4M2$MXBNfy3^RF(1e1FXnY>G|S~n5*ER~8_%+;n1F5ryk zceNKp^Cq*oS@56y8N(kdIbVtBa;M?LD_RqfYc{yK3OwgteFp9#x3HdjCOzJy5c3&9Q6b;_h^YqKbsF2^3{HOdJs0e zHLrAV?x-z&%W`;Pqnu^LdRssnkCEM9)}X=?$&8DdW(Zk`9|5qtRH#$dO@^Z+W6xlf zeoHvy(H%%W8ZhfXp{@%r&IVQ&)l;hUQ@U8UD1C~ z7Ma?eanyBSE{I=#mxE!!`Xz!jiZgDlRDGGOwJVx#*v$D~1mn_VHg^;>M)4ic{4ySe zj;JNm>E#txyNM^Lf8g;5x&PHwl~fJVWh!w1G65q?G!S{fFMGz9>OQB6axiQBsg-Lx^;0of=L&yp6_iK>_)~Xb)tSk+bW~U5kH7?+SXxZz>w4PwtE-gaoz7%G+ z(BgocyOJ;)6RHIyee_e5OX7bd0>T1V7DOv0raOJC1mDHwJ7fL8585K^j?7K(e=H!@L0J&*yx*?MFWYoxg{?wI_^c!f6giJG) z>_4m?ykJJ`&eRKOdtI@+Fm)zX3%7qvp5A1omV-)QCVM@q zI$^btb2P%RuDR=>)e5mbjrFF(A`9xi3ZeflO@=&UeqBMGhMFR~Vg3Zt8i`{nc~y!y<$-19ED_C148szs%M%l zy!tA271YLHQLBHJj+Kl#;6*+=g|d-8kbd3=9Sm+DZL?nq2~g?CFs)WC6~ovSZ^N8! zz|3`!wpVzY zH|x`B*H>1TWK3T0Axp+C5mp6&Gq9Yw6vVNgiFF|w(dSz=#Mexs{Prp!uFy*Ly)#?3 zUKxXpMMi)7>{}{&1NM%llG6eBQ7SQ*<4(ifQ#r;4!4@KZP3sslsn5gHGPj|sq5XET z4Im+exfbi!LrS=IcP?<4sqMo23lKh8fa%3NOfL+k7oUUaO=pQX(1^7cOZ#a$wLx#a zFyGq(sMGtY?zDowY`{?McO8G^;T_>J1CJmQLt!i8OPAo5H`J~i$SN(#xyfQXy zW+fD9W~Nw7IzPp5GbjUzfVcrzZlkEbMCE|!%5d&(!X)r(hpKv}H19Tta0{Ttl=a44 z=BIx&{H_9{IhdkMBjgbgQ1dv^T40F+epnik#%0P93?8zSlut}?9$014T2For2~xY?6f zor>PNu34*u+9|sr)*tnGnn8%$G?&g~ppJhio&bhM`^C$R5*p|5<{g7257lg67xnxg z;smlOqtu5EtXJ*wVx(kJuM_2+Bpn(h#2P`ApZu9NX{dmvGU+NAUTn=dq_`0_)JJ8| z_M92pmS2^FUa#(mk1!|r$5Thr9TTKq8g>;3PhpcepeZ+6+D_#u+c%bdR;#tt{WO2S zMx895WA3z<=oUmaM z)G5bFswl4rFeLs8Z@B285dG?SZ*OTTHQC_7qD)bJ)%Ug)^Cw*~70OiMv8 z3$F=dccYnCc7&fgG_Vz6GcfXN~DNsVe}cNPR>MXC*>q&4LY2j^Y=j+fYa z=&(?_Jm>QAaoI3auZBixwV8}c->$9}XMJ@Q4nBZ>It5apWY4LNsBs=!UDf1&0ur<< zaXg1luxX6dRliItGGfd9ox*qgd{%6Ng0)vt3=mV64ZzcDrH;`w5*)v;Sut!MEQa(` zZk8e9CQ0M{G^L>0X^WQ<4J6Y`aiwil4JBA~bENH|@vD$$>g&QX-7-E+&n*oRq>+r( z*jNYtN8VVVYM1rA6=QaJ{y4mUNd~K{>{9&-F?5wo(yQr|U3&lh-{#pvix6ebZgQam zpP8u4+$$}V@WDiR%$1~$fg~~k@dgh;d<@dnULqLgLs$HuNnb!#2b z%0#C+*4s)CdylNQ@IvuUjd?fdz8EOV)iNP|g!{!RL9>8>cqep(A55p-IaA-7;i#hq zd6mIi2Rg{3jO$OH|IP12@A>pN5Yq2Nd(+m=baNx{JJG>_4o9qi7j&?ZubzjJWzzO% zQB$=y-)YX1q!<3B_p4|q3!Db>eXkjX?Upqr@S@S^SDqV`0e~>$ zqO6D1@Su=wD7KlZvA^#~n? zudO~}4|}{Gsz+^qakw9grVnti@#~v{rbzGobe~L0?0iYmF$)w4A>#CtZ&|!TP8QJS z#{v}8G!~Xk>l_Qx!Y#AJ!7A8>1wey1_6*3qpkfrs0Rjv{whdc@m%y~}Q+v&V zNgIoEF8o*K$64v-w{xlEiJMOGAgM3l z-*2V*ua>{I5B~35+XwpE#{24he0k|T|1G)6JmP%^|E|cT_dFd7C^&+D&rJhiRKP`f z#QPrpsX-*7&u?K6_+zYWG@*fjq+i7wTTPPw;Yv{%j_80%sazhi5$$qu+s>sNH(JYb zE*~LRoj(~eG3JsDqsfT&klEV&FAW=>tpO(Gg3d37ALR zrr?BrkPMPElHk}lOhou_$0Z}WwTomF?V1K3cu(F%=~t#D$dOd^+nk{>**7r`6TCUi zAk#kr-!)U!%IOGW3&YO6y&bSaEF|D%O2;5?lHk9|dW6H)9Dp%nMre!z$|0BM{8pTf z!E=Uxg*>xwb4?~3p_5aupg$A9^sKjvN3*Otpb=Wq|HVV_BkqyUHD17ae_MkC7m1aKNhPrl3)s?5s8; z{~(jQl=WS6IRem*Qa+?$sy#!SBWq4(=Yn++Nmf@EjPUOq8zPPC9tV_qGnQb!^2BHX zy)+I>AIu*gq@mnA?@v__xGFPv!4TaE6LdzO09#8p=>29AC< zBNT(&)MjbdB2PC1So3=a*8Jecnq{niC@id)K7j+39r0aw@onG-;fTsRxZdYsh)=~9 zMlq_8kq17#EzdfIi0YO^V-wAq zq48NGz{QY1an9dji$VRx8}-7V!XKAKg?LK-z>9eSR-~iREBZ8*q}qwnaG3PyV7)aX zGD!wE@TJCMZ&+VO+ZE(?26RSVsxZLs4h-<)mtX*t*Bm5cA(2c{qyre;QZ87Egi<2T zSjPWgB&*R;V>o&BXu<`o z<{c$ODeS&wxDqQ(N3%a_(HDXe=$BfRkM3=)w?Mtg9!}e=1W*KYz;6YA?EEb9x(qD! zy*ZyDjla?)pR%acBH1w7A;Vs@wGd0Vfb|2JC^CMd*#tu3>E80r_LiB^Z{tkz{$u3z z2kg^2#70~^q59i8#eGF4~X`L+Ux~|J*qcw5&mK@hr8=+ zc$hp0XXoknWKueO5HWRs!G#;$DO%0d*SWQMasX0CpWl$l;y#GYI7K5;uvJl)REJwS z?Gb1q5qXeG!^k710^=ua@>pv#N%dwQAp?0 zg#H|9z4RyO)R}I7ggqXf>|Y#wdwq8L{^E$31~3j0$iu}IhAv8*Vft<0bV8f6t!6>c zsh)+qaQ_2IH&xuDAgaF}T$71RBJVk@6c=E1s5Zw=oNlRYu#K@GHkw-jN%vswx3@6< z14JQt(QNL*{(vYXyBm9Zn*rer+!I^do2`Iw3HA3jpgvE3;rDK9cRL^);!Eu8?QK9E ziY|=18&D^4Z}S?pF>;G!a{47_7zS`%87d;$_^+I*sYrYP`Fb=lp=gfs z2S|DFtbTBK;-)+_oiXoT=iGH8LQqf?nbfM&G94g87_j4_Em#pGFTE3ReqKj8U+&;R z2V6cjR0ywsS4>h55gQ*bxddG{7?il*8gR>uY4!Dtq{%}xLE&LPNrCO`(gE{Z0bGE{ z9(t=$bi?{d%Df11J~B|xo;m3pB9Q|h0QuO|k~go_Z2qT5?iA6Yo@QzdyNJa$0lV=* zU0vv!@xbC)c{hBufBB->ymB+zY6=H>%o8`;twz#+a}wg+J3i>8TF_@xtNH4qd=Cg0 zq*^t{iPS0%kz_HQP7MP(j+5!sH|L>4_}C^=6tb9hW#u3m`KB zUUGi$V-z42O-Dr$_*e?HSwvW@XvFvdKvN_M)u@A2Q_3336Hqc!Kr$=KEqd(3cqnt zD&{oh!szYl@tn;FA1=K$=RsOac1u7j_JH03w~i&g34A`(Ti|}V^9gSG(WIXUc@8Yg zrjoDoM@Q@T^ES}(GjmCM?phux@2W)2Ga&qb0j|8}HU#S8*GuA9KrLwEXYQoAxD+F& z7pvLYBGtRmLk8SP^v-CHkF#h?f#}EqqU(hh8bT-$2X|E5GQ>+5v-2()^jM0RsT6DU zX*NhtCu;31!Ov{~cjc(aAFB6b4nYMWAP}>te1k&yj9}3CH^3U{I@w(c_#V)KHMJ;z zMU5U!yLX<7o*!`)XWYwlsewx5pxuPeLP^tGrb7z{Gm>wfWGn}$q9^_FVDJGiu$89b zHwsFdpZ`PbBlySV?IZZ7e;Xfsk?{e)_~$V`;3p-mKJJg{R4@H>%1_OY3tLOCiy7hm{#rXxs$Uh*=3gD{SB z$-`T>RK9j=Ept^lZmCSm)4uHMN6ph|V~sCu=EwxC%!(UpT)OJ?J=f6YAr3Y(-PW?f z`kTFZZ#bL#CY{?_h1gYdZyXQF^j*A@YUA38A>I-MAQL7zfMsU-r; zoq9UH3`-6x&e-58OpWEF3Za8^8l`zTRJutIO?ThF-G6`a?djR^FGq(SxICj*&|~;r zR|P;bz}MnCD^_d?&cgo4%*cU0-@=#Z@U;%N zJMVdsr@eR9vk?~pCa5{^-|B9?mIzt#4JC7LxXv868MsNkKYOFl@;jQ+VTQhq;9qLr z*suTLP89s-d}jQ$b`Hp6k*bU89eo7&TLc?=)q6n=(f=yx_cJCVhyg|#Utu;6dNP(v-}Ch}YjAlZo115!W=c_H506)I}_bp_(BVB5Z-8qS+;i zmY(G}{Tq-v?Y@9WlKcZGa#|aJ-oKAMvjPPxW|(p>!ynZbIfvMBrQ*`u+{`8QfY_(= zyDM>KaUAF6E9Q5>26oKYqP#;3@BOHmO#Zu{^IFG34#Gn!8HBKUouor5!#oHw=d}u%jT7Tg*ARJB#oB*A|E@n+Ob|l{CgkDf*_7#lg7h2YsYxhY5e71XGsYEX?|$T zLIo`1Cdi`f92_Pk0Scu;NVKVh7_t2@okE&}uxsqZ;r&XJcz98HTtM0sKMfyJF7>s2x|$h$t9m#{#`EhSn&%XP10{j z69vwa_Z(0GQE5T00fC4I7%~=O?dI#Fx$7V105zEK@02E+Y0qHvMUE%=r1($Zo{o%z zcgv)aT-wd)HPHb^umK`#NS}yYj7ZYB*-l@|cDl9}fO_4!1kyrb&tpMoT$Uno;P0D+ z$F#$LBkmADwc7|hihq-@i?qGUi!6)zWwN$*g#mKV6E3OB`b@<{N%|0g85zeI&cU}r z%9IWD)3DLGLD-hiL*`;CG+8bo8jN_*KtyYZ#PaZ$0hiV(3{#eD%v%>|M=4$L7`WJdD08Bgr%YpX2(Gh@%Gxy?&?)xp0J{*Cd%Q%&vsOJ3;P zHu&}++Z>Ak`~dlq|0BN4M`vSPs5+hU7v<_NEWO)2WUvFs;Hm2ziBQ-CY8k)|W_zo- zw;K@3Vi5|T?^+iFMzvSF7dte^P7l0)S<%>-_v~cyX5f+m3Lu( zkR++^r)wg3z7bsI*^cuxBOH^CyliUM;h3+rg0IseaUcd8gI8(H*IU6$QM|&rQL*Sw zHz^EB3Rf|QL_{W*TCSnNz^h%vGYej58poYhn|TEvmqDjQK!*`yVf4Tm9r(2B}t zC52F_YD&egvbKhs5Uu&eDO_ZMLoX(SB3KOX`<3~Dg^eOWtcnbqYX2$fA1|00>`Bvj zVv4iq@`})2FLH;!fh)+wqRKxp)R;lgiC=yXG=|WzRM4j156A=pWZ5?$B#|qBf*sX* z!H~8RF0~o4!a0?iqOie=F9VQ&8c8r!b>6se+(VH(s5{OI^^-RMxf?(o^>r+9uc!5>ca3<0@3nFO3EF|i!DKgVyU5N%uMeGb>}#Lj98@JLPo&~ z1Y=8stQIbqU>5{-1ndLYPsB#WG_er~9V;auh!#;?B}kLl*#&53S7#vycY;$0)?|Ov zvcDMHUsTsT-{*jtokT=sh7j!*A`q5~zZRWVv<}Gu5LKdLigm+8u+u)A?ZCfOCD|Q? zr^%2D_%34IP>hE+EG3G6IM~miNKqys&(2iljh;$pX?+heN2m!y{>)G3b#0pa%x;~Z zT?K>=96-niSZOztY?MW+3{};q{lKT)z-pAB7~fP{)M(y7{vx<4wS-nN1+dg``~Ul` zmI>|s`wsqJeg_wL=gwXgAoT6cz=9RLA{F*ZgRkRekf(@Pyg`_M+91es!!F4g1Yse) zQORwbYLBk|7{-s3rQ}0pXNDShJP~L|s<8ujVWBN4_~uAHLdU0Emq^CSoGj zq;xc57|Bmn=@*5ljUzpkxRwqWxyyfMWE3;a82!l7n*-d3waNW(hUa96jO{X`tY@o}Wj&>g+GuK<@IyOCQ2ttf;(7 z#)*;PE_>weDj*L}Hj7;MhwvBw5x#o73fl6?Z}>K7g~+9U)Ui&lSz#mm78DJa=7h7T<6*z+aQgtAKoj0i44CKE)ql02lE`u!uRS z<~{lpkW;980(JM}Q>gnUK83mmP+qBy6yI@t0M!oT1E}`4IzscPyj-dYLv9UjeVb2& zrkKNeV$+t6XaxDpk*3vDX7q-XDXr*Y=1LNg_h$Hii5a=PRh~2p2Ah8s6yKM^$|Ciz z_v$q&s3>GwYk{_){YKeXU0yHl=g^032g`;F`fmP7niDeWfs0=9kn`~y{v)};b4hNl z0&@0uwm0gGd>KUV^ywud^6n}izr|JcR7PkY1CfFv%0gq&ap%k=jM9iSN@nCfAo~G% z9e1aH)3G@huWLH5*VyQc^vT5Cn1Cn1Z5gi!1(rVGVXCiAPmd^l| zG6fEphdo3C&b&MOW$kuR)sQl;-7*?jNM4YC@_plmqaLRN5HC6M(D^`UE#}kVwMiF$mT84`y7NTO$SgW4~%{6ft|`A z5w{+}pQvWyU5^YC0WL)9)gz;+_3kbi+mAyo#*#(e#(Iz6a_JEjwxcM}A`7q>q@#F$ z5Dvk>gO0Sw<|d{i#0_*v=xw~&+TPq@FDz2>-bu|_6H+9dCe^s@$v`V)(S3;=u_zz? z0ni=E5_Xj`IX*wl#p~+YpXUPths4t-osvn8$`c~F9Iz)E<8hK()JhjepQR|s8X!&wE{waA5f@E9|JMK%fa*%))KI01YWgBDcDfD`jPuJwrgGFm7b4n-Kv6xTxFj(T{;oKLvz;p2Tk55qpZfG`AfA3RDoU+mfF z;7wshLf`yzyT#LkcnSMtFT20>2z>)0J)nvv-Eo?M_t_}nI$DQz&E496DI9a*_dRD1 zuaZxZ*K9N!TRROX>vQlQQjx1Z4F@8NygMmJ(evjI4-etPW|*Y6&o`RQ=5y#4eBA3R z)#Ygy81qRQc^exZu^f(vRHpos-)caY>#fGdW@BSB@JJ@p^D8Ex-t0JkQywOyLb zPOUu*dk78El+hAK*>Km*L&#_f&V+E8ksgDTS>+kRB(~~-cE;kn@eUpvYCb*XVgnv((8X8rQ$Z;7F;xsM27m$i zmud|CY(NC|b5+ryqckQl1yx5DQ&4q`=T|I;a~xUzTjVAlpNbWkFx#cn^X1 z$2i_eHI6rANY3#`5y#t+C|qatSU%dvQy$c|GoF1MJ~ve44b7OkN%L@vFa)-K!{h^l z4gHxh7oE{xwmlP&GY{MBm8M|fz!~vAsHdoLamTa9z9KQTH^3{_crSp=f6BkRJ~Vn< z4uN8SA;LV&sQ#&<13VOB*UDn-}~Q-S2}lN0udB4xu0$XYURgm`I`Vzy|{u#E7Ls3R;Q+ z^Zi95K@b)One59q#^H3ry>ZJj8dV+K&f$rPeUqIEN#d|g`fBKAp!j|1J1@bD8$`= z$j1$I`?-BQ4pfsK@fu!z@15FWW01N#2ZP^wzDMYZKetNorExkQ+!&w|7=Eev;c}Vy z;Siy2PCz;lRH6b(N6>Ug9b6BKu9C>;b2cONk0L59k|Ps~UW4$p-@lm!KK)ATM;#eb z==;E@e<<+^{eTL(=1wyp^m~Xzy1l)B6%hL4(>jG7zvn$no>I~&d@&XEVP2S!r4JN_ zMsyuX`h6aUc}D2(%ST0oL_YttK@l+vksTA!I$tRDf&hutvSp$r+UFF}*5PMttYx7e~e^D6pyC-(AVyx5H z9gezolt7{!^4{#J09&FCy!lkm))&%I^Mh2;AIU`D0EpqtHC3sZgIqp+1+$lQUaD|(zIG^PT=C);atlKZPH#DpjWz49j!Dv74D}kFFVh2V{S)Z{cglLemeK=%ZW{I9w)wGD z(gSWUuLu0$|BfE;2U`!g7nkG2<;Mt+P&`3zuBb_}N@_aZ_gky{vU#Pq7`N=|;rEQl z^bzem!6@|dD!*fBJb_~oWquQ)U_fyB%x?umy^b<}0~nF{Uh6)sZ5c=OBtTt2^0mvD zWo}^2#@N4P5NpypA7dSV*h17}fqcV+aaYP3bO32w9~yG9BXYXCu+qRL0(Z3?= z2xAeMJga4^;xgO_{xMlPf1VeaON59*BfEts=@c9EUtJvhzYX$;b?t zC-l%{mGP(1GfT`CwU|>rU2$p^AIJ5%d-Pr5!!i0}^JJGlN)R-E@Wg5u!WXfc)ox|A zPnduMYzZ=Y_ZnWnM>jxd9r98hGs|?bUljUP$d7$iz|lgp-Uw12a}!$Q;T(_$_nHM; z4=OkXJGM^bF##H26Hao6qb*lptR(Hqo9EyiPpWr>GsZjjWz-dz48H0j7WFhS&nW<2 z4lv6$vcS=qE-$iw5fAOH!$~z_3CJE!UEE?Flmzv9x(n~PE{lIKmNwDPc%&L`H2vg2 ztcMym;Hjnp&%97*c%2>FCu@xG+2Oivhk2fUL#+6zM(0o1j`xzLgJD0WrVF=XAEQ#Z z#)BiYNa%I20Jw?bnHcPYF^|((cjTIQ27UmbdsJ8`Ovl-OH%nT65YEyLAx0B9LXA7j z;uc0;beDjkajsw{DMk`t(i(TjUVfDHf6>&{@KHk^D%Sd0)EIqc(Z9FRXI9?c=rfB@ zA=!T#UPSq+)o0`#6KImYNbOm*C1PMXU`8Mf5k1>CJVvrVc$86 z=0$%;%)>r^3~!%Z&BpyB+qMn6=YUD0pA3fnz;%q#au5uSAQ4Z!q2I$)NW4574DEsI z8@81U?Vf8H-lzvDaP!tStzG$x(VL*Y|{vwo=As(`z6-wCj%vIpyXZR>r2sV%l0s{ zQt?}FqbcrIQ-yUx@#r+&-o7jF~TBnLD+1IIBeTko_rR+p9K8-d@0 z{y2UZ7>?D$3oKu2;2J}(XBoEN8yP`B7kcA=8D=oB4A1#}U>mMAunc!Junl`Oa17Tj zZNqorZj{)DZx1ZPw?fM@EW1ZnETrcdz60-^-pCkQbdhhMUT5^XZMbgFGCZqi8=l{D z3~N{pY{LwC&SGGgK?0RR1Anqsu%JF4TIAcIV+6w>i5n_)ri&?#p`7kXhEBmCMk zJdZAQ`oIW=muG?D^eodDjuHZ`Ww>_FGlC(uXW$!_KX8lyMgv>o+e$vmF^0oIV0h4~ z5dZ_eFuk5*44oc)3vIW0kT$@yI^X4g8GP*bT*LE{foC`Y0LB@(Ff%N}8Q6wnBNTg9 z0E@*l93Q$kgty)xFor`IXfJ@A4(7Z(8`wrLa1F~!TwDN#XG04{1J?-rCpKgm;_^0) zp`C2>#2*BPJKAWX-wO=4mDMpu-oP@&)UZtGXK+JN0|y7pT);P$31AJ>iUvb}gse3( zEHCj52W!EJ1;cE)gTU}T0D-%srGer5y`kZ|f3Q<-SC5<_y!=BQvTVb54A)O!0gndO z0A_+eY&R~jq12&Ls)u`+0TbM@VCGn+VR-{%1oM6f%fk-_FzUk|ExRF1Kp1q(7`m57 zF041#Ge+)H$8%uSyF=5k-a1x)0NWG1wq4us6U(sxm_w-WE#|pA8(1c;&5?~6JpfdK zY3{%q8UFCCAOHiomdx*+`1oFe7;lg0MzCe_)U>(0V z>E)XhBY*-VK{_V;HCb~>bXX+G;9wF1t42;AC)g{!n=5( zH-Ry<03{B9@-Qq5K85kOoaR$#kF^{aws(2v^q_nXa1UOnd$3KzT1-R3t7CQ2UV+>)Ajcgcqi!QP-2WGM9FNwm&#bVfg z=o=2q8YieB1Dmsd4RAy>TCXA?5(buG19V3&UF3@Je1Mvb#5P<+I?UgtXN>I7rj2^& z$cf#v06Y$@7OPG+yb%#SozV z=3D>*U|*~ZWf?Or_}0^HGIYT;*2gP4O6l5V|bvJL$K(dn(3 z(ldM4M#wQDLbq+h^XR^?ZJ^C)4#F*_4o2b^b2j(x0CUnU zre2;o4ldfMIT*pF>muTV?FjN(4&4_6%R&MIelZ1btGvaG_5Hv%0{Fq_%QM%4S#7z7 z6Wkhqc*9W_^sL)LZ(updX}N)60s{9(gusV}?=5^|6#9S({01Gkumq9!^9)=)BAs^L zk(~fdY?uLj2(*t^&vo(PV&FonfVEw?p#$ukQ}cANuKfWqP8R;v6CZiXW`YA6#~ssM z4BVw}*v{pdZ34;}8KxJGV3p#9YDe_mL$(@!FCx`)2S|d6i(G&nY+4>}bsk;B{%6=o zzHV%0& zphE_(VGqLqz#Fu-&f&nLbb;E`ha2W z5nYsp4n;t`4^`}7_DEXcA!&$z^^|dXn?>Sk#{_>!mwG3b7{R8C z#1@43T$Fk@qX8T@Oc~%ty&+v{+SNnh=rS;DcQJ6@x{eiYay$adwpRfRygwi@gE^v0 zJ#~R%fojF27A4p{YdJE1Jd0=w$1nkL4KL3?ng~>d>;7A@`u_jrtp1TZLUoAkfYfNT zuwlcs4J*Li&sz?mK1{cCm*SbYDAO~fDJ zE`pPG=!OBT!=M&alE%v;LFKj(aezX^%}!g!2>EXp$PT=J)FccdM?yaqfImP+8<1i$ zAd=j-!wujb?H)* zuT}^78h|XE_t)#*f_x=6r+HdW!m0cQ_M%Gg1^dV+jy3+<3;7v!ryqKjOdmLy*< z&p_~o`cH>{#7aw)4c3As`!CTEc_UKgn?R&4Mj%pLx{CqcTw9^=<~6WK#%R>@d=rHj zzGIlacVn#%eC70P-vwcdy9{8cKqzvX8hx{82LKSS=h#qyb7Os$AK;D;HWJ>#MWvf< zeM5zo4R!=U&vsyu-dx{s1j9c9pe)>_y>o;0NkJd(x zd-KYF@qJ_D_beZz^4LdvX+Ocl+tulyQO(G3Ef>v|?BM1;`a_@vtf6ZJARj}`CyGcc zQV)QYhD>xC;Ys}rqE63nLePPsA`Cw@d(E@@M#$?tyj-4*U=sy}{lB1QkjPnvY5gmz zb_RiAj{ey-{}o$|Z{qZEhlcAu0c-+xZKmOWFYKig82$oQT(Gpi6~8!vi54A0dogf8 z(isxYRoE@p11;>(?ODjBSv9W)E;)sPkJSr$LCr#d{etZ*4L7V)2e{w>H-Pk&M5?|4 z{DlMjMWa>)*)m9s77j=!L%%2aLUUl*3m_au36U0NupAhk-DDXI4YZXSB?Ds!vd{s4 zNeYK3CH8xC71V@D;y%Y&S_ulsQA;)e>Hl9bd=40x`JQ28AHWn4q?JHDK5;yJLVYy8 zv=YZ~&^%`WPbjXoJTzXzrVdeAfy5OGh=4n{F3(VOhLUmm7R2r02;S>xXxF@g@v>dv~1#UY75Ydsu&4VdDT*`qOT1&h`sd{Zs>X=}EH57m- zIFK5DV99OJq=AIN_E0ruAuApT{A7_e;}TzPe+=vyd<{6t^}sgLCAqfLb|6EE&r91k zf&>>EK>LCBtt{u=XC8?Aj@u<`)8y>B=nOqD>i5obux zT*3?3KSmy!0M@8@I2;(J^%pgNjRatzxpbjUmnx=t8w3N;lA}J<8-nG*2s!3@f1zf3 zh8MK7DgmexJqrd7M#c9@GdDtkb<;0cPOzXYXW-aiWPcBI%EKOA#YzV4tk)Y^Q`qB% z185OgUYN*D!e|by1cl~snGQSytW#kyVaofo(m@~xYMugR*{*oP7tObSp@mkhmZz|h zmf(o}zXte@3qp$#NY$obmkLt>tr=XfqzBOyh~_~4GC~2&sFA<~pxXwG`)~^UG2qRS zLx!q8D1SjD7JvaF2<*umWdsJ3puPjM=N>L7tJes%(CF9mrf6w7z``vb6y@H)LhESH z@IVv+!VwT0*upGi*z-ew*sn)Dx)Lr55SCzYKW%iB7TWj$R7Ws2G)+)efXY$8Y5`yk z8|%VaMH8*Y0?HmvT^K_T46p*k5;pM59@=d{-$DmuiB4^J15;&WjJ&^S1$oe&z%+pS zM^8gH5KUkn)h?=^sfW?T4Q5F_;1f}%K~;<$Eb z4bd`tNYY=N{zJ5XA%N>WxcWW13UX9_36sik41WapEI{iOQH0r3Q{d{0t7x%@6+p^g z0=T+~(*arSf^gEa27&m+t`$C#z0~_AneKam_{FqW0U|iZwL5x0#py^0)g$q}xW#V1 z8lt|zan1T$v%vR*p<{G+TILp-CS8)gW?la~%wSfo=i29J(VI!Tu=V(xl=o znegD9fDzj3?Sc^=Uogq+--oWz0RVzffSRTjgy8kSCu1hZ74X3whTv1D{>9+gLQ)_! zQ&5cEGv7L{wSlDmiYASQJ;w$+^(VfI+CmjiJsAx*@gC{xM#d<3;tvhS-awW1(6F{} zCF*6Ykud^)aS_nU8{cdsA$oP;q!An_^xWmZ9woLjumiB+1N9ml6k9rAG?)x90jeEc zp4l{%rZG$`+Ze(~y1`r9g)vTG3zK%l6r9O_UJXe9Vkg1 z(jNVP#>#!*BW&PTg>fcer4Xf)!-n-2MwT`zx&yk@N;MgM=~8QoZBlkNhi+UFRM=?03bH!~)~XEzmJPO3 zc&JO-%%D}lfTS9>OBbp38qv8gn+*HwbAy0?!R?;gb8B6c3lu+TEkRywf_*F$JX*rG zvOuic1`k>x;ps!0j&s!<0h*-tHZ8nB3SraHuAxVl+790z7{ei&zuLI`0>gAdVE=lf z#`tu%p(?D&ZBtcWSgQ8iTiK`*`TlQert17tEmVgiI_LRsZKLXp&_>lFHFGEqkVqwe zEJ#0q`*oCWNW$p_WS~N3!RnD(RBYp!-%aBHd2q-JzHU&O%+qb~;!HW~ju z2L|8T)}L%A1ttEeW>Nz`0Iw4!oG^ja-#)d8;(wR+6*zQ47rDss@UO8tMmfZ53EZSS+=F?cw1d`Tr1G+Tc1*kxWOu+mG zNq}7vpjn$PX1zLw!zV+_1l5IqGXhB>m`|f6o3CI=JYx%p&<^NQpC|w4d%>z?^OZWjU0hC#e zG(og%X@m)@5_B8RzsQFF$q)o0fnnSKObbky+^F$&$=iix$z$ImX&wn?%w#U$*xw3I z`(Fo7!h8P$Z~`Cs5G}c_?7}?c^Z{*r0!K%Hk72EVK&hh3aF-UBejvD zlKFhz#750ho|WkSHOsdhie4qz#|&aDpF`Z%|LL;?VuAHNxb3deGyjM629EhZdY_$V zMNDCM!Vg83RAtl$r;1s8UDT|dVcKW$vfqvu0gV%G+`!jsJnKV$1i*5DzQ_j0LB~XwOL&Vl=)zi%}Wl6dbs6aL&mx@~v6a-@lCJx^|UE1$YS!*_o*3a5gqs zTpVRpT0*gAT~?icWgIaIC{&EgwSLfY`==Ggw90evW_VS9Sm#!XSW|zhx;+oVB!Tdl z8=)N#DxC8OeERV#@ma~6dQx5*q6Q2)AnRZVtI{;iV_j?Rt{|K@yQ*7~Ba9*e_SLE` zSfm^@2?Q)dz!_Xd#~;%yk6vPWv0Cjld20}^R++Y01iz|($I4_8IK-_ThK6M*@8!tW zLlD+LyL-1OvKcvW@M*FRa|}(jT8R}2{>Phd z#01k=IZ_chR|l-X)E(*$UzIxE+@L7rySA-EQ39ldP^?Mi_c0jj)d3LWeQ zRIYbU)|>zpBcO1|{~(a?TlB>p*N&F865w*BHkzj2xLhBQf1h3OqKZykr`I71{i<_b zWH(|+Ec>7i->Z0zZIv#g$8A>v4(6|K2H&&R)P>`UDX1uqil`h<*DTae$O~z~Q_UNh z{!nLG#Z%1=TszQNHsz^iSytfdEK4BpPvBXOx~w`f4_8;idlur z;*>>cbw-}%e{r5*EXS&T{*uR~xL@nz=(s%LDT}DFvs(s0rr?TAtlxPOVW3rr&Z)Sh zwGFQ;a;d$rz@)x<=5#ftgo-3hZO4*nlZNOfbpjJKm8_9ayHkLNTUPI+A2?P zg|6KSE3B_sWS~dt^DG8mx7E4UFV6a~_cY&`?GU$Jf7PsY25~>`L*!u@EO^|v&cF63 z?r{F`L#Wxd%X-bl(l?^iMnD1 z_^P$ef3ovV5)|XH?P~T7G2A{@Wm!j;hHxz~nX(Tz2l>J!{VkP>_&{lf1Bg{Y5W6+Y z&Tc<=ttQBTwfRlW*@A3p)RSxdO~H-2N}#}_{N}BK%Ue)LMf;PhFT=)xz}O-F#=RvsM3v)%2~5YO-(hO$v3+& zV76dalHBOVj-BrOFB()RgTrR54@hxVI~EKH}1 ze=L8LjAMpjvhQbE5{0Q2>vcrzV!Pb(nFupWpl^jTjAu-S{_bedbXU}}tk~VuNAjco zBP_S0Gmo|bRee+S)orS$$v>R-BDpb~YQk9j!fQS4bv|DKue+`Be5n z()J}T)b*|6vDTFa*H-%G<FAV z*S6yUa7OtVGUmli&6uj0|I}t2#i`MQ;P81kEqgD*3&?O&bI#&4KC8~;XW}c0?7_0n zJkb-3;ahoT+f6BA0 z9A61`1K5f!?oGTCH1Fo?^?I#q*>mGJon=qIy+-7;>>X7S=Vf2tpsm*%yewQFHlgA% z++IiIYU;;V?8k%deJh(?5FHJ4NkYNGF#vi_doau@B{kkmeUt*#GDDH(S@`uGFt;ot z85f{#R?s~b&nhAO!UEV7p3b9`f6Z@VV8VwmeQ|e~)|*1cWQF6fV+!Ac5R?$AK6-s| zo}mQsq7x(Th#wIc`RjyVzL5WW>b)5;GW}ZjU zWu$cpHsh$!B6gLBU&dnRYkvbggRWNj`1b78;eQT$btu@Y22Q`qNO3&-q#gI)r@h`> z1TE{`M{@r~cmcxo)5md?f6R(rmWuS=6=d%9;u-xy*XXXw6S`@UN|e+h;wY(`f`NDI z_i4Wt;Pfw){U9 z9y-2|!QFSnj=xPI*(-KMAR3oU0%*Jq@=)6|ak+Kv*AE2k5Hms4e^N1G&VcB8b}{bX z%cI^!R`rTX+ua*+4FT&zb>=7rEy}izKEz-x$Rs!^uQuz=6-P`}z z-u~|2Xm9_iy|>??f4%(&xuw6AH}6_|``g=Zv`_wXHrgku9P{_B@UT4lX)Ee$$s^cu zQXYY*GN(|npM71^$=v0hacJt=O<_`N#GqxDTFKC;L!W4+(X#6>=2`wIRBaXHHVJ^J zEdT(|MPJJ(EjE?^s!>xmi*(NWZ=T(I^ZLp2mxsSSdf3;me_}MuxiEg5>aZo}v@ZMK zfhkd(_GLfTpaT_IpFY>M(m0EXBK#QXx<1A(kZHkWN2alw-oKaj(8QpZO{Y~J&5&(k z$1y8eexkFhMVQW#NZMUt$>VgbV*cO$Ihg;KZ@~ONlKx+Y9oG>-LB$1+j>8iz(^tSSLrYr~l6 zOHY*F%q%Eap!GWTFH2R$9aNS5sD;?Wj1{a8SiR38r9s7ZCd8|lE7NE;>gyJ5YyEfE z`eVD6`ERsq+3j8H7uvNfxmmgL#%%3c&Oe_cb#K2>fByELvr+!0Zj`>lwzXC+;5~kY zIx)pjAjf|WQfG*f5z?YPh^ozd%Y zq1pPH^<_=XNJ%uIgf; zc=?!z2WVqO@#b9_Z$6`N^>^<|6$n(ypvv){f3>E}-nhw?bIcI(WAo$ynC>{OBFZ)# zhdeW~^TIgK&NZE72Fw$BXtD}X?l_)n&{-|!luxhCXZQExV`)q~uucG>`u<&T?_s7lxzQxN ze}*A^5vy74R#y9j2{^zm6zcM$V;jrA0YdALmjV~DOcz^JpChW!{Lhe|kN`Ft+7h;zgH`OlDYb6!0u7AH%5wT)ApF zf}Gv>ZrvdR^LEL=8mI)@P?1*0J(9-k0?AB$yA2r83$=__)pQyah1!=7TTp6bge{=_ zgV5=0k04S&f&Pya12Ux~o|gZ>Kn2$dD@Q1-^k7Nd*I72i#{d|mBHHE_krjONe_Ype zu(v2x)-Y9ALl9>EuIWYxmjeRLrIw9^-t9vY72~UTHjdVGj)ctEGakz$5Uk)aofcpf z&ulHrv}~v|O9wO>&$Ue7Ww-f~3@Z+h%-ogfA-f`@_Cg$dn6f$7rab#u+vq*+{j6Zq z8nV8I{70QH(XYfFlMqI$x01Scf5KXT+>T9VGv~YMskS7L^BS_4LWvKGVvE-4#lC_yzx=b#N2GdZJ`yETGKQ1NfEX;5E zI!gu9`+KQteSwzfTVQ#WeY4+MRQ>T*Et?CbBTH*B^v9{fa2E|DE*Obpe}_2&aJGbh zu1y;-F(rp1ava+yU{|cO?IkmnEF%ng&2U2AnHYyq!ZQ>C{)5(d&E)IZHn@dQdc4bu z>rE{XpD6IY^tSGmQ9^$Io8duR@++;kRql!T>pUtx`>~nM> z42ReP%)2{P^!cz+UKi8se>@U457X@IJWC_gd@nkT&*DY9!X!>VGvVv0!)^>mVZB>n zp){jYhqBvh7z(ZO1`9|BK@bctwmn%LPgrGAS@*DBhG&PIf}yD zY6Xk@x{bDoVP}O-=&T5@(F)Q51vm|g<~VTkD!z=+3a8AvEci*h>bL^Wn zexuzAKY_xE{w;KV&Mk}>*{7-~xtQeJMN zhBW#DW<%v@=KO~9%N~90rtWmw?l?5uWff3tlr&{;9(spgNok*Tv{##1BJ zin-2;MaNmyUU9C0W@WGVphd0qb>3v!+l%)1`PH10f01$L4wVYW(a)4VE|pxH>d49Q$@oeULl+k+cG|N*H)TwdERFW}@lbS>e~e(} z611R%;*o|`F!*q+0{6?tx#pPKbAN3nj@RbP1=e}gdTk7VDp6!a`0sX&bxR>M=}VYMp0u#Oh+j*A3SCdq~_2gK)F+HMm63Pr{|&Wo}qdHi0n$f{%pD#I}CVRg09 ze?Sk^*RyJ>Xqh8rA|cpPJX(9T*4Nn8;uS9*p)Z%>GcR5#tK@5I!>tQc=B0)jtMwYc ze$9)oRN@gYUds*mV^qG7nBn9gV~e=O>3kP9mwY#|(0 z9P;96jdob^kQWcYgzNd2R386l#WP+Ue-cKLZD@M>LTDcMBC^|!9%zxi$BTQqT+h-2 z%X7eILctBFN@g&HPO^ANb(E~H=o0%nU;!mTqQq^?mhSJTs<9bZ;EQ&rI_JeR0`^N@ zyihvu3H8!32+m-yI6VcGJ0=wIWyDST=rJ!oDIfjX8sCU8Z?p$)XUaWZ(l_^cfAOpG z%^UirvG9;q9|!4RaG--|^S%bQ9iYc5Yi(vK=jXtpVxREh4GsMrv7DOyqc{hePO0>= z*=$;!WGOG6Xl3K|Wlu}LH+9tI^0L-DO-jd#F?nGrAKJSoLMhtYkUG7lv{DQK73%Q9 zRtj~M$2y#NuL+4@{zamqeWQM9|gSdXn~Cy+!YLaUu zy86Cs-oMDRuNNo%rhQdfew3~-x;9v*Q#)T zzY391sc($KN2f1dK7ajuwd(hEebOf?QY-SQerg&0yHz&stDUP3Ln-A+n-?;eipYdbT010?f)=XdQomX&@1wi@zIc=BSJGgq->0_Bcr~ZC zEckcF@8AFL9pi6zCz^iz{^V-CI{EG+tIqj%|NCAJq;YrhpxL0_pWOM5RUf)`;OcC9 z2d+Ny>O->wS4&=`ug4eoxZZwS6`F?6jOAys-`eg z_xH6b2Xd~u7+2>yS>#kWi3y~qy!xUP^=QlR98jd#0|5Wge^;+~^+@^Zvx>>9S7gv6 zNBmSv^+_sJ`}Fx&UVWx z3s(0g)jc}9KfYRTVZ-VHubwIe9ByDk!aV!?$|;4q?BnQU3oQcuv<*`6Ru8(;3g*yykAUcHwp%}Y7w)w9}rm$U$^ zUP!Vb(kGC=H9nts^^)5D_!}Dc>#oMhI`4^Q03!)iR*#!TP{sFo^($5U<~pD$l|I=? zL~ISvU3FY1=GbECadg6~d;9x}sdM#atPl~^9bP?Af2zCu3yFy8a*K$l9_e1`hXVI4@$iA1SHRPxe|n02 zIz8?0e{mj-1>+(%tlxR1P?=SW%8a%rxB&~j;}(K(1*DFFv>8u4n_bPVNZUFckJ7ci|iS%P(IqY!+M$y%wB ze-Con$;b!!Y;&jKMbJ)zL77H4DASZrOQpg2CLcerU^;Klxx07M@ALhAl4v4l&yd$_ zBu)g7m``)ER|-`{fIN{AskBMkGovEB0!Ov|KFFq6q|m%;jmVg3#;1z0@U)OZKn2Nh zIN~$SCew^OK5qJUYJoq9k!T4T!kb;9!bQUZJHH1OUYC*`s-MiuU znZOnWFOS0$R`Gn2Yw2-u!Xmg7IJnZWZN1Z1KpJz%p|f~0t+bRCtkTERxwxwre-AZx z!KX8&x#yjeP0BiPibV%>EC>XO&9NXX>;s>k(+Hd?oUAl>Qd!SwORoPADN^J&IiH?U zVM{*!NQGT&b1~B|e0s6TwoFeU@mxF}7LV!)#HNq1nt@Mh>uKjXpKg; z=MG(SG_u(AImfdJ=IYoQj85Lq{-)pgPJ!gT7N%~KA$xmT$)yYL>CqUbv(}I!X+w_e z!8wcRbK<0s!;1bsu=e+(|FJkX_xGdkX;Ys*<HHq({@Uy7AN+we|~FT9j0Yar~lGQxBU9WkF6JuUBCFbdGRJzi?TLeh%+?x zd$avssmpG^Q7UslFV@U3w_}Mu)RcpcdwWyo7?H}!dg>gv!BLlc!l%yh^mqFCjedTi zpC9SxXZo?|$D|+o1P-sk-7`vfK|epy&rAAwOFy6J=P~{KNByqD|j}UeyGQr(E`%pgcO`4Rp@Z+HSN|~xmqQu#Mo0E z5C3F<6Dfb6^XX~@M|}EZv_J{{^AJ2N!h^nAh4A_Vu0Qem!$lcARSLj_=XC)MSZPjJ2R!K-SOH%M8 zqpB-K9|%&{mKHFX@`Qw@N%9TjF9oN2Nuit$PC$?+B+bVs%|T=ss9MpjCsMGA1XxQ^ zhdY+AD{m+f+NF{iPv%M!7Rovi^4l$JfdWPP`kW^V!s*4ORte*<~Uk~6K;rBEnY@fs$oWnvcSF63Gri^l3U#)~@D{r)L)ZSM-QDm;k=T2CI(r=u+ zs=@u0C!dv%UU!50s|xNTo{;c00snxm9gKWM*qpSee<&n++q^v5un`@c>qH3W2YR`A zK3)vMQ=Z&Y3V(1*7LLW-gj0SevV3e$Mm3aLh9o~8*^KYrJ>i+&oP5S=4|(!HsrF$_ z=N^-QJ9);FhXjNU@oXpIoV?_Xd4Mu^Nc&Q-_Nof9YE5>v8gokj`VCD5~(JtqPwmw1_2-VQQ9QpzrfUQG+LMI$>Wn5O4F(2YPfI z-v#zY8C7DOlP5eOO?YzWTA;MRAuGmZ9UbTi=%TU3I*WvrLOprvPG9omj?#%AIy!x+ zcKRJpeo*rN)Mjc+r4rnLC;2#e0$gpaF-hL?f8-~ngx}S52>wx$GnPCSd4J={?@HcZ zw(@>u$)(8qBTs%Ip#9t^MI@mrlpcx2lb*ixTDb58nf9&J+c^RkO*pQoLq`8?;8Tw**wELS7-AA?>ty7JbG}TCD#7_ywX5Wm00+rumYN;>-rv_r>j+UROhRX z^gW>5srST4L8uGaz>|T&)tfDbqqN zf>>2N0h*#sZGOh*3XL=W*pfR;=4VhUPDOnz@6@8(El3%)fv9BGY7kYoLFQ5jmUZ zulW4YWd4Xw{y(2f5nR(am4=zWe-c4%wD~J(BLI3^s_rYFD|F2K^`8sULh`f4hhKoutV4}f4GGrpLGa3=87#qS&O`$YWS5x z_XqL&t}gaSE%s@v86xq4_~u!=jdc?b>#|Op#D`ray{K~n2_#nFTR#7Zmc{RKS0H-~ zHvdi4j?`d};6P1>$VD(uf3+dy)f%?C`R|gKnuA96AZqXlFNGm0uH?olxXB<8PFibK z=D+Z{qMx1rs0dkWcE5H6)tV5i6*6#>tMz#Pi-u&UKny?g`HutvYh%4DHJRJOw)qsr z^>eayq3xl3Po8^}Vbe>m7(u}2k;_&lIu zHl$gvqLR%bK1VUue5jA-BdmB<@)?P-X5dC<8#Qx_8K=APss&NloXK&fQbu^&G?-2*?hHvf1erpSZw6AdJ~}VIi|1z zYk|BU=#y}@f~!V?ZZ1^t}T&m;P& z=x0hlujuD9{d}dL*YtBlKMVRfr=Jh>b4EWO>1Rnle;4%goPO@n&r|w&fcg};ODJJZ zKVNFy$LtxOk??Bvf-6dp*-K@Mn1LJj*$dj*W}o=%rIPXS?Zt3X(kF#NF=@OTqY63m zsG?u_>@hX%KJP#JdLB*7Xx0mB0zui)W^d}VL|uC}c|Rn#$lI^WE!SzY`_jkW#+lB% zacv1ve{(0L>VzbRLtE$@9F!r`MFcA%M8m4MMj5nPVk$pt9A8oajU^Qpz(X<1GtiK* zY`ys&OzUQEj0f<;%-d!(6Sp*REM$S#Sau-@XcJNx^o zw7g=`8pRW$pDj7<><2!(r25{W3HtH-lasrvfA`1QWULJ)?`LmC(Em2k-`o28la)5%_{Hk|@%t0Kxn14S!P0s56aVi0 zd+q&ueF9H!`Rs=dCn?9Z+|dOOX%N9M%pYX4=w7Lrdad*5_jMN4*4MLlOg%@&5G#nB zfB7VC^8Ez%)_r}Pu2vCX1Subx{my4^2^PO`>pKFuQgSopjgfz*{ z$NDbfd@%cM(jS=pu>k*%d`7at+0RfVn_0VsanK*kt=z_TCJfiYE>!4cVDf#Meo)@`F)KJrM$nqdsl*>eh1cH zE%jEa-yka#2mV+N!o27>KjCm_tJcg!aNM=i`%}{);VwaC{aUQ3rqm8=Ua>`N7(5;^ zFas9GbzJd$zbNXF7c;M6Q5(O)e^+Z(15+F;Mo8q`JjlP7j(iXDyLa`Jhv3noB#Gs7 z@aXw>Zmw2ZEY)Gk{@6655(~7pRg1)K_A;7Bd6Z72H&Be6un3Fv|CGHCQ3Q(5xQxRj zE}~g)&?~C*DA)8>4ho{J*eBwN^u@I6SpDV+-u-=SjOgK-Es~C}I@IaWf0`}ke23}_ zEVw%l=CegtTx!8=X-8qXFy={?U5x-ZB*p^~ zFxNo;CY1d{SN6pmp|?o12>oxXJ_;6Ris7Ri@EoaBv$1=O`7A)O$o_u*y>vf%phrN- z9_M%Op43}mGifHNdIEp(e^E-o>SfDkpUAExXCXIPCh7>k&+2og2cca11<%O35*wUJ zCnYSrYw5@*fI;PAu2uSK)t)$D%@OnX7^vt^TBRS<9Mcraylb5th}VmmHr4m{#ehy> zu?VLGYsof&C)7zaj`d?`&IyL5kH(r3s9v1ci7CTa{PL9Hx5`RwX6%2C9e~6cJ0j5r+r>qLO;)P~h1F4Ko;Xw{C9MXcXL8E->e1`dxA&gDdGxCG zskaEhWI7Tae+%%4NM2#2D?a$<_479mo;-TE{ZW}!(?vAv{_4@om(O3m>VtRRVy5X@ zL_SgqR_9hIw9S$!Yj?q~Uf+BDrlSi*8J5+KZw_C*dUOBifAIC|!)HHie;F6Ast;#z z32vQtegF2})5C}Nc76XATs?-nzkhuA=;=cO{!Z8f(jfJX0wZG%Zh4ev@?*bU_Kkyt z#fyhOP(BXlcIjfEu<*_Cy`k)vkFfOTFORm0ZKjCQjOQj#6v|+8c<^Z^n!>0%6Oe->!r@Pj=UDe}zhfm+Ud?fsPio{oM9z1yT z>eUT%Z4b)Ya9Q6DnlB?s6J17Z z+I(5a(AkF_?bpBcde+QYQ+TxWyUVPAEeG*gn7nMX!wFt+5 z-If#qH4Ad{7);FAaZ~t-&OYDRWMUTUkK!zSHC;q!A8J*coEmHae$YMOwRKaIETW-6V453sfC?G@L}*;s|{IjN!n}dZXWU ze-}=4_VphdvgWmRA*b_kbkYo8sZ-@AI(vO>RU7Wgki@Ku)Qx$Zlu_R0T5FMXR}CAX z$Ra}r;Q{SB`oUzwZ)DTguUg57mqAhg@n-0u{=?^|&z`?Nefa3FNHojyK%2~ng@^zGSsoeLHH)m_q z(H{1iy<(qFboQJto^^Gq;T#c8r-BsG*(2==MU2~ICljO&o-t%c;9+go5Z0J`e}7-Q zO@Y=L9RF#$b}ETDI78U_QjqiYH_;jgRKI?Q$@cg6pqEO6u%2`I%r>{r{r%_7TYz)M zo{Np=-mTUrojnC==&bAAv zH@2%a*!DsRw7*T{&G=*e{m1R^e`)hOsC&UnRyUKUtgeygtp1vlH=EXJ+ImD4+Pfan z4bl``IPUEMwb!J|-8`-L?p$uvF_SFh#-7}i)1h zQzJ`XMnzOgKEF=T6%t({OGhZ-qxdvF8Gx;5x*lK|Nqf76p|=l|y9 z-@9@4Yt#MxCIjCjr|w}C-u5DaW>48xPKGOoUDLYh_Ufbte%Njxfdd-&VY_h(QFkrU z==fm0*?fBS2OEC2-Ec8Z(DJkGma8OZtLc)T-fp|{$yVd*N%4nT|8cwZg4W;PZ(j1v zDcNebkdACOn=)^;c=xo1e?|0kbNhb!2T^P>j>O^q5(2s0auZ$a`dIts8ZcDnCJC3;fj@d3y&a}itc_tyP=ggkz>^47u!uH{R1dO^hu;Nq87WhN){60y5xML zFDdmU@9xCQ8wc+XEkNqqr_H`KTuHB^SQ58hyRMs#<&$)rL&p{$l_diVR%bsS-)@q^ zp)R2K(DZEq2R>1we;VaQT$Difh+9oRkbzvwF#i|hZJ(A z;vqz@n(~m^%@Q6O(?vA>9L*s3Q)pyW8Rbu2A3bHEk&*j4X;4#Wm*!`{9l5VqK zC59db0dU6z+FIAwPoZ=YkJFpi`I{T3&NVY6ML{l24fIBjGXT8N$FqZ68R+|PIuy^O zgKJuLeE&pee^34ZP~Qlkz9FFAxdBNLmTALM72K-`YkZ4rT>%6nI=K86gtB-cq+}bg;cZ=9_nU2bLF-$MJPtre`I#oJz-dA%{lRNgQmm=IX5)${>%M+dbd@Fe&+6#d#?u3FZjUi5%Iyfm< z?OfrjRBZft9o%UAE6Yf8_ymPer3_gg5s{X0A%jHCX;`4Pw5GcHl4R=hCfp+DJe$Ol ze}LnAd-+&XAGNkc3Yhr)zjVoKf*gDLGWq%2z~*2yG5dsUe89 zcqx8Yt78Z(Et?J`)4DdNW5-X}uj&+u8q<}d=q&5dI&MnBYMN=yj<-{x$nvHld$q#3 zm_*S;PU7v|QofO!<`}&b7P#UIeNt!(e|=nxZ~y(89TzN$SiNi(jjbUm{!iIeOFE|r zq+4RIMh?BXh|e}(yxNc(Guka^E{cbGj?yCvL&v{~C!y5-iK!dL=8n)t)wkIaHaC$! zutg|4!c9AvkSdSiR9&2x7vm^mRhma1=_H+Gw6qVulf0z34 zNt6KfJ^t}JD}fG60%16y2Gd!*Rxr+2!Z=_lD`K}HRX-Ibj_Cd)kJ4F0HW_i6M)}KV ze$X6ef>m&Mb`FQ};$`#%$5YqBjxev~TF4?>QKfWk@kNGtFV`%cbY+1+FXMO;gZen1 zEFePt1bhmN7w2#bI`6S!m9jwtANwa-%&x)@SzbO0^W*{yCZ=Rr2x1yBL2c8wK5;FepNq{G2#DUlM^#i@RP;_!`%z+QaIgst25%2et)|Tki}%CWxfg96Xc|hT}7eOY)8Le>38oGk}MN0_YUJ zXEAVJ3+QGmHWr*pzzE}!a#jHBpV3&lhb;DL)i3iZ67ERnVN&3IN2QH}6>tq0PjVS- zEd}J6H@4eNbWD+k*4$%ZD*TXlopJdRr?c#fw4>hRoDz&#HpLSgyWg~t`2=^2r{P6b zm86jxE7~c=sPI{{fACwDWDSB@JX9&KversP>qhC-L2oyv@DblU^up5GnJ=T09T6Sr zfEC%Cg2@|)X0ldsibeV)ATf+GhhB8qNaEIuaP zQXQz~mYVw8JE3c z)TYZSG=P~~qz9D$slY1t)^4#7R#Y?$Q)m}C?B+Wba@FobazScWz2$k5& ze~%{Re>hq*vu?LSOw^|Gf;mTvdwqS-swSpVnsLs*S z6)Hls#WyvHL``F;s`G*Ybq^R1Fl-F#UU zeAH4YZwgriTC?UEVt<39{g{%4j3LyepM7x0e=*7Er4-jSZ|i+~s#O@Gir43lrg#EO zn>Hy3`m{FYuFbde3ARvH4Zi#9r}`8S<*8c$n!fsxj3&w5YUk<1t>Njgdu^uX;thCF zJzjvv+Y^1w_AIt%VFiS6UhJr5dv_EbU{UUw8pW6JoOhcSU(>)wR=Ic#4$m+^>YhoO ze>d5rS38UDY7{g?NHke$oMp@CA8OX8oy|JhS#(#kpdn4O;h@J>v54nohvUnE zb#S|8ir6@CU|(Ta)L3iZo2VPFg0yFE^)ro4(T}9~%5Vw{@D<0Ubmc-%>E`?_1p&&0mhT}LO1r@Xz zib({S79qJPu`A8W^Y%8n-!@gPs!ayun{Af52WTg>70XWgEdifRXa$^Eu zRV>(fb}pW>a|W9YJ;5CVIMO5Be=$OiltA}PAS6l?4@@j5N)!)_Mnz`C@|qobEMf%8 zXI3wv)|>2{HCw3q2A)~7jj6AWnwk!k_NytZg^ktsB8j!|ikd+rF%@aF3xJe06Vbeg zphR~+iom~YL=UAZdMHUYkpaV1iiv)+w4mTM-Hc3W#*kePn?pvsg!~0afA@2(0C80Z zi3$pU0%iX34w-*UGXFJr?a>nBf$Sp$B~KH&6ND=J+W?2APA8gn6}Oq zcOXKDWt$_NEiQSgjjW*uBtY^wAQ7clY>2aTc=6M~fn^`(5SL z6{)-kf^bWbJgAV(zc-#!&}&R8Men*2_d)glRnL&?yw2;Ye}?>82leEzAy*wXv>FA# zp>`d|C)hOjRU$VuVEIiI`_1A4B;Yd?`_Ykf2nv|VL(q%gwUizAf9V;P5=j4G4WU4z zb^HY+8j`;Ot4qNFP4Q?m7MJkISfJYQb@a7lbB;rF+?S2$vpzNfeo^Eh>t+4sGibyN zY!E6I%Z(Hs3;75qYGyTK_f}iHg|p3h9H!-XZiqW+Qo@>o$BW5qoG{s#vGD3Pp;OMN z+N7lEWZDioCMN*6e*>X5tk)nCnXA&)UsSNy7%i1BsD-1~3b*1f#%~Ndv}TLnkkl#F zI)409hPFMd8P|llh8#!4r#Fope9;V`qVlH!>40+BhH^H^ZU^O-W2T=Qsc+ z>lei0Qj`s<+B{3fH#Z=K2H@e~rWMX#vT$m|SKJ!Y{nHkTd&8LhAn6kcIA?R@d=+K{ zCZOU(mviWHf7t?4%mpi?tb|ZP=9b`S^*o-$m1_GM`0P|ahSY0gdO)Wb#3wU^;ut`yQV%{nAhifAngU& z!oFS3cX7EOB*PZ&4UHfZK(_F%&-W5c3V+D6>b%buf1~U39)cq5J~+lfw~Qe_3eSZN z`eLYGtsybvucA^Ug0re-XwFN;24F8*t)%NZ)irIG6TFsl&B#czSp?o`Ay^w2SUk&S zQ6DMf+Ww$U*Y-@Lcw5Hz;5J=X98Ek#&mTa?zK+izYR%RcDDvCZha%9P^w}Co z8;iClNX0A*`Jg(g8jI>^!NxpJXBgF_%b`UH7AVK@$y(UB6n`IB69_9jhAAK|RT}SV zHILLxm6j?B=FRa58Uui{&hvb?`$2Xdb2L}%e|#76|Bt;d?{m{=68?Wb1;gW=K-|Kh zTg*eW&e%?z_=?9)o%F2?PQ<4n;au(`tIuLs_Ht} z($#(pYjrjlJ2T{ZXS?NWO?SRgRT3r6ga2l^PBqQ=T0hm{uN+Y(65c84fpcE~p!&jn zf1#px+|=P7B&-MYpZP^k$~?ZR>V0{7rm&Mhk4*Box!t1v6#SwJkZ3@?&w_qSk$d4L zJGaU&^kA@q*1V-rLYjeQ&c0q>Y;AQb!_|fTG^lnA~u?Rox&Au2$hXQT6-k znBSzcpunZ}L*YF#7m`N_QQ53&_bi>qf7pthD9&>-?VCPnSmK0%&|je61D9-Q)FyB3 zA-Y5JCD&O4y|Ub;O}yRiTIvkdk$OM!M58bWTV=4s8j9T9jW0@1ilt)F<~D2v z*uoWDF7x6E#PAO%FJBmJ+P(Qz$@?^5Og`)>iVsF~yjuy}O9mNf@;x$lHo_H|e|m2N z3X7TIC5jiEGbdXy{eA7lbXNN6Dk53or+64Z_@O+{YMp>LR3!|k0vDc32$ALc;e{70 z6n@R9+~XIHnM#5%eOXgO5Z<*G!1o$fVN-%8LunqaJ&e7D7YOr-IAgQrIc#F$!^0Tn zn7Gb+fZu!!u5$YR-X_gX-z&)Ne<+i6%K8G8v3`J=j*a;uaKH<9ZKvQY=5u8uP5W@!nPqwX{}T4b;8we03TqPv?pXsVZBY6oiN~#Z449Q0OX3uXx21 zswC@}Dru;!-1rQeOi*43nco{w2hdZR{{AbSxEbM?Yib(!;ze|h$G6z$KB9~C)&Mxv#&sa=l+p69WWF5N&0V}<^{c6|UK zwmy3n#ivP9Tg1K0R03b$EZyL`asV<3?Auis)B4P%uHD-}#!Mwqn0TN8UpI2`P2uMj z3FyMzmsxzvGsDJO(6}aVpzr`uK(4=UFq2VbCJ_l1BP?}!cLvM3-Bh7&?0diemQ$VK&Fz1?O$MTE)V_LfB zySvs)=_=VjGAwf)jED;MAr`Elz$z?vc2rgtD^sMX5kNL8?~=~!XigaD+tG}$^|hlV zL3PL|B8;W5qZL6nUv{)0Tz}ixjwT`;$~oLJ^m|Q9C(#v{18C7XBQ2r}hdSS&1>w7Q zUh?ZYVwW=S-W^SSH%XM}-KG==kb6DnS7P(Tp+tVJ(-PuWwe#Xa5X@o^qAN|;QgDZ< z>N_zw)c0OuzlSrTIHAK>d4B;`z507_pFi`^6@ZEq+(C*4zlVnhsecisOB!Ez3Ei!g zdhkto4|(nPu$u4l+_!Gdr|HH+H&RebOo|%3%t?t`rz!;`k7gJK)tzssLC~ckW7}i;rF%W9hr zPGsnylR!@5{^g{1Du06Lq+CR~lgxs<@1}Em4IMP4`JnkV5hZyS(Qn03$<$!GjU^JF zQS=AV1;mZsS>s}@*d7$2R|NUMnQ%#4v6vASUm<$zMDHX%=A=Fbv#e_<5x{4~HC=S} z*Nvrs6LIN0IK6keIZeLSPA~53r^(l+*@J~Z4Q~{B2?Siin12TJVeL&}=d4_2h*yFu z!v{&ucAKI-5!fg!y+q9w9}gUdeL+Q;=uAV45Jm$B;IFSH3dyjD))HM3WF4GuB42|@ z)4Fcg30H=&&Nj_>XT5}XRE~9C=lYW|cUc7)GJ7W;K7nDv07XgF8rU~xl$vtw5jR~r z0ei*>6)}5e_kVI=3Bt7&0*ZDa2#2|04t2iSL~o3u|3ghG&14vWB!so6Tv_p$LvYE8 zZOC73h!(a}D~oZ18WzkT%#pKj|DV4#NK@l2O3A62ST3=W&%KC!+*444opH>lAcKy($UKtUN4mgjFo`Z&`pR1pdxx>_!LnlOA5Omw(-l>t#zO$0hvZJYRBet~DC|KOGZmobx^$9%{+q;oN{Z&=Q@5dHOsD!4OWY zdGSr(RE7!-2?rly%-|;lb^W7Fd-7c@fp1W%7QRxFwU3vgVO_E!s8}5qUMnaQ7odT;uz&yn$gy~x!Bpv^PG4S-wPJbLAh=q zn50UMBoZLcGb~!P<;+9T21IfyFq-HGmsAxRkN9Ch(^Oy}j_gem9rJWu%RewxG{iD) z^xLln{i7LGf%AKTkS&5D{ghr^+yB33cQ@v=h$N*GO3=~TS0+6yP0IxuF z>dtgfPJflE%w{y1#@?hz=3ZlBI#UdW-pFOE9+R66K# zs{b{eXA%wbLZV?_{C^M+Dth&A5w9tFU4OOy;845~o;mOk@f=kpNG!n>A@g_!IxZ!- zUqX_rUcVQyp#Gf1`m1F_4n!VAy$L0s)6OU0ct=@iX#V#G3(5s5b5i)nZa)9^T_GNd`YfPXo>(CrH` zhZp%A=H|LDU%h$y^2G^=I80ZPO)Ha4RWrCt)ZPI(63xh4h$$ASMX;O@Irx6ru)0d9NRN4(R29I{9cm zCRF&+fT5sdY07Whna)SD-R6%Ye_S5Go8nqw7SaT7YGBsfnl5T{*M9?tW^M{8VWwOx zz3GzOBjs>Tjdu*t^>Rmj*3rBhnd|r@bk=y&maq#pL%pA5I@z!e*|bt|CZL2%cl}P?-rFl2Qp#%twh*<``0CG`Tl-eW@-5bpV6q0 z9u?BiJn7xV(o1Q+%F(YpdE&d%vz=smIrZ0xcTV4c7{sZ&sbCT;{4Cl?V>d{E@G6on zyma||oie9`8h;97gyf4M<7jU1o9|q}gkmv4vJ2XSk!t#OtKtm_7p=jqkQ05YZGel8 zFq%>td(#x2WT!zUiRpA5!-(KT+#^G_2z-eJQ)+X9+4a?o>@*Gy>4+u~(^v2$B7gjV zI&8ADAHMBqvFYEf)~TeMMGp_l*FyQg(4FGaOSs}pd4CZKvxHXy&R((xbjhI)PG#Oj zlCpCOXPzY&@9;5)5jjUW5whhlBWEiomTIe3Bv3@Du4*+>rV2E|dS`WT3VGQ+FbpH# z6~M5`8$x_5(jW(iWbqMSF(Nwim`} zm3N=?0w%MSZN{=!_hU5$3zjz?D_Gs3)s%9JrHT!Hs!K@_5IZklZnIQ%Q8Z5?ay=ON z0{0o;ZzQPh?doPHLHP(too`@y;8W>RgjJ|f!L~8i!a?RGs8m%T0nZ z@a!feler`%zs6;G0Y(|;N71qZ_2A#-^33A0mBrXbcW#ItXbd7^6TQ3f35<22a0a@5 zpfnE(U?8-v?7=s=mRLB4y(O;wn5tc-On<|*KNGrfs9ctYOy_7#8OxWrsh7+>n#k&3 zIja>2R?ATS<3HRq1tB_}vGTB)y-fL!_xCmT0Ad@yk7=^@ks*Pm;Jcf>w^db_6myFi z;gcwZ$mS-p1;XE1DamaMVRCm+A>N6$&3qyX(Q)p^89?-%9G4Nqkz6{6l0G3EB!9rt z*e-xfS)>#?RM0$$Q@}P$l4+o|^tDK4f<$_hY`5B!V|kp9DFN_dzyPsN0Du@i^c@aW zQ_(je?n1^$IEnq19HN!R#hc7-c>5K<@l6ZKs?>~rkV@)4dCRVhibv-f3fHuc=MFDR*5#a zrk|xo^6xk&7$QitiWAHo=pO}6%27UwBzNy@O7TybY!x^XxEE%1)m@k#Sbs-_hkjml zF)9$M)-{pmAix2jG?H0_NKFJgO$1r?PR0(LRWG&-S9U(CsHM<7Iu8YM(rq+0$fVk7 zd2;dt2Cu}7Qa`fUP8q;yRsNXCLP{lVi6+fewP7Y1e$vn>_syg+%Z;@0J1=>K99vq^ z&pB{FEQMOX8g-(%!Cxwz8h=m;8*#xwna2TDXbY2^_y8^uuSKZyO>szOaBMJDG1i87 zD>uT&TX2>lo0{o640#9Z+`-mIb&o&i6voDb*S^P z79#@?WQE}EhJ7Zns?qCR?3901D;VkEpxAkWpW^r_=f${xLqobgg)3IPeP&7zCA5b0 zK4=EPR!3VMq?Dt%fiJn^p<3ayJbyCJ%jL`^W>yl_*RbTJc}V#@U=NBpkns*Ji}d+K zi$UdeALWdx!GG@uq~rM7nG(@!jr@wl_z-%5rV>Tf`Gf_Tuuc+lCf@HfZN(H7(^gDn zW!fsjhq`GKohW9mW{UE9#1#EOGla5ZepuZoNyE%YiR|2gmA3YVvpWQR0tcDHWXL3T zn3v!{@Iy?OK*U}_J2G0HT+vKnXhzFGn`dB5g*dP|R)67Mkjto0D0>vCECGmbjy^dT z08DOS2#W*@D!U5hSh#LV^(@C&Stc$5qwke)u0?Nm@6Ls}0qA7bxrt&?0LHp57aoDt z+4tGQ^!>QvR#pf=#0_aI-;jEO33W3kdcs(BES2kHiLSe&==-q-rgUJv%h-;9$d!Wj z2|9Mohktla3FjjftwTW5#!J+3xzo|Tu~V7?T;igFk61wvrr?@8jOb4JkCpNQ2#(6N za{6s2ub}^!qQZAh^j6YC_(gK=2j|3hS@cU$+=;%EJoI7tA3@Q9vmH`BKUeDcUEEdu zo-2!2uC0XnG}mzxzVgKt(7tPl4<8fTFRc3Zc2>sj=(40FF%VeU8Q!GCL- zHh*#(AIIC%*>-gBkJEeqdHB`o*QfVS8>bJP)8XlVzk9zq-DdwY-i}V!ruoopoUR}B zo;*2SKN*FHasn8SD48Q{xY)RsUMwYTD^#v#DzuKA79nOLL%qt({() zv(rn{)%Bs2eqSGI+UWGsv>Kd_&X{6iw@PG8d z=>tt(*H7rsR{PJ<>CA1+$D3xRZ$}5G_YS{0)lPNTkL1W1Z*BeS|AL*O!Gc(g!T5Bx zwN7WJvu$%^Hrnvo?2ODtXRMzZe`+RJy}yC_uL;zr#!%Pn)7jVhP}dNQ|6nNI{udlP z5B`jHzSdz>L+y0hrgLe9lKc@$Ii-@a!09-Y+M`mMy zCHq+;e{N@uk=5vo^MqE`81)D4q?{t2t!B10`9F=CKjI&TB!6-WGKVor+%_n(91W!F zh5d#^M4J^Nx+#e0<}Hb6;Vj`3Y3MQuz1{Bh`NYK;xqsEdPtcG`L$eFl(SKl?WDPNr z&#fqDRz(frydz?(zYoA^Da*sb|ELh=X6%PaL}vNb{eFU1h%H#oJ>)L;1wa|4D|w2F ze$+6e2XBaLy~tPknVzk@K=fzj1-I$U$_w`N1Y9B9*o|*$d*NQ@y>Ktq zy~}&yUf$e`f7bT`{i4Ws@_z>w80$!p%QWFvO$to1!5+=%V=%1ao~y8^=v>UE4lMTV z*hwWNMm{hP^b1+*YEf#t#reSGe0b=NMGVkRal^yN(EblXt8KRprcselH=Z&J+6k@*hKSeP4?ViGi90-E-quK0D+(VOfOl z9KJT<^_Crc3;Dlr2Y;nHk)bzbhQ3*4=v!zl1McCZ)304Q{kr1x>)!J8<6dw+>Gb11 zH)?~QF?D_1)u_lNTn{`rO&%-=s1k{T@rC>1D0S|qnY<4CKuz^wYNMge6F+oQRFk;X zQTPIfRdW>PuI;u@d5~VjCpp z8B1{gQmg=f*-t(QZ&cE8QNb(>>E zaG!YTLx781y)fl2Ge1C4TgKB} z2~VRBh7Rygr?X8v+m7y^HpZv3O*hlEq1_llaCqqX!qe~yS4O&MS@WazqcTP1fw39?exY& z5fOUS8-MGC0ccCNO;TJ12c!O&Q-<&ehCkA`LGf(>A)cN4xxd~3lu4i$*ggqHZTQoH zKix6*Lbo;bH_*d@ilx}PP}kw1<~d#S>tJM=W9CD=OouKXCFWESCm_CM{?R9!9T#ptY zAh}9FnqiW1nqiXOl4ihL$4{adYL0lsI)DKC7*>-xWz~n#z%JY`>(?CnQID~yyY5`G zD5h`=`3lYeS)CFT3JY6AJ#Z+-gO;^HnQ}9CmsU}3uW_XHK6e*d_$q;}gV(f@miE+z z1%CiL3upkWEKrXd^1j!P0w;HP92E3O#OM)85vDRQJohSC>@x@!Dj$zXuT}__piHnt zj9`)UB6j-cUf!;Mx1wlv`}fbf{$-QYc>3b!htHlqdiUtzo5xNxAQLK~?uoQt;7cVl zV)IFWL5KR?j!q^qdeoUf0Avpw?equDfqzaWE=%@wG6`8MqGn4clY}LQI+?5?ic!1U zg5)VnUduZY{Qx_ou~_8M7*O-L$l+-eLdvrM^32K|;*q5gu6tyTkNzjlPe@naZh265 zS112dc-?ppTK)}G<=3}c?zwy95f|cU^LurdMH7Mz0v-p!tr6=}=+KdSO*{F13V-#( z!>~}e8hTpDoJP319bMpO6*REGDSHT6Q5{RtoAFqyVjoPVnr@(ZycUxHEIQ6YwFIY&_rIek|P;z_@5&T`D3a}YKm3b zQ0M(yIg^<-8tdGf)nu{nT%(nPjmyTw(Z>3*-;DPic=CG8JkU*6JPjfcNcO{Ao-=zq zThN>Bd-n;MYux#P4n1|yHMk%jxXOI0ZzzhHvwg=ce$i0Pr#AAhlvh-qrp zXaE;xK&VZ`!ZWjTluMIq45z?LrCxChmFvFmJ934h)Dg3%k`{=#T&NDFLQK<)`^43S zgDYmZCS2u`(2>?k_&|`sEZzY#xqt+45I$;?k+m~f<~|rv?Y*tJo3j!Yvw~tV@M2r2;x&_psm(@ zAE#>Ks4#lf3$(d2FZ`V_HIu?UQSN9%xEEFtOu(He(99jAVu~*PDz`w>&LPYw?YT}Urb5`7~XElnXHg0wj$tH9jpfhjJ%+C_$_p*9uFx5ytc7JA|mb*P*vQ@UcBC*h^ zbFFfiu(M(0LMvs}oEY zI?0=?Y>&?%TYpfgDF^GI1dZwVh>p^+qw-rBfW=@KlnytJNa5_Q*sO6AL#b?zJ%)Uf z?^=lQe#v%ZwWAWv@`Jv_Yg8;N%H9qFal|rKSiCYLeVO{1RgO<|M8hwL%QxaFI7~nj zk5M|-#c7UMLmN?&j&vvA%}4u4=3oP{f|s>3hVVRtJjF=&OS za$UO4EC>|bJGTRR76?iaDqDj^jMQ9!H#KBC!7?@vYPr*Yj*ujn&McMa7F=B_3AX{HIBk~dz zlXn1wc3~CxBXi8T*(={p4-Y2^h8ExqEM*ZTr+@B>`b@-LUl?nixFBUq0{4vGoHvHN z$b7j$dSiC#d;=xG%By_$x@$keuw#)dS>v$1f_^e(egQ4qB(G_NN^Y+v=dy(?$VV3? zpY@X~iIczj|G?ktvP#yIH@ohv3df2&zA@@};TlFYCqn6DZZ9r0h;_kPEy)B9o175}89O8R*;w#FZovmlIj`j1jepxI zP(}rmZsbXBQHSIZ6>ZI>jK%XXl{Z%@3qPVr68U7A#~bEV%b;rjyBuBU3seFt-#0 ziD(@Hiq`g53J1QgE#G(&yNi_w_ds^~@|tWw%fM~GHu7ewtxjTZwxA6bI6Mfs`*hfO z*-r79@f+E2&(t)A&6z~*6o16x~FB98plGV)a?PgrQf?8Km7{H;q{1<^Z zkTBJ%Fwe(lW}vRVz?VFdxm!e4Juu09?fbuYvvdhB5J~%c>PIw&1q8xAv8%&}svAqp z)Bqv93XW>N@K8{{SyFZ81Njzbp2faI9nNLw&mdkRnzPvt9;lx;w10K%f5DM`-rC=G zs#ad$t=20DqXJ<`U%6M1S1rz|+OK>=3_^#v`O4Dnq<+=1Az&f8oIPc8tR?}PG znY+*UZKq}$26GRBNU$gxY(^@Hd?Jp^snyY!6qLWnT$H-8GX-QUZSBZPj<<1sH$F&?}&n$>gl|bYN()dMvP` zh}HQU#&7k_ zCO*`ZdZ|xs_3_M06^77M;^J)D)dKEA)=>f1=|{4R>D*Qyuz$%;9;i7*Wq30^BkD2S zNBDS(@6`6ozK%^!m<@@I@CJxmbtOwL-87TF$vY zWF|c=v6xH}Ws;aPps9Wo{4+fY?%&sA5vQl{R#G(chI7h$?cSuk&qV+af{{CzBS2_4 zLG>an)XCc6j(_{P0A~tJb8+jKpy&Q!s;zaq8U<#}y%Wa7lf_#vB@!>+Lb4YpA_?G* zBsrMy;g}bS3mq&fq-rFPlv+Y)YVurjafBgBhzbD*R3Zxylif_n3u3O2t4N?hNHKwoN*fU0COj7Cs(UU=pP=^5qmPcl*Vov#^ddlj@1A9FY(T_#u+P-&nt?M z05yPW1V9IXrU%!1T!H973qjArD@Ag^s|FDcgGF;72kCYz!cc)dnSK=FT>*!ywZ2K9 zq1ahx7=P5=zd~pXnQ+E&JcG^kb}ODh=ZxosYiG{E$C(f z3%Z{(%H*aHza666;p|NO!kEQ4Jq?~hFy$G9@CiW@Ao36_!D7cS)uluZ-mL7bfTk-e znl8hcp~^et>D{E&Y{_Jq^-zAXH(7Cyh}VIEet%S>J5;#hm&Dnu#|cUy_fk4ka`#EaW4-$2{# zin2(A0IpM=*~m{g{U@C~bHTO+GiVdm((sl*^>dsb$e*5#MdE zK!05ff}J5O?Ay)SeZ1R!(y&m{rM?ulrr^jK1!v-t0R1|bQn(*X^|>2if$dg3p{%UF z8^R`F4LlTZ$BUrl`de@NR1Z>ZX!o~PciU=$O~kS9t|B_qhgiwI2TZP$JChYdWpOko zuS>47B>V@*mcyNtnFNfaZRt$$=9+cr!G8re+xp(f%Fj%A&PWyFefIbNbp+@tbYR6QFDa9r~nc?q$t zHJ4qN?g}u!qXBChJ#G3ib!S%!n2@YN7685+F%VC9g!eUQV`7mQ?J1gvAQvCT9Dmc= z{0*DfZZ*ww#3%jmkRJxIPE6fqA$`CApg1OC;*PAbI2-bN>g2)$%pW@@@$hbX#F`}@ zJ2S>QfmeM47MzM{2VsCivs-M~d{NEu5R!!sBwJuJlY=2oKIDFaCoi;-dKxIoieG6eZzB*? zF*;ql=gn;8>7xUp+(RDLE`5FqNe8;JfeI95EtiCX_q-Vdgu`;Ie4bZP48u?=&7G{L zQ<@}29z|h1jGUq<-mG}b#D8N}srN;gJ^>p#-0X6BE*h_t!=LOlPzyDg$%h)8L^DDe z&VAwprUo;qlgY33qR`o=3KZ2Oas!opQ~9ibK;eqdG011DWzvsivzPJH(X)R>Cf_<0 zo`Ql#&C+=LQrC3Dn?a}wlRPw@nmX$BguiRLv2=r(PsOD-i~JKi@qf7%4!HPW;?u<5 zcryr42R?{n10)&5g(%sfJA;VIp%b%E;3RP-kF+qaYjTV}Zcwo-4kDY&w(}w45xHr=yvcbOCVaCXXHJLiv+L^qR*e5nYc!ok) zMl#PK<26%H$g|G$4S&bhGlm;-q|8gq`2I&57LzmyX^nL0hoI;+&uo-JB< z_EOi@!l`zyFF9(F7N3x&m}bx!&u4*1Ia)ji`0B=(F*U^ZdXMIb&M)ap)5wM)&S>^| zEk$oLw`D>(K_x>E|*T*|Z zzrOq5kbeF0XG_1nyN&egyE{q0e*E8(e*OHn^y|~4U%&r_q+h@NE&aM#`t{>Y(yxD& zrC%SJ^y_CK^!iCW{9clN{qW~Yzka&C^y}XL9qHFSS%3Ov{Vo0aTl)34^y_cw*Da-A zW+DChp(_1ignBOhVzMhau_E)D%K2{)b;;Fyj;KpfykHuxykPMrJfp!aBw6OQlB_05 zvP_g@wf0D|P-Uak?3b5qv3xT=5vP}~`AK4~>sy3s!Gt59L&aq)k;0&CMI`|W%Gx`E zvO9>zCV&4z`Bsw)tcV9b#wNdL)wyM|r39o)`C3^O+0s0hEzRp?OY?oQrMOnM#KcO! zX=svH7ApzG(y~}-ejBlpybs74#7dl%O+=nV7K%8IqtIoYbu!X3SiDVPN22>Z4+D_^_i<9aGf-80O5!nF57$YDH=oDq%sUs97Q(Wv5>-(Nw#@=<5A*n_Hd??kXz=D& zXz*k2wt?3dg3f2RcD%0RT>$g?YP~z5RUsKLV7aA9AreDAN_vA?zkkKR zFKhIvC*kbMQZu4HV^^St0o&=O5qb&FZd1aaUP+qfDGYDw1X{0aHe2$M}L;Y_k%3GxL(jcdu-9?$b+^d{`%`H@^Y}8&s@;)CPr6 z1S>aQc)^=6vW?Ey5H%W=UyOC&r5W+V#WQ+N{lY*H4E05UMjymbWcAL$u77|uQ*>l? zq3;M8Qnty|&0f1MEp=AQx)w-GT!9W(=M@oVn2RvOdJ$$= zE5b}2O~a_qh7Xg0^y@kGNnj+u`;P;(LWAqq{DlN4_w>Fq&YOlGF3@0e!ByU#iFYmC zk$8q&><6}p8S(BUf~?BB)qiKK_M zN|xn=CvI^2ELAaIn*yuZYP1AE3d4+(?gr5h}0K7S7O${fAeu91f8 z>5|S^Wrv46khA78HC5h-PL{iJ4clhlnRYl`T zx(Yr@^*WR3$sli}UVnD{(a0l|6`KrI1JgM4?K`_kxR*nORNHR-xp^_i&cL6S7k&z^ zL%>UcNG^(_zji3)?3CIA4>&aiz@7Z`OhKUwZWx%y$$FuLfq$jfX$h{T#Y!QL1xE^Y zVCCBG!1%$|aCtr{eye&>f1*Hr>)DP$vp+`}^jONuaGAO`9TVQR$Q8ktruPVltHpjRdsSYtQXa z^KW-?xX-sCgohxbaIAl-A~PpB?xw|@>_Hw}i=3o~hkrZB?%j^lovf_LygK=Fq>yKK zkV0PmZ%85E{Mk~-%iBmHFYhFUeEzo-^3$Y{FaJVP$cJSqa>r?(U_a)Z1_p6iDTdvk$OleTGQg!!pI zroL}))PF z;gZZ0aO%aLK7Vp(3fVXhX0BC z`+qtR5B7cW;=N^h*Ne<9%b%GJ44tvD>Et$ABguM#lhVw+@PWs_6FLop83<-FqW(x} zl;DUJAY^ccVAm@bl%CazillCDT;E#+wi*LQP>C!eD)7jzl<2CcAPkOuZ+cdv$C79e z!ivj@r&lTn@Sw^DWz*335KbCwp>{nIu7A-Wc&9snn8ZY|YZ-1myIaFC*@O`d?2vG% zV*5zptpk{_SyKt9=Gf}Pm?~G{S^+=C_;BF{oGxdPKYU*<%w~KYDQPI{=(B%v)m8Tb z;)&>Bm$q_26gQjAi1PgT^XJN=Q2F)OUw+hTEY3dW|BvSVzmr%ugud+-foi*jg@&Jxn$Eb{UqDfQ&~C~o;m6N5MSo_CtjTHm zmoZ6Z3ay-6iOHX7mAuC&8F1q-95?QoCgUXk3<$Z`?v`fxci9q4;6GLjjBwKJ76X0` zsolii5#Fibjf!MY0cjA%ut>1RdMSfd&0vo8vE8cHNrAz-Q^h+Onzv~A`V7??nm5(Z zymKdSY_n!qcc0io-6Cdk(+le(fsl# z#=P?mv_4@=-nEU^o!hwkCN)35MDu1$ad+Hu*EX7WZsUs_!FNR!cYlZO+hDZMMv7km zgIS+&kp2+_%iT}w&&JKoKLGW90X%7b0^RXPkau?{Zte=5x53Vzjo`lkHa0(jO#5tH zYJNU)y*pLay8DVWKjBdLY@Ba?0#$n}_JoHFM>hI5jF6o((EsAHD&UrB9{<>q-g2#> zBf)30$j5NsEW{(fjepYdcB|p9gG{+j@I{iR{7|s!JLaZVt+}ZsyJNG^9b2$lwkc(5 zim~QB`?!%RRSrZy{oJ2QFZ3E%Z?U*EZ)3~HGwJBLA^nYpKdjY=^wNnC`(dsmu z(MCe?{;ZJ$Qb5#30V5vjz02}BQx>W~Yj|&2w8w(g!7K5c+~G+)++=o)dW)6bkkFwZ ztYU#=b6;-|PS!|S7}?ZF-38ojkhzmGZ2^=+Vn8Ryan=F~=a4*Q-J6l6v$C{+xH@xt zjHyvYJa+A}rhi5f`Cf|9Tq~GD$375mKEa@ml-+)&a9uz%G8*e-;v`0XHFJ0(pI@!8U{1=>IbXKt`qy9=6tcW!>mk?QQqWz}*XoCXgT5~^#Lw&@C$7gjBKn|4dm zL@(e$8d1&M3l`73fWE*GX2lLDBDI#S7sPh=ob>))cTn8<5{_Pl_8OAACh7W7jj20L z8_89Wx__6ArMFo6a6?Js1{M-w)!6FRNQ2{Hta-W}XVPin5%m;Z8ORgRktYC<2fK%0 zdJFgpa1pZ$2Iigkqy`Vn{m@Opj%5yk@MJ9u)iR??Rp1HMaaKcE)ZhXpaY<4;^?TqdvF@udw)PwRTroLriIUCNOn75CnYD8tG;xe z6lZmQhocGYA)*@14qcVbg@Fv(Jj6O>15ydch&G3k0&&_Bz_2N76o5lzz!|C2aK&oF z>;h752T)@^3u#8gX0}JXmx!2i!<(^ueDs8iUmj81DGdKSJQW%fKb)SShizuxwCZbt zUVjA?x>5SEyH2>|xjiV)3eZX=AX=p5>$6X!7)Rq;im|qAb6h4Q zN2t$s6#tXT7wa6U(@{Jw5hxx~GJ3%1g9X(##g_5L(w1C(r-7>131vZ?b^QpBSAS63 zD~?Ql`Jd*=nWUhT3NYfgW)&0Q?hcz}Oz5|mkl*H$ta6WSy z7FjxGafnL3H{4I3Sg~bG(?m(J)9jQ~ww;}jolOVmxo*qZ9?3VH9Y}NUlFCN1V^Z2i z_F6s;C;5GTe0Z219(sa;U-h(vq<c*uV9x!FlT#bw4{Tt7naoadA~9^IznM?OyalxoZS7BR_$b$i2B z69#|oth5CQ3EhJY_;}CttSEVfB`=(nc6D>f3($ljGiRAC@88dkmjCnx>eCk*@>sJ2 z$MK~JgeJ~Qi|6OsKHgkAKYu(t7w^0~WpIIxos+9l4+NYK=e9O=Mq>dDTwh^I=JGin z%jb9;ULUVh-h* z?GDqTj~Zf}wA^Ve)-$j>5U0-JAuD?zRV>#L1G*B9-o1=#lZQDqoPUsJBP^|vthvmP zYf#LH2S;Om9D?HSE}MbA(IDSCNy8N*@76_z1PHW*O!1JN(Kqgb(Qxx3%XBDl!|_lR z%@_1|tlMSg8)>I-^nVppIl{tUJ5ssvSL6L(zshSRU#a7-^s%1VQ!;ac9g)kj=;Lg= zoskG;ph87XoE!k7!^4QIc%EGvc2U%}+HP0m9OrX~E50hSoewShoLs<)sIMdFcd3OoJJX zX-pnEf$=Jal_k%LoDYX;6jRlHNRFMrIA%*vo)#I7hm6~_kI5qr9OOmu`O&bfr0D5G zF!r!L`w@BN1m$h~+FAXo1!R;jvPx6|w<=K)XdtNoQFxQUQ6*|+@u66Gsd>uI!eRr} zW#qhK-I|p?iGP%Qb;Pq+8=hPAQp~zaR5s@-QTgQZA*n=_=LWoVzj9t}w@mc>!I=zq zjBYzppd>~pUXWZ;Vb9sF-)=FKS3yiZuH);kNFnjCUu3$CYU)p%&{+B(lI=DeeHF!f zw(NGhnYh!lMGTRsj+sXGKj!nfnvq|fg{QsJhbq*fqJI;CWc49Y$+ymOxFe@{y;p+q zgsk;Ux9dt2DCl)@st*gA}d`fgM;JX)xJP+&&apr!;Yr;Q!*zn zbp1%nx5LTd;mhsz5|n{Yz|fSubY5<^ix?O6ty3pac#)0C_s+uAHZnZeuZnXi#>KK< zkm_M)zkkj2BkrU7`}{aKJk-8tw661(2`TS6JV6j6SLCC!2(<6X33*N?WI?XTJ@S}b z=JLzS;k?BE&ISK_vGh`U61h_ft4kZO3DiutZhld}?OKk&$j{Q+4 zO~M`0WQpeIC`?@>&Sw9CV{f<(!Nhk#E>l1^DuCyAyK}17|dLs!h84?QNDURSqJG_ysp9^1bZu94cb=ih<%t0 zu{vesB8+DzJSLhNfHi^762Ap|wsO)hu^SaBFhSo_E@Lt}DtR7$eB(}7>ur_1lwVTm z`F|HWIrGx*uc9Rl5-~B)!;h7eRZ>YWm7l~ZA4F8yS=FPeJ_ey-Zl@RhqK2qjF z%vOyKT`8tY!gCtWeVArOSSQc`K`LN&)C{E0)uajYXI4#SG-5RsjcHtIU8PuR5Dq6e(D9)WG_f)TSBS2KxX{wGl^6aE?<@YF_w)GJN$t;>?>I!>SrxQ$aY zjI{bmT~Kqvt}#s##lTB-?k!#Y)GCpf`XYaIxoN!i3yA-R*>m%iMw(NtemkRAa6nd* zg@mI>fApyRu-k{)aK~2xC;uGN1-&fNDT9Yq6vkyph7Wk?|H4n=N$AhiERQf=ywMloh+spPGqsxkB~g|ossHJ+z1%JNicth zALfz`4T<1&=EC0v`|;sVkos{O9wHZ9-i54Kgx{jbr$yP{F)g00y&%M=Ic80!o;M4p z__*qJ%qBiX0mVY=G+c)18NK2!;OI@AxXF_JcvJjMr}#eM-0Q@PC-{?uz`V1eOk&py z=4&A7)Cpc==3Se_(4k2J9fS&}9zK8h-WhWFe)wS>ek`(7>nk?NIlM?nfY0%3wW_c6*3*-=R<1_f*jZ^%&guhGIhdO2+&eZIK8!Vus zvmj}F3%QUNvBsLCrv?!A}^cG2Abzb20dN z3hgiW@+@Zg)Gg?28bUV~OB$bfP-uZmyzp@~7AyPrv_u$M#9??20I_uOGxL-< zaZ!-6bdxjcv*b%?Z8^mkR^NXzI)nZ!lN9r&DZF{prMCz_xGQ`{kn!j=fo^z18Df^@ZSi3%e5u|Js;M-2R%EZS1VkNvoQ5>hN0F=_M4(Ci6(zcNaSBdAvpe3 zeed_R#~u)Deeb*gci%sUnes!QuP1{T*c%)mS8jYZ3oioxxQ@hNJcKcph7YOl0{E>E zK3CpH7eH(k28(buVNY!9uR;k61r~xq&_;L;++fyBX&QS;V>$C#idSTI6X4#2ymdagm!$ai6mX4!VlQbpSpy=7&~J3Kjv_>+5yN8eBTy$i=TjA3rAwS8fX08{as0nC=to@@cY21^ z#MEVAh=&`KC`MQKi+d*aU{G;53HfONkLf&iSM(x`0sY473Fcp8{sgBYaS;e%7G3;Z z(iO!AmJSopNMP*PcCvDPkN^6q>z}dbIK9FL=z9|S-ppeOp}&TMOkm6;#MH=*alVtt zUk7K61W&Ex_c?$5^_f&wNPpMZiwh69Z#8W!i}T6vJ19HF1$0C(n}h~Q1|7^Z!mwjybM18Twe;1ykeW12`UM~k_UtRtXx=qy(fbQV4%HfGLZ&Ppx8mqWW#^5w9I{`5G; zi%EV*zleCyO&qcEgr?Iab6xs#GY_kY@8``T8YU=3iD!zQT)lI;H{#`Da$UsB#R?)` zLYH*1Sk!+;ycE|H`&996xvv=~5-hGz2LydR?4`{z>Epb_*1(^^7deotr%c zEf(Cb3=1Vh7FVCtc~K4A<1a31tMHjOUA%#Xt%bL*%qwq64^maRo+G+kK}9fn8M(oX z&Ooy6?Gvmou2>g56u_r@vz;?%q(|;{tGSN)=H-9$XDSnJCz8$`Q?|>FZVb*;yJD+X z;ChBS93Oyrkjj!krP@Y{z)OccE%*aN%ltzTcGB1)0 z^llJN-tB6=#OK;#MK*KTNv}fRo5F29a10GMm^A{L;?aw{W6=!QSN{zq7!w86Sh! zq;|jA(#hiFwvPPJQ6HC3LOhRMw|qi=`E8h{;i}eeAGCh9>yvMBQsa|P^2is+fda4b zj2>{`agTn2@PORtfxGiNAL!cRvGIaDG%ntLuIINGK*0Z*e%qv**MVDXoU?MElVehhmJ+9K3P1g!I^*P1%2_-_|{u6trhSNHuKKC8J&H5r7a$U!_X(* zC7o$~sQ0**fCbAqX4A8Dz2NC1By*PDjDC;aCEoyme`*MO8G#+dhllFJ=`>sisq(Gs zgX6BU8_Q$pfb#T_qTUbgke*qbvNB;XQQ#Nl|w@3#Qz(!;|YCC~WQ&PIQ$-``1% zvbMfkrzz->ADE~II#S)~v@u~LRY@RO0g+gG8FMSqMqLo^$1s6B)X3)(N`xPcw$=T# zO&CV`dGv5Li$P>pvr^$icxk4F%d%y+*m>P++k4?60fW)$1^nF9I8B#4=XR?$8tUiw z;@Q&|Ki;-=-wV!o*5TrrR!V=+ZQdUiaVWlT{WImtN4wD^+#dzEq_Yx|gyQL+FQIr; zNGP6i3B{blp~5$~*x#?*Dy`~A!n@>FI&k`jJl*j4vM|vfs792>pNCVM8F3<30 z;)(NTk}N|}iWO$>Uh;?s;9>95l-CG99$hQ^c!9!?M=1PwRf{`w77>4m=;sOJ5e2^} z!azvWGR0vh5EBFDgScRTF9kPt91kKX?3h?Uo4Km;h~sL*n~l*Mz4Q($@}!i)bm_q! z_Zki;*af<~;Pzd-o_*RuTWp^IARQdm-&_sn{cj2>IHf^KV>PRZ!1e;_+=<$TtJp{) zF9^`07X5viaDr zcBqzP5q1rV+U|&s38y1$N-9)@eQ=OsbRQXiz5es@*M|asz2^8!B~?Ld1(6AS#5Zt( zp7>5K5){QSjN70=Q6Sqdoc(YuetLrV=>y2QU+84*vgJp7Z%QOjhUCuEcxtRyPD+c6qr<29UTM5=be{k2VuRvyOfUG>Tid2^T6vEl_vpzpYHUb>0o8kaeA z2J5NALk(<*onRD?C7aQGQP6Pn|Ki*tI;NVOFI2MlPTQP&^y1s_67+;krQKKBpch1I z0wP8(Oz>uAtIwNlrQJWaOarnjrqb#eO~q82?GsFcC&hnEnr#JNn{B1pZt%wjzI|Mo zjduIkYAJ1{t>90yoeY$wng7>-w?@-EX?5_c(*CHDxd&0RKz#!)N5P1$=J->mUOa_c z%gyxCZnnwv3jW4+)8ys<0m8buSzA^brPVe1O3O3`-?yx((NRprY8WlWGMWveZ?qal z*Jw2?qiKIw4a?~JjjqvYSk|;*v>QghVPP_47&I(Q!i28Tg(Sr?T2P{`V2PH|WmUHf zOR*rU(J`QT%dm{W$5qd;8Xcnpbt`7W=wTbZ2DECl8!e+fHK98lXjNe?TM3lyC_Du+ zDwt7$vMrSwFLj~Hr)KUYV-_C=@|WK z!&1yfvte`_P0Z7QM~l6;8iv(q87-g9o6(%&)HGrIji%BvtVR~x2BnNODqAl>6u*RVQfOKErEKk2R6K5lnm zk^AjIFaOX)RB|kmn@UrWp4-RGJf}#;s+4y3H@F6j!!v5D+z^7jGRGon`zBNXm9&pr z9m8yQdP*DK6zL7R+g7ZmG3c~g#RqKrSR{WVrpuq9NS-rKW<}b+XvlbgF| zm^~PDuX)_Gj9yE;H5F@MwA<|tG|{$t9mVPy9TR4#W%R6m_t@$foldu@SRKQ(20g`U z8)n<;D1iLBeaL3DdtIo;Y!3P`m}aNdSDKb#4XiFyYc|b+(rg)>?qGn;^!gp8*)f0m zT{iYs*HW5&!|L>#SbMkC1+3cab}VSMXZ1Tu%Q6Poo1W3?wOUH6WpsK?3wz(Uno6r} zbO$|bw%6#U8CLZ=yZHjw~t$v z(Q3nvfbqh3Ov7yTae10%zs<&J^={b3Xum%J60z+u^ut%LvQ?dF+-vS`FjJDP3!HP9IeO%F258$Y4m~FP= z{Q>l_W3*aOOV6-+X7ku;Ll1Eh+ieR+)NXeBIE}4A2i|)Fi>Q>6n|%haX8(WK>Ki??h3$4)05PV~>O;A<(QQFHO{3XtV>`{B)kg^G zK)WqtV8Zu~G3c^>nS(a=yE`xua{Crc&A@0|Y+RitfP`uE2W;HE7R-ZX3|g?I`$lun zZXLIp#-P{1h3~UBglIB0)!7Qage?Z2dh_FsSTgZ76z z9JK$^FxGn%)46x~?%jVg_lm~vER~0cVoLogrYhDQ&fyuICu%)wB`nFgj+AJ5>L-mB zJM{lCG2!2=HlF%IC8Zv}@m90}dOkJbstPh)E&;&SfNRrzq`L|K%ABhj(Ezzo)Q!&W z)U8IdGMU$QxLVE0(v4_cM!sX@KFSlR65LBI1Mre%blWb_D~x|?X#pJ${{sc16zNU= z7uMEn;8*!E%Z6q2`sY2v9Qa+M2{e7LW%QAx?>0I{tJ!E7 zR`krWfQn6xwL_r?2s$l z>Jk=JvuTkfv;46-1WLUPyfm>@bj$}5SilGO z`5#PIAgyV1o4#QVfJA5;W*<1{a&ch1I}O9KrY)n@2X?)!bd27h0r0A4>e=Hrj~}V_KDl+1@UXCffZv!@gr9jxQ8m*s>Zkhn_3M|fudDUPn``Ak z67xD=zkTuI>5K37*ZI@Ub;j!;0L6b%=gHfXSC4;RJi4x@zujDGvQFT{WqlRFkfoc- zEF+6{?NUXqPt%n9iDm-wquUDAO*F8@`?^gOCLY>5sxkHP@;^6Men#i1-7&!`7QjNz z>rT+j0{m2jk!=$2RA8G#)*|ees%e?R>Y14^qQM3@Q&8n}=Ef!E>NPRPe;rfIp9&_Q zpzwdS4j$3e_57ryx!C$TsMA-hCS!-%l|Q(?F2Vwti#Xw7`0=9;%8n`KPrw)y}f zt3D`vuNxo2iQ&!k>{jZA%TBIm$TfoCJ->e#L3gSdfe^vA0{TY0@=w%xlX?x|T;*Qh zy2m#uNY-`#^*UhP$FA1~u-zM__jbL4n6~>>Hg}Y7UXo23hJNZrs6`g=@3V&~)83KD z(axWLncXigvpZE~oYxd?0DlN45LJ1vDh~TDF0h5VjqCduj8iD(h%vL*xfgiJvUq=I zn~yz10N@?%ox0oY{-E_UMK3 z9E^E|GJJtM&(l90cb*rDGUw@DMW7NA)$WD!c|ucLc^afdx#xQ;kG<#u=kZ0+L`GhM zC_FDKqu-=KbTjU*=npB100X%ugov9pjn0GXaPfKUbjY~}2pQ&#ECxC`cWc#+&OLt6 zPQdHjhEIY?*x=9OjQml`Naug_QH~4LL&+_gP`Jr;glY_ya!zFq zn)xbYP*fAR4Lnickx{pdrzrbmGBYx9WBM?dE(@1E`B8}0CShQp(>V0k_J~eHX0;}K z&fyS~-Gk~pyp=&z*`|ravYAvqRr`#k;)=1UrjnSVa1>M9hDXS&#@ z%j2eFvvCG%GYm-%jt;A&)t4&|P-0!OorChHtMth(dvb+=4eHs&!u^Uv>gLBg<(Qsi zBrCw0lU_z%8Qi_R(oN)*LE%|%6@LJ#ul1?@;a$gQ)UKt?tTUj zlNsDuf8r>4-1v59joUgZjE5^%h#NRQjL9-FR5diVH8g*o$&U}?mB)vh?|6I|-PV_3 zJh?-E?r9+N(IfA(Kr<6%9XB_7uKhXMC~MB{de#vV_&FZH-tCV4wf-ZEVE z$>YWj9B}(7F`F3~F*7orI6k(*3;a34LD(8$iyPb6lL~vJP@CNIK{S2qxxk2+N(}ca z?17Rsv*CXvEFru^0~0QnXgoDsb+6WFXlQ(Cxa#94kLyn~G=58XG{=|X8h1w5I8Ifw zScLz^iLV-2@OX$Gj&*R28uASqts>M8+~30k_t7KGzjCh)eC5Wmr+i^uJ7ST8)3GkF z#_5Wn9O63ohKB{@i!b0S@S$vtosp#6D-c20LhOGN8R0<#3^E!=CR=DwnenCQ5ZxId#V-*cpNRa5xHy*UHGprd@G8cbjD18Q_XT$c8Ok z{pWul_tdQrQ3=v^aD}HqPVWnq|amB3Us-bG2De8H4RSZ8lKG_T= zLz_Yb%N&Y7AU?C73BG$EiAu;)+~82a(a;hHTU)Ac`26&;DkVhrEewt;|HcVpxbu9~ zMOdpQfZM=W$p$HZB?0a1yRk zoI)t1{4%bQLn3iL0g6Gw8k1w5pzS(g4pZnGB(&4k7Kzy!gnk5ks#{wsjp-WSAty5p zDR0dYd10|oTA02o8SO6pz!C3$_R4Sntsd&{oyDo@+m>P(L1+!x4YB zH5wY{;crzy9jLCBsp^tS4;O|U$dw(P$mNUHzw3wLc3rQ5da8cl{~nTPjqa7dUB4EF ztRF9BzQt`l^V|bnQHXdBGZErtqVe+| z(^8VU{go<-5D9ENWo+6`7xo7h=qr)JEfTGQ$!ej2#g|O*|eRQ+H@c@(FgtgAT;PI4F`LHuw%#GIA!4 z)aQW6);)DCZ|Jx;guculk~{+X=$O5HZqA^O-#BjnRfGpLHWMiigoKh6Iw#9)P-KqI zx$OBk=mA-{tQxitbT($#bP0cxgK(#nG%de%VY;?AJi!BVmTdvY9$)v&v6TD?z34y{vLDc_0b@@aokI~o6#Tfvo6LqU7V6S3hh_0Zhg3TzIJ$fumOU= zxqgJ>VD)kZQ!ts2QD=YPSg-L+SgCAyBRGj`PwpliM5y_XWhEj{o<{=!r@{)5tT@>x zFU;U=1ghbILk6eSi`+g~4M|$7?{&MUt`j=ufER<^eQQqn9S{*rIM_IZA${z3&nE8b zLHZ2FTh9!7EnvGZ-{>Fe;*3siHwtc_527G>G%=l!e3>w^dtQGZ>Js1Rq{@`M6#|tu zwx4bC_!%@aYsOSJ`;joiRt%iNMx#2{=NQ{1*5V)9Ze*wxwc4#31wtBxagI0;TbYDS zkUo<(C0}7mZfB%0@?}W6jICNv%kMGi1tVR97iNej=4?&*Z)hr3*mMpbJ--jOt~FUq zSTfQC{D*K!=6Zi7>sDxjVah%>M`p(vIG|Bp+tS0K=`z7dQdr#Sd0t8gfBh_5N3)6Gg zDm{`+gOt%7!NHkoQXC$S`RW>Z23UcO2lWFuIYC7o!{L7i`-2Cn2i6m(>f&jrYFgFy zTnw#aQmQYPhO*SqgK)7hS$jP&j8Hp(jI{%H=!&#?03Y&=XxVjKb1;~ZlbT2MT!!IP zX>$N08MEbSaZ0DF1{zgs`Ei(TQ;5$z{!&u!Wn-##hnLyDi^`kVQYFVHuS2Xeo_j(9q#@rJzfcKks1=$aCUZhV4GlSl ze^t9irr}@JVPd3{J*bmJf#E@-$nYSMmHMQq;;I$-z#?-=z&+X$rR>?J%9Q^-WBg1F zwQ90J-In&$>!CS|S*6RJ5u~rp5-@}39uFL=ufu}wCf!VSzc)=ml8sa^h5o;{M#TqTrMoZt~v?-vL}g z00ARIH76`N zW3K$qWy%6@($OR$dfkF*x{_t58 zhMs$gry&U-47U_mBj}}`;=k8W1Pk#JS+H3TQm>Lbk8W{7Xrd^HeRY0VI+r3e{ zHWdCtLE}0+JW001`n91XKY0S`WMzLet__7=@&|xQH+HTKaEJ>OA~}v566{-TJ)+gI z6Z}hX48)`a4hLZ77;Xe#A=o(Z+@NVZ_*$=e`BGE0D!8!2VvQn$2w-pV&{MMzp4dwC zhl-8)5(RPNpd1(#;DRtV1EG!bsgUwpB2_5KJG8B&>1j2Ew4`dXl*CCz(-41NqAT~h zFhIxnGc5mfR(L5yFAQGfxHbqL9>Z8CzL}nT+%w%9tfv8Mp5-IMG#LSEt+WVt1`#QcQ2D|5^}`2g)jrWeN-`y7r-I!DQX z-R&E^M11&byioMFSRi)iYYTs4=DldM#R0bv{VDuIJyL~Y!7s5;rYw39Rp2ec@8YhJ;_jJ0r0RsdD3THu6X$ z=b7}tT|mCDM9R4{!UKQD#g$Wc6onF`yP(5KYi>yS#GS^e3f+siR>GBt0XwmhL2~%J zOgj)b)zqkycn3|gFYuv+JSiQdy_!lPuzOE2;w$_X;dQC#H&o8;wtr_V+;0D zcAWO6MG6(_LmYop6s1V>M07i*Zs%mrow;y0+$9=L3Mp&7D&tk zDH}r3J~DHw$KGgm=^YQ8QO7fV8xem~JtTUs(M+PdG7A*OW?OI!JN8BnwjU^TXL1rv zyDYo9G`sYo7$kr6IiCC0ivs)xo8wg(Qc&h>AZf$#GnJTQ%9uS$dcuk4%L0CpnI$&Q zOhMH1W~pry_D$HPnJYfk6@eGw3U}0zFJmNJ6;n9NjV5R$NFWi?y4@9)t}ErtqDCkZ z^Db5kBjt@5gq0S?04#n>y^ECV%{!o&ZpFdtnLn~_b%lQ_NYTrgg#7_-NhuR!;;%@2 z2$}AwFv8h4ixR#^9TO8BQ2goAo`a+;bLus?syL*$xauW6tF2AGPT7w|W&bzGEgIRS zbHi1e`9zR_t4lVn?UJV*#(Q#X`nEn#Jo3#b^pquX>|?@4z?dy|30Yncn!{1*{tmw% zMge^wuxo!{K)s|A7O?GoTYdsk$~b?LNRouo5DICEgB4RkzvAbYxdYs9jZ77Ck5eQe z4Y>~eLUvkY?b&t0ZN|-~pqPq*@K)e$%E&;@sF#2Z?Rx$YoG(XCXbu25wnU8BQlG;~ z?#A~b*UnN-kR;Us6e4#ZrO$?@uHDhuZo|X3g7^TH*qZkfOrJJIgojdXn!(BqFIDeWMDnEpT-Ytg20%-I=PX zJWDj|sUhNo%CN)p>-0)N1Je=>O9!kP`%izsDS9>}KE|_-sBF0rSBKbT`Jc(7e}aD* z{{;W~UA_A6e_t=I{_+2DueE>u`?ni#WJazr8>(6roL=I{h5>f?f|-b`W3cb0eMYJ0Dk%o2b%YtMhE;zv z41K2)g*Y&hBnVD1lGLH)m*&TiUfAij~RjKKSmFfUx;YfVZRCcx>!{60~x zBIhwBQDLz|vi=|!cIXKx9CvnhcQk)AYa6b*v-22cMw8Brwm36dccX^vZ=i;p-m4*R zr-r=ziPVs9(`v{*RYOj>_VJ8gT&C2JXXVw9tzSnC*%H-|M}~xF%D{A=I)UZfH)d}| z9pro|(LoCQh&c?6WTzmb`avBz23-&1c|@id@(fopFb*E5p`n_Fm!4P$kR5-`I512) zx1h-$Oy-pjC2%tHD&+IZi|3UmomW1aSI%;|Bnw2meUnzxudWeL(ZL09 zMqFJZ2e!n#$Q;sUrpp4^`w4y(!Rd>M0O@yJc!%W8-U+DVyo(smBh6q5bPuUa*{S$x zOz*#2TlF27G)V>uP7B?Lel>s4ui)o3`*xsTh1c-yC7nhB>1eV%8(1Yf4|h|~5E3O+ zT7JO}Dllg;fiHcGTp1!m2L+}gmZ>ktVoCdfG z&jt_=h$xuhmrZB}KwYgXZ<^09*=?4H%&Kz`+MykQp1}<9%}mji)+vmVOzH`^8^hwB zO8D-@n`XOt@`9%}0pouiUV!tMqAT@ktqY#bnNl)!fTAl`p*J%2YN!Hixa5Me;gU;& zaxnI;GX>$g6KEx%dwqt(3C1o7g%rR?S^6)YH@x(oJ0S%Ax_FnZU+q=mt0kM z5DbpZT4lFXtB}~YLWV;8khicIPhI(tUenxV~sT<%a+n4i!Iw=ABmA$ zp*I5JThD*S(gq!w?vZPgmL!?OG$Ak|i2w{a#71AU_527!1H6*;q-tfu8RWB{s?6wU#NvrKy zL|6xgF18y#o1NOK!t`j{_RhA|GyO2xTEXX-h?ajO8wa)t)2P=DLL++QLq5+yI}cP6 zqy;WO(AH?=ut(0nS;-yOWyAb1+FtY4wy8&tKv`q0$e%7DnGeuub!cs`dvDv+tw$#E zDcO0I4LXA!rPR6>KY_hc5rORBoDe@HJ81Ga%sl>b>e_gk1aC*9+ zO(TPcdU4!cPU$W>$oMxMQ>~#2`>$HplE8ljvq{y@xY@)uuQ<4R%I3I-Xs_zqbwtgE zWPJu&m)Ni<>ysIyUBv`KFM2M`-rSA$?05t1+364Bt(=|QtL<*5wtM#zsqN11DLB_s zaPlcwNWnR~NGm@n`zD(}i^c2{zj&8Yets&i{CxB4C_mqb%FpLgBUYk#qJ9Bcno57r zh+c>q(N&mCsah0Pr>!kTc>uMBwSnqMXE(5ulKs0f7sVk6S`G~nYOxQmQ9JN|=i3G0 zxMYGOxauB+R}N_AnCGr&*PES#yR9Quk|ox(rK!%z*J1BstCYuO;^5a+pk#DTwD(XGMjcp*h_q z!mY9rc1c2w@glCYv6<;8NRlv+(3U(a7Q~E{C7RjC zjRRPS84KlDu~3E)3kAf^dkJ*rS*b8H$d~)l#^!Hd2qP!Afs?G_SdGLR$FYB@D-MSp zZ~|G!1~*K8S9d68E6`n(M03<}HTl6|Z5$v#s(VFCRqT*c9M5K_QJULgiM}oj2XMp^ z?_SBso{dO6y+DV69ITBq5%gw%Y(5xXC5Aa;Mbmwtb5C;h(oiKO3;X}RqomD|2>aqTs~c#)FZUYD2KUj90A z+e=Yy`ykyZ3HJj8;}mwI1jmUSf&2lPhKnba_ZM$k*z~R5x#^q3Ky|7C`3ZiVvyUmG z_XxZwVlBT3g1@T3O+{NQz%o;>X$XE3B|$b}K-efDVU46*rdhs%D!hM*EOr4|pf2J5 zDl)8xYJ@B*Mn%XXVw5zUAH&z?v}(F?2%kvktRkdrLGcVlPrmXxJa8Ov3A0#} z}?_NMfOo^O{+ox&`cnV+yhEFF0=}34SpvV7bEu|okN(e zb-K-xkQuk=QGtK^T$VQrm62qe;~Zb}#T8uR@+1<<@|6j5u`yQkTRKVxzb%By;J5Pe zGU5)(g^q~(C>J@Spg|iOwrEnUZ`qjXNEz`^&GF2yuedMHB7wGE(lE(~lDHb_JLy+x zgbi6cvM3r!Gv>Qnj2MwLPd1Q+WFp|8?0T037>Mui2pfOd^-c)05%;`2v_|T2KE6iL z<5ZB1xV}8nMy5EKp(Y8!k$J=;aq!!j_#3h=%7@<&*Qb2c2-&kn=2;RXg5OC;ibzeW zY($9SUQ1#_lv*jVysSbzi)8ETijcWC~CNFA|&R1~hG zT=!)fU5tO`k>6>PlBU+f;ssT*Qm)+!HryiRJA@dlJX=X2;73x$RD6$8*@#g;l6;aN zAK5!(DaqcHWn2{VL+lR{;zMYVvV~3pdI%ymi`G#Xy?NFsir$=v|2yTxe{hUW1)K-6 zu1w7NSgS>UQXP~e2z{lJsH`M~-dSJh-ExJdrAdDko800B7icl)4T17QTJD&2LsIPB z^~K)L7n=nMPydnCB~^=T%fq3PUZp6{S*5auA!*f8!7%BqFcyF^L1XAm9v72!X*M(_ z%QiJ)6KZ&Vr&_IM4wK z%=Ty|1k%Wpl1T^Dg7EMer;kRFG5bTp&t(}ADE7NXw1S^&o%*?Sfc1^c(N84=iZkvK z393* z6J*H2B}VW8tC5U_lIDr0rWI1~eJ*p(A|=VV`&AiJ)4wF!54;Cr>zr%QIHsPKFB8`mIIQ? zW1*Xgn^#hYdxFy2*<~g_5kcuBO;AcE)?zW?1f>&;U!(|1C()hTWmrkd*k#xv^efn9 zSXC*mV=~B4g~c-$);)v8L#Uwu%<5@4ZGFqRs$Fxxd_n4h>m>^P8F9-8Q}ch-b?lpC z8grP5dO&=6;9Wf+eo5r99;gj%i6j7XzD%fQZj?$yTUaf@4fP3LOg%O~^ zlhG5YCWQ@axp^7;y;dL&(g4_pW)(ceRusY@QRqf>;2jX8G2~&?5sU=KXlwy{`JvC& z2%Y^RpI9tZ)iL-Z4S=m=y!n3`s%g4UmN0E=>p`->`3OkR`Krd-pL_cIMh)Pxs%c!& z&mxDecGnt$pVW`PQX{-?mAdX2rV!Y(vdg{Py($?7j~;PP6vDg?pVS}Jmo)L7o}}_A zHM?nC)vgafY(#ADn?Et%wsqvSt8YKTUEwnU^kgY|?cXrmnwWSzbb<&OX3X>?U zSNI%Ze^z-8GUqF=qds(Oy>fc;0P(Z5UO9C`#7@%WM|_s#1HW*je5>0N59Jdb9NW4D-jf7((68GY$ zdRhaFqbs5xeKCLZ6@>yK$M8Obv#tr|#rj$GJ_Ur4 zUMwcPShi6$k~A{>u{s$swLoWp1D#Ujv01Eo+jZ?<0ix45SkhDGxi@eu@PNl5sI9j> zcQ6Coyk$g`p{{F0RhXZSdxLBvqQ`tRGNM=k)G;Q3>Un?aq@$s_23v>IRl8ad$K?eL zX90=q!bB&C`o#chkjQpJbc4o*Iy5FumNdx+i3bHJipTYU2HK0$SuvBUMc46o17&Ym zY^{bR{i=o<2<=>J=xP^rR8{pL*jqJjRZ2X#M4qNyAFvHL#n7V$M#65Vnub*cA&eYh z%+Qom+*N<$B}C)*0x?J?CGN>CB8u*EzE5y6P&5=^ZW)yf#ZXmiD4bP4hnkw6di3jb z>WMDh+7dNtwN%vb)Uu=KJkK|0nhIb|vh--&HScN%?XX5_@V0i;C}|QTq}X98t{NmV zO^R-Sy*n(3qo|>oq28p%M&hQM8xDRv9DM0;xY~b3yjtOrrefrx$qqZ4KJ+V`YEeAmC0jkNpK{PyY4xS|u&WOg@-$;k$a$@aZ|?RNUL z=1-(wYo+yT6RKZpbF~_$;DkB}Z}sn9zczm@uV0(}I{LL)7WX{4OwNOS35FnuZN}87 ze0%$Q*3iD*A}$5D7NS_CAkkvT=gL##<;qjzTXI6YBqzi(=?O8#G=7j(?TMV+sgza6 zwFVI|f5@=6AignN~VJpqzFBuASK@=3c8kZd^6fob_jF`OEzIM4ZI;% zT}nhgIWDsFQ%7{-Oy{!;;!Nj|E&>tG6c5FoF=vr^;DLv%l}F*pks4G(-x;cK zu((>`ZdTf!|5ZkOkaUAm=KEy{WWj%@CR%A`L%8ArTIgI*Jhf$w- ziMp%3L`_lEl5q?M&rxM-gnhv?*w@xMkZSWg@CQvpHcsze);vjMsMA%3hd?c5Z}=8a zKe^oYb#T9okaV(ANP0(vq!WKtLzA}}nw;l#)y^kXL!ro(E7cFX`4m(?3{;`ie;)Zn zG5jv280IRb5L8SqQy;l&bi!cbBsyW!@ME2@XZTbn92<%ci&Vb4cUY|G^_H6M_MWkbRva~L0sS&dDC7N6qR|?ZTDM;}#g}r}b1t~G)Nb&=uE zRKKT&Kq*Z*V>J{|3qXGq&}Jao&{}omXu{PTbl_+n^g$sL7ZCt!UBlv3GabSON>Rk#K=mws4fWzi1hF&4Zp)QB*qAR- znCI9x?5ptlfDkUqLTRyYEEZ~f&C5hbDN(v;C<5`^!tcqjQAvOBFS)jNi9pTd7?XUnp0Ko1Y`xQquC5;7(OP>;vhQW(3iT18cgwpcx^!gyHKmzso1UD_@f^*{?4(`-=n zl(^Yy$fb5S`&xh4pPv69R?o>__k@pY2_Jdy6cRp8o{498vHFnaphd0a_`gP8XE)QVFly9|kG+u^m}hmEeEfjF9*iBys2d+i^!x_|I>@ zL6Esv7<;cy{$gw1pn-0k8M@CU{{JpRf;TtbgZSmJbU{_K{*jGJJ|so74O^0)UJv1ymqZC z3eo4Yx{ZIQRU!eZpsBAhoqRlG9@MEta`I8C1!5cW2UyP-fv4MwIzxv$en83T0j5Y( z)4N3TR5p5uNUf6FaZd-0H;7$zW~0`K&=fw;2f*h>EE~JRB!AhgqvOz4u~lUK{yQ_ zk5*T_ZdXCiJ%9KT4@TI(B*E|K0W#fqP{8dTNwf_PE94+qhKz7%>yPsd;`Jqg_;{1s z`2e7>Q4!jI(4j-a5fiU*kbDWJ_yAaylsF7$toI^w__g7xd$oEE=I{pt4nu)M$wCxC zO#dv7JR-3mS4wggYV=SgI-0~1#-TcST@9b8lMl$%5M3Eu5Sz%=`M%n~ z)7tytYiBdtYdrk>)7qqu_r&#I`%ZZj_uQRY>zKrkNL%u)H?RK{5rP#>#SqD!aCN* z>tw#k({*bZN0@V6pG@U4`J&1Kdx2}}67AK00OY*@93g9p<4D%SL5+4Z`WQ24lazYpGOA8ZFd&py~rJ3F_ji!|%{#iBjn7lF8c z54Np4H>Ku_(J z{>1GbfS%gKcep*0+oSBS_8czu8U{0e3`@9863Tt3z<~;Eg6&QYl$CWEF7ycYjdlbc zvF#r7h(!+EnS3gMVR8SxI^J0W!J@gDhKh~0BU(gFT1Mgri!3xiU1Xyk8les%uCr){ zCUHM?GY*mM*dekl_mA}qvl?JFw7@UcQ3dB$qs`qQ+3Q9lR;=t zsyfK|*OGZNhr^*xRelgVHuk>U;qJEG*v~dHR4Xn;-p@AT0I8@N&rW0mD2Qgz<*&9z;j}v4o}pHk$00g*P$`anECPgZkuPu2;?>52+QTG%yu$*2c7lX2vC!bY z8BHEW3IStF_~zOj3d_{W=cGHfET_rM>YUP4by$+YIm-ar=EiW-uHVmN`6JU5baRi+H#?!My?wkZknGH)1KnJ>1t_a5(hb>ZIp{7>!IDTv7GCe`O?p_TZTphTc%G zEfEP#bZYB!pzVSXJ-X6!Y#X}@0x|n6zKaI~XB0Sr0v_6bHu!_nPs~}Ccm9<vcBFIAcSTz*5(HU|(j6gD_^PE{PYhkYl6 zjv_R8=~6?%c5@l|k^9Q)q*Jn%*eOW-HuddX2QE|K()Ooxgz+Rs8FBY9DcuZmjCt}z zcM-d<`^fA-)KOQ*Rd$6i4e6)jD!YnzY3D_C+<;GiyvDPjN+zD_P)?fmbIE?YnZ<_% zS*kQYyai?>P)fG{GS;2XaoBr}XQZ;6ywnj*I;PP+QMqR=IlXKA`0kN)8wGSVsQJ(~s8^i%$ml`Bj?sgJXolM}08T zmS`q_-V4Y_JLLb}Orb>}a#~t0PWXe2;(=5f{RHh+tHg`mu&U0b`)UqDLuxsVt zu%2nE`3_;?&IpDBASo$mu3JVoGEYF4LNqsj9%ADeb|P5%!>X_mEMvXS3<;zl18jF@ zims4_YMcI_=!F!PipDtWNRkQB&m?q43U#qdj2pvE9PHL1Nk!$6xW<_I{$wSD5dTg>q<+z8f ze#e_C$bu_u)6hv2zkCC}Zq%of#ko~~WQgWFFFRWt^JO0;WgjPHKcdMYPGf};H&B*9 zlk`eZQKJA?Krvpi%m{8h(3EAVu8rq?YIXtxF!qJH$!=`0IEWI~T2?h1YV2pcOqWQZ z>>b3DRLY`8`F~6C{YpDlHkUh|J*z8A)V@@cX*nmFY<(YL*Vgx!niSB|o}xK_>|uKR zo^*bFO`%pU2w#_RB61um{7OmY%{TuZP$oY!2cT%&+PZn8rtW=t_Hl61j+U`xFG>3 z69%eSoc~IEIx%B$j-Q>NP53xj}(A{SZbz=6(%|kRFJAnf%Jf@^4Z@whYRgPE+ne|5q&OpzN zG5eT^WeRyJPT8m#hEbD!>phwegB$Q%NBmRnMxSzHY*mIrQ8=jO_K9bIXil@#F#%$0{U$thPUb*%q}w1JkYWw&Dvto8`AKhYw4K4Ydunusrp!l*cC_ z8_Lr7aM>_m{M5&-qsnVg)gq2bVmD9_b$Zw&9Mf-2*Sx`%nHTx-3wJMqos%&^OM7d9 z!z(LrxEuABAO)0v6F5vk;P5y4l(?#u7C1hmIn9y_91=03emB^u+6LIE#*e^G?c6nX zs!;|z)z}C-wR?}9x*c|E|0lvu?WL_jHHw|u<&deT{9-?aoqBTj^1;*caIN~U1J|mH zaIMGpaIJf|);(P79DI zrt>wP&i+_!x@ju;4FgA@fUJNNj}sZ~J#d|F`rO&sBF@e`YOaiA%ZktHkMpP!wkUc9 zKFvijer5C;~8wj zM19xCGeQh|5Q9gh!Hl^haN^UC6upuJ<^kq$)bv(=eQwPcc(`Qo3rt(EM9si()p~7z zr=g){WVq_n+Rn}s4K*#pRd;r4`@0%y4oZSy2Tl-zq5Pa`RWhi+EGCerZgGf!KDRQ! z*&83vuJ&uS>m@SBW@xTN*)m;Db!a*+ag1wr^Y**uV7+4;%ZMmmWBfwVaGE4)CL6nf zoVUAwy;}F_Sw$+EW|Re3(00gwqRI1+>42J$3#*pCLh~wqDASoJqm>n-0tX`#kS{Jo z^yYn;)55rgS{R`Kpo4LdtQheqNeU7~9ip6T$O?lss>)evsA)@QPltptWIWb1{PXux zZa2Hd&98J6rpSZk^7KTnC?qKII!(7@1CS+uY4EGHnABqu^P`gJ3+bn5D3EimS=}DhBD1q@cbl4qvjy|IUGhLE+VyfZQeaNNI=bQm7w{m0Q*{T!<*)z3BC_xibe z{oK8N?p{B)(w(x|{0g)rKY26o0hP#5WHe_YaS07>nDt{ixTO+kvhf8Tc|NQTkRT{TAr!n&p&{FUe*{1@`MR=+8A9z3uTFWd)pK1ONAeC+bRMxZ6g&5vdP zlZOfg)>5NUDE%RIh9F+9^pFaET0kL0F7@V65-XtD&ZtmvtU|>Z6{ATriQS|Gg+Ql%$%Na4wqw7p5@#1t$XDO-1Les1<-b3?P0 zg{PezUnB#w5Tqui%0ksLY6W^Tccf>xWx4~2(V)NHhBD1pDsKQv)s7cDH5bMjvkVU>sH~D43bDpBEb`NGViW`!xPEm;lI|4 z_s>>TlAc7xa;gsTmd(6RF&FY@_)r+PnIc@B6_WdFa&Ip8I^enzez zN`O$v6`@dmF%-%%nrG^29F%D|R6FMxj^F^~FdS4wdkIUwU0->V? zR9L2?3s(x((VnUXr8_!U)1y{WnQ}dvh*#mJV7X>90n2$5EN5oHash9aAP<(a6U}3f zK(fBvLva!=1Q-qsg9E?eX9>W}H-qt-nSr=OccXAnDoa!|oUC2VRHCDjRv(4^Rn zhD4T3wH>@wQ0o6Jl=|0VejPpjo}kBXxzZy~(DNpAM|+KDCxjK3oPPow zUV1k-1Dt*6i%=-XXkiik#4LV*e=-fwnu5{>l%9dn+*hedl&f$oBVa0=E{n7X)sGen zj*-ZnxfI(O(~}YHzO+Aur{Zd8`ZqXavu=rc;#%o{682`kE}B3}Y-&q1G77?3R+G&s zgLx5D6VSoQvDI8GJaq&r)MEHbCfnvl3uh6-*sybL0rU2aO-3}q+(x6`AuGsSLWLIoC<#)xF z`2&y$E$@zz2raV&5+R*v9TK4x+=~;p5+_>GPb5xQDRF{Kti^(L{bJD?@QWxVP7F$m z6KqBJ6~qZvRVGe!?_mM=uz-75z&$KrrN>2o%Utyg{6uHKarz8Mz3y4pFBYvCzqm=A0cYjUfWMB{ zeM|JZZ%y*HsMc7Nz=-@68W`j+*T5iur1^jh>{a{wfD9A^2_}+R6yRpJi>**i9~^0K zv^r{t{Ge(bY5b!PYREMn)Z=*d@yvq99tw=GdgGg;-XCwsKn)}V=imV#@c^Zkns^70 zIsHt8EW@L-4;nR=3?jp-;%SK80D^6Z8+F7t>ZodYHbAtL_wSD0U%ouMIQ_eSd7@}@ z9uM!$nWif5T{8-Mp6`6YHmZyU81|QecT;g(8arx4&>o=KwXqvI<^V!_#4+_=SsGX_ zeY#F4zXimLO^LO9OSUo$w7Cl{W*URk%7FRG5X37(AYB>wxz=1RmtqA%j=Neclq0u7 zbo&+0A_1|0cx|~vR}Ko1f32Z^IR%6M0VZV9C%P+wh+FNu*{7Nt>{G2Dp=a&iwVt(A zM$g*XNY6UG-(zpL$6o$Kd+giv9^0gQ?38b7-(%aq&K}zq_t>L*J?p)m z^Jr23tVs-t6Xpp^VQM)Rn9mG6>;mW+T2lp6Cz^xy{je; zIVv_<{X(A&3k~>6)H=#&bGorMrz`i_=oYgRe}&IRcO##TM0tm-&73wG#aRJ5~g5~v2 zLgyI!%uC3vjxhF5Pu7J$rl~gd7D~I+xJi&Z?b~|N_#1iB2uIj|*2&$d4c={_HaPzg zYJ-crRvVm`Q5&3Zq&E0;uQs@y+Ti(5q&D~~tu}Z^)drj&ruB?pJWr_&o|RV{ocua! zgA-A0@cv$HaIZGFR~y``4OXiSUVaBc+}2x@3mLBJ{eKk6ZR_EkGcL5gBnXLzS;mF)#`($^?DTmq z20J;!uZ_pv`m)x!yY(VpxI9||DovK4 zp=zl0QA4c{-^We5^*Ze)-THht8i&6(&^Y}0BQy@L?pou2@Mjr~!=D>z9R9f1INVO- zQ2&WE4z;w#;cu#O_=77NcKAg-rEzH7{f@CyUdi$K*HLnO7L^>k_ezd?CC9yz<6g;8 zj+(Z$pUAn5w49q^s7*`UmgHWB4vIdM@IX;9In4uAQYAXjwOILO?6) z#x(WpdE@+l7Qt-m<+ml6?PDq1k`vHq^}%y&!YPP<(bW_pOK#+9SDQrR_T12P+yc-E zN#cZf2t+^AK(99>vAQ3!NZq%3yY=R)-hTWwZ?`{e@^-kjm8-hLgOo#Og?VL>|3-DH z$E~Bn5!1(LUeKL7CPToL>_@p=sJb4K`_d6Z#$ZrXh;`-=rZ%QtPckEf5)BxPC@in@ zRtAoL!swbFh562zN^C7OSUa#e(P-$X??|ibM{ZGFz1}yR3@8}tyJ%?ZlELMT;)Xjt zku{pv;b#fXxxB##_g8-KmDiDd(dnUi&&OR|`R$X}34T-HNN$;-8dg7f9WW_mZCFc0 zACaZGYytPzw@52AeZVHln?>3|<{6rYo;L`8oe}9Bj-|AZLhV}??YZMRL2q^0!fKbL zItmZh7c@z%>B{!DqNS;u`;2=l*>}KK4Oxg1q&K{Y7}Y!v^V_)f^K zmzs{R!fV52f^6SI{h%biGBi7ZJ|CL?jpJT=BYpQ@xEhR13(onG>i`uUJbLDZp*Pfj z8`Zt+^A6F(vFA#CG_3?4==9?8mw{a>JGGi}tu0ZfS}gC|Dq+EDlp1@%36_^NgG&Zu7-3S1~e{nd~1aL<0Q9`5Pb z+%fg?rKW1tks0=2>L8Gnq5!|eLoX+PiSv~Th5?92QCwW4{N_ilFi%}gLu9l>q}2K6 zNcrtk;JJYL#Y=SMUKegW9uVDss*E_)_;I^GnE!bOz4{eu#OH-=OEzP~S4@cn9?d#(oX;yT;CbttL!=Ejw0! zDxfvQTU+FB$P`72!qlDpo(g7!6Tli^4aL`?7Pnx3q`o!7UbQ>$JYRKx>vuII-uPer z?r;48yJul%KyLl7{y@~n_Iqg+aPfB>Z;jF`gp$mhL*W`JJw?+M zMT^&U;c1AJVfv|ylt9twa?p`~(|W=(O-43$ZGz{B2TIYnl5N|)eMJ~y{u1?VVvI>G zg2QAH;yUWsK!Ojk4jSk;-UR!{W`I?#>f_PCw6OYH`?nhaDhqeiL;b%O{{)L|?Vr|f zH%Lmk8G7$WBc9okwZaYRk8cAyx1C@#FlV~b9pI@_ggoa9WM<`BE|KMb4M!mL+p7@i z0X+#-2LQ2H(qqNyH%Jnm-j7@eN4hHg#PlHve}muw*t-7)cf)+iQ4pG86c9st(g=i1`Vl9hYBe&wbWAwxW%vdK|Ma7)SF4X*C8MVy_yU3%tLj?dnn zziD1JPZXk4R+<+VXBY4*R!x)J7w_M_JAL;ez74BQ)%7N-7OQ>*E)#Hicad|gA)y>peDfobeBv-`i7`s6QmTp_xCF^*d-z`cU@~c5U5E?QX)DBH)>&cA)le3~RAa zEg~;e-@kkP?(E|`U|Ap+3hLif&ztW~PT##S6m~&wlCCvq50e|b?~QmAFnMB9w7kNg zgYie&k_^8dhS|q|?H3`_ zt1PtxmOrUQVdk&bXHHfdS-|h8ifAa zlG2^;d3mv}=ostYbWF8|D(t^%y`dc_h#y+>2i1&pn9kPqT&xh0kja+tZM}}bFR(lC zCc0uqp%-UgAeRA{mGt?(}@Uwxtu=ldT#iUmM$gOCHLPDQItq_XA;TotwgdT`zd@UNKPy`Ai|vOg{LQ! zAv6j{QAhyj)UF2Ta~S-5eGU!pkZ+0#EI^83n1{(`mTbuDWgfo@<7tVCBN5~t^(RD# z0kJAXbQ{~P@qKK!Ces#5KFbDCNomWkvfj^#T8`9z4^#<;=3tQdU^0T1V3}pgp$~W|SIfl_pb{8aXB!%F zjgTNij4(k2C?t{rfpe3cbwxQrh3)1Gmv69<>1NtXoDNImYDfW}Schu21+ZfO=x$Yn z$%o&6#8wBj|AucBW&pHci-p*vTmTA<`a$@67A1QSK6=EY76Bw1UdM8i4;6B?++Nf( zgR_att44Pu7x^Gy;4A;yaIgGpZ5aznT7k(fsnGFeg{9(|hs+2I4yUrkg#J(&lhV;!799X_H3PD4KuvSfm198&u zt6k4;nm~pjAj0@?y8<|v(7H)0o(f`Us`{90;HxS@--;VeUQw(agsfe%6%I>R7>by# zFmX2zdTfxuIO3Iah02|zb#!bDgoh#Y_L`3dhsChXb+3Z9QSYC!)`MU9-f^{g(WG~O z*L{E~-860kcqcuThGx*eh+KLu^*RCe#{{L)@*>~D$d_wDSYyp@U>_pecx5i?rI(5( zUxr}O ziE|d7{u%1OfiGja_=6^aSofF2CV6guxa$7S^C&je@1WrrJ??NW4=7-zppxOfc?-=U|UsC|9v%Z+?xRoJwjF4 zf39k3|CtIe!27CJ9e9>G2&mfOrL=?T$>d;Vc%(U{Oz@&$Fl*uP)OE4{^78F}8-3nx z_rl>o?_YqP2!N`Yle&+?aJEgX5UHRy{f9ql3;S}v;;&!vAFf;RU;HPp_#c1hivQv+ zR{W&0uVXy{(;cxDb-p}E)JpviR7Fs#Yt6M?3)9axY6t%BTm^LCKYFCOhI!>*qX%kO zbzB=y&tQH3w^7q#AwH1=M=aNW)1Vo5Fb4nwQe1VojxFwDN2v9OGPRyBk(nLbtBal~ z_+lXxBlZTM+wJEftO{~hn1>Dc!YB%1KMvWs6;8HcvQaxm|Fs&TD}^RhkiwEFNa2YT z0KCJV0y;I*01Ik$WcmS^JDCQ~1Mu`b)}Hl0s{Jpp%Q+gF)0}~>iRP?-yNKrujBZPG zRcf1+8Xx2b;FoAlH!83zq)ml?|EQhh&-1AREX7Sz0I!LcW z7K}UXNzkvY^{MDL^0i@qJ{1L(N-9I|XX|1P1{9_#ty`jOuRnR6#LXfJ zA})s2&Ycbgw+h}wEH|pmWbMUzCguCFs`CoHHTsQJ-WvTKaL<4tqoMvTxo*HwX-7l- z{S})rL2x~M#t~ep&9>@eJF>7UaT$#Lk&Tclm2(PYzJJU0$o)Tm)c&93SgE1@-*Cas zzp*OVB?ruT0zj`po^hYEEof^?ehQ~h&isje^)))BKY==J^ELD-!cqdR%!bt*8c{!0PD&Xxg7`wp7>kqd|Z z{IiHe)TMadZvioX-d%n#)P8@K7#KJZAx6IF0=O0>YlJRBS(mp2-OrwbV3!$#dePWS z1{#Q&Wq`g-7DlNq1#d3iSZM?pLbtO ze3&v0jp>bAy4y*KOyUgQdEs+_>yeQq=EMAl);l%!pRC*_i5DX@3+nG`sQ*~v$1+y? zPZ^>Ue8hBE=Eyer{tUKB$A+L|At(HD1&%MDn^;rI+uRC#!6LFdUDYp4bi$?@tOexM z&fzb@?m|0%h~uYLc??p#9_#`T$|_cw11uLwLhT3_ZzR}#2Mz)}zYC!h!Z-#08LNM4c`oHU zgY_cN=L#(1+r-U++H1z!@I7UT0KvB=IV54pm)X61>fHTWW+rQyvt}<3)Q4WT8{kl{ zoVp>ZJRCSfhyKXy?t#h^vNuqLrKRs^>*&gVR;{ABU7imqF%L4j*6-_6bLFb&kyX)D zH8gcKG!63my7NheZJQ{9PhD`ty1}8UkPg-s3#G20dJO?+zGX$RceTzCaf0GeLrTqaPLv2;NeE z%R_ej#5>!h-q{YFoFU>H035NGXd304Dx(xAT2j{u@OWxkA*^0R_Qn!uR#4=WEIk2W zr2M8kw)6nNougBe)VljgI!Gp|l@&P11bvRN9Z=#^zgYGVQ}M}?mAbhIk=%)VN5XDc zsW`#0=en2_@yH6DF_vosoq%{_)8ET~%*v7~I4@IIcC%=yC|Um!Yr$aUTF@nH!GK6e zwgd$Ww1m?x(AuGC&v4b<$9sEEH8dR=uKHxBzQ3oTX@}fzJbj{}=@9PMcb>xioBWr{ zf@+t@ByA7d4hNl1dmLNG0H=;CNi@nN5>crH6}wBspXoRc8=c{r7SmZUoE|SZ144e>j zD1t6Aw@{&EC=&KvcnAd4;uzJH6DP3ZXUnfG$Ahq%EQP58FuDrK=jr`2pKf2OVG;<2 z`)}8Kl+|?Y#C#LmmTuKf^Ws$(yntIH(}jVX z8}QU|%JsrZ2V=M5;~OV`2r&%=o#UD*WSW`I7|#r-TGBI|knC`^G@7<01a8LE&IC4; zo>{=^#}rFpd}eXDDKK{XJ1o+8=+27cj3e9jCup8ou5^kv0G73!b}A*6#=P|ccQrWK zUtJTKscCe^s#Xnp<_N2E*v9lxjriPujvOD`s&c`u6b(hbv*KxgygV1Dfz`MrC%SSS z2vAN4+87?$ZAG1-Q;1&eT>@4~cuNPjk%41VJA~E4LsOqN5zmL5N2Q`5eI9b1VL*O9 z_xxeur!UYv1BNASzCEOkz6}oW%JQ3=GYjZ|dgtP->-~uwTUVef6+}9eT{F53vVtu6n9IxWBUjcXeD4zDP= zWc7T1ak`?Ky|{|Ha_)O$$HsQ0GpmF>oZY4>a1<&Mo5#j>frYR((O|oz-d?HEWv2gj71lORUS==R3=tQS~q)f2*^`%QuY}eu|2l5TN zGEzC8EQ3V66qYG9&>|*PS3u{h4 zJiQZl`srnPclznu9}wkWdUnTA4yJEQL^((&S{LPD`lB2Yr*G~F5N<_)Fg^Zx2oR>H z_dx5lK8Hfz`i|LL<1h{HN46Pa(dZcC98u*V@d3~!iB91`f`p9n zxiC~Ds<1q0Uilag`Mf2O9=Z~9Z`K(h>yVH#__Bb15oxn8%b~#dOaIB3fMt;*HU?)_ zDwb#CqFhMRQb?GX2hQE8RKWf({?2_T{iRYtFQ%VX+K!(S+wmu2JN~Nx8NqR&C=?NN z20-8}Sn@K) zu`DHjaFIb9=%V#G=L(isOF%_J%GQN&9$jO4Cc2;SlL|Sw4Nw=wfdHl#nK%)>n60vx zi4y@WA7C~F5qoOXGw~mKVi<`!+CgZShLMO=RUJseNLU2iNEUR5QzlK~@t)XyM{Tym))=0rt zGcZXAyK)vM%yW2irm0;X`62y=un45n$EP%s0!$yKI(eyfH7@mE?V#OET#JgY+DQW< zA;oTS2*(nBy>9e~(S-elS!Do5sQ8EhJ$34@b;cIW?h$A6? zLC%2?9&w*R^5c?u1Xe1hMIfX{w#^&~O?&9L!q4RSdDMxwsqP?}zV%!u^!!&|C;iz< z1yhrI+S|_Z>+6!j#`nzg!XWg`QH(!~2BBld1tKAq&V{J3l}aDaXpCTfEBR#O+kCR? z`4bcL3D6EW2+9|wQW*`R8^=xUl9o4r96G}8O+|hzZqBx2y5eu&ihMyt@Nvf+fU?6c zv3tH>>*zUsnIDH)M^ACEtp>e)J;*JMYGZ?z_G8*BbM+i4ZjzVlo8)2Hsrkz5!1VV5 zbCC8#;CGAL1y4ilyXN4P*Wm-k$3ri~@89#^qBjDgnWYOly)`i5Sl$|8D`}U1oP0RO ze&Bd+adSLe-yB~GN64yyvJqG^)1P7=eiGWacmU*kqPWWI14d6@6jnI{v1H%>=!Cua z`+3)_uH-196;@^?%<@|Z_p(M=8HjpH0#U=3rJ*SaL=DRZnts&K^aJ_%kUaWKuD`&e z*J%1dL({*>9f(>z{j8zspWi2cYW4JQ3J-m?3EVS=B{moy^A8Cg^Hl*sJ20gB*e!z* zl*S!sh$u*x1275TpboTKji)sYO>2g$KHh!W*b(d|)5hJ{s&+Q8RqfteK5l3E*#C(v zA8CJBGCmdy*7b|U^a;P%PwDKRlvkiPejNpRLsXzYm74V#HiudEDU_9e;JrPU0a!sd zv8NJ8K!D<5mHMYOh_(WBwH{R{rlTo&Dy~|Q?_)Q-H2oV4OnE7%5>I6j+br>}2(mqN zRZaI*65MdPBAnUWw5YGy2K2(SWVPf_hybNMy}S{2w};q`B#UHzHo4Y28ds-{M;7hZt%D4%cmj_5+xfvb`78@2(mAt{+v1Xl2Z;xae+ zO9T`lL)nJSe2ZDDKA-Bz+-6mSHVR<-IdJc46>HWVM}@k=63>SD7oq9f99(U5k=M|F(GfTbGvL`ql)0AB0uJ7^O?S-Gs= zkdt-g13f#Jdm{)d^Z-b(#cN(zjcU&Uq)URysWVaxCl_N2-Nq{^{93Q1Fz1yNkF4K> z0E@&WiTqjL(3mWL35x}ZRaqi+O3PCIwM4a2WeSwdeU!4nHdDC@0YX>yhBg6}@;~|9<=z0<37d<5 zEX?5Weg@~}B*RXm>4eoJ25d_I^|6am*%~R z;Z`PwOYi3~F&pA{lcURKOF<1?IXXYTIQ!5%QP7UATr^)bk0D4j+SQfgqj$&6H*etAp01oUY4~Wg z56M29y>6a=C`)uXC>gpkG&{isF})VWtNbtg1pZZkAI`qPaeQ)Jsa4|jx*?Ad2`1dj zt~_p(7?b)S3*k@4UKazo3*i8lOLQqEC(45?73e#>SX}nh5X{m7&g`<6TE&dZt{MWT z7$K!b;GM@2Ac*_R!>A%7NwA8$hpw(DC|*-Dy9}Uz{>c)QxvwFo8hAsj`ZTEgyu;nV0|(TAFNMaCXJ$yM1kQ!qR8+dk+mw!$ec5h*AN@EdJXY0 ztJe@8v3d=~<5jOAHd;vnGFJ6kY^-vneoIalbiU##O=BofTxDN=^a#Z?;S{$SPaYjt z`SqiJM03aT{+i>?h0?R+;R8PRs#(}x@gtF^Fw(=vrsCcY|AB= zrKYbg0j)1D?sqD})%6lxImku9wT9A51RFemMH+|u2 zuJpBJRAmQZdPt=QP|-KA^c%_eFT%e(&b}vS9xix&P<_teWd*0UCbxYAG3}@xq0zv! zaL*gq*w>X7Hhrr{D1GCS$m}S^{^{e-lvD`5nJ+ccKQ$J^LV0@6x^Um_=od<2R%VNs<(Wt|t!}=aC`{cktCkV#9ZRktk$7NQy*P zkKp?hix1uPKF+ebFp9H4Fw~ z*^c?G?^8Iopsg>OjR!c@Xeac>_v%f5va*)x%(2%`_a(Uj#nO-seicM(26UHuj~hF? z8oC@B^X7-Qy3+jcRzXMSmuD>y=r7M&3TmCbIeK@bEA+2|T9-!`uirHU{C2_~H+_sXQjK_a3B$Xs$2{eFwX^FM|uW?@QJjq$RE>J*$u;V!0UwbYw zg1YXy?b?^$zT$V>0)Yp;I>^Kx{7XXkA-RnvXxMs@ygW|wa{echyj+)Tt3Lx*^&i&E zyE36NyWRg?0YX`Seo%nWxEbw#q;&3vO6OW!D7Via&J)r(5mJck-^(T0#b^%rbDc=P zUtXFw`s+yZMxr$DSR#m0&QGq|`$s2C_yj-CTc@4lqkZxwMBRe~bRzQ%EWk&M+yx8L z2tI=4Qc+JrnieKAtORhc=B|h23j&Y9HuuD%iEja|>Oz4pk(na-brd^)@hO*J=4i-c zrLV7phs78>`3)6X6egMn^_O-=$iC62xauC1Qhh%w|a@9@mGH`P` zDyggR=d+m$AqRhPdn{sq&Z#xSUaXQxt0AZY;!vu9uxNvb{G9MG7fSRB!e4vl_)4Y0 zMQ$jfETA5+Et)`12wN!fO%D(eh+iN!&a>#GLChmq(U{;)Xd23IRu)cGm zkhPoudzE{4?r~Rt{tBCP3I)E9L!r{H?#BhbCW)0W0l(TE<8-N&xsM0nFHf+usN;4% zm}{8Z=K|-TRpg-Dg@h>l10xOVU4?BFl?S8GLieeeKluHVPRj{h27ETt&I|}G>?|h| zW!=$gWgWO9(O`$M`fz>SA%Q|{$HCqi9wIA)Xzhx4vOe*Dc(rWDM{_emI`Q`|E)5^` zNkkIT1HbjTjfQcGKBVZQv5?}#by_!5Gy^qaefAOG`=}RZm_ddannLA$k9-})U#IYO zif-uFI{ADbf4+gwH|Q3CJI3xUYx`B)@7wkDThubU9ra$S0E+HXv0gRefrXCGnR3G; z#VVg2uK&&!M-}~XFBI_z9-)^AY3Q2>-GfzH&p2>Kh)$Ensp zdk7r72;#7ojVO^%|D(eM_2FlN_V6N?-tmyclrLm)XcZA-Q|6H7d6Gvn@*m9sg2fMG z0%3Ji`_oX%I@x|FqCJdMQ_GoKlW(CIE8!7;F$UadQe`Go_we!jaf%5nWQr{bJ6vKq zK8jC;k)#ad{IJn~ z;Qn>by;IOJp)L2JdN-NhRalnC_cW(D2`OuFJ30qvP(8AAA(JFrl`Z#y$P-09glpQ) zCSGM%^^LR<<(DhybL7({?YIM6@#cH*12KAXZkzt+i8sH0dijH) z9-j>LzsAW>|9&UKldq$?Z0o8&aOtbR~_ zGfTHQs|F^#>Q$COloNC7+XIu*0j3d#732e2vN8c{4J8wvRKyQBefDsF3f;5FU9@|e z#%$l`8opdia-M=CX)}?b2;QE=%kG}71QG9kEojntr2ETlQ=M z+6AU#Kc&LLGj8>@>r4PSibpcK`dA`-JWcGI-4CS`&&~7Cr4#qfR;P60q1mdJPCPIp zD`!O!%$b?WRkU4J6u|@;eq=0`6$ND_&=4bBkm>TD!u5y0iY;S*6(wa(%wCA5q4ZTf zS!_L9Y&~6UJzZ>FQmoA4la(hm?c{YyY&fG&5@SvFEr++_pEE|A3Rs$%)*iD(h-@Pu z66DNu_gozZW6@{=KJ?7_-ke($i65qBf3MGsi6|WspGW3!Z>T5eB!15`fv^tYz~yk! z0R@tFxJvb{)xREpcnt%JyoRAS#CW+>)m;M!hfpd#Up5-d-My1z?z>i%%Ve=ytWj_vUs+ZK0h zOWd*Dk~_BlkR5yekR7}KkR5yYkR5yQfE}9zqzg0w7JwNINBejX8AZq2xnLxh*wcfA z(R94M2YU1@+2<3v=sVfQALz0;SUL+Zl{gdvJrMvakw)Co)9HlhRH-8*oiYkql{#6{ z>7tlbnFA-CQV3?1e>jOqy1KM4^-N#txqYdp`clv7OFh+>dQM;JnZDHX`yxC3GNn@~ zj84OK+zNhQkw{*H-Ghe;&u@waw4#S>n9zrO)em zbY4%R^LiAY*EfjSj}wdiZ#}x5KgiK7NGjex55~c755PG12u(s!1a*!0q*JS2d|_Rx zu7>8OPi?Q6CwpI8IBK6?bwi(c#P0>_Tr*BRcWV0pE#|wE8?4SX9h}8f580yla9}C*ODC{ek{Zlvt^q!apY)P?-N-1q!f{_yXFQ~58?FOdAT zydV4fzm6aKd(n@*X688Hz`kcPH3HbvI)Nc8#f34ebAbL9vL{FYW1hJrjUjRw_ z#bqRAv&;poM8gN5LXy|;)tZLrXTw+PT8I>0Q#?|9n^3LHES1O9g<$LTfU4!jctO>wz+_NyUFi8}8Q0=YBY=LOcIyli%?8vwhJZxmbjA zctxrcGOT_2^r;w%bOc!-h{t60(7Wk!6@Df*J ze@B$BEiCh56Zx0OGpo_rE z7pBOV&I7{wRSpOzp3e`o4R)|73!OjT1|t<ff-k=H%jT`>MP7CS$*@un%MB5O5QTO zx`IlXpe~oO1 z0flD}H_*&-z}_SePFx7_Fta8&2(Uh|Z|ni~G?uq@H?y1pj%qThA?lCq8UK9-!FwbX z(~x{|2x+VbkyuD4;vSuUL-6n$CI#grqhFcvg(MC6z*>BW1IwQH28g3(6YJhkdK0&Q zt%T^S+XFW7AhPmhbUDVuz)yVogc@oG-;oTDn{Gdj zN-&+oV9$b$yP`(VngY-q#4tFSrn{pCn$g`-1A)HI3w=fU)}NffUP%H|dAop}V^NY* zB%J986pcQVwXYvlH3)rff4cuwHGOQsw$Wx>G2zTm-|YTNg2pv8`yd7xn|-*e&r*q^ z*zG-Y2Fa%843drVlHHgiNOo(EAlX%7f4`N4ct008w_6_K{W_740RN({m~zTfwk4b& z!#3%Kr~}P(UA5ap3l9@*|F3iG+1NKO?*4rlYN)0`bB}qt&Ej+ie>~krak?W@4b1N6 zyzxX<#JScesB)CBABAV=Q@KbakYYLdO!fgHl8Y*;Bh{~S{Y^mn8%>jlO5 zyOvBZvw?sN)NCP}USj${lT*h4N&2kK17wIz6ta18%pH&tf9AnL3PX_owkLm0kCPC2 zns&L%1lDZ#pb9tv?<)Y6Utb5M1yT7~fhD4T1swk=&|6W zk&vRnQe4z8f8mCwA<2y-$ictY&>>LuQ5(G*ZS<~uqj&Q*`eW%vKLF6i(i6cgGZ6{} zkVO-rj0iF{5m=y$=a>fWW2b?WI}J_%74M0s0VsNUTGXmtt|zJS0hY~^8fqZar1Rt; zXP)%HZ;&wtFX#Kq`Tlag|9Q^$`V(yHg^G)!ZM}?Ue?l?NRlq%yf+ARMI?Iw;{$Jyl{fekNXH}&DHBUyLF`&@uoSjV{)WgR4ScZM z{e9NB@d_!h`@bfK2Y7VOu=9F~ow+1RwL4*ElM+d1a0MN)oc`GLS`*`jTC2Ww-3hiF z^+rS7e~$IM7+jLKOSra=379s7=a4k1pKEg3%WrIpXQHv=Xm~2CtmpmoG!ZVGH9gYF ztkvRS^B``ltrP77!aN0g!E;EuH9dnWXojP{WTZ!9-n(q(mLCWH5-;m%^VG!b9NROA zoJ%kZ_CXG1EGD*tKTx%h(x}ev0J9*%Z8Rzof7rm$p@iSZ2+|I)06k3ulW zlvoOu)t}1z&IMUv8f0*V;9g*fKx?2TqM&g4Wuu`)lr5#0d1#|WIPvoBrz~Ab-N))C zCEx{DwSu#qvfA4iE&9VzlCg|5U6PX90nd=|DUqdggp_q5jfR4Lk2Y?wZP2m)RlcTl0O{cvPvXJq#$v><1|FxvXF zb&NsE9LDzlM;M8S!=VjEw!L}adXI*mf4tj43)VsK?Bv}8w-MGk!+R{2WZNUe_qop+ zo$o#(`UNAPDBq83^{)aMPNNvNk1VY_6GQd}pzevv43i!dZR=S)DB5m$4~n+`13W0& z^Jn&;X!|8RD3Xa*c~G?bFCG++@}Ou>{yZKO?P0az;zrIYmQND{qHu1|C7LVby$U?q70!w&Ug&Jz# zkmo6RzRzNcsZ})AKXo)!1KDVhZ*Jy@W@(;z_b+u3=^+iKuU?72LSj!6z!uB&bih}G zpmDD0>BP4H`DS|v23hS9u|Aud0APmtrhiepjFJy|q8pNEU=AVC%p3}de}EmbmdpNf zIn#241ojyf$U;&#H_;(lkfs@KNEyE#nxc`Z_RRKNO;M9EL@2sZyb4UE1QPPgpr{eLmo1ptWPjsK9SE_$GyNqkGt%&3iiJP0HZO8J%`&ec;5=4nN zp%yX8c|rE{$rV}zF2oxS#uV4~%~!W~H4sIdK)(>RZ_Ncwp`f{Ef5V^XEG2My?W-J2 zNh<9vEvzjYd9PMOlaaBLO-_`#QYB+TeS3ySwhzH;Q*%|O$FP3OEAs9fpmIcfoc3)j z;SMOCuE-p>o=1{-{s2kl^^cHb-aWS@^SX>A^ZG%O%q}HdEK;c0P6hADb^yTQ+C z2;kk|)hjj)SPa-0`Zo}9fCIn*Mjn@1UgLWoq=ph98cQ+4LFd-tlb5#GUtd=})8m#? zMJZKBD~Js%&3TCZzGu$@*HayYH9cM;L{;knBwWktk5y4Lf5(^L1<2(%qmbC#j+27u zb1H~#bNTZTf9NCx(Fe~jh(0PWh;IFL1ko)~5PkR}h<*`7zX+mV1koi0(I>GS^I$cU zkD8C%Ljgkypn4vT&+|tYapnp$&uwRv6ajo2+Q{L2HnICD>U>*~|0`fn+9!oV-cusj zJt2bKvy5ODe+5*ud%X$r+LZ7%SIBFd?PDTZJ}|NIW)3iN{>i(tXTmj|MreGJ`x<8CzA=zT9`Vy{|4p5(1;2 zYlT0FOB&dout9L?vFA7A2S7m3j(WnAkbDOy1LeSUx9KC@h*}`skKLQh?2vtKNQ4Cxu=Bo;r-_U(O3aypQ9D`T?}Bz{HXX zZ!Ca_X@AX8n*8(@lqRt7^9r*^a*@$k_x!vs`@ex5xkUrsLE#|s&B&at@+{?L1;j`= z7%6WYf3TpJ*bJUMzDUC!NQ=DxrXt^9Vh1bf{TEg)flzrT6*_XWLgbi%?$2=F*N3(< zklaO;{nOL4&ga%4HQDw9E13KF6T}@Cz+61WP`#N0hap&5pOZEfn^#{?)qpi#D{tLR zDsL86{;qvq`SfWOxJ{sYc^O`VCEJu%;v>(qDdr`1kE|i+{hA5&wQEA^s)Y*QXar#ET^2MH2BMi71jp zf1vh<>>`uFP|hHp`WZMME^bL&(5-5f02H==GJ7|wru$=ShSdcTFx$kJbXHY0okv7g zl{5CF5Qm!Ivv^eP4^liT0gDPeYZ97F7E6i-n6kvUQZ9=&mB%HGyJ@AUhY0ge?waTQ zF`imR`=?k>ss?8Jt(x3Y`L*#=>e}c;f7eDwYE^O3MAUluGId{c*hK=_s)i))!=fTD z@8S?58M|rwv>&jI5jxT!A`p@_mqcfB=7dF&0k0`H@|m(@7gaJ<3`dWqO!)MXWX2m& z7#U!@&S$v)u=p|3V7l?-f2}*C zzL5wJZp{Ptz@5&(@y$@&;ZR|SqlV%@EcHn$46i@KlgRHj6ytXRaA5&~H;Ms7%Yvza(_s z5*=2e%9m&_k5sh(iK4x<|5dWBfBp`F+1J)rE{fg5?Mr+^40C>mEZQyPL59A z8qlz8SDteejxfoP>c<6dKst(G6 z3S9^5N{IS|3yS(hnIdVo=%-0Rzi5r523{NK*1m@;_wKyn&)LJR<&a&RR-P?xPYIES zVSg}U6H)jnr*~fQv>2(6B@4Ttf6-R58ybaYf^|-A zX+-vod{HDmH`~8R!G8PZ9E2T1b57(Gsbmaacx(=+yTt$!^-^N6p}JsLM;Lhi0A})( z1|e?asjFr;30L>F%YO#^X%Ew4FWgHFjS9&w~OD=82vtfDxGoqZEjmAOe%asHM@7SV{p@|?0v6(uWI?0}<>I|=L=kpp5qV&^rj1oj(fH6?6wSf(#l9we3|ZGw9a zQI%fR)abY^L3J&;hJEQ8_8)!X<*(KmARopMUfKg_ek*5m6Q#RAK8|A2{~sbs3pqEPks+M5@B z*4#^-G02P?PJN^tGNBYWws_N&3RHB1rFj@n#rHbHQTqU9CK?v8Q^xSJpBMvV*z{94 zWZ@+Ee?{Z%JP6oLk{?fq^U#uEjIv9xl(B8&vPA(33{6iP0(h~#2N)lj>kp$^V*e{tluGe^9gdE)KNPT$Tf;ZF8Y3$lEG zyGDJr;nB_te7k7m{-z)c7L*LH@m-AF1{3!CH!;GVBZIEwqBlOePAQb$hS*I+W}{)T zTQwhB!$Z*wpz0X9vjCP~Jm7|%HoWNs&!Up)IOSC`9q$L&0(IkP7lO2uq(R4g84~Hl~BkRED^p#fcpZnjaQRxRzNm((aWP7 zs{Ax`y*@T7ESO3}B1@hznuIJH&7LK!yxu<)WoN4?+bf_fy*96$kbP;g+zBZyfAtSV zwqB70sxt)%6r4V&y``ZJ!FGf_Rzn?v?FegJL!Eo_JR{Gy`V2F2e})KZBmfD{%#NM0_Hfcjf}P3t2aXiN1`48SQ9lrt z0~>UTu_Ybu2kq!9&f_BB!E#5iVg#a#G_iK0m979D3?2+T=sg^2GQNk+3XliY-s7go zF6%_WZGfoewN}3&5h!JlKQhe;RD*FPR-)Y^>4zJM8{LRaITtXd}vPf+c{PJM4Zm?6xTeT+R%; zfRifca>J`TF}6ua|4V*Qt$F|2JcVM0`|R?AKszvQ%;KmJ4* z_bqOJ;$-xn^P=EU3F$f>!G))@t3xdawJWf(rm=AA@=; zHC{rU)}w(pR$03}8q%V}fj6`eb@L+2- zXuw*HLO5t8F?)-{34Z8yPb;6!j*Ht#0`CU;I0$B+&W`t@C*uJ)e+w&{^4odohTQtJ z8RV}NVWD&V{2HLU_@aHC_7ypC2bc*AuVR}Gc$+rXh$UELZp8Q7_-@S5{S)>VY((e} zLYLSsgO%rFXV7sb45N%F?Ic&@yTYq+m)vvj$UV3H;MKTlmw34G#kWQm45)(aanbZT z=V$@lm0(VHI?q4f`}tQ>QQ1KaaEiIr|e? z|9nka|C~_kf1gus^z(&3oF%M(-aY@>`=z|~&*5Lk`sXn1Pu+PN^C<6RJhIPOh%@ZZ zCxKtgD?f-sj@g(8^Tclp*^N(x-FQoQ;tx`uIB<{MTkIWJK31brB_fGbO5Jw)llcJq zWWJ%!PZB?FiGh(qJTsQd&hKgf=93~@`n#}evW8p`f4u}Ia|L`<*a>y1`|cF0oeyfD zX|$v7a~Xc>GCQ+I)LRxF&h6hZF~JVpz?uMVZLH>U&CXZR(N$51qpNSapf;MDE?Bqp z3mr`Z9_ygCuI`CnN}uU z2bQ|jq}|)$y#+aIpB>a$r=?O*Gc;172`vmAiqR8Cwvn3W;0<1lslDL=tnFTu_c zT7WkoS;mCD#~|{Q^vn+EG>=+De53mA+zAYuf1o;@V(%2(n>_JXXGTF8F1$+wE8B2h z*P@w8k|)hNEiOJLJ=%jTX3R9dsv%{4hCNf!_&X04E-&y*Xoj%tL)5eS*Wl7fU5ntL z_Kk%CH@MeCLa%^(C%$nlF{4}w_iwS-tuJpdjld<%u!cx*4!d2g+=dI*YFF%qqm-{IWEVwL-C6KMZ#C85- z;raTRoUb3@I{!&So&RR9^Y&L2ZtFA4^YM`rs2Jkhs0tZcZMjrx3aVAX)FP7t_5esw zt138-$P4Lrrrm^Yh&%Hf2uuk zojzXGR|gV3Sx4bsvmaE{x8Mw{t*RR|nft+0DOBEh?sQd+aPfPp`nv9_+5-2f2uoai zS5-${=E`Z-NR3a^w)d7_IrZ$-Q*C7VB;8XH1u8y<)2T$oBwhH(D~eF(nRQ$FfbXO= zPPu$>jPJg^rb8>RimM?u5-B$Bf0yTH<9?0VxL?vTj#e=4dY0o;AN-6Hck**&e)|wH z2M~ci!P=%ze7vJyWZE&sq2;qUI%9mtSx2WI%SQqpqDT;%1TF)s1A0gpx?c+!x*B2V zekB5v>H`nt=T{Lb;)pN|j>q2ZJO4t9;Ew4F#c5i9{%P8Xr)fR+wvn8Wf9g*#Tav0n zoJ>IzkaT4fiSh~05)>?!@2FdB6wciynY#_RjMOyL*_7)Rn~4hqp~)XpyO~cO>Fpwg;mi`>jk}KTJd) z2^vaB$sZ!3C)dp~5_-2xDtcEhk&xW1R|xXe73W?gDdScQrfF8cf1|{IGepW4cTTk7 z&j0s+|KETEJrn3eapSMtV*+bdx&tY2!6094utAPyOppYFM`#SPZAgj{6AA@es!*s^ zQGEk#R8g&3Wx55gq;5eZQVA7?huS z%=+#JB`*?X6d0-5fAy`Zj525MQz|v~ouU(T--8nrNQXLG8rrwNgHofuA?P&ry@%^G z`c{98Ut7-LHRCYKD>hbXFVbK4F-!E@ww?BU|vwM`8-G2YiV`jHMNgNtvek_-4=$Fg=e<6S9i)ME0bs3vCHnIN- zHgBw}VTesfA5RA`Wyyv=kQi@~+Y9hjEZRobof*|+u#1g!u!}H6`(v{>dcpogw63ZW z<0{W|2r855P`o4pVx6;5=HILysps^5g%Dk5*oSRg%AVT5SD=Asf%RKdvkc}^nOe4^ z5JZ6__h#ade*y9?X4U}C5TK_giPq-T^nahS>stxHU^YtO1Hwvsn;CDnHxl{JO)Kvl zkrhA$0KQC&^m|b;iQI1t^7m*UDaP6=QB2RX2O}(NMQ^iAD*&E&B*{H$m&l!QNR{A+ zel1xJ_qvo7(rJ||M3(nzS|YDEmk#9JyhPq>d@sv;f9;gW%Pa=79sYNT%;L33QpUbj zR7QM>bS-*q(Zbyc4l4UI;NNEY?I%senwk;q?hiC|e@y&`H@BO09veiN`?vx#p&ux_ zjy_NWw6JdtRWtwj2?hJ);V1O*m^^$yNA%NYboeWI_zm^nl7}uj?vRHz3O2~YHTrKr z9`4XDe|_?BfR4Aw!xz+|iQh7jIsq><9d&cFzP$s6t&ZBPZC9&c%+UcCU@z5v_40NcI*+ZKkVZ<(^2?*i7Q5g;lXC2?r_ z*Yp=z^C3Ey=BtR&*{7<5Ed6Rr+dCphf1%n^9Rz+`A-XQ8b)p}Q^^;Eb=-rpA^G^o{ zt@Crid;yavpS}U{&hKQ>i@Y+f+UM`l)E@yjA?lW_pYV{0+9^e#_I9b-NePL%I|cdL z*ZNuOpmp@Qb#;F9{^aN+qJT9A7A&y)ppi4EDqFV#dg;Wzp7;*pnC#w}U&*`uf1_j3 zBk#C)OAXXSQNMm_op)JLp@!zV&11M?->2QA{G-HgC{R1V)P|Z)XSz6lAQ~H=LVUZe zLew=n57{2UC8N>%i|VC5AQo}jB2f2LE#h&rDfF*C5Gd6=TKAfh&d-@@&-~@QbD|R! zhbpO-SU~Bsd2eF(KjM2ZYneb}f3bNef3G3&wKbWzw+9{`z<62{Umv<&%Myu$wFNj< znTIMSfsQm3Bd=LE_6QCz7z18{wy-AH3smL6olk(b3n~@`K8+Jq{CUs6_X9kw*bWJx z*8}Y+_Vh{{__!Ws@n8X+=e**2m5JN8CS%tRbVWlcO3PY76hVuqpN7!qe^5RId}PxD zK?lJ>^hot*uH$2ZH!7?G*E{6kqy34EodABqxFH{MS+_?6)HiM2w?~czf^IZ1ZIDlT z9|+JX8q!gwT%|p{R{@R#tdkJQY@DdRhR8Z_bohgKON>RP8ODifX(-ta;{>i{QT4`& z+SgEAzj30H*i*Za8}2Rce?h?xEPZqMMC%N5+Jds39XEFLt~fpYocQXNhAFmd-)-~8v*n-Nl8E8?p+@ajr@ zWx^ZrZg-kC#S+gi9|yo;M}mSNXa5Z3`=|IC))3ttC2x~S@g4DH7dG4V_2TbkHe>nj zN7t&j0S4j*7}M#Df8N4=^p?)2d9d_XY_wdMeKH~c`JOar#k?^UDFnqZK$9xwL z=wZP2a-7-A1Gr<84pKpYaiThU=B;FRcTxwB7KdU@5);sifBkWqnjYDbCHpU<(?@(? z@q`Q&imP404v9tHez$*hc6xMJv77<>(K$PMe{@p8&W-K44l(|WtS>5-hbuk~^#3@@ zEAVb3^!sY^E&1y#+T;$-TKnA=-;qP~u7IHxve8hS(MC>T!qFEQd<5{HA(8=H9EIqU z>fR1e+{g5Rq1&+^+zGSMaBpJ`? zc@!Zek5UN9ASMRXYO3cVo4h&Ezf|>it?t2xtGAzyjt{SnPTqB{*u-cZB2NR$GPR0^ z`iZ6zI9~u!Mz-E}r&BvP|FFLXU>slK-yqpze*vi3CmxPEB8O$FZc+VYgKQnP4w0+( z=JsT8(A!v4)^52USyPjGDlID*Kd>C&#XvGyf3YgW5T#=I6)W0e6iOY-RNnaX!sRQl^9jHF zh;kLM*rm&xs0w#&IxN7+k8NMKX0{p7$HWy^MtX;H)&%tsvLx?)5_ZAiNmQPN7Gd(r z+3z##yK}FP;qoq)9H$%5k>%-J(Qs(E z*D@4n743M(?&yFRLP|G1$~GqUAV~(C-G!ok4@$_}ea_2m7v~}&@4g2iyOfaBBvH`u zWk`8fL`nitR{HFK)a8zjf5IKSTW$yMCNLhp2MzZr4XH%#ii^1vbevDkPCknwku;Vg zmQ<`J&pMk2alSPDl2qPjO`Og1m;Am+;)Cx&;v>!m+LOVR?F?N79p+Q_AeXviP0Hpe z^y+=9s~)BH_ml6@o6}U&PYM`Te$j+8_fX~EwKP9Vm{~|ONvEMKeRwk&Bivh8s2Hv zzzUXI4U1PBK2_8?f48W!e9&bsm*N8BqO8EI?FK)m#aX+-t5?^80bm6p|(N#;N!mQ3`j3Z(>4sz09>oR zwK2ZpY#!L ziD6Tuogrf77(K*<@5D_F>+lDO1sl^4!S*-MG<0M7s-_MuoJ%y0?rmP$qbh=hn5&Br zjYPk)f16N4Gv)&`Fv-Rzy1n!@b*P1CW23QIbkuaoQPVFvYT~oRiq8`3&wZA-rtGA! z9D8a7ph+eV5M5XCXSP#m`W09Sps;dC09$}sQ2yr{-w!=&iv0?tQj7%v0slXWu^^sK zL)V)Ea0hXsY;0Bscm$h7s3Bjv4t%dq5N~ene?c%NlYWft(KtZF*J2Wosn4gj4;f~* zgXV12teK|2zV7GEB*mVN6twWYz7e2!63zEqo%dQ%kTnSm3y}sG4x-hA`YA;7>_te*qr;FinfB4n`&==)pCb8Ke>@3|!} zVF9@d=`kJ#87ExCKAsW!W?Xa;t4wyNrA~V%@GL**;=3SZ_O6*caa-xBH?X{GRzmty zvOLzcY>7@HAuG!vO@m!t;$2Kg#(EWFf7FpV&T1i(oKJ37+_xi{)?Q#*yb!}9zi5|j z;>%_6qBJy7HPzB#9FPl67J_8CV3PVt5VtW=-TrrOc{J#1W=_YDJ<*BTa|ieJ=(x0< zG4||0K`8*75XA=(crng+N#rCo7rc*aH8!SewP-NbY9X4zo;ZWcn~>O5HNEG$e-oA^ z`pGl$7xcjBQC+FHoClz*+of{Y>@_ppdoLA=Px<7~sPhAA+@e=bCm1w-V?3Ev=6j&3%K&8U~c=yKk z{WnwU8pa_Ax%TrmC)`S455XoA6n%N8MUP{xz{C#-DAYZ8&|ZC0 zk!JjRWT&Zp7z42dayCc!Il1I^Qh--V1F994q7q{w?VYe^==Y4nP^9 zbD3EcbHPZFhxaS$Qzk+5g*ac3Q}?H@ntHCOEsf0PJM%h3JI(4&i9_`3%CmE0XNw-4 z{2YYC69g3W>}1C%oSltob+bx+ZrODb#v2=X^^}b4U#uqwYe*JYS|MK5paFo1~g^?qf$f4%<}zP z*Bh`Dvvi6u6zn&kKv);}25jx=od;|Tb${LiqfC3`969QOe^hBWh?i}QK>~3jToCU~ zOm%&5bG!xdi0EsCt|I=Cp9!~nS<%|$3M~Q`fYrNtcc!U;dH6;Nvpjbe&g$#j5A5N6 zG&zt3bLA+&Q$Kzui0bqxw}^!0twO@8B7bUZLg0=jnv9GFx|eum8(L_%v-2}JX+1!oGru{ zqKztGi9cPz6NyYZl+G3D zB%0*NIciF_SSmOo5KLb`f^z|ZY0@4w7ltIwz+gKNf1)TDN{jxY`>UZit~a$N3Zm}w zP8{)as@BXeS{N~gJCos}6%o>P6F*is#^r zKaVt8e<4!f`~mrt?dZC$XbfZwoyu4ne)<@Rv&VLw_*_ck0Ho3p-*G%Zg>r%rtP3I; zz$v;@7vfoI%=F`}P}9^CdU5_rp=@I)G&dpQJJeM0bw#z!#zv!r^xy;XK2Suo7_KZS zJz#f4mtXLx^nf68rL3z3WBmYb(|At?9!*4Ne;nb&LD-p3=@kH`8pZybN55}9J7CYD zX5fq9(sYn;rRzWJ=1(tZ;{AV5{9!CYW?&-A!S zWKl}+;$;zvB^;VG=OOm{o;?d(kGO;BG4TjCyO;Hc4YUOtn+t&55hN864JX32IMI1b ze=Zh9UC2tEvQ^%=yz z7Ih>X7dyRLfL)2Sjq%#3iVLNBX@K)vecsPvf!m|p-YV8~O%=qm=D zsZn2p6x>P#Fs^@uHHL;Np$$fkh88hZXuKh5Md0dW(3vezG+D4G6zr8Pn0ONz`6Qs< zsn=v~&9+dp9oNiEUi{^fv>_E335Q%OG}}#L?)`vWd-SqvuiUk#D|YRh|HZrZfBlc# zwQrtl*SD~I?_M2IgAv4t03y)26TGU0njz0gdM(M>wt}%fweD0_ z#OoRYbe5b_D3u;ujA@#_KCtz(f7apAS?i#i%}+Kv1JjN6+-$`g?e!1ZXzyM&+Lasa z^@@$Q`@eXjZU4xPw)_G?Q~$LTZyV`HU2u&-rMj?^qAe_}aVb+F3` zq;oEjgyEIKJQ{@s1ppzkqOh1N_DpWr&1@{V4%g$xAYMw;DxlZ|06wi1_bY0No!gMr zeTut7d$;ncQL;1$2aRKDr^I%PIqpZNYuUI4SuFbg(i1?BM>ZSm% znVB04K+Oyouwod7aLyf=fBU;hZR!s==MG=axs~VK(Ta2KysU1XHRgDajw~j5aC}SwGnqm7Aj>1EB6_VLb!fWFrRs9(WWnL$tm0b*4RhcHGwGwY z4W&?eaeDEsBz30z=?`aMZs4t#9fAqJQg0?MA!9l6w6twg> z1^o>vD25%4)${(-**=ZBBYP{PW*}BkI`%u8;yj(?Tu9SB+dnzqKS)k-!F+f(Q_26Ppg{rPnIvcQO`4MenMtzI4@!v0fl;J9{X#cc zM7_A@f(3S3e=%zRAdc92;fPmq#I~Fxrp|+l2t^PqgRdR;)=?0H4~*Z0$bT|6%YCGn z)ih177!z=hxaI{hUW3M^lylP$5s9f)G~G`qa}iB*DHLc_co?FsMx$9+q9<864e%UD z!5?hw)WF{Wj1M*%b%K7dV0Y2>+QyTwpf4M;jv%+l8?E}jjd?40b#v-tT z3GUv{+>vL^#`oN*IqmoiW|_=b(^$}0cE*DEpm(6A;NH+1f*b#YTD|_Qweha@?j4x* zfKkui8vSOqzX_Hou^*kG{B1ZKDhdC2o_w%T+o~#pV<0aVZx5|ujg{-^_*&oJs#X#B z_>rF%e_Ie4JyDIP-&dK_eeB}L%X|0k-P?DysGY;%aI+_Ar!}Z=S+Pkh&pjLttbrBh zZZ;c@O@+2b`P-mTAJ&ICosO+)jR>$o`P*<~xH;TbkTsjVwY->cAqt53ET=Q!-Ju%n zXsV~b-KS*Gw={v8%HOtY+t_MA=t0{LPH7ane{+iFD46v^y?D5VHzG@+zYTG}*X*;5 z++1rQ&5C!1)-d(~{96+bnmZc=7h!D8FvmAIvj+CuH`0?5CX#0lFrC6Qh&%JBFUt6) zP6*PC-HsjC0Uu>>K|cn2+{pZy2bLMSPC%k!v)_UdcCu`gw40WHWNxnVkKD~Q)mgFx zf4i^^AK=LZ`Zu^Y7E!yDnun(fwaU)CCe8ni+LSk|)iAT1MUt_WE4A5O#dpCkfnhgP z*#GoeT~k8Dmvd~p{kqN!@n{#SNLjD^^B)RNLV8`#_RF95#;hH2S$dWLA(#WQ4aZo_ zeSCuNg3r`i4cz2NFW*^Hdvb3muR(}`e_vCSc=Q&0e%e<5ocw&}IsrO!dv4&O4|sBe z;qr?1J=>Zf-*WudKKAUPf_iL1$tDXDNUYZh>508ug7$hHJo?4^P zXh14qB`L4>uC2i#tX9<4SX~=O!;+GKRo5)&Kd+9E zyPB6Ms;Pgiu!h-sDFBy`ZibAw^^b-+PCJ43Y&ZY8!Ib>0eammsE|yC zjS>~st1BzqVk1;oA))409<`eBvZ?ds{EZco;n^uuVY5_)JF6-r)T))KaC2pa+q}Y! zf(j#Q6;((k=r*glxI!`u3v1lu5YJ_Gr znyl&-H9|SBHw$VclXRy{jhicLtVMIbs7ku1Yk4cX8SlD{ZC3X;S4nDXl&G>uA zRh2-`#zvVc>#M7bj_cQ31ywfqFcnn^W8G}Bx>r@Xv8u`@AEuR6ZWdK}8G+|f2SpHi zjqwx%dR~Y~q!+0$Jkr*941awhLdV1mkmC#wv4@>LN8JEenabGmoxelCK?uaRSS~ZK zbboA388F3KjR0L_)lR3Ldw0(hRSDDz>+GQw;9QiBOl2x0M;Dh!P=D!wiP2h>0j)&( z4hVG`b=FPl_*B=lRBbO)x{(fuM^zsepnJRA^+Yo!k0XuP04c4$V;S|H?F?8F@H&cv zL9DM2RU1s9cvm%KM_5F}=Uc!ciW=_69a4R+-t#el)X`Ep!@XGDCcHJI8lbByQvKD{ zaw*LPpzh$c8cKrl#DAk2f$s$C>nwOike!X^Fw-meZsyUrLKG|p+rb!nfGYzz!AMe^ zp1Zexf-VodRUuLqh_nmZDXUd;&?Pi3E);C3DvWUa=^WW(u`cOJqp2^Qlc>`Ug2H-n#At zTLLX8zD;MCcUrIv4?i$Q@f@A1vY?X;qRiyRw*e2ODH+9G$ILd(6Gq-yEb@ML=aGA%7K2_6hyS8)ZLXc*zz@6o6Bw zf%gdJtfB!v12gnDFL+Eoo(54XbOVRz5_z%Bui8^dsQ?-A@D31++9a+}eqY{NgERc! zIralmqY}5)%4yN<_aNyfXXd$JGXM*%Jdi}E4OD*3p-BMU7q%k}U20)E($sgxmF$+s zm2AJ@NU($qJcKpz0fD_gnGdiMhQ?9q_H~pfJ`p88Q7R@@97eF`7{8o% zPINj{_V6CiL!^~497*3;094g1Fce^{7*q4+s}Hdt6^6q18YZ_QNfC}u{!Du5AH0T)qI41SI(fS_** zA<&UxRN|kO7T*!p*V*L6PT+z2lOyqFiuhVsFlorj-5f}Ed(YE-AzCMokLe&=Gx)(& zkVuG*sl|c0ywFj%s|4Cw9hl?gk_OS%V1I_0bRrG((++?vz`x`d_`R44`2)YXp+7V5 zCu{TsY*m{C66=%zTAv8V>=_+J9wc2OyCvlEO?+WpsxBaI`*inZ1KQUX5T=6BCiKZ( zy%(r+&4^A}?7Nd2tj<|Dcn?_msLro4SWi9-lp%=^^+;eOJEx&sHoKzm+(=}3Tz{zQ zOtnb=z(q-c14cnOEmKOQA@h?Ya@p0E#Ga3Gy!#$O?7o-Gz)eDTkzFm~LSyaA}CGLCd(7M5;*qV6Q8r)a# z9q!LzAJG-cQ0=l1VXKb^+Zh=9&$JhXa{UTK?m#S);{FAo6&NvlMLsfuc z1;T0T>uWI&<00#!cF7qRPJixQ=$Tan0YNPDf>w)cx}+{O1V5SIVU+?c)qf1zw03(Q zwyu)_>MO2JropRM-01=;MNlQdTq21#j5w8Nk_47{QN7#+6KC6*W14KsuuNBXXApgM zrfSI5VV=+*aZ+yeOs2YRs+DI>7Oq*1iVf|d z+F+m7*VQ$9xrBE9(KoNaP_+xHkKHzJD=s8Sba+*&~SCg-H0R1EQ6TWz+=&4T_PU;L{ug) zQ*o#Y2k|E%&4-+b6H($1aR7}E=2uk`xd}xgj4!m9D2*M3Ewt$pkM>r3sMf1Z64{(e zBG@*4(Lm7(yr`qVT!fdqd?O}DJWKyivtF&jm4*KNxlyfZaeoF12{vg%cBF-FJ+O-{v5Q;jLD)!;eMjElZPs8f+2AYHV-4Oh;`+`b z+SIBBZ|Nn3#DCPZRde+xVPgNjD)H~}#Qr@sv2&(##2Dq1PSCJ1A>1B+NJ7iRkSRGL zx)>-$Gv1Ri(CLAe%fJPKZ3;Ia zdh6Abs{0+p3+qdI|ZCKdMR+WR;^wuVY3p4{-d`Se#OsTbeug$cY8keZa^%z7ntHtLk&y^)Y<%n0=O>m zPczVrz*PR{e}oh$2p!#1LFi1!fOFRz{~``w0+g0WVSPLq?!iA&8SSm@4BXp2`X>@Y zn2tW$bM%pcseJ~rOi#5bG`DM7A*$E5wpIuJc7LPUuvUfEfz*@ugjI%?4dyz#=>-DY zHWej$nkezHwS)l3egy)YS84!L2BvP*uv%@aS%)#hI=+M0c@od%f!inh4J_Yt3_3;f zb(d7Gdw@!R08ocoR^AZq#@^;pG2m`@!|~dY1CndctnPY0i-qlauU=^s#Ye?Z^BH{F z4}Vn9V8nnj)(FB7=z;rbHpAY57aO7_5U)}w)*1lo{dT%oKRCWc4 zE?*S=C+0XkJaupI{$xU`^?@ggd!-y$9+i;Nki@{RWHX4pSuP!^vpLqS!GPp|y@*(g z1p3hJ&wZ6JcstF_MuRx*^MMaUoekG%Ab*RgF&yxUUV#5O1c)W;pij0!G7f=MGzY`j zr`7~;V*<+t_6siC2{|IuSXCT%fb~juj6F<*0#0Qvd;u_nV2r`;Y&NkWFyvr_eUO}M zyZ-CfyPA99UoMvu6<_$5$R|w0ISwLbSP*0o>lWbNVTN;y2g=G5X{c=~h}L;)`G1D; zDz!~x;kIa-iV`Mzb8z3E*!{`?gUAp&{d?t=t%U+PQoVl%p1z5m>Xo*24IT9`Xc%Um zdt(pqpaOCz+qnVx+<+wX^@>P4Sd5vb(go!L@W2B8HP@|1{#23-HzcR6lfm1zyZaqi`TC~ z111WhQ?c||GZ59F@maX*{Ol188oO%|9a=z|LWF0CKiA^ectQungWSv3*S2Qm>Vu)P z=}e}!Fz_RqWQZrIi3w_n1S6J7%eFTNliW?|HZrpuz(|bmok1wscCn!OgnwUf_M#}A zPPA5L5TdQ>=Eg?Rq4LX^u^<2LGUn~7%h(TmL&JZg>3hb`&FmCACsWj_UY=Q)x`-^m z2wtNguq8vhzMd>EVKEk_&B`JTE!j%Sgux*8}a90)N{eh@h>CpjiVmE+|t;7zn^E41_y^4I2(Ah#eAb5t*r3 zu$MAQ)C^TL%@QpXVGgn&uvS)3Trze$BJ$geJwP;*c|w~Ej$j(#T$UXvn~szXBV}I- zM#y>hoZX~ZEkFMR{(?m6#N`@*Nu`LaUDPp}2l{ehUy|;?-`FNNb-O`CHYUBX zCA2Qi9yZAAO0X{hl|;qrBh^_hRmWsXBux_#4Ur|(LoO?DfX`Jb=_l7edRCJgS3)D~ zi>b-lEKEM9{47zKIe#iM*wYLC$tcswaeEv< z6gMin5vHvv;!IGk79tP_KRh2jVPZ+67NXw7?Ug79$n|#O_SB2G$V;$z>`!32&0`}Y zK-`lQXoZN`;(tg!x*;0jK<239Uw{e^mV+dzx|a zfBtj+ALsHP>cxNj|D0d`V^90(&1j0!o>a`PF))KF&u)GI|n9!w3Z0_O%K^5u--vz|7Aw@U#3Zzbp8QunzRcV=tlxJ`)Rk-e*F2O z4;&|`PzGwCgVh{sM64NPo<=YAkG%^ZZ%sTbuKN zq>=ha2i@xAJa9d0gd-P^m@kapFcEty#|4g9GRo|G>+4G3&0!=>cDM7i|ThP z_2w24&t(9c12Z87jdKMd+HP)bHj*;e-(2q+Lw|u=8}*&!Cx?}{;%1Y)Ve*xTVSjbZ z>aLRo`ivweUg8e7o4DV3TEID}_|ir$88I|wh&Jkt%^GwR1eUc;^0d|1-r16gF29e7 zwm@M)SaNlR{kA)pPcVqow`FY<<{nHq$#MzE%oE^bP4UNaxmH62 z(l&B*gT^R?i&S7u0qCvHo#Mc>9_1nbdVs47g4%>AmR{Op6Wk!-k>_Y|l?sTIBe!5B zO0S?r?4MU7VFQHC=W(=cY&UD0S=v4y;(zfs&yHHP*=VMEATU5t=}C#&Ug8&V%vLo+ zDrH*y+%l-p8$v3qa15=C!zWm;8}-dbnqal<&7EzHC(m+Bl3Ds2 zwyxXOOcQwU-B_2#z9L8b#r^VaDQv)=V+1KTa=}g_SYJ;OCgHswd-ihxg*DRzeooW? ztfd{b1j4cll})ZiL)BSdcTzt34uAL2rwW=yh+I=T^&_Ew9-e)4Aox`60R(0(foA&> zt$|z-;xlzRSi7zcv*c?A8KwF9x=NJN%jFz)V=d<(w;*7RW>^=Wo{Q+qDeaQGdoA(w~8p zJQ+s9&@l&EzVg_DL)6-exJ#CbNan88$x+YQ>aP8>E9&MP z)4i}S(V7~o=p5~zX7!;uI-;kx_!U-*onXKHB&%-Ka;{xD!~-GpB1Bd?wi}Ru8f9@$ zU}}(MS{L3WN)Z48K}Fq(w0~URK0S7tJ3A{58WI|U+?O?(aa;-y$IHjViEva>SSy*e zcZfY3%zA`_-LFhx{Wz2R3YW8zDuIiNx15+V$*tm%+Z=ExX{K4Y7M5n4{S|C;0nE>1 zS!B4-e*67>vzB4nK!ii1g^)vlMhn^AtU=%qh!#S&S52<;^oW6#O@IEi$iHqv+~+^? zA_>#A)a9l?smq~_QXisic~53M#8Hrp9E7F(>f``R>+5)pKgT1p8+F(p1D3GzoFjYr7sc8<(aM{h}W|OkSAHOH*Ob z^ux@ZOw7$oQ-KGb)*9TKTO_45xTi0vqG&B5|Ees2+}iv2 zobf0^L|0W-*2>J4nJd@Nx2{Wmfsar%Aw9_5+u-9FP6&-~omGOTKB}=4Rx1Udpsvx; zZwAi5y=a~Eek}_YNAE!?O(tHO{UzTRp}aO08LKxZ&wrTT=n^0W9Qwh%Tk_eyq=-!5 z#z(<(NVP@g8Fg@mD)4i4!XoFm)MU{vFmfpokjUI83ntrWOy)JxAm=CEcFBWen|RYD zF;i$TWUhM=GX5>%c|zuv(riNJu1w+Rk+d&9^2aa73Bp|vu~sNXYx4BbPXE@Jitiio zNhCtX{vNRD)TfGMF4Vqpd27K+6wNDGzrZ-`0hP z%5V6hmg>!0G{W&-bqg8HC+(cHhBa|#`_?t_#eacX6aVxaf6PgKq@0&8xgx8&X$-Mk z6Crq}Dc&d@QnwqurTIi0AfhIyOOVH|e@+51cr5==oPmf1tT|mw1bEH0RSquk<*jmD z+aq8@CTsF&=ShG2F8?9dFg+R*k!`gZLC})pnLs=tOle)wOTsSw zq39NB4(IA<8;rw|>_hQ8`s{~78j!)k5hEc?ODCoEzvyp0dboY755ALl+1anT*{^G} z$BVCsN7SCD!@)Z^kZQvMfeJL3E!sm^2YA71c{#{!SUj&F~wYz$rSVUV$I8l&^A90b;jn7vgJ&jhZsez;`3n(VaGiegS^&(9(G}il+2*aTbwiUc$fN zSQQa<{G^Ob2BBdVCi_8pphmCe+&jFlJHh>lk)?SIiVFVA$) zhPvh2hV7g^*S=eN#A9bcSg&KAO;)RTBEh(@ZP_$djf7Oa^Ac}h6JYPkIfH9#H{6iN zu4$~gK*ru)WudtGvw3-%&yUdseziJp-9X!(LU3@~Gg)`r({uO4A4iTeew4(Cnrf$6 zbaE1r%WQN?PRHta@nY{scYo;4Vy`n5=CEFqlRD0DCoFwlkxMOaMoPSqMy^n|xg{E+ z=&f!Umy~@-mj{P0_D=Q=e)NWRy?<^DRV!4tY|ECT z12~G4_2%UIFQbx(a6+nlWTV#&Z4Alz*AAMQ9K{n57RqW2v+a#1mlp<2ng!$};S zN@lhT_XqMJNy86zo+ay#aYBycWKAAEd$|1x9_;^kUPxYWzubtQJbe5KQgS`o@}HM? zQCkpSvpXL3pL_zK#DCrKr+))mMpAeM9zXu1w*P-)y=#uv_M@lU z{ku^tTuhUPj~=%n!oq!-d>qM|)FC2u{C{8+uSFQZtl2^erY8PO z-BrHwG^s~IA@5>}6X8gdy5`aIf=?hd?l@AX`_b6K(8Af5fJ8_A^cNU2v*o| zNNz&O7U=>q;i#Mkw>WUm&^~W-ANYAR=5FwDZO*Az@KmBE-7s3N0dYj>y~<%UiZ($k z+l6G7bhI%=eFDP}Rch-+_p-QD8|aU%>l z<^guXIC8x1_j7UHyDR_@&s5`}8r)~3kl|ZfgX&8**xZB|7u2*bB&vt7X^8q@cps|A zQLoqQ^gEX&M<gvC$6LNgq532fpf>=i%RUByh0H_ zE9J!%rysIh{)TY!8Z6W&G!uwP4Ov7UAnb=QzjbOzB9fNWp{s%Gxo9ZEUh1_4TG+}DrKPx0@nx0{ri>Gfy>$fy1})( zwqf#sdBGs@Y;FqllkLFj2WPZyH~JU)w|`9#rISF_G~O;e3MRimh&G7dMl+{ur1PyZ zQBoc4P0n-vyqp4fS*ZlPPJbuu%T3ySy4g>f=36fIz%z+Su(O?RZWc8x zGv4iPpkh=?a`|die3_%qVOGE{zR_R%YUEgCxeHqh%i>lLRk4vIrXNfa(|41^^nb@` z6p_zJFw^b2SA=Kx``A-Pj|pQACcX|rupy*D^e^;pl4tj#dw4-D00P+M-oK9;x2tS} zuU7eL1@>yNvl&sh0w4*9#D|_+Y-aG)O_7krW(HD$*|*=b2WLb*Oev{s>4e;iqUhe{ z!WNFA=)oDe_x?RRNH+1g-dzn4Z}`iaPk z!{_hz_YRKJ=!LQjM&$6#-rL>dSBD2DFZN!(I(P*?)9CODPFY3CUVuuZklOtpci+C+ z{pR(aS5mvyxCM{)Uhh4}I*;~_)5t&ufSqRXYxD?kOMx|magOR0VwYLaaS)Q&ZZ zA2D2yynKDQdz?lu=Vh*M9UZ@Yb?|K(NfA%o{O0iR_1^A58YzK8-9C8t`gIx|Ear1{ zWAEVIej0&Ou)6X3)zNVpy?-t$UH#!Vf7*L~oGKyEyLqB|Pd-w8_~O-D=!nruo7H1a)JtPG`J)eg<$o4IbjXt*cVEBr zD}2SS7P8a*(#LymU+zBNYf|uv3Cd^rgw~08cM$B5cP!8uz!lA+z$L+wO|lI`HQU(M zb=cBy{~4C@UNGF{464vrl5*wcPw{z!Y}^gughU1FWGmQ1H?ZBU%z-k3OV zI78x;HY4Jcv;*Q4)PLjQ(NOPVj|{Je?Q7C?p#N~^ww3)mWr>xTeRD^v_Uze{$2-zo zjXJrY>wDYDMu?GD@mVsEpJZ=|hlajBEcDldruYwD>suuHrkvi$5PzOi2;h;$dY!j)LLqD+ zwb~VFg$C6niF%-1!7~WJkLa@$+OgG9N~bY6oXsjK%&E$|izk||wiG3B0R{!X3?PE_ z@1rOOK&fnMh`lPS0#=t^lmsi6jW^ZH%fIpiYgZ!+NIEI+{ru9$#xZufBRuU!>-9LP zoy_LW$qaxACx3_v{_M%)TPOCLH2V5$=Mo%`pFDiD z-GC>tF5V6j`n_eeyEiY+qBMH{aq>7K(eD16D2=-CE1xU`l~4L`Jt_D^UT(wX8P7kc z$6IhMRo8I&2rfl2pQ^_@aJ{&k%d3Zw4(;&G&v=zTgMX_DofhiplZZrn$KT<_6zbh` z$biComW&)O9WtK6wfW9zM51qxqcr*|BGD_SmML7@S}0sPwM^jJ)G~`m^crgUG9uA| zZPXOHY&dK^;f4b5vkeu63Q5d`Y@=7sNZn%R&OLN$z#sPV z^eJ94AqxYAlk)1uvesn5Ic4%1s-99w#VL?CEq?&F8LwwhFLl}uFH_rg=vV5r4!%o; z9LpKhMNJE!&u2WJ^ta`gruzD!yq>7*9d!*ucqSB|77hvUVqr;uas~Z3k)O$7a0-Va zsJ4(h4ps|{TNt9?YM%eLDCNsQ<6J1NzRV}8v!T>wG2yb*=_9>^h0&7 zxC}|0Vu@jKBXY z{4Fc|Z}2yg{%`(U{4HzzAK~{S*^K`jfA{hCe}TWD`hSbBKEh`FC$cy+<1a}0Bl*?; z9e=}D{~{|v%KuON3E%n4|0+BE@qd$N4h0ZT1JtuX8`P7#nqe!iwSPpvkBzx3 z8SDzprpO14hUnXFGxWV?Bk)O}33&gm2Iy*QFx(It#Ha^B?!!kR_QMBv@}I7` z&Vcf5B&(v65;kX-EY>nevTT4H`QR>c)TbKcsJ9^_Gwkvu7q_mgycbwl@us(~;vLxr zxp4BHqFj?_7DnES?pPH?=%ebcw;l@Tv)*DT%;&w8Q1GgE*D@&Utbeb8@aA0$U@x@% z^%{#`t*0)_ww{8bx2;+ife*@?-kNn$`{4CO+XtcOzke%^TvJ;4@m%ubr!E+JL1-Pc zf?<7k&2&AJ+vFshouUu7vV| z#TC$W$kQ&j0FtiHEjVO7gwo7u@@mz84EI8rQ89&tg^pAXrlI)v5UrR3RKrXTD8O2d z&{0hSNr-p^`S@ayj2%C{ZKQ9|AiwN(H~u5*e^n-fGJiu~wp-%NOB-iSv#)aCM;IaI zhO}E4NPI-Xqg((kWU*c+aS|?(p=mn%s-8A3RJc@m;x@t$B{*N3!I_bz9|s2ZLa=v( zJwH_8S?0&pHhR{^F(!@3#(@(U3H-HMz0{R8!VXQmXXqm`6f*GxBiAjxd44&CDH_N1 zcqf`9y?@DhF`se@NxrDL$bgkv5q#BR5Y@X55I;4tr9#%*JL<@3A@TGuogRj|b>!lt z7Z!lk(+E`mKsxU#+SxnWSGPLV4HNlCf_@A%2ZQ$}?G@7maE58P&86m`PXtXB;c7Up zZMT7pHjTFJ%+@SxVs&LNMYjPb+cn07g+gp%n14-~8gtsa%Eft=Arw>lShw`zRTe$S ztBQ*1K@|SXMBxD7!emRRv6TC!T*n*8VaDw{3+<;n+dBa9mj@p{?QbLeU+CGR$Il?E zP`J{qou~bTEV5u*;tFt7LhmV*p?UD(lbvTfj}kI#sdS!@X_(L_+mIamJWT16CtEuS zxqk{ieD>tYlV=Gz4L;m{`en7iNVGT3gb=D z-0F&90UIizNh;z3@*bmK&RKRDCxbK0x3dR`QQAc`yBw%ka%7F0a7RCW`1G06vg_OP z+qn@~^;Ul;&;6Yl%8|KbJ_&gMW2h zRl~Hm`5=LCp2&s}M!n9@us&*N^_5nQP2f zF78M!bL1hLfBeS+wf5rl|2P!&-+u{<+EBUgO!N!Has7z@9^${pF7UwNCj)^V{Zj=3 zWq)fR&?5x|3QgV3Mjyy^oRBej4a?7I?_CLSM$XK5UV}%v>g^vxDE;gBs&_e6KmaOV z;(ojj$p(`|PQ6!wyrj?Lz1}Zx$ZoR6CH_VB3j6#ZytD1>z|QujWiLHQ$bZ}LUfO@S z{V*ZFw!HT?AumA^c?n^6l#47n$FPH!y{cemb1F*Ang(?JoV|&Y_}4fgFO$KqaU#=; z$+P)4E&KnI?I#I&7bfi4lP3xJE-Y05ifBT<2-o`b5xn_(xSJk=X5~hx_xrd7O=iD(%EpSQ}(9nS6{{F(h=X>9Iw~w zPmynAYw163t_?d}pAKJ6^Z(!Am#d~a2McxQ?=7^`@}EUu46T}xF+h4FG=@qg=wFvO z5cj%3I_K5^hkrGplVB>RMVxfII)X`-1ggyC0{&ED0p>0UuOcjzpm^EfiATtes+@3=(?J;!^1)KJjMMeCzi?h1=2vkGWu zBV%pZu~;MZ2;f#0a>Ma*vl$!@XSh$jE!R%dfwxu4Eq_tPi9@2~5j`Kv$sr3Q#0v_i z$Id5QU6B_y=9M}_5MD^Udp4ARz}iw#aa>%|av@w%Nj8|S-PP^`ykAd}t@3NTukxFv zhaO1JAkxjN>c;JplL@fa;;Lq5!)4VxRJ}kpwEbaeaT>RlO+SUVS9QVa=y7> z3^p(W;%Ztw(5kHhdXvLmrcf1x0?Lx^8U+9dsed%ZEOBrWl-dh$t*}c;k+=mB4NBpw zx^Ka`03Z&dRJ~>EH^Y|Wu;s~Gw>z`#9wM)$re)3}L~rqX+vU+C-95l$feyv{r;FK) z@><1qR3(&>)Xxbe;4pKBTSE=Fl@6a7%>(y=X^u zQGZx2^{FRsnrWaS6MgoTw-og{;qmW=rDO&{`Vj#M6XYrXQ!2%^s*NRfVyZL?FzkNC z0L^5-3M-~dgC5raZj7@YxP9S_wO=p2mShtu0Tm%1J#OYQY*D}061r$v)2Y=2G7|c+ zJ@!?-Ac?(#`{9=G(NPIrxtSMK&0$asBd1c}Z>Cci$VDlvCG^Yx%5i`Q|Tt}Ne(}pG+P(gVx2OdZ%!BI`!plPB9EOq0b0X-jP@I|brzkekZ zIYN0F1oRCqP&d?}B#F4;$q~%)x#Y3!PZ}1#%v$Gw5GBjpo#-*3|7(Cqr}tvn5w1B( z$}xfzdJzJNJ!T21RR|za*n8Y|8C&DAA9LHZbwyiC>&!#%kTqdnJXH%)959~U-Aa+c z6tPRK$&qSST!w236jE(<+oa3El7C=&z?q25EE6$`fs#*(xuE=?e%~PQdu);t{^NEM zr_;rR{=GU$$;PUG2oInukOEMzat~U8lv(c1WA^zSE2rN^fpDR4w%*8BD``C~Gr$xx z+*ma_x>CrYWhVZbeunWZy4?+%;6lCNtk%!vx-Wablfwb)O5AiR0FPi3Jb#O-u`a>k zE--M??&PF*l(s2s7FaA_0SiL<$BtH{1Vwtc~Al+}xoknweBco^92$j{(YD z+vtF}A=^fSd@Szh-`oXVjm=?6IK7mlWn3tm*(l%K94FXu7Q7)Lt{{NQ7JmuX)#7`w zn9Osr|My#I{fW}T`vwemG=C;{Z7rxUY^=PwRg|hu&gD)8ImWQNL~`rE@!JND-!X8K zISb=jSS17cRkj7kEr2APz{#MWkP^9kpg>})zv@$}4u>mYmzJVlw+mK-!W?tCJG}xK zGJ>gijIi%-)Pb!V*k?qiAZ@K5TbF@JALgTi4mou4)` zc~d}DL8mBN*723yw90XjY-Cx{sJsYQu6yJ%1`xfXhOy0tMOtHL+lz(6b8w)9Q!8lk ztPT!ls3LrpSU=fDh5j)WcUCp(j?$JC8RfBQaWdG5A(K0#A}JXi=*@#kUB>{GM9B8J z%utBc=`(MAZEjjS#D5>9*HILa$Hg9CcbmL!&%0((~|PQO?*VG!Wf)b-rNUWF{FDbWWopuLw(w zi+)%UFCc6|=yZO*bFDUNc@j!!>7YaV(c0$;K)9j}vh6uK)PJ@TcXk(X9NqS%e!j)l za7?sH-X;YzsAu^KqTqpE^2?NDj-Mw0|^A#KT8`j?70}W2c)F(lT9W zLY5BGs9A+cZzWuG7;x2$Q5s?AN2GF~R8#e;53g!URH?4J4xb7H>z5@ktk&tS$#@Nl zU6;clxvpnLd5v&Rl#2E-K z?zH}um4KEfC!EgGP-+eO!V#1V%3~-MU=Su8D|Scpz{`J34|P6C3lr?j+IqfdhgIA< z-`F}moLp0rQ}(S>)#JY*2bb1z$P^9e?!RP|=^Aq6P>!RPY<8pbO6%D*MhU zYtel}CBJh@T43N%$uFFe7E?G>@^=lCFVB6y#*np;z69Q+BcW&C0s7a(N~~4(Fev|4 zmVZ+#ujOA;?i(ne&I`-+fc0j8vs<-f*9Nj6tvqI;(R&le{G#?7g~`!Ee>Sz}StYiMBH@E(?LXkAJtXKYHZO@^4)+Nw%~%)hNLgItjt{=iCc! z3aqv%;5&vka6PgIjmG=Vc@_C8&$t>BXHfkQVDboonQaZIE)Z{au9j~bD>$!_7;F{x zibDjib3Raz5c<6@tASx!8cTo5Mv)4JKzSf4*kryyq{r%_xB~bB=`slTbbv3bf`9EI zGA8uBSrrh7YT`yNE>OiqlApSp+ABaB;U-U z*wk0b;<}N3mT8s*DU*2&esWS_VSkEgIQD>%gTiL{E3~^|ndPGb-OT6@m~{k%-;)y% z0^v&_GnDSp#dI+Jb6h54xtH>xI-`|I%Ck{9UI*Pxd$!)h$*!pHNu{Dq^s+@386Q+% zE=A$2Qd$nmvHty1r+>;3gFx_LvAx)~El_H~H*l`7|dL2|4 zq>fBQt<>bIES_48wT*abjI`Feewp=2w0n74oGr>l)fm+j;uu9{F#I!m1-LBHbfOC+moZANtlNxfZEpxaNgy_3#d9>y4 zXpe$x%|FwHCPen5elXm|9bRX)>G5>JCbZVBWVEff+p2rC9e-TmMqBNApB9c1vN4he zq-T|;w1uYID|)o!v%ym|eQfE>zB&!r7G~shNFT5-c_Z+k$RK=SaEns9P+B%A`WBWS z@g>8k`DztiF65a|U%Q@hcrP*egIo3k`LWeXtX8qe3N-9l72KdrGrp%&G&Zk%Hagnr|YKr-sp5=3+LUAAp3RkMwe&S?Cx2+Uj z)*Uevh(UGSD`#$ix^Q>1ko^umBXWG#d5hNqc`+G)UHPPEXW+>f zL1dA2cOVH?M^JuQupH$fU{lh$J})Nco$F#gmx2Q;J9IV!a|z)|LioTLv%mm_Mut1R z7JqbM35`z6K#9MiR-BT7daV%#qi(LQ`~QM z+XAafYx8UY{u!{)(y6;|Z*SK=QnI~TP=V43flW`kh&fn_%43Xd^ancl%iN&9UE4Ha z^sRr{60RIGDqOmjQn)tuK)5hwM7S{4M;ucygaHFt^JO}Uq}k5g)}vGFTay6NKC%Ng zCMM0OWdWUIRCO^FvdKm5&3Z;rWOsY8sP$OsrWExigP+IJt-qO5wDFA)qlD69w!K*B zq>~NiHN9KQLfTf7I}7y8^VzqVqqMEAPndtXEg4MzKsy6DPCuc$C9&{+Gx6ysy>6I0 zkPY>dhPyQ->L-2PG(V6i^;3pg=P|6zj4&BP;q_amKp>fF%i0&nM`}xc!q|p$tA17$ z&4jB#TATcES9!w#ZJAeF-qVz=iI~(gXuCe+V(uEe|H@>ZVqroFNRicHP)MGQD1?8z z-0u@a;#}ym8a+yP#ovn3MC)pO+%eDr4UmD8y^ovJXHQF0P z!uJdLt3MtT0PJu-JHd!;6?1qoj2AkX;0S^VPBu4_bTK*_XBX>rnQ?jAN526elvIGr zF)c(z3VetoLwLq}kVF72W3uPw!(v#b`KTPHI&@eeDJ-)2a6X!h({rQe$g+QIk-+h& zU<*2!ce^ubTAN6d^G6Mh3g&j7Cl-kcB;6vS>b?6mfjb^>uEwa@Jv#0jlvC;_c@-sO zd0nV1uXxTm&crMhWFgg!r+Dl-#;?R5vtxDWCkrwmb21~-B!M&YB#{yFKnobMKT5Jr zljTgZ#y~f3ZCr88bokiq#+58=@n}LmjuWzRD%)k7^)X2n*+<1pjVjk`(~%#$-OFy* zR<{@@mOj?9 zA*j6a4>SeL89{lAGh|`)w+6`~&)ATvx2b(QPg;O5j1D*-XiKyte>qUL)MZN-{X$GV zycEZMNS(|#*lM+*6|Ae3_y8Uk^aJHL0rxKFeN>niGkto%K*K@6@lSaW;jjO(%uxYwoaT<@Tvy}3Z8WW1` zv2UHZfGLjSu;LKizhbpAu2^vC)bPR9;6x07u|Usv+7>c^e_yveYeWX*S%;Vg%du{^ z@5Da>-%Uym9o>=mY2ff@J^f}SM{}QLKi!rNgjlDUZD??Pn68+?oZ&=A6A^OYO>HJie?$lXWm(;o%ZbC6!`sxy9Z+#y@(Z2K zzB9{pHa_3@=(X36%xBz>eDzWj62nui0e>m zGTO6&Msd_118!EX@9 z$0@Y$7rH90T&vNcS-Zf%879fVbH*a8g#tS<^B8FdtQfAOHSE=0Nq6l^icxsdznE}< z22kP7f1`0N#vBDA{F8g0ej>|z)p;=!aWEDWHuo(9eht544W&sGOe6%Lns6mcWhF!F zD9QCvsJXg>ihI-_%QzZqZSEJL+Ud{bEi^TgfQ*$@I& z(!yB8^mhu~WwsAeZXeglkT-HAlT#wbV2JS0e+bk_f+66t{6IlBNEzjEG|fdGkunK9 zQouh|@EIg%T7;f})}=acd5EE(@C+kcnfH0PbU%sL<}+~RRSh>xb+`k~Tc^bYW`q%k z<_z0&KvnbW+Y616z*NRre+Mi$jse-y-vtR7z=PXr3MQh#5DXk^h5g1POwUzN0J|BxBu0H zP#KMh3@xwg{RU!l6GDF65O-mufAP{wqJWp0i_p;#;;9W5EkZba)i>_a@=ztde<4NI z9~57*!RBU>hztZNeg;5MbX3@cT1xW!xiK29!BV~nuJj1s2-43t?G75XNKf%|LX^J- z$aKZrV)7N0?AZ+b{^c#m-1xk_Drlw8h9O8iB&a6dS)>CrB|`us-nVPes!a;+DmVhpNY?Y+*NUQwwJ7;%Dq zVK9m@;c(PW1|_`O?Lww4)~n9ZbNP9Bb@Q_1`*MhqWK@i^GLibUyUGDInByuHH6wQO zoe*xD8~V9X8$OsLu|jXFYpjP<$u3(iUcl1i(o5TN?qOhb{X_Y53Jrn)e-9r}LAU{x z1)Fg62FT}tjqHlCZZze2ULAlZSb>LdxzX2(f8pBm-=V7pR^b%+y)8cWD!+lehxIDG zs5sC$$tgUrUs1d$-t-Q^=i6xw2&3+GP#m=0akK|*0`wA0-9>T(VspPg$iK?A2KVn9 z_AEyEm{eI&9pne`W|<6^e`^S@sz&8F6GUXynwf=#>4+Bm&QG7QXnyas9ujtuoRkCC zL+lbfpkY!g@k1Lkd{m&ys-MX@xgw|JlAMtb$ebB)eYye>zw7 zn;Ku6fb!S9d45XgGNQb*l^PXwmSxBEqj*6l(DSy(k&Th0v)njuv8e|7iq?#uhQ| zW=3w3!Sz@7`vcrHPPB>cB#RHT(NwRH*@>way9)k~ z5)xlz@lhszj89B;dr6Xvd`18>1qK>k^hEi(yr%qlUctfAR0%ti%0BYo*9tK#YvQ2^ zA?{$dw~qP%f69t!r~W=@eUzXDARw?ae#|tDdkJEW9cKc<13wzb7~FP`69f9UTAAhf zSn5~Z1s-nUxvbJx&f0rC6u-yE$uQmr%cJ+C+l}{q@SWqHdY&Z2t+H0qduKm^tTe`p zx}}usgj}%B{&3&%woawzcpUFST9T1C=>7cdI6Iaee`poiO)wT%F948T4>;PL{d~33 z_*7&c^k=GU5hz=%R)sEmoTR`F!EWz%-7WIC+ub)i8RiPERWMe=?y}HCxQn&RaU6#Roc7x%WD- zuDQ@cDi2^XxZ{h~z7ssgy)io5Pdv-Pu@iPce>}}O-SdklISiuRQ;p~(g94@gKc?z1 z2(}dYOU)wZ1}r5G2eZH&VXKvf;wSpO+7y)DqAha}0<10Vf7T~0@uygTc-YjGNYyGI z*mMi5K@?;uQQ5aaIJU&F;LNb}FspP4Ija7Gj@{m@`P1zQF-1@5)En*41%AU$Sl3H< ze{ifdJ_pa@zm{Kx;aB3HK)_*L{G@wL?jrszwamj!MT6vAqsPERPM1Z6z*nFPkwHZk zO)GHbX^mv`;#Ag2BdR942c{qbXw6c({voTG0yp5WV)HN=0cA$T&`sW;GL;9Y*XG+eNv_aHI=brP`djnHq*^%kHf1b;1 zTDJPNdhKf&$@oB8is4QCu+G$#p*G#EBVN8|9Skr?@tLkMUUn9|NIUnmjp-gy^sSTk zkct6b>vTLv_8m~f^ur0&p6oo^c8|ha?mPtD#8SFvh#hU}-_D+H5wW8@$%A|~k-OFtJ+u@&_Jb@5fAAs$q`CKyw=d+Y9?A@7<6t##7o-_}8b@(N@Dl;= zY7&u7Bmpo;kx4>~w+M;gSq^)T<7Dkv2#eKM~M z4tdFk+M&tBW?-5W6{l%Da8YV#c(ruIW(4WV*(Nl)lXW08MgGPPD3Fk3f9*TghsNVk z>@*qRa-~Ceh*)&McRSp5J@CnF^du>9cp@SQ5T0x@Qf1|)9Ww3=k8Y&#mK59I6Q;|* zXAu$4V)+sE;wI8z4PT4RLd_ki$n&tC~e@1I3w4<4;1VqGW z?F4+>)?yn85?Jg<(WY8u!HHUq)@C$@1>A`h3B0&eFG??J{o>lZ*s}QCI!D8vV&3%p z+MAqukFblEWw*5xn$ikBv9`e~;m(n>M)rss#S*Mh7Tt)}&Da+4Fb>U4XQDB8Gei%6 zZ$YTAMr^N;(?dLpe_5i|f}}MZ=9UpKU(>??^smElGa>qG^ub$^hDZvnnU>a2utiG` znbpgN7|5N~)(tC`WJ8Z483ZG66*Yl`m0ZtZ;pukNKEq9a7M8|()XrVx`L25?0JQD* zF$0|CVQmLw{tlR0{$>tWCvvQKKtf2uAwqW%{#mjL2uey`f5Cp0;)--J=O0 zxqXtvqnIb&M?Zyq+)6)XzPCqMeP)}22shm-Ts*nbRwpW6D!xLKCs2_ay5R z`gOGVN2hnpe}_@WelY^5jLirF+>uub#VhNi5iRz|_7~JzPdm47Gr@?n+xG=i@274L z!C1Aw?V6!z`Xd`eTSVO7h0s5|#)X3K{@C)SDEmXJTp+^lk1lYMs@vDO_Bg>mxD=Vu zx^+czLn$8Kp^k;^w&$ES2q@^sawTz<=#O15-ezvCe_(`S-;Gf0kJBg`IHs8msjEg+ zG}R_y+77!0=y|MJaJyT-$(m}wdpdqNsKy0B|#W5Qk9o9 z7Eh!?e~$^m7-5{SB3mLD+frHce?X9?jV+?C_pHrvqYrUzm^t-3bSD6t6?kY8i8T6$2mhdvle8f@Z5oOJFiIvDSjx=wY4qms=r~%h3CmjohrpM{@;PgyOCOC1 z&$b7=>DZ+*$M}w2CKcHdg7+lmcqpJIXv_8Nf3*dA@XGciWU0HPt+esTAl5l!jj3cf zol;P0&jIneaIZ7(DX1b_YR5D}Fsx9e`4m>CerK$*7bNdB2Uf*)mRa540AyH8G+8*> zo(jNLB_bD@XGfge)~H6$A`| zf2o@YfmH^!Wy4JN01{g*M-CddRi-MMgnjV=*4?wgkpkGt%O#-{7e=Im?Rzh_h!rchj#9iQVaq!m_CPNG&7ZW>k zFtHh!4d14aW}4)KKSYMc^GXNp$R#isZ&b zo*AS=a;BS!`KmgX`Bl`&!nd>$P-(ti^Vo&CQ)r3KRMW0~&L>OxNoT@GcBXnCf2~3v zt?;8Ro?a<;papnnO)^U6?pF3Mqhx^F+q~P27b?f2;Na3Vu~%DUu2!d6hQ3J?Tf;C) zhS4xeqpseSmyBM&d;2P#Y|b{Blq8~Vlx!~C6=Lpgnt)Vw?1$XgY=CM5on;t&cl~n` zK#oJ>9IOFTKb@oR{JdOS#LxvVe+bL0;eKf2$xlj8*PU`GpH z0P+P88IcG{v?&JmTs*}lF%gOCq}X?Bghbzq?Y zD>V@(S>pkjWfOUFIL{`%50pdu1~V{yjUs7pR(zuXbni>(q->Uu^IJ-(nxb)bE*bo) zO}3~KQd;5VRP}j@;)dzZf3m$l%V2+At;uDE(p*khK>$U9oMo3Us-v_DT&D^aIxMvQyZX0J7J4BAt%{&&+dd|FT2*;e`GAO6L1dKuVs63 zbdShI_W8iu9$v2_7Ou%ha3uv`VZHaYRduARszd!A+3FH1U_l~249IsX%ljWI_e9bS2mBEE$KZ`CGb5UI7Ts*ieKGNwR z8hq?_kGtIfU}Utff6Lx?8&P$prJFFP^R*;DAs>hPn~pQJnt22F<)bS)$@;x5(l{ff z=t{bo$S%99%vP^f4*ps^? zd7T|PVbjp#uTAQedHgyV6xpuCV*%;l3@0Us2p>rFMtRCQf6kls&F40`No{*I9$v7P z-@U2gdLI|$tnMi$T_NrAy43DisZbj&q`Pn(@&ZorTx%qF$SJ<2$0)kp2mi`&&U?u^ z4~m`uJk25*itjPbF%^FX-!}4zPIaF1Cd6;#r#EvM)KN0mjlr=Jiy!%l0td4~T@DDaMzU>}()lN)$MAuz;TO$i~o+ zb*<$Ne>JuGlcBi@kl^|^?(#p;{9-@9N>aQnzpV?&D=Y>@2$S9IWMN?76kAaQC&qH@ zB=!jK83BDOos$A$HmLX?lZ9QTlvD{5Q-33=bR1 z_^ylOk4DI)RGwchT4FTSw7`g7=p6u+sBVVPf92pFc0`2^vMbBE>AsWRCAYzMl?u>Q z<0S8cJoe2ExUuNLk@qDkH~!40mxTa`yiizYQGJgz-4SYNsaHXUe()ktSND%~-ZvN# zM-Ia{%|gCWtDsR&dmq3yWKDfPPPov=WJs#6U$H81klA(zo+7C+ssqK0T!o?4)=J>U ze@3S$wv-A6>3nQQ0LKN9#`QRRD_)^HW+Ruu;u>>ZegGma)q|`s={QVEGKGU!B%sv8 zQZjr4CQORI>g)Jj4JccC2B6eR034Jn1BM`duTc9H+}olDf|J}OCl=6fp-MLebe1gD zt3vTBu5`&-Lk5LAt->+g$a`{)kV8MufAn=tUspneyVs-hgtXIyimW;0sjEhlP1HWN zbo<;)E&b(n3m@Cw3NW*u0fDfVMoYYc4NQ<%ffB_@yvOUHK_VH%vSe0UFK|-uL`f>{ z1DK7RsJE7qsH3rA$A)w@%>j?UQ2Prvf6Ikc z%fPNDNi6EE1(0|HNEGnx1L2j5lpVWxp+Lb>sz%ub2r+VbzT`u-(x$NGIeW=|EnvSc zdb`Ok0cRgTD^bx!0LW5@h!B}%ZKF>n*%D;#kdImz<-@hx#4t%*-R#_l{vW!pZEjXd zat+{dKrGQsu^t{{6 zZB=UzZQnK$2HX}}OAV!j6#>}}Ohl*^g)ovlA(|G~4|4(X=|)VM&xS1%Lp-Rf+%uO~zga&l}I4>^ypw5cWKi*~!`K-g)oktG(AR z+??fj_h5H_Pnl8NtcIQ;;g!p+8+5huy_X#a`2cjJk!RqW5G{tZyxskFfA8S<8E6fW$*8Fr~ABg};qY#9Qe zWGEzv0$xD)5u9!z3z5XH!b|Ve>dXhZS-V;?h>}B9O?ZvK6~dDJ#wU9}ziO~Oa~5fa zDT1jv-fuQ_|@UT$&0<0uMS?pPa`TCSVI@j z5O?7s%zDi_cn#DHE^~8QnZXV? z&6WsRTSpw7cwT1)Eop`TSkU}6z!4y7sq|l;)}uV8p?IMB$ISZEUpt{z4U%N8c4DDA z;yfAPhGMwhnbbysT@PisrQT0y@}U0h+Wfkef?N8)WTKzre`Ib5R5@f3<~7@CVm-*lW7oTAo}#H{~$qejh0QoI)>}u2gV%TWdFxVOeh@ zjtU-*n%uXRqWH|F#*;>#aI^u>SyjMCe#}8l9@lSKXkOQxq36~V_Qv{PhkP5ZVh+~y zTIIo_bqbJqe^kzO0QWi7Bn{5}Y@We=?XERtconl)M~HjFlib}fnk-Kh?huCS!pAn+ z*WJ|$y~|ds7DiaDP6IO~A*aDFLzjL&mFn<%8DNKvjd@z$Cg3)JMj<{uHe|-)^L@o&h9js7;t++b!hOv|; zWEprj4cFN21F0n`FP)>|1rVCnU?D_#i~9_&vI+wggf^FpgCdB9xNuU5 zgEX^&umY_c@(=Q)aLX#WT5Z+t^yYabUTK$)laq*SA>xTX&NBIB`UB>|E1Yf0ziOjO zV|q81f9vG#;kM0BEmoU@+J=B_TL~Gl=VJs($H4>3&N81)=` zF@IP3_tmOzcB$W$tw?P46XLlErcQvdceS63^B&LHw3GlpGBP;cd7LO+$+kBTKlvc1 zqwyeo9@m{R660={8~o^m@Vkn~HP-vSe`z^ZdxrGh)OJ-QOat;BTZO7P>E%b=t^&Ws zIS3pnV*gG;L>ztnwYrMD{PXNbKc_+{A1!M25w0_>C+B`|tK}D%@6P8ZFi&F`DP%iic zgPt6Rj?p+pKNj6Oo0(jLxaULme)}EkbC{l`3v-IU(_y|f7&I$KEWehU)>Heru#)XbAs7Iu!6uW88Gbz+E&7uMe~G4Z?cbfZ%5UIis-q-MT%XzAiJsHov9_T?H1J%6zcTjNft*y) zSm=S_t^|X;vF0eZm>jhXdN9zIjP+{6C#;Lo4pQjt1PfU>Nru3u@^7pkU>tMa<5Yb% zZkU^K_j9iD@Uqru3REj-&R>+*4CCZtM}Ex%f~%2Nl*^~Re{TjUN2H$jHW5Q{`iFp3&_% z*M9HDX9uq#QY<^~cF&a>^W4o{mWRcd@bS)Bw22O1Tb|Ki))&}STt<-U(pkwb{Gi8Lo@?Kbi>e+j1e-5>Xb3*_a-8N)mOwI;KX z>r3qn2MDgtZSH$hk~4(3mFF&A$wbB-Ew0xW&7{^xi>qla=ufy8s2s?0(X5p_qvAy|o5jfh;>MKN zs_4};Np5|Ub6A$pi@Do{teD_SUYd;vy7031e2@`eG9sW7B!yg>DS{jhORAxlqad71AV5HHX6~r!@Z(P zzop0yV3knS!B1#3{KXlwTCqoQ*;5$4)*o4&8stzpOwSX{B;>g(!yrL^R`HUTm$qyW zf7f6`oy{t-T5XtNF*ntS5lko2?S@L&m|)SI+3@xDBMgc;!1&!R8__Y?2n0sr$Zs&W zZYb}B)EUbjgs6qS8dyx+6b`l+#Usj1v0Ua_?42%UV$ zkzE3n;gWm=76+uvtFgIo;489V>`dlqe}hcq%jT&LlCeS1CL#lU$mi+S8bs-q1r9^g z<-E$-^uC%*n1^`C+=3ZTBUawWqM^t3VOoD6>y-1>`Wl0i?6%f6IGeVy%hAV9`x7Gb zt2XSQgLorftv2#jdz7si)&2paXsdbZc|M=hX-9Q+Y}EOU45lPX9O!PV+m9{Yf4cOO z^6=Jm^q4U2ZVmquz~s6K@-?NCdCtN3^@VAg$^F`U&t4Q$K(OvyLiSftcA$q% z6YOk6JZzdzAwjQxy6o5**U1o+dv-0Wts@QbiJ)cHng3b1T&QS0R~yqB)O+S zrXdjF9IsaA7z8E?-n)jW<&no4MTLMI-=7%fSe@dvME=#})QHx6O zhn#ASP^*w<_ky~3S5aZ$LBipI&L-z>Zo`0OV5mNZVtta`-RwOkw=%Re*R23Wf78b7sZ~it@06GMbdpy>fy^`vZ@7HCDd%%IVm6IS`WWem;(FL+ zU#nN+Mz!Ttqt@Fh-TH(|F&+l2Kn};$&Uom-$owK!GwMzlSicvyTtEhG!7OZUQ&b$97D&#PF}E#Z(sMX_RN|*XoPz}C9U=*BocKMy zY0+mQ7G9IEitm@x#y*SOS+Fw{AGtN#cwCEBas<$cCv%!}t)pZ;A%7*rJ#9O6n%&B{ zn-;24zyu6qJvy~n*ikNt`HD9PN(Pw2oqQ4#)LZ6sqMM|H$(TnuC^Cp=)A71 zzmt%dY4fy07$9gQhM0^i(~#4p)GZF_cePrQwy8gpVIG5Dc*~~X9m(k}+r!W~pZh0r zwOIgRN|4S;4r^UrX9h5;IrM`e%^y2q$IkrB9Q|`ae}w5CfW^yW^d4z);~fgHP7S%F zrf4EYKXdC@6AC04I}0LllfCn*T3pgsmw;n*I#;4|HKZxpr`^qCjoQ&#$m42N*A}U0 zS#w=i=%^9it<(%|Rl*ILY9}4VrVlY(t1U(2SmWG-(X4B~?e?6vtHn#`S=R5BzBYhR zfJuT-e|kPFQ?}(lER(?o*NzUg?TVo1hzr$aBr#Xw1`lnsb8KXpM^(4$U1l=HwS+1N z?0<1!!3V&y8gn&8DXoyG>*)2zLIzKdGKELz;bAhVGpb;0W~fMMR0ICs1aJqOZt~IA z+(|H(qbD^xpy(yDY_2~-rr8`FjUZzfIS+Ufe=g7!j8kxJS9)toCPA-2x2QZ(U`ZXj z0b@SZeWSi#^RrQx>S5ip(krU^UU$~a7o@ZEgv>nWO}NoA(Qes*o0AdCXdg7c!bWvU zTJt(j>z+NkS-jCt>T2>jv9^wOrM#>722&4Hwv1N00@eWfIw-n9wXx$93`1d)22=-5 ze}ew0#`7j^wyLhDw~e}O+4c>Hpz@L&NhN2(3H?l-Q>7BUZtsKXEEi&J9E4-WAlxq2 z(k^}I^_TXne%J&b7~@FMW{399fM0F-HFz!>4GyzgfEGvE=2!d~6U^PW%zEM6t4&4c zz@k;L{=xn>fAfYfYv6s9G2)QC3!kT(=S1eD4T*D)Pz-|J1l9a92zNqQ? z-66LB9r__{QR`hwM@@o<FMGuj`mePRP2V16wx{|*FoB8f49S6 zIIsQIQ^yQc?|cda;tJ2Jm3t(mYw&5@arxre?XkPyk8ulNL;dlqgV(PP_D*yuhw3Mx z?|fgdY47Oy?(5yRC&xd(+4EvT{ZfbD{Aus`@m-}}9USkyeYyL5@2-OH4j^{#jzW6} z@AmKh;+uEJCt>Pr^Ev&b=I{Oae|YcU=#JL67OFMAwVc!T)-tx~w|uVNa#K`#8j8T? z5WqWJ6V4jwhMZ^Ic%~9wz!f^N5}vofw#l8g;iglUe7Qz%y9M?zfW0O`oxD#gR0|6J z{UQTIi$=l)vALOm6S|XbL5v5t04b8@H}P2;oSN38b8T}D>5iLli>M2ff9@V}5MPlO z#s#@Xlv`8gD&if<&EgpH5@QqoCOC$Wvm2a=g$rlG6doPNa`X-uLoN}p?E1&czYCTj zU^;@ADFm)3mD7Xd)RNCM8%5Q;6cOQ*%}w$m7vO$>9Vg@y0_wvOdo%%r>SN6$qjkf3F5~0GZ>j081O8R@8Sp1+Y7Oy3&Z0>T;w?j4>J<^qLFR z3woA-f(j08h=b(5k%@$uUg@-y;fsW9^Z^x9)2penO)$VL^|#lc-;#waCI;elI#`f6 z3g#6sB;?Q&5N;;>A3)kt1hz9T zX4>)GAdYEIa*-_8lEJ50^z}8rd7v$ZN0M{TGd_!f&t-!2V^Hg^R^Gj2wF)8M@~e!W z6MmZUs}Y}$S1Vlmf8@`)Lwwk0mR}J*HSwA?-&e4rwEDr?&M=VzF`wg642C)7m&6Q0 z%FosrKXtn6L#+MlZ$4vt>OTnVPahJ!Y<<*Q)3m6r%8F(}Ke_S&L>aw?SVJ6Oc}kd1 z^^MSGcAmEz887pzAZ+LvZNv10M+fDUx_F^r|5ahgwMw95e_KWHZ43Vim2700(?V;x zfd+DQUb&_m49+o^cQf#YMO_m<$~dMW!6!~t`kpET*YcO`MAfT;2pu9OyH%e%RVQ<6 z8>!(((%Y3AwLW7*Cc7*XY0R?a1-(hBf@Bi}iIYni(w#aau3dU<%oSYeMkPL@cwFNA zUagp6F*ig=f5B{c&4cqNs|!Q}ub*sHpajrdJxFv299YJk7a+K&_7Pd=6Zl0#wa7{2 zagE<2nt75thE;W4q8S6NvG_|flc`7kzycmmnHn^$CUnJ{*0Gu@;4_7XcLeF=*Eq-d zDd8v0__A6Y65q3y$e1}Hm&vf%b$5Z@neESp*Nb(^f1K6s$Wu+s2A33%et7wAQlpW>Sv06m{70j{REHCB@PTl-(eBVzxuCt%1c?QT< z494Ez&(RUP-yg#*{NdDe=!l29A_X$MmAXVl3x-g&9URIik&wQ96L&V+8p~VT>NPs* zj~z@sf4=LT5Ou(w?4Z{zdx}tU<^Dq`3ZH@i4Leoh@dmBGi#$Km2B+BRLe^uXcZUT&<{+Om>$X`i0jV38Sj4cgG zW5s`gT~}9WVuza8U$1xFh64!wTm9`L)dRH!QHcU!leRoJDJozQ`A*mNvKCf|LZtA@ zet~gP>)HorCHJ;|(;~TcHP-7Z%BF`tMmd#GWp@04Uu-1wRh99J-c@-OCo+uGBCNwh ze+|(Upy~y@drMEi>mV5H*-y2knA1z1S)tc11zOb#WFqdhsjbHUNG0-rwpBlAKDUb| zzwX)d4vIQfkXJKUp}P^`&R!El?%$Og^=OO?OOql08AmeZ-)NwAOT{bS0}l{z2*2*R z=P3Syj3^OM-S1es+vRVt++l1Gw``3se`Jl+UnjN*t+6(qMyQ#)kk58`o8yhk8mo~7%dN-tJnp4pm$){>+_Q?iT-R<&Uy+CdL7C-nB zdg*8P{;&4_H}3tH{!XL^7sGB5;a+Qzc*gf)Qvh6+w+6+RY_PdmBqHXcV(e*wfBDa9 z9FJq#;1B_tj^h|suSCay%LWb5Thi+a> zXlXVfk}L&(z%LYmU-FOLu3kSde;l&8`MQuuI5U^ER-q{k!6=-&&GifswZ71~blk-< z#=h0stQsRYAOAu&SQv)2lB@r5+icZIP9?t^0WOGaWCX$l)eJ|na#v7v%Cs#MR$#KD zxzS%6jT}y`Z?mO-48E9Z>w=%MXW;zrEYv?WAeX@}6wy$PpleI(!o0bve;Y@61Agfv)biz=IgNX^aL(0+ESQ-m3Sj+P!jd6N zBi&KafbX^CMl~{RF^-ig*{}ycl3?xJVTA83RuPUG5?=#N#4)^`tKRg0T_NjAzrOwsWQ)r zj8NgP(ZpC<=FWuuP0D}(XmEwpu;&^*wZh0+C56W|n~prwNOrRXe_Hj2rV7STJJ$1S zM+>}K#r(J1?e3_Pkc07?mf9c^!}3DuB7Uhkp&$+Q0%AG03KVvwHGxMO_l<>zyJV$F z-~3fmTIM8zrM)$>pBWv>x~8}6`x;J!SinW#dwP?V`obN%GA_cL0=|*h9C)=-zXPLQ z-CBWU7N}xjt^$=Te{QYBoj6%R@}8=a51Tdl)2FS{v><*Km|UH#|7?^je{$_n&f4*V zBewskmPbphR{T#I91-#KEtLM0UZwmexjs5;VILU;Dh2PT>h{x!>_6-Z2~uq9+4`J% zav}1`d9a@CP+A22%kg89fai4s=T}=&d<6Jr$jg!w5uTt(f9RB6NruE=@f{>ZEl>_f z7)u7soVdzc8>X@)7@&YE<9~MdV9fU(!}0frxWe!MzrB5Xf7>?F?pKj?_Ne3=M6uJ` zmU>y8G?#ALq)B7A`OV-Cg0i#Q_x#buB0&(uWiXg|<{8L3 zW77Rh`J^fVe?TeX_|iVoM2{@dUfBDoN*`l&a?rT0DzXL*u3+4}c4*o|9f83WxESNXVuAtA6u40~KDfcJf ze~Fl)tX97IS=f5o*tPr-SwGRZlK3zBBXX~hfKe&jdaou0C3Lzg;Kd14=EFp-&-P4g zZF#6Ct=Pgc6;ySNgqY*Zk&Z%~H#Q<0qV|fLcWvp>hmgvo+=lc+Q=8c5@>>DZmJT%a zPZvgpf2F_M#J$9*&20Xd*q{DPegzz*L{KRwOqB4ZJE`J6-o+lcXBm@QjMP$WI}q5o zNal}8x!8BCZ{0cGodRBy(yq^~w+eUQy^4Hy53I{>D4nVRvK31v;sw#1gL*DOgaPJ2 zala0rjJga-r_c$C+-BI@EVnBLqHqtm};pi5Fp)F za>ea>(9WBWo%;=(@TuQhYW{mgL#tr}*>+G!91=rAO} zf9yU?@mX=5-PGN>M&DEwoKCQh6>A6BM@2U9;gNO8quL)dIWUA1&%fL=YzG1Wx`C}o zfo@0rd`$SN?|yM6SK7&$!ys!;nCabF3FymrFEPv!)y)BPWEXNWAn46wX`>Y(M?qA#65)xPbR{*lE&L@kwPkv1 z=H-K0z(r=;NVfn-F^LmSrF zH~k88`c1jDYi}`orBbpWf2C2f>J&&(+q6$sLqqe!t!znt--dyYo`+5WiXC=5ZdMT` zRXoG&C;kp4Qa-32?Pj@0E8SG|r(>K2(7FpC*jZF3>!os^#s9?Io{`rk+X<7iy?FNW>Td%T}Yi~!!)f(p8B*BZCcK&#co&5vqemzA@4b` z$WXJ8o+4&_RHWs^_Rw-YWkFJU=O+*BrAh_Y1irm@sX z8)&hoF~y$7diBemY%egmLTBZHYqluk*+$Efb}7UOT}hh;X?D8`f0t?EexUV`Er6&e zfb`QcS6{q{@nG8)#ev<_Yeqn3NH3Zd@L-EAG>-?_<3)d$A{lI_BiNyi2=)TIS1-6- z;G-scHNqfPG?0zXw?k~fHGgjx4j3a zD!3*~bgpB_84z{rf7E+^(oLI)UPyk?&OG&U15Y~}cm8i}+&MXZEG*GQ%A!1;7TVVy zwIA~-MEyy^DV1-4cbO^~8S*48hR>qm-G*Jkf4QK@c7Cy(urUCnco z>ddgEWvx=i_9_1Y*Jg?C&M#!L=A)SK&!duz=oQN$pRo9KS*_UmM*l@_We1L7Y39QZ#l# zB-LFoT-lTcf+*Z=ORBS;gw~$qcy?l>%McfgY{0EfyEQ!CD>fR>lGeBcfrf1XDatt* zJv~#pTg2P<-C0d%x9}31`AeQLync@NO5+HPWr$f2$874`~Y#+d3`!l#hn`!3b;c2GFlG@A0rUwUZN5xML zM-#~|9|n9o+ny@o?uB<`N|UL~Fuy_Ebr^Z_rO)F@Rcuv9P{}x$_bP9a>L8s)$qC)j z#p3XGM+u$TRA6EZyc!ii+^WujoEyr21PQ#+GwT#G5`Sd5$kb^lcoQVN*vE0=aD14y zy1nM7xN`GeI5Jb5?SGI%(CL~x;R=T&uU)qnC^58W-q3p~qM23jF~~Sg!PecX-E3fH zy;)!E-@Aii9myw#C^`Z(A#g*t%>Xmq?{2DX@O!0VC8eTPvvgnzXh(`W3A6FJzf$Mq zg_r(QDt{MytMfM(fg`htV?4R!XAF#QLmLBbYkjNs9vgB0);BC|evo0`-X}4mckmUt zyL?P;uccc6*EhiYmRWugcBo1LE&QodEq?LKE%m^nmBU+Fq6P=s+L*76W}qKV0s0eA zk2K|aC&s1FcS2jMSghWYp~MncLIBF z{_=N%%Zy(HD7Jiy3K6IO<{LqO=kfiiOkcH*NK57mt@7ZN81{c@)JazsFR3Tw3o{?wHXgs{y4Yt41dR{FZKs)U8Q9pG__)Kc`Wvs}|j~ z?|X+=DhaBcIm22=st_xFoaHO&v3J^ycQ;v&fKF+N?mF@c zp_Rw_Bom2keWqIkGGzOab6*DSKBKZKA<$Mx+Yvi2D~_ud>d(Y|=x-J1}rd zO{(%6h28{=fnq1tnE-(;bUcRSe+r@XB{41f?sk!J@>3`kRX~Q%KG+@zmY<4I^C|9;Ou8bVsb!av8UFQZX zUlicTc=pT_lxJX9Cft1>iG^n78**dF%v}ldPJc<+j z=<#PApG)AC0T`t-f$w{e^PZBpbx$z2Vz|3Wtx!6sVG6-w^*Q$)t+!QKqqEvdYrqiN zp%Z7ROHQKD`63YlA_MZ>cYkil!U&RlJQgBCRFC4J5*(c};|bZM)FF)An)hsGk!R8I z@|=oZ=&|eA#}A)WGT9JFJa1`9`u?!6){kpA0HK_(VPU$-tTr13`vaPX?zOI*_9~_?P|kzXnUX$*x$%2U*)xm%y0? zWKILrV{7waLSL(aFn=FDSm@bRB%4v`q9N|Cnydoz=upxv8sBb0Q-92}lMIi+_Nt5}yImt-1)U69 zy(8M-D%(g&<9`siLxRmHqXzRZf>HzoP%xWjO=8U~$IIGCFhsoAcQHcU!S2r=5z3z- zj1NLeF#PZ3DjB_d z^XByI^?y&NPk;+}MDCY<4I~IuZduTHz=Bq#jl}V@zBhUMig|H7$?6}y99FjC>45!% zo;^&4A-a32aw(6;5t{YXZ^C1R%@>DMl~uVWUbof%X^#oeNb4)c(^hT~y(bm`I?3+r zIN?d1Rsdwu`Q~9x)Z;OeA?z)w(%_X@)x%XF(OVr(64Eeq9BH0?4iqNUjhWuin*^hYJD@tA%Zt+aY9ZW(O+W*<*4 z!BFQ6*`+&VKmPRm-EV5VobQ0}+ zsDF}HqP@Wpb{VYNgRFPg!j@`cll6h9PKV9kaN)}(DsXflU7;P7a9m~DEPdAsE&s=s z=d`u0m7aM%>UHgK6`R=V*hI4hJ7UP$Yq(WLndbNPcw7Mo54r6mluYaDOK3D39!C}k91qsLSK33*MyP`?wSnYSc zx5IZQs=w2BC%4dM56#Hj;$aM);k#=l4xnW7UMN2|NW>0&{J?f>zOr{qCOi#M|I7sC zrB32Vr`;empb_D#pr1eTsesFnPS_uUsDzl9>M-OGb1f)^SU4R76WKbAn(5Qg>3>YV zeW9PmScJulYA?%~Bs?B`$K+Y>8s!2ey-v2_1E#upxkzurd3ilRo9j7nQF4uAzxVNS zu0sI(I^cu#Q^Ee*9dg+E7GF8565X2_x3a zlS~Eo{S2%o^s9(I##5TyoDPK%u1q5Pq?}m4T%f**Y0$AR&vaR#l8eBM5pI`=Br&0q zvjc(Mx=x|t~+=if^nyYT!w!o zfmDKFruxq5vAY75LbKlXhjtjTbHr)v?OHU7?7BJ8*VS65FuSxdsTdX?nua^k; zUld@<=iR1y z)W^qmI1TFw+U%H5W`8tfm%73w#+3Dx95ZV;LI-;XR z&kr*v!K6<9GmY$WyB#E#Ld^|gfhzT*!XRtYHiE_AR}HxpNTq&O@DuFLgh{U6uvti0 zj>~VOQ9;kM{N_zb0h%ueI8e#ghcuu|_0$iw>-L#?vmQmr(t?=Qf)40)ZuV>^5jNPd z^rn>Qm^er(4u7BC4M)l#=nuMx6Cm~^`aH~KNAZv$wTW+soxF$F880D~qR5OO#E=fg z>@0$2Hj?q0$!HY!q(f{lnwUI}$!H+=A|bw9Q_a964M$tfAcG|dv2h&@k5iPT|E`!& zDsE}z)lkZHr_PAZa0w+^xODrHn`Oy^$a`*Z%Mu9`#eXESQ$30ha1Wjjd2UN#OXA9~ zg`tvW0<%~nvjv-dzdO?j!2Y-x6xBN_`b{M`4aUZGcIk{aQu#fxK>YooK57Ya54yrU zNJ-{^Zz_wet~Owk3UGAQwDg_!r6rlOfcL!wG3jN;wr$Q~XD6SkswQV!89;GR19>6??M?_RzYmQ+hjA+2+F+%=)_8;}zP~{4n|L+eJ)_2eH+M z@oXROwG+S@5Z_p$W619Vb|^_kYH2ZT4M#Dg7=JvCx^oRfdbPc_LyMskF_xB7S4?dx zK(7I98-~*jJ~4LM7R(W0_4R;u{2!^sefsdd6>wo24=-!$-krcaFNu;;Z>zFnm`9t&%k9|Jh0 zbE$`}L|1Im@&k|^gN-@L(iN89#L~_zGJpJ)@1uFSjS8}k7x8q36>LbBZey~YEa@7S z8noD&B`YTe$KzaGt~F({vH=z#3vsNu5N4{Ej`(lNIZtx(FI8 zkzzxyxu{7{71GuA#=FF%-IH$aVt=8`ygrFBXYnDxl2mNE-3jM#tFPd&(d#NS1AMpB z@F^UI>gE^LY~WO=oQAo$9C(BGKzN1&C8xIm2-Ys!Sff-vZyL+3zy+&z6yJ*2o?c>N z_0;aHm@+-kwlS)bB6Z;5WNp;(Vg{IX&zc}kJ!{76W|S1bk?H998}s-|Jb!N8)e!I% z!gIQY;xlEfw4iIu~%3qGhm*gsK^a{Q)ExCeo#TB_uUG@^#bQJeOWy!VL z!7#2J3}Xm7v?K@Gn4D|bc>~9NM*+LGnKdMgF0LG;=l9yB6U zEzhaRAOLKM9SVZZB|$?3n}6L4Q(ZL5)(zzk@eL!%wDCNkGiAL>q&YlzC4@Q7?u+M9 zOb#+La21zK1xuW_Vy@MS>6}cs+Hdc5Hj(uZYi!81npN`5a@I?P3b~TR2*B3J(&5om z=TA6E&!THPoSda6$hYuHM6$_No~Rlu1}h0)5N~}>p2vv$0TG16v45h9gmnV2ZKKVh zL%fCO!lS&j>)^dD!?_d3^8SF;+gjfiB_1`N@YR5UFaQ41h7cp8*0A>dORKjkSYLKs!3I% zr$Hf<`ZOUK+;0PW`F~fi+sPXtx&e;LMGGG+*BjTy9+@_yg&2P$IEIGo*|AX}l$njk zg)~e;Cak?YrL-W!@v`;=L&tK{u_ZwcokoBWNiOY}dC&03tr5okJ(`77ML3&~9Y%Z> zXzrDYXlI7uWNM;jtJI22-}AJM7^%Rn+5+V_*l&R5D`lOJ<$vm98KCmY2`g9h!<%*3 z4E=R_qI~i-$9K9<}pLU^1Gk%ZL9dl22qOH|lD=LLEMm-$j(6-)Pu$D3W${+wC z{Q3;kiUiT}@PYGnJa(OXrpsrw6w}hofT;{Ytm0d#m?se0 z$3*H2$$T4Kxu?N+ff`u8+nskGJaQh4$z=q^4;2$7 zthU-zM1OrP#%1+C^Li1$dbme6QQYkltiuh1W$Wm!M&kbQQO(pd^*+@b5hq?l?*ATj zA~@I=i~T-~e+>#W!0v@Cz#WJfB^LUOP#@0_Lh~KUGvnbkTuvxUws{sZ%|UU%yy$TT zBq1V!z2b&tJUu(Rrps-XUz|z6*x6Zh{Mpg*cT5G;dC;XY}f{s*2jR3ydl}NE3^%2&wn@tm$lqv(Pj`N=&(%(yB(MaI@BJ^UP=uevp!7I<#;S&%uUuW2rq}GKBMcJ z+;sD*k!wk@OwPbjNjbR2$aBdu0`lznZWlcVvTHb`!9jqtq$JjeB%H|cNEi^-WD|P1 zg@l(e8D`Sb*M$?ERs)3OW(E6`4xRv}t$!Mb<0}Cyq6<#U2A{|P?yclZQOHE;$sUM- znGF63`}N=wuu7~1bwTv;U|UcKBEDiZYm&jHX|{Fp=+SvK$?(;a6}@_tKU!6JZKIUF zvS>!Zp!?ir_{bFJUJc_R^+m-4QSWy7*GIi%9-AN|$o2puh#JN8isa+*9aN6tHh%#x zU@oh(0KeYv$&!^To0{;wDfK>BKoU_{e|L%)A&`2%14Vm)69@0w)qp_a+IYaqw#lk=)NFF*iZKDwsM8iwZ4iZ&T59*HILP;3|vSM-V& zum~SEkN#L)T$C3VOS)WUTUMM`G|zK(UR+HC4F!>?_@f< zvB7i-riHb^nNpJXnCu!Lf`1Y%jEE~dl7K)VUCEPdh}A(PLwF$H!@P&PiFdy^Rw&Uzf zY^JcazNolTe7aCLcMtY6{hpmkMD)AtI+#y)Yfea{JBzg9-$R2Q4iWDSE2nNR7z;ww z32`|_zMGzU+EMEFw@-CJMMR4_B%+9jTs7A z!laX{PB{Ux=*Gj#x`)LTUAE`Z=w+$&D377TUJnC_Nf>bY2PStD`W*U2tejvN6T&_+ zY%CnRr=vOoNKE?0{;mdk#X}$K!ADg!aJ4%J@G@2A`>Mw@Zz5#W`=3>L z%72gOli;~_8O|3$30(7&8E)Ev zQ-6xzI;%Ta>UIdpdfQG$s-X2JJaeC~$_@<=!nM>#_kX70?(3Q1B3{Wsx!FNhGE&z* z(IPV6(mO;n3!CvID(z$Cfmw&h6NXSp48RIB`S8^Lh*n$2%R3vc%YIbbao=(GWxeqL zA`ubcGK2tm#gXbzfG}f`cn(8!CYQ9Xvww4%mZY9+vu2ZWqWn*c*y;E(;^JmR@ffm_ zO8`x(Yn!es9*O7xQA}clA0AKJuhXOH!-s8b9*d$1Q@x9#^LDXF^-ZAg!AKVSEl^Ac z5lqg`a2&y(WJZ+Kd)r6<`)Q0E9i-VuGCKup!%p|3&p!jFdwy362`d?IVIR$LfPbk; zs>)VQR#z)$xPZT|aBZKll?<|XH+Vqv2%4-5dLvqtGSI+htcX~w!ntnG*eYTB1X%Sj z&r2a_4Y3eLf&pnXUR7cEBds`>WR#dN?GCPpV?46kEI#9j7thTldnenZQZNG2Ni;cO zE0V2Nr}D!AS|X$ez3Z90o#WuvviYpIMsFeeP(Rq z7fKqdwo7O6(`OJ$LPd%vw9l-GO* zcU{?Sz7))L=SED=n)%Tpv1ikb8(A_OYVHVNfsO>%?1cz?nb0c`ih)C+iQo;~qyzQh_hZlO;wdZ^RwV6zEu|1gA&VUV;R=jGrDo+Y> z`1XPyguYcDC;-Ta-n*bV0Ac6PkfFPeMUAy!mB#^{l>)sbmsS%ekRNQ`0PmmT%mGkc zP@R_*AZ$!j5GNft0#yuc6_9Rn@HKnw3dvsuf*jD7G6OEYO<$d=ZGT^NwLVQmG@c(V zBzj)hQ0Plb6KH_MK_oWgursm!K6EB*Dk=3l)1*s2C$geBip?fFVD3J!n0aA4!r&uot@DStZwR2Pe;w{ zF1o9AdcYc)uI%8q&H}46_+2;~Llk*3Q^i!u-iW4Zoe|s^1y`QDBn^fEY9xEIl_`xA zIK~9nW88A^jgq*i>n!f*OJsybG4U;kE6JN0{J4VV?&UMbGk@BB{8$rX;Pw%*m$6)> z$dII_KMqv6NGno_fR@NkPYbefUM?)5izYh&nX4$15aTP`?IO@;#Y{<$bq@3kdIP+b zK^g*xU17T&o6`lrFXwa--`0?a<5;3uQOB4zf^3PKsj|uH@9E7GeqKkFt(9WB<9gmK zpaBNgIj4)=j(@w8a<`LT4R;|Tr?x7BJsLu{tV;^hdtkbj3qaaC)yQ|)bvqqXA7owT zYAHg--KZoO(zn0Ebkku!cI0I2NcGSjm;q$B0u)=F-U_bjgq@I=Km7dU)yrp3;MWJj zYP}OB^ck@>ro`W=h}`}XdoLt-)P!BuB1Q+^0?j&T`hQuK43Rb6YHIDI!3e*E?{>J~ z?URPw;(Eded<6L0Js%2;YZW~UyNcSF6e*v#DD(AHDnyBOh*G+lHAypX7rR|E&+)Of z;$c`rMA^lRog^6jB9wpM2=PL} zxKc^llaTC}dxLzblMY+nvgM6xv9n4EvI@(^u+>;RmkB!Hr zw<*g$HzN|=sz;KH*fTQY=NPY*G>-L3^2k$C&3~eZqXD5>r0jz5IAIrY&xg`0mWMNs z43DQ;{bDN^%%Q<3f>^cc?Y)Z(Y76KJvol(-`)Q33$9ur2G@J>Zs!bk8E|}eP;;Dai!7I7>kb!|?Iu^`Axb@sgn!ZJO?!u@h!cpQ z41ea~Q+-SiDRkH)$~6hJZ_=8CW|6bA*UwL%q_@~w@j4&^t}EUMR!ZN(jo;hnUiRdh z(W<+xFOhUwe}FKnsX2kMn$$M>Kr1^2XK@+qvUf>U@JDGu!C{k!j({VC{o(pKIkrv4 zL?XacEyHZ$d>?VUeDOXQ7tXRFH>zAt<^VsQmh3#x&qOy6-`9fg?cxu-p_>j0#)=2g6$6#XP%TkapB%Te5?$u1~5>YV>!y2M!|brs z+qp6ah-nthOK`b_d3NPds+r59)B+P2JGL%oT*3lW3YdAbnCeGiv*5@bTO#Mc-o^Rg zr}^1HE(9aP_p~>owb*$s=*{cw0)ITx!S# zW|WMOEtEGmqu5W{Eg#i$;lb#CjULz*=_m5zpGo#&$MVtG3g~{=-FACCSXSa6B|kCm zkK;BV%*65W-Hsz^K~3pOuznhk7lw_p*Aa`A?@JSu)lGXTDB9T5sEP?(!K1(_XVjem zkVCK18dDaNs>jFVVsTz&H-8R5#dj%U3v@vVgJ?ROie5EN9d3DZoatN3)+hEZDuf%ubt{NhLE1`b3O!!zy>KVjcAu0zL%gFw)u6KIo zmA$9F^jMj2^`*_cTo`HrxiATfXFOrnhWpHdmJK87Xws)<2Y*%;XY0uy%#(A^9SeCM zVCKK!#^`96v-MxT%bYBPck}K2*$I$CUOo;Rtk_*=ztHRge6O#wt9RmPiZFoNr_}g6{%(jM}GsVGivQpd;wjd7UPec61N}O zDPFCzWA4{4J)L2Y9%!>es2`>?u;o`Hnv3CqBb5Z%c&ML!^#gh55~_<_-UX2T>C!Rco>#_BYb;Hfpw*Sj6i zNO!P3q<=7F@|is}zC6f*Z_K$5IC`a#POIJ+#;+p!1!AX2C6wP4IP)`=3_i5Lqgz|P zCiL&1gE=C%BXE-yu_t7*(v(nEYot3yW}f9lwLV!}R9eU}Dkeozet>h0-xbB4u;;+p zXLW~yz|;^)0rPO9KzDdhpW`-MN9>)s0hz-URDX|?DqfIb8%qijz%D6tjTBoOl~YIiO93Ay{||rARy~fZo0m4LOBd51j4O-V#4b0p*}?i%SDCanVL2gE z0Dm_lFDr4Qw;9tRNHL?wYV<5C&kOLVbJacwf0nmRP!3aAIY}2YiuaP)uCkVXo0>M0 zJXH-l>{couo@p)p^hUQ@S=^6Cb+za5S{l+Dq8vx%BBf>;!!lPH=J)pcuvCrlxZ_C8 z$KzqE?8x8TsFL%10Su5L>$drTB-adt%70qOEg)Vz-Si*+$QE%3@TGNZ5PIV7GHoq) zujK+2tV5G4=uF{YOQkevf46!@7eUFmBG`Kou4EU=#8bGf>E?pL$oB@SfHzM;+&`SDY#Q7F7{F6H8_WJ1>}4Lk@{+~ znY?)Sgb&0@pydh zbfS%2RqJJgPKph3#7;#D1})EC0Aj#wIAoc2x^iX-J)vH2aZ(Au!B#8kODQ5k+YgY{ zsrwKtwG3!x` zOO->zRd(IlnjXWGckU_2dG(F={LIixLzH`?pWNj8iErJuI!KK~fAbj9XDNfAg{c zh+_f!MOh_8IYNoSXq%(!c-&x)604+zNG5cCw1|c9`vray_HBsU$WYpwS=?2Q#E?x! zG3Z7j@vFq*KzZFcf`3w|KfhvZPhRWI5Z$EHa9dG86AiAk!-0Hd3+J{O)PEcrRIm-1 zAr-%Z16u06%}Ry?IW;X*Rpn2^;DCZJ{AhuX=9`Q^X`&-kU`GE3^OmB3;>eKPyak42 z4h{*5!TxouQ|?Uag5@+ihP*p=2{gR-BmvVh1MsVR$dFQx$A9$qsJ3i-?Rd<7iCRMS z3zWTP4{iLLY@@(WnpVgIsG4q!30$~0Pb`Pvj70lx7K{`rC4=V7p*@OKz8!so-3svWzfKcFc)#lXR-A#rv5e8}FKr`co zs8Vi11S=6DSbxP?8bu8C5I(OKixhGrPH9?dAXH||U3+qe`1#YHsbZ^wSi;(JHp5R% zltFuP?b=aR5&JW04kD0su1<%jLVa+06ekha%o|4SnX?DS;Es#*^J=J_hi!m|XukE) z-?~9;5ME(!{^BJmD${beW8V_?ebo3vIiNPQ*o`uC6n{GFZTQ32uA^AQS z<2AE2KZ>=p@8g91E%NX%0^>(Q;cdSNH+t-Z&ixz;fDvHLnfND>O7@KYuJD({GEoYU z$ew;bL9!bqh{_MrA^tvfyjJY@9a~@vXyS-=Ab>PVnMX_X_eSDTh1eV)?}ac&8c_jZ_}#@ZHyv z5wo{|%?md|XRrMU@`#zOR?e42UNLyi9#iw!seg4fatj4L1_4S8D;P*3!a=4Z23IK# zAgja~4!vHMuB6j7qRJ`}?4=zU67P0)Y%~V^C@er{_$S7XAUCzS?OIq&&A!sed@8CX zyB!tTZu^+qEfl)-SW;Qh7FehLx!ZLhn(W9xX~1Kkv5Q7Ur7Ez3NiPH<0D97k?@^z~ zOn;6dJ)W55JBK_MEvn6>aD}TG>re1$K2@4Set>YGib;(dq!z_R9Oo(fDJo)-WQwQ7 zbjfLUp@SBA%4b3*MqGuLk=iKWvpKhaE|NK4ba;#GdD@53z6%xUd(|bMBvefx6Srcg z#S5T#)YjU=i?s#Q=43w7&yUE+etJYk{(rN8 z12mK|`o9Vyqh`jwOXMT_3fxxWZ_tEr+NW5I&DeWmI07^BPhcnsyaV#v%12>5?thB2 zGgb`klu+MH8VH*uEX@Ff3u=7eZ868CpE8r84H8YsQxR!XAsR>y_A&UdsqDu9)C#>h?quZNADVh0Q3nKLjv9gAp6ZRYt#U$vFyxb zG%!1h$W+j5km)z4Bge#}EBrJjTt^;;)fM0`=(*D@(vtLkP}+0}+gy#MNAmS5I7j3j zLJ>n1PL!s0f{E*3=7N~)2{`c|zzA`PET5``au#dFc+BDSiIJv_tNY3PEr0Lm`STB3 zaRdtF%MOYjKSIaF@7ubJA8~Hq>%sF+rHvsRk!w<;IXbR%FXIQx9CZ93Rx=ieYATg(?uX3H9@Ms&Ld!Y0Km!a+iZe#jc@8T!g+1AOKk$TWYf$ z9B289ovu#j)q=Ev1 z+OoG9k6VoV>5G9ifq(z~t0Sc49P0&w<5UXepew}PxZWPfm_vePth_AvdN^|eC3%Lq zV8wg!gg73T)}%FOx6+Cr<_hc}UL#m}dQMuTPSH#>&Ez?$O|uA(aQ0!SjpHn3|A<<7 z7;4gXx8v@4DDpKRWm)<*Y+0h;1JoDZjfq3yIl%pbHiA(@vwtSx55Owh1SlJ!y5Lw+ zO!_MsS0dd5R*wt(hzXO_17qe`2#iy@U>ul!k$E=d&W_ZL^`ccw!bpkBIqA^xVn3l{d zk}tH`q}m489Un0OpMkRojrtU^I7(SXf*St$G;o3~#tQ%b0Mh10P$C5Z4`R z?{dfkq<)lfFTzV6y|cEdAoU;g)XhN9FCiqyNq_J6nc7J$&O(FwFj>moy`b@+pDev= zKN4~)R--hp7xP5Y~zbhFIYr@LBx_@NlIhdXj<$kkZp?YSOrXM zd6m<;b}@1itrp%K6;X6X94KAuo`CRcPdTN@?IjRz%J-UF*dh=CuvhB?BB*MM6=wTV zjw=NP8};K@EUEORK~GHV9t*ku%_-i24Z&Q~AA{3PY%$de4#E)J@>1d-vhg?ruYa~U z)yh*wDI&p8k*cGN)CABQQe3r4o=jQV0+d7VE5pLfW2N+l>{wNpgTlvd=5rg!f{YXr zLc0#}+GD`Y9QoxId$I~x1oXE$2A07$RaMYTkR?taX{`EJs+jxfT@l3)SSom6SNKoX z0MLd|QYeKX-cwDl$&ijmvfe~G(tm61r;6^(@&1@^sw4|f6(kl#tuwnb3y=$niJ2g^ zosvq2KD0r#J2EXMT~Hgkvu+NgaKp|pVMEXG8S}o(mYOVn3FV69V9)=Ee*Zw9!|m!F*!Z(H0JY z(K0O}doDo?0nU_5@qNxwFn`L4^C`=CdO6$RN|!2lQWC2N#Kw5JPuQ2@i(0j4qLwHu z*lLk(;h-*f;f*M?)g1h(Hn#D2s6$o&Sv;)$L%P?_*w@@K(@@k8+58o8$qK9q(pW@B zfmG;6XmTC6f-Y#`J3k`F^izz#1Ms$*IGR+L6MM!uJ1ZkLg|#CP9DgK3YaP)FoIfi# zKW)?1{CF`%5ZH!nK^~-;?tF+85eV?50C|^kGhXh4wDn@nU&5|e#^gNBCQ>0np%vLb z)A<6|?YTA#v-s=uXt#^bg>jh0w%RBS#NvmF5sWyw#Eb`8OTWZPc@+{qrNQ^kqAOd5 z=nrF3sN$!4en|^Y}_5UgvO}3azF$-r8EG}v#L`WCxFYVBZtJ>*yj<4andK2FY!02 z_KM2*fTl^^8Sgey>x`wTxeuwbx(%Ehm<+0MQ zv*6}lDK;U?%4eOHYNE}SDg+CzSwfApTBOC(d~(HV*3i{%7wNx|a5fYYrN65ZELE$h zB9_%jvl2V61Dlh2Au8cfJs#(=g`Tc#^fZto*-+^ocPN;`UC-4>yi?MAM>P_mjquHQ zOj$PQ58=Mth|O$IOi*KxT1TOFkFch zVV_1NsR3(kV&v8kBL`gGKEtqkt zw1{%jxOyk7F>q5!&!#*-WzGqYl9E)|k<&FiBBrKbB>|CwbFd-nm@r�-wSrTgYpU zivsDkk$**2e|#R#at#ts9Gy7_Ztk9}kKkFS#$5>fx8=H;1!P#q){hJnqC9*IavUp@ zZI>>n0<{h3i3CaD7XYz0wy)1!$JJ%F)xHq);0hX8(J$-^(G$C!V>SS8Sj^C3qs;%V z1Kp5?YquLhK9aAZ#>(P=CI-A}7&n@!YKnbA?SJED5v71V1piIMZ-Bvw&PnYR(&)dz z8#9y5PfQW9wI*1OWa%x`0sC6EP1xRIAFp&+ov0Ge%W>R4fy?+-8Xr*G5S^n>=p`~- zI3%`J5F+B$Vb?&YQ=N%U$gDB>%CaKR-EJ7E?lN6q58;=csX-(Z5BaplWA+v1JBnal zV1KLx%mn!vjZ93GY5G?)=@1>}C_&xrig!eXRve&2Dx+wV9Oa?W;cT+9TZjF46Zk{90;mMILb8}3lq|kkvsxc>p^Cn?`lnRG5Kft z&+-(AgL5=Z=2=_QLADaeovau{ZQY`yB!kg}ojM+rw7IVM#X#o%uE8aQIdMhvntx5! z46Z4sgR0q3ehmq6Q9Q52+bXD^)4E2yBIL|n7W8ruU2j;v8L%4dquF5Do)1_#c(SdE zq8dC!MJOiLR}|8JHXBg}FB;IYZaE!5B3|)zwTZBOP{?q_K~_Q#?Ss)^lU>n4Rt{c1 z8&rId4f3{bs!Qn+Qe#Zu-Y6N3P=C>5CG9JSfx6iJx`Dase=?}6!OQYBy{!0+7|1*; z2X(fl+6C2YXiZhS6X>YH0C@|+lHPwd&tkQa;(45m;5l_%JMdi9eeR#-i;4@>Dabf} znF-OetlCC347svpN}U znr2%kj~<;@lMDwNlFmQMADz>Z@(jNJVOz5IEqy4h3yktwRQ?Qx1S$^>$$`3|AXHpd z<--y_wP1hJ)kE31f0iRuIfXbb4{^V`;F;TftT$tg{PgHU%gMEb-AO4=48}m^kHtBn zk7*^6Y5kn>ls|^TAD&ii*?*)EcO^rG*cL+aN}Kp49S+L?AB;t8D#&DijBbU8yd<3{ zqp~kNgE-+lrkrz`*Z@pZ#=eS*5GxsSg5OPx2qnWj<045Ie$Xj0!A7^5Z^|Jz_wxCL z`O#Q;4t6cLXHvKV%NJ6JwU=9q-1(hhRf{^DtnU3gh*?n^eTU{E1%EU5`L3p>;4k1x z5o`tQGs&sx)go@bRRb(Sp)6uTJLpP4+&T<#cM-@1hzzYKB%4=4btDylh47lT0oIrY zl1tOsWp=Zq-|#A1epYz_8ZaV75n*)jP)k^w18w+5{ zp@#)>N!rA5MgX`pf`8H&Lqx1H z)py#Rt%8Y+yF`9vYLd>4#|@gdeNJk*z{1>vhulHZ>+a02Lmx!M9JYVwGwC!LK@M`7 z%Uq7a1TGlp++0|7Y_Zr(g{6n@-QGest(#+Bcfx}Q0$eXPA>s=p2L|C}j@z$U37X`s z%&H-4*zIHnc)gfqWT3maX&uF0D+77VVNL2pCy;6y6LCT|90#J_r1u|zY5%9|)IQzp ztT}_oWnZV5g*6eU;7e4S8;0=h@C_AfVaNGTP71^Kq5p)16ua5#qwe=A=gz#@mjp?@5+wIHm$8^~RqEekw2Fmqe)) z5LiZ1(e%J#Wvj$qar=0GSVVjCOegU&-0^?4pu+icp9QY;f4x3HeE>mM=NVtg>SZ

y67Hr8v~GAwLu(moMNCm3Cg9&58A?{kXQe*n7F$ob$t^Mj>$^vwMi#9>H&+ zojq?$Iaq(iPI*?=Stw@47HYWSqFb@55=yM&oYc`_q5H?H2I_{FC__*%Rh@NYcO*;D zisT_08)U*Q|4^r~o`-6gR{E|o4J7g~N$+US=e(%+D^_0giNubXLp2r{B2*m`6XA$8 zZ_p0Lqw5Xr@J3P|-bhqp-UIFE32-a2x_QRdYh{1i0sR~XCIUBKWJ}!uXLIA+mO&jx z1lw~GKncUf6UeZQ!-VrLJ1dSub}vjDik@8I@hLSqtYQ=g-R`2I$i{ADGZ=2?HYTIP2w4R2ap<;-b zee(9@X>~#E^3HYhnwRCaZSdh*Kka{^eN{cF%04}L@;$w=%HnUg2knyn^Dih})vvQM zJEt7K=_xK&|K&Z!!r#%?D|RJ^USMi{)&hS+fOlJc)}dFD(FrThi@}((|3=*r#IiU<*Mk6k8{)S<~L8@9eS|$xwntsy2EQ-HD#aS&e@%G?)AQJ6Q%q~ zXJ3WEE?C~EzP0bYEU&VHAznCiyMIB6QvUq4uio|SopbkKvAb$_CWyXt*Hb-HByfN8 z9yJ}R=-&1CQ^>x0*Rwyrdl7h6Ts`nCtHF>RUhaXL2WtXu>F=r~UU6!%Z}ivjyzFmE z_uhee;NKqk`kyS7`w6&vZ;xd3t}VZ-mLeGPU0dEQ4xcw0OTVys$GINpk{2{8 zh`NF|Lp^R^4b=E8ZBBlC^{P4t=dFKv%3OmoMYYU|SJn9|dPNIU$h|&V5NG{xF9GLpr900e(?{qy21BT4%bIST;F8%22Ho>VpTPD!?UgY z{ghXw{PP)tTHgs&hP?KoXg|EJO4d}W)^D?hUS~J**Y}ie^$S7#m_OxTCry7=t}?!Q znr*WsE6`l1Z*iJk${#EUJ zEl$lP_;8Ta)^B$@K4}_A1k-!px*SQEA zb0Y|&lMt3nLs;nbAS)y9;F&QGm(szxct#d^c0;qb#r!JG_7eRjLGsT<#MQGF(@Nok z04M_p+mZq@NkEqdSKt{C8BZX5WSd^h3Uin1e|DAp6AnhRDic^_h! Zq7nEm5#$vE$RUcS{|}>I1!MJXKL8Q)u3P{B diff --git a/core/web/chains_controller.go b/core/web/chains_controller.go index a99cbf4ca4b..6bc5ee4daa3 100644 --- a/core/web/chains_controller.go +++ b/core/web/chains_controller.go @@ -5,14 +5,13 @@ import ( "net/http" "github.com/gin-gonic/gin" + "github.com/manyminds/api2go/jsonapi" "github.com/smartcontractkit/chainlink-common/pkg/types" - commonTypes "github.com/smartcontractkit/chainlink/v2/common/types" "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/logger/audit" "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" - "github.com/smartcontractkit/chainlink/v2/core/web/presenters" ) type ChainsController interface { @@ -22,6 +21,16 @@ type ChainsController interface { Show(*gin.Context) } +type chainsController[R jsonapi.EntityNamer] struct { + network string + resourceName string + chainStats chainlink.ChainStatuser + errNotEnabled error + newResource func(types.ChainStatus) R + lggr logger.Logger + auditLogger audit.AuditLogger +} + type errChainDisabled struct { name string tomlKey string @@ -31,51 +40,50 @@ func (e errChainDisabled) Error() string { return fmt.Sprintf("%s is disabled: Set %s=true to enable", e.name, e.tomlKey) } -type chainsController struct { - chainStats chainlink.RelayerChainInteroperators - newResource func(commonTypes.ChainStatusWithID) presenters.ChainResource - lggr logger.Logger - auditLogger audit.AuditLogger -} - -func NewChainsController(chainStats chainlink.RelayerChainInteroperators, lggr logger.Logger, auditLogger audit.AuditLogger) *chainsController { - return &chainsController{ - chainStats: chainStats, - newResource: presenters.NewChainResource, - lggr: lggr, - auditLogger: auditLogger, +func newChainsController[R jsonapi.EntityNamer](network string, chainStats chainlink.ChainsNodesStatuser, errNotEnabled error, + newResource func(types.ChainStatus) R, lggr logger.Logger, auditLogger audit.AuditLogger) *chainsController[R] { + return &chainsController[R]{ + network: network, + resourceName: network + "_chain", + chainStats: chainStats, + errNotEnabled: errNotEnabled, + newResource: newResource, + lggr: lggr, + auditLogger: auditLogger, } } -func (cc *chainsController) Index(c *gin.Context, size, page, offset int) { - chainStats := cc.chainStats - if network := c.Param("network"); network != "" { - chainStats = chainStats.List(chainlink.FilterRelayersByType(network)) +func (cc *chainsController[R]) Index(c *gin.Context, size, page, offset int) { + if cc.chainStats == nil { + jsonAPIError(c, http.StatusBadRequest, cc.errNotEnabled) + return } - - chains, count, err := chainStats.ChainStatuses(c.Request.Context(), offset, size) + chains, count, err := cc.chainStats.ChainStatuses(c.Request.Context(), offset, size) if err != nil { jsonAPIError(c, http.StatusBadRequest, err) return } - resources := []presenters.ChainResource{} + var resources []R for _, chain := range chains { resources = append(resources, cc.newResource(chain)) } - paginatedResponse(c, "chain", size, page, resources, count, err) + paginatedResponse(c, cc.resourceName, size, page, resources, count, err) } -func (cc *chainsController) Show(c *gin.Context) { - relayID := types.RelayID{Network: c.Param("network"), ChainID: c.Param("ID")} +func (cc *chainsController[R]) Show(c *gin.Context) { + if cc.chainStats == nil { + jsonAPIError(c, http.StatusBadRequest, cc.errNotEnabled) + return + } + relayID := types.RelayID{Network: cc.network, ChainID: c.Param("ID")} chain, err := cc.chainStats.ChainStatus(c.Request.Context(), relayID) - status := commonTypes.ChainStatusWithID{ChainStatus: chain, RelayID: relayID} if err != nil { jsonAPIError(c, http.StatusBadRequest, err) return } - jsonAPIResponse(c, cc.newResource(status), "chain") + jsonAPIResponse(c, cc.newResource(chain), cc.resourceName) } diff --git a/core/web/chains_controller_test.go b/core/web/chains_controller_test.go deleted file mode 100644 index d4e9b785f23..00000000000 --- a/core/web/chains_controller_test.go +++ /dev/null @@ -1,586 +0,0 @@ -package web_test - -import ( - "fmt" - "math/big" - "net/http" - "sort" - "testing" - "time" - - "github.com/manyminds/api2go/jsonapi" - "github.com/shopspring/decimal" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - "golang.org/x/exp/rand" - - commoncfg "github.com/smartcontractkit/chainlink-common/pkg/config" - commonTypes "github.com/smartcontractkit/chainlink-common/pkg/types" - coscfg "github.com/smartcontractkit/chainlink-cosmos/pkg/cosmos/config" - "github.com/smartcontractkit/chainlink-solana/pkg/solana/config" - - evmcfg "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/toml" - "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" - ubig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" - "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" - "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" - "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest" - "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/cosmostest" - "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" - "github.com/smartcontractkit/chainlink/v2/core/web" - "github.com/smartcontractkit/chainlink/v2/core/web/presenters" -) - -func Test_EVMChainsController_Show(t *testing.T) { - t.Parallel() - - validID := ubig.New(testutils.NewRandomEVMChainID()) - - testCases := []struct { - name string - inputID string - wantStatusCode int - want *evmcfg.EVMConfig - }{ - { - inputID: validID.String(), - name: "success", - want: &evmcfg.EVMConfig{ - ChainID: validID, - Enabled: ptr(true), - Chain: evmcfg.Defaults(nil, &evmcfg.Chain{ - GasEstimator: evmcfg.GasEstimator{ - EIP1559DynamicFees: ptr(true), - BlockHistory: evmcfg.BlockHistoryEstimator{ - BlockHistorySize: ptr[uint16](50), - }, - }, - RPCBlockQueryDelay: ptr[uint16](23), - MinIncomingConfirmations: ptr[uint32](12), - LinkContractAddress: ptr(types.EIP55AddressFromAddress(testutils.NewAddress())), - }), - }, - wantStatusCode: http.StatusOK, - }, - { - inputID: "invalidid", - name: "invalid id", - want: nil, - wantStatusCode: http.StatusBadRequest, - }, - { - inputID: "234", - name: "not found", - want: nil, - wantStatusCode: http.StatusBadRequest, - }, - } - - for _, testCase := range testCases { - tc := testCase - - t.Run(tc.name, func(t *testing.T) { - t.Parallel() - - controller := setupEVMChainsControllerTest(t, configtest.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) { - if tc.want != nil { - c.EVM = evmcfg.EVMConfigs{tc.want} - } - })) - - wantedResult := tc.want - resp, cleanup := controller.client.Get( - "/v2/chains/evm/" + tc.inputID, - ) - t.Cleanup(cleanup) - require.Equal(t, tc.wantStatusCode, resp.StatusCode) - - if wantedResult != nil { - resource1 := presenters.ChainResource{} - err := web.ParseJSONAPIResponse(cltest.ParseResponseBody(t, resp), &resource1) - require.NoError(t, err) - - assert.Equal(t, resource1.ID, wantedResult.ChainID.String()) - toml, err := wantedResult.TOMLString() - require.NoError(t, err) - assert.Equal(t, toml, resource1.Config) - } - }) - } -} - -func Test_EVMChainsController_Index(t *testing.T) { - t.Parallel() - - // sort test chain ids to make expected comparison easy - chainIDs := []*big.Int{testutils.NewRandomEVMChainID(), testutils.NewRandomEVMChainID(), testutils.NewRandomEVMChainID()} - sort.Slice(chainIDs, func(i, j int) bool { - return chainIDs[i].String() < chainIDs[j].String() - }) - - configuredChains := evmcfg.EVMConfigs{ - {ChainID: ubig.New(chainIDs[0]), Chain: evmcfg.Defaults(nil)}, - { - ChainID: ubig.New(chainIDs[1]), - Chain: evmcfg.Defaults(nil, &evmcfg.Chain{ - RPCBlockQueryDelay: ptr[uint16](13), - GasEstimator: evmcfg.GasEstimator{ - EIP1559DynamicFees: ptr(true), - BlockHistory: evmcfg.BlockHistoryEstimator{ - BlockHistorySize: ptr[uint16](1), - }, - }, - MinIncomingConfirmations: ptr[uint32](120), - }), - }, - { - ChainID: ubig.New(chainIDs[2]), - Chain: evmcfg.Defaults(nil, &evmcfg.Chain{ - RPCBlockQueryDelay: ptr[uint16](5), - GasEstimator: evmcfg.GasEstimator{ - EIP1559DynamicFees: ptr(false), - BlockHistory: evmcfg.BlockHistoryEstimator{ - BlockHistorySize: ptr[uint16](2), - }, - }, - MinIncomingConfirmations: ptr[uint32](30), - }), - }, - } - - assert.Len(t, configuredChains, 3) - controller := setupEVMChainsControllerTest(t, configtest.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) { - c.EVM = append(c.EVM, configuredChains...) - })) - - badResp, cleanup := controller.client.Get("/v2/chains/evm?size=asd") - t.Cleanup(cleanup) - require.Equal(t, http.StatusUnprocessableEntity, badResp.StatusCode) - - resp, cleanup := controller.client.Get("/v2/chains/evm?size=3") - t.Cleanup(cleanup) - require.Equal(t, http.StatusOK, resp.StatusCode) - - body := cltest.ParseResponseBody(t, resp) - - metaCount, err := cltest.ParseJSONAPIResponseMetaCount(body) - require.NoError(t, err) - require.Equal(t, 1+len(configuredChains), metaCount) - - var links jsonapi.Links - - var gotChains []presenters.ChainResource - err = web.ParsePaginatedResponse(body, &gotChains, &links) - require.NoError(t, err) - assert.NotEmpty(t, links["next"].Href) - assert.Empty(t, links["prev"].Href) - - assert.Len(t, links, 1) - // the difference in index value here seems to be due to the fact - // that cltest always has a default EVM chain, which is the off-by-one - // in the indices - assert.Equal(t, gotChains[2].ID, configuredChains[1].ChainID.String()) - toml, err := configuredChains[1].TOMLString() - require.NoError(t, err) - assert.Equal(t, toml, gotChains[2].Config) - - resp, cleanup = controller.client.Get(links["next"].Href) - t.Cleanup(cleanup) - require.Equal(t, http.StatusOK, resp.StatusCode) - - gotChains = []presenters.ChainResource{} - err = web.ParsePaginatedResponse(cltest.ParseResponseBody(t, resp), &gotChains, &links) - require.NoError(t, err) - assert.Empty(t, links["next"].Href) - assert.NotEmpty(t, links["prev"].Href) - - assert.Len(t, links, 1) - assert.Equal(t, gotChains[0].ID, configuredChains[2].ChainID.String()) - toml, err = configuredChains[2].TOMLString() - require.NoError(t, err) - assert.Equal(t, toml, gotChains[0].Config) -} - -type TestEVMChainsController struct { - app *cltest.TestApplication - client cltest.HTTPClientCleaner -} - -func setupEVMChainsControllerTest(t *testing.T, cfg chainlink.GeneralConfig) *TestEVMChainsController { - // Using this instead of `NewApplicationEVMDisabled` since we need the chain set to be loaded in the app - // for the sake of the API endpoints to work properly - app := cltest.NewApplicationWithConfig(t, cfg) - ctx := testutils.Context(t) - require.NoError(t, app.Start(ctx)) - - client := app.NewHTTPClient(nil) - - return &TestEVMChainsController{ - app: app, - client: client, - } -} - -func ptr[T any](t T) *T { return &t } - -func Test_CosmosChainsController_Show(t *testing.T) { - t.Parallel() - - const validID = "Chainlink-12" - - testCases := []struct { - name string - inputID string - wantStatusCode int - want func(t *testing.T, app *cltest.TestApplication) *commonTypes.ChainStatus - }{ - { - inputID: validID, - name: "success", - want: func(t *testing.T, app *cltest.TestApplication) *commonTypes.ChainStatus { - return &commonTypes.ChainStatus{ - ID: validID, - Enabled: true, - Config: `ChainID = 'Chainlink-12' -Enabled = true -Bech32Prefix = 'wasm' -BlockRate = '6s' -BlocksUntilTxTimeout = 30 -ConfirmPollPeriod = '1s' -FallbackGasPrice = '9.999' -GasToken = 'ucosm' -GasLimitMultiplier = '1.55555' -MaxMsgsPerBatch = 100 -OCR2CachePollPeriod = '4s' -OCR2CacheTTL = '1m0s' -TxMsgTimeout = '10m0s' -Nodes = [] -`, - } - }, - wantStatusCode: http.StatusOK, - }, - { - inputID: "234", - name: "not found", - want: func(t *testing.T, app *cltest.TestApplication) *commonTypes.ChainStatus { - return nil - }, - wantStatusCode: http.StatusBadRequest, - }, - } - - for _, testCase := range testCases { - tc := testCase - - t.Run(tc.name, func(t *testing.T) { - t.Parallel() - - controller := setupCosmosChainsControllerTestV2(t, &coscfg.TOMLConfig{ - ChainID: ptr(validID), - Enabled: ptr(true), - Chain: coscfg.Chain{ - FallbackGasPrice: ptr(decimal.RequireFromString("9.999")), - GasLimitMultiplier: ptr(decimal.RequireFromString("1.55555")), - }}) - - wantedResult := tc.want(t, controller.app) - resp, cleanup := controller.client.Get( - "/v2/chains/cosmos/" + tc.inputID, - ) - t.Cleanup(cleanup) - require.Equal(t, tc.wantStatusCode, resp.StatusCode) - - if wantedResult != nil { - resource1 := presenters.ChainResource{} - err := web.ParseJSONAPIResponse(cltest.ParseResponseBody(t, resp), &resource1) - require.NoError(t, err) - - assert.Equal(t, wantedResult.ID, resource1.ID) - assert.Equal(t, wantedResult.Config, resource1.Config) - } - }) - } -} - -func Test_CosmosChainsController_Index(t *testing.T) { - t.Parallel() - - chainA := &coscfg.TOMLConfig{ - ChainID: ptr("a" + cosmostest.RandomChainID()), - Enabled: ptr(true), - Chain: coscfg.Chain{ - FallbackGasPrice: ptr(decimal.RequireFromString("9.999")), - }, - } - - chainB := &coscfg.TOMLConfig{ - ChainID: ptr("b" + cosmostest.RandomChainID()), - Enabled: ptr(true), - Chain: coscfg.Chain{ - GasLimitMultiplier: ptr(decimal.RequireFromString("1.55555")), - }, - } - controller := setupCosmosChainsControllerTestV2(t, chainA, chainB) - - badResp, cleanup := controller.client.Get("/v2/chains/cosmos?size=asd") - t.Cleanup(cleanup) - require.Equal(t, http.StatusUnprocessableEntity, badResp.StatusCode) - - resp, cleanup := controller.client.Get("/v2/chains/cosmos?size=1") - t.Cleanup(cleanup) - require.Equal(t, http.StatusOK, resp.StatusCode) - - body := cltest.ParseResponseBody(t, resp) - - metaCount, err := cltest.ParseJSONAPIResponseMetaCount(body) - require.NoError(t, err) - require.Equal(t, 2, metaCount) - - var links jsonapi.Links - - var chains []presenters.ChainResource - err = web.ParsePaginatedResponse(body, &chains, &links) - require.NoError(t, err) - assert.NotEmpty(t, links["next"].Href) - assert.Empty(t, links["prev"].Href) - - assert.Len(t, links, 1) - assert.Equal(t, *chainA.ChainID, chains[0].ID) - tomlA, err := chainA.TOMLString() - require.NoError(t, err) - assert.Equal(t, tomlA, chains[0].Config) - - resp, cleanup = controller.client.Get(links["next"].Href) - t.Cleanup(cleanup) - require.Equal(t, http.StatusOK, resp.StatusCode) - - chains = []presenters.ChainResource{} - err = web.ParsePaginatedResponse(cltest.ParseResponseBody(t, resp), &chains, &links) - require.NoError(t, err) - assert.Empty(t, links["next"].Href) - assert.NotEmpty(t, links["prev"].Href) - - assert.Len(t, links, 1) - assert.Equal(t, *chainB.ChainID, chains[0].ID) - tomlB, err := chainB.TOMLString() - require.NoError(t, err) - assert.Equal(t, tomlB, chains[0].Config) -} - -type TestCosmosChainsController struct { - app *cltest.TestApplication - client cltest.HTTPClientCleaner -} - -func setupCosmosChainsControllerTestV2(t *testing.T, cfgs ...*coscfg.TOMLConfig) *TestCosmosChainsController { - for i := range cfgs { - cfgs[i].SetDefaults() - } - cfg := configtest.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) { - c.Cosmos = cfgs - c.EVM = nil - }) - app := cltest.NewApplicationWithConfig(t, cfg) - ctx := testutils.Context(t) - require.NoError(t, app.Start(ctx)) - - client := app.NewHTTPClient(nil) - - return &TestCosmosChainsController{ - app: app, - client: client, - } -} -func Test_SolanaChainsController_Show(t *testing.T) { - t.Parallel() - - const validID = "Chainlink-12" - - testCases := []struct { - name string - inputID string - wantStatusCode int - want func(t *testing.T, app *cltest.TestApplication) *commonTypes.ChainStatus - }{ - { - inputID: validID, - name: "success", - want: func(t *testing.T, app *cltest.TestApplication) *commonTypes.ChainStatus { - return &commonTypes.ChainStatus{ - ID: validID, - Enabled: true, - Config: `ChainID = 'Chainlink-12' -BalancePollPeriod = '5s' -ConfirmPollPeriod = '500ms' -OCR2CachePollPeriod = '1s' -OCR2CacheTTL = '1m0s' -TxTimeout = '1h0m0s' -TxRetryTimeout = '10s' -TxConfirmTimeout = '30s' -TxExpirationRebroadcast = false -TxRetentionTimeout = '0s' -SkipPreflight = false -Commitment = 'confirmed' -MaxRetries = 0 -FeeEstimatorMode = 'fixed' -ComputeUnitPriceMax = 1000 -ComputeUnitPriceMin = 0 -ComputeUnitPriceDefault = 0 -FeeBumpPeriod = '3s' -BlockHistoryPollPeriod = '5s' -BlockHistorySize = 1 -ComputeUnitLimitDefault = 200000 -EstimateComputeUnitLimit = false -Nodes = [] - -[MultiNode] -Enabled = false -PollFailureThreshold = 5 -PollInterval = '15s' -SelectionMode = 'PriorityLevel' -SyncThreshold = 10 -NodeIsSyncingEnabled = false -LeaseDuration = '1m0s' -FinalizedBlockPollInterval = '5s' -EnforceRepeatableRead = true -DeathDeclarationDelay = '20s' -NodeNoNewHeadsThreshold = '20s' -NoNewFinalizedHeadsThreshold = '20s' -FinalityDepth = 0 -FinalityTagEnabled = true -FinalizedBlockOffset = 50 -`, - } - }, - wantStatusCode: http.StatusOK, - }, - { - inputID: "234", - name: "not found", - want: func(t *testing.T, app *cltest.TestApplication) *commonTypes.ChainStatus { - return nil - }, - wantStatusCode: http.StatusBadRequest, - }, - } - - for _, testCase := range testCases { - tc := testCase - - t.Run(tc.name, func(t *testing.T) { - t.Parallel() - - controller := setupSolanaChainsControllerTestV2(t, &config.TOMLConfig{ - ChainID: ptr(validID), - Chain: config.Chain{ - SkipPreflight: ptr(false), - TxTimeout: commoncfg.MustNewDuration(time.Hour), - }, - }) - - wantedResult := tc.want(t, controller.app) - resp, cleanup := controller.client.Get( - "/v2/chains/solana/" + tc.inputID, - ) - t.Cleanup(cleanup) - require.Equal(t, tc.wantStatusCode, resp.StatusCode) - - if wantedResult != nil { - resource1 := presenters.ChainResource{} - err := web.ParseJSONAPIResponse(cltest.ParseResponseBody(t, resp), &resource1) - require.NoError(t, err) - - assert.Equal(t, wantedResult.ID, resource1.ID) - assert.Equal(t, wantedResult.Enabled, resource1.Enabled) - assert.Equal(t, wantedResult.Config, resource1.Config) - } - }) - } -} - -func Test_SolanaChainsController_Index(t *testing.T) { - t.Parallel() - - chainA := &config.TOMLConfig{ - ChainID: ptr(fmt.Sprintf("ChainlinktestA-%d", rand.Int31n(999999))), - Chain: config.Chain{ - TxTimeout: commoncfg.MustNewDuration(time.Hour), - }, - } - chainB := &config.TOMLConfig{ - ChainID: ptr(fmt.Sprintf("ChainlinktestB-%d", rand.Int31n(999999))), - Chain: config.Chain{ - SkipPreflight: ptr(false), - }, - } - controller := setupSolanaChainsControllerTestV2(t, chainA, chainB) - - badResp, cleanup := controller.client.Get("/v2/chains/solana?size=asd") - t.Cleanup(cleanup) - require.Equal(t, http.StatusUnprocessableEntity, badResp.StatusCode) - - resp, cleanup := controller.client.Get("/v2/chains/solana?size=1") - t.Cleanup(cleanup) - require.Equal(t, http.StatusOK, resp.StatusCode) - - body := cltest.ParseResponseBody(t, resp) - - metaCount, err := cltest.ParseJSONAPIResponseMetaCount(body) - require.NoError(t, err) - require.Equal(t, 2, metaCount) - - var links jsonapi.Links - - chains := []presenters.ChainResource{} - err = web.ParsePaginatedResponse(body, &chains, &links) - require.NoError(t, err) - assert.NotEmpty(t, links["next"].Href) - assert.Empty(t, links["prev"].Href) - - assert.Len(t, links, 1) - assert.Equal(t, *chainA.ChainID, chains[0].ID) - tomlA, err := chainA.TOMLString() - require.NoError(t, err) - assert.Equal(t, tomlA, chains[0].Config) - - resp, cleanup = controller.client.Get(links["next"].Href) - t.Cleanup(cleanup) - require.Equal(t, http.StatusOK, resp.StatusCode) - - chains = []presenters.ChainResource{} - err = web.ParsePaginatedResponse(cltest.ParseResponseBody(t, resp), &chains, &links) - require.NoError(t, err) - assert.Empty(t, links["next"].Href) - assert.NotEmpty(t, links["prev"].Href) - - assert.Len(t, links, 1) - assert.Equal(t, *chainB.ChainID, chains[0].ID) - tomlB, err := chainB.TOMLString() - require.NoError(t, err) - assert.Equal(t, tomlB, chains[0].Config) -} - -type TestSolanaChainsController struct { - app *cltest.TestApplication - client cltest.HTTPClientCleaner -} - -func setupSolanaChainsControllerTestV2(t *testing.T, cfgs ...*config.TOMLConfig) *TestSolanaChainsController { - for i := range cfgs { - cfgs[i].SetDefaults() - } - cfg := configtest.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) { - c.Solana = cfgs - c.EVM = nil - }) - app := cltest.NewApplicationWithConfig(t, cfg) - require.NoError(t, app.Start(testutils.Context(t))) - - client := app.NewHTTPClient(nil) - - return &TestSolanaChainsController{ - app: app, - client: client, - } -} diff --git a/core/web/cosmos_chains_controller.go b/core/web/cosmos_chains_controller.go new file mode 100644 index 00000000000..27c3976ce39 --- /dev/null +++ b/core/web/cosmos_chains_controller.go @@ -0,0 +1,17 @@ +package web + +import ( + "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" + "github.com/smartcontractkit/chainlink/v2/core/services/relay" + "github.com/smartcontractkit/chainlink/v2/core/web/presenters" +) + +func NewCosmosChainsController(app chainlink.Application) ChainsController { + return newChainsController[presenters.CosmosChainResource]( + relay.NetworkCosmos, + app.GetRelayers().List(chainlink.FilterRelayersByType(relay.NetworkCosmos)), + ErrCosmosNotEnabled, + presenters.NewCosmosChainResource, + app.GetLogger(), + app.GetAuditLogger()) +} diff --git a/core/web/cosmos_chains_controller_test.go b/core/web/cosmos_chains_controller_test.go new file mode 100644 index 00000000000..2d5eb42515a --- /dev/null +++ b/core/web/cosmos_chains_controller_test.go @@ -0,0 +1,193 @@ +package web_test + +import ( + "fmt" + "net/http" + "testing" + + "github.com/manyminds/api2go/jsonapi" + "github.com/shopspring/decimal" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + "github.com/smartcontractkit/chainlink-common/pkg/types" + coscfg "github.com/smartcontractkit/chainlink-cosmos/pkg/cosmos/config" + + "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" + "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" + "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest" + "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/cosmostest" + "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" + "github.com/smartcontractkit/chainlink/v2/core/web" + "github.com/smartcontractkit/chainlink/v2/core/web/presenters" +) + +func Test_CosmosChainsController_Show(t *testing.T) { + t.Parallel() + + const validId = "Chainlink-12" + + testCases := []struct { + name string + inputId string + wantStatusCode int + want func(t *testing.T, app *cltest.TestApplication) *types.ChainStatus + }{ + { + inputId: validId, + name: "success", + want: func(t *testing.T, app *cltest.TestApplication) *types.ChainStatus { + return &types.ChainStatus{ + ID: validId, + Enabled: true, + Config: `ChainID = 'Chainlink-12' +Enabled = true +Bech32Prefix = 'wasm' +BlockRate = '6s' +BlocksUntilTxTimeout = 30 +ConfirmPollPeriod = '1s' +FallbackGasPrice = '9.999' +GasToken = 'ucosm' +GasLimitMultiplier = '1.55555' +MaxMsgsPerBatch = 100 +OCR2CachePollPeriod = '4s' +OCR2CacheTTL = '1m0s' +TxMsgTimeout = '10m0s' +Nodes = [] +`, + } + }, + wantStatusCode: http.StatusOK, + }, + { + inputId: "234", + name: "not found", + want: func(t *testing.T, app *cltest.TestApplication) *types.ChainStatus { + return nil + }, + wantStatusCode: http.StatusBadRequest, + }, + } + + for _, testCase := range testCases { + tc := testCase + + t.Run(tc.name, func(t *testing.T) { + t.Parallel() + + controller := setupCosmosChainsControllerTestV2(t, &coscfg.TOMLConfig{ + ChainID: ptr(validId), + Enabled: ptr(true), + Chain: coscfg.Chain{ + FallbackGasPrice: ptr(decimal.RequireFromString("9.999")), + GasLimitMultiplier: ptr(decimal.RequireFromString("1.55555")), + }}) + + wantedResult := tc.want(t, controller.app) + resp, cleanup := controller.client.Get( + fmt.Sprintf("/v2/chains/cosmos/%s", tc.inputId), + ) + t.Cleanup(cleanup) + require.Equal(t, tc.wantStatusCode, resp.StatusCode) + + if wantedResult != nil { + resource1 := presenters.CosmosChainResource{} + err := web.ParseJSONAPIResponse(cltest.ParseResponseBody(t, resp), &resource1) + require.NoError(t, err) + + assert.Equal(t, wantedResult.ID, resource1.ID) + assert.Equal(t, wantedResult.Config, resource1.Config) + } + }) + } +} + +func Test_CosmosChainsController_Index(t *testing.T) { + t.Parallel() + + chainA := &coscfg.TOMLConfig{ + ChainID: ptr("a" + cosmostest.RandomChainID()), + Enabled: ptr(true), + Chain: coscfg.Chain{ + FallbackGasPrice: ptr(decimal.RequireFromString("9.999")), + }, + } + + chainB := &coscfg.TOMLConfig{ + ChainID: ptr("b" + cosmostest.RandomChainID()), + Enabled: ptr(true), + Chain: coscfg.Chain{ + GasLimitMultiplier: ptr(decimal.RequireFromString("1.55555")), + }, + } + controller := setupCosmosChainsControllerTestV2(t, chainA, chainB) + + badResp, cleanup := controller.client.Get("/v2/chains/cosmos?size=asd") + t.Cleanup(cleanup) + require.Equal(t, http.StatusUnprocessableEntity, badResp.StatusCode) + + resp, cleanup := controller.client.Get("/v2/chains/cosmos?size=1") + t.Cleanup(cleanup) + require.Equal(t, http.StatusOK, resp.StatusCode) + + body := cltest.ParseResponseBody(t, resp) + + metaCount, err := cltest.ParseJSONAPIResponseMetaCount(body) + require.NoError(t, err) + require.Equal(t, 2, metaCount) + + var links jsonapi.Links + + var chains []presenters.CosmosChainResource + err = web.ParsePaginatedResponse(body, &chains, &links) + assert.NoError(t, err) + assert.NotEmpty(t, links["next"].Href) + assert.Empty(t, links["prev"].Href) + + assert.Len(t, links, 1) + assert.Equal(t, *chainA.ChainID, chains[0].ID) + tomlA, err := chainA.TOMLString() + require.NoError(t, err) + assert.Equal(t, tomlA, chains[0].Config) + + resp, cleanup = controller.client.Get(links["next"].Href) + t.Cleanup(cleanup) + require.Equal(t, http.StatusOK, resp.StatusCode) + + chains = []presenters.CosmosChainResource{} + err = web.ParsePaginatedResponse(cltest.ParseResponseBody(t, resp), &chains, &links) + assert.NoError(t, err) + assert.Empty(t, links["next"].Href) + assert.NotEmpty(t, links["prev"].Href) + + assert.Len(t, links, 1) + assert.Equal(t, *chainB.ChainID, chains[0].ID) + tomlB, err := chainB.TOMLString() + require.NoError(t, err) + assert.Equal(t, tomlB, chains[0].Config) +} + +type TestCosmosChainsController struct { + app *cltest.TestApplication + client cltest.HTTPClientCleaner +} + +func setupCosmosChainsControllerTestV2(t *testing.T, cfgs ...*coscfg.TOMLConfig) *TestCosmosChainsController { + for i := range cfgs { + cfgs[i].SetDefaults() + } + cfg := configtest.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) { + c.Cosmos = cfgs + c.EVM = nil + }) + app := cltest.NewApplicationWithConfig(t, cfg) + ctx := testutils.Context(t) + require.NoError(t, app.Start(ctx)) + + client := app.NewHTTPClient(nil) + + return &TestCosmosChainsController{ + app: app, + client: client, + } +} diff --git a/core/web/cosmos_nodes_controller.go b/core/web/cosmos_nodes_controller.go new file mode 100644 index 00000000000..f3a226721ca --- /dev/null +++ b/core/web/cosmos_nodes_controller.go @@ -0,0 +1,18 @@ +package web + +import ( + "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" + "github.com/smartcontractkit/chainlink/v2/core/services/relay" + "github.com/smartcontractkit/chainlink/v2/core/web/presenters" +) + +// ErrCosmosNotEnabled is returned when COSMOS_ENABLED is not true. +var ErrCosmosNotEnabled = errChainDisabled{name: "Cosmos", tomlKey: "Cosmos.Enabled"} + +func NewCosmosNodesController(app chainlink.Application) NodesController { + scopedNodeStatuser := NewNetworkScopedNodeStatuser(app.GetRelayers(), relay.NetworkCosmos) + + return newNodesController[presenters.CosmosNodeResource]( + scopedNodeStatuser, ErrCosmosNotEnabled, presenters.NewCosmosNodeResource, app.GetAuditLogger(), + ) +} diff --git a/core/web/cosmos_transfer_controller.go b/core/web/cosmos_transfer_controller.go index f80dda005eb..ab3d8c20f30 100644 --- a/core/web/cosmos_transfer_controller.go +++ b/core/web/cosmos_transfer_controller.go @@ -27,13 +27,11 @@ type CosmosTransfersController struct { App chainlink.Application } -var ErrCosmosNotEnabled = errChainDisabled{name: "Cosmos", tomlKey: "Cosmos.Enabled"} - // Create sends native coins from the Chainlink's account to a specified address. func (tc *CosmosTransfersController) Create(c *gin.Context) { relayers := tc.App.GetRelayers().List(chainlink.FilterRelayersByType(relay.NetworkCosmos)) if relayers == nil { - jsonAPIError(c, http.StatusBadRequest, ErrCosmosNotEnabled) + jsonAPIError(c, http.StatusBadRequest, ErrSolanaNotEnabled) return } diff --git a/core/web/evm_chains_controller.go b/core/web/evm_chains_controller.go new file mode 100644 index 00000000000..9c887fa409c --- /dev/null +++ b/core/web/evm_chains_controller.go @@ -0,0 +1,19 @@ +package web + +import ( + "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" + "github.com/smartcontractkit/chainlink/v2/core/services/relay" + "github.com/smartcontractkit/chainlink/v2/core/web/presenters" +) + +var ErrEVMNotEnabled = errChainDisabled{name: "EVM", tomlKey: "EVM.Enabled"} + +func NewEVMChainsController(app chainlink.Application) ChainsController { + return newChainsController[presenters.EVMChainResource]( + relay.NetworkEVM, + app.GetRelayers().List(chainlink.FilterRelayersByType(relay.NetworkEVM)), + ErrEVMNotEnabled, + presenters.NewEVMChainResource, + app.GetLogger(), + app.GetAuditLogger()) +} diff --git a/core/web/evm_chains_controller_test.go b/core/web/evm_chains_controller_test.go new file mode 100644 index 00000000000..ab8bf35e6cb --- /dev/null +++ b/core/web/evm_chains_controller_test.go @@ -0,0 +1,215 @@ +package web_test + +import ( + "fmt" + "math/big" + "net/http" + "sort" + "testing" + + "github.com/manyminds/api2go/jsonapi" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + evmcfg "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/toml" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" + ubig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" + "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" + "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" + "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest" + "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" + "github.com/smartcontractkit/chainlink/v2/core/web" + "github.com/smartcontractkit/chainlink/v2/core/web/presenters" +) + +func Test_EVMChainsController_Show(t *testing.T) { + t.Parallel() + + validId := ubig.New(testutils.NewRandomEVMChainID()) + + testCases := []struct { + name string + inputId string + wantStatusCode int + want *evmcfg.EVMConfig + }{ + { + inputId: validId.String(), + name: "success", + want: &evmcfg.EVMConfig{ + ChainID: validId, + Enabled: ptr(true), + Chain: evmcfg.Defaults(nil, &evmcfg.Chain{ + GasEstimator: evmcfg.GasEstimator{ + EIP1559DynamicFees: ptr(true), + BlockHistory: evmcfg.BlockHistoryEstimator{ + BlockHistorySize: ptr[uint16](50), + }, + }, + RPCBlockQueryDelay: ptr[uint16](23), + MinIncomingConfirmations: ptr[uint32](12), + LinkContractAddress: ptr(types.EIP55AddressFromAddress(testutils.NewAddress())), + }), + }, + wantStatusCode: http.StatusOK, + }, + { + inputId: "invalidid", + name: "invalid id", + want: nil, + wantStatusCode: http.StatusBadRequest, + }, + { + inputId: "234", + name: "not found", + want: nil, + wantStatusCode: http.StatusBadRequest, + }, + } + + for _, testCase := range testCases { + tc := testCase + + t.Run(tc.name, func(t *testing.T) { + t.Parallel() + + controller := setupEVMChainsControllerTest(t, configtest.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) { + if tc.want != nil { + c.EVM = evmcfg.EVMConfigs{tc.want} + } + })) + + wantedResult := tc.want + resp, cleanup := controller.client.Get( + fmt.Sprintf("/v2/chains/evm/%s", tc.inputId), + ) + t.Cleanup(cleanup) + require.Equal(t, tc.wantStatusCode, resp.StatusCode) + + if wantedResult != nil { + resource1 := presenters.EVMChainResource{} + err := web.ParseJSONAPIResponse(cltest.ParseResponseBody(t, resp), &resource1) + require.NoError(t, err) + + assert.Equal(t, resource1.ID, wantedResult.ChainID.String()) + toml, err := wantedResult.TOMLString() + require.NoError(t, err) + assert.Equal(t, toml, resource1.Config) + } + }) + } +} + +func Test_EVMChainsController_Index(t *testing.T) { + t.Parallel() + + // sort test chain ids to make expected comparison easy + chainIDs := []*big.Int{testutils.NewRandomEVMChainID(), testutils.NewRandomEVMChainID(), testutils.NewRandomEVMChainID()} + sort.Slice(chainIDs, func(i, j int) bool { + return chainIDs[i].String() < chainIDs[j].String() + }) + + configuredChains := evmcfg.EVMConfigs{ + {ChainID: ubig.New(chainIDs[0]), Chain: evmcfg.Defaults(nil)}, + { + ChainID: ubig.New(chainIDs[1]), + Chain: evmcfg.Defaults(nil, &evmcfg.Chain{ + RPCBlockQueryDelay: ptr[uint16](13), + GasEstimator: evmcfg.GasEstimator{ + EIP1559DynamicFees: ptr(true), + BlockHistory: evmcfg.BlockHistoryEstimator{ + BlockHistorySize: ptr[uint16](1), + }, + }, + MinIncomingConfirmations: ptr[uint32](120), + }), + }, + { + ChainID: ubig.New(chainIDs[2]), + Chain: evmcfg.Defaults(nil, &evmcfg.Chain{ + RPCBlockQueryDelay: ptr[uint16](5), + GasEstimator: evmcfg.GasEstimator{ + EIP1559DynamicFees: ptr(false), + BlockHistory: evmcfg.BlockHistoryEstimator{ + BlockHistorySize: ptr[uint16](2), + }, + }, + MinIncomingConfirmations: ptr[uint32](30), + }), + }, + } + + assert.Len(t, configuredChains, 3) + controller := setupEVMChainsControllerTest(t, configtest.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) { + c.EVM = append(c.EVM, configuredChains...) + })) + + badResp, cleanup := controller.client.Get("/v2/chains/evm?size=asd") + t.Cleanup(cleanup) + require.Equal(t, http.StatusUnprocessableEntity, badResp.StatusCode) + + resp, cleanup := controller.client.Get("/v2/chains/evm?size=3") + t.Cleanup(cleanup) + require.Equal(t, http.StatusOK, resp.StatusCode) + + body := cltest.ParseResponseBody(t, resp) + + metaCount, err := cltest.ParseJSONAPIResponseMetaCount(body) + require.NoError(t, err) + require.Equal(t, 1+len(configuredChains), metaCount) + + var links jsonapi.Links + + var gotChains []presenters.EVMChainResource + err = web.ParsePaginatedResponse(body, &gotChains, &links) + assert.NoError(t, err) + assert.NotEmpty(t, links["next"].Href) + assert.Empty(t, links["prev"].Href) + + assert.Len(t, links, 1) + // the difference in index value here seems to be due to the fact + // that cltest always has a default EVM chain, which is the off-by-one + // in the indices + assert.Equal(t, gotChains[2].ID, configuredChains[1].ChainID.String()) + toml, err := configuredChains[1].TOMLString() + require.NoError(t, err) + assert.Equal(t, toml, gotChains[2].Config) + + resp, cleanup = controller.client.Get(links["next"].Href) + t.Cleanup(cleanup) + require.Equal(t, http.StatusOK, resp.StatusCode) + + gotChains = []presenters.EVMChainResource{} + err = web.ParsePaginatedResponse(cltest.ParseResponseBody(t, resp), &gotChains, &links) + assert.NoError(t, err) + assert.Empty(t, links["next"].Href) + assert.NotEmpty(t, links["prev"].Href) + + assert.Len(t, links, 1) + assert.Equal(t, gotChains[0].ID, configuredChains[2].ChainID.String()) + toml, err = configuredChains[2].TOMLString() + require.NoError(t, err) + assert.Equal(t, toml, gotChains[0].Config) +} + +type TestEVMChainsController struct { + app *cltest.TestApplication + client cltest.HTTPClientCleaner +} + +func setupEVMChainsControllerTest(t *testing.T, cfg chainlink.GeneralConfig) *TestEVMChainsController { + // Using this instead of `NewApplicationEVMDisabled` since we need the chain set to be loaded in the app + // for the sake of the API endpoints to work properly + app := cltest.NewApplicationWithConfig(t, cfg) + ctx := testutils.Context(t) + require.NoError(t, app.Start(ctx)) + + client := app.NewHTTPClient(nil) + + return &TestEVMChainsController{ + app: app, + client: client, + } +} + +func ptr[T any](t T) *T { return &t } diff --git a/core/web/evm_nodes_controller.go b/core/web/evm_nodes_controller.go new file mode 100644 index 00000000000..8872f51d7e3 --- /dev/null +++ b/core/web/evm_nodes_controller.go @@ -0,0 +1,14 @@ +package web + +import ( + "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" + "github.com/smartcontractkit/chainlink/v2/core/services/relay" + "github.com/smartcontractkit/chainlink/v2/core/web/presenters" +) + +func NewEVMNodesController(app chainlink.Application) NodesController { + scopedNodeStatuser := NewNetworkScopedNodeStatuser(app.GetRelayers(), relay.NetworkEVM) + + return newNodesController[presenters.EVMNodeResource]( + scopedNodeStatuser, ErrEVMNotEnabled, presenters.NewEVMNodeResource, app.GetAuditLogger()) +} diff --git a/core/web/middleware.go b/core/web/middleware.go index aacb912dca7..6e9378e618f 100644 --- a/core/web/middleware.go +++ b/core/web/middleware.go @@ -2,6 +2,7 @@ package web import ( "embed" + "errors" "fmt" "io/fs" "net/http" @@ -39,7 +40,7 @@ const ( // ServeFileSystem wraps a http.FileSystem with an additional file existence check type ServeFileSystem interface { http.FileSystem - Exists(prefix string, path string) (bool, error) + Exists(prefix string, path string) bool } // EmbedFileSystem implements the ServeFileSystem interface using an embed.FS @@ -59,19 +60,23 @@ func NewEmbedFileSystem(efs embed.FS, pathPrefix string) ServeFileSystem { } // Exists implements the ServeFileSystem interface. -func (e *EmbedFileSystem) Exists(prefix string, filepath string) (found bool, err error) { +func (e *EmbedFileSystem) Exists(prefix string, filepath string) bool { + found := false if p := path.Base(strings.TrimPrefix(filepath, prefix)); len(p) < len(filepath) { - err = fs.WalkDir(e.FS, ".", func(fpath string, d fs.DirEntry, err error) error { + //nolint:errcheck + fs.WalkDir(e.FS, ".", func(fpath string, d fs.DirEntry, err error) error { fileName := path.Base(fpath) if fileName == p { found = true - return fs.SkipAll + // Return an error so that we terminate the search early. + // Otherwise, the search will continue for the rest of the file tree. + return errors.New("file found") } return nil }) } - return + return found } // Open implements the http.FileSystem interface. @@ -142,9 +147,7 @@ func (f *gzipFileHandler) findBestFile(w http.ResponseWriter, r *http.Request, f ext := extensionForEncoding(posenc) fname := fpath + ext - if ok, err := f.root.Exists("/", fname); err != nil { - return nil, nil, err - } else if ok { + if f.root.Exists("/", fname) { available = append(available, posenc) } } @@ -227,10 +230,7 @@ func ServeGzippedAssets(urlPrefix string, fs ServeFileSystem, lggr logger.Logger fileserver = http.StripPrefix(urlPrefix, fileserver) } return func(c *gin.Context) { - if ok, err := fs.Exists(urlPrefix, c.Request.URL.Path); err != nil { - lggr.Errorw("Failed to search for file", "err", err) - c.AbortWithStatus(http.StatusInternalServerError) - } else if ok { + if fs.Exists(urlPrefix, c.Request.URL.Path) { fileserver.ServeHTTP(c.Writer, c.Request) c.Abort() } else { diff --git a/core/web/nodes_controller.go b/core/web/nodes_controller.go index ee40de9885c..0e43316629a 100644 --- a/core/web/nodes_controller.go +++ b/core/web/nodes_controller.go @@ -2,6 +2,7 @@ package web import ( "context" + "net/http" "github.com/gin-gonic/gin" "github.com/manyminds/api2go/jsonapi" @@ -10,7 +11,6 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/logger/audit" "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" - "github.com/smartcontractkit/chainlink/v2/core/web/presenters" ) type NodesController interface { @@ -36,38 +36,42 @@ func (n *NetworkScopedNodeStatuser) NodeStatuses(ctx context.Context, offset, li } type nodesController[R jsonapi.EntityNamer] struct { - relayers chainlink.RelayerChainInteroperators - newResource func(status types.NodeStatus) R - auditLogger audit.AuditLogger + nodeSet *NetworkScopedNodeStatuser + errNotEnabled error + newResource func(status types.NodeStatus) R + auditLogger audit.AuditLogger } -func NewNodesController( - relayers chainlink.RelayerChainInteroperators, auditLogger audit.AuditLogger, +func newNodesController[R jsonapi.EntityNamer]( + nodeSet *NetworkScopedNodeStatuser, + errNotEnabled error, + newResource func(status types.NodeStatus) R, + auditLogger audit.AuditLogger, ) NodesController { - return &nodesController[presenters.NodeResource]{ - relayers: relayers, - newResource: presenters.NewNodeResource, - auditLogger: auditLogger, + return &nodesController[R]{ + nodeSet: nodeSet, + errNotEnabled: errNotEnabled, + newResource: newResource, + auditLogger: auditLogger, } } func (n *nodesController[R]) Index(c *gin.Context, size, page, offset int) { + if n.nodeSet == nil { + jsonAPIError(c, http.StatusBadRequest, n.errNotEnabled) + return + } + id := c.Param("ID") - network := c.Param("network") var nodes []types.NodeStatus var count int var err error - relayers := n.relayers - if network != "" { - relayers = relayers.List(chainlink.FilterRelayersByType(network)) - } - ctx := c.Request.Context() if id == "" { // fetch all nodes - nodes, count, err = relayers.NodeStatuses(ctx, offset, size) + nodes, count, err = n.nodeSet.NodeStatuses(ctx, offset, size) } else { // fetch nodes for chain ID // backward compatibility @@ -75,9 +79,9 @@ func (n *nodesController[R]) Index(c *gin.Context, size, page, offset int) { err = rid.UnmarshalString(id) if err != nil { rid.ChainID = id - rid.Network = network + rid.Network = n.nodeSet.network } - nodes, count, err = relayers.NodeStatuses(ctx, offset, size, rid) + nodes, count, err = n.nodeSet.NodeStatuses(ctx, offset, size, rid) } var resources []R diff --git a/core/web/presenters/chain.go b/core/web/presenters/chain.go index 280f7a7f8d4..99cf9a1d252 100644 --- a/core/web/presenters/chain.go +++ b/core/web/presenters/chain.go @@ -1,32 +1,11 @@ package presenters -import ( - "github.com/smartcontractkit/chainlink-common/pkg/types" - commonTypes "github.com/smartcontractkit/chainlink/v2/common/types" -) - type ChainResource struct { JAID - Network string `json:"network"` Enabled bool `json:"enabled"` Config string `json:"config"` // TOML } -// GetName implements the api2go EntityNamer interface -func (r ChainResource) GetName() string { - return "chain" -} - -// NewChainResource returns a new ChainResource for chain. -func NewChainResource(chain commonTypes.ChainStatusWithID) ChainResource { - return ChainResource{ - JAID: NewJAID(chain.RelayID.ChainID), - Network: chain.RelayID.Network, - Config: chain.Config, - Enabled: chain.Enabled, - } -} - type NodeResource struct { JAID ChainID string `json:"chainID"` @@ -34,19 +13,3 @@ type NodeResource struct { Config string `json:"config"` // TOML State string `json:"state"` } - -// NewNodeResource returns a new NodeResource for node. -func NewNodeResource(node types.NodeStatus) NodeResource { - return NodeResource{ - JAID: NewPrefixedJAID(node.Name, node.ChainID), - ChainID: node.ChainID, - Name: node.Name, - State: node.State, - Config: node.Config, - } -} - -// GetName implements the api2go EntityNamer interface -func (r NodeResource) GetName() string { - return "node" -} diff --git a/core/web/presenters/cosmos_chain.go b/core/web/presenters/cosmos_chain.go new file mode 100644 index 00000000000..c2bc4b52b61 --- /dev/null +++ b/core/web/presenters/cosmos_chain.go @@ -0,0 +1,45 @@ +package presenters + +import ( + "github.com/smartcontractkit/chainlink-common/pkg/types" +) + +// CosmosChainResource is an Cosmos chain JSONAPI resource. +type CosmosChainResource struct { + ChainResource +} + +// GetName implements the api2go EntityNamer interface +func (r CosmosChainResource) GetName() string { + return "cosmos_chain" +} + +// NewCosmosChainResource returns a new CosmosChainResource for chain. +func NewCosmosChainResource(chain types.ChainStatus) CosmosChainResource { + return CosmosChainResource{ChainResource{ + JAID: NewJAID(chain.ID), + Config: chain.Config, + Enabled: chain.Enabled, + }} +} + +// CosmosNodeResource is a Cosmos node JSONAPI resource. +type CosmosNodeResource struct { + NodeResource +} + +// GetName implements the api2go EntityNamer interface +func (r CosmosNodeResource) GetName() string { + return "cosmos_node" +} + +// NewCosmosNodeResource returns a new CosmosNodeResource for node. +func NewCosmosNodeResource(node types.NodeStatus) CosmosNodeResource { + return CosmosNodeResource{NodeResource{ + JAID: NewPrefixedJAID(node.Name, node.ChainID), + ChainID: node.ChainID, + Name: node.Name, + State: node.State, + Config: node.Config, + }} +} diff --git a/core/web/presenters/evm_chain.go b/core/web/presenters/evm_chain.go new file mode 100644 index 00000000000..adf399d4b01 --- /dev/null +++ b/core/web/presenters/evm_chain.go @@ -0,0 +1,43 @@ +package presenters + +import "github.com/smartcontractkit/chainlink-common/pkg/types" + +// EVMChainResource is an EVM chain JSONAPI resource. +type EVMChainResource struct { + ChainResource +} + +// GetName implements the api2go EntityNamer interface +func (r EVMChainResource) GetName() string { + return "evm_chain" +} + +// NewEVMChainResource returns a new EVMChainResource for chain. +func NewEVMChainResource(chain types.ChainStatus) EVMChainResource { + return EVMChainResource{ChainResource{ + JAID: NewJAID(chain.ID), + Config: chain.Config, + Enabled: chain.Enabled, + }} +} + +// EVMNodeResource is an EVM node JSONAPI resource. +type EVMNodeResource struct { + NodeResource +} + +// GetName implements the api2go EntityNamer interface +func (r EVMNodeResource) GetName() string { + return "evm_node" +} + +// NewEVMNodeResource returns a new EVMNodeResource for node. +func NewEVMNodeResource(node types.NodeStatus) EVMNodeResource { + return EVMNodeResource{NodeResource{ + JAID: NewPrefixedJAID(node.Name, node.ChainID), + ChainID: node.ChainID, + Name: node.Name, + State: node.State, + Config: node.Config, + }} +} diff --git a/core/web/presenters/job.go b/core/web/presenters/job.go index 8b01eeb5005..bb518650516 100644 --- a/core/web/presenters/job.go +++ b/core/web/presenters/job.go @@ -176,7 +176,6 @@ type OffChainReporting2Spec struct { BlockchainTimeout models.Interval `json:"blockchainTimeout"` ContractConfigTrackerPollInterval models.Interval `json:"contractConfigTrackerPollInterval"` ContractConfigConfirmations uint16 `json:"contractConfigConfirmations"` - OnchainSigningStrategy map[string]interface{} `json:"onchainSigningStrategy"` CreatedAt time.Time `json:"createdAt"` UpdatedAt time.Time `json:"updatedAt"` CollectTelemetry bool `json:"collectTelemetry"` @@ -195,7 +194,6 @@ func NewOffChainReporting2Spec(spec *job.OCR2OracleSpec) *OffChainReporting2Spec BlockchainTimeout: spec.BlockchainTimeout, ContractConfigTrackerPollInterval: spec.ContractConfigTrackerPollInterval, ContractConfigConfirmations: spec.ContractConfigConfirmations, - OnchainSigningStrategy: spec.OnchainSigningStrategy, CreatedAt: spec.CreatedAt, UpdatedAt: spec.UpdatedAt, CollectTelemetry: spec.CaptureEATelemetry, diff --git a/core/web/presenters/jsonapi.go b/core/web/presenters/jsonapi.go index fe3aee8393f..d14e24a7455 100644 --- a/core/web/presenters/jsonapi.go +++ b/core/web/presenters/jsonapi.go @@ -16,8 +16,8 @@ func NewJAID(id string) JAID { } // NewPrefixedJAID prefixes JAID with chain id in %s/%s format. -func NewPrefixedJAID(id string, prefix string) JAID { - return JAID{ID: fmt.Sprintf("%s/%s", prefix, id)} +func NewPrefixedJAID(id string, chainID string) JAID { + return JAID{ID: fmt.Sprintf("%s/%s", chainID, id)} } // NewJAIDInt32 converts an int32 into a JAID diff --git a/core/web/presenters/node_test.go b/core/web/presenters/node_test.go index d2db83009d9..34210a52166 100644 --- a/core/web/presenters/node_test.go +++ b/core/web/presenters/node_test.go @@ -13,6 +13,7 @@ import ( func TestNodeResource(t *testing.T) { var nodeResource NodeResource + var r interface{} state := "test" cfg := "cfg" testCases := []string{"solana", "cosmos", "starknet"} @@ -20,25 +21,62 @@ func TestNodeResource(t *testing.T) { chainID := fmt.Sprintf("%s chain ID", tc) nodeName := fmt.Sprintf("%s_node", tc) - nodeResource = NewNodeResource(types.NodeStatus{ - ChainID: chainID, - Name: nodeName, - Config: cfg, - State: state, - }) - + switch tc { + case "evm": + evmNodeResource := NewEVMNodeResource( + types.NodeStatus{ + ChainID: chainID, + Name: nodeName, + Config: cfg, + State: state, + }) + r = evmNodeResource + nodeResource = evmNodeResource.NodeResource + case "solana": + solanaNodeResource := NewSolanaNodeResource( + types.NodeStatus{ + ChainID: chainID, + Name: nodeName, + Config: cfg, + State: state, + }) + r = solanaNodeResource + nodeResource = solanaNodeResource.NodeResource + case "cosmos": + cosmosNodeResource := NewCosmosNodeResource( + types.NodeStatus{ + ChainID: chainID, + Name: nodeName, + Config: cfg, + State: state, + }) + r = cosmosNodeResource + nodeResource = cosmosNodeResource.NodeResource + case "starknet": + starknetNodeResource := NewStarkNetNodeResource( + types.NodeStatus{ + ChainID: chainID, + Name: nodeName, + Config: cfg, + State: state, + }) + r = starknetNodeResource + nodeResource = starknetNodeResource.NodeResource + default: + t.Fail() + } assert.Equal(t, chainID, nodeResource.ChainID) assert.Equal(t, nodeName, nodeResource.Name) assert.Equal(t, cfg, nodeResource.Config) assert.Equal(t, state, nodeResource.State) - b, err := jsonapi.Marshal(nodeResource) + b, err := jsonapi.Marshal(r) require.NoError(t, err) expected := fmt.Sprintf(` { "data":{ - "type":"node", + "type":"%s_node", "id":"%s/%s", "attributes":{ "chainID":"%s", @@ -48,7 +86,7 @@ func TestNodeResource(t *testing.T) { } } } - `, chainID, nodeName, chainID, nodeName, cfg, state) + `, tc, chainID, nodeName, chainID, nodeName, cfg, state) assert.JSONEq(t, expected, string(b)) } } diff --git a/core/web/presenters/p2p_key_test.go b/core/web/presenters/p2p_key_test.go index 2d6d307f207..4e7b4e954fd 100644 --- a/core/web/presenters/p2p_key_test.go +++ b/core/web/presenters/p2p_key_test.go @@ -2,18 +2,17 @@ package presenters import ( "fmt" - "math/big" "testing" "github.com/manyminds/api2go/jsonapi" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/p2pkey" + "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/keystest" ) func TestP2PKeyResource(t *testing.T) { - key := p2pkey.MustNewV2XXXTestingOnly(big.NewInt(1)) + key := keystest.NewP2PKeyV2(t) peerID := key.PeerID() peerIDStr := peerID.String() diff --git a/core/web/presenters/solana_chain.go b/core/web/presenters/solana_chain.go new file mode 100644 index 00000000000..798d98124a5 --- /dev/null +++ b/core/web/presenters/solana_chain.go @@ -0,0 +1,45 @@ +package presenters + +import ( + "github.com/smartcontractkit/chainlink-common/pkg/types" +) + +// SolanaChainResource is an Solana chain JSONAPI resource. +type SolanaChainResource struct { + ChainResource +} + +// GetName implements the api2go EntityNamer interface +func (r SolanaChainResource) GetName() string { + return "solana_chain" +} + +// NewSolanaChainResource returns a new SolanaChainResource for chain. +func NewSolanaChainResource(chain types.ChainStatus) SolanaChainResource { + return SolanaChainResource{ChainResource{ + JAID: NewJAID(chain.ID), + Config: chain.Config, + Enabled: chain.Enabled, + }} +} + +// SolanaNodeResource is a Solana node JSONAPI resource. +type SolanaNodeResource struct { + NodeResource +} + +// GetName implements the api2go EntityNamer interface +func (r SolanaNodeResource) GetName() string { + return "solana_node" +} + +// NewSolanaNodeResource returns a new SolanaNodeResource for node. +func NewSolanaNodeResource(node types.NodeStatus) SolanaNodeResource { + return SolanaNodeResource{NodeResource{ + JAID: NewPrefixedJAID(node.Name, node.ChainID), + ChainID: node.ChainID, + Name: node.Name, + State: node.State, + Config: node.Config, + }} +} diff --git a/core/web/presenters/starknet_chain.go b/core/web/presenters/starknet_chain.go new file mode 100644 index 00000000000..addf798fe9f --- /dev/null +++ b/core/web/presenters/starknet_chain.go @@ -0,0 +1,45 @@ +package presenters + +import ( + "github.com/smartcontractkit/chainlink-common/pkg/types" +) + +// StarkNetChainResource is an StarkNet chain JSONAPI resource. +type StarkNetChainResource struct { + ChainResource +} + +// GetName implements the api2go EntityNamer interface +func (r StarkNetChainResource) GetName() string { + return "starknet_chain" +} + +// NewStarkNetChainResource returns a new StarkNetChainResource for chain. +func NewStarkNetChainResource(chain types.ChainStatus) StarkNetChainResource { + return StarkNetChainResource{ChainResource{ + JAID: NewJAID(chain.ID), + Config: chain.Config, + Enabled: chain.Enabled, + }} +} + +// StarkNetNodeResource is a StarkNet node JSONAPI resource. +type StarkNetNodeResource struct { + NodeResource +} + +// GetName implements the api2go EntityNamer interface +func (r StarkNetNodeResource) GetName() string { + return "starknet_node" +} + +// NewStarkNetNodeResource returns a new StarkNetNodeResource for node. +func NewStarkNetNodeResource(node types.NodeStatus) StarkNetNodeResource { + return StarkNetNodeResource{NodeResource{ + JAID: NewPrefixedJAID(node.Name, node.ChainID), + ChainID: node.ChainID, + Name: node.Name, + State: node.State, + Config: node.Config, + }} +} diff --git a/core/web/resolver/spec.go b/core/web/resolver/spec.go index 4a6989ae2dd..ce23df49264 100644 --- a/core/web/resolver/spec.go +++ b/core/web/resolver/spec.go @@ -1,7 +1,7 @@ package resolver import ( - "strconv" + "fmt" "github.com/graph-gophers/graphql-go" @@ -139,13 +139,8 @@ func (r *SpecResolver) ToStreamSpec() (*StreamSpecResolver, bool) { if r.j.Type != job.Stream { return nil, false } - res := &StreamSpecResolver{} - if r.j.StreamID != nil { - sid := strconv.FormatUint(uint64(*r.j.StreamID), 10) - res.streamID = &sid - } - return res, true + return &StreamSpecResolver{streamID: fmt.Sprintf("%d", r.j.StreamID)}, true } type CronSpecResolver struct { @@ -992,11 +987,6 @@ func (r *BootstrapSpecResolver) ContractConfigConfirmations() *int32 { return &confirmations } -// RelayConfig resolves the spec's onchain signing strategy config -func (r *OCR2SpecResolver) OnchainSigningStrategy() gqlscalar.Map { - return gqlscalar.Map(r.spec.OnchainSigningStrategy) -} - // CreatedAt resolves the spec's created at timestamp. func (r *BootstrapSpecResolver) CreatedAt() graphql.Time { return graphql.Time{Time: r.spec.CreatedAt} @@ -1067,9 +1057,9 @@ func (r *StandardCapabilitiesSpecResolver) Config() *string { } type StreamSpecResolver struct { - streamID *string + streamID string } -func (r *StreamSpecResolver) StreamID() *string { +func (r *StreamSpecResolver) StreamID() string { return r.streamID } diff --git a/core/web/resolver/spec_test.go b/core/web/resolver/spec_test.go index 61a29d4f54a..69d6a56509c 100644 --- a/core/web/resolver/spec_test.go +++ b/core/web/resolver/spec_test.go @@ -2,7 +2,6 @@ package resolver import ( "context" - "fmt" "testing" "time" @@ -472,12 +471,6 @@ func TestResolver_OCR2Spec(t *testing.T) { pluginConfig := map[string]interface{}{ "juelsPerFeeCoinSource": 100000000, } - onchainSigningStrategy := map[string]interface{}{ - "strategyName": "multi-chain", - "config": map[string]any{ - "evm": "b3df4d8748b67731a1112e8b45a764941974f5590c93672eebbc4f3504dd10ed", - }, - } require.NoError(t, err) testCases := []GQLTestCase{ @@ -493,7 +486,6 @@ func TestResolver_OCR2Spec(t *testing.T) { ContractID: contractAddress.String(), ContractConfigConfirmations: 1, ContractConfigTrackerPollInterval: models.Interval(1 * time.Minute), - OnchainSigningStrategy: onchainSigningStrategy, CreatedAt: f.Timestamp(), OCRKeyBundleID: null.StringFrom(keyBundleID.String()), MonitoringEndpoint: null.StringFrom("https://monitor.endpoint"), @@ -517,7 +509,6 @@ func TestResolver_OCR2Spec(t *testing.T) { contractID contractConfigConfirmations contractConfigTrackerPollInterval - onchainSigningStrategy createdAt ocrKeyBundleID monitoringEndpoint @@ -542,12 +533,6 @@ func TestResolver_OCR2Spec(t *testing.T) { "contractID": "0x613a38AC1659769640aaE063C651F48E0250454C", "contractConfigConfirmations": 1, "contractConfigTrackerPollInterval": "1m0s", - "onchainSigningStrategy": { - "strategyName": "multi-chain", - "config": { - "evm": "b3df4d8748b67731a1112e8b45a764941974f5590c93672eebbc4f3504dd10ed" - } - }, "createdAt": "2021-01-01T00:00:00Z", "ocrKeyBundleID": "f5bf259689b26f1374efb3c9a9868796953a0f814bb2d39b968d0e61b58620a5", "monitoringEndpoint": "https://monitor.endpoint", @@ -1181,85 +1166,3 @@ func TestResolver_StandardCapabilitiesSpec(t *testing.T) { RunGQLTests(t, testCases) } - -func TestResolver_StreamSpec(t *testing.T) { - var ( - id1 = int32(1) - id2 = int32(2) - streamID = uint32(3) - ) - - testCases := []GQLTestCase{ - { - name: "stream spec with stream ID", - authenticated: true, - before: func(ctx context.Context, f *gqlTestFramework) { - f.App.On("JobORM").Return(f.Mocks.jobORM) - f.Mocks.jobORM.On("FindJobWithoutSpecErrors", mock.Anything, id1).Return(job.Job{ - Type: job.Stream, - StreamID: &streamID, - }, nil) - }, - query: fmt.Sprintf(` - query GetJob { - job(id: "%d") { - ... on Job { - spec { - __typename - ... on StreamSpec { - streamID - } - } - } - } - } - `, id1), - result: fmt.Sprintf(` - { - "job": { - "spec": { - "__typename": "StreamSpec", - "streamID": "%d" - } - } - } - `, streamID), - }, - { - name: "stream spec without stream ID", - authenticated: true, - before: func(ctx context.Context, f *gqlTestFramework) { - f.App.On("JobORM").Return(f.Mocks.jobORM) - f.Mocks.jobORM.On("FindJobWithoutSpecErrors", mock.Anything, id2).Return(job.Job{ - Type: job.Stream, - }, nil) - }, - query: fmt.Sprintf(` - query GetJob { - job(id: "%d") { - ... on Job { - spec { - __typename - ... on StreamSpec { - streamID - } - } - } - } - } - `, id2), - result: ` - { - "job": { - "spec": { - "__typename": "StreamSpec", - "streamID": null - } - } - } - `, - }, - } - - RunGQLTests(t, testCases) -} diff --git a/core/web/resolver/testdata/config-empty-effective.toml b/core/web/resolver/testdata/config-empty-effective.toml index a2052c04a8e..cd51afac5f8 100644 --- a/core/web/resolver/testdata/config-empty-effective.toml +++ b/core/web/resolver/testdata/config-empty-effective.toml @@ -237,7 +237,6 @@ CertFile = '' [Mercury.Transmitter] TransmitQueueMaxSize = 10000 TransmitTimeout = '5s' -TransmitConcurrency = 100 [Capabilities] [Capabilities.Peering] @@ -269,11 +268,6 @@ Address = '' NetworkID = 'evm' ChainID = '1' -[Capabilities.WorkflowRegistry] -Address = '' -NetworkID = 'evm' -ChainID = '1' - [Capabilities.GatewayConnector] ChainIDForNodeKey = '' NodeAddress = '' diff --git a/core/web/resolver/testdata/config-full.toml b/core/web/resolver/testdata/config-full.toml index 1418ae9497e..bfb0dcb9961 100644 --- a/core/web/resolver/testdata/config-full.toml +++ b/core/web/resolver/testdata/config-full.toml @@ -247,7 +247,6 @@ CertFile = '' [Mercury.Transmitter] TransmitQueueMaxSize = 123 TransmitTimeout = '3m54s' -TransmitConcurrency = 456 [Capabilities] [Capabilities.Peering] @@ -279,11 +278,6 @@ Address = '' NetworkID = 'evm' ChainID = '1' -[Capabilities.WorkflowRegistry] -Address = '' -NetworkID = 'evm' -ChainID = '1' - [Capabilities.GatewayConnector] ChainIDForNodeKey = '11155111' NodeAddress = '0x68902d681c28119f9b2531473a417088bf008e59' @@ -337,7 +331,6 @@ FinalizedBlockOffset = 0 NoNewFinalizedHeadsThreshold = '15m0s' [EVM.Transactions] -Enabled = true ForwardersEnabled = true MaxInFlight = 19 MaxQueued = 99 @@ -498,7 +491,6 @@ OCR2CacheTTL = '1h0m0s' TxTimeout = '1h0m0s' TxRetryTimeout = '1m0s' TxConfirmTimeout = '1s' -TxExpirationRebroadcast = false TxRetentionTimeout = '0s' SkipPreflight = true Commitment = 'banana' diff --git a/core/web/resolver/testdata/config-multi-chain-effective.toml b/core/web/resolver/testdata/config-multi-chain-effective.toml index f5de84093a4..074cb82482b 100644 --- a/core/web/resolver/testdata/config-multi-chain-effective.toml +++ b/core/web/resolver/testdata/config-multi-chain-effective.toml @@ -237,7 +237,6 @@ CertFile = '' [Mercury.Transmitter] TransmitQueueMaxSize = 10000 TransmitTimeout = '5s' -TransmitConcurrency = 100 [Capabilities] [Capabilities.Peering] @@ -269,11 +268,6 @@ Address = '' NetworkID = 'evm' ChainID = '1' -[Capabilities.WorkflowRegistry] -Address = '' -NetworkID = 'evm' -ChainID = '1' - [Capabilities.GatewayConnector] ChainIDForNodeKey = '' NodeAddress = '' @@ -320,7 +314,6 @@ FinalizedBlockOffset = 0 NoNewFinalizedHeadsThreshold = '9m0s' [EVM.Transactions] -Enabled = true ForwardersEnabled = false MaxInFlight = 16 MaxQueued = 250 @@ -431,7 +424,6 @@ FinalizedBlockOffset = 0 NoNewFinalizedHeadsThreshold = '0s' [EVM.Transactions] -Enabled = true ForwardersEnabled = false MaxInFlight = 16 MaxQueued = 250 @@ -536,7 +528,6 @@ FinalizedBlockOffset = 0 NoNewFinalizedHeadsThreshold = '6m0s' [EVM.Transactions] -Enabled = true ForwardersEnabled = false MaxInFlight = 16 MaxQueued = 5000 @@ -662,7 +653,6 @@ OCR2CacheTTL = '1m0s' TxTimeout = '1m0s' TxRetryTimeout = '10s' TxConfirmTimeout = '30s' -TxExpirationRebroadcast = false TxRetentionTimeout = '0s' SkipPreflight = true Commitment = 'confirmed' @@ -708,7 +698,6 @@ OCR2CacheTTL = '1m0s' TxTimeout = '1m0s' TxRetryTimeout = '10s' TxConfirmTimeout = '30s' -TxExpirationRebroadcast = false TxRetentionTimeout = '0s' SkipPreflight = true Commitment = 'confirmed' diff --git a/core/web/router.go b/core/web/router.go index c57bf3c8095..6e96b47981b 100644 --- a/core/web/router.go +++ b/core/web/router.go @@ -390,23 +390,36 @@ func v2Routes(app chainlink.Application, r *gin.RouterGroup) { authv2.PATCH("/log", auth.RequiresAdminRole(lgc.Patch)) chains := authv2.Group("chains") - chainController := NewChainsController( - app.GetRelayers(), - app.GetLogger(), - app.GetAuditLogger(), - ) - chains.GET("", paginatedRequest(chainController.Index)) - chains.GET("/:network", paginatedRequest(chainController.Index)) - chains.GET("/:network/:ID", chainController.Show) + for _, chain := range []struct { + path string + cc ChainsController + }{ + {"evm", NewEVMChainsController(app)}, + {"solana", NewSolanaChainsController(app)}, + {"starknet", NewStarkNetChainsController(app)}, + {"cosmos", NewCosmosChainsController(app)}, + } { + chains.GET(chain.path, paginatedRequest(chain.cc.Index)) + chains.GET(chain.path+"/:ID", chain.cc.Show) + } nodes := authv2.Group("nodes") - nodesController := NewNodesController( - app.GetRelayers(), - app.GetAuditLogger(), - ) - nodes.GET("", paginatedRequest(nodesController.Index)) - nodes.GET("/:network", paginatedRequest(nodesController.Index)) - chains.GET("/:network/:ID/nodes", paginatedRequest(nodesController.Index)) + for _, chain := range []struct { + path string + nc NodesController + }{ + {"evm", NewEVMNodesController(app)}, + {"solana", NewSolanaNodesController(app)}, + {"starknet", NewStarkNetNodesController(app)}, + {"cosmos", NewCosmosNodesController(app)}, + } { + if chain.path == "evm" { + // TODO still EVM only . Archive ticket: story/26276/multi-chain-type-ui-node-chain-configuration + nodes.GET("", paginatedRequest(chain.nc.Index)) + } + nodes.GET(chain.path, paginatedRequest(chain.nc.Index)) + chains.GET(chain.path+"/:ID/nodes", paginatedRequest(chain.nc.Index)) + } efc := EVMForwardersController{app} authv2.GET("/nodes/evm/forwarders", paginatedRequest(efc.Index)) diff --git a/core/web/schema/type/spec.graphql b/core/web/schema/type/spec.graphql index 984aad02a5a..db81001543c 100644 --- a/core/web/schema/type/spec.graphql +++ b/core/web/schema/type/spec.graphql @@ -82,7 +82,6 @@ type OCR2Spec { p2pv2Bootstrappers: [String!] relay: String! relayConfig: Map! - onchainSigningStrategy: Map! transmitterID: String pluginType: String! pluginConfig: Map! @@ -183,5 +182,5 @@ type StandardCapabilitiesSpec { } type StreamSpec { - streamID: String + streamID: String! } diff --git a/core/web/solana_chains_controller.go b/core/web/solana_chains_controller.go new file mode 100644 index 00000000000..56d44d600ca --- /dev/null +++ b/core/web/solana_chains_controller.go @@ -0,0 +1,17 @@ +package web + +import ( + "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" + "github.com/smartcontractkit/chainlink/v2/core/services/relay" + "github.com/smartcontractkit/chainlink/v2/core/web/presenters" +) + +func NewSolanaChainsController(app chainlink.Application) ChainsController { + return newChainsController( + relay.NetworkSolana, + app.GetRelayers().List(chainlink.FilterRelayersByType(relay.NetworkSolana)), + ErrSolanaNotEnabled, + presenters.NewSolanaChainResource, + app.GetLogger(), + app.GetAuditLogger()) +} diff --git a/core/web/solana_chains_controller_test.go b/core/web/solana_chains_controller_test.go new file mode 100644 index 00000000000..fdc9bd16b9b --- /dev/null +++ b/core/web/solana_chains_controller_test.go @@ -0,0 +1,216 @@ +package web_test + +import ( + "fmt" + "math/rand" + "net/http" + "testing" + "time" + + "github.com/manyminds/api2go/jsonapi" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + commoncfg "github.com/smartcontractkit/chainlink-common/pkg/config" + "github.com/smartcontractkit/chainlink-common/pkg/types" + "github.com/smartcontractkit/chainlink-solana/pkg/solana/config" + + "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" + "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" + "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest" + "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" + "github.com/smartcontractkit/chainlink/v2/core/web" + "github.com/smartcontractkit/chainlink/v2/core/web/presenters" +) + +func Test_SolanaChainsController_Show(t *testing.T) { + t.Parallel() + + const validId = "Chainlink-12" + + testCases := []struct { + name string + inputId string + wantStatusCode int + want func(t *testing.T, app *cltest.TestApplication) *types.ChainStatus + }{ + { + inputId: validId, + name: "success", + want: func(t *testing.T, app *cltest.TestApplication) *types.ChainStatus { + return &types.ChainStatus{ + ID: validId, + Enabled: true, + Config: `ChainID = 'Chainlink-12' +BalancePollPeriod = '5s' +ConfirmPollPeriod = '500ms' +OCR2CachePollPeriod = '1s' +OCR2CacheTTL = '1m0s' +TxTimeout = '1h0m0s' +TxRetryTimeout = '10s' +TxConfirmTimeout = '30s' +TxRetentionTimeout = '0s' +SkipPreflight = false +Commitment = 'confirmed' +MaxRetries = 0 +FeeEstimatorMode = 'fixed' +ComputeUnitPriceMax = 1000 +ComputeUnitPriceMin = 0 +ComputeUnitPriceDefault = 0 +FeeBumpPeriod = '3s' +BlockHistoryPollPeriod = '5s' +BlockHistorySize = 1 +ComputeUnitLimitDefault = 200000 +EstimateComputeUnitLimit = false +Nodes = [] + +[MultiNode] +Enabled = false +PollFailureThreshold = 5 +PollInterval = '15s' +SelectionMode = 'PriorityLevel' +SyncThreshold = 10 +NodeIsSyncingEnabled = false +LeaseDuration = '1m0s' +FinalizedBlockPollInterval = '5s' +EnforceRepeatableRead = true +DeathDeclarationDelay = '20s' +NodeNoNewHeadsThreshold = '20s' +NoNewFinalizedHeadsThreshold = '20s' +FinalityDepth = 0 +FinalityTagEnabled = true +FinalizedBlockOffset = 50 +`, + } + }, + wantStatusCode: http.StatusOK, + }, + { + inputId: "234", + name: "not found", + want: func(t *testing.T, app *cltest.TestApplication) *types.ChainStatus { + return nil + }, + wantStatusCode: http.StatusBadRequest, + }, + } + + for _, testCase := range testCases { + tc := testCase + + t.Run(tc.name, func(t *testing.T) { + t.Parallel() + + controller := setupSolanaChainsControllerTestV2(t, &config.TOMLConfig{ + ChainID: ptr(validId), + Chain: config.Chain{ + SkipPreflight: ptr(false), + TxTimeout: commoncfg.MustNewDuration(time.Hour), + }, + }) + + wantedResult := tc.want(t, controller.app) + resp, cleanup := controller.client.Get( + fmt.Sprintf("/v2/chains/solana/%s", tc.inputId), + ) + t.Cleanup(cleanup) + require.Equal(t, tc.wantStatusCode, resp.StatusCode) + + if wantedResult != nil { + resource1 := presenters.SolanaChainResource{} + err := web.ParseJSONAPIResponse(cltest.ParseResponseBody(t, resp), &resource1) + require.NoError(t, err) + + assert.Equal(t, wantedResult.ID, resource1.ID) + assert.Equal(t, wantedResult.Enabled, resource1.Enabled) + assert.Equal(t, wantedResult.Config, resource1.Config) + } + }) + } +} + +func Test_SolanaChainsController_Index(t *testing.T) { + t.Parallel() + + chainA := &config.TOMLConfig{ + ChainID: ptr(fmt.Sprintf("ChainlinktestA-%d", rand.Int31n(999999))), + Chain: config.Chain{ + TxTimeout: commoncfg.MustNewDuration(time.Hour), + }, + } + chainB := &config.TOMLConfig{ + ChainID: ptr(fmt.Sprintf("ChainlinktestB-%d", rand.Int31n(999999))), + Chain: config.Chain{ + SkipPreflight: ptr(false), + }, + } + controller := setupSolanaChainsControllerTestV2(t, chainA, chainB) + + badResp, cleanup := controller.client.Get("/v2/chains/solana?size=asd") + t.Cleanup(cleanup) + require.Equal(t, http.StatusUnprocessableEntity, badResp.StatusCode) + + resp, cleanup := controller.client.Get("/v2/chains/solana?size=1") + t.Cleanup(cleanup) + require.Equal(t, http.StatusOK, resp.StatusCode) + + body := cltest.ParseResponseBody(t, resp) + + metaCount, err := cltest.ParseJSONAPIResponseMetaCount(body) + require.NoError(t, err) + require.Equal(t, 2, metaCount) + + var links jsonapi.Links + + chains := []presenters.SolanaChainResource{} + err = web.ParsePaginatedResponse(body, &chains, &links) + assert.NoError(t, err) + assert.NotEmpty(t, links["next"].Href) + assert.Empty(t, links["prev"].Href) + + assert.Len(t, links, 1) + assert.Equal(t, *chainA.ChainID, chains[0].ID) + tomlA, err := chainA.TOMLString() + require.NoError(t, err) + assert.Equal(t, tomlA, chains[0].Config) + + resp, cleanup = controller.client.Get(links["next"].Href) + t.Cleanup(cleanup) + require.Equal(t, http.StatusOK, resp.StatusCode) + + chains = []presenters.SolanaChainResource{} + err = web.ParsePaginatedResponse(cltest.ParseResponseBody(t, resp), &chains, &links) + assert.NoError(t, err) + assert.Empty(t, links["next"].Href) + assert.NotEmpty(t, links["prev"].Href) + + assert.Len(t, links, 1) + assert.Equal(t, *chainB.ChainID, chains[0].ID) + tomlB, err := chainB.TOMLString() + require.NoError(t, err) + assert.Equal(t, tomlB, chains[0].Config) +} + +type TestSolanaChainsController struct { + app *cltest.TestApplication + client cltest.HTTPClientCleaner +} + +func setupSolanaChainsControllerTestV2(t *testing.T, cfgs ...*config.TOMLConfig) *TestSolanaChainsController { + for i := range cfgs { + cfgs[i].SetDefaults() + } + cfg := configtest.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) { + c.Solana = cfgs + c.EVM = nil + }) + app := cltest.NewApplicationWithConfig(t, cfg) + require.NoError(t, app.Start(testutils.Context(t))) + + client := app.NewHTTPClient(nil) + + return &TestSolanaChainsController{ + app: app, + client: client, + } +} diff --git a/core/web/solana_nodes_controller.go b/core/web/solana_nodes_controller.go new file mode 100644 index 00000000000..71b8f70c5ec --- /dev/null +++ b/core/web/solana_nodes_controller.go @@ -0,0 +1,17 @@ +package web + +import ( + "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" + "github.com/smartcontractkit/chainlink/v2/core/services/relay" + "github.com/smartcontractkit/chainlink/v2/core/web/presenters" +) + +// ErrSolanaNotEnabled is returned when Solana.Enabled is not true. +var ErrSolanaNotEnabled = errChainDisabled{name: "Solana", tomlKey: "Solana.Enabled"} + +func NewSolanaNodesController(app chainlink.Application) NodesController { + scopedNodeStatuser := NewNetworkScopedNodeStatuser(app.GetRelayers(), relay.NetworkSolana) + + return newNodesController[presenters.SolanaNodeResource]( + scopedNodeStatuser, ErrSolanaNotEnabled, presenters.NewSolanaNodeResource, app.GetAuditLogger()) +} diff --git a/core/web/solana_transfer_controller.go b/core/web/solana_transfer_controller.go index 5a5f51bc9dd..07c629a7dd1 100644 --- a/core/web/solana_transfer_controller.go +++ b/core/web/solana_transfer_controller.go @@ -22,8 +22,6 @@ type SolanaTransfersController struct { App chainlink.Application } -var ErrSolanaNotEnabled = errChainDisabled{name: "Solana", tomlKey: "Solana.Enabled"} - // Create sends SOL and other native coins from the Chainlink's account to a specified address. func (tc *SolanaTransfersController) Create(c *gin.Context) { relayers := tc.App.GetRelayers().List(chainlink.FilterRelayersByType(relay.NetworkSolana)) diff --git a/core/web/starknet_chains_controller.go b/core/web/starknet_chains_controller.go new file mode 100644 index 00000000000..eb79ba3f962 --- /dev/null +++ b/core/web/starknet_chains_controller.go @@ -0,0 +1,17 @@ +package web + +import ( + "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" + "github.com/smartcontractkit/chainlink/v2/core/services/relay" + "github.com/smartcontractkit/chainlink/v2/core/web/presenters" +) + +func NewStarkNetChainsController(app chainlink.Application) ChainsController { + return newChainsController( + relay.NetworkStarkNet, + app.GetRelayers().List(chainlink.FilterRelayersByType(relay.NetworkStarkNet)), + ErrStarkNetNotEnabled, + presenters.NewStarkNetChainResource, + app.GetLogger(), + app.GetAuditLogger()) +} diff --git a/core/web/starknet_nodes_controller.go b/core/web/starknet_nodes_controller.go new file mode 100644 index 00000000000..664b89d03ca --- /dev/null +++ b/core/web/starknet_nodes_controller.go @@ -0,0 +1,17 @@ +package web + +import ( + "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" + "github.com/smartcontractkit/chainlink/v2/core/services/relay" + "github.com/smartcontractkit/chainlink/v2/core/web/presenters" +) + +// ErrStarkNetNotEnabled is returned when Starknet.Enabled is not true. +var ErrStarkNetNotEnabled = errChainDisabled{name: "StarkNet", tomlKey: "Starknet.Enabled"} + +func NewStarkNetNodesController(app chainlink.Application) NodesController { + scopedNodeStatuser := NewNetworkScopedNodeStatuser(app.GetRelayers(), relay.NetworkStarkNet) + + return newNodesController[presenters.StarkNetNodeResource]( + scopedNodeStatuser, ErrStarkNetNotEnabled, presenters.NewStarkNetNodeResource, app.GetAuditLogger()) +} diff --git a/core/web/testutils/mock_relayer.go b/core/web/testutils/mock_relayer.go index c96bf5ee494..4666f9da6a4 100644 --- a/core/web/testutils/mock_relayer.go +++ b/core/web/testutils/mock_relayer.go @@ -33,7 +33,7 @@ func (m MockRelayer) HealthReport() map[string]error { panic("not implemented") } -func (m MockRelayer) NewContractWriter(_ context.Context, _ []byte) (commontypes.ContractWriter, error) { +func (m MockRelayer) NewChainWriter(_ context.Context, _ []byte) (commontypes.ChainWriter, error) { panic("not implemented") } diff --git a/deployment/.golangci.yml b/deployment/.golangci.yml index ff1303e26ce..0268ba7beaa 100644 --- a/deployment/.golangci.yml +++ b/deployment/.golangci.yml @@ -1,33 +1,15 @@ run: timeout: 15m - allow-parallel-runners: true linters: enable: - - containedctx - - depguard - - errname - - errorlint - exhaustive - exportloopref - - fatcontext - - ginkgolinter - - gocritic + - revive - goimports - gosec - - loggercheck - - mirror - misspell - - noctx - - nolintlint - - perfsprint - - prealloc - - revive - rowserrcheck - - spancheck - - sqlclosecheck - - testifylint - - unconvert - - whitespace + - errorlint linters-settings: exhaustive: default-signifies-exhaustive: true @@ -41,28 +23,6 @@ linters-settings: govet: enable: - shadow - settings: - printf: - # Additionally check chainlink custom loggers - funcs: - - (github.com/smartcontractkit/chainlink/v2/core/logger.Logger).Tracef - - (github.com/smartcontractkit/chainlink/v2/core/logger.Logger).Debugf - - (github.com/smartcontractkit/chainlink/v2/core/logger.Logger).Infof - - (github.com/smartcontractkit/chainlink/v2/core/logger.Logger).Warnf - - (github.com/smartcontractkit/chainlink/v2/core/logger.Logger).Errorf - - (github.com/smartcontractkit/chainlink/v2/core/logger.Logger).Criticalf - - (github.com/smartcontractkit/chainlink/v2/core/logger.Logger).Panicf - - (github.com/smartcontractkit/chainlink/v2/core/logger.Logger).Fatalf - - (github.com/smartcontractkit/chainlink/v2/core/logger.SugaredLogger).AssumptionViolationf - - (github.com/smartcontractkit/chainlink-common/pkg/logger.Logger).Debugf - - (github.com/smartcontractkit/chainlink-common/pkg/logger.Logger).Infof - - (github.com/smartcontractkit/chainlink-common/pkg/logger.Logger).Warnf - - (github.com/smartcontractkit/chainlink-common/pkg/logger.Logger).Errorf - - (github.com/smartcontractkit/chainlink-common/pkg/logger.Logger).Panicf - - (github.com/smartcontractkit/chainlink-common/pkg/logger.Logger).Fatalf - - (github.com/smartcontractkit/chainlink-common/pkg/logger.SugaredLogger).AssumptionViolationf - - (github.com/smartcontractkit/chainlink-common/pkg/logger.SugaredLogger).Tracef - - (github.com/smartcontractkit/chainlink-common/pkg/logger.SugaredLogger).Criticalf revive: confidence: 0.8 rules: @@ -73,10 +33,9 @@ linters-settings: - name: error-return - name: error-strings - name: error-naming - - name: exported - name: if-return - name: increment-decrement - - name: var-naming + # - name: var-naming // doesn't work with some generated names - name: var-declaration - name: package-comments - name: range @@ -87,7 +46,7 @@ linters-settings: - name: errorf - name: empty-block - name: superfluous-else - # - name: unused-parameter + #- name: unused-parameter - name: unreachable-code - name: redefines-builtin-id - name: waitgroup-by-value @@ -102,69 +61,13 @@ linters-settings: - name: identical-branches - name: get-return # - name: flag-parameter // probably one we should work on doing better at in the future - - name: early-return + # - name: early-return // probably one we should work on doing better at in the future - name: defer - name: constant-logical-expr - name: confusing-naming - name: confusing-results - name: bool-literal-in-expr - name: atomic - depguard: - rules: - main: - list-mode: lax - deny: - - pkg: cosmossdk.io/errors - desc: Use the standard library instead - - pkg: github.com/gofrs/uuid - desc: Use github.com/google/uuid instead - - pkg: github.com/jackc/pgx3 - desc: Use github.com/jackc/pgx4 instead - - pkg: github.com/jackc/pgx5 - desc: Use github.com/jackc/pgx4 instead - - pkg: github.com/satori/go.uuid - desc: Use github.com/google/uuid instead - - pkg: github.com/test-go/testify/assert - desc: Use github.com/stretchr/testify/assert instead - - pkg: github.com/test-go/testify/mock - desc: Use github.com/stretchr/testify/mock instead - - pkg: github.com/test-go/testify/require - desc: Use github.com/stretchr/testify/require instead - - pkg: go.uber.org/multierr - desc: Use the standard library instead, for example https://pkg.go.dev/errors#Join - - pkg: gopkg.in/guregu/null.v1 - desc: Use gopkg.in/guregu/null.v4 instead - - pkg: gopkg.in/guregu/null.v2 - desc: Use gopkg.in/guregu/null.v4 instead - - pkg: gopkg.in/guregu/null.v3 - desc: Use gopkg.in/guregu/null.v4 instead - - pkg: github.com/go-gorm/gorm - desc: Use github.com/jmoiron/sqlx directly instead - loggercheck: - # Check that *w logging functions have even number of args (i.e., well formed key-value pairs). - rules: - - (github.com/smartcontractkit/chainlink/v2/core/logger.Logger).Tracew - - (github.com/smartcontractkit/chainlink/v2/core/logger.Logger).Debugw - - (github.com/smartcontractkit/chainlink/v2/core/logger.Logger).Infow - - (github.com/smartcontractkit/chainlink/v2/core/logger.Logger).Warnw - - (github.com/smartcontractkit/chainlink/v2/core/logger.Logger).Errorw - - (github.com/smartcontractkit/chainlink/v2/core/logger.Logger).Criticalw - - (github.com/smartcontractkit/chainlink/v2/core/logger.Logger).Panicw - - (github.com/smartcontractkit/chainlink/v2/core/logger.Logger).Fatalw - - (github.com/smartcontractkit/chainlink/v2/core/logger.SugaredLogger).AssumptionViolationw - - (github.com/smartcontractkit/chainlink-common/pkg/logger.Logger).Debugw - - (github.com/smartcontractkit/chainlink-common/pkg/logger.Logger).Infow - - (github.com/smartcontractkit/chainlink-common/pkg/logger.Logger).Warnw - - (github.com/smartcontractkit/chainlink-common/pkg/logger.Logger).Errorw - - (github.com/smartcontractkit/chainlink-common/pkg/logger.Logger).Panicw - - (github.com/smartcontractkit/chainlink-common/pkg/logger.Logger).Fatalw - - (github.com/smartcontractkit/chainlink-common/pkg/logger.SugaredLogger).AssumptionViolationw - - (github.com/smartcontractkit/chainlink-common/pkg/logger.SugaredLogger).Tracew - - (github.com/smartcontractkit/chainlink-common/pkg/logger.SugaredLogger).Criticalw - - (github.com/smartcontractkit/chainlink-common/pkg/logger.SugaredLogger).With - nolintlint: - require-specific: true - require-explanation: true issues: exclude-rules: - path: memory/(.+)\.go diff --git a/deployment/.mockery.yaml b/deployment/.mockery.yaml deleted file mode 100644 index 79e4d52104a..00000000000 --- a/deployment/.mockery.yaml +++ /dev/null @@ -1,13 +0,0 @@ -dir: "{{ .InterfaceDir }}/mocks" -mockname: "{{ .InterfaceName }}" -outpkg: mocks -filename: "{{ .InterfaceName | snakecase }}.go" -packages: - github.com/smartcontractkit/chainlink/deployment: - interfaces: - OffchainClient: - config: - mockname: "Mock{{ .InterfaceName }}" - filename: offchain_client_mock.go - inpackage: true - dir: "{{ .InterfaceDir }}/mocks" \ No newline at end of file diff --git a/deployment/README.md b/deployment/README.md index f3bd29b768b..723397edc1c 100644 --- a/deployment/README.md +++ b/deployment/README.md @@ -6,14 +6,14 @@ deployment/configuration logic to be tested against ephemeral environments and then exposed for use in persistent environments like testnet/mainnet. ## Table of Contents -- [Address Book](#address-book) -- [View](#view) -- [Environment](#environment) -- [Job Distributor](#job-distributor) -- [Changesets](#changsets) -- [Directory Structure](#directory-structure) -- [Integration Testing](#integration-testing) -- [FAQ](#faq) +- [Address Book](##Address-Book) +- [View](##View) +- [Environment](##Environment) +- [Job Distributor](##Job-Distributor) +- [Changesets](##Changesets) +- [Directory Structure](##Directory-Structure) +- [Integration Testing](##Integration-Testing) +- [FAQ](##FAQ) ## Address Book An [address book](https://github.com/smartcontractkit/chainlink/blob/develop/deployment/address_book.go#L79) represents @@ -100,14 +100,12 @@ TODO: Add various examples in deployment/example. contracts (like MCMS, LinkToken etc) which can be shared by products. -/deployment/product/internal +/deployment/ +- package name `deployment` - Internal building blocks for changesets +- TODO: can we make this `internal`? -/deployment/product/view -- Hold readonly mappings Go bindings to json marshallable objects. -- Used to generate a view of the system. - -/deployment/product/changeset +/deployment//changeset - Think of this as the public API for deployment and configuration of your product. - All the changesets should have an associated test using a memory or devenv diff --git a/deployment/address_book.go b/deployment/address_book.go index 3ce0332a4c3..076e2a235d6 100644 --- a/deployment/address_book.go +++ b/deployment/address_book.go @@ -27,7 +27,6 @@ var ( Version1_1_0 = *semver.MustParse("1.1.0") Version1_2_0 = *semver.MustParse("1.2.0") Version1_5_0 = *semver.MustParse("1.5.0") - Version1_5_1 = *semver.MustParse("1.5.1") Version1_6_0_dev = *semver.MustParse("1.6.0-dev") ) @@ -89,33 +88,26 @@ type AddressBook interface { Remove(ab AddressBook) error } -type AddressesByChain map[uint64]map[string]TypeAndVersion - type AddressBookMap struct { - addressesByChain AddressesByChain + addressesByChain map[uint64]map[string]TypeAndVersion mtx sync.RWMutex } -// Save will save an address for a given chain selector. It will error if there is a conflicting existing address. +// save will save an address for a given chain selector. It will error if there is a conflicting existing address. func (m *AddressBookMap) save(chainSelector uint64, address string, typeAndVersion TypeAndVersion) error { - family, err := chainsel.GetSelectorFamily(chainSelector) - if err != nil { + _, exists := chainsel.ChainBySelector(chainSelector) + if !exists { return errors.Wrapf(ErrInvalidChainSelector, "chain selector %d", chainSelector) } - if family == chainsel.FamilyEVM { - if address == "" || address == common.HexToAddress("0x0").Hex() { - return errors.Wrap(ErrInvalidAddress, "address cannot be empty") - } - if common.IsHexAddress(address) { - // IMPORTANT: WE ALWAYS STANDARDIZE ETHEREUM ADDRESS STRINGS TO EIP55 - address = common.HexToAddress(address).Hex() - } else { - return errors.Wrapf(ErrInvalidAddress, "address %s is not a valid Ethereum address, only Ethereum addresses supported for EVM chains", address) - } + if address == "" || address == common.HexToAddress("0x0").Hex() { + return errors.Wrap(ErrInvalidAddress, "address cannot be empty") + } + if common.IsHexAddress(address) { + // IMPORTANT: WE ALWAYS STANDARDIZE ETHEREUM ADDRESS STRINGS TO EIP55 + address = common.HexToAddress(address).Hex() + } else { + return errors.Wrapf(ErrInvalidAddress, "address %s is not a valid Ethereum address, only Ethereum addresses supported", address) } - - // TODO NONEVM-960: Add validation for non-EVM chain addresses - if typeAndVersion.Type == "" { return fmt.Errorf("type cannot be empty") } @@ -150,8 +142,8 @@ func (m *AddressBookMap) Addresses() (map[uint64]map[string]TypeAndVersion, erro } func (m *AddressBookMap) AddressesForChain(chainSelector uint64) (map[string]TypeAndVersion, error) { - _, err := chainsel.GetChainIDFromSelector(chainSelector) - if err != nil { + _, exists := chainsel.ChainBySelector(chainSelector) + if !exists { return nil, errors.Wrapf(ErrInvalidChainSelector, "chain selector %d", chainSelector) } @@ -203,7 +195,7 @@ func (m *AddressBookMap) Remove(ab AddressBook) error { // State of m.addressesByChain storage must not be changed in case of an error // need to do double iteration over the address book. First validation, second actual deletion for chainSelector, chainAddresses := range addresses { - for address := range chainAddresses { + for address, _ := range chainAddresses { if _, exists := m.addressesByChain[chainSelector][address]; !exists { return errors.New("AddressBookMap does not contain address from the given address book") } @@ -211,7 +203,7 @@ func (m *AddressBookMap) Remove(ab AddressBook) error { } for chainSelector, chainAddresses := range addresses { - for address := range chainAddresses { + for address, _ := range chainAddresses { delete(m.addressesByChain[chainSelector], address) } } @@ -258,41 +250,3 @@ func SearchAddressBook(ab AddressBook, chain uint64, typ ContractType) (string, return "", fmt.Errorf("not found") } - -func AddressBookContains(ab AddressBook, chain uint64, addrToFind string) (bool, error) { - addrs, err := ab.AddressesForChain(chain) - if err != nil { - return false, err - } - - for addr := range addrs { - if addr == addrToFind { - return true, nil - } - } - - return false, nil -} - -// AddressesContainBundle checks if the addresses -// contains a single instance of all the addresses in the bundle. -// It returns an error if there are more than one instance of a contract. -func AddressesContainBundle(addrs map[string]TypeAndVersion, wantTypes map[TypeAndVersion]struct{}) (bool, error) { - counts := make(map[TypeAndVersion]int) - for wantType := range wantTypes { - for _, haveType := range addrs { - if wantType == haveType { - counts[wantType]++ - if counts[wantType] > 1 { - return false, fmt.Errorf("found more than one instance of contract %s", wantType) - } - } - } - } - // Either 0 or 1, so we can just check the sum. - sum := 0 - for _, count := range counts { - sum += count - } - return sum == len(wantTypes), nil -} diff --git a/deployment/address_book_test.go b/deployment/address_book_test.go index e022e89a9ab..9040902a169 100644 --- a/deployment/address_book_test.go +++ b/deployment/address_book_test.go @@ -44,10 +44,6 @@ func TestAddressBook_Save(t *testing.T) { err = ab.Save(chainsel.TEST_90000001.Selector, common.HexToAddress("0x0").Hex(), onRamp100) require.Error(t, err) - // Zero address but non evm chain - err = NewMemoryAddressBook().Save(chainsel.APTOS_MAINNET.Selector, common.HexToAddress("0x0").Hex(), onRamp100) - require.NoError(t, err) - // Distinct address same TV will not err = ab.Save(chainsel.TEST_90000001.Selector, addr2, onRamp100) require.NoError(t, err) @@ -210,14 +206,14 @@ func TestAddressBook_ConcurrencyAndDeadlock(t *testing.T) { require.NoError(t, err) for chainSelector, chainAddresses := range addresses { // concurrent read chainAddresses from Addresses() method - for address := range chainAddresses { + for address, _ := range chainAddresses { addresses[chainSelector][address] = onRamp110 } // concurrent read chainAddresses from AddressesForChain() method chainAddresses, err = baseAB.AddressesForChain(chainSelector) require.NoError(t, err) - for address := range chainAddresses { + for address, _ := range chainAddresses { _ = addresses[chainSelector][address] } } @@ -243,36 +239,3 @@ func TestAddressBook_ConcurrencyAndDeadlock(t *testing.T) { wg.Wait() } - -func TestAddressesContainsBundle(t *testing.T) { - onRamp100 := NewTypeAndVersion("OnRamp", Version1_0_0) - onRamp110 := NewTypeAndVersion("OnRamp", Version1_1_0) - onRamp120 := NewTypeAndVersion("OnRamp", Version1_2_0) - addr1 := common.HexToAddress("0x1").String() - addr2 := common.HexToAddress("0x2").String() - addr3 := common.HexToAddress("0x3").String() - - // More than one instance should error - _, err := AddressesContainBundle(map[string]TypeAndVersion{ - addr1: onRamp100, - addr2: onRamp100, - }, map[TypeAndVersion]struct{}{onRamp100: {}}) - require.Error(t, err) - - // No such instances should be false - exists, err := AddressesContainBundle(map[string]TypeAndVersion{ - addr2: onRamp110, - addr1: onRamp110, - }, map[TypeAndVersion]struct{}{onRamp100: {}}) - require.NoError(t, err) - assert.Equal(t, exists, false) - - // 2 elements - exists, err = AddressesContainBundle(map[string]TypeAndVersion{ - addr1: onRamp100, - addr2: onRamp110, - addr3: onRamp120, - }, map[TypeAndVersion]struct{}{onRamp100: {}, onRamp110: {}}) - require.NoError(t, err) - assert.Equal(t, exists, true) -} diff --git a/deployment/ccip/active_candidate.go b/deployment/ccip/active_candidate.go new file mode 100644 index 00000000000..c65dac04103 --- /dev/null +++ b/deployment/ccip/active_candidate.go @@ -0,0 +1,139 @@ +package ccipdeployment + +import ( + "fmt" + "github.com/smartcontractkit/ccip-owner-contracts/pkg/proposal/mcms" + "github.com/smartcontractkit/chainlink/deployment" + cctypes "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/types" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/ccip_home" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry" + "math/big" +) + +// SetCandidateExecPluginOps calls setCandidate on CCIPHome contract through the UpdateDON call on CapReg contract +// This proposes to set up OCR3 config for the provided plugin for the DON +func SetCandidateOnExistingDon( + pluginConfig ccip_home.CCIPHomeOCR3Config, + capReg *capabilities_registry.CapabilitiesRegistry, + ccipHome *ccip_home.CCIPHome, + chainSelector uint64, + nodes deployment.Nodes, +) ([]mcms.Operation, error) { + // fetch DON ID for the chain + donID, err := DonIDForChain(capReg, ccipHome, chainSelector) + if err != nil { + return nil, fmt.Errorf("fetch don id for chain: %w", err) + } + fmt.Printf("donID: %d", donID) + encodedSetCandidateCall, err := CCIPHomeABI.Pack( + "setCandidate", + donID, + pluginConfig.PluginType, + pluginConfig, + [32]byte{}, + ) + if err != nil { + return nil, fmt.Errorf("pack set candidate call: %w", err) + } + + // set candidate call + updateDonTx, err := capReg.UpdateDON( + deployment.SimTransactOpts(), + donID, + nodes.PeerIDs(), + []capabilities_registry.CapabilitiesRegistryCapabilityConfiguration{ + { + CapabilityId: CCIPCapabilityID, + Config: encodedSetCandidateCall, + }, + }, + false, + nodes.DefaultF(), + ) + if err != nil { + return nil, fmt.Errorf("update don w/ exec config: %w", err) + } + + return []mcms.Operation{{ + To: capReg.Address(), + Data: updateDonTx.Data(), + Value: big.NewInt(0), + }}, nil +} + +// PromoteCandidateOp will create the MCMS Operation for `promoteCandidateAndRevokeActive` directed towards the capabilityRegistry +func PromoteCandidateOp(donID uint32, pluginType uint8, capReg *capabilities_registry.CapabilitiesRegistry, + ccipHome *ccip_home.CCIPHome, nodes deployment.Nodes) (mcms.Operation, error) { + + allConfigs, err := ccipHome.GetAllConfigs(nil, donID, pluginType) + if err != nil { + return mcms.Operation{}, err + } + + if allConfigs.CandidateConfig.ConfigDigest == [32]byte{} { + return mcms.Operation{}, fmt.Errorf("candidate digest is empty, expected nonempty") + } + fmt.Printf("commit candidate digest after setCandidate: %x\n", allConfigs.CandidateConfig.ConfigDigest) + + encodedPromotionCall, err := CCIPHomeABI.Pack( + "promoteCandidateAndRevokeActive", + donID, + pluginType, + allConfigs.CandidateConfig.ConfigDigest, + allConfigs.ActiveConfig.ConfigDigest, + ) + if err != nil { + return mcms.Operation{}, fmt.Errorf("pack promotion call: %w", err) + } + + updateDonTx, err := capReg.UpdateDON( + deployment.SimTransactOpts(), + donID, + nodes.PeerIDs(), + []capabilities_registry.CapabilitiesRegistryCapabilityConfiguration{ + { + CapabilityId: CCIPCapabilityID, + Config: encodedPromotionCall, + }, + }, + false, + nodes.DefaultF(), + ) + if err != nil { + return mcms.Operation{}, fmt.Errorf("error creating updateDon op for donID(%d) and plugin type (%d): %w", donID, pluginType, err) + } + return mcms.Operation{ + To: capReg.Address(), + Data: updateDonTx.Data(), + Value: big.NewInt(0), + }, nil +} + +// PromoteAllCandidatesForChainOps promotes the candidate commit and exec configs to active by calling promoteCandidateAndRevokeActive on CCIPHome through the UpdateDON call on CapReg contract +func PromoteAllCandidatesForChainOps( + capReg *capabilities_registry.CapabilitiesRegistry, + ccipHome *ccip_home.CCIPHome, + chainSelector uint64, + nodes deployment.Nodes, +) ([]mcms.Operation, error) { + // fetch DON ID for the chain + donID, err := DonIDForChain(capReg, ccipHome, chainSelector) + if err != nil { + return nil, fmt.Errorf("fetch don id for chain: %w", err) + } + + var mcmsOps []mcms.Operation + updateCommitOp, err := PromoteCandidateOp(donID, uint8(cctypes.PluginTypeCCIPCommit), capReg, ccipHome, nodes) + if err != nil { + return nil, fmt.Errorf("promote candidate op: %w", err) + } + mcmsOps = append(mcmsOps, updateCommitOp) + + updateExecOp, err := PromoteCandidateOp(donID, uint8(cctypes.PluginTypeCCIPExec), capReg, ccipHome, nodes) + if err != nil { + return nil, fmt.Errorf("promote candidate op: %w", err) + } + mcmsOps = append(mcmsOps, updateExecOp) + + return mcmsOps, nil +} diff --git a/deployment/ccip/add_lane.go b/deployment/ccip/add_lane.go new file mode 100644 index 00000000000..8af96277fc2 --- /dev/null +++ b/deployment/ccip/add_lane.go @@ -0,0 +1,138 @@ +package ccipdeployment + +import ( + "encoding/hex" + "math/big" + + "github.com/ethereum/go-ethereum/common" + + "github.com/smartcontractkit/chainlink/deployment" + "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/ccipevm" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/offramp" + + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/fee_quoter" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/onramp" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/router" +) + +type InitialPrices struct { + LinkPrice *big.Int // USD to the power of 18 (e18) per LINK + WethPrice *big.Int // USD to the power of 18 (e18) per WETH + GasPrice *big.Int // uint224 packed gas price in USD (112 for exec // 112 for da) +} + +var DefaultInitialPrices = InitialPrices{ + LinkPrice: deployment.E18Mult(20), + WethPrice: deployment.E18Mult(4000), + GasPrice: ToPackedFee(big.NewInt(8e14), big.NewInt(0)), +} + +func AddLaneWithDefaultPrices(e deployment.Environment, state CCIPOnChainState, from, to uint64) error { + return AddLane(e, state, from, to, DefaultInitialPrices) +} + +func AddLane(e deployment.Environment, state CCIPOnChainState, from, to uint64, initialPrices InitialPrices) error { + // TODO: Batch + tx, err := state.Chains[from].Router.ApplyRampUpdates(e.Chains[from].DeployerKey, []router.RouterOnRamp{ + { + DestChainSelector: to, + OnRamp: state.Chains[from].OnRamp.Address(), + }, + }, []router.RouterOffRamp{}, []router.RouterOffRamp{}) + if _, err := deployment.ConfirmIfNoError(e.Chains[from], tx, err); err != nil { + return err + } + tx, err = state.Chains[from].OnRamp.ApplyDestChainConfigUpdates(e.Chains[from].DeployerKey, + []onramp.OnRampDestChainConfigArgs{ + { + DestChainSelector: to, + Router: state.Chains[from].Router.Address(), + }, + }) + if _, err := deployment.ConfirmIfNoError(e.Chains[from], tx, err); err != nil { + return err + } + + _, err = state.Chains[from].FeeQuoter.UpdatePrices( + e.Chains[from].DeployerKey, fee_quoter.InternalPriceUpdates{ + TokenPriceUpdates: []fee_quoter.InternalTokenPriceUpdate{ + { + SourceToken: state.Chains[from].LinkToken.Address(), + UsdPerToken: initialPrices.LinkPrice, + }, + { + SourceToken: state.Chains[from].Weth9.Address(), + UsdPerToken: initialPrices.WethPrice, + }, + }, + GasPriceUpdates: []fee_quoter.InternalGasPriceUpdate{ + { + DestChainSelector: to, + UsdPerUnitGas: initialPrices.GasPrice, + }, + }}) + if _, err := deployment.ConfirmIfNoError(e.Chains[from], tx, err); err != nil { + return err + } + + // Enable dest in fee quoter + tx, err = state.Chains[from].FeeQuoter.ApplyDestChainConfigUpdates(e.Chains[from].DeployerKey, + []fee_quoter.FeeQuoterDestChainConfigArgs{ + { + DestChainSelector: to, + DestChainConfig: DefaultFeeQuoterDestChainConfig(), + }, + }) + if _, err := deployment.ConfirmIfNoError(e.Chains[from], tx, err); err != nil { + return err + } + + tx, err = state.Chains[to].OffRamp.ApplySourceChainConfigUpdates(e.Chains[to].DeployerKey, + []offramp.OffRampSourceChainConfigArgs{ + { + Router: state.Chains[to].Router.Address(), + SourceChainSelector: from, + IsEnabled: true, + OnRamp: common.LeftPadBytes(state.Chains[from].OnRamp.Address().Bytes(), 32), + }, + }) + if _, err := deployment.ConfirmIfNoError(e.Chains[to], tx, err); err != nil { + return err + } + tx, err = state.Chains[to].Router.ApplyRampUpdates(e.Chains[to].DeployerKey, []router.RouterOnRamp{}, []router.RouterOffRamp{}, []router.RouterOffRamp{ + { + SourceChainSelector: from, + OffRamp: state.Chains[to].OffRamp.Address(), + }, + }) + _, err = deployment.ConfirmIfNoError(e.Chains[to], tx, err) + return err +} + +func DefaultFeeQuoterDestChainConfig() fee_quoter.FeeQuoterDestChainConfig { + // https://github.com/smartcontractkit/ccip/blob/c4856b64bd766f1ddbaf5d13b42d3c4b12efde3a/contracts/src/v0.8/ccip/libraries/Internal.sol#L337-L337 + /* + ```Solidity + // bytes4(keccak256("CCIP ChainFamilySelector EVM")) + bytes4 public constant CHAIN_FAMILY_SELECTOR_EVM = 0x2812d52c; + ``` + */ + evmFamilySelector, _ := hex.DecodeString("2812d52c") + return fee_quoter.FeeQuoterDestChainConfig{ + IsEnabled: true, + MaxNumberOfTokensPerMsg: 10, + MaxDataBytes: 256, + MaxPerMsgGasLimit: 3_000_000, + DestGasOverhead: ccipevm.DestGasOverhead, + DefaultTokenFeeUSDCents: 1, + DestGasPerPayloadByte: ccipevm.CalldataGasPerByte, + DestDataAvailabilityOverheadGas: 100, + DestGasPerDataAvailabilityByte: 100, + DestDataAvailabilityMultiplierBps: 1, + DefaultTokenDestGasOverhead: 125_000, + DefaultTxGasLimit: 200_000, + GasMultiplierWeiPerEth: 11e17, // Gas multiplier in wei per eth is scaled by 1e18, so 11e17 is 1.1 = 110% + NetworkFeeUSDCents: 1, + ChainFamilySelector: [4]byte(evmFamilySelector), + } +} diff --git a/deployment/ccip/add_lane_test.go b/deployment/ccip/add_lane_test.go new file mode 100644 index 00000000000..5edfdae1ab0 --- /dev/null +++ b/deployment/ccip/add_lane_test.go @@ -0,0 +1,154 @@ +package ccipdeployment + +import ( + "testing" + "time" + + "github.com/ethereum/go-ethereum/common" + "github.com/stretchr/testify/require" + + commonutils "github.com/smartcontractkit/chainlink-common/pkg/utils" + "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/testcontext" + + "github.com/smartcontractkit/chainlink/deployment" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/offramp" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/router" + "github.com/smartcontractkit/chainlink/v2/core/logger" +) + +// TestAddLane covers the workflow of adding a lane between two chains and enabling it. +// It also covers the case where the onRamp is disabled on the OffRamp contract initially and then enabled. +func TestAddLane(t *testing.T) { + t.Parallel() + // We add more chains to the chainlink nodes than the number of chains where CCIP is deployed. + e := NewMemoryEnvironmentWithJobs(t, logger.TestLogger(t), 4, 4) + // Here we have CR + nodes set up, but no CCIP contracts deployed. + state, err := LoadOnchainState(e.Env) + require.NoError(t, err) + + selectors := e.Env.AllChainSelectors() + // deploy CCIP contracts on two chains + chain1, chain2 := selectors[0], selectors[1] + + feeds := state.Chains[e.FeedChainSel].USDFeeds + tokenConfig := NewTestTokenConfig(feeds) + newAddresses := deployment.NewMemoryAddressBook() + err = DeployPrerequisiteChainContracts(e.Env, newAddresses, e.Env.AllChainSelectors()) + require.NoError(t, err) + require.NoError(t, e.Env.ExistingAddresses.Merge(newAddresses)) + + // Set up CCIP contracts and a DON per chain. + newAddresses = deployment.NewMemoryAddressBook() + err = DeployCCIPContracts(e.Env, newAddresses, DeployCCIPContractConfig{ + HomeChainSel: e.HomeChainSel, + FeedChainSel: e.FeedChainSel, + TokenConfig: tokenConfig, + MCMSConfig: NewTestMCMSConfig(t, e.Env), + ChainsToDeploy: []uint64{chain1, chain2}, + OCRSecrets: deployment.XXXGenerateTestOCRSecrets(), + }) + require.NoError(t, err) + require.NoError(t, e.Env.ExistingAddresses.Merge(newAddresses)) + + // We expect no lanes available on any chain. + state, err = LoadOnchainState(e.Env) + require.NoError(t, err) + for _, sel := range []uint64{chain1, chain2} { + chain := state.Chains[sel] + offRamps, err := chain.Router.GetOffRamps(nil) + require.NoError(t, err) + require.Len(t, offRamps, 0) + } + + replayBlocks, err := LatestBlocksByChain(testcontext.Get(t), e.Env.Chains) + require.NoError(t, err) + + // Add one lane from chain1 to chain 2 and send traffic. + require.NoError(t, AddLaneWithDefaultPrices(e.Env, state, chain1, chain2)) + + ReplayLogs(t, e.Env.Offchain, replayBlocks) + time.Sleep(30 * time.Second) + // disable the onRamp initially on OffRamp + disableRampTx, err := state.Chains[chain2].OffRamp.ApplySourceChainConfigUpdates(e.Env.Chains[chain2].DeployerKey, []offramp.OffRampSourceChainConfigArgs{ + { + Router: state.Chains[chain2].Router.Address(), + SourceChainSelector: chain1, + IsEnabled: false, + OnRamp: common.LeftPadBytes(state.Chains[chain1].OnRamp.Address().Bytes(), 32), + }, + }) + _, err = deployment.ConfirmIfNoError(e.Env.Chains[chain2], disableRampTx, err) + require.NoError(t, err) + + for _, sel := range []uint64{chain1, chain2} { + chain := state.Chains[sel] + offRamps, err := chain.Router.GetOffRamps(nil) + require.NoError(t, err) + if sel == chain2 { + require.Len(t, offRamps, 1) + srcCfg, err := chain.OffRamp.GetSourceChainConfig(nil, chain1) + require.NoError(t, err) + require.Equal(t, common.LeftPadBytes(state.Chains[chain1].OnRamp.Address().Bytes(), 32), srcCfg.OnRamp) + require.False(t, srcCfg.IsEnabled) + } else { + require.Len(t, offRamps, 0) + } + } + + latesthdr, err := e.Env.Chains[chain2].Client.HeaderByNumber(testcontext.Get(t), nil) + require.NoError(t, err) + startBlock := latesthdr.Number.Uint64() + // Send traffic on the first lane and it should not be processed by the plugin as onRamp is disabled + // we will check this by confirming that the message is not executed by the end of the test + msgSentEvent1 := TestSendRequest(t, e.Env, state, chain1, chain2, false, router.ClientEVM2AnyMessage{ + Receiver: common.LeftPadBytes(state.Chains[chain2].Receiver.Address().Bytes(), 32), + Data: []byte("hello world"), + TokenAmounts: nil, + FeeToken: common.HexToAddress("0x0"), + ExtraArgs: nil, + }) + require.Equal(t, uint64(1), msgSentEvent1.SequenceNumber) + + // Add another lane + require.NoError(t, AddLaneWithDefaultPrices(e.Env, state, chain2, chain1)) + + // Send traffic on the second lane and it should succeed + latesthdr, err = e.Env.Chains[chain1].Client.HeaderByNumber(testcontext.Get(t), nil) + require.NoError(t, err) + startBlock2 := latesthdr.Number.Uint64() + msgSentEvent2 := TestSendRequest(t, e.Env, state, chain2, chain1, false, router.ClientEVM2AnyMessage{ + Receiver: common.LeftPadBytes(state.Chains[chain2].Receiver.Address().Bytes(), 32), + Data: []byte("hello world"), + TokenAmounts: nil, + FeeToken: common.HexToAddress("0x0"), + ExtraArgs: nil, + }) + require.Equal(t, uint64(1), msgSentEvent2.SequenceNumber) + require.NoError(t, commonutils.JustError(ConfirmExecWithSeqNr(t, e.Env.Chains[chain2], e.Env.Chains[chain1], state.Chains[chain1].OffRamp, &startBlock2, msgSentEvent2.SequenceNumber))) + + // now check for the previous message from chain 1 to chain 2 that it has not been executed till now as the onRamp was disabled + ConfirmNoExecConsistentlyWithSeqNr(t, e.Env.Chains[chain1], e.Env.Chains[chain2], state.Chains[chain2].OffRamp, msgSentEvent1.SequenceNumber, 30*time.Second) + + // enable the onRamp on OffRamp + enableRampTx, err := state.Chains[chain2].OffRamp.ApplySourceChainConfigUpdates(e.Env.Chains[chain2].DeployerKey, []offramp.OffRampSourceChainConfigArgs{ + { + Router: state.Chains[chain2].Router.Address(), + SourceChainSelector: chain1, + IsEnabled: true, + OnRamp: common.LeftPadBytes(state.Chains[chain1].OnRamp.Address().Bytes(), 32), + }, + }) + _, err = deployment.ConfirmIfNoError(e.Env.Chains[chain2], enableRampTx, err) + require.NoError(t, err) + + srcCfg, err := state.Chains[chain2].OffRamp.GetSourceChainConfig(nil, chain1) + require.NoError(t, err) + require.Equal(t, common.LeftPadBytes(state.Chains[chain1].OnRamp.Address().Bytes(), 32), srcCfg.OnRamp) + require.True(t, srcCfg.IsEnabled) + + // we need the replay here otherwise plugin is not able to locate the message + ReplayLogs(t, e.Env.Offchain, replayBlocks) + time.Sleep(30 * time.Second) + // Now that the onRamp is enabled, the request should be processed + require.NoError(t, commonutils.JustError(ConfirmExecWithSeqNr(t, e.Env.Chains[chain1], e.Env.Chains[chain2], state.Chains[chain2].OffRamp, &startBlock, msgSentEvent1.SequenceNumber))) +} diff --git a/deployment/ccip/changeset/accept_ownership_test.go b/deployment/ccip/changeset/accept_ownership_test.go deleted file mode 100644 index f74556b6600..00000000000 --- a/deployment/ccip/changeset/accept_ownership_test.go +++ /dev/null @@ -1,126 +0,0 @@ -package changeset - -import ( - "testing" - - "github.com/ethereum/go-ethereum/common" - - "github.com/stretchr/testify/require" - "golang.org/x/exp/maps" - - commonchangeset "github.com/smartcontractkit/chainlink/deployment/common/changeset" - "github.com/smartcontractkit/chainlink/deployment/common/proposalutils" -) - -func Test_NewAcceptOwnershipChangeset(t *testing.T) { - t.Parallel() - e := NewMemoryEnvironment(t) - state, err := LoadOnchainState(e.Env) - require.NoError(t, err) - - allChains := maps.Keys(e.Env.Chains) - source := allChains[0] - dest := allChains[1] - - timelockContracts := map[uint64]*proposalutils.TimelockExecutionContracts{ - source: { - Timelock: state.Chains[source].Timelock, - CallProxy: state.Chains[source].CallProxy, - }, - dest: { - Timelock: state.Chains[dest].Timelock, - CallProxy: state.Chains[dest].CallProxy, - }, - } - - // at this point we have the initial deploys done, now we need to transfer ownership - // to the timelock contract - state, err = LoadOnchainState(e.Env) - require.NoError(t, err) - - // compose the transfer ownership and accept ownership changesets - _, err = commonchangeset.ApplyChangesets(t, e.Env, timelockContracts, []commonchangeset.ChangesetApplication{ - // note this doesn't have proposals. - { - Changeset: commonchangeset.WrapChangeSet(commonchangeset.TransferToMCMSWithTimelock), - Config: genTestTransferOwnershipConfig(e, allChains, state), - }, - }) - require.NoError(t, err) - - assertTimelockOwnership(t, e, allChains, state) -} - -func genTestTransferOwnershipConfig( - e DeployedEnv, - chains []uint64, - state CCIPOnChainState, -) commonchangeset.TransferToMCMSWithTimelockConfig { - var ( - timelocksPerChain = make(map[uint64]common.Address) - contracts = make(map[uint64][]common.Address) - ) - - // chain contracts - for _, chain := range chains { - timelocksPerChain[chain] = state.Chains[chain].Timelock.Address() - contracts[chain] = []common.Address{ - state.Chains[chain].OnRamp.Address(), - state.Chains[chain].OffRamp.Address(), - state.Chains[chain].FeeQuoter.Address(), - state.Chains[chain].NonceManager.Address(), - state.Chains[chain].RMNRemote.Address(), - state.Chains[chain].TestRouter.Address(), - state.Chains[chain].Router.Address(), - } - } - - // home chain - homeChainTimelockAddress := state.Chains[e.HomeChainSel].Timelock.Address() - timelocksPerChain[e.HomeChainSel] = homeChainTimelockAddress - contracts[e.HomeChainSel] = append(contracts[e.HomeChainSel], - state.Chains[e.HomeChainSel].CapabilityRegistry.Address(), - state.Chains[e.HomeChainSel].CCIPHome.Address(), - state.Chains[e.HomeChainSel].RMNHome.Address(), - ) - - return commonchangeset.TransferToMCMSWithTimelockConfig{ - ContractsByChain: contracts, - } -} - -// assertTimelockOwnership asserts that the ownership of the contracts has been transferred -// to the appropriate timelock contract on each chain. -func assertTimelockOwnership( - t *testing.T, - e DeployedEnv, - chains []uint64, - state CCIPOnChainState, -) { - // check that the ownership has been transferred correctly - for _, chain := range chains { - for _, contract := range []common.Address{ - state.Chains[chain].OnRamp.Address(), - state.Chains[chain].OffRamp.Address(), - state.Chains[chain].FeeQuoter.Address(), - state.Chains[chain].NonceManager.Address(), - state.Chains[chain].RMNRemote.Address(), - } { - owner, _, err := commonchangeset.LoadOwnableContract(contract, e.Env.Chains[chain].Client) - require.NoError(t, err) - require.Equal(t, state.Chains[chain].Timelock.Address(), owner) - } - } - - // check home chain contracts ownership - homeChainTimelockAddress := state.Chains[e.HomeChainSel].Timelock.Address() - for _, contract := range []common.Address{ - state.Chains[e.HomeChainSel].CapabilityRegistry.Address(), - state.Chains[e.HomeChainSel].CCIPHome.Address(), - state.Chains[e.HomeChainSel].RMNHome.Address(), - } { - owner, _, err := commonchangeset.LoadOwnableContract(contract, e.Env.Chains[e.HomeChainSel].Client) - require.NoError(t, err) - require.Equal(t, homeChainTimelockAddress, owner) - } -} diff --git a/deployment/ccip/changeset/active_candidate.go b/deployment/ccip/changeset/active_candidate.go new file mode 100644 index 00000000000..9f46b8d20f1 --- /dev/null +++ b/deployment/ccip/changeset/active_candidate.go @@ -0,0 +1,97 @@ +package changeset + +import ( + "fmt" + "github.com/smartcontractkit/ccip-owner-contracts/pkg/proposal/mcms" + "github.com/smartcontractkit/ccip-owner-contracts/pkg/proposal/timelock" + + "github.com/smartcontractkit/chainlink/deployment" + ccdeploy "github.com/smartcontractkit/chainlink/deployment/ccip" + cctypes "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/types" +) + +// PromoteAllCandidatesChangeset generates a proposal to call promoteCandidate on the CCIPHome through CapReg. +// This needs to be called after SetCandidateProposal is executed. +func PromoteAllCandidatesChangeset( + state ccdeploy.CCIPOnChainState, + homeChainSel, newChainSel uint64, + nodes deployment.Nodes, +) (deployment.ChangesetOutput, error) { + promoteCandidateOps, err := ccdeploy.PromoteAllCandidatesForChainOps( + state.Chains[homeChainSel].CapabilityRegistry, + state.Chains[homeChainSel].CCIPHome, + newChainSel, + nodes.NonBootstraps(), + ) + if err != nil { + return deployment.ChangesetOutput{}, err + } + + prop, err := ccdeploy.BuildProposalFromBatches(state, []timelock.BatchChainOperation{{ + ChainIdentifier: mcms.ChainIdentifier(homeChainSel), + Batch: promoteCandidateOps, + }}, "promoteCandidate for commit and execution", 0) + if err != nil { + return deployment.ChangesetOutput{}, err + } + return deployment.ChangesetOutput{ + Proposals: []timelock.MCMSWithTimelockProposal{ + *prop, + }, + }, nil +} + +// SetCandidateExecPluginProposal calls setCandidate on the CCIPHome for setting up OCR3 exec Plugin config for the new chain. +func SetCandidatePluginChangeset( + state ccdeploy.CCIPOnChainState, + e deployment.Environment, + nodes deployment.Nodes, + ocrSecrets deployment.OCRSecrets, + homeChainSel, feedChainSel, newChainSel uint64, + tokenConfig ccdeploy.TokenConfig, + pluginType cctypes.PluginType, +) (deployment.ChangesetOutput, error) { + newDONArgs, err := ccdeploy.BuildOCR3ConfigForCCIPHome( + ocrSecrets, + state.Chains[newChainSel].OffRamp, + e.Chains[newChainSel], + feedChainSel, + tokenConfig.GetTokenInfo(e.Logger, state.Chains[newChainSel].LinkToken, state.Chains[newChainSel].Weth9), + nodes.NonBootstraps(), + state.Chains[homeChainSel].RMNHome.Address(), + nil, + ) + if err != nil { + return deployment.ChangesetOutput{}, err + } + + execConfig, ok := newDONArgs[pluginType] + if !ok { + return deployment.ChangesetOutput{}, fmt.Errorf("missing exec plugin in ocr3Configs") + } + + setCandidateMCMSOps, err := ccdeploy.SetCandidateOnExistingDon( + execConfig, + state.Chains[homeChainSel].CapabilityRegistry, + state.Chains[homeChainSel].CCIPHome, + newChainSel, + nodes.NonBootstraps(), + ) + if err != nil { + return deployment.ChangesetOutput{}, err + } + + prop, err := ccdeploy.BuildProposalFromBatches(state, []timelock.BatchChainOperation{{ + ChainIdentifier: mcms.ChainIdentifier(homeChainSel), + Batch: setCandidateMCMSOps, + }}, "SetCandidate for execution", 0) + if err != nil { + return deployment.ChangesetOutput{}, err + } + return deployment.ChangesetOutput{ + Proposals: []timelock.MCMSWithTimelockProposal{ + *prop, + }, + }, nil + +} diff --git a/deployment/ccip/changeset/active_candidate_test.go b/deployment/ccip/changeset/active_candidate_test.go new file mode 100644 index 00000000000..cd1d7604817 --- /dev/null +++ b/deployment/ccip/changeset/active_candidate_test.go @@ -0,0 +1,247 @@ +package changeset + +import ( + "testing" + + "github.com/ethereum/go-ethereum/common" + "github.com/smartcontractkit/ccip-owner-contracts/pkg/proposal/mcms" + "github.com/smartcontractkit/ccip-owner-contracts/pkg/proposal/timelock" + + "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/testcontext" + + cctypes "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/types" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/router" + + "github.com/smartcontractkit/chainlink/deployment" + + "github.com/stretchr/testify/require" + + jobv1 "github.com/smartcontractkit/chainlink-protos/job-distributor/v1/job" + + ccdeploy "github.com/smartcontractkit/chainlink/deployment/ccip" + + "github.com/smartcontractkit/chainlink/v2/core/logger" +) + +func TestActiveCandidate(t *testing.T) { + t.Skipf("to be enabled after latest cl-ccip is compatible") + + lggr := logger.TestLogger(t) + ctx := ccdeploy.Context(t) + tenv := ccdeploy.NewMemoryEnvironment(t, lggr, 3, 5, ccdeploy.MockLinkPrice, ccdeploy.MockWethPrice) + e := tenv.Env + + state, err := ccdeploy.LoadOnchainState(tenv.Env) + require.NoError(t, err) + require.NotNil(t, state.Chains[tenv.HomeChainSel].LinkToken) + + feeds := state.Chains[tenv.FeedChainSel].USDFeeds + tokenConfig := ccdeploy.NewTestTokenConfig(feeds) + + output, err := InitialDeploy(tenv.Env, ccdeploy.DeployCCIPContractConfig{ + HomeChainSel: tenv.HomeChainSel, + FeedChainSel: tenv.FeedChainSel, + ChainsToDeploy: tenv.Env.AllChainSelectors(), + TokenConfig: tokenConfig, + MCMSConfig: ccdeploy.NewTestMCMSConfig(t, e), + OCRSecrets: deployment.XXXGenerateTestOCRSecrets(), + }) + require.NoError(t, err) + // Get new state after migration. + require.NoError(t, tenv.Env.ExistingAddresses.Merge(output.AddressBook)) + state, err = ccdeploy.LoadOnchainState(tenv.Env) + require.NoError(t, err) + homeCS, destCS := tenv.HomeChainSel, tenv.FeedChainSel + + // Ensure capreg logs are up to date. + ccdeploy.ReplayLogs(t, e.Offchain, tenv.ReplayBlocks) + + // Apply the jobs. + for nodeID, jobs := range output.JobSpecs { + for _, job := range jobs { + // Note these auto-accept + _, err := e.Offchain.ProposeJob(ctx, + &jobv1.ProposeJobRequest{ + NodeId: nodeID, + Spec: job, + }) + require.NoError(t, err) + } + } + + // Add all lanes + require.NoError(t, ccdeploy.AddLanesForAll(e, state)) + // Need to keep track of the block number for each chain so that event subscription can be done from that block. + startBlocks := make(map[uint64]*uint64) + // Send a message from each chain to every other chain. + expectedSeqNum := make(map[uint64]uint64) + for src := range e.Chains { + for dest, destChain := range e.Chains { + if src == dest { + continue + } + latesthdr, err := destChain.Client.HeaderByNumber(testcontext.Get(t), nil) + require.NoError(t, err) + block := latesthdr.Number.Uint64() + startBlocks[dest] = &block + msgSentEvent := ccdeploy.TestSendRequest(t, e, state, src, dest, false, router.ClientEVM2AnyMessage{ + Receiver: common.LeftPadBytes(state.Chains[dest].Receiver.Address().Bytes(), 32), + Data: []byte("hello world"), + TokenAmounts: nil, + FeeToken: common.HexToAddress("0x0"), + ExtraArgs: nil, + }) + expectedSeqNum[dest] = msgSentEvent.SequenceNumber + } + } + + // Wait for all commit reports to land. + ccdeploy.ConfirmCommitForAllWithExpectedSeqNums(t, e, state, expectedSeqNum, startBlocks) + + //After commit is reported on all chains, token prices should be updated in FeeQuoter. + for dest := range e.Chains { + linkAddress := state.Chains[dest].LinkToken.Address() + feeQuoter := state.Chains[dest].FeeQuoter + timestampedPrice, err := feeQuoter.GetTokenPrice(nil, linkAddress) + require.NoError(t, err) + require.Equal(t, ccdeploy.MockLinkPrice, timestampedPrice.Value) + } + + //Wait for all exec reports to land + ccdeploy.ConfirmExecWithSeqNrForAll(t, e, state, expectedSeqNum, startBlocks) + + // transfer ownership + ccdeploy.TransferAllOwnership(t, state, homeCS, e) + acceptOwnershipProposal, err := ccdeploy.GenerateAcceptOwnershipProposal(state, homeCS, e.AllChainSelectors()) + require.NoError(t, err) + acceptOwnershipExec := ccdeploy.SignProposal(t, e, acceptOwnershipProposal) + for _, sel := range e.AllChainSelectors() { + ccdeploy.ExecuteProposal(t, e, acceptOwnershipExec, state, sel) + } + // Apply the accept ownership proposal to all the chains. + + err = ccdeploy.ConfirmRequestOnSourceAndDest(t, e, state, homeCS, destCS, 2) + require.NoError(t, err) + + // [ACTIVE, CANDIDATE] setup by setting candidate through cap reg + capReg, ccipHome := state.Chains[homeCS].CapabilityRegistry, state.Chains[homeCS].CCIPHome + donID, err := ccdeploy.DonIDForChain(capReg, ccipHome, destCS) + require.NoError(t, err) + donInfo, err := state.Chains[homeCS].CapabilityRegistry.GetDON(nil, donID) + require.NoError(t, err) + require.Equal(t, 5, len(donInfo.NodeP2PIds)) + require.Equal(t, uint32(4), donInfo.ConfigCount) + + state, err = ccdeploy.LoadOnchainState(e) + require.NoError(t, err) + + // delete a non-bootstrap node + nodes, err := deployment.NodeInfo(e.NodeIDs, e.Offchain) + require.NoError(t, err) + var newNodeIDs []string + // make sure we delete a node that is NOT bootstrap. + // we will remove bootstrap later by calling nodes.NonBootstrap() + if nodes[0].IsBootstrap { + newNodeIDs = e.NodeIDs[:len(e.NodeIDs)-1] + } else { + newNodeIDs = e.NodeIDs[1:] + } + nodes, err = deployment.NodeInfo(newNodeIDs, e.Offchain) + require.NoError(t, err) + + // this will construct ocr3 configurations for the + // commit and exec plugin we will be using + rmnHomeAddress := state.Chains[homeCS].RMNHome.Address() + ocr3ConfigMap, err := ccdeploy.BuildOCR3ConfigForCCIPHome( + deployment.XXXGenerateTestOCRSecrets(), + state.Chains[destCS].OffRamp, + e.Chains[destCS], + destCS, + tokenConfig.GetTokenInfo(e.Logger, state.Chains[destCS].LinkToken, state.Chains[destCS].Weth9), + nodes.NonBootstraps(), + rmnHomeAddress, + nil, + ) + require.NoError(t, err) + + setCommitCandidateOp, err := ccdeploy.SetCandidateOnExistingDon( + ocr3ConfigMap[cctypes.PluginTypeCCIPCommit], + state.Chains[homeCS].CapabilityRegistry, + state.Chains[homeCS].CCIPHome, + destCS, + nodes.NonBootstraps(), + ) + require.NoError(t, err) + setCommitCandidateProposal, err := ccdeploy.BuildProposalFromBatches(state, []timelock.BatchChainOperation{{ + ChainIdentifier: mcms.ChainIdentifier(homeCS), + Batch: setCommitCandidateOp, + }}, "set new candidates on commit plugin", 0) + require.NoError(t, err) + setCommitCandidateSigned := ccdeploy.SignProposal(t, e, setCommitCandidateProposal) + ccdeploy.ExecuteProposal(t, e, setCommitCandidateSigned, state, homeCS) + + // create the op for the commit plugin as well + setExecCandidateOp, err := ccdeploy.SetCandidateOnExistingDon( + ocr3ConfigMap[cctypes.PluginTypeCCIPExec], + state.Chains[homeCS].CapabilityRegistry, + state.Chains[homeCS].CCIPHome, + destCS, + nodes.NonBootstraps(), + ) + require.NoError(t, err) + + setExecCandidateProposal, err := ccdeploy.BuildProposalFromBatches(state, []timelock.BatchChainOperation{{ + ChainIdentifier: mcms.ChainIdentifier(homeCS), + Batch: setExecCandidateOp, + }}, "set new candidates on commit and exec plugins", 0) + require.NoError(t, err) + setExecCandidateSigned := ccdeploy.SignProposal(t, e, setExecCandidateProposal) + ccdeploy.ExecuteProposal(t, e, setExecCandidateSigned, state, homeCS) + + // check setup was successful by confirming number of nodes from cap reg + donInfo, err = state.Chains[homeCS].CapabilityRegistry.GetDON(nil, donID) + require.NoError(t, err) + require.Equal(t, 4, len(donInfo.NodeP2PIds)) + require.Equal(t, uint32(6), donInfo.ConfigCount) + // [ACTIVE, CANDIDATE] done setup + + // [ACTIVE, CANDIDATE] make sure we can still send successful transaction without updating job specs + err = ccdeploy.ConfirmRequestOnSourceAndDest(t, e, state, homeCS, destCS, 3) + require.NoError(t, err) + // [ACTIVE, CANDIDATE] done send successful transaction on active + + // [NEW ACTIVE, NO CANDIDATE] promote to active + // confirm by getting old candidate digest and making sure new active matches + oldCandidateDigest, err := state.Chains[homeCS].CCIPHome.GetCandidateDigest(nil, donID, uint8(cctypes.PluginTypeCCIPExec)) + require.NoError(t, err) + + promoteOps, err := ccdeploy.PromoteAllCandidatesForChainOps(state.Chains[homeCS].CapabilityRegistry, state.Chains[homeCS].CCIPHome, destCS, nodes.NonBootstraps()) + require.NoError(t, err) + promoteProposal, err := ccdeploy.BuildProposalFromBatches(state, []timelock.BatchChainOperation{{ + ChainIdentifier: mcms.ChainIdentifier(homeCS), + Batch: promoteOps, + }}, "promote candidates and revoke actives", 0) + require.NoError(t, err) + promoteSigned := ccdeploy.SignProposal(t, e, promoteProposal) + ccdeploy.ExecuteProposal(t, e, promoteSigned, state, homeCS) + // [NEW ACTIVE, NO CANDIDATE] done promoting + + // [NEW ACTIVE, NO CANDIDATE] check onchain state + newActiveDigest, err := state.Chains[homeCS].CCIPHome.GetActiveDigest(nil, donID, uint8(cctypes.PluginTypeCCIPExec)) + require.NoError(t, err) + require.Equal(t, oldCandidateDigest, newActiveDigest) + + newCandidateDigest, err := state.Chains[homeCS].CCIPHome.GetCandidateDigest(nil, donID, uint8(cctypes.PluginTypeCCIPCommit)) + require.NoError(t, err) + require.Equal(t, newCandidateDigest, [32]byte{}) + // [NEW ACTIVE, NO CANDIDATE] done checking on chain state + + // [NEW ACTIVE, NO CANDIDATE] send successful request on new active + donInfo, err = state.Chains[homeCS].CapabilityRegistry.GetDON(nil, donID) + require.NoError(t, err) + require.Equal(t, uint32(8), donInfo.ConfigCount) + + err = ccdeploy.ConfirmRequestOnSourceAndDest(t, e, state, homeCS, destCS, 4) + require.NoError(t, err) + // [NEW ACTIVE, NO CANDIDATE] done sending successful request +} diff --git a/deployment/ccip/changeset/add_chain.go b/deployment/ccip/changeset/add_chain.go new file mode 100644 index 00000000000..3ce6d17d24e --- /dev/null +++ b/deployment/ccip/changeset/add_chain.go @@ -0,0 +1,144 @@ +package changeset + +import ( + "fmt" + "math/big" + + ccipdeployment "github.com/smartcontractkit/chainlink/deployment/ccip" + + "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/types" + + "github.com/smartcontractkit/ccip-owner-contracts/pkg/proposal/mcms" + "github.com/smartcontractkit/ccip-owner-contracts/pkg/proposal/timelock" + + "github.com/smartcontractkit/chainlink/deployment" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/fee_quoter" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/onramp" +) + +// NewChainInboundChangeset generates a proposal +// to connect the new chain to the existing chains. +func NewChainInboundChangeset( + e deployment.Environment, + state ccipdeployment.CCIPOnChainState, + homeChainSel uint64, + newChainSel uint64, + sources []uint64, +) (deployment.ChangesetOutput, error) { + // Generate proposal which enables new destination (from test router) on all source chains. + var batches []timelock.BatchChainOperation + for _, source := range sources { + enableOnRampDest, err := state.Chains[source].OnRamp.ApplyDestChainConfigUpdates(deployment.SimTransactOpts(), []onramp.OnRampDestChainConfigArgs{ + { + DestChainSelector: newChainSel, + Router: state.Chains[source].TestRouter.Address(), + }, + }) + if err != nil { + return deployment.ChangesetOutput{}, err + } + enableFeeQuoterDest, err := state.Chains[source].FeeQuoter.ApplyDestChainConfigUpdates( + deployment.SimTransactOpts(), + []fee_quoter.FeeQuoterDestChainConfigArgs{ + { + DestChainSelector: newChainSel, + DestChainConfig: ccipdeployment.DefaultFeeQuoterDestChainConfig(), + }, + }) + if err != nil { + return deployment.ChangesetOutput{}, err + } + batches = append(batches, timelock.BatchChainOperation{ + ChainIdentifier: mcms.ChainIdentifier(source), + Batch: []mcms.Operation{ + { + // Enable the source in on ramp + To: state.Chains[source].OnRamp.Address(), + Data: enableOnRampDest.Data(), + Value: big.NewInt(0), + }, + { + To: state.Chains[source].FeeQuoter.Address(), + Data: enableFeeQuoterDest.Data(), + Value: big.NewInt(0), + }, + }, + }) + } + + addChainOp, err := ccipdeployment.ApplyChainConfigUpdatesOp(e, state, homeChainSel, []uint64{newChainSel}) + if err != nil { + return deployment.ChangesetOutput{}, err + } + + batches = append(batches, timelock.BatchChainOperation{ + ChainIdentifier: mcms.ChainIdentifier(homeChainSel), + Batch: []mcms.Operation{ + addChainOp, + }, + }) + + prop, err := ccipdeployment.BuildProposalFromBatches(state, batches, "proposal to set new chains", 0) + if err != nil { + return deployment.ChangesetOutput{}, err + } + + return deployment.ChangesetOutput{ + Proposals: []timelock.MCMSWithTimelockProposal{*prop}, + }, nil +} + +// AddDonAndSetCandidateChangeset adds new DON for destination to home chain +// and sets the commit plugin config as candidateConfig for the don. +func AddDonAndSetCandidateChangeset( + state ccipdeployment.CCIPOnChainState, + e deployment.Environment, + nodes deployment.Nodes, + ocrSecrets deployment.OCRSecrets, + homeChainSel, feedChainSel, newChainSel uint64, + tokenConfig ccipdeployment.TokenConfig, + pluginType types.PluginType, +) (deployment.ChangesetOutput, error) { + newDONArgs, err := ccipdeployment.BuildOCR3ConfigForCCIPHome( + ocrSecrets, + state.Chains[newChainSel].OffRamp, + e.Chains[newChainSel], + feedChainSel, + tokenConfig.GetTokenInfo(e.Logger, state.Chains[newChainSel].LinkToken, state.Chains[newChainSel].Weth9), + nodes.NonBootstraps(), + state.Chains[homeChainSel].RMNHome.Address(), + nil, + ) + if err != nil { + return deployment.ChangesetOutput{}, err + } + latestDon, err := ccipdeployment.LatestCCIPDON(state.Chains[homeChainSel].CapabilityRegistry) + if err != nil { + return deployment.ChangesetOutput{}, err + } + commitConfig, ok := newDONArgs[pluginType] + if !ok { + return deployment.ChangesetOutput{}, fmt.Errorf("missing commit plugin in ocr3Configs") + } + donID := latestDon.Id + 1 + addDonOp, err := ccipdeployment.NewDonWithCandidateOp( + donID, commitConfig, + state.Chains[homeChainSel].CapabilityRegistry, + nodes.NonBootstraps(), + ) + if err != nil { + return deployment.ChangesetOutput{}, err + } + + prop, err := ccipdeployment.BuildProposalFromBatches(state, []timelock.BatchChainOperation{{ + ChainIdentifier: mcms.ChainIdentifier(homeChainSel), + Batch: []mcms.Operation{addDonOp}, + }}, "setCandidate for commit and AddDon on new Chain", 0) + if err != nil { + return deployment.ChangesetOutput{}, err + } + + return deployment.ChangesetOutput{ + Proposals: []timelock.MCMSWithTimelockProposal{*prop}, + }, nil +} diff --git a/deployment/ccip/changeset/add_chain_test.go b/deployment/ccip/changeset/add_chain_test.go new file mode 100644 index 00000000000..2d79a76005d --- /dev/null +++ b/deployment/ccip/changeset/add_chain_test.go @@ -0,0 +1,240 @@ +package changeset + +import ( + "testing" + "time" + + ccipdeployment "github.com/smartcontractkit/chainlink/deployment/ccip" + + "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/types" + + "github.com/ethereum/go-ethereum/common" + + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/rmn_home" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + cciptypes "github.com/smartcontractkit/chainlink-ccip/pkg/types/ccipocr3" + commonutils "github.com/smartcontractkit/chainlink-common/pkg/utils" + + "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/testcontext" + + "github.com/smartcontractkit/chainlink/deployment" + + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/offramp" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/router" + "github.com/smartcontractkit/chainlink/v2/core/logger" +) + +func TestAddChainInbound(t *testing.T) { + // 4 chains where the 4th is added after initial deployment. + e := ccipdeployment.NewMemoryEnvironmentWithJobs(t, logger.TestLogger(t), 4, 4) + state, err := ccipdeployment.LoadOnchainState(e.Env) + require.NoError(t, err) + // Take first non-home chain as the new chain. + newChain := e.Env.AllChainSelectorsExcluding([]uint64{e.HomeChainSel})[0] + // We deploy to the rest. + initialDeploy := e.Env.AllChainSelectorsExcluding([]uint64{newChain}) + newAddresses := deployment.NewMemoryAddressBook() + err = ccipdeployment.DeployPrerequisiteChainContracts(e.Env, newAddresses, initialDeploy) + require.NoError(t, err) + require.NoError(t, e.Env.ExistingAddresses.Merge(newAddresses)) + + tokenConfig := ccipdeployment.NewTestTokenConfig(state.Chains[e.FeedChainSel].USDFeeds) + newAddresses = deployment.NewMemoryAddressBook() + err = ccipdeployment.DeployCCIPContracts(e.Env, newAddresses, ccipdeployment.DeployCCIPContractConfig{ + HomeChainSel: e.HomeChainSel, + FeedChainSel: e.FeedChainSel, + ChainsToDeploy: initialDeploy, + TokenConfig: tokenConfig, + MCMSConfig: ccipdeployment.NewTestMCMSConfig(t, e.Env), + OCRSecrets: deployment.XXXGenerateTestOCRSecrets(), + }) + require.NoError(t, err) + require.NoError(t, e.Env.ExistingAddresses.Merge(newAddresses)) + state, err = ccipdeployment.LoadOnchainState(e.Env) + require.NoError(t, err) + + // Connect all the existing lanes. + for _, source := range initialDeploy { + for _, dest := range initialDeploy { + if source != dest { + require.NoError(t, ccipdeployment.AddLaneWithDefaultPrices(e.Env, state, source, dest)) + } + } + } + + rmnHomeAddress, err := deployment.SearchAddressBook(e.Env.ExistingAddresses, e.HomeChainSel, ccipdeployment.RMNHome) + require.NoError(t, err) + require.True(t, common.IsHexAddress(rmnHomeAddress)) + rmnHome, err := rmn_home.NewRMNHome(common.HexToAddress(rmnHomeAddress), e.Env.Chains[e.HomeChainSel].Client) + require.NoError(t, err) + + // Deploy contracts to new chain + newAddresses = deployment.NewMemoryAddressBook() + err = ccipdeployment.DeployPrerequisiteChainContracts(e.Env, newAddresses, []uint64{newChain}) + require.NoError(t, err) + require.NoError(t, e.Env.ExistingAddresses.Merge(newAddresses)) + newAddresses = deployment.NewMemoryAddressBook() + err = ccipdeployment.DeployChainContracts(e.Env, + e.Env.Chains[newChain], newAddresses, + ccipdeployment.NewTestMCMSConfig(t, e.Env), rmnHome) + require.NoError(t, err) + require.NoError(t, e.Env.ExistingAddresses.Merge(newAddresses)) + state, err = ccipdeployment.LoadOnchainState(e.Env) + require.NoError(t, err) + + // Transfer onramp/fq ownership to timelock. + // Enable the new dest on the test router. + for _, source := range initialDeploy { + tx, err := state.Chains[source].OnRamp.TransferOwnership(e.Env.Chains[source].DeployerKey, state.Chains[source].Timelock.Address()) + require.NoError(t, err) + _, err = deployment.ConfirmIfNoError(e.Env.Chains[source], tx, err) + require.NoError(t, err) + tx, err = state.Chains[source].FeeQuoter.TransferOwnership(e.Env.Chains[source].DeployerKey, state.Chains[source].Timelock.Address()) + require.NoError(t, err) + _, err = deployment.ConfirmIfNoError(e.Env.Chains[source], tx, err) + require.NoError(t, err) + tx, err = state.Chains[source].TestRouter.ApplyRampUpdates(e.Env.Chains[source].DeployerKey, []router.RouterOnRamp{ + { + DestChainSelector: newChain, + OnRamp: state.Chains[source].OnRamp.Address(), + }, + }, nil, nil) + _, err = deployment.ConfirmIfNoError(e.Env.Chains[source], tx, err) + require.NoError(t, err) + } + // Transfer CR contract ownership + tx, err := state.Chains[e.HomeChainSel].CapabilityRegistry.TransferOwnership(e.Env.Chains[e.HomeChainSel].DeployerKey, state.Chains[e.HomeChainSel].Timelock.Address()) + require.NoError(t, err) + _, err = deployment.ConfirmIfNoError(e.Env.Chains[e.HomeChainSel], tx, err) + require.NoError(t, err) + tx, err = state.Chains[e.HomeChainSel].CCIPHome.TransferOwnership(e.Env.Chains[e.HomeChainSel].DeployerKey, state.Chains[e.HomeChainSel].Timelock.Address()) + require.NoError(t, err) + _, err = deployment.ConfirmIfNoError(e.Env.Chains[e.HomeChainSel], tx, err) + require.NoError(t, err) + + acceptOwnershipProposal, err := ccipdeployment.GenerateAcceptOwnershipProposal(state, e.HomeChainSel, initialDeploy) + require.NoError(t, err) + acceptOwnershipExec := ccipdeployment.SignProposal(t, e.Env, acceptOwnershipProposal) + // Apply the accept ownership proposal to all the chains. + for _, sel := range initialDeploy { + ccipdeployment.ExecuteProposal(t, e.Env, acceptOwnershipExec, state, sel) + } + for _, chain := range initialDeploy { + owner, err2 := state.Chains[chain].OnRamp.Owner(nil) + require.NoError(t, err2) + require.Equal(t, state.Chains[chain].Timelock.Address(), owner) + } + cfgOwner, err := state.Chains[e.HomeChainSel].CCIPHome.Owner(nil) + require.NoError(t, err) + crOwner, err := state.Chains[e.HomeChainSel].CapabilityRegistry.Owner(nil) + require.NoError(t, err) + require.Equal(t, state.Chains[e.HomeChainSel].Timelock.Address(), cfgOwner) + require.Equal(t, state.Chains[e.HomeChainSel].Timelock.Address(), crOwner) + + nodes, err := deployment.NodeInfo(e.Env.NodeIDs, e.Env.Offchain) + require.NoError(t, err) + + // Generate and sign inbound proposal to new 4th chain. + chainInboundChangeset, err := NewChainInboundChangeset(e.Env, state, e.HomeChainSel, newChain, initialDeploy) + require.NoError(t, err) + ccipdeployment.ProcessChangeset(t, e.Env, chainInboundChangeset) + + // TODO This currently is not working - Able to send the request here but request gets stuck in execution + // Send a new message and expect that this is delivered once the chain is completely set up as inbound + //TestSendRequest(t, e.Env, state, initialDeploy[0], newChain, true) + + t.Logf("Executing add don and set candidate proposal for commit plugin on chain %d", newChain) + addDonChangeset, err := AddDonAndSetCandidateChangeset(state, e.Env, nodes, deployment.XXXGenerateTestOCRSecrets(), e.HomeChainSel, e.FeedChainSel, newChain, tokenConfig, types.PluginTypeCCIPCommit) + require.NoError(t, err) + ccipdeployment.ProcessChangeset(t, e.Env, addDonChangeset) + + t.Logf("Executing promote candidate proposal for exec plugin on chain %d", newChain) + setCandidateForExecChangeset, err := SetCandidatePluginChangeset(state, e.Env, nodes, deployment.XXXGenerateTestOCRSecrets(), e.HomeChainSel, e.FeedChainSel, newChain, tokenConfig, types.PluginTypeCCIPExec) + require.NoError(t, err) + ccipdeployment.ProcessChangeset(t, e.Env, setCandidateForExecChangeset) + + t.Logf("Executing promote candidate proposal for both commit and exec plugins on chain %d", newChain) + donPromoteChangeset, err := PromoteAllCandidatesChangeset(state, e.HomeChainSel, newChain, nodes) + require.NoError(t, err) + ccipdeployment.ProcessChangeset(t, e.Env, donPromoteChangeset) + + // verify if the configs are updated + require.NoError(t, ccipdeployment.ValidateCCIPHomeConfigSetUp( + state.Chains[e.HomeChainSel].CapabilityRegistry, + state.Chains[e.HomeChainSel].CCIPHome, + newChain, + )) + replayBlocks, err := ccipdeployment.LatestBlocksByChain(testcontext.Get(t), e.Env.Chains) + require.NoError(t, err) + + // Now configure the new chain using deployer key (not transferred to timelock yet). + var offRampEnables []offramp.OffRampSourceChainConfigArgs + for _, source := range initialDeploy { + offRampEnables = append(offRampEnables, offramp.OffRampSourceChainConfigArgs{ + Router: state.Chains[newChain].Router.Address(), + SourceChainSelector: source, + IsEnabled: true, + OnRamp: common.LeftPadBytes(state.Chains[source].OnRamp.Address().Bytes(), 32), + }) + } + tx, err = state.Chains[newChain].OffRamp.ApplySourceChainConfigUpdates(e.Env.Chains[newChain].DeployerKey, offRampEnables) + require.NoError(t, err) + _, err = deployment.ConfirmIfNoError(e.Env.Chains[newChain], tx, err) + require.NoError(t, err) + // Set the OCR3 config on new 4th chain to enable the plugin. + latestDON, err := ccipdeployment.LatestCCIPDON(state.Chains[e.HomeChainSel].CapabilityRegistry) + require.NoError(t, err) + ocrConfigs, err := ccipdeployment.BuildSetOCR3ConfigArgs(latestDON.Id, state.Chains[e.HomeChainSel].CCIPHome, newChain) + require.NoError(t, err) + tx, err = state.Chains[newChain].OffRamp.SetOCR3Configs(e.Env.Chains[newChain].DeployerKey, ocrConfigs) + require.NoError(t, err) + _, err = deployment.ConfirmIfNoError(e.Env.Chains[newChain], tx, err) + require.NoError(t, err) + + // Assert the inbound lanes to the new chain are wired correctly. + state, err = ccipdeployment.LoadOnchainState(e.Env) + require.NoError(t, err) + for _, chain := range initialDeploy { + cfg, err2 := state.Chains[chain].OnRamp.GetDestChainConfig(nil, newChain) + require.NoError(t, err2) + assert.Equal(t, cfg.Router, state.Chains[chain].TestRouter.Address()) + fqCfg, err2 := state.Chains[chain].FeeQuoter.GetDestChainConfig(nil, newChain) + require.NoError(t, err2) + assert.True(t, fqCfg.IsEnabled) + s, err2 := state.Chains[newChain].OffRamp.GetSourceChainConfig(nil, chain) + require.NoError(t, err2) + assert.Equal(t, common.LeftPadBytes(state.Chains[chain].OnRamp.Address().Bytes(), 32), s.OnRamp) + } + // Ensure job related logs are up to date. + time.Sleep(30 * time.Second) + ccipdeployment.ReplayLogs(t, e.Env.Offchain, replayBlocks) + + // TODO: Send via all inbound lanes and use parallel helper + // Now that the proposal has been executed we expect to be able to send traffic to this new 4th chain. + latesthdr, err := e.Env.Chains[newChain].Client.HeaderByNumber(testcontext.Get(t), nil) + require.NoError(t, err) + startBlock := latesthdr.Number.Uint64() + msgSentEvent := ccipdeployment.TestSendRequest(t, e.Env, state, initialDeploy[0], newChain, true, router.ClientEVM2AnyMessage{ + Receiver: common.LeftPadBytes(state.Chains[newChain].Receiver.Address().Bytes(), 32), + Data: []byte("hello world"), + TokenAmounts: nil, + FeeToken: common.HexToAddress("0x0"), + ExtraArgs: nil, + }) + require.NoError(t, + ccipdeployment.ConfirmCommitWithExpectedSeqNumRange(t, e.Env.Chains[initialDeploy[0]], e.Env.Chains[newChain], state.Chains[newChain].OffRamp, &startBlock, cciptypes.SeqNumRange{ + cciptypes.SeqNum(1), + cciptypes.SeqNum(msgSentEvent.SequenceNumber), + })) + require.NoError(t, + commonutils.JustError(ccipdeployment.ConfirmExecWithSeqNr(t, e.Env.Chains[initialDeploy[0]], e.Env.Chains[newChain], state.Chains[newChain].OffRamp, &startBlock, msgSentEvent.SequenceNumber))) + + linkAddress := state.Chains[newChain].LinkToken.Address() + feeQuoter := state.Chains[newChain].FeeQuoter + timestampedPrice, err := feeQuoter.GetTokenPrice(nil, linkAddress) + require.NoError(t, err) + require.Equal(t, ccipdeployment.MockLinkPrice, timestampedPrice.Value) +} diff --git a/deployment/ccip/changeset/cs_add_lane_test.go b/deployment/ccip/changeset/cs_add_lane_test.go deleted file mode 100644 index e793c1866d9..00000000000 --- a/deployment/ccip/changeset/cs_add_lane_test.go +++ /dev/null @@ -1,124 +0,0 @@ -package changeset - -import ( - "math/big" - "testing" - - "github.com/ethereum/go-ethereum/common" - "github.com/stretchr/testify/require" - - "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/testcontext" - - commoncs "github.com/smartcontractkit/chainlink/deployment/common/changeset" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/fee_quoter" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/router" -) - -func TestAddLanesWithTestRouter(t *testing.T) { - t.Parallel() - e := NewMemoryEnvironment(t) - // Here we have CR + nodes set up, but no CCIP contracts deployed. - state, err := LoadOnchainState(e.Env) - require.NoError(t, err) - - selectors := e.Env.AllChainSelectors() - chain1, chain2 := selectors[0], selectors[1] - - stateChain1 := state.Chains[chain1] - e.Env, err = commoncs.ApplyChangesets(t, e.Env, e.TimelockContracts(t), []commoncs.ChangesetApplication{ - { - Changeset: commoncs.WrapChangeSet(UpdateOnRampsDests), - Config: UpdateOnRampDestsConfig{ - UpdatesByChain: map[uint64]map[uint64]OnRampDestinationUpdate{ - chain1: { - chain2: { - IsEnabled: true, - TestRouter: true, - AllowListEnabled: false, - }, - }, - }, - }, - }, - { - Changeset: commoncs.WrapChangeSet(UpdateFeeQuoterPricesCS), - Config: UpdateFeeQuoterPricesConfig{ - PricesByChain: map[uint64]FeeQuoterPriceUpdatePerSource{ - chain1: { - TokenPrices: map[common.Address]*big.Int{ - stateChain1.LinkToken.Address(): DefaultLinkPrice, - stateChain1.Weth9.Address(): DefaultWethPrice, - }, - GasPrices: map[uint64]*big.Int{ - chain2: DefaultGasPrice, - }, - }, - }, - }, - }, - { - Changeset: commoncs.WrapChangeSet(UpdateFeeQuoterDests), - Config: UpdateFeeQuoterDestsConfig{ - UpdatesByChain: map[uint64]map[uint64]fee_quoter.FeeQuoterDestChainConfig{ - chain1: { - chain2: DefaultFeeQuoterDestChainConfig(), - }, - }, - }, - }, - { - Changeset: commoncs.WrapChangeSet(UpdateOffRampSources), - Config: UpdateOffRampSourcesConfig{ - UpdatesByChain: map[uint64]map[uint64]OffRampSourceUpdate{ - chain2: { - chain1: { - IsEnabled: true, - TestRouter: true, - }, - }, - }, - }, - }, - { - Changeset: commoncs.WrapChangeSet(UpdateRouterRamps), - Config: UpdateRouterRampsConfig{ - TestRouter: true, - UpdatesByChain: map[uint64]RouterUpdates{ - // onRamp update on source chain - chain1: { - OnRampUpdates: map[uint64]bool{ - chain2: true, - }, - }, - // offramp update on dest chain - chain2: { - OffRampUpdates: map[uint64]bool{ - chain1: true, - }, - }, - }, - }, - }, - }) - require.NoError(t, err) - // Need to keep track of the block number for each chain so that event subscription can be done from that block. - startBlocks := make(map[uint64]*uint64) - // Send a message from each chain to every other chain. - expectedSeqNumExec := make(map[SourceDestPair][]uint64) - latesthdr, err := e.Env.Chains[chain2].Client.HeaderByNumber(testcontext.Get(t), nil) - require.NoError(t, err) - block := latesthdr.Number.Uint64() - startBlocks[chain2] = &block - msgSentEvent := TestSendRequest(t, e.Env, state, chain1, chain2, true, router.ClientEVM2AnyMessage{ - Receiver: common.LeftPadBytes(state.Chains[chain2].Receiver.Address().Bytes(), 32), - Data: []byte("hello"), - TokenAmounts: nil, - FeeToken: common.HexToAddress("0x0"), - ExtraArgs: nil, - }) - expectedSeqNumExec[SourceDestPair{ - SourceChainSelector: chain1, - DestChainSelector: chain2, - }] = []uint64{msgSentEvent.SequenceNumber} - ConfirmExecWithSeqNrsForAll(t, e.Env, state, expectedSeqNumExec, startBlocks) -} diff --git a/deployment/ccip/changeset/cs_ccip_home.go b/deployment/ccip/changeset/cs_ccip_home.go deleted file mode 100644 index 0c82afee261..00000000000 --- a/deployment/ccip/changeset/cs_ccip_home.go +++ /dev/null @@ -1,1212 +0,0 @@ -package changeset - -import ( - "bytes" - "encoding/hex" - "fmt" - "math/big" - "os" - "time" - - "github.com/ethereum/go-ethereum/accounts/abi/bind" - "github.com/ethereum/go-ethereum/common" - "github.com/smartcontractkit/ccip-owner-contracts/pkg/gethwrappers" - "github.com/smartcontractkit/ccip-owner-contracts/pkg/proposal/mcms" - "github.com/smartcontractkit/ccip-owner-contracts/pkg/proposal/timelock" - - "github.com/smartcontractkit/chainlink-ccip/chainconfig" - "github.com/smartcontractkit/chainlink-ccip/pkg/types/ccipocr3" - "github.com/smartcontractkit/chainlink-ccip/pluginconfig" - "github.com/smartcontractkit/chainlink-common/pkg/config" - "github.com/smartcontractkit/chainlink-common/pkg/logger" - "github.com/smartcontractkit/chainlink-common/pkg/merklemulti" - - "github.com/smartcontractkit/chainlink/deployment" - "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/internal" - commoncs "github.com/smartcontractkit/chainlink/deployment/common/changeset" - "github.com/smartcontractkit/chainlink/deployment/common/proposalutils" - commontypes "github.com/smartcontractkit/chainlink/deployment/common/types" - "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/types" - cctypes "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/types" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/ccip_home" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry_1_1_0" -) - -var ( - _ deployment.ChangeSet[AddDonAndSetCandidateChangesetConfig] = AddDonAndSetCandidateChangeset - _ deployment.ChangeSet[PromoteCandidatesChangesetConfig] = PromoteAllCandidatesChangeset - _ deployment.ChangeSet[SetCandidateChangesetConfig] = SetCandidateChangeset - _ deployment.ChangeSet[RevokeCandidateChangesetConfig] = RevokeCandidateChangeset - _ deployment.ChangeSet[UpdateChainConfigConfig] = UpdateChainConfig -) - -type CCIPOCRParams struct { - OCRParameters commontypes.OCRParameters - // Note contains pointers to Arb feeds for prices - CommitOffChainConfig pluginconfig.CommitOffchainConfig - // Note ontains USDC config - ExecuteOffChainConfig pluginconfig.ExecuteOffchainConfig -} - -func (c CCIPOCRParams) Validate() error { - if err := c.OCRParameters.Validate(); err != nil { - return fmt.Errorf("invalid OCR parameters: %w", err) - } - if err := c.CommitOffChainConfig.Validate(); err != nil { - return fmt.Errorf("invalid commit off-chain config: %w", err) - } - if err := c.ExecuteOffChainConfig.Validate(); err != nil { - return fmt.Errorf("invalid execute off-chain config: %w", err) - } - return nil -} - -// DefaultOCRParams returns the default OCR parameters for a chain, -// except for a few values which must be parameterized (passed as arguments). -func DefaultOCRParams( - feedChainSel uint64, - tokenInfo map[ccipocr3.UnknownEncodedAddress]pluginconfig.TokenInfo, - tokenDataObservers []pluginconfig.TokenDataObserverConfig, -) CCIPOCRParams { - return CCIPOCRParams{ - OCRParameters: commontypes.OCRParameters{ - DeltaProgress: internal.DeltaProgress, - DeltaResend: internal.DeltaResend, - DeltaInitial: internal.DeltaInitial, - DeltaRound: internal.DeltaRound, - DeltaGrace: internal.DeltaGrace, - DeltaCertifiedCommitRequest: internal.DeltaCertifiedCommitRequest, - DeltaStage: internal.DeltaStage, - Rmax: internal.Rmax, - MaxDurationQuery: internal.MaxDurationQuery, - MaxDurationObservation: internal.MaxDurationObservation, - MaxDurationShouldAcceptAttestedReport: internal.MaxDurationShouldAcceptAttestedReport, - MaxDurationShouldTransmitAcceptedReport: internal.MaxDurationShouldTransmitAcceptedReport, - }, - ExecuteOffChainConfig: pluginconfig.ExecuteOffchainConfig{ - BatchGasLimit: internal.BatchGasLimit, - RelativeBoostPerWaitHour: internal.RelativeBoostPerWaitHour, - InflightCacheExpiry: *config.MustNewDuration(internal.InflightCacheExpiry), - RootSnoozeTime: *config.MustNewDuration(internal.RootSnoozeTime), - MessageVisibilityInterval: *config.MustNewDuration(internal.FirstBlockAge), - BatchingStrategyID: internal.BatchingStrategyID, - TokenDataObservers: tokenDataObservers, - }, - CommitOffChainConfig: pluginconfig.CommitOffchainConfig{ - RemoteGasPriceBatchWriteFrequency: *config.MustNewDuration(internal.RemoteGasPriceBatchWriteFrequency), - TokenPriceBatchWriteFrequency: *config.MustNewDuration(internal.TokenPriceBatchWriteFrequency), - TokenInfo: tokenInfo, - PriceFeedChainSelector: ccipocr3.ChainSelector(feedChainSel), - NewMsgScanBatchSize: merklemulti.MaxNumberTreeLeaves, - MaxReportTransmissionCheckAttempts: 5, - RMNEnabled: os.Getenv("ENABLE_RMN") == "true", // only enabled in manual test - RMNSignaturesTimeout: 30 * time.Minute, - MaxMerkleTreeSize: merklemulti.MaxNumberTreeLeaves, - SignObservationPrefix: "chainlink ccip 1.6 rmn observation", - }, - } -} - -type PromoteCandidatesChangesetConfig struct { - HomeChainSelector uint64 - - // RemoteChainSelectors is the chain selector of the DONs that we want to promote the candidate config of. - // Note that each (chain, ccip capability version) pair has a unique DON ID. - RemoteChainSelectors []uint64 - - PluginType types.PluginType - // MCMS is optional MCMS configuration, if provided the changeset will generate an MCMS proposal. - // If nil, the changeset will execute the commands directly using the deployer key - // of the provided environment. - MCMS *MCMSConfig -} - -func (p PromoteCandidatesChangesetConfig) Validate(e deployment.Environment) ([]uint32, error) { - state, err := LoadOnchainState(e) - if err != nil { - return nil, err - } - if err := deployment.IsValidChainSelector(p.HomeChainSelector); err != nil { - return nil, fmt.Errorf("home chain selector invalid: %w", err) - } - homeChainState, exists := state.Chains[p.HomeChainSelector] - if !exists { - return nil, fmt.Errorf("home chain %d does not exist", p.HomeChainSelector) - } - if err := commoncs.ValidateOwnership(e.GetContext(), p.MCMS != nil, e.Chains[p.HomeChainSelector].DeployerKey.From, homeChainState.Timelock.Address(), homeChainState.CapabilityRegistry); err != nil { - return nil, err - } - - if p.PluginType != types.PluginTypeCCIPCommit && - p.PluginType != types.PluginTypeCCIPExec { - return nil, fmt.Errorf("PluginType must be set to either CCIPCommit or CCIPExec") - } - - var donIDs []uint32 - for _, chainSelector := range p.RemoteChainSelectors { - if err := deployment.IsValidChainSelector(chainSelector); err != nil { - return nil, fmt.Errorf("don chain selector invalid: %w", err) - } - chainState, exists := state.Chains[chainSelector] - if !exists { - return nil, fmt.Errorf("chain %d does not exist", chainSelector) - } - if chainState.OffRamp == nil { - // should not be possible, but a defensive check. - return nil, fmt.Errorf("OffRamp contract does not exist") - } - - donID, err := internal.DonIDForChain( - state.Chains[p.HomeChainSelector].CapabilityRegistry, - state.Chains[p.HomeChainSelector].CCIPHome, - chainSelector, - ) - if err != nil { - return nil, fmt.Errorf("fetch don id for chain: %w", err) - } - if donID == 0 { - return nil, fmt.Errorf("don doesn't exist in CR for chain %d", chainSelector) - } - // Check that candidate digest and active digest are not both zero - this is enforced onchain. - pluginConfigs, err := state.Chains[p.HomeChainSelector].CCIPHome.GetAllConfigs(&bind.CallOpts{ - Context: e.GetContext(), - }, donID, uint8(p.PluginType)) - if err != nil { - return nil, fmt.Errorf("fetching %s configs from cciphome: %w", p.PluginType.String(), err) - } - - if pluginConfigs.ActiveConfig.ConfigDigest == [32]byte{} && - pluginConfigs.CandidateConfig.ConfigDigest == [32]byte{} { - return nil, fmt.Errorf("%s active and candidate config digests are both zero", p.PluginType.String()) - } - donIDs = append(donIDs, donID) - } - if len(e.NodeIDs) == 0 { - return nil, fmt.Errorf("NodeIDs must be set") - } - if state.Chains[p.HomeChainSelector].CCIPHome == nil { - return nil, fmt.Errorf("CCIPHome contract does not exist") - } - if state.Chains[p.HomeChainSelector].CapabilityRegistry == nil { - return nil, fmt.Errorf("CapabilityRegistry contract does not exist") - } - - return donIDs, nil -} - -// PromoteAllCandidatesChangeset generates a proposal to call promoteCandidate on the CCIPHome through CapReg. -// Note that a DON must exist prior to being able to use this changeset effectively, -// i.e AddDonAndSetCandidateChangeset must be called first. -// This can also be used to promote a 0x0 candidate config to be the active, effectively shutting down the DON. -// At that point you can call the RemoveDON changeset to remove the DON entirely from the capability registry. -func PromoteAllCandidatesChangeset( - e deployment.Environment, - cfg PromoteCandidatesChangesetConfig, -) (deployment.ChangesetOutput, error) { - donIDs, err := cfg.Validate(e) - if err != nil { - return deployment.ChangesetOutput{}, fmt.Errorf("%w: %w", deployment.ErrInvalidConfig, err) - } - state, err := LoadOnchainState(e) - if err != nil { - return deployment.ChangesetOutput{}, err - } - - nodes, err := deployment.NodeInfo(e.NodeIDs, e.Offchain) - if err != nil { - return deployment.ChangesetOutput{}, fmt.Errorf("fetch node info: %w", err) - } - - txOpts := e.Chains[cfg.HomeChainSelector].DeployerKey - if cfg.MCMS != nil { - txOpts = deployment.SimTransactOpts() - } - - homeChain := e.Chains[cfg.HomeChainSelector] - - var ops []mcms.Operation - for _, donID := range donIDs { - promoteCandidateOps, err := promoteAllCandidatesForChainOps( - txOpts, - homeChain, - state.Chains[cfg.HomeChainSelector].CapabilityRegistry, - state.Chains[cfg.HomeChainSelector].CCIPHome, - nodes.NonBootstraps(), - donID, - cfg.PluginType, - cfg.MCMS != nil, - ) - if err != nil { - return deployment.ChangesetOutput{}, fmt.Errorf("generating promote candidate ops: %w", err) - } - ops = append(ops, promoteCandidateOps) - } - - // Disabled MCMS means that we already executed the txes, so just return early w/out the proposals. - if cfg.MCMS == nil { - return deployment.ChangesetOutput{}, nil - } - - prop, err := proposalutils.BuildProposalFromBatches( - map[uint64]common.Address{ - cfg.HomeChainSelector: state.Chains[cfg.HomeChainSelector].Timelock.Address(), - }, - map[uint64]*gethwrappers.ManyChainMultiSig{ - cfg.HomeChainSelector: state.Chains[cfg.HomeChainSelector].ProposerMcm, - }, - []timelock.BatchChainOperation{{ - ChainIdentifier: mcms.ChainIdentifier(cfg.HomeChainSelector), - Batch: ops, - }}, - "promoteCandidate for commit and execution", - cfg.MCMS.MinDelay, - ) - if err != nil { - return deployment.ChangesetOutput{}, err - } - return deployment.ChangesetOutput{ - Proposals: []timelock.MCMSWithTimelockProposal{ - *prop, - }, - }, nil -} - -// SetCandidateConfigBase is a common base config struct for AddDonAndSetCandidateChangesetConfig and SetCandidateChangesetConfig. -// This is extracted to deduplicate most of the validation logic. -// Remaining validation logic is done in the specific config structs that inherit from this. -type SetCandidateConfigBase struct { - HomeChainSelector uint64 - FeedChainSelector uint64 - - // OCRConfigPerRemoteChainSelector is the chain selector of the chain where the DON will be added. - OCRConfigPerRemoteChainSelector map[uint64]CCIPOCRParams - - // Only set one plugin at a time. TODO - // come back and allow both. - PluginType types.PluginType - - // MCMS is optional MCMS configuration, if provided the changeset will generate an MCMS proposal. - // If nil, the changeset will execute the commands directly using the deployer key - // of the provided environment. - MCMS *MCMSConfig -} - -func (s SetCandidateConfigBase) Validate(e deployment.Environment, state CCIPOnChainState) error { - if err := deployment.IsValidChainSelector(s.HomeChainSelector); err != nil { - return fmt.Errorf("home chain selector invalid: %w", err) - } - if err := deployment.IsValidChainSelector(s.FeedChainSelector); err != nil { - return fmt.Errorf("feed chain selector invalid: %w", err) - } - homeChainState, exists := state.Chains[s.HomeChainSelector] - if !exists { - return fmt.Errorf("home chain %d does not exist", s.HomeChainSelector) - } - if err := commoncs.ValidateOwnership(e.GetContext(), s.MCMS != nil, e.Chains[s.HomeChainSelector].DeployerKey.From, homeChainState.Timelock.Address(), homeChainState.CapabilityRegistry); err != nil { - return err - } - - for chainSelector, params := range s.OCRConfigPerRemoteChainSelector { - if err := deployment.IsValidChainSelector(chainSelector); err != nil { - return fmt.Errorf("don chain selector invalid: %w", err) - } - if state.Chains[chainSelector].OffRamp == nil { - // should not be possible, but a defensive check. - return fmt.Errorf("OffRamp contract does not exist on don chain selector %d", chainSelector) - } - if s.PluginType != types.PluginTypeCCIPCommit && - s.PluginType != types.PluginTypeCCIPExec { - return fmt.Errorf("PluginType must be set to either CCIPCommit or CCIPExec") - } - - // no donID check since this config is used for both adding a new DON and updating an existing one. - // see AddDonAndSetCandidateChangesetConfig.Validate and SetCandidateChangesetConfig.Validate - // for these checks. - // check that chain config is set up for the new chain - chainConfig, err := state.Chains[s.HomeChainSelector].CCIPHome.GetChainConfig(nil, chainSelector) - if err != nil { - return fmt.Errorf("get all chain configs: %w", err) - } - // FChain should never be zero if a chain config is set in CCIPHome - if chainConfig.FChain == 0 { - return fmt.Errorf("chain config not set up for new chain %d", chainSelector) - } - err = params.Validate() - if err != nil { - return fmt.Errorf("invalid ccip ocr params: %w", err) - } - - // TODO: validate token config in the commit config, if commit is the plugin. - // TODO: validate gas config in the chain config in cciphome for this RemoteChainSelectors. - } - if len(e.NodeIDs) == 0 { - return fmt.Errorf("nodeIDs must be set") - } - if state.Chains[s.HomeChainSelector].CCIPHome == nil { - return fmt.Errorf("CCIPHome contract does not exist") - } - if state.Chains[s.HomeChainSelector].CapabilityRegistry == nil { - return fmt.Errorf("CapabilityRegistry contract does not exist") - } - - if e.OCRSecrets.IsEmpty() { - return fmt.Errorf("OCR secrets must be set") - } - - return nil -} - -// AddDonAndSetCandidateChangesetConfig is a separate config struct -// because the validation is slightly different from SetCandidateChangesetConfig. -// In particular, we check to make sure we don't already have a DON for the chain. -type AddDonAndSetCandidateChangesetConfig struct { - SetCandidateConfigBase -} - -func (a AddDonAndSetCandidateChangesetConfig) Validate(e deployment.Environment, state CCIPOnChainState) error { - err := a.SetCandidateConfigBase.Validate(e, state) - if err != nil { - return err - } - - for chainSelector := range a.OCRConfigPerRemoteChainSelector { - // check if a DON already exists for this chain - donID, err := internal.DonIDForChain( - state.Chains[a.HomeChainSelector].CapabilityRegistry, - state.Chains[a.HomeChainSelector].CCIPHome, - chainSelector, - ) - if err != nil { - return fmt.Errorf("fetch don id for chain: %w", err) - } - if donID != 0 { - return fmt.Errorf("don already exists in CR for chain %d, it has id %d", chainSelector, donID) - } - } - - return nil -} - -// AddDonAndSetCandidateChangeset adds new DON for destination to home chain -// and sets the plugin config as candidateConfig for the don. -// -// This is the first step to creating a CCIP DON and must be executed before any -// other changesets (SetCandidateChangeset, PromoteAllCandidatesChangeset) -// can be executed. -// -// Note that these operations must be done together because the createDON call -// in the capability registry calls the capability config contract, so we must -// provide suitable calldata for CCIPHome. -func AddDonAndSetCandidateChangeset( - e deployment.Environment, - cfg AddDonAndSetCandidateChangesetConfig, -) (deployment.ChangesetOutput, error) { - state, err := LoadOnchainState(e) - if err != nil { - return deployment.ChangesetOutput{}, err - } - - err = cfg.Validate(e, state) - if err != nil { - return deployment.ChangesetOutput{}, fmt.Errorf("%w: %w", deployment.ErrInvalidConfig, err) - } - - nodes, err := deployment.NodeInfo(e.NodeIDs, e.Offchain) - if err != nil { - return deployment.ChangesetOutput{}, fmt.Errorf("get node info: %w", err) - } - - txOpts := e.Chains[cfg.HomeChainSelector].DeployerKey - if cfg.MCMS != nil { - txOpts = deployment.SimTransactOpts() - } - var donOps []mcms.Operation - for chainSelector, params := range cfg.OCRConfigPerRemoteChainSelector { - newDONArgs, err := internal.BuildOCR3ConfigForCCIPHome( - e.OCRSecrets, - state.Chains[chainSelector].OffRamp, - e.Chains[chainSelector], - nodes.NonBootstraps(), - state.Chains[cfg.HomeChainSelector].RMNHome.Address(), - params.OCRParameters, - params.CommitOffChainConfig, - params.ExecuteOffChainConfig, - ) - if err != nil { - return deployment.ChangesetOutput{}, err - } - - latestDon, err := internal.LatestCCIPDON(state.Chains[cfg.HomeChainSelector].CapabilityRegistry) - if err != nil { - return deployment.ChangesetOutput{}, err - } - - pluginOCR3Config, ok := newDONArgs[cfg.PluginType] - if !ok { - return deployment.ChangesetOutput{}, fmt.Errorf("missing commit plugin in ocr3Configs") - } - - expectedDonID := latestDon.Id + 1 - addDonOp, err := newDonWithCandidateOp( - txOpts, - e.Chains[cfg.HomeChainSelector], - expectedDonID, - pluginOCR3Config, - state.Chains[cfg.HomeChainSelector].CapabilityRegistry, - nodes.NonBootstraps(), - cfg.MCMS != nil, - ) - if err != nil { - return deployment.ChangesetOutput{}, err - } - donOps = append(donOps, addDonOp) - } - if cfg.MCMS == nil { - return deployment.ChangesetOutput{}, nil - } - - prop, err := proposalutils.BuildProposalFromBatches( - map[uint64]common.Address{ - cfg.HomeChainSelector: state.Chains[cfg.HomeChainSelector].Timelock.Address(), - }, - map[uint64]*gethwrappers.ManyChainMultiSig{ - cfg.HomeChainSelector: state.Chains[cfg.HomeChainSelector].ProposerMcm, - }, - []timelock.BatchChainOperation{{ - ChainIdentifier: mcms.ChainIdentifier(cfg.HomeChainSelector), - Batch: donOps, - }}, - fmt.Sprintf("addDON on new Chain && setCandidate for plugin %s", cfg.PluginType.String()), - cfg.MCMS.MinDelay, - ) - if err != nil { - return deployment.ChangesetOutput{}, fmt.Errorf("failed to build proposal from batch: %w", err) - } - - return deployment.ChangesetOutput{ - Proposals: []timelock.MCMSWithTimelockProposal{*prop}, - }, nil -} - -// newDonWithCandidateOp sets the candidate commit config by calling setCandidate on CCIPHome contract through the AddDON call on CapReg contract -// This should be done first before calling any other UpdateDON calls -// This proposes to set up OCR3 config for the commit plugin for the DON -func newDonWithCandidateOp( - txOpts *bind.TransactOpts, - homeChain deployment.Chain, - donID uint32, - pluginConfig ccip_home.CCIPHomeOCR3Config, - capReg *capabilities_registry.CapabilitiesRegistry, - nodes deployment.Nodes, - mcmsEnabled bool, -) (mcms.Operation, error) { - encodedSetCandidateCall, err := internal.CCIPHomeABI.Pack( - "setCandidate", - donID, - pluginConfig.PluginType, - pluginConfig, - [32]byte{}, - ) - if err != nil { - return mcms.Operation{}, fmt.Errorf("pack set candidate call: %w", err) - } - - addDonTx, err := capReg.AddDON( - txOpts, - nodes.PeerIDs(), - []capabilities_registry.CapabilitiesRegistryCapabilityConfiguration{ - { - CapabilityId: internal.CCIPCapabilityID, - Config: encodedSetCandidateCall, - }, - }, - false, // isPublic - false, // acceptsWorkflows - nodes.DefaultF(), - ) - if err != nil { - return mcms.Operation{}, fmt.Errorf("could not generate add don tx w/ commit config: %w", err) - } - if !mcmsEnabled { - _, err = deployment.ConfirmIfNoError(homeChain, addDonTx, err) - if err != nil { - return mcms.Operation{}, fmt.Errorf("error confirming addDon call: %w", err) - } - } - - return mcms.Operation{ - To: capReg.Address(), - Data: addDonTx.Data(), - Value: big.NewInt(0), - }, nil -} - -type SetCandidateChangesetConfig struct { - SetCandidateConfigBase -} - -func (s SetCandidateChangesetConfig) Validate(e deployment.Environment, state CCIPOnChainState) (map[uint64]uint32, error) { - err := s.SetCandidateConfigBase.Validate(e, state) - if err != nil { - return nil, err - } - - chainToDonIDs := make(map[uint64]uint32) - for chainSelector := range s.OCRConfigPerRemoteChainSelector { - donID, err := internal.DonIDForChain( - state.Chains[s.HomeChainSelector].CapabilityRegistry, - state.Chains[s.HomeChainSelector].CCIPHome, - chainSelector, - ) - if err != nil { - return nil, fmt.Errorf("fetch don id for chain: %w", err) - } - if donID == 0 { - return nil, fmt.Errorf("don doesn't exist in CR for chain %d", chainSelector) - } - chainToDonIDs[chainSelector] = donID - } - - return chainToDonIDs, nil -} - -// SetCandidateChangeset generates a proposal to call setCandidate on the CCIPHome through the capability registry. -// A DON must exist in order to use this changeset effectively, i.e AddDonAndSetCandidateChangeset must be called first. -func SetCandidateChangeset( - e deployment.Environment, - cfg SetCandidateChangesetConfig, -) (deployment.ChangesetOutput, error) { - state, err := LoadOnchainState(e) - if err != nil { - return deployment.ChangesetOutput{}, err - } - - chainToDonIDs, err := cfg.Validate(e, state) - if err != nil { - return deployment.ChangesetOutput{}, fmt.Errorf("%w: %w", deployment.ErrInvalidConfig, err) - } - - nodes, err := deployment.NodeInfo(e.NodeIDs, e.Offchain) - if err != nil { - return deployment.ChangesetOutput{}, fmt.Errorf("get node info: %w", err) - } - - txOpts := e.Chains[cfg.HomeChainSelector].DeployerKey - if cfg.MCMS != nil { - txOpts = deployment.SimTransactOpts() - } - var setCandidateOps []mcms.Operation - for chainSelector, params := range cfg.OCRConfigPerRemoteChainSelector { - newDONArgs, err := internal.BuildOCR3ConfigForCCIPHome( - e.OCRSecrets, - state.Chains[chainSelector].OffRamp, - e.Chains[chainSelector], - nodes.NonBootstraps(), - state.Chains[cfg.HomeChainSelector].RMNHome.Address(), - params.OCRParameters, - params.CommitOffChainConfig, - params.ExecuteOffChainConfig, - ) - if err != nil { - return deployment.ChangesetOutput{}, err - } - - config, ok := newDONArgs[cfg.PluginType] - if !ok { - return deployment.ChangesetOutput{}, fmt.Errorf("missing %s plugin in ocr3Configs", cfg.PluginType.String()) - } - - setCandidateMCMSOps, err := setCandidateOnExistingDon( - txOpts, - e.Chains[cfg.HomeChainSelector], - state.Chains[cfg.HomeChainSelector].CapabilityRegistry, - nodes.NonBootstraps(), - chainToDonIDs[chainSelector], - config, - cfg.MCMS != nil, - ) - if err != nil { - return deployment.ChangesetOutput{}, err - } - setCandidateOps = append(setCandidateOps, setCandidateMCMSOps...) - } - - if cfg.MCMS == nil { - return deployment.ChangesetOutput{}, nil - } - - prop, err := proposalutils.BuildProposalFromBatches( - map[uint64]common.Address{ - cfg.HomeChainSelector: state.Chains[cfg.HomeChainSelector].Timelock.Address(), - }, - map[uint64]*gethwrappers.ManyChainMultiSig{ - cfg.HomeChainSelector: state.Chains[cfg.HomeChainSelector].ProposerMcm, - }, - []timelock.BatchChainOperation{{ - ChainIdentifier: mcms.ChainIdentifier(cfg.HomeChainSelector), - Batch: setCandidateOps, - }}, - fmt.Sprintf("SetCandidate for %s plugin", cfg.PluginType.String()), - cfg.MCMS.MinDelay, - ) - if err != nil { - return deployment.ChangesetOutput{}, err - } - return deployment.ChangesetOutput{ - Proposals: []timelock.MCMSWithTimelockProposal{ - *prop, - }, - }, nil -} - -// setCandidateOnExistingDon calls setCandidate on CCIPHome contract through the UpdateDON call on CapReg contract -// This proposes to set up OCR3 config for the provided plugin for the DON -func setCandidateOnExistingDon( - txOpts *bind.TransactOpts, - homeChain deployment.Chain, - capReg *capabilities_registry.CapabilitiesRegistry, - nodes deployment.Nodes, - donID uint32, - pluginConfig ccip_home.CCIPHomeOCR3Config, - mcmsEnabled bool, -) ([]mcms.Operation, error) { - if donID == 0 { - return nil, fmt.Errorf("donID is zero") - } - - encodedSetCandidateCall, err := internal.CCIPHomeABI.Pack( - "setCandidate", - donID, - pluginConfig.PluginType, - pluginConfig, - [32]byte{}, - ) - if err != nil { - return nil, fmt.Errorf("pack set candidate call: %w", err) - } - - // set candidate call - updateDonTx, err := capReg.UpdateDON( - txOpts, - donID, - nodes.PeerIDs(), - []capabilities_registry.CapabilitiesRegistryCapabilityConfiguration{ - { - CapabilityId: internal.CCIPCapabilityID, - Config: encodedSetCandidateCall, - }, - }, - false, - nodes.DefaultF(), - ) - if err != nil { - return nil, fmt.Errorf("update don w/ setCandidate call: %w", err) - } - if !mcmsEnabled { - _, err = deployment.ConfirmIfNoError(homeChain, updateDonTx, err) - if err != nil { - return nil, fmt.Errorf("error confirming updateDon call: %w", err) - } - } - if !mcmsEnabled { - _, err = deployment.ConfirmIfNoError(homeChain, updateDonTx, err) - if err != nil { - return nil, fmt.Errorf("error confirming updateDon call: %w", err) - } - } - - return []mcms.Operation{{ - To: capReg.Address(), - Data: updateDonTx.Data(), - Value: big.NewInt(0), - }}, nil -} - -// promoteCandidateOp will create the MCMS Operation for `promoteCandidateAndRevokeActive` directed towards the capabilityRegistry -func promoteCandidateOp( - txOpts *bind.TransactOpts, - homeChain deployment.Chain, - capReg *capabilities_registry.CapabilitiesRegistry, - ccipHome *ccip_home.CCIPHome, - nodes deployment.Nodes, - donID uint32, - pluginType uint8, - mcmsEnabled bool, -) (mcms.Operation, error) { - allConfigs, err := ccipHome.GetAllConfigs(nil, donID, pluginType) - if err != nil { - return mcms.Operation{}, err - } - - encodedPromotionCall, err := internal.CCIPHomeABI.Pack( - "promoteCandidateAndRevokeActive", - donID, - pluginType, - allConfigs.CandidateConfig.ConfigDigest, - allConfigs.ActiveConfig.ConfigDigest, - ) - if err != nil { - return mcms.Operation{}, fmt.Errorf("pack promotion call: %w", err) - } - - updateDonTx, err := capReg.UpdateDON( - txOpts, - donID, - nodes.PeerIDs(), - []capabilities_registry.CapabilitiesRegistryCapabilityConfiguration{ - { - CapabilityId: internal.CCIPCapabilityID, - Config: encodedPromotionCall, - }, - }, - false, - nodes.DefaultF(), - ) - if err != nil { - return mcms.Operation{}, fmt.Errorf("error creating updateDon op for donID(%d) and plugin type (%d): %w", donID, pluginType, err) - } - if !mcmsEnabled { - _, err = deployment.ConfirmIfNoError(homeChain, updateDonTx, err) - if err != nil { - return mcms.Operation{}, fmt.Errorf("error confirming updateDon call for donID(%d) and plugin type (%d): %w", donID, pluginType, err) - } - } - - return mcms.Operation{ - To: capReg.Address(), - Data: updateDonTx.Data(), - Value: big.NewInt(0), - }, nil -} - -// promoteAllCandidatesForChainOps promotes the candidate commit and exec configs to active by calling promoteCandidateAndRevokeActive on CCIPHome through the UpdateDON call on CapReg contract -func promoteAllCandidatesForChainOps( - txOpts *bind.TransactOpts, - homeChain deployment.Chain, - capReg *capabilities_registry.CapabilitiesRegistry, - ccipHome *ccip_home.CCIPHome, - nodes deployment.Nodes, - donID uint32, - pluginType cctypes.PluginType, - mcmsEnabled bool, -) (mcms.Operation, error) { - if donID == 0 { - return mcms.Operation{}, fmt.Errorf("donID is zero") - } - - updatePluginOp, err := promoteCandidateOp( - txOpts, - homeChain, - capReg, - ccipHome, - nodes, - donID, - uint8(pluginType), - mcmsEnabled, - ) - if err != nil { - return mcms.Operation{}, fmt.Errorf("promote candidate op for plugin %s: %w", pluginType.String(), err) - } - return updatePluginOp, nil -} - -type RevokeCandidateChangesetConfig struct { - HomeChainSelector uint64 - - // RemoteChainSelector is the chain selector whose candidate config we want to revoke. - RemoteChainSelector uint64 - PluginType types.PluginType - - // MCMS is optional MCMS configuration, if provided the changeset will generate an MCMS proposal. - // If nil, the changeset will execute the commands directly using the deployer key - // of the provided environment. - MCMS *MCMSConfig -} - -func (r RevokeCandidateChangesetConfig) Validate(e deployment.Environment, state CCIPOnChainState) (donID uint32, err error) { - if err := deployment.IsValidChainSelector(r.HomeChainSelector); err != nil { - return 0, fmt.Errorf("home chain selector invalid: %w", err) - } - if err := deployment.IsValidChainSelector(r.RemoteChainSelector); err != nil { - return 0, fmt.Errorf("don chain selector invalid: %w", err) - } - if len(e.NodeIDs) == 0 { - return 0, fmt.Errorf("NodeIDs must be set") - } - if state.Chains[r.HomeChainSelector].CCIPHome == nil { - return 0, fmt.Errorf("CCIPHome contract does not exist") - } - if state.Chains[r.HomeChainSelector].CapabilityRegistry == nil { - return 0, fmt.Errorf("CapabilityRegistry contract does not exist") - } - homeChainState, exists := state.Chains[r.HomeChainSelector] - if !exists { - return 0, fmt.Errorf("home chain %d does not exist", r.HomeChainSelector) - } - if err := commoncs.ValidateOwnership(e.GetContext(), r.MCMS != nil, e.Chains[r.HomeChainSelector].DeployerKey.From, homeChainState.Timelock.Address(), homeChainState.CapabilityRegistry); err != nil { - return 0, err - } - - // check that the don exists for this chain - donID, err = internal.DonIDForChain( - state.Chains[r.HomeChainSelector].CapabilityRegistry, - state.Chains[r.HomeChainSelector].CCIPHome, - r.RemoteChainSelector, - ) - if err != nil { - return 0, fmt.Errorf("fetch don id for chain: %w", err) - } - if donID == 0 { - return 0, fmt.Errorf("don doesn't exist in CR for chain %d", r.RemoteChainSelector) - } - - // check that candidate digest is not zero - this is enforced onchain. - candidateDigest, err := state.Chains[r.HomeChainSelector].CCIPHome.GetCandidateDigest(nil, donID, uint8(r.PluginType)) - if err != nil { - return 0, fmt.Errorf("fetching candidate digest from cciphome: %w", err) - } - if candidateDigest == [32]byte{} { - return 0, fmt.Errorf("candidate config digest is zero, can't revoke it") - } - - return donID, nil -} - -func RevokeCandidateChangeset(e deployment.Environment, cfg RevokeCandidateChangesetConfig) (deployment.ChangesetOutput, error) { - state, err := LoadOnchainState(e) - if err != nil { - return deployment.ChangesetOutput{}, err - } - - donID, err := cfg.Validate(e, state) - if err != nil { - return deployment.ChangesetOutput{}, fmt.Errorf("%w: %w", deployment.ErrInvalidConfig, err) - } - - nodes, err := deployment.NodeInfo(e.NodeIDs, e.Offchain) - if err != nil { - return deployment.ChangesetOutput{}, fmt.Errorf("fetch nodes info: %w", err) - } - - txOpts := e.Chains[cfg.HomeChainSelector].DeployerKey - if cfg.MCMS != nil { - txOpts = deployment.SimTransactOpts() - } - - homeChain := e.Chains[cfg.HomeChainSelector] - ops, err := revokeCandidateOps( - txOpts, - homeChain, - state.Chains[cfg.HomeChainSelector].CapabilityRegistry, - state.Chains[cfg.HomeChainSelector].CCIPHome, - nodes.NonBootstraps(), - donID, - uint8(cfg.PluginType), - cfg.MCMS != nil, - ) - if err != nil { - return deployment.ChangesetOutput{}, fmt.Errorf("revoke candidate ops: %w", err) - } - if cfg.MCMS == nil { - return deployment.ChangesetOutput{}, nil - } - - prop, err := proposalutils.BuildProposalFromBatches( - map[uint64]common.Address{ - cfg.HomeChainSelector: state.Chains[cfg.HomeChainSelector].Timelock.Address(), - }, - map[uint64]*gethwrappers.ManyChainMultiSig{ - cfg.HomeChainSelector: state.Chains[cfg.HomeChainSelector].ProposerMcm, - }, - []timelock.BatchChainOperation{{ - ChainIdentifier: mcms.ChainIdentifier(cfg.HomeChainSelector), - Batch: ops, - }}, - fmt.Sprintf("revokeCandidate for don %d", cfg.RemoteChainSelector), - cfg.MCMS.MinDelay, - ) - if err != nil { - return deployment.ChangesetOutput{}, err - } - - return deployment.ChangesetOutput{ - Proposals: []timelock.MCMSWithTimelockProposal{ - *prop, - }, - }, nil -} - -func revokeCandidateOps( - txOpts *bind.TransactOpts, - homeChain deployment.Chain, - capReg *capabilities_registry.CapabilitiesRegistry, - ccipHome *ccip_home.CCIPHome, - nodes deployment.Nodes, - donID uint32, - pluginType uint8, - mcmsEnabled bool, -) ([]mcms.Operation, error) { - if donID == 0 { - return nil, fmt.Errorf("donID is zero") - } - - candidateDigest, err := ccipHome.GetCandidateDigest(nil, donID, pluginType) - if err != nil { - return nil, fmt.Errorf("fetching candidate digest from cciphome: %w", err) - } - - encodedRevokeCandidateCall, err := internal.CCIPHomeABI.Pack( - "revokeCandidate", - donID, - pluginType, - candidateDigest, - ) - if err != nil { - return nil, fmt.Errorf("pack set candidate call: %w", err) - } - - updateDonTx, err := capReg.UpdateDON( - txOpts, - donID, - nodes.PeerIDs(), - []capabilities_registry.CapabilitiesRegistryCapabilityConfiguration{ - { - CapabilityId: internal.CCIPCapabilityID, - Config: encodedRevokeCandidateCall, - }, - }, - false, // isPublic - nodes.DefaultF(), - ) - if err != nil { - return nil, fmt.Errorf("update don w/ revokeCandidate call: %w", deployment.MaybeDataErr(err)) - } - if !mcmsEnabled { - _, err = deployment.ConfirmIfNoError(homeChain, updateDonTx, err) - if err != nil { - return nil, fmt.Errorf("error confirming updateDon call: %w", err) - } - } - - return []mcms.Operation{{ - To: capReg.Address(), - Data: updateDonTx.Data(), - Value: big.NewInt(0), - }}, nil -} - -type ChainConfig struct { - Readers [][32]byte - FChain uint8 - EncodableChainConfig chainconfig.ChainConfig -} - -type UpdateChainConfigConfig struct { - HomeChainSelector uint64 - RemoteChainRemoves []uint64 - RemoteChainAdds map[uint64]ChainConfig - MCMS *MCMSConfig -} - -func (c UpdateChainConfigConfig) Validate(e deployment.Environment) error { - state, err := LoadOnchainState(e) - if err != nil { - return err - } - if err := deployment.IsValidChainSelector(c.HomeChainSelector); err != nil { - return fmt.Errorf("home chain selector invalid: %w", err) - } - if len(c.RemoteChainRemoves) == 0 && len(c.RemoteChainAdds) == 0 { - return fmt.Errorf("no chain adds or removes") - } - homeChainState, exists := state.Chains[c.HomeChainSelector] - if !exists { - return fmt.Errorf("home chain %d does not exist", c.HomeChainSelector) - } - if err := commoncs.ValidateOwnership(e.GetContext(), c.MCMS != nil, e.Chains[c.HomeChainSelector].DeployerKey.From, homeChainState.Timelock.Address(), homeChainState.CCIPHome); err != nil { - return err - } - for _, remove := range c.RemoteChainRemoves { - if err := deployment.IsValidChainSelector(remove); err != nil { - return fmt.Errorf("chain remove selector invalid: %w", err) - } - if _, ok := state.SupportedChains()[remove]; !ok { - return fmt.Errorf("chain to remove %d is not supported", remove) - } - } - for add, ccfg := range c.RemoteChainAdds { - if err := deployment.IsValidChainSelector(add); err != nil { - return fmt.Errorf("chain remove selector invalid: %w", err) - } - if _, ok := state.SupportedChains()[add]; !ok { - return fmt.Errorf("chain to add %d is not supported", add) - } - if ccfg.FChain == 0 { - return fmt.Errorf("FChain must be set") - } - if len(ccfg.Readers) == 0 { - return fmt.Errorf("Readers must be set") - } - } - return nil -} - -func UpdateChainConfig(e deployment.Environment, cfg UpdateChainConfigConfig) (deployment.ChangesetOutput, error) { - if err := cfg.Validate(e); err != nil { - return deployment.ChangesetOutput{}, fmt.Errorf("%w: %w", deployment.ErrInvalidConfig, err) - } - state, err := LoadOnchainState(e) - if err != nil { - return deployment.ChangesetOutput{}, err - } - txOpts := e.Chains[cfg.HomeChainSelector].DeployerKey - txOpts.Context = e.GetContext() - if cfg.MCMS != nil { - txOpts = deployment.SimTransactOpts() - } - var adds []ccip_home.CCIPHomeChainConfigArgs - for chain, ccfg := range cfg.RemoteChainAdds { - encodedChainConfig, err := chainconfig.EncodeChainConfig(chainconfig.ChainConfig{ - GasPriceDeviationPPB: ccfg.EncodableChainConfig.GasPriceDeviationPPB, - DAGasPriceDeviationPPB: ccfg.EncodableChainConfig.DAGasPriceDeviationPPB, - OptimisticConfirmations: ccfg.EncodableChainConfig.OptimisticConfirmations, - }) - if err != nil { - return deployment.ChangesetOutput{}, fmt.Errorf("encoding chain config: %w", err) - } - chainConfig := ccip_home.CCIPHomeChainConfig{ - Readers: ccfg.Readers, - FChain: ccfg.FChain, - Config: encodedChainConfig, - } - existingCfg, err := state.Chains[cfg.HomeChainSelector].CCIPHome.GetChainConfig(nil, chain) - if err != nil { - return deployment.ChangesetOutput{}, fmt.Errorf("get chain config for selector %d: %w", chain, err) - } - if isChainConfigEqual(existingCfg, chainConfig) { - e.Logger.Infow("Chain config already exists, not applying again", - "addedChain", chain, - "chainConfig", chainConfig, - ) - continue - } - adds = append(adds, ccip_home.CCIPHomeChainConfigArgs{ - ChainSelector: chain, - ChainConfig: chainConfig, - }) - } - - tx, err := state.Chains[cfg.HomeChainSelector].CCIPHome.ApplyChainConfigUpdates(txOpts, cfg.RemoteChainRemoves, adds) - if cfg.MCMS == nil { - _, err = deployment.ConfirmIfNoError(e.Chains[cfg.HomeChainSelector], tx, err) - if err != nil { - return deployment.ChangesetOutput{}, err - } - e.Logger.Infof("Updated chain config on chain %d removes %v, adds %v", cfg.HomeChainSelector, cfg.RemoteChainRemoves, cfg.RemoteChainAdds) - return deployment.ChangesetOutput{}, nil - } - - p, err := proposalutils.BuildProposalFromBatches( - map[uint64]common.Address{ - cfg.HomeChainSelector: state.Chains[cfg.HomeChainSelector].Timelock.Address(), - }, - map[uint64]*gethwrappers.ManyChainMultiSig{ - cfg.HomeChainSelector: state.Chains[cfg.HomeChainSelector].ProposerMcm, - }, - []timelock.BatchChainOperation{{ - ChainIdentifier: mcms.ChainIdentifier(cfg.HomeChainSelector), - Batch: []mcms.Operation{ - { - To: state.Chains[cfg.HomeChainSelector].CCIPHome.Address(), - Data: tx.Data(), - Value: big.NewInt(0), - }, - }, - }}, - "Update chain config", - cfg.MCMS.MinDelay, - ) - if err != nil { - return deployment.ChangesetOutput{}, err - } - e.Logger.Infof("Proposed chain config update on chain %d removes %v, adds %v", cfg.HomeChainSelector, cfg.RemoteChainRemoves, cfg.RemoteChainAdds) - return deployment.ChangesetOutput{Proposals: []timelock.MCMSWithTimelockProposal{ - *p, - }}, nil -} - -func isChainConfigEqual(a, b ccip_home.CCIPHomeChainConfig) bool { - mapReader := make(map[[32]byte]struct{}) - for i := range a.Readers { - mapReader[a.Readers[i]] = struct{}{} - } - for i := range b.Readers { - if _, ok := mapReader[b.Readers[i]]; !ok { - return false - } - } - return bytes.Equal(a.Config, b.Config) && - a.FChain == b.FChain -} - -// ValidateCCIPHomeConfigSetUp checks that the commit and exec active and candidate configs are set up correctly -// TODO: Utilize this -func ValidateCCIPHomeConfigSetUp( - lggr logger.Logger, - capReg *capabilities_registry.CapabilitiesRegistry, - ccipHome *ccip_home.CCIPHome, - chainSel uint64, -) error { - // fetch DONID - donID, err := internal.DonIDForChain(capReg, ccipHome, chainSel) - if err != nil { - return fmt.Errorf("fetch don id for chain: %w", err) - } - if donID == 0 { - return fmt.Errorf("don id for chain (%d) does not exist", chainSel) - } - - // final sanity checks on configs. - commitConfigs, err := ccipHome.GetAllConfigs(&bind.CallOpts{ - //Pending: true, - }, donID, uint8(cctypes.PluginTypeCCIPCommit)) - if err != nil { - return fmt.Errorf("get all commit configs: %w", err) - } - commitActiveDigest, err := ccipHome.GetActiveDigest(nil, donID, uint8(cctypes.PluginTypeCCIPCommit)) - if err != nil { - return fmt.Errorf("get active commit digest: %w", err) - } - lggr.Debugw("Fetched active commit digest", "commitActiveDigest", hex.EncodeToString(commitActiveDigest[:])) - commitCandidateDigest, err := ccipHome.GetCandidateDigest(nil, donID, uint8(cctypes.PluginTypeCCIPCommit)) - if err != nil { - return fmt.Errorf("get commit candidate digest: %w", err) - } - lggr.Debugw("Fetched candidate commit digest", "commitCandidateDigest", hex.EncodeToString(commitCandidateDigest[:])) - if commitConfigs.ActiveConfig.ConfigDigest == [32]byte{} { - return fmt.Errorf( - "active config digest is empty for commit, expected nonempty, donID: %d, cfg: %+v, config digest from GetActiveDigest call: %x, config digest from GetCandidateDigest call: %x", - donID, commitConfigs.ActiveConfig, commitActiveDigest, commitCandidateDigest) - } - if commitConfigs.CandidateConfig.ConfigDigest != [32]byte{} { - return fmt.Errorf( - "candidate config digest is nonempty for commit, expected empty, donID: %d, cfg: %+v, config digest from GetCandidateDigest call: %x, config digest from GetActiveDigest call: %x", - donID, commitConfigs.CandidateConfig, commitCandidateDigest, commitActiveDigest) - } - - execConfigs, err := ccipHome.GetAllConfigs(nil, donID, uint8(cctypes.PluginTypeCCIPExec)) - if err != nil { - return fmt.Errorf("get all exec configs: %w", err) - } - lggr.Debugw("Fetched exec configs", - "ActiveConfig.ConfigDigest", hex.EncodeToString(execConfigs.ActiveConfig.ConfigDigest[:]), - "CandidateConfig.ConfigDigest", hex.EncodeToString(execConfigs.CandidateConfig.ConfigDigest[:]), - ) - if execConfigs.ActiveConfig.ConfigDigest == [32]byte{} { - return fmt.Errorf("active config digest is empty for exec, expected nonempty, cfg: %v", execConfigs.ActiveConfig) - } - if execConfigs.CandidateConfig.ConfigDigest != [32]byte{} { - return fmt.Errorf("candidate config digest is nonempty for exec, expected empty, cfg: %v", execConfigs.CandidateConfig) - } - return nil -} diff --git a/deployment/ccip/changeset/cs_ccip_home_test.go b/deployment/ccip/changeset/cs_ccip_home_test.go deleted file mode 100644 index dae32557f8b..00000000000 --- a/deployment/ccip/changeset/cs_ccip_home_test.go +++ /dev/null @@ -1,529 +0,0 @@ -package changeset - -import ( - "math/big" - "testing" - - "github.com/ethereum/go-ethereum/accounts/abi/bind" - "github.com/stretchr/testify/assert" - "golang.org/x/exp/maps" - - "github.com/smartcontractkit/chainlink-ccip/chainconfig" - cciptypes "github.com/smartcontractkit/chainlink-ccip/pkg/types/ccipocr3" - "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/testcontext" - - "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/internal" - "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/types" - "github.com/smartcontractkit/chainlink/v2/core/logger" - - "github.com/stretchr/testify/require" - - commonchangeset "github.com/smartcontractkit/chainlink/deployment/common/changeset" - "github.com/smartcontractkit/chainlink/deployment/common/proposalutils" -) - -func Test_PromoteCandidate(t *testing.T) { - for _, tc := range []struct { - name string - mcmsEnabled bool - }{ - { - name: "MCMS enabled", - mcmsEnabled: true, - }, - { - name: "MCMS disabled", - mcmsEnabled: false, - }, - } { - t.Run(tc.name, func(t *testing.T) { - ctx := testcontext.Get(t) - tenv := NewMemoryEnvironment(t, - WithChains(2), - WithNodes(4)) - state, err := LoadOnchainState(tenv.Env) - require.NoError(t, err) - - // Deploy to all chains. - allChains := maps.Keys(tenv.Env.Chains) - source := allChains[0] - dest := allChains[1] - - if tc.mcmsEnabled { - // Transfer ownership to timelock so that we can promote the zero digest later down the line. - transferToTimelock(t, tenv, state, source, dest) - } - - var ( - capReg = state.Chains[tenv.HomeChainSel].CapabilityRegistry - ccipHome = state.Chains[tenv.HomeChainSel].CCIPHome - ) - donID, err := internal.DonIDForChain(capReg, ccipHome, dest) - require.NoError(t, err) - require.NotEqual(t, uint32(0), donID) - t.Logf("donID: %d", donID) - candidateDigestCommitBefore, err := ccipHome.GetCandidateDigest(&bind.CallOpts{ - Context: ctx, - }, donID, uint8(types.PluginTypeCCIPCommit)) - require.NoError(t, err) - require.Equal(t, [32]byte{}, candidateDigestCommitBefore) - ActiveDigestExecBefore, err := ccipHome.GetActiveDigest(&bind.CallOpts{ - Context: ctx, - }, donID, uint8(types.PluginTypeCCIPExec)) - require.NoError(t, err) - require.NotEqual(t, [32]byte{}, ActiveDigestExecBefore) - - var mcmsConfig *MCMSConfig - if tc.mcmsEnabled { - mcmsConfig = &MCMSConfig{ - MinDelay: 0, - } - } - // promotes zero digest on commit and ensure exec is not affected - _, err = commonchangeset.ApplyChangesets(t, tenv.Env, map[uint64]*proposalutils.TimelockExecutionContracts{ - tenv.HomeChainSel: { - Timelock: state.Chains[tenv.HomeChainSel].Timelock, - CallProxy: state.Chains[tenv.HomeChainSel].CallProxy, - }, - }, []commonchangeset.ChangesetApplication{ - { - Changeset: commonchangeset.WrapChangeSet(PromoteAllCandidatesChangeset), - Config: PromoteCandidatesChangesetConfig{ - HomeChainSelector: tenv.HomeChainSel, - RemoteChainSelectors: []uint64{dest}, - MCMS: mcmsConfig, - PluginType: types.PluginTypeCCIPCommit, - }, - }, - }) - require.NoError(t, err) - - // after promoting the zero digest, active digest should also be zero - activeDigestCommit, err := ccipHome.GetActiveDigest(&bind.CallOpts{ - Context: ctx, - }, donID, uint8(types.PluginTypeCCIPCommit)) - require.NoError(t, err) - require.Equal(t, [32]byte{}, activeDigestCommit) - - activeDigestExec, err := ccipHome.GetActiveDigest(&bind.CallOpts{ - Context: ctx, - }, donID, uint8(types.PluginTypeCCIPExec)) - require.NoError(t, err) - require.Equal(t, ActiveDigestExecBefore, activeDigestExec) - }) - } -} - -func Test_SetCandidate(t *testing.T) { - for _, tc := range []struct { - name string - mcmsEnabled bool - }{ - { - name: "MCMS enabled", - mcmsEnabled: true, - }, - { - name: "MCMS disabled", - mcmsEnabled: false, - }, - } { - t.Run(tc.name, func(t *testing.T) { - ctx := testcontext.Get(t) - tenv := NewMemoryEnvironment(t, - WithChains(2), - WithNodes(4)) - state, err := LoadOnchainState(tenv.Env) - require.NoError(t, err) - - // Deploy to all chains. - allChains := maps.Keys(tenv.Env.Chains) - source := allChains[0] - dest := allChains[1] - - if tc.mcmsEnabled { - // Transfer ownership to timelock so that we can promote the zero digest later down the line. - transferToTimelock(t, tenv, state, source, dest) - } - - var ( - capReg = state.Chains[tenv.HomeChainSel].CapabilityRegistry - ccipHome = state.Chains[tenv.HomeChainSel].CCIPHome - ) - donID, err := internal.DonIDForChain(capReg, ccipHome, dest) - require.NoError(t, err) - require.NotEqual(t, uint32(0), donID) - candidateDigestCommitBefore, err := ccipHome.GetCandidateDigest(&bind.CallOpts{ - Context: ctx, - }, donID, uint8(types.PluginTypeCCIPCommit)) - require.NoError(t, err) - require.Equal(t, [32]byte{}, candidateDigestCommitBefore) - candidateDigestExecBefore, err := ccipHome.GetCandidateDigest(&bind.CallOpts{ - Context: ctx, - }, donID, uint8(types.PluginTypeCCIPExec)) - require.NoError(t, err) - require.Equal(t, [32]byte{}, candidateDigestExecBefore) - - var mcmsConfig *MCMSConfig - if tc.mcmsEnabled { - mcmsConfig = &MCMSConfig{ - MinDelay: 0, - } - } - tokenConfig := NewTestTokenConfig(state.Chains[tenv.FeedChainSel].USDFeeds) - _, err = commonchangeset.ApplyChangesets(t, tenv.Env, map[uint64]*proposalutils.TimelockExecutionContracts{ - tenv.HomeChainSel: { - Timelock: state.Chains[tenv.HomeChainSel].Timelock, - CallProxy: state.Chains[tenv.HomeChainSel].CallProxy, - }, - }, []commonchangeset.ChangesetApplication{ - { - Changeset: commonchangeset.WrapChangeSet(SetCandidateChangeset), - Config: SetCandidateChangesetConfig{ - SetCandidateConfigBase: SetCandidateConfigBase{ - HomeChainSelector: tenv.HomeChainSel, - FeedChainSelector: tenv.FeedChainSel, - OCRConfigPerRemoteChainSelector: map[uint64]CCIPOCRParams{ - dest: DefaultOCRParams( - tenv.FeedChainSel, - tokenConfig.GetTokenInfo(logger.TestLogger(t), state.Chains[dest].LinkToken, state.Chains[dest].Weth9), - nil, - ), - }, - PluginType: types.PluginTypeCCIPCommit, - MCMS: mcmsConfig, - }, - }, - }, - { - Changeset: commonchangeset.WrapChangeSet(SetCandidateChangeset), - Config: SetCandidateChangesetConfig{ - SetCandidateConfigBase: SetCandidateConfigBase{ - HomeChainSelector: tenv.HomeChainSel, - FeedChainSelector: tenv.FeedChainSel, - OCRConfigPerRemoteChainSelector: map[uint64]CCIPOCRParams{ - dest: DefaultOCRParams( - tenv.FeedChainSel, - tokenConfig.GetTokenInfo(logger.TestLogger(t), state.Chains[dest].LinkToken, state.Chains[dest].Weth9), - nil, - ), - }, - PluginType: types.PluginTypeCCIPExec, - MCMS: mcmsConfig, - }, - }, - }, - }) - require.NoError(t, err) - - // after setting a new candidate on both plugins, the candidate config digest - // should be nonzero. - candidateDigestCommitAfter, err := ccipHome.GetCandidateDigest(&bind.CallOpts{ - Context: ctx, - }, donID, uint8(types.PluginTypeCCIPCommit)) - require.NoError(t, err) - require.NotEqual(t, [32]byte{}, candidateDigestCommitAfter) - require.NotEqual(t, candidateDigestCommitBefore, candidateDigestCommitAfter) - - candidateDigestExecAfter, err := ccipHome.GetCandidateDigest(&bind.CallOpts{ - Context: ctx, - }, donID, uint8(types.PluginTypeCCIPExec)) - require.NoError(t, err) - require.NotEqual(t, [32]byte{}, candidateDigestExecAfter) - require.NotEqual(t, candidateDigestExecBefore, candidateDigestExecAfter) - }) - } -} - -func Test_RevokeCandidate(t *testing.T) { - for _, tc := range []struct { - name string - mcmsEnabled bool - }{ - { - name: "MCMS enabled", - mcmsEnabled: true, - }, - { - name: "MCMS disabled", - mcmsEnabled: false, - }, - } { - t.Run(tc.name, func(t *testing.T) { - ctx := testcontext.Get(t) - tenv := NewMemoryEnvironment(t, - WithChains(2), - WithNodes(4)) - state, err := LoadOnchainState(tenv.Env) - require.NoError(t, err) - - // Deploy to all chains. - allChains := maps.Keys(tenv.Env.Chains) - source := allChains[0] - dest := allChains[1] - - if tc.mcmsEnabled { - // Transfer ownership to timelock so that we can promote the zero digest later down the line. - transferToTimelock(t, tenv, state, source, dest) - } - - var ( - capReg = state.Chains[tenv.HomeChainSel].CapabilityRegistry - ccipHome = state.Chains[tenv.HomeChainSel].CCIPHome - ) - donID, err := internal.DonIDForChain(capReg, ccipHome, dest) - require.NoError(t, err) - require.NotEqual(t, uint32(0), donID) - candidateDigestCommitBefore, err := ccipHome.GetCandidateDigest(&bind.CallOpts{ - Context: ctx, - }, donID, uint8(types.PluginTypeCCIPCommit)) - require.NoError(t, err) - require.Equal(t, [32]byte{}, candidateDigestCommitBefore) - candidateDigestExecBefore, err := ccipHome.GetCandidateDigest(&bind.CallOpts{ - Context: ctx, - }, donID, uint8(types.PluginTypeCCIPExec)) - require.NoError(t, err) - require.Equal(t, [32]byte{}, candidateDigestExecBefore) - - var mcmsConfig *MCMSConfig - if tc.mcmsEnabled { - mcmsConfig = &MCMSConfig{ - MinDelay: 0, - } - } - tokenConfig := NewTestTokenConfig(state.Chains[tenv.FeedChainSel].USDFeeds) - _, err = commonchangeset.ApplyChangesets(t, tenv.Env, map[uint64]*proposalutils.TimelockExecutionContracts{ - tenv.HomeChainSel: { - Timelock: state.Chains[tenv.HomeChainSel].Timelock, - CallProxy: state.Chains[tenv.HomeChainSel].CallProxy, - }, - }, []commonchangeset.ChangesetApplication{ - { - Changeset: commonchangeset.WrapChangeSet(SetCandidateChangeset), - Config: SetCandidateChangesetConfig{ - SetCandidateConfigBase: SetCandidateConfigBase{ - HomeChainSelector: tenv.HomeChainSel, - FeedChainSelector: tenv.FeedChainSel, - OCRConfigPerRemoteChainSelector: map[uint64]CCIPOCRParams{ - dest: DefaultOCRParams( - tenv.FeedChainSel, - tokenConfig.GetTokenInfo(logger.TestLogger(t), state.Chains[dest].LinkToken, state.Chains[dest].Weth9), - nil, - ), - }, - PluginType: types.PluginTypeCCIPCommit, - MCMS: mcmsConfig, - }, - }, - }, - { - Changeset: commonchangeset.WrapChangeSet(SetCandidateChangeset), - Config: SetCandidateChangesetConfig{ - SetCandidateConfigBase: SetCandidateConfigBase{ - HomeChainSelector: tenv.HomeChainSel, - FeedChainSelector: tenv.FeedChainSel, - OCRConfigPerRemoteChainSelector: map[uint64]CCIPOCRParams{ - dest: DefaultOCRParams( - tenv.FeedChainSel, - tokenConfig.GetTokenInfo(logger.TestLogger(t), state.Chains[dest].LinkToken, state.Chains[dest].Weth9), - nil, - ), - }, - PluginType: types.PluginTypeCCIPExec, - MCMS: mcmsConfig, - }, - }, - }, - }) - require.NoError(t, err) - - // after setting a new candidate on both plugins, the candidate config digest - // should be nonzero. - candidateDigestCommitAfter, err := ccipHome.GetCandidateDigest(&bind.CallOpts{ - Context: ctx, - }, donID, uint8(types.PluginTypeCCIPCommit)) - require.NoError(t, err) - require.NotEqual(t, [32]byte{}, candidateDigestCommitAfter) - require.NotEqual(t, candidateDigestCommitBefore, candidateDigestCommitAfter) - - candidateDigestExecAfter, err := ccipHome.GetCandidateDigest(&bind.CallOpts{ - Context: ctx, - }, donID, uint8(types.PluginTypeCCIPExec)) - require.NoError(t, err) - require.NotEqual(t, [32]byte{}, candidateDigestExecAfter) - require.NotEqual(t, candidateDigestExecBefore, candidateDigestExecAfter) - - // next we can revoke candidate - this should set the candidate digest back to zero - _, err = commonchangeset.ApplyChangesets(t, tenv.Env, map[uint64]*proposalutils.TimelockExecutionContracts{ - tenv.HomeChainSel: { - Timelock: state.Chains[tenv.HomeChainSel].Timelock, - CallProxy: state.Chains[tenv.HomeChainSel].CallProxy, - }, - }, []commonchangeset.ChangesetApplication{ - { - Changeset: commonchangeset.WrapChangeSet(RevokeCandidateChangeset), - Config: RevokeCandidateChangesetConfig{ - HomeChainSelector: tenv.HomeChainSel, - RemoteChainSelector: dest, - PluginType: types.PluginTypeCCIPCommit, - MCMS: mcmsConfig, - }, - }, - { - Changeset: commonchangeset.WrapChangeSet(RevokeCandidateChangeset), - Config: RevokeCandidateChangesetConfig{ - HomeChainSelector: tenv.HomeChainSel, - RemoteChainSelector: dest, - PluginType: types.PluginTypeCCIPExec, - MCMS: mcmsConfig, - }, - }, - }) - require.NoError(t, err) - - // after revoking the candidate, the candidate digest should be zero - candidateDigestCommitAfterRevoke, err := ccipHome.GetCandidateDigest(&bind.CallOpts{ - Context: ctx, - }, donID, uint8(types.PluginTypeCCIPCommit)) - require.NoError(t, err) - require.Equal(t, [32]byte{}, candidateDigestCommitAfterRevoke) - - candidateDigestExecAfterRevoke, err := ccipHome.GetCandidateDigest(&bind.CallOpts{ - Context: ctx, - }, donID, uint8(types.PluginTypeCCIPExec)) - require.NoError(t, err) - require.Equal(t, [32]byte{}, candidateDigestExecAfterRevoke) - }) - } -} - -func transferToTimelock( - t *testing.T, - tenv DeployedEnv, - state CCIPOnChainState, - source, - dest uint64) { - // Transfer ownership to timelock so that we can promote the zero digest later down the line. - _, err := commonchangeset.ApplyChangesets(t, tenv.Env, map[uint64]*proposalutils.TimelockExecutionContracts{ - source: { - Timelock: state.Chains[source].Timelock, - CallProxy: state.Chains[source].CallProxy, - }, - dest: { - Timelock: state.Chains[dest].Timelock, - CallProxy: state.Chains[dest].CallProxy, - }, - tenv.HomeChainSel: { - Timelock: state.Chains[tenv.HomeChainSel].Timelock, - CallProxy: state.Chains[tenv.HomeChainSel].CallProxy, - }, - }, []commonchangeset.ChangesetApplication{ - { - Changeset: commonchangeset.WrapChangeSet(commonchangeset.TransferToMCMSWithTimelock), - Config: genTestTransferOwnershipConfig(tenv, []uint64{source, dest}, state), - }, - }) - require.NoError(t, err) - assertTimelockOwnership(t, tenv, []uint64{source, dest}, state) -} - -func Test_UpdateChainConfigs(t *testing.T) { - for _, tc := range []struct { - name string - mcmsEnabled bool - }{ - { - name: "MCMS enabled", - mcmsEnabled: true, - }, - { - name: "MCMS disabled", - mcmsEnabled: false, - }, - } { - t.Run(tc.name, func(t *testing.T) { - tenv := NewMemoryEnvironment(t, WithChains(3)) - state, err := LoadOnchainState(tenv.Env) - require.NoError(t, err) - - allChains := maps.Keys(tenv.Env.Chains) - source := allChains[0] - dest := allChains[1] - otherChain := allChains[2] - - if tc.mcmsEnabled { - // Transfer ownership to timelock so that we can promote the zero digest later down the line. - transferToTimelock(t, tenv, state, source, dest) - } - - ccipHome := state.Chains[tenv.HomeChainSel].CCIPHome - otherChainConfig, err := ccipHome.GetChainConfig(nil, otherChain) - require.NoError(t, err) - assert.True(t, otherChainConfig.FChain != 0) - - var mcmsConfig *MCMSConfig - if tc.mcmsEnabled { - mcmsConfig = &MCMSConfig{ - MinDelay: 0, - } - } - _, err = commonchangeset.ApplyChangesets(t, tenv.Env, map[uint64]*proposalutils.TimelockExecutionContracts{ - tenv.HomeChainSel: { - Timelock: state.Chains[tenv.HomeChainSel].Timelock, - CallProxy: state.Chains[tenv.HomeChainSel].CallProxy, - }, - }, []commonchangeset.ChangesetApplication{ - { - Changeset: commonchangeset.WrapChangeSet(UpdateChainConfig), - Config: UpdateChainConfigConfig{ - HomeChainSelector: tenv.HomeChainSel, - RemoteChainRemoves: []uint64{otherChain}, - RemoteChainAdds: make(map[uint64]ChainConfig), - MCMS: mcmsConfig, - }, - }, - }) - require.NoError(t, err) - - // other chain should be gone - chainConfigAfter, err := ccipHome.GetChainConfig(nil, otherChain) - require.NoError(t, err) - assert.True(t, chainConfigAfter.FChain == 0) - - // Lets add it back now. - _, err = commonchangeset.ApplyChangesets(t, tenv.Env, map[uint64]*proposalutils.TimelockExecutionContracts{ - tenv.HomeChainSel: { - Timelock: state.Chains[tenv.HomeChainSel].Timelock, - CallProxy: state.Chains[tenv.HomeChainSel].CallProxy, - }, - }, []commonchangeset.ChangesetApplication{ - { - Changeset: commonchangeset.WrapChangeSet(UpdateChainConfig), - Config: UpdateChainConfigConfig{ - HomeChainSelector: tenv.HomeChainSel, - RemoteChainRemoves: []uint64{}, - RemoteChainAdds: map[uint64]ChainConfig{ - otherChain: { - EncodableChainConfig: chainconfig.ChainConfig{ - GasPriceDeviationPPB: cciptypes.BigInt{Int: big.NewInt(internal.GasPriceDeviationPPB)}, - DAGasPriceDeviationPPB: cciptypes.BigInt{Int: big.NewInt(internal.DAGasPriceDeviationPPB)}, - OptimisticConfirmations: internal.OptimisticConfirmations, - }, - FChain: otherChainConfig.FChain, - Readers: otherChainConfig.Readers, - }, - }, - MCMS: mcmsConfig, - }, - }, - }) - require.NoError(t, err) - - chainConfigAfter2, err := ccipHome.GetChainConfig(nil, otherChain) - require.NoError(t, err) - assert.Equal(t, chainConfigAfter2.FChain, otherChainConfig.FChain) - assert.Equal(t, chainConfigAfter2.Readers, otherChainConfig.Readers) - assert.Equal(t, chainConfigAfter2.Config, otherChainConfig.Config) - }) - } -} diff --git a/deployment/ccip/changeset/cs_chain_contracts.go b/deployment/ccip/changeset/cs_chain_contracts.go deleted file mode 100644 index f85814f1768..00000000000 --- a/deployment/ccip/changeset/cs_chain_contracts.go +++ /dev/null @@ -1,1129 +0,0 @@ -package changeset - -import ( - "bytes" - "context" - "encoding/hex" - "errors" - "fmt" - "math/big" - - "github.com/ethereum/go-ethereum/accounts/abi/bind" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/types" - "github.com/smartcontractkit/ccip-owner-contracts/pkg/gethwrappers" - "github.com/smartcontractkit/ccip-owner-contracts/pkg/proposal/mcms" - "github.com/smartcontractkit/ccip-owner-contracts/pkg/proposal/timelock" - - "github.com/smartcontractkit/chainlink-common/pkg/logger" - - "github.com/smartcontractkit/chainlink/deployment" - "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/internal" - commoncs "github.com/smartcontractkit/chainlink/deployment/common/changeset" - "github.com/smartcontractkit/chainlink/deployment/common/proposalutils" - "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/ccipevm" - cctypes "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/types" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/fee_quoter" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/nonce_manager" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/offramp" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/onramp" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/router" -) - -var ( - _ deployment.ChangeSet[UpdateOnRampDestsConfig] = UpdateOnRampsDests - _ deployment.ChangeSet[UpdateOffRampSourcesConfig] = UpdateOffRampSources - _ deployment.ChangeSet[UpdateRouterRampsConfig] = UpdateRouterRamps - _ deployment.ChangeSet[UpdateFeeQuoterDestsConfig] = UpdateFeeQuoterDests - _ deployment.ChangeSet[SetOCR3OffRampConfig] = SetOCR3OffRamp - _ deployment.ChangeSet[UpdateFeeQuoterPricesConfig] = UpdateFeeQuoterPricesCS - _ deployment.ChangeSet[UpdateNonceManagerConfig] = UpdateNonceManagersCS -) - -type UpdateNonceManagerConfig struct { - UpdatesByChain map[uint64]NonceManagerUpdate // source -> dest -> update - MCMS *MCMSConfig -} - -type NonceManagerUpdate struct { - AddedAuthCallers []common.Address - RemovedAuthCallers []common.Address - PreviousRampsArgs []PreviousRampCfg -} - -type PreviousRampCfg struct { - RemoteChainSelector uint64 - OverrideExisting bool - EnableOnRamp bool - EnableOffRamp bool -} - -func (cfg UpdateNonceManagerConfig) Validate(e deployment.Environment) error { - state, err := LoadOnchainState(e) - if err != nil { - return err - } - for sourceSel, update := range cfg.UpdatesByChain { - sourceChainState, ok := state.Chains[sourceSel] - if !ok { - return fmt.Errorf("chain %d not found in onchain state", sourceSel) - } - if sourceChainState.NonceManager == nil { - return fmt.Errorf("missing nonce manager for chain %d", sourceSel) - } - sourceChain, ok := e.Chains[sourceSel] - if !ok { - return fmt.Errorf("missing chain %d in environment", sourceSel) - } - if err := commoncs.ValidateOwnership(e.GetContext(), cfg.MCMS != nil, sourceChain.DeployerKey.From, sourceChainState.Timelock.Address(), sourceChainState.OnRamp); err != nil { - return fmt.Errorf("chain %s: %w", sourceChain.String(), err) - } - for _, prevRamp := range update.PreviousRampsArgs { - if prevRamp.RemoteChainSelector == sourceSel { - return errors.New("source and dest chain cannot be the same") - } - if _, ok := state.Chains[prevRamp.RemoteChainSelector]; !ok { - return fmt.Errorf("dest chain %d not found in onchain state for chain %d", prevRamp.RemoteChainSelector, sourceSel) - } - if !prevRamp.EnableOnRamp && !prevRamp.EnableOffRamp { - return errors.New("must specify either onramp or offramp") - } - if prevRamp.EnableOnRamp { - if prevOnRamp := state.Chains[sourceSel].EVM2EVMOnRamp; prevOnRamp == nil { - return fmt.Errorf("no previous onramp for source chain %d", sourceSel) - } else if prevOnRamp[prevRamp.RemoteChainSelector] == nil { - return fmt.Errorf("no previous onramp for source chain %d and dest chain %d", sourceSel, prevRamp.RemoteChainSelector) - } - } - if prevRamp.EnableOffRamp { - if prevOffRamp := state.Chains[sourceSel].EVM2EVMOffRamp; prevOffRamp == nil { - return fmt.Errorf("missing previous offramps for chain %d", sourceSel) - } else if prevOffRamp[prevRamp.RemoteChainSelector] == nil { - return fmt.Errorf("no previous offramp for source chain %d and dest chain %d", prevRamp.RemoteChainSelector, sourceSel) - } - } - } - } - return nil -} - -func UpdateNonceManagersCS(e deployment.Environment, cfg UpdateNonceManagerConfig) (deployment.ChangesetOutput, error) { - if err := cfg.Validate(e); err != nil { - return deployment.ChangesetOutput{}, err - } - s, err := LoadOnchainState(e) - if err != nil { - return deployment.ChangesetOutput{}, err - } - var batches []timelock.BatchChainOperation - timelocks := make(map[uint64]common.Address) - proposers := make(map[uint64]*gethwrappers.ManyChainMultiSig) - for chainSel, updates := range cfg.UpdatesByChain { - txOpts := e.Chains[chainSel].DeployerKey - if cfg.MCMS != nil { - txOpts = deployment.SimTransactOpts() - } - nm := s.Chains[chainSel].NonceManager - var authTx, prevRampsTx *types.Transaction - if len(updates.AddedAuthCallers) > 0 || len(updates.RemovedAuthCallers) > 0 { - authTx, err = nm.ApplyAuthorizedCallerUpdates(txOpts, nonce_manager.AuthorizedCallersAuthorizedCallerArgs{ - AddedCallers: updates.AddedAuthCallers, - RemovedCallers: updates.RemovedAuthCallers, - }) - if err != nil { - return deployment.ChangesetOutput{}, fmt.Errorf("error updating authorized callers for chain %s: %w", e.Chains[chainSel].String(), err) - } - } - if len(updates.PreviousRampsArgs) > 0 { - previousRampsArgs := make([]nonce_manager.NonceManagerPreviousRampsArgs, 0) - for _, prevRamp := range updates.PreviousRampsArgs { - var onRamp, offRamp common.Address - if prevRamp.EnableOnRamp { - onRamp = s.Chains[chainSel].EVM2EVMOnRamp[prevRamp.RemoteChainSelector].Address() - } - if prevRamp.EnableOffRamp { - offRamp = s.Chains[chainSel].EVM2EVMOffRamp[prevRamp.RemoteChainSelector].Address() - } - previousRampsArgs = append(previousRampsArgs, nonce_manager.NonceManagerPreviousRampsArgs{ - RemoteChainSelector: prevRamp.RemoteChainSelector, - OverrideExistingRamps: prevRamp.OverrideExisting, - PrevRamps: nonce_manager.NonceManagerPreviousRamps{ - PrevOnRamp: onRamp, - PrevOffRamp: offRamp, - }, - }) - } - prevRampsTx, err = nm.ApplyPreviousRampsUpdates(txOpts, previousRampsArgs) - if err != nil { - return deployment.ChangesetOutput{}, fmt.Errorf("error updating previous ramps for chain %s: %w", e.Chains[chainSel].String(), err) - } - if err != nil { - return deployment.ChangesetOutput{}, fmt.Errorf("error updating previous ramps for chain %s: %w", e.Chains[chainSel].String(), err) - } - } - if cfg.MCMS == nil { - if authTx != nil { - if _, err := deployment.ConfirmIfNoError(e.Chains[chainSel], authTx, err); err != nil { - return deployment.ChangesetOutput{}, err - } - } - if prevRampsTx != nil { - if _, err := deployment.ConfirmIfNoError(e.Chains[chainSel], prevRampsTx, err); err != nil { - return deployment.ChangesetOutput{}, err - } - } - } else { - ops := make([]mcms.Operation, 0) - if authTx != nil { - ops = append(ops, mcms.Operation{ - To: nm.Address(), - Data: authTx.Data(), - Value: big.NewInt(0), - }) - } - if prevRampsTx != nil { - ops = append(ops, mcms.Operation{ - To: nm.Address(), - Data: prevRampsTx.Data(), - Value: big.NewInt(0), - }) - } - if len(ops) == 0 { - return deployment.ChangesetOutput{}, errors.New("no operations to batch") - } - batches = append(batches, timelock.BatchChainOperation{ - ChainIdentifier: mcms.ChainIdentifier(chainSel), - Batch: ops, - }) - timelocks[chainSel] = s.Chains[chainSel].Timelock.Address() - proposers[chainSel] = s.Chains[chainSel].ProposerMcm - } - } - if cfg.MCMS == nil { - return deployment.ChangesetOutput{}, nil - } - - p, err := proposalutils.BuildProposalFromBatches( - timelocks, - proposers, - batches, - "Update nonce manager for previous ramps and authorized callers", - cfg.MCMS.MinDelay, - ) - if err != nil { - return deployment.ChangesetOutput{}, err - } - return deployment.ChangesetOutput{Proposals: []timelock.MCMSWithTimelockProposal{ - *p, - }}, nil -} - -type UpdateOnRampDestsConfig struct { - UpdatesByChain map[uint64]map[uint64]OnRampDestinationUpdate - // Disallow mixing MCMS/non-MCMS per chain for simplicity. - // (can still be acheived by calling this function multiple times) - MCMS *MCMSConfig -} - -type OnRampDestinationUpdate struct { - IsEnabled bool // If false, disables the destination by setting router to 0x0. - TestRouter bool // Flag for safety only allow specifying either router or testRouter. - AllowListEnabled bool -} - -func (cfg UpdateOnRampDestsConfig) Validate(e deployment.Environment) error { - state, err := LoadOnchainState(e) - if err != nil { - return err - } - supportedChains := state.SupportedChains() - for chainSel, updates := range cfg.UpdatesByChain { - chainState, ok := state.Chains[chainSel] - if !ok { - return fmt.Errorf("chain %d not found in onchain state", chainSel) - } - if chainState.TestRouter == nil { - return fmt.Errorf("missing test router for chain %d", chainSel) - } - if chainState.Router == nil { - return fmt.Errorf("missing router for chain %d", chainSel) - } - if chainState.OnRamp == nil { - return fmt.Errorf("missing onramp onramp for chain %d", chainSel) - } - if err := commoncs.ValidateOwnership(e.GetContext(), cfg.MCMS != nil, e.Chains[chainSel].DeployerKey.From, chainState.Timelock.Address(), chainState.OnRamp); err != nil { - return err - } - - for destination := range updates { - // Destination cannot be an unknown destination. - if _, ok := supportedChains[destination]; !ok { - return fmt.Errorf("destination chain %d is not a supported %s", destination, chainState.OnRamp.Address()) - } - sc, err := chainState.OnRamp.GetStaticConfig(&bind.CallOpts{Context: e.GetContext()}) - if err != nil { - return fmt.Errorf("failed to get onramp static config %s: %w", chainState.OnRamp.Address(), err) - } - if destination == sc.ChainSelector { - return fmt.Errorf("cannot update onramp destination to the same chain") - } - } - } - return nil -} - -// UpdateOnRampsDests updates the onramp destinations for each onramp -// in the chains specified. Multichain support is important - consider when we add a new chain -// and need to update the onramp destinations for all chains to support the new chain. -func UpdateOnRampsDests(e deployment.Environment, cfg UpdateOnRampDestsConfig) (deployment.ChangesetOutput, error) { - if err := cfg.Validate(e); err != nil { - return deployment.ChangesetOutput{}, err - } - s, err := LoadOnchainState(e) - if err != nil { - return deployment.ChangesetOutput{}, err - } - var batches []timelock.BatchChainOperation - timelocks := make(map[uint64]common.Address) - proposers := make(map[uint64]*gethwrappers.ManyChainMultiSig) - for chainSel, updates := range cfg.UpdatesByChain { - txOpts := e.Chains[chainSel].DeployerKey - txOpts.Context = e.GetContext() - if cfg.MCMS != nil { - txOpts = deployment.SimTransactOpts() - } - onRamp := s.Chains[chainSel].OnRamp - var args []onramp.OnRampDestChainConfigArgs - for destination, update := range updates { - router := common.HexToAddress("0x0") - // If not enabled, set router to 0x0. - if update.IsEnabled { - if update.TestRouter { - router = s.Chains[chainSel].TestRouter.Address() - } else { - router = s.Chains[chainSel].Router.Address() - } - } - args = append(args, onramp.OnRampDestChainConfigArgs{ - DestChainSelector: destination, - Router: router, - AllowlistEnabled: update.AllowListEnabled, - }) - } - tx, err := onRamp.ApplyDestChainConfigUpdates(txOpts, args) - if err != nil { - return deployment.ChangesetOutput{}, err - } - if cfg.MCMS == nil { - if _, err := deployment.ConfirmIfNoError(e.Chains[chainSel], tx, err); err != nil { - return deployment.ChangesetOutput{}, err - } - } else { - batches = append(batches, timelock.BatchChainOperation{ - ChainIdentifier: mcms.ChainIdentifier(chainSel), - Batch: []mcms.Operation{ - { - To: onRamp.Address(), - Data: tx.Data(), - Value: big.NewInt(0), - }, - }, - }) - timelocks[chainSel] = s.Chains[chainSel].Timelock.Address() - proposers[chainSel] = s.Chains[chainSel].ProposerMcm - } - } - if cfg.MCMS == nil { - return deployment.ChangesetOutput{}, nil - } - - p, err := proposalutils.BuildProposalFromBatches( - timelocks, - proposers, - batches, - "Update onramp destinations", - cfg.MCMS.MinDelay, - ) - if err != nil { - return deployment.ChangesetOutput{}, err - } - return deployment.ChangesetOutput{Proposals: []timelock.MCMSWithTimelockProposal{ - *p, - }}, nil -} - -type UpdateFeeQuoterPricesConfig struct { - PricesByChain map[uint64]FeeQuoterPriceUpdatePerSource // source -> PriceDetails - MCMS *MCMSConfig -} - -type FeeQuoterPriceUpdatePerSource struct { - TokenPrices map[common.Address]*big.Int // token address -> price - GasPrices map[uint64]*big.Int // dest chain -> gas price -} - -func (cfg UpdateFeeQuoterPricesConfig) Validate(e deployment.Environment) error { - state, err := LoadOnchainState(e) - if err != nil { - return err - } - for chainSel, initialPrice := range cfg.PricesByChain { - if err := deployment.IsValidChainSelector(chainSel); err != nil { - return fmt.Errorf("invalid chain selector: %w", err) - } - chainState, ok := state.Chains[chainSel] - if !ok { - return fmt.Errorf("chain %d not found in onchain state", chainSel) - } - fq := chainState.FeeQuoter - if fq == nil { - return fmt.Errorf("missing fee quoter for chain %d", chainSel) - } - if err := commoncs.ValidateOwnership(e.GetContext(), cfg.MCMS != nil, e.Chains[chainSel].DeployerKey.From, chainState.Timelock.Address(), chainState.FeeQuoter); err != nil { - return err - } - // check that whether price updaters are set - authCallers, err := fq.GetAllAuthorizedCallers(&bind.CallOpts{Context: e.GetContext()}) - if err != nil { - return fmt.Errorf("failed to get authorized callers for chain %d: %w", chainSel, err) - } - if len(authCallers) == 0 { - return fmt.Errorf("no authorized callers for chain %d", chainSel) - } - expectedAuthCaller := e.Chains[chainSel].DeployerKey.From - if cfg.MCMS != nil { - expectedAuthCaller = chainState.Timelock.Address() - } - foundCaller := false - for _, authCaller := range authCallers { - if authCaller.Cmp(expectedAuthCaller) == 0 { - foundCaller = true - } - } - if !foundCaller { - return fmt.Errorf("expected authorized caller %s not found for chain %d", expectedAuthCaller.String(), chainSel) - } - for token, price := range initialPrice.TokenPrices { - if price == nil { - return fmt.Errorf("token price for chain %d is nil", chainSel) - } - if token == (common.Address{}) { - return fmt.Errorf("token address for chain %d is empty", chainSel) - } - contains, err := deployment.AddressBookContains(e.ExistingAddresses, chainSel, token.String()) - if err != nil { - return fmt.Errorf("error checking address book for token %s: %w", token.String(), err) - } - if !contains { - return fmt.Errorf("token %s not found in address book for chain %d", token.String(), chainSel) - } - } - for dest, price := range initialPrice.GasPrices { - if chainSel == dest { - return errors.New("source and dest chain cannot be the same") - } - if err := deployment.IsValidChainSelector(dest); err != nil { - return fmt.Errorf("invalid dest chain selector: %w", err) - } - if price == nil { - return fmt.Errorf("gas price for chain %d is nil", chainSel) - } - if _, ok := state.Chains[dest]; !ok { - return fmt.Errorf("dest chain %d not found in onchain state for chain %d", dest, chainSel) - } - } - } - - return nil -} - -func UpdateFeeQuoterPricesCS(e deployment.Environment, cfg UpdateFeeQuoterPricesConfig) (deployment.ChangesetOutput, error) { - if err := cfg.Validate(e); err != nil { - return deployment.ChangesetOutput{}, err - } - s, err := LoadOnchainState(e) - if err != nil { - return deployment.ChangesetOutput{}, err - } - var batches []timelock.BatchChainOperation - timelocks := make(map[uint64]common.Address) - proposers := make(map[uint64]*gethwrappers.ManyChainMultiSig) - for chainSel, initialPrice := range cfg.PricesByChain { - txOpts := e.Chains[chainSel].DeployerKey - if cfg.MCMS != nil { - txOpts = deployment.SimTransactOpts() - } - fq := s.Chains[chainSel].FeeQuoter - var tokenPricesArgs []fee_quoter.InternalTokenPriceUpdate - for token, price := range initialPrice.TokenPrices { - tokenPricesArgs = append(tokenPricesArgs, fee_quoter.InternalTokenPriceUpdate{ - SourceToken: token, - UsdPerToken: price, - }) - } - var gasPricesArgs []fee_quoter.InternalGasPriceUpdate - for dest, price := range initialPrice.GasPrices { - gasPricesArgs = append(gasPricesArgs, fee_quoter.InternalGasPriceUpdate{ - DestChainSelector: dest, - UsdPerUnitGas: price, - }) - } - tx, err := fq.UpdatePrices(txOpts, fee_quoter.InternalPriceUpdates{ - TokenPriceUpdates: tokenPricesArgs, - GasPriceUpdates: gasPricesArgs, - }) - if err != nil { - return deployment.ChangesetOutput{}, fmt.Errorf("error updating prices for chain %s: %w", e.Chains[chainSel].String(), err) - } - if cfg.MCMS == nil { - if _, err := deployment.ConfirmIfNoError(e.Chains[chainSel], tx, err); err != nil { - return deployment.ChangesetOutput{}, fmt.Errorf("error confirming transaction for chain %s: %w", e.Chains[chainSel].String(), err) - } - } else { - batches = append(batches, timelock.BatchChainOperation{ - ChainIdentifier: mcms.ChainIdentifier(chainSel), - Batch: []mcms.Operation{ - { - To: fq.Address(), - Data: tx.Data(), - Value: big.NewInt(0), - }, - }, - }) - } - } - if cfg.MCMS == nil { - return deployment.ChangesetOutput{}, nil - } - - p, err := proposalutils.BuildProposalFromBatches( - timelocks, - proposers, - batches, - "Update fq prices", - cfg.MCMS.MinDelay, - ) - if err != nil { - return deployment.ChangesetOutput{}, err - } - return deployment.ChangesetOutput{Proposals: []timelock.MCMSWithTimelockProposal{ - *p, - }}, nil -} - -type UpdateFeeQuoterDestsConfig struct { - UpdatesByChain map[uint64]map[uint64]fee_quoter.FeeQuoterDestChainConfig - // Disallow mixing MCMS/non-MCMS per chain for simplicity. - // (can still be acheived by calling this function multiple times) - MCMS *MCMSConfig -} - -func (cfg UpdateFeeQuoterDestsConfig) Validate(e deployment.Environment) error { - state, err := LoadOnchainState(e) - if err != nil { - return err - } - supportedChains := state.SupportedChains() - for chainSel, updates := range cfg.UpdatesByChain { - chainState, ok := state.Chains[chainSel] - if !ok { - return fmt.Errorf("chain %d not found in onchain state", chainSel) - } - if chainState.TestRouter == nil { - return fmt.Errorf("missing test router for chain %d", chainSel) - } - if chainState.Router == nil { - return fmt.Errorf("missing router for chain %d", chainSel) - } - if chainState.OnRamp == nil { - return fmt.Errorf("missing onramp onramp for chain %d", chainSel) - } - if err := commoncs.ValidateOwnership(e.GetContext(), cfg.MCMS != nil, e.Chains[chainSel].DeployerKey.From, chainState.Timelock.Address(), chainState.FeeQuoter); err != nil { - return err - } - - for destination := range updates { - // Destination cannot be an unknown destination. - if _, ok := supportedChains[destination]; !ok { - return fmt.Errorf("destination chain %d is not a supported %s", destination, chainState.OnRamp.Address()) - } - sc, err := chainState.OnRamp.GetStaticConfig(&bind.CallOpts{Context: e.GetContext()}) - if err != nil { - return fmt.Errorf("failed to get onramp static config %s: %w", chainState.OnRamp.Address(), err) - } - if destination == sc.ChainSelector { - return fmt.Errorf("source and destination chain cannot be the same") - } - } - } - return nil -} - -func UpdateFeeQuoterDests(e deployment.Environment, cfg UpdateFeeQuoterDestsConfig) (deployment.ChangesetOutput, error) { - if err := cfg.Validate(e); err != nil { - return deployment.ChangesetOutput{}, err - } - s, err := LoadOnchainState(e) - if err != nil { - return deployment.ChangesetOutput{}, err - } - var batches []timelock.BatchChainOperation - timelocks := make(map[uint64]common.Address) - proposers := make(map[uint64]*gethwrappers.ManyChainMultiSig) - for chainSel, updates := range cfg.UpdatesByChain { - txOpts := e.Chains[chainSel].DeployerKey - txOpts.Context = e.GetContext() - if cfg.MCMS != nil { - txOpts = deployment.SimTransactOpts() - } - fq := s.Chains[chainSel].FeeQuoter - var args []fee_quoter.FeeQuoterDestChainConfigArgs - for destination, dc := range updates { - args = append(args, fee_quoter.FeeQuoterDestChainConfigArgs{ - DestChainSelector: destination, - DestChainConfig: dc, - }) - } - tx, err := fq.ApplyDestChainConfigUpdates(txOpts, args) - if err != nil { - return deployment.ChangesetOutput{}, err - } - if cfg.MCMS == nil { - if _, err := deployment.ConfirmIfNoError(e.Chains[chainSel], tx, err); err != nil { - return deployment.ChangesetOutput{}, err - } - } else { - batches = append(batches, timelock.BatchChainOperation{ - ChainIdentifier: mcms.ChainIdentifier(chainSel), - Batch: []mcms.Operation{ - { - To: fq.Address(), - Data: tx.Data(), - Value: big.NewInt(0), - }, - }, - }) - timelocks[chainSel] = s.Chains[chainSel].Timelock.Address() - proposers[chainSel] = s.Chains[chainSel].ProposerMcm - } - } - if cfg.MCMS == nil { - return deployment.ChangesetOutput{}, nil - } - - p, err := proposalutils.BuildProposalFromBatches( - timelocks, - proposers, - batches, - "Update fq destinations", - cfg.MCMS.MinDelay, - ) - if err != nil { - return deployment.ChangesetOutput{}, err - } - return deployment.ChangesetOutput{Proposals: []timelock.MCMSWithTimelockProposal{ - *p, - }}, nil -} - -type UpdateOffRampSourcesConfig struct { - UpdatesByChain map[uint64]map[uint64]OffRampSourceUpdate - MCMS *MCMSConfig -} - -type OffRampSourceUpdate struct { - IsEnabled bool // If false, disables the source by setting router to 0x0. - TestRouter bool // Flag for safety only allow specifying either router or testRouter. -} - -func (cfg UpdateOffRampSourcesConfig) Validate(e deployment.Environment) error { - state, err := LoadOnchainState(e) - if err != nil { - return err - } - supportedChains := state.SupportedChains() - for chainSel, updates := range cfg.UpdatesByChain { - chainState, ok := state.Chains[chainSel] - if !ok { - return fmt.Errorf("chain %d not found in onchain state", chainSel) - } - if chainState.TestRouter == nil { - return fmt.Errorf("missing test router for chain %d", chainSel) - } - if chainState.Router == nil { - return fmt.Errorf("missing router for chain %d", chainSel) - } - if chainState.OffRamp == nil { - return fmt.Errorf("missing onramp onramp for chain %d", chainSel) - } - if err := commoncs.ValidateOwnership(e.GetContext(), cfg.MCMS != nil, e.Chains[chainSel].DeployerKey.From, chainState.Timelock.Address(), chainState.OffRamp); err != nil { - return err - } - - for source := range updates { - // Source cannot be an unknown - if _, ok := supportedChains[source]; !ok { - return fmt.Errorf("source chain %d is not a supported chain %s", source, chainState.OffRamp.Address()) - } - - if source == chainSel { - return fmt.Errorf("cannot update offramp source to the same chain %d", source) - } - sourceChain := state.Chains[source] - // Source chain must have the onramp deployed. - // Note this also validates the specified source selector. - if sourceChain.OnRamp == nil { - return fmt.Errorf("missing onramp for source %d", source) - } - } - } - return nil -} - -// UpdateOffRampSources updates the offramp sources for each offramp. -func UpdateOffRampSources(e deployment.Environment, cfg UpdateOffRampSourcesConfig) (deployment.ChangesetOutput, error) { - if err := cfg.Validate(e); err != nil { - return deployment.ChangesetOutput{}, err - } - s, err := LoadOnchainState(e) - if err != nil { - return deployment.ChangesetOutput{}, err - } - var batches []timelock.BatchChainOperation - timelocks := make(map[uint64]common.Address) - proposers := make(map[uint64]*gethwrappers.ManyChainMultiSig) - for chainSel, updates := range cfg.UpdatesByChain { - txOpts := e.Chains[chainSel].DeployerKey - txOpts.Context = e.GetContext() - if cfg.MCMS != nil { - txOpts = deployment.SimTransactOpts() - } - offRamp := s.Chains[chainSel].OffRamp - var args []offramp.OffRampSourceChainConfigArgs - for source, update := range updates { - router := common.HexToAddress("0x0") - if update.IsEnabled { - if update.TestRouter { - router = s.Chains[chainSel].TestRouter.Address() - } else { - router = s.Chains[chainSel].Router.Address() - } - } - onRamp := s.Chains[source].OnRamp - args = append(args, offramp.OffRampSourceChainConfigArgs{ - SourceChainSelector: source, - Router: router, - IsEnabled: update.IsEnabled, - OnRamp: common.LeftPadBytes(onRamp.Address().Bytes(), 32), - }) - } - tx, err := offRamp.ApplySourceChainConfigUpdates(txOpts, args) - if err != nil { - return deployment.ChangesetOutput{}, err - } - if cfg.MCMS == nil { - if _, err := deployment.ConfirmIfNoError(e.Chains[chainSel], tx, err); err != nil { - return deployment.ChangesetOutput{}, err - } - } else { - batches = append(batches, timelock.BatchChainOperation{ - ChainIdentifier: mcms.ChainIdentifier(chainSel), - Batch: []mcms.Operation{ - { - To: offRamp.Address(), - Data: tx.Data(), - Value: big.NewInt(0), - }, - }, - }) - timelocks[chainSel] = s.Chains[chainSel].Timelock.Address() - proposers[chainSel] = s.Chains[chainSel].ProposerMcm - } - } - if cfg.MCMS == nil { - return deployment.ChangesetOutput{}, nil - } - - p, err := proposalutils.BuildProposalFromBatches( - timelocks, - proposers, - batches, - "Update offramp sources", - cfg.MCMS.MinDelay, - ) - if err != nil { - return deployment.ChangesetOutput{}, err - } - return deployment.ChangesetOutput{Proposals: []timelock.MCMSWithTimelockProposal{ - *p, - }}, nil -} - -type UpdateRouterRampsConfig struct { - // TestRouter means the updates will be applied to the test router - // on all chains. Disallow mixing test router/non-test router per chain for simplicity. - TestRouter bool - UpdatesByChain map[uint64]RouterUpdates - MCMS *MCMSConfig -} - -type RouterUpdates struct { - OffRampUpdates map[uint64]bool - OnRampUpdates map[uint64]bool -} - -func (cfg UpdateRouterRampsConfig) Validate(e deployment.Environment) error { - state, err := LoadOnchainState(e) - if err != nil { - return err - } - supportedChains := state.SupportedChains() - for chainSel, update := range cfg.UpdatesByChain { - chainState, ok := state.Chains[chainSel] - if !ok { - return fmt.Errorf("chain %d not found in onchain state", chainSel) - } - if chainState.TestRouter == nil { - return fmt.Errorf("missing test router for chain %d", chainSel) - } - if chainState.Router == nil { - return fmt.Errorf("missing router for chain %d", chainSel) - } - if chainState.OffRamp == nil { - return fmt.Errorf("missing onramp onramp for chain %d", chainSel) - } - if err := commoncs.ValidateOwnership(e.GetContext(), cfg.MCMS != nil, e.Chains[chainSel].DeployerKey.From, chainState.Timelock.Address(), chainState.Router); err != nil { - return err - } - - for source := range update.OffRampUpdates { - // Source cannot be an unknown - if _, ok := supportedChains[source]; !ok { - return fmt.Errorf("source chain %d is not a supported chain %s", source, chainState.OffRamp.Address()) - } - if source == chainSel { - return fmt.Errorf("cannot update offramp source to the same chain %d", source) - } - sourceChain := state.Chains[source] - // Source chain must have the onramp deployed. - // Note this also validates the specified source selector. - if sourceChain.OnRamp == nil { - return fmt.Errorf("missing onramp for source %d", source) - } - } - for destination := range update.OnRampUpdates { - // Source cannot be an unknown - if _, ok := supportedChains[destination]; !ok { - return fmt.Errorf("dest chain %d is not a supported chain %s", destination, chainState.OffRamp.Address()) - } - if destination == chainSel { - return fmt.Errorf("cannot update onRamp dest to the same chain %d", destination) - } - destChain := state.Chains[destination] - if destChain.OffRamp == nil { - return fmt.Errorf("missing offramp for dest %d", destination) - } - } - - } - return nil -} - -// UpdateRouterRamps updates the on/offramps -// in either the router or test router for a series of chains. Use cases include: -// - Ramp upgrade. After deploying new ramps you can enable them on the test router and -// ensure it works e2e. Then enable the ramps on the real router. -// - New chain support. When adding a new chain, you can enable the new destination -// on all chains to support the new chain through the test router first. Once tested, -// Enable the new destination on the real router. -func UpdateRouterRamps(e deployment.Environment, cfg UpdateRouterRampsConfig) (deployment.ChangesetOutput, error) { - if err := cfg.Validate(e); err != nil { - return deployment.ChangesetOutput{}, err - } - s, err := LoadOnchainState(e) - if err != nil { - return deployment.ChangesetOutput{}, err - } - var batches []timelock.BatchChainOperation - timelocks := make(map[uint64]common.Address) - proposers := make(map[uint64]*gethwrappers.ManyChainMultiSig) - for chainSel, update := range cfg.UpdatesByChain { - txOpts := e.Chains[chainSel].DeployerKey - txOpts.Context = e.GetContext() - if cfg.MCMS != nil { - txOpts = deployment.SimTransactOpts() - } - routerC := s.Chains[chainSel].Router - if cfg.TestRouter { - routerC = s.Chains[chainSel].TestRouter - } - // Note if we add distinct offramps per source to the state, - // we'll need to add support here for looking them up. - // For now its simple, all sources use the same offramp. - offRamp := s.Chains[chainSel].OffRamp - var removes, adds []router.RouterOffRamp - for source, enabled := range update.OffRampUpdates { - if enabled { - adds = append(adds, router.RouterOffRamp{ - SourceChainSelector: source, - OffRamp: offRamp.Address(), - }) - } else { - removes = append(removes, router.RouterOffRamp{ - SourceChainSelector: source, - OffRamp: offRamp.Address(), - }) - } - } - // Ditto here, only one onramp expected until 1.7. - onRamp := s.Chains[chainSel].OnRamp - var onRampUpdates []router.RouterOnRamp - for dest, enabled := range update.OnRampUpdates { - if enabled { - onRampUpdates = append(onRampUpdates, router.RouterOnRamp{ - DestChainSelector: dest, - OnRamp: onRamp.Address(), - }) - } else { - onRampUpdates = append(onRampUpdates, router.RouterOnRamp{ - DestChainSelector: dest, - OnRamp: common.HexToAddress("0x0"), - }) - } - } - tx, err := routerC.ApplyRampUpdates(txOpts, onRampUpdates, removes, adds) - if err != nil { - return deployment.ChangesetOutput{}, err - } - if cfg.MCMS == nil { - if _, err := deployment.ConfirmIfNoError(e.Chains[chainSel], tx, err); err != nil { - return deployment.ChangesetOutput{}, err - } - } else { - batches = append(batches, timelock.BatchChainOperation{ - ChainIdentifier: mcms.ChainIdentifier(chainSel), - Batch: []mcms.Operation{ - { - To: routerC.Address(), - Data: tx.Data(), - Value: big.NewInt(0), - }, - }, - }) - timelocks[chainSel] = s.Chains[chainSel].Timelock.Address() - proposers[chainSel] = s.Chains[chainSel].ProposerMcm - } - } - if cfg.MCMS == nil { - return deployment.ChangesetOutput{}, nil - } - - p, err := proposalutils.BuildProposalFromBatches( - timelocks, - proposers, - batches, - "Update router offramps", - cfg.MCMS.MinDelay, - ) - if err != nil { - return deployment.ChangesetOutput{}, err - } - return deployment.ChangesetOutput{Proposals: []timelock.MCMSWithTimelockProposal{ - *p, - }}, nil -} - -type SetOCR3OffRampConfig struct { - HomeChainSel uint64 - RemoteChainSels []uint64 - MCMS *MCMSConfig -} - -func (c SetOCR3OffRampConfig) Validate(e deployment.Environment) error { - state, err := LoadOnchainState(e) - if err != nil { - return err - } - if _, ok := state.Chains[c.HomeChainSel]; !ok { - return fmt.Errorf("home chain %d not found in onchain state", c.HomeChainSel) - } - for _, remote := range c.RemoteChainSels { - chainState, ok := state.Chains[remote] - if !ok { - return fmt.Errorf("remote chain %d not found in onchain state", remote) - } - if err := commoncs.ValidateOwnership(e.GetContext(), c.MCMS != nil, e.Chains[remote].DeployerKey.From, chainState.Timelock.Address(), chainState.OffRamp); err != nil { - return err - } - } - return nil -} - -// SetOCR3OffRamp will set the OCR3 offramp for the given chain. -// to the active configuration on CCIPHome. This -// is used to complete the candidate->active promotion cycle, it's -// run after the candidate is confirmed to be working correctly. -// Multichain is especially helpful for NOP rotations where we have -// to touch all the chain to change signers. -func SetOCR3OffRamp(e deployment.Environment, cfg SetOCR3OffRampConfig) (deployment.ChangesetOutput, error) { - if err := cfg.Validate(e); err != nil { - return deployment.ChangesetOutput{}, err - } - state, err := LoadOnchainState(e) - if err != nil { - return deployment.ChangesetOutput{}, err - } - var batches []timelock.BatchChainOperation - timelocks := make(map[uint64]common.Address) - proposers := make(map[uint64]*gethwrappers.ManyChainMultiSig) - for _, remote := range cfg.RemoteChainSels { - donID, err := internal.DonIDForChain( - state.Chains[cfg.HomeChainSel].CapabilityRegistry, - state.Chains[cfg.HomeChainSel].CCIPHome, - remote) - args, err := internal.BuildSetOCR3ConfigArgs(donID, state.Chains[cfg.HomeChainSel].CCIPHome, remote) - if err != nil { - return deployment.ChangesetOutput{}, err - } - set, err := isOCR3ConfigSetOnOffRamp(e.Logger, e.Chains[remote], state.Chains[remote].OffRamp, args) - if err != nil { - return deployment.ChangesetOutput{}, err - } - if set { - e.Logger.Infof("OCR3 config already set on offramp for chain %d", remote) - continue - } - txOpts := e.Chains[remote].DeployerKey - if cfg.MCMS != nil { - txOpts = deployment.SimTransactOpts() - } - offRamp := state.Chains[remote].OffRamp - tx, err := offRamp.SetOCR3Configs(txOpts, args) - if err != nil { - return deployment.ChangesetOutput{}, err - } - if cfg.MCMS == nil { - if _, err := deployment.ConfirmIfNoError(e.Chains[remote], tx, err); err != nil { - return deployment.ChangesetOutput{}, err - } - } else { - batches = append(batches, timelock.BatchChainOperation{ - ChainIdentifier: mcms.ChainIdentifier(remote), - Batch: []mcms.Operation{ - { - To: offRamp.Address(), - Data: tx.Data(), - Value: big.NewInt(0), - }, - }, - }) - timelocks[remote] = state.Chains[remote].Timelock.Address() - proposers[remote] = state.Chains[remote].ProposerMcm - } - } - if cfg.MCMS == nil { - return deployment.ChangesetOutput{}, nil - } - p, err := proposalutils.BuildProposalFromBatches( - timelocks, - proposers, - batches, - "Update OCR3 config", - cfg.MCMS.MinDelay, - ) - if err != nil { - return deployment.ChangesetOutput{}, err - } - e.Logger.Infof("Proposing OCR3 config update for", cfg.RemoteChainSels) - return deployment.ChangesetOutput{Proposals: []timelock.MCMSWithTimelockProposal{ - *p, - }}, nil -} - -func isOCR3ConfigSetOnOffRamp( - lggr logger.Logger, - chain deployment.Chain, - offRamp *offramp.OffRamp, - offrampOCR3Configs []offramp.MultiOCR3BaseOCRConfigArgs, -) (bool, error) { - mapOfframpOCR3Configs := make(map[cctypes.PluginType]offramp.MultiOCR3BaseOCRConfigArgs) - for _, config := range offrampOCR3Configs { - mapOfframpOCR3Configs[cctypes.PluginType(config.OcrPluginType)] = config - } - - for _, pluginType := range []cctypes.PluginType{cctypes.PluginTypeCCIPCommit, cctypes.PluginTypeCCIPExec} { - ocrConfig, err := offRamp.LatestConfigDetails(&bind.CallOpts{ - Context: context.Background(), - }, uint8(pluginType)) - if err != nil { - return false, fmt.Errorf("error fetching OCR3 config for plugin %s chain %s: %w", pluginType.String(), chain.String(), err) - } - lggr.Debugw("Fetched OCR3 Configs", - "MultiOCR3BaseOCRConfig.F", ocrConfig.ConfigInfo.F, - "MultiOCR3BaseOCRConfig.N", ocrConfig.ConfigInfo.N, - "MultiOCR3BaseOCRConfig.IsSignatureVerificationEnabled", ocrConfig.ConfigInfo.IsSignatureVerificationEnabled, - "Signers", ocrConfig.Signers, - "Transmitters", ocrConfig.Transmitters, - "configDigest", hex.EncodeToString(ocrConfig.ConfigInfo.ConfigDigest[:]), - "chain", chain.String(), - ) - // TODO: assertions to be done as part of full state - // resprentation validation CCIP-3047 - if mapOfframpOCR3Configs[pluginType].ConfigDigest != ocrConfig.ConfigInfo.ConfigDigest { - lggr.Infow("OCR3 config digest mismatch", "pluginType", pluginType.String()) - return false, nil - } - if mapOfframpOCR3Configs[pluginType].F != ocrConfig.ConfigInfo.F { - lggr.Infow("OCR3 config F mismatch", "pluginType", pluginType.String()) - return false, nil - } - if mapOfframpOCR3Configs[pluginType].IsSignatureVerificationEnabled != ocrConfig.ConfigInfo.IsSignatureVerificationEnabled { - lggr.Infow("OCR3 config signature verification mismatch", "pluginType", pluginType.String()) - return false, nil - } - if pluginType == cctypes.PluginTypeCCIPCommit { - // only commit will set signers, exec doesn't need them. - for i, signer := range mapOfframpOCR3Configs[pluginType].Signers { - if !bytes.Equal(signer.Bytes(), ocrConfig.Signers[i].Bytes()) { - lggr.Infow("OCR3 config signer mismatch", "pluginType", pluginType.String()) - return false, nil - } - } - } - for i, transmitter := range mapOfframpOCR3Configs[pluginType].Transmitters { - if !bytes.Equal(transmitter.Bytes(), ocrConfig.Transmitters[i].Bytes()) { - lggr.Infow("OCR3 config transmitter mismatch", "pluginType", pluginType.String()) - return false, nil - } - } - } - return true, nil -} - -func DefaultFeeQuoterDestChainConfig() fee_quoter.FeeQuoterDestChainConfig { - // https://github.com/smartcontractkit/ccip/blob/c4856b64bd766f1ddbaf5d13b42d3c4b12efde3a/contracts/src/v0.8/ccip/libraries/Internal.sol#L337-L337 - /* - ```Solidity - // bytes4(keccak256("CCIP ChainFamilySelector EVM")) - bytes4 public constant CHAIN_FAMILY_SELECTOR_EVM = 0x2812d52c; - ``` - */ - evmFamilySelector, _ := hex.DecodeString("2812d52c") - return fee_quoter.FeeQuoterDestChainConfig{ - IsEnabled: true, - MaxNumberOfTokensPerMsg: 10, - MaxDataBytes: 256, - MaxPerMsgGasLimit: 3_000_000, - DestGasOverhead: ccipevm.DestGasOverhead, - DefaultTokenFeeUSDCents: 1, - DestGasPerPayloadByte: ccipevm.CalldataGasPerByte, - DestDataAvailabilityOverheadGas: 100, - DestGasPerDataAvailabilityByte: 100, - DestDataAvailabilityMultiplierBps: 1, - DefaultTokenDestGasOverhead: 125_000, - DefaultTxGasLimit: 200_000, - GasMultiplierWeiPerEth: 11e17, // Gas multiplier in wei per eth is scaled by 1e18, so 11e17 is 1.1 = 110% - NetworkFeeUSDCents: 1, - ChainFamilySelector: [4]byte(evmFamilySelector), - } -} diff --git a/deployment/ccip/changeset/cs_chain_contracts_test.go b/deployment/ccip/changeset/cs_chain_contracts_test.go deleted file mode 100644 index 0a1e0ce3b7b..00000000000 --- a/deployment/ccip/changeset/cs_chain_contracts_test.go +++ /dev/null @@ -1,364 +0,0 @@ -package changeset - -import ( - "testing" - - "github.com/ethereum/go-ethereum/accounts/abi/bind" - "github.com/ethereum/go-ethereum/common" - "github.com/stretchr/testify/require" - "golang.org/x/exp/maps" - - "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/testcontext" - - commonchangeset "github.com/smartcontractkit/chainlink/deployment/common/changeset" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/fee_quoter" -) - -func TestUpdateOnRampsDests(t *testing.T) { - for _, tc := range []struct { - name string - mcmsEnabled bool - }{ - { - name: "MCMS enabled", - mcmsEnabled: true, - }, - { - name: "MCMS disabled", - mcmsEnabled: false, - }, - } { - t.Run(tc.name, func(t *testing.T) { - ctx := testcontext.Get(t) - // Default env just has 2 chains with all contracts - // deployed but no lanes. - tenv := NewMemoryEnvironment(t) - state, err := LoadOnchainState(tenv.Env) - require.NoError(t, err) - - allChains := maps.Keys(tenv.Env.Chains) - source := allChains[0] - dest := allChains[1] - - if tc.mcmsEnabled { - // Transfer ownership to timelock so that we can promote the zero digest later down the line. - transferToTimelock(t, tenv, state, source, dest) - } - - var mcmsConfig *MCMSConfig - if tc.mcmsEnabled { - mcmsConfig = &MCMSConfig{ - MinDelay: 0, - } - } - _, err = commonchangeset.ApplyChangesets(t, tenv.Env, tenv.TimelockContracts(t), []commonchangeset.ChangesetApplication{ - { - Changeset: commonchangeset.WrapChangeSet(UpdateOnRampsDests), - Config: UpdateOnRampDestsConfig{ - UpdatesByChain: map[uint64]map[uint64]OnRampDestinationUpdate{ - source: { - dest: { - IsEnabled: true, - TestRouter: true, - AllowListEnabled: false, - }, - }, - dest: { - source: { - IsEnabled: true, - TestRouter: false, - AllowListEnabled: true, - }, - }, - }, - MCMS: mcmsConfig, - }, - }, - }) - require.NoError(t, err) - - // Assert the onramp configuration is as we expect. - sourceCfg, err := state.Chains[source].OnRamp.GetDestChainConfig(&bind.CallOpts{Context: ctx}, dest) - require.NoError(t, err) - require.Equal(t, state.Chains[source].TestRouter.Address(), sourceCfg.Router) - require.Equal(t, false, sourceCfg.AllowlistEnabled) - destCfg, err := state.Chains[dest].OnRamp.GetDestChainConfig(&bind.CallOpts{Context: ctx}, source) - require.NoError(t, err) - require.Equal(t, state.Chains[dest].Router.Address(), destCfg.Router) - require.Equal(t, true, destCfg.AllowlistEnabled) - }) - } -} - -func TestUpdateOffRampsSources(t *testing.T) { - for _, tc := range []struct { - name string - mcmsEnabled bool - }{ - { - name: "MCMS enabled", - mcmsEnabled: true, - }, - { - name: "MCMS disabled", - mcmsEnabled: false, - }, - } { - t.Run(tc.name, func(t *testing.T) { - ctx := testcontext.Get(t) - tenv := NewMemoryEnvironment(t) - state, err := LoadOnchainState(tenv.Env) - require.NoError(t, err) - - allChains := maps.Keys(tenv.Env.Chains) - source := allChains[0] - dest := allChains[1] - - if tc.mcmsEnabled { - // Transfer ownership to timelock so that we can promote the zero digest later down the line. - transferToTimelock(t, tenv, state, source, dest) - } - - var mcmsConfig *MCMSConfig - if tc.mcmsEnabled { - mcmsConfig = &MCMSConfig{ - MinDelay: 0, - } - } - _, err = commonchangeset.ApplyChangesets(t, tenv.Env, tenv.TimelockContracts(t), []commonchangeset.ChangesetApplication{ - { - Changeset: commonchangeset.WrapChangeSet(UpdateOffRampSources), - Config: UpdateOffRampSourcesConfig{ - UpdatesByChain: map[uint64]map[uint64]OffRampSourceUpdate{ - source: { - dest: { - IsEnabled: true, - TestRouter: true, - }, - }, - dest: { - source: { - IsEnabled: true, - TestRouter: false, - }, - }, - }, - MCMS: mcmsConfig, - }, - }, - }) - require.NoError(t, err) - - // Assert the offramp configuration is as we expect. - sourceCfg, err := state.Chains[source].OffRamp.GetSourceChainConfig(&bind.CallOpts{Context: ctx}, dest) - require.NoError(t, err) - require.Equal(t, state.Chains[source].TestRouter.Address(), sourceCfg.Router) - destCfg, err := state.Chains[dest].OffRamp.GetSourceChainConfig(&bind.CallOpts{Context: ctx}, source) - require.NoError(t, err) - require.Equal(t, state.Chains[dest].Router.Address(), destCfg.Router) - }) - } -} - -func TestUpdateFQDests(t *testing.T) { - for _, tc := range []struct { - name string - mcmsEnabled bool - }{ - { - name: "MCMS enabled", - mcmsEnabled: true, - }, - { - name: "MCMS disabled", - mcmsEnabled: false, - }, - } { - t.Run(tc.name, func(t *testing.T) { - ctx := testcontext.Get(t) - tenv := NewMemoryEnvironment(t) - state, err := LoadOnchainState(tenv.Env) - require.NoError(t, err) - - allChains := maps.Keys(tenv.Env.Chains) - source := allChains[0] - dest := allChains[1] - - if tc.mcmsEnabled { - // Transfer ownership to timelock so that we can promote the zero digest later down the line. - transferToTimelock(t, tenv, state, source, dest) - } - - var mcmsConfig *MCMSConfig - if tc.mcmsEnabled { - mcmsConfig = &MCMSConfig{ - MinDelay: 0, - } - } - - fqCfg1 := DefaultFeeQuoterDestChainConfig() - fqCfg2 := DefaultFeeQuoterDestChainConfig() - fqCfg2.DestGasOverhead = 1000 - _, err = commonchangeset.ApplyChangesets(t, tenv.Env, tenv.TimelockContracts(t), []commonchangeset.ChangesetApplication{ - { - Changeset: commonchangeset.WrapChangeSet(UpdateFeeQuoterDests), - Config: UpdateFeeQuoterDestsConfig{ - UpdatesByChain: map[uint64]map[uint64]fee_quoter.FeeQuoterDestChainConfig{ - source: { - dest: fqCfg1, - }, - dest: { - source: fqCfg2, - }, - }, - MCMS: mcmsConfig, - }, - }, - }) - require.NoError(t, err) - - // Assert the fq configuration is as we expect. - source2destCfg, err := state.Chains[source].FeeQuoter.GetDestChainConfig(&bind.CallOpts{Context: ctx}, dest) - require.NoError(t, err) - AssertEqualFeeConfig(t, fqCfg1, source2destCfg) - dest2sourceCfg, err := state.Chains[dest].FeeQuoter.GetDestChainConfig(&bind.CallOpts{Context: ctx}, source) - require.NoError(t, err) - AssertEqualFeeConfig(t, fqCfg2, dest2sourceCfg) - }) - } -} - -func TestUpdateRouterRamps(t *testing.T) { - for _, tc := range []struct { - name string - mcmsEnabled bool - }{ - { - name: "MCMS enabled", - mcmsEnabled: true, - }, - { - name: "MCMS disabled", - mcmsEnabled: false, - }, - } { - t.Run(tc.name, func(t *testing.T) { - ctx := testcontext.Get(t) - tenv := NewMemoryEnvironment(t) - state, err := LoadOnchainState(tenv.Env) - require.NoError(t, err) - - allChains := maps.Keys(tenv.Env.Chains) - source := allChains[0] - dest := allChains[1] - - if tc.mcmsEnabled { - // Transfer ownership to timelock so that we can promote the zero digest later down the line. - transferToTimelock(t, tenv, state, source, dest) - } - - var mcmsConfig *MCMSConfig - if tc.mcmsEnabled { - mcmsConfig = &MCMSConfig{ - MinDelay: 0, - } - } - - // Updates test router. - _, err = commonchangeset.ApplyChangesets(t, tenv.Env, tenv.TimelockContracts(t), []commonchangeset.ChangesetApplication{ - { - Changeset: commonchangeset.WrapChangeSet(UpdateRouterRamps), - Config: UpdateRouterRampsConfig{ - TestRouter: true, - UpdatesByChain: map[uint64]RouterUpdates{ - source: { - OffRampUpdates: map[uint64]bool{ - dest: true, - }, - OnRampUpdates: map[uint64]bool{ - dest: true, - }, - }, - dest: { - OffRampUpdates: map[uint64]bool{ - source: true, - }, - OnRampUpdates: map[uint64]bool{ - source: true, - }, - }, - }, - MCMS: mcmsConfig, - }, - }, - }) - require.NoError(t, err) - - // Assert the router configuration is as we expect. - source2destOnRampTest, err := state.Chains[source].TestRouter.GetOnRamp(&bind.CallOpts{Context: ctx}, dest) - require.NoError(t, err) - require.Equal(t, state.Chains[source].OnRamp.Address(), source2destOnRampTest) - source2destOnRampReal, err := state.Chains[source].Router.GetOnRamp(&bind.CallOpts{Context: ctx}, dest) - require.NoError(t, err) - require.Equal(t, common.HexToAddress("0x0"), source2destOnRampReal) - }) - } -} - -func TestUpdateNonceManagersCS(t *testing.T) { - for _, tc := range []struct { - name string - mcmsEnabled bool - }{ - { - name: "MCMS enabled", - mcmsEnabled: true, - }, - { - name: "MCMS disabled", - mcmsEnabled: false, - }, - } { - t.Run(tc.name, func(t *testing.T) { - tenv := NewMemoryEnvironment(t) - state, err := LoadOnchainState(tenv.Env) - require.NoError(t, err) - - allChains := maps.Keys(tenv.Env.Chains) - source := allChains[0] - dest := allChains[1] - - if tc.mcmsEnabled { - // Transfer ownership to timelock so that we can promote the zero digest later down the line. - transferToTimelock(t, tenv, state, source, dest) - } - - var mcmsConfig *MCMSConfig - if tc.mcmsEnabled { - mcmsConfig = &MCMSConfig{ - MinDelay: 0, - } - } - - _, err = commonchangeset.ApplyChangesets(t, tenv.Env, tenv.TimelockContracts(t), []commonchangeset.ChangesetApplication{ - { - Changeset: commonchangeset.WrapChangeSet(UpdateNonceManagersCS), - Config: UpdateNonceManagerConfig{ - UpdatesByChain: map[uint64]NonceManagerUpdate{ - source: { - RemovedAuthCallers: []common.Address{state.Chains[source].OnRamp.Address()}, - }, - }, - MCMS: mcmsConfig, - }, - }, - }) - require.NoError(t, err) - // Assert the nonce manager configuration is as we expect. - callers, err := state.Chains[source].NonceManager.GetAllAuthorizedCallers(nil) - require.NoError(t, err) - require.NotContains(t, callers, state.Chains[source].OnRamp.Address()) - require.Contains(t, callers, state.Chains[source].OffRamp.Address()) - }) - } -} diff --git a/deployment/ccip/changeset/cs_deploy_chain.go b/deployment/ccip/changeset/cs_deploy_chain.go deleted file mode 100644 index 444f204dd0a..00000000000 --- a/deployment/ccip/changeset/cs_deploy_chain.go +++ /dev/null @@ -1,402 +0,0 @@ -package changeset - -import ( - "fmt" - "math/big" - - "github.com/ethereum/go-ethereum/accounts/abi/bind" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/common/hexutil" - "github.com/smartcontractkit/ccip-owner-contracts/pkg/proposal/timelock" - "golang.org/x/sync/errgroup" - - "github.com/smartcontractkit/chainlink/deployment" - "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/internal" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/ccip_home" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/fee_quoter" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/nonce_manager" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/offramp" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/onramp" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/rmn_home" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/rmn_remote" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/router" -) - -var _ deployment.ChangeSet[DeployChainContractsConfig] = DeployChainContracts - -// DeployChainContracts deploys all new CCIP v1.6 or later contracts for the given chains. -// It returns the new addresses for the contracts. -// DeployChainContracts is idempotent. If there is an error, it will return the successfully deployed addresses and the error so that the caller can call the -// changeset again with the same input to retry the failed deployment. -// Caller should update the environment's address book with the returned addresses. -// Points to note : -// In case of migrating from legacy ccip to 1.6, the previous RMN address should be set while deploying RMNRemote. -// if there is no existing RMN address found, RMNRemote will be deployed with 0x0 address for previous RMN address -// which will set RMN to 0x0 address immutably in RMNRemote. -func DeployChainContracts(env deployment.Environment, c DeployChainContractsConfig) (deployment.ChangesetOutput, error) { - if err := c.Validate(); err != nil { - return deployment.ChangesetOutput{}, fmt.Errorf("invalid DeployChainContractsConfig: %w", err) - } - newAddresses := deployment.NewMemoryAddressBook() - err := deployChainContractsForChains(env, newAddresses, c.HomeChainSelector, c.ChainSelectors) - if err != nil { - env.Logger.Errorw("Failed to deploy CCIP contracts", "err", err, "newAddresses", newAddresses) - return deployment.ChangesetOutput{AddressBook: newAddresses}, deployment.MaybeDataErr(err) - } - return deployment.ChangesetOutput{ - Proposals: []timelock.MCMSWithTimelockProposal{}, - AddressBook: newAddresses, - JobSpecs: nil, - }, nil -} - -type DeployChainContractsConfig struct { - ChainSelectors []uint64 - HomeChainSelector uint64 -} - -func (c DeployChainContractsConfig) Validate() error { - for _, cs := range c.ChainSelectors { - if err := deployment.IsValidChainSelector(cs); err != nil { - return fmt.Errorf("invalid chain selector: %d - %w", cs, err) - } - } - if err := deployment.IsValidChainSelector(c.HomeChainSelector); err != nil { - return fmt.Errorf("invalid home chain selector: %d - %w", c.HomeChainSelector, err) - } - return nil -} - -func deployChainContractsForChains( - e deployment.Environment, - ab deployment.AddressBook, - homeChainSel uint64, - chainsToDeploy []uint64) error { - existingState, err := LoadOnchainState(e) - if err != nil { - e.Logger.Errorw("Failed to load existing onchain state", "err") - return err - } - - capReg := existingState.Chains[homeChainSel].CapabilityRegistry - if capReg == nil { - e.Logger.Errorw("Failed to get capability registry") - return fmt.Errorf("capability registry not found") - } - cr, err := capReg.GetHashedCapabilityId( - &bind.CallOpts{}, internal.CapabilityLabelledName, internal.CapabilityVersion) - if err != nil { - e.Logger.Errorw("Failed to get hashed capability id", "err", err) - return err - } - if cr != internal.CCIPCapabilityID { - return fmt.Errorf("unexpected mismatch between calculated ccip capability id (%s) and expected ccip capability id constant (%s)", - hexutil.Encode(cr[:]), - hexutil.Encode(internal.CCIPCapabilityID[:])) - } - capability, err := capReg.GetCapability(nil, internal.CCIPCapabilityID) - if err != nil { - e.Logger.Errorw("Failed to get capability", "err", err) - return err - } - ccipHome, err := ccip_home.NewCCIPHome(capability.ConfigurationContract, e.Chains[homeChainSel].Client) - if err != nil { - e.Logger.Errorw("Failed to get ccip config", "err", err) - return err - } - if ccipHome.Address() != existingState.Chains[homeChainSel].CCIPHome.Address() { - return fmt.Errorf("ccip home address mismatch") - } - rmnHome := existingState.Chains[homeChainSel].RMNHome - if rmnHome == nil { - e.Logger.Errorw("Failed to get rmn home", "err", err) - return fmt.Errorf("rmn home not found") - } - deployGrp := errgroup.Group{} - for _, chainSel := range chainsToDeploy { - chain, ok := e.Chains[chainSel] - if !ok { - return fmt.Errorf("chain %d not found", chainSel) - } - if existingState.Chains[chainSel].LinkToken == nil || existingState.Chains[chainSel].Weth9 == nil { - return fmt.Errorf("fee tokens not found for chain %d", chainSel) - } - deployGrp.Go( - func() error { - err := deployChainContracts(e, chain, ab, rmnHome) - if err != nil { - e.Logger.Errorw("Failed to deploy chain contracts", "chain", chainSel, "err", err) - return fmt.Errorf("failed to deploy chain contracts for chain %d: %w", chainSel, err) - } - return nil - }) - } - if err := deployGrp.Wait(); err != nil { - e.Logger.Errorw("Failed to deploy chain contracts", "err", err) - return err - } - return nil -} - -func deployChainContracts( - e deployment.Environment, - chain deployment.Chain, - ab deployment.AddressBook, - rmnHome *rmn_home.RMNHome, -) error { - // check for existing contracts - state, err := LoadOnchainState(e) - if err != nil { - e.Logger.Errorw("Failed to load existing onchain state", "err") - return err - } - chainState, chainExists := state.Chains[chain.Selector] - if !chainExists { - return fmt.Errorf("chain %s not found in existing state, deploy the prerequisites first", chain.String()) - } - if chainState.Weth9 == nil { - return fmt.Errorf("weth9 not found for chain %s, deploy the prerequisites first", chain.String()) - } - if chainState.Timelock == nil { - return fmt.Errorf("timelock not found for chain %s, deploy the mcms contracts first", chain.String()) - } - weth9Contract := chainState.Weth9 - if chainState.LinkToken == nil { - return fmt.Errorf("link token not found for chain %s, deploy the prerequisites first", chain.String()) - } - linkTokenContract := chainState.LinkToken - if chainState.TokenAdminRegistry == nil { - return fmt.Errorf("token admin registry not found for chain %s, deploy the prerequisites first", chain.String()) - } - tokenAdminReg := chainState.TokenAdminRegistry - if chainState.RegistryModule == nil { - return fmt.Errorf("registry module not found for chain %s, deploy the prerequisites first", chain.String()) - } - if chainState.Router == nil { - return fmt.Errorf("router not found for chain %s, deploy the prerequisites first", chain.String()) - } - rmnProxyContract := chainState.RMNProxy - if chainState.RMNProxy == nil { - e.Logger.Errorw("RMNProxy not found", "chain", chain.String()) - return fmt.Errorf("rmn proxy not found for chain %s, deploy the prerequisites first", chain.String()) - } - var rmnLegacyAddr common.Address - if chainState.MockRMN != nil { - rmnLegacyAddr = chainState.MockRMN.Address() - } - // If RMN is deployed, set rmnLegacyAddr to the RMN address - if chainState.RMN != nil { - rmnLegacyAddr = chainState.RMN.Address() - } - if rmnLegacyAddr == (common.Address{}) { - e.Logger.Warnf("No legacy RMN contract found for chain %s, will not setRMN in RMNRemote", chain.String()) - } - rmnRemoteContract := chainState.RMNRemote - if chainState.RMNRemote == nil { - // TODO: Correctly configure RMN remote. - rmnRemote, err := deployment.DeployContract(e.Logger, chain, ab, - func(chain deployment.Chain) deployment.ContractDeploy[*rmn_remote.RMNRemote] { - rmnRemoteAddr, tx, rmnRemote, err2 := rmn_remote.DeployRMNRemote( - chain.DeployerKey, - chain.Client, - chain.Selector, - rmnLegacyAddr, - ) - return deployment.ContractDeploy[*rmn_remote.RMNRemote]{ - rmnRemoteAddr, rmnRemote, tx, deployment.NewTypeAndVersion(RMNRemote, deployment.Version1_6_0_dev), err2, - } - }) - if err != nil { - e.Logger.Errorw("Failed to deploy RMNRemote", "chain", chain.String(), "err", err) - return err - } - rmnRemoteContract = rmnRemote.Contract - } else { - e.Logger.Infow("rmn remote already deployed", "chain", chain.String(), "addr", chainState.RMNRemote.Address) - } - - activeDigest, err := rmnHome.GetActiveDigest(&bind.CallOpts{}) - if err != nil { - e.Logger.Errorw("Failed to get active digest", "chain", chain.String(), "err", err) - return err - } - e.Logger.Infow("setting active home digest to rmn remote", "chain", chain.String(), "digest", activeDigest) - - tx, err := rmnRemoteContract.SetConfig(chain.DeployerKey, rmn_remote.RMNRemoteConfig{ - RmnHomeContractConfigDigest: activeDigest, - Signers: []rmn_remote.RMNRemoteSigner{ - {NodeIndex: 0, OnchainPublicKey: common.Address{1}}, - }, - F: 0, // TODO: update when we have signers - }) - if _, err := deployment.ConfirmIfNoError(chain, tx, err); err != nil { - e.Logger.Errorw("Failed to confirm RMNRemote config", "chain", chain.String(), "err", err) - return err - } - if chainState.TestRouter == nil { - _, err := deployment.DeployContract(e.Logger, chain, ab, - func(chain deployment.Chain) deployment.ContractDeploy[*router.Router] { - routerAddr, tx2, routerC, err2 := router.DeployRouter( - chain.DeployerKey, - chain.Client, - weth9Contract.Address(), - rmnProxyContract.Address(), - ) - return deployment.ContractDeploy[*router.Router]{ - routerAddr, routerC, tx2, deployment.NewTypeAndVersion(TestRouter, deployment.Version1_2_0), err2, - } - }) - if err != nil { - e.Logger.Errorw("Failed to deploy test router", "chain", chain.String(), "err", err) - return err - } - } else { - e.Logger.Infow("test router already deployed", "chain", chain.String(), "addr", chainState.TestRouter.Address) - } - - nmContract := chainState.NonceManager - if chainState.NonceManager == nil { - nonceManager, err := deployment.DeployContract(e.Logger, chain, ab, - func(chain deployment.Chain) deployment.ContractDeploy[*nonce_manager.NonceManager] { - nonceManagerAddr, tx2, nonceManager, err2 := nonce_manager.DeployNonceManager( - chain.DeployerKey, - chain.Client, - []common.Address{}, // Need to add onRamp after - ) - return deployment.ContractDeploy[*nonce_manager.NonceManager]{ - nonceManagerAddr, nonceManager, tx2, deployment.NewTypeAndVersion(NonceManager, deployment.Version1_6_0_dev), err2, - } - }) - if err != nil { - e.Logger.Errorw("Failed to deploy nonce manager", "chain", chain.String(), "err", err) - return err - } - nmContract = nonceManager.Contract - } else { - e.Logger.Infow("nonce manager already deployed", "chain", chain.String(), "addr", chainState.NonceManager.Address) - } - feeQuoterContract := chainState.FeeQuoter - if chainState.FeeQuoter == nil { - feeQuoter, err := deployment.DeployContract(e.Logger, chain, ab, - func(chain deployment.Chain) deployment.ContractDeploy[*fee_quoter.FeeQuoter] { - prAddr, tx2, pr, err2 := fee_quoter.DeployFeeQuoter( - chain.DeployerKey, - chain.Client, - fee_quoter.FeeQuoterStaticConfig{ - MaxFeeJuelsPerMsg: big.NewInt(0).Mul(big.NewInt(2e2), big.NewInt(1e18)), - LinkToken: linkTokenContract.Address(), - TokenPriceStalenessThreshold: uint32(24 * 60 * 60), - }, - []common.Address{state.Chains[chain.Selector].Timelock.Address()}, // timelock should be able to update, ramps added after - []common.Address{weth9Contract.Address(), linkTokenContract.Address()}, // fee tokens - []fee_quoter.FeeQuoterTokenPriceFeedUpdate{}, - []fee_quoter.FeeQuoterTokenTransferFeeConfigArgs{}, // TODO: tokens - []fee_quoter.FeeQuoterPremiumMultiplierWeiPerEthArgs{ - { - PremiumMultiplierWeiPerEth: 9e17, // 0.9 ETH - Token: linkTokenContract.Address(), - }, - { - PremiumMultiplierWeiPerEth: 1e18, - Token: weth9Contract.Address(), - }, - }, - []fee_quoter.FeeQuoterDestChainConfigArgs{}, - ) - return deployment.ContractDeploy[*fee_quoter.FeeQuoter]{ - prAddr, pr, tx2, deployment.NewTypeAndVersion(FeeQuoter, deployment.Version1_6_0_dev), err2, - } - }) - if err != nil { - e.Logger.Errorw("Failed to deploy fee quoter", "chain", chain.String(), "err", err) - return err - } - feeQuoterContract = feeQuoter.Contract - } else { - e.Logger.Infow("fee quoter already deployed", "chain", chain.String(), "addr", chainState.FeeQuoter.Address) - } - onRampContract := chainState.OnRamp - if onRampContract == nil { - onRamp, err := deployment.DeployContract(e.Logger, chain, ab, - func(chain deployment.Chain) deployment.ContractDeploy[*onramp.OnRamp] { - onRampAddr, tx2, onRamp, err2 := onramp.DeployOnRamp( - chain.DeployerKey, - chain.Client, - onramp.OnRampStaticConfig{ - ChainSelector: chain.Selector, - RmnRemote: rmnProxyContract.Address(), - NonceManager: nmContract.Address(), - TokenAdminRegistry: tokenAdminReg.Address(), - }, - onramp.OnRampDynamicConfig{ - FeeQuoter: feeQuoterContract.Address(), - FeeAggregator: common.HexToAddress("0x1"), // TODO real fee aggregator - }, - []onramp.OnRampDestChainConfigArgs{}, - ) - return deployment.ContractDeploy[*onramp.OnRamp]{ - onRampAddr, onRamp, tx2, deployment.NewTypeAndVersion(OnRamp, deployment.Version1_6_0_dev), err2, - } - }) - if err != nil { - e.Logger.Errorw("Failed to deploy onramp", "chain", chain.String(), "err", err) - return err - } - onRampContract = onRamp.Contract - } else { - e.Logger.Infow("onramp already deployed", "chain", chain.String(), "addr", chainState.OnRamp.Address) - } - offRampContract := chainState.OffRamp - if offRampContract == nil { - offRamp, err := deployment.DeployContract(e.Logger, chain, ab, - func(chain deployment.Chain) deployment.ContractDeploy[*offramp.OffRamp] { - offRampAddr, tx2, offRamp, err2 := offramp.DeployOffRamp( - chain.DeployerKey, - chain.Client, - offramp.OffRampStaticConfig{ - ChainSelector: chain.Selector, - GasForCallExactCheck: 5_000, - RmnRemote: rmnProxyContract.Address(), - NonceManager: nmContract.Address(), - TokenAdminRegistry: tokenAdminReg.Address(), - }, - offramp.OffRampDynamicConfig{ - FeeQuoter: feeQuoterContract.Address(), - PermissionLessExecutionThresholdSeconds: uint32(86400), - IsRMNVerificationDisabled: true, - }, - []offramp.OffRampSourceChainConfigArgs{}, - ) - return deployment.ContractDeploy[*offramp.OffRamp]{ - Address: offRampAddr, Contract: offRamp, Tx: tx2, Tv: deployment.NewTypeAndVersion(OffRamp, deployment.Version1_6_0_dev), Err: err2, - } - }) - if err != nil { - e.Logger.Errorw("Failed to deploy offramp", "chain", chain.String(), "err", err) - return err - } - offRampContract = offRamp.Contract - } else { - e.Logger.Infow("offramp already deployed", "chain", chain.String(), "addr", chainState.OffRamp.Address) - } - // Basic wiring is always needed. - tx, err = feeQuoterContract.ApplyAuthorizedCallerUpdates(chain.DeployerKey, fee_quoter.AuthorizedCallersAuthorizedCallerArgs{ - // TODO: We enable the deployer initially to set prices - // Should be removed after. - AddedCallers: []common.Address{offRampContract.Address(), chain.DeployerKey.From}, - }) - if _, err := deployment.ConfirmIfNoError(chain, tx, err); err != nil { - e.Logger.Errorw("Failed to confirm fee quoter authorized caller update", "chain", chain.String(), "err", err) - return err - } - e.Logger.Infow("Added fee quoter authorized callers", "chain", chain.String(), "callers", []common.Address{offRampContract.Address(), chain.DeployerKey.From}) - tx, err = nmContract.ApplyAuthorizedCallerUpdates(chain.DeployerKey, nonce_manager.AuthorizedCallersAuthorizedCallerArgs{ - AddedCallers: []common.Address{offRampContract.Address(), onRampContract.Address()}, - }) - if _, err := deployment.ConfirmIfNoError(chain, tx, err); err != nil { - e.Logger.Errorw("Failed to update nonce manager with ramps", "chain", chain.String(), "err", err) - return err - } - e.Logger.Infow("Added nonce manager authorized callers", "chain", chain.String(), "callers", []common.Address{offRampContract.Address(), onRampContract.Address()}) - return nil -} diff --git a/deployment/ccip/changeset/cs_deploy_chain_test.go b/deployment/ccip/changeset/cs_deploy_chain_test.go deleted file mode 100644 index a72b1b1568b..00000000000 --- a/deployment/ccip/changeset/cs_deploy_chain_test.go +++ /dev/null @@ -1,116 +0,0 @@ -package changeset - -import ( - "encoding/json" - "fmt" - "testing" - - "github.com/stretchr/testify/require" - "go.uber.org/zap/zapcore" - - "github.com/smartcontractkit/chainlink/deployment" - commonchangeset "github.com/smartcontractkit/chainlink/deployment/common/changeset" - "github.com/smartcontractkit/chainlink/deployment/common/proposalutils" - commontypes "github.com/smartcontractkit/chainlink/deployment/common/types" - "github.com/smartcontractkit/chainlink/deployment/environment/memory" - "github.com/smartcontractkit/chainlink/v2/core/logger" -) - -func TestDeployChainContractsChangeset(t *testing.T) { - t.Parallel() - lggr := logger.TestLogger(t) - e := memory.NewMemoryEnvironment(t, lggr, zapcore.InfoLevel, memory.MemoryEnvironmentConfig{ - Bootstraps: 1, - Chains: 2, - Nodes: 4, - }) - selectors := e.AllChainSelectors() - homeChainSel := selectors[0] - nodes, err := deployment.NodeInfo(e.NodeIDs, e.Offchain) - require.NoError(t, err) - p2pIds := nodes.NonBootstraps().PeerIDs() - cfg := make(map[uint64]commontypes.MCMSWithTimelockConfig) - for _, chain := range e.AllChainSelectors() { - cfg[chain] = proposalutils.SingleGroupTimelockConfig(t) - } - var prereqCfg []DeployPrerequisiteConfigPerChain - for _, chain := range e.AllChainSelectors() { - prereqCfg = append(prereqCfg, DeployPrerequisiteConfigPerChain{ - ChainSelector: chain, - }) - } - e, err = commonchangeset.ApplyChangesets(t, e, nil, []commonchangeset.ChangesetApplication{ - { - Changeset: commonchangeset.WrapChangeSet(DeployHomeChain), - Config: DeployHomeChainConfig{ - HomeChainSel: homeChainSel, - RMNStaticConfig: NewTestRMNStaticConfig(), - RMNDynamicConfig: NewTestRMNDynamicConfig(), - NodeOperators: NewTestNodeOperator(e.Chains[homeChainSel].DeployerKey.From), - NodeP2PIDsPerNodeOpAdmin: map[string][][32]byte{ - "NodeOperator": p2pIds, - }, - }, - }, - { - Changeset: commonchangeset.WrapChangeSet(commonchangeset.DeployLinkToken), - Config: selectors, - }, - { - Changeset: commonchangeset.WrapChangeSet(commonchangeset.DeployMCMSWithTimelock), - Config: cfg, - }, - { - Changeset: commonchangeset.WrapChangeSet(DeployPrerequisites), - Config: DeployPrerequisiteConfig{ - Configs: prereqCfg, - }, - }, - { - Changeset: commonchangeset.WrapChangeSet(DeployChainContracts), - Config: DeployChainContractsConfig{ - ChainSelectors: selectors, - HomeChainSelector: homeChainSel, - }, - }, - }) - require.NoError(t, err) - - // load onchain state - state, err := LoadOnchainState(e) - require.NoError(t, err) - - // verify all contracts populated - require.NotNil(t, state.Chains[homeChainSel].CapabilityRegistry) - require.NotNil(t, state.Chains[homeChainSel].CCIPHome) - require.NotNil(t, state.Chains[homeChainSel].RMNHome) - for _, sel := range selectors { - require.NotNil(t, state.Chains[sel].LinkToken) - require.NotNil(t, state.Chains[sel].Weth9) - require.NotNil(t, state.Chains[sel].TokenAdminRegistry) - require.NotNil(t, state.Chains[sel].RegistryModule) - require.NotNil(t, state.Chains[sel].Router) - require.NotNil(t, state.Chains[sel].RMNRemote) - require.NotNil(t, state.Chains[sel].TestRouter) - require.NotNil(t, state.Chains[sel].NonceManager) - require.NotNil(t, state.Chains[sel].FeeQuoter) - require.NotNil(t, state.Chains[sel].OffRamp) - require.NotNil(t, state.Chains[sel].OnRamp) - } -} - -func TestDeployCCIPContracts(t *testing.T) { - t.Parallel() - e := NewMemoryEnvironment(t) - // Deploy all the CCIP contracts. - state, err := LoadOnchainState(e.Env) - require.NoError(t, err) - snap, err := state.View(e.Env.AllChainSelectors()) - require.NoError(t, err) - - // Assert expect every deployed address to be in the address book. - // TODO (CCIP-3047): Add the rest of CCIPv2 representation - b, err := json.MarshalIndent(snap, "", " ") - require.NoError(t, err) - fmt.Println(string(b)) -} diff --git a/deployment/ccip/changeset/cs_home_chain.go b/deployment/ccip/changeset/cs_home_chain.go deleted file mode 100644 index b92a8d132a4..00000000000 --- a/deployment/ccip/changeset/cs_home_chain.go +++ /dev/null @@ -1,418 +0,0 @@ -package changeset - -import ( - "bytes" - "context" - "encoding/json" - "fmt" - "math/big" - - "github.com/ethereum/go-ethereum/accounts/abi/bind" - "github.com/ethereum/go-ethereum/common" - "github.com/pkg/errors" - "github.com/smartcontractkit/ccip-owner-contracts/pkg/gethwrappers" - "github.com/smartcontractkit/ccip-owner-contracts/pkg/proposal/mcms" - "github.com/smartcontractkit/ccip-owner-contracts/pkg/proposal/timelock" - "golang.org/x/exp/maps" - - "github.com/smartcontractkit/chainlink-common/pkg/logger" - "github.com/smartcontractkit/chainlink/deployment/common/proposalutils" - - "github.com/smartcontractkit/chainlink/deployment" - "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/internal" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/ccip_home" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/rmn_home" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry_1_1_0" - p2ptypes "github.com/smartcontractkit/chainlink/v2/core/services/p2p/types" -) - -var _ deployment.ChangeSet[DeployHomeChainConfig] = DeployHomeChain - -// DeployHomeChain is a separate changeset because it is a standalone deployment performed once in home chain for the entire CCIP deployment. -func DeployHomeChain(env deployment.Environment, cfg DeployHomeChainConfig) (deployment.ChangesetOutput, error) { - err := cfg.Validate() - if err != nil { - return deployment.ChangesetOutput{}, errors.Wrapf(deployment.ErrInvalidConfig, "%v", err) - } - ab := deployment.NewMemoryAddressBook() - // Note we also deploy the cap reg. - _, err = deployHomeChain(env.Logger, env, ab, env.Chains[cfg.HomeChainSel], cfg.RMNStaticConfig, cfg.RMNDynamicConfig, cfg.NodeOperators, cfg.NodeP2PIDsPerNodeOpAdmin) - if err != nil { - env.Logger.Errorw("Failed to deploy cap reg", "err", err, "addresses", env.ExistingAddresses) - return deployment.ChangesetOutput{ - AddressBook: ab, - }, err - } - - return deployment.ChangesetOutput{ - Proposals: []timelock.MCMSWithTimelockProposal{}, - AddressBook: ab, - JobSpecs: nil, - }, nil -} - -type DeployHomeChainConfig struct { - HomeChainSel uint64 - RMNStaticConfig rmn_home.RMNHomeStaticConfig - RMNDynamicConfig rmn_home.RMNHomeDynamicConfig - NodeOperators []capabilities_registry.CapabilitiesRegistryNodeOperator - NodeP2PIDsPerNodeOpAdmin map[string][][32]byte -} - -func (c DeployHomeChainConfig) Validate() error { - if c.HomeChainSel == 0 { - return fmt.Errorf("home chain selector must be set") - } - if c.RMNDynamicConfig.OffchainConfig == nil { - return fmt.Errorf("offchain config for RMNHomeDynamicConfig must be set") - } - if c.RMNStaticConfig.OffchainConfig == nil { - return fmt.Errorf("offchain config for RMNHomeStaticConfig must be set") - } - if len(c.NodeOperators) == 0 { - return fmt.Errorf("node operators must be set") - } - for _, nop := range c.NodeOperators { - if nop.Admin == (common.Address{}) { - return fmt.Errorf("node operator admin address must be set") - } - if nop.Name == "" { - return fmt.Errorf("node operator name must be set") - } - if len(c.NodeP2PIDsPerNodeOpAdmin[nop.Name]) == 0 { - return fmt.Errorf("node operator %s must have node p2p ids provided", nop.Name) - } - } - - return nil -} - -// deployCapReg deploys the CapabilitiesRegistry contract if it is not already deployed -// and returns a deployment.ContractDeploy struct with the address and contract instance. -func deployCapReg( - lggr logger.Logger, - state CCIPOnChainState, - ab deployment.AddressBook, - chain deployment.Chain, -) (*deployment.ContractDeploy[*capabilities_registry.CapabilitiesRegistry], error) { - homeChainState, exists := state.Chains[chain.Selector] - if exists { - cr := homeChainState.CapabilityRegistry - if cr != nil { - lggr.Infow("Found CapabilitiesRegistry in chain state", "address", cr.Address().String()) - return &deployment.ContractDeploy[*capabilities_registry.CapabilitiesRegistry]{ - Address: cr.Address(), Contract: cr, Tv: deployment.NewTypeAndVersion(CapabilitiesRegistry, deployment.Version1_0_0), - }, nil - } - } - capReg, err := deployment.DeployContract(lggr, chain, ab, - func(chain deployment.Chain) deployment.ContractDeploy[*capabilities_registry.CapabilitiesRegistry] { - crAddr, tx, cr, err2 := capabilities_registry.DeployCapabilitiesRegistry( - chain.DeployerKey, - chain.Client, - ) - return deployment.ContractDeploy[*capabilities_registry.CapabilitiesRegistry]{ - Address: crAddr, Contract: cr, Tv: deployment.NewTypeAndVersion(CapabilitiesRegistry, deployment.Version1_0_0), Tx: tx, Err: err2, - } - }) - if err != nil { - lggr.Errorw("Failed to deploy capreg", "chain", chain.String(), "err", err) - return nil, err - } - return capReg, nil -} - -func deployHomeChain( - lggr logger.Logger, - e deployment.Environment, - ab deployment.AddressBook, - chain deployment.Chain, - rmnHomeStatic rmn_home.RMNHomeStaticConfig, - rmnHomeDynamic rmn_home.RMNHomeDynamicConfig, - nodeOps []capabilities_registry.CapabilitiesRegistryNodeOperator, - nodeP2PIDsPerNodeOpAdmin map[string][][32]byte, -) (*deployment.ContractDeploy[*capabilities_registry.CapabilitiesRegistry], error) { - // load existing state - state, err := LoadOnchainState(e) - if err != nil { - return nil, fmt.Errorf("failed to load onchain state: %w", err) - } - // Deploy CapabilitiesRegistry, CCIPHome, RMNHome - capReg, err := deployCapReg(lggr, state, ab, chain) - if err != nil { - return nil, err - } - - lggr.Infow("deployed/connected to capreg", "addr", capReg.Address) - ccipHome, err := deployment.DeployContract( - lggr, chain, ab, - func(chain deployment.Chain) deployment.ContractDeploy[*ccip_home.CCIPHome] { - ccAddr, tx, cc, err2 := ccip_home.DeployCCIPHome( - chain.DeployerKey, - chain.Client, - capReg.Address, - ) - return deployment.ContractDeploy[*ccip_home.CCIPHome]{ - Address: ccAddr, Tv: deployment.NewTypeAndVersion(CCIPHome, deployment.Version1_6_0_dev), Tx: tx, Err: err2, Contract: cc, - } - }) - if err != nil { - lggr.Errorw("Failed to deploy CCIPHome", "chain", chain.String(), "err", err) - return nil, err - } - - rmnHome, err := deployment.DeployContract( - lggr, chain, ab, - func(chain deployment.Chain) deployment.ContractDeploy[*rmn_home.RMNHome] { - rmnAddr, tx, rmn, err2 := rmn_home.DeployRMNHome( - chain.DeployerKey, - chain.Client, - ) - return deployment.ContractDeploy[*rmn_home.RMNHome]{ - Address: rmnAddr, Tv: deployment.NewTypeAndVersion(RMNHome, deployment.Version1_6_0_dev), Tx: tx, Err: err2, Contract: rmn, - } - }, - ) - if err != nil { - lggr.Errorw("Failed to deploy RMNHome", "chain", chain.String(), "err", err) - return nil, err - } - - // considering the RMNHome is recently deployed, there is no digest to overwrite - tx, err := rmnHome.Contract.SetCandidate(chain.DeployerKey, rmnHomeStatic, rmnHomeDynamic, [32]byte{}) - if _, err := deployment.ConfirmIfNoError(chain, tx, err); err != nil { - lggr.Errorw("Failed to set candidate on RMNHome", "err", err) - return nil, err - } - - rmnCandidateDigest, err := rmnHome.Contract.GetCandidateDigest(nil) - if err != nil { - lggr.Errorw("Failed to get RMNHome candidate digest", "chain", chain.String(), "err", err) - return nil, err - } - - tx, err = rmnHome.Contract.PromoteCandidateAndRevokeActive(chain.DeployerKey, rmnCandidateDigest, [32]byte{}) - if _, err := deployment.ConfirmIfNoError(chain, tx, err); err != nil { - lggr.Errorw("Failed to promote candidate and revoke active on RMNHome", "chain", chain.String(), "err", err) - return nil, err - } - - rmnActiveDigest, err := rmnHome.Contract.GetActiveDigest(nil) - if err != nil { - lggr.Errorw("Failed to get RMNHome active digest", "chain", chain.String(), "err", err) - return nil, err - } - lggr.Infow("Got rmn home active digest", "digest", rmnActiveDigest) - - if rmnActiveDigest != rmnCandidateDigest { - lggr.Errorw("RMNHome active digest does not match previously candidate digest", - "active", rmnActiveDigest, "candidate", rmnCandidateDigest) - return nil, errors.New("RMNHome active digest does not match candidate digest") - } - - tx, err = capReg.Contract.AddCapabilities(chain.DeployerKey, []capabilities_registry.CapabilitiesRegistryCapability{ - { - LabelledName: internal.CapabilityLabelledName, - Version: internal.CapabilityVersion, - CapabilityType: 2, // consensus. not used (?) - ResponseType: 0, // report. not used (?) - ConfigurationContract: ccipHome.Address, - }, - }) - if _, err := deployment.ConfirmIfNoError(chain, tx, err); err != nil { - lggr.Errorw("Failed to add capabilities", "chain", chain.String(), "err", err) - return nil, err - } - - tx, err = capReg.Contract.AddNodeOperators(chain.DeployerKey, nodeOps) - txBlockNum, err := deployment.ConfirmIfNoError(chain, tx, err) - if err != nil { - lggr.Errorw("Failed to add node operators", "chain", chain.String(), "err", err) - return nil, err - } - addedEvent, err := capReg.Contract.FilterNodeOperatorAdded(&bind.FilterOpts{ - Start: txBlockNum, - Context: context.Background(), - }, nil, nil) - if err != nil { - lggr.Errorw("Failed to filter NodeOperatorAdded event", "chain", chain.String(), "err", err) - return capReg, err - } - // Need to fetch nodeoperators ids to be able to add nodes for corresponding node operators - p2pIDsByNodeOpId := make(map[uint32][][32]byte) - for addedEvent.Next() { - for nopName, p2pId := range nodeP2PIDsPerNodeOpAdmin { - if addedEvent.Event.Name == nopName { - lggr.Infow("Added node operator", "admin", addedEvent.Event.Admin, "name", addedEvent.Event.Name) - p2pIDsByNodeOpId[addedEvent.Event.NodeOperatorId] = p2pId - } - } - } - if len(p2pIDsByNodeOpId) != len(nodeP2PIDsPerNodeOpAdmin) { - lggr.Errorw("Failed to add all node operators", "added", maps.Keys(p2pIDsByNodeOpId), "expected", maps.Keys(nodeP2PIDsPerNodeOpAdmin), "chain", chain.String()) - return capReg, errors.New("failed to add all node operators") - } - // Adds initial set of nodes to CR, who all have the CCIP capability - if err := addNodes(lggr, capReg.Contract, chain, p2pIDsByNodeOpId); err != nil { - return capReg, err - } - return capReg, nil -} - -func isEqualCapabilitiesRegistryNodeParams(a, b capabilities_registry.CapabilitiesRegistryNodeParams) (bool, error) { - aBytes, err := json.Marshal(a) - if err != nil { - return false, err - } - bBytes, err := json.Marshal(b) - if err != nil { - return false, err - } - return bytes.Equal(aBytes, bBytes), nil -} - -func addNodes( - lggr logger.Logger, - capReg *capabilities_registry.CapabilitiesRegistry, - chain deployment.Chain, - p2pIDsByNodeOpId map[uint32][][32]byte, -) error { - var nodeParams []capabilities_registry.CapabilitiesRegistryNodeParams - nodes, err := capReg.GetNodes(nil) - if err != nil { - return err - } - existingNodeParams := make(map[p2ptypes.PeerID]capabilities_registry.CapabilitiesRegistryNodeParams) - for _, node := range nodes { - existingNodeParams[node.P2pId] = capabilities_registry.CapabilitiesRegistryNodeParams{ - NodeOperatorId: node.NodeOperatorId, - Signer: node.Signer, - P2pId: node.P2pId, - HashedCapabilityIds: node.HashedCapabilityIds, - } - } - for nopID, p2pIDs := range p2pIDsByNodeOpId { - for _, p2pID := range p2pIDs { - // if any p2pIDs are empty throw error - if bytes.Equal(p2pID[:], make([]byte, 32)) { - return errors.Wrapf(errors.New("empty p2pID"), "p2pID: %x selector: %d", p2pID, chain.Selector) - } - nodeParam := capabilities_registry.CapabilitiesRegistryNodeParams{ - NodeOperatorId: nopID, - Signer: p2pID, // Not used in tests - P2pId: p2pID, - EncryptionPublicKey: p2pID, // Not used in tests - HashedCapabilityIds: [][32]byte{internal.CCIPCapabilityID}, - } - if existing, ok := existingNodeParams[p2pID]; ok { - if isEqual, err := isEqualCapabilitiesRegistryNodeParams(existing, nodeParam); err != nil && isEqual { - lggr.Infow("Node already exists", "p2pID", p2pID) - continue - } - } - - nodeParams = append(nodeParams, nodeParam) - } - } - if len(nodeParams) == 0 { - lggr.Infow("No new nodes to add") - return nil - } - tx, err := capReg.AddNodes(chain.DeployerKey, nodeParams) - if err != nil { - lggr.Errorw("Failed to add nodes", "chain", chain.String(), "err", deployment.MaybeDataErr(err)) - return err - } - _, err = chain.Confirm(tx) - return err -} - -type RemoveDONsConfig struct { - HomeChainSel uint64 - DonIDs []uint32 - MCMS *MCMSConfig -} - -func (c RemoveDONsConfig) Validate(homeChain CCIPChainState) error { - if err := deployment.IsValidChainSelector(c.HomeChainSel); err != nil { - return fmt.Errorf("home chain selector must be set %w", err) - } - if len(c.DonIDs) == 0 { - return fmt.Errorf("don ids must be set") - } - // Cap reg must exist - if homeChain.CapabilityRegistry == nil { - return fmt.Errorf("cap reg does not exist") - } - if homeChain.CCIPHome == nil { - return fmt.Errorf("ccip home does not exist") - } - if err := internal.DONIdExists(homeChain.CapabilityRegistry, c.DonIDs); err != nil { - return err - } - return nil -} - -// RemoveDONs removes DONs from the CapabilitiesRegistry contract. -// TODO: Could likely be moved to common, but needs -// a common state struct first. -func RemoveDONs(e deployment.Environment, cfg RemoveDONsConfig) (deployment.ChangesetOutput, error) { - state, err := LoadOnchainState(e) - if err != nil { - return deployment.ChangesetOutput{}, err - } - homeChain, ok := e.Chains[cfg.HomeChainSel] - if !ok { - return deployment.ChangesetOutput{}, fmt.Errorf("home chain %d not found", cfg.HomeChainSel) - } - homeChainState := state.Chains[cfg.HomeChainSel] - if err := cfg.Validate(homeChainState); err != nil { - return deployment.ChangesetOutput{}, err - } - txOpts := homeChain.DeployerKey - if cfg.MCMS != nil { - txOpts = deployment.SimTransactOpts() - } - - tx, err := homeChainState.CapabilityRegistry.RemoveDONs(txOpts, cfg.DonIDs) - if err != nil { - return deployment.ChangesetOutput{}, err - } - if cfg.MCMS == nil { - _, err = homeChain.Confirm(tx) - if err != nil { - return deployment.ChangesetOutput{}, err - } - e.Logger.Infof("Removed dons using deployer key tx %s", tx.Hash().String()) - return deployment.ChangesetOutput{}, nil - } - p, err := proposalutils.BuildProposalFromBatches( - map[uint64]common.Address{ - cfg.HomeChainSel: homeChainState.Timelock.Address(), - }, - map[uint64]*gethwrappers.ManyChainMultiSig{ - cfg.HomeChainSel: homeChainState.ProposerMcm, - }, - []timelock.BatchChainOperation{ - { - ChainIdentifier: mcms.ChainIdentifier(cfg.HomeChainSel), - Batch: []mcms.Operation{ - { - To: homeChainState.CapabilityRegistry.Address(), - Data: tx.Data(), - Value: big.NewInt(0), - }, - }, - }, - }, - "Remove DONs", - cfg.MCMS.MinDelay, - ) - if err != nil { - return deployment.ChangesetOutput{}, err - } - e.Logger.Infof("Created proposal to remove dons") - return deployment.ChangesetOutput{Proposals: []timelock.MCMSWithTimelockProposal{ - *p, - }}, nil -} diff --git a/deployment/ccip/changeset/cs_home_chain_test.go b/deployment/ccip/changeset/cs_home_chain_test.go deleted file mode 100644 index 8a2d4f87709..00000000000 --- a/deployment/ccip/changeset/cs_home_chain_test.go +++ /dev/null @@ -1,173 +0,0 @@ -package changeset - -import ( - "testing" - - "github.com/ethereum/go-ethereum/common" - "github.com/stretchr/testify/require" - "go.uber.org/zap/zapcore" - - "github.com/smartcontractkit/chainlink/deployment" - commoncs "github.com/smartcontractkit/chainlink/deployment/common/changeset" - "github.com/smartcontractkit/chainlink/deployment/common/proposalutils" - "github.com/smartcontractkit/chainlink/deployment/common/view/v1_0" - "github.com/smartcontractkit/chainlink/deployment/environment/memory" - "github.com/smartcontractkit/chainlink/v2/core/logger" -) - -func TestDeployHomeChain(t *testing.T) { - t.Parallel() - lggr := logger.TestLogger(t) - e := memory.NewMemoryEnvironment(t, lggr, zapcore.InfoLevel, memory.MemoryEnvironmentConfig{ - Bootstraps: 1, - Chains: 2, - Nodes: 4, - }) - homeChainSel := e.AllChainSelectors()[0] - nodes, err := deployment.NodeInfo(e.NodeIDs, e.Offchain) - require.NoError(t, err) - p2pIds := nodes.NonBootstraps().PeerIDs() - homeChainCfg := DeployHomeChainConfig{ - HomeChainSel: homeChainSel, - RMNStaticConfig: NewTestRMNStaticConfig(), - RMNDynamicConfig: NewTestRMNDynamicConfig(), - NodeOperators: NewTestNodeOperator(e.Chains[homeChainSel].DeployerKey.From), - NodeP2PIDsPerNodeOpAdmin: map[string][][32]byte{ - "NodeOperator": p2pIds, - }, - } - output, err := DeployHomeChain(e, homeChainCfg) - require.NoError(t, err) - require.NoError(t, e.ExistingAddresses.Merge(output.AddressBook)) - state, err := LoadOnchainState(e) - require.NoError(t, err) - require.NotNil(t, state.Chains[homeChainSel].CapabilityRegistry) - require.NotNil(t, state.Chains[homeChainSel].CCIPHome) - require.NotNil(t, state.Chains[homeChainSel].RMNHome) - snap, err := state.View([]uint64{homeChainSel}) - require.NoError(t, err) - chainName := e.Chains[homeChainSel].Name() - _, ok := snap[chainName] - require.True(t, ok) - capRegSnap, ok := snap[chainName].CapabilityRegistry[state.Chains[homeChainSel].CapabilityRegistry.Address().String()] - require.True(t, ok) - require.NotNil(t, capRegSnap) - require.Equal(t, capRegSnap.Nops, []v1_0.NopView{ - { - Admin: e.Chains[homeChainSel].DeployerKey.From, - Name: "NodeOperator", - }, - }) - require.Len(t, capRegSnap.Nodes, len(p2pIds)) -} - -func TestRemoveDonsValidate(t *testing.T) { - e := NewMemoryEnvironment(t) - s, err := LoadOnchainState(e.Env) - require.NoError(t, err) - homeChain := s.Chains[e.HomeChainSel] - var tt = []struct { - name string - config RemoveDONsConfig - expectErr bool - }{ - { - name: "invalid home", - config: RemoveDONsConfig{ - HomeChainSel: 0, - DonIDs: []uint32{1}, - }, - expectErr: true, - }, - { - name: "invalid dons", - config: RemoveDONsConfig{ - HomeChainSel: e.HomeChainSel, - DonIDs: []uint32{1377}, - }, - expectErr: true, - }, - { - name: "no dons", - config: RemoveDONsConfig{ - HomeChainSel: e.HomeChainSel, - DonIDs: []uint32{}, - }, - expectErr: true, - }, - { - name: "success", - config: RemoveDONsConfig{ - HomeChainSel: e.HomeChainSel, - DonIDs: []uint32{1}, - }, - expectErr: false, - }, - } - for _, tc := range tt { - t.Run(tc.name, func(t *testing.T) { - err := tc.config.Validate(homeChain) - if tc.expectErr { - require.Error(t, err) - } else { - require.NoError(t, err) - } - }) - } -} - -func TestRemoveDons(t *testing.T) { - e := NewMemoryEnvironment(t) - s, err := LoadOnchainState(e.Env) - require.NoError(t, err) - homeChain := s.Chains[e.HomeChainSel] - - // Remove a don w/o MCMS - donsBefore, err := homeChain.CapabilityRegistry.GetDONs(nil) - require.NoError(t, err) - e.Env, err = commoncs.ApplyChangesets(t, e.Env, nil, []commoncs.ChangesetApplication{ - { - Changeset: commoncs.WrapChangeSet(RemoveDONs), - Config: RemoveDONsConfig{ - HomeChainSel: e.HomeChainSel, - DonIDs: []uint32{donsBefore[0].Id}, - }, - }, - }) - require.NoError(t, err) - donsAfter, err := homeChain.CapabilityRegistry.GetDONs(nil) - require.NoError(t, err) - require.Len(t, donsAfter, len(donsBefore)-1) - - // Remove a don w/ MCMS - donsBefore, err = homeChain.CapabilityRegistry.GetDONs(nil) - require.NoError(t, err) - e.Env, err = commoncs.ApplyChangesets(t, e.Env, map[uint64]*proposalutils.TimelockExecutionContracts{ - e.HomeChainSel: { - Timelock: s.Chains[e.HomeChainSel].Timelock, - CallProxy: s.Chains[e.HomeChainSel].CallProxy, - }, - }, []commoncs.ChangesetApplication{ - { - Changeset: commoncs.WrapChangeSet(commoncs.TransferToMCMSWithTimelock), - Config: commoncs.TransferToMCMSWithTimelockConfig{ - ContractsByChain: map[uint64][]common.Address{ - e.HomeChainSel: {homeChain.CapabilityRegistry.Address()}, - }, - MinDelay: 0, - }, - }, - { - Changeset: commoncs.WrapChangeSet(RemoveDONs), - Config: RemoveDONsConfig{ - HomeChainSel: e.HomeChainSel, - DonIDs: []uint32{donsBefore[0].Id}, - MCMS: &MCMSConfig{MinDelay: 0}, - }, - }, - }) - require.NoError(t, err) - donsAfter, err = homeChain.CapabilityRegistry.GetDONs(nil) - require.NoError(t, err) - require.Len(t, donsAfter, len(donsBefore)-1) -} diff --git a/deployment/ccip/changeset/cs_jobspec_test.go b/deployment/ccip/changeset/cs_jobspec_test.go deleted file mode 100644 index a0445b0d5ee..00000000000 --- a/deployment/ccip/changeset/cs_jobspec_test.go +++ /dev/null @@ -1,36 +0,0 @@ -package changeset - -import ( - "testing" - - "github.com/stretchr/testify/require" - "go.uber.org/zap/zapcore" - - "github.com/smartcontractkit/chainlink/deployment" - "github.com/smartcontractkit/chainlink/deployment/environment/memory" - ccip "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/validate" - "github.com/smartcontractkit/chainlink/v2/core/logger" -) - -func TestJobSpecChangeset(t *testing.T) { - t.Parallel() - lggr := logger.TestLogger(t) - e := memory.NewMemoryEnvironment(t, lggr, zapcore.InfoLevel, memory.MemoryEnvironmentConfig{ - Chains: 1, - Nodes: 4, - }) - output, err := CCIPCapabilityJobspec(e, nil) - require.NoError(t, err) - require.NotNil(t, output.JobSpecs) - nodes, err := deployment.NodeInfo(e.NodeIDs, e.Offchain) - require.NoError(t, err) - for _, node := range nodes { - jobs, exists := output.JobSpecs[node.NodeID] - require.True(t, exists) - require.NotNil(t, jobs) - for _, job := range jobs { - _, err = ccip.ValidatedCCIPSpec(job) - require.NoError(t, err) - } - } -} diff --git a/deployment/ccip/changeset/cs_prerequisites.go b/deployment/ccip/changeset/cs_prerequisites.go deleted file mode 100644 index 94535df4a0f..00000000000 --- a/deployment/ccip/changeset/cs_prerequisites.go +++ /dev/null @@ -1,433 +0,0 @@ -package changeset - -import ( - "fmt" - - "github.com/ethereum/go-ethereum/common" - "github.com/pkg/errors" - "github.com/smartcontractkit/ccip-owner-contracts/pkg/proposal/timelock" - "golang.org/x/sync/errgroup" - - "github.com/smartcontractkit/chainlink/deployment" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/maybe_revert_message_receiver" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/mock_rmn_contract" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/price_registry_1_2_0" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/registry_module_owner_custom" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/rmn_contract" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/rmn_proxy_contract" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/router" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/token_admin_registry" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/weth9" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/shared/generated/multicall3" -) - -var ( - _ deployment.ChangeSet[DeployPrerequisiteConfig] = DeployPrerequisites -) - -// DeployPrerequisites deploys the pre-requisite contracts for CCIP -// pre-requisite contracts are the contracts which can be reused from previous versions of CCIP -// Or the contracts which are already deployed on the chain ( for example, tokens, feeds, etc) -// Caller should update the environment's address book with the returned addresses. -func DeployPrerequisites(env deployment.Environment, cfg DeployPrerequisiteConfig) (deployment.ChangesetOutput, error) { - err := cfg.Validate() - if err != nil { - return deployment.ChangesetOutput{}, errors.Wrapf(deployment.ErrInvalidConfig, "%v", err) - } - ab := deployment.NewMemoryAddressBook() - err = deployPrerequisiteChainContracts(env, ab, cfg) - if err != nil { - env.Logger.Errorw("Failed to deploy prerequisite contracts", "err", err, "addressBook", ab) - return deployment.ChangesetOutput{ - AddressBook: ab, - }, fmt.Errorf("failed to deploy prerequisite contracts: %w", err) - } - return deployment.ChangesetOutput{ - Proposals: []timelock.MCMSWithTimelockProposal{}, - AddressBook: ab, - JobSpecs: nil, - }, nil -} - -type DeployPrerequisiteContractsOpts struct { - USDCEnabled bool - Multicall3Enabled bool - LegacyDeploymentCfg *LegacyDeploymentConfig -} - -type LegacyDeploymentConfig struct { - RMNConfig *rmn_contract.RMNConfig - PriceRegStalenessThreshold uint32 -} - -type DeployPrerequisiteConfig struct { - Configs []DeployPrerequisiteConfigPerChain -} - -type DeployPrerequisiteConfigPerChain struct { - ChainSelector uint64 - Opts []PrerequisiteOpt - // TODO handle tokens and feeds in prerequisite config - Tokens map[TokenSymbol]common.Address - Feeds map[TokenSymbol]common.Address -} - -func (c DeployPrerequisiteConfig) Validate() error { - mapAllChainSelectors := make(map[uint64]struct{}) - for _, cfg := range c.Configs { - cs := cfg.ChainSelector - mapAllChainSelectors[cs] = struct{}{} - if err := deployment.IsValidChainSelector(cs); err != nil { - return fmt.Errorf("invalid chain selector: %d - %w", cs, err) - } - } - return nil -} - -type PrerequisiteOpt func(o *DeployPrerequisiteContractsOpts) - -func WithUSDCEnabled() PrerequisiteOpt { - return func(o *DeployPrerequisiteContractsOpts) { - o.USDCEnabled = true - } -} - -func WithMultiCall3Enabled() PrerequisiteOpt { - return func(o *DeployPrerequisiteContractsOpts) { - o.Multicall3Enabled = true - } -} - -func WithLegacyDeploymentEnabled(cfg LegacyDeploymentConfig) PrerequisiteOpt { - return func(o *DeployPrerequisiteContractsOpts) { - if cfg.PriceRegStalenessThreshold == 0 { - panic("PriceRegStalenessThreshold must be set") - } - // TODO validate RMNConfig - o.LegacyDeploymentCfg = &cfg - } -} - -func deployPrerequisiteChainContracts(e deployment.Environment, ab deployment.AddressBook, cfg DeployPrerequisiteConfig) error { - state, err := LoadOnchainState(e) - if err != nil { - e.Logger.Errorw("Failed to load existing onchain state", "err") - return err - } - deployGrp := errgroup.Group{} - for _, c := range cfg.Configs { - chain := e.Chains[c.ChainSelector] - deployGrp.Go(func() error { - err := deployPrerequisiteContracts(e, ab, state, chain, c.Opts...) - if err != nil { - e.Logger.Errorw("Failed to deploy prerequisite contracts", "chain", chain.String(), "err", err) - return err - } - return nil - }) - } - return deployGrp.Wait() -} - -// deployPrerequisiteContracts deploys the contracts that can be ported from previous CCIP version to the new one. -// This is only required for staging and test environments where the contracts are not already deployed. -func deployPrerequisiteContracts(e deployment.Environment, ab deployment.AddressBook, state CCIPOnChainState, chain deployment.Chain, opts ...PrerequisiteOpt) error { - deployOpts := &DeployPrerequisiteContractsOpts{} - for _, opt := range opts { - if opt != nil { - opt(deployOpts) - } - } - lggr := e.Logger - chainState, chainExists := state.Chains[chain.Selector] - var weth9Contract *weth9.WETH9 - var tokenAdminReg *token_admin_registry.TokenAdminRegistry - var registryModule *registry_module_owner_custom.RegistryModuleOwnerCustom - var rmnProxy *rmn_proxy_contract.RMNProxyContract - var r *router.Router - var mc3 *multicall3.Multicall3 - if chainExists { - weth9Contract = chainState.Weth9 - tokenAdminReg = chainState.TokenAdminRegistry - registryModule = chainState.RegistryModule - rmnProxy = chainState.RMNProxy - r = chainState.Router - mc3 = chainState.Multicall3 - } - var rmnAddr common.Address - // if we are setting up 1.5 version, deploy RMN contract based on the config provided - // else deploy the mock RMN contract - if deployOpts.LegacyDeploymentCfg != nil && deployOpts.LegacyDeploymentCfg.RMNConfig != nil { - if chainState.RMN == nil { - rmn, err := deployment.DeployContract(lggr, chain, ab, - func(chain deployment.Chain) deployment.ContractDeploy[*rmn_contract.RMNContract] { - rmnAddress, tx2, rmnC, err2 := rmn_contract.DeployRMNContract( - chain.DeployerKey, - chain.Client, - *deployOpts.LegacyDeploymentCfg.RMNConfig, - ) - return deployment.ContractDeploy[*rmn_contract.RMNContract]{ - Address: rmnAddress, Contract: rmnC, Tx: tx2, Tv: deployment.NewTypeAndVersion(RMN, deployment.Version1_5_0), Err: err2, - } - }) - if err != nil { - lggr.Errorw("Failed to deploy RMN", "chain", chain.String(), "err", err) - return err - } - rmnAddr = rmn.Address - } else { - lggr.Infow("RMN already deployed", "chain", chain.String(), "address", chainState.RMN.Address) - rmnAddr = chainState.RMN.Address() - } - } else { - if chainState.MockRMN == nil { - rmn, err := deployment.DeployContract(lggr, chain, ab, - func(chain deployment.Chain) deployment.ContractDeploy[*mock_rmn_contract.MockRMNContract] { - rmnAddress, tx2, rmnC, err2 := mock_rmn_contract.DeployMockRMNContract( - chain.DeployerKey, - chain.Client, - ) - return deployment.ContractDeploy[*mock_rmn_contract.MockRMNContract]{ - Address: rmnAddress, Contract: rmnC, Tx: tx2, Tv: deployment.NewTypeAndVersion(MockRMN, deployment.Version1_0_0), Err: err2, - } - }) - if err != nil { - lggr.Errorw("Failed to deploy mock RMN", "chain", chain.String(), "err", err) - return err - } - rmnAddr = rmn.Address - } else { - lggr.Infow("Mock RMN already deployed", "chain", chain.String(), "addr", chainState.MockRMN.Address) - rmnAddr = chainState.MockRMN.Address() - } - } - if rmnProxy == nil { - rmnProxyContract, err := deployment.DeployContract(lggr, chain, ab, - func(chain deployment.Chain) deployment.ContractDeploy[*rmn_proxy_contract.RMNProxyContract] { - rmnProxyAddr, tx2, rmnProxy, err2 := rmn_proxy_contract.DeployRMNProxyContract( - chain.DeployerKey, - chain.Client, - rmnAddr, - ) - return deployment.ContractDeploy[*rmn_proxy_contract.RMNProxyContract]{ - Address: rmnProxyAddr, Contract: rmnProxy, Tx: tx2, Tv: deployment.NewTypeAndVersion(ARMProxy, deployment.Version1_0_0), Err: err2, - } - }) - if err != nil { - lggr.Errorw("Failed to deploy RMNProxy", "chain", chain.String(), "err", err) - return err - } - rmnProxy = rmnProxyContract.Contract - } else { - lggr.Infow("RMNProxy already deployed", "chain", chain.String(), "addr", rmnProxy.Address) - // check if the RMNProxy is pointing to the correct RMN contract - currentRMNAddr, err := rmnProxy.GetARM(nil) - if err != nil { - lggr.Errorw("Failed to get RMN from RMNProxy", "chain", chain.String(), "err", err) - return err - } - if currentRMNAddr != rmnAddr { - lggr.Infow("RMNProxy is not pointing to the correct RMN contract, updating RMN", "chain", chain.String(), "currentRMN", currentRMNAddr, "expectedRMN", rmnAddr) - rmnOwner, err := rmnProxy.Owner(nil) - if err != nil { - lggr.Errorw("Failed to get owner of RMNProxy", "chain", chain.String(), "err", err) - return err - } - if rmnOwner != chain.DeployerKey.From { - lggr.Warnw( - "RMNProxy is not owned by the deployer and RMNProxy is not pointing to the correct RMN contract, "+ - "run SetRMNRemoteOnRMNProxy to update RMN with a proposal", - "chain", chain.String(), "owner", rmnOwner, "currentRMN", currentRMNAddr, "expectedRMN", rmnAddr) - } else { - tx, err := rmnProxy.SetARM(chain.DeployerKey, rmnAddr) - if err != nil { - lggr.Errorw("Failed to set RMN on RMNProxy", "chain", chain.String(), "err", err) - return err - } - _, err = chain.Confirm(tx) - if err != nil { - lggr.Errorw("Failed to confirm setRMN on RMNProxy", "chain", chain.String(), "err", err) - return err - } - } - } - } - if tokenAdminReg == nil { - tokenAdminRegistry, err := deployment.DeployContract(e.Logger, chain, ab, - func(chain deployment.Chain) deployment.ContractDeploy[*token_admin_registry.TokenAdminRegistry] { - tokenAdminRegistryAddr, tx2, tokenAdminRegistry, err2 := token_admin_registry.DeployTokenAdminRegistry( - chain.DeployerKey, - chain.Client) - return deployment.ContractDeploy[*token_admin_registry.TokenAdminRegistry]{ - Address: tokenAdminRegistryAddr, Contract: tokenAdminRegistry, Tx: tx2, Tv: deployment.NewTypeAndVersion(TokenAdminRegistry, deployment.Version1_5_0), Err: err2, - } - }) - if err != nil { - e.Logger.Errorw("Failed to deploy token admin registry", "chain", chain.String(), "err", err) - return err - } - tokenAdminReg = tokenAdminRegistry.Contract - } else { - e.Logger.Infow("tokenAdminRegistry already deployed", "chain", chain.String(), "addr", tokenAdminReg.Address) - } - if registryModule == nil { - customRegistryModule, err := deployment.DeployContract(e.Logger, chain, ab, - func(chain deployment.Chain) deployment.ContractDeploy[*registry_module_owner_custom.RegistryModuleOwnerCustom] { - regModAddr, tx2, regMod, err2 := registry_module_owner_custom.DeployRegistryModuleOwnerCustom( - chain.DeployerKey, - chain.Client, - tokenAdminReg.Address()) - return deployment.ContractDeploy[*registry_module_owner_custom.RegistryModuleOwnerCustom]{ - Address: regModAddr, Contract: regMod, Tx: tx2, Tv: deployment.NewTypeAndVersion(RegistryModule, deployment.Version1_5_0), Err: err2, - } - }) - if err != nil { - e.Logger.Errorw("Failed to deploy custom registry module", "chain", chain.String(), "err", err) - return err - } - registryModule = customRegistryModule.Contract - } else { - e.Logger.Infow("custom registry module already deployed", "chain", chain.String(), "addr", registryModule.Address) - } - isRegistryAdded, err := tokenAdminReg.IsRegistryModule(nil, registryModule.Address()) - if err != nil { - e.Logger.Errorw("Failed to check if registry module is added on token admin registry", "chain", chain.String(), "err", err) - return fmt.Errorf("failed to check if registry module is added on token admin registry: %w", err) - } - if !isRegistryAdded { - tx, err := tokenAdminReg.AddRegistryModule(chain.DeployerKey, registryModule.Address()) - if err != nil { - e.Logger.Errorw("Failed to assign registry module on token admin registry", "chain", chain.String(), "err", err) - return fmt.Errorf("failed to assign registry module on token admin registry: %w", err) - } - - _, err = chain.Confirm(tx) - if err != nil { - e.Logger.Errorw("Failed to confirm assign registry module on token admin registry", "chain", chain.String(), "err", err) - return fmt.Errorf("failed to confirm assign registry module on token admin registry: %w", err) - } - e.Logger.Infow("assigned registry module on token admin registry") - } - if weth9Contract == nil { - weth, err := deployment.DeployContract(lggr, chain, ab, - func(chain deployment.Chain) deployment.ContractDeploy[*weth9.WETH9] { - weth9Addr, tx2, weth9c, err2 := weth9.DeployWETH9( - chain.DeployerKey, - chain.Client, - ) - return deployment.ContractDeploy[*weth9.WETH9]{ - Address: weth9Addr, Contract: weth9c, Tx: tx2, Tv: deployment.NewTypeAndVersion(WETH9, deployment.Version1_0_0), Err: err2, - } - }) - if err != nil { - lggr.Errorw("Failed to deploy weth9", "chain", chain.String(), "err", err) - return err - } - weth9Contract = weth.Contract - } else { - lggr.Infow("weth9 already deployed", "chain", chain.String(), "addr", weth9Contract.Address) - weth9Contract = chainState.Weth9 - } - - // if router is not already deployed, we deploy it - if r == nil { - routerContract, err := deployment.DeployContract(e.Logger, chain, ab, - func(chain deployment.Chain) deployment.ContractDeploy[*router.Router] { - routerAddr, tx2, routerC, err2 := router.DeployRouter( - chain.DeployerKey, - chain.Client, - weth9Contract.Address(), - rmnProxy.Address(), - ) - return deployment.ContractDeploy[*router.Router]{ - Address: routerAddr, Contract: routerC, Tx: tx2, Tv: deployment.NewTypeAndVersion(Router, deployment.Version1_2_0), Err: err2, - } - }) - if err != nil { - e.Logger.Errorw("Failed to deploy router", "chain", chain.String(), "err", err) - return err - } - - r = routerContract.Contract - } else { - e.Logger.Infow("router already deployed", "chain", chain.String(), "addr", chainState.Router.Address) - } - if deployOpts.Multicall3Enabled && mc3 == nil { - _, err := deployment.DeployContract(e.Logger, chain, ab, - func(chain deployment.Chain) deployment.ContractDeploy[*multicall3.Multicall3] { - multicall3Addr, tx2, multicall3Wrapper, err2 := multicall3.DeployMulticall3( - chain.DeployerKey, - chain.Client, - ) - return deployment.ContractDeploy[*multicall3.Multicall3]{ - Address: multicall3Addr, Contract: multicall3Wrapper, Tx: tx2, Tv: deployment.NewTypeAndVersion(Multicall3, deployment.Version1_0_0), Err: err2, - } - }) - if err != nil { - e.Logger.Errorw("Failed to deploy ccip multicall", "chain", chain.String(), "err", err) - return err - } - } else { - if mc3 != nil { - e.Logger.Info("ccip multicall already deployed", "chain", chain.String(), "addr", mc3.Address) - } - } - if deployOpts.USDCEnabled { - token, pool, messenger, transmitter, err1 := DeployUSDC(e.Logger, chain, ab, rmnProxy.Address(), r.Address()) - if err1 != nil { - return err1 - } - e.Logger.Infow("Deployed USDC contracts", - "chain", chain.String(), - "token", token.Address(), - "pool", pool.Address(), - "transmitter", transmitter.Address(), - "messenger", messenger.Address(), - ) - } - if chainState.Receiver == nil { - _, err := deployment.DeployContract(e.Logger, chain, ab, - func(chain deployment.Chain) deployment.ContractDeploy[*maybe_revert_message_receiver.MaybeRevertMessageReceiver] { - receiverAddr, tx, receiver, err2 := maybe_revert_message_receiver.DeployMaybeRevertMessageReceiver( - chain.DeployerKey, - chain.Client, - false, - ) - return deployment.ContractDeploy[*maybe_revert_message_receiver.MaybeRevertMessageReceiver]{ - Address: receiverAddr, Contract: receiver, Tx: tx, Tv: deployment.NewTypeAndVersion(CCIPReceiver, deployment.Version1_0_0), Err: err2, - } - }) - if err != nil { - e.Logger.Errorw("Failed to deploy receiver", "chain", chain.String(), "err", err) - return err - } - } else { - e.Logger.Infow("receiver already deployed", "addr", chainState.Receiver.Address, "chain", chain.String()) - } - // Only applicable if setting up for 1.5 version, remove this once we have fully migrated to 1.6 - if deployOpts.LegacyDeploymentCfg != nil { - if chainState.PriceRegistry == nil { - _, err := deployment.DeployContract(lggr, chain, ab, - func(chain deployment.Chain) deployment.ContractDeploy[*price_registry_1_2_0.PriceRegistry] { - priceRegAddr, tx2, priceRegAddrC, err2 := price_registry_1_2_0.DeployPriceRegistry( - chain.DeployerKey, - chain.Client, - nil, - []common.Address{weth9Contract.Address(), chainState.LinkToken.Address()}, - deployOpts.LegacyDeploymentCfg.PriceRegStalenessThreshold, - ) - return deployment.ContractDeploy[*price_registry_1_2_0.PriceRegistry]{ - Address: priceRegAddr, Contract: priceRegAddrC, Tx: tx2, - Tv: deployment.NewTypeAndVersion(PriceRegistry, deployment.Version1_2_0), Err: err2, - } - }) - if err != nil { - lggr.Errorw("Failed to deploy PriceRegistry", "chain", chain.String(), "err", err) - return err - } - } else { - lggr.Infow("PriceRegistry already deployed", "chain", chain.String(), "addr", chainState.PriceRegistry.Address) - } - } - return nil -} diff --git a/deployment/ccip/changeset/cs_update_rmn_config.go b/deployment/ccip/changeset/cs_update_rmn_config.go deleted file mode 100644 index 96f8eacb4cc..00000000000 --- a/deployment/ccip/changeset/cs_update_rmn_config.go +++ /dev/null @@ -1,588 +0,0 @@ -package changeset - -import ( - "fmt" - "math/big" - "reflect" - "time" - - "github.com/ethereum/go-ethereum/accounts/abi/bind" - "github.com/ethereum/go-ethereum/common" - "github.com/smartcontractkit/ccip-owner-contracts/pkg/gethwrappers" - "github.com/smartcontractkit/ccip-owner-contracts/pkg/proposal/mcms" - "github.com/smartcontractkit/ccip-owner-contracts/pkg/proposal/timelock" - - "github.com/smartcontractkit/chainlink/deployment" - "github.com/smartcontractkit/chainlink/deployment/common/proposalutils" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/rmn_home" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/rmn_remote" - "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/p2pkey" -) - -type SetRMNRemoteOnRMNProxyConfig struct { - ChainSelectors []uint64 - MCMSConfig *MCMSConfig -} - -func (c SetRMNRemoteOnRMNProxyConfig) Validate(state CCIPOnChainState) error { - for _, chain := range c.ChainSelectors { - err := deployment.IsValidChainSelector(chain) - if err != nil { - return err - } - chainState, exists := state.Chains[chain] - if !exists { - return fmt.Errorf("chain %d not found in state", chain) - } - if chainState.RMNRemote == nil { - return fmt.Errorf("RMNRemote not found for chain %d", chain) - } - if chainState.RMNProxy == nil { - return fmt.Errorf("RMNProxy not found for chain %d", chain) - } - } - return nil -} - -func SetRMNRemoteOnRMNProxy(e deployment.Environment, cfg SetRMNRemoteOnRMNProxyConfig) (deployment.ChangesetOutput, error) { - state, err := LoadOnchainState(e) - if err != nil { - return deployment.ChangesetOutput{}, fmt.Errorf("failed to load onchain state: %w", err) - } - if err := cfg.Validate(state); err != nil { - return deployment.ChangesetOutput{}, err - } - timelocks, err := state.GetAllTimeLocksForChains(cfg.ChainSelectors) - if err != nil { - return deployment.ChangesetOutput{}, fmt.Errorf("failed to get timelocks for chains %v: %w", cfg.ChainSelectors, err) - } - multiSigs, err := state.GetAllProposerMCMSForChains(cfg.ChainSelectors) - if err != nil { - return deployment.ChangesetOutput{}, fmt.Errorf("failed to get proposer MCMS for chains %v: %w", cfg.ChainSelectors, err) - } - var timelockBatch []timelock.BatchChainOperation - for _, sel := range cfg.ChainSelectors { - chain, exists := e.Chains[sel] - if !exists { - return deployment.ChangesetOutput{}, fmt.Errorf("chain %d not found", sel) - } - txOpts := chain.DeployerKey - if cfg.MCMSConfig != nil { - txOpts = deployment.SimTransactOpts() - } - mcmsOps, err := setRMNRemoteOnRMNProxyOp(txOpts, chain, state.Chains[sel], cfg.MCMSConfig != nil) - if err != nil { - return deployment.ChangesetOutput{}, fmt.Errorf("failed to set RMNRemote on RMNProxy for chain %s: %w", chain.String(), err) - } - if cfg.MCMSConfig != nil { - timelockBatch = append(timelockBatch, timelock.BatchChainOperation{ - ChainIdentifier: mcms.ChainIdentifier(sel), - Batch: []mcms.Operation{mcmsOps}, - }) - } - } - // If we're not using MCMS, we can just return now as we've already confirmed the transactions - if len(timelockBatch) == 0 { - return deployment.ChangesetOutput{}, nil - } - prop, err := proposalutils.BuildProposalFromBatches( - timelocks, - multiSigs, - timelockBatch, - fmt.Sprintf("proposal to set RMNRemote on RMNProxy for chains %v", cfg.ChainSelectors), - cfg.MCMSConfig.MinDelay, - ) - if err != nil { - return deployment.ChangesetOutput{}, err - } - return deployment.ChangesetOutput{ - Proposals: []timelock.MCMSWithTimelockProposal{ - *prop, - }, - }, nil -} - -func setRMNRemoteOnRMNProxyOp(txOpts *bind.TransactOpts, chain deployment.Chain, chainState CCIPChainState, mcmsEnabled bool) (mcms.Operation, error) { - rmnProxy := chainState.RMNProxy - rmnRemoteAddr := chainState.RMNRemote.Address() - setRMNTx, err := rmnProxy.SetARM(txOpts, rmnRemoteAddr) - if err != nil { - return mcms.Operation{}, fmt.Errorf("failed to build call data/transaction to set RMNRemote on RMNProxy for chain %s: %w", chain.String(), err) - } - if !mcmsEnabled { - _, err = deployment.ConfirmIfNoError(chain, setRMNTx, err) - if err != nil { - return mcms.Operation{}, fmt.Errorf("failed to confirm tx to set RMNRemote on RMNProxy for chain %s: %w", chain.String(), deployment.MaybeDataErr(err)) - } - } - return mcms.Operation{ - To: rmnProxy.Address(), - Data: setRMNTx.Data(), - Value: big.NewInt(0), - }, nil -} - -type RMNNopConfig struct { - NodeIndex uint64 - OffchainPublicKey [32]byte - EVMOnChainPublicKey common.Address - PeerId p2pkey.PeerID -} - -func (c RMNNopConfig) ToRMNHomeNode() rmn_home.RMNHomeNode { - return rmn_home.RMNHomeNode{ - PeerId: c.PeerId, - OffchainPublicKey: c.OffchainPublicKey, - } -} - -func (c RMNNopConfig) ToRMNRemoteSigner() rmn_remote.RMNRemoteSigner { - return rmn_remote.RMNRemoteSigner{ - OnchainPublicKey: c.EVMOnChainPublicKey, - NodeIndex: c.NodeIndex, - } -} - -func (c RMNNopConfig) SetBit(bitmap *big.Int, value bool) { - if value { - bitmap.SetBit(bitmap, int(c.NodeIndex), 1) - } else { - bitmap.SetBit(bitmap, int(c.NodeIndex), 0) - } -} - -func getDeployer(e deployment.Environment, chain uint64, mcmConfig *MCMSConfig) *bind.TransactOpts { - if mcmConfig == nil { - return e.Chains[chain].DeployerKey - } - - return deployment.SimTransactOpts() -} - -type MCMSConfig struct { - MinDelay time.Duration -} - -type SetRMNHomeCandidateConfig struct { - HomeChainSelector uint64 - RMNStaticConfig rmn_home.RMNHomeStaticConfig - RMNDynamicConfig rmn_home.RMNHomeDynamicConfig - DigestToOverride [32]byte - MCMSConfig *MCMSConfig -} - -func (c SetRMNHomeCandidateConfig) Validate(state CCIPOnChainState) error { - err := deployment.IsValidChainSelector(c.HomeChainSelector) - if err != nil { - return err - } - - if len(c.RMNDynamicConfig.OffchainConfig) != 0 { - return fmt.Errorf("RMNDynamicConfig.OffchainConfig must be empty") - } - if len(c.RMNStaticConfig.OffchainConfig) != 0 { - return fmt.Errorf("RMNStaticConfig.OffchainConfig must be empty") - } - - if len(c.RMNStaticConfig.Nodes) > 256 { - return fmt.Errorf("RMNStaticConfig.Nodes must be less than 256") - } - - var ( - peerIds = make(map[[32]byte]struct{}) - offchainPublicKeys = make(map[[32]byte]struct{}) - ) - - for _, node := range c.RMNStaticConfig.Nodes { - if _, exists := peerIds[node.PeerId]; exists { - return fmt.Errorf("peerId %x is duplicated", node.PeerId) - } - peerIds[node.PeerId] = struct{}{} - - if _, exists := offchainPublicKeys[node.OffchainPublicKey]; exists { - return fmt.Errorf("offchainPublicKey %x is duplicated", node.OffchainPublicKey) - } - offchainPublicKeys[node.OffchainPublicKey] = struct{}{} - } - rmnHome := state.Chains[c.HomeChainSelector].RMNHome - - if rmnHome == nil { - return fmt.Errorf("RMNHome not found for chain %d", c.HomeChainSelector) - } - - currentDigest, err := rmnHome.GetCandidateDigest(nil) - if err != nil { - return fmt.Errorf("failed to get RMNHome candidate digest: %w", err) - } - - if currentDigest != c.DigestToOverride { - return fmt.Errorf("current digest (%x) does not match digest to override (%x)", currentDigest[:], c.DigestToOverride[:]) - } - - return nil -} - -type PromoteRMNHomeCandidateConfig struct { - HomeChainSelector uint64 - DigestToPromote [32]byte - MCMSConfig *MCMSConfig -} - -func (c PromoteRMNHomeCandidateConfig) Validate(state CCIPOnChainState) error { - err := deployment.IsValidChainSelector(c.HomeChainSelector) - if err != nil { - return err - } - - rmnHome := state.Chains[c.HomeChainSelector].RMNHome - if rmnHome == nil { - return fmt.Errorf("RMNHome not found for chain %d", c.HomeChainSelector) - } - - currentCandidateDigest, err := rmnHome.GetCandidateDigest(nil) - if err != nil { - return fmt.Errorf("failed to get RMNHome candidate digest: %w", err) - } - - if currentCandidateDigest != c.DigestToPromote { - return fmt.Errorf("current digest (%x) does not match digest to promote (%x)", currentCandidateDigest[:], c.DigestToPromote[:]) - } - - return nil -} - -// NewSetRMNHomeCandidateConfigChangeset creates a changeset to set the RMNHome candidate config -// DigestToOverride is the digest of the current candidate config that the new config will override -// StaticConfig contains the list of nodes with their peerIDs (found in their rageproxy keystore) and offchain public keys (found in the RMN keystore) -// DynamicConfig contains the list of source chains with their chain selectors, f value and the bitmap of the nodes that are oberver for each source chain -// The bitmap is a 256 bit array where each bit represents a node. If the bit matching the index of the node in the static config is set it means that the node is an observer -func NewSetRMNHomeCandidateConfigChangeset(e deployment.Environment, config SetRMNHomeCandidateConfig) (deployment.ChangesetOutput, error) { - state, err := LoadOnchainState(e) - if err != nil { - return deployment.ChangesetOutput{}, fmt.Errorf("failed to load onchain state: %w", err) - } - - err = config.Validate(state) - if err != nil { - return deployment.ChangesetOutput{}, err - } - - homeChain, ok := e.Chains[config.HomeChainSelector] - if !ok { - return deployment.ChangesetOutput{}, fmt.Errorf("chain %d not found", config.HomeChainSelector) - } - - rmnHome := state.Chains[config.HomeChainSelector].RMNHome - if rmnHome == nil { - return deployment.ChangesetOutput{}, fmt.Errorf("RMNHome not found for chain %s", homeChain.String()) - } - - deployer := getDeployer(e, config.HomeChainSelector, config.MCMSConfig) - setCandidateTx, err := rmnHome.SetCandidate(deployer, config.RMNStaticConfig, config.RMNDynamicConfig, config.DigestToOverride) - if err != nil { - return deployment.ChangesetOutput{}, fmt.Errorf("build RMNHome set candidate calldata for chain %s: %w", homeChain.String(), err) - } - - if config.MCMSConfig == nil { - chain := e.Chains[config.HomeChainSelector] - _, err := chain.Confirm(setCandidateTx) - - if err != nil { - return deployment.ChangesetOutput{}, fmt.Errorf("failed to confirm tx for chain %s: %w", homeChain.String(), deployment.MaybeDataErr(err)) - } - - return deployment.ChangesetOutput{}, nil - } - - op := mcms.Operation{ - To: rmnHome.Address(), - Data: setCandidateTx.Data(), - Value: big.NewInt(0), - } - - batches := []timelock.BatchChainOperation{ - { - ChainIdentifier: mcms.ChainIdentifier(config.HomeChainSelector), - Batch: []mcms.Operation{op}, - }, - } - - timelocksPerChain := buildTimelockAddressPerChain(e, state) - - proposerMCMSes := buildProposerPerChain(e, state) - - prop, err := proposalutils.BuildProposalFromBatches( - timelocksPerChain, - proposerMCMSes, - batches, - "proposal to set candidate config", - config.MCMSConfig.MinDelay, - ) - - return deployment.ChangesetOutput{ - Proposals: []timelock.MCMSWithTimelockProposal{*prop}, - }, nil -} - -func NewPromoteCandidateConfigChangeset(e deployment.Environment, config PromoteRMNHomeCandidateConfig) (deployment.ChangesetOutput, error) { - state, err := LoadOnchainState(e) - if err != nil { - return deployment.ChangesetOutput{}, fmt.Errorf("failed to load onchain state: %w", err) - } - - err = config.Validate(state) - if err != nil { - return deployment.ChangesetOutput{}, err - } - - homeChain, ok := e.Chains[config.HomeChainSelector] - - if !ok { - return deployment.ChangesetOutput{}, fmt.Errorf("chain %d not found", config.HomeChainSelector) - } - - rmnHome := state.Chains[config.HomeChainSelector].RMNHome - if rmnHome == nil { - return deployment.ChangesetOutput{}, fmt.Errorf("RMNHome not found for chain %s", homeChain.String()) - } - - currentCandidateDigest, err := rmnHome.GetCandidateDigest(nil) - if err != nil { - return deployment.ChangesetOutput{}, fmt.Errorf("failed to get RMNHome candidate digest for chain %s: %w", homeChain.String(), err) - } - - currentActiveDigest, err := rmnHome.GetActiveDigest(nil) - if err != nil { - return deployment.ChangesetOutput{}, fmt.Errorf("failed to get RMNHome active digest for chain %s: %w", homeChain.String(), err) - } - - deployer := getDeployer(e, config.HomeChainSelector, config.MCMSConfig) - promoteCandidateTx, err := rmnHome.PromoteCandidateAndRevokeActive(deployer, currentCandidateDigest, currentActiveDigest) - if err != nil { - return deployment.ChangesetOutput{}, fmt.Errorf("get call data to promote RMNHome candidate digest for chain %s: %w", homeChain.String(), err) - } - - if config.MCMSConfig == nil { - chain := e.Chains[config.HomeChainSelector] - _, err := chain.Confirm(promoteCandidateTx) - - if err != nil { - return deployment.ChangesetOutput{}, fmt.Errorf("failed to confirm tx for chain %s: %w", homeChain.String(), deployment.MaybeDataErr(err)) - } - - return deployment.ChangesetOutput{}, nil - } - - op := mcms.Operation{ - To: rmnHome.Address(), - Data: promoteCandidateTx.Data(), - Value: big.NewInt(0), - } - - batches := []timelock.BatchChainOperation{ - { - ChainIdentifier: mcms.ChainIdentifier(config.HomeChainSelector), - Batch: []mcms.Operation{op}, - }, - } - - timelocksPerChain := buildTimelockAddressPerChain(e, state) - - proposerMCMSes := buildProposerPerChain(e, state) - - prop, err := proposalutils.BuildProposalFromBatches( - timelocksPerChain, - proposerMCMSes, - batches, - "proposal to promote candidate config", - config.MCMSConfig.MinDelay, - ) - - if err != nil { - return deployment.ChangesetOutput{}, fmt.Errorf("failed to build proposal for chain %s: %w", homeChain.String(), err) - } - - return deployment.ChangesetOutput{ - Proposals: []timelock.MCMSWithTimelockProposal{*prop}, - }, nil -} - -func buildTimelockPerChain(e deployment.Environment, state CCIPOnChainState) map[uint64]*proposalutils.TimelockExecutionContracts { - timelocksPerChain := make(map[uint64]*proposalutils.TimelockExecutionContracts) - for _, chain := range e.Chains { - timelocksPerChain[chain.Selector] = &proposalutils.TimelockExecutionContracts{ - Timelock: state.Chains[chain.Selector].Timelock, - CallProxy: state.Chains[chain.Selector].CallProxy, - } - } - return timelocksPerChain -} - -func buildTimelockAddressPerChain(e deployment.Environment, state CCIPOnChainState) map[uint64]common.Address { - timelocksPerChain := buildTimelockPerChain(e, state) - timelockAddressPerChain := make(map[uint64]common.Address) - for chain, timelock := range timelocksPerChain { - timelockAddressPerChain[chain] = timelock.Timelock.Address() - } - return timelockAddressPerChain -} - -func buildProposerPerChain(e deployment.Environment, state CCIPOnChainState) map[uint64]*gethwrappers.ManyChainMultiSig { - proposerPerChain := make(map[uint64]*gethwrappers.ManyChainMultiSig) - for _, chain := range e.Chains { - proposerPerChain[chain.Selector] = state.Chains[chain.Selector].ProposerMcm - } - return proposerPerChain -} - -func buildRMNRemotePerChain(e deployment.Environment, state CCIPOnChainState) map[uint64]*rmn_remote.RMNRemote { - timelocksPerChain := make(map[uint64]*rmn_remote.RMNRemote) - for _, chain := range e.Chains { - timelocksPerChain[chain.Selector] = state.Chains[chain.Selector].RMNRemote - } - return timelocksPerChain -} - -type RMNRemoteConfig struct { - Signers []rmn_remote.RMNRemoteSigner - F uint64 -} - -type SetRMNRemoteConfig struct { - HomeChainSelector uint64 - RMNRemoteConfigs map[uint64]RMNRemoteConfig - MCMSConfig *MCMSConfig -} - -func (c SetRMNRemoteConfig) Validate() error { - err := deployment.IsValidChainSelector(c.HomeChainSelector) - if err != nil { - return err - } - - for chain, config := range c.RMNRemoteConfigs { - err := deployment.IsValidChainSelector(chain) - if err != nil { - return err - } - - for i := 0; i < len(config.Signers)-1; i++ { - if config.Signers[i].NodeIndex >= config.Signers[i+1].NodeIndex { - return fmt.Errorf("signers must be in ascending order of nodeIndex, but found %d >= %d", config.Signers[i].NodeIndex, config.Signers[i+1].NodeIndex) - } - } - - if len(config.Signers) < 2*int(config.F)+1 { - return fmt.Errorf("signers count (%d) must be greater than or equal to %d", len(config.Signers), 2*config.F+1) - } - } - - return nil -} - -func NewSetRMNRemoteConfigChangeset(e deployment.Environment, config SetRMNRemoteConfig) (deployment.ChangesetOutput, error) { - state, err := LoadOnchainState(e) - if err != nil { - return deployment.ChangesetOutput{}, fmt.Errorf("failed to load onchain state: %w", err) - } - - lggr := e.Logger - - err = config.Validate() - if err != nil { - return deployment.ChangesetOutput{}, err - } - - homeChain, ok := e.Chains[config.HomeChainSelector] - - if !ok { - return deployment.ChangesetOutput{}, fmt.Errorf("chain %d not found", config.HomeChainSelector) - } - - rmnHome := state.Chains[config.HomeChainSelector].RMNHome - if rmnHome == nil { - return deployment.ChangesetOutput{}, fmt.Errorf("RMNHome not found for chain %s", homeChain.String()) - } - - activeConfig, err := rmnHome.GetActiveDigest(nil) - if err != nil { - return deployment.ChangesetOutput{}, fmt.Errorf("failed to get RMNHome active digest for chain %s: %w", homeChain.String(), err) - } - - rmnRemotePerChain := buildRMNRemotePerChain(e, state) - batches := make([]timelock.BatchChainOperation, 0) - for chain, remoteConfig := range config.RMNRemoteConfigs { - remote, ok := rmnRemotePerChain[chain] - if !ok { - return deployment.ChangesetOutput{}, fmt.Errorf("RMNRemote contract not found for chain %d", chain) - } - - currentVersionConfig, err := remote.GetVersionedConfig(nil) - if err != nil { - return deployment.ChangesetOutput{}, fmt.Errorf("failed to get RMNRemote config for chain %s: %w", e.Chains[chain].String(), err) - } - - newConfig := rmn_remote.RMNRemoteConfig{ - RmnHomeContractConfigDigest: activeConfig, - Signers: remoteConfig.Signers, - F: remoteConfig.F, - } - - if reflect.DeepEqual(currentVersionConfig.Config, newConfig) { - lggr.Infow("RMNRemote config already up to date", "chain", e.Chains[chain].String()) - continue - } - - deployer := getDeployer(e, chain, config.MCMSConfig) - tx, err := remote.SetConfig(deployer, newConfig) - - if err != nil { - return deployment.ChangesetOutput{}, fmt.Errorf("build call data to set RMNRemote config for chain %s: %w", e.Chains[chain].String(), err) - } - - if config.MCMSConfig == nil { - _, err := e.Chains[chain].Confirm(tx) - - if err != nil { - return deployment.ChangesetOutput{}, fmt.Errorf("failed to confirm tx for chain %s: %w", e.Chains[chain].String(), deployment.MaybeDataErr(err)) - } - } - - op := mcms.Operation{ - To: remote.Address(), - Data: tx.Data(), - Value: big.NewInt(0), - } - - batch := timelock.BatchChainOperation{ - ChainIdentifier: mcms.ChainIdentifier(chain), - Batch: []mcms.Operation{op}, - } - - batches = append(batches, batch) - } - - if config.MCMSConfig == nil { - return deployment.ChangesetOutput{}, nil - } - - timelocksPerChain := buildTimelockAddressPerChain(e, state) - - proposerMCMSes := buildProposerPerChain(e, state) - - prop, err := proposalutils.BuildProposalFromBatches( - timelocksPerChain, - proposerMCMSes, - batches, - "proposal to promote candidate config", - config.MCMSConfig.MinDelay, - ) - - if err != nil { - return deployment.ChangesetOutput{}, fmt.Errorf("failed to build proposal for chain %s: %w", homeChain.String(), err) - } - - return deployment.ChangesetOutput{ - Proposals: []timelock.MCMSWithTimelockProposal{*prop}, - }, nil -} diff --git a/deployment/ccip/changeset/cs_update_rmn_config_test.go b/deployment/ccip/changeset/cs_update_rmn_config_test.go deleted file mode 100644 index e7543e22cb7..00000000000 --- a/deployment/ccip/changeset/cs_update_rmn_config_test.go +++ /dev/null @@ -1,306 +0,0 @@ -package changeset - -import ( - "testing" - - "github.com/ethereum/go-ethereum/common" - "github.com/stretchr/testify/require" - - "github.com/smartcontractkit/chainlink/deployment" - commonchangeset "github.com/smartcontractkit/chainlink/deployment/common/changeset" - "github.com/smartcontractkit/chainlink/deployment/common/proposalutils" - commontypes "github.com/smartcontractkit/chainlink/deployment/common/types" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/rmn_home" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/rmn_remote" -) - -var ( - rmn_staging_1 = RMNNopConfig{ - NodeIndex: 0, - PeerId: deployment.MustPeerIDFromString("p2p_12D3KooWRXxZq3pd4a3ZGkKj7Nt1SQQrnB8CuvbPnnV9KVeMeWqg"), - OffchainPublicKey: [32]byte(common.FromHex("0xb34944857a42444d1b285d7940d6e06682309e0781e43a69676ee9f85c73c2d1")), - EVMOnChainPublicKey: common.HexToAddress("0x5af8ee32316a6427f169a45fdc1b3a91a85ac459e3c1cb91c69e1c51f0c1fc21"), - } - rmn_staging_2 = RMNNopConfig{ - NodeIndex: 1, - PeerId: deployment.MustPeerIDFromString("p2p_12D3KooWEmdxYQFsRbD9aFczF32zA3CcUwuSiWCk2CrmACo4v9RL"), - OffchainPublicKey: [32]byte(common.FromHex("0x68d9f3f274e3985528a923a9bace3d39c55dd778b187b4120b384cc48c892859")), - EVMOnChainPublicKey: common.HexToAddress("0x858589216956f482a0f68b282a7050af4cd48ed2"), - } - rmn_staging_3 = RMNNopConfig{ - NodeIndex: 2, - PeerId: deployment.MustPeerIDFromString("p2p_12D3KooWJS42cNXKJvj6DeZnxEX7aGxhEuap6uNFrz554AbUDw6Q"), - OffchainPublicKey: [32]byte(common.FromHex("0x5af8ee32316a6427f169a45fdc1b3a91a85ac459e3c1cb91c69e1c51f0c1fc21")), - EVMOnChainPublicKey: common.HexToAddress("0x7c5e94162c6fabbdeb3bfe83ae532846e337bfae"), - } -) - -type updateRMNConfigTestCase struct { - useMCMS bool - name string - nops []RMNNopConfig -} - -func TestUpdateRMNConfig(t *testing.T) { - t.Parallel() - testCases := []updateRMNConfigTestCase{ - { - useMCMS: true, - name: "with MCMS", - nops: []RMNNopConfig{rmn_staging_1, rmn_staging_2, rmn_staging_3}, - }, - { - useMCMS: false, - name: "without MCMS", - nops: []RMNNopConfig{rmn_staging_1, rmn_staging_2, rmn_staging_3}, - }, - } - - for _, tc := range testCases { - t.Run(tc.name, func(t *testing.T) { - t.Parallel() - updateRMNConfig(t, tc) - }) - } -} - -func updateRMNConfig(t *testing.T, tc updateRMNConfigTestCase) { - e := NewMemoryEnvironment(t) - - state, err := LoadOnchainState(e.Env) - require.NoError(t, err) - - contractsByChain := make(map[uint64][]common.Address) - rmnRemoteAddressesByChain := buildRMNRemoteAddressPerChain(e.Env, state) - for chainSelector, rmnRemoteAddress := range rmnRemoteAddressesByChain { - contractsByChain[chainSelector] = []common.Address{rmnRemoteAddress} - } - - contractsByChain[e.HomeChainSel] = append(contractsByChain[e.HomeChainSel], state.Chains[e.HomeChainSel].RMNHome.Address()) - - timelocksPerChain := buildTimelockPerChain(e.Env, state) - if tc.useMCMS { - // This is required because RMNHome is initially owned by the deployer - _, err = commonchangeset.ApplyChangesets(t, e.Env, timelocksPerChain, []commonchangeset.ChangesetApplication{ - { - Changeset: commonchangeset.WrapChangeSet(commonchangeset.TransferToMCMSWithTimelock), - Config: commonchangeset.TransferToMCMSWithTimelockConfig{ - ContractsByChain: contractsByChain, - MinDelay: 0, - }, - }, - }) - } - - rmnHome := state.Chains[e.HomeChainSel].RMNHome - - previousCandidateDigest, err := rmnHome.GetCandidateDigest(nil) - require.NoError(t, err) - previousActiveDigest, err := rmnHome.GetActiveDigest(nil) - require.NoError(t, err) - - var mcmsConfig *MCMSConfig = nil - - if tc.useMCMS { - mcmsConfig = &MCMSConfig{ - MinDelay: 0, - } - } - - nodes := make([]rmn_home.RMNHomeNode, 0, len(tc.nops)) - for _, nop := range tc.nops { - nodes = append(nodes, nop.ToRMNHomeNode()) - } - - setRMNHomeCandidateConfig := SetRMNHomeCandidateConfig{ - HomeChainSelector: e.HomeChainSel, - RMNStaticConfig: rmn_home.RMNHomeStaticConfig{ - Nodes: nodes, - OffchainConfig: []byte(""), - }, - RMNDynamicConfig: rmn_home.RMNHomeDynamicConfig{ - SourceChains: []rmn_home.RMNHomeSourceChain{}, - OffchainConfig: []byte(""), - }, - MCMSConfig: mcmsConfig, - } - - _, err = commonchangeset.ApplyChangesets(t, e.Env, timelocksPerChain, []commonchangeset.ChangesetApplication{ - { - Changeset: commonchangeset.WrapChangeSet(NewSetRMNHomeCandidateConfigChangeset), - Config: setRMNHomeCandidateConfig, - }, - }) - - require.NoError(t, err) - - state, err = LoadOnchainState(e.Env) - require.NoError(t, err) - - currentCandidateDigest, err := rmnHome.GetCandidateDigest(nil) - require.NoError(t, err) - currentActiveDigest, err := rmnHome.GetActiveDigest(nil) - require.NoError(t, err) - - require.NotEqual(t, previousCandidateDigest, currentCandidateDigest) - require.Equal(t, previousActiveDigest, currentActiveDigest) - - promoteConfig := PromoteRMNHomeCandidateConfig{ - HomeChainSelector: e.HomeChainSel, - DigestToPromote: currentCandidateDigest, - MCMSConfig: mcmsConfig, - } - - _, err = commonchangeset.ApplyChangesets(t, e.Env, timelocksPerChain, []commonchangeset.ChangesetApplication{ - { - Changeset: commonchangeset.WrapChangeSet(NewPromoteCandidateConfigChangeset), - Config: promoteConfig, - }, - }) - - require.NoError(t, err) - currentActiveDigest, err = rmnHome.GetActiveDigest(nil) - - require.NoError(t, err) - require.NotEqual(t, previousActiveDigest, currentActiveDigest) - - signers := make([]rmn_remote.RMNRemoteSigner, 0, len(tc.nops)) - for _, nop := range tc.nops { - signers = append(signers, nop.ToRMNRemoteSigner()) - } - - remoteConfigs := make(map[uint64]RMNRemoteConfig, len(e.Env.Chains)) - for _, chain := range e.Env.Chains { - remoteConfig := RMNRemoteConfig{ - Signers: signers, - F: 0, - } - - remoteConfigs[chain.Selector] = remoteConfig - } - - setRemoteConfig := SetRMNRemoteConfig{ - HomeChainSelector: e.HomeChainSel, - RMNRemoteConfigs: remoteConfigs, - MCMSConfig: mcmsConfig, - } - - _, err = commonchangeset.ApplyChangesets(t, e.Env, timelocksPerChain, []commonchangeset.ChangesetApplication{ - { - Changeset: commonchangeset.WrapChangeSet(NewSetRMNRemoteConfigChangeset), - Config: setRemoteConfig, - }, - }) - - require.NoError(t, err) - rmnRemotePerChain := buildRMNRemotePerChain(e.Env, state) - for _, rmnRemote := range rmnRemotePerChain { - remoteConfigSetEvents, err := rmnRemote.FilterConfigSet(nil, nil) - require.NoError(t, err) - var lastEvent *rmn_remote.RMNRemoteConfigSet - for remoteConfigSetEvents.Next() { - lastEvent = remoteConfigSetEvents.Event - } - require.NotNil(t, lastEvent) - require.Equal(t, lastEvent.Config.RmnHomeContractConfigDigest, currentActiveDigest) - } -} - -func buildRMNRemoteAddressPerChain(e deployment.Environment, state CCIPOnChainState) map[uint64]common.Address { - rmnRemotePerChain := buildRMNRemotePerChain(e, state) - rmnRemoteAddressPerChain := make(map[uint64]common.Address) - for chain, remote := range rmnRemotePerChain { - if remote == nil { - continue - } - rmnRemoteAddressPerChain[chain] = remote.Address() - } - return rmnRemoteAddressPerChain -} - -func TestSetRMNRemoteOnRMNProxy(t *testing.T) { - t.Parallel() - e := NewMemoryEnvironment(t, WithNoJobsAndContracts()) - allChains := e.Env.AllChainSelectors() - mcmsCfg := make(map[uint64]commontypes.MCMSWithTimelockConfig) - var err error - var prereqCfgs []DeployPrerequisiteConfigPerChain - for _, c := range e.Env.AllChainSelectors() { - mcmsCfg[c] = proposalutils.SingleGroupTimelockConfig(t) - prereqCfgs = append(prereqCfgs, DeployPrerequisiteConfigPerChain{ - ChainSelector: c, - }) - } - // Need to deploy prerequisites first so that we can form the USDC config - // no proposals to be made, timelock can be passed as nil here - e.Env, err = commonchangeset.ApplyChangesets(t, e.Env, nil, []commonchangeset.ChangesetApplication{ - { - Changeset: commonchangeset.WrapChangeSet(commonchangeset.DeployLinkToken), - Config: allChains, - }, - { - Changeset: commonchangeset.WrapChangeSet(DeployPrerequisites), - Config: DeployPrerequisiteConfig{ - Configs: prereqCfgs, - }, - }, - { - Changeset: commonchangeset.WrapChangeSet(commonchangeset.DeployMCMSWithTimelock), - Config: mcmsCfg, - }, - }) - require.NoError(t, err) - contractsByChain := make(map[uint64][]common.Address) - state, err := LoadOnchainState(e.Env) - require.NoError(t, err) - for _, chain := range allChains { - rmnProxy := state.Chains[chain].RMNProxy - require.NotNil(t, rmnProxy) - contractsByChain[chain] = []common.Address{rmnProxy.Address()} - } - timelockContractsPerChain := make(map[uint64]*proposalutils.TimelockExecutionContracts) - for _, chain := range allChains { - timelockContractsPerChain[chain] = &proposalutils.TimelockExecutionContracts{ - Timelock: state.Chains[chain].Timelock, - CallProxy: state.Chains[chain].CallProxy, - } - } - e.Env, err = commonchangeset.ApplyChangesets(t, e.Env, timelockContractsPerChain, []commonchangeset.ChangesetApplication{ - // transfer ownership of RMNProxy to timelock - { - Changeset: commonchangeset.WrapChangeSet(commonchangeset.TransferToMCMSWithTimelock), - Config: commonchangeset.TransferToMCMSWithTimelockConfig{ - ContractsByChain: contractsByChain, - MinDelay: 0, - }, - }, - { - Changeset: commonchangeset.WrapChangeSet(DeployChainContracts), - Config: DeployChainContractsConfig{ - ChainSelectors: allChains, - HomeChainSelector: e.HomeChainSel, - }, - }, - { - Changeset: commonchangeset.WrapChangeSet(SetRMNRemoteOnRMNProxy), - Config: SetRMNRemoteOnRMNProxyConfig{ - ChainSelectors: allChains, - MCMSConfig: &MCMSConfig{ - MinDelay: 0, - }, - }, - }, - }) - require.NoError(t, err) - state, err = LoadOnchainState(e.Env) - require.NoError(t, err) - for _, chain := range allChains { - rmnProxy := state.Chains[chain].RMNProxy - proxyOwner, err := rmnProxy.Owner(nil) - require.NoError(t, err) - require.Equal(t, state.Chains[chain].Timelock.Address(), proxyOwner) - rmnAddr, err := rmnProxy.GetARM(nil) - require.NoError(t, err) - require.Equal(t, rmnAddr, state.Chains[chain].RMNRemote.Address()) - } -} diff --git a/deployment/ccip/changeset/home_chain.go b/deployment/ccip/changeset/home_chain.go new file mode 100644 index 00000000000..0fabd2efb18 --- /dev/null +++ b/deployment/ccip/changeset/home_chain.go @@ -0,0 +1,73 @@ +package changeset + +import ( + "fmt" + + "github.com/ethereum/go-ethereum/common" + "github.com/pkg/errors" + "github.com/smartcontractkit/ccip-owner-contracts/pkg/proposal/timelock" + + "github.com/smartcontractkit/chainlink/deployment" + ccipdeployment "github.com/smartcontractkit/chainlink/deployment/ccip" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/rmn_home" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry" +) + +var _ deployment.ChangeSet[DeployHomeChainConfig] = DeployHomeChain + +// DeployHomeChain is a separate changeset because it is a standalone deployment performed once in home chain for the entire CCIP deployment. +func DeployHomeChain(env deployment.Environment, cfg DeployHomeChainConfig) (deployment.ChangesetOutput, error) { + err := cfg.Validate() + if err != nil { + return deployment.ChangesetOutput{}, errors.Wrapf(deployment.ErrInvalidConfig, "%v", err) + } + ab := deployment.NewMemoryAddressBook() + // Note we also deploy the cap reg. + _, err = ccipdeployment.DeployHomeChain(env.Logger, env, ab, env.Chains[cfg.HomeChainSel], cfg.RMNStaticConfig, cfg.RMNDynamicConfig, cfg.NodeOperators, cfg.NodeP2PIDsPerNodeOpAdmin) + if err != nil { + env.Logger.Errorw("Failed to deploy cap reg", "err", err, "addresses", env.ExistingAddresses) + return deployment.ChangesetOutput{}, err + } + + return deployment.ChangesetOutput{ + Proposals: []timelock.MCMSWithTimelockProposal{}, + AddressBook: ab, + JobSpecs: nil, + }, nil +} + +type DeployHomeChainConfig struct { + HomeChainSel uint64 + RMNStaticConfig rmn_home.RMNHomeStaticConfig + RMNDynamicConfig rmn_home.RMNHomeDynamicConfig + NodeOperators []capabilities_registry.CapabilitiesRegistryNodeOperator + NodeP2PIDsPerNodeOpAdmin map[string][][32]byte +} + +func (c DeployHomeChainConfig) Validate() error { + if c.HomeChainSel == 0 { + return fmt.Errorf("home chain selector must be set") + } + if c.RMNDynamicConfig.OffchainConfig == nil { + return fmt.Errorf("offchain config for RMNHomeDynamicConfig must be set") + } + if c.RMNStaticConfig.OffchainConfig == nil { + return fmt.Errorf("offchain config for RMNHomeStaticConfig must be set") + } + if len(c.NodeOperators) == 0 { + return fmt.Errorf("node operators must be set") + } + for _, nop := range c.NodeOperators { + if nop.Admin == (common.Address{}) { + return fmt.Errorf("node operator admin address must be set") + } + if nop.Name == "" { + return fmt.Errorf("node operator name must be set") + } + if len(c.NodeP2PIDsPerNodeOpAdmin[nop.Name]) == 0 { + return fmt.Errorf("node operator %s must have node p2p ids provided", nop.Name) + } + } + + return nil +} diff --git a/deployment/ccip/changeset/home_chain_test.go b/deployment/ccip/changeset/home_chain_test.go new file mode 100644 index 00000000000..f0abdc64437 --- /dev/null +++ b/deployment/ccip/changeset/home_chain_test.go @@ -0,0 +1,63 @@ +package changeset + +import ( + "testing" + + chainsel "github.com/smartcontractkit/chain-selectors" + "github.com/stretchr/testify/require" + "go.uber.org/zap/zapcore" + + "github.com/smartcontractkit/chainlink/deployment" + ccdeploy "github.com/smartcontractkit/chainlink/deployment/ccip" + "github.com/smartcontractkit/chainlink/deployment/common/view/v1_0" + "github.com/smartcontractkit/chainlink/deployment/environment/memory" + "github.com/smartcontractkit/chainlink/v2/core/logger" +) + +func TestDeployHomeChain(t *testing.T) { + lggr := logger.TestLogger(t) + e := memory.NewMemoryEnvironment(t, lggr, zapcore.InfoLevel, memory.MemoryEnvironmentConfig{ + Bootstraps: 1, + Chains: 2, + Nodes: 4, + }) + homeChainSel := e.AllChainSelectors()[0] + nodes, err := deployment.NodeInfo(e.NodeIDs, e.Offchain) + require.NoError(t, err) + p2pIds := nodes.NonBootstraps().PeerIDs() + homeChainCfg := DeployHomeChainConfig{ + HomeChainSel: homeChainSel, + RMNStaticConfig: ccdeploy.NewTestRMNStaticConfig(), + RMNDynamicConfig: ccdeploy.NewTestRMNDynamicConfig(), + NodeOperators: ccdeploy.NewTestNodeOperator(e.Chains[homeChainSel].DeployerKey.From), + NodeP2PIDsPerNodeOpAdmin: map[string][][32]byte{ + "NodeOperator": p2pIds, + }, + } + output, err := DeployHomeChain(e, homeChainCfg) + require.NoError(t, err) + require.NoError(t, e.ExistingAddresses.Merge(output.AddressBook)) + state, err := ccdeploy.LoadOnchainState(e) + require.NoError(t, err) + require.NotNil(t, state.Chains[homeChainSel].CapabilityRegistry) + require.NotNil(t, state.Chains[homeChainSel].CCIPHome) + require.NotNil(t, state.Chains[homeChainSel].RMNHome) + snap, err := state.View([]uint64{homeChainSel}) + require.NoError(t, err) + chainid, err := chainsel.ChainIdFromSelector(homeChainSel) + require.NoError(t, err) + chainName, err := chainsel.NameFromChainId(chainid) + require.NoError(t, err) + _, ok := snap[chainName] + require.True(t, ok) + capRegSnap, ok := snap[chainName].CapabilityRegistry[state.Chains[homeChainSel].CapabilityRegistry.Address().String()] + require.True(t, ok) + require.NotNil(t, capRegSnap) + require.Equal(t, capRegSnap.Nops, []v1_0.NopView{ + { + Admin: e.Chains[homeChainSel].DeployerKey.From, + Name: "NodeOperator", + }, + }) + require.Len(t, capRegSnap.Nodes, len(p2pIds)) +} diff --git a/deployment/ccip/changeset/initial_deploy.go b/deployment/ccip/changeset/initial_deploy.go new file mode 100644 index 00000000000..de17834e8bd --- /dev/null +++ b/deployment/ccip/changeset/initial_deploy.go @@ -0,0 +1,30 @@ +package changeset + +import ( + "github.com/smartcontractkit/ccip-owner-contracts/pkg/proposal/timelock" + + "github.com/smartcontractkit/chainlink/deployment" + + ccipdeployment "github.com/smartcontractkit/chainlink/deployment/ccip" +) + +var _ deployment.ChangeSet[ccipdeployment.DeployCCIPContractConfig] = InitialDeploy + +func InitialDeploy(env deployment.Environment, c ccipdeployment.DeployCCIPContractConfig) (deployment.ChangesetOutput, error) { + newAddresses := deployment.NewMemoryAddressBook() + err := ccipdeployment.DeployCCIPContracts(env, newAddresses, c) + if err != nil { + env.Logger.Errorw("Failed to deploy CCIP contracts", "err", err, "newAddresses", newAddresses) + return deployment.ChangesetOutput{AddressBook: newAddresses}, deployment.MaybeDataErr(err) + } + js, err := ccipdeployment.NewCCIPJobSpecs(env.NodeIDs, env.Offchain) + if err != nil { + return deployment.ChangesetOutput{AddressBook: newAddresses}, err + } + return deployment.ChangesetOutput{ + Proposals: []timelock.MCMSWithTimelockProposal{}, + AddressBook: newAddresses, + // Mapping of which nodes get which jobs. + JobSpecs: js, + }, nil +} diff --git a/deployment/ccip/changeset/initial_deploy_test.go b/deployment/ccip/changeset/initial_deploy_test.go new file mode 100644 index 00000000000..a3756022245 --- /dev/null +++ b/deployment/ccip/changeset/initial_deploy_test.go @@ -0,0 +1,103 @@ +package changeset + +import ( + "testing" + + "github.com/ethereum/go-ethereum/common" + + jobv1 "github.com/smartcontractkit/chainlink-protos/job-distributor/v1/job" + + "github.com/smartcontractkit/chainlink/deployment" + ccdeploy "github.com/smartcontractkit/chainlink/deployment/ccip" + + "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/testcontext" + + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/router" + "github.com/smartcontractkit/chainlink/v2/core/logger" + + "github.com/stretchr/testify/require" +) + +func TestInitialDeploy(t *testing.T) { + lggr := logger.TestLogger(t) + ctx := ccdeploy.Context(t) + tenv := ccdeploy.NewMemoryEnvironment(t, lggr, 3, 4, ccdeploy.MockLinkPrice, ccdeploy.MockWethPrice) + e := tenv.Env + + state, err := ccdeploy.LoadOnchainState(tenv.Env) + require.NoError(t, err) + output, err := DeployPrerequisites(e, DeployPrerequisiteConfig{ + ChainSelectors: tenv.Env.AllChainSelectors(), + }) + require.NoError(t, err) + require.NoError(t, tenv.Env.ExistingAddresses.Merge(output.AddressBook)) + + output, err = InitialDeploy(tenv.Env, ccdeploy.DeployCCIPContractConfig{ + HomeChainSel: tenv.HomeChainSel, + FeedChainSel: tenv.FeedChainSel, + ChainsToDeploy: tenv.Env.AllChainSelectors(), + TokenConfig: ccdeploy.NewTestTokenConfig(state.Chains[tenv.FeedChainSel].USDFeeds), + MCMSConfig: ccdeploy.NewTestMCMSConfig(t, e), + OCRSecrets: deployment.XXXGenerateTestOCRSecrets(), + }) + require.NoError(t, err) + // Get new state after migration. + require.NoError(t, tenv.Env.ExistingAddresses.Merge(output.AddressBook)) + state, err = ccdeploy.LoadOnchainState(e) + require.NoError(t, err) + require.NotNil(t, state.Chains[tenv.HomeChainSel].LinkToken) + // Ensure capreg logs are up to date. + ccdeploy.ReplayLogs(t, e.Offchain, tenv.ReplayBlocks) + + // Apply the jobs. + for nodeID, jobs := range output.JobSpecs { + for _, job := range jobs { + // Note these auto-accept + _, err := e.Offchain.ProposeJob(ctx, + &jobv1.ProposeJobRequest{ + NodeId: nodeID, + Spec: job, + }) + require.NoError(t, err) + } + } + + // Add all lanes + require.NoError(t, ccdeploy.AddLanesForAll(e, state)) + // Need to keep track of the block number for each chain so that event subscription can be done from that block. + startBlocks := make(map[uint64]*uint64) + // Send a message from each chain to every other chain. + expectedSeqNum := make(map[uint64]uint64) + + for src := range e.Chains { + for dest, destChain := range e.Chains { + if src == dest { + continue + } + latesthdr, err := destChain.Client.HeaderByNumber(testcontext.Get(t), nil) + require.NoError(t, err) + block := latesthdr.Number.Uint64() + startBlocks[dest] = &block + msgSentEvent := ccdeploy.TestSendRequest(t, e, state, src, dest, false, router.ClientEVM2AnyMessage{ + Receiver: common.LeftPadBytes(state.Chains[dest].Receiver.Address().Bytes(), 32), + Data: []byte("hello"), + TokenAmounts: nil, + FeeToken: common.HexToAddress("0x0"), + ExtraArgs: nil, + }) + expectedSeqNum[dest] = msgSentEvent.SequenceNumber + } + } + + // Wait for all commit reports to land. + ccdeploy.ConfirmCommitForAllWithExpectedSeqNums(t, e, state, expectedSeqNum, startBlocks) + + // Confirm token and gas prices are updated + ccdeploy.ConfirmTokenPriceUpdatedForAll(t, e, state, startBlocks, + ccdeploy.DefaultInitialPrices.LinkPrice, ccdeploy.DefaultInitialPrices.WethPrice) + // TODO: Fix gas prices? + //ccdeploy.ConfirmGasPriceUpdatedForAll(t, e, state, startBlocks) + // + //// Wait for all exec reports to land + ccdeploy.ConfirmExecWithSeqNrForAll(t, e, state, expectedSeqNum, startBlocks) +} diff --git a/deployment/ccip/changeset/internal/deploy_home_chain.go b/deployment/ccip/changeset/internal/deploy_home_chain.go deleted file mode 100644 index ec5b879be0c..00000000000 --- a/deployment/ccip/changeset/internal/deploy_home_chain.go +++ /dev/null @@ -1,349 +0,0 @@ -package internal - -import ( - "context" - "fmt" - "time" - - "github.com/ethereum/go-ethereum/accounts/abi" - "github.com/ethereum/go-ethereum/accounts/abi/bind" - "github.com/ethereum/go-ethereum/common" - "github.com/smartcontractkit/libocr/offchainreporting2plus/confighelper" - "github.com/smartcontractkit/libocr/offchainreporting2plus/ocr3confighelper" - - "github.com/smartcontractkit/chainlink-ccip/pluginconfig" - - "github.com/smartcontractkit/chainlink/deployment" - types2 "github.com/smartcontractkit/chainlink/deployment/common/types" - "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/types" - "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/ccip_home" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/offramp" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry_1_1_0" -) - -const ( - CapabilityLabelledName = "ccip" - CapabilityVersion = "v1.0.0" - - FirstBlockAge = 8 * time.Hour - RemoteGasPriceBatchWriteFrequency = 30 * time.Minute - TokenPriceBatchWriteFrequency = 30 * time.Minute - BatchGasLimit = 6_500_000 - RelativeBoostPerWaitHour = 10000.5 - InflightCacheExpiry = 10 * time.Minute - RootSnoozeTime = 30 * time.Minute - BatchingStrategyID = 0 - DeltaProgress = 30 * time.Second - DeltaResend = 10 * time.Second - DeltaInitial = 20 * time.Second - DeltaRound = 2 * time.Second - DeltaGrace = 2 * time.Second - DeltaCertifiedCommitRequest = 10 * time.Second - DeltaStage = 10 * time.Second - Rmax = 3 - MaxDurationQuery = 500 * time.Millisecond - MaxDurationObservation = 5 * time.Second - MaxDurationShouldAcceptAttestedReport = 10 * time.Second - MaxDurationShouldTransmitAcceptedReport = 10 * time.Second - - GasPriceDeviationPPB = 1000 - DAGasPriceDeviationPPB = 0 - OptimisticConfirmations = 1 -) - -var ( - CCIPCapabilityID = utils.Keccak256Fixed(MustABIEncode(`[{"type": "string"}, {"type": "string"}]`, CapabilityLabelledName, CapabilityVersion)) - CCIPHomeABI *abi.ABI -) - -func init() { - var err error - CCIPHomeABI, err = ccip_home.CCIPHomeMetaData.GetAbi() - if err != nil { - panic(err) - } -} - -func MustABIEncode(abiString string, args ...interface{}) []byte { - encoded, err := utils.ABIEncode(abiString, args...) - if err != nil { - panic(err) - } - return encoded -} - -// getNodeOperatorIDMap returns a map of node operator names to their IDs -// If maxNops is greater than the number of node operators, it will return all node operators -// Unused now but could be useful in the future. -func getNodeOperatorIDMap(capReg *capabilities_registry.CapabilitiesRegistry, maxNops uint32) (map[string]uint32, error) { - nopIdByName := make(map[string]uint32) - operators, err := capReg.GetNodeOperators(nil) - if err != nil { - return nil, err - } - if len(operators) < int(maxNops) { - maxNops = uint32(len(operators)) - } - for i := uint32(1); i <= maxNops; i++ { - operator, err := capReg.GetNodeOperator(nil, i) - if err != nil { - return nil, err - } - nopIdByName[operator.Name] = i - } - return nopIdByName, nil -} - -func LatestCCIPDON(registry *capabilities_registry.CapabilitiesRegistry) (*capabilities_registry.CapabilitiesRegistryDONInfo, error) { - dons, err := registry.GetDONs(nil) - if err != nil { - return nil, err - } - var ccipDON capabilities_registry.CapabilitiesRegistryDONInfo - for _, don := range dons { - if len(don.CapabilityConfigurations) == 1 && - don.CapabilityConfigurations[0].CapabilityId == CCIPCapabilityID && - don.Id > ccipDON.Id { - ccipDON = don - } - } - return &ccipDON, nil -} - -// DonIDForChain returns the DON ID for the chain with the given selector -// It looks up with the CCIPHome contract to find the OCR3 configs for the DONs, and returns the DON ID for the chain matching with the given selector from the OCR3 configs -func DonIDForChain(registry *capabilities_registry.CapabilitiesRegistry, ccipHome *ccip_home.CCIPHome, chainSelector uint64) (uint32, error) { - dons, err := registry.GetDONs(nil) - if err != nil { - return 0, fmt.Errorf("get Dons from capability registry: %w", err) - } - var donIDs []uint32 - for _, don := range dons { - if len(don.CapabilityConfigurations) == 1 && - don.CapabilityConfigurations[0].CapabilityId == CCIPCapabilityID { - configs, err := ccipHome.GetAllConfigs(nil, don.Id, uint8(types.PluginTypeCCIPCommit)) - if err != nil { - return 0, fmt.Errorf("get all commit configs from cciphome: %w", err) - } - if configs.ActiveConfig.ConfigDigest == [32]byte{} && configs.CandidateConfig.ConfigDigest == [32]byte{} { - configs, err = ccipHome.GetAllConfigs(nil, don.Id, uint8(types.PluginTypeCCIPExec)) - if err != nil { - return 0, fmt.Errorf("get all exec configs from cciphome: %w", err) - } - } - if configs.ActiveConfig.Config.ChainSelector == chainSelector || configs.CandidateConfig.Config.ChainSelector == chainSelector { - donIDs = append(donIDs, don.Id) - } - } - } - - // more than one DON is an error - if len(donIDs) > 1 { - return 0, fmt.Errorf("more than one DON found for (chain selector %d, ccip capability id %x) pair", chainSelector, CCIPCapabilityID[:]) - } - - // no DON found - don ID of 0 indicates that (this is the case in the CR as well). - if len(donIDs) == 0 { - return 0, nil - } - - // DON found - return it. - return donIDs[0], nil -} - -// BuildSetOCR3ConfigArgs builds the OCR3 config arguments for the OffRamp contract -// using the donID's OCR3 configs from the CCIPHome contract. -func BuildSetOCR3ConfigArgs( - donID uint32, - ccipHome *ccip_home.CCIPHome, - destSelector uint64, -) ([]offramp.MultiOCR3BaseOCRConfigArgs, error) { - var offrampOCR3Configs []offramp.MultiOCR3BaseOCRConfigArgs - for _, pluginType := range []types.PluginType{types.PluginTypeCCIPCommit, types.PluginTypeCCIPExec} { - ocrConfig, err2 := ccipHome.GetAllConfigs(&bind.CallOpts{ - Context: context.Background(), - }, donID, uint8(pluginType)) - if err2 != nil { - return nil, err2 - } - - fmt.Printf("pluginType: %s, destSelector: %d, donID: %d, activeConfig digest: %x, candidateConfig digest: %x\n", - pluginType.String(), destSelector, donID, ocrConfig.ActiveConfig.ConfigDigest, ocrConfig.CandidateConfig.ConfigDigest) - - // we expect only an active config and no candidate config. - if ocrConfig.ActiveConfig.ConfigDigest == [32]byte{} || ocrConfig.CandidateConfig.ConfigDigest != [32]byte{} { - return nil, fmt.Errorf("invalid OCR3 config state, expected active config and no candidate config, donID: %d", donID) - } - - activeConfig := ocrConfig.ActiveConfig - var signerAddresses []common.Address - var transmitterAddresses []common.Address - for _, node := range activeConfig.Config.Nodes { - signerAddresses = append(signerAddresses, common.BytesToAddress(node.SignerKey)) - transmitterAddresses = append(transmitterAddresses, common.BytesToAddress(node.TransmitterKey)) - } - - offrampOCR3Configs = append(offrampOCR3Configs, offramp.MultiOCR3BaseOCRConfigArgs{ - ConfigDigest: activeConfig.ConfigDigest, - OcrPluginType: uint8(pluginType), - F: activeConfig.Config.FRoleDON, - IsSignatureVerificationEnabled: pluginType == types.PluginTypeCCIPCommit, - Signers: signerAddresses, - Transmitters: transmitterAddresses, - }) - } - return offrampOCR3Configs, nil -} - -func BuildOCR3ConfigForCCIPHome( - ocrSecrets deployment.OCRSecrets, - offRamp *offramp.OffRamp, - dest deployment.Chain, - nodes deployment.Nodes, - rmnHomeAddress common.Address, - ocrParams types2.OCRParameters, - commitOffchainCfg pluginconfig.CommitOffchainConfig, - execOffchainCfg pluginconfig.ExecuteOffchainConfig, -) (map[types.PluginType]ccip_home.CCIPHomeOCR3Config, error) { - p2pIDs := nodes.PeerIDs() - // Get OCR3 Config from helper - var schedule []int - var oracles []confighelper.OracleIdentityExtra - for _, node := range nodes { - schedule = append(schedule, 1) - cfg, exists := node.OCRConfigForChainSelector(dest.Selector) - if !exists { - return nil, fmt.Errorf("no OCR config for chain %d", dest.Selector) - } - oracles = append(oracles, confighelper.OracleIdentityExtra{ - OracleIdentity: confighelper.OracleIdentity{ - OnchainPublicKey: cfg.OnchainPublicKey, - TransmitAccount: cfg.TransmitAccount, - OffchainPublicKey: cfg.OffchainPublicKey, - PeerID: cfg.PeerID.String()[4:], - }, ConfigEncryptionPublicKey: cfg.ConfigEncryptionPublicKey, - }) - } - - // Add DON on capability registry contract - ocr3Configs := make(map[types.PluginType]ccip_home.CCIPHomeOCR3Config) - for _, pluginType := range []types.PluginType{types.PluginTypeCCIPCommit, types.PluginTypeCCIPExec} { - var encodedOffchainConfig []byte - var err2 error - if pluginType == types.PluginTypeCCIPCommit { - encodedOffchainConfig, err2 = pluginconfig.EncodeCommitOffchainConfig(pluginconfig.CommitOffchainConfig{ - RemoteGasPriceBatchWriteFrequency: commitOffchainCfg.RemoteGasPriceBatchWriteFrequency, - TokenPriceBatchWriteFrequency: commitOffchainCfg.TokenPriceBatchWriteFrequency, - PriceFeedChainSelector: commitOffchainCfg.PriceFeedChainSelector, - TokenInfo: commitOffchainCfg.TokenInfo, - NewMsgScanBatchSize: commitOffchainCfg.NewMsgScanBatchSize, - MaxReportTransmissionCheckAttempts: commitOffchainCfg.MaxReportTransmissionCheckAttempts, - MaxMerkleTreeSize: commitOffchainCfg.MaxMerkleTreeSize, - SignObservationPrefix: commitOffchainCfg.SignObservationPrefix, - RMNEnabled: commitOffchainCfg.RMNEnabled, - RMNSignaturesTimeout: commitOffchainCfg.RMNSignaturesTimeout, - }) - } else { - encodedOffchainConfig, err2 = pluginconfig.EncodeExecuteOffchainConfig(pluginconfig.ExecuteOffchainConfig{ - BatchGasLimit: execOffchainCfg.BatchGasLimit, - RelativeBoostPerWaitHour: execOffchainCfg.RelativeBoostPerWaitHour, - MessageVisibilityInterval: execOffchainCfg.MessageVisibilityInterval, - InflightCacheExpiry: execOffchainCfg.InflightCacheExpiry, - RootSnoozeTime: execOffchainCfg.RootSnoozeTime, - BatchingStrategyID: execOffchainCfg.BatchingStrategyID, - TokenDataObservers: execOffchainCfg.TokenDataObservers, - }) - } - if err2 != nil { - return nil, err2 - } - signers, transmitters, configF, _, offchainConfigVersion, offchainConfig, err2 := ocr3confighelper.ContractSetConfigArgsDeterministic( - ocrSecrets.EphemeralSk, - ocrSecrets.SharedSecret, - ocrParams.DeltaProgress, - ocrParams.DeltaResend, - ocrParams.DeltaInitial, - ocrParams.DeltaRound, - ocrParams.DeltaGrace, - ocrParams.DeltaCertifiedCommitRequest, - ocrParams.DeltaStage, - ocrParams.Rmax, - schedule, - oracles, - encodedOffchainConfig, - nil, // maxDurationInitialization - ocrParams.MaxDurationQuery, - ocrParams.MaxDurationObservation, - ocrParams.MaxDurationShouldAcceptAttestedReport, - ocrParams.MaxDurationShouldTransmitAcceptedReport, - int(nodes.DefaultF()), - []byte{}, // empty OnChainConfig - ) - if err2 != nil { - return nil, err2 - } - - signersBytes := make([][]byte, len(signers)) - for i, signer := range signers { - signersBytes[i] = signer - } - - transmittersBytes := make([][]byte, len(transmitters)) - for i, transmitter := range transmitters { - parsed, err2 := common.ParseHexOrString(string(transmitter)) - if err2 != nil { - return nil, err2 - } - transmittersBytes[i] = parsed - } - - var ocrNodes []ccip_home.CCIPHomeOCR3Node - for i := range nodes { - ocrNodes = append(ocrNodes, ccip_home.CCIPHomeOCR3Node{ - P2pId: p2pIDs[i], - SignerKey: signersBytes[i], - TransmitterKey: transmittersBytes[i], - }) - } - - _, ok := ocr3Configs[pluginType] - if ok { - return nil, fmt.Errorf("pluginType %s already exists in ocr3Configs", pluginType.String()) - } - - ocr3Configs[pluginType] = ccip_home.CCIPHomeOCR3Config{ - PluginType: uint8(pluginType), - ChainSelector: dest.Selector, - FRoleDON: configF, - OffchainConfigVersion: offchainConfigVersion, - OfframpAddress: offRamp.Address().Bytes(), - Nodes: ocrNodes, - OffchainConfig: offchainConfig, - RmnHomeAddress: rmnHomeAddress.Bytes(), - } - } - - return ocr3Configs, nil -} - -func DONIdExists(cr *capabilities_registry.CapabilitiesRegistry, donIDs []uint32) error { - // DON ids must exist - dons, err := cr.GetDONs(nil) - if err != nil { - return fmt.Errorf("failed to get dons: %w", err) - } - for _, donID := range donIDs { - exists := false - for _, don := range dons { - if don.Id == donID { - exists = true - break - } - } - if !exists { - return fmt.Errorf("don id %d does not exist", donID) - } - } - return nil -} diff --git a/deployment/ccip/changeset/prerequisites.go b/deployment/ccip/changeset/prerequisites.go new file mode 100644 index 00000000000..7bead1cc05c --- /dev/null +++ b/deployment/ccip/changeset/prerequisites.go @@ -0,0 +1,58 @@ +package changeset + +import ( + "fmt" + + "github.com/ethereum/go-ethereum/common" + "github.com/pkg/errors" + "github.com/smartcontractkit/ccip-owner-contracts/pkg/proposal/timelock" + chain_selectors "github.com/smartcontractkit/chain-selectors" + + "github.com/smartcontractkit/chainlink/deployment" + ccipdeployment "github.com/smartcontractkit/chainlink/deployment/ccip" +) + +var ( + _ deployment.ChangeSet[DeployPrerequisiteConfig] = DeployPrerequisites +) + +// DeployPrerequisites deploys the pre-requisite contracts for CCIP +// pre-requisite contracts are the contracts which can be reused from previous versions of CCIP +func DeployPrerequisites(env deployment.Environment, cfg DeployPrerequisiteConfig) (deployment.ChangesetOutput, error) { + err := cfg.Validate() + if err != nil { + return deployment.ChangesetOutput{}, errors.Wrapf(deployment.ErrInvalidConfig, "%v", err) + } + ab := deployment.NewMemoryAddressBook() + err = ccipdeployment.DeployPrerequisiteChainContracts(env, ab, cfg.ChainSelectors) + if err != nil { + env.Logger.Errorw("Failed to deploy prerequisite contracts", "err", err, "addressBook", ab) + return deployment.ChangesetOutput{}, fmt.Errorf("failed to deploy prerequisite contracts: %w", err) + } + return deployment.ChangesetOutput{ + Proposals: []timelock.MCMSWithTimelockProposal{}, + AddressBook: ab, + JobSpecs: nil, + }, nil +} + +type DeployPrerequisiteConfig struct { + ChainSelectors []uint64 + // TODO handle tokens and feeds in prerequisite config + Tokens map[ccipdeployment.TokenSymbol]common.Address + Feeds map[ccipdeployment.TokenSymbol]common.Address +} + +func (c DeployPrerequisiteConfig) Validate() error { + for _, cs := range c.ChainSelectors { + if cs == 0 { + return fmt.Errorf("chain selector must be set") + } + _, err := chain_selectors.ChainIdFromSelector(cs) + if err != nil { + return fmt.Errorf("invalid chain selector: %d - %w", cs, err) + } + + } + return nil +} diff --git a/deployment/ccip/changeset/cs_prerequisites_test.go b/deployment/ccip/changeset/prerequisites_test.go similarity index 81% rename from deployment/ccip/changeset/cs_prerequisites_test.go rename to deployment/ccip/changeset/prerequisites_test.go index 5835bd41aa3..94d5c8d0581 100644 --- a/deployment/ccip/changeset/cs_prerequisites_test.go +++ b/deployment/ccip/changeset/prerequisites_test.go @@ -6,6 +6,7 @@ import ( "github.com/stretchr/testify/require" "go.uber.org/zap/zapcore" + ccipdeployment "github.com/smartcontractkit/chainlink/deployment/ccip" "github.com/smartcontractkit/chainlink/deployment/environment/memory" "github.com/smartcontractkit/chainlink/v2/core/logger" ) @@ -20,18 +21,15 @@ func TestDeployPrerequisites(t *testing.T) { }) newChain := e.AllChainSelectors()[0] cfg := DeployPrerequisiteConfig{ - Configs: []DeployPrerequisiteConfigPerChain{ - { - ChainSelector: newChain, - }, - }, + ChainSelectors: []uint64{newChain}, } output, err := DeployPrerequisites(e, cfg) require.NoError(t, err) err = e.ExistingAddresses.Merge(output.AddressBook) require.NoError(t, err) - state, err := LoadOnchainState(e) + state, err := ccipdeployment.LoadOnchainState(e) require.NoError(t, err) + require.NotNil(t, state.Chains[newChain].LinkToken) require.NotNil(t, state.Chains[newChain].Weth9) require.NotNil(t, state.Chains[newChain].TokenAdminRegistry) require.NotNil(t, state.Chains[newChain].RegistryModule) diff --git a/deployment/common/changeset/save_existing.go b/deployment/ccip/changeset/save_existing.go similarity index 88% rename from deployment/common/changeset/save_existing.go rename to deployment/ccip/changeset/save_existing.go index a5177c8e49b..8995fdf7f4c 100644 --- a/deployment/common/changeset/save_existing.go +++ b/deployment/ccip/changeset/save_existing.go @@ -6,6 +6,7 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/pkg/errors" "github.com/smartcontractkit/ccip-owner-contracts/pkg/proposal/timelock" + chain_selectors "github.com/smartcontractkit/chain-selectors" "github.com/smartcontractkit/chainlink/deployment" ) @@ -26,7 +27,11 @@ type ExistingContractsConfig struct { func (cfg ExistingContractsConfig) Validate() error { for _, ec := range cfg.ExistingContracts { - if err := deployment.IsValidChainSelector(ec.ChainSelector); err != nil { + if ec.ChainSelector == 0 { + return fmt.Errorf("chain selectors must be set") + } + _, err := chain_selectors.ChainIdFromSelector(ec.ChainSelector) + if err != nil { return fmt.Errorf("invalid chain selector: %d - %w", ec.ChainSelector, err) } if ec.Address == (common.Address{}) { @@ -42,8 +47,6 @@ func (cfg ExistingContractsConfig) Validate() error { return nil } -// SaveExistingContracts saves the existing contracts to the address book. -// Caller should update the environment's address book with the returned addresses. func SaveExistingContracts(env deployment.Environment, cfg ExistingContractsConfig) (deployment.ChangesetOutput, error) { err := cfg.Validate() if err != nil { diff --git a/deployment/ccip/changeset/save_existing_test.go b/deployment/ccip/changeset/save_existing_test.go index 080ed80481a..5f09c13b272 100644 --- a/deployment/ccip/changeset/save_existing_test.go +++ b/deployment/ccip/changeset/save_existing_test.go @@ -9,13 +9,12 @@ import ( "go.uber.org/zap/zapcore" "github.com/smartcontractkit/chainlink/deployment" - commonchangeset "github.com/smartcontractkit/chainlink/deployment/common/changeset" - commontypes "github.com/smartcontractkit/chainlink/deployment/common/types" + ccipdeployment "github.com/smartcontractkit/chainlink/deployment/ccip" "github.com/smartcontractkit/chainlink/deployment/environment/memory" "github.com/smartcontractkit/chainlink/v2/core/logger" ) -func TestSaveExistingCCIP(t *testing.T) { +func TestSaveExisting(t *testing.T) { t.Parallel() lggr := logger.TestLogger(t) e := memory.NewMemoryEnvironment(t, lggr, zapcore.InfoLevel, memory.MemoryEnvironmentConfig{ @@ -26,41 +25,41 @@ func TestSaveExistingCCIP(t *testing.T) { chains := e.AllChainSelectors() chain1 := chains[0] chain2 := chains[1] - cfg := commonchangeset.ExistingContractsConfig{ - ExistingContracts: []commonchangeset.Contract{ + cfg := ExistingContractsConfig{ + ExistingContracts: []Contract{ { Address: common.BigToAddress(big.NewInt(1)), - TypeAndVersion: deployment.NewTypeAndVersion(commontypes.LinkToken, deployment.Version1_0_0), + TypeAndVersion: deployment.NewTypeAndVersion(ccipdeployment.LinkToken, deployment.Version1_0_0), ChainSelector: chain1, }, { Address: common.BigToAddress(big.NewInt(2)), - TypeAndVersion: deployment.NewTypeAndVersion(WETH9, deployment.Version1_0_0), + TypeAndVersion: deployment.NewTypeAndVersion(ccipdeployment.WETH9, deployment.Version1_0_0), ChainSelector: chain1, }, { Address: common.BigToAddress(big.NewInt(3)), - TypeAndVersion: deployment.NewTypeAndVersion(TokenAdminRegistry, deployment.Version1_5_0), + TypeAndVersion: deployment.NewTypeAndVersion(ccipdeployment.TokenAdminRegistry, deployment.Version1_5_0), ChainSelector: chain1, }, { Address: common.BigToAddress(big.NewInt(4)), - TypeAndVersion: deployment.NewTypeAndVersion(RegistryModule, deployment.Version1_5_0), + TypeAndVersion: deployment.NewTypeAndVersion(ccipdeployment.RegistryModule, deployment.Version1_5_0), ChainSelector: chain2, }, { Address: common.BigToAddress(big.NewInt(5)), - TypeAndVersion: deployment.NewTypeAndVersion(Router, deployment.Version1_2_0), + TypeAndVersion: deployment.NewTypeAndVersion(ccipdeployment.Router, deployment.Version1_2_0), ChainSelector: chain2, }, }, } - output, err := commonchangeset.SaveExistingContracts(e, cfg) + output, err := SaveExistingContracts(e, cfg) require.NoError(t, err) err = e.ExistingAddresses.Merge(output.AddressBook) require.NoError(t, err) - state, err := LoadOnchainState(e) + state, err := ccipdeployment.LoadOnchainState(e) require.NoError(t, err) require.Equal(t, state.Chains[chain1].LinkToken.Address(), common.BigToAddress(big.NewInt(1))) require.Equal(t, state.Chains[chain1].Weth9.Address(), common.BigToAddress(big.NewInt(2))) diff --git a/deployment/ccip/changeset/solana_state.go b/deployment/ccip/changeset/solana_state.go deleted file mode 100644 index 4e5507cfcd3..00000000000 --- a/deployment/ccip/changeset/solana_state.go +++ /dev/null @@ -1,6 +0,0 @@ -package changeset - -// SolChainState holds a Go binding for all the currently deployed CCIP programs -// on a chain. If a binding is nil, it means here is no such contract on the chain. -type SolCCIPChainState struct { -} diff --git a/deployment/ccip/changeset/state_test.go b/deployment/ccip/changeset/state_test.go deleted file mode 100644 index 3587332fff2..00000000000 --- a/deployment/ccip/changeset/state_test.go +++ /dev/null @@ -1,15 +0,0 @@ -package changeset - -import ( - "testing" - - "github.com/stretchr/testify/require" -) - -func TestSmokeState(t *testing.T) { - tenv := NewMemoryEnvironment(t, WithChains(3)) - state, err := LoadOnchainState(tenv.Env) - require.NoError(t, err) - _, err = state.View(tenv.Env.AllChainSelectors()) - require.NoError(t, err) -} diff --git a/deployment/ccip/changeset/test_environment.go b/deployment/ccip/changeset/test_environment.go deleted file mode 100644 index f723efbf619..00000000000 --- a/deployment/ccip/changeset/test_environment.go +++ /dev/null @@ -1,612 +0,0 @@ -package changeset - -import ( - "context" - "fmt" - "math/big" - "os" - "testing" - "time" - - "github.com/ethereum/go-ethereum/accounts/abi/bind" - "github.com/stretchr/testify/require" - "go.uber.org/zap/zapcore" - - "github.com/smartcontractkit/chainlink-ccip/chainconfig" - cciptypes "github.com/smartcontractkit/chainlink-ccip/pkg/types/ccipocr3" - "github.com/smartcontractkit/chainlink-ccip/pluginconfig" - commonconfig "github.com/smartcontractkit/chainlink-common/pkg/config" - "github.com/smartcontractkit/chainlink-common/pkg/logger" - jobv1 "github.com/smartcontractkit/chainlink-protos/job-distributor/v1/job" - "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/testcontext" - - "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/internal" - "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/types" - - "github.com/smartcontractkit/chainlink/deployment" - commonchangeset "github.com/smartcontractkit/chainlink/deployment/common/changeset" - "github.com/smartcontractkit/chainlink/deployment/common/proposalutils" - commontypes "github.com/smartcontractkit/chainlink/deployment/common/types" - "github.com/smartcontractkit/chainlink/deployment/environment/memory" -) - -type EnvType string - -const ( - Memory EnvType = "in-memory" - Docker EnvType = "docker" - ENVTESTTYPE = "CCIP_V16_TEST_ENV" -) - -type TestConfigs struct { - Type EnvType // set by env var CCIP_V16_TEST_ENV, defaults to Memory - CreateJob bool - // TODO: This should be CreateContracts so the booleans make sense? - CreateJobAndContracts bool - LegacyDeployment bool - Chains int // only used in memory mode, for docker mode, this is determined by the integration-test config toml input - ChainIDs []uint64 // only used in memory mode, for docker mode, this is determined by the integration-test config toml input - NumOfUsersPerChain int // only used in memory mode, for docker mode, this is determined by the integration-test config toml input - Nodes int // only used in memory mode, for docker mode, this is determined by the integration-test config toml input - Bootstraps int // only used in memory mode, for docker mode, this is determined by the integration-test config toml input - IsUSDC bool - IsUSDCAttestationMissing bool - IsMultiCall3 bool - OCRConfigOverride func(CCIPOCRParams) CCIPOCRParams - RMNEnabled bool - NumOfRMNNodes int - LinkPrice *big.Int - WethPrice *big.Int -} - -func (tc *TestConfigs) Validate() error { - if tc.Chains < 2 { - return fmt.Errorf("chains must be at least 2") - } - if tc.Nodes < 4 { - return fmt.Errorf("nodes must be at least 4") - } - if tc.Bootstraps < 1 { - return fmt.Errorf("bootstraps must be at least 1") - } - if tc.Type == Memory && tc.RMNEnabled { - return fmt.Errorf("cannot run RMN tests in memory mode") - } - return nil -} - -func (tc *TestConfigs) MustSetEnvTypeOrDefault(t *testing.T) { - envType := os.Getenv(ENVTESTTYPE) - if envType == "" || envType == string(Memory) { - tc.Type = Memory - } else if envType == string(Docker) { - tc.Type = Docker - } else { - t.Fatalf("env var CCIP_V16_TEST_ENV must be either %s or %s, defaults to %s if unset, got: %s", Memory, Docker, Memory, envType) - } -} - -func DefaultTestConfigs() *TestConfigs { - return &TestConfigs{ - Chains: 2, - NumOfUsersPerChain: 1, - Nodes: 4, - Bootstraps: 1, - LinkPrice: MockLinkPrice, - WethPrice: MockWethPrice, - CreateJobAndContracts: true, - } -} - -type TestOps func(testCfg *TestConfigs) - -func WithMultiCall3() TestOps { - return func(testCfg *TestConfigs) { - testCfg.IsMultiCall3 = true - } -} - -func WithLegacyDeployment() TestOps { - return func(testCfg *TestConfigs) { - testCfg.LegacyDeployment = true - } -} - -func WithChainIds(chainIDs []uint64) TestOps { - return func(testCfg *TestConfigs) { - testCfg.ChainIDs = chainIDs - } -} - -func WithJobsOnly() TestOps { - return func(testCfg *TestConfigs) { - testCfg.CreateJobAndContracts = false - testCfg.CreateJob = true - } -} - -func WithNoJobsAndContracts() TestOps { - return func(testCfg *TestConfigs) { - testCfg.CreateJobAndContracts = false - testCfg.CreateJob = false - } -} - -func WithRMNEnabled(numOfNode int) TestOps { - return func(testCfg *TestConfigs) { - testCfg.RMNEnabled = true - testCfg.NumOfRMNNodes = numOfNode - } -} - -func WithOCRConfigOverride(override func(CCIPOCRParams) CCIPOCRParams) TestOps { - return func(testCfg *TestConfigs) { - testCfg.OCRConfigOverride = override - } -} - -func WithUSDCAttestationMissing() TestOps { - return func(testCfg *TestConfigs) { - testCfg.IsUSDCAttestationMissing = true - } -} - -func WithUSDC() TestOps { - return func(testCfg *TestConfigs) { - testCfg.IsUSDC = true - } -} - -func WithChains(numChains int) TestOps { - return func(testCfg *TestConfigs) { - testCfg.Chains = numChains - } -} - -func WithUsersPerChain(numUsers int) TestOps { - return func(testCfg *TestConfigs) { - testCfg.NumOfUsersPerChain = numUsers - } -} - -func WithNodes(numNodes int) TestOps { - return func(testCfg *TestConfigs) { - testCfg.Nodes = numNodes - } -} - -func WithBootstraps(numBootstraps int) TestOps { - return func(testCfg *TestConfigs) { - testCfg.Bootstraps = numBootstraps - } -} - -type TestEnvironment interface { - SetupJobs(t *testing.T) - StartNodes(t *testing.T, tc *TestConfigs, crConfig deployment.CapabilityRegistryConfig) - StartChains(t *testing.T, tc *TestConfigs) - DeployedEnvironment() DeployedEnv - MockUSDCAttestationServer(t *testing.T, isUSDCAttestationMissing bool) string -} - -type DeployedEnv struct { - Env deployment.Environment - HomeChainSel uint64 - FeedChainSel uint64 - ReplayBlocks map[uint64]uint64 - Users map[uint64][]*bind.TransactOpts -} - -func (d *DeployedEnv) TimelockContracts(t *testing.T) map[uint64]*proposalutils.TimelockExecutionContracts { - timelocks := make(map[uint64]*proposalutils.TimelockExecutionContracts) - state, err := LoadOnchainState(d.Env) - require.NoError(t, err) - for chain, chainState := range state.Chains { - timelocks[chain] = &proposalutils.TimelockExecutionContracts{ - Timelock: chainState.Timelock, - CallProxy: chainState.CallProxy, - } - } - return timelocks -} - -func (d *DeployedEnv) SetupJobs(t *testing.T) { - ctx := testcontext.Get(t) - out, err := CCIPCapabilityJobspec(d.Env, struct{}{}) - require.NoError(t, err) - for nodeID, jobs := range out.JobSpecs { - for _, job := range jobs { - // Note these auto-accept - _, err := d.Env.Offchain.ProposeJob(ctx, - &jobv1.ProposeJobRequest{ - NodeId: nodeID, - Spec: job, - }) - require.NoError(t, err) - } - } - // Wait for plugins to register filters? - // TODO: Investigate how to avoid. - time.Sleep(30 * time.Second) - ReplayLogs(t, d.Env.Offchain, d.ReplayBlocks) -} - -type MemoryEnvironment struct { - DeployedEnv - Chains map[uint64]deployment.Chain -} - -func (m *MemoryEnvironment) DeployedEnvironment() DeployedEnv { - return m.DeployedEnv -} - -func (m *MemoryEnvironment) StartChains(t *testing.T, tc *TestConfigs) { - ctx := testcontext.Get(t) - var chains map[uint64]deployment.Chain - var users map[uint64][]*bind.TransactOpts - if len(tc.ChainIDs) > 0 { - chains, users = memory.NewMemoryChainsWithChainIDs(t, tc.ChainIDs, tc.NumOfUsersPerChain) - if tc.Chains > len(tc.ChainIDs) { - additionalChains, additionalUsers := memory.NewMemoryChains(t, tc.Chains-len(tc.ChainIDs), tc.NumOfUsersPerChain) - for k, v := range additionalChains { - chains[k] = v - } - for k, v := range additionalUsers { - users[k] = v - } - } - } else { - chains, users = memory.NewMemoryChains(t, tc.Chains, tc.NumOfUsersPerChain) - } - m.Chains = chains - homeChainSel, feedSel := allocateCCIPChainSelectors(chains) - replayBlocks, err := LatestBlocksByChain(ctx, chains) - require.NoError(t, err) - m.DeployedEnv = DeployedEnv{ - Env: deployment.Environment{ - Chains: m.Chains, - }, - HomeChainSel: homeChainSel, - FeedChainSel: feedSel, - ReplayBlocks: replayBlocks, - Users: users, - } -} - -func (m *MemoryEnvironment) StartNodes(t *testing.T, tc *TestConfigs, crConfig deployment.CapabilityRegistryConfig) { - require.NotNil(t, m.Chains, "start chains first, chains are empty") - require.NotNil(t, m.DeployedEnv, "start chains and initiate deployed env first before starting nodes") - nodes := memory.NewNodes(t, zapcore.InfoLevel, m.Chains, tc.Nodes, tc.Bootstraps, crConfig) - ctx := testcontext.Get(t) - lggr := logger.Test(t) - for _, node := range nodes { - require.NoError(t, node.App.Start(ctx)) - t.Cleanup(func() { - require.NoError(t, node.App.Stop()) - }) - } - m.DeployedEnv.Env = memory.NewMemoryEnvironmentFromChainsNodes(func() context.Context { return ctx }, lggr, m.Chains, nodes) -} - -func (m *MemoryEnvironment) MockUSDCAttestationServer(t *testing.T, isUSDCAttestationMissing bool) string { - server := mockAttestationResponse(isUSDCAttestationMissing) - endpoint := server.URL - t.Cleanup(func() { - server.Close() - }) - return endpoint -} - -// NewMemoryEnvironment creates an in-memory environment based on the testconfig requested -func NewMemoryEnvironment(t *testing.T, opts ...TestOps) DeployedEnv { - testCfg := DefaultTestConfigs() - for _, opt := range opts { - opt(testCfg) - } - require.NoError(t, testCfg.Validate(), "invalid test config") - env := &MemoryEnvironment{} - if testCfg.LegacyDeployment { - return NewLegacyEnvironment(t, testCfg, env) - } - if testCfg.CreateJobAndContracts { - return NewEnvironmentWithJobsAndContracts(t, testCfg, env) - } - if testCfg.CreateJob { - return NewEnvironmentWithJobs(t, testCfg, env) - } - return NewEnvironment(t, testCfg, env) -} - -func NewLegacyEnvironment(t *testing.T, tc *TestConfigs, tEnv TestEnvironment) DeployedEnv { - var err error - tEnv.StartChains(t, tc) - e := tEnv.DeployedEnvironment() - require.NotEmpty(t, e.Env.Chains) - tEnv.StartNodes(t, tc, deployment.CapabilityRegistryConfig{}) - e = tEnv.DeployedEnvironment() - allChains := e.Env.AllChainSelectors() - - mcmsCfg := make(map[uint64]commontypes.MCMSWithTimelockConfig) - for _, c := range e.Env.AllChainSelectors() { - mcmsCfg[c] = proposalutils.SingleGroupTimelockConfig(t) - } - var prereqCfg []DeployPrerequisiteConfigPerChain - for _, chain := range allChains { - var opts []PrerequisiteOpt - if tc != nil { - if tc.IsUSDC { - opts = append(opts, WithUSDCEnabled()) - } - if tc.IsMultiCall3 { - opts = append(opts, WithMultiCall3Enabled()) - } - } - opts = append(opts, WithLegacyDeploymentEnabled(LegacyDeploymentConfig{ - PriceRegStalenessThreshold: 60 * 60 * 24 * 14, // two weeks - })) - prereqCfg = append(prereqCfg, DeployPrerequisiteConfigPerChain{ - ChainSelector: chain, - Opts: opts, - }) - } - - e.Env, err = commonchangeset.ApplyChangesets(t, e.Env, nil, []commonchangeset.ChangesetApplication{ - { - Changeset: commonchangeset.WrapChangeSet(commonchangeset.DeployLinkToken), - Config: allChains, - }, - { - Changeset: commonchangeset.WrapChangeSet(DeployPrerequisites), - Config: DeployPrerequisiteConfig{ - Configs: prereqCfg, - }, - }, - { - Changeset: commonchangeset.WrapChangeSet(commonchangeset.DeployMCMSWithTimelock), - Config: mcmsCfg, - }, - }) - require.NoError(t, err) - return e -} - -func NewEnvironment(t *testing.T, tc *TestConfigs, tEnv TestEnvironment) DeployedEnv { - lggr := logger.Test(t) - tEnv.StartChains(t, tc) - dEnv := tEnv.DeployedEnvironment() - require.NotEmpty(t, dEnv.FeedChainSel) - require.NotEmpty(t, dEnv.HomeChainSel) - require.NotEmpty(t, dEnv.Env.Chains) - ab := deployment.NewMemoryAddressBook() - crConfig := DeployTestContracts(t, lggr, ab, dEnv.HomeChainSel, dEnv.FeedChainSel, dEnv.Env.Chains, tc.LinkPrice, tc.WethPrice) - tEnv.StartNodes(t, tc, crConfig) - dEnv = tEnv.DeployedEnvironment() - // TODO: Should use ApplyChangesets here. - envNodes, err := deployment.NodeInfo(dEnv.Env.NodeIDs, dEnv.Env.Offchain) - require.NoError(t, err) - dEnv.Env.ExistingAddresses = ab - _, err = deployHomeChain(lggr, dEnv.Env, dEnv.Env.ExistingAddresses, dEnv.Env.Chains[dEnv.HomeChainSel], - NewTestRMNStaticConfig(), - NewTestRMNDynamicConfig(), - NewTestNodeOperator(dEnv.Env.Chains[dEnv.HomeChainSel].DeployerKey.From), - map[string][][32]byte{ - "NodeOperator": envNodes.NonBootstraps().PeerIDs(), - }, - ) - require.NoError(t, err) - - return dEnv -} - -func NewEnvironmentWithJobsAndContracts(t *testing.T, tc *TestConfigs, tEnv TestEnvironment) DeployedEnv { - var err error - e := NewEnvironment(t, tc, tEnv) - allChains := e.Env.AllChainSelectors() - mcmsCfg := make(map[uint64]commontypes.MCMSWithTimelockConfig) - - for _, c := range e.Env.AllChainSelectors() { - mcmsCfg[c] = proposalutils.SingleGroupTimelockConfig(t) - } - - var prereqCfg []DeployPrerequisiteConfigPerChain - for _, chain := range allChains { - var opts []PrerequisiteOpt - if tc != nil { - if tc.IsUSDC { - opts = append(opts, WithUSDCEnabled()) - } - if tc.IsMultiCall3 { - opts = append(opts, WithMultiCall3Enabled()) - } - } - prereqCfg = append(prereqCfg, DeployPrerequisiteConfigPerChain{ - ChainSelector: chain, - Opts: opts, - }) - } - // Need to deploy prerequisites first so that we can form the USDC config - // no proposals to be made, timelock can be passed as nil here - e.Env, err = commonchangeset.ApplyChangesets(t, e.Env, nil, []commonchangeset.ChangesetApplication{ - { - Changeset: commonchangeset.WrapChangeSet(commonchangeset.DeployLinkToken), - Config: allChains, - }, - { - Changeset: commonchangeset.WrapChangeSet(DeployPrerequisites), - Config: DeployPrerequisiteConfig{ - Configs: prereqCfg, - }, - }, - { - Changeset: commonchangeset.WrapChangeSet(commonchangeset.DeployMCMSWithTimelock), - Config: mcmsCfg, - }, - { - Changeset: commonchangeset.WrapChangeSet(DeployChainContracts), - Config: DeployChainContractsConfig{ - ChainSelectors: allChains, - HomeChainSelector: e.HomeChainSel, - }, - }, - { - Changeset: commonchangeset.WrapChangeSet(SetRMNRemoteOnRMNProxy), - Config: SetRMNRemoteOnRMNProxyConfig{ - ChainSelectors: allChains, - }, - }, - }) - require.NoError(t, err) - - state, err := LoadOnchainState(e.Env) - require.NoError(t, err) - // Assert link present - require.NotNil(t, state.Chains[e.FeedChainSel].LinkToken) - require.NotNil(t, state.Chains[e.FeedChainSel].Weth9) - - tokenConfig := NewTestTokenConfig(state.Chains[e.FeedChainSel].USDFeeds) - var tokenDataProviders []pluginconfig.TokenDataObserverConfig - if tc.IsUSDC { - endpoint := tEnv.MockUSDCAttestationServer(t, tc.IsUSDCAttestationMissing) - cctpContracts := make(map[cciptypes.ChainSelector]pluginconfig.USDCCCTPTokenConfig) - for _, usdcChain := range allChains { - require.NotNil(t, state.Chains[usdcChain].MockUSDCTokenMessenger) - require.NotNil(t, state.Chains[usdcChain].MockUSDCTransmitter) - require.NotNil(t, state.Chains[usdcChain].USDCTokenPool) - cctpContracts[cciptypes.ChainSelector(usdcChain)] = pluginconfig.USDCCCTPTokenConfig{ - SourcePoolAddress: state.Chains[usdcChain].USDCTokenPool.Address().String(), - SourceMessageTransmitterAddr: state.Chains[usdcChain].MockUSDCTransmitter.Address().String(), - } - } - tokenDataProviders = append(tokenDataProviders, pluginconfig.TokenDataObserverConfig{ - Type: pluginconfig.USDCCCTPHandlerType, - Version: "1.0", - USDCCCTPObserverConfig: &pluginconfig.USDCCCTPObserverConfig{ - Tokens: cctpContracts, - AttestationAPI: endpoint, - AttestationAPITimeout: commonconfig.MustNewDuration(time.Second), - AttestationAPIInterval: commonconfig.MustNewDuration(500 * time.Millisecond), - }}) - } - // Build the per chain config. - ocrConfigs := make(map[uint64]CCIPOCRParams) - chainConfigs := make(map[uint64]ChainConfig) - timelockContractsPerChain := make(map[uint64]*proposalutils.TimelockExecutionContracts) - nodeInfo, err := deployment.NodeInfo(e.Env.NodeIDs, e.Env.Offchain) - require.NoError(t, err) - for _, chain := range allChains { - timelockContractsPerChain[chain] = &proposalutils.TimelockExecutionContracts{ - Timelock: state.Chains[chain].Timelock, - CallProxy: state.Chains[chain].CallProxy, - } - tokenInfo := tokenConfig.GetTokenInfo(e.Env.Logger, state.Chains[chain].LinkToken, state.Chains[chain].Weth9) - ocrParams := DefaultOCRParams(e.FeedChainSel, tokenInfo, tokenDataProviders) - if tc.OCRConfigOverride != nil { - ocrParams = tc.OCRConfigOverride(ocrParams) - } - ocrConfigs[chain] = ocrParams - chainConfigs[chain] = ChainConfig{ - Readers: nodeInfo.NonBootstraps().PeerIDs(), - FChain: uint8(len(nodeInfo.NonBootstraps().PeerIDs()) / 3), - EncodableChainConfig: chainconfig.ChainConfig{ - GasPriceDeviationPPB: cciptypes.BigInt{Int: big.NewInt(internal.GasPriceDeviationPPB)}, - DAGasPriceDeviationPPB: cciptypes.BigInt{Int: big.NewInt(internal.DAGasPriceDeviationPPB)}, - OptimisticConfirmations: internal.OptimisticConfirmations, - }, - } - } - // Deploy second set of changesets to deploy and configure the CCIP contracts. - e.Env, err = commonchangeset.ApplyChangesets(t, e.Env, timelockContractsPerChain, []commonchangeset.ChangesetApplication{ - { - // Add the chain configs for the new chains. - Changeset: commonchangeset.WrapChangeSet(UpdateChainConfig), - Config: UpdateChainConfigConfig{ - HomeChainSelector: e.HomeChainSel, - RemoteChainAdds: chainConfigs, - }, - }, - { - // Add the DONs and candidate commit OCR instances for the chain. - Changeset: commonchangeset.WrapChangeSet(AddDonAndSetCandidateChangeset), - Config: AddDonAndSetCandidateChangesetConfig{ - SetCandidateConfigBase{ - HomeChainSelector: e.HomeChainSel, - FeedChainSelector: e.FeedChainSel, - OCRConfigPerRemoteChainSelector: ocrConfigs, - PluginType: types.PluginTypeCCIPCommit, - }, - }, - }, - { - // Add the exec OCR instances for the new chains. - Changeset: commonchangeset.WrapChangeSet(SetCandidateChangeset), - Config: SetCandidateChangesetConfig{ - SetCandidateConfigBase{ - HomeChainSelector: e.HomeChainSel, - FeedChainSelector: e.FeedChainSel, - OCRConfigPerRemoteChainSelector: ocrConfigs, - PluginType: types.PluginTypeCCIPExec, - }, - }, - }, - { - // Promote everything - Changeset: commonchangeset.WrapChangeSet(PromoteAllCandidatesChangeset), - Config: PromoteCandidatesChangesetConfig{ - HomeChainSelector: e.HomeChainSel, - RemoteChainSelectors: allChains, - PluginType: types.PluginTypeCCIPCommit, - }, - }, - { - // Promote everything - Changeset: commonchangeset.WrapChangeSet(PromoteAllCandidatesChangeset), - Config: PromoteCandidatesChangesetConfig{ - HomeChainSelector: e.HomeChainSel, - RemoteChainSelectors: allChains, - PluginType: types.PluginTypeCCIPExec, - }, - }, - { - // Enable the OCR config on the remote chains. - Changeset: commonchangeset.WrapChangeSet(SetOCR3OffRamp), - Config: SetOCR3OffRampConfig{ - HomeChainSel: e.HomeChainSel, - RemoteChainSels: allChains, - }, - }, - { - Changeset: commonchangeset.WrapChangeSet(CCIPCapabilityJobspec), - }, - }) - require.NoError(t, err) - - ReplayLogs(t, e.Env.Offchain, e.ReplayBlocks) - - state, err = LoadOnchainState(e.Env) - require.NoError(t, err) - require.NotNil(t, state.Chains[e.HomeChainSel].CapabilityRegistry) - require.NotNil(t, state.Chains[e.HomeChainSel].CCIPHome) - require.NotNil(t, state.Chains[e.HomeChainSel].RMNHome) - for _, chain := range allChains { - require.NotNil(t, state.Chains[chain].LinkToken) - require.NotNil(t, state.Chains[chain].Weth9) - require.NotNil(t, state.Chains[chain].TokenAdminRegistry) - require.NotNil(t, state.Chains[chain].RegistryModule) - require.NotNil(t, state.Chains[chain].Router) - require.NotNil(t, state.Chains[chain].RMNRemote) - require.NotNil(t, state.Chains[chain].TestRouter) - require.NotNil(t, state.Chains[chain].NonceManager) - require.NotNil(t, state.Chains[chain].FeeQuoter) - require.NotNil(t, state.Chains[chain].OffRamp) - require.NotNil(t, state.Chains[chain].OnRamp) - } - return e -} - -// NewEnvironmentWithJobs creates a new CCIP environment -// with capreg, fee tokens, feeds, nodes and jobs set up. -func NewEnvironmentWithJobs(t *testing.T, tc *TestConfigs, tEnv TestEnvironment) DeployedEnv { - e := NewEnvironment(t, tc, tEnv) - e.SetupJobs(t) - return e -} diff --git a/deployment/ccip/changeset/test_helpers.go b/deployment/ccip/changeset/test_helpers.go deleted file mode 100644 index cfd24d88ebd..00000000000 --- a/deployment/ccip/changeset/test_helpers.go +++ /dev/null @@ -1,1259 +0,0 @@ -package changeset - -import ( - "context" - "fmt" - "math/big" - "net/http" - "net/http/httptest" - "sort" - "strings" - "testing" - "time" - - "golang.org/x/sync/errgroup" - - "github.com/ethereum/go-ethereum/accounts/abi/bind" - "github.com/ethereum/go-ethereum/common/hexutil" - "github.com/ethereum/go-ethereum/core/types" - "github.com/pkg/errors" - - commoncs "github.com/smartcontractkit/chainlink/deployment/common/changeset" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/fee_quoter" - "github.com/smartcontractkit/chainlink/v2/core/services/relay" - - "github.com/ethereum/go-ethereum/common" - "github.com/stretchr/testify/require" - - chainsel "github.com/smartcontractkit/chain-selectors" - "go.uber.org/multierr" - - "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/testcontext" - - "github.com/smartcontractkit/chainlink-ccip/pkg/reader" - cciptypes "github.com/smartcontractkit/chainlink-ccip/pkg/types/ccipocr3" - - "github.com/smartcontractkit/chainlink-common/pkg/logger" - commonutils "github.com/smartcontractkit/chainlink-common/pkg/utils" - "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" - - "github.com/smartcontractkit/chainlink/deployment" - "github.com/smartcontractkit/chainlink/deployment/environment/devenv" - "github.com/smartcontractkit/chainlink/deployment/environment/memory" - - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/burn_mint_token_pool" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/mock_v3_aggregator_contract" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/onramp" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/router" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/usdc_token_pool" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/aggregator_v3_interface" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/mock_ethusd_aggregator_wrapper" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/shared/generated/burn_mint_erc677" - "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/abihelpers" -) - -const ( - HomeChainIndex = 0 - FeedChainIndex = 1 -) - -var ( - // bytes4 public constant EVM_EXTRA_ARGS_V2_TAG = 0x181dcf10; - evmExtraArgsV2Tag = hexutil.MustDecode("0x181dcf10") - - routerABI = abihelpers.MustParseABI(router.RouterABI) - - DefaultLinkPrice = deployment.E18Mult(20) - DefaultWethPrice = deployment.E18Mult(4000) - DefaultGasPrice = ToPackedFee(big.NewInt(8e14), big.NewInt(0)) -) - -// Context returns a context with the test's deadline, if available. -func Context(tb testing.TB) context.Context { - ctx := context.Background() - var cancel func() - switch t := tb.(type) { - case *testing.T: - if d, ok := t.Deadline(); ok { - ctx, cancel = context.WithDeadline(ctx, d) - } - } - if cancel == nil { - ctx, cancel = context.WithCancel(ctx) - } - tb.Cleanup(cancel) - return ctx -} - -func ReplayLogs(t *testing.T, oc deployment.OffchainClient, replayBlocks map[uint64]uint64) { - switch oc := oc.(type) { - case *memory.JobClient: - require.NoError(t, oc.ReplayLogs(replayBlocks)) - case *devenv.JobDistributor: - require.NoError(t, oc.ReplayLogs(replayBlocks)) - default: - t.Fatalf("unsupported offchain client type %T", oc) - } -} - -func DeployTestContracts(t *testing.T, - lggr logger.Logger, - ab deployment.AddressBook, - homeChainSel, - feedChainSel uint64, - chains map[uint64]deployment.Chain, - linkPrice *big.Int, - wethPrice *big.Int, -) deployment.CapabilityRegistryConfig { - capReg, err := deployCapReg(lggr, - // deploying cap reg for the first time on a blank chain state - CCIPOnChainState{ - Chains: make(map[uint64]CCIPChainState), - }, ab, chains[homeChainSel]) - require.NoError(t, err) - - _, err = DeployFeeds(lggr, ab, chains[feedChainSel], linkPrice, wethPrice) - require.NoError(t, err) - - evmChainID, err := chainsel.ChainIdFromSelector(homeChainSel) - require.NoError(t, err) - - return deployment.CapabilityRegistryConfig{ - EVMChainID: evmChainID, - Contract: capReg.Address, - NetworkType: relay.NetworkEVM, - } -} - -func LatestBlocksByChain(ctx context.Context, chains map[uint64]deployment.Chain) (map[uint64]uint64, error) { - latestBlocks := make(map[uint64]uint64) - for _, chain := range chains { - latesthdr, err := chain.Client.HeaderByNumber(ctx, nil) - if err != nil { - return nil, errors.Wrapf(err, "failed to get latest header for chain %d", chain.Selector) - } - block := latesthdr.Number.Uint64() - latestBlocks[chain.Selector] = block - } - return latestBlocks, nil -} - -func allocateCCIPChainSelectors(chains map[uint64]deployment.Chain) (homeChainSel uint64, feeChainSel uint64) { - // Lower chainSel is home chain. - var chainSels []uint64 - // Say first chain is home chain. - for chainSel := range chains { - chainSels = append(chainSels, chainSel) - } - sort.Slice(chainSels, func(i, j int) bool { - return chainSels[i] < chainSels[j] - }) - // Take lowest for determinism. - return chainSels[HomeChainIndex], chainSels[FeedChainIndex] -} - -// mockAttestationResponse mocks the USDC attestation server, it returns random Attestation. -// We don't need to return exactly the same attestation, because our Mocked USDC contract doesn't rely on any specific -// value, but instead of that it just checks if the attestation is present. Therefore, it makes the test a bit simpler -// and doesn't require very detailed mocks. Please see tests in chainlink-ccip for detailed tests using real attestations -func mockAttestationResponse(isFaulty bool) *httptest.Server { - server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - response := `{ - "status": "complete", - "attestation": "0x9049623e91719ef2aa63c55f357be2529b0e7122ae552c18aff8db58b4633c4d3920ff03d3a6d1ddf11f06bf64d7fd60d45447ac81f527ba628877dc5ca759651b08ffae25a6d3b1411749765244f0a1c131cbfe04430d687a2e12fd9d2e6dc08e118ad95d94ad832332cf3c4f7a4f3da0baa803b7be024b02db81951c0f0714de1b" - }` - if isFaulty { - response = `{ - "status": "pending", - "error": "internal error" - }` - } - _, err := w.Write([]byte(response)) - if err != nil { - panic(err) - } - })) - return server -} - -func CCIPSendRequest( - e deployment.Environment, - state CCIPOnChainState, - cfg *CCIPSendReqConfig, -) (*types.Transaction, uint64, error) { - msg := router.ClientEVM2AnyMessage{ - Receiver: cfg.Evm2AnyMessage.Receiver, - Data: cfg.Evm2AnyMessage.Data, - TokenAmounts: cfg.Evm2AnyMessage.TokenAmounts, - FeeToken: cfg.Evm2AnyMessage.FeeToken, - ExtraArgs: cfg.Evm2AnyMessage.ExtraArgs, - } - r := state.Chains[cfg.SourceChain].Router - if cfg.IsTestRouter { - r = state.Chains[cfg.SourceChain].TestRouter - } - - if msg.FeeToken == common.HexToAddress("0x0") { // fee is in native token - return retryCcipSendUntilNativeFeeIsSufficient(e, r, cfg) - } - - tx, err := r.CcipSend(cfg.Sender, cfg.DestChain, msg) - if err != nil { - return nil, 0, errors.Wrap(err, "failed to send CCIP message") - } - blockNum, err := e.Chains[cfg.SourceChain].Confirm(tx) - if err != nil { - return tx, 0, errors.Wrap(err, "failed to confirm CCIP message") - } - return tx, blockNum, nil -} - -// retryCcipSendUntilNativeFeeIsSufficient sends a CCIP message with a native fee, -// and retries until the fee is sufficient. This is due to the fact that the fee is not known in advance, -// and the message will be rejected if the fee is insufficient. -func retryCcipSendUntilNativeFeeIsSufficient( - e deployment.Environment, - r *router.Router, - cfg *CCIPSendReqConfig, -) (*types.Transaction, uint64, error) { - const errCodeInsufficientFee = "0x07da6ee6" - defer func() { cfg.Sender.Value = nil }() - - for { - fee, err := r.GetFee(&bind.CallOpts{Context: context.Background()}, cfg.DestChain, cfg.Evm2AnyMessage) - if err != nil { - return nil, 0, fmt.Errorf("failed to get fee: %w", deployment.MaybeDataErr(err)) - } - - cfg.Sender.Value = fee - - tx, err := r.CcipSend(cfg.Sender, cfg.DestChain, cfg.Evm2AnyMessage) - if err != nil { - return nil, 0, fmt.Errorf("failed to send CCIP message: %w", err) - } - - blockNum, err := e.Chains[cfg.SourceChain].Confirm(tx) - if err != nil { - if strings.Contains(err.Error(), errCodeInsufficientFee) { - continue - } - return nil, 0, fmt.Errorf("failed to confirm CCIP message: %w", deployment.MaybeDataErr(err)) - } - - return tx, blockNum, nil - } -} - -// CCIPSendCalldata packs the calldata for the Router's ccipSend method. -// This is expected to be used in Multicall scenarios (i.e multiple ccipSend calls -// in a single transaction). -func CCIPSendCalldata( - destChainSelector uint64, - evm2AnyMessage router.ClientEVM2AnyMessage, -) ([]byte, error) { - calldata, err := routerABI.Methods["ccipSend"].Inputs.Pack( - destChainSelector, - evm2AnyMessage, - ) - if err != nil { - return nil, fmt.Errorf("pack ccipSend calldata: %w", err) - } - - calldata = append(routerABI.Methods["ccipSend"].ID, calldata...) - return calldata, nil -} - -func TestSendRequest( - t *testing.T, - e deployment.Environment, - state CCIPOnChainState, - src, dest uint64, - testRouter bool, - evm2AnyMessage router.ClientEVM2AnyMessage, -) (msgSentEvent *onramp.OnRampCCIPMessageSent) { - msgSentEvent, err := DoSendRequest(t, e, state, - WithSender(e.Chains[src].DeployerKey), - WithSourceChain(src), - WithDestChain(dest), - WithTestRouter(testRouter), - WithEvm2AnyMessage(evm2AnyMessage)) - require.NoError(t, err) - return msgSentEvent -} - -type CCIPSendReqConfig struct { - SourceChain uint64 - DestChain uint64 - IsTestRouter bool - Sender *bind.TransactOpts - Evm2AnyMessage router.ClientEVM2AnyMessage -} - -type SendReqOpts func(*CCIPSendReqConfig) - -func WithSender(sender *bind.TransactOpts) SendReqOpts { - return func(c *CCIPSendReqConfig) { - c.Sender = sender - } -} - -func WithEvm2AnyMessage(msg router.ClientEVM2AnyMessage) SendReqOpts { - return func(c *CCIPSendReqConfig) { - c.Evm2AnyMessage = msg - } -} - -func WithTestRouter(isTestRouter bool) SendReqOpts { - return func(c *CCIPSendReqConfig) { - c.IsTestRouter = isTestRouter - } -} - -func WithSourceChain(sourceChain uint64) SendReqOpts { - return func(c *CCIPSendReqConfig) { - c.SourceChain = sourceChain - } -} - -func WithDestChain(destChain uint64) SendReqOpts { - return func(c *CCIPSendReqConfig) { - c.DestChain = destChain - } -} - -// DoSendRequest similar to TestSendRequest but returns an error. -func DoSendRequest( - t *testing.T, - e deployment.Environment, - state CCIPOnChainState, - opts ...SendReqOpts, -) (*onramp.OnRampCCIPMessageSent, error) { - cfg := &CCIPSendReqConfig{} - for _, opt := range opts { - opt(cfg) - } - // Set default sender if not provided - if cfg.Sender == nil { - cfg.Sender = e.Chains[cfg.SourceChain].DeployerKey - } - t.Logf("Sending CCIP request from chain selector %d to chain selector %d from sender %s", - cfg.SourceChain, cfg.DestChain, cfg.Sender.From.String()) - tx, blockNum, err := CCIPSendRequest(e, state, cfg) - if err != nil { - return nil, err - } - - it, err := state.Chains[cfg.SourceChain].OnRamp.FilterCCIPMessageSent(&bind.FilterOpts{ - Start: blockNum, - End: &blockNum, - Context: context.Background(), - }, []uint64{cfg.DestChain}, []uint64{}) - if err != nil { - return nil, err - } - - require.True(t, it.Next()) - t.Logf("CCIP message (id %x) sent from chain selector %d to chain selector %d tx %s seqNum %d nonce %d sender %s", - it.Event.Message.Header.MessageId[:], - cfg.SourceChain, - cfg.DestChain, - tx.Hash().String(), - it.Event.SequenceNumber, - it.Event.Message.Header.Nonce, - it.Event.Message.Sender.String(), - ) - return it.Event, nil -} - -// MakeEVMExtraArgsV2 creates the extra args for the EVM2Any message that is destined -// for an EVM chain. The extra args contain the gas limit and allow out of order flag. -func MakeEVMExtraArgsV2(gasLimit uint64, allowOOO bool) []byte { - // extra args is the tag followed by the gas limit and allowOOO abi-encoded. - var extraArgs []byte - extraArgs = append(extraArgs, evmExtraArgsV2Tag...) - gasLimitBytes := new(big.Int).SetUint64(gasLimit).Bytes() - // pad from the left to 32 bytes - gasLimitBytes = common.LeftPadBytes(gasLimitBytes, 32) - - // abi-encode allowOOO - var allowOOOBytes []byte - if allowOOO { - allowOOOBytes = append(allowOOOBytes, 1) - } else { - allowOOOBytes = append(allowOOOBytes, 0) - } - // pad from the left to 32 bytes - allowOOOBytes = common.LeftPadBytes(allowOOOBytes, 32) - - extraArgs = append(extraArgs, gasLimitBytes...) - extraArgs = append(extraArgs, allowOOOBytes...) - return extraArgs -} - -func AddLane(t *testing.T, e *DeployedEnv, from, to uint64, isTestRouter bool, gasprice map[uint64]*big.Int, tokenPrices map[common.Address]*big.Int, fqCfg fee_quoter.FeeQuoterDestChainConfig) { - var err error - e.Env, err = commoncs.ApplyChangesets(t, e.Env, e.TimelockContracts(t), []commoncs.ChangesetApplication{ - { - Changeset: commoncs.WrapChangeSet(UpdateOnRampsDests), - Config: UpdateOnRampDestsConfig{ - UpdatesByChain: map[uint64]map[uint64]OnRampDestinationUpdate{ - from: { - to: { - IsEnabled: true, - TestRouter: isTestRouter, - AllowListEnabled: false, - }, - }, - }, - }, - }, - { - Changeset: commoncs.WrapChangeSet(UpdateFeeQuoterPricesCS), - Config: UpdateFeeQuoterPricesConfig{ - PricesByChain: map[uint64]FeeQuoterPriceUpdatePerSource{ - from: { - TokenPrices: tokenPrices, - GasPrices: gasprice, - }, - }, - }, - }, - { - Changeset: commoncs.WrapChangeSet(UpdateFeeQuoterDests), - Config: UpdateFeeQuoterDestsConfig{ - UpdatesByChain: map[uint64]map[uint64]fee_quoter.FeeQuoterDestChainConfig{ - from: { - to: fqCfg, - }, - }, - }, - }, - { - Changeset: commoncs.WrapChangeSet(UpdateOffRampSources), - Config: UpdateOffRampSourcesConfig{ - UpdatesByChain: map[uint64]map[uint64]OffRampSourceUpdate{ - to: { - from: { - IsEnabled: true, - TestRouter: isTestRouter, - }, - }, - }, - }, - }, - { - Changeset: commoncs.WrapChangeSet(UpdateRouterRamps), - Config: UpdateRouterRampsConfig{ - TestRouter: isTestRouter, - UpdatesByChain: map[uint64]RouterUpdates{ - // onRamp update on source chain - from: { - OnRampUpdates: map[uint64]bool{ - to: true, - }, - }, - // offramp update on dest chain - to: { - OffRampUpdates: map[uint64]bool{ - from: true, - }, - }, - }, - }, - }, - }) - require.NoError(t, err) -} - -func AddLaneWithDefaultPricesAndFeeQuoterConfig(t *testing.T, e *DeployedEnv, state CCIPOnChainState, from, to uint64, isTestRouter bool) { - stateChainFrom := state.Chains[from] - AddLane(t, e, from, to, isTestRouter, - map[uint64]*big.Int{ - to: DefaultGasPrice, - }, map[common.Address]*big.Int{ - stateChainFrom.LinkToken.Address(): DefaultLinkPrice, - stateChainFrom.Weth9.Address(): DefaultWethPrice, - }, DefaultFeeQuoterDestChainConfig()) -} - -// AddLanesForAll adds densely connected lanes for all chains in the environment so that each chain -// is connected to every other chain except itself. -func AddLanesForAll(t *testing.T, e *DeployedEnv, state CCIPOnChainState) { - for source := range e.Env.Chains { - for dest := range e.Env.Chains { - if source != dest { - AddLaneWithDefaultPricesAndFeeQuoterConfig(t, e, state, source, dest, false) - } - } - } -} - -func ToPackedFee(execFee, daFee *big.Int) *big.Int { - daShifted := new(big.Int).Lsh(daFee, 112) - return new(big.Int).Or(daShifted, execFee) -} - -const ( - // MockLinkAggregatorDescription This is the description of the MockV3Aggregator.sol contract - //nolint:lll - // https://github.com/smartcontractkit/chainlink/blob/a348b98e90527520049c580000a86fb8ceff7fa7/contracts/src/v0.8/tests/MockV3Aggregator.sol#L76-L76 - MockLinkAggregatorDescription = "v0.8/tests/MockV3Aggregator.sol" - // MockWETHAggregatorDescription WETH use description from MockETHUSDAggregator.sol - //nolint:lll - // https://github.com/smartcontractkit/chainlink/blob/a348b98e90527520049c580000a86fb8ceff7fa7/contracts/src/v0.8/automation/testhelpers/MockETHUSDAggregator.sol#L19-L19 - MockWETHAggregatorDescription = "MockETHUSDAggregator" -) - -var ( - MockLinkPrice = deployment.E18Mult(500) - MockWethPrice = big.NewInt(9e8) - // MockDescriptionToTokenSymbol maps a mock feed description to token descriptor - MockDescriptionToTokenSymbol = map[string]TokenSymbol{ - MockLinkAggregatorDescription: LinkSymbol, - MockWETHAggregatorDescription: WethSymbol, - } - MockSymbolToDescription = map[TokenSymbol]string{ - LinkSymbol: MockLinkAggregatorDescription, - WethSymbol: MockWETHAggregatorDescription, - } - MockSymbolToDecimals = map[TokenSymbol]uint8{ - LinkSymbol: LinkDecimals, - WethSymbol: WethDecimals, - } -) - -func DeployFeeds( - lggr logger.Logger, - ab deployment.AddressBook, - chain deployment.Chain, - linkPrice *big.Int, - wethPrice *big.Int, -) (map[string]common.Address, error) { - linkTV := deployment.NewTypeAndVersion(PriceFeed, deployment.Version1_0_0) - mockLinkFeed := func(chain deployment.Chain) deployment.ContractDeploy[*aggregator_v3_interface.AggregatorV3Interface] { - linkFeed, tx, _, err1 := mock_v3_aggregator_contract.DeployMockV3Aggregator( - chain.DeployerKey, - chain.Client, - LinkDecimals, // decimals - linkPrice, // initialAnswer - ) - aggregatorCr, err2 := aggregator_v3_interface.NewAggregatorV3Interface(linkFeed, chain.Client) - - return deployment.ContractDeploy[*aggregator_v3_interface.AggregatorV3Interface]{ - Address: linkFeed, Contract: aggregatorCr, Tv: linkTV, Tx: tx, Err: multierr.Append(err1, err2), - } - } - - mockWethFeed := func(chain deployment.Chain) deployment.ContractDeploy[*aggregator_v3_interface.AggregatorV3Interface] { - wethFeed, tx, _, err1 := mock_ethusd_aggregator_wrapper.DeployMockETHUSDAggregator( - chain.DeployerKey, - chain.Client, - wethPrice, // initialAnswer - ) - aggregatorCr, err2 := aggregator_v3_interface.NewAggregatorV3Interface(wethFeed, chain.Client) - - return deployment.ContractDeploy[*aggregator_v3_interface.AggregatorV3Interface]{ - Address: wethFeed, Contract: aggregatorCr, Tv: linkTV, Tx: tx, Err: multierr.Append(err1, err2), - } - } - - linkFeedAddress, linkFeedDescription, err := deploySingleFeed(lggr, ab, chain, mockLinkFeed, LinkSymbol) - if err != nil { - return nil, err - } - - wethFeedAddress, wethFeedDescription, err := deploySingleFeed(lggr, ab, chain, mockWethFeed, WethSymbol) - if err != nil { - return nil, err - } - - descriptionToAddress := map[string]common.Address{ - linkFeedDescription: linkFeedAddress, - wethFeedDescription: wethFeedAddress, - } - - return descriptionToAddress, nil -} - -func deploySingleFeed( - lggr logger.Logger, - ab deployment.AddressBook, - chain deployment.Chain, - deployFunc func(deployment.Chain) deployment.ContractDeploy[*aggregator_v3_interface.AggregatorV3Interface], - symbol TokenSymbol, -) (common.Address, string, error) { - //tokenTV := deployment.NewTypeAndVersion(PriceFeed, deployment.Version1_0_0) - mockTokenFeed, err := deployment.DeployContract(lggr, chain, ab, deployFunc) - if err != nil { - lggr.Errorw("Failed to deploy token feed", "err", err, "symbol", symbol) - return common.Address{}, "", err - } - - lggr.Infow("deployed mockTokenFeed", "addr", mockTokenFeed.Address) - - desc, err := mockTokenFeed.Contract.Description(&bind.CallOpts{}) - if err != nil { - lggr.Errorw("Failed to get description", "err", err, "symbol", symbol) - return common.Address{}, "", err - } - - if desc != MockSymbolToDescription[symbol] { - lggr.Errorw("Unexpected description for token", "symbol", symbol, "desc", desc) - return common.Address{}, "", fmt.Errorf("unexpected description: %s", desc) - } - - return mockTokenFeed.Address, desc, nil -} - -func ConfirmRequestOnSourceAndDest(t *testing.T, env deployment.Environment, state CCIPOnChainState, sourceCS, destCS, expectedSeqNr uint64) error { - latesthdr, err := env.Chains[destCS].Client.HeaderByNumber(testcontext.Get(t), nil) - require.NoError(t, err) - startBlock := latesthdr.Number.Uint64() - fmt.Printf("startblock %d", startBlock) - msgSentEvent := TestSendRequest(t, env, state, sourceCS, destCS, false, router.ClientEVM2AnyMessage{ - Receiver: common.LeftPadBytes(state.Chains[destCS].Receiver.Address().Bytes(), 32), - Data: []byte("hello world"), - TokenAmounts: nil, - FeeToken: common.HexToAddress("0x0"), - ExtraArgs: nil, - }) - require.Equal(t, expectedSeqNr, msgSentEvent.SequenceNumber) - - fmt.Printf("Request sent for seqnr %d", msgSentEvent.SequenceNumber) - require.NoError(t, - commonutils.JustError(ConfirmCommitWithExpectedSeqNumRange(t, env.Chains[sourceCS], env.Chains[destCS], state.Chains[destCS].OffRamp, &startBlock, cciptypes.SeqNumRange{ - cciptypes.SeqNum(msgSentEvent.SequenceNumber), - cciptypes.SeqNum(msgSentEvent.SequenceNumber), - }, true))) - - fmt.Printf("Commit confirmed for seqnr %d", msgSentEvent.SequenceNumber) - require.NoError( - t, - commonutils.JustError( - ConfirmExecWithSeqNrs( - t, - env.Chains[sourceCS], - env.Chains[destCS], - state.Chains[destCS].OffRamp, - &startBlock, - []uint64{msgSentEvent.SequenceNumber}, - ), - ), - ) - - return nil -} - -func DeployTransferableToken( - lggr logger.Logger, - chains map[uint64]deployment.Chain, - src, dst uint64, - srcActor, dstActor *bind.TransactOpts, - state CCIPOnChainState, - addresses deployment.AddressBook, - token string, -) (*burn_mint_erc677.BurnMintERC677, *burn_mint_token_pool.BurnMintTokenPool, *burn_mint_erc677.BurnMintERC677, *burn_mint_token_pool.BurnMintTokenPool, error) { - // Deploy token and pools - srcToken, srcPool, dstToken, dstPool, err := deployTokenPoolsInParallel(lggr, chains, src, dst, srcActor, dstActor, state, addresses, token) - if err != nil { - return nil, nil, nil, nil, err - } - - // Configure pools in parallel - configurePoolGrp := errgroup.Group{} - configurePoolGrp.Go(func() error { - err := setTokenPoolCounterPart(chains[src], srcPool, srcActor, dst, dstToken.Address(), dstPool.Address()) - if err != nil { - return fmt.Errorf("failed to set token pool counter part chain %d: %w", src, err) - } - err = grantMintBurnPermissions(lggr, chains[src], srcToken, srcActor, srcPool.Address()) - if err != nil { - return fmt.Errorf("failed to grant mint burn permissions chain %d: %w", src, err) - } - return nil - }) - configurePoolGrp.Go(func() error { - err := setTokenPoolCounterPart(chains[dst], dstPool, dstActor, src, srcToken.Address(), srcPool.Address()) - if err != nil { - return fmt.Errorf("failed to set token pool counter part chain %d: %w", dst, err) - } - if err := grantMintBurnPermissions(lggr, chains[dst], dstToken, dstActor, dstPool.Address()); err != nil { - return fmt.Errorf("failed to grant mint burn permissions chain %d: %w", dst, err) - } - return nil - }) - if err := configurePoolGrp.Wait(); err != nil { - return nil, nil, nil, nil, err - } - return srcToken, srcPool, dstToken, dstPool, nil -} - -func deployTokenPoolsInParallel( - lggr logger.Logger, - chains map[uint64]deployment.Chain, - src, dst uint64, - srcActor, dstActor *bind.TransactOpts, - state CCIPOnChainState, - addresses deployment.AddressBook, - token string, -) ( - *burn_mint_erc677.BurnMintERC677, - *burn_mint_token_pool.BurnMintTokenPool, - *burn_mint_erc677.BurnMintERC677, - *burn_mint_token_pool.BurnMintTokenPool, - error, -) { - deployGrp := errgroup.Group{} - // Deploy token and pools - var srcToken *burn_mint_erc677.BurnMintERC677 - var srcPool *burn_mint_token_pool.BurnMintTokenPool - var dstToken *burn_mint_erc677.BurnMintERC677 - var dstPool *burn_mint_token_pool.BurnMintTokenPool - - deployGrp.Go(func() error { - var err error - srcToken, srcPool, err = deployTransferTokenOneEnd(lggr, chains[src], srcActor, addresses, token) - if err != nil { - return err - } - if err := attachTokenToTheRegistry(chains[src], state.Chains[src], srcActor, srcToken.Address(), srcPool.Address()); err != nil { - return err - } - return nil - }) - deployGrp.Go(func() error { - var err error - dstToken, dstPool, err = deployTransferTokenOneEnd(lggr, chains[dst], dstActor, addresses, token) - if err != nil { - return err - } - if err := attachTokenToTheRegistry(chains[dst], state.Chains[dst], dstActor, dstToken.Address(), dstPool.Address()); err != nil { - return err - } - return nil - }) - if err := deployGrp.Wait(); err != nil { - return nil, nil, nil, nil, err - } - if srcToken == nil || srcPool == nil || dstToken == nil || dstPool == nil { - return nil, nil, nil, nil, fmt.Errorf("failed to deploy token and pool") - } - return srcToken, srcPool, dstToken, dstPool, nil -} - -func grantMintBurnPermissions(lggr logger.Logger, chain deployment.Chain, token *burn_mint_erc677.BurnMintERC677, actor *bind.TransactOpts, address common.Address) error { - lggr.Infow("Granting burn/mint permissions", "token", token.Address(), "address", address) - tx, err := token.GrantMintAndBurnRoles(actor, address) - if err != nil { - return err - } - _, err = chain.Confirm(tx) - return err -} - -func setUSDCTokenPoolCounterPart( - chain deployment.Chain, - tokenPool *usdc_token_pool.USDCTokenPool, - destChainSelector uint64, - actor *bind.TransactOpts, - destTokenAddress common.Address, - destTokenPoolAddress common.Address, -) error { - allowedCaller := common.LeftPadBytes(destTokenPoolAddress.Bytes(), 32) - var fixedAddr [32]byte - copy(fixedAddr[:], allowedCaller[:32]) - - domain, _ := reader.AllAvailableDomains()[destChainSelector] - - domains := []usdc_token_pool.USDCTokenPoolDomainUpdate{ - { - AllowedCaller: fixedAddr, - DomainIdentifier: domain, - DestChainSelector: destChainSelector, - Enabled: true, - }, - } - tx, err := tokenPool.SetDomains(chain.DeployerKey, domains) - if err != nil { - return err - } - - _, err = chain.Confirm(tx) - if err != nil { - return err - } - - pool, err := burn_mint_token_pool.NewBurnMintTokenPool(tokenPool.Address(), chain.Client) - if err != nil { - return err - } - - return setTokenPoolCounterPart(chain, pool, actor, destChainSelector, destTokenAddress, destTokenPoolAddress) -} - -func setTokenPoolCounterPart(chain deployment.Chain, tokenPool *burn_mint_token_pool.BurnMintTokenPool, actor *bind.TransactOpts, destChainSelector uint64, destTokenAddress common.Address, destTokenPoolAddress common.Address) error { - tx, err := tokenPool.ApplyChainUpdates( - actor, - []uint64{}, - []burn_mint_token_pool.TokenPoolChainUpdate{ - { - RemoteChainSelector: destChainSelector, - RemotePoolAddresses: [][]byte{common.LeftPadBytes(destTokenPoolAddress.Bytes(), 32)}, - RemoteTokenAddress: common.LeftPadBytes(destTokenAddress.Bytes(), 32), - OutboundRateLimiterConfig: burn_mint_token_pool.RateLimiterConfig{ - IsEnabled: false, - Capacity: big.NewInt(0), - Rate: big.NewInt(0), - }, - InboundRateLimiterConfig: burn_mint_token_pool.RateLimiterConfig{ - IsEnabled: false, - Capacity: big.NewInt(0), - Rate: big.NewInt(0), - }, - }, - }, - ) - if err != nil { - return fmt.Errorf("failed to apply chain updates on token pool %s: %w", tokenPool.Address(), err) - } - - _, err = chain.Confirm(tx) - if err != nil { - return err - } - - tx, err = tokenPool.AddRemotePool( - actor, - destChainSelector, - destTokenPoolAddress.Bytes(), - ) - if err != nil { - return fmt.Errorf("failed to set remote pool on token pool %s: %w", tokenPool.Address(), err) - } - - _, err = chain.Confirm(tx) - return err -} - -func attachTokenToTheRegistry( - chain deployment.Chain, - state CCIPChainState, - owner *bind.TransactOpts, - token common.Address, - tokenPool common.Address, -) error { - pool, err := state.TokenAdminRegistry.GetPool(nil, token) - if err != nil { - return err - } - // Pool is already registered, don't reattach it, because it would cause revert - if pool != (common.Address{}) { - return nil - } - - tx, err := state.RegistryModule.RegisterAdminViaOwner(owner, token) - if err != nil { - return err - } - _, err = chain.Confirm(tx) - if err != nil { - return err - } - - tx, err = state.TokenAdminRegistry.AcceptAdminRole(owner, token) - if err != nil { - return err - } - _, err = chain.Confirm(tx) - if err != nil { - return err - } - - tx, err = state.TokenAdminRegistry.SetPool(owner, token, tokenPool) - if err != nil { - return err - } - _, err = chain.Confirm(tx) - if err != nil { - return err - } - return nil -} - -func deployTransferTokenOneEnd( - lggr logger.Logger, - chain deployment.Chain, - deployer *bind.TransactOpts, - addressBook deployment.AddressBook, - tokenSymbol string, -) (*burn_mint_erc677.BurnMintERC677, *burn_mint_token_pool.BurnMintTokenPool, error) { - var rmnAddress, routerAddress string - chainAddresses, err := addressBook.AddressesForChain(chain.Selector) - if err != nil { - return nil, nil, err - } - for address, v := range chainAddresses { - if deployment.NewTypeAndVersion(ARMProxy, deployment.Version1_0_0) == v { - rmnAddress = address - } - if deployment.NewTypeAndVersion(Router, deployment.Version1_2_0) == v { - routerAddress = address - } - if rmnAddress != "" && routerAddress != "" { - break - } - } - - tokenDecimals := uint8(18) - - tokenContract, err := deployment.DeployContract(lggr, chain, addressBook, - func(chain deployment.Chain) deployment.ContractDeploy[*burn_mint_erc677.BurnMintERC677] { - tokenAddress, tx, token, err2 := burn_mint_erc677.DeployBurnMintERC677( - deployer, - chain.Client, - tokenSymbol, - tokenSymbol, - tokenDecimals, - big.NewInt(0).Mul(big.NewInt(1e9), big.NewInt(1e18)), - ) - return deployment.ContractDeploy[*burn_mint_erc677.BurnMintERC677]{ - tokenAddress, token, tx, deployment.NewTypeAndVersion(BurnMintToken, deployment.Version1_0_0), err2, - } - }) - if err != nil { - lggr.Errorw("Failed to deploy Token ERC677", "err", err) - return nil, nil, err - } - - tx, err := tokenContract.Contract.GrantMintRole(deployer, deployer.From) - if err != nil { - return nil, nil, err - } - _, err = chain.Confirm(tx) - if err != nil { - return nil, nil, err - } - - tokenPool, err := deployment.DeployContract(lggr, chain, addressBook, - func(chain deployment.Chain) deployment.ContractDeploy[*burn_mint_token_pool.BurnMintTokenPool] { - tokenPoolAddress, tx, tokenPoolContract, err2 := burn_mint_token_pool.DeployBurnMintTokenPool( - deployer, - chain.Client, - tokenContract.Address, - tokenDecimals, - []common.Address{}, - common.HexToAddress(rmnAddress), - common.HexToAddress(routerAddress), - ) - return deployment.ContractDeploy[*burn_mint_token_pool.BurnMintTokenPool]{ - tokenPoolAddress, tokenPoolContract, tx, deployment.NewTypeAndVersion(BurnMintTokenPool, deployment.Version1_5_1), err2, - } - }) - if err != nil { - lggr.Errorw("Failed to deploy token pool", "err", err) - return nil, nil, err - } - - return tokenContract.Contract, tokenPool.Contract, nil -} - -type MintTokenInfo struct { - auth *bind.TransactOpts - sender *bind.TransactOpts - tokens []*burn_mint_erc677.BurnMintERC677 -} - -func NewMintTokenInfo(auth *bind.TransactOpts, tokens ...*burn_mint_erc677.BurnMintERC677) MintTokenInfo { - return MintTokenInfo{auth: auth, tokens: tokens} -} - -func NewMintTokenWithCustomSender(auth *bind.TransactOpts, sender *bind.TransactOpts, tokens ...*burn_mint_erc677.BurnMintERC677) MintTokenInfo { - return MintTokenInfo{auth: auth, sender: sender, tokens: tokens} -} - -// MintAndAllow mints tokens for deployers and allow router to spend them -func MintAndAllow( - t *testing.T, - e deployment.Environment, - state CCIPOnChainState, - tokenMap map[uint64][]MintTokenInfo, -) { - configurePoolGrp := errgroup.Group{} - tenCoins := new(big.Int).Mul(big.NewInt(1e18), big.NewInt(10)) - - for chain, mintTokenInfos := range tokenMap { - mintTokenInfos := mintTokenInfos - - configurePoolGrp.Go(func() error { - for _, mintTokenInfo := range mintTokenInfos { - sender := mintTokenInfo.sender - if sender == nil { - sender = e.Chains[chain].DeployerKey - } - - for _, token := range mintTokenInfo.tokens { - tx, err := token.Mint( - mintTokenInfo.auth, - sender.From, - new(big.Int).Mul(tenCoins, big.NewInt(10)), - ) - require.NoError(t, err) - _, err = e.Chains[chain].Confirm(tx) - require.NoError(t, err) - - tx, err = token.Approve(sender, state.Chains[chain].Router.Address(), tenCoins) - require.NoError(t, err) - _, err = e.Chains[chain].Confirm(tx) - require.NoError(t, err) - } - } - return nil - }) - } - - require.NoError(t, configurePoolGrp.Wait()) -} - -func Transfer( - ctx context.Context, - t *testing.T, - env deployment.Environment, - state CCIPOnChainState, - sourceChain, destChain uint64, - tokens []router.ClientEVMTokenAmount, - receiver common.Address, - data, extraArgs []byte, -) (*onramp.OnRampCCIPMessageSent, map[uint64]*uint64) { - startBlocks := make(map[uint64]*uint64) - - latesthdr, err := env.Chains[destChain].Client.HeaderByNumber(ctx, nil) - require.NoError(t, err) - block := latesthdr.Number.Uint64() - startBlocks[destChain] = &block - - msgSentEvent := TestSendRequest(t, env, state, sourceChain, destChain, false, router.ClientEVM2AnyMessage{ - Receiver: common.LeftPadBytes(receiver.Bytes(), 32), - Data: data, - TokenAmounts: tokens, - FeeToken: common.HexToAddress("0x0"), - ExtraArgs: extraArgs, - }) - return msgSentEvent, startBlocks -} - -type TestTransferRequest struct { - Name string - SourceChain, DestChain uint64 - Receiver common.Address - ExpectedStatus int - // optional - Tokens []router.ClientEVMTokenAmount - Data []byte - ExtraArgs []byte - ExpectedTokenBalances map[common.Address]*big.Int -} - -// TransferMultiple sends multiple CCIPMessages (represented as TestTransferRequest) sequentially. -// It verifies whether message is not reverted on the source and proper event is emitted by OnRamp. -// However, it doesn't wait for message to be committed or executed. Therefore, you can send multiple messages very fast, -// but you need to make sure they are committed/executed on your own (if that's the intention). -// It saves some time during test execution, because we let plugins batch instead of executing one by one -// If you want to wait for execution in a "batch" manner you will need to pass maps returned by TransferMultiple to -// either ConfirmMultipleCommits (for commit) or ConfirmExecWithSeqNrsForAll (for exec). Check example usage in the tests. -func TransferMultiple( - ctx context.Context, - t *testing.T, - env deployment.Environment, - state CCIPOnChainState, - requests []TestTransferRequest, -) ( - map[uint64]*uint64, - map[SourceDestPair]cciptypes.SeqNumRange, - map[SourceDestPair]map[uint64]int, - map[uint64]map[TokenReceiverIdentifier]*big.Int, -) { - startBlocks := make(map[uint64]*uint64) - expectedSeqNums := make(map[SourceDestPair]cciptypes.SeqNumRange) - expectedExecutionStates := make(map[SourceDestPair]map[uint64]int) - expectedTokenBalances := make(TokenBalanceAccumulator) - - for _, tt := range requests { - t.Run(tt.Name, func(t *testing.T) { - expectedTokenBalances.add(tt.DestChain, tt.Receiver, tt.ExpectedTokenBalances) - - pairId := SourceDestPair{ - SourceChainSelector: tt.SourceChain, - DestChainSelector: tt.DestChain, - } - - msg, blocks := Transfer( - ctx, t, env, state, tt.SourceChain, tt.DestChain, tt.Tokens, tt.Receiver, tt.Data, tt.ExtraArgs) - if _, ok := expectedExecutionStates[pairId]; !ok { - expectedExecutionStates[pairId] = make(map[uint64]int) - } - expectedExecutionStates[pairId][msg.SequenceNumber] = tt.ExpectedStatus - - if _, ok := startBlocks[tt.DestChain]; !ok { - startBlocks[tt.DestChain] = blocks[tt.DestChain] - } - - seqNr, ok := expectedSeqNums[pairId] - if ok { - expectedSeqNums[pairId] = cciptypes.NewSeqNumRange( - seqNr.Start(), cciptypes.SeqNum(msg.SequenceNumber), - ) - } else { - expectedSeqNums[pairId] = cciptypes.NewSeqNumRange( - cciptypes.SeqNum(msg.SequenceNumber), cciptypes.SeqNum(msg.SequenceNumber), - ) - } - }) - } - - return startBlocks, expectedSeqNums, expectedExecutionStates, expectedTokenBalances -} - -// TransferAndWaitForSuccess sends a message from sourceChain to destChain and waits for it to be executed -func TransferAndWaitForSuccess( - ctx context.Context, - t *testing.T, - env deployment.Environment, - state CCIPOnChainState, - sourceChain, destChain uint64, - tokens []router.ClientEVMTokenAmount, - receiver common.Address, - data []byte, - expectedStatus int, - extraArgs []byte, -) { - identifier := SourceDestPair{ - SourceChainSelector: sourceChain, - DestChainSelector: destChain, - } - - expectedSeqNum := make(map[SourceDestPair]uint64) - expectedSeqNumExec := make(map[SourceDestPair][]uint64) - - msgSentEvent, startBlocks := Transfer(ctx, t, env, state, sourceChain, destChain, tokens, receiver, data, extraArgs) - expectedSeqNum[identifier] = msgSentEvent.SequenceNumber - expectedSeqNumExec[identifier] = []uint64{msgSentEvent.SequenceNumber} - - // Wait for all commit reports to land. - ConfirmCommitForAllWithExpectedSeqNums(t, env, state, expectedSeqNum, startBlocks) - - // Wait for all exec reports to land - states := ConfirmExecWithSeqNrsForAll(t, env, state, expectedSeqNumExec, startBlocks) - require.Equal(t, expectedStatus, states[identifier][msgSentEvent.SequenceNumber]) -} - -// TokenBalanceAccumulator is a convenient accumulator to aggregate expected balances of different tokens -// used across the tests. You can iterate over your test cases and build the final "expected" balances for tokens (per chain, per sender) -// For instance, if your test runs multiple transfers for the same token, and you want to verify the balance of tokens at -// the end of the execution, you can simply use that struct for aggregating expected tokens -// Please also see WaitForTokenBalances to better understand how you can assert token balances -type TokenBalanceAccumulator map[uint64]map[TokenReceiverIdentifier]*big.Int - -func (t TokenBalanceAccumulator) add( - destChain uint64, - receiver common.Address, - expectedBalance map[common.Address]*big.Int) { - for token, balance := range expectedBalance { - tkIdentifier := TokenReceiverIdentifier{token, receiver} - - if _, ok := t[destChain]; !ok { - t[destChain] = make(map[TokenReceiverIdentifier]*big.Int) - } - actual, ok := t[destChain][tkIdentifier] - if !ok { - actual = big.NewInt(0) - } - t[destChain][tkIdentifier] = new(big.Int).Add(actual, balance) - } -} - -type TokenReceiverIdentifier struct { - token common.Address - receiver common.Address -} - -// WaitForTokenBalances waits for multiple ERC20 tokens to reach a particular balance -// It works in a batch manner, so you can pass and exhaustive list of different tokens (per senders and chains) -// and it would work concurrently for the balance to be met. Check WaitForTheTokenBalance to see how balance -// checking is made for a token/receiver pair -func WaitForTokenBalances( - ctx context.Context, - t *testing.T, - chains map[uint64]deployment.Chain, - expectedBalances map[uint64]map[TokenReceiverIdentifier]*big.Int, -) { - errGrp := &errgroup.Group{} - for chainID, tokens := range expectedBalances { - for id, balance := range tokens { - id := id - balance := balance - errGrp.Go(func() error { - WaitForTheTokenBalance(ctx, t, id.token, id.receiver, chains[chainID], balance) - return nil - }) - } - } - require.NoError(t, errGrp.Wait()) -} - -func WaitForTheTokenBalance( - ctx context.Context, - t *testing.T, - token common.Address, - receiver common.Address, - chain deployment.Chain, - expected *big.Int, -) { - tokenContract, err := burn_mint_erc677.NewBurnMintERC677(token, chain.Client) - require.NoError(t, err) - - require.Eventually(t, func() bool { - actualBalance, err := tokenContract.BalanceOf(&bind.CallOpts{Context: ctx}, receiver) - require.NoError(t, err) - - t.Log("Waiting for the token balance", - "expected", expected, - "actual", actualBalance, - "token", token, - "receiver", receiver, - ) - - return actualBalance.Cmp(expected) == 0 - }, tests.WaitTimeout(t), 100*time.Millisecond) -} - -func GetTokenBalance( - ctx context.Context, - t *testing.T, - token common.Address, - receiver common.Address, - chain deployment.Chain, -) *big.Int { - tokenContract, err := burn_mint_erc677.NewBurnMintERC677(token, chain.Client) - require.NoError(t, err) - - balance, err := tokenContract.BalanceOf(&bind.CallOpts{Context: ctx}, receiver) - require.NoError(t, err) - - t.Log("Getting token balance", - "actual", balance, - "token", token, - "receiver", receiver, - ) - - return balance -} - -func DefaultRouterMessage(receiverAddress common.Address) router.ClientEVM2AnyMessage { - return router.ClientEVM2AnyMessage{ - Receiver: common.LeftPadBytes(receiverAddress.Bytes(), 32), - Data: []byte("hello world"), - TokenAmounts: nil, - FeeToken: common.HexToAddress("0x0"), - ExtraArgs: nil, - } -} diff --git a/deployment/ccip/changeset/v1_5/cs_jobspec.go b/deployment/ccip/changeset/v1_5/cs_jobspec.go deleted file mode 100644 index bdb36d531f8..00000000000 --- a/deployment/ccip/changeset/v1_5/cs_jobspec.go +++ /dev/null @@ -1,149 +0,0 @@ -package v1_5 - -import ( - "fmt" - - "github.com/smartcontractkit/chainlink/deployment" - "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" - "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/config" - integrationtesthelpers "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/testhelpers/integration" -) - -type JobSpecsForLanesConfig struct { - Configs []JobSpecInput -} - -func (c JobSpecsForLanesConfig) Validate() error { - for _, cfg := range c.Configs { - if err := cfg.Validate(); err != nil { - return fmt.Errorf("invalid JobSpecInput: %w", err) - } - } - return nil -} - -type JobSpecInput struct { - SourceChainSelector uint64 - DestinationChainSelector uint64 - DestEVMChainID uint64 - DestinationStartBlock uint64 - TokenPricesUSDPipeline string - PriceGetterConfigJson string - USDCAttestationAPI string - USDCCfg *config.USDCConfig -} - -func (j JobSpecInput) Validate() error { - if err := deployment.IsValidChainSelector(j.SourceChainSelector); err != nil { - return fmt.Errorf("SourceChainSelector is invalid: %w", err) - } - if err := deployment.IsValidChainSelector(j.DestinationChainSelector); err != nil { - return fmt.Errorf("DestinationChainSelector is invalid: %w", err) - } - if j.TokenPricesUSDPipeline == "" && j.PriceGetterConfigJson == "" { - return fmt.Errorf("TokenPricesUSDPipeline or PriceGetterConfigJson is required") - } - if j.USDCCfg != nil { - if err := j.USDCCfg.ValidateUSDCConfig(); err != nil { - return fmt.Errorf("USDCCfg is invalid: %w", err) - } - if j.USDCAttestationAPI == "" { - return fmt.Errorf("USDCAttestationAPI is required") - } - } - return nil -} - -func JobSpecsForLanes(env deployment.Environment, c JobSpecsForLanesConfig) (deployment.ChangesetOutput, error) { - if err := c.Validate(); err != nil { - return deployment.ChangesetOutput{}, fmt.Errorf("invalid JobSpecsForLanesConfig: %w", err) - } - state, err := changeset.LoadOnchainState(env) - if err != nil { - return deployment.ChangesetOutput{}, err - } - nodesToJobSpecs, err := jobSpecsForLane(env, state, c) - if err != nil { - return deployment.ChangesetOutput{}, err - } - return deployment.ChangesetOutput{ - JobSpecs: nodesToJobSpecs, - }, nil -} - -func jobSpecsForLane( - env deployment.Environment, - state changeset.CCIPOnChainState, - lanesCfg JobSpecsForLanesConfig, -) (map[string][]string, error) { - nodes, err := deployment.NodeInfo(env.NodeIDs, env.Offchain) - if err != nil { - return nil, err - } - nodesToJobSpecs := make(map[string][]string) - for _, node := range nodes { - var specs []string - for _, cfg := range lanesCfg.Configs { - destChainState := state.Chains[cfg.DestinationChainSelector] - sourceChain := env.Chains[cfg.SourceChainSelector] - destChain := env.Chains[cfg.DestinationChainSelector] - - ccipJobParam := integrationtesthelpers.CCIPJobSpecParams{ - OffRamp: destChainState.EVM2EVMOffRamp[cfg.SourceChainSelector].Address(), - CommitStore: destChainState.CommitStore[cfg.SourceChainSelector].Address(), - SourceChainName: sourceChain.Name(), - DestChainName: destChain.Name(), - DestEvmChainId: cfg.DestEVMChainID, - TokenPricesUSDPipeline: cfg.TokenPricesUSDPipeline, - PriceGetterConfig: cfg.PriceGetterConfigJson, - DestStartBlock: cfg.DestinationStartBlock, - USDCAttestationAPI: cfg.USDCAttestationAPI, - USDCConfig: cfg.USDCCfg, - P2PV2Bootstrappers: nodes.BootstrapLocators(), - } - if !node.IsBootstrap { - ocrCfg, found := node.OCRConfigForChainSelector(cfg.DestinationChainSelector) - if !found { - return nil, fmt.Errorf("OCR config not found for chain %s", destChain.String()) - } - ocrKeyBundleID := ocrCfg.KeyBundleID - transmitterID := ocrCfg.TransmitAccount - commitSpec, err := ccipJobParam.CommitJobSpec() - if err != nil { - return nil, fmt.Errorf("failed to generate commit job spec for source %s and destination %s: %w", - sourceChain.String(), destChain.String(), err) - } - commitSpec.OCR2OracleSpec.OCRKeyBundleID.SetValid(ocrKeyBundleID) - commitSpec.OCR2OracleSpec.TransmitterID.SetValid(string(transmitterID)) - commitSpecStr, err := commitSpec.String() - if err != nil { - return nil, fmt.Errorf("failed to convert commit job spec to string for source %s and destination %s: %w", - sourceChain.String(), destChain.String(), err) - } - execSpec, err := ccipJobParam.ExecutionJobSpec() - if err != nil { - return nil, fmt.Errorf("failed to generate execution job spec for source %s and destination %s: %w", - sourceChain.String(), destChain.String(), err) - } - execSpec.OCR2OracleSpec.OCRKeyBundleID.SetValid(ocrKeyBundleID) - execSpec.OCR2OracleSpec.TransmitterID.SetValid(string(transmitterID)) - execSpecStr, err := execSpec.String() - if err != nil { - return nil, fmt.Errorf("failed to convert execution job spec to string for source %s and destination %s: %w", - sourceChain.String(), destChain.String(), err) - } - specs = append(specs, commitSpecStr, execSpecStr) - } else { - bootstrapSpec := ccipJobParam.BootstrapJob(destChainState.CommitStore[cfg.SourceChainSelector].Address().String()) - bootstrapSpecStr, err := bootstrapSpec.String() - if err != nil { - return nil, fmt.Errorf("failed to convert bootstrap job spec to string for source %s and destination %s: %w", - sourceChain.String(), destChain.String(), err) - } - specs = append(specs, bootstrapSpecStr) - } - } - nodesToJobSpecs[node.NodeID] = append(nodesToJobSpecs[node.NodeID], specs...) - } - return nodesToJobSpecs, nil -} diff --git a/deployment/ccip/changeset/v1_5/cs_lane_contracts.go b/deployment/ccip/changeset/v1_5/cs_lane_contracts.go deleted file mode 100644 index 2d6c8fcb5ed..00000000000 --- a/deployment/ccip/changeset/v1_5/cs_lane_contracts.go +++ /dev/null @@ -1,288 +0,0 @@ -package v1_5 - -import ( - "fmt" - - "github.com/ethereum/go-ethereum/common" - - "github.com/smartcontractkit/chainlink/deployment" - "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/commit_store" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/evm_2_evm_offramp" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/evm_2_evm_onramp" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/price_registry_1_2_0" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/router" -) - -var _ deployment.ChangeSet[DeployLanesConfig] = DeployLanes - -type DeployLanesConfig struct { - Configs []DeployLaneConfig -} - -func (c *DeployLanesConfig) Validate(e deployment.Environment, state changeset.CCIPOnChainState) error { - for _, cfg := range c.Configs { - if err := cfg.Validate(e, state); err != nil { - return err - } - } - return nil -} - -type DeployLaneConfig struct { - SourceChainSelector uint64 - DestinationChainSelector uint64 - - // onRamp specific configuration - OnRampStaticCfg evm_2_evm_onramp.EVM2EVMOnRampStaticConfig - OnRampDynamicCfg evm_2_evm_onramp.EVM2EVMOnRampDynamicConfig - OnRampFeeTokenArgs []evm_2_evm_onramp.EVM2EVMOnRampFeeTokenConfigArgs - OnRampTransferTokenCfgs []evm_2_evm_onramp.EVM2EVMOnRampTokenTransferFeeConfigArgs - OnRampNopsAndWeight []evm_2_evm_onramp.EVM2EVMOnRampNopAndWeight - OnRampRateLimiterCfg evm_2_evm_onramp.RateLimiterConfig - - // offRamp specific configuration - OffRampRateLimiterCfg evm_2_evm_offramp.RateLimiterConfig - - // Price Registry specific configuration - InitialTokenPrices []price_registry_1_2_0.InternalTokenPriceUpdate - GasPriceUpdates []price_registry_1_2_0.InternalGasPriceUpdate -} - -func (c *DeployLaneConfig) Validate(e deployment.Environment, state changeset.CCIPOnChainState) error { - if err := deployment.IsValidChainSelector(c.SourceChainSelector); err != nil { - return err - } - if err := deployment.IsValidChainSelector(c.DestinationChainSelector); err != nil { - return err - } - sourceChain, exists := e.Chains[c.SourceChainSelector] - if !exists { - return fmt.Errorf("source chain %d not found in environment", c.SourceChainSelector) - } - destChain, exists := e.Chains[c.DestinationChainSelector] - if !exists { - return fmt.Errorf("destination chain %d not found in environment", c.DestinationChainSelector) - } - sourceChainState, exists := state.Chains[c.SourceChainSelector] - if !exists { - return fmt.Errorf("source chain %d not found in state", c.SourceChainSelector) - } - destChainState, exists := state.Chains[c.DestinationChainSelector] - if !exists { - return fmt.Errorf("destination chain %d not found in state", c.DestinationChainSelector) - } - // check for existing chain contracts on both source and destination chains - if err := arePrerequisitesMet(sourceChainState, sourceChain); err != nil { - return err - } - if err := arePrerequisitesMet(destChainState, destChain); err != nil { - return err - } - // TODO: Add rest of the config validation - return nil -} - -func DeployLanes(env deployment.Environment, c DeployLanesConfig) (deployment.ChangesetOutput, error) { - state, err := changeset.LoadOnchainState(env) - if err != nil { - return deployment.ChangesetOutput{}, fmt.Errorf("failed to load CCIP onchain state: %w", err) - } - if err := c.Validate(env, state); err != nil { - return deployment.ChangesetOutput{}, fmt.Errorf("invalid DeployChainContractsConfig: %w", err) - } - newAddresses := deployment.NewMemoryAddressBook() - for _, cfg := range c.Configs { - if err := deployLane(env, state, newAddresses, cfg); err != nil { - return deployment.ChangesetOutput{ - AddressBook: newAddresses, - }, err - } - } - return deployment.ChangesetOutput{ - AddressBook: newAddresses, - }, nil -} - -func deployLane(e deployment.Environment, state changeset.CCIPOnChainState, ab deployment.AddressBook, cfg DeployLaneConfig) error { - // update prices on the source price registry - sourceChainState := state.Chains[cfg.SourceChainSelector] - destChainState := state.Chains[cfg.DestinationChainSelector] - sourceChain := e.Chains[cfg.SourceChainSelector] - destChain := e.Chains[cfg.DestinationChainSelector] - sourcePriceReg := sourceChainState.PriceRegistry - tx, err := sourcePriceReg.UpdatePrices(sourceChain.DeployerKey, price_registry_1_2_0.InternalPriceUpdates{ - TokenPriceUpdates: cfg.InitialTokenPrices, - GasPriceUpdates: cfg.GasPriceUpdates, - }) - if err != nil { - return err - } - _, err = sourceChain.Confirm(tx) - if err != nil { - return fmt.Errorf("failed to confirm price update tx for chain %s: %w", sourceChain.String(), deployment.MaybeDataErr(err)) - } - // ================================================================ - // │ Deploy Lane │ - // ================================================================ - // Deploy onRamp on source chain - onRamp, onRampExists := sourceChainState.EVM2EVMOnRamp[cfg.DestinationChainSelector] - if !onRampExists { - onRampC, err := deployment.DeployContract(e.Logger, sourceChain, ab, - func(chain deployment.Chain) deployment.ContractDeploy[*evm_2_evm_onramp.EVM2EVMOnRamp] { - onRampAddress, tx2, onRampC, err2 := evm_2_evm_onramp.DeployEVM2EVMOnRamp( - sourceChain.DeployerKey, - sourceChain.Client, - cfg.OnRampStaticCfg, - cfg.OnRampDynamicCfg, - cfg.OnRampRateLimiterCfg, - cfg.OnRampFeeTokenArgs, - cfg.OnRampTransferTokenCfgs, - cfg.OnRampNopsAndWeight, - ) - return deployment.ContractDeploy[*evm_2_evm_onramp.EVM2EVMOnRamp]{ - Address: onRampAddress, Contract: onRampC, Tx: tx2, - Tv: deployment.NewTypeAndVersion(changeset.OnRamp, deployment.Version1_5_0), Err: err2, - } - }) - if err != nil { - e.Logger.Errorw("Failed to deploy EVM2EVMOnRamp", "chain", sourceChain.String(), "err", err) - return err - } - onRamp = onRampC.Contract - } else { - e.Logger.Infow("EVM2EVMOnRamp already exists", - "source chain", sourceChain.String(), "destination chain", destChain.String(), - "address", onRamp.Address().String()) - } - - // Deploy commit store on source chain - commitStore, commitStoreExists := destChainState.CommitStore[cfg.SourceChainSelector] - if !commitStoreExists { - commitStoreC, err := deployment.DeployContract(e.Logger, destChain, ab, - func(chain deployment.Chain) deployment.ContractDeploy[*commit_store.CommitStore] { - commitStoreAddress, tx2, commitStoreC, err2 := commit_store.DeployCommitStore( - destChain.DeployerKey, - destChain.Client, - commit_store.CommitStoreStaticConfig{ - ChainSelector: destChain.Selector, - SourceChainSelector: sourceChain.Selector, - OnRamp: onRamp.Address(), - RmnProxy: destChainState.RMNProxy.Address(), - }, - ) - return deployment.ContractDeploy[*commit_store.CommitStore]{ - Address: commitStoreAddress, Contract: commitStoreC, Tx: tx2, - Tv: deployment.NewTypeAndVersion(changeset.CommitStore, deployment.Version1_5_0), Err: err2, - } - }) - if err != nil { - e.Logger.Errorw("Failed to deploy CommitStore", "chain", sourceChain.String(), "err", err) - return err - } - commitStore = commitStoreC.Contract - } else { - e.Logger.Infow("CommitStore already exists", - "source chain", sourceChain.String(), "destination chain", destChain.String(), - "address", commitStore.Address().String()) - } - - // Deploy offRamp on destination chain - offRamp, offRampExists := destChainState.EVM2EVMOffRamp[cfg.SourceChainSelector] - if !offRampExists { - offRampC, err := deployment.DeployContract(e.Logger, destChain, ab, - func(chain deployment.Chain) deployment.ContractDeploy[*evm_2_evm_offramp.EVM2EVMOffRamp] { - offRampAddress, tx2, offRampC, err2 := evm_2_evm_offramp.DeployEVM2EVMOffRamp( - destChain.DeployerKey, - destChain.Client, - evm_2_evm_offramp.EVM2EVMOffRampStaticConfig{ - CommitStore: commitStore.Address(), - ChainSelector: destChain.Selector, - SourceChainSelector: sourceChain.Selector, - OnRamp: onRamp.Address(), - PrevOffRamp: common.HexToAddress(""), - RmnProxy: destChainState.RMNProxy.Address(), // RMN, formerly ARM - TokenAdminRegistry: destChainState.TokenAdminRegistry.Address(), - }, - cfg.OffRampRateLimiterCfg, - ) - return deployment.ContractDeploy[*evm_2_evm_offramp.EVM2EVMOffRamp]{ - Address: offRampAddress, Contract: offRampC, Tx: tx2, - Tv: deployment.NewTypeAndVersion(changeset.OffRamp, deployment.Version1_5_0), Err: err2, - } - }) - if err != nil { - e.Logger.Errorw("Failed to deploy EVM2EVMOffRamp", "chain", sourceChain.String(), "err", err) - return err - } - offRamp = offRampC.Contract - } else { - e.Logger.Infow("EVM2EVMOffRamp already exists", - "source chain", sourceChain.String(), "destination chain", destChain.String(), - "address", offRamp.Address().String()) - } - - // Apply Router updates - tx, err = sourceChainState.Router.ApplyRampUpdates(sourceChain.DeployerKey, - []router.RouterOnRamp{{DestChainSelector: destChain.Selector, OnRamp: onRamp.Address()}}, nil, nil) - if err != nil { - return fmt.Errorf("failed to apply router updates for source chain %s: %w", sourceChain.String(), deployment.MaybeDataErr(err)) - } - _, err = sourceChain.Confirm(tx) - if err != nil { - return fmt.Errorf("failed to confirm router updates tx %s for source chain %s: %w", tx.Hash().String(), sourceChain.String(), deployment.MaybeDataErr(err)) - } - - tx, err = destChainState.Router.ApplyRampUpdates(destChain.DeployerKey, - nil, - nil, - []router.RouterOffRamp{{SourceChainSelector: sourceChain.Selector, OffRamp: offRamp.Address()}}, - ) - if err != nil { - return fmt.Errorf("failed to apply router updates for destination chain %s: %w", destChain.String(), deployment.MaybeDataErr(err)) - } - _, err = destChain.Confirm(tx) - if err != nil { - return fmt.Errorf("failed to confirm router updates tx %s for destination chain %s: %w", tx.Hash().String(), destChain.String(), deployment.MaybeDataErr(err)) - } - - // price registry updates - _, err = destChainState.PriceRegistry.ApplyPriceUpdatersUpdates( - destChain.DeployerKey, - []common.Address{commitStore.Address()}, - []common.Address{}, - ) - if err != nil { - return fmt.Errorf("failed to apply price registry updates for destination chain %s: %w", destChain.String(), deployment.MaybeDataErr(err)) - } - _, err = destChain.Confirm(tx) - if err != nil { - return fmt.Errorf("failed to confirm price registry updates tx %s for destination chain %s: %w", tx.Hash().String(), destChain.String(), deployment.MaybeDataErr(err)) - } - return nil -} - -func arePrerequisitesMet(chainState changeset.CCIPChainState, chain deployment.Chain) error { - if chainState.Router == nil { - return fmt.Errorf("router not found for chain %s", chain.String()) - } - if chainState.PriceRegistry == nil { - return fmt.Errorf("price registry not found for chain %s", chain.String()) - } - if chainState.RMN == nil && chainState.MockRMN == nil { - return fmt.Errorf("neither RMN nor mockRMN found for chain %s", chain.String()) - } - if chainState.Weth9 == nil { - return fmt.Errorf("WETH9 not found for chain %s", chain.String()) - } - if chainState.LinkToken == nil { - return fmt.Errorf("LINK token not found for chain %s", chain.String()) - } - if chainState.TokenAdminRegistry == nil { - return fmt.Errorf("token admin registry not found for chain %s", chain.String()) - } - if chainState.RMNProxy == nil { - return fmt.Errorf("RMNProxy not found for chain %s", chain.String()) - } - return nil -} diff --git a/deployment/ccip/changeset/v1_5/cs_ocr2_config.go b/deployment/ccip/changeset/v1_5/cs_ocr2_config.go deleted file mode 100644 index 497bcb53ad8..00000000000 --- a/deployment/ccip/changeset/v1_5/cs_ocr2_config.go +++ /dev/null @@ -1,329 +0,0 @@ -package v1_5 - -import ( - "fmt" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/common/hexutil" - "github.com/pkg/errors" - "github.com/smartcontractkit/libocr/offchainreporting2plus/confighelper" - - "github.com/smartcontractkit/chainlink-common/pkg/config" - - "github.com/smartcontractkit/chainlink/deployment" - "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/evm_2_evm_offramp" - "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/abihelpers" - "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/testhelpers" -) - -type FinalOCR2Config struct { - Signers []common.Address - Transmitters []common.Address - F uint8 - OnchainConfig []byte - OffchainConfigVersion uint64 - OffchainConfig []byte -} - -type CommitOCR2ConfigParams struct { - DestinationChainSelector uint64 - SourceChainSelector uint64 - OCR2ConfigParams confighelper.PublicConfig - GasPriceHeartBeat config.Duration - DAGasPriceDeviationPPB uint32 - ExecGasPriceDeviationPPB uint32 - TokenPriceHeartBeat config.Duration - TokenPriceDeviationPPB uint32 - InflightCacheExpiry config.Duration - PriceReportingDisabled bool -} - -func (c *CommitOCR2ConfigParams) PopulateOffChainAndOnChainCfg(priceReg common.Address) error { - var err error - c.OCR2ConfigParams.ReportingPluginConfig, err = testhelpers.NewCommitOffchainConfig( - c.GasPriceHeartBeat, - c.DAGasPriceDeviationPPB, - c.ExecGasPriceDeviationPPB, - c.TokenPriceHeartBeat, - c.TokenPriceDeviationPPB, - c.InflightCacheExpiry, - c.PriceReportingDisabled, - ).Encode() - if err != nil { - return errors.Wrapf(err, "failed to encode offchain config for source chain %d and destination chain %d", - c.SourceChainSelector, c.DestinationChainSelector) - } - c.OCR2ConfigParams.OnchainConfig, err = abihelpers.EncodeAbiStruct(testhelpers.NewCommitOnchainConfig(priceReg)) - if err != nil { - return fmt.Errorf("failed to encode onchain config for source chain %d and destination chain %d: %w", - c.SourceChainSelector, c.DestinationChainSelector, err) - } - return nil -} - -func (c *CommitOCR2ConfigParams) Validate(state changeset.CCIPOnChainState) error { - if err := deployment.IsValidChainSelector(c.DestinationChainSelector); err != nil { - return fmt.Errorf("invalid DestinationChainSelector: %w", err) - } - if err := deployment.IsValidChainSelector(c.SourceChainSelector); err != nil { - return fmt.Errorf("invalid SourceChainSelector: %w", err) - } - - chain, exists := state.Chains[c.DestinationChainSelector] - if !exists { - return fmt.Errorf("chain %d does not exist in state", c.DestinationChainSelector) - } - if chain.CommitStore == nil { - return fmt.Errorf("chain %d does not have a commit store", c.DestinationChainSelector) - } - _, exists = chain.CommitStore[c.SourceChainSelector] - if !exists { - return fmt.Errorf("chain %d does not have a commit store for source chain %d", c.DestinationChainSelector, c.SourceChainSelector) - } - if chain.PriceRegistry == nil { - return fmt.Errorf("chain %d does not have a price registry", c.DestinationChainSelector) - } - return nil -} - -type ExecuteOCR2ConfigParams struct { - DestinationChainSelector uint64 - SourceChainSelector uint64 - DestOptimisticConfirmations uint32 - BatchGasLimit uint32 - RelativeBoostPerWaitHour float64 - InflightCacheExpiry config.Duration - RootSnoozeTime config.Duration - BatchingStrategyID uint32 - MessageVisibilityInterval config.Duration - ExecOnchainConfig evm_2_evm_offramp.EVM2EVMOffRampDynamicConfig - OCR2ConfigParams confighelper.PublicConfig -} - -func (e *ExecuteOCR2ConfigParams) PopulateOffChainAndOnChainCfg(router, priceReg common.Address) error { - var err error - e.OCR2ConfigParams.ReportingPluginConfig, err = testhelpers.NewExecOffchainConfig( - e.DestOptimisticConfirmations, - e.BatchGasLimit, - e.RelativeBoostPerWaitHour, - e.InflightCacheExpiry, - e.RootSnoozeTime, - e.BatchingStrategyID, - ).Encode() - if err != nil { - return fmt.Errorf("failed to encode offchain config for exec plugin, source chain %d dest chain %d :%w", - e.SourceChainSelector, e.DestinationChainSelector, err) - } - e.OCR2ConfigParams.OnchainConfig, err = abihelpers.EncodeAbiStruct(testhelpers.NewExecOnchainConfig( - e.ExecOnchainConfig.PermissionLessExecutionThresholdSeconds, - router, - priceReg, - e.ExecOnchainConfig.MaxNumberOfTokensPerMsg, - e.ExecOnchainConfig.MaxDataBytes, - )) - if err != nil { - return fmt.Errorf("failed to encode onchain config for exec plugin, source chain %d dest chain %d :%w", - e.SourceChainSelector, e.DestinationChainSelector, err) - } - return nil -} - -func (e *ExecuteOCR2ConfigParams) Validate(state changeset.CCIPOnChainState) error { - if err := deployment.IsValidChainSelector(e.SourceChainSelector); err != nil { - return fmt.Errorf("invalid SourceChainSelector: %w", err) - } - if err := deployment.IsValidChainSelector(e.DestinationChainSelector); err != nil { - return fmt.Errorf("invalid DestinationChainSelector: %w", err) - } - chain, exists := state.Chains[e.DestinationChainSelector] - if !exists { - return fmt.Errorf("chain %d does not exist in state", e.DestinationChainSelector) - } - if chain.EVM2EVMOffRamp == nil { - return fmt.Errorf("chain %d does not have an EVM2EVMOffRamp", e.DestinationChainSelector) - } - _, exists = chain.EVM2EVMOffRamp[e.SourceChainSelector] - if !exists { - return fmt.Errorf("chain %d does not have an EVM2EVMOffRamp for source chain %d", e.DestinationChainSelector, e.SourceChainSelector) - } - if chain.PriceRegistry == nil { - return fmt.Errorf("chain %d does not have a price registry", e.DestinationChainSelector) - } - if chain.Router == nil { - return fmt.Errorf("chain %d does not have a router", e.DestinationChainSelector) - } - return nil -} - -type OCR2Config struct { - CommitConfigs []CommitOCR2ConfigParams - ExecConfigs []ExecuteOCR2ConfigParams -} - -func (o OCR2Config) Validate(state changeset.CCIPOnChainState) error { - for _, c := range o.CommitConfigs { - if err := c.Validate(state); err != nil { - return err - } - } - for _, e := range o.ExecConfigs { - if err := e.Validate(state); err != nil { - return err - } - } - return nil -} - -// SetOCR2ConfigForTest sets the OCR2 config on the chain for commit and offramp -// This is currently not suitable for prod environments it's only for testing -func SetOCR2ConfigForTest(env deployment.Environment, c OCR2Config) (deployment.ChangesetOutput, error) { - state, err := changeset.LoadOnchainState(env) - if err != nil { - return deployment.ChangesetOutput{}, fmt.Errorf("failed to load CCIP onchain state: %w", err) - } - if err := c.Validate(state); err != nil { - return deployment.ChangesetOutput{}, fmt.Errorf("invalid OCR2 config: %w", err) - } - for _, commit := range c.CommitConfigs { - if err := commit.PopulateOffChainAndOnChainCfg(state.Chains[commit.DestinationChainSelector].PriceRegistry.Address()); err != nil { - return deployment.ChangesetOutput{}, fmt.Errorf("failed to populate offchain and onchain config for commit: %w", err) - } - finalCfg, err := deriveOCR2Config(env, commit.DestinationChainSelector, commit.OCR2ConfigParams) - if err != nil { - return deployment.ChangesetOutput{}, fmt.Errorf("failed to derive OCR2 config for commit: %w", err) - } - commitStore := state.Chains[commit.DestinationChainSelector].CommitStore[commit.SourceChainSelector] - chain := env.Chains[commit.DestinationChainSelector] - tx, err := commitStore.SetOCR2Config( - chain.DeployerKey, - finalCfg.Signers, - finalCfg.Transmitters, - finalCfg.F, - finalCfg.OnchainConfig, - finalCfg.OffchainConfigVersion, - finalCfg.OffchainConfig, - ) - if err != nil { - return deployment.ChangesetOutput{}, fmt.Errorf("failed to set OCR2 config for commit store %s on chain %s: %w", - commitStore.Address().String(), chain.String(), deployment.MaybeDataErr(err)) - } - _, err = chain.Confirm(tx) - if err != nil { - return deployment.ChangesetOutput{}, fmt.Errorf("failed to confirm OCR2 for commit store %s config on chain %s: %w", - commitStore.Address().String(), chain.String(), err) - } - } - for _, exec := range c.ExecConfigs { - if err := exec.PopulateOffChainAndOnChainCfg( - state.Chains[exec.DestinationChainSelector].Router.Address(), - state.Chains[exec.DestinationChainSelector].PriceRegistry.Address()); err != nil { - return deployment.ChangesetOutput{}, fmt.Errorf("failed to populate offchain and onchain config for offramp: %w", err) - } - finalCfg, err := deriveOCR2Config(env, exec.DestinationChainSelector, exec.OCR2ConfigParams) - if err != nil { - return deployment.ChangesetOutput{}, fmt.Errorf("failed to derive OCR2 config for offramp: %w", err) - } - offRamp := state.Chains[exec.DestinationChainSelector].EVM2EVMOffRamp[exec.SourceChainSelector] - chain := env.Chains[exec.DestinationChainSelector] - tx, err := offRamp.SetOCR2Config( - chain.DeployerKey, - finalCfg.Signers, - finalCfg.Transmitters, - finalCfg.F, - finalCfg.OnchainConfig, - finalCfg.OffchainConfigVersion, - finalCfg.OffchainConfig, - ) - if err != nil { - return deployment.ChangesetOutput{}, fmt.Errorf("failed to set OCR2 config for offramp %s on chain %s: %w", - offRamp.Address().String(), chain.String(), err) - } - _, err = chain.Confirm(tx) - if err != nil { - return deployment.ChangesetOutput{}, fmt.Errorf("failed to confirm OCR2 for offramp %s config on chain %s: %w", - offRamp.Address().String(), chain.String(), err) - } - } - return deployment.ChangesetOutput{}, nil -} - -func deriveOCR2Config( - env deployment.Environment, - chainSel uint64, - ocrParams confighelper.PublicConfig, -) (FinalOCR2Config, error) { - nodeInfo, err := deployment.NodeInfo(env.NodeIDs, env.Offchain) - if err != nil { - return FinalOCR2Config{}, fmt.Errorf("failed to get node info: %w", err) - } - nodes := nodeInfo.NonBootstraps() - // Get OCR3 Config from helper - var schedule []int - var oracles []confighelper.OracleIdentityExtra - for _, node := range nodes { - schedule = append(schedule, 1) - cfg, exists := node.OCRConfigForChainSelector(chainSel) - if !exists { - return FinalOCR2Config{}, fmt.Errorf("no OCR config for chain %d", chainSel) - } - oracles = append(oracles, confighelper.OracleIdentityExtra{ - OracleIdentity: confighelper.OracleIdentity{ - OnchainPublicKey: cfg.OnchainPublicKey, - TransmitAccount: cfg.TransmitAccount, - OffchainPublicKey: cfg.OffchainPublicKey, - PeerID: cfg.PeerID.Raw(), - }, - ConfigEncryptionPublicKey: cfg.ConfigEncryptionPublicKey, - }) - } - - signers, transmitters, threshold, onchainConfig, offchainConfigVersion, offchainConfig, err := confighelper.ContractSetConfigArgsForTests( - ocrParams.DeltaProgress, - ocrParams.DeltaResend, - ocrParams.DeltaRound, - ocrParams.DeltaGrace, - ocrParams.DeltaStage, - ocrParams.RMax, - schedule, - oracles, - ocrParams.ReportingPluginConfig, - nil, - ocrParams.MaxDurationQuery, - ocrParams.MaxDurationObservation, - ocrParams.MaxDurationReport, - ocrParams.MaxDurationShouldAcceptFinalizedReport, - ocrParams.MaxDurationShouldTransmitAcceptedReport, - int(nodes.DefaultF()), - ocrParams.OnchainConfig, - ) - if err != nil { - return FinalOCR2Config{}, fmt.Errorf("failed to derive OCR2 config: %w", err) - } - var signersAddresses []common.Address - for _, signer := range signers { - if len(signer) != 20 { - return FinalOCR2Config{}, fmt.Errorf("address is not 20 bytes %s", signer) - } - signersAddresses = append(signersAddresses, common.BytesToAddress(signer)) - } - var transmittersAddresses []common.Address - for _, transmitter := range transmitters { - bytes, err := hexutil.Decode(string(transmitter)) - if err != nil { - return FinalOCR2Config{}, errors.Wrap(err, fmt.Sprintf("given address is not valid %s", transmitter)) - } - if len(bytes) != 20 { - return FinalOCR2Config{}, errors.Errorf("address is not 20 bytes %s", transmitter) - } - transmittersAddresses = append(transmittersAddresses, common.BytesToAddress(bytes)) - } - return FinalOCR2Config{ - Signers: signersAddresses, - Transmitters: transmittersAddresses, - F: threshold, - OnchainConfig: onchainConfig, - OffchainConfigVersion: offchainConfigVersion, - OffchainConfig: offchainConfig, - }, nil -} diff --git a/deployment/ccip/changeset/v1_5/e2e_test.go b/deployment/ccip/changeset/v1_5/e2e_test.go deleted file mode 100644 index 11bb566c641..00000000000 --- a/deployment/ccip/changeset/v1_5/e2e_test.go +++ /dev/null @@ -1,56 +0,0 @@ -package v1_5 - -import ( - "context" - "testing" - - "github.com/ethereum/go-ethereum/common" - chainselectors "github.com/smartcontractkit/chain-selectors" - "github.com/stretchr/testify/require" - - "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/router" -) - -// This test only works if the destination chain id is 1337 -// Otherwise it shows error for offchain and onchain config digest mismatch -func TestE2ELegacy(t *testing.T) { - e := changeset.NewMemoryEnvironment( - t, - changeset.WithLegacyDeployment(), - changeset.WithChains(3), - changeset.WithChainIds([]uint64{chainselectors.GETH_TESTNET.EvmChainID})) - state, err := changeset.LoadOnchainState(e.Env) - require.NoError(t, err) - allChains := e.Env.AllChainSelectorsExcluding([]uint64{chainselectors.GETH_TESTNET.Selector}) - require.Contains(t, e.Env.AllChainSelectors(), chainselectors.GETH_TESTNET.Selector) - require.Len(t, allChains, 2) - src, dest := allChains[1], chainselectors.GETH_TESTNET.Selector - srcChain := e.Env.Chains[src] - destChain := e.Env.Chains[dest] - pairs := []changeset.SourceDestPair{ - {SourceChainSelector: src, DestChainSelector: dest}, - } - e.Env = AddLanes(t, e.Env, state, pairs) - // reload state after adding lanes - state, err = changeset.LoadOnchainState(e.Env) - require.NoError(t, err) - sentEvent, err := SendRequest(t, e.Env, state, - changeset.WithSourceChain(src), - changeset.WithDestChain(dest), - changeset.WithTestRouter(false), - changeset.WithEvm2AnyMessage(router.ClientEVM2AnyMessage{ - Receiver: common.LeftPadBytes(state.Chains[dest].Receiver.Address().Bytes(), 32), - Data: []byte("hello"), - TokenAmounts: nil, - FeeToken: common.HexToAddress("0x0"), - ExtraArgs: nil, - }), - ) - require.NoError(t, err) - require.NotNil(t, sentEvent) - destStartBlock, err := destChain.Client.HeaderByNumber(context.Background(), nil) - require.NoError(t, err) - WaitForCommit(t, srcChain, destChain, state.Chains[dest].CommitStore[src], sentEvent.Message.SequenceNumber) - WaitForExecute(t, srcChain, destChain, state.Chains[dest].EVM2EVMOffRamp[src], []uint64{sentEvent.Message.SequenceNumber}, destStartBlock.Number.Uint64()) -} diff --git a/deployment/ccip/changeset/v1_5/test_helpers.go b/deployment/ccip/changeset/v1_5/test_helpers.go deleted file mode 100644 index e1a03539a77..00000000000 --- a/deployment/ccip/changeset/v1_5/test_helpers.go +++ /dev/null @@ -1,384 +0,0 @@ -package v1_5 - -import ( - "context" - "fmt" - "math/big" - "net/http" - "net/http/httptest" - "strconv" - "testing" - "time" - - "github.com/ethereum/go-ethereum/accounts/abi/bind" - "github.com/ethereum/go-ethereum/common" - chain_selectors "github.com/smartcontractkit/chain-selectors" - "github.com/smartcontractkit/libocr/offchainreporting2plus/confighelper" - "github.com/stretchr/testify/require" - - "github.com/smartcontractkit/chainlink-common/pkg/config" - cciptypes "github.com/smartcontractkit/chainlink-common/pkg/types/ccip" - - "github.com/smartcontractkit/chainlink/deployment" - "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" - commonchangeset "github.com/smartcontractkit/chainlink/deployment/common/changeset" - "github.com/smartcontractkit/chainlink/deployment/environment/memory" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/commit_store" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/evm_2_evm_offramp" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/evm_2_evm_onramp" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/price_registry_1_2_0" - "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/testhelpers" -) - -func AddLanes(t *testing.T, e deployment.Environment, state changeset.CCIPOnChainState, pairs []changeset.SourceDestPair) deployment.Environment { - addLanesCfg, commitOCR2Configs, execOCR2Configs, jobspecs := LaneConfigsForChains(t, e, state, pairs) - var err error - e, err = commonchangeset.ApplyChangesets(t, e, nil, []commonchangeset.ChangesetApplication{ - { - Changeset: commonchangeset.WrapChangeSet(DeployLanes), - Config: DeployLanesConfig{ - Configs: addLanesCfg, - }, - }, - { - Changeset: commonchangeset.WrapChangeSet(SetOCR2ConfigForTest), - Config: OCR2Config{ - CommitConfigs: commitOCR2Configs, - ExecConfigs: execOCR2Configs, - }, - }, - { - Changeset: commonchangeset.WrapChangeSet(JobSpecsForLanes), - Config: JobSpecsForLanesConfig{ - Configs: jobspecs, - }, - }, - }) - require.NoError(t, err) - return e -} - -func LaneConfigsForChains(t *testing.T, env deployment.Environment, state changeset.CCIPOnChainState, pairs []changeset.SourceDestPair) ( - []DeployLaneConfig, - []CommitOCR2ConfigParams, - []ExecuteOCR2ConfigParams, - []JobSpecInput, -) { - var addLanesCfg []DeployLaneConfig - var commitOCR2Configs []CommitOCR2ConfigParams - var execOCR2Configs []ExecuteOCR2ConfigParams - var jobSpecs []JobSpecInput - for _, pair := range pairs { - dest := pair.DestChainSelector - src := pair.SourceChainSelector - sourceChainState := state.Chains[src] - destChainState := state.Chains[dest] - require.NotNil(t, sourceChainState.LinkToken) - require.NotNil(t, sourceChainState.RMNProxy) - require.NotNil(t, sourceChainState.TokenAdminRegistry) - require.NotNil(t, sourceChainState.Router) - require.NotNil(t, sourceChainState.PriceRegistry) - require.NotNil(t, sourceChainState.Weth9) - require.NotNil(t, destChainState.LinkToken) - require.NotNil(t, destChainState.RMNProxy) - require.NotNil(t, destChainState.TokenAdminRegistry) - tokenPrice, _, _ := CreatePricesPipeline(t, state, src, dest) - block, err := env.Chains[dest].Client.HeaderByNumber(context.Background(), nil) - require.NoError(t, err) - destEVMChainIdStr, err := chain_selectors.GetChainIDFromSelector(dest) - require.NoError(t, err) - destEVMChainId, err := strconv.ParseUint(destEVMChainIdStr, 10, 64) - require.NoError(t, err) - jobSpecs = append(jobSpecs, JobSpecInput{ - SourceChainSelector: src, - DestinationChainSelector: dest, - DestEVMChainID: destEVMChainId, - TokenPricesUSDPipeline: tokenPrice, - DestinationStartBlock: block.Number.Uint64(), - }) - addLanesCfg = append(addLanesCfg, DeployLaneConfig{ - SourceChainSelector: src, - DestinationChainSelector: dest, - OnRampStaticCfg: evm_2_evm_onramp.EVM2EVMOnRampStaticConfig{ - LinkToken: sourceChainState.LinkToken.Address(), - ChainSelector: src, - DestChainSelector: dest, - DefaultTxGasLimit: 200_000, - MaxNopFeesJuels: big.NewInt(0).Mul(big.NewInt(100_000_000), big.NewInt(1e18)), - PrevOnRamp: common.Address{}, - RmnProxy: sourceChainState.RMNProxy.Address(), - TokenAdminRegistry: sourceChainState.TokenAdminRegistry.Address(), - }, - OnRampDynamicCfg: evm_2_evm_onramp.EVM2EVMOnRampDynamicConfig{ - Router: sourceChainState.Router.Address(), - MaxNumberOfTokensPerMsg: 5, - DestGasOverhead: 350_000, - DestGasPerPayloadByte: 16, - DestDataAvailabilityOverheadGas: 33_596, - DestGasPerDataAvailabilityByte: 16, - DestDataAvailabilityMultiplierBps: 6840, - PriceRegistry: sourceChainState.PriceRegistry.Address(), - MaxDataBytes: 1e5, - MaxPerMsgGasLimit: 4_000_000, - DefaultTokenFeeUSDCents: 50, - DefaultTokenDestGasOverhead: 125_000, - }, - OnRampFeeTokenArgs: []evm_2_evm_onramp.EVM2EVMOnRampFeeTokenConfigArgs{ - { - Token: sourceChainState.LinkToken.Address(), - NetworkFeeUSDCents: 1_00, - GasMultiplierWeiPerEth: 1e18, - PremiumMultiplierWeiPerEth: 9e17, - Enabled: true, - }, - { - Token: sourceChainState.Weth9.Address(), - NetworkFeeUSDCents: 1_00, - GasMultiplierWeiPerEth: 1e18, - PremiumMultiplierWeiPerEth: 1e18, - Enabled: true, - }, - }, - OnRampTransferTokenCfgs: []evm_2_evm_onramp.EVM2EVMOnRampTokenTransferFeeConfigArgs{ - { - Token: sourceChainState.LinkToken.Address(), - MinFeeUSDCents: 50, // $0.5 - MaxFeeUSDCents: 1_000_000_00, // $ 1 million - DeciBps: 5_0, // 5 bps - DestGasOverhead: 350_000, - DestBytesOverhead: 32, - AggregateRateLimitEnabled: true, - }, - }, - OnRampNopsAndWeight: []evm_2_evm_onramp.EVM2EVMOnRampNopAndWeight{}, - OnRampRateLimiterCfg: evm_2_evm_onramp.RateLimiterConfig{ - IsEnabled: true, - Capacity: testhelpers.LinkUSDValue(100), - Rate: testhelpers.LinkUSDValue(1), - }, - OffRampRateLimiterCfg: evm_2_evm_offramp.RateLimiterConfig{ - IsEnabled: true, - Capacity: testhelpers.LinkUSDValue(100), - Rate: testhelpers.LinkUSDValue(1), - }, - InitialTokenPrices: []price_registry_1_2_0.InternalTokenPriceUpdate{ - { - SourceToken: sourceChainState.LinkToken.Address(), - UsdPerToken: new(big.Int).Mul(big.NewInt(1e18), big.NewInt(20)), - }, - { - SourceToken: sourceChainState.Weth9.Address(), - UsdPerToken: new(big.Int).Mul(big.NewInt(1e18), big.NewInt(2000)), - }, - }, - GasPriceUpdates: []price_registry_1_2_0.InternalGasPriceUpdate{ - { - DestChainSelector: dest, - UsdPerUnitGas: big.NewInt(20000e9), - }, - }, - }) - commitOCR2Configs = append(commitOCR2Configs, CommitOCR2ConfigParams{ - SourceChainSelector: src, - DestinationChainSelector: dest, - OCR2ConfigParams: DefaultOCRParams(), - GasPriceHeartBeat: *config.MustNewDuration(10 * time.Second), - DAGasPriceDeviationPPB: 1, - ExecGasPriceDeviationPPB: 1, - TokenPriceHeartBeat: *config.MustNewDuration(10 * time.Second), - TokenPriceDeviationPPB: 1, - InflightCacheExpiry: *config.MustNewDuration(5 * time.Second), - PriceReportingDisabled: false, - }) - execOCR2Configs = append(execOCR2Configs, ExecuteOCR2ConfigParams{ - DestinationChainSelector: dest, - SourceChainSelector: src, - DestOptimisticConfirmations: 1, - BatchGasLimit: 5_000_000, - RelativeBoostPerWaitHour: 0.07, - InflightCacheExpiry: *config.MustNewDuration(1 * time.Minute), - RootSnoozeTime: *config.MustNewDuration(1 * time.Minute), - BatchingStrategyID: 0, - MessageVisibilityInterval: config.Duration{}, - ExecOnchainConfig: evm_2_evm_offramp.EVM2EVMOffRampDynamicConfig{ - PermissionLessExecutionThresholdSeconds: uint32(24 * time.Hour.Seconds()), - MaxDataBytes: 1e5, - MaxNumberOfTokensPerMsg: 5, - }, - OCR2ConfigParams: DefaultOCRParams(), - }) - } - return addLanesCfg, commitOCR2Configs, execOCR2Configs, jobSpecs -} - -func CreatePricesPipeline(t *testing.T, state changeset.CCIPOnChainState, source, dest uint64) (string, *httptest.Server, *httptest.Server) { - sourceRouter := state.Chains[source].Router - destRouter := state.Chains[dest].Router - destLink := state.Chains[dest].LinkToken - linkUSD := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { - _, err := w.Write([]byte(`{"UsdPerLink": "8000000000000000000"}`)) - require.NoError(t, err) - })) - t.Cleanup(linkUSD.Close) - - ethUSD := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { - _, err := w.Write([]byte(`{"UsdPerETH": "1700000000000000000000"}`)) - require.NoError(t, err) - })) - t.Cleanup(ethUSD.Close) - - sourceWrappedNative, err := sourceRouter.GetWrappedNative(nil) - require.NoError(t, err) - destWrappedNative, err := destRouter.GetWrappedNative(nil) - require.NoError(t, err) - tokenPricesUSDPipeline := fmt.Sprintf(` -// Price 1 -link [type=http method=GET url="%s"]; -link_parse [type=jsonparse path="UsdPerLink"]; -link->link_parse; -eth [type=http method=GET url="%s"]; -eth_parse [type=jsonparse path="UsdPerETH"]; -eth->eth_parse; -merge [type=merge left="{}" right="{\\\"%s\\\":$(link_parse), \\\"%s\\\":$(eth_parse), \\\"%s\\\":$(eth_parse)}"];`, - linkUSD.URL, ethUSD.URL, destLink.Address(), sourceWrappedNative, destWrappedNative) - - return tokenPricesUSDPipeline, linkUSD, ethUSD -} - -func DefaultOCRParams() confighelper.PublicConfig { - return confighelper.PublicConfig{ - DeltaProgress: 2 * time.Second, - DeltaResend: 1 * time.Second, - DeltaRound: 1 * time.Second, - DeltaGrace: 500 * time.Millisecond, - DeltaStage: 2 * time.Second, - RMax: 3, - MaxDurationInitialization: nil, - MaxDurationQuery: 50 * time.Millisecond, - MaxDurationObservation: 1 * time.Second, - MaxDurationReport: 100 * time.Millisecond, - MaxDurationShouldAcceptFinalizedReport: 100 * time.Millisecond, - MaxDurationShouldTransmitAcceptedReport: 100 * time.Millisecond, - } -} - -func SendRequest( - t *testing.T, - e deployment.Environment, - state changeset.CCIPOnChainState, - opts ...changeset.SendReqOpts, -) (*evm_2_evm_onramp.EVM2EVMOnRampCCIPSendRequested, error) { - cfg := &changeset.CCIPSendReqConfig{} - for _, opt := range opts { - opt(cfg) - } - // Set default sender if not provided - if cfg.Sender == nil { - cfg.Sender = e.Chains[cfg.SourceChain].DeployerKey - } - t.Logf("Sending CCIP request from chain selector %d to chain selector %d from sender %s", - cfg.SourceChain, cfg.DestChain, cfg.Sender.From.String()) - tx, blockNum, err := changeset.CCIPSendRequest(e, state, cfg) - if err != nil { - return nil, err - } - - onRamp := state.Chains[cfg.SourceChain].EVM2EVMOnRamp[cfg.DestChain] - - it, err := onRamp.FilterCCIPSendRequested(&bind.FilterOpts{ - Start: blockNum, - End: &blockNum, - Context: context.Background(), - }) - if err != nil { - return nil, err - } - - require.True(t, it.Next()) - t.Logf("CCIP message (id %x) sent from chain selector %d to chain selector %d tx %s seqNum %d sender %s", - it.Event.Message.MessageId[:], - cfg.SourceChain, - cfg.DestChain, - tx.Hash().String(), - it.Event.Message.SequenceNumber, - it.Event.Message.Sender.String(), - ) - return it.Event, nil -} - -func WaitForCommit( - t *testing.T, - src deployment.Chain, - dest deployment.Chain, - commitStore *commit_store.CommitStore, - seqNr uint64, -) { - timer := time.NewTimer(5 * time.Minute) - defer timer.Stop() - ticker := time.NewTicker(2 * time.Second) - defer ticker.Stop() - for { - select { - case <-ticker.C: - if backend, ok := src.Client.(*memory.Backend); ok { - backend.Commit() - } - if backend, ok := dest.Client.(*memory.Backend); ok { - backend.Commit() - } - minSeqNr, err := commitStore.GetExpectedNextSequenceNumber(nil) - require.NoError(t, err) - t.Logf("Waiting for commit for sequence number %d, current min sequence number %d", seqNr, minSeqNr) - if minSeqNr > seqNr { - t.Logf("Commit for sequence number %d found", seqNr) - return - } - case <-timer.C: - t.Fatalf("timed out waiting for commit for sequence number %d for commit store %s ", seqNr, commitStore.Address().String()) - return - } - } -} - -func WaitForExecute( - t *testing.T, - src deployment.Chain, - dest deployment.Chain, - offRamp *evm_2_evm_offramp.EVM2EVMOffRamp, - seqNrs []uint64, - blockNum uint64, -) { - timer := time.NewTimer(5 * time.Minute) - defer timer.Stop() - ticker := time.NewTicker(2 * time.Second) - defer ticker.Stop() - for { - select { - case <-ticker.C: - if backend, ok := src.Client.(*memory.Backend); ok { - backend.Commit() - } - if backend, ok := dest.Client.(*memory.Backend); ok { - backend.Commit() - } - t.Logf("Waiting for execute for sequence numbers %v", seqNrs) - it, err := offRamp.FilterExecutionStateChanged( - &bind.FilterOpts{ - Start: blockNum, - }, seqNrs, [][32]byte{}) - require.NoError(t, err) - for it.Next() { - t.Logf("Execution state changed for sequence number=%d current state=%d", it.Event.SequenceNumber, it.Event.State) - if cciptypes.MessageExecutionState(it.Event.State) == cciptypes.ExecutionStateSuccess { - t.Logf("Execution for sequence number %d found", it.Event.SequenceNumber) - return - } - t.Logf("Execution for sequence number %d resulted in status %d", it.Event.SequenceNumber, it.Event.State) - t.Fail() - } - case <-timer.C: - t.Fatalf("timed out waiting for execute for sequence numbers %v for offramp %s ", seqNrs, offRamp.Address().String()) - return - } - } -} diff --git a/deployment/ccip/changeset/view.go b/deployment/ccip/changeset/view.go index 1fd8fdbe38f..9d3eb8260c7 100644 --- a/deployment/ccip/changeset/view.go +++ b/deployment/ccip/changeset/view.go @@ -4,6 +4,7 @@ import ( "encoding/json" "github.com/smartcontractkit/chainlink/deployment" + ccipdeployment "github.com/smartcontractkit/chainlink/deployment/ccip" ccipview "github.com/smartcontractkit/chainlink/deployment/ccip/view" "github.com/smartcontractkit/chainlink/deployment/common/view" ) @@ -11,7 +12,7 @@ import ( var _ deployment.ViewState = ViewCCIP func ViewCCIP(e deployment.Environment) (json.Marshaler, error) { - state, err := LoadOnchainState(e) + state, err := ccipdeployment.LoadOnchainState(e) if err != nil { return nil, err } diff --git a/deployment/ccip/changeset/view_test.go b/deployment/ccip/changeset/view_test.go deleted file mode 100644 index 35193979849..00000000000 --- a/deployment/ccip/changeset/view_test.go +++ /dev/null @@ -1,14 +0,0 @@ -package changeset - -import ( - "testing" - - "github.com/stretchr/testify/require" -) - -func TestSmokeView(t *testing.T) { - t.Parallel() - tenv := NewMemoryEnvironment(t, WithChains(3)) - _, err := ViewCCIP(tenv.Env) - require.NoError(t, err) -} diff --git a/deployment/ccip/consts.go b/deployment/ccip/consts.go new file mode 100644 index 00000000000..48466bcef46 --- /dev/null +++ b/deployment/ccip/consts.go @@ -0,0 +1,11 @@ +package ccipdeployment + +type TokenSymbol string + +const ( + LinkSymbol TokenSymbol = "LINK" + WethSymbol TokenSymbol = "WETH" + USDCSymbol TokenSymbol = "USDC" + LinkDecimals = 18 + WethDecimals = 18 +) diff --git a/deployment/ccip/deploy.go b/deployment/ccip/deploy.go new file mode 100644 index 00000000000..83e233b71bb --- /dev/null +++ b/deployment/ccip/deploy.go @@ -0,0 +1,851 @@ +package ccipdeployment + +import ( + "fmt" + "math/big" + + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/pkg/errors" + "github.com/smartcontractkit/ccip-owner-contracts/pkg/config" + owner_helpers "github.com/smartcontractkit/ccip-owner-contracts/pkg/gethwrappers" + cciptypes "github.com/smartcontractkit/chainlink-ccip/pkg/types/ccipocr3" + "github.com/smartcontractkit/chainlink-ccip/pluginconfig" + commonconfig "github.com/smartcontractkit/chainlink-common/pkg/config" + "github.com/smartcontractkit/chainlink-common/pkg/logger" + + "github.com/smartcontractkit/chainlink/deployment" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/ccip_home" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/fee_quoter" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/maybe_revert_message_receiver" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/mock_rmn_contract" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/nonce_manager" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/offramp" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/onramp" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/registry_module_owner_custom" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/rmn_home" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/rmn_proxy_contract" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/rmn_remote" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/router" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/token_admin_registry" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/weth9" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/shared/generated/burn_mint_erc677" +) + +var ( + MockRMN deployment.ContractType = "MockRMN" + RMNRemote deployment.ContractType = "RMNRemote" + LinkToken deployment.ContractType = "LinkToken" + ARMProxy deployment.ContractType = "ARMProxy" + WETH9 deployment.ContractType = "WETH9" + Router deployment.ContractType = "Router" + CommitStore deployment.ContractType = "CommitStore" + TokenAdminRegistry deployment.ContractType = "TokenAdminRegistry" + RegistryModule deployment.ContractType = "RegistryModuleOwnerCustom" + NonceManager deployment.ContractType = "NonceManager" + FeeQuoter deployment.ContractType = "FeeQuoter" + AdminManyChainMultisig deployment.ContractType = "AdminManyChainMultiSig" + BypasserManyChainMultisig deployment.ContractType = "BypasserManyChainMultiSig" + CancellerManyChainMultisig deployment.ContractType = "CancellerManyChainMultiSig" + ProposerManyChainMultisig deployment.ContractType = "ProposerManyChainMultiSig" + CCIPHome deployment.ContractType = "CCIPHome" + CCIPConfig deployment.ContractType = "CCIPConfig" + RMNHome deployment.ContractType = "RMNHome" + RBACTimelock deployment.ContractType = "RBACTimelock" + OnRamp deployment.ContractType = "OnRamp" + OffRamp deployment.ContractType = "OffRamp" + CapabilitiesRegistry deployment.ContractType = "CapabilitiesRegistry" + PriceFeed deployment.ContractType = "PriceFeed" + // Note test router maps to a regular router contract. + TestRouter deployment.ContractType = "TestRouter" + CCIPReceiver deployment.ContractType = "CCIPReceiver" + BurnMintToken deployment.ContractType = "BurnMintToken" + BurnMintTokenPool deployment.ContractType = "BurnMintTokenPool" + USDCToken deployment.ContractType = "USDCToken" + USDCMockTransmitter deployment.ContractType = "USDCMockTransmitter" + USDCTokenMessenger deployment.ContractType = "USDCTokenMessenger" + USDCTokenPool deployment.ContractType = "USDCTokenPool" +) + +func DeployPrerequisiteChainContracts(e deployment.Environment, ab deployment.AddressBook, selectors []uint64) error { + state, err := LoadOnchainState(e) + if err != nil { + e.Logger.Errorw("Failed to load existing onchain state", "err") + return err + } + for _, sel := range selectors { + chain := e.Chains[sel] + err = DeployPrerequisiteContracts(e, ab, state, chain) + if err != nil { + return errors.Wrapf(err, "failed to deploy prerequisite contracts for chain %d", sel) + } + } + return nil +} + +// DeployPrerequisiteContracts deploys the contracts that can be ported from previous CCIP version to the new one. +// This is only required for staging and test environments where the contracts are not already deployed. +func DeployPrerequisiteContracts(e deployment.Environment, ab deployment.AddressBook, state CCIPOnChainState, chain deployment.Chain) error { + lggr := e.Logger + chainState, chainExists := state.Chains[chain.Selector] + var weth9Contract *weth9.WETH9 + var linkTokenContract *burn_mint_erc677.BurnMintERC677 + var tokenAdminReg *token_admin_registry.TokenAdminRegistry + var registryModule *registry_module_owner_custom.RegistryModuleOwnerCustom + var rmnProxy *rmn_proxy_contract.RMNProxyContract + var r *router.Router + if chainExists { + weth9Contract = chainState.Weth9 + linkTokenContract = chainState.LinkToken + tokenAdminReg = chainState.TokenAdminRegistry + registryModule = chainState.RegistryModule + rmnProxy = chainState.RMNProxyExisting + r = chainState.Router + } + if rmnProxy == nil { + // we want to replicate the mainnet scenario where RMNProxy is already deployed with some existing RMN + // This will need us to use two different RMNProxy contracts + // 1. RMNProxyNew with RMNRemote - ( deployed later in chain contracts) + // 2. RMNProxyExisting with mockRMN - ( deployed here, replicating the behavior of existing RMNProxy with already set RMN) + rmn, err := deployment.DeployContract(lggr, chain, ab, + func(chain deployment.Chain) deployment.ContractDeploy[*mock_rmn_contract.MockRMNContract] { + rmnAddr, tx2, rmn, err2 := mock_rmn_contract.DeployMockRMNContract( + chain.DeployerKey, + chain.Client, + ) + return deployment.ContractDeploy[*mock_rmn_contract.MockRMNContract]{ + rmnAddr, rmn, tx2, deployment.NewTypeAndVersion(MockRMN, deployment.Version1_0_0), err2, + } + }) + if err != nil { + lggr.Errorw("Failed to deploy mock RMN", "err", err) + return err + } + lggr.Infow("deployed mock RMN", "addr", rmn.Address) + rmnProxyContract, err := deployment.DeployContract(lggr, chain, ab, + func(chain deployment.Chain) deployment.ContractDeploy[*rmn_proxy_contract.RMNProxyContract] { + rmnProxyAddr, tx2, rmnProxy, err2 := rmn_proxy_contract.DeployRMNProxyContract( + chain.DeployerKey, + chain.Client, + rmn.Address, + ) + return deployment.ContractDeploy[*rmn_proxy_contract.RMNProxyContract]{ + rmnProxyAddr, rmnProxy, tx2, deployment.NewTypeAndVersion(ARMProxy, deployment.Version1_0_0), err2, + } + }) + if err != nil { + lggr.Errorw("Failed to deploy RMNProxyNew", "err", err) + return err + } + lggr.Infow("deployed RMNProxyNew", "addr", rmnProxyContract.Address) + rmnProxy = rmnProxyContract.Contract + } + if tokenAdminReg == nil { + tokenAdminRegistry, err := deployment.DeployContract(e.Logger, chain, ab, + func(chain deployment.Chain) deployment.ContractDeploy[*token_admin_registry.TokenAdminRegistry] { + tokenAdminRegistryAddr, tx2, tokenAdminRegistry, err2 := token_admin_registry.DeployTokenAdminRegistry( + chain.DeployerKey, + chain.Client) + return deployment.ContractDeploy[*token_admin_registry.TokenAdminRegistry]{ + tokenAdminRegistryAddr, tokenAdminRegistry, tx2, deployment.NewTypeAndVersion(TokenAdminRegistry, deployment.Version1_5_0), err2, + } + }) + if err != nil { + e.Logger.Errorw("Failed to deploy token admin registry", "err", err) + return err + } + e.Logger.Infow("deployed tokenAdminRegistry", "addr", tokenAdminRegistry) + tokenAdminReg = tokenAdminRegistry.Contract + } else { + e.Logger.Infow("tokenAdminRegistry already deployed", "addr", tokenAdminReg.Address) + } + if registryModule == nil { + customRegistryModule, err := deployment.DeployContract(e.Logger, chain, ab, + func(chain deployment.Chain) deployment.ContractDeploy[*registry_module_owner_custom.RegistryModuleOwnerCustom] { + regModAddr, tx2, regMod, err2 := registry_module_owner_custom.DeployRegistryModuleOwnerCustom( + chain.DeployerKey, + chain.Client, + tokenAdminReg.Address()) + return deployment.ContractDeploy[*registry_module_owner_custom.RegistryModuleOwnerCustom]{ + regModAddr, regMod, tx2, deployment.NewTypeAndVersion(RegistryModule, deployment.Version1_5_0), err2, + } + }) + if err != nil { + e.Logger.Errorw("Failed to deploy custom registry module", "err", err) + return err + } + e.Logger.Infow("deployed custom registry module", "addr", customRegistryModule) + registryModule = customRegistryModule.Contract + } else { + e.Logger.Infow("custom registry module already deployed", "addr", registryModule.Address) + } + isRegistryAdded, err := tokenAdminReg.IsRegistryModule(nil, registryModule.Address()) + if err != nil { + e.Logger.Errorw("Failed to check if registry module is added on token admin registry", "err", err) + return fmt.Errorf("failed to check if registry module is added on token admin registry: %w", err) + } + if !isRegistryAdded { + tx, err := tokenAdminReg.AddRegistryModule(chain.DeployerKey, registryModule.Address()) + if err != nil { + e.Logger.Errorw("Failed to assign registry module on token admin registry", "err", err) + return fmt.Errorf("failed to assign registry module on token admin registry: %w", err) + } + + _, err = chain.Confirm(tx) + if err != nil { + e.Logger.Errorw("Failed to confirm assign registry module on token admin registry", "err", err) + return fmt.Errorf("failed to confirm assign registry module on token admin registry: %w", err) + } + e.Logger.Infow("assigned registry module on token admin registry") + } + if weth9Contract == nil { + weth, err := deployment.DeployContract(lggr, chain, ab, + func(chain deployment.Chain) deployment.ContractDeploy[*weth9.WETH9] { + weth9Addr, tx2, weth9c, err2 := weth9.DeployWETH9( + chain.DeployerKey, + chain.Client, + ) + return deployment.ContractDeploy[*weth9.WETH9]{ + weth9Addr, weth9c, tx2, deployment.NewTypeAndVersion(WETH9, deployment.Version1_0_0), err2, + } + }) + if err != nil { + lggr.Errorw("Failed to deploy weth9", "err", err) + return err + } + lggr.Infow("deployed weth9", "addr", weth.Address) + weth9Contract = weth.Contract + } else { + lggr.Infow("weth9 already deployed", "addr", weth9Contract.Address) + } + if linkTokenContract == nil { + linkToken, err := deployment.DeployContract(lggr, chain, ab, + func(chain deployment.Chain) deployment.ContractDeploy[*burn_mint_erc677.BurnMintERC677] { + linkTokenAddr, tx2, linkToken, err2 := burn_mint_erc677.DeployBurnMintERC677( + chain.DeployerKey, + chain.Client, + "Link Token", + "LINK", + uint8(18), + big.NewInt(0).Mul(big.NewInt(1e9), big.NewInt(1e18)), + ) + return deployment.ContractDeploy[*burn_mint_erc677.BurnMintERC677]{ + linkTokenAddr, linkToken, tx2, deployment.NewTypeAndVersion(LinkToken, deployment.Version1_0_0), err2, + } + }) + if err != nil { + lggr.Errorw("Failed to deploy linkToken", "err", err) + return err + } + lggr.Infow("deployed linkToken", "addr", linkToken.Address) + linkTokenContract = linkToken.Contract + } else { + lggr.Infow("linkToken already deployed", "addr", linkTokenContract.Address) + } + // if router is not already deployed, we deploy it + if r == nil { + routerContract, err := deployment.DeployContract(e.Logger, chain, ab, + func(chain deployment.Chain) deployment.ContractDeploy[*router.Router] { + routerAddr, tx2, routerC, err2 := router.DeployRouter( + chain.DeployerKey, + chain.Client, + weth9Contract.Address(), + rmnProxy.Address(), + ) + return deployment.ContractDeploy[*router.Router]{ + routerAddr, routerC, tx2, deployment.NewTypeAndVersion(Router, deployment.Version1_2_0), err2, + } + }) + if err != nil { + e.Logger.Errorw("Failed to deploy router", "err", err) + return err + } + e.Logger.Infow("deployed router", "addr", routerContract.Address) + r = routerContract.Contract + } else { + e.Logger.Infow("router already deployed", "addr", chainState.Router.Address) + } + return nil +} + +type USDCConfig struct { + Enabled bool + USDCAttestationConfig +} + +type USDCAttestationConfig struct { + API string + APITimeout *commonconfig.Duration + APIInterval *commonconfig.Duration +} + +type DeployCCIPContractConfig struct { + HomeChainSel uint64 + FeedChainSel uint64 + ChainsToDeploy []uint64 + TokenConfig TokenConfig + // I believe it makes sense to have the same signers across all chains + // since that's the point MCMS. + MCMSConfig MCMSConfig + USDCConfig USDCConfig + // For setting OCR configuration + OCRSecrets deployment.OCRSecrets +} + +// DeployCCIPContracts assumes the following contracts are deployed: +// - Capability registry +// - CCIP home +// - RMN home +// - Fee tokens on all chains. +// and present in ExistingAddressBook. +// It then deploys the rest of the CCIP chain contracts to the selected chains +// registers the nodes with the capability registry and creates a DON for +// each new chain. TODO: Might be better to break this down a bit? +func DeployCCIPContracts(e deployment.Environment, ab deployment.AddressBook, c DeployCCIPContractConfig) error { + if c.OCRSecrets.IsEmpty() { + return fmt.Errorf("OCR secrets are empty") + } + nodes, err := deployment.NodeInfo(e.NodeIDs, e.Offchain) + if err != nil || len(nodes) == 0 { + e.Logger.Errorw("Failed to get node info", "err", err) + return err + } + existingState, err := LoadOnchainState(e) + if err != nil { + e.Logger.Errorw("Failed to load existing onchain state", "err") + return err + } + capReg := existingState.Chains[c.HomeChainSel].CapabilityRegistry + if capReg == nil { + e.Logger.Errorw("Failed to get capability registry") + return fmt.Errorf("capability registry not found") + } + cr, err := capReg.GetHashedCapabilityId( + &bind.CallOpts{}, CapabilityLabelledName, CapabilityVersion) + if err != nil { + e.Logger.Errorw("Failed to get hashed capability id", "err", err) + return err + } + if cr != CCIPCapabilityID { + return fmt.Errorf("capability registry does not support CCIP %s %s", hexutil.Encode(cr[:]), hexutil.Encode(CCIPCapabilityID[:])) + } + capability, err := capReg.GetCapability(nil, CCIPCapabilityID) + if err != nil { + e.Logger.Errorw("Failed to get capability", "err", err) + return err + } + ccipHome, err := ccip_home.NewCCIPHome(capability.ConfigurationContract, e.Chains[c.HomeChainSel].Client) + if err != nil { + e.Logger.Errorw("Failed to get ccip config", "err", err) + return err + } + if ccipHome.Address() != existingState.Chains[c.HomeChainSel].CCIPHome.Address() { + return fmt.Errorf("ccip home address mismatch") + } + + rmnHome := existingState.Chains[c.HomeChainSel].RMNHome + if rmnHome == nil { + e.Logger.Errorw("Failed to get rmn home", "err", err) + return fmt.Errorf("rmn home not found") + } + + usdcConfiguration := make(map[cciptypes.ChainSelector]pluginconfig.USDCCCTPTokenConfig) + for _, chainSel := range c.ChainsToDeploy { + chain, ok := e.Chains[chainSel] + if !ok { + return fmt.Errorf("chain %d not found", chainSel) + } + if existingState.Chains[chainSel].LinkToken == nil || existingState.Chains[chainSel].Weth9 == nil { + return fmt.Errorf("fee tokens not found for chain %d", chainSel) + } + err = DeployChainContracts(e, chain, ab, c.MCMSConfig, rmnHome) + if err != nil { + return err + } + + if c.USDCConfig.Enabled { + token, pool, messenger, transmitter, err1 := DeployUSDC(e.Logger, chain, ab, existingState.Chains[chainSel]) + if err1 != nil { + return err1 + } + e.Logger.Infow("Deployed USDC contracts", + "chainSelector", chainSel, + "token", token.Address(), + "pool", pool.Address(), + "transmitter", transmitter.Address(), + "messenger", messenger.Address(), + ) + + usdcConfiguration[cciptypes.ChainSelector(chainSel)] = pluginconfig.USDCCCTPTokenConfig{ + SourcePoolAddress: pool.Address().Hex(), + SourceMessageTransmitterAddr: transmitter.Address().Hex(), + } + } + } + + for _, chainSel := range c.ChainsToDeploy { + chain, _ := e.Chains[chainSel] + + chainAddresses, err := ab.AddressesForChain(chain.Selector) + if err != nil { + e.Logger.Errorw("Failed to get chain addresses", "err", err) + return err + } + chainState, err := LoadChainState(chain, chainAddresses) + if err != nil { + e.Logger.Errorw("Failed to load chain state", "err", err) + return err + } + + tokenInfo := c.TokenConfig.GetTokenInfo(e.Logger, existingState.Chains[chainSel].LinkToken, existingState.Chains[chainSel].Weth9) + // TODO: Do we want to extract this? + // Add chain config for each chain. + _, err = AddChainConfig( + e.Logger, + e.Chains[c.HomeChainSel], + ccipHome, + chain.Selector, + nodes.NonBootstraps().PeerIDs()) + if err != nil { + return err + } + var tokenDataObserversConf []pluginconfig.TokenDataObserverConfig + if c.USDCConfig.Enabled { + tokenDataObserversConf = []pluginconfig.TokenDataObserverConfig{{ + Type: pluginconfig.USDCCCTPHandlerType, + Version: "1.0", + USDCCCTPObserverConfig: &pluginconfig.USDCCCTPObserverConfig{ + Tokens: usdcConfiguration, + AttestationAPI: c.USDCConfig.API, + AttestationAPITimeout: c.USDCConfig.APITimeout, + AttestationAPIInterval: c.USDCConfig.APIInterval, + }, + }} + } + // For each chain, we create a DON on the home chain (2 OCR instances) + if err := AddDON( + e.Logger, + c.OCRSecrets, + capReg, + ccipHome, + rmnHome.Address(), + chainState.OffRamp, + c.FeedChainSel, + tokenInfo, + chain, + e.Chains[c.HomeChainSel], + nodes.NonBootstraps(), + tokenDataObserversConf, + ); err != nil { + e.Logger.Errorw("Failed to add DON", "err", err) + return err + } + } + + return nil +} + +type MCMSConfig struct { + Admin config.Config + Canceller config.Config + Bypasser config.Config + Proposer config.Config + Executors []common.Address +} + +func DeployMCMSWithConfig( + contractType deployment.ContractType, + lggr logger.Logger, + chain deployment.Chain, + ab deployment.AddressBook, + mcmConfig config.Config, +) (*deployment.ContractDeploy[*owner_helpers.ManyChainMultiSig], error) { + groupQuorums, groupParents, signerAddresses, signerGroups := mcmConfig.ExtractSetConfigInputs() + mcm, err := deployment.DeployContract(lggr, chain, ab, + func(chain deployment.Chain) deployment.ContractDeploy[*owner_helpers.ManyChainMultiSig] { + mcmAddr, tx, mcm, err2 := owner_helpers.DeployManyChainMultiSig( + chain.DeployerKey, + chain.Client, + ) + return deployment.ContractDeploy[*owner_helpers.ManyChainMultiSig]{ + mcmAddr, mcm, tx, deployment.NewTypeAndVersion(contractType, deployment.Version1_0_0), err2, + } + }) + if err != nil { + lggr.Errorw("Failed to deploy mcm", "err", err) + return mcm, err + } + mcmsTx, err := mcm.Contract.SetConfig(chain.DeployerKey, + signerAddresses, + signerGroups, // Signer 1 is int group 0 (root group) with quorum 1. + groupQuorums, + groupParents, + false, + ) + if _, err := deployment.ConfirmIfNoError(chain, mcmsTx, err); err != nil { + lggr.Errorw("Failed to confirm mcm config", "err", err) + return mcm, err + } + return mcm, nil +} + +type MCMSContracts struct { + Admin *deployment.ContractDeploy[*owner_helpers.ManyChainMultiSig] + Canceller *deployment.ContractDeploy[*owner_helpers.ManyChainMultiSig] + Bypasser *deployment.ContractDeploy[*owner_helpers.ManyChainMultiSig] + Proposer *deployment.ContractDeploy[*owner_helpers.ManyChainMultiSig] + Timelock *deployment.ContractDeploy[*owner_helpers.RBACTimelock] +} + +// DeployMCMSContracts deploys the MCMS contracts for the given configuration +// as well as the timelock. +func DeployMCMSContracts( + lggr logger.Logger, + chain deployment.Chain, + ab deployment.AddressBook, + mcmConfig MCMSConfig, +) (*MCMSContracts, error) { + adminMCM, err := DeployMCMSWithConfig(AdminManyChainMultisig, lggr, chain, ab, mcmConfig.Admin) + if err != nil { + return nil, err + } + bypasser, err := DeployMCMSWithConfig(BypasserManyChainMultisig, lggr, chain, ab, mcmConfig.Bypasser) + if err != nil { + return nil, err + } + canceller, err := DeployMCMSWithConfig(CancellerManyChainMultisig, lggr, chain, ab, mcmConfig.Canceller) + if err != nil { + return nil, err + } + proposer, err := DeployMCMSWithConfig(ProposerManyChainMultisig, lggr, chain, ab, mcmConfig.Proposer) + if err != nil { + return nil, err + } + + timelock, err := deployment.DeployContract(lggr, chain, ab, + func(chain deployment.Chain) deployment.ContractDeploy[*owner_helpers.RBACTimelock] { + timelock, tx2, cc, err2 := owner_helpers.DeployRBACTimelock( + chain.DeployerKey, + chain.Client, + big.NewInt(0), // minDelay + adminMCM.Address, + []common.Address{proposer.Address}, // proposers + mcmConfig.Executors, //executors + []common.Address{canceller.Address}, // cancellers + []common.Address{bypasser.Address}, // bypassers + ) + return deployment.ContractDeploy[*owner_helpers.RBACTimelock]{ + timelock, cc, tx2, deployment.NewTypeAndVersion(RBACTimelock, deployment.Version1_0_0), err2, + } + }) + if err != nil { + lggr.Errorw("Failed to deploy timelock", "err", err) + return nil, err + } + lggr.Infow("deployed timelock", "addr", timelock.Address) + return &MCMSContracts{ + Admin: adminMCM, + Canceller: canceller, + Bypasser: bypasser, + Proposer: proposer, + Timelock: timelock, + }, nil +} + +func DeployChainContracts( + e deployment.Environment, + chain deployment.Chain, + ab deployment.AddressBook, + mcmsConfig MCMSConfig, + rmnHome *rmn_home.RMNHome, +) error { + mcmsContracts, err := DeployMCMSContracts(e.Logger, chain, ab, mcmsConfig) + if err != nil { + return err + } + // check for existing contracts + state, err := LoadOnchainState(e) + if err != nil { + e.Logger.Errorw("Failed to load existing onchain state", "err") + return err + } + chainState, chainExists := state.Chains[chain.Selector] + if !chainExists { + return fmt.Errorf("chain %d not found in existing state, deploy the prerequisites first", chain.Selector) + } + if chainState.Weth9 == nil { + return fmt.Errorf("weth9 not found for chain %d, deploy the prerequisites first", chain.Selector) + } + weth9Contract := chainState.Weth9 + if chainState.LinkToken == nil { + return fmt.Errorf("link token not found for chain %d, deploy the prerequisites first", chain.Selector) + } + linkTokenContract := chainState.LinkToken + if chainState.TokenAdminRegistry == nil { + return fmt.Errorf("token admin registry not found for chain %d, deploy the prerequisites first", chain.Selector) + } + tokenAdminReg := chainState.TokenAdminRegistry + if chainState.RegistryModule == nil { + return fmt.Errorf("registry module not found for chain %d, deploy the prerequisites first", chain.Selector) + } + if chainState.Router == nil { + return fmt.Errorf("router not found for chain %d, deploy the prerequisites first", chain.Selector) + } + if chainState.Receiver == nil { + ccipReceiver, err := deployment.DeployContract(e.Logger, chain, ab, + func(chain deployment.Chain) deployment.ContractDeploy[*maybe_revert_message_receiver.MaybeRevertMessageReceiver] { + receiverAddr, tx, receiver, err2 := maybe_revert_message_receiver.DeployMaybeRevertMessageReceiver( + chain.DeployerKey, + chain.Client, + false, + ) + return deployment.ContractDeploy[*maybe_revert_message_receiver.MaybeRevertMessageReceiver]{ + receiverAddr, receiver, tx, deployment.NewTypeAndVersion(CCIPReceiver, deployment.Version1_0_0), err2, + } + }) + if err != nil { + e.Logger.Errorw("Failed to deploy receiver", "err", err) + return err + } + e.Logger.Infow("deployed receiver", "addr", ccipReceiver.Address) + } else { + e.Logger.Infow("receiver already deployed", "addr", chainState.Receiver.Address) + } + rmnRemoteContract := chainState.RMNRemote + if chainState.RMNRemote == nil { + // TODO: Correctly configure RMN remote. + rmnRemote, err := deployment.DeployContract(e.Logger, chain, ab, + func(chain deployment.Chain) deployment.ContractDeploy[*rmn_remote.RMNRemote] { + rmnRemoteAddr, tx, rmnRemote, err2 := rmn_remote.DeployRMNRemote( + chain.DeployerKey, + chain.Client, + chain.Selector, + ) + return deployment.ContractDeploy[*rmn_remote.RMNRemote]{ + rmnRemoteAddr, rmnRemote, tx, deployment.NewTypeAndVersion(RMNRemote, deployment.Version1_6_0_dev), err2, + } + }) + if err != nil { + e.Logger.Errorw("Failed to deploy RMNRemote", "err", err) + return err + } + e.Logger.Infow("deployed RMNRemote", "addr", rmnRemote.Address) + rmnRemoteContract = rmnRemote.Contract + } else { + e.Logger.Infow("rmn remote already deployed", "addr", chainState.RMNRemote.Address) + } + activeDigest, err := rmnHome.GetActiveDigest(&bind.CallOpts{}) + if err != nil { + e.Logger.Errorw("Failed to get active digest", "err", err) + return err + } + e.Logger.Infow("setting active home digest to rmn remote", "digest", activeDigest) + + tx, err := rmnRemoteContract.SetConfig(chain.DeployerKey, rmn_remote.RMNRemoteConfig{ + RmnHomeContractConfigDigest: activeDigest, + Signers: []rmn_remote.RMNRemoteSigner{ + {NodeIndex: 0, OnchainPublicKey: common.Address{1}}, + }, + F: 0, // TODO: update when we have signers + }) + if _, err := deployment.ConfirmIfNoError(chain, tx, err); err != nil { + e.Logger.Errorw("Failed to confirm RMNRemote config", "err", err) + return err + } + + // we deploy a new RMNProxy so that RMNRemote can be tested first before pointing it to the main Existing RMNProxy + // To differentiate between the two RMNProxies, we will deploy new one with Version1_6_0_dev + rmnProxyContract := chainState.RMNProxyNew + if chainState.RMNProxyNew == nil { + // we deploy a new rmnproxy contract to test RMNRemote + rmnProxy, err := deployment.DeployContract(e.Logger, chain, ab, + func(chain deployment.Chain) deployment.ContractDeploy[*rmn_proxy_contract.RMNProxyContract] { + rmnProxyAddr, tx, rmnProxy, err2 := rmn_proxy_contract.DeployRMNProxyContract( + chain.DeployerKey, + chain.Client, + rmnRemoteContract.Address(), + ) + return deployment.ContractDeploy[*rmn_proxy_contract.RMNProxyContract]{ + rmnProxyAddr, rmnProxy, tx, deployment.NewTypeAndVersion(ARMProxy, deployment.Version1_6_0_dev), err2, + } + }) + if err != nil { + e.Logger.Errorw("Failed to deploy RMNProxyNew", "err", err) + return err + } + e.Logger.Infow("deployed new RMNProxyNew", "addr", rmnProxy.Address) + rmnProxyContract = rmnProxy.Contract + } else { + e.Logger.Infow("rmn proxy already deployed", "addr", chainState.RMNProxyNew.Address) + } + if chainState.TestRouter == nil { + testRouterContract, err := deployment.DeployContract(e.Logger, chain, ab, + func(chain deployment.Chain) deployment.ContractDeploy[*router.Router] { + routerAddr, tx2, routerC, err2 := router.DeployRouter( + chain.DeployerKey, + chain.Client, + weth9Contract.Address(), + rmnProxyContract.Address(), + ) + return deployment.ContractDeploy[*router.Router]{ + routerAddr, routerC, tx2, deployment.NewTypeAndVersion(TestRouter, deployment.Version1_2_0), err2, + } + }) + if err != nil { + e.Logger.Errorw("Failed to deploy test router", "err", err) + return err + } + e.Logger.Infow("deployed test router", "addr", testRouterContract.Address) + } else { + e.Logger.Infow("test router already deployed", "addr", chainState.TestRouter.Address) + } + + nmContract := chainState.NonceManager + if chainState.NonceManager == nil { + nonceManager, err := deployment.DeployContract(e.Logger, chain, ab, + func(chain deployment.Chain) deployment.ContractDeploy[*nonce_manager.NonceManager] { + nonceManagerAddr, tx2, nonceManager, err2 := nonce_manager.DeployNonceManager( + chain.DeployerKey, + chain.Client, + []common.Address{}, // Need to add onRamp after + ) + return deployment.ContractDeploy[*nonce_manager.NonceManager]{ + nonceManagerAddr, nonceManager, tx2, deployment.NewTypeAndVersion(NonceManager, deployment.Version1_6_0_dev), err2, + } + }) + if err != nil { + e.Logger.Errorw("Failed to deploy nonce manager", "err", err) + return err + } + e.Logger.Infow("Deployed nonce manager", "addr", nonceManager.Address) + nmContract = nonceManager.Contract + } else { + e.Logger.Infow("nonce manager already deployed", "addr", chainState.NonceManager.Address) + } + feeQuoterContract := chainState.FeeQuoter + if chainState.FeeQuoter == nil { + feeQuoter, err := deployment.DeployContract(e.Logger, chain, ab, + func(chain deployment.Chain) deployment.ContractDeploy[*fee_quoter.FeeQuoter] { + prAddr, tx2, pr, err2 := fee_quoter.DeployFeeQuoter( + chain.DeployerKey, + chain.Client, + fee_quoter.FeeQuoterStaticConfig{ + MaxFeeJuelsPerMsg: big.NewInt(0).Mul(big.NewInt(2e2), big.NewInt(1e18)), + LinkToken: linkTokenContract.Address(), + TokenPriceStalenessThreshold: uint32(24 * 60 * 60), + }, + []common.Address{mcmsContracts.Timelock.Address}, // timelock should be able to update, ramps added after + []common.Address{weth9Contract.Address(), linkTokenContract.Address()}, // fee tokens + []fee_quoter.FeeQuoterTokenPriceFeedUpdate{}, + []fee_quoter.FeeQuoterTokenTransferFeeConfigArgs{}, // TODO: tokens + []fee_quoter.FeeQuoterPremiumMultiplierWeiPerEthArgs{ + { + PremiumMultiplierWeiPerEth: 9e17, // 0.9 ETH + Token: linkTokenContract.Address(), + }, + { + PremiumMultiplierWeiPerEth: 1e18, + Token: weth9Contract.Address(), + }, + }, + []fee_quoter.FeeQuoterDestChainConfigArgs{}, + ) + return deployment.ContractDeploy[*fee_quoter.FeeQuoter]{ + prAddr, pr, tx2, deployment.NewTypeAndVersion(FeeQuoter, deployment.Version1_6_0_dev), err2, + } + }) + if err != nil { + e.Logger.Errorw("Failed to deploy fee quoter", "err", err) + return err + } + e.Logger.Infow("Deployed fee quoter", "addr", feeQuoter.Address) + feeQuoterContract = feeQuoter.Contract + } else { + e.Logger.Infow("fee quoter already deployed", "addr", chainState.FeeQuoter.Address) + } + onRampContract := chainState.OnRamp + if onRampContract == nil { + onRamp, err := deployment.DeployContract(e.Logger, chain, ab, + func(chain deployment.Chain) deployment.ContractDeploy[*onramp.OnRamp] { + onRampAddr, tx2, onRamp, err2 := onramp.DeployOnRamp( + chain.DeployerKey, + chain.Client, + onramp.OnRampStaticConfig{ + ChainSelector: chain.Selector, + RmnRemote: rmnProxyContract.Address(), + NonceManager: nmContract.Address(), + TokenAdminRegistry: tokenAdminReg.Address(), + }, + onramp.OnRampDynamicConfig{ + FeeQuoter: feeQuoterContract.Address(), + FeeAggregator: common.HexToAddress("0x1"), // TODO real fee aggregator + }, + []onramp.OnRampDestChainConfigArgs{}, + ) + return deployment.ContractDeploy[*onramp.OnRamp]{ + onRampAddr, onRamp, tx2, deployment.NewTypeAndVersion(OnRamp, deployment.Version1_6_0_dev), err2, + } + }) + if err != nil { + e.Logger.Errorw("Failed to deploy onramp", "err", err) + return err + } + e.Logger.Infow("Deployed onramp", "addr", onRamp.Address) + onRampContract = onRamp.Contract + } else { + e.Logger.Infow("onramp already deployed", "addr", chainState.OnRamp.Address) + } + offRampContract := chainState.OffRamp + if offRampContract == nil { + offRamp, err := deployment.DeployContract(e.Logger, chain, ab, + func(chain deployment.Chain) deployment.ContractDeploy[*offramp.OffRamp] { + offRampAddr, tx2, offRamp, err2 := offramp.DeployOffRamp( + chain.DeployerKey, + chain.Client, + offramp.OffRampStaticConfig{ + ChainSelector: chain.Selector, + RmnRemote: rmnProxyContract.Address(), + NonceManager: nmContract.Address(), + TokenAdminRegistry: tokenAdminReg.Address(), + }, + offramp.OffRampDynamicConfig{ + FeeQuoter: feeQuoterContract.Address(), + PermissionLessExecutionThresholdSeconds: uint32(86400), + IsRMNVerificationDisabled: true, + }, + []offramp.OffRampSourceChainConfigArgs{}, + ) + return deployment.ContractDeploy[*offramp.OffRamp]{ + Address: offRampAddr, Contract: offRamp, Tx: tx2, Tv: deployment.NewTypeAndVersion(OffRamp, deployment.Version1_6_0_dev), Err: err2, + } + }) + if err != nil { + e.Logger.Errorw("Failed to deploy offramp", "err", err) + return err + } + e.Logger.Infow("Deployed offramp", "addr", offRamp.Address) + offRampContract = offRamp.Contract + } else { + e.Logger.Infow("offramp already deployed", "addr", chainState.OffRamp.Address) + } + // Basic wiring is always needed. + tx, err = feeQuoterContract.ApplyAuthorizedCallerUpdates(chain.DeployerKey, fee_quoter.AuthorizedCallersAuthorizedCallerArgs{ + // TODO: We enable the deployer initially to set prices + // Should be removed after. + AddedCallers: []common.Address{offRampContract.Address(), chain.DeployerKey.From}, + }) + if _, err := deployment.ConfirmIfNoError(chain, tx, err); err != nil { + e.Logger.Errorw("Failed to confirm fee quoter authorized caller update", "err", err) + return err + } + + tx, err = nmContract.ApplyAuthorizedCallerUpdates(chain.DeployerKey, nonce_manager.AuthorizedCallersAuthorizedCallerArgs{ + AddedCallers: []common.Address{offRampContract.Address(), onRampContract.Address()}, + }) + if _, err := deployment.ConfirmIfNoError(chain, tx, err); err != nil { + e.Logger.Errorw("Failed to update nonce manager with ramps", "err", err) + return err + } + return nil +} diff --git a/deployment/ccip/deploy_home_chain.go b/deployment/ccip/deploy_home_chain.go new file mode 100644 index 00000000000..9c7c65bc9dc --- /dev/null +++ b/deployment/ccip/deploy_home_chain.go @@ -0,0 +1,1085 @@ +package ccipdeployment + +import ( + "bytes" + "context" + "encoding/hex" + "encoding/json" + "fmt" + "math/big" + "os" + "time" + + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "github.com/pkg/errors" + "github.com/smartcontractkit/ccip-owner-contracts/pkg/proposal/mcms" + "golang.org/x/exp/maps" + + "github.com/smartcontractkit/chainlink-ccip/chainconfig" + "github.com/smartcontractkit/chainlink-ccip/pkg/types/ccipocr3" + "github.com/smartcontractkit/chainlink-ccip/pluginconfig" + + commonconfig "github.com/smartcontractkit/chainlink-common/pkg/config" + "github.com/smartcontractkit/chainlink-common/pkg/logger" + "github.com/smartcontractkit/chainlink-common/pkg/merklemulti" + + confighelper2 "github.com/smartcontractkit/libocr/offchainreporting2plus/confighelper" + "github.com/smartcontractkit/libocr/offchainreporting2plus/ocr3confighelper" + + "github.com/smartcontractkit/chainlink/deployment" + cctypes "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/types" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/ccip_home" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/offramp" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/rmn_home" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry" + p2ptypes "github.com/smartcontractkit/chainlink/v2/core/services/p2p/types" +) + +const ( + NodeOperatorID = 1 + CapabilityLabelledName = "ccip" + CapabilityVersion = "v1.0.0" + + FirstBlockAge = 8 * time.Hour + RemoteGasPriceBatchWriteFrequency = 30 * time.Minute + TokenPriceBatchWriteFrequency = 30 * time.Minute + BatchGasLimit = 6_500_000 + RelativeBoostPerWaitHour = 1.5 + InflightCacheExpiry = 10 * time.Minute + RootSnoozeTime = 30 * time.Minute + BatchingStrategyID = 0 + DeltaProgress = 30 * time.Second + DeltaResend = 10 * time.Second + DeltaInitial = 20 * time.Second + DeltaRound = 2 * time.Second + DeltaGrace = 2 * time.Second + DeltaCertifiedCommitRequest = 10 * time.Second + DeltaStage = 10 * time.Second + Rmax = 3 + MaxDurationQuery = 500 * time.Millisecond + MaxDurationObservation = 5 * time.Second + MaxDurationShouldAcceptAttestedReport = 10 * time.Second + MaxDurationShouldTransmitAcceptedReport = 10 * time.Second +) + +var ( + CCIPCapabilityID = utils.Keccak256Fixed(MustABIEncode(`[{"type": "string"}, {"type": "string"}]`, CapabilityLabelledName, CapabilityVersion)) + CCIPHomeABI *abi.ABI +) + +func init() { + var err error + CCIPHomeABI, err = ccip_home.CCIPHomeMetaData.GetAbi() + if err != nil { + panic(err) + } +} + +func MustABIEncode(abiString string, args ...interface{}) []byte { + encoded, err := utils.ABIEncode(abiString, args...) + if err != nil { + panic(err) + } + return encoded +} + +// DeployCapReg deploys the CapabilitiesRegistry contract if it is not already deployed +// and returns a deployment.ContractDeploy struct with the address and contract instance. +func DeployCapReg( + lggr logger.Logger, + state CCIPOnChainState, + ab deployment.AddressBook, + chain deployment.Chain, +) (*deployment.ContractDeploy[*capabilities_registry.CapabilitiesRegistry], error) { + homeChainState, exists := state.Chains[chain.Selector] + if exists { + cr := homeChainState.CapabilityRegistry + if cr != nil { + lggr.Infow("Found CapabilitiesRegistry in chain state", "address", cr.Address().String()) + return &deployment.ContractDeploy[*capabilities_registry.CapabilitiesRegistry]{ + Address: cr.Address(), Contract: cr, Tv: deployment.NewTypeAndVersion(CapabilitiesRegistry, deployment.Version1_0_0), + }, nil + } + } + capReg, err := deployment.DeployContract(lggr, chain, ab, + func(chain deployment.Chain) deployment.ContractDeploy[*capabilities_registry.CapabilitiesRegistry] { + crAddr, tx, cr, err2 := capabilities_registry.DeployCapabilitiesRegistry( + chain.DeployerKey, + chain.Client, + ) + return deployment.ContractDeploy[*capabilities_registry.CapabilitiesRegistry]{ + Address: crAddr, Contract: cr, Tv: deployment.NewTypeAndVersion(CapabilitiesRegistry, deployment.Version1_0_0), Tx: tx, Err: err2, + } + }) + if err != nil { + lggr.Errorw("Failed to deploy capreg", "err", err) + return nil, err + } + return capReg, nil +} + +func DeployHomeChain( + lggr logger.Logger, + e deployment.Environment, + ab deployment.AddressBook, + chain deployment.Chain, + rmnHomeStatic rmn_home.RMNHomeStaticConfig, + rmnHomeDynamic rmn_home.RMNHomeDynamicConfig, + nodeOps []capabilities_registry.CapabilitiesRegistryNodeOperator, + nodeP2PIDsPerNodeOpAdmin map[string][][32]byte, +) (*deployment.ContractDeploy[*capabilities_registry.CapabilitiesRegistry], error) { + // load existing state + state, err := LoadOnchainState(e) + if err != nil { + return nil, fmt.Errorf("failed to load onchain state: %w", err) + } + // Deploy CapabilitiesRegistry, CCIPHome, RMNHome + capReg, err := DeployCapReg(lggr, state, ab, chain) + if err != nil { + return nil, err + } + + lggr.Infow("deployed/connected to capreg", "addr", capReg.Address) + ccipHome, err := deployment.DeployContract( + lggr, chain, ab, + func(chain deployment.Chain) deployment.ContractDeploy[*ccip_home.CCIPHome] { + ccAddr, tx, cc, err2 := ccip_home.DeployCCIPHome( + chain.DeployerKey, + chain.Client, + capReg.Address, + ) + return deployment.ContractDeploy[*ccip_home.CCIPHome]{ + Address: ccAddr, Tv: deployment.NewTypeAndVersion(CCIPHome, deployment.Version1_6_0_dev), Tx: tx, Err: err2, Contract: cc, + } + }) + if err != nil { + lggr.Errorw("Failed to deploy CCIPHome", "err", err) + return nil, err + } + lggr.Infow("deployed CCIPHome", "addr", ccipHome.Address) + + rmnHome, err := deployment.DeployContract( + lggr, chain, ab, + func(chain deployment.Chain) deployment.ContractDeploy[*rmn_home.RMNHome] { + rmnAddr, tx, rmn, err2 := rmn_home.DeployRMNHome( + chain.DeployerKey, + chain.Client, + ) + return deployment.ContractDeploy[*rmn_home.RMNHome]{ + Address: rmnAddr, Tv: deployment.NewTypeAndVersion(RMNHome, deployment.Version1_6_0_dev), Tx: tx, Err: err2, Contract: rmn, + } + }, + ) + if err != nil { + lggr.Errorw("Failed to deploy RMNHome", "err", err) + return nil, err + } + lggr.Infow("deployed RMNHome", "addr", rmnHome.Address) + + // considering the RMNHome is recently deployed, there is no digest to overwrite + tx, err := rmnHome.Contract.SetCandidate(chain.DeployerKey, rmnHomeStatic, rmnHomeDynamic, [32]byte{}) + if _, err := deployment.ConfirmIfNoError(chain, tx, err); err != nil { + lggr.Errorw("Failed to set candidate on RMNHome", "err", err) + return nil, err + } + + rmnCandidateDigest, err := rmnHome.Contract.GetCandidateDigest(nil) + if err != nil { + lggr.Errorw("Failed to get RMNHome candidate digest", "err", err) + return nil, err + } + + tx, err = rmnHome.Contract.PromoteCandidateAndRevokeActive(chain.DeployerKey, rmnCandidateDigest, [32]byte{}) + if _, err := deployment.ConfirmIfNoError(chain, tx, err); err != nil { + lggr.Errorw("Failed to promote candidate and revoke active on RMNHome", "err", err) + return nil, err + } + + rmnActiveDigest, err := rmnHome.Contract.GetActiveDigest(nil) + if err != nil { + lggr.Errorw("Failed to get RMNHome active digest", "err", err) + return nil, err + } + lggr.Infow("Got rmn home active digest", "digest", rmnActiveDigest) + + if rmnActiveDigest != rmnCandidateDigest { + lggr.Errorw("RMNHome active digest does not match previously candidate digest", + "active", rmnActiveDigest, "candidate", rmnCandidateDigest) + return nil, errors.New("RMNHome active digest does not match candidate digest") + } + + tx, err = capReg.Contract.AddCapabilities(chain.DeployerKey, []capabilities_registry.CapabilitiesRegistryCapability{ + { + LabelledName: CapabilityLabelledName, + Version: CapabilityVersion, + CapabilityType: 2, // consensus. not used (?) + ResponseType: 0, // report. not used (?) + ConfigurationContract: ccipHome.Address, + }, + }) + if _, err := deployment.ConfirmIfNoError(chain, tx, err); err != nil { + lggr.Errorw("Failed to add capabilities", "err", err) + return nil, err + } + + tx, err = capReg.Contract.AddNodeOperators(chain.DeployerKey, nodeOps) + txBlockNum, err := deployment.ConfirmIfNoError(chain, tx, err) + if err != nil { + lggr.Errorw("Failed to add node operators", "err", err) + return nil, err + } + addedEvent, err := capReg.Contract.FilterNodeOperatorAdded(&bind.FilterOpts{ + Start: txBlockNum, + Context: context.Background(), + }, nil, nil) + if err != nil { + lggr.Errorw("Failed to filter NodeOperatorAdded event", "err", err) + return capReg, err + } + // Need to fetch nodeoperators ids to be able to add nodes for corresponding node operators + p2pIDsByNodeOpId := make(map[uint32][][32]byte) + for addedEvent.Next() { + for nopName, p2pId := range nodeP2PIDsPerNodeOpAdmin { + if addedEvent.Event.Name == nopName { + lggr.Infow("Added node operator", "admin", addedEvent.Event.Admin, "name", addedEvent.Event.Name) + p2pIDsByNodeOpId[addedEvent.Event.NodeOperatorId] = p2pId + } + } + } + if len(p2pIDsByNodeOpId) != len(nodeP2PIDsPerNodeOpAdmin) { + lggr.Errorw("Failed to add all node operators", "added", maps.Keys(p2pIDsByNodeOpId), "expected", maps.Keys(nodeP2PIDsPerNodeOpAdmin)) + return capReg, errors.New("failed to add all node operators") + } + // Adds initial set of nodes to CR, who all have the CCIP capability + if err := AddNodes(lggr, capReg.Contract, chain, p2pIDsByNodeOpId); err != nil { + return capReg, err + } + return capReg, nil +} + +// getNodeOperatorIDMap returns a map of node operator names to their IDs +// If maxNops is greater than the number of node operators, it will return all node operators +func getNodeOperatorIDMap(capReg *capabilities_registry.CapabilitiesRegistry, maxNops uint32) (map[string]uint32, error) { + nopIdByName := make(map[string]uint32) + operators, err := capReg.GetNodeOperators(nil) + if err != nil { + return nil, err + } + if len(operators) < int(maxNops) { + maxNops = uint32(len(operators)) + } + for i := uint32(1); i <= maxNops; i++ { + operator, err := capReg.GetNodeOperator(nil, i) + if err != nil { + return nil, err + } + nopIdByName[operator.Name] = i + } + return nopIdByName, nil +} + +func isEqualCapabilitiesRegistryNodeParams(a, b capabilities_registry.CapabilitiesRegistryNodeParams) (bool, error) { + aBytes, err := json.Marshal(a) + if err != nil { + return false, err + } + bBytes, err := json.Marshal(b) + if err != nil { + return false, err + } + return bytes.Equal(aBytes, bBytes), nil +} + +func AddNodes( + lggr logger.Logger, + capReg *capabilities_registry.CapabilitiesRegistry, + chain deployment.Chain, + p2pIDsByNodeOpId map[uint32][][32]byte, +) error { + var nodeParams []capabilities_registry.CapabilitiesRegistryNodeParams + nodes, err := capReg.GetNodes(nil) + if err != nil { + return err + } + existingNodeParams := make(map[p2ptypes.PeerID]capabilities_registry.CapabilitiesRegistryNodeParams) + for _, node := range nodes { + existingNodeParams[node.P2pId] = capabilities_registry.CapabilitiesRegistryNodeParams{ + NodeOperatorId: node.NodeOperatorId, + Signer: node.Signer, + P2pId: node.P2pId, + HashedCapabilityIds: node.HashedCapabilityIds, + } + } + for nopID, p2pIDs := range p2pIDsByNodeOpId { + for _, p2pID := range p2pIDs { + // if any p2pIDs are empty throw error + if bytes.Equal(p2pID[:], make([]byte, 32)) { + return errors.Wrapf(errors.New("empty p2pID"), "p2pID: %x selector: %d", p2pID, chain.Selector) + } + nodeParam := capabilities_registry.CapabilitiesRegistryNodeParams{ + NodeOperatorId: nopID, + Signer: p2pID, // Not used in tests + P2pId: p2pID, + EncryptionPublicKey: p2pID, // Not used in tests + HashedCapabilityIds: [][32]byte{CCIPCapabilityID}, + } + if existing, ok := existingNodeParams[p2pID]; ok { + if isEqual, err := isEqualCapabilitiesRegistryNodeParams(existing, nodeParam); err != nil && isEqual { + lggr.Infow("Node already exists", "p2pID", p2pID) + continue + } + } + + nodeParams = append(nodeParams, nodeParam) + } + } + if len(nodeParams) == 0 { + lggr.Infow("No new nodes to add") + return nil + } + tx, err := capReg.AddNodes(chain.DeployerKey, nodeParams) + if err != nil { + lggr.Errorw("Failed to add nodes", "err", deployment.MaybeDataErr(err)) + return err + } + _, err = chain.Confirm(tx) + return err +} + +func SetupConfigInfo(chainSelector uint64, readers [][32]byte, fChain uint8, cfg []byte) ccip_home.CCIPHomeChainConfigArgs { + return ccip_home.CCIPHomeChainConfigArgs{ + ChainSelector: chainSelector, + ChainConfig: ccip_home.CCIPHomeChainConfig{ + Readers: readers, + FChain: fChain, + Config: cfg, + }, + } +} + +func AddChainConfig( + lggr logger.Logger, + h deployment.Chain, + ccipConfig *ccip_home.CCIPHome, + chainSelector uint64, + p2pIDs [][32]byte, +) (ccip_home.CCIPHomeChainConfigArgs, error) { + // First Add ChainConfig that includes all p2pIDs as readers + encodedExtraChainConfig, err := chainconfig.EncodeChainConfig(chainconfig.ChainConfig{ + GasPriceDeviationPPB: ccipocr3.NewBigIntFromInt64(1000), + DAGasPriceDeviationPPB: ccipocr3.NewBigIntFromInt64(0), + OptimisticConfirmations: 1, + }) + if err != nil { + return ccip_home.CCIPHomeChainConfigArgs{}, err + } + chainConfig := SetupConfigInfo(chainSelector, p2pIDs, uint8(len(p2pIDs)/3), encodedExtraChainConfig) + tx, err := ccipConfig.ApplyChainConfigUpdates(h.DeployerKey, nil, []ccip_home.CCIPHomeChainConfigArgs{ + chainConfig, + }) + if _, err := deployment.ConfirmIfNoError(h, tx, err); err != nil { + return ccip_home.CCIPHomeChainConfigArgs{}, err + } + lggr.Infow("Applied chain config updates", "chainConfig", chainConfig) + return chainConfig, nil +} + +func BuildOCR3ConfigForCCIPHome( + ocrSecrets deployment.OCRSecrets, + offRamp *offramp.OffRamp, + dest deployment.Chain, + feedChainSel uint64, + tokenInfo map[ccipocr3.UnknownEncodedAddress]pluginconfig.TokenInfo, + nodes deployment.Nodes, + rmnHomeAddress common.Address, + configs []pluginconfig.TokenDataObserverConfig, +) (map[cctypes.PluginType]ccip_home.CCIPHomeOCR3Config, error) { + p2pIDs := nodes.PeerIDs() + // Get OCR3 Config from helper + var schedule []int + var oracles []confighelper2.OracleIdentityExtra + for _, node := range nodes { + schedule = append(schedule, 1) + cfg := node.SelToOCRConfig[dest.Selector] + oracles = append(oracles, confighelper2.OracleIdentityExtra{ + OracleIdentity: confighelper2.OracleIdentity{ + OnchainPublicKey: cfg.OnchainPublicKey, + TransmitAccount: cfg.TransmitAccount, + OffchainPublicKey: cfg.OffchainPublicKey, + PeerID: cfg.PeerID.String()[4:], + }, ConfigEncryptionPublicKey: cfg.ConfigEncryptionPublicKey, + }) + } + + // Add DON on capability registry contract + ocr3Configs := make(map[cctypes.PluginType]ccip_home.CCIPHomeOCR3Config) + for _, pluginType := range []cctypes.PluginType{cctypes.PluginTypeCCIPCommit, cctypes.PluginTypeCCIPExec} { + var encodedOffchainConfig []byte + var err2 error + if pluginType == cctypes.PluginTypeCCIPCommit { + encodedOffchainConfig, err2 = pluginconfig.EncodeCommitOffchainConfig(pluginconfig.CommitOffchainConfig{ + RemoteGasPriceBatchWriteFrequency: *commonconfig.MustNewDuration(RemoteGasPriceBatchWriteFrequency), + TokenPriceBatchWriteFrequency: *commonconfig.MustNewDuration(TokenPriceBatchWriteFrequency), + PriceFeedChainSelector: ccipocr3.ChainSelector(feedChainSel), + TokenInfo: tokenInfo, + NewMsgScanBatchSize: merklemulti.MaxNumberTreeLeaves, + MaxReportTransmissionCheckAttempts: 5, + MaxMerkleTreeSize: merklemulti.MaxNumberTreeLeaves, + SignObservationPrefix: "chainlink ccip 1.6 rmn observation", + RMNEnabled: os.Getenv("ENABLE_RMN") == "true", // only enabled in manual test + }) + } else { + encodedOffchainConfig, err2 = pluginconfig.EncodeExecuteOffchainConfig(pluginconfig.ExecuteOffchainConfig{ + BatchGasLimit: BatchGasLimit, + RelativeBoostPerWaitHour: RelativeBoostPerWaitHour, + MessageVisibilityInterval: *commonconfig.MustNewDuration(FirstBlockAge), + InflightCacheExpiry: *commonconfig.MustNewDuration(InflightCacheExpiry), + RootSnoozeTime: *commonconfig.MustNewDuration(RootSnoozeTime), + BatchingStrategyID: BatchingStrategyID, + TokenDataObservers: configs, + }) + } + if err2 != nil { + return nil, err2 + } + signers, transmitters, configF, _, offchainConfigVersion, offchainConfig, err2 := ocr3confighelper.ContractSetConfigArgsDeterministic( + ocrSecrets.EphemeralSk, + ocrSecrets.SharedSecret, + DeltaProgress, + DeltaResend, + DeltaInitial, + DeltaRound, + DeltaGrace, + DeltaCertifiedCommitRequest, + DeltaStage, + Rmax, + schedule, + oracles, + encodedOffchainConfig, + nil, // maxDurationInitialization + MaxDurationQuery, + MaxDurationObservation, + MaxDurationShouldAcceptAttestedReport, + MaxDurationShouldTransmitAcceptedReport, + int(nodes.DefaultF()), + []byte{}, // empty OnChainConfig + ) + if err2 != nil { + return nil, err2 + } + + signersBytes := make([][]byte, len(signers)) + for i, signer := range signers { + signersBytes[i] = signer + } + + transmittersBytes := make([][]byte, len(transmitters)) + for i, transmitter := range transmitters { + parsed, err2 := common.ParseHexOrString(string(transmitter)) + if err2 != nil { + return nil, err2 + } + transmittersBytes[i] = parsed + } + + var ocrNodes []ccip_home.CCIPHomeOCR3Node + for i := range nodes { + ocrNodes = append(ocrNodes, ccip_home.CCIPHomeOCR3Node{ + P2pId: p2pIDs[i], + SignerKey: signersBytes[i], + TransmitterKey: transmittersBytes[i], + }) + } + + _, ok := ocr3Configs[pluginType] + if ok { + return nil, fmt.Errorf("pluginType %s already exists in ocr3Configs", pluginType.String()) + } + + ocr3Configs[pluginType] = ccip_home.CCIPHomeOCR3Config{ + PluginType: uint8(pluginType), + ChainSelector: dest.Selector, + FRoleDON: configF, + OffchainConfigVersion: offchainConfigVersion, + OfframpAddress: offRamp.Address().Bytes(), + Nodes: ocrNodes, + OffchainConfig: offchainConfig, + RmnHomeAddress: rmnHomeAddress.Bytes(), + } + } + + return ocr3Configs, nil +} + +func LatestCCIPDON(registry *capabilities_registry.CapabilitiesRegistry) (*capabilities_registry.CapabilitiesRegistryDONInfo, error) { + dons, err := registry.GetDONs(nil) + if err != nil { + return nil, err + } + var ccipDON capabilities_registry.CapabilitiesRegistryDONInfo + for _, don := range dons { + if len(don.CapabilityConfigurations) == 1 && + don.CapabilityConfigurations[0].CapabilityId == CCIPCapabilityID && + don.Id > ccipDON.Id { + ccipDON = don + } + } + return &ccipDON, nil +} + +// DonIDForChain returns the DON ID for the chain with the given selector +// It looks up with the CCIPHome contract to find the OCR3 configs for the DONs, and returns the DON ID for the chain matching with the given selector from the OCR3 configs +func DonIDForChain(registry *capabilities_registry.CapabilitiesRegistry, ccipHome *ccip_home.CCIPHome, chainSelector uint64) (uint32, error) { + dons, err := registry.GetDONs(nil) + if err != nil { + return 0, err + } + // TODO: what happens if there are multiple dons for one chain (accidentally?) + for _, don := range dons { + if len(don.CapabilityConfigurations) == 1 && + don.CapabilityConfigurations[0].CapabilityId == CCIPCapabilityID { + configs, err := ccipHome.GetAllConfigs(nil, don.Id, uint8(cctypes.PluginTypeCCIPCommit)) + if err != nil { + return 0, err + } + if configs.ActiveConfig.Config.ChainSelector == chainSelector || configs.CandidateConfig.Config.ChainSelector == chainSelector { + return don.Id, nil + } + } + } + return 0, fmt.Errorf("no DON found for chain %d", chainSelector) +} + +func BuildSetOCR3ConfigArgs( + donID uint32, + ccipHome *ccip_home.CCIPHome, + destSelector uint64, +) ([]offramp.MultiOCR3BaseOCRConfigArgs, error) { + var offrampOCR3Configs []offramp.MultiOCR3BaseOCRConfigArgs + for _, pluginType := range []cctypes.PluginType{cctypes.PluginTypeCCIPCommit, cctypes.PluginTypeCCIPExec} { + ocrConfig, err2 := ccipHome.GetAllConfigs(&bind.CallOpts{ + Context: context.Background(), + }, donID, uint8(pluginType)) + if err2 != nil { + return nil, err2 + } + + fmt.Printf("pluginType: %s, destSelector: %d, donID: %d, activeConfig digest: %x, candidateConfig digest: %x\n", + pluginType.String(), destSelector, donID, ocrConfig.ActiveConfig.ConfigDigest, ocrConfig.CandidateConfig.ConfigDigest) + + // we expect only an active config and no candidate config. + if ocrConfig.ActiveConfig.ConfigDigest == [32]byte{} || ocrConfig.CandidateConfig.ConfigDigest != [32]byte{} { + return nil, fmt.Errorf("invalid OCR3 config state, expected active config and no candidate config, donID: %d", donID) + } + + activeConfig := ocrConfig.ActiveConfig + var signerAddresses []common.Address + var transmitterAddresses []common.Address + for _, node := range activeConfig.Config.Nodes { + signerAddresses = append(signerAddresses, common.BytesToAddress(node.SignerKey)) + transmitterAddresses = append(transmitterAddresses, common.BytesToAddress(node.TransmitterKey)) + } + + offrampOCR3Configs = append(offrampOCR3Configs, offramp.MultiOCR3BaseOCRConfigArgs{ + ConfigDigest: activeConfig.ConfigDigest, + OcrPluginType: uint8(pluginType), + F: activeConfig.Config.FRoleDON, + IsSignatureVerificationEnabled: pluginType == cctypes.PluginTypeCCIPCommit, + Signers: signerAddresses, + Transmitters: transmitterAddresses, + }) + } + return offrampOCR3Configs, nil +} + +// CreateDON creates one DON with 2 plugins (commit and exec) +// It first set a new candidate for the DON with the first plugin type and AddDON on capReg +// Then for subsequent operations it uses UpdateDON to promote the first plugin to the active deployment +// and to set candidate and promote it for the second plugin +func CreateDON( + lggr logger.Logger, + capReg *capabilities_registry.CapabilitiesRegistry, + ccipHome *ccip_home.CCIPHome, + ocr3Configs map[cctypes.PluginType]ccip_home.CCIPHomeOCR3Config, + home deployment.Chain, + newChainSel uint64, + nodes deployment.Nodes, +) error { + commitConfig, ok := ocr3Configs[cctypes.PluginTypeCCIPCommit] + if !ok { + return fmt.Errorf("missing commit plugin in ocr3Configs") + } + + execConfig, ok := ocr3Configs[cctypes.PluginTypeCCIPExec] + if !ok { + return fmt.Errorf("missing exec plugin in ocr3Configs") + } + + latestDon, err := LatestCCIPDON(capReg) + if err != nil { + return err + } + + donID := latestDon.Id + 1 + + err = setupCommitDON(donID, commitConfig, capReg, home, nodes, ccipHome) + if err != nil { + return fmt.Errorf("setup commit don: %w", err) + } + + // TODO: bug in contract causing this to not work as expected. + err = setupExecDON(donID, execConfig, capReg, home, nodes, ccipHome) + if err != nil { + return fmt.Errorf("setup exec don: %w", err) + } + return ValidateCCIPHomeConfigSetUp(capReg, ccipHome, newChainSel) +} + +func setupExecDON( + donID uint32, + execConfig ccip_home.CCIPHomeOCR3Config, + capReg *capabilities_registry.CapabilitiesRegistry, + home deployment.Chain, + nodes deployment.Nodes, + ccipHome *ccip_home.CCIPHome, +) error { + encodedSetCandidateCall, err := CCIPHomeABI.Pack( + "setCandidate", + donID, + execConfig.PluginType, + execConfig, + [32]byte{}, + ) + if err != nil { + return fmt.Errorf("pack set candidate call: %w", err) + } + + // set candidate call + tx, err := capReg.UpdateDON( + home.DeployerKey, + donID, + nodes.PeerIDs(), + []capabilities_registry.CapabilitiesRegistryCapabilityConfiguration{ + { + CapabilityId: CCIPCapabilityID, + Config: encodedSetCandidateCall, + }, + }, + false, + nodes.DefaultF(), + ) + if err != nil { + return fmt.Errorf("update don w/ exec config: %w", err) + } + + if _, err := deployment.ConfirmIfNoError(home, tx, err); err != nil { + return fmt.Errorf("confirm update don w/ exec config: %w", err) + } + + execCandidateDigest, err := ccipHome.GetCandidateDigest(nil, donID, execConfig.PluginType) + if err != nil { + return fmt.Errorf("get exec candidate digest 1st time: %w", err) + } + + if execCandidateDigest == [32]byte{} { + return fmt.Errorf("candidate digest is empty, expected nonempty") + } + + // promote candidate call + encodedPromotionCall, err := CCIPHomeABI.Pack( + "promoteCandidateAndRevokeActive", + donID, + execConfig.PluginType, + execCandidateDigest, + [32]byte{}, + ) + if err != nil { + return fmt.Errorf("pack promotion call: %w", err) + } + + tx, err = capReg.UpdateDON( + home.DeployerKey, + donID, + nodes.PeerIDs(), + []capabilities_registry.CapabilitiesRegistryCapabilityConfiguration{ + { + CapabilityId: CCIPCapabilityID, + Config: encodedPromotionCall, + }, + }, + false, + nodes.DefaultF(), + ) + if err != nil { + return fmt.Errorf("update don w/ exec config: %w", err) + } + bn, err := deployment.ConfirmIfNoError(home, tx, err) + if err != nil { + return fmt.Errorf("confirm update don w/ exec config: %w", err) + } + if bn == 0 { + return fmt.Errorf("UpdateDON tx not confirmed") + } + // check if candidate digest is promoted + pEvent, err := ccipHome.FilterConfigPromoted(&bind.FilterOpts{ + Context: context.Background(), + Start: bn, + }, [][32]byte{execCandidateDigest}) + if err != nil { + return fmt.Errorf("filter exec config promoted: %w", err) + } + if !pEvent.Next() { + return fmt.Errorf("exec config not promoted") + } + // check that candidate digest is empty. + execCandidateDigest, err = ccipHome.GetCandidateDigest(nil, donID, execConfig.PluginType) + if err != nil { + return fmt.Errorf("get exec candidate digest 2nd time: %w", err) + } + + if execCandidateDigest != [32]byte{} { + return fmt.Errorf("candidate digest is nonempty after promotion, expected empty") + } + + // check that active digest is non-empty. + execActiveDigest, err := ccipHome.GetActiveDigest(nil, donID, uint8(cctypes.PluginTypeCCIPExec)) + if err != nil { + return fmt.Errorf("get active exec digest: %w", err) + } + + if execActiveDigest == [32]byte{} { + return fmt.Errorf("active exec digest is empty, expected nonempty") + } + + execConfigs, err := ccipHome.GetAllConfigs(nil, donID, uint8(cctypes.PluginTypeCCIPExec)) + if err != nil { + return fmt.Errorf("get all exec configs 2nd time: %w", err) + } + + // print the above info + fmt.Printf("completed exec DON creation and promotion: donID: %d execCandidateDigest: %x, execActiveDigest: %x, execCandidateDigestFromGetAllConfigs: %x, execActiveDigestFromGetAllConfigs: %x\n", + donID, execCandidateDigest, execActiveDigest, execConfigs.CandidateConfig.ConfigDigest, execConfigs.ActiveConfig.ConfigDigest) + + return nil +} + +// SetCandidateCommitPluginWithAddDonOps sets the candidate commit config by calling setCandidate on CCIPHome contract through the AddDON call on CapReg contract +// This should be done first before calling any other UpdateDON calls +// This proposes to set up OCR3 config for the commit plugin for the DON +func NewDonWithCandidateOp( + donID uint32, + pluginConfig ccip_home.CCIPHomeOCR3Config, + capReg *capabilities_registry.CapabilitiesRegistry, + nodes deployment.Nodes, +) (mcms.Operation, error) { + encodedSetCandidateCall, err := CCIPHomeABI.Pack( + "setCandidate", + donID, + pluginConfig.PluginType, + pluginConfig, + [32]byte{}, + ) + if err != nil { + return mcms.Operation{}, fmt.Errorf("pack set candidate call: %w", err) + } + addDonTx, err := capReg.AddDON(deployment.SimTransactOpts(), nodes.PeerIDs(), []capabilities_registry.CapabilitiesRegistryCapabilityConfiguration{ + { + CapabilityId: CCIPCapabilityID, + Config: encodedSetCandidateCall, + }, + }, false, false, nodes.DefaultF()) + if err != nil { + return mcms.Operation{}, fmt.Errorf("could not generate add don tx w/ commit config: %w", err) + } + return mcms.Operation{ + To: capReg.Address(), + Data: addDonTx.Data(), + Value: big.NewInt(0), + }, nil +} + +// ValidateCCIPHomeConfigSetUp checks that the commit and exec active and candidate configs are set up correctly +func ValidateCCIPHomeConfigSetUp( + capReg *capabilities_registry.CapabilitiesRegistry, + ccipHome *ccip_home.CCIPHome, + chainSel uint64, +) error { + // fetch DONID + donID, err := DonIDForChain(capReg, ccipHome, chainSel) + if err != nil { + return fmt.Errorf("fetch don id for chain: %w", err) + } + // final sanity checks on configs. + commitConfigs, err := ccipHome.GetAllConfigs(&bind.CallOpts{ + //Pending: true, + }, donID, uint8(cctypes.PluginTypeCCIPCommit)) + if err != nil { + return fmt.Errorf("get all commit configs: %w", err) + } + commitActiveDigest, err := ccipHome.GetActiveDigest(nil, donID, uint8(cctypes.PluginTypeCCIPCommit)) + if err != nil { + return fmt.Errorf("get active commit digest: %w", err) + } + commitCandidateDigest, err := ccipHome.GetCandidateDigest(nil, donID, uint8(cctypes.PluginTypeCCIPCommit)) + if err != nil { + return fmt.Errorf("get commit candidate digest: %w", err) + } + if commitConfigs.ActiveConfig.ConfigDigest == [32]byte{} { + return fmt.Errorf( + "active config digest is empty for commit, expected nonempty, donID: %d, cfg: %+v, config digest from GetActiveDigest call: %x, config digest from GetCandidateDigest call: %x", + donID, commitConfigs.ActiveConfig, commitActiveDigest, commitCandidateDigest) + } + if commitConfigs.CandidateConfig.ConfigDigest != [32]byte{} { + return fmt.Errorf( + "candidate config digest is nonempty for commit, expected empty, donID: %d, cfg: %+v, config digest from GetCandidateDigest call: %x, config digest from GetActiveDigest call: %x", + donID, commitConfigs.CandidateConfig, commitCandidateDigest, commitActiveDigest) + } + + execConfigs, err := ccipHome.GetAllConfigs(nil, donID, uint8(cctypes.PluginTypeCCIPExec)) + if err != nil { + return fmt.Errorf("get all exec configs: %w", err) + } + if execConfigs.ActiveConfig.ConfigDigest == [32]byte{} { + return fmt.Errorf("active config digest is empty for exec, expected nonempty, cfg: %v", execConfigs.ActiveConfig) + } + if execConfigs.CandidateConfig.ConfigDigest != [32]byte{} { + return fmt.Errorf("candidate config digest is nonempty for exec, expected empty, cfg: %v", execConfigs.CandidateConfig) + } + return nil +} + +func setupCommitDON( + donID uint32, + commitConfig ccip_home.CCIPHomeOCR3Config, + capReg *capabilities_registry.CapabilitiesRegistry, + home deployment.Chain, + nodes deployment.Nodes, + ccipHome *ccip_home.CCIPHome, +) error { + encodedSetCandidateCall, err := CCIPHomeABI.Pack( + "setCandidate", + donID, + commitConfig.PluginType, + commitConfig, + [32]byte{}, + ) + if err != nil { + return fmt.Errorf("pack set candidate call: %w", err) + } + tx, err := capReg.AddDON(home.DeployerKey, nodes.PeerIDs(), []capabilities_registry.CapabilitiesRegistryCapabilityConfiguration{ + { + CapabilityId: CCIPCapabilityID, + Config: encodedSetCandidateCall, + }, + }, false, false, nodes.DefaultF()) + if err != nil { + return fmt.Errorf("add don w/ commit config: %w", err) + } + + if _, err := deployment.ConfirmIfNoError(home, tx, err); err != nil { + return fmt.Errorf("confirm add don w/ commit config: %w", err) + } + + commitCandidateDigest, err := ccipHome.GetCandidateDigest(nil, donID, commitConfig.PluginType) + if err != nil { + return fmt.Errorf("get commit candidate digest: %w", err) + } + + if commitCandidateDigest == [32]byte{} { + return fmt.Errorf("candidate digest is empty, expected nonempty") + } + fmt.Printf("commit candidate digest after setCandidate: %x\n", commitCandidateDigest) + + encodedPromotionCall, err := CCIPHomeABI.Pack( + "promoteCandidateAndRevokeActive", + donID, + commitConfig.PluginType, + commitCandidateDigest, + [32]byte{}, + ) + if err != nil { + return fmt.Errorf("pack promotion call: %w", err) + } + + tx, err = capReg.UpdateDON( + home.DeployerKey, + donID, + nodes.PeerIDs(), + []capabilities_registry.CapabilitiesRegistryCapabilityConfiguration{ + { + CapabilityId: CCIPCapabilityID, + Config: encodedPromotionCall, + }, + }, + false, + nodes.DefaultF(), + ) + if err != nil { + return fmt.Errorf("update don w/ commit config: %w", err) + } + + if _, err := deployment.ConfirmIfNoError(home, tx, err); err != nil { + return fmt.Errorf("confirm update don w/ commit config: %w", err) + } + + // check that candidate digest is empty. + commitCandidateDigest, err = ccipHome.GetCandidateDigest(nil, donID, commitConfig.PluginType) + if err != nil { + return fmt.Errorf("get commit candidate digest 2nd time: %w", err) + } + + if commitCandidateDigest != [32]byte{} { + return fmt.Errorf("candidate digest is nonempty after promotion, expected empty") + } + + // check that active digest is non-empty. + commitActiveDigest, err := ccipHome.GetActiveDigest(nil, donID, uint8(cctypes.PluginTypeCCIPCommit)) + if err != nil { + return fmt.Errorf("get active commit digest: %w", err) + } + + if commitActiveDigest == [32]byte{} { + return fmt.Errorf("active commit digest is empty, expected nonempty") + } + + commitConfigs, err := ccipHome.GetAllConfigs(nil, donID, uint8(cctypes.PluginTypeCCIPCommit)) + if err != nil { + return fmt.Errorf("get all commit configs 2nd time: %w", err) + } + + // print the above information + fmt.Printf("completed commit DON creation and promotion: donID: %d, commitCandidateDigest: %x, commitActiveDigest: %x, commitCandidateDigestFromGetAllConfigs: %x, commitActiveDigestFromGetAllConfigs: %x\n", + donID, commitCandidateDigest, commitActiveDigest, commitConfigs.CandidateConfig.ConfigDigest, commitConfigs.ActiveConfig.ConfigDigest) + + return nil +} + +func AddDON( + lggr logger.Logger, + ocrSecrets deployment.OCRSecrets, + capReg *capabilities_registry.CapabilitiesRegistry, + ccipHome *ccip_home.CCIPHome, + rmnHomeAddress common.Address, + offRamp *offramp.OffRamp, + feedChainSel uint64, + // Token address on Dest chain to aggregate address on feed chain + tokenInfo map[ccipocr3.UnknownEncodedAddress]pluginconfig.TokenInfo, + dest deployment.Chain, + home deployment.Chain, + nodes deployment.Nodes, + tokenConfigs []pluginconfig.TokenDataObserverConfig, +) error { + ocrConfigs, err := BuildOCR3ConfigForCCIPHome( + ocrSecrets, offRamp, dest, feedChainSel, tokenInfo, nodes, rmnHomeAddress, tokenConfigs) + if err != nil { + return err + } + err = CreateDON(lggr, capReg, ccipHome, ocrConfigs, home, dest.Selector, nodes) + if err != nil { + return err + } + don, err := LatestCCIPDON(capReg) + if err != nil { + return err + } + lggr.Infow("Added DON", "donID", don.Id) + + offrampOCR3Configs, err := BuildSetOCR3ConfigArgs(don.Id, ccipHome, dest.Selector) + if err != nil { + return err + } + lggr.Infow("Setting OCR3 Configs", + "offrampOCR3Configs", offrampOCR3Configs, + "configDigestCommit", hex.EncodeToString(offrampOCR3Configs[cctypes.PluginTypeCCIPCommit].ConfigDigest[:]), + "configDigestExec", hex.EncodeToString(offrampOCR3Configs[cctypes.PluginTypeCCIPExec].ConfigDigest[:]), + "chainSelector", dest.Selector, + ) + + tx, err := offRamp.SetOCR3Configs(dest.DeployerKey, offrampOCR3Configs) + if _, err := deployment.ConfirmIfNoError(dest, tx, err); err != nil { + return err + } + + mapOfframpOCR3Configs := make(map[cctypes.PluginType]offramp.MultiOCR3BaseOCRConfigArgs) + for _, config := range offrampOCR3Configs { + mapOfframpOCR3Configs[cctypes.PluginType(config.OcrPluginType)] = config + } + + for _, pluginType := range []cctypes.PluginType{cctypes.PluginTypeCCIPCommit, cctypes.PluginTypeCCIPExec} { + ocrConfig, err := offRamp.LatestConfigDetails(&bind.CallOpts{ + Context: context.Background(), + }, uint8(pluginType)) + if err != nil { + return err + } + // TODO: assertions to be done as part of full state + // resprentation validation CCIP-3047 + if mapOfframpOCR3Configs[pluginType].ConfigDigest != ocrConfig.ConfigInfo.ConfigDigest { + return fmt.Errorf("%s OCR3 config digest mismatch", pluginType.String()) + } + if mapOfframpOCR3Configs[pluginType].F != ocrConfig.ConfigInfo.F { + return fmt.Errorf("%s OCR3 config F mismatch", pluginType.String()) + } + if mapOfframpOCR3Configs[pluginType].IsSignatureVerificationEnabled != ocrConfig.ConfigInfo.IsSignatureVerificationEnabled { + return fmt.Errorf("%s OCR3 config signature verification mismatch", pluginType.String()) + } + if pluginType == cctypes.PluginTypeCCIPCommit { + // only commit will set signers, exec doesn't need them. + for i, signer := range mapOfframpOCR3Configs[pluginType].Signers { + if !bytes.Equal(signer.Bytes(), ocrConfig.Signers[i].Bytes()) { + return fmt.Errorf("%s OCR3 config signer mismatch", pluginType.String()) + } + } + } + for i, transmitter := range mapOfframpOCR3Configs[pluginType].Transmitters { + if !bytes.Equal(transmitter.Bytes(), ocrConfig.Transmitters[i].Bytes()) { + return fmt.Errorf("%s OCR3 config transmitter mismatch", pluginType.String()) + } + } + } + + return nil +} + +func ApplyChainConfigUpdatesOp( + e deployment.Environment, + state CCIPOnChainState, + homeChainSel uint64, + chains []uint64, +) (mcms.Operation, error) { + nodes, err := deployment.NodeInfo(e.NodeIDs, e.Offchain) + if err != nil { + return mcms.Operation{}, err + } + encodedExtraChainConfig, err := chainconfig.EncodeChainConfig(chainconfig.ChainConfig{ + GasPriceDeviationPPB: ccipocr3.NewBigIntFromInt64(1000), + DAGasPriceDeviationPPB: ccipocr3.NewBigIntFromInt64(0), + OptimisticConfirmations: 1, + }) + if err != nil { + return mcms.Operation{}, err + } + var chainConfigUpdates []ccip_home.CCIPHomeChainConfigArgs + for _, chainSel := range chains { + chainConfig := SetupConfigInfo(chainSel, nodes.NonBootstraps().PeerIDs(), + nodes.DefaultF(), encodedExtraChainConfig) + chainConfigUpdates = append(chainConfigUpdates, chainConfig) + } + + addChain, err := state.Chains[homeChainSel].CCIPHome.ApplyChainConfigUpdates( + deployment.SimTransactOpts(), + nil, + chainConfigUpdates, + ) + if err != nil { + return mcms.Operation{}, err + } + return mcms.Operation{ + To: state.Chains[homeChainSel].CCIPHome.Address(), + Data: addChain.Data(), + Value: big.NewInt(0), + }, nil +} diff --git a/deployment/ccip/deploy_test.go b/deployment/ccip/deploy_test.go new file mode 100644 index 00000000000..dc1927261d1 --- /dev/null +++ b/deployment/ccip/deploy_test.go @@ -0,0 +1,86 @@ +package ccipdeployment + +import ( + "encoding/json" + "fmt" + "testing" + + "github.com/stretchr/testify/require" + "go.uber.org/zap/zapcore" + + "github.com/smartcontractkit/chainlink/deployment" + "github.com/smartcontractkit/chainlink/deployment/environment/memory" + "github.com/smartcontractkit/chainlink/v2/core/logger" +) + +func TestDeployCCIPContracts(t *testing.T) { + lggr := logger.TestLogger(t) + e := memory.NewMemoryEnvironment(t, lggr, zapcore.InfoLevel, memory.MemoryEnvironmentConfig{ + Bootstraps: 1, + Chains: 2, + Nodes: 4, + }) + // Deploy all the CCIP contracts. + homeChainSel, feedChainSel := allocateCCIPChainSelectors(e.Chains) + _ = DeployTestContracts(t, lggr, e.ExistingAddresses, homeChainSel, feedChainSel, e.Chains, MockLinkPrice, MockWethPrice) + + nodes, err := deployment.NodeInfo(e.NodeIDs, e.Offchain) + require.NoError(t, err) + + _, err = DeployHomeChain(lggr, e, e.ExistingAddresses, e.Chains[homeChainSel], + NewTestRMNStaticConfig(), + NewTestRMNDynamicConfig(), + NewTestNodeOperator(e.Chains[homeChainSel].DeployerKey.From), + map[string][][32]byte{ + "NodeOperator": nodes.NonBootstraps().PeerIDs(), + }, + ) + require.NoError(t, err) + // Load the state after deploying the cap reg and feeds. + s, err := LoadOnchainState(e) + require.NoError(t, err) + require.NotNil(t, s.Chains[homeChainSel].CapabilityRegistry) + require.NotNil(t, s.Chains[homeChainSel].CCIPHome) + require.NotNil(t, s.Chains[feedChainSel].USDFeeds) + + newAddresses := deployment.NewMemoryAddressBook() + err = DeployPrerequisiteChainContracts(e, newAddresses, e.AllChainSelectors()) + require.NoError(t, err) + require.NoError(t, e.ExistingAddresses.Merge(newAddresses)) + + newAddresses = deployment.NewMemoryAddressBook() + err = DeployCCIPContracts(e, newAddresses, DeployCCIPContractConfig{ + HomeChainSel: homeChainSel, + FeedChainSel: feedChainSel, + ChainsToDeploy: e.AllChainSelectors(), + TokenConfig: NewTokenConfig(), + MCMSConfig: NewTestMCMSConfig(t, e), + OCRSecrets: deployment.XXXGenerateTestOCRSecrets(), + }) + require.NoError(t, err) + require.NoError(t, e.ExistingAddresses.Merge(newAddresses)) + state, err := LoadOnchainState(e) + require.NoError(t, err) + snap, err := state.View(e.AllChainSelectors()) + require.NoError(t, err) + + // Assert expect every deployed address to be in the address book. + // TODO (CCIP-3047): Add the rest of CCIPv2 representation + b, err := json.MarshalIndent(snap, "", " ") + require.NoError(t, err) + fmt.Println(string(b)) +} + +func TestJobSpecGeneration(t *testing.T) { + lggr := logger.TestLogger(t) + e := memory.NewMemoryEnvironment(t, lggr, zapcore.InfoLevel, memory.MemoryEnvironmentConfig{ + Chains: 1, + Nodes: 1, + }) + js, err := NewCCIPJobSpecs(e.NodeIDs, e.Offchain) + require.NoError(t, err) + for node, jb := range js { + fmt.Println(node, jb) + } + // TODO: Add job assertions +} diff --git a/deployment/ccip/changeset/cs_jobspec.go b/deployment/ccip/jobs.go similarity index 60% rename from deployment/ccip/changeset/cs_jobspec.go rename to deployment/ccip/jobs.go index 2551f193f47..b7ffed45cac 100644 --- a/deployment/ccip/changeset/cs_jobspec.go +++ b/deployment/ccip/jobs.go @@ -1,28 +1,24 @@ -package changeset +package ccipdeployment import ( - "github.com/smartcontractkit/ccip-owner-contracts/pkg/proposal/timelock" - "github.com/smartcontractkit/chainlink/deployment" - "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/internal" "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/validate" "github.com/smartcontractkit/chainlink/v2/core/services/relay" ) -var _ deployment.ChangeSet[any] = CCIPCapabilityJobspec - -// CCIPCapabilityJobspec returns the job specs for the CCIP capability. -// The caller needs to propose these job specs to the offchain system. -func CCIPCapabilityJobspec(env deployment.Environment, _ any) (deployment.ChangesetOutput, error) { - nodes, err := deployment.NodeInfo(env.NodeIDs, env.Offchain) +// In our case, the only address needed is the cap registry which is actually an env var. +// and will pre-exist for our deployment. So the job specs only depend on the environment operators. +func NewCCIPJobSpecs(nodeIds []string, oc deployment.OffchainClient) (map[string][]string, error) { + nodes, err := deployment.NodeInfo(nodeIds, oc) if err != nil { - return deployment.ChangesetOutput{}, err + return nil, err } // Generate a set of brand new job specs for CCIP for a specific environment // (including NOPs) and new addresses. // We want to assign one CCIP capability job to each node. And node with // an addr we'll list as bootstrapper. // Find the bootstrap nodes + nodesToJobSpecs := make(map[string][]string) for _, node := range nodes { var spec string @@ -30,8 +26,8 @@ func CCIPCapabilityJobspec(env deployment.Environment, _ any) (deployment.Change if !node.IsBootstrap { spec, err = validate.NewCCIPSpecToml(validate.SpecArgs{ P2PV2Bootstrappers: nodes.BootstrapLocators(), - CapabilityVersion: internal.CapabilityVersion, - CapabilityLabelledName: internal.CapabilityLabelledName, + CapabilityVersion: CapabilityVersion, + CapabilityLabelledName: CapabilityLabelledName, OCRKeyBundleIDs: map[string]string{ // TODO: Validate that that all EVM chains are using the same keybundle. relay.NetworkEVM: node.FirstOCRKeybundle().KeyBundleID, @@ -43,8 +39,8 @@ func CCIPCapabilityJobspec(env deployment.Environment, _ any) (deployment.Change } else { spec, err = validate.NewCCIPSpecToml(validate.SpecArgs{ P2PV2Bootstrappers: []string{}, // Intentionally empty for bootstraps. - CapabilityVersion: internal.CapabilityVersion, - CapabilityLabelledName: internal.CapabilityLabelledName, + CapabilityVersion: CapabilityVersion, + CapabilityLabelledName: CapabilityLabelledName, OCRKeyBundleIDs: map[string]string{}, // TODO: validate that all EVM chains are using the same keybundle P2PKeyID: node.PeerID.String(), @@ -53,13 +49,9 @@ func CCIPCapabilityJobspec(env deployment.Environment, _ any) (deployment.Change }) } if err != nil { - return deployment.ChangesetOutput{}, err + return nil, err } nodesToJobSpecs[node.NodeID] = append(nodesToJobSpecs[node.NodeID], spec) } - return deployment.ChangesetOutput{ - Proposals: []timelock.MCMSWithTimelockProposal{}, - AddressBook: nil, - JobSpecs: nodesToJobSpecs, - }, nil + return nodesToJobSpecs, nil } diff --git a/deployment/ccip/ownership.go b/deployment/ccip/ownership.go new file mode 100644 index 00000000000..ebc3ed60d09 --- /dev/null +++ b/deployment/ccip/ownership.go @@ -0,0 +1,37 @@ +package ccipdeployment + +import ( + "testing" + + "github.com/stretchr/testify/require" + + "github.com/smartcontractkit/chainlink/deployment" +) + +func TransferAllOwnership(t *testing.T, state CCIPOnChainState, homeCS uint64, e deployment.Environment) { + for _, source := range e.AllChainSelectors() { + if state.Chains[source].OnRamp != nil { + tx, err := state.Chains[source].OnRamp.TransferOwnership(e.Chains[source].DeployerKey, state.Chains[source].Timelock.Address()) + require.NoError(t, err) + _, err = deployment.ConfirmIfNoError(e.Chains[source], tx, err) + require.NoError(t, err) + } + if state.Chains[source].FeeQuoter != nil { + tx, err := state.Chains[source].FeeQuoter.TransferOwnership(e.Chains[source].DeployerKey, state.Chains[source].Timelock.Address()) + require.NoError(t, err) + _, err = deployment.ConfirmIfNoError(e.Chains[source], tx, err) + require.NoError(t, err) + } + // TODO: add offramp and commit stores + + } + // Transfer CR contract ownership + tx, err := state.Chains[homeCS].CapabilityRegistry.TransferOwnership(e.Chains[homeCS].DeployerKey, state.Chains[homeCS].Timelock.Address()) + require.NoError(t, err) + _, err = deployment.ConfirmIfNoError(e.Chains[homeCS], tx, err) + require.NoError(t, err) + tx, err = state.Chains[homeCS].CCIPHome.TransferOwnership(e.Chains[homeCS].DeployerKey, state.Chains[homeCS].Timelock.Address()) + require.NoError(t, err) + _, err = deployment.ConfirmIfNoError(e.Chains[homeCS], tx, err) + require.NoError(t, err) +} diff --git a/deployment/ccip/propose.go b/deployment/ccip/propose.go new file mode 100644 index 00000000000..9d6ac417968 --- /dev/null +++ b/deployment/ccip/propose.go @@ -0,0 +1,247 @@ +package ccipdeployment + +import ( + "bytes" + "context" + "crypto/ecdsa" + "fmt" + "math/big" + "testing" + "time" + + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/crypto" + "github.com/smartcontractkit/ccip-owner-contracts/pkg/config" + owner_helpers "github.com/smartcontractkit/ccip-owner-contracts/pkg/gethwrappers" + "github.com/smartcontractkit/ccip-owner-contracts/pkg/proposal/mcms" + "github.com/smartcontractkit/ccip-owner-contracts/pkg/proposal/timelock" + chainsel "github.com/smartcontractkit/chain-selectors" + "github.com/stretchr/testify/require" + + mapset "github.com/deckarep/golang-set/v2" + + "github.com/smartcontractkit/chainlink/deployment" +) + +var ( + TestXXXMCMSSigner *ecdsa.PrivateKey +) + +func init() { + key, err := crypto.GenerateKey() + if err != nil { + panic(err) + } + TestXXXMCMSSigner = key +} + +func SingleGroupMCMS(t *testing.T) config.Config { + publicKey := TestXXXMCMSSigner.Public().(*ecdsa.PublicKey) + // Convert the public key to an Ethereum address + address := crypto.PubkeyToAddress(*publicKey) + c, err := config.NewConfig(1, []common.Address{address}, []config.Config{}) + require.NoError(t, err) + return *c +} + +func NewTestMCMSConfig(t *testing.T, e deployment.Environment) MCMSConfig { + c := SingleGroupMCMS(t) + // All deployer keys can execute. + var executors []common.Address + for _, chain := range e.Chains { + executors = append(executors, chain.DeployerKey.From) + } + return MCMSConfig{ + Admin: c, + Bypasser: c, + Canceller: c, + Executors: executors, + Proposer: c, + } +} + +func SignProposal(t *testing.T, env deployment.Environment, proposal *timelock.MCMSWithTimelockProposal) *mcms.Executor { + executorClients := make(map[mcms.ChainIdentifier]mcms.ContractDeployBackend) + for _, chain := range env.Chains { + chainselc, exists := chainsel.ChainBySelector(chain.Selector) + require.True(t, exists) + chainSel := mcms.ChainIdentifier(chainselc.Selector) + executorClients[chainSel] = chain.Client + } + executor, err := proposal.ToExecutor(true) + require.NoError(t, err) + payload, err := executor.SigningHash() + require.NoError(t, err) + // Sign the payload + sig, err := crypto.Sign(payload.Bytes(), TestXXXMCMSSigner) + require.NoError(t, err) + mcmSig, err := mcms.NewSignatureFromBytes(sig) + require.NoError(t, err) + executor.Proposal.AddSignature(mcmSig) + require.NoError(t, executor.Proposal.Validate()) + return executor +} + +func ExecuteProposal(t *testing.T, env deployment.Environment, executor *mcms.Executor, + state CCIPOnChainState, sel uint64) { + t.Log("Executing proposal on chain", sel) + // Set the root. + tx, err2 := executor.SetRootOnChain(env.Chains[sel].Client, env.Chains[sel].DeployerKey, mcms.ChainIdentifier(sel)) + if err2 != nil { + require.NoError(t, deployment.MaybeDataErr(err2)) + } + _, err2 = env.Chains[sel].Confirm(tx) + require.NoError(t, err2) + + // TODO: This sort of helper probably should move to the MCMS lib. + // Execute all the transactions in the proposal which are for this chain. + for _, chainOp := range executor.Operations[mcms.ChainIdentifier(sel)] { + for idx, op := range executor.ChainAgnosticOps { + if bytes.Equal(op.Data, chainOp.Data) && op.To == chainOp.To { + opTx, err3 := executor.ExecuteOnChain(env.Chains[sel].Client, env.Chains[sel].DeployerKey, idx) + require.NoError(t, err3) + block, err3 := env.Chains[sel].Confirm(opTx) + require.NoError(t, err3) + t.Log("executed", chainOp) + it, err3 := state.Chains[sel].Timelock.FilterCallScheduled(&bind.FilterOpts{ + Start: block, + End: &block, + Context: context.Background(), + }, nil, nil) + require.NoError(t, err3) + var calls []owner_helpers.RBACTimelockCall + var pred, salt [32]byte + for it.Next() { + // Note these are the same for the whole batch, can overwrite + pred = it.Event.Predecessor + salt = it.Event.Salt + t.Log("scheduled", it.Event) + calls = append(calls, owner_helpers.RBACTimelockCall{ + Target: it.Event.Target, + Data: it.Event.Data, + Value: it.Event.Value, + }) + } + tx, err := state.Chains[sel].Timelock.ExecuteBatch( + env.Chains[sel].DeployerKey, calls, pred, salt) + require.NoError(t, err) + _, err = env.Chains[sel].Confirm(tx) + require.NoError(t, err) + } + } + } +} + +func GenerateAcceptOwnershipProposal( + state CCIPOnChainState, + homeChain uint64, + chains []uint64, +) (*timelock.MCMSWithTimelockProposal, error) { + // TODO: Accept rest of contracts + var batches []timelock.BatchChainOperation + for _, sel := range chains { + chain, _ := chainsel.ChainBySelector(sel) + acceptOnRamp, err := state.Chains[sel].OnRamp.AcceptOwnership(deployment.SimTransactOpts()) + if err != nil { + return nil, err + } + acceptFeeQuoter, err := state.Chains[sel].FeeQuoter.AcceptOwnership(deployment.SimTransactOpts()) + if err != nil { + return nil, err + } + chainSel := mcms.ChainIdentifier(chain.Selector) + batches = append(batches, timelock.BatchChainOperation{ + ChainIdentifier: chainSel, + Batch: []mcms.Operation{ + { + To: state.Chains[sel].OnRamp.Address(), + Data: acceptOnRamp.Data(), + Value: big.NewInt(0), + }, + { + To: state.Chains[sel].FeeQuoter.Address(), + Data: acceptFeeQuoter.Data(), + Value: big.NewInt(0), + }, + }, + }) + } + + acceptCR, err := state.Chains[homeChain].CapabilityRegistry.AcceptOwnership(deployment.SimTransactOpts()) + if err != nil { + return nil, err + } + acceptCCIPConfig, err := state.Chains[homeChain].CCIPHome.AcceptOwnership(deployment.SimTransactOpts()) + if err != nil { + return nil, err + } + homeChainID := mcms.ChainIdentifier(homeChain) + batches = append(batches, timelock.BatchChainOperation{ + ChainIdentifier: homeChainID, + Batch: []mcms.Operation{ + { + To: state.Chains[homeChain].CapabilityRegistry.Address(), + Data: acceptCR.Data(), + Value: big.NewInt(0), + }, + { + To: state.Chains[homeChain].CCIPHome.Address(), + Data: acceptCCIPConfig.Data(), + Value: big.NewInt(0), + }, + }, + }) + + return BuildProposalFromBatches(state, batches, "accept ownership operations", 0) +} + +func BuildProposalMetadata(state CCIPOnChainState, chains []uint64) (map[mcms.ChainIdentifier]common.Address, map[mcms.ChainIdentifier]mcms.ChainMetadata, error) { + tlAddressMap := make(map[mcms.ChainIdentifier]common.Address) + metaDataPerChain := make(map[mcms.ChainIdentifier]mcms.ChainMetadata) + for _, sel := range chains { + chainId := mcms.ChainIdentifier(sel) + tlAddressMap[chainId] = state.Chains[sel].Timelock.Address() + mcm := state.Chains[sel].ProposerMcm + opCount, err := mcm.GetOpCount(nil) + if err != nil { + return nil, nil, err + } + metaDataPerChain[chainId] = mcms.ChainMetadata{ + StartingOpCount: opCount.Uint64(), + MCMAddress: mcm.Address(), + } + } + return tlAddressMap, metaDataPerChain, nil +} + +// Given batches of operations, we build the metadata and timelock addresses of those opartions +// We then return a proposal that can be executed and signed +func BuildProposalFromBatches(state CCIPOnChainState, batches []timelock.BatchChainOperation, description string, minDelay time.Duration) (*timelock.MCMSWithTimelockProposal, error) { + if len(batches) == 0 { + return nil, fmt.Errorf("no operations in batch") + } + + chains := mapset.NewSet[uint64]() + for _, op := range batches { + chains.Add(uint64(op.ChainIdentifier)) + } + + tls, mcmsMd, err := BuildProposalMetadata(state, chains.ToSlice()) + if err != nil { + return nil, err + } + + return timelock.NewMCMSWithTimelockProposal( + "1", + 2004259681, // TODO: should be parameterized and based on current block timestamp. + []mcms.Signature{}, + false, + mcmsMd, + tls, + description, + batches, + timelock.Schedule, + minDelay.String(), + ) +} diff --git a/deployment/ccip/changeset/state.go b/deployment/ccip/state.go similarity index 51% rename from deployment/ccip/changeset/state.go rename to deployment/ccip/state.go index 792da317027..dcbe52524cf 100644 --- a/deployment/ccip/changeset/state.go +++ b/deployment/ccip/state.go @@ -1,18 +1,7 @@ -package changeset +package ccipdeployment import ( "fmt" - - "github.com/smartcontractkit/ccip-owner-contracts/pkg/gethwrappers" - - burn_mint_token_pool "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/burn_mint_token_pool_1_4_0" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/commit_store" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/evm_2_evm_offramp" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/evm_2_evm_onramp" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/price_registry_1_2_0" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/rmn_contract" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/shared/generated/erc20" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/mock_usdc_token_messenger" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/mock_usdc_token_transmitter" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/usdc_token_pool" @@ -20,6 +9,7 @@ import ( "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" "github.com/pkg/errors" + chainsel "github.com/smartcontractkit/chain-selectors" "github.com/smartcontractkit/chainlink/deployment" "github.com/smartcontractkit/chainlink/deployment/ccip/view" @@ -27,21 +17,21 @@ import ( "github.com/smartcontractkit/chainlink/deployment/ccip/view/v1_2" "github.com/smartcontractkit/chainlink/deployment/ccip/view/v1_5" "github.com/smartcontractkit/chainlink/deployment/ccip/view/v1_6" - commoncs "github.com/smartcontractkit/chainlink/deployment/common/changeset" - commontypes "github.com/smartcontractkit/chainlink/deployment/common/types" common_v1_0 "github.com/smartcontractkit/chainlink/deployment/common/view/v1_0" - + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/ccip_config" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/commit_store" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/mock_rmn_contract" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/registry_module_owner_custom" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/rmn_home" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/shared/generated/multicall3" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/ccip_home" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/fee_quoter" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/maybe_revert_message_receiver" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry_1_1_0" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/shared/generated/burn_mint_erc677" + owner_wrappers "github.com/smartcontractkit/ccip-owner-contracts/pkg/gethwrappers" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/nonce_manager" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/offramp" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/onramp" @@ -53,65 +43,29 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/aggregator_v3_interface" ) -var ( - // Legacy - CommitStore deployment.ContractType = "CommitStore" - PriceRegistry deployment.ContractType = "PriceRegistry" - RMN deployment.ContractType = "RMN" - - // Not legacy - MockRMN deployment.ContractType = "MockRMN" - RMNRemote deployment.ContractType = "RMNRemote" - ARMProxy deployment.ContractType = "ARMProxy" - WETH9 deployment.ContractType = "WETH9" - Router deployment.ContractType = "Router" - TokenAdminRegistry deployment.ContractType = "TokenAdminRegistry" - RegistryModule deployment.ContractType = "RegistryModuleOwnerCustom" - NonceManager deployment.ContractType = "NonceManager" - FeeQuoter deployment.ContractType = "FeeQuoter" - CCIPHome deployment.ContractType = "CCIPHome" - RMNHome deployment.ContractType = "RMNHome" - OnRamp deployment.ContractType = "OnRamp" - OffRamp deployment.ContractType = "OffRamp" - CapabilitiesRegistry deployment.ContractType = "CapabilitiesRegistry" - PriceFeed deployment.ContractType = "PriceFeed" - - // Test contracts. Note test router maps to a regular router contract. - TestRouter deployment.ContractType = "TestRouter" - Multicall3 deployment.ContractType = "Multicall3" - CCIPReceiver deployment.ContractType = "CCIPReceiver" - USDCMockTransmitter deployment.ContractType = "USDCMockTransmitter" - - // Pools - BurnMintToken deployment.ContractType = "BurnMintToken" - BurnMintTokenPool deployment.ContractType = "BurnMintTokenPool" - USDCToken deployment.ContractType = "USDCToken" - USDCTokenMessenger deployment.ContractType = "USDCTokenMessenger" - USDCTokenPool deployment.ContractType = "USDCTokenPool" -) - // CCIPChainState holds a Go binding for all the currently deployed CCIP contracts // on a chain. If a binding is nil, it means here is no such contract on the chain. type CCIPChainState struct { - commoncs.MCMSWithTimelockState - commoncs.LinkTokenState - commoncs.StaticLinkTokenState OnRamp *onramp.OnRamp OffRamp *offramp.OffRamp FeeQuoter *fee_quoter.FeeQuoter - RMNProxy *rmn_proxy_contract.RMNProxyContract + RMNProxyNew *rmn_proxy_contract.RMNProxyContract + RMNProxyExisting *rmn_proxy_contract.RMNProxyContract NonceManager *nonce_manager.NonceManager TokenAdminRegistry *token_admin_registry.TokenAdminRegistry RegistryModule *registry_module_owner_custom.RegistryModuleOwnerCustom Router *router.Router + CommitStore *commit_store.CommitStore Weth9 *weth9.WETH9 RMNRemote *rmn_remote.RMNRemote + MockRMN *mock_rmn_contract.MockRMNContract + // TODO: May need to support older link too + LinkToken *burn_mint_erc677.BurnMintERC677 // Map between token Descriptor (e.g. LinkSymbol, WethSymbol) // and the respective token contract // This is more of an illustration of how we'll have tokens, and it might need some work later to work properly. // Not all tokens will be burn and mint tokens. - BurnMintTokens677 map[TokenSymbol]*burn_mint_erc677.BurnMintERC677 - BurnMintTokenPools map[TokenSymbol]*burn_mint_token_pool.BurnMintTokenPool + BurnMintTokens677 map[TokenSymbol]*burn_mint_erc677.BurnMintERC677 // Map between token Symbol (e.g. LinkSymbol, WethSymbol) // and the respective aggregator USD feed contract USDFeeds map[TokenSymbol]*aggregator_v3_interface.AggregatorV3Interface @@ -120,6 +74,13 @@ type CCIPChainState struct { CapabilityRegistry *capabilities_registry.CapabilitiesRegistry CCIPHome *ccip_home.CCIPHome RMNHome *rmn_home.RMNHome + AdminMcm *owner_wrappers.ManyChainMultiSig + BypasserMcm *owner_wrappers.ManyChainMultiSig + CancellerMcm *owner_wrappers.ManyChainMultiSig + ProposerMcm *owner_wrappers.ManyChainMultiSig + Timelock *owner_wrappers.RBACTimelock + // TODO remove once staging upgraded. + CCIPConfig *ccip_config.CCIPConfig // Test contracts Receiver *maybe_revert_message_receiver.MaybeRevertMessageReceiver @@ -127,15 +88,6 @@ type CCIPChainState struct { USDCTokenPool *usdc_token_pool.USDCTokenPool MockUSDCTransmitter *mock_usdc_token_transmitter.MockE2EUSDCTransmitter MockUSDCTokenMessenger *mock_usdc_token_messenger.MockE2EUSDCTokenMessenger - Multicall3 *multicall3.Multicall3 - - // Legacy contracts - EVM2EVMOnRamp map[uint64]*evm_2_evm_onramp.EVM2EVMOnRamp // mapping of dest chain selector -> EVM2EVMOnRamp - CommitStore map[uint64]*commit_store.CommitStore // mapping of source chain selector -> CommitStore - EVM2EVMOffRamp map[uint64]*evm_2_evm_offramp.EVM2EVMOffRamp // mapping of source chain selector -> EVM2EVMOffRamp - MockRMN *mock_rmn_contract.MockRMNContract - PriceRegistry *price_registry_1_2_0.PriceRegistry - RMN *rmn_contract.RMNContract } func (c CCIPChainState) GenerateView() (view.ChainView, error) { @@ -143,44 +95,35 @@ func (c CCIPChainState) GenerateView() (view.ChainView, error) { if c.Router != nil { routerView, err := v1_2.GenerateRouterView(c.Router) if err != nil { - return chainView, errors.Wrapf(err, "failed to generate router view for router %s", c.Router.Address().String()) + return chainView, err } chainView.Router[c.Router.Address().Hex()] = routerView } if c.TokenAdminRegistry != nil { taView, err := v1_5.GenerateTokenAdminRegistryView(c.TokenAdminRegistry) if err != nil { - return chainView, errors.Wrapf(err, "failed to generate token admin registry view for token admin registry %s", c.TokenAdminRegistry.Address().String()) + return chainView, err } chainView.TokenAdminRegistry[c.TokenAdminRegistry.Address().Hex()] = taView } if c.NonceManager != nil { nmView, err := v1_6.GenerateNonceManagerView(c.NonceManager) if err != nil { - return chainView, errors.Wrapf(err, "failed to generate nonce manager view for nonce manager %s", c.NonceManager.Address().String()) + return chainView, err } chainView.NonceManager[c.NonceManager.Address().Hex()] = nmView } if c.RMNRemote != nil { rmnView, err := v1_6.GenerateRMNRemoteView(c.RMNRemote) if err != nil { - return chainView, errors.Wrapf(err, "failed to generate rmn remote view for rmn remote %s", c.RMNRemote.Address().String()) - } - chainView.RMNRemote[c.RMNRemote.Address().Hex()] = rmnView - } - - if c.RMNHome != nil { - rmnHomeView, err := v1_6.GenerateRMNHomeView(c.RMNHome) - if err != nil { - return chainView, errors.Wrapf(err, "failed to generate rmn home view for rmn home %s", c.RMNHome.Address().String()) + return chainView, err } - chainView.RMNHome[c.RMNHome.Address().Hex()] = rmnHomeView + chainView.RMN[c.RMNRemote.Address().Hex()] = rmnView } - if c.FeeQuoter != nil && c.Router != nil && c.TokenAdminRegistry != nil { fqView, err := v1_6.GenerateFeeQuoterView(c.FeeQuoter, c.Router, c.TokenAdminRegistry) if err != nil { - return chainView, errors.Wrapf(err, "failed to generate fee quoter view for fee quoter %s", c.FeeQuoter.Address().String()) + return chainView, err } chainView.FeeQuoter[c.FeeQuoter.Address().Hex()] = fqView } @@ -192,7 +135,7 @@ func (c CCIPChainState) GenerateView() (view.ChainView, error) { c.TokenAdminRegistry, ) if err != nil { - return chainView, errors.Wrapf(err, "failed to generate on ramp view for on ramp %s", c.OnRamp.Address().String()) + return chainView, err } chainView.OnRamp[c.OnRamp.Address().Hex()] = onRampView } @@ -203,156 +146,55 @@ func (c CCIPChainState) GenerateView() (view.ChainView, error) { c.Router, ) if err != nil { - return chainView, errors.Wrapf(err, "failed to generate off ramp view for off ramp %s", c.OffRamp.Address().String()) + return chainView, err } chainView.OffRamp[c.OffRamp.Address().Hex()] = offRampView } - if c.RMNProxy != nil { - rmnProxyView, err := v1_0.GenerateRMNProxyView(c.RMNProxy) + if c.CommitStore != nil { + commitStoreView, err := v1_5.GenerateCommitStoreView(c.CommitStore) if err != nil { - return chainView, errors.Wrapf(err, "failed to generate rmn proxy view for rmn proxy %s", c.RMNProxy.Address().String()) + return chainView, err } - chainView.RMNProxy[c.RMNProxy.Address().Hex()] = rmnProxyView + chainView.CommitStore[c.CommitStore.Address().Hex()] = commitStoreView } - if c.CCIPHome != nil && c.CapabilityRegistry != nil { - chView, err := v1_6.GenerateCCIPHomeView(c.CapabilityRegistry, c.CCIPHome) + + if c.RMNProxyNew != nil { + rmnProxyView, err := v1_0.GenerateRMNProxyView(c.RMNProxyNew) if err != nil { - return chainView, errors.Wrapf(err, "failed to generate CCIP home view for CCIP home %s", c.CCIPHome.Address()) + return chainView, err } - chainView.CCIPHome[c.CCIPHome.Address().Hex()] = chView + chainView.RMNProxy[c.RMNProxyNew.Address().Hex()] = rmnProxyView } if c.CapabilityRegistry != nil { capRegView, err := common_v1_0.GenerateCapabilityRegistryView(c.CapabilityRegistry) - if err != nil { - return chainView, errors.Wrapf(err, "failed to generate capability registry view for capability registry %s", c.CapabilityRegistry.Address().String()) - } - chainView.CapabilityRegistry[c.CapabilityRegistry.Address().Hex()] = capRegView - } - if c.MCMSWithTimelockState.Timelock != nil { - mcmsView, err := c.MCMSWithTimelockState.GenerateMCMSWithTimelockView() - if err != nil { - return chainView, errors.Wrapf(err, "failed to generate MCMS with timelock view for MCMS with timelock %s", c.MCMSWithTimelockState.Timelock.Address().String()) - } - chainView.MCMSWithTimelock = mcmsView - } - if c.LinkToken != nil { - linkTokenView, err := c.GenerateLinkView() - if err != nil { - return chainView, errors.Wrapf(err, "failed to generate link token view for link token %s", c.LinkToken.Address().String()) - } - chainView.LinkToken = linkTokenView - } - if c.StaticLinkToken != nil { - staticLinkTokenView, err := c.GenerateStaticLinkView() if err != nil { return chainView, err } - chainView.StaticLinkToken = staticLinkTokenView - } - // Legacy contracts - if c.CommitStore != nil { - for source, commitStore := range c.CommitStore { - commitStoreView, err := v1_5.GenerateCommitStoreView(commitStore) - if err != nil { - return chainView, errors.Wrapf(err, "failed to generate commit store view for commit store %s for source %d", commitStore.Address().String(), source) - } - chainView.CommitStore[commitStore.Address().Hex()] = commitStoreView - } - } - - if c.PriceRegistry != nil { - priceRegistryView, err := v1_2.GeneratePriceRegistryView(c.PriceRegistry) - if err != nil { - return chainView, errors.Wrapf(err, "failed to generate price registry view for price registry %s", c.PriceRegistry.Address().String()) - } - chainView.PriceRegistry[c.PriceRegistry.Address().String()] = priceRegistryView - } - - if c.RMN != nil { - rmnView, err := v1_5.GenerateRMNView(c.RMN) - if err != nil { - return chainView, errors.Wrapf(err, "failed to generate rmn view for rmn %s", c.RMN.Address().String()) - } - chainView.RMN[c.RMN.Address().Hex()] = rmnView - } - - if c.EVM2EVMOffRamp != nil { - for source, offRamp := range c.EVM2EVMOffRamp { - offRampView, err := v1_5.GenerateOffRampView(offRamp) - if err != nil { - return chainView, errors.Wrapf(err, "failed to generate off ramp view for off ramp %s for source %d", offRamp.Address().String(), source) - } - chainView.EVM2EVMOffRamp[offRamp.Address().Hex()] = offRampView - } - } - - if c.EVM2EVMOnRamp != nil { - for dest, onRamp := range c.EVM2EVMOnRamp { - onRampView, err := v1_5.GenerateOnRampView(onRamp) - if err != nil { - return chainView, errors.Wrapf(err, "failed to generate on ramp view for on ramp %s for dest %d", onRamp.Address().String(), dest) - } - chainView.EVM2EVMOnRamp[onRamp.Address().Hex()] = onRampView - } + chainView.CapabilityRegistry[c.CapabilityRegistry.Address().Hex()] = capRegView } - return chainView, nil } -// CCIPOnChainState state always derivable from an address book. +// Onchain state always derivable from an address book. // Offchain state always derivable from a list of nodeIds. // Note can translate this into Go struct needed for MCMS/Docs/UI. type CCIPOnChainState struct { // Populated go bindings for the appropriate version for all contracts. // We would hold 2 versions of each contract here. Once we upgrade we can phase out the old one. // When generating bindings, make sure the package name corresponds to the version. - Chains map[uint64]CCIPChainState - SolChains map[uint64]SolCCIPChainState -} - -func (s CCIPOnChainState) GetAllProposerMCMSForChains(chains []uint64) (map[uint64]*gethwrappers.ManyChainMultiSig, error) { - multiSigs := make(map[uint64]*gethwrappers.ManyChainMultiSig) - for _, chain := range chains { - chainState, ok := s.Chains[chain] - if !ok { - return nil, fmt.Errorf("chain %d not found", chain) - } - if chainState.ProposerMcm == nil { - return nil, fmt.Errorf("proposer mcm not found for chain %d", chain) - } - multiSigs[chain] = chainState.ProposerMcm - } - return multiSigs, nil -} - -func (s CCIPOnChainState) GetAllTimeLocksForChains(chains []uint64) (map[uint64]common.Address, error) { - timelocks := make(map[uint64]common.Address) - for _, chain := range chains { - chainState, ok := s.Chains[chain] - if !ok { - return nil, fmt.Errorf("chain %d not found", chain) - } - if chainState.Timelock == nil { - return nil, fmt.Errorf("timelock not found for chain %d", chain) - } - timelocks[chain] = chainState.Timelock.Address() - } - return timelocks, nil -} - -func (s CCIPOnChainState) SupportedChains() map[uint64]struct{} { - chains := make(map[uint64]struct{}) - for chain := range s.Chains { - chains[chain] = struct{}{} - } - return chains + Chains map[uint64]CCIPChainState } func (s CCIPOnChainState) View(chains []uint64) (map[string]view.ChainView, error) { m := make(map[string]view.ChainView) for _, chainSelector := range chains { - chainInfo, err := deployment.ChainInfo(chainSelector) + // TODO: Need a utility for this + chainid, err := chainsel.ChainIdFromSelector(chainSelector) + if err != nil { + return m, err + } + chainName, err := chainsel.NameFromChainId(chainid) if err != nil { return m, err } @@ -364,11 +206,7 @@ func (s CCIPOnChainState) View(chains []uint64) (map[string]view.ChainView, erro if err != nil { return m, err } - name := chainInfo.ChainName - if chainInfo.ChainName == "" { - name = fmt.Sprintf("%d", chainSelector) - } - m[name] = chainView + m[chainName] = chainView } return m, nil } @@ -397,35 +235,41 @@ func LoadOnchainState(e deployment.Environment) (CCIPOnChainState, error) { } // LoadChainState Loads all state for a chain into state +// Modifies map in place func LoadChainState(chain deployment.Chain, addresses map[string]deployment.TypeAndVersion) (CCIPChainState, error) { var state CCIPChainState - mcmsWithTimelock, err := commoncs.MaybeLoadMCMSWithTimelockChainState(chain, addresses) - if err != nil { - return state, err - } - state.MCMSWithTimelockState = *mcmsWithTimelock - - linkState, err := commoncs.MaybeLoadLinkTokenChainState(chain, addresses) - if err != nil { - return state, err - } - state.LinkTokenState = *linkState - staticLinkState, err := commoncs.MaybeLoadStaticLinkTokenState(chain, addresses) - if err != nil { - return state, err - } - state.StaticLinkTokenState = *staticLinkState for address, tvStr := range addresses { switch tvStr.String() { - case deployment.NewTypeAndVersion(commontypes.RBACTimelock, deployment.Version1_0_0).String(), - deployment.NewTypeAndVersion(commontypes.CallProxy, deployment.Version1_0_0).String(), - deployment.NewTypeAndVersion(commontypes.ProposerManyChainMultisig, deployment.Version1_0_0).String(), - deployment.NewTypeAndVersion(commontypes.CancellerManyChainMultisig, deployment.Version1_0_0).String(), - deployment.NewTypeAndVersion(commontypes.BypasserManyChainMultisig, deployment.Version1_0_0).String(), - deployment.NewTypeAndVersion(commontypes.LinkToken, deployment.Version1_0_0).String(), - deployment.NewTypeAndVersion(commontypes.StaticLinkToken, deployment.Version1_0_0).String(): - // Skip common contracts, they are already loaded. - continue + case deployment.NewTypeAndVersion(RBACTimelock, deployment.Version1_0_0).String(): + tl, err := owner_wrappers.NewRBACTimelock(common.HexToAddress(address), chain.Client) + if err != nil { + return state, err + } + state.Timelock = tl + case deployment.NewTypeAndVersion(AdminManyChainMultisig, deployment.Version1_0_0).String(): + mcms, err := owner_wrappers.NewManyChainMultiSig(common.HexToAddress(address), chain.Client) + if err != nil { + return state, err + } + state.AdminMcm = mcms + case deployment.NewTypeAndVersion(ProposerManyChainMultisig, deployment.Version1_0_0).String(): + mcms, err := owner_wrappers.NewManyChainMultiSig(common.HexToAddress(address), chain.Client) + if err != nil { + return state, err + } + state.ProposerMcm = mcms + case deployment.NewTypeAndVersion(BypasserManyChainMultisig, deployment.Version1_0_0).String(): + mcms, err := owner_wrappers.NewManyChainMultiSig(common.HexToAddress(address), chain.Client) + if err != nil { + return state, err + } + state.BypasserMcm = mcms + case deployment.NewTypeAndVersion(CancellerManyChainMultisig, deployment.Version1_0_0).String(): + mcms, err := owner_wrappers.NewManyChainMultiSig(common.HexToAddress(address), chain.Client) + if err != nil { + return state, err + } + state.CancellerMcm = mcms case deployment.NewTypeAndVersion(CapabilitiesRegistry, deployment.Version1_0_0).String(): cr, err := capabilities_registry.NewCapabilitiesRegistry(common.HexToAddress(address), chain.Client) if err != nil { @@ -449,7 +293,25 @@ func LoadChainState(chain deployment.Chain, addresses map[string]deployment.Type if err != nil { return state, err } - state.RMNProxy = armProxy + state.RMNProxyExisting = armProxy + case deployment.NewTypeAndVersion(ARMProxy, deployment.Version1_6_0_dev).String(): + armProxy, err := rmn_proxy_contract.NewRMNProxyContract(common.HexToAddress(address), chain.Client) + if err != nil { + return state, err + } + state.RMNProxyNew = armProxy + case deployment.NewTypeAndVersion(ARMProxy, deployment.Version1_6_0_dev).String(): + armProxy, err := rmn_proxy_contract.NewRMNProxyContract(common.HexToAddress(address), chain.Client) + if err != nil { + return state, err + } + state.RMNProxyNew = armProxy + case deployment.NewTypeAndVersion(MockRMN, deployment.Version1_0_0).String(): + mockRMN, err := mock_rmn_contract.NewMockRMNContract(common.HexToAddress(address), chain.Client) + if err != nil { + return state, err + } + state.MockRMN = mockRMN case deployment.NewTypeAndVersion(RMNRemote, deployment.Version1_6_0_dev).String(): rmnRemote, err := rmn_remote.NewRMNRemote(common.HexToAddress(address), chain.Client) if err != nil { @@ -474,6 +336,12 @@ func LoadChainState(chain deployment.Chain, addresses map[string]deployment.Type return state, err } state.NonceManager = nm + case deployment.NewTypeAndVersion(CommitStore, deployment.Version1_5_0).String(): + cs, err := commit_store.NewCommitStore(common.HexToAddress(address), chain.Client) + if err != nil { + return state, err + } + state.CommitStore = cs case deployment.NewTypeAndVersion(TokenAdminRegistry, deployment.Version1_5_0).String(): tm, err := token_admin_registry.NewTokenAdminRegistry(common.HexToAddress(address), chain.Client) if err != nil { @@ -504,6 +372,12 @@ func LoadChainState(chain deployment.Chain, addresses map[string]deployment.Type return state, err } state.FeeQuoter = fq + case deployment.NewTypeAndVersion(LinkToken, deployment.Version1_0_0).String(): + lt, err := burn_mint_erc677.NewBurnMintERC677(common.HexToAddress(address), chain.Client) + if err != nil { + return state, err + } + state.LinkToken = lt case deployment.NewTypeAndVersion(USDCToken, deployment.Version1_0_0).String(): ut, err := burn_mint_erc677.NewBurnMintERC677(common.HexToAddress(address), chain.Client) if err != nil { @@ -536,18 +410,19 @@ func LoadChainState(chain deployment.Chain, addresses map[string]deployment.Type return state, err } state.CCIPHome = ccipHome - case deployment.NewTypeAndVersion(CCIPReceiver, deployment.Version1_0_0).String(): - mr, err := maybe_revert_message_receiver.NewMaybeRevertMessageReceiver(common.HexToAddress(address), chain.Client) + case deployment.NewTypeAndVersion(CCIPConfig, deployment.Version1_0_0).String(): + // TODO: Remove once staging upgraded. + ccipConfig, err := ccip_config.NewCCIPConfig(common.HexToAddress(address), chain.Client) if err != nil { return state, err } - state.Receiver = mr - case deployment.NewTypeAndVersion(Multicall3, deployment.Version1_0_0).String(): - mc, err := multicall3.NewMulticall3(common.HexToAddress(address), chain.Client) + state.CCIPConfig = ccipConfig + case deployment.NewTypeAndVersion(CCIPReceiver, deployment.Version1_0_0).String(): + mr, err := maybe_revert_message_receiver.NewMaybeRevertMessageReceiver(common.HexToAddress(address), chain.Client) if err != nil { return state, err } - state.Multicall3 = mc + state.Receiver = mr case deployment.NewTypeAndVersion(PriceFeed, deployment.Version1_0_0).String(): feed, err := aggregator_v3_interface.NewAggregatorV3Interface(common.HexToAddress(address), chain.Client) if err != nil { @@ -565,98 +440,6 @@ func LoadChainState(chain deployment.Chain, addresses map[string]deployment.Type return state, fmt.Errorf("unknown feed description %s", desc) } state.USDFeeds[key] = feed - case deployment.NewTypeAndVersion(BurnMintTokenPool, deployment.Version1_5_1).String(): - pool, err := burn_mint_token_pool.NewBurnMintTokenPool(common.HexToAddress(address), chain.Client) - if err != nil { - return state, err - } - if state.BurnMintTokenPools == nil { - state.BurnMintTokenPools = make(map[TokenSymbol]*burn_mint_token_pool.BurnMintTokenPool) - } - tokAddress, err := pool.GetToken(nil) - if err != nil { - return state, err - } - tok, err := erc20.NewERC20(tokAddress, chain.Client) - if err != nil { - return state, err - } - symbol, err := tok.Symbol(nil) - if err != nil { - return state, err - } - state.BurnMintTokenPools[TokenSymbol(symbol)] = pool - case deployment.NewTypeAndVersion(BurnMintToken, deployment.Version1_0_0).String(): - tok, err := burn_mint_erc677.NewBurnMintERC677(common.HexToAddress(address), chain.Client) - if err != nil { - return state, err - } - if state.BurnMintTokens677 == nil { - state.BurnMintTokens677 = make(map[TokenSymbol]*burn_mint_erc677.BurnMintERC677) - } - symbol, err := tok.Symbol(nil) - if err != nil { - return state, fmt.Errorf("failed to get token symbol of token at %s: %w", address, err) - } - state.BurnMintTokens677[TokenSymbol(symbol)] = tok - // legacy addresses below - case deployment.NewTypeAndVersion(OnRamp, deployment.Version1_5_0).String(): - onRampC, err := evm_2_evm_onramp.NewEVM2EVMOnRamp(common.HexToAddress(address), chain.Client) - if err != nil { - return state, err - } - sCfg, err := onRampC.GetStaticConfig(nil) - if err != nil { - return state, fmt.Errorf("failed to get static config chain %s: %w", chain.String(), err) - } - if state.EVM2EVMOnRamp == nil { - state.EVM2EVMOnRamp = make(map[uint64]*evm_2_evm_onramp.EVM2EVMOnRamp) - } - state.EVM2EVMOnRamp[sCfg.DestChainSelector] = onRampC - case deployment.NewTypeAndVersion(OffRamp, deployment.Version1_5_0).String(): - offRamp, err := evm_2_evm_offramp.NewEVM2EVMOffRamp(common.HexToAddress(address), chain.Client) - if err != nil { - return state, err - } - sCfg, err := offRamp.GetStaticConfig(nil) - if err != nil { - return state, err - } - if state.EVM2EVMOffRamp == nil { - state.EVM2EVMOffRamp = make(map[uint64]*evm_2_evm_offramp.EVM2EVMOffRamp) - } - state.EVM2EVMOffRamp[sCfg.SourceChainSelector] = offRamp - case deployment.NewTypeAndVersion(CommitStore, deployment.Version1_5_0).String(): - commitStore, err := commit_store.NewCommitStore(common.HexToAddress(address), chain.Client) - if err != nil { - return state, err - } - sCfg, err := commitStore.GetStaticConfig(nil) - if err != nil { - return state, err - } - if state.CommitStore == nil { - state.CommitStore = make(map[uint64]*commit_store.CommitStore) - } - state.CommitStore[sCfg.SourceChainSelector] = commitStore - case deployment.NewTypeAndVersion(PriceRegistry, deployment.Version1_2_0).String(): - pr, err := price_registry_1_2_0.NewPriceRegistry(common.HexToAddress(address), chain.Client) - if err != nil { - return state, err - } - state.PriceRegistry = pr - case deployment.NewTypeAndVersion(RMN, deployment.Version1_5_0).String(): - rmnC, err := rmn_contract.NewRMNContract(common.HexToAddress(address), chain.Client) - if err != nil { - return state, err - } - state.RMN = rmnC - case deployment.NewTypeAndVersion(MockRMN, deployment.Version1_0_0).String(): - mockRMN, err := mock_rmn_contract.NewMockRMNContract(common.HexToAddress(address), chain.Client) - if err != nil { - return state, err - } - state.MockRMN = mockRMN default: return state, fmt.Errorf("unknown contract %s", tvStr) } diff --git a/deployment/ccip/changeset/test_assertions.go b/deployment/ccip/test_assertions.go similarity index 57% rename from deployment/ccip/changeset/test_assertions.go rename to deployment/ccip/test_assertions.go index bcfb49250d4..0c15c8b95ed 100644 --- a/deployment/ccip/changeset/test_assertions.go +++ b/deployment/ccip/test_assertions.go @@ -1,4 +1,4 @@ -package changeset +package ccipdeployment import ( "context" @@ -10,14 +10,11 @@ import ( "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" - "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "golang.org/x/sync/errgroup" "github.com/smartcontractkit/chainlink-ccip/pkg/types/ccipocr3" - commonutils "github.com/smartcontractkit/chainlink-common/pkg/utils" "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" - "github.com/smartcontractkit/chainlink/deployment/environment/memory" "github.com/smartcontractkit/chainlink/deployment" @@ -150,24 +147,15 @@ func ConfirmTokenPriceUpdated( return nil } -// SourceDestPair is represents a pair of source and destination chain selectors. -// Use this as a key in maps that need to identify sequence numbers, nonces, or -// other things that require identification. -type SourceDestPair struct { - SourceChainSelector uint64 - DestChainSelector uint64 -} - // ConfirmCommitForAllWithExpectedSeqNums waits for all chains in the environment to commit the given expectedSeqNums. -// expectedSeqNums is a map that maps a (source, dest) selector pair to the expected sequence number -// to confirm the commit for. +// expectedSeqNums is a map of destinationchain selector to expected sequence number // startBlocks is a map of destination chain selector to start block number to start watching from. // If startBlocks is nil, it will start watching from the latest block. func ConfirmCommitForAllWithExpectedSeqNums( t *testing.T, e deployment.Environment, state CCIPOnChainState, - expectedSeqNums map[SourceDestPair]uint64, + expectedSeqNums map[uint64]uint64, startBlocks map[uint64]*uint64, ) { var wg errgroup.Group @@ -184,26 +172,20 @@ func ConfirmCommitForAllWithExpectedSeqNums( startBlock = startBlocks[dstChain.Selector] } - expectedSeqNum, ok := expectedSeqNums[SourceDestPair{ - SourceChainSelector: srcChain.Selector, - DestChainSelector: dstChain.Selector, - }] - if !ok || expectedSeqNum == 0 { + if expectedSeqNums[dstChain.Selector] == 0 { return nil } - return commonutils.JustError(ConfirmCommitWithExpectedSeqNumRange( + return ConfirmCommitWithExpectedSeqNumRange( t, srcChain, dstChain, state.Chains[dstChain.Selector].OffRamp, startBlock, ccipocr3.SeqNumRange{ - ccipocr3.SeqNum(expectedSeqNum), - ccipocr3.SeqNum(expectedSeqNum), - }, - true, - )) + ccipocr3.SeqNum(expectedSeqNums[dstChain.Selector]), + ccipocr3.SeqNum(expectedSeqNums[dstChain.Selector]), + }) }) } } @@ -222,79 +204,12 @@ func ConfirmCommitForAllWithExpectedSeqNums( return false } }, - tests.WaitTimeout(t), - 2*time.Second, + 3*time.Minute, + 1*time.Second, "all commitments did not confirm", ) } -type commitReportTracker struct { - seenMessages map[uint64]map[uint64]bool -} - -func newCommitReportTracker(sourceChainSelector uint64, seqNrs ccipocr3.SeqNumRange) commitReportTracker { - seenMessages := make(map[uint64]map[uint64]bool) - seenMessages[sourceChainSelector] = make(map[uint64]bool) - - for i := seqNrs.Start(); i <= seqNrs.End(); i++ { - seenMessages[sourceChainSelector][uint64(i)] = false - } - return commitReportTracker{seenMessages: seenMessages} -} - -func (c *commitReportTracker) visitCommitReport(sourceChainSelector uint64, minSeqNr uint64, maxSeqNr uint64) { - if _, ok := c.seenMessages[sourceChainSelector]; !ok { - return - } - - for i := minSeqNr; i <= maxSeqNr; i++ { - c.seenMessages[sourceChainSelector][i] = true - } -} - -func (c *commitReportTracker) allCommited(sourceChainSelector uint64) bool { - for _, v := range c.seenMessages[sourceChainSelector] { - if !v { - return false - } - } - return true -} - -// ConfirmMultipleCommits waits for multiple ccipocr3.SeqNumRange to be committed by the Offramp. -// Waiting is done in parallel per every sourceChain/destChain (lane) passed as argument. -func ConfirmMultipleCommits( - t *testing.T, - chains map[uint64]deployment.Chain, - state map[uint64]CCIPChainState, - startBlocks map[uint64]*uint64, - enforceSingleCommit bool, - expectedSeqNums map[SourceDestPair]ccipocr3.SeqNumRange, -) error { - errGrp := &errgroup.Group{} - - for sourceDest, seqRange := range expectedSeqNums { - seqRange := seqRange - srcChain := sourceDest.SourceChainSelector - destChain := sourceDest.DestChainSelector - - errGrp.Go(func() error { - _, err := ConfirmCommitWithExpectedSeqNumRange( - t, - chains[srcChain], - chains[destChain], - state[destChain].OffRamp, - startBlocks[destChain], - seqRange, - enforceSingleCommit, - ) - return err - }) - } - - return errGrp.Wait() -} - // ConfirmCommitWithExpectedSeqNumRange waits for a commit report on the destination chain with the expected sequence number range. // startBlock is the block number to start watching from. // If startBlock is nil, it will start watching from the latest block. @@ -305,19 +220,16 @@ func ConfirmCommitWithExpectedSeqNumRange( offRamp *offramp.OffRamp, startBlock *uint64, expectedSeqNumRange ccipocr3.SeqNumRange, - enforceSingleCommit bool, -) (*offramp.OffRampCommitReportAccepted, error) { +) error { sink := make(chan *offramp.OffRampCommitReportAccepted) subscription, err := offRamp.WatchCommitReportAccepted(&bind.WatchOpts{ Context: context.Background(), Start: startBlock, }, sink) if err != nil { - return nil, fmt.Errorf("error to subscribe CommitReportAccepted : %w", err) + return fmt.Errorf("error to subscribe CommitReportAccepted : %w", err) } - seenMessages := newCommitReportTracker(src.Selector, expectedSeqNumRange) - defer subscription.Unsubscribe() var duration time.Duration deadline, ok := t.Deadline() @@ -353,49 +265,32 @@ func ConfirmCommitWithExpectedSeqNumRange( event := iter.Event if len(event.MerkleRoots) > 0 { for _, mr := range event.MerkleRoots { - t.Logf("Received commit report for [%d, %d] on selector %d from source selector %d expected seq nr range %s, token prices: %v, tx hash: %s", - mr.MinSeqNr, mr.MaxSeqNr, dest.Selector, src.Selector, expectedSeqNumRange.String(), event.PriceUpdates.TokenPriceUpdates, event.Raw.TxHash.String()) - seenMessages.visitCommitReport(src.Selector, mr.MinSeqNr, mr.MaxSeqNr) - if mr.SourceChainSelector == src.Selector && uint64(expectedSeqNumRange.Start()) >= mr.MinSeqNr && uint64(expectedSeqNumRange.End()) <= mr.MaxSeqNr { - t.Logf("All sequence numbers commited in a single report [%d, %d]", expectedSeqNumRange.Start(), expectedSeqNumRange.End()) - return event, nil - } - - if !enforceSingleCommit && seenMessages.allCommited(src.Selector) { - t.Logf("All sequence numbers already commited from range [%d, %d]", expectedSeqNumRange.Start(), expectedSeqNumRange.End()) - return event, nil + t.Logf("Received commit report for [%d, %d] on selector %d from source selector %d expected seq nr range %s, token prices: %v", + mr.MinSeqNr, mr.MaxSeqNr, dest.Selector, src.Selector, expectedSeqNumRange.String(), event.PriceUpdates.TokenPriceUpdates) + return nil } } } } case subErr := <-subscription.Err(): - return nil, fmt.Errorf("subscription error: %w", subErr) + return fmt.Errorf("subscription error: %w", subErr) case <-timer.C: - return nil, fmt.Errorf("timed out after waiting %s duration for commit report on chain selector %d from source selector %d expected seq nr range %s", + return fmt.Errorf("timed out after waiting %s duration for commit report on chain selector %d from source selector %d expected seq nr range %s", duration.String(), dest.Selector, src.Selector, expectedSeqNumRange.String()) case report := <-sink: if len(report.MerkleRoots) > 0 { // Check the interval of sequence numbers and make sure it matches // the expected range. for _, mr := range report.MerkleRoots { - t.Logf("Received commit report for [%d, %d] on selector %d from source selector %d expected seq nr range %s, token prices: %v", - mr.MinSeqNr, mr.MaxSeqNr, dest.Selector, src.Selector, expectedSeqNumRange.String(), report.PriceUpdates.TokenPriceUpdates) - - seenMessages.visitCommitReport(src.Selector, mr.MinSeqNr, mr.MaxSeqNr) - if mr.SourceChainSelector == src.Selector && uint64(expectedSeqNumRange.Start()) >= mr.MinSeqNr && uint64(expectedSeqNumRange.End()) <= mr.MaxSeqNr { - t.Logf("All sequence numbers commited in a single report [%d, %d]", expectedSeqNumRange.Start(), expectedSeqNumRange.End()) - return report, nil - } - - if !enforceSingleCommit && seenMessages.allCommited(src.Selector) { - t.Logf("All sequence numbers already commited from range [%d, %d]", expectedSeqNumRange.Start(), expectedSeqNumRange.End()) - return report, nil + t.Logf("Received commit report for [%d, %d] on selector %d from source selector %d expected seq nr range %s, token prices: %v", + mr.MinSeqNr, mr.MaxSeqNr, dest.Selector, src.Selector, expectedSeqNumRange.String(), report.PriceUpdates.TokenPriceUpdates) + return nil } } } @@ -403,24 +298,23 @@ func ConfirmCommitWithExpectedSeqNumRange( } } -// ConfirmExecWithSeqNrsForAll waits for all chains in the environment to execute the given expectedSeqNums. -// If successful, it returns a map that maps the SourceDestPair to the expected sequence number -// to its execution state. -// expectedSeqNums is a map of SourceDestPair to a slice of expected sequence numbers to be executed. +// ConfirmExecWithSeqNrForAll waits for all chains in the environment to execute the given expectedSeqNums. +// If successful, it returns a map that maps the expected sequence numbers to their respective execution state. +// expectedSeqNums is a map of destination chain selector to expected sequence number // startBlocks is a map of destination chain selector to start block number to start watching from. // If startBlocks is nil, it will start watching from the latest block. -func ConfirmExecWithSeqNrsForAll( +func ConfirmExecWithSeqNrForAll( t *testing.T, e deployment.Environment, state CCIPOnChainState, - expectedSeqNums map[SourceDestPair][]uint64, + expectedSeqNums map[uint64]uint64, startBlocks map[uint64]*uint64, -) (executionStates map[SourceDestPair]map[uint64]int) { +) (executionStates map[uint64]int) { var ( wg errgroup.Group mx sync.Mutex ) - executionStates = make(map[SourceDestPair]map[uint64]int) + executionStates = make(map[uint64]int) for src, srcChain := range e.Chains { for dest, dstChain := range e.Chains { if src == dest { @@ -434,60 +328,47 @@ func ConfirmExecWithSeqNrsForAll( startBlock = startBlocks[dstChain.Selector] } - expectedSeqNum, ok := expectedSeqNums[SourceDestPair{ - SourceChainSelector: srcChain.Selector, - DestChainSelector: dstChain.Selector, - }] - if !ok || len(expectedSeqNum) == 0 { + if expectedSeqNums[dstChain.Selector] == 0 { return nil } - innerExecutionStates, err := ConfirmExecWithSeqNrs( + executionState, err := ConfirmExecWithSeqNr( t, srcChain, dstChain, state.Chains[dstChain.Selector].OffRamp, startBlock, - expectedSeqNum, + expectedSeqNums[dstChain.Selector], ) if err != nil { return err } mx.Lock() - executionStates[SourceDestPair{ - SourceChainSelector: srcChain.Selector, - DestChainSelector: dstChain.Selector, - }] = innerExecutionStates + executionStates[expectedSeqNums[dstChain.Selector]] = executionState mx.Unlock() return nil }) } } - require.NoError(t, wg.Wait()) return executionStates } -// ConfirmExecWithSeqNrs waits for an execution state change on the destination chain with the expected sequence number. +// ConfirmExecWithSeqNr waits for an execution state change on the destination chain with the expected sequence number. // startBlock is the block number to start watching from. // If startBlock is nil, it will start watching from the latest block. -// Returns a map that maps the expected sequence number to its execution state. -func ConfirmExecWithSeqNrs( +func ConfirmExecWithSeqNr( t *testing.T, source, dest deployment.Chain, offRamp *offramp.OffRamp, startBlock *uint64, - expectedSeqNrs []uint64, -) (executionStates map[uint64]int, err error) { - if len(expectedSeqNrs) == 0 { - return nil, fmt.Errorf("no expected sequence numbers provided") - } - - timer := time.NewTimer(8 * time.Minute) + expectedSeqNr uint64, +) (executionState int, err error) { + timer := time.NewTimer(5 * time.Minute) defer timer.Stop() - tick := time.NewTicker(3 * time.Second) + tick := time.NewTicker(5 * time.Second) defer tick.Stop() sink := make(chan *offramp.OffRampExecutionStateChanged) subscription, err := offRamp.WatchExecutionStateChanged(&bind.WatchOpts{ @@ -495,55 +376,33 @@ func ConfirmExecWithSeqNrs( Start: startBlock, }, sink, nil, nil, nil) if err != nil { - return nil, fmt.Errorf("error to subscribe ExecutionStateChanged : %w", err) + return -1, fmt.Errorf("error to subscribe ExecutionStateChanged : %w", err) } defer subscription.Unsubscribe() - - // some state to efficiently track the execution states - // of all the expected sequence numbers. - executionStates = make(map[uint64]int) - seqNrsToWatch := make(map[uint64]struct{}) - for _, seqNr := range expectedSeqNrs { - seqNrsToWatch[seqNr] = struct{}{} - } for { select { case <-tick.C: - for expectedSeqNr := range seqNrsToWatch { - scc, executionState := GetExecutionState(t, source, dest, offRamp, expectedSeqNr) - t.Logf("Waiting for ExecutionStateChanged on chain %d (offramp %s) from chain %d with expected sequence number %d, current onchain minSeqNr: %d, execution state: %s", - dest.Selector, offRamp.Address().String(), source.Selector, expectedSeqNr, scc.MinSeqNr, executionStateToString(executionState)) - if executionState == EXECUTION_STATE_SUCCESS || executionState == EXECUTION_STATE_FAILURE { - t.Logf("Observed %s execution state on chain %d (offramp %s) from chain %d with expected sequence number %d", - executionStateToString(executionState), dest.Selector, offRamp.Address().String(), source.Selector, expectedSeqNr) - executionStates[expectedSeqNr] = int(executionState) - delete(seqNrsToWatch, expectedSeqNr) - if len(seqNrsToWatch) == 0 { - return executionStates, nil - } - } + scc, executionState := GetExecutionState(t, source, dest, offRamp, expectedSeqNr) + t.Logf("Waiting for ExecutionStateChanged on chain %d (offramp %s) from chain %d with expected sequence number %d, current onchain minSeqNr: %d, execution state: %s", + dest.Selector, offRamp.Address().String(), source.Selector, expectedSeqNr, scc.MinSeqNr, executionStateToString(executionState)) + if executionState == EXECUTION_STATE_SUCCESS || executionState == EXECUTION_STATE_FAILURE { + t.Logf("Observed %s execution state on chain %d (offramp %s) from chain %d with expected sequence number %d", + executionStateToString(executionState), dest.Selector, offRamp.Address().String(), source.Selector, expectedSeqNr) + return int(executionState), nil } case execEvent := <-sink: t.Logf("Received ExecutionStateChanged (state %s) for seqNum %d on chain %d (offramp %s) from chain %d", - executionStateToString(execEvent.State), execEvent.SequenceNumber, dest.Selector, offRamp.Address().String(), - source.Selector, - ) - - _, found := seqNrsToWatch[execEvent.SequenceNumber] - if found && execEvent.SourceChainSelector == source.Selector { + executionStateToString(execEvent.State), execEvent.SequenceNumber, dest.Selector, offRamp.Address().String(), source.Selector) + if execEvent.SequenceNumber == expectedSeqNr && execEvent.SourceChainSelector == source.Selector { t.Logf("Received ExecutionStateChanged (state %s) on chain %d (offramp %s) from chain %d with expected sequence number %d", - executionStateToString(execEvent.State), dest.Selector, offRamp.Address().String(), source.Selector, execEvent.SequenceNumber) - executionStates[execEvent.SequenceNumber] = int(execEvent.State) - delete(seqNrsToWatch, execEvent.SequenceNumber) - if len(seqNrsToWatch) == 0 { - return executionStates, nil - } + executionStateToString(execEvent.State), dest.Selector, offRamp.Address().String(), source.Selector, expectedSeqNr) + return int(execEvent.State), nil } case <-timer.C: - return nil, fmt.Errorf("timed out waiting for ExecutionStateChanged on chain %d (offramp %s) from chain %d with expected sequence numbers %+v", - dest.Selector, offRamp.Address().String(), source.Selector, expectedSeqNrs) + return -1, fmt.Errorf("timed out waiting for ExecutionStateChanged on chain %d (offramp %s) from chain %d with expected sequence number %d", + dest.Selector, offRamp.Address().String(), source.Selector, expectedSeqNr) case subErr := <-subscription.Err(): - return nil, fmt.Errorf("subscription error: %w", subErr) + return -1, fmt.Errorf("subscription error: %w", subErr) } } } @@ -600,22 +459,6 @@ func RequireConsistently(t *testing.T, condition func() bool, duration time.Dura } } -func SeqNumberRangeToSlice(seqRanges map[SourceDestPair]ccipocr3.SeqNumRange) map[SourceDestPair][]uint64 { - flatten := make(map[SourceDestPair][]uint64) - - for srcDst, seqRange := range seqRanges { - if _, ok := flatten[srcDst]; !ok { - flatten[srcDst] = make([]uint64, 0, seqRange.End()-seqRange.Start()+1) - } - - for i := seqRange.Start(); i <= seqRange.End(); i++ { - flatten[srcDst] = append(flatten[srcDst], uint64(i)) - } - } - - return flatten -} - const ( EXECUTION_STATE_UNTOUCHED = 0 EXECUTION_STATE_INPROGRESS = 1 @@ -637,19 +480,3 @@ func executionStateToString(state uint8) string { return "UNKNOWN" } } - -func AssertEqualFeeConfig(t *testing.T, want, have fee_quoter.FeeQuoterDestChainConfig) { - assert.Equal(t, want.DestGasOverhead, have.DestGasOverhead) - assert.Equal(t, want.IsEnabled, have.IsEnabled) - assert.Equal(t, want.ChainFamilySelector, have.ChainFamilySelector) - assert.Equal(t, want.DefaultTokenDestGasOverhead, have.DefaultTokenDestGasOverhead) - assert.Equal(t, want.DefaultTokenFeeUSDCents, have.DefaultTokenFeeUSDCents) - assert.Equal(t, want.DefaultTxGasLimit, have.DefaultTxGasLimit) - assert.Equal(t, want.DestGasPerPayloadByte, have.DestGasPerPayloadByte) - assert.Equal(t, want.DestGasPerDataAvailabilityByte, have.DestGasPerDataAvailabilityByte) - assert.Equal(t, want.DestDataAvailabilityMultiplierBps, have.DestDataAvailabilityMultiplierBps) - assert.Equal(t, want.DestDataAvailabilityOverheadGas, have.DestDataAvailabilityOverheadGas) - assert.Equal(t, want.MaxDataBytes, have.MaxDataBytes) - assert.Equal(t, want.MaxNumberOfTokensPerMsg, have.MaxNumberOfTokensPerMsg) - assert.Equal(t, want.MaxPerMsgGasLimit, have.MaxPerMsgGasLimit) -} diff --git a/deployment/ccip/test_helpers.go b/deployment/ccip/test_helpers.go new file mode 100644 index 00000000000..d682a72eddc --- /dev/null +++ b/deployment/ccip/test_helpers.go @@ -0,0 +1,797 @@ +package ccipdeployment + +import ( + "context" + "fmt" + "math/big" + "sort" + "testing" + "time" + + mapset "github.com/deckarep/golang-set/v2" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/ethereum/go-ethereum/core/types" + "github.com/pkg/errors" + "github.com/stretchr/testify/require" + + "go.uber.org/multierr" + "go.uber.org/zap/zapcore" + + chainsel "github.com/smartcontractkit/chain-selectors" + "github.com/smartcontractkit/chainlink-ccip/pkg/reader" + cciptypes "github.com/smartcontractkit/chainlink-ccip/pkg/types/ccipocr3" + "github.com/smartcontractkit/chainlink-common/pkg/logger" + commonutils "github.com/smartcontractkit/chainlink-common/pkg/utils" + jobv1 "github.com/smartcontractkit/chainlink-protos/job-distributor/v1/job" + "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/testcontext" + + "github.com/smartcontractkit/chainlink/deployment" + "github.com/smartcontractkit/chainlink/deployment/environment/devenv" + "github.com/smartcontractkit/chainlink/deployment/environment/memory" + + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/burn_mint_token_pool" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/mock_v3_aggregator_contract" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/onramp" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/router" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/usdc_token_pool" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/aggregator_v3_interface" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/mock_ethusd_aggregator_wrapper" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/shared/generated/burn_mint_erc677" +) + +const ( + HomeChainIndex = 0 + FeedChainIndex = 1 +) + +var ( + // bytes4 public constant EVM_EXTRA_ARGS_V2_TAG = 0x181dcf10; + evmExtraArgsV2Tag = hexutil.MustDecode("0x181dcf10") +) + +// Context returns a context with the test's deadline, if available. +func Context(tb testing.TB) context.Context { + ctx := context.Background() + var cancel func() + switch t := tb.(type) { + case *testing.T: + if d, ok := t.Deadline(); ok { + ctx, cancel = context.WithDeadline(ctx, d) + } + } + if cancel == nil { + ctx, cancel = context.WithCancel(ctx) + } + tb.Cleanup(cancel) + return ctx +} + +type DeployedEnv struct { + Env deployment.Environment + HomeChainSel uint64 + FeedChainSel uint64 + ReplayBlocks map[uint64]uint64 +} + +func (e *DeployedEnv) SetupJobs(t *testing.T) { + ctx := testcontext.Get(t) + jbs, err := NewCCIPJobSpecs(e.Env.NodeIDs, e.Env.Offchain) + require.NoError(t, err) + for nodeID, jobs := range jbs { + for _, job := range jobs { + // Note these auto-accept + _, err := e.Env.Offchain.ProposeJob(ctx, + &jobv1.ProposeJobRequest{ + NodeId: nodeID, + Spec: job, + }) + require.NoError(t, err) + } + } + // Wait for plugins to register filters? + // TODO: Investigate how to avoid. + time.Sleep(30 * time.Second) + ReplayLogs(t, e.Env.Offchain, e.ReplayBlocks) +} + +func ReplayLogs(t *testing.T, oc deployment.OffchainClient, replayBlocks map[uint64]uint64) { + switch oc := oc.(type) { + case *memory.JobClient: + require.NoError(t, oc.ReplayLogs(replayBlocks)) + case *devenv.JobDistributor: + require.NoError(t, oc.ReplayLogs(replayBlocks)) + default: + t.Fatalf("unsupported offchain client type %T", oc) + } +} + +func DeployTestContracts(t *testing.T, + lggr logger.Logger, + ab deployment.AddressBook, + homeChainSel, + feedChainSel uint64, + chains map[uint64]deployment.Chain, + linkPrice *big.Int, + wethPrice *big.Int, +) deployment.CapabilityRegistryConfig { + capReg, err := DeployCapReg(lggr, + // deploying cap reg for the first time on a blank chain state + CCIPOnChainState{ + Chains: make(map[uint64]CCIPChainState), + }, ab, chains[homeChainSel]) + require.NoError(t, err) + _, err = DeployFeeds(lggr, ab, chains[feedChainSel], linkPrice, wethPrice) + require.NoError(t, err) + evmChainID, err := chainsel.ChainIdFromSelector(homeChainSel) + require.NoError(t, err) + return deployment.CapabilityRegistryConfig{ + EVMChainID: evmChainID, + Contract: capReg.Address, + } +} + +func LatestBlocksByChain(ctx context.Context, chains map[uint64]deployment.Chain) (map[uint64]uint64, error) { + latestBlocks := make(map[uint64]uint64) + for _, chain := range chains { + latesthdr, err := chain.Client.HeaderByNumber(ctx, nil) + if err != nil { + return nil, errors.Wrapf(err, "failed to get latest header for chain %d", chain.Selector) + } + block := latesthdr.Number.Uint64() + latestBlocks[chain.Selector] = block + } + return latestBlocks, nil +} + +func allocateCCIPChainSelectors(chains map[uint64]deployment.Chain) (homeChainSel uint64, feeChainSel uint64) { + // Lower chainSel is home chain. + var chainSels []uint64 + // Say first chain is home chain. + for chainSel := range chains { + chainSels = append(chainSels, chainSel) + } + sort.Slice(chainSels, func(i, j int) bool { + return chainSels[i] < chainSels[j] + }) + // Take lowest for determinism. + return chainSels[HomeChainIndex], chainSels[FeedChainIndex] +} + +// NewMemoryEnvironment creates a new CCIP environment +// with capreg, fee tokens, feeds and nodes set up. +func NewMemoryEnvironment( + t *testing.T, + lggr logger.Logger, + numChains int, + numNodes int, + linkPrice *big.Int, + wethPrice *big.Int) DeployedEnv { + require.GreaterOrEqual(t, numChains, 2, "numChains must be at least 2 for home and feed chains") + require.GreaterOrEqual(t, numNodes, 4, "numNodes must be at least 4") + ctx := testcontext.Get(t) + chains := memory.NewMemoryChains(t, numChains) + homeChainSel, feedSel := allocateCCIPChainSelectors(chains) + replayBlocks, err := LatestBlocksByChain(ctx, chains) + require.NoError(t, err) + + ab := deployment.NewMemoryAddressBook() + crConfig := DeployTestContracts(t, lggr, ab, homeChainSel, feedSel, chains, linkPrice, wethPrice) + nodes := memory.NewNodes(t, zapcore.InfoLevel, chains, numNodes, 1, crConfig) + for _, node := range nodes { + require.NoError(t, node.App.Start(ctx)) + t.Cleanup(func() { + require.NoError(t, node.App.Stop()) + }) + } + e := memory.NewMemoryEnvironmentFromChainsNodes(t, lggr, chains, nodes) + envNodes, err := deployment.NodeInfo(e.NodeIDs, e.Offchain) + require.NoError(t, err) + e.ExistingAddresses = ab + _, err = DeployHomeChain(lggr, e, e.ExistingAddresses, chains[homeChainSel], + NewTestRMNStaticConfig(), + NewTestRMNDynamicConfig(), + NewTestNodeOperator(chains[homeChainSel].DeployerKey.From), + map[string][][32]byte{ + "NodeOperator": envNodes.NonBootstraps().PeerIDs(), + }, + ) + require.NoError(t, err) + + return DeployedEnv{ + Env: e, + HomeChainSel: homeChainSel, + FeedChainSel: feedSel, + ReplayBlocks: replayBlocks, + } +} + +// NewMemoryEnvironmentWithJobs creates a new CCIP environment +// with capreg, fee tokens, feeds, nodes and jobs set up. +func NewMemoryEnvironmentWithJobs(t *testing.T, lggr logger.Logger, numChains int, numNodes int) DeployedEnv { + e := NewMemoryEnvironment(t, lggr, numChains, numNodes, MockLinkPrice, MockWethPrice) + e.SetupJobs(t) + return e +} + +func NewMemoryEnvironmentWithJobsAndPrices( + t *testing.T, + lggr logger.Logger, + numChains int, + numNodes int, + linkPrice *big.Int, + wethPrice *big.Int) DeployedEnv { + e := NewMemoryEnvironment(t, lggr, numChains, numNodes, linkPrice, wethPrice) + e.SetupJobs(t) + return e +} + +func CCIPSendRequest( + e deployment.Environment, + state CCIPOnChainState, + src, dest uint64, + testRouter bool, + evm2AnyMessage router.ClientEVM2AnyMessage, +) (*types.Transaction, uint64, error) { + msg := router.ClientEVM2AnyMessage{ + Receiver: evm2AnyMessage.Receiver, + Data: evm2AnyMessage.Data, + TokenAmounts: evm2AnyMessage.TokenAmounts, + FeeToken: evm2AnyMessage.FeeToken, + ExtraArgs: evm2AnyMessage.ExtraArgs, + } + r := state.Chains[src].Router + if testRouter { + r = state.Chains[src].TestRouter + } + fee, err := r.GetFee( + &bind.CallOpts{Context: context.Background()}, dest, msg) + if err != nil { + return nil, 0, errors.Wrap(deployment.MaybeDataErr(err), "failed to get fee") + } + if msg.FeeToken == common.HexToAddress("0x0") { + e.Chains[src].DeployerKey.Value = fee + defer func() { e.Chains[src].DeployerKey.Value = nil }() + } + tx, err := r.CcipSend( + e.Chains[src].DeployerKey, + dest, + msg) + if err != nil { + return nil, 0, errors.Wrap(err, "failed to send CCIP message") + } + blockNum, err := e.Chains[src].Confirm(tx) + if err != nil { + return tx, 0, errors.Wrap(err, "failed to confirm CCIP message") + } + return tx, blockNum, nil +} + +func TestSendRequest( + t *testing.T, + e deployment.Environment, + state CCIPOnChainState, + src, dest uint64, + testRouter bool, + evm2AnyMessage router.ClientEVM2AnyMessage, +) (msgSentEvent *onramp.OnRampCCIPMessageSent) { + t.Logf("Sending CCIP request from chain selector %d to chain selector %d", + src, dest) + tx, blockNum, err := CCIPSendRequest( + e, + state, + src, dest, + testRouter, + evm2AnyMessage, + ) + require.NoError(t, err) + it, err := state.Chains[src].OnRamp.FilterCCIPMessageSent(&bind.FilterOpts{ + Start: blockNum, + End: &blockNum, + Context: context.Background(), + }, []uint64{dest}, []uint64{}) + require.NoError(t, err) + require.True(t, it.Next()) + t.Logf("CCIP message (id %x) sent from chain selector %d to chain selector %d tx %s seqNum %d nonce %d sender %s", + it.Event.Message.Header.MessageId[:], + src, + dest, + tx.Hash().String(), + it.Event.SequenceNumber, + it.Event.Message.Header.Nonce, + it.Event.Message.Sender.String(), + ) + return it.Event +} + +// MakeEVMExtraArgsV2 creates the extra args for the EVM2Any message that is destined +// for an EVM chain. The extra args contain the gas limit and allow out of order flag. +func MakeEVMExtraArgsV2(gasLimit uint64, allowOOO bool) []byte { + // extra args is the tag followed by the gas limit and allowOOO abi-encoded. + var extraArgs []byte + extraArgs = append(extraArgs, evmExtraArgsV2Tag...) + gasLimitBytes := new(big.Int).SetUint64(gasLimit).Bytes() + // pad from the left to 32 bytes + gasLimitBytes = common.LeftPadBytes(gasLimitBytes, 32) + + // abi-encode allowOOO + var allowOOOBytes []byte + if allowOOO { + allowOOOBytes = append(allowOOOBytes, 1) + } else { + allowOOOBytes = append(allowOOOBytes, 0) + } + // pad from the left to 32 bytes + allowOOOBytes = common.LeftPadBytes(allowOOOBytes, 32) + + extraArgs = append(extraArgs, gasLimitBytes...) + extraArgs = append(extraArgs, allowOOOBytes...) + return extraArgs +} + +// AddLanesForAll adds densely connected lanes for all chains in the environment so that each chain +// is connected to every other chain except itself. +func AddLanesForAll(e deployment.Environment, state CCIPOnChainState) error { + for source := range e.Chains { + for dest := range e.Chains { + if source != dest { + err := AddLaneWithDefaultPrices(e, state, source, dest) + if err != nil { + return err + } + } + } + } + return nil +} + +func ToPackedFee(execFee, daFee *big.Int) *big.Int { + daShifted := new(big.Int).Lsh(daFee, 112) + return new(big.Int).Or(daShifted, execFee) +} + +const ( + // MockLinkAggregatorDescription This is the description of the MockV3Aggregator.sol contract + // nolint:lll + // https://github.com/smartcontractkit/chainlink/blob/a348b98e90527520049c580000a86fb8ceff7fa7/contracts/src/v0.8/tests/MockV3Aggregator.sol#L76-L76 + MockLinkAggregatorDescription = "v0.8/tests/MockV3Aggregator.sol" + // MockWETHAggregatorDescription WETH use description from MockETHUSDAggregator.sol + // nolint:lll + // https://github.com/smartcontractkit/chainlink/blob/a348b98e90527520049c580000a86fb8ceff7fa7/contracts/src/v0.8/automation/testhelpers/MockETHUSDAggregator.sol#L19-L19 + MockWETHAggregatorDescription = "MockETHUSDAggregator" +) + +var ( + MockLinkPrice = deployment.E18Mult(500) + MockWethPrice = big.NewInt(9e8) + // MockDescriptionToTokenSymbol maps a mock feed description to token descriptor + MockDescriptionToTokenSymbol = map[string]TokenSymbol{ + MockLinkAggregatorDescription: LinkSymbol, + MockWETHAggregatorDescription: WethSymbol, + } + MockSymbolToDescription = map[TokenSymbol]string{ + LinkSymbol: MockLinkAggregatorDescription, + WethSymbol: MockWETHAggregatorDescription, + } + MockSymbolToDecimals = map[TokenSymbol]uint8{ + LinkSymbol: LinkDecimals, + WethSymbol: WethDecimals, + } +) + +func DeployFeeds( + lggr logger.Logger, + ab deployment.AddressBook, + chain deployment.Chain, + linkPrice *big.Int, + wethPrice *big.Int, +) (map[string]common.Address, error) { + linkTV := deployment.NewTypeAndVersion(PriceFeed, deployment.Version1_0_0) + mockLinkFeed := func(chain deployment.Chain) deployment.ContractDeploy[*aggregator_v3_interface.AggregatorV3Interface] { + linkFeed, tx, _, err1 := mock_v3_aggregator_contract.DeployMockV3Aggregator( + chain.DeployerKey, + chain.Client, + LinkDecimals, // decimals + linkPrice, // initialAnswer + ) + aggregatorCr, err2 := aggregator_v3_interface.NewAggregatorV3Interface(linkFeed, chain.Client) + + return deployment.ContractDeploy[*aggregator_v3_interface.AggregatorV3Interface]{ + Address: linkFeed, Contract: aggregatorCr, Tv: linkTV, Tx: tx, Err: multierr.Append(err1, err2), + } + } + + mockWethFeed := func(chain deployment.Chain) deployment.ContractDeploy[*aggregator_v3_interface.AggregatorV3Interface] { + wethFeed, tx, _, err1 := mock_ethusd_aggregator_wrapper.DeployMockETHUSDAggregator( + chain.DeployerKey, + chain.Client, + wethPrice, // initialAnswer + ) + aggregatorCr, err2 := aggregator_v3_interface.NewAggregatorV3Interface(wethFeed, chain.Client) + + return deployment.ContractDeploy[*aggregator_v3_interface.AggregatorV3Interface]{ + Address: wethFeed, Contract: aggregatorCr, Tv: linkTV, Tx: tx, Err: multierr.Append(err1, err2), + } + } + + linkFeedAddress, linkFeedDescription, err := deploySingleFeed(lggr, ab, chain, mockLinkFeed, LinkSymbol) + if err != nil { + return nil, err + } + + wethFeedAddress, wethFeedDescription, err := deploySingleFeed(lggr, ab, chain, mockWethFeed, WethSymbol) + if err != nil { + return nil, err + } + + descriptionToAddress := map[string]common.Address{ + linkFeedDescription: linkFeedAddress, + wethFeedDescription: wethFeedAddress, + } + + return descriptionToAddress, nil +} + +func deploySingleFeed( + lggr logger.Logger, + ab deployment.AddressBook, + chain deployment.Chain, + deployFunc func(deployment.Chain) deployment.ContractDeploy[*aggregator_v3_interface.AggregatorV3Interface], + symbol TokenSymbol, +) (common.Address, string, error) { + //tokenTV := deployment.NewTypeAndVersion(PriceFeed, deployment.Version1_0_0) + mockTokenFeed, err := deployment.DeployContract(lggr, chain, ab, deployFunc) + if err != nil { + lggr.Errorw("Failed to deploy token feed", "err", err, "symbol", symbol) + return common.Address{}, "", err + } + + lggr.Infow("deployed mockTokenFeed", "addr", mockTokenFeed.Address) + + desc, err := mockTokenFeed.Contract.Description(&bind.CallOpts{}) + if err != nil { + lggr.Errorw("Failed to get description", "err", err, "symbol", symbol) + return common.Address{}, "", err + } + + if desc != MockSymbolToDescription[symbol] { + lggr.Errorw("Unexpected description for token", "symbol", symbol, "desc", desc) + return common.Address{}, "", fmt.Errorf("unexpected description: %s", desc) + } + + return mockTokenFeed.Address, desc, nil +} + +func ConfirmRequestOnSourceAndDest(t *testing.T, env deployment.Environment, state CCIPOnChainState, sourceCS, destCS, expectedSeqNr uint64) error { + latesthdr, err := env.Chains[destCS].Client.HeaderByNumber(testcontext.Get(t), nil) + require.NoError(t, err) + startBlock := latesthdr.Number.Uint64() + fmt.Printf("startblock %d", startBlock) + msgSentEvent := TestSendRequest(t, env, state, sourceCS, destCS, false, router.ClientEVM2AnyMessage{ + Receiver: common.LeftPadBytes(state.Chains[destCS].Receiver.Address().Bytes(), 32), + Data: []byte("hello world"), + TokenAmounts: nil, + FeeToken: common.HexToAddress("0x0"), + ExtraArgs: nil, + }) + require.Equal(t, expectedSeqNr, msgSentEvent.SequenceNumber) + + fmt.Printf("Request sent for seqnr %d", msgSentEvent.SequenceNumber) + require.NoError(t, + ConfirmCommitWithExpectedSeqNumRange(t, env.Chains[sourceCS], env.Chains[destCS], state.Chains[destCS].OffRamp, &startBlock, cciptypes.SeqNumRange{ + cciptypes.SeqNum(msgSentEvent.SequenceNumber), + cciptypes.SeqNum(msgSentEvent.SequenceNumber), + })) + + fmt.Printf("Commit confirmed for seqnr %d", msgSentEvent.SequenceNumber) + require.NoError( + t, + commonutils.JustError( + ConfirmExecWithSeqNr( + t, + env.Chains[sourceCS], + env.Chains[destCS], + state.Chains[destCS].OffRamp, + &startBlock, + msgSentEvent.SequenceNumber, + ), + ), + ) + + return nil +} + +func ProcessChangeset(t *testing.T, e deployment.Environment, c deployment.ChangesetOutput) { + + // TODO: Add support for jobspecs as well + + // sign and execute all proposals provided + if len(c.Proposals) != 0 { + state, err := LoadOnchainState(e) + require.NoError(t, err) + for _, prop := range c.Proposals { + chains := mapset.NewSet[uint64]() + for _, op := range prop.Transactions { + chains.Add(uint64(op.ChainIdentifier)) + } + + signed := SignProposal(t, e, &prop) + for _, sel := range chains.ToSlice() { + ExecuteProposal(t, e, signed, state, sel) + } + } + } + + // merge address books + if c.AddressBook != nil { + err := e.ExistingAddresses.Merge(c.AddressBook) + require.NoError(t, err) + } +} + +func DeployTransferableToken( + lggr logger.Logger, + chains map[uint64]deployment.Chain, + src, dst uint64, + state CCIPOnChainState, + addresses deployment.AddressBook, + token string, +) (*burn_mint_erc677.BurnMintERC677, *burn_mint_token_pool.BurnMintTokenPool, *burn_mint_erc677.BurnMintERC677, *burn_mint_token_pool.BurnMintTokenPool, error) { + // Deploy token and pools + srcToken, srcPool, err := deployTransferTokenOneEnd(lggr, chains[src], addresses, token) + if err != nil { + return nil, nil, nil, nil, err + } + dstToken, dstPool, err := deployTransferTokenOneEnd(lggr, chains[dst], addresses, token) + if err != nil { + return nil, nil, nil, nil, err + } + + // Attach token pools to registry + if err := attachTokenToTheRegistry(chains[src], state.Chains[src], chains[src].DeployerKey, srcToken.Address(), srcPool.Address()); err != nil { + return nil, nil, nil, nil, err + } + + if err := attachTokenToTheRegistry(chains[dst], state.Chains[dst], chains[dst].DeployerKey, dstToken.Address(), dstPool.Address()); err != nil { + return nil, nil, nil, nil, err + } + + // Connect pool to each other + if err := setTokenPoolCounterPart(chains[src], srcPool, dst, dstToken.Address(), dstPool.Address()); err != nil { + return nil, nil, nil, nil, err + } + + if err := setTokenPoolCounterPart(chains[dst], dstPool, src, srcToken.Address(), srcPool.Address()); err != nil { + return nil, nil, nil, nil, err + } + + // Add burn/mint permissions + if err := grantMintBurnPermissions(lggr, chains[src], srcToken, srcPool.Address()); err != nil { + return nil, nil, nil, nil, err + } + + if err := grantMintBurnPermissions(lggr, chains[dst], dstToken, dstPool.Address()); err != nil { + return nil, nil, nil, nil, err + } + + return srcToken, srcPool, dstToken, dstPool, nil +} + +func grantMintBurnPermissions(lggr logger.Logger, chain deployment.Chain, token *burn_mint_erc677.BurnMintERC677, address common.Address) error { + lggr.Infow("Granting burn permissions", "token", token.Address(), "burner", address) + tx, err := token.GrantBurnRole(chain.DeployerKey, address) + if err != nil { + return err + } + _, err = chain.Confirm(tx) + if err != nil { + return err + } + + lggr.Infow("Granting mint permissions", "token", token.Address(), "minter", address) + tx, err = token.GrantMintRole(chain.DeployerKey, address) + if err != nil { + return err + } + _, err = chain.Confirm(tx) + return err +} + +func setUSDCTokenPoolCounterPart( + chain deployment.Chain, + tokenPool *usdc_token_pool.USDCTokenPool, + destChainSelector uint64, + destTokenAddress common.Address, + destTokenPoolAddress common.Address, +) error { + allowedCaller := common.LeftPadBytes(destTokenPoolAddress.Bytes(), 32) + var fixedAddr [32]byte + copy(fixedAddr[:], allowedCaller[:32]) + + domain, _ := reader.AllAvailableDomains()[destChainSelector] + + domains := []usdc_token_pool.USDCTokenPoolDomainUpdate{ + { + AllowedCaller: fixedAddr, + DomainIdentifier: domain, + DestChainSelector: destChainSelector, + Enabled: true, + }, + } + tx, err := tokenPool.SetDomains(chain.DeployerKey, domains) + if err != nil { + return err + } + + _, err = chain.Confirm(tx) + if err != nil { + return err + } + + pool, err := burn_mint_token_pool.NewBurnMintTokenPool(tokenPool.Address(), chain.Client) + if err != nil { + return err + } + + return setTokenPoolCounterPart(chain, pool, destChainSelector, destTokenAddress, destTokenPoolAddress) +} + +func setTokenPoolCounterPart( + chain deployment.Chain, + tokenPool *burn_mint_token_pool.BurnMintTokenPool, + destChainSelector uint64, + destTokenAddress common.Address, + destTokenPoolAddress common.Address, +) error { + tx, err := tokenPool.ApplyChainUpdates( + chain.DeployerKey, + []burn_mint_token_pool.TokenPoolChainUpdate{ + { + RemoteChainSelector: destChainSelector, + Allowed: true, + RemotePoolAddress: common.LeftPadBytes(destTokenPoolAddress.Bytes(), 32), + RemoteTokenAddress: common.LeftPadBytes(destTokenAddress.Bytes(), 32), + OutboundRateLimiterConfig: burn_mint_token_pool.RateLimiterConfig{ + IsEnabled: false, + Capacity: big.NewInt(0), + Rate: big.NewInt(0), + }, + InboundRateLimiterConfig: burn_mint_token_pool.RateLimiterConfig{ + IsEnabled: false, + Capacity: big.NewInt(0), + Rate: big.NewInt(0), + }, + }, + }, + ) + if err != nil { + return fmt.Errorf("failed to apply chain updates on token pool %s: %w", tokenPool.Address(), err) + } + + _, err = chain.Confirm(tx) + if err != nil { + return err + } + + tx, err = tokenPool.SetRemotePool( + chain.DeployerKey, + destChainSelector, + destTokenPoolAddress.Bytes(), + ) + if err != nil { + return fmt.Errorf("failed to set remote pool on token pool %s: %w", tokenPool.Address(), err) + } + + _, err = chain.Confirm(tx) + return err +} + +func attachTokenToTheRegistry( + chain deployment.Chain, + state CCIPChainState, + owner *bind.TransactOpts, + token common.Address, + tokenPool common.Address, +) error { + tx, err := state.RegistryModule.RegisterAdminViaOwner(owner, token) + if err != nil { + return err + } + _, err = chain.Confirm(tx) + if err != nil { + return err + } + + tx, err = state.TokenAdminRegistry.AcceptAdminRole(owner, token) + if err != nil { + return err + } + _, err = chain.Confirm(tx) + if err != nil { + return err + } + + tx, err = state.TokenAdminRegistry.SetPool(owner, token, tokenPool) + if err != nil { + return err + } + _, err = chain.Confirm(tx) + if err != nil { + return err + } + return nil +} + +func deployTransferTokenOneEnd( + lggr logger.Logger, + chain deployment.Chain, + addressBook deployment.AddressBook, + tokenSymbol string, +) (*burn_mint_erc677.BurnMintERC677, *burn_mint_token_pool.BurnMintTokenPool, error) { + var rmnAddress, routerAddress string + chainAddresses, err := addressBook.AddressesForChain(chain.Selector) + if err != nil { + return nil, nil, err + } + for address, v := range chainAddresses { + if deployment.NewTypeAndVersion(ARMProxy, deployment.Version1_0_0) == v { + rmnAddress = address + } + if deployment.NewTypeAndVersion(Router, deployment.Version1_2_0) == v { + routerAddress = address + } + if rmnAddress != "" && routerAddress != "" { + break + } + } + + tokenContract, err := deployment.DeployContract(lggr, chain, addressBook, + func(chain deployment.Chain) deployment.ContractDeploy[*burn_mint_erc677.BurnMintERC677] { + USDCTokenAddr, tx, token, err2 := burn_mint_erc677.DeployBurnMintERC677( + chain.DeployerKey, + chain.Client, + tokenSymbol, + tokenSymbol, + uint8(18), + big.NewInt(0).Mul(big.NewInt(1e9), big.NewInt(1e18)), + ) + return deployment.ContractDeploy[*burn_mint_erc677.BurnMintERC677]{ + USDCTokenAddr, token, tx, deployment.NewTypeAndVersion(BurnMintToken, deployment.Version1_0_0), err2, + } + }) + if err != nil { + lggr.Errorw("Failed to deploy Token ERC677", "err", err) + return nil, nil, err + } + + tx, err := tokenContract.Contract.GrantMintRole(chain.DeployerKey, chain.DeployerKey.From) + if err != nil { + return nil, nil, err + } + _, err = chain.Confirm(tx) + if err != nil { + return nil, nil, err + } + + tokenPool, err := deployment.DeployContract(lggr, chain, addressBook, + func(chain deployment.Chain) deployment.ContractDeploy[*burn_mint_token_pool.BurnMintTokenPool] { + tokenPoolAddress, tx, tokenPoolContract, err2 := burn_mint_token_pool.DeployBurnMintTokenPool( + chain.DeployerKey, + chain.Client, + tokenContract.Address, + []common.Address{}, + common.HexToAddress(rmnAddress), + common.HexToAddress(routerAddress), + ) + return deployment.ContractDeploy[*burn_mint_token_pool.BurnMintTokenPool]{ + tokenPoolAddress, tokenPoolContract, tx, deployment.NewTypeAndVersion(BurnMintTokenPool, deployment.Version1_0_0), err2, + } + }) + if err != nil { + lggr.Errorw("Failed to deploy token pool", "err", err) + return nil, nil, err + } + + return tokenContract.Contract, tokenPool.Contract, nil +} diff --git a/deployment/ccip/changeset/test_params.go b/deployment/ccip/test_params.go similarity index 92% rename from deployment/ccip/changeset/test_params.go rename to deployment/ccip/test_params.go index a76a610a178..531c48532f1 100644 --- a/deployment/ccip/changeset/test_params.go +++ b/deployment/ccip/test_params.go @@ -1,10 +1,10 @@ -package changeset +package ccipdeployment import ( "github.com/ethereum/go-ethereum/common" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/rmn_home" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry_1_1_0" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry" ) func NewTestRMNStaticConfig() rmn_home.RMNHomeStaticConfig { diff --git a/deployment/ccip/changeset/test_usdc_helpers.go b/deployment/ccip/test_usdc_helpers.go similarity index 66% rename from deployment/ccip/changeset/test_usdc_helpers.go rename to deployment/ccip/test_usdc_helpers.go index 55f1bd25a36..787ca328a8e 100644 --- a/deployment/ccip/changeset/test_usdc_helpers.go +++ b/deployment/ccip/test_usdc_helpers.go @@ -1,21 +1,16 @@ -package changeset +package ccipdeployment import ( - "math/big" - - "golang.org/x/sync/errgroup" - "github.com/ethereum/go-ethereum/common" - "github.com/smartcontractkit/chainlink-ccip/pkg/reader" "github.com/smartcontractkit/chainlink-common/pkg/logger" - "github.com/smartcontractkit/chainlink/deployment" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/fee_quoter" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/mock_usdc_token_messenger" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/mock_usdc_token_transmitter" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/usdc_token_pool" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/shared/generated/burn_mint_erc677" + "math/big" ) func ConfigureUSDCTokenPools( @@ -29,78 +24,53 @@ func ConfigureUSDCTokenPools( srcPool := state.Chains[src].USDCTokenPool dstPool := state.Chains[dst].USDCTokenPool - args := []struct { - sourceChain deployment.Chain - dstChainSel uint64 - state CCIPChainState - srcToken *burn_mint_erc677.BurnMintERC677 - srcPool *usdc_token_pool.USDCTokenPool - dstToken *burn_mint_erc677.BurnMintERC677 - dstPool *usdc_token_pool.USDCTokenPool - }{ - { - chains[src], - dst, - state.Chains[src], - srcToken, - srcPool, - dstToken, - dstPool, - }, - { - chains[dst], - src, - state.Chains[dst], - dstToken, - dstPool, - srcToken, - srcPool, - }, + // Attach token pools to registry + if err := attachTokenToTheRegistry(chains[src], state.Chains[src], chains[src].DeployerKey, srcToken.Address(), srcPool.Address()); err != nil { + lggr.Errorw("Failed to attach token to the registry", "err", err, "token", srcToken.Address(), "pool", srcPool.Address()) + return nil, nil, err } - configurePoolGrp := errgroup.Group{} - for _, arg := range args { - configurePoolGrp.Go(configureSingleChain(lggr, arg.sourceChain, arg.dstChainSel, arg.state, arg.srcToken, arg.srcPool, arg.dstToken, arg.dstPool)) + if err := attachTokenToTheRegistry(chains[dst], state.Chains[dst], chains[dst].DeployerKey, dstToken.Address(), dstPool.Address()); err != nil { + lggr.Errorw("Failed to attach token to the registry", "err", err, "token", dstToken.Address(), "pool", dstPool.Address()) + return nil, nil, err } - if err := configurePoolGrp.Wait(); err != nil { + + // Connect pool to each other + if err := setUSDCTokenPoolCounterPart(chains[src], srcPool, dst, dstToken.Address(), dstPool.Address()); err != nil { + lggr.Errorw("Failed to set counter part", "err", err, "srcPool", srcPool.Address(), "dstPool", dstPool.Address()) return nil, nil, err } - return srcToken, dstToken, nil -} -func configureSingleChain( - lggr logger.Logger, - sourceChain deployment.Chain, - dstChainSel uint64, - state CCIPChainState, - srcToken *burn_mint_erc677.BurnMintERC677, - srcPool *usdc_token_pool.USDCTokenPool, - dstToken *burn_mint_erc677.BurnMintERC677, - dstPool *usdc_token_pool.USDCTokenPool, -) func() error { - return func() error { - if err := attachTokenToTheRegistry(sourceChain, state, sourceChain.DeployerKey, srcToken.Address(), srcPool.Address()); err != nil { - lggr.Errorw("Failed to attach token to the registry", "err", err, "token", srcToken.Address(), "pool", srcPool.Address()) - return err - } + if err := setUSDCTokenPoolCounterPart(chains[dst], dstPool, src, srcToken.Address(), srcPool.Address()); err != nil { + lggr.Errorw("Failed to set counter part", "err", err, "srcPool", dstPool.Address(), "dstPool", srcPool.Address()) + return nil, nil, err + } - if err := setUSDCTokenPoolCounterPart(sourceChain, srcPool, dstChainSel, sourceChain.DeployerKey, dstToken.Address(), dstPool.Address()); err != nil { - lggr.Errorw("Failed to set counter part", "err", err, "srcPool", srcPool.Address(), "dstPool", dstPool.Address()) - return err + // Add burn/mint permissions for source + for _, addr := range []common.Address{ + srcPool.Address(), + state.Chains[src].MockUSDCTokenMessenger.Address(), + state.Chains[src].MockUSDCTransmitter.Address(), + } { + if err := grantMintBurnPermissions(lggr, chains[src], srcToken, addr); err != nil { + lggr.Errorw("Failed to grant mint/burn permissions", "err", err, "token", srcToken.Address(), "minter", addr) + return nil, nil, err } + } - for _, addr := range []common.Address{ - srcPool.Address(), - state.MockUSDCTokenMessenger.Address(), - state.MockUSDCTransmitter.Address(), - } { - if err := grantMintBurnPermissions(lggr, sourceChain, srcToken, sourceChain.DeployerKey, addr); err != nil { - lggr.Errorw("Failed to grant mint/burn permissions", "err", err, "token", srcToken.Address(), "address", addr) - return err - } + // Add burn/mint permissions for dest + for _, addr := range []common.Address{ + dstPool.Address(), + state.Chains[dst].MockUSDCTokenMessenger.Address(), + state.Chains[dst].MockUSDCTransmitter.Address(), + } { + if err := grantMintBurnPermissions(lggr, chains[dst], dstToken, addr); err != nil { + lggr.Errorw("Failed to grant mint/burn permissions", "err", err, "token", dstToken.Address(), "minter", addr) + return nil, nil, err } - return nil } + + return srcToken, dstToken, nil } func UpdateFeeQuoterForUSDC( @@ -147,8 +117,7 @@ func DeployUSDC( lggr logger.Logger, chain deployment.Chain, addresses deployment.AddressBook, - rmnProxy common.Address, - router common.Address, + state CCIPChainState, ) ( *burn_mint_erc677.BurnMintERC677, *usdc_token_pool.USDCTokenPool, @@ -161,10 +130,10 @@ func DeployUSDC( tokenAddress, tx, tokenContract, err2 := burn_mint_erc677.DeployBurnMintERC677( chain.DeployerKey, chain.Client, - USDCName, - string(USDCSymbol), - UsdcDecimals, - big.NewInt(0), + "USDC Token", + "USDC", + uint8(18), + big.NewInt(0).Mul(big.NewInt(1e9), big.NewInt(1e18)), ) return deployment.ContractDeploy[*burn_mint_erc677.BurnMintERC677]{ Address: tokenAddress, @@ -175,13 +144,13 @@ func DeployUSDC( } }) if err != nil { - lggr.Errorw("Failed to deploy USDC token", "chain", chain.String(), "err", err) + lggr.Errorw("Failed to deploy USDC token", "err", err) return nil, nil, nil, nil, err } tx, err := token.Contract.GrantMintRole(chain.DeployerKey, chain.DeployerKey.From) if err != nil { - lggr.Errorw("Failed to grant mint role", "chain", chain.String(), "token", token.Contract.Address(), "err", err) + lggr.Errorw("Failed to grant mint role", "token", token.Contract.Address(), "err", err) return nil, nil, nil, nil, err } _, err = chain.Confirm(tx) @@ -207,10 +176,12 @@ func DeployUSDC( } }) if err != nil { - lggr.Errorw("Failed to deploy mock USDC transmitter", "chain", chain.String(), "err", err) + lggr.Errorw("Failed to deploy mock USDC transmitter", "err", err) return nil, nil, nil, nil, err } + lggr.Infow("deployed mock USDC transmitter", "addr", transmitter.Address) + messenger, err := deployment.DeployContract(lggr, chain, addresses, func(chain deployment.Chain) deployment.ContractDeploy[*mock_usdc_token_messenger.MockE2EUSDCTokenMessenger] { messengerAddress, tx, messengerContract, err2 := mock_usdc_token_messenger.DeployMockE2EUSDCTokenMessenger( @@ -228,9 +199,10 @@ func DeployUSDC( } }) if err != nil { - lggr.Errorw("Failed to deploy USDC token messenger", "chain", chain.String(), "err", err) + lggr.Errorw("Failed to deploy USDC token messenger", "err", err) return nil, nil, nil, nil, err } + lggr.Infow("deployed mock USDC token messenger", "addr", messenger.Address) tokenPool, err := deployment.DeployContract(lggr, chain, addresses, func(chain deployment.Chain) deployment.ContractDeploy[*usdc_token_pool.USDCTokenPool] { @@ -240,8 +212,8 @@ func DeployUSDC( messenger.Address, token.Address, []common.Address{}, - rmnProxy, - router, + state.RMNProxyExisting.Address(), + state.Router.Address(), ) return deployment.ContractDeploy[*usdc_token_pool.USDCTokenPool]{ Address: tokenPoolAddress, @@ -252,9 +224,10 @@ func DeployUSDC( } }) if err != nil { - lggr.Errorw("Failed to deploy USDC token pool", "chain", chain.String(), "err", err) + lggr.Errorw("Failed to deploy USDC token pool", "err", err) return nil, nil, nil, nil, err } + lggr.Infow("deployed USDC token pool", "addr", tokenPool.Address) return token.Contract, tokenPool.Contract, messenger.Contract, transmitter.Contract, nil } diff --git a/deployment/ccip/changeset/token_info.go b/deployment/ccip/token_info.go similarity index 88% rename from deployment/ccip/changeset/token_info.go rename to deployment/ccip/token_info.go index 7c008a8a884..559c961e3d4 100644 --- a/deployment/ccip/changeset/token_info.go +++ b/deployment/ccip/token_info.go @@ -1,25 +1,14 @@ -package changeset +package ccipdeployment import ( "github.com/smartcontractkit/chainlink-ccip/pkg/types/ccipocr3" "github.com/smartcontractkit/chainlink-ccip/pluginconfig" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/shared/generated/link_token" - "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/weth9" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/aggregator_v3_interface" -) + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/shared/generated/burn_mint_erc677" -type TokenSymbol string - -const ( - LinkSymbol TokenSymbol = "LINK" - WethSymbol TokenSymbol = "WETH" - USDCSymbol TokenSymbol = "USDC" - USDCName string = "USD Coin" - LinkDecimals = 18 - WethDecimals = 18 - UsdcDecimals = 6 + "github.com/smartcontractkit/chainlink-common/pkg/logger" ) var ( @@ -67,7 +56,7 @@ func (tc *TokenConfig) UpsertTokenInfo( // GetTokenInfo Adds mapping between dest chain tokens and their respective aggregators on feed chain. func (tc *TokenConfig) GetTokenInfo( lggr logger.Logger, - linkToken *link_token.LinkToken, + linkToken *burn_mint_erc677.BurnMintERC677, wethToken *weth9.WETH9, ) map[ccipocr3.UnknownEncodedAddress]pluginconfig.TokenInfo { tokenToAggregate := make(map[ccipocr3.UnknownEncodedAddress]pluginconfig.TokenInfo) diff --git a/deployment/ccip/view/types/contract_state.go b/deployment/ccip/view/types/contract_state.go new file mode 100644 index 00000000000..f65c510af53 --- /dev/null +++ b/deployment/ccip/view/types/contract_state.go @@ -0,0 +1,33 @@ +package types + +import ( + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" +) + +type ContractMetaData struct { + TypeAndVersion string `json:"typeAndVersion,omitempty"` + Address common.Address `json:"address,omitempty"` + Owner common.Address `json:"owner,omitempty"` +} + +func NewContractMetaData(tv Meta, addr common.Address) (ContractMetaData, error) { + tvStr, err := tv.TypeAndVersion(nil) + if err != nil { + return ContractMetaData{}, err + } + owner, err := tv.Owner(nil) + if err != nil { + return ContractMetaData{}, err + } + return ContractMetaData{ + TypeAndVersion: tvStr, + Address: addr, + Owner: owner, + }, nil +} + +type Meta interface { + TypeAndVersion(opts *bind.CallOpts) (string, error) + Owner(opts *bind.CallOpts) (common.Address, error) +} diff --git a/deployment/ccip/view/v1_2/price_registry.go b/deployment/ccip/view/v1_2/price_registry.go deleted file mode 100644 index ee0f1067b6c..00000000000 --- a/deployment/ccip/view/v1_2/price_registry.go +++ /dev/null @@ -1,45 +0,0 @@ -package v1_2 - -import ( - "fmt" - - "github.com/ethereum/go-ethereum/common" - - "github.com/smartcontractkit/chainlink/deployment/common/view/types" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/price_registry_1_2_0" -) - -type PriceRegistryView struct { - types.ContractMetaData - FeeTokens []common.Address `json:"feeTokens"` - StalenessThreshold string `json:"stalenessThreshold"` - Updaters []common.Address `json:"updaters"` -} - -func GeneratePriceRegistryView(pr *price_registry_1_2_0.PriceRegistry) (PriceRegistryView, error) { - if pr == nil { - return PriceRegistryView{}, fmt.Errorf("cannot generate view for nil PriceRegistry") - } - meta, err := types.NewContractMetaData(pr, pr.Address()) - if err != nil { - return PriceRegistryView{}, fmt.Errorf("failed to generate contract metadata for PriceRegistry %s: %w", pr.Address(), err) - } - ft, err := pr.GetFeeTokens(nil) - if err != nil { - return PriceRegistryView{}, fmt.Errorf("failed to get fee tokens %s: %w", pr.Address(), err) - } - st, err := pr.GetStalenessThreshold(nil) - if err != nil { - return PriceRegistryView{}, fmt.Errorf("failed to get staleness threshold %s: %w", pr.Address(), err) - } - updaters, err := pr.GetPriceUpdaters(nil) - if err != nil { - return PriceRegistryView{}, fmt.Errorf("failed to get price updaters %s: %w", pr.Address(), err) - } - return PriceRegistryView{ - ContractMetaData: meta, - FeeTokens: ft, - StalenessThreshold: st.String(), - Updaters: updaters, - }, nil -} diff --git a/deployment/ccip/view/v1_2/price_registry_test.go b/deployment/ccip/view/v1_2/price_registry_test.go deleted file mode 100644 index cbcdbe253ce..00000000000 --- a/deployment/ccip/view/v1_2/price_registry_test.go +++ /dev/null @@ -1,38 +0,0 @@ -package v1_2 - -import ( - "encoding/json" - "testing" - - "github.com/ethereum/go-ethereum/common" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - "go.uber.org/zap/zapcore" - - "github.com/smartcontractkit/chainlink/deployment" - "github.com/smartcontractkit/chainlink/deployment/environment/memory" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/price_registry_1_2_0" - "github.com/smartcontractkit/chainlink/v2/core/logger" -) - -func TestGeneratePriceRegistryView(t *testing.T) { - e := memory.NewMemoryEnvironment(t, logger.TestLogger(t), zapcore.InfoLevel, memory.MemoryEnvironmentConfig{ - Chains: 1, - }) - chain := e.Chains[e.AllChainSelectors()[0]] - f1, f2 := common.HexToAddress("0x1"), common.HexToAddress("0x2") - _, tx, c, err := price_registry_1_2_0.DeployPriceRegistry( - chain.DeployerKey, chain.Client, []common.Address{chain.DeployerKey.From}, []common.Address{f1, f2}, uint32(10)) - _, err = deployment.ConfirmIfNoError(chain, tx, err) - require.NoError(t, err) - - v, err := GeneratePriceRegistryView(c) - require.NoError(t, err) - assert.Equal(t, v.Owner, chain.DeployerKey.From) - assert.Equal(t, v.TypeAndVersion, "PriceRegistry 1.2.0") - assert.Equal(t, v.FeeTokens, []common.Address{f1, f2}) - assert.Equal(t, v.StalenessThreshold, "10") - assert.Equal(t, v.Updaters, []common.Address{chain.DeployerKey.From}) - _, err = json.MarshalIndent(v, "", " ") - require.NoError(t, err) -} diff --git a/deployment/ccip/view/v1_5/offramp.go b/deployment/ccip/view/v1_5/offramp.go deleted file mode 100644 index 95e40d9da27..00000000000 --- a/deployment/ccip/view/v1_5/offramp.go +++ /dev/null @@ -1,40 +0,0 @@ -package v1_5 - -import ( - "fmt" - - "github.com/smartcontractkit/chainlink/deployment/common/view/types" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/evm_2_evm_offramp" -) - -type OffRampView struct { - types.ContractMetaData - StaticConfig evm_2_evm_offramp.EVM2EVMOffRampStaticConfig `json:"staticConfig"` - DynamicConfig evm_2_evm_offramp.EVM2EVMOffRampDynamicConfig `json:"dynamicConfig"` -} - -func GenerateOffRampView(r *evm_2_evm_offramp.EVM2EVMOffRamp) (OffRampView, error) { - if r == nil { - return OffRampView{}, fmt.Errorf("cannot generate view for nil OffRamp") - } - meta, err := types.NewContractMetaData(r, r.Address()) - if err != nil { - return OffRampView{}, fmt.Errorf("failed to generate contract metadata for OffRamp %s: %w", r.Address(), err) - } - staticConfig, err := r.GetStaticConfig(nil) - if err != nil { - return OffRampView{}, fmt.Errorf("failed to get static config for OffRamp %s: %w", r.Address(), err) - } - dynamicConfig, err := r.GetDynamicConfig(nil) - if err != nil { - return OffRampView{}, fmt.Errorf("failed to get dynamic config for OffRamp %s: %w", r.Address(), err) - } - - // TODO: If needed, we can filter logs to get the OCR config. - // May not be required for the legacy contracts. - return OffRampView{ - ContractMetaData: meta, - StaticConfig: staticConfig, - DynamicConfig: dynamicConfig, - }, nil -} diff --git a/deployment/ccip/view/v1_5/offramp_test.go b/deployment/ccip/view/v1_5/offramp_test.go deleted file mode 100644 index d6539fe2ba5..00000000000 --- a/deployment/ccip/view/v1_5/offramp_test.go +++ /dev/null @@ -1,60 +0,0 @@ -package v1_5 - -import ( - "encoding/json" - "testing" - - "github.com/ethereum/go-ethereum/common" - chainsel "github.com/smartcontractkit/chain-selectors" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - "go.uber.org/zap/zapcore" - - "math/big" - - "github.com/smartcontractkit/chainlink/deployment" - "github.com/smartcontractkit/chainlink/deployment/environment/memory" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/commit_store" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/evm_2_evm_offramp" - "github.com/smartcontractkit/chainlink/v2/core/logger" -) - -func TestOffRampView(t *testing.T) { - e := memory.NewMemoryEnvironment(t, logger.TestLogger(t), zapcore.InfoLevel, memory.MemoryEnvironmentConfig{ - Chains: 1, - }) - chain := e.Chains[e.AllChainSelectors()[0]] - _, tx, c, err := commit_store.DeployCommitStore( - chain.DeployerKey, chain.Client, commit_store.CommitStoreStaticConfig{ - ChainSelector: chainsel.TEST_90000002.Selector, - SourceChainSelector: chainsel.TEST_90000001.Selector, - OnRamp: common.HexToAddress("0x4"), - RmnProxy: common.HexToAddress("0x1"), - }) - _, err = deployment.ConfirmIfNoError(chain, tx, err) - require.NoError(t, err) - sc := evm_2_evm_offramp.EVM2EVMOffRampStaticConfig{ - ChainSelector: chainsel.TEST_90000002.Selector, - SourceChainSelector: chainsel.TEST_90000001.Selector, - RmnProxy: common.HexToAddress("0x1"), - CommitStore: c.Address(), - TokenAdminRegistry: common.HexToAddress("0x3"), - OnRamp: common.HexToAddress("0x4"), - } - rl := evm_2_evm_offramp.RateLimiterConfig{ - IsEnabled: true, - Capacity: big.NewInt(100), - Rate: big.NewInt(10), - } - _, tx, c2, err := evm_2_evm_offramp.DeployEVM2EVMOffRamp( - chain.DeployerKey, chain.Client, sc, rl) - _, err = deployment.ConfirmIfNoError(chain, tx, err) - require.NoError(t, err) - - v, err := GenerateOffRampView(c2) - require.NoError(t, err) - assert.Equal(t, v.StaticConfig, sc) - assert.Equal(t, v.TypeAndVersion, "EVM2EVMOffRamp 1.5.0") - _, err = json.MarshalIndent(v, "", " ") - require.NoError(t, err) -} diff --git a/deployment/ccip/view/v1_5/onramp.go b/deployment/ccip/view/v1_5/onramp.go deleted file mode 100644 index d679f6c14c0..00000000000 --- a/deployment/ccip/view/v1_5/onramp.go +++ /dev/null @@ -1,39 +0,0 @@ -package v1_5 - -import ( - "fmt" - - "github.com/smartcontractkit/chainlink/deployment/common/view/types" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/evm_2_evm_onramp" -) - -type OnRampView struct { - types.ContractMetaData - StaticConfig evm_2_evm_onramp.EVM2EVMOnRampStaticConfig `json:"staticConfig"` - DynamicConfig evm_2_evm_onramp.EVM2EVMOnRampDynamicConfig `json:"dynamicConfig"` -} - -func GenerateOnRampView(r *evm_2_evm_onramp.EVM2EVMOnRamp) (OnRampView, error) { - if r == nil { - return OnRampView{}, fmt.Errorf("cannot generate view for nil OnRamp") - } - meta, err := types.NewContractMetaData(r, r.Address()) - if err != nil { - return OnRampView{}, fmt.Errorf("failed to generate contract metadata for OnRamp %s: %w", r.Address(), err) - } - staticConfig, err := r.GetStaticConfig(nil) - if err != nil { - return OnRampView{}, fmt.Errorf("failed to get static config for OnRamp %s: %w", r.Address(), err) - } - dynamicConfig, err := r.GetDynamicConfig(nil) - if err != nil { - return OnRampView{}, fmt.Errorf("failed to get dynamic config for OnRamp %s: %w", r.Address(), err) - } - - // Add billing if needed, maybe not required for legacy contract? - return OnRampView{ - ContractMetaData: meta, - StaticConfig: staticConfig, - DynamicConfig: dynamicConfig, - }, nil -} diff --git a/deployment/ccip/view/v1_5/onramp_test.go b/deployment/ccip/view/v1_5/onramp_test.go deleted file mode 100644 index 4d7ef0225a6..00000000000 --- a/deployment/ccip/view/v1_5/onramp_test.go +++ /dev/null @@ -1,71 +0,0 @@ -package v1_5 - -import ( - "encoding/json" - "math/big" - "testing" - - "github.com/ethereum/go-ethereum/common" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - "go.uber.org/zap/zapcore" - - "github.com/smartcontractkit/chainlink/deployment" - "github.com/smartcontractkit/chainlink/deployment/environment/memory" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/evm_2_evm_onramp" - "github.com/smartcontractkit/chainlink/v2/core/logger" -) - -func TestOnRampView(t *testing.T) { - e := memory.NewMemoryEnvironment(t, logger.TestLogger(t), zapcore.InfoLevel, memory.MemoryEnvironmentConfig{ - Chains: 1, - }) - chain := e.Chains[e.AllChainSelectors()[0]] - _, tx, c, err := evm_2_evm_onramp.DeployEVM2EVMOnRamp( - chain.DeployerKey, chain.Client, - evm_2_evm_onramp.EVM2EVMOnRampStaticConfig{ - LinkToken: common.HexToAddress("0x1"), - ChainSelector: chain.Selector, - DestChainSelector: 100, - DefaultTxGasLimit: 10, - MaxNopFeesJuels: big.NewInt(10), - PrevOnRamp: common.Address{}, - RmnProxy: common.HexToAddress("0x2"), - TokenAdminRegistry: common.HexToAddress("0x3"), - }, - evm_2_evm_onramp.EVM2EVMOnRampDynamicConfig{ - Router: common.HexToAddress("0x4"), - MaxNumberOfTokensPerMsg: 0, - DestGasOverhead: 0, - DestGasPerPayloadByte: 0, - DestDataAvailabilityOverheadGas: 0, - DestGasPerDataAvailabilityByte: 0, - DestDataAvailabilityMultiplierBps: 0, - PriceRegistry: common.HexToAddress("0x5"), - MaxDataBytes: 0, - MaxPerMsgGasLimit: 0, - DefaultTokenFeeUSDCents: 0, - DefaultTokenDestGasOverhead: 0, - EnforceOutOfOrder: false, - }, - evm_2_evm_onramp.RateLimiterConfig{ - IsEnabled: true, - Capacity: big.NewInt(100), - Rate: big.NewInt(10), - }, - []evm_2_evm_onramp.EVM2EVMOnRampFeeTokenConfigArgs{}, - []evm_2_evm_onramp.EVM2EVMOnRampTokenTransferFeeConfigArgs{}, - []evm_2_evm_onramp.EVM2EVMOnRampNopAndWeight{}, - ) - _, err = deployment.ConfirmIfNoError(chain, tx, err) - require.NoError(t, err) - v, err := GenerateOnRampView(c) - require.NoError(t, err) - // Check a few fields. - assert.Equal(t, v.StaticConfig.ChainSelector, chain.Selector) - assert.Equal(t, v.DynamicConfig.Router, common.HexToAddress("0x4")) - assert.Equal(t, v.TypeAndVersion, "EVM2EVMOnRamp 1.5.0") - _, err = json.MarshalIndent(v, "", " ") - require.NoError(t, err) - -} diff --git a/deployment/ccip/view/v1_5/rmn.go b/deployment/ccip/view/v1_5/rmn.go deleted file mode 100644 index cef55460446..00000000000 --- a/deployment/ccip/view/v1_5/rmn.go +++ /dev/null @@ -1,31 +0,0 @@ -package v1_5 - -import ( - "fmt" - - "github.com/smartcontractkit/chainlink/deployment/common/view/types" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/rmn_contract" -) - -type RMNView struct { - types.ContractMetaData - ConfigDetails rmn_contract.GetConfigDetails `json:"configDetails"` -} - -func GenerateRMNView(r *rmn_contract.RMNContract) (RMNView, error) { - if r == nil { - return RMNView{}, fmt.Errorf("cannot generate view for nil RMN") - } - meta, err := types.NewContractMetaData(r, r.Address()) - if err != nil { - return RMNView{}, fmt.Errorf("failed to generate contract metadata for RMN: %w", err) - } - config, err := r.GetConfigDetails(nil) - if err != nil { - return RMNView{}, fmt.Errorf("failed to get config details for RMN: %w", err) - } - return RMNView{ - ContractMetaData: meta, - ConfigDetails: config, - }, nil -} diff --git a/deployment/ccip/view/v1_5/rmn_test.go b/deployment/ccip/view/v1_5/rmn_test.go deleted file mode 100644 index 3ec7d7a9cc9..00000000000 --- a/deployment/ccip/view/v1_5/rmn_test.go +++ /dev/null @@ -1,53 +0,0 @@ -package v1_5 - -import ( - "encoding/json" - "testing" - - "github.com/ethereum/go-ethereum/common" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - "go.uber.org/zap/zapcore" - - "github.com/smartcontractkit/chainlink/deployment/environment/memory" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/rmn_contract" - "github.com/smartcontractkit/chainlink/v2/core/logger" -) - -func TestGenerateRMNView(t *testing.T) { - e := memory.NewMemoryEnvironment(t, logger.TestLogger(t), zapcore.InfoLevel, memory.MemoryEnvironmentConfig{ - Chains: 1, - }) - chain := e.Chains[e.AllChainSelectors()[0]] - cfg := rmn_contract.RMNConfig{ - Voters: []rmn_contract.RMNVoter{ - { - BlessVoteAddr: chain.DeployerKey.From, - CurseVoteAddr: common.HexToAddress("0x3"), - BlessWeight: 1, - CurseWeight: 1, - }, - { - BlessVoteAddr: common.HexToAddress("0x1"), - CurseVoteAddr: common.HexToAddress("0x2"), - BlessWeight: 1, - CurseWeight: 1, - }, - }, - BlessWeightThreshold: uint16(2), - CurseWeightThreshold: uint16(1), - } - _, tx, c, err := rmn_contract.DeployRMNContract( - chain.DeployerKey, chain.Client, cfg) - require.NoError(t, err) - _, err = chain.Confirm(tx) - require.NoError(t, err) - v, err := GenerateRMNView(c) - require.NoError(t, err) - assert.Equal(t, v.Owner, chain.DeployerKey.From) - assert.Equal(t, v.TypeAndVersion, "RMN 1.5.0") - assert.Equal(t, v.ConfigDetails.Version, uint32(1)) - assert.Equal(t, v.ConfigDetails.Config, cfg) - _, err = json.MarshalIndent(v, "", " ") - require.NoError(t, err) -} diff --git a/deployment/ccip/view/v1_6/capreg.go b/deployment/ccip/view/v1_6/capreg.go new file mode 100644 index 00000000000..26ec545d98e --- /dev/null +++ b/deployment/ccip/view/v1_6/capreg.go @@ -0,0 +1,45 @@ +package v1_6 + +import ( + "github.com/ethereum/go-ethereum/common" + + "github.com/smartcontractkit/chainlink/deployment/common/view/types" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry" +) + +// CapRegView denotes a view of the capabilities registry contract. +// Note that the contract itself is 1.0.0 versioned, but we're releasing it first +// as part of 1.6 for CCIP. +type CapRegView struct { + types.ContractMetaData + Capabilities []CapabilityView `json:"capabilities,omitempty"` +} + +type CapabilityView struct { + LabelledName string `json:"labelledName"` + Version string `json:"version"` + ConfigContract common.Address `json:"configContract"` +} + +func GenerateCapRegView(capReg *capabilities_registry.CapabilitiesRegistry) (CapRegView, error) { + tv, err := types.NewContractMetaData(capReg, capReg.Address()) + if err != nil { + return CapRegView{}, err + } + caps, err := capReg.GetCapabilities(nil) + if err != nil { + return CapRegView{}, err + } + var capViews []CapabilityView + for _, capability := range caps { + capViews = append(capViews, CapabilityView{ + LabelledName: capability.LabelledName, + Version: capability.Version, + ConfigContract: capability.ConfigurationContract, + }) + } + return CapRegView{ + ContractMetaData: tv, + Capabilities: capViews, + }, nil +} diff --git a/deployment/ccip/view/v1_6/ccip_home.go b/deployment/ccip/view/v1_6/ccip_home.go deleted file mode 100644 index b188c32c079..00000000000 --- a/deployment/ccip/view/v1_6/ccip_home.go +++ /dev/null @@ -1,85 +0,0 @@ -package v1_6 - -import ( - "fmt" - "math/big" - - "github.com/ethereum/go-ethereum/common" - - "github.com/smartcontractkit/chainlink/deployment/common/view/types" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/ccip_home" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry_1_1_0" -) - -// https://github.com/smartcontractkit/chainlink/blob/develop/contracts/src/v0.8/ccip/libraries/Internal.sol#L190 -const ( - CommitPluginType = 0 - ExecPluginType = 1 -) - -type DonView struct { - DonID uint32 `json:"donID"` - // TODO: find a way to hexify the bytes here - CommitConfigs ccip_home.GetAllConfigs `json:"commitConfigs"` - ExecConfigs ccip_home.GetAllConfigs `json:"execConfigs"` -} - -type CCIPHomeView struct { - types.ContractMetaData - ChainConfigs []ccip_home.CCIPHomeChainConfigArgs `json:"chainConfigs"` - CapabilityRegistry common.Address `json:"capabilityRegistry"` - Dons []DonView `json:"dons"` -} - -func GenerateCCIPHomeView(cr *capabilities_registry.CapabilitiesRegistry, ch *ccip_home.CCIPHome) (CCIPHomeView, error) { - if ch == nil { - return CCIPHomeView{}, fmt.Errorf("cannot generate view for nil CCIPHome") - } - meta, err := types.NewContractMetaData(ch, ch.Address()) - if err != nil { - return CCIPHomeView{}, fmt.Errorf("failed to generate contract metadata for CCIPHome %s: %w", ch.Address(), err) - } - numChains, err := ch.GetNumChainConfigurations(nil) - if err != nil { - return CCIPHomeView{}, fmt.Errorf("failed to get number of chain configurations for CCIPHome %s: %w", ch.Address(), err) - } - // Pagination shouldn't be required here, but we can add it if needed. - chains, err := ch.GetAllChainConfigs(nil, big.NewInt(0), numChains) - if err != nil { - return CCIPHomeView{}, fmt.Errorf("failed to get all chain configs for CCIPHome %s: %w", ch.Address(), err) - } - crAddr, err := ch.GetCapabilityRegistry(nil) - if err != nil { - return CCIPHomeView{}, fmt.Errorf("failed to get capability registry for CCIPHome %s: %w", ch.Address(), err) - } - if crAddr != cr.Address() { - return CCIPHomeView{}, fmt.Errorf("capability registry address mismatch for CCIPHome %s: %w", ch.Address(), err) - } - dons, err := cr.GetDONs(nil) - if err != nil { - return CCIPHomeView{}, fmt.Errorf("failed to get DONs for CCIPHome %s: %w", ch.Address(), err) - } - // Get every don's configuration. - var dvs []DonView - for _, d := range dons { - commitConfigs, err := ch.GetAllConfigs(nil, d.Id, CommitPluginType) - if err != nil { - return CCIPHomeView{}, fmt.Errorf("failed to get active commit config for CCIPHome %s: %w", ch.Address(), err) - } - execConfigs, err := ch.GetAllConfigs(nil, d.Id, ExecPluginType) - if err != nil { - return CCIPHomeView{}, fmt.Errorf("failed to get active commit config for CCIPHome %s: %w", ch.Address(), err) - } - dvs = append(dvs, DonView{ - DonID: d.Id, - CommitConfigs: commitConfigs, - ExecConfigs: execConfigs, - }) - } - return CCIPHomeView{ - ContractMetaData: meta, - ChainConfigs: chains, - CapabilityRegistry: crAddr, - Dons: dvs, - }, nil -} diff --git a/deployment/ccip/view/v1_6/ccip_home_test.go b/deployment/ccip/view/v1_6/ccip_home_test.go deleted file mode 100644 index 8ea79e8eac3..00000000000 --- a/deployment/ccip/view/v1_6/ccip_home_test.go +++ /dev/null @@ -1,40 +0,0 @@ -package v1_6 - -import ( - "encoding/json" - "testing" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - "go.uber.org/zap/zapcore" - - "github.com/smartcontractkit/chainlink/deployment" - "github.com/smartcontractkit/chainlink/deployment/environment/memory" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/ccip_home" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry_1_1_0" - "github.com/smartcontractkit/chainlink/v2/core/logger" -) - -func TestCCIPHomeView(t *testing.T) { - e := memory.NewMemoryEnvironment(t, logger.TestLogger(t), zapcore.InfoLevel, memory.MemoryEnvironmentConfig{ - Chains: 1, - }) - chain := e.Chains[e.AllChainSelectors()[0]] - _, tx, cr, err := capabilities_registry.DeployCapabilitiesRegistry( - chain.DeployerKey, chain.Client) - require.NoError(t, err) - _, err = deployment.ConfirmIfNoError(chain, tx, err) - require.NoError(t, err) - - _, tx, ch, err := ccip_home.DeployCCIPHome( - chain.DeployerKey, chain.Client, cr.Address()) - _, err = deployment.ConfirmIfNoError(chain, tx, err) - require.NoError(t, err) - - v, err := GenerateCCIPHomeView(cr, ch) - require.NoError(t, err) - assert.Equal(t, v.TypeAndVersion, "CCIPHome 1.6.0-dev") - - _, err = json.MarshalIndent(v, "", " ") - require.NoError(t, err) -} diff --git a/deployment/ccip/view/v1_6/rmnhome.go b/deployment/ccip/view/v1_6/rmnhome.go deleted file mode 100644 index 82d39074d6f..00000000000 --- a/deployment/ccip/view/v1_6/rmnhome.go +++ /dev/null @@ -1,214 +0,0 @@ -package v1_6 - -import ( - "encoding/hex" - "encoding/json" - "fmt" - "math/big" - - "github.com/ethereum/go-ethereum/accounts/abi/bind" - "github.com/smartcontractkit/chainlink/deployment/common/view/types" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/rmn_home" -) - -type RMNHomeView struct { - types.ContractMetaData - CandidateConfig *RMNHomeVersionedConfig `json:"candidateConfig,omitempty"` - ActiveConfig *RMNHomeVersionedConfig `json:"activeConfig,omitempty"` -} - -type RMNHomeVersionedConfig struct { - Version uint32 `json:"version"` - StaticConfig RMNHomeStaticConfig `json:"staticConfig"` - DynamicConfig RMNHomeDynamicConfig `json:"dynamicConfig"` - Digest [32]byte `json:"digest"` -} - -func decodeHexString(hexStr string, expectedLength int) ([]byte, error) { - bytes, err := hex.DecodeString(hexStr) - if err != nil { - return nil, err - } - if len(bytes) != expectedLength { - return nil, fmt.Errorf("invalid length: expected %d, got %d", expectedLength, len(bytes)) - } - return bytes, nil -} - -func (c RMNHomeVersionedConfig) MarshalJSON() ([]byte, error) { - type Alias RMNHomeVersionedConfig - return json.Marshal(&struct { - Digest string `json:"digest"` - *Alias - }{ - Digest: hex.EncodeToString(c.Digest[:]), - Alias: (*Alias)(&c), - }) -} - -func (c *RMNHomeVersionedConfig) UnmarshalJSON(data []byte) error { - type Alias RMNHomeVersionedConfig - aux := &struct { - Digest string `json:"digest"` - *Alias - }{ - Alias: (*Alias)(c), - } - - if err := json.Unmarshal(data, &aux); err != nil { - return err - } - - digestBytes, err := decodeHexString(aux.Digest, 32) - if err != nil { - return err - } - copy(c.Digest[:], digestBytes) - return nil -} - -type RMNHomeStaticConfig struct { - Nodes []RMNHomeNode `json:"nodes"` -} - -type RMNHomeDynamicConfig struct { - SourceChains []RMNHomeSourceChain `json:"sourceChains"` -} - -type RMNHomeSourceChain struct { - ChainSelector uint64 `json:"selector"` - F uint64 `json:"f"` - ObserverNodesBitmap *big.Int `json:"observerNodesBitmap"` -} - -type RMNHomeNode struct { - PeerId [32]byte `json:"peerId"` - OffchainPublicKey [32]byte `json:"offchainPublicKey"` -} - -func (n RMNHomeNode) MarshalJSON() ([]byte, error) { - type Alias RMNHomeNode - return json.Marshal(&struct { - PeerId string `json:"peerId"` - OffchainPublicKey string `json:"offchainPublicKey"` - *Alias - }{ - PeerId: hex.EncodeToString(n.PeerId[:]), - OffchainPublicKey: hex.EncodeToString(n.OffchainPublicKey[:]), - Alias: (*Alias)(&n), - }) -} - -func (n *RMNHomeNode) UnmarshalJSON(data []byte) error { - type Alias RMNHomeNode - aux := &struct { - PeerId string `json:"peerId"` - OffchainPublicKey string `json:"offchainPublicKey"` - *Alias - }{ - Alias: (*Alias)(n), - } - if err := json.Unmarshal(data, &aux); err != nil { - return err - } - - peerIdBytes, err := decodeHexString(aux.PeerId, 32) - if err != nil { - return err - } - copy(n.PeerId[:], peerIdBytes) - - offchainPublicKeyBytes, err := decodeHexString(aux.OffchainPublicKey, 32) - if err != nil { - return err - } - copy(n.OffchainPublicKey[:], offchainPublicKeyBytes) - - return nil -} - -type DigestFunc func(*bind.CallOpts) ([32]byte, error) - -func mapNodes(nodes []rmn_home.RMNHomeNode) []RMNHomeNode { - result := make([]RMNHomeNode, len(nodes)) - for i, node := range nodes { - result[i] = RMNHomeNode{ - PeerId: node.PeerId, - OffchainPublicKey: node.OffchainPublicKey, - } - } - return result -} - -func mapSourceChains(chains []rmn_home.RMNHomeSourceChain) []RMNHomeSourceChain { - result := make([]RMNHomeSourceChain, len(chains)) - for i, chain := range chains { - result[i] = RMNHomeSourceChain{ - ChainSelector: chain.ChainSelector, - F: chain.F, - ObserverNodesBitmap: chain.ObserverNodesBitmap, - } - } - return result -} - -func generateRmnHomeVersionedConfig(reader *rmn_home.RMNHome, digestFunc DigestFunc) (*RMNHomeVersionedConfig, error) { - address := reader.Address() - digest, err := digestFunc(nil) - if err != nil { - return nil, fmt.Errorf("failed to get digest for contract %s: %w", address, err) - } - - if digest == [32]byte{} { - return nil, nil - } - - config, err := reader.GetConfig(nil, digest) - if err != nil { - return nil, fmt.Errorf("failed to get config for contract %s: %w", address, err) - } - - staticConfig := RMNHomeStaticConfig{ - Nodes: mapNodes(config.VersionedConfig.StaticConfig.Nodes), - } - - dynamicConfig := RMNHomeDynamicConfig{ - SourceChains: mapSourceChains(config.VersionedConfig.DynamicConfig.SourceChains), - } - - return &RMNHomeVersionedConfig{ - Version: config.VersionedConfig.Version, - Digest: config.VersionedConfig.ConfigDigest, - StaticConfig: staticConfig, - DynamicConfig: dynamicConfig, - }, nil -} - -func GenerateRMNHomeView(rmnReader *rmn_home.RMNHome) (RMNHomeView, error) { - if rmnReader == nil { - return RMNHomeView{}, nil - } - - address := rmnReader.Address() - - activeConfig, err := generateRmnHomeVersionedConfig(rmnReader, rmnReader.GetActiveDigest) - if err != nil { - return RMNHomeView{}, fmt.Errorf("failed to generate active config for contract %s: %w", address, err) - } - - candidateConfig, err := generateRmnHomeVersionedConfig(rmnReader, rmnReader.GetCandidateDigest) - if err != nil { - return RMNHomeView{}, fmt.Errorf("failed to generate candidate config for contract %s: %w", address, err) - } - - contractMetaData, err := types.NewContractMetaData(rmnReader, rmnReader.Address()) - if err != nil { - return RMNHomeView{}, fmt.Errorf("failed to create contract metadata for contract %s: %w", address, err) - } - - return RMNHomeView{ - ContractMetaData: contractMetaData, - CandidateConfig: candidateConfig, - ActiveConfig: activeConfig, - }, nil -} diff --git a/deployment/ccip/view/view.go b/deployment/ccip/view/view.go index 8f698ba2277..9ef8583bdf6 100644 --- a/deployment/ccip/view/view.go +++ b/deployment/ccip/view/view.go @@ -19,25 +19,13 @@ type ChainView struct { // v1.5 TokenAdminRegistry map[string]v1_5.TokenAdminRegistryView `json:"tokenAdminRegistry,omitempty"` CommitStore map[string]v1_5.CommitStoreView `json:"commitStore,omitempty"` - PriceRegistry map[string]v1_2.PriceRegistryView `json:"priceRegistry,omitempty"` - EVM2EVMOnRamp map[string]v1_5.OnRampView `json:"evm2evmOnRamp,omitempty"` - EVM2EVMOffRamp map[string]v1_5.OffRampView `json:"evm2evmOffRamp,omitempty"` - RMN map[string]v1_5.RMNView `json:"rmn,omitempty"` - // v1.6 - FeeQuoter map[string]v1_6.FeeQuoterView `json:"feeQuoter,omitempty"` - NonceManager map[string]v1_6.NonceManagerView `json:"nonceManager,omitempty"` - RMNRemote map[string]v1_6.RMNRemoteView `json:"rmnRemote,omitempty"` - RMNHome map[string]v1_6.RMNHomeView `json:"rmnHome,omitempty"` - OnRamp map[string]v1_6.OnRampView `json:"onRamp,omitempty"` - OffRamp map[string]v1_6.OffRampView `json:"offRamp,omitempty"` - // TODO: Perhaps restrict to one CCIPHome/CR? Shouldn't - // be more than one per env. - CCIPHome map[string]v1_6.CCIPHomeView `json:"ccipHome,omitempty"` + FeeQuoter map[string]v1_6.FeeQuoterView `json:"feeQuoter,omitempty"` + NonceManager map[string]v1_6.NonceManagerView `json:"nonceManager,omitempty"` + RMN map[string]v1_6.RMNRemoteView `json:"rmn,omitempty"` + OnRamp map[string]v1_6.OnRampView `json:"onRamp,omitempty"` + OffRamp map[string]v1_6.OffRampView `json:"offRamp,omitempty"` CapabilityRegistry map[string]common_v1_0.CapabilityRegistryView `json:"capabilityRegistry,omitempty"` - MCMSWithTimelock common_v1_0.MCMSWithTimelockView `json:"mcmsWithTimelock,omitempty"` - LinkToken common_v1_0.LinkTokenView `json:"linkToken,omitempty"` - StaticLinkToken common_v1_0.StaticLinkTokenView `json:"staticLinkToken,omitempty"` } func NewChain() ChainView { @@ -45,26 +33,17 @@ func NewChain() ChainView { // v1.0 RMNProxy: make(map[string]v1_0.RMNProxyView), // v1.2 - Router: make(map[string]v1_2.RouterView), - PriceRegistry: make(map[string]v1_2.PriceRegistryView), + Router: make(map[string]v1_2.RouterView), // v1.5 TokenAdminRegistry: make(map[string]v1_5.TokenAdminRegistryView), CommitStore: make(map[string]v1_5.CommitStoreView), - EVM2EVMOnRamp: make(map[string]v1_5.OnRampView), - EVM2EVMOffRamp: make(map[string]v1_5.OffRampView), - RMN: make(map[string]v1_5.RMNView), // v1.6 FeeQuoter: make(map[string]v1_6.FeeQuoterView), NonceManager: make(map[string]v1_6.NonceManagerView), - RMNRemote: make(map[string]v1_6.RMNRemoteView), - RMNHome: make(map[string]v1_6.RMNHomeView), + RMN: make(map[string]v1_6.RMNRemoteView), OnRamp: make(map[string]v1_6.OnRampView), OffRamp: make(map[string]v1_6.OffRampView), CapabilityRegistry: make(map[string]common_v1_0.CapabilityRegistryView), - CCIPHome: make(map[string]v1_6.CCIPHomeView), - MCMSWithTimelock: common_v1_0.MCMSWithTimelockView{}, - LinkToken: common_v1_0.LinkTokenView{}, - StaticLinkToken: common_v1_0.StaticLinkTokenView{}, } } diff --git a/deployment/common/changeset/deploy_link_token.go b/deployment/common/changeset/deploy_link_token.go deleted file mode 100644 index c115a7ee083..00000000000 --- a/deployment/common/changeset/deploy_link_token.go +++ /dev/null @@ -1,59 +0,0 @@ -package changeset - -import ( - "fmt" - - "github.com/smartcontractkit/chainlink-common/pkg/logger" - - "github.com/smartcontractkit/chainlink/deployment" - "github.com/smartcontractkit/chainlink/deployment/common/types" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/shared/generated/link_token" -) - -var _ deployment.ChangeSet[[]uint64] = DeployLinkToken - -// DeployLinkToken deploys a link token contract to the chain identified by the ChainSelector. -func DeployLinkToken(e deployment.Environment, chains []uint64) (deployment.ChangesetOutput, error) { - for _, chain := range chains { - _, ok := e.Chains[chain] - if !ok { - return deployment.ChangesetOutput{}, fmt.Errorf("chain not found in environment") - } - } - newAddresses := deployment.NewMemoryAddressBook() - for _, chain := range chains { - _, err := deployLinkTokenContract( - e.Logger, e.Chains[chain], newAddresses, - ) - if err != nil { - return deployment.ChangesetOutput{AddressBook: newAddresses}, err - } - } - return deployment.ChangesetOutput{AddressBook: newAddresses}, nil -} - -func deployLinkTokenContract( - lggr logger.Logger, - chain deployment.Chain, - ab deployment.AddressBook, -) (*deployment.ContractDeploy[*link_token.LinkToken], error) { - linkToken, err := deployment.DeployContract[*link_token.LinkToken](lggr, chain, ab, - func(chain deployment.Chain) deployment.ContractDeploy[*link_token.LinkToken] { - linkTokenAddr, tx, linkToken, err2 := link_token.DeployLinkToken( - chain.DeployerKey, - chain.Client, - ) - return deployment.ContractDeploy[*link_token.LinkToken]{ - Address: linkTokenAddr, - Contract: linkToken, - Tx: tx, - Tv: deployment.NewTypeAndVersion(types.LinkToken, deployment.Version1_0_0), - Err: err2, - } - }) - if err != nil { - lggr.Errorw("Failed to deploy link token", "chain", chain.String(), "err", err) - return linkToken, err - } - return linkToken, nil -} diff --git a/deployment/common/changeset/deploy_link_token_test.go b/deployment/common/changeset/deploy_link_token_test.go deleted file mode 100644 index bc472d2a247..00000000000 --- a/deployment/common/changeset/deploy_link_token_test.go +++ /dev/null @@ -1,35 +0,0 @@ -package changeset_test - -import ( - "testing" - - "github.com/stretchr/testify/require" - "go.uber.org/zap/zapcore" - - "github.com/smartcontractkit/chainlink/deployment/common/changeset" - "github.com/smartcontractkit/chainlink/deployment/environment/memory" - "github.com/smartcontractkit/chainlink/v2/core/logger" -) - -func TestDeployLinkToken(t *testing.T) { - t.Parallel() - lggr := logger.TestLogger(t) - e := memory.NewMemoryEnvironment(t, lggr, zapcore.InfoLevel, memory.MemoryEnvironmentConfig{ - Chains: 1, - }) - chain1 := e.AllChainSelectors()[0] - e, err := changeset.ApplyChangesets(t, e, nil, []changeset.ChangesetApplication{ - { - Changeset: changeset.WrapChangeSet(changeset.DeployLinkToken), - Config: []uint64{chain1}, - }, - }) - require.NoError(t, err) - addrs, err := e.ExistingAddresses.AddressesForChain(chain1) - require.NoError(t, err) - state, err := changeset.MaybeLoadLinkTokenChainState(e.Chains[chain1], addrs) - require.NoError(t, err) - // View itself already unit tested - _, err = state.GenerateLinkView() - require.NoError(t, err) -} diff --git a/deployment/common/changeset/deploy_mcms_with_timelock.go b/deployment/common/changeset/deploy_mcms_with_timelock.go deleted file mode 100644 index 06f9aba6164..00000000000 --- a/deployment/common/changeset/deploy_mcms_with_timelock.go +++ /dev/null @@ -1,39 +0,0 @@ -package changeset - -import ( - "context" - "fmt" - - "github.com/ethereum/go-ethereum/accounts/abi/bind" - "github.com/ethereum/go-ethereum/common" - - "github.com/smartcontractkit/chainlink/deployment" - "github.com/smartcontractkit/chainlink/deployment/common/changeset/internal" - "github.com/smartcontractkit/chainlink/deployment/common/types" -) - -var _ deployment.ChangeSet[map[uint64]types.MCMSWithTimelockConfig] = DeployMCMSWithTimelock - -func DeployMCMSWithTimelock(e deployment.Environment, cfgByChain map[uint64]types.MCMSWithTimelockConfig) (deployment.ChangesetOutput, error) { - newAddresses := deployment.NewMemoryAddressBook() - err := internal.DeployMCMSWithTimelockContractsBatch( - e.Logger, e.Chains, newAddresses, cfgByChain, - ) - if err != nil { - return deployment.ChangesetOutput{AddressBook: newAddresses}, err - } - return deployment.ChangesetOutput{AddressBook: newAddresses}, nil -} - -func ValidateOwnership(ctx context.Context, mcms bool, deployerKey, timelock common.Address, contract Ownable) error { - owner, err := contract.Owner(&bind.CallOpts{Context: ctx}) - if err != nil { - return fmt.Errorf("failed to get owner: %w", err) - } - if mcms && owner != timelock { - return fmt.Errorf("%s not owned by deployer key", contract.Address()) - } else if !mcms && owner != deployerKey { - return fmt.Errorf("%s not owned by deployer key", contract.Address()) - } - return nil -} diff --git a/deployment/common/changeset/example/add_mint_burners_link.go b/deployment/common/changeset/example/add_mint_burners_link.go deleted file mode 100644 index 7322f99dd60..00000000000 --- a/deployment/common/changeset/example/add_mint_burners_link.go +++ /dev/null @@ -1,70 +0,0 @@ -package example - -import ( - "github.com/ethereum/go-ethereum/accounts/abi/bind" - "github.com/ethereum/go-ethereum/common" - - "github.com/smartcontractkit/chainlink/deployment" - "github.com/smartcontractkit/chainlink/deployment/common/changeset" -) - -type AddMintersBurnersLinkConfig struct { - ChainSelector uint64 - Minters []common.Address - Burners []common.Address -} - -var _ deployment.ChangeSet[*AddMintersBurnersLinkConfig] = AddMintersBurnersLink - -// AddMintersBurnersLink grants the minter / burner role to the provided addresses. -func AddMintersBurnersLink(e deployment.Environment, cfg *AddMintersBurnersLinkConfig) (deployment.ChangesetOutput, error) { - - chain := e.Chains[cfg.ChainSelector] - addresses, err := e.ExistingAddresses.AddressesForChain(cfg.ChainSelector) - if err != nil { - return deployment.ChangesetOutput{}, err - } - linkState, err := changeset.MaybeLoadLinkTokenChainState(chain, addresses) - if err != nil { - return deployment.ChangesetOutput{}, err - } - - for _, minter := range cfg.Minters { - // check if minter is already a minter - isMinter, err := linkState.LinkToken.IsMinter(&bind.CallOpts{Context: e.GetContext()}, minter) - if err != nil { - return deployment.ChangesetOutput{}, err - } - if isMinter { - continue - } - tx, err := linkState.LinkToken.GrantMintRole(chain.DeployerKey, minter) - if err != nil { - return deployment.ChangesetOutput{}, err - } - _, err = deployment.ConfirmIfNoError(chain, tx, err) - if err != nil { - return deployment.ChangesetOutput{}, err - } - } - for _, burner := range cfg.Burners { - // check if burner is already a burner - isBurner, err := linkState.LinkToken.IsBurner(&bind.CallOpts{Context: e.GetContext()}, burner) - if err != nil { - return deployment.ChangesetOutput{}, err - } - if isBurner { - continue - } - tx, err := linkState.LinkToken.GrantBurnRole(chain.DeployerKey, burner) - if err != nil { - return deployment.ChangesetOutput{}, err - } - _, err = deployment.ConfirmIfNoError(chain, tx, err) - if err != nil { - return deployment.ChangesetOutput{}, err - } - } - return deployment.ChangesetOutput{}, nil - -} diff --git a/deployment/common/changeset/example/add_mint_burners_link_test.go b/deployment/common/changeset/example/add_mint_burners_link_test.go deleted file mode 100644 index 4dbfddc0b30..00000000000 --- a/deployment/common/changeset/example/add_mint_burners_link_test.go +++ /dev/null @@ -1,50 +0,0 @@ -package example_test - -import ( - "context" - "testing" - - "github.com/ethereum/go-ethereum/accounts/abi/bind" - "github.com/ethereum/go-ethereum/common" - "github.com/stretchr/testify/require" - - "github.com/smartcontractkit/chainlink/deployment/common/changeset" - "github.com/smartcontractkit/chainlink/deployment/common/changeset/example" -) - -// TestAddMintersBurnersLink tests the AddMintersBurnersLink changeset -func TestAddMintersBurnersLink(t *testing.T) { - t.Parallel() - ctx := context.Background() - // Deploy Link Token and Timelock contracts and add addresses to environment - env := setupLinkTransferTestEnv(t) - - chainSelector := env.AllChainSelectors()[0] - chain := env.Chains[chainSelector] - addrs, err := env.ExistingAddresses.AddressesForChain(chainSelector) - require.NoError(t, err) - require.Len(t, addrs, 6) - - mcmsState, err := changeset.MaybeLoadMCMSWithTimelockChainState(chain, addrs) - require.NoError(t, err) - linkState, err := changeset.MaybeLoadLinkTokenChainState(chain, addrs) - require.NoError(t, err) - - timelockAddress := mcmsState.Timelock.Address() - - // Mint some funds - _, err = example.AddMintersBurnersLink(env, &example.AddMintersBurnersLinkConfig{ - ChainSelector: chainSelector, - Minters: []common.Address{timelockAddress}, - Burners: []common.Address{timelockAddress}, - }) - require.NoError(t, err) - - // check timelock balance - isMinter, err := linkState.LinkToken.IsMinter(&bind.CallOpts{Context: ctx}, timelockAddress) - require.NoError(t, err) - require.True(t, isMinter) - isBurner, err := linkState.LinkToken.IsBurner(&bind.CallOpts{Context: ctx}, timelockAddress) - require.NoError(t, err) - require.True(t, isBurner) -} diff --git a/deployment/common/changeset/example/link_transfer.go b/deployment/common/changeset/example/link_transfer.go deleted file mode 100644 index 2e3be48a4d1..00000000000 --- a/deployment/common/changeset/example/link_transfer.go +++ /dev/null @@ -1,239 +0,0 @@ -package example - -import ( - "errors" - "fmt" - "math/big" - "time" - - "github.com/ethereum/go-ethereum/accounts/abi/bind" - "github.com/ethereum/go-ethereum/common" - ethTypes "github.com/ethereum/go-ethereum/core/types" - owner_helpers "github.com/smartcontractkit/ccip-owner-contracts/pkg/gethwrappers" - chain_selectors "github.com/smartcontractkit/chain-selectors" - - "github.com/smartcontractkit/ccip-owner-contracts/pkg/proposal/mcms" - "github.com/smartcontractkit/ccip-owner-contracts/pkg/proposal/timelock" - - "github.com/smartcontractkit/chainlink/deployment" - "github.com/smartcontractkit/chainlink/deployment/common/changeset" - "github.com/smartcontractkit/chainlink/deployment/common/proposalutils" - "github.com/smartcontractkit/chainlink/deployment/common/types" -) - -const MaxTimelockDelay = 24 * 7 * time.Hour - -type TransferConfig struct { - To common.Address - Value *big.Int -} - -type MCMSConfig struct { - MinDelay time.Duration // delay for timelock worker to execute the transfers. - OverrideRoot bool -} - -type LinkTransferConfig struct { - Transfers map[uint64][]TransferConfig - From common.Address - McmsConfig *MCMSConfig -} - -var _ deployment.ChangeSet[*LinkTransferConfig] = LinkTransfer - -func getDeployer(e deployment.Environment, chain uint64, mcmConfig *MCMSConfig) *bind.TransactOpts { - if mcmConfig == nil { - return e.Chains[chain].DeployerKey - } - - return deployment.SimTransactOpts() -} - -// Validate checks that the LinkTransferConfig is valid. -func (cfg LinkTransferConfig) Validate(e deployment.Environment) error { - ctx := e.GetContext() - // Check that Transfers map has at least one chainSel - if len(cfg.Transfers) == 0 { - return errors.New("transfers map must have at least one chainSel") - } - - // Check transfers config values. - for chainSel, transfers := range cfg.Transfers { - selector, err := chain_selectors.GetSelectorFamily(chainSel) - if err != nil { - return fmt.Errorf("invalid chain selector: %w", err) - } - if selector != chain_selectors.FamilyEVM { - return fmt.Errorf("chain selector %d is not an EVM chain", chainSel) - } - chain, ok := e.Chains[chainSel] - if !ok { - return fmt.Errorf("chain with selector %d not found", chainSel) - } - addrs, err := e.ExistingAddresses.AddressesForChain(chainSel) - if err != nil { - return fmt.Errorf("error getting addresses for chain %d: %w", chainSel, err) - } - if len(transfers) == 0 { - return fmt.Errorf("transfers for chainSel %d must have at least one LinkTransfer", chainSel) - } - totalAmount := big.NewInt(0) - linkState, err := changeset.MaybeLoadLinkTokenChainState(chain, addrs) - if err != nil { - return fmt.Errorf("error loading link token state during validation: %w", err) - } - for _, transfer := range transfers { - if transfer.To == (common.Address{}) { - return errors.New("'to' address for transfers must be set") - } - if transfer.Value == nil { - return errors.New("value for transfers must be set") - } - if transfer.Value.Cmp(big.NewInt(0)) == 0 { - return errors.New("value for transfers must be non-zero") - } - if transfer.Value.Cmp(big.NewInt(0)) == -1 { - return errors.New("value for transfers must be positive") - } - totalAmount.Add(totalAmount, transfer.Value) - } - // check that from address has enough funds for the transfers - balance, err := linkState.LinkToken.BalanceOf(&bind.CallOpts{Context: ctx}, cfg.From) - if balance.Cmp(totalAmount) < 0 { - return fmt.Errorf("sender does not have enough funds for transfers for chain selector %d, required: %s, available: %s", chainSel, totalAmount.String(), balance.String()) - } - } - - if cfg.McmsConfig == nil { - return nil - } - - // Upper bound for min delay (7 days) - if cfg.McmsConfig.MinDelay > MaxTimelockDelay { - return errors.New("minDelay must be less than 7 days") - } - - return nil -} - -// initStatePerChain initializes the state for each chain selector on the provided config -func initStatePerChain(cfg *LinkTransferConfig, e deployment.Environment) ( - linkStatePerChain map[uint64]*changeset.LinkTokenState, - mcmsStatePerChain map[uint64]*changeset.MCMSWithTimelockState, - err error) { - linkStatePerChain = map[uint64]*changeset.LinkTokenState{} - mcmsStatePerChain = map[uint64]*changeset.MCMSWithTimelockState{} - // Load state for each chain - chainSelectors := []uint64{} - for chainSelector := range cfg.Transfers { - chainSelectors = append(chainSelectors, chainSelector) - } - linkStatePerChain, err = changeset.MaybeLoadLinkTokenState(e, chainSelectors) - if err != nil { - return nil, nil, err - } - mcmsStatePerChain, err = changeset.MaybeLoadMCMSWithTimelockState(e, chainSelectors) - if err != nil { - return nil, nil, err - - } - return linkStatePerChain, mcmsStatePerChain, nil -} - -// transferOrBuildTx transfers the LINK tokens or builds the tx for the MCMS proposal -func transferOrBuildTx( - e deployment.Environment, - linkState *changeset.LinkTokenState, - transfer TransferConfig, - opts *bind.TransactOpts, - chain deployment.Chain, - mcmsConfig *MCMSConfig) (*ethTypes.Transaction, error) { - tx, err := linkState.LinkToken.Transfer(opts, transfer.To, transfer.Value) - if err != nil { - return nil, fmt.Errorf("error packing transfer tx data: %w", err) - } - // only wait for tx if we are not using MCMS - if mcmsConfig == nil { - if _, err := deployment.ConfirmIfNoError(chain, tx, err); err != nil { - e.Logger.Errorw("Failed to confirm transfer tx", "chain", chain.String(), "err", err) - return nil, err - } - } - return tx, nil - -} - -// LinkTransfer takes the given link transfers and executes them or creates an MCMS proposal for them. -func LinkTransfer(e deployment.Environment, cfg *LinkTransferConfig) (deployment.ChangesetOutput, error) { - - err := cfg.Validate(e) - if err != nil { - return deployment.ChangesetOutput{}, fmt.Errorf("invalid LinkTransferConfig: %w", err) - } - chainSelectors := []uint64{} - for chainSelector := range cfg.Transfers { - chainSelectors = append(chainSelectors, chainSelector) - } - mcmsPerChain := map[uint64]*owner_helpers.ManyChainMultiSig{} - - timelockAddresses := map[uint64]common.Address{} - // Initialize state for each chain - linkStatePerChain, mcmsStatePerChain, err := initStatePerChain(cfg, e) - - allBatches := []timelock.BatchChainOperation{} - for chainSelector := range cfg.Transfers { - chainID := mcms.ChainIdentifier(chainSelector) - chain := e.Chains[chainSelector] - linkAddress := linkStatePerChain[chainSelector].LinkToken.Address() - mcmsState := mcmsStatePerChain[chainSelector] - linkState := linkStatePerChain[chainSelector] - - timelockAddress := mcmsState.Timelock.Address() - - mcmsPerChain[uint64(chainID)] = mcmsState.ProposerMcm - - timelockAddresses[chainSelector] = timelockAddress - batch := timelock.BatchChainOperation{ - ChainIdentifier: chainID, - Batch: []mcms.Operation{}, - } - - opts := getDeployer(e, chainSelector, cfg.McmsConfig) - totalAmount := big.NewInt(0) - for _, transfer := range cfg.Transfers[chainSelector] { - tx, err := transferOrBuildTx(e, linkState, transfer, opts, chain, cfg.McmsConfig) - if err != nil { - return deployment.ChangesetOutput{}, err - } - op := mcms.Operation{ - To: linkAddress, - Data: tx.Data(), - Value: big.NewInt(0), - ContractType: string(types.LinkToken), - } - batch.Batch = append(batch.Batch, op) - totalAmount.Add(totalAmount, transfer.Value) - } - - allBatches = append(allBatches, batch) - } - - if cfg.McmsConfig != nil { - proposal, err := proposalutils.BuildProposalFromBatches( - timelockAddresses, - mcmsPerChain, - allBatches, - "LINK Value transfer proposal", - cfg.McmsConfig.MinDelay, - ) - if err != nil { - return deployment.ChangesetOutput{}, err - } - - return deployment.ChangesetOutput{ - Proposals: []timelock.MCMSWithTimelockProposal{*proposal}, - }, nil - } - - return deployment.ChangesetOutput{}, nil -} diff --git a/deployment/common/changeset/example/link_transfer_test.go b/deployment/common/changeset/example/link_transfer_test.go deleted file mode 100644 index eecfbd37c95..00000000000 --- a/deployment/common/changeset/example/link_transfer_test.go +++ /dev/null @@ -1,373 +0,0 @@ -package example_test - -import ( - "context" - "math/big" - "testing" - "time" - - "github.com/ethereum/go-ethereum/accounts/abi/bind" - "github.com/ethereum/go-ethereum/common" - chain_selectors "github.com/smartcontractkit/chain-selectors" - - "github.com/smartcontractkit/chainlink/deployment/common/changeset/example" - "github.com/smartcontractkit/chainlink/deployment/common/proposalutils" - "github.com/smartcontractkit/chainlink/v2/core/logger" - - "github.com/stretchr/testify/require" - "go.uber.org/zap/zapcore" - - "github.com/smartcontractkit/chainlink/deployment" - "github.com/smartcontractkit/chainlink/deployment/common/changeset" - "github.com/smartcontractkit/chainlink/deployment/common/types" - "github.com/smartcontractkit/chainlink/deployment/environment/memory" -) - -// setupLinkTransferContracts deploys all required contracts for the link transfer tests and returns the updated env. -func setupLinkTransferTestEnv(t *testing.T) deployment.Environment { - - lggr := logger.TestLogger(t) - cfg := memory.MemoryEnvironmentConfig{ - Nodes: 1, - Chains: 2, - } - env := memory.NewMemoryEnvironment(t, lggr, zapcore.DebugLevel, cfg) - chainSelector := env.AllChainSelectors()[0] - config := proposalutils.SingleGroupMCMS(t) - - // Deploy MCMS and Timelock - env, err := changeset.ApplyChangesets(t, env, nil, []changeset.ChangesetApplication{ - { - Changeset: changeset.WrapChangeSet(changeset.DeployLinkToken), - Config: []uint64{chainSelector}, - }, - { - Changeset: changeset.WrapChangeSet(changeset.DeployMCMSWithTimelock), - Config: map[uint64]types.MCMSWithTimelockConfig{ - chainSelector: { - Canceller: config, - Bypasser: config, - Proposer: config, - TimelockMinDelay: big.NewInt(0), - }, - }, - }, - }) - require.NoError(t, err) - return env -} - -// TestLinkTransferMCMS tests the LinkTransfer changeset by sending LINK from a timelock contract -// to the deployer key via mcms proposal. -func TestLinkTransferMCMS(t *testing.T) { - t.Parallel() - ctx := context.Background() - - env := setupLinkTransferTestEnv(t) - chainSelector := env.AllChainSelectors()[0] - chain := env.Chains[chainSelector] - addrs, err := env.ExistingAddresses.AddressesForChain(chainSelector) - require.NoError(t, err) - require.Len(t, addrs, 6) - - mcmsState, err := changeset.MaybeLoadMCMSWithTimelockChainState(chain, addrs) - require.NoError(t, err) - linkState, err := changeset.MaybeLoadLinkTokenChainState(chain, addrs) - require.NoError(t, err) - timelockAddress := mcmsState.Timelock.Address() - - // Mint some funds - // grant minter permissions - tx, err := linkState.LinkToken.GrantMintRole(chain.DeployerKey, chain.DeployerKey.From) - require.NoError(t, err) - _, err = deployment.ConfirmIfNoError(chain, tx, err) - require.NoError(t, err) - - tx, err = linkState.LinkToken.Mint(chain.DeployerKey, timelockAddress, big.NewInt(750)) - require.NoError(t, err) - _, err = deployment.ConfirmIfNoError(chain, tx, err) - require.NoError(t, err) - - timelocks := map[uint64]*proposalutils.TimelockExecutionContracts{ - chainSelector: { - Timelock: mcmsState.Timelock, - CallProxy: mcmsState.CallProxy, - }, - } - // Apply the changeset - _, err = changeset.ApplyChangesets(t, env, timelocks, []changeset.ChangesetApplication{ - // the changeset produces proposals, ApplyChangesets will sign & execute them. - // in practice, signing and executing are separated processes. - { - Changeset: changeset.WrapChangeSet(example.LinkTransfer), - Config: &example.LinkTransferConfig{ - From: timelockAddress, - Transfers: map[uint64][]example.TransferConfig{ - chainSelector: { - { - To: chain.DeployerKey.From, - Value: big.NewInt(500), - }, - }, - }, - McmsConfig: &example.MCMSConfig{ - MinDelay: 0, - OverrideRoot: true, - }, - }, - }, - }) - require.NoError(t, err) - - // Check new balances - endBalance, err := linkState.LinkToken.BalanceOf(&bind.CallOpts{Context: ctx}, chain.DeployerKey.From) - require.NoError(t, err) - expectedBalance := big.NewInt(500) - require.Equal(t, expectedBalance, endBalance) - - // check timelock balance - endBalance, err = linkState.LinkToken.BalanceOf(&bind.CallOpts{Context: ctx}, timelockAddress) - require.NoError(t, err) - expectedBalance = big.NewInt(250) - require.Equal(t, expectedBalance, endBalance) -} - -// TestLinkTransfer tests the LinkTransfer changeset by sending LINK from a timelock contract to the deployer key. -func TestLinkTransfer(t *testing.T) { - t.Parallel() - ctx := context.Background() - - env := setupLinkTransferTestEnv(t) - chainSelector := env.AllChainSelectors()[0] - chain := env.Chains[chainSelector] - addrs, err := env.ExistingAddresses.AddressesForChain(chainSelector) - require.NoError(t, err) - require.Len(t, addrs, 6) - - mcmsState, err := changeset.MaybeLoadMCMSWithTimelockChainState(chain, addrs) - require.NoError(t, err) - linkState, err := changeset.MaybeLoadLinkTokenChainState(chain, addrs) - require.NoError(t, err) - timelockAddress := mcmsState.Timelock.Address() - - // Mint some funds - // grant minter permissions - tx, err := linkState.LinkToken.GrantMintRole(chain.DeployerKey, chain.DeployerKey.From) - require.NoError(t, err) - _, err = deployment.ConfirmIfNoError(chain, tx, err) - require.NoError(t, err) - - tx, err = linkState.LinkToken.Mint(chain.DeployerKey, chain.DeployerKey.From, big.NewInt(750)) - require.NoError(t, err) - _, err = deployment.ConfirmIfNoError(chain, tx, err) - require.NoError(t, err) - - timelocks := map[uint64]*proposalutils.TimelockExecutionContracts{ - chainSelector: { - Timelock: mcmsState.Timelock, - CallProxy: mcmsState.CallProxy, - }, - } - - // Apply the changeset - _, err = changeset.ApplyChangesets(t, env, timelocks, []changeset.ChangesetApplication{ - // the changeset produces proposals, ApplyChangesets will sign & execute them. - // in practice, signing and executing are separated processes. - { - Changeset: changeset.WrapChangeSet(example.LinkTransfer), - Config: &example.LinkTransferConfig{ - From: chain.DeployerKey.From, - Transfers: map[uint64][]example.TransferConfig{ - chainSelector: { - { - To: timelockAddress, - Value: big.NewInt(500), - }, - }, - }, - // No MCMSConfig here means we'll execute the txs directly. - }, - }, - }) - require.NoError(t, err) - - // Check new balances - endBalance, err := linkState.LinkToken.BalanceOf(&bind.CallOpts{Context: ctx}, chain.DeployerKey.From) - require.NoError(t, err) - expectedBalance := big.NewInt(250) - require.Equal(t, expectedBalance, endBalance) - - // check timelock balance - endBalance, err = linkState.LinkToken.BalanceOf(&bind.CallOpts{Context: ctx}, timelockAddress) - require.NoError(t, err) - expectedBalance = big.NewInt(500) - require.Equal(t, expectedBalance, endBalance) -} - -func TestValidate(t *testing.T) { - env := setupLinkTransferTestEnv(t) - chainSelector := env.AllChainSelectors()[0] - chain := env.Chains[chainSelector] - addrs, err := env.ExistingAddresses.AddressesForChain(chainSelector) - require.NoError(t, err) - require.Len(t, addrs, 6) - mcmsState, err := changeset.MaybeLoadMCMSWithTimelockChainState(chain, addrs) - require.NoError(t, err) - linkState, err := changeset.MaybeLoadLinkTokenChainState(chain, addrs) - require.NoError(t, err) - tx, err := linkState.LinkToken.GrantMintRole(chain.DeployerKey, chain.DeployerKey.From) - require.NoError(t, err) - _, err = deployment.ConfirmIfNoError(chain, tx, err) - require.NoError(t, err) - tx, err = linkState.LinkToken.Mint(chain.DeployerKey, chain.DeployerKey.From, big.NewInt(750)) - require.NoError(t, err) - _, err = deployment.ConfirmIfNoError(chain, tx, err) - - require.NoError(t, err) - tests := []struct { - name string - cfg example.LinkTransferConfig - errorMsg string - }{ - { - name: "valid config", - cfg: example.LinkTransferConfig{ - Transfers: map[uint64][]example.TransferConfig{ - chainSelector: {{To: mcmsState.Timelock.Address(), Value: big.NewInt(100)}}}, - From: chain.DeployerKey.From, - McmsConfig: &example.MCMSConfig{ - MinDelay: time.Hour, - }, - }, - }, - { - name: "valid non mcms config", - cfg: example.LinkTransferConfig{ - Transfers: map[uint64][]example.TransferConfig{ - chainSelector: {{To: mcmsState.Timelock.Address(), Value: big.NewInt(100)}}}, - From: chain.DeployerKey.From, - }, - }, - { - name: "insufficient funds", - cfg: example.LinkTransferConfig{ - Transfers: map[uint64][]example.TransferConfig{ - chainSelector: { - {To: chain.DeployerKey.From, Value: big.NewInt(100)}, - {To: chain.DeployerKey.From, Value: big.NewInt(500)}, - {To: chain.DeployerKey.From, Value: big.NewInt(1250)}, - }, - }, - From: mcmsState.Timelock.Address(), - McmsConfig: &example.MCMSConfig{ - MinDelay: time.Hour, - }, - }, - errorMsg: "sender does not have enough funds for transfers for chain selector 909606746561742123, required: 1850, available: 0", - }, - { - name: "invalid config: empty transfers", - cfg: example.LinkTransferConfig{Transfers: map[uint64][]example.TransferConfig{}}, - errorMsg: "transfers map must have at least one chainSel", - }, - { - name: "invalid chain selector", - cfg: example.LinkTransferConfig{ - Transfers: map[uint64][]example.TransferConfig{ - 1: {{To: common.Address{}, Value: big.NewInt(100)}}}, - }, - errorMsg: "invalid chain selector: unknown chain selector 1", - }, - { - name: "chain selector not found", - cfg: example.LinkTransferConfig{ - Transfers: map[uint64][]example.TransferConfig{ - chain_selectors.ETHEREUM_TESTNET_GOERLI_ARBITRUM_1.Selector: {{To: common.Address{}, Value: big.NewInt(100)}}}, - }, - errorMsg: "chain with selector 6101244977088475029 not found", - }, - { - name: "empty transfer list", - cfg: example.LinkTransferConfig{ - Transfers: map[uint64][]example.TransferConfig{ - chainSelector: {}, - }, - }, - errorMsg: "transfers for chainSel 909606746561742123 must have at least one LinkTransfer", - }, - { - name: "empty value", - cfg: example.LinkTransferConfig{ - Transfers: map[uint64][]example.TransferConfig{ - chainSelector: { - {To: chain.DeployerKey.From, Value: nil}, - }, - }, - }, - errorMsg: "value for transfers must be set", - }, - { - name: "zero value", - cfg: example.LinkTransferConfig{ - Transfers: map[uint64][]example.TransferConfig{ - chainSelector: { - {To: chain.DeployerKey.From, Value: big.NewInt(0)}, - }, - }, - }, - errorMsg: "value for transfers must be non-zero", - }, - { - name: "negative value", - cfg: example.LinkTransferConfig{ - Transfers: map[uint64][]example.TransferConfig{ - chainSelector: { - {To: chain.DeployerKey.From, Value: big.NewInt(-5)}, - }, - }, - }, - errorMsg: "value for transfers must be positive", - }, - { - name: "non-evm-chain", - cfg: example.LinkTransferConfig{ - Transfers: map[uint64][]example.TransferConfig{ - chain_selectors.APTOS_MAINNET.Selector: {{To: mcmsState.Timelock.Address(), Value: big.NewInt(100)}}}, - From: chain.DeployerKey.From, - }, - errorMsg: "chain selector 4741433654826277614 is not an EVM chain", - }, - { - name: "delay greater than max allowed", - cfg: example.LinkTransferConfig{ - Transfers: map[uint64][]example.TransferConfig{ - chainSelector: {{To: mcmsState.Timelock.Address(), Value: big.NewInt(100)}}}, - From: chain.DeployerKey.From, - McmsConfig: &example.MCMSConfig{ - MinDelay: time.Hour * 24 * 10, - }, - }, - errorMsg: "minDelay must be less than 7 days", - }, - { - name: "invalid config: transfer to address missing", - cfg: example.LinkTransferConfig{ - Transfers: map[uint64][]example.TransferConfig{ - chainSelector: {{To: common.Address{}, Value: big.NewInt(100)}}}, - }, - errorMsg: "'to' address for transfers must be set", - }, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - err := tt.cfg.Validate(env) - if tt.errorMsg != "" { - require.Error(t, err) - require.Contains(t, err.Error(), tt.errorMsg) - } else { - require.NoError(t, err) - } - }) - } -} diff --git a/deployment/common/changeset/example/mint_link.go b/deployment/common/changeset/example/mint_link.go deleted file mode 100644 index dc50f8a1a27..00000000000 --- a/deployment/common/changeset/example/mint_link.go +++ /dev/null @@ -1,43 +0,0 @@ -package example - -import ( - "math/big" - - "github.com/ethereum/go-ethereum/common" - - "github.com/smartcontractkit/chainlink/deployment" - "github.com/smartcontractkit/chainlink/deployment/common/changeset" -) - -type MintLinkConfig struct { - Amount *big.Int - ChainSelector uint64 - To common.Address -} - -var _ deployment.ChangeSet[*MintLinkConfig] = MintLink - -// MintLink mints LINK to the provided contract. -func MintLink(e deployment.Environment, cfg *MintLinkConfig) (deployment.ChangesetOutput, error) { - - chain := e.Chains[cfg.ChainSelector] - addresses, err := e.ExistingAddresses.AddressesForChain(cfg.ChainSelector) - if err != nil { - return deployment.ChangesetOutput{}, err - } - linkState, err := changeset.MaybeLoadLinkTokenChainState(chain, addresses) - if err != nil { - return deployment.ChangesetOutput{}, err - } - - tx, err := linkState.LinkToken.Mint(chain.DeployerKey, cfg.To, cfg.Amount) - if err != nil { - return deployment.ChangesetOutput{}, err - } - _, err = deployment.ConfirmIfNoError(chain, tx, err) - if err != nil { - return deployment.ChangesetOutput{}, err - } - return deployment.ChangesetOutput{}, nil - -} diff --git a/deployment/common/changeset/example/mint_link_test.go b/deployment/common/changeset/example/mint_link_test.go deleted file mode 100644 index 1c60c3221de..00000000000 --- a/deployment/common/changeset/example/mint_link_test.go +++ /dev/null @@ -1,58 +0,0 @@ -package example_test - -import ( - "math/big" - "testing" - - "github.com/ethereum/go-ethereum/accounts/abi/bind" - "github.com/ethereum/go-ethereum/common" - "github.com/stretchr/testify/require" - - "github.com/smartcontractkit/chainlink/deployment/common/changeset" - "github.com/smartcontractkit/chainlink/deployment/common/changeset/example" -) - -// TestMintLink tests the MintLink changeset -func TestMintLink(t *testing.T) { - t.Parallel() - env := setupLinkTransferTestEnv(t) - ctx := env.GetContext() - chainSelector := env.AllChainSelectors()[0] - chain := env.Chains[chainSelector] - - addrs, err := env.ExistingAddresses.AddressesForChain(chainSelector) - require.NoError(t, err) - require.Len(t, addrs, 6) - - mcmsState, err := changeset.MaybeLoadMCMSWithTimelockChainState(chain, addrs) - require.NoError(t, err) - linkState, err := changeset.MaybeLoadLinkTokenChainState(chain, addrs) - require.NoError(t, err) - - _, err = changeset.ApplyChangesets(t, env, nil, []changeset.ChangesetApplication{ - { - Changeset: changeset.WrapChangeSet(example.AddMintersBurnersLink), - Config: &example.AddMintersBurnersLinkConfig{ - ChainSelector: chainSelector, - Minters: []common.Address{chain.DeployerKey.From}, - }, - }, - }) - require.NoError(t, err) - - timelockAddress := mcmsState.Timelock.Address() - - // Mint some funds - _, err = example.MintLink(env, &example.MintLinkConfig{ - ChainSelector: chainSelector, - To: timelockAddress, - Amount: big.NewInt(7568), - }) - require.NoError(t, err) - - // check timelock balance - endBalance, err := linkState.LinkToken.BalanceOf(&bind.CallOpts{Context: ctx}, timelockAddress) - require.NoError(t, err) - expectedBalance := big.NewInt(7568) - require.Equal(t, expectedBalance, endBalance) -} diff --git a/deployment/common/changeset/internal/mcms.go b/deployment/common/changeset/internal/mcms.go deleted file mode 100644 index baa82d77c8f..00000000000 --- a/deployment/common/changeset/internal/mcms.go +++ /dev/null @@ -1,172 +0,0 @@ -package internal - -import ( - "github.com/ethereum/go-ethereum/common" - "github.com/smartcontractkit/ccip-owner-contracts/pkg/config" - owner_helpers "github.com/smartcontractkit/ccip-owner-contracts/pkg/gethwrappers" - - "github.com/smartcontractkit/chainlink-common/pkg/logger" - - "github.com/smartcontractkit/chainlink/deployment" - "github.com/smartcontractkit/chainlink/deployment/common/types" - "github.com/smartcontractkit/chainlink/deployment/common/view/v1_0" -) - -func DeployMCMSWithConfig( - contractType deployment.ContractType, - lggr logger.Logger, - chain deployment.Chain, - ab deployment.AddressBook, - mcmConfig config.Config, -) (*deployment.ContractDeploy[*owner_helpers.ManyChainMultiSig], error) { - groupQuorums, groupParents, signerAddresses, signerGroups := mcmConfig.ExtractSetConfigInputs() - mcm, err := deployment.DeployContract[*owner_helpers.ManyChainMultiSig](lggr, chain, ab, - func(chain deployment.Chain) deployment.ContractDeploy[*owner_helpers.ManyChainMultiSig] { - mcmAddr, tx, mcm, err2 := owner_helpers.DeployManyChainMultiSig( - chain.DeployerKey, - chain.Client, - ) - return deployment.ContractDeploy[*owner_helpers.ManyChainMultiSig]{ - mcmAddr, mcm, tx, deployment.NewTypeAndVersion(contractType, deployment.Version1_0_0), err2, - } - }) - if err != nil { - lggr.Errorw("Failed to deploy mcm", "chain", chain.String(), "err", err) - return mcm, err - } - mcmsTx, err := mcm.Contract.SetConfig(chain.DeployerKey, - signerAddresses, - // Signer 1 is int group 0 (root group) with quorum 1. - signerGroups, - groupQuorums, - groupParents, - false, - ) - if _, err := deployment.ConfirmIfNoError(chain, mcmsTx, err); err != nil { - lggr.Errorw("Failed to confirm mcm config", "chain", chain.String(), "err", err) - return mcm, err - } - return mcm, nil -} - -// MCMSWithTimelockDeploy holds a bundle of MCMS contract deploys. -type MCMSWithTimelockDeploy struct { - Canceller *deployment.ContractDeploy[*owner_helpers.ManyChainMultiSig] - Bypasser *deployment.ContractDeploy[*owner_helpers.ManyChainMultiSig] - Proposer *deployment.ContractDeploy[*owner_helpers.ManyChainMultiSig] - Timelock *deployment.ContractDeploy[*owner_helpers.RBACTimelock] - CallProxy *deployment.ContractDeploy[*owner_helpers.CallProxy] -} - -func DeployMCMSWithTimelockContractsBatch( - lggr logger.Logger, - chains map[uint64]deployment.Chain, - ab deployment.AddressBook, - cfgByChain map[uint64]types.MCMSWithTimelockConfig, -) error { - for chainSel, cfg := range cfgByChain { - _, err := DeployMCMSWithTimelockContracts(lggr, chains[chainSel], ab, cfg) - if err != nil { - return err - } - } - return nil -} - -// DeployMCMSWithTimelockContracts deploys an MCMS for -// each of the timelock roles Bypasser, ProposerMcm, Canceller. -// MCMS contracts for the given configuration -// as well as the timelock. It's not necessarily the only way to use -// the timelock and MCMS, but its reasonable pattern. -func DeployMCMSWithTimelockContracts( - lggr logger.Logger, - chain deployment.Chain, - ab deployment.AddressBook, - config types.MCMSWithTimelockConfig, -) (*MCMSWithTimelockDeploy, error) { - bypasser, err := DeployMCMSWithConfig(types.BypasserManyChainMultisig, lggr, chain, ab, config.Bypasser) - if err != nil { - return nil, err - } - canceller, err := DeployMCMSWithConfig(types.CancellerManyChainMultisig, lggr, chain, ab, config.Canceller) - if err != nil { - return nil, err - } - proposer, err := DeployMCMSWithConfig(types.ProposerManyChainMultisig, lggr, chain, ab, config.Proposer) - if err != nil { - return nil, err - } - - timelock, err := deployment.DeployContract(lggr, chain, ab, - func(chain deployment.Chain) deployment.ContractDeploy[*owner_helpers.RBACTimelock] { - timelock, tx2, cc, err2 := owner_helpers.DeployRBACTimelock( - chain.DeployerKey, - chain.Client, - config.TimelockMinDelay, - // Deployer is the initial admin. - // TODO: Could expose this as config? - // Or keep this enforced to follow the same pattern? - chain.DeployerKey.From, - []common.Address{proposer.Address}, // proposers - // Executors field is empty here because we grant the executor role to the call proxy later - // and the call proxy cannot be deployed before the timelock. - []common.Address{}, - []common.Address{canceller.Address, proposer.Address, bypasser.Address}, // cancellers - []common.Address{bypasser.Address}, // bypassers - ) - return deployment.ContractDeploy[*owner_helpers.RBACTimelock]{ - timelock, cc, tx2, deployment.NewTypeAndVersion(types.RBACTimelock, deployment.Version1_0_0), err2, - } - }) - if err != nil { - lggr.Errorw("Failed to deploy timelock", "chain", chain.String(), "err", err) - return nil, err - } - - callProxy, err := deployment.DeployContract(lggr, chain, ab, - func(chain deployment.Chain) deployment.ContractDeploy[*owner_helpers.CallProxy] { - callProxy, tx2, cc, err2 := owner_helpers.DeployCallProxy( - chain.DeployerKey, - chain.Client, - timelock.Address, - ) - return deployment.ContractDeploy[*owner_helpers.CallProxy]{ - callProxy, cc, tx2, deployment.NewTypeAndVersion(types.CallProxy, deployment.Version1_0_0), err2, - } - }) - if err != nil { - lggr.Errorw("Failed to deploy call proxy", "chain", chain.String(), "err", err) - return nil, err - } - - grantRoleTx, err := timelock.Contract.GrantRole( - chain.DeployerKey, - v1_0.EXECUTOR_ROLE.ID, - callProxy.Address, - ) - if err != nil { - lggr.Errorw("Failed to grant timelock executor role", "chain", chain.String(), "err", err) - return nil, err - } - - if _, err := deployment.ConfirmIfNoError(chain, grantRoleTx, err); err != nil { - lggr.Errorw("Failed to grant timelock executor role", "chain", chain.String(), "err", err) - return nil, err - } - // We grant the timelock the admin role on the MCMS contracts. - tx, err := timelock.Contract.GrantRole(chain.DeployerKey, - v1_0.ADMIN_ROLE.ID, timelock.Address) - if _, err := deployment.ConfirmIfNoError(chain, tx, err); err != nil { - lggr.Errorw("Failed to grant timelock admin role", "chain", chain.String(), "err", err) - return nil, err - } - // After the proposer cycle is validated, - // we can remove the deployer as an admin. - return &MCMSWithTimelockDeploy{ - Canceller: canceller, - Bypasser: bypasser, - Proposer: proposer, - Timelock: timelock, - CallProxy: callProxy, - }, nil -} diff --git a/deployment/common/changeset/internal/mcms_test.go b/deployment/common/changeset/internal/mcms_test.go deleted file mode 100644 index 92822422daa..00000000000 --- a/deployment/common/changeset/internal/mcms_test.go +++ /dev/null @@ -1,49 +0,0 @@ -package internal_test - -import ( - "encoding/json" - "testing" - - chainsel "github.com/smartcontractkit/chain-selectors" - "github.com/stretchr/testify/require" - - "github.com/smartcontractkit/chainlink/deployment" - "github.com/smartcontractkit/chainlink/deployment/common/changeset" - "github.com/smartcontractkit/chainlink/deployment/common/changeset/internal" - "github.com/smartcontractkit/chainlink/deployment/common/proposalutils" - "github.com/smartcontractkit/chainlink/deployment/common/types" - "github.com/smartcontractkit/chainlink/deployment/environment/memory" - "github.com/smartcontractkit/chainlink/v2/core/logger" -) - -func TestDeployMCMSWithConfig(t *testing.T) { - lggr := logger.TestLogger(t) - chains, _ := memory.NewMemoryChainsWithChainIDs(t, []uint64{ - chainsel.TEST_90000001.EvmChainID, - }, 1) - ab := deployment.NewMemoryAddressBook() - _, err := internal.DeployMCMSWithConfig(types.ProposerManyChainMultisig, - lggr, chains[chainsel.TEST_90000001.Selector], ab, proposalutils.SingleGroupMCMS(t)) - require.NoError(t, err) -} - -func TestDeployMCMSWithTimelockContracts(t *testing.T) { - lggr := logger.TestLogger(t) - chains, _ := memory.NewMemoryChainsWithChainIDs(t, []uint64{ - chainsel.TEST_90000001.EvmChainID, - }, 1) - ab := deployment.NewMemoryAddressBook() - _, err := internal.DeployMCMSWithTimelockContracts(lggr, - chains[chainsel.TEST_90000001.Selector], - ab, proposalutils.SingleGroupTimelockConfig(t)) - require.NoError(t, err) - addresses, err := ab.AddressesForChain(chainsel.TEST_90000001.Selector) - require.NoError(t, err) - require.Len(t, addresses, 5) - mcmsState, err := changeset.MaybeLoadMCMSWithTimelockChainState(chains[chainsel.TEST_90000001.Selector], addresses) - require.NoError(t, err) - v, err := mcmsState.GenerateMCMSWithTimelockView() - b, err := json.MarshalIndent(v, "", " ") - require.NoError(t, err) - t.Log(string(b)) -} diff --git a/deployment/common/changeset/save_existing_test.go b/deployment/common/changeset/save_existing_test.go deleted file mode 100644 index 2a2618c8f54..00000000000 --- a/deployment/common/changeset/save_existing_test.go +++ /dev/null @@ -1,54 +0,0 @@ -package changeset - -import ( - "math/big" - "testing" - - "github.com/ethereum/go-ethereum/common" - chainsel "github.com/smartcontractkit/chain-selectors" - "github.com/stretchr/testify/require" - - "github.com/smartcontractkit/chainlink/deployment" - "github.com/smartcontractkit/chainlink/v2/core/logger" -) - -func TestSaveExisting(t *testing.T) { - dummyEnv := deployment.Environment{ - Name: "dummy", - Logger: logger.TestLogger(t), - ExistingAddresses: deployment.NewMemoryAddressBook(), - Chains: map[uint64]deployment.Chain{ - chainsel.TEST_90000001.Selector: {}, - chainsel.TEST_90000002.Selector: {}, - }, - } - ExistingContracts := ExistingContractsConfig{ - ExistingContracts: []Contract{ - { - Address: common.BigToAddress(big.NewInt(1)), - TypeAndVersion: deployment.TypeAndVersion{ - Type: "dummy1", - Version: deployment.Version1_5_0, - }, - ChainSelector: chainsel.TEST_90000001.Selector, - }, - { - Address: common.BigToAddress(big.NewInt(2)), - TypeAndVersion: deployment.TypeAndVersion{ - Type: "dummy2", - Version: deployment.Version1_1_0, - }, - ChainSelector: chainsel.TEST_90000002.Selector, - }, - }, - } - - output, err := SaveExistingContracts(dummyEnv, ExistingContracts) - require.NoError(t, err) - require.NoError(t, dummyEnv.ExistingAddresses.Merge(output.AddressBook)) - addresses, err := dummyEnv.ExistingAddresses.Addresses() - require.Len(t, addresses, 2) - addressForChain1, exists := addresses[chainsel.TEST_90000001.Selector] - require.True(t, exists) - require.Len(t, addressForChain1, 1) -} diff --git a/deployment/common/changeset/set_config_mcms.go b/deployment/common/changeset/set_config_mcms.go deleted file mode 100644 index 3ba5d2db4b6..00000000000 --- a/deployment/common/changeset/set_config_mcms.go +++ /dev/null @@ -1,209 +0,0 @@ -package changeset - -import ( - "context" - "errors" - "fmt" - "math/big" - "time" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/types" - "github.com/smartcontractkit/ccip-owner-contracts/pkg/config" - "github.com/smartcontractkit/ccip-owner-contracts/pkg/gethwrappers" - "github.com/smartcontractkit/ccip-owner-contracts/pkg/proposal/mcms" - "github.com/smartcontractkit/ccip-owner-contracts/pkg/proposal/timelock" - chain_selectors "github.com/smartcontractkit/chain-selectors" - - "github.com/smartcontractkit/chainlink-common/pkg/logger" - - "github.com/smartcontractkit/chainlink/deployment" - "github.com/smartcontractkit/chainlink/deployment/common/proposalutils" - commontypes "github.com/smartcontractkit/chainlink/deployment/common/types" -) - -type ConfigPerRole struct { - Proposer config.Config - Canceller config.Config - Bypasser config.Config -} -type TimelockConfig struct { - MinDelay time.Duration // delay for timelock worker to execute the transfers. -} - -type MCMSConfig struct { - ConfigsPerChain map[uint64]ConfigPerRole - ProposalConfig *TimelockConfig -} - -var _ deployment.ChangeSet[MCMSConfig] = SetConfigMCMS - -// Validate checks that the MCMSConfig is valid -func (cfg MCMSConfig) Validate(e deployment.Environment, selectors []uint64) error { - if len(cfg.ConfigsPerChain) == 0 { - return errors.New("no chain configs provided") - } - // configs should have at least one chain - state, err := MaybeLoadMCMSWithTimelockState(e, selectors) - if err != nil { - return err - } - for chainSelector, c := range cfg.ConfigsPerChain { - family, err := chain_selectors.GetSelectorFamily(chainSelector) - if err != nil { - return err - } - if family != chain_selectors.FamilyEVM { - return fmt.Errorf("chain selector: %d is not an ethereum chain", chainSelector) - } - _, ok := e.Chains[chainSelector] - if !ok { - return fmt.Errorf("chain selector: %d not found in environment", chainSelector) - } - _, ok = state[chainSelector] - if !ok { - return fmt.Errorf("chain selector: %d not found for MCMS state", chainSelector) - } - if err := c.Proposer.Validate(); err != nil { - return err - } - if err := c.Canceller.Validate(); err != nil { - return err - } - if err := c.Bypasser.Validate(); err != nil { - return err - } - } - return nil -} - -// setConfigOrTxData executes set config tx or gets the tx data for the MCMS proposal -func setConfigOrTxData(ctx context.Context, lggr logger.Logger, chain deployment.Chain, cfg config.Config, contract *gethwrappers.ManyChainMultiSig, useMCMS bool) (*types.Transaction, error) { - groupQuorums, groupParents, signerAddresses, signerGroups := cfg.ExtractSetConfigInputs() - opts := deployment.SimTransactOpts() - if !useMCMS { - opts = chain.DeployerKey - } - opts.Context = ctx - tx, err := contract.SetConfig(opts, signerAddresses, signerGroups, groupQuorums, groupParents, false) - if err != nil { - return nil, err - } - if !useMCMS { - _, err = deployment.ConfirmIfNoError(chain, tx, err) - if err != nil { - return nil, err - } - lggr.Infow("SetConfigMCMS tx confirmed", "txHash", tx.Hash().Hex()) - } - return tx, nil -} - -type setConfigTxs struct { - proposerTx *types.Transaction - cancellerTx *types.Transaction - bypasserTx *types.Transaction -} - -// setConfigPerRole sets the configuration for each of the MCMS contract roles on the mcmsState. -func setConfigPerRole(ctx context.Context, lggr logger.Logger, chain deployment.Chain, cfg ConfigPerRole, mcmsState *MCMSWithTimelockState, useMCMS bool) (setConfigTxs, error) { - // Proposer set config - proposerTx, err := setConfigOrTxData(ctx, lggr, chain, cfg.Proposer, mcmsState.ProposerMcm, useMCMS) - if err != nil { - return setConfigTxs{}, err - } - // Canceller set config - cancellerTx, err := setConfigOrTxData(ctx, lggr, chain, cfg.Canceller, mcmsState.CancellerMcm, useMCMS) - if err != nil { - return setConfigTxs{}, err - } - // Bypasser set config - bypasserTx, err := setConfigOrTxData(ctx, lggr, chain, cfg.Bypasser, mcmsState.BypasserMcm, useMCMS) - if err != nil { - return setConfigTxs{}, err - } - - return setConfigTxs{ - proposerTx: proposerTx, - cancellerTx: cancellerTx, - bypasserTx: bypasserTx, - }, nil -} - -func addTxsToProposalBatch(setConfigTxsChain setConfigTxs, chainSelector uint64, state MCMSWithTimelockState) timelock.BatchChainOperation { - result := timelock.BatchChainOperation{ - ChainIdentifier: mcms.ChainIdentifier(chainSelector), - Batch: []mcms.Operation{}, - } - result.Batch = append(result.Batch, mcms.Operation{ - To: state.ProposerMcm.Address(), - Data: setConfigTxsChain.proposerTx.Data(), - Value: big.NewInt(0), - ContractType: string(commontypes.ProposerManyChainMultisig), - }) - result.Batch = append(result.Batch, mcms.Operation{ - To: state.CancellerMcm.Address(), - Data: setConfigTxsChain.cancellerTx.Data(), - Value: big.NewInt(0), - ContractType: string(commontypes.CancellerManyChainMultisig), - }) - result.Batch = append(result.Batch, mcms.Operation{ - To: state.BypasserMcm.Address(), - Data: setConfigTxsChain.bypasserTx.Data(), - Value: big.NewInt(0), - ContractType: string(commontypes.BypasserManyChainMultisig), - }) - return result -} - -// SetConfigMCMS sets the configuration of the MCMS contract on the chain identified by the chainSelector. -func SetConfigMCMS(e deployment.Environment, cfg MCMSConfig) (deployment.ChangesetOutput, error) { - selectors := []uint64{} - lggr := e.Logger - ctx := e.GetContext() - for chainSelector := range cfg.ConfigsPerChain { - selectors = append(selectors, chainSelector) - } - useMCMS := cfg.ProposalConfig != nil - err := cfg.Validate(e, selectors) - if err != nil { - return deployment.ChangesetOutput{}, err - } - - batches := []timelock.BatchChainOperation{} - timelocksPerChain := map[uint64]common.Address{} - proposerMcmsPerChain := map[uint64]*gethwrappers.ManyChainMultiSig{} - - mcmsStatePerChain, err := MaybeLoadMCMSWithTimelockState(e, selectors) - if err != nil { - return deployment.ChangesetOutput{}, err - } - - for chainSelector, c := range cfg.ConfigsPerChain { - chain := e.Chains[chainSelector] - state := mcmsStatePerChain[chainSelector] - timelocksPerChain[chainSelector] = state.Timelock.Address() - proposerMcmsPerChain[chainSelector] = state.ProposerMcm - setConfigTxsChain, err := setConfigPerRole(ctx, lggr, chain, c, state, useMCMS) - if err != nil { - return deployment.ChangesetOutput{}, err - } - if useMCMS { - batch := addTxsToProposalBatch(setConfigTxsChain, chainSelector, *state) - batches = append(batches, batch) - } - - } - - if useMCMS { - // Create MCMS with timelock proposal - proposal, err := proposalutils.BuildProposalFromBatches(timelocksPerChain, proposerMcmsPerChain, batches, "Set config proposal", cfg.ProposalConfig.MinDelay) - if err != nil { - return deployment.ChangesetOutput{}, fmt.Errorf("failed to build proposal from batch: %w", err) - } - lggr.Infow("SetConfigMCMS proposal created", "proposal", proposal) - return deployment.ChangesetOutput{Proposals: []timelock.MCMSWithTimelockProposal{*proposal}}, nil - } - - return deployment.ChangesetOutput{}, nil -} diff --git a/deployment/common/changeset/set_config_mcms_test.go b/deployment/common/changeset/set_config_mcms_test.go deleted file mode 100644 index 7220bdd755a..00000000000 --- a/deployment/common/changeset/set_config_mcms_test.go +++ /dev/null @@ -1,313 +0,0 @@ -package changeset_test - -import ( - "testing" - - "github.com/ethereum/go-ethereum/accounts/abi/bind" - "github.com/ethereum/go-ethereum/common" - "github.com/smartcontractkit/ccip-owner-contracts/pkg/config" - chain_selectors "github.com/smartcontractkit/chain-selectors" - "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" - - commonchangeset "github.com/smartcontractkit/chainlink/deployment/common/changeset" - "github.com/smartcontractkit/chainlink/deployment/common/proposalutils" - "github.com/smartcontractkit/chainlink/v2/core/logger" - - "github.com/stretchr/testify/require" - "go.uber.org/zap/zapcore" - - "github.com/smartcontractkit/chainlink/deployment" - - "github.com/smartcontractkit/chainlink/deployment/common/types" - "github.com/smartcontractkit/chainlink/deployment/environment/memory" -) - -// setupSetConfigTestEnv deploys all required contracts for the setConfig MCMS contract call. -func setupSetConfigTestEnv(t *testing.T) deployment.Environment { - - lggr := logger.TestLogger(t) - cfg := memory.MemoryEnvironmentConfig{ - Nodes: 1, - Chains: 2, - } - env := memory.NewMemoryEnvironment(t, lggr, zapcore.DebugLevel, cfg) - chainSelector := env.AllChainSelectors()[0] - - config := proposalutils.SingleGroupTimelockConfig(t) - // Deploy MCMS and Timelock - env, err := commonchangeset.ApplyChangesets(t, env, nil, []commonchangeset.ChangesetApplication{ - { - Changeset: commonchangeset.WrapChangeSet(commonchangeset.DeployLinkToken), - Config: []uint64{chainSelector}, - }, - { - Changeset: commonchangeset.WrapChangeSet(commonchangeset.DeployMCMSWithTimelock), - Config: map[uint64]types.MCMSWithTimelockConfig{ - chainSelector: config, - }, - }, - }) - require.NoError(t, err) - return env -} - -// TestSetConfigMCMSVariants tests the SetConfigMCMS changeset variants. -func TestSetConfigMCMSVariants(t *testing.T) { - - // Add the timelock as a signer to check state changes - for _, tc := range []struct { - name string - changeSets func(mcmsState *commonchangeset.MCMSWithTimelockState, chainSel uint64, cfgProp, cfgCancel, cfgBypass config.Config) []commonchangeset.ChangesetApplication - }{ - { - name: "MCMS disabled", - changeSets: func(mcmsState *commonchangeset.MCMSWithTimelockState, chainSel uint64, cfgProp, cfgCancel, cfgBypass config.Config) []commonchangeset.ChangesetApplication { - - return []commonchangeset.ChangesetApplication{ - { - Changeset: commonchangeset.WrapChangeSet(commonchangeset.SetConfigMCMS), - Config: commonchangeset.MCMSConfig{ - ConfigsPerChain: map[uint64]commonchangeset.ConfigPerRole{ - chainSel: { - Proposer: cfgProp, - Canceller: cfgCancel, - Bypasser: cfgBypass, - }, - }, - }, - }, - } - }, - }, - { - name: "MCMS enabled", - changeSets: func(mcmsState *commonchangeset.MCMSWithTimelockState, chainSel uint64, cfgProp, cfgCancel, cfgBypass config.Config) []commonchangeset.ChangesetApplication { - return []commonchangeset.ChangesetApplication{ - { - Changeset: commonchangeset.WrapChangeSet(commonchangeset.TransferToMCMSWithTimelock), - Config: commonchangeset.TransferToMCMSWithTimelockConfig{ - ContractsByChain: map[uint64][]common.Address{ - chainSel: {mcmsState.ProposerMcm.Address(), mcmsState.BypasserMcm.Address(), mcmsState.CancellerMcm.Address()}, - }, - }, - }, - { - Changeset: commonchangeset.WrapChangeSet(commonchangeset.SetConfigMCMS), - Config: commonchangeset.MCMSConfig{ - ProposalConfig: &commonchangeset.TimelockConfig{ - MinDelay: 0, - }, - ConfigsPerChain: map[uint64]commonchangeset.ConfigPerRole{ - chainSel: { - Proposer: cfgProp, - Canceller: cfgCancel, - Bypasser: cfgBypass, - }, - }, - }, - }, - } - }, - }, - } { - t.Run(tc.name, func(t *testing.T) { - ctx := tests.Context(t) - - env := setupSetConfigTestEnv(t) - chainSelector := env.AllChainSelectors()[0] - chain := env.Chains[chainSelector] - addrs, err := env.ExistingAddresses.AddressesForChain(chainSelector) - require.NoError(t, err) - require.Len(t, addrs, 6) - - mcmsState, err := commonchangeset.MaybeLoadMCMSWithTimelockChainState(chain, addrs) - require.NoError(t, err) - timelockAddress := mcmsState.Timelock.Address() - cfgProposer := proposalutils.SingleGroupMCMS(t) - cfgProposer.Signers = append(cfgProposer.Signers, timelockAddress) - cfgProposer.Quorum = 2 // quorum should change to 2 out of 2 signers - timelockMap := map[uint64]*proposalutils.TimelockExecutionContracts{ - chainSelector: { - Timelock: mcmsState.Timelock, - CallProxy: mcmsState.CallProxy, - }, - } - cfgCanceller := proposalutils.SingleGroupMCMS(t) - cfgBypasser := proposalutils.SingleGroupMCMS(t) - cfgBypasser.Signers = append(cfgBypasser.Signers, timelockAddress) - cfgBypasser.Signers = append(cfgBypasser.Signers, mcmsState.ProposerMcm.Address()) - cfgBypasser.Quorum = 3 // quorum should change to 3 out of 3 signers - - // Set config on all 3 MCMS contracts - changesetsToApply := tc.changeSets(mcmsState, chainSelector, cfgProposer, cfgCanceller, cfgBypasser) - _, err = commonchangeset.ApplyChangesets(t, env, timelockMap, changesetsToApply) - require.NoError(t, err) - - // Check new State - expected := cfgProposer.ToRawConfig() - opts := &bind.CallOpts{Context: ctx} - newConf, err := mcmsState.ProposerMcm.GetConfig(opts) - require.NoError(t, err) - require.Equal(t, expected, newConf) - - expected = cfgBypasser.ToRawConfig() - newConf, err = mcmsState.BypasserMcm.GetConfig(opts) - require.NoError(t, err) - require.Equal(t, expected, newConf) - - expected = cfgCanceller.ToRawConfig() - newConf, err = mcmsState.CancellerMcm.GetConfig(opts) - require.NoError(t, err) - require.Equal(t, expected, newConf) - }) - } -} - -func TestValidate(t *testing.T) { - env := setupSetConfigTestEnv(t) - - chainSelector := env.AllChainSelectors()[0] - chain := env.Chains[chainSelector] - addrs, err := env.ExistingAddresses.AddressesForChain(chainSelector) - require.NoError(t, err) - require.Len(t, addrs, 6) - mcmsState, err := commonchangeset.MaybeLoadMCMSWithTimelockChainState(chain, addrs) - require.NoError(t, err) - cfg := proposalutils.SingleGroupMCMS(t) - timelockAddress := mcmsState.Timelock.Address() - // Add the timelock as a signer to check state changes - cfg.Signers = append(cfg.Signers, timelockAddress) - cfg.Quorum = 2 // quorum - - cfgInvalid := proposalutils.SingleGroupMCMS(t) - cfgInvalid.Quorum = 0 - require.NoError(t, err) - tests := []struct { - name string - cfg commonchangeset.MCMSConfig - errorMsg string - }{ - { - name: "valid config", - cfg: commonchangeset.MCMSConfig{ - ProposalConfig: &commonchangeset.TimelockConfig{ - MinDelay: 0, - }, - ConfigsPerChain: map[uint64]commonchangeset.ConfigPerRole{ - chainSelector: { - Proposer: cfg, - Canceller: cfg, - Bypasser: cfg, - }, - }, - }, - }, - { - name: "valid non mcms config", - cfg: commonchangeset.MCMSConfig{ - ConfigsPerChain: map[uint64]commonchangeset.ConfigPerRole{ - chainSelector: { - Proposer: cfg, - Canceller: cfg, - Bypasser: cfg, - }, - }, - }, - }, - { - name: "no chain configurations", - cfg: commonchangeset.MCMSConfig{ - ConfigsPerChain: map[uint64]commonchangeset.ConfigPerRole{}, - }, - errorMsg: "no chain configs provided", - }, - { - name: "non evm chain", - cfg: commonchangeset.MCMSConfig{ - ConfigsPerChain: map[uint64]commonchangeset.ConfigPerRole{ - chain_selectors.APTOS_MAINNET.Selector: { - Proposer: cfg, - Canceller: cfg, - Bypasser: cfg, - }, - }, - }, - errorMsg: "chain selector: 4741433654826277614 is not an ethereum chain", - }, - { - name: "chain selector not found in environment", - cfg: commonchangeset.MCMSConfig{ - ConfigsPerChain: map[uint64]commonchangeset.ConfigPerRole{ - 123: { - Proposer: cfg, - Canceller: cfg, - Bypasser: cfg, - }, - }, - }, - errorMsg: "unknown chain selector 123", - }, - { - name: "invalid proposer config", - cfg: commonchangeset.MCMSConfig{ - ProposalConfig: &commonchangeset.TimelockConfig{ - MinDelay: 0, - }, - ConfigsPerChain: map[uint64]commonchangeset.ConfigPerRole{ - chainSelector: { - Proposer: cfgInvalid, - Canceller: cfg, - Bypasser: cfg, - }, - }, - }, - errorMsg: "invalid MCMS config: Quorum must be greater than 0", - }, - { - name: "invalid canceller config", - cfg: commonchangeset.MCMSConfig{ - ProposalConfig: &commonchangeset.TimelockConfig{ - MinDelay: 0, - }, - ConfigsPerChain: map[uint64]commonchangeset.ConfigPerRole{ - chainSelector: { - Proposer: cfg, - Canceller: cfgInvalid, - Bypasser: cfg, - }, - }, - }, - errorMsg: "invalid MCMS config: Quorum must be greater than 0", - }, - { - name: "invalid bypasser config", - cfg: commonchangeset.MCMSConfig{ - ProposalConfig: &commonchangeset.TimelockConfig{ - MinDelay: 0, - }, - ConfigsPerChain: map[uint64]commonchangeset.ConfigPerRole{ - chainSelector: { - Proposer: cfg, - Canceller: cfg, - Bypasser: cfgInvalid, - }, - }, - }, - errorMsg: "invalid MCMS config: Quorum must be greater than 0", - }, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - selectors := []uint64{chainSelector} - - err := tt.cfg.Validate(env, selectors) - if tt.errorMsg != "" { - require.Error(t, err) - require.Contains(t, err.Error(), tt.errorMsg) - } else { - require.NoError(t, err) - } - }) - } -} diff --git a/deployment/common/changeset/state.go b/deployment/common/changeset/state.go deleted file mode 100644 index 0db34abad71..00000000000 --- a/deployment/common/changeset/state.go +++ /dev/null @@ -1,227 +0,0 @@ -package changeset - -import ( - "errors" - "fmt" - - "github.com/ethereum/go-ethereum/common" - owner_helpers "github.com/smartcontractkit/ccip-owner-contracts/pkg/gethwrappers" - - "github.com/smartcontractkit/chainlink/deployment" - "github.com/smartcontractkit/chainlink/deployment/common/proposalutils" - "github.com/smartcontractkit/chainlink/deployment/common/types" - "github.com/smartcontractkit/chainlink/deployment/common/view/v1_0" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/link_token_interface" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/shared/generated/link_token" -) - -// MCMSWithTimelockState holds the Go bindings -// for a MCMSWithTimelock contract deployment. -// It is public for use in product specific packages. -// Either all fields are nil or all fields are non-nil. -type MCMSWithTimelockState struct { - *proposalutils.MCMSWithTimelockContracts -} - -func (state MCMSWithTimelockState) GenerateMCMSWithTimelockView() (v1_0.MCMSWithTimelockView, error) { - if err := state.Validate(); err != nil { - return v1_0.MCMSWithTimelockView{}, err - } - timelockView, err := v1_0.GenerateTimelockView(*state.Timelock) - if err != nil { - return v1_0.MCMSWithTimelockView{}, nil - } - callProxyView, err := v1_0.GenerateCallProxyView(*state.CallProxy) - if err != nil { - return v1_0.MCMSWithTimelockView{}, nil - } - bypasserView, err := v1_0.GenerateMCMSView(*state.BypasserMcm) - if err != nil { - return v1_0.MCMSWithTimelockView{}, nil - } - proposerView, err := v1_0.GenerateMCMSView(*state.ProposerMcm) - if err != nil { - return v1_0.MCMSWithTimelockView{}, nil - } - cancellerView, err := v1_0.GenerateMCMSView(*state.CancellerMcm) - if err != nil { - return v1_0.MCMSWithTimelockView{}, nil - } - return v1_0.MCMSWithTimelockView{ - Timelock: timelockView, - Bypasser: bypasserView, - Proposer: proposerView, - Canceller: cancellerView, - CallProxy: callProxyView, - }, nil -} - -// MaybeLoadMCMSWithTimelockState loads the MCMSWithTimelockState state for each chain in the given environment. -func MaybeLoadMCMSWithTimelockState(env deployment.Environment, chainSelectors []uint64) (map[uint64]*MCMSWithTimelockState, error) { - result := map[uint64]*MCMSWithTimelockState{} - for _, chainSelector := range chainSelectors { - chain, ok := env.Chains[chainSelector] - if !ok { - return nil, fmt.Errorf("chain %d not found", chainSelector) - } - addressesChain, err := env.ExistingAddresses.AddressesForChain(chainSelector) - if err != nil { - return nil, err - } - state, err := MaybeLoadMCMSWithTimelockChainState(chain, addressesChain) - if err != nil { - return nil, err - } - result[chainSelector] = state - } - return result, nil -} - -// MaybeLoadMCMSWithTimelockChainState looks for the addresses corresponding to -// contracts deployed with DeployMCMSWithTimelock and loads them into a -// MCMSWithTimelockState struct. If none of the contracts are found, the state struct will be nil. -// An error indicates: -// - Found but was unable to load a contract -// - It only found part of the bundle of contracts -// - If found more than one instance of a contract (we expect one bundle in the given addresses) -func MaybeLoadMCMSWithTimelockChainState(chain deployment.Chain, addresses map[string]deployment.TypeAndVersion) (*MCMSWithTimelockState, error) { - state := MCMSWithTimelockState{ - MCMSWithTimelockContracts: &proposalutils.MCMSWithTimelockContracts{}, - } - // We expect one of each contract on the chain. - timelock := deployment.NewTypeAndVersion(types.RBACTimelock, deployment.Version1_0_0) - callProxy := deployment.NewTypeAndVersion(types.CallProxy, deployment.Version1_0_0) - proposer := deployment.NewTypeAndVersion(types.ProposerManyChainMultisig, deployment.Version1_0_0) - canceller := deployment.NewTypeAndVersion(types.CancellerManyChainMultisig, deployment.Version1_0_0) - bypasser := deployment.NewTypeAndVersion(types.BypasserManyChainMultisig, deployment.Version1_0_0) - - // Ensure we either have the bundle or not. - _, err := deployment.AddressesContainBundle(addresses, - map[deployment.TypeAndVersion]struct{}{ - timelock: {}, proposer: {}, canceller: {}, bypasser: {}, callProxy: {}, - }) - if err != nil { - return nil, fmt.Errorf("unable to check MCMS contracts on chain %s error: %w", chain.Name(), err) - } - - for address, tvStr := range addresses { - switch tvStr { - case timelock: - tl, err := owner_helpers.NewRBACTimelock(common.HexToAddress(address), chain.Client) - if err != nil { - return nil, err - } - state.Timelock = tl - case callProxy: - cp, err := owner_helpers.NewCallProxy(common.HexToAddress(address), chain.Client) - if err != nil { - return nil, err - } - state.CallProxy = cp - case proposer: - mcms, err := owner_helpers.NewManyChainMultiSig(common.HexToAddress(address), chain.Client) - if err != nil { - return nil, err - } - state.ProposerMcm = mcms - case bypasser: - mcms, err := owner_helpers.NewManyChainMultiSig(common.HexToAddress(address), chain.Client) - if err != nil { - return nil, err - } - state.BypasserMcm = mcms - case canceller: - mcms, err := owner_helpers.NewManyChainMultiSig(common.HexToAddress(address), chain.Client) - if err != nil { - return nil, err - } - state.CancellerMcm = mcms - } - } - return &state, nil -} - -type LinkTokenState struct { - LinkToken *link_token.LinkToken -} - -func (s LinkTokenState) GenerateLinkView() (v1_0.LinkTokenView, error) { - if s.LinkToken == nil { - return v1_0.LinkTokenView{}, errors.New("link token not found") - } - return v1_0.GenerateLinkTokenView(s.LinkToken) -} - -// MaybeLoadLinkTokenState loads the LinkTokenState state for each chain in the given environment. -func MaybeLoadLinkTokenState(env deployment.Environment, chainSelectors []uint64) (map[uint64]*LinkTokenState, error) { - result := map[uint64]*LinkTokenState{} - for _, chainSelector := range chainSelectors { - chain, ok := env.Chains[chainSelector] - if !ok { - return nil, fmt.Errorf("chain %d not found", chainSelector) - } - addressesChain, err := env.ExistingAddresses.AddressesForChain(chainSelector) - if err != nil { - return nil, err - } - state, err := MaybeLoadLinkTokenChainState(chain, addressesChain) - if err != nil { - return nil, err - } - result[chainSelector] = state - } - return result, nil -} - -func MaybeLoadLinkTokenChainState(chain deployment.Chain, addresses map[string]deployment.TypeAndVersion) (*LinkTokenState, error) { - state := LinkTokenState{} - linkToken := deployment.NewTypeAndVersion(types.LinkToken, deployment.Version1_0_0) - // Perhaps revisit if we have a use case for multiple. - _, err := deployment.AddressesContainBundle(addresses, map[deployment.TypeAndVersion]struct{}{linkToken: {}}) - if err != nil { - return nil, fmt.Errorf("unable to check link token on chain %s error: %w", chain.Name(), err) - } - for address, tvStr := range addresses { - switch tvStr { - case linkToken: - lt, err := link_token.NewLinkToken(common.HexToAddress(address), chain.Client) - if err != nil { - return nil, err - } - state.LinkToken = lt - } - } - return &state, nil -} - -type StaticLinkTokenState struct { - StaticLinkToken *link_token_interface.LinkToken -} - -func (s StaticLinkTokenState) GenerateStaticLinkView() (v1_0.StaticLinkTokenView, error) { - if s.StaticLinkToken == nil { - return v1_0.StaticLinkTokenView{}, errors.New("static link token not found") - } - return v1_0.GenerateStaticLinkTokenView(s.StaticLinkToken) -} - -func MaybeLoadStaticLinkTokenState(chain deployment.Chain, addresses map[string]deployment.TypeAndVersion) (*StaticLinkTokenState, error) { - state := StaticLinkTokenState{} - staticLinkToken := deployment.NewTypeAndVersion(types.StaticLinkToken, deployment.Version1_0_0) - // Perhaps revisit if we have a use case for multiple. - _, err := deployment.AddressesContainBundle(addresses, map[deployment.TypeAndVersion]struct{}{staticLinkToken: {}}) - if err != nil { - return nil, fmt.Errorf("unable to check static link token on chain %s error: %w", chain.Name(), err) - } - for address, tvStr := range addresses { - switch tvStr { - case staticLinkToken: - lt, err := link_token_interface.NewLinkToken(common.HexToAddress(address), chain.Client) - if err != nil { - return nil, err - } - state.StaticLinkToken = lt - } - } - return &state, nil -} diff --git a/deployment/common/changeset/test_helpers.go b/deployment/common/changeset/test_helpers.go deleted file mode 100644 index e92b36e5b55..00000000000 --- a/deployment/common/changeset/test_helpers.go +++ /dev/null @@ -1,99 +0,0 @@ -package changeset - -import ( - "fmt" - "testing" - - mapset "github.com/deckarep/golang-set/v2" - jobv1 "github.com/smartcontractkit/chainlink-protos/job-distributor/v1/job" - "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/testcontext" - - "github.com/smartcontractkit/chainlink/deployment" - "github.com/smartcontractkit/chainlink/deployment/common/proposalutils" -) - -type ChangesetApplication struct { - Changeset deployment.ChangeSet[any] - Config any -} - -func WrapChangeSet[C any](fn deployment.ChangeSet[C]) func(e deployment.Environment, config any) (deployment.ChangesetOutput, error) { - return func(e deployment.Environment, config any) (deployment.ChangesetOutput, error) { - var zeroC C - if config != nil { - c, ok := config.(C) - if !ok { - return deployment.ChangesetOutput{}, fmt.Errorf("invalid config type, expected %T", c) - } - return fn(e, config.(C)) - } - - return fn(e, zeroC) - } -} - -// ApplyChangesets applies the changeset applications to the environment and returns the updated environment. -func ApplyChangesets(t *testing.T, e deployment.Environment, timelockContractsPerChain map[uint64]*proposalutils.TimelockExecutionContracts, changesetApplications []ChangesetApplication) (deployment.Environment, error) { - currentEnv := e - for i, csa := range changesetApplications { - out, err := csa.Changeset(currentEnv, csa.Config) - if err != nil { - return e, fmt.Errorf("failed to apply changeset at index %d: %w", i, err) - } - var addresses deployment.AddressBook - if out.AddressBook != nil { - addresses = out.AddressBook - err := addresses.Merge(currentEnv.ExistingAddresses) - if err != nil { - return e, fmt.Errorf("failed to merge address book: %w", err) - } - } else { - addresses = currentEnv.ExistingAddresses - } - if out.JobSpecs != nil { - ctx := testcontext.Get(t) - for nodeID, jobs := range out.JobSpecs { - for _, job := range jobs { - // Note these auto-accept - _, err := currentEnv.Offchain.ProposeJob(ctx, - &jobv1.ProposeJobRequest{ - NodeId: nodeID, - Spec: job, - }) - if err != nil { - return e, fmt.Errorf("failed to propose job: %w", err) - } - } - } - } - if out.Proposals != nil { - for _, prop := range out.Proposals { - chains := mapset.NewSet[uint64]() - for _, op := range prop.Transactions { - chains.Add(uint64(op.ChainIdentifier)) - } - - signed := proposalutils.SignProposal(t, e, &prop) - for _, sel := range chains.ToSlice() { - timelockContracts, ok := timelockContractsPerChain[sel] - if !ok || timelockContracts == nil { - return deployment.Environment{}, fmt.Errorf("timelock contracts not found for chain %d", sel) - } - - proposalutils.ExecuteProposal(t, e, signed, timelockContracts, sel) - } - } - } - currentEnv = deployment.Environment{ - Name: e.Name, - Logger: e.Logger, - ExistingAddresses: addresses, - Chains: e.Chains, - NodeIDs: e.NodeIDs, - Offchain: e.Offchain, - OCRSecrets: e.OCRSecrets, - GetContext: e.GetContext, - } - } - return currentEnv, nil -} diff --git a/deployment/common/changeset/transfer_to_mcms_with_timelock.go b/deployment/common/changeset/transfer_to_mcms_with_timelock.go deleted file mode 100644 index 45efccefd2e..00000000000 --- a/deployment/common/changeset/transfer_to_mcms_with_timelock.go +++ /dev/null @@ -1,274 +0,0 @@ -package changeset - -import ( - "encoding/binary" - "fmt" - "math/big" - "time" - - "github.com/ethereum/go-ethereum/accounts/abi/bind" - "github.com/ethereum/go-ethereum/common" - gethtypes "github.com/ethereum/go-ethereum/core/types" - owner_helpers "github.com/smartcontractkit/ccip-owner-contracts/pkg/gethwrappers" - "github.com/smartcontractkit/ccip-owner-contracts/pkg/proposal/mcms" - "github.com/smartcontractkit/ccip-owner-contracts/pkg/proposal/timelock" - - "github.com/smartcontractkit/chainlink/deployment" - "github.com/smartcontractkit/chainlink/deployment/common/proposalutils" - "github.com/smartcontractkit/chainlink/deployment/common/types" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/shared/generated/burn_mint_erc677" -) - -type TransferToMCMSWithTimelockConfig struct { - ContractsByChain map[uint64][]common.Address - // MinDelay is for the accept ownership proposal - MinDelay time.Duration -} - -type Ownable interface { - Owner(opts *bind.CallOpts) (common.Address, error) - TransferOwnership(opts *bind.TransactOpts, newOwner common.Address) (*gethtypes.Transaction, error) - AcceptOwnership(opts *bind.TransactOpts) (*gethtypes.Transaction, error) - Address() common.Address -} - -func LoadOwnableContract(addr common.Address, client bind.ContractBackend) (common.Address, Ownable, error) { - // Just using the ownership interface from here. - c, err := burn_mint_erc677.NewBurnMintERC677(addr, client) - if err != nil { - return common.Address{}, nil, fmt.Errorf("failed to create contract: %v", err) - } - owner, err := c.Owner(nil) - if err != nil { - return common.Address{}, nil, fmt.Errorf("failed to get owner of contract: %v", err) - } - return owner, c, nil -} - -func (t TransferToMCMSWithTimelockConfig) Validate(e deployment.Environment) error { - for chainSelector, contracts := range t.ContractsByChain { - for _, contract := range contracts { - // Cannot transfer an unknown address. - // Note this also assures non-zero addresses. - if exists, err := deployment.AddressBookContains(e.ExistingAddresses, chainSelector, contract.String()); err != nil || !exists { - if err != nil { - return fmt.Errorf("failed to check address book: %v", err) - } - return fmt.Errorf("contract %s not found in address book", contract) - } - owner, _, err := LoadOwnableContract(contract, e.Chains[chainSelector].Client) - if err != nil { - return fmt.Errorf("failed to load ownable: %v", err) - } - if owner != e.Chains[chainSelector].DeployerKey.From { - return fmt.Errorf("contract %s is not owned by the deployer key", contract) - } - } - // If there is no timelock and mcms proposer on the chain, the transfer will fail. - if _, err := deployment.SearchAddressBook(e.ExistingAddresses, chainSelector, types.RBACTimelock); err != nil { - return fmt.Errorf("timelock not present on the chain %v", err) - } - if _, err := deployment.SearchAddressBook(e.ExistingAddresses, chainSelector, types.ProposerManyChainMultisig); err != nil { - return fmt.Errorf("mcms proposer not present on the chain %v", err) - } - } - - return nil -} - -var _ deployment.ChangeSet[TransferToMCMSWithTimelockConfig] = TransferToMCMSWithTimelock - -// TransferToMCMSWithTimelock creates a changeset that transfers ownership of all the -// contracts in the provided configuration to the timelock on the chain and generates -// a corresponding accept ownership proposal to complete the transfer. -// It assumes that DeployMCMSWithTimelock has already been run s.t. -// the timelock and mcmses exist on the chain and that the proposed addresses to transfer ownership -// are currently owned by the deployer key. -func TransferToMCMSWithTimelock( - e deployment.Environment, - cfg TransferToMCMSWithTimelockConfig, -) (deployment.ChangesetOutput, error) { - if err := cfg.Validate(e); err != nil { - return deployment.ChangesetOutput{}, err - } - var batches []timelock.BatchChainOperation - timelocksByChain := make(map[uint64]common.Address) - proposersByChain := make(map[uint64]*owner_helpers.ManyChainMultiSig) - for chainSelector, contracts := range cfg.ContractsByChain { - // Already validated that the timelock/proposer exists. - timelockAddr, _ := deployment.SearchAddressBook(e.ExistingAddresses, chainSelector, types.RBACTimelock) - proposerAddr, _ := deployment.SearchAddressBook(e.ExistingAddresses, chainSelector, types.ProposerManyChainMultisig) - timelocksByChain[chainSelector] = common.HexToAddress(timelockAddr) - proposer, err := owner_helpers.NewManyChainMultiSig(common.HexToAddress(proposerAddr), e.Chains[chainSelector].Client) - if err != nil { - return deployment.ChangesetOutput{}, fmt.Errorf("failed to create proposer mcms: %v", err) - } - proposersByChain[chainSelector] = proposer - - var ops []mcms.Operation - for _, contract := range contracts { - // Just using the ownership interface. - // Already validated is ownable. - owner, c, _ := LoadOwnableContract(contract, e.Chains[chainSelector].Client) - if owner.String() == timelockAddr { - // Already owned by timelock. - e.Logger.Infof("contract %s already owned by timelock", contract) - continue - } - tx, err := c.TransferOwnership(e.Chains[chainSelector].DeployerKey, common.HexToAddress(timelockAddr)) - _, err = deployment.ConfirmIfNoError(e.Chains[chainSelector], tx, err) - if err != nil { - return deployment.ChangesetOutput{}, fmt.Errorf("failed to transfer ownership of contract %T: %v", contract, err) - } - tx, err = c.AcceptOwnership(deployment.SimTransactOpts()) - if err != nil { - return deployment.ChangesetOutput{}, fmt.Errorf("failed to generate accept ownership calldata of %s: %w", contract, err) - } - ops = append(ops, mcms.Operation{ - To: contract, - Data: tx.Data(), - Value: big.NewInt(0), - }) - } - batches = append(batches, timelock.BatchChainOperation{ - ChainIdentifier: mcms.ChainIdentifier(chainSelector), - Batch: ops, - }) - } - proposal, err := proposalutils.BuildProposalFromBatches( - timelocksByChain, proposersByChain, batches, "Transfer ownership to timelock", cfg.MinDelay) - if err != nil { - return deployment.ChangesetOutput{}, fmt.Errorf("failed to build proposal from batch: %w, batches: %+v", err, batches) - } - - return deployment.ChangesetOutput{Proposals: []timelock.MCMSWithTimelockProposal{*proposal}}, nil -} - -var _ deployment.ChangeSet[TransferToDeployerConfig] = TransferToDeployer - -type TransferToDeployerConfig struct { - ContractAddress common.Address - ChainSel uint64 -} - -// TransferToDeployer relies on the deployer key -// still being a timelock admin and transfers the ownership of a contract -// back to the deployer key. It's effectively the rollback function of transferring -// to the timelock. -func TransferToDeployer(e deployment.Environment, cfg TransferToDeployerConfig) (deployment.ChangesetOutput, error) { - owner, ownable, err := LoadOwnableContract(cfg.ContractAddress, e.Chains[cfg.ChainSel].Client) - if err != nil { - return deployment.ChangesetOutput{}, err - } - if owner == e.Chains[cfg.ChainSel].DeployerKey.From { - e.Logger.Infof("Contract %s already owned by deployer", cfg.ContractAddress) - return deployment.ChangesetOutput{}, nil - } - tx, err := ownable.TransferOwnership(deployment.SimTransactOpts(), e.Chains[cfg.ChainSel].DeployerKey.From) - if err != nil { - return deployment.ChangesetOutput{}, err - } - addrs, err := e.ExistingAddresses.AddressesForChain(cfg.ChainSel) - if err != nil { - return deployment.ChangesetOutput{}, err - } - tls, err := MaybeLoadMCMSWithTimelockChainState(e.Chains[cfg.ChainSel], addrs) - if err != nil { - return deployment.ChangesetOutput{}, err - } - calls := []owner_helpers.RBACTimelockCall{ - { - Target: ownable.Address(), - Data: tx.Data(), - Value: big.NewInt(0), - }, - } - var salt [32]byte - binary.BigEndian.PutUint32(salt[:], uint32(time.Now().Unix())) - tx, err = tls.Timelock.ScheduleBatch(e.Chains[cfg.ChainSel].DeployerKey, calls, [32]byte{}, salt, big.NewInt(0)) - if _, err = deployment.ConfirmIfNoError(e.Chains[cfg.ChainSel], tx, err); err != nil { - return deployment.ChangesetOutput{}, err - } - e.Logger.Infof("scheduled transfer ownership batch with tx %s", tx.Hash().Hex()) - timelockExecutorProxy, err := owner_helpers.NewRBACTimelock(tls.CallProxy.Address(), e.Chains[cfg.ChainSel].Client) - if err != nil { - return deployment.ChangesetOutput{}, fmt.Errorf("error creating timelock executor proxy: %w", err) - } - tx, err = timelockExecutorProxy.ExecuteBatch( - e.Chains[cfg.ChainSel].DeployerKey, calls, [32]byte{}, salt) - if err != nil { - return deployment.ChangesetOutput{}, fmt.Errorf("error executing batch: %w", err) - } - if _, err = deployment.ConfirmIfNoError(e.Chains[cfg.ChainSel], tx, err); err != nil { - return deployment.ChangesetOutput{}, err - } - e.Logger.Infof("executed transfer ownership to deployer key with tx %s", tx.Hash().Hex()) - - tx, err = ownable.AcceptOwnership(e.Chains[cfg.ChainSel].DeployerKey) - if _, err = deployment.ConfirmIfNoError(e.Chains[cfg.ChainSel], tx, err); err != nil { - return deployment.ChangesetOutput{}, err - } - e.Logger.Infof("deployer key accepted ownership tx %s", tx.Hash().Hex()) - return deployment.ChangesetOutput{}, nil -} - -var _ deployment.ChangeSet[RenounceTimelockDeployerConfig] = RenounceTimelockDeployer - -type RenounceTimelockDeployerConfig struct { - ChainSel uint64 -} - -func (cfg RenounceTimelockDeployerConfig) Validate(e deployment.Environment) error { - if err := deployment.IsValidChainSelector(cfg.ChainSel); err != nil { - return fmt.Errorf("invalid chain selector: %w", err) - } - - _, ok := e.Chains[cfg.ChainSel] - if !ok { - return fmt.Errorf("chain selector: %d not found in environment", cfg.ChainSel) - } - - // MCMS should already exists - state, err := MaybeLoadMCMSWithTimelockState(e, []uint64{cfg.ChainSel}) - if err != nil { - return err - } - - contract, ok := state[cfg.ChainSel] - if !ok { - return fmt.Errorf("mcms contracts not found on chain %d", cfg.ChainSel) - } - if contract.Timelock == nil { - return fmt.Errorf("timelock not found on chain %d", cfg.ChainSel) - } - - return nil -} - -// RenounceTimelockDeployer revokes the deployer key from administering the contract. -func RenounceTimelockDeployer(e deployment.Environment, cfg RenounceTimelockDeployerConfig) (deployment.ChangesetOutput, error) { - if err := cfg.Validate(e); err != nil { - return deployment.ChangesetOutput{}, err - } - - contracts, err := MaybeLoadMCMSWithTimelockState(e, []uint64{cfg.ChainSel}) - if err != nil { - return deployment.ChangesetOutput{}, err - } - tl := contracts[cfg.ChainSel].Timelock - admin, err := tl.ADMINROLE(&bind.CallOpts{Context: e.GetContext()}) - if err != nil { - return deployment.ChangesetOutput{}, fmt.Errorf("failed to get admin role: %w", err) - } - - chain := e.Chains[cfg.ChainSel] - tx, err := tl.RenounceRole(chain.DeployerKey, admin, chain.DeployerKey.From) - if err != nil { - return deployment.ChangesetOutput{}, fmt.Errorf("failed to revoke deployer key: %w", err) - } - if _, err := deployment.ConfirmIfNoError(chain, tx, err); err != nil { - return deployment.ChangesetOutput{}, err - } - e.Logger.Infof("revoked deployer key from owning contract %s", tl.Address().Hex()) - return deployment.ChangesetOutput{}, nil -} diff --git a/deployment/common/changeset/transfer_to_mcms_with_timelock_test.go b/deployment/common/changeset/transfer_to_mcms_with_timelock_test.go deleted file mode 100644 index c8c0f462811..00000000000 --- a/deployment/common/changeset/transfer_to_mcms_with_timelock_test.go +++ /dev/null @@ -1,215 +0,0 @@ -package changeset - -import ( - "math/big" - "testing" - - "github.com/ethereum/go-ethereum/accounts/abi/bind" - "github.com/ethereum/go-ethereum/common" - chain_selectors "github.com/smartcontractkit/chain-selectors" - "github.com/stretchr/testify/require" - - "github.com/smartcontractkit/chainlink/deployment" - "github.com/smartcontractkit/chainlink/deployment/common/proposalutils" - "github.com/smartcontractkit/chainlink/deployment/common/types" - "github.com/smartcontractkit/chainlink/deployment/environment/memory" - "github.com/smartcontractkit/chainlink/v2/core/logger" -) - -func TestTransferToMCMSWithTimelock(t *testing.T) { - lggr := logger.TestLogger(t) - e := memory.NewMemoryEnvironment(t, lggr, 0, memory.MemoryEnvironmentConfig{ - Chains: 1, - Nodes: 1, - }) - chain1 := e.AllChainSelectors()[0] - e, err := ApplyChangesets(t, e, nil, []ChangesetApplication{ - { - Changeset: WrapChangeSet(DeployLinkToken), - Config: []uint64{chain1}, - }, - { - Changeset: WrapChangeSet(DeployMCMSWithTimelock), - Config: map[uint64]types.MCMSWithTimelockConfig{ - chain1: proposalutils.SingleGroupTimelockConfig(t), - }, - }, - }) - require.NoError(t, err) - addrs, err := e.ExistingAddresses.AddressesForChain(chain1) - require.NoError(t, err) - state, err := MaybeLoadMCMSWithTimelockChainState(e.Chains[chain1], addrs) - require.NoError(t, err) - link, err := MaybeLoadLinkTokenChainState(e.Chains[chain1], addrs) - require.NoError(t, err) - e, err = ApplyChangesets(t, e, map[uint64]*proposalutils.TimelockExecutionContracts{ - chain1: { - Timelock: state.Timelock, - CallProxy: state.CallProxy, - }, - }, []ChangesetApplication{ - { - Changeset: WrapChangeSet(TransferToMCMSWithTimelock), - Config: TransferToMCMSWithTimelockConfig{ - ContractsByChain: map[uint64][]common.Address{ - chain1: {link.LinkToken.Address()}, - }, - MinDelay: 0, - }, - }, - }) - require.NoError(t, err) - // We expect now that the link token is owned by the MCMS timelock. - link, err = MaybeLoadLinkTokenChainState(e.Chains[chain1], addrs) - require.NoError(t, err) - o, err := link.LinkToken.Owner(nil) - require.NoError(t, err) - require.Equal(t, state.Timelock.Address(), o) - - // Try a rollback to the deployer. - e, err = ApplyChangesets(t, e, nil, []ChangesetApplication{ - { - Changeset: WrapChangeSet(TransferToDeployer), - Config: TransferToDeployerConfig{ - ContractAddress: link.LinkToken.Address(), - ChainSel: chain1, - }, - }, - }) - require.NoError(t, err) - - o, err = link.LinkToken.Owner(nil) - require.NoError(t, err) - require.Equal(t, e.Chains[chain1].DeployerKey.From, o) -} - -func TestRenounceTimelockDeployerConfigValidate(t *testing.T) { - t.Parallel() - lggr := logger.TestLogger(t) - e := memory.NewMemoryEnvironment(t, lggr, 0, memory.MemoryEnvironmentConfig{ - Chains: 1, - Nodes: 1, - }) - chain1 := e.AllChainSelectors()[0] - e, err := ApplyChangesets(t, e, nil, []ChangesetApplication{ - { - Changeset: WrapChangeSet(DeployMCMSWithTimelock), - Config: map[uint64]types.MCMSWithTimelockConfig{ - chain1: proposalutils.SingleGroupTimelockConfig(t), - }, - }, - }) - require.NoError(t, err) - - envWithNoMCMS := memory.NewMemoryEnvironment(t, lggr, 0, memory.MemoryEnvironmentConfig{ - Chains: 1, - Nodes: 1, - }) - chain2 := envWithNoMCMS.AllChainSelectors()[0] - - for _, test := range []struct { - name string - config RenounceTimelockDeployerConfig - env deployment.Environment - err string - }{ - { - name: "valid config", - env: e, - config: RenounceTimelockDeployerConfig{ - ChainSel: chain1, - }, - }, - { - name: "invalid chain selector", - env: e, - config: RenounceTimelockDeployerConfig{ - ChainSel: 0, - }, - err: "invalid chain selector: chain selector must be set", - }, - { - name: "chain does not exists on env", - env: e, - config: RenounceTimelockDeployerConfig{ - ChainSel: chain_selectors.ETHEREUM_TESTNET_SEPOLIA.Selector, - }, - err: "chain selector: 16015286601757825753 not found in environment", - }, - { - name: "no MCMS deployed", - env: envWithNoMCMS, - config: RenounceTimelockDeployerConfig{ - ChainSel: chain2, - }, - // chain does not match any existing addresses - err: "chain selector 909606746561742123: chain not found", - }, - } { - t.Run(test.name, func(t *testing.T) { - t.Parallel() - err := test.config.Validate(test.env) - if test.err != "" { - require.EqualError(t, err, test.err) - } else { - require.NoError(t, err) - } - }) - } -} - -func TestRenounceTimelockDeployer(t *testing.T) { - lggr := logger.TestLogger(t) - e := memory.NewMemoryEnvironment(t, lggr, 0, memory.MemoryEnvironmentConfig{ - Chains: 1, - Nodes: 1, - }) - chain1 := e.AllChainSelectors()[0] - e, err := ApplyChangesets(t, e, nil, []ChangesetApplication{ - { - Changeset: WrapChangeSet(DeployMCMSWithTimelock), - Config: map[uint64]types.MCMSWithTimelockConfig{ - chain1: proposalutils.SingleGroupTimelockConfig(t), - }, - }, - }) - require.NoError(t, err) - addrs, err := e.ExistingAddresses.AddressesForChain(chain1) - require.NoError(t, err) - - state, err := MaybeLoadMCMSWithTimelockChainState(e.Chains[chain1], addrs) - require.NoError(t, err) - - tl := state.Timelock - require.NotNil(t, tl) - - adminRole, err := tl.ADMINROLE(nil) - require.NoError(t, err) - - r, err := tl.GetRoleMemberCount(&bind.CallOpts{}, adminRole) - require.NoError(t, err) - require.Equal(t, int64(2), r.Int64()) - - // Revoke Deployer - e, err = ApplyChangesets(t, e, nil, []ChangesetApplication{ - { - Changeset: WrapChangeSet(RenounceTimelockDeployer), - Config: RenounceTimelockDeployerConfig{ - ChainSel: chain1, - }, - }, - }) - require.NoError(t, err) - - // Check that the deployer is no longer an admin - r, err = tl.GetRoleMemberCount(&bind.CallOpts{}, adminRole) - require.NoError(t, err) - require.Equal(t, int64(1), r.Int64()) - - // Retrieve the admin address - admin, err := tl.GetRoleMember(&bind.CallOpts{}, adminRole, big.NewInt(0)) - require.NoError(t, err) - - // Check that the admin is the timelock - require.Equal(t, tl.Address(), admin) -} diff --git a/deployment/common/proposalutils/mcms_helpers.go b/deployment/common/proposalutils/mcms_helpers.go deleted file mode 100644 index 51a720a4389..00000000000 --- a/deployment/common/proposalutils/mcms_helpers.go +++ /dev/null @@ -1,275 +0,0 @@ -package proposalutils - -import ( - "bytes" - "encoding/json" - "errors" - "fmt" - - "github.com/ethereum/go-ethereum/accounts/abi/bind" - "github.com/ethereum/go-ethereum/common" - owner_helpers "github.com/smartcontractkit/ccip-owner-contracts/pkg/gethwrappers" - "github.com/smartcontractkit/ccip-owner-contracts/pkg/proposal/mcms" - "github.com/smartcontractkit/chainlink-common/pkg/logger" - "github.com/smartcontractkit/chainlink/deployment" - "github.com/smartcontractkit/chainlink/deployment/common/types" -) - -// TimelockExecutionContracts is a helper struct for executing timelock proposals. it contains -// the timelock and call proxy contracts. -type TimelockExecutionContracts struct { - Timelock *owner_helpers.RBACTimelock - CallProxy *owner_helpers.CallProxy -} - -// NewTimelockExecutionContracts creates a new TimelockExecutionContracts struct. -// If there are multiple timelocks or call proxy on the chain, an error is returned. -// If there is a missing timelocks or call proxy on the chain, an error is returned. -func NewTimelockExecutionContracts(env deployment.Environment, chainSelector uint64) (*TimelockExecutionContracts, error) { - addrTypeVer, err := env.ExistingAddresses.AddressesForChain(chainSelector) - if err != nil { - return nil, fmt.Errorf("error getting addresses for chain: %w", err) - } - var timelock *owner_helpers.RBACTimelock - var callProxy *owner_helpers.CallProxy - for addr, tv := range addrTypeVer { - if tv.Type == types.RBACTimelock { - if timelock != nil { - return nil, fmt.Errorf("multiple timelocks found on chain %d", chainSelector) - } - var err error - timelock, err = owner_helpers.NewRBACTimelock(common.HexToAddress(addr), env.Chains[chainSelector].Client) - if err != nil { - return nil, fmt.Errorf("error creating timelock: %w", err) - } - } - if tv.Type == types.CallProxy { - if callProxy != nil { - return nil, fmt.Errorf("multiple call proxies found on chain %d", chainSelector) - } - var err error - callProxy, err = owner_helpers.NewCallProxy(common.HexToAddress(addr), env.Chains[chainSelector].Client) - if err != nil { - return nil, fmt.Errorf("error creating call proxy: %w", err) - } - } - } - if timelock == nil || callProxy == nil { - return nil, fmt.Errorf("missing timelock (%T) or call proxy(%T) on chain %d", timelock == nil, callProxy == nil, chainSelector) - } - return &TimelockExecutionContracts{ - Timelock: timelock, - CallProxy: callProxy, - }, nil -} - -type RunTimelockExecutorConfig struct { - Executor *mcms.Executor - TimelockContracts *TimelockExecutionContracts - ChainSelector uint64 - // BlockStart is optional. It filter the timelock scheduled events. - // If not provided, the executor assumes that the operations have not been executed yet - // executes all the operations for the given chain. - BlockStart *uint64 - BlockEnd *uint64 -} - -func (cfg RunTimelockExecutorConfig) Validate() error { - if cfg.Executor == nil { - return fmt.Errorf("executor is nil") - } - if cfg.TimelockContracts == nil { - return fmt.Errorf("timelock contracts is nil") - } - if cfg.ChainSelector == 0 { - return fmt.Errorf("chain selector is 0") - } - if cfg.BlockStart != nil && cfg.BlockEnd == nil { - if *cfg.BlockStart > *cfg.BlockEnd { - return fmt.Errorf("block start is greater than block end") - } - } - if cfg.BlockStart == nil && cfg.BlockEnd != nil { - return fmt.Errorf("block start must not be nil when block end is not nil") - } - - if len(cfg.Executor.Operations[mcms.ChainIdentifier(cfg.ChainSelector)]) == 0 { - return fmt.Errorf("no operations for chain %d", cfg.ChainSelector) - } - return nil -} - -// RunTimelockExecutor runs the scheduled operations for the given chain. -// If the block start is not provided, it assumes that the operations have not been scheduled yet -// and executes all the operations for the given chain. -// It is an error if there are no operations for the given chain. -func RunTimelockExecutor(env deployment.Environment, cfg RunTimelockExecutorConfig) error { - // TODO: This sort of helper probably should move to the MCMS lib. - // Execute all the transactions in the proposal which are for this chain. - if err := cfg.Validate(); err != nil { - return fmt.Errorf("error validating config: %w", err) - } - for _, chainOp := range cfg.Executor.Operations[mcms.ChainIdentifier(cfg.ChainSelector)] { - for idx, op := range cfg.Executor.ChainAgnosticOps { - start := cfg.BlockStart - end := cfg.BlockEnd - if bytes.Equal(op.Data, chainOp.Data) && op.To == chainOp.To { - if start == nil { - opTx, err2 := cfg.Executor.ExecuteOnChain(env.Chains[cfg.ChainSelector].Client, env.Chains[cfg.ChainSelector].DeployerKey, idx) - if err2 != nil { - return fmt.Errorf("error executing on chain: %w", err2) - } - block, err2 := env.Chains[cfg.ChainSelector].Confirm(opTx) - if err2 != nil { - return fmt.Errorf("error confirming on chain: %w", err2) - } - start = &block - end = &block - } - - it, err2 := cfg.TimelockContracts.Timelock.FilterCallScheduled(&bind.FilterOpts{ - Start: *start, - End: end, - Context: env.GetContext(), - }, nil, nil) - if err2 != nil { - return fmt.Errorf("error filtering call scheduled: %w", err2) - } - var calls []owner_helpers.RBACTimelockCall - var pred, salt [32]byte - for it.Next() { - // Note these are the same for the whole batch, can overwrite - pred = it.Event.Predecessor - salt = it.Event.Salt - verboseDebug(env.Logger, it.Event) - env.Logger.Info("scheduled", "event", it.Event) - calls = append(calls, owner_helpers.RBACTimelockCall{ - Target: it.Event.Target, - Data: it.Event.Data, - Value: it.Event.Value, - }) - } - if len(calls) == 0 { - return fmt.Errorf("no calls found for chain %d in blocks [%d, %d]", cfg.ChainSelector, *start, *end) - } - timelockExecutorProxy, err := owner_helpers.NewRBACTimelock(cfg.TimelockContracts.CallProxy.Address(), env.Chains[cfg.ChainSelector].Client) - if err != nil { - return fmt.Errorf("error creating timelock executor proxy: %w", err) - } - tx, err := timelockExecutorProxy.ExecuteBatch( - env.Chains[cfg.ChainSelector].DeployerKey, calls, pred, salt) - if err != nil { - return fmt.Errorf("error executing batch: %w", err) - } - _, err = env.Chains[cfg.ChainSelector].Confirm(tx) - if err != nil { - return fmt.Errorf("error confirming batch: %w", err) - } - } - } - } - return nil -} - -func verboseDebug(lggr logger.Logger, event *owner_helpers.RBACTimelockCallScheduled) { - b, err := json.Marshal(event) - if err != nil { - panic(err) - } - lggr.Debug("scheduled", "event", string(b)) -} - -// MCMSWithTimelockContracts holds the Go bindings -// for a MCMSWithTimelock contract deployment. -// It is public for use in product specific packages. -// Either all fields are nil or all fields are non-nil. -type MCMSWithTimelockContracts struct { - CancellerMcm *owner_helpers.ManyChainMultiSig - BypasserMcm *owner_helpers.ManyChainMultiSig - ProposerMcm *owner_helpers.ManyChainMultiSig - Timelock *owner_helpers.RBACTimelock - CallProxy *owner_helpers.CallProxy -} - -// Validate checks that all fields are non-nil, ensuring it's ready -// for use generating views or interactions. -func (state MCMSWithTimelockContracts) Validate() error { - if state.Timelock == nil { - return errors.New("timelock not found") - } - if state.CancellerMcm == nil { - return errors.New("canceller not found") - } - if state.ProposerMcm == nil { - return errors.New("proposer not found") - } - if state.BypasserMcm == nil { - return errors.New("bypasser not found") - } - if state.CallProxy == nil { - return errors.New("call proxy not found") - } - return nil -} - -// MaybeLoadMCMSWithTimelockContracts looks for the addresses corresponding to -// contracts deployed with DeployMCMSWithTimelock and loads them into a -// MCMSWithTimelockState struct. If none of the contracts are found, the state struct will be nil. -// An error indicates: -// - Found but was unable to load a contract -// - It only found part of the bundle of contracts -// - If found more than one instance of a contract (we expect one bundle in the given addresses) -func MaybeLoadMCMSWithTimelockContracts(chain deployment.Chain, addresses map[string]deployment.TypeAndVersion) (*MCMSWithTimelockContracts, error) { - state := MCMSWithTimelockContracts{} - // We expect one of each contract on the chain. - timelock := deployment.NewTypeAndVersion(types.RBACTimelock, deployment.Version1_0_0) - callProxy := deployment.NewTypeAndVersion(types.CallProxy, deployment.Version1_0_0) - proposer := deployment.NewTypeAndVersion(types.ProposerManyChainMultisig, deployment.Version1_0_0) - canceller := deployment.NewTypeAndVersion(types.CancellerManyChainMultisig, deployment.Version1_0_0) - bypasser := deployment.NewTypeAndVersion(types.BypasserManyChainMultisig, deployment.Version1_0_0) - - // Ensure we either have the bundle or not. - _, err := deployment.AddressesContainBundle(addresses, - map[deployment.TypeAndVersion]struct{}{ - timelock: {}, proposer: {}, canceller: {}, bypasser: {}, callProxy: {}, - }) - if err != nil { - return nil, fmt.Errorf("unable to check MCMS contracts on chain %s error: %w", chain.Name(), err) - } - - for address, tvStr := range addresses { - switch tvStr { - case timelock: - tl, err := owner_helpers.NewRBACTimelock(common.HexToAddress(address), chain.Client) - if err != nil { - return nil, err - } - state.Timelock = tl - case callProxy: - cp, err := owner_helpers.NewCallProxy(common.HexToAddress(address), chain.Client) - if err != nil { - return nil, err - } - state.CallProxy = cp - case proposer: - mcms, err := owner_helpers.NewManyChainMultiSig(common.HexToAddress(address), chain.Client) - if err != nil { - return nil, err - } - state.ProposerMcm = mcms - case bypasser: - mcms, err := owner_helpers.NewManyChainMultiSig(common.HexToAddress(address), chain.Client) - if err != nil { - return nil, err - } - state.BypasserMcm = mcms - case canceller: - mcms, err := owner_helpers.NewManyChainMultiSig(common.HexToAddress(address), chain.Client) - if err != nil { - return nil, err - } - state.CancellerMcm = mcms - } - } - return &state, nil -} diff --git a/deployment/common/proposalutils/mcms_test_helpers.go b/deployment/common/proposalutils/mcms_test_helpers.go deleted file mode 100644 index 610fe84f34c..00000000000 --- a/deployment/common/proposalutils/mcms_test_helpers.go +++ /dev/null @@ -1,92 +0,0 @@ -package proposalutils - -import ( - "crypto/ecdsa" - "math/big" - "testing" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/crypto" - "github.com/smartcontractkit/ccip-owner-contracts/pkg/config" - "github.com/smartcontractkit/ccip-owner-contracts/pkg/proposal/mcms" - "github.com/smartcontractkit/ccip-owner-contracts/pkg/proposal/timelock" - chainsel "github.com/smartcontractkit/chain-selectors" - "github.com/stretchr/testify/require" - - "github.com/smartcontractkit/chainlink/deployment" - commontypes "github.com/smartcontractkit/chainlink/deployment/common/types" - // "github.com/smartcontractkit/chainlink/deployment/common/proposalutils" -) - -var ( - // TestXXXMCMSSigner is a throwaway private key used for signing MCMS proposals. - // in tests. - TestXXXMCMSSigner *ecdsa.PrivateKey -) - -func init() { - key, err := crypto.GenerateKey() - if err != nil { - panic(err) - } - TestXXXMCMSSigner = key -} - -func SingleGroupMCMS(t *testing.T) config.Config { - publicKey := TestXXXMCMSSigner.Public().(*ecdsa.PublicKey) - // Convert the public key to an Ethereum address - address := crypto.PubkeyToAddress(*publicKey) - c, err := config.NewConfig(1, []common.Address{address}, []config.Config{}) - require.NoError(t, err) - return *c -} - -func SignProposal(t *testing.T, env deployment.Environment, proposal *timelock.MCMSWithTimelockProposal) *mcms.Executor { - executorClients := make(map[mcms.ChainIdentifier]mcms.ContractDeployBackend) - for _, chain := range env.Chains { - chainselc, exists := chainsel.ChainBySelector(chain.Selector) - require.True(t, exists) - chainSel := mcms.ChainIdentifier(chainselc.Selector) - executorClients[chainSel] = chain.Client - } - executor, err := proposal.ToExecutor(true) - require.NoError(t, err) - payload, err := executor.SigningHash() - require.NoError(t, err) - // Sign the payload - sig, err := crypto.Sign(payload.Bytes(), TestXXXMCMSSigner) - require.NoError(t, err) - mcmSig, err := mcms.NewSignatureFromBytes(sig) - require.NoError(t, err) - executor.Proposal.AddSignature(mcmSig) - require.NoError(t, executor.Proposal.Validate()) - return executor -} - -func ExecuteProposal(t *testing.T, env deployment.Environment, executor *mcms.Executor, - timelockContracts *TimelockExecutionContracts, sel uint64) { - t.Log("Executing proposal on chain", sel) - // Set the root. - tx, err2 := executor.SetRootOnChain(env.Chains[sel].Client, env.Chains[sel].DeployerKey, mcms.ChainIdentifier(sel)) - if err2 != nil { - require.NoError(t, deployment.MaybeDataErr(err2)) - } - - _, err2 = env.Chains[sel].Confirm(tx) - require.NoError(t, err2) - cfg := RunTimelockExecutorConfig{ - Executor: executor, - TimelockContracts: timelockContracts, - ChainSelector: sel, - } - require.NoError(t, RunTimelockExecutor(env, cfg)) -} - -func SingleGroupTimelockConfig(t *testing.T) commontypes.MCMSWithTimelockConfig { - return commontypes.MCMSWithTimelockConfig{ - Canceller: SingleGroupMCMS(t), - Bypasser: SingleGroupMCMS(t), - Proposer: SingleGroupMCMS(t), - TimelockMinDelay: big.NewInt(0), - } -} diff --git a/deployment/common/proposalutils/propose.go b/deployment/common/proposalutils/propose.go deleted file mode 100644 index baf506cb2f8..00000000000 --- a/deployment/common/proposalutils/propose.go +++ /dev/null @@ -1,88 +0,0 @@ -package proposalutils - -import ( - "fmt" - "time" - - mapset "github.com/deckarep/golang-set/v2" - "github.com/ethereum/go-ethereum/common" - "github.com/smartcontractkit/ccip-owner-contracts/pkg/gethwrappers" - "github.com/smartcontractkit/ccip-owner-contracts/pkg/proposal/mcms" - "github.com/smartcontractkit/ccip-owner-contracts/pkg/proposal/timelock" -) - -const ( - DefaultValidUntil = 72 * time.Hour -) - - -func BuildProposalMetadata( - chainSelectors []uint64, - proposerMcmsesPerChain map[uint64]*gethwrappers.ManyChainMultiSig, -) (map[mcms.ChainIdentifier]mcms.ChainMetadata, error) { - metaDataPerChain := make(map[mcms.ChainIdentifier]mcms.ChainMetadata) - for _, selector := range chainSelectors { - proposerMcms, ok := proposerMcmsesPerChain[selector] - if !ok { - return nil, fmt.Errorf("missing proposer mcm for chain %d", selector) - } - chainId := mcms.ChainIdentifier(selector) - opCount, err := proposerMcms.GetOpCount(nil) - if err != nil { - return nil, fmt.Errorf("failed to get op count for chain %d: %w", selector, err) - } - metaDataPerChain[chainId] = mcms.ChainMetadata{ - StartingOpCount: opCount.Uint64(), - MCMAddress: proposerMcms.Address(), - } - } - return metaDataPerChain, nil -} - -// BuildProposalFromBatches Given batches of operations, we build the metadata and timelock addresses of those opartions -// We then return a proposal that can be executed and signed. -// You can specify multiple batches for the same chain, but the only -// usecase to do that would be you have a batch that can't fit in a single -// transaction due to gas or calldata constraints of the chain. -// The batches are specified separately because we eventually intend -// to support user-specified cross chain ordering of batch execution by the tooling itself. -// TODO: Can/should merge timelocks and proposers into a single map for the chain. -func BuildProposalFromBatches( - timelocksPerChain map[uint64]common.Address, - proposerMcmsesPerChain map[uint64]*gethwrappers.ManyChainMultiSig, - batches []timelock.BatchChainOperation, - description string, - minDelay time.Duration, -) (*timelock.MCMSWithTimelockProposal, error) { - if len(batches) == 0 { - return nil, fmt.Errorf("no operations in batch") - } - - chains := mapset.NewSet[uint64]() - for _, op := range batches { - chains.Add(uint64(op.ChainIdentifier)) - } - - mcmsMd, err := BuildProposalMetadata(chains.ToSlice(), proposerMcmsesPerChain) - if err != nil { - return nil, err - } - - tlsPerChainId := make(map[mcms.ChainIdentifier]common.Address) - for chainId, tl := range timelocksPerChain { - tlsPerChainId[mcms.ChainIdentifier(chainId)] = tl - } - validUntil := time.Now().Unix() + int64(DefaultValidUntil.Seconds()) - return timelock.NewMCMSWithTimelockProposal( - "1", - uint32(validUntil), - []mcms.Signature{}, - false, - mcmsMd, - tlsPerChainId, - description, - batches, - timelock.Schedule, - minDelay.String(), - ) -} diff --git a/deployment/common/types/types.go b/deployment/common/types/types.go deleted file mode 100644 index 0f04421af43..00000000000 --- a/deployment/common/types/types.go +++ /dev/null @@ -1,91 +0,0 @@ -package types - -import ( - "fmt" - "math/big" - "time" - - "github.com/smartcontractkit/ccip-owner-contracts/pkg/config" - - "github.com/smartcontractkit/chainlink/deployment" -) - -const ( - BypasserManyChainMultisig deployment.ContractType = "BypasserManyChainMultiSig" - CancellerManyChainMultisig deployment.ContractType = "CancellerManyChainMultiSig" - ProposerManyChainMultisig deployment.ContractType = "ProposerManyChainMultiSig" - RBACTimelock deployment.ContractType = "RBACTimelock" - CallProxy deployment.ContractType = "CallProxy" - // LinkToken is the burn/mint link token. It should be used everywhere for - // new deployments. Corresponds to - // https://github.com/smartcontractkit/chainlink/blob/develop/core/gethwrappers/shared/generated/link_token/link_token.go#L34 - LinkToken deployment.ContractType = "LinkToken" - // StaticLinkToken represents the (very old) non-burn/mint link token. - // It is not used in new deployments, but still exists on some chains - // and has a distinct ABI from the new LinkToken. - // Corresponds to the ABI - // https://github.com/smartcontractkit/chainlink/blob/develop/core/gethwrappers/generated/link_token_interface/link_token_interface.go#L34 - StaticLinkToken deployment.ContractType = "StaticLinkToken" -) - -type MCMSWithTimelockConfig struct { - Canceller config.Config - Bypasser config.Config - Proposer config.Config - TimelockMinDelay *big.Int -} - -type OCRParameters struct { - DeltaProgress time.Duration - DeltaResend time.Duration - DeltaInitial time.Duration - DeltaRound time.Duration - DeltaGrace time.Duration - DeltaCertifiedCommitRequest time.Duration - DeltaStage time.Duration - Rmax uint64 - MaxDurationQuery time.Duration - MaxDurationObservation time.Duration - MaxDurationShouldAcceptAttestedReport time.Duration - MaxDurationShouldTransmitAcceptedReport time.Duration -} - -func (params OCRParameters) Validate() error { - if params.DeltaProgress <= 0 { - return fmt.Errorf("deltaProgress must be positive") - } - if params.DeltaResend <= 0 { - return fmt.Errorf("deltaResend must be positive") - } - if params.DeltaInitial <= 0 { - return fmt.Errorf("deltaInitial must be positive") - } - if params.DeltaRound <= 0 { - return fmt.Errorf("deltaRound must be positive") - } - if params.DeltaGrace <= 0 { - return fmt.Errorf("deltaGrace must be positive") - } - if params.DeltaCertifiedCommitRequest <= 0 { - return fmt.Errorf("deltaCertifiedCommitRequest must be positive") - } - if params.DeltaStage <= 0 { - return fmt.Errorf("deltaStage must be positive") - } - if params.Rmax <= 0 { - return fmt.Errorf("rmax must be positive") - } - if params.MaxDurationQuery <= 0 { - return fmt.Errorf("maxDurationQuery must be positive") - } - if params.MaxDurationObservation <= 0 { - return fmt.Errorf("maxDurationObservation must be positive") - } - if params.MaxDurationShouldAcceptAttestedReport <= 0 { - return fmt.Errorf("maxDurationShouldAcceptAttestedReport must be positive") - } - if params.MaxDurationShouldTransmitAcceptedReport <= 0 { - return fmt.Errorf("maxDurationShouldTransmitAcceptedReport must be positive") - } - return nil -} diff --git a/deployment/common/view/nops.go b/deployment/common/view/nops.go index 61e16d59145..12b8dad96f4 100644 --- a/deployment/common/view/nops.go +++ b/deployment/common/view/nops.go @@ -4,16 +4,15 @@ import ( "context" "fmt" - "github.com/pkg/errors" - nodev1 "github.com/smartcontractkit/chainlink-protos/job-distributor/v1/node" + chainsel "github.com/smartcontractkit/chain-selectors" + nodev1 "github.com/smartcontractkit/chainlink-protos/job-distributor/v1/node" "github.com/smartcontractkit/chainlink/deployment" ) type NopView struct { // NodeID is the unique identifier of the node NodeID string `json:"nodeID"` - PeerID string `json:"peerID"` IsBootstrap bool `json:"isBootstrap"` OCRKeys map[string]OCRKeyView `json:"ocrKeys"` PayeeAddress string `json:"payeeAddress"` @@ -41,7 +40,7 @@ func GenerateNopsView(nodeIds []string, oc deployment.OffchainClient) (map[strin // get node info nodeDetails, err := oc.GetNode(context.Background(), &nodev1.GetNodeRequest{Id: node.NodeID}) if err != nil { - return nv, errors.Wrapf(err, "failed to get node details from offchain client for node %s", node.NodeID) + return nv, err } if nodeDetails == nil || nodeDetails.Node == nil { return nv, fmt.Errorf("failed to get node details from offchain client for node %s", node.NodeID) @@ -52,7 +51,6 @@ func GenerateNopsView(nodeIds []string, oc deployment.OffchainClient) (map[strin } nop := NopView{ NodeID: node.NodeID, - PeerID: node.PeerID.String(), IsBootstrap: node.IsBootstrap, OCRKeys: make(map[string]OCRKeyView), PayeeAddress: node.AdminAddr, @@ -60,8 +58,16 @@ func GenerateNopsView(nodeIds []string, oc deployment.OffchainClient) (map[strin IsConnected: nodeDetails.Node.IsConnected, IsEnabled: nodeDetails.Node.IsEnabled, } - for details, ocrConfig := range node.SelToOCRConfig { - nop.OCRKeys[details.ChainName] = OCRKeyView{ + for sel, ocrConfig := range node.SelToOCRConfig { + chainid, err := chainsel.ChainIdFromSelector(sel) + if err != nil { + return nv, err + } + chainName, err := chainsel.NameFromChainId(chainid) + if err != nil { + return nv, err + } + nop.OCRKeys[chainName] = OCRKeyView{ OffchainPublicKey: fmt.Sprintf("%x", ocrConfig.OffchainPublicKey[:]), OnchainPublicKey: fmt.Sprintf("%x", ocrConfig.OnchainPublicKey[:]), PeerID: ocrConfig.PeerID.String(), diff --git a/deployment/common/view/types/contract_state.go b/deployment/common/view/types/contract_state.go index 9b63d1f4db0..f65c510af53 100644 --- a/deployment/common/view/types/contract_state.go +++ b/deployment/common/view/types/contract_state.go @@ -1,8 +1,6 @@ package types import ( - "fmt" - "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" ) @@ -16,11 +14,11 @@ type ContractMetaData struct { func NewContractMetaData(tv Meta, addr common.Address) (ContractMetaData, error) { tvStr, err := tv.TypeAndVersion(nil) if err != nil { - return ContractMetaData{}, fmt.Errorf("failed to get type and version addr %s: %w", addr.String(), err) + return ContractMetaData{}, err } owner, err := tv.Owner(nil) if err != nil { - return ContractMetaData{}, fmt.Errorf("failed to get owner addr %s: %w", addr.String(), err) + return ContractMetaData{}, err } return ContractMetaData{ TypeAndVersion: tvStr, diff --git a/deployment/common/view/v1_0/capreg.go b/deployment/common/view/v1_0/capreg.go index 1d3ea485cf1..2ddd5a13463 100644 --- a/deployment/common/view/v1_0/capreg.go +++ b/deployment/common/view/v1_0/capreg.go @@ -11,7 +11,7 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/smartcontractkit/chainlink/deployment/common/view/types" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry_1_1_0" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/p2pkey" ) @@ -26,7 +26,7 @@ type CapabilityRegistryView struct { // MarshalJSON marshals the CapabilityRegistryView to JSON. It includes the Capabilities, Nodes, Nops, and Dons // and a denormalized summary of the Dons with their associated Nodes and Capabilities, which is useful for a high-level view -func (v *CapabilityRegistryView) MarshalJSON() ([]byte, error) { +func (v CapabilityRegistryView) MarshalJSON() ([]byte, error) { // Alias to avoid recursive calls type Alias struct { types.ContractMetaData @@ -51,36 +51,6 @@ func (v *CapabilityRegistryView) MarshalJSON() ([]byte, error) { return json.MarshalIndent(&a, "", " ") } -// UnmarshalJSON unmarshals the CapabilityRegistryView from JSON. Since the CapabilityRegistryView doesn't hold a DonCapabilities field, -// it is not unmarshaled. -func (v *CapabilityRegistryView) UnmarshalJSON(data []byte) error { - // Alias to avoid recursive calls - type Alias struct { - types.ContractMetaData - Capabilities []CapabilityView `json:"capabilities,omitempty"` - Nodes []NodeView `json:"nodes,omitempty"` - Nops []NopView `json:"nops,omitempty"` - Dons []DonView `json:"dons,omitempty"` - DonCapabilities []DonDenormalizedView `json:"don_capabilities_summary,omitempty"` - } - a := Alias{ - ContractMetaData: v.ContractMetaData, - Capabilities: v.Capabilities, - Nodes: v.Nodes, - Nops: v.Nops, - Dons: v.Dons, - } - if err := json.Unmarshal(data, &a); err != nil { - return err - } - v.ContractMetaData = a.ContractMetaData - v.Capabilities = a.Capabilities - v.Nodes = a.Nodes - v.Nops = a.Nops - v.Dons = a.Dons - return nil -} - // GenerateCapabilityRegistryView generates a CapRegView from a CapabilitiesRegistry contract. func GenerateCapabilityRegistryView(capReg *capabilities_registry.CapabilitiesRegistry) (CapabilityRegistryView, error) { tv, err := types.NewContractMetaData(capReg, capReg.Address()) @@ -142,7 +112,7 @@ type DonDenormalizedView struct { // Nodes and Capabilities. This is a useful form of the CapabilityRegistryView, but it is not definitive. // The full CapRegView should be used for the most accurate information as it can contain // Capabilities and Nodes the are not associated with any Don. -func (v *CapabilityRegistryView) DonDenormalizedView() ([]DonDenormalizedView, error) { +func (v CapabilityRegistryView) DonDenormalizedView() ([]DonDenormalizedView, error) { var out []DonDenormalizedView for _, don := range v.Dons { var nodes []NodeDenormalizedView @@ -170,91 +140,6 @@ func (v *CapabilityRegistryView) DonDenormalizedView() ([]DonDenormalizedView, e return out, nil } -func (v *CapabilityRegistryView) NodesToNodesParams() ([]capabilities_registry.CapabilitiesRegistryNodeParams, error) { - var nodesParams []capabilities_registry.CapabilitiesRegistryNodeParams - for _, node := range v.Nodes { - signer, err := hexTo32Bytes(node.Signer) - if err != nil { - return nil, err - } - encryptionPubKey, err := hexTo32Bytes(node.EncryptionPublicKey) - if err != nil { - return nil, err - } - capIDs := make([][32]byte, len(node.CapabilityIDs)) - for i, id := range node.CapabilityIDs { - cid, err := hexTo32Bytes(id) - if err != nil { - return nil, err - } - capIDs[i] = cid - } - nodesParams = append(nodesParams, capabilities_registry.CapabilitiesRegistryNodeParams{ - Signer: signer, - P2pId: node.P2pId, - EncryptionPublicKey: encryptionPubKey, - NodeOperatorId: node.NodeOperatorID, - HashedCapabilityIds: capIDs, - }) - } - - return nodesParams, nil -} - -func (v *CapabilityRegistryView) CapabilitiesToCapabilitiesParams() []capabilities_registry.CapabilitiesRegistryCapability { - var capabilitiesParams []capabilities_registry.CapabilitiesRegistryCapability - for _, capability := range v.Capabilities { - capabilitiesParams = append(capabilitiesParams, capabilities_registry.CapabilitiesRegistryCapability{ - LabelledName: capability.LabelledName, - Version: capability.Version, - CapabilityType: capability.CapabilityType, - ResponseType: capability.ResponseType, - ConfigurationContract: capability.ConfigurationContract, - }) - } - return capabilitiesParams -} - -func (v *CapabilityRegistryView) NopsToNopsParams() []capabilities_registry.CapabilitiesRegistryNodeOperator { - var nopsParams []capabilities_registry.CapabilitiesRegistryNodeOperator - for _, nop := range v.Nops { - nopsParams = append(nopsParams, capabilities_registry.CapabilitiesRegistryNodeOperator{ - Admin: nop.Admin, - Name: nop.Name, - }) - } - return nopsParams -} - -func (v *CapabilityRegistryView) CapabilityConfigToCapabilityConfigParams(don DonView) ([]capabilities_registry.CapabilitiesRegistryCapabilityConfiguration, error) { - var cfgs []capabilities_registry.CapabilitiesRegistryCapabilityConfiguration - for _, cfg := range don.CapabilityConfigurations { - cid, err := hexTo32Bytes(cfg.ID) - if err != nil { - return nil, err - } - config, err := hex.DecodeString(cfg.Config) - if err != nil { - return nil, err - } - cfgs = append(cfgs, capabilities_registry.CapabilitiesRegistryCapabilityConfiguration{ - CapabilityId: cid, - Config: config, - }) - } - return cfgs, nil -} - -func hexTo32Bytes(val string) ([32]byte, error) { - var out [32]byte - b, err := hex.DecodeString(val) - if err != nil { - return out, err - } - copy(out[:], b) - return out, nil -} - // CapabilityView is a serialization-friendly view of a capability in the capabilities registry. type CapabilityView struct { ID string `json:"id"` // hex 32 bytes @@ -387,7 +272,7 @@ func NewNodeView(n capabilities_registry.INodeInfoProviderNodeInfo) NodeView { ConfigCount: n.ConfigCount, WorkflowDONID: n.WorkflowDONId, Signer: hex.EncodeToString(n.Signer[:]), - P2pId: n.P2pId, + P2pId: p2pkey.PeerID(n.P2pId), EncryptionPublicKey: hex.EncodeToString(n.EncryptionPublicKey[:]), }, NodeOperatorID: n.NodeOperatorId, @@ -443,7 +328,7 @@ func NewNopView(nop capabilities_registry.CapabilitiesRegistryNodeOperator) NopV } } -func (v *CapabilityRegistryView) nodeDenormalizedView(n NodeView) (NodeDenormalizedView, error) { +func (v CapabilityRegistryView) nodeDenormalizedView(n NodeView) (NodeDenormalizedView, error) { nop, err := nodeNop(n, v.Nops) if err != nil { return NodeDenormalizedView{}, err diff --git a/deployment/common/view/v1_0/capreg_test.go b/deployment/common/view/v1_0/capreg_test.go index 15fe23be00e..8ba7b880364 100644 --- a/deployment/common/view/v1_0/capreg_test.go +++ b/deployment/common/view/v1_0/capreg_test.go @@ -4,10 +4,9 @@ import ( "math/big" "testing" - "github.com/stretchr/testify/assert" - "github.com/smartcontractkit/chainlink/deployment/common/view/types" - cr "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry_1_1_0" + cr "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry" + "github.com/stretchr/testify/assert" ) func TestCapRegView_Denormalize(t *testing.T) { diff --git a/deployment/common/view/v1_0/link_token.go b/deployment/common/view/v1_0/link_token.go deleted file mode 100644 index 6dd1a00be3b..00000000000 --- a/deployment/common/view/v1_0/link_token.go +++ /dev/null @@ -1,58 +0,0 @@ -package v1_0 - -import ( - "fmt" - "math/big" - - "github.com/ethereum/go-ethereum/common" - - "github.com/smartcontractkit/chainlink/deployment" - commontypes "github.com/smartcontractkit/chainlink/deployment/common/types" - "github.com/smartcontractkit/chainlink/deployment/common/view/types" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/shared/generated/link_token" -) - -type LinkTokenView struct { - types.ContractMetaData - Decimals uint8 `json:"decimals"` - Supply *big.Int `json:"supply"` - Minters []common.Address `json:"minters"` - Burners []common.Address `json:"burners"` -} - -func GenerateLinkTokenView(lt *link_token.LinkToken) (LinkTokenView, error) { - owner, err := lt.Owner(nil) - if err != nil { - return LinkTokenView{}, fmt.Errorf("failed to get owner %s: %w", lt.Address(), err) - } - decimals, err := lt.Decimals(nil) - if err != nil { - return LinkTokenView{}, fmt.Errorf("failed to get decimals %s: %w", lt.Address(), err) - } - totalSupply, err := lt.TotalSupply(nil) - if err != nil { - return LinkTokenView{}, fmt.Errorf("failed to get total supply %s: %w", lt.Address(), err) - } - minters, err := lt.GetMinters(nil) - if err != nil { - return LinkTokenView{}, fmt.Errorf("failed to get minters %s: %w", lt.Address(), err) - } - burners, err := lt.GetBurners(nil) - if err != nil { - return LinkTokenView{}, fmt.Errorf("failed to get burners %s: %w", lt.Address(), err) - } - return LinkTokenView{ - ContractMetaData: types.ContractMetaData{ - TypeAndVersion: deployment.TypeAndVersion{ - commontypes.LinkToken, - deployment.Version1_0_0, - }.String(), - Address: lt.Address(), - Owner: owner, - }, - Decimals: decimals, - Supply: totalSupply, - Minters: minters, - Burners: burners, - }, nil -} diff --git a/deployment/common/view/v1_0/link_token_test.go b/deployment/common/view/v1_0/link_token_test.go deleted file mode 100644 index c83c0b3e3c2..00000000000 --- a/deployment/common/view/v1_0/link_token_test.go +++ /dev/null @@ -1,53 +0,0 @@ -package v1_0 - -import ( - "math/big" - "testing" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - "go.uber.org/zap/zapcore" - - "github.com/smartcontractkit/chainlink/deployment/environment/memory" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/shared/generated/link_token" - "github.com/smartcontractkit/chainlink/v2/core/logger" -) - -func TestLinkTokenView(t *testing.T) { - e := memory.NewMemoryEnvironment(t, logger.TestLogger(t), zapcore.InfoLevel, memory.MemoryEnvironmentConfig{ - Chains: 1, - }) - chain := e.Chains[e.AllChainSelectors()[0]] - _, tx, lt, err := link_token.DeployLinkToken(chain.DeployerKey, chain.Client) - require.NoError(t, err) - _, err = chain.Confirm(tx) - require.NoError(t, err) - v, err := GenerateLinkTokenView(lt) - require.NoError(t, err) - - assert.Equal(t, v.Owner, chain.DeployerKey.From) - assert.Equal(t, v.TypeAndVersion, "LinkToken 1.0.0") - assert.Equal(t, v.Decimals, uint8(18)) - // Initially nothing minted and no minters/burners. - assert.Equal(t, v.Supply.String(), "0") - require.Len(t, v.Minters, 0) - require.Len(t, v.Burners, 0) - - // Add some minters - tx, err = lt.GrantMintAndBurnRoles(chain.DeployerKey, chain.DeployerKey.From) - require.NoError(t, err) - _, err = chain.Confirm(tx) - require.NoError(t, err) - tx, err = lt.Mint(chain.DeployerKey, chain.DeployerKey.From, big.NewInt(100)) - _, err = chain.Confirm(tx) - require.NoError(t, err) - - v, err = GenerateLinkTokenView(lt) - require.NoError(t, err) - - assert.Equal(t, v.Supply.String(), "100") - require.Len(t, v.Minters, 1) - require.Equal(t, v.Minters[0].String(), chain.DeployerKey.From.String()) - require.Len(t, v.Burners, 1) - require.Equal(t, v.Burners[0].String(), chain.DeployerKey.From.String()) -} diff --git a/deployment/common/view/v1_0/mcms.go b/deployment/common/view/v1_0/mcms.go deleted file mode 100644 index bc971623545..00000000000 --- a/deployment/common/view/v1_0/mcms.go +++ /dev/null @@ -1,164 +0,0 @@ -package v1_0 - -import ( - "math/big" - - "github.com/ethereum/go-ethereum/common" - "github.com/smartcontractkit/ccip-owner-contracts/pkg/config" - owner_helpers "github.com/smartcontractkit/ccip-owner-contracts/pkg/gethwrappers" - - "github.com/smartcontractkit/chainlink/deployment/common/view/types" - "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" -) - -type Role struct { - ID common.Hash - Name string -} - -const ( - EXECUTOR_ROLE_STR = "EXECUTOR_ROLE" - BYPASSER_ROLE_STR = "BYPASSER_ROLE" - CANCELLER_ROLE_STR = "CANCELLER_ROLE" - PROPOSER_ROLE_STR = "PROPOSER_ROLE" - ADMIN_ROLE_STR = "ADMIN_ROLE" -) - -// https://github.com/smartcontractkit/ccip-owner-contracts/blob/9d81692b324ce7ea2ef8a75e683889edbc7e2dd0/src/RBACTimelock.sol#L71 -// Just to avoid invoking the Go binding to get these. -var ( - ADMIN_ROLE = Role{ - ID: utils.MustHash(ADMIN_ROLE_STR), - Name: ADMIN_ROLE_STR, - } - PROPOSER_ROLE = Role{ - ID: utils.MustHash(PROPOSER_ROLE_STR), - Name: PROPOSER_ROLE_STR, - } - BYPASSER_ROLE = Role{ - ID: utils.MustHash(BYPASSER_ROLE_STR), - Name: BYPASSER_ROLE_STR, - } - CANCELLER_ROLE = Role{ - ID: utils.MustHash(CANCELLER_ROLE_STR), - Name: CANCELLER_ROLE_STR, - } - EXECUTOR_ROLE = Role{ - ID: utils.MustHash(EXECUTOR_ROLE_STR), - Name: EXECUTOR_ROLE_STR, - } -) - -type MCMSView struct { - types.ContractMetaData - // Note config is json marshallable. - Config config.Config `json:"config"` -} - -func GenerateMCMSView(mcms owner_helpers.ManyChainMultiSig) (MCMSView, error) { - owner, err := mcms.Owner(nil) - if err != nil { - return MCMSView{}, nil - } - c, err := mcms.GetConfig(nil) - if err != nil { - return MCMSView{}, nil - } - parsedConfig, err := config.NewConfigFromRaw(c) - if err != nil { - return MCMSView{}, nil - } - return MCMSView{ - // Has no type and version on the contract - ContractMetaData: types.ContractMetaData{ - Owner: owner, - Address: mcms.Address(), - }, - Config: *parsedConfig, - }, nil -} - -type TimelockView struct { - types.ContractMetaData - MembersByRole map[string][]common.Address `json:"membersByRole"` -} - -func GenerateTimelockView(tl owner_helpers.RBACTimelock) (TimelockView, error) { - membersByRole := make(map[string][]common.Address) - for _, role := range []Role{ADMIN_ROLE, PROPOSER_ROLE, BYPASSER_ROLE, CANCELLER_ROLE, EXECUTOR_ROLE} { - numMembers, err := tl.GetRoleMemberCount(nil, role.ID) - if err != nil { - return TimelockView{}, nil - } - for i := int64(0); i < numMembers.Int64(); i++ { - member, err2 := tl.GetRoleMember(nil, role.ID, big.NewInt(i)) - if err2 != nil { - return TimelockView{}, nil - } - membersByRole[role.Name] = append(membersByRole[role.Name], member) - } - } - return TimelockView{ - // Has no type and version or owner. - ContractMetaData: types.ContractMetaData{ - Address: tl.Address(), - }, - MembersByRole: membersByRole, - }, nil -} - -type CallProxyView struct { - types.ContractMetaData -} - -func GenerateCallProxyView(cp owner_helpers.CallProxy) (CallProxyView, error) { - return CallProxyView{ - ContractMetaData: types.ContractMetaData{ - Address: cp.Address(), - }, - }, nil -} - -type MCMSWithTimelockView struct { - Bypasser MCMSView `json:"bypasser"` - Canceller MCMSView `json:"canceller"` - Proposer MCMSView `json:"proposer"` - Timelock TimelockView `json:"timelock"` - CallProxy CallProxyView `json:"callProxy"` -} - -func GenerateMCMSWithTimelockView( - bypasser owner_helpers.ManyChainMultiSig, - canceller owner_helpers.ManyChainMultiSig, - proposer owner_helpers.ManyChainMultiSig, - timelock owner_helpers.RBACTimelock, -) (MCMSWithTimelockView, error) { - timelockView, err := GenerateTimelockView(timelock) - if err != nil { - return MCMSWithTimelockView{}, nil - } - callProxyView, err := GenerateCallProxyView(owner_helpers.CallProxy{}) - if err != nil { - return MCMSWithTimelockView{}, nil - } - bypasserView, err := GenerateMCMSView(bypasser) - if err != nil { - return MCMSWithTimelockView{}, nil - } - proposerView, err := GenerateMCMSView(proposer) - if err != nil { - return MCMSWithTimelockView{}, nil - } - cancellerView, err := GenerateMCMSView(canceller) - if err != nil { - return MCMSWithTimelockView{}, nil - } - - return MCMSWithTimelockView{ - Timelock: timelockView, - Bypasser: bypasserView, - Proposer: proposerView, - Canceller: cancellerView, - CallProxy: callProxyView, - }, nil -} diff --git a/deployment/common/view/v1_0/static_link_token.go b/deployment/common/view/v1_0/static_link_token.go deleted file mode 100644 index 525f1a9f0c5..00000000000 --- a/deployment/common/view/v1_0/static_link_token.go +++ /dev/null @@ -1,40 +0,0 @@ -package v1_0 - -import ( - "fmt" - "math/big" - - "github.com/smartcontractkit/chainlink/deployment" - commontypes "github.com/smartcontractkit/chainlink/deployment/common/types" - "github.com/smartcontractkit/chainlink/deployment/common/view/types" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/link_token_interface" -) - -type StaticLinkTokenView struct { - types.ContractMetaData - Decimals uint8 `json:"decimals"` - Supply *big.Int `json:"supply"` -} - -func GenerateStaticLinkTokenView(lt *link_token_interface.LinkToken) (StaticLinkTokenView, error) { - decimals, err := lt.Decimals(nil) - if err != nil { - return StaticLinkTokenView{}, fmt.Errorf("failed to get decimals %s: %w", lt.Address(), err) - } - totalSupply, err := lt.TotalSupply(nil) - if err != nil { - return StaticLinkTokenView{}, fmt.Errorf("failed to get total supply %s: %w", lt.Address(), err) - } - return StaticLinkTokenView{ - ContractMetaData: types.ContractMetaData{ - TypeAndVersion: deployment.TypeAndVersion{ - commontypes.StaticLinkToken, - deployment.Version1_0_0, - }.String(), - Address: lt.Address(), - // No owner. - }, - Decimals: decimals, - Supply: totalSupply, - }, nil -} diff --git a/deployment/common/view/v1_0/static_link_token_test.go b/deployment/common/view/v1_0/static_link_token_test.go deleted file mode 100644 index 517efac9438..00000000000 --- a/deployment/common/view/v1_0/static_link_token_test.go +++ /dev/null @@ -1,32 +0,0 @@ -package v1_0 - -import ( - "testing" - - "github.com/ethereum/go-ethereum/common" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - "go.uber.org/zap/zapcore" - - "github.com/smartcontractkit/chainlink/deployment/environment/memory" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/link_token_interface" - "github.com/smartcontractkit/chainlink/v2/core/logger" -) - -func TestStaticLinkTokenView(t *testing.T) { - e := memory.NewMemoryEnvironment(t, logger.TestLogger(t), zapcore.InfoLevel, memory.MemoryEnvironmentConfig{ - Chains: 1, - }) - chain := e.Chains[e.AllChainSelectors()[0]] - _, tx, lt, err := link_token_interface.DeployLinkToken(chain.DeployerKey, chain.Client) - require.NoError(t, err) - _, err = chain.Confirm(tx) - require.NoError(t, err) - v, err := GenerateStaticLinkTokenView(lt) - require.NoError(t, err) - - assert.Equal(t, v.Owner, common.HexToAddress("0x0")) // Ownerless - assert.Equal(t, v.TypeAndVersion, "StaticLinkToken 1.0.0") - assert.Equal(t, v.Decimals, uint8(18)) - assert.Equal(t, v.Supply.String(), "1000000000000000000000000000") -} diff --git a/deployment/environment.go b/deployment/environment.go index bfbeac2f0c4..5d4e782b0fe 100644 --- a/deployment/environment.go +++ b/deployment/environment.go @@ -7,13 +7,14 @@ import ( "fmt" "math/big" "sort" - "strings" + "strconv" "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/rpc" chain_selectors "github.com/smartcontractkit/chain-selectors" + "github.com/smartcontractkit/chainlink-testing-framework/lib/docker/test_env" types2 "github.com/smartcontractkit/libocr/offchainreporting2/types" types3 "github.com/smartcontractkit/libocr/offchainreporting2plus/types" "google.golang.org/grpc" @@ -22,7 +23,6 @@ import ( csav1 "github.com/smartcontractkit/chainlink-protos/job-distributor/v1/csa" jobv1 "github.com/smartcontractkit/chainlink-protos/job-distributor/v1/job" nodev1 "github.com/smartcontractkit/chainlink-protos/job-distributor/v1/node" - "github.com/smartcontractkit/chainlink-protos/job-distributor/v1/shared/ptypes" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/p2pkey" ) @@ -54,30 +54,6 @@ type Chain struct { // Note the Sign function can be abstract supporting a variety of key storage mechanisms (e.g. KMS etc). DeployerKey *bind.TransactOpts Confirm func(tx *types.Transaction) (uint64, error) - // Users are a set of keys that can be used to interact with the chain. - // These are distinct from the deployer key. - Users []*bind.TransactOpts -} - -func (c Chain) String() string { - chainInfo, err := ChainInfo(c.Selector) - if err != nil { - // we should never get here, if the selector is invalid it should not be in the environment - panic(err) - } - return fmt.Sprintf("%s (%d)", chainInfo.ChainName, chainInfo.ChainSelector) -} - -func (c Chain) Name() string { - chainInfo, err := ChainInfo(c.Selector) - if err != nil { - // we should never get here, if the selector is invalid it should not be in the environment - panic(err) - } - if chainInfo.ChainName == "" { - return fmt.Sprintf("%d", c.Selector) - } - return chainInfo.ChainName } // Environment represents an instance of a deployed product @@ -98,11 +74,9 @@ type Environment struct { Logger logger.Logger ExistingAddresses AddressBook Chains map[uint64]Chain - SolChains map[uint64]SolChain NodeIDs []string Offchain OffchainClient - GetContext func() context.Context - OCRSecrets OCRSecrets + MockAdapter *test_env.Killgrave } func NewEnvironment( @@ -112,8 +86,6 @@ func NewEnvironment( chains map[uint64]Chain, nodeIDs []string, offchain OffchainClient, - ctx func() context.Context, - secrets OCRSecrets, ) *Environment { return &Environment{ Name: name, @@ -122,8 +94,6 @@ func NewEnvironment( Chains: chains, NodeIDs: nodeIDs, Offchain: offchain, - GetContext: ctx, - OCRSecrets: secrets, } } @@ -158,21 +128,13 @@ func (e Environment) AllChainSelectorsExcluding(excluding []uint64) []uint64 { return selectors } -func (e Environment) AllDeployerKeys() []common.Address { - var deployerKeys []common.Address - for sel := range e.Chains { - deployerKeys = append(deployerKeys, e.Chains[sel].DeployerKey.From) - } - return deployerKeys -} - func ConfirmIfNoError(chain Chain, tx *types.Transaction, err error) (uint64, error) { if err != nil { //revive:disable var d rpc.DataError ok := errors.As(err, &d) if ok { - return 0, fmt.Errorf("transaction reverted on chain %s: Error %s ErrorData %v", chain.String(), d.Error(), d.ErrorData()) + return 0, fmt.Errorf("transaction reverted: Error %s ErrorData %v", d.Error(), d.ErrorData()) } return 0, err } @@ -184,7 +146,7 @@ func MaybeDataErr(err error) error { var d rpc.DataError ok := errors.As(err, &d) if ok { - return fmt.Errorf("%s: %v", d.Error(), d.ErrorData()) + return d } return err } @@ -255,38 +217,11 @@ func (n Nodes) BootstrapLocators() []string { type Node struct { NodeID string - Name string - CSAKey string - SelToOCRConfig map[chain_selectors.ChainDetails]OCRConfig + SelToOCRConfig map[uint64]OCRConfig PeerID p2pkey.PeerID IsBootstrap bool MultiAddr string AdminAddr string - Labels []*ptypes.Label -} - -func (n Node) OCRConfigForChainDetails(details chain_selectors.ChainDetails) (OCRConfig, bool) { - c, ok := n.SelToOCRConfig[details] - return c, ok -} - -func (n Node) OCRConfigForChainSelector(chainSel uint64) (OCRConfig, bool) { - fam, err := chain_selectors.GetSelectorFamily(chainSel) - if err != nil { - return OCRConfig{}, false - } - - id, err := chain_selectors.GetChainIDFromSelector(chainSel) - if err != nil { - return OCRConfig{}, false - } - - want, err := chain_selectors.GetChainDetailsByChainIDAndFamily(id, fam) - if err != nil { - return OCRConfig{}, false - } - c, ok := n.SelToOCRConfig[want] - return c, ok } func (n Node) FirstOCRKeybundle() OCRConfig { @@ -305,69 +240,50 @@ func MustPeerIDFromString(s string) p2pkey.PeerID { } type NodeChainConfigsLister interface { - ListNodes(ctx context.Context, in *nodev1.ListNodesRequest, opts ...grpc.CallOption) (*nodev1.ListNodesResponse, error) ListNodeChainConfigs(ctx context.Context, in *nodev1.ListNodeChainConfigsRequest, opts ...grpc.CallOption) (*nodev1.ListNodeChainConfigsResponse, error) } // Gathers all the node info through JD required to be able to set -// OCR config for example. nodeIDs can be JD IDs or PeerIDs +// OCR config for example. func NodeInfo(nodeIDs []string, oc NodeChainConfigsLister) (Nodes, error) { - if len(nodeIDs) == 0 { - return nil, nil - } - // if nodeIDs starts with `p2p_` lookup by p2p_id instead - filterByPeerIDs := strings.HasPrefix(nodeIDs[0], "p2p_") - var filter *nodev1.ListNodesRequest_Filter - if filterByPeerIDs { - selector := strings.Join(nodeIDs, ",") - filter = &nodev1.ListNodesRequest_Filter{ - Enabled: 1, - Selectors: []*ptypes.Selector{ - { - Key: "p2p_id", - Op: ptypes.SelectorOp_IN, - Value: &selector, - }, - }, - } - } else { - filter = &nodev1.ListNodesRequest_Filter{ - Enabled: 1, - Ids: nodeIDs, - } - } - nodesFromJD, err := oc.ListNodes(context.Background(), &nodev1.ListNodesRequest{ - Filter: filter, - }) - if err != nil { - return nil, fmt.Errorf("failed to list nodes: %w", err) - } - var nodes []Node - for _, node := range nodesFromJD.GetNodes() { + for _, nodeID := range nodeIDs { // TODO: Filter should accept multiple nodes nodeChainConfigs, err := oc.ListNodeChainConfigs(context.Background(), &nodev1.ListNodeChainConfigsRequest{Filter: &nodev1.ListNodeChainConfigsRequest_Filter{ - NodeIds: []string{node.Id}, + NodeIds: []string{nodeID}, }}) if err != nil { return nil, err } - selToOCRConfig := make(map[chain_selectors.ChainDetails]OCRConfig) + selToOCRConfig := make(map[uint64]OCRConfig) bootstrap := false var peerID p2pkey.PeerID var multiAddr string var adminAddr string for _, chainConfig := range nodeChainConfigs.ChainConfigs { + if chainConfig.Chain.Type == nodev1.ChainType_CHAIN_TYPE_SOLANA { + // Note supported for CCIP yet. + continue + } // NOTE: Assume same peerID/multiAddr for all chains. // Might make sense to change proto as peerID/multiAddr is 1-1 with nodeID? peerID = MustPeerIDFromString(chainConfig.Ocr2Config.P2PKeyBundle.PeerId) multiAddr = chainConfig.Ocr2Config.Multiaddr + adminAddr = chainConfig.AdminAddress if chainConfig.Ocr2Config.IsBootstrap { // NOTE: Assume same peerID for all chains. // Might make sense to change proto as peerID is 1-1 with nodeID? bootstrap = true break } + evmChainID, err := strconv.Atoi(chainConfig.Chain.Id) + if err != nil { + return nil, err + } + sel, err := chain_selectors.SelectorFromChainId(uint64(evmChainID)) + if err != nil { + return nil, err + } b := common.Hex2Bytes(chainConfig.Ocr2Config.OcrKeyBundle.OffchainPublicKey) var opk types2.OffchainPublicKey copy(opk[:], b) @@ -376,59 +292,22 @@ func NodeInfo(nodeIDs []string, oc NodeChainConfigsLister) (Nodes, error) { var cpk types3.ConfigEncryptionPublicKey copy(cpk[:], b) - var pubkey types3.OnchainPublicKey - if chainConfig.Chain.Type == nodev1.ChainType_CHAIN_TYPE_EVM { - // convert from pubkey to address - pubkey = common.HexToAddress(chainConfig.Ocr2Config.OcrKeyBundle.OnchainSigningAddress).Bytes() - } else { - pubkey = common.Hex2Bytes(chainConfig.Ocr2Config.OcrKeyBundle.OnchainSigningAddress) - } - - ocrConfig := OCRConfig{ + selToOCRConfig[sel] = OCRConfig{ OffchainPublicKey: opk, - OnchainPublicKey: pubkey, + OnchainPublicKey: common.HexToAddress(chainConfig.Ocr2Config.OcrKeyBundle.OnchainSigningAddress).Bytes(), PeerID: MustPeerIDFromString(chainConfig.Ocr2Config.P2PKeyBundle.PeerId), TransmitAccount: types2.Account(chainConfig.AccountAddress), ConfigEncryptionPublicKey: cpk, KeyBundleID: chainConfig.Ocr2Config.OcrKeyBundle.BundleId, } - - if chainConfig.Chain.Type == nodev1.ChainType_CHAIN_TYPE_EVM { - // NOTE: Assume same adminAddr for all chains. We always use EVM addr - adminAddr = chainConfig.AdminAddress - } - - var family string - switch chainConfig.Chain.Type { - case nodev1.ChainType_CHAIN_TYPE_EVM: - family = chain_selectors.FamilyEVM - case nodev1.ChainType_CHAIN_TYPE_APTOS: - family = chain_selectors.FamilyAptos - case nodev1.ChainType_CHAIN_TYPE_SOLANA: - family = chain_selectors.FamilySolana - case nodev1.ChainType_CHAIN_TYPE_STARKNET: - family = chain_selectors.FamilyStarknet - default: - return nil, fmt.Errorf("unsupported chain type %s", chainConfig.Chain.Type) - } - - details, err := chain_selectors.GetChainDetailsByChainIDAndFamily(chainConfig.Chain.Id, family) - if err != nil { - return nil, err - } - - selToOCRConfig[details] = ocrConfig } nodes = append(nodes, Node{ - NodeID: node.Id, - Name: node.Name, - CSAKey: node.PublicKey, + NodeID: nodeID, SelToOCRConfig: selToOCRConfig, IsBootstrap: bootstrap, PeerID: peerID, MultiAddr: multiAddr, AdminAddr: adminAddr, - Labels: node.Labels, }) } @@ -436,7 +315,6 @@ func NodeInfo(nodeIDs []string, oc NodeChainConfigsLister) (Nodes, error) { } type CapabilityRegistryConfig struct { - EVMChainID uint64 // chain id of the chain the CR is deployed on - Contract common.Address // address of the CR contract - NetworkType string // network type of the chain + EVMChainID uint64 // chain id of the chain the CR is deployed on + Contract common.Address // address of the CR contract } diff --git a/deployment/environment/clo/don_nodeset.go b/deployment/environment/clo/don_nodeset.go new file mode 100644 index 00000000000..c4cfa212c0b --- /dev/null +++ b/deployment/environment/clo/don_nodeset.go @@ -0,0 +1,67 @@ +package clo + +import ( + "strings" + + "github.com/smartcontractkit/chainlink/deployment/environment/clo/models" +) + +// CapabilityNodeSets groups nodes by a given filter function, resulting in a map of don name to nodes. +func CapabilityNodeSets(nops []*models.NodeOperator, donFilters map[string]FilterFuncT[*models.Node]) map[string][]*models.NodeOperator { + // first drop bootstraps if they exist because they do not serve capabilities + nonBootstrapNops := FilterNopNodes(nops, func(n *models.Node) bool { + for _, chain := range n.ChainConfigs { + if chain.Ocr2Config.IsBootstrap { + return false + } + } + return true + }) + // apply given filters to non-bootstrap nodes + out := make(map[string][]*models.NodeOperator) + for name, f := range donFilters { + out[name] = FilterNopNodes(nonBootstrapNops, f) + } + return out +} + +// FilterNopNodes filters the nodes of each nop by the provided filter function. +// if a nop has no nodes after filtering, it is not included in the output. +func FilterNopNodes(nops []*models.NodeOperator, f FilterFuncT[*models.Node]) []*models.NodeOperator { + var out []*models.NodeOperator + for _, nop := range nops { + var res []*models.Node + for _, n := range nop.Nodes { + node := n + if f(n) { + res = append(res, node) + } + } + if len(res) > 0 { + filterNop := *nop + filterNop.Nodes = res + out = append(out, &filterNop) + } + } + return out +} + +type FilterFuncT[T any] func(n T) bool + +func ProductFilterGenerator(p models.ProductType) FilterFuncT[*models.Node] { + return func(n *models.Node) bool { + for _, prod := range n.SupportedProducts { + if prod == p { + return true + } + } + return false + } +} + +// this could be generalized to a regex filter +func NodeNameFilterGenerator(contains string) FilterFuncT[*models.Node] { + return func(n *models.Node) bool { + return strings.Contains(n.Name, contains) + } +} diff --git a/deployment/environment/clo/don_nodeset_test.go b/deployment/environment/clo/don_nodeset_test.go new file mode 100644 index 00000000000..b576e95835a --- /dev/null +++ b/deployment/environment/clo/don_nodeset_test.go @@ -0,0 +1,104 @@ +package clo_test + +import ( + "encoding/json" + "os" + "path/filepath" + "sort" + "strings" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/test-go/testify/require" + + "github.com/smartcontractkit/chainlink/deployment/environment/clo" + "github.com/smartcontractkit/chainlink/deployment/environment/clo/models" +) + +// this is hacky, but there is no first class concept of a chain writer node in CLO +// in prod, probably better to make an explicit list of pubkeys if we can't add a category or product type +// sufficient for testing +var ( + writerFilter = func(n *models.Node) bool { + return strings.Contains(n.Name, "Prod Keystone Cap One") && !strings.Contains(n.Name, "Boot") + } + + assetFilter = func(n *models.Node) bool { + return strings.Contains(n.Name, "Prod Keystone Asset") && !strings.Contains(n.Name, "Bootstrap") + } + + wfFilter = func(n *models.Node) bool { + return strings.Contains(n.Name, "Prod Keystone One") && !strings.Contains(n.Name, "Boot") + } +) + +func TestGenerateNopNodesData(t *testing.T) { + t.Skipf("this test is for generating test data only") + // use for generating keystone deployment test data + // `./bin/fmscli --config ~/.fmsclient/prod.yaml login` + // `./bin/fmscli --config ~/.fmsclient/prod.yaml get nodeOperators > /tmp/all-clo-nops.json` + + regenerateFromCLO := false + if regenerateFromCLO { + path := "/tmp/all-clo-nops.json" + f, err := os.ReadFile(path) + require.NoError(t, err) + type cloData struct { + Nops []*models.NodeOperator `json:"nodeOperators"` + } + var d cloData + require.NoError(t, json.Unmarshal(f, &d)) + require.NotEmpty(t, d.Nops) + allNops := d.Nops + sort.Slice(allNops, func(i, j int) bool { + return allNops[i].ID < allNops[j].ID + }) + + ksFilter := func(n *models.Node) bool { + return writerFilter(n) || assetFilter(n) || wfFilter(n) + } + ksNops := clo.FilterNopNodes(allNops, ksFilter) + require.NotEmpty(t, ksNops) + b, err := json.MarshalIndent(ksNops, "", " ") + require.NoError(t, err) + require.NoError(t, os.WriteFile("testdata/keystone_nops.json", b, 0644)) // nolint: gosec + } + keystoneNops := loadTestNops(t, "testdata/keystone_nops.json") + + m := clo.CapabilityNodeSets(keystoneNops, map[string]clo.FilterFuncT[*models.Node]{ + "workflow": wfFilter, + "chainWriter": writerFilter, + "asset": assetFilter, + }) + assert.Len(t, m, 3) + assert.Len(t, m["workflow"], 10) + assert.Len(t, m["chainWriter"], 10) + assert.Len(t, m["asset"], 16) + + // can be used to derive the test data for the keystone deployment + updateTestData := true + if updateTestData { + d := "/tmp" // change this to the path where you want to write the test, "../deployment/keystone/testdata" + b, err := json.MarshalIndent(m["workflow"], "", " ") + require.NoError(t, err) + require.NoError(t, os.WriteFile(filepath.Join(d, "workflow_nodes.json"), b, 0600)) + + b, err = json.MarshalIndent(m["chainWriter"], "", " ") + require.NoError(t, err) + require.NoError(t, os.WriteFile(filepath.Join(d, "chain_writer_nodes.json"), b, 0600)) + b, err = json.MarshalIndent(m["asset"], "", " ") + require.NoError(t, err) + require.NoError(t, os.WriteFile(filepath.Join(d, "asset_nodes.json"), b, 0600)) + } +} + +func loadTestNops(t *testing.T, path string) []*models.NodeOperator { + f, err := os.ReadFile(path) + require.NoError(t, err) + var nodes []*models.NodeOperator + require.NoError(t, json.Unmarshal(f, &nodes)) + sort.Slice(nodes, func(i, j int) bool { + return nodes[i].ID < nodes[j].ID + }) + return nodes +} diff --git a/deployment/environment/clo/models/models.go b/deployment/environment/clo/models/models.go new file mode 100644 index 00000000000..1d33cff84d5 --- /dev/null +++ b/deployment/environment/clo/models/models.go @@ -0,0 +1,28 @@ +// TODO: KS-455: Refactor this package to use chainlink-common +// Fork from: https://github.com/smartcontractkit/feeds-manager/tree/develop/api/models +// until it can be refactored in cahinlink-common. + +// Package models provides generated go types that reflect the GraphQL types +// defined in the API schemas. +// +// To maintain compatibility with the default JSON interfaces, any necessary model +// overrides can be defined this package. +package models + +import "go/types" + +// Generic Error model to override existing GQL Error types and allow unmarshaling of GQL Error unions +type Error struct { + Typename string `json:"__typename,omitempty"` + Message string `json:"message,omitempty"` + Path *[]string `json:"path,omitempty"` +} + +func (e *Error) Underlying() types.Type { return e } +func (e *Error) String() string { return "Error" } + +// Unmarshal GQL Time fields into go strings because by default, time.Time results in zero-value +// timestamps being present in the CLI output, e.g. "createdAt": "0001-01-01T00:00:00Z". +// This is because the default JSON interfaces don't recognize it as an empty value for Time.time +// and fail to omit it when using `json:"omitempty"` tags. +type Time string diff --git a/deployment/environment/clo/models/models_gen.go b/deployment/environment/clo/models/models_gen.go new file mode 100644 index 00000000000..baea1dbcbed --- /dev/null +++ b/deployment/environment/clo/models/models_gen.go @@ -0,0 +1,3653 @@ +// Forked from https://github.com/smartcontractkit/feeds-manager/blob/afc24439ee1dffd3781b53c9419ccd1eb44f4163/api/models/models_gen.go#L1 +// TODO: KS-455: Refactor this package to use chainlink-common +// Code generated by github.com/99designs/gqlgen, DO NOT EDIT. + +package models + +import ( + "fmt" + "io" + "strconv" +) + +type AggregatorConfig interface { + IsAggregatorConfig() +} + +type AggregatorSpecConfig interface { + IsAggregatorSpecConfig() +} + +type JobConfig interface { + IsJobConfig() +} + +type Action struct { + Name string `json:"name,omitempty"` + ActionType ActionType `json:"actionType,omitempty"` + Run *ActionRun `json:"run,omitempty"` + Tasks []*Task `json:"tasks,omitempty"` +} + +type ActionRun struct { + ID string `json:"id,omitempty"` + Network *Network `json:"network,omitempty"` + ActionType ActionType `json:"actionType,omitempty"` + Status ActionRunStatus `json:"status,omitempty"` + Tasks []*Task `json:"tasks,omitempty"` + TaskRuns []*TaskRun `json:"taskRuns,omitempty"` + CreatedAt Time `json:"createdAt,omitempty"` +} + +type ActivateBootstrapNodeInput struct { + ID string `json:"id,omitempty"` + ContractType ContractType `json:"contractType,omitempty"` +} + +type ActivateBootstrapNodePayload struct { + Node *Node `json:"node,omitempty"` + Errors []Error `json:"errors,omitempty"` +} + +type AddAggregatorInput struct { + Name string `json:"name,omitempty"` + Template string `json:"template,omitempty"` + CategoryID string `json:"categoryID,omitempty"` +} + +type AddChainInput struct { + NetworkID string `json:"networkID,omitempty"` + Template string `json:"template,omitempty"` + // The Display Name lets a user differentiate multiple CCIP chains on the same network. It is not unique and used for display purposes only. + DisplayName *string `json:"displayName,omitempty"` +} + +type AddChainPayload struct { + Errors []Error `json:"errors,omitempty"` + Chain *CCIPChain `json:"chain,omitempty"` +} + +type AddChainTestContractsInput struct { + ChainID string `json:"chainID,omitempty"` +} + +type AddChainTestContractsPayload struct { + Chain *CCIPChain `json:"chain,omitempty"` + Errors []Error `json:"errors,omitempty"` +} + +type AddFeedAggregatorInput struct { + FeedID string `json:"feedID,omitempty"` + Aggregator *AddAggregatorInput `json:"aggregator,omitempty"` +} + +type AddFeedAggregatorPayload struct { + Aggregator *Aggregator `json:"aggregator,omitempty"` + Errors []Error `json:"errors,omitempty"` +} + +type AddFeedInput struct { + Name string `json:"name,omitempty"` + NetworkID string `json:"networkID,omitempty"` + Proxy *AddProxyInput `json:"proxy,omitempty"` + Aggregator *AddAggregatorInput `json:"aggregator,omitempty"` +} + +type AddFeedPayload struct { + Feed *Feed `json:"feed,omitempty"` + Errors []Error `json:"errors,omitempty"` +} + +type AddLaneInput struct { + ChainAid string `json:"chainAID,omitempty"` + ChainBid string `json:"chainBID,omitempty"` + Template string `json:"template,omitempty"` + // The Display Name lets a user differentiate multiple CCIP chains on the same network. It is not unique and used for display purposes only. + DisplayName *string `json:"displayName,omitempty"` +} + +type AddLanePayload struct { + Errors []Error `json:"errors,omitempty"` + Lane *CCIPLane `json:"lane,omitempty"` +} + +type AddLaneUpgradeInput struct { + LaneID string `json:"laneID,omitempty"` + Template string `json:"template,omitempty"` +} + +type AddLaneUpgradePayload struct { + Lane *CCIPLane `json:"lane,omitempty"` + Errors []Error `json:"errors,omitempty"` +} + +type AddMercuryV03NetworkStackInput struct { + NetworkID string `json:"networkID,omitempty"` + MercuryServerURL string `json:"mercuryServerURL,omitempty"` + MercuryServerPubKey string `json:"mercuryServerPubKey,omitempty"` + ReadAccessController *ReadAccessController `json:"readAccessController,omitempty"` + NativeSurcharge *string `json:"nativeSurcharge,omitempty"` + Servers *string `json:"servers,omitempty"` +} + +type AddMercuryV03NetworkStackPayload struct { + NetworkStack *MercuryV03NetworkStack `json:"networkStack,omitempty"` + Errors []Error `json:"errors,omitempty"` +} + +type AddProxyInput struct { + AccessControllerAddress *string `json:"accessControllerAddress,omitempty"` +} + +type AddStorageContractInput struct { + NetworkID string `json:"networkID,omitempty"` + Template string `json:"template,omitempty"` + DisplayName *string `json:"displayName,omitempty"` +} + +type AddStorageContractPayload struct { + StorageContract *StorageContract `json:"storageContract,omitempty"` + Errors []Error `json:"errors,omitempty"` +} + +type AddTokenInput struct { + Template string `json:"template,omitempty"` +} + +type AddTokenPayload struct { + Token *CCIPToken `json:"token,omitempty"` + Errors []Error `json:"errors,omitempty"` +} + +type AddTokenPoolInput struct { + ID string `json:"id,omitempty"` + Template string `json:"template,omitempty"` +} + +type AddTokenPoolPayload struct { + Errors []Error `json:"errors,omitempty"` + Chain *CCIPChain `json:"chain,omitempty"` +} + +type AddVerificationProviderInput struct { + FeedID string `json:"feedID,omitempty"` + NetworkStackID string `json:"networkStackID,omitempty"` +} + +type AddVerificationProviderPayload struct { + Feed *MercuryV03Feed `json:"feed,omitempty"` + Errors []Error `json:"errors,omitempty"` +} + +type Aggregator struct { + ID string `json:"id,omitempty"` + Name string `json:"name,omitempty"` + ContractAddress *string `json:"contractAddress,omitempty"` + ContractType ContractType `json:"contractType,omitempty"` + DeploymentStatus DeploymentStatus `json:"deploymentStatus,omitempty"` + OwnerAddress *string `json:"ownerAddress,omitempty"` + OwnerAddressType *ContractOwnerType `json:"ownerAddressType,omitempty"` + PendingOwnerAddress *string `json:"pendingOwnerAddress,omitempty"` + PendingOwnerType *ContractOwnerType `json:"pendingOwnerType,omitempty"` + TransferOwnershipStatus TransferOwnershipStatus `json:"transferOwnershipStatus,omitempty"` + Don *Don `json:"don,omitempty"` + BootstrapMultiaddrs []string `json:"bootstrapMultiaddrs,omitempty"` + SpecConfig AggregatorSpecConfig `json:"specConfig,omitempty"` + Config AggregatorConfig `json:"config,omitempty"` + Feed *Feed `json:"feed,omitempty"` + Network *Network `json:"network,omitempty"` + Category *Category `json:"category,omitempty"` + CreatedAt Time `json:"createdAt,omitempty"` +} + +type AggregatorBilling struct { + MaximumGasPrice string `json:"maximumGasPrice,omitempty"` + ReasonableGasPrice string `json:"reasonableGasPrice,omitempty"` + MicroLinkPerEth string `json:"microLinkPerEth,omitempty"` + LinkGweiPerObservation string `json:"linkGweiPerObservation,omitempty"` + LinkGewiPerTransmission string `json:"linkGewiPerTransmission,omitempty"` +} + +type AggregatorConfigOcr1 struct { + Description string `json:"description,omitempty"` + ReasonableGasPrice string `json:"reasonableGasPrice,omitempty"` + MaximumGasPrice string `json:"maximumGasPrice,omitempty"` + MicroLinkPerEth string `json:"microLinkPerEth,omitempty"` + LinkGweiPerObservation string `json:"linkGweiPerObservation,omitempty"` + LinkGweiPerTransmission string `json:"linkGweiPerTransmission,omitempty"` + MinimumAnswer string `json:"minimumAnswer,omitempty"` + MaximumAnswer string `json:"maximumAnswer,omitempty"` + Decimals string `json:"decimals,omitempty"` + DeltaProgress string `json:"deltaProgress,omitempty"` + DeltaResend string `json:"deltaResend,omitempty"` + DeltaRound string `json:"deltaRound,omitempty"` + DeltaGrace string `json:"deltaGrace,omitempty"` + DeltaC string `json:"deltaC,omitempty"` + AlphaPpb string `json:"alphaPPB,omitempty"` + DeltaStage string `json:"deltaStage,omitempty"` + RMax string `json:"rMax,omitempty"` + S []int `json:"s,omitempty"` + F string `json:"f,omitempty"` +} + +func (AggregatorConfigOcr1) IsAggregatorConfig() {} + +type AggregatorConfigOcr2 struct { + MinimumAnswer string `json:"minimumAnswer,omitempty"` + MaximumAnswer string `json:"maximumAnswer,omitempty"` + Description string `json:"description,omitempty"` + Decimals string `json:"decimals,omitempty"` + DeltaGrace string `json:"deltaGrace,omitempty"` + DeltaProgress string `json:"deltaProgress,omitempty"` + DeltaResend string `json:"deltaResend,omitempty"` + DeltaRound string `json:"deltaRound,omitempty"` + DeltaStage string `json:"deltaStage,omitempty"` + F string `json:"f,omitempty"` + MaxDurationObservation string `json:"maxDurationObservation,omitempty"` + MaxDurationQuery string `json:"maxDurationQuery,omitempty"` + MaxDurationReport string `json:"maxDurationReport,omitempty"` + MaxDurationShouldAcceptFinalizedReport string `json:"maxDurationShouldAcceptFinalizedReport,omitempty"` + MaxDurationShouldTransmitAcceptedReport string `json:"maxDurationShouldTransmitAcceptedReport,omitempty"` + RMax string `json:"rMax,omitempty"` + S []int `json:"s,omitempty"` + AlphaAcceptInfinite bool `json:"alphaAcceptInfinite,omitempty"` + AlphaAcceptPpb string `json:"alphaAcceptPPB,omitempty"` + AlphaReportInfinite bool `json:"alphaReportInfinite,omitempty"` + AlphaReportPpb string `json:"alphaReportPPB,omitempty"` + DeltaC string `json:"deltaC,omitempty"` + ObservationPaymentGjuels string `json:"observationPaymentGjuels,omitempty"` + TransmissionPaymentGjuels string `json:"transmissionPaymentGjuels,omitempty"` + MaximumGasPriceGwei *string `json:"maximumGasPriceGwei,omitempty"` + ReasonableGasPriceGwei *string `json:"reasonableGasPriceGwei,omitempty"` + AccountingGas *string `json:"accountingGas,omitempty"` +} + +func (AggregatorConfigOcr2) IsAggregatorConfig() {} + +type AggregatorOnChainConfig struct { + ConfigCount string `json:"configCount,omitempty"` + BlockNumber string `json:"blockNumber,omitempty"` + ConfigDigest []string `json:"configDigest,omitempty"` +} + +type AggregatorOnChainState struct { + Billing *AggregatorBilling `json:"billing,omitempty"` + Config *AggregatorOnChainConfig `json:"config,omitempty"` + OwnerAddress string `json:"ownerAddress,omitempty"` +} + +type AggregatorProxy struct { + ID string `json:"id,omitempty"` + ContractAddress *string `json:"contractAddress,omitempty"` + TransferOwnershipStatus TransferOwnershipStatus `json:"transferOwnershipStatus,omitempty"` + OwnerAddress *string `json:"ownerAddress,omitempty"` + OwnerAddressType *ContractOwnerType `json:"ownerAddressType,omitempty"` + PendingOwnerAddress *string `json:"pendingOwnerAddress,omitempty"` + PendingOwnerType *ContractOwnerType `json:"pendingOwnerType,omitempty"` + Aggregator *Aggregator `json:"aggregator,omitempty"` + AccessControllerAddress *string `json:"accessControllerAddress,omitempty"` + Feed *Feed `json:"feed,omitempty"` + Network *Network `json:"network,omitempty"` + CreatedAt Time `json:"createdAt,omitempty"` +} + +type ArchiveChainPayload struct { + Chain *CCIPChain `json:"chain,omitempty"` + Errors []Error `json:"errors,omitempty"` +} + +type ArchiveContractInput struct { + ChainID string `json:"chainID,omitempty"` + ContractID string `json:"contractID,omitempty"` +} + +type ArchiveContractPayload struct { + Contract *Contract `json:"contract,omitempty"` + Errors []Error `json:"errors,omitempty"` +} + +type ArchiveFeedPayload struct { + Feed *MercuryV03Feed `json:"feed,omitempty"` + Errors []Error `json:"errors,omitempty"` +} + +type ArchiveLanePayload struct { + Lane *CCIPLane `json:"lane,omitempty"` + Errors []Error `json:"errors,omitempty"` +} + +type ArchiveNetworkInput struct { + ID string `json:"id,omitempty"` +} + +type ArchiveNetworkPayload struct { + Network *Network `json:"network,omitempty"` + Errors []Error `json:"errors,omitempty"` +} + +type ArchiveNetworkStackPayload struct { + NetworkStack *MercuryV03NetworkStack `json:"networkStack,omitempty"` + Errors []Error `json:"errors,omitempty"` +} + +type AssignNodeToJobInput struct { + JobID string `json:"jobID,omitempty"` + NodeID string `json:"nodeID,omitempty"` +} + +type AssignNodeToJobPayload struct { + Job *Job `json:"job,omitempty"` + Errors []Error `json:"errors,omitempty"` +} + +type BuildInfo struct { + Version string `json:"version,omitempty"` +} + +type CCIPChain struct { + ID string `json:"id,omitempty"` + Network *Network `json:"network,omitempty"` + Contracts []*Contract `json:"contracts,omitempty"` + WorkflowRuns []*WorkflowRun `json:"workflowRuns,omitempty"` + SupportedTokens []*EVMBridgedToken `json:"supportedTokens,omitempty"` + FeeTokens []string `json:"feeTokens,omitempty"` + WrappedNativeToken string `json:"wrappedNativeToken,omitempty"` + ArchivedAt *Time `json:"archivedAt,omitempty"` + // The Display Name lets a user differentiate multiple CCIP chains on the same network. It is not unique and used for display purposes only. + DisplayName *string `json:"displayName,omitempty"` + DeployedTemplate map[string]interface{} `json:"deployedTemplate,omitempty"` + Labels map[string]interface{} `json:"labels,omitempty"` +} + +type CCIPChainBasic struct { + ID string `json:"id,omitempty"` + ChainID string `json:"chainID,omitempty"` + Contracts []*ContractBasic `json:"contracts,omitempty"` +} + +type CCIPChainFilter struct { + IsArchived *bool `json:"isArchived,omitempty"` + Selectors []*CCIPChainSelector `json:"selectors,omitempty"` +} + +type CCIPChainSelector struct { + Key string `json:"key,omitempty"` + Op SelectorOp `json:"op,omitempty"` + Value *string `json:"value,omitempty"` +} + +type CCIPEndpoint struct { + Chain *CCIPChain `json:"chain,omitempty"` + Contracts []*Contract `json:"contracts,omitempty"` +} + +type CCIPEndpointBasic struct { + Chain *CCIPChainBasic `json:"chain,omitempty"` + Contracts []*ContractBasic `json:"contracts,omitempty"` +} + +type CCIPLane struct { + ID string `json:"id,omitempty"` + ChainA *CCIPChain `json:"chainA,omitempty"` + ChainB *CCIPChain `json:"chainB,omitempty"` + LegA *CCIPLaneLeg `json:"legA,omitempty"` + LegB *CCIPLaneLeg `json:"legB,omitempty"` + LegAProvisional *CCIPLaneLeg `json:"legAProvisional,omitempty"` + LegBProvisional *CCIPLaneLeg `json:"legBProvisional,omitempty"` + Dons []*Don `json:"dons,omitempty"` + WorkflowRuns []*WorkflowRun `json:"workflowRuns,omitempty"` + Status CCIPLaneLegStatus `json:"status,omitempty"` + ArchivedAt *Time `json:"archivedAt,omitempty"` + DisplayName *string `json:"displayName,omitempty"` + DeployedTemplate map[string]interface{} `json:"deployedTemplate,omitempty"` + DeployedProvisionalTemplate map[string]interface{} `json:"deployedProvisionalTemplate,omitempty"` +} + +type CCIPLaneChainUpdateInput struct { + ID string `json:"id,omitempty"` +} + +type CCIPLaneLeg struct { + ID string `json:"id,omitempty"` + Tag CCIPLaneLegTag `json:"tag,omitempty"` + Source *CCIPEndpoint `json:"source,omitempty"` + Destination *CCIPEndpoint `json:"destination,omitempty"` + WorkflowRuns []*WorkflowRun `json:"workflowRuns,omitempty"` + Dons []*Don `json:"dons,omitempty"` + Status CCIPLaneLegStatus `json:"status,omitempty"` + ArchivedAt *Time `json:"archivedAt,omitempty"` + SupportedTokens []string `json:"supportedTokens,omitempty"` +} + +type CCIPLaneLegBasic struct { + ID string `json:"id,omitempty"` + Source *CCIPEndpointBasic `json:"source,omitempty"` + Destination *CCIPEndpointBasic `json:"destination,omitempty"` + Dons []*DONBasic `json:"dons,omitempty"` + Status CCIPLaneLegStatus `json:"status,omitempty"` + SupportedTokens []string `json:"supportedTokens,omitempty"` +} + +type CCIPLaneLegsFilter struct { + ContractAddress string `json:"contractAddress,omitempty"` + NetworkNameKey string `json:"networkNameKey,omitempty"` +} + +type CCIPLanesFilter struct { + IsArchived *bool `json:"isArchived,omitempty"` +} + +type CCIPMutations struct { + AddChain *AddChainPayload `json:"addChain,omitempty"` + ImportChain *ImportChainPayload `json:"importChain,omitempty"` + AddChainTestContracts *AddChainTestContractsPayload `json:"addChainTestContracts,omitempty"` + AddTokenPool *AddTokenPoolPayload `json:"addTokenPool,omitempty"` + ImportTokenPool *ImportTokenPoolPayload `json:"importTokenPool,omitempty"` + AddToken *AddTokenPayload `json:"addToken,omitempty"` + DeployContract *DeployContractPayload `json:"deployContract,omitempty"` + DeleteContract *DeleteContractPayload `json:"deleteContract,omitempty"` + ArchiveContract *ArchiveContractPayload `json:"archiveContract,omitempty"` + // Deploys the contracts for a chain + DeployChain *CcipDeployChainPayload `json:"deployChain,omitempty"` + DeployChainTestContracts *CcipDeployChainTestContractsPayload `json:"deployChainTestContracts,omitempty"` + DeployToken *DeployTokenPayload `json:"deployToken,omitempty"` + DeregisterTestToken *DeregisterTestTokenPayload `json:"deregisterTestToken,omitempty"` + AddLane *AddLanePayload `json:"addLane,omitempty"` + ImportLane *ImportLanePayload `json:"importLane,omitempty"` + AddLaneUpgrade *AddLaneUpgradePayload `json:"addLaneUpgrade,omitempty"` + UpdateLane *UpdateLanePayload `json:"updateLane,omitempty"` + ArchiveLane *ArchiveLanePayload `json:"archiveLane,omitempty"` + ArchiveChain *ArchiveChainPayload `json:"archiveChain,omitempty"` + CancelLaneUpgrade *CancelLaneUpgradePayload `json:"cancelLaneUpgrade,omitempty"` + ConfirmLaneUpgrade *ConfirmLaneUpgradePayload `json:"confirmLaneUpgrade,omitempty"` + DeployLaneLeg *CcipDeployLaneLegPayload `json:"deployLaneLeg,omitempty"` + SetAllowListTokenPool *SetAllowListTokenPoolPayload `json:"setAllowListTokenPool,omitempty"` + // SetConfigLaneLeg sets the on chain configuration for the Commit Store and Off Ramp contracts of the lane leg. + // + // The configuration values passed as arguments to the contract call are provided by the most recently inserted + // RDD template. + SetConfigLaneLeg *CcipSetConfigLaneLegPayload `json:"setConfigLaneLeg,omitempty"` + TransferOwnership *TransferOwnershipPayload `json:"transferOwnership,omitempty"` + TransferAdminRole *TransferAdminRolePayload `json:"transferAdminRole,omitempty"` + UpdateChain *UpdateCCIPChainPayload `json:"updateChain,omitempty"` + RemoveLiquidity *RemoveLiquidityPayload `json:"removeLiquidity,omitempty"` + SyncChain *SyncChainPayload `json:"syncChain,omitempty"` + SyncLane *SyncLanePayload `json:"syncLane,omitempty"` + SyncContracts *SyncContractsPayload `json:"syncContracts,omitempty"` +} + +type CCIPQueries struct { + Chains []*CCIPChain `json:"chains,omitempty"` + Lanes []*CCIPLane `json:"lanes,omitempty"` + LaneLegs []*CCIPLaneLegBasic `json:"laneLegs,omitempty"` + Chain *CCIPChain `json:"chain,omitempty"` + Lane *CCIPLane `json:"lane,omitempty"` + Tokens []*CCIPToken `json:"tokens,omitempty"` + Token *CCIPToken `json:"token,omitempty"` +} + +type CCIPToken struct { + ID string `json:"id,omitempty"` + Symbol string `json:"symbol,omitempty"` + TokenPools []*CCIPTokenPool `json:"tokenPools,omitempty"` +} + +type CCIPTokenPool struct { + ID string `json:"id,omitempty"` + Contract *Contract `json:"contract,omitempty"` + Address *string `json:"address,omitempty"` + TokenAddress string `json:"tokenAddress,omitempty"` + TokenSymbol string `json:"tokenSymbol,omitempty"` + Chain *CCIPChain `json:"chain,omitempty"` + WorkflowRuns []*WorkflowRun `json:"workflowRuns,omitempty"` +} + +type CcipDeployChainInput struct { + ChainID string `json:"chainID,omitempty"` +} + +type CcipDeployChainPayload struct { + WorkflowRun *WorkflowRun `json:"workflowRun,omitempty"` + Errors []Error `json:"errors,omitempty"` +} + +type CcipDeployChainTestContractsInput struct { + ChainID string `json:"chainID,omitempty"` +} + +type CcipDeployChainTestContractsPayload struct { + WorkflowRun *WorkflowRun `json:"workflowRun,omitempty"` + Errors []Error `json:"errors,omitempty"` +} + +type CcipDeployLaneLegInput struct { + LegID string `json:"legID,omitempty"` +} + +type CcipDeployLaneLegPayload struct { + WorkflowRun *WorkflowRun `json:"workflowRun,omitempty"` + Errors []Error `json:"errors,omitempty"` +} + +type CcipSetConfigLaneLegInput struct { + LegID string `json:"legID,omitempty"` +} + +type CcipSetConfigLaneLegPayload struct { + WorkflowRun *WorkflowRun `json:"workflowRun,omitempty"` + Errors []Error `json:"errors,omitempty"` +} + +type CSAKeypair struct { + ID string `json:"id,omitempty"` + PublicKey string `json:"publicKey,omitempty"` + CreatedAt Time `json:"createdAt,omitempty"` +} + +type CancelLaneUpgradeInput struct { + LaneID string `json:"laneID,omitempty"` +} + +type CancelLaneUpgradePayload struct { + Errors []Error `json:"errors,omitempty"` + Lane *CCIPLane `json:"lane,omitempty"` +} + +type Category struct { + ID string `json:"id,omitempty"` + Name string `json:"name,omitempty"` + Color string `json:"color,omitempty"` + CreatedAt Time `json:"createdAt,omitempty"` +} + +type ConfirmLaneUpgradeInput struct { + LaneID string `json:"laneID,omitempty"` +} + +type ConfirmLaneUpgradePayload struct { + Errors []Error `json:"errors,omitempty"` + Lane *CCIPLane `json:"lane,omitempty"` +} + +type Contract struct { + ID string `json:"id,omitempty"` + Network *Network `json:"network,omitempty"` + Name string `json:"name,omitempty"` + Version int `json:"version,omitempty"` + Semver *string `json:"semver,omitempty"` + Tag ContractTag `json:"tag,omitempty"` + Address *string `json:"address,omitempty"` + Metadata map[string]interface{} `json:"metadata,omitempty"` + OwnerAddress *string `json:"ownerAddress,omitempty"` + OwnerType ContractOwnerType `json:"ownerType,omitempty"` + PendingOwnerAddress *string `json:"pendingOwnerAddress,omitempty"` + PendingOwnerType *ContractOwnerType `json:"pendingOwnerType,omitempty"` + TransferOwnershipStatus TransferOwnershipStatus `json:"transferOwnershipStatus,omitempty"` + VerificationStatus VerificationStatus `json:"verificationStatus,omitempty"` + SourceCodeHash string `json:"sourceCodeHash,omitempty"` + DeployedAt *Time `json:"deployedAt,omitempty"` + Imported bool `json:"imported,omitempty"` + ArchivedAt *Time `json:"archivedAt,omitempty"` +} + +type ContractBasic struct { + ID string `json:"id,omitempty"` + Name string `json:"name,omitempty"` + Version int `json:"version,omitempty"` + Semver *string `json:"semver,omitempty"` + Address *string `json:"address,omitempty"` + Metadata map[string]interface{} `json:"metadata,omitempty"` +} + +type CreateBootstrapJobInput struct { + DonID string `json:"donID,omitempty"` + NodeID string `json:"nodeID,omitempty"` +} + +type CreateBootstrapJobPayload struct { + Job *Job `json:"job,omitempty"` + Errors []Error `json:"errors,omitempty"` +} + +type CreateCSAKeypairPayload struct { + CsaKeypair *CSAKeypair `json:"csaKeypair,omitempty"` + Errors []Error `json:"errors,omitempty"` +} + +type CreateCategoryInput struct { + Name string `json:"name,omitempty"` + Color *string `json:"color,omitempty"` +} + +type CreateCategoryPayload struct { + Category *Category `json:"category,omitempty"` + Errors []Error `json:"errors,omitempty"` +} + +type CreateJobInput struct { + Type JobType `json:"type,omitempty"` + Ocr2PluginType *OCR2PluginType `json:"ocr2PluginType,omitempty"` + Config *JobConfigInput `json:"config,omitempty"` + DonID string `json:"donID,omitempty"` + NodeOperatorID string `json:"nodeOperatorID,omitempty"` +} + +type CreateJobPayload struct { + Job *Job `json:"job,omitempty"` + Errors []Error `json:"errors,omitempty"` +} + +type CreateMercuryNetworkStackInput struct { + NetworkID string `json:"networkID,omitempty"` + VerifierAddress string `json:"verifierAddress,omitempty"` + VerifierProxyAddress string `json:"verifierProxyAddress,omitempty"` + ServerURL string `json:"serverURL,omitempty"` + ServerPublicKey string `json:"serverPublicKey,omitempty"` + Servers *string `json:"servers,omitempty"` +} + +type CreateMercuryNetworkStackPayload struct { + NetworkStack *MercuryNetworkStack `json:"networkStack,omitempty"` + Errors []Error `json:"errors,omitempty"` +} + +type CreateNetworkInput struct { + ChainID string `json:"chainID,omitempty"` + ChainType ChainType `json:"chainType,omitempty"` + Name string `json:"name,omitempty"` + NativeToken string `json:"nativeToken,omitempty"` + NativeTokenContractAddress *string `json:"nativeTokenContractAddress,omitempty"` + ConfigContractAddress *string `json:"configContractAddress,omitempty"` + LinkUSDProxyAddress *string `json:"linkUSDProxyAddress,omitempty"` + NativeUSDProxyAddress *string `json:"nativeUSDProxyAddress,omitempty"` + LinkContractAddress *string `json:"linkContractAddress,omitempty"` + FlagsContractAddress *string `json:"flagsContractAddress,omitempty"` + LinkFunding *string `json:"linkFunding,omitempty"` + BillingAdminAccessControllerAddress *string `json:"billingAdminAccessControllerAddress,omitempty"` + RequesterAdminAccessControllerAddress *string `json:"requesterAdminAccessControllerAddress,omitempty"` + ExplorerAPIKey *string `json:"explorerAPIKey,omitempty"` + ExplorerAPIURL *string `json:"explorerAPIURL,omitempty"` +} + +type CreateNetworkPayload struct { + Network *Network `json:"network,omitempty"` + Errors []Error `json:"errors,omitempty"` +} + +type CreateNodeInput struct { + Name string `json:"name,omitempty"` + PublicKey string `json:"publicKey,omitempty"` + NodeOperatorID string `json:"nodeOperatorID,omitempty"` + SupportedCategoryIDs []string `json:"supportedCategoryIDs,omitempty"` + SupportedProducts []ProductType `json:"supportedProducts,omitempty"` +} + +type CreateNodeOperatorInput struct { + Keys []string `json:"keys,omitempty"` + Name string `json:"name,omitempty"` + Email *string `json:"email,omitempty"` + Website *string `json:"website,omitempty"` +} + +type CreateNodeOperatorPayload struct { + NodeOperator *NodeOperator `json:"nodeOperator,omitempty"` + Errors []Error `json:"errors,omitempty"` +} + +type CreateNodePayload struct { + Node *Node `json:"node,omitempty"` + Errors []Error `json:"errors,omitempty"` +} + +type CreateRelayerAccountInput struct { + RelayerID string `json:"relayerID,omitempty"` +} + +type CreateRelayerAccountPayload struct { + RelayerAccount *RelayerAccount `json:"relayerAccount,omitempty"` + Errors []Error `json:"errors,omitempty"` +} + +type CreateRelayerInput struct { + Name string `json:"name,omitempty"` + NetworkID string `json:"networkID,omitempty"` + Config string `json:"config,omitempty"` + URL *RelayerURL `json:"url,omitempty"` +} + +type CreateRelayerPayload struct { + Relayer *Relayer `json:"relayer,omitempty"` + Errors []Error `json:"errors,omitempty"` +} + +type CreateUserInput struct { + Email string `json:"email,omitempty"` + Name string `json:"name,omitempty"` + Password string `json:"password,omitempty"` + Role UserRole `json:"role,omitempty"` +} + +type CreateUserPayload struct { + User *User `json:"user,omitempty"` + Errors []Error `json:"errors,omitempty"` +} + +type CreateVaultInput struct { + Name string `json:"name,omitempty"` + Address string `json:"address,omitempty"` + VaultType VaultType `json:"vaultType,omitempty"` + SupportedProducts []ProductType `json:"supportedProducts,omitempty"` + NetworkID string `json:"networkID,omitempty"` +} + +type CreateVaultPayload struct { + Vault *Vault `json:"vault,omitempty"` + Errors []Error `json:"errors,omitempty"` +} + +type CreateWebhookInput struct { + Name string `json:"name,omitempty"` + EndpointURL string `json:"endpointURL,omitempty"` +} + +type CreateWebhookPayload struct { + Webhook *Webhook `json:"webhook,omitempty"` + Errors []Error `json:"errors,omitempty"` +} + +type Don struct { + ID string `json:"id,omitempty"` + Network *Network `json:"network,omitempty"` + ExecutionType DONExecutionType `json:"executionType,omitempty"` + Jobs []*Job `json:"jobs,omitempty"` +} + +type DONBasic struct { + ID string `json:"id,omitempty"` + ExecutionType DONExecutionType `json:"executionType,omitempty"` + Jobs []*JobBasic `json:"jobs,omitempty"` +} + +type DeactivateBootstrapNodeInput struct { + ID string `json:"id,omitempty"` + ContractType ContractType `json:"contractType,omitempty"` +} + +type DeactivateBootstrapNodePayload struct { + Node *Node `json:"node,omitempty"` + Errors []Error `json:"errors,omitempty"` +} + +type DeleteContractInput struct { + ChainID string `json:"chainID,omitempty"` + ContractID string `json:"contractID,omitempty"` +} + +type DeleteContractPayload struct { + Errors []Error `json:"errors,omitempty"` +} + +type DeleteFeedInput struct { + ID string `json:"id,omitempty"` +} + +type DeleteFeedPayload struct { + Feed *Feed `json:"feed,omitempty"` + Errors []Error `json:"errors,omitempty"` +} + +type DeleteJobInput struct { + ID string `json:"id,omitempty"` +} + +type DeleteJobPayload struct { + Job *Job `json:"job,omitempty"` + Errors []Error `json:"errors,omitempty"` +} + +type DeleteNodeInput struct { + ID string `json:"id,omitempty"` +} + +type DeleteNodePayload struct { + Node *Node `json:"node,omitempty"` + Errors []Error `json:"errors,omitempty"` +} + +type DeleteVaultInput struct { + ID string `json:"id,omitempty"` +} + +type DeleteVaultPayload struct { + Vault *Vault `json:"vault,omitempty"` + Errors []Error `json:"errors,omitempty"` +} + +type DeleteWebhookInput struct { + ID string `json:"id,omitempty"` +} + +type DeleteWebhookPayload struct { + Webhook *Webhook `json:"webhook,omitempty"` + Errors []Error `json:"errors,omitempty"` +} + +type DeleteWorkflowRunInput struct { + WorkflowRunID string `json:"workflowRunID,omitempty"` +} + +type DeleteWorkflowRunPayload struct { + WorkflowRun *WorkflowRun `json:"workflowRun,omitempty"` + Errors []Error `json:"errors,omitempty"` +} + +type DeployContractInput struct { + ChainID string `json:"chainID,omitempty"` + ContractID string `json:"contractID,omitempty"` +} + +type DeployContractPayload struct { + Errors []Error `json:"errors,omitempty"` + WorkflowRun *WorkflowRun `json:"workflowRun,omitempty"` +} + +type DeployMercuryV03NetworkStackInput struct { + NetworkStackID string `json:"networkStackID,omitempty"` +} + +type DeployMercuryV03NetworkStackPayload struct { + WorkflowRun *WorkflowRun `json:"workflowRun,omitempty"` + Errors []Error `json:"errors,omitempty"` +} + +type DeploySetStorageContractInput struct { + StorageID string `json:"storageID,omitempty"` +} + +type DeploySetStorageContractPayload struct { + WorkflowRun *WorkflowRun `json:"workflowRun,omitempty"` + Errors []Error `json:"errors,omitempty"` +} + +type DeployTokenInput struct { + Symbol string `json:"symbol,omitempty"` +} + +type DeployTokenPayload struct { + WorkflowRunsAndContracts []*WorkflowRunAndContract `json:"workflowRunsAndContracts,omitempty"` + Errors []Error `json:"errors,omitempty"` +} + +type DeregisterTestTokenInput struct { + LaneLegID string `json:"laneLegID,omitempty"` +} + +type DeregisterTestTokenPayload struct { + WorkflowRun *WorkflowRun `json:"workflowRun,omitempty"` + Errors []Error `json:"errors,omitempty"` +} + +type DisableNodeInput struct { + ID string `json:"id,omitempty"` +} + +type DisableNodePayload struct { + Node *Node `json:"node,omitempty"` + Errors []Error `json:"errors,omitempty"` +} + +type DisableRelayerInput struct { + ID string `json:"id,omitempty"` +} + +type DisableRelayerPayload struct { + Relayer *Relayer `json:"relayer,omitempty"` + Errors []Error `json:"errors,omitempty"` +} + +type DisableUserInput struct { + ID string `json:"id,omitempty"` +} + +type DisableUserPayload struct { + User *User `json:"user,omitempty"` + Errors []Error `json:"errors,omitempty"` +} + +type EVMBridgedToken struct { + Token string `json:"token,omitempty"` + Address string `json:"address,omitempty"` + TokenPoolType TokenPoolType `json:"tokenPoolType,omitempty"` + PriceType TokenPriceType `json:"priceType,omitempty"` + Price *string `json:"price,omitempty"` + PriceFeed *PriceFeed `json:"priceFeed,omitempty"` +} + +type EnableNodeInput struct { + ID string `json:"id,omitempty"` +} + +type EnableNodePayload struct { + Node *Node `json:"node,omitempty"` + Errors []Error `json:"errors,omitempty"` +} + +type EnableRelayerInput struct { + ID string `json:"id,omitempty"` +} + +type EnableRelayerPayload struct { + Relayer *Relayer `json:"relayer,omitempty"` + Errors []Error `json:"errors,omitempty"` +} + +type Feed struct { + ID string `json:"id,omitempty"` + Name string `json:"name,omitempty"` + Status FeedStatus `json:"status,omitempty"` + Network *Network `json:"network,omitempty"` + Proxy *AggregatorProxy `json:"proxy,omitempty"` + Aggregators []*Aggregator `json:"aggregators,omitempty"` + WorkflowRuns []*WorkflowRun `json:"workflowRuns,omitempty"` + CreatedAt Time `json:"createdAt,omitempty"` +} + +type FeedsFilters struct { + ChainID *string `json:"chainID,omitempty"` + ChainType *ChainType `json:"chainType,omitempty"` + Name *string `json:"name,omitempty"` + NetworkID *string `json:"networkID,omitempty"` + ProxyAddress *string `json:"proxyAddress,omitempty"` + Limit *string `json:"limit,omitempty"` + Offset *string `json:"offset,omitempty"` +} + +type FeedsInput struct { + Filter *FeedsFilters `json:"filter,omitempty"` +} + +type GauntletReport struct { + ID string `json:"id,omitempty"` + TraceID string `json:"traceID,omitempty"` + WorkflowRun *WorkflowRun `json:"workflowRun,omitempty"` + TransactionHash *string `json:"transactionHash,omitempty"` + ReportID string `json:"reportID,omitempty"` + Timestamp Time `json:"timestamp,omitempty"` + Op string `json:"op,omitempty"` + Input string `json:"input,omitempty"` + Output *string `json:"output,omitempty"` + Requirements *string `json:"requirements,omitempty"` + Config string `json:"config,omitempty"` + Subops *string `json:"subops,omitempty"` + Events *string `json:"events,omitempty"` + Snapshot *string `json:"snapshot,omitempty"` + Error *string `json:"error,omitempty"` + TraceExtra *string `json:"traceExtra,omitempty"` +} + +type GauntletReportsInput struct { + TraceID *string `json:"traceID,omitempty"` + WorkflowRunID *int `json:"workflowRunID,omitempty"` + TransactionHash *string `json:"transactionHash,omitempty"` +} + +type ImportAggregatorInput struct { + Name string `json:"name,omitempty"` + ContractAddress string `json:"contractAddress,omitempty"` + Template string `json:"template,omitempty"` + CategoryID string `json:"categoryID,omitempty"` +} + +type ImportChainInput struct { + NetworkID string `json:"networkID,omitempty"` + Template string `json:"template,omitempty"` + // The Display Name lets a user differentiate multiple CCIP chains on the same network. It is not unique and used for display purposes only. + DisplayName *string `json:"displayName,omitempty"` +} + +type ImportChainPayload struct { + Errors []Error `json:"errors,omitempty"` + Chain *CCIPChain `json:"chain,omitempty"` +} + +type ImportFeedAggregatorInput struct { + FeedID string `json:"feedID,omitempty"` + Aggregator *ImportAggregatorInput `json:"aggregator,omitempty"` +} + +type ImportFeedAggregatorPayload struct { + Aggregator *Aggregator `json:"aggregator,omitempty"` + Errors []Error `json:"errors,omitempty"` +} + +type ImportFeedInput struct { + Name string `json:"name,omitempty"` + NetworkID string `json:"networkID,omitempty"` + Proxy *ImportProxyInput `json:"proxy,omitempty"` + Aggregators []*ImportAggregatorInput `json:"aggregators,omitempty"` +} + +type ImportFeedPayload struct { + Feed *Feed `json:"feed,omitempty"` + Errors []Error `json:"errors,omitempty"` +} + +type ImportKeystoneWorkflowInput struct { + CategoryID string `json:"categoryID,omitempty"` + NetworkID string `json:"networkID,omitempty"` + Template string `json:"template,omitempty"` +} + +type ImportKeystoneWorkflowPayload struct { + Workflow *KeystoneWorkflow `json:"workflow,omitempty"` + Errors []Error `json:"errors,omitempty"` +} + +type ImportLaneInput struct { + ChainAid string `json:"chainAID,omitempty"` + ChainBid string `json:"chainBID,omitempty"` + Template string `json:"template,omitempty"` + // The Display Name lets a user differentiate multiple CCIP chains on the same network. It is not unique and used for display purposes only. + DisplayName *string `json:"displayName,omitempty"` +} + +type ImportLanePayload struct { + Errors []Error `json:"errors,omitempty"` + Lane *CCIPLane `json:"lane,omitempty"` +} + +type ImportMercuryFeedInput struct { + Name string `json:"name,omitempty"` + ExternalFeedID string `json:"externalFeedID,omitempty"` + NetworkStackID string `json:"networkStackID,omitempty"` + FromBlock string `json:"fromBlock,omitempty"` + Template string `json:"template,omitempty"` +} + +type ImportMercuryFeedPayload struct { + Feed *MercuryFeed `json:"feed,omitempty"` + Errors []Error `json:"errors,omitempty"` +} + +type ImportMercuryV03FeedInput struct { + Name string `json:"name,omitempty"` + ExternalFeedID string `json:"externalFeedID,omitempty"` + Template string `json:"template,omitempty"` + CategoryID string `json:"categoryID,omitempty"` +} + +type ImportMercuryV03FeedPayload struct { + Feed *MercuryV03Feed `json:"feed,omitempty"` + Errors []Error `json:"errors,omitempty"` +} + +type ImportMercuryV03NetworkStackInput struct { + NetworkID string `json:"networkID,omitempty"` + VerifierAddress string `json:"verifierAddress,omitempty"` + VerifierProxyAddress string `json:"verifierProxyAddress,omitempty"` + RewardBankAddress string `json:"rewardBankAddress,omitempty"` + FeeManagerAddress string `json:"feeManagerAddress,omitempty"` + MercuryServerURL string `json:"mercuryServerURL,omitempty"` + MercuryServerPubKey string `json:"mercuryServerPubKey,omitempty"` + Servers *string `json:"servers,omitempty"` +} + +type ImportMercuryV03NetworkStackPayload struct { + NetworkStack *MercuryV03NetworkStack `json:"networkStack,omitempty"` + Errors []Error `json:"errors,omitempty"` +} + +type ImportOCR3CapabilityInput struct { + CategoryID string `json:"categoryID,omitempty"` + NetworkID string `json:"networkID,omitempty"` + Template string `json:"template,omitempty"` +} + +type ImportOCR3CapabilityPayload struct { + Ocr3Capability *OCR3Capability `json:"ocr3Capability,omitempty"` + Errors []Error `json:"errors,omitempty"` +} + +type ImportProxyInput struct { + ContractAddress string `json:"contractAddress,omitempty"` + AccessControllerAddress *string `json:"accessControllerAddress,omitempty"` + AggregatorAddress string `json:"aggregatorAddress,omitempty"` +} + +type ImportTokenPoolInput struct { + ID string `json:"id,omitempty"` + Template string `json:"template,omitempty"` +} + +type ImportTokenPoolPayload struct { + Errors []Error `json:"errors,omitempty"` + Chain *CCIPChain `json:"chain,omitempty"` +} + +type Job struct { + ID string `json:"id,omitempty"` + UUID string `json:"uuid,omitempty"` + Type JobType `json:"type,omitempty"` + Ocr2PluginType *OCR2PluginType `json:"ocr2PluginType,omitempty"` + Status JobStatus `json:"status,omitempty"` + NodeOperator *NodeOperator `json:"nodeOperator,omitempty"` + Node *Node `json:"node,omitempty"` + IsBootstrap bool `json:"isBootstrap,omitempty"` + Config JobConfig `json:"config,omitempty"` + Spec *string `json:"spec,omitempty"` + ProposalChanged bool `json:"proposalChanged,omitempty"` + AssignableNodes []*Node `json:"assignableNodes,omitempty"` + CanPropose bool `json:"canPropose,omitempty"` + CanRevoke bool `json:"canRevoke,omitempty"` + Proposals []*JobProposal `json:"proposals,omitempty"` + CreatedAt Time `json:"createdAt,omitempty"` +} + +type JobBasic struct { + ID string `json:"id,omitempty"` + UUID string `json:"uuid,omitempty"` + Type JobType `json:"type,omitempty"` + Ocr2PluginType *OCR2PluginType `json:"ocr2PluginType,omitempty"` + Status JobStatus `json:"status,omitempty"` + IsBootstrap bool `json:"isBootstrap,omitempty"` +} + +type JobConfigEmpty struct { + Empty bool `json:"_empty,omitempty"` +} + +func (JobConfigEmpty) IsJobConfig() {} + +type JobConfigEmptyInput struct { + Empty *bool `json:"_empty,omitempty"` +} + +type JobConfigInput struct { + Ocr1 *JobConfigOCR1Input `json:"ocr1,omitempty"` + Ocr2Median *JobConfigOCR2MedianInput `json:"ocr2Median,omitempty"` + Ocr2Mercury *JobConfigOCR2MercuryInput `json:"ocr2Mercury,omitempty"` + Ocr2CCIPCommit *JobConfigEmptyInput `json:"ocr2CCIPCommit,omitempty"` + Ocr2CCIPExecution *JobConfigEmptyInput `json:"ocr2CCIPExecution,omitempty"` + Ocr2CCIPRebalancer *JobConfigEmptyInput `json:"ocr2CCIPRebalancer,omitempty"` +} + +type JobConfigOcr1 struct { + Apis []string `json:"apis,omitempty"` +} + +func (JobConfigOcr1) IsJobConfig() {} + +type JobConfigOCR1Input struct { + Apis []string `json:"apis,omitempty"` +} + +type JobConfigOCR2Median struct { + Apis []string `json:"apis,omitempty"` +} + +func (JobConfigOCR2Median) IsJobConfig() {} + +type JobConfigOCR2MedianInput struct { + Apis []string `json:"apis,omitempty"` +} + +type JobConfigOCR2Mercury struct { + Apis []string `json:"apis,omitempty"` +} + +func (JobConfigOCR2Mercury) IsJobConfig() {} + +type JobConfigOCR2MercuryInput struct { + Apis []string `json:"apis,omitempty"` + CrossApis []string `json:"crossApis,omitempty"` +} + +type JobProposal struct { + ID string `json:"id,omitempty"` + Version string `json:"version,omitempty"` + Status JobProposalStatus `json:"status,omitempty"` + Spec string `json:"spec,omitempty"` + Job *Job `json:"job,omitempty"` + CreatedAt Time `json:"createdAt,omitempty"` + UpdatedAt Time `json:"updatedAt,omitempty"` + ProposedAt *Time `json:"proposedAt,omitempty"` + ResponseReceivedAt *Time `json:"responseReceivedAt,omitempty"` +} + +type KeystoneWorkflow struct { + ID string `json:"id,omitempty"` + WorkflowSpec string `json:"workflowSpec,omitempty"` + WorkflowOwner string `json:"workflowOwner,omitempty"` + ExternalWorkflowID string `json:"externalWorkflowID,omitempty"` + Don *Don `json:"don,omitempty"` + Name string `json:"name,omitempty"` + Category *Category `json:"category,omitempty"` +} + +type KeystoneWorkflowMutations struct { + ImportWorkflow *ImportKeystoneWorkflowPayload `json:"importWorkflow,omitempty"` + UpdateWorkflow *UpdateKeystoneWorkflowPayload `json:"updateWorkflow,omitempty"` +} + +type KeystoneWorkflowQueries struct { + Workflow *KeystoneWorkflow `json:"workflow,omitempty"` + Workflows []*KeystoneWorkflow `json:"workflows,omitempty"` +} + +type ListAggregatorsFilter struct { + NetworkID *string `json:"networkID,omitempty"` + ContractAddress *string `json:"contractAddress,omitempty"` +} + +type ListRelayersFilter struct { + Enabled *bool `json:"enabled,omitempty"` +} + +type ListWebhookCallsFilter struct { + State *WebhookCallState `json:"state,omitempty"` +} + +type LoginInput struct { + Email string `json:"email,omitempty"` + Password string `json:"password,omitempty"` +} + +type LoginPayload struct { + Session *Session `json:"session,omitempty"` + Errors []Error `json:"errors,omitempty"` +} + +type LogoutPayload struct { + Session *Session `json:"session,omitempty"` +} + +type MarkStaleJobsInput struct { + Ids []string `json:"ids,omitempty"` +} + +type MarkStaleJobsPayload struct { + Jobs []*Job `json:"jobs,omitempty"` + Errors []Error `json:"errors,omitempty"` +} + +type MercuryFeed struct { + ID string `json:"id,omitempty"` + Name string `json:"name,omitempty"` + ExternalFeedID string `json:"externalFeedID,omitempty"` + NetworkStack *MercuryNetworkStack `json:"networkStack,omitempty"` + FromBlock string `json:"fromBlock,omitempty"` + Template string `json:"template,omitempty"` + Don *Don `json:"don,omitempty"` + CreatedAt Time `json:"createdAt,omitempty"` + UpdatedAt Time `json:"updatedAt,omitempty"` +} + +type MercuryFeedsFilters struct { + Name *string `json:"name,omitempty"` + NetworkID *string `json:"networkID,omitempty"` + VerifierProxyAddress *string `json:"verifierProxyAddress,omitempty"` + Limit *string `json:"limit,omitempty"` + Offset *string `json:"offset,omitempty"` +} + +type MercuryFeedsInput struct { + Filter *MercuryFeedsFilters `json:"filter,omitempty"` +} + +type MercuryMutations struct { + CreateNetworkStack *CreateMercuryNetworkStackPayload `json:"createNetworkStack,omitempty"` + ImportFeed *ImportMercuryFeedPayload `json:"importFeed,omitempty"` + UpdateFeed *UpdateMercuryFeedPayload `json:"updateFeed,omitempty"` + UpdateNetworkStack *UpdateMercuryNetworkStackPayload `json:"updateNetworkStack,omitempty"` +} + +type MercuryNetworkStack struct { + ID string `json:"id,omitempty"` + Network *Network `json:"network,omitempty"` + VerifierAddress string `json:"verifierAddress,omitempty"` + VerifierProxyAddress string `json:"verifierProxyAddress,omitempty"` + ServerURL string `json:"serverURL,omitempty"` + ServerPublicKey string `json:"serverPublicKey,omitempty"` + CreatedAt Time `json:"createdAt,omitempty"` + UpdatedAt Time `json:"updatedAt,omitempty"` + Servers []*MercuryServer `json:"servers,omitempty"` +} + +type MercuryQueries struct { + NetworkStacks []*MercuryNetworkStack `json:"networkStacks,omitempty"` + NetworkStack *MercuryNetworkStack `json:"networkStack,omitempty"` + Feed *MercuryFeed `json:"feed,omitempty"` + Feeds []*MercuryFeed `json:"feeds,omitempty"` +} + +type MercuryServer struct { + URL string `json:"url,omitempty"` + PublicKey string `json:"publicKey,omitempty"` +} + +type MercuryV03Feed struct { + ID string `json:"id,omitempty"` + Name string `json:"name,omitempty"` + ExternalFeedID string `json:"externalFeedID,omitempty"` + Verifiers []*MercuryV03Verifier `json:"verifiers,omitempty"` + ReportSchemaVersion ReportSchemaVersion `json:"reportSchemaVersion,omitempty"` + Template string `json:"template,omitempty"` + Don *Don `json:"don,omitempty"` + CreatedAt Time `json:"createdAt,omitempty"` + UpdatedAt Time `json:"updatedAt,omitempty"` + ArchivedAt *Time `json:"archivedAt,omitempty"` + Category *Category `json:"category,omitempty"` +} + +type MercuryV03FeedFilter struct { + IsArchived *bool `json:"isArchived,omitempty"` + TransmitToServer *bool `json:"transmitToServer,omitempty"` +} + +type MercuryV03Mutations struct { + ArchiveFeed *ArchiveFeedPayload `json:"archiveFeed,omitempty"` + ArchiveNetworkStack *ArchiveNetworkStackPayload `json:"archiveNetworkStack,omitempty"` + AddVerificationProvider *AddVerificationProviderPayload `json:"addVerificationProvider,omitempty"` + RemoveVerificationProvider *RemoveVerificationProviderPayload `json:"removeVerificationProvider,omitempty"` + AddNetworkStack *AddMercuryV03NetworkStackPayload `json:"addNetworkStack,omitempty"` + DeployNetworkStack *DeployMercuryV03NetworkStackPayload `json:"deployNetworkStack,omitempty"` + ImportFeed *ImportMercuryV03FeedPayload `json:"importFeed,omitempty"` + ImportNetworkStack *ImportMercuryV03NetworkStackPayload `json:"importNetworkStack,omitempty"` + TransferOwnership *TransferOwnershipPayload `json:"transferOwnership,omitempty"` + UpdateNetworkStack *UpdateMercuryV03NetworkStackPayload `json:"updateNetworkStack,omitempty"` + UpdateFeed *UpdateMercuryV03FeedPayload `json:"updateFeed,omitempty"` + VerifyContract *VerifyMercuryV03ContractPayload `json:"verifyContract,omitempty"` +} + +type MercuryV03NetworkStack struct { + ID string `json:"id,omitempty"` + Network *Network `json:"network,omitempty"` + Status NetworkStackStatus `json:"status,omitempty"` + VerifierAddress *string `json:"verifierAddress,omitempty"` + VerifierProxyAddress *string `json:"verifierProxyAddress,omitempty"` + RewardBankAddress *string `json:"rewardBankAddress,omitempty"` + FeeManagerAddress *string `json:"feeManagerAddress,omitempty"` + MercuryServerURL string `json:"mercuryServerURL,omitempty"` + MercuryServerPubKey string `json:"mercuryServerPubKey,omitempty"` + Contracts []*Contract `json:"contracts,omitempty"` + WorkflowRuns []*WorkflowRun `json:"workflowRuns,omitempty"` + CreatedAt Time `json:"createdAt,omitempty"` + UpdatedAt Time `json:"updatedAt,omitempty"` + ArchivedAt *Time `json:"archivedAt,omitempty"` + Servers []*MercuryServer `json:"servers,omitempty"` +} + +type MercuryV03NetworkStackFilter struct { + IsArchived *bool `json:"isArchived,omitempty"` +} + +type MercuryV03Queries struct { + NetworkStack *MercuryV03NetworkStack `json:"networkStack,omitempty"` + NetworkStacks []*MercuryV03NetworkStack `json:"networkStacks,omitempty"` + Feed *MercuryV03Feed `json:"feed,omitempty"` + Feeds []*MercuryV03Feed `json:"feeds,omitempty"` +} + +type MercuryV03Verifier struct { + ID string `json:"id,omitempty"` + NetworkStack *MercuryV03NetworkStack `json:"networkStack,omitempty"` + NetworkStackType NetworkStackType `json:"networkStackType,omitempty"` +} + +type Mutation struct { +} + +type Network struct { + ID string `json:"id,omitempty"` + ChainID string `json:"chainID,omitempty"` + ChainType ChainType `json:"chainType,omitempty"` + Name string `json:"name,omitempty"` + NativeToken string `json:"nativeToken,omitempty"` + Archived bool `json:"archived,omitempty"` + NativeTokenContractAddress *string `json:"nativeTokenContractAddress,omitempty"` + ConfigContractAddress *string `json:"configContractAddress,omitempty"` + LinkUSDProxyAddress *string `json:"linkUSDProxyAddress,omitempty"` + NativeUSDProxyAddress *string `json:"nativeUSDProxyAddress,omitempty"` + LinkContractAddress *string `json:"linkContractAddress,omitempty"` + FlagsContractAddress *string `json:"flagsContractAddress,omitempty"` + LinkFunding string `json:"linkFunding,omitempty"` + BillingAdminAccessControllerAddress *string `json:"billingAdminAccessControllerAddress,omitempty"` + RequesterAdminAccessControllerAddress *string `json:"requesterAdminAccessControllerAddress,omitempty"` + IconName *string `json:"iconName,omitempty"` + ExplorerURL *string `json:"explorerURL,omitempty"` + Relayers []*Relayer `json:"relayers,omitempty"` + Vaults []*Vault `json:"vaults,omitempty"` + ExplorerAPIKey *string `json:"explorerAPIKey,omitempty"` + ExplorerAPIURL *string `json:"explorerAPIURL,omitempty"` +} + +type NetworksFilters struct { + Archived *bool `json:"archived,omitempty"` + ChainID *string `json:"chainID,omitempty"` + ChainType *ChainType `json:"chainType,omitempty"` + Name *string `json:"name,omitempty"` +} + +type NetworksInput struct { + Filter *NetworksFilters `json:"filter,omitempty"` +} + +type Node struct { + ID string `json:"id,omitempty"` + Name string `json:"name,omitempty"` + PublicKey *string `json:"publicKey,omitempty"` + ChainConfigs []*NodeChainConfig `json:"chainConfigs,omitempty"` + Connected bool `json:"connected,omitempty"` + Enabled bool `json:"enabled,omitempty"` + Metadata *NodeMetadata `json:"metadata,omitempty"` + NodeOperator *NodeOperator `json:"nodeOperator,omitempty"` + Version *string `json:"version,omitempty"` + SupportedProducts []ProductType `json:"supportedProducts,omitempty"` + Categories []*Category `json:"categories,omitempty"` + CreatedAt Time `json:"createdAt,omitempty"` +} + +type NodeChainConfig struct { + ID string `json:"id,omitempty"` + Network *Network `json:"network,omitempty"` + AccountAddress string `json:"accountAddress,omitempty"` + AdminAddress string `json:"adminAddress,omitempty"` + Ocr1Config *NodeOCR1Config `json:"ocr1Config,omitempty"` + Ocr1BootstrapVerified bool `json:"ocr1BootstrapVerified,omitempty"` + Ocr2Config *NodeOCR2Config `json:"ocr2Config,omitempty"` + Ocr2BootstrapVerified bool `json:"ocr2BootstrapVerified,omitempty"` + CreatedAt Time `json:"createdAt,omitempty"` +} + +type NodeConnectionInfo struct { + PublicKey string `json:"publicKey,omitempty"` + RPCURL string `json:"rpcURL,omitempty"` +} + +type NodeMetadata struct { + JobCount int `json:"jobCount,omitempty"` +} + +type NodeOCR1Config struct { + Enabled bool `json:"enabled,omitempty"` + IsBootstrap bool `json:"isBootstrap,omitempty"` + Multiaddr *string `json:"multiaddr,omitempty"` + P2pKeyBundle *NodeOCR1ConfigP2PKeyBundle `json:"p2pKeyBundle,omitempty"` + OcrKeyBundle *NodeOCR1ConfigOCRKeyBundle `json:"ocrKeyBundle,omitempty"` +} + +type NodeOCR1ConfigOCRKeyBundle struct { + BundleID string `json:"bundleID,omitempty"` + ConfigPublicKey string `json:"configPublicKey,omitempty"` + OffchainPublicKey string `json:"offchainPublicKey,omitempty"` + OnchainSigningAddress string `json:"onchainSigningAddress,omitempty"` +} + +type NodeOCR1ConfigP2PKeyBundle struct { + PeerID string `json:"peerID,omitempty"` + PublicKey string `json:"publicKey,omitempty"` +} + +type NodeOCR2Config struct { + Enabled bool `json:"enabled,omitempty"` + IsBootstrap bool `json:"isBootstrap,omitempty"` + Multiaddr *string `json:"multiaddr,omitempty"` + ForwarderAddress *string `json:"forwarderAddress,omitempty"` + P2pKeyBundle *NodeOCR2ConfigP2PKeyBundle `json:"p2pKeyBundle,omitempty"` + OcrKeyBundle *NodeOCR2ConfigOCRKeyBundle `json:"ocrKeyBundle,omitempty"` + Plugins *NodeOCR2ConfigPlugins `json:"plugins,omitempty"` +} + +type NodeOCR2ConfigOCRKeyBundle struct { + BundleID string `json:"bundleID,omitempty"` + ConfigPublicKey string `json:"configPublicKey,omitempty"` + OffchainPublicKey string `json:"offchainPublicKey,omitempty"` + OnchainSigningAddress string `json:"onchainSigningAddress,omitempty"` +} + +type NodeOCR2ConfigP2PKeyBundle struct { + PeerID string `json:"peerID,omitempty"` + PublicKey string `json:"publicKey,omitempty"` +} + +type NodeOCR2ConfigPlugins struct { + CcipCommit bool `json:"ccipCommit,omitempty"` + CcipExecution bool `json:"ccipExecution,omitempty"` + CcipRebalancer bool `json:"ccipRebalancer,omitempty"` + Median bool `json:"median,omitempty"` + Mercury bool `json:"mercury,omitempty"` +} + +type NodeOperator struct { + ID string `json:"id,omitempty"` + Keys []string `json:"keys,omitempty"` + Name string `json:"name,omitempty"` + Email string `json:"email,omitempty"` + Website string `json:"website,omitempty"` + Metadata *NodeOperatorMetadata `json:"metadata,omitempty"` + Nodes []*Node `json:"nodes,omitempty"` + CreatedAt Time `json:"createdAt,omitempty"` +} + +type NodeOperatorMetadata struct { + NodeCount int `json:"nodeCount,omitempty"` + JobCount int `json:"jobCount,omitempty"` +} + +type NodesFilters struct { + NetworkID *string `json:"networkID,omitempty"` +} + +type NodesInput struct { + Filter *NodesFilters `json:"filter,omitempty"` +} + +type OCR3Capability struct { + ID string `json:"id,omitempty"` + ContractAddress string `json:"contractAddress,omitempty"` + Name string `json:"name,omitempty"` + BootstrapMultiaddrs []string `json:"bootstrapMultiaddrs,omitempty"` + Template string `json:"template,omitempty"` + Category *Category `json:"category,omitempty"` + Don *Don `json:"don,omitempty"` +} + +type OCR3CapabilityMutations struct { + ImportOCR3Capability *ImportOCR3CapabilityPayload `json:"importOCR3Capability,omitempty"` + UpdateOCR3Capability *UpdateOCR3CapabilityPayload `json:"updateOCR3Capability,omitempty"` +} + +type OCR3CapabilityQueries struct { + Ocr3Capability *OCR3Capability `json:"ocr3Capability,omitempty"` + Ocr3Capabilities []*OCR3Capability `json:"ocr3Capabilities,omitempty"` +} + +type PriceFeed struct { + AggregatorAddress string `json:"aggregatorAddress,omitempty"` + Multiplier string `json:"multiplier,omitempty"` +} + +type Profile struct { + ID string `json:"id,omitempty"` + Name string `json:"name,omitempty"` + Email string `json:"email,omitempty"` + Role UserRole `json:"role,omitempty"` + Permits []string `json:"permits,omitempty"` + CreatedAt Time `json:"createdAt,omitempty"` +} + +type ProposeJobInput struct { + ID string `json:"id,omitempty"` +} + +type ProposeJobPayload struct { + Job *Job `json:"job,omitempty"` + Errors []Error `json:"errors,omitempty"` +} + +type Query struct { +} + +type ReadAccessController struct { + Address string `json:"address,omitempty"` +} + +type Relayer struct { + ID string `json:"id,omitempty"` + Name string `json:"name,omitempty"` + URL *URL `json:"url,omitempty"` + Config string `json:"config,omitempty"` + IsEnabled bool `json:"isEnabled,omitempty"` + Network *Network `json:"network,omitempty"` + Accounts []*RelayerAccount `json:"accounts,omitempty"` +} + +type RelayerAccount struct { + ID string `json:"id,omitempty"` + Relayer *Relayer `json:"relayer,omitempty"` + Address string `json:"address,omitempty"` + NativeBalance string `json:"nativeBalance,omitempty"` + LinkBalance string `json:"linkBalance,omitempty"` +} + +type RelayerURL struct { + Websocket string `json:"websocket,omitempty"` + HTTP string `json:"http,omitempty"` +} + +type RemoveLiquidityInput struct { + ChainID string `json:"chainID,omitempty"` + TokenPoolContractID string `json:"tokenPoolContractID,omitempty"` + Amount string `json:"amount,omitempty"` +} + +type RemoveLiquidityPayload struct { + Errors []Error `json:"errors,omitempty"` + WorkflowRun *WorkflowRun `json:"workflowRun,omitempty"` +} + +type RemoveVerificationProviderInput struct { + FeedID string `json:"feedID,omitempty"` + NetworkStackID string `json:"networkStackID,omitempty"` +} + +type RemoveVerificationProviderPayload struct { + Feed *MercuryV03Feed `json:"feed,omitempty"` + Errors []Error `json:"errors,omitempty"` +} + +type RetryActionRunInput struct { + ActionRunID string `json:"actionRunID,omitempty"` +} + +type RetryActionRunPayload struct { + Status ActionRunStatus `json:"status,omitempty"` + Errors []Error `json:"errors,omitempty"` +} + +type RetryWebhookCallInput struct { + WebhookCallID string `json:"webhookCallID,omitempty"` +} + +type RetryWebhookCallPayload struct { + WebhookCall *WebhookCall `json:"webhookCall,omitempty"` + Errors []Error `json:"errors,omitempty"` +} + +type RevokeJobInput struct { + ID string `json:"id,omitempty"` +} + +type RevokeJobPayload struct { + Job *Job `json:"job,omitempty"` + Errors []Error `json:"errors,omitempty"` +} + +type Role struct { + ID string `json:"id,omitempty"` + Name string `json:"name,omitempty"` + Permits []string `json:"permits,omitempty"` +} + +type RunCCIPCommandInput struct { + Command CCIPCommand `json:"command,omitempty"` + LaneLegID string `json:"laneLegID,omitempty"` + Upgrade *bool `json:"upgrade,omitempty"` +} + +type RunCCIPCommandPayload struct { + Errors []Error `json:"errors,omitempty"` + WorkflowRun *WorkflowRun `json:"workflowRun,omitempty"` +} + +type SendTestWebhookEventInput struct { + WebhookID string `json:"webhookID,omitempty"` +} + +type SendTestWebhookEventPayload struct { + WebhookCall *WebhookCall `json:"webhookCall,omitempty"` + Errors []Error `json:"errors,omitempty"` +} + +type Session struct { + ID string `json:"id,omitempty"` + Token string `json:"token,omitempty"` + ExpiresAt Time `json:"expiresAt,omitempty"` + Revoked bool `json:"revoked,omitempty"` + Permits []string `json:"permits,omitempty"` +} + +type SetAllowListTokenPoolInput struct { + ChainID string `json:"chainID,omitempty"` + TokenPoolContractID string `json:"tokenPoolContractID,omitempty"` + AllowList []string `json:"allowList,omitempty"` +} + +type SetAllowListTokenPoolPayload struct { + Errors []Error `json:"errors,omitempty"` + WorkflowRun *WorkflowRun `json:"workflowRun,omitempty"` +} + +type SetPasswordInput struct { + UserID string `json:"userID,omitempty"` + Password string `json:"password,omitempty"` +} + +type SetPasswordPayload struct { + Errors []Error `json:"errors,omitempty"` +} + +type SetupAppInput struct { + Token string `json:"token,omitempty"` + Email string `json:"email,omitempty"` + Name string `json:"name,omitempty"` + Password string `json:"password,omitempty"` +} + +type SetupAppPayload struct { + Errors []Error `json:"errors,omitempty"` +} + +type SpecConfigOffChainReporting1 struct { + Decimals int `json:"decimals,omitempty"` +} + +func (SpecConfigOffChainReporting1) IsAggregatorSpecConfig() {} + +type SpecConfigOffChainReporting2 struct { + Decimals int `json:"decimals,omitempty"` +} + +func (SpecConfigOffChainReporting2) IsAggregatorSpecConfig() {} + +type StorageContract struct { + ID string `json:"id,omitempty"` + Network *Network `json:"network,omitempty"` + DisplayName *string `json:"displayName,omitempty"` + Template string `json:"template,omitempty"` + Contract *Contract `json:"contract,omitempty"` + WorkflowRuns []*WorkflowRun `json:"workflowRuns,omitempty"` +} + +type StorageContractFilter struct { + NetworkID *string `json:"networkID,omitempty"` +} + +// Grouping of all mutations related to the Storage contract resource. +type StorageMutations struct { + // addStorageContract adds a new storage contract to the database and creates + // a single new resource. + AddStorageContract *AddStorageContractPayload `json:"addStorageContract,omitempty"` + // deploySetStorageContract deploys a new storage contract to the network and + // sets the value on chain to the value provided from the template of the storage. + DeploySetStorageContract *DeploySetStorageContractPayload `json:"deploySetStorageContract,omitempty"` +} + +// Grouping of all queries related to the Storage contract resource. +type StorageQueries struct { + StorageContracts []*StorageContract `json:"storageContracts,omitempty"` + StorageContract *StorageContract `json:"storageContract,omitempty"` +} + +type SyncAggregatorInput struct { + ID string `json:"id,omitempty"` +} + +type SyncAggregatorPayload struct { + Aggregator *Aggregator `json:"aggregator,omitempty"` + Errors []Error `json:"errors,omitempty"` +} + +type SyncAggregatorProxyInput struct { + ID string `json:"id,omitempty"` +} + +type SyncAggregatorProxyPayload struct { + AggregatorProxy *AggregatorProxy `json:"aggregatorProxy,omitempty"` + Errors []Error `json:"errors,omitempty"` +} + +type SyncChainInput struct { + ChainID string `json:"chainID,omitempty"` +} + +type SyncChainPayload struct { + Chain *CCIPChain `json:"chain,omitempty"` + Errors []Error `json:"errors,omitempty"` +} + +type SyncContractsInput struct { + ContractIDs []string `json:"contractIDs,omitempty"` +} + +type SyncContractsPayload struct { + Contracts []*Contract `json:"contracts,omitempty"` + Errors []Error `json:"errors,omitempty"` +} + +type SyncLaneInput struct { + LaneID string `json:"laneID,omitempty"` +} + +type SyncLanePayload struct { + Lane *CCIPLane `json:"lane,omitempty"` + Errors []Error `json:"errors,omitempty"` +} + +type Task struct { + Name string `json:"name,omitempty"` + Run *TaskRun `json:"run,omitempty"` +} + +type TaskRun struct { + ID string `json:"id,omitempty"` + Input string `json:"input,omitempty"` + Output string `json:"output,omitempty"` + Status TaskRunStatus `json:"status,omitempty"` + Error *string `json:"error,omitempty"` + TxHash *string `json:"txHash,omitempty"` +} + +type Token struct { + Symbol string `json:"symbol,omitempty"` + Address string `json:"address,omitempty"` +} + +type TransferAdminRoleInput struct { + TokenAdminRegistryID string `json:"tokenAdminRegistryID,omitempty"` + TokenPoolID string `json:"tokenPoolID,omitempty"` + VaultID string `json:"vaultID,omitempty"` +} + +type TransferAdminRolePayload struct { + Errors []Error `json:"errors,omitempty"` + WorkflowRun *WorkflowRun `json:"workflowRun,omitempty"` +} + +type TransferOwnershipInput struct { + ContractIDs []string `json:"contractIDs,omitempty"` + VaultID string `json:"vaultID,omitempty"` +} + +type TransferOwnershipPayload struct { + Errors []Error `json:"errors,omitempty"` + WorkflowRun *WorkflowRun `json:"workflowRun,omitempty"` +} + +type URL struct { + Websocket string `json:"websocket,omitempty"` + HTTP *string `json:"http,omitempty"` +} + +type UnarchiveNetworkInput struct { + ID string `json:"id,omitempty"` +} + +type UnarchiveNetworkPayload struct { + Network *Network `json:"network,omitempty"` + Errors []Error `json:"errors,omitempty"` +} + +type UpdateAggregatorDetailsInput struct { + ID string `json:"id,omitempty"` + Name string `json:"name,omitempty"` + CategoryID string `json:"categoryID,omitempty"` +} + +type UpdateAggregatorDetailsPayload struct { + Aggregator *Aggregator `json:"aggregator,omitempty"` + Errors []Error `json:"errors,omitempty"` +} + +type UpdateAggregatorInput struct { + ID string `json:"id,omitempty"` + AggregatorTemplate *string `json:"aggregatorTemplate,omitempty"` +} + +type UpdateAggregatorPayload struct { + Aggregator *Aggregator `json:"aggregator,omitempty"` + Errors []Error `json:"errors,omitempty"` +} + +type UpdateAggregatorProxyInput struct { + ID string `json:"id,omitempty"` + ContractAddress string `json:"contractAddress,omitempty"` +} + +type UpdateAggregatorProxyPayload struct { + ID string `json:"id,omitempty"` + Errors []Error `json:"errors,omitempty"` +} + +type UpdateCCIPChainInput struct { + ID string `json:"id,omitempty"` + Template string `json:"template,omitempty"` +} + +type UpdateCCIPChainPayload struct { + Chain *CCIPChain `json:"chain,omitempty"` + Errors []Error `json:"errors,omitempty"` +} + +type UpdateCategoryInput struct { + ID string `json:"id,omitempty"` + Name string `json:"name,omitempty"` + Color *string `json:"color,omitempty"` +} + +type UpdateCategoryPayload struct { + Category *Category `json:"category,omitempty"` + Errors []Error `json:"errors,omitempty"` +} + +type UpdateFeedInput struct { + ID string `json:"id,omitempty"` + Name string `json:"name,omitempty"` +} + +type UpdateFeedPayload struct { + Feed *Feed `json:"feed,omitempty"` + Errors []Error `json:"errors,omitempty"` +} + +type UpdateKeystoneWorkflowInput struct { + ID string `json:"id,omitempty"` + Template string `json:"template,omitempty"` + CategoryID string `json:"categoryID,omitempty"` +} + +type UpdateKeystoneWorkflowPayload struct { + Workflow *KeystoneWorkflow `json:"workflow,omitempty"` + Errors []Error `json:"errors,omitempty"` +} + +type UpdateLaneInput struct { + Template *string `json:"template,omitempty"` + UpdateStartBlocks *bool `json:"updateStartBlocks,omitempty"` + LegA *CCIPLaneChainUpdateInput `json:"legA,omitempty"` + LegB *CCIPLaneChainUpdateInput `json:"legB,omitempty"` +} + +type UpdateLanePayload struct { + Errors []Error `json:"errors,omitempty"` + Lane *CCIPLane `json:"lane,omitempty"` +} + +type UpdateMercuryFeedInput struct { + ID string `json:"id,omitempty"` + FromBlock string `json:"fromBlock,omitempty"` + Template *string `json:"template,omitempty"` +} + +type UpdateMercuryFeedPayload struct { + Feed *MercuryFeed `json:"feed,omitempty"` + Errors []Error `json:"errors,omitempty"` +} + +type UpdateMercuryNetworkStackInput struct { + ID string `json:"id,omitempty"` + VerifierAddress string `json:"verifierAddress,omitempty"` + VerifierProxyAddress string `json:"verifierProxyAddress,omitempty"` + ServerURL string `json:"serverURL,omitempty"` + ServerPublicKey string `json:"serverPublicKey,omitempty"` + Servers *string `json:"servers,omitempty"` +} + +type UpdateMercuryNetworkStackPayload struct { + NetworkStack *MercuryNetworkStack `json:"networkStack,omitempty"` + Errors []Error `json:"errors,omitempty"` +} + +type UpdateMercuryV03FeedInput struct { + ID string `json:"id,omitempty"` + Template string `json:"template,omitempty"` + CategoryID string `json:"categoryID,omitempty"` +} + +type UpdateMercuryV03FeedPayload struct { + Feed *MercuryV03Feed `json:"feed,omitempty"` + Errors []Error `json:"errors,omitempty"` +} + +type UpdateMercuryV03NetworkStackInput struct { + ID string `json:"id,omitempty"` + VerifierAddress string `json:"verifierAddress,omitempty"` + VerifierProxyAddress string `json:"verifierProxyAddress,omitempty"` + RewardBankAddress string `json:"rewardBankAddress,omitempty"` + FeeManagerAddress string `json:"feeManagerAddress,omitempty"` + MercuryServerURL string `json:"mercuryServerURL,omitempty"` + MercuryServerPubKey string `json:"mercuryServerPubKey,omitempty"` + Servers *string `json:"servers,omitempty"` +} + +type UpdateMercuryV03NetworkStackPayload struct { + NetworkStack *MercuryV03NetworkStack `json:"networkStack,omitempty"` + Errors []Error `json:"errors,omitempty"` +} + +type UpdateNetworkInput struct { + ID string `json:"id,omitempty"` + Name string `json:"name,omitempty"` + NativeToken string `json:"nativeToken,omitempty"` + NativeTokenContractAddress *string `json:"nativeTokenContractAddress,omitempty"` + ConfigContractAddress *string `json:"configContractAddress,omitempty"` + LinkUSDProxyAddress *string `json:"linkUSDProxyAddress,omitempty"` + NativeUSDProxyAddress *string `json:"nativeUSDProxyAddress,omitempty"` + LinkContractAddress *string `json:"linkContractAddress,omitempty"` + FlagsContractAddress *string `json:"flagsContractAddress,omitempty"` + LinkFunding *string `json:"linkFunding,omitempty"` + BillingAdminAccessControllerAddress *string `json:"billingAdminAccessControllerAddress,omitempty"` + RequesterAdminAccessControllerAddress *string `json:"requesterAdminAccessControllerAddress,omitempty"` + ExplorerAPIKey *string `json:"explorerAPIKey,omitempty"` + ExplorerAPIURL *string `json:"explorerAPIURL,omitempty"` +} + +type UpdateNetworkPayload struct { + Network *Network `json:"network,omitempty"` + Errors []Error `json:"errors,omitempty"` +} + +type UpdateNodeInput struct { + ID string `json:"id,omitempty"` + Name string `json:"name,omitempty"` + PublicKey string `json:"publicKey,omitempty"` + SupportedCategoryIDs []string `json:"supportedCategoryIDs,omitempty"` + SupportedProducts []ProductType `json:"supportedProducts,omitempty"` +} + +type UpdateNodeOperatorInput struct { + ID string `json:"id,omitempty"` + Keys []string `json:"keys,omitempty"` + Name string `json:"name,omitempty"` + Email string `json:"email,omitempty"` + Website string `json:"website,omitempty"` +} + +type UpdateNodeOperatorPayload struct { + NodeOperator *NodeOperator `json:"nodeOperator,omitempty"` + Errors []Error `json:"errors,omitempty"` +} + +type UpdateNodePayload struct { + Node *Node `json:"node,omitempty"` + Errors []Error `json:"errors,omitempty"` +} + +type UpdateOCR3CapabilityInput struct { + ID string `json:"id,omitempty"` + Template string `json:"template,omitempty"` + CategoryID string `json:"categoryID,omitempty"` +} + +type UpdateOCR3CapabilityPayload struct { + Ocr3Capability *OCR3Capability `json:"ocr3Capability,omitempty"` + Errors []Error `json:"errors,omitempty"` +} + +type UpdatePasswordInput struct { + OldPassword string `json:"oldPassword,omitempty"` + NewPassword string `json:"newPassword,omitempty"` +} + +type UpdatePasswordPayload struct { + Errors []Error `json:"errors,omitempty"` +} + +type UpdateProfileInput struct { + Name string `json:"name,omitempty"` +} + +type UpdateProfilePayload struct { + Profile *Profile `json:"profile,omitempty"` + Errors []Error `json:"errors,omitempty"` +} + +type UpdateRelayerInput struct { + ID string `json:"id,omitempty"` + Name string `json:"name,omitempty"` + URL *RelayerURL `json:"url,omitempty"` + Config string `json:"config,omitempty"` +} + +type UpdateRelayerPayload struct { + Relayer *Relayer `json:"relayer,omitempty"` + Errors []Error `json:"errors,omitempty"` +} + +type UpdateUserInput struct { + ID string `json:"id,omitempty"` + Name string `json:"name,omitempty"` + Email string `json:"email,omitempty"` + Role UserRole `json:"role,omitempty"` +} + +type UpdateUserPayload struct { + User *User `json:"user,omitempty"` + Errors []Error `json:"errors,omitempty"` +} + +type UpdateVaultInput struct { + ID string `json:"id,omitempty"` + Name string `json:"name,omitempty"` + Address string `json:"address,omitempty"` + SupportedProducts []ProductType `json:"supportedProducts,omitempty"` +} + +type UpdateVaultPayload struct { + Vault *Vault `json:"vault,omitempty"` + Errors []Error `json:"errors,omitempty"` +} + +type UpdateWebhookInput struct { + ID string `json:"id,omitempty"` + Name string `json:"name,omitempty"` + EndpointURL string `json:"endpointURL,omitempty"` + Enabled bool `json:"enabled,omitempty"` +} + +type UpdateWebhookPayload struct { + Webhook *Webhook `json:"webhook,omitempty"` + Errors []Error `json:"errors,omitempty"` +} + +type User struct { + ID string `json:"id,omitempty"` + Name string `json:"name,omitempty"` + Email string `json:"email,omitempty"` + Role UserRole `json:"role,omitempty"` + Disabled bool `json:"disabled,omitempty"` + CreatedAt Time `json:"createdAt,omitempty"` +} + +type Vault struct { + ID string `json:"id,omitempty"` + Name string `json:"name,omitempty"` + Address string `json:"address,omitempty"` + Type VaultType `json:"type,omitempty"` + SupportedProducts []ProductType `json:"supportedProducts,omitempty"` + Network *Network `json:"network,omitempty"` + CreatedAt Time `json:"createdAt,omitempty"` + UpdatedAt Time `json:"updatedAt,omitempty"` +} + +type VaultsFilters struct { + Type *VaultType `json:"type,omitempty"` +} + +type VaultsInput struct { + Filter *VaultsFilters `json:"filter,omitempty"` +} + +type VerifyMercuryV03ContractInput struct { + ContractIDs []string `json:"contractIDs,omitempty"` +} + +type VerifyMercuryV03ContractPayload struct { + WorkflowRun *WorkflowRun `json:"workflowRun,omitempty"` + Errors []Error `json:"errors,omitempty"` +} + +type Webhook struct { + ID string `json:"id,omitempty"` + Name string `json:"name,omitempty"` + EndpointURL string `json:"endpointURL,omitempty"` + SecretKey string `json:"secretKey,omitempty"` + Enabled bool `json:"enabled,omitempty"` + CreatedAt Time `json:"createdAt,omitempty"` + UpdatedAt Time `json:"updatedAt,omitempty"` +} + +type WebhookCall struct { + ID string `json:"id,omitempty"` + UUID string `json:"uuid,omitempty"` + Type string `json:"type,omitempty"` + State string `json:"state,omitempty"` + Payload string `json:"payload,omitempty"` + Attempts []*WebhookCallAttempt `json:"attempts,omitempty"` + CreatedAt Time `json:"createdAt,omitempty"` + DeliveredAt *Time `json:"deliveredAt,omitempty"` +} + +type WebhookCallAttempt struct { + ID string `json:"id,omitempty"` + StatusCode int `json:"statusCode,omitempty"` + Timestamp Time `json:"timestamp,omitempty"` +} + +type WorkflowRun struct { + ID string `json:"id,omitempty"` + WorkflowType WorkflowType `json:"workflowType,omitempty"` + Status WorkflowRunStatus `json:"status,omitempty"` + User *User `json:"user,omitempty"` + AccountAddress *string `json:"accountAddress,omitempty"` + Actions []*Action `json:"actions,omitempty"` + CreatedAt Time `json:"createdAt,omitempty"` + Name *string `json:"name,omitempty"` + DeletedAt *Time `json:"deletedAt,omitempty"` +} + +type WorkflowRunAndContract struct { + WorkflowRun *WorkflowRun `json:"workflowRun,omitempty"` + Contract *Contract `json:"contract,omitempty"` +} + +type WorkflowRunsFilters struct { + UserID *string `json:"userID,omitempty"` +} + +type WorkflowRunsInput struct { + Filter *WorkflowRunsFilters `json:"filter,omitempty"` +} + +type ActionRunStatus string + +const ( + ActionRunStatusPending ActionRunStatus = "PENDING" + ActionRunStatusInProgress ActionRunStatus = "IN_PROGRESS" + ActionRunStatusCompleted ActionRunStatus = "COMPLETED" + ActionRunStatusErrored ActionRunStatus = "ERRORED" +) + +var AllActionRunStatus = []ActionRunStatus{ + ActionRunStatusPending, + ActionRunStatusInProgress, + ActionRunStatusCompleted, + ActionRunStatusErrored, +} + +func (e ActionRunStatus) IsValid() bool { + switch e { + case ActionRunStatusPending, ActionRunStatusInProgress, ActionRunStatusCompleted, ActionRunStatusErrored: + return true + } + return false +} + +func (e ActionRunStatus) String() string { + return string(e) +} + +func (e *ActionRunStatus) UnmarshalGQL(v interface{}) error { + str, ok := v.(string) + if !ok { + return fmt.Errorf("enums must be strings") + } + + *e = ActionRunStatus(str) + if !e.IsValid() { + return fmt.Errorf("%s is not a valid ActionRunStatus", str) + } + return nil +} + +func (e ActionRunStatus) MarshalGQL(w io.Writer) { + fmt.Fprint(w, strconv.Quote(e.String())) +} + +type ActionType string + +const ( + ActionTypeGeneric ActionType = "GENERIC" +) + +var AllActionType = []ActionType{ + ActionTypeGeneric, +} + +func (e ActionType) IsValid() bool { + switch e { + case ActionTypeGeneric: + return true + } + return false +} + +func (e ActionType) String() string { + return string(e) +} + +func (e *ActionType) UnmarshalGQL(v interface{}) error { + str, ok := v.(string) + if !ok { + return fmt.Errorf("enums must be strings") + } + + *e = ActionType(str) + if !e.IsValid() { + return fmt.Errorf("%s is not a valid ActionType", str) + } + return nil +} + +func (e ActionType) MarshalGQL(w io.Writer) { + fmt.Fprint(w, strconv.Quote(e.String())) +} + +type CCIPCommand string + +const ( + CCIPCommandSetConfig CCIPCommand = "SET_CONFIG" +) + +var AllCCIPCommand = []CCIPCommand{ + CCIPCommandSetConfig, +} + +func (e CCIPCommand) IsValid() bool { + switch e { + case CCIPCommandSetConfig: + return true + } + return false +} + +func (e CCIPCommand) String() string { + return string(e) +} + +func (e *CCIPCommand) UnmarshalGQL(v interface{}) error { + str, ok := v.(string) + if !ok { + return fmt.Errorf("enums must be strings") + } + + *e = CCIPCommand(str) + if !e.IsValid() { + return fmt.Errorf("%s is not a valid CCIPCommand", str) + } + return nil +} + +func (e CCIPCommand) MarshalGQL(w io.Writer) { + fmt.Fprint(w, strconv.Quote(e.String())) +} + +type CCIPJobType string + +const ( + CCIPJobTypeCommit CCIPJobType = "COMMIT" + CCIPJobTypeExecute CCIPJobType = "EXECUTE" + CCIPJobTypeBootstrap CCIPJobType = "BOOTSTRAP" +) + +var AllCCIPJobType = []CCIPJobType{ + CCIPJobTypeCommit, + CCIPJobTypeExecute, + CCIPJobTypeBootstrap, +} + +func (e CCIPJobType) IsValid() bool { + switch e { + case CCIPJobTypeCommit, CCIPJobTypeExecute, CCIPJobTypeBootstrap: + return true + } + return false +} + +func (e CCIPJobType) String() string { + return string(e) +} + +func (e *CCIPJobType) UnmarshalGQL(v interface{}) error { + str, ok := v.(string) + if !ok { + return fmt.Errorf("enums must be strings") + } + + *e = CCIPJobType(str) + if !e.IsValid() { + return fmt.Errorf("%s is not a valid CCIPJobType", str) + } + return nil +} + +func (e CCIPJobType) MarshalGQL(w io.Writer) { + fmt.Fprint(w, strconv.Quote(e.String())) +} + +type CCIPLaneLegStatus string + +const ( + CCIPLaneLegStatusDraft CCIPLaneLegStatus = "DRAFT" + CCIPLaneLegStatusReady CCIPLaneLegStatus = "READY" +) + +var AllCCIPLaneLegStatus = []CCIPLaneLegStatus{ + CCIPLaneLegStatusDraft, + CCIPLaneLegStatusReady, +} + +func (e CCIPLaneLegStatus) IsValid() bool { + switch e { + case CCIPLaneLegStatusDraft, CCIPLaneLegStatusReady: + return true + } + return false +} + +func (e CCIPLaneLegStatus) String() string { + return string(e) +} + +func (e *CCIPLaneLegStatus) UnmarshalGQL(v interface{}) error { + str, ok := v.(string) + if !ok { + return fmt.Errorf("enums must be strings") + } + + *e = CCIPLaneLegStatus(str) + if !e.IsValid() { + return fmt.Errorf("%s is not a valid CCIPLaneLegStatus", str) + } + return nil +} + +func (e CCIPLaneLegStatus) MarshalGQL(w io.Writer) { + fmt.Fprint(w, strconv.Quote(e.String())) +} + +type CCIPLaneLegTag string + +const ( + CCIPLaneLegTagMain CCIPLaneLegTag = "MAIN" + CCIPLaneLegTagProvisional CCIPLaneLegTag = "PROVISIONAL" + CCIPLaneLegTagDead CCIPLaneLegTag = "DEAD" +) + +var AllCCIPLaneLegTag = []CCIPLaneLegTag{ + CCIPLaneLegTagMain, + CCIPLaneLegTagProvisional, + CCIPLaneLegTagDead, +} + +func (e CCIPLaneLegTag) IsValid() bool { + switch e { + case CCIPLaneLegTagMain, CCIPLaneLegTagProvisional, CCIPLaneLegTagDead: + return true + } + return false +} + +func (e CCIPLaneLegTag) String() string { + return string(e) +} + +func (e *CCIPLaneLegTag) UnmarshalGQL(v interface{}) error { + str, ok := v.(string) + if !ok { + return fmt.Errorf("enums must be strings") + } + + *e = CCIPLaneLegTag(str) + if !e.IsValid() { + return fmt.Errorf("%s is not a valid CCIPLaneLegTag", str) + } + return nil +} + +func (e CCIPLaneLegTag) MarshalGQL(w io.Writer) { + fmt.Fprint(w, strconv.Quote(e.String())) +} + +type ChainType string + +const ( + ChainTypeEvm ChainType = "EVM" + ChainTypeSolana ChainType = "SOLANA" + ChainTypeStarknet ChainType = "STARKNET" + ChainTypeAptos ChainType = "APTOS" + +) + +var AllChainType = []ChainType{ + ChainTypeEvm, + ChainTypeSolana, + ChainTypeStarknet, + ChainTypeAptos, +} + +func (e ChainType) IsValid() bool { + switch e { + case ChainTypeEvm, ChainTypeSolana, ChainTypeStarknet, ChainTypeAptos: + return true + } + return false +} + +func (e ChainType) String() string { + return string(e) +} + +func (e *ChainType) UnmarshalGQL(v interface{}) error { + str, ok := v.(string) + if !ok { + return fmt.Errorf("enums must be strings") + } + + *e = ChainType(str) + if !e.IsValid() { + return fmt.Errorf("%s is not a valid ChainType", str) + } + return nil +} + +func (e ChainType) MarshalGQL(w io.Writer) { + fmt.Fprint(w, strconv.Quote(e.String())) +} + +type ContractOwnerType string + +const ( + ContractOwnerTypeSystem ContractOwnerType = "SYSTEM" + ContractOwnerTypeExternal ContractOwnerType = "EXTERNAL" + ContractOwnerTypeVault ContractOwnerType = "VAULT" + ContractOwnerTypeNotOwnable ContractOwnerType = "NOT_OWNABLE" +) + +var AllContractOwnerType = []ContractOwnerType{ + ContractOwnerTypeSystem, + ContractOwnerTypeExternal, + ContractOwnerTypeVault, + ContractOwnerTypeNotOwnable, +} + +func (e ContractOwnerType) IsValid() bool { + switch e { + case ContractOwnerTypeSystem, ContractOwnerTypeExternal, ContractOwnerTypeVault, ContractOwnerTypeNotOwnable: + return true + } + return false +} + +func (e ContractOwnerType) String() string { + return string(e) +} + +func (e *ContractOwnerType) UnmarshalGQL(v interface{}) error { + str, ok := v.(string) + if !ok { + return fmt.Errorf("enums must be strings") + } + + *e = ContractOwnerType(str) + if !e.IsValid() { + return fmt.Errorf("%s is not a valid ContractOwnerType", str) + } + return nil +} + +func (e ContractOwnerType) MarshalGQL(w io.Writer) { + fmt.Fprint(w, strconv.Quote(e.String())) +} + +type ContractTag string + +const ( + ContractTagMain ContractTag = "MAIN" + ContractTagTest ContractTag = "TEST" + ContractTagUpgrade ContractTag = "UPGRADE" + ContractTagDead ContractTag = "DEAD" +) + +var AllContractTag = []ContractTag{ + ContractTagMain, + ContractTagTest, + ContractTagUpgrade, + ContractTagDead, +} + +func (e ContractTag) IsValid() bool { + switch e { + case ContractTagMain, ContractTagTest, ContractTagUpgrade, ContractTagDead: + return true + } + return false +} + +func (e ContractTag) String() string { + return string(e) +} + +func (e *ContractTag) UnmarshalGQL(v interface{}) error { + str, ok := v.(string) + if !ok { + return fmt.Errorf("enums must be strings") + } + + *e = ContractTag(str) + if !e.IsValid() { + return fmt.Errorf("%s is not a valid ContractTag", str) + } + return nil +} + +func (e ContractTag) MarshalGQL(w io.Writer) { + fmt.Fprint(w, strconv.Quote(e.String())) +} + +type ContractType string + +const ( + ContractTypeOcr1 ContractType = "OCR1" + ContractTypeOcr2 ContractType = "OCR2" +) + +var AllContractType = []ContractType{ + ContractTypeOcr1, + ContractTypeOcr2, +} + +func (e ContractType) IsValid() bool { + switch e { + case ContractTypeOcr1, ContractTypeOcr2: + return true + } + return false +} + +func (e ContractType) String() string { + return string(e) +} + +func (e *ContractType) UnmarshalGQL(v interface{}) error { + str, ok := v.(string) + if !ok { + return fmt.Errorf("enums must be strings") + } + + *e = ContractType(str) + if !e.IsValid() { + return fmt.Errorf("%s is not a valid ContractType", str) + } + return nil +} + +func (e ContractType) MarshalGQL(w io.Writer) { + fmt.Fprint(w, strconv.Quote(e.String())) +} + +type DONExecutionType string + +const ( + DONExecutionTypeMercury DONExecutionType = "MERCURY" + DONExecutionTypeMercuryV03 DONExecutionType = "MERCURY_V03" + DONExecutionTypeAggregator DONExecutionType = "AGGREGATOR" + DONExecutionTypeCcipCommit DONExecutionType = "CCIP_COMMIT" + DONExecutionTypeCcipExecute DONExecutionType = "CCIP_EXECUTE" + DONExecutionTypeKeystoneWorkflow DONExecutionType = "KEYSTONE_WORKFLOW" +) + +var AllDONExecutionType = []DONExecutionType{ + DONExecutionTypeMercury, + DONExecutionTypeMercuryV03, + DONExecutionTypeAggregator, + DONExecutionTypeCcipCommit, + DONExecutionTypeCcipExecute, + DONExecutionTypeKeystoneWorkflow, +} + +func (e DONExecutionType) IsValid() bool { + switch e { + case DONExecutionTypeMercury, DONExecutionTypeMercuryV03, DONExecutionTypeAggregator, DONExecutionTypeCcipCommit, DONExecutionTypeCcipExecute, DONExecutionTypeKeystoneWorkflow: + return true + } + return false +} + +func (e DONExecutionType) String() string { + return string(e) +} + +func (e *DONExecutionType) UnmarshalGQL(v interface{}) error { + str, ok := v.(string) + if !ok { + return fmt.Errorf("enums must be strings") + } + + *e = DONExecutionType(str) + if !e.IsValid() { + return fmt.Errorf("%s is not a valid DONExecutionType", str) + } + return nil +} + +func (e DONExecutionType) MarshalGQL(w io.Writer) { + fmt.Fprint(w, strconv.Quote(e.String())) +} + +type DeploymentStatus string + +const ( + DeploymentStatusPending DeploymentStatus = "PENDING" + DeploymentStatusQueued DeploymentStatus = "QUEUED" + DeploymentStatusInProgress DeploymentStatus = "IN_PROGRESS" + DeploymentStatusCompleted DeploymentStatus = "COMPLETED" + DeploymentStatusErrored DeploymentStatus = "ERRORED" +) + +var AllDeploymentStatus = []DeploymentStatus{ + DeploymentStatusPending, + DeploymentStatusQueued, + DeploymentStatusInProgress, + DeploymentStatusCompleted, + DeploymentStatusErrored, +} + +func (e DeploymentStatus) IsValid() bool { + switch e { + case DeploymentStatusPending, DeploymentStatusQueued, DeploymentStatusInProgress, DeploymentStatusCompleted, DeploymentStatusErrored: + return true + } + return false +} + +func (e DeploymentStatus) String() string { + return string(e) +} + +func (e *DeploymentStatus) UnmarshalGQL(v interface{}) error { + str, ok := v.(string) + if !ok { + return fmt.Errorf("enums must be strings") + } + + *e = DeploymentStatus(str) + if !e.IsValid() { + return fmt.Errorf("%s is not a valid DeploymentStatus", str) + } + return nil +} + +func (e DeploymentStatus) MarshalGQL(w io.Writer) { + fmt.Fprint(w, strconv.Quote(e.String())) +} + +type FeedStatus string + +const ( + FeedStatusDraft FeedStatus = "DRAFT" + FeedStatusReady FeedStatus = "READY" +) + +var AllFeedStatus = []FeedStatus{ + FeedStatusDraft, + FeedStatusReady, +} + +func (e FeedStatus) IsValid() bool { + switch e { + case FeedStatusDraft, FeedStatusReady: + return true + } + return false +} + +func (e FeedStatus) String() string { + return string(e) +} + +func (e *FeedStatus) UnmarshalGQL(v interface{}) error { + str, ok := v.(string) + if !ok { + return fmt.Errorf("enums must be strings") + } + + *e = FeedStatus(str) + if !e.IsValid() { + return fmt.Errorf("%s is not a valid FeedStatus", str) + } + return nil +} + +func (e FeedStatus) MarshalGQL(w io.Writer) { + fmt.Fprint(w, strconv.Quote(e.String())) +} + +type JobProposalStatus string + +const ( + JobProposalStatusProposed JobProposalStatus = "PROPOSED" + JobProposalStatusApproved JobProposalStatus = "APPROVED" + JobProposalStatusRejected JobProposalStatus = "REJECTED" + JobProposalStatusAccepted JobProposalStatus = "ACCEPTED" + JobProposalStatusPending JobProposalStatus = "PENDING" +) + +var AllJobProposalStatus = []JobProposalStatus{ + JobProposalStatusProposed, + JobProposalStatusApproved, + JobProposalStatusRejected, + JobProposalStatusAccepted, + JobProposalStatusPending, +} + +func (e JobProposalStatus) IsValid() bool { + switch e { + case JobProposalStatusProposed, JobProposalStatusApproved, JobProposalStatusRejected, JobProposalStatusAccepted, JobProposalStatusPending: + return true + } + return false +} + +func (e JobProposalStatus) String() string { + return string(e) +} + +func (e *JobProposalStatus) UnmarshalGQL(v interface{}) error { + str, ok := v.(string) + if !ok { + return fmt.Errorf("enums must be strings") + } + + *e = JobProposalStatus(str) + if !e.IsValid() { + return fmt.Errorf("%s is not a valid JobProposalStatus", str) + } + return nil +} + +func (e JobProposalStatus) MarshalGQL(w io.Writer) { + fmt.Fprint(w, strconv.Quote(e.String())) +} + +type JobStatus string + +const ( + JobStatusDraft JobStatus = "DRAFT" + JobStatusProposed JobStatus = "PROPOSED" + JobStatusApproved JobStatus = "APPROVED" + JobStatusRejected JobStatus = "REJECTED" + JobStatusCancelled JobStatus = "CANCELLED" + JobStatusDisabled JobStatus = "DISABLED" + JobStatusDeleted JobStatus = "DELETED" + JobStatusRevoked JobStatus = "REVOKED" +) + +var AllJobStatus = []JobStatus{ + JobStatusDraft, + JobStatusProposed, + JobStatusApproved, + JobStatusRejected, + JobStatusCancelled, + JobStatusDisabled, + JobStatusDeleted, + JobStatusRevoked, +} + +func (e JobStatus) IsValid() bool { + switch e { + case JobStatusDraft, JobStatusProposed, JobStatusApproved, JobStatusRejected, JobStatusCancelled, JobStatusDisabled, JobStatusDeleted, JobStatusRevoked: + return true + } + return false +} + +func (e JobStatus) String() string { + return string(e) +} + +func (e *JobStatus) UnmarshalGQL(v interface{}) error { + str, ok := v.(string) + if !ok { + return fmt.Errorf("enums must be strings") + } + + *e = JobStatus(str) + if !e.IsValid() { + return fmt.Errorf("%s is not a valid JobStatus", str) + } + return nil +} + +func (e JobStatus) MarshalGQL(w io.Writer) { + fmt.Fprint(w, strconv.Quote(e.String())) +} + +type JobType string + +const ( + JobTypeOffchainreporting JobType = "OFFCHAINREPORTING" + JobTypeOffchainreporting2 JobType = "OFFCHAINREPORTING2" + JobTypeBootstrap JobType = "BOOTSTRAP" + JobTypeWorkflow JobType = "WORKFLOW" +) + +var AllJobType = []JobType{ + JobTypeOffchainreporting, + JobTypeOffchainreporting2, + JobTypeBootstrap, + JobTypeWorkflow, +} + +func (e JobType) IsValid() bool { + switch e { + case JobTypeOffchainreporting, JobTypeOffchainreporting2, JobTypeBootstrap, JobTypeWorkflow: + return true + } + return false +} + +func (e JobType) String() string { + return string(e) +} + +func (e *JobType) UnmarshalGQL(v interface{}) error { + str, ok := v.(string) + if !ok { + return fmt.Errorf("enums must be strings") + } + + *e = JobType(str) + if !e.IsValid() { + return fmt.Errorf("%s is not a valid JobType", str) + } + return nil +} + +func (e JobType) MarshalGQL(w io.Writer) { + fmt.Fprint(w, strconv.Quote(e.String())) +} + +type NetworkStackStatus string + +const ( + NetworkStackStatusReady NetworkStackStatus = "READY" + NetworkStackStatusInProgress NetworkStackStatus = "IN_PROGRESS" +) + +var AllNetworkStackStatus = []NetworkStackStatus{ + NetworkStackStatusReady, + NetworkStackStatusInProgress, +} + +func (e NetworkStackStatus) IsValid() bool { + switch e { + case NetworkStackStatusReady, NetworkStackStatusInProgress: + return true + } + return false +} + +func (e NetworkStackStatus) String() string { + return string(e) +} + +func (e *NetworkStackStatus) UnmarshalGQL(v interface{}) error { + str, ok := v.(string) + if !ok { + return fmt.Errorf("enums must be strings") + } + + *e = NetworkStackStatus(str) + if !e.IsValid() { + return fmt.Errorf("%s is not a valid NetworkStackStatus", str) + } + return nil +} + +func (e NetworkStackStatus) MarshalGQL(w io.Writer) { + fmt.Fprint(w, strconv.Quote(e.String())) +} + +type NetworkStackType string + +const ( + NetworkStackTypeMain NetworkStackType = "MAIN" + NetworkStackTypeAdditional NetworkStackType = "ADDITIONAL" +) + +var AllNetworkStackType = []NetworkStackType{ + NetworkStackTypeMain, + NetworkStackTypeAdditional, +} + +func (e NetworkStackType) IsValid() bool { + switch e { + case NetworkStackTypeMain, NetworkStackTypeAdditional: + return true + } + return false +} + +func (e NetworkStackType) String() string { + return string(e) +} + +func (e *NetworkStackType) UnmarshalGQL(v interface{}) error { + str, ok := v.(string) + if !ok { + return fmt.Errorf("enums must be strings") + } + + *e = NetworkStackType(str) + if !e.IsValid() { + return fmt.Errorf("%s is not a valid NetworkStackType", str) + } + return nil +} + +func (e NetworkStackType) MarshalGQL(w io.Writer) { + fmt.Fprint(w, strconv.Quote(e.String())) +} + +type OCR2PluginType string + +const ( + OCR2PluginTypeMedian OCR2PluginType = "MEDIAN" + OCR2PluginTypeCcipCommit OCR2PluginType = "CCIP_COMMIT" + OCR2PluginTypeCcipExecute OCR2PluginType = "CCIP_EXECUTE" + OCR2PluginTypeCcipRebalancer OCR2PluginType = "CCIP_REBALANCER" + OCR2PluginTypeMercury OCR2PluginType = "MERCURY" +) + +var AllOCR2PluginType = []OCR2PluginType{ + OCR2PluginTypeMedian, + OCR2PluginTypeCcipCommit, + OCR2PluginTypeCcipExecute, + OCR2PluginTypeCcipRebalancer, + OCR2PluginTypeMercury, +} + +func (e OCR2PluginType) IsValid() bool { + switch e { + case OCR2PluginTypeMedian, OCR2PluginTypeCcipCommit, OCR2PluginTypeCcipExecute, OCR2PluginTypeCcipRebalancer, OCR2PluginTypeMercury: + return true + } + return false +} + +func (e OCR2PluginType) String() string { + return string(e) +} + +func (e *OCR2PluginType) UnmarshalGQL(v interface{}) error { + str, ok := v.(string) + if !ok { + return fmt.Errorf("enums must be strings") + } + + *e = OCR2PluginType(str) + if !e.IsValid() { + return fmt.Errorf("%s is not a valid OCR2PluginType", str) + } + return nil +} + +func (e OCR2PluginType) MarshalGQL(w io.Writer) { + fmt.Fprint(w, strconv.Quote(e.String())) +} + +type ProductType string + +const ( + ProductTypeDataFeeds ProductType = "DATA_FEEDS" + ProductTypeDataStreamsV02 ProductType = "DATA_STREAMS_V02" + ProductTypeDataStreamsV03 ProductType = "DATA_STREAMS_V03" + ProductTypeCcip ProductType = "CCIP" + ProductTypeWorkflow ProductType = "WORKFLOW" + ProductTypeOcr3Capability ProductType = "OCR3_CAPABILITY" +) + +var AllProductType = []ProductType{ + ProductTypeDataFeeds, + ProductTypeDataStreamsV02, + ProductTypeDataStreamsV03, + ProductTypeCcip, + ProductTypeWorkflow, + ProductTypeOcr3Capability, +} + +func (e ProductType) IsValid() bool { + switch e { + case ProductTypeDataFeeds, ProductTypeDataStreamsV02, ProductTypeDataStreamsV03, ProductTypeCcip, ProductTypeWorkflow, ProductTypeOcr3Capability: + return true + } + return false +} + +func (e ProductType) String() string { + return string(e) +} + +func (e *ProductType) UnmarshalGQL(v interface{}) error { + str, ok := v.(string) + if !ok { + return fmt.Errorf("enums must be strings") + } + + *e = ProductType(str) + if !e.IsValid() { + return fmt.Errorf("%s is not a valid ProductType", str) + } + return nil +} + +func (e ProductType) MarshalGQL(w io.Writer) { + fmt.Fprint(w, strconv.Quote(e.String())) +} + +type ReportSchemaVersion string + +const ( + ReportSchemaVersionBasic ReportSchemaVersion = "BASIC" + ReportSchemaVersionPremium ReportSchemaVersion = "PREMIUM" + ReportSchemaVersionBlockBased ReportSchemaVersion = "BLOCK_BASED" +) + +var AllReportSchemaVersion = []ReportSchemaVersion{ + ReportSchemaVersionBasic, + ReportSchemaVersionPremium, + ReportSchemaVersionBlockBased, +} + +func (e ReportSchemaVersion) IsValid() bool { + switch e { + case ReportSchemaVersionBasic, ReportSchemaVersionPremium, ReportSchemaVersionBlockBased: + return true + } + return false +} + +func (e ReportSchemaVersion) String() string { + return string(e) +} + +func (e *ReportSchemaVersion) UnmarshalGQL(v interface{}) error { + str, ok := v.(string) + if !ok { + return fmt.Errorf("enums must be strings") + } + + *e = ReportSchemaVersion(str) + if !e.IsValid() { + return fmt.Errorf("%s is not a valid ReportSchemaVersion", str) + } + return nil +} + +func (e ReportSchemaVersion) MarshalGQL(w io.Writer) { + fmt.Fprint(w, strconv.Quote(e.String())) +} + +type SelectorOp string + +const ( + SelectorOpEq SelectorOp = "EQ" + SelectorOpNotEq SelectorOp = "NOT_EQ" + SelectorOpIn SelectorOp = "IN" + SelectorOpNotIn SelectorOp = "NOT_IN" + SelectorOpExist SelectorOp = "EXIST" + SelectorOpNotExist SelectorOp = "NOT_EXIST" +) + +var AllSelectorOp = []SelectorOp{ + SelectorOpEq, + SelectorOpNotEq, + SelectorOpIn, + SelectorOpNotIn, + SelectorOpExist, + SelectorOpNotExist, +} + +func (e SelectorOp) IsValid() bool { + switch e { + case SelectorOpEq, SelectorOpNotEq, SelectorOpIn, SelectorOpNotIn, SelectorOpExist, SelectorOpNotExist: + return true + } + return false +} + +func (e SelectorOp) String() string { + return string(e) +} + +func (e *SelectorOp) UnmarshalGQL(v interface{}) error { + str, ok := v.(string) + if !ok { + return fmt.Errorf("enums must be strings") + } + + *e = SelectorOp(str) + if !e.IsValid() { + return fmt.Errorf("%s is not a valid SelectorOp", str) + } + return nil +} + +func (e SelectorOp) MarshalGQL(w io.Writer) { + fmt.Fprint(w, strconv.Quote(e.String())) +} + +type TaskRunStatus string + +const ( + TaskRunStatusInProgress TaskRunStatus = "IN_PROGRESS" + TaskRunStatusCompleted TaskRunStatus = "COMPLETED" + TaskRunStatusErrored TaskRunStatus = "ERRORED" +) + +var AllTaskRunStatus = []TaskRunStatus{ + TaskRunStatusInProgress, + TaskRunStatusCompleted, + TaskRunStatusErrored, +} + +func (e TaskRunStatus) IsValid() bool { + switch e { + case TaskRunStatusInProgress, TaskRunStatusCompleted, TaskRunStatusErrored: + return true + } + return false +} + +func (e TaskRunStatus) String() string { + return string(e) +} + +func (e *TaskRunStatus) UnmarshalGQL(v interface{}) error { + str, ok := v.(string) + if !ok { + return fmt.Errorf("enums must be strings") + } + + *e = TaskRunStatus(str) + if !e.IsValid() { + return fmt.Errorf("%s is not a valid TaskRunStatus", str) + } + return nil +} + +func (e TaskRunStatus) MarshalGQL(w io.Writer) { + fmt.Fprint(w, strconv.Quote(e.String())) +} + +type TokenPoolType string + +const ( + TokenPoolTypeLockRelease TokenPoolType = "LOCK_RELEASE" + TokenPoolTypeLockReleaseAndProxy TokenPoolType = "LOCK_RELEASE_AND_PROXY" + TokenPoolTypeBurnMint TokenPoolType = "BURN_MINT" + TokenPoolTypeBurnMintAndProxy TokenPoolType = "BURN_MINT_AND_PROXY" + TokenPoolTypeBurnFromMint TokenPoolType = "BURN_FROM_MINT" + TokenPoolTypeBurnWithFromMint TokenPoolType = "BURN_WITH_FROM_MINT" + TokenPoolTypeBurnWithFromMintAndProxy TokenPoolType = "BURN_WITH_FROM_MINT_AND_PROXY" + TokenPoolTypeUsdc TokenPoolType = "USDC" + TokenPoolTypeFeeTokenOnly TokenPoolType = "FEE_TOKEN_ONLY" +) + +var AllTokenPoolType = []TokenPoolType{ + TokenPoolTypeLockRelease, + TokenPoolTypeLockReleaseAndProxy, + TokenPoolTypeBurnMint, + TokenPoolTypeBurnMintAndProxy, + TokenPoolTypeBurnFromMint, + TokenPoolTypeBurnWithFromMint, + TokenPoolTypeBurnWithFromMintAndProxy, + TokenPoolTypeUsdc, + TokenPoolTypeFeeTokenOnly, +} + +func (e TokenPoolType) IsValid() bool { + switch e { + case TokenPoolTypeLockRelease, TokenPoolTypeLockReleaseAndProxy, TokenPoolTypeBurnMint, TokenPoolTypeBurnMintAndProxy, TokenPoolTypeBurnFromMint, TokenPoolTypeBurnWithFromMint, TokenPoolTypeBurnWithFromMintAndProxy, TokenPoolTypeUsdc, TokenPoolTypeFeeTokenOnly: + return true + } + return false +} + +func (e TokenPoolType) String() string { + return string(e) +} + +func (e *TokenPoolType) UnmarshalGQL(v interface{}) error { + str, ok := v.(string) + if !ok { + return fmt.Errorf("enums must be strings") + } + + *e = TokenPoolType(str) + if !e.IsValid() { + return fmt.Errorf("%s is not a valid TokenPoolType", str) + } + return nil +} + +func (e TokenPoolType) MarshalGQL(w io.Writer) { + fmt.Fprint(w, strconv.Quote(e.String())) +} + +type TokenPriceType string + +const ( + TokenPriceTypeFixed TokenPriceType = "FIXED" + TokenPriceTypeFeed TokenPriceType = "FEED" +) + +var AllTokenPriceType = []TokenPriceType{ + TokenPriceTypeFixed, + TokenPriceTypeFeed, +} + +func (e TokenPriceType) IsValid() bool { + switch e { + case TokenPriceTypeFixed, TokenPriceTypeFeed: + return true + } + return false +} + +func (e TokenPriceType) String() string { + return string(e) +} + +func (e *TokenPriceType) UnmarshalGQL(v interface{}) error { + str, ok := v.(string) + if !ok { + return fmt.Errorf("enums must be strings") + } + + *e = TokenPriceType(str) + if !e.IsValid() { + return fmt.Errorf("%s is not a valid TokenPriceType", str) + } + return nil +} + +func (e TokenPriceType) MarshalGQL(w io.Writer) { + fmt.Fprint(w, strconv.Quote(e.String())) +} + +type TransferOwnershipStatus string + +const ( + TransferOwnershipStatusNone TransferOwnershipStatus = "NONE" + TransferOwnershipStatusProcessingTransaction TransferOwnershipStatus = "PROCESSING_TRANSACTION" + TransferOwnershipStatusAwaitingConfirmation TransferOwnershipStatus = "AWAITING_CONFIRMATION" + TransferOwnershipStatusError TransferOwnershipStatus = "ERROR" +) + +var AllTransferOwnershipStatus = []TransferOwnershipStatus{ + TransferOwnershipStatusNone, + TransferOwnershipStatusProcessingTransaction, + TransferOwnershipStatusAwaitingConfirmation, + TransferOwnershipStatusError, +} + +func (e TransferOwnershipStatus) IsValid() bool { + switch e { + case TransferOwnershipStatusNone, TransferOwnershipStatusProcessingTransaction, TransferOwnershipStatusAwaitingConfirmation, TransferOwnershipStatusError: + return true + } + return false +} + +func (e TransferOwnershipStatus) String() string { + return string(e) +} + +func (e *TransferOwnershipStatus) UnmarshalGQL(v interface{}) error { + str, ok := v.(string) + if !ok { + return fmt.Errorf("enums must be strings") + } + + *e = TransferOwnershipStatus(str) + if !e.IsValid() { + return fmt.Errorf("%s is not a valid TransferOwnershipStatus", str) + } + return nil +} + +func (e TransferOwnershipStatus) MarshalGQL(w io.Writer) { + fmt.Fprint(w, strconv.Quote(e.String())) +} + +type UserRole string + +const ( + UserRoleViewer UserRole = "VIEWER" + UserRoleOps UserRole = "OPS" + UserRoleMaintainer UserRole = "MAINTAINER" + UserRoleAdmin UserRole = "ADMIN" + UserRoleFoundation UserRole = "FOUNDATION" + UserRoleDataProvider UserRole = "DATA_PROVIDER" + UserRoleCcipValidator UserRole = "CCIP_VALIDATOR" + UserRoleDataStreamsOps UserRole = "DATA_STREAMS_OPS" +) + +var AllUserRole = []UserRole{ + UserRoleViewer, + UserRoleOps, + UserRoleMaintainer, + UserRoleAdmin, + UserRoleFoundation, + UserRoleDataProvider, + UserRoleCcipValidator, + UserRoleDataStreamsOps, +} + +func (e UserRole) IsValid() bool { + switch e { + case UserRoleViewer, UserRoleOps, UserRoleMaintainer, UserRoleAdmin, UserRoleFoundation, UserRoleDataProvider, UserRoleCcipValidator, UserRoleDataStreamsOps: + return true + } + return false +} + +func (e UserRole) String() string { + return string(e) +} + +func (e *UserRole) UnmarshalGQL(v interface{}) error { + str, ok := v.(string) + if !ok { + return fmt.Errorf("enums must be strings") + } + + *e = UserRole(str) + if !e.IsValid() { + return fmt.Errorf("%s is not a valid UserRole", str) + } + return nil +} + +func (e UserRole) MarshalGQL(w io.Writer) { + fmt.Fprint(w, strconv.Quote(e.String())) +} + +type VaultType string + +const ( + VaultTypeEoa VaultType = "EOA" + VaultTypeSafe VaultType = "SAFE" + VaultTypeTimelock VaultType = "TIMELOCK" +) + +var AllVaultType = []VaultType{ + VaultTypeEoa, + VaultTypeSafe, + VaultTypeTimelock, +} + +func (e VaultType) IsValid() bool { + switch e { + case VaultTypeEoa, VaultTypeSafe, VaultTypeTimelock: + return true + } + return false +} + +func (e VaultType) String() string { + return string(e) +} + +func (e *VaultType) UnmarshalGQL(v interface{}) error { + str, ok := v.(string) + if !ok { + return fmt.Errorf("enums must be strings") + } + + *e = VaultType(str) + if !e.IsValid() { + return fmt.Errorf("%s is not a valid VaultType", str) + } + return nil +} + +func (e VaultType) MarshalGQL(w io.Writer) { + fmt.Fprint(w, strconv.Quote(e.String())) +} + +type VerificationStatus string + +const ( + VerificationStatusUnknown VerificationStatus = "UNKNOWN" + VerificationStatusSuccess VerificationStatus = "SUCCESS" + VerificationStatusPending VerificationStatus = "PENDING" + VerificationStatusError VerificationStatus = "ERROR" +) + +var AllVerificationStatus = []VerificationStatus{ + VerificationStatusUnknown, + VerificationStatusSuccess, + VerificationStatusPending, + VerificationStatusError, +} + +func (e VerificationStatus) IsValid() bool { + switch e { + case VerificationStatusUnknown, VerificationStatusSuccess, VerificationStatusPending, VerificationStatusError: + return true + } + return false +} + +func (e VerificationStatus) String() string { + return string(e) +} + +func (e *VerificationStatus) UnmarshalGQL(v interface{}) error { + str, ok := v.(string) + if !ok { + return fmt.Errorf("enums must be strings") + } + + *e = VerificationStatus(str) + if !e.IsValid() { + return fmt.Errorf("%s is not a valid VerificationStatus", str) + } + return nil +} + +func (e VerificationStatus) MarshalGQL(w io.Writer) { + fmt.Fprint(w, strconv.Quote(e.String())) +} + +type WebhookCallState string + +const ( + WebhookCallStatePending WebhookCallState = "PENDING" + WebhookCallStateSuccess WebhookCallState = "SUCCESS" + WebhookCallStateError WebhookCallState = "ERROR" + WebhookCallStateFailed WebhookCallState = "FAILED" +) + +var AllWebhookCallState = []WebhookCallState{ + WebhookCallStatePending, + WebhookCallStateSuccess, + WebhookCallStateError, + WebhookCallStateFailed, +} + +func (e WebhookCallState) IsValid() bool { + switch e { + case WebhookCallStatePending, WebhookCallStateSuccess, WebhookCallStateError, WebhookCallStateFailed: + return true + } + return false +} + +func (e WebhookCallState) String() string { + return string(e) +} + +func (e *WebhookCallState) UnmarshalGQL(v interface{}) error { + str, ok := v.(string) + if !ok { + return fmt.Errorf("enums must be strings") + } + + *e = WebhookCallState(str) + if !e.IsValid() { + return fmt.Errorf("%s is not a valid WebhookCallState", str) + } + return nil +} + +func (e WebhookCallState) MarshalGQL(w io.Writer) { + fmt.Fprint(w, strconv.Quote(e.String())) +} + +type WorkflowRunStatus string + +const ( + WorkflowRunStatusPending WorkflowRunStatus = "PENDING" + WorkflowRunStatusInProgress WorkflowRunStatus = "IN_PROGRESS" + WorkflowRunStatusCompleted WorkflowRunStatus = "COMPLETED" + WorkflowRunStatusErrored WorkflowRunStatus = "ERRORED" +) + +var AllWorkflowRunStatus = []WorkflowRunStatus{ + WorkflowRunStatusPending, + WorkflowRunStatusInProgress, + WorkflowRunStatusCompleted, + WorkflowRunStatusErrored, +} + +func (e WorkflowRunStatus) IsValid() bool { + switch e { + case WorkflowRunStatusPending, WorkflowRunStatusInProgress, WorkflowRunStatusCompleted, WorkflowRunStatusErrored: + return true + } + return false +} + +func (e WorkflowRunStatus) String() string { + return string(e) +} + +func (e *WorkflowRunStatus) UnmarshalGQL(v interface{}) error { + str, ok := v.(string) + if !ok { + return fmt.Errorf("enums must be strings") + } + + *e = WorkflowRunStatus(str) + if !e.IsValid() { + return fmt.Errorf("%s is not a valid WorkflowRunStatus", str) + } + return nil +} + +func (e WorkflowRunStatus) MarshalGQL(w io.Writer) { + fmt.Fprint(w, strconv.Quote(e.String())) +} + +type WorkflowType string + +const ( + WorkflowTypeGeneric WorkflowType = "GENERIC" +) + +var AllWorkflowType = []WorkflowType{ + WorkflowTypeGeneric, +} + +func (e WorkflowType) IsValid() bool { + switch e { + case WorkflowTypeGeneric: + return true + } + return false +} + +func (e WorkflowType) String() string { + return string(e) +} + +func (e *WorkflowType) UnmarshalGQL(v interface{}) error { + str, ok := v.(string) + if !ok { + return fmt.Errorf("enums must be strings") + } + + *e = WorkflowType(str) + if !e.IsValid() { + return fmt.Errorf("%s is not a valid WorkflowType", str) + } + return nil +} + +func (e WorkflowType) MarshalGQL(w io.Writer) { + fmt.Fprint(w, strconv.Quote(e.String())) +} diff --git a/deployment/environment/clo/offchain_client_impl.go b/deployment/environment/clo/offchain_client_impl.go new file mode 100644 index 00000000000..16c50126398 --- /dev/null +++ b/deployment/environment/clo/offchain_client_impl.go @@ -0,0 +1,265 @@ +package clo + +import ( + "context" + "fmt" + "slices" + "strings" + + "go.uber.org/zap" + "google.golang.org/grpc" + + "github.com/smartcontractkit/chainlink-common/pkg/logger" + csav1 "github.com/smartcontractkit/chainlink-protos/job-distributor/v1/csa" + jobv1 "github.com/smartcontractkit/chainlink-protos/job-distributor/v1/job" + nodev1 "github.com/smartcontractkit/chainlink-protos/job-distributor/v1/node" + "github.com/smartcontractkit/chainlink-protos/job-distributor/v1/shared/ptypes" + "github.com/smartcontractkit/chainlink/deployment/environment/clo/models" +) + +type JobClient struct { + NodeOperators []*models.NodeOperator `json:"nodeOperators"` + nodesByID map[string]*models.Node + lggr logger.Logger +} + +func (j JobClient) UpdateJob(ctx context.Context, in *jobv1.UpdateJobRequest, opts ...grpc.CallOption) (*jobv1.UpdateJobResponse, error) { + //TODO CCIP-3108 implement me + panic("implement me") +} + +func (j JobClient) DisableNode(ctx context.Context, in *nodev1.DisableNodeRequest, opts ...grpc.CallOption) (*nodev1.DisableNodeResponse, error) { + //TODO CCIP-3108 implement me + panic("implement me") +} + +func (j JobClient) EnableNode(ctx context.Context, in *nodev1.EnableNodeRequest, opts ...grpc.CallOption) (*nodev1.EnableNodeResponse, error) { + //TODO CCIP-3108 implement me + panic("implement me") +} + +func (j JobClient) RegisterNode(ctx context.Context, in *nodev1.RegisterNodeRequest, opts ...grpc.CallOption) (*nodev1.RegisterNodeResponse, error) { + //TODO implement me + panic("implement me") +} + +func (j JobClient) UpdateNode(ctx context.Context, in *nodev1.UpdateNodeRequest, opts ...grpc.CallOption) (*nodev1.UpdateNodeResponse, error) { + //TODO CCIP-3108 implement me + panic("implement me") +} + +func (j JobClient) GetKeypair(ctx context.Context, in *csav1.GetKeypairRequest, opts ...grpc.CallOption) (*csav1.GetKeypairResponse, error) { + //TODO implement me + panic("implement me") +} + +func (j JobClient) ListKeypairs(ctx context.Context, in *csav1.ListKeypairsRequest, opts ...grpc.CallOption) (*csav1.ListKeypairsResponse, error) { + //TODO CCIP-3108 implement me + panic("implement me") +} + +func (j JobClient) GetNode(ctx context.Context, in *nodev1.GetNodeRequest, opts ...grpc.CallOption) (*nodev1.GetNodeResponse, error) { + //TODO CCIP-3108 implement me + panic("implement me") +} + +func (j JobClient) ListNodes(ctx context.Context, in *nodev1.ListNodesRequest, opts ...grpc.CallOption) (*nodev1.ListNodesResponse, error) { + include := func(node *nodev1.Node) bool { + if in.Filter == nil { + return true + } + if len(in.Filter.Ids) > 0 { + idx := slices.IndexFunc(in.Filter.Ids, func(id string) bool { + return node.Id == id + }) + if idx < 0 { + return false + } + } + for _, selector := range in.Filter.Selectors { + idx := slices.IndexFunc(node.Labels, func(label *ptypes.Label) bool { + return label.Key == selector.Key + }) + if idx < 0 { + return false + } + label := node.Labels[idx] + + switch selector.Op { + case ptypes.SelectorOp_IN: + values := strings.Split(*selector.Value, ",") + found := slices.Contains(values, *label.Value) + if !found { + return false + } + default: + panic("unimplemented selector") + } + } + return true + } + var nodes []*nodev1.Node + for _, nop := range j.NodeOperators { + for _, n := range nop.Nodes { + p2pId, err := NodeP2PId(n) + if err != nil { + return nil, fmt.Errorf("failed to get p2p id for node %s: %w", n.ID, err) + } + node := &nodev1.Node{ + Id: n.ID, + Name: n.Name, + PublicKey: *n.PublicKey, + IsEnabled: n.Enabled, + IsConnected: n.Connected, + Labels: []*ptypes.Label{ + { + Key: "p2p_id", + Value: &p2pId, // here n.ID is also peer ID + }, + }, + } + if include(node) { + nodes = append(nodes, node) + } + } + } + return &nodev1.ListNodesResponse{ + Nodes: nodes, + }, nil +} + +func (j JobClient) ListNodeChainConfigs(ctx context.Context, in *nodev1.ListNodeChainConfigsRequest, opts ...grpc.CallOption) (*nodev1.ListNodeChainConfigsResponse, error) { + + resp := &nodev1.ListNodeChainConfigsResponse{ + ChainConfigs: make([]*nodev1.ChainConfig, 0), + } + // no filter, return all + if in.Filter == nil || len(in.Filter.NodeIds) == 0 { + for _, n := range j.nodesByID { + ccfg := cloNodeToChainConfigs(n) + resp.ChainConfigs = append(resp.ChainConfigs, ccfg...) + } + } else { + for _, want := range in.Filter.NodeIds { + n, ok := j.nodesByID[want] + if !ok { + j.lggr.Warn("node not found", zap.String("node_id", want)) + continue + } + ccfg := cloNodeToChainConfigs(n) + resp.ChainConfigs = append(resp.ChainConfigs, ccfg...) + } + } + return resp, nil + +} + +func (j JobClient) GetJob(ctx context.Context, in *jobv1.GetJobRequest, opts ...grpc.CallOption) (*jobv1.GetJobResponse, error) { + //TODO CCIP-3108 implement me + panic("implement me") +} + +func (j JobClient) GetProposal(ctx context.Context, in *jobv1.GetProposalRequest, opts ...grpc.CallOption) (*jobv1.GetProposalResponse, error) { + //TODO CCIP-3108 implement me + panic("implement me") +} + +func (j JobClient) ListJobs(ctx context.Context, in *jobv1.ListJobsRequest, opts ...grpc.CallOption) (*jobv1.ListJobsResponse, error) { + //TODO CCIP-3108 implement me + panic("implement me") +} + +func (j JobClient) ListProposals(ctx context.Context, in *jobv1.ListProposalsRequest, opts ...grpc.CallOption) (*jobv1.ListProposalsResponse, error) { + //TODO CCIP-3108 implement me + panic("implement me") +} + +func (j JobClient) ProposeJob(ctx context.Context, in *jobv1.ProposeJobRequest, opts ...grpc.CallOption) (*jobv1.ProposeJobResponse, error) { + panic("implement me") + +} + +func (j JobClient) RevokeJob(ctx context.Context, in *jobv1.RevokeJobRequest, opts ...grpc.CallOption) (*jobv1.RevokeJobResponse, error) { + //TODO CCIP-3108 implement me + panic("implement me") +} + +func (j JobClient) DeleteJob(ctx context.Context, in *jobv1.DeleteJobRequest, opts ...grpc.CallOption) (*jobv1.DeleteJobResponse, error) { + //TODO CCIP-3108 implement me + panic("implement me") +} + +type GetNodeOperatorsResponse struct { + NodeOperators []*models.NodeOperator `json:"nodeOperators"` +} + +type JobClientConfig struct { + Nops []*models.NodeOperator +} + +func NewJobClient(lggr logger.Logger, cfg JobClientConfig) *JobClient { + + c := &JobClient{ + NodeOperators: cfg.Nops, + nodesByID: make(map[string]*models.Node), + lggr: lggr, + } + for _, nop := range c.NodeOperators { + for _, n := range nop.Nodes { + node := n + c.nodesByID[n.ID] = node // maybe should use the public key instead? + } + } + return c +} + +func cloNodeToChainConfigs(n *models.Node) []*nodev1.ChainConfig { + out := make([]*nodev1.ChainConfig, 0) + for _, ccfg := range n.ChainConfigs { + out = append(out, cloChainCfgToJDChainCfg(ccfg)) + } + return out +} + +func cloChainCfgToJDChainCfg(ccfg *models.NodeChainConfig) *nodev1.ChainConfig { + var ctype nodev1.ChainType + switch ccfg.Network.ChainType { + case models.ChainTypeEvm: + ctype = nodev1.ChainType_CHAIN_TYPE_EVM + case models.ChainTypeSolana: + ctype = nodev1.ChainType_CHAIN_TYPE_SOLANA + case models.ChainTypeStarknet: + ctype = nodev1.ChainType_CHAIN_TYPE_STARKNET + case models.ChainTypeAptos: + ctype = nodev1.ChainType_CHAIN_TYPE_APTOS + default: + panic(fmt.Sprintf("Unsupported chain family %v", ccfg.Network.ChainType)) + } + + return &nodev1.ChainConfig{ + Chain: &nodev1.Chain{ + Id: ccfg.Network.ChainID, + Type: ctype, + }, + AccountAddress: ccfg.AccountAddress, + AdminAddress: ccfg.AdminAddress, + // only care about ocr2 for now + Ocr2Config: &nodev1.OCR2Config{ + Enabled: ccfg.Ocr2Config.Enabled, + IsBootstrap: ccfg.Ocr2Config.IsBootstrap, + P2PKeyBundle: &nodev1.OCR2Config_P2PKeyBundle{ + PeerId: ccfg.Ocr2Config.P2pKeyBundle.PeerID, + PublicKey: ccfg.Ocr2Config.P2pKeyBundle.PublicKey, + }, + OcrKeyBundle: &nodev1.OCR2Config_OCRKeyBundle{ + BundleId: ccfg.Ocr2Config.OcrKeyBundle.BundleID, + ConfigPublicKey: ccfg.Ocr2Config.OcrKeyBundle.ConfigPublicKey, + OffchainPublicKey: ccfg.Ocr2Config.OcrKeyBundle.OffchainPublicKey, + OnchainSigningAddress: ccfg.Ocr2Config.OcrKeyBundle.OnchainSigningAddress, + }, + // TODO: the clo cli does not serialize this field, so it will always be nil + //Multiaddr: *ccfg.Ocr2Config.Multiaddr, + //ForwarderAddress: ccfg.Ocr2Config.ForwarderAddress, + }, + } +} diff --git a/deployment/environment/clo/offchain_client_impl_test.go b/deployment/environment/clo/offchain_client_impl_test.go new file mode 100644 index 00000000000..f2d6fcf6f41 --- /dev/null +++ b/deployment/environment/clo/offchain_client_impl_test.go @@ -0,0 +1,677 @@ +package clo_test + +import ( + "context" + "encoding/json" + "reflect" + "testing" + + "github.com/test-go/testify/require" + "google.golang.org/grpc" + + nodev1 "github.com/smartcontractkit/chainlink-protos/job-distributor/v1/node" + "github.com/smartcontractkit/chainlink-protos/job-distributor/v1/shared/ptypes" + "github.com/smartcontractkit/chainlink/deployment/environment/clo" + "github.com/smartcontractkit/chainlink/deployment/environment/clo/models" + "github.com/smartcontractkit/chainlink/v2/core/logger" +) + +var ( + p2pid_1 = "p2p_12D3KooWBCMCCZZ8x57AXvJvpCujqhZzTjWXbReaRE7807807807" + p2pid_2 = "p2p_12D3KooWBCMCCZZ8x57AXvJvpCujqhZzTjWXbReaRE6868686868" + p2pid_3 = "p2p_12D3KooWBCMCCZZ8x57AXvJvpCujqhZzTjWXbReaRE9999999999" + p2pid_4 = "p2p_12D3KooWBCMCCZZ8x57AXvJvpCujqhZzTjWXbReaRE1000000000" +) + +var testNops = ` +[ + { + "id": "67", + "name": "Chainlink Keystone Node Operator 9", + "nodes": [ + { + "id": "780", + "name": "Chainlink Sepolia Prod Keystone One 9", + "publicKey": "412dc6fe48ea4e34baaa77da2e3b032d39b938597b6f3d61fe7ed183a827a431", + "connected": true, + "chainConfigs": [ + { + "network": { + "id": "140", + "chainID": "421614", + "chainType": "EVM" + }, + "ocr2Config": { + "p2pKeyBundle": { + "peerID": "p2p_12D3KooWBCMCCZZ8x57AXvJvpCujqhZzTjWXbReaRE7807807807" + } + } + } + ], + "supportedProducts": [ + "WORKFLOW", + "OCR3_CAPABILITY" + ] + } + ], + "createdAt": "2024-08-14T19:00:07.113658Z" + }, + { + "id": "68", + "name": "Chainlink Keystone Node Operator 8", + "nodes": [ + { + "id": "781", + "name": "Chainlink Sepolia Prod Keystone One 8", + "publicKey": "1141dd1e46797ced9b0fbad49115f18507f6f6e6e3cc86e7e5ba169e58645adc", + "connected": true, + "chainConfigs": [ + { + "network": { + "id": "140", + "chainID": "421614", + "chainType": "EVM" + }, + "ocr2Config": { + "p2pKeyBundle": { + "peerID": "p2p_12D3KooWBCMCCZZ8x57AXvJvpCujqhZzTjWXbReaRE6868686868" + } + } + } + ], + "supportedProducts": [ + "WORKFLOW", + "OCR3_CAPABILITY" + ] + } + ], + "createdAt": "2024-08-14T20:26:37.622463Z" + }, + { + "id": "999", + "name": "Chainlink Keystone Node Operator 100", + "nodes": [ + { + "id": "999", + "name": "Chainlink Sepolia Prod Keystone One 999", + "publicKey": "9991dd1e46797ced9b0fbad49115f18507f6f6e6e3cc86e7e5ba169e58999999", + "connected": true, + "chainConfigs": [ + { + "network": { + "id": "140", + "chainID": "421614", + "chainType": "EVM" + }, + "ocr2Config": { + "p2pKeyBundle": { + "peerID": "p2p_12D3KooWBCMCCZZ8x57AXvJvpCujqhZzTjWXbReaRE9999999999" + } + } + } + ], + "supportedProducts": [ + "WORKFLOW", + "OCR3_CAPABILITY" + ] + }, + { + "id": "1000", + "name": "Chainlink Sepolia Prod Keystone One 1000", + "publicKey": "1000101e46797ced9b0fbad49115f18507f6f6e6e3cc86e7e5ba169e58641000", + "connected": true, + "chainConfigs": [ + { + "network": { + "id": "140", + "chainID": "421614", + "chainType": "EVM" + }, + "ocr2Config": { + "p2pKeyBundle": { + "peerID": "p2p_12D3KooWBCMCCZZ8x57AXvJvpCujqhZzTjWXbReaRE1000000000" + } + } + } + ], + "supportedProducts": [ + "WORKFLOW", + "OCR3_CAPABILITY" + ] + } + ], + "createdAt": "2024-08-14T20:26:37.622463Z" + } +] +` + +func parseTestNops(t *testing.T) []*models.NodeOperator { + t.Helper() + var out []*models.NodeOperator + err := json.Unmarshal([]byte(testNops), &out) + require.NoError(t, err) + require.Len(t, out, 3, "wrong number of nops") + return out +} +func TestJobClient_ListNodes(t *testing.T) { + lggr := logger.TestLogger(t) + nops := parseTestNops(t) + + type fields struct { + NodeOperators []*models.NodeOperator + RemapNodeIDsToPeerIDs bool + } + type args struct { + ctx context.Context + in *nodev1.ListNodesRequest + opts []grpc.CallOption + } + tests := []struct { + name string + fields fields + args args + want *nodev1.ListNodesResponse + wantErr bool + }{ + { + name: "empty", + fields: fields{ + NodeOperators: make([]*models.NodeOperator, 0), + }, + args: args{ + ctx: context.Background(), + in: &nodev1.ListNodesRequest{}, + }, + want: &nodev1.ListNodesResponse{}, + }, + { + name: "one node from one nop", + fields: fields{ + NodeOperators: nops[0:1], + }, + args: args{ + ctx: context.Background(), + in: &nodev1.ListNodesRequest{}, + }, + want: &nodev1.ListNodesResponse{ + Nodes: []*nodev1.Node{ + { + Id: "780", + Name: "Chainlink Sepolia Prod Keystone One 9", + PublicKey: "412dc6fe48ea4e34baaa77da2e3b032d39b938597b6f3d61fe7ed183a827a431", + IsConnected: true, + Labels: []*ptypes.Label{ + { + Key: "p2p_id", + Value: &p2pid_1, + }, + }, + }, + }, + }, + }, + { + name: "two nops each with one node", + fields: fields{ + NodeOperators: nops[0:2], + }, + args: args{ + ctx: context.Background(), + in: &nodev1.ListNodesRequest{}, + }, + want: &nodev1.ListNodesResponse{ + Nodes: []*nodev1.Node{ + { + Id: "780", + Name: "Chainlink Sepolia Prod Keystone One 9", + PublicKey: "412dc6fe48ea4e34baaa77da2e3b032d39b938597b6f3d61fe7ed183a827a431", + IsConnected: true, + Labels: []*ptypes.Label{ + { + Key: "p2p_id", + Value: &p2pid_1, + }, + }, + }, + { + Id: "781", + Name: "Chainlink Sepolia Prod Keystone One 8", + PublicKey: "1141dd1e46797ced9b0fbad49115f18507f6f6e6e3cc86e7e5ba169e58645adc", + IsConnected: true, + Labels: []*ptypes.Label{ + { + Key: "p2p_id", + Value: &p2pid_2, + }, + }, + }, + }, + }, + }, + { + name: "two nodes from one nop", + fields: fields{ + NodeOperators: nops[2:3], + }, + args: args{ + ctx: context.Background(), + in: &nodev1.ListNodesRequest{}, + }, + want: &nodev1.ListNodesResponse{ + Nodes: []*nodev1.Node{ + { + Id: "999", + Name: "Chainlink Sepolia Prod Keystone One 999", + PublicKey: "9991dd1e46797ced9b0fbad49115f18507f6f6e6e3cc86e7e5ba169e58999999", + IsConnected: true, + Labels: []*ptypes.Label{ + { + Key: "p2p_id", + Value: &p2pid_3, + }, + }, + }, + { + Id: "1000", + Name: "Chainlink Sepolia Prod Keystone One 1000", + PublicKey: "1000101e46797ced9b0fbad49115f18507f6f6e6e3cc86e7e5ba169e58641000", + IsConnected: true, + Labels: []*ptypes.Label{ + { + Key: "p2p_id", + Value: &p2pid_4, + }, + }, + }, + }, + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + j := clo.NewJobClient(lggr, clo.JobClientConfig{Nops: tt.fields.NodeOperators}) + + got, err := j.ListNodes(tt.args.ctx, tt.args.in, tt.args.opts...) + if (err != nil) != tt.wantErr { + t.Errorf("JobClient.ListNodes() error = %v, wantErr %v", err, tt.wantErr) + return + } + if !reflect.DeepEqual(got, tt.want) { + t.Errorf("JobClient.ListNodes() = %v, want %v", got, tt.want) + } + }) + } +} + +var testNopsWithChainConfigs = ` +[ + { + "id": "67", + "keys": [ + "keystone-09" + ], + "name": "Chainlink Keystone Node Operator 9", + "metadata": { + "nodeCount": 1, + "jobCount": 4 + }, + "nodes": [ + { + "id": "780", + "name": "Chainlink Sepolia Prod Keystone One 9", + "publicKey": "412dc6fe48ea4e34baaa77da2e3b032d39b938597b6f3d61fe7ed183a827a431", + "chainConfigs": [ + { + "network": { + "id": "140", + "chainID": "421614", + "chainType": "EVM", + "name": "Arbitrum Testnet (Sepolia)" + }, + "accountAddress": "0xbA8E21dFaa0501fCD43146d0b5F21c2B8E0eEdfB", + "adminAddress": "0x0000000000000000000000000000000000000000", + "ocr1Config": { + "p2pKeyBundle": {}, + "ocrKeyBundle": {} + }, + "ocr2Config": { + "enabled": true, + "p2pKeyBundle": { + "peerID": "p2p_12D3KooWBCMCCZZ8x57AXvJvpCujqhZzTjWXbReaRE8TxNr5dM4U", + "publicKey": "147d5cc651819b093cd2fdff9760f0f0f77b7ef7798d9e24fc6a350b7300e5d9" + }, + "ocrKeyBundle": { + "bundleID": "1c28e76d180d1ed1524e61845fa58a384415de7e51017edf1f8c553e28357772", + "configPublicKey": "09fced0207611ed618bf0759ab128d9797e15b18e46436be1a56a91e4043ec0e", + "offchainPublicKey": "c805572b813a072067eab2087ddbee8aa719090e12890b15c01094f0d3f74a5f", + "onchainSigningAddress": "679296b7c1eb4948efcc87efc550940a182e610c" + }, + "plugins": {} + } + }, + { + "network": { + "id": "129", + "chainID": "11155111", + "chainType": "EVM", + "name": "Ethereum Testnet (Sepolia)" + }, + "accountAddress": "0x0b04cE574E80Da73191Ec141c0016a54A6404056", + "adminAddress": "0x0000000000000000000000000000000000000000", + "ocr1Config": { + "p2pKeyBundle": {}, + "ocrKeyBundle": {} + }, + "ocr2Config": { + "enabled": true, + "p2pKeyBundle": { + "peerID": "p2p_12D3KooWBCMCCZZ8x57AXvJvpCujqhZzTjWXbReaRE8TxNr5dM4U", + "publicKey": "147d5cc651819b093cd2fdff9760f0f0f77b7ef7798d9e24fc6a350b7300e5d9" + }, + "ocrKeyBundle": { + "bundleID": "1c28e76d180d1ed1524e61845fa58a384415de7e51017edf1f8c553e28357772", + "configPublicKey": "09fced0207611ed618bf0759ab128d9797e15b18e46436be1a56a91e4043ec0e", + "offchainPublicKey": "c805572b813a072067eab2087ddbee8aa719090e12890b15c01094f0d3f74a5f", + "onchainSigningAddress": "679296b7c1eb4948efcc87efc550940a182e610c" + }, + "plugins": {} + } + } + ], + "connected": true, + "supportedProducts": [ + "WORKFLOW", + "OCR3_CAPABILITY" + ], + "categories": [ + { + "id": "11", + "name": "Keystone" + } + ] + } + ], + "createdAt": "2024-08-14T19:00:07.113658Z" + }, + { + "id": "68", + "keys": [ + "keystone-08" + ], + "name": "Chainlink Keystone Node Operator 8", + "metadata": { + "nodeCount": 1, + "jobCount": 4 + }, + "nodes": [ + { + "id": "781", + "name": "Chainlink Sepolia Prod Keystone One 8", + "publicKey": "1141dd1e46797ced9b0fbad49115f18507f6f6e6e3cc86e7e5ba169e58645adc", + "chainConfigs": [ + { + "network": { + "id": "140", + "chainID": "421614", + "chainType": "EVM", + "name": "Arbitrum Testnet (Sepolia)" + }, + "accountAddress": "0xEa4bC3638660D78Da56f39f6680dCDD0cEAaD2c6", + "adminAddress": "0x0000000000000000000000000000000000000000", + "ocr1Config": { + "p2pKeyBundle": {}, + "ocrKeyBundle": {} + }, + "ocr2Config": { + "enabled": true, + "p2pKeyBundle": { + "peerID": "p2p_12D3KooWAUagqMycsro27kFznSQRHbhfCBLx8nKD4ptTiUGDe38c", + "publicKey": "09ca39cd924653c72fbb0e458b629c3efebdad3e29e7cd0b5760754d919ed829" + }, + "ocrKeyBundle": { + "bundleID": "be0d639de3ae3cbeaa31ca369514f748ba1d271145cba6796bcc12aace2f64c3", + "configPublicKey": "e3d4d7a7372a3b1110db0290ab3649eb5fbb0daf6cf3ae02cfe5f367700d9264", + "offchainPublicKey": "ad08c2a5878cada53521f4e2bb449f191ccca7899246721a0deeea19f7b83f70", + "onchainSigningAddress": "8c2aa1e6fad88a6006dfb116eb866cbad2910314" + }, + "plugins": {} + } + }, + { + "network": { + "id": "129", + "chainID": "11155111", + "chainType": "EVM", + "name": "Ethereum Testnet (Sepolia)" + }, + "accountAddress": "0x31B179dcF8f9036C30f04bE578793e51bF14A39E", + "adminAddress": "0x0000000000000000000000000000000000000000", + "ocr1Config": { + "p2pKeyBundle": {}, + "ocrKeyBundle": {} + }, + "ocr2Config": { + "enabled": true, + "p2pKeyBundle": { + "peerID": "p2p_12D3KooWAUagqMycsro27kFznSQRHbhfCBLx8nKD4ptTiUGDe38c", + "publicKey": "09ca39cd924653c72fbb0e458b629c3efebdad3e29e7cd0b5760754d919ed829" + }, + "ocrKeyBundle": { + "bundleID": "be0d639de3ae3cbeaa31ca369514f748ba1d271145cba6796bcc12aace2f64c3", + "configPublicKey": "e3d4d7a7372a3b1110db0290ab3649eb5fbb0daf6cf3ae02cfe5f367700d9264", + "offchainPublicKey": "ad08c2a5878cada53521f4e2bb449f191ccca7899246721a0deeea19f7b83f70", + "onchainSigningAddress": "8c2aa1e6fad88a6006dfb116eb866cbad2910314" + }, + "plugins": {} + } + } + ], + "connected": true, + "supportedProducts": [ + "WORKFLOW", + "OCR3_CAPABILITY" + ], + "categories": [ + { + "id": "11", + "name": "Keystone" + } + ] + } + ], + "createdAt": "2024-08-14T20:26:37.622463Z" + } +]` + +func TestJobClient_ListNodeChainConfigs(t *testing.T) { + nops := parseTestNopsWithChainConfigs(t) + lggr := logger.TestLogger(t) + type fields struct { + NodeOperators []*models.NodeOperator + } + type args struct { + ctx context.Context + in *nodev1.ListNodeChainConfigsRequest + opts []grpc.CallOption + } + tests := []struct { + name string + fields fields + args args + want *nodev1.ListNodeChainConfigsResponse + wantErr bool + }{ + { + name: "empty", + fields: fields{ + NodeOperators: make([]*models.NodeOperator, 0), + }, + args: args{ + ctx: context.Background(), + in: &nodev1.ListNodeChainConfigsRequest{}, + }, + want: &nodev1.ListNodeChainConfigsResponse{ + ChainConfigs: make([]*nodev1.ChainConfig, 0), + }, + }, + + { + name: "no matching nodes", + fields: fields{ + NodeOperators: nops, + }, + args: args{ + ctx: context.Background(), + in: &nodev1.ListNodeChainConfigsRequest{ + Filter: &nodev1.ListNodeChainConfigsRequest_Filter{ + NodeIds: []string{"not-a-node-id"}, + }, + }, + }, + want: &nodev1.ListNodeChainConfigsResponse{ + ChainConfigs: make([]*nodev1.ChainConfig, 0), + }, + }, + + { + name: "one nop with one node that has two chain configs", + fields: fields{ + NodeOperators: nops[0:1], + }, + args: args{ + ctx: context.Background(), + in: &nodev1.ListNodeChainConfigsRequest{}, + }, + want: &nodev1.ListNodeChainConfigsResponse{ + ChainConfigs: []*nodev1.ChainConfig{ + { + Chain: &nodev1.Chain{ + Id: "421614", + Type: nodev1.ChainType_CHAIN_TYPE_EVM, + }, + AccountAddress: "0xbA8E21dFaa0501fCD43146d0b5F21c2B8E0eEdfB", + AdminAddress: "0x0000000000000000000000000000000000000000", + Ocr2Config: &nodev1.OCR2Config{ + Enabled: true, + P2PKeyBundle: &nodev1.OCR2Config_P2PKeyBundle{ + PeerId: "p2p_12D3KooWBCMCCZZ8x57AXvJvpCujqhZzTjWXbReaRE8TxNr5dM4U", + PublicKey: "147d5cc651819b093cd2fdff9760f0f0f77b7ef7798d9e24fc6a350b7300e5d9", + }, + OcrKeyBundle: &nodev1.OCR2Config_OCRKeyBundle{ + BundleId: "1c28e76d180d1ed1524e61845fa58a384415de7e51017edf1f8c553e28357772", + ConfigPublicKey: "09fced0207611ed618bf0759ab128d9797e15b18e46436be1a56a91e4043ec0e", + OffchainPublicKey: "c805572b813a072067eab2087ddbee8aa719090e12890b15c01094f0d3f74a5f", + OnchainSigningAddress: "679296b7c1eb4948efcc87efc550940a182e610c", + }, + }, + }, + { + Chain: &nodev1.Chain{ + Id: "11155111", + Type: nodev1.ChainType_CHAIN_TYPE_EVM, + }, + AccountAddress: "0x0b04cE574E80Da73191Ec141c0016a54A6404056", + AdminAddress: "0x0000000000000000000000000000000000000000", + Ocr2Config: &nodev1.OCR2Config{ + Enabled: true, + P2PKeyBundle: &nodev1.OCR2Config_P2PKeyBundle{ + PeerId: "p2p_12D3KooWBCMCCZZ8x57AXvJvpCujqhZzTjWXbReaRE8TxNr5dM4U", + PublicKey: "147d5cc651819b093cd2fdff9760f0f0f77b7ef7798d9e24fc6a350b7300e5d9", + }, + OcrKeyBundle: &nodev1.OCR2Config_OCRKeyBundle{ + BundleId: "1c28e76d180d1ed1524e61845fa58a384415de7e51017edf1f8c553e28357772", + ConfigPublicKey: "09fced0207611ed618bf0759ab128d9797e15b18e46436be1a56a91e4043ec0e", + OffchainPublicKey: "c805572b813a072067eab2087ddbee8aa719090e12890b15c01094f0d3f74a5f", + OnchainSigningAddress: "679296b7c1eb4948efcc87efc550940a182e610c", + }, + }, + }, + }, + }, + }, + + { + name: "one nop with one node that has two chain configs matching the filter", + fields: fields{ + NodeOperators: nops, + }, + args: args{ + ctx: context.Background(), + in: &nodev1.ListNodeChainConfigsRequest{ + Filter: &nodev1.ListNodeChainConfigsRequest_Filter{ + NodeIds: []string{"780"}, + }, + }, + }, + want: &nodev1.ListNodeChainConfigsResponse{ + ChainConfigs: []*nodev1.ChainConfig{ + { + Chain: &nodev1.Chain{ + Id: "421614", + Type: nodev1.ChainType_CHAIN_TYPE_EVM, + }, + AccountAddress: "0xbA8E21dFaa0501fCD43146d0b5F21c2B8E0eEdfB", + AdminAddress: "0x0000000000000000000000000000000000000000", + Ocr2Config: &nodev1.OCR2Config{ + Enabled: true, + P2PKeyBundle: &nodev1.OCR2Config_P2PKeyBundle{ + PeerId: "p2p_12D3KooWBCMCCZZ8x57AXvJvpCujqhZzTjWXbReaRE8TxNr5dM4U", + PublicKey: "147d5cc651819b093cd2fdff9760f0f0f77b7ef7798d9e24fc6a350b7300e5d9", + }, + OcrKeyBundle: &nodev1.OCR2Config_OCRKeyBundle{ + BundleId: "1c28e76d180d1ed1524e61845fa58a384415de7e51017edf1f8c553e28357772", + ConfigPublicKey: "09fced0207611ed618bf0759ab128d9797e15b18e46436be1a56a91e4043ec0e", + OffchainPublicKey: "c805572b813a072067eab2087ddbee8aa719090e12890b15c01094f0d3f74a5f", + OnchainSigningAddress: "679296b7c1eb4948efcc87efc550940a182e610c", + }, + }, + }, + { + Chain: &nodev1.Chain{ + Id: "11155111", + Type: nodev1.ChainType_CHAIN_TYPE_EVM, + }, + AccountAddress: "0x0b04cE574E80Da73191Ec141c0016a54A6404056", + AdminAddress: "0x0000000000000000000000000000000000000000", + Ocr2Config: &nodev1.OCR2Config{ + Enabled: true, + P2PKeyBundle: &nodev1.OCR2Config_P2PKeyBundle{ + PeerId: "p2p_12D3KooWBCMCCZZ8x57AXvJvpCujqhZzTjWXbReaRE8TxNr5dM4U", + PublicKey: "147d5cc651819b093cd2fdff9760f0f0f77b7ef7798d9e24fc6a350b7300e5d9", + }, + OcrKeyBundle: &nodev1.OCR2Config_OCRKeyBundle{ + BundleId: "1c28e76d180d1ed1524e61845fa58a384415de7e51017edf1f8c553e28357772", + ConfigPublicKey: "09fced0207611ed618bf0759ab128d9797e15b18e46436be1a56a91e4043ec0e", + OffchainPublicKey: "c805572b813a072067eab2087ddbee8aa719090e12890b15c01094f0d3f74a5f", + OnchainSigningAddress: "679296b7c1eb4948efcc87efc550940a182e610c", + }, + }, + }, + }, + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + j := clo.NewJobClient(lggr, clo.JobClientConfig{Nops: tt.fields.NodeOperators}) + + got, err := j.ListNodeChainConfigs(tt.args.ctx, tt.args.in, tt.args.opts...) + if (err != nil) != tt.wantErr { + t.Errorf("JobClient.ListNodeChainConfigs() error = %v, wantErr %v", err, tt.wantErr) + return + } + if !reflect.DeepEqual(got, tt.want) { + t.Errorf("JobClient.ListNodeChainConfigs() = %v, want %v", got, tt.want) + } + }) + } +} + +func parseTestNopsWithChainConfigs(t *testing.T) []*models.NodeOperator { + t.Helper() + var out []*models.NodeOperator + err := json.Unmarshal([]byte(testNopsWithChainConfigs), &out) + require.NoError(t, err) + require.Len(t, out, 2, "wrong number of nops") + return out +} diff --git a/deployment/environment/clo/testdata/keystone_nops.json b/deployment/environment/clo/testdata/keystone_nops.json new file mode 100644 index 00000000000..679a85935a4 --- /dev/null +++ b/deployment/environment/clo/testdata/keystone_nops.json @@ -0,0 +1,3162 @@ +[ + { + "id": "67", + "keys": [ + "keystone-09" + ], + "name": "Chainlink Keystone Node Operator 9", + "metadata": { + "nodeCount": 2, + "jobCount": 4 + }, + "nodes": [ + { + "id": "780", + "name": "Chainlink Sepolia Prod Keystone One 9", + "publicKey": "412dc6fe48ea4e34baaa77da2e3b032d39b938597b6f3d61fe7ed183a827a431", + "chainConfigs": [ + { + "network": { + "id": "140", + "chainID": "421614", + "chainType": "EVM", + "name": "Arbitrum Testnet (Sepolia)" + }, + "accountAddress": "0xbA8E21dFaa0501fCD43146d0b5F21c2B8E0eEdfB", + "adminAddress": "0x0000000000000000000000000000000000000000", + "ocr1Config": { + "p2pKeyBundle": {}, + "ocrKeyBundle": {} + }, + "ocr2Config": { + "enabled": true, + "p2pKeyBundle": { + "peerID": "p2p_12D3KooWBCMCCZZ8x57AXvJvpCujqhZzTjWXbReaRE8TxNr5dM4U", + "publicKey": "147d5cc651819b093cd2fdff9760f0f0f77b7ef7798d9e24fc6a350b7300e5d9" + }, + "ocrKeyBundle": { + "bundleID": "1c28e76d180d1ed1524e61845fa58a384415de7e51017edf1f8c553e28357772", + "configPublicKey": "09fced0207611ed618bf0759ab128d9797e15b18e46436be1a56a91e4043ec0e", + "offchainPublicKey": "c805572b813a072067eab2087ddbee8aa719090e12890b15c01094f0d3f74a5f", + "onchainSigningAddress": "679296b7c1eb4948efcc87efc550940a182e610c" + }, + "plugins": {} + } + }, + { + "network": { + "id": "129", + "chainID": "11155111", + "chainType": "EVM", + "name": "Ethereum Testnet (Sepolia)" + }, + "accountAddress": "0x0b04cE574E80Da73191Ec141c0016a54A6404056", + "adminAddress": "0x0000000000000000000000000000000000000000", + "ocr1Config": { + "p2pKeyBundle": {}, + "ocrKeyBundle": {} + }, + "ocr2Config": { + "enabled": true, + "p2pKeyBundle": { + "peerID": "p2p_12D3KooWBCMCCZZ8x57AXvJvpCujqhZzTjWXbReaRE8TxNr5dM4U", + "publicKey": "147d5cc651819b093cd2fdff9760f0f0f77b7ef7798d9e24fc6a350b7300e5d9" + }, + "ocrKeyBundle": { + "bundleID": "1c28e76d180d1ed1524e61845fa58a384415de7e51017edf1f8c553e28357772", + "configPublicKey": "09fced0207611ed618bf0759ab128d9797e15b18e46436be1a56a91e4043ec0e", + "offchainPublicKey": "c805572b813a072067eab2087ddbee8aa719090e12890b15c01094f0d3f74a5f", + "onchainSigningAddress": "679296b7c1eb4948efcc87efc550940a182e610c" + }, + "plugins": {} + } + } + ], + "connected": true, + "supportedProducts": [ + "WORKFLOW", + "OCR3_CAPABILITY" + ], + "categories": [ + { + "id": "11", + "name": "Keystone" + } + ] + }, + { + "id": "818", + "name": "Chainlink Sepolia Prod Keystone Cap One 9", + "publicKey": "3f5bbcb4b0409e6ea39d824f1837787484475fffb12e5e4a70509756ef6c7f9a", + "chainConfigs": [ + { + "network": { + "id": "140", + "chainID": "421614", + "chainType": "EVM", + "name": "Arbitrum Testnet (Sepolia)" + }, + "accountAddress": "0x9b74f08bD7269919C0597C0E00e70ef2A66829db", + "adminAddress": "0x0000000000000000000000000000000000000000", + "ocr1Config": { + "p2pKeyBundle": {}, + "ocrKeyBundle": {} + }, + "ocr2Config": { + "enabled": true, + "p2pKeyBundle": { + "peerID": "p2p_12D3KooWPG6X2RgqoSWtM3kvETV6kK4ki8FftaBkwvFWk8yKRBkz", + "publicKey": "c7bf55cf625a55470b0c56c3e51ad175c9dd0d42ca48246c205c715b7495937f" + }, + "ocrKeyBundle": { + "bundleID": "aa717effd7d28374c5980dbd9583dcff5e0800e7100051c6c8418899648dffbf", + "configPublicKey": "3fd95a3839f15adcdff573e6fbf07d06d78fbfeac5eb683f67e70226c1983c44", + "offchainPublicKey": "2b8b8d091c6f4446365f463e6132d699206bbddd38284e8e14ae0443382f297c", + "onchainSigningAddress": "b05b138a987fceffa68f79bdbb36a1faf8d3d964" + }, + "plugins": {} + } + }, + { + "network": { + "id": "10", + "chainID": "43113", + "chainType": "EVM", + "name": "Avalanche Testnet (Fuji)" + }, + "accountAddress": "0x662B6B119f7fc9Dc2A526395A9EA88AE79A1192F", + "adminAddress": "0x0000000000000000000000000000000000000000", + "ocr1Config": { + "p2pKeyBundle": {}, + "ocrKeyBundle": {} + }, + "ocr2Config": { + "enabled": true, + "p2pKeyBundle": { + "peerID": "p2p_12D3KooWPG6X2RgqoSWtM3kvETV6kK4ki8FftaBkwvFWk8yKRBkz", + "publicKey": "c7bf55cf625a55470b0c56c3e51ad175c9dd0d42ca48246c205c715b7495937f" + }, + "ocrKeyBundle": { + "bundleID": "aa717effd7d28374c5980dbd9583dcff5e0800e7100051c6c8418899648dffbf", + "configPublicKey": "3fd95a3839f15adcdff573e6fbf07d06d78fbfeac5eb683f67e70226c1983c44", + "offchainPublicKey": "2b8b8d091c6f4446365f463e6132d699206bbddd38284e8e14ae0443382f297c", + "onchainSigningAddress": "b05b138a987fceffa68f79bdbb36a1faf8d3d964" + }, + "plugins": {} + } + }, + { + "network": { + "id": "147", + "chainID": "84532", + "chainType": "EVM", + "name": "Base Testnet (Sepolia)" + }, + "accountAddress": "0x34431021e0E07c75816226697Af6Ef02725e36af", + "adminAddress": "0x0000000000000000000000000000000000000000", + "ocr1Config": { + "p2pKeyBundle": {}, + "ocrKeyBundle": {} + }, + "ocr2Config": { + "enabled": true, + "p2pKeyBundle": { + "peerID": "p2p_12D3KooWPG6X2RgqoSWtM3kvETV6kK4ki8FftaBkwvFWk8yKRBkz", + "publicKey": "c7bf55cf625a55470b0c56c3e51ad175c9dd0d42ca48246c205c715b7495937f" + }, + "ocrKeyBundle": { + "bundleID": "aa717effd7d28374c5980dbd9583dcff5e0800e7100051c6c8418899648dffbf", + "configPublicKey": "3fd95a3839f15adcdff573e6fbf07d06d78fbfeac5eb683f67e70226c1983c44", + "offchainPublicKey": "2b8b8d091c6f4446365f463e6132d699206bbddd38284e8e14ae0443382f297c", + "onchainSigningAddress": "b05b138a987fceffa68f79bdbb36a1faf8d3d964" + }, + "plugins": {} + } + }, + { + "network": { + "id": "129", + "chainID": "11155111", + "chainType": "EVM", + "name": "Ethereum Testnet (Sepolia)" + }, + "accountAddress": "0xB5988d5d9ADd3d98CF45211bE37cf9b3372054C9", + "adminAddress": "0x0000000000000000000000000000000000000000", + "ocr1Config": { + "p2pKeyBundle": {}, + "ocrKeyBundle": {} + }, + "ocr2Config": { + "enabled": true, + "p2pKeyBundle": { + "peerID": "p2p_12D3KooWPG6X2RgqoSWtM3kvETV6kK4ki8FftaBkwvFWk8yKRBkz", + "publicKey": "c7bf55cf625a55470b0c56c3e51ad175c9dd0d42ca48246c205c715b7495937f" + }, + "ocrKeyBundle": { + "bundleID": "aa717effd7d28374c5980dbd9583dcff5e0800e7100051c6c8418899648dffbf", + "configPublicKey": "3fd95a3839f15adcdff573e6fbf07d06d78fbfeac5eb683f67e70226c1983c44", + "offchainPublicKey": "2b8b8d091c6f4446365f463e6132d699206bbddd38284e8e14ae0443382f297c", + "onchainSigningAddress": "b05b138a987fceffa68f79bdbb36a1faf8d3d964" + }, + "plugins": {} + } + } + ], + "connected": true, + "supportedProducts": [ + "OCR3_CAPABILITY", + "DATA_STREAMS_V03" + ], + "categories": [ + { + "id": "11", + "name": "Keystone" + } + ] + } + ], + "createdAt": "2024-08-14T19:00:07.113658Z" + }, + { + "id": "68", + "keys": [ + "keystone-08" + ], + "name": "Chainlink Keystone Node Operator 8", + "metadata": { + "nodeCount": 2, + "jobCount": 4 + }, + "nodes": [ + { + "id": "781", + "name": "Chainlink Sepolia Prod Keystone One 8", + "publicKey": "1141dd1e46797ced9b0fbad49115f18507f6f6e6e3cc86e7e5ba169e58645adc", + "chainConfigs": [ + { + "network": { + "id": "140", + "chainID": "421614", + "chainType": "EVM", + "name": "Arbitrum Testnet (Sepolia)" + }, + "accountAddress": "0xEa4bC3638660D78Da56f39f6680dCDD0cEAaD2c6", + "adminAddress": "0x0000000000000000000000000000000000000000", + "ocr1Config": { + "p2pKeyBundle": {}, + "ocrKeyBundle": {} + }, + "ocr2Config": { + "enabled": true, + "p2pKeyBundle": { + "peerID": "p2p_12D3KooWAUagqMycsro27kFznSQRHbhfCBLx8nKD4ptTiUGDe38c", + "publicKey": "09ca39cd924653c72fbb0e458b629c3efebdad3e29e7cd0b5760754d919ed829" + }, + "ocrKeyBundle": { + "bundleID": "be0d639de3ae3cbeaa31ca369514f748ba1d271145cba6796bcc12aace2f64c3", + "configPublicKey": "e3d4d7a7372a3b1110db0290ab3649eb5fbb0daf6cf3ae02cfe5f367700d9264", + "offchainPublicKey": "ad08c2a5878cada53521f4e2bb449f191ccca7899246721a0deeea19f7b83f70", + "onchainSigningAddress": "8c2aa1e6fad88a6006dfb116eb866cbad2910314" + }, + "plugins": {} + } + }, + { + "network": { + "id": "129", + "chainID": "11155111", + "chainType": "EVM", + "name": "Ethereum Testnet (Sepolia)" + }, + "accountAddress": "0x31B179dcF8f9036C30f04bE578793e51bF14A39E", + "adminAddress": "0x0000000000000000000000000000000000000000", + "ocr1Config": { + "p2pKeyBundle": {}, + "ocrKeyBundle": {} + }, + "ocr2Config": { + "enabled": true, + "p2pKeyBundle": { + "peerID": "p2p_12D3KooWAUagqMycsro27kFznSQRHbhfCBLx8nKD4ptTiUGDe38c", + "publicKey": "09ca39cd924653c72fbb0e458b629c3efebdad3e29e7cd0b5760754d919ed829" + }, + "ocrKeyBundle": { + "bundleID": "be0d639de3ae3cbeaa31ca369514f748ba1d271145cba6796bcc12aace2f64c3", + "configPublicKey": "e3d4d7a7372a3b1110db0290ab3649eb5fbb0daf6cf3ae02cfe5f367700d9264", + "offchainPublicKey": "ad08c2a5878cada53521f4e2bb449f191ccca7899246721a0deeea19f7b83f70", + "onchainSigningAddress": "8c2aa1e6fad88a6006dfb116eb866cbad2910314" + }, + "plugins": {} + } + } + ], + "connected": true, + "supportedProducts": [ + "WORKFLOW", + "OCR3_CAPABILITY" + ], + "categories": [ + { + "id": "11", + "name": "Keystone" + } + ] + }, + { + "id": "817", + "name": "Chainlink Sepolia Prod Keystone Cap One 8", + "publicKey": "2346da196a82c88fe6c315d2e4d0dddacf4590a172b20adb6f27a8601ca0540d", + "chainConfigs": [ + { + "network": { + "id": "140", + "chainID": "421614", + "chainType": "EVM", + "name": "Arbitrum Testnet (Sepolia)" + }, + "accountAddress": "0xa5C7133aBD35F9d742bD2997D693A507c5eBf4Ac", + "adminAddress": "0x0000000000000000000000000000000000000000", + "ocr1Config": { + "p2pKeyBundle": {}, + "ocrKeyBundle": {} + }, + "ocr2Config": { + "enabled": true, + "p2pKeyBundle": { + "peerID": "p2p_12D3KooWNfg9cYxEri1zGbdCZ87DekmruYY6J1wUobEwNNVewMpT", + "publicKey": "beee088bccea272eb6473fcc1cd3e22f2fc8d3a253a6398b69f5aab94070e690" + }, + "ocrKeyBundle": { + "bundleID": "9fba2d29874bb06b07272bd9141f096c1987d790bb0f81c3ffaf66d11cdac4f2", + "configPublicKey": "66dec87065de79e64ed4edd2478ec40a66f955af56e7b837729f464f8487d713", + "offchainPublicKey": "a0f59d50078c77812da8d3077f552209adfb58e76b635e008b6b0f872ce52139", + "onchainSigningAddress": "ed25406f1ef2e1381f6e1e04341f1a6e8b4eacea" + }, + "plugins": {} + } + }, + { + "network": { + "id": "10", + "chainID": "43113", + "chainType": "EVM", + "name": "Avalanche Testnet (Fuji)" + }, + "accountAddress": "0x9fd869f5baADb79F9b7C58c0855fcAc0384e1d4B", + "adminAddress": "0x0000000000000000000000000000000000000000", + "ocr1Config": { + "p2pKeyBundle": {}, + "ocrKeyBundle": {} + }, + "ocr2Config": { + "enabled": true, + "p2pKeyBundle": { + "peerID": "p2p_12D3KooWNfg9cYxEri1zGbdCZ87DekmruYY6J1wUobEwNNVewMpT", + "publicKey": "beee088bccea272eb6473fcc1cd3e22f2fc8d3a253a6398b69f5aab94070e690" + }, + "ocrKeyBundle": { + "bundleID": "9fba2d29874bb06b07272bd9141f096c1987d790bb0f81c3ffaf66d11cdac4f2", + "configPublicKey": "66dec87065de79e64ed4edd2478ec40a66f955af56e7b837729f464f8487d713", + "offchainPublicKey": "a0f59d50078c77812da8d3077f552209adfb58e76b635e008b6b0f872ce52139", + "onchainSigningAddress": "ed25406f1ef2e1381f6e1e04341f1a6e8b4eacea" + }, + "plugins": {} + } + }, + { + "network": { + "id": "147", + "chainID": "84532", + "chainType": "EVM", + "name": "Base Testnet (Sepolia)" + }, + "accountAddress": "0xe477E4C2e335E9b839665d710dE77CFECa9C43A7", + "adminAddress": "0x0000000000000000000000000000000000000000", + "ocr1Config": { + "p2pKeyBundle": {}, + "ocrKeyBundle": {} + }, + "ocr2Config": { + "enabled": true, + "p2pKeyBundle": { + "peerID": "p2p_12D3KooWNfg9cYxEri1zGbdCZ87DekmruYY6J1wUobEwNNVewMpT", + "publicKey": "beee088bccea272eb6473fcc1cd3e22f2fc8d3a253a6398b69f5aab94070e690" + }, + "ocrKeyBundle": { + "bundleID": "9fba2d29874bb06b07272bd9141f096c1987d790bb0f81c3ffaf66d11cdac4f2", + "configPublicKey": "66dec87065de79e64ed4edd2478ec40a66f955af56e7b837729f464f8487d713", + "offchainPublicKey": "a0f59d50078c77812da8d3077f552209adfb58e76b635e008b6b0f872ce52139", + "onchainSigningAddress": "ed25406f1ef2e1381f6e1e04341f1a6e8b4eacea" + }, + "plugins": {} + } + }, + { + "network": { + "id": "129", + "chainID": "11155111", + "chainType": "EVM", + "name": "Ethereum Testnet (Sepolia)" + }, + "accountAddress": "0x056A1275DD670205aba10D8fC9bB597777a65030", + "adminAddress": "0x0000000000000000000000000000000000000000", + "ocr1Config": { + "p2pKeyBundle": {}, + "ocrKeyBundle": {} + }, + "ocr2Config": { + "enabled": true, + "p2pKeyBundle": { + "peerID": "p2p_12D3KooWNfg9cYxEri1zGbdCZ87DekmruYY6J1wUobEwNNVewMpT", + "publicKey": "beee088bccea272eb6473fcc1cd3e22f2fc8d3a253a6398b69f5aab94070e690" + }, + "ocrKeyBundle": { + "bundleID": "9fba2d29874bb06b07272bd9141f096c1987d790bb0f81c3ffaf66d11cdac4f2", + "configPublicKey": "66dec87065de79e64ed4edd2478ec40a66f955af56e7b837729f464f8487d713", + "offchainPublicKey": "a0f59d50078c77812da8d3077f552209adfb58e76b635e008b6b0f872ce52139", + "onchainSigningAddress": "ed25406f1ef2e1381f6e1e04341f1a6e8b4eacea" + }, + "plugins": {} + } + } + ], + "connected": true, + "supportedProducts": [ + "OCR3_CAPABILITY", + "DATA_STREAMS_V03" + ], + "categories": [ + { + "id": "11", + "name": "Keystone" + } + ] + } + ], + "createdAt": "2024-08-14T20:26:37.622463Z" + }, + { + "id": "69", + "keys": [ + "keystone-07" + ], + "name": "Chainlink Keystone Node Operator 7", + "metadata": { + "nodeCount": 2, + "jobCount": 4 + }, + "nodes": [ + { + "id": "782", + "name": "Chainlink Sepolia Prod Keystone One 7", + "publicKey": "b473091fe1d4dbbc26ad71c67b4432f8f4280e06bab5e2122a92f4ab8b6ff2f5", + "chainConfigs": [ + { + "network": { + "id": "140", + "chainID": "421614", + "chainType": "EVM", + "name": "Arbitrum Testnet (Sepolia)" + }, + "accountAddress": "0x65bE4739E187a39b859766C143b569acd5BE234d", + "adminAddress": "0x0000000000000000000000000000000000000000", + "ocr1Config": { + "p2pKeyBundle": {}, + "ocrKeyBundle": {} + }, + "ocr2Config": { + "enabled": true, + "p2pKeyBundle": { + "peerID": "p2p_12D3KooWQMCj73V5xmCd6C5VsJr7rbFG2TF9LwVcLiiBqXps9MgC", + "publicKey": "d7e9f2252b09edf0802a65b60bc9956691747894cb3ab9fefd072adf742eb9f1" + }, + "ocrKeyBundle": { + "bundleID": "e6d6ffec6cff01ac20d57bc42626c8e955293f232d383bf468351d867a7b8213", + "configPublicKey": "4d2f75f98b911c20fe7808384312d8b913e6b7a98c34d05c6e461434c92b4502", + "offchainPublicKey": "01496edce35663071d74472e02119432ba059b3904d205e4358014410e4f2be3", + "onchainSigningAddress": "213803bb9f9715379aaf11aadb0212369701dc0a" + }, + "plugins": {} + } + }, + { + "network": { + "id": "129", + "chainID": "11155111", + "chainType": "EVM", + "name": "Ethereum Testnet (Sepolia)" + }, + "accountAddress": "0x9ad9f3AD49e5aB0F28bD694d211a90297bD90D7f", + "adminAddress": "0x0000000000000000000000000000000000000000", + "ocr1Config": { + "p2pKeyBundle": {}, + "ocrKeyBundle": {} + }, + "ocr2Config": { + "enabled": true, + "p2pKeyBundle": { + "peerID": "p2p_12D3KooWQMCj73V5xmCd6C5VsJr7rbFG2TF9LwVcLiiBqXps9MgC", + "publicKey": "d7e9f2252b09edf0802a65b60bc9956691747894cb3ab9fefd072adf742eb9f1" + }, + "ocrKeyBundle": { + "bundleID": "e6d6ffec6cff01ac20d57bc42626c8e955293f232d383bf468351d867a7b8213", + "configPublicKey": "4d2f75f98b911c20fe7808384312d8b913e6b7a98c34d05c6e461434c92b4502", + "offchainPublicKey": "01496edce35663071d74472e02119432ba059b3904d205e4358014410e4f2be3", + "onchainSigningAddress": "213803bb9f9715379aaf11aadb0212369701dc0a" + }, + "plugins": {} + } + } + ], + "connected": true, + "supportedProducts": [ + "WORKFLOW", + "OCR3_CAPABILITY" + ], + "categories": [ + { + "id": "11", + "name": "Keystone" + } + ] + }, + { + "id": "816", + "name": "Chainlink Sepolia Prod Keystone Cap One 7", + "publicKey": "50d4e3393516d1998e5c39874d7c0da2291e4e3727f8baac4380e9f5573cc648", + "chainConfigs": [ + { + "network": { + "id": "140", + "chainID": "421614", + "chainType": "EVM", + "name": "Arbitrum Testnet (Sepolia)" + }, + "accountAddress": "0x0ba7c1096B701A862bBCe7F13E9D33eED7e33c1D", + "adminAddress": "0x0000000000000000000000000000000000000000", + "ocr1Config": { + "p2pKeyBundle": {}, + "ocrKeyBundle": {} + }, + "ocr2Config": { + "enabled": true, + "p2pKeyBundle": { + "peerID": "p2p_12D3KooWQswQr8fxJG5ieMrayptGV4rvCjDWPCFtfkqm4L6NZbbb", + "publicKey": "dfc9a26dc022bd244c13d62ca88bbe62ca996065bd23224e1f1b77128914d84e" + }, + "ocrKeyBundle": { + "bundleID": "d4566a0c2f256e59733ad2a6dff9f388a1e00b2e65ec1cff7590cb59028888cd", + "configPublicKey": "58db0da621471e616615b8c1c1658ee3b7afbfa64662ce28b38272a95964052c", + "offchainPublicKey": "262fee9de8dd0c8758ba78de8873fdb6705c45ce331bc16ac81dc5b5f0b9680f", + "onchainSigningAddress": "516a9990d3a202b25c2cdd2f6316f4d066543e5d" + }, + "plugins": {} + } + }, + { + "network": { + "id": "10", + "chainID": "43113", + "chainType": "EVM", + "name": "Avalanche Testnet (Fuji)" + }, + "accountAddress": "0xcC44eD47023Bd88B82092A708c38609e8Fc2D197", + "adminAddress": "0x0000000000000000000000000000000000000000", + "ocr1Config": { + "p2pKeyBundle": {}, + "ocrKeyBundle": {} + }, + "ocr2Config": { + "enabled": true, + "p2pKeyBundle": { + "peerID": "p2p_12D3KooWQswQr8fxJG5ieMrayptGV4rvCjDWPCFtfkqm4L6NZbbb", + "publicKey": "dfc9a26dc022bd244c13d62ca88bbe62ca996065bd23224e1f1b77128914d84e" + }, + "ocrKeyBundle": { + "bundleID": "d4566a0c2f256e59733ad2a6dff9f388a1e00b2e65ec1cff7590cb59028888cd", + "configPublicKey": "58db0da621471e616615b8c1c1658ee3b7afbfa64662ce28b38272a95964052c", + "offchainPublicKey": "262fee9de8dd0c8758ba78de8873fdb6705c45ce331bc16ac81dc5b5f0b9680f", + "onchainSigningAddress": "516a9990d3a202b25c2cdd2f6316f4d066543e5d" + }, + "plugins": {} + } + }, + { + "network": { + "id": "147", + "chainID": "84532", + "chainType": "EVM", + "name": "Base Testnet (Sepolia)" + }, + "accountAddress": "0x0E8F4E699cd331022FaA2Ad75E500e70303C8767", + "adminAddress": "0x0000000000000000000000000000000000000000", + "ocr1Config": { + "p2pKeyBundle": {}, + "ocrKeyBundle": {} + }, + "ocr2Config": { + "enabled": true, + "p2pKeyBundle": { + "peerID": "p2p_12D3KooWQswQr8fxJG5ieMrayptGV4rvCjDWPCFtfkqm4L6NZbbb", + "publicKey": "dfc9a26dc022bd244c13d62ca88bbe62ca996065bd23224e1f1b77128914d84e" + }, + "ocrKeyBundle": { + "bundleID": "d4566a0c2f256e59733ad2a6dff9f388a1e00b2e65ec1cff7590cb59028888cd", + "configPublicKey": "58db0da621471e616615b8c1c1658ee3b7afbfa64662ce28b38272a95964052c", + "offchainPublicKey": "262fee9de8dd0c8758ba78de8873fdb6705c45ce331bc16ac81dc5b5f0b9680f", + "onchainSigningAddress": "516a9990d3a202b25c2cdd2f6316f4d066543e5d" + }, + "plugins": {} + } + }, + { + "network": { + "id": "129", + "chainID": "11155111", + "chainType": "EVM", + "name": "Ethereum Testnet (Sepolia)" + }, + "accountAddress": "0x49c36b3BEc6b6e0e77305273FAFC68f479630535", + "adminAddress": "0x0000000000000000000000000000000000000000", + "ocr1Config": { + "p2pKeyBundle": {}, + "ocrKeyBundle": {} + }, + "ocr2Config": { + "enabled": true, + "p2pKeyBundle": { + "peerID": "p2p_12D3KooWQswQr8fxJG5ieMrayptGV4rvCjDWPCFtfkqm4L6NZbbb", + "publicKey": "dfc9a26dc022bd244c13d62ca88bbe62ca996065bd23224e1f1b77128914d84e" + }, + "ocrKeyBundle": { + "bundleID": "d4566a0c2f256e59733ad2a6dff9f388a1e00b2e65ec1cff7590cb59028888cd", + "configPublicKey": "58db0da621471e616615b8c1c1658ee3b7afbfa64662ce28b38272a95964052c", + "offchainPublicKey": "262fee9de8dd0c8758ba78de8873fdb6705c45ce331bc16ac81dc5b5f0b9680f", + "onchainSigningAddress": "516a9990d3a202b25c2cdd2f6316f4d066543e5d" + }, + "plugins": {} + } + } + ], + "connected": true, + "supportedProducts": [ + "OCR3_CAPABILITY", + "DATA_STREAMS_V03" + ], + "categories": [ + { + "id": "11", + "name": "Keystone" + } + ] + } + ], + "createdAt": "2024-08-14T20:30:51.07624Z" + }, + { + "id": "70", + "keys": [ + "keystone-06" + ], + "name": "Chainlink Keystone Node Operator 6", + "metadata": { + "nodeCount": 2, + "jobCount": 4 + }, + "nodes": [ + { + "id": "783", + "name": "Chainlink Sepolia Prod Keystone One 6", + "publicKey": "75ac63fc97a31e31168084e0de8ccd2bea90059b609d962f3e43fc296cdba28d", + "chainConfigs": [ + { + "network": { + "id": "140", + "chainID": "421614", + "chainType": "EVM", + "name": "Arbitrum Testnet (Sepolia)" + }, + "accountAddress": "0x8706E716fc1ee972F3E4D42D42711Aa175Aa654A", + "adminAddress": "0x0000000000000000000000000000000000000000", + "ocr1Config": { + "p2pKeyBundle": {}, + "ocrKeyBundle": {} + }, + "ocr2Config": { + "enabled": true, + "p2pKeyBundle": { + "peerID": "p2p_12D3KooWNJ8de3PUURZ2oucrVTpnRTqNBTUYwHLQjK9LzN3E6Mfn", + "publicKey": "b96933429b1a81c811e1195389d7733e936b03e8086e75ea1fa92c61564b6c31" + }, + "ocrKeyBundle": { + "bundleID": "62d36269d916b4834b17dc6d637c1c39b0895396249a0845764c898e83f63525", + "configPublicKey": "8c6c7d889ac6cc9e663ae48073bbf130fae105d6a3689636db27752e3e3e6816", + "offchainPublicKey": "aa3419628ea3536783742d17d8adf05681aa6a6bd2b206fbde78c7e5aa38586d", + "onchainSigningAddress": "4885973b2fcf061d5cdfb8f74c5139bd3056e9da" + }, + "plugins": {} + } + }, + { + "network": { + "id": "129", + "chainID": "11155111", + "chainType": "EVM", + "name": "Ethereum Testnet (Sepolia)" + }, + "accountAddress": "0x19e10B063a62B1574AE19020A64fDe6419892dA6", + "adminAddress": "0x0000000000000000000000000000000000000000", + "ocr1Config": { + "p2pKeyBundle": {}, + "ocrKeyBundle": {} + }, + "ocr2Config": { + "enabled": true, + "p2pKeyBundle": { + "peerID": "p2p_12D3KooWNJ8de3PUURZ2oucrVTpnRTqNBTUYwHLQjK9LzN3E6Mfn", + "publicKey": "b96933429b1a81c811e1195389d7733e936b03e8086e75ea1fa92c61564b6c31" + }, + "ocrKeyBundle": { + "bundleID": "62d36269d916b4834b17dc6d637c1c39b0895396249a0845764c898e83f63525", + "configPublicKey": "8c6c7d889ac6cc9e663ae48073bbf130fae105d6a3689636db27752e3e3e6816", + "offchainPublicKey": "aa3419628ea3536783742d17d8adf05681aa6a6bd2b206fbde78c7e5aa38586d", + "onchainSigningAddress": "4885973b2fcf061d5cdfb8f74c5139bd3056e9da" + }, + "plugins": {} + } + } + ], + "connected": true, + "supportedProducts": [ + "WORKFLOW", + "OCR3_CAPABILITY" + ], + "categories": [ + { + "id": "11", + "name": "Keystone" + } + ] + }, + { + "id": "815", + "name": "Chainlink Sepolia Prod Keystone Cap One 6", + "publicKey": "2669981add3071fae5dfd760fe97e7d2b90157f86b40227f306f1f3906099fc3", + "chainConfigs": [ + { + "network": { + "id": "140", + "chainID": "421614", + "chainType": "EVM", + "name": "Arbitrum Testnet (Sepolia)" + }, + "accountAddress": "0x405eE4ad3E79786f899810ff6de16a83A920Db5D", + "adminAddress": "0x0000000000000000000000000000000000000000", + "ocr1Config": { + "p2pKeyBundle": {}, + "ocrKeyBundle": {} + }, + "ocr2Config": { + "enabled": true, + "p2pKeyBundle": { + "peerID": "p2p_12D3KooWHB1ucYgRqrocS6t834wL5XaB11JSPgKwzB6QwRPzRayu", + "publicKey": "6d4c18afa813bf7eec73e98a260294bce4b0b26eb9f6efceb2c9402eead56c98" + }, + "ocrKeyBundle": { + "bundleID": "d55283594d4e2c3e507f81ea9ad96261ebec1b1e8579bb1392ca22f7dc9b471b", + "configPublicKey": "32d5b6d38147fa23ec1dc4eeb240e2e70ea768b9a5182676075acd5a2ab2794c", + "offchainPublicKey": "9922cb5c0ae08f0b917979593824bde7ddad0935950e2835914acc34f6cd62f3", + "onchainSigningAddress": "bca900017893ea1366c110941d698d078c2b93ca" + }, + "plugins": {} + } + }, + { + "network": { + "id": "10", + "chainID": "43113", + "chainType": "EVM", + "name": "Avalanche Testnet (Fuji)" + }, + "accountAddress": "0x58D39d629ae9f904b0Ae509179b9e7c9B0184cee", + "adminAddress": "0x0000000000000000000000000000000000000000", + "ocr1Config": { + "p2pKeyBundle": {}, + "ocrKeyBundle": {} + }, + "ocr2Config": { + "enabled": true, + "p2pKeyBundle": { + "peerID": "p2p_12D3KooWHB1ucYgRqrocS6t834wL5XaB11JSPgKwzB6QwRPzRayu", + "publicKey": "6d4c18afa813bf7eec73e98a260294bce4b0b26eb9f6efceb2c9402eead56c98" + }, + "ocrKeyBundle": { + "bundleID": "d55283594d4e2c3e507f81ea9ad96261ebec1b1e8579bb1392ca22f7dc9b471b", + "configPublicKey": "32d5b6d38147fa23ec1dc4eeb240e2e70ea768b9a5182676075acd5a2ab2794c", + "offchainPublicKey": "9922cb5c0ae08f0b917979593824bde7ddad0935950e2835914acc34f6cd62f3", + "onchainSigningAddress": "bca900017893ea1366c110941d698d078c2b93ca" + }, + "plugins": {} + } + }, + { + "network": { + "id": "147", + "chainID": "84532", + "chainType": "EVM", + "name": "Base Testnet (Sepolia)" + }, + "accountAddress": "0x34bFe10F4f4e1101b019639ABd5E5eE5186B80E6", + "adminAddress": "0x0000000000000000000000000000000000000000", + "ocr1Config": { + "p2pKeyBundle": {}, + "ocrKeyBundle": {} + }, + "ocr2Config": { + "enabled": true, + "p2pKeyBundle": { + "peerID": "p2p_12D3KooWHB1ucYgRqrocS6t834wL5XaB11JSPgKwzB6QwRPzRayu", + "publicKey": "6d4c18afa813bf7eec73e98a260294bce4b0b26eb9f6efceb2c9402eead56c98" + }, + "ocrKeyBundle": { + "bundleID": "d55283594d4e2c3e507f81ea9ad96261ebec1b1e8579bb1392ca22f7dc9b471b", + "configPublicKey": "32d5b6d38147fa23ec1dc4eeb240e2e70ea768b9a5182676075acd5a2ab2794c", + "offchainPublicKey": "9922cb5c0ae08f0b917979593824bde7ddad0935950e2835914acc34f6cd62f3", + "onchainSigningAddress": "bca900017893ea1366c110941d698d078c2b93ca" + }, + "plugins": {} + } + }, + { + "network": { + "id": "129", + "chainID": "11155111", + "chainType": "EVM", + "name": "Ethereum Testnet (Sepolia)" + }, + "accountAddress": "0x1741EB7468A490b4A9BA6f4CC7A47B82EcD65c4c", + "adminAddress": "0x0000000000000000000000000000000000000000", + "ocr1Config": { + "p2pKeyBundle": {}, + "ocrKeyBundle": {} + }, + "ocr2Config": { + "enabled": true, + "p2pKeyBundle": { + "peerID": "p2p_12D3KooWHB1ucYgRqrocS6t834wL5XaB11JSPgKwzB6QwRPzRayu", + "publicKey": "6d4c18afa813bf7eec73e98a260294bce4b0b26eb9f6efceb2c9402eead56c98" + }, + "ocrKeyBundle": { + "bundleID": "d55283594d4e2c3e507f81ea9ad96261ebec1b1e8579bb1392ca22f7dc9b471b", + "configPublicKey": "32d5b6d38147fa23ec1dc4eeb240e2e70ea768b9a5182676075acd5a2ab2794c", + "offchainPublicKey": "9922cb5c0ae08f0b917979593824bde7ddad0935950e2835914acc34f6cd62f3", + "onchainSigningAddress": "bca900017893ea1366c110941d698d078c2b93ca" + }, + "plugins": {} + } + } + ], + "connected": true, + "supportedProducts": [ + "OCR3_CAPABILITY", + "DATA_STREAMS_V03" + ], + "categories": [ + { + "id": "11", + "name": "Keystone" + } + ] + } + ], + "createdAt": "2024-08-14T20:32:14.024795Z" + }, + { + "id": "71", + "keys": [ + "keystone-05" + ], + "name": "Chainlink Keystone Node Operator 5", + "metadata": { + "nodeCount": 2, + "jobCount": 4 + }, + "nodes": [ + { + "id": "784", + "name": "Chainlink Sepolia Prod Keystone One 5", + "publicKey": "4542f4fd2ed150c8c976b39802fe3d994aec3ac94fd11e7817f693b1c9a1dabb", + "chainConfigs": [ + { + "network": { + "id": "140", + "chainID": "421614", + "chainType": "EVM", + "name": "Arbitrum Testnet (Sepolia)" + }, + "accountAddress": "0xcea9f5C042130dD35Eff5B5a6E2361A0276570e3", + "adminAddress": "0x0000000000000000000000000000000000000000", + "ocr1Config": { + "p2pKeyBundle": {}, + "ocrKeyBundle": {} + }, + "ocr2Config": { + "enabled": true, + "p2pKeyBundle": { + "peerID": "p2p_12D3KooWR8d5kbZb7YiQWKpT1J1PfMqNaGAmb4jBFx9DWag4hpSZ", + "publicKey": "e38c9f2760db006f070e9cc1bc1c2269ad033751adaa85d022fb760cbc5b5ef6" + }, + "ocrKeyBundle": { + "bundleID": "99fad0362cc8dc8a57a8e616e68133a6d5a8834e08a1b4819710f0e912df5abc", + "configPublicKey": "36de4924cf11938b4461aea1ce99cb640e9603d9a7c294ab6c54acd51d575a49", + "offchainPublicKey": "283471ed66d61fbe11f64eff65d738b59a0301c9a4f846280db26c64c9fdd3f8", + "onchainSigningAddress": "657587eb55cecd6f90b97297b611c3024e488cc0" + }, + "plugins": {} + } + }, + { + "network": { + "id": "129", + "chainID": "11155111", + "chainType": "EVM", + "name": "Ethereum Testnet (Sepolia)" + }, + "accountAddress": "0xdAd1F3F8ec690cf335D46c50EdA5547CeF875161", + "adminAddress": "0x0000000000000000000000000000000000000000", + "ocr1Config": { + "p2pKeyBundle": {}, + "ocrKeyBundle": {} + }, + "ocr2Config": { + "enabled": true, + "p2pKeyBundle": { + "peerID": "p2p_12D3KooWR8d5kbZb7YiQWKpT1J1PfMqNaGAmb4jBFx9DWag4hpSZ", + "publicKey": "e38c9f2760db006f070e9cc1bc1c2269ad033751adaa85d022fb760cbc5b5ef6" + }, + "ocrKeyBundle": { + "bundleID": "99fad0362cc8dc8a57a8e616e68133a6d5a8834e08a1b4819710f0e912df5abc", + "configPublicKey": "36de4924cf11938b4461aea1ce99cb640e9603d9a7c294ab6c54acd51d575a49", + "offchainPublicKey": "283471ed66d61fbe11f64eff65d738b59a0301c9a4f846280db26c64c9fdd3f8", + "onchainSigningAddress": "657587eb55cecd6f90b97297b611c3024e488cc0" + }, + "plugins": {} + } + } + ], + "connected": true, + "supportedProducts": [ + "WORKFLOW", + "OCR3_CAPABILITY" + ], + "categories": [ + { + "id": "11", + "name": "Keystone" + } + ] + }, + { + "id": "814", + "name": "Chainlink Sepolia Prod Keystone Cap One 5", + "publicKey": "94e9ee398547f1564b8b5f72c6148e511919ed0e59b94ae848d63685108f2ab4", + "chainConfigs": [ + { + "network": { + "id": "140", + "chainID": "421614", + "chainType": "EVM", + "name": "Arbitrum Testnet (Sepolia)" + }, + "accountAddress": "0xbd1ee3165178D3A3E38458a9Fb1d6BF7fb5C443e", + "adminAddress": "0x0000000000000000000000000000000000000000", + "ocr1Config": { + "p2pKeyBundle": {}, + "ocrKeyBundle": {} + }, + "ocr2Config": { + "enabled": true, + "p2pKeyBundle": { + "peerID": "p2p_12D3KooWCiwWc97Q3Z9YUGZcAf46TMLg1uMvrEDa4gT6HZUFFCB1", + "publicKey": "2b2f46bf3b7ab2f39a7fec18166a6ebbc0a72209e920c33933f9adf07b101cc0" + }, + "ocrKeyBundle": { + "bundleID": "bf1736a09452daa0923f2c680f3fa6362ae652294e80ce72d923b304b0dcbb13", + "configPublicKey": "4ebd2a563c458485d2698d06142daa37ea2bee706b4a1a71c8435f2ec254506a", + "offchainPublicKey": "8577b96b270b36e74eb5d411caa14353cdadea599d6d6aa9cccf534ce31f1ef5", + "onchainSigningAddress": "b6727a31772b71d15e3120bfd618545292e1f9df" + }, + "plugins": {} + } + }, + { + "network": { + "id": "10", + "chainID": "43113", + "chainType": "EVM", + "name": "Avalanche Testnet (Fuji)" + }, + "accountAddress": "0x9b6284B5775E46fB02C1a589596EF07c35b55377", + "adminAddress": "0x0000000000000000000000000000000000000000", + "ocr1Config": { + "p2pKeyBundle": {}, + "ocrKeyBundle": {} + }, + "ocr2Config": { + "enabled": true, + "p2pKeyBundle": { + "peerID": "p2p_12D3KooWCiwWc97Q3Z9YUGZcAf46TMLg1uMvrEDa4gT6HZUFFCB1", + "publicKey": "2b2f46bf3b7ab2f39a7fec18166a6ebbc0a72209e920c33933f9adf07b101cc0" + }, + "ocrKeyBundle": { + "bundleID": "bf1736a09452daa0923f2c680f3fa6362ae652294e80ce72d923b304b0dcbb13", + "configPublicKey": "4ebd2a563c458485d2698d06142daa37ea2bee706b4a1a71c8435f2ec254506a", + "offchainPublicKey": "8577b96b270b36e74eb5d411caa14353cdadea599d6d6aa9cccf534ce31f1ef5", + "onchainSigningAddress": "b6727a31772b71d15e3120bfd618545292e1f9df" + }, + "plugins": {} + } + }, + { + "network": { + "id": "147", + "chainID": "84532", + "chainType": "EVM", + "name": "Base Testnet (Sepolia)" + }, + "accountAddress": "0xD83DCED517E4df64e913B97b3d0A906e4CA63d43", + "adminAddress": "0x0000000000000000000000000000000000000000", + "ocr1Config": { + "p2pKeyBundle": {}, + "ocrKeyBundle": {} + }, + "ocr2Config": { + "enabled": true, + "p2pKeyBundle": { + "peerID": "p2p_12D3KooWCiwWc97Q3Z9YUGZcAf46TMLg1uMvrEDa4gT6HZUFFCB1", + "publicKey": "2b2f46bf3b7ab2f39a7fec18166a6ebbc0a72209e920c33933f9adf07b101cc0" + }, + "ocrKeyBundle": { + "bundleID": "bf1736a09452daa0923f2c680f3fa6362ae652294e80ce72d923b304b0dcbb13", + "configPublicKey": "4ebd2a563c458485d2698d06142daa37ea2bee706b4a1a71c8435f2ec254506a", + "offchainPublicKey": "8577b96b270b36e74eb5d411caa14353cdadea599d6d6aa9cccf534ce31f1ef5", + "onchainSigningAddress": "b6727a31772b71d15e3120bfd618545292e1f9df" + }, + "plugins": {} + } + }, + { + "network": { + "id": "129", + "chainID": "11155111", + "chainType": "EVM", + "name": "Ethereum Testnet (Sepolia)" + }, + "accountAddress": "0xFF1218066b4b5Cd9dE2A73639862082bcC98bf0D", + "adminAddress": "0x0000000000000000000000000000000000000000", + "ocr1Config": { + "p2pKeyBundle": {}, + "ocrKeyBundle": {} + }, + "ocr2Config": { + "enabled": true, + "p2pKeyBundle": { + "peerID": "p2p_12D3KooWCiwWc97Q3Z9YUGZcAf46TMLg1uMvrEDa4gT6HZUFFCB1", + "publicKey": "2b2f46bf3b7ab2f39a7fec18166a6ebbc0a72209e920c33933f9adf07b101cc0" + }, + "ocrKeyBundle": { + "bundleID": "bf1736a09452daa0923f2c680f3fa6362ae652294e80ce72d923b304b0dcbb13", + "configPublicKey": "4ebd2a563c458485d2698d06142daa37ea2bee706b4a1a71c8435f2ec254506a", + "offchainPublicKey": "8577b96b270b36e74eb5d411caa14353cdadea599d6d6aa9cccf534ce31f1ef5", + "onchainSigningAddress": "b6727a31772b71d15e3120bfd618545292e1f9df" + }, + "plugins": {} + } + } + ], + "connected": true, + "supportedProducts": [ + "OCR3_CAPABILITY", + "DATA_STREAMS_V03" + ], + "categories": [ + { + "id": "11", + "name": "Keystone" + } + ] + } + ], + "createdAt": "2024-08-14T20:38:35.588611Z" + }, + { + "id": "72", + "keys": [ + "keystone-04" + ], + "name": "Chainlink Keystone Node Operator 4", + "metadata": { + "nodeCount": 2, + "jobCount": 4 + }, + "nodes": [ + { + "id": "785", + "name": "Chainlink Sepolia Prod Keystone One 4", + "publicKey": "07e0ffc57b6263604df517b94bd986169451a3c90600a855bb19212dc575de54", + "chainConfigs": [ + { + "network": { + "id": "140", + "chainID": "421614", + "chainType": "EVM", + "name": "Arbitrum Testnet (Sepolia)" + }, + "accountAddress": "0x0be7Df958604166D9Bf0F727F0AC7A4Fb0f5B8a1", + "adminAddress": "0x0000000000000000000000000000000000000000", + "ocr1Config": { + "p2pKeyBundle": {}, + "ocrKeyBundle": {} + }, + "ocr2Config": { + "enabled": true, + "p2pKeyBundle": { + "peerID": "p2p_12D3KooWHqR1w26yHatTSZQW3xbRct9SxWzVj9X4SpU916Hy8jYg", + "publicKey": "77224be9d052343b1d17156a1e463625c0d746468d4f5a44cddd452365b1d4ed" + }, + "ocrKeyBundle": { + "bundleID": "8e563a16ec5a802345b162d0f31149e8d5055014a31847d7b20d6de500aa48bd", + "configPublicKey": "c812eab2415f45cc1d2afdb2be2e3ea419bb7851acfc30c07b4df42c856e8f74", + "offchainPublicKey": "2a4c7dec127fdd8145e48c5edb9467225098bd8c8ad1dade868325b787affbde", + "onchainSigningAddress": "a6f35436cb7bffd615cc47a0a04aa0a78696a144" + }, + "plugins": {} + } + }, + { + "network": { + "id": "129", + "chainID": "11155111", + "chainType": "EVM", + "name": "Ethereum Testnet (Sepolia)" + }, + "accountAddress": "0x6F5cAb24Fb7412bB516b3468b9F3a9c471d25fE5", + "adminAddress": "0x0000000000000000000000000000000000000000", + "ocr1Config": { + "p2pKeyBundle": {}, + "ocrKeyBundle": {} + }, + "ocr2Config": { + "enabled": true, + "p2pKeyBundle": { + "peerID": "p2p_12D3KooWHqR1w26yHatTSZQW3xbRct9SxWzVj9X4SpU916Hy8jYg", + "publicKey": "77224be9d052343b1d17156a1e463625c0d746468d4f5a44cddd452365b1d4ed" + }, + "ocrKeyBundle": { + "bundleID": "8e563a16ec5a802345b162d0f31149e8d5055014a31847d7b20d6de500aa48bd", + "configPublicKey": "c812eab2415f45cc1d2afdb2be2e3ea419bb7851acfc30c07b4df42c856e8f74", + "offchainPublicKey": "2a4c7dec127fdd8145e48c5edb9467225098bd8c8ad1dade868325b787affbde", + "onchainSigningAddress": "a6f35436cb7bffd615cc47a0a04aa0a78696a144" + }, + "plugins": {} + } + } + ], + "connected": true, + "supportedProducts": [ + "WORKFLOW", + "OCR3_CAPABILITY" + ], + "categories": [ + { + "id": "11", + "name": "Keystone" + } + ] + }, + { + "id": "813", + "name": "Chainlink Sepolia Prod Keystone Cap One 4", + "publicKey": "a618fe2d3260151957d105d2dd593dddaad20c45dc6ae8eab265504e6585a02c", + "chainConfigs": [ + { + "network": { + "id": "140", + "chainID": "421614", + "chainType": "EVM", + "name": "Arbitrum Testnet (Sepolia)" + }, + "accountAddress": "0xE73E4D047DA32De40C7008075aEb9F60C8AF3C90", + "adminAddress": "0x0000000000000000000000000000000000000000", + "ocr1Config": { + "p2pKeyBundle": {}, + "ocrKeyBundle": {} + }, + "ocr2Config": { + "enabled": true, + "p2pKeyBundle": { + "peerID": "p2p_12D3KooWPMfQRpMy3wYzSMe3BLS8GFuC3fauk7FhTtgfbtp6T6jT", + "publicKey": "c92c6c81f3dff17c05577b9f87177d735d797a3ceedc0fa1395682dfbb66a8d2" + }, + "ocrKeyBundle": { + "bundleID": "fbcfd8420c2ebc450c81fcf72c6673fdd786702c881467e69817c20350bf819b", + "configPublicKey": "282a47a24fd976134f25a99f6370e072f228098010d2594d849d0a4c2788f878", + "offchainPublicKey": "1a7902a01e27818cda034637fdce603a265bc380934324b6f48cf23873234ec6", + "onchainSigningAddress": "7e799378dda3dcdc503233735f09150f0684be19" + }, + "plugins": {} + } + }, + { + "network": { + "id": "10", + "chainID": "43113", + "chainType": "EVM", + "name": "Avalanche Testnet (Fuji)" + }, + "accountAddress": "0x7501ff3462fd2133f2E1F93DB7Ec514988B43E56", + "adminAddress": "0x0000000000000000000000000000000000000000", + "ocr1Config": { + "p2pKeyBundle": {}, + "ocrKeyBundle": {} + }, + "ocr2Config": { + "enabled": true, + "p2pKeyBundle": { + "peerID": "p2p_12D3KooWPMfQRpMy3wYzSMe3BLS8GFuC3fauk7FhTtgfbtp6T6jT", + "publicKey": "c92c6c81f3dff17c05577b9f87177d735d797a3ceedc0fa1395682dfbb66a8d2" + }, + "ocrKeyBundle": { + "bundleID": "fbcfd8420c2ebc450c81fcf72c6673fdd786702c881467e69817c20350bf819b", + "configPublicKey": "282a47a24fd976134f25a99f6370e072f228098010d2594d849d0a4c2788f878", + "offchainPublicKey": "1a7902a01e27818cda034637fdce603a265bc380934324b6f48cf23873234ec6", + "onchainSigningAddress": "7e799378dda3dcdc503233735f09150f0684be19" + }, + "plugins": {} + } + }, + { + "network": { + "id": "147", + "chainID": "84532", + "chainType": "EVM", + "name": "Base Testnet (Sepolia)" + }, + "accountAddress": "0xef080765890a3F697C4920609621fe301Dd34A70", + "adminAddress": "0x0000000000000000000000000000000000000000", + "ocr1Config": { + "p2pKeyBundle": {}, + "ocrKeyBundle": {} + }, + "ocr2Config": { + "enabled": true, + "p2pKeyBundle": { + "peerID": "p2p_12D3KooWPMfQRpMy3wYzSMe3BLS8GFuC3fauk7FhTtgfbtp6T6jT", + "publicKey": "c92c6c81f3dff17c05577b9f87177d735d797a3ceedc0fa1395682dfbb66a8d2" + }, + "ocrKeyBundle": { + "bundleID": "fbcfd8420c2ebc450c81fcf72c6673fdd786702c881467e69817c20350bf819b", + "configPublicKey": "282a47a24fd976134f25a99f6370e072f228098010d2594d849d0a4c2788f878", + "offchainPublicKey": "1a7902a01e27818cda034637fdce603a265bc380934324b6f48cf23873234ec6", + "onchainSigningAddress": "7e799378dda3dcdc503233735f09150f0684be19" + }, + "plugins": {} + } + }, + { + "network": { + "id": "129", + "chainID": "11155111", + "chainType": "EVM", + "name": "Ethereum Testnet (Sepolia)" + }, + "accountAddress": "0x860235D5Db42eF568665900BBD6bA3DB2fA4f33f", + "adminAddress": "0x0000000000000000000000000000000000000000", + "ocr1Config": { + "p2pKeyBundle": {}, + "ocrKeyBundle": {} + }, + "ocr2Config": { + "enabled": true, + "p2pKeyBundle": { + "peerID": "p2p_12D3KooWPMfQRpMy3wYzSMe3BLS8GFuC3fauk7FhTtgfbtp6T6jT", + "publicKey": "c92c6c81f3dff17c05577b9f87177d735d797a3ceedc0fa1395682dfbb66a8d2" + }, + "ocrKeyBundle": { + "bundleID": "fbcfd8420c2ebc450c81fcf72c6673fdd786702c881467e69817c20350bf819b", + "configPublicKey": "282a47a24fd976134f25a99f6370e072f228098010d2594d849d0a4c2788f878", + "offchainPublicKey": "1a7902a01e27818cda034637fdce603a265bc380934324b6f48cf23873234ec6", + "onchainSigningAddress": "7e799378dda3dcdc503233735f09150f0684be19" + }, + "plugins": {} + } + } + ], + "connected": true, + "supportedProducts": [ + "OCR3_CAPABILITY", + "DATA_STREAMS_V03" + ], + "categories": [ + { + "id": "11", + "name": "Keystone" + } + ] + } + ], + "createdAt": "2024-08-14T20:39:26.24249Z" + }, + { + "id": "73", + "keys": [ + "keystone-03", + "keystone-bt-03" + ], + "name": "Chainlink Keystone Node Operator 3", + "metadata": { + "nodeCount": 3, + "jobCount": 5 + }, + "nodes": [ + { + "id": "786", + "name": "\tChainlink Sepolia Prod Keystone One 3", + "publicKey": "487901e0c0a9d3c66e7cfc50f3a9e3cdbfdf1b0107273d73d94a91d278545516", + "chainConfigs": [ + { + "network": { + "id": "140", + "chainID": "421614", + "chainType": "EVM", + "name": "Arbitrum Testnet (Sepolia)" + }, + "accountAddress": "0x3Be73A57a36E5ab00DcceD755B4bfF8bb99e52b2", + "adminAddress": "0x0000000000000000000000000000000000000000", + "ocr1Config": { + "p2pKeyBundle": {}, + "ocrKeyBundle": {} + }, + "ocr2Config": { + "enabled": true, + "p2pKeyBundle": { + "peerID": "p2p_12D3KooWCcVLytqinD8xMn27NvomcQhj2mqMVzyGemz6oPwv1SMT", + "publicKey": "298834a041a056df58c839cb53d99b78558693042e54dff238f504f16d18d4b6" + }, + "ocrKeyBundle": { + "bundleID": "8843b5db0608f92dac38ca56775766a08db9ee82224a19595d04bd6c58b38fbd", + "configPublicKey": "63375a3d175364bd299e7cecf352cb3e469dd30116cf1418f2b7571fb46c4a4b", + "offchainPublicKey": "b4c4993d6c15fee63800db901a8b35fa419057610962caab1c1d7bed55709127", + "onchainSigningAddress": "6607c140e558631407f33bafbabd103863cee876" + }, + "plugins": {} + } + }, + { + "network": { + "id": "129", + "chainID": "11155111", + "chainType": "EVM", + "name": "Ethereum Testnet (Sepolia)" + }, + "accountAddress": "0xA9eFB53c513E413762b2Be5299D161d8E6e7278e", + "adminAddress": "0x0000000000000000000000000000000000000000", + "ocr1Config": { + "p2pKeyBundle": {}, + "ocrKeyBundle": {} + }, + "ocr2Config": { + "enabled": true, + "p2pKeyBundle": { + "peerID": "p2p_12D3KooWCcVLytqinD8xMn27NvomcQhj2mqMVzyGemz6oPwv1SMT", + "publicKey": "298834a041a056df58c839cb53d99b78558693042e54dff238f504f16d18d4b6" + }, + "ocrKeyBundle": { + "bundleID": "8843b5db0608f92dac38ca56775766a08db9ee82224a19595d04bd6c58b38fbd", + "configPublicKey": "63375a3d175364bd299e7cecf352cb3e469dd30116cf1418f2b7571fb46c4a4b", + "offchainPublicKey": "b4c4993d6c15fee63800db901a8b35fa419057610962caab1c1d7bed55709127", + "onchainSigningAddress": "6607c140e558631407f33bafbabd103863cee876" + }, + "plugins": {} + } + } + ], + "connected": true, + "supportedProducts": [ + "WORKFLOW", + "OCR3_CAPABILITY" + ], + "categories": [ + { + "id": "11", + "name": "Keystone" + } + ] + }, + { + "id": "812", + "name": "Chainlink Sepolia Prod Keystone Cap One 3", + "publicKey": "f4cf97438c3ad86003e5c0368ab52c70f7fbb7f39ae0d7bf6dacbe16807e8a36", + "chainConfigs": [ + { + "network": { + "id": "147", + "chainID": "84532", + "chainType": "EVM", + "name": "Base Testnet (Sepolia)" + }, + "accountAddress": "0x646665317aF70313B3E83Ea1369A91de389DaCAe", + "adminAddress": "0x0000000000000000000000000000000000000000", + "ocr1Config": { + "p2pKeyBundle": {}, + "ocrKeyBundle": {} + }, + "ocr2Config": { + "enabled": true, + "p2pKeyBundle": { + "peerID": "p2p_12D3KooWAvLkcnc8Zttykk6gGeTWFiT6TqgovRHnb6Ym6QqjnLVM", + "publicKey": "1063921b717c3e32210d2803fe684cd818ea2a4a96e405373e5786c8a13c7600" + }, + "ocrKeyBundle": { + "bundleID": "5b46ab201ba66bd93bae6f41afc59c2e578e0f5682fbdf76e1b647fde6d6e8dd", + "configPublicKey": "a01d7d13f3e67ff84ff208cc44c923fe245d02d6029c91dc38422ef44f2bb26e", + "offchainPublicKey": "64eded06a47efc5e311799c1e1fa833cf78d17f079b2f6019c3247debe490439", + "onchainSigningAddress": "afca74e3b850a9435b2dc479ca8bc8e1b45dd0b2" + }, + "plugins": {} + } + }, + { + "network": { + "id": "10", + "chainID": "43113", + "chainType": "EVM", + "name": "Avalanche Testnet (Fuji)" + }, + "accountAddress": "0x3Ab2A4e4765A0374F727a9a9eCE893734e2928ec", + "adminAddress": "0x0000000000000000000000000000000000000000", + "ocr1Config": { + "p2pKeyBundle": {}, + "ocrKeyBundle": {} + }, + "ocr2Config": { + "enabled": true, + "p2pKeyBundle": { + "peerID": "p2p_12D3KooWAvLkcnc8Zttykk6gGeTWFiT6TqgovRHnb6Ym6QqjnLVM", + "publicKey": "1063921b717c3e32210d2803fe684cd818ea2a4a96e405373e5786c8a13c7600" + }, + "ocrKeyBundle": { + "bundleID": "5b46ab201ba66bd93bae6f41afc59c2e578e0f5682fbdf76e1b647fde6d6e8dd", + "configPublicKey": "a01d7d13f3e67ff84ff208cc44c923fe245d02d6029c91dc38422ef44f2bb26e", + "offchainPublicKey": "64eded06a47efc5e311799c1e1fa833cf78d17f079b2f6019c3247debe490439", + "onchainSigningAddress": "afca74e3b850a9435b2dc479ca8bc8e1b45dd0b2" + }, + "plugins": {} + } + }, + { + "network": { + "id": "129", + "chainID": "11155111", + "chainType": "EVM", + "name": "Ethereum Testnet (Sepolia)" + }, + "accountAddress": "0x9905E8C3A4f82037170a8c411CD8b11D4894066f", + "adminAddress": "0x0000000000000000000000000000000000000000", + "ocr1Config": { + "p2pKeyBundle": {}, + "ocrKeyBundle": {} + }, + "ocr2Config": { + "enabled": true, + "p2pKeyBundle": { + "peerID": "p2p_12D3KooWAvLkcnc8Zttykk6gGeTWFiT6TqgovRHnb6Ym6QqjnLVM", + "publicKey": "1063921b717c3e32210d2803fe684cd818ea2a4a96e405373e5786c8a13c7600" + }, + "ocrKeyBundle": { + "bundleID": "5b46ab201ba66bd93bae6f41afc59c2e578e0f5682fbdf76e1b647fde6d6e8dd", + "configPublicKey": "a01d7d13f3e67ff84ff208cc44c923fe245d02d6029c91dc38422ef44f2bb26e", + "offchainPublicKey": "64eded06a47efc5e311799c1e1fa833cf78d17f079b2f6019c3247debe490439", + "onchainSigningAddress": "afca74e3b850a9435b2dc479ca8bc8e1b45dd0b2" + }, + "plugins": {} + } + }, + { + "network": { + "id": "140", + "chainID": "421614", + "chainType": "EVM", + "name": "Arbitrum Testnet (Sepolia)" + }, + "accountAddress": "0x762354eC86ea2253F5da27FF8b952Cb7Dec52B6D", + "adminAddress": "0x0000000000000000000000000000000000000000", + "ocr1Config": { + "p2pKeyBundle": {}, + "ocrKeyBundle": {} + }, + "ocr2Config": { + "enabled": true, + "p2pKeyBundle": { + "peerID": "p2p_12D3KooWAvLkcnc8Zttykk6gGeTWFiT6TqgovRHnb6Ym6QqjnLVM", + "publicKey": "1063921b717c3e32210d2803fe684cd818ea2a4a96e405373e5786c8a13c7600" + }, + "ocrKeyBundle": { + "bundleID": "5b46ab201ba66bd93bae6f41afc59c2e578e0f5682fbdf76e1b647fde6d6e8dd", + "configPublicKey": "a01d7d13f3e67ff84ff208cc44c923fe245d02d6029c91dc38422ef44f2bb26e", + "offchainPublicKey": "64eded06a47efc5e311799c1e1fa833cf78d17f079b2f6019c3247debe490439", + "onchainSigningAddress": "afca74e3b850a9435b2dc479ca8bc8e1b45dd0b2" + }, + "plugins": {} + } + } + ], + "connected": true, + "supportedProducts": [ + "OCR3_CAPABILITY", + "DATA_STREAMS_V03" + ], + "categories": [ + { + "id": "11", + "name": "Keystone" + } + ] + } + ], + "createdAt": "2024-08-14T20:40:30.499914Z" + }, + { + "id": "74", + "keys": [ + "keystone-02", + "keystone-bt-02" + ], + "name": "Chainlink Keystone Node Operator 2", + "metadata": { + "nodeCount": 3, + "jobCount": 5 + }, + "nodes": [ + { + "id": "787", + "name": "Chainlink Sepolia Prod Keystone One 2", + "publicKey": "7a166fbc816eb4a4dcb620d11c3ccac5c085d56b1972374100116f87619debb8", + "chainConfigs": [ + { + "network": { + "id": "140", + "chainID": "421614", + "chainType": "EVM", + "name": "Arbitrum Testnet (Sepolia)" + }, + "accountAddress": "0x693bf95A3ef46E5dABe17d1A89dB1E83948aeD88", + "adminAddress": "0x0000000000000000000000000000000000000000", + "ocr1Config": { + "p2pKeyBundle": {}, + "ocrKeyBundle": {} + }, + "ocr2Config": { + "enabled": true, + "p2pKeyBundle": { + "peerID": "p2p_12D3KooWGDmBKZ7B3PynGrvfHTJMEecpjfHts9YK5NWk8oJuxcAo", + "publicKey": "5f247f61a6d5bfdd1d5064db0bd25fe443648133c6131975edb23481424e3d9c" + }, + "ocrKeyBundle": { + "bundleID": "1d20490fe469dd6af3d418cc310a6e835181fa13e8dc80156bcbe302b7afcd34", + "configPublicKey": "ee466234b3b2f65b13c848b17aa6a8d4e0aa0311d3bf8e77a64f20b04ed48d39", + "offchainPublicKey": "dba3c61e5f8bec594be481bcaf67ecea0d1c2950edb15b158ce3dbc77877def3", + "onchainSigningAddress": "d4dcc573e9d24a8b27a07bba670ba3a2ab36e5bb" + }, + "plugins": {} + } + }, + { + "network": { + "id": "129", + "chainID": "11155111", + "chainType": "EVM", + "name": "Ethereum Testnet (Sepolia)" + }, + "accountAddress": "0xCea84bC1881F3cE14BA13Dc3a00DC1Ff3D553fF0", + "adminAddress": "0x0000000000000000000000000000000000000000", + "ocr1Config": { + "p2pKeyBundle": {}, + "ocrKeyBundle": {} + }, + "ocr2Config": { + "enabled": true, + "p2pKeyBundle": { + "peerID": "p2p_12D3KooWGDmBKZ7B3PynGrvfHTJMEecpjfHts9YK5NWk8oJuxcAo", + "publicKey": "5f247f61a6d5bfdd1d5064db0bd25fe443648133c6131975edb23481424e3d9c" + }, + "ocrKeyBundle": { + "bundleID": "1d20490fe469dd6af3d418cc310a6e835181fa13e8dc80156bcbe302b7afcd34", + "configPublicKey": "ee466234b3b2f65b13c848b17aa6a8d4e0aa0311d3bf8e77a64f20b04ed48d39", + "offchainPublicKey": "dba3c61e5f8bec594be481bcaf67ecea0d1c2950edb15b158ce3dbc77877def3", + "onchainSigningAddress": "d4dcc573e9d24a8b27a07bba670ba3a2ab36e5bb" + }, + "plugins": {} + } + } + ], + "connected": true, + "supportedProducts": [ + "WORKFLOW", + "OCR3_CAPABILITY" + ], + "categories": [ + { + "id": "11", + "name": "Keystone" + } + ] + }, + { + "id": "811", + "name": "Chainlink Sepolia Prod Keystone Cap One 2", + "publicKey": "a1f112923513f13ede1ca8f982ea0ab6221d584b40cd57f0c82307ab79c0e69f", + "chainConfigs": [ + { + "network": { + "id": "10", + "chainID": "43113", + "chainType": "EVM", + "name": "Avalanche Testnet (Fuji)" + }, + "accountAddress": "0xbF1Ad47D99A65e230235537b47C8D1Dddb22FD53", + "adminAddress": "0x0000000000000000000000000000000000000000", + "ocr1Config": { + "p2pKeyBundle": {}, + "ocrKeyBundle": {} + }, + "ocr2Config": { + "enabled": true, + "p2pKeyBundle": { + "peerID": "p2p_12D3KooWQhLYuAxx4WDKafnuhZUTix8Y24gtB92vEUpAC4EdH4VA", + "publicKey": "dd1268a3e7ed4b9c83b1227e5bf2558e6b77af585c66e88a06f1164a1a94f8ed" + }, + "ocrKeyBundle": { + "bundleID": "a11d9438035564bfe84fcfb513b579edbe173fa26c00331e71a010d00b856037", + "configPublicKey": "407cab2a04fa868f645c6848a53abdb8136b08441c50b191651c4f1a348ee700", + "offchainPublicKey": "64a3215839e5630f12ae66b4363f40d82e9c981118c304ca0c4ca5fc2c6e1f37", + "onchainSigningAddress": "6579d77791ee8f8116495dbe6fa6586980177230" + }, + "plugins": {} + } + }, + { + "network": { + "id": "147", + "chainID": "84532", + "chainType": "EVM", + "name": "Base Testnet (Sepolia)" + }, + "accountAddress": "0xa8d4698f74a0A427c1b8ec4575d9dFdD17Be288c", + "adminAddress": "0x0000000000000000000000000000000000000000", + "ocr1Config": { + "p2pKeyBundle": {}, + "ocrKeyBundle": {} + }, + "ocr2Config": { + "enabled": true, + "p2pKeyBundle": { + "peerID": "p2p_12D3KooWQhLYuAxx4WDKafnuhZUTix8Y24gtB92vEUpAC4EdH4VA", + "publicKey": "dd1268a3e7ed4b9c83b1227e5bf2558e6b77af585c66e88a06f1164a1a94f8ed" + }, + "ocrKeyBundle": { + "bundleID": "a11d9438035564bfe84fcfb513b579edbe173fa26c00331e71a010d00b856037", + "configPublicKey": "407cab2a04fa868f645c6848a53abdb8136b08441c50b191651c4f1a348ee700", + "offchainPublicKey": "64a3215839e5630f12ae66b4363f40d82e9c981118c304ca0c4ca5fc2c6e1f37", + "onchainSigningAddress": "6579d77791ee8f8116495dbe6fa6586980177230" + }, + "plugins": {} + } + }, + { + "network": { + "id": "129", + "chainID": "11155111", + "chainType": "EVM", + "name": "Ethereum Testnet (Sepolia)" + }, + "accountAddress": "0xf286c79b4a613a1fE480C8e4fB17B837E7D8ba03", + "adminAddress": "0x0000000000000000000000000000000000000000", + "ocr1Config": { + "p2pKeyBundle": {}, + "ocrKeyBundle": {} + }, + "ocr2Config": { + "enabled": true, + "p2pKeyBundle": { + "peerID": "p2p_12D3KooWQhLYuAxx4WDKafnuhZUTix8Y24gtB92vEUpAC4EdH4VA", + "publicKey": "dd1268a3e7ed4b9c83b1227e5bf2558e6b77af585c66e88a06f1164a1a94f8ed" + }, + "ocrKeyBundle": { + "bundleID": "a11d9438035564bfe84fcfb513b579edbe173fa26c00331e71a010d00b856037", + "configPublicKey": "407cab2a04fa868f645c6848a53abdb8136b08441c50b191651c4f1a348ee700", + "offchainPublicKey": "64a3215839e5630f12ae66b4363f40d82e9c981118c304ca0c4ca5fc2c6e1f37", + "onchainSigningAddress": "6579d77791ee8f8116495dbe6fa6586980177230" + }, + "plugins": {} + } + }, + { + "network": { + "id": "140", + "chainID": "421614", + "chainType": "EVM", + "name": "Arbitrum Testnet (Sepolia)" + }, + "accountAddress": "0xfe85A25cE2CB58b280CC0316305fC678Bf570f5e", + "adminAddress": "0x0000000000000000000000000000000000000000", + "ocr1Config": { + "p2pKeyBundle": {}, + "ocrKeyBundle": {} + }, + "ocr2Config": { + "enabled": true, + "p2pKeyBundle": { + "peerID": "p2p_12D3KooWQhLYuAxx4WDKafnuhZUTix8Y24gtB92vEUpAC4EdH4VA", + "publicKey": "dd1268a3e7ed4b9c83b1227e5bf2558e6b77af585c66e88a06f1164a1a94f8ed" + }, + "ocrKeyBundle": { + "bundleID": "a11d9438035564bfe84fcfb513b579edbe173fa26c00331e71a010d00b856037", + "configPublicKey": "407cab2a04fa868f645c6848a53abdb8136b08441c50b191651c4f1a348ee700", + "offchainPublicKey": "64a3215839e5630f12ae66b4363f40d82e9c981118c304ca0c4ca5fc2c6e1f37", + "onchainSigningAddress": "6579d77791ee8f8116495dbe6fa6586980177230" + }, + "plugins": {} + } + } + ], + "connected": true, + "supportedProducts": [ + "OCR3_CAPABILITY", + "DATA_STREAMS_V03" + ], + "categories": [ + { + "id": "11", + "name": "Keystone" + } + ] + } + ], + "createdAt": "2024-08-14T20:41:33.205484Z" + }, + { + "id": "75", + "keys": [ + "keystone-01", + "keystone-bt-01" + ], + "name": "Chainlink Keystone Node Operator 1", + "metadata": { + "nodeCount": 3, + "jobCount": 5 + }, + "nodes": [ + { + "id": "788", + "name": "Chainlink Sepolia Prod Keystone One 1", + "publicKey": "28b91143ec9111796a7d63e14c1cf6bb01b4ed59667ab54f5bc72ebe49c881be", + "chainConfigs": [ + { + "network": { + "id": "140", + "chainID": "421614", + "chainType": "EVM", + "name": "Arbitrum Testnet (Sepolia)" + }, + "accountAddress": "0xe45a754B30FdE9852A826F58c6bd94Fa6554CE96", + "adminAddress": "0x0000000000000000000000000000000000000000", + "ocr1Config": { + "p2pKeyBundle": {}, + "ocrKeyBundle": {} + }, + "ocr2Config": { + "enabled": true, + "p2pKeyBundle": { + "peerID": "p2p_12D3KooWCbDiL7sP9BVby5KaZqPpaVP1RBokoa9ShzH5WhkYX46v", + "publicKey": "2934f31f278e5c60618f85861bd6add54a4525d79a642019bdc87d75d26372c3" + }, + "ocrKeyBundle": { + "bundleID": "7a9b75510b8d09932b98142419bef52436ff725dd9395469473b487ef87fdfb0", + "configPublicKey": "2c45fec2320f6bcd36444529a86d9f8b4439499a5d8272dec9bcbbebb5e1bf01", + "offchainPublicKey": "255096a3b7ade10e29c648e0b407fc486180464f713446b1da04f013df6179c8", + "onchainSigningAddress": "8258f4c4761cc445333017608044a204fd0c006a" + }, + "plugins": {} + } + }, + { + "network": { + "id": "129", + "chainID": "11155111", + "chainType": "EVM", + "name": "Ethereum Testnet (Sepolia)" + }, + "accountAddress": "0x415aa1E9a1bcB3929ed92bFa1F9735Dc0D45AD31", + "adminAddress": "0x0000000000000000000000000000000000000000", + "ocr1Config": { + "p2pKeyBundle": {}, + "ocrKeyBundle": {} + }, + "ocr2Config": { + "enabled": true, + "p2pKeyBundle": { + "peerID": "p2p_12D3KooWCbDiL7sP9BVby5KaZqPpaVP1RBokoa9ShzH5WhkYX46v", + "publicKey": "2934f31f278e5c60618f85861bd6add54a4525d79a642019bdc87d75d26372c3" + }, + "ocrKeyBundle": { + "bundleID": "7a9b75510b8d09932b98142419bef52436ff725dd9395469473b487ef87fdfb0", + "configPublicKey": "2c45fec2320f6bcd36444529a86d9f8b4439499a5d8272dec9bcbbebb5e1bf01", + "offchainPublicKey": "255096a3b7ade10e29c648e0b407fc486180464f713446b1da04f013df6179c8", + "onchainSigningAddress": "8258f4c4761cc445333017608044a204fd0c006a" + }, + "plugins": {} + } + } + ], + "connected": true, + "supportedProducts": [ + "WORKFLOW", + "OCR3_CAPABILITY" + ], + "categories": [ + { + "id": "11", + "name": "Keystone" + } + ] + }, + { + "id": "810", + "name": "Chainlink Sepolia Prod Keystone Cap One 1", + "publicKey": "9ef27cd1855a0ed6932be33c80d7cd9c178307e5a240dbeb9055946359dc5d7f", + "chainConfigs": [ + { + "network": { + "id": "140", + "chainID": "421614", + "chainType": "EVM", + "name": "Arbitrum Testnet (Sepolia)" + }, + "accountAddress": "0xBB465BCa1b289269F2a95a36f5B6fD006Af56ede", + "adminAddress": "0x0000000000000000000000000000000000000000", + "ocr1Config": { + "p2pKeyBundle": {}, + "ocrKeyBundle": {} + }, + "ocr2Config": { + "enabled": true, + "p2pKeyBundle": { + "peerID": "p2p_12D3KooWMNg1a7HvNWuHAPMdveWr1J6NNCVBU1Z4w5swzepT5Wvf", + "publicKey": "abb750e04bee21d830c6ce0f08180853466139fc6055c6737614797c0704d59c" + }, + "ocrKeyBundle": { + "bundleID": "0d176a4c2d68c619d237e419c31a030e5b2162ee031baa8ebc8472623da9b067", + "configPublicKey": "43e4dbf80a9c818a7d35c080f61b6f8f9b175fa1217b1d01168140da75322d5c", + "offchainPublicKey": "707db88237aaaaddc22bf0fe914540ea7b8bbfbe5cf88349cabb26e34762237c", + "onchainSigningAddress": "ac08f52ec257ddbb493e7b9e299dd2c166a7f090" + }, + "plugins": {} + } + }, + { + "network": { + "id": "10", + "chainID": "43113", + "chainType": "EVM", + "name": "Avalanche Testnet (Fuji)" + }, + "accountAddress": "0x5e3618cFF8Ab337b3c73c2775d1a2EC65e5abEF0", + "adminAddress": "0x0000000000000000000000000000000000000000", + "ocr1Config": { + "p2pKeyBundle": {}, + "ocrKeyBundle": {} + }, + "ocr2Config": { + "enabled": true, + "p2pKeyBundle": { + "peerID": "p2p_12D3KooWMNg1a7HvNWuHAPMdveWr1J6NNCVBU1Z4w5swzepT5Wvf", + "publicKey": "abb750e04bee21d830c6ce0f08180853466139fc6055c6737614797c0704d59c" + }, + "ocrKeyBundle": { + "bundleID": "0d176a4c2d68c619d237e419c31a030e5b2162ee031baa8ebc8472623da9b067", + "configPublicKey": "43e4dbf80a9c818a7d35c080f61b6f8f9b175fa1217b1d01168140da75322d5c", + "offchainPublicKey": "707db88237aaaaddc22bf0fe914540ea7b8bbfbe5cf88349cabb26e34762237c", + "onchainSigningAddress": "ac08f52ec257ddbb493e7b9e299dd2c166a7f090" + }, + "plugins": {} + } + }, + { + "network": { + "id": "147", + "chainID": "84532", + "chainType": "EVM", + "name": "Base Testnet (Sepolia)" + }, + "accountAddress": "0x1796BbC2AbbAd5660C8a7812b313E1f48A99f1D1", + "adminAddress": "0x0000000000000000000000000000000000000000", + "ocr1Config": { + "p2pKeyBundle": {}, + "ocrKeyBundle": {} + }, + "ocr2Config": { + "enabled": true, + "p2pKeyBundle": { + "peerID": "p2p_12D3KooWMNg1a7HvNWuHAPMdveWr1J6NNCVBU1Z4w5swzepT5Wvf", + "publicKey": "abb750e04bee21d830c6ce0f08180853466139fc6055c6737614797c0704d59c" + }, + "ocrKeyBundle": { + "bundleID": "0d176a4c2d68c619d237e419c31a030e5b2162ee031baa8ebc8472623da9b067", + "configPublicKey": "43e4dbf80a9c818a7d35c080f61b6f8f9b175fa1217b1d01168140da75322d5c", + "offchainPublicKey": "707db88237aaaaddc22bf0fe914540ea7b8bbfbe5cf88349cabb26e34762237c", + "onchainSigningAddress": "ac08f52ec257ddbb493e7b9e299dd2c166a7f090" + }, + "plugins": {} + } + }, + { + "network": { + "id": "129", + "chainID": "11155111", + "chainType": "EVM", + "name": "Ethereum Testnet (Sepolia)" + }, + "accountAddress": "0xA2bfAc45e6878fbE04525C23dFbb11fFb224Ea60", + "adminAddress": "0x0000000000000000000000000000000000000000", + "ocr1Config": { + "p2pKeyBundle": {}, + "ocrKeyBundle": {} + }, + "ocr2Config": { + "enabled": true, + "p2pKeyBundle": { + "peerID": "p2p_12D3KooWMNg1a7HvNWuHAPMdveWr1J6NNCVBU1Z4w5swzepT5Wvf", + "publicKey": "abb750e04bee21d830c6ce0f08180853466139fc6055c6737614797c0704d59c" + }, + "ocrKeyBundle": { + "bundleID": "0d176a4c2d68c619d237e419c31a030e5b2162ee031baa8ebc8472623da9b067", + "configPublicKey": "43e4dbf80a9c818a7d35c080f61b6f8f9b175fa1217b1d01168140da75322d5c", + "offchainPublicKey": "707db88237aaaaddc22bf0fe914540ea7b8bbfbe5cf88349cabb26e34762237c", + "onchainSigningAddress": "ac08f52ec257ddbb493e7b9e299dd2c166a7f090" + }, + "plugins": {} + } + } + ], + "connected": true, + "supportedProducts": [ + "OCR3_CAPABILITY", + "DATA_STREAMS_V03" + ], + "categories": [ + { + "id": "11", + "name": "Keystone" + } + ] + } + ], + "createdAt": "2024-08-14T20:42:05.709664Z" + }, + { + "id": "76", + "keys": [ + "keystone-00", + "keystone-bt-00" + ], + "name": "Chainlink Keystone Node Operator 0", + "metadata": { + "nodeCount": 3, + "jobCount": 5 + }, + "nodes": [ + { + "id": "789", + "name": "Chainlink Sepolia Prod Keystone One 0", + "publicKey": "403b72f0b1b3b5f5a91bcfedb7f28599767502a04b5b7e067fcf3782e23eeb9c", + "chainConfigs": [ + { + "network": { + "id": "140", + "chainID": "421614", + "chainType": "EVM", + "name": "Arbitrum Testnet (Sepolia)" + }, + "accountAddress": "0x1a04C6b4b1A45D20356F93DcE7931F765955BAa7", + "adminAddress": "0x0000000000000000000000000000000000000000", + "ocr1Config": { + "p2pKeyBundle": {}, + "ocrKeyBundle": {} + }, + "ocr2Config": { + "enabled": true, + "p2pKeyBundle": { + "peerID": "p2p_12D3KooWMWUKdoAc2ruZf9f55p7NVFj7AFiPm67xjQ8BZBwkqyYv", + "publicKey": "adb6bf005cdb23f21e11b82d66b9f62628c2939640ed93028bf0dad3923c5a8b" + }, + "ocrKeyBundle": { + "bundleID": "665a101d79d310cb0a5ebf695b06e8fc8082b5cbe62d7d362d80d47447a31fea", + "configPublicKey": "5193f72fc7b4323a86088fb0acb4e4494ae351920b3944bd726a59e8dbcdd45f", + "offchainPublicKey": "03dacd15fc96c965c648e3623180de002b71a97cf6eeca9affb91f461dcd6ce1", + "onchainSigningAddress": "b35409a8d4f9a18da55c5b2bb08a3f5f68d44442" + }, + "plugins": {} + } + }, + { + "network": { + "id": "129", + "chainID": "11155111", + "chainType": "EVM", + "name": "Ethereum Testnet (Sepolia)" + }, + "accountAddress": "0x2877F08d9c5Cc9F401F730Fa418fAE563A9a2FF3", + "adminAddress": "0x0000000000000000000000000000000000000000", + "ocr1Config": { + "p2pKeyBundle": {}, + "ocrKeyBundle": {} + }, + "ocr2Config": { + "enabled": true, + "p2pKeyBundle": { + "peerID": "p2p_12D3KooWMWUKdoAc2ruZf9f55p7NVFj7AFiPm67xjQ8BZBwkqyYv", + "publicKey": "adb6bf005cdb23f21e11b82d66b9f62628c2939640ed93028bf0dad3923c5a8b" + }, + "ocrKeyBundle": { + "bundleID": "665a101d79d310cb0a5ebf695b06e8fc8082b5cbe62d7d362d80d47447a31fea", + "configPublicKey": "5193f72fc7b4323a86088fb0acb4e4494ae351920b3944bd726a59e8dbcdd45f", + "offchainPublicKey": "03dacd15fc96c965c648e3623180de002b71a97cf6eeca9affb91f461dcd6ce1", + "onchainSigningAddress": "b35409a8d4f9a18da55c5b2bb08a3f5f68d44442" + }, + "plugins": {} + } + } + ], + "connected": true, + "supportedProducts": [ + "WORKFLOW", + "OCR3_CAPABILITY" + ], + "categories": [ + { + "id": "11", + "name": "Keystone" + } + ] + }, + { + "id": "809", + "name": "Chainlink Sepolia Prod Keystone Cap One 0", + "publicKey": "545197637db59b96b22528ff90960b9e7cdcea81c8a5a9f06ae6b728bcba35cb", + "chainConfigs": [ + { + "network": { + "id": "10", + "chainID": "43113", + "chainType": "EVM", + "name": "Avalanche Testnet (Fuji)" + }, + "accountAddress": "0x66a88b0a23D8351e8F5e228eEe8439e65F423842", + "adminAddress": "0x0000000000000000000000000000000000000000", + "ocr1Config": { + "p2pKeyBundle": {}, + "ocrKeyBundle": {} + }, + "ocr2Config": { + "enabled": true, + "p2pKeyBundle": { + "peerID": "p2p_12D3KooWFux8Vvs8CPfUSKitXwQsq81ZBhQYcbKRH5L5jkFbQ6nH", + "publicKey": "5a946cfec8e3c33f6c88961dcab2bbd8bb9d05538c8f931bb62d59b1d7fd782e" + }, + "ocrKeyBundle": { + "bundleID": "d9a3c3afdb310ba11b058afd6ee3159edfbc740df4daefd65c257a7ed46ed9ef", + "configPublicKey": "64fd95e7bcbb33e3dd548247352bb7be5ea6577a840e5e3b66336f710b5b272e", + "offchainPublicKey": "216b1e3dc51ad21be806c010397cc2e0bf59b2a06ade89bc7d0c0a7299a4e01e", + "onchainSigningAddress": "a4f0acbe902443aa842db278f421da99cdc47a8b" + }, + "plugins": {} + } + }, + { + "network": { + "id": "129", + "chainID": "11155111", + "chainType": "EVM", + "name": "Ethereum Testnet (Sepolia)" + }, + "accountAddress": "0x36a46774A3743641D4C274b385608Cb455B5B6b8", + "adminAddress": "0x0000000000000000000000000000000000000000", + "ocr1Config": { + "p2pKeyBundle": {}, + "ocrKeyBundle": {} + }, + "ocr2Config": { + "enabled": true, + "p2pKeyBundle": { + "peerID": "p2p_12D3KooWFux8Vvs8CPfUSKitXwQsq81ZBhQYcbKRH5L5jkFbQ6nH", + "publicKey": "5a946cfec8e3c33f6c88961dcab2bbd8bb9d05538c8f931bb62d59b1d7fd782e" + }, + "ocrKeyBundle": { + "bundleID": "d9a3c3afdb310ba11b058afd6ee3159edfbc740df4daefd65c257a7ed46ed9ef", + "configPublicKey": "64fd95e7bcbb33e3dd548247352bb7be5ea6577a840e5e3b66336f710b5b272e", + "offchainPublicKey": "216b1e3dc51ad21be806c010397cc2e0bf59b2a06ade89bc7d0c0a7299a4e01e", + "onchainSigningAddress": "a4f0acbe902443aa842db278f421da99cdc47a8b" + }, + "plugins": {} + } + }, + { + "network": { + "id": "147", + "chainID": "84532", + "chainType": "EVM", + "name": "Base Testnet (Sepolia)" + }, + "accountAddress": "0x868ab67c00fF7e21aFf470C066798e5bE4240305", + "adminAddress": "0x0000000000000000000000000000000000000000", + "ocr1Config": { + "p2pKeyBundle": {}, + "ocrKeyBundle": {} + }, + "ocr2Config": { + "enabled": true, + "p2pKeyBundle": { + "peerID": "p2p_12D3KooWFux8Vvs8CPfUSKitXwQsq81ZBhQYcbKRH5L5jkFbQ6nH", + "publicKey": "5a946cfec8e3c33f6c88961dcab2bbd8bb9d05538c8f931bb62d59b1d7fd782e" + }, + "ocrKeyBundle": { + "bundleID": "d9a3c3afdb310ba11b058afd6ee3159edfbc740df4daefd65c257a7ed46ed9ef", + "configPublicKey": "64fd95e7bcbb33e3dd548247352bb7be5ea6577a840e5e3b66336f710b5b272e", + "offchainPublicKey": "216b1e3dc51ad21be806c010397cc2e0bf59b2a06ade89bc7d0c0a7299a4e01e", + "onchainSigningAddress": "a4f0acbe902443aa842db278f421da99cdc47a8b" + }, + "plugins": {} + } + }, + { + "network": { + "id": "140", + "chainID": "421614", + "chainType": "EVM", + "name": "Arbitrum Testnet (Sepolia)" + }, + "accountAddress": "0xa60bC482fCfcd12B752541a00555E4e448Bc1d16", + "adminAddress": "0x0000000000000000000000000000000000000000", + "ocr1Config": { + "p2pKeyBundle": {}, + "ocrKeyBundle": {} + }, + "ocr2Config": { + "enabled": true, + "p2pKeyBundle": { + "peerID": "p2p_12D3KooWFux8Vvs8CPfUSKitXwQsq81ZBhQYcbKRH5L5jkFbQ6nH", + "publicKey": "5a946cfec8e3c33f6c88961dcab2bbd8bb9d05538c8f931bb62d59b1d7fd782e" + }, + "ocrKeyBundle": { + "bundleID": "d9a3c3afdb310ba11b058afd6ee3159edfbc740df4daefd65c257a7ed46ed9ef", + "configPublicKey": "64fd95e7bcbb33e3dd548247352bb7be5ea6577a840e5e3b66336f710b5b272e", + "offchainPublicKey": "216b1e3dc51ad21be806c010397cc2e0bf59b2a06ade89bc7d0c0a7299a4e01e", + "onchainSigningAddress": "a4f0acbe902443aa842db278f421da99cdc47a8b" + }, + "plugins": {} + } + } + ], + "connected": true, + "supportedProducts": [ + "OCR3_CAPABILITY", + "DATA_STREAMS_V03" + ], + "categories": [ + { + "id": "11", + "name": "Keystone" + } + ] + } + ], + "createdAt": "2024-08-14T20:42:49.446864Z" + }, + { + "id": "81", + "keys": [ + "cl-df-asset-don-testnet-0" + ], + "name": "Chainlink Keystone Asset DON Node Operator 0", + "metadata": { + "nodeCount": 2, + "jobCount": 18 + }, + "nodes": [ + { + "id": "831", + "name": "Chainlink Sepolia Prod Keystone Asset Node 0", + "publicKey": "d791dad33f1aeff811f3364088993053d5d08fa595ba48f73aecd4ee2d5035a1", + "chainConfigs": [ + { + "network": { + "id": "129", + "chainID": "11155111", + "chainType": "EVM", + "name": "Ethereum Testnet (Sepolia)" + }, + "accountAddress": "0xe826b8D7f57b1c08E2d0C9477006244AECB280c3", + "adminAddress": "0x900FDC4d45297A743e4508986d4C1aa1BAf89A83", + "ocr1Config": { + "p2pKeyBundle": {}, + "ocrKeyBundle": {} + }, + "ocr2Config": { + "enabled": true, + "p2pKeyBundle": { + "peerID": "p2p_12D3KooWDh47EiK5TzG4yApEEwLecgRkqZKQif3fcnsztfhQNzNh", + "publicKey": "398f42d12c7f3445341e42ce4ea555c87d84db68c808c76a0655e5d993d7a2a6" + }, + "ocrKeyBundle": { + "bundleID": "c8dee638c00194cf38bd0c30306fffd14b561601828085ceaaf0ab5fe451ec23", + "configPublicKey": "dbd5d1f5aa4921fd1e7b16f26dc75aff5cc08fee6e74324e947654ba78791e7e", + "offchainPublicKey": "66a599cda37e6fb5dc50e16d7c81e6967e010a25bbeaabf20752e228a26f5bc3", + "onchainSigningAddress": "9184c1c20da57f2f747a60909d0152c289e8518f" + }, + "plugins": { + "mercury": true + } + } + } + ], + "connected": true, + "supportedProducts": [ + "DATA_STREAMS_V03" + ], + "categories": [ + { + "id": "11", + "name": "Keystone" + } + ] + } + ], + "createdAt": "2024-09-18T19:19:34.127102Z" + }, + { + "id": "82", + "keys": [ + "cl-df-asset-don-testnet-1" + ], + "name": "Chainlink Keystone Asset DON Node Operator 1", + "metadata": { + "nodeCount": 1, + "jobCount": 9 + }, + "nodes": [ + { + "id": "832", + "name": "Chainlink Sepolia Prod Keystone Asset Node 1", + "publicKey": "eb410038ba7847a729c4e40c1d4afdbcce9ad33cc71e459883cd98f0883a5366", + "chainConfigs": [ + { + "network": { + "id": "129", + "chainID": "11155111", + "chainType": "EVM", + "name": "Ethereum Testnet (Sepolia)" + }, + "accountAddress": "0xCE154165b0d60D1efA9b3c7a172ED77712Cb82f9", + "adminAddress": "0x900FDC4d45297A743e4508986d4C1aa1BAf89A83", + "ocr1Config": { + "p2pKeyBundle": {}, + "ocrKeyBundle": {} + }, + "ocr2Config": { + "enabled": true, + "p2pKeyBundle": { + "peerID": "p2p_12D3KooWG7WEsQjxXQdn5WAEQSDh77qxjMoWxz3rGYrRC9pPB7qx", + "publicKey": "5d8a1f11ecd0cd2cdd95fec35b8ea6386af567bc96aa2c2ea47e91d22b1f12bf" + }, + "ocrKeyBundle": { + "bundleID": "a6dda044db7fa1fa652ec9ff60a44fb31ee99d33db35599848b21e34ce33c343", + "configPublicKey": "586fb9935401e8907ead91e7a3423a0c0676d4669bac619f71c99913e14b362a", + "offchainPublicKey": "9557c0c4c6c8aeb41ecaa84f0aa7d0e1be7ffa9e4a08da27b23bd64b2d0c0fe9", + "onchainSigningAddress": "bd3e16dda612f543c0f79fafc03fa35f3f300e30" + }, + "plugins": { + "mercury": true + } + } + } + ], + "connected": true, + "supportedProducts": [ + "DATA_STREAMS_V03" + ], + "categories": [ + { + "id": "11", + "name": "Keystone" + } + ] + } + ], + "createdAt": "2024-09-18T19:19:48.159926Z" + }, + { + "id": "83", + "keys": [ + "cl-df-asset-don-testnet-2" + ], + "name": "Chainlink Keystone Asset DON Node Operator 2", + "metadata": { + "nodeCount": 1, + "jobCount": 9 + }, + "nodes": [ + { + "id": "833", + "name": "Chainlink Sepolia Prod Keystone Asset Node 2", + "publicKey": "daf14b79caa585c3dacf550688aeed5371f8fd39cbfb6e33add2fb82538626b0", + "chainConfigs": [ + { + "network": { + "id": "129", + "chainID": "11155111", + "chainType": "EVM", + "name": "Ethereum Testnet (Sepolia)" + }, + "accountAddress": "0xbb16a69A7bb8778dc52a2D081EE1B2Dde0237F3b", + "adminAddress": "0x900FDC4d45297A743e4508986d4C1aa1BAf89A83", + "ocr1Config": { + "p2pKeyBundle": {}, + "ocrKeyBundle": {} + }, + "ocr2Config": { + "enabled": true, + "p2pKeyBundle": { + "peerID": "p2p_12D3KooWBWms38viHaptUHTXXNdN4Qm2ZxDWtuaZviZtq1WzWWcq", + "publicKey": "1935b60309f79e7fd1bfd4736df5729b7532bcd435be2a707dd28519e9ae6e6a" + }, + "ocrKeyBundle": { + "bundleID": "9c63a332ff254cd2cda8bcf2c3f0e46ee95d4991595019619a0c60907437d98c", + "configPublicKey": "29b9b6f61db8e72df13e17e274bdf5450987953079b9dee2745f2d288dc7e86d", + "offchainPublicKey": "c3b08d0b68baf68da2c8446f6a9dc552af3ab2014b900d75ca9e2122b6fc9eb0", + "onchainSigningAddress": "cb66494d66922ad00708bce7c83ada133ddb8994" + }, + "plugins": { + "mercury": true + } + } + } + ], + "connected": true, + "supportedProducts": [ + "DATA_STREAMS_V03" + ], + "categories": [ + { + "id": "11", + "name": "Keystone" + } + ] + } + ], + "createdAt": "2024-09-18T19:20:01.151494Z" + }, + { + "id": "84", + "keys": [ + "cl-df-asset-don-testnet-3" + ], + "name": "Chainlink Keystone Asset DON Node Operator 3", + "metadata": { + "nodeCount": 1, + "jobCount": 9 + }, + "nodes": [ + { + "id": "834", + "name": "Chainlink Sepolia Prod Keystone Asset Node 3", + "publicKey": "0e1f9462a8b326d746fde2d5016faa9f2e017f7e6e5969aaf3281519d2e31dbc", + "chainConfigs": [ + { + "network": { + "id": "129", + "chainID": "11155111", + "chainType": "EVM", + "name": "Ethereum Testnet (Sepolia)" + }, + "accountAddress": "0xA64f65e0c12ab015792c34867BE5b80b4D4C551A", + "adminAddress": "0x900FDC4d45297A743e4508986d4C1aa1BAf89A83", + "ocr1Config": { + "p2pKeyBundle": {}, + "ocrKeyBundle": {} + }, + "ocr2Config": { + "enabled": true, + "p2pKeyBundle": { + "peerID": "p2p_12D3KooWMhHZTVHz23gCQAEzFyeBLxR9ghVqMQHk18VND4TbAc1U", + "publicKey": "b07bf77b2b1d8964915d4871b4cd0173e13bc1d0590731a8969393a6e80aef8f" + }, + "ocrKeyBundle": { + "bundleID": "87770ad41d54661a6dee424612f4338b49cd4fd20bdab1f11c308c76efeb56f8", + "configPublicKey": "dd0edc91d1476a0a4c554e8fe8050dadba679ba42f53973bf181d85eed1b6821", + "offchainPublicKey": "2ba2cc779c8e1460d9ff823d594708a344bb7a9d84aa3aa3833d539852511a88", + "onchainSigningAddress": "5e5b1a602c5a79ec6cdeb67e6f855d58061f785f" + }, + "plugins": { + "mercury": true + } + } + } + ], + "connected": true, + "supportedProducts": [ + "DATA_STREAMS_V03" + ], + "categories": [ + { + "id": "11", + "name": "Keystone" + } + ] + } + ], + "createdAt": "2024-09-18T19:20:10.382565Z" + }, + { + "id": "85", + "keys": [ + "cl-df-asset-don-testnet-4" + ], + "name": "Chainlink Keystone Asset DON Node Operator 4", + "metadata": { + "nodeCount": 1, + "jobCount": 9 + }, + "nodes": [ + { + "id": "835", + "name": "Chainlink Sepolia Prod Keystone Asset Node 4", + "publicKey": "1d5f6ef3443e48bd471efdb47a5b9c6c900a14f35253c2b562908186f5b8b457", + "chainConfigs": [ + { + "network": { + "id": "129", + "chainID": "11155111", + "chainType": "EVM", + "name": "Ethereum Testnet (Sepolia)" + }, + "accountAddress": "0x7284bBa5C8090Ac99d55b14db015a291C017275c", + "adminAddress": "0x900FDC4d45297A743e4508986d4C1aa1BAf89A83", + "ocr1Config": { + "p2pKeyBundle": {}, + "ocrKeyBundle": {} + }, + "ocr2Config": { + "enabled": true, + "p2pKeyBundle": { + "peerID": "p2p_12D3KooWMrkkbkFYJydLhcYKr8AnxNcNGmwfVXMQGdn8uoSpYoJs", + "publicKey": "b2e8f0b25c7334e8082cb82eee29bc4f48ae086b8fe4a2fd5eb4e08195a0e06c" + }, + "ocrKeyBundle": { + "bundleID": "1ceac31d893d21e95a62419d94b1a88805fa4f056b1636ccd79ab0ca8b4fe68c", + "configPublicKey": "4c94f49461fd0fd9d4da5cda4590a2cf80fba2ea27c422b92ee18a3aaaa51321", + "offchainPublicKey": "d1649b393614e01811979340d2726280f9ea57fd7a1ee28958adbbaf71b41bf5", + "onchainSigningAddress": "e47d17607054e9899d3fb7fa5b4b3e01b85b8fc9" + }, + "plugins": { + "mercury": true + } + } + } + ], + "connected": true, + "supportedProducts": [ + "DATA_STREAMS_V03" + ], + "categories": [ + { + "id": "11", + "name": "Keystone" + } + ] + } + ], + "createdAt": "2024-09-18T19:20:21.050174Z" + }, + { + "id": "86", + "keys": [ + "cl-df-asset-don-testnet-5" + ], + "name": "Chainlink Keystone Asset DON Node Operator 5", + "metadata": { + "nodeCount": 1, + "jobCount": 9 + }, + "nodes": [ + { + "id": "837", + "name": "Chainlink Sepolia Prod Keystone Asset Node 5", + "publicKey": "d87dfbb7444036e0654578afdb11864e31a0de1824ca2780f24b16116a85463d", + "chainConfigs": [ + { + "network": { + "id": "129", + "chainID": "11155111", + "chainType": "EVM", + "name": "Ethereum Testnet (Sepolia)" + }, + "accountAddress": "0x6c75DB65540ca889803a092d4C1497D3337cDE30", + "adminAddress": "0x900FDC4d45297A743e4508986d4C1aa1BAf89A83", + "ocr1Config": { + "p2pKeyBundle": {}, + "ocrKeyBundle": {} + }, + "ocr2Config": { + "enabled": true, + "p2pKeyBundle": { + "peerID": "p2p_12D3KooWH8q69DtEqahJdwKfYXnkRHHH6E4jTqevZSAZzGsrnsTB", + "publicKey": "6cbcb3cc0a48ec9d94bb1424beea5e1b7cf57fda2dbfc519afd9221cbeac3b8e" + }, + "ocrKeyBundle": { + "bundleID": "6e088c00e61fea95a5a808a56e7e55c58ec0d61c3207383a2c63abc705bd120c", + "configPublicKey": "0728ce40c95155853ecd31bc213ed2b39d4ecf2e62dc95334f008181ad010848", + "offchainPublicKey": "521d4c291fe8ef245b2e497982b0a07127cd3c65439a10784d914e03ba24328d", + "onchainSigningAddress": "d32a6ed4be6656fd988a0e43e71ce43fab3faba4" + }, + "plugins": { + "mercury": true + } + } + } + ], + "connected": true, + "supportedProducts": [ + "DATA_STREAMS_V03" + ], + "categories": [ + { + "id": "11", + "name": "Keystone" + } + ] + } + ], + "createdAt": "2024-09-18T19:21:21.831183Z" + }, + { + "id": "87", + "keys": [ + "cl-df-asset-don-testnet-6" + ], + "name": "Chainlink Keystone Asset DON Node Operator 6", + "metadata": { + "nodeCount": 1, + "jobCount": 9 + }, + "nodes": [ + { + "id": "838", + "name": "Chainlink Sepolia Prod Keystone Asset Node 6", + "publicKey": "294f58723d4049af0dcd63eedfcda957287401a10070db509ede7a799bb70654", + "chainConfigs": [ + { + "network": { + "id": "129", + "chainID": "11155111", + "chainType": "EVM", + "name": "Ethereum Testnet (Sepolia)" + }, + "accountAddress": "0xa2788731913cc2deBC061F8594AEaa8e99B4FCCE", + "adminAddress": "0x900FDC4d45297A743e4508986d4C1aa1BAf89A83", + "ocr1Config": { + "p2pKeyBundle": {}, + "ocrKeyBundle": {} + }, + "ocr2Config": { + "enabled": true, + "p2pKeyBundle": { + "peerID": "p2p_12D3KooWD7URmTzSeotMvEzkJTiFrwUHhcGMBeaS9GY8763Sqqnf", + "publicKey": "30f502f9fb19b54e8644f038f57f9a43582f76b86bace61759fff12886ccf1a8" + }, + "ocrKeyBundle": { + "bundleID": "57bc2a8a62ed96e6aa7b9bbe56f93abeef938a1766cb8a6d18e42ebf71101646", + "configPublicKey": "36c882b0cdcec84aa85f00ea43cd31254406cec84d31f6dded69b4fbb3f17449", + "offchainPublicKey": "46951e1e18cee25cd417b3fa7feb25fb53623a249e1c09491bb978dccc2ea76e", + "onchainSigningAddress": "abcd8be3952a84fb10947dbeb768a255ead58ca2" + }, + "plugins": { + "mercury": true + } + } + } + ], + "connected": true, + "supportedProducts": [ + "DATA_STREAMS_V03" + ], + "categories": [ + { + "id": "11", + "name": "Keystone" + } + ] + } + ], + "createdAt": "2024-09-18T19:21:34.93501Z" + }, + { + "id": "88", + "keys": [ + "cl-df-asset-don-testnet-7" + ], + "name": "Chainlink Keystone Asset DON Node Operator 7", + "metadata": { + "nodeCount": 1, + "jobCount": 9 + }, + "nodes": [ + { + "id": "839", + "name": "Chainlink Sepolia Prod Keystone Asset Node 7", + "publicKey": "55b0ec5d90de973c00efce233334a9d3c5a94062ea010575bb248eb6804a9cfe", + "chainConfigs": [ + { + "network": { + "id": "129", + "chainID": "11155111", + "chainType": "EVM", + "name": "Ethereum Testnet (Sepolia)" + }, + "accountAddress": "0x14dAF00DaD855089A6586690d5C1fD2779302736", + "adminAddress": "0x900FDC4d45297A743e4508986d4C1aa1BAf89A83", + "ocr1Config": { + "p2pKeyBundle": {}, + "ocrKeyBundle": {} + }, + "ocr2Config": { + "enabled": true, + "p2pKeyBundle": { + "peerID": "p2p_12D3KooWBbo44H5CLACV3yGyDWrtMuSWRdN5sQcDsnPC4WfLr6Jo", + "publicKey": "1a7ef5e7420434fcf06de3d15a0191f7499e00e15427679616ce800779ceb514" + }, + "ocrKeyBundle": { + "bundleID": "f87acde2c1c21e8859d84813034d84a3f3bb1d49596e13ac66731d50750b9436", + "configPublicKey": "e75f21bc1dc6eac12358277caf18a216ed54f8dc84285941ef1f5fb1047f8d5b", + "offchainPublicKey": "c7b86dfbdf31a3b13c44305cd6fc88c402653198201006083414223ffc36950d", + "onchainSigningAddress": "93fbb113f191959f8ab5e052395676e0038f2f1f" + }, + "plugins": { + "mercury": true + } + } + } + ], + "connected": true, + "supportedProducts": [ + "DATA_STREAMS_V03" + ], + "categories": [ + { + "id": "11", + "name": "Keystone" + } + ] + } + ], + "createdAt": "2024-09-18T19:21:45.063449Z" + }, + { + "id": "89", + "keys": [ + "cl-df-asset-don-testnet-8" + ], + "name": "Chainlink Keystone Asset DON Node Operator 8", + "metadata": { + "nodeCount": 1, + "jobCount": 9 + }, + "nodes": [ + { + "id": "840", + "name": "Chainlink Sepolia Prod Keystone Asset Node 8", + "publicKey": "8f9f327ac7ad823a0f3297f3505591bcd40adc8fb1309f99874c26663cbd5914", + "chainConfigs": [ + { + "network": { + "id": "129", + "chainID": "11155111", + "chainType": "EVM", + "name": "Ethereum Testnet (Sepolia)" + }, + "accountAddress": "0xb0C0168905C07F00A141494eaeFc0bD9F153fc16", + "adminAddress": "0x900FDC4d45297A743e4508986d4C1aa1BAf89A83", + "ocr1Config": { + "p2pKeyBundle": {}, + "ocrKeyBundle": {} + }, + "ocr2Config": { + "enabled": true, + "p2pKeyBundle": { + "peerID": "p2p_12D3KooWGVroAehJh33SBns9MohmctNPZSDh89KRQM1J6TSCnT1v", + "publicKey": "63442493270891409900afd3bb868d03fd07c775bb38c56e56a624b674a68b35" + }, + "ocrKeyBundle": { + "bundleID": "4413e0a3080c3dfa7709b16c3ee68c04359e2dd66d107fd3be6ba7c615c4b3b6", + "configPublicKey": "8f3975b19fc6f02e241119b2132331ed9ed0d19221bd0cfd6f54b5859090a741", + "offchainPublicKey": "f4f182c889668d8951932c49e1ffb1252b8a33a9875d3f19aea7bb805b65c7a6", + "onchainSigningAddress": "b257e9efe637f38b5462a170737571ea0f0e2e05" + }, + "plugins": { + "mercury": true + } + } + } + ], + "connected": true, + "supportedProducts": [ + "DATA_STREAMS_V03" + ], + "categories": [ + { + "id": "11", + "name": "Keystone" + } + ] + } + ], + "createdAt": "2024-09-18T19:21:55.09098Z" + }, + { + "id": "90", + "keys": [ + "cl-df-asset-don-testnet-9" + ], + "name": "Chainlink Keystone Asset DON Node Operator 9", + "metadata": { + "nodeCount": 1, + "jobCount": 9 + }, + "nodes": [ + { + "id": "841", + "name": "Chainlink Sepolia Prod Keystone Asset Node 9", + "publicKey": "1d79884071dfec1f39dc62f4868f4a143ae39cb03ad9d14142b184686c2b5a93", + "chainConfigs": [ + { + "network": { + "id": "129", + "chainID": "11155111", + "chainType": "EVM", + "name": "Ethereum Testnet (Sepolia)" + }, + "accountAddress": "0x2F5E08a5b9D893e9dA2d68Ef605fBa6f8Ebfd0cB", + "adminAddress": "0x900FDC4d45297A743e4508986d4C1aa1BAf89A83", + "ocr1Config": { + "p2pKeyBundle": {}, + "ocrKeyBundle": {} + }, + "ocr2Config": { + "enabled": true, + "p2pKeyBundle": { + "peerID": "p2p_12D3KooWEBn9tWmMWrSxRZe2VQ56RcSHRUPdcFoD3Ep88wqTT9zP", + "publicKey": "40eb109d9f28e8754dfff419a9175d6714405907413d2f77657355721c3b2bd0" + }, + "ocrKeyBundle": { + "bundleID": "6d4da72b1daad0b9ea47a7daa6cde81c1608b7bd199c05b18b989d10c5d7b99e", + "configPublicKey": "7e1c66bfa23c270770401d0dd739adad5a52827ecb40a0668f7e014d53f38059", + "offchainPublicKey": "712561a10b1f7dd96f0ae0f0d3e6cdf83fdd0837d333cf9bbae0090126ae7f39", + "onchainSigningAddress": "2ef8cea7dae7bd1e876a59a44ca59b89adf8abb4" + }, + "plugins": { + "mercury": true + } + } + } + ], + "connected": true, + "supportedProducts": [ + "DATA_STREAMS_V03" + ], + "categories": [ + { + "id": "11", + "name": "Keystone" + } + ] + } + ], + "createdAt": "2024-09-18T19:22:09.476108Z" + }, + { + "id": "91", + "keys": [ + "cl-df-asset-don-testnet-10" + ], + "name": "Chainlink Keystone Asset DON Node Operator 10", + "metadata": { + "nodeCount": 1, + "jobCount": 9 + }, + "nodes": [ + { + "id": "842", + "name": "Chainlink Sepolia Prod Keystone Asset Node 10", + "publicKey": "cf6c47ad934518f5947ce8f1a48c2df8c93bd585788a3a82229fd4d723efa706", + "chainConfigs": [ + { + "network": { + "id": "129", + "chainID": "11155111", + "chainType": "EVM", + "name": "Ethereum Testnet (Sepolia)" + }, + "accountAddress": "0x4794743bB8f159954Efa31642609ebfD4D2b9EdC", + "adminAddress": "0x900FDC4d45297A743e4508986d4C1aa1BAf89A83", + "ocr1Config": { + "p2pKeyBundle": {}, + "ocrKeyBundle": {} + }, + "ocr2Config": { + "enabled": true, + "p2pKeyBundle": { + "peerID": "p2p_12D3KooWNXZCbQe4Ao7KEciJGY6Ec4oZLZNGcMTPyZ7XpFhLPyLo", + "publicKey": "bcd987b3b2b20d9effe30598850ddfd33023339dab012c4aee4cdc4246111bfc" + }, + "ocrKeyBundle": { + "bundleID": "a8d9929327d89cfabd8c583d250dfddbc14e947e9253f7471191886ca5197786", + "configPublicKey": "a1a390e756bce818d1786dca6ba3e45013085087e5a3be6253d8bbbd6479255a", + "offchainPublicKey": "76522fec251ce6130c03a816025f2054eb3ac83b7d30347f42b73a77e7b9a511", + "onchainSigningAddress": "179d48901e5e9c3c11dd947c001f8a2ee887c8eb" + }, + "plugins": { + "mercury": true + } + } + } + ], + "connected": true, + "supportedProducts": [ + "DATA_STREAMS_V03" + ], + "categories": [ + { + "id": "11", + "name": "Keystone" + } + ] + } + ], + "createdAt": "2024-09-18T19:22:30.732346Z" + }, + { + "id": "92", + "keys": [ + "cl-df-asset-don-testnet-11" + ], + "name": "Chainlink Keystone Asset DON Node Operator 11", + "metadata": { + "nodeCount": 1, + "jobCount": 9 + }, + "nodes": [ + { + "id": "843", + "name": "Chainlink Sepolia Prod Keystone Asset Node 11", + "publicKey": "c239c23670224558a64ea3165eae8d67a17b75b1874fbccf8a4dd98e953820ad", + "chainConfigs": [ + { + "network": { + "id": "129", + "chainID": "11155111", + "chainType": "EVM", + "name": "Ethereum Testnet (Sepolia)" + }, + "accountAddress": "0x27AFd92F391dFD7BA1bbC89e3bd13ceC9A667c11", + "adminAddress": "0x900FDC4d45297A743e4508986d4C1aa1BAf89A83", + "ocr1Config": { + "p2pKeyBundle": {}, + "ocrKeyBundle": {} + }, + "ocr2Config": { + "enabled": true, + "p2pKeyBundle": { + "peerID": "p2p_12D3KooWSSzLfwq7QSdJcpDLFiBznA1XR58dwg1xre4b88SbP7VF", + "publicKey": "f71ccc7f7b73f1499f72987679a94a11e8564f01415acdb958c008c5bfe21eae" + }, + "ocrKeyBundle": { + "bundleID": "3e691b13aa702631fba25f6e128a566bdff3982cc3438af29acc2a819b9d6e02", + "configPublicKey": "149d81dce137d0874b477ad6c19dc72801f335200622fa34f1c660623febed22", + "offchainPublicKey": "b0d0d8e3c62abc7236e6539413ef82e568dd24f0c39ff6e8e2babe513590a522", + "onchainSigningAddress": "a0f2feab4d03899eb2e830bd4abc3fd5babef3e1" + }, + "plugins": { + "mercury": true + } + } + } + ], + "connected": true, + "supportedProducts": [ + "DATA_STREAMS_V03" + ], + "categories": [ + { + "id": "11", + "name": "Keystone" + } + ] + } + ], + "createdAt": "2024-09-18T19:22:42.314654Z" + }, + { + "id": "93", + "keys": [ + "cl-df-asset-don-testnet-12" + ], + "name": "Chainlink Keystone Asset DON Node Operator 12", + "metadata": { + "nodeCount": 1, + "jobCount": 9 + }, + "nodes": [ + { + "id": "844", + "name": "Chainlink Sepolia Prod Keystone Asset Node 12", + "publicKey": "71b29eb63daa6ac2e48b46669936eff5606879b102bae78afc929554c435dd0b", + "chainConfigs": [ + { + "network": { + "id": "129", + "chainID": "11155111", + "chainType": "EVM", + "name": "Ethereum Testnet (Sepolia)" + }, + "accountAddress": "0x13d5b27d71B4C4697874177Ff43DEB1884Cff49e", + "adminAddress": "0x900FDC4d45297A743e4508986d4C1aa1BAf89A83", + "ocr1Config": { + "p2pKeyBundle": {}, + "ocrKeyBundle": {} + }, + "ocr2Config": { + "enabled": true, + "p2pKeyBundle": { + "peerID": "p2p_12D3KooWT1LMqEW51UfxBynzjYjuybQzVkmf4rH9js9e16QAbU3X", + "publicKey": "ff66057a6c96779134a6527364cddcce43b69e3d1820f59dde5e6b38d1d32fde" + }, + "ocrKeyBundle": { + "bundleID": "4854ee3fc7ac4591eea33c5d0d1cefd4ad819d2c374a2f86267a9999228a967a", + "configPublicKey": "470225644f274147b5b80c862a3f3cd7a19fed4ff915e9c18ac80e06003ecc6a", + "offchainPublicKey": "e7d89e196f5f6d92f4c42ab34f9a2f21f3201314be65b819872c4609b87866c7", + "onchainSigningAddress": "c84f2f60ccb1d7e6c6e4ae4bc3cab8bb85db8977" + }, + "plugins": { + "mercury": true + } + } + } + ], + "connected": true, + "supportedProducts": [ + "DATA_STREAMS_V03" + ], + "categories": [ + { + "id": "11", + "name": "Keystone" + } + ] + } + ], + "createdAt": "2024-09-18T19:22:52.838595Z" + }, + { + "id": "94", + "keys": [ + "cl-df-asset-don-testnet-13" + ], + "name": "Chainlink Keystone Asset DON Node Operator 13", + "metadata": { + "nodeCount": 1, + "jobCount": 9 + }, + "nodes": [ + { + "id": "845", + "name": "Chainlink Sepolia Prod Keystone Asset Node 13", + "publicKey": "c098264a552125355804b903de06400621f2d1de357c2bed94586727fe8a3502", + "chainConfigs": [ + { + "network": { + "id": "129", + "chainID": "11155111", + "chainType": "EVM", + "name": "Ethereum Testnet (Sepolia)" + }, + "accountAddress": "0x5647A091F2a09915c1C0F6ac95630Be87114881F", + "adminAddress": "0x900FDC4d45297A743e4508986d4C1aa1BAf89A83", + "ocr1Config": { + "p2pKeyBundle": {}, + "ocrKeyBundle": {} + }, + "ocr2Config": { + "enabled": true, + "p2pKeyBundle": { + "peerID": "p2p_12D3KooWRjg2KoP6jKVWU2BczeduWsdnfN69tHN2YGEAGtETvc9P", + "publicKey": "ec87467a512f8218bb63f7fcf46cf0b8fd8ebb14bd5f3b670908d505a5af801a" + }, + "ocrKeyBundle": { + "bundleID": "20626049a1e24912a14d186645ba70fea4860efcc987b3ec7c9ddc881b5057db", + "configPublicKey": "d84d4653db0caca062d4058e9937ae618a53bbd1b41a673c5f13bebc24e7aa3a", + "offchainPublicKey": "156c8ab52099386377fe27bbd50dafa368ff2790245f1407579f590b0bae7a1e", + "onchainSigningAddress": "4f4b7bff5d32d62326b575d8c951d34e54888e31" + }, + "plugins": { + "mercury": true + } + } + } + ], + "connected": true, + "supportedProducts": [ + "DATA_STREAMS_V03" + ], + "categories": [ + { + "id": "11", + "name": "Keystone" + } + ] + } + ], + "createdAt": "2024-09-18T19:23:19.587619Z" + }, + { + "id": "95", + "keys": [ + "cl-df-asset-don-testnet-14" + ], + "name": "Chainlink Keystone Asset DON Node Operator 14", + "metadata": { + "nodeCount": 1, + "jobCount": 9 + }, + "nodes": [ + { + "id": "846", + "name": "Chainlink Sepolia Prod Keystone Asset Node 14", + "publicKey": "12681ec137cd2d25e7c71638f564404dd764061921c870bbcddf683d048eed21", + "chainConfigs": [ + { + "network": { + "id": "129", + "chainID": "11155111", + "chainType": "EVM", + "name": "Ethereum Testnet (Sepolia)" + }, + "accountAddress": "0x0419E70d32c3972930c99aaaDF20dCB473c56d22", + "adminAddress": "0x900FDC4d45297A743e4508986d4C1aa1BAf89A83", + "ocr1Config": { + "p2pKeyBundle": {}, + "ocrKeyBundle": {} + }, + "ocr2Config": { + "enabled": true, + "p2pKeyBundle": { + "peerID": "p2p_12D3KooWCdEG68z5kwYuD1xp1aJsFBtpw2HYh1K3ffVM6keVrJnT", + "publicKey": "29b8bafebdef5e11ec3556fbcacdfb626d2f80cf178406e38664775e8b1ace78" + }, + "ocrKeyBundle": { + "bundleID": "80b1304898d5cea3c684790a0f01158468c7fa7770675edef33e4b137232ddc9", + "configPublicKey": "15552ecb6ff10103a534f02594a7b7cbab686d76d5e7b32a9c67059e8c856861", + "offchainPublicKey": "b561b7df3bdfe70f1af9395dbc00ef796774aa352c9a30d9c7e2f7e74d438073", + "onchainSigningAddress": "fb1ca65bf473b4443d7359becc0de67a2d96228d" + }, + "plugins": { + "mercury": true + } + } + } + ], + "connected": true, + "supportedProducts": [ + "DATA_STREAMS_V03" + ], + "categories": [ + { + "id": "11", + "name": "Keystone" + } + ] + } + ], + "createdAt": "2024-09-18T19:23:44.73219Z" + }, + { + "id": "96", + "keys": [ + "cl-df-asset-don-testnet-15" + ], + "name": "Chainlink Keystone Asset DON Node Operator 15", + "metadata": { + "nodeCount": 1, + "jobCount": 9 + }, + "nodes": [ + { + "id": "847", + "name": "Chainlink Sepolia Prod Keystone Asset Node 15", + "publicKey": "a9a5d084f9cbbbd291eb43c33dd137cd6140e33c53cebb260463bf52795ec579", + "chainConfigs": [ + { + "network": { + "id": "129", + "chainID": "11155111", + "chainType": "EVM", + "name": "Ethereum Testnet (Sepolia)" + }, + "accountAddress": "0x931900764a585D7a01e500976B630B4747216c8c", + "adminAddress": "0x900FDC4d45297A743e4508986d4C1aa1BAf89A83", + "ocr1Config": { + "p2pKeyBundle": {}, + "ocrKeyBundle": {} + }, + "ocr2Config": { + "enabled": true, + "p2pKeyBundle": { + "peerID": "p2p_12D3KooWQyZ9A9ScBpcoRww1gJVBNB2brNkjJhaqze6ehuv6bmfQ", + "publicKey": "e139f020ae4bc9efaa77da9cfd54339d36176479028f849b9e64ad2cf29acba3" + }, + "ocrKeyBundle": { + "bundleID": "5c1c69eb1d6619b2c9b93bdfdd9c1b87c28101d6fc88bf7979ad52ceda459908", + "configPublicKey": "33f2107ab22b3dd5c19d5de0c5b1e6e038f2275ba455eed7997485caec421925", + "offchainPublicKey": "bb91b077c135cbdd1f4422c6021cf56d78326710c8bb8c4a87b3e7415e48915f", + "onchainSigningAddress": "b94e3de607033d03e3f0cc3ef1f09edd2592b440" + }, + "plugins": { + "mercury": true + } + } + } + ], + "connected": true, + "supportedProducts": [ + "DATA_STREAMS_V03" + ], + "categories": [ + { + "id": "11", + "name": "Keystone" + } + ] + } + ], + "createdAt": "2024-09-18T19:24:01.875231Z" + } +] \ No newline at end of file diff --git a/deployment/environment/clo/utils.go b/deployment/environment/clo/utils.go new file mode 100644 index 00000000000..67be141a6db --- /dev/null +++ b/deployment/environment/clo/utils.go @@ -0,0 +1,101 @@ +package clo + +import ( + "fmt" + + jd "github.com/smartcontractkit/chainlink-protos/job-distributor/v1/node" + "github.com/smartcontractkit/chainlink/deployment/environment/clo/models" +) + +// NewChainConfig creates a new JobDistributor ChainConfig from a clo model NodeChainConfig +func NewChainConfig(chain *models.NodeChainConfig) *jd.ChainConfig { + return &jd.ChainConfig{ + Chain: &jd.Chain{ + Id: chain.Network.ChainID, + Type: jd.ChainType_CHAIN_TYPE_EVM, // TODO: support other chain types + }, + + AccountAddress: chain.AccountAddress, + AdminAddress: chain.AdminAddress, + Ocr2Config: &jd.OCR2Config{ + Enabled: chain.Ocr2Config.Enabled, + P2PKeyBundle: &jd.OCR2Config_P2PKeyBundle{ + PeerId: chain.Ocr2Config.P2pKeyBundle.PeerID, + PublicKey: chain.Ocr2Config.P2pKeyBundle.PublicKey, + }, + OcrKeyBundle: &jd.OCR2Config_OCRKeyBundle{ + BundleId: chain.Ocr2Config.OcrKeyBundle.BundleID, + OnchainSigningAddress: chain.Ocr2Config.OcrKeyBundle.OnchainSigningAddress, + OffchainPublicKey: chain.Ocr2Config.OcrKeyBundle.OffchainPublicKey, + ConfigPublicKey: chain.Ocr2Config.OcrKeyBundle.ConfigPublicKey, + }, + }, + } +} + +func NodeP2PId(n *models.Node) (string, error) { + p2pIds := make(map[string]struct{}) + for _, cc := range n.ChainConfigs { + if cc.Ocr2Config != nil && cc.Ocr2Config.P2pKeyBundle != nil { + p2pIds[cc.Ocr2Config.P2pKeyBundle.PeerID] = struct{}{} + } + } + if len(p2pIds) == 0 { + return "", fmt.Errorf("no p2p id found for node %s", n.ID) + } + if len(p2pIds) > 1 { + return "", fmt.Errorf("multiple p2p ids found for node %s", n.ID) + } + var p2pId string + for k := range p2pIds { + p2pId = k + break + } + return p2pId, nil +} + +func NodesToPeerIDs(nodes []*models.Node) ([]string, error) { + var p2pIds []string + for _, node := range nodes { + p2pId, err := NodeP2PId(node) + if err != nil { + return nil, err + } + p2pIds = append(p2pIds, p2pId) + } + return p2pIds, nil +} + +func NopsToNodes(nops []*models.NodeOperator) []*models.Node { + var nodes []*models.Node + for _, nop := range nops { + nodes = append(nodes, nop.Nodes...) + } + return nodes +} + +func NopsToPeerIds(nops []*models.NodeOperator) ([]string, error) { + return NodesToPeerIDs(NopsToNodes(nops)) +} + +func SetIdToPeerId(n *models.Node) error { + p2pId, err := NodeP2PId(n) + if err != nil { + return err + } + n.ID = p2pId + return nil +} + +// SetNodeIdsToPeerIds sets the ID of each node in the NOPs to the P2P ID of the node +// It mutates the input NOPs +func SetNodeIdsToPeerIds(nops []*models.NodeOperator) error { + for _, nop := range nops { + for _, n := range nop.Nodes { + if err := SetIdToPeerId(n); err != nil { + return err + } + } + } + return nil +} diff --git a/deployment/environment/clo/utils_test.go b/deployment/environment/clo/utils_test.go new file mode 100644 index 00000000000..e2202d4e14f --- /dev/null +++ b/deployment/environment/clo/utils_test.go @@ -0,0 +1,168 @@ +package clo + +import ( + "testing" + + "github.com/smartcontractkit/chainlink/deployment/environment/clo/models" + "github.com/stretchr/testify/assert" +) + +func TestSetNodeIdsToPeerIds(t *testing.T) { + type args struct { + nops []*models.NodeOperator + } + tests := []struct { + name string + args args + want []*models.NodeOperator + wantErr bool + }{ + { + name: "no nodes", + args: args{ + nops: []*models.NodeOperator{ + { + ID: "nop1", + }, + }, + }, + want: []*models.NodeOperator{ + { + ID: "nop1", + }, + }, + }, + { + name: "error no p2p key bundle", + args: args{ + nops: []*models.NodeOperator{ + { + ID: "nop1", + Nodes: []*models.Node{ + { + ID: "node1", + ChainConfigs: []*models.NodeChainConfig{ + { + Ocr2Config: &models.NodeOCR2Config{}, + }, + }, + }, + }, + }, + }, + }, + wantErr: true, + }, + { + name: "error multiple p2p key bundle", + args: args{ + nops: []*models.NodeOperator{ + { + ID: "nop1", + Nodes: []*models.Node{ + { + ID: "node1", + ChainConfigs: []*models.NodeChainConfig{ + { + Ocr2Config: &models.NodeOCR2Config{ + P2pKeyBundle: &models.NodeOCR2ConfigP2PKeyBundle{ + PeerID: "peer1", + }, + }, + }, + { + Ocr2Config: &models.NodeOCR2Config{ + P2pKeyBundle: &models.NodeOCR2ConfigP2PKeyBundle{ + PeerID: "peer2", + }, + }, + }, + }, + }, + }, + }, + }, + }, + wantErr: true, + }, + { + name: "multiple nodes", + args: args{ + nops: []*models.NodeOperator{ + { + ID: "nop1", + Nodes: []*models.Node{ + { + ID: "node1", + ChainConfigs: []*models.NodeChainConfig{ + { + Ocr2Config: &models.NodeOCR2Config{ + P2pKeyBundle: &models.NodeOCR2ConfigP2PKeyBundle{ + PeerID: "peer1", + }, + }, + }, + }, + }, + { + ID: "node2", + ChainConfigs: []*models.NodeChainConfig{ + { + Ocr2Config: &models.NodeOCR2Config{ + P2pKeyBundle: &models.NodeOCR2ConfigP2PKeyBundle{ + PeerID: "another peer id", + }, + }, + }, + }, + }, + }, + }, + }, + }, + want: []*models.NodeOperator{ + { + ID: "nop1", + Nodes: []*models.Node{ + { + ID: "peer1", + ChainConfigs: []*models.NodeChainConfig{ + { + Ocr2Config: &models.NodeOCR2Config{ + P2pKeyBundle: &models.NodeOCR2ConfigP2PKeyBundle{ + PeerID: "peer1", + }, + }, + }, + }, + }, + { + ID: "another peer id", + ChainConfigs: []*models.NodeChainConfig{ + { + Ocr2Config: &models.NodeOCR2Config{ + P2pKeyBundle: &models.NodeOCR2ConfigP2PKeyBundle{ + PeerID: "another peer id", + }, + }, + }, + }, + }, + }, + }, + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + err := SetNodeIdsToPeerIds(tt.args.nops) + if (err != nil) != tt.wantErr { + t.Errorf("SetNodeIdsToPeerIds() error = %v, wantErr %v", err, tt.wantErr) + } + if err != nil { + return + } + assert.EqualValues(t, tt.args.nops, tt.want) + }) + } +} diff --git a/deployment/environment/crib/ccip_deployer.go b/deployment/environment/crib/ccip_deployer.go deleted file mode 100644 index bb3acec8aa4..00000000000 --- a/deployment/environment/crib/ccip_deployer.go +++ /dev/null @@ -1,225 +0,0 @@ -package crib - -import ( - "context" - "errors" - "fmt" - "math/big" - - "github.com/ethereum/go-ethereum/common" - "github.com/smartcontractkit/ccip-owner-contracts/pkg/config" - - commonchangeset "github.com/smartcontractkit/chainlink/deployment/common/changeset" - commontypes "github.com/smartcontractkit/chainlink/deployment/common/types" - "github.com/smartcontractkit/chainlink/deployment/environment/devenv" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/fee_quoter" - "github.com/smartcontractkit/chainlink/v2/core/services/relay" - - "github.com/smartcontractkit/chainlink/deployment" - "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" - "github.com/smartcontractkit/chainlink/v2/core/logger" -) - -// DeployHomeChainContracts deploys the home chain contracts so that the chainlink nodes can be started with the CR address in Capabilities.ExternalRegistry -// DeployHomeChainContracts is to 1. Set up crib with chains and chainlink nodes ( cap reg is not known yet so not setting the config with capreg address) -// Call DeployHomeChain changeset with nodeinfo ( the peer id and all) -func DeployHomeChainContracts(ctx context.Context, lggr logger.Logger, envConfig devenv.EnvironmentConfig, homeChainSel uint64, feedChainSel uint64) (deployment.CapabilityRegistryConfig, deployment.AddressBook, error) { - e, _, err := devenv.NewEnvironment(func() context.Context { return ctx }, lggr, envConfig) - if err != nil { - return deployment.CapabilityRegistryConfig{}, nil, err - } - if e == nil { - return deployment.CapabilityRegistryConfig{}, nil, errors.New("environment is nil") - } - - nodes, err := deployment.NodeInfo(e.NodeIDs, e.Offchain) - if err != nil { - return deployment.CapabilityRegistryConfig{}, e.ExistingAddresses, fmt.Errorf("failed to get node info from env: %w", err) - } - p2pIds := nodes.NonBootstraps().PeerIDs() - *e, err = commonchangeset.ApplyChangesets(nil, *e, nil, []commonchangeset.ChangesetApplication{ - { - Changeset: commonchangeset.WrapChangeSet(changeset.DeployHomeChain), - Config: changeset.DeployHomeChainConfig{ - HomeChainSel: homeChainSel, - RMNStaticConfig: changeset.NewTestRMNStaticConfig(), - RMNDynamicConfig: changeset.NewTestRMNDynamicConfig(), - NodeOperators: changeset.NewTestNodeOperator(e.Chains[homeChainSel].DeployerKey.From), - NodeP2PIDsPerNodeOpAdmin: map[string][][32]byte{ - "NodeOperator": p2pIds, - }, - }, - }, - }) - - state, err := changeset.LoadOnchainState(*e) - if err != nil { - return deployment.CapabilityRegistryConfig{}, e.ExistingAddresses, fmt.Errorf("failed to load on chain state: %w", err) - } - capRegAddr := state.Chains[homeChainSel].CapabilityRegistry.Address() - if capRegAddr == common.HexToAddress("0x") { - return deployment.CapabilityRegistryConfig{}, e.ExistingAddresses, fmt.Errorf("cap Reg address not found: %w", err) - } - capRegConfig := deployment.CapabilityRegistryConfig{ - EVMChainID: homeChainSel, - Contract: state.Chains[homeChainSel].CapabilityRegistry.Address(), - NetworkType: relay.NetworkEVM, - } - return capRegConfig, e.ExistingAddresses, nil -} - -func DeployCCIPAndAddLanes(ctx context.Context, lggr logger.Logger, envConfig devenv.EnvironmentConfig, homeChainSel, feedChainSel uint64, ab deployment.AddressBook) (DeployCCIPOutput, error) { - e, _, err := devenv.NewEnvironment(func() context.Context { return ctx }, lggr, envConfig) - if err != nil { - return DeployCCIPOutput{}, fmt.Errorf("failed to initiate new environment: %w", err) - } - e.ExistingAddresses = ab - chainSelectors := e.AllChainSelectors() - cfg := make(map[uint64]commontypes.MCMSWithTimelockConfig) - var prereqCfgs []changeset.DeployPrerequisiteConfigPerChain - for _, chain := range e.AllChainSelectors() { - mcmsConfig, err := config.NewConfig(1, []common.Address{e.Chains[chain].DeployerKey.From}, []config.Config{}) - if err != nil { - return DeployCCIPOutput{}, fmt.Errorf("failed to create mcms config: %w", err) - } - cfg[chain] = commontypes.MCMSWithTimelockConfig{ - Canceller: *mcmsConfig, - Bypasser: *mcmsConfig, - Proposer: *mcmsConfig, - TimelockMinDelay: big.NewInt(0), - } - prereqCfgs = append(prereqCfgs, changeset.DeployPrerequisiteConfigPerChain{ - ChainSelector: chain, - }) - } - - // This will not apply any proposals because we pass nil to testing. - // However, setup is ok because we only need to deploy the contracts and distribute job specs - *e, err = commonchangeset.ApplyChangesets(nil, *e, nil, []commonchangeset.ChangesetApplication{ - { - Changeset: commonchangeset.WrapChangeSet(commonchangeset.DeployLinkToken), - Config: chainSelectors, - }, - { - Changeset: commonchangeset.WrapChangeSet(changeset.DeployPrerequisites), - Config: changeset.DeployPrerequisiteConfig{ - Configs: prereqCfgs, - }, - }, - { - Changeset: commonchangeset.WrapChangeSet(commonchangeset.DeployMCMSWithTimelock), - Config: cfg, - }, - { - Changeset: commonchangeset.WrapChangeSet(changeset.DeployChainContracts), - Config: changeset.DeployChainContractsConfig{ - ChainSelectors: chainSelectors, - HomeChainSelector: homeChainSel, - }, - }, - { - Changeset: commonchangeset.WrapChangeSet(changeset.CCIPCapabilityJobspec), - Config: struct{}{}, - }, - }) - state, err := changeset.LoadOnchainState(*e) - if err != nil { - return DeployCCIPOutput{}, fmt.Errorf("failed to load onchain state: %w", err) - } - // Add all lanes - for from := range e.Chains { - for to := range e.Chains { - if from != to { - stateChain1 := state.Chains[from] - newEnv, err := commonchangeset.ApplyChangesets(nil, *e, nil, []commonchangeset.ChangesetApplication{ - { - Changeset: commonchangeset.WrapChangeSet(changeset.UpdateOnRampsDests), - Config: changeset.UpdateOnRampDestsConfig{ - UpdatesByChain: map[uint64]map[uint64]changeset.OnRampDestinationUpdate{ - from: { - to: { - IsEnabled: true, - TestRouter: false, - AllowListEnabled: false, - }, - }, - }, - }, - }, - { - Changeset: commonchangeset.WrapChangeSet(changeset.UpdateFeeQuoterPricesCS), - Config: changeset.UpdateFeeQuoterPricesConfig{ - PricesByChain: map[uint64]changeset.FeeQuoterPriceUpdatePerSource{ - from: { - TokenPrices: map[common.Address]*big.Int{ - stateChain1.LinkToken.Address(): changeset.DefaultLinkPrice, - stateChain1.Weth9.Address(): changeset.DefaultWethPrice, - }, - GasPrices: map[uint64]*big.Int{ - to: changeset.DefaultGasPrice, - }, - }, - }, - }, - }, - { - Changeset: commonchangeset.WrapChangeSet(changeset.UpdateFeeQuoterDests), - Config: changeset.UpdateFeeQuoterDestsConfig{ - UpdatesByChain: map[uint64]map[uint64]fee_quoter.FeeQuoterDestChainConfig{ - from: { - to: changeset.DefaultFeeQuoterDestChainConfig(), - }, - }, - }, - }, - { - Changeset: commonchangeset.WrapChangeSet(changeset.UpdateOffRampSources), - Config: changeset.UpdateOffRampSourcesConfig{ - UpdatesByChain: map[uint64]map[uint64]changeset.OffRampSourceUpdate{ - to: { - from: { - IsEnabled: true, - TestRouter: true, - }, - }, - }, - }, - }, - { - Changeset: commonchangeset.WrapChangeSet(changeset.UpdateRouterRamps), - Config: changeset.UpdateRouterRampsConfig{ - TestRouter: true, - UpdatesByChain: map[uint64]changeset.RouterUpdates{ - // onRamp update on source chain - from: { - OnRampUpdates: map[uint64]bool{ - to: true, - }, - }, - // off - from: { - OffRampUpdates: map[uint64]bool{ - to: true, - }, - }, - }, - }, - }, - }) - if err != nil { - return DeployCCIPOutput{}, fmt.Errorf("failed to apply changesets: %w", err) - } - e = &newEnv - } - } - } - - addresses, err := e.ExistingAddresses.Addresses() - if err != nil { - return DeployCCIPOutput{}, fmt.Errorf("failed to get convert address book to address book map: %w", err) - } - return DeployCCIPOutput{ - AddressBook: *deployment.NewMemoryAddressBookFromMap(addresses), - NodeIDs: e.NodeIDs, - }, err -} diff --git a/deployment/environment/crib/data.go b/deployment/environment/crib/data.go deleted file mode 100644 index b9197691613..00000000000 --- a/deployment/environment/crib/data.go +++ /dev/null @@ -1,81 +0,0 @@ -package crib - -import ( - "encoding/json" - "fmt" - "io" - "os" - - "github.com/smartcontractkit/chainlink/deployment" - "github.com/smartcontractkit/chainlink/deployment/environment/devenv" -) - -type OutputReader struct { - outputDir string -} - -func NewOutputReader(outputDir string) *OutputReader { - return &OutputReader{outputDir: outputDir} -} - -func (r *OutputReader) ReadNodesDetails() NodesDetails { - byteValue := r.readFile(NodesDetailsFileName) - - var result NodesDetails - - // Unmarshal the JSON into the map - err := json.Unmarshal(byteValue, &result) - if err != nil { - fmt.Println("Error unmarshalling JSON:", err) - panic(err) - } - - return result -} - -func (r *OutputReader) ReadChainConfigs() []devenv.ChainConfig { - byteValue := r.readFile(ChainsConfigsFileName) - - var result []devenv.ChainConfig - - // Unmarshal the JSON into the map - err := json.Unmarshal(byteValue, &result) - if err != nil { - fmt.Println("Error unmarshalling JSON:", err) - panic(err) - } - - return result -} - -func (r *OutputReader) ReadAddressBook() *deployment.AddressBookMap { - byteValue := r.readFile(AddressBookFileName) - - var result map[uint64]map[string]deployment.TypeAndVersion - - // Unmarshal the JSON into the map - err := json.Unmarshal(byteValue, &result) - if err != nil { - fmt.Println("Error unmarshalling JSON:", err) - panic(err) - } - - return deployment.NewMemoryAddressBookFromMap(result) -} - -func (r *OutputReader) readFile(fileName string) []byte { - file, err := os.Open(fmt.Sprintf("%s/%s", r.outputDir, fileName)) - if err != nil { - fmt.Println("Error opening file:", err) - panic(err) - } - defer file.Close() - - // Read the file's content into a byte slice - byteValue, err := io.ReadAll(file) - if err != nil { - fmt.Println("Error reading file:", err) - panic(err) - } - return byteValue -} diff --git a/deployment/environment/crib/env.go b/deployment/environment/crib/env.go deleted file mode 100644 index 3af1acaf754..00000000000 --- a/deployment/environment/crib/env.go +++ /dev/null @@ -1,45 +0,0 @@ -package crib - -const ( - AddressBookFileName = "ccip-v2-scripts-address-book.json" - NodesDetailsFileName = "ccip-v2-scripts-nodes-details.json" - ChainsConfigsFileName = "ccip-v2-scripts-chains-details.json" -) - -type CRIBEnv struct { - envStateDir string -} - -func NewDevspaceEnvFromStateDir(envStateDir string) CRIBEnv { - return CRIBEnv{ - envStateDir: envStateDir, - } -} - -func (c CRIBEnv) GetConfig() DeployOutput { - reader := NewOutputReader(c.envStateDir) - nodesDetails := reader.ReadNodesDetails() - chainConfigs := reader.ReadChainConfigs() - return DeployOutput{ - AddressBook: reader.ReadAddressBook(), - NodeIDs: nodesDetails.NodeIDs, - Chains: chainConfigs, - } -} - -type RPC struct { - External *string - Internal *string -} - -type ChainConfig struct { - ChainID uint64 // chain id as per EIP-155, mainly applicable for EVM chains - ChainName string // name of the chain populated from chainselector repo - ChainType string // should denote the chain family. Acceptable values are EVM, COSMOS, SOLANA, STARKNET, APTOS etc - WSRPCs []RPC // websocket rpcs to connect to the chain - HTTPRPCs []RPC // http rpcs to connect to the chain -} - -type NodesDetails struct { - NodeIDs []string -} diff --git a/deployment/environment/crib/env_test.go b/deployment/environment/crib/env_test.go deleted file mode 100644 index 262a2540923..00000000000 --- a/deployment/environment/crib/env_test.go +++ /dev/null @@ -1,18 +0,0 @@ -package crib - -import ( - "testing" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" -) - -func TestShouldProvideEnvironmentConfig(t *testing.T) { - t.Parallel() - env := NewDevspaceEnvFromStateDir("testdata/lanes-deployed-state") - config := env.GetConfig() - require.NotNil(t, config) - assert.NotEmpty(t, config.NodeIDs) - assert.NotNil(t, config.AddressBook) - assert.NotEmpty(t, config.Chains) -} diff --git a/deployment/environment/crib/testdata/lanes-deployed-state/ccip-v2-scripts-address-book.json b/deployment/environment/crib/testdata/lanes-deployed-state/ccip-v2-scripts-address-book.json deleted file mode 100644 index e4b2672cb5f..00000000000 --- a/deployment/environment/crib/testdata/lanes-deployed-state/ccip-v2-scripts-address-book.json +++ /dev/null @@ -1 +0,0 @@ -{"12922642891491394802":{"0x05Aa229Aec102f78CE0E852A812a388F076Aa555":{"Type":"CancellerManyChainMultiSig","Version":"1.0.0"},"0x0D4ff719551E23185Aeb16FFbF2ABEbB90635942":{"Type":"TestRouter","Version":"1.2.0"},"0x0f5D1ef48f12b6f691401bfe88c2037c690a6afe":{"Type":"ProposerManyChainMultiSig","Version":"1.0.0"},"0x2dE080e97B0caE9825375D31f5D0eD5751fDf16D":{"Type":"CCIPReceiver","Version":"1.0.0"},"0x2fc631e4B3018258759C52AF169200213e84ABab":{"Type":"OnRamp","Version":"1.6.0-dev"},"0x5C7c905B505f0Cf40Ab6600d05e677F717916F6B":{"Type":"Router","Version":"1.2.0"},"0x63cf2Cd54fE91e3545D1379abf5bfd194545259d":{"Type":"OffRamp","Version":"1.6.0-dev"},"0x712516e61C8B383dF4A63CFe83d7701Bce54B03e":{"Type":"LinkToken","Version":"1.0.0"},"0x71C95911E9a5D330f4D621842EC243EE1343292e":{"Type":"PriceFeed","Version":"1.0.0"},"0x73eccD6288e117cAcA738BDAD4FEC51312166C1A":{"Type":"RMNRemote","Version":"1.6.0-dev"},"0x8464135c8F25Da09e49BC8782676a84730C318bC":{"Type":"PriceFeed","Version":"1.0.0"},"0x85C5Dd61585773423e378146D4bEC6f8D149E248":{"Type":"TokenAdminRegistry","Version":"1.5.0"},"0x948B3c65b89DF0B4894ABE91E6D02FE579834F8F":{"Type":"WETH9","Version":"1.0.0"},"0xAfe1b5bdEbD4ae65AF2024738bf0735fbb65d44b":{"Type":"FeeQuoter","Version":"1.6.0-dev"},"0xC6bA8C3233eCF65B761049ef63466945c362EdD2":{"Type":"BypasserManyChainMultiSig","Version":"1.0.0"},"0xbCF26943C0197d2eE0E5D05c716Be60cc2761508":{"Type":"AdminManyChainMultiSig","Version":"1.0.0"},"0xcA03Dc4665A8C3603cb4Fd5Ce71Af9649dC00d44":{"Type":"RBACTimelock","Version":"1.0.0"},"0xe6b98F104c1BEf218F3893ADab4160Dc73Eb8367":{"Type":"ARMProxy","Version":"1.0.0"},"0xfbAb4aa40C202E4e80390171E82379824f7372dd":{"Type":"NonceManager","Version":"1.6.0-dev"}},"3379446385462418246":{"0x09635F643e140090A9A8Dcd712eD6285858ceBef":{"Type":"RMNRemote","Version":"1.6.0-dev"},"0x0B306BF915C4d645ff596e518fAf3F9669b97016":{"Type":"LinkToken","Version":"1.0.0"},"0x1613beB3B2C4f22Ee086B2b38C1476A3cE7f78E8":{"Type":"OnRamp","Version":"1.6.0-dev"},"0x2279B7A0a67DB372996a5FaB50D91eAA73d2eBe6":{"Type":"CCIPHome","Version":"1.6.0-dev"},"0x322813Fd9A801c5507c9de605d63CEA4f2CE6c44":{"Type":"ProposerManyChainMultiSig","Version":"1.0.0"},"0x3Aa5ebB10DC797CAC828524e59A333d0A371443c":{"Type":"BypasserManyChainMultiSig","Version":"1.0.0"},"0x4A679253410272dd5232B3Ff7cF5dbB88f295319":{"Type":"RBACTimelock","Version":"1.0.0"},"0x59b670e9fA9D0A427751Af201D676719a970857b":{"Type":"CancellerManyChainMultiSig","Version":"1.0.0"},"0x67d269191c92Caf3cD7723F116c85e6E9bf55933":{"Type":"ARMProxy","Version":"1.0.0"},"0x7a2088a1bFc9d81c55368AE168C2C02570cB814F":{"Type":"CCIPReceiver","Version":"1.0.0"},"0x84eA74d481Ee0A5332c457a4d796187F6Ba67fEB":{"Type":"TokenAdminRegistry","Version":"1.5.0"},"0x851356ae760d987E095750cCeb3bC6014560891C":{"Type":"OffRamp","Version":"1.6.0-dev"},"0x8A791620dd6260079BF849Dc5567aDC3F2FdC318":{"Type":"RMNHome","Version":"1.6.0-dev"},"0x9A676e781A523b5d0C0e43731313A708CB607508":{"Type":"WETH9","Version":"1.0.0"},"0x9A9f2CCfdE556A7E9Ff0848998Aa4a0CFD8863AE":{"Type":"AdminManyChainMultiSig","Version":"1.0.0"},"0x9E545E3C0baAB3E08CdfD552C960A1050f373042":{"Type":"NonceManager","Version":"1.6.0-dev"},"0xE6E340D132b5f46d1e472DebcD681B2aBc16e57E":{"Type":"Router","Version":"1.2.0"},"0xa513E6E4b8f2a923D98304ec87F64353C4D5C853":{"Type":"CapabilitiesRegistry","Version":"1.0.0"},"0xa82fF9aFd8f496c3d6ac40E2a0F282E47488CFc9":{"Type":"FeeQuoter","Version":"1.6.0-dev"},"0xc3e53F4d16Ae77Db1c982e75a937B9f60FE63690":{"Type":"TestRouter","Version":"1.2.0"}}} diff --git a/deployment/environment/crib/testdata/lanes-deployed-state/ccip-v2-scripts-chains-details.json b/deployment/environment/crib/testdata/lanes-deployed-state/ccip-v2-scripts-chains-details.json deleted file mode 100644 index f93ea4ce231..00000000000 --- a/deployment/environment/crib/testdata/lanes-deployed-state/ccip-v2-scripts-chains-details.json +++ /dev/null @@ -1,24 +0,0 @@ -[ - { - "ChainID": 1337, - "ChainName": "alpha", - "ChainType": "EVM", - "WSRPCs": [ - "wss://crib-local-geth-1337-ws.local:443" - ], - "HTTPRPCs": [ - "https://crib-local-geth-1337-ws.local:443" - ] - }, - { - "ChainID": 2337, - "ChainName": "alpha", - "ChainType": "EVM", - "WSRPCs": [ - "wss://crib-local-geth-2337-ws.local:443" - ], - "HTTPRPCs": [ - "https://crib-local-geth-2337-ws.local:443" - ] - } -] diff --git a/deployment/environment/crib/testdata/lanes-deployed-state/ccip-v2-scripts-nodes-details.json b/deployment/environment/crib/testdata/lanes-deployed-state/ccip-v2-scripts-nodes-details.json deleted file mode 100644 index 477ae0527b1..00000000000 --- a/deployment/environment/crib/testdata/lanes-deployed-state/ccip-v2-scripts-nodes-details.json +++ /dev/null @@ -1 +0,0 @@ -{"NodeIDs":["node_2URuou3RXmtZu5gLQX8qd","node_m9TTQbUxBx3WjDEjmpVDL","node_4FiKVPtuQjCTvHnS7QpES","node_A4VTgecDwMoG2YYicyjuG","node_jQFpzXDadzaADq147nThS"]} diff --git a/deployment/environment/crib/types.go b/deployment/environment/crib/types.go deleted file mode 100644 index d19c8424443..00000000000 --- a/deployment/environment/crib/types.go +++ /dev/null @@ -1,39 +0,0 @@ -package crib - -import ( - "context" - "github.com/smartcontractkit/chainlink-common/pkg/logger" - "github.com/smartcontractkit/chainlink/deployment" - "github.com/smartcontractkit/chainlink/deployment/environment/devenv" -) - -const ( - CRIB_ENV_NAME = "Crib Environment" -) - -type DeployOutput struct { - NodeIDs []string - Chains []devenv.ChainConfig // chain selector -> Chain Config - AddressBook deployment.AddressBook // Addresses of all contracts -} - -type DeployCCIPOutput struct { - AddressBook deployment.AddressBookMap - NodeIDs []string -} - -func NewDeployEnvironmentFromCribOutput(lggr logger.Logger, output DeployOutput) (*deployment.Environment, error) { - chains, err := devenv.NewChains(lggr, output.Chains) - if err != nil { - return nil, err - } - return deployment.NewEnvironment( - CRIB_ENV_NAME, - lggr, - output.AddressBook, - chains, - output.NodeIDs, - nil, // todo: populate the offchain client using output.DON - func() context.Context { return context.Background() }, deployment.XXXGenerateTestOCRSecrets(), - ), nil -} diff --git a/deployment/environment/devenv/.sample.env b/deployment/environment/devenv/.sample.env index 8ab186e3044..ddf0b97e9a9 100644 --- a/deployment/environment/devenv/.sample.env +++ b/deployment/environment/devenv/.sample.env @@ -7,12 +7,6 @@ E2E_JD_VERSION= E2E_TEST_CHAINLINK_IMAGE=public.ecr.aws/w0i8p0z9/chainlink-ccip E2E_TEST_CHAINLINK_VERSION=2.14.0-ccip1.5.0 -E2E_RMN_RAGEPROXY_IMAGE= -E2E_RMN_RAGEPROXY_VERSION=master-5208d09 -E2E_RMN_AFN2PROXY_IMAGE= -E2E_RMN_AFN2PROXY_VERSION=master-5208d09 - - # RPC Configuration E2E_TEST_SEPOLIA_WALLET_KEY= E2E_TEST_SEPOLIA_RPC_HTTP_URL_1= diff --git a/deployment/environment/devenv/README.md b/deployment/environment/devenv/README.md index e6f5bc1b5ac..f5e11f0475e 100644 --- a/deployment/environment/devenv/README.md +++ b/deployment/environment/devenv/README.md @@ -14,11 +14,11 @@ Pre-requisites: #### Setting Up Testconfig with Simulated Private Ethereum Network -To run tests (e.g., [ccip-test](../../../integration-tests/ccip-tests/smoke/ccip_test.go)), -you need to set up the testconfig following the [testconfig setup instructions](../../../integration-tests/testconfig/README.md). +To run tests (e.g., [ccip-test](../../integration-tests/smoke/ccip_test.go)), +you need to set up the testconfig following the [testconfig setup instructions](../../integration-tests/testconfig/README.md). The testconfig specifies the details of the different configurations to set up the environment and run the tests. -Generally, tests are run with the [default](../../../integration-tests/testconfig/default.toml) config unless overridden by product-specific config. -For example, the [ccip-test](../../../integration-tests/ccip-tests/smoke/ccip_test.go) uses [ccip.toml](../../../integration-tests/testconfig/ccip/ccip.toml) to specify +Generally, tests are run with the [default](../../integration-tests/testconfig/default.toml) config unless overridden by product-specific config. +For example, the [ccip-test](../../integration-tests/smoke/ccip_test.go) uses [ccip.toml](../../integration-tests/testconfig/ccip/ccip.toml) to specify CCIP-specific test environment details. There are additional secret configuration parameters required by the `devenv` environment that are not stored in the testconfig. @@ -37,7 +37,7 @@ By default, tests are run with private Ethereum network containers set up in the the Chainlink nodes and job distributor. To run tests against existing testnet/mainnet, set the `selected_network` field in the testconfig with the specific network names. -For example, if running [ccip-smoke](../../../integration-tests/ccip-tests/smoke/ccip_test.go) tests with Sepolia, Avax, and Binance testnets, +For example, if running [ccip-smoke](../../integration-tests/smoke/ccip_test.go) tests with Sepolia, Avax, and Binance testnets, copy the contents of [sepolia_avax_binance.toml](../../integration-tests/testconfig/ccip/overrides/sepolia_avax_binance.toml) to the `overrides.toml` file. @@ -48,4 +48,4 @@ provide necessary secrets applicable to the network you are running the tests ag - `E2E_TEST__RPC_HTTP_URL_` - `E2E_TEST__RPC_WS_URL_` -Now you are all set to run the tests with the existing testnet/mainnet. +Now you are all set to run the tests with the existing testnet/mainnet. \ No newline at end of file diff --git a/deployment/environment/devenv/chain.go b/deployment/environment/devenv/chain.go index 5c6c4336ed7..cdbaf35e860 100644 --- a/deployment/environment/devenv/chain.go +++ b/deployment/environment/devenv/chain.go @@ -3,12 +3,10 @@ package devenv import ( "context" "fmt" - "math/big" "time" "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/ethclient" chainselectors "github.com/smartcontractkit/chain-selectors" @@ -23,68 +21,12 @@ const ( // ChainConfig holds the configuration for a with a deployer key which can be used to send transactions to the chain. type ChainConfig struct { - ChainID uint64 // chain id as per EIP-155, mainly applicable for EVM chains - ChainName string // name of the chain populated from chainselector repo - ChainType string // should denote the chain family. Acceptable values are EVM, COSMOS, SOLANA, STARKNET, APTOS etc - WSRPCs []string // websocket rpcs to connect to the chain - HTTPRPCs []string // http rpcs to connect to the chain - DeployerKey *bind.TransactOpts // key to deploy and configure contracts on the chain - Users []*bind.TransactOpts // map of addresses to their transact opts to interact with the chain as users -} - -func (c *ChainConfig) SetUsers(pvtkeys []string) error { - if pvtkeys == nil { - // if no private keys are provided, set deployer key as the user - if c.DeployerKey != nil { - c.Users = []*bind.TransactOpts{c.DeployerKey} - return nil - } else { - return fmt.Errorf("no private keys provided for users, deployer key is also not set") - } - } - for _, pvtKeyStr := range pvtkeys { - pvtKey, err := crypto.HexToECDSA(pvtKeyStr) - if err != nil { - return fmt.Errorf("failed to convert private key to ECDSA: %w", err) - } - user, err := bind.NewKeyedTransactorWithChainID(pvtKey, new(big.Int).SetUint64(c.ChainID)) - if err != nil { - return fmt.Errorf("failed to create transactor: %w", err) - } - c.Users = append(c.Users, user) - } - return nil -} - -// SetDeployerKey sets the deployer key for the chain. If private key is not provided, it fetches the deployer key from KMS. -func (c *ChainConfig) SetDeployerKey(pvtKeyStr *string) error { - if pvtKeyStr != nil && *pvtKeyStr != "" { - pvtKey, err := crypto.HexToECDSA(*pvtKeyStr) - if err != nil { - return fmt.Errorf("failed to convert private key to ECDSA: %w", err) - } - deployer, err := bind.NewKeyedTransactorWithChainID(pvtKey, new(big.Int).SetUint64(c.ChainID)) - if err != nil { - return fmt.Errorf("failed to create transactor: %w", err) - } - fmt.Printf("Deployer Address: %s for chain id %d\n", deployer.From.Hex(), c.ChainID) - c.DeployerKey = deployer - return nil - } - kmsConfig, err := deployment.KMSConfigFromEnvVars() - if err != nil { - return fmt.Errorf("failed to get kms config from env vars: %w", err) - } - kmsClient, err := deployment.NewKMSClient(kmsConfig) - if err != nil { - return fmt.Errorf("failed to create KMS client: %w", err) - } - evmKMSClient := deployment.NewEVMKMSClient(kmsClient, kmsConfig.KmsDeployerKeyId) - c.DeployerKey, err = evmKMSClient.GetKMSTransactOpts(context.Background(), new(big.Int).SetUint64(c.ChainID)) - if err != nil { - return fmt.Errorf("failed to get transactor from KMS client: %w", err) - } - return nil + ChainID uint64 // chain id as per EIP-155, mainly applicable for EVM chains + ChainName string // name of the chain populated from chainselector repo + ChainType string // should denote the chain family. Acceptable values are EVM, COSMOS, SOLANA, STARKNET, APTOS etc + WSRPCs []string // websocket rpcs to connect to the chain + HTTPRPCs []string // http rpcs to connect to the chain + DeployerKey *bind.TransactOpts // key to send transactions to the chain } func NewChains(logger logger.Logger, configs []ChainConfig) (map[uint64]deployment.Chain, error) { @@ -108,10 +50,6 @@ func NewChains(logger logger.Logger, configs []ChainConfig) (map[uint64]deployme if ec == nil { return nil, fmt.Errorf("failed to connect to chain %s", chainCfg.ChainName) } - chainInfo, err := deployment.ChainInfo(selector) - if err != nil { - return nil, fmt.Errorf("failed to get chain info for chain %s: %w", chainCfg.ChainName, err) - } chains[selector] = deployment.Chain{ Selector: selector, Client: ec, @@ -119,24 +57,28 @@ func NewChains(logger logger.Logger, configs []ChainConfig) (map[uint64]deployme Confirm: func(tx *types.Transaction) (uint64, error) { var blockNumber uint64 if tx == nil { - return 0, fmt.Errorf("tx was nil, nothing to confirm chain %s", chainInfo.ChainName) + return 0, fmt.Errorf("tx was nil, nothing to confirm") } ctx, cancel := context.WithTimeout(context.Background(), 3*time.Minute) defer cancel() + chainId, err := ec.ChainID(ctx) + if err != nil { + return blockNumber, fmt.Errorf("failed to get chain id: %w", err) + } receipt, err := bind.WaitMined(ctx, ec, tx) if err != nil { - return blockNumber, fmt.Errorf("failed to get confirmed receipt for chain %s: %w", chainInfo.ChainName, err) + return blockNumber, fmt.Errorf("failed to get confirmed receipt for chain %d: %w", chainId, err) } if receipt == nil { - return blockNumber, fmt.Errorf("receipt was nil for tx %s chain %s", tx.Hash().Hex(), chainInfo.ChainName) + return blockNumber, fmt.Errorf("receipt was nil for tx %s", tx.Hash().Hex()) } blockNumber = receipt.BlockNumber.Uint64() if receipt.Status == 0 { errReason, err := deployment.GetErrorReasonFromTx(ec, chainCfg.DeployerKey.From, tx, receipt) if err == nil && errReason != "" { - return blockNumber, fmt.Errorf("tx %s reverted,error reason: %s chain %s", tx.Hash().Hex(), errReason, chainInfo.ChainName) + return blockNumber, fmt.Errorf("tx %s reverted,error reason: %s", tx.Hash().Hex(), errReason) } - return blockNumber, fmt.Errorf("tx %s reverted, could not decode error reason chain %s", tx.Hash().Hex(), chainInfo.ChainName) + return blockNumber, fmt.Errorf("tx %s reverted, could not decode error reason", tx.Hash().Hex()) } return blockNumber, nil }, diff --git a/deployment/environment/devenv/don.go b/deployment/environment/devenv/don.go index 76f6ee92b68..830f5b921bc 100644 --- a/deployment/environment/devenv/don.go +++ b/deployment/environment/devenv/don.go @@ -2,9 +2,7 @@ package devenv import ( "context" - "errors" "fmt" - chainsel "github.com/smartcontractkit/chain-selectors" "strconv" "strings" "time" @@ -12,6 +10,8 @@ import ( "github.com/hashicorp/go-multierror" "github.com/rs/zerolog" "github.com/sethvargo/go-retry" + chainsel "github.com/smartcontractkit/chain-selectors" + nodev1 "github.com/smartcontractkit/chainlink-protos/job-distributor/v1/node" clclient "github.com/smartcontractkit/chainlink/deployment/environment/nodeclient" "github.com/smartcontractkit/chainlink/deployment/environment/web/sdk/client" @@ -185,7 +185,7 @@ type JDChainConfigInput struct { // It expects bootstrap nodes to have label with key "type" and value as "bootstrap". // It fetches the account address, peer id, and OCR2 key bundle id and creates the JobDistributorChainConfig. func (n *Node) CreateCCIPOCRSupportedChains(ctx context.Context, chains []JDChainConfigInput, jd JobDistributor) error { - for _, chain := range chains { + for i, chain := range chains { chainId := strconv.FormatUint(chain.ChainID, 10) var account string switch chain.ChainType { @@ -239,51 +239,35 @@ func (n *Node) CreateCCIPOCRSupportedChains(ctx context.Context, chains []JDChai break } } - - // retry twice with 5 seconds interval to create JobDistributorChainConfig - err = retry.Do(ctx, retry.WithMaxDuration(10*time.Second, retry.NewConstant(3*time.Second)), func(ctx context.Context) error { - // check the node chain config to see if this chain already exists - nodeChainConfigs, err := jd.ListNodeChainConfigs(context.Background(), &nodev1.ListNodeChainConfigsRequest{ - Filter: &nodev1.ListNodeChainConfigsRequest_Filter{ - NodeIds: []string{n.NodeId}, - }}) - if err != nil { - return retry.RetryableError(fmt.Errorf("failed to list node chain configs for node %s, retrying..: %w", n.Name, err)) - } - if nodeChainConfigs != nil { - for _, chainConfig := range nodeChainConfigs.ChainConfigs { - if chainConfig.Chain.Id == chainId { - return nil - } - } - } - - // JD silently fails to update nodeChainConfig. Therefore, we fetch the node config and - // if it's not updated , throw an error - _, err = n.gqlClient.CreateJobDistributorChainConfig(ctx, client.JobDistributorChainConfigInput{ - JobDistributorID: n.JDId, - ChainID: chainId, - ChainType: chain.ChainType, - AccountAddr: account, - AdminAddr: n.adminAddr, - Ocr2Enabled: true, - Ocr2IsBootstrap: isBootstrap, - Ocr2Multiaddr: n.multiAddr, - Ocr2P2PPeerID: value(peerID), - Ocr2KeyBundleID: ocr2BundleId, - Ocr2Plugins: `{"commit":true,"execute":true,"median":false,"mercury":false}`, - }) - // todo: add a check if the chain config failed because of a duplicate in that case, should we update or return success? - if err != nil { - return fmt.Errorf("failed to create CCIPOCR2SupportedChains for node %s: %w", n.Name, err) - } - - return retry.RetryableError(errors.New("retrying CreateChainConfig in JD")) + // JD silently fails to update nodeChainConfig. Therefore, we fetch the node config and + // if it's not updated , throw an error + _, err = n.gqlClient.CreateJobDistributorChainConfig(ctx, client.JobDistributorChainConfigInput{ + JobDistributorID: n.JDId, + ChainID: chainId, + ChainType: chain.ChainType, + AccountAddr: account, + AdminAddr: n.adminAddr, + Ocr2Enabled: true, + Ocr2IsBootstrap: isBootstrap, + Ocr2Multiaddr: n.multiAddr, + Ocr2P2PPeerID: value(peerID), + Ocr2KeyBundleID: ocr2BundleId, + Ocr2Plugins: `{"commit":true,"execute":true,"median":false,"mercury":false}`, }) - if err != nil { return fmt.Errorf("failed to create CCIPOCR2SupportedChains for node %s: %w", n.Name, err) } + // query the node chain config to check if it's created + nodeChainConfigs, err := jd.ListNodeChainConfigs(context.Background(), &nodev1.ListNodeChainConfigsRequest{ + Filter: &nodev1.ListNodeChainConfigsRequest_Filter{ + NodeIds: []string{n.NodeId}, + }}) + if err != nil { + return fmt.Errorf("failed to list node chain configs for node %s: %w", n.Name, err) + } + if nodeChainConfigs == nil || len(nodeChainConfigs.ChainConfigs) < i+1 { + return fmt.Errorf("failed to create chain config for node %s", n.Name) + } } return nil } @@ -351,30 +335,8 @@ func (n *Node) RegisterNodeToJobDistributor(ctx context.Context, jd JobDistribut Labels: n.labels, Name: n.Name, }) - // node already registered, fetch it's id - // TODO: check for rpc code = "AlreadyExists" instead - if err != nil && strings.Contains(err.Error(), "AlreadyExists") { - nodesResponse, err := jd.ListNodes(ctx, &nodev1.ListNodesRequest{ - Filter: &nodev1.ListNodesRequest_Filter{ - Selectors: []*ptypes.Selector{ - { - Key: "p2p_id", - Op: ptypes.SelectorOp_EQ, - Value: peerID, - }, - }, - }, - }) - if err != nil { - return err - } - nodes := nodesResponse.GetNodes() - if len(nodes) == 0 { - return fmt.Errorf("failed to find node: %v", n.Name) - } - n.NodeId = nodes[0].Id - return nil - } else if err != nil { + + if err != nil { return fmt.Errorf("failed to register node %s: %w", n.Name, err) } if registerResponse.GetNode().GetId() == "" { @@ -393,17 +355,6 @@ func (n *Node) CreateJobDistributor(ctx context.Context, jd JobDistributor) (str return "", err } // create the job distributor in the node with the csa key - resp, err := n.gqlClient.ListJobDistributors(ctx) - if err != nil { - return "", fmt.Errorf("could not list job distrubutors: %w", err) - } - if len(resp.FeedsManagers.Results) > 0 { - for _, fm := range resp.FeedsManagers.Results { - if fm.GetPublicKey() == csaKey { - return fm.GetId(), nil - } - } - } return n.gqlClient.CreateJobDistributor(ctx, client.JobDistributorInput{ Name: "Job Distributor", Uri: jd.WSRPC, @@ -421,9 +372,8 @@ func (n *Node) SetUpAndLinkJobDistributor(ctx context.Context, jd JobDistributor } // now create the job distributor in the node id, err := n.CreateJobDistributor(ctx, jd) - if err != nil && - (!strings.Contains(err.Error(), "only a single feeds manager is supported") || !strings.Contains(err.Error(), "DuplicateFeedsManagerError")) { - return fmt.Errorf("failed to create job distributor in node %s: %w", n.Name, err) + if err != nil { + return err } // wait for the node to connect to the job distributor err = retry.Do(ctx, retry.WithMaxDuration(1*time.Minute, retry.NewFibonacci(1*time.Second)), func(ctx context.Context) error { @@ -431,7 +381,7 @@ func (n *Node) SetUpAndLinkJobDistributor(ctx context.Context, jd JobDistributor Id: n.NodeId, }) if err != nil { - return retry.RetryableError(fmt.Errorf("failed to get node %s: %w", n.Name, err)) + return fmt.Errorf("failed to get node %s: %w", n.Name, err) } if getRes.GetNode() == nil { return fmt.Errorf("no node found for node id %s", n.NodeId) diff --git a/deployment/environment/devenv/environment.go b/deployment/environment/devenv/environment.go index 121caea43bb..af39e59e3bf 100644 --- a/deployment/environment/devenv/environment.go +++ b/deployment/environment/devenv/environment.go @@ -14,16 +14,18 @@ const ( ) type EnvironmentConfig struct { - Chains []ChainConfig - JDConfig JDConfig + Chains []ChainConfig + HomeChainSelector uint64 + FeedChainSelector uint64 + JDConfig JDConfig } -func NewEnvironment(ctx func() context.Context, lggr logger.Logger, config EnvironmentConfig) (*deployment.Environment, *DON, error) { +func NewEnvironment(ctx context.Context, lggr logger.Logger, config EnvironmentConfig) (*deployment.Environment, *DON, error) { chains, err := NewChains(lggr, config.Chains) if err != nil { return nil, nil, fmt.Errorf("failed to create chains: %w", err) } - offChain, err := NewJDClient(ctx(), config.JDConfig) + offChain, err := NewJDClient(ctx, config.JDConfig) if err != nil { return nil, nil, fmt.Errorf("failed to create JD client: %w", err) } @@ -32,17 +34,15 @@ func NewEnvironment(ctx func() context.Context, lggr logger.Logger, config Envir if !ok { return nil, nil, fmt.Errorf("offchain client does not implement JobDistributor") } - if jd == nil { - return nil, nil, fmt.Errorf("offchain client is not set up") + if jd == nil || jd.don == nil { + return nil, nil, fmt.Errorf("offchain client does not have a DON") } - var nodeIDs []string - if jd.don != nil { - err = jd.don.CreateSupportedChains(ctx(), config.Chains, *jd) - if err != nil { - return nil, nil, err - } - nodeIDs = jd.don.NodeIds() + + err = jd.don.CreateSupportedChains(ctx, config.Chains, *jd) + if err != nil { + return nil, nil, err } + nodeIDs := jd.don.NodeIds() return deployment.NewEnvironment( DevEnv, @@ -51,7 +51,5 @@ func NewEnvironment(ctx func() context.Context, lggr logger.Logger, config Envir chains, nodeIDs, offChain, - ctx, - deployment.XXXGenerateTestOCRSecrets(), ), jd.don, nil } diff --git a/deployment/environment/devenv/jd.go b/deployment/environment/devenv/jd.go index 818f9b09400..9af8412d61e 100644 --- a/deployment/environment/devenv/jd.go +++ b/deployment/environment/devenv/jd.go @@ -20,7 +20,6 @@ type JDConfig struct { WSRPC string Creds credentials.TransportCredentials Auth oauth2.TokenSource - GAP string NodeInfo []NodeInfo } @@ -45,40 +44,13 @@ func authTokenInterceptor(source oauth2.TokenSource) grpc.UnaryClientInterceptor } } -func gapTokenInterceptor(token string) grpc.UnaryClientInterceptor { - return func( - ctx context.Context, - method string, - req, reply any, - cc *grpc.ClientConn, - invoker grpc.UnaryInvoker, - opts ...grpc.CallOption, - ) error { - return invoker( - metadata.AppendToOutgoingContext(ctx, "x-authorization-github-jwt", "Bearer "+token), - method, req, reply, cc, opts..., - ) - } -} - func NewJDConnection(cfg JDConfig) (*grpc.ClientConn, error) { - opts := []grpc.DialOption{} - interceptors := []grpc.UnaryClientInterceptor{} - - if cfg.Creds != nil { - opts = append(opts, grpc.WithTransportCredentials(cfg.Creds)) + opts := []grpc.DialOption{ + grpc.WithTransportCredentials(cfg.Creds), } if cfg.Auth != nil { - interceptors = append(interceptors, authTokenInterceptor(cfg.Auth)) + opts = append(opts, grpc.WithUnaryInterceptor(authTokenInterceptor(cfg.Auth))) } - if cfg.GAP != "" { - interceptors = append(interceptors, gapTokenInterceptor(cfg.GAP)) - } - - if len(interceptors) > 0 { - opts = append(opts, grpc.WithChainUnaryInterceptor(interceptors...)) - } - conn, err := grpc.NewClient(cfg.GRPC, opts...) if err != nil { return nil, fmt.Errorf("failed to connect Job Distributor service. Err: %w", err) diff --git a/deployment/environment/devenv/rmn.go b/deployment/environment/devenv/rmn.go index 3e0c6efe0cd..63f27f1e422 100644 --- a/deployment/environment/devenv/rmn.go +++ b/deployment/environment/devenv/rmn.go @@ -22,6 +22,7 @@ import ( "github.com/smartcontractkit/chainlink-testing-framework/lib/docker" "github.com/smartcontractkit/chainlink-testing-framework/lib/docker/test_env" "github.com/smartcontractkit/chainlink-testing-framework/lib/logging" + "github.com/smartcontractkit/chainlink-testing-framework/lib/logstream" p2ptypes "github.com/smartcontractkit/chainlink/v2/core/services/p2p/types" ) @@ -50,6 +51,7 @@ func NewRage2ProxyComponent( imageVersion string, local ProxyLocalConfig, shared ProxySharedConfig, + logStream *logstream.LogStream, ) (*RageProxy, error) { rageName := fmt.Sprintf("%s-proxy-%s", name, uuid.NewString()[0:8]) @@ -69,6 +71,7 @@ func NewRage2ProxyComponent( ContainerImage: imageName, ContainerVersion: imageVersion, Networks: networks, + LogStream: logStream, }, Passphrase: DefaultAFNPassphrase, proxyListenerPort: listenPort, @@ -190,7 +193,8 @@ func NewAFN2ProxyComponent( imageName, imageVersion string, shared SharedConfig, - local LocalConfig) (*AFN2Proxy, error) { + local LocalConfig, + logStream *logstream.LogStream) (*AFN2Proxy, error) { afnName := fmt.Sprintf("%s-%s", name, uuid.NewString()[0:8]) rmn := &AFN2Proxy{ EnvComponent: test_env.EnvComponent{ @@ -198,6 +202,7 @@ func NewAFN2ProxyComponent( ContainerImage: imageName, ContainerVersion: imageVersion, Networks: networks, + LogStream: logStream, }, AFNPassphrase: DefaultAFNPassphrase, Shared: shared, @@ -338,6 +343,7 @@ func NewRMNCluster( proxyVersion string, rmnImage string, rmnVersion string, + logStream *logstream.LogStream, ) (*RMNCluster, error) { rmn := &RMNCluster{ t: t, @@ -345,7 +351,7 @@ func NewRMNCluster( Nodes: make(map[string]RMNNode), } for name, rmnConfig := range config { - proxy, err := NewRage2ProxyComponent(networks, name, proxyImage, proxyVersion, rmnConfig.ProxyLocal, rmnConfig.ProxyShared) + proxy, err := NewRage2ProxyComponent(networks, name, proxyImage, proxyVersion, rmnConfig.ProxyLocal, rmnConfig.ProxyShared, logStream) if err != nil { return nil, err } @@ -365,7 +371,7 @@ func NewRMNCluster( return nil, err } rmnConfig.Local.Networking.RageProxy = strings.TrimPrefix(fmt.Sprintf("%s:%s", proxyName, port), "/") - afn, err := NewAFN2ProxyComponent(networks, name, rmnImage, rmnVersion, rmnConfig.Shared, rmnConfig.Local) + afn, err := NewAFN2ProxyComponent(networks, name, rmnImage, rmnVersion, rmnConfig.Shared, rmnConfig.Local, logStream) if err != nil { return nil, err } diff --git a/deployment/environment/devenv/rmn_config.go b/deployment/environment/devenv/rmn_config.go index 623499a6fe8..59d5e5d1cdb 100644 --- a/deployment/environment/devenv/rmn_config.go +++ b/deployment/environment/devenv/rmn_config.go @@ -33,7 +33,7 @@ type SharedConfigNetworking struct { type HomeChain struct { Name string `toml:"name"` CapabilitiesRegistry string `toml:"capabilities_registry"` - CCIPHome string `toml:"ccip_home"` + CCIPConfig string `toml:"ccip_config"` RMNHome string `toml:"rmn_home"` } diff --git a/deployment/environment/memory/chain.go b/deployment/environment/memory/chain.go index 77a8f397d39..1bb359f9c53 100644 --- a/deployment/environment/memory/chain.go +++ b/deployment/environment/memory/chain.go @@ -9,19 +9,17 @@ import ( "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/ethclient/simulated" + "github.com/ethereum/go-ethereum/params" "github.com/stretchr/testify/require" chainsel "github.com/smartcontractkit/chain-selectors" "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" - - "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" ) type EVMChain struct { Backend *simulated.Backend DeployerKey *bind.TransactOpts - Users []*bind.TransactOpts } func fundAddress(t *testing.T, from *bind.TransactOpts, to common.Address, amount *big.Int, backend *simulated.Backend) { @@ -44,46 +42,42 @@ func fundAddress(t *testing.T, from *bind.TransactOpts, to common.Address, amoun backend.Commit() } -func GenerateChains(t *testing.T, numChains int, numUsers int) map[uint64]EVMChain { +func GenerateChains(t *testing.T, numChains int) map[uint64]EVMChain { chains := make(map[uint64]EVMChain) for i := 0; i < numChains; i++ { chainID := chainsel.TEST_90000001.EvmChainID + uint64(i) - chains[chainID] = evmChain(t, numUsers) + key, err := crypto.GenerateKey() + require.NoError(t, err) + owner, err := bind.NewKeyedTransactorWithChainID(key, big.NewInt(1337)) + require.NoError(t, err) + // there have to be enough initial funds on each chain to allocate for all the nodes that share the given chain in the test + backend := simulated.NewBackend(types.GenesisAlloc{ + owner.From: {Balance: big.NewInt(0).Mul(big.NewInt(7000), big.NewInt(params.Ether))}}, + simulated.WithBlockGasLimit(50000000)) + backend.Commit() // ts will be now. + chains[chainID] = EVMChain{ + Backend: backend, + DeployerKey: owner, + } } return chains } -func GenerateChainsWithIds(t *testing.T, chainIDs []uint64, numUsers int) map[uint64]EVMChain { +func GenerateChainsWithIds(t *testing.T, chainIDs []uint64) map[uint64]EVMChain { chains := make(map[uint64]EVMChain) for _, chainID := range chainIDs { - chains[chainID] = evmChain(t, numUsers) - } - return chains -} - -func evmChain(t *testing.T, numUsers int) EVMChain { - key, err := crypto.GenerateKey() - require.NoError(t, err) - owner, err := bind.NewKeyedTransactorWithChainID(key, big.NewInt(1337)) - require.NoError(t, err) - genesis := types.GenesisAlloc{ - owner.From: {Balance: assets.Ether(1_000_000).ToInt()}} - // create a set of user keys - var users []*bind.TransactOpts - for j := 0; j < numUsers; j++ { key, err := crypto.GenerateKey() require.NoError(t, err) - user, err := bind.NewKeyedTransactorWithChainID(key, big.NewInt(1337)) + owner, err := bind.NewKeyedTransactorWithChainID(key, big.NewInt(1337)) require.NoError(t, err) - users = append(users, user) - genesis[user.From] = types.Account{Balance: assets.Ether(1_000_000).ToInt()} - } - // there have to be enough initial funds on each chain to allocate for all the nodes that share the given chain in the test - backend := simulated.NewBackend(genesis, simulated.WithBlockGasLimit(50000000)) - backend.Commit() // ts will be now. - return EVMChain{ - Backend: backend, - DeployerKey: owner, - Users: users, + backend := simulated.NewBackend(types.GenesisAlloc{ + owner.From: {Balance: big.NewInt(0).Mul(big.NewInt(700000), big.NewInt(params.Ether))}}, + simulated.WithBlockGasLimit(10000000)) + backend.Commit() // Note initializes block timestamp to now(). + chains[chainID] = EVMChain{ + Backend: backend, + DeployerKey: owner, + } } + return chains } diff --git a/deployment/environment/memory/environment.go b/deployment/environment/memory/environment.go index a74d23a847b..a1478a3bf52 100644 --- a/deployment/environment/memory/environment.go +++ b/deployment/environment/memory/environment.go @@ -3,9 +3,7 @@ package memory import ( "context" "fmt" - "strconv" "testing" - "time" "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/core/types" @@ -15,8 +13,6 @@ import ( chainsel "github.com/smartcontractkit/chain-selectors" - "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" - "github.com/smartcontractkit/chainlink/deployment" "github.com/smartcontractkit/chainlink-common/pkg/logger" @@ -27,11 +23,10 @@ const ( ) type MemoryEnvironmentConfig struct { - Chains int - NumOfUsersPerChain int - Nodes int - Bootstraps int - RegistryConfig deployment.CapabilityRegistryConfig + Chains int + Nodes int + Bootstraps int + RegistryConfig deployment.CapabilityRegistryConfig } // For placeholders like aptos @@ -48,64 +43,48 @@ func NewMemoryChain(t *testing.T, selector uint64) deployment.Chain { // Needed for environment variables on the node which point to prexisitng addresses. // i.e. CapReg. -func NewMemoryChains(t *testing.T, numChains int, numUsers int) (map[uint64]deployment.Chain, map[uint64][]*bind.TransactOpts) { - mchains := GenerateChains(t, numChains, numUsers) - users := make(map[uint64][]*bind.TransactOpts) - for id, chain := range mchains { - sel, err := chainsel.SelectorFromChainId(id) - require.NoError(t, err) - users[sel] = chain.Users - } - return generateMemoryChain(t, mchains), users +func NewMemoryChains(t *testing.T, numChains int) map[uint64]deployment.Chain { + mchains := GenerateChains(t, numChains) + return generateMemoryChain(t, mchains) } -func NewMemoryChainsWithChainIDs(t *testing.T, chainIDs []uint64, numUsers int) (map[uint64]deployment.Chain, map[uint64][]*bind.TransactOpts) { - mchains := GenerateChainsWithIds(t, chainIDs, numUsers) - users := make(map[uint64][]*bind.TransactOpts) - for id, chain := range mchains { - sel, err := chainsel.SelectorFromChainId(id) - require.NoError(t, err) - users[sel] = chain.Users - } - return generateMemoryChain(t, mchains), users +func NewMemoryChainsWithChainIDs(t *testing.T, chainIDs []uint64) map[uint64]deployment.Chain { + mchains := GenerateChainsWithIds(t, chainIDs) + return generateMemoryChain(t, mchains) } func generateMemoryChain(t *testing.T, inputs map[uint64]EVMChain) map[uint64]deployment.Chain { chains := make(map[uint64]deployment.Chain) for cid, chain := range inputs { chain := chain - chainInfo, err := chainsel.GetChainDetailsByChainIDAndFamily(strconv.FormatUint(cid, 10), chainsel.FamilyEVM) + sel, err := chainsel.SelectorFromChainId(cid) require.NoError(t, err) backend := NewBackend(chain.Backend) - chains[chainInfo.ChainSelector] = deployment.Chain{ - Selector: chainInfo.ChainSelector, + chains[sel] = deployment.Chain{ + Selector: sel, Client: backend, DeployerKey: chain.DeployerKey, Confirm: func(tx *types.Transaction) (uint64, error) { if tx == nil { - return 0, fmt.Errorf("tx was nil, nothing to confirm, chain %s", chainInfo.ChainName) + return 0, fmt.Errorf("tx was nil, nothing to confirm") } for { backend.Commit() - receipt, err := func() (*types.Receipt, error) { - ctx, cancel := context.WithTimeout(context.Background(), 1*time.Minute) - defer cancel() - return bind.WaitMined(ctx, backend, tx) - }() + receipt, err := backend.TransactionReceipt(context.Background(), tx.Hash()) if err != nil { - return 0, fmt.Errorf("tx %s failed to confirm: %w, chain %d", tx.Hash().Hex(), err, chainInfo.ChainSelector) + t.Log("failed to get receipt", err) + continue } if receipt.Status == 0 { errReason, err := deployment.GetErrorReasonFromTx(chain.Backend.Client(), chain.DeployerKey.From, tx, receipt) if err == nil && errReason != "" { - return 0, fmt.Errorf("tx %s reverted,error reason: %s chain %s", tx.Hash().Hex(), errReason, chainInfo.ChainName) + return 0, fmt.Errorf("tx %s reverted,error reason: %s", tx.Hash().Hex(), errReason) } - return 0, fmt.Errorf("tx %s reverted, could not decode error reason chain %s", tx.Hash().Hex(), chainInfo.ChainName) + return 0, fmt.Errorf("tx %s reverted, could not decode error reason", tx.Hash().Hex()) } return receipt.BlockNumber.Uint64(), nil } }, - Users: chain.Users, } } return chains @@ -113,9 +92,6 @@ func generateMemoryChain(t *testing.T, inputs map[uint64]EVMChain) map[uint64]de func NewNodes(t *testing.T, logLevel zapcore.Level, chains map[uint64]deployment.Chain, numNodes, numBootstraps int, registryConfig deployment.CapabilityRegistryConfig) map[string]Node { nodesByPeerID := make(map[string]Node) - if numNodes+numBootstraps == 0 { - return nodesByPeerID - } ports := freeport.GetN(t, numBootstraps+numNodes) // bootstrap nodes must be separate nodes from plugin nodes, // since we won't run a bootstrapper and a plugin oracle on the same @@ -134,12 +110,10 @@ func NewNodes(t *testing.T, logLevel zapcore.Level, chains map[uint64]deployment return nodesByPeerID } -func NewMemoryEnvironmentFromChainsNodes( - ctx func() context.Context, +func NewMemoryEnvironmentFromChainsNodes(t *testing.T, lggr logger.Logger, chains map[uint64]deployment.Chain, - nodes map[string]Node, -) deployment.Environment { + nodes map[string]Node) deployment.Environment { var nodeIDs []string for id := range nodes { nodeIDs = append(nodeIDs, id) @@ -151,14 +125,12 @@ func NewMemoryEnvironmentFromChainsNodes( chains, nodeIDs, // Note these have the p2p_ prefix. NewMemoryJobClient(nodes), - ctx, - deployment.XXXGenerateTestOCRSecrets(), ) } // To be used by tests and any kind of deployment logic. func NewMemoryEnvironment(t *testing.T, lggr logger.Logger, logLevel zapcore.Level, config MemoryEnvironmentConfig) deployment.Environment { - chains, _ := NewMemoryChains(t, config.Chains, config.NumOfUsersPerChain) + chains := NewMemoryChains(t, config.Chains) nodes := NewNodes(t, logLevel, chains, config.Nodes, config.Bootstraps, config.RegistryConfig) var nodeIDs []string for id := range nodes { @@ -171,7 +143,5 @@ func NewMemoryEnvironment(t *testing.T, lggr logger.Logger, logLevel zapcore.Lev chains, nodeIDs, NewMemoryJobClient(nodes), - func() context.Context { return tests.Context(t) }, - deployment.XXXGenerateTestOCRSecrets(), ) } diff --git a/deployment/environment/memory/job_client.go b/deployment/environment/memory/job_client.go index a3cfee41608..df1e3d5c5d5 100644 --- a/deployment/environment/memory/job_client.go +++ b/deployment/environment/memory/job_client.go @@ -17,22 +17,14 @@ import ( jobv1 "github.com/smartcontractkit/chainlink-protos/job-distributor/v1/job" nodev1 "github.com/smartcontractkit/chainlink-protos/job-distributor/v1/node" "github.com/smartcontractkit/chainlink-protos/job-distributor/v1/shared/ptypes" - "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/validate" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/chaintype" - ocr2validate "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/validate" - "github.com/smartcontractkit/chainlink/v2/core/services/ocrbootstrap" ) type JobClient struct { Nodes map[string]Node } -func (j JobClient) BatchProposeJob(ctx context.Context, in *jobv1.BatchProposeJobRequest, opts ...grpc.CallOption) (*jobv1.BatchProposeJobResponse, error) { - //TODO CCIP-3108 implement me - panic("implement me") -} - func (j JobClient) UpdateJob(ctx context.Context, in *jobv1.UpdateJobRequest, opts ...grpc.CallOption) (*jobv1.UpdateJobResponse, error) { //TODO CCIP-3108 implement me panic("implement me") @@ -192,17 +184,16 @@ func (j JobClient) ListNodeChainConfigs(ctx context.Context, in *nodev1.ListNode if err != nil { return nil, err } + chainID, err := chainsel.ChainIdFromSelector(selector) + if err != nil { + return nil, err + } + if family == chainsel.FamilyEVM { // already handled above continue } - // NOTE: this supports non-EVM too - chainID, err := chainsel.GetChainIDFromSelector(selector) - if err != nil { - return nil, err - } - var ocrtype chaintype.ChainType switch family { case chainsel.FamilyEVM: @@ -216,7 +207,7 @@ func (j JobClient) ListNodeChainConfigs(ctx context.Context, in *nodev1.ListNode case chainsel.FamilyAptos: ocrtype = chaintype.Aptos default: - return nil, fmt.Errorf("Unsupported chain family %v", family) + panic(fmt.Sprintf("Unsupported chain family %v", family)) } bundle := n.Keys.OCRKeyBundles[ocrtype] @@ -247,7 +238,7 @@ func (j JobClient) ListNodeChainConfigs(ctx context.Context, in *nodev1.ListNode chainConfigs = append(chainConfigs, &nodev1.ChainConfig{ Chain: &nodev1.Chain{ - Id: chainID, + Id: strconv.Itoa(int(chainID)), Type: ctype, }, AccountAddress: "", // TODO: support AccountAddress @@ -297,27 +288,7 @@ func (j JobClient) ProposeJob(ctx context.Context, in *jobv1.ProposeJobRequest, // TODO: Use FMS jb, err := validate.ValidatedCCIPSpec(in.Spec) if err != nil { - if !strings.Contains(err.Error(), "the only supported type is currently 'ccip'") { - return nil, err - } - // check if it's offchainreporting2 job - jb, err = ocr2validate.ValidatedOracleSpecToml( - ctx, - n.App.GetConfig().OCR2(), - n.App.GetConfig().Insecure(), - in.Spec, - nil, // not required for validation - ) - if err != nil { - if !strings.Contains(err.Error(), "the only supported type is currently 'offchainreporting2'") { - return nil, err - } - // check if it's bootstrap job - jb, err = ocrbootstrap.ValidatedBootstrapSpecToml(in.Spec) - if err != nil { - return nil, fmt.Errorf("failed to validate job spec only ccip, bootstrap and offchainreporting2 are supported: %w", err) - } - } + return nil, err } err = n.App.AddJobV2(ctx, &jb) if err != nil { diff --git a/deployment/environment/memory/node.go b/deployment/environment/memory/node.go index 84f0d2e443f..c2e4e457fbd 100644 --- a/deployment/environment/memory/node.go +++ b/deployment/environment/memory/node.go @@ -78,10 +78,6 @@ func NewNode( ) *Node { evmchains := make(map[uint64]EVMChain) for _, chain := range chains { - // we're only mapping evm chains here - if family, err := chainsel.GetSelectorFamily(chain.Selector); err != nil || family != chainsel.FamilyEVM { - continue - } evmChainID, err := chainsel.ChainIdFromSelector(chain.Selector) if err != nil { t.Fatal(err) @@ -286,8 +282,6 @@ func CreateKeys(t *testing.T, } backend := chain.Client.(*Backend).Sim fundAddress(t, chain.DeployerKey, transmitters[evmChainID], assets.Ether(1000).ToInt(), backend) - // need to look more into it, but it seems like with sim chains nodes are sending txs with 0x from address - fundAddress(t, chain.DeployerKey, common.Address{}, assets.Ether(1000).ToInt(), backend) } return Keys{ diff --git a/deployment/environment/memory/node_test.go b/deployment/environment/memory/node_test.go index 78bc2db90e5..7cbcb66d04a 100644 --- a/deployment/environment/memory/node_test.go +++ b/deployment/environment/memory/node_test.go @@ -8,12 +8,11 @@ import ( "go.uber.org/zap/zapcore" "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" - "github.com/smartcontractkit/chainlink/deployment" ) func TestNode(t *testing.T) { - chains, _ := NewMemoryChains(t, 3, 5) + chains := NewMemoryChains(t, 3) ports := freeport.GetN(t, 1) node := NewNode(t, ports[0], chains, zapcore.DebugLevel, false, deployment.CapabilityRegistryConfig{}) // We expect 3 transmitter keys diff --git a/deployment/environment/web/sdk/client/client.go b/deployment/environment/web/sdk/client/client.go index e0a56b9e642..011eb0cce31 100644 --- a/deployment/environment/web/sdk/client/client.go +++ b/deployment/environment/web/sdk/client/client.go @@ -4,11 +4,10 @@ import ( "context" "encoding/json" "fmt" - "github.com/Khan/genqlient/graphql" - "github.com/sethvargo/go-retry" "net/http" "strings" - "time" + + "github.com/Khan/genqlient/graphql" "github.com/smartcontractkit/chainlink/deployment/environment/web/sdk/client/doer" "github.com/smartcontractkit/chainlink/deployment/environment/web/sdk/internal/generated" @@ -61,15 +60,8 @@ func New(baseURI string, creds Credentials) (Client, error) { endpoints: ep, credentials: creds, } - - err := retry.Do(context.Background(), retry.WithMaxDuration(10*time.Second, retry.NewFibonacci(2*time.Second)), func(ctx context.Context) error { - err := c.login() - if err != nil { - return retry.RetryableError(fmt.Errorf("retrying login to node: %w", err)) - } - return nil - }) - if err != nil { + + if err := c.login(); err != nil { return nil, fmt.Errorf("failed to login to node: %w", err) } @@ -210,11 +202,7 @@ func (c *client) CreateJobDistributor(ctx context.Context, in JobDistributorInpu feedsManager := success.GetFeedsManager() return feedsManager.GetId(), nil } - if err, ok := response.GetCreateFeedsManager().(*generated.CreateFeedsManagerCreateFeedsManagerSingleFeedsManagerError); ok { - msg := err.GetMessage() - return "", fmt.Errorf("failed to create feeds manager: %v", msg) - } - return "", fmt.Errorf("failed to create feeds manager: %v", response.GetCreateFeedsManager().GetTypename()) + return "", fmt.Errorf("failed to create feeds manager") } func (c *client) UpdateJobDistributor(ctx context.Context, id string, in JobDistributorInput) error { diff --git a/deployment/environment_test.go b/deployment/environment_test.go deleted file mode 100644 index 37a7e3baeae..00000000000 --- a/deployment/environment_test.go +++ /dev/null @@ -1,91 +0,0 @@ -package deployment - -import ( - "reflect" - "testing" - - chain_selectors "github.com/smartcontractkit/chain-selectors" -) - -func TestNode_OCRConfigForChainSelector(t *testing.T) { - var m = map[chain_selectors.ChainDetails]OCRConfig{ - chain_selectors.ChainDetails{ - ChainSelector: chain_selectors.APTOS_TESTNET.Selector, - ChainName: chain_selectors.APTOS_TESTNET.Name, - }: OCRConfig{ - KeyBundleID: "aptos bundle 1", - }, - chain_selectors.ChainDetails{ - ChainSelector: chain_selectors.ETHEREUM_MAINNET_ARBITRUM_1.Selector, - ChainName: chain_selectors.ETHEREUM_MAINNET_ARBITRUM_1.Name, - }: OCRConfig{ - KeyBundleID: "arb bundle 1", - }, - } - - type fields struct { - SelToOCRConfig map[chain_selectors.ChainDetails]OCRConfig - } - type args struct { - chainSel uint64 - } - tests := []struct { - name string - fields fields - args args - want OCRConfig - exist bool - }{ - { - name: "aptos ok", - fields: fields{ - SelToOCRConfig: m, - }, - args: args{ - chainSel: chain_selectors.APTOS_TESTNET.Selector, - }, - want: OCRConfig{ - KeyBundleID: "aptos bundle 1", - }, - exist: true, - }, - { - name: "arb ok", - fields: fields{ - SelToOCRConfig: m, - }, - args: args{ - chainSel: chain_selectors.ETHEREUM_MAINNET_ARBITRUM_1.Selector, - }, - want: OCRConfig{ - KeyBundleID: "arb bundle 1", - }, - exist: true, - }, - { - name: "no exist", - fields: fields{ - SelToOCRConfig: m, - }, - args: args{ - chainSel: chain_selectors.WEMIX_MAINNET.Selector, // not in test data - }, - want: OCRConfig{}, - exist: false, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - n := Node{ - SelToOCRConfig: tt.fields.SelToOCRConfig, - } - got, got1 := n.OCRConfigForChainSelector(tt.args.chainSel) - if !reflect.DeepEqual(got, tt.want) { - t.Errorf("Node.OCRConfigForChainSelector() got = %v, want %v", got, tt.want) - } - if got1 != tt.exist { - t.Errorf("Node.OCRConfigForChainSelector() got1 = %v, want %v", got1, tt.exist) - } - }) - } -} diff --git a/deployment/evm_kmsclient.go b/deployment/evm_kmsclient.go index b28a3842930..07af77523c8 100644 --- a/deployment/evm_kmsclient.go +++ b/deployment/evm_kmsclient.go @@ -8,7 +8,6 @@ import ( "encoding/hex" "fmt" "math/big" - "os" "github.com/aws/aws-sdk-go/aws/session" @@ -232,21 +231,3 @@ var awsSessionFromProfileFn = func(config KMS) *session.Session { }, })) } - -func KMSConfigFromEnvVars() (KMS, error) { - var config KMS - var exists bool - config.KmsDeployerKeyId, exists = os.LookupEnv("KMS_DEPLOYER_KEY_ID") - if !exists { - return config, fmt.Errorf("KMS_DEPLOYER_KEY_ID is required") - } - config.KmsDeployerKeyRegion, exists = os.LookupEnv("KMS_DEPLOYER_KEY_REGION") - if !exists { - return config, fmt.Errorf("KMS_DEPLOYER_KEY_REGION is required") - } - config.AwsProfileName, exists = os.LookupEnv("AWS_PROFILE") - if !exists { - return config, fmt.Errorf("AWS_PROFILE is required") - } - return config, nil -} diff --git a/deployment/go.mod b/deployment/go.mod index 9eb3a02d573..0e9b16bad92 100644 --- a/deployment/go.mod +++ b/deployment/go.mod @@ -1,16 +1,10 @@ module github.com/smartcontractkit/chainlink/deployment -go 1.23.3 - -toolchain go1.23.4 +go 1.22.8 // Make sure we're working with the latest chainlink libs replace github.com/smartcontractkit/chainlink/v2 => ../ -// Using a separate inline `require` here to avoid surrounding line changes -// creating potential merge conflicts. -require github.com/smartcontractkit/chainlink/v2 v2.0.0-20241206210521-125d98cdaf66 - require ( github.com/Khan/genqlient v0.7.0 github.com/Masterminds/semver/v3 v3.3.0 @@ -26,12 +20,13 @@ require ( github.com/pkg/errors v0.9.1 github.com/rs/zerolog v1.33.0 github.com/sethvargo/go-retry v0.2.4 - github.com/smartcontractkit/ccip-owner-contracts v0.0.0-salt-fix - github.com/smartcontractkit/chain-selectors v1.0.34 - github.com/smartcontractkit/chainlink-ccip v0.0.0-20241218114855-f74219171000 - github.com/smartcontractkit/chainlink-common v0.4.1-0.20241217120918-bbe318cd0760 - github.com/smartcontractkit/chainlink-protos/job-distributor v0.6.0 + github.com/smartcontractkit/ccip-owner-contracts v0.0.0-20240926212305-a6deabdfce86 + github.com/smartcontractkit/chain-selectors v1.0.29 + github.com/smartcontractkit/chainlink-ccip v0.0.0-20241118091009-43c2b4804cec + github.com/smartcontractkit/chainlink-common v0.3.1-0.20241114134822-aadff98ef068 + github.com/smartcontractkit/chainlink-protos/job-distributor v0.4.0 github.com/smartcontractkit/chainlink-testing-framework/lib v1.50.13 + github.com/smartcontractkit/chainlink/v2 v2.0.0-00010101000000-000000000000 github.com/smartcontractkit/libocr v0.0.0-20241007185508-adbe57025f12 github.com/stretchr/testify v1.9.0 github.com/test-go/testify v1.1.4 @@ -40,7 +35,7 @@ require ( go.uber.org/zap v1.27.0 golang.org/x/exp v0.0.0-20241009180824-f66d83c29e7c golang.org/x/oauth2 v0.23.0 - golang.org/x/sync v0.10.0 + golang.org/x/sync v0.8.0 google.golang.org/grpc v1.67.1 google.golang.org/protobuf v1.35.1 gopkg.in/guregu/null.v4 v4.0.0 @@ -82,7 +77,7 @@ require ( github.com/alecthomas/units v0.0.0-20240626203959-61d1e3462e30 // indirect github.com/alexflint/go-arg v1.4.2 // indirect github.com/alexflint/go-scalar v1.0.0 // indirect - github.com/andybalholm/brotli v1.1.1 // indirect + github.com/andybalholm/brotli v1.1.0 // indirect github.com/armon/go-metrics v0.4.1 // indirect github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect github.com/atombender/go-jsonschema v0.16.1-0.20240916205339-a74cd4e2851c // indirect @@ -113,7 +108,7 @@ require ( github.com/blang/semver/v4 v4.0.0 // indirect github.com/blendle/zapdriver v1.3.1 // indirect github.com/btcsuite/btcd/btcec/v2 v2.3.4 // indirect - github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0 // indirect + github.com/btcsuite/btcd/chaincfg/chainhash v1.0.3 // indirect github.com/buger/jsonparser v1.1.1 // indirect github.com/bytecodealliance/wasmtime-go/v23 v23.0.0 // indirect github.com/bytedance/sonic v1.11.6 // indirect @@ -223,7 +218,7 @@ require ( github.com/go-viper/mapstructure/v2 v2.1.0 // indirect github.com/go-webauthn/webauthn v0.9.4 // indirect github.com/go-webauthn/x v0.1.5 // indirect - github.com/goccy/go-json v0.10.3 // indirect + github.com/goccy/go-json v0.10.2 // indirect github.com/goccy/go-yaml v1.12.0 // indirect github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2 // indirect github.com/gofrs/flock v0.8.1 // indirect @@ -315,12 +310,12 @@ require ( github.com/json-iterator/go v1.1.12 // indirect github.com/julienschmidt/httprouter v1.3.0 // indirect github.com/kelseyhightower/envconfig v1.4.0 // indirect - github.com/klauspost/compress v1.17.11 // indirect - github.com/klauspost/cpuid/v2 v2.2.8 // indirect + github.com/klauspost/compress v1.17.9 // indirect + github.com/klauspost/cpuid/v2 v2.2.7 // indirect github.com/kr/pretty v0.3.1 // indirect github.com/kr/text v0.2.0 // indirect github.com/kylelemons/godebug v1.1.0 // indirect - github.com/leanovate/gopter v0.2.11 // indirect + github.com/leanovate/gopter v0.2.10-0.20210127095200-9abe2343507a // indirect github.com/leodido/go-urn v1.4.0 // indirect github.com/lib/pq v1.10.9 // indirect github.com/libp2p/go-buffer-pool v0.1.0 // indirect @@ -364,7 +359,6 @@ require ( github.com/oklog/run v1.1.0 // indirect github.com/oklog/ulid v1.3.1 // indirect github.com/olekukonko/tablewriter v0.0.5 // indirect - github.com/onsi/gomega v1.34.2 // indirect github.com/opencontainers/go-digest v1.0.0 // indirect github.com/opencontainers/image-spec v1.1.0 // indirect github.com/opentracing-contrib/go-grpc v0.0.0-20210225150812-73cb765af46e // indirect @@ -390,7 +384,7 @@ require ( github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect github.com/rivo/uniseg v0.4.4 // indirect github.com/robfig/cron/v3 v3.0.1 // indirect - github.com/rogpeppe/go-internal v1.13.1 // indirect + github.com/rogpeppe/go-internal v1.12.0 // indirect github.com/rs/cors v1.10.1 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/sagikazarmark/locafero v0.4.0 // indirect @@ -407,19 +401,19 @@ require ( github.com/shopspring/decimal v1.4.0 // indirect github.com/sirupsen/logrus v1.9.3 // indirect github.com/smartcontractkit/chainlink-automation v0.8.1 // indirect - github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241202195413-82468150ac1e // indirect - github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20241216163550-fa030d178ba3 // indirect + github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241017133723-5277829bd53f // indirect + github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20241018134907-a00ba3729b5e // indirect github.com/smartcontractkit/chainlink-feeds v0.1.1 // indirect - github.com/smartcontractkit/chainlink-protos/orchestrator v0.4.0 // indirect - github.com/smartcontractkit/chainlink-solana v1.1.1-0.20241219173444-150f7443fdd3 // indirect - github.com/smartcontractkit/chainlink-starknet/relayer v0.1.1-0.20241202202529-2033490e77b8 // indirect + github.com/smartcontractkit/chainlink-protos/orchestrator v0.3.0 // indirect + github.com/smartcontractkit/chainlink-solana v1.1.1-0.20241115191142-8b8369c1f44e // indirect + github.com/smartcontractkit/chainlink-starknet/relayer v0.1.1-0.20241017135645-176a23722fd8 // indirect github.com/smartcontractkit/chainlink-testing-framework/lib/grafana v1.50.0 // indirect github.com/smartcontractkit/chainlink-testing-framework/seth v1.50.5 // indirect github.com/smartcontractkit/chainlink-testing-framework/wasp v1.50.2 // indirect github.com/smartcontractkit/grpc-proxy v0.0.0-20240830132753-a7e17fec5ab7 // indirect github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20241009055228-33d0c0bf38de // indirect github.com/smartcontractkit/tdh2/go/tdh2 v0.0.0-20241009055228-33d0c0bf38de // indirect - github.com/smartcontractkit/wsrpc v0.8.3 // indirect + github.com/smartcontractkit/wsrpc v0.8.2 // indirect github.com/soheilhy/cmux v0.1.5 // indirect github.com/sony/gobreaker v0.5.0 // indirect github.com/sourcegraph/conc v0.3.0 // indirect @@ -493,12 +487,12 @@ require ( go.uber.org/ratelimit v0.3.1 // indirect go4.org/netipx v0.0.0-20230125063823-8449b0a6169f // indirect golang.org/x/arch v0.11.0 // indirect - golang.org/x/crypto v0.31.0 // indirect + golang.org/x/crypto v0.28.0 // indirect golang.org/x/mod v0.21.0 // indirect golang.org/x/net v0.30.0 // indirect - golang.org/x/sys v0.28.0 // indirect - golang.org/x/term v0.27.0 // indirect - golang.org/x/text v0.21.0 // indirect + golang.org/x/sys v0.26.0 // indirect + golang.org/x/term v0.25.0 // indirect + golang.org/x/text v0.19.0 // indirect golang.org/x/time v0.7.0 // indirect golang.org/x/tools v0.26.0 // indirect golang.org/x/xerrors v0.0.0-20240903120638-7835f813f4da // indirect diff --git a/deployment/go.sum b/deployment/go.sum index cc0176b90a8..b21fdc94975 100644 --- a/deployment/go.sum +++ b/deployment/go.sum @@ -16,11 +16,6 @@ cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKV cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs= cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc= cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= -cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI= -cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk= -cloud.google.com/go v0.78.0/go.mod h1:QjdrLG0uq+YwhjoVOLsS1t7TW8fs36kLs4XO5R5ECHg= -cloud.google.com/go v0.79.0/go.mod h1:3bzgcEeQlzbuEAYu4mrWhKqWjmpprinYgKJLgKHnbb8= -cloud.google.com/go v0.81.0/go.mod h1:mk/AM35KwGk/Nm2YSeZbxXdrNK3KZOYHmLkOqC2V6E0= cloud.google.com/go v0.116.0 h1:B3fRrSDkLRt5qSHWe40ERJvhvnQwdZiHu0bJOpldweE= cloud.google.com/go v0.116.0/go.mod h1:cEPSRWPzZEswwdr9BxE6ChEn01dWlTaF05LiC2Xs70U= cloud.google.com/go/auth v0.9.9 h1:BmtbpNQozo8ZwW2t7QJjnrQtdganSdmqeIBxHxNkEZQ= @@ -184,11 +179,9 @@ github.com/allegro/bigcache v1.2.1/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2uc github.com/andres-erbsen/clock v0.0.0-20160526145045-9e14626cd129/go.mod h1:rFgpPQZYZ8vdbc+48xibu8ALc3yeyd64IhHS+PU6Yyg= github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883 h1:bvNMNQO63//z+xNgfBlViaCIJKLlCJ6/fmUseuG0wVQ= github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8= -github.com/andybalholm/brotli v1.1.1 h1:PR2pgnyFznKEugtsUo0xLdDop5SKXd5Qf5ysW+7XdTA= -github.com/andybalholm/brotli v1.1.1/go.mod h1:05ib4cKhjx3OQYUY22hTVd34Bc8upXjOLL2rKwwZBoA= +github.com/andybalholm/brotli v1.1.0 h1:eLKJA0d02Lf0mVpIDgYnqXcUn0GqVmEFny3VuID1U3M= +github.com/andybalholm/brotli v1.1.0/go.mod h1:sms7XGricyQI9K10gOSf56VKKWS4oLer58Q+mhRPtnY= github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= -github.com/apache/arrow-go/v18 v18.0.0 h1:1dBDaSbH3LtulTyOVYaBCHO3yVRwjV+TZaqn3g6V7ZM= -github.com/apache/arrow-go/v18 v18.0.0/go.mod h1:t6+cWRSmKgdQ6HsxisQjok+jBpKGhRDiqcf3p0p/F+A= github.com/arbovm/levenshtein v0.0.0-20160628152529-48b4e1c0c4d0 h1:jfIu9sQUG6Ig+0+Ap1h4unLjW6YQJpKZVmUzxsD4E/Q= github.com/arbovm/levenshtein v0.0.0-20160628152529-48b4e1c0c4d0/go.mod h1:t2tdKJDJF9BV14lnkjHmOQgcvEKgtqs5a1N3LNdJhGE= github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= @@ -268,7 +261,6 @@ github.com/bgentry/speakeasy v0.1.1-0.20220910012023-760eaf8b6816/go.mod h1:+zsy github.com/bits-and-blooms/bitset v1.13.0 h1:bAQ9OPNFYbGHV6Nez0tmNI0RiEu7/hxlYJRUA0wFAVE= github.com/bits-and-blooms/bitset v1.13.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8= github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84= -github.com/bketelsen/crypt v0.0.4/go.mod h1:aI6NrJ0pMGgvZKL1iVgXLnfIFJtfV+bKCoqOes/6LfM= github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM= github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ= github.com/blendle/zapdriver v1.3.1 h1:C3dydBOWYRiOk+B8X9IVZ5IOe+7cl+tGOexN4QqHfpE= @@ -278,10 +270,10 @@ github.com/bradleyjkemp/cupaloy/v2 v2.6.0/go.mod h1:bm7JXdkRd4BHJk9HpwqAI8BoAY1l github.com/btcsuite/btcd v0.22.0-beta h1:LTDpDKUM5EeOFBPM8IXpinEcmZ6FWfNZbE3lfrfdnWo= github.com/btcsuite/btcd/btcec/v2 v2.3.2 h1:5n0X6hX0Zk+6omWcihdYvdAlGf2DfasC0GMf7DClJ3U= github.com/btcsuite/btcd/btcec/v2 v2.3.2/go.mod h1:zYzJ8etWJQIv1Ogk7OzpWjowwOdXY1W/17j2MW85J04= -github.com/btcsuite/btcd/btcutil v1.1.5 h1:+wER79R5670vs/ZusMTF1yTcRYE5GUsFbdjdisflzM8= -github.com/btcsuite/btcd/btcutil v1.1.5/go.mod h1:PSZZ4UitpLBWzxGd5VGOrLnmOjtPP/a6HaFo12zMs00= -github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0 h1:59Kx4K6lzOW5w6nFlA0v5+lk/6sjybR934QNHSJZPTQ= -github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= +github.com/btcsuite/btcd/btcutil v1.1.3 h1:xfbtw8lwpp0G6NwSHb+UE67ryTFHJAiNuipusjXSohQ= +github.com/btcsuite/btcd/btcutil v1.1.3/go.mod h1:UR7dsSJzJUfMmFiiLlIrMq1lS9jh9EdCV7FStZSnpi0= +github.com/btcsuite/btcd/chaincfg/chainhash v1.0.3 h1:SDlJ7bAm4ewvrmZtR0DaiYbQGdKPeaaIm7bM+qRhFeU= +github.com/btcsuite/btcd/chaincfg/chainhash v1.0.3/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= github.com/bufbuild/protocompile v0.4.0 h1:LbFKd2XowZvQ/kajzguUp2DC9UEIQhIq77fZZlaQsNA= github.com/bufbuild/protocompile v0.4.0/go.mod h1:3v93+mbWn/v3xzN+31nwkJfrEpAUwp+BagBSZWx+TP8= github.com/buger/jsonparser v1.1.1 h1:2PnMjfWD7wBILjqQbt530v576A/cAbQvEW9gGIpYMUs= @@ -332,7 +324,6 @@ github.com/cloudwego/base64x v0.1.4/go.mod h1:0zlkT4Wn5C6NdauXdJRhSKRlJvmclQ1hhJ github.com/cloudwego/iasm v0.2.0 h1:1KNIy1I1H9hNNFEEH3DVnI4UujN+1zjpuk6gwHLTssg= github.com/cloudwego/iasm v0.2.0/go.mod h1:8rXZaNYT2n95jn+zTI1sDr+IgcD2GVs0nlbbQPiEFhY= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= -github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cncf/xds/go v0.0.0-20240723142845-024c85f92f20 h1:N+3sFI5GUjRKBi+i0TxYVST9h4Ie192jJWpHvthBBgg= github.com/cncf/xds/go v0.0.0-20240723142845-024c85f92f20/go.mod h1:W+zGtBO5Y1IgJhy4+A9GOqVhqLpfZi+vwmdNXUehLA8= @@ -382,7 +373,6 @@ github.com/coreos/go-semver v0.3.1 h1:yi21YpKnrx1gt5R+la8n5WgS0kCrsPp33dmEyHReZr github.com/coreos/go-semver v0.3.1/go.mod h1:irMmmIw/7yzSRPWryHsK7EYSg09caPQL03VsM8rvUec= github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= -github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs= github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= @@ -489,9 +479,7 @@ github.com/emicklei/go-restful/v3 v3.12.1/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRr github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= -github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po= github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= -github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= github.com/envoyproxy/go-control-plane v0.13.0 h1:HzkeUz1Knt+3bK+8LG1bxOO/jzWZmdxpwC51i202les= github.com/envoyproxy/go-control-plane v0.13.0/go.mod h1:GRaKG3dwvFoTg4nj7aXdZnvMg4d7nvT/wl9WgVXn3Q8= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= @@ -550,8 +538,8 @@ github.com/gedex/inflector v0.0.0-20170307190818-16278e9db813/go.mod h1:P+oSoE9y github.com/getsentry/sentry-go v0.27.0 h1:Pv98CIbtB3LkMWmXi4Joa5OOcwbmnX88sF5qbK3r3Ps= github.com/getsentry/sentry-go v0.27.0/go.mod h1:lc76E2QywIyW8WuBnwl8Lc4bkmQH4+w1gwTf25trprY= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= -github.com/gin-contrib/cors v1.7.2 h1:oLDHxdg8W/XDoN/8zamqk/Drgt4oVZDvaV0YmvVICQw= -github.com/gin-contrib/cors v1.7.2/go.mod h1:SUJVARKgQ40dmrzgXEVxj2m7Ig1v1qIboQkPDTQ9t2E= +github.com/gin-contrib/cors v1.5.0 h1:DgGKV7DDoOn36DFkNtbHrjoRiT5ExCe+PC9/xp7aKvk= +github.com/gin-contrib/cors v1.5.0/go.mod h1:TvU7MAZ3EwrPLI2ztzTt3tqgvBCq+wn8WpZmfADjupI= github.com/gin-contrib/expvar v0.0.1 h1:IuU5ArEgihz50vG8Onrwz22kJr7Mcvgv9xSSpfU5g+w= github.com/gin-contrib/expvar v0.0.1/go.mod h1:8o2CznfQi1JjktORdHr2/abg3wSV6OCnXh0yGypvvVw= github.com/gin-contrib/sessions v0.0.5 h1:CATtfHmLMQrMNpJRgzjWXD7worTh7g7ritsQfmF+0jE= @@ -640,8 +628,8 @@ github.com/go-webauthn/x v0.1.5 h1:V2TCzDU2TGLd0kSZOXdrqDVV5JB9ILnKxA9S53CSBw0= github.com/go-webauthn/x v0.1.5/go.mod h1:qbzWwcFcv4rTwtCLOZd+icnr6B7oSsAGZJqlt8cukqY= github.com/go-zookeeper/zk v1.0.3 h1:7M2kwOsc//9VeeFiPtf+uSJlVpU66x9Ba5+8XK7/TDg= github.com/go-zookeeper/zk v1.0.3/go.mod h1:nOB03cncLtlp4t+UAkGSV+9beXP/akpekBwL+UX1Qcw= -github.com/goccy/go-json v0.10.3 h1:KZ5WoDbxAIgm2HNbYckL0se1fHD6rz5j4ywS6ebzDqA= -github.com/goccy/go-json v0.10.3/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M= +github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU= +github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= github.com/goccy/go-yaml v1.12.0 h1:/1WHjnMsI1dlIBQutrvSMGZRQufVO3asrHfTwfACoPM= github.com/goccy/go-yaml v1.12.0/go.mod h1:wKnAMd44+9JAAnGQpWVEgBzGt3YuTaQ4uXoHvE4m7WU= github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2 h1:ZpnhV/YsD2/4cESfV5+Hoeu/iUR3ruzNvZ+yQfO03a0= @@ -677,7 +665,6 @@ github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= -github.com/golang/mock v1.5.0/go.mod h1:CWnOUgYIOo4TcNZ0wHX3YZCqsaM1I1Jvs6v3mP3KVu8= github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc= github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= @@ -709,8 +696,6 @@ github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Z github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.1.2 h1:xf4v41cLI2Z6FxbKm+8Bu+m8ifhj15JuZ9sa0jZCMUU= github.com/google/btree v1.1.2/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4= -github.com/google/flatbuffers v24.3.25+incompatible h1:CX395cjN9Kke9mmalRoL3d81AtFUxJM+yDthflgJGkI= -github.com/google/flatbuffers v24.3.25+incompatible/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8= github.com/google/gnostic-models v0.6.9-0.20230804172637-c7be7c783f49 h1:0VpGH+cDhbDtdcweoyCVsF3fhN8kejK6rFe/2FFX2nU= github.com/google/gnostic-models v0.6.9-0.20230804172637-c7be7c783f49/go.mod h1:BkkQ4L1KS1xMt2aWSPStnn55ChGC0DPOn2FQYj+f25M= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= @@ -740,7 +725,6 @@ github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= -github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= github.com/google/orderedcode v0.0.1 h1:UzfcAexk9Vhv8+9pNOgRu41f16lHq725vPwnSeiG/Us= github.com/google/orderedcode v0.0.1/go.mod h1:iVyU4/qPKHY5h/wSd6rZZCDcLJNxiWO6dvsYES2Sb20= github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= @@ -750,10 +734,6 @@ github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hf github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20240827171923-fa2c70bbbfe5 h1:5iH8iuqE5apketRbSFBy+X1V0o+l+8NF1avt4HWl7cA= github.com/google/pprof v0.0.0-20240827171923-fa2c70bbbfe5/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144= @@ -777,7 +757,6 @@ github.com/googleapis/gax-go/v2 v2.13.0/go.mod h1:Z/fvTZXF8/uw7Xu5GuslPw+bplx6SS github.com/gophercloud/gophercloud v1.13.0 h1:8iY9d1DAbzMW6Vok1AxbbK5ZaUjzMp0tdyt4fX9IeJ0= github.com/gophercloud/gophercloud v1.13.0/go.mod h1:aAVqcocTSXh2vYFZ1JTvx4EQmfgzxRcNupUfxZbBNDM= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= -github.com/gopherjs/gopherjs v1.17.2/go.mod h1:pRRIvn/QzFLrKfvEz3qUuEhtE/zLCWfreZ6J5gM2i+k= github.com/gorilla/context v1.1.1 h1:AWwleXJkX/nhcU9bZSnZoi3h/qGYqQAGhq6zZe/aQW8= github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= github.com/gorilla/handlers v1.5.1 h1:9lRY6j8DEeeBT10CvO9hGW0gmky0BprnvDI5vfhUHH4= @@ -1036,18 +1015,17 @@ github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+o github.com/klauspost/compress v1.11.4/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= github.com/klauspost/compress v1.12.3/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg= github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= -github.com/klauspost/compress v1.17.11 h1:In6xLpyWOi1+C7tXUUWv2ot1QvBjxevKAaI6IXrJmUc= -github.com/klauspost/compress v1.17.11/go.mod h1:pMDklpSncoRMuLFrf1W9Ss9KT+0rH90U12bZKk7uwG0= +github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA= +github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= -github.com/klauspost/cpuid/v2 v2.2.8 h1:+StwCXwm9PdpiEkPyzBXIy+M9KUb4ODm0Zarf1kS5BM= -github.com/klauspost/cpuid/v2 v2.2.8/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws= +github.com/klauspost/cpuid/v2 v2.2.7 h1:ZWSB3igEs+d0qvnxR/ZBzXVmxkgt8DdzP6m9pfuVLDM= +github.com/klauspost/cpuid/v2 v2.2.7/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws= github.com/knz/go-libedit v1.10.1/go.mod h1:MZTVkCWyz0oBc7JOWP3wNAzd002ZbM/5hgShxwh4x8M= github.com/kolo/xmlrpc v0.0.0-20220921171641-a4b6fa1dd06b h1:udzkj9S/zlT5X367kqJis0QP7YMxobob6zhzq6Yre00= github.com/kolo/xmlrpc v0.0.0-20220921171641-a4b6fa1dd06b/go.mod h1:pcaDhQK0/NJZEvtCO0qQPPropqV0sJOJ6YW7X+9kRwM= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= @@ -1060,8 +1038,8 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= -github.com/leanovate/gopter v0.2.11 h1:vRjThO1EKPb/1NsDXuDrzldR28RLkBflWYcU9CvzWu4= -github.com/leanovate/gopter v0.2.11/go.mod h1:aK3tzZP/C+p1m3SPRE4SYZFGP7jjkuSI4f7Xvpt0S9c= +github.com/leanovate/gopter v0.2.10-0.20210127095200-9abe2343507a h1:dHCfT5W7gghzPtfsW488uPmEOm85wewI+ypUwibyTdU= +github.com/leanovate/gopter v0.2.10-0.20210127095200-9abe2343507a/go.mod h1:U2L/78B+KVFIx2VmW6onHJQzXtFb+p5y3y2Sh+Jxxv8= github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ= github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI= github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= @@ -1086,7 +1064,6 @@ github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I= github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= -github.com/magiconair/properties v1.8.5/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= @@ -1095,8 +1072,6 @@ github.com/manifoldco/promptui v0.9.0 h1:3V4HzJk1TtXW1MTZMP7mdlwbBpIinw3HztaIlYt github.com/manifoldco/promptui v0.9.0/go.mod h1:ka04sppxSGFAtxX0qhlYQjISsg9mR4GWtQEhdbn6Pgg= github.com/manyminds/api2go v0.0.0-20171030193247-e7b693844a6f h1:tVvGiZQFjOXP+9YyGqSA6jE55x1XVxmoPYudncxrZ8U= github.com/manyminds/api2go v0.0.0-20171030193247-e7b693844a6f/go.mod h1:Z60vy0EZVSu0bOugCHdcN5ZxFMKSpjRgsnh0XKPFqqk= -github.com/marcboeker/go-duckdb v1.8.3 h1:ZkYwiIZhbYsT6MmJsZ3UPTHrTZccDdM4ztoqSlEMXiQ= -github.com/marcboeker/go-duckdb v1.8.3/go.mod h1:C9bYRE1dPYb1hhfu/SSomm78B0FXmNgRvv6YBW/Hooc= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ= github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= @@ -1204,8 +1179,6 @@ github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f h1:KUppIJq7/+ github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f h1:y5//uYreIhSUg3J1GEMiLbxo1LJaP8RfCpH6pymGZus= github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw= -github.com/neelance/astrewrite v0.0.0-20160511093645-99348263ae86/go.mod h1:kHJEU3ofeGjhHklVoIGuVj85JJwZ6kWPaJwCIxgnFmo= -github.com/neelance/sourcemap v0.0.0-20200213170602-2833bce08e4c/go.mod h1:Qr6/a/Q4r9LP1IltGz7tA7iOK1WonHEYhu1HRBA7ZiM= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= github.com/nkovacs/streamquote v0.0.0-20170412213628-49af9bddb229/go.mod h1:0aYXnNPJ8l7uZxf45rWW1a/uME32OF0rhiYGNQ2oF2E= github.com/nsf/jsondiff v0.0.0-20230430225905-43f6cf3098c1 h1:dOYG7LS/WK00RWZc8XGgcUTlTxpp3mKhdR2Q9z9HbXM= @@ -1225,8 +1198,8 @@ github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vv github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU= github.com/onsi/ginkgo/v2 v2.1.3/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c= -github.com/onsi/ginkgo/v2 v2.20.1 h1:YlVIbqct+ZmnEph770q9Q7NVAz4wwIiVNahee6JyUzo= -github.com/onsi/ginkgo/v2 v2.20.1/go.mod h1:lG9ey2Z29hR41WMVthyJBGUBcBhGOtoPF2VFMvBXFCI= +github.com/onsi/ginkgo/v2 v2.19.0 h1:9Cnnf7UHo57Hy3k6/m5k3dRfGTMXGvxhHFvkDTCTpvA= +github.com/onsi/ginkgo/v2 v2.19.0/go.mod h1:rlwLi9PilAFJ8jCg9UE1QP6VBpd6/xj3SRC0d6TU0To= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= @@ -1258,7 +1231,6 @@ github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTK github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58 h1:onHthvaw9LFnH4t2DcNVpwGmV9E1BkGknEliJkfwQj0= github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58/go.mod h1:DXv8WO4yhMYhSNPKjeNKa5WY9YCIEBRbNzFFPJbWO6Y= github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= -github.com/pelletier/go-toml v1.9.3/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8= github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= github.com/pelletier/go-toml/v2 v2.2.3 h1:YmeHyLY8mFWbdkNWwpr+qIL2bEqT0o95WSdkNHvL12M= @@ -1268,8 +1240,8 @@ github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR github.com/petermattis/goid v0.0.0-20180202154549-b0b1615b78e5/go.mod h1:jvVRKCrJTQWu0XVbaOlby/2lO20uSCHEMzzplHXte1o= github.com/petermattis/goid v0.0.0-20230317030725-371a4b8eda08 h1:hDSdbBuw3Lefr6R18ax0tZ2BJeNB3NehB3trOwYBsdU= github.com/petermattis/goid v0.0.0-20230317030725-371a4b8eda08/go.mod h1:pxMtw7cyUw6B2bRH0ZBANSPg+AoSud1I1iyJHI69jH4= -github.com/pierrec/lz4/v4 v4.1.21 h1:yOVMLb6qSIDP67pl/5F7RepeKYu/VmTyEXvuMI5d9mQ= -github.com/pierrec/lz4/v4 v4.1.21/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= +github.com/pierrec/lz4/v4 v4.1.18 h1:xaKrnTkyoqfh1YItXl56+6KJNVYWlEEPuAQW9xsplYQ= +github.com/pierrec/lz4/v4 v4.1.18/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= github.com/pingcap/errors v0.11.4 h1:lFuQV/oaUMGcD2tqt+01ROSmJs75VG1ToEOkZIZ4nE4= github.com/pingcap/errors v0.11.4/go.mod h1:Oi8TUi2kEtXXLMJk9l1cGmz20kV3TaQ0usTwv5KuLY8= github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c h1:+mdjkGKdHQG3305AYmdv1U2eRNDiU2ErMBj1gwrq8eQ= @@ -1279,7 +1251,6 @@ github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI= github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10 h1:GFCKgmp0tecUJ0sJuv4pzYCqS9+RGSn52M3FUwPs+uo= github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10/go.mod h1:t/avpk3KcrXxUnYOhZhMXJlSEyie6gQbtLq5NM3loB8= github.com/pmezard/go-difflib v0.0.0-20151028094244-d8ed2627bdf0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= @@ -1347,8 +1318,8 @@ github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6So github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= -github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII= -github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o= +github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= +github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= github.com/rs/cors v1.10.1 h1:L0uuZVXIKlI1SShY2nhFfo44TYvDPQ1w4oFkUJNfhyo= github.com/rs/cors v1.10.1/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU= github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ= @@ -1398,41 +1369,37 @@ github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFR github.com/shopspring/decimal v1.3.1/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= github.com/shopspring/decimal v1.4.0 h1:bxl37RwXBklmTi0C79JfXCEBD1cqqHt0bbgBAGFp81k= github.com/shopspring/decimal v1.4.0/go.mod h1:gawqmDU56v4yIKSwfBSFip1HdCCXN8/+DMd9qYNcwME= -github.com/shurcooL/go v0.0.0-20200502201357-93f07166e636/go.mod h1:TDJrrUr11Vxrven61rcy3hJMUqaf/CLWYhHNPmT14Lk= -github.com/shurcooL/httpfs v0.0.0-20190707220628-8d4bc4ba7749/go.mod h1:ZY1cvUeJuFPAdZ/B6v7RHavJWZn2YPVFQ1OSXhCGOkg= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= -github.com/shurcooL/vfsgen v0.0.0-20200824052919-0d455de96546/go.mod h1:TrYk7fJVaAttu97ZZKrO9UbRa8izdowaMIZcxYMbVaw= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= -github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= -github.com/smartcontractkit/ccip-owner-contracts v0.0.0-salt-fix h1:DPJD++yKLSx0EfT+U14P8vLVxjXFmoIETiCO9lVwQo8= -github.com/smartcontractkit/ccip-owner-contracts v0.0.0-salt-fix/go.mod h1:NnT6w4Kj42OFFXhSx99LvJZWPpMjmo4+CpDEWfw61xY= -github.com/smartcontractkit/chain-selectors v1.0.34 h1:MJ17OGu8+jjl426pcKrJkCf3fePb3eCreuAnUA3RBj4= -github.com/smartcontractkit/chain-selectors v1.0.34/go.mod h1:xsKM0aN3YGcQKTPRPDDtPx2l4mlTN1Djmg0VVXV40b8= +github.com/smartcontractkit/ccip-owner-contracts v0.0.0-20240926212305-a6deabdfce86 h1:qQH6fZZe31nBAG6INHph3z5ysDTPptyu0TR9uoJ1+ok= +github.com/smartcontractkit/ccip-owner-contracts v0.0.0-20240926212305-a6deabdfce86/go.mod h1:WtWOoVQQEHxRHL2hNmuRrvDfYfQG/CioFNoa9Rr2mBE= +github.com/smartcontractkit/chain-selectors v1.0.29 h1:aZ9+OoUSMn4nqnissHtDvDoKR7JONfDqTHX3MHYIUIE= +github.com/smartcontractkit/chain-selectors v1.0.29/go.mod h1:xsKM0aN3YGcQKTPRPDDtPx2l4mlTN1Djmg0VVXV40b8= github.com/smartcontractkit/chainlink-automation v0.8.1 h1:sTc9LKpBvcKPc1JDYAmgBc2xpDKBco/Q4h4ydl6+UUU= github.com/smartcontractkit/chainlink-automation v0.8.1/go.mod h1:Iij36PvWZ6blrdC5A/nrQUBuf3MH3JvsBB9sSyc9W08= -github.com/smartcontractkit/chainlink-ccip v0.0.0-20241218114855-f74219171000 h1:6Zzr/R1j6P7bbvcUlt5WUIbItvrrGdGzIsiAzQezcwo= -github.com/smartcontractkit/chainlink-ccip v0.0.0-20241218114855-f74219171000/go.mod h1:ncjd6mPZSRlelEqH/2KeLE1pU3UlqzBSn8RYkEoECzY= -github.com/smartcontractkit/chainlink-common v0.4.1-0.20241217120918-bbe318cd0760 h1:lB5A3TP0zOVuu1n0kEm6d8/o/4Knh6HLvsU/GChk+sI= -github.com/smartcontractkit/chainlink-common v0.4.1-0.20241217120918-bbe318cd0760/go.mod h1:yti7e1+G9hhkYhj+L5sVUULn9Bn3bBL5/AxaNqdJ5YQ= -github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241202195413-82468150ac1e h1:PRoeby6ZlTuTkv2f+7tVU4+zboTfRzI+beECynF4JQ0= -github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241202195413-82468150ac1e/go.mod h1:mUh5/woemsVaHgTorA080hrYmO3syBCmPdnWc/5dOqk= -github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20241216163550-fa030d178ba3 h1:aeiBdBHGY8QNftps+VqrIk6OnfeeOD5z4jrAabW4ZSc= -github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20241216163550-fa030d178ba3/go.mod h1:AS6zY2BkcRwfiGzNabGbHhfrLSrXrcI/GmjnT4jQ5/s= +github.com/smartcontractkit/chainlink-ccip v0.0.0-20241118091009-43c2b4804cec h1:5vS1k8Qn09p8SQ3JzvS8iy4Pve7s3aVq+UPIdl74smY= +github.com/smartcontractkit/chainlink-ccip v0.0.0-20241118091009-43c2b4804cec/go.mod h1:4adKaHNaxFsRvV/lYfqtbsWyyvIPUMLR0FdOJN/ljis= +github.com/smartcontractkit/chainlink-common v0.3.1-0.20241114134822-aadff98ef068 h1:2llRW4Tn9W/EZp2XvXclQ9IjeTBwwxVPrrqaerX+vCE= +github.com/smartcontractkit/chainlink-common v0.3.1-0.20241114134822-aadff98ef068/go.mod h1:ny87uTW6hLjCTLiBqBRNFEhETSXhHWevYlPclT5lSco= +github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241017133723-5277829bd53f h1:BwrIaQIx5Iy6eT+DfLhFfK2XqjxRm74mVdlX8gbu4dw= +github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241017133723-5277829bd53f/go.mod h1:wHtwSR3F1CQSJJZDQKuqaqFYnvkT+kMyget7dl8Clvo= +github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20241018134907-a00ba3729b5e h1:JiETqdNM0bktAUGMc62COwXIaw3rR3M77Me6bBLG0Fg= +github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20241018134907-a00ba3729b5e/go.mod h1:iK3BNHKCLgSgkOyiu3iE7sfZ20Qnuk7xwjV/yO/6gnQ= github.com/smartcontractkit/chainlink-feeds v0.1.1 h1:JzvUOM/OgGQA1sOqTXXl52R6AnNt+Wg64sVG+XSA49c= github.com/smartcontractkit/chainlink-feeds v0.1.1/go.mod h1:55EZ94HlKCfAsUiKUTNI7QlE/3d3IwTlsU3YNa/nBb4= -github.com/smartcontractkit/chainlink-protos/job-distributor v0.6.0 h1:0ewLMbAz3rZrovdRUCgd028yOXX8KigB4FndAUdI2kM= -github.com/smartcontractkit/chainlink-protos/job-distributor v0.6.0/go.mod h1:/dVVLXrsp+V0AbcYGJo3XMzKg3CkELsweA/TTopCsKE= -github.com/smartcontractkit/chainlink-protos/orchestrator v0.4.0 h1:ZBat8EBvE2LpSQR9U1gEbRV6PfAkiFdINmQ8nVnXIAQ= -github.com/smartcontractkit/chainlink-protos/orchestrator v0.4.0/go.mod h1:m/A3lqD7ms/RsQ9BT5P2uceYY0QX5mIt4KQxT2G6qEo= -github.com/smartcontractkit/chainlink-solana v1.1.1-0.20241219173444-150f7443fdd3 h1:AIIiwrZ5T4nEjFT33aLZKoXwD63JSMu72wWe/rUdfm0= -github.com/smartcontractkit/chainlink-solana v1.1.1-0.20241219173444-150f7443fdd3/go.mod h1:ARILnIgKelP0YkVzxXO111S9j0b4uKyt7iLpYjOkCtU= -github.com/smartcontractkit/chainlink-starknet/relayer v0.1.1-0.20241202202529-2033490e77b8 h1:tNS7U9lrxkFvEuyxQv11HHOiV9LPDGC9wYEy+yM/Jv4= -github.com/smartcontractkit/chainlink-starknet/relayer v0.1.1-0.20241202202529-2033490e77b8/go.mod h1:EBrEgcdIbwepqguClkv8Ohy7CbyWSJaE4EC9aBJlQK0= +github.com/smartcontractkit/chainlink-protos/job-distributor v0.4.0 h1:1xTm8UGeDUAjvCXRh08+4xBRX33owH5MqC522JdelM0= +github.com/smartcontractkit/chainlink-protos/job-distributor v0.4.0/go.mod h1:/dVVLXrsp+V0AbcYGJo3XMzKg3CkELsweA/TTopCsKE= +github.com/smartcontractkit/chainlink-protos/orchestrator v0.3.0 h1:PBUaFfPLm+Efq7H9kdfGBivH+QhJ6vB5EZTR/sCZsxI= +github.com/smartcontractkit/chainlink-protos/orchestrator v0.3.0/go.mod h1:m/A3lqD7ms/RsQ9BT5P2uceYY0QX5mIt4KQxT2G6qEo= +github.com/smartcontractkit/chainlink-solana v1.1.1-0.20241115191142-8b8369c1f44e h1:XxTWJ9VIXK+XuAjP5131PqqBn0NEt5lBvnRAWRdqy8A= +github.com/smartcontractkit/chainlink-solana v1.1.1-0.20241115191142-8b8369c1f44e/go.mod h1:mGmRvlk54ufCufV4EBWizOGtXoXfePoFAuYEVC8EwdY= +github.com/smartcontractkit/chainlink-starknet/relayer v0.1.1-0.20241017135645-176a23722fd8 h1:B4DFdk6MGcQnoCjjMBCx7Z+GWQpxRWJ4O8W/dVJyWGA= +github.com/smartcontractkit/chainlink-starknet/relayer v0.1.1-0.20241017135645-176a23722fd8/go.mod h1:WkBqgBo+g34Gm5vWkDDl8Fh3Mzd7bF5hXp7rryg0t5o= github.com/smartcontractkit/chainlink-testing-framework/lib v1.50.13 h1:T0kbw07Vb6xUyA9MIJZfErMgWseWi1zf7cYvRpoq7ug= github.com/smartcontractkit/chainlink-testing-framework/lib v1.50.13/go.mod h1:1CKUOzoK+Ga19WuhRH9pxZ+qUUnrlIx108VEA6qSzeQ= github.com/smartcontractkit/chainlink-testing-framework/lib/grafana v1.50.0 h1:VIxK8u0Jd0Q/VuhmsNm6Bls6Tb31H/sA3A/rbc5hnhg= @@ -1449,12 +1416,10 @@ github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20241009055228- github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20241009055228-33d0c0bf38de/go.mod h1:Sl2MF/Fp3fgJIVzhdGhmZZX2BlnM0oUUyBP4s4xYb6o= github.com/smartcontractkit/tdh2/go/tdh2 v0.0.0-20241009055228-33d0c0bf38de h1:66VQxXx3lvTaAZrMBkIcdH9VEjujUEvmBQdnyOJnkOc= github.com/smartcontractkit/tdh2/go/tdh2 v0.0.0-20241009055228-33d0c0bf38de/go.mod h1:NSc7hgOQbXG3DAwkOdWnZzLTZENXSwDJ7Va1nBp0YU0= -github.com/smartcontractkit/wsrpc v0.8.3 h1:9tDf7Ut61g36RJIyxV9iI73SqoOMasKPfURV9oMLrPg= -github.com/smartcontractkit/wsrpc v0.8.3/go.mod h1:2u/wfnhl5R4RlSXseN4n6HHIWk8w1Am3AT6gWftQbNg= -github.com/smarty/assertions v1.15.0/go.mod h1:yABtdzeQs6l1brC900WlRNwj6ZR55d7B+E8C6HtKdec= +github.com/smartcontractkit/wsrpc v0.8.2 h1:XB/xcn/MMseHW+8JE8+a/rceA86ck7Ur6cEa9LiUC8M= +github.com/smartcontractkit/wsrpc v0.8.2/go.mod h1:2u/wfnhl5R4RlSXseN4n6HHIWk8w1Am3AT6gWftQbNg= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= -github.com/smartystreets/goconvey v1.8.1/go.mod h1:+/u4qLyY6x1jReYOp7GOM2FSt8aP9CzCZL03bI28W60= github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= github.com/soheilhy/cmux v0.1.5 h1:jjzc5WVemNEDTLwv9tlmemhC73tI08BNOIGwBOo10Js= github.com/soheilhy/cmux v0.1.5/go.mod h1:T7TcVDs9LWfQgPlPsdngu6I6QIoyIFZDDC6sNE1GqG0= @@ -1466,7 +1431,6 @@ github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasO github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI= github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= -github.com/spf13/afero v1.6.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I= github.com/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8= github.com/spf13/afero v1.11.0/go.mod h1:GH9Y3pIexgf1MTIWtNGyogA5MwRIDXGUr+hbWNoBjkY= github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= @@ -1475,18 +1439,15 @@ github.com/spf13/cast v1.6.0 h1:GEiTHELF+vaR5dhz3VqZfFSzZjYbgeKDpBxQVS4GYJ0= github.com/spf13/cast v1.6.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo= github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU= github.com/spf13/cobra v1.1.1/go.mod h1:WnodtKOvamDL/PwE2M4iKs8aMDBZ5Q5klgD3qfVJQMI= -github.com/spf13/cobra v1.2.1/go.mod h1:ExllRjgxM/piMAM+3tAZvg8fsklGAf3tPfi+i8t68Nk= github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM= github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y= github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= -github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= github.com/spf13/viper v1.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg= github.com/spf13/viper v1.7.1/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg= -github.com/spf13/viper v1.8.1/go.mod h1:o0Pch8wJ9BVSWGQMbra6iw0oQ5oktSIBaujf1rJH9Ns= github.com/spf13/viper v1.19.0 h1:RWq5SEjt8o25SROyN3z2OrDB9l7RPd3lwTWU8EcEdcI= github.com/spf13/viper v1.19.0/go.mod h1:GQUN9bilAbhU/jgc1bKs99f/suXKeUMct8Adx5+Ntkg= github.com/status-im/keycard-go v0.2.0 h1:QDLFswOQu1r5jsycloeQh3bVU8n/NatHHaZobtDnDzA= @@ -1595,8 +1556,6 @@ github.com/xlab/treeprint v1.2.0/go.mod h1:gj5Gd3gPdKtR1ikdDK6fnFLdmIS0X30kTTuNd github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 h1:gEOO8jv9F4OT7lGCjxCBTO/36wtF6j2nSip77qHd4x4= github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1/go.mod h1:Ohn+xnUBiLI6FVj/9LpzZWtj1/D6lUovWYBkxHVV3aM= -github.com/xyproto/randomstring v1.0.5 h1:YtlWPoRdgMu3NZtP45drfy1GKoojuR7hmRcnhZqKjWU= -github.com/xyproto/randomstring v1.0.5/go.mod h1:rgmS5DeNXLivK7YprL0pY+lTuhNQW3iGxZ18UQApw/E= github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d/go.mod h1:rHwXgn7JulP+udvsHwJoVG1YGAP6VLg4y9I5dyZdqmA= github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= @@ -1608,8 +1567,6 @@ github.com/yuin/gopher-lua v1.1.0 h1:BojcDhfyDWgU2f2TOzYK/g5p2gxMrku8oupLDqlnSqE github.com/yuin/gopher-lua v1.1.0/go.mod h1:GBR0iDaNXjAgGg9zfCvksxSRnQx76gclCIb7kdAd1Pw= github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo0= github.com/yusufpapurcu/wmi v1.2.4/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= -github.com/zeebo/xxh3 v1.0.2 h1:xZmwmqxHZA8AI603jOQ0tMqmBr9lPeFwGg6d+xy9DC0= -github.com/zeebo/xxh3 v1.0.2/go.mod h1:5NWz9Sef7zIDm2JHfFlcQvNekmcEl9ekUZQQKCYaDcA= github.com/zenazn/goji v0.9.0/go.mod h1:7S9M489iMyHBNxwZnk9/EHS098H4/F6TATF2mIxtB1Q= github.com/zondax/hid v0.9.2 h1:WCJFnEDMiqGF64nlZz28E9qLVZ0KSJ7xpc5DLEyma2U= github.com/zondax/hid v0.9.2/go.mod h1:l5wttcP0jwtdLjqjMMWFVEE7d1zO0jvSPA9OPZxWpEM= @@ -1627,13 +1584,10 @@ go.dedis.ch/protobuf v1.0.11/go.mod h1:97QR256dnkimeNdfmURz0wAMNVbd1VmLXhG1CrTYr go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.etcd.io/bbolt v1.3.9 h1:8x7aARPEXiXbHmtUwAIv7eV2fQFHrLLavdiJ3uzJXoI= go.etcd.io/bbolt v1.3.9/go.mod h1:zaO32+Ti0PK1ivdPtgMESzuzL2VPoIG1PCQNvOdo/dE= -go.etcd.io/etcd/api/v3 v3.5.0/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs= go.etcd.io/etcd/api/v3 v3.5.14 h1:vHObSCxyB9zlF60w7qzAdTcGaglbJOpSj1Xj9+WGxq0= go.etcd.io/etcd/api/v3 v3.5.14/go.mod h1:BmtWcRlQvwa1h3G2jvKYwIQy4PkHlDej5t7uLMUdJUU= -go.etcd.io/etcd/client/pkg/v3 v3.5.0/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g= go.etcd.io/etcd/client/pkg/v3 v3.5.14 h1:SaNH6Y+rVEdxfpA2Jr5wkEvN6Zykme5+YnbCkxvuWxQ= go.etcd.io/etcd/client/pkg/v3 v3.5.14/go.mod h1:8uMgAokyG1czCtIdsq+AGyYQMvpIKnSvPjFMunkgeZI= -go.etcd.io/etcd/client/v2 v2.305.0/go.mod h1:h9puh54ZTgAKtEbut2oe9P4L/oqKCVB6xsXlzd7alYQ= go.etcd.io/etcd/client/v3 v3.5.14 h1:CWfRs4FDaDoSz81giL7zPpZH2Z35tbOrAJkkjMqOupg= go.etcd.io/etcd/client/v3 v3.5.14/go.mod h1:k3XfdV/VIHy/97rqWjoUzrj9tk7GgJGH9J8L4dNXmAk= go.mongodb.org/mongo-driver v1.11.0/go.mod h1:s7p5vEtfbeR1gYi6pnj3c3/urpbLv2T5Sfd6Rp2HBB8= @@ -1646,7 +1600,6 @@ go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= -go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= go.opentelemetry.io/collector/pdata v1.12.0 h1:Xx5VK1p4VO0md8MWm2icwC1MnJ7f8EimKItMWw46BmA= @@ -1724,7 +1677,6 @@ go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= go.uber.org/zap v1.14.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= go.uber.org/zap v1.16.0/go.mod h1:MA8QOfq0BHJwdXa996Y4dYkAqRKB8/1K1QMMZVaNZjQ= -go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo= go.uber.org/zap v1.21.0/go.mod h1:wjWOCqI0f2ZZrJF/UufIOkiC8ii6tm1iqIsLo76RfJw= go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= @@ -1756,8 +1708,8 @@ golang.org/x/crypto v0.0.0-20220214200702-86341886e292/go.mod h1:IxCIyHEi3zRg3s0 golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.3.0/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4= golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc= -golang.org/x/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U= -golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk= +golang.org/x/crypto v0.28.0 h1:GBDwsMXVQi34v5CCYUm2jkJvu4cbtru2U4TN2PSyQnw= +golang.org/x/crypto v0.28.0/go.mod h1:rmgy+3RHxRZMyY0jjAJShp2zgEdOqj2AO7U0pYmeQ7U= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -1783,7 +1735,6 @@ golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRu golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= @@ -1792,12 +1743,9 @@ golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzB golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/mod v0.9.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.21.0 h1:vvrHzRwRfVKSiLrG+d4FMl/Qi4ukBCE6kZlTUkDYRT0= golang.org/x/mod v0.21.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -1837,11 +1785,8 @@ golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81R golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc= golang.org/x/net v0.0.0-20210331212208-0fccb6fa2b5c/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= @@ -1855,7 +1800,6 @@ golang.org/x/net v0.0.0-20220607020251-c690dde0001d/go.mod h1:XRhObCWvk6IyKnWLug golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= -golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/net v0.30.0 h1:AcW1SDZMkb8IpzCdQUaIq2sP4sZ4zw+55h6ynffypl4= golang.org/x/net v0.30.0/go.mod h1:2wGyMJ5iFasEhkwi13ChkO/t1ECNC4X4eBKkVFyYFlU= @@ -1864,13 +1808,6 @@ golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4Iltr golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210220000619-9bb904979d93/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210313182246-cd4f82c27b84/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210402161424-2e8d93401602/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.23.0 h1:PbgcYx2W7i4LvjJWEbf0ngHV6qJYr86PkAV3bXdLEbs= golang.org/x/oauth2 v0.23.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= @@ -1887,8 +1824,8 @@ golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ= -golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ= +golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -1939,23 +1876,17 @@ golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210303074136-134d130e1a04/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210305230114-8fe3ee5dd75b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210331175145-43e1dd70ce54/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -1982,8 +1913,8 @@ golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA= -golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo= +golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20201210144234-2321bbc49cbf/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= @@ -1991,11 +1922,10 @@ golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuX golang.org/x/term v0.0.0-20220526004731-065cf7ba2467/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= -golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU= -golang.org/x/term v0.27.0 h1:WP60Sv1nlK1T6SupCHbXzSaN0b9wUmsPoRS9b61A23Q= -golang.org/x/term v0.27.0/go.mod h1:iMsnZpn0cago0GOrHO2+Y7u7JPn5AylBrcoWkElMTSM= +golang.org/x/term v0.25.0 h1:WtHI/ltw4NvSUig5KARz9h521QvRC8RmF/cuYqifU24= +golang.org/x/term v0.25.0/go.mod h1:RPyXicDX+6vLxogjjRxjgD2TKtmAO6NZBsBRfrOLu7M= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -2007,11 +1937,10 @@ golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= -golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo= -golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ= +golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM= +golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -2068,19 +1997,12 @@ golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roY golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE= -golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= -golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= -golang.org/x/tools v0.7.0/go.mod h1:4pg6aUX35JBAogB10C9AtvVL+qowtN4pT3CGSQex14s= golang.org/x/tools v0.26.0 h1:v/60pFQmzmT9ExmjDv2gGIfi3OqfKoEP6I5+umXlbnQ= golang.org/x/tools v0.26.0/go.mod h1:TPVVj70c7JJ3WCazhD8OdXcZg/og+b9+tH/KxylGwH0= golang.org/x/xerrors v0.0.0-20190410155217-1f06c39b4373/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -2113,12 +2035,6 @@ google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0M google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM= google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc= -google.golang.org/api v0.35.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg= -google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34qYtE= -google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8= -google.golang.org/api v0.41.0/go.mod h1:RkxM5lITDfTzmyKFPt+wGrCJbVfniCr2ool8kTBzRTU= -google.golang.org/api v0.43.0/go.mod h1:nQsDGjRXMo4lvh5hP0TKqF244gqhGcr/YSIykhUk/94= -google.golang.org/api v0.44.0/go.mod h1:EBOGZqzyhtvMDoxwS97ctnh0zUmYY6CxqXsc1AvkYD8= google.golang.org/api v0.202.0 h1:y1iuVHMqokQbimW79ZqPZWo4CiyFu6HcCYHwSNyzlfo= google.golang.org/api v0.202.0/go.mod h1:3Jjeq7M/SFblTNCp7ES2xhq+WvGL0KeXI0joHQBfwTQ= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= @@ -2164,18 +2080,7 @@ google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7Fc google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210222152913-aa3ee6e6a81c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210303154014-9728d6b83eeb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210310155132-4ce2db91004e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210319143718-93e7006c17a6/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210401141331-865547bb08e2/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A= -google.golang.org/genproto v0.0.0-20210402141018-6c239bbf2bb1/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A= -google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= google.golang.org/genproto v0.0.0-20241021214115-324edc3d5d38 h1:Q3nlH8iSQSRUwOskjbcSMcF2jiYMNiQYZ0c2KEJLKKU= google.golang.org/genproto v0.0.0-20241021214115-324edc3d5d38/go.mod h1:xBI+tzfqGGN2JBeSebfKXFSdBpWVQ7sLW40PTupVRm4= google.golang.org/genproto/googleapis/api v0.0.0-20241021214115-324edc3d5d38 h1:2oV8dfuIkM1Ti7DwXc0BJfnwr9csz4TDXI9EmiI+Rbw= @@ -2197,14 +2102,9 @@ google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKa google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= -google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= -google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8= -google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= -google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= google.golang.org/grpc v1.36.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= -google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= google.golang.org/grpc v1.67.1 h1:zWnc1Vrcno+lHZCOofnIMvycFcc0QRGIzm9dhnDX68E= google.golang.org/grpc v1.67.1/go.mod h1:1gLDyUQU7CTLJI90u3nXZ9ekeghjeM7pTDZlqFNg2AA= google.golang.org/grpc/stats/opentelemetry v0.0.0-20241022174616-4bb0170ac65f h1:TsfHqsKI7qhOoYugDRyFDSKAuzegDVmkSCpjUyLkb+8= @@ -2240,7 +2140,6 @@ gopkg.in/inconshreveable/log15.v2 v2.0.0-20180818164646-67afb5ed74ec/go.mod h1:a gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= -gopkg.in/ini.v1 v1.62.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/natefinch/lumberjack.v2 v2.2.1 h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST95x9zc= diff --git a/deployment/helpers.go b/deployment/helpers.go index 34a2584a544..1f0dc3064d6 100644 --- a/deployment/helpers.go +++ b/deployment/helpers.go @@ -14,9 +14,7 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/crypto" - "github.com/ethereum/go-ethereum/rpc" "github.com/pkg/errors" - chain_selectors "github.com/smartcontractkit/chain-selectors" "github.com/smartcontractkit/chainlink-common/pkg/logger" ) @@ -88,7 +86,7 @@ func parseError(txError error) (string, error) { return callErr.Data, nil } -func parseErrorFromABI(errorString string, contractABI string) (string, error) { +func ParseErrorFromABI(errorString string, contractABI string) (string, error) { parsedAbi, err := abi.JSON(strings.NewReader(contractABI)) if err != nil { return "", errors.Wrap(err, "error loading ABI") @@ -113,30 +111,6 @@ func parseErrorFromABI(errorString string, contractABI string) (string, error) { return "", errors.New("error not found in ABI") } -// DecodeErr decodes an error from a contract call using the contract's ABI. -// If the error is not decodable, it returns the original error. -func DecodeErr(encodedABI string, err error) error { - if err == nil { - return nil - } - //revive:disable - var d rpc.DataError - ok := errors.As(err, &d) - if ok { - encErr, ok := d.ErrorData().(string) - if !ok { - return fmt.Errorf("error without error data: %s", d.Error()) - } - errStr, parseErr := parseErrorFromABI(encErr, encodedABI) - if parseErr != nil { - return fmt.Errorf("failed to decode error '%s' with abi: %w", encErr, parseErr) - } - return fmt.Errorf("contract error: %s", errStr) - - } - return fmt.Errorf("cannot decode error with abi: %w", err) -} - // ContractDeploy represents the result of an EVM contract deployment // via an abigen Go binding. It contains all the return values // as they are useful in different ways. @@ -163,46 +137,18 @@ func DeployContract[C any]( ) (*ContractDeploy[C], error) { contractDeploy := deploy(chain) if contractDeploy.Err != nil { - lggr.Errorw("Failed to deploy contract", "chain", chain.String(), "err", contractDeploy.Err) + lggr.Errorw("Failed to deploy contract", "err", contractDeploy.Err) return nil, contractDeploy.Err } _, err := chain.Confirm(contractDeploy.Tx) if err != nil { - lggr.Errorw("Failed to confirm deployment", "chain", chain.String(), "Contract", contractDeploy.Tv.String(), "err", err) + lggr.Errorw("Failed to confirm deployment", "err", err) return nil, err } - lggr.Infow("Deployed contract", "Contract", contractDeploy.Tv.String(), "addr", contractDeploy.Address, "chain", chain.String()) err = addressBook.Save(chain.Selector, contractDeploy.Address.String(), contractDeploy.Tv) if err != nil { - lggr.Errorw("Failed to save contract address", "Contract", contractDeploy.Tv.String(), "addr", contractDeploy.Address, "chain", chain.String(), "err", err) + lggr.Errorw("Failed to save contract address", "err", err) return nil, err } return &contractDeploy, nil } - -func IsValidChainSelector(cs uint64) error { - if cs == 0 { - return fmt.Errorf("chain selector must be set") - } - _, err := chain_selectors.GetSelectorFamily(cs) - if err != nil { - return err - } - return nil -} - -func ChainInfo(cs uint64) (chain_selectors.ChainDetails, error) { - id, err := chain_selectors.GetChainIDFromSelector(cs) - if err != nil { - return chain_selectors.ChainDetails{}, err - } - family, err := chain_selectors.GetSelectorFamily(cs) - if err != nil { - return chain_selectors.ChainDetails{}, err - } - info, err := chain_selectors.GetChainDetailsByChainIDAndFamily(id, family) - if err != nil { - return chain_selectors.ChainDetails{}, err - } - return info, nil -} diff --git a/deployment/keystone/changeset/internal/capability_definitions.go b/deployment/keystone/capability_definitions.go similarity index 93% rename from deployment/keystone/changeset/internal/capability_definitions.go rename to deployment/keystone/capability_definitions.go index 21c2b4fce01..61f129a939a 100644 --- a/deployment/keystone/changeset/internal/capability_definitions.go +++ b/deployment/keystone/capability_definitions.go @@ -1,6 +1,6 @@ -package internal +package keystone -import kcr "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry_1_1_0" +import kcr "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry" // TODO: KS-457 configuration management for capabilities from external sources var StreamTriggerCap = kcr.CapabilitiesRegistryCapability{ diff --git a/deployment/keystone/capability_management.go b/deployment/keystone/capability_management.go new file mode 100644 index 00000000000..4e15ea897ab --- /dev/null +++ b/deployment/keystone/capability_management.go @@ -0,0 +1,70 @@ +package keystone + +import ( + "fmt" + "strings" + + "github.com/smartcontractkit/chainlink-common/pkg/logger" + "github.com/smartcontractkit/chainlink/deployment" + kcr "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry" +) + +// AddCapabilities adds the capabilities to the registry +// it tries to add all capabilities in one go, if that fails, it falls back to adding them one by one +func AddCapabilities(lggr logger.Logger, registry *kcr.CapabilitiesRegistry, chain deployment.Chain, capabilities []kcr.CapabilitiesRegistryCapability) error { + if len(capabilities) == 0 { + return nil + } + // dedup capabilities + var deduped []kcr.CapabilitiesRegistryCapability + seen := make(map[string]struct{}) + for _, cap := range capabilities { + if _, ok := seen[CapabilityID(cap)]; !ok { + seen[CapabilityID(cap)] = struct{}{} + deduped = append(deduped, cap) + } + } + + tx, err := registry.AddCapabilities(chain.DeployerKey, deduped) + if err != nil { + err = DecodeErr(kcr.CapabilitiesRegistryABI, err) + // no typed errors in the abi, so we have to do string matching + // try to add all capabilities in one go, if that fails, fall back to 1-by-1 + if !strings.Contains(err.Error(), "CapabilityAlreadyExists") { + return fmt.Errorf("failed to call AddCapabilities: %w", err) + } + lggr.Warnw("capabilities already exist, falling back to 1-by-1", "capabilities", deduped) + for _, cap := range deduped { + tx, err = registry.AddCapabilities(chain.DeployerKey, []kcr.CapabilitiesRegistryCapability{cap}) + if err != nil { + err = DecodeErr(kcr.CapabilitiesRegistryABI, err) + if strings.Contains(err.Error(), "CapabilityAlreadyExists") { + lggr.Warnw("capability already exists, skipping", "capability", cap) + continue + } + return fmt.Errorf("failed to call AddCapabilities for capability %v: %w", cap, err) + } + // 1-by-1 tx is pending and we need to wait for it to be mined + _, err = chain.Confirm(tx) + if err != nil { + return fmt.Errorf("failed to confirm AddCapabilities confirm transaction %s: %w", tx.Hash().String(), err) + } + lggr.Debugw("registered capability", "capability", cap) + + } + } else { + // the bulk add tx is pending and we need to wait for it to be mined + _, err = chain.Confirm(tx) + if err != nil { + return fmt.Errorf("failed to confirm AddCapabilities confirm transaction %s: %w", tx.Hash().String(), err) + } + lggr.Info("registered capabilities", "capabilities", deduped) + } + return nil +} + +// CapabilityID returns a unique id for the capability +// TODO: mv to chainlink-common? ref https://github.com/smartcontractkit/chainlink/blob/4fb06b4525f03c169c121a68defa9b13677f5f20/contracts/src/v0.8/keystone/CapabilitiesRegistry.sol#L170 +func CapabilityID(c kcr.CapabilitiesRegistryCapability) string { + return fmt.Sprintf("%s@%s", c.LabelledName, c.Version) +} diff --git a/deployment/keystone/changeset/internal/capability_registry_deployer.go b/deployment/keystone/capability_registry_deployer.go similarity index 90% rename from deployment/keystone/changeset/internal/capability_registry_deployer.go rename to deployment/keystone/capability_registry_deployer.go index 492ba168c9d..efe1d23f11f 100644 --- a/deployment/keystone/changeset/internal/capability_registry_deployer.go +++ b/deployment/keystone/capability_registry_deployer.go @@ -1,4 +1,4 @@ -package internal +package keystone import ( "context" @@ -9,9 +9,8 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/smartcontractkit/chainlink-common/pkg/logger" - "github.com/smartcontractkit/chainlink/deployment" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry_1_1_0" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry" ) type CapabilitiesRegistryDeployer struct { @@ -19,12 +18,8 @@ type CapabilitiesRegistryDeployer struct { contract *capabilities_registry.CapabilitiesRegistry } -func NewCapabilitiesRegistryDeployer() (*CapabilitiesRegistryDeployer, error) { - lggr, err := logger.New() - if err != nil { - return nil, err - } - return &CapabilitiesRegistryDeployer{lggr: lggr}, nil +func NewCapabilitiesRegistryDeployer(lggr logger.Logger) *CapabilitiesRegistryDeployer { + return &CapabilitiesRegistryDeployer{lggr: lggr} } func (c *CapabilitiesRegistryDeployer) Contract() *capabilities_registry.CapabilitiesRegistry { diff --git a/deployment/keystone/changeset/accept_ownership.go b/deployment/keystone/changeset/accept_ownership.go deleted file mode 100644 index dd709523bc2..00000000000 --- a/deployment/keystone/changeset/accept_ownership.go +++ /dev/null @@ -1,49 +0,0 @@ -package changeset - -import ( - "time" - - "github.com/ethereum/go-ethereum/common" - - kslib "github.com/smartcontractkit/chainlink/deployment/keystone/changeset/internal" - - "github.com/smartcontractkit/chainlink/deployment" - "github.com/smartcontractkit/chainlink/deployment/common/changeset" -) - -type AcceptAllOwnershipRequest struct { - ChainSelector uint64 - MinDelay time.Duration -} - -var _ deployment.ChangeSet[*AcceptAllOwnershipRequest] = AcceptAllOwnershipsProposal - -// AcceptAllOwnershipsProposal creates a MCMS proposal to call accept ownership on all the Keystone contracts in the address book. -func AcceptAllOwnershipsProposal(e deployment.Environment, req *AcceptAllOwnershipRequest) (deployment.ChangesetOutput, error) { - chainSelector := req.ChainSelector - minDelay := req.MinDelay - chain := e.Chains[chainSelector] - addrBook := e.ExistingAddresses - - r, err := kslib.GetContractSets(e.Logger, &kslib.GetContractSetsRequest{ - Chains: map[uint64]deployment.Chain{ - req.ChainSelector: chain, - }, - AddressBook: addrBook, - }) - if err != nil { - return deployment.ChangesetOutput{}, err - } - contracts := r.ContractSets[chainSelector] - - // Construct the configuration - cfg := changeset.TransferToMCMSWithTimelockConfig{ - ContractsByChain: map[uint64][]common.Address{ - chainSelector: contracts.TransferableContracts(), - }, - MinDelay: minDelay, - } - - // Create and return the changeset - return changeset.TransferToMCMSWithTimelock(e, cfg) -} diff --git a/deployment/keystone/changeset/accept_ownership_test.go b/deployment/keystone/changeset/accept_ownership_test.go deleted file mode 100644 index 4007fde4f79..00000000000 --- a/deployment/keystone/changeset/accept_ownership_test.go +++ /dev/null @@ -1,72 +0,0 @@ -package changeset_test - -import ( - "testing" - - "github.com/stretchr/testify/require" - "go.uber.org/zap/zapcore" - - "github.com/smartcontractkit/chainlink-common/pkg/logger" - - commonchangeset "github.com/smartcontractkit/chainlink/deployment/common/changeset" - "github.com/smartcontractkit/chainlink/deployment/common/proposalutils" - "github.com/smartcontractkit/chainlink/deployment/common/types" - "github.com/smartcontractkit/chainlink/deployment/environment/memory" - "github.com/smartcontractkit/chainlink/deployment/keystone/changeset" -) - -func TestAcceptAllOwnership(t *testing.T) { - t.Parallel() - lggr := logger.Test(t) - cfg := memory.MemoryEnvironmentConfig{ - Nodes: 1, - Chains: 2, - } - env := memory.NewMemoryEnvironment(t, lggr, zapcore.DebugLevel, cfg) - registrySel := env.AllChainSelectors()[0] - env, err := commonchangeset.ApplyChangesets(t, env, nil, []commonchangeset.ChangesetApplication{ - { - Changeset: commonchangeset.WrapChangeSet(changeset.DeployCapabilityRegistry), - Config: registrySel, - }, - { - Changeset: commonchangeset.WrapChangeSet(changeset.DeployOCR3), - Config: registrySel, - }, - { - Changeset: commonchangeset.WrapChangeSet(changeset.DeployForwarder), - Config: changeset.DeployForwarderRequest{}, - }, - { - Changeset: commonchangeset.WrapChangeSet(changeset.DeployFeedsConsumer), - Config: &changeset.DeployFeedsConsumerRequest{ChainSelector: registrySel}, - }, - { - Changeset: commonchangeset.WrapChangeSet(commonchangeset.DeployMCMSWithTimelock), - Config: map[uint64]types.MCMSWithTimelockConfig{ - registrySel: proposalutils.SingleGroupTimelockConfig(t), - }, - }, - }) - require.NoError(t, err) - addrs, err := env.ExistingAddresses.AddressesForChain(registrySel) - require.NoError(t, err) - timelock, err := commonchangeset.MaybeLoadMCMSWithTimelockChainState(env.Chains[registrySel], addrs) - require.NoError(t, err) - - _, err = commonchangeset.ApplyChangesets(t, env, map[uint64]*proposalutils.TimelockExecutionContracts{ - registrySel: &proposalutils.TimelockExecutionContracts{ - Timelock: timelock.Timelock, - CallProxy: timelock.CallProxy, - }, - }, []commonchangeset.ChangesetApplication{ - { - Changeset: commonchangeset.WrapChangeSet(changeset.AcceptAllOwnershipsProposal), - Config: &changeset.AcceptAllOwnershipRequest{ - ChainSelector: registrySel, - MinDelay: 0, - }, - }, - }) - require.NoError(t, err) -} diff --git a/deployment/keystone/changeset/addrbook_utils.go b/deployment/keystone/changeset/addrbook_utils.go deleted file mode 100644 index fa4dd27ca18..00000000000 --- a/deployment/keystone/changeset/addrbook_utils.go +++ /dev/null @@ -1,113 +0,0 @@ -package changeset - -import ( - "fmt" - - "github.com/ethereum/go-ethereum/accounts/abi/bind" - "github.com/ethereum/go-ethereum/common" - ccipowner "github.com/smartcontractkit/ccip-owner-contracts/pkg/gethwrappers" - - "github.com/smartcontractkit/chainlink/deployment" - - "github.com/smartcontractkit/chainlink/deployment/keystone/changeset/internal" - capReg "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry_1_1_0" - feeds_consumer "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/feeds_consumer_1_0_0" - keystoneForwarder "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/forwarder_1_0_0" - ocr3Capability "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/ocr3_capability_1_0_0" -) - -// contractConstructor is a function type that takes an address and a client, -// returning the contract instance and an error. -type contractConstructor[T any] func(address common.Address, client bind.ContractBackend) (*T, error) - -// getContractsFromAddrBook retrieves a list of contract instances of a specified type from the address book. -// It uses the provided constructor to initialize matching contracts for the given chain. -func getContractsFromAddrBook[T any]( - addrBook deployment.AddressBook, - chain deployment.Chain, - desiredType deployment.ContractType, - constructor contractConstructor[T], -) ([]*T, error) { - chainAddresses, err := addrBook.AddressesForChain(chain.Selector) - if err != nil { - return nil, fmt.Errorf("failed to get addresses for chain %d: %w", chain.Selector, err) - } - - var contracts []*T - for addr, typeAndVersion := range chainAddresses { - if typeAndVersion.Type == desiredType { - address := common.HexToAddress(addr) - contractInstance, err := constructor(address, chain.Client) - if err != nil { - return nil, fmt.Errorf("failed to construct %s at %s: %w", desiredType, addr, err) - } - contracts = append(contracts, contractInstance) - } - } - - if len(contracts) == 0 { - return nil, fmt.Errorf("no %s found for chain %d", desiredType, chain.Selector) - } - - return contracts, nil -} - -// capRegistriesFromAddrBook retrieves CapabilitiesRegistry contracts for the given chain. -func capRegistriesFromAddrBook(addrBook deployment.AddressBook, chain deployment.Chain) ([]*capReg.CapabilitiesRegistry, error) { - return getContractsFromAddrBook[capReg.CapabilitiesRegistry]( - addrBook, - chain, - internal.CapabilitiesRegistry, - capReg.NewCapabilitiesRegistry, - ) -} - -// ocr3FromAddrBook retrieves OCR3Capability contracts for the given chain. -func ocr3FromAddrBook(addrBook deployment.AddressBook, chain deployment.Chain) ([]*ocr3Capability.OCR3Capability, error) { - return getContractsFromAddrBook[ocr3Capability.OCR3Capability]( - addrBook, - chain, - internal.OCR3Capability, - ocr3Capability.NewOCR3Capability, - ) -} - -// forwardersFromAddrBook retrieves KeystoneForwarder contracts for the given chain. -func forwardersFromAddrBook(addrBook deployment.AddressBook, chain deployment.Chain) ([]*keystoneForwarder.KeystoneForwarder, error) { - return getContractsFromAddrBook[keystoneForwarder.KeystoneForwarder]( - addrBook, - chain, - internal.KeystoneForwarder, - keystoneForwarder.NewKeystoneForwarder, - ) -} - -// feedsConsumersFromAddrBook retrieves FeedsConsumer contracts for the given chain. -func feedsConsumersFromAddrBook(addrBook deployment.AddressBook, chain deployment.Chain) ([]*feeds_consumer.KeystoneFeedsConsumer, error) { - return getContractsFromAddrBook[feeds_consumer.KeystoneFeedsConsumer]( - addrBook, - chain, - internal.FeedConsumer, - feeds_consumer.NewKeystoneFeedsConsumer, - ) -} - -// proposersFromAddrBook retrieves ManyChainMultiSig proposer contracts for the given chain. -func proposersFromAddrBook(addrBook deployment.AddressBook, chain deployment.Chain) ([]*ccipowner.ManyChainMultiSig, error) { - return getContractsFromAddrBook[ccipowner.ManyChainMultiSig]( - addrBook, - chain, - internal.ProposerManyChainMultiSig, - ccipowner.NewManyChainMultiSig, - ) -} - -// timelocksFromAddrBook retrieves RBACTimelock contracts for the given chain. -func timelocksFromAddrBook(addrBook deployment.AddressBook, chain deployment.Chain) ([]*ccipowner.RBACTimelock, error) { - return getContractsFromAddrBook[ccipowner.RBACTimelock]( - addrBook, - chain, - internal.RBACTimelock, - ccipowner.NewRBACTimelock, - ) -} diff --git a/deployment/keystone/changeset/append_node_capabilities_test.go b/deployment/keystone/changeset/append_node_capabilities_test.go deleted file mode 100644 index fb2c99ed15e..00000000000 --- a/deployment/keystone/changeset/append_node_capabilities_test.go +++ /dev/null @@ -1,134 +0,0 @@ -package changeset_test - -import ( - "testing" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - "golang.org/x/exp/maps" - - commonchangeset "github.com/smartcontractkit/chainlink/deployment/common/changeset" - "github.com/smartcontractkit/chainlink/deployment/common/proposalutils" - "github.com/smartcontractkit/chainlink/deployment/keystone/changeset" - "github.com/smartcontractkit/chainlink/deployment/keystone/changeset/test" - kcr "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry_1_1_0" - "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/p2pkey" -) - -func TestAppendNodeCapabilities(t *testing.T) { - t.Parallel() - - var ( - capA = kcr.CapabilitiesRegistryCapability{ - LabelledName: "capA", - Version: "0.4.2", - } - capB = kcr.CapabilitiesRegistryCapability{ - LabelledName: "capB", - Version: "3.16.0", - } - caps = []kcr.CapabilitiesRegistryCapability{capA, capB} - ) - t.Run("no mcms", func(t *testing.T) { - te := test.SetupTestEnv(t, test.TestConfig{ - WFDonConfig: test.DonConfig{N: 4}, - AssetDonConfig: test.DonConfig{N: 4}, - WriterDonConfig: test.DonConfig{N: 4}, - NumChains: 1, - }) - - newCapabilities := make(map[p2pkey.PeerID][]kcr.CapabilitiesRegistryCapability) - for id, _ := range te.WFNodes { - k, err := p2pkey.MakePeerID(id) - require.NoError(t, err) - newCapabilities[k] = caps - } - - t.Run("succeeds if existing capabilities not explicit", func(t *testing.T) { - cfg := changeset.AppendNodeCapabilitiesRequest{ - RegistryChainSel: te.RegistrySelector, - P2pToCapabilities: newCapabilities, - } - - csOut, err := changeset.AppendNodeCapabilities(te.Env, &cfg) - require.NoError(t, err) - require.Len(t, csOut.Proposals, 0) - require.Nil(t, csOut.AddressBook) - - validateCapabilityAppends(t, te, newCapabilities) - }) - }) - t.Run("with mcms", func(t *testing.T) { - te := test.SetupTestEnv(t, test.TestConfig{ - WFDonConfig: test.DonConfig{N: 4}, - AssetDonConfig: test.DonConfig{N: 4}, - WriterDonConfig: test.DonConfig{N: 4}, - NumChains: 1, - UseMCMS: true, - }) - - newCapabilities := make(map[p2pkey.PeerID][]kcr.CapabilitiesRegistryCapability) - for id, _ := range te.WFNodes { - k, err := p2pkey.MakePeerID(id) - require.NoError(t, err) - newCapabilities[k] = caps - } - - cfg := changeset.AppendNodeCapabilitiesRequest{ - RegistryChainSel: te.RegistrySelector, - P2pToCapabilities: newCapabilities, - MCMSConfig: &changeset.MCMSConfig{MinDuration: 0}, - } - - csOut, err := changeset.AppendNodeCapabilities(te.Env, &cfg) - require.NoError(t, err) - require.Len(t, csOut.Proposals, 1) - require.Len(t, csOut.Proposals[0].Transactions, 1) - require.Len(t, csOut.Proposals[0].Transactions[0].Batch, 2) // add capabilities, update nodes - require.Nil(t, csOut.AddressBook) - - // now apply the changeset such that the proposal is signed and execed - contracts := te.ContractSets()[te.RegistrySelector] - timelockContracts := map[uint64]*proposalutils.TimelockExecutionContracts{ - te.RegistrySelector: { - Timelock: contracts.Timelock, - CallProxy: contracts.CallProxy, - }, - } - - _, err = commonchangeset.ApplyChangesets(t, te.Env, timelockContracts, []commonchangeset.ChangesetApplication{ - { - Changeset: commonchangeset.WrapChangeSet(changeset.AppendNodeCapabilities), - Config: &cfg, - }, - }) - require.NoError(t, err) - validateCapabilityAppends(t, te, newCapabilities) - }) - -} - -// validateUpdate checks reads nodes from the registry and checks they have the expected updates -func validateCapabilityAppends(t *testing.T, te test.TestEnv, appended map[p2pkey.PeerID][]kcr.CapabilitiesRegistryCapability) { - registry := te.ContractSets()[te.RegistrySelector].CapabilitiesRegistry - wfP2PIDs := p2pIDs(t, maps.Keys(te.WFNodes)) - nodes, err := registry.GetNodesByP2PIds(nil, wfP2PIDs) - require.NoError(t, err) - require.Len(t, nodes, len(wfP2PIDs)) - for _, node := range nodes { - want := appended[node.P2pId] - require.NotNil(t, want) - assertContainsCapabilities(t, registry, want, node) - } -} - -func assertContainsCapabilities(t *testing.T, registry *kcr.CapabilitiesRegistry, want []kcr.CapabilitiesRegistryCapability, got kcr.INodeInfoProviderNodeInfo) { - wantHashes := make([][32]byte, len(want)) - for i, c := range want { - h, err := registry.GetHashedCapabilityId(nil, c.LabelledName, c.Version) - require.NoError(t, err) - wantHashes[i] = h - assert.Contains(t, got.HashedCapabilityIds, h, "missing capability %v", c) - } - assert.LessOrEqual(t, len(want), len(got.HashedCapabilityIds)) -} diff --git a/deployment/keystone/changeset/append_node_capabilities.go b/deployment/keystone/changeset/append_node_capbilities.go similarity index 55% rename from deployment/keystone/changeset/append_node_capabilities.go rename to deployment/keystone/changeset/append_node_capbilities.go index d558cf39c95..974c4970c51 100644 --- a/deployment/keystone/changeset/append_node_capabilities.go +++ b/deployment/keystone/changeset/append_node_capbilities.go @@ -3,11 +3,8 @@ package changeset import ( "fmt" - "github.com/ethereum/go-ethereum/common" - "github.com/smartcontractkit/ccip-owner-contracts/pkg/gethwrappers" - "github.com/smartcontractkit/ccip-owner-contracts/pkg/proposal/timelock" "github.com/smartcontractkit/chainlink/deployment" - "github.com/smartcontractkit/chainlink/deployment/common/proposalutils" + kslib "github.com/smartcontractkit/chainlink/deployment/keystone" "github.com/smartcontractkit/chainlink/deployment/keystone/changeset/internal" ) @@ -19,39 +16,15 @@ type AppendNodeCapabilitiesRequest = MutateNodeCapabilitiesRequest // AppendNodeCapabilities adds any new capabilities to the registry, merges the new capabilities with the existing capabilities // of the node, and updates the nodes in the registry host the union of the new and existing capabilities. func AppendNodeCapabilities(env deployment.Environment, req *AppendNodeCapabilitiesRequest) (deployment.ChangesetOutput, error) { - c, err := req.convert(env) + cfg, err := req.convert(env) if err != nil { return deployment.ChangesetOutput{}, err } - r, err := internal.AppendNodeCapabilitiesImpl(env.Logger, c) + _, err = internal.AppendNodeCapabilitiesImpl(env.Logger, cfg) if err != nil { return deployment.ChangesetOutput{}, err } - out := deployment.ChangesetOutput{} - if req.UseMCMS() { - if r.Ops == nil { - return out, fmt.Errorf("expected MCMS operation to be non-nil") - } - timelocksPerChain := map[uint64]common.Address{ - c.Chain.Selector: c.ContractSet.Timelock.Address(), - } - proposerMCMSes := map[uint64]*gethwrappers.ManyChainMultiSig{ - c.Chain.Selector: c.ContractSet.ProposerMcm, - } - - proposal, err := proposalutils.BuildProposalFromBatches( - timelocksPerChain, - proposerMCMSes, - []timelock.BatchChainOperation{*r.Ops}, - "proposal to set update node capabilities", - req.MCMSConfig.MinDuration, - ) - if err != nil { - return out, fmt.Errorf("failed to build proposal: %w", err) - } - out.Proposals = []timelock.MCMSWithTimelockProposal{*proposal} - } - return out, nil + return deployment.ChangesetOutput{}, nil } func (req *AppendNodeCapabilitiesRequest) convert(e deployment.Environment) (*internal.AppendNodeCapabilitiesRequest, error) { @@ -62,19 +35,21 @@ func (req *AppendNodeCapabilitiesRequest) convert(e deployment.Environment) (*in if !ok { return nil, fmt.Errorf("registry chain selector %d does not exist in environment", req.RegistryChainSel) } - resp, err := internal.GetContractSets(e.Logger, &internal.GetContractSetsRequest{ + contracts, err := kslib.GetContractSets(e.Logger, &kslib.GetContractSetsRequest{ Chains: map[uint64]deployment.Chain{req.RegistryChainSel: registryChain}, - AddressBook: e.ExistingAddresses, + AddressBook: req.AddressBook, }) if err != nil { return nil, fmt.Errorf("failed to get contract sets: %w", err) } - contracts := resp.ContractSets[req.RegistryChainSel] + registry := contracts.ContractSets[req.RegistryChainSel].CapabilitiesRegistry + if registry == nil { + return nil, fmt.Errorf("capabilities registry not found for chain %d", req.RegistryChainSel) + } return &internal.AppendNodeCapabilitiesRequest{ Chain: registryChain, - ContractSet: &contracts, + Registry: registry, P2pToCapabilities: req.P2pToCapabilities, - UseMCMS: req.UseMCMS(), }, nil } diff --git a/deployment/keystone/changeset/compatiblity.go b/deployment/keystone/changeset/compatiblity.go deleted file mode 100644 index 7f80b6ab53d..00000000000 --- a/deployment/keystone/changeset/compatiblity.go +++ /dev/null @@ -1,95 +0,0 @@ -package changeset - -import "github.com/smartcontractkit/chainlink/deployment/keystone/changeset/internal" - -//TODO: KS-673 refactor internal package to reduce and remove the duplication - -// OracleConfig is the configuration for an oracle -type OracleConfig = internal.OracleConfig - -// OCR3OnchainConfig is the onchain configuration of an OCR2 contract -type OCR3OnchainConfig = internal.OCR2OracleConfig - -// NodeKeys is a set of public keys for a node -type NodeKeys = internal.NodeKeys - -// TopLevelConfigSource is the top level configuration source -type TopLevelConfigSource = internal.TopLevelConfigSource - -// GenerateOCR3Config generates an OCR3 config -var GenerateOCR3Config = internal.GenerateOCR3Config - -// FeedConsumer is a feed consumer contract type -var FeedConsumer = internal.FeedConsumer - -// KeystoneForwarder is a keystone forwarder contract type -var KeystoneForwarder = internal.KeystoneForwarder - -// GetContractSetsRequest is a request to get contract sets -type GetContractSetsRequest = internal.GetContractSetsRequest - -// GetContractSetsResponse is a response to get contract sets -type GetContractSetsResponse = internal.GetContractSetsResponse - -// GetContractSets gets contract sets -var GetContractSets = internal.GetContractSets - -// RegisterCapabilitiesRequest is a request to register capabilities -type RegisterCapabilitiesRequest = internal.RegisterCapabilitiesRequest - -// RegisterCapabilitiesResponse is a response to register capabilities -type RegisterCapabilitiesResponse = internal.RegisterCapabilitiesResponse - -// RegisterCapabilities registers capabilities -var RegisterCapabilities = internal.RegisterCapabilities - -// RegisterNOPSRequest is a request to register NOPS -type RegisterNOPSRequest = internal.RegisterNOPSRequest - -// RegisterNOPSResponse is a response to register NOPS -type RegisterNOPSResponse = internal.RegisterNOPSResponse - -// RegisterNOPS registers NOPS -var RegisterNOPS = internal.RegisterNOPS - -// RegisterNodesRequest is a request to register nodes with the capabilities registry -type RegisterNodesRequest = internal.RegisterNodesRequest - -// RegisterNodesResponse is a response to register nodes with the capabilities registry -type RegisterNodesResponse = internal.RegisterNodesResponse - -// RegisterNodes registers nodes with the capabilities registry -var RegisterNodes = internal.RegisterNodes - -// RegisteredCapability is a wrapper of a capability and its ID -type RegisteredCapability = internal.RegisteredCapability - -// FromCapabilitiesRegistryCapability converts a capabilities registry capability to a registered capability -var FromCapabilitiesRegistryCapability = internal.FromCapabilitiesRegistryCapability - -// RegisterDonsRequest is a request to register Dons with the capabilities registry -type RegisterDonsRequest = internal.RegisterDonsRequest - -// RegisterDonsResponse is a response to register Dons with the capabilities registry -type RegisterDonsResponse = internal.RegisterDonsResponse - -// RegisterDons registers Dons with the capabilities registry -var RegisterDons = internal.RegisterDons - -// DONToRegister is the minimal information needed to register a DON with the capabilities registry -type DONToRegister = internal.DONToRegister - -// ConfigureContractsRequest is a request to configure ALL the contracts -type ConfigureContractsRequest = internal.ConfigureContractsRequest - -// ConfigureContractsResponse is a response to configure ALL the contracts -type ConfigureContractsResponse = internal.ConfigureContractsResponse - -// DonCapabilities is a set of capabilities hosted by a set of node operators -// in is in a convenient form to handle the CLO representation of the nop data -type DonCapabilities = internal.DonCapabilities - -type DeployRequest = internal.DeployRequest -type DeployResponse = internal.DeployResponse - -type ContractSet = internal.ContractSet diff --git a/deployment/keystone/changeset/configure_contracts.go b/deployment/keystone/changeset/configure_contracts.go index b57ebb0ed52..d5bcb32243b 100644 --- a/deployment/keystone/changeset/configure_contracts.go +++ b/deployment/keystone/changeset/configure_contracts.go @@ -5,30 +5,10 @@ import ( "fmt" "github.com/smartcontractkit/chainlink-common/pkg/logger" - "github.com/smartcontractkit/chainlink/deployment" - kslib "github.com/smartcontractkit/chainlink/deployment/keystone/changeset/internal" + kslib "github.com/smartcontractkit/chainlink/deployment/keystone" ) -var _ deployment.ChangeSet[InitialContractsCfg] = ConfigureInitialContractsChangeset - -type InitialContractsCfg struct { - RegistryChainSel uint64 - Dons []kslib.DonCapabilities - OCR3Config *kslib.OracleConfig -} - -func ConfigureInitialContractsChangeset(e deployment.Environment, cfg InitialContractsCfg) (deployment.ChangesetOutput, error) { - req := &kslib.ConfigureContractsRequest{ - Env: &e, - RegistryChainSel: cfg.RegistryChainSel, - Dons: cfg.Dons, - OCR3Config: cfg.OCR3Config, - } - return ConfigureInitialContracts(e.Logger, req) -} - -// Deprecated: Use ConfigureInitialContractsChangeset instead. func ConfigureInitialContracts(lggr logger.Logger, req *kslib.ConfigureContractsRequest) (deployment.ChangesetOutput, error) { if err := req.Validate(); err != nil { return deployment.ChangesetOutput{}, fmt.Errorf("failed to validate request: %w", err) diff --git a/deployment/keystone/changeset/deploy_consumer.go b/deployment/keystone/changeset/deploy_consumer.go deleted file mode 100644 index d94d7ac0adc..00000000000 --- a/deployment/keystone/changeset/deploy_consumer.go +++ /dev/null @@ -1,31 +0,0 @@ -package changeset - -import ( - "fmt" - - "github.com/smartcontractkit/chainlink/deployment" - kslib "github.com/smartcontractkit/chainlink/deployment/keystone/changeset/internal" -) - -type DeployFeedsConsumerRequest struct { - ChainSelector uint64 -} - -var _ deployment.ChangeSet[*DeployFeedsConsumerRequest] = DeployFeedsConsumer - -// DeployFeedsConsumer deploys the FeedsConsumer contract to the chain with the given chainSelector. -func DeployFeedsConsumer(env deployment.Environment, req *DeployFeedsConsumerRequest) (deployment.ChangesetOutput, error) { - chainSelector := req.ChainSelector - lggr := env.Logger - chain, ok := env.Chains[chainSelector] - if !ok { - return deployment.ChangesetOutput{}, fmt.Errorf("chain not found in environment") - } - ab := deployment.NewMemoryAddressBook() - deployResp, err := kslib.DeployFeedsConsumer(chain, ab) - if err != nil { - return deployment.ChangesetOutput{}, fmt.Errorf("failed to deploy FeedsConsumer: %w", err) - } - lggr.Infof("Deployed %s chain selector %d addr %s", deployResp.Tv.String(), chain.Selector, deployResp.Address.String()) - return deployment.ChangesetOutput{AddressBook: ab}, nil -} diff --git a/deployment/keystone/changeset/deploy_consumer_test.go b/deployment/keystone/changeset/deploy_consumer_test.go deleted file mode 100644 index 9a1e8f57da7..00000000000 --- a/deployment/keystone/changeset/deploy_consumer_test.go +++ /dev/null @@ -1,40 +0,0 @@ -package changeset_test - -import ( - "testing" - - "go.uber.org/zap/zapcore" - - "github.com/stretchr/testify/require" - - "github.com/smartcontractkit/chainlink-common/pkg/logger" - - "github.com/smartcontractkit/chainlink/deployment/environment/memory" - "github.com/smartcontractkit/chainlink/deployment/keystone/changeset" -) - -func TestDeployFeedsConsumer(t *testing.T) { - t.Parallel() - lggr := logger.Test(t) - cfg := memory.MemoryEnvironmentConfig{ - Nodes: 1, - Chains: 2, - } - env := memory.NewMemoryEnvironment(t, lggr, zapcore.DebugLevel, cfg) - - registrySel := env.AllChainSelectors()[0] - resp, err := changeset.DeployFeedsConsumer(env, &changeset.DeployFeedsConsumerRequest{ - ChainSelector: registrySel, - }) - require.NoError(t, err) - require.NotNil(t, resp) - // feeds consumer should be deployed on chain 0 - addrs, err := resp.AddressBook.AddressesForChain(registrySel) - require.NoError(t, err) - require.Len(t, addrs, 1) - - // no feeds consumer registry on chain 1 - require.NotEqual(t, registrySel, env.AllChainSelectors()[1]) - oaddrs, _ := resp.AddressBook.AddressesForChain(env.AllChainSelectors()[1]) - require.Len(t, oaddrs, 0) -} diff --git a/deployment/keystone/changeset/deploy_forwarder.go b/deployment/keystone/changeset/deploy_forwarder.go index 66923140e6a..55ab0dcd86d 100644 --- a/deployment/keystone/changeset/deploy_forwarder.go +++ b/deployment/keystone/changeset/deploy_forwarder.go @@ -2,123 +2,31 @@ package changeset import ( "fmt" - "maps" - "slices" - "github.com/ethereum/go-ethereum/common" - "github.com/smartcontractkit/ccip-owner-contracts/pkg/gethwrappers" - "github.com/smartcontractkit/ccip-owner-contracts/pkg/proposal/timelock" "github.com/smartcontractkit/chainlink/deployment" - "github.com/smartcontractkit/chainlink/deployment/common/proposalutils" - "github.com/smartcontractkit/chainlink/deployment/keystone/changeset/internal" + kslib "github.com/smartcontractkit/chainlink/deployment/keystone" ) -var _ deployment.ChangeSet[DeployForwarderRequest] = DeployForwarder +var _ deployment.ChangeSet[uint64] = DeployForwarder -type DeployForwarderRequest struct { - ChainSelectors []uint64 // filter to only deploy to these chains; if empty, deploy to all chains -} - -// DeployForwarder deploys the KeystoneForwarder contract to all chains in the environment -// callers must merge the output addressbook with the existing one -// TODO: add selectors to deploy only to specific chains -func DeployForwarder(env deployment.Environment, cfg DeployForwarderRequest) (deployment.ChangesetOutput, error) { +func DeployForwarder(env deployment.Environment, registryChainSel uint64) (deployment.ChangesetOutput, error) { lggr := env.Logger - ab := deployment.NewMemoryAddressBook() - selectors := cfg.ChainSelectors - if len(selectors) == 0 { - selectors = slices.Collect(maps.Keys(env.Chains)) + // expect OCR3 to be deployed & capabilities registry + regAddrs, err := env.ExistingAddresses.AddressesForChain(registryChainSel) + if err != nil { + return deployment.ChangesetOutput{}, fmt.Errorf("no addresses found for chain %d: %w", registryChainSel, err) } - for _, sel := range selectors { - chain, ok := env.Chains[sel] - if !ok { - return deployment.ChangesetOutput{}, fmt.Errorf("chain with selector %d not found", sel) - } + if len(regAddrs) != 2 { + return deployment.ChangesetOutput{}, fmt.Errorf("expected 2 addresses for chain %d, got %d", registryChainSel, len(regAddrs)) + } + ab := deployment.NewMemoryAddressBook() + for _, chain := range env.Chains { lggr.Infow("deploying forwarder", "chainSelector", chain.Selector) - forwarderResp, err := internal.DeployForwarder(chain, ab) + err := kslib.DeployForwarder(lggr, chain, ab) if err != nil { return deployment.ChangesetOutput{}, fmt.Errorf("failed to deploy KeystoneForwarder to chain selector %d: %w", chain.Selector, err) } - lggr.Infof("Deployed %s chain selector %d addr %s", forwarderResp.Tv.String(), chain.Selector, forwarderResp.Address.String()) } return deployment.ChangesetOutput{AddressBook: ab}, nil } - -var _ deployment.ChangeSet[ConfigureForwardContractsRequest] = ConfigureForwardContracts - -type ConfigureForwardContractsRequest struct { - WFDonName string - // workflow don node ids in the offchain client. Used to fetch and derive the signer keys - WFNodeIDs []string - RegistryChainSel uint64 - - // MCMSConfig is optional. If non-nil, the changes will be proposed using MCMS. - MCMSConfig *MCMSConfig -} - -func (r ConfigureForwardContractsRequest) Validate() error { - if len(r.WFNodeIDs) == 0 { - return fmt.Errorf("WFNodeIDs must not be empty") - } - return nil -} - -func (r ConfigureForwardContractsRequest) UseMCMS() bool { - return r.MCMSConfig != nil -} - -func ConfigureForwardContracts(env deployment.Environment, req ConfigureForwardContractsRequest) (deployment.ChangesetOutput, error) { - wfDon, err := internal.NewRegisteredDon(env, internal.RegisteredDonConfig{ - NodeIDs: req.WFNodeIDs, - Name: req.WFDonName, - RegistryChainSel: req.RegistryChainSel, - }) - if err != nil { - return deployment.ChangesetOutput{}, fmt.Errorf("failed to create registered don: %w", err) - } - r, err := internal.ConfigureForwardContracts(&env, internal.ConfigureForwarderContractsRequest{ - Dons: []internal.RegisteredDon{*wfDon}, - UseMCMS: req.UseMCMS(), - }) - if err != nil { - return deployment.ChangesetOutput{}, fmt.Errorf("failed to configure forward contracts: %w", err) - } - - cresp, err := internal.GetContractSets(env.Logger, &internal.GetContractSetsRequest{ - Chains: env.Chains, - AddressBook: env.ExistingAddresses, - }) - if err != nil { - return deployment.ChangesetOutput{}, fmt.Errorf("failed to get contract sets: %w", err) - } - - var out deployment.ChangesetOutput - if req.UseMCMS() { - if len(r.OpsPerChain) == 0 { - return out, fmt.Errorf("expected MCMS operation to be non-nil") - } - for chainSelector, op := range r.OpsPerChain { - contracts := cresp.ContractSets[chainSelector] - timelocksPerChain := map[uint64]common.Address{ - chainSelector: contracts.Timelock.Address(), - } - proposerMCMSes := map[uint64]*gethwrappers.ManyChainMultiSig{ - chainSelector: contracts.ProposerMcm, - } - - proposal, err := proposalutils.BuildProposalFromBatches( - timelocksPerChain, - proposerMCMSes, - []timelock.BatchChainOperation{op}, - "proposal to set forwarder config", - req.MCMSConfig.MinDuration, - ) - if err != nil { - return out, fmt.Errorf("failed to build proposal: %w", err) - } - out.Proposals = append(out.Proposals, *proposal) - } - } - return out, nil -} diff --git a/deployment/keystone/changeset/deploy_forwarder_test.go b/deployment/keystone/changeset/deploy_forwarder_test.go index ec80a9432b0..8d73134fc1d 100644 --- a/deployment/keystone/changeset/deploy_forwarder_test.go +++ b/deployment/keystone/changeset/deploy_forwarder_test.go @@ -1,7 +1,6 @@ package changeset_test import ( - "fmt" "testing" "go.uber.org/zap/zapcore" @@ -10,11 +9,9 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink/deployment" - commonchangeset "github.com/smartcontractkit/chainlink/deployment/common/changeset" - "github.com/smartcontractkit/chainlink/deployment/common/proposalutils" "github.com/smartcontractkit/chainlink/deployment/environment/memory" + kslb "github.com/smartcontractkit/chainlink/deployment/keystone" "github.com/smartcontractkit/chainlink/deployment/keystone/changeset" - "github.com/smartcontractkit/chainlink/deployment/keystone/changeset/test" ) func TestDeployForwarder(t *testing.T) { @@ -27,14 +24,46 @@ func TestDeployForwarder(t *testing.T) { } env := memory.NewMemoryEnvironment(t, lggr, zapcore.DebugLevel, cfg) + var ( + ocrTV = deployment.NewTypeAndVersion(kslb.OCR3Capability, deployment.Version1_0_0) + crTV = deployment.NewTypeAndVersion(kslb.CapabilitiesRegistry, deployment.Version1_0_0) + ) + registrySel := env.AllChainSelectors()[0] + t.Run("err if no capabilities registry on registry chain", func(t *testing.T) { + m := make(map[uint64]map[string]deployment.TypeAndVersion) + m[registrySel] = map[string]deployment.TypeAndVersion{ + "0x0000000000000000000000000000000000000002": ocrTV, + } + env.ExistingAddresses = deployment.NewMemoryAddressBookFromMap(m) + // capabilities registry and ocr3 must be deployed on registry chain + _, err := changeset.DeployForwarder(env, registrySel) + require.Error(t, err) + }) + + t.Run("err if no ocr3 on registry chain", func(t *testing.T) { + m := make(map[uint64]map[string]deployment.TypeAndVersion) + m[registrySel] = map[string]deployment.TypeAndVersion{ + "0x0000000000000000000000000000000000000001": crTV, + } + env.ExistingAddresses = deployment.NewMemoryAddressBookFromMap(m) + // capabilities registry and ocr3 must be deployed on registry chain + _, err := changeset.DeployForwarder(env, registrySel) + require.Error(t, err) + }) t.Run("should deploy forwarder", func(t *testing.T) { ab := deployment.NewMemoryAddressBook() + // fake capabilities registry + err := ab.Save(registrySel, "0x0000000000000000000000000000000000000001", crTV) + require.NoError(t, err) + // fake ocr3 + err = ab.Save(registrySel, "0x0000000000000000000000000000000000000002", ocrTV) + require.NoError(t, err) // deploy forwarder env.ExistingAddresses = ab - resp, err := changeset.DeployForwarder(env, changeset.DeployForwarderRequest{}) + resp, err := changeset.DeployForwarder(env, registrySel) require.NoError(t, err) require.NotNil(t, resp) // registry, ocr3, forwarder should be deployed on registry chain @@ -49,94 +78,3 @@ func TestDeployForwarder(t *testing.T) { require.Len(t, oaddrs, 1) }) } - -func TestConfigureForwarders(t *testing.T) { - t.Parallel() - - t.Run("no mcms ", func(t *testing.T) { - for _, nChains := range []int{1, 3} { - name := fmt.Sprintf("nChains=%d", nChains) - t.Run(name, func(t *testing.T) { - te := test.SetupTestEnv(t, test.TestConfig{ - WFDonConfig: test.DonConfig{N: 4}, - AssetDonConfig: test.DonConfig{N: 4}, - WriterDonConfig: test.DonConfig{N: 4}, - NumChains: nChains, - }) - - var wfNodes []string - for id, _ := range te.WFNodes { - wfNodes = append(wfNodes, id) - } - - cfg := changeset.ConfigureForwardContractsRequest{ - WFDonName: "test-wf-don", - WFNodeIDs: wfNodes, - RegistryChainSel: te.RegistrySelector, - } - csOut, err := changeset.ConfigureForwardContracts(te.Env, cfg) - require.NoError(t, err) - require.Nil(t, csOut.AddressBook) - require.Len(t, csOut.Proposals, 0) - // check that forwarder - // TODO set up a listener to check that the forwarder is configured - contractSet := te.ContractSets() - for selector := range te.Env.Chains { - cs, ok := contractSet[selector] - require.True(t, ok) - require.NotNil(t, cs.Forwarder) - } - }) - } - }) - - t.Run("with mcms", func(t *testing.T) { - for _, nChains := range []int{1, 3} { - name := fmt.Sprintf("nChains=%d", nChains) - t.Run(name, func(t *testing.T) { - te := test.SetupTestEnv(t, test.TestConfig{ - WFDonConfig: test.DonConfig{N: 4}, - AssetDonConfig: test.DonConfig{N: 4}, - WriterDonConfig: test.DonConfig{N: 4}, - NumChains: nChains, - UseMCMS: true, - }) - - var wfNodes []string - for id, _ := range te.WFNodes { - wfNodes = append(wfNodes, id) - } - - cfg := changeset.ConfigureForwardContractsRequest{ - WFDonName: "test-wf-don", - WFNodeIDs: wfNodes, - RegistryChainSel: te.RegistrySelector, - MCMSConfig: &changeset.MCMSConfig{MinDuration: 0}, - } - csOut, err := changeset.ConfigureForwardContracts(te.Env, cfg) - require.NoError(t, err) - require.Len(t, csOut.Proposals, nChains) - require.Nil(t, csOut.AddressBook) - - timelockContracts := make(map[uint64]*proposalutils.TimelockExecutionContracts) - for selector, contractSet := range te.ContractSets() { - require.NotNil(t, contractSet.Timelock) - require.NotNil(t, contractSet.CallProxy) - timelockContracts[selector] = &proposalutils.TimelockExecutionContracts{ - Timelock: contractSet.Timelock, - CallProxy: contractSet.CallProxy, - } - } - _, err = commonchangeset.ApplyChangesets(t, te.Env, timelockContracts, []commonchangeset.ChangesetApplication{ - { - Changeset: commonchangeset.WrapChangeSet(changeset.ConfigureForwardContracts), - Config: cfg, - }, - }) - require.NoError(t, err) - - }) - } - }) - -} diff --git a/deployment/keystone/changeset/deploy_ocr3.go b/deployment/keystone/changeset/deploy_ocr3.go index 4e85590e521..e0edf4a4440 100644 --- a/deployment/keystone/changeset/deploy_ocr3.go +++ b/deployment/keystone/changeset/deploy_ocr3.go @@ -1,112 +1,36 @@ package changeset import ( - "encoding/json" "fmt" - "io" - - "github.com/ethereum/go-ethereum/common" - "github.com/smartcontractkit/ccip-owner-contracts/pkg/gethwrappers" - "github.com/smartcontractkit/ccip-owner-contracts/pkg/proposal/timelock" + "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink/deployment" - "github.com/smartcontractkit/chainlink/deployment/common/proposalutils" - kslib "github.com/smartcontractkit/chainlink/deployment/keystone/changeset/internal" + kslib "github.com/smartcontractkit/chainlink/deployment/keystone" ) -var _ deployment.ChangeSet[uint64] = DeployOCR3 - -func DeployOCR3(env deployment.Environment, registryChainSel uint64) (deployment.ChangesetOutput, error) { - lggr := env.Logger +func DeployOCR3(env deployment.Environment, config interface{}) (deployment.ChangesetOutput, error) { + registryChainSel, ok := config.(uint64) + if !ok { + return deployment.ChangesetOutput{}, deployment.ErrInvalidConfig + } ab := deployment.NewMemoryAddressBook() // ocr3 only deployed on registry chain c, ok := env.Chains[registryChainSel] if !ok { return deployment.ChangesetOutput{}, fmt.Errorf("chain not found in environment") } - ocr3Resp, err := kslib.DeployOCR3(c, ab) + err := kslib.DeployOCR3(env.Logger, c, ab) if err != nil { return deployment.ChangesetOutput{}, fmt.Errorf("failed to deploy OCR3Capability: %w", err) } - lggr.Infof("Deployed %s chain selector %d addr %s", ocr3Resp.Tv.String(), c.Selector, ocr3Resp.Address.String()) return deployment.ChangesetOutput{AddressBook: ab}, nil } -var _ deployment.ChangeSet[ConfigureOCR3Config] = ConfigureOCR3Contract - -type ConfigureOCR3Config struct { - ChainSel uint64 - NodeIDs []string - OCR3Config *kslib.OracleConfig - DryRun bool - WriteGeneratedConfig io.Writer // if not nil, write the generated config to this writer as JSON [OCR2OracleConfig] - - // MCMSConfig is optional. If non-nil, the changes will be proposed using MCMS. - MCMSConfig *MCMSConfig -} - -func (cfg ConfigureOCR3Config) UseMCMS() bool { - return cfg.MCMSConfig != nil -} - -func ConfigureOCR3Contract(env deployment.Environment, cfg ConfigureOCR3Config) (deployment.ChangesetOutput, error) { - resp, err := kslib.ConfigureOCR3ContractFromJD(&env, kslib.ConfigureOCR3Config{ - ChainSel: cfg.ChainSel, - NodeIDs: cfg.NodeIDs, - OCR3Config: cfg.OCR3Config, - DryRun: cfg.DryRun, - UseMCMS: cfg.UseMCMS(), - }) +func ConfigureOCR3Contract(lggr logger.Logger, env deployment.Environment, ab deployment.AddressBook, registryChainSel uint64, nodes []string, cfg kslib.OracleConfigWithSecrets) (deployment.ChangesetOutput, error) { + err := kslib.ConfigureOCR3ContractFromJD(&env, registryChainSel, nodes, ab, &cfg) if err != nil { return deployment.ChangesetOutput{}, fmt.Errorf("failed to configure OCR3Capability: %w", err) } - if w := cfg.WriteGeneratedConfig; w != nil { - b, err := json.MarshalIndent(&resp.OCR2OracleConfig, "", " ") - if err != nil { - return deployment.ChangesetOutput{}, fmt.Errorf("failed to marshal response output: %w", err) - } - env.Logger.Infof("Generated OCR3 config: %s", string(b)) - n, err := w.Write(b) - if err != nil { - return deployment.ChangesetOutput{}, fmt.Errorf("failed to write response output: %w", err) - } - if n != len(b) { - return deployment.ChangesetOutput{}, fmt.Errorf("failed to write all bytes") - } - } - // does not create any new addresses - var out deployment.ChangesetOutput - if cfg.UseMCMS() { - if resp.Ops == nil { - return out, fmt.Errorf("expected MCMS operation to be non-nil") - } - r, err := kslib.GetContractSets(env.Logger, &kslib.GetContractSetsRequest{ - Chains: env.Chains, - AddressBook: env.ExistingAddresses, - }) - if err != nil { - return out, fmt.Errorf("failed to get contract sets: %w", err) - } - contracts := r.ContractSets[cfg.ChainSel] - timelocksPerChain := map[uint64]common.Address{ - cfg.ChainSel: contracts.Timelock.Address(), - } - proposerMCMSes := map[uint64]*gethwrappers.ManyChainMultiSig{ - cfg.ChainSel: contracts.ProposerMcm, - } - proposal, err := proposalutils.BuildProposalFromBatches( - timelocksPerChain, - proposerMCMSes, - []timelock.BatchChainOperation{*resp.Ops}, - "proposal to set OCR3 config", - cfg.MCMSConfig.MinDuration, - ) - if err != nil { - return out, fmt.Errorf("failed to build proposal: %w", err) - } - out.Proposals = []timelock.MCMSWithTimelockProposal{*proposal} - - } - return out, nil + return deployment.ChangesetOutput{AddressBook: ab}, nil } diff --git a/deployment/keystone/changeset/deploy_ocr3_test.go b/deployment/keystone/changeset/deploy_ocr3_test.go index c12f6878835..d3fdf118f8b 100644 --- a/deployment/keystone/changeset/deploy_ocr3_test.go +++ b/deployment/keystone/changeset/deploy_ocr3_test.go @@ -1,8 +1,6 @@ package changeset_test import ( - "bytes" - "encoding/json" "testing" "go.uber.org/zap/zapcore" @@ -11,13 +9,8 @@ import ( "github.com/stretchr/testify/require" "github.com/smartcontractkit/chainlink-common/pkg/logger" - - commonchangeset "github.com/smartcontractkit/chainlink/deployment/common/changeset" - "github.com/smartcontractkit/chainlink/deployment/common/proposalutils" "github.com/smartcontractkit/chainlink/deployment/environment/memory" "github.com/smartcontractkit/chainlink/deployment/keystone/changeset" - "github.com/smartcontractkit/chainlink/deployment/keystone/changeset/internal" - "github.com/smartcontractkit/chainlink/deployment/keystone/changeset/test" ) func TestDeployOCR3(t *testing.T) { @@ -44,99 +37,3 @@ func TestDeployOCR3(t *testing.T) { oaddrs, _ := resp.AddressBook.AddressesForChain(env.AllChainSelectors()[1]) assert.Len(t, oaddrs, 0) } - -func TestConfigureOCR3(t *testing.T) { - t.Parallel() - - c := internal.OracleConfig{ - MaxFaultyOracles: 1, - DeltaProgressMillis: 12345, - } - - t.Run("no mcms", func(t *testing.T) { - - te := test.SetupTestEnv(t, test.TestConfig{ - WFDonConfig: test.DonConfig{N: 4}, - AssetDonConfig: test.DonConfig{N: 4}, - WriterDonConfig: test.DonConfig{N: 4}, - NumChains: 1, - }) - - var wfNodes []string - for id, _ := range te.WFNodes { - wfNodes = append(wfNodes, id) - } - - w := &bytes.Buffer{} - cfg := changeset.ConfigureOCR3Config{ - ChainSel: te.RegistrySelector, - NodeIDs: wfNodes, - OCR3Config: &c, - WriteGeneratedConfig: w, - } - - csOut, err := changeset.ConfigureOCR3Contract(te.Env, cfg) - require.NoError(t, err) - var got internal.OCR2OracleConfig - err = json.Unmarshal(w.Bytes(), &got) - require.NoError(t, err) - assert.Len(t, got.Signers, 4) - assert.Len(t, got.Transmitters, 4) - assert.Nil(t, csOut.Proposals) - }) - - t.Run("mcms", func(t *testing.T) { - te := test.SetupTestEnv(t, test.TestConfig{ - WFDonConfig: test.DonConfig{N: 4}, - AssetDonConfig: test.DonConfig{N: 4}, - WriterDonConfig: test.DonConfig{N: 4}, - NumChains: 1, - UseMCMS: true, - }) - - var wfNodes []string - for id, _ := range te.WFNodes { - wfNodes = append(wfNodes, id) - } - - w := &bytes.Buffer{} - cfg := changeset.ConfigureOCR3Config{ - ChainSel: te.RegistrySelector, - NodeIDs: wfNodes, - OCR3Config: &c, - WriteGeneratedConfig: w, - MCMSConfig: &changeset.MCMSConfig{MinDuration: 0}, - } - - csOut, err := changeset.ConfigureOCR3Contract(te.Env, cfg) - require.NoError(t, err) - var got internal.OCR2OracleConfig - err = json.Unmarshal(w.Bytes(), &got) - require.NoError(t, err) - assert.Len(t, got.Signers, 4) - assert.Len(t, got.Transmitters, 4) - assert.NotNil(t, csOut.Proposals) - t.Logf("got: %v", csOut.Proposals[0]) - - contracts := te.ContractSets()[te.RegistrySelector] - require.NoError(t, err) - var timelockContracts = map[uint64]*proposalutils.TimelockExecutionContracts{ - te.RegistrySelector: { - Timelock: contracts.Timelock, - CallProxy: contracts.CallProxy, - }, - } - - // now apply the changeset such that the proposal is signed and execed - w2 := &bytes.Buffer{} - cfg.WriteGeneratedConfig = w2 - _, err = commonchangeset.ApplyChangesets(t, te.Env, timelockContracts, []commonchangeset.ChangesetApplication{ - { - Changeset: commonchangeset.WrapChangeSet(changeset.ConfigureOCR3Contract), - Config: cfg, - }, - }) - require.NoError(t, err) - }) - -} diff --git a/deployment/keystone/changeset/deploy_registry.go b/deployment/keystone/changeset/deploy_registry.go index 2b8342c06dd..2c08e5ca8b7 100644 --- a/deployment/keystone/changeset/deploy_registry.go +++ b/deployment/keystone/changeset/deploy_registry.go @@ -4,23 +4,22 @@ import ( "fmt" "github.com/smartcontractkit/chainlink/deployment" - kslib "github.com/smartcontractkit/chainlink/deployment/keystone/changeset/internal" + kslib "github.com/smartcontractkit/chainlink/deployment/keystone" ) -var _ deployment.ChangeSet[uint64] = DeployCapabilityRegistry - -func DeployCapabilityRegistry(env deployment.Environment, registrySelector uint64) (deployment.ChangesetOutput, error) { - lggr := env.Logger +func DeployCapabilityRegistry(env deployment.Environment, config interface{}) (deployment.ChangesetOutput, error) { + registrySelector, ok := config.(uint64) + if !ok { + return deployment.ChangesetOutput{}, deployment.ErrInvalidConfig + } chain, ok := env.Chains[registrySelector] if !ok { return deployment.ChangesetOutput{}, fmt.Errorf("chain not found in environment") } ab := deployment.NewMemoryAddressBook() - capabilitiesRegistryResp, err := kslib.DeployCapabilitiesRegistry(chain, ab) + err := kslib.DeployCapabilitiesRegistry(env.Logger, chain, ab) if err != nil { return deployment.ChangesetOutput{}, fmt.Errorf("failed to deploy CapabilitiesRegistry: %w", err) } - lggr.Infof("Deployed %s chain selector %d addr %s", capabilitiesRegistryResp.Tv.String(), chain.Selector, capabilitiesRegistryResp.Address.String()) - return deployment.ChangesetOutput{AddressBook: ab}, nil } diff --git a/deployment/keystone/changeset/deploy_registry_test.go b/deployment/keystone/changeset/deploy_registry_test.go index 9abf357f2a8..6aa383ef68c 100644 --- a/deployment/keystone/changeset/deploy_registry_test.go +++ b/deployment/keystone/changeset/deploy_registry_test.go @@ -8,7 +8,6 @@ import ( "github.com/stretchr/testify/require" "github.com/smartcontractkit/chainlink-common/pkg/logger" - "github.com/smartcontractkit/chainlink/deployment/environment/memory" "github.com/smartcontractkit/chainlink/deployment/keystone/changeset" ) diff --git a/deployment/keystone/changeset/internal/append_node_capabilities.go b/deployment/keystone/changeset/internal/append_node_capabilities.go index 32fe8572da3..cb28c03c6f5 100644 --- a/deployment/keystone/changeset/internal/append_node_capabilities.go +++ b/deployment/keystone/changeset/internal/append_node_capabilities.go @@ -5,24 +5,23 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink/deployment" - - kcr "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry_1_1_0" + kslib "github.com/smartcontractkit/chainlink/deployment/keystone" + kcr "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/p2pkey" ) type AppendNodeCapabilitiesRequest struct { - Chain deployment.Chain - ContractSet *ContractSet + Chain deployment.Chain + Registry *kcr.CapabilitiesRegistry P2pToCapabilities map[p2pkey.PeerID][]kcr.CapabilitiesRegistryCapability - UseMCMS bool } func (req *AppendNodeCapabilitiesRequest) Validate() error { if len(req.P2pToCapabilities) == 0 { return fmt.Errorf("p2pToCapabilities is empty") } - if req.ContractSet.CapabilitiesRegistry == nil { + if req.Registry == nil { return fmt.Errorf("registry is nil") } return nil @@ -32,33 +31,30 @@ func AppendNodeCapabilitiesImpl(lggr logger.Logger, req *AppendNodeCapabilitiesR if err := req.Validate(); err != nil { return nil, fmt.Errorf("failed to validate request: %w", err) } + // collect all the capabilities and add them to the registry + var capabilities []kcr.CapabilitiesRegistryCapability + for _, cap := range req.P2pToCapabilities { + capabilities = append(capabilities, cap...) + } + err := kslib.AddCapabilities(lggr, req.Registry, req.Chain, capabilities) + if err != nil { + return nil, fmt.Errorf("failed to add capabilities: %w", err) + } // for each node, merge the new capabilities with the existing ones and update the node updatesByPeer := make(map[p2pkey.PeerID]NodeUpdate) for p2pID, caps := range req.P2pToCapabilities { - caps, err := AppendCapabilities(lggr, req.ContractSet.CapabilitiesRegistry, req.Chain, []p2pkey.PeerID{p2pID}, caps) + caps, err := AppendCapabilities(lggr, req.Registry, req.Chain, []p2pkey.PeerID{p2pID}, caps) if err != nil { return nil, fmt.Errorf("failed to append capabilities for p2p %s: %w", p2pID, err) } updatesByPeer[p2pID] = NodeUpdate{Capabilities: caps[p2pID]} } - // collect all the capabilities and add them to the registry - var capabilities []kcr.CapabilitiesRegistryCapability - for _, cap := range req.P2pToCapabilities { - capabilities = append(capabilities, cap...) - } - op, err := AddCapabilities(lggr, req.ContractSet, req.Chain, capabilities, req.UseMCMS) - if err != nil { - return nil, fmt.Errorf("failed to add capabilities: %w", err) - } - updateNodesReq := &UpdateNodesRequest{ Chain: req.Chain, - ContractSet: req.ContractSet, + Registry: req.Registry, P2pToUpdates: updatesByPeer, - UseMCMS: req.UseMCMS, - Ops: op, } resp, err := UpdateNodes(lggr, updateNodesReq) if err != nil { diff --git a/deployment/keystone/changeset/internal/append_node_capabilities_test.go b/deployment/keystone/changeset/internal/append_node_capabilities_test.go index 6d26133195d..d28dcd73230 100644 --- a/deployment/keystone/changeset/internal/append_node_capabilities_test.go +++ b/deployment/keystone/changeset/internal/append_node_capabilities_test.go @@ -11,7 +11,7 @@ import ( "github.com/smartcontractkit/chainlink/deployment/keystone/changeset/internal" kstest "github.com/smartcontractkit/chainlink/deployment/keystone/changeset/internal/test" - kcr "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry_1_1_0" + kcr "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/p2pkey" ) @@ -94,8 +94,8 @@ func TestAppendNodeCapabilities(t *testing.T) { t.Run(tt.name, func(t *testing.T) { setupResp := kstest.SetupTestRegistry(t, lggr, tt.args.initialState) + tt.args.req.Registry = setupResp.Registry tt.args.req.Chain = setupResp.Chain - tt.args.req.ContractSet = setupResp.ContractSet got, err := internal.AppendNodeCapabilitiesImpl(tt.args.lggr, tt.args.req) if (err != nil) != tt.wantErr { diff --git a/deployment/keystone/changeset/internal/capability_management.go b/deployment/keystone/changeset/internal/capability_management.go deleted file mode 100644 index 268b4fd0d01..00000000000 --- a/deployment/keystone/changeset/internal/capability_management.go +++ /dev/null @@ -1,92 +0,0 @@ -package internal - -import ( - "fmt" - "math/big" - - "github.com/smartcontractkit/ccip-owner-contracts/pkg/proposal/mcms" - "github.com/smartcontractkit/ccip-owner-contracts/pkg/proposal/timelock" - "github.com/smartcontractkit/chainlink-common/pkg/logger" - "github.com/smartcontractkit/chainlink/deployment" - kcr "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry_1_1_0" -) - -// AddCapabilities adds the capabilities to the registry -func AddCapabilities(lggr logger.Logger, contractSet *ContractSet, chain deployment.Chain, capabilities []kcr.CapabilitiesRegistryCapability, useMCMS bool) (*timelock.BatchChainOperation, error) { - if len(capabilities) == 0 { - return nil, nil - } - registry := contractSet.CapabilitiesRegistry - deduped, err := dedupCapabilities(registry, capabilities) - if err != nil { - return nil, fmt.Errorf("failed to dedup capabilities: %w", err) - } - txOpts := chain.DeployerKey - if useMCMS { - txOpts = deployment.SimTransactOpts() - } - tx, err := registry.AddCapabilities(txOpts, deduped) - if err != nil { - err = deployment.DecodeErr(kcr.CapabilitiesRegistryABI, err) - return nil, fmt.Errorf("failed to add capabilities: %w", err) - } - var batch *timelock.BatchChainOperation - if !useMCMS { - _, err = chain.Confirm(tx) - if err != nil { - return nil, fmt.Errorf("failed to confirm AddCapabilities confirm transaction %s: %w", tx.Hash().String(), err) - } - lggr.Info("registered capabilities", "capabilities", deduped) - } else { - batch = &timelock.BatchChainOperation{ - ChainIdentifier: mcms.ChainIdentifier(chain.Selector), - Batch: []mcms.Operation{ - { - To: registry.Address(), - Data: tx.Data(), - Value: big.NewInt(0), - }, - }, - } - } - return batch, nil -} - -// CapabilityID returns a unique id for the capability -// TODO: mv to chainlink-common? ref https://github.com/smartcontractkit/chainlink/blob/4fb06b4525f03c169c121a68defa9b13677f5f20/contracts/src/v0.8/keystone/CapabilitiesRegistry.sol#L170 -func CapabilityID(c kcr.CapabilitiesRegistryCapability) string { - return fmt.Sprintf("%s@%s", c.LabelledName, c.Version) -} - -// dedupCapabilities deduplicates the capabilities -// dedup capabilities with respect to the registry -// contract reverts on adding the same capability twice and that would cause the whole transaction to revert -// which is very bad for us for mcms -func dedupCapabilities(registry *kcr.CapabilitiesRegistry, capabilities []kcr.CapabilitiesRegistryCapability) ([]kcr.CapabilitiesRegistryCapability, error) { - var out []kcr.CapabilitiesRegistryCapability - existing, err := registry.GetCapabilities(nil) - if err != nil { - return nil, fmt.Errorf("failed to call GetCapabilities: %w", err) - } - existingByID := make(map[[32]byte]struct{}) - for _, cap := range existing { - existingByID[cap.HashedId] = struct{}{} - } - seen := make(map[string]struct{}) - for _, candidate := range capabilities { - h, err := registry.GetHashedCapabilityId(nil, candidate.LabelledName, candidate.Version) - if err != nil { - return nil, fmt.Errorf("failed to call GetHashedCapabilityId: %w", err) - } - // dedup input capabilities - if _, exists := seen[CapabilityID(candidate)]; exists { - continue - } - seen[CapabilityID(candidate)] = struct{}{} - // dedup with respect to the registry - if _, exists := existingByID[h]; !exists { - out = append(out, candidate) - } - } - return out, nil -} diff --git a/deployment/keystone/changeset/internal/consumer_deployer.go b/deployment/keystone/changeset/internal/consumer_deployer.go deleted file mode 100644 index 3c2de539ccb..00000000000 --- a/deployment/keystone/changeset/internal/consumer_deployer.go +++ /dev/null @@ -1,55 +0,0 @@ -package internal - -import ( - "fmt" - - "github.com/smartcontractkit/chainlink-common/pkg/logger" - - "github.com/smartcontractkit/chainlink/deployment" - feeds_consumer "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/feeds_consumer_1_0_0" -) - -type KeystoneFeedsConsumerDeployer struct { - lggr logger.Logger - contract *feeds_consumer.KeystoneFeedsConsumer -} - -func NewKeystoneFeedsConsumerDeployer() (*KeystoneFeedsConsumerDeployer, error) { - lggr, err := logger.New() - if err != nil { - return nil, err - } - return &KeystoneFeedsConsumerDeployer{lggr: lggr}, nil -} - -func (c *KeystoneFeedsConsumerDeployer) deploy(req DeployRequest) (*DeployResponse, error) { - est, err := estimateDeploymentGas(req.Chain.Client, feeds_consumer.KeystoneFeedsConsumerABI) - if err != nil { - return nil, fmt.Errorf("failed to estimate gas: %w", err) - } - c.lggr.Debugf("Feeds Consumer estimated gas: %d", est) - - consumerAddr, tx, consumer, err := feeds_consumer.DeployKeystoneFeedsConsumer( - req.Chain.DeployerKey, - req.Chain.Client) - if err != nil { - return nil, fmt.Errorf("failed to deploy feeds consumer: %w", err) - } - - _, err = req.Chain.Confirm(tx) - if err != nil { - return nil, fmt.Errorf("failed to confirm and save feeds consumer: %w", err) - } - - tv := deployment.TypeAndVersion{ - Type: FeedConsumer, - } - - resp := &DeployResponse{ - Address: consumerAddr, - Tx: tx.Hash(), - Tv: tv, - } - c.contract = consumer - return resp, nil -} diff --git a/deployment/keystone/changeset/internal/contract_set.go b/deployment/keystone/changeset/internal/contract_set.go deleted file mode 100644 index e60f37d6f76..00000000000 --- a/deployment/keystone/changeset/internal/contract_set.go +++ /dev/null @@ -1,115 +0,0 @@ -package internal - -import ( - "fmt" - - "github.com/smartcontractkit/chainlink/deployment" -) - -type deployContractsRequest struct { - chain deployment.Chain - isRegistryChain bool - ad deployment.AddressBook -} - -type deployContractSetResponse struct { - deployment.AddressBook -} - -func deployContractsToChain(req deployContractsRequest) (*deployContractSetResponse, error) { - if req.ad == nil { - req.ad = deployment.NewMemoryAddressBook() - } - // this is mutated in the Deploy* functions - resp := &deployContractSetResponse{ - AddressBook: req.ad, - } - - // cap reg and ocr3 only deployed on registry chain - if req.isRegistryChain { - _, err := DeployCapabilitiesRegistry(req.chain, resp.AddressBook) - if err != nil { - return nil, fmt.Errorf("failed to deploy CapabilitiesRegistry: %w", err) - } - _, err = DeployOCR3(req.chain, resp.AddressBook) - if err != nil { - return nil, fmt.Errorf("failed to deploy OCR3Capability: %w", err) - } - } - _, err := DeployForwarder(req.chain, resp.AddressBook) - if err != nil { - return nil, fmt.Errorf("failed to deploy KeystoneForwarder: %w", err) - } - return resp, nil -} - -// DeployCapabilitiesRegistry deploys the CapabilitiesRegistry contract to the chain -// and saves the address in the address book. This mutates the address book. -func DeployCapabilitiesRegistry(chain deployment.Chain, ab deployment.AddressBook) (*DeployResponse, error) { - capabilitiesRegistryDeployer, err := NewCapabilitiesRegistryDeployer() - capabilitiesRegistryResp, err := capabilitiesRegistryDeployer.Deploy(DeployRequest{Chain: chain}) - if err != nil { - return nil, fmt.Errorf("failed to deploy CapabilitiesRegistry: %w", err) - } - err = ab.Save(chain.Selector, capabilitiesRegistryResp.Address.String(), capabilitiesRegistryResp.Tv) - if err != nil { - return nil, fmt.Errorf("failed to save CapabilitiesRegistry: %w", err) - } - return capabilitiesRegistryResp, nil -} - -// DeployOCR3 deploys the OCR3Capability contract to the chain -// and saves the address in the address book. This mutates the address book. -func DeployOCR3(chain deployment.Chain, ab deployment.AddressBook) (*DeployResponse, error) { - ocr3Deployer, err := NewOCR3Deployer() - if err != nil { - return nil, fmt.Errorf("failed to create OCR3Deployer: %w", err) - } - ocr3Resp, err := ocr3Deployer.deploy(DeployRequest{Chain: chain}) - if err != nil { - return nil, fmt.Errorf("failed to deploy OCR3Capability: %w", err) - } - err = ab.Save(chain.Selector, ocr3Resp.Address.String(), ocr3Resp.Tv) - if err != nil { - return nil, fmt.Errorf("failed to save OCR3Capability: %w", err) - } - - return ocr3Resp, nil -} - -// DeployForwarder deploys the KeystoneForwarder contract to the chain -// and saves the address in the address book. This mutates the address book. -func DeployForwarder(chain deployment.Chain, ab deployment.AddressBook) (*DeployResponse, error) { - forwarderDeployer, err := NewKeystoneForwarderDeployer() - if err != nil { - return nil, fmt.Errorf("failed to create KeystoneForwarderDeployer: %w", err) - } - forwarderResp, err := forwarderDeployer.deploy(DeployRequest{Chain: chain}) - if err != nil { - return nil, fmt.Errorf("failed to deploy KeystoneForwarder: %w", err) - } - err = ab.Save(chain.Selector, forwarderResp.Address.String(), forwarderResp.Tv) - if err != nil { - return nil, fmt.Errorf("failed to save KeystoneForwarder: %w", err) - } - return forwarderResp, nil -} - -// DeployFeedsConsumer deploys the KeystoneFeedsConsumer contract to the chain -// and saves the address in the address book. This mutates the address book. -func DeployFeedsConsumer(chain deployment.Chain, ab deployment.AddressBook) (*DeployResponse, error) { - consumerDeploy, err := NewKeystoneFeedsConsumerDeployer() - if err != nil { - return nil, err - } - consumerResp, err := consumerDeploy.deploy(DeployRequest{Chain: chain}) - if err != nil { - return nil, fmt.Errorf("failed to deploy FeedsConsumer: %w", err) - } - err = ab.Save(chain.Selector, consumerResp.Address.String(), consumerResp.Tv) - if err != nil { - - return nil, fmt.Errorf("failed to save FeedsConsumer: %w", err) - } - return consumerResp, nil -} diff --git a/deployment/keystone/changeset/internal/forwarder_deployer.go b/deployment/keystone/changeset/internal/forwarder_deployer.go deleted file mode 100644 index 2ce3ae88146..00000000000 --- a/deployment/keystone/changeset/internal/forwarder_deployer.go +++ /dev/null @@ -1,101 +0,0 @@ -package internal - -import ( - "fmt" - - "github.com/ethereum/go-ethereum/accounts/abi/bind" - "github.com/smartcontractkit/ccip-owner-contracts/pkg/proposal/timelock" - "github.com/smartcontractkit/chainlink-common/pkg/logger" - - "github.com/smartcontractkit/chainlink/deployment" - forwarder "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/forwarder_1_0_0" -) - -type KeystoneForwarderDeployer struct { - lggr logger.Logger - contract *forwarder.KeystoneForwarder -} - -func NewKeystoneForwarderDeployer() (*KeystoneForwarderDeployer, error) { - lggr, err := logger.New() - if err != nil { - return nil, err - } - return &KeystoneForwarderDeployer{lggr: lggr}, nil -} -func (c *KeystoneForwarderDeployer) deploy(req DeployRequest) (*DeployResponse, error) { - est, err := estimateDeploymentGas(req.Chain.Client, forwarder.KeystoneForwarderABI) - if err != nil { - return nil, fmt.Errorf("failed to estimate gas: %w", err) - } - c.lggr.Debugf("Forwarder estimated gas: %d", est) - - forwarderAddr, tx, forwarder, err := forwarder.DeployKeystoneForwarder( - req.Chain.DeployerKey, - req.Chain.Client) - if err != nil { - return nil, fmt.Errorf("failed to deploy KeystoneForwarder: %w", err) - } - - _, err = req.Chain.Confirm(tx) - if err != nil { - return nil, fmt.Errorf("failed to confirm and save KeystoneForwarder: %w", err) - } - tvStr, err := forwarder.TypeAndVersion(&bind.CallOpts{}) - if err != nil { - return nil, fmt.Errorf("failed to get type and version: %w", err) - } - tv, err := deployment.TypeAndVersionFromString(tvStr) - if err != nil { - return nil, fmt.Errorf("failed to parse type and version from %s: %w", tvStr, err) - } - resp := &DeployResponse{ - Address: forwarderAddr, - Tx: tx.Hash(), - Tv: tv, - } - c.contract = forwarder - return resp, nil -} - -type ConfigureForwarderContractsRequest struct { - Dons []RegisteredDon - - UseMCMS bool -} -type ConfigureForwarderContractsResponse struct { - OpsPerChain map[uint64]timelock.BatchChainOperation -} - -// Depreciated: use [changeset.ConfigureForwarders] instead -// ConfigureForwardContracts configures the forwarder contracts on all chains for the given DONS -// the address book is required to contain the an address of the deployed forwarder contract for every chain in the environment -func ConfigureForwardContracts(env *deployment.Environment, req ConfigureForwarderContractsRequest) (*ConfigureForwarderContractsResponse, error) { - contractSetsResp, err := GetContractSets(env.Logger, &GetContractSetsRequest{ - Chains: env.Chains, - AddressBook: env.ExistingAddresses, - }) - if err != nil { - return nil, fmt.Errorf("failed to get contract sets: %w", err) - } - - opPerChain := make(map[uint64]timelock.BatchChainOperation) - // configure forwarders on all chains - for _, chain := range env.Chains { - // get the forwarder contract for the chain - contracts, ok := contractSetsResp.ContractSets[chain.Selector] - if !ok { - return nil, fmt.Errorf("failed to get contract set for chain %d", chain.Selector) - } - ops, err := configureForwarder(env.Logger, chain, contracts, req.Dons, req.UseMCMS) - if err != nil { - return nil, fmt.Errorf("failed to configure forwarder for chain selector %d: %w", chain.Selector, err) - } - for k, op := range ops { - opPerChain[k] = op - } - } - return &ConfigureForwarderContractsResponse{ - OpsPerChain: opPerChain, - }, nil -} diff --git a/deployment/keystone/changeset/internal/ocr3config_test.go b/deployment/keystone/changeset/internal/ocr3config_test.go deleted file mode 100644 index b412a727eb9..00000000000 --- a/deployment/keystone/changeset/internal/ocr3config_test.go +++ /dev/null @@ -1,179 +0,0 @@ -// TODO: KS-458 copied from https://github.com/smartcontractkit/chainlink/blob/65924811dc53a211613927c814d7f04fd85439a4/core/scripts/keystone/src/88_gen_ocr3_config.go#L1 -// to unblock go mod issues when trying to import the scripts package -package internal - -import ( - "encoding/json" - "os" - "sort" - "strings" - "testing" - - "github.com/ethereum/go-ethereum/common" - chain_selectors "github.com/smartcontractkit/chain-selectors" - types2 "github.com/smartcontractkit/libocr/offchainreporting2/types" - "github.com/smartcontractkit/libocr/offchainreporting2plus/types" - types3 "github.com/smartcontractkit/libocr/offchainreporting2plus/types" - "github.com/test-go/testify/require" - - "github.com/smartcontractkit/chainlink/deployment" - "github.com/smartcontractkit/chainlink/deployment/common/view" - "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/p2pkey" -) - -var wantOCR3Config = `{ - "Signers": [ - "011400b35409a8d4f9a18da55c5b2bb08a3f5f68d44442052000b8834eaa062f0df4ccfe7832253920071ec14dc4f78b13ecdda10b824e2dd3b6", - "0114008258f4c4761cc445333017608044a204fd0c006a052000247d0189f65f58be83a4e7d87ff338aaf8956e9acb9fcc783f34f9edc29d1b40", - "011400d4dcc573e9d24a8b27a07bba670ba3a2ab36e5bb052000ba20d3da9b07663f1e8039081a514649fd61a48be2d241bc63537ee47d028fcd", - "0114006607c140e558631407f33bafbabd103863cee876052000046faf34ebfe42510251e6098bc34fa3dd5f2de38ac07e47f2d1b34ac770639f", - "011400a6f35436cb7bffd615cc47a0a04aa0a78696a1440520001221e131ef21014a6a99ed22376eb869746a3b5e30fd202cf79e44efaeb8c5c2", - "011400657587eb55cecd6f90b97297b611c3024e488cc0052000425d1354a7b8180252a221040c718cac0ba0251c7efe31a2acefbba578dc2153", - "0114004885973b2fcf061d5cdfb8f74c5139bd3056e9da0520004a94c75cb9fe8b1fba86fd4b71ad130943281fdefad10216c46eb2285d60950f", - "011400213803bb9f9715379aaf11aadb0212369701dc0a05200096dc85670c49caa986de4ad288e680e9afb0f5491160dcbb4868ca718e194fc8", - "0114008c2aa1e6fad88a6006dfb116eb866cbad2910314052000bddafb20cc50d89e0ae2f244908c27b1d639615d8186b28c357669de3359f208", - "011400679296b7c1eb4948efcc87efc550940a182e610c0520004fa557850e4d5c21b3963c97414c1f37792700c4d3b8abdb904b765fd47e39bf" - ], - "Transmitters": [ - "0x2877F08d9c5Cc9F401F730Fa418fAE563A9a2FF3", - "0x415aa1E9a1bcB3929ed92bFa1F9735Dc0D45AD31", - "0xCea84bC1881F3cE14BA13Dc3a00DC1Ff3D553fF0", - "0xA9eFB53c513E413762b2Be5299D161d8E6e7278e", - "0x6F5cAb24Fb7412bB516b3468b9F3a9c471d25fE5", - "0xdAd1F3F8ec690cf335D46c50EdA5547CeF875161", - "0x19e10B063a62B1574AE19020A64fDe6419892dA6", - "0x9ad9f3AD49e5aB0F28bD694d211a90297bD90D7f", - "0x31B179dcF8f9036C30f04bE578793e51bF14A39E", - "0x0b04cE574E80Da73191Ec141c0016a54A6404056" - ], - "F": 3, - "OnchainConfig": "0x", - "OffchainConfigVersion": 30, - "OffchainConfig": "0xc80180e497d012d00180e497d012d80180a8d6b907e00180cab5ee01e80180d88ee16ff0010afa01010a82022003dacd15fc96c965c648e3623180de002b71a97cf6eeca9affb91f461dcd6ce1820220255096a3b7ade10e29c648e0b407fc486180464f713446b1da04f013df6179c8820220dba3c61e5f8bec594be481bcaf67ecea0d1c2950edb15b158ce3dbc77877def3820220b4c4993d6c15fee63800db901a8b35fa419057610962caab1c1d7bed557091278202202a4c7dec127fdd8145e48c5edb9467225098bd8c8ad1dade868325b787affbde820220283471ed66d61fbe11f64eff65d738b59a0301c9a4f846280db26c64c9fdd3f8820220aa3419628ea3536783742d17d8adf05681aa6a6bd2b206fbde78c7e5aa38586d82022001496edce35663071d74472e02119432ba059b3904d205e4358014410e4f2be3820220ad08c2a5878cada53521f4e2bb449f191ccca7899246721a0deeea19f7b83f70820220c805572b813a072067eab2087ddbee8aa719090e12890b15c01094f0d3f74a5f8a02008a02008a02008a02008a02008a02008a02008a02008a02008a020098028094ebdc03a0028094ebdc03a8028094ebdc03b0028094ebdc03ba02f8010a20da47a8cc1c10796dd43f98ed113c648625e2e504c16ac5da9c65669e2377241b1220f5beca3bb11406079dc174183105c474c862a73c257ce8b3d9f5ca065e6264691a10805015e4203740495a23e93c1bd06ba81a10ca58ff36ffb0545dc3f800ddd6f8d0481a1076f664639ca8b5209e488895faa5460f1a104a1e89a7f2d8c89158f18856bf289c2a1a10c2f4330787831f419713ad4990e347d31a10fd403ec0797c001a2794b51d6178916d1a10e14fff88fdd3d1554ed861104ddc56a81a10b0284b9817fec2c3066c6f2651d17fc41a10b090233a67d502f78191c9e19a2a032b1a10e483414860bb612af50ee15ce8cd8ef5c00280e497d012c8028094ebdc03" -}` - -var ocr3Cfg = ` -{ - "MaxQueryLengthBytes": 1000000, - "MaxObservationLengthBytes": 1000000, - "MaxReportLengthBytes": 1000000, - "MaxRequestBatchSize": 1000, - "UniqueReports": true, - "DeltaProgressMillis": 5000, - "DeltaResendMillis": 5000, - "DeltaInitialMillis": 5000, - "DeltaRoundMillis": 2000, - "DeltaGraceMillis": 500, - "DeltaCertifiedCommitRequestMillis": 1000, - "DeltaStageMillis": 30000, - "MaxRoundsPerEpoch": 10, - "TransmissionSchedule": [ - 10 - ], - "MaxDurationQueryMillis": 1000, - "MaxDurationObservationMillis": 1000, - "MaxDurationReportMillis": 1000, - "MaxDurationAcceptMillis": 1000, - "MaxDurationTransmitMillis": 1000, - "MaxFaultyOracles": 3 -}` - -func Test_configureOCR3Request_generateOCR3Config(t *testing.T) { - nodes := loadTestData(t, "testdata/testnet_wf_view.json") - - var cfg OracleConfig - err := json.Unmarshal([]byte(ocr3Cfg), &cfg) - require.NoError(t, err) - r := configureOCR3Request{ - cfg: &cfg, - nodes: nodes, - chain: deployment.Chain{ - Selector: chain_selectors.ETHEREUM_TESTNET_SEPOLIA.Selector, - }, - ocrSecrets: deployment.XXXGenerateTestOCRSecrets(), - } - got, err := r.generateOCR3Config() - require.NoError(t, err) - b, err := json.MarshalIndent(got, "", " ") - require.NoError(t, err) - require.Equal(t, wantOCR3Config, string(b)) -} - -func loadTestData(t *testing.T, path string) []deployment.Node { - data, err := os.ReadFile(path) - require.NoError(t, err) - var nodeViews map[string]*view.NopView - err = json.Unmarshal(data, &nodeViews) - require.NoError(t, err) - require.Len(t, nodeViews, 10) - - names := make([]string, 0) - for k := range nodeViews { - names = append(names, k) - } - sort.Strings(names) - - // in general we can map from the view to the node, but we know the test data - var nodes []deployment.Node - //for _, nv := range nodeViews { - for _, name := range names { - nv := nodeViews[name] - node := deployment.Node{ - NodeID: nv.NodeID, - IsBootstrap: nv.IsBootstrap, - SelToOCRConfig: make(map[chain_selectors.ChainDetails]deployment.OCRConfig), - AdminAddr: nv.PayeeAddress, - } - for chain, ocrKey := range nv.OCRKeys { - // TODO: this decoding could be shared with NodeInfo - p, err := p2pkey.MakePeerID(ocrKey.PeerID) - require.NoError(t, err) - - b := common.Hex2Bytes(ocrKey.OffchainPublicKey) - var opk types2.OffchainPublicKey - copy(opk[:], b) - - b = common.Hex2Bytes(ocrKey.ConfigEncryptionPublicKey) - var cpk types3.ConfigEncryptionPublicKey - copy(cpk[:], b) - - var pubkey types3.OnchainPublicKey - if strings.HasPrefix(chain, "ethereum") { - // convert from pubkey to address - pubkey = common.HexToAddress(ocrKey.OnchainPublicKey).Bytes() - } else { - pubkey = common.Hex2Bytes(ocrKey.OnchainPublicKey) - } - - ocrCfg := deployment.OCRConfig{ - KeyBundleID: ocrKey.KeyBundleID, - OffchainPublicKey: opk, - OnchainPublicKey: pubkey, - PeerID: p, - TransmitAccount: types.Account(ocrKey.TransmitAccount), - ConfigEncryptionPublicKey: cpk, - } - var k chain_selectors.ChainDetails - switch chain { - case "aptos-testnet": - k = chain_selectors.ChainDetails{ - ChainSelector: chain_selectors.APTOS_TESTNET.Selector, - ChainName: chain, - } - - case "ethereum-testnet-sepolia": - k = chain_selectors.ChainDetails{ - ChainSelector: chain_selectors.ETHEREUM_TESTNET_SEPOLIA.Selector, - ChainName: chain, - } - default: - t.Fatalf("unexpected chain %s", chain) - } - node.SelToOCRConfig[k] = ocrCfg - } - - nodes = append(nodes, node) - } - require.Len(t, nodes, 10) - return nodes -} diff --git a/deployment/keystone/changeset/internal/test/utils.go b/deployment/keystone/changeset/internal/test/utils.go index cc7e3b27160..cea20fd327d 100644 --- a/deployment/keystone/changeset/internal/test/utils.go +++ b/deployment/keystone/changeset/internal/test/utils.go @@ -13,12 +13,13 @@ import ( capabilitiespb "github.com/smartcontractkit/chainlink-common/pkg/capabilities/pb" "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink-common/pkg/values" - "github.com/smartcontractkit/chainlink/deployment" "github.com/smartcontractkit/chainlink/deployment/environment/memory" - "github.com/smartcontractkit/chainlink/deployment/keystone/changeset/internal" - capabilities_registry "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry_1_1_0" + kslib "github.com/smartcontractkit/chainlink/deployment/keystone" + internal "github.com/smartcontractkit/chainlink/deployment/keystone/changeset/internal" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry" + kcr "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/p2pkey" ) @@ -27,27 +28,24 @@ type Don struct { P2PIDs []p2pkey.PeerID CapabilityConfigs []internal.CapabilityConfig } - type SetupTestRegistryRequest struct { - P2pToCapabilities map[p2pkey.PeerID][]capabilities_registry.CapabilitiesRegistryCapability - NopToNodes map[capabilities_registry.CapabilitiesRegistryNodeOperator][]*internal.P2PSignerEnc + P2pToCapabilities map[p2pkey.PeerID][]kcr.CapabilitiesRegistryCapability + NopToNodes map[kcr.CapabilitiesRegistryNodeOperator][]*internal.P2PSignerEnc Dons []Don - // TODO maybe add support for MCMS at this level } type SetupTestRegistryResponse struct { - Registry *capabilities_registry.CapabilitiesRegistry + Registry *kcr.CapabilitiesRegistry Chain deployment.Chain RegistrySelector uint64 - ContractSet *internal.ContractSet } func SetupTestRegistry(t *testing.T, lggr logger.Logger, req *SetupTestRegistryRequest) *SetupTestRegistryResponse { chain := testChain(t) // deploy the registry - registry := deployCapReg(t, chain) + registry := deployCapReg(t, lggr, chain) // convert req to nodeoperators - nops := make([]capabilities_registry.CapabilitiesRegistryNodeOperator, 0) + nops := make([]kcr.CapabilitiesRegistryNodeOperator, 0) for nop := range req.NopToNodes { nops = append(nops, nop) } @@ -59,19 +57,19 @@ func SetupTestRegistry(t *testing.T, lggr logger.Logger, req *SetupTestRegistryR // add capabilities to registry capCache := NewCapabiltyCache(t) - var capabilities []capabilities_registry.CapabilitiesRegistryCapability + var capabilities []kcr.CapabilitiesRegistryCapability for _, caps := range req.P2pToCapabilities { capabilities = append(capabilities, caps...) } registeredCapabilities := capCache.AddCapabilities(lggr, chain, registry, capabilities) - expectedDeduped := make(map[capabilities_registry.CapabilitiesRegistryCapability]struct{}) + expectedDeduped := make(map[kcr.CapabilitiesRegistryCapability]struct{}) for _, cap := range capabilities { expectedDeduped[cap] = struct{}{} } require.Len(t, registeredCapabilities, len(expectedDeduped)) // make the nodes and register node - var nodeParams []capabilities_registry.CapabilitiesRegistryNodeParams + var nodeParams []kcr.CapabilitiesRegistryNodeParams initialp2pToCapabilities := make(map[p2pkey.PeerID][][32]byte) for p2pID := range req.P2pToCapabilities { initialp2pToCapabilities[p2pID] = mustCapabilityIds(t, registry, registeredCapabilities) @@ -82,7 +80,7 @@ func SetupTestRegistry(t *testing.T, lggr logger.Logger, req *SetupTestRegistryR require.Fail(t, "missing nopToNodes for %s", nop.Name) } for _, p2pSignerEnc := range req.NopToNodes[nop] { - nodeParams = append(nodeParams, capabilities_registry.CapabilitiesRegistryNodeParams{ + nodeParams = append(nodeParams, kcr.CapabilitiesRegistryNodeParams{ Signer: p2pSignerEnc.Signer, P2pId: p2pSignerEnc.P2PKey, EncryptionPublicKey: p2pSignerEnc.EncryptionPublicKey, @@ -100,61 +98,43 @@ func SetupTestRegistry(t *testing.T, lggr logger.Logger, req *SetupTestRegistryR Registry: registry, Chain: chain, RegistrySelector: chain.Selector, - ContractSet: &internal.ContractSet{ - CapabilitiesRegistry: registry, - }, } } -func deployCapReg(t *testing.T, chain deployment.Chain) *capabilities_registry.CapabilitiesRegistry { - capabilitiesRegistryDeployer, err := internal.NewCapabilitiesRegistryDeployer() - require.NoError(t, err) - _, err = capabilitiesRegistryDeployer.Deploy(internal.DeployRequest{Chain: chain}) +func deployCapReg(t *testing.T, lggr logger.Logger, chain deployment.Chain) *kcr.CapabilitiesRegistry { + capabilitiesRegistryDeployer := kslib.NewCapabilitiesRegistryDeployer(lggr) + _, err := capabilitiesRegistryDeployer.Deploy(kslib.DeployRequest{Chain: chain}) require.NoError(t, err) return capabilitiesRegistryDeployer.Contract() } -func addNops(t *testing.T, lggr logger.Logger, chain deployment.Chain, registry *capabilities_registry.CapabilitiesRegistry, nops []capabilities_registry.CapabilitiesRegistryNodeOperator) *internal.RegisterNOPSResponse { - env := &deployment.Environment{ - Logger: lggr, - Chains: map[uint64]deployment.Chain{ - chain.Selector: chain, - }, - ExistingAddresses: deployment.NewMemoryAddressBookFromMap(map[uint64]map[string]deployment.TypeAndVersion{ - chain.Selector: { - registry.Address().String(): deployment.TypeAndVersion{ - Type: internal.CapabilitiesRegistry, - Version: deployment.Version1_0_0, - }, - }, - }), - } - resp, err := internal.RegisterNOPS(context.TODO(), lggr, internal.RegisterNOPSRequest{ - Env: env, - RegistryChainSelector: chain.Selector, - Nops: nops, +func addNops(t *testing.T, lggr logger.Logger, chain deployment.Chain, registry *kcr.CapabilitiesRegistry, nops []kcr.CapabilitiesRegistryNodeOperator) *kslib.RegisterNOPSResponse { + resp, err := kslib.RegisterNOPS(context.TODO(), lggr, kslib.RegisterNOPSRequest{ + Chain: chain, + Registry: registry, + Nops: nops, }) require.NoError(t, err) return resp } -func addNodes(t *testing.T, lggr logger.Logger, chain deployment.Chain, registry *capabilities_registry.CapabilitiesRegistry, nodes []capabilities_registry.CapabilitiesRegistryNodeParams) { +func addNodes(t *testing.T, lggr logger.Logger, chain deployment.Chain, registry *kcr.CapabilitiesRegistry, nodes []kcr.CapabilitiesRegistryNodeParams) { tx, err := registry.AddNodes(chain.DeployerKey, nodes) if err != nil { - err2 := deployment.DecodeErr(capabilities_registry.CapabilitiesRegistryABI, err) + err2 := kslib.DecodeErr(kcr.CapabilitiesRegistryABI, err) require.Fail(t, fmt.Sprintf("failed to call AddNodes: %s: %s", err, err2)) } _, err = chain.Confirm(tx) require.NoError(t, err) } -func addDons(t *testing.T, lggr logger.Logger, chain deployment.Chain, registry *capabilities_registry.CapabilitiesRegistry, capCache *CapabilityCache, dons []Don) { +func addDons(t *testing.T, lggr logger.Logger, chain deployment.Chain, registry *kcr.CapabilitiesRegistry, capCache *CapabilityCache, dons []Don) { for _, don := range dons { acceptsWorkflows := false // lookup the capabilities - var capConfigs []capabilities_registry.CapabilitiesRegistryCapabilityConfiguration + var capConfigs []kcr.CapabilitiesRegistryCapabilityConfiguration for _, ccfg := range don.CapabilityConfigs { - var cc = capabilities_registry.CapabilitiesRegistryCapabilityConfiguration{ + var cc = kcr.CapabilitiesRegistryCapabilityConfiguration{ CapabilityId: [32]byte{}, Config: ccfg.Config, } @@ -162,6 +142,7 @@ func addDons(t *testing.T, lggr logger.Logger, chain deployment.Chain, registry cc.Config = defaultCapConfig(t, ccfg.Capability) } var exists bool + //var cc kcr.CapabilitiesRegistryCapabilityConfiguration{} cc.CapabilityId, exists = capCache.Get(ccfg.Capability) require.True(t, exists, "capability not found in cache %v", ccfg.Capability) capConfigs = append(capConfigs, cc) @@ -174,7 +155,7 @@ func addDons(t *testing.T, lggr logger.Logger, chain deployment.Chain, registry f := len(don.P2PIDs)/3 + 1 tx, err := registry.AddDON(chain.DeployerKey, internal.PeerIDsToBytes(don.P2PIDs), capConfigs, isPublic, acceptsWorkflows, uint8(f)) if err != nil { - err2 := deployment.DecodeErr(capabilities_registry.CapabilitiesRegistryABI, err) + err2 := kslib.DecodeErr(kcr.CapabilitiesRegistryABI, err) require.Fail(t, fmt.Sprintf("failed to call AddDON: %s: %s", err, err2)) } _, err = chain.Confirm(tx) @@ -182,7 +163,7 @@ func addDons(t *testing.T, lggr logger.Logger, chain deployment.Chain, registry } } -func defaultCapConfig(t *testing.T, cap capabilities_registry.CapabilitiesRegistryCapability) []byte { +func defaultCapConfig(t *testing.T, cap kcr.CapabilitiesRegistryCapability) []byte { empty := &capabilitiespb.CapabilityConfig{ DefaultConfig: values.Proto(values.EmptyMap()).GetMapValue(), } @@ -203,24 +184,24 @@ func NewCapabiltyCache(t *testing.T) *CapabilityCache { nameToId: make(map[string][32]byte), } } -func (cc *CapabilityCache) Get(cap capabilities_registry.CapabilitiesRegistryCapability) ([32]byte, bool) { - id, exists := cc.nameToId[internal.CapabilityID(cap)] +func (cc *CapabilityCache) Get(cap kcr.CapabilitiesRegistryCapability) ([32]byte, bool) { + id, exists := cc.nameToId[kslib.CapabilityID(cap)] return id, exists } // AddCapabilities adds the capabilities to the registry and returns the registered capabilities // if the capability is already registered, it will not be re-registered // if duplicate capabilities are passed, they will be deduped -func (cc *CapabilityCache) AddCapabilities(lggr logger.Logger, chain deployment.Chain, registry *capabilities_registry.CapabilitiesRegistry, capabilities []capabilities_registry.CapabilitiesRegistryCapability) []internal.RegisteredCapability { +func (cc *CapabilityCache) AddCapabilities(lggr logger.Logger, chain deployment.Chain, registry *kcr.CapabilitiesRegistry, capabilities []kcr.CapabilitiesRegistryCapability) []kslib.RegisteredCapability { t := cc.t - var out []internal.RegisteredCapability + var out []kslib.RegisteredCapability // get the registered capabilities & dedup - seen := make(map[capabilities_registry.CapabilitiesRegistryCapability]struct{}) - var toRegister []capabilities_registry.CapabilitiesRegistryCapability + seen := make(map[kcr.CapabilitiesRegistryCapability]struct{}) + var toRegister []kcr.CapabilitiesRegistryCapability for _, cap := range capabilities { - id, cached := cc.nameToId[internal.CapabilityID(cap)] + id, cached := cc.nameToId[kslib.CapabilityID(cap)] if cached { - out = append(out, internal.RegisteredCapability{ + out = append(out, kslib.RegisteredCapability{ CapabilitiesRegistryCapability: cap, ID: id, }) @@ -237,7 +218,7 @@ func (cc *CapabilityCache) AddCapabilities(lggr logger.Logger, chain deployment. } tx, err := registry.AddCapabilities(chain.DeployerKey, toRegister) if err != nil { - err2 := deployment.DecodeErr(capabilities_registry.CapabilitiesRegistryABI, err) + err2 := kslib.DecodeErr(kcr.CapabilitiesRegistryABI, err) require.Fail(t, fmt.Sprintf("failed to call AddCapabilities: %s: %s", err, err2)) } _, err = chain.Confirm(tx) @@ -248,18 +229,18 @@ func (cc *CapabilityCache) AddCapabilities(lggr logger.Logger, chain deployment. capb := capb id, err := registry.GetHashedCapabilityId(&bind.CallOpts{}, capb.LabelledName, capb.Version) require.NoError(t, err) - out = append(out, internal.RegisteredCapability{ + out = append(out, kslib.RegisteredCapability{ CapabilitiesRegistryCapability: capb, ID: id, }) // cache the id - cc.nameToId[internal.CapabilityID(capb)] = id + cc.nameToId[kslib.CapabilityID(capb)] = id } return out } func testChain(t *testing.T) deployment.Chain { - chains, _ := memory.NewMemoryChains(t, 1, 5) + chains := memory.NewMemoryChains(t, 1) var chain deployment.Chain for _, c := range chains { chain = c @@ -269,7 +250,7 @@ func testChain(t *testing.T) deployment.Chain { return chain } -func capabilityIds(registry *capabilities_registry.CapabilitiesRegistry, rcs []internal.RegisteredCapability) ([][32]byte, error) { +func capabilityIds(registry *capabilities_registry.CapabilitiesRegistry, rcs []kslib.RegisteredCapability) ([][32]byte, error) { out := make([][32]byte, len(rcs)) for i := range rcs { id, err := registry.GetHashedCapabilityId(&bind.CallOpts{}, rcs[i].LabelledName, rcs[i].Version) @@ -281,7 +262,7 @@ func capabilityIds(registry *capabilities_registry.CapabilitiesRegistry, rcs []i return out, nil } -func mustCapabilityIds(t *testing.T, registry *capabilities_registry.CapabilitiesRegistry, rcs []internal.RegisteredCapability) [][32]byte { +func mustCapabilityIds(t *testing.T, registry *capabilities_registry.CapabilitiesRegistry, rcs []kslib.RegisteredCapability) [][32]byte { t.Helper() out, err := capabilityIds(registry, rcs) require.NoError(t, err) diff --git a/deployment/keystone/changeset/internal/testdata/testnet_wf_view.json b/deployment/keystone/changeset/internal/testdata/testnet_wf_view.json deleted file mode 100644 index 8a4162f5e58..00000000000 --- a/deployment/keystone/changeset/internal/testdata/testnet_wf_view.json +++ /dev/null @@ -1,262 +0,0 @@ -{ - "cl-keystone-one-0": { - "nodeID": "node_00", - "isBootstrap": false, - "ocrKeys": { - "aptos-testnet": { - "offchainPublicKey": "4ec55bbe76a6b1fdc885c59da85a8fe44cf06afe1e4719f0824a731937526c52", - "onchainPublicKey": "b8834eaa062f0df4ccfe7832253920071ec14dc4f78b13ecdda10b824e2dd3b6", - "peerID": "p2p_12D3KooWMWUKdoAc2ruZf9f55p7NVFj7AFiPm67xjQ8BZBwkqyYv", - "transmitAccount": " ", - "configEncryptionPublicKey": "559ea4ee5774a31d97914a4220d6a47094ae8e2cf0806e80e1eacd851f3e6757", - "keyBundleID": "b4504e84ea307cc2afffca0206bd4bf8e98acc5a03c9bd47b2456e3845a5d1fa" - }, - "ethereum-testnet-sepolia": { - "offchainPublicKey": "03dacd15fc96c965c648e3623180de002b71a97cf6eeca9affb91f461dcd6ce1", - "onchainPublicKey": "b35409a8d4f9a18da55c5b2bb08a3f5f68d44442", - "peerID": "p2p_12D3KooWMWUKdoAc2ruZf9f55p7NVFj7AFiPm67xjQ8BZBwkqyYv", - "transmitAccount": "0x2877F08d9c5Cc9F401F730Fa418fAE563A9a2FF3", - "configEncryptionPublicKey": "5193f72fc7b4323a86088fb0acb4e4494ae351920b3944bd726a59e8dbcdd45f", - "keyBundleID": "665a101d79d310cb0a5ebf695b06e8fc8082b5cbe62d7d362d80d47447a31fea" - } - }, - "payeeAddress": "", - "csaKey": "403b72f0b1b3b5f5a91bcfedb7f28599767502a04b5b7e067fcf3782e23eeb9c", - "isConnected": true, - "isEnabled": true - }, - "cl-keystone-one-1": { - "nodeID": "node_01", - "isBootstrap": false, - "ocrKeys": { - "aptos-testnet": { - "offchainPublicKey": "a38dbe521643479d78ab5477cae78161a5de0030c95098e3fbb09add6aca9508", - "onchainPublicKey": "247d0189f65f58be83a4e7d87ff338aaf8956e9acb9fcc783f34f9edc29d1b40", - "peerID": "p2p_12D3KooWCbDiL7sP9BVby5KaZqPpaVP1RBokoa9ShzH5WhkYX46v", - "transmitAccount": " ", - "configEncryptionPublicKey": "a38dbe521643479d78ab5477cae78161a5de0030c95098e3fbb09add6aca9508", - "keyBundleID": "4b6418b8ab88ea1244c3c48eb5f4c86f9f0301aebffcac4fcfac5cdfb7cf6933" - }, - "ethereum-testnet-sepolia": { - "offchainPublicKey": "255096a3b7ade10e29c648e0b407fc486180464f713446b1da04f013df6179c8", - "onchainPublicKey": "8258f4c4761cc445333017608044a204fd0c006a", - "peerID": "p2p_12D3KooWCbDiL7sP9BVby5KaZqPpaVP1RBokoa9ShzH5WhkYX46v", - "transmitAccount": "0x415aa1E9a1bcB3929ed92bFa1F9735Dc0D45AD31", - "configEncryptionPublicKey": "2c45fec2320f6bcd36444529a86d9f8b4439499a5d8272dec9bcbbebb5e1bf01", - "keyBundleID": "7a9b75510b8d09932b98142419bef52436ff725dd9395469473b487ef87fdfb0" - } - }, - "payeeAddress": "", - "csaKey": "28b91143ec9111796a7d63e14c1cf6bb01b4ed59667ab54f5bc72ebe49c881be", - "isConnected": true, - "isEnabled": true - }, - "cl-keystone-one-2": { - "nodeID": "node_MgvchYopDVSBv3BCpNgEk", - "isBootstrap": false, - "ocrKeys": { - "aptos-testnet": { - "offchainPublicKey": "450aa794c87198a595761a8c18f0f1590046c8092960036638d002256af95254", - "onchainPublicKey": "ba20d3da9b07663f1e8039081a514649fd61a48be2d241bc63537ee47d028fcd", - "peerID": "p2p_12D3KooWGDmBKZ7B3PynGrvfHTJMEecpjfHts9YK5NWk8oJuxcAo", - "transmitAccount": " ", - "configEncryptionPublicKey": "412a4bed6b064c17168871d28dbb965cc0a898f7b19eb3fa7cd01d3e3d10b66c", - "keyBundleID": "e57c608a899d80e510913d2c7ef55758ee81e9eb73eb531003af1564307fd133" - }, - "ethereum-testnet-sepolia": { - "offchainPublicKey": "dba3c61e5f8bec594be481bcaf67ecea0d1c2950edb15b158ce3dbc77877def3", - "onchainPublicKey": "d4dcc573e9d24a8b27a07bba670ba3a2ab36e5bb", - "peerID": "p2p_12D3KooWGDmBKZ7B3PynGrvfHTJMEecpjfHts9YK5NWk8oJuxcAo", - "transmitAccount": "0xCea84bC1881F3cE14BA13Dc3a00DC1Ff3D553fF0", - "configEncryptionPublicKey": "ee466234b3b2f65b13c848b17aa6a8d4e0aa0311d3bf8e77a64f20b04ed48d39", - "keyBundleID": "1d20490fe469dd6af3d418cc310a6e835181fa13e8dc80156bcbe302b7afcd34" - } - }, - "payeeAddress": "", - "csaKey": "7a166fbc816eb4a4dcb620d11c3ccac5c085d56b1972374100116f87619debb8", - "isConnected": true, - "isEnabled": true - }, - "cl-keystone-one-3": { - "nodeID": "node_Q9CZrC45VZZkMnCbDNgzH", - "isBootstrap": false, - "ocrKeys": { - "aptos-testnet": { - "offchainPublicKey": "886044b333af681ab4bf3be663122524ece9725e110ac2a64cda8526cad6983e", - "onchainPublicKey": "046faf34ebfe42510251e6098bc34fa3dd5f2de38ac07e47f2d1b34ac770639f", - "peerID": "p2p_12D3KooWCcVLytqinD8xMn27NvomcQhj2mqMVzyGemz6oPwv1SMT", - "transmitAccount": " ", - "configEncryptionPublicKey": "a7f3435bfbaabebd1572142ff1aec9ed98758d9bb098f1fcc77262fcae7f4171", - "keyBundleID": "5811a96a0c3b5f5b52973eee10e5771cf5953d37d5616ea71f7ae76f09f6e332" - }, - "ethereum-testnet-sepolia": { - "offchainPublicKey": "b4c4993d6c15fee63800db901a8b35fa419057610962caab1c1d7bed55709127", - "onchainPublicKey": "6607c140e558631407f33bafbabd103863cee876", - "peerID": "p2p_12D3KooWCcVLytqinD8xMn27NvomcQhj2mqMVzyGemz6oPwv1SMT", - "transmitAccount": "0xA9eFB53c513E413762b2Be5299D161d8E6e7278e", - "configEncryptionPublicKey": "63375a3d175364bd299e7cecf352cb3e469dd30116cf1418f2b7571fb46c4a4b", - "keyBundleID": "8843b5db0608f92dac38ca56775766a08db9ee82224a19595d04bd6c58b38fbd" - } - }, - "payeeAddress": "", - "csaKey": "487901e0c0a9d3c66e7cfc50f3a9e3cdbfdf1b0107273d73d94a91d278545516", - "isConnected": true, - "isEnabled": true - }, - "cl-keystone-one-4": { - "nodeID": "node_q9CQHG4n4QozxAz5UCufa", - "isBootstrap": false, - "ocrKeys": { - "aptos-testnet": { - "offchainPublicKey": "b34bb49788541de8b6cfb321799a41927a391a4eb135c74f6cb14eec0531ee6f", - "onchainPublicKey": "1221e131ef21014a6a99ed22376eb869746a3b5e30fd202cf79e44efaeb8c5c2", - "peerID": "p2p_12D3KooWHqR1w26yHatTSZQW3xbRct9SxWzVj9X4SpU916Hy8jYg", - "transmitAccount": " ", - "configEncryptionPublicKey": "96ae354418e50dcd5b3dae62e8f0bc911bbce7f761220837aacdaa6f82bd0f29", - "keyBundleID": "b1ab478c1322bc4f8227be50898a8044efc70cf0156ec53cf132119db7e94dea" - }, - "ethereum-testnet-sepolia": { - "offchainPublicKey": "2a4c7dec127fdd8145e48c5edb9467225098bd8c8ad1dade868325b787affbde", - "onchainPublicKey": "a6f35436cb7bffd615cc47a0a04aa0a78696a144", - "peerID": "p2p_12D3KooWHqR1w26yHatTSZQW3xbRct9SxWzVj9X4SpU916Hy8jYg", - "transmitAccount": "0x6F5cAb24Fb7412bB516b3468b9F3a9c471d25fE5", - "configEncryptionPublicKey": "c812eab2415f45cc1d2afdb2be2e3ea419bb7851acfc30c07b4df42c856e8f74", - "keyBundleID": "8e563a16ec5a802345b162d0f31149e8d5055014a31847d7b20d6de500aa48bd" - } - }, - "payeeAddress": "", - "csaKey": "07e0ffc57b6263604df517b94bd986169451a3c90600a855bb19212dc575de54", - "isConnected": true, - "isEnabled": true - }, - "cl-keystone-one-5": { - "nodeID": "node_sS3MELvKpNQBMqh7t5QL5", - "isBootstrap": false, - "ocrKeys": { - "aptos-testnet": { - "offchainPublicKey": "11674b98849d8e070ac69d37c284b3091fcd374913f52b2b83ce2d9a4a4e0213", - "onchainPublicKey": "425d1354a7b8180252a221040c718cac0ba0251c7efe31a2acefbba578dc2153", - "peerID": "p2p_12D3KooWR8d5kbZb7YiQWKpT1J1PfMqNaGAmb4jBFx9DWag4hpSZ", - "transmitAccount": " ", - "configEncryptionPublicKey": "263bee0d09d90e0e618c4cdd630d1437f7377f2d544df57f39ddd47984970555", - "keyBundleID": "44b5f46bfbb04d0984469298ec43c350ec6b2cd4556b18265ebac1b6cc329c7c" - }, - "ethereum-testnet-sepolia": { - "offchainPublicKey": "283471ed66d61fbe11f64eff65d738b59a0301c9a4f846280db26c64c9fdd3f8", - "onchainPublicKey": "657587eb55cecd6f90b97297b611c3024e488cc0", - "peerID": "p2p_12D3KooWR8d5kbZb7YiQWKpT1J1PfMqNaGAmb4jBFx9DWag4hpSZ", - "transmitAccount": "0xdAd1F3F8ec690cf335D46c50EdA5547CeF875161", - "configEncryptionPublicKey": "36de4924cf11938b4461aea1ce99cb640e9603d9a7c294ab6c54acd51d575a49", - "keyBundleID": "99fad0362cc8dc8a57a8e616e68133a6d5a8834e08a1b4819710f0e912df5abc" - } - }, - "payeeAddress": "", - "csaKey": "4542f4fd2ed150c8c976b39802fe3d994aec3ac94fd11e7817f693b1c9a1dabb", - "isConnected": true, - "isEnabled": true - }, - "cl-keystone-one-6": { - "nodeID": "node_jb1oicMu3xxx2N2e4JWvE", - "isBootstrap": false, - "ocrKeys": { - "aptos-testnet": { - "offchainPublicKey": "6fc8c3fb55b39577abbab20028bee93d1d6d8a888dd298354b95d4af3ccb6009", - "onchainPublicKey": "4a94c75cb9fe8b1fba86fd4b71ad130943281fdefad10216c46eb2285d60950f", - "peerID": "p2p_12D3KooWNJ8de3PUURZ2oucrVTpnRTqNBTUYwHLQjK9LzN3E6Mfn", - "transmitAccount": " ", - "configEncryptionPublicKey": "3ae1a1c713e4ad63f67191fd93620c9eebe44e1d5f3264036ec0fbcd59cf9664", - "keyBundleID": "b419e9e3f1256aa2907a1a396bdf27ba5002a30eee440ab96cb60369429ce277" - }, - "ethereum-testnet-sepolia": { - "offchainPublicKey": "aa3419628ea3536783742d17d8adf05681aa6a6bd2b206fbde78c7e5aa38586d", - "onchainPublicKey": "4885973b2fcf061d5cdfb8f74c5139bd3056e9da", - "peerID": "p2p_12D3KooWNJ8de3PUURZ2oucrVTpnRTqNBTUYwHLQjK9LzN3E6Mfn", - "transmitAccount": "0x19e10B063a62B1574AE19020A64fDe6419892dA6", - "configEncryptionPublicKey": "8c6c7d889ac6cc9e663ae48073bbf130fae105d6a3689636db27752e3e3e6816", - "keyBundleID": "62d36269d916b4834b17dc6d637c1c39b0895396249a0845764c898e83f63525" - } - }, - "payeeAddress": "", - "csaKey": "75ac63fc97a31e31168084e0de8ccd2bea90059b609d962f3e43fc296cdba28d", - "isConnected": true, - "isEnabled": true - }, - "cl-keystone-one-7": { - "nodeID": "node_nokJcFtJ5hunVbgLXufKn", - "isBootstrap": false, - "ocrKeys": { - "aptos-testnet": { - "offchainPublicKey": "cf0684a0e59399fe9b92cfc740d9696f925e78ee7d0273947e5f7b830070eaaa", - "onchainPublicKey": "96dc85670c49caa986de4ad288e680e9afb0f5491160dcbb4868ca718e194fc8", - "peerID": "p2p_12D3KooWQMCj73V5xmCd6C5VsJr7rbFG2TF9LwVcLiiBqXps9MgC", - "transmitAccount": " ", - "configEncryptionPublicKey": "209eea27e73b0ecc1c49b3ea274e4a18a1f5ed62fd79f443f0b5b9cc6019356e", - "keyBundleID": "14082da0f33b4cec842bc1e1002e617a194ed4a81105603bd6c1edf784aa3743" - }, - "ethereum-testnet-sepolia": { - "offchainPublicKey": "01496edce35663071d74472e02119432ba059b3904d205e4358014410e4f2be3", - "onchainPublicKey": "213803bb9f9715379aaf11aadb0212369701dc0a", - "peerID": "p2p_12D3KooWQMCj73V5xmCd6C5VsJr7rbFG2TF9LwVcLiiBqXps9MgC", - "transmitAccount": "0x9ad9f3AD49e5aB0F28bD694d211a90297bD90D7f", - "configEncryptionPublicKey": "4d2f75f98b911c20fe7808384312d8b913e6b7a98c34d05c6e461434c92b4502", - "keyBundleID": "e6d6ffec6cff01ac20d57bc42626c8e955293f232d383bf468351d867a7b8213" - } - }, - "payeeAddress": "", - "csaKey": "b473091fe1d4dbbc26ad71c67b4432f8f4280e06bab5e2122a92f4ab8b6ff2f5", - "isConnected": true, - "isEnabled": true - }, - "cl-keystone-one-8": { - "nodeID": "node_7iTc33UzaAj6XmGa5hHC9", - "isBootstrap": false, - "ocrKeys": { - "aptos-testnet": { - "offchainPublicKey": "c791d2b9d3562f991af68ab7164a19734d551a9404d91c9571fdcdc5dcb237ca", - "onchainPublicKey": "bddafb20cc50d89e0ae2f244908c27b1d639615d8186b28c357669de3359f208", - "peerID": "p2p_12D3KooWAUagqMycsro27kFznSQRHbhfCBLx8nKD4ptTiUGDe38c", - "transmitAccount": " ", - "configEncryptionPublicKey": "0874e6cd5c8e651ab0ff564a474832ed9eaf2c5025b553f908d04921d9777d50", - "keyBundleID": "6726df46033038b724a4e6371807b6aa09efc829d0a3f7a5db4fd7df4b69fea7" - }, - "ethereum-testnet-sepolia": { - "offchainPublicKey": "ad08c2a5878cada53521f4e2bb449f191ccca7899246721a0deeea19f7b83f70", - "onchainPublicKey": "8c2aa1e6fad88a6006dfb116eb866cbad2910314", - "peerID": "p2p_12D3KooWAUagqMycsro27kFznSQRHbhfCBLx8nKD4ptTiUGDe38c", - "transmitAccount": "0x31B179dcF8f9036C30f04bE578793e51bF14A39E", - "configEncryptionPublicKey": "e3d4d7a7372a3b1110db0290ab3649eb5fbb0daf6cf3ae02cfe5f367700d9264", - "keyBundleID": "be0d639de3ae3cbeaa31ca369514f748ba1d271145cba6796bcc12aace2f64c3" - } - }, - "payeeAddress": "", - "csaKey": "1141dd1e46797ced9b0fbad49115f18507f6f6e6e3cc86e7e5ba169e58645adc", - "isConnected": true, - "isEnabled": true - }, - "cl-keystone-one-9": { - "nodeID": "node_V3xAXNftjt6sxkfRgmw9J", - "isBootstrap": false, - "ocrKeys": { - "aptos-testnet": { - "offchainPublicKey": "ff1144bbf648e6f76c58d0ce53a9a2cbe9a284d52db8691a714cac8e3a96b8b4", - "onchainPublicKey": "4fa557850e4d5c21b3963c97414c1f37792700c4d3b8abdb904b765fd47e39bf", - "peerID": "p2p_12D3KooWBCMCCZZ8x57AXvJvpCujqhZzTjWXbReaRE8TxNr5dM4U", - "transmitAccount": " ", - "configEncryptionPublicKey": "6a1f37f06833c55ecf46233439ea6179a835bac6f2b2dee725b747c121813149", - "keyBundleID": "d834cf7c830df7510228b33b138c018ff16b4eecf82273ed3bcd862bbbc046d4" - }, - "ethereum-testnet-sepolia": { - "offchainPublicKey": "c805572b813a072067eab2087ddbee8aa719090e12890b15c01094f0d3f74a5f", - "onchainPublicKey": "679296b7c1eb4948efcc87efc550940a182e610c", - "peerID": "p2p_12D3KooWBCMCCZZ8x57AXvJvpCujqhZzTjWXbReaRE8TxNr5dM4U", - "transmitAccount": "0x0b04cE574E80Da73191Ec141c0016a54A6404056", - "configEncryptionPublicKey": "09fced0207611ed618bf0759ab128d9797e15b18e46436be1a56a91e4043ec0e", - "keyBundleID": "1c28e76d180d1ed1524e61845fa58a384415de7e51017edf1f8c553e28357772" - } - }, - "payeeAddress": "", - "csaKey": "412dc6fe48ea4e34baaa77da2e3b032d39b938597b6f3d61fe7ed183a827a431", - "isConnected": true, - "isEnabled": true - } -} \ No newline at end of file diff --git a/deployment/keystone/changeset/internal/types.go b/deployment/keystone/changeset/internal/types.go deleted file mode 100644 index 173e3ba1ad0..00000000000 --- a/deployment/keystone/changeset/internal/types.go +++ /dev/null @@ -1,348 +0,0 @@ -package internal - -import ( - "errors" - "fmt" - "slices" - "sort" - "strconv" - "strings" - - "github.com/ethereum/go-ethereum/common" - - chainsel "github.com/smartcontractkit/chain-selectors" - - "github.com/smartcontractkit/chainlink/deployment" - - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry_1_1_0" - kcr "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry_1_1_0" - "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/p2pkey" -) - -var ( - CapabilitiesRegistry deployment.ContractType = "CapabilitiesRegistry" // https://github.com/smartcontractkit/chainlink/blob/50c1b3dbf31bd145b312739b08967600a5c67f30/contracts/src/v0.8/keystone/CapabilitiesRegistry.sol#L392 - WorkflowRegistry deployment.ContractType = "WorkflowRegistry" // https://github.com/smartcontractkit/chainlink/blob/develop/contracts/src/v0.8/workflow/dev/WorkflowRegistry.sol - KeystoneForwarder deployment.ContractType = "KeystoneForwarder" // https://github.com/smartcontractkit/chainlink/blob/50c1b3dbf31bd145b312739b08967600a5c67f30/contracts/src/v0.8/keystone/KeystoneForwarder.sol#L90 - OCR3Capability deployment.ContractType = "OCR3Capability" // https://github.com/smartcontractkit/chainlink/blob/50c1b3dbf31bd145b312739b08967600a5c67f30/contracts/src/v0.8/keystone/OCR3Capability.sol#L12 - FeedConsumer deployment.ContractType = "FeedConsumer" // no type and a version in contract https://github.com/smartcontractkit/chainlink/blob/89183a8a5d22b1aeca0ade3b76d16aa84067aa57/contracts/src/v0.8/keystone/KeystoneFeedsConsumer.sol#L1 - RBACTimelock deployment.ContractType = "RBACTimelock" // no type and a version in contract https://github.com/smartcontractkit/ccip-owner-contracts/blob/main/src/RBACTimelock.sol - ProposerManyChainMultiSig deployment.ContractType = "ProposerManyChainMultiSig" // no type and a version in contract https://github.com/smartcontractkit/ccip-owner-contracts/blob/main/src/ManyChainMultiSig.sol -) - -type DeployResponse struct { - Address common.Address - Tx common.Hash // todo: chain agnostic - Tv deployment.TypeAndVersion -} - -type DeployRequest struct { - Chain deployment.Chain -} - -type DonNode struct { - Don string - Node string // not unique across environments -} - -type CapabilityHost struct { - NodeID string // globally unique - Capabilities []capabilities_registry.CapabilitiesRegistryCapability -} - -type Nop struct { - capabilities_registry.CapabilitiesRegistryNodeOperator - NodeIDs []string // nodes run by this operator -} - -func toNodeKeys(o *deployment.Node, registryChainSel uint64) NodeKeys { - var aptosOcr2KeyBundleId string - var aptosOnchainPublicKey string - var aptosCC *deployment.OCRConfig - for details, cfg := range o.SelToOCRConfig { - if family, err := chainsel.GetSelectorFamily(details.ChainSelector); err == nil && family == chainsel.FamilyAptos { - aptosCC = &cfg - break - } - } - if aptosCC != nil { - aptosOcr2KeyBundleId = aptosCC.KeyBundleID - aptosOnchainPublicKey = fmt.Sprintf("%x", aptosCC.OnchainPublicKey[:]) - } - registryChainID, err := chainsel.ChainIdFromSelector(registryChainSel) - if err != nil { - panic(err) - } - registryChainDetails, err := chainsel.GetChainDetailsByChainIDAndFamily(strconv.Itoa(int(registryChainID)), chainsel.FamilyEVM) - if err != nil { - panic(err) - } - evmCC := o.SelToOCRConfig[registryChainDetails] - return NodeKeys{ - EthAddress: string(evmCC.TransmitAccount), - P2PPeerID: strings.TrimPrefix(o.PeerID.String(), "p2p_"), - OCR2BundleID: evmCC.KeyBundleID, - OCR2OffchainPublicKey: fmt.Sprintf("%x", evmCC.OffchainPublicKey[:]), - OCR2OnchainPublicKey: fmt.Sprintf("%x", evmCC.OnchainPublicKey[:]), - OCR2ConfigPublicKey: fmt.Sprintf("%x", evmCC.ConfigEncryptionPublicKey[:]), - CSAPublicKey: o.CSAKey, - // default value of encryption public key is the CSA public key - // TODO: DEVSVCS-760 - EncryptionPublicKey: strings.TrimPrefix(o.CSAKey, "csa_"), - // TODO Aptos support. How will that be modeled in clo data? - // TODO: AptosAccount is unset but probably unused - AptosBundleID: aptosOcr2KeyBundleId, - AptosOnchainPublicKey: aptosOnchainPublicKey, - } -} -func makeNodeKeysSlice(nodes []deployment.Node, registryChainSel uint64) []NodeKeys { - var out []NodeKeys - for _, n := range nodes { - out = append(out, toNodeKeys(&n, registryChainSel)) - } - return out -} - -type NOP struct { - Name string - Nodes []string // peerID -} - -func (v NOP) Validate() error { - if v.Name == "" { - return errors.New("name is empty") - } - if len(v.Nodes) == 0 { - return errors.New("no nodes") - } - for i, n := range v.Nodes { - _, err := p2pkey.MakePeerID(n) - if err != nil { - return fmt.Errorf("failed to nop %s: node %d is not valid peer id %s: %w", v.Name, i, n, err) - } - } - - return nil -} - -// DonCapabilities is a set of capabilities hosted by a set of node operators -// in is in a convenient form to handle the CLO representation of the nop data -type DonCapabilities struct { - Name string - F uint8 - Nops []NOP - Capabilities []kcr.CapabilitiesRegistryCapability // every capability is hosted on each nop -} - -func (v DonCapabilities) Validate() error { - if v.Name == "" { - return errors.New("name is empty") - } - if len(v.Nops) == 0 { - return errors.New("no nops") - } - for i, n := range v.Nops { - if err := n.Validate(); err != nil { - return fmt.Errorf("failed to validate nop %d '%s': %w", i, n.Name, err) - } - } - if len(v.Capabilities) == 0 { - return errors.New("no capabilities") - } - return nil -} - -func NodeOperator(name string, adminAddress string) capabilities_registry.CapabilitiesRegistryNodeOperator { - return capabilities_registry.CapabilitiesRegistryNodeOperator{ - Name: name, - Admin: adminAddr(adminAddress), - } -} - -func nopsToNodes(donInfos []DonInfo, dons []DonCapabilities, chainSelector uint64) (map[capabilities_registry.CapabilitiesRegistryNodeOperator][]string, error) { - out := make(map[capabilities_registry.CapabilitiesRegistryNodeOperator][]string) - for _, don := range dons { - for _, nop := range don.Nops { - idx := slices.IndexFunc(donInfos, func(donInfo DonInfo) bool { - return donInfo.Name == don.Name - }) - if idx < 0 { - return nil, fmt.Errorf("couldn't find donInfo for %v", don.Name) - } - donInfo := donInfos[idx] - idx = slices.IndexFunc(donInfo.Nodes, func(node deployment.Node) bool { - return node.PeerID.String() == nop.Nodes[0] - }) - if idx < 0 { - return nil, fmt.Errorf("couldn't find node with p2p_id '%v'", nop.Nodes[0]) - } - node := donInfo.Nodes[idx] - a := node.AdminAddr - nodeOperator := NodeOperator(nop.Name, a) - for _, node := range nop.Nodes { - idx = slices.IndexFunc(donInfo.Nodes, func(n deployment.Node) bool { - return n.PeerID.String() == node - }) - if idx < 0 { - return nil, fmt.Errorf("couldn't find node with p2p_id '%v'", node) - } - out[nodeOperator] = append(out[nodeOperator], donInfo.Nodes[idx].NodeID) - } - } - } - - return out, nil -} - -// mapDonsToCaps converts a list of DonCapabilities to a map of don name to capabilities -func mapDonsToCaps(dons []DonInfo) map[string][]kcr.CapabilitiesRegistryCapability { - out := make(map[string][]kcr.CapabilitiesRegistryCapability) - for _, don := range dons { - out[don.Name] = don.Capabilities - } - return out -} - -// mapDonsToNodes returns a map of don name to simplified representation of their nodes -// all nodes must have evm config and ocr3 capability nodes are must also have an aptos chain config -func mapDonsToNodes(dons []DonInfo, excludeBootstraps bool, registryChainSel uint64) (map[string][]deployment.Node, error) { - donToNodes := make(map[string][]deployment.Node) - // get the nodes for each don from the offchain client, get ocr2 config from one of the chain configs for the node b/c - // they are equivalent - - for _, don := range dons { - for _, node := range don.Nodes { - if excludeBootstraps && node.IsBootstrap { - continue - } - if _, ok := donToNodes[don.Name]; !ok { - donToNodes[don.Name] = make([]deployment.Node, 0) - } - donToNodes[don.Name] = append(donToNodes[don.Name], node) - } - } - - return donToNodes, nil -} - -// RegisteredDon is a representation of a don that exists in the in the capabilities registry all with the enriched node data -type RegisteredDon struct { - Name string - Info capabilities_registry.CapabilitiesRegistryDONInfo - Nodes []deployment.Node -} - -type RegisteredDonConfig struct { - Name string - NodeIDs []string // ids in the offchain client - RegistryChainSel uint64 -} - -func NewRegisteredDon(env deployment.Environment, cfg RegisteredDonConfig) (*RegisteredDon, error) { - // load the don info from the capabilities registry - r, err := GetContractSets(env.Logger, &GetContractSetsRequest{ - Chains: env.Chains, - AddressBook: env.ExistingAddresses, - }) - if err != nil { - return nil, fmt.Errorf("failed to get contract sets: %w", err) - } - capReg := r.ContractSets[cfg.RegistryChainSel].CapabilitiesRegistry - - di, err := capReg.GetDONs(nil) - if err != nil { - return nil, fmt.Errorf("failed to get dons: %w", err) - } - // load the nodes from the offchain client - nodes, err := deployment.NodeInfo(cfg.NodeIDs, env.Offchain) - if err != nil { - return nil, fmt.Errorf("failed to get node info: %w", err) - } - want := sortedHash(nodes.PeerIDs()) - var don *kcr.CapabilitiesRegistryDONInfo - for i, d := range di { - got := sortedHash(d.NodeP2PIds) - if got == want { - don = &di[i] - } - } - if don == nil { - return nil, fmt.Errorf("don not found in registry") - } - return &RegisteredDon{ - Name: cfg.Name, - Info: *don, - Nodes: nodes, - }, nil -} - -func (d RegisteredDon) Signers(chainFamily string) []common.Address { - sort.Slice(d.Nodes, func(i, j int) bool { - return d.Nodes[i].PeerID.String() < d.Nodes[j].PeerID.String() - }) - var out []common.Address - for _, n := range d.Nodes { - if n.IsBootstrap { - continue - } - var found bool - var registryChainDetails chainsel.ChainDetails - for details, _ := range n.SelToOCRConfig { - if family, err := chainsel.GetSelectorFamily(details.ChainSelector); err == nil && family == chainFamily { - found = true - registryChainDetails = details - - } - } - if !found { - panic(fmt.Sprintf("chainType not found: %v", chainFamily)) - } - // eth address is the first 20 bytes of the Signer - config, exists := n.SelToOCRConfig[registryChainDetails] - if !exists { - panic(fmt.Sprintf("chainID not found: %v", registryChainDetails)) - } - signer := config.OnchainPublicKey - signerAddress := common.BytesToAddress(signer) - out = append(out, signerAddress) - } - return out -} - -func joinInfoAndNodes(donInfos map[string]kcr.CapabilitiesRegistryDONInfo, dons []DonInfo, registryChainSel uint64) ([]RegisteredDon, error) { - // all maps should have the same keys - nodes, err := mapDonsToNodes(dons, true, registryChainSel) - if err != nil { - return nil, fmt.Errorf("failed to map dons to capabilities: %w", err) - } - if len(donInfos) != len(nodes) { - return nil, fmt.Errorf("mismatched lengths don infos %d, nodes %d", len(donInfos), len(nodes)) - } - var out []RegisteredDon - for donName, info := range donInfos { - - ocr2nodes, ok := nodes[donName] - if !ok { - return nil, fmt.Errorf("nodes not found for don %s", donName) - } - out = append(out, RegisteredDon{ - Name: donName, - Info: info, - Nodes: ocr2nodes, - }) - } - - return out, nil -} - -var emptyAddr = "0x0000000000000000000000000000000000000000" - -// compute the admin address from the string. If the address is empty, replaces the 0s with fs -// contract registry disallows 0x0 as an admin address, but our test net nops use it -func adminAddr(addr string) common.Address { - needsFixing := addr == emptyAddr - addr = strings.TrimPrefix(addr, "0x") - if needsFixing { - addr = strings.ReplaceAll(addr, "0", "f") - } - return common.HexToAddress(strings.TrimPrefix(addr, "0x")) -} diff --git a/deployment/keystone/changeset/internal/types_test.go b/deployment/keystone/changeset/internal/types_test.go deleted file mode 100644 index cfc953d6126..00000000000 --- a/deployment/keystone/changeset/internal/types_test.go +++ /dev/null @@ -1,78 +0,0 @@ -package internal - -import ( - "encoding/hex" - "fmt" - "math/big" - "strconv" - "strings" - "testing" - - "github.com/ethereum/go-ethereum/common" - chainsel "github.com/smartcontractkit/chain-selectors" - "github.com/smartcontractkit/chainlink/deployment" - "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/p2pkey" - "github.com/smartcontractkit/libocr/offchainreporting2plus/types" - "github.com/stretchr/testify/require" -) - -func Test_toNodeKeys(t *testing.T) { - registryChainSel := chainsel.TEST_90000001 - registryChainID, err := chainsel.ChainIdFromSelector(registryChainSel.Selector) - if err != nil { - panic(err) - } - registryChainDetails, err := chainsel.GetChainDetailsByChainIDAndFamily(strconv.Itoa(int(registryChainID)), chainsel.FamilyEVM) - if err != nil { - panic(err) - } - aptosChainDetails, err := chainsel.GetChainDetailsByChainIDAndFamily(strconv.Itoa(int(1)), chainsel.FamilyAptos) - if err != nil { - panic(err) - } - - p2pID := p2pkey.MustNewV2XXXTestingOnly(big.NewInt(100)) - pubKey_1 := "11114981a6119ca3f932cdb8c402d71a72d672adae7849f581ecff8b8e1098e7" // valid csa key - signing_1 := common.Hex2Bytes("11117293a4Cc2621b61193135a95928735e4795f") // valid eth address - admin_1 := common.HexToAddress("0x1111567890123456789012345678901234567890") // valid eth address - signing_2 := common.Hex2Bytes("eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee") // valid key - var encryptionpubkey [32]byte - if _, err := hex.Decode(encryptionpubkey[:], []byte(pubKey_1)); err != nil { - panic(fmt.Sprintf("failed to decode pubkey %s: %v", encryptionpubkey, err)) - } - keys := toNodeKeys(&deployment.Node{ - NodeID: "p2p_123", - Name: "node 1", - PeerID: p2pID.PeerID(), - CSAKey: pubKey_1, - AdminAddr: admin_1.String(), - SelToOCRConfig: map[chainsel.ChainDetails]deployment.OCRConfig{ - registryChainDetails: { - OffchainPublicKey: types.OffchainPublicKey(common.FromHex("1111111111111111111111111111111111111111111111111111111111111111")), - OnchainPublicKey: signing_1[:], - PeerID: p2pID.PeerID(), - TransmitAccount: types.Account(admin_1.String()), - ConfigEncryptionPublicKey: encryptionpubkey, - KeyBundleID: "abcd", - }, - aptosChainDetails: { - TransmitAccount: "ff", - OnchainPublicKey: signing_2, - KeyBundleID: "aptos", - }, - }, - }, registryChainSel.Selector) - - require.Equal(t, NodeKeys{ - EthAddress: admin_1.String(), - AptosBundleID: "aptos", - AptosOnchainPublicKey: hex.EncodeToString(signing_2), - P2PPeerID: strings.TrimPrefix(p2pID.PeerID().String(), "p2p_"), - OCR2BundleID: "abcd", - OCR2OnchainPublicKey: hex.EncodeToString(signing_1), - OCR2OffchainPublicKey: "1111111111111111111111111111111111111111111111111111111111111111", - OCR2ConfigPublicKey: pubKey_1, - CSAPublicKey: pubKey_1, - EncryptionPublicKey: pubKey_1, - }, keys) -} diff --git a/deployment/keystone/changeset/internal/update_don.go b/deployment/keystone/changeset/internal/update_don.go index 3cfc386b2ba..4883368dc4d 100644 --- a/deployment/keystone/changeset/internal/update_don.go +++ b/deployment/keystone/changeset/internal/update_don.go @@ -6,18 +6,17 @@ import ( "encoding/hex" "encoding/json" "fmt" - "math/big" "sort" "github.com/ethereum/go-ethereum/accounts/abi/bind" - "github.com/smartcontractkit/ccip-owner-contracts/pkg/proposal/mcms" - "github.com/smartcontractkit/ccip-owner-contracts/pkg/proposal/timelock" "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink/deployment" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/p2pkey" "google.golang.org/protobuf/proto" - kcr "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry_1_1_0" + kcr "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry" + + kslib "github.com/smartcontractkit/chainlink/deployment/keystone" ) // CapabilityConfig is a struct that holds a capability and its configuration @@ -27,21 +26,18 @@ type CapabilityConfig struct { } type UpdateDonRequest struct { - Chain deployment.Chain - ContractSet *ContractSet // contract set for the given chain + Registry *kcr.CapabilitiesRegistry + Chain deployment.Chain P2PIDs []p2pkey.PeerID // this is the unique identifier for the don CapabilityConfigs []CapabilityConfig // if Config subfield is nil, a default config is used - - UseMCMS bool } -func (r *UpdateDonRequest) AppendNodeCapabilitiesRequest() *AppendNodeCapabilitiesRequest { +func (r *UpdateDonRequest) appendNodeCapabilitiesRequest() *AppendNodeCapabilitiesRequest { out := &AppendNodeCapabilitiesRequest{ Chain: r.Chain, - ContractSet: r.ContractSet, + Registry: r.Registry, P2pToCapabilities: make(map[p2pkey.PeerID][]kcr.CapabilitiesRegistryCapability), - UseMCMS: r.UseMCMS, } for _, p2pid := range r.P2PIDs { if _, exists := out.P2pToCapabilities[p2pid]; !exists { @@ -55,7 +51,7 @@ func (r *UpdateDonRequest) AppendNodeCapabilitiesRequest() *AppendNodeCapabiliti } func (r *UpdateDonRequest) Validate() error { - if r.ContractSet.CapabilitiesRegistry == nil { + if r.Registry == nil { return fmt.Errorf("registry is required") } if len(r.P2PIDs) == 0 { @@ -66,7 +62,6 @@ func (r *UpdateDonRequest) Validate() error { type UpdateDonResponse struct { DonInfo kcr.CapabilitiesRegistryDONInfo - Ops *timelock.BatchChainOperation } func UpdateDon(lggr logger.Logger, req *UpdateDonRequest) (*UpdateDonResponse, error) { @@ -74,8 +69,7 @@ func UpdateDon(lggr logger.Logger, req *UpdateDonRequest) (*UpdateDonResponse, e return nil, fmt.Errorf("failed to validate request: %w", err) } - registry := req.ContractSet.CapabilitiesRegistry - getDonsResp, err := registry.GetDONs(&bind.CallOpts{}) + getDonsResp, err := req.Registry.GetDONs(&bind.CallOpts{}) if err != nil { return nil, fmt.Errorf("failed to get Dons: %w", err) } @@ -84,42 +78,29 @@ func UpdateDon(lggr logger.Logger, req *UpdateDonRequest) (*UpdateDonResponse, e if err != nil { return nil, fmt.Errorf("failed to lookup don by p2pIDs: %w", err) } - cfgs, err := computeConfigs(registry, req.CapabilityConfigs, don) + cfgs, err := computeConfigs(req.Registry, req.CapabilityConfigs, don) if err != nil { return nil, fmt.Errorf("failed to compute configs: %w", err) } - txOpts := req.Chain.DeployerKey - if req.UseMCMS { - txOpts = deployment.SimTransactOpts() + _, err = AppendNodeCapabilitiesImpl(lggr, req.appendNodeCapabilitiesRequest()) + if err != nil { + return nil, fmt.Errorf("failed to append node capabilities: %w", err) } - tx, err := registry.UpdateDON(txOpts, don.Id, don.NodeP2PIds, cfgs, don.IsPublic, don.F) + + tx, err := req.Registry.UpdateDON(req.Chain.DeployerKey, don.Id, don.NodeP2PIds, cfgs, don.IsPublic, don.F) if err != nil { - err = deployment.DecodeErr(kcr.CapabilitiesRegistryABI, err) + err = kslib.DecodeErr(kcr.CapabilitiesRegistryABI, err) return nil, fmt.Errorf("failed to call UpdateDON: %w", err) } - var ops *timelock.BatchChainOperation - if !req.UseMCMS { - _, err = req.Chain.Confirm(tx) - if err != nil { - return nil, fmt.Errorf("failed to confirm UpdateDON transaction %s: %w", tx.Hash().String(), err) - } - } else { - ops = &timelock.BatchChainOperation{ - ChainIdentifier: mcms.ChainIdentifier(req.Chain.Selector), - Batch: []mcms.Operation{ - { - To: registry.Address(), - Data: tx.Data(), - Value: big.NewInt(0), - }, - }, - } - } + _, err = req.Chain.Confirm(tx) + if err != nil { + return nil, fmt.Errorf("failed to confirm UpdateDON transaction %s: %w", tx.Hash().String(), err) + } out := don out.CapabilityConfigurations = cfgs - return &UpdateDonResponse{DonInfo: out, Ops: ops}, nil + return &UpdateDonResponse{DonInfo: out}, nil } func PeerIDsToBytes(p2pIDs []p2pkey.PeerID) [][32]byte { @@ -148,7 +129,7 @@ func computeConfigs(registry *kcr.CapabilitiesRegistry, caps []CapabilityConfig, } out[i].CapabilityId = id if out[i].Config == nil { - c := DefaultCapConfig(cap.Capability.CapabilityType, int(donInfo.F)) + c := kslib.DefaultCapConfig(cap.Capability.CapabilityType, int(donInfo.F)) cb, err := proto.Marshal(c) if err != nil { return nil, fmt.Errorf("failed to marshal capability config for %v: %w", c, err) diff --git a/deployment/keystone/changeset/internal/update_don_test.go b/deployment/keystone/changeset/internal/update_don_test.go index 57b15138538..12ccfe290b1 100644 --- a/deployment/keystone/changeset/internal/update_don_test.go +++ b/deployment/keystone/changeset/internal/update_don_test.go @@ -2,32 +2,29 @@ package internal_test import ( "bytes" - "encoding/hex" - "fmt" "math/big" "sort" - "strconv" "testing" "github.com/ethereum/go-ethereum/common" chainsel "github.com/smartcontractkit/chain-selectors" "github.com/smartcontractkit/chainlink-common/pkg/logger" + nodev1 "github.com/smartcontractkit/chainlink-protos/job-distributor/v1/node" "github.com/smartcontractkit/chainlink/deployment" + "github.com/smartcontractkit/chainlink/deployment/keystone" + kslib "github.com/smartcontractkit/chainlink/deployment/keystone" kscs "github.com/smartcontractkit/chainlink/deployment/keystone/changeset" "github.com/smartcontractkit/chainlink/deployment/keystone/changeset/internal" kstest "github.com/smartcontractkit/chainlink/deployment/keystone/changeset/internal/test" - kcr "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry_1_1_0" + kcr "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/p2pkey" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) -var ( - registryChain = chainsel.TEST_90000001 -) - func TestUpdateDon(t *testing.T) { var ( + registryChain = chainsel.TEST_90000001 // nodes p2p_1 = p2pkey.MustNewV2XXXTestingOnly(big.NewInt(100)) pubKey_1 = "11114981a6119ca3f932cdb8c402d71a72d672adae7849f581ecff8b8e1098e7" // valid csa key @@ -81,13 +78,13 @@ func TestUpdateDon(t *testing.T) { admin: admin_4, }) // capabilities - initialCap = kcr.CapabilitiesRegistryCapability{ + cap_A = kcr.CapabilitiesRegistryCapability{ LabelledName: "test", Version: "1.0.0", CapabilityType: 0, } - capToAdd = kcr.CapabilitiesRegistryCapability{ + cap_B = kcr.CapabilitiesRegistryCapability{ LabelledName: "cap b", Version: "1.0.0", CapabilityType: 1, @@ -98,41 +95,29 @@ func TestUpdateDon(t *testing.T) { t.Run("empty", func(t *testing.T) { cfg := setupUpdateDonTestConfig{ - dons: []internal.DonInfo{ + dons: []kslib.DonInfo{ { Name: "don 1", - Nodes: []deployment.Node{node_1, node_2, node_3, node_4}, - Capabilities: []kcr.CapabilitiesRegistryCapability{initialCap}, + Nodes: []keystone.Node{node_1, node_2, node_3, node_4}, + Capabilities: []kcr.CapabilitiesRegistryCapability{cap_A}, }, }, - nops: []internal.NOP{ + nops: []keystone.NOP{ { Name: "nop 1", - Nodes: []string{node_1.NodeID, node_2.NodeID, node_3.NodeID, node_4.NodeID}, + Nodes: []string{node_1.ID, node_2.ID, node_3.ID, node_4.ID}, }, }, } - testCfg := registerTestDon(t, lggr, cfg) - // add the new capabilities to registry - m := make(map[p2pkey.PeerID][]kcr.CapabilitiesRegistryCapability) - for _, node := range cfg.dons[0].Nodes { - m[node.PeerID] = append(m[node.PeerID], capToAdd) - } - - _, err := internal.AppendNodeCapabilitiesImpl(lggr, &internal.AppendNodeCapabilitiesRequest{ - Chain: testCfg.Chain, - ContractSet: testCfg.ContractSet, - P2pToCapabilities: m, - }) - require.NoError(t, err) + testCfg := setupUpdateDonTest(t, lggr, cfg) req := &internal.UpdateDonRequest{ - ContractSet: testCfg.ContractSet, - Chain: testCfg.Chain, - P2PIDs: []p2pkey.PeerID{p2p_1.PeerID(), p2p_2.PeerID(), p2p_3.PeerID(), p2p_4.PeerID()}, + Registry: testCfg.Registry, + Chain: testCfg.Chain, + P2PIDs: []p2pkey.PeerID{p2p_1.PeerID(), p2p_2.PeerID(), p2p_3.PeerID(), p2p_4.PeerID()}, CapabilityConfigs: []internal.CapabilityConfig{ - {Capability: initialCap}, {Capability: capToAdd}, + {Capability: cap_A}, {Capability: cap_B}, }, } want := &internal.UpdateDonResponse{ @@ -141,8 +126,8 @@ func TestUpdateDon(t *testing.T) { ConfigCount: 1, NodeP2PIds: internal.PeerIDsToBytes([]p2pkey.PeerID{p2p_1.PeerID(), p2p_2.PeerID(), p2p_3.PeerID(), p2p_4.PeerID()}), CapabilityConfigurations: []kcr.CapabilitiesRegistryCapabilityConfiguration{ - {CapabilityId: kstest.MustCapabilityId(t, testCfg.Registry, initialCap)}, - {CapabilityId: kstest.MustCapabilityId(t, testCfg.Registry, capToAdd)}, + {CapabilityId: kstest.MustCapabilityId(t, testCfg.Registry, cap_A)}, + {CapabilityId: kstest.MustCapabilityId(t, testCfg.Registry, cap_B)}, }, }, } @@ -185,44 +170,35 @@ type minimalNodeCfg struct { admin common.Address } -func newNode(t *testing.T, cfg minimalNodeCfg) deployment.Node { +func newNode(t *testing.T, cfg minimalNodeCfg) keystone.Node { t.Helper() - registryChainID, err := chainsel.ChainIdFromSelector(registryChain.Selector) - if err != nil { - panic(err) - } - registryChainDetails, err := chainsel.GetChainDetailsByChainIDAndFamily(strconv.Itoa(int(registryChainID)), chainsel.FamilyEVM) - if err != nil { - panic(err) - } - - signingAddr, err := hex.DecodeString(cfg.signingAddr) - require.NoError(t, err) - - var pubkey [32]byte - if _, err := hex.Decode(pubkey[:], []byte(cfg.pubKey)); err != nil { - panic(fmt.Sprintf("failed to decode pubkey %s: %v", pubkey, err)) - } - - return deployment.Node{ - NodeID: cfg.id, - PeerID: cfg.p2p.PeerID(), - CSAKey: cfg.pubKey, - AdminAddr: cfg.admin.String(), - SelToOCRConfig: map[chainsel.ChainDetails]deployment.OCRConfig{ - registryChainDetails: { - OnchainPublicKey: signingAddr, - PeerID: cfg.p2p.PeerID(), - ConfigEncryptionPublicKey: pubkey, + return keystone.Node{ + ID: cfg.id, + PublicKey: &cfg.pubKey, + ChainConfigs: []*nodev1.ChainConfig{ + { + Chain: &nodev1.Chain{ + Id: "test chain", + Type: nodev1.ChainType_CHAIN_TYPE_EVM, + }, + AdminAddress: cfg.admin.String(), + Ocr2Config: &nodev1.OCR2Config{ + P2PKeyBundle: &nodev1.OCR2Config_P2PKeyBundle{ + PeerId: cfg.p2p.PeerID().String(), + }, + OcrKeyBundle: &nodev1.OCR2Config_OCRKeyBundle{ + OnchainSigningAddress: cfg.signingAddr, + }, + }, }, }, } } type setupUpdateDonTestConfig struct { - dons []internal.DonInfo - nops []internal.NOP + dons []kslib.DonInfo + nops []keystone.NOP } type setupUpdateDonTestResult struct { @@ -230,19 +206,18 @@ type setupUpdateDonTestResult struct { chain deployment.Chain } -func registerTestDon(t *testing.T, lggr logger.Logger, cfg setupUpdateDonTestConfig) *kstest.SetupTestRegistryResponse { +func setupUpdateDonTest(t *testing.T, lggr logger.Logger, cfg setupUpdateDonTestConfig) *kstest.SetupTestRegistryResponse { t.Helper() req := newSetupTestRegistryRequest(t, cfg.dons, cfg.nops) return kstest.SetupTestRegistry(t, lggr, req) - } -func newSetupTestRegistryRequest(t *testing.T, dons []internal.DonInfo, nops []internal.NOP) *kstest.SetupTestRegistryRequest { +func newSetupTestRegistryRequest(t *testing.T, dons []kslib.DonInfo, nops []keystone.NOP) *kstest.SetupTestRegistryRequest { t.Helper() - nodes := make(map[string]deployment.Node) + nodes := make(map[string]keystone.Node) for _, don := range dons { for _, node := range don.Nodes { - nodes[node.NodeID] = node + nodes[node.ID] = node } } nopsToNodes := makeNopToNodes(t, nops, nodes) @@ -256,7 +231,7 @@ func newSetupTestRegistryRequest(t *testing.T, dons []internal.DonInfo, nops []i return req } -func makeNopToNodes(t *testing.T, nops []internal.NOP, nodes map[string]deployment.Node) map[kcr.CapabilitiesRegistryNodeOperator][]*internal.P2PSignerEnc { +func makeNopToNodes(t *testing.T, nops []keystone.NOP, nodes map[string]keystone.Node) map[kcr.CapabilitiesRegistryNodeOperator][]*internal.P2PSignerEnc { nopToNodes := make(map[kcr.CapabilitiesRegistryNodeOperator][]*internal.P2PSignerEnc) for _, nop := range nops { @@ -264,15 +239,15 @@ func makeNopToNodes(t *testing.T, nops []internal.NOP, nodes map[string]deployme // so we can just use the first one crnop := kcr.CapabilitiesRegistryNodeOperator{ Name: nop.Name, - Admin: common.HexToAddress(nodes[nop.Nodes[0]].AdminAddr), + Admin: common.HexToAddress(nodes[nop.Nodes[0]].ChainConfigs[0].AdminAddress), } var signers []*internal.P2PSignerEnc for _, nodeID := range nop.Nodes { node := nodes[nodeID] - require.NotNil(t, node.CSAKey, "public key is nil %s", node.NodeID) + require.NotNil(t, node.PublicKey, "public key is nil %s", node.ID) // all chain configs are the same wrt admin address & node keys - p, err := kscs.NewP2PSignerEnc(&node, registryChain.Selector) - require.NoError(t, err, "failed to make p2p signer enc from clo nod %s", node.NodeID) + p, err := kscs.NewP2PSignerEncFromJD(node.ChainConfigs[0], *node.PublicKey) + require.NoError(t, err, "failed to make p2p signer enc from clo nod %s", node.ID) signers = append(signers, p) } nopToNodes[crnop] = signers @@ -280,13 +255,13 @@ func makeNopToNodes(t *testing.T, nops []internal.NOP, nodes map[string]deployme return nopToNodes } -func makeP2PToCapabilities(t *testing.T, dons []internal.DonInfo) map[p2pkey.PeerID][]kcr.CapabilitiesRegistryCapability { +func makeP2PToCapabilities(t *testing.T, dons []kslib.DonInfo) map[p2pkey.PeerID][]kcr.CapabilitiesRegistryCapability { p2pToCapabilities := make(map[p2pkey.PeerID][]kcr.CapabilitiesRegistryCapability) for _, don := range dons { for _, node := range don.Nodes { for _, cap := range don.Capabilities { - p, err := kscs.NewP2PSignerEnc(&node, registryChain.Selector) - require.NoError(t, err, "failed to make p2p signer enc from clo nod %s", node.NodeID) + p, err := kscs.NewP2PSignerEncFromJD(node.ChainConfigs[0], *node.PublicKey) + require.NoError(t, err, "failed to make p2p signer enc from clo nod %s", node.ID) p2pToCapabilities[p.P2PKey] = append(p2pToCapabilities[p.P2PKey], cap) } } @@ -294,7 +269,7 @@ func makeP2PToCapabilities(t *testing.T, dons []internal.DonInfo) map[p2pkey.Pee return p2pToCapabilities } -func makeTestDon(t *testing.T, dons []internal.DonInfo) []kstest.Don { +func makeTestDon(t *testing.T, dons []kslib.DonInfo) []kstest.Don { out := make([]kstest.Don, len(dons)) for i, don := range dons { out[i] = testDon(t, don) @@ -302,13 +277,13 @@ func makeTestDon(t *testing.T, dons []internal.DonInfo) []kstest.Don { return out } -func testDon(t *testing.T, don internal.DonInfo) kstest.Don { +func testDon(t *testing.T, don kslib.DonInfo) kstest.Don { var p2pids []p2pkey.PeerID for _, node := range don.Nodes { // all chain configs are the same wrt admin address & node keys // so we can just use the first one - p, err := kscs.NewP2PSignerEnc(&node, registryChain.Selector) - require.NoError(t, err, "failed to make p2p signer enc from clo nod %s", node.NodeID) + p, err := kscs.NewP2PSignerEncFromJD(node.ChainConfigs[0], *node.PublicKey) + require.NoError(t, err, "failed to make p2p signer enc from clo nod %s", node.ID) p2pids = append(p2pids, p.P2PKey) } @@ -324,3 +299,11 @@ func testDon(t *testing.T, don internal.DonInfo) kstest.Don { CapabilityConfigs: capabilityConfigs, } } + +func newP2PSignerEnc(signer [32]byte, p2pkey p2pkey.PeerID, encryptionPublicKey [32]byte) *internal.P2PSignerEnc { + return &internal.P2PSignerEnc{ + Signer: signer, + P2PKey: p2pkey, + EncryptionPublicKey: encryptionPublicKey, + } +} diff --git a/deployment/keystone/changeset/internal/update_node_capabilities.go b/deployment/keystone/changeset/internal/update_node_capabilities.go index 16c37267060..0420c46f27d 100644 --- a/deployment/keystone/changeset/internal/update_node_capabilities.go +++ b/deployment/keystone/changeset/internal/update_node_capabilities.go @@ -5,23 +5,23 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink/deployment" - kcr "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry_1_1_0" + kslib "github.com/smartcontractkit/chainlink/deployment/keystone" + kcr "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/p2pkey" ) type UpdateNodeCapabilitiesImplRequest struct { - Chain deployment.Chain - ContractSet *ContractSet - P2pToCapabilities map[p2pkey.PeerID][]kcr.CapabilitiesRegistryCapability + Chain deployment.Chain + Registry *kcr.CapabilitiesRegistry - UseMCMS bool + P2pToCapabilities map[p2pkey.PeerID][]kcr.CapabilitiesRegistryCapability } func (req *UpdateNodeCapabilitiesImplRequest) Validate() error { if len(req.P2pToCapabilities) == 0 { return fmt.Errorf("p2pToCapabilities is empty") } - if req.ContractSet == nil { + if req.Registry == nil { return fmt.Errorf("registry is nil") } @@ -37,7 +37,7 @@ func UpdateNodeCapabilitiesImpl(lggr logger.Logger, req *UpdateNodeCapabilitiesI for _, cap := range req.P2pToCapabilities { capabilities = append(capabilities, cap...) } - op, err := AddCapabilities(lggr, req.ContractSet, req.Chain, capabilities, req.UseMCMS) + err := kslib.AddCapabilities(lggr, req.Registry, req.Chain, capabilities) if err != nil { return nil, fmt.Errorf("failed to add capabilities: %w", err) } @@ -49,10 +49,8 @@ func UpdateNodeCapabilitiesImpl(lggr logger.Logger, req *UpdateNodeCapabilitiesI updateNodesReq := &UpdateNodesRequest{ Chain: req.Chain, + Registry: req.Registry, P2pToUpdates: p2pToUpdates, - ContractSet: req.ContractSet, - Ops: op, - UseMCMS: req.UseMCMS, } resp, err := UpdateNodes(lggr, updateNodesReq) if err != nil { diff --git a/deployment/keystone/changeset/internal/update_node_capabilities_test.go b/deployment/keystone/changeset/internal/update_node_capabilities_test.go index 65da264dd01..0346ff20dd6 100644 --- a/deployment/keystone/changeset/internal/update_node_capabilities_test.go +++ b/deployment/keystone/changeset/internal/update_node_capabilities_test.go @@ -8,9 +8,9 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink/deployment" - "github.com/smartcontractkit/chainlink/deployment/keystone/changeset/internal" + kslib "github.com/smartcontractkit/chainlink/deployment/keystone/changeset/internal" kstest "github.com/smartcontractkit/chainlink/deployment/keystone/changeset/internal/test" - kcr "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry_1_1_0" + kcr "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/p2pkey" ) @@ -25,9 +25,9 @@ func TestUpdateNodeCapabilities(t *testing.T) { }, }, } - nopToNodes = map[kcr.CapabilitiesRegistryNodeOperator][]*internal.P2PSignerEnc{ - testNop(t, "testNop"): []*internal.P2PSignerEnc{ - &internal.P2PSignerEnc{ + nopToNodes = map[kcr.CapabilitiesRegistryNodeOperator][]*kslib.P2PSignerEnc{ + testNop(t, "testNop"): []*kslib.P2PSignerEnc{ + &kslib.P2PSignerEnc{ Signer: [32]byte{0: 1}, P2PKey: testPeerID(t, "0x1"), EncryptionPublicKey: [32]byte{3: 16, 4: 2}, @@ -40,7 +40,7 @@ func TestUpdateNodeCapabilities(t *testing.T) { type args struct { lggr logger.Logger - req *internal.UpdateNodeCapabilitiesImplRequest // chain and registry are set in the test setup + req *kslib.UpdateNodeCapabilitiesImplRequest // chain and registry are set in the test setup initialState *kstest.SetupTestRegistryRequest } tests := []struct { @@ -53,7 +53,7 @@ func TestUpdateNodeCapabilities(t *testing.T) { name: "invalid request", args: args{ lggr: lggr, - req: &internal.UpdateNodeCapabilitiesImplRequest{ + req: &kslib.UpdateNodeCapabilitiesImplRequest{ Chain: deployment.Chain{}, }, initialState: &kstest.SetupTestRegistryRequest{}, @@ -68,7 +68,7 @@ func TestUpdateNodeCapabilities(t *testing.T) { P2pToCapabilities: initialp2pToCapabilities, NopToNodes: nopToNodes, }, - req: &internal.UpdateNodeCapabilitiesImplRequest{ + req: &kslib.UpdateNodeCapabilitiesImplRequest{ P2pToCapabilities: map[p2pkey.PeerID][]kcr.CapabilitiesRegistryCapability{ testPeerID(t, "0x1"): []kcr.CapabilitiesRegistryCapability{ { @@ -92,10 +92,10 @@ func TestUpdateNodeCapabilities(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { setupResp := kstest.SetupTestRegistry(t, lggr, tt.args.initialState) + tt.args.req.Registry = setupResp.Registry tt.args.req.Chain = setupResp.Chain - tt.args.req.ContractSet = setupResp.ContractSet - got, err := internal.UpdateNodeCapabilitiesImpl(tt.args.lggr, tt.args.req) + got, err := kslib.UpdateNodeCapabilitiesImpl(tt.args.lggr, tt.args.req) if (err != nil) != tt.wantErr { t.Errorf("UpdateNodeCapabilities() error = %v, wantErr %v", err, tt.wantErr) return diff --git a/deployment/keystone/changeset/internal/update_nodes.go b/deployment/keystone/changeset/internal/update_nodes.go index b27c17ad19f..b8a08c37e50 100644 --- a/deployment/keystone/changeset/internal/update_nodes.go +++ b/deployment/keystone/changeset/internal/update_nodes.go @@ -5,18 +5,16 @@ import ( "encoding/hex" "errors" "fmt" - "math/big" "sort" "github.com/ethereum/go-ethereum/accounts/abi/bind" - "github.com/smartcontractkit/ccip-owner-contracts/pkg/proposal/mcms" - "github.com/smartcontractkit/ccip-owner-contracts/pkg/proposal/timelock" "github.com/smartcontractkit/chainlink-common/pkg/logger" - kcr "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry_1_1_0" + kcr "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/p2pkey" "github.com/smartcontractkit/chainlink/deployment" + kslib "github.com/smartcontractkit/chainlink/deployment/keystone" ) type NodeUpdate struct { @@ -28,19 +26,14 @@ type NodeUpdate struct { } type UpdateNodesRequest struct { - Chain deployment.Chain - ContractSet *ContractSet // contract set for the given chain + Chain deployment.Chain + Registry *kcr.CapabilitiesRegistry P2pToUpdates map[p2pkey.PeerID]NodeUpdate - - UseMCMS bool - // If UseMCMS is true, and Ops is not nil then the UpdateNodes contract operation - // will be added to the Ops.Batch - Ops *timelock.BatchChainOperation } func (req *UpdateNodesRequest) NodeParams() ([]kcr.CapabilitiesRegistryNodeParams, error) { - return makeNodeParams(req.ContractSet.CapabilitiesRegistry, req.P2pToUpdates) + return makeNodeParams(req.Registry, req.P2pToUpdates) } // P2PSignerEnc represent the key fields in kcr.CapabilitiesRegistryNodeParams @@ -59,7 +52,7 @@ func (req *UpdateNodesRequest) Validate() error { for peer, updates := range req.P2pToUpdates { seen := make(map[string]struct{}) for _, cap := range updates.Capabilities { - id := CapabilityID(cap) + id := kslib.CapabilityID(cap) if _, exists := seen[id]; exists { return fmt.Errorf("duplicate capability %s for %s", id, peer) } @@ -78,7 +71,7 @@ func (req *UpdateNodesRequest) Validate() error { } } - if req.ContractSet.CapabilitiesRegistry == nil { + if req.Registry == nil { return errors.New("registry is nil") } @@ -87,14 +80,10 @@ func (req *UpdateNodesRequest) Validate() error { type UpdateNodesResponse struct { NodeParams []kcr.CapabilitiesRegistryNodeParams - // MCMS operation to update the nodes - // The operation is added to the Batch of the given Ops if not nil - Ops *timelock.BatchChainOperation } // UpdateNodes updates the nodes in the registry -// the update sets the signer and capabilities for each node. -// The nodes and capabilities must already exist in the registry. +// the update sets the signer and capabilities for each node. it does not append capabilities to the existing ones func UpdateNodes(lggr logger.Logger, req *UpdateNodesRequest) (*UpdateNodesResponse, error) { if err := req.Validate(); err != nil { return nil, fmt.Errorf("failed to validate request: %w", err) @@ -102,46 +91,20 @@ func UpdateNodes(lggr logger.Logger, req *UpdateNodesRequest) (*UpdateNodesRespo params, err := req.NodeParams() if err != nil { - err = deployment.DecodeErr(kcr.CapabilitiesRegistryABI, err) + err = kslib.DecodeErr(kcr.CapabilitiesRegistryABI, err) return nil, fmt.Errorf("failed to make node params: %w", err) } - txOpts := req.Chain.DeployerKey - if req.UseMCMS { - txOpts = deployment.SimTransactOpts() - } - registry := req.ContractSet.CapabilitiesRegistry - tx, err := registry.UpdateNodes(txOpts, params) + tx, err := req.Registry.UpdateNodes(req.Chain.DeployerKey, params) if err != nil { - err = deployment.DecodeErr(kcr.CapabilitiesRegistryABI, err) + err = kslib.DecodeErr(kcr.CapabilitiesRegistryABI, err) return nil, fmt.Errorf("failed to call UpdateNodes: %w", err) } - ops := req.Ops - if !req.UseMCMS { - _, err = req.Chain.Confirm(tx) - if err != nil { - return nil, fmt.Errorf("failed to confirm UpdateNodes confirm transaction %s: %w", tx.Hash().String(), err) - } - } else { - op := mcms.Operation{ - To: registry.Address(), - Data: tx.Data(), - Value: big.NewInt(0), - } - - if ops == nil { - ops = &timelock.BatchChainOperation{ - ChainIdentifier: mcms.ChainIdentifier(req.Chain.Selector), - Batch: []mcms.Operation{ - op, - }, - } - } else { - ops.Batch = append(ops.Batch, op) - } + _, err = req.Chain.Confirm(tx) + if err != nil { + return nil, fmt.Errorf("failed to confirm UpdateNodes confirm transaction %s: %w", tx.Hash().String(), err) } - - return &UpdateNodesResponse{NodeParams: params, Ops: ops}, nil + return &UpdateNodesResponse{NodeParams: params}, nil } // AppendCapabilities appends the capabilities to the existing capabilities of the nodes listed in p2pIds in the registry @@ -182,8 +145,8 @@ func AppendCapabilities(lggr logger.Logger, registry *kcr.CapabilitiesRegistry, var deduped []kcr.CapabilitiesRegistryCapability seen := make(map[string]struct{}) for _, cap := range mergedCaps { - if _, ok := seen[CapabilityID(cap)]; !ok { - seen[CapabilityID(cap)] = struct{}{} + if _, ok := seen[kslib.CapabilityID(cap)]; !ok { + seen[kslib.CapabilityID(cap)] = struct{}{} deduped = append(deduped, cap) } } @@ -203,7 +166,7 @@ func makeNodeParams(registry *kcr.CapabilitiesRegistry, nodes, err := registry.GetNodesByP2PIds(&bind.CallOpts{}, PeerIDsToBytes(p2pIds)) if err != nil { - err = deployment.DecodeErr(kcr.CapabilitiesRegistryABI, err) + err = kslib.DecodeErr(kcr.CapabilitiesRegistryABI, err) return nil, fmt.Errorf("failed to get nodes by p2p ids: %w", err) } for _, node := range nodes { @@ -260,11 +223,11 @@ func makeNodeParams(registry *kcr.CapabilitiesRegistry, } -// fetchCapabilityIDs fetches the capability ids for the given capabilities +// fetchkslib.CapabilityIDs fetches the capability ids for the given capabilities func fetchCapabilityIDs(registry *kcr.CapabilitiesRegistry, caps []kcr.CapabilitiesRegistryCapability) (map[string][32]byte, error) { out := make(map[string][32]byte) for _, cap := range caps { - name := CapabilityID(cap) + name := kslib.CapabilityID(cap) if _, exists := out[name]; exists { continue } diff --git a/deployment/keystone/changeset/internal/update_nodes_test.go b/deployment/keystone/changeset/internal/update_nodes_test.go index 0f22120998a..395f1060465 100644 --- a/deployment/keystone/changeset/internal/update_nodes_test.go +++ b/deployment/keystone/changeset/internal/update_nodes_test.go @@ -14,13 +14,13 @@ import ( "github.com/stretchr/testify/require" "github.com/smartcontractkit/chainlink-common/pkg/logger" - "github.com/smartcontractkit/chainlink/deployment" - "github.com/smartcontractkit/chainlink/deployment/keystone/changeset/internal" + kslib "github.com/smartcontractkit/chainlink/deployment/keystone" + internal "github.com/smartcontractkit/chainlink/deployment/keystone/changeset/internal" kstest "github.com/smartcontractkit/chainlink/deployment/keystone/changeset/internal/test" "github.com/smartcontractkit/chainlink/deployment/environment/memory" - kcr "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry_1_1_0" + kcr "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/p2pkey" ) @@ -29,7 +29,7 @@ func Test_UpdateNodesRequest_validate(t *testing.T) { p2pToUpdates map[p2pkey.PeerID]internal.NodeUpdate nopToNodes map[kcr.CapabilitiesRegistryNodeOperator][]*internal.P2PSignerEnc chain deployment.Chain - contractSet *internal.ContractSet + registry *kcr.CapabilitiesRegistry } tests := []struct { name string @@ -42,7 +42,7 @@ func Test_UpdateNodesRequest_validate(t *testing.T) { p2pToUpdates: map[p2pkey.PeerID]internal.NodeUpdate{}, nopToNodes: nil, chain: deployment.Chain{}, - contractSet: nil, + registry: nil, }, wantErr: true, }, @@ -54,9 +54,9 @@ func Test_UpdateNodesRequest_validate(t *testing.T) { EncryptionPublicKey: "jk", }, }, - nopToNodes: nil, - chain: deployment.Chain{}, - contractSet: nil, + nopToNodes: nil, + chain: deployment.Chain{}, + registry: nil, }, wantErr: true, }, @@ -68,9 +68,9 @@ func Test_UpdateNodesRequest_validate(t *testing.T) { EncryptionPublicKey: "aabb", }, }, - nopToNodes: nil, - chain: deployment.Chain{}, - contractSet: nil, + nopToNodes: nil, + chain: deployment.Chain{}, + registry: nil, }, wantErr: true, }, @@ -80,7 +80,7 @@ func Test_UpdateNodesRequest_validate(t *testing.T) { req := &internal.UpdateNodesRequest{ P2pToUpdates: tt.fields.p2pToUpdates, Chain: tt.fields.chain, - ContractSet: tt.fields.contractSet, + Registry: tt.fields.registry, } if err := req.Validate(); (err != nil) != tt.wantErr { t.Errorf("internal.UpdateNodesRequest.validate() error = %v, wantErr %v", err, tt.wantErr) @@ -129,7 +129,8 @@ func TestUpdateNodes(t *testing.T) { }, }, }, - Chain: chain, + Chain: chain, + Registry: nil, // set in test to ensure no conflicts }, nopsToNodes: map[kcr.CapabilitiesRegistryNodeOperator][]*internal.P2PSignerEnc{ testNop(t, "nop1"): []*internal.P2PSignerEnc{ @@ -175,7 +176,8 @@ func TestUpdateNodes(t *testing.T) { }, }, }, - Chain: chain, + Chain: chain, + Registry: nil, // set in test to ensure no conflicts }, nopsToNodes: map[kcr.CapabilitiesRegistryNodeOperator][]*internal.P2PSignerEnc{ testNop(t, "nop1"): []*internal.P2PSignerEnc{ @@ -232,7 +234,8 @@ func TestUpdateNodes(t *testing.T) { }, }, }, - Chain: chain, + Chain: chain, + Registry: nil, // set in test to ensure no conflicts }, nopsToNodes: map[kcr.CapabilitiesRegistryNodeOperator][]*internal.P2PSignerEnc{ testNop(t, "nopA"): []*internal.P2PSignerEnc{ @@ -296,7 +299,8 @@ func TestUpdateNodes(t *testing.T) { }, }, }, - Chain: chain, + Chain: chain, + Registry: nil, // set in test to ensure no conflicts }, nopsToNodes: map[kcr.CapabilitiesRegistryNodeOperator][]*internal.P2PSignerEnc{ testNop(t, "nopA"): []*internal.P2PSignerEnc{ @@ -345,8 +349,8 @@ func TestUpdateNodes(t *testing.T) { EncryptionPublicKey: newKeyStr, }, }, - Chain: chain, - ContractSet: nil, // set in test to ensure no conflicts + Chain: chain, + Registry: nil, // set in test to ensure no conflicts }, nopsToNodes: map[kcr.CapabilitiesRegistryNodeOperator][]*internal.P2PSignerEnc{ testNop(t, "nop1"): []*internal.P2PSignerEnc{ @@ -380,8 +384,8 @@ func TestUpdateNodes(t *testing.T) { Signer: [32]byte{0: 2, 1: 3}, }, }, - Chain: chain, - ContractSet: nil, // set in test to ensure no conflicts + Chain: chain, + Registry: nil, // set in test to ensure no conflicts }, nopsToNodes: map[kcr.CapabilitiesRegistryNodeOperator][]*internal.P2PSignerEnc{ testNop(t, "nop1"): []*internal.P2PSignerEnc{ @@ -415,7 +419,8 @@ func TestUpdateNodes(t *testing.T) { NodeOperatorID: 2, }, }, - Chain: chain, + Chain: chain, + Registry: nil, // set in test to ensure no conflicts }, nopsToNodes: map[kcr.CapabilitiesRegistryNodeOperator][]*internal.P2PSignerEnc{ testNop(t, "nop1"): []*internal.P2PSignerEnc{ @@ -457,21 +462,21 @@ func TestUpdateNodes(t *testing.T) { NopToNodes: tt.args.nopsToNodes, }) registry := setupResp.Registry - tt.args.req.ContractSet = setupResp.ContractSet + tt.args.req.Registry = setupResp.Registry tt.args.req.Chain = setupResp.Chain id, err := registry.GetHashedCapabilityId(&bind.CallOpts{}, phonyCap.LabelledName, phonyCap.Version) require.NoError(t, err) // register the capabilities that the Update will use - expectedUpdatedCaps := make(map[p2pkey.PeerID][]internal.RegisteredCapability) + expectedUpdatedCaps := make(map[p2pkey.PeerID][]kslib.RegisteredCapability) capCache := kstest.NewCapabiltyCache(t) for p2p, update := range tt.args.req.P2pToUpdates { if len(update.Capabilities) > 0 { expectedCaps := capCache.AddCapabilities(tt.args.lggr, tt.args.req.Chain, registry, update.Capabilities) expectedUpdatedCaps[p2p] = expectedCaps } else { - expectedUpdatedCaps[p2p] = []internal.RegisteredCapability{ + expectedUpdatedCaps[p2p] = []kslib.RegisteredCapability{ {CapabilitiesRegistryCapability: phonyCap, ID: id}, } } @@ -563,7 +568,7 @@ func TestUpdateNodes(t *testing.T) { toRegister := p2pToCapabilitiesUpdated[testPeerID(t, "peerID_1")] tx, err := registry.AddCapabilities(chain.DeployerKey, toRegister) if err != nil { - err2 := deployment.DecodeErr(kcr.CapabilitiesRegistryABI, err) + err2 := kslib.DecodeErr(kcr.CapabilitiesRegistryABI, err) require.Fail(t, fmt.Sprintf("failed to call AddCapabilities: %s: %s", err, err2)) } _, err = chain.Confirm(tx) @@ -575,8 +580,8 @@ func TestUpdateNodes(t *testing.T) { Capabilities: toRegister, }, }, - Chain: chain, - ContractSet: setupResp.ContractSet, + Chain: chain, + Registry: registry, } _, err = internal.UpdateNodes(lggr, req) require.NoError(t, err) @@ -653,7 +658,7 @@ func TestAppendCapabilities(t *testing.T) { wantCaps = append(wantCaps, newCaps...) for i, got := range gotCaps { - assert.Equal(t, internal.CapabilityID(wantCaps[i]), internal.CapabilityID(got)) + assert.Equal(t, kslib.CapabilityID(wantCaps[i]), kslib.CapabilityID(got)) } // trying to append an existing capability should not change the result @@ -674,7 +679,7 @@ func testPeerID(t *testing.T, s string) p2pkey.PeerID { } func testChain(t *testing.T) deployment.Chain { - chains, _ := memory.NewMemoryChains(t, 1, 5) + chains := memory.NewMemoryChains(t, 1) var chain deployment.Chain for _, c := range chains { chain = c diff --git a/deployment/keystone/changeset/test/helpers.go b/deployment/keystone/changeset/test/helpers.go deleted file mode 100644 index 5ddaeda524e..00000000000 --- a/deployment/keystone/changeset/test/helpers.go +++ /dev/null @@ -1,391 +0,0 @@ -package test - -import ( - "bytes" - "context" - "crypto/sha256" - "encoding/hex" - "errors" - "math" - "sort" - "testing" - - "github.com/stretchr/testify/require" - "go.uber.org/zap/zapcore" - "golang.org/x/exp/maps" - - "github.com/smartcontractkit/chainlink-common/pkg/logger" - "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" - - "github.com/smartcontractkit/chainlink/deployment" - commonchangeset "github.com/smartcontractkit/chainlink/deployment/common/changeset" - "github.com/smartcontractkit/chainlink/deployment/common/proposalutils" - commontypes "github.com/smartcontractkit/chainlink/deployment/common/types" - "github.com/smartcontractkit/chainlink/deployment/environment/memory" - kschangeset "github.com/smartcontractkit/chainlink/deployment/keystone/changeset" - "github.com/smartcontractkit/chainlink/deployment/keystone/changeset/internal" - "github.com/smartcontractkit/chainlink/deployment/keystone/changeset/workflowregistry" - kcr "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry_1_1_0" - "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/p2pkey" -) - -type DonConfig struct { - N int -} - -func (c DonConfig) Validate() error { - if c.N < 4 { - return errors.New("N must be at least 4") - } - return nil -} - -// TODO: separate the config into different types; wf should expand to types of ocr keybundles; writer to target chains; ... -type WFDonConfig = DonConfig -type AssetDonConfig = DonConfig -type WriterDonConfig = DonConfig - -type TestConfig struct { - WFDonConfig - AssetDonConfig - WriterDonConfig - NumChains int - - UseMCMS bool -} - -func (c TestConfig) Validate() error { - if err := c.WFDonConfig.Validate(); err != nil { - return err - } - if err := c.AssetDonConfig.Validate(); err != nil { - return err - } - if err := c.WriterDonConfig.Validate(); err != nil { - return err - } - if c.NumChains < 1 { - return errors.New("NumChains must be at least 1") - } - return nil -} - -type TestEnv struct { - t *testing.T - Env deployment.Environment - RegistrySelector uint64 - - WFNodes map[string]memory.Node - CWNodes map[string]memory.Node - AssetNodes map[string]memory.Node -} - -func (te TestEnv) ContractSets() map[uint64]internal.ContractSet { - r, err := internal.GetContractSets(te.Env.Logger, &internal.GetContractSetsRequest{ - Chains: te.Env.Chains, - AddressBook: te.Env.ExistingAddresses, - }) - require.NoError(te.t, err) - return r.ContractSets -} - -// SetupTestEnv sets up a keystone test environment with the given configuration -// TODO: make more configurable; eg many tests don't need all the nodes (like when testing a registry change) -func SetupTestEnv(t *testing.T, c TestConfig) TestEnv { - require.NoError(t, c.Validate()) - lggr := logger.Test(t) - ctx := tests.Context(t) - chains, _ := memory.NewMemoryChains(t, c.NumChains, 1) - registryChainSel := registryChain(t, chains) - // note that all the nodes require TOML configuration of the cap registry address - // and writers need forwarder address as TOML config - // we choose to use changesets to deploy the initial contracts because that's how it's done in the real world - // this requires a initial environment to house the address book - e := deployment.Environment{ - Logger: lggr, - Chains: chains, - ExistingAddresses: deployment.NewMemoryAddressBook(), - } - e, err := commonchangeset.ApplyChangesets(t, e, nil, []commonchangeset.ChangesetApplication{ - { - Changeset: commonchangeset.WrapChangeSet(kschangeset.DeployCapabilityRegistry), - Config: registryChainSel, - }, - { - Changeset: commonchangeset.WrapChangeSet(kschangeset.DeployOCR3), - Config: registryChainSel, - }, - { - Changeset: commonchangeset.WrapChangeSet(kschangeset.DeployForwarder), - Config: kschangeset.DeployForwarderRequest{}, - }, - { - Changeset: commonchangeset.WrapChangeSet(workflowregistry.Deploy), - Config: registryChainSel, - }, - }) - require.NoError(t, err) - require.NotNil(t, e) - require.Len(t, e.Chains, c.NumChains) - validateInitialChainState(t, e, registryChainSel) - // now that we have the initial contracts deployed, we can configure the nodes with the addresses - // TODO: configure the nodes with the correct override functions - crConfig := deployment.CapabilityRegistryConfig{ - EVMChainID: registryChainSel, - Contract: [20]byte{}, - } - - wfChains := map[uint64]deployment.Chain{} - wfChains[registryChainSel] = chains[registryChainSel] - wfNodes := memory.NewNodes(t, zapcore.InfoLevel, wfChains, c.WFDonConfig.N, 0, crConfig) - require.Len(t, wfNodes, c.WFDonConfig.N) - - writerChains := map[uint64]deployment.Chain{} - maps.Copy(writerChains, chains) - cwNodes := memory.NewNodes(t, zapcore.InfoLevel, writerChains, c.WriterDonConfig.N, 0, crConfig) - require.Len(t, cwNodes, c.WriterDonConfig.N) - - assetChains := map[uint64]deployment.Chain{} - assetChains[registryChainSel] = chains[registryChainSel] - assetNodes := memory.NewNodes(t, zapcore.InfoLevel, assetChains, c.AssetDonConfig.N, 0, crConfig) - require.Len(t, assetNodes, c.AssetDonConfig.N) - - // TODO: partition nodes into multiple nops - - wfDon := internal.DonCapabilities{ - Name: internal.WFDonName, - Nops: []internal.NOP{ - { - Name: "nop 1", - Nodes: maps.Keys(wfNodes), - }, - }, - Capabilities: []kcr.CapabilitiesRegistryCapability{internal.OCR3Cap}, - } - cwDon := internal.DonCapabilities{ - Name: internal.TargetDonName, - Nops: []internal.NOP{ - { - Name: "nop 2", - Nodes: maps.Keys(cwNodes), - }, - }, - Capabilities: []kcr.CapabilitiesRegistryCapability{internal.WriteChainCap}, - } - assetDon := internal.DonCapabilities{ - Name: internal.StreamDonName, - Nops: []internal.NOP{ - { - Name: "nop 3", - Nodes: maps.Keys(assetNodes), - }, - }, - Capabilities: []kcr.CapabilitiesRegistryCapability{internal.StreamTriggerCap}, - } - - allChains := make(map[uint64]deployment.Chain) - maps.Copy(allChains, chains) - - allNodes := make(map[string]memory.Node) - maps.Copy(allNodes, wfNodes) - maps.Copy(allNodes, cwNodes) - maps.Copy(allNodes, assetNodes) - env := memory.NewMemoryEnvironmentFromChainsNodes(func() context.Context { return ctx }, lggr, allChains, allNodes) - // set the env addresses to the deployed addresses that were created prior to configuring the nodes - err = env.ExistingAddresses.Merge(e.ExistingAddresses) - require.NoError(t, err) - - var ocr3Config = internal.OracleConfig{ - MaxFaultyOracles: len(wfNodes) / 3, - } - var allDons = []internal.DonCapabilities{wfDon, cwDon, assetDon} - - csOut, err := kschangeset.ConfigureInitialContractsChangeset(env, kschangeset.InitialContractsCfg{ - RegistryChainSel: registryChainSel, - Dons: allDons, - OCR3Config: &ocr3Config, - }) - require.NoError(t, err) - require.Nil(t, csOut.AddressBook, "no new addresses should be created in configure initial contracts") - - req := &internal.GetContractSetsRequest{ - Chains: env.Chains, - AddressBook: env.ExistingAddresses, - } - - contractSetsResp, err := internal.GetContractSets(lggr, req) - require.NoError(t, err) - require.Len(t, contractSetsResp.ContractSets, len(env.Chains)) - // check the registry - gotRegistry := contractSetsResp.ContractSets[registryChainSel].CapabilitiesRegistry - require.NotNil(t, gotRegistry) - // validate the registry - // check the nodes - gotNodes, err := gotRegistry.GetNodes(nil) - require.NoError(t, err) - require.Len(t, gotNodes, len(allNodes)) - validateNodes(t, gotRegistry, wfNodes, expectedHashedCapabilities(t, gotRegistry, wfDon)) - validateNodes(t, gotRegistry, cwNodes, expectedHashedCapabilities(t, gotRegistry, cwDon)) - validateNodes(t, gotRegistry, assetNodes, expectedHashedCapabilities(t, gotRegistry, assetDon)) - - // check the dons - validateDon(t, gotRegistry, wfNodes, wfDon) - validateDon(t, gotRegistry, cwNodes, cwDon) - validateDon(t, gotRegistry, assetNodes, assetDon) - - if c.UseMCMS { - // deploy, configure and xfer ownership of MCMS on all chains - timelockCfgs := make(map[uint64]commontypes.MCMSWithTimelockConfig) - for sel := range env.Chains { - t.Logf("Enabling MCMS on chain %d", sel) - timelockCfgs[sel] = proposalutils.SingleGroupTimelockConfig(t) - } - env, err = commonchangeset.ApplyChangesets(t, env, nil, []commonchangeset.ChangesetApplication{ - { - Changeset: commonchangeset.WrapChangeSet(commonchangeset.DeployMCMSWithTimelock), - Config: timelockCfgs, - }, - }) - require.NoError(t, err) - // extract the MCMS address - r, err := internal.GetContractSets(lggr, &internal.GetContractSetsRequest{ - Chains: env.Chains, - AddressBook: env.ExistingAddresses, - }) - require.NoError(t, err) - for sel := range env.Chains { - mcms := r.ContractSets[sel].MCMSWithTimelockState - require.NotNil(t, mcms, "MCMS not found on chain %d", sel) - require.NoError(t, mcms.Validate()) - - // transfer ownership of all contracts to the MCMS - env, err = commonchangeset.ApplyChangesets(t, env, map[uint64]*proposalutils.TimelockExecutionContracts{sel: {Timelock: mcms.Timelock, CallProxy: mcms.CallProxy}}, []commonchangeset.ChangesetApplication{ - { - Changeset: commonchangeset.WrapChangeSet(kschangeset.AcceptAllOwnershipsProposal), - Config: &kschangeset.AcceptAllOwnershipRequest{ - ChainSelector: sel, - MinDelay: 0, - }, - }, - }) - require.NoError(t, err) - } - } - return TestEnv{ - t: t, - Env: env, - RegistrySelector: registryChainSel, - WFNodes: wfNodes, - CWNodes: cwNodes, - AssetNodes: assetNodes, - } -} - -func registryChain(t *testing.T, chains map[uint64]deployment.Chain) uint64 { - var registryChainSel uint64 = math.MaxUint64 - for sel := range chains { - if sel < registryChainSel { - registryChainSel = sel - } - } - return registryChainSel -} - -// validateInitialChainState checks that the initial chain state -// has the expected contracts deployed -func validateInitialChainState(t *testing.T, env deployment.Environment, registryChainSel uint64) { - ad := env.ExistingAddresses - // all contracts on registry chain - registryChainAddrs, err := ad.AddressesForChain(registryChainSel) - require.NoError(t, err) - require.Len(t, registryChainAddrs, 4) // registry, ocr3, forwarder, workflowRegistry - // only forwarder on non-home chain - for sel := range env.Chains { - chainAddrs, err := ad.AddressesForChain(sel) - require.NoError(t, err) - if sel != registryChainSel { - require.Len(t, chainAddrs, 1) - } else { - require.Len(t, chainAddrs, 4) - } - containsForwarder := false - for _, tv := range chainAddrs { - if tv.Type == internal.KeystoneForwarder { - containsForwarder = true - break - } - } - require.True(t, containsForwarder, "no forwarder found in %v on chain %d for target don", chainAddrs, sel) - } -} - -// validateNodes checks that the nodes exist and have the expected capabilities -func validateNodes(t *testing.T, gotRegistry *kcr.CapabilitiesRegistry, nodes map[string]memory.Node, expectedHashedCaps [][32]byte) { - gotNodes, err := gotRegistry.GetNodesByP2PIds(nil, p2pIDs(t, maps.Keys(nodes))) - require.NoError(t, err) - require.Len(t, gotNodes, len(nodes)) - for _, n := range gotNodes { - require.Equal(t, expectedHashedCaps, n.HashedCapabilityIds) - } -} - -// validateDon checks that the don exists and has the expected capabilities -func validateDon(t *testing.T, gotRegistry *kcr.CapabilitiesRegistry, nodes map[string]memory.Node, don internal.DonCapabilities) { - gotDons, err := gotRegistry.GetDONs(nil) - require.NoError(t, err) - wantP2PID := sortedHash(p2pIDs(t, maps.Keys(nodes))) - found := false - for _, have := range gotDons { - gotP2PID := sortedHash(have.NodeP2PIds) - if gotP2PID == wantP2PID { - found = true - gotCapIDs := capIDs(t, have.CapabilityConfigurations) - require.Equal(t, expectedHashedCapabilities(t, gotRegistry, don), gotCapIDs) - break - } - } - require.True(t, found, "don not found in registry") -} - -func capIDs(t *testing.T, cfgs []kcr.CapabilitiesRegistryCapabilityConfiguration) [][32]byte { - var out [][32]byte - for _, cfg := range cfgs { - out = append(out, cfg.CapabilityId) - } - return out -} - -func ptr[T any](t T) *T { - return &t -} - -func p2pIDs(t *testing.T, vals []string) [][32]byte { - var out [][32]byte - for _, v := range vals { - id, err := p2pkey.MakePeerID(v) - require.NoError(t, err) - out = append(out, id) - } - return out -} - -func expectedHashedCapabilities(t *testing.T, registry *kcr.CapabilitiesRegistry, don internal.DonCapabilities) [][32]byte { - out := make([][32]byte, len(don.Capabilities)) - var err error - for i, cap := range don.Capabilities { - out[i], err = registry.GetHashedCapabilityId(nil, cap.LabelledName, cap.Version) - require.NoError(t, err) - } - return out -} - -func sortedHash(p2pids [][32]byte) string { - sha256Hash := sha256.New() - sort.Slice(p2pids, func(i, j int) bool { - return bytes.Compare(p2pids[i][:], p2pids[j][:]) < 0 - }) - for _, id := range p2pids { - sha256Hash.Write(id[:]) - } - return hex.EncodeToString(sha256Hash.Sum(nil)) -} diff --git a/deployment/keystone/changeset/test/helpers_test.go b/deployment/keystone/changeset/test/helpers_test.go deleted file mode 100644 index 2d06e087db0..00000000000 --- a/deployment/keystone/changeset/test/helpers_test.go +++ /dev/null @@ -1,34 +0,0 @@ -package test - -import ( - "fmt" - "testing" - - "github.com/stretchr/testify/require" - - "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" - "github.com/smartcontractkit/chainlink-protos/job-distributor/v1/node" -) - -func TestSetupTestEnv(t *testing.T) { - t.Parallel() - ctx := tests.Context(t) - for _, useMCMS := range []bool{true, false} { - te := SetupTestEnv(t, TestConfig{ - WFDonConfig: DonConfig{N: 4}, - AssetDonConfig: DonConfig{N: 4}, - WriterDonConfig: DonConfig{N: 4}, - NumChains: 3, - UseMCMS: useMCMS, - }) - t.Run(fmt.Sprintf("set up test env using MCMS: %t", useMCMS), func(t *testing.T) { - require.NotNil(t, te.Env.ExistingAddresses) - require.Len(t, te.Env.Chains, 3) - require.NotEmpty(t, te.RegistrySelector) - require.NotNil(t, te.Env.Offchain) - r, err := te.Env.Offchain.ListNodes(ctx, &node.ListNodesRequest{}) - require.NoError(t, err) - require.Len(t, r.Nodes, 12) - }) - } -} diff --git a/deployment/keystone/changeset/types.go b/deployment/keystone/changeset/types.go new file mode 100644 index 00000000000..fb609041792 --- /dev/null +++ b/deployment/keystone/changeset/types.go @@ -0,0 +1,43 @@ +package changeset + +import ( + "encoding/hex" + "errors" + "fmt" + + v1 "github.com/smartcontractkit/chainlink-protos/job-distributor/v1/node" + "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/p2pkey" +) + +func NewP2PSignerEncFromJD(ccfg *v1.ChainConfig, pubkeyStr string) (*P2PSignerEnc, error) { + if ccfg == nil { + return nil, errors.New("nil ocr2config") + } + var pubkey [32]byte + if _, err := hex.Decode(pubkey[:], []byte(pubkeyStr)); err != nil { + return nil, fmt.Errorf("failed to decode pubkey %s: %w", pubkey, err) + } + ocfg := ccfg.Ocr2Config + p2p := p2pkey.PeerID{} + if err := p2p.UnmarshalString(ocfg.P2PKeyBundle.PeerId); err != nil { + return nil, fmt.Errorf("failed to unmarshal peer id %s: %w", ocfg.P2PKeyBundle.PeerId, err) + } + + signer := ocfg.OcrKeyBundle.OnchainSigningAddress + if len(signer) != 40 { + return nil, fmt.Errorf("invalid onchain signing address %s", ocfg.OcrKeyBundle.OnchainSigningAddress) + } + signerB, err := hex.DecodeString(signer) + if err != nil { + return nil, fmt.Errorf("failed to convert signer %s: %w", signer, err) + } + + var sigb [32]byte + copy(sigb[:], signerB) + + return &P2PSignerEnc{ + Signer: sigb, + P2PKey: p2p, + EncryptionPublicKey: pubkey, // TODO. no current way to get this from the node itself (and therefore not in clo or jd) + }, nil +} diff --git a/deployment/keystone/changeset/update_don.go b/deployment/keystone/changeset/update_don.go index 5b381a4e498..1ab40d5a935 100644 --- a/deployment/keystone/changeset/update_don.go +++ b/deployment/keystone/changeset/update_don.go @@ -4,10 +4,8 @@ import ( "fmt" "github.com/smartcontractkit/chainlink/deployment" - "github.com/smartcontractkit/chainlink/deployment/keystone/changeset/internal" - kcr "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry_1_1_0" - "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/p2pkey" + kcr "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry" ) var _ deployment.ChangeSet[*UpdateDonRequest] = UpdateDon @@ -15,28 +13,7 @@ var _ deployment.ChangeSet[*UpdateDonRequest] = UpdateDon // CapabilityConfig is a struct that holds a capability and its configuration type CapabilityConfig = internal.CapabilityConfig -type UpdateDonRequest struct { - RegistryChainSel uint64 - P2PIDs []p2pkey.PeerID // this is the unique identifier for the don - CapabilityConfigs []CapabilityConfig // if Config subfield is nil, a default config is used - - // MCMSConfig is optional. If non-nil, the changes will be proposed using MCMS. - MCMSConfig *MCMSConfig -} - -func (r *UpdateDonRequest) Validate() error { - if len(r.P2PIDs) == 0 { - return fmt.Errorf("p2pIDs is required") - } - if len(r.CapabilityConfigs) == 0 { - return fmt.Errorf("capabilityConfigs is required") - } - return nil -} - -func (r UpdateDonRequest) UseMCMS() bool { - return r.MCMSConfig != nil -} +type UpdateDonRequest = internal.UpdateDonRequest type UpdateDonResponse struct { DonInfo kcr.CapabilitiesRegistryDONInfo @@ -46,73 +23,9 @@ type UpdateDonResponse struct { // This a complex action in practice that involves registering missing capabilities, adding the nodes, and updating // the capabilities of the DON func UpdateDon(env deployment.Environment, req *UpdateDonRequest) (deployment.ChangesetOutput, error) { - appendResult, err := AppendNodeCapabilities(env, appendRequest(req)) - if err != nil { - return deployment.ChangesetOutput{}, fmt.Errorf("failed to append node capabilities: %w", err) - } - - ur, err := updateDonRequest(env, req) - if err != nil { - return deployment.ChangesetOutput{}, fmt.Errorf("failed to create update don request: %w", err) - } - updateResult, err := internal.UpdateDon(env.Logger, ur) + _, err := internal.UpdateDon(env.Logger, req) if err != nil { return deployment.ChangesetOutput{}, fmt.Errorf("failed to update don: %w", err) } - - out := deployment.ChangesetOutput{} - if req.UseMCMS() { - if updateResult.Ops == nil { - return out, fmt.Errorf("expected MCMS operation to be non-nil") - } - if len(appendResult.Proposals) == 0 { - return out, fmt.Errorf("expected append node capabilities to return proposals") - } - - out.Proposals = appendResult.Proposals - - // add the update don to the existing batch - // this makes the proposal all-or-nothing because all the operations are in the same batch, there is only one tr - // transaction and only one proposal - out.Proposals[0].Transactions[0].Batch = append(out.Proposals[0].Transactions[0].Batch, updateResult.Ops.Batch...) - - } - return out, nil - -} - -func appendRequest(r *UpdateDonRequest) *AppendNodeCapabilitiesRequest { - out := &AppendNodeCapabilitiesRequest{ - RegistryChainSel: r.RegistryChainSel, - P2pToCapabilities: make(map[p2pkey.PeerID][]kcr.CapabilitiesRegistryCapability), - MCMSConfig: r.MCMSConfig, - } - for _, p2pid := range r.P2PIDs { - if _, exists := out.P2pToCapabilities[p2pid]; !exists { - out.P2pToCapabilities[p2pid] = make([]kcr.CapabilitiesRegistryCapability, 0) - } - for _, cc := range r.CapabilityConfigs { - out.P2pToCapabilities[p2pid] = append(out.P2pToCapabilities[p2pid], cc.Capability) - } - } - return out -} - -func updateDonRequest(env deployment.Environment, r *UpdateDonRequest) (*internal.UpdateDonRequest, error) { - resp, err := internal.GetContractSets(env.Logger, &internal.GetContractSetsRequest{ - Chains: env.Chains, - AddressBook: env.ExistingAddresses, - }) - if err != nil { - return nil, fmt.Errorf("failed to get contract sets: %w", err) - } - contractSet := resp.ContractSets[r.RegistryChainSel] - - return &internal.UpdateDonRequest{ - Chain: env.Chains[r.RegistryChainSel], - ContractSet: &contractSet, - P2PIDs: r.P2PIDs, - CapabilityConfigs: r.CapabilityConfigs, - UseMCMS: r.UseMCMS(), - }, nil + return deployment.ChangesetOutput{}, nil } diff --git a/deployment/keystone/changeset/update_don_test.go b/deployment/keystone/changeset/update_don_test.go deleted file mode 100644 index 2487087e235..00000000000 --- a/deployment/keystone/changeset/update_don_test.go +++ /dev/null @@ -1,159 +0,0 @@ -package changeset_test - -import ( - "testing" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - - commonchangeset "github.com/smartcontractkit/chainlink/deployment/common/changeset" - "github.com/smartcontractkit/chainlink/deployment/common/proposalutils" - "github.com/smartcontractkit/chainlink/deployment/keystone/changeset" - "github.com/smartcontractkit/chainlink/deployment/keystone/changeset/internal" - "github.com/smartcontractkit/chainlink/deployment/keystone/changeset/test" - kcr "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry_1_1_0" - "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/p2pkey" -) - -func TestUpdateDon(t *testing.T) { - t.Parallel() - - var ( - capA = kcr.CapabilitiesRegistryCapability{ - LabelledName: "capA", - Version: "0.4.2", - } - capB = kcr.CapabilitiesRegistryCapability{ - LabelledName: "capB", - Version: "3.16.0", - } - caps = []kcr.CapabilitiesRegistryCapability{capA, capB} - ) - t.Run("no mcms", func(t *testing.T) { - te := test.SetupTestEnv(t, test.TestConfig{ - WFDonConfig: test.DonConfig{N: 4}, - AssetDonConfig: test.DonConfig{N: 4}, - WriterDonConfig: test.DonConfig{N: 4}, - NumChains: 1, - }) - - // contract set is already deployed with capabilities - // we have to keep track of the existing capabilities to add to the new ones - var p2pIDs []p2pkey.PeerID - newCapabilities := make(map[p2pkey.PeerID][]kcr.CapabilitiesRegistryCapability) - for id, _ := range te.WFNodes { - k, err := p2pkey.MakePeerID(id) - require.NoError(t, err) - p2pIDs = append(p2pIDs, k) - newCapabilities[k] = caps - } - - t.Run("succeeds if update sets new and existing capabilities", func(t *testing.T) { - cfg := changeset.UpdateDonRequest{ - RegistryChainSel: te.RegistrySelector, - P2PIDs: p2pIDs, - CapabilityConfigs: []changeset.CapabilityConfig{ - { - Capability: capA, - }, - { - Capability: capB, - }, - }, - } - - csOut, err := changeset.UpdateDon(te.Env, &cfg) - require.NoError(t, err) - require.Len(t, csOut.Proposals, 0) - require.Nil(t, csOut.AddressBook) - - assertDonContainsCapabilities(t, te.ContractSets()[te.RegistrySelector].CapabilitiesRegistry, caps, p2pIDs) - }) - }) - t.Run("with mcms", func(t *testing.T) { - te := test.SetupTestEnv(t, test.TestConfig{ - WFDonConfig: test.DonConfig{N: 4}, - AssetDonConfig: test.DonConfig{N: 4}, - WriterDonConfig: test.DonConfig{N: 4}, - NumChains: 1, - UseMCMS: true, - }) - - // contract set is already deployed with capabilities - // we have to keep track of the existing capabilities to add to the new ones - var p2pIDs []p2pkey.PeerID - for id, _ := range te.WFNodes { - k, err := p2pkey.MakePeerID(id) - require.NoError(t, err) - p2pIDs = append(p2pIDs, k) - } - - cfg := changeset.UpdateDonRequest{ - RegistryChainSel: te.RegistrySelector, - P2PIDs: p2pIDs, - CapabilityConfigs: []changeset.CapabilityConfig{ - { - Capability: capA, - }, - { - Capability: capB, - }, - }, - MCMSConfig: &changeset.MCMSConfig{MinDuration: 0}, - } - - csOut, err := changeset.UpdateDon(te.Env, &cfg) - require.NoError(t, err) - - require.Len(t, csOut.Proposals, 1) - require.Len(t, csOut.Proposals[0].Transactions, 1) // append node capabilties cs, update don - require.Len(t, csOut.Proposals[0].Transactions[0].Batch, 3) // add capabilities, update nodes, update don - require.Nil(t, csOut.AddressBook) - - // now apply the changeset such that the proposal is signed and execed - contracts := te.ContractSets()[te.RegistrySelector] - timelockContracts := map[uint64]*proposalutils.TimelockExecutionContracts{ - te.RegistrySelector: { - Timelock: contracts.Timelock, - CallProxy: contracts.CallProxy, - }, - } - _, err = commonchangeset.ApplyChangesets(t, te.Env, timelockContracts, []commonchangeset.ChangesetApplication{ - { - Changeset: commonchangeset.WrapChangeSet(changeset.UpdateDon), - Config: &cfg, - }, - }) - require.NoError(t, err) - assertDonContainsCapabilities(t, te.ContractSets()[te.RegistrySelector].CapabilitiesRegistry, caps, p2pIDs) - }) -} - -func assertDonContainsCapabilities(t *testing.T, registry *kcr.CapabilitiesRegistry, want []kcr.CapabilitiesRegistryCapability, p2pIDs []p2pkey.PeerID) { - dons, err := registry.GetDONs(nil) - require.NoError(t, err) - var got *kcr.CapabilitiesRegistryDONInfo - for i, don := range dons { - if internal.SortedHash(internal.PeerIDsToBytes(p2pIDs)) == internal.SortedHash(don.NodeP2PIds) { - got = &dons[i] - break - } - } - require.NotNil(t, got, "missing don with p2pIDs %v", p2pIDs) - wantHashes := make([][32]byte, len(want)) - for i, c := range want { - h, err := registry.GetHashedCapabilityId(nil, c.LabelledName, c.Version) - require.NoError(t, err) - wantHashes[i] = h - assert.Contains(t, capIDsFromCapCfgs(got.CapabilityConfigurations), h, "missing capability %v", c) - } - assert.LessOrEqual(t, len(want), len(got.CapabilityConfigurations), "too many capabilities") -} - -func capIDsFromCapCfgs(cfgs []kcr.CapabilitiesRegistryCapabilityConfiguration) [][32]byte { - out := make([][32]byte, len(cfgs)) - for i, c := range cfgs { - out[i] = c.CapabilityId - } - return out -} diff --git a/deployment/keystone/changeset/update_node_capabilities.go b/deployment/keystone/changeset/update_node_capabilities.go index 8c4d01159ed..0b6c4fb5462 100644 --- a/deployment/keystone/changeset/update_node_capabilities.go +++ b/deployment/keystone/changeset/update_node_capabilities.go @@ -1,19 +1,17 @@ package changeset import ( + "encoding/json" "fmt" - "strconv" - "github.com/ethereum/go-ethereum/common" chainsel "github.com/smartcontractkit/chain-selectors" - "github.com/smartcontractkit/ccip-owner-contracts/pkg/gethwrappers" - "github.com/smartcontractkit/ccip-owner-contracts/pkg/proposal/timelock" "github.com/smartcontractkit/chainlink/deployment" - "github.com/smartcontractkit/chainlink/deployment/common/proposalutils" + "github.com/smartcontractkit/chainlink/deployment/keystone" + kslib "github.com/smartcontractkit/chainlink/deployment/keystone" "github.com/smartcontractkit/chainlink/deployment/keystone/changeset/internal" - kcr "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry_1_1_0" + kcr "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/p2pkey" ) @@ -21,29 +19,15 @@ var _ deployment.ChangeSet[*MutateNodeCapabilitiesRequest] = UpdateNodeCapabilit type P2PSignerEnc = internal.P2PSignerEnc -func NewP2PSignerEnc(n *deployment.Node, registryChainSel uint64) (*P2PSignerEnc, error) { - // TODO: deduplicate everywhere - registryChainID, err := chainsel.ChainIdFromSelector(registryChainSel) +func NewP2PSignerEnc(n *keystone.Node, registryChainSel uint64) (*P2PSignerEnc, error) { + p2p, signer, enc, err := kslib.ExtractKeys(n, registryChainSel) if err != nil { - return nil, err + return nil, fmt.Errorf("failed to extract keys: %w", err) } - registryChainDetails, err := chainsel.GetChainDetailsByChainIDAndFamily(strconv.Itoa(int(registryChainID)), chainsel.FamilyEVM) - if err != nil { - return nil, err - } - evmCC, exists := n.SelToOCRConfig[registryChainDetails] - if !exists { - return nil, fmt.Errorf("NewP2PSignerEnc: registryChainSel not found on node: %v", registryChainSel) - } - var signer [32]byte - copy(signer[:], evmCC.OnchainPublicKey) - var csakey [32]byte - copy(csakey[:], evmCC.ConfigEncryptionPublicKey[:]) - return &P2PSignerEnc{ Signer: signer, - P2PKey: n.PeerID, - EncryptionPublicKey: csakey, + P2PKey: p2p, + EncryptionPublicKey: enc, }, nil } @@ -52,14 +36,16 @@ type UpdateNodeCapabilitiesRequest = MutateNodeCapabilitiesRequest // MutateNodeCapabilitiesRequest is a request to change the capabilities of nodes in the registry type MutateNodeCapabilitiesRequest struct { - RegistryChainSel uint64 - P2pToCapabilities map[p2pkey.PeerID][]kcr.CapabilitiesRegistryCapability + AddressBook deployment.AddressBook + RegistryChainSel uint64 - // MCMSConfig is optional. If non-nil, the changes will be proposed using MCMS. - MCMSConfig *MCMSConfig + P2pToCapabilities map[p2pkey.PeerID][]kcr.CapabilitiesRegistryCapability } func (req *MutateNodeCapabilitiesRequest) Validate() error { + if req.AddressBook == nil { + return fmt.Errorf("address book is nil") + } if len(req.P2pToCapabilities) == 0 { return fmt.Errorf("p2pToCapabilities is empty") } @@ -71,10 +57,6 @@ func (req *MutateNodeCapabilitiesRequest) Validate() error { return nil } -func (req *MutateNodeCapabilitiesRequest) UseMCMS() bool { - return req.MCMSConfig != nil -} - func (req *MutateNodeCapabilitiesRequest) updateNodeCapabilitiesImplRequest(e deployment.Environment) (*internal.UpdateNodeCapabilitiesImplRequest, error) { if err := req.Validate(); err != nil { return nil, fmt.Errorf("failed to validate UpdateNodeCapabilitiesRequest: %w", err) @@ -83,61 +65,38 @@ func (req *MutateNodeCapabilitiesRequest) updateNodeCapabilitiesImplRequest(e de if !ok { return nil, fmt.Errorf("registry chain selector %d does not exist in environment", req.RegistryChainSel) } - resp, err := internal.GetContractSets(e.Logger, &internal.GetContractSetsRequest{ + contracts, err := kslib.GetContractSets(e.Logger, &kslib.GetContractSetsRequest{ Chains: map[uint64]deployment.Chain{req.RegistryChainSel: registryChain}, - AddressBook: e.ExistingAddresses, + AddressBook: req.AddressBook, }) if err != nil { return nil, fmt.Errorf("failed to get contract sets: %w", err) } - contractSet, exists := resp.ContractSets[req.RegistryChainSel] - if !exists { - return nil, fmt.Errorf("contract set not found for chain %d", req.RegistryChainSel) + registry := contracts.ContractSets[req.RegistryChainSel].CapabilitiesRegistry + if registry == nil { + return nil, fmt.Errorf("capabilities registry not found for chain %d", req.RegistryChainSel) } return &internal.UpdateNodeCapabilitiesImplRequest{ Chain: registryChain, - ContractSet: &contractSet, + Registry: registry, P2pToCapabilities: req.P2pToCapabilities, - UseMCMS: req.UseMCMS(), }, nil } // UpdateNodeCapabilities updates the capabilities of nodes in the registry -func UpdateNodeCapabilities(env deployment.Environment, req *UpdateNodeCapabilitiesRequest) (deployment.ChangesetOutput, error) { +func UpdateNodeCapabilities(env deployment.Environment, req *MutateNodeCapabilitiesRequest) (deployment.ChangesetOutput, error) { c, err := req.updateNodeCapabilitiesImplRequest(env) if err != nil { return deployment.ChangesetOutput{}, fmt.Errorf("failed to convert request: %w", err) } r, err := internal.UpdateNodeCapabilitiesImpl(env.Logger, c) - if err != nil { - return deployment.ChangesetOutput{}, fmt.Errorf("failed to update nodes: %w", err) - } - - out := deployment.ChangesetOutput{} - if req.UseMCMS() { - if r.Ops == nil { - return out, fmt.Errorf("expected MCMS operation to be non-nil") - } - timelocksPerChain := map[uint64]common.Address{ - c.Chain.Selector: c.ContractSet.Timelock.Address(), - } - proposerMCMSes := map[uint64]*gethwrappers.ManyChainMultiSig{ - c.Chain.Selector: c.ContractSet.ProposerMcm, - } - - proposal, err := proposalutils.BuildProposalFromBatches( - timelocksPerChain, - proposerMCMSes, - []timelock.BatchChainOperation{*r.Ops}, - "proposal to set update node capabilities", - req.MCMSConfig.MinDuration, - ) - if err != nil { - return out, fmt.Errorf("failed to build proposal: %w", err) + if err == nil { + b, err2 := json.Marshal(r) + if err2 != nil { + env.Logger.Debugf("Updated node capabilities '%s'", b) } - out.Proposals = []timelock.MCMSWithTimelockProposal{*proposal} } - return out, nil + return deployment.ChangesetOutput{}, err } diff --git a/deployment/keystone/changeset/update_node_capabilities_test.go b/deployment/keystone/changeset/update_node_capabilities_test.go deleted file mode 100644 index cf6b9601039..00000000000 --- a/deployment/keystone/changeset/update_node_capabilities_test.go +++ /dev/null @@ -1,208 +0,0 @@ -package changeset_test - -import ( - "testing" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - "golang.org/x/exp/maps" - - commonchangeset "github.com/smartcontractkit/chainlink/deployment/common/changeset" - "github.com/smartcontractkit/chainlink/deployment/common/proposalutils" - "github.com/smartcontractkit/chainlink/deployment/keystone/changeset" - "github.com/smartcontractkit/chainlink/deployment/keystone/changeset/test" - kcr "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry_1_1_0" - "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/p2pkey" -) - -func TestUpdateNodeCapabilities(t *testing.T) { - t.Parallel() - - var ( - capA = kcr.CapabilitiesRegistryCapability{ - LabelledName: "capA", - Version: "0.4.2", - } - capB = kcr.CapabilitiesRegistryCapability{ - LabelledName: "capB", - Version: "3.16.0", - } - caps = []kcr.CapabilitiesRegistryCapability{capA, capB} - ) - t.Run("no mcms", func(t *testing.T) { - te := test.SetupTestEnv(t, test.TestConfig{ - WFDonConfig: test.DonConfig{N: 4}, - AssetDonConfig: test.DonConfig{N: 4}, - WriterDonConfig: test.DonConfig{N: 4}, - NumChains: 1, - }) - - // contract set is already deployed with capabilities - // we have to keep track of the existing capabilities to add to the new ones - var p2pIDs []p2pkey.PeerID - newCapabilities := make(map[p2pkey.PeerID][]kcr.CapabilitiesRegistryCapability) - for id, _ := range te.WFNodes { - k, err := p2pkey.MakePeerID(id) - require.NoError(t, err) - p2pIDs = append(p2pIDs, k) - newCapabilities[k] = caps - } - - t.Run("fails if update drops existing capabilities", func(t *testing.T) { - - cfg := changeset.UpdateNodeCapabilitiesRequest{ - RegistryChainSel: te.RegistrySelector, - P2pToCapabilities: newCapabilities, - } - - _, err := changeset.UpdateNodeCapabilities(te.Env, &cfg) - require.Error(t, err) - assert.Contains(t, err.Error(), "CapabilityRequiredByDON") - }) - t.Run("succeeds if update sets new and existing capabilities", func(t *testing.T) { - existing := getNodeCapabilities(te.ContractSets()[te.RegistrySelector].CapabilitiesRegistry, p2pIDs) - - capabiltiesToSet := existing - for k, v := range newCapabilities { - capabiltiesToSet[k] = append(capabiltiesToSet[k], v...) - } - cfg := changeset.UpdateNodeCapabilitiesRequest{ - RegistryChainSel: te.RegistrySelector, - P2pToCapabilities: capabiltiesToSet, - } - - csOut, err := changeset.UpdateNodeCapabilities(te.Env, &cfg) - require.NoError(t, err) - require.Len(t, csOut.Proposals, 0) - require.Nil(t, csOut.AddressBook) - - validateCapabilityUpdates(t, te, capabiltiesToSet) - }) - }) - t.Run("with mcms", func(t *testing.T) { - te := test.SetupTestEnv(t, test.TestConfig{ - WFDonConfig: test.DonConfig{N: 4}, - AssetDonConfig: test.DonConfig{N: 4}, - WriterDonConfig: test.DonConfig{N: 4}, - NumChains: 1, - UseMCMS: true, - }) - - // contract set is already deployed with capabilities - // we have to keep track of the existing capabilities to add to the new ones - var p2pIDs []p2pkey.PeerID - newCapabilities := make(map[p2pkey.PeerID][]kcr.CapabilitiesRegistryCapability) - for id, _ := range te.WFNodes { - k, err := p2pkey.MakePeerID(id) - require.NoError(t, err) - p2pIDs = append(p2pIDs, k) - newCapabilities[k] = caps - } - - existing := getNodeCapabilities(te.ContractSets()[te.RegistrySelector].CapabilitiesRegistry, p2pIDs) - - capabiltiesToSet := existing - for k, v := range newCapabilities { - capabiltiesToSet[k] = append(capabiltiesToSet[k], v...) - } - cfg := changeset.UpdateNodeCapabilitiesRequest{ - RegistryChainSel: te.RegistrySelector, - P2pToCapabilities: capabiltiesToSet, - MCMSConfig: &changeset.MCMSConfig{MinDuration: 0}, - } - - csOut, err := changeset.UpdateNodeCapabilities(te.Env, &cfg) - require.NoError(t, err) - require.Len(t, csOut.Proposals, 1) - require.Len(t, csOut.Proposals[0].Transactions, 1) - require.Len(t, csOut.Proposals[0].Transactions[0].Batch, 2) // add capabilities, update nodes - require.Nil(t, csOut.AddressBook) - - // now apply the changeset such that the proposal is signed and execed - contracts := te.ContractSets()[te.RegistrySelector] - timelockContracts := map[uint64]*proposalutils.TimelockExecutionContracts{ - te.RegistrySelector: { - Timelock: contracts.Timelock, - CallProxy: contracts.CallProxy, - }, - } - - _, err = commonchangeset.ApplyChangesets(t, te.Env, timelockContracts, []commonchangeset.ChangesetApplication{ - { - Changeset: commonchangeset.WrapChangeSet(changeset.UpdateNodeCapabilities), - Config: &cfg, - }, - }) - require.NoError(t, err) - validateCapabilityUpdates(t, te, capabiltiesToSet) - - }) - -} - -// validateUpdate checks reads nodes from the registry and checks they have the expected updates -func validateCapabilityUpdates(t *testing.T, te test.TestEnv, expected map[p2pkey.PeerID][]kcr.CapabilitiesRegistryCapability) { - registry := te.ContractSets()[te.RegistrySelector].CapabilitiesRegistry - wfP2PIDs := p2pIDs(t, maps.Keys(te.WFNodes)) - nodes, err := registry.GetNodesByP2PIds(nil, wfP2PIDs) - require.NoError(t, err) - require.Len(t, nodes, len(wfP2PIDs)) - for _, node := range nodes { - want := expected[node.P2pId] - require.NotNil(t, want) - assertEqualCapabilities(t, registry, want, node) - } -} - -func assertEqualCapabilities(t *testing.T, registry *kcr.CapabilitiesRegistry, want []kcr.CapabilitiesRegistryCapability, got kcr.INodeInfoProviderNodeInfo) { - wantHashes := make([][32]byte, len(want)) - for i, c := range want { - h, err := registry.GetHashedCapabilityId(nil, c.LabelledName, c.Version) - require.NoError(t, err) - wantHashes[i] = h - } - assert.Equal(t, len(want), len(got.HashedCapabilityIds)) - assert.ElementsMatch(t, wantHashes, got.HashedCapabilityIds) -} - -func getNodeCapabilities(registry *kcr.CapabilitiesRegistry, p2pIDs []p2pkey.PeerID) map[p2pkey.PeerID][]kcr.CapabilitiesRegistryCapability { - m := make(map[p2pkey.PeerID][]kcr.CapabilitiesRegistryCapability) - caps, err := registry.GetCapabilities(nil) - if err != nil { - panic(err) - } - var capMap = make(map[[32]byte]kcr.CapabilitiesRegistryCapability) - for _, c := range caps { - capMap[c.HashedId] = kcr.CapabilitiesRegistryCapability{ - LabelledName: c.LabelledName, - Version: c.Version, - CapabilityType: c.CapabilityType, - ResponseType: c.ResponseType, - ConfigurationContract: c.ConfigurationContract, - } - } - nodes, err := registry.GetNodesByP2PIds(nil, peerIDsToBytes(p2pIDs)) - if err != nil { - panic(err) - } - for _, n := range nodes { - caps := make([]kcr.CapabilitiesRegistryCapability, len(n.HashedCapabilityIds)) - for i, h := range n.HashedCapabilityIds { - c, ok := capMap[h] - if !ok { - panic("capability not found") - } - caps[i] = c - } - m[n.P2pId] = caps - } - return m -} - -func peerIDsToBytes(p2pIDs []p2pkey.PeerID) [][32]byte { - bs := make([][32]byte, len(p2pIDs)) - for i, p := range p2pIDs { - bs[i] = p - } - return bs -} diff --git a/deployment/keystone/changeset/update_nodes.go b/deployment/keystone/changeset/update_nodes.go index 10a7ad4e441..7e436160d2e 100644 --- a/deployment/keystone/changeset/update_nodes.go +++ b/deployment/keystone/changeset/update_nodes.go @@ -2,99 +2,23 @@ package changeset import ( "fmt" - "time" - "github.com/ethereum/go-ethereum/common" - "github.com/smartcontractkit/ccip-owner-contracts/pkg/gethwrappers" - "github.com/smartcontractkit/ccip-owner-contracts/pkg/proposal/timelock" "github.com/smartcontractkit/chainlink/deployment" - "github.com/smartcontractkit/chainlink/deployment/common/proposalutils" - "github.com/smartcontractkit/chainlink/deployment/keystone/changeset/internal" - "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/p2pkey" ) -type MCMSConfig struct { - MinDuration time.Duration -} - var _ deployment.ChangeSet[*UpdateNodesRequest] = UpdateNodes -type UpdateNodesRequest struct { - RegistryChainSel uint64 - P2pToUpdates map[p2pkey.PeerID]NodeUpdate - - // MCMSConfig is optional. If non-nil, the changes will be proposed using MCMS. - MCMSConfig *MCMSConfig -} - -func (r *UpdateNodesRequest) Validate() error { - if r.P2pToUpdates == nil { - return fmt.Errorf("P2pToUpdates must be non-nil") - } - return nil -} - -func (r UpdateNodesRequest) UseMCMS() bool { - return r.MCMSConfig != nil -} - +type UpdateNodesRequest = internal.UpdateNodesRequest type NodeUpdate = internal.NodeUpdate // UpdateNodes updates the a set of nodes. -// The nodes and capabilities in the request must already exist in the registry contract. +// This a complex action in practice that involves registering missing capabilities, adding the nodes, and updating +// the capabilities of the DON func UpdateNodes(env deployment.Environment, req *UpdateNodesRequest) (deployment.ChangesetOutput, error) { - // extract the registry contract and chain from the environment - registryChain, ok := env.Chains[req.RegistryChainSel] - if !ok { - return deployment.ChangesetOutput{}, fmt.Errorf("registry chain selector %d does not exist in environment", req.RegistryChainSel) - } - cresp, err := internal.GetContractSets(env.Logger, &internal.GetContractSetsRequest{ - Chains: env.Chains, - AddressBook: env.ExistingAddresses, - }) - if err != nil { - return deployment.ChangesetOutput{}, fmt.Errorf("failed to get contract sets: %w", err) - } - contracts, exists := cresp.ContractSets[req.RegistryChainSel] - if !exists { - return deployment.ChangesetOutput{}, fmt.Errorf("contract set not found for chain %d", req.RegistryChainSel) - } - - resp, err := internal.UpdateNodes(env.Logger, &internal.UpdateNodesRequest{ - Chain: registryChain, - ContractSet: &contracts, - P2pToUpdates: req.P2pToUpdates, - UseMCMS: req.UseMCMS(), - }) + _, err := internal.UpdateNodes(env.Logger, req) if err != nil { return deployment.ChangesetOutput{}, fmt.Errorf("failed to update don: %w", err) } - - out := deployment.ChangesetOutput{} - if req.UseMCMS() { - if resp.Ops == nil { - return out, fmt.Errorf("expected MCMS operation to be non-nil") - } - timelocksPerChain := map[uint64]common.Address{ - req.RegistryChainSel: contracts.Timelock.Address(), - } - proposerMCMSes := map[uint64]*gethwrappers.ManyChainMultiSig{ - req.RegistryChainSel: contracts.ProposerMcm, - } - - proposal, err := proposalutils.BuildProposalFromBatches( - timelocksPerChain, - proposerMCMSes, - []timelock.BatchChainOperation{*resp.Ops}, - "proposal to set update nodes", - req.MCMSConfig.MinDuration, - ) - if err != nil { - return out, fmt.Errorf("failed to build proposal: %w", err) - } - out.Proposals = []timelock.MCMSWithTimelockProposal{*proposal} - } - - return out, nil + return deployment.ChangesetOutput{}, nil } diff --git a/deployment/keystone/changeset/update_nodes_test.go b/deployment/keystone/changeset/update_nodes_test.go deleted file mode 100644 index 33662aa669d..00000000000 --- a/deployment/keystone/changeset/update_nodes_test.go +++ /dev/null @@ -1,139 +0,0 @@ -package changeset_test - -import ( - "encoding/hex" - "testing" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - "golang.org/x/exp/maps" - - commonchangeset "github.com/smartcontractkit/chainlink/deployment/common/changeset" - "github.com/smartcontractkit/chainlink/deployment/common/proposalutils" - "github.com/smartcontractkit/chainlink/deployment/keystone/changeset" - "github.com/smartcontractkit/chainlink/deployment/keystone/changeset/test" - "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/p2pkey" -) - -func TestUpdateNodes(t *testing.T) { - t.Parallel() - - t.Run("no mcms", func(t *testing.T) { - te := test.SetupTestEnv(t, test.TestConfig{ - WFDonConfig: test.DonConfig{N: 4}, - AssetDonConfig: test.DonConfig{N: 4}, - WriterDonConfig: test.DonConfig{N: 4}, - NumChains: 1, - }) - - updates := make(map[p2pkey.PeerID]changeset.NodeUpdate) - i := uint8(0) - for id, _ := range te.WFNodes { - k, err := p2pkey.MakePeerID(id) - require.NoError(t, err) - pubKey := [32]byte{31: i + 1} - // don't set capabilities or nop b/c those must already exist in the contract - // those ops must be a different proposal when using MCMS - updates[k] = changeset.NodeUpdate{ - EncryptionPublicKey: hex.EncodeToString(pubKey[:]), - Signer: [32]byte{0: i + 1}, - } - i++ - } - - cfg := changeset.UpdateNodesRequest{ - RegistryChainSel: te.RegistrySelector, - P2pToUpdates: updates, - } - - csOut, err := changeset.UpdateNodes(te.Env, &cfg) - require.NoError(t, err) - require.Len(t, csOut.Proposals, 0) - require.Nil(t, csOut.AddressBook) - - validateUpdate(t, te, updates) - }) - - t.Run("with mcms", func(t *testing.T) { - te := test.SetupTestEnv(t, test.TestConfig{ - WFDonConfig: test.DonConfig{N: 4}, - AssetDonConfig: test.DonConfig{N: 4}, - WriterDonConfig: test.DonConfig{N: 4}, - NumChains: 1, - UseMCMS: true, - }) - - updates := make(map[p2pkey.PeerID]changeset.NodeUpdate) - i := uint8(0) - for id, _ := range te.WFNodes { - k, err := p2pkey.MakePeerID(id) - require.NoError(t, err) - pubKey := [32]byte{31: i + 1} - // don't set capabilities or nop b/c those must already exist in the contract - // those ops must be a different proposal when using MCMS - updates[k] = changeset.NodeUpdate{ - EncryptionPublicKey: hex.EncodeToString(pubKey[:]), - Signer: [32]byte{0: i + 1}, - } - i++ - } - - cfg := changeset.UpdateNodesRequest{ - RegistryChainSel: te.RegistrySelector, - P2pToUpdates: updates, - MCMSConfig: &changeset.MCMSConfig{MinDuration: 0}, - } - - csOut, err := changeset.UpdateNodes(te.Env, &cfg) - require.NoError(t, err) - require.Len(t, csOut.Proposals, 1) - require.Nil(t, csOut.AddressBook) - - // now apply the changeset such that the proposal is signed and execed - contracts := te.ContractSets()[te.RegistrySelector] - timelockContracts := map[uint64]*proposalutils.TimelockExecutionContracts{ - te.RegistrySelector: { - Timelock: contracts.Timelock, - CallProxy: contracts.CallProxy, - }, - } - _, err = commonchangeset.ApplyChangesets(t, te.Env, timelockContracts, []commonchangeset.ChangesetApplication{ - { - Changeset: commonchangeset.WrapChangeSet(changeset.UpdateNodes), - Config: &changeset.UpdateNodesRequest{ - RegistryChainSel: te.RegistrySelector, - P2pToUpdates: updates, - MCMSConfig: &changeset.MCMSConfig{MinDuration: 0}, - }, - }, - }) - require.NoError(t, err) - - validateUpdate(t, te, updates) - }) - -} - -// validateUpdate checks reads nodes from the registry and checks they have the expected updates -func validateUpdate(t *testing.T, te test.TestEnv, expected map[p2pkey.PeerID]changeset.NodeUpdate) { - registry := te.ContractSets()[te.RegistrySelector].CapabilitiesRegistry - wfP2PIDs := p2pIDs(t, maps.Keys(te.WFNodes)) - nodes, err := registry.GetNodesByP2PIds(nil, wfP2PIDs) - require.NoError(t, err) - require.Len(t, nodes, len(wfP2PIDs)) - for _, node := range nodes { - // only check the fields that were updated - assert.Equal(t, expected[node.P2pId].EncryptionPublicKey, hex.EncodeToString(node.EncryptionPublicKey[:])) - assert.Equal(t, expected[node.P2pId].Signer, node.Signer) - } -} - -func p2pIDs(t *testing.T, vals []string) [][32]byte { - var out [][32]byte - for _, v := range vals { - id, err := p2pkey.MakePeerID(v) - require.NoError(t, err) - out = append(out, id) - } - return out -} diff --git a/deployment/keystone/changeset/view.go b/deployment/keystone/changeset/view.go index 9c8678d8778..cab4ca25ae7 100644 --- a/deployment/keystone/changeset/view.go +++ b/deployment/keystone/changeset/view.go @@ -2,20 +2,19 @@ package changeset import ( "encoding/json" - "fmt" chainsel "github.com/smartcontractkit/chain-selectors" "github.com/smartcontractkit/chainlink/deployment" commonview "github.com/smartcontractkit/chainlink/deployment/common/view" - "github.com/smartcontractkit/chainlink/deployment/keystone/changeset/internal" + "github.com/smartcontractkit/chainlink/deployment/keystone" "github.com/smartcontractkit/chainlink/deployment/keystone/view" ) var _ deployment.ViewState = ViewKeystone func ViewKeystone(e deployment.Environment) (json.Marshaler, error) { - state, err := internal.GetContractSets(e.Logger, &internal.GetContractSetsRequest{ + state, err := keystone.GetContractSets(e.Logger, &keystone.GetContractSetsRequest{ Chains: e.Chains, AddressBook: e.ExistingAddresses, }) @@ -26,22 +25,22 @@ func ViewKeystone(e deployment.Environment) (json.Marshaler, error) { for chainSel, contracts := range state.ContractSets { chainid, err := chainsel.ChainIdFromSelector(chainSel) if err != nil { - return nil, fmt.Errorf("failed to resolve chain id for selector %d: %w", chainSel, err) + return nil, err } chainName, err := chainsel.NameFromChainId(chainid) if err != nil { - return nil, fmt.Errorf("failed to get name for chainid %d selector %d:%w", chainid, chainSel, err) + return nil, err } v, err := contracts.View() if err != nil { - return nil, fmt.Errorf("failed to view contract set: %w", err) + return nil, err } chainViews[chainName] = v } nopsView, err := commonview.GenerateNopsView(e.NodeIDs, e.Offchain) if err != nil { - return nil, fmt.Errorf("failed to view nops: %w", err) + return nil, err } return &view.KeystoneView{ Chains: chainViews, diff --git a/deployment/keystone/changeset/view_test.go b/deployment/keystone/changeset/view_test.go index 5b32699fd89..2d4569dfbec 100644 --- a/deployment/keystone/changeset/view_test.go +++ b/deployment/keystone/changeset/view_test.go @@ -7,7 +7,6 @@ import ( "go.uber.org/zap/zapcore" "github.com/smartcontractkit/chainlink-common/pkg/logger" - "github.com/smartcontractkit/chainlink/deployment/environment/memory" ) @@ -26,7 +25,7 @@ func TestKeystoneView(t *testing.T) { require.NoError(t, err) require.NotNil(t, resp) require.NoError(t, env.ExistingAddresses.Merge(resp.AddressBook)) - resp, err = DeployForwarder(env, DeployForwarderRequest{}) + resp, err = DeployForwarder(env, registryChain) require.NoError(t, err) require.NotNil(t, resp) require.NoError(t, env.ExistingAddresses.Merge(resp.AddressBook)) diff --git a/deployment/keystone/changeset/workflowregistry/deploy.go b/deployment/keystone/changeset/workflowregistry/deploy.go deleted file mode 100644 index e55484aa711..00000000000 --- a/deployment/keystone/changeset/workflowregistry/deploy.go +++ /dev/null @@ -1,25 +0,0 @@ -package workflowregistry - -import ( - "fmt" - - "github.com/smartcontractkit/chainlink/deployment" -) - -var _ deployment.ChangeSet[uint64] = Deploy - -func Deploy(env deployment.Environment, registrySelector uint64) (deployment.ChangesetOutput, error) { - lggr := env.Logger - chain, ok := env.Chains[registrySelector] - if !ok { - return deployment.ChangesetOutput{}, fmt.Errorf("chain not found in environment") - } - ab := deployment.NewMemoryAddressBook() - wrResp, err := deployWorkflowRegistry(chain, ab) - if err != nil { - return deployment.ChangesetOutput{}, fmt.Errorf("failed to deploy CapabilitiesRegistry: %w", err) - } - lggr.Infof("Deployed %s chain selector %d addr %s", wrResp.Tv.String(), chain.Selector, wrResp.Address.String()) - - return deployment.ChangesetOutput{AddressBook: ab}, nil -} diff --git a/deployment/keystone/changeset/workflowregistry/deploy_test.go b/deployment/keystone/changeset/workflowregistry/deploy_test.go deleted file mode 100644 index 16eb6fa8512..00000000000 --- a/deployment/keystone/changeset/workflowregistry/deploy_test.go +++ /dev/null @@ -1,38 +0,0 @@ -package workflowregistry - -import ( - "testing" - - "go.uber.org/zap/zapcore" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - - "github.com/smartcontractkit/chainlink-common/pkg/logger" - "github.com/smartcontractkit/chainlink/deployment/environment/memory" -) - -func Test_Deploy(t *testing.T) { - t.Parallel() - lggr := logger.Test(t) - cfg := memory.MemoryEnvironmentConfig{ - Nodes: 1, // nodes unused but required in config - Chains: 2, - } - env := memory.NewMemoryEnvironment(t, lggr, zapcore.DebugLevel, cfg) - - registrySel := env.AllChainSelectors()[0] - - resp, err := Deploy(env, registrySel) - require.NoError(t, err) - require.NotNil(t, resp) - // OCR3 should be deployed on chain 0 - addrs, err := resp.AddressBook.AddressesForChain(registrySel) - require.NoError(t, err) - require.Len(t, addrs, 1) - - // nothing on chain 1 - require.NotEqual(t, registrySel, env.AllChainSelectors()[1]) - oaddrs, _ := resp.AddressBook.AddressesForChain(env.AllChainSelectors()[1]) - assert.Len(t, oaddrs, 0) -} diff --git a/deployment/keystone/changeset/workflowregistry/setup_test.go b/deployment/keystone/changeset/workflowregistry/setup_test.go deleted file mode 100644 index 78e7d852080..00000000000 --- a/deployment/keystone/changeset/workflowregistry/setup_test.go +++ /dev/null @@ -1,54 +0,0 @@ -package workflowregistry - -import ( - "testing" - - "github.com/smartcontractkit/chainlink-common/pkg/logger" - "github.com/smartcontractkit/chainlink/deployment" - "github.com/smartcontractkit/chainlink/deployment/environment/memory" - "github.com/smartcontractkit/chainlink/deployment/keystone/changeset" - workflow_registry "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/workflow/generated/workflow_registry_wrapper" - "github.com/stretchr/testify/require" -) - -type SetupTestWorkflowRegistryResponse struct { - Registry *workflow_registry.WorkflowRegistry - Chain deployment.Chain - RegistrySelector uint64 - AddressBook deployment.AddressBook -} - -func SetupTestWorkflowRegistry(t *testing.T, lggr logger.Logger, chainSel uint64) *SetupTestWorkflowRegistryResponse { - chain := testChain(t) - - deployer, err := newWorkflowRegistryDeployer() - require.NoError(t, err) - resp, err := deployer.Deploy(changeset.DeployRequest{Chain: chain}) - require.NoError(t, err) - - addressBook := deployment.NewMemoryAddressBookFromMap( - map[uint64]map[string]deployment.TypeAndVersion{ - chainSel: map[string]deployment.TypeAndVersion{ - resp.Address.Hex(): resp.Tv, - }, - }, - ) - - return &SetupTestWorkflowRegistryResponse{ - Registry: deployer.Contract(), - Chain: chain, - RegistrySelector: chain.Selector, - AddressBook: addressBook, - } -} - -func testChain(t *testing.T) deployment.Chain { - chains, _ := memory.NewMemoryChains(t, 1, 5) - var chain deployment.Chain - for _, c := range chains { - chain = c - break - } - require.NotEmpty(t, chain) - return chain -} diff --git a/deployment/keystone/changeset/workflowregistry/strategies.go b/deployment/keystone/changeset/workflowregistry/strategies.go deleted file mode 100644 index 617d6e6e8dc..00000000000 --- a/deployment/keystone/changeset/workflowregistry/strategies.go +++ /dev/null @@ -1,85 +0,0 @@ -package workflowregistry - -import ( - "math/big" - - "github.com/ethereum/go-ethereum/accounts/abi/bind" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/types" - - "github.com/smartcontractkit/ccip-owner-contracts/pkg/gethwrappers" - "github.com/smartcontractkit/ccip-owner-contracts/pkg/proposal/mcms" - "github.com/smartcontractkit/ccip-owner-contracts/pkg/proposal/timelock" - - "github.com/smartcontractkit/chainlink/deployment" - "github.com/smartcontractkit/chainlink/deployment/common/proposalutils" - "github.com/smartcontractkit/chainlink/deployment/keystone/changeset" -) - -type strategy interface { - Apply(callFn func(opts *bind.TransactOpts) (*types.Transaction, error)) (deployment.ChangesetOutput, error) -} - -type simpleTransaction struct { - chain deployment.Chain -} - -func (s *simpleTransaction) Apply(callFn func(opts *bind.TransactOpts) (*types.Transaction, error)) (deployment.ChangesetOutput, error) { - tx, err := callFn(s.chain.DeployerKey) - if err != nil { - return deployment.ChangesetOutput{}, err - } - - _, err = s.chain.Confirm(tx) - return deployment.ChangesetOutput{}, err -} - -type mcmsTransaction struct { - Config *changeset.MCMSConfig - Description string - Address common.Address - ChainSel uint64 - ContractSet *changeset.ContractSet -} - -func (m *mcmsTransaction) Apply(callFn func(opts *bind.TransactOpts) (*types.Transaction, error)) (deployment.ChangesetOutput, error) { - opts := deployment.SimTransactOpts() - - tx, err := callFn(opts) - if err != nil { - return deployment.ChangesetOutput{}, err - } - - op := timelock.BatchChainOperation{ - ChainIdentifier: mcms.ChainIdentifier(m.ChainSel), - Batch: []mcms.Operation{ - { - Data: tx.Data(), - To: m.Address, - Value: big.NewInt(0), - }, - }, - } - - timelocksPerChain := map[uint64]common.Address{ - m.ChainSel: m.ContractSet.Timelock.Address(), - } - proposerMCMSes := map[uint64]*gethwrappers.ManyChainMultiSig{ - m.ChainSel: m.ContractSet.ProposerMcm, - } - - proposal, err := proposalutils.BuildProposalFromBatches( - timelocksPerChain, - proposerMCMSes, - []timelock.BatchChainOperation{op}, - m.Description, - m.Config.MinDuration, - ) - if err != nil { - return deployment.ChangesetOutput{}, err - } - - return deployment.ChangesetOutput{ - Proposals: []timelock.MCMSWithTimelockProposal{*proposal}, - }, nil -} diff --git a/deployment/keystone/changeset/workflowregistry/update_allowed_dons.go b/deployment/keystone/changeset/workflowregistry/update_allowed_dons.go deleted file mode 100644 index 5001370b552..00000000000 --- a/deployment/keystone/changeset/workflowregistry/update_allowed_dons.go +++ /dev/null @@ -1,80 +0,0 @@ -package workflowregistry - -import ( - "errors" - "fmt" - - "github.com/ethereum/go-ethereum/accounts/abi/bind" - "github.com/ethereum/go-ethereum/core/types" - - "github.com/smartcontractkit/chainlink/deployment" - - "github.com/smartcontractkit/chainlink/deployment/keystone/changeset" - workflow_registry "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/workflow/generated/workflow_registry_wrapper" -) - -var _ deployment.ChangeSet[*UpdateAllowedDonsRequest] = UpdateAllowedDons - -type UpdateAllowedDonsRequest struct { - RegistryChainSel uint64 - DonIDs []uint32 - Allowed bool - - MCMSConfig *changeset.MCMSConfig -} - -func (r *UpdateAllowedDonsRequest) Validate() error { - if len(r.DonIDs) == 0 { - return errors.New("Must provide at least one DonID") - } - return nil -} - -// UpdateAllowedDons updates the list of DONs that workflows can be sent to. -func UpdateAllowedDons(env deployment.Environment, req *UpdateAllowedDonsRequest) (deployment.ChangesetOutput, error) { - if err := req.Validate(); err != nil { - return deployment.ChangesetOutput{}, err - } - - resp, err := changeset.GetContractSets(env.Logger, &changeset.GetContractSetsRequest{ - Chains: env.Chains, - AddressBook: env.ExistingAddresses, - }) - if err != nil { - return deployment.ChangesetOutput{}, fmt.Errorf("failed to get contract sets: %w", err) - } - - cs := resp.ContractSets[req.RegistryChainSel] - if cs.WorkflowRegistry == nil { - return deployment.ChangesetOutput{}, errors.New("could not find workflow registry") - } - registry := cs.WorkflowRegistry - - chain, ok := env.Chains[req.RegistryChainSel] - if !ok { - return deployment.ChangesetOutput{}, fmt.Errorf("registry chain selector %d does not exist in environment", req.RegistryChainSel) - } - - var s strategy - if req.MCMSConfig != nil { - s = &mcmsTransaction{ - Config: req.MCMSConfig, - Description: "proposal to update allowed dons", - Address: registry.Address(), - ChainSel: req.RegistryChainSel, - ContractSet: &cs, - } - } else { - s = &simpleTransaction{ - chain: chain, - } - } - - return s.Apply(func(opts *bind.TransactOpts) (*types.Transaction, error) { - tx, err := registry.UpdateAllowedDONs(opts, req.DonIDs, req.Allowed) - if err != nil { - err = deployment.DecodeErr(workflow_registry.WorkflowRegistryABI, err) - } - return tx, err - }) -} diff --git a/deployment/keystone/changeset/workflowregistry/update_allowed_dons_test.go b/deployment/keystone/changeset/workflowregistry/update_allowed_dons_test.go deleted file mode 100644 index f24db609553..00000000000 --- a/deployment/keystone/changeset/workflowregistry/update_allowed_dons_test.go +++ /dev/null @@ -1,110 +0,0 @@ -package workflowregistry_test - -import ( - "testing" - - "github.com/ethereum/go-ethereum/accounts/abi/bind" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - - "github.com/smartcontractkit/chainlink-common/pkg/logger" - - chain_selectors "github.com/smartcontractkit/chain-selectors" - - "github.com/smartcontractkit/chainlink/deployment" - commonchangeset "github.com/smartcontractkit/chainlink/deployment/common/changeset" - "github.com/smartcontractkit/chainlink/deployment/common/proposalutils" - "github.com/smartcontractkit/chainlink/deployment/keystone/changeset" - "github.com/smartcontractkit/chainlink/deployment/keystone/changeset/test" - "github.com/smartcontractkit/chainlink/deployment/keystone/changeset/workflowregistry" -) - -func TestUpdateAllowedDons(t *testing.T) { - lggr := logger.Test(t) - - chainSel := chain_selectors.ETHEREUM_TESTNET_SEPOLIA.Selector - resp := workflowregistry.SetupTestWorkflowRegistry(t, lggr, chainSel) - registry := resp.Registry - - dons, err := registry.GetAllAllowedDONs(&bind.CallOpts{}) - require.NoError(t, err) - - assert.Len(t, dons, 0) - - env := deployment.Environment{ - Logger: lggr, - Chains: map[uint64]deployment.Chain{ - chainSel: resp.Chain, - }, - ExistingAddresses: resp.AddressBook, - } - - _, err = workflowregistry.UpdateAllowedDons( - env, - &workflowregistry.UpdateAllowedDonsRequest{ - RegistryChainSel: chainSel, - DonIDs: []uint32{1}, - Allowed: true, - }, - ) - require.NoError(t, err) - - dons, err = registry.GetAllAllowedDONs(&bind.CallOpts{}) - require.NoError(t, err) - - assert.Len(t, dons, 1) - assert.Equal(t, dons[0], uint32(1)) - - _, err = workflowregistry.UpdateAllowedDons( - env, - &workflowregistry.UpdateAllowedDonsRequest{ - RegistryChainSel: chainSel, - DonIDs: []uint32{1}, - Allowed: false, - }, - ) - require.NoError(t, err) - - dons, err = registry.GetAllAllowedDONs(&bind.CallOpts{}) - require.NoError(t, err) - - assert.Len(t, dons, 0) -} - -func Test_UpdateAllowedDons_WithMCMS(t *testing.T) { - te := test.SetupTestEnv(t, test.TestConfig{ - WFDonConfig: test.DonConfig{N: 4}, - AssetDonConfig: test.DonConfig{N: 4}, - WriterDonConfig: test.DonConfig{N: 4}, - NumChains: 1, - UseMCMS: true, - }) - - req := &workflowregistry.UpdateAllowedDonsRequest{ - RegistryChainSel: te.RegistrySelector, - DonIDs: []uint32{1}, - Allowed: true, - MCMSConfig: &changeset.MCMSConfig{MinDuration: 0}, - } - - out, err := workflowregistry.UpdateAllowedDons(te.Env, req) - require.NoError(t, err) - require.Len(t, out.Proposals, 1) - require.Nil(t, out.AddressBook) - - contracts := te.ContractSets()[te.RegistrySelector] - timelockContracts := map[uint64]*proposalutils.TimelockExecutionContracts{ - te.RegistrySelector: { - Timelock: contracts.Timelock, - CallProxy: contracts.CallProxy, - }, - } - - _, err = commonchangeset.ApplyChangesets(t, te.Env, timelockContracts, []commonchangeset.ChangesetApplication{ - { - Changeset: commonchangeset.WrapChangeSet(workflowregistry.UpdateAllowedDons), - Config: req, - }, - }) - require.NoError(t, err) -} diff --git a/deployment/keystone/changeset/workflowregistry/update_authorized_addresses.go b/deployment/keystone/changeset/workflowregistry/update_authorized_addresses.go deleted file mode 100644 index b2d5ffcce1e..00000000000 --- a/deployment/keystone/changeset/workflowregistry/update_authorized_addresses.go +++ /dev/null @@ -1,105 +0,0 @@ -package workflowregistry - -import ( - "errors" - "fmt" - - "github.com/ethereum/go-ethereum/accounts/abi/bind" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/types" - - "github.com/smartcontractkit/chainlink/deployment" - - "github.com/smartcontractkit/chainlink/deployment/keystone/changeset" - workflow_registry "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/workflow/generated/workflow_registry_wrapper" -) - -var _ deployment.ChangeSet[*UpdateAuthorizedAddressesRequest] = UpdateAuthorizedAddresses - -type UpdateAuthorizedAddressesRequest struct { - RegistryChainSel uint64 - - Addresses []string - Allowed bool - - MCMSConfig *changeset.MCMSConfig -} - -func (r *UpdateAuthorizedAddressesRequest) Validate() error { - if len(r.Addresses) == 0 { - return errors.New("Must provide at least 1 address") - } - - return nil -} - -func getWorkflowRegistry(env deployment.Environment, chainSel uint64) (*workflow_registry.WorkflowRegistry, error) { - resp, err := changeset.GetContractSets(env.Logger, &changeset.GetContractSetsRequest{ - Chains: env.Chains, - AddressBook: env.ExistingAddresses, - }) - if err != nil { - return nil, fmt.Errorf("failed to get contract sets: %w", err) - } - - cs := resp.ContractSets[chainSel] - if cs.WorkflowRegistry == nil { - return nil, errors.New("could not find workflow registry") - } - - return cs.WorkflowRegistry, nil -} - -// UpdateAuthorizedAddresses updates the list of DONs that workflows can be sent to. -func UpdateAuthorizedAddresses(env deployment.Environment, req *UpdateAuthorizedAddressesRequest) (deployment.ChangesetOutput, error) { - if err := req.Validate(); err != nil { - return deployment.ChangesetOutput{}, err - } - - resp, err := changeset.GetContractSets(env.Logger, &changeset.GetContractSetsRequest{ - Chains: env.Chains, - AddressBook: env.ExistingAddresses, - }) - if err != nil { - return deployment.ChangesetOutput{}, fmt.Errorf("failed to get contract sets: %w", err) - } - - cs := resp.ContractSets[req.RegistryChainSel] - if cs.WorkflowRegistry == nil { - return deployment.ChangesetOutput{}, errors.New("could not find workflow registry") - } - registry := cs.WorkflowRegistry - - chain, ok := env.Chains[req.RegistryChainSel] - if !ok { - return deployment.ChangesetOutput{}, fmt.Errorf("registry chain selector %d does not exist in environment", req.RegistryChainSel) - } - - var addr []common.Address - for _, a := range req.Addresses { - addr = append(addr, common.HexToAddress(a)) - } - - var s strategy - if req.MCMSConfig != nil { - s = &mcmsTransaction{ - Config: req.MCMSConfig, - Description: "proposal to update authorized addresses", - Address: registry.Address(), - ChainSel: chain.Selector, - ContractSet: &cs, - } - } else { - s = &simpleTransaction{ - chain: chain, - } - } - - return s.Apply(func(opts *bind.TransactOpts) (*types.Transaction, error) { - tx, err := registry.UpdateAuthorizedAddresses(opts, addr, req.Allowed) - if err != nil { - err = deployment.DecodeErr(workflow_registry.WorkflowRegistryABI, err) - } - return tx, err - }) -} diff --git a/deployment/keystone/changeset/workflowregistry/update_authorized_addresses_test.go b/deployment/keystone/changeset/workflowregistry/update_authorized_addresses_test.go deleted file mode 100644 index a8d969fce0c..00000000000 --- a/deployment/keystone/changeset/workflowregistry/update_authorized_addresses_test.go +++ /dev/null @@ -1,113 +0,0 @@ -package workflowregistry_test - -import ( - "testing" - - "github.com/ethereum/go-ethereum/accounts/abi/bind" - "github.com/ethereum/go-ethereum/common" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - - chain_selectors "github.com/smartcontractkit/chain-selectors" - - "github.com/smartcontractkit/chainlink-common/pkg/logger" - - "github.com/smartcontractkit/chainlink/deployment" - commonchangeset "github.com/smartcontractkit/chainlink/deployment/common/changeset" - "github.com/smartcontractkit/chainlink/deployment/common/proposalutils" - "github.com/smartcontractkit/chainlink/deployment/keystone/changeset" - "github.com/smartcontractkit/chainlink/deployment/keystone/changeset/test" - "github.com/smartcontractkit/chainlink/deployment/keystone/changeset/workflowregistry" -) - -func TestUpdateAuthorizedAddresses(t *testing.T) { - lggr := logger.Test(t) - - chainSel := chain_selectors.ETHEREUM_TESTNET_SEPOLIA.Selector - resp := workflowregistry.SetupTestWorkflowRegistry(t, lggr, chainSel) - registry := resp.Registry - - dons, err := registry.GetAllAuthorizedAddresses(&bind.CallOpts{}) - require.NoError(t, err) - - assert.Len(t, dons, 0) - - env := deployment.Environment{ - Logger: lggr, - Chains: map[uint64]deployment.Chain{ - chainSel: resp.Chain, - }, - ExistingAddresses: resp.AddressBook, - } - - addr := "0xc0ffee254729296a45a3885639AC7E10F9d54979" - _, err = workflowregistry.UpdateAuthorizedAddresses( - env, - &workflowregistry.UpdateAuthorizedAddressesRequest{ - RegistryChainSel: chainSel, - Addresses: []string{addr}, - Allowed: true, - }, - ) - require.NoError(t, err) - - dons, err = registry.GetAllAuthorizedAddresses(&bind.CallOpts{}) - require.NoError(t, err) - - assert.Len(t, dons, 1) - assert.Equal(t, dons[0], common.HexToAddress(addr)) - - _, err = workflowregistry.UpdateAuthorizedAddresses( - env, - &workflowregistry.UpdateAuthorizedAddressesRequest{ - RegistryChainSel: chainSel, - Addresses: []string{addr}, - Allowed: false, - }, - ) - require.NoError(t, err) - - dons, err = registry.GetAllAuthorizedAddresses(&bind.CallOpts{}) - require.NoError(t, err) - - assert.Len(t, dons, 0) -} - -func Test_UpdateAuthorizedAddresses_WithMCMS(t *testing.T) { - te := test.SetupTestEnv(t, test.TestConfig{ - WFDonConfig: test.DonConfig{N: 4}, - AssetDonConfig: test.DonConfig{N: 4}, - WriterDonConfig: test.DonConfig{N: 4}, - NumChains: 1, - UseMCMS: true, - }) - - addr := "0xc0ffee254729296a45a3885639AC7E10F9d54979" - req := &workflowregistry.UpdateAuthorizedAddressesRequest{ - RegistryChainSel: te.RegistrySelector, - Addresses: []string{addr}, - Allowed: true, - MCMSConfig: &changeset.MCMSConfig{MinDuration: 0}, - } - - out, err := workflowregistry.UpdateAuthorizedAddresses(te.Env, req) - require.NoError(t, err) - require.Len(t, out.Proposals, 1) - require.Nil(t, out.AddressBook) - - contracts := te.ContractSets()[te.RegistrySelector] - timelockContracts := map[uint64]*proposalutils.TimelockExecutionContracts{ - te.RegistrySelector: { - Timelock: contracts.Timelock, - CallProxy: contracts.CallProxy, - }, - } - - _, err = commonchangeset.ApplyChangesets(t, te.Env, timelockContracts, []commonchangeset.ChangesetApplication{ - { - Changeset: commonchangeset.WrapChangeSet(workflowregistry.UpdateAuthorizedAddresses), - Config: req, - }, - }) - require.NoError(t, err) -} diff --git a/deployment/keystone/changeset/workflowregistry/workflow_registry_deployer.go b/deployment/keystone/changeset/workflowregistry/workflow_registry_deployer.go deleted file mode 100644 index ac5bbd16cc8..00000000000 --- a/deployment/keystone/changeset/workflowregistry/workflow_registry_deployer.go +++ /dev/null @@ -1,76 +0,0 @@ -package workflowregistry - -import ( - "fmt" - - "github.com/ethereum/go-ethereum/accounts/abi/bind" - - "github.com/smartcontractkit/chainlink-common/pkg/logger" - - "github.com/smartcontractkit/chainlink/deployment" - "github.com/smartcontractkit/chainlink/deployment/keystone/changeset" - workflow_registry "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/workflow/generated/workflow_registry_wrapper" -) - -type workflowRegistryDeployer struct { - lggr logger.Logger - contract *workflow_registry.WorkflowRegistry -} - -func newWorkflowRegistryDeployer() (*workflowRegistryDeployer, error) { - lggr, err := logger.New() - if err != nil { - return nil, err - } - return &workflowRegistryDeployer{lggr: lggr}, nil -} - -func (c *workflowRegistryDeployer) Contract() *workflow_registry.WorkflowRegistry { - return c.contract -} - -func (c *workflowRegistryDeployer) Deploy(req changeset.DeployRequest) (*changeset.DeployResponse, error) { - - addr, tx, wr, err := workflow_registry.DeployWorkflowRegistry( - req.Chain.DeployerKey, - req.Chain.Client) - if err != nil { - return nil, deployment.DecodeErr(workflow_registry.WorkflowRegistryABI, err) - } - - _, err = req.Chain.Confirm(tx) - if err != nil { - return nil, fmt.Errorf("failed to confirm and save WorkflowRegistry: %w", err) - } - tvStr, err := wr.TypeAndVersion(&bind.CallOpts{}) - if err != nil { - return nil, fmt.Errorf("failed to get type and version: %w", err) - } - - tv, err := deployment.TypeAndVersionFromString(tvStr) - if err != nil { - return nil, fmt.Errorf("failed to parse type and version from %s: %w", tvStr, err) - } - resp := &changeset.DeployResponse{ - Address: addr, - Tx: tx.Hash(), - Tv: tv, - } - c.contract = wr - return resp, nil -} - -// deployWorkflowRegistry deploys the WorkflowRegistry contract to the chain -// and saves the address in the address book. This mutates the address book. -func deployWorkflowRegistry(chain deployment.Chain, ab deployment.AddressBook) (*changeset.DeployResponse, error) { - deployer, err := newWorkflowRegistryDeployer() - resp, err := deployer.Deploy(changeset.DeployRequest{Chain: chain}) - if err != nil { - return nil, fmt.Errorf("failed to deploy WorkflowRegistry: %w", err) - } - err = ab.Save(chain.Selector, resp.Address.String(), resp.Tv) - if err != nil { - return nil, fmt.Errorf("failed to save WorkflowRegistry: %w", err) - } - return resp, nil -} diff --git a/deployment/keystone/contract_set.go b/deployment/keystone/contract_set.go new file mode 100644 index 00000000000..a0446dcfce0 --- /dev/null +++ b/deployment/keystone/contract_set.go @@ -0,0 +1,93 @@ +package keystone + +import ( + "fmt" + + "github.com/smartcontractkit/chainlink-common/pkg/logger" + "github.com/smartcontractkit/chainlink/deployment" +) + +type deployContractsRequest struct { + chain deployment.Chain + isRegistryChain bool + ad deployment.AddressBook +} + +type deployContractSetResponse struct { + deployment.AddressBook +} + +func deployContractsToChain(lggr logger.Logger, req deployContractsRequest) (*deployContractSetResponse, error) { + if req.ad == nil { + req.ad = deployment.NewMemoryAddressBook() + } + // this is mutated in the Deploy* functions + resp := &deployContractSetResponse{ + AddressBook: req.ad, + } + + // cap reg and ocr3 only deployed on registry chain + if req.isRegistryChain { + err := DeployCapabilitiesRegistry(lggr, req.chain, resp.AddressBook) + if err != nil { + return nil, fmt.Errorf("failed to deploy CapabilitiesRegistry: %w", err) + } + err = DeployOCR3(lggr, req.chain, resp.AddressBook) + if err != nil { + return nil, fmt.Errorf("failed to deploy OCR3Capability: %w", err) + } + } + err := DeployForwarder(lggr, req.chain, resp.AddressBook) + if err != nil { + return nil, fmt.Errorf("failed to deploy KeystoneForwarder: %w", err) + } + return resp, nil +} + +// DeployCapabilitiesRegistry deploys the CapabilitiesRegistry contract to the chain +// and saves the address in the address book. This mutates the address book. +func DeployCapabilitiesRegistry(lggr logger.Logger, chain deployment.Chain, ab deployment.AddressBook) error { + capabilitiesRegistryDeployer := CapabilitiesRegistryDeployer{lggr: lggr} + capabilitiesRegistryResp, err := capabilitiesRegistryDeployer.Deploy(DeployRequest{Chain: chain}) + if err != nil { + return fmt.Errorf("failed to deploy CapabilitiesRegistry: %w", err) + } + err = ab.Save(chain.Selector, capabilitiesRegistryResp.Address.String(), capabilitiesRegistryResp.Tv) + if err != nil { + return fmt.Errorf("failed to save CapabilitiesRegistry: %w", err) + } + lggr.Infof("Deployed %s chain selector %d addr %s", capabilitiesRegistryResp.Tv.String(), chain.Selector, capabilitiesRegistryResp.Address.String()) + return nil +} + +// DeployOCR3 deploys the OCR3Capability contract to the chain +// and saves the address in the address book. This mutates the address book. +func DeployOCR3(lggr logger.Logger, chain deployment.Chain, ab deployment.AddressBook) error { + ocr3Deployer := OCR3Deployer{lggr: lggr} + ocr3Resp, err := ocr3Deployer.deploy(DeployRequest{Chain: chain}) + if err != nil { + return fmt.Errorf("failed to deploy OCR3Capability: %w", err) + } + err = ab.Save(chain.Selector, ocr3Resp.Address.String(), ocr3Resp.Tv) + if err != nil { + return fmt.Errorf("failed to save OCR3Capability: %w", err) + } + lggr.Infof("Deployed %s chain selector %d addr %s", ocr3Resp.Tv.String(), chain.Selector, ocr3Resp.Address.String()) + return nil +} + +// DeployForwarder deploys the KeystoneForwarder contract to the chain +// and saves the address in the address book. This mutates the address book. +func DeployForwarder(lggr logger.Logger, chain deployment.Chain, ab deployment.AddressBook) error { + forwarderDeployer := KeystoneForwarderDeployer{lggr: lggr} + forwarderResp, err := forwarderDeployer.deploy(DeployRequest{Chain: chain}) + if err != nil { + return fmt.Errorf("failed to deploy KeystoneForwarder: %w", err) + } + err = ab.Save(chain.Selector, forwarderResp.Address.String(), forwarderResp.Tv) + if err != nil { + return fmt.Errorf("failed to save KeystoneForwarder: %w", err) + } + lggr.Infof("Deployed %s chain selector %d addr %s", forwarderResp.Tv.String(), chain.Selector, forwarderResp.Address.String()) + return nil +} diff --git a/deployment/keystone/changeset/internal/deploy.go b/deployment/keystone/deploy.go similarity index 53% rename from deployment/keystone/changeset/internal/deploy.go rename to deployment/keystone/deploy.go index 5afcae11e93..a43f906178e 100644 --- a/deployment/keystone/changeset/internal/deploy.go +++ b/deployment/keystone/deploy.go @@ -1,4 +1,4 @@ -package internal +package keystone import ( "bytes" @@ -7,17 +7,17 @@ import ( "encoding/hex" "errors" "fmt" - "math/big" + "slices" "sort" - "strconv" "strings" "time" "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/rpc" "golang.org/x/exp/maps" - "github.com/smartcontractkit/ccip-owner-contracts/pkg/proposal/mcms" - "github.com/smartcontractkit/ccip-owner-contracts/pkg/proposal/timelock" + nodev1 "github.com/smartcontractkit/chainlink-protos/job-distributor/v1/node" + "github.com/smartcontractkit/chainlink-protos/job-distributor/v1/shared/ptypes" "github.com/smartcontractkit/chainlink/deployment" "google.golang.org/protobuf/proto" @@ -27,9 +27,10 @@ import ( capabilitiespb "github.com/smartcontractkit/chainlink-common/pkg/capabilities/pb" "github.com/smartcontractkit/chainlink-common/pkg/values" - - capabilities_registry "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry_1_1_0" - kf "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/forwarder_1_0_0" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry" + kcr "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry" + kf "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/forwarder" + kocr3 "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/ocr3_capability" "github.com/smartcontractkit/chainlink-common/pkg/logger" ) @@ -38,10 +39,9 @@ type ConfigureContractsRequest struct { RegistryChainSel uint64 Env *deployment.Environment - Dons []DonCapabilities // externally sourced based on the environment - OCR3Config *OracleConfig // TODO: probably should be a map of don to config; but currently we only have one wf don therefore one config + Dons []DonCapabilities // externally sourced based on the environment + OCR3Config *OracleConfigWithSecrets // TODO: probably should be a map of don to config; but currently we only have one wf don therefore one config - // TODO rm this option; unused DoContractDeploy bool // if false, the contracts are assumed to be deployed and the address book is used } @@ -66,7 +66,7 @@ func (r ConfigureContractsRequest) Validate() error { type ConfigureContractsResponse struct { Changeset *deployment.ChangesetOutput - DonInfos map[string]capabilities_registry.CapabilitiesRegistryDONInfo + DonInfos map[string]kcr.CapabilitiesRegistryDONInfo } // ConfigureContracts configures contracts them with the given DONS and their capabilities. It optionally deploys the contracts @@ -76,7 +76,21 @@ func ConfigureContracts(ctx context.Context, lggr logger.Logger, req ConfigureCo return nil, fmt.Errorf("invalid request: %w", err) } - cfgRegistryResp, err := ConfigureRegistry(ctx, lggr, req, req.Env.ExistingAddresses) + addrBook := req.Env.ExistingAddresses + if req.DoContractDeploy { + contractDeployCS, err := DeployContracts(lggr, req.Env, req.RegistryChainSel) + if err != nil { + return nil, fmt.Errorf("failed to deploy contracts: %w", err) + } + addrBook = contractDeployCS.AddressBook + } else { + lggr.Debug("skipping contract deployment") + } + if addrBook == nil { + return nil, errors.New("address book is nil") + } + + cfgRegistryResp, err := ConfigureRegistry(ctx, lggr, req, addrBook) if err != nil { return nil, fmt.Errorf("failed to configure registry: %w", err) } @@ -91,33 +105,31 @@ func ConfigureContracts(ctx context.Context, lggr logger.Logger, req ConfigureCo if err != nil { return nil, fmt.Errorf("failed to assimilate registry to Dons: %w", err) } - // ignore response because we are not using mcms here and therefore no proposals are returned - _, err = ConfigureForwardContracts(req.Env, ConfigureForwarderContractsRequest{ - Dons: dons, - }) + err = ConfigureForwardContracts(req.Env, dons, addrBook) if err != nil { return nil, fmt.Errorf("failed to configure forwarder contracts: %w", err) } - err = ConfigureOCR3Contract(req.Env, req.RegistryChainSel, dons, req.OCR3Config) + err = ConfigureOCR3Contract(req.Env, req.RegistryChainSel, dons, addrBook, req.OCR3Config) if err != nil { return nil, fmt.Errorf("failed to configure OCR3 contract: %w", err) } return &ConfigureContractsResponse{ - Changeset: &deployment.ChangesetOutput{}, // no new addresses, proposals etc - DonInfos: cfgRegistryResp.DonInfos, + Changeset: &deployment.ChangesetOutput{ + AddressBook: addrBook, + }, + DonInfos: cfgRegistryResp.DonInfos, }, nil } // DeployContracts deploys the all the keystone contracts on all chains and returns the address book in the changeset -func DeployContracts(e *deployment.Environment, chainSel uint64) (*deployment.ChangesetOutput, error) { - lggr := e.Logger +func DeployContracts(lggr logger.Logger, e *deployment.Environment, chainSel uint64) (*deployment.ChangesetOutput, error) { adbook := deployment.NewMemoryAddressBook() // deploy contracts on all chains and track the registry and ocr3 contracts for _, chain := range e.Chains { lggr.Infow("deploying contracts", "chain", chain.Selector) - deployResp, err := deployContractsToChain(deployContractsRequest{ + deployResp, err := deployContractsToChain(lggr, deployContractsRequest{ chain: chain, isRegistryChain: chain.Selector == chainSel, }, @@ -138,9 +150,76 @@ func DeployContracts(e *deployment.Environment, chainSel uint64) (*deployment.Ch // DonInfo is DonCapabilities, but expanded to contain node information type DonInfo struct { Name string - F uint8 - Nodes []deployment.Node - Capabilities []capabilities_registry.CapabilitiesRegistryCapability // every capability is hosted on each node + Nodes []Node + Capabilities []kcr.CapabilitiesRegistryCapability // every capability is hosted on each node +} + +// TODO: merge with deployment/environment.go Node +type Node struct { + ID string + P2PID string + Name string + PublicKey *string + ChainConfigs []*nodev1.ChainConfig +} + +// TODO: merge with deployment/environment.go NodeInfo, we currently lookup based on p2p_id, and chain-selectors needs non-EVM support +func NodesFromJD(name string, nodeIDs []string, jd deployment.OffchainClient) ([]Node, error) { + // lookup nodes based on p2p_ids + var nodes []Node + selector := strings.Join(nodeIDs, ",") + nodesFromJD, err := jd.ListNodes(context.Background(), &nodev1.ListNodesRequest{ + Filter: &nodev1.ListNodesRequest_Filter{ + Enabled: 1, + Selectors: []*ptypes.Selector{ + { + Key: "p2p_id", + Op: ptypes.SelectorOp_IN, + Value: &selector, + }, + }, + }, + }) + if err != nil { + return nil, fmt.Errorf("failed to list nodes '%s': %w", name, err) + } + + for _, id := range nodeIDs { + idx := slices.IndexFunc(nodesFromJD.GetNodes(), func(node *nodev1.Node) bool { + return slices.ContainsFunc(node.Labels, func(label *ptypes.Label) bool { + return label.Key == "p2p_id" && *label.Value == id + }) + }) + if idx < 0 { + var got []string + for _, node := range nodesFromJD.GetNodes() { + for _, label := range node.Labels { + if label.Key == "p2p_id" { + got = append(got, *label.Value) + } + } + } + return nil, fmt.Errorf("node id %s not found in list '%s'", id, strings.Join(got, ",")) + } + + jdNode := nodesFromJD.Nodes[idx] + // TODO: Filter should accept multiple nodes + nodeChainConfigs, err := jd.ListNodeChainConfigs(context.Background(), &nodev1.ListNodeChainConfigsRequest{Filter: &nodev1.ListNodeChainConfigsRequest_Filter{ + NodeIds: []string{jdNode.Id}, // must use the jd-specific internal node id + }}) + if err != nil { + return nil, err + } + + nodes = append(nodes, Node{ + ID: jdNode.Id, + P2PID: id, + Name: name, + PublicKey: &jdNode.PublicKey, + ChainConfigs: nodeChainConfigs.GetChainConfigs(), + }) + } + return nodes, nil } func DonInfos(dons []DonCapabilities, jd deployment.OffchainClient) ([]DonInfo, error) { @@ -150,13 +229,12 @@ func DonInfos(dons []DonCapabilities, jd deployment.OffchainClient) ([]DonInfo, for _, nop := range don.Nops { nodeIDs = append(nodeIDs, nop.Nodes...) } - nodes, err := deployment.NodeInfo(nodeIDs, jd) + nodes, err := NodesFromJD(don.Name, nodeIDs, jd) if err != nil { return nil, err } donInfos = append(donInfos, DonInfo{ Name: don.Name, - F: don.F, Nodes: nodes, Capabilities: don.Capabilities, }) @@ -164,45 +242,42 @@ func DonInfos(dons []DonCapabilities, jd deployment.OffchainClient) ([]DonInfo, return donInfos, nil } -func GetRegistryContract(e *deployment.Environment, registryChainSel uint64) (*capabilities_registry.CapabilitiesRegistry, deployment.Chain, error) { - registryChain, ok := e.Chains[registryChainSel] +// ConfigureRegistry configures the registry contract with the given DONS and their capabilities +// the address book is required to contain the addresses of the deployed registry contract +func ConfigureRegistry(ctx context.Context, lggr logger.Logger, req ConfigureContractsRequest, addrBook deployment.AddressBook) (*ConfigureContractsResponse, error) { + registryChain, ok := req.Env.Chains[req.RegistryChainSel] if !ok { - return nil, deployment.Chain{}, fmt.Errorf("chain %d not found in environment", registryChainSel) + return nil, fmt.Errorf("chain %d not found in environment", req.RegistryChainSel) } - contractSetsResp, err := GetContractSets(e.Logger, &GetContractSetsRequest{ - Chains: e.Chains, - AddressBook: e.ExistingAddresses, + contractSetsResp, err := GetContractSets(req.Env.Logger, &GetContractSetsRequest{ + Chains: req.Env.Chains, + AddressBook: addrBook, }) if err != nil { - return nil, deployment.Chain{}, fmt.Errorf("failed to get contract sets: %w", err) + return nil, fmt.Errorf("failed to get contract sets: %w", err) + } + + donInfos, err := DonInfos(req.Dons, req.Env.Offchain) + if err != nil { + return nil, fmt.Errorf("failed to get don infos: %w", err) } // ensure registry is deployed and get the registry contract and chain - var registry *capabilities_registry.CapabilitiesRegistry - registryChainContracts, ok := contractSetsResp.ContractSets[registryChainSel] + var registry *kcr.CapabilitiesRegistry + registryChainContracts, ok := contractSetsResp.ContractSets[req.RegistryChainSel] if !ok { - return nil, deployment.Chain{}, fmt.Errorf("failed to deploy registry chain contracts. expected chain %d", registryChainSel) + return nil, fmt.Errorf("failed to deploy registry chain contracts. expected chain %d", req.RegistryChainSel) } registry = registryChainContracts.CapabilitiesRegistry if registry == nil { - return nil, deployment.Chain{}, fmt.Errorf("no registry contract found") - } - e.Logger.Debugf("registry contract address: %s, chain %d", registry.Address().String(), registryChainSel) - return registry, registryChain, nil -} - -// ConfigureRegistry configures the registry contract with the given DONS and their capabilities -// the address book is required to contain the addresses of the deployed registry contract -func ConfigureRegistry(ctx context.Context, lggr logger.Logger, req ConfigureContractsRequest, addrBook deployment.AddressBook) (*ConfigureContractsResponse, error) { - donInfos, err := DonInfos(req.Dons, req.Env.Offchain) - if err != nil { - return nil, fmt.Errorf("failed to get don infos: %w", err) + return nil, fmt.Errorf("no registry contract found") } + lggr.Debugf("registry contract address: %s, chain %d", registry.Address().String(), req.RegistryChainSel) // all the subsequent calls to the registry are in terms of nodes // compute the mapping of dons to their nodes for reuse in various registry calls - donToNodes, err := mapDonsToNodes(donInfos, true, req.RegistryChainSel) + donToOcr2Nodes, err := mapDonsToNodes(donInfos, true, req.RegistryChainSel) if err != nil { return nil, fmt.Errorf("failed to map dons to nodes: %w", err) } @@ -216,22 +291,22 @@ func ConfigureRegistry(ctx context.Context, lggr logger.Logger, req ConfigureCon } // register capabilities - capabilitiesResp, err := RegisterCapabilities(lggr, RegisterCapabilitiesRequest{ - Env: req.Env, - RegistryChainSelector: req.RegistryChainSel, - DonToCapabilities: donToCapabilities, + capabilitiesResp, err := registerCapabilities(lggr, registerCapabilitiesRequest{ + chain: registryChain, + registry: registry, + donToCapabilities: donToCapabilities, }) if err != nil { return nil, fmt.Errorf("failed to register capabilities: %w", err) } - lggr.Infow("registered capabilities", "capabilities", capabilitiesResp.DonToCapabilities) + lggr.Infow("registered capabilities", "capabilities", capabilitiesResp.donToCapabilities) // register node operators nopsList := maps.Keys(nopsToNodeIDs) nopsResp, err := RegisterNOPS(ctx, lggr, RegisterNOPSRequest{ - Env: req.Env, - RegistryChainSelector: req.RegistryChainSel, - Nops: nopsList, + Chain: registryChain, + Registry: registry, + Nops: nopsList, }) if err != nil { return nil, fmt.Errorf("failed to register node operators: %w", err) @@ -239,13 +314,13 @@ func ConfigureRegistry(ctx context.Context, lggr logger.Logger, req ConfigureCon lggr.Infow("registered node operators", "nops", nopsResp.Nops) // register nodes - nodesResp, err := RegisterNodes(lggr, &RegisterNodesRequest{ - Env: req.Env, - RegistryChainSelector: req.RegistryChainSel, - NopToNodeIDs: nopsToNodeIDs, - DonToNodes: donToNodes, - DonToCapabilities: capabilitiesResp.DonToCapabilities, - Nops: nopsResp.Nops, + nodesResp, err := registerNodes(lggr, ®isterNodesRequest{ + registry: registry, + chain: registryChain, + nopToNodeIDs: nopsToNodeIDs, + donToOcr2Nodes: donToOcr2Nodes, + donToCapabilities: capabilitiesResp.donToCapabilities, + nops: nopsResp.Nops, }) if err != nil { return nil, fmt.Errorf("failed to register nodes: %w", err) @@ -254,51 +329,60 @@ func ConfigureRegistry(ctx context.Context, lggr logger.Logger, req ConfigureCon // TODO: annotate nodes with node_operator_id in JD? - donsToRegister := []DONToRegister{} - for _, don := range req.Dons { - nodes, ok := donToNodes[don.Name] - if !ok { - return nil, fmt.Errorf("nodes not found for don %s", don.Name) - } - f := don.F - if f == 0 { - // TODO: fallback to a default value for compatibility - change to error - f = uint8(len(nodes) / 3) - lggr.Warnw("F not set for don - falling back to default", "don", don.Name, "f", f) - } - donsToRegister = append(donsToRegister, DONToRegister{ - Name: don.Name, - F: f, - Nodes: nodes, - }) - } - - nodeIdToP2PID := map[string][32]byte{} - for nodeID, params := range nodesResp.nodeIDToParams { - nodeIdToP2PID[nodeID] = params.P2pId - } // register DONS - donsResp, err := RegisterDons(lggr, RegisterDonsRequest{ - Env: req.Env, - RegistryChainSelector: req.RegistryChainSel, - NodeIDToP2PID: nodeIdToP2PID, - DonToCapabilities: capabilitiesResp.DonToCapabilities, - DonsToRegister: donsToRegister, + donsResp, err := registerDons(lggr, registerDonsRequest{ + registry: registry, + chain: registryChain, + nodeIDToParams: nodesResp.nodeIDToParams, + donToCapabilities: capabilitiesResp.donToCapabilities, + donToOcr2Nodes: donToOcr2Nodes, }) if err != nil { return nil, fmt.Errorf("failed to register DONS: %w", err) } - lggr.Infow("registered DONs", "dons", len(donsResp.DonInfos)) + lggr.Infow("registered DONs", "dons", len(donsResp.donInfos)) return &ConfigureContractsResponse{ - Changeset: &deployment.ChangesetOutput{}, // no new addresses, proposals etc - DonInfos: donsResp.DonInfos, + Changeset: &deployment.ChangesetOutput{ + AddressBook: addrBook, + }, + DonInfos: donsResp.donInfos, }, nil } -// Depreciated: use changeset.ConfigureOCR3Contract instead +// ConfigureForwardContracts configures the forwarder contracts on all chains for the given DONS +// the address book is required to contain the an address of the deployed forwarder contract for every chain in the environment +func ConfigureForwardContracts(env *deployment.Environment, dons []RegisteredDon, addrBook deployment.AddressBook) error { + contractSetsResp, err := GetContractSets(env.Logger, &GetContractSetsRequest{ + Chains: env.Chains, + AddressBook: addrBook, + }) + if err != nil { + return fmt.Errorf("failed to get contract sets: %w", err) + } + + // configure forwarders on all chains + for _, chain := range env.Chains { + // get the forwarder contract for the chain + contracts, ok := contractSetsResp.ContractSets[chain.Selector] + if !ok { + return fmt.Errorf("failed to get contract set for chain %d", chain.Selector) + } + fwrd := contracts.Forwarder + if fwrd == nil { + return fmt.Errorf("no forwarder contract found for chain %d", chain.Selector) + } + + err := configureForwarder(env.Logger, chain, fwrd, dons) + if err != nil { + return fmt.Errorf("failed to configure forwarder for chain selector %d: %w", chain.Selector, err) + } + } + return nil +} + // ocr3 contract on the registry chain for the wf dons -func ConfigureOCR3Contract(env *deployment.Environment, chainSel uint64, dons []RegisteredDon, cfg *OracleConfig) error { +func ConfigureOCR3Contract(env *deployment.Environment, chainSel uint64, dons []RegisteredDon, addrBook deployment.AddressBook, cfg *OracleConfigWithSecrets) error { registryChain, ok := env.Chains[chainSel] if !ok { return fmt.Errorf("chain %d not found in environment", chainSel) @@ -306,7 +390,7 @@ func ConfigureOCR3Contract(env *deployment.Environment, chainSel uint64, dons [] contractSetsResp, err := GetContractSets(env.Logger, &GetContractSetsRequest{ Chains: env.Chains, - AddressBook: env.ExistingAddresses, + AddressBook: addrBook, }) if err != nil { return fmt.Errorf("failed to get contract sets: %w", err) @@ -327,12 +411,10 @@ func ConfigureOCR3Contract(env *deployment.Environment, chainSel uint64, dons [] } _, err := configureOCR3contract(configureOCR3Request{ - cfg: cfg, - chain: registryChain, - contract: contract, - nodes: don.Nodes, - contractSet: &contracts, - ocrSecrets: env.OCRSecrets, + cfg: cfg, + chain: registryChain, + contract: contract, + nodes: don.Nodes, }) if err != nil { return fmt.Errorf("failed to configure OCR3 contract for don %s: %w", don.Name, err) @@ -341,127 +423,81 @@ func ConfigureOCR3Contract(env *deployment.Environment, chainSel uint64, dons [] return nil } -type ConfigureOCR3Resp struct { - OCR2OracleConfig - Ops *timelock.BatchChainOperation -} - -type ConfigureOCR3Config struct { - ChainSel uint64 - NodeIDs []string - OCR3Config *OracleConfig - DryRun bool - - UseMCMS bool -} - -// Depreciated: use changeset.ConfigureOCR3Contract instead -func ConfigureOCR3ContractFromJD(env *deployment.Environment, cfg ConfigureOCR3Config) (*ConfigureOCR3Resp, error) { - prefix := "" - if cfg.DryRun { - prefix = "DRY RUN: " - } - env.Logger.Infof("%sconfiguring OCR3 contract for chain %d", prefix, cfg.ChainSel) - registryChain, ok := env.Chains[cfg.ChainSel] +func ConfigureOCR3ContractFromJD(env *deployment.Environment, chainSel uint64, nodeIDs []string, addrBook deployment.AddressBook, cfg *OracleConfigWithSecrets) error { + registryChain, ok := env.Chains[chainSel] if !ok { - return nil, fmt.Errorf("chain %d not found in environment", cfg.ChainSel) + return fmt.Errorf("chain %d not found in environment", chainSel) } contractSetsResp, err := GetContractSets(env.Logger, &GetContractSetsRequest{ Chains: env.Chains, - AddressBook: env.ExistingAddresses, + AddressBook: addrBook, }) if err != nil { - return nil, fmt.Errorf("failed to get contract sets: %w", err) + return fmt.Errorf("failed to get contract sets: %w", err) } - contracts, ok := contractSetsResp.ContractSets[cfg.ChainSel] + contracts, ok := contractSetsResp.ContractSets[chainSel] if !ok { - return nil, fmt.Errorf("failed to get contract set for chain %d", cfg.ChainSel) + return fmt.Errorf("failed to get contract set for chain %d", chainSel) } contract := contracts.OCR3 if contract == nil { - return nil, fmt.Errorf("no ocr3 contract found for chain %d", cfg.ChainSel) + return fmt.Errorf("no ocr3 contract found for chain %d", chainSel) } - nodes, err := deployment.NodeInfo(cfg.NodeIDs, env.Offchain) + nodes, err := NodesFromJD("nodes", nodeIDs, env.Offchain) if err != nil { - return nil, err + return err } - r, err := configureOCR3contract(configureOCR3Request{ - cfg: cfg.OCR3Config, - chain: registryChain, - contract: contract, - nodes: nodes, - dryRun: cfg.DryRun, - contractSet: &contracts, - useMCMS: cfg.UseMCMS, - ocrSecrets: env.OCRSecrets, - }) - if err != nil { - return nil, err + var ocr2nodes []*ocr2Node + for _, node := range nodes { + n, err := newOcr2NodeFromJD(&node, chainSel) + if err != nil { + return fmt.Errorf("failed to create ocr2 node from clo node: %w", err) + } + ocr2nodes = append(ocr2nodes, n) } - return &ConfigureOCR3Resp{ - OCR2OracleConfig: r.ocrConfig, - Ops: r.ops, - }, nil - + _, err = configureOCR3contract(configureOCR3Request{ + cfg: cfg, + chain: registryChain, + contract: contract, + nodes: ocr2nodes, + }) + return err } -type RegisterCapabilitiesRequest struct { - Env *deployment.Environment - RegistryChainSelector uint64 - DonToCapabilities map[string][]capabilities_registry.CapabilitiesRegistryCapability +type registerCapabilitiesRequest struct { + chain deployment.Chain + registry *kcr.CapabilitiesRegistry + donToCapabilities map[string][]kcr.CapabilitiesRegistryCapability } -type RegisterCapabilitiesResponse struct { - DonToCapabilities map[string][]RegisteredCapability +type registerCapabilitiesResponse struct { + donToCapabilities map[string][]RegisteredCapability } type RegisteredCapability struct { - capabilities_registry.CapabilitiesRegistryCapability + kcr.CapabilitiesRegistryCapability ID [32]byte } -func FromCapabilitiesRegistryCapability(cap *capabilities_registry.CapabilitiesRegistryCapability, e deployment.Environment, registryChainSelector uint64) (*RegisteredCapability, error) { - registry, _, err := GetRegistryContract(&e, registryChainSelector) - if err != nil { - return nil, fmt.Errorf("failed to get registry: %w", err) - } - id, err := registry.GetHashedCapabilityId(&bind.CallOpts{}, cap.LabelledName, cap.Version) - if err != nil { - return nil, fmt.Errorf("failed to call GetHashedCapabilityId for capability %v: %w", cap, err) - } - return &RegisteredCapability{ - CapabilitiesRegistryCapability: *cap, - ID: id, - }, nil -} - -// RegisterCapabilities add computes the capability id, adds it to the registry and associates the registered capabilities with appropriate don(s) -func RegisterCapabilities(lggr logger.Logger, req RegisterCapabilitiesRequest) (*RegisterCapabilitiesResponse, error) { - if len(req.DonToCapabilities) == 0 { +// registerCapabilities add computes the capability id, adds it to the registry and associates the registered capabilities with appropriate don(s) +func registerCapabilities(lggr logger.Logger, req registerCapabilitiesRequest) (*registerCapabilitiesResponse, error) { + if len(req.donToCapabilities) == 0 { return nil, fmt.Errorf("no capabilities to register") } - cresp, err := GetContractSets(req.Env.Logger, &GetContractSetsRequest{ - Chains: req.Env.Chains, - AddressBook: req.Env.ExistingAddresses, - }) - contracts := cresp.ContractSets[req.RegistryChainSelector] - registry := contracts.CapabilitiesRegistry - registryChain := req.Env.Chains[req.RegistryChainSelector] - - lggr.Infow("registering capabilities...", "len", len(req.DonToCapabilities)) - resp := &RegisterCapabilitiesResponse{ - DonToCapabilities: make(map[string][]RegisteredCapability), + lggr.Infow("registering capabilities...", "len", len(req.donToCapabilities)) + resp := ®isterCapabilitiesResponse{ + donToCapabilities: make(map[string][]RegisteredCapability), } // capability could be hosted on multiple dons. need to deduplicate - uniqueCaps := make(map[capabilities_registry.CapabilitiesRegistryCapability][32]byte) - for don, caps := range req.DonToCapabilities { + uniqueCaps := make(map[kcr.CapabilitiesRegistryCapability][32]byte) + for don, caps := range req.donToCapabilities { var registerCaps []RegisteredCapability for _, cap := range caps { id, ok := uniqueCaps[cap] if !ok { var err error - id, err = registry.GetHashedCapabilityId(&bind.CallOpts{}, cap.LabelledName, cap.Version) + id, err = req.registry.GetHashedCapabilityId(&bind.CallOpts{}, cap.LabelledName, cap.Version) if err != nil { return nil, fmt.Errorf("failed to call GetHashedCapabilityId for capability %v: %w", cap, err) } @@ -474,19 +510,15 @@ func RegisterCapabilities(lggr logger.Logger, req RegisterCapabilitiesRequest) ( lggr.Debugw("hashed capability id", "capability", cap, "id", id) registerCaps = append(registerCaps, registerCap) } - resp.DonToCapabilities[don] = registerCaps + resp.donToCapabilities[don] = registerCaps } - var capabilities []capabilities_registry.CapabilitiesRegistryCapability + var capabilities []kcr.CapabilitiesRegistryCapability for cap := range uniqueCaps { capabilities = append(capabilities, cap) } - if len(capabilities) == 0 { - lggr.Warn("no new capabilities to register") - return &RegisterCapabilitiesResponse{}, nil - } - // not using mcms; ignore proposals - _, err = AddCapabilities(lggr, &contracts, registryChain, capabilities, false) + + err := AddCapabilities(lggr, req.registry, req.chain, capabilities) if err != nil { return nil, fmt.Errorf("failed to add capabilities: %w", err) } @@ -494,22 +526,18 @@ func RegisterCapabilities(lggr logger.Logger, req RegisterCapabilitiesRequest) ( } type RegisterNOPSRequest struct { - Env *deployment.Environment - RegistryChainSelector uint64 - Nops []capabilities_registry.CapabilitiesRegistryNodeOperator + Chain deployment.Chain + Registry *kcr.CapabilitiesRegistry + Nops []kcr.CapabilitiesRegistryNodeOperator } type RegisterNOPSResponse struct { - Nops []*capabilities_registry.CapabilitiesRegistryNodeOperatorAdded + Nops []*kcr.CapabilitiesRegistryNodeOperatorAdded } func RegisterNOPS(ctx context.Context, lggr logger.Logger, req RegisterNOPSRequest) (*RegisterNOPSResponse, error) { - registry, registryChain, err := GetRegistryContract(req.Env, req.RegistryChainSelector) - if err != nil { - return nil, fmt.Errorf("failed to get registry: %w", err) - } lggr.Infow("registering node operators...", "len", len(req.Nops)) - existingNops, err := registry.GetNodeOperators(&bind.CallOpts{}) + existingNops, err := req.Registry.GetNodeOperators(&bind.CallOpts{}) if err != nil { return nil, err } @@ -519,15 +547,15 @@ func RegisterNOPS(ctx context.Context, lggr logger.Logger, req RegisterNOPSReque } lggr.Infow("fetched existing node operators", "len", len(existingNopsAddrToID)) resp := &RegisterNOPSResponse{ - Nops: []*capabilities_registry.CapabilitiesRegistryNodeOperatorAdded{}, + Nops: []*kcr.CapabilitiesRegistryNodeOperatorAdded{}, } - nops := []capabilities_registry.CapabilitiesRegistryNodeOperator{} + nops := []kcr.CapabilitiesRegistryNodeOperator{} for _, nop := range req.Nops { if id, ok := existingNopsAddrToID[nop]; !ok { nops = append(nops, nop) } else { lggr.Debugw("node operator already exists", "name", nop.Name, "admin", nop.Admin.String(), "id", id) - resp.Nops = append(resp.Nops, &capabilities_registry.CapabilitiesRegistryNodeOperatorAdded{ + resp.Nops = append(resp.Nops, &kcr.CapabilitiesRegistryNodeOperatorAdded{ NodeOperatorId: id, Name: nop.Name, Admin: nop.Admin, @@ -538,19 +566,19 @@ func RegisterNOPS(ctx context.Context, lggr logger.Logger, req RegisterNOPSReque lggr.Debug("no new node operators to register") return resp, nil } - tx, err := registry.AddNodeOperators(registryChain.DeployerKey, nops) + tx, err := req.Registry.AddNodeOperators(req.Chain.DeployerKey, nops) if err != nil { - err = deployment.DecodeErr(capabilities_registry.CapabilitiesRegistryABI, err) + err = DecodeErr(kcr.CapabilitiesRegistryABI, err) return nil, fmt.Errorf("failed to call AddNodeOperators: %w", err) } // for some reason that i don't understand, the confirm must be called before the WaitMined or the latter will hang // (at least for a simulated backend chain) - _, err = registryChain.Confirm(tx) + _, err = req.Chain.Confirm(tx) if err != nil { return nil, fmt.Errorf("failed to confirm AddNodeOperators confirm transaction %s: %w", tx.Hash().String(), err) } - receipt, err := bind.WaitMined(ctx, registryChain.Client, tx) + receipt, err := bind.WaitMined(ctx, req.Chain.Client, tx) if err != nil { return nil, fmt.Errorf("failed to mine AddNodeOperators confirm transaction %s: %w", tx.Hash().String(), err) } @@ -558,7 +586,7 @@ func RegisterNOPS(ctx context.Context, lggr logger.Logger, req RegisterNOPSReque return nil, fmt.Errorf("expected %d log entries for AddNodeOperators, got %d", len(nops), len(receipt.Logs)) } for i, log := range receipt.Logs { - o, err := registry.ParseNodeOperatorAdded(*log) + o, err := req.Registry.ParseNodeOperatorAdded(*log) if err != nil { return nil, fmt.Errorf("failed to parse log %d for operator added: %w", i, err) } @@ -603,39 +631,58 @@ func DefaultCapConfig(capType uint8, nNodes int) *capabilitiespb.CapabilityConfi } } +func DecodeErr(encodedABI string, err error) error { + if err == nil { + return nil + } + + //revive:disable + var d rpc.DataError + ok := errors.As(err, &d) + if ok { + encErr, ok := d.ErrorData().(string) + if !ok { + return fmt.Errorf("error without error data: %s", d.Error()) + } + errStr, parseErr := deployment.ParseErrorFromABI(encErr, encodedABI) + if parseErr != nil { + return fmt.Errorf("failed to decode error '%s' with abi: %w", encErr, parseErr) + } + return fmt.Errorf("contract error: %s", errStr) + + } + return fmt.Errorf("cannot decode error with abi: %w", err) +} + // register nodes -type RegisterNodesRequest struct { - Env *deployment.Environment - RegistryChainSelector uint64 - NopToNodeIDs map[capabilities_registry.CapabilitiesRegistryNodeOperator][]string - DonToNodes map[string][]deployment.Node - DonToCapabilities map[string][]RegisteredCapability - Nops []*capabilities_registry.CapabilitiesRegistryNodeOperatorAdded +type registerNodesRequest struct { + registry *kcr.CapabilitiesRegistry + chain deployment.Chain + nopToNodeIDs map[kcr.CapabilitiesRegistryNodeOperator][]string + donToOcr2Nodes map[string][]*ocr2Node + donToCapabilities map[string][]RegisteredCapability + nops []*kcr.CapabilitiesRegistryNodeOperatorAdded } -type RegisterNodesResponse struct { - nodeIDToParams map[string]capabilities_registry.CapabilitiesRegistryNodeParams +type registerNodesResponse struct { + nodeIDToParams map[string]kcr.CapabilitiesRegistryNodeParams } // registerNodes registers the nodes with the registry. it assumes that the deployer key in the Chain // can sign the transactions update the contract state -func RegisterNodes(lggr logger.Logger, req *RegisterNodesRequest) (*RegisterNodesResponse, error) { - registry, registryChain, err := GetRegistryContract(req.Env, req.RegistryChainSelector) - if err != nil { - return nil, fmt.Errorf("failed to get registry: %w", err) - } - +// TODO: 467 refactor to support MCMS. Specifically need to separate the call data generation from the actual contract call +func registerNodes(lggr logger.Logger, req *registerNodesRequest) (*registerNodesResponse, error) { var count int - for _, nodes := range req.NopToNodeIDs { + for _, nodes := range req.nopToNodeIDs { count += len(nodes) } lggr.Infow("registering nodes...", "len", count) - nodeToRegisterNop := make(map[string]*capabilities_registry.CapabilitiesRegistryNodeOperatorAdded) - for _, nop := range req.Nops { - n := capabilities_registry.CapabilitiesRegistryNodeOperator{ + nodeToRegisterNop := make(map[string]*kcr.CapabilitiesRegistryNodeOperatorAdded) + for _, nop := range req.nops { + n := kcr.CapabilitiesRegistryNodeOperator{ Name: nop.Name, Admin: nop.Admin, } - nodeIDs := req.NopToNodeIDs[n] + nodeIDs := req.nopToNodeIDs[n] for _, nodeID := range nodeIDs { _, exists := nodeToRegisterNop[nodeID] if !exists { @@ -644,21 +691,11 @@ func RegisterNodes(lggr logger.Logger, req *RegisterNodesRequest) (*RegisterNode } } - // TODO: deduplicate everywhere - registryChainID, err := chainsel.ChainIdFromSelector(registryChain.Selector) - if err != nil { - return nil, err - } - registryChainDetails, err := chainsel.GetChainDetailsByChainIDAndFamily(strconv.Itoa(int(registryChainID)), chainsel.FamilyEVM) - if err != nil { - return nil, err - } - - nodeIDToParams := make(map[string]capabilities_registry.CapabilitiesRegistryNodeParams) - for don, nodes := range req.DonToNodes { - caps, ok := req.DonToCapabilities[don] + nodeIDToParams := make(map[string]kcr.CapabilitiesRegistryNodeParams) + for don, ocr2nodes := range req.donToOcr2Nodes { + caps, ok := req.donToCapabilities[don] if !ok { - return nil, fmt.Errorf("capabilities not found for don %s", don) + return nil, fmt.Errorf("capabilities not found for node operator %s", don) } var hashedCapabilityIds [][32]byte for _, cap := range caps { @@ -666,30 +703,22 @@ func RegisterNodes(lggr logger.Logger, req *RegisterNodesRequest) (*RegisterNode } lggr.Debugw("hashed capability ids", "don", don, "ids", hashedCapabilityIds) - for _, n := range nodes { - if n.IsBootstrap { // bootstraps are part of the DON but don't host capabilities + for _, n := range ocr2nodes { + if n.IsBoostrap { // bootstraps are part of the DON but don't host capabilities continue } - nop, ok := nodeToRegisterNop[n.NodeID] + nop, ok := nodeToRegisterNop[n.ID] if !ok { - return nil, fmt.Errorf("node operator not found for node %s", n.NodeID) + return nil, fmt.Errorf("node operator not found for node %s", n.ID) } - params, ok := nodeIDToParams[n.NodeID] + params, ok := nodeIDToParams[n.ID] if !ok { - evmCC, exists := n.SelToOCRConfig[registryChainDetails] - if !exists { - return nil, fmt.Errorf("config for selector %v not found on node (id: %s, name: %s)", registryChain.Selector, n.NodeID, n.Name) - } - var signer [32]byte - copy(signer[:], evmCC.OnchainPublicKey) - var csakey [32]byte - copy(csakey[:], evmCC.ConfigEncryptionPublicKey[:]) - params = capabilities_registry.CapabilitiesRegistryNodeParams{ + params = kcr.CapabilitiesRegistryNodeParams{ NodeOperatorId: nop.NodeOperatorId, - Signer: signer, - P2pId: n.PeerID, - EncryptionPublicKey: csakey, + Signer: n.Signer, + P2pId: n.P2PKey, + EncryptionPublicKey: n.EncryptionPublicKey, HashedCapabilityIds: hashedCapabilityIds, } } else { @@ -709,18 +738,18 @@ func RegisterNodes(lggr logger.Logger, req *RegisterNodesRequest) (*RegisterNode } params.HashedCapabilityIds = append(params.HashedCapabilityIds, newCapIds...) } - nodeIDToParams[n.NodeID] = params + nodeIDToParams[n.ID] = params } } - var uniqueNodeParams []capabilities_registry.CapabilitiesRegistryNodeParams + var uniqueNodeParams []kcr.CapabilitiesRegistryNodeParams for _, v := range nodeIDToParams { uniqueNodeParams = append(uniqueNodeParams, v) } - lggr.Debugw("unique node params to add", "count", len(uniqueNodeParams), "params", uniqueNodeParams) - tx, err := registry.AddNodes(registryChain.DeployerKey, uniqueNodeParams) + lggr.Debugw("unique node params to add", "count", len(uniqueNodeParams)) + tx, err := req.registry.AddNodes(req.chain.DeployerKey, uniqueNodeParams) if err != nil { - err = deployment.DecodeErr(capabilities_registry.CapabilitiesRegistryABI, err) + err = DecodeErr(kcr.CapabilitiesRegistryABI, err) // no typed errors in the abi, so we have to do string matching // try to add all nodes in one go, if that fails, fall back to 1-by-1 if !strings.Contains(err.Error(), "NodeAlreadyExists") { @@ -728,9 +757,9 @@ func RegisterNodes(lggr logger.Logger, req *RegisterNodesRequest) (*RegisterNode } lggr.Warn("nodes already exist, falling back to 1-by-1") for _, singleNodeParams := range uniqueNodeParams { - tx, err = registry.AddNodes(registryChain.DeployerKey, []capabilities_registry.CapabilitiesRegistryNodeParams{singleNodeParams}) + tx, err = req.registry.AddNodes(req.chain.DeployerKey, []kcr.CapabilitiesRegistryNodeParams{singleNodeParams}) if err != nil { - err = deployment.DecodeErr(capabilities_registry.CapabilitiesRegistryABI, err) + err = DecodeErr(kcr.CapabilitiesRegistryABI, err) if strings.Contains(err.Error(), "NodeAlreadyExists") { lggr.Warnw("node already exists, skipping", "p2pid", hex.EncodeToString(singleNodeParams.P2pId[:])) continue @@ -738,7 +767,7 @@ func RegisterNodes(lggr logger.Logger, req *RegisterNodesRequest) (*RegisterNode return nil, fmt.Errorf("failed to call AddNode for node with p2pid %v: %w", singleNodeParams.P2pId, err) } // 1-by-1 tx is pending and we need to wait for it to be mined - _, err = registryChain.Confirm(tx) + _, err = req.chain.Confirm(tx) if err != nil { return nil, fmt.Errorf("failed to confirm AddNode of p2pid node %v transaction %s: %w", singleNodeParams.P2pId, tx.Hash().String(), err) } @@ -746,33 +775,27 @@ func RegisterNodes(lggr logger.Logger, req *RegisterNodesRequest) (*RegisterNode } } else { // the bulk add tx is pending and we need to wait for it to be mined - _, err = registryChain.Confirm(tx) + _, err = req.chain.Confirm(tx) if err != nil { return nil, fmt.Errorf("failed to confirm AddNode confirm transaction %s: %w", tx.Hash().String(), err) } } - return &RegisterNodesResponse{ + return ®isterNodesResponse{ nodeIDToParams: nodeIDToParams, }, nil } -type DONToRegister struct { - Name string - F uint8 - Nodes []deployment.Node -} +type registerDonsRequest struct { + registry *kcr.CapabilitiesRegistry + chain deployment.Chain -type RegisterDonsRequest struct { - Env *deployment.Environment - RegistryChainSelector uint64 - - NodeIDToP2PID map[string][32]byte - DonToCapabilities map[string][]RegisteredCapability - DonsToRegister []DONToRegister + nodeIDToParams map[string]kcr.CapabilitiesRegistryNodeParams + donToCapabilities map[string][]RegisteredCapability + donToOcr2Nodes map[string][]*ocr2Node } -type RegisterDonsResponse struct { - DonInfos map[string]capabilities_registry.CapabilitiesRegistryDONInfo +type registerDonsResponse struct { + donInfos map[string]kcr.CapabilitiesRegistryDONInfo } func sortedHash(p2pids [][32]byte) string { @@ -786,20 +809,16 @@ func sortedHash(p2pids [][32]byte) string { return hex.EncodeToString(sha256Hash.Sum(nil)) } -func RegisterDons(lggr logger.Logger, req RegisterDonsRequest) (*RegisterDonsResponse, error) { - registry, registryChain, err := GetRegistryContract(req.Env, req.RegistryChainSelector) - if err != nil { - return nil, fmt.Errorf("failed to get registry: %w", err) - } - lggr.Infow("registering DONs...", "len", len(req.DonsToRegister)) +func registerDons(lggr logger.Logger, req registerDonsRequest) (*registerDonsResponse, error) { + lggr.Infow("registering DONs...", "len", len(req.donToOcr2Nodes)) // track hash of sorted p2pids to don name because the registry return value does not include the don name // and we need to map it back to the don name to access the other mapping data such as the don's capabilities & nodes p2pIdsToDon := make(map[string]string) var addedDons = 0 - donInfos, err := registry.GetDONs(&bind.CallOpts{}) + donInfos, err := req.registry.GetDONs(&bind.CallOpts{}) if err != nil { - err = deployment.DecodeErr(capabilities_registry.CapabilitiesRegistryABI, err) + err = DecodeErr(kcr.CapabilitiesRegistryABI, err) return nil, fmt.Errorf("failed to call GetDONs: %w", err) } existingDONs := make(map[string]struct{}) @@ -808,33 +827,33 @@ func RegisterDons(lggr logger.Logger, req RegisterDonsRequest) (*RegisterDonsRes } lggr.Infow("fetched existing DONs...", "len", len(donInfos), "lenByNodesHash", len(existingDONs)) - for _, don := range req.DonsToRegister { + for don, ocr2nodes := range req.donToOcr2Nodes { var p2pIds [][32]byte - for _, n := range don.Nodes { - if n.IsBootstrap { + for _, n := range ocr2nodes { + if n.IsBoostrap { continue } - p2pID, ok := req.NodeIDToP2PID[n.NodeID] + params, ok := req.nodeIDToParams[n.ID] if !ok { - return nil, fmt.Errorf("node params not found for non-bootstrap node %s", n.NodeID) + return nil, fmt.Errorf("node params not found for non-bootstrap node %s", n.ID) } - p2pIds = append(p2pIds, p2pID) + p2pIds = append(p2pIds, params.P2pId) } p2pSortedHash := sortedHash(p2pIds) - p2pIdsToDon[p2pSortedHash] = don.Name + p2pIdsToDon[p2pSortedHash] = don if _, ok := existingDONs[p2pSortedHash]; ok { lggr.Debugw("don already exists, ignoring", "don", don, "p2p sorted hash", p2pSortedHash) continue } - caps, ok := req.DonToCapabilities[don.Name] + caps, ok := req.donToCapabilities[don] if !ok { - return nil, fmt.Errorf("capabilities not found for DON %s", don.Name) + return nil, fmt.Errorf("capabilities not found for node operator %s", don) } wfSupported := false - var cfgs []capabilities_registry.CapabilitiesRegistryCapabilityConfiguration + var cfgs []kcr.CapabilitiesRegistryCapabilityConfiguration for _, cap := range caps { if cap.CapabilityType == 2 { // OCR3 capability => WF supported wfSupported = true @@ -845,22 +864,23 @@ func RegisterDons(lggr logger.Logger, req RegisterDonsRequest) (*RegisterDonsRes if err != nil { return nil, fmt.Errorf("failed to marshal capability config for %v: %w", cap, err) } - cfgs = append(cfgs, capabilities_registry.CapabilitiesRegistryCapabilityConfiguration{ + cfgs = append(cfgs, kcr.CapabilitiesRegistryCapabilityConfiguration{ CapabilityId: cap.ID, Config: cfgb, }) } - tx, err := registry.AddDON(registryChain.DeployerKey, p2pIds, cfgs, true, wfSupported, don.F) + f := len(p2pIds) / 3 // assuming n=3f+1. TODO should come for some config. + tx, err := req.registry.AddDON(req.chain.DeployerKey, p2pIds, cfgs, true, wfSupported, uint8(f)) if err != nil { - err = deployment.DecodeErr(capabilities_registry.CapabilitiesRegistryABI, err) - return nil, fmt.Errorf("failed to call AddDON for don '%s' p2p2Id hash %s capability %v: %w", don.Name, p2pSortedHash, cfgs, err) + err = DecodeErr(kcr.CapabilitiesRegistryABI, err) + return nil, fmt.Errorf("failed to call AddDON for don '%s' p2p2Id hash %s capability %v: %w", don, p2pSortedHash, cfgs, err) } - _, err = registryChain.Confirm(tx) + _, err = req.chain.Confirm(tx) if err != nil { - return nil, fmt.Errorf("failed to confirm AddDON transaction %s for don %s: %w", tx.Hash().String(), don.Name, err) + return nil, fmt.Errorf("failed to confirm AddDON transaction %s for don %s: %w", tx.Hash().String(), don, err) } - lggr.Debugw("registered DON", "don", don.Name, "p2p sorted hash", p2pSortedHash, "cgs", cfgs, "wfSupported", wfSupported, "f", don.F) + lggr.Debugw("registered DON", "don", don, "p2p sorted hash", p2pSortedHash, "cgs", cfgs, "wfSupported", wfSupported, "f", f) addedDons++ } lggr.Debugf("Registered all DONs (new=%d), waiting for registry to update", addedDons) @@ -870,7 +890,7 @@ func RegisterDons(lggr logger.Logger, req RegisterDonsRequest) (*RegisterDonsRes foundAll := false for i := 0; i < 10; i++ { lggr.Debugw("attempting to get DONs from registry", "attempt#", i) - donInfos, err = registry.GetDONs(&bind.CallOpts{}) + donInfos, err = req.registry.GetDONs(&bind.CallOpts{}) if !containsAllDONs(donInfos, p2pIdsToDon) { lggr.Debugw("some expected dons not registered yet, re-checking after a delay ...") time.Sleep(2 * time.Second) @@ -880,15 +900,15 @@ func RegisterDons(lggr logger.Logger, req RegisterDonsRequest) (*RegisterDonsRes } } if err != nil { - err = deployment.DecodeErr(capabilities_registry.CapabilitiesRegistryABI, err) + err = DecodeErr(kcr.CapabilitiesRegistryABI, err) return nil, fmt.Errorf("failed to call GetDONs: %w", err) } if !foundAll { return nil, fmt.Errorf("did not find all desired DONS") } - resp := RegisterDonsResponse{ - DonInfos: make(map[string]capabilities_registry.CapabilitiesRegistryDONInfo), + resp := registerDonsResponse{ + donInfos: make(map[string]kcr.CapabilitiesRegistryDONInfo), } for i, donInfo := range donInfos { donName, ok := p2pIdsToDon[sortedHash(donInfo.NodeP2PIds)] @@ -897,13 +917,13 @@ func RegisterDons(lggr logger.Logger, req RegisterDonsRequest) (*RegisterDonsRes continue } lggr.Debugw("adding don info to the reponse (keyed by DON name)", "don", donName) - resp.DonInfos[donName] = donInfos[i] + resp.donInfos[donName] = donInfos[i] } return &resp, nil } // are all DONs from p2pIdsToDon in donInfos -func containsAllDONs(donInfos []capabilities_registry.CapabilitiesRegistryDONInfo, p2pIdsToDon map[string]string) bool { +func containsAllDONs(donInfos []kcr.CapabilitiesRegistryDONInfo, p2pIdsToDon map[string]string) bool { found := make(map[string]struct{}) for _, donInfo := range donInfos { hash := sortedHash(donInfo.NodeP2PIds) @@ -916,50 +936,65 @@ func containsAllDONs(donInfos []capabilities_registry.CapabilitiesRegistryDONInf // configureForwarder sets the config for the forwarder contract on the chain for all Dons that accept workflows // dons that don't accept workflows are not registered with the forwarder -func configureForwarder(lggr logger.Logger, chain deployment.Chain, contractSet ContractSet, dons []RegisteredDon, useMCMS bool) (map[uint64]timelock.BatchChainOperation, error) { - if contractSet.Forwarder == nil { - return nil, errors.New("nil forwarder contract") +func configureForwarder(lggr logger.Logger, chain deployment.Chain, fwdr *kf.KeystoneForwarder, dons []RegisteredDon) error { + if fwdr == nil { + return errors.New("nil forwarder contract") } - var ( - fwdr = contractSet.Forwarder - opMap = make(map[uint64]timelock.BatchChainOperation) - ) for _, dn := range dons { if !dn.Info.AcceptsWorkflows { continue } ver := dn.Info.ConfigCount // note config count on the don info is the version on the forwarder - signers := dn.Signers(chainsel.FamilyEVM) - txOpts := chain.DeployerKey - if useMCMS { - txOpts = deployment.SimTransactOpts() - } - tx, err := fwdr.SetConfig(txOpts, dn.Info.Id, ver, dn.Info.F, signers) + tx, err := fwdr.SetConfig(chain.DeployerKey, dn.Info.Id, ver, dn.Info.F, dn.signers()) if err != nil { - err = deployment.DecodeErr(kf.KeystoneForwarderABI, err) - return nil, fmt.Errorf("failed to call SetConfig for forwarder %s on chain %d: %w", fwdr.Address().String(), chain.Selector, err) + err = DecodeErr(kf.KeystoneForwarderABI, err) + return fmt.Errorf("failed to call SetConfig for forwarder %s on chain %d: %w", fwdr.Address().String(), chain.Selector, err) } - if !useMCMS { - _, err = chain.Confirm(tx) - if err != nil { - err = deployment.DecodeErr(kf.KeystoneForwarderABI, err) - return nil, fmt.Errorf("failed to confirm SetConfig for forwarder %s: %w", fwdr.Address().String(), err) - } - } else { - // create the mcms proposals - ops := timelock.BatchChainOperation{ - ChainIdentifier: mcms.ChainIdentifier(chain.Selector), - Batch: []mcms.Operation{ - { - To: fwdr.Address(), - Data: tx.Data(), - Value: big.NewInt(0), - }, - }, - } - opMap[chain.Selector] = ops + _, err = chain.Confirm(tx) + if err != nil { + err = DecodeErr(kf.KeystoneForwarderABI, err) + return fmt.Errorf("failed to confirm SetConfig for forwarder %s: %w", fwdr.Address().String(), err) } - lggr.Debugw("configured forwarder", "forwarder", fwdr.Address().String(), "donId", dn.Info.Id, "version", ver, "f", dn.Info.F, "signers", signers) + lggr.Debugw("configured forwarder", "forwarder", fwdr.Address().String(), "donId", dn.Info.Id, "version", ver, "f", dn.Info.F, "signers", dn.signers()) + } + return nil +} + +type configureOCR3Request struct { + cfg *OracleConfigWithSecrets + chain deployment.Chain + contract *kocr3.OCR3Capability + nodes []*ocr2Node +} +type configureOCR3Response struct { + ocrConfig Orc2drOracleConfig +} + +func configureOCR3contract(req configureOCR3Request) (*configureOCR3Response, error) { + if req.contract == nil { + return nil, fmt.Errorf("OCR3 contract is nil") + } + nks := makeNodeKeysSlice(req.nodes) + ocrConfig, err := GenerateOCR3Config(*req.cfg, nks) + if err != nil { + return nil, fmt.Errorf("failed to generate OCR3 config: %w", err) + } + tx, err := req.contract.SetConfig(req.chain.DeployerKey, + ocrConfig.Signers, + ocrConfig.Transmitters, + ocrConfig.F, + ocrConfig.OnchainConfig, + ocrConfig.OffchainConfigVersion, + ocrConfig.OffchainConfig, + ) + if err != nil { + err = DecodeErr(kocr3.OCR3CapabilityABI, err) + return nil, fmt.Errorf("failed to call SetConfig for OCR3 contract %s: %w", req.contract.Address().String(), err) + } + _, err = req.chain.Confirm(tx) + if err != nil { + err = DecodeErr(kocr3.OCR3CapabilityABI, err) + return nil, fmt.Errorf("failed to confirm SetConfig for OCR3 contract %s: %w", req.contract.Address().String(), err) } - return opMap, nil + return &configureOCR3Response{ocrConfig}, nil } diff --git a/deployment/keystone/deploy_test.go b/deployment/keystone/deploy_test.go new file mode 100644 index 00000000000..4e0d2a52dcc --- /dev/null +++ b/deployment/keystone/deploy_test.go @@ -0,0 +1,439 @@ +package keystone_test + +import ( + "encoding/json" + "fmt" + "os" + "strconv" + "testing" + + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/stretchr/testify/assert" + "github.com/test-go/testify/require" + "go.uber.org/zap/zapcore" + "golang.org/x/exp/maps" + + chainsel "github.com/smartcontractkit/chain-selectors" + + "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" + + "github.com/smartcontractkit/chainlink/deployment" + "github.com/smartcontractkit/chainlink/deployment/environment/clo" + "github.com/smartcontractkit/chainlink/deployment/environment/clo/models" + "github.com/smartcontractkit/chainlink/deployment/environment/memory" + "github.com/smartcontractkit/chainlink/deployment/keystone" + kcr "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry" + "github.com/smartcontractkit/chainlink/v2/core/logger" +) + +func TestDeploy(t *testing.T) { + lggr := logger.TestLogger(t) + + // sepolia; all nodes are on the this chain + sepoliaChainId := uint64(11155111) + sepoliaArbitrumChainId := uint64(421614) + + sepoliaChainSel, err := chainsel.SelectorFromChainId(sepoliaChainId) + require.NoError(t, err) + // sepoliaArbitrumChainSel, err := chainsel.SelectorFromChainId(sepoliaArbitrumChainId) + // require.NoError(t, err) + // aptosChainSel := uint64(999) // TODO: + + crConfig := deployment.CapabilityRegistryConfig{ + EVMChainID: sepoliaChainId, + Contract: [20]byte{}, + } + + evmChains := memory.NewMemoryChainsWithChainIDs(t, []uint64{sepoliaChainId, sepoliaArbitrumChainId}) + // aptosChain := memory.NewMemoryChain(t, aptosChainSel) + + wfChains := map[uint64]deployment.Chain{} + wfChains[sepoliaChainSel] = evmChains[sepoliaChainSel] + // wfChains[aptosChainSel] = aptosChain + wfNodes := memory.NewNodes(t, zapcore.InfoLevel, wfChains, 4, 0, crConfig) + require.Len(t, wfNodes, 4) + + cwNodes := memory.NewNodes(t, zapcore.InfoLevel, evmChains, 4, 0, crConfig) + + assetChains := map[uint64]deployment.Chain{} + assetChains[sepoliaChainSel] = evmChains[sepoliaChainSel] + assetNodes := memory.NewNodes(t, zapcore.InfoLevel, assetChains, 4, 0, crConfig) + require.Len(t, assetNodes, 4) + + // TODO: partition nodes into multiple nops + + wfDon := keystone.DonCapabilities{ + Name: keystone.WFDonName, + Nops: []keystone.NOP{ + { + Name: "nop 1", + Nodes: maps.Keys(wfNodes), + }, + }, + Capabilities: []kcr.CapabilitiesRegistryCapability{keystone.OCR3Cap}, + } + cwDon := keystone.DonCapabilities{ + Name: keystone.TargetDonName, + Nops: []keystone.NOP{ + { + Name: "nop 2", + Nodes: maps.Keys(cwNodes), + }, + }, + Capabilities: []kcr.CapabilitiesRegistryCapability{keystone.WriteChainCap}, + } + assetDon := keystone.DonCapabilities{ + Name: keystone.StreamDonName, + Nops: []keystone.NOP{ + { + Name: "nop 3", + Nodes: maps.Keys(assetNodes), + }, + }, + Capabilities: []kcr.CapabilitiesRegistryCapability{keystone.StreamTriggerCap}, + } + + allChains := make(map[uint64]deployment.Chain) + maps.Copy(allChains, evmChains) + // allChains[aptosChainSel] = aptosChain + + allNodes := make(map[string]memory.Node) + maps.Copy(allNodes, wfNodes) + maps.Copy(allNodes, cwNodes) + maps.Copy(allNodes, assetNodes) + env := memory.NewMemoryEnvironmentFromChainsNodes(t, lggr, allChains, allNodes) + + var ocr3Config = keystone.OracleConfigWithSecrets{ + OracleConfig: keystone.OracleConfig{ + MaxFaultyOracles: len(wfNodes) / 3, + }, + OCRSecrets: deployment.XXXGenerateTestOCRSecrets(), + } + + ctx := tests.Context(t) + // explicitly deploy the contracts + cs, err := keystone.DeployContracts(lggr, &env, sepoliaChainSel) + require.NoError(t, err) + env.ExistingAddresses = cs.AddressBook + deployReq := keystone.ConfigureContractsRequest{ + RegistryChainSel: sepoliaChainSel, + Env: &env, + OCR3Config: &ocr3Config, + Dons: []keystone.DonCapabilities{wfDon, cwDon, assetDon}, + DoContractDeploy: false, + } + deployResp, err := keystone.ConfigureContracts(ctx, lggr, deployReq) + require.NoError(t, err) + ad := deployResp.Changeset.AddressBook + addrs, err := ad.Addresses() + require.NoError(t, err) + lggr.Infow("Deployed Keystone contracts", "address book", addrs) + + // all contracts on home chain + homeChainAddrs, err := ad.AddressesForChain(sepoliaChainSel) + require.NoError(t, err) + require.Len(t, homeChainAddrs, 3) + // only forwarder on non-home chain + for sel := range env.Chains { + chainAddrs, err := ad.AddressesForChain(sel) + require.NoError(t, err) + if sel != sepoliaChainSel { + require.Len(t, chainAddrs, 1) + } else { + require.Len(t, chainAddrs, 3) + } + containsForwarder := false + for _, tv := range chainAddrs { + if tv.Type == keystone.KeystoneForwarder { + containsForwarder = true + break + } + } + require.True(t, containsForwarder, "no forwarder found in %v on chain %d for target don", chainAddrs, sel) + } + req := &keystone.GetContractSetsRequest{ + Chains: env.Chains, + AddressBook: ad, + } + + contractSetsResp, err := keystone.GetContractSets(lggr, req) + require.NoError(t, err) + require.Len(t, contractSetsResp.ContractSets, len(env.Chains)) + // check the registry + regChainContracts, ok := contractSetsResp.ContractSets[sepoliaChainSel] + require.True(t, ok) + gotRegistry := regChainContracts.CapabilitiesRegistry + require.NotNil(t, gotRegistry) + // contract reads + gotDons, err := gotRegistry.GetDONs(&bind.CallOpts{}) + if err != nil { + err = keystone.DecodeErr(kcr.CapabilitiesRegistryABI, err) + require.Fail(t, fmt.Sprintf("failed to get Dons from registry at %s: %s", gotRegistry.Address().String(), err)) + } + require.NoError(t, err) + assert.Len(t, gotDons, len(deployReq.Dons)) + + for n, info := range deployResp.DonInfos { + found := false + for _, gdon := range gotDons { + if gdon.Id == info.Id { + found = true + assert.EqualValues(t, info, gdon) + break + } + } + require.True(t, found, "don %s not found in registry", n) + } + // check the forwarder + for _, cs := range contractSetsResp.ContractSets { + forwarder := cs.Forwarder + require.NotNil(t, forwarder) + // any read to ensure that the contract is deployed correctly + _, err := forwarder.Owner(&bind.CallOpts{}) + require.NoError(t, err) + // TODO expand this test; there is no get method on the forwarder so unclear how to test it + } + // check the ocr3 contract + for chainSel, cs := range contractSetsResp.ContractSets { + if chainSel != sepoliaChainSel { + require.Nil(t, cs.OCR3) + continue + } + require.NotNil(t, cs.OCR3) + // any read to ensure that the contract is deployed correctly + _, err := cs.OCR3.LatestConfigDetails(&bind.CallOpts{}) + require.NoError(t, err) + } +} + +// TODO: Deprecated, remove everything below that leverages CLO + +func nodeOperatorsToIDs(t *testing.T, nops []*models.NodeOperator) (nodeIDs []keystone.NOP) { + for _, nop := range nops { + nodeOperator := keystone.NOP{ + Name: nop.Name, + } + for _, node := range nop.Nodes { + p2pID, err := clo.NodeP2PId(node) + require.NoError(t, err) + + nodeOperator.Nodes = append(nodeOperator.Nodes, p2pID) + } + nodeIDs = append(nodeIDs, nodeOperator) + } + return nodeIDs +} + +func TestDeployCLO(t *testing.T) { + lggr := logger.TestLogger(t) + + wfNops := loadTestNops(t, "testdata/workflow_nodes.json") + cwNops := loadTestNops(t, "testdata/chain_writer_nodes.json") + assetNops := loadTestNops(t, "testdata/asset_nodes.json") + require.Len(t, wfNops, 10) + requireChains(t, wfNops, []models.ChainType{models.ChainTypeEvm, models.ChainTypeAptos}) + require.Len(t, cwNops, 10) + requireChains(t, cwNops, []models.ChainType{models.ChainTypeEvm, models.ChainTypeEvm}) + require.Len(t, assetNops, 16) + requireChains(t, assetNops, []models.ChainType{models.ChainTypeEvm}) + + wfNodes := nodeOperatorsToIDs(t, wfNops) + cwNodes := nodeOperatorsToIDs(t, cwNops) + assetNodes := nodeOperatorsToIDs(t, assetNops) + + wfDon := keystone.DonCapabilities{ + Name: keystone.WFDonName, + Nops: wfNodes, + Capabilities: []kcr.CapabilitiesRegistryCapability{keystone.OCR3Cap}, + } + cwDon := keystone.DonCapabilities{ + Name: keystone.TargetDonName, + Nops: cwNodes, + Capabilities: []kcr.CapabilitiesRegistryCapability{keystone.WriteChainCap}, + } + assetDon := keystone.DonCapabilities{ + Name: keystone.StreamDonName, + Nops: assetNodes, + Capabilities: []kcr.CapabilitiesRegistryCapability{keystone.StreamTriggerCap}, + } + + var allNops []*models.NodeOperator + allNops = append(allNops, wfNops...) + allNops = append(allNops, cwNops...) + allNops = append(allNops, assetNops...) + + chains := make(map[uint64]struct{}) + for _, nop := range allNops { + for _, node := range nop.Nodes { + for _, chain := range node.ChainConfigs { + // chain selector lib doesn't support chain id 2 and we don't use it in tests + // because it's not an evm chain + if chain.Network.ChainID == "2" { // aptos chain + continue + } + id, err := strconv.ParseUint(chain.Network.ChainID, 10, 64) + require.NoError(t, err, "failed to parse chain id to uint64") + chains[id] = struct{}{} + } + } + } + var chainIDs []uint64 + for c := range chains { + chainIDs = append(chainIDs, c) + } + allChains := memory.NewMemoryChainsWithChainIDs(t, chainIDs) + + env := &deployment.Environment{ + Name: "CLO", + ExistingAddresses: deployment.NewMemoryAddressBook(), + Offchain: clo.NewJobClient(lggr, clo.JobClientConfig{Nops: allNops}), + Chains: allChains, + Logger: lggr, + } + // assume that all the nodes in the provided input nops are part of the don + for _, nop := range allNops { + for _, node := range nop.Nodes { + env.NodeIDs = append(env.NodeIDs, node.ID) + } + } + + // sepolia; all nodes are on the this chain + registryChainSel, err := chainsel.SelectorFromChainId(11155111) + require.NoError(t, err) + + var ocr3Config = keystone.OracleConfigWithSecrets{ + OracleConfig: keystone.OracleConfig{ + MaxFaultyOracles: len(wfNops) / 3, + }, + OCRSecrets: deployment.XXXGenerateTestOCRSecrets(), + } + + ctx := tests.Context(t) + // explicitly deploy the contracts + cs, err := keystone.DeployContracts(lggr, env, registryChainSel) + require.NoError(t, err) + // Deploy successful these are now part of our env. + require.NoError(t, env.ExistingAddresses.Merge(cs.AddressBook)) + + deployReq := keystone.ConfigureContractsRequest{ + RegistryChainSel: registryChainSel, + Env: env, + OCR3Config: &ocr3Config, + Dons: []keystone.DonCapabilities{wfDon, cwDon, assetDon}, + DoContractDeploy: false, + } + deployResp, err := keystone.ConfigureContracts(ctx, lggr, deployReq) + require.NoError(t, err) + ad := deployResp.Changeset.AddressBook + addrs, err := ad.Addresses() + require.NoError(t, err) + lggr.Infow("Deployed Keystone contracts", "address book", addrs) + + // all contracts on home chain + homeChainAddrs, err := ad.AddressesForChain(registryChainSel) + require.NoError(t, err) + require.Len(t, homeChainAddrs, 3) + // only forwarder on non-home chain + for sel := range env.Chains { + chainAddrs, err := ad.AddressesForChain(sel) + require.NoError(t, err) + if sel != registryChainSel { + require.Len(t, chainAddrs, 1) + } else { + require.Len(t, chainAddrs, 3) + } + containsForwarder := false + for _, tv := range chainAddrs { + if tv.Type == keystone.KeystoneForwarder { + containsForwarder = true + break + } + } + require.True(t, containsForwarder, "no forwarder found in %v on chain %d for target don", chainAddrs, sel) + } + req := &keystone.GetContractSetsRequest{ + Chains: env.Chains, + AddressBook: ad, + } + + contractSetsResp, err := keystone.GetContractSets(lggr, req) + require.NoError(t, err) + require.Len(t, contractSetsResp.ContractSets, len(env.Chains)) + // check the registry + regChainContracts, ok := contractSetsResp.ContractSets[registryChainSel] + require.True(t, ok) + gotRegistry := regChainContracts.CapabilitiesRegistry + require.NotNil(t, gotRegistry) + // check DONs + gotDons, err := gotRegistry.GetDONs(&bind.CallOpts{}) + if err != nil { + err = keystone.DecodeErr(kcr.CapabilitiesRegistryABI, err) + require.Fail(t, fmt.Sprintf("failed to get DONs from registry at %s: %s", gotRegistry.Address().String(), err)) + } + require.NoError(t, err) + assert.Len(t, gotDons, len(deployReq.Dons)) + // check NOPs + nops, err := gotRegistry.GetNodeOperators(&bind.CallOpts{}) + if err != nil { + err = keystone.DecodeErr(kcr.CapabilitiesRegistryABI, err) + require.Fail(t, fmt.Sprintf("failed to get NOPs from registry at %s: %s", gotRegistry.Address().String(), err)) + } + require.NoError(t, err) + assert.Len(t, nops, 26) // 10 NOPs owning workflow & writer DONs + 16 NOPs owning Asset DON + + for n, info := range deployResp.DonInfos { + found := false + for _, gdon := range gotDons { + if gdon.Id == info.Id { + found = true + assert.EqualValues(t, info, gdon) + break + } + } + require.True(t, found, "don %s not found in registry", n) + } + // check the forwarder + for _, cs := range contractSetsResp.ContractSets { + forwarder := cs.Forwarder + require.NotNil(t, forwarder) + // any read to ensure that the contract is deployed correctly + _, err := forwarder.Owner(&bind.CallOpts{}) + require.NoError(t, err) + // TODO expand this test; there is no get method on the forwarder so unclear how to test it + } + // check the ocr3 contract + for chainSel, cs := range contractSetsResp.ContractSets { + if chainSel != registryChainSel { + require.Nil(t, cs.OCR3) + continue + } + require.NotNil(t, cs.OCR3) + // any read to ensure that the contract is deployed correctly + _, err := cs.OCR3.LatestConfigDetails(&bind.CallOpts{}) + require.NoError(t, err) + } +} + +func requireChains(t *testing.T, donNops []*models.NodeOperator, cs []models.ChainType) { + got := make(map[models.ChainType]struct{}) + want := make(map[models.ChainType]struct{}) + for _, c := range cs { + want[c] = struct{}{} + } + for _, nop := range donNops { + for _, node := range nop.Nodes { + for _, cc := range node.ChainConfigs { + got[cc.Network.ChainType] = struct{}{} + } + } + require.EqualValues(t, want, got, "did not find all chains in node %s", nop.Name) + } +} + +func loadTestNops(t *testing.T, pth string) []*models.NodeOperator { + f, err := os.ReadFile(pth) + require.NoError(t, err) + var nops []*models.NodeOperator + require.NoError(t, json.Unmarshal(f, &nops)) + return nops +} diff --git a/deployment/keystone/deprecated.go b/deployment/keystone/deprecated.go deleted file mode 100644 index 0e85cbedb17..00000000000 --- a/deployment/keystone/deprecated.go +++ /dev/null @@ -1,127 +0,0 @@ -package keystone - -import "github.com/smartcontractkit/chainlink/deployment/keystone/changeset" - -//TODO: delete this after the downstream migration is done - -// DEPRECATED: Use changeset package instead -// OracleConfig is the configuration for an oracle -type OracleConfig = changeset.OracleConfig - -// DEPRECATED: Use changeset package instead -// OCR3OnchainConfig is the onchain configuration of an OCR2 contract -type OCR2OracleConfig = changeset.OCR3OnchainConfig - -// DEPRECATED: Use changeset package instead -// NodeKeys is a set of public keys for a node -type NodeKeys = changeset.NodeKeys - -// DEPRECATED: Use changeset package instead -// TopLevelConfigSource is the top level configuration source -type TopLevelConfigSource = changeset.TopLevelConfigSource - -// DEPRECATED: Use changeset package instead -// GenerateOCR3Config generates an OCR3 config -var GenerateOCR3Config = changeset.GenerateOCR3Config - -// DEPRECATED: Use changeset package instead -// FeedConsumer is a feed consumer contract type -var FeedConsumer = changeset.FeedConsumer - -// DEPRECATED: Use changeset package instead -// KeystoneForwarder is a keystone forwarder contract type -var KeystoneForwarder = changeset.KeystoneForwarder - -// DEPRECATED: Use changeset package instead -// GetContractSetsRequest is a request to get contract sets -type GetContractSetsRequest = changeset.GetContractSetsRequest - -// DEPRECATED: Use changeset package instead -// GetContractSetsResponse is a response to get contract sets -type GetContractSetsResponse = changeset.GetContractSetsResponse - -// DEPRECATED: Use changeset package instead -// GetContractSets gets contract sets -var GetContractSets = changeset.GetContractSets - -// DEPRECATED: Use changeset package instead -// RegisterCapabilitiesRequest is a request to register capabilities -type RegisterCapabilitiesRequest = changeset.RegisterCapabilitiesRequest - -// DEPRECATED: Use changeset package instead -// RegisterCapabilitiesResponse is a response to register capabilities -type RegisterCapabilitiesResponse = changeset.RegisterCapabilitiesResponse - -// DEPRECATED: Use changeset package instead -// RegisterCapabilities registers capabilities -var RegisterCapabilities = changeset.RegisterCapabilities - -// DEPRECATED: Use changeset package instead -// RegisterNOPSRequest is a request to register NOPS -type RegisterNOPSRequest = changeset.RegisterNOPSRequest - -// DEPRECATED: Use changeset package instead -// RegisterNOPSResponse is a response to register NOPS -type RegisterNOPSResponse = changeset.RegisterNOPSResponse - -// DEPRECATED: Use changeset package instead -// RegisterNOPS registers NOPS -var RegisterNOPS = changeset.RegisterNOPS - -// DEPRECATED: Use changeset package instead -// RegisterNodesRequest is a request to register nodes with the capabilities registry -type RegisterNodesRequest = changeset.RegisterNodesRequest - -// DEPRECATED: Use changeset package instead -// RegisterNodesResponse is a response to register nodes with the capabilities registry -type RegisterNodesResponse = changeset.RegisterNodesResponse - -// DEPRECATED: Use changeset package instead -// RegisterNodes registers nodes with the capabilities registry -var RegisterNodes = changeset.RegisterNodes - -// DEPRECATED: Use changeset package instead -// RegisteredCapability is a wrapper of a capability and its ID -type RegisteredCapability = changeset.RegisteredCapability - -// DEPRECATED: Use changeset package instead -// FromCapabilitiesRegistryCapability converts a capabilities registry capability to a registered capability -var FromCapabilitiesRegistryCapability = changeset.FromCapabilitiesRegistryCapability - -// DEPRECATED: Use changeset package instead -// RegisterDonsRequest is a request to register Dons with the capabilities registry -type RegisterDonsRequest = changeset.RegisterDonsRequest - -// DEPRECATED: Use changeset package instead -// RegisterDonsResponse is a response to register Dons with the capabilities registry -type RegisterDonsResponse = changeset.RegisterDonsResponse - -// DEPRECATED: Use changeset package instead -// RegisterDons registers Dons with the capabilities registry -var RegisterDons = changeset.RegisterDons - -// DEPRECATED: Use changeset package instead -// DONToRegister is the minimal information needed to register a DON with the capabilities registry -type DONToRegister = changeset.DONToRegister - -// DEPRECATED: Use changeset package instead -// ConfigureContractsRequest is a request to configure ALL the contracts -type ConfigureContractsRequest = changeset.ConfigureContractsRequest - -// DEPRECATED: Use changeset package instead -// ConfigureContractsResponse is a response to configure ALL the contracts -type ConfigureContractsResponse = changeset.ConfigureContractsResponse - -// DEPRECATED: Use changeset package instead -// DonCapabilities is a set of capabilities hosted by a set of node operators -// in is in a convenient form to handle the CLO representation of the nop data -type DonCapabilities = changeset.DonCapabilities - -// DEPRECATED: Use changeset package instead -type DeployRequest = changeset.DeployRequest - -// DEPRECATED: Use changeset package instead -type DeployResponse = changeset.DeployResponse - -// DEPRECATED: Use changeset package instead -type ContractSet = changeset.ContractSet diff --git a/deployment/keystone/forwarder_deployer.go b/deployment/keystone/forwarder_deployer.go new file mode 100644 index 00000000000..b7fde675973 --- /dev/null +++ b/deployment/keystone/forwarder_deployer.go @@ -0,0 +1,50 @@ +package keystone + +import ( + "fmt" + + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/smartcontractkit/chainlink-common/pkg/logger" + "github.com/smartcontractkit/chainlink/deployment" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/forwarder" +) + +type KeystoneForwarderDeployer struct { + lggr logger.Logger + contract *forwarder.KeystoneForwarder +} + +func (c *KeystoneForwarderDeployer) deploy(req DeployRequest) (*DeployResponse, error) { + est, err := estimateDeploymentGas(req.Chain.Client, forwarder.KeystoneForwarderABI) + if err != nil { + return nil, fmt.Errorf("failed to estimate gas: %w", err) + } + c.lggr.Debugf("Forwarder estimated gas: %d", est) + + forwarderAddr, tx, forwarder, err := forwarder.DeployKeystoneForwarder( + req.Chain.DeployerKey, + req.Chain.Client) + if err != nil { + return nil, fmt.Errorf("failed to deploy KeystoneForwarder: %w", err) + } + + _, err = req.Chain.Confirm(tx) + if err != nil { + return nil, fmt.Errorf("failed to confirm and save KeystoneForwarder: %w", err) + } + tvStr, err := forwarder.TypeAndVersion(&bind.CallOpts{}) + if err != nil { + return nil, fmt.Errorf("failed to get type and version: %w", err) + } + tv, err := deployment.TypeAndVersionFromString(tvStr) + if err != nil { + return nil, fmt.Errorf("failed to parse type and version from %s: %w", tvStr, err) + } + resp := &DeployResponse{ + Address: forwarderAddr, + Tx: tx.Hash(), + Tv: tv, + } + c.contract = forwarder + return resp, nil +} diff --git a/deployment/keystone/changeset/internal/ocr3_deployer.go b/deployment/keystone/ocr3_deployer.go similarity index 82% rename from deployment/keystone/changeset/internal/ocr3_deployer.go rename to deployment/keystone/ocr3_deployer.go index beafe9bb9e2..5f2ba34f42c 100644 --- a/deployment/keystone/changeset/internal/ocr3_deployer.go +++ b/deployment/keystone/ocr3_deployer.go @@ -1,13 +1,12 @@ -package internal +package keystone import ( "fmt" "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/smartcontractkit/chainlink-common/pkg/logger" - "github.com/smartcontractkit/chainlink/deployment" - ocr3_capability "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/ocr3_capability_1_0_0" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/ocr3_capability" ) type OCR3Deployer struct { @@ -15,14 +14,6 @@ type OCR3Deployer struct { contract *ocr3_capability.OCR3Capability } -func NewOCR3Deployer() (*OCR3Deployer, error) { - lggr, err := logger.New() - if err != nil { - return nil, err - } - return &OCR3Deployer{lggr: lggr}, nil -} - func (c *OCR3Deployer) deploy(req DeployRequest) (*DeployResponse, error) { est, err := estimateDeploymentGas(req.Chain.Client, ocr3_capability.OCR3CapabilityABI) if err != nil { diff --git a/deployment/keystone/changeset/internal/ocr3config.go b/deployment/keystone/ocr3config.go similarity index 57% rename from deployment/keystone/changeset/internal/ocr3config.go rename to deployment/keystone/ocr3config.go index 74f8a9dabd5..5cd8ada8c61 100644 --- a/deployment/keystone/changeset/internal/ocr3config.go +++ b/deployment/keystone/ocr3config.go @@ -1,6 +1,6 @@ // TODO: KS-458 copied from https://github.com/smartcontractkit/chainlink/blob/65924811dc53a211613927c814d7f04fd85439a4/core/scripts/keystone/src/88_gen_ocr3_config.go#L1 // to unblock go mod issues when trying to import the scripts package -package internal +package keystone import ( "crypto/ed25519" @@ -8,8 +8,6 @@ import ( "encoding/json" "errors" "fmt" - "math/big" - "strings" "time" "github.com/ethereum/go-ethereum/common" @@ -18,20 +16,19 @@ import ( "github.com/smartcontractkit/libocr/offchainreporting2plus/ocr3confighelper" "github.com/smartcontractkit/libocr/offchainreporting2plus/types" - "github.com/smartcontractkit/ccip-owner-contracts/pkg/proposal/mcms" - "github.com/smartcontractkit/ccip-owner-contracts/pkg/proposal/timelock" - "github.com/smartcontractkit/chainlink/deployment" - kocr3 "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/ocr3_capability_1_0_0" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/chaintype" "github.com/smartcontractkit/chainlink/v2/core/services/ocrcommon" "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm" ) type TopLevelConfigSource struct { - OracleConfig OracleConfig + OracleConfig OracleConfigWithSecrets +} +type OracleConfigWithSecrets struct { + OracleConfig + deployment.OCRSecrets `json:"-" toml:"-"` // don't spill secrets } - type OracleConfig struct { MaxQueryLengthBytes uint32 MaxObservationLengthBytes uint32 @@ -71,8 +68,7 @@ type NodeKeys struct { EncryptionPublicKey string `json:"EncryptionPublicKey"` } -// OCR2OracleConfig is the input configuration for an OCR2/3 contract. -type OCR2OracleConfig struct { +type Orc2drOracleConfig struct { Signers [][]byte Transmitters []common.Address F uint8 @@ -81,7 +77,7 @@ type OCR2OracleConfig struct { OffchainConfig []byte } -func (c OCR2OracleConfig) MarshalJSON() ([]byte, error) { +func (c Orc2drOracleConfig) MarshalJSON() ([]byte, error) { alias := struct { Signers []string Transmitters []string @@ -109,54 +105,16 @@ func (c OCR2OracleConfig) MarshalJSON() ([]byte, error) { return json.Marshal(alias) } -func (c *OCR2OracleConfig) UnmarshalJSON(data []byte) error { - type aliasT struct { - Signers []string - Transmitters []string - F uint8 - OnchainConfig string - OffchainConfigVersion uint64 - OffchainConfig string - } - var alias aliasT - err := json.Unmarshal(data, &alias) - if err != nil { - return fmt.Errorf("failed to unmarshal OCR2OracleConfig alias: %w", err) - } - c.F = alias.F - c.OffchainConfigVersion = alias.OffchainConfigVersion - c.Signers = make([][]byte, len(alias.Signers)) - for i, signer := range alias.Signers { - c.Signers[i], err = hex.DecodeString(strings.TrimPrefix(signer, "0x")) - if err != nil { - return fmt.Errorf("failed to decode signer: %w", err) - } - } - c.Transmitters = make([]common.Address, len(alias.Transmitters)) - for i, transmitter := range alias.Transmitters { - c.Transmitters[i] = common.HexToAddress(transmitter) - } - c.OnchainConfig, err = hex.DecodeString(strings.TrimPrefix(alias.OnchainConfig, "0x")) - if err != nil { - return fmt.Errorf("failed to decode onchain config: %w", err) - } - c.OffchainConfig, err = hex.DecodeString(strings.TrimPrefix(alias.OffchainConfig, "0x")) - if err != nil { - return fmt.Errorf("failed to decode offchain config: %w", err) - } - return nil -} - -func GenerateOCR3Config(cfg OracleConfig, nca []NodeKeys, secrets deployment.OCRSecrets) (OCR2OracleConfig, error) { +func GenerateOCR3Config(cfg OracleConfigWithSecrets, nca []NodeKeys) (Orc2drOracleConfig, error) { onchainPubKeys := [][]byte{} allPubKeys := map[string]any{} - if secrets.IsEmpty() { - return OCR2OracleConfig{}, errors.New("OCRSecrets is required") + if cfg.OCRSecrets.IsEmpty() { + return Orc2drOracleConfig{}, errors.New("OCRSecrets is required") } for _, n := range nca { // evm keys always required if n.OCR2OnchainPublicKey == "" { - return OCR2OracleConfig{}, errors.New("OCR2OnchainPublicKey is required") + return Orc2drOracleConfig{}, errors.New("OCR2OnchainPublicKey is required") } ethPubKey := common.HexToAddress(n.OCR2OnchainPublicKey) pubKeys := map[string]types.OnchainPublicKey{ @@ -166,7 +124,7 @@ func GenerateOCR3Config(cfg OracleConfig, nca []NodeKeys, secrets deployment.OCR if n.AptosOnchainPublicKey != "" { aptosPubKey, err := hex.DecodeString(n.AptosOnchainPublicKey) if err != nil { - return OCR2OracleConfig{}, fmt.Errorf("failed to decode AptosOnchainPublicKey: %w", err) + return Orc2drOracleConfig{}, fmt.Errorf("failed to decode AptosOnchainPublicKey: %w", err) } pubKeys[string(chaintype.Aptos)] = aptosPubKey } @@ -175,13 +133,13 @@ func GenerateOCR3Config(cfg OracleConfig, nca []NodeKeys, secrets deployment.OCR raw := hex.EncodeToString(key) _, exists := allPubKeys[raw] if exists { - return OCR2OracleConfig{}, fmt.Errorf("Duplicate onchain public key: '%s'", raw) + return Orc2drOracleConfig{}, fmt.Errorf("Duplicate onchain public key: '%s'", raw) } allPubKeys[raw] = struct{}{} } pubKey, err := ocrcommon.MarshalMultichainPublicKey(pubKeys) if err != nil { - return OCR2OracleConfig{}, fmt.Errorf("failed to marshal multichain public key: %w", err) + return Orc2drOracleConfig{}, fmt.Errorf("failed to marshal multichain public key: %w", err) } onchainPubKeys = append(onchainPubKeys, pubKey) } @@ -190,13 +148,13 @@ func GenerateOCR3Config(cfg OracleConfig, nca []NodeKeys, secrets deployment.OCR for _, n := range nca { pkBytes, err := hex.DecodeString(n.OCR2OffchainPublicKey) if err != nil { - return OCR2OracleConfig{}, fmt.Errorf("failed to decode OCR2OffchainPublicKey: %w", err) + return Orc2drOracleConfig{}, fmt.Errorf("failed to decode OCR2OffchainPublicKey: %w", err) } pkBytesFixed := [ed25519.PublicKeySize]byte{} nCopied := copy(pkBytesFixed[:], pkBytes) if nCopied != ed25519.PublicKeySize { - return OCR2OracleConfig{}, fmt.Errorf("wrong num elements copied from ocr2 offchain public key. expected %d but got %d", ed25519.PublicKeySize, nCopied) + return Orc2drOracleConfig{}, fmt.Errorf("wrong num elements copied from ocr2 offchain public key. expected %d but got %d", ed25519.PublicKeySize, nCopied) } offchainPubKeysBytes = append(offchainPubKeysBytes, types.OffchainPublicKey(pkBytesFixed)) @@ -206,13 +164,13 @@ func GenerateOCR3Config(cfg OracleConfig, nca []NodeKeys, secrets deployment.OCR for _, n := range nca { pkBytes, err := hex.DecodeString(n.OCR2ConfigPublicKey) if err != nil { - return OCR2OracleConfig{}, fmt.Errorf("failed to decode OCR2ConfigPublicKey: %w", err) + return Orc2drOracleConfig{}, fmt.Errorf("failed to decode OCR2ConfigPublicKey: %w", err) } pkBytesFixed := [ed25519.PublicKeySize]byte{} n := copy(pkBytesFixed[:], pkBytes) if n != ed25519.PublicKeySize { - return OCR2OracleConfig{}, fmt.Errorf("wrong num elements copied from ocr2 config public key. expected %d but got %d", ed25519.PublicKeySize, n) + return Orc2drOracleConfig{}, fmt.Errorf("wrong num elements copied from ocr2 config public key. expected %d but got %d", ed25519.PublicKeySize, n) } configPubKeysBytes = append(configPubKeysBytes, types.ConfigEncryptionPublicKey(pkBytesFixed)) @@ -232,8 +190,8 @@ func GenerateOCR3Config(cfg OracleConfig, nca []NodeKeys, secrets deployment.OCR } signers, transmitters, f, onchainConfig, offchainConfigVersion, offchainConfig, err := ocr3confighelper.ContractSetConfigArgsDeterministic( - secrets.EphemeralSk, - secrets.SharedSecret, + cfg.EphemeralSk, + cfg.SharedSecret, time.Duration(cfg.DeltaProgressMillis)*time.Millisecond, time.Duration(cfg.DeltaResendMillis)*time.Millisecond, time.Duration(cfg.DeltaInitialMillis)*time.Millisecond, @@ -254,7 +212,7 @@ func GenerateOCR3Config(cfg OracleConfig, nca []NodeKeys, secrets deployment.OCR nil, // empty onChain config ) if err != nil { - return OCR2OracleConfig{}, fmt.Errorf("failed to generate contract config args: %w", err) + return Orc2drOracleConfig{}, fmt.Errorf("failed to generate contract config args: %w", err) } var configSigners [][]byte @@ -264,10 +222,10 @@ func GenerateOCR3Config(cfg OracleConfig, nca []NodeKeys, secrets deployment.OCR transmitterAddresses, err := evm.AccountToAddress(transmitters) if err != nil { - return OCR2OracleConfig{}, fmt.Errorf("failed to convert transmitters to addresses: %w", err) + return Orc2drOracleConfig{}, fmt.Errorf("failed to convert transmitters to addresses: %w", err) } - config := OCR2OracleConfig{ + config := Orc2drOracleConfig{ Signers: configSigners, Transmitters: transmitterAddresses, F: f, @@ -278,78 +236,3 @@ func GenerateOCR3Config(cfg OracleConfig, nca []NodeKeys, secrets deployment.OCR return config, nil } - -type configureOCR3Request struct { - cfg *OracleConfig - chain deployment.Chain - contract *kocr3.OCR3Capability - nodes []deployment.Node - dryRun bool - ocrSecrets deployment.OCRSecrets - - useMCMS bool - contractSet *ContractSet -} - -func (r configureOCR3Request) generateOCR3Config() (OCR2OracleConfig, error) { - nks := makeNodeKeysSlice(r.nodes, r.chain.Selector) - return GenerateOCR3Config(*r.cfg, nks, r.ocrSecrets) -} - -type configureOCR3Response struct { - ocrConfig OCR2OracleConfig - ops *timelock.BatchChainOperation -} - -func configureOCR3contract(req configureOCR3Request) (*configureOCR3Response, error) { - if req.contract == nil { - return nil, fmt.Errorf("OCR3 contract is nil") - } - ocrConfig, err := req.generateOCR3Config() - if err != nil { - return nil, fmt.Errorf("failed to generate OCR3 config: %w", err) - } - if req.dryRun { - return &configureOCR3Response{ocrConfig, nil}, nil - } - - txOpt := req.chain.DeployerKey - if req.useMCMS { - txOpt = deployment.SimTransactOpts() - } - - tx, err := req.contract.SetConfig(txOpt, - ocrConfig.Signers, - ocrConfig.Transmitters, - ocrConfig.F, - ocrConfig.OnchainConfig, - ocrConfig.OffchainConfigVersion, - ocrConfig.OffchainConfig, - ) - if err != nil { - err = deployment.DecodeErr(kocr3.OCR3CapabilityABI, err) - return nil, fmt.Errorf("failed to call SetConfig for OCR3 contract %s using mcms: %T: %w", req.contract.Address().String(), req.useMCMS, err) - } - - var ops *timelock.BatchChainOperation - if !req.useMCMS { - _, err = req.chain.Confirm(tx) - if err != nil { - err = deployment.DecodeErr(kocr3.OCR3CapabilityABI, err) - return nil, fmt.Errorf("failed to confirm SetConfig for OCR3 contract %s: %w", req.contract.Address().String(), err) - } - } else { - ops = &timelock.BatchChainOperation{ - ChainIdentifier: mcms.ChainIdentifier(req.chain.Selector), - Batch: []mcms.Operation{ - { - To: req.contract.Address(), - Data: tx.Data(), - Value: big.NewInt(0), - }, - }, - } - } - - return &configureOCR3Response{ocrConfig, ops}, nil -} diff --git a/deployment/keystone/changeset/internal/state.go b/deployment/keystone/state.go similarity index 64% rename from deployment/keystone/changeset/internal/state.go rename to deployment/keystone/state.go index d0817069d9a..33200a40e02 100644 --- a/deployment/keystone/changeset/internal/state.go +++ b/deployment/keystone/state.go @@ -1,4 +1,4 @@ -package internal +package keystone import ( "fmt" @@ -6,15 +6,12 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/smartcontractkit/chainlink-common/pkg/logger" - "github.com/smartcontractkit/chainlink/deployment" - commonchangeset "github.com/smartcontractkit/chainlink/deployment/common/changeset" common_v1_0 "github.com/smartcontractkit/chainlink/deployment/common/view/v1_0" "github.com/smartcontractkit/chainlink/deployment/keystone/view" - capabilities_registry "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry_1_1_0" - forwarder "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/forwarder_1_0_0" - ocr3_capability "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/ocr3_capability_1_0_0" - workflow_registry "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/workflow/generated/workflow_registry_wrapper" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/forwarder" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/ocr3_capability" ) type GetContractSetsRequest struct { @@ -27,28 +24,9 @@ type GetContractSetsResponse struct { } type ContractSet struct { - commonchangeset.MCMSWithTimelockState OCR3 *ocr3_capability.OCR3Capability Forwarder *forwarder.KeystoneForwarder CapabilitiesRegistry *capabilities_registry.CapabilitiesRegistry - WorkflowRegistry *workflow_registry.WorkflowRegistry -} - -func (cs ContractSet) TransferableContracts() []common.Address { - var out []common.Address - if cs.OCR3 != nil { - out = append(out, cs.OCR3.Address()) - } - if cs.Forwarder != nil { - out = append(out, cs.Forwarder.Address()) - } - if cs.CapabilitiesRegistry != nil { - out = append(out, cs.CapabilitiesRegistry.Address()) - } - if cs.WorkflowRegistry != nil { - out = append(out, cs.WorkflowRegistry.Address()) - } - return out } func (cs ContractSet) View() (view.KeystoneChainView, error) { @@ -83,11 +61,6 @@ func GetContractSets(lggr logger.Logger, req *GetContractSetsRequest) (*GetContr func loadContractSet(lggr logger.Logger, chain deployment.Chain, addresses map[string]deployment.TypeAndVersion) (*ContractSet, error) { var out ContractSet - mcmsWithTimelock, err := commonchangeset.MaybeLoadMCMSWithTimelockChainState(chain, addresses) - if err != nil { - return nil, fmt.Errorf("failed to load mcms contract: %w", err) - } - out.MCMSWithTimelockState = *mcmsWithTimelock for addr, tv := range addresses { // todo handle versions @@ -110,12 +83,6 @@ func loadContractSet(lggr logger.Logger, chain deployment.Chain, addresses map[s return nil, fmt.Errorf("failed to create OCR3Capability contract from address %s: %w", addr, err) } out.OCR3 = c - case WorkflowRegistry: - c, err := workflow_registry.NewWorkflowRegistry(common.HexToAddress(addr), chain.Client) - if err != nil { - return nil, fmt.Errorf("failed to create OCR3Capability contract from address %s: %w", addr, err) - } - out.WorkflowRegistry = c default: lggr.Warnw("unknown contract type", "type", tv.Type) // ignore unknown contract types diff --git a/deployment/keystone/test/changeset/capability_registry.go b/deployment/keystone/test/changeset/capability_registry.go deleted file mode 100644 index 98f1e752f5a..00000000000 --- a/deployment/keystone/test/changeset/capability_registry.go +++ /dev/null @@ -1,88 +0,0 @@ -package changeset - -import ( - "fmt" - "testing" - - chainsel "github.com/smartcontractkit/chain-selectors" - - "github.com/smartcontractkit/chainlink/deployment" - - "github.com/smartcontractkit/chainlink/deployment/common/view/v1_0" - - "github.com/smartcontractkit/chainlink/deployment/keystone/changeset" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry_1_1_0" -) - -type HydrateConfig struct { - ChainID uint64 -} - -// HydrateCapabilityRegistry deploys a new capabilities registry contract and hydrates it with the provided data. -func HydrateCapabilityRegistry(t *testing.T, v v1_0.CapabilityRegistryView, env deployment.Environment, cfg HydrateConfig) (*capabilities_registry.CapabilitiesRegistry, error) { - t.Helper() - chainSelector, err := chainsel.SelectorFromChainId(cfg.ChainID) - if err != nil { - return nil, fmt.Errorf("failed to get chain selector from chain id: %w", err) - } - chain, ok := env.Chains[chainSelector] - if !ok { - return nil, fmt.Errorf("chain with id %d not found", cfg.ChainID) - } - changesetOutput, err := changeset.DeployCapabilityRegistry(env, chainSelector) - if err != nil { - return nil, fmt.Errorf("failed to deploy contract: %w", err) - } - - resp, err := changeset.GetContractSets(env.Logger, &changeset.GetContractSetsRequest{ - Chains: env.Chains, - AddressBook: changesetOutput.AddressBook, - }) - if err != nil { - return nil, fmt.Errorf("failed to get contract sets: %w", err) - } - cs, ok := resp.ContractSets[chainSelector] - if !ok { - return nil, fmt.Errorf("failed to get contract set for chain selector: %d, chain ID: %d", chainSelector, cfg.ChainID) - } - - deployedContract := cs.CapabilitiesRegistry - - nopsParams := v.NopsToNopsParams() - tx, err := deployedContract.AddNodeOperators(chain.DeployerKey, nopsParams) - if _, err = deployment.ConfirmIfNoError(chain, tx, deployment.DecodeErr(capabilities_registry.CapabilitiesRegistryABI, err)); err != nil { - return nil, fmt.Errorf("failed to add node operators: %w", err) - } - - capabilitiesParams := v.CapabilitiesToCapabilitiesParams() - tx, err = deployedContract.AddCapabilities(chain.DeployerKey, capabilitiesParams) - if _, err = deployment.ConfirmIfNoError(chain, tx, deployment.DecodeErr(capabilities_registry.CapabilitiesRegistryABI, err)); err != nil { - return nil, fmt.Errorf("failed to add capabilities: %w", err) - } - - nodesParams, err := v.NodesToNodesParams() - if err != nil { - return nil, fmt.Errorf("failed to convert nodes to nodes params: %w", err) - } - tx, err = deployedContract.AddNodes(chain.DeployerKey, nodesParams) - if _, err = deployment.ConfirmIfNoError(chain, tx, deployment.DecodeErr(capabilities_registry.CapabilitiesRegistryABI, err)); err != nil { - return nil, fmt.Errorf("failed to add nodes: %w", err) - } - - for _, don := range v.Dons { - cfgs, err := v.CapabilityConfigToCapabilityConfigParams(don) - if err != nil { - return nil, fmt.Errorf("failed to convert capability configurations to capability configuration params: %w", err) - } - var peerIds [][32]byte - for _, id := range don.NodeP2PIds { - peerIds = append(peerIds, id) - } - tx, err = deployedContract.AddDON(chain.DeployerKey, peerIds, cfgs, don.IsPublic, don.AcceptsWorkflows, don.F) - if _, err = deployment.ConfirmIfNoError(chain, tx, deployment.DecodeErr(capabilities_registry.CapabilitiesRegistryABI, err)); err != nil { - return nil, fmt.Errorf("failed to add don: %w", err) - } - } - - return deployedContract, nil -} diff --git a/deployment/keystone/test/changeset/capability_registry_test.go b/deployment/keystone/test/changeset/capability_registry_test.go deleted file mode 100644 index 765c95ff294..00000000000 --- a/deployment/keystone/test/changeset/capability_registry_test.go +++ /dev/null @@ -1,46 +0,0 @@ -package changeset - -import ( - "encoding/json" - "os" - "testing" - - "github.com/stretchr/testify/require" - "go.uber.org/zap/zapcore" - - chainsel "github.com/smartcontractkit/chain-selectors" - - "github.com/smartcontractkit/chainlink/deployment/common/view/v1_0" - "github.com/smartcontractkit/chainlink/deployment/environment/memory" - "github.com/smartcontractkit/chainlink/v2/core/logger" -) - -func TestHydrateCapabilityRegistry(t *testing.T) { - b, err := os.ReadFile("testdata/capability_registry_view.json") - require.NoError(t, err) - require.NotEmpty(t, b) - var capabilityRegistryView v1_0.CapabilityRegistryView - require.NoError(t, json.Unmarshal(b, &capabilityRegistryView)) - - chainID := chainsel.TEST_90000001.EvmChainID - cfg := HydrateConfig{ChainID: chainID} - env := memory.NewMemoryEnvironment(t, logger.TestLogger(t), zapcore.InfoLevel, memory.MemoryEnvironmentConfig{ - Bootstraps: 1, - Chains: 1, - Nodes: 4, - }) - hydrated, err := HydrateCapabilityRegistry(t, capabilityRegistryView, env, cfg) - require.NoError(t, err) - require.NotNil(t, hydrated) - hydratedCapView, err := v1_0.GenerateCapabilityRegistryView(hydrated) - require.NoError(t, err) - - // Setting address/owner values to be the same in order to compare the views - hydratedCapView.Address = capabilityRegistryView.Address - hydratedCapView.Owner = capabilityRegistryView.Owner - b1, err := capabilityRegistryView.MarshalJSON() - require.NoError(t, err) - b2, err := hydratedCapView.MarshalJSON() - require.NoError(t, err) - require.Equal(t, string(b1), string(b2)) -} diff --git a/deployment/keystone/test/changeset/testdata/capability_registry_view.json b/deployment/keystone/test/changeset/testdata/capability_registry_view.json deleted file mode 100644 index fef22a7b4dc..00000000000 --- a/deployment/keystone/test/changeset/testdata/capability_registry_view.json +++ /dev/null @@ -1,455 +0,0 @@ -{ - "typeAndVersion": "CapabilitiesRegistry 1.1.0", - "address": "0x65a097a74769fe1c415993f45d9b56ffffb65807", - "owner": "0x61050aeba13a5f7ba0b06cac4e1aee625fe4a640", - "capabilities": [ - { - "id": "9f0f33d3737af0a2acae89e7f8c4638aeb886a67c1d84e13aee8532c70aa9483", - "labelled_name": "write_ethereum-testnet-sepolia", - "version": "1.0.0", - "capability_type": 3, - "response_type": 0, - "configuration_contract": "0x0000000000000000000000000000000000000000" - }, - { - "id": "1ea6e85dfb8ebb08b7cd82b42ab4655429a8ae116d513be0d68a7d7661667a8a", - "labelled_name": "streams-trigger", - "version": "1.0.0", - "capability_type": 0, - "response_type": 0, - "configuration_contract": "0x0000000000000000000000000000000000000000" - }, - { - "id": "578ebf7413c15e36dfd792396c5a4d75c43f0ee7bbabdb703f7c5acd0bb65a1b", - "labelled_name": "offchain_reporting", - "version": "1.0.0", - "capability_type": 2, - "response_type": 0, - "configuration_contract": "0x0000000000000000000000000000000000000000" - } - ], - "nodes": [ - { - "config_count": 1, - "workflow_don_id": 1, - "signer": "f36818345fb18549bd24305c79f2f28d80d25710000000000000000000000000", - "p2p_id": "p2p_12D3KooWGVWpMrCZDotqSYWj8xqb1i5kNecpoarczpQoSAHdqwj8", - "encryption_public_key": "986707930499b85ab01705aa8d5cd99dca40926db3fa1728e6b58d25fddfe46b", - "node_operator_id": 1, - "capability_ids": [ - "578ebf7413c15e36dfd792396c5a4d75c43f0ee7bbabdb703f7c5acd0bb65a1b" - ] - }, - { - "config_count": 1, - "workflow_don_id": 0, - "signer": "a0e11229b4b5d40d299f7f4b3348a1b16f5f3dd3000000000000000000000000", - "p2p_id": "p2p_12D3KooWPsGKEe34m9X8qiWVpa6VEcjdvhbygJRLKXdVEr3r96PH", - "encryption_public_key": "10c77049880fe0924f463763789985a0f76e09f82fc6f39943684b2dd05b98bf", - "node_operator_id": 2, - "capability_ids": [ - "9f0f33d3737af0a2acae89e7f8c4638aeb886a67c1d84e13aee8532c70aa9483" - ], - "capability_don_ids": [ - 2 - ] - }, - { - "config_count": 1, - "workflow_don_id": 0, - "signer": "3f871cd7c34e50320934b6ba9b90b249363fd378000000000000000000000000", - "p2p_id": "p2p_12D3KooWLjKKWLhYkr68PH9FaZZR93WbJuohWWcTfA9JeY1UPoJa", - "encryption_public_key": "5cf5abd0349b27cde43ad1a55aa3b02a5518aa6eed365bd65ca5e0e2cbfdaa5a", - "node_operator_id": 3, - "capability_ids": [ - "1ea6e85dfb8ebb08b7cd82b42ab4655429a8ae116d513be0d68a7d7661667a8a" - ], - "capability_don_ids": [ - 3 - ] - }, - { - "config_count": 1, - "workflow_don_id": 0, - "signer": "d7a432ce8f23c410302e7577de9973ccbca29576000000000000000000000000", - "p2p_id": "p2p_12D3KooWRG3rsPdQyWCPsQukUF5JqFLdPqVVXvEfG2PAPBbqdRXp", - "encryption_public_key": "c10cead34374ba20704a05ca0369018b41778a0297adb85554cdd6e5955bf4b6", - "node_operator_id": 3, - "capability_ids": [ - "1ea6e85dfb8ebb08b7cd82b42ab4655429a8ae116d513be0d68a7d7661667a8a" - ], - "capability_don_ids": [ - 3 - ] - }, - { - "config_count": 1, - "workflow_don_id": 0, - "signer": "f1d2b3d13c46b0c1ded96534aabd6bae61934e3f000000000000000000000000", - "p2p_id": "p2p_12D3KooWD1uj8Y9Phdr1yScfbBy1Q9ebedMVBjMUBLW4m4XnEzGF", - "encryption_public_key": "5fc3dae131da5b0ac5474ad029e3a6c547e17249a6266427d5eea1f529b6488b", - "node_operator_id": 3, - "capability_ids": [ - "1ea6e85dfb8ebb08b7cd82b42ab4655429a8ae116d513be0d68a7d7661667a8a" - ], - "capability_don_ids": [ - 3 - ] - }, - { - "config_count": 1, - "workflow_don_id": 1, - "signer": "afabd7685010d619ee6614e732b15e898c293426000000000000000000000000", - "p2p_id": "p2p_12D3KooWE8ymezL2wxXcZdhznnBkVNcBRbtxVfNx1vppu7Z7zfnd", - "encryption_public_key": "8a2aef988ccc85d985d12270c5263032b9a7c71a86430e7b3c30a2f493462aee", - "node_operator_id": 1, - "capability_ids": [ - "578ebf7413c15e36dfd792396c5a4d75c43f0ee7bbabdb703f7c5acd0bb65a1b" - ] - }, - { - "config_count": 1, - "workflow_don_id": 1, - "signer": "4bad6c33b85ba3bbbada74c93a7a719962456af8000000000000000000000000", - "p2p_id": "p2p_12D3KooWSEF7cqkbMrS6uCo6xzCsfcPgquN652mZijmay8e3pn5R", - "encryption_public_key": "cf8e0e8c830f733dd5992076d0adaeb34c97410dd5d8d04afccad88070b07f20", - "node_operator_id": 1, - "capability_ids": [ - "578ebf7413c15e36dfd792396c5a4d75c43f0ee7bbabdb703f7c5acd0bb65a1b" - ] - }, - { - "config_count": 1, - "workflow_don_id": 1, - "signer": "078cb3bca763a11a0c79df636b018311d9e36954000000000000000000000000", - "p2p_id": "p2p_12D3KooWAumheDZJdc3in1qiYGAQESTUm1nAWGA59eQPb3wuFHJa", - "encryption_public_key": "c8f45b74982037dd52eeb3df5295c7769757c72cde9a930fc82cb72caf0085ad", - "node_operator_id": 1, - "capability_ids": [ - "578ebf7413c15e36dfd792396c5a4d75c43f0ee7bbabdb703f7c5acd0bb65a1b" - ] - }, - { - "config_count": 1, - "workflow_don_id": 0, - "signer": "7621630d4f33e02f659445974060df375c126e82000000000000000000000000", - "p2p_id": "p2p_12D3KooWF1XmgvoLx45H3iGc9jD4mK7X1mctYmhZCqw5h1S1sXtA", - "encryption_public_key": "f8d7485910b56c9521dea1beb3d50151917bae18e131ad311ef90300318b8110", - "node_operator_id": 2, - "capability_ids": [ - "9f0f33d3737af0a2acae89e7f8c4638aeb886a67c1d84e13aee8532c70aa9483" - ], - "capability_don_ids": [ - 2 - ] - }, - { - "config_count": 1, - "workflow_don_id": 0, - "signer": "b5599a0a8aa99860997e42d650c3dc1ac767a4b1000000000000000000000000", - "p2p_id": "p2p_12D3KooWFBsQE8gCZndyefzCZG6KHyjoeii7o7ff171tQHsGYq1p", - "encryption_public_key": "4081aacba87f07ea54c32517a9b661963a5fed5fbfd2042ff0823293d8fbd523", - "node_operator_id": 2, - "capability_ids": [ - "9f0f33d3737af0a2acae89e7f8c4638aeb886a67c1d84e13aee8532c70aa9483" - ], - "capability_don_ids": [ - 2 - ] - }, - { - "config_count": 1, - "workflow_don_id": 0, - "signer": "2067cc4ec71978974265e578eb9b5c62cccc0d33000000000000000000000000", - "p2p_id": "p2p_12D3KooWKYQ51iqiS99MWfE8gwy7P1sN8oL4WboWLPxHRo8duc28", - "encryption_public_key": "533bfbd913615823cbb93251f27f3cbdd035a732c0a68ad49081b37a702fe4a1", - "node_operator_id": 2, - "capability_ids": [ - "9f0f33d3737af0a2acae89e7f8c4638aeb886a67c1d84e13aee8532c70aa9483" - ], - "capability_don_ids": [ - 2 - ] - }, - { - "config_count": 1, - "workflow_don_id": 0, - "signer": "cd08a4d5934c41a389c2bd7b6fadfb1dace5f110000000000000000000000000", - "p2p_id": "p2p_12D3KooWMQjP7pp8ecxMSMd3Y3NocDsHt7g64bd7iGJhCr35gkby", - "encryption_public_key": "9ee181448ef55e381217ec959375fb302eba62e61006e4c9467832836cc8640e", - "node_operator_id": 3, - "capability_ids": [ - "1ea6e85dfb8ebb08b7cd82b42ab4655429a8ae116d513be0d68a7d7661667a8a" - ], - "capability_don_ids": [ - 3 - ] - } - ], - "nops": [ - { - "admin": "0x528fdfde37119b52010a4920b09ef828249a3434", - "name": "nop 1" - }, - { - "admin": "0xe0967f1d0f36df4c53a34e491465c9d3f0095eb9", - "name": "nop 2" - }, - { - "admin": "0xe676a607b6f5c0b6d4c21aa616d727d5b0a47f35", - "name": "nop 3" - } - ], - "dons": [ - { - "id": 1, - "config_count": 1, - "f": 1, - "is_public": true, - "accepts_workflows": true, - "node_p2p_ids": [ - "p2p_12D3KooWAumheDZJdc3in1qiYGAQESTUm1nAWGA59eQPb3wuFHJa", - "p2p_12D3KooWE8ymezL2wxXcZdhznnBkVNcBRbtxVfNx1vppu7Z7zfnd", - "p2p_12D3KooWGVWpMrCZDotqSYWj8xqb1i5kNecpoarczpQoSAHdqwj8", - "p2p_12D3KooWSEF7cqkbMrS6uCo6xzCsfcPgquN652mZijmay8e3pn5R" - ], - "capability_configurations": [ - { - "id": "578ebf7413c15e36dfd792396c5a4d75c43f0ee7bbabdb703f7c5acd0bb65a1b", - "config": "0a00" - } - ] - }, - { - "id": 2, - "config_count": 1, - "f": 1, - "is_public": true, - "node_p2p_ids": [ - "p2p_12D3KooWF1XmgvoLx45H3iGc9jD4mK7X1mctYmhZCqw5h1S1sXtA", - "p2p_12D3KooWFBsQE8gCZndyefzCZG6KHyjoeii7o7ff171tQHsGYq1p", - "p2p_12D3KooWKYQ51iqiS99MWfE8gwy7P1sN8oL4WboWLPxHRo8duc28", - "p2p_12D3KooWPsGKEe34m9X8qiWVpa6VEcjdvhbygJRLKXdVEr3r96PH" - ], - "capability_configurations": [ - { - "id": "9f0f33d3737af0a2acae89e7f8c4638aeb886a67c1d84e13aee8532c70aa9483", - "config": "0a001a1a0a187369676e65645f7265706f72742e5369676e617475726573" - } - ] - }, - { - "id": 3, - "config_count": 1, - "f": 1, - "is_public": true, - "node_p2p_ids": [ - "p2p_12D3KooWD1uj8Y9Phdr1yScfbBy1Q9ebedMVBjMUBLW4m4XnEzGF", - "p2p_12D3KooWLjKKWLhYkr68PH9FaZZR93WbJuohWWcTfA9JeY1UPoJa", - "p2p_12D3KooWMQjP7pp8ecxMSMd3Y3NocDsHt7g64bd7iGJhCr35gkby", - "p2p_12D3KooWRG3rsPdQyWCPsQukUF5JqFLdPqVVXvEfG2PAPBbqdRXp" - ], - "capability_configurations": [ - { - "id": "1ea6e85dfb8ebb08b7cd82b42ab4655429a8ae116d513be0d68a7d7661667a8a", - "config": "0a00120a0a0208141202083c1802" - } - ] - } - ], - "don_capabilities_summary": [ - { - "don": { - "id": 1, - "config_count": 1, - "f": 1, - "is_public": true, - "accepts_workflows": true - }, - "nodes": [ - { - "config_count": 1, - "workflow_don_id": 1, - "signer": "f36818345fb18549bd24305c79f2f28d80d25710000000000000000000000000", - "p2p_id": "p2p_12D3KooWGVWpMrCZDotqSYWj8xqb1i5kNecpoarczpQoSAHdqwj8", - "encryption_public_key": "986707930499b85ab01705aa8d5cd99dca40926db3fa1728e6b58d25fddfe46b", - "nop": { - "admin": "0x528fdfde37119b52010a4920b09ef828249a3434", - "name": "nop 1" - } - }, - { - "config_count": 1, - "workflow_don_id": 1, - "signer": "afabd7685010d619ee6614e732b15e898c293426000000000000000000000000", - "p2p_id": "p2p_12D3KooWE8ymezL2wxXcZdhznnBkVNcBRbtxVfNx1vppu7Z7zfnd", - "encryption_public_key": "8a2aef988ccc85d985d12270c5263032b9a7c71a86430e7b3c30a2f493462aee", - "nop": { - "admin": "0x528fdfde37119b52010a4920b09ef828249a3434", - "name": "nop 1" - } - }, - { - "config_count": 1, - "workflow_don_id": 1, - "signer": "4bad6c33b85ba3bbbada74c93a7a719962456af8000000000000000000000000", - "p2p_id": "p2p_12D3KooWSEF7cqkbMrS6uCo6xzCsfcPgquN652mZijmay8e3pn5R", - "encryption_public_key": "cf8e0e8c830f733dd5992076d0adaeb34c97410dd5d8d04afccad88070b07f20", - "nop": { - "admin": "0x528fdfde37119b52010a4920b09ef828249a3434", - "name": "nop 1" - } - }, - { - "config_count": 1, - "workflow_don_id": 1, - "signer": "078cb3bca763a11a0c79df636b018311d9e36954000000000000000000000000", - "p2p_id": "p2p_12D3KooWAumheDZJdc3in1qiYGAQESTUm1nAWGA59eQPb3wuFHJa", - "encryption_public_key": "c8f45b74982037dd52eeb3df5295c7769757c72cde9a930fc82cb72caf0085ad", - "nop": { - "admin": "0x528fdfde37119b52010a4920b09ef828249a3434", - "name": "nop 1" - } - } - ], - "capabilities": [ - { - "id": "578ebf7413c15e36dfd792396c5a4d75c43f0ee7bbabdb703f7c5acd0bb65a1b", - "labelled_name": "offchain_reporting", - "version": "1.0.0", - "capability_type": 2, - "response_type": 0, - "configuration_contract": "0x0000000000000000000000000000000000000000" - } - ] - }, - { - "don": { - "id": 2, - "config_count": 1, - "f": 1, - "is_public": true - }, - "nodes": [ - { - "config_count": 1, - "workflow_don_id": 0, - "signer": "a0e11229b4b5d40d299f7f4b3348a1b16f5f3dd3000000000000000000000000", - "p2p_id": "p2p_12D3KooWPsGKEe34m9X8qiWVpa6VEcjdvhbygJRLKXdVEr3r96PH", - "encryption_public_key": "10c77049880fe0924f463763789985a0f76e09f82fc6f39943684b2dd05b98bf", - "nop": { - "admin": "0xe0967f1d0f36df4c53a34e491465c9d3f0095eb9", - "name": "nop 2" - } - }, - { - "config_count": 1, - "workflow_don_id": 0, - "signer": "7621630d4f33e02f659445974060df375c126e82000000000000000000000000", - "p2p_id": "p2p_12D3KooWF1XmgvoLx45H3iGc9jD4mK7X1mctYmhZCqw5h1S1sXtA", - "encryption_public_key": "f8d7485910b56c9521dea1beb3d50151917bae18e131ad311ef90300318b8110", - "nop": { - "admin": "0xe0967f1d0f36df4c53a34e491465c9d3f0095eb9", - "name": "nop 2" - } - }, - { - "config_count": 1, - "workflow_don_id": 0, - "signer": "b5599a0a8aa99860997e42d650c3dc1ac767a4b1000000000000000000000000", - "p2p_id": "p2p_12D3KooWFBsQE8gCZndyefzCZG6KHyjoeii7o7ff171tQHsGYq1p", - "encryption_public_key": "4081aacba87f07ea54c32517a9b661963a5fed5fbfd2042ff0823293d8fbd523", - "nop": { - "admin": "0xe0967f1d0f36df4c53a34e491465c9d3f0095eb9", - "name": "nop 2" - } - }, - { - "config_count": 1, - "workflow_don_id": 0, - "signer": "2067cc4ec71978974265e578eb9b5c62cccc0d33000000000000000000000000", - "p2p_id": "p2p_12D3KooWKYQ51iqiS99MWfE8gwy7P1sN8oL4WboWLPxHRo8duc28", - "encryption_public_key": "533bfbd913615823cbb93251f27f3cbdd035a732c0a68ad49081b37a702fe4a1", - "nop": { - "admin": "0xe0967f1d0f36df4c53a34e491465c9d3f0095eb9", - "name": "nop 2" - } - } - ], - "capabilities": [ - { - "id": "9f0f33d3737af0a2acae89e7f8c4638aeb886a67c1d84e13aee8532c70aa9483", - "labelled_name": "write_ethereum-testnet-sepolia", - "version": "1.0.0", - "capability_type": 3, - "response_type": 0, - "configuration_contract": "0x0000000000000000000000000000000000000000" - } - ] - }, - { - "don": { - "id": 3, - "config_count": 1, - "f": 1, - "is_public": true - }, - "nodes": [ - { - "config_count": 1, - "workflow_don_id": 0, - "signer": "3f871cd7c34e50320934b6ba9b90b249363fd378000000000000000000000000", - "p2p_id": "p2p_12D3KooWLjKKWLhYkr68PH9FaZZR93WbJuohWWcTfA9JeY1UPoJa", - "encryption_public_key": "5cf5abd0349b27cde43ad1a55aa3b02a5518aa6eed365bd65ca5e0e2cbfdaa5a", - "nop": { - "admin": "0xe676a607b6f5c0b6d4c21aa616d727d5b0a47f35", - "name": "nop 3" - } - }, - { - "config_count": 1, - "workflow_don_id": 0, - "signer": "d7a432ce8f23c410302e7577de9973ccbca29576000000000000000000000000", - "p2p_id": "p2p_12D3KooWRG3rsPdQyWCPsQukUF5JqFLdPqVVXvEfG2PAPBbqdRXp", - "encryption_public_key": "c10cead34374ba20704a05ca0369018b41778a0297adb85554cdd6e5955bf4b6", - "nop": { - "admin": "0xe676a607b6f5c0b6d4c21aa616d727d5b0a47f35", - "name": "nop 3" - } - }, - { - "config_count": 1, - "workflow_don_id": 0, - "signer": "f1d2b3d13c46b0c1ded96534aabd6bae61934e3f000000000000000000000000", - "p2p_id": "p2p_12D3KooWD1uj8Y9Phdr1yScfbBy1Q9ebedMVBjMUBLW4m4XnEzGF", - "encryption_public_key": "5fc3dae131da5b0ac5474ad029e3a6c547e17249a6266427d5eea1f529b6488b", - "nop": { - "admin": "0xe676a607b6f5c0b6d4c21aa616d727d5b0a47f35", - "name": "nop 3" - } - }, - { - "config_count": 1, - "workflow_don_id": 0, - "signer": "cd08a4d5934c41a389c2bd7b6fadfb1dace5f110000000000000000000000000", - "p2p_id": "p2p_12D3KooWMQjP7pp8ecxMSMd3Y3NocDsHt7g64bd7iGJhCr35gkby", - "encryption_public_key": "9ee181448ef55e381217ec959375fb302eba62e61006e4c9467832836cc8640e", - "nop": { - "admin": "0xe676a607b6f5c0b6d4c21aa616d727d5b0a47f35", - "name": "nop 3" - } - } - ], - "capabilities": [ - { - "id": "1ea6e85dfb8ebb08b7cd82b42ab4655429a8ae116d513be0d68a7d7661667a8a", - "labelled_name": "streams-trigger", - "version": "1.0.0", - "capability_type": 0, - "response_type": 0, - "configuration_contract": "0x0000000000000000000000000000000000000000" - } - ] - } - ] -} \ No newline at end of file diff --git a/deployment/keystone/testdata/asset_nodes.json b/deployment/keystone/testdata/asset_nodes.json new file mode 100644 index 00000000000..9ad2ba4e0e8 --- /dev/null +++ b/deployment/keystone/testdata/asset_nodes.json @@ -0,0 +1,978 @@ +[ + { + "id": "81", + "keys": [ + "cl-df-asset-don-testnet-0" + ], + "name": "Chainlink Keystone Asset DON Node Operator 0", + "metadata": { + "nodeCount": 2, + "jobCount": 18 + }, + "nodes": [ + { + "id": "831", + "name": "Chainlink Sepolia Prod Keystone Asset Node 0", + "publicKey": "d791dad33f1aeff811f3364088993053d5d08fa595ba48f73aecd4ee2d5035a1", + "chainConfigs": [ + { + "network": { + "id": "129", + "chainID": "11155111", + "chainType": "EVM", + "name": "Ethereum Testnet (Sepolia)" + }, + "accountAddress": "0xe826b8D7f57b1c08E2d0C9477006244AECB280c3", + "adminAddress": "0x900FDC4d45297A743e4508986d4C1aa1BAf89A83", + "ocr1Config": { + "p2pKeyBundle": {}, + "ocrKeyBundle": {} + }, + "ocr2Config": { + "enabled": true, + "p2pKeyBundle": { + "peerID": "p2p_12D3KooWDh47EiK5TzG4yApEEwLecgRkqZKQif3fcnsztfhQNzNh", + "publicKey": "398f42d12c7f3445341e42ce4ea555c87d84db68c808c76a0655e5d993d7a2a6" + }, + "ocrKeyBundle": { + "bundleID": "c8dee638c00194cf38bd0c30306fffd14b561601828085ceaaf0ab5fe451ec23", + "configPublicKey": "dbd5d1f5aa4921fd1e7b16f26dc75aff5cc08fee6e74324e947654ba78791e7e", + "offchainPublicKey": "66a599cda37e6fb5dc50e16d7c81e6967e010a25bbeaabf20752e228a26f5bc3", + "onchainSigningAddress": "9184c1c20da57f2f747a60909d0152c289e8518f" + }, + "plugins": { + "mercury": true + } + } + } + ], + "connected": true, + "supportedProducts": [ + "DATA_STREAMS_V03" + ], + "categories": [ + { + "id": "11", + "name": "Keystone" + } + ] + } + ], + "createdAt": "2024-09-18T19:19:34.127102Z" + }, + { + "id": "82", + "keys": [ + "cl-df-asset-don-testnet-1" + ], + "name": "Chainlink Keystone Asset DON Node Operator 1", + "metadata": { + "nodeCount": 1, + "jobCount": 9 + }, + "nodes": [ + { + "id": "832", + "name": "Chainlink Sepolia Prod Keystone Asset Node 1", + "publicKey": "eb410038ba7847a729c4e40c1d4afdbcce9ad33cc71e459883cd98f0883a5366", + "chainConfigs": [ + { + "network": { + "id": "129", + "chainID": "11155111", + "chainType": "EVM", + "name": "Ethereum Testnet (Sepolia)" + }, + "accountAddress": "0xCE154165b0d60D1efA9b3c7a172ED77712Cb82f9", + "adminAddress": "0x900FDC4d45297A743e4508986d4C1aa1BAf89A83", + "ocr1Config": { + "p2pKeyBundle": {}, + "ocrKeyBundle": {} + }, + "ocr2Config": { + "enabled": true, + "p2pKeyBundle": { + "peerID": "p2p_12D3KooWG7WEsQjxXQdn5WAEQSDh77qxjMoWxz3rGYrRC9pPB7qx", + "publicKey": "5d8a1f11ecd0cd2cdd95fec35b8ea6386af567bc96aa2c2ea47e91d22b1f12bf" + }, + "ocrKeyBundle": { + "bundleID": "a6dda044db7fa1fa652ec9ff60a44fb31ee99d33db35599848b21e34ce33c343", + "configPublicKey": "586fb9935401e8907ead91e7a3423a0c0676d4669bac619f71c99913e14b362a", + "offchainPublicKey": "9557c0c4c6c8aeb41ecaa84f0aa7d0e1be7ffa9e4a08da27b23bd64b2d0c0fe9", + "onchainSigningAddress": "bd3e16dda612f543c0f79fafc03fa35f3f300e30" + }, + "plugins": { + "mercury": true + } + } + } + ], + "connected": true, + "supportedProducts": [ + "DATA_STREAMS_V03" + ], + "categories": [ + { + "id": "11", + "name": "Keystone" + } + ] + } + ], + "createdAt": "2024-09-18T19:19:48.159926Z" + }, + { + "id": "83", + "keys": [ + "cl-df-asset-don-testnet-2" + ], + "name": "Chainlink Keystone Asset DON Node Operator 2", + "metadata": { + "nodeCount": 1, + "jobCount": 9 + }, + "nodes": [ + { + "id": "833", + "name": "Chainlink Sepolia Prod Keystone Asset Node 2", + "publicKey": "daf14b79caa585c3dacf550688aeed5371f8fd39cbfb6e33add2fb82538626b0", + "chainConfigs": [ + { + "network": { + "id": "129", + "chainID": "11155111", + "chainType": "EVM", + "name": "Ethereum Testnet (Sepolia)" + }, + "accountAddress": "0xbb16a69A7bb8778dc52a2D081EE1B2Dde0237F3b", + "adminAddress": "0x900FDC4d45297A743e4508986d4C1aa1BAf89A83", + "ocr1Config": { + "p2pKeyBundle": {}, + "ocrKeyBundle": {} + }, + "ocr2Config": { + "enabled": true, + "p2pKeyBundle": { + "peerID": "p2p_12D3KooWBWms38viHaptUHTXXNdN4Qm2ZxDWtuaZviZtq1WzWWcq", + "publicKey": "1935b60309f79e7fd1bfd4736df5729b7532bcd435be2a707dd28519e9ae6e6a" + }, + "ocrKeyBundle": { + "bundleID": "9c63a332ff254cd2cda8bcf2c3f0e46ee95d4991595019619a0c60907437d98c", + "configPublicKey": "29b9b6f61db8e72df13e17e274bdf5450987953079b9dee2745f2d288dc7e86d", + "offchainPublicKey": "c3b08d0b68baf68da2c8446f6a9dc552af3ab2014b900d75ca9e2122b6fc9eb0", + "onchainSigningAddress": "cb66494d66922ad00708bce7c83ada133ddb8994" + }, + "plugins": { + "mercury": true + } + } + } + ], + "connected": true, + "supportedProducts": [ + "DATA_STREAMS_V03" + ], + "categories": [ + { + "id": "11", + "name": "Keystone" + } + ] + } + ], + "createdAt": "2024-09-18T19:20:01.151494Z" + }, + { + "id": "84", + "keys": [ + "cl-df-asset-don-testnet-3" + ], + "name": "Chainlink Keystone Asset DON Node Operator 3", + "metadata": { + "nodeCount": 1, + "jobCount": 9 + }, + "nodes": [ + { + "id": "834", + "name": "Chainlink Sepolia Prod Keystone Asset Node 3", + "publicKey": "0e1f9462a8b326d746fde2d5016faa9f2e017f7e6e5969aaf3281519d2e31dbc", + "chainConfigs": [ + { + "network": { + "id": "129", + "chainID": "11155111", + "chainType": "EVM", + "name": "Ethereum Testnet (Sepolia)" + }, + "accountAddress": "0xA64f65e0c12ab015792c34867BE5b80b4D4C551A", + "adminAddress": "0x900FDC4d45297A743e4508986d4C1aa1BAf89A83", + "ocr1Config": { + "p2pKeyBundle": {}, + "ocrKeyBundle": {} + }, + "ocr2Config": { + "enabled": true, + "p2pKeyBundle": { + "peerID": "p2p_12D3KooWMhHZTVHz23gCQAEzFyeBLxR9ghVqMQHk18VND4TbAc1U", + "publicKey": "b07bf77b2b1d8964915d4871b4cd0173e13bc1d0590731a8969393a6e80aef8f" + }, + "ocrKeyBundle": { + "bundleID": "87770ad41d54661a6dee424612f4338b49cd4fd20bdab1f11c308c76efeb56f8", + "configPublicKey": "dd0edc91d1476a0a4c554e8fe8050dadba679ba42f53973bf181d85eed1b6821", + "offchainPublicKey": "2ba2cc779c8e1460d9ff823d594708a344bb7a9d84aa3aa3833d539852511a88", + "onchainSigningAddress": "5e5b1a602c5a79ec6cdeb67e6f855d58061f785f" + }, + "plugins": { + "mercury": true + } + } + } + ], + "connected": true, + "supportedProducts": [ + "DATA_STREAMS_V03" + ], + "categories": [ + { + "id": "11", + "name": "Keystone" + } + ] + } + ], + "createdAt": "2024-09-18T19:20:10.382565Z" + }, + { + "id": "85", + "keys": [ + "cl-df-asset-don-testnet-4" + ], + "name": "Chainlink Keystone Asset DON Node Operator 4", + "metadata": { + "nodeCount": 1, + "jobCount": 9 + }, + "nodes": [ + { + "id": "835", + "name": "Chainlink Sepolia Prod Keystone Asset Node 4", + "publicKey": "1d5f6ef3443e48bd471efdb47a5b9c6c900a14f35253c2b562908186f5b8b457", + "chainConfigs": [ + { + "network": { + "id": "129", + "chainID": "11155111", + "chainType": "EVM", + "name": "Ethereum Testnet (Sepolia)" + }, + "accountAddress": "0x7284bBa5C8090Ac99d55b14db015a291C017275c", + "adminAddress": "0x900FDC4d45297A743e4508986d4C1aa1BAf89A83", + "ocr1Config": { + "p2pKeyBundle": {}, + "ocrKeyBundle": {} + }, + "ocr2Config": { + "enabled": true, + "p2pKeyBundle": { + "peerID": "p2p_12D3KooWMrkkbkFYJydLhcYKr8AnxNcNGmwfVXMQGdn8uoSpYoJs", + "publicKey": "b2e8f0b25c7334e8082cb82eee29bc4f48ae086b8fe4a2fd5eb4e08195a0e06c" + }, + "ocrKeyBundle": { + "bundleID": "1ceac31d893d21e95a62419d94b1a88805fa4f056b1636ccd79ab0ca8b4fe68c", + "configPublicKey": "4c94f49461fd0fd9d4da5cda4590a2cf80fba2ea27c422b92ee18a3aaaa51321", + "offchainPublicKey": "d1649b393614e01811979340d2726280f9ea57fd7a1ee28958adbbaf71b41bf5", + "onchainSigningAddress": "e47d17607054e9899d3fb7fa5b4b3e01b85b8fc9" + }, + "plugins": { + "mercury": true + } + } + } + ], + "connected": true, + "supportedProducts": [ + "DATA_STREAMS_V03" + ], + "categories": [ + { + "id": "11", + "name": "Keystone" + } + ] + } + ], + "createdAt": "2024-09-18T19:20:21.050174Z" + }, + { + "id": "86", + "keys": [ + "cl-df-asset-don-testnet-5" + ], + "name": "Chainlink Keystone Asset DON Node Operator 5", + "metadata": { + "nodeCount": 1, + "jobCount": 9 + }, + "nodes": [ + { + "id": "837", + "name": "Chainlink Sepolia Prod Keystone Asset Node 5", + "publicKey": "d87dfbb7444036e0654578afdb11864e31a0de1824ca2780f24b16116a85463d", + "chainConfigs": [ + { + "network": { + "id": "129", + "chainID": "11155111", + "chainType": "EVM", + "name": "Ethereum Testnet (Sepolia)" + }, + "accountAddress": "0x6c75DB65540ca889803a092d4C1497D3337cDE30", + "adminAddress": "0x900FDC4d45297A743e4508986d4C1aa1BAf89A83", + "ocr1Config": { + "p2pKeyBundle": {}, + "ocrKeyBundle": {} + }, + "ocr2Config": { + "enabled": true, + "p2pKeyBundle": { + "peerID": "p2p_12D3KooWH8q69DtEqahJdwKfYXnkRHHH6E4jTqevZSAZzGsrnsTB", + "publicKey": "6cbcb3cc0a48ec9d94bb1424beea5e1b7cf57fda2dbfc519afd9221cbeac3b8e" + }, + "ocrKeyBundle": { + "bundleID": "6e088c00e61fea95a5a808a56e7e55c58ec0d61c3207383a2c63abc705bd120c", + "configPublicKey": "0728ce40c95155853ecd31bc213ed2b39d4ecf2e62dc95334f008181ad010848", + "offchainPublicKey": "521d4c291fe8ef245b2e497982b0a07127cd3c65439a10784d914e03ba24328d", + "onchainSigningAddress": "d32a6ed4be6656fd988a0e43e71ce43fab3faba4" + }, + "plugins": { + "mercury": true + } + } + } + ], + "connected": true, + "supportedProducts": [ + "DATA_STREAMS_V03" + ], + "categories": [ + { + "id": "11", + "name": "Keystone" + } + ] + } + ], + "createdAt": "2024-09-18T19:21:21.831183Z" + }, + { + "id": "87", + "keys": [ + "cl-df-asset-don-testnet-6" + ], + "name": "Chainlink Keystone Asset DON Node Operator 6", + "metadata": { + "nodeCount": 1, + "jobCount": 9 + }, + "nodes": [ + { + "id": "838", + "name": "Chainlink Sepolia Prod Keystone Asset Node 6", + "publicKey": "294f58723d4049af0dcd63eedfcda957287401a10070db509ede7a799bb70654", + "chainConfigs": [ + { + "network": { + "id": "129", + "chainID": "11155111", + "chainType": "EVM", + "name": "Ethereum Testnet (Sepolia)" + }, + "accountAddress": "0xa2788731913cc2deBC061F8594AEaa8e99B4FCCE", + "adminAddress": "0x900FDC4d45297A743e4508986d4C1aa1BAf89A83", + "ocr1Config": { + "p2pKeyBundle": {}, + "ocrKeyBundle": {} + }, + "ocr2Config": { + "enabled": true, + "p2pKeyBundle": { + "peerID": "p2p_12D3KooWD7URmTzSeotMvEzkJTiFrwUHhcGMBeaS9GY8763Sqqnf", + "publicKey": "30f502f9fb19b54e8644f038f57f9a43582f76b86bace61759fff12886ccf1a8" + }, + "ocrKeyBundle": { + "bundleID": "57bc2a8a62ed96e6aa7b9bbe56f93abeef938a1766cb8a6d18e42ebf71101646", + "configPublicKey": "36c882b0cdcec84aa85f00ea43cd31254406cec84d31f6dded69b4fbb3f17449", + "offchainPublicKey": "46951e1e18cee25cd417b3fa7feb25fb53623a249e1c09491bb978dccc2ea76e", + "onchainSigningAddress": "abcd8be3952a84fb10947dbeb768a255ead58ca2" + }, + "plugins": { + "mercury": true + } + } + } + ], + "connected": true, + "supportedProducts": [ + "DATA_STREAMS_V03" + ], + "categories": [ + { + "id": "11", + "name": "Keystone" + } + ] + } + ], + "createdAt": "2024-09-18T19:21:34.93501Z" + }, + { + "id": "88", + "keys": [ + "cl-df-asset-don-testnet-7" + ], + "name": "Chainlink Keystone Asset DON Node Operator 7", + "metadata": { + "nodeCount": 1, + "jobCount": 9 + }, + "nodes": [ + { + "id": "839", + "name": "Chainlink Sepolia Prod Keystone Asset Node 7", + "publicKey": "55b0ec5d90de973c00efce233334a9d3c5a94062ea010575bb248eb6804a9cfe", + "chainConfigs": [ + { + "network": { + "id": "129", + "chainID": "11155111", + "chainType": "EVM", + "name": "Ethereum Testnet (Sepolia)" + }, + "accountAddress": "0x14dAF00DaD855089A6586690d5C1fD2779302736", + "adminAddress": "0x900FDC4d45297A743e4508986d4C1aa1BAf89A83", + "ocr1Config": { + "p2pKeyBundle": {}, + "ocrKeyBundle": {} + }, + "ocr2Config": { + "enabled": true, + "p2pKeyBundle": { + "peerID": "p2p_12D3KooWBbo44H5CLACV3yGyDWrtMuSWRdN5sQcDsnPC4WfLr6Jo", + "publicKey": "1a7ef5e7420434fcf06de3d15a0191f7499e00e15427679616ce800779ceb514" + }, + "ocrKeyBundle": { + "bundleID": "f87acde2c1c21e8859d84813034d84a3f3bb1d49596e13ac66731d50750b9436", + "configPublicKey": "e75f21bc1dc6eac12358277caf18a216ed54f8dc84285941ef1f5fb1047f8d5b", + "offchainPublicKey": "c7b86dfbdf31a3b13c44305cd6fc88c402653198201006083414223ffc36950d", + "onchainSigningAddress": "93fbb113f191959f8ab5e052395676e0038f2f1f" + }, + "plugins": { + "mercury": true + } + } + } + ], + "connected": true, + "supportedProducts": [ + "DATA_STREAMS_V03" + ], + "categories": [ + { + "id": "11", + "name": "Keystone" + } + ] + } + ], + "createdAt": "2024-09-18T19:21:45.063449Z" + }, + { + "id": "89", + "keys": [ + "cl-df-asset-don-testnet-8" + ], + "name": "Chainlink Keystone Asset DON Node Operator 8", + "metadata": { + "nodeCount": 1, + "jobCount": 9 + }, + "nodes": [ + { + "id": "840", + "name": "Chainlink Sepolia Prod Keystone Asset Node 8", + "publicKey": "8f9f327ac7ad823a0f3297f3505591bcd40adc8fb1309f99874c26663cbd5914", + "chainConfigs": [ + { + "network": { + "id": "129", + "chainID": "11155111", + "chainType": "EVM", + "name": "Ethereum Testnet (Sepolia)" + }, + "accountAddress": "0xb0C0168905C07F00A141494eaeFc0bD9F153fc16", + "adminAddress": "0x900FDC4d45297A743e4508986d4C1aa1BAf89A83", + "ocr1Config": { + "p2pKeyBundle": {}, + "ocrKeyBundle": {} + }, + "ocr2Config": { + "enabled": true, + "p2pKeyBundle": { + "peerID": "p2p_12D3KooWGVroAehJh33SBns9MohmctNPZSDh89KRQM1J6TSCnT1v", + "publicKey": "63442493270891409900afd3bb868d03fd07c775bb38c56e56a624b674a68b35" + }, + "ocrKeyBundle": { + "bundleID": "4413e0a3080c3dfa7709b16c3ee68c04359e2dd66d107fd3be6ba7c615c4b3b6", + "configPublicKey": "8f3975b19fc6f02e241119b2132331ed9ed0d19221bd0cfd6f54b5859090a741", + "offchainPublicKey": "f4f182c889668d8951932c49e1ffb1252b8a33a9875d3f19aea7bb805b65c7a6", + "onchainSigningAddress": "b257e9efe637f38b5462a170737571ea0f0e2e05" + }, + "plugins": { + "mercury": true + } + } + } + ], + "connected": true, + "supportedProducts": [ + "DATA_STREAMS_V03" + ], + "categories": [ + { + "id": "11", + "name": "Keystone" + } + ] + } + ], + "createdAt": "2024-09-18T19:21:55.09098Z" + }, + { + "id": "90", + "keys": [ + "cl-df-asset-don-testnet-9" + ], + "name": "Chainlink Keystone Asset DON Node Operator 9", + "metadata": { + "nodeCount": 1, + "jobCount": 9 + }, + "nodes": [ + { + "id": "841", + "name": "Chainlink Sepolia Prod Keystone Asset Node 9", + "publicKey": "1d79884071dfec1f39dc62f4868f4a143ae39cb03ad9d14142b184686c2b5a93", + "chainConfigs": [ + { + "network": { + "id": "129", + "chainID": "11155111", + "chainType": "EVM", + "name": "Ethereum Testnet (Sepolia)" + }, + "accountAddress": "0x2F5E08a5b9D893e9dA2d68Ef605fBa6f8Ebfd0cB", + "adminAddress": "0x900FDC4d45297A743e4508986d4C1aa1BAf89A83", + "ocr1Config": { + "p2pKeyBundle": {}, + "ocrKeyBundle": {} + }, + "ocr2Config": { + "enabled": true, + "p2pKeyBundle": { + "peerID": "p2p_12D3KooWEBn9tWmMWrSxRZe2VQ56RcSHRUPdcFoD3Ep88wqTT9zP", + "publicKey": "40eb109d9f28e8754dfff419a9175d6714405907413d2f77657355721c3b2bd0" + }, + "ocrKeyBundle": { + "bundleID": "6d4da72b1daad0b9ea47a7daa6cde81c1608b7bd199c05b18b989d10c5d7b99e", + "configPublicKey": "7e1c66bfa23c270770401d0dd739adad5a52827ecb40a0668f7e014d53f38059", + "offchainPublicKey": "712561a10b1f7dd96f0ae0f0d3e6cdf83fdd0837d333cf9bbae0090126ae7f39", + "onchainSigningAddress": "2ef8cea7dae7bd1e876a59a44ca59b89adf8abb4" + }, + "plugins": { + "mercury": true + } + } + } + ], + "connected": true, + "supportedProducts": [ + "DATA_STREAMS_V03" + ], + "categories": [ + { + "id": "11", + "name": "Keystone" + } + ] + } + ], + "createdAt": "2024-09-18T19:22:09.476108Z" + }, + { + "id": "91", + "keys": [ + "cl-df-asset-don-testnet-10" + ], + "name": "Chainlink Keystone Asset DON Node Operator 10", + "metadata": { + "nodeCount": 1, + "jobCount": 9 + }, + "nodes": [ + { + "id": "842", + "name": "Chainlink Sepolia Prod Keystone Asset Node 10", + "publicKey": "cf6c47ad934518f5947ce8f1a48c2df8c93bd585788a3a82229fd4d723efa706", + "chainConfigs": [ + { + "network": { + "id": "129", + "chainID": "11155111", + "chainType": "EVM", + "name": "Ethereum Testnet (Sepolia)" + }, + "accountAddress": "0x4794743bB8f159954Efa31642609ebfD4D2b9EdC", + "adminAddress": "0x900FDC4d45297A743e4508986d4C1aa1BAf89A83", + "ocr1Config": { + "p2pKeyBundle": {}, + "ocrKeyBundle": {} + }, + "ocr2Config": { + "enabled": true, + "p2pKeyBundle": { + "peerID": "p2p_12D3KooWNXZCbQe4Ao7KEciJGY6Ec4oZLZNGcMTPyZ7XpFhLPyLo", + "publicKey": "bcd987b3b2b20d9effe30598850ddfd33023339dab012c4aee4cdc4246111bfc" + }, + "ocrKeyBundle": { + "bundleID": "a8d9929327d89cfabd8c583d250dfddbc14e947e9253f7471191886ca5197786", + "configPublicKey": "a1a390e756bce818d1786dca6ba3e45013085087e5a3be6253d8bbbd6479255a", + "offchainPublicKey": "76522fec251ce6130c03a816025f2054eb3ac83b7d30347f42b73a77e7b9a511", + "onchainSigningAddress": "179d48901e5e9c3c11dd947c001f8a2ee887c8eb" + }, + "plugins": { + "mercury": true + } + } + } + ], + "connected": true, + "supportedProducts": [ + "DATA_STREAMS_V03" + ], + "categories": [ + { + "id": "11", + "name": "Keystone" + } + ] + } + ], + "createdAt": "2024-09-18T19:22:30.732346Z" + }, + { + "id": "92", + "keys": [ + "cl-df-asset-don-testnet-11" + ], + "name": "Chainlink Keystone Asset DON Node Operator 11", + "metadata": { + "nodeCount": 1, + "jobCount": 9 + }, + "nodes": [ + { + "id": "843", + "name": "Chainlink Sepolia Prod Keystone Asset Node 11", + "publicKey": "c239c23670224558a64ea3165eae8d67a17b75b1874fbccf8a4dd98e953820ad", + "chainConfigs": [ + { + "network": { + "id": "129", + "chainID": "11155111", + "chainType": "EVM", + "name": "Ethereum Testnet (Sepolia)" + }, + "accountAddress": "0x27AFd92F391dFD7BA1bbC89e3bd13ceC9A667c11", + "adminAddress": "0x900FDC4d45297A743e4508986d4C1aa1BAf89A83", + "ocr1Config": { + "p2pKeyBundle": {}, + "ocrKeyBundle": {} + }, + "ocr2Config": { + "enabled": true, + "p2pKeyBundle": { + "peerID": "p2p_12D3KooWSSzLfwq7QSdJcpDLFiBznA1XR58dwg1xre4b88SbP7VF", + "publicKey": "f71ccc7f7b73f1499f72987679a94a11e8564f01415acdb958c008c5bfe21eae" + }, + "ocrKeyBundle": { + "bundleID": "3e691b13aa702631fba25f6e128a566bdff3982cc3438af29acc2a819b9d6e02", + "configPublicKey": "149d81dce137d0874b477ad6c19dc72801f335200622fa34f1c660623febed22", + "offchainPublicKey": "b0d0d8e3c62abc7236e6539413ef82e568dd24f0c39ff6e8e2babe513590a522", + "onchainSigningAddress": "a0f2feab4d03899eb2e830bd4abc3fd5babef3e1" + }, + "plugins": { + "mercury": true + } + } + } + ], + "connected": true, + "supportedProducts": [ + "DATA_STREAMS_V03" + ], + "categories": [ + { + "id": "11", + "name": "Keystone" + } + ] + } + ], + "createdAt": "2024-09-18T19:22:42.314654Z" + }, + { + "id": "93", + "keys": [ + "cl-df-asset-don-testnet-12" + ], + "name": "Chainlink Keystone Asset DON Node Operator 12", + "metadata": { + "nodeCount": 1, + "jobCount": 9 + }, + "nodes": [ + { + "id": "844", + "name": "Chainlink Sepolia Prod Keystone Asset Node 12", + "publicKey": "71b29eb63daa6ac2e48b46669936eff5606879b102bae78afc929554c435dd0b", + "chainConfigs": [ + { + "network": { + "id": "129", + "chainID": "11155111", + "chainType": "EVM", + "name": "Ethereum Testnet (Sepolia)" + }, + "accountAddress": "0x13d5b27d71B4C4697874177Ff43DEB1884Cff49e", + "adminAddress": "0x900FDC4d45297A743e4508986d4C1aa1BAf89A83", + "ocr1Config": { + "p2pKeyBundle": {}, + "ocrKeyBundle": {} + }, + "ocr2Config": { + "enabled": true, + "p2pKeyBundle": { + "peerID": "p2p_12D3KooWT1LMqEW51UfxBynzjYjuybQzVkmf4rH9js9e16QAbU3X", + "publicKey": "ff66057a6c96779134a6527364cddcce43b69e3d1820f59dde5e6b38d1d32fde" + }, + "ocrKeyBundle": { + "bundleID": "4854ee3fc7ac4591eea33c5d0d1cefd4ad819d2c374a2f86267a9999228a967a", + "configPublicKey": "470225644f274147b5b80c862a3f3cd7a19fed4ff915e9c18ac80e06003ecc6a", + "offchainPublicKey": "e7d89e196f5f6d92f4c42ab34f9a2f21f3201314be65b819872c4609b87866c7", + "onchainSigningAddress": "c84f2f60ccb1d7e6c6e4ae4bc3cab8bb85db8977" + }, + "plugins": { + "mercury": true + } + } + } + ], + "connected": true, + "supportedProducts": [ + "DATA_STREAMS_V03" + ], + "categories": [ + { + "id": "11", + "name": "Keystone" + } + ] + } + ], + "createdAt": "2024-09-18T19:22:52.838595Z" + }, + { + "id": "94", + "keys": [ + "cl-df-asset-don-testnet-13" + ], + "name": "Chainlink Keystone Asset DON Node Operator 13", + "metadata": { + "nodeCount": 1, + "jobCount": 9 + }, + "nodes": [ + { + "id": "845", + "name": "Chainlink Sepolia Prod Keystone Asset Node 13", + "publicKey": "c098264a552125355804b903de06400621f2d1de357c2bed94586727fe8a3502", + "chainConfigs": [ + { + "network": { + "id": "129", + "chainID": "11155111", + "chainType": "EVM", + "name": "Ethereum Testnet (Sepolia)" + }, + "accountAddress": "0x5647A091F2a09915c1C0F6ac95630Be87114881F", + "adminAddress": "0x900FDC4d45297A743e4508986d4C1aa1BAf89A83", + "ocr1Config": { + "p2pKeyBundle": {}, + "ocrKeyBundle": {} + }, + "ocr2Config": { + "enabled": true, + "p2pKeyBundle": { + "peerID": "p2p_12D3KooWRjg2KoP6jKVWU2BczeduWsdnfN69tHN2YGEAGtETvc9P", + "publicKey": "ec87467a512f8218bb63f7fcf46cf0b8fd8ebb14bd5f3b670908d505a5af801a" + }, + "ocrKeyBundle": { + "bundleID": "20626049a1e24912a14d186645ba70fea4860efcc987b3ec7c9ddc881b5057db", + "configPublicKey": "d84d4653db0caca062d4058e9937ae618a53bbd1b41a673c5f13bebc24e7aa3a", + "offchainPublicKey": "156c8ab52099386377fe27bbd50dafa368ff2790245f1407579f590b0bae7a1e", + "onchainSigningAddress": "4f4b7bff5d32d62326b575d8c951d34e54888e31" + }, + "plugins": { + "mercury": true + } + } + } + ], + "connected": true, + "supportedProducts": [ + "DATA_STREAMS_V03" + ], + "categories": [ + { + "id": "11", + "name": "Keystone" + } + ] + } + ], + "createdAt": "2024-09-18T19:23:19.587619Z" + }, + { + "id": "95", + "keys": [ + "cl-df-asset-don-testnet-14" + ], + "name": "Chainlink Keystone Asset DON Node Operator 14", + "metadata": { + "nodeCount": 1, + "jobCount": 9 + }, + "nodes": [ + { + "id": "846", + "name": "Chainlink Sepolia Prod Keystone Asset Node 14", + "publicKey": "12681ec137cd2d25e7c71638f564404dd764061921c870bbcddf683d048eed21", + "chainConfigs": [ + { + "network": { + "id": "129", + "chainID": "11155111", + "chainType": "EVM", + "name": "Ethereum Testnet (Sepolia)" + }, + "accountAddress": "0x0419E70d32c3972930c99aaaDF20dCB473c56d22", + "adminAddress": "0x900FDC4d45297A743e4508986d4C1aa1BAf89A83", + "ocr1Config": { + "p2pKeyBundle": {}, + "ocrKeyBundle": {} + }, + "ocr2Config": { + "enabled": true, + "p2pKeyBundle": { + "peerID": "p2p_12D3KooWCdEG68z5kwYuD1xp1aJsFBtpw2HYh1K3ffVM6keVrJnT", + "publicKey": "29b8bafebdef5e11ec3556fbcacdfb626d2f80cf178406e38664775e8b1ace78" + }, + "ocrKeyBundle": { + "bundleID": "80b1304898d5cea3c684790a0f01158468c7fa7770675edef33e4b137232ddc9", + "configPublicKey": "15552ecb6ff10103a534f02594a7b7cbab686d76d5e7b32a9c67059e8c856861", + "offchainPublicKey": "b561b7df3bdfe70f1af9395dbc00ef796774aa352c9a30d9c7e2f7e74d438073", + "onchainSigningAddress": "fb1ca65bf473b4443d7359becc0de67a2d96228d" + }, + "plugins": { + "mercury": true + } + } + } + ], + "connected": true, + "supportedProducts": [ + "DATA_STREAMS_V03" + ], + "categories": [ + { + "id": "11", + "name": "Keystone" + } + ] + } + ], + "createdAt": "2024-09-18T19:23:44.73219Z" + }, + { + "id": "96", + "keys": [ + "cl-df-asset-don-testnet-15" + ], + "name": "Chainlink Keystone Asset DON Node Operator 15", + "metadata": { + "nodeCount": 1, + "jobCount": 9 + }, + "nodes": [ + { + "id": "847", + "name": "Chainlink Sepolia Prod Keystone Asset Node 15", + "publicKey": "a9a5d084f9cbbbd291eb43c33dd137cd6140e33c53cebb260463bf52795ec579", + "chainConfigs": [ + { + "network": { + "id": "129", + "chainID": "11155111", + "chainType": "EVM", + "name": "Ethereum Testnet (Sepolia)" + }, + "accountAddress": "0x931900764a585D7a01e500976B630B4747216c8c", + "adminAddress": "0x900FDC4d45297A743e4508986d4C1aa1BAf89A83", + "ocr1Config": { + "p2pKeyBundle": {}, + "ocrKeyBundle": {} + }, + "ocr2Config": { + "enabled": true, + "p2pKeyBundle": { + "peerID": "p2p_12D3KooWQyZ9A9ScBpcoRww1gJVBNB2brNkjJhaqze6ehuv6bmfQ", + "publicKey": "e139f020ae4bc9efaa77da9cfd54339d36176479028f849b9e64ad2cf29acba3" + }, + "ocrKeyBundle": { + "bundleID": "5c1c69eb1d6619b2c9b93bdfdd9c1b87c28101d6fc88bf7979ad52ceda459908", + "configPublicKey": "33f2107ab22b3dd5c19d5de0c5b1e6e038f2275ba455eed7997485caec421925", + "offchainPublicKey": "bb91b077c135cbdd1f4422c6021cf56d78326710c8bb8c4a87b3e7415e48915f", + "onchainSigningAddress": "b94e3de607033d03e3f0cc3ef1f09edd2592b440" + }, + "plugins": { + "mercury": true + } + } + } + ], + "connected": true, + "supportedProducts": [ + "DATA_STREAMS_V03" + ], + "categories": [ + { + "id": "11", + "name": "Keystone" + } + ] + } + ], + "createdAt": "2024-09-18T19:24:01.875231Z" + } +] diff --git a/deployment/keystone/testdata/chain_writer_nodes.json b/deployment/keystone/testdata/chain_writer_nodes.json new file mode 100644 index 00000000000..807730451ad --- /dev/null +++ b/deployment/keystone/testdata/chain_writer_nodes.json @@ -0,0 +1,1447 @@ + +[ + { + "id": "67", + "keys": [ + "keystone-09" + ], + "name": "Chainlink Keystone Node Operator 9", + "metadata": { + "nodeCount": 2, + "jobCount": 4 + }, + "nodes": [ + { + "id": "818", + "name": "Chainlink Sepolia Prod Keystone Cap One 9", + "publicKey": "3f5bbcb4b0409e6ea39d824f1837787484475fffb12e5e4a70509756ef6c7f9a", + "chainConfigs": [ + { + "network": { + "id": "140", + "chainID": "421614", + "chainType": "EVM", + "name": "Arbitrum Testnet (Sepolia)" + }, + "accountAddress": "0x9b74f08bD7269919C0597C0E00e70ef2A66829db", + "adminAddress": "0x0000000000000000000000000000000000000000", + "ocr1Config": { + "p2pKeyBundle": {}, + "ocrKeyBundle": {} + }, + "ocr2Config": { + "enabled": true, + "p2pKeyBundle": { + "peerID": "p2p_12D3KooWPG6X2RgqoSWtM3kvETV6kK4ki8FftaBkwvFWk8yKRBkz", + "publicKey": "c7bf55cf625a55470b0c56c3e51ad175c9dd0d42ca48246c205c715b7495937f" + }, + "ocrKeyBundle": { + "bundleID": "aa717effd7d28374c5980dbd9583dcff5e0800e7100051c6c8418899648dffbf", + "configPublicKey": "3fd95a3839f15adcdff573e6fbf07d06d78fbfeac5eb683f67e70226c1983c44", + "offchainPublicKey": "2b8b8d091c6f4446365f463e6132d699206bbddd38284e8e14ae0443382f297c", + "onchainSigningAddress": "b05b138a987fceffa68f79bdbb36a1faf8d3d964" + }, + "plugins": {} + } + }, + { + "network": { + "id": "10", + "chainID": "43113", + "chainType": "EVM", + "name": "Avalanche Testnet (Fuji)" + }, + "accountAddress": "0x662B6B119f7fc9Dc2A526395A9EA88AE79A1192F", + "adminAddress": "0x0000000000000000000000000000000000000000", + "ocr1Config": { + "p2pKeyBundle": {}, + "ocrKeyBundle": {} + }, + "ocr2Config": { + "enabled": true, + "p2pKeyBundle": { + "peerID": "p2p_12D3KooWPG6X2RgqoSWtM3kvETV6kK4ki8FftaBkwvFWk8yKRBkz", + "publicKey": "c7bf55cf625a55470b0c56c3e51ad175c9dd0d42ca48246c205c715b7495937f" + }, + "ocrKeyBundle": { + "bundleID": "aa717effd7d28374c5980dbd9583dcff5e0800e7100051c6c8418899648dffbf", + "configPublicKey": "3fd95a3839f15adcdff573e6fbf07d06d78fbfeac5eb683f67e70226c1983c44", + "offchainPublicKey": "2b8b8d091c6f4446365f463e6132d699206bbddd38284e8e14ae0443382f297c", + "onchainSigningAddress": "b05b138a987fceffa68f79bdbb36a1faf8d3d964" + }, + "plugins": {} + } + }, + { + "network": { + "id": "147", + "chainID": "84532", + "chainType": "EVM", + "name": "Base Testnet (Sepolia)" + }, + "accountAddress": "0x34431021e0E07c75816226697Af6Ef02725e36af", + "adminAddress": "0x0000000000000000000000000000000000000000", + "ocr1Config": { + "p2pKeyBundle": {}, + "ocrKeyBundle": {} + }, + "ocr2Config": { + "enabled": true, + "p2pKeyBundle": { + "peerID": "p2p_12D3KooWPG6X2RgqoSWtM3kvETV6kK4ki8FftaBkwvFWk8yKRBkz", + "publicKey": "c7bf55cf625a55470b0c56c3e51ad175c9dd0d42ca48246c205c715b7495937f" + }, + "ocrKeyBundle": { + "bundleID": "aa717effd7d28374c5980dbd9583dcff5e0800e7100051c6c8418899648dffbf", + "configPublicKey": "3fd95a3839f15adcdff573e6fbf07d06d78fbfeac5eb683f67e70226c1983c44", + "offchainPublicKey": "2b8b8d091c6f4446365f463e6132d699206bbddd38284e8e14ae0443382f297c", + "onchainSigningAddress": "b05b138a987fceffa68f79bdbb36a1faf8d3d964" + }, + "plugins": {} + } + }, + { + "network": { + "id": "129", + "chainID": "11155111", + "chainType": "EVM", + "name": "Ethereum Testnet (Sepolia)" + }, + "accountAddress": "0xB5988d5d9ADd3d98CF45211bE37cf9b3372054C9", + "adminAddress": "0x0000000000000000000000000000000000000000", + "ocr1Config": { + "p2pKeyBundle": {}, + "ocrKeyBundle": {} + }, + "ocr2Config": { + "enabled": true, + "p2pKeyBundle": { + "peerID": "p2p_12D3KooWPG6X2RgqoSWtM3kvETV6kK4ki8FftaBkwvFWk8yKRBkz", + "publicKey": "c7bf55cf625a55470b0c56c3e51ad175c9dd0d42ca48246c205c715b7495937f" + }, + "ocrKeyBundle": { + "bundleID": "aa717effd7d28374c5980dbd9583dcff5e0800e7100051c6c8418899648dffbf", + "configPublicKey": "3fd95a3839f15adcdff573e6fbf07d06d78fbfeac5eb683f67e70226c1983c44", + "offchainPublicKey": "2b8b8d091c6f4446365f463e6132d699206bbddd38284e8e14ae0443382f297c", + "onchainSigningAddress": "b05b138a987fceffa68f79bdbb36a1faf8d3d964" + }, + "plugins": {} + } + } + ], + "connected": true, + "supportedProducts": [ + "OCR3_CAPABILITY", + "DATA_STREAMS_V03" + ], + "categories": [ + { + "id": "11", + "name": "Keystone" + } + ] + } + ], + "createdAt": "2024-08-14T19:00:07.113658Z" + }, + { + "id": "68", + "keys": [ + "keystone-08" + ], + "name": "Chainlink Keystone Node Operator 8", + "metadata": { + "nodeCount": 2, + "jobCount": 4 + }, + "nodes": [ + { + "id": "817", + "name": "Chainlink Sepolia Prod Keystone Cap One 8", + "publicKey": "2346da196a82c88fe6c315d2e4d0dddacf4590a172b20adb6f27a8601ca0540d", + "chainConfigs": [ + { + "network": { + "id": "140", + "chainID": "421614", + "chainType": "EVM", + "name": "Arbitrum Testnet (Sepolia)" + }, + "accountAddress": "0xa5C7133aBD35F9d742bD2997D693A507c5eBf4Ac", + "adminAddress": "0x0000000000000000000000000000000000000000", + "ocr1Config": { + "p2pKeyBundle": {}, + "ocrKeyBundle": {} + }, + "ocr2Config": { + "enabled": true, + "p2pKeyBundle": { + "peerID": "p2p_12D3KooWNfg9cYxEri1zGbdCZ87DekmruYY6J1wUobEwNNVewMpT", + "publicKey": "beee088bccea272eb6473fcc1cd3e22f2fc8d3a253a6398b69f5aab94070e690" + }, + "ocrKeyBundle": { + "bundleID": "9fba2d29874bb06b07272bd9141f096c1987d790bb0f81c3ffaf66d11cdac4f2", + "configPublicKey": "66dec87065de79e64ed4edd2478ec40a66f955af56e7b837729f464f8487d713", + "offchainPublicKey": "a0f59d50078c77812da8d3077f552209adfb58e76b635e008b6b0f872ce52139", + "onchainSigningAddress": "ed25406f1ef2e1381f6e1e04341f1a6e8b4eacea" + }, + "plugins": {} + } + }, + { + "network": { + "id": "10", + "chainID": "43113", + "chainType": "EVM", + "name": "Avalanche Testnet (Fuji)" + }, + "accountAddress": "0x9fd869f5baADb79F9b7C58c0855fcAc0384e1d4B", + "adminAddress": "0x0000000000000000000000000000000000000000", + "ocr1Config": { + "p2pKeyBundle": {}, + "ocrKeyBundle": {} + }, + "ocr2Config": { + "enabled": true, + "p2pKeyBundle": { + "peerID": "p2p_12D3KooWNfg9cYxEri1zGbdCZ87DekmruYY6J1wUobEwNNVewMpT", + "publicKey": "beee088bccea272eb6473fcc1cd3e22f2fc8d3a253a6398b69f5aab94070e690" + }, + "ocrKeyBundle": { + "bundleID": "9fba2d29874bb06b07272bd9141f096c1987d790bb0f81c3ffaf66d11cdac4f2", + "configPublicKey": "66dec87065de79e64ed4edd2478ec40a66f955af56e7b837729f464f8487d713", + "offchainPublicKey": "a0f59d50078c77812da8d3077f552209adfb58e76b635e008b6b0f872ce52139", + "onchainSigningAddress": "ed25406f1ef2e1381f6e1e04341f1a6e8b4eacea" + }, + "plugins": {} + } + }, + { + "network": { + "id": "147", + "chainID": "84532", + "chainType": "EVM", + "name": "Base Testnet (Sepolia)" + }, + "accountAddress": "0xe477E4C2e335E9b839665d710dE77CFECa9C43A7", + "adminAddress": "0x0000000000000000000000000000000000000000", + "ocr1Config": { + "p2pKeyBundle": {}, + "ocrKeyBundle": {} + }, + "ocr2Config": { + "enabled": true, + "p2pKeyBundle": { + "peerID": "p2p_12D3KooWNfg9cYxEri1zGbdCZ87DekmruYY6J1wUobEwNNVewMpT", + "publicKey": "beee088bccea272eb6473fcc1cd3e22f2fc8d3a253a6398b69f5aab94070e690" + }, + "ocrKeyBundle": { + "bundleID": "9fba2d29874bb06b07272bd9141f096c1987d790bb0f81c3ffaf66d11cdac4f2", + "configPublicKey": "66dec87065de79e64ed4edd2478ec40a66f955af56e7b837729f464f8487d713", + "offchainPublicKey": "a0f59d50078c77812da8d3077f552209adfb58e76b635e008b6b0f872ce52139", + "onchainSigningAddress": "ed25406f1ef2e1381f6e1e04341f1a6e8b4eacea" + }, + "plugins": {} + } + }, + { + "network": { + "id": "129", + "chainID": "11155111", + "chainType": "EVM", + "name": "Ethereum Testnet (Sepolia)" + }, + "accountAddress": "0x056A1275DD670205aba10D8fC9bB597777a65030", + "adminAddress": "0x0000000000000000000000000000000000000000", + "ocr1Config": { + "p2pKeyBundle": {}, + "ocrKeyBundle": {} + }, + "ocr2Config": { + "enabled": true, + "p2pKeyBundle": { + "peerID": "p2p_12D3KooWNfg9cYxEri1zGbdCZ87DekmruYY6J1wUobEwNNVewMpT", + "publicKey": "beee088bccea272eb6473fcc1cd3e22f2fc8d3a253a6398b69f5aab94070e690" + }, + "ocrKeyBundle": { + "bundleID": "9fba2d29874bb06b07272bd9141f096c1987d790bb0f81c3ffaf66d11cdac4f2", + "configPublicKey": "66dec87065de79e64ed4edd2478ec40a66f955af56e7b837729f464f8487d713", + "offchainPublicKey": "a0f59d50078c77812da8d3077f552209adfb58e76b635e008b6b0f872ce52139", + "onchainSigningAddress": "ed25406f1ef2e1381f6e1e04341f1a6e8b4eacea" + }, + "plugins": {} + } + } + ], + "connected": true, + "supportedProducts": [ + "OCR3_CAPABILITY", + "DATA_STREAMS_V03" + ], + "categories": [ + { + "id": "11", + "name": "Keystone" + } + ] + } + ], + "createdAt": "2024-08-14T20:26:37.622463Z" + }, + { + "id": "69", + "keys": [ + "keystone-07" + ], + "name": "Chainlink Keystone Node Operator 7", + "metadata": { + "nodeCount": 2, + "jobCount": 4 + }, + "nodes": [ + { + "id": "816", + "name": "Chainlink Sepolia Prod Keystone Cap One 7", + "publicKey": "50d4e3393516d1998e5c39874d7c0da2291e4e3727f8baac4380e9f5573cc648", + "chainConfigs": [ + { + "network": { + "id": "140", + "chainID": "421614", + "chainType": "EVM", + "name": "Arbitrum Testnet (Sepolia)" + }, + "accountAddress": "0x0ba7c1096B701A862bBCe7F13E9D33eED7e33c1D", + "adminAddress": "0x0000000000000000000000000000000000000000", + "ocr1Config": { + "p2pKeyBundle": {}, + "ocrKeyBundle": {} + }, + "ocr2Config": { + "enabled": true, + "p2pKeyBundle": { + "peerID": "p2p_12D3KooWQswQr8fxJG5ieMrayptGV4rvCjDWPCFtfkqm4L6NZbbb", + "publicKey": "dfc9a26dc022bd244c13d62ca88bbe62ca996065bd23224e1f1b77128914d84e" + }, + "ocrKeyBundle": { + "bundleID": "d4566a0c2f256e59733ad2a6dff9f388a1e00b2e65ec1cff7590cb59028888cd", + "configPublicKey": "58db0da621471e616615b8c1c1658ee3b7afbfa64662ce28b38272a95964052c", + "offchainPublicKey": "262fee9de8dd0c8758ba78de8873fdb6705c45ce331bc16ac81dc5b5f0b9680f", + "onchainSigningAddress": "516a9990d3a202b25c2cdd2f6316f4d066543e5d" + }, + "plugins": {} + } + }, + { + "network": { + "id": "10", + "chainID": "43113", + "chainType": "EVM", + "name": "Avalanche Testnet (Fuji)" + }, + "accountAddress": "0xcC44eD47023Bd88B82092A708c38609e8Fc2D197", + "adminAddress": "0x0000000000000000000000000000000000000000", + "ocr1Config": { + "p2pKeyBundle": {}, + "ocrKeyBundle": {} + }, + "ocr2Config": { + "enabled": true, + "p2pKeyBundle": { + "peerID": "p2p_12D3KooWQswQr8fxJG5ieMrayptGV4rvCjDWPCFtfkqm4L6NZbbb", + "publicKey": "dfc9a26dc022bd244c13d62ca88bbe62ca996065bd23224e1f1b77128914d84e" + }, + "ocrKeyBundle": { + "bundleID": "d4566a0c2f256e59733ad2a6dff9f388a1e00b2e65ec1cff7590cb59028888cd", + "configPublicKey": "58db0da621471e616615b8c1c1658ee3b7afbfa64662ce28b38272a95964052c", + "offchainPublicKey": "262fee9de8dd0c8758ba78de8873fdb6705c45ce331bc16ac81dc5b5f0b9680f", + "onchainSigningAddress": "516a9990d3a202b25c2cdd2f6316f4d066543e5d" + }, + "plugins": {} + } + }, + { + "network": { + "id": "147", + "chainID": "84532", + "chainType": "EVM", + "name": "Base Testnet (Sepolia)" + }, + "accountAddress": "0x0E8F4E699cd331022FaA2Ad75E500e70303C8767", + "adminAddress": "0x0000000000000000000000000000000000000000", + "ocr1Config": { + "p2pKeyBundle": {}, + "ocrKeyBundle": {} + }, + "ocr2Config": { + "enabled": true, + "p2pKeyBundle": { + "peerID": "p2p_12D3KooWQswQr8fxJG5ieMrayptGV4rvCjDWPCFtfkqm4L6NZbbb", + "publicKey": "dfc9a26dc022bd244c13d62ca88bbe62ca996065bd23224e1f1b77128914d84e" + }, + "ocrKeyBundle": { + "bundleID": "d4566a0c2f256e59733ad2a6dff9f388a1e00b2e65ec1cff7590cb59028888cd", + "configPublicKey": "58db0da621471e616615b8c1c1658ee3b7afbfa64662ce28b38272a95964052c", + "offchainPublicKey": "262fee9de8dd0c8758ba78de8873fdb6705c45ce331bc16ac81dc5b5f0b9680f", + "onchainSigningAddress": "516a9990d3a202b25c2cdd2f6316f4d066543e5d" + }, + "plugins": {} + } + }, + { + "network": { + "id": "129", + "chainID": "11155111", + "chainType": "EVM", + "name": "Ethereum Testnet (Sepolia)" + }, + "accountAddress": "0x49c36b3BEc6b6e0e77305273FAFC68f479630535", + "adminAddress": "0x0000000000000000000000000000000000000000", + "ocr1Config": { + "p2pKeyBundle": {}, + "ocrKeyBundle": {} + }, + "ocr2Config": { + "enabled": true, + "p2pKeyBundle": { + "peerID": "p2p_12D3KooWQswQr8fxJG5ieMrayptGV4rvCjDWPCFtfkqm4L6NZbbb", + "publicKey": "dfc9a26dc022bd244c13d62ca88bbe62ca996065bd23224e1f1b77128914d84e" + }, + "ocrKeyBundle": { + "bundleID": "d4566a0c2f256e59733ad2a6dff9f388a1e00b2e65ec1cff7590cb59028888cd", + "configPublicKey": "58db0da621471e616615b8c1c1658ee3b7afbfa64662ce28b38272a95964052c", + "offchainPublicKey": "262fee9de8dd0c8758ba78de8873fdb6705c45ce331bc16ac81dc5b5f0b9680f", + "onchainSigningAddress": "516a9990d3a202b25c2cdd2f6316f4d066543e5d" + }, + "plugins": {} + } + } + ], + "connected": true, + "supportedProducts": [ + "OCR3_CAPABILITY", + "DATA_STREAMS_V03" + ], + "categories": [ + { + "id": "11", + "name": "Keystone" + } + ] + } + ], + "createdAt": "2024-08-14T20:30:51.07624Z" + }, + { + "id": "70", + "keys": [ + "keystone-06" + ], + "name": "Chainlink Keystone Node Operator 6", + "metadata": { + "nodeCount": 2, + "jobCount": 4 + }, + "nodes": [ + { + "id": "815", + "name": "Chainlink Sepolia Prod Keystone Cap One 6", + "publicKey": "2669981add3071fae5dfd760fe97e7d2b90157f86b40227f306f1f3906099fc3", + "chainConfigs": [ + { + "network": { + "id": "140", + "chainID": "421614", + "chainType": "EVM", + "name": "Arbitrum Testnet (Sepolia)" + }, + "accountAddress": "0x405eE4ad3E79786f899810ff6de16a83A920Db5D", + "adminAddress": "0x0000000000000000000000000000000000000000", + "ocr1Config": { + "p2pKeyBundle": {}, + "ocrKeyBundle": {} + }, + "ocr2Config": { + "enabled": true, + "p2pKeyBundle": { + "peerID": "p2p_12D3KooWHB1ucYgRqrocS6t834wL5XaB11JSPgKwzB6QwRPzRayu", + "publicKey": "6d4c18afa813bf7eec73e98a260294bce4b0b26eb9f6efceb2c9402eead56c98" + }, + "ocrKeyBundle": { + "bundleID": "d55283594d4e2c3e507f81ea9ad96261ebec1b1e8579bb1392ca22f7dc9b471b", + "configPublicKey": "32d5b6d38147fa23ec1dc4eeb240e2e70ea768b9a5182676075acd5a2ab2794c", + "offchainPublicKey": "9922cb5c0ae08f0b917979593824bde7ddad0935950e2835914acc34f6cd62f3", + "onchainSigningAddress": "bca900017893ea1366c110941d698d078c2b93ca" + }, + "plugins": {} + } + }, + { + "network": { + "id": "10", + "chainID": "43113", + "chainType": "EVM", + "name": "Avalanche Testnet (Fuji)" + }, + "accountAddress": "0x58D39d629ae9f904b0Ae509179b9e7c9B0184cee", + "adminAddress": "0x0000000000000000000000000000000000000000", + "ocr1Config": { + "p2pKeyBundle": {}, + "ocrKeyBundle": {} + }, + "ocr2Config": { + "enabled": true, + "p2pKeyBundle": { + "peerID": "p2p_12D3KooWHB1ucYgRqrocS6t834wL5XaB11JSPgKwzB6QwRPzRayu", + "publicKey": "6d4c18afa813bf7eec73e98a260294bce4b0b26eb9f6efceb2c9402eead56c98" + }, + "ocrKeyBundle": { + "bundleID": "d55283594d4e2c3e507f81ea9ad96261ebec1b1e8579bb1392ca22f7dc9b471b", + "configPublicKey": "32d5b6d38147fa23ec1dc4eeb240e2e70ea768b9a5182676075acd5a2ab2794c", + "offchainPublicKey": "9922cb5c0ae08f0b917979593824bde7ddad0935950e2835914acc34f6cd62f3", + "onchainSigningAddress": "bca900017893ea1366c110941d698d078c2b93ca" + }, + "plugins": {} + } + }, + { + "network": { + "id": "147", + "chainID": "84532", + "chainType": "EVM", + "name": "Base Testnet (Sepolia)" + }, + "accountAddress": "0x34bFe10F4f4e1101b019639ABd5E5eE5186B80E6", + "adminAddress": "0x0000000000000000000000000000000000000000", + "ocr1Config": { + "p2pKeyBundle": {}, + "ocrKeyBundle": {} + }, + "ocr2Config": { + "enabled": true, + "p2pKeyBundle": { + "peerID": "p2p_12D3KooWHB1ucYgRqrocS6t834wL5XaB11JSPgKwzB6QwRPzRayu", + "publicKey": "6d4c18afa813bf7eec73e98a260294bce4b0b26eb9f6efceb2c9402eead56c98" + }, + "ocrKeyBundle": { + "bundleID": "d55283594d4e2c3e507f81ea9ad96261ebec1b1e8579bb1392ca22f7dc9b471b", + "configPublicKey": "32d5b6d38147fa23ec1dc4eeb240e2e70ea768b9a5182676075acd5a2ab2794c", + "offchainPublicKey": "9922cb5c0ae08f0b917979593824bde7ddad0935950e2835914acc34f6cd62f3", + "onchainSigningAddress": "bca900017893ea1366c110941d698d078c2b93ca" + }, + "plugins": {} + } + }, + { + "network": { + "id": "129", + "chainID": "11155111", + "chainType": "EVM", + "name": "Ethereum Testnet (Sepolia)" + }, + "accountAddress": "0x1741EB7468A490b4A9BA6f4CC7A47B82EcD65c4c", + "adminAddress": "0x0000000000000000000000000000000000000000", + "ocr1Config": { + "p2pKeyBundle": {}, + "ocrKeyBundle": {} + }, + "ocr2Config": { + "enabled": true, + "p2pKeyBundle": { + "peerID": "p2p_12D3KooWHB1ucYgRqrocS6t834wL5XaB11JSPgKwzB6QwRPzRayu", + "publicKey": "6d4c18afa813bf7eec73e98a260294bce4b0b26eb9f6efceb2c9402eead56c98" + }, + "ocrKeyBundle": { + "bundleID": "d55283594d4e2c3e507f81ea9ad96261ebec1b1e8579bb1392ca22f7dc9b471b", + "configPublicKey": "32d5b6d38147fa23ec1dc4eeb240e2e70ea768b9a5182676075acd5a2ab2794c", + "offchainPublicKey": "9922cb5c0ae08f0b917979593824bde7ddad0935950e2835914acc34f6cd62f3", + "onchainSigningAddress": "bca900017893ea1366c110941d698d078c2b93ca" + }, + "plugins": {} + } + } + ], + "connected": true, + "supportedProducts": [ + "OCR3_CAPABILITY", + "DATA_STREAMS_V03" + ], + "categories": [ + { + "id": "11", + "name": "Keystone" + } + ] + } + ], + "createdAt": "2024-08-14T20:32:14.024795Z" + }, + { + "id": "71", + "keys": [ + "keystone-05" + ], + "name": "Chainlink Keystone Node Operator 5", + "metadata": { + "nodeCount": 2, + "jobCount": 4 + }, + "nodes": [ + { + "id": "814", + "name": "Chainlink Sepolia Prod Keystone Cap One 5", + "publicKey": "94e9ee398547f1564b8b5f72c6148e511919ed0e59b94ae848d63685108f2ab4", + "chainConfigs": [ + { + "network": { + "id": "140", + "chainID": "421614", + "chainType": "EVM", + "name": "Arbitrum Testnet (Sepolia)" + }, + "accountAddress": "0xbd1ee3165178D3A3E38458a9Fb1d6BF7fb5C443e", + "adminAddress": "0x0000000000000000000000000000000000000000", + "ocr1Config": { + "p2pKeyBundle": {}, + "ocrKeyBundle": {} + }, + "ocr2Config": { + "enabled": true, + "p2pKeyBundle": { + "peerID": "p2p_12D3KooWCiwWc97Q3Z9YUGZcAf46TMLg1uMvrEDa4gT6HZUFFCB1", + "publicKey": "2b2f46bf3b7ab2f39a7fec18166a6ebbc0a72209e920c33933f9adf07b101cc0" + }, + "ocrKeyBundle": { + "bundleID": "bf1736a09452daa0923f2c680f3fa6362ae652294e80ce72d923b304b0dcbb13", + "configPublicKey": "4ebd2a563c458485d2698d06142daa37ea2bee706b4a1a71c8435f2ec254506a", + "offchainPublicKey": "8577b96b270b36e74eb5d411caa14353cdadea599d6d6aa9cccf534ce31f1ef5", + "onchainSigningAddress": "b6727a31772b71d15e3120bfd618545292e1f9df" + }, + "plugins": {} + } + }, + { + "network": { + "id": "10", + "chainID": "43113", + "chainType": "EVM", + "name": "Avalanche Testnet (Fuji)" + }, + "accountAddress": "0x9b6284B5775E46fB02C1a589596EF07c35b55377", + "adminAddress": "0x0000000000000000000000000000000000000000", + "ocr1Config": { + "p2pKeyBundle": {}, + "ocrKeyBundle": {} + }, + "ocr2Config": { + "enabled": true, + "p2pKeyBundle": { + "peerID": "p2p_12D3KooWCiwWc97Q3Z9YUGZcAf46TMLg1uMvrEDa4gT6HZUFFCB1", + "publicKey": "2b2f46bf3b7ab2f39a7fec18166a6ebbc0a72209e920c33933f9adf07b101cc0" + }, + "ocrKeyBundle": { + "bundleID": "bf1736a09452daa0923f2c680f3fa6362ae652294e80ce72d923b304b0dcbb13", + "configPublicKey": "4ebd2a563c458485d2698d06142daa37ea2bee706b4a1a71c8435f2ec254506a", + "offchainPublicKey": "8577b96b270b36e74eb5d411caa14353cdadea599d6d6aa9cccf534ce31f1ef5", + "onchainSigningAddress": "b6727a31772b71d15e3120bfd618545292e1f9df" + }, + "plugins": {} + } + }, + { + "network": { + "id": "147", + "chainID": "84532", + "chainType": "EVM", + "name": "Base Testnet (Sepolia)" + }, + "accountAddress": "0xD83DCED517E4df64e913B97b3d0A906e4CA63d43", + "adminAddress": "0x0000000000000000000000000000000000000000", + "ocr1Config": { + "p2pKeyBundle": {}, + "ocrKeyBundle": {} + }, + "ocr2Config": { + "enabled": true, + "p2pKeyBundle": { + "peerID": "p2p_12D3KooWCiwWc97Q3Z9YUGZcAf46TMLg1uMvrEDa4gT6HZUFFCB1", + "publicKey": "2b2f46bf3b7ab2f39a7fec18166a6ebbc0a72209e920c33933f9adf07b101cc0" + }, + "ocrKeyBundle": { + "bundleID": "bf1736a09452daa0923f2c680f3fa6362ae652294e80ce72d923b304b0dcbb13", + "configPublicKey": "4ebd2a563c458485d2698d06142daa37ea2bee706b4a1a71c8435f2ec254506a", + "offchainPublicKey": "8577b96b270b36e74eb5d411caa14353cdadea599d6d6aa9cccf534ce31f1ef5", + "onchainSigningAddress": "b6727a31772b71d15e3120bfd618545292e1f9df" + }, + "plugins": {} + } + }, + { + "network": { + "id": "129", + "chainID": "11155111", + "chainType": "EVM", + "name": "Ethereum Testnet (Sepolia)" + }, + "accountAddress": "0xFF1218066b4b5Cd9dE2A73639862082bcC98bf0D", + "adminAddress": "0x0000000000000000000000000000000000000000", + "ocr1Config": { + "p2pKeyBundle": {}, + "ocrKeyBundle": {} + }, + "ocr2Config": { + "enabled": true, + "p2pKeyBundle": { + "peerID": "p2p_12D3KooWCiwWc97Q3Z9YUGZcAf46TMLg1uMvrEDa4gT6HZUFFCB1", + "publicKey": "2b2f46bf3b7ab2f39a7fec18166a6ebbc0a72209e920c33933f9adf07b101cc0" + }, + "ocrKeyBundle": { + "bundleID": "bf1736a09452daa0923f2c680f3fa6362ae652294e80ce72d923b304b0dcbb13", + "configPublicKey": "4ebd2a563c458485d2698d06142daa37ea2bee706b4a1a71c8435f2ec254506a", + "offchainPublicKey": "8577b96b270b36e74eb5d411caa14353cdadea599d6d6aa9cccf534ce31f1ef5", + "onchainSigningAddress": "b6727a31772b71d15e3120bfd618545292e1f9df" + }, + "plugins": {} + } + } + ], + "connected": true, + "supportedProducts": [ + "OCR3_CAPABILITY", + "DATA_STREAMS_V03" + ], + "categories": [ + { + "id": "11", + "name": "Keystone" + } + ] + } + ], + "createdAt": "2024-08-14T20:38:35.588611Z" + }, + { + "id": "72", + "keys": [ + "keystone-04" + ], + "name": "Chainlink Keystone Node Operator 4", + "metadata": { + "nodeCount": 2, + "jobCount": 4 + }, + "nodes": [ + { + "id": "813", + "name": "Chainlink Sepolia Prod Keystone Cap One 4", + "publicKey": "a618fe2d3260151957d105d2dd593dddaad20c45dc6ae8eab265504e6585a02c", + "chainConfigs": [ + { + "network": { + "id": "140", + "chainID": "421614", + "chainType": "EVM", + "name": "Arbitrum Testnet (Sepolia)" + }, + "accountAddress": "0xE73E4D047DA32De40C7008075aEb9F60C8AF3C90", + "adminAddress": "0x0000000000000000000000000000000000000000", + "ocr1Config": { + "p2pKeyBundle": {}, + "ocrKeyBundle": {} + }, + "ocr2Config": { + "enabled": true, + "p2pKeyBundle": { + "peerID": "p2p_12D3KooWPMfQRpMy3wYzSMe3BLS8GFuC3fauk7FhTtgfbtp6T6jT", + "publicKey": "c92c6c81f3dff17c05577b9f87177d735d797a3ceedc0fa1395682dfbb66a8d2" + }, + "ocrKeyBundle": { + "bundleID": "fbcfd8420c2ebc450c81fcf72c6673fdd786702c881467e69817c20350bf819b", + "configPublicKey": "282a47a24fd976134f25a99f6370e072f228098010d2594d849d0a4c2788f878", + "offchainPublicKey": "1a7902a01e27818cda034637fdce603a265bc380934324b6f48cf23873234ec6", + "onchainSigningAddress": "7e799378dda3dcdc503233735f09150f0684be19" + }, + "plugins": {} + } + }, + { + "network": { + "id": "10", + "chainID": "43113", + "chainType": "EVM", + "name": "Avalanche Testnet (Fuji)" + }, + "accountAddress": "0x7501ff3462fd2133f2E1F93DB7Ec514988B43E56", + "adminAddress": "0x0000000000000000000000000000000000000000", + "ocr1Config": { + "p2pKeyBundle": {}, + "ocrKeyBundle": {} + }, + "ocr2Config": { + "enabled": true, + "p2pKeyBundle": { + "peerID": "p2p_12D3KooWPMfQRpMy3wYzSMe3BLS8GFuC3fauk7FhTtgfbtp6T6jT", + "publicKey": "c92c6c81f3dff17c05577b9f87177d735d797a3ceedc0fa1395682dfbb66a8d2" + }, + "ocrKeyBundle": { + "bundleID": "fbcfd8420c2ebc450c81fcf72c6673fdd786702c881467e69817c20350bf819b", + "configPublicKey": "282a47a24fd976134f25a99f6370e072f228098010d2594d849d0a4c2788f878", + "offchainPublicKey": "1a7902a01e27818cda034637fdce603a265bc380934324b6f48cf23873234ec6", + "onchainSigningAddress": "7e799378dda3dcdc503233735f09150f0684be19" + }, + "plugins": {} + } + }, + { + "network": { + "id": "147", + "chainID": "84532", + "chainType": "EVM", + "name": "Base Testnet (Sepolia)" + }, + "accountAddress": "0xef080765890a3F697C4920609621fe301Dd34A70", + "adminAddress": "0x0000000000000000000000000000000000000000", + "ocr1Config": { + "p2pKeyBundle": {}, + "ocrKeyBundle": {} + }, + "ocr2Config": { + "enabled": true, + "p2pKeyBundle": { + "peerID": "p2p_12D3KooWPMfQRpMy3wYzSMe3BLS8GFuC3fauk7FhTtgfbtp6T6jT", + "publicKey": "c92c6c81f3dff17c05577b9f87177d735d797a3ceedc0fa1395682dfbb66a8d2" + }, + "ocrKeyBundle": { + "bundleID": "fbcfd8420c2ebc450c81fcf72c6673fdd786702c881467e69817c20350bf819b", + "configPublicKey": "282a47a24fd976134f25a99f6370e072f228098010d2594d849d0a4c2788f878", + "offchainPublicKey": "1a7902a01e27818cda034637fdce603a265bc380934324b6f48cf23873234ec6", + "onchainSigningAddress": "7e799378dda3dcdc503233735f09150f0684be19" + }, + "plugins": {} + } + }, + { + "network": { + "id": "129", + "chainID": "11155111", + "chainType": "EVM", + "name": "Ethereum Testnet (Sepolia)" + }, + "accountAddress": "0x860235D5Db42eF568665900BBD6bA3DB2fA4f33f", + "adminAddress": "0x0000000000000000000000000000000000000000", + "ocr1Config": { + "p2pKeyBundle": {}, + "ocrKeyBundle": {} + }, + "ocr2Config": { + "enabled": true, + "p2pKeyBundle": { + "peerID": "p2p_12D3KooWPMfQRpMy3wYzSMe3BLS8GFuC3fauk7FhTtgfbtp6T6jT", + "publicKey": "c92c6c81f3dff17c05577b9f87177d735d797a3ceedc0fa1395682dfbb66a8d2" + }, + "ocrKeyBundle": { + "bundleID": "fbcfd8420c2ebc450c81fcf72c6673fdd786702c881467e69817c20350bf819b", + "configPublicKey": "282a47a24fd976134f25a99f6370e072f228098010d2594d849d0a4c2788f878", + "offchainPublicKey": "1a7902a01e27818cda034637fdce603a265bc380934324b6f48cf23873234ec6", + "onchainSigningAddress": "7e799378dda3dcdc503233735f09150f0684be19" + }, + "plugins": {} + } + } + ], + "connected": true, + "supportedProducts": [ + "OCR3_CAPABILITY", + "DATA_STREAMS_V03" + ], + "categories": [ + { + "id": "11", + "name": "Keystone" + } + ] + } + ], + "createdAt": "2024-08-14T20:39:26.24249Z" + }, + { + "id": "73", + "keys": [ + "keystone-03", + "keystone-bt-03" + ], + "name": "Chainlink Keystone Node Operator 3", + "metadata": { + "nodeCount": 3, + "jobCount": 5 + }, + "nodes": [ + { + "id": "812", + "name": "Chainlink Sepolia Prod Keystone Cap One 3", + "publicKey": "f4cf97438c3ad86003e5c0368ab52c70f7fbb7f39ae0d7bf6dacbe16807e8a36", + "chainConfigs": [ + { + "network": { + "id": "147", + "chainID": "84532", + "chainType": "EVM", + "name": "Base Testnet (Sepolia)" + }, + "accountAddress": "0x646665317aF70313B3E83Ea1369A91de389DaCAe", + "adminAddress": "0x0000000000000000000000000000000000000000", + "ocr1Config": { + "p2pKeyBundle": {}, + "ocrKeyBundle": {} + }, + "ocr2Config": { + "enabled": true, + "p2pKeyBundle": { + "peerID": "p2p_12D3KooWAvLkcnc8Zttykk6gGeTWFiT6TqgovRHnb6Ym6QqjnLVM", + "publicKey": "1063921b717c3e32210d2803fe684cd818ea2a4a96e405373e5786c8a13c7600" + }, + "ocrKeyBundle": { + "bundleID": "5b46ab201ba66bd93bae6f41afc59c2e578e0f5682fbdf76e1b647fde6d6e8dd", + "configPublicKey": "a01d7d13f3e67ff84ff208cc44c923fe245d02d6029c91dc38422ef44f2bb26e", + "offchainPublicKey": "64eded06a47efc5e311799c1e1fa833cf78d17f079b2f6019c3247debe490439", + "onchainSigningAddress": "afca74e3b850a9435b2dc479ca8bc8e1b45dd0b2" + }, + "plugins": {} + } + }, + { + "network": { + "id": "10", + "chainID": "43113", + "chainType": "EVM", + "name": "Avalanche Testnet (Fuji)" + }, + "accountAddress": "0x3Ab2A4e4765A0374F727a9a9eCE893734e2928ec", + "adminAddress": "0x0000000000000000000000000000000000000000", + "ocr1Config": { + "p2pKeyBundle": {}, + "ocrKeyBundle": {} + }, + "ocr2Config": { + "enabled": true, + "p2pKeyBundle": { + "peerID": "p2p_12D3KooWAvLkcnc8Zttykk6gGeTWFiT6TqgovRHnb6Ym6QqjnLVM", + "publicKey": "1063921b717c3e32210d2803fe684cd818ea2a4a96e405373e5786c8a13c7600" + }, + "ocrKeyBundle": { + "bundleID": "5b46ab201ba66bd93bae6f41afc59c2e578e0f5682fbdf76e1b647fde6d6e8dd", + "configPublicKey": "a01d7d13f3e67ff84ff208cc44c923fe245d02d6029c91dc38422ef44f2bb26e", + "offchainPublicKey": "64eded06a47efc5e311799c1e1fa833cf78d17f079b2f6019c3247debe490439", + "onchainSigningAddress": "afca74e3b850a9435b2dc479ca8bc8e1b45dd0b2" + }, + "plugins": {} + } + }, + { + "network": { + "id": "129", + "chainID": "11155111", + "chainType": "EVM", + "name": "Ethereum Testnet (Sepolia)" + }, + "accountAddress": "0x9905E8C3A4f82037170a8c411CD8b11D4894066f", + "adminAddress": "0x0000000000000000000000000000000000000000", + "ocr1Config": { + "p2pKeyBundle": {}, + "ocrKeyBundle": {} + }, + "ocr2Config": { + "enabled": true, + "p2pKeyBundle": { + "peerID": "p2p_12D3KooWAvLkcnc8Zttykk6gGeTWFiT6TqgovRHnb6Ym6QqjnLVM", + "publicKey": "1063921b717c3e32210d2803fe684cd818ea2a4a96e405373e5786c8a13c7600" + }, + "ocrKeyBundle": { + "bundleID": "5b46ab201ba66bd93bae6f41afc59c2e578e0f5682fbdf76e1b647fde6d6e8dd", + "configPublicKey": "a01d7d13f3e67ff84ff208cc44c923fe245d02d6029c91dc38422ef44f2bb26e", + "offchainPublicKey": "64eded06a47efc5e311799c1e1fa833cf78d17f079b2f6019c3247debe490439", + "onchainSigningAddress": "afca74e3b850a9435b2dc479ca8bc8e1b45dd0b2" + }, + "plugins": {} + } + }, + { + "network": { + "id": "140", + "chainID": "421614", + "chainType": "EVM", + "name": "Arbitrum Testnet (Sepolia)" + }, + "accountAddress": "0x762354eC86ea2253F5da27FF8b952Cb7Dec52B6D", + "adminAddress": "0x0000000000000000000000000000000000000000", + "ocr1Config": { + "p2pKeyBundle": {}, + "ocrKeyBundle": {} + }, + "ocr2Config": { + "enabled": true, + "p2pKeyBundle": { + "peerID": "p2p_12D3KooWAvLkcnc8Zttykk6gGeTWFiT6TqgovRHnb6Ym6QqjnLVM", + "publicKey": "1063921b717c3e32210d2803fe684cd818ea2a4a96e405373e5786c8a13c7600" + }, + "ocrKeyBundle": { + "bundleID": "5b46ab201ba66bd93bae6f41afc59c2e578e0f5682fbdf76e1b647fde6d6e8dd", + "configPublicKey": "a01d7d13f3e67ff84ff208cc44c923fe245d02d6029c91dc38422ef44f2bb26e", + "offchainPublicKey": "64eded06a47efc5e311799c1e1fa833cf78d17f079b2f6019c3247debe490439", + "onchainSigningAddress": "afca74e3b850a9435b2dc479ca8bc8e1b45dd0b2" + }, + "plugins": {} + } + } + ], + "connected": true, + "supportedProducts": [ + "OCR3_CAPABILITY", + "DATA_STREAMS_V03" + ], + "categories": [ + { + "id": "11", + "name": "Keystone" + } + ] + } + ], + "createdAt": "2024-08-14T20:40:30.499914Z" + }, + { + "id": "74", + "keys": [ + "keystone-02", + "keystone-bt-02" + ], + "name": "Chainlink Keystone Node Operator 2", + "metadata": { + "nodeCount": 3, + "jobCount": 5 + }, + "nodes": [ + { + "id": "811", + "name": "Chainlink Sepolia Prod Keystone Cap One 2", + "publicKey": "a1f112923513f13ede1ca8f982ea0ab6221d584b40cd57f0c82307ab79c0e69f", + "chainConfigs": [ + { + "network": { + "id": "10", + "chainID": "43113", + "chainType": "EVM", + "name": "Avalanche Testnet (Fuji)" + }, + "accountAddress": "0xbF1Ad47D99A65e230235537b47C8D1Dddb22FD53", + "adminAddress": "0x0000000000000000000000000000000000000000", + "ocr1Config": { + "p2pKeyBundle": {}, + "ocrKeyBundle": {} + }, + "ocr2Config": { + "enabled": true, + "p2pKeyBundle": { + "peerID": "p2p_12D3KooWQhLYuAxx4WDKafnuhZUTix8Y24gtB92vEUpAC4EdH4VA", + "publicKey": "dd1268a3e7ed4b9c83b1227e5bf2558e6b77af585c66e88a06f1164a1a94f8ed" + }, + "ocrKeyBundle": { + "bundleID": "a11d9438035564bfe84fcfb513b579edbe173fa26c00331e71a010d00b856037", + "configPublicKey": "407cab2a04fa868f645c6848a53abdb8136b08441c50b191651c4f1a348ee700", + "offchainPublicKey": "64a3215839e5630f12ae66b4363f40d82e9c981118c304ca0c4ca5fc2c6e1f37", + "onchainSigningAddress": "6579d77791ee8f8116495dbe6fa6586980177230" + }, + "plugins": {} + } + }, + { + "network": { + "id": "147", + "chainID": "84532", + "chainType": "EVM", + "name": "Base Testnet (Sepolia)" + }, + "accountAddress": "0xa8d4698f74a0A427c1b8ec4575d9dFdD17Be288c", + "adminAddress": "0x0000000000000000000000000000000000000000", + "ocr1Config": { + "p2pKeyBundle": {}, + "ocrKeyBundle": {} + }, + "ocr2Config": { + "enabled": true, + "p2pKeyBundle": { + "peerID": "p2p_12D3KooWQhLYuAxx4WDKafnuhZUTix8Y24gtB92vEUpAC4EdH4VA", + "publicKey": "dd1268a3e7ed4b9c83b1227e5bf2558e6b77af585c66e88a06f1164a1a94f8ed" + }, + "ocrKeyBundle": { + "bundleID": "a11d9438035564bfe84fcfb513b579edbe173fa26c00331e71a010d00b856037", + "configPublicKey": "407cab2a04fa868f645c6848a53abdb8136b08441c50b191651c4f1a348ee700", + "offchainPublicKey": "64a3215839e5630f12ae66b4363f40d82e9c981118c304ca0c4ca5fc2c6e1f37", + "onchainSigningAddress": "6579d77791ee8f8116495dbe6fa6586980177230" + }, + "plugins": {} + } + }, + { + "network": { + "id": "129", + "chainID": "11155111", + "chainType": "EVM", + "name": "Ethereum Testnet (Sepolia)" + }, + "accountAddress": "0xf286c79b4a613a1fE480C8e4fB17B837E7D8ba03", + "adminAddress": "0x0000000000000000000000000000000000000000", + "ocr1Config": { + "p2pKeyBundle": {}, + "ocrKeyBundle": {} + }, + "ocr2Config": { + "enabled": true, + "p2pKeyBundle": { + "peerID": "p2p_12D3KooWQhLYuAxx4WDKafnuhZUTix8Y24gtB92vEUpAC4EdH4VA", + "publicKey": "dd1268a3e7ed4b9c83b1227e5bf2558e6b77af585c66e88a06f1164a1a94f8ed" + }, + "ocrKeyBundle": { + "bundleID": "a11d9438035564bfe84fcfb513b579edbe173fa26c00331e71a010d00b856037", + "configPublicKey": "407cab2a04fa868f645c6848a53abdb8136b08441c50b191651c4f1a348ee700", + "offchainPublicKey": "64a3215839e5630f12ae66b4363f40d82e9c981118c304ca0c4ca5fc2c6e1f37", + "onchainSigningAddress": "6579d77791ee8f8116495dbe6fa6586980177230" + }, + "plugins": {} + } + }, + { + "network": { + "id": "140", + "chainID": "421614", + "chainType": "EVM", + "name": "Arbitrum Testnet (Sepolia)" + }, + "accountAddress": "0xfe85A25cE2CB58b280CC0316305fC678Bf570f5e", + "adminAddress": "0x0000000000000000000000000000000000000000", + "ocr1Config": { + "p2pKeyBundle": {}, + "ocrKeyBundle": {} + }, + "ocr2Config": { + "enabled": true, + "p2pKeyBundle": { + "peerID": "p2p_12D3KooWQhLYuAxx4WDKafnuhZUTix8Y24gtB92vEUpAC4EdH4VA", + "publicKey": "dd1268a3e7ed4b9c83b1227e5bf2558e6b77af585c66e88a06f1164a1a94f8ed" + }, + "ocrKeyBundle": { + "bundleID": "a11d9438035564bfe84fcfb513b579edbe173fa26c00331e71a010d00b856037", + "configPublicKey": "407cab2a04fa868f645c6848a53abdb8136b08441c50b191651c4f1a348ee700", + "offchainPublicKey": "64a3215839e5630f12ae66b4363f40d82e9c981118c304ca0c4ca5fc2c6e1f37", + "onchainSigningAddress": "6579d77791ee8f8116495dbe6fa6586980177230" + }, + "plugins": {} + } + } + ], + "connected": true, + "supportedProducts": [ + "OCR3_CAPABILITY", + "DATA_STREAMS_V03" + ], + "categories": [ + { + "id": "11", + "name": "Keystone" + } + ] + } + ], + "createdAt": "2024-08-14T20:41:33.205484Z" + }, + { + "id": "75", + "keys": [ + "keystone-01", + "keystone-bt-01" + ], + "name": "Chainlink Keystone Node Operator 1", + "metadata": { + "nodeCount": 3, + "jobCount": 5 + }, + "nodes": [ + { + "id": "810", + "name": "Chainlink Sepolia Prod Keystone Cap One 1", + "publicKey": "9ef27cd1855a0ed6932be33c80d7cd9c178307e5a240dbeb9055946359dc5d7f", + "chainConfigs": [ + { + "network": { + "id": "140", + "chainID": "421614", + "chainType": "EVM", + "name": "Arbitrum Testnet (Sepolia)" + }, + "accountAddress": "0xBB465BCa1b289269F2a95a36f5B6fD006Af56ede", + "adminAddress": "0x0000000000000000000000000000000000000000", + "ocr1Config": { + "p2pKeyBundle": {}, + "ocrKeyBundle": {} + }, + "ocr2Config": { + "enabled": true, + "p2pKeyBundle": { + "peerID": "p2p_12D3KooWMNg1a7HvNWuHAPMdveWr1J6NNCVBU1Z4w5swzepT5Wvf", + "publicKey": "abb750e04bee21d830c6ce0f08180853466139fc6055c6737614797c0704d59c" + }, + "ocrKeyBundle": { + "bundleID": "0d176a4c2d68c619d237e419c31a030e5b2162ee031baa8ebc8472623da9b067", + "configPublicKey": "43e4dbf80a9c818a7d35c080f61b6f8f9b175fa1217b1d01168140da75322d5c", + "offchainPublicKey": "707db88237aaaaddc22bf0fe914540ea7b8bbfbe5cf88349cabb26e34762237c", + "onchainSigningAddress": "ac08f52ec257ddbb493e7b9e299dd2c166a7f090" + }, + "plugins": {} + } + }, + { + "network": { + "id": "10", + "chainID": "43113", + "chainType": "EVM", + "name": "Avalanche Testnet (Fuji)" + }, + "accountAddress": "0x5e3618cFF8Ab337b3c73c2775d1a2EC65e5abEF0", + "adminAddress": "0x0000000000000000000000000000000000000000", + "ocr1Config": { + "p2pKeyBundle": {}, + "ocrKeyBundle": {} + }, + "ocr2Config": { + "enabled": true, + "p2pKeyBundle": { + "peerID": "p2p_12D3KooWMNg1a7HvNWuHAPMdveWr1J6NNCVBU1Z4w5swzepT5Wvf", + "publicKey": "abb750e04bee21d830c6ce0f08180853466139fc6055c6737614797c0704d59c" + }, + "ocrKeyBundle": { + "bundleID": "0d176a4c2d68c619d237e419c31a030e5b2162ee031baa8ebc8472623da9b067", + "configPublicKey": "43e4dbf80a9c818a7d35c080f61b6f8f9b175fa1217b1d01168140da75322d5c", + "offchainPublicKey": "707db88237aaaaddc22bf0fe914540ea7b8bbfbe5cf88349cabb26e34762237c", + "onchainSigningAddress": "ac08f52ec257ddbb493e7b9e299dd2c166a7f090" + }, + "plugins": {} + } + }, + { + "network": { + "id": "147", + "chainID": "84532", + "chainType": "EVM", + "name": "Base Testnet (Sepolia)" + }, + "accountAddress": "0x1796BbC2AbbAd5660C8a7812b313E1f48A99f1D1", + "adminAddress": "0x0000000000000000000000000000000000000000", + "ocr1Config": { + "p2pKeyBundle": {}, + "ocrKeyBundle": {} + }, + "ocr2Config": { + "enabled": true, + "p2pKeyBundle": { + "peerID": "p2p_12D3KooWMNg1a7HvNWuHAPMdveWr1J6NNCVBU1Z4w5swzepT5Wvf", + "publicKey": "abb750e04bee21d830c6ce0f08180853466139fc6055c6737614797c0704d59c" + }, + "ocrKeyBundle": { + "bundleID": "0d176a4c2d68c619d237e419c31a030e5b2162ee031baa8ebc8472623da9b067", + "configPublicKey": "43e4dbf80a9c818a7d35c080f61b6f8f9b175fa1217b1d01168140da75322d5c", + "offchainPublicKey": "707db88237aaaaddc22bf0fe914540ea7b8bbfbe5cf88349cabb26e34762237c", + "onchainSigningAddress": "ac08f52ec257ddbb493e7b9e299dd2c166a7f090" + }, + "plugins": {} + } + }, + { + "network": { + "id": "129", + "chainID": "11155111", + "chainType": "EVM", + "name": "Ethereum Testnet (Sepolia)" + }, + "accountAddress": "0xA2bfAc45e6878fbE04525C23dFbb11fFb224Ea60", + "adminAddress": "0x0000000000000000000000000000000000000000", + "ocr1Config": { + "p2pKeyBundle": {}, + "ocrKeyBundle": {} + }, + "ocr2Config": { + "enabled": true, + "p2pKeyBundle": { + "peerID": "p2p_12D3KooWMNg1a7HvNWuHAPMdveWr1J6NNCVBU1Z4w5swzepT5Wvf", + "publicKey": "abb750e04bee21d830c6ce0f08180853466139fc6055c6737614797c0704d59c" + }, + "ocrKeyBundle": { + "bundleID": "0d176a4c2d68c619d237e419c31a030e5b2162ee031baa8ebc8472623da9b067", + "configPublicKey": "43e4dbf80a9c818a7d35c080f61b6f8f9b175fa1217b1d01168140da75322d5c", + "offchainPublicKey": "707db88237aaaaddc22bf0fe914540ea7b8bbfbe5cf88349cabb26e34762237c", + "onchainSigningAddress": "ac08f52ec257ddbb493e7b9e299dd2c166a7f090" + }, + "plugins": {} + } + } + ], + "connected": true, + "supportedProducts": [ + "OCR3_CAPABILITY", + "DATA_STREAMS_V03" + ], + "categories": [ + { + "id": "11", + "name": "Keystone" + } + ] + } + ], + "createdAt": "2024-08-14T20:42:05.709664Z" + }, + { + "id": "76", + "keys": [ + "keystone-00", + "keystone-bt-00" + ], + "name": "Chainlink Keystone Node Operator 0", + "metadata": { + "nodeCount": 3, + "jobCount": 5 + }, + "nodes": [ + { + "id": "809", + "name": "Chainlink Sepolia Prod Keystone Cap One 0", + "publicKey": "545197637db59b96b22528ff90960b9e7cdcea81c8a5a9f06ae6b728bcba35cb", + "chainConfigs": [ + { + "network": { + "id": "10", + "chainID": "43113", + "chainType": "EVM", + "name": "Avalanche Testnet (Fuji)" + }, + "accountAddress": "0x66a88b0a23D8351e8F5e228eEe8439e65F423842", + "adminAddress": "0x0000000000000000000000000000000000000000", + "ocr1Config": { + "p2pKeyBundle": {}, + "ocrKeyBundle": {} + }, + "ocr2Config": { + "enabled": true, + "p2pKeyBundle": { + "peerID": "p2p_12D3KooWFux8Vvs8CPfUSKitXwQsq81ZBhQYcbKRH5L5jkFbQ6nH", + "publicKey": "5a946cfec8e3c33f6c88961dcab2bbd8bb9d05538c8f931bb62d59b1d7fd782e" + }, + "ocrKeyBundle": { + "bundleID": "d9a3c3afdb310ba11b058afd6ee3159edfbc740df4daefd65c257a7ed46ed9ef", + "configPublicKey": "64fd95e7bcbb33e3dd548247352bb7be5ea6577a840e5e3b66336f710b5b272e", + "offchainPublicKey": "216b1e3dc51ad21be806c010397cc2e0bf59b2a06ade89bc7d0c0a7299a4e01e", + "onchainSigningAddress": "a4f0acbe902443aa842db278f421da99cdc47a8b" + }, + "plugins": {} + } + }, + { + "network": { + "id": "129", + "chainID": "11155111", + "chainType": "EVM", + "name": "Ethereum Testnet (Sepolia)" + }, + "accountAddress": "0x36a46774A3743641D4C274b385608Cb455B5B6b8", + "adminAddress": "0x0000000000000000000000000000000000000000", + "ocr1Config": { + "p2pKeyBundle": {}, + "ocrKeyBundle": {} + }, + "ocr2Config": { + "enabled": true, + "p2pKeyBundle": { + "peerID": "p2p_12D3KooWFux8Vvs8CPfUSKitXwQsq81ZBhQYcbKRH5L5jkFbQ6nH", + "publicKey": "5a946cfec8e3c33f6c88961dcab2bbd8bb9d05538c8f931bb62d59b1d7fd782e" + }, + "ocrKeyBundle": { + "bundleID": "d9a3c3afdb310ba11b058afd6ee3159edfbc740df4daefd65c257a7ed46ed9ef", + "configPublicKey": "64fd95e7bcbb33e3dd548247352bb7be5ea6577a840e5e3b66336f710b5b272e", + "offchainPublicKey": "216b1e3dc51ad21be806c010397cc2e0bf59b2a06ade89bc7d0c0a7299a4e01e", + "onchainSigningAddress": "a4f0acbe902443aa842db278f421da99cdc47a8b" + }, + "plugins": {} + } + }, + { + "network": { + "id": "147", + "chainID": "84532", + "chainType": "EVM", + "name": "Base Testnet (Sepolia)" + }, + "accountAddress": "0x868ab67c00fF7e21aFf470C066798e5bE4240305", + "adminAddress": "0x0000000000000000000000000000000000000000", + "ocr1Config": { + "p2pKeyBundle": {}, + "ocrKeyBundle": {} + }, + "ocr2Config": { + "enabled": true, + "p2pKeyBundle": { + "peerID": "p2p_12D3KooWFux8Vvs8CPfUSKitXwQsq81ZBhQYcbKRH5L5jkFbQ6nH", + "publicKey": "5a946cfec8e3c33f6c88961dcab2bbd8bb9d05538c8f931bb62d59b1d7fd782e" + }, + "ocrKeyBundle": { + "bundleID": "d9a3c3afdb310ba11b058afd6ee3159edfbc740df4daefd65c257a7ed46ed9ef", + "configPublicKey": "64fd95e7bcbb33e3dd548247352bb7be5ea6577a840e5e3b66336f710b5b272e", + "offchainPublicKey": "216b1e3dc51ad21be806c010397cc2e0bf59b2a06ade89bc7d0c0a7299a4e01e", + "onchainSigningAddress": "a4f0acbe902443aa842db278f421da99cdc47a8b" + }, + "plugins": {} + } + }, + { + "network": { + "id": "140", + "chainID": "421614", + "chainType": "EVM", + "name": "Arbitrum Testnet (Sepolia)" + }, + "accountAddress": "0xa60bC482fCfcd12B752541a00555E4e448Bc1d16", + "adminAddress": "0x0000000000000000000000000000000000000000", + "ocr1Config": { + "p2pKeyBundle": {}, + "ocrKeyBundle": {} + }, + "ocr2Config": { + "enabled": true, + "p2pKeyBundle": { + "peerID": "p2p_12D3KooWFux8Vvs8CPfUSKitXwQsq81ZBhQYcbKRH5L5jkFbQ6nH", + "publicKey": "5a946cfec8e3c33f6c88961dcab2bbd8bb9d05538c8f931bb62d59b1d7fd782e" + }, + "ocrKeyBundle": { + "bundleID": "d9a3c3afdb310ba11b058afd6ee3159edfbc740df4daefd65c257a7ed46ed9ef", + "configPublicKey": "64fd95e7bcbb33e3dd548247352bb7be5ea6577a840e5e3b66336f710b5b272e", + "offchainPublicKey": "216b1e3dc51ad21be806c010397cc2e0bf59b2a06ade89bc7d0c0a7299a4e01e", + "onchainSigningAddress": "a4f0acbe902443aa842db278f421da99cdc47a8b" + }, + "plugins": {} + } + } + ], + "connected": true, + "supportedProducts": [ + "OCR3_CAPABILITY", + "DATA_STREAMS_V03" + ], + "categories": [ + { + "id": "11", + "name": "Keystone" + } + ] + } + ], + "createdAt": "2024-08-14T20:42:49.446864Z" + } +] diff --git a/deployment/keystone/testdata/ocr3config.json b/deployment/keystone/testdata/ocr3config.json new file mode 100644 index 00000000000..6835a4143f4 --- /dev/null +++ b/deployment/keystone/testdata/ocr3config.json @@ -0,0 +1,27 @@ +{ + "OracleConfig": { + "MaxQueryLengthBytes": 1000000, + "MaxObservationLengthBytes": 1000000, + "MaxReportLengthBytes": 1000000, + "MaxRequestBatchSize": 1000, + "UniqueReports": true, + + "DeltaProgressMillis": 5000, + "DeltaResendMillis": 5000, + "DeltaInitialMillis": 5000, + "DeltaRoundMillis": 2000, + "DeltaGraceMillis": 500, + "DeltaCertifiedCommitRequestMillis": 1000, + "DeltaStageMillis": 30000, + "MaxRoundsPerEpoch": 10, + "TransmissionSchedule": [1, 1, 1, 1], + + "MaxDurationQueryMillis": 1000, + "MaxDurationObservationMillis": 1000, + "MaxDurationReportMillis": 1000, + "MaxDurationAcceptMillis": 1000, + "MaxDurationTransmitMillis": 1000, + + "MaxFaultyOracles": 1 + } +} diff --git a/deployment/keystone/testdata/workflow_nodes.json b/deployment/keystone/testdata/workflow_nodes.json new file mode 100644 index 00000000000..a5cf7de56fd --- /dev/null +++ b/deployment/keystone/testdata/workflow_nodes.json @@ -0,0 +1,1107 @@ + +[ + { + "id": "67", + "keys": [ + "keystone-09" + ], + "name": "Chainlink Keystone Node Operator 9", + "metadata": { + "nodeCount": 2, + "jobCount": 4 + }, + "nodes": [ + { + "id": "780", + "name": "Chainlink Sepolia Prod Keystone One 9", + "publicKey": "412dc6fe48ea4e34baaa77da2e3b032d39b938597b6f3d61fe7ed183a827a431", + "chainConfigs": [ + { + "network": { + "id": "1401", + "chainID": "2", + "chainType": "APTOS", + "name": "APTOS TEST" + }, + "ocr2Config": { + "enabled": true, + "p2pKeyBundle": { + "peerID": "p2p_12D3KooWBCMCCZZ8x57AXvJvpCujqhZzTjWXbReaRE8TxNr5dM4U", + "publicKey": "147d5cc651819b093cd2fdff9760f0f0f77b7ef7798d9e24fc6a350b7300e5d9" + }, + "ocrKeyBundle": { + "bundleID": "d834cf7c830df7510228b33b138c018ff16b4eecf82273ed3bcd862bbbc046d4", + "configPublicKey": "6a1f37f06833c55ecf46233439ea6179a835bac6f2b2dee725b747c121813149", + "offchainPublicKey": "ff1144bbf648e6f76c58d0ce53a9a2cbe9a284d52db8691a714cac8e3a96b8b4", + "onchainSigningAddress": "4fa557850e4d5c21b3963c97414c1f37792700c4d3b8abdb904b765fd47e39bf" + }, + "plugins": {} + } + }, + { + "network": { + "id": "140", + "chainID": "421614", + "chainType": "EVM", + "name": "Arbitrum Testnet (Sepolia)" + }, + "accountAddress": "0xbA8E21dFaa0501fCD43146d0b5F21c2B8E0eEdfB", + "adminAddress": "0x0000000000000000000000000000000000000000", + "ocr1Config": { + "p2pKeyBundle": {}, + "ocrKeyBundle": {} + }, + "ocr2Config": { + "enabled": true, + "p2pKeyBundle": { + "peerID": "p2p_12D3KooWBCMCCZZ8x57AXvJvpCujqhZzTjWXbReaRE8TxNr5dM4U", + "publicKey": "147d5cc651819b093cd2fdff9760f0f0f77b7ef7798d9e24fc6a350b7300e5d9" + }, + "ocrKeyBundle": { + "bundleID": "1c28e76d180d1ed1524e61845fa58a384415de7e51017edf1f8c553e28357772", + "configPublicKey": "09fced0207611ed618bf0759ab128d9797e15b18e46436be1a56a91e4043ec0e", + "offchainPublicKey": "c805572b813a072067eab2087ddbee8aa719090e12890b15c01094f0d3f74a5f", + "onchainSigningAddress": "679296b7c1eb4948efcc87efc550940a182e610c" + }, + "plugins": {} + } + }, + { + "network": { + "id": "129", + "chainID": "11155111", + "chainType": "EVM", + "name": "Ethereum Testnet (Sepolia)" + }, + "accountAddress": "0x0b04cE574E80Da73191Ec141c0016a54A6404056", + "adminAddress": "0x0000000000000000000000000000000000000000", + "ocr1Config": { + "p2pKeyBundle": {}, + "ocrKeyBundle": {} + }, + "ocr2Config": { + "enabled": true, + "p2pKeyBundle": { + "peerID": "p2p_12D3KooWBCMCCZZ8x57AXvJvpCujqhZzTjWXbReaRE8TxNr5dM4U", + "publicKey": "147d5cc651819b093cd2fdff9760f0f0f77b7ef7798d9e24fc6a350b7300e5d9" + }, + "ocrKeyBundle": { + "bundleID": "1c28e76d180d1ed1524e61845fa58a384415de7e51017edf1f8c553e28357772", + "configPublicKey": "09fced0207611ed618bf0759ab128d9797e15b18e46436be1a56a91e4043ec0e", + "offchainPublicKey": "c805572b813a072067eab2087ddbee8aa719090e12890b15c01094f0d3f74a5f", + "onchainSigningAddress": "679296b7c1eb4948efcc87efc550940a182e610c" + }, + "plugins": {} + } + } + ], + "connected": true, + "supportedProducts": [ + "WORKFLOW", + "OCR3_CAPABILITY" + ], + "categories": [ + { + "id": "11", + "name": "Keystone" + } + ] + } + ], + "createdAt": "2024-08-14T19:00:07.113658Z" + }, + { + "id": "68", + "keys": [ + "keystone-08" + ], + "name": "Chainlink Keystone Node Operator 8", + "metadata": { + "nodeCount": 2, + "jobCount": 4 + }, + "nodes": [ + { + "id": "781", + "name": "Chainlink Sepolia Prod Keystone One 8", + "publicKey": "1141dd1e46797ced9b0fbad49115f18507f6f6e6e3cc86e7e5ba169e58645adc", + "chainConfigs": [ + { + "network": { + "id": "1402", + "chainID": "2", + "chainType": "APTOS", + "name": "APTOS TEST" + }, + "ocr2Config": { + "enabled": true, + "p2pKeyBundle": { + "peerID": "p2p_12D3KooWAUagqMycsro27kFznSQRHbhfCBLx8nKD4ptTiUGDe38c", + "publicKey": "09ca39cd924653c72fbb0e458b629c3efebdad3e29e7cd0b5760754d919ed829" + }, + "ocrKeyBundle": { + "bundleID": "6726df46033038b724a4e6371807b6aa09efc829d0a3f7a5db4fd7df4b69fea7", + "configPublicKey": "0874e6cd5c8e651ab0ff564a474832ed9eaf2c5025b553f908d04921d9777d50", + "offchainPublicKey": "c791d2b9d3562f991af68ab7164a19734d551a9404d91c9571fdcdc5dcb237ca", + "onchainSigningAddress": "bddafb20cc50d89e0ae2f244908c27b1d639615d8186b28c357669de3359f208" + }, + "plugins": {} + } + }, + { + "network": { + "id": "140", + "chainID": "421614", + "chainType": "EVM", + "name": "Arbitrum Testnet (Sepolia)" + }, + "accountAddress": "0xEa4bC3638660D78Da56f39f6680dCDD0cEAaD2c6", + "adminAddress": "0x0000000000000000000000000000000000000000", + "ocr1Config": { + "p2pKeyBundle": {}, + "ocrKeyBundle": {} + }, + "ocr2Config": { + "enabled": true, + "p2pKeyBundle": { + "peerID": "p2p_12D3KooWAUagqMycsro27kFznSQRHbhfCBLx8nKD4ptTiUGDe38c", + "publicKey": "09ca39cd924653c72fbb0e458b629c3efebdad3e29e7cd0b5760754d919ed829" + }, + "ocrKeyBundle": { + "bundleID": "be0d639de3ae3cbeaa31ca369514f748ba1d271145cba6796bcc12aace2f64c3", + "configPublicKey": "e3d4d7a7372a3b1110db0290ab3649eb5fbb0daf6cf3ae02cfe5f367700d9264", + "offchainPublicKey": "ad08c2a5878cada53521f4e2bb449f191ccca7899246721a0deeea19f7b83f70", + "onchainSigningAddress": "8c2aa1e6fad88a6006dfb116eb866cbad2910314" + }, + "plugins": {} + } + }, + { + "network": { + "id": "129", + "chainID": "11155111", + "chainType": "EVM", + "name": "Ethereum Testnet (Sepolia)" + }, + "accountAddress": "0x31B179dcF8f9036C30f04bE578793e51bF14A39E", + "adminAddress": "0x0000000000000000000000000000000000000000", + "ocr1Config": { + "p2pKeyBundle": {}, + "ocrKeyBundle": {} + }, + "ocr2Config": { + "enabled": true, + "p2pKeyBundle": { + "peerID": "p2p_12D3KooWAUagqMycsro27kFznSQRHbhfCBLx8nKD4ptTiUGDe38c", + "publicKey": "09ca39cd924653c72fbb0e458b629c3efebdad3e29e7cd0b5760754d919ed829" + }, + "ocrKeyBundle": { + "bundleID": "be0d639de3ae3cbeaa31ca369514f748ba1d271145cba6796bcc12aace2f64c3", + "configPublicKey": "e3d4d7a7372a3b1110db0290ab3649eb5fbb0daf6cf3ae02cfe5f367700d9264", + "offchainPublicKey": "ad08c2a5878cada53521f4e2bb449f191ccca7899246721a0deeea19f7b83f70", + "onchainSigningAddress": "8c2aa1e6fad88a6006dfb116eb866cbad2910314" + }, + "plugins": {} + } + } + ], + "connected": true, + "supportedProducts": [ + "WORKFLOW", + "OCR3_CAPABILITY" + ], + "categories": [ + { + "id": "11", + "name": "Keystone" + } + ] + } + ], + "createdAt": "2024-08-14T20:26:37.622463Z" + }, + { + "id": "69", + "keys": [ + "keystone-07" + ], + "name": "Chainlink Keystone Node Operator 7", + "metadata": { + "nodeCount": 2, + "jobCount": 4 + }, + "nodes": [ + { + "id": "782", + "name": "Chainlink Sepolia Prod Keystone One 7", + "publicKey": "b473091fe1d4dbbc26ad71c67b4432f8f4280e06bab5e2122a92f4ab8b6ff2f5", + "chainConfigs": [ + { + "network": { + "id": "1403", + "chainID": "2", + "chainType": "APTOS", + "name": "APTOS TEST" + }, + "ocr2Config": { + "enabled": true, + "p2pKeyBundle": { + "peerID": "p2p_12D3KooWQMCj73V5xmCd6C5VsJr7rbFG2TF9LwVcLiiBqXps9MgC", + "publicKey": "d7e9f2252b09edf0802a65b60bc9956691747894cb3ab9fefd072adf742eb9f1" + }, + "ocrKeyBundle": { + "bundleID": "14082da0f33b4cec842bc1e1002e617a194ed4a81105603bd6c1edf784aa3743", + "configPublicKey": "209eea27e73b0ecc1c49b3ea274e4a18a1f5ed62fd79f443f0b5b9cc6019356e", + "offchainPublicKey": "cf0684a0e59399fe9b92cfc740d9696f925e78ee7d0273947e5f7b830070eaaa", + "onchainSigningAddress": "96dc85670c49caa986de4ad288e680e9afb0f5491160dcbb4868ca718e194fc8" + }, + "plugins": {} + } + }, + { + "network": { + "id": "140", + "chainID": "421614", + "chainType": "EVM", + "name": "Arbitrum Testnet (Sepolia)" + }, + "accountAddress": "0x65bE4739E187a39b859766C143b569acd5BE234d", + "adminAddress": "0x0000000000000000000000000000000000000000", + "ocr1Config": { + "p2pKeyBundle": {}, + "ocrKeyBundle": {} + }, + "ocr2Config": { + "enabled": true, + "p2pKeyBundle": { + "peerID": "p2p_12D3KooWQMCj73V5xmCd6C5VsJr7rbFG2TF9LwVcLiiBqXps9MgC", + "publicKey": "d7e9f2252b09edf0802a65b60bc9956691747894cb3ab9fefd072adf742eb9f1" + }, + "ocrKeyBundle": { + "bundleID": "e6d6ffec6cff01ac20d57bc42626c8e955293f232d383bf468351d867a7b8213", + "configPublicKey": "4d2f75f98b911c20fe7808384312d8b913e6b7a98c34d05c6e461434c92b4502", + "offchainPublicKey": "01496edce35663071d74472e02119432ba059b3904d205e4358014410e4f2be3", + "onchainSigningAddress": "213803bb9f9715379aaf11aadb0212369701dc0a" + }, + "plugins": {} + } + }, + { + "network": { + "id": "129", + "chainID": "11155111", + "chainType": "EVM", + "name": "Ethereum Testnet (Sepolia)" + }, + "accountAddress": "0x9ad9f3AD49e5aB0F28bD694d211a90297bD90D7f", + "adminAddress": "0x0000000000000000000000000000000000000000", + "ocr1Config": { + "p2pKeyBundle": {}, + "ocrKeyBundle": {} + }, + "ocr2Config": { + "enabled": true, + "p2pKeyBundle": { + "peerID": "p2p_12D3KooWQMCj73V5xmCd6C5VsJr7rbFG2TF9LwVcLiiBqXps9MgC", + "publicKey": "d7e9f2252b09edf0802a65b60bc9956691747894cb3ab9fefd072adf742eb9f1" + }, + "ocrKeyBundle": { + "bundleID": "e6d6ffec6cff01ac20d57bc42626c8e955293f232d383bf468351d867a7b8213", + "configPublicKey": "4d2f75f98b911c20fe7808384312d8b913e6b7a98c34d05c6e461434c92b4502", + "offchainPublicKey": "01496edce35663071d74472e02119432ba059b3904d205e4358014410e4f2be3", + "onchainSigningAddress": "213803bb9f9715379aaf11aadb0212369701dc0a" + }, + "plugins": {} + } + } + ], + "connected": true, + "supportedProducts": [ + "WORKFLOW", + "OCR3_CAPABILITY" + ], + "categories": [ + { + "id": "11", + "name": "Keystone" + } + ] + } + ], + "createdAt": "2024-08-14T20:30:51.07624Z" + }, + { + "id": "70", + "keys": [ + "keystone-06" + ], + "name": "Chainlink Keystone Node Operator 6", + "metadata": { + "nodeCount": 2, + "jobCount": 4 + }, + "nodes": [ + { + "id": "783", + "name": "Chainlink Sepolia Prod Keystone One 6", + "publicKey": "75ac63fc97a31e31168084e0de8ccd2bea90059b609d962f3e43fc296cdba28d", + "chainConfigs": [ + { + "network": { + "id": "1404", + "chainID": "2", + "chainType": "APTOS", + "name": "APTOS TEST" + }, + "ocr2Config": { + "enabled": true, + "p2pKeyBundle": { + "peerID": "p2p_12D3KooWNJ8de3PUURZ2oucrVTpnRTqNBTUYwHLQjK9LzN3E6Mfn", + "publicKey": "b96933429b1a81c811e1195389d7733e936b03e8086e75ea1fa92c61564b6c31" + }, + "ocrKeyBundle": { + "bundleID": "b419e9e3f1256aa2907a1a396bdf27ba5002a30eee440ab96cb60369429ce277", + "configPublicKey": "3ae1a1c713e4ad63f67191fd93620c9eebe44e1d5f3264036ec0fbcd59cf9664", + "offchainPublicKey": "6fc8c3fb55b39577abbab20028bee93d1d6d8a888dd298354b95d4af3ccb6009", + "onchainSigningAddress": "4a94c75cb9fe8b1fba86fd4b71ad130943281fdefad10216c46eb2285d60950f" + }, + "plugins": {} + } + }, + { + "network": { + "id": "140", + "chainID": "421614", + "chainType": "EVM", + "name": "Arbitrum Testnet (Sepolia)" + }, + "accountAddress": "0x8706E716fc1ee972F3E4D42D42711Aa175Aa654A", + "adminAddress": "0x0000000000000000000000000000000000000000", + "ocr1Config": { + "p2pKeyBundle": {}, + "ocrKeyBundle": {} + }, + "ocr2Config": { + "enabled": true, + "p2pKeyBundle": { + "peerID": "p2p_12D3KooWNJ8de3PUURZ2oucrVTpnRTqNBTUYwHLQjK9LzN3E6Mfn", + "publicKey": "b96933429b1a81c811e1195389d7733e936b03e8086e75ea1fa92c61564b6c31" + }, + "ocrKeyBundle": { + "bundleID": "62d36269d916b4834b17dc6d637c1c39b0895396249a0845764c898e83f63525", + "configPublicKey": "8c6c7d889ac6cc9e663ae48073bbf130fae105d6a3689636db27752e3e3e6816", + "offchainPublicKey": "aa3419628ea3536783742d17d8adf05681aa6a6bd2b206fbde78c7e5aa38586d", + "onchainSigningAddress": "4885973b2fcf061d5cdfb8f74c5139bd3056e9da" + }, + "plugins": {} + } + }, + { + "network": { + "id": "129", + "chainID": "11155111", + "chainType": "EVM", + "name": "Ethereum Testnet (Sepolia)" + }, + "accountAddress": "0x19e10B063a62B1574AE19020A64fDe6419892dA6", + "adminAddress": "0x0000000000000000000000000000000000000000", + "ocr1Config": { + "p2pKeyBundle": {}, + "ocrKeyBundle": {} + }, + "ocr2Config": { + "enabled": true, + "p2pKeyBundle": { + "peerID": "p2p_12D3KooWNJ8de3PUURZ2oucrVTpnRTqNBTUYwHLQjK9LzN3E6Mfn", + "publicKey": "b96933429b1a81c811e1195389d7733e936b03e8086e75ea1fa92c61564b6c31" + }, + "ocrKeyBundle": { + "bundleID": "62d36269d916b4834b17dc6d637c1c39b0895396249a0845764c898e83f63525", + "configPublicKey": "8c6c7d889ac6cc9e663ae48073bbf130fae105d6a3689636db27752e3e3e6816", + "offchainPublicKey": "aa3419628ea3536783742d17d8adf05681aa6a6bd2b206fbde78c7e5aa38586d", + "onchainSigningAddress": "4885973b2fcf061d5cdfb8f74c5139bd3056e9da" + }, + "plugins": {} + } + } + ], + "connected": true, + "supportedProducts": [ + "WORKFLOW", + "OCR3_CAPABILITY" + ], + "categories": [ + { + "id": "11", + "name": "Keystone" + } + ] + } + ], + "createdAt": "2024-08-14T20:32:14.024795Z" + }, + { + "id": "71", + "keys": [ + "keystone-05" + ], + "name": "Chainlink Keystone Node Operator 5", + "metadata": { + "nodeCount": 2, + "jobCount": 4 + }, + "nodes": [ + { + "id": "784", + "name": "Chainlink Sepolia Prod Keystone One 5", + "publicKey": "4542f4fd2ed150c8c976b39802fe3d994aec3ac94fd11e7817f693b1c9a1dabb", + "chainConfigs": [ + { + "network": { + "id": "14005", + "chainID": "2", + "chainType": "APTOS", + "name": "APTOS TEST" + }, + "ocr2Config": { + "enabled": true, + "p2pKeyBundle": { + "peerID": "p2p_12D3KooWR8d5kbZb7YiQWKpT1J1PfMqNaGAmb4jBFx9DWag4hpSZ", + "publicKey": "e38c9f2760db006f070e9cc1bc1c2269ad033751adaa85d022fb760cbc5b5ef6" + }, + "ocrKeyBundle": { + "bundleID": "44b5f46bfbb04d0984469298ec43c350ec6b2cd4556b18265ebac1b6cc329c7c", + "configPublicKey": "263bee0d09d90e0e618c4cdd630d1437f7377f2d544df57f39ddd47984970555", + "offchainPublicKey": "11674b98849d8e070ac69d37c284b3091fcd374913f52b2b83ce2d9a4a4e0213", + "onchainSigningAddress": "425d1354a7b8180252a221040c718cac0ba0251c7efe31a2acefbba578dc2153" + }, + "plugins": {} + } + }, + { + "network": { + "id": "140", + "chainID": "421614", + "chainType": "EVM", + "name": "Arbitrum Testnet (Sepolia)" + }, + "accountAddress": "0xcea9f5C042130dD35Eff5B5a6E2361A0276570e3", + "adminAddress": "0x0000000000000000000000000000000000000000", + "ocr1Config": { + "p2pKeyBundle": {}, + "ocrKeyBundle": {} + }, + "ocr2Config": { + "enabled": true, + "p2pKeyBundle": { + "peerID": "p2p_12D3KooWR8d5kbZb7YiQWKpT1J1PfMqNaGAmb4jBFx9DWag4hpSZ", + "publicKey": "e38c9f2760db006f070e9cc1bc1c2269ad033751adaa85d022fb760cbc5b5ef6" + }, + "ocrKeyBundle": { + "bundleID": "99fad0362cc8dc8a57a8e616e68133a6d5a8834e08a1b4819710f0e912df5abc", + "configPublicKey": "36de4924cf11938b4461aea1ce99cb640e9603d9a7c294ab6c54acd51d575a49", + "offchainPublicKey": "283471ed66d61fbe11f64eff65d738b59a0301c9a4f846280db26c64c9fdd3f8", + "onchainSigningAddress": "657587eb55cecd6f90b97297b611c3024e488cc0" + }, + "plugins": {} + } + }, + { + "network": { + "id": "129", + "chainID": "11155111", + "chainType": "EVM", + "name": "Ethereum Testnet (Sepolia)" + }, + "accountAddress": "0xdAd1F3F8ec690cf335D46c50EdA5547CeF875161", + "adminAddress": "0x0000000000000000000000000000000000000000", + "ocr1Config": { + "p2pKeyBundle": {}, + "ocrKeyBundle": {} + }, + "ocr2Config": { + "enabled": true, + "p2pKeyBundle": { + "peerID": "p2p_12D3KooWR8d5kbZb7YiQWKpT1J1PfMqNaGAmb4jBFx9DWag4hpSZ", + "publicKey": "e38c9f2760db006f070e9cc1bc1c2269ad033751adaa85d022fb760cbc5b5ef6" + }, + "ocrKeyBundle": { + "bundleID": "99fad0362cc8dc8a57a8e616e68133a6d5a8834e08a1b4819710f0e912df5abc", + "configPublicKey": "36de4924cf11938b4461aea1ce99cb640e9603d9a7c294ab6c54acd51d575a49", + "offchainPublicKey": "283471ed66d61fbe11f64eff65d738b59a0301c9a4f846280db26c64c9fdd3f8", + "onchainSigningAddress": "657587eb55cecd6f90b97297b611c3024e488cc0" + }, + "plugins": {} + } + } + ], + "connected": true, + "supportedProducts": [ + "WORKFLOW", + "OCR3_CAPABILITY" + ], + "categories": [ + { + "id": "11", + "name": "Keystone" + } + ] + } + ], + "createdAt": "2024-08-14T20:38:35.588611Z" + }, + { + "id": "72", + "keys": [ + "keystone-04" + ], + "name": "Chainlink Keystone Node Operator 4", + "metadata": { + "nodeCount": 2, + "jobCount": 4 + }, + "nodes": [ + { + "id": "785", + "name": "Chainlink Sepolia Prod Keystone One 4", + "publicKey": "07e0ffc57b6263604df517b94bd986169451a3c90600a855bb19212dc575de54", + "chainConfigs": [ + { + "network": { + "id": "1406", + "chainID": "2", + "chainType": "APTOS", + "name": "APTOS TEST" + }, + "ocr2Config": { + "enabled": true, + "p2pKeyBundle": { + "peerID": "p2p_12D3KooWHqR1w26yHatTSZQW3xbRct9SxWzVj9X4SpU916Hy8jYg", + "publicKey": "77224be9d052343b1d17156a1e463625c0d746468d4f5a44cddd452365b1d4ed" + }, + "ocrKeyBundle": { + "bundleID": "b1ab478c1322bc4f8227be50898a8044efc70cf0156ec53cf132119db7e94dea", + "configPublicKey": "96ae354418e50dcd5b3dae62e8f0bc911bbce7f761220837aacdaa6f82bd0f29", + "offchainPublicKey": "b34bb49788541de8b6cfb321799a41927a391a4eb135c74f6cb14eec0531ee6f", + "onchainSigningAddress": "1221e131ef21014a6a99ed22376eb869746a3b5e30fd202cf79e44efaeb8c5c2" + }, + "plugins": {} + } + }, + { + "network": { + "id": "140", + "chainID": "421614", + "chainType": "EVM", + "name": "Arbitrum Testnet (Sepolia)" + }, + "accountAddress": "0x0be7Df958604166D9Bf0F727F0AC7A4Fb0f5B8a1", + "adminAddress": "0x0000000000000000000000000000000000000000", + "ocr1Config": { + "p2pKeyBundle": {}, + "ocrKeyBundle": {} + }, + "ocr2Config": { + "enabled": true, + "p2pKeyBundle": { + "peerID": "p2p_12D3KooWHqR1w26yHatTSZQW3xbRct9SxWzVj9X4SpU916Hy8jYg", + "publicKey": "77224be9d052343b1d17156a1e463625c0d746468d4f5a44cddd452365b1d4ed" + }, + "ocrKeyBundle": { + "bundleID": "8e563a16ec5a802345b162d0f31149e8d5055014a31847d7b20d6de500aa48bd", + "configPublicKey": "c812eab2415f45cc1d2afdb2be2e3ea419bb7851acfc30c07b4df42c856e8f74", + "offchainPublicKey": "2a4c7dec127fdd8145e48c5edb9467225098bd8c8ad1dade868325b787affbde", + "onchainSigningAddress": "a6f35436cb7bffd615cc47a0a04aa0a78696a144" + }, + "plugins": {} + } + }, + { + "network": { + "id": "129", + "chainID": "11155111", + "chainType": "EVM", + "name": "Ethereum Testnet (Sepolia)" + }, + "accountAddress": "0x6F5cAb24Fb7412bB516b3468b9F3a9c471d25fE5", + "adminAddress": "0x0000000000000000000000000000000000000000", + "ocr1Config": { + "p2pKeyBundle": {}, + "ocrKeyBundle": {} + }, + "ocr2Config": { + "enabled": true, + "p2pKeyBundle": { + "peerID": "p2p_12D3KooWHqR1w26yHatTSZQW3xbRct9SxWzVj9X4SpU916Hy8jYg", + "publicKey": "77224be9d052343b1d17156a1e463625c0d746468d4f5a44cddd452365b1d4ed" + }, + "ocrKeyBundle": { + "bundleID": "8e563a16ec5a802345b162d0f31149e8d5055014a31847d7b20d6de500aa48bd", + "configPublicKey": "c812eab2415f45cc1d2afdb2be2e3ea419bb7851acfc30c07b4df42c856e8f74", + "offchainPublicKey": "2a4c7dec127fdd8145e48c5edb9467225098bd8c8ad1dade868325b787affbde", + "onchainSigningAddress": "a6f35436cb7bffd615cc47a0a04aa0a78696a144" + }, + "plugins": {} + } + } + ], + "connected": true, + "supportedProducts": [ + "WORKFLOW", + "OCR3_CAPABILITY" + ], + "categories": [ + { + "id": "11", + "name": "Keystone" + } + ] + } + ], + "createdAt": "2024-08-14T20:39:26.24249Z" + }, + { + "id": "73", + "keys": [ + "keystone-03", + "keystone-bt-03" + ], + "name": "Chainlink Keystone Node Operator 3", + "metadata": { + "nodeCount": 3, + "jobCount": 5 + }, + "nodes": [ + { + "id": "786", + "name": "Chainlink Sepolia Prod Keystone One 3", + "publicKey": "487901e0c0a9d3c66e7cfc50f3a9e3cdbfdf1b0107273d73d94a91d278545516", + "chainConfigs": [ + { + "network": { + "id": "1417", + "chainID": "2", + "chainType": "APTOS", + "name": "APTOS TEST" + }, + "ocr2Config": { + "enabled": true, + "p2pKeyBundle": { + "peerID": "p2p_12D3KooWCcVLytqinD8xMn27NvomcQhj2mqMVzyGemz6oPwv1SMT", + "publicKey": "298834a041a056df58c839cb53d99b78558693042e54dff238f504f16d18d4b6" + }, + "ocrKeyBundle": { + "bundleID": "5811a96a0c3b5f5b52973eee10e5771cf5953d37d5616ea71f7ae76f09f6e332", + "configPublicKey": "a7f3435bfbaabebd1572142ff1aec9ed98758d9bb098f1fcc77262fcae7f4171", + "offchainPublicKey": "886044b333af681ab4bf3be663122524ece9725e110ac2a64cda8526cad6983e", + "onchainSigningAddress": "046faf34ebfe42510251e6098bc34fa3dd5f2de38ac07e47f2d1b34ac770639f" + }, + "plugins": {} + } + }, + { + "network": { + "id": "140", + "chainID": "421614", + "chainType": "EVM", + "name": "Arbitrum Testnet (Sepolia)" + }, + "accountAddress": "0x3Be73A57a36E5ab00DcceD755B4bfF8bb99e52b2", + "adminAddress": "0x0000000000000000000000000000000000000000", + "ocr1Config": { + "p2pKeyBundle": {}, + "ocrKeyBundle": {} + }, + "ocr2Config": { + "enabled": true, + "p2pKeyBundle": { + "peerID": "p2p_12D3KooWCcVLytqinD8xMn27NvomcQhj2mqMVzyGemz6oPwv1SMT", + "publicKey": "298834a041a056df58c839cb53d99b78558693042e54dff238f504f16d18d4b6" + }, + "ocrKeyBundle": { + "bundleID": "8843b5db0608f92dac38ca56775766a08db9ee82224a19595d04bd6c58b38fbd", + "configPublicKey": "63375a3d175364bd299e7cecf352cb3e469dd30116cf1418f2b7571fb46c4a4b", + "offchainPublicKey": "b4c4993d6c15fee63800db901a8b35fa419057610962caab1c1d7bed55709127", + "onchainSigningAddress": "6607c140e558631407f33bafbabd103863cee876" + }, + "plugins": {} + } + }, + { + "network": { + "id": "129", + "chainID": "11155111", + "chainType": "EVM", + "name": "Ethereum Testnet (Sepolia)" + }, + "accountAddress": "0xA9eFB53c513E413762b2Be5299D161d8E6e7278e", + "adminAddress": "0x0000000000000000000000000000000000000000", + "ocr1Config": { + "p2pKeyBundle": {}, + "ocrKeyBundle": {} + }, + "ocr2Config": { + "enabled": true, + "p2pKeyBundle": { + "peerID": "p2p_12D3KooWCcVLytqinD8xMn27NvomcQhj2mqMVzyGemz6oPwv1SMT", + "publicKey": "298834a041a056df58c839cb53d99b78558693042e54dff238f504f16d18d4b6" + }, + "ocrKeyBundle": { + "bundleID": "8843b5db0608f92dac38ca56775766a08db9ee82224a19595d04bd6c58b38fbd", + "configPublicKey": "63375a3d175364bd299e7cecf352cb3e469dd30116cf1418f2b7571fb46c4a4b", + "offchainPublicKey": "b4c4993d6c15fee63800db901a8b35fa419057610962caab1c1d7bed55709127", + "onchainSigningAddress": "6607c140e558631407f33bafbabd103863cee876" + }, + "plugins": {} + } + } + ], + "connected": true, + "supportedProducts": [ + "WORKFLOW", + "OCR3_CAPABILITY" + ], + "categories": [ + { + "id": "11", + "name": "Keystone" + } + ] + } + ], + "createdAt": "2024-08-14T20:40:30.499914Z" + }, + { + "id": "74", + "keys": [ + "keystone-02", + "keystone-bt-02" + ], + "name": "Chainlink Keystone Node Operator 2", + "metadata": { + "nodeCount": 3, + "jobCount": 5 + }, + "nodes": [ + { + "id": "787", + "name": "Chainlink Sepolia Prod Keystone One 2", + "publicKey": "7a166fbc816eb4a4dcb620d11c3ccac5c085d56b1972374100116f87619debb8", + "chainConfigs": [ + { + "network": { + "id": "140", + "chainID": "421614", + "chainType": "EVM", + "name": "Arbitrum Testnet (Sepolia)" + }, + "accountAddress": "0x693bf95A3ef46E5dABe17d1A89dB1E83948aeD88", + "adminAddress": "0x0000000000000000000000000000000000000000", + "ocr1Config": { + "p2pKeyBundle": {}, + "ocrKeyBundle": {} + }, + "ocr2Config": { + "enabled": true, + "p2pKeyBundle": { + "peerID": "p2p_12D3KooWGDmBKZ7B3PynGrvfHTJMEecpjfHts9YK5NWk8oJuxcAo", + "publicKey": "5f247f61a6d5bfdd1d5064db0bd25fe443648133c6131975edb23481424e3d9c" + }, + "ocrKeyBundle": { + "bundleID": "1d20490fe469dd6af3d418cc310a6e835181fa13e8dc80156bcbe302b7afcd34", + "configPublicKey": "ee466234b3b2f65b13c848b17aa6a8d4e0aa0311d3bf8e77a64f20b04ed48d39", + "offchainPublicKey": "dba3c61e5f8bec594be481bcaf67ecea0d1c2950edb15b158ce3dbc77877def3", + "onchainSigningAddress": "d4dcc573e9d24a8b27a07bba670ba3a2ab36e5bb" + }, + "plugins": {} + } + }, + { + "network": { + "id": "1408", + "chainID": "2", + "chainType": "APTOS", + "name": "APTOS TEST" + }, + "ocr2Config": { + "enabled": true, + "p2pKeyBundle": { + "peerID": "p2p_12D3KooWGDmBKZ7B3PynGrvfHTJMEecpjfHts9YK5NWk8oJuxcAo", + "publicKey": "5f247f61a6d5bfdd1d5064db0bd25fe443648133c6131975edb23481424e3d9c" + }, + "ocrKeyBundle": { + "bundleID": "e57c608a899d80e510913d2c7ef55758ee81e9eb73eb531003af1564307fd133", + "configPublicKey": "412a4bed6b064c17168871d28dbb965cc0a898f7b19eb3fa7cd01d3e3d10b66c", + "offchainPublicKey": "450aa794c87198a595761a8c18f0f1590046c8092960036638d002256af95254", + "onchainSigningAddress": "ba20d3da9b07663f1e8039081a514649fd61a48be2d241bc63537ee47d028fcd" + }, + "plugins": {} + } + }, + { + "network": { + "id": "129", + "chainID": "11155111", + "chainType": "EVM", + "name": "Ethereum Testnet (Sepolia)" + }, + "accountAddress": "0xCea84bC1881F3cE14BA13Dc3a00DC1Ff3D553fF0", + "adminAddress": "0x0000000000000000000000000000000000000000", + "ocr1Config": { + "p2pKeyBundle": {}, + "ocrKeyBundle": {} + }, + "ocr2Config": { + "enabled": true, + "p2pKeyBundle": { + "peerID": "p2p_12D3KooWGDmBKZ7B3PynGrvfHTJMEecpjfHts9YK5NWk8oJuxcAo", + "publicKey": "5f247f61a6d5bfdd1d5064db0bd25fe443648133c6131975edb23481424e3d9c" + }, + "ocrKeyBundle": { + "bundleID": "1d20490fe469dd6af3d418cc310a6e835181fa13e8dc80156bcbe302b7afcd34", + "configPublicKey": "ee466234b3b2f65b13c848b17aa6a8d4e0aa0311d3bf8e77a64f20b04ed48d39", + "offchainPublicKey": "dba3c61e5f8bec594be481bcaf67ecea0d1c2950edb15b158ce3dbc77877def3", + "onchainSigningAddress": "d4dcc573e9d24a8b27a07bba670ba3a2ab36e5bb" + }, + "plugins": {} + } + } + ], + "connected": true, + "supportedProducts": [ + "WORKFLOW", + "OCR3_CAPABILITY" + ], + "categories": [ + { + "id": "11", + "name": "Keystone" + } + ] + } + ], + "createdAt": "2024-08-14T20:41:33.205484Z" + }, + { + "id": "75", + "keys": [ + "keystone-01", + "keystone-bt-01" + ], + "name": "Chainlink Keystone Node Operator 1", + "metadata": { + "nodeCount": 3, + "jobCount": 5 + }, + "nodes": [ + { + "id": "788", + "name": "Chainlink Sepolia Prod Keystone One 1", + "publicKey": "28b91143ec9111796a7d63e14c1cf6bb01b4ed59667ab54f5bc72ebe49c881be", + "chainConfigs": [ + { + "network": { + "id": "1409", + "chainID": "2", + "chainType": "APTOS", + "name": "APTOS TEST" + }, + "ocr2Config": { + "enabled": true, + "p2pKeyBundle": { + "peerID": "p2p_12D3KooWCbDiL7sP9BVby5KaZqPpaVP1RBokoa9ShzH5WhkYX46v", + "publicKey": "2934f31f278e5c60618f85861bd6add54a4525d79a642019bdc87d75d26372c3" + }, + "ocrKeyBundle": { + "bundleID": "4b6418b8ab88ea1244c3c48eb5f4c86f9f0301aebffcac4fcfac5cdfb7cf6933", + "configPublicKey": "a38dbe521643479d78ab5477cae78161a5de0030c95098e3fbb09add6aca9508", + "offchainPublicKey": "7718dcbf40173dbd876720aa64028a6b18bf9a87543fc83a549515c4937962e3", + "onchainSigningAddress": "247d0189f65f58be83a4e7d87ff338aaf8956e9acb9fcc783f34f9edc29d1b40" + }, + "plugins": {} + } + }, + { + "network": { + "id": "140", + "chainID": "421614", + "chainType": "EVM", + "name": "Arbitrum Testnet (Sepolia)" + }, + "accountAddress": "0xe45a754B30FdE9852A826F58c6bd94Fa6554CE96", + "adminAddress": "0x0000000000000000000000000000000000000000", + "ocr1Config": { + "p2pKeyBundle": {}, + "ocrKeyBundle": {} + }, + "ocr2Config": { + "enabled": true, + "p2pKeyBundle": { + "peerID": "p2p_12D3KooWCbDiL7sP9BVby5KaZqPpaVP1RBokoa9ShzH5WhkYX46v", + "publicKey": "2934f31f278e5c60618f85861bd6add54a4525d79a642019bdc87d75d26372c3" + }, + "ocrKeyBundle": { + "bundleID": "7a9b75510b8d09932b98142419bef52436ff725dd9395469473b487ef87fdfb0", + "configPublicKey": "2c45fec2320f6bcd36444529a86d9f8b4439499a5d8272dec9bcbbebb5e1bf01", + "offchainPublicKey": "255096a3b7ade10e29c648e0b407fc486180464f713446b1da04f013df6179c8", + "onchainSigningAddress": "8258f4c4761cc445333017608044a204fd0c006a" + }, + "plugins": {} + } + }, + { + "network": { + "id": "129", + "chainID": "11155111", + "chainType": "EVM", + "name": "Ethereum Testnet (Sepolia)" + }, + "accountAddress": "0x415aa1E9a1bcB3929ed92bFa1F9735Dc0D45AD31", + "adminAddress": "0x0000000000000000000000000000000000000000", + "ocr1Config": { + "p2pKeyBundle": {}, + "ocrKeyBundle": {} + }, + "ocr2Config": { + "enabled": true, + "p2pKeyBundle": { + "peerID": "p2p_12D3KooWCbDiL7sP9BVby5KaZqPpaVP1RBokoa9ShzH5WhkYX46v", + "publicKey": "2934f31f278e5c60618f85861bd6add54a4525d79a642019bdc87d75d26372c3" + }, + "ocrKeyBundle": { + "bundleID": "7a9b75510b8d09932b98142419bef52436ff725dd9395469473b487ef87fdfb0", + "configPublicKey": "2c45fec2320f6bcd36444529a86d9f8b4439499a5d8272dec9bcbbebb5e1bf01", + "offchainPublicKey": "255096a3b7ade10e29c648e0b407fc486180464f713446b1da04f013df6179c8", + "onchainSigningAddress": "8258f4c4761cc445333017608044a204fd0c006a" + }, + "plugins": {} + } + } + ], + "connected": true, + "supportedProducts": [ + "WORKFLOW", + "OCR3_CAPABILITY" + ], + "categories": [ + { + "id": "11", + "name": "Keystone" + } + ] + } + ], + "createdAt": "2024-08-14T20:42:05.709664Z" + }, + { + "id": "76", + "keys": [ + "keystone-00", + "keystone-bt-00" + ], + "name": "Chainlink Keystone Node Operator 0", + "metadata": { + "nodeCount": 3, + "jobCount": 5 + }, + "nodes": [ + { + "id": "789", + "name": "Chainlink Sepolia Prod Keystone One 0", + "publicKey": "403b72f0b1b3b5f5a91bcfedb7f28599767502a04b5b7e067fcf3782e23eeb9c", + "chainConfigs": [ + { + "network": { + "id": "1411", + "chainID": "2", + "chainType": "APTOS", + "name": "APTOS TEST" + }, + "ocr2Config": { + "enabled": true, + "p2pKeyBundle": { + "peerID": "p2p_12D3KooWMWUKdoAc2ruZf9f55p7NVFj7AFiPm67xjQ8BZBwkqyYv", + "publicKey": "adb6bf005cdb23f21e11b82d66b9f62628c2939640ed93028bf0dad3923c5a8b" + }, + "ocrKeyBundle": { + "bundleID": "b4504e84ea307cc2afffca0206bd4bf8e98acc5a03c9bd47b2456e3845a5d1fa", + "configPublicKey": "559ea4ee5774a31d97914a4220d6a47094ae8e2cf0806e80e1eacd851f3e6757", + "offchainPublicKey": "4ec55bbe76a6b1fdc885c59da85a8fe44cf06afe1e4719f0824a731937526c52", + "onchainSigningAddress": "b8834eaa062f0df4ccfe7832253920071ec14dc4f78b13ecdda10b824e2dd3b6" + }, + "plugins": {} + } + }, + { + "network": { + "id": "140", + "chainID": "421614", + "chainType": "EVM", + "name": "Arbitrum Testnet (Sepolia)" + }, + "accountAddress": "0x1a04C6b4b1A45D20356F93DcE7931F765955BAa7", + "adminAddress": "0x0000000000000000000000000000000000000000", + "ocr1Config": { + "p2pKeyBundle": {}, + "ocrKeyBundle": {} + }, + "ocr2Config": { + "enabled": true, + "p2pKeyBundle": { + "peerID": "p2p_12D3KooWMWUKdoAc2ruZf9f55p7NVFj7AFiPm67xjQ8BZBwkqyYv", + "publicKey": "adb6bf005cdb23f21e11b82d66b9f62628c2939640ed93028bf0dad3923c5a8b" + }, + "ocrKeyBundle": { + "bundleID": "665a101d79d310cb0a5ebf695b06e8fc8082b5cbe62d7d362d80d47447a31fea", + "configPublicKey": "5193f72fc7b4323a86088fb0acb4e4494ae351920b3944bd726a59e8dbcdd45f", + "offchainPublicKey": "03dacd15fc96c965c648e3623180de002b71a97cf6eeca9affb91f461dcd6ce1", + "onchainSigningAddress": "b35409a8d4f9a18da55c5b2bb08a3f5f68d44442" + }, + "plugins": {} + } + }, + { + "network": { + "id": "129", + "chainID": "11155111", + "chainType": "EVM", + "name": "Ethereum Testnet (Sepolia)" + }, + "accountAddress": "0x2877F08d9c5Cc9F401F730Fa418fAE563A9a2FF3", + "adminAddress": "0x0000000000000000000000000000000000000000", + "ocr1Config": { + "p2pKeyBundle": {}, + "ocrKeyBundle": {} + }, + "ocr2Config": { + "enabled": true, + "p2pKeyBundle": { + "peerID": "p2p_12D3KooWMWUKdoAc2ruZf9f55p7NVFj7AFiPm67xjQ8BZBwkqyYv", + "publicKey": "adb6bf005cdb23f21e11b82d66b9f62628c2939640ed93028bf0dad3923c5a8b" + }, + "ocrKeyBundle": { + "bundleID": "665a101d79d310cb0a5ebf695b06e8fc8082b5cbe62d7d362d80d47447a31fea", + "configPublicKey": "5193f72fc7b4323a86088fb0acb4e4494ae351920b3944bd726a59e8dbcdd45f", + "offchainPublicKey": "03dacd15fc96c965c648e3623180de002b71a97cf6eeca9affb91f461dcd6ce1", + "onchainSigningAddress": "b35409a8d4f9a18da55c5b2bb08a3f5f68d44442" + }, + "plugins": {} + } + } + ], + "connected": true, + "supportedProducts": [ + "WORKFLOW", + "OCR3_CAPABILITY" + ], + "categories": [ + { + "id": "11", + "name": "Keystone" + } + ] + } + ], + "createdAt": "2024-08-14T20:42:49.446864Z" + } +] diff --git a/deployment/keystone/types.go b/deployment/keystone/types.go new file mode 100644 index 00000000000..e5657657ed9 --- /dev/null +++ b/deployment/keystone/types.go @@ -0,0 +1,429 @@ +package keystone + +import ( + "encoding/hex" + "errors" + "fmt" + "slices" + "sort" + "strconv" + "strings" + + "github.com/ethereum/go-ethereum/common" + + chainsel "github.com/smartcontractkit/chain-selectors" + + "github.com/smartcontractkit/chainlink/deployment" + + v1 "github.com/smartcontractkit/chainlink-protos/job-distributor/v1/node" + + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry" + kcr "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry" + "github.com/smartcontractkit/chainlink/v2/core/services/keystore/chaintype" + "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/p2pkey" +) + +var ( + CapabilitiesRegistry deployment.ContractType = "CapabilitiesRegistry" // https://github.com/smartcontractkit/chainlink/blob/50c1b3dbf31bd145b312739b08967600a5c67f30/contracts/src/v0.8/keystone/CapabilitiesRegistry.sol#L392 + KeystoneForwarder deployment.ContractType = "KeystoneForwarder" // https://github.com/smartcontractkit/chainlink/blob/50c1b3dbf31bd145b312739b08967600a5c67f30/contracts/src/v0.8/keystone/KeystoneForwarder.sol#L90 + OCR3Capability deployment.ContractType = "OCR3Capability" // https://github.com/smartcontractkit/chainlink/blob/50c1b3dbf31bd145b312739b08967600a5c67f30/contracts/src/v0.8/keystone/OCR3Capability.sol#L12 + FeedConsumer deployment.ContractType = "FeedConsumer" // no type and a version in contract https://github.com/smartcontractkit/chainlink/blob/89183a8a5d22b1aeca0ade3b76d16aa84067aa57/contracts/src/v0.8/keystone/KeystoneFeedsConsumer.sol#L1 +) + +type DeployResponse struct { + Address common.Address + Tx common.Hash // todo: chain agnostic + Tv deployment.TypeAndVersion +} + +type DeployRequest struct { + Chain deployment.Chain +} + +type DonNode struct { + Don string + Node string // not unique across environments +} + +type CapabilityHost struct { + NodeID string // globally unique + Capabilities []capabilities_registry.CapabilitiesRegistryCapability +} + +type Nop struct { + capabilities_registry.CapabilitiesRegistryNodeOperator + NodeIDs []string // nodes run by this operator +} + +// ocr2Node is a subset of the node configuration that is needed to register a node +// with the capabilities registry. Signer and P2PKey are chain agnostic. +// TODO: KS-466 when we migrate fully to the JD offchain client, we should be able remove this shim and use environment.Node directly +type ocr2Node struct { + ID string + Signer [32]byte // note that in capabilities registry we need a [32]byte, but in the forwarder we need a common.Address [20]byte + P2PKey p2pkey.PeerID + EncryptionPublicKey [32]byte + IsBoostrap bool + // useful when have to register the ocr3 contract config + p2pKeyBundle *v1.OCR2Config_P2PKeyBundle + ethOcr2KeyBundle *v1.OCR2Config_OCRKeyBundle + aptosOcr2KeyBundle *v1.OCR2Config_OCRKeyBundle + csaKey string // *v1.Node.PublicKey + accountAddress string +} + +func (o *ocr2Node) signerAddress() common.Address { + // eth address is the first 20 bytes of the Signer + return common.BytesToAddress(o.Signer[:20]) +} + +func (o *ocr2Node) toNodeKeys() NodeKeys { + var aptosOcr2KeyBundleId string + var aptosOnchainPublicKey string + if o.aptosOcr2KeyBundle != nil { + aptosOcr2KeyBundleId = o.aptosOcr2KeyBundle.BundleId + aptosOnchainPublicKey = o.aptosOcr2KeyBundle.OnchainSigningAddress + } + return NodeKeys{ + EthAddress: o.accountAddress, + P2PPeerID: strings.TrimPrefix(o.p2pKeyBundle.PeerId, "p2p_"), + OCR2BundleID: o.ethOcr2KeyBundle.BundleId, + OCR2OnchainPublicKey: o.ethOcr2KeyBundle.OnchainSigningAddress, + OCR2OffchainPublicKey: o.ethOcr2KeyBundle.OffchainPublicKey, + OCR2ConfigPublicKey: o.ethOcr2KeyBundle.ConfigPublicKey, + CSAPublicKey: o.csaKey, + // default value of encryption public key is the CSA public key + // TODO: DEVSVCS-760 + EncryptionPublicKey: strings.TrimPrefix(o.csaKey, "csa_"), + // TODO Aptos support. How will that be modeled in clo data? + AptosBundleID: aptosOcr2KeyBundleId, + AptosOnchainPublicKey: aptosOnchainPublicKey, + } +} +func newOcr2NodeFromJD(n *Node, registryChainSel uint64) (*ocr2Node, error) { + if n.PublicKey == nil { + return nil, errors.New("no public key") + } + // the chain configs are equivalent as far as the ocr2 config is concerned so take the first one + if len(n.ChainConfigs) == 0 { + return nil, errors.New("no chain configs") + } + // all nodes should have an evm chain config, specifically the registry chain + evmCC, err := registryChainConfig(n.ChainConfigs, v1.ChainType_CHAIN_TYPE_EVM, registryChainSel) + if err != nil { + return nil, fmt.Errorf("failed to get registry chain config for sel %d: %w", registryChainSel, err) + } + cfgs := map[chaintype.ChainType]*v1.ChainConfig{ + chaintype.EVM: evmCC, + } + aptosCC, exists := firstChainConfigByType(n.ChainConfigs, v1.ChainType_CHAIN_TYPE_APTOS) + if exists { + cfgs[chaintype.Aptos] = aptosCC + } + return newOcr2Node(n.ID, cfgs, *n.PublicKey) +} + +func ExtractKeys(n *Node, registerChainSel uint64) (p2p p2pkey.PeerID, signer [32]byte, encPubKey [32]byte, err error) { + orc2n, err := newOcr2NodeFromJD(n, registerChainSel) + if err != nil { + return p2p, signer, encPubKey, fmt.Errorf("failed to create ocr2 node for node %s: %w", n.ID, err) + } + return orc2n.P2PKey, orc2n.Signer, orc2n.EncryptionPublicKey, nil +} + +func newOcr2Node(id string, ccfgs map[chaintype.ChainType]*v1.ChainConfig, csaPubKey string) (*ocr2Node, error) { + if ccfgs == nil { + return nil, errors.New("nil ocr2config") + } + evmCC, exists := ccfgs[chaintype.EVM] + if !exists { + return nil, errors.New("no evm chain config for node id " + id) + } + + if csaPubKey == "" { + return nil, errors.New("empty csa public key") + } + // parse csapublic key to + csaKey, err := hex.DecodeString(csaPubKey) + if err != nil { + return nil, fmt.Errorf("failed to decode csa public key %s: %w", csaPubKey, err) + } + if len(csaKey) != 32 { + return nil, fmt.Errorf("invalid csa public key '%s'. expected len 32 got %d", csaPubKey, len(csaKey)) + } + var csaKeyb [32]byte + copy(csaKeyb[:], csaKey) + + ocfg := evmCC.Ocr2Config + p := p2pkey.PeerID{} + if err := p.UnmarshalString(ocfg.P2PKeyBundle.PeerId); err != nil { + return nil, fmt.Errorf("failed to unmarshal peer id %s: %w", ocfg.P2PKeyBundle.PeerId, err) + } + + signer := ocfg.OcrKeyBundle.OnchainSigningAddress + if len(signer) != 40 { + return nil, fmt.Errorf("invalid onchain signing address %s", ocfg.OcrKeyBundle.OnchainSigningAddress) + } + signerB, err := hex.DecodeString(signer) + if err != nil { + return nil, fmt.Errorf("failed to convert signer %s: %w", signer, err) + } + + var sigb [32]byte + copy(sigb[:], signerB) + + n := &ocr2Node{ + ID: id, + Signer: sigb, + P2PKey: p, + EncryptionPublicKey: csaKeyb, + IsBoostrap: ocfg.IsBootstrap, + p2pKeyBundle: ocfg.P2PKeyBundle, + ethOcr2KeyBundle: evmCC.Ocr2Config.OcrKeyBundle, + aptosOcr2KeyBundle: nil, + accountAddress: evmCC.AccountAddress, + csaKey: csaPubKey, + } + // aptos chain config is optional + if aptosCC, exists := ccfgs[chaintype.Aptos]; exists { + n.aptosOcr2KeyBundle = aptosCC.Ocr2Config.OcrKeyBundle + } + + return n, nil +} + +func makeNodeKeysSlice(nodes []*ocr2Node) []NodeKeys { + var out []NodeKeys + for _, n := range nodes { + out = append(out, n.toNodeKeys()) + } + return out +} + +type NOP struct { + Name string + Nodes []string // peerID +} + +func (v NOP) Validate() error { + if v.Name == "" { + return errors.New("name is empty") + } + if len(v.Nodes) == 0 { + return errors.New("no nodes") + } + for i, n := range v.Nodes { + _, err := p2pkey.MakePeerID(n) + if err != nil { + return fmt.Errorf("failed to nop %s: node %d is not valid peer id %s: %w", v.Name, i, n, err) + } + } + + return nil +} + +// DonCapabilities is a set of capabilities hosted by a set of node operators +// in is in a convenient form to handle the CLO representation of the nop data +type DonCapabilities struct { + Name string + Nops []NOP + Capabilities []kcr.CapabilitiesRegistryCapability // every capability is hosted on each nop +} + +func (v DonCapabilities) Validate() error { + if v.Name == "" { + return errors.New("name is empty") + } + if len(v.Nops) == 0 { + return errors.New("no nops") + } + for i, n := range v.Nops { + if err := n.Validate(); err != nil { + return fmt.Errorf("failed to validate nop %d '%s': %w", i, n.Name, err) + } + } + if len(v.Capabilities) == 0 { + return errors.New("no capabilities") + } + return nil +} + +func NodeOperator(name string, adminAddress string) capabilities_registry.CapabilitiesRegistryNodeOperator { + return capabilities_registry.CapabilitiesRegistryNodeOperator{ + Name: name, + Admin: adminAddr(adminAddress), + } +} + +func AdminAddress(n *Node, chainSel uint64) (string, error) { + cid, err := chainsel.ChainIdFromSelector(chainSel) + if err != nil { + return "", fmt.Errorf("failed to get chain id from selector %d: %w", chainSel, err) + } + cidStr := strconv.FormatUint(cid, 10) + for _, chain := range n.ChainConfigs { + //TODO validate chainType field + if chain.Chain.Id == cidStr { + return chain.AdminAddress, nil + } + } + return "", fmt.Errorf("no chain config for chain %d", cid) +} + +func nopsToNodes(donInfos []DonInfo, dons []DonCapabilities, chainSelector uint64) (map[capabilities_registry.CapabilitiesRegistryNodeOperator][]string, error) { + out := make(map[capabilities_registry.CapabilitiesRegistryNodeOperator][]string) + for _, don := range dons { + for _, nop := range don.Nops { + idx := slices.IndexFunc(donInfos, func(donInfo DonInfo) bool { + return donInfo.Name == don.Name + }) + if idx < 0 { + return nil, fmt.Errorf("couldn't find donInfo for %v", don.Name) + } + donInfo := donInfos[idx] + idx = slices.IndexFunc(donInfo.Nodes, func(node Node) bool { + return node.P2PID == nop.Nodes[0] + }) + if idx < 0 { + return nil, fmt.Errorf("couldn't find node with p2p_id %v", nop.Nodes[0]) + } + node := donInfo.Nodes[idx] + a, err := AdminAddress(&node, chainSelector) + if err != nil { + return nil, fmt.Errorf("failed to get admin address for node %s: %w", node.ID, err) + } + nodeOperator := NodeOperator(nop.Name, a) + for _, node := range nop.Nodes { + + idx = slices.IndexFunc(donInfo.Nodes, func(n Node) bool { + return n.P2PID == node + }) + if idx < 0 { + return nil, fmt.Errorf("couldn't find node with p2p_id %v", node) + } + out[nodeOperator] = append(out[nodeOperator], donInfo.Nodes[idx].ID) + + } + } + } + + return out, nil +} + +// mapDonsToCaps converts a list of DonCapabilities to a map of don name to capabilities +func mapDonsToCaps(dons []DonInfo) map[string][]kcr.CapabilitiesRegistryCapability { + out := make(map[string][]kcr.CapabilitiesRegistryCapability) + for _, don := range dons { + out[don.Name] = don.Capabilities + } + return out +} + +// mapDonsToNodes returns a map of don name to simplified representation of their nodes +// all nodes must have evm config and ocr3 capability nodes are must also have an aptos chain config +func mapDonsToNodes(dons []DonInfo, excludeBootstraps bool, registryChainSel uint64) (map[string][]*ocr2Node, error) { + donToOcr2Nodes := make(map[string][]*ocr2Node) + // get the nodes for each don from the offchain client, get ocr2 config from one of the chain configs for the node b/c + // they are equivalent, and transform to ocr2node representation + + for _, don := range dons { + for _, node := range don.Nodes { + ocr2n, err := newOcr2NodeFromJD(&node, registryChainSel) + if err != nil { + return nil, fmt.Errorf("failed to create ocr2 node for node %s: %w", node.ID, err) + } + if excludeBootstraps && ocr2n.IsBoostrap { + continue + } + if _, ok := donToOcr2Nodes[don.Name]; !ok { + donToOcr2Nodes[don.Name] = make([]*ocr2Node, 0) + } + donToOcr2Nodes[don.Name] = append(donToOcr2Nodes[don.Name], ocr2n) + } + } + + return donToOcr2Nodes, nil +} + +func firstChainConfigByType(ccfgs []*v1.ChainConfig, t v1.ChainType) (*v1.ChainConfig, bool) { + for _, c := range ccfgs { + if c.Chain.Type == t { + return c, true + } + } + return nil, false +} + +func registryChainConfig(ccfgs []*v1.ChainConfig, t v1.ChainType, sel uint64) (*v1.ChainConfig, error) { + chainId, err := chainsel.ChainIdFromSelector(sel) + if err != nil { + return nil, fmt.Errorf("failed to get chain id from selector %d: %w", sel, err) + } + chainIdStr := strconv.FormatUint(chainId, 10) + for _, c := range ccfgs { + if c.Chain.Type == t && c.Chain.Id == chainIdStr { + return c, nil + } + } + return nil, fmt.Errorf("no chain config for chain %d", chainId) +} + +// RegisteredDon is a representation of a don that exists in the in the capabilities registry all with the enriched node data +type RegisteredDon struct { + Name string + Info capabilities_registry.CapabilitiesRegistryDONInfo + Nodes []*ocr2Node +} + +func (d RegisteredDon) signers() []common.Address { + sort.Slice(d.Nodes, func(i, j int) bool { + return d.Nodes[i].P2PKey.String() < d.Nodes[j].P2PKey.String() + }) + var out []common.Address + for _, n := range d.Nodes { + if n.IsBoostrap { + continue + } + out = append(out, n.signerAddress()) + } + return out +} + +func joinInfoAndNodes(donInfos map[string]kcr.CapabilitiesRegistryDONInfo, dons []DonInfo, registryChainSel uint64) ([]RegisteredDon, error) { + // all maps should have the same keys + nodes, err := mapDonsToNodes(dons, true, registryChainSel) + if err != nil { + return nil, fmt.Errorf("failed to map dons to capabilities: %w", err) + } + if len(donInfos) != len(nodes) { + return nil, fmt.Errorf("mismatched lengths don infos %d, nodes %d", len(donInfos), len(nodes)) + } + var out []RegisteredDon + for donName, info := range donInfos { + + ocr2nodes, ok := nodes[donName] + if !ok { + return nil, fmt.Errorf("nodes not found for don %s", donName) + } + out = append(out, RegisteredDon{ + Name: donName, + Info: info, + Nodes: ocr2nodes, + }) + } + + return out, nil +} + +var emptyAddr = "0x0000000000000000000000000000000000000000" + +// compute the admin address from the string. If the address is empty, replaces the 0s with fs +// contract registry disallows 0x0 as an admin address, but our test net nops use it +func adminAddr(addr string) common.Address { + needsFixing := addr == emptyAddr + addr = strings.TrimPrefix(addr, "0x") + if needsFixing { + addr = strings.ReplaceAll(addr, "0", "f") + } + return common.HexToAddress(strings.TrimPrefix(addr, "0x")) +} diff --git a/deployment/keystone/types_test.go b/deployment/keystone/types_test.go new file mode 100644 index 00000000000..925649bba0d --- /dev/null +++ b/deployment/keystone/types_test.go @@ -0,0 +1,402 @@ +package keystone + +import ( + "testing" + + "github.com/stretchr/testify/assert" + + v1 "github.com/smartcontractkit/chainlink-protos/job-distributor/v1/node" + "github.com/smartcontractkit/chainlink/v2/core/services/keystore/chaintype" +) + +func Test_newOcr2Node(t *testing.T) { + type args struct { + id string + ccfgs map[chaintype.ChainType]*v1.ChainConfig + csaPubKey string + } + tests := []struct { + name string + args args + wantAptos bool + wantErr bool + }{ + { + name: "no aptos", + args: args{ + id: "1", + ccfgs: map[chaintype.ChainType]*v1.ChainConfig{ + chaintype.EVM: { + + Ocr2Config: &v1.OCR2Config{ + P2PKeyBundle: &v1.OCR2Config_P2PKeyBundle{ + PeerId: "p2p_12D3KooWMWUKdoAc2ruZf9f55p7NVFj7AFiPm67xjQ8BZBwkqyYv", + PublicKey: "pubKey", + }, + OcrKeyBundle: &v1.OCR2Config_OCRKeyBundle{ + BundleId: "bundleId", + ConfigPublicKey: "03dacd15fc96c965c648e3623180de002b71a97cf6eeca9affb91f461dcd6ce1", + OffchainPublicKey: "03dacd15fc96c965c648e3623180de002b71a97cf6eeca9affb91f461dcd6ce1", + OnchainSigningAddress: "b35409a8d4f9a18da55c5b2bb08a3f5f68d44442", + }, + }, + }, + }, + csaPubKey: "1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef", + }, + }, + { + name: "with aptos", + args: args{ + id: "1", + ccfgs: map[chaintype.ChainType]*v1.ChainConfig{ + chaintype.EVM: { + + Ocr2Config: &v1.OCR2Config{ + P2PKeyBundle: &v1.OCR2Config_P2PKeyBundle{ + PeerId: "p2p_12D3KooWMWUKdoAc2ruZf9f55p7NVFj7AFiPm67xjQ8BZBwkqyYv", + PublicKey: "pubKey", + }, + OcrKeyBundle: &v1.OCR2Config_OCRKeyBundle{ + BundleId: "bundleId", + ConfigPublicKey: "03dacd15fc96c965c648e3623180de002b71a97cf6eeca9affb91f461dcd6ce1", + OffchainPublicKey: "03dacd15fc96c965c648e3623180de002b71a97cf6eeca9affb91f461dcd6ce1", + OnchainSigningAddress: "b35409a8d4f9a18da55c5b2bb08a3f5f68d44442", + }, + }, + }, + chaintype.Aptos: { + + Ocr2Config: &v1.OCR2Config{ + P2PKeyBundle: &v1.OCR2Config_P2PKeyBundle{ + PeerId: "p2p_12D3KooWMWUKdoAc2ruZf9f55p7NVFj7AFiPm67xjQ8BZB11111", + PublicKey: "pubKey", + }, + OcrKeyBundle: &v1.OCR2Config_OCRKeyBundle{ + BundleId: "bundleId2", + ConfigPublicKey: "0000015fc96c965c648e3623180de002b71a97cf6eeca9affb91f461dcd6ce1", + OffchainPublicKey: "03dacd15fc96c965c648e3623180de002b71a97cf6eeca9affb91f461dcd6ce1", + OnchainSigningAddress: "111409a8d4f9a18da55c5b2bb08a3f5f68d44777", + }, + }, + }, + }, + csaPubKey: "1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef", + }, + wantAptos: true, + }, + { + name: "bad csa key", + args: args{ + id: "1", + ccfgs: map[chaintype.ChainType]*v1.ChainConfig{ + chaintype.EVM: { + + Ocr2Config: &v1.OCR2Config{ + P2PKeyBundle: &v1.OCR2Config_P2PKeyBundle{ + PeerId: "p2p_12D3KooWMWUKdoAc2ruZf9f55p7NVFj7AFiPm67xjQ8BZBwkqyYv", + PublicKey: "pubKey", + }, + OcrKeyBundle: &v1.OCR2Config_OCRKeyBundle{ + BundleId: "bundleId", + ConfigPublicKey: "03dacd15fc96c965c648e3623180de002b71a97cf6eeca9affb91f461dcd6ce1", + OffchainPublicKey: "03dacd15fc96c965c648e3623180de002b71a97cf6eeca9affb91f461dcd6ce1", + OnchainSigningAddress: "b35409a8d4f9a18da55c5b2bb08a3f5f68d44442", + }, + }, + }, + }, + csaPubKey: "not hex", + }, + wantErr: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := newOcr2Node(tt.args.id, tt.args.ccfgs, tt.args.csaPubKey) + if (err != nil) != tt.wantErr { + t.Errorf("newOcr2Node() error = %v, wantErr %v", err, tt.wantErr) + return + } + if tt.wantErr { + return + } + assert.NotNil(t, got.ethOcr2KeyBundle) + assert.NotNil(t, got.p2pKeyBundle) + assert.NotNil(t, got.Signer) + assert.NotNil(t, got.EncryptionPublicKey) + assert.NotEmpty(t, got.csaKey) + assert.NotEmpty(t, got.P2PKey) + assert.Equal(t, tt.wantAptos, got.aptosOcr2KeyBundle != nil) + }) + } +} + +// func Test_mapDonsToNodes(t *testing.T) { +// var ( +// pubKey = "03dacd15fc96c965c648e3623180de002b71a97cf6eeca9affb91f461dcd6ce1" +// evmSig = "b35409a8d4f9a18da55c5b2bb08a3f5f68d44442" +// aptosSig = "b35409a8d4f9a18da55c5b2bb08a3f5f68d44442b35409a8d4f9a18da55c5b2bb08a3f5f68d44442" +// peerID = "p2p_12D3KooWMWUKdoAc2ruZf9f55p7NVFj7AFiPm67xjQ8BZBwkqyYv" +// // todo: these should be defined in common +// writerCap = 3 +// ocr3Cap = 2 +// registryChainSel = chainsel.ETHEREUM_TESTNET_SEPOLIA.Selector +// registryChainID = strconv.FormatUint(chainsel.ETHEREUM_TESTNET_SEPOLIA.EvmChainID, 10) +// ) +// type args struct { +// dons []DonCapabilities +// excludeBootstraps bool +// } +// tests := []struct { +// name string +// args args +// wantErr bool +// }{ +// { +// name: "writer evm only", +// args: args{ +// dons: []DonCapabilities{ +// { +// Name: "ok writer", +// Nops: []*models.NodeOperator{ +// { +// Nodes: []*models.Node{ +// { +// PublicKey: &pubKey, +// ChainConfigs: []*models.NodeChainConfig{ +// { +// ID: "1", +// Network: &models.Network{ +// ChainType: models.ChainTypeEvm, +// ChainID: registryChainID, +// }, +// Ocr2Config: &models.NodeOCR2Config{ +// P2pKeyBundle: &models.NodeOCR2ConfigP2PKeyBundle{ +// PeerID: peerID, +// }, +// OcrKeyBundle: &models.NodeOCR2ConfigOCRKeyBundle{ +// ConfigPublicKey: pubKey, +// OffchainPublicKey: pubKey, +// OnchainSigningAddress: evmSig, +// }, +// }, +// }, +// }, +// }, +// }, +// }, +// }, +// Capabilities: []kcr.CapabilitiesRegistryCapability{ +// { +// LabelledName: "writer", +// Version: "1", +// CapabilityType: uint8(writerCap), +// }, +// }, +// }, +// }, +// }, +// wantErr: false, +// }, +// { +// name: "err if no evm chain", +// args: args{ +// dons: []DonCapabilities{ +// { +// Name: "bad chain", +// Nops: []*models.NodeOperator{ +// { +// Nodes: []*models.Node{ +// { +// PublicKey: &pubKey, +// ChainConfigs: []*models.NodeChainConfig{ +// { +// ID: "1", +// Network: &models.Network{ +// ChainType: models.ChainTypeSolana, +// }, +// Ocr2Config: &models.NodeOCR2Config{ +// P2pKeyBundle: &models.NodeOCR2ConfigP2PKeyBundle{ +// PeerID: peerID, +// }, +// OcrKeyBundle: &models.NodeOCR2ConfigOCRKeyBundle{ +// ConfigPublicKey: pubKey, +// OffchainPublicKey: pubKey, +// OnchainSigningAddress: evmSig, +// }, +// }, +// }, +// }, +// }, +// }, +// }, +// }, +// Capabilities: []kcr.CapabilitiesRegistryCapability{ +// { +// LabelledName: "writer", +// Version: "1", +// CapabilityType: uint8(writerCap), +// }, +// }, +// }, +// }, +// }, +// wantErr: true, +// }, +// { +// name: "ocr3 cap evm only", +// args: args{ +// dons: []DonCapabilities{ +// { +// Name: "bad chain", +// Nops: []*models.NodeOperator{ +// { +// Nodes: []*models.Node{ +// { +// PublicKey: &pubKey, +// ChainConfigs: []*models.NodeChainConfig{ +// { +// ID: "1", +// Network: &models.Network{ +// ChainType: models.ChainTypeEvm, +// ChainID: registryChainID, +// }, +// Ocr2Config: &models.NodeOCR2Config{ +// P2pKeyBundle: &models.NodeOCR2ConfigP2PKeyBundle{ +// PeerID: peerID, +// }, +// OcrKeyBundle: &models.NodeOCR2ConfigOCRKeyBundle{ +// ConfigPublicKey: pubKey, +// OffchainPublicKey: pubKey, +// OnchainSigningAddress: evmSig, +// }, +// }, +// }, +// }, +// }, +// }, +// }, +// }, +// Capabilities: []kcr.CapabilitiesRegistryCapability{ +// { +// LabelledName: "ocr3", +// Version: "1", +// CapabilityType: uint8(ocr3Cap), +// }, +// }, +// }, +// }, +// }, +// wantErr: false, +// }, +// { +// name: "ocr3 cap evm & aptos", +// args: args{ +// dons: []DonCapabilities{ +// { +// Name: "ok chain", +// Nops: []*models.NodeOperator{ +// { +// Nodes: []*models.Node{ +// { +// PublicKey: &pubKey, +// ChainConfigs: []*models.NodeChainConfig{ +// { +// ID: "1", +// Network: &models.Network{ +// ChainType: models.ChainTypeEvm, +// ChainID: registryChainID, +// }, +// Ocr2Config: &models.NodeOCR2Config{ +// P2pKeyBundle: &models.NodeOCR2ConfigP2PKeyBundle{ +// PeerID: peerID, +// }, +// OcrKeyBundle: &models.NodeOCR2ConfigOCRKeyBundle{ +// ConfigPublicKey: pubKey, +// OffchainPublicKey: pubKey, +// OnchainSigningAddress: evmSig, +// }, +// }, +// }, +// { +// ID: "2", +// Network: &models.Network{ +// ChainType: models.ChainTypeAptos, +// }, +// Ocr2Config: &models.NodeOCR2Config{ +// P2pKeyBundle: &models.NodeOCR2ConfigP2PKeyBundle{ +// PeerID: peerID, +// }, +// OcrKeyBundle: &models.NodeOCR2ConfigOCRKeyBundle{ +// ConfigPublicKey: pubKey, +// OffchainPublicKey: pubKey, +// OnchainSigningAddress: aptosSig, +// }, +// }, +// }, +// }, +// }, +// }, +// }, +// }, +// Capabilities: []kcr.CapabilitiesRegistryCapability{ +// { +// LabelledName: "ocr3", +// Version: "1", +// CapabilityType: uint8(ocr3Cap), +// }, +// }, +// }, +// }, +// }, +// wantErr: false, +// }, +// } +// for _, tt := range tests { +// t.Run(tt.name, func(t *testing.T) { +// _, err := mapDonsToNodes(tt.args.dons, tt.args.excludeBootstraps, registryChainSel) +// if (err != nil) != tt.wantErr { +// t.Errorf("mapDonsToNodes() error = %v, wantErr %v", err, tt.wantErr) +// return +// } +// }) +// } +// // make sure the clo test data is correct +// wfNops := loadTestNops(t, "testdata/workflow_nodes.json") +// cwNops := loadTestNops(t, "testdata/chain_writer_nodes.json") +// assetNops := loadTestNops(t, "testdata/asset_nodes.json") +// require.Len(t, wfNops, 10) +// require.Len(t, cwNops, 10) +// require.Len(t, assetNops, 16) + +// wfDon := DonCapabilities{ +// Name: WFDonName, +// Nops: wfNops, +// Capabilities: []kcr.CapabilitiesRegistryCapability{OCR3Cap}, +// } +// cwDon := DonCapabilities{ +// Name: TargetDonName, +// Nops: cwNops, +// Capabilities: []kcr.CapabilitiesRegistryCapability{WriteChainCap}, +// } +// assetDon := DonCapabilities{ +// Name: StreamDonName, +// Nops: assetNops, +// Capabilities: []kcr.CapabilitiesRegistryCapability{StreamTriggerCap}, +// } +// _, err := mapDonsToNodes([]DonCapabilities{wfDon}, false, registryChainSel) +// require.NoError(t, err, "failed to map wf don") +// _, err = mapDonsToNodes([]DonCapabilities{cwDon}, false, registryChainSel) +// require.NoError(t, err, "failed to map cw don") +// _, err = mapDonsToNodes([]DonCapabilities{assetDon}, false, registryChainSel) +// require.NoError(t, err, "failed to map asset don") +// } + +// func loadTestNops(t *testing.T, pth string) []*models.NodeOperator { +// f, err := os.ReadFile(pth) +// require.NoError(t, err) +// var nops []*models.NodeOperator +// require.NoError(t, json.Unmarshal(f, &nops)) +// return nops +// } diff --git a/deployment/mocks/offchain_client_mock.go b/deployment/mocks/offchain_client_mock.go deleted file mode 100644 index de7a6df3a0d..00000000000 --- a/deployment/mocks/offchain_client_mock.go +++ /dev/null @@ -1,1375 +0,0 @@ -// Code generated by mockery v2.46.3. DO NOT EDIT. - -package deployment - -import ( - context "context" - - csa "github.com/smartcontractkit/chainlink-protos/job-distributor/v1/csa" - grpc "google.golang.org/grpc" - - job "github.com/smartcontractkit/chainlink-protos/job-distributor/v1/job" - - mock "github.com/stretchr/testify/mock" - - node "github.com/smartcontractkit/chainlink-protos/job-distributor/v1/node" -) - -// MockOffchainClient is an autogenerated mock type for the OffchainClient type -type MockOffchainClient struct { - mock.Mock -} - -type MockOffchainClient_Expecter struct { - mock *mock.Mock -} - -func (_m *MockOffchainClient) EXPECT() *MockOffchainClient_Expecter { - return &MockOffchainClient_Expecter{mock: &_m.Mock} -} - -// BatchProposeJob provides a mock function with given fields: ctx, in, opts -func (_m *MockOffchainClient) BatchProposeJob(ctx context.Context, in *job.BatchProposeJobRequest, opts ...grpc.CallOption) (*job.BatchProposeJobResponse, error) { - _va := make([]interface{}, len(opts)) - for _i := range opts { - _va[_i] = opts[_i] - } - var _ca []interface{} - _ca = append(_ca, ctx, in) - _ca = append(_ca, _va...) - ret := _m.Called(_ca...) - - if len(ret) == 0 { - panic("no return value specified for BatchProposeJob") - } - - var r0 *job.BatchProposeJobResponse - var r1 error - if rf, ok := ret.Get(0).(func(context.Context, *job.BatchProposeJobRequest, ...grpc.CallOption) (*job.BatchProposeJobResponse, error)); ok { - return rf(ctx, in, opts...) - } - if rf, ok := ret.Get(0).(func(context.Context, *job.BatchProposeJobRequest, ...grpc.CallOption) *job.BatchProposeJobResponse); ok { - r0 = rf(ctx, in, opts...) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*job.BatchProposeJobResponse) - } - } - - if rf, ok := ret.Get(1).(func(context.Context, *job.BatchProposeJobRequest, ...grpc.CallOption) error); ok { - r1 = rf(ctx, in, opts...) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// MockOffchainClient_BatchProposeJob_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'BatchProposeJob' -type MockOffchainClient_BatchProposeJob_Call struct { - *mock.Call -} - -// BatchProposeJob is a helper method to define mock.On call -// - ctx context.Context -// - in *job.BatchProposeJobRequest -// - opts ...grpc.CallOption -func (_e *MockOffchainClient_Expecter) BatchProposeJob(ctx interface{}, in interface{}, opts ...interface{}) *MockOffchainClient_BatchProposeJob_Call { - return &MockOffchainClient_BatchProposeJob_Call{Call: _e.mock.On("BatchProposeJob", - append([]interface{}{ctx, in}, opts...)...)} -} - -func (_c *MockOffchainClient_BatchProposeJob_Call) Run(run func(ctx context.Context, in *job.BatchProposeJobRequest, opts ...grpc.CallOption)) *MockOffchainClient_BatchProposeJob_Call { - _c.Call.Run(func(args mock.Arguments) { - variadicArgs := make([]grpc.CallOption, len(args)-2) - for i, a := range args[2:] { - if a != nil { - variadicArgs[i] = a.(grpc.CallOption) - } - } - run(args[0].(context.Context), args[1].(*job.BatchProposeJobRequest), variadicArgs...) - }) - return _c -} - -func (_c *MockOffchainClient_BatchProposeJob_Call) Return(_a0 *job.BatchProposeJobResponse, _a1 error) *MockOffchainClient_BatchProposeJob_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *MockOffchainClient_BatchProposeJob_Call) RunAndReturn(run func(context.Context, *job.BatchProposeJobRequest, ...grpc.CallOption) (*job.BatchProposeJobResponse, error)) *MockOffchainClient_BatchProposeJob_Call { - _c.Call.Return(run) - return _c -} - -// DeleteJob provides a mock function with given fields: ctx, in, opts -func (_m *MockOffchainClient) DeleteJob(ctx context.Context, in *job.DeleteJobRequest, opts ...grpc.CallOption) (*job.DeleteJobResponse, error) { - _va := make([]interface{}, len(opts)) - for _i := range opts { - _va[_i] = opts[_i] - } - var _ca []interface{} - _ca = append(_ca, ctx, in) - _ca = append(_ca, _va...) - ret := _m.Called(_ca...) - - if len(ret) == 0 { - panic("no return value specified for DeleteJob") - } - - var r0 *job.DeleteJobResponse - var r1 error - if rf, ok := ret.Get(0).(func(context.Context, *job.DeleteJobRequest, ...grpc.CallOption) (*job.DeleteJobResponse, error)); ok { - return rf(ctx, in, opts...) - } - if rf, ok := ret.Get(0).(func(context.Context, *job.DeleteJobRequest, ...grpc.CallOption) *job.DeleteJobResponse); ok { - r0 = rf(ctx, in, opts...) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*job.DeleteJobResponse) - } - } - - if rf, ok := ret.Get(1).(func(context.Context, *job.DeleteJobRequest, ...grpc.CallOption) error); ok { - r1 = rf(ctx, in, opts...) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// MockOffchainClient_DeleteJob_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'DeleteJob' -type MockOffchainClient_DeleteJob_Call struct { - *mock.Call -} - -// DeleteJob is a helper method to define mock.On call -// - ctx context.Context -// - in *job.DeleteJobRequest -// - opts ...grpc.CallOption -func (_e *MockOffchainClient_Expecter) DeleteJob(ctx interface{}, in interface{}, opts ...interface{}) *MockOffchainClient_DeleteJob_Call { - return &MockOffchainClient_DeleteJob_Call{Call: _e.mock.On("DeleteJob", - append([]interface{}{ctx, in}, opts...)...)} -} - -func (_c *MockOffchainClient_DeleteJob_Call) Run(run func(ctx context.Context, in *job.DeleteJobRequest, opts ...grpc.CallOption)) *MockOffchainClient_DeleteJob_Call { - _c.Call.Run(func(args mock.Arguments) { - variadicArgs := make([]grpc.CallOption, len(args)-2) - for i, a := range args[2:] { - if a != nil { - variadicArgs[i] = a.(grpc.CallOption) - } - } - run(args[0].(context.Context), args[1].(*job.DeleteJobRequest), variadicArgs...) - }) - return _c -} - -func (_c *MockOffchainClient_DeleteJob_Call) Return(_a0 *job.DeleteJobResponse, _a1 error) *MockOffchainClient_DeleteJob_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *MockOffchainClient_DeleteJob_Call) RunAndReturn(run func(context.Context, *job.DeleteJobRequest, ...grpc.CallOption) (*job.DeleteJobResponse, error)) *MockOffchainClient_DeleteJob_Call { - _c.Call.Return(run) - return _c -} - -// DisableNode provides a mock function with given fields: ctx, in, opts -func (_m *MockOffchainClient) DisableNode(ctx context.Context, in *node.DisableNodeRequest, opts ...grpc.CallOption) (*node.DisableNodeResponse, error) { - _va := make([]interface{}, len(opts)) - for _i := range opts { - _va[_i] = opts[_i] - } - var _ca []interface{} - _ca = append(_ca, ctx, in) - _ca = append(_ca, _va...) - ret := _m.Called(_ca...) - - if len(ret) == 0 { - panic("no return value specified for DisableNode") - } - - var r0 *node.DisableNodeResponse - var r1 error - if rf, ok := ret.Get(0).(func(context.Context, *node.DisableNodeRequest, ...grpc.CallOption) (*node.DisableNodeResponse, error)); ok { - return rf(ctx, in, opts...) - } - if rf, ok := ret.Get(0).(func(context.Context, *node.DisableNodeRequest, ...grpc.CallOption) *node.DisableNodeResponse); ok { - r0 = rf(ctx, in, opts...) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*node.DisableNodeResponse) - } - } - - if rf, ok := ret.Get(1).(func(context.Context, *node.DisableNodeRequest, ...grpc.CallOption) error); ok { - r1 = rf(ctx, in, opts...) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// MockOffchainClient_DisableNode_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'DisableNode' -type MockOffchainClient_DisableNode_Call struct { - *mock.Call -} - -// DisableNode is a helper method to define mock.On call -// - ctx context.Context -// - in *node.DisableNodeRequest -// - opts ...grpc.CallOption -func (_e *MockOffchainClient_Expecter) DisableNode(ctx interface{}, in interface{}, opts ...interface{}) *MockOffchainClient_DisableNode_Call { - return &MockOffchainClient_DisableNode_Call{Call: _e.mock.On("DisableNode", - append([]interface{}{ctx, in}, opts...)...)} -} - -func (_c *MockOffchainClient_DisableNode_Call) Run(run func(ctx context.Context, in *node.DisableNodeRequest, opts ...grpc.CallOption)) *MockOffchainClient_DisableNode_Call { - _c.Call.Run(func(args mock.Arguments) { - variadicArgs := make([]grpc.CallOption, len(args)-2) - for i, a := range args[2:] { - if a != nil { - variadicArgs[i] = a.(grpc.CallOption) - } - } - run(args[0].(context.Context), args[1].(*node.DisableNodeRequest), variadicArgs...) - }) - return _c -} - -func (_c *MockOffchainClient_DisableNode_Call) Return(_a0 *node.DisableNodeResponse, _a1 error) *MockOffchainClient_DisableNode_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *MockOffchainClient_DisableNode_Call) RunAndReturn(run func(context.Context, *node.DisableNodeRequest, ...grpc.CallOption) (*node.DisableNodeResponse, error)) *MockOffchainClient_DisableNode_Call { - _c.Call.Return(run) - return _c -} - -// EnableNode provides a mock function with given fields: ctx, in, opts -func (_m *MockOffchainClient) EnableNode(ctx context.Context, in *node.EnableNodeRequest, opts ...grpc.CallOption) (*node.EnableNodeResponse, error) { - _va := make([]interface{}, len(opts)) - for _i := range opts { - _va[_i] = opts[_i] - } - var _ca []interface{} - _ca = append(_ca, ctx, in) - _ca = append(_ca, _va...) - ret := _m.Called(_ca...) - - if len(ret) == 0 { - panic("no return value specified for EnableNode") - } - - var r0 *node.EnableNodeResponse - var r1 error - if rf, ok := ret.Get(0).(func(context.Context, *node.EnableNodeRequest, ...grpc.CallOption) (*node.EnableNodeResponse, error)); ok { - return rf(ctx, in, opts...) - } - if rf, ok := ret.Get(0).(func(context.Context, *node.EnableNodeRequest, ...grpc.CallOption) *node.EnableNodeResponse); ok { - r0 = rf(ctx, in, opts...) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*node.EnableNodeResponse) - } - } - - if rf, ok := ret.Get(1).(func(context.Context, *node.EnableNodeRequest, ...grpc.CallOption) error); ok { - r1 = rf(ctx, in, opts...) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// MockOffchainClient_EnableNode_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'EnableNode' -type MockOffchainClient_EnableNode_Call struct { - *mock.Call -} - -// EnableNode is a helper method to define mock.On call -// - ctx context.Context -// - in *node.EnableNodeRequest -// - opts ...grpc.CallOption -func (_e *MockOffchainClient_Expecter) EnableNode(ctx interface{}, in interface{}, opts ...interface{}) *MockOffchainClient_EnableNode_Call { - return &MockOffchainClient_EnableNode_Call{Call: _e.mock.On("EnableNode", - append([]interface{}{ctx, in}, opts...)...)} -} - -func (_c *MockOffchainClient_EnableNode_Call) Run(run func(ctx context.Context, in *node.EnableNodeRequest, opts ...grpc.CallOption)) *MockOffchainClient_EnableNode_Call { - _c.Call.Run(func(args mock.Arguments) { - variadicArgs := make([]grpc.CallOption, len(args)-2) - for i, a := range args[2:] { - if a != nil { - variadicArgs[i] = a.(grpc.CallOption) - } - } - run(args[0].(context.Context), args[1].(*node.EnableNodeRequest), variadicArgs...) - }) - return _c -} - -func (_c *MockOffchainClient_EnableNode_Call) Return(_a0 *node.EnableNodeResponse, _a1 error) *MockOffchainClient_EnableNode_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *MockOffchainClient_EnableNode_Call) RunAndReturn(run func(context.Context, *node.EnableNodeRequest, ...grpc.CallOption) (*node.EnableNodeResponse, error)) *MockOffchainClient_EnableNode_Call { - _c.Call.Return(run) - return _c -} - -// GetJob provides a mock function with given fields: ctx, in, opts -func (_m *MockOffchainClient) GetJob(ctx context.Context, in *job.GetJobRequest, opts ...grpc.CallOption) (*job.GetJobResponse, error) { - _va := make([]interface{}, len(opts)) - for _i := range opts { - _va[_i] = opts[_i] - } - var _ca []interface{} - _ca = append(_ca, ctx, in) - _ca = append(_ca, _va...) - ret := _m.Called(_ca...) - - if len(ret) == 0 { - panic("no return value specified for GetJob") - } - - var r0 *job.GetJobResponse - var r1 error - if rf, ok := ret.Get(0).(func(context.Context, *job.GetJobRequest, ...grpc.CallOption) (*job.GetJobResponse, error)); ok { - return rf(ctx, in, opts...) - } - if rf, ok := ret.Get(0).(func(context.Context, *job.GetJobRequest, ...grpc.CallOption) *job.GetJobResponse); ok { - r0 = rf(ctx, in, opts...) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*job.GetJobResponse) - } - } - - if rf, ok := ret.Get(1).(func(context.Context, *job.GetJobRequest, ...grpc.CallOption) error); ok { - r1 = rf(ctx, in, opts...) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// MockOffchainClient_GetJob_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetJob' -type MockOffchainClient_GetJob_Call struct { - *mock.Call -} - -// GetJob is a helper method to define mock.On call -// - ctx context.Context -// - in *job.GetJobRequest -// - opts ...grpc.CallOption -func (_e *MockOffchainClient_Expecter) GetJob(ctx interface{}, in interface{}, opts ...interface{}) *MockOffchainClient_GetJob_Call { - return &MockOffchainClient_GetJob_Call{Call: _e.mock.On("GetJob", - append([]interface{}{ctx, in}, opts...)...)} -} - -func (_c *MockOffchainClient_GetJob_Call) Run(run func(ctx context.Context, in *job.GetJobRequest, opts ...grpc.CallOption)) *MockOffchainClient_GetJob_Call { - _c.Call.Run(func(args mock.Arguments) { - variadicArgs := make([]grpc.CallOption, len(args)-2) - for i, a := range args[2:] { - if a != nil { - variadicArgs[i] = a.(grpc.CallOption) - } - } - run(args[0].(context.Context), args[1].(*job.GetJobRequest), variadicArgs...) - }) - return _c -} - -func (_c *MockOffchainClient_GetJob_Call) Return(_a0 *job.GetJobResponse, _a1 error) *MockOffchainClient_GetJob_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *MockOffchainClient_GetJob_Call) RunAndReturn(run func(context.Context, *job.GetJobRequest, ...grpc.CallOption) (*job.GetJobResponse, error)) *MockOffchainClient_GetJob_Call { - _c.Call.Return(run) - return _c -} - -// GetKeypair provides a mock function with given fields: ctx, in, opts -func (_m *MockOffchainClient) GetKeypair(ctx context.Context, in *csa.GetKeypairRequest, opts ...grpc.CallOption) (*csa.GetKeypairResponse, error) { - _va := make([]interface{}, len(opts)) - for _i := range opts { - _va[_i] = opts[_i] - } - var _ca []interface{} - _ca = append(_ca, ctx, in) - _ca = append(_ca, _va...) - ret := _m.Called(_ca...) - - if len(ret) == 0 { - panic("no return value specified for GetKeypair") - } - - var r0 *csa.GetKeypairResponse - var r1 error - if rf, ok := ret.Get(0).(func(context.Context, *csa.GetKeypairRequest, ...grpc.CallOption) (*csa.GetKeypairResponse, error)); ok { - return rf(ctx, in, opts...) - } - if rf, ok := ret.Get(0).(func(context.Context, *csa.GetKeypairRequest, ...grpc.CallOption) *csa.GetKeypairResponse); ok { - r0 = rf(ctx, in, opts...) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*csa.GetKeypairResponse) - } - } - - if rf, ok := ret.Get(1).(func(context.Context, *csa.GetKeypairRequest, ...grpc.CallOption) error); ok { - r1 = rf(ctx, in, opts...) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// MockOffchainClient_GetKeypair_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetKeypair' -type MockOffchainClient_GetKeypair_Call struct { - *mock.Call -} - -// GetKeypair is a helper method to define mock.On call -// - ctx context.Context -// - in *csa.GetKeypairRequest -// - opts ...grpc.CallOption -func (_e *MockOffchainClient_Expecter) GetKeypair(ctx interface{}, in interface{}, opts ...interface{}) *MockOffchainClient_GetKeypair_Call { - return &MockOffchainClient_GetKeypair_Call{Call: _e.mock.On("GetKeypair", - append([]interface{}{ctx, in}, opts...)...)} -} - -func (_c *MockOffchainClient_GetKeypair_Call) Run(run func(ctx context.Context, in *csa.GetKeypairRequest, opts ...grpc.CallOption)) *MockOffchainClient_GetKeypair_Call { - _c.Call.Run(func(args mock.Arguments) { - variadicArgs := make([]grpc.CallOption, len(args)-2) - for i, a := range args[2:] { - if a != nil { - variadicArgs[i] = a.(grpc.CallOption) - } - } - run(args[0].(context.Context), args[1].(*csa.GetKeypairRequest), variadicArgs...) - }) - return _c -} - -func (_c *MockOffchainClient_GetKeypair_Call) Return(_a0 *csa.GetKeypairResponse, _a1 error) *MockOffchainClient_GetKeypair_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *MockOffchainClient_GetKeypair_Call) RunAndReturn(run func(context.Context, *csa.GetKeypairRequest, ...grpc.CallOption) (*csa.GetKeypairResponse, error)) *MockOffchainClient_GetKeypair_Call { - _c.Call.Return(run) - return _c -} - -// GetNode provides a mock function with given fields: ctx, in, opts -func (_m *MockOffchainClient) GetNode(ctx context.Context, in *node.GetNodeRequest, opts ...grpc.CallOption) (*node.GetNodeResponse, error) { - _va := make([]interface{}, len(opts)) - for _i := range opts { - _va[_i] = opts[_i] - } - var _ca []interface{} - _ca = append(_ca, ctx, in) - _ca = append(_ca, _va...) - ret := _m.Called(_ca...) - - if len(ret) == 0 { - panic("no return value specified for GetNode") - } - - var r0 *node.GetNodeResponse - var r1 error - if rf, ok := ret.Get(0).(func(context.Context, *node.GetNodeRequest, ...grpc.CallOption) (*node.GetNodeResponse, error)); ok { - return rf(ctx, in, opts...) - } - if rf, ok := ret.Get(0).(func(context.Context, *node.GetNodeRequest, ...grpc.CallOption) *node.GetNodeResponse); ok { - r0 = rf(ctx, in, opts...) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*node.GetNodeResponse) - } - } - - if rf, ok := ret.Get(1).(func(context.Context, *node.GetNodeRequest, ...grpc.CallOption) error); ok { - r1 = rf(ctx, in, opts...) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// MockOffchainClient_GetNode_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetNode' -type MockOffchainClient_GetNode_Call struct { - *mock.Call -} - -// GetNode is a helper method to define mock.On call -// - ctx context.Context -// - in *node.GetNodeRequest -// - opts ...grpc.CallOption -func (_e *MockOffchainClient_Expecter) GetNode(ctx interface{}, in interface{}, opts ...interface{}) *MockOffchainClient_GetNode_Call { - return &MockOffchainClient_GetNode_Call{Call: _e.mock.On("GetNode", - append([]interface{}{ctx, in}, opts...)...)} -} - -func (_c *MockOffchainClient_GetNode_Call) Run(run func(ctx context.Context, in *node.GetNodeRequest, opts ...grpc.CallOption)) *MockOffchainClient_GetNode_Call { - _c.Call.Run(func(args mock.Arguments) { - variadicArgs := make([]grpc.CallOption, len(args)-2) - for i, a := range args[2:] { - if a != nil { - variadicArgs[i] = a.(grpc.CallOption) - } - } - run(args[0].(context.Context), args[1].(*node.GetNodeRequest), variadicArgs...) - }) - return _c -} - -func (_c *MockOffchainClient_GetNode_Call) Return(_a0 *node.GetNodeResponse, _a1 error) *MockOffchainClient_GetNode_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *MockOffchainClient_GetNode_Call) RunAndReturn(run func(context.Context, *node.GetNodeRequest, ...grpc.CallOption) (*node.GetNodeResponse, error)) *MockOffchainClient_GetNode_Call { - _c.Call.Return(run) - return _c -} - -// GetProposal provides a mock function with given fields: ctx, in, opts -func (_m *MockOffchainClient) GetProposal(ctx context.Context, in *job.GetProposalRequest, opts ...grpc.CallOption) (*job.GetProposalResponse, error) { - _va := make([]interface{}, len(opts)) - for _i := range opts { - _va[_i] = opts[_i] - } - var _ca []interface{} - _ca = append(_ca, ctx, in) - _ca = append(_ca, _va...) - ret := _m.Called(_ca...) - - if len(ret) == 0 { - panic("no return value specified for GetProposal") - } - - var r0 *job.GetProposalResponse - var r1 error - if rf, ok := ret.Get(0).(func(context.Context, *job.GetProposalRequest, ...grpc.CallOption) (*job.GetProposalResponse, error)); ok { - return rf(ctx, in, opts...) - } - if rf, ok := ret.Get(0).(func(context.Context, *job.GetProposalRequest, ...grpc.CallOption) *job.GetProposalResponse); ok { - r0 = rf(ctx, in, opts...) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*job.GetProposalResponse) - } - } - - if rf, ok := ret.Get(1).(func(context.Context, *job.GetProposalRequest, ...grpc.CallOption) error); ok { - r1 = rf(ctx, in, opts...) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// MockOffchainClient_GetProposal_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetProposal' -type MockOffchainClient_GetProposal_Call struct { - *mock.Call -} - -// GetProposal is a helper method to define mock.On call -// - ctx context.Context -// - in *job.GetProposalRequest -// - opts ...grpc.CallOption -func (_e *MockOffchainClient_Expecter) GetProposal(ctx interface{}, in interface{}, opts ...interface{}) *MockOffchainClient_GetProposal_Call { - return &MockOffchainClient_GetProposal_Call{Call: _e.mock.On("GetProposal", - append([]interface{}{ctx, in}, opts...)...)} -} - -func (_c *MockOffchainClient_GetProposal_Call) Run(run func(ctx context.Context, in *job.GetProposalRequest, opts ...grpc.CallOption)) *MockOffchainClient_GetProposal_Call { - _c.Call.Run(func(args mock.Arguments) { - variadicArgs := make([]grpc.CallOption, len(args)-2) - for i, a := range args[2:] { - if a != nil { - variadicArgs[i] = a.(grpc.CallOption) - } - } - run(args[0].(context.Context), args[1].(*job.GetProposalRequest), variadicArgs...) - }) - return _c -} - -func (_c *MockOffchainClient_GetProposal_Call) Return(_a0 *job.GetProposalResponse, _a1 error) *MockOffchainClient_GetProposal_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *MockOffchainClient_GetProposal_Call) RunAndReturn(run func(context.Context, *job.GetProposalRequest, ...grpc.CallOption) (*job.GetProposalResponse, error)) *MockOffchainClient_GetProposal_Call { - _c.Call.Return(run) - return _c -} - -// ListJobs provides a mock function with given fields: ctx, in, opts -func (_m *MockOffchainClient) ListJobs(ctx context.Context, in *job.ListJobsRequest, opts ...grpc.CallOption) (*job.ListJobsResponse, error) { - _va := make([]interface{}, len(opts)) - for _i := range opts { - _va[_i] = opts[_i] - } - var _ca []interface{} - _ca = append(_ca, ctx, in) - _ca = append(_ca, _va...) - ret := _m.Called(_ca...) - - if len(ret) == 0 { - panic("no return value specified for ListJobs") - } - - var r0 *job.ListJobsResponse - var r1 error - if rf, ok := ret.Get(0).(func(context.Context, *job.ListJobsRequest, ...grpc.CallOption) (*job.ListJobsResponse, error)); ok { - return rf(ctx, in, opts...) - } - if rf, ok := ret.Get(0).(func(context.Context, *job.ListJobsRequest, ...grpc.CallOption) *job.ListJobsResponse); ok { - r0 = rf(ctx, in, opts...) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*job.ListJobsResponse) - } - } - - if rf, ok := ret.Get(1).(func(context.Context, *job.ListJobsRequest, ...grpc.CallOption) error); ok { - r1 = rf(ctx, in, opts...) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// MockOffchainClient_ListJobs_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ListJobs' -type MockOffchainClient_ListJobs_Call struct { - *mock.Call -} - -// ListJobs is a helper method to define mock.On call -// - ctx context.Context -// - in *job.ListJobsRequest -// - opts ...grpc.CallOption -func (_e *MockOffchainClient_Expecter) ListJobs(ctx interface{}, in interface{}, opts ...interface{}) *MockOffchainClient_ListJobs_Call { - return &MockOffchainClient_ListJobs_Call{Call: _e.mock.On("ListJobs", - append([]interface{}{ctx, in}, opts...)...)} -} - -func (_c *MockOffchainClient_ListJobs_Call) Run(run func(ctx context.Context, in *job.ListJobsRequest, opts ...grpc.CallOption)) *MockOffchainClient_ListJobs_Call { - _c.Call.Run(func(args mock.Arguments) { - variadicArgs := make([]grpc.CallOption, len(args)-2) - for i, a := range args[2:] { - if a != nil { - variadicArgs[i] = a.(grpc.CallOption) - } - } - run(args[0].(context.Context), args[1].(*job.ListJobsRequest), variadicArgs...) - }) - return _c -} - -func (_c *MockOffchainClient_ListJobs_Call) Return(_a0 *job.ListJobsResponse, _a1 error) *MockOffchainClient_ListJobs_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *MockOffchainClient_ListJobs_Call) RunAndReturn(run func(context.Context, *job.ListJobsRequest, ...grpc.CallOption) (*job.ListJobsResponse, error)) *MockOffchainClient_ListJobs_Call { - _c.Call.Return(run) - return _c -} - -// ListKeypairs provides a mock function with given fields: ctx, in, opts -func (_m *MockOffchainClient) ListKeypairs(ctx context.Context, in *csa.ListKeypairsRequest, opts ...grpc.CallOption) (*csa.ListKeypairsResponse, error) { - _va := make([]interface{}, len(opts)) - for _i := range opts { - _va[_i] = opts[_i] - } - var _ca []interface{} - _ca = append(_ca, ctx, in) - _ca = append(_ca, _va...) - ret := _m.Called(_ca...) - - if len(ret) == 0 { - panic("no return value specified for ListKeypairs") - } - - var r0 *csa.ListKeypairsResponse - var r1 error - if rf, ok := ret.Get(0).(func(context.Context, *csa.ListKeypairsRequest, ...grpc.CallOption) (*csa.ListKeypairsResponse, error)); ok { - return rf(ctx, in, opts...) - } - if rf, ok := ret.Get(0).(func(context.Context, *csa.ListKeypairsRequest, ...grpc.CallOption) *csa.ListKeypairsResponse); ok { - r0 = rf(ctx, in, opts...) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*csa.ListKeypairsResponse) - } - } - - if rf, ok := ret.Get(1).(func(context.Context, *csa.ListKeypairsRequest, ...grpc.CallOption) error); ok { - r1 = rf(ctx, in, opts...) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// MockOffchainClient_ListKeypairs_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ListKeypairs' -type MockOffchainClient_ListKeypairs_Call struct { - *mock.Call -} - -// ListKeypairs is a helper method to define mock.On call -// - ctx context.Context -// - in *csa.ListKeypairsRequest -// - opts ...grpc.CallOption -func (_e *MockOffchainClient_Expecter) ListKeypairs(ctx interface{}, in interface{}, opts ...interface{}) *MockOffchainClient_ListKeypairs_Call { - return &MockOffchainClient_ListKeypairs_Call{Call: _e.mock.On("ListKeypairs", - append([]interface{}{ctx, in}, opts...)...)} -} - -func (_c *MockOffchainClient_ListKeypairs_Call) Run(run func(ctx context.Context, in *csa.ListKeypairsRequest, opts ...grpc.CallOption)) *MockOffchainClient_ListKeypairs_Call { - _c.Call.Run(func(args mock.Arguments) { - variadicArgs := make([]grpc.CallOption, len(args)-2) - for i, a := range args[2:] { - if a != nil { - variadicArgs[i] = a.(grpc.CallOption) - } - } - run(args[0].(context.Context), args[1].(*csa.ListKeypairsRequest), variadicArgs...) - }) - return _c -} - -func (_c *MockOffchainClient_ListKeypairs_Call) Return(_a0 *csa.ListKeypairsResponse, _a1 error) *MockOffchainClient_ListKeypairs_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *MockOffchainClient_ListKeypairs_Call) RunAndReturn(run func(context.Context, *csa.ListKeypairsRequest, ...grpc.CallOption) (*csa.ListKeypairsResponse, error)) *MockOffchainClient_ListKeypairs_Call { - _c.Call.Return(run) - return _c -} - -// ListNodeChainConfigs provides a mock function with given fields: ctx, in, opts -func (_m *MockOffchainClient) ListNodeChainConfigs(ctx context.Context, in *node.ListNodeChainConfigsRequest, opts ...grpc.CallOption) (*node.ListNodeChainConfigsResponse, error) { - _va := make([]interface{}, len(opts)) - for _i := range opts { - _va[_i] = opts[_i] - } - var _ca []interface{} - _ca = append(_ca, ctx, in) - _ca = append(_ca, _va...) - ret := _m.Called(_ca...) - - if len(ret) == 0 { - panic("no return value specified for ListNodeChainConfigs") - } - - var r0 *node.ListNodeChainConfigsResponse - var r1 error - if rf, ok := ret.Get(0).(func(context.Context, *node.ListNodeChainConfigsRequest, ...grpc.CallOption) (*node.ListNodeChainConfigsResponse, error)); ok { - return rf(ctx, in, opts...) - } - if rf, ok := ret.Get(0).(func(context.Context, *node.ListNodeChainConfigsRequest, ...grpc.CallOption) *node.ListNodeChainConfigsResponse); ok { - r0 = rf(ctx, in, opts...) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*node.ListNodeChainConfigsResponse) - } - } - - if rf, ok := ret.Get(1).(func(context.Context, *node.ListNodeChainConfigsRequest, ...grpc.CallOption) error); ok { - r1 = rf(ctx, in, opts...) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// MockOffchainClient_ListNodeChainConfigs_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ListNodeChainConfigs' -type MockOffchainClient_ListNodeChainConfigs_Call struct { - *mock.Call -} - -// ListNodeChainConfigs is a helper method to define mock.On call -// - ctx context.Context -// - in *node.ListNodeChainConfigsRequest -// - opts ...grpc.CallOption -func (_e *MockOffchainClient_Expecter) ListNodeChainConfigs(ctx interface{}, in interface{}, opts ...interface{}) *MockOffchainClient_ListNodeChainConfigs_Call { - return &MockOffchainClient_ListNodeChainConfigs_Call{Call: _e.mock.On("ListNodeChainConfigs", - append([]interface{}{ctx, in}, opts...)...)} -} - -func (_c *MockOffchainClient_ListNodeChainConfigs_Call) Run(run func(ctx context.Context, in *node.ListNodeChainConfigsRequest, opts ...grpc.CallOption)) *MockOffchainClient_ListNodeChainConfigs_Call { - _c.Call.Run(func(args mock.Arguments) { - variadicArgs := make([]grpc.CallOption, len(args)-2) - for i, a := range args[2:] { - if a != nil { - variadicArgs[i] = a.(grpc.CallOption) - } - } - run(args[0].(context.Context), args[1].(*node.ListNodeChainConfigsRequest), variadicArgs...) - }) - return _c -} - -func (_c *MockOffchainClient_ListNodeChainConfigs_Call) Return(_a0 *node.ListNodeChainConfigsResponse, _a1 error) *MockOffchainClient_ListNodeChainConfigs_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *MockOffchainClient_ListNodeChainConfigs_Call) RunAndReturn(run func(context.Context, *node.ListNodeChainConfigsRequest, ...grpc.CallOption) (*node.ListNodeChainConfigsResponse, error)) *MockOffchainClient_ListNodeChainConfigs_Call { - _c.Call.Return(run) - return _c -} - -// ListNodes provides a mock function with given fields: ctx, in, opts -func (_m *MockOffchainClient) ListNodes(ctx context.Context, in *node.ListNodesRequest, opts ...grpc.CallOption) (*node.ListNodesResponse, error) { - _va := make([]interface{}, len(opts)) - for _i := range opts { - _va[_i] = opts[_i] - } - var _ca []interface{} - _ca = append(_ca, ctx, in) - _ca = append(_ca, _va...) - ret := _m.Called(_ca...) - - if len(ret) == 0 { - panic("no return value specified for ListNodes") - } - - var r0 *node.ListNodesResponse - var r1 error - if rf, ok := ret.Get(0).(func(context.Context, *node.ListNodesRequest, ...grpc.CallOption) (*node.ListNodesResponse, error)); ok { - return rf(ctx, in, opts...) - } - if rf, ok := ret.Get(0).(func(context.Context, *node.ListNodesRequest, ...grpc.CallOption) *node.ListNodesResponse); ok { - r0 = rf(ctx, in, opts...) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*node.ListNodesResponse) - } - } - - if rf, ok := ret.Get(1).(func(context.Context, *node.ListNodesRequest, ...grpc.CallOption) error); ok { - r1 = rf(ctx, in, opts...) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// MockOffchainClient_ListNodes_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ListNodes' -type MockOffchainClient_ListNodes_Call struct { - *mock.Call -} - -// ListNodes is a helper method to define mock.On call -// - ctx context.Context -// - in *node.ListNodesRequest -// - opts ...grpc.CallOption -func (_e *MockOffchainClient_Expecter) ListNodes(ctx interface{}, in interface{}, opts ...interface{}) *MockOffchainClient_ListNodes_Call { - return &MockOffchainClient_ListNodes_Call{Call: _e.mock.On("ListNodes", - append([]interface{}{ctx, in}, opts...)...)} -} - -func (_c *MockOffchainClient_ListNodes_Call) Run(run func(ctx context.Context, in *node.ListNodesRequest, opts ...grpc.CallOption)) *MockOffchainClient_ListNodes_Call { - _c.Call.Run(func(args mock.Arguments) { - variadicArgs := make([]grpc.CallOption, len(args)-2) - for i, a := range args[2:] { - if a != nil { - variadicArgs[i] = a.(grpc.CallOption) - } - } - run(args[0].(context.Context), args[1].(*node.ListNodesRequest), variadicArgs...) - }) - return _c -} - -func (_c *MockOffchainClient_ListNodes_Call) Return(_a0 *node.ListNodesResponse, _a1 error) *MockOffchainClient_ListNodes_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *MockOffchainClient_ListNodes_Call) RunAndReturn(run func(context.Context, *node.ListNodesRequest, ...grpc.CallOption) (*node.ListNodesResponse, error)) *MockOffchainClient_ListNodes_Call { - _c.Call.Return(run) - return _c -} - -// ListProposals provides a mock function with given fields: ctx, in, opts -func (_m *MockOffchainClient) ListProposals(ctx context.Context, in *job.ListProposalsRequest, opts ...grpc.CallOption) (*job.ListProposalsResponse, error) { - _va := make([]interface{}, len(opts)) - for _i := range opts { - _va[_i] = opts[_i] - } - var _ca []interface{} - _ca = append(_ca, ctx, in) - _ca = append(_ca, _va...) - ret := _m.Called(_ca...) - - if len(ret) == 0 { - panic("no return value specified for ListProposals") - } - - var r0 *job.ListProposalsResponse - var r1 error - if rf, ok := ret.Get(0).(func(context.Context, *job.ListProposalsRequest, ...grpc.CallOption) (*job.ListProposalsResponse, error)); ok { - return rf(ctx, in, opts...) - } - if rf, ok := ret.Get(0).(func(context.Context, *job.ListProposalsRequest, ...grpc.CallOption) *job.ListProposalsResponse); ok { - r0 = rf(ctx, in, opts...) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*job.ListProposalsResponse) - } - } - - if rf, ok := ret.Get(1).(func(context.Context, *job.ListProposalsRequest, ...grpc.CallOption) error); ok { - r1 = rf(ctx, in, opts...) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// MockOffchainClient_ListProposals_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ListProposals' -type MockOffchainClient_ListProposals_Call struct { - *mock.Call -} - -// ListProposals is a helper method to define mock.On call -// - ctx context.Context -// - in *job.ListProposalsRequest -// - opts ...grpc.CallOption -func (_e *MockOffchainClient_Expecter) ListProposals(ctx interface{}, in interface{}, opts ...interface{}) *MockOffchainClient_ListProposals_Call { - return &MockOffchainClient_ListProposals_Call{Call: _e.mock.On("ListProposals", - append([]interface{}{ctx, in}, opts...)...)} -} - -func (_c *MockOffchainClient_ListProposals_Call) Run(run func(ctx context.Context, in *job.ListProposalsRequest, opts ...grpc.CallOption)) *MockOffchainClient_ListProposals_Call { - _c.Call.Run(func(args mock.Arguments) { - variadicArgs := make([]grpc.CallOption, len(args)-2) - for i, a := range args[2:] { - if a != nil { - variadicArgs[i] = a.(grpc.CallOption) - } - } - run(args[0].(context.Context), args[1].(*job.ListProposalsRequest), variadicArgs...) - }) - return _c -} - -func (_c *MockOffchainClient_ListProposals_Call) Return(_a0 *job.ListProposalsResponse, _a1 error) *MockOffchainClient_ListProposals_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *MockOffchainClient_ListProposals_Call) RunAndReturn(run func(context.Context, *job.ListProposalsRequest, ...grpc.CallOption) (*job.ListProposalsResponse, error)) *MockOffchainClient_ListProposals_Call { - _c.Call.Return(run) - return _c -} - -// ProposeJob provides a mock function with given fields: ctx, in, opts -func (_m *MockOffchainClient) ProposeJob(ctx context.Context, in *job.ProposeJobRequest, opts ...grpc.CallOption) (*job.ProposeJobResponse, error) { - _va := make([]interface{}, len(opts)) - for _i := range opts { - _va[_i] = opts[_i] - } - var _ca []interface{} - _ca = append(_ca, ctx, in) - _ca = append(_ca, _va...) - ret := _m.Called(_ca...) - - if len(ret) == 0 { - panic("no return value specified for ProposeJob") - } - - var r0 *job.ProposeJobResponse - var r1 error - if rf, ok := ret.Get(0).(func(context.Context, *job.ProposeJobRequest, ...grpc.CallOption) (*job.ProposeJobResponse, error)); ok { - return rf(ctx, in, opts...) - } - if rf, ok := ret.Get(0).(func(context.Context, *job.ProposeJobRequest, ...grpc.CallOption) *job.ProposeJobResponse); ok { - r0 = rf(ctx, in, opts...) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*job.ProposeJobResponse) - } - } - - if rf, ok := ret.Get(1).(func(context.Context, *job.ProposeJobRequest, ...grpc.CallOption) error); ok { - r1 = rf(ctx, in, opts...) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// MockOffchainClient_ProposeJob_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ProposeJob' -type MockOffchainClient_ProposeJob_Call struct { - *mock.Call -} - -// ProposeJob is a helper method to define mock.On call -// - ctx context.Context -// - in *job.ProposeJobRequest -// - opts ...grpc.CallOption -func (_e *MockOffchainClient_Expecter) ProposeJob(ctx interface{}, in interface{}, opts ...interface{}) *MockOffchainClient_ProposeJob_Call { - return &MockOffchainClient_ProposeJob_Call{Call: _e.mock.On("ProposeJob", - append([]interface{}{ctx, in}, opts...)...)} -} - -func (_c *MockOffchainClient_ProposeJob_Call) Run(run func(ctx context.Context, in *job.ProposeJobRequest, opts ...grpc.CallOption)) *MockOffchainClient_ProposeJob_Call { - _c.Call.Run(func(args mock.Arguments) { - variadicArgs := make([]grpc.CallOption, len(args)-2) - for i, a := range args[2:] { - if a != nil { - variadicArgs[i] = a.(grpc.CallOption) - } - } - run(args[0].(context.Context), args[1].(*job.ProposeJobRequest), variadicArgs...) - }) - return _c -} - -func (_c *MockOffchainClient_ProposeJob_Call) Return(_a0 *job.ProposeJobResponse, _a1 error) *MockOffchainClient_ProposeJob_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *MockOffchainClient_ProposeJob_Call) RunAndReturn(run func(context.Context, *job.ProposeJobRequest, ...grpc.CallOption) (*job.ProposeJobResponse, error)) *MockOffchainClient_ProposeJob_Call { - _c.Call.Return(run) - return _c -} - -// RegisterNode provides a mock function with given fields: ctx, in, opts -func (_m *MockOffchainClient) RegisterNode(ctx context.Context, in *node.RegisterNodeRequest, opts ...grpc.CallOption) (*node.RegisterNodeResponse, error) { - _va := make([]interface{}, len(opts)) - for _i := range opts { - _va[_i] = opts[_i] - } - var _ca []interface{} - _ca = append(_ca, ctx, in) - _ca = append(_ca, _va...) - ret := _m.Called(_ca...) - - if len(ret) == 0 { - panic("no return value specified for RegisterNode") - } - - var r0 *node.RegisterNodeResponse - var r1 error - if rf, ok := ret.Get(0).(func(context.Context, *node.RegisterNodeRequest, ...grpc.CallOption) (*node.RegisterNodeResponse, error)); ok { - return rf(ctx, in, opts...) - } - if rf, ok := ret.Get(0).(func(context.Context, *node.RegisterNodeRequest, ...grpc.CallOption) *node.RegisterNodeResponse); ok { - r0 = rf(ctx, in, opts...) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*node.RegisterNodeResponse) - } - } - - if rf, ok := ret.Get(1).(func(context.Context, *node.RegisterNodeRequest, ...grpc.CallOption) error); ok { - r1 = rf(ctx, in, opts...) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// MockOffchainClient_RegisterNode_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'RegisterNode' -type MockOffchainClient_RegisterNode_Call struct { - *mock.Call -} - -// RegisterNode is a helper method to define mock.On call -// - ctx context.Context -// - in *node.RegisterNodeRequest -// - opts ...grpc.CallOption -func (_e *MockOffchainClient_Expecter) RegisterNode(ctx interface{}, in interface{}, opts ...interface{}) *MockOffchainClient_RegisterNode_Call { - return &MockOffchainClient_RegisterNode_Call{Call: _e.mock.On("RegisterNode", - append([]interface{}{ctx, in}, opts...)...)} -} - -func (_c *MockOffchainClient_RegisterNode_Call) Run(run func(ctx context.Context, in *node.RegisterNodeRequest, opts ...grpc.CallOption)) *MockOffchainClient_RegisterNode_Call { - _c.Call.Run(func(args mock.Arguments) { - variadicArgs := make([]grpc.CallOption, len(args)-2) - for i, a := range args[2:] { - if a != nil { - variadicArgs[i] = a.(grpc.CallOption) - } - } - run(args[0].(context.Context), args[1].(*node.RegisterNodeRequest), variadicArgs...) - }) - return _c -} - -func (_c *MockOffchainClient_RegisterNode_Call) Return(_a0 *node.RegisterNodeResponse, _a1 error) *MockOffchainClient_RegisterNode_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *MockOffchainClient_RegisterNode_Call) RunAndReturn(run func(context.Context, *node.RegisterNodeRequest, ...grpc.CallOption) (*node.RegisterNodeResponse, error)) *MockOffchainClient_RegisterNode_Call { - _c.Call.Return(run) - return _c -} - -// RevokeJob provides a mock function with given fields: ctx, in, opts -func (_m *MockOffchainClient) RevokeJob(ctx context.Context, in *job.RevokeJobRequest, opts ...grpc.CallOption) (*job.RevokeJobResponse, error) { - _va := make([]interface{}, len(opts)) - for _i := range opts { - _va[_i] = opts[_i] - } - var _ca []interface{} - _ca = append(_ca, ctx, in) - _ca = append(_ca, _va...) - ret := _m.Called(_ca...) - - if len(ret) == 0 { - panic("no return value specified for RevokeJob") - } - - var r0 *job.RevokeJobResponse - var r1 error - if rf, ok := ret.Get(0).(func(context.Context, *job.RevokeJobRequest, ...grpc.CallOption) (*job.RevokeJobResponse, error)); ok { - return rf(ctx, in, opts...) - } - if rf, ok := ret.Get(0).(func(context.Context, *job.RevokeJobRequest, ...grpc.CallOption) *job.RevokeJobResponse); ok { - r0 = rf(ctx, in, opts...) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*job.RevokeJobResponse) - } - } - - if rf, ok := ret.Get(1).(func(context.Context, *job.RevokeJobRequest, ...grpc.CallOption) error); ok { - r1 = rf(ctx, in, opts...) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// MockOffchainClient_RevokeJob_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'RevokeJob' -type MockOffchainClient_RevokeJob_Call struct { - *mock.Call -} - -// RevokeJob is a helper method to define mock.On call -// - ctx context.Context -// - in *job.RevokeJobRequest -// - opts ...grpc.CallOption -func (_e *MockOffchainClient_Expecter) RevokeJob(ctx interface{}, in interface{}, opts ...interface{}) *MockOffchainClient_RevokeJob_Call { - return &MockOffchainClient_RevokeJob_Call{Call: _e.mock.On("RevokeJob", - append([]interface{}{ctx, in}, opts...)...)} -} - -func (_c *MockOffchainClient_RevokeJob_Call) Run(run func(ctx context.Context, in *job.RevokeJobRequest, opts ...grpc.CallOption)) *MockOffchainClient_RevokeJob_Call { - _c.Call.Run(func(args mock.Arguments) { - variadicArgs := make([]grpc.CallOption, len(args)-2) - for i, a := range args[2:] { - if a != nil { - variadicArgs[i] = a.(grpc.CallOption) - } - } - run(args[0].(context.Context), args[1].(*job.RevokeJobRequest), variadicArgs...) - }) - return _c -} - -func (_c *MockOffchainClient_RevokeJob_Call) Return(_a0 *job.RevokeJobResponse, _a1 error) *MockOffchainClient_RevokeJob_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *MockOffchainClient_RevokeJob_Call) RunAndReturn(run func(context.Context, *job.RevokeJobRequest, ...grpc.CallOption) (*job.RevokeJobResponse, error)) *MockOffchainClient_RevokeJob_Call { - _c.Call.Return(run) - return _c -} - -// UpdateJob provides a mock function with given fields: ctx, in, opts -func (_m *MockOffchainClient) UpdateJob(ctx context.Context, in *job.UpdateJobRequest, opts ...grpc.CallOption) (*job.UpdateJobResponse, error) { - _va := make([]interface{}, len(opts)) - for _i := range opts { - _va[_i] = opts[_i] - } - var _ca []interface{} - _ca = append(_ca, ctx, in) - _ca = append(_ca, _va...) - ret := _m.Called(_ca...) - - if len(ret) == 0 { - panic("no return value specified for UpdateJob") - } - - var r0 *job.UpdateJobResponse - var r1 error - if rf, ok := ret.Get(0).(func(context.Context, *job.UpdateJobRequest, ...grpc.CallOption) (*job.UpdateJobResponse, error)); ok { - return rf(ctx, in, opts...) - } - if rf, ok := ret.Get(0).(func(context.Context, *job.UpdateJobRequest, ...grpc.CallOption) *job.UpdateJobResponse); ok { - r0 = rf(ctx, in, opts...) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*job.UpdateJobResponse) - } - } - - if rf, ok := ret.Get(1).(func(context.Context, *job.UpdateJobRequest, ...grpc.CallOption) error); ok { - r1 = rf(ctx, in, opts...) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// MockOffchainClient_UpdateJob_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'UpdateJob' -type MockOffchainClient_UpdateJob_Call struct { - *mock.Call -} - -// UpdateJob is a helper method to define mock.On call -// - ctx context.Context -// - in *job.UpdateJobRequest -// - opts ...grpc.CallOption -func (_e *MockOffchainClient_Expecter) UpdateJob(ctx interface{}, in interface{}, opts ...interface{}) *MockOffchainClient_UpdateJob_Call { - return &MockOffchainClient_UpdateJob_Call{Call: _e.mock.On("UpdateJob", - append([]interface{}{ctx, in}, opts...)...)} -} - -func (_c *MockOffchainClient_UpdateJob_Call) Run(run func(ctx context.Context, in *job.UpdateJobRequest, opts ...grpc.CallOption)) *MockOffchainClient_UpdateJob_Call { - _c.Call.Run(func(args mock.Arguments) { - variadicArgs := make([]grpc.CallOption, len(args)-2) - for i, a := range args[2:] { - if a != nil { - variadicArgs[i] = a.(grpc.CallOption) - } - } - run(args[0].(context.Context), args[1].(*job.UpdateJobRequest), variadicArgs...) - }) - return _c -} - -func (_c *MockOffchainClient_UpdateJob_Call) Return(_a0 *job.UpdateJobResponse, _a1 error) *MockOffchainClient_UpdateJob_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *MockOffchainClient_UpdateJob_Call) RunAndReturn(run func(context.Context, *job.UpdateJobRequest, ...grpc.CallOption) (*job.UpdateJobResponse, error)) *MockOffchainClient_UpdateJob_Call { - _c.Call.Return(run) - return _c -} - -// UpdateNode provides a mock function with given fields: ctx, in, opts -func (_m *MockOffchainClient) UpdateNode(ctx context.Context, in *node.UpdateNodeRequest, opts ...grpc.CallOption) (*node.UpdateNodeResponse, error) { - _va := make([]interface{}, len(opts)) - for _i := range opts { - _va[_i] = opts[_i] - } - var _ca []interface{} - _ca = append(_ca, ctx, in) - _ca = append(_ca, _va...) - ret := _m.Called(_ca...) - - if len(ret) == 0 { - panic("no return value specified for UpdateNode") - } - - var r0 *node.UpdateNodeResponse - var r1 error - if rf, ok := ret.Get(0).(func(context.Context, *node.UpdateNodeRequest, ...grpc.CallOption) (*node.UpdateNodeResponse, error)); ok { - return rf(ctx, in, opts...) - } - if rf, ok := ret.Get(0).(func(context.Context, *node.UpdateNodeRequest, ...grpc.CallOption) *node.UpdateNodeResponse); ok { - r0 = rf(ctx, in, opts...) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*node.UpdateNodeResponse) - } - } - - if rf, ok := ret.Get(1).(func(context.Context, *node.UpdateNodeRequest, ...grpc.CallOption) error); ok { - r1 = rf(ctx, in, opts...) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// MockOffchainClient_UpdateNode_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'UpdateNode' -type MockOffchainClient_UpdateNode_Call struct { - *mock.Call -} - -// UpdateNode is a helper method to define mock.On call -// - ctx context.Context -// - in *node.UpdateNodeRequest -// - opts ...grpc.CallOption -func (_e *MockOffchainClient_Expecter) UpdateNode(ctx interface{}, in interface{}, opts ...interface{}) *MockOffchainClient_UpdateNode_Call { - return &MockOffchainClient_UpdateNode_Call{Call: _e.mock.On("UpdateNode", - append([]interface{}{ctx, in}, opts...)...)} -} - -func (_c *MockOffchainClient_UpdateNode_Call) Run(run func(ctx context.Context, in *node.UpdateNodeRequest, opts ...grpc.CallOption)) *MockOffchainClient_UpdateNode_Call { - _c.Call.Run(func(args mock.Arguments) { - variadicArgs := make([]grpc.CallOption, len(args)-2) - for i, a := range args[2:] { - if a != nil { - variadicArgs[i] = a.(grpc.CallOption) - } - } - run(args[0].(context.Context), args[1].(*node.UpdateNodeRequest), variadicArgs...) - }) - return _c -} - -func (_c *MockOffchainClient_UpdateNode_Call) Return(_a0 *node.UpdateNodeResponse, _a1 error) *MockOffchainClient_UpdateNode_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *MockOffchainClient_UpdateNode_Call) RunAndReturn(run func(context.Context, *node.UpdateNodeRequest, ...grpc.CallOption) (*node.UpdateNodeResponse, error)) *MockOffchainClient_UpdateNode_Call { - _c.Call.Return(run) - return _c -} - -// NewMockOffchainClient creates a new instance of MockOffchainClient. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. -// The first argument is typically a *testing.T value. -func NewMockOffchainClient(t interface { - mock.TestingT - Cleanup(func()) -}) *MockOffchainClient { - mock := &MockOffchainClient{} - mock.Mock.Test(t) - - t.Cleanup(func() { mock.AssertExpectations(t) }) - - return mock -} diff --git a/deployment/multiclient.go b/deployment/multiclient.go index 9765e0368ea..dcda07ebb0b 100644 --- a/deployment/multiclient.go +++ b/deployment/multiclient.go @@ -12,7 +12,6 @@ import ( "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/ethclient" "github.com/pkg/errors" - chainselectors "github.com/smartcontractkit/chain-selectors" "github.com/smartcontractkit/chainlink-common/pkg/logger" ) @@ -47,7 +46,6 @@ type MultiClient struct { Backups []*ethclient.Client RetryConfig RetryConfig lggr logger.Logger - chainName string } func NewMultiClient(lggr logger.Logger, rpcs []RPC, opts ...func(client *MultiClient)) (*MultiClient, error) { @@ -61,15 +59,6 @@ func NewMultiClient(lggr logger.Logger, rpcs []RPC, opts ...func(client *MultiCl if err != nil { return nil, fmt.Errorf("failed to dial ws url '%s': %w", rpc.WSURL, err) } - id, err := client.ChainID(context.Background()) - if err != nil { - return nil, fmt.Errorf("failed to get chain id: %w", err) - } - details, err := chainselectors.GetChainDetailsByChainIDAndFamily(id.String(), chainselectors.FamilyEVM) - if err != nil { - return nil, fmt.Errorf("failed to lookup chain details %w", err) - } - mc.chainName = details.ChainName clients = append(clients, client) } mc.Client = clients[0] @@ -109,16 +98,16 @@ func (mc *MultiClient) NonceAt(ctx context.Context, account common.Address, bloc } func (mc *MultiClient) WaitMined(ctx context.Context, tx *types.Transaction) (*types.Receipt, error) { - mc.lggr.Debugf("Waiting for tx %s to be mined for chain %s", tx.Hash().Hex(), mc.chainName) + mc.lggr.Debugf("Waiting for tx %s to be mined", tx.Hash().Hex()) // no retries here because we want to wait for the tx to be mined resultCh := make(chan *types.Receipt) doneCh := make(chan struct{}) waitMined := func(client *ethclient.Client, tx *types.Transaction) { - mc.lggr.Debugf("Waiting for tx %s to be mined with chain %s", tx.Hash().Hex(), mc.chainName) + mc.lggr.Debugf("Waiting for tx %s to be mined with client %v", tx.Hash().Hex(), client) receipt, err := bind.WaitMined(ctx, client, tx) if err != nil { - mc.lggr.Warnf("WaitMined error %v with chain %s", err, mc.chainName) + mc.lggr.Warnf("WaitMined error %v with client %v", err, client) return } select { @@ -135,7 +124,6 @@ func (mc *MultiClient) WaitMined(ctx context.Context, tx *types.Transaction) (*t select { case receipt = <-resultCh: close(doneCh) - mc.lggr.Debugf("Tx %s mined with chain %s", tx.Hash().Hex(), mc.chainName) return receipt, nil case <-ctx.Done(): mc.lggr.Warnf("WaitMined context done %v", ctx.Err()) @@ -146,12 +134,11 @@ func (mc *MultiClient) WaitMined(ctx context.Context, tx *types.Transaction) (*t func (mc *MultiClient) retryWithBackups(opName string, op func(*ethclient.Client) error) error { var err error - for i, client := range append([]*ethclient.Client{mc.Client}, mc.Backups...) { + for _, client := range append([]*ethclient.Client{mc.Client}, mc.Backups...) { err2 := retry.Do(func() error { - mc.lggr.Debugf("Trying op %s with chain %s client index %d", opName, mc.chainName, i) err = op(client) if err != nil { - mc.lggr.Warnf("retryable error '%s' for op %s with chain %s client index %d", err.Error(), opName, mc.chainName, i) + mc.lggr.Warnf("retryable error '%s' for op %s with client %v", err.Error(), opName, client) return err } return nil @@ -159,7 +146,7 @@ func (mc *MultiClient) retryWithBackups(opName string, op func(*ethclient.Client if err2 == nil { return nil } - mc.lggr.Infof("Client at index %d failed, trying next client chain %s", i, mc.chainName) + mc.lggr.Infof("Client %v failed, trying next client", client) } - return errors.Wrapf(err, "All backup clients %v failed for chain %s", mc.Backups, mc.chainName) + return errors.Wrapf(err, "All backup clients %v failed", mc.Backups) } diff --git a/deployment/multiclient_test.go b/deployment/multiclient_test.go index 2e10c46e33f..0dbebbe3a6a 100644 --- a/deployment/multiclient_test.go +++ b/deployment/multiclient_test.go @@ -1,7 +1,6 @@ package deployment import ( - "io/ioutil" "net/http" "net/http/httptest" "testing" @@ -16,33 +15,20 @@ func TestMultiClient(t *testing.T) { lggr := logger.TestLogger(t) // Expect an error if no RPCs supplied. s := httptest.NewServer(http.HandlerFunc(func(writer http.ResponseWriter, request *http.Request) { - b, err := ioutil.ReadAll(request.Body) + writer.WriteHeader(http.StatusOK) + _, err := writer.Write([]byte(`{"jsonrpc":"2.0","id":1,"result":true}`)) require.NoError(t, err) - // TODO: Helper struct somewhere for this? - if string(b) == "{\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"eth_chainId\"}" { - writer.WriteHeader(http.StatusOK) - // Respond with 1337 - _, err = writer.Write([]byte(`{"jsonrpc":"2.0","id":1,"result":"0x539"}`)) - require.NoError(t, err) - return - } else { - // Dial - writer.WriteHeader(http.StatusOK) - _, err = writer.Write([]byte(`{"jsonrpc":"2.0","id":1,"result":true}`)) - require.NoError(t, err) - } })) defer s.Close() + _, err := NewMultiClient(lggr, []RPC{}) + require.Error(t, err) + // Expect defaults to be set if not provided. mc, err := NewMultiClient(lggr, []RPC{{WSURL: s.URL}}) require.NoError(t, err) - require.NotNil(t, mc) assert.Equal(t, mc.RetryConfig.Attempts, uint(RPC_DEFAULT_RETRY_ATTEMPTS)) assert.Equal(t, mc.RetryConfig.Delay, RPC_DEFAULT_RETRY_DELAY) - _, err = NewMultiClient(lggr, []RPC{}) - require.Error(t, err) - // Expect second client to be set as backup. mc, err = NewMultiClient(lggr, []RPC{ {WSURL: s.URL}, diff --git a/deployment/solana_chain.go b/deployment/solana_chain.go deleted file mode 100644 index 338642e3e32..00000000000 --- a/deployment/solana_chain.go +++ /dev/null @@ -1,5 +0,0 @@ -package deployment - -// SolChain represents a Solana chain. -type SolChain struct { -} diff --git a/docs/CONFIG.md b/docs/CONFIG.md index f624016b354..ff918468c07 100644 --- a/docs/CONFIG.md +++ b/docs/CONFIG.md @@ -1213,33 +1213,6 @@ ListenAddresses = ['1.2.3.4:9999', '[a52d:0:a88:1274::abcd]:1337'] # Example ListenAddresses is the addresses the peer will listen to on the network in `host:port` form as accepted by `net.Listen()`, but the host and port must be fully specified and cannot be empty. You can specify `0.0.0.0` (IPv4) or `::` (IPv6) to listen on all interfaces, but that is not recommended. -## Capabilities.WorkflowRegistry -```toml -[Capabilities.WorkflowRegistry] -Address = '0x0' # Example -NetworkID = 'evm' # Default -ChainID = '1' # Default -``` - - -### Address -```toml -Address = '0x0' # Example -``` -Address is the address for the workflow registry contract. - -### NetworkID -```toml -NetworkID = 'evm' # Default -``` -NetworkID identifies the target network where the remote registry is located. - -### ChainID -```toml -ChainID = '1' # Default -``` -ChainID identifies the target chain id where the remote registry is located. - ## Capabilities.ExternalRegistry ```toml [Capabilities.ExternalRegistry] @@ -1902,7 +1875,6 @@ CertFile is the path to a PEM file of trusted root certificate authority certifi [Mercury.Transmitter] TransmitQueueMaxSize = 10_000 # Default TransmitTimeout = "5s" # Default -TransmitConcurrency = 100 # Default ``` Mercury.Transmitter controls settings for the mercury transmitter @@ -1925,14 +1897,6 @@ TransmitTimeout controls how long the transmitter will wait for a response when sending a message to the mercury server, before aborting and considering the transmission to be failed. -### TransmitConcurrency -```toml -TransmitConcurrency = 100 # Default -``` -TransmitConcurrency is the max number of concurrent transmits to each server. - -Only has effect with LLO jobs. - ## Telemetry ```toml [Telemetry] @@ -2034,7 +1998,6 @@ FinalizedBlockOffset = 0 NoNewFinalizedHeadsThreshold = '9m0s' [Transactions] -Enabled = true ForwardersEnabled = false MaxInFlight = 16 MaxQueued = 250 @@ -2139,7 +2102,6 @@ FinalizedBlockOffset = 0 NoNewFinalizedHeadsThreshold = '0s' [Transactions] -Enabled = true ForwardersEnabled = false MaxInFlight = 16 MaxQueued = 250 @@ -2244,7 +2206,6 @@ FinalizedBlockOffset = 0 NoNewFinalizedHeadsThreshold = '0s' [Transactions] -Enabled = true ForwardersEnabled = false MaxInFlight = 16 MaxQueued = 250 @@ -2349,7 +2310,6 @@ FinalizedBlockOffset = 0 NoNewFinalizedHeadsThreshold = '0s' [Transactions] -Enabled = true ForwardersEnabled = false MaxInFlight = 16 MaxQueued = 250 @@ -2455,7 +2415,6 @@ FinalizedBlockOffset = 0 NoNewFinalizedHeadsThreshold = '13m0s' [Transactions] -Enabled = true ForwardersEnabled = false MaxInFlight = 16 MaxQueued = 250 @@ -2564,7 +2523,6 @@ FinalizedBlockOffset = 0 NoNewFinalizedHeadsThreshold = '0s' [Transactions] -Enabled = true ForwardersEnabled = false MaxInFlight = 16 MaxQueued = 250 @@ -2669,7 +2627,6 @@ FinalizedBlockOffset = 0 NoNewFinalizedHeadsThreshold = '0s' [Transactions] -Enabled = true ForwardersEnabled = false MaxInFlight = 16 MaxQueued = 250 @@ -2775,7 +2732,6 @@ FinalizedBlockOffset = 0 NoNewFinalizedHeadsThreshold = '0s' [Transactions] -Enabled = true ForwardersEnabled = false MaxInFlight = 16 MaxQueued = 250 @@ -2880,7 +2836,6 @@ FinalizedBlockOffset = 2 NoNewFinalizedHeadsThreshold = '45s' [Transactions] -Enabled = true ForwardersEnabled = false MaxInFlight = 16 MaxQueued = 250 @@ -2984,7 +2939,6 @@ FinalizedBlockOffset = 0 NoNewFinalizedHeadsThreshold = '0s' [Transactions] -Enabled = true ForwardersEnabled = false MaxInFlight = 16 MaxQueued = 250 @@ -3088,7 +3042,6 @@ FinalizedBlockOffset = 0 NoNewFinalizedHeadsThreshold = '0s' [Transactions] -Enabled = true ForwardersEnabled = false MaxInFlight = 16 MaxQueued = 250 @@ -3193,7 +3146,6 @@ FinalizedBlockOffset = 2 NoNewFinalizedHeadsThreshold = '40s' [Transactions] -Enabled = true ForwardersEnabled = false MaxInFlight = 16 MaxQueued = 250 @@ -3299,7 +3251,6 @@ FinalizedBlockOffset = 2 NoNewFinalizedHeadsThreshold = '2m0s' [Transactions] -Enabled = true ForwardersEnabled = false MaxInFlight = 16 MaxQueued = 250 @@ -3404,7 +3355,6 @@ FinalizedBlockOffset = 0 NoNewFinalizedHeadsThreshold = '0s' [Transactions] -Enabled = true ForwardersEnabled = false MaxInFlight = 16 MaxQueued = 250 @@ -3509,7 +3459,6 @@ FinalizedBlockOffset = 0 NoNewFinalizedHeadsThreshold = '6m0s' [Transactions] -Enabled = true ForwardersEnabled = false MaxInFlight = 16 MaxQueued = 5000 @@ -3614,7 +3563,6 @@ FinalizedBlockOffset = 2 NoNewFinalizedHeadsThreshold = '0s' [Transactions] -Enabled = true ForwardersEnabled = false MaxInFlight = 16 MaxQueued = 250 @@ -3720,7 +3668,6 @@ FinalizedBlockOffset = 2 NoNewFinalizedHeadsThreshold = '0s' [Transactions] -Enabled = true ForwardersEnabled = false MaxInFlight = 16 MaxQueued = 250 @@ -3801,115 +3748,6 @@ GasLimitDefault = 400000

-
Bsquared Mainnet (223)

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

-
Fantom Mainnet (250)

```toml @@ -3935,7 +3773,6 @@ FinalizedBlockOffset = 0 NoNewFinalizedHeadsThreshold = '0s' [Transactions] -Enabled = true ForwardersEnabled = false MaxInFlight = 16 MaxQueued = 250 @@ -4040,7 +3877,6 @@ FinalizedBlockOffset = 2 NoNewFinalizedHeadsThreshold = '0s' [Transactions] -Enabled = true ForwardersEnabled = false MaxInFlight = 16 MaxQueued = 250 @@ -4149,7 +3985,6 @@ FinalizedBlockOffset = 0 NoNewFinalizedHeadsThreshold = '0s' [Transactions] -Enabled = true ForwardersEnabled = false MaxInFlight = 16 MaxQueued = 250 @@ -4257,7 +4092,6 @@ FinalizedBlockOffset = 2 NoNewFinalizedHeadsThreshold = '0s' [Transactions] -Enabled = true ForwardersEnabled = false MaxInFlight = 16 MaxQueued = 250 @@ -4362,7 +4196,6 @@ FinalizedBlockOffset = 2 NoNewFinalizedHeadsThreshold = '0s' [Transactions] -Enabled = true ForwardersEnabled = false MaxInFlight = 16 MaxQueued = 250 @@ -4467,7 +4300,6 @@ FinalizedBlockOffset = 2 NoNewFinalizedHeadsThreshold = '0s' [Transactions] -Enabled = true ForwardersEnabled = false MaxInFlight = 16 MaxQueued = 250 @@ -4542,7 +4374,7 @@ ObservationGracePeriod = '1s' [OCR2] [OCR2.Automation] -GasLimit = 6000000 +GasLimit = 5400000 [Workflow] GasLimitDefault = 400000 @@ -4575,7 +4407,6 @@ FinalizedBlockOffset = 2 NoNewFinalizedHeadsThreshold = '0s' [Transactions] -Enabled = true ForwardersEnabled = false MaxInFlight = 16 MaxQueued = 250 @@ -4650,7 +4481,7 @@ ObservationGracePeriod = '1s' [OCR2] [OCR2.Automation] -GasLimit = 6000000 +GasLimit = 5400000 [Workflow] GasLimitDefault = 400000 @@ -4684,7 +4515,6 @@ FinalizedBlockOffset = 0 NoNewFinalizedHeadsThreshold = '0s' [Transactions] -Enabled = true ForwardersEnabled = false MaxInFlight = 16 MaxQueued = 250 @@ -4768,32 +4598,31 @@ GasLimitDefault = 400000

-
Worldchain Mainnet (480)

+

Metis Rinkeby (588)

```toml AutoCreateKey = true BlockBackfillDepth = 10 BlockBackfillSkip = false -ChainType = 'optimismBedrock' -FinalityDepth = 2500 -FinalityTagEnabled = true +ChainType = 'metis' +FinalityDepth = 10 +FinalityTagEnabled = false LogBackfillBatchSize = 1000 -LogPollInterval = '3s' +LogPollInterval = '15s' LogKeepBlocksDepth = 100000 LogPrunePageSize = 0 BackupLogPollerBlockDelay = 100 -MinIncomingConfirmations = 3 +MinIncomingConfirmations = 1 MinContractPayment = '0.00001 link' NonceAutoSync = true -NoNewHeadsThreshold = '3m0s' +NoNewHeadsThreshold = '0s' LogBroadcasterEnabled = true RPCDefaultBatchSize = 250 RPCBlockQueryDelay = 1 FinalizedBlockOffset = 0 -NoNewFinalizedHeadsThreshold = '1h30m0s' +NoNewFinalizedHeadsThreshold = '0s' [Transactions] -Enabled = true ForwardersEnabled = false MaxInFlight = 16 MaxQueued = 250 @@ -4808,10 +4637,10 @@ Enabled = false Enabled = true [GasEstimator] -Mode = 'FeeHistory' +Mode = 'SuggestedPrice' PriceDefault = '20 gwei' PriceMax = '115792089237316195423570985008687907853269984665.640564039457584007913129639935 tether' -PriceMin = '1 gwei' +PriceMin = '0' LimitDefault = 500000 LimitMax = 500000 LimitMultiplier = '1' @@ -4820,24 +4649,20 @@ EstimateLimit = false BumpMin = '5 gwei' BumpPercent = 20 BumpThreshold = 3 -EIP1559DynamicFees = true +EIP1559DynamicFees = false FeeCapDefault = '100 gwei' TipCapDefault = '1 wei' TipCapMin = '1 wei' [GasEstimator.BlockHistory] BatchSize = 25 -BlockHistorySize = 100 +BlockHistorySize = 0 CheckInclusionBlocks = 12 CheckInclusionPercentile = 90 TransactionPercentile = 60 [GasEstimator.FeeHistory] -CacheTimeout = '4s' - -[GasEstimator.DAOracle] -OracleType = 'opstack' -OracleAddress = '0x420000000000000000000000000000000000000F' +CacheTimeout = '10s' [HeadTracker] HistoryDepth = 100 @@ -4851,7 +4676,7 @@ PersistenceEnabled = true PollFailureThreshold = 5 PollInterval = '10s' SelectionMode = 'HighestHead' -SyncThreshold = 5 +SyncThreshold = 10 LeaseDuration = '0s' NodeIsSyncingEnabled = false FinalizedBlockPollInterval = '5s' @@ -4860,7 +4685,7 @@ DeathDeclarationDelay = '1m0s' NewHeadsPollInterval = '0s' [OCR] -ContractConfirmations = 4 +ContractConfirmations = 1 ContractTransmitterTransmitTimeout = '10s' DatabaseTimeout = '10s' DeltaCOverride = '168h0m0s' @@ -4877,13 +4702,12 @@ GasLimitDefault = 400000

-
Metis Rinkeby (588)

+

Klaytn Testnet (1001)

```toml AutoCreateKey = true BlockBackfillDepth = 10 BlockBackfillSkip = false -ChainType = 'metis' FinalityDepth = 10 FinalityTagEnabled = false LogBackfillBatchSize = 1000 @@ -4894,7 +4718,7 @@ BackupLogPollerBlockDelay = 100 MinIncomingConfirmations = 1 MinContractPayment = '0.00001 link' NonceAutoSync = true -NoNewHeadsThreshold = '0s' +NoNewHeadsThreshold = '30s' LogBroadcasterEnabled = true RPCDefaultBatchSize = 250 RPCBlockQueryDelay = 1 @@ -4902,7 +4726,6 @@ FinalizedBlockOffset = 0 NoNewFinalizedHeadsThreshold = '0s' [Transactions] -Enabled = true ForwardersEnabled = false MaxInFlight = 16 MaxQueued = 250 @@ -4918,9 +4741,9 @@ Enabled = true [GasEstimator] Mode = 'SuggestedPrice' -PriceDefault = '20 gwei' +PriceDefault = '750 gwei' PriceMax = '115792089237316195423570985008687907853269984665.640564039457584007913129639935 tether' -PriceMin = '0' +PriceMin = '1 gwei' LimitDefault = 500000 LimitMax = 500000 LimitMultiplier = '1' @@ -4928,7 +4751,7 @@ LimitTransfer = 21000 EstimateLimit = false BumpMin = '5 gwei' BumpPercent = 20 -BumpThreshold = 3 +BumpThreshold = 5 EIP1559DynamicFees = false FeeCapDefault = '100 gwei' TipCapDefault = '1 wei' @@ -4936,7 +4759,7 @@ TipCapMin = '1 wei' [GasEstimator.BlockHistory] BatchSize = 25 -BlockHistorySize = 0 +BlockHistorySize = 8 CheckInclusionBlocks = 12 CheckInclusionPercentile = 90 TransactionPercentile = 60 @@ -4956,7 +4779,7 @@ PersistenceEnabled = true PollFailureThreshold = 5 PollInterval = '10s' SelectionMode = 'HighestHead' -SyncThreshold = 10 +SyncThreshold = 5 LeaseDuration = '0s' NodeIsSyncingEnabled = false FinalizedBlockPollInterval = '5s' @@ -4982,14 +4805,15 @@ GasLimitDefault = 400000

-
Klaytn Testnet (1001)

+

Metis Mainnet (1088)

```toml AutoCreateKey = true BlockBackfillDepth = 10 BlockBackfillSkip = false +ChainType = 'metis' FinalityDepth = 10 -FinalityTagEnabled = false +FinalityTagEnabled = true LogBackfillBatchSize = 1000 LogPollInterval = '15s' LogKeepBlocksDepth = 100000 @@ -4998,7 +4822,7 @@ BackupLogPollerBlockDelay = 100 MinIncomingConfirmations = 1 MinContractPayment = '0.00001 link' NonceAutoSync = true -NoNewHeadsThreshold = '30s' +NoNewHeadsThreshold = '0s' LogBroadcasterEnabled = true RPCDefaultBatchSize = 250 RPCBlockQueryDelay = 1 @@ -5006,7 +4830,6 @@ FinalizedBlockOffset = 0 NoNewFinalizedHeadsThreshold = '0s' [Transactions] -Enabled = true ForwardersEnabled = false MaxInFlight = 16 MaxQueued = 250 @@ -5022,9 +4845,9 @@ Enabled = true [GasEstimator] Mode = 'SuggestedPrice' -PriceDefault = '750 gwei' +PriceDefault = '20 gwei' PriceMax = '115792089237316195423570985008687907853269984665.640564039457584007913129639935 tether' -PriceMin = '1 gwei' +PriceMin = '0' LimitDefault = 500000 LimitMax = 500000 LimitMultiplier = '1' @@ -5032,7 +4855,7 @@ LimitTransfer = 21000 EstimateLimit = false BumpMin = '5 gwei' BumpPercent = 20 -BumpThreshold = 5 +BumpThreshold = 3 EIP1559DynamicFees = false FeeCapDefault = '100 gwei' TipCapDefault = '1 wei' @@ -5040,7 +4863,7 @@ TipCapMin = '1 wei' [GasEstimator.BlockHistory] BatchSize = 25 -BlockHistorySize = 8 +BlockHistorySize = 0 CheckInclusionBlocks = 12 CheckInclusionPercentile = 90 TransactionPercentile = 60 @@ -5060,7 +4883,7 @@ PersistenceEnabled = true PollFailureThreshold = 5 PollInterval = '10s' SelectionMode = 'HighestHead' -SyncThreshold = 5 +SyncThreshold = 10 LeaseDuration = '0s' NodeIsSyncingEnabled = false FinalizedBlockPollInterval = '5s' @@ -5086,47 +4909,47 @@ GasLimitDefault = 400000

-
Metis Mainnet (1088)

+

Polygon Zkevm Mainnet (1101)

```toml AutoCreateKey = true BlockBackfillDepth = 10 BlockBackfillSkip = false -ChainType = 'metis' -FinalityDepth = 10 -FinalityTagEnabled = true +ChainType = 'zkevm' +FinalityDepth = 500 +FinalityTagEnabled = false LogBackfillBatchSize = 1000 -LogPollInterval = '15s' +LogPollInterval = '30s' LogKeepBlocksDepth = 100000 LogPrunePageSize = 0 BackupLogPollerBlockDelay = 100 MinIncomingConfirmations = 1 MinContractPayment = '0.00001 link' NonceAutoSync = true -NoNewHeadsThreshold = '0s' +NoNewHeadsThreshold = '6m0s' LogBroadcasterEnabled = true -RPCDefaultBatchSize = 250 -RPCBlockQueryDelay = 1 +RPCDefaultBatchSize = 100 +RPCBlockQueryDelay = 15 FinalizedBlockOffset = 0 NoNewFinalizedHeadsThreshold = '0s' [Transactions] -Enabled = true ForwardersEnabled = false MaxInFlight = 16 MaxQueued = 250 ReaperInterval = '1h0m0s' ReaperThreshold = '168h0m0s' -ResendAfterThreshold = '1m0s' +ResendAfterThreshold = '3m0s' [Transactions.AutoPurge] -Enabled = false +Enabled = true +MinAttempts = 3 [BalanceMonitor] Enabled = true [GasEstimator] -Mode = 'SuggestedPrice' +Mode = 'FeeHistory' PriceDefault = '20 gwei' PriceMax = '115792089237316195423570985008687907853269984665.640564039457584007913129639935 tether' PriceMin = '0' @@ -5136,7 +4959,7 @@ LimitMultiplier = '1' LimitTransfer = 21000 EstimateLimit = false BumpMin = '5 gwei' -BumpPercent = 20 +BumpPercent = 40 BumpThreshold = 3 EIP1559DynamicFees = false FeeCapDefault = '100 gwei' @@ -5145,16 +4968,16 @@ TipCapMin = '1 wei' [GasEstimator.BlockHistory] BatchSize = 25 -BlockHistorySize = 0 +BlockHistorySize = 8 CheckInclusionBlocks = 12 CheckInclusionPercentile = 90 TransactionPercentile = 60 [GasEstimator.FeeHistory] -CacheTimeout = '10s' +CacheTimeout = '4s' [HeadTracker] -HistoryDepth = 100 +HistoryDepth = 2000 MaxBufferSize = 3 SamplingInterval = '1s' MaxAllowedFinalityDepth = 10000 @@ -5165,7 +4988,7 @@ PersistenceEnabled = true PollFailureThreshold = 5 PollInterval = '10s' SelectionMode = 'HighestHead' -SyncThreshold = 10 +SyncThreshold = 5 LeaseDuration = '0s' NodeIsSyncingEnabled = false FinalizedBlockPollInterval = '5s' @@ -5191,62 +5014,60 @@ GasLimitDefault = 400000

-
Polygon Zkevm Mainnet (1101)

+

WeMix Mainnet (1111)

```toml AutoCreateKey = true BlockBackfillDepth = 10 BlockBackfillSkip = false -ChainType = 'zkevm' -FinalityDepth = 500 -FinalityTagEnabled = false +ChainType = 'wemix' +FinalityDepth = 10 +FinalityTagEnabled = true LogBackfillBatchSize = 1000 -LogPollInterval = '30s' +LogPollInterval = '3s' LogKeepBlocksDepth = 100000 LogPrunePageSize = 0 BackupLogPollerBlockDelay = 100 MinIncomingConfirmations = 1 MinContractPayment = '0.00001 link' NonceAutoSync = true -NoNewHeadsThreshold = '6m0s' +NoNewHeadsThreshold = '30s' LogBroadcasterEnabled = true -RPCDefaultBatchSize = 100 -RPCBlockQueryDelay = 15 -FinalizedBlockOffset = 0 -NoNewFinalizedHeadsThreshold = '0s' +RPCDefaultBatchSize = 250 +RPCBlockQueryDelay = 1 +FinalizedBlockOffset = 2 +NoNewFinalizedHeadsThreshold = '40s' [Transactions] -Enabled = true ForwardersEnabled = false MaxInFlight = 16 MaxQueued = 250 ReaperInterval = '1h0m0s' ReaperThreshold = '168h0m0s' -ResendAfterThreshold = '3m0s' +ResendAfterThreshold = '1m0s' [Transactions.AutoPurge] -Enabled = true -MinAttempts = 3 +Enabled = false [BalanceMonitor] Enabled = true [GasEstimator] -Mode = 'FeeHistory' +Mode = 'BlockHistory' PriceDefault = '20 gwei' PriceMax = '115792089237316195423570985008687907853269984665.640564039457584007913129639935 tether' -PriceMin = '0' +PriceMin = '1 gwei' LimitDefault = 500000 LimitMax = 500000 LimitMultiplier = '1' LimitTransfer = 21000 EstimateLimit = false BumpMin = '5 gwei' -BumpPercent = 40 +BumpPercent = 20 BumpThreshold = 3 -EIP1559DynamicFees = false +EIP1559DynamicFees = true FeeCapDefault = '100 gwei' -TipCapDefault = '1 wei' +TipCapDefault = '100 gwei' TipCapMin = '1 wei' [GasEstimator.BlockHistory] @@ -5257,10 +5078,10 @@ CheckInclusionPercentile = 90 TransactionPercentile = 60 [GasEstimator.FeeHistory] -CacheTimeout = '4s' +CacheTimeout = '10s' [HeadTracker] -HistoryDepth = 2000 +HistoryDepth = 100 MaxBufferSize = 3 SamplingInterval = '1s' MaxAllowedFinalityDepth = 10000 @@ -5297,7 +5118,7 @@ GasLimitDefault = 400000

-
WeMix Mainnet (1111)

+

WeMix Testnet (1112)

```toml AutoCreateKey = true @@ -5322,7 +5143,6 @@ FinalizedBlockOffset = 2 NoNewFinalizedHeadsThreshold = '40s' [Transactions] -Enabled = true ForwardersEnabled = false MaxInFlight = 16 MaxQueued = 250 @@ -5369,7 +5189,7 @@ HistoryDepth = 100 MaxBufferSize = 3 SamplingInterval = '1s' MaxAllowedFinalityDepth = 10000 -FinalityTagBypass = true +FinalityTagBypass = false PersistenceEnabled = true [NodePool] @@ -5402,38 +5222,36 @@ GasLimitDefault = 400000

-
WeMix Testnet (1112)

+

Simulated (1337)

```toml AutoCreateKey = true BlockBackfillDepth = 10 BlockBackfillSkip = false -ChainType = 'wemix' FinalityDepth = 10 -FinalityTagEnabled = true +FinalityTagEnabled = false LogBackfillBatchSize = 1000 -LogPollInterval = '3s' +LogPollInterval = '15s' LogKeepBlocksDepth = 100000 LogPrunePageSize = 0 BackupLogPollerBlockDelay = 100 MinIncomingConfirmations = 1 -MinContractPayment = '0.00001 link' +MinContractPayment = '100' NonceAutoSync = true -NoNewHeadsThreshold = '30s' +NoNewHeadsThreshold = '0s' LogBroadcasterEnabled = true RPCDefaultBatchSize = 250 RPCBlockQueryDelay = 1 -FinalizedBlockOffset = 2 -NoNewFinalizedHeadsThreshold = '40s' +FinalizedBlockOffset = 0 +NoNewFinalizedHeadsThreshold = '0s' [Transactions] -Enabled = true ForwardersEnabled = false MaxInFlight = 16 MaxQueued = 250 ReaperInterval = '1h0m0s' -ReaperThreshold = '168h0m0s' -ResendAfterThreshold = '1m0s' +ReaperThreshold = '0s' +ResendAfterThreshold = '0s' [Transactions.AutoPurge] Enabled = false @@ -5442,10 +5260,10 @@ Enabled = false Enabled = true [GasEstimator] -Mode = 'BlockHistory' -PriceDefault = '20 gwei' -PriceMax = '115792089237316195423570985008687907853269984665.640564039457584007913129639935 tether' -PriceMin = '1 gwei' +Mode = 'FixedPrice' +PriceDefault = '1 gwei' +PriceMax = '1 gwei' +PriceMin = '0' LimitDefault = 500000 LimitMax = 500000 LimitMultiplier = '1' @@ -5453,10 +5271,10 @@ LimitTransfer = 21000 EstimateLimit = false BumpMin = '5 gwei' BumpPercent = 20 -BumpThreshold = 3 -EIP1559DynamicFees = true -FeeCapDefault = '100 gwei' -TipCapDefault = '100 gwei' +BumpThreshold = 0 +EIP1559DynamicFees = false +FeeCapDefault = '1 gwei' +TipCapDefault = '1 mwei' TipCapMin = '1 wei' [GasEstimator.BlockHistory] @@ -5470,11 +5288,11 @@ TransactionPercentile = 60 CacheTimeout = '10s' [HeadTracker] -HistoryDepth = 100 -MaxBufferSize = 3 -SamplingInterval = '1s' +HistoryDepth = 10 +MaxBufferSize = 100 +SamplingInterval = '0s' MaxAllowedFinalityDepth = 10000 -FinalityTagBypass = false +FinalityTagBypass = true PersistenceEnabled = true [NodePool] @@ -5485,7 +5303,7 @@ SyncThreshold = 5 LeaseDuration = '0s' NodeIsSyncingEnabled = false FinalizedBlockPollInterval = '5s' -EnforceRepeatableRead = true +EnforceRepeatableRead = false DeathDeclarationDelay = '1m0s' NewHeadsPollInterval = '0s' @@ -5507,38 +5325,38 @@ GasLimitDefault = 400000

-
Bsquared Testnet (1123)

+

Soneium Sepolia (1946)

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

-
Unichain Testnet (1301)

+

Kroma Sepolia (2358)

```toml AutoCreateKey = true BlockBackfillDepth = 10 BlockBackfillSkip = false -ChainType = 'optimismBedrock' -FinalityDepth = 2000 +ChainType = 'kroma' +FinalityDepth = 400 FinalityTagEnabled = true LogBackfillBatchSize = 1000 LogPollInterval = '2s' LogKeepBlocksDepth = 100000 LogPrunePageSize = 0 BackupLogPollerBlockDelay = 100 -MinIncomingConfirmations = 3 +MinIncomingConfirmations = 1 MinContractPayment = '0.00001 link' NonceAutoSync = true -NoNewHeadsThreshold = '3m0s' +NoNewHeadsThreshold = '40s' LogBroadcasterEnabled = true RPCDefaultBatchSize = 250 RPCBlockQueryDelay = 1 -FinalizedBlockOffset = 0 -NoNewFinalizedHeadsThreshold = '45m0s' +FinalizedBlockOffset = 2 +NoNewFinalizedHeadsThreshold = '0s' [Transactions] -Enabled = true ForwardersEnabled = false MaxInFlight = 16 MaxQueued = 250 ReaperInterval = '1h0m0s' ReaperThreshold = '168h0m0s' -ResendAfterThreshold = '1m0s' +ResendAfterThreshold = '30s' [Transactions.AutoPurge] Enabled = false @@ -5656,16 +5473,16 @@ Enabled = false Enabled = true [GasEstimator] -Mode = 'FeeHistory' +Mode = 'BlockHistory' PriceDefault = '20 gwei' PriceMax = '115792089237316195423570985008687907853269984665.640564039457584007913129639935 tether' -PriceMin = '1 gwei' +PriceMin = '1 wei' LimitDefault = 500000 LimitMax = 500000 LimitMultiplier = '1' LimitTransfer = 21000 EstimateLimit = false -BumpMin = '5 gwei' +BumpMin = '100 wei' BumpPercent = 20 BumpThreshold = 3 EIP1559DynamicFees = true @@ -5675,20 +5492,20 @@ TipCapMin = '1 wei' [GasEstimator.BlockHistory] BatchSize = 25 -BlockHistorySize = 100 +BlockHistorySize = 24 CheckInclusionBlocks = 12 CheckInclusionPercentile = 90 TransactionPercentile = 60 [GasEstimator.FeeHistory] -CacheTimeout = '2s' +CacheTimeout = '10s' [GasEstimator.DAOracle] OracleType = 'opstack' -OracleAddress = '0x420000000000000000000000000000000000000F' +OracleAddress = '0x4200000000000000000000000000000000000005' [HeadTracker] -HistoryDepth = 100 +HistoryDepth = 400 MaxBufferSize = 3 SamplingInterval = '1s' MaxAllowedFinalityDepth = 10000 @@ -5699,7 +5516,7 @@ PersistenceEnabled = true PollFailureThreshold = 5 PollInterval = '10s' SelectionMode = 'HighestHead' -SyncThreshold = 5 +SyncThreshold = 10 LeaseDuration = '0s' NodeIsSyncingEnabled = false FinalizedBlockPollInterval = '5s' @@ -5708,7 +5525,7 @@ DeathDeclarationDelay = '1m0s' NewHeadsPollInterval = '0s' [OCR] -ContractConfirmations = 4 +ContractConfirmations = 1 ContractTransmitterTransmitTimeout = '10s' DatabaseTimeout = '10s' DeltaCOverride = '168h0m0s' @@ -5725,48 +5542,49 @@ GasLimitDefault = 400000

-
Simulated (1337)

+

Polygon Zkevm Cardona (2442)

```toml AutoCreateKey = true BlockBackfillDepth = 10 BlockBackfillSkip = false -FinalityDepth = 10 +ChainType = 'zkevm' +FinalityDepth = 500 FinalityTagEnabled = false LogBackfillBatchSize = 1000 -LogPollInterval = '15s' +LogPollInterval = '30s' LogKeepBlocksDepth = 100000 LogPrunePageSize = 0 BackupLogPollerBlockDelay = 100 MinIncomingConfirmations = 1 -MinContractPayment = '100' +MinContractPayment = '0.00001 link' NonceAutoSync = true -NoNewHeadsThreshold = '0s' +NoNewHeadsThreshold = '12m0s' LogBroadcasterEnabled = true -RPCDefaultBatchSize = 250 +RPCDefaultBatchSize = 100 RPCBlockQueryDelay = 1 FinalizedBlockOffset = 0 NoNewFinalizedHeadsThreshold = '0s' [Transactions] -Enabled = true ForwardersEnabled = false MaxInFlight = 16 MaxQueued = 250 ReaperInterval = '1h0m0s' -ReaperThreshold = '0s' -ResendAfterThreshold = '0s' +ReaperThreshold = '168h0m0s' +ResendAfterThreshold = '3m0s' [Transactions.AutoPurge] -Enabled = false +Enabled = true +MinAttempts = 3 [BalanceMonitor] Enabled = true [GasEstimator] -Mode = 'FixedPrice' -PriceDefault = '1 gwei' -PriceMax = '1 gwei' +Mode = 'FeeHistory' +PriceDefault = '20 gwei' +PriceMax = '115792089237316195423570985008687907853269984665.640564039457584007913129639935 tether' PriceMin = '0' LimitDefault = 500000 LimitMax = 500000 @@ -5774,11 +5592,11 @@ LimitMultiplier = '1' LimitTransfer = 21000 EstimateLimit = false BumpMin = '5 gwei' -BumpPercent = 20 -BumpThreshold = 0 +BumpPercent = 40 +BumpThreshold = 3 EIP1559DynamicFees = false -FeeCapDefault = '1 gwei' -TipCapDefault = '1 mwei' +FeeCapDefault = '100 gwei' +TipCapDefault = '1 wei' TipCapMin = '1 wei' [GasEstimator.BlockHistory] @@ -5789,12 +5607,12 @@ CheckInclusionPercentile = 90 TransactionPercentile = 60 [GasEstimator.FeeHistory] -CacheTimeout = '10s' +CacheTimeout = '4s' [HeadTracker] -HistoryDepth = 10 -MaxBufferSize = 100 -SamplingInterval = '0s' +HistoryDepth = 2000 +MaxBufferSize = 3 +SamplingInterval = '1s' MaxAllowedFinalityDepth = 10000 FinalityTagBypass = true PersistenceEnabled = true @@ -5807,7 +5625,7 @@ SyncThreshold = 5 LeaseDuration = '0s' NodeIsSyncingEnabled = false FinalizedBlockPollInterval = '5s' -EnforceRepeatableRead = false +EnforceRepeatableRead = true DeathDeclarationDelay = '1m0s' NewHeadsPollInterval = '0s' @@ -5829,542 +5647,7 @@ GasLimitDefault = 400000

-
Soneium Sepolia (1946)

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

- -
Ronin Mainnet (2020)

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

- -
Ronin Saigon (2021)

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

- -
Kroma Sepolia (2358)

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

- -
Polygon Zkevm Cardona (2442)

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

- -
Fantom Testnet (4002)

+

Fantom Testnet (4002)

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

- -
Worldchain Testnet (4801)

- -```toml -AutoCreateKey = true -BlockBackfillDepth = 10 -BlockBackfillSkip = false -ChainType = 'optimismBedrock' -FinalityDepth = 2500 -FinalityTagEnabled = true +LinkContractAddress = '0xfaFedb041c0DD4fA2Dc0d87a6B0979Ee6FA7af5F' LogBackfillBatchSize = 1000 -LogPollInterval = '3s' +LogPollInterval = '1s' LogKeepBlocksDepth = 100000 LogPrunePageSize = 0 BackupLogPollerBlockDelay = 100 MinIncomingConfirmations = 3 MinContractPayment = '0.00001 link' NonceAutoSync = true -NoNewHeadsThreshold = '3m0s' +NoNewHeadsThreshold = '0s' LogBroadcasterEnabled = true RPCDefaultBatchSize = 250 -RPCBlockQueryDelay = 1 +RPCBlockQueryDelay = 2 FinalizedBlockOffset = 0 -NoNewFinalizedHeadsThreshold = '1h30m0s' +NoNewFinalizedHeadsThreshold = '0s' [Transactions] -Enabled = true ForwardersEnabled = false MaxInFlight = 16 MaxQueued = 250 @@ -6509,7 +5686,7 @@ Enabled = false Enabled = true [GasEstimator] -Mode = 'FeeHistory' +Mode = 'SuggestedPrice' PriceDefault = '20 gwei' PriceMax = '115792089237316195423570985008687907853269984665.640564039457584007913129639935 tether' PriceMin = '1 gwei' @@ -6521,24 +5698,20 @@ EstimateLimit = false BumpMin = '5 gwei' BumpPercent = 20 BumpThreshold = 3 -EIP1559DynamicFees = true +EIP1559DynamicFees = false FeeCapDefault = '100 gwei' TipCapDefault = '1 wei' TipCapMin = '1 wei' [GasEstimator.BlockHistory] BatchSize = 25 -BlockHistorySize = 100 +BlockHistorySize = 8 CheckInclusionBlocks = 12 CheckInclusionPercentile = 90 TransactionPercentile = 60 [GasEstimator.FeeHistory] -CacheTimeout = '4s' - -[GasEstimator.DAOracle] -OracleType = 'opstack' -OracleAddress = '0x420000000000000000000000000000000000000F' +CacheTimeout = '10s' [HeadTracker] HistoryDepth = 100 @@ -6570,7 +5743,7 @@ ObservationGracePeriod = '1s' [OCR2] [OCR2.Automation] -GasLimit = 5400000 +GasLimit = 3800000 [Workflow] GasLimitDefault = 400000 @@ -6602,7 +5775,6 @@ FinalizedBlockOffset = 0 NoNewFinalizedHeadsThreshold = '0s' [Transactions] -Enabled = true ForwardersEnabled = false MaxInFlight = 16 MaxQueued = 250 @@ -6707,7 +5879,6 @@ FinalizedBlockOffset = 0 NoNewFinalizedHeadsThreshold = '15m0s' [Transactions] -Enabled = true ForwardersEnabled = false MaxInFlight = 16 MaxQueued = 250 @@ -6816,7 +5987,6 @@ FinalizedBlockOffset = 2 NoNewFinalizedHeadsThreshold = '2m0s' [Transactions] -Enabled = true ForwardersEnabled = false MaxInFlight = 16 MaxQueued = 250 @@ -6922,7 +6092,6 @@ FinalizedBlockOffset = 0 NoNewFinalizedHeadsThreshold = '0s' [Transactions] -Enabled = true ForwardersEnabled = false MaxInFlight = 16 MaxQueued = 250 @@ -7031,7 +6200,6 @@ FinalizedBlockOffset = 0 NoNewFinalizedHeadsThreshold = '0s' [Transactions] -Enabled = true ForwardersEnabled = false MaxInFlight = 16 MaxQueued = 250 @@ -7140,7 +6308,6 @@ FinalizedBlockOffset = 0 NoNewFinalizedHeadsThreshold = '0s' [Transactions] -Enabled = true ForwardersEnabled = false MaxInFlight = 16 MaxQueued = 250 @@ -7248,7 +6415,6 @@ FinalizedBlockOffset = 2 NoNewFinalizedHeadsThreshold = '1m0s' [Transactions] -Enabled = true ForwardersEnabled = false MaxInFlight = 16 MaxQueued = 250 @@ -7353,7 +6519,6 @@ FinalizedBlockOffset = 2 NoNewFinalizedHeadsThreshold = '1m0s' [Transactions] -Enabled = true ForwardersEnabled = false MaxInFlight = 16 MaxQueued = 250 @@ -7369,9 +6534,9 @@ Enabled = true [GasEstimator] Mode = 'BlockHistory' -PriceDefault = '1 gwei' +PriceDefault = '25 gwei' PriceMax = '115792089237316195423570985008687907853269984665.640564039457584007913129639935 tether' -PriceMin = '1 gwei' +PriceMin = '25 gwei' LimitDefault = 500000 LimitMax = 500000 LimitMultiplier = '1' @@ -7458,7 +6623,6 @@ FinalizedBlockOffset = 2 NoNewFinalizedHeadsThreshold = '1m0s' [Transactions] -Enabled = true ForwardersEnabled = false MaxInFlight = 16 MaxQueued = 250 @@ -7474,9 +6638,9 @@ Enabled = true [GasEstimator] Mode = 'BlockHistory' -PriceDefault = '1 gwei' +PriceDefault = '25 gwei' PriceMax = '115792089237316195423570985008687907853269984665.640564039457584007913129639935 tether' -PriceMin = '1 gwei' +PriceMin = '25 gwei' LimitDefault = 500000 LimitMax = 500000 LimitMultiplier = '1' @@ -7563,7 +6727,6 @@ FinalizedBlockOffset = 0 NoNewFinalizedHeadsThreshold = '45m0s' [Transactions] -Enabled = true ForwardersEnabled = false MaxInFlight = 16 MaxQueued = 250 @@ -7669,7 +6832,6 @@ FinalizedBlockOffset = 0 NoNewFinalizedHeadsThreshold = '15m0s' [Transactions] -Enabled = true ForwardersEnabled = false MaxInFlight = 16 MaxQueued = 250 @@ -7781,7 +6943,6 @@ FinalizedBlockOffset = 0 NoNewFinalizedHeadsThreshold = '15m0s' [Transactions] -Enabled = true ForwardersEnabled = false MaxInFlight = 16 MaxQueued = 250 @@ -7891,7 +7052,6 @@ FinalizedBlockOffset = 0 NoNewFinalizedHeadsThreshold = '0s' [Transactions] -Enabled = true ForwardersEnabled = false MaxInFlight = 16 MaxQueued = 250 @@ -7995,238 +7155,26 @@ FinalizedBlockOffset = 0 NoNewFinalizedHeadsThreshold = '0s' [Transactions] -Enabled = true -ForwardersEnabled = false -MaxInFlight = 16 -MaxQueued = 250 -ReaperInterval = '1h0m0s' -ReaperThreshold = '168h0m0s' -ResendAfterThreshold = '3m0s' - -[Transactions.AutoPurge] -Enabled = true -Threshold = 50 -MinAttempts = 3 - -[BalanceMonitor] -Enabled = true - -[GasEstimator] -Mode = 'BlockHistory' -PriceDefault = '20 gwei' -PriceMax = '115792089237316195423570985008687907853269984665.640564039457584007913129639935 tether' -PriceMin = '1 wei' -LimitDefault = 500000 -LimitMax = 500000 -LimitMultiplier = '1' -LimitTransfer = 21000 -EstimateLimit = false -BumpMin = '5 gwei' -BumpPercent = 20 -BumpThreshold = 3 -EIP1559DynamicFees = true -FeeCapDefault = '100 gwei' -TipCapDefault = '1 wei' -TipCapMin = '1 wei' - -[GasEstimator.BlockHistory] -BatchSize = 25 -BlockHistorySize = 8 -CheckInclusionBlocks = 12 -CheckInclusionPercentile = 90 -TransactionPercentile = 60 - -[GasEstimator.FeeHistory] -CacheTimeout = '10s' - -[HeadTracker] -HistoryDepth = 1000 -MaxBufferSize = 3 -SamplingInterval = '1s' -MaxAllowedFinalityDepth = 10000 -FinalityTagBypass = true -PersistenceEnabled = true - -[NodePool] -PollFailureThreshold = 5 -PollInterval = '10s' -SelectionMode = 'HighestHead' -SyncThreshold = 5 -LeaseDuration = '0s' -NodeIsSyncingEnabled = false -FinalizedBlockPollInterval = '5s' -EnforceRepeatableRead = true -DeathDeclarationDelay = '1m0s' -NewHeadsPollInterval = '0s' - -[OCR] -ContractConfirmations = 4 -ContractTransmitterTransmitTimeout = '10s' -DatabaseTimeout = '10s' -DeltaCOverride = '168h0m0s' -DeltaCJitterOverride = '1h0m0s' -ObservationGracePeriod = '1s' - -[OCR2] -[OCR2.Automation] -GasLimit = 5400000 - -[Workflow] -GasLimitDefault = 400000 -``` - -

- -
Linea Mainnet (59144)

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

- -
Metis Sepolia (59902)

- -```toml -AutoCreateKey = true -BlockBackfillDepth = 10 -BlockBackfillSkip = false -ChainType = 'metis' -FinalityDepth = 10 -FinalityTagEnabled = true -LogBackfillBatchSize = 1000 -LogPollInterval = '15s' -LogKeepBlocksDepth = 100000 -LogPrunePageSize = 0 -BackupLogPollerBlockDelay = 100 -MinIncomingConfirmations = 1 -MinContractPayment = '0.00001 link' -NonceAutoSync = true -NoNewHeadsThreshold = '0s' -LogBroadcasterEnabled = true -RPCDefaultBatchSize = 250 -RPCBlockQueryDelay = 1 -FinalizedBlockOffset = 0 -NoNewFinalizedHeadsThreshold = '0s' - -[Transactions] -Enabled = true ForwardersEnabled = false MaxInFlight = 16 MaxQueued = 250 ReaperInterval = '1h0m0s' ReaperThreshold = '168h0m0s' -ResendAfterThreshold = '1m0s' +ResendAfterThreshold = '3m0s' [Transactions.AutoPurge] -Enabled = false +Enabled = true +Threshold = 50 +MinAttempts = 3 [BalanceMonitor] Enabled = true [GasEstimator] -Mode = 'SuggestedPrice' +Mode = 'BlockHistory' PriceDefault = '20 gwei' PriceMax = '115792089237316195423570985008687907853269984665.640564039457584007913129639935 tether' -PriceMin = '0' +PriceMin = '1 wei' LimitDefault = 500000 LimitMax = 500000 LimitMultiplier = '1' @@ -8235,14 +7183,14 @@ EstimateLimit = false BumpMin = '5 gwei' BumpPercent = 20 BumpThreshold = 3 -EIP1559DynamicFees = false +EIP1559DynamicFees = true FeeCapDefault = '100 gwei' TipCapDefault = '1 wei' TipCapMin = '1 wei' [GasEstimator.BlockHistory] BatchSize = 25 -BlockHistorySize = 0 +BlockHistorySize = 8 CheckInclusionBlocks = 12 CheckInclusionPercentile = 90 TransactionPercentile = 60 @@ -8251,7 +7199,7 @@ TransactionPercentile = 60 CacheTimeout = '10s' [HeadTracker] -HistoryDepth = 100 +HistoryDepth = 1000 MaxBufferSize = 3 SamplingInterval = '1s' MaxAllowedFinalityDepth = 10000 @@ -8262,7 +7210,7 @@ PersistenceEnabled = true PollFailureThreshold = 5 PollInterval = '10s' SelectionMode = 'HighestHead' -SyncThreshold = 10 +SyncThreshold = 5 LeaseDuration = '0s' NodeIsSyncingEnabled = false FinalizedBlockPollInterval = '5s' @@ -8271,7 +7219,7 @@ DeathDeclarationDelay = '1m0s' NewHeadsPollInterval = '0s' [OCR] -ContractConfirmations = 1 +ContractConfirmations = 4 ContractTransmitterTransmitTimeout = '10s' DatabaseTimeout = '10s' DeltaCOverride = '168h0m0s' @@ -8288,79 +7236,75 @@ GasLimitDefault = 400000

-
BOB Mainnet (60808)

+

Linea Mainnet (59144)

```toml AutoCreateKey = true BlockBackfillDepth = 10 BlockBackfillSkip = false -ChainType = 'optimismBedrock' -FinalityDepth = 3150 -FinalityTagEnabled = true +FinalityDepth = 300 +FinalityTagEnabled = false LogBackfillBatchSize = 1000 -LogPollInterval = '3s' +LogPollInterval = '15s' LogKeepBlocksDepth = 100000 LogPrunePageSize = 0 BackupLogPollerBlockDelay = 100 MinIncomingConfirmations = 3 MinContractPayment = '0.00001 link' NonceAutoSync = true -NoNewHeadsThreshold = '3m0s' +NoNewHeadsThreshold = '0s' LogBroadcasterEnabled = true RPCDefaultBatchSize = 250 RPCBlockQueryDelay = 1 FinalizedBlockOffset = 0 -NoNewFinalizedHeadsThreshold = '1h50m0s' +NoNewFinalizedHeadsThreshold = '0s' [Transactions] -Enabled = true ForwardersEnabled = false MaxInFlight = 16 MaxQueued = 250 ReaperInterval = '1h0m0s' ReaperThreshold = '168h0m0s' -ResendAfterThreshold = '1m0s' +ResendAfterThreshold = '3m0s' [Transactions.AutoPurge] -Enabled = false +Enabled = true +Threshold = 50 +MinAttempts = 3 [BalanceMonitor] Enabled = true [GasEstimator] -Mode = 'FeeHistory' +Mode = 'BlockHistory' PriceDefault = '20 gwei' PriceMax = '115792089237316195423570985008687907853269984665.640564039457584007913129639935 tether' -PriceMin = '1 gwei' +PriceMin = '400 mwei' LimitDefault = 500000 LimitMax = 500000 LimitMultiplier = '1' LimitTransfer = 21000 EstimateLimit = false BumpMin = '5 gwei' -BumpPercent = 20 +BumpPercent = 40 BumpThreshold = 3 -EIP1559DynamicFees = true +EIP1559DynamicFees = false FeeCapDefault = '100 gwei' TipCapDefault = '1 wei' TipCapMin = '1 wei' [GasEstimator.BlockHistory] BatchSize = 25 -BlockHistorySize = 100 +BlockHistorySize = 8 CheckInclusionBlocks = 12 CheckInclusionPercentile = 90 TransactionPercentile = 60 [GasEstimator.FeeHistory] -CacheTimeout = '4s' - -[GasEstimator.DAOracle] -OracleType = 'opstack' -OracleAddress = '0x420000000000000000000000000000000000000F' +CacheTimeout = '10s' [HeadTracker] -HistoryDepth = 100 +HistoryDepth = 350 MaxBufferSize = 3 SamplingInterval = '1s' MaxAllowedFinalityDepth = 10000 @@ -8397,35 +7341,34 @@ GasLimitDefault = 400000

-
Polygon Mumbai (80001)

+

Metis Sepolia (59902)

```toml AutoCreateKey = true BlockBackfillDepth = 10 BlockBackfillSkip = false -FinalityDepth = 500 -FinalityTagEnabled = false -LinkContractAddress = '0x326C977E6efc84E512bB9C30f76E30c160eD06FB' +ChainType = 'metis' +FinalityDepth = 10 +FinalityTagEnabled = true LogBackfillBatchSize = 1000 -LogPollInterval = '1s' +LogPollInterval = '15s' LogKeepBlocksDepth = 100000 LogPrunePageSize = 0 BackupLogPollerBlockDelay = 100 -MinIncomingConfirmations = 5 +MinIncomingConfirmations = 1 MinContractPayment = '0.00001 link' NonceAutoSync = true -NoNewHeadsThreshold = '30s' +NoNewHeadsThreshold = '0s' LogBroadcasterEnabled = true -RPCDefaultBatchSize = 100 -RPCBlockQueryDelay = 10 +RPCDefaultBatchSize = 250 +RPCBlockQueryDelay = 1 FinalizedBlockOffset = 0 NoNewFinalizedHeadsThreshold = '0s' [Transactions] -Enabled = true ForwardersEnabled = false MaxInFlight = 16 -MaxQueued = 5000 +MaxQueued = 250 ReaperInterval = '1h0m0s' ReaperThreshold = '168h0m0s' ResendAfterThreshold = '1m0s' @@ -8437,18 +7380,18 @@ Enabled = false Enabled = true [GasEstimator] -Mode = 'BlockHistory' -PriceDefault = '25 gwei' +Mode = 'SuggestedPrice' +PriceDefault = '20 gwei' PriceMax = '115792089237316195423570985008687907853269984665.640564039457584007913129639935 tether' -PriceMin = '25 gwei' +PriceMin = '0' LimitDefault = 500000 LimitMax = 500000 LimitMultiplier = '1' LimitTransfer = 21000 EstimateLimit = false -BumpMin = '20 gwei' +BumpMin = '5 gwei' BumpPercent = 20 -BumpThreshold = 5 +BumpThreshold = 3 EIP1559DynamicFees = false FeeCapDefault = '100 gwei' TipCapDefault = '1 wei' @@ -8456,7 +7399,7 @@ TipCapMin = '1 wei' [GasEstimator.BlockHistory] BatchSize = 25 -BlockHistorySize = 24 +BlockHistorySize = 0 CheckInclusionBlocks = 12 CheckInclusionPercentile = 90 TransactionPercentile = 60 @@ -8465,7 +7408,7 @@ TransactionPercentile = 60 CacheTimeout = '10s' [HeadTracker] -HistoryDepth = 2000 +HistoryDepth = 100 MaxBufferSize = 3 SamplingInterval = '1s' MaxAllowedFinalityDepth = 10000 @@ -8485,7 +7428,7 @@ DeathDeclarationDelay = '1m0s' NewHeadsPollInterval = '0s' [OCR] -ContractConfirmations = 4 +ContractConfirmations = 1 ContractTransmitterTransmitTimeout = '10s' DatabaseTimeout = '10s' DeltaCOverride = '168h0m0s' @@ -8502,7 +7445,7 @@ GasLimitDefault = 400000

-
Polygon Amoy (80002)

+

Polygon Mumbai (80001)

```toml AutoCreateKey = true @@ -8510,6 +7453,7 @@ BlockBackfillDepth = 10 BlockBackfillSkip = false FinalityDepth = 500 FinalityTagEnabled = false +LinkContractAddress = '0x326C977E6efc84E512bB9C30f76E30c160eD06FB' LogBackfillBatchSize = 1000 LogPollInterval = '1s' LogKeepBlocksDepth = 100000 @@ -8523,10 +7467,9 @@ LogBroadcasterEnabled = true RPCDefaultBatchSize = 100 RPCBlockQueryDelay = 10 FinalizedBlockOffset = 0 -NoNewFinalizedHeadsThreshold = '12m0s' +NoNewFinalizedHeadsThreshold = '0s' [Transactions] -Enabled = true ForwardersEnabled = false MaxInFlight = 16 MaxQueued = 5000 @@ -8553,7 +7496,7 @@ EstimateLimit = false BumpMin = '20 gwei' BumpPercent = 20 BumpThreshold = 5 -EIP1559DynamicFees = true +EIP1559DynamicFees = false FeeCapDefault = '100 gwei' TipCapDefault = '1 wei' TipCapMin = '1 wei' @@ -8606,34 +7549,33 @@ GasLimitDefault = 400000

-
Berachain Testnet (80084)

+

Polygon Amoy (80002)

```toml AutoCreateKey = true BlockBackfillDepth = 10 BlockBackfillSkip = false -FinalityDepth = 10 +FinalityDepth = 500 FinalityTagEnabled = false LogBackfillBatchSize = 1000 -LogPollInterval = '6s' +LogPollInterval = '1s' LogKeepBlocksDepth = 100000 LogPrunePageSize = 0 BackupLogPollerBlockDelay = 100 -MinIncomingConfirmations = 3 +MinIncomingConfirmations = 5 MinContractPayment = '0.00001 link' NonceAutoSync = true -NoNewHeadsThreshold = '3m0s' +NoNewHeadsThreshold = '30s' LogBroadcasterEnabled = true -RPCDefaultBatchSize = 250 -RPCBlockQueryDelay = 1 +RPCDefaultBatchSize = 100 +RPCBlockQueryDelay = 10 FinalizedBlockOffset = 0 -NoNewFinalizedHeadsThreshold = '5m0s' +NoNewFinalizedHeadsThreshold = '12m0s' [Transactions] -Enabled = true ForwardersEnabled = false MaxInFlight = 16 -MaxQueued = 250 +MaxQueued = 5000 ReaperInterval = '1h0m0s' ReaperThreshold = '168h0m0s' ResendAfterThreshold = '1m0s' @@ -8645,18 +7587,18 @@ Enabled = false Enabled = true [GasEstimator] -Mode = 'FeeHistory' -PriceDefault = '20 gwei' +Mode = 'BlockHistory' +PriceDefault = '25 gwei' PriceMax = '115792089237316195423570985008687907853269984665.640564039457584007913129639935 tether' -PriceMin = '1 gwei' +PriceMin = '25 gwei' LimitDefault = 500000 LimitMax = 500000 LimitMultiplier = '1' LimitTransfer = 21000 EstimateLimit = false -BumpMin = '5 gwei' +BumpMin = '20 gwei' BumpPercent = 20 -BumpThreshold = 3 +BumpThreshold = 5 EIP1559DynamicFees = true FeeCapDefault = '100 gwei' TipCapDefault = '1 wei' @@ -8664,7 +7606,7 @@ TipCapMin = '1 wei' [GasEstimator.BlockHistory] BatchSize = 25 -BlockHistorySize = 100 +BlockHistorySize = 24 CheckInclusionBlocks = 12 CheckInclusionPercentile = 90 TransactionPercentile = 60 @@ -8673,7 +7615,7 @@ TransactionPercentile = 60 CacheTimeout = '10s' [HeadTracker] -HistoryDepth = 100 +HistoryDepth = 2000 MaxBufferSize = 3 SamplingInterval = '1s' MaxAllowedFinalityDepth = 10000 @@ -8684,7 +7626,7 @@ PersistenceEnabled = true PollFailureThreshold = 5 PollInterval = '10s' SelectionMode = 'HighestHead' -SyncThreshold = 5 +SyncThreshold = 10 LeaseDuration = '0s' NodeIsSyncingEnabled = false FinalizedBlockPollInterval = '5s' @@ -8735,7 +7677,6 @@ FinalizedBlockOffset = 0 NoNewFinalizedHeadsThreshold = '0s' [Transactions] -Enabled = true ForwardersEnabled = false MaxInFlight = 16 MaxQueued = 250 @@ -8844,7 +7785,6 @@ FinalizedBlockOffset = 0 NoNewFinalizedHeadsThreshold = '12m0s' [Transactions] -Enabled = true ForwardersEnabled = false MaxInFlight = 16 MaxQueued = 250 @@ -8954,7 +7894,6 @@ FinalizedBlockOffset = 0 NoNewFinalizedHeadsThreshold = '0s' [Transactions] -Enabled = true ForwardersEnabled = false MaxInFlight = 16 MaxQueued = 250 @@ -9063,7 +8002,6 @@ FinalizedBlockOffset = 0 NoNewFinalizedHeadsThreshold = '0s' [Transactions] -Enabled = true ForwardersEnabled = false MaxInFlight = 16 MaxQueued = 250 @@ -9171,7 +8109,6 @@ FinalizedBlockOffset = 0 NoNewFinalizedHeadsThreshold = '0s' [Transactions] -Enabled = true ForwardersEnabled = false MaxInFlight = 16 MaxQueued = 250 @@ -9279,7 +8216,6 @@ FinalizedBlockOffset = 0 NoNewFinalizedHeadsThreshold = '0s' [Transactions] -Enabled = true ForwardersEnabled = false MaxInFlight = 16 MaxQueued = 250 @@ -9389,7 +8325,6 @@ FinalizedBlockOffset = 0 NoNewFinalizedHeadsThreshold = '0s' [Transactions] -Enabled = true ForwardersEnabled = false MaxInFlight = 16 MaxQueued = 250 @@ -9474,115 +8409,6 @@ GasLimitDefault = 400000

-
BOB Testnet (808813)

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

-
Ethereum Sepolia (11155111)

```toml @@ -9608,7 +8434,6 @@ FinalizedBlockOffset = 0 NoNewFinalizedHeadsThreshold = '0s' [Transactions] -Enabled = true ForwardersEnabled = false MaxInFlight = 16 MaxQueued = 250 @@ -9713,7 +8538,6 @@ FinalizedBlockOffset = 0 NoNewFinalizedHeadsThreshold = '15m0s' [Transactions] -Enabled = true ForwardersEnabled = false MaxInFlight = 16 MaxQueued = 250 @@ -9822,7 +8646,6 @@ FinalizedBlockOffset = 0 NoNewFinalizedHeadsThreshold = '0s' [Transactions] -Enabled = true ForwardersEnabled = false MaxInFlight = 16 MaxQueued = 250 @@ -9927,7 +8750,6 @@ FinalizedBlockOffset = 0 NoNewFinalizedHeadsThreshold = '0s' [Transactions] -Enabled = true ForwardersEnabled = false MaxInFlight = 16 MaxQueued = 250 @@ -10213,7 +9035,6 @@ Set to zero to disable. ## EVM.Transactions ```toml [EVM.Transactions] -Enabled = true # Default ForwardersEnabled = false # Default MaxInFlight = 16 # Default MaxQueued = 250 # Default @@ -10223,12 +9044,6 @@ ResendAfterThreshold = '1m' # Default ``` -### Enabled -```toml -Enabled = true # Default -``` -Enabled is a feature flag for the Transaction Manager. This flag also enables or disables the gas estimator since it is dependent on the TXM to start it. - ### ForwardersEnabled ```toml ForwardersEnabled = false # Default @@ -11264,7 +10079,6 @@ OCR2CacheTTL = '1m' # Default TxTimeout = '1m' # Default TxRetryTimeout = '10s' # Default TxConfirmTimeout = '30s' # Default -TxExpirationRebroadcast = false # Default TxRetentionTimeout = '0s' # Default SkipPreflight = true # Default Commitment = 'confirmed' # Default @@ -11335,13 +10149,6 @@ TxConfirmTimeout = '30s' # Default ``` TxConfirmTimeout is the duration to wait when confirming a tx signature, before discarding as unconfirmed. -### TxExpirationRebroadcast -```toml -TxExpirationRebroadcast = false # Default -``` -TxExpirationRebroadcast enables or disables transaction rebroadcast if expired. Expiration check is performed every `ConfirmPollPeriod` -A transaction is considered expired if the blockhash it was sent with is 150 blocks older than the latest blockhash. - ### TxRetentionTimeout ```toml TxRetentionTimeout = '0s' # Default diff --git a/flake.lock b/flake.lock index 55ba1ddd565..71af2318c95 100644 --- a/flake.lock +++ b/flake.lock @@ -5,11 +5,11 @@ "systems": "systems" }, "locked": { - "lastModified": 1731533236, - "narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=", + "lastModified": 1710146030, + "narHash": "sha256-SZ5L6eA7HJ/nmkzGG7/ISclqe6oZdOZTNoesiInkXPQ=", "owner": "numtide", "repo": "flake-utils", - "rev": "11707dc2f618dd54ca8739b309ec4fc024de578b", + "rev": "b1d9ab70662946ef0850d488da1c9019f3a9752a", "type": "github" }, "original": { @@ -26,11 +26,11 @@ "nixpkgs": "nixpkgs" }, "locked": { - "lastModified": 1730625090, - "narHash": "sha256-lWfkkj+GEUM0UqYLD2Rx3zzILTL3xdmGJKGR4fwONpA=", + "lastModified": 1725354688, + "narHash": "sha256-KHHFemVt6C/hbGoMzIq7cpxmjdp+KZVZaqbvx02aliY=", "owner": "shazow", "repo": "foundry.nix", - "rev": "1c6a742bcbfd55a80de0e1f967a60174716a1560", + "rev": "671672bd60a0d2e5f6757638fdf27e806df755a4", "type": "github" }, "original": { @@ -45,11 +45,11 @@ "nixpkgs": "nixpkgs_2" }, "locked": { - "lastModified": 1732296943, - "narHash": "sha256-I1RVZIODsNWyidRW4E7Mhwjj0iDHL1wEE90VyxmXBKc=", + "lastModified": 1726594821, + "narHash": "sha256-ORImH+i+zOCMOdztNDqGDbyyFRC/FKmgbX8w50TNbQY=", "owner": "goreleaser", "repo": "nur", - "rev": "d65134bd2cc0e930e6c03694734deb41ec72e030", + "rev": "bd2ee272ddfffbda9377a472131728e83ce2332d", "type": "github" }, "original": { @@ -90,11 +90,11 @@ }, "nixpkgs_3": { "locked": { - "lastModified": 1732521221, - "narHash": "sha256-2ThgXBUXAE1oFsVATK1ZX9IjPcS4nKFOAjhPNKuiMn0=", + "lastModified": 1725103162, + "narHash": "sha256-Ym04C5+qovuQDYL/rKWSR+WESseQBbNAe5DsXNx5trY=", "owner": "nixos", "repo": "nixpkgs", - "rev": "4633a7c72337ea8fd23a4f2ba3972865e3ec685d", + "rev": "12228ff1752d7b7624a54e9c1af4b222b3c1073b", "type": "github" }, "original": { @@ -106,11 +106,11 @@ }, "nur": { "locked": { - "lastModified": 1732854630, - "narHash": "sha256-ZliP697Djpq+JM4MuO6kvj5RWjCdg39ZQ2moFoqFbdE=", + "lastModified": 1727912806, + "narHash": "sha256-LDOTTOGPaEP233gBrL8dnPGopc1lqcJFe0VB/+K/yWc=", "owner": "nix-community", "repo": "NUR", - "rev": "cc2a3158b6a714b98a8b891d6dcfc3a43039051f", + "rev": "9d9bcd30fec126b08b49020b7af08bc1aad66210", "type": "github" }, "original": { diff --git a/go.mod b/go.mod index f3e76d0be9b..e6039802f93 100644 --- a/go.mod +++ b/go.mod @@ -1,17 +1,15 @@ module github.com/smartcontractkit/chainlink/v2 -go 1.23.3 - -toolchain go1.23.4 +go 1.22.8 require ( github.com/Depado/ginprom v1.8.0 - github.com/Masterminds/semver/v3 v3.3.0 + github.com/Masterminds/semver/v3 v3.2.1 github.com/Masterminds/sprig/v3 v3.2.3 github.com/NethermindEth/juno v0.3.1 github.com/NethermindEth/starknet.go v0.7.1-0.20240401080518-34a506f3cfdb github.com/XSAM/otelsql v0.27.0 - github.com/andybalholm/brotli v1.1.1 + github.com/andybalholm/brotli v1.1.0 github.com/avast/retry-go/v4 v4.6.0 github.com/btcsuite/btcd/btcec/v2 v2.3.4 github.com/cometbft/cometbft v0.37.5 @@ -23,10 +21,9 @@ require ( github.com/ethereum/go-ethereum v1.14.11 github.com/fatih/color v1.17.0 github.com/fxamacker/cbor/v2 v2.7.0 - github.com/gagliardetto/binary v0.8.0 - github.com/gagliardetto/solana-go v1.12.0 + github.com/gagliardetto/solana-go v1.8.4 github.com/getsentry/sentry-go v0.27.0 - github.com/gin-contrib/cors v1.7.2 + github.com/gin-contrib/cors v1.5.0 github.com/gin-contrib/expvar v0.0.1 github.com/gin-contrib/sessions v0.0.5 github.com/gin-contrib/size v0.0.0-20230212012657-e14a14094dc4 @@ -34,7 +31,7 @@ require ( github.com/go-ldap/ldap/v3 v3.4.6 github.com/go-viper/mapstructure/v2 v2.1.0 github.com/go-webauthn/webauthn v0.9.4 - github.com/google/pprof v0.0.0-20240827171923-fa2c70bbbfe5 + github.com/google/pprof v0.0.0-20240711041743-f6c9dda6c6da github.com/google/uuid v1.6.0 github.com/gorilla/securecookie v1.1.2 github.com/gorilla/sessions v1.2.2 @@ -55,45 +52,44 @@ require ( github.com/jonboulle/clockwork v0.4.0 github.com/jpillora/backoff v1.0.0 github.com/kylelemons/godebug v1.1.0 - github.com/leanovate/gopter v0.2.11 + github.com/leanovate/gopter v0.2.10-0.20210127095200-9abe2343507a github.com/lib/pq v1.10.9 github.com/manyminds/api2go v0.0.0-20171030193247-e7b693844a6f github.com/mitchellh/go-homedir v1.1.0 github.com/mr-tron/base58 v1.2.0 github.com/olekukonko/tablewriter v0.0.5 - github.com/onsi/gomega v1.34.2 + github.com/onsi/gomega v1.33.1 github.com/patrickmn/go-cache v2.1.0+incompatible github.com/pelletier/go-toml v1.9.5 - github.com/pelletier/go-toml/v2 v2.2.3 + github.com/pelletier/go-toml/v2 v2.2.2 github.com/pkg/errors v0.9.1 github.com/pressly/goose/v3 v3.21.1 - github.com/prometheus/client_golang v1.20.5 + github.com/prometheus/client_golang v1.20.0 github.com/prometheus/client_model v0.6.1 - github.com/prometheus/common v0.60.0 + github.com/prometheus/common v0.59.1 github.com/prometheus/prometheus v0.54.1 github.com/robfig/cron/v3 v3.0.1 - github.com/rogpeppe/go-internal v1.13.1 + github.com/rogpeppe/go-internal v1.12.0 github.com/rs/zerolog v1.33.0 github.com/scylladb/go-reflectx v1.0.1 github.com/shirou/gopsutil/v3 v3.24.3 github.com/shopspring/decimal v1.4.0 - github.com/smartcontractkit/chain-selectors v1.0.34 + github.com/smartcontractkit/chain-selectors v1.0.29 github.com/smartcontractkit/chainlink-automation v0.8.1 - github.com/smartcontractkit/chainlink-ccip v0.0.0-20241218114855-f74219171000 - github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20241223194433-f25773de7c0e - github.com/smartcontractkit/chainlink-common v0.4.1-0.20241217120918-bbe318cd0760 - github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241202195413-82468150ac1e - github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20241216163550-fa030d178ba3 + github.com/smartcontractkit/chainlink-ccip v0.0.0-20241118091009-43c2b4804cec + github.com/smartcontractkit/chainlink-common v0.3.1-0.20241114134822-aadff98ef068 + github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241017133723-5277829bd53f + github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20241018134907-a00ba3729b5e github.com/smartcontractkit/chainlink-feeds v0.1.1 - github.com/smartcontractkit/chainlink-protos/orchestrator v0.4.0 - github.com/smartcontractkit/chainlink-solana v1.1.1-0.20241219173444-150f7443fdd3 - github.com/smartcontractkit/chainlink-starknet/relayer v0.1.1-0.20241202202529-2033490e77b8 + github.com/smartcontractkit/chainlink-protos/orchestrator v0.3.0 + github.com/smartcontractkit/chainlink-solana v1.1.1-0.20241115191142-8b8369c1f44e + github.com/smartcontractkit/chainlink-starknet/relayer v0.1.1-0.20241017135645-176a23722fd8 github.com/smartcontractkit/libocr v0.0.0-20241007185508-adbe57025f12 github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20241009055228-33d0c0bf38de github.com/smartcontractkit/tdh2/go/tdh2 v0.0.0-20241009055228-33d0c0bf38de - github.com/smartcontractkit/wsrpc v0.8.3 + github.com/smartcontractkit/wsrpc v0.8.2 github.com/spf13/cast v1.6.0 - github.com/stretchr/testify v1.10.0 + github.com/stretchr/testify v1.9.0 github.com/test-go/testify v1.1.4 github.com/theodesp/go-heaps v0.0.0-20190520121037-88e35354fe0a github.com/tidwall/gjson v1.17.0 @@ -108,18 +104,17 @@ require ( go.opentelemetry.io/contrib/instrumentation/github.com/gin-gonic/gin/otelgin v0.49.0 go.opentelemetry.io/otel v1.31.0 go.opentelemetry.io/otel/metric v1.31.0 - go.opentelemetry.io/otel/sdk/metric v1.31.0 go.opentelemetry.io/otel/trace v1.31.0 go.uber.org/multierr v1.11.0 go.uber.org/zap v1.27.0 - golang.org/x/crypto v0.31.0 - golang.org/x/exp v0.0.0-20241210194714-1829a127f884 - golang.org/x/mod v0.22.0 - golang.org/x/sync v0.10.0 - golang.org/x/term v0.27.0 - golang.org/x/text v0.21.0 + golang.org/x/crypto v0.28.0 + golang.org/x/exp v0.0.0-20241009180824-f66d83c29e7c + golang.org/x/mod v0.21.0 + golang.org/x/sync v0.8.0 + golang.org/x/term v0.25.0 + golang.org/x/text v0.19.0 golang.org/x/time v0.7.0 - golang.org/x/tools v0.28.0 + golang.org/x/tools v0.26.0 gonum.org/v1/gonum v0.15.1 google.golang.org/grpc v1.67.1 google.golang.org/protobuf v1.35.1 @@ -132,6 +127,7 @@ require ( cel.dev/expr v0.17.0 // indirect cloud.google.com/go/auth v0.9.9 // indirect cloud.google.com/go/storage v1.45.0 // indirect + contrib.go.opencensus.io/exporter/stackdriver v0.13.5 // indirect cosmossdk.io/api v0.3.1 // indirect cosmossdk.io/core v0.5.1 // indirect cosmossdk.io/depinject v1.0.0-alpha.4 // indirect @@ -149,7 +145,6 @@ require ( github.com/Masterminds/goutils v1.1.1 // indirect github.com/Microsoft/go-winio v0.6.2 // indirect github.com/VictoriaMetrics/fastcache v1.12.2 // indirect - github.com/apache/arrow-go/v18 v18.0.0 // indirect github.com/armon/go-metrics v0.4.1 // indirect github.com/atombender/go-jsonschema v0.16.1-0.20240916205339-a74cd4e2851c // indirect github.com/bahlo/generic-list-go v0.2.0 // indirect @@ -160,14 +155,13 @@ require ( github.com/blendle/zapdriver v1.3.1 // indirect github.com/buger/jsonparser v1.1.1 // indirect github.com/bytecodealliance/wasmtime-go/v23 v23.0.0 // indirect - github.com/bytedance/sonic v1.11.6 // indirect - github.com/bytedance/sonic/loader v0.1.1 // indirect + github.com/bytedance/sonic v1.10.1 // indirect github.com/cenkalti/backoff v2.2.1+incompatible // indirect github.com/cenkalti/backoff/v4 v4.3.0 // indirect github.com/cespare/xxhash v1.1.0 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect - github.com/cloudwego/base64x v0.1.4 // indirect - github.com/cloudwego/iasm v0.2.0 // indirect + github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d // indirect + github.com/chenzhuoyu/iasm v0.9.0 // indirect github.com/cockroachdb/errors v1.11.3 // indirect github.com/cockroachdb/fifo v0.0.0-20240606204812-0bbfbd93a7ce // indirect github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b // indirect @@ -192,7 +186,8 @@ require ( github.com/crate-crypto/go-kzg-4844 v1.0.0 // indirect github.com/danieljoos/wincred v1.1.2 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect - github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 // indirect + github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 // indirect + github.com/dfuse-io/logging v0.0.0-20210109005628-b97a57253f70 // indirect github.com/dgraph-io/badger/v2 v2.2007.4 // indirect github.com/dgraph-io/ristretto v0.1.1 // indirect github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13 // indirect @@ -204,6 +199,7 @@ require ( github.com/ethereum/go-verkle v0.1.1-0.20240829091221-dffa7562dbe9 // indirect github.com/fsnotify/fsnotify v1.7.0 // indirect github.com/gabriel-vasile/mimetype v1.4.3 // indirect + github.com/gagliardetto/binary v0.7.7 // indirect github.com/gagliardetto/treeout v0.1.4 // indirect github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08 // indirect github.com/gedex/inflector v0.0.0-20170307190818-16278e9db813 // indirect @@ -220,7 +216,7 @@ require ( github.com/go-playground/universal-translator v0.18.1 // indirect github.com/go-playground/validator/v10 v10.22.0 // indirect github.com/go-webauthn/x v0.1.5 // indirect - github.com/goccy/go-json v0.10.3 // indirect + github.com/goccy/go-json v0.10.2 // indirect github.com/goccy/go-yaml v1.12.0 // indirect github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2 // indirect github.com/gofrs/flock v0.8.1 // indirect @@ -229,10 +225,10 @@ require ( github.com/golang-jwt/jwt/v4 v4.5.0 // indirect github.com/golang-jwt/jwt/v5 v5.2.1 // indirect github.com/golang/glog v1.2.2 // indirect + github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/golang/protobuf v1.5.4 // indirect github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb // indirect github.com/google/btree v1.1.2 // indirect - github.com/google/flatbuffers v24.3.25+incompatible // indirect github.com/google/go-cmp v0.6.0 // indirect github.com/google/go-tpm v0.9.0 // indirect github.com/google/gofuzz v1.2.0 // indirect @@ -270,8 +266,8 @@ require ( github.com/jackpal/go-nat-pmp v1.0.2 // indirect github.com/jmhodges/levigo v1.0.0 // indirect github.com/json-iterator/go v1.1.12 // indirect - github.com/klauspost/compress v1.17.11 // indirect - github.com/klauspost/cpuid/v2 v2.2.8 // indirect + github.com/klauspost/compress v1.17.9 // indirect + github.com/klauspost/cpuid/v2 v2.2.5 // indirect github.com/kr/pretty v0.3.1 // indirect github.com/kr/text v0.2.0 // indirect github.com/leodido/go-urn v1.4.0 // indirect @@ -280,7 +276,6 @@ require ( github.com/logrusorgru/aurora v2.0.3+incompatible // indirect github.com/magiconair/properties v1.8.7 // indirect github.com/mailru/easyjson v0.7.7 // indirect - github.com/marcboeker/go-duckdb v1.8.3 // indirect github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.20 // indirect github.com/mattn/go-runewidth v0.0.14 // indirect @@ -300,11 +295,9 @@ require ( github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect github.com/oklog/run v1.1.0 // indirect github.com/opencontainers/go-digest v1.0.0 // indirect - github.com/opencontainers/image-spec v1.1.0 // indirect github.com/opencontainers/runc v1.1.10 // indirect github.com/opentracing/opentracing-go v1.2.0 // indirect github.com/petermattis/goid v0.0.0-20230317030725-371a4b8eda08 // indirect - github.com/pierrec/lz4/v4 v4.1.21 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect github.com/prometheus/procfs v0.15.1 // indirect @@ -326,12 +319,13 @@ require ( github.com/spf13/pflag v1.0.5 // indirect github.com/spf13/viper v1.19.0 // indirect github.com/status-im/keycard-go v0.2.0 // indirect - github.com/streamingfast/logging v0.0.0-20230608130331-f22c91403091 // indirect + github.com/streamingfast/logging v0.0.0-20220405224725-2755dab2ce75 // indirect github.com/stretchr/objx v0.5.2 // indirect github.com/subosito/gotenv v1.6.0 // indirect github.com/supranational/blst v0.3.13 // indirect github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d // indirect github.com/tendermint/go-amino v0.16.0 // indirect + github.com/teris-io/shortid v0.0.0-20201117134242-e59966efd125 // indirect github.com/tidwall/btree v1.6.0 // indirect github.com/tidwall/match v1.1.1 // indirect github.com/tidwall/pretty v1.2.1 // indirect @@ -345,12 +339,12 @@ require ( github.com/x448/float16 v0.8.4 // indirect github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect github.com/yusufpapurcu/wmi v1.2.4 // indirect - github.com/zeebo/xxh3 v1.0.2 // indirect github.com/zondax/hid v0.9.2 // indirect github.com/zondax/ledger-go v0.14.3 // indirect go.dedis.ch/protobuf v1.0.11 // indirect go.etcd.io/bbolt v1.3.9 // indirect go.mongodb.org/mongo-driver v1.15.0 // indirect + go.opencensus.io v0.24.0 // indirect go.opentelemetry.io/contrib/detectors/gcp v1.31.0 // indirect go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.56.0 // indirect go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.56.0 // indirect @@ -367,11 +361,13 @@ require ( go.opentelemetry.io/otel/log v0.6.0 // indirect go.opentelemetry.io/otel/sdk v1.31.0 // indirect go.opentelemetry.io/otel/sdk/log v0.6.0 // indirect + go.opentelemetry.io/otel/sdk/metric v1.31.0 // indirect go.opentelemetry.io/proto/otlp v1.3.1 // indirect - go.uber.org/ratelimit v0.3.1 // indirect + go.uber.org/ratelimit v0.3.0 // indirect golang.org/x/arch v0.11.0 // indirect - golang.org/x/net v0.32.0 // indirect - golang.org/x/sys v0.28.0 // indirect + golang.org/x/net v0.30.0 // indirect + golang.org/x/oauth2 v0.23.0 // indirect + golang.org/x/sys v0.26.0 // indirect golang.org/x/xerrors v0.0.0-20240903120638-7835f813f4da // indirect google.golang.org/api v0.202.0 // indirect google.golang.org/genproto v0.0.0-20241021214115-324edc3d5d38 // indirect diff --git a/go.sum b/go.sum index 0c9654d1fb5..270966b2a91 100644 --- a/go.sum +++ b/go.sum @@ -3,6 +3,7 @@ cel.dev/expr v0.17.0/go.mod h1:HCwbrn+qQoHPXgfz6cl2J0hDybnX2N1sQQkl9EggXx8= cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= +cloud.google.com/go v0.43.0/go.mod h1:BOSR3VbTLkk6FDC/TcffxP4NF/FFBGA5ku+jvKOP7pg= cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= @@ -10,16 +11,7 @@ cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4= cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M= -cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc= cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk= -cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs= -cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc= -cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= -cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI= -cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk= -cloud.google.com/go v0.78.0/go.mod h1:QjdrLG0uq+YwhjoVOLsS1t7TW8fs36kLs4XO5R5ECHg= -cloud.google.com/go v0.79.0/go.mod h1:3bzgcEeQlzbuEAYu4mrWhKqWjmpprinYgKJLgKHnbb8= -cloud.google.com/go v0.81.0/go.mod h1:mk/AM35KwGk/Nm2YSeZbxXdrNK3KZOYHmLkOqC2V6E0= cloud.google.com/go v0.116.0 h1:B3fRrSDkLRt5qSHWe40ERJvhvnQwdZiHu0bJOpldweE= cloud.google.com/go v0.116.0/go.mod h1:cEPSRWPzZEswwdr9BxE6ChEn01dWlTaF05LiC2Xs70U= cloud.google.com/go/auth v0.9.9 h1:BmtbpNQozo8ZwW2t7QJjnrQtdganSdmqeIBxHxNkEZQ= @@ -29,9 +21,6 @@ cloud.google.com/go/auth/oauth2adapt v0.2.4/go.mod h1:jC/jOpwFP6JBxhB3P5Rr0a9HLM cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= -cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= -cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= -cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= cloud.google.com/go/compute v1.28.1 h1:XwPcZjgMCnU2tkwY10VleUjSAfpTj9RDn+kGrbYsi8o= cloud.google.com/go/compute/metadata v0.5.2 h1:UxK4uu/Tn+I3p2dYWTfiX4wva7aYlKixAHn3fyqngqo= cloud.google.com/go/compute/metadata v0.5.2/go.mod h1:C66sj2AluDcIqakBq/M8lw8/ybHgOZqin2obFxa/E5k= @@ -45,14 +34,15 @@ cloud.google.com/go/monitoring v1.21.1/go.mod h1:Rj++LKrlht9uBi8+Eb530dIrzG/cU/l cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= -cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU= cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= -cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= -cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= cloud.google.com/go/storage v1.45.0 h1:5av0QcIVj77t+44mV4gffFC/LscFRUhto6UBMB5SimM= cloud.google.com/go/storage v1.45.0/go.mod h1:wpPblkIuMP5jCB/E48Pz9zIo2S/zD8g+ITmxKkPCITE= +contrib.go.opencensus.io/exporter/stackdriver v0.12.6/go.mod h1:8x999/OcIPy5ivx/wDiV7Gx4D+VUPODf0mWRGRc5kSk= +contrib.go.opencensus.io/exporter/stackdriver v0.13.4/go.mod h1:aXENhDJ1Y4lIg4EUaVTwzvYETVNZk10Pu26tevFKLUc= +contrib.go.opencensus.io/exporter/stackdriver v0.13.5 h1:TNaexHK16gPUoc7uzELKOU7JULqccn1NDuqUxmxSqfo= +contrib.go.opencensus.io/exporter/stackdriver v0.13.5/go.mod h1:aXENhDJ1Y4lIg4EUaVTwzvYETVNZk10Pu26tevFKLUc= cosmossdk.io/api v0.3.1 h1:NNiOclKRR0AOlO4KIqeaG6PS6kswOMhHD0ir0SscNXE= cosmossdk.io/api v0.3.1/go.mod h1:DfHfMkiNA2Uhy8fj0JJlOCYOBp4eWUUJ1te5zBGNyIw= cosmossdk.io/core v0.5.1 h1:vQVtFrIYOQJDV3f7rw4pjjVqc1id4+mE0L9hHP66pyI= @@ -68,6 +58,7 @@ cosmossdk.io/math v1.3.0/go.mod h1:vnRTxewy+M7BtXBNFybkuhSH4WfedVAAnERHgVFhp3k= cosmossdk.io/tools/rosetta v0.2.1 h1:ddOMatOH+pbxWbrGJKRAawdBkPYLfKXutK9IETnjYxw= cosmossdk.io/tools/rosetta v0.2.1/go.mod h1:Pqdc1FdvkNV3LcNIkYWt2RQY6IP1ge6YWZk8MhhO9Hw= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= +filippo.io/edwards25519 v1.0.0-rc.1/go.mod h1:N1IkdkCkiLB6tki+MYJoSx2JTY9NUlxZE7eHn5EwJns= filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 h1:/vQbFIOMbk2FiG/kXiLl8BRyzTWDw7gX/Hz7Dd5eDMs= @@ -94,6 +85,8 @@ github.com/DataDog/zstd v1.5.2 h1:vUG4lAyuPCXO0TLbXvPv7EB7cNK1QV/luu55UHLrrn8= github.com/DataDog/zstd v1.5.2/go.mod h1:g4AWEaM3yOg3HYfnJ3YIawPnVdXJh9QME85blwSAmyw= github.com/Depado/ginprom v1.8.0 h1:zaaibRLNI1dMiiuj1MKzatm8qrcHzikMlCc1anqOdyo= github.com/Depado/ginprom v1.8.0/go.mod h1:XBaKzeNBqPF4vxJpNLincSQZeMDnZp1tIbU0FU0UKgg= +github.com/GeertJohan/go.incremental v1.0.0/go.mod h1:6fAjUhbVuX1KcMD3c8TEgVUqmo4seqhv0i0kdATSkM0= +github.com/GeertJohan/go.rice v1.0.0/go.mod h1:eH6gbSOAUv07dQuZVnBmoDP8mgsM1rtixis4Tib9if0= github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.24.3 h1:cb3br57K508pQEFgBxn9GDhPS9HefpyMPK1RzmtMNzk= github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.24.3/go.mod h1:itPGVDKf9cC/ov4MdvJ2QZ0khw4bfoo9jzwTJlaxy2k= github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.48.3 h1:xir5X8TS8UBVPWg2jHL+cSTf0jZgqYQSA54TscSt1/0= @@ -104,8 +97,8 @@ github.com/Masterminds/goutils v1.1.1 h1:5nUrii3FMTL5diU80unEVvNevw1nH4+ZV4DSLVJ github.com/Masterminds/goutils v1.1.1/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU= github.com/Masterminds/semver/v3 v3.1.1/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs= github.com/Masterminds/semver/v3 v3.2.0/go.mod h1:qvl/7zhW3nngYb5+80sSMF+FG2BjYrf8m9wsX0PNOMQ= -github.com/Masterminds/semver/v3 v3.3.0 h1:B8LGeaivUe71a5qox1ICM/JLl0NqZSW5CHyL+hmvYS0= -github.com/Masterminds/semver/v3 v3.3.0/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM= +github.com/Masterminds/semver/v3 v3.2.1 h1:RN9w6+7QoMeJVGyfmbcgs28Br8cvmnucEXnY0rYXWg0= +github.com/Masterminds/semver/v3 v3.2.1/go.mod h1:qvl/7zhW3nngYb5+80sSMF+FG2BjYrf8m9wsX0PNOMQ= github.com/Masterminds/sprig/v3 v3.2.3 h1:eL2fZNezLomi0uOLqjQoN6BfsDD+fyLtgbJMAj9n6YA= github.com/Masterminds/sprig/v3 v3.2.3/go.mod h1:rXcFaZ2zZbLRJv/xSysmlgIM1u11eBaRMhvYXJNkGuM= github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY= @@ -125,6 +118,7 @@ github.com/VividCortex/gohistogram v1.0.0 h1:6+hBz+qvs0JOrrNhhmR7lFxo5sINxBCGXrd github.com/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/4+TcAqDqk/vUH7g= github.com/XSAM/otelsql v0.27.0 h1:i9xtxtdcqXV768a5C6SoT/RkG+ue3JTOgkYInzlTOqs= github.com/XSAM/otelsql v0.27.0/go.mod h1:0mFB3TvLa7NCuhm/2nU7/b2wEtsczkj8Rey8ygO7V+A= +github.com/akavel/rsrc v0.8.0/go.mod h1:uLoCtb9J+EyAqh+26kdrTgmzRBFPGOolLWKpdxkKq+c= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= @@ -134,13 +128,10 @@ github.com/alexbrainman/sspi v0.0.0-20210105120005-909beea2cc74/go.mod h1:cEWa1L github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM= github.com/allegro/bigcache v1.2.1 h1:hg1sY1raCwic3Vnsvje6TT7/pnZba83LeFck5NrFKSc= github.com/allegro/bigcache v1.2.1/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM= -github.com/andybalholm/brotli v1.1.1 h1:PR2pgnyFznKEugtsUo0xLdDop5SKXd5Qf5ysW+7XdTA= -github.com/andybalholm/brotli v1.1.1/go.mod h1:05ib4cKhjx3OQYUY22hTVd34Bc8upXjOLL2rKwwZBoA= +github.com/andres-erbsen/clock v0.0.0-20160526145045-9e14626cd129/go.mod h1:rFgpPQZYZ8vdbc+48xibu8ALc3yeyd64IhHS+PU6Yyg= +github.com/andybalholm/brotli v1.1.0 h1:eLKJA0d02Lf0mVpIDgYnqXcUn0GqVmEFny3VuID1U3M= +github.com/andybalholm/brotli v1.1.0/go.mod h1:sms7XGricyQI9K10gOSf56VKKWS4oLer58Q+mhRPtnY= github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= -github.com/apache/arrow-go/v18 v18.0.0 h1:1dBDaSbH3LtulTyOVYaBCHO3yVRwjV+TZaqn3g6V7ZM= -github.com/apache/arrow-go/v18 v18.0.0/go.mod h1:t6+cWRSmKgdQ6HsxisQjok+jBpKGhRDiqcf3p0p/F+A= -github.com/apache/thrift v0.21.0 h1:tdPmh/ptjE1IJnhbhrcl2++TauVjy242rkV/UzJChnE= -github.com/apache/thrift v0.21.0/go.mod h1:W1H8aR/QRtYNvrPeFXBtobyRkd0/YVhTc6i07XIAgDw= github.com/appleboy/gofight/v2 v2.1.2 h1:VOy3jow4vIK8BRQJoC/I9muxyYlJ2yb9ht2hZoS3rf4= github.com/appleboy/gofight/v2 v2.1.2/go.mod h1:frW+U1QZEdDgixycTj4CygQ48yLTUhplt43+Wczp3rw= github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= @@ -153,6 +144,8 @@ github.com/atombender/go-jsonschema v0.16.1-0.20240916205339-a74cd4e2851c h1:cxQ github.com/atombender/go-jsonschema v0.16.1-0.20240916205339-a74cd4e2851c/go.mod h1:3XzxudkrYVUvbduN/uI2fl4lSrMSzU0+3RCu2mpnfx8= github.com/avast/retry-go/v4 v4.6.0 h1:K9xNA+KeB8HHc2aWFuLb25Offp+0iVRXEvFx8IinRJA= github.com/avast/retry-go/v4 v4.6.0/go.mod h1:gvWlPhBVsvBbLkVGDg/KwvBv0bEkCOLRRSHKIr2PyOE= +github.com/aws/aws-sdk-go v1.22.1/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= +github.com/aws/aws-sdk-go v1.23.20/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= github.com/aws/aws-sdk-go v1.54.19 h1:tyWV+07jagrNiCcGRzRhdtVjQs7Vy41NwsuOcl0IbVI= github.com/aws/aws-sdk-go v1.54.19/go.mod h1:eRwEWoyTWFMVYVQzKMNHWP5/RV4xIUGMQfXQHfHkpNU= github.com/bahlo/generic-list-go v0.2.0 h1:5sz/EEAK+ls5wF+NeqDpk5+iNdMDXrh3z3nPnH1Wvgk= @@ -171,26 +164,26 @@ github.com/bgentry/speakeasy v0.1.1-0.20220910012023-760eaf8b6816 h1:41iFGWnSlI2 github.com/bgentry/speakeasy v0.1.1-0.20220910012023-760eaf8b6816/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= github.com/bits-and-blooms/bitset v1.13.0 h1:bAQ9OPNFYbGHV6Nez0tmNI0RiEu7/hxlYJRUA0wFAVE= github.com/bits-and-blooms/bitset v1.13.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8= -github.com/bketelsen/crypt v0.0.4/go.mod h1:aI6NrJ0pMGgvZKL1iVgXLnfIFJtfV+bKCoqOes/6LfM= +github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84= github.com/blendle/zapdriver v1.3.1 h1:C3dydBOWYRiOk+B8X9IVZ5IOe+7cl+tGOexN4QqHfpE= github.com/blendle/zapdriver v1.3.1/go.mod h1:mdXfREi6u5MArG4j9fewC+FGnXaBR+T4Ox4J2u4eHCc= github.com/btcsuite/btcd v0.22.1 h1:CnwP9LM/M9xuRrGSCGeMVs9iv09uMqwsVX7EeIpgV2c= github.com/btcsuite/btcd/btcec/v2 v2.3.2 h1:5n0X6hX0Zk+6omWcihdYvdAlGf2DfasC0GMf7DClJ3U= github.com/btcsuite/btcd/btcec/v2 v2.3.2/go.mod h1:zYzJ8etWJQIv1Ogk7OzpWjowwOdXY1W/17j2MW85J04= -github.com/btcsuite/btcd/btcutil v1.1.5 h1:+wER79R5670vs/ZusMTF1yTcRYE5GUsFbdjdisflzM8= -github.com/btcsuite/btcd/btcutil v1.1.5/go.mod h1:PSZZ4UitpLBWzxGd5VGOrLnmOjtPP/a6HaFo12zMs00= -github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0 h1:59Kx4K6lzOW5w6nFlA0v5+lk/6sjybR934QNHSJZPTQ= -github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= +github.com/btcsuite/btcd/btcutil v1.1.3 h1:xfbtw8lwpp0G6NwSHb+UE67ryTFHJAiNuipusjXSohQ= +github.com/btcsuite/btcd/btcutil v1.1.3/go.mod h1:UR7dsSJzJUfMmFiiLlIrMq1lS9jh9EdCV7FStZSnpi0= +github.com/btcsuite/btcd/chaincfg/chainhash v1.0.3 h1:SDlJ7bAm4ewvrmZtR0DaiYbQGdKPeaaIm7bM+qRhFeU= +github.com/btcsuite/btcd/chaincfg/chainhash v1.0.3/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= github.com/bufbuild/protocompile v0.4.0 h1:LbFKd2XowZvQ/kajzguUp2DC9UEIQhIq77fZZlaQsNA= github.com/bufbuild/protocompile v0.4.0/go.mod h1:3v93+mbWn/v3xzN+31nwkJfrEpAUwp+BagBSZWx+TP8= github.com/buger/jsonparser v1.1.1 h1:2PnMjfWD7wBILjqQbt530v576A/cAbQvEW9gGIpYMUs= github.com/buger/jsonparser v1.1.1/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx27UK13J/0= github.com/bytecodealliance/wasmtime-go/v23 v23.0.0 h1:NJvU4S8KEk1GnF6+FvlnzMD/8wXTj/mYJSG6Q4yu3Pw= github.com/bytecodealliance/wasmtime-go/v23 v23.0.0/go.mod h1:5YIL+Ouiww2zpO7u+iZ1U1G5NvmwQYaXdmCZQGjQM0U= -github.com/bytedance/sonic v1.11.6 h1:oUp34TzMlL+OY1OUWxHqsdkgC/Zfc85zGqw9siXjrc0= -github.com/bytedance/sonic v1.11.6/go.mod h1:LysEHSvpvDySVdC2f87zGWf6CIKJcAvqab1ZaiQtds4= -github.com/bytedance/sonic/loader v0.1.1 h1:c+e5Pt1k/cy5wMveRDyk2X4B9hF4g7an8N3zCYjJFNM= -github.com/bytedance/sonic/loader v0.1.1/go.mod h1:ncP89zfokxS5LZrJxl5z0UJcsk4M4yY2JpfqGeCtNLU= +github.com/bytedance/sonic v1.5.0/go.mod h1:ED5hyg4y6t3/9Ku1R6dU/4KyJ48DZ4jPhfY1O2AihPM= +github.com/bytedance/sonic v1.10.0-rc/go.mod h1:ElCzW+ufi8qKqNW0FY314xriJhyJhuoJ3gFZdAHF7NM= +github.com/bytedance/sonic v1.10.1 h1:7a1wuFXL1cMy7a3f7/VFcEtriuXQnUBhtoVfOZiaysc= +github.com/bytedance/sonic v1.10.1/go.mod h1:iZcSUejdk5aukTND/Eu/ivjQuEL0Cu9/rf50Hi0u/g4= github.com/cenkalti/backoff v2.2.1+incompatible h1:tNowT99t7UNflLxfYYSlKYsBpXdEet03Pg2g16Swow4= github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM= github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= @@ -206,6 +199,12 @@ github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XL github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/chenzhuoyu/base64x v0.0.0-20211019084208-fb5309c8db06/go.mod h1:DH46F32mSOjUmXrMHnKwZdA8wcEefY7UVqBKYGjpdQY= +github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311/go.mod h1:b583jCggY9gE99b6G5LEC39OIiVsWj+R97kbl5odCEk= +github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d h1:77cEq6EriyTZ0g/qfRdp61a3Uu/AWrgIq2s0ClJV1g0= +github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d/go.mod h1:8EPpVsBuRksnlj1mLy4AWzRNQYxauNi62uWcE3to6eA= +github.com/chenzhuoyu/iasm v0.9.0 h1:9fhXjVzq5hUy2gkhhgHl95zG2cEAhw9OSGs8toWWAwo= +github.com/chenzhuoyu/iasm v0.9.0/go.mod h1:Xjy2NpN3h7aUqeqM+woSuuvxmIe6+DDsiNLIrkAmYog= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= github.com/chzyer/readline v1.5.1 h1:upd/6fQk4src78LMRzh5vItIt361/o4uq553V8B5sGI= @@ -214,12 +213,7 @@ github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMn github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6Dob7S7YxXgwXpfOuvO54S+tGdZdw9fuRZt25Ag= github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= -github.com/cloudwego/base64x v0.1.4 h1:jwCgWpFanWmN8xoIUHa2rtzmkd5J2plF/dnLS6Xd/0Y= -github.com/cloudwego/base64x v0.1.4/go.mod h1:0zlkT4Wn5C6NdauXdJRhSKRlJvmclQ1hhJgA0rcu/8w= -github.com/cloudwego/iasm v0.2.0 h1:1KNIy1I1H9hNNFEEH3DVnI4UujN+1zjpuk6gwHLTssg= -github.com/cloudwego/iasm v0.2.0/go.mod h1:8rXZaNYT2n95jn+zTI1sDr+IgcD2GVs0nlbbQPiEFhY= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= -github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cncf/xds/go v0.0.0-20240905190251-b4127c9b8d78 h1:QVw89YDxXxEe+l8gU8ETbOasdwEV+avkR75ZzsVV9WI= github.com/cncf/xds/go v0.0.0-20240905190251-b4127c9b8d78/go.mod h1:W+zGtBO5Y1IgJhy4+A9GOqVhqLpfZi+vwmdNXUehLA8= @@ -255,14 +249,16 @@ github.com/consensys/gnark-crypto v0.12.1 h1:lHH39WuuFgVHONRl3J0LRBtuYdQTumFSDtJ github.com/consensys/gnark-crypto v0.12.1/go.mod h1:v2Gy7L/4ZRosZ7Ivs+9SfUDr0f5UlG+EM5t7MPHiLuY= github.com/containerd/continuity v0.4.3 h1:6HVkalIp+2u1ZLH1J/pYX2oBVXlJZvh1X1A7bEZ9Su8= github.com/containerd/continuity v0.4.3/go.mod h1:F6PTNCKepoxEaXLQp3wDAjygEnImnZ/7o4JzpodfroQ= +github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= +github.com/coreos/etcd v3.3.13+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk= github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= -github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= +github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= github.com/cosmos/btcutil v1.0.5 h1:t+ZFcX77LpKtDBhjucvnOH8C2l2ioGsBNEQ3jef8xFk= github.com/cosmos/btcutil v1.0.5/go.mod h1:IyB7iuqZMJlthe2tkIFL33xPyzbFYP0XVdS8P5lUPis= github.com/cosmos/cosmos-proto v1.0.0-beta.5 h1:eNcayDLpip+zVLRLYafhzLvQlSmyab+RC5W7ZfmxJLA= @@ -299,6 +295,7 @@ github.com/creachadair/taskgroup v0.4.2 h1:jsBLdAJE42asreGss2xZGZ8fJra7WtwnHWeJF github.com/creachadair/taskgroup v0.4.2/go.mod h1:qiXUOSrbwAY3u0JPGTzObbE3yf9hcXHDKBZ2ZjpCbgM= github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= +github.com/daaku/go.zipexe v1.0.0/go.mod h1:z8IiR6TsVLEYKwXAoE/I+8ys/sDkgTzSL0CLnGVd57E= github.com/danieljoos/wincred v1.1.2 h1:QLdCxFs1/Yl4zduvBdcHB8goaYk9RARS2SgLLRuAyr0= github.com/danieljoos/wincred v1.1.2/go.mod h1:GijpziifJoIBfYh+S7BbkdUTU4LfM+QnGqR5Vl2tAx0= github.com/danielkov/gin-helmet v0.0.0-20171108135313-1387e224435e h1:5jVSh2l/ho6ajWhSPNN84eHEdq3dp0T7+f6r3Tc6hsk= @@ -312,18 +309,23 @@ github.com/deckarep/golang-set/v2 v2.6.0 h1:XfcQbWM1LlMB8BsJ8N9vW5ehnnPVIw0je80N github.com/deckarep/golang-set/v2 v2.6.0/go.mod h1:VAky9rY/yGXJOLEDv3OMci+7wtDpOF4IN+y82NBOac4= github.com/decred/dcrd/crypto/blake256 v1.0.1 h1:7PltbUIQB7u/FfZ39+DGa/ShuMyJ5ilcvdfma9wOH6Y= github.com/decred/dcrd/crypto/blake256 v1.0.1/go.mod h1:2OfgNZ5wDpcsFmHmCK5gZTPcCXqlm2ArzUIkw9czNJo= -github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 h1:rpfIENRNNilwHwZeG5+P150SMrnNEcHYvcCuK6dPZSg= -github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0/go.mod h1:v57UDF4pDQJcEfFUCRop3lJL149eHGSe9Jvczhzjo/0= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 h1:8UrgZ3GkP4i/CLijOJx79Yu+etlyjdBU4sfcs2WYQMs= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0/go.mod h1:v57UDF4pDQJcEfFUCRop3lJL149eHGSe9Jvczhzjo/0= github.com/desertbit/timer v0.0.0-20180107155436-c41aec40b27f h1:U5y3Y5UE0w7amNe7Z5G/twsBW0KEalRQXZzf8ufSh9I= github.com/desertbit/timer v0.0.0-20180107155436-c41aec40b27f/go.mod h1:xH/i4TFMt8koVQZ6WFms69WAsDWr2XsYL3Hkl7jkoLE= +github.com/dfuse-io/logging v0.0.0-20201110202154-26697de88c79/go.mod h1:V+ED4kT/t/lKtH99JQmKIb0v9WL3VaYkJ36CfHlVECI= +github.com/dfuse-io/logging v0.0.0-20210109005628-b97a57253f70 h1:CuJS05R9jmNlUK8GOxrEELPbfXm0EuGh/30LjkjN5vo= +github.com/dfuse-io/logging v0.0.0-20210109005628-b97a57253f70/go.mod h1:EoK/8RFbMEteaCaz89uessDTnCWjbbcr+DXcBh4el5o= github.com/dgraph-io/badger/v2 v2.2007.4 h1:TRWBQg8UrlUhaFdco01nO2uXwzKS7zd+HVdwV/GHc4o= github.com/dgraph-io/badger/v2 v2.2007.4/go.mod h1:vSw/ax2qojzbN6eXHIx6KPKtCSHJN/Uz0X0VPruTIhk= github.com/dgraph-io/ristretto v0.0.3-0.20200630154024-f66de99634de/go.mod h1:KPxhHT9ZxKefz+PCeOGsrHpl1qZ7i70dGTu2u+Ahh6E= github.com/dgraph-io/ristretto v0.1.1 h1:6CWw5tJNgpegArSHpNHJKldNeq03FQCwYvfMVWajOK8= github.com/dgraph-io/ristretto v0.1.1/go.mod h1:S1GPSBCYCIhmVNfcth17y2zZtQT6wzkzgwUve0VDWWA= +github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13 h1:fAjc9m62+UWV/WAFKLNi6ZS0675eEUC9y3AlwSbQu1Y= github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= +github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= github.com/docker/distribution v2.8.2+incompatible h1:T3de5rq0dB1j30rp0sA2rER+m322EBzniBPB6ZIzuh8= github.com/docker/distribution v2.8.2+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= @@ -340,9 +342,7 @@ github.com/dvsekhvalnov/jose2go v1.7.0/go.mod h1:QsHjhyTlD/lAVqn/NSbVZmSCGeDehTB github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= -github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po= github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= -github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= github.com/envoyproxy/go-control-plane v0.13.1 h1:vPfJZCkob6yTMEgS+0TwfTUfbHjfy/6vOJ8hUWX/uXE= github.com/envoyproxy/go-control-plane v0.13.1/go.mod h1:X45hY0mufo6Fd0KW3rqsGvQMw58jvjymeCzBU3mWyHw= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= @@ -357,6 +357,7 @@ github.com/ethereum/go-ethereum v1.14.11/go.mod h1:+l/fr42Mma+xBnhefL/+z11/hcmJ2 github.com/ethereum/go-verkle v0.1.1-0.20240829091221-dffa7562dbe9 h1:8NfxH2iXvJ60YRB8ChToFTUzl8awsc3cJ8CbLjGIl/A= github.com/ethereum/go-verkle v0.1.1-0.20240829091221-dffa7562dbe9/go.mod h1:M3b90YRnzqKyyzBEWJGqj8Qff4IDeXnzFw0P9bFw3uk= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= +github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU= github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= github.com/fatih/color v1.17.0 h1:GlRw1BRJxkpqUCBKzKOw098ed57fEsKeNjpTe3cSjK4= github.com/fatih/color v1.17.0/go.mod h1:YZ7TlrGPkiz6ku9fK3TLD/pl3CpsiFyu8N92HLgmosI= @@ -375,12 +376,12 @@ github.com/fxamacker/cbor/v2 v2.7.0 h1:iM5WgngdRBanHcxugY4JySA0nk1wZorNOpTgCMedv github.com/fxamacker/cbor/v2 v2.7.0/go.mod h1:pxXPTn3joSm21Gbwsv0w9OSA2y1HFR9qXEeXQVeNoDQ= github.com/gabriel-vasile/mimetype v1.4.3 h1:in2uUcidCuFcDKtdcBxlR0rJ1+fsokWf+uqxgUFjbI0= github.com/gabriel-vasile/mimetype v1.4.3/go.mod h1:d8uq/6HKRL6CGdk+aubisF/M5GcPfT7nKyLpA0lbSSk= -github.com/gagliardetto/binary v0.8.0 h1:U9ahc45v9HW0d15LoN++vIXSJyqR/pWw8DDlhd7zvxg= -github.com/gagliardetto/binary v0.8.0/go.mod h1:2tfj51g5o9dnvsc+fL3Jxr22MuWzYXwx9wEoN0XQ7/c= +github.com/gagliardetto/binary v0.7.7 h1:QZpT38+sgoPg+TIQjH94sLbl/vX+nlIRA37pEyOsjfY= +github.com/gagliardetto/binary v0.7.7/go.mod h1:mUuay5LL8wFVnIlecHakSZMvcdqfs+CsotR5n77kyjM= github.com/gagliardetto/gofuzz v1.2.2 h1:XL/8qDMzcgvR4+CyRQW9UGdwPRPMHVJfqQ/uMvSUuQw= github.com/gagliardetto/gofuzz v1.2.2/go.mod h1:bkH/3hYLZrMLbfYWA0pWzXmi5TTRZnu4pMGZBkqMKvY= -github.com/gagliardetto/solana-go v1.12.0 h1:rzsbilDPj6p+/DOPXBMLhwMZeBgeRuXjm5zQFCoXgsg= -github.com/gagliardetto/solana-go v1.12.0/go.mod h1:l/qqqIN6qJJPtxW/G1PF4JtcE3Zg2vD2EliZrr9Gn5k= +github.com/gagliardetto/solana-go v1.8.4 h1:vmD/JmTlonyXGy39bAo0inMhmbdAwV7rXZtLDMZeodE= +github.com/gagliardetto/solana-go v1.8.4/go.mod h1:i+7aAyNDTHG0jK8GZIBSI4OVvDqkt2Qx+LklYclRNG8= github.com/gagliardetto/treeout v0.1.4 h1:ozeYerrLCmCubo1TcIjFiOWTTGteOOHND1twdFpgwaw= github.com/gagliardetto/treeout v0.1.4/go.mod h1:loUefvXTrlRG5rYmJmExNryyBRh8f89VZhmMOyCyqok= github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08 h1:f6D9Hr8xV8uYKlyuj8XIruxlh9WjVjdh1gIicAS7ays= @@ -390,8 +391,8 @@ github.com/gedex/inflector v0.0.0-20170307190818-16278e9db813/go.mod h1:P+oSoE9y github.com/getsentry/sentry-go v0.27.0 h1:Pv98CIbtB3LkMWmXi4Joa5OOcwbmnX88sF5qbK3r3Ps= github.com/getsentry/sentry-go v0.27.0/go.mod h1:lc76E2QywIyW8WuBnwl8Lc4bkmQH4+w1gwTf25trprY= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= -github.com/gin-contrib/cors v1.7.2 h1:oLDHxdg8W/XDoN/8zamqk/Drgt4oVZDvaV0YmvVICQw= -github.com/gin-contrib/cors v1.7.2/go.mod h1:SUJVARKgQ40dmrzgXEVxj2m7Ig1v1qIboQkPDTQ9t2E= +github.com/gin-contrib/cors v1.5.0 h1:DgGKV7DDoOn36DFkNtbHrjoRiT5ExCe+PC9/xp7aKvk= +github.com/gin-contrib/cors v1.5.0/go.mod h1:TvU7MAZ3EwrPLI2ztzTt3tqgvBCq+wn8WpZmfADjupI= github.com/gin-contrib/expvar v0.0.1 h1:IuU5ArEgihz50vG8Onrwz22kJr7Mcvgv9xSSpfU5g+w= github.com/gin-contrib/expvar v0.0.1/go.mod h1:8o2CznfQi1JjktORdHr2/abg3wSV6OCnXh0yGypvvVw= github.com/gin-contrib/sessions v0.0.5 h1:CATtfHmLMQrMNpJRgzjWXD7worTh7g7ritsQfmF+0jE= @@ -463,8 +464,8 @@ github.com/go-webauthn/webauthn v0.9.4/go.mod h1:LqupCtzSef38FcxzaklmOn7AykGKhAh github.com/go-webauthn/x v0.1.5 h1:V2TCzDU2TGLd0kSZOXdrqDVV5JB9ILnKxA9S53CSBw0= github.com/go-webauthn/x v0.1.5/go.mod h1:qbzWwcFcv4rTwtCLOZd+icnr6B7oSsAGZJqlt8cukqY= github.com/goccy/go-json v0.9.7/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= -github.com/goccy/go-json v0.10.3 h1:KZ5WoDbxAIgm2HNbYckL0se1fHD6rz5j4ywS6ebzDqA= -github.com/goccy/go-json v0.10.3/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M= +github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU= +github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= github.com/goccy/go-yaml v1.12.0 h1:/1WHjnMsI1dlIBQutrvSMGZRQufVO3asrHfTwfACoPM= github.com/goccy/go-yaml v1.12.0/go.mod h1:wKnAMd44+9JAAnGQpWVEgBzGt3YuTaQ4uXoHvE4m7WU= github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2 h1:ZpnhV/YsD2/4cESfV5+Hoeu/iUR3ruzNvZ+yQfO03a0= @@ -484,6 +485,7 @@ github.com/golang-jwt/jwt/v5 v5.2.1/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVI github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/glog v1.2.2 h1:1+mZ9upx1Dh6FmUTFR1naJ77miKiXgALjWOZ3NVFPmY= github.com/golang/glog v1.2.2/go.mod h1:6AhwSGph0fcJtXVM/PEHPqZlFeoLxhs7/t5UDAwmO+w= +github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= @@ -493,10 +495,7 @@ github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfb github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= -github.com/golang/mock v1.5.0/go.mod h1:CWnOUgYIOo4TcNZ0wHX3YZCqsaM1I1Jvs6v3mP3KVu8= github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc= github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= @@ -504,7 +503,6 @@ github.com/golang/protobuf v1.3.0/go.mod h1:Qd/q+1AKNOZr9uGQzbzCmRO6sUih6GTPZv6a github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= -github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= @@ -519,6 +517,7 @@ github.com/golang/protobuf v1.5.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= +github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb h1:PBC98N2aIaM3XXiurYmW7fx4GZkL8feAMVq7nEjURHk= @@ -527,18 +526,13 @@ github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Z github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.1.2 h1:xf4v41cLI2Z6FxbKm+8Bu+m8ifhj15JuZ9sa0jZCMUU= github.com/google/btree v1.1.2/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4= -github.com/google/flatbuffers v24.3.25+incompatible h1:CX395cjN9Kke9mmalRoL3d81AtFUxJM+yDthflgJGkI= -github.com/google/flatbuffers v24.3.25+incompatible/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE= @@ -552,8 +546,6 @@ github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/ github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= -github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= -github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= github.com/google/orderedcode v0.0.1 h1:UzfcAexk9Vhv8+9pNOgRu41f16lHq725vPwnSeiG/Us= github.com/google/orderedcode v0.0.1/go.mod h1:iVyU4/qPKHY5h/wSd6rZZCDcLJNxiWO6dvsYES2Sb20= github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= @@ -561,15 +553,9 @@ github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OI github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20240827171923-fa2c70bbbfe5 h1:5iH8iuqE5apketRbSFBy+X1V0o+l+8NF1avt4HWl7cA= -github.com/google/pprof v0.0.0-20240827171923-fa2c70bbbfe5/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144= +github.com/google/pprof v0.0.0-20240711041743-f6c9dda6c6da h1:xRmpO92tb8y+Z85iUOMOicpCfaYcv7o3Cg3wKrIpg8g= +github.com/google/pprof v0.0.0-20240711041743-f6c9dda6c6da/go.mod h1:K1liHPHnj73Fdn/EKuT8nrFqBihUSKXoLYU0BuatOYo= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/s2a-go v0.1.8 h1:zZDs9gcbt9ZPLV0ndSyQk6Kacx2g/X+SKYovpnz3SMM= github.com/google/s2a-go v0.1.8/go.mod h1:6iNWHTpQ+nfNRN5E00MSdfDwVesa8hhS32PhPO8deJA= @@ -586,17 +572,18 @@ github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5m github.com/googleapis/gax-go/v2 v2.13.0 h1:yitjD5f7jQHhyDsnhKEBU52NdvvdSeGzlAnDPT0hH1s= github.com/googleapis/gax-go/v2 v2.13.0/go.mod h1:Z/fvTZXF8/uw7Xu5GuslPw+bplx6SS338j1Is2S+B7A= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= -github.com/gopherjs/gopherjs v1.17.2/go.mod h1:pRRIvn/QzFLrKfvEz3qUuEhtE/zLCWfreZ6J5gM2i+k= github.com/gorilla/context v1.1.1 h1:AWwleXJkX/nhcU9bZSnZoi3h/qGYqQAGhq6zZe/aQW8= github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= github.com/gorilla/handlers v1.5.1 h1:9lRY6j8DEeeBT10CvO9hGW0gmky0BprnvDI5vfhUHH4= github.com/gorilla/handlers v1.5.1/go.mod h1:t8XrUpc4KVXb7HGyJ4/cEnwQiaxrX/hz1Zv/4g96P1Q= github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI= github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= +github.com/gorilla/rpc v1.2.0/go.mod h1:V4h9r+4sF5HnzqbwIez0fKSpANP0zlYd3qR7p36jkTQ= github.com/gorilla/securecookie v1.1.2 h1:YCIWL56dvtr73r6715mJs5ZvhtnY73hBvEF8kXD8ePA= github.com/gorilla/securecookie v1.1.2/go.mod h1:NfCASbcHqRSY+3a8tlWJwsQap2VX5pwzwo4h3eOamfo= github.com/gorilla/sessions v1.2.2 h1:lqzMYz6bOfvn2WriPUjNByzeXIlVzURcPmgMczkmTjY= github.com/gorilla/sessions v1.2.2/go.mod h1:ePLdVu+jbEgHH+KWw8I1z2wqd0BAdAQh/8LRvBeoNcQ= +github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY= github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY= github.com/grafana/pyroscope-go v1.1.2 h1:7vCfdORYQMCxIzI3NlYAs3FcBP760+gWuYWOyiVyYx8= @@ -607,12 +594,15 @@ github.com/graph-gophers/dataloader v5.0.0+incompatible h1:R+yjsbrNq1Mo3aPG+Z/EK github.com/graph-gophers/dataloader v5.0.0+incompatible/go.mod h1:jk4jk0c5ZISbKaMe8WsVopGB5/15GvGHMdMdPtwlRp4= github.com/graph-gophers/graphql-go v1.5.0 h1:fDqblo50TEpD0LY7RXk/LFVYEVqo3+tXMNMPSVXA1yc= github.com/graph-gophers/graphql-go v1.5.0/go.mod h1:YtmJZDLbF1YYNrlNAuiO5zAStUWc3XZT07iGsVqe1Os= +github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 h1:+9834+KizmvFV7pXQGSXQTsaWhq2GjuNUt0aUU0YBYw= github.com/grpc-ecosystem/go-grpc-middleware v1.3.0/go.mod h1:z0ButlSOZa5vEBq9m2m2hlwIgKw+rp3sdCBRoJY+30Y= github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.0.1 h1:qnpSQwGEnkcRpTqNOIR6bJbR0gAorgP9CSALpRcKoAA= github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.0.1/go.mod h1:lXGCsh6c22WGtjr+qGHj1otzZpV/1kwTMAqkwZsnWRU= github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.1.0 h1:pRhl55Yx1eC7BZ1N+BBWwnKaMyD8uC+34TLdndZMAKk= github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.1.0/go.mod h1:XKMd7iuf/RGPSMJ/U4HP0zS2Z9Fh8Ps9a+6X26m/tmI= +github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= +github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= github.com/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4M0+kPpLofRdBo= github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= github.com/grpc-ecosystem/grpc-gateway/v2 v2.22.0 h1:asbCHRVmodnJTuQ3qamDwqVOIjwqUPTYmYuemVOx+Ys= @@ -665,6 +655,7 @@ github.com/hashicorp/go-version v1.6.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09 github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/golang-lru v0.5.3/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= github.com/hashicorp/golang-lru v0.6.0 h1:uL2shRDx7RTrOrTCUZEGP/wJUFiUI8QT6E7z5o8jga4= github.com/hashicorp/golang-lru v0.6.0/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k= @@ -758,8 +749,10 @@ github.com/jackc/puddle v0.0.0-20190608224051-11cab39313c9/go.mod h1:m4B5Dj62Y0f github.com/jackc/puddle v1.1.3/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= github.com/jackpal/go-nat-pmp v1.0.2 h1:KzKSgb7qkJvOUTqYl9/Hg/me3pWgBmERKrTGD7BdWus= github.com/jackpal/go-nat-pmp v1.0.2/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc= +github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jhump/protoreflect v1.15.1 h1:HUMERORf3I3ZdX05WaQ6MIpd/NJ434hTp5YiKgfCL6c= github.com/jhump/protoreflect v1.15.1/go.mod h1:jD/2GMKKE6OqX8qTjhADU1e6DShO+gavG9e0Q693nKo= +github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg= github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= github.com/jmhodges/levigo v1.0.0 h1:q5EC36kV79HWeTBWsod3mG11EgStG3qArTKcvlksN1U= @@ -768,6 +761,7 @@ github.com/jmoiron/sqlx v1.4.0 h1:1PLqN7S1UYp5t4SrVVnt4nUVNemrDAtxlulVe+Qgm3o= github.com/jmoiron/sqlx v1.4.0/go.mod h1:ZrZ7UsYB/weZdl2Bxg6jCRO9c3YHl8r3ahlKmRT4JLY= github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0= github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4= +github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= github.com/jonboulle/clockwork v0.4.0 h1:p4Cf1aMWXnXAUh8lVfewRBx1zaTSYKrKMF2g3ST4RZ4= github.com/jonboulle/clockwork v0.4.0/go.mod h1:xgRqUGwRcjKCO1vbZUEtSLrqKoPSsUpK7fnezOII0kc= github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= @@ -775,7 +769,6 @@ github.com/jpillora/backoff v1.0.0 h1:uvFg412JmmHBHw7iwprIxkPMI+sGQ4kzOWsMeHnm2E github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= -github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= @@ -784,19 +777,17 @@ github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfV github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/klauspost/asmfmt v1.3.2 h1:4Ri7ox3EwapiOjCki+hw14RyKk201CN4rzyCJRFLpK4= -github.com/klauspost/asmfmt v1.3.2/go.mod h1:AG8TuvYojzulgDAMCnYn50l/5QV3Bs/tp6j0HLHbNSE= github.com/klauspost/compress v1.11.4/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= github.com/klauspost/compress v1.12.3/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg= -github.com/klauspost/compress v1.17.11 h1:In6xLpyWOi1+C7tXUUWv2ot1QvBjxevKAaI6IXrJmUc= -github.com/klauspost/compress v1.17.11/go.mod h1:pMDklpSncoRMuLFrf1W9Ss9KT+0rH90U12bZKk7uwG0= +github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= +github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA= +github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= -github.com/klauspost/cpuid/v2 v2.2.8 h1:+StwCXwm9PdpiEkPyzBXIy+M9KUb4ODm0Zarf1kS5BM= -github.com/klauspost/cpuid/v2 v2.2.8/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws= +github.com/klauspost/cpuid/v2 v2.2.5 h1:0E5MSMDEoAulmXNFquVs//DdoomxaoTY1kUhbc/qbZg= +github.com/klauspost/cpuid/v2 v2.2.5/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws= github.com/knz/go-libedit v1.10.1/go.mod h1:MZTVkCWyz0oBc7JOWP3wNAzd002ZbM/5hgShxwh4x8M= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= @@ -810,8 +801,8 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= -github.com/leanovate/gopter v0.2.11 h1:vRjThO1EKPb/1NsDXuDrzldR28RLkBflWYcU9CvzWu4= -github.com/leanovate/gopter v0.2.11/go.mod h1:aK3tzZP/C+p1m3SPRE4SYZFGP7jjkuSI4f7Xvpt0S9c= +github.com/leanovate/gopter v0.2.10-0.20210127095200-9abe2343507a h1:dHCfT5W7gghzPtfsW488uPmEOm85wewI+ypUwibyTdU= +github.com/leanovate/gopter v0.2.10-0.20210127095200-9abe2343507a/go.mod h1:U2L/78B+KVFIx2VmW6onHJQzXtFb+p5y3y2Sh+Jxxv8= github.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ictyFfxY= github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ= github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI= @@ -829,7 +820,7 @@ github.com/logrusorgru/aurora v2.0.3+incompatible h1:tOpm7WcpBTn4fjmVfgpQq0EfczG github.com/logrusorgru/aurora v2.0.3+incompatible/go.mod h1:7rIyQOR62GCctdiQpZ/zOJlFyk6y+94wXzv6RNZgaR4= github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I= github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= -github.com/magiconair/properties v1.8.5/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= +github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= @@ -838,10 +829,9 @@ github.com/manifoldco/promptui v0.9.0 h1:3V4HzJk1TtXW1MTZMP7mdlwbBpIinw3HztaIlYt github.com/manifoldco/promptui v0.9.0/go.mod h1:ka04sppxSGFAtxX0qhlYQjISsg9mR4GWtQEhdbn6Pgg= github.com/manyminds/api2go v0.0.0-20171030193247-e7b693844a6f h1:tVvGiZQFjOXP+9YyGqSA6jE55x1XVxmoPYudncxrZ8U= github.com/manyminds/api2go v0.0.0-20171030193247-e7b693844a6f/go.mod h1:Z60vy0EZVSu0bOugCHdcN5ZxFMKSpjRgsnh0XKPFqqk= -github.com/marcboeker/go-duckdb v1.8.3 h1:ZkYwiIZhbYsT6MmJsZ3UPTHrTZccDdM4ztoqSlEMXiQ= -github.com/marcboeker/go-duckdb v1.8.3/go.mod h1:C9bYRE1dPYb1hhfu/SSomm78B0FXmNgRvv6YBW/Hooc= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ= +github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= @@ -850,6 +840,8 @@ github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovk github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= +github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= +github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= @@ -869,10 +861,6 @@ github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3N github.com/mimoo/StrobeGo v0.0.0-20181016162300-f8f6d4d2b643/go.mod h1:43+3pMjjKimDBf5Kr4ZFNGbLql1zKkbImw+fZbw3geM= github.com/mimoo/StrobeGo v0.0.0-20210601165009-122bf33a46e0 h1:QRUSJEgZn2Snx0EmT/QLXibWjSUDjKWvXIT19NBVp94= github.com/mimoo/StrobeGo v0.0.0-20210601165009-122bf33a46e0/go.mod h1:43+3pMjjKimDBf5Kr4ZFNGbLql1zKkbImw+fZbw3geM= -github.com/minio/asm2plan9s v0.0.0-20200509001527-cdd76441f9d8 h1:AMFGa4R4MiIpspGNG7Z948v4n35fFGB3RR3G/ry4FWs= -github.com/minio/asm2plan9s v0.0.0-20200509001527-cdd76441f9d8/go.mod h1:mC1jAcsrzbxHt8iiaC+zU4b1ylILSosueou12R++wfY= -github.com/minio/c2goasm v0.0.0-20190812172519-36a3d3bbc4f3 h1:+n/aFZefKZp7spd8DFdX7uMikMLXX4oubIzJF4kv/wI= -github.com/minio/c2goasm v0.0.0-20190812172519-36a3d3bbc4f3/go.mod h1:RagcQ7I8IeTMnF8JTXieKnO4Z6JCsikNEzj0DwauVzE= github.com/minio/highwayhash v1.0.2 h1:Aak5U0nElisjDCfPSG79Tgzkn2gl66NxOMspRrKnA/g= github.com/minio/highwayhash v1.0.2/go.mod h1:BQskDq+xkJ12lmlUUi7U0M5Swg3EWR+dLTk+kldvVxY= github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= @@ -909,6 +897,7 @@ github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lN github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= +github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc= github.com/mostynb/zstdpool-freelist v0.0.0-20201229113212-927304c0c3b1 h1:mPMvm6X6tf4w8y7j9YIt6V9jfWhL6QlbEc7CCmeQlWk= github.com/mostynb/zstdpool-freelist v0.0.0-20201229113212-927304c0c3b1/go.mod h1:ye2e/VUEtE2BHE+G/QcKkcLQVAEJoYRFj5VUOQatCRE= github.com/mr-tron/base58 v1.2.0 h1:T/HDJBh4ZCPbU39/+c3rRvE0uKBQlU27+QI8LJ4t64o= @@ -920,9 +909,8 @@ github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8m github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/ncruces/go-strftime v0.1.9 h1:bY0MQC28UADQmHmaF5dgpLmImcShSi2kHU9XLdhx/f4= github.com/ncruces/go-strftime v0.1.9/go.mod h1:Fwc5htZGVVkseilnfgOVb9mKy6w1naJmn9CehxcKcls= -github.com/neelance/astrewrite v0.0.0-20160511093645-99348263ae86/go.mod h1:kHJEU3ofeGjhHklVoIGuVj85JJwZ6kWPaJwCIxgnFmo= -github.com/neelance/sourcemap v0.0.0-20200213170602-2833bce08e4c/go.mod h1:Qr6/a/Q4r9LP1IltGz7tA7iOK1WonHEYhu1HRBA7ZiM= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= +github.com/nkovacs/streamquote v0.0.0-20170412213628-49af9bddb229/go.mod h1:0aYXnNPJ8l7uZxf45rWW1a/uME32OF0rhiYGNQ2oF2E= github.com/nsf/jsondiff v0.0.0-20230430225905-43f6cf3098c1 h1:dOYG7LS/WK00RWZc8XGgcUTlTxpp3mKhdR2Q9z9HbXM= github.com/nsf/jsondiff v0.0.0-20230430225905-43f6cf3098c1/go.mod h1:mpRZBD8SJ55OIICQ3iWH0Yz3cjzA61JdqMLoWXeB2+8= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= @@ -930,6 +918,7 @@ github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= github.com/oklog/run v1.1.0 h1:GEenZ1cK0+q0+wsJew9qUg/DyD8k3JzYsZAi5gYi2mA= github.com/oklog/run v1.1.0/go.mod h1:sVPdnTZT1zYwAJeCMu2Th4T21pA3FPOQRfWjQlk7DVU= +github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= @@ -938,14 +927,14 @@ github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vv github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU= github.com/onsi/ginkgo/v2 v2.1.3/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c= -github.com/onsi/ginkgo/v2 v2.20.1 h1:YlVIbqct+ZmnEph770q9Q7NVAz4wwIiVNahee6JyUzo= -github.com/onsi/ginkgo/v2 v2.20.1/go.mod h1:lG9ey2Z29hR41WMVthyJBGUBcBhGOtoPF2VFMvBXFCI= +github.com/onsi/ginkgo/v2 v2.17.2 h1:7eMhcy3GimbsA3hEnVKdw/PQM9XN9krpKVXsZdph0/g= +github.com/onsi/ginkgo/v2 v2.17.2/go.mod h1:nP2DPOQoNsQmsVyv5rDA8JkXQoCs6goXIvr/PRJ1eCc= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= github.com/onsi/gomega v1.19.0/go.mod h1:LY+I3pBVzYsTBU1AnDwOSxaYi9WoWiqgwooUqq9yPro= -github.com/onsi/gomega v1.34.2 h1:pNCwDkzrsv7MS9kpaQvVb1aVLahQXyJ/Tv5oAZMI3i8= -github.com/onsi/gomega v1.34.2/go.mod h1:v1xfxRgk0KIsG+QOdm7p8UosrOzPYRo60fd3B/1Dukc= +github.com/onsi/gomega v1.33.1 h1:dsYjIxxSR755MDmKVsaFQTE22ChNBcuuTWgkUDSubOk= +github.com/onsi/gomega v1.33.1/go.mod h1:U4R44UsT+9eLIaYRB2a5qajjtQYn0hauxvRm16AVYg0= github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= github.com/opencontainers/image-spec v1.1.0 h1:8SG7/vwALn54lVB/0yZ/MMwhFrPYtpEHQb2IpWsCzug= @@ -963,17 +952,14 @@ github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144T github.com/patrickmn/go-cache v2.1.0+incompatible h1:HRMgzkcYKYpi3C8ajMPV8OFXaaRUnok+kx1WdO15EQc= github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ= github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= -github.com/pelletier/go-toml v1.9.3/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8= github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= github.com/pelletier/go-toml/v2 v2.0.1/go.mod h1:r9LEWfGN8R5k0VXJ+0BkIe7MYkRdwZOjgMj2KwnJFUo= -github.com/pelletier/go-toml/v2 v2.2.3 h1:YmeHyLY8mFWbdkNWwpr+qIL2bEqT0o95WSdkNHvL12M= -github.com/pelletier/go-toml/v2 v2.2.3/go.mod h1:MfCQTFTvCcUyyvvwm1+G6H/jORL20Xlb6rzQu9GuUkc= +github.com/pelletier/go-toml/v2 v2.2.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6Wq+LM= +github.com/pelletier/go-toml/v2 v2.2.2/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs= github.com/petermattis/goid v0.0.0-20180202154549-b0b1615b78e5/go.mod h1:jvVRKCrJTQWu0XVbaOlby/2lO20uSCHEMzzplHXte1o= github.com/petermattis/goid v0.0.0-20230317030725-371a4b8eda08 h1:hDSdbBuw3Lefr6R18ax0tZ2BJeNB3NehB3trOwYBsdU= github.com/petermattis/goid v0.0.0-20230317030725-371a4b8eda08/go.mod h1:pxMtw7cyUw6B2bRH0ZBANSPg+AoSud1I1iyJHI69jH4= -github.com/pierrec/lz4/v4 v4.1.21 h1:yOVMLb6qSIDP67pl/5F7RepeKYu/VmTyEXvuMI5d9mQ= -github.com/pierrec/lz4/v4 v4.1.21/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= github.com/pingcap/errors v0.11.4 h1:lFuQV/oaUMGcD2tqt+01ROSmJs75VG1ToEOkZIZ4nE4= github.com/pingcap/errors v0.11.4/go.mod h1:Oi8TUi2kEtXXLMJk9l1cGmz20kV3TaQ0usTwv5KuLY8= github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= @@ -981,7 +967,6 @@ github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI= github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10 h1:GFCKgmp0tecUJ0sJuv4pzYCqS9+RGSn52M3FUwPs+uo= github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10/go.mod h1:t/avpk3KcrXxUnYOhZhMXJlSEyie6gQbtLq5NM3loB8= github.com/pmezard/go-difflib v0.0.0-20151028094244-d8ed2627bdf0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= @@ -994,27 +979,32 @@ github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:Om github.com/pressly/goose/v3 v3.21.1 h1:5SSAKKWej8LVVzNLuT6KIvP1eFDuPvxa+B6H0w78buQ= github.com/pressly/goose/v3 v3.21.1/go.mod h1:sqthmzV8PitchEkjecFJII//l43dLOCzfWh8pHEe+vE= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= +github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= -github.com/prometheus/client_golang v1.20.5 h1:cxppBPuYhUnsO6yo/aoRol4L7q7UFfdm+bR9r+8l63Y= -github.com/prometheus/client_golang v1.20.5/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= +github.com/prometheus/client_golang v1.20.0 h1:jBzTZ7B099Rg24tny+qngoynol8LtVYlA2bqx3vEloI= +github.com/prometheus/client_golang v1.20.0/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E= github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= +github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= +github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4= -github.com/prometheus/common v0.60.0 h1:+V9PAREWNvJMAuJ1x1BaWl9dewMW4YrHZQbx0sJNllA= -github.com/prometheus/common v0.60.0/go.mod h1:h0LYf1R1deLSKtD4Vdg8gy4RuOvENW2J/h19V5NADQw= +github.com/prometheus/common v0.59.1 h1:LXb1quJHWm1P6wq/U824uxYi4Sg0oGvNeUm1z5dJoX0= +github.com/prometheus/common v0.59.1/go.mod h1:GpWM7dewqmVYcd7SmRaiWVe9SSqjf0UrwnYnpEZNuT0= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= +github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc= github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk= github.com/prometheus/prometheus v0.54.1 h1:vKuwQNjnYN2/mDoWfHXDhAsz/68q/dQDb+YbcEqU7MQ= github.com/prometheus/prometheus v0.54.1/go.mod h1:xlLByHhk2g3ycakQGrMaU8K7OySZx98BzeCR99991NY= +github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= github.com/rakyll/statik v0.1.7 h1:OF3QCZUuyPxuGEP7B4ypUa7sB/iHtqOTDYZXGM8KOdQ= github.com/rakyll/statik v0.1.7/go.mod h1:AlZONWzMtEnMs7W4e/1LURLiI49pIMmp6V9Unghqrcc= github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 h1:N/ElC8H3+5XpJzTSTfLsJV/mx9Q9g7kxmchpfZyxgzM= @@ -1028,13 +1018,14 @@ github.com/rivo/uniseg v0.4.4 h1:8TfxU8dW6PdqD27gjM8MVNuicgxIjxpm4K7x4jp8sis= github.com/rivo/uniseg v0.4.4/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs= github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro= +github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE= github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= -github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII= -github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o= +github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= +github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= github.com/rs/cors v1.9.0 h1:l9HGsTsHJcvW14Nk7J9KFz8bzeAWXn3CG6bgt7LsrAE= github.com/rs/cors v1.9.0/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU= github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ= @@ -1075,38 +1066,32 @@ github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFR github.com/shopspring/decimal v1.3.1/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= github.com/shopspring/decimal v1.4.0 h1:bxl37RwXBklmTi0C79JfXCEBD1cqqHt0bbgBAGFp81k= github.com/shopspring/decimal v1.4.0/go.mod h1:gawqmDU56v4yIKSwfBSFip1HdCCXN8/+DMd9qYNcwME= -github.com/shurcooL/go v0.0.0-20200502201357-93f07166e636/go.mod h1:TDJrrUr11Vxrven61rcy3hJMUqaf/CLWYhHNPmT14Lk= -github.com/shurcooL/httpfs v0.0.0-20190707220628-8d4bc4ba7749/go.mod h1:ZY1cvUeJuFPAdZ/B6v7RHavJWZn2YPVFQ1OSXhCGOkg= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= -github.com/shurcooL/vfsgen v0.0.0-20200824052919-0d455de96546/go.mod h1:TrYk7fJVaAttu97ZZKrO9UbRa8izdowaMIZcxYMbVaw= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= -github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= -github.com/smartcontractkit/chain-selectors v1.0.34 h1:MJ17OGu8+jjl426pcKrJkCf3fePb3eCreuAnUA3RBj4= -github.com/smartcontractkit/chain-selectors v1.0.34/go.mod h1:xsKM0aN3YGcQKTPRPDDtPx2l4mlTN1Djmg0VVXV40b8= +github.com/smartcontractkit/chain-selectors v1.0.29 h1:aZ9+OoUSMn4nqnissHtDvDoKR7JONfDqTHX3MHYIUIE= +github.com/smartcontractkit/chain-selectors v1.0.29/go.mod h1:xsKM0aN3YGcQKTPRPDDtPx2l4mlTN1Djmg0VVXV40b8= github.com/smartcontractkit/chainlink-automation v0.8.1 h1:sTc9LKpBvcKPc1JDYAmgBc2xpDKBco/Q4h4ydl6+UUU= github.com/smartcontractkit/chainlink-automation v0.8.1/go.mod h1:Iij36PvWZ6blrdC5A/nrQUBuf3MH3JvsBB9sSyc9W08= -github.com/smartcontractkit/chainlink-ccip v0.0.0-20241218114855-f74219171000 h1:6Zzr/R1j6P7bbvcUlt5WUIbItvrrGdGzIsiAzQezcwo= -github.com/smartcontractkit/chainlink-ccip v0.0.0-20241218114855-f74219171000/go.mod h1:ncjd6mPZSRlelEqH/2KeLE1pU3UlqzBSn8RYkEoECzY= -github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20241223194433-f25773de7c0e h1:aZ9IMSlI3qxelcNqhkOIwK7Z8I5HpCmWvAeOdFzCKwE= -github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20241223194433-f25773de7c0e/go.mod h1:Bmwq4lNb5tE47sydN0TKetcLEGbgl+VxHEWp4S0LI60= -github.com/smartcontractkit/chainlink-common v0.4.1-0.20241217120918-bbe318cd0760 h1:lB5A3TP0zOVuu1n0kEm6d8/o/4Knh6HLvsU/GChk+sI= -github.com/smartcontractkit/chainlink-common v0.4.1-0.20241217120918-bbe318cd0760/go.mod h1:yti7e1+G9hhkYhj+L5sVUULn9Bn3bBL5/AxaNqdJ5YQ= -github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241202195413-82468150ac1e h1:PRoeby6ZlTuTkv2f+7tVU4+zboTfRzI+beECynF4JQ0= -github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241202195413-82468150ac1e/go.mod h1:mUh5/woemsVaHgTorA080hrYmO3syBCmPdnWc/5dOqk= -github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20241216163550-fa030d178ba3 h1:aeiBdBHGY8QNftps+VqrIk6OnfeeOD5z4jrAabW4ZSc= -github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20241216163550-fa030d178ba3/go.mod h1:AS6zY2BkcRwfiGzNabGbHhfrLSrXrcI/GmjnT4jQ5/s= +github.com/smartcontractkit/chainlink-ccip v0.0.0-20241118091009-43c2b4804cec h1:5vS1k8Qn09p8SQ3JzvS8iy4Pve7s3aVq+UPIdl74smY= +github.com/smartcontractkit/chainlink-ccip v0.0.0-20241118091009-43c2b4804cec/go.mod h1:4adKaHNaxFsRvV/lYfqtbsWyyvIPUMLR0FdOJN/ljis= +github.com/smartcontractkit/chainlink-common v0.3.1-0.20241114134822-aadff98ef068 h1:2llRW4Tn9W/EZp2XvXclQ9IjeTBwwxVPrrqaerX+vCE= +github.com/smartcontractkit/chainlink-common v0.3.1-0.20241114134822-aadff98ef068/go.mod h1:ny87uTW6hLjCTLiBqBRNFEhETSXhHWevYlPclT5lSco= +github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241017133723-5277829bd53f h1:BwrIaQIx5Iy6eT+DfLhFfK2XqjxRm74mVdlX8gbu4dw= +github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241017133723-5277829bd53f/go.mod h1:wHtwSR3F1CQSJJZDQKuqaqFYnvkT+kMyget7dl8Clvo= +github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20241018134907-a00ba3729b5e h1:JiETqdNM0bktAUGMc62COwXIaw3rR3M77Me6bBLG0Fg= +github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20241018134907-a00ba3729b5e/go.mod h1:iK3BNHKCLgSgkOyiu3iE7sfZ20Qnuk7xwjV/yO/6gnQ= github.com/smartcontractkit/chainlink-feeds v0.1.1 h1:JzvUOM/OgGQA1sOqTXXl52R6AnNt+Wg64sVG+XSA49c= github.com/smartcontractkit/chainlink-feeds v0.1.1/go.mod h1:55EZ94HlKCfAsUiKUTNI7QlE/3d3IwTlsU3YNa/nBb4= -github.com/smartcontractkit/chainlink-protos/orchestrator v0.4.0 h1:ZBat8EBvE2LpSQR9U1gEbRV6PfAkiFdINmQ8nVnXIAQ= -github.com/smartcontractkit/chainlink-protos/orchestrator v0.4.0/go.mod h1:m/A3lqD7ms/RsQ9BT5P2uceYY0QX5mIt4KQxT2G6qEo= -github.com/smartcontractkit/chainlink-solana v1.1.1-0.20241219173444-150f7443fdd3 h1:AIIiwrZ5T4nEjFT33aLZKoXwD63JSMu72wWe/rUdfm0= -github.com/smartcontractkit/chainlink-solana v1.1.1-0.20241219173444-150f7443fdd3/go.mod h1:ARILnIgKelP0YkVzxXO111S9j0b4uKyt7iLpYjOkCtU= -github.com/smartcontractkit/chainlink-starknet/relayer v0.1.1-0.20241202202529-2033490e77b8 h1:tNS7U9lrxkFvEuyxQv11HHOiV9LPDGC9wYEy+yM/Jv4= -github.com/smartcontractkit/chainlink-starknet/relayer v0.1.1-0.20241202202529-2033490e77b8/go.mod h1:EBrEgcdIbwepqguClkv8Ohy7CbyWSJaE4EC9aBJlQK0= +github.com/smartcontractkit/chainlink-protos/orchestrator v0.3.0 h1:PBUaFfPLm+Efq7H9kdfGBivH+QhJ6vB5EZTR/sCZsxI= +github.com/smartcontractkit/chainlink-protos/orchestrator v0.3.0/go.mod h1:m/A3lqD7ms/RsQ9BT5P2uceYY0QX5mIt4KQxT2G6qEo= +github.com/smartcontractkit/chainlink-solana v1.1.1-0.20241115191142-8b8369c1f44e h1:XxTWJ9VIXK+XuAjP5131PqqBn0NEt5lBvnRAWRdqy8A= +github.com/smartcontractkit/chainlink-solana v1.1.1-0.20241115191142-8b8369c1f44e/go.mod h1:mGmRvlk54ufCufV4EBWizOGtXoXfePoFAuYEVC8EwdY= +github.com/smartcontractkit/chainlink-starknet/relayer v0.1.1-0.20241017135645-176a23722fd8 h1:B4DFdk6MGcQnoCjjMBCx7Z+GWQpxRWJ4O8W/dVJyWGA= +github.com/smartcontractkit/chainlink-starknet/relayer v0.1.1-0.20241017135645-176a23722fd8/go.mod h1:WkBqgBo+g34Gm5vWkDDl8Fh3Mzd7bF5hXp7rryg0t5o= github.com/smartcontractkit/grpc-proxy v0.0.0-20240830132753-a7e17fec5ab7 h1:12ijqMM9tvYVEm+nR826WsrNi6zCKpwBhuApq127wHs= github.com/smartcontractkit/grpc-proxy v0.0.0-20240830132753-a7e17fec5ab7/go.mod h1:FX7/bVdoep147QQhsOPkYsPEXhGZjeYx6lBSaSXtZOA= github.com/smartcontractkit/libocr v0.0.0-20241007185508-adbe57025f12 h1:NzZGjaqez21I3DU7objl3xExTH4fxYvzTqar8DC6360= @@ -1115,19 +1100,17 @@ github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20241009055228- github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20241009055228-33d0c0bf38de/go.mod h1:Sl2MF/Fp3fgJIVzhdGhmZZX2BlnM0oUUyBP4s4xYb6o= github.com/smartcontractkit/tdh2/go/tdh2 v0.0.0-20241009055228-33d0c0bf38de h1:66VQxXx3lvTaAZrMBkIcdH9VEjujUEvmBQdnyOJnkOc= github.com/smartcontractkit/tdh2/go/tdh2 v0.0.0-20241009055228-33d0c0bf38de/go.mod h1:NSc7hgOQbXG3DAwkOdWnZzLTZENXSwDJ7Va1nBp0YU0= -github.com/smartcontractkit/wsrpc v0.8.3 h1:9tDf7Ut61g36RJIyxV9iI73SqoOMasKPfURV9oMLrPg= -github.com/smartcontractkit/wsrpc v0.8.3/go.mod h1:2u/wfnhl5R4RlSXseN4n6HHIWk8w1Am3AT6gWftQbNg= -github.com/smarty/assertions v1.15.0/go.mod h1:yABtdzeQs6l1brC900WlRNwj6ZR55d7B+E8C6HtKdec= +github.com/smartcontractkit/wsrpc v0.8.2 h1:XB/xcn/MMseHW+8JE8+a/rceA86ck7Ur6cEa9LiUC8M= +github.com/smartcontractkit/wsrpc v0.8.2/go.mod h1:2u/wfnhl5R4RlSXseN4n6HHIWk8w1Am3AT6gWftQbNg= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= -github.com/smartystreets/goconvey v1.8.1/go.mod h1:+/u4qLyY6x1jReYOp7GOM2FSt8aP9CzCZL03bI28W60= +github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo= github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI= github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= -github.com/spf13/afero v1.6.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I= github.com/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8= github.com/spf13/afero v1.11.0/go.mod h1:GH9Y3pIexgf1MTIWtNGyogA5MwRIDXGUr+hbWNoBjkY= github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= @@ -1135,22 +1118,22 @@ github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkU github.com/spf13/cast v1.6.0 h1:GEiTHELF+vaR5dhz3VqZfFSzZjYbgeKDpBxQVS4GYJ0= github.com/spf13/cast v1.6.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo= github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU= -github.com/spf13/cobra v1.2.1/go.mod h1:ExllRjgxM/piMAM+3tAZvg8fsklGAf3tPfi+i8t68Nk= +github.com/spf13/cobra v1.1.1/go.mod h1:WnodtKOvamDL/PwE2M4iKs8aMDBZ5Q5klgD3qfVJQMI= github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM= github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y= github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= -github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= -github.com/spf13/viper v1.8.1/go.mod h1:o0Pch8wJ9BVSWGQMbra6iw0oQ5oktSIBaujf1rJH9Ns= +github.com/spf13/viper v1.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg= +github.com/spf13/viper v1.7.1/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg= github.com/spf13/viper v1.19.0 h1:RWq5SEjt8o25SROyN3z2OrDB9l7RPd3lwTWU8EcEdcI= github.com/spf13/viper v1.19.0/go.mod h1:GQUN9bilAbhU/jgc1bKs99f/suXKeUMct8Adx5+Ntkg= github.com/status-im/keycard-go v0.2.0 h1:QDLFswOQu1r5jsycloeQh3bVU8n/NatHHaZobtDnDzA= github.com/status-im/keycard-go v0.2.0/go.mod h1:wlp8ZLbsmrF6g6WjugPAx+IzoLrkdf9+mHxBEeo3Hbg= -github.com/streamingfast/logging v0.0.0-20230608130331-f22c91403091 h1:RN5mrigyirb8anBEtdjtHFIufXdacyTi6i4KBfeNXeo= -github.com/streamingfast/logging v0.0.0-20230608130331-f22c91403091/go.mod h1:VlduQ80JcGJSargkRU4Sg9Xo63wZD/l8A5NC/Uo1/uU= +github.com/streamingfast/logging v0.0.0-20220405224725-2755dab2ce75 h1:ZqpS7rAhhKD7S7DnrpEdrnW1/gZcv82ytpMviovkli4= +github.com/streamingfast/logging v0.0.0-20220405224725-2755dab2ce75/go.mod h1:VlduQ80JcGJSargkRU4Sg9Xo63wZD/l8A5NC/Uo1/uU= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= @@ -1170,9 +1153,8 @@ github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1F github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= -github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= -github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8= github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= @@ -1182,16 +1164,21 @@ github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d h1:vfofYNRScrDd github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d/go.mod h1:RRCYJbIwD5jmqPI9XoAFR0OcDxqUctll6zUj/+B4S48= github.com/tendermint/go-amino v0.16.0 h1:GyhmgQKvqF82e2oZeuMSp9JTN0N09emoSZlb2lyGa2E= github.com/tendermint/go-amino v0.16.0/go.mod h1:TQU0M1i/ImAo+tYpZi73AU3V/dKeCoMC9Sphe2ZwGME= +github.com/teris-io/shortid v0.0.0-20171029131806-771a37caa5cf/go.mod h1:M8agBzgqHIhgj7wEn9/0hJUZcrvt9VY+Ln+S1I5Mha0= +github.com/teris-io/shortid v0.0.0-20201117134242-e59966efd125 h1:3SNcvBmEPE1YlB1JpVZouslJpI3GBNoiqW7+wb0Rz7w= +github.com/teris-io/shortid v0.0.0-20201117134242-e59966efd125/go.mod h1:M8agBzgqHIhgj7wEn9/0hJUZcrvt9VY+Ln+S1I5Mha0= github.com/test-go/testify v1.1.4 h1:Tf9lntrKUMHiXQ07qBScBTSA0dhYQlu83hswqelv1iE= github.com/test-go/testify v1.1.4/go.mod h1:rH7cfJo/47vWGdi4GPj16x3/t1xGOj2YxzmNQzk2ghU= github.com/theodesp/go-heaps v0.0.0-20190520121037-88e35354fe0a h1:YuO+afVc3eqrjiCUizNCxI53bl/BnPiVwXqLzqYTqgU= github.com/theodesp/go-heaps v0.0.0-20190520121037-88e35354fe0a/go.mod h1:/sfW47zCZp9FrtGcWyo1VjbgDaodxX9ovZvgLb/MxaA= github.com/tidwall/btree v1.6.0 h1:LDZfKfQIBHGHWSwckhXI0RPSXzlo+KYdjK7FWSqOzzg= github.com/tidwall/btree v1.6.0/go.mod h1:twD9XRA5jj9VUQGELzDO4HPQTNJsoWWfYEL+EUQ2cKY= +github.com/tidwall/gjson v1.9.3/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= github.com/tidwall/gjson v1.17.0 h1:/Jocvlh98kcTfpN2+JzGQWQcqrPQwDrVEMApx/M5ZwM= github.com/tidwall/gjson v1.17.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA= github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM= +github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= github.com/tidwall/pretty v1.2.1 h1:qjsOFOWWQl+N3RsoF5/ssm1pHmJJwhjlSbZ51I6wMl4= github.com/tidwall/pretty v1.2.1/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= @@ -1199,6 +1186,7 @@ github.com/tklauser/go-sysconf v0.3.12 h1:0QaGUFOdQaIVdPgfITYzaTegZvdCjmYO52cSFA github.com/tklauser/go-sysconf v0.3.12/go.mod h1:Ho14jnntGE1fpdOqQEEaiKRpvIavV0hSfmBq8nJbHYI= github.com/tklauser/numcpus v0.6.1 h1:ng9scYS7az0Bk4OZLvrNXNSAO2Pxr1XXRAPyjhIx+Fk= github.com/tklauser/numcpus v0.6.1/go.mod h1:1XfjsgE2zo8GVw7POkMbHENHzVg3GzmoZ9fESEdAacY= +github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM= github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI= github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08= @@ -1224,29 +1212,29 @@ github.com/urfave/cli v1.22.14 h1:ebbhrRiGK2i4naQJr+1Xj92HXZCrK7MsyTS/ob3HnAk= github.com/urfave/cli v1.22.14/go.mod h1:X0eDS6pD6Exaclxm99NJ3FiCDRED7vIHpx2mDOHLvkA= github.com/urfave/cli/v2 v2.25.7 h1:VAzn5oq403l5pHjc4OhD54+XGO9cdKVL/7lDjF+iKUs= github.com/urfave/cli/v2 v2.25.7/go.mod h1:8qnjx1vcq5s2/wpsqoZFndg2CE5tNFyrTvS6SinrnYQ= +github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= github.com/valyala/fastjson v1.4.1 h1:hrltpHpIpkaxll8QltMU8c3QZ5+qIiCL8yKqPFJI/yE= github.com/valyala/fastjson v1.4.1/go.mod h1:nV6MsjxL2IMJQUoHDIrjEI7oLyeqK6aBD7EFWPsvP8o= +github.com/valyala/fasttemplate v1.0.1/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPUpymEIMZ47gx8= github.com/wk8/go-ordered-map/v2 v2.1.8 h1:5h/BUHu93oj4gIdvHHHGsScSTMijfx5PeYkE/fJgbpc= github.com/wk8/go-ordered-map/v2 v2.1.8/go.mod h1:5nJHM5DyteebpVlHnWMV0rPz6Zp7+xBAnxjb1X5vnTw= github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM= github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg= +github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI= +github.com/xdg-go/scram v1.1.1/go.mod h1:RaEWvsqvNKKvBPvcKeFjrG2cJqOkHTiyTpzz23ni57g= +github.com/xdg-go/stringprep v1.0.3/go.mod h1:W3f5j4i+9rC0kuIEJL0ky1VpHXQU3ocBgklLGvcBnW8= +github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 h1:bAn7/zixMGCfxrRTfdpNzjtPYqr8smhKouy9mxVdGPU= github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673/go.mod h1:N3UwUGtsrSj3ccvlPHLoLsHnpR27oXr4ZE984MbSER8= -github.com/xyproto/randomstring v1.0.5 h1:YtlWPoRdgMu3NZtP45drfy1GKoojuR7hmRcnhZqKjWU= -github.com/xyproto/randomstring v1.0.5/go.mod h1:rgmS5DeNXLivK7YprL0pY+lTuhNQW3iGxZ18UQApw/E= +github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d/go.mod h1:rHwXgn7JulP+udvsHwJoVG1YGAP6VLg4y9I5dyZdqmA= github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo0= github.com/yusufpapurcu/wmi v1.2.4/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= -github.com/zeebo/assert v1.3.0 h1:g7C04CbJuIDKNPFHmsk4hwZDO5O+kntRxzaUoNXj+IQ= -github.com/zeebo/assert v1.3.0/go.mod h1:Pq9JiuJQpG8JLJdtkwrJESF0Foym2/D9XMU5ciN/wJ0= -github.com/zeebo/xxh3 v1.0.2 h1:xZmwmqxHZA8AI603jOQ0tMqmBr9lPeFwGg6d+xy9DC0= -github.com/zeebo/xxh3 v1.0.2/go.mod h1:5NWz9Sef7zIDm2JHfFlcQvNekmcEl9ekUZQQKCYaDcA= github.com/zenazn/goji v0.9.0/go.mod h1:7S9M489iMyHBNxwZnk9/EHS098H4/F6TATF2mIxtB1Q= github.com/zondax/hid v0.9.2 h1:WCJFnEDMiqGF64nlZz28E9qLVZ0KSJ7xpc5DLEyma2U= github.com/zondax/hid v0.9.2/go.mod h1:l5wttcP0jwtdLjqjMMWFVEE7d1zO0jvSPA9OPZxWpEM= @@ -1262,20 +1250,19 @@ go.dedis.ch/protobuf v1.0.5/go.mod h1:eIV4wicvi6JK0q/QnfIEGeSFNG0ZeB24kzut5+HaRL go.dedis.ch/protobuf v1.0.7/go.mod h1:pv5ysfkDX/EawiPqcW3ikOxsL5t+BqnV6xHSmE79KI4= go.dedis.ch/protobuf v1.0.11 h1:FTYVIEzY/bfl37lu3pR4lIj+F9Vp1jE8oh91VmxKgLo= go.dedis.ch/protobuf v1.0.11/go.mod h1:97QR256dnkimeNdfmURz0wAMNVbd1VmLXhG1CrTYrJ4= +go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.etcd.io/bbolt v1.3.9 h1:8x7aARPEXiXbHmtUwAIv7eV2fQFHrLLavdiJ3uzJXoI= go.etcd.io/bbolt v1.3.9/go.mod h1:zaO32+Ti0PK1ivdPtgMESzuzL2VPoIG1PCQNvOdo/dE= -go.etcd.io/etcd/api/v3 v3.5.0/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs= -go.etcd.io/etcd/client/pkg/v3 v3.5.0/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g= -go.etcd.io/etcd/client/v2 v2.305.0/go.mod h1:h9puh54ZTgAKtEbut2oe9P4L/oqKCVB6xsXlzd7alYQ= +go.mongodb.org/mongo-driver v1.11.0/go.mod h1:s7p5vEtfbeR1gYi6pnj3c3/urpbLv2T5Sfd6Rp2HBB8= go.mongodb.org/mongo-driver v1.15.0 h1:rJCKC8eEliewXjZGf0ddURtl7tTVy1TK3bfl0gkUSLc= go.mongodb.org/mongo-driver v1.15.0/go.mod h1:Vzb0Mk/pa7e6cWw85R4F/endUC3u0U9jGcNU603k65c= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= +go.opencensus.io v0.22.1/go.mod h1:Ap50jQcDJrx6rB6VgeeFPtuPIf3wMRvRfrfYDO6+BmA= go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= -go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= go.opentelemetry.io/contrib/detectors/gcp v1.31.0 h1:G1JQOreVrfhRkner+l4mrGxmfqYCAuy76asTDAo0xsA= @@ -1342,13 +1329,15 @@ go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKY go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= -go.uber.org/ratelimit v0.3.1 h1:K4qVE+byfv/B3tC+4nYWP7v/6SimcO7HzHekoMNBma0= -go.uber.org/ratelimit v0.3.1/go.mod h1:6euWsTB6U/Nb3X++xEUXA8ciPJvr19Q/0h1+oDcJhRk= +go.uber.org/ratelimit v0.2.0/go.mod h1:YYBV4e4naJvhpitQrWJu1vCpgB7CboMe0qhltKt6mUg= +go.uber.org/ratelimit v0.3.0 h1:IdZd9wqvFXnvLvSEBo0KPcGfkoBGNkpTHlrE3Rcjkjw= +go.uber.org/ratelimit v0.3.0/go.mod h1:So5LG7CV1zWpY1sHe+DXTJqQvOx+FFPFaAs2SnoyBaI= go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA= go.uber.org/zap v1.9.1/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= -go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo= +go.uber.org/zap v1.14.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= +go.uber.org/zap v1.16.0/go.mod h1:MA8QOfq0BHJwdXa996Y4dYkAqRKB8/1K1QMMZVaNZjQ= go.uber.org/zap v1.21.0/go.mod h1:wjWOCqI0f2ZZrJF/UufIOkiC8ii6tm1iqIsLo76RfJw= go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= @@ -1374,10 +1363,11 @@ golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5y golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20220214200702-86341886e292/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.3.0/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4= golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc= -golang.org/x/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U= -golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk= +golang.org/x/crypto v0.28.0 h1:GBDwsMXVQi34v5CCYUm2jkJvu4cbtru2U4TN2PSyQnw= +golang.org/x/crypto v0.28.0/go.mod h1:rmgy+3RHxRZMyY0jjAJShp2zgEdOqj2AO7U0pYmeQ7U= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -1388,8 +1378,8 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0 golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= -golang.org/x/exp v0.0.0-20241210194714-1829a127f884 h1:Y/Mj/94zIQQGHVSv1tTtQBDaQaJe62U9bkDZKKyhPCU= -golang.org/x/exp v0.0.0-20241210194714-1829a127f884/go.mod h1:qj5a5QZpwLU2NLQudwIN5koi3beDhSAlJwa67PuM98c= +golang.org/x/exp v0.0.0-20241009180824-f66d83c29e7c h1:7dEasQXItcW1xKJ2+gg5VOiBnqWrJc+rq0DPKyvvdbY= +golang.org/x/exp v0.0.0-20241009180824-f66d83c29e7c/go.mod h1:NQtJDoLvd6faHhE7m4T/1IY708gDefGGjR/iUW8yQQ8= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= @@ -1403,7 +1393,6 @@ golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRu golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= @@ -1412,20 +1401,18 @@ golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzB golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/mod v0.9.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/mod v0.22.0 h1:D4nJWe9zXqHOmWqj4VMOJhvzj7bEZg4wEYa759z1pH4= -golang.org/x/mod v0.22.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY= +golang.org/x/mod v0.21.0 h1:vvrHzRwRfVKSiLrG+d4FMl/Qi4ukBCE6kZlTUkDYRT0= +golang.org/x/mod v0.21.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= @@ -1435,29 +1422,19 @@ golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc= golang.org/x/net v0.0.0-20210331212208-0fccb6fa2b5c/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= @@ -1469,22 +1446,14 @@ golang.org/x/net v0.0.0-20220607020251-c690dde0001d/go.mod h1:XRhObCWvk6IyKnWLug golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= -golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= -golang.org/x/net v0.32.0 h1:ZqPmj8Kzc+Y6e0+skZsuACbx+wzMgo5MQsJh9Qd6aYI= -golang.org/x/net v0.32.0/go.mod h1:CwU0IoeOlnQQWJ6ioyFrfRuomB8GKF6KbYXZVyeXNfs= +golang.org/x/net v0.30.0 h1:AcW1SDZMkb8IpzCdQUaIq2sP4sZ4zw+55h6ynffypl4= +golang.org/x/net v0.30.0/go.mod h1:2wGyMJ5iFasEhkwi13ChkO/t1ECNC4X4eBKkVFyYFlU= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210220000619-9bb904979d93/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210313182246-cd4f82c27b84/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210402161424-2e8d93401602/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.23.0 h1:PbgcYx2W7i4LvjJWEbf0ngHV6qJYr86PkAV3bXdLEbs= golang.org/x/oauth2 v0.23.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -1494,19 +1463,18 @@ golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ= -golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ= +golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190124100055-b90733256f2e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -1522,6 +1490,7 @@ golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190804053845-51ab0e2deafa/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -1537,29 +1506,17 @@ golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210305230114-8fe3ee5dd75b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210331175145-43e1dd70ce54/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -1583,18 +1540,18 @@ golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA= -golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo= +golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.0.0-20201210144234-2321bbc49cbf/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= -golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU= -golang.org/x/term v0.27.0 h1:WP60Sv1nlK1T6SupCHbXzSaN0b9wUmsPoRS9b61A23Q= -golang.org/x/term v0.27.0/go.mod h1:iMsnZpn0cago0GOrHO2+Y7u7JPn5AylBrcoWkElMTSM= +golang.org/x/term v0.25.0 h1:WtHI/ltw4NvSUig5KARz9h521QvRC8RmF/cuYqifU24= +golang.org/x/term v0.25.0/go.mod h1:RPyXicDX+6vLxogjjRxjgD2TKtmAO6NZBsBRfrOLu7M= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -1606,11 +1563,10 @@ golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= -golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo= -golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ= +golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM= +golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -1633,6 +1589,7 @@ golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgw golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20190823170909-c4a336ef6a2f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191010075000-0337d82405ff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= @@ -1642,6 +1599,7 @@ golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtn golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191216052735-49a3e744a425/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200103221440-774c71fcf114/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= @@ -1652,33 +1610,16 @@ golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapK golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= -golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= -golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE= -golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= -golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= -golang.org/x/tools v0.7.0/go.mod h1:4pg6aUX35JBAogB10C9AtvVL+qowtN4pT3CGSQex14s= -golang.org/x/tools v0.28.0 h1:WuB6qZ4RPCQo5aP3WdKZS7i595EdWqWR8vqJTlwTVK8= -golang.org/x/tools v0.28.0/go.mod h1:dcIOrVd3mfQKTgrDVQHqCPMWy6lnhfhtX3hLXYVLfRw= +golang.org/x/tools v0.26.0 h1:v/60pFQmzmT9ExmjDv2gGIfi3OqfKoEP6I5+umXlbnQ= +golang.org/x/tools v0.26.0/go.mod h1:TPVVj70c7JJ3WCazhD8OdXcZg/og+b9+tH/KxylGwH0= golang.org/x/xerrors v0.0.0-20190410155217-1f06c39b4373/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20190513163551-3ee3066db522/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -1694,39 +1635,29 @@ google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEt google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= +google.golang.org/api v0.10.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= -google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM= -google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc= -google.golang.org/api v0.35.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg= -google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34qYtE= -google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8= -google.golang.org/api v0.41.0/go.mod h1:RkxM5lITDfTzmyKFPt+wGrCJbVfniCr2ool8kTBzRTU= -google.golang.org/api v0.43.0/go.mod h1:nQsDGjRXMo4lvh5hP0TKqF244gqhGcr/YSIykhUk/94= -google.golang.org/api v0.44.0/go.mod h1:EBOGZqzyhtvMDoxwS97ctnh0zUmYY6CxqXsc1AvkYD8= google.golang.org/api v0.202.0 h1:y1iuVHMqokQbimW79ZqPZWo4CiyFu6HcCYHwSNyzlfo= google.golang.org/api v0.202.0/go.mod h1:3Jjeq7M/SFblTNCp7ES2xhq+WvGL0KeXI0joHQBfwTQ= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= +google.golang.org/appengine v1.6.2/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20180831171423-11092d34479b/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190716160619-c506a9f90610/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= @@ -1739,33 +1670,12 @@ google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvx google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA= google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200324203455-a04cca1dde73/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200423170343-7949de9c1215/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= -google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= -google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210222152913-aa3ee6e6a81c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210303154014-9728d6b83eeb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210310155132-4ce2db91004e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210319143718-93e7006c17a6/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210401141331-865547bb08e2/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A= -google.golang.org/genproto v0.0.0-20210402141018-6c239bbf2bb1/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A= -google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= google.golang.org/genproto v0.0.0-20241021214115-324edc3d5d38 h1:Q3nlH8iSQSRUwOskjbcSMcF2jiYMNiQYZ0c2KEJLKKU= google.golang.org/genproto v0.0.0-20241021214115-324edc3d5d38/go.mod h1:xBI+tzfqGGN2JBeSebfKXFSdBpWVQ7sLW40PTupVRm4= google.golang.org/genproto/googleapis/api v0.0.0-20241021214115-324edc3d5d38 h1:2oV8dfuIkM1Ti7DwXc0BJfnwr9csz4TDXI9EmiI+Rbw= @@ -1775,23 +1685,18 @@ google.golang.org/genproto/googleapis/rpc v0.0.0-20241021214115-324edc3d5d38/go. google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= +google.golang.org/grpc v1.22.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.23.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= -google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= -google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= -google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= -google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8= -google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= -google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= google.golang.org/grpc v1.36.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= -google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= google.golang.org/grpc v1.67.1 h1:zWnc1Vrcno+lHZCOofnIMvycFcc0QRGIzm9dhnDX68E= google.golang.org/grpc v1.67.1/go.mod h1:1gLDyUQU7CTLJI90u3nXZ9ekeghjeM7pTDZlqFNg2AA= google.golang.org/grpc/stats/opentelemetry v0.0.0-20241022174616-4bb0170ac65f h1:TsfHqsKI7qhOoYugDRyFDSKAuzegDVmkSCpjUyLkb+8= @@ -1804,7 +1709,6 @@ google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzi google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= @@ -1827,13 +1731,15 @@ gopkg.in/guregu/null.v2 v2.1.2/go.mod h1:XORrx8tyS5ZDcyUboCIxQtta/Aujk/6pfWrn9Xe gopkg.in/guregu/null.v4 v4.0.0 h1:1Wm3S1WEA2I26Kq+6vcW+w0gcDo44YKYD7YIEJNHDjg= gopkg.in/guregu/null.v4 v4.0.0/go.mod h1:YoQhUrADuG3i9WqesrCmpNRwm1ypAgSHYqoOcTu/JrI= gopkg.in/inconshreveable/log15.v2 v2.0.0-20180818164646-67afb5ed74ec/go.mod h1:aPpfJ7XW+gOuirDoZ8gHhLh3kZ1B08FtV2bbmy7Jv3s= -gopkg.in/ini.v1 v1.62.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/natefinch/lumberjack.v2 v2.2.1 h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST95x9zc= gopkg.in/natefinch/lumberjack.v2 v2.2.1/go.mod h1:YD8tP3GAjkrDg1eZH7EGmyESg/lsYskCTPBJVb9jqSc= +gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= +gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= @@ -1856,7 +1762,6 @@ honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWh honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= honnef.co/go/tools v0.1.3/go.mod h1:NgwopIslSNH47DimFoV78dnkksY2EFtX0ajyb3K/las= k8s.io/utils v0.0.0-20240711033017-18e509b52bc8 h1:pUdcCO1Lk/tbT5ztQWOBi5HBgbBP1J8+AsQnQCKsi8A= k8s.io/utils v0.0.0-20240711033017-18e509b52bc8/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= diff --git a/integration-tests/.golangci.yml b/integration-tests/.golangci.yml index 337555e17cb..8969110d988 100644 --- a/integration-tests/.golangci.yml +++ b/integration-tests/.golangci.yml @@ -1,33 +1,15 @@ run: timeout: 15m - allow-parallel-runners: true linters: enable: - - containedctx - - depguard - - errname - - errorlint - exhaustive - exportloopref - - fatcontext - - ginkgolinter - - gocritic + - revive - goimports - gosec - - loggercheck - - mirror - misspell - - noctx - - nolintlint - - perfsprint - - prealloc - - revive - rowserrcheck - - spancheck - - sqlclosecheck - - testifylint - - unconvert - - whitespace + - errorlint linters-settings: exhaustive: default-signifies-exhaustive: true @@ -41,28 +23,6 @@ linters-settings: govet: enable: - shadow - settings: - printf: - # Additionally check chainlink custom loggers - funcs: - - (github.com/smartcontractkit/chainlink/v2/core/logger.Logger).Tracef - - (github.com/smartcontractkit/chainlink/v2/core/logger.Logger).Debugf - - (github.com/smartcontractkit/chainlink/v2/core/logger.Logger).Infof - - (github.com/smartcontractkit/chainlink/v2/core/logger.Logger).Warnf - - (github.com/smartcontractkit/chainlink/v2/core/logger.Logger).Errorf - - (github.com/smartcontractkit/chainlink/v2/core/logger.Logger).Criticalf - - (github.com/smartcontractkit/chainlink/v2/core/logger.Logger).Panicf - - (github.com/smartcontractkit/chainlink/v2/core/logger.Logger).Fatalf - - (github.com/smartcontractkit/chainlink/v2/core/logger.SugaredLogger).AssumptionViolationf - - (github.com/smartcontractkit/chainlink-common/pkg/logger.Logger).Debugf - - (github.com/smartcontractkit/chainlink-common/pkg/logger.Logger).Infof - - (github.com/smartcontractkit/chainlink-common/pkg/logger.Logger).Warnf - - (github.com/smartcontractkit/chainlink-common/pkg/logger.Logger).Errorf - - (github.com/smartcontractkit/chainlink-common/pkg/logger.Logger).Panicf - - (github.com/smartcontractkit/chainlink-common/pkg/logger.Logger).Fatalf - - (github.com/smartcontractkit/chainlink-common/pkg/logger.SugaredLogger).AssumptionViolationf - - (github.com/smartcontractkit/chainlink-common/pkg/logger.SugaredLogger).Tracef - - (github.com/smartcontractkit/chainlink-common/pkg/logger.SugaredLogger).Criticalf revive: confidence: 0.8 rules: @@ -73,10 +33,9 @@ linters-settings: - name: error-return - name: error-strings - name: error-naming - - name: exported - name: if-return - name: increment-decrement - - name: var-naming + # - name: var-naming // doesn't work with some generated names - name: var-declaration - name: package-comments - name: range @@ -87,7 +46,7 @@ linters-settings: - name: errorf - name: empty-block - name: superfluous-else - # - name: unused-parameter + #- name: unused-parameter - name: unreachable-code - name: redefines-builtin-id - name: waitgroup-by-value @@ -102,69 +61,13 @@ linters-settings: - name: identical-branches - name: get-return # - name: flag-parameter // probably one we should work on doing better at in the future - - name: early-return + # - name: early-return // probably one we should work on doing better at in the future - name: defer - name: constant-logical-expr - name: confusing-naming - name: confusing-results - name: bool-literal-in-expr - name: atomic - depguard: - rules: - main: - list-mode: lax - deny: - - pkg: cosmossdk.io/errors - desc: Use the standard library instead - - pkg: github.com/gofrs/uuid - desc: Use github.com/google/uuid instead - - pkg: github.com/jackc/pgx3 - desc: Use github.com/jackc/pgx4 instead - - pkg: github.com/jackc/pgx5 - desc: Use github.com/jackc/pgx4 instead - - pkg: github.com/satori/go.uuid - desc: Use github.com/google/uuid instead - - pkg: github.com/test-go/testify/assert - desc: Use github.com/stretchr/testify/assert instead - - pkg: github.com/test-go/testify/mock - desc: Use github.com/stretchr/testify/mock instead - - pkg: github.com/test-go/testify/require - desc: Use github.com/stretchr/testify/require instead - - pkg: go.uber.org/multierr - desc: Use the standard library instead, for example https://pkg.go.dev/errors#Join - - pkg: gopkg.in/guregu/null.v1 - desc: Use gopkg.in/guregu/null.v4 instead - - pkg: gopkg.in/guregu/null.v2 - desc: Use gopkg.in/guregu/null.v4 instead - - pkg: gopkg.in/guregu/null.v3 - desc: Use gopkg.in/guregu/null.v4 instead - - pkg: github.com/go-gorm/gorm - desc: Use github.com/jmoiron/sqlx directly instead - loggercheck: - # Check that *w logging functions have even number of args (i.e., well formed key-value pairs). - rules: - - (github.com/smartcontractkit/chainlink/v2/core/logger.Logger).Tracew - - (github.com/smartcontractkit/chainlink/v2/core/logger.Logger).Debugw - - (github.com/smartcontractkit/chainlink/v2/core/logger.Logger).Infow - - (github.com/smartcontractkit/chainlink/v2/core/logger.Logger).Warnw - - (github.com/smartcontractkit/chainlink/v2/core/logger.Logger).Errorw - - (github.com/smartcontractkit/chainlink/v2/core/logger.Logger).Criticalw - - (github.com/smartcontractkit/chainlink/v2/core/logger.Logger).Panicw - - (github.com/smartcontractkit/chainlink/v2/core/logger.Logger).Fatalw - - (github.com/smartcontractkit/chainlink/v2/core/logger.SugaredLogger).AssumptionViolationw - - (github.com/smartcontractkit/chainlink-common/pkg/logger.Logger).Debugw - - (github.com/smartcontractkit/chainlink-common/pkg/logger.Logger).Infow - - (github.com/smartcontractkit/chainlink-common/pkg/logger.Logger).Warnw - - (github.com/smartcontractkit/chainlink-common/pkg/logger.Logger).Errorw - - (github.com/smartcontractkit/chainlink-common/pkg/logger.Logger).Panicw - - (github.com/smartcontractkit/chainlink-common/pkg/logger.Logger).Fatalw - - (github.com/smartcontractkit/chainlink-common/pkg/logger.SugaredLogger).AssumptionViolationw - - (github.com/smartcontractkit/chainlink-common/pkg/logger.SugaredLogger).Tracew - - (github.com/smartcontractkit/chainlink-common/pkg/logger.SugaredLogger).Criticalw - - (github.com/smartcontractkit/chainlink-common/pkg/logger.SugaredLogger).With - nolintlint: - require-specific: true - require-explanation: true issues: exclude-rules: - text: "^G404: Use of weak random number generator" diff --git a/integration-tests/.tool-versions b/integration-tests/.tool-versions index 3e44e439ff2..e85f4cdc4e5 100644 --- a/integration-tests/.tool-versions +++ b/integration-tests/.tool-versions @@ -1,6 +1,6 @@ -golang 1.23.3 +golang 1.22.8 k3d 5.4.6 kubectl 1.25.5 nodejs 20.13.1 -golangci-lint 1.62.0 +golangci-lint 1.61.1 task 3.35.1 diff --git a/integration-tests/actions/actions.go b/integration-tests/actions/actions.go index 53283967976..76e6cbd4185 100644 --- a/integration-tests/actions/actions.go +++ b/integration-tests/actions/actions.go @@ -350,13 +350,12 @@ func SendFunds(logger zerolog.Logger, client *seth.Client, payload FundsToSendPa return nil, err } - gasLimit, err := client.EstimateGasLimitForFundTransfer(fromAddress, payload.ToAddress, payload.Amount) + var gasLimit int64 + gasLimitRaw, err := client.EstimateGasLimitForFundTransfer(fromAddress, payload.ToAddress, payload.Amount) if err != nil { - transferGasFee := client.Cfg.Network.TransferGasFee - if transferGasFee < 0 { - return nil, fmt.Errorf("negative transfer gas fee: %d", transferGasFee) - } - gasLimit = uint64(transferGasFee) + gasLimit = client.Cfg.Network.TransferGasFee + } else { + gasLimit = int64(gasLimitRaw) } gasPrice := big.NewInt(0) @@ -364,17 +363,14 @@ func SendFunds(logger zerolog.Logger, client *seth.Client, payload FundsToSendPa gasTipCap := big.NewInt(0) if payload.GasLimit != nil { - if *payload.GasLimit < 0 { - return nil, fmt.Errorf("negative gas limit: %d", *payload.GasLimit) - } - gasLimit = uint64(*payload.GasLimit) + gasLimit = *payload.GasLimit } if client.Cfg.Network.EIP1559DynamicFees { // if any of the dynamic fees are not set, we need to either estimate them or read them from config if payload.GasFeeCap == nil || payload.GasTipCap == nil { // estimation or config reading happens here - txOptions := client.NewTXOpts(seth.WithGasLimit(gasLimit)) + txOptions := client.NewTXOpts(seth.WithGasLimit(uint64(gasLimit))) gasFeeCap = txOptions.GasFeeCap gasTipCap = txOptions.GasTipCap } @@ -389,7 +385,7 @@ func SendFunds(logger zerolog.Logger, client *seth.Client, payload FundsToSendPa } } else { if payload.GasPrice == nil { - txOptions := client.NewTXOpts(seth.WithGasLimit(gasLimit)) + txOptions := client.NewTXOpts(seth.WithGasLimit(uint64(gasLimit))) gasPrice = txOptions.GasPrice } else { gasPrice = payload.GasPrice @@ -403,7 +399,7 @@ func SendFunds(logger zerolog.Logger, client *seth.Client, payload FundsToSendPa Nonce: nonce, To: &payload.ToAddress, Value: payload.Amount, - Gas: gasLimit, + Gas: uint64(gasLimit), GasFeeCap: gasFeeCap, GasTipCap: gasTipCap, } @@ -412,7 +408,7 @@ func SendFunds(logger zerolog.Logger, client *seth.Client, payload FundsToSendPa Nonce: nonce, To: &payload.ToAddress, Value: payload.Amount, - Gas: gasLimit, + Gas: uint64(gasLimit), GasPrice: gasPrice, } } @@ -433,7 +429,7 @@ func SendFunds(logger zerolog.Logger, client *seth.Client, payload FundsToSendPa Str("To", payload.ToAddress.Hex()). Str("Amount (wei/ether)", fmt.Sprintf("%s/%s", payload.Amount, conversions.WeiToEther(payload.Amount).Text('f', -1))). Uint64("Nonce", nonce). - Uint64("Gas Limit", gasLimit). + Int64("Gas Limit", gasLimit). Str("Gas Price", gasPrice.String()). Str("Gas Fee Cap", gasFeeCap.String()). Str("Gas Tip Cap", gasTipCap.String()). @@ -453,7 +449,7 @@ func SendFunds(logger zerolog.Logger, client *seth.Client, payload FundsToSendPa Str("TxHash", signedTx.Hash().String()). Str("Amount (wei/ether)", fmt.Sprintf("%s/%s", payload.Amount, conversions.WeiToEther(payload.Amount).Text('f', -1))). Uint64("Nonce", nonce). - Uint64("Gas Limit", gasLimit). + Int64("Gas Limit", gasLimit). Str("Gas Price", gasPrice.String()). Str("Gas Fee Cap", gasFeeCap.String()). Str("Gas Tip Cap", gasTipCap.String()). @@ -1042,7 +1038,7 @@ func GetLatestFinalizedBlockHeader(ctx context.Context, client *seth.Client, net } latestBlockNumber := header.Number.Uint64() finalizedBlockNumber := latestBlockNumber - network.FinalityDepth - return client.Client.HeaderByNumber(ctx, new(big.Int).SetUint64(finalizedBlockNumber)) + return client.Client.HeaderByNumber(ctx, big.NewInt(int64(finalizedBlockNumber))) } // SendLinkFundsToDeploymentAddresses sends LINK token to all addresses, but the root one, from the root address. It uses @@ -1245,7 +1241,7 @@ func GetStalenessReportCleanupFn(t *testing.T, logger zerolog.Logger, chainClien endBlock, err := chainClient.Client.BlockNumber(context.Background()) require.NoError(t, err, "Failed to get end block") - total, ok, reverted, stale, err := GenerateUpkeepReport(t, chainClient, new(big.Int).SetUint64(startBlock), new(big.Int).SetUint64(endBlock), registry, registryVersion) + total, ok, reverted, stale, err := GenerateUpkeepReport(t, chainClient, big.NewInt(int64(startBlock)), big.NewInt(int64(endBlock)), registry, registryVersion) require.NoError(t, err, "Failed to get staleness data") if stale > 0 || reverted > 0 { logger.Warn().Int("Total upkeeps", total).Int("Successful upkeeps", ok).Int("Reverted Upkeeps", reverted).Int("Stale Upkeeps", stale).Msg("Staleness data") diff --git a/integration-tests/actions/automationv2/actions.go b/integration-tests/actions/automationv2/actions.go index 25033201dd1..1f17634e58d 100644 --- a/integration-tests/actions/automationv2/actions.go +++ b/integration-tests/actions/automationv2/actions.go @@ -7,7 +7,6 @@ import ( "encoding/json" "errors" "fmt" - "math" "math/big" "strings" "testing" @@ -643,15 +642,10 @@ func calculateOCR2ConfigArgs(a *AutomationTest, S []int, oracleIdentities []conf MaxUpkeepBatchSize: a.PluginConfig.MaxUpkeepBatchSize, }) - rMax := a.PublicConfig.RMax - if rMax > math.MaxUint8 { - panic(fmt.Errorf("rmax overflows uint8: %d", rMax)) - } - return ocr2.ContractSetConfigArgsForTests( a.PublicConfig.DeltaProgress, a.PublicConfig.DeltaResend, a.PublicConfig.DeltaRound, a.PublicConfig.DeltaGrace, - a.PublicConfig.DeltaStage, uint8(rMax), + a.PublicConfig.DeltaStage, uint8(a.PublicConfig.RMax), S, oracleIdentities, offC, nil, a.PublicConfig.MaxDurationQuery, a.PublicConfig.MaxDurationObservation, diff --git a/integration-tests/actions/ccip_helpers.go b/integration-tests/actions/ccip_helpers.go deleted file mode 100644 index cdfd343eaa5..00000000000 --- a/integration-tests/actions/ccip_helpers.go +++ /dev/null @@ -1,45 +0,0 @@ -package actions - -import ( - "fmt" - "net/http" - - "github.com/rs/zerolog/log" - - ctfClient "github.com/smartcontractkit/chainlink-testing-framework/lib/client" - ctftestenv "github.com/smartcontractkit/chainlink-testing-framework/lib/docker/test_env" -) - -// SetMockServerWithUSDCAttestation responds with a mock attestation for any msgHash -// The path is set with regex to match any path that starts with /v1/attestations -func SetMockServerWithUSDCAttestation( - killGrave *ctftestenv.Killgrave, - mockserver *ctfClient.MockserverClient, -) error { - path := "/v1/attestations" - response := struct { - Status string `json:"status"` - Attestation string `json:"attestation"` - Error string `json:"error"` - }{ - Status: "complete", - Attestation: "0x9049623e91719ef2aa63c55f357be2529b0e7122ae552c18aff8db58b4633c4d3920ff03d3a6d1ddf11f06bf64d7fd60d45447ac81f527ba628877dc5ca759651b08ffae25a6d3b1411749765244f0a1c131cbfe04430d687a2e12fd9d2e6dc08e118ad95d94ad832332cf3c4f7a4f3da0baa803b7be024b02db81951c0f0714de1b", - } - if killGrave == nil && mockserver == nil { - return fmt.Errorf("both killgrave and mockserver are nil") - } - log.Info().Str("path", path).Msg("setting attestation-api response for any msgHash") - if killGrave != nil { - err := killGrave.SetAnyValueResponse(fmt.Sprintf("%s/{_hash:.*}", path), []string{http.MethodGet}, response) - if err != nil { - return fmt.Errorf("failed to set killgrave server value: %w", err) - } - } - if mockserver != nil { - err := mockserver.SetAnyValueResponse(fmt.Sprintf("%s/.*", path), response) - if err != nil { - return fmt.Errorf("failed to set mockserver value: %w URL = %s", err, fmt.Sprintf("%s/%s/.*", mockserver.LocalURL(), path)) - } - } - return nil -} diff --git a/integration-tests/actions/keeper_helpers.go b/integration-tests/actions/keeper_helpers.go index 1562e363f8c..0966e0b486e 100644 --- a/integration-tests/actions/keeper_helpers.go +++ b/integration-tests/actions/keeper_helpers.go @@ -670,14 +670,15 @@ Distribute your funds across multiple private keys and update your configuration func GetAndAssertCorrectConcurrency(client *seth.Client, minConcurrency int) (int, error) { concurrency := client.Cfg.GetMaxConcurrency() + var msg string + if client.Cfg.IsSimulatedNetwork() { + msg = fmt.Sprintf(INSUFFICIENT_EPHEMERAL_KEYS, concurrency) + } else { + msg = fmt.Sprintf(INSUFFICIENT_STATIC_KEYS, concurrency) + } + if concurrency < minConcurrency { - var err error - if client.Cfg.IsSimulatedNetwork() { - err = fmt.Errorf(INSUFFICIENT_EPHEMERAL_KEYS, concurrency) - } else { - err = fmt.Errorf(INSUFFICIENT_STATIC_KEYS, concurrency) - } - return 0, err + return 0, fmt.Errorf(msg) } return concurrency, nil diff --git a/integration-tests/actions/ocr2_helpers.go b/integration-tests/actions/ocr2_helpers.go index 842395bb25b..1d386b158a0 100644 --- a/integration-tests/actions/ocr2_helpers.go +++ b/integration-tests/actions/ocr2_helpers.go @@ -4,15 +4,12 @@ import ( "crypto/ed25519" "encoding/hex" "fmt" - "net/http" "strings" "time" - "github.com/avast/retry-go" "github.com/ethereum/go-ethereum/common" "github.com/google/uuid" "github.com/lib/pq" - "github.com/rs/zerolog" "github.com/rs/zerolog/log" "golang.org/x/sync/errgroup" "gopkg.in/guregu/null.v4" @@ -195,7 +192,6 @@ func CreateOCRv2Jobs( mockServerValue int, // Value to get from the mock server when querying the path chainId int64, // EVM chain ID forwardingAllowed bool, - l zerolog.Logger, ) error { // Collect P2P ID bootstrapP2PIds, err := bootstrapNode.MustReadP2PKeys() @@ -222,9 +218,6 @@ func CreateOCRv2Jobs( } } - // Initialize map to store job IDs for each chainlink node - jobIDs := make(map[*nodeclient.ChainlinkK8sClient][]string) - for _, ocrInstance := range ocrInstances { bootstrapSpec := &nodeclient.OCR2TaskJobSpec{ Name: fmt.Sprintf("ocr2-bootstrap-%s", ocrInstance.Address()), @@ -291,46 +284,10 @@ func CreateOCRv2Jobs( P2PV2Bootstrappers: pq.StringArray{p2pV2Bootstrapper}, // bootstrap node key and address @bootstrap:6690 }, } - var ocrJob *nodeclient.Job - ocrJob, err = chainlinkNode.MustCreateJob(ocrSpec) + _, err = chainlinkNode.MustCreateJob(ocrSpec) if err != nil { return fmt.Errorf("creating OCR task job on OCR node have failed: %w", err) } - jobIDs[chainlinkNode] = append(jobIDs[chainlinkNode], ocrJob.Data.ID) // Store each job ID per node - } - } - l.Info().Msg("Verify OCRv2 jobs have been created") - for chainlinkNode, ids := range jobIDs { - for _, jobID := range ids { - err := retry.Do( - func() error { - _, resp, err := chainlinkNode.ReadJob(jobID) - if err != nil { - return err - } - if resp.StatusCode != http.StatusOK { - return fmt.Errorf("unexpected response status: %d", resp.StatusCode) - } - l.Info(). - Str("Node", chainlinkNode.PodName). - Str("Job ID", jobID). - Msg("OCRv2 job successfully created") - return nil - }, - retry.Attempts(4), - retry.Delay(time.Second*2), - retry.OnRetry(func(n uint, err error) { - l.Debug(). - Str("Node", chainlinkNode.PodName). - Str("Job ID", jobID). - Uint("Attempt", n+1). - Err(err). - Msg("Retrying job verification") - }), - ) - if err != nil { - l.Error().Err(err).Str("Node", chainlinkNode.PodName).Str("JobID", jobID).Msg("Failed to verify OCRv2 job creation") - } } } return nil diff --git a/integration-tests/actions/refund.go b/integration-tests/actions/refund.go index e9910928c6c..0eb83e736e5 100644 --- a/integration-tests/actions/refund.go +++ b/integration-tests/actions/refund.go @@ -5,7 +5,6 @@ import ( "crypto/ecdsa" "encoding/json" "fmt" - "math" "math/big" "regexp" "strconv" @@ -344,9 +343,6 @@ func returnAllFundsIfPossible(log zerolog.Logger, sethClient *seth.Client, fromP if err != nil { gasLimit = sethClient.Cfg.Network.TransferGasFee } else { - if gasLimitRaw > math.MaxInt64 { - return fmt.Errorf("gas limit overflows int64: %d", gasLimitRaw) - } gasLimit = int64(gasLimitRaw) } diff --git a/integration-tests/actions/vrf/vrfv2plus/setup_steps.go b/integration-tests/actions/vrf/vrfv2plus/setup_steps.go index c997bb837c7..3d3a549458a 100644 --- a/integration-tests/actions/vrf/vrfv2plus/setup_steps.go +++ b/integration-tests/actions/vrf/vrfv2plus/setup_steps.go @@ -105,7 +105,7 @@ func SetupVRFV2_5Environment( return nil, nil, nil, err } l.Info().Str("Coordinator", vrfContracts.CoordinatorV2Plus.Address()).Msg("Registering Proving Key") - provingKey, err := VRFV2_5RegisterProvingKey(vrfKey, vrfContracts.CoordinatorV2Plus, assets.GWei(*configGeneral.CLNodeMaxGasPriceGWei).ToInt().Uint64()) + provingKey, err := VRFV2_5RegisterProvingKey(vrfKey, vrfContracts.CoordinatorV2Plus, uint64(assets.GWei(*configGeneral.CLNodeMaxGasPriceGWei).Int64())) if err != nil { return nil, nil, nil, fmt.Errorf(vrfcommon.ErrGenericFormat, vrfcommon.ErrRegisteringProvingKey, err) } diff --git a/integration-tests/benchmark/automation_test.go b/integration-tests/benchmark/automation_test.go index c4a113a8d99..0a63ff2c27a 100644 --- a/integration-tests/benchmark/automation_test.go +++ b/integration-tests/benchmark/automation_test.go @@ -77,7 +77,7 @@ func TestAutomationBenchmark(t *testing.T) { config, err := tc.GetConfig([]string{testType}, tc.Automation) require.NoError(t, err, "Error getting test config") - testEnvironment, benchmarkNetwork := SetupAutomationBenchmarkEnv(t, testType, &config) + testEnvironment, benchmarkNetwork := SetupAutomationBenchmarkEnv(t, &config) if testEnvironment.WillUseRemoteRunner() { return } @@ -245,7 +245,7 @@ var networkConfig = map[string]NetworkConfig{ }, } -func SetupAutomationBenchmarkEnv(t *testing.T, testType string, keeperTestConfig types.AutomationBenchmarkTestConfig) (*environment.Environment, blockchain.EVMNetwork) { +func SetupAutomationBenchmarkEnv(t *testing.T, keeperTestConfig types.AutomationBenchmarkTestConfig) (*environment.Environment, blockchain.EVMNetwork) { l := logging.GetTestLogger(t) testNetwork := networks.MustGetSelectedNetworkConfig(keeperTestConfig.GetNetworkConfig())[0] // Environment currently being used to run benchmark test on blockTime := "1" @@ -259,12 +259,6 @@ func SetupAutomationBenchmarkEnv(t *testing.T, testType string, keeperTestConfig networkName = strings.ReplaceAll(networkName, "_", "-") testNetwork.Name = networkName - nsLabels, err := environment.GetRequiredChainLinkNamespaceLabels(string(tc.Keeper), testType) - require.NoError(t, err, "Error creating required chain.link labels for namespace") - - workloadPodLabels, err := environment.GetRequiredChainLinkWorkloadAndPodLabels(string(tc.Keeper), testType) - require.NoError(t, err, "Error creating required chain.link labels for workloads and pods") - testEnvironment := environment.New(&environment.Config{ TTL: time.Hour * 720, // 30 days, NamespacePrefix: fmt.Sprintf( @@ -275,9 +269,6 @@ func SetupAutomationBenchmarkEnv(t *testing.T, testType string, keeperTestConfig ), Test: t, PreventPodEviction: true, - Labels: nsLabels, - WorkloadLabels: workloadPodLabels, - PodLabels: workloadPodLabels, }) dbResources := dbResources @@ -325,6 +316,7 @@ func SetupAutomationBenchmarkEnv(t *testing.T, testType string, keeperTestConfig }, })) } + var err error if testNetwork.Simulated { // TODO we need to update the image in CTF, the old one is not available anymore // deploy blockscout if running on simulated diff --git a/integration-tests/ccip-tests/actions/ccip_helpers.go b/integration-tests/ccip-tests/actions/ccip_helpers.go index 492ee2fd0fa..c24ae2ecd54 100644 --- a/integration-tests/ccip-tests/actions/ccip_helpers.go +++ b/integration-tests/ccip-tests/actions/ccip_helpers.go @@ -631,11 +631,7 @@ func (ccipModule *CCIPCommon) UpdateTokenPricesAtRegularInterval(ctx context.Con aggregators = append(aggregators, contract) } go func(aggregators []*contracts.MockAggregator) { - now := time.Now().UnixNano() - if now < 0 { - panic(fmt.Errorf("negative timestamp: %d", now)) - } - rand.NewSource(uint64(now)) + rand.NewSource(uint64(time.Now().UnixNano())) ticker := time.NewTicker(interval) for { select { @@ -1665,11 +1661,7 @@ func (sourceCCIP *SourceCCIPModule) IsPastRequestTriggeredWithinTimeframe(ctx co if err != nil { return nil, fmt.Errorf("error while getting average source block time. Error: %w", err) } - blocks := timeframe.Duration() / avgBlockTime - if blocks < 0 { - return nil, fmt.Errorf("negative blocks: %d", blocks) - } - filterFromBlock := latestBlock - uint64(blocks) //nolint:gosec // G115 false positive + filterFromBlock := latestBlock - uint64(timeframe.Duration()/avgBlockTime) onRampContract, err := evm_2_evm_onramp.NewEVM2EVMOnRamp(common.HexToAddress(sourceCCIP.OnRamp.EthAddress.Hex()), sourceCCIP.Common.ChainClient.Backend()) @@ -1686,7 +1678,7 @@ func (sourceCCIP *SourceCCIPModule) IsPastRequestTriggeredWithinTimeframe(ctx co _ = iterator.Close() }() if iterator.Next() { - hdr, err := sourceCCIP.Common.ChainClient.HeaderByNumber(context.Background(), new(big.Int).SetUint64(iterator.Event.Raw.BlockNumber)) + hdr, err := sourceCCIP.Common.ChainClient.HeaderByNumber(context.Background(), big.NewInt(int64(iterator.Event.Raw.BlockNumber))) if err != nil { return nil, fmt.Errorf("error getting header for block: %d, Error: %w", iterator.Event.Raw.BlockNumber, err) } @@ -4165,7 +4157,7 @@ func (c *CCIPTestEnv) SetUpNodeKeysAndFund( nodeFund *big.Float, chains []blockchain.EVMClient, ) error { - if len(c.CLNodes) == 0 { + if c.CLNodes == nil || len(c.CLNodes) == 0 { return fmt.Errorf("no chainlink nodes to setup") } var chainlinkNodes []*nodeclient.ChainlinkClient @@ -4379,30 +4371,21 @@ func NewBalanceSheet() *BalanceSheet { } } -type attestationStatusResponse struct { - Status string `json:"status"` - Attestation string `json:"attestation"` - Error string `json:"error"` -} - // SetMockServerWithUSDCAttestation responds with a mock attestation for any msgHash // The path is set with regex to match any path that starts with /v1/attestations func SetMockServerWithUSDCAttestation( killGrave *ctftestenv.Killgrave, mockserver *ctfClient.MockserverClient, - isFaulty bool, ) error { path := "/v1/attestations" - response := attestationStatusResponse{ + response := struct { + Status string `json:"status"` + Attestation string `json:"attestation"` + Error string `json:"error"` + }{ Status: "complete", Attestation: "0x9049623e91719ef2aa63c55f357be2529b0e7122ae552c18aff8db58b4633c4d3920ff03d3a6d1ddf11f06bf64d7fd60d45447ac81f527ba628877dc5ca759651b08ffae25a6d3b1411749765244f0a1c131cbfe04430d687a2e12fd9d2e6dc08e118ad95d94ad832332cf3c4f7a4f3da0baa803b7be024b02db81951c0f0714de1b", } - if isFaulty { - response = attestationStatusResponse{ - Status: "pending", - Error: "internal error", - } - } if killGrave == nil && mockserver == nil { return fmt.Errorf("both killgrave and mockserver are nil") } diff --git a/integration-tests/ccip-tests/actions/reorg_helpers.go b/integration-tests/ccip-tests/actions/reorg_helpers.go index 2ce9639613b..017b8ffab69 100644 --- a/integration-tests/ccip-tests/actions/reorg_helpers.go +++ b/integration-tests/ccip-tests/actions/reorg_helpers.go @@ -27,16 +27,16 @@ type ReorgConfig struct { // DstGethHTTPURL dest chain Geth HTTP URL DstGethHTTPURL string // SrcFinalityDepth source chain finality depth - SrcFinalityDepth int + SrcFinalityDepth uint64 // DstGethHTTPURL dest chain finality depth - DstFinalityDepth int + DstFinalityDepth uint64 // FinalityDelta blocks to rewind below or above finality FinalityDelta int } // Validate validates ReorgConfig params func (rc *ReorgConfig) Validate() error { - if rc.FinalityDelta >= rc.SrcFinalityDepth || rc.FinalityDelta >= rc.DstFinalityDepth { + if rc.FinalityDelta >= int(rc.SrcFinalityDepth) || rc.FinalityDelta >= int(rc.DstFinalityDepth) { return fmt.Errorf( "finality delta can't be higher than source or dest chain finality, delta: %d, src: %d, dst: %d", rc.FinalityDelta, rc.SrcFinalityDepth, rc.DstFinalityDepth, diff --git a/integration-tests/ccip-tests/contracts/contract_deployer.go b/integration-tests/ccip-tests/contracts/contract_deployer.go index 1f2859ae0db..07ed6e5dd8e 100644 --- a/integration-tests/ccip-tests/contracts/contract_deployer.go +++ b/integration-tests/ccip-tests/contracts/contract_deployer.go @@ -21,9 +21,8 @@ import ( ocrconfighelper2 "github.com/smartcontractkit/libocr/offchainreporting2/confighelper" ocrtypes2 "github.com/smartcontractkit/libocr/offchainreporting2/types" - "github.com/smartcontractkit/chainlink-testing-framework/lib/blockchain" - "github.com/smartcontractkit/chainlink-common/pkg/config" + "github.com/smartcontractkit/chainlink-testing-framework/lib/blockchain" "github.com/smartcontractkit/chainlink/deployment/environment/nodeclient" "github.com/smartcontractkit/chainlink/integration-tests/contracts" @@ -57,6 +56,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/abihelpers" ccipconfig "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/config" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/testhelpers" + "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/testhelpers/testhelpers_1_4_0" "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm" ) @@ -505,7 +505,6 @@ func (e *CCIPContractsDeployer) DeployLockReleaseTokenPoolContract(tokenAddr str auth, wrappers.MustNewWrappedContractBackend(e.evmClient, nil), token, - 18, []common.Address{}, rmnProxy, true, @@ -1414,6 +1413,16 @@ func NewCommitOffchainConfig( InflightCacheExpiry, priceReportingDisabled, ), nil + case V1_2_0: + return testhelpers_1_4_0.NewCommitOffchainConfig( + GasPriceHeartBeat, + DAGasPriceDeviationPPB, + ExecGasPriceDeviationPPB, + TokenPriceHeartBeat, + TokenPriceDeviationPPB, + InflightCacheExpiry, + priceReportingDisabled, + ), nil default: return nil, fmt.Errorf("version not supported: %s", VersionMap[CommitStoreContract]) } @@ -1425,6 +1434,8 @@ func NewCommitOnchainConfig( switch VersionMap[CommitStoreContract] { case Latest: return testhelpers.NewCommitOnchainConfig(PriceRegistry), nil + case V1_2_0: + return testhelpers_1_4_0.NewCommitOnchainConfig(PriceRegistry), nil default: return nil, fmt.Errorf("version not supported: %s", VersionMap[CommitStoreContract]) } @@ -1441,6 +1452,15 @@ func NewExecOnchainConfig( switch VersionMap[OffRampContract] { case Latest: return testhelpers.NewExecOnchainConfig(PermissionLessExecutionThresholdSeconds, Router, PriceRegistry, MaxNumberOfTokensPerMsg, MaxDataBytes), nil + case V1_2_0: + return testhelpers_1_4_0.NewExecOnchainConfig( + PermissionLessExecutionThresholdSeconds, + Router, + PriceRegistry, + MaxNumberOfTokensPerMsg, + MaxDataBytes, + MaxPoolReleaseOrMintGas, + ), nil default: return nil, fmt.Errorf("version not supported: %s", VersionMap[OffRampContract]) } @@ -1465,6 +1485,15 @@ func NewExecOffchainConfig( rootSnoozeTime, batchingStrategyID, ), nil + case V1_2_0: + return testhelpers_1_4_0.NewExecOffchainConfig( + destOptimisticConfirmations, + batchGasLimit, + relativeBoostPerWaitHour, + inflightCacheExpiry, + rootSnoozeTime, + batchingStrategyID, + ), nil default: return nil, fmt.Errorf("version not supported: %s", VersionMap[OffRampContract]) } diff --git a/integration-tests/ccip-tests/contracts/contract_models.go b/integration-tests/ccip-tests/contracts/contract_models.go index 257670dbaa1..83fe12a60a6 100644 --- a/integration-tests/ccip-tests/contracts/contract_models.go +++ b/integration-tests/ccip-tests/contracts/contract_models.go @@ -478,13 +478,14 @@ func (w TokenPoolWrapper) IsSupportedChain(opts *bind.CallOpts, remoteChainSelec func (w TokenPoolWrapper) ApplyChainUpdates(opts *bind.TransactOpts, update []token_pool.TokenPoolChainUpdate) (*types.Transaction, error) { if w.Latest != nil && w.Latest.PoolInterface != nil { - return w.Latest.PoolInterface.ApplyChainUpdates(opts, []uint64{}, update) + return w.Latest.PoolInterface.ApplyChainUpdates(opts, update) } if w.V1_4_0 != nil && w.V1_4_0.PoolInterface != nil { V1_4_0Updates := make([]token_pool_1_4_0.TokenPoolChainUpdate, len(update)) for i, u := range update { V1_4_0Updates[i] = token_pool_1_4_0.TokenPoolChainUpdate{ RemoteChainSelector: u.RemoteChainSelector, + Allowed: u.Allowed, InboundRateLimiterConfig: token_pool_1_4_0.RateLimiterConfig{ IsEnabled: u.InboundRateLimiterConfig.IsEnabled, Capacity: u.InboundRateLimiterConfig.Capacity, @@ -503,13 +504,8 @@ func (w TokenPoolWrapper) ApplyChainUpdates(opts *bind.TransactOpts, update []to } func (w TokenPoolWrapper) SetChainRateLimiterConfig(opts *bind.TransactOpts, selector uint64, out token_pool.RateLimiterConfig, in token_pool.RateLimiterConfig) (*types.Transaction, error) { - if w.Latest != nil && w.Latest.PoolInterface != nil { - selectors := []uint64{selector} - out := []token_pool.RateLimiterConfig{out} - in := []token_pool.RateLimiterConfig{in} - - return w.Latest.PoolInterface.SetChainRateLimiterConfigs(opts, selectors, out, in) + return w.Latest.PoolInterface.SetChainRateLimiterConfig(opts, selector, out, in) } if w.V1_4_0 != nil && w.V1_4_0.PoolInterface != nil { return w.V1_4_0.PoolInterface.SetChainRateLimiterConfig(opts, selector, @@ -832,8 +828,9 @@ func (pool *TokenPool) SetRemoteChainOnPool(remoteChainSelector uint64, remotePo selectorsToUpdate = append(selectorsToUpdate, token_pool.TokenPoolChainUpdate{ RemoteChainSelector: remoteChainSelector, - RemotePoolAddresses: [][]byte{encodedPoolAddress}, + RemotePoolAddress: encodedPoolAddress, RemoteTokenAddress: encodedTokenAddress, + Allowed: true, InboundRateLimiterConfig: token_pool.RateLimiterConfig{ IsEnabled: true, Capacity: new(big.Int).Mul(big.NewInt(1e18), big.NewInt(1e9)), @@ -2244,11 +2241,7 @@ func (a *MockAggregator) UpdateRoundData(answer *big.Int, minP, maxP *int) error // if answer is nil, we calculate the answer with random percentage (within the provided range) of latest answer if answer == nil { - now := time.Now().UnixNano() - if now < 0 { - return fmt.Errorf("negative timestamp: %d", now) - } - rand.Seed(uint64(now)) + rand.Seed(uint64(time.Now().UnixNano())) randomNumber := rand.Intn(pointer.GetInt(maxP)-pointer.GetInt(minP)+1) + pointer.GetInt(minP) // answer = previous round answer + (previous round answer * random percentage) answer = new(big.Int).Add(a.Answer, new(big.Int).Div(new(big.Int).Mul(a.Answer, big.NewInt(int64(randomNumber))), big.NewInt(100))) diff --git a/integration-tests/ccip-tests/load/ccip_loadgen.go b/integration-tests/ccip-tests/load/ccip_loadgen.go index d562cce88b2..3ce770d31bc 100644 --- a/integration-tests/ccip-tests/load/ccip_loadgen.go +++ b/integration-tests/ccip-tests/load/ccip_loadgen.go @@ -300,7 +300,7 @@ func (c *CCIPE2ELoad) Call(_ *wasp.Generator) *wasp.Response { } // the msg is no longer needed, so we can clear it to avoid holding extra data during load - //nolint:ineffassign,staticcheck + // nolint:ineffassign,staticcheck msg = router.ClientEVM2AnyMessage{} txConfirmationTime := time.Now().UTC() diff --git a/integration-tests/ccip-tests/smoke/ccip_test.go b/integration-tests/ccip-tests/smoke/ccip_test.go index a74d404db18..08054459481 100644 --- a/integration-tests/ccip-tests/smoke/ccip_test.go +++ b/integration-tests/ccip-tests/smoke/ccip_test.go @@ -2,7 +2,6 @@ package smoke import ( "fmt" - "math" "math/big" "testing" "time" @@ -15,7 +14,7 @@ import ( "github.com/smartcontractkit/chainlink-testing-framework/lib/logging" "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/ptr" - "github.com/smartcontractkit/chainlink/integration-tests/ccip-tests/utils" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/evm_2_evm_onramp" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/lock_release_token_pool" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/token_pool" @@ -875,8 +874,8 @@ func TestSmokeCCIPReorgBelowFinality(t *testing.T) { require.NoError(t, err, "Send requests failed") rs := SetupReorgSuite(t, &log, setUpOutput) // run below finality reorg in both source and destination chain - blocksBackSrc := rs.Cfg.SrcFinalityDepth - rs.Cfg.FinalityDelta - blocksBackDst := rs.Cfg.DstFinalityDepth - rs.Cfg.FinalityDelta + blocksBackSrc := int(rs.Cfg.SrcFinalityDepth) - rs.Cfg.FinalityDelta + blocksBackDst := int(rs.Cfg.DstFinalityDepth) - rs.Cfg.FinalityDelta rs.RunReorg(rs.DstClient, blocksBackSrc, "Source", 2*time.Second) rs.RunReorg(rs.DstClient, blocksBackDst, "Destination", 2*time.Second) time.Sleep(1 * time.Minute) @@ -886,10 +885,9 @@ func TestSmokeCCIPReorgBelowFinality(t *testing.T) { // Test creates above finality reorg at destination and // expects ccip transactions in-flight and the one initiated after reorg -// doesn't go through and verifies f+1 nodes is able to detect reorg. +// doesn't go through and verifies every node is able to detect reorg. // Note: LogPollInterval interval is set as 1s to detect the reorg immediately func TestSmokeCCIPReorgAboveFinalityAtDestination(t *testing.T) { - utils.SkipFlakey(t, "https://smartcontract-it.atlassian.net/browse/CCIP-4401") t.Parallel() t.Run("Above finality reorg in destination chain", func(t *testing.T) { performAboveFinalityReorgAndValidate(t, "Destination") @@ -898,10 +896,9 @@ func TestSmokeCCIPReorgAboveFinalityAtDestination(t *testing.T) { // Test creates above finality reorg at destination and // expects ccip transactions in-flight doesn't go through, the transaction initiated after reorg -// shouldn't even get initiated and verifies f+1 nodes is able to detect reorg. +// shouldn't even get initiated and verifies every node is able to detect reorg. // Note: LogPollInterval interval is set as 1s to detect the reorg immediately func TestSmokeCCIPReorgAboveFinalityAtSource(t *testing.T) { - utils.SkipFlakey(t, "https://smartcontract-it.atlassian.net/browse/CCIP-4401") t.Parallel() t.Run("Above finality reorg in source chain", func(t *testing.T) { performAboveFinalityReorgAndValidate(t, "Source") @@ -933,18 +930,16 @@ func performAboveFinalityReorgAndValidate(t *testing.T, network string) { logPollerName := "" if network == "Destination" { logPollerName = fmt.Sprintf("EVM.%d.LogPoller", lane.DestChain.GetChainID()) - rs.RunReorg(rs.DstClient, rs.Cfg.DstFinalityDepth+rs.Cfg.FinalityDelta, network, 2*time.Second) + rs.RunReorg(rs.DstClient, int(rs.Cfg.DstFinalityDepth)+rs.Cfg.FinalityDelta, network, 2*time.Second) } else { logPollerName = fmt.Sprintf("EVM.%d.LogPoller", lane.SourceChain.GetChainID()) - rs.RunReorg(rs.SrcClient, rs.Cfg.SrcFinalityDepth+rs.Cfg.FinalityDelta, network, 2*time.Second) + rs.RunReorg(rs.SrcClient, int(rs.Cfg.SrcFinalityDepth)+rs.Cfg.FinalityDelta, network, 2*time.Second) } - // DON is 3F+1, finding f+1 from the given number of nodes in the environment - fPlus1Nodes := int(math.Ceil(float64(len(setUpOutput.Env.CLNodes)-1)/3)) + 1 - // assert at least f+1 nodes is detecting the reorg (LogPollInterval is set as 1s for faster detection) - // additional context: Commit requires 2f+1 observations, so f+1 nodes need to detect it in order to force the entire DON to stop processing messages. + clNodes := setUpOutput.Env.CLNodes + // assert every node is detecting the reorg (LogPollInterval is set as 1s for faster detection) nodesDetectedViolation := make(map[string]bool) assert.Eventually(t, func() bool { - for _, node := range setUpOutput.Env.CLNodes { + for _, node := range clNodes { if _, ok := nodesDetectedViolation[node.ChainlinkClient.URL()]; ok { continue } @@ -957,8 +952,8 @@ func performAboveFinalityReorgAndValidate(t *testing.T, network string) { } } } - return len(nodesDetectedViolation) >= fPlus1Nodes - }, 3*time.Minute, 20*time.Second, "Reorg above finality depth is not detected by f+1 nodes") + return len(nodesDetectedViolation) == len(clNodes) + }, 3*time.Minute, 20*time.Second, "Reorg above finality depth is not detected by every node") log.Debug().Interface("Nodes", nodesDetectedViolation).Msg("Violation detection details") // send another request and verify it fails err = lane.SendRequests(1, gasLimit) @@ -1128,25 +1123,17 @@ func testOffRampRateLimits(t *testing.T, rateLimiterConfig contracts.RateLimiter // SetupReorgSuite defines the setup required to perform re-org step func SetupReorgSuite(t *testing.T, lggr *zerolog.Logger, setupOutput *testsetups.CCIPTestSetUpOutputs) *actions.ReorgSuite { - var finalitySrc int - var finalityDst int + var finalitySrc uint64 + var finalityDst uint64 if setupOutput.Cfg.SelectedNetworks[0].FinalityTag { finalitySrc = 10 } else { - finalityDepth := setupOutput.Cfg.SelectedNetworks[0].FinalityDepth - if finalityDepth > math.MaxInt { - t.Fatalf("source finality depth overflows int: %d", finalityDepth) - } - finalitySrc = int(finalityDepth) + finalitySrc = setupOutput.Cfg.SelectedNetworks[0].FinalityDepth } if setupOutput.Cfg.SelectedNetworks[1].FinalityTag { finalityDst = 10 } else { - finalityDepth := setupOutput.Cfg.SelectedNetworks[1].FinalityDepth - if finalityDepth > math.MaxInt { - t.Fatalf("destination finality depth overflows int: %d", finalityDepth) - } - finalityDst = int(finalityDepth) + finalityDst = setupOutput.Cfg.SelectedNetworks[1].FinalityDepth } var srcGethHTTPURL, dstGethHTTPURL string if setupOutput.Env.LocalCluster != nil { diff --git a/integration-tests/ccip-tests/testconfig/README.md b/integration-tests/ccip-tests/testconfig/README.md index d614ed62ea4..ff57ecaa220 100644 --- a/integration-tests/ccip-tests/testconfig/README.md +++ b/integration-tests/ccip-tests/testconfig/README.md @@ -430,6 +430,32 @@ Example usage: TTL = "11h" ``` +### CCIP.Env.Logging + +Specifies the logging configuration for the test. Imported from [LoggingConfig](https://github.com/smartcontractkit/chainlink-testing-framework/blob/main/config/logging.go#L11) in chainlink-testing-framework. +Example usage: + +```toml +[CCIP.Env.Logging] +test_log_collect = false # if set to true will save logs even if test did not fail + +[CCIP.Env.Logging.LogStream] +# supported targets: file, loki, in-memory. if empty no logs will be persistet +log_targets = ["file"] +# context timeout for starting log producer and also time-frame for requesting logs +log_producer_timeout = "10s" +# number of retries before log producer gives up and stops listening to logs +log_producer_retry_limit = 10 + +[CCIP.Env.Logging.Loki] +tenant_id = "..." +endpoint = "https://loki...." + +[CCIP.Env.Logging.Grafana] +base_url = "https://grafana..../" +dashboard_url = "/d/6vjVx-1V8/ccip-long-running-tests" +``` + ### CCIP.Env.Lane.LeaderLaneEnabled Specifies whether to enable the leader lane feature. This setting is only applicable for new deployments. diff --git a/integration-tests/ccip-tests/testconfig/global.go b/integration-tests/ccip-tests/testconfig/global.go index 8866d31705a..725b1e90a4f 100644 --- a/integration-tests/ccip-tests/testconfig/global.go +++ b/integration-tests/ccip-tests/testconfig/global.go @@ -175,6 +175,120 @@ type Common struct { func (p *Common) ReadFromEnvVar() error { logger := logging.GetTestLogger(nil) + testLogCollect := ctfconfig.MustReadEnvVar_Boolean(ctfconfig.E2E_TEST_LOG_COLLECT_ENV) + if testLogCollect != nil { + if p.Logging == nil { + p.Logging = &ctfconfig.LoggingConfig{} + } + logger.Debug().Msgf("Using %s env var to override Logging.TestLogCollect", ctfconfig.E2E_TEST_LOG_COLLECT_ENV) + p.Logging.TestLogCollect = testLogCollect + } + + loggingRunID := ctfconfig.MustReadEnvVar_String(ctfconfig.E2E_TEST_LOGGING_RUN_ID_ENV) + if loggingRunID != "" { + if p.Logging == nil { + p.Logging = &ctfconfig.LoggingConfig{} + } + logger.Debug().Msgf("Using %s env var to override Logging.RunID", ctfconfig.E2E_TEST_LOGGING_RUN_ID_ENV) + p.Logging.RunId = &loggingRunID + } + + logstreamLogTargets := ctfconfig.MustReadEnvVar_Strings(ctfconfig.E2E_TEST_LOG_STREAM_LOG_TARGETS_ENV, ",") + if len(logstreamLogTargets) > 0 { + if p.Logging == nil { + p.Logging = &ctfconfig.LoggingConfig{} + } + if p.Logging.LogStream == nil { + p.Logging.LogStream = &ctfconfig.LogStreamConfig{} + } + logger.Debug().Msgf("Using %s env var to override Logging.LogStream.LogTargets", ctfconfig.E2E_TEST_LOG_STREAM_LOG_TARGETS_ENV) + p.Logging.LogStream.LogTargets = logstreamLogTargets + } + + lokiTenantID := ctfconfig.MustReadEnvVar_String(ctfconfig.E2E_TEST_LOKI_TENANT_ID_ENV) + if lokiTenantID != "" { + if p.Logging == nil { + p.Logging = &ctfconfig.LoggingConfig{} + } + if p.Logging.Loki == nil { + p.Logging.Loki = &ctfconfig.LokiConfig{} + } + logger.Debug().Msgf("Using %s env var to override Logging.Loki.TenantId", ctfconfig.E2E_TEST_LOKI_TENANT_ID_ENV) + p.Logging.Loki.TenantId = &lokiTenantID + } + + lokiEndpoint := ctfconfig.MustReadEnvVar_String(ctfconfig.E2E_TEST_LOKI_ENDPOINT_ENV) + if lokiEndpoint != "" { + if p.Logging == nil { + p.Logging = &ctfconfig.LoggingConfig{} + } + if p.Logging.Loki == nil { + p.Logging.Loki = &ctfconfig.LokiConfig{} + } + logger.Debug().Msgf("Using %s env var to override Logging.Loki.Endpoint", ctfconfig.E2E_TEST_LOKI_ENDPOINT_ENV) + p.Logging.Loki.Endpoint = &lokiEndpoint + } + + lokiBasicAuth := ctfconfig.MustReadEnvVar_String(ctfconfig.E2E_TEST_LOKI_BASIC_AUTH_ENV) + if lokiBasicAuth != "" { + if p.Logging == nil { + p.Logging = &ctfconfig.LoggingConfig{} + } + if p.Logging.Loki == nil { + p.Logging.Loki = &ctfconfig.LokiConfig{} + } + logger.Debug().Msgf("Using %s env var to override Logging.Loki.BasicAuth", ctfconfig.E2E_TEST_LOKI_BASIC_AUTH_ENV) + p.Logging.Loki.BasicAuth = &lokiBasicAuth + } + + lokiBearerToken := ctfconfig.MustReadEnvVar_String(ctfconfig.E2E_TEST_LOKI_BEARER_TOKEN_ENV) + if lokiBearerToken != "" { + if p.Logging == nil { + p.Logging = &ctfconfig.LoggingConfig{} + } + if p.Logging.Loki == nil { + p.Logging.Loki = &ctfconfig.LokiConfig{} + } + logger.Debug().Msgf("Using %s env var to override Logging.Loki.BearerToken", ctfconfig.E2E_TEST_LOKI_BEARER_TOKEN_ENV) + p.Logging.Loki.BearerToken = &lokiBearerToken + } + + grafanaBaseUrl := ctfconfig.MustReadEnvVar_String(ctfconfig.E2E_TEST_GRAFANA_BASE_URL_ENV) + if grafanaBaseUrl != "" { + if p.Logging == nil { + p.Logging = &ctfconfig.LoggingConfig{} + } + if p.Logging.Grafana == nil { + p.Logging.Grafana = &ctfconfig.GrafanaConfig{} + } + logger.Debug().Msgf("Using %s env var to override Logging.Grafana.BaseUrl", ctfconfig.E2E_TEST_GRAFANA_BASE_URL_ENV) + p.Logging.Grafana.BaseUrl = &grafanaBaseUrl + } + + grafanaDashboardUrl := ctfconfig.MustReadEnvVar_String(ctfconfig.E2E_TEST_GRAFANA_DASHBOARD_URL_ENV) + if grafanaDashboardUrl != "" { + if p.Logging == nil { + p.Logging = &ctfconfig.LoggingConfig{} + } + if p.Logging.Grafana == nil { + p.Logging.Grafana = &ctfconfig.GrafanaConfig{} + } + logger.Debug().Msgf("Using %s env var to override Logging.Grafana.DashboardUrl", ctfconfig.E2E_TEST_GRAFANA_DASHBOARD_URL_ENV) + p.Logging.Grafana.DashboardUrl = &grafanaDashboardUrl + } + + grafanaBearerToken := ctfconfig.MustReadEnvVar_String(ctfconfig.E2E_TEST_GRAFANA_BEARER_TOKEN_ENV) + if grafanaBearerToken != "" { + if p.Logging == nil { + p.Logging = &ctfconfig.LoggingConfig{} + } + if p.Logging.Grafana == nil { + p.Logging.Grafana = &ctfconfig.GrafanaConfig{} + } + logger.Debug().Msgf("Using %s env var to override Logging.Grafana.BearerToken", ctfconfig.E2E_TEST_GRAFANA_BEARER_TOKEN_ENV) + p.Logging.Grafana.BearerToken = &grafanaBearerToken + } + selectedNetworks := ctfconfig.MustReadEnvVar_Strings(ctfconfig.E2E_TEST_SELECTED_NETWORK_ENV, ",") if len(selectedNetworks) > 0 { if p.Network == nil { @@ -307,6 +421,9 @@ func (p *Common) GetSethConfig() *seth.Config { } func (p *Common) Validate() error { + if err := p.Logging.Validate(); err != nil { + return fmt.Errorf("error validating logging config %w", err) + } if p.Network == nil { return errors.New("no networks specified") } @@ -467,7 +584,7 @@ func (c *ChainlinkDeployment) Validate() error { if c.NoOfNodes == nil { return errors.New("chainlink config is invalid, NoOfNodes should be specified") } - if len(c.Nodes) > 0 { + if c.Nodes != nil && len(c.Nodes) > 0 { noOfNodes := pointer.GetInt(c.NoOfNodes) if noOfNodes != len(c.Nodes) { return errors.New("chainlink config is invalid, NoOfNodes and Nodes length mismatch") diff --git a/integration-tests/ccip-tests/testconfig/tomls/ccip-default.toml b/integration-tests/ccip-tests/testconfig/tomls/ccip-default.toml index 89858a94ddb..b03f03a6dab 100644 --- a/integration-tests/ccip-tests/testconfig/tomls/ccip-default.toml +++ b/integration-tests/ccip-tests/testconfig/tomls/ccip-default.toml @@ -73,6 +73,17 @@ addresses_to_fund = [ [CCIP.Env.PrivateEthereumNetworks.SIMULATED_2.EthereumChainConfig.HardForkEpochs] Deneb = 500 +[CCIP.Env.Logging] +test_log_collect = false # if set to true will save logs even if test did not fail + +[CCIP.Env.Logging.LogStream] +# supported targets: file, loki, in-memory. if empty no logs will be persistet +log_targets = ["file"] +# context timeout for starting log producer and also time-frame for requesting logs +log_producer_timeout = "10s" +# number of retries before log producer gives up and stops listening to logs +log_producer_retry_limit = 10 + # these values will be used to set up chainlink DON # along with these values, the secrets needs to be specified as part of .env variables # @@ -97,7 +108,7 @@ DBArgs = [ [CCIP.Env.NewCLCluster.Common] Name = 'node1' # name of the chainlink node, used as prefix for all the chainlink node names , used for k8s deployment DBImage = 'postgres' # postgresql database image to be used for k8s deployment -DBTag = '12.0' # postgresql database image tag to be used for k8s deployment +DBTag = '13.12' # postgresql database image tag to be used for k8s deployment # override config toml file for chainlink nodes BaseConfigTOML = """ [Feature] diff --git a/integration-tests/ccip-tests/testconfig/tomls/contract-version1.4.toml b/integration-tests/ccip-tests/testconfig/tomls/contract-version1.4.toml new file mode 100644 index 00000000000..392b058e5c8 --- /dev/null +++ b/integration-tests/ccip-tests/testconfig/tomls/contract-version1.4.toml @@ -0,0 +1,13 @@ +[CCIP] +[CCIP.ContractVersions] +PriceRegistry = '1.2.0' +OffRamp = '1.2.0' +OnRamp = '1.2.0' +TokenPool = '1.4.0' +CommitStore = '1.2.0' + +[CCIP.Groups.smoke.TokenConfig] +CCIPOwnerTokens = true + +[CCIP.Groups.load.TokenConfig] +CCIPOwnerTokens = true \ No newline at end of file diff --git a/integration-tests/ccip-tests/testsetups/ccip.go b/integration-tests/ccip-tests/testsetups/ccip.go index fbfbc4c1ccd..eee424d50d1 100644 --- a/integration-tests/ccip-tests/testsetups/ccip.go +++ b/integration-tests/ccip-tests/testsetups/ccip.go @@ -3,7 +3,6 @@ package testsetups import ( "context" "fmt" - "math" "math/big" "math/rand" "os" @@ -37,7 +36,6 @@ import ( "github.com/smartcontractkit/chainlink-testing-framework/lib/k8s/environment" "github.com/smartcontractkit/chainlink-testing-framework/lib/networks" "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/testcontext" - tc "github.com/smartcontractkit/chainlink/integration-tests/testconfig" integrationactions "github.com/smartcontractkit/chainlink/integration-tests/actions" "github.com/smartcontractkit/chainlink/integration-tests/ccip-tests/actions" @@ -236,9 +234,6 @@ func (c *CCIPTestConfig) SetNetworkPairs(lggr zerolog.Logger) error { var chainIDs []int64 existingChainIDs := make(map[uint64]struct{}) for _, net := range c.SelectedNetworks { - if net.ChainID < 0 { - return fmt.Errorf("negative chain ID: %d", net.ChainID) - } existingChainIDs[uint64(net.ChainID)] = struct{}{} } for _, id := range chainselectors.TestChainIds() { @@ -246,9 +241,6 @@ func (c *CCIPTestConfig) SetNetworkPairs(lggr zerolog.Logger) error { if _, exists := existingChainIDs[id]; exists { continue } - if id > math.MaxInt64 { - return fmt.Errorf("chain ID overflows int64: %d", id) - } chainIDs = append(chainIDs, int64(id)) } for i := 0; i < c.TestGroupInput.NoOfNetworks-actualNoOfNetworks; i++ { @@ -308,7 +300,7 @@ func (c *CCIPTestConfig) SetNetworkPairs(lggr zerolog.Logger) error { var newNetworkPairs []NetworkPair denselyConnectedNetworks := make(map[string]struct{}) // if densely connected networks are provided, choose all the network pairs containing the networks mentioned in the list for DenselyConnectedNetworkChainIds - if len(c.TestGroupInput.DenselyConnectedNetworkChainIds) > 0 { + if c.TestGroupInput.DenselyConnectedNetworkChainIds != nil && len(c.TestGroupInput.DenselyConnectedNetworkChainIds) > 0 { for _, n := range c.TestGroupInput.DenselyConnectedNetworkChainIds { denselyConnectedNetworks[n] = struct{}{} } @@ -1154,7 +1146,7 @@ func CCIPDefaultTestSetUp( // if it's a new USDC deployment, set up mock server for attestation, // we need to set it only once for all the lanes as the attestation path uses regex to match the path for // all messages across all lanes - err = actions.SetMockServerWithUSDCAttestation(killgrave, setUpArgs.Env.MockServer, false) + err = actions.SetMockServerWithUSDCAttestation(killgrave, setUpArgs.Env.MockServer) require.NoError(t, err, "failed to set up mock server for attestation") } } @@ -1415,19 +1407,9 @@ func (o *CCIPTestSetUpOutputs) CreateEnvironment( } func createEnvironmentConfig(t *testing.T, envName string, testConfig *CCIPTestConfig, reportPath string) *environment.Config { - testType := testConfig.TestGroupInput.Type - nsLabels, err := environment.GetRequiredChainLinkNamespaceLabels(string(tc.CCIP), testType) - require.NoError(t, err, "Error creating required chain.link labels for namespace") - - workloadPodLabels, err := environment.GetRequiredChainLinkWorkloadAndPodLabels(string(tc.CCIP), testType) - require.NoError(t, err, "Error creating required chain.link labels for workloads and pods") - envConfig := &environment.Config{ NamespacePrefix: envName, Test: t, - Labels: nsLabels, - WorkloadLabels: workloadPodLabels, - PodLabels: workloadPodLabels, // PreventPodEviction: true, //TODO: enable this once we have a way to handle pod eviction } if pointer.GetBool(testConfig.TestGroupInput.StoreLaneConfig) { diff --git a/integration-tests/ccip-tests/testsetups/test_env.go b/integration-tests/ccip-tests/testsetups/test_env.go index 3c3406a3e5a..263d291453d 100644 --- a/integration-tests/ccip-tests/testsetups/test_env.go +++ b/integration-tests/ccip-tests/testsetups/test_env.go @@ -352,6 +352,7 @@ func DeployLocalCluster( pointer.GetString(clNode.ChainlinkImage.Image), pointer.GetString(clNode.ChainlinkImage.Version), toml, + env.LogStream, test_env.WithPgDBOptions( ctftestenv.WithPostgresImageName(clNode.DBImage), ctftestenv.WithPostgresImageVersion(clNode.DBTag), @@ -380,6 +381,7 @@ func DeployLocalCluster( pointer.GetString(testInputs.EnvInput.NewCLCluster.Common.ChainlinkImage.Image), pointer.GetString(testInputs.EnvInput.NewCLCluster.Common.ChainlinkImage.Version), toml, + env.LogStream, test_env.WithPgDBOptions( ctftestenv.WithPostgresImageName(testInputs.EnvInput.NewCLCluster.Common.DBImage), ctftestenv.WithPostgresImageVersion(testInputs.EnvInput.NewCLCluster.Common.DBTag), diff --git a/integration-tests/testsetups/ccip/test_helpers.go b/integration-tests/ccip-tests/testsetups/test_helpers.go similarity index 53% rename from integration-tests/testsetups/ccip/test_helpers.go rename to integration-tests/ccip-tests/testsetups/test_helpers.go index 6725ac1df9b..246584be7d5 100644 --- a/integration-tests/testsetups/ccip/test_helpers.go +++ b/integration-tests/ccip-tests/testsetups/test_helpers.go @@ -1,210 +1,179 @@ -package ccip +package testsetups import ( - "bytes" - "context" "fmt" "math/big" "os" "strconv" "testing" - "github.com/ethereum/go-ethereum/accounts/abi/bind" chainsel "github.com/smartcontractkit/chain-selectors" - "go.uber.org/zap/zapcore" - commonconfig "github.com/smartcontractkit/chainlink-common/pkg/config" "github.com/smartcontractkit/chainlink-testing-framework/lib/blockchain" ctfconfig "github.com/smartcontractkit/chainlink-testing-framework/lib/config" ctftestenv "github.com/smartcontractkit/chainlink-testing-framework/lib/docker/test_env" "github.com/smartcontractkit/chainlink-testing-framework/lib/logging" "github.com/smartcontractkit/chainlink-testing-framework/lib/networks" - "github.com/smartcontractkit/chainlink-testing-framework/lib/testreporters" "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/conversions" "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/ptr" "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/testcontext" "github.com/smartcontractkit/chainlink-testing-framework/seth" "github.com/smartcontractkit/chainlink/deployment" - "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" - integrationnodes "github.com/smartcontractkit/chainlink/integration-tests/types/config/node" - evmcfg "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/toml" - corechainlink "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" - - "github.com/AlekSi/pointer" - "github.com/ethereum/go-ethereum/common" - "github.com/rs/zerolog" - "github.com/stretchr/testify/require" - "github.com/subosito/gotenv" - "golang.org/x/sync/errgroup" - "google.golang.org/grpc/credentials/insecure" - + ccipdeployment "github.com/smartcontractkit/chainlink/deployment/ccip" "github.com/smartcontractkit/chainlink/deployment/environment/devenv" clclient "github.com/smartcontractkit/chainlink/deployment/environment/nodeclient" "github.com/smartcontractkit/chainlink/integration-tests/actions" - ccipactions "github.com/smartcontractkit/chainlink/integration-tests/ccip-tests/actions" "github.com/smartcontractkit/chainlink/integration-tests/contracts" "github.com/smartcontractkit/chainlink/integration-tests/docker/test_env" + "github.com/smartcontractkit/chainlink/integration-tests/testconfig" tc "github.com/smartcontractkit/chainlink/integration-tests/testconfig" "github.com/smartcontractkit/chainlink/integration-tests/utils" "github.com/smartcontractkit/chainlink/v2/core/logger" + "github.com/smartcontractkit/chainlink/v2/core/services/relay" + + "github.com/AlekSi/pointer" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/crypto" + "github.com/rs/zerolog" + "github.com/stretchr/testify/require" + "github.com/subosito/gotenv" + "golang.org/x/sync/errgroup" + "google.golang.org/grpc/credentials/insecure" ) // DeployedLocalDevEnvironment is a helper struct for setting up a local dev environment with docker type DeployedLocalDevEnvironment struct { - changeset.DeployedEnv - testEnv *test_env.CLClusterTestEnv - DON *devenv.DON - devEnvTestCfg tc.TestConfig - devEnvCfg *devenv.EnvironmentConfig + ccipdeployment.DeployedEnv + testEnv *test_env.CLClusterTestEnv + DON *devenv.DON +} + +func (d DeployedLocalDevEnvironment) RestartChainlinkNodes(t *testing.T) error { + errGrp := errgroup.Group{} + for _, n := range d.testEnv.ClCluster.Nodes { + n := n + errGrp.Go(func() error { + if err := n.Container.Terminate(testcontext.Get(t)); err != nil { + return err + } + err := n.RestartContainer() + if err != nil { + return err + } + return nil + }) + + } + return errGrp.Wait() } -func (l *DeployedLocalDevEnvironment) DeployedEnvironment() changeset.DeployedEnv { - return l.DeployedEnv +func NewLocalDevEnvironmentWithDefaultPrice( + t *testing.T, + lggr logger.Logger) (ccipdeployment.DeployedEnv, *test_env.CLClusterTestEnv, testconfig.TestConfig) { + return NewLocalDevEnvironment(t, lggr, ccipdeployment.MockLinkPrice, ccipdeployment.MockWethPrice) } -func (l *DeployedLocalDevEnvironment) StartChains(t *testing.T, _ *changeset.TestConfigs) { - lggr := logger.TestLogger(t) +func NewLocalDevEnvironment( + t *testing.T, + lggr logger.Logger, + linkPrice, wethPrice *big.Int) (ccipdeployment.DeployedEnv, *test_env.CLClusterTestEnv, testconfig.TestConfig) { ctx := testcontext.Get(t) + // create a local docker environment with simulated chains and job-distributor + // we cannot create the chainlink nodes yet as we need to deploy the capability registry first envConfig, testEnv, cfg := CreateDockerEnv(t) - l.devEnvTestCfg = cfg - l.testEnv = testEnv - l.devEnvCfg = envConfig - users := make(map[uint64][]*bind.TransactOpts) - for _, chain := range envConfig.Chains { - details, found := chainsel.ChainByEvmChainID(chain.ChainID) - require.Truef(t, found, "chain not found") - users[details.Selector] = chain.Users - } - homeChainSel := l.devEnvTestCfg.CCIP.GetHomeChainSelector() - require.NotEmpty(t, homeChainSel, "homeChainSel should not be empty") - feedSel := l.devEnvTestCfg.CCIP.GetFeedChainSelector() - require.NotEmpty(t, feedSel, "feedSel should not be empty") + require.NotNil(t, envConfig) + require.NotEmpty(t, envConfig.Chains, "chainConfigs should not be empty") + require.NotEmpty(t, envConfig.JDConfig, "jdUrl should not be empty") chains, err := devenv.NewChains(lggr, envConfig.Chains) require.NoError(t, err) - replayBlocks, err := changeset.LatestBlocksByChain(ctx, chains) + // locate the home chain + homeChainSel := envConfig.HomeChainSelector + require.NotEmpty(t, homeChainSel, "homeChainSel should not be empty") + feedSel := envConfig.FeedChainSelector + require.NotEmpty(t, feedSel, "feedSel should not be empty") + replayBlocks, err := ccipdeployment.LatestBlocksByChain(ctx, chains) require.NoError(t, err) - l.DeployedEnv.Users = users - l.DeployedEnv.Env.Chains = chains - l.DeployedEnv.FeedChainSel = feedSel - l.DeployedEnv.HomeChainSel = homeChainSel - l.DeployedEnv.ReplayBlocks = replayBlocks -} -func (l *DeployedLocalDevEnvironment) StartNodes(t *testing.T, _ *changeset.TestConfigs, crConfig deployment.CapabilityRegistryConfig) { - require.NotNil(t, l.testEnv, "docker env is empty, start chains first") - require.NotEmpty(t, l.devEnvTestCfg, "integration test config is empty, start chains first") - require.NotNil(t, l.devEnvCfg, "dev environment config is empty, start chains first") - err := StartChainlinkNodes(t, l.devEnvCfg, + ab := deployment.NewMemoryAddressBook() + crConfig := ccipdeployment.DeployTestContracts(t, lggr, ab, homeChainSel, feedSel, chains, linkPrice, wethPrice) + + // start the chainlink nodes with the CR address + err = StartChainlinkNodes(t, envConfig, crConfig, - l.testEnv, l.devEnvTestCfg) + testEnv, cfg) require.NoError(t, err) - ctx := testcontext.Get(t) - lggr := logger.TestLogger(t) - e, don, err := devenv.NewEnvironment(func() context.Context { return ctx }, lggr, *l.devEnvCfg) + e, don, err := devenv.NewEnvironment(ctx, lggr, *envConfig) require.NoError(t, err) require.NotNil(t, e) - l.DON = don - l.DeployedEnv.Env = *e + e.ExistingAddresses = ab + e.MockAdapter = testEnv.MockAdapter - // fund the nodes + envNodes, err := deployment.NodeInfo(e.NodeIDs, e.Offchain) + require.NoError(t, err) + _, err = ccipdeployment.DeployHomeChain(lggr, *e, e.ExistingAddresses, chains[homeChainSel], + ccipdeployment.NewTestRMNStaticConfig(), + ccipdeployment.NewTestRMNDynamicConfig(), + ccipdeployment.NewTestNodeOperator(chains[homeChainSel].DeployerKey.From), + map[string][][32]byte{ + "NodeOperator": envNodes.NonBootstraps().PeerIDs(), + }, + ) + require.NoError(t, err) zeroLogLggr := logging.GetTestLogger(t) - FundNodes(t, zeroLogLggr, l.testEnv, l.devEnvTestCfg, don.PluginNodes()) + // fund the nodes + FundNodes(t, zeroLogLggr, testEnv, cfg, don.PluginNodes()) + + return ccipdeployment.DeployedEnv{ + Env: *e, + HomeChainSel: homeChainSel, + FeedChainSel: feedSel, + ReplayBlocks: replayBlocks, + }, testEnv, cfg } -func (l *DeployedLocalDevEnvironment) MockUSDCAttestationServer(t *testing.T, isUSDCAttestationMissing bool) string { - err := ccipactions.SetMockServerWithUSDCAttestation(l.testEnv.MockAdapter, nil, isUSDCAttestationMissing) +func NewLocalDevEnvironmentWithRMN( + t *testing.T, + lggr logger.Logger, + numRmnNodes int, +) (ccipdeployment.DeployedEnv, devenv.RMNCluster) { + tenv, dockerenv, _ := NewLocalDevEnvironmentWithDefaultPrice(t, lggr) + state, err := ccipdeployment.LoadOnchainState(tenv.Env) require.NoError(t, err) - return l.testEnv.MockAdapter.InternalEndpoint -} - -func (l *DeployedLocalDevEnvironment) RestartChainlinkNodes(t *testing.T) error { - errGrp := errgroup.Group{} - for _, n := range l.testEnv.ClCluster.Nodes { - n := n - errGrp.Go(func() error { - if err := n.Container.Terminate(testcontext.Get(t)); err != nil { - return err - } - err := n.RestartContainer() - if err != nil { - return err - } - return nil - }) - - } - return errGrp.Wait() -} -// NewIntegrationEnvironment creates a new integration test environment based on the provided test config -// It can create a memory environment or a docker environment based on env var CCIP_V16_TEST_ENV -// By default, it creates a memory environment if env var CCIP_V16_TEST_ENV is not set -// if CCIP_V16_TEST_ENV is set to 'docker', it creates a docker environment with test config provided under testconfig/ccip/ccip.toml -// It also creates a RMN cluster if the test config has RMN enabled -// It returns the deployed environment and RMN cluster ( in case of RMN enabled) -func NewIntegrationEnvironment(t *testing.T, opts ...changeset.TestOps) (changeset.DeployedEnv, devenv.RMNCluster) { - testCfg := changeset.DefaultTestConfigs() - for _, opt := range opts { - opt(testCfg) - } - // check for EnvType env var - testCfg.MustSetEnvTypeOrDefault(t) - require.NoError(t, testCfg.Validate(), "invalid test config") - switch testCfg.Type { - case changeset.Memory: - memEnv := changeset.NewMemoryEnvironment(t, opts...) - return memEnv, devenv.RMNCluster{} - case changeset.Docker: - dockerEnv := &DeployedLocalDevEnvironment{} - if testCfg.LegacyDeployment { - deployedEnv := changeset.NewLegacyEnvironment(t, testCfg, dockerEnv) - require.NotNil(t, dockerEnv.testEnv, "empty docker environment") - return deployedEnv, devenv.RMNCluster{} - } - if testCfg.RMNEnabled { - deployedEnv := changeset.NewEnvironmentWithJobsAndContracts(t, testCfg, dockerEnv) - l := logging.GetTestLogger(t) - require.NotNil(t, dockerEnv.testEnv, "empty docker environment") - config := GenerateTestRMNConfig(t, testCfg.NumOfRMNNodes, deployedEnv, MustNetworksToRPCMap(dockerEnv.testEnv.EVMNetworks)) - require.NotNil(t, dockerEnv.devEnvTestCfg.CCIP) - rmnCluster, err := devenv.NewRMNCluster( - t, l, - []string{dockerEnv.testEnv.DockerNetwork.ID}, - config, - dockerEnv.devEnvTestCfg.CCIP.RMNConfig.GetProxyImage(), - dockerEnv.devEnvTestCfg.CCIP.RMNConfig.GetProxyVersion(), - dockerEnv.devEnvTestCfg.CCIP.RMNConfig.GetAFN2ProxyImage(), - dockerEnv.devEnvTestCfg.CCIP.RMNConfig.GetAFN2ProxyVersion(), - ) - require.NoError(t, err) - return deployedEnv, *rmnCluster - } - if testCfg.CreateJobAndContracts { - deployedEnv := changeset.NewEnvironmentWithJobsAndContracts(t, testCfg, dockerEnv) - require.NotNil(t, dockerEnv.testEnv, "empty docker environment") - return deployedEnv, devenv.RMNCluster{} - } - if testCfg.CreateJob { - deployedEnv := changeset.NewEnvironmentWithJobs(t, testCfg, dockerEnv) - require.NotNil(t, dockerEnv.testEnv, "empty docker environment") - return deployedEnv, devenv.RMNCluster{} - } - deployedEnv := changeset.NewEnvironment(t, testCfg, dockerEnv) - require.NotNil(t, dockerEnv.testEnv, "empty docker environment") - return deployedEnv, devenv.RMNCluster{} - default: - require.Failf(t, "Type %s not supported in integration tests choose between %s and %s", string(testCfg.Type), changeset.Memory, changeset.Docker) - } - return changeset.DeployedEnv{}, devenv.RMNCluster{} + // Deploy CCIP contracts. + newAddresses := deployment.NewMemoryAddressBook() + err = ccipdeployment.DeployCCIPContracts(tenv.Env, newAddresses, ccipdeployment.DeployCCIPContractConfig{ + HomeChainSel: tenv.HomeChainSel, + FeedChainSel: tenv.FeedChainSel, + ChainsToDeploy: tenv.Env.AllChainSelectors(), + TokenConfig: ccipdeployment.NewTestTokenConfig(state.Chains[tenv.FeedChainSel].USDFeeds), + MCMSConfig: ccipdeployment.NewTestMCMSConfig(t, tenv.Env), + OCRSecrets: deployment.XXXGenerateTestOCRSecrets(), + }) + require.NoError(t, err) + require.NoError(t, tenv.Env.ExistingAddresses.Merge(newAddresses)) + + l := logging.GetTestLogger(t) + config := GenerateTestRMNConfig(t, numRmnNodes, tenv, MustNetworksToRPCMap(dockerenv.EVMNetworks)) + rmnCluster, err := devenv.NewRMNCluster( + t, l, + []string{dockerenv.DockerNetwork.ID}, + config, + "rageproxy", + "latest", + "afn2proxy", + "latest", + dockerenv.LogStream, + ) + require.NoError(t, err) + return tenv, *rmnCluster } func MustNetworksToRPCMap(evmNetworks []*blockchain.EVMNetwork) map[uint64]string { rpcs := make(map[uint64]string) for _, network := range evmNetworks { - if network.ChainID < 0 { - panic(fmt.Errorf("negative chain ID: %d", network.ChainID)) - } sel, err := chainsel.SelectorFromChainId(uint64(network.ChainID)) if err != nil { panic(err) @@ -227,14 +196,14 @@ func MustCCIPNameToRMNName(a string) string { return v } -func GenerateTestRMNConfig(t *testing.T, nRMNNodes int, tenv changeset.DeployedEnv, rpcMap map[uint64]string) map[string]devenv.RMNConfig { +func GenerateTestRMNConfig(t *testing.T, nRMNNodes int, tenv ccipdeployment.DeployedEnv, rpcMap map[uint64]string) map[string]devenv.RMNConfig { // Find the bootstrappers. nodes, err := deployment.NodeInfo(tenv.Env.NodeIDs, tenv.Env.Offchain) require.NoError(t, err) bootstrappers := nodes.BootstrapLocators() // Just set all RMN nodes to support all chains. - state, err := changeset.LoadOnchainState(tenv.Env) + state, err := ccipdeployment.LoadOnchainState(tenv.Env) require.NoError(t, err) var chainParams []devenv.ChainParam var remoteChains []devenv.RemoteChains @@ -271,7 +240,7 @@ func GenerateTestRMNConfig(t *testing.T, nRMNNodes int, tenv changeset.DeployedE HomeChain: devenv.HomeChain{ Name: MustCCIPNameToRMNName(hc.Name), CapabilitiesRegistry: state.Chains[tenv.HomeChainSel].CapabilityRegistry.Address().String(), - CCIPHome: state.Chains[tenv.HomeChainSel].CCIPHome.Address().String(), + CCIPConfig: state.Chains[tenv.HomeChainSel].CCIPHome.Address().String(), RMNHome: state.Chains[tenv.HomeChainSel].RMNHome.Address().String(), }, RemoteChains: remoteChains, @@ -329,30 +298,11 @@ func CreateDockerEnv(t *testing.T) ( } } - // ignore critical CL node logs until they are fixed, as otherwise tests will fail - var logScannerSettings = test_env.GetDefaultChainlinkNodeLogScannerSettingsWithExtraAllowedMessages(testreporters.NewAllowedLogMessage( - "No live RPC nodes available", - "CL nodes are started before simulated chains, so this is expected", - zapcore.DPanicLevel, - testreporters.WarnAboutAllowedMsgs_No), - testreporters.NewAllowedLogMessage( - "Error stopping job service", - "Possible lifecycle bug in chainlink: failed to close RMN home reader: has already been stopped: already stopped", - zapcore.DPanicLevel, - testreporters.WarnAboutAllowedMsgs_No), - testreporters.NewAllowedLogMessage( - "Shutdown grace period of 5s exceeded, closing DB and exiting...", - "Possible lifecycle bug in chainlink.", - zapcore.DPanicLevel, - testreporters.WarnAboutAllowedMsgs_No), - ) - builder := test_env.NewCLTestEnvBuilder(). WithTestConfig(&cfg). WithTestInstance(t). WithMockAdapter(). WithJobDistributor(cfg.CCIP.JobDistributorConfig). - WithChainlinkNodeLogScanner(logScannerSettings). WithStandardCleanup() // if private ethereum networks are provided, we will use them to create the test environment @@ -398,9 +348,16 @@ func CreateDockerEnv(t *testing.T) ( } require.NotEmpty(t, jdConfig, "JD config is empty") + homeChainSelector, err := cfg.CCIP.GetHomeChainSelector(evmNetworks) + require.NoError(t, err, "Error getting home chain selector") + feedChainSelector, err := cfg.CCIP.GetFeedChainSelector(evmNetworks) + require.NoError(t, err, "Error getting feed chain selector") + return &devenv.EnvironmentConfig{ - Chains: chains, - JDConfig: jdConfig, + Chains: chains, + JDConfig: jdConfig, + HomeChainSelector: homeChainSelector, + FeedChainSelector: feedChainSelector, }, env, cfg } @@ -445,11 +402,10 @@ func StartChainlinkNodes( cfg.NodeConfig.CommonChainConfigTOML, cfg.NodeConfig.ChainConfigTOMLByChainID, ) - if registryConfig.Contract != (common.Address{}) { - toml.Capabilities.ExternalRegistry.NetworkID = ptr.Ptr(registryConfig.NetworkType) - toml.Capabilities.ExternalRegistry.ChainID = ptr.Ptr(strconv.FormatUint(registryConfig.EVMChainID, 10)) - toml.Capabilities.ExternalRegistry.Address = ptr.Ptr(registryConfig.Contract.String()) - } + + toml.Capabilities.ExternalRegistry.NetworkID = ptr.Ptr(relay.NetworkEVM) + toml.Capabilities.ExternalRegistry.ChainID = ptr.Ptr(strconv.FormatUint(registryConfig.EVMChainID, 10)) + toml.Capabilities.ExternalRegistry.Address = ptr.Ptr(registryConfig.Contract.String()) if err != nil { return err @@ -459,6 +415,7 @@ func StartChainlinkNodes( pointer.GetString(cfg.GetChainlinkImageConfig().Image), pointer.GetString(cfg.GetChainlinkImageConfig().Version), toml, + env.LogStream, test_env.WithPgDBOptions( ctftestenv.WithPostgresImageVersion(pointer.GetString(cfg.GetChainlinkImageConfig().PostgresVersion)), ), @@ -524,61 +481,41 @@ func FundNodes(t *testing.T, lggr zerolog.Logger, env *test_env.CLClusterTestEnv } } }) - fundGrp := errgroup.Group{} for i := range evmNetworks { - fundGrp.Go(func() error { - evmNetwork := evmNetworks[i] - sethClient, err := utils.TestAwareSethClient(t, cfg, &evmNetwork) - if err != nil { - return fmt.Errorf("error getting seth client for network %s: %w", evmNetwork.Name, err) - } - if len(sethClient.PrivateKeys) == 0 { - return fmt.Errorf(seth.ErrNoKeyLoaded) - } - privateKey := sethClient.PrivateKeys[0] - if evmNetwork.ChainID < 0 { - return fmt.Errorf("negative chain ID: %d", evmNetwork.ChainID) - } - for _, node := range nodes { - nodeAddr, ok := node.AccountAddr[uint64(evmNetwork.ChainID)] - if !ok { - return fmt.Errorf("account address not found for chain %d", evmNetwork.ChainID) - } - fromAddress, err := actions.PrivateKeyToAddress(privateKey) - if err != nil { - return fmt.Errorf("error getting address from private key: %w", err) - } - amount := big.NewFloat(pointer.GetFloat64(cfg.Common.ChainlinkNodeFunding)) - toAddr := common.HexToAddress(nodeAddr) - receipt, err := actions.SendFunds(lggr, sethClient, actions.FundsToSendPayload{ - ToAddress: toAddr, - Amount: conversions.EtherToWei(amount), - PrivateKey: privateKey, - }) - if err != nil { - return fmt.Errorf("error sending funds to node %s: %w", node.Name, err) - } - if receipt == nil { - return fmt.Errorf("receipt is nil") - } - txHash := "(none)" - if receipt != nil { - txHash = receipt.TxHash.String() - } - lggr.Info(). - Str("From", fromAddress.Hex()). - Str("To", toAddr.String()). - Str("TxHash", txHash). - Str("Amount", amount.String()). - Msg("Funded Chainlink node") + evmNetwork := evmNetworks[i] + sethClient, err := utils.TestAwareSethClient(t, cfg, &evmNetwork) + require.NoError(t, err, "Error getting seth client for network %s", evmNetwork.Name) + require.Greater(t, len(sethClient.PrivateKeys), 0, seth.ErrNoKeyLoaded) + privateKey := sethClient.PrivateKeys[0] + for _, node := range nodes { + nodeAddr, ok := node.AccountAddr[uint64(evmNetwork.ChainID)] + require.True(t, ok, "Account address not found for chain %d", evmNetwork.ChainID) + fromAddress, err := actions.PrivateKeyToAddress(privateKey) + require.NoError(t, err, "Error getting address from private key") + amount := big.NewFloat(pointer.GetFloat64(cfg.Common.ChainlinkNodeFunding)) + toAddr := common.HexToAddress(nodeAddr) + receipt, err := actions.SendFunds(lggr, sethClient, actions.FundsToSendPayload{ + ToAddress: toAddr, + Amount: conversions.EtherToWei(amount), + PrivateKey: privateKey, + }) + require.NoError(t, err, "Error sending funds to node %s", node.Name) + require.NotNil(t, receipt, "Receipt is nil") + txHash := "(none)" + if receipt != nil { + txHash = receipt.TxHash.String() } - return nil - }) + lggr.Info(). + Str("From", fromAddress.Hex()). + Str("To", toAddr.String()). + Str("TxHash", txHash). + Str("Amount", amount.String()). + Msg("Funded Chainlink node") + } } - require.NoError(t, fundGrp.Wait(), "Error funding chainlink nodes") } -// CreateChainConfigFromNetworks creates a list of CCIPOCRParams from the network config provided in test config. +// CreateChainConfigFromNetworks creates a list of ChainConfig from the network config provided in test config. // It either creates it from the private ethereum networks created by the test environment or from the // network URLs provided in the network config ( if the network is a live testnet). // It uses the private keys from the network config to create the deployer key for each chain. @@ -589,110 +526,56 @@ func CreateChainConfigFromNetworks( networkConfig *ctfconfig.NetworkConfig, ) []devenv.ChainConfig { evmNetworks := networks.MustGetSelectedNetworkConfig(networkConfig) - networkPvtKeys := make(map[uint64][]string) + networkPvtKeys := make(map[int64]string) for _, net := range evmNetworks { require.Greater(t, len(net.PrivateKeys), 0, "No private keys found for network") - if net.ChainID < 0 { - t.Fatalf("negative chain ID: %d", net.ChainID) - } - networkPvtKeys[uint64(net.ChainID)] = net.PrivateKeys - } - type chainDetails struct { - chainId uint64 - wsRPCs []string - httpRPCs []string + networkPvtKeys[net.ChainID] = net.PrivateKeys[0] } var chains []devenv.ChainConfig - var chaindetails []chainDetails + // if private ethereum networks are not provided, we will create chains from the network URLs if len(privateEthereumNetworks) == 0 { for _, net := range evmNetworks { chainId := net.ChainID - if chainId < 0 { - t.Fatalf("negative chain ID: %d", chainId) - } - chaindetails = append(chaindetails, chainDetails{ - chainId: uint64(chainId), - wsRPCs: net.URLs, - httpRPCs: net.HTTPURLs, - }) - } - } else { - for _, net := range privateEthereumNetworks { - chainId := net.EthereumChainConfig.ChainID - if chainId < 0 { - t.Fatalf("negative chain ID: %d", chainId) - } - rpcProvider, err := env.GetRpcProvider(int64(chainId)) - require.NoError(t, err, "Error getting rpc provider") - chaindetails = append(chaindetails, chainDetails{ - chainId: uint64(chainId), - wsRPCs: rpcProvider.PublicWsUrls(), - httpRPCs: rpcProvider.PublicHttpUrls(), + chainName, err := chainsel.NameFromChainId(uint64(chainId)) + require.NoError(t, err, "Error getting chain name") + pvtKeyStr, exists := networkPvtKeys[chainId] + require.Truef(t, exists, "Private key not found for chain id %d", chainId) + pvtKey, err := crypto.HexToECDSA(pvtKeyStr) + require.NoError(t, err) + deployer, err := bind.NewKeyedTransactorWithChainID(pvtKey, big.NewInt(chainId)) + require.NoError(t, err) + deployer.GasLimit = net.DefaultGasLimit + chains = append(chains, devenv.ChainConfig{ + ChainID: uint64(chainId), + ChainName: chainName, + ChainType: "EVM", + WSRPCs: net.URLs, + HTTPRPCs: net.HTTPURLs, + DeployerKey: deployer, }) } + return chains } - for _, cd := range chaindetails { - chainId := cd.chainId - chainName, err := chainsel.NameFromChainId(chainId) + for _, networkCfg := range privateEthereumNetworks { + chainId := networkCfg.EthereumChainConfig.ChainID + chainName, err := chainsel.NameFromChainId(uint64(chainId)) require.NoError(t, err, "Error getting chain name") - chainCfg := devenv.ChainConfig{ - ChainID: chainId, - ChainName: chainName, - ChainType: "EVM", - WSRPCs: cd.wsRPCs, - HTTPRPCs: cd.httpRPCs, - } - var pvtKey *string - // if private keys are provided, use the first private key as deployer key - // otherwise it will try to load the private key from KMS - if len(networkPvtKeys[chainId]) > 0 { - pvtKey = ptr.Ptr(networkPvtKeys[chainId][0]) - } - require.NoError(t, chainCfg.SetDeployerKey(pvtKey), "Error setting deployer key") - var additionalPvtKeys []string - if len(networkPvtKeys[chainId]) > 1 { - additionalPvtKeys = networkPvtKeys[chainId][1:] - } - // if no additional private keys are provided, this will set the users to default deployer key - require.NoError(t, chainCfg.SetUsers(additionalPvtKeys), "Error setting users") - chains = append(chains, chainCfg) + rpcProvider, err := env.GetRpcProvider(int64(chainId)) + require.NoError(t, err, "Error getting rpc provider") + pvtKeyStr, exists := networkPvtKeys[int64(chainId)] + require.Truef(t, exists, "Private key not found for chain id %d", chainId) + pvtKey, err := crypto.HexToECDSA(pvtKeyStr) + require.NoError(t, err) + deployer, err := bind.NewKeyedTransactorWithChainID(pvtKey, big.NewInt(int64(chainId))) + require.NoError(t, err) + chains = append(chains, devenv.ChainConfig{ + ChainID: uint64(chainId), + ChainName: chainName, + ChainType: devenv.EVMChainType, + WSRPCs: rpcProvider.PublicWsUrls(), + HTTPRPCs: rpcProvider.PublicHttpUrls(), + DeployerKey: deployer, + }) } return chains } - -func SetNodeConfig(nets []blockchain.EVMNetwork, nodeConfig, commonChain string, configByChain map[string]string) (*corechainlink.Config, string, error) { - var tomlCfg *corechainlink.Config - var err error - var commonChainConfig *evmcfg.Chain - if commonChain != "" { - err = commonconfig.DecodeTOML(bytes.NewReader([]byte(commonChain)), &commonChainConfig) - if err != nil { - return nil, "", err - } - } - configByChainMap := make(map[int64]evmcfg.Chain) - for k, v := range configByChain { - var chain evmcfg.Chain - err = commonconfig.DecodeTOML(bytes.NewReader([]byte(v)), &chain) - if err != nil { - return nil, "", err - } - chainId, err := strconv.ParseInt(k, 10, 64) - if err != nil { - return nil, "", err - } - configByChainMap[chainId] = chain - } - if nodeConfig == "" { - tomlCfg = integrationnodes.NewConfig( - integrationnodes.NewBaseConfig(), - integrationnodes.WithPrivateEVMs(nets, commonChainConfig, configByChainMap)) - } else { - tomlCfg, err = integrationnodes.NewConfigFromToml([]byte(nodeConfig), integrationnodes.WithPrivateEVMs(nets, commonChainConfig, configByChainMap)) - if err != nil { - return nil, "", err - } - } - tomlStr, err := tomlCfg.TOMLString() - return tomlCfg, tomlStr, err -} diff --git a/integration-tests/ccip-tests/types/config/node/core.go b/integration-tests/ccip-tests/types/config/node/core.go index 404719e31e1..5c9defbbb51 100644 --- a/integration-tests/ccip-tests/types/config/node/core.go +++ b/integration-tests/ccip-tests/types/config/node/core.go @@ -3,7 +3,6 @@ package node import ( "bytes" "fmt" - "math" "math/big" "github.com/smartcontractkit/chainlink-testing-framework/lib/blockchain" @@ -55,9 +54,6 @@ func WithPrivateEVMs(networks []blockchain.EVMNetwork, commonChainConfig *evmcfg } } if evmConfig.Chain.FinalityDepth == nil && network.FinalityDepth > 0 { - if network.FinalityDepth > math.MaxUint32 { - panic(fmt.Errorf("finality depth overflows uint32: %d", network.FinalityDepth)) - } evmConfig.Chain.FinalityDepth = ptr.Ptr(uint32(network.FinalityDepth)) } if evmConfig.Chain.FinalityTagEnabled == nil && network.FinalityTag { diff --git a/integration-tests/ccip-tests/utils/common.go b/integration-tests/ccip-tests/utils/common.go index f4d5ee503b1..afa8158e450 100644 --- a/integration-tests/ccip-tests/utils/common.go +++ b/integration-tests/ccip-tests/utils/common.go @@ -4,7 +4,6 @@ import ( "path/filepath" "runtime" "sync" - "testing" ) func ProjectRoot() string { @@ -12,10 +11,6 @@ func ProjectRoot() string { return filepath.Join(filepath.Dir(b), "/..") } -func SkipFlakey(t *testing.T, ticketURL string) { - t.Skip("Flakey", ticketURL) -} - // DeleteNilEntriesFromMap checks for nil entry in map, store all not-nil entries to another map and deallocates previous map // Deleting keys from a map actually does not delete the key, It just sets the corresponding value to nil. func DeleteNilEntriesFromMap(inputMap *sync.Map) *sync.Map { diff --git a/integration-tests/chaos/automation_chaos_test.go b/integration-tests/chaos/automation_chaos_test.go index 80e4a46581e..73ae7c07378 100644 --- a/integration-tests/chaos/automation_chaos_test.go +++ b/integration-tests/chaos/automation_chaos_test.go @@ -197,20 +197,11 @@ func TestAutomationChaos(t *testing.T) { t.Parallel() network := networks.MustGetSelectedNetworkConfig(config.Network)[0] // Need a new copy of the network for each test - nsLabels, err := environment.GetRequiredChainLinkNamespaceLabels(string(tc.Automation), "chaos") - require.NoError(t, err, "Error creating required chain.link labels for namespace") - - workloadPodLabels, err := environment.GetRequiredChainLinkWorkloadAndPodLabels(string(tc.Automation), "chaos") - require.NoError(t, err, "Error creating required chain.link labels for workloads and pods") - testEnvironment := environment. New(&environment.Config{ NamespacePrefix: fmt.Sprintf("chaos-automation-%s", name), TTL: time.Hour * 1, Test: t, - Labels: nsLabels, - WorkloadLabels: workloadPodLabels, - PodLabels: workloadPodLabels, }). AddHelm(testCase.networkChart). AddHelm(testCase.clChart) diff --git a/integration-tests/chaos/ocr_chaos_test.go b/integration-tests/chaos/ocr_chaos_test.go index f072adcc46a..41017d7eeb7 100644 --- a/integration-tests/chaos/ocr_chaos_test.go +++ b/integration-tests/chaos/ocr_chaos_test.go @@ -141,24 +141,15 @@ func TestOCRChaos(t *testing.T) { t.Run(fmt.Sprintf("OCR_%s", name), func(t *testing.T) { t.Parallel() - nsLabels, err := environment.GetRequiredChainLinkNamespaceLabels("data-feedsv1.0", "chaos") - require.NoError(t, err, "Error creating required chain.link labels for namespace") - - workloadPodLabels, err := environment.GetRequiredChainLinkWorkloadAndPodLabels("data-feedsv1.0", "chaos") - require.NoError(t, err, "Error creating required chain.link labels for workloads and pods") - testEnvironment := environment.New(&environment.Config{ NamespacePrefix: fmt.Sprintf("chaos-ocr-%s", name), Test: t, - Labels: nsLabels, - WorkloadLabels: workloadPodLabels, - PodLabels: workloadPodLabels, }). AddHelm(mockservercfg.New(nil)). AddHelm(mockserver.New(nil)). AddHelm(testCase.networkChart). AddHelm(testCase.clChart) - err = testEnvironment.Run() + err := testEnvironment.Run() require.NoError(t, err) if testEnvironment.WillUseRemoteRunner() { return diff --git a/integration-tests/contracts/ccipreader_test.go b/integration-tests/contracts/ccipreader_test.go deleted file mode 100644 index f46a680c8a0..00000000000 --- a/integration-tests/contracts/ccipreader_test.go +++ /dev/null @@ -1,1576 +0,0 @@ -package contracts - -import ( - "context" - "fmt" - "math/big" - "sort" - "testing" - "time" - - "github.com/ethereum/go-ethereum/accounts/abi/bind" - "github.com/ethereum/go-ethereum/common" - ethtypes "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/crypto" - "github.com/ethereum/go-ethereum/ethclient/simulated" - "github.com/jmoiron/sqlx" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - "go.uber.org/zap/zapcore" - - "github.com/smartcontractkit/chainlink/v2/core/utils/testutils/heavyweight" - - "github.com/smartcontractkit/chainlink-ccip/plugintypes" - - "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" - "github.com/smartcontractkit/chainlink/deployment/environment/memory" - "github.com/smartcontractkit/chainlink/integration-tests/utils/pgtest" - - readermocks "github.com/smartcontractkit/chainlink-ccip/mocks/pkg/contractreader" - - ubig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" - - cciptypes "github.com/smartcontractkit/chainlink-ccip/pkg/types/ccipocr3" - - "github.com/smartcontractkit/chainlink-common/pkg/types" - "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" - - evmconfig "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/configs/evm" - "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" - "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" - "github.com/smartcontractkit/chainlink/v2/core/chains/evm/headtracker" - "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller" - "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/ccip_reader_tester" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/fee_quoter" - "github.com/smartcontractkit/chainlink/v2/core/logger" - "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm" - evmtypes "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/types" - - "github.com/smartcontractkit/chainlink-ccip/pkg/consts" - "github.com/smartcontractkit/chainlink-ccip/pkg/contractreader" - ccipreaderpkg "github.com/smartcontractkit/chainlink-ccip/pkg/reader" - - evmchaintypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/offramp" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/onramp" -) - -const ( - chainS1 = cciptypes.ChainSelector(1) - chainS2 = cciptypes.ChainSelector(2) - chainS3 = cciptypes.ChainSelector(3) - chainD = cciptypes.ChainSelector(4) -) - -var ( - defaultGasPrice = assets.GWei(10) -) - -var ( - onrampABI = evmchaintypes.MustGetABI(onramp.OnRampABI) - offrampABI = evmchaintypes.MustGetABI(offramp.OffRampABI) -) - -func setupGetCommitGTETimestampTest(ctx context.Context, t testing.TB, finalityDepth int64, useHeavyDB bool) (*testSetupData, int64, common.Address) { - sb, auth := setupSimulatedBackendAndAuth(t) - onRampAddress := utils.RandomAddress() - s := testSetup(ctx, t, testSetupParams{ - ReaderChain: chainD, - DestChain: chainD, - OnChainSeqNums: nil, - Cfg: evmconfig.DestReaderConfig, - ToMockBindings: map[cciptypes.ChainSelector][]types.BoundContract{ - chainS1: { - { - Address: onRampAddress.Hex(), - Name: consts.ContractNameOnRamp, - }, - }, - }, - BindTester: true, - ContractNameToBind: consts.ContractNameOffRamp, - SimulatedBackend: sb, - Auth: auth, - FinalityDepth: finalityDepth, - UseHeavyDB: useHeavyDB, - }) - - return s, finalityDepth, onRampAddress -} - -func setupExecutedMessageRangesTest(ctx context.Context, t testing.TB, useHeavyDB bool) *testSetupData { - sb, auth := setupSimulatedBackendAndAuth(t) - return testSetup(ctx, t, testSetupParams{ - ReaderChain: chainD, - DestChain: chainD, - OnChainSeqNums: nil, - Cfg: evmconfig.DestReaderConfig, - // Cfg: cfg, - ToBindContracts: nil, - ToMockBindings: nil, - BindTester: true, - ContractNameToBind: consts.ContractNameOffRamp, - SimulatedBackend: sb, - Auth: auth, - UseHeavyDB: useHeavyDB, - }) -} - -func setupMsgsBetweenSeqNumsTest(ctx context.Context, t testing.TB, useHeavyDB bool) *testSetupData { - sb, auth := setupSimulatedBackendAndAuth(t) - return testSetup(ctx, t, testSetupParams{ - ReaderChain: chainS1, - DestChain: chainD, - OnChainSeqNums: nil, - Cfg: evmconfig.SourceReaderConfig, - ToBindContracts: nil, - ToMockBindings: nil, - BindTester: true, - ContractNameToBind: consts.ContractNameOnRamp, - SimulatedBackend: sb, - Auth: auth, - UseHeavyDB: useHeavyDB, - }) -} - -func emitCommitReports(ctx context.Context, t *testing.T, s *testSetupData, numReports int, tokenA common.Address, onRampAddress common.Address) uint64 { - var firstReportTs uint64 - for i := uint8(0); int(i) < numReports; i++ { - _, err := s.contract.EmitCommitReportAccepted(s.auth, ccip_reader_tester.OffRampCommitReport{ - PriceUpdates: ccip_reader_tester.InternalPriceUpdates{ - TokenPriceUpdates: []ccip_reader_tester.InternalTokenPriceUpdate{ - { - SourceToken: tokenA, - UsdPerToken: big.NewInt(1000), - }, - }, - GasPriceUpdates: []ccip_reader_tester.InternalGasPriceUpdate{ - { - DestChainSelector: uint64(chainD), - UsdPerUnitGas: big.NewInt(90), - }, - }, - }, - MerkleRoots: []ccip_reader_tester.InternalMerkleRoot{ - { - SourceChainSelector: uint64(chainS1), - MinSeqNr: 10, - MaxSeqNr: 20, - MerkleRoot: [32]byte{i + 1}, - OnRampAddress: common.LeftPadBytes(onRampAddress.Bytes(), 32), - }, - }, - RmnSignatures: []ccip_reader_tester.IRMNRemoteSignature{ - { - R: [32]byte{1}, - S: [32]byte{2}, - }, - { - R: [32]byte{3}, - S: [32]byte{4}, - }, - }, - }) - require.NoError(t, err) - bh := s.sb.Commit() - b, err := s.sb.Client().BlockByHash(ctx, bh) - require.NoError(t, err) - if firstReportTs == 0 { - firstReportTs = b.Time() - } - } - return firstReportTs -} - -func TestCCIPReader_GetOffRampConfigDigest(t *testing.T) { - t.Parallel() - ctx := tests.Context(t) - sb, auth := setupSimulatedBackendAndAuth(t) - - addr, _, _, err := offramp.DeployOffRamp(auth, sb.Client(), offramp.OffRampStaticConfig{ - ChainSelector: uint64(chainD), - GasForCallExactCheck: 5_000, - RmnRemote: utils.RandomAddress(), - TokenAdminRegistry: utils.RandomAddress(), - NonceManager: utils.RandomAddress(), - }, offramp.OffRampDynamicConfig{ - FeeQuoter: utils.RandomAddress(), - PermissionLessExecutionThresholdSeconds: 1, - IsRMNVerificationDisabled: true, - MessageInterceptor: utils.RandomAddress(), - }, []offramp.OffRampSourceChainConfigArgs{}) - require.NoError(t, err) - sb.Commit() - - offRamp, err := offramp.NewOffRamp(addr, sb.Client()) - require.NoError(t, err) - - commitConfigDigest := utils.RandomBytes32() - execConfigDigest := utils.RandomBytes32() - - _, err = offRamp.SetOCR3Configs(auth, []offramp.MultiOCR3BaseOCRConfigArgs{ - { - ConfigDigest: commitConfigDigest, - OcrPluginType: consts.PluginTypeCommit, - F: 1, - IsSignatureVerificationEnabled: true, - Signers: []common.Address{utils.RandomAddress(), utils.RandomAddress(), utils.RandomAddress(), utils.RandomAddress()}, - Transmitters: []common.Address{utils.RandomAddress(), utils.RandomAddress(), utils.RandomAddress(), utils.RandomAddress()}, - }, - { - ConfigDigest: execConfigDigest, - OcrPluginType: consts.PluginTypeExecute, - F: 1, - IsSignatureVerificationEnabled: false, - Signers: []common.Address{utils.RandomAddress(), utils.RandomAddress(), utils.RandomAddress(), utils.RandomAddress()}, - Transmitters: []common.Address{utils.RandomAddress(), utils.RandomAddress(), utils.RandomAddress(), utils.RandomAddress()}, - }, - }) - require.NoError(t, err) - sb.Commit() - - commitConfigDetails, err := offRamp.LatestConfigDetails(&bind.CallOpts{ - Context: ctx, - }, consts.PluginTypeCommit) - require.NoError(t, err) - require.Equal(t, commitConfigDigest, commitConfigDetails.ConfigInfo.ConfigDigest) - - execConfigDetails, err := offRamp.LatestConfigDetails(&bind.CallOpts{ - Context: ctx, - }, consts.PluginTypeExecute) - require.NoError(t, err) - require.Equal(t, execConfigDigest, execConfigDetails.ConfigInfo.ConfigDigest) - - db := pgtest.NewSqlxDB(t) - lggr := logger.TestLogger(t) - lggr.SetLogLevel(zapcore.ErrorLevel) - lpOpts := logpoller.Opts{ - PollPeriod: time.Millisecond, - FinalityDepth: 1, - BackfillBatchSize: 10, - RpcBatchSize: 10, - KeepFinalizedBlocksDepth: 100000, - } - cl := client.NewSimulatedBackendClient(t, sb, big.NewInt(1337)) - headTracker := headtracker.NewSimulatedHeadTracker(cl, lpOpts.UseFinalityTag, lpOpts.FinalityDepth) - orm := logpoller.NewORM(big.NewInt(1337), db, lggr) - lp := logpoller.NewLogPoller( - orm, - cl, - lggr, - headTracker, - lpOpts, - ) - require.NoError(t, lp.Start(ctx)) - t.Cleanup(func() { require.NoError(t, lp.Close()) }) - - cr, err := evm.NewChainReaderService(ctx, lggr, lp, headTracker, cl, evmconfig.DestReaderConfig) - require.NoError(t, err) - err = cr.Start(ctx) - require.NoError(t, err) - t.Cleanup(func() { require.NoError(t, cr.Close()) }) - - extendedCr := contractreader.NewExtendedContractReader(cr) - err = extendedCr.Bind(ctx, []types.BoundContract{ - { - Address: addr.Hex(), - Name: consts.ContractNameOffRamp, - }, - }) - require.NoError(t, err) - - reader := ccipreaderpkg.NewCCIPReaderWithExtendedContractReaders( - ctx, - lggr, - map[cciptypes.ChainSelector]contractreader.Extended{ - chainD: extendedCr, - }, - nil, - chainD, - addr.Bytes(), - ) - - ccipReaderCommitDigest, err := reader.GetOffRampConfigDigest(ctx, consts.PluginTypeCommit) - require.NoError(t, err) - require.Equal(t, commitConfigDigest, ccipReaderCommitDigest) - - ccipReaderExecDigest, err := reader.GetOffRampConfigDigest(ctx, consts.PluginTypeExecute) - require.NoError(t, err) - require.Equal(t, execConfigDigest, ccipReaderExecDigest) -} - -func TestCCIPReader_CommitReportsGTETimestamp(t *testing.T) { - t.Parallel() - ctx := tests.Context(t) - s, _, onRampAddress := setupGetCommitGTETimestampTest(ctx, t, 0, false) - - tokenA := common.HexToAddress("123") - const numReports = 5 - - firstReportTs := emitCommitReports(ctx, t, s, numReports, tokenA, onRampAddress) - - // Need to replay as sometimes the logs are not picked up by the log poller (?) - // Maybe another situation where chain reader doesn't register filters as expected. - require.NoError(t, s.lp.Replay(ctx, 1)) - - var reports []plugintypes.CommitPluginReportWithMeta - var err error - require.Eventually(t, func() bool { - reports, err = s.reader.CommitReportsGTETimestamp( - ctx, - chainD, - // Skips first report - //nolint:gosec // this won't overflow - time.Unix(int64(firstReportTs)+1, 0), - 10, - ) - require.NoError(t, err) - return len(reports) == numReports-1 - }, 30*time.Second, 50*time.Millisecond) - - assert.Len(t, reports, numReports-1) - assert.Len(t, reports[0].Report.MerkleRoots, 1) - assert.Equal(t, chainS1, reports[0].Report.MerkleRoots[0].ChainSel) - assert.Equal(t, onRampAddress.Bytes(), []byte(reports[0].Report.MerkleRoots[0].OnRampAddress)) - assert.Equal(t, cciptypes.SeqNum(10), reports[0].Report.MerkleRoots[0].SeqNumsRange.Start()) - assert.Equal(t, cciptypes.SeqNum(20), reports[0].Report.MerkleRoots[0].SeqNumsRange.End()) - assert.Equal(t, "0x0200000000000000000000000000000000000000000000000000000000000000", - reports[0].Report.MerkleRoots[0].MerkleRoot.String()) - assert.Equal(t, tokenA.String(), string(reports[0].Report.PriceUpdates.TokenPriceUpdates[0].TokenID)) - assert.Equal(t, uint64(1000), reports[0].Report.PriceUpdates.TokenPriceUpdates[0].Price.Uint64()) - assert.Equal(t, chainD, reports[0].Report.PriceUpdates.GasPriceUpdates[0].ChainSel) - assert.Equal(t, uint64(90), reports[0].Report.PriceUpdates.GasPriceUpdates[0].GasPrice.Uint64()) -} - -func TestCCIPReader_CommitReportsGTETimestamp_RespectsFinality(t *testing.T) { - t.Parallel() - ctx := tests.Context(t) - var finalityDepth int64 = 10 - s, _, onRampAddress := setupGetCommitGTETimestampTest(ctx, t, finalityDepth, false) - - tokenA := common.HexToAddress("123") - const numReports = 5 - - firstReportTs := emitCommitReports(ctx, t, s, numReports, tokenA, onRampAddress) - - // Need to replay as sometimes the logs are not picked up by the log poller (?) - // Maybe another situation where chain reader doesn't register filters as expected. - require.NoError(t, s.lp.Replay(ctx, 1)) - - var reports []plugintypes.CommitPluginReportWithMeta - var err error - // Will not return any reports as the finality depth is not reached. - require.Never(t, func() bool { - reports, err = s.reader.CommitReportsGTETimestamp( - ctx, - chainD, - // Skips first report - //nolint:gosec // this won't overflow - time.Unix(int64(firstReportTs)+1, 0), - 10, - ) - require.NoError(t, err) - return len(reports) == numReports-1 - }, 20*time.Second, 50*time.Millisecond) - - // Commit finality depth number of blocks. - for i := 0; i < int(finalityDepth); i++ { - s.sb.Commit() - } - - require.Eventually(t, func() bool { - reports, err = s.reader.CommitReportsGTETimestamp( - ctx, - chainD, - // Skips first report - //nolint:gosec // this won't overflow - time.Unix(int64(firstReportTs)+1, 0), - 10, - ) - require.NoError(t, err) - return len(reports) == numReports-1 - }, 30*time.Second, 50*time.Millisecond) - - assert.Len(t, reports, numReports-1) - assert.Len(t, reports[0].Report.MerkleRoots, 1) - assert.Equal(t, chainS1, reports[0].Report.MerkleRoots[0].ChainSel) - assert.Equal(t, onRampAddress.Bytes(), []byte(reports[0].Report.MerkleRoots[0].OnRampAddress)) - assert.Equal(t, cciptypes.SeqNum(10), reports[0].Report.MerkleRoots[0].SeqNumsRange.Start()) - assert.Equal(t, cciptypes.SeqNum(20), reports[0].Report.MerkleRoots[0].SeqNumsRange.End()) - assert.Equal(t, "0x0200000000000000000000000000000000000000000000000000000000000000", - reports[0].Report.MerkleRoots[0].MerkleRoot.String()) - assert.Equal(t, tokenA.String(), string(reports[0].Report.PriceUpdates.TokenPriceUpdates[0].TokenID)) - assert.Equal(t, uint64(1000), reports[0].Report.PriceUpdates.TokenPriceUpdates[0].Price.Uint64()) - assert.Equal(t, chainD, reports[0].Report.PriceUpdates.GasPriceUpdates[0].ChainSel) - assert.Equal(t, uint64(90), reports[0].Report.PriceUpdates.GasPriceUpdates[0].GasPrice.Uint64()) -} - -func TestCCIPReader_ExecutedMessageRanges(t *testing.T) { - t.Parallel() - ctx := tests.Context(t) - s := setupExecutedMessageRangesTest(ctx, t, false) - _, err := s.contract.EmitExecutionStateChanged( - s.auth, - uint64(chainS1), - 14, - cciptypes.Bytes32{1, 0, 0, 1}, - cciptypes.Bytes32{1, 0, 0, 1, 1, 0, 0, 1}, - 1, - []byte{1, 2, 3, 4}, - big.NewInt(250_000), - ) - require.NoError(t, err) - s.sb.Commit() - - _, err = s.contract.EmitExecutionStateChanged( - s.auth, - uint64(chainS1), - 15, - cciptypes.Bytes32{1, 0, 0, 2}, - cciptypes.Bytes32{1, 0, 0, 2, 1, 0, 0, 2}, - 1, - []byte{1, 2, 3, 4, 5}, - big.NewInt(350_000), - ) - require.NoError(t, err) - s.sb.Commit() - - // Need to replay as sometimes the logs are not picked up by the log poller (?) - // Maybe another situation where chain reader doesn't register filters as expected. - require.NoError(t, s.lp.Replay(ctx, 1)) - - var executedRanges []cciptypes.SeqNumRange - require.Eventually(t, func() bool { - executedRanges, err = s.reader.ExecutedMessageRanges( - ctx, - chainS1, - chainD, - cciptypes.NewSeqNumRange(14, 15), - ) - require.NoError(t, err) - return len(executedRanges) == 2 - }, tests.WaitTimeout(t), 50*time.Millisecond) - - assert.Equal(t, cciptypes.SeqNum(14), executedRanges[0].Start()) - assert.Equal(t, cciptypes.SeqNum(14), executedRanges[0].End()) - - assert.Equal(t, cciptypes.SeqNum(15), executedRanges[1].Start()) - assert.Equal(t, cciptypes.SeqNum(15), executedRanges[1].End()) -} - -func TestCCIPReader_MsgsBetweenSeqNums(t *testing.T) { - t.Parallel() - ctx := tests.Context(t) - - s := setupMsgsBetweenSeqNumsTest(ctx, t, false) - _, err := s.contract.EmitCCIPMessageSent(s.auth, uint64(chainD), ccip_reader_tester.InternalEVM2AnyRampMessage{ - Header: ccip_reader_tester.InternalRampMessageHeader{ - MessageId: [32]byte{1, 0, 0, 0, 0}, - SourceChainSelector: uint64(chainS1), - DestChainSelector: uint64(chainD), - SequenceNumber: 10, - }, - Sender: utils.RandomAddress(), - Data: make([]byte, 0), - Receiver: utils.RandomAddress().Bytes(), - ExtraArgs: make([]byte, 0), - FeeToken: utils.RandomAddress(), - FeeTokenAmount: big.NewInt(1), - FeeValueJuels: big.NewInt(2), - TokenAmounts: []ccip_reader_tester.InternalEVM2AnyTokenTransfer{{Amount: big.NewInt(1)}, {Amount: big.NewInt(2)}}, - }) - require.NoError(t, err) - - _, err = s.contract.EmitCCIPMessageSent(s.auth, uint64(chainD), ccip_reader_tester.InternalEVM2AnyRampMessage{ - Header: ccip_reader_tester.InternalRampMessageHeader{ - MessageId: [32]byte{1, 0, 0, 0, 1}, - SourceChainSelector: uint64(chainS1), - DestChainSelector: uint64(chainD), - SequenceNumber: 15, - }, - Sender: utils.RandomAddress(), - Data: make([]byte, 0), - Receiver: utils.RandomAddress().Bytes(), - ExtraArgs: make([]byte, 0), - FeeToken: utils.RandomAddress(), - FeeTokenAmount: big.NewInt(3), - FeeValueJuels: big.NewInt(4), - TokenAmounts: []ccip_reader_tester.InternalEVM2AnyTokenTransfer{{Amount: big.NewInt(3)}, {Amount: big.NewInt(4)}}, - }) - require.NoError(t, err) - - s.sb.Commit() - - // Need to replay as sometimes the logs are not picked up by the log poller (?) - // Maybe another situation where chain reader doesn't register filters as expected. - require.NoError(t, s.lp.Replay(ctx, 1)) - - var msgs []cciptypes.Message - require.Eventually(t, func() bool { - msgs, err = s.reader.MsgsBetweenSeqNums( - ctx, - chainS1, - cciptypes.NewSeqNumRange(5, 20), - ) - require.NoError(t, err) - return len(msgs) == 2 - }, tests.WaitTimeout(t), 100*time.Millisecond) - - require.Len(t, msgs, 2) - // sort to ensure ascending order of sequence numbers. - sort.Slice(msgs, func(i, j int) bool { - return msgs[i].Header.SequenceNumber < msgs[j].Header.SequenceNumber - }) - require.Equal(t, cciptypes.SeqNum(10), msgs[0].Header.SequenceNumber) - require.Equal(t, big.NewInt(1), msgs[0].FeeTokenAmount.Int) - require.Equal(t, big.NewInt(2), msgs[0].FeeValueJuels.Int) - require.Equal(t, int64(1), msgs[0].TokenAmounts[0].Amount.Int64()) - require.Equal(t, int64(2), msgs[0].TokenAmounts[1].Amount.Int64()) - - require.Equal(t, cciptypes.SeqNum(15), msgs[1].Header.SequenceNumber) - require.Equal(t, big.NewInt(3), msgs[1].FeeTokenAmount.Int) - require.Equal(t, big.NewInt(4), msgs[1].FeeValueJuels.Int) - require.Equal(t, int64(3), msgs[1].TokenAmounts[0].Amount.Int64()) - require.Equal(t, int64(4), msgs[1].TokenAmounts[1].Amount.Int64()) - - for _, msg := range msgs { - require.Equal(t, chainS1, msg.Header.SourceChainSelector) - require.Equal(t, chainD, msg.Header.DestChainSelector) - } -} - -func TestCCIPReader_NextSeqNum(t *testing.T) { - t.Parallel() - ctx := tests.Context(t) - - onChainSeqNums := map[cciptypes.ChainSelector]cciptypes.SeqNum{ - chainS1: 10, - chainS2: 20, - chainS3: 30, - } - - cfg := evmtypes.ChainReaderConfig{ - Contracts: map[string]evmtypes.ChainContractReader{ - consts.ContractNameOffRamp: { - ContractABI: ccip_reader_tester.CCIPReaderTesterABI, - Configs: map[string]*evmtypes.ChainReaderDefinition{ - consts.MethodNameGetSourceChainConfig: { - ChainSpecificName: "getSourceChainConfig", - ReadType: evmtypes.Method, - }, - }, - }, - }, - } - - sb, auth := setupSimulatedBackendAndAuth(t) - s := testSetup(ctx, t, testSetupParams{ - ReaderChain: chainD, - DestChain: chainD, - OnChainSeqNums: onChainSeqNums, - Cfg: cfg, - ToBindContracts: nil, - ToMockBindings: nil, - BindTester: true, - ContractNameToBind: consts.ContractNameOffRamp, - SimulatedBackend: sb, - Auth: auth, - }) - - seqNums, err := s.reader.NextSeqNum(ctx, []cciptypes.ChainSelector{chainS1, chainS2, chainS3}) - require.NoError(t, err) - assert.Len(t, seqNums, 3) - assert.Equal(t, cciptypes.SeqNum(10), seqNums[0]) - assert.Equal(t, cciptypes.SeqNum(20), seqNums[1]) - assert.Equal(t, cciptypes.SeqNum(30), seqNums[2]) -} - -func TestCCIPReader_GetExpectedNextSequenceNumber(t *testing.T) { - t.Parallel() - ctx := tests.Context(t) - //env := NewMemoryEnvironmentContractsOnly(t, logger.TestLogger(t), 2, 4, nil) - env := changeset.NewMemoryEnvironment(t) - state, err := changeset.LoadOnchainState(env.Env) - require.NoError(t, err) - - selectors := env.Env.AllChainSelectors() - destChain, srcChain := selectors[0], selectors[1] - - changeset.AddLaneWithDefaultPricesAndFeeQuoterConfig(t, &env, state, destChain, srcChain, false) - changeset.AddLaneWithDefaultPricesAndFeeQuoterConfig(t, &env, state, srcChain, destChain, false) - - reader := testSetupRealContracts( - ctx, - t, - destChain, - map[cciptypes.ChainSelector][]types.BoundContract{ - cciptypes.ChainSelector(srcChain): { - { - Address: state.Chains[srcChain].OnRamp.Address().String(), - Name: consts.ContractNameOnRamp, - }, - }, - }, - nil, - env, - ) - - maxExpectedSeqNum := uint64(10) - var i uint64 - for i = 1; i < maxExpectedSeqNum; i++ { - msg := changeset.DefaultRouterMessage(state.Chains[destChain].Receiver.Address()) - msgSentEvent := changeset.TestSendRequest(t, env.Env, state, srcChain, destChain, false, msg) - require.Equal(t, uint64(i), msgSentEvent.SequenceNumber) - require.Equal(t, uint64(i), msgSentEvent.Message.Header.Nonce) // check outbound nonce incremented - seqNum, err2 := reader.GetExpectedNextSequenceNumber(ctx, cs(srcChain), cs(destChain)) - require.NoError(t, err2) - require.Equal(t, cciptypes.SeqNum(i+1), seqNum) - } -} - -func TestCCIPReader_Nonces(t *testing.T) { - t.Parallel() - ctx := tests.Context(t) - var nonces = map[cciptypes.ChainSelector]map[common.Address]uint64{ - chainS1: { - utils.RandomAddress(): 10, - utils.RandomAddress(): 20, - }, - chainS2: { - utils.RandomAddress(): 30, - utils.RandomAddress(): 40, - }, - chainS3: { - utils.RandomAddress(): 50, - utils.RandomAddress(): 60, - }, - } - - cfg := evmtypes.ChainReaderConfig{ - Contracts: map[string]evmtypes.ChainContractReader{ - consts.ContractNameNonceManager: { - ContractABI: ccip_reader_tester.CCIPReaderTesterABI, - Configs: map[string]*evmtypes.ChainReaderDefinition{ - consts.MethodNameGetInboundNonce: { - ChainSpecificName: "getInboundNonce", - ReadType: evmtypes.Method, - }, - }, - }, - }, - } - - sb, auth := setupSimulatedBackendAndAuth(t) - s := testSetup(ctx, t, testSetupParams{ - ReaderChain: chainD, - DestChain: chainD, - Cfg: cfg, - BindTester: true, - ContractNameToBind: consts.ContractNameNonceManager, - SimulatedBackend: sb, - Auth: auth, - }) - - // Add some nonces. - for chain, addrs := range nonces { - for addr, nonce := range addrs { - _, err := s.contract.SetInboundNonce(s.auth, uint64(chain), nonce, common.LeftPadBytes(addr.Bytes(), 32)) - require.NoError(t, err) - } - } - s.sb.Commit() - - for sourceChain, addrs := range nonces { - var addrQuery []string - for addr := range addrs { - addrQuery = append(addrQuery, addr.String()) - } - addrQuery = append(addrQuery, utils.RandomAddress().String()) - - results, err := s.reader.Nonces(ctx, sourceChain, chainD, addrQuery) - require.NoError(t, err) - assert.Len(t, results, len(addrQuery)) - for addr, nonce := range addrs { - assert.Equal(t, nonce, results[addr.String()]) - } - } -} - -func Test_GetChainFeePriceUpdates(t *testing.T) { - t.Parallel() - ctx := tests.Context(t) - env := changeset.NewMemoryEnvironment(t) - state, err := changeset.LoadOnchainState(env.Env) - require.NoError(t, err) - - selectors := env.Env.AllChainSelectors() - chain1, chain2 := selectors[0], selectors[1] - - changeset.AddLaneWithDefaultPricesAndFeeQuoterConfig(t, &env, state, chain1, chain2, false) - changeset.AddLaneWithDefaultPricesAndFeeQuoterConfig(t, &env, state, chain2, chain1, false) - - // Change the gas price for chain2 - feeQuoter := state.Chains[chain1].FeeQuoter - _, err = feeQuoter.UpdatePrices( - env.Env.Chains[chain1].DeployerKey, fee_quoter.InternalPriceUpdates{ - GasPriceUpdates: []fee_quoter.InternalGasPriceUpdate{ - { - DestChainSelector: chain2, - UsdPerUnitGas: defaultGasPrice.ToInt(), - }, - }, - }, - ) - require.NoError(t, err) - be := env.Env.Chains[chain1].Client.(*memory.Backend) - be.Commit() - - gas, err := feeQuoter.GetDestinationChainGasPrice(&bind.CallOpts{}, chain2) - require.NoError(t, err) - require.Equal(t, defaultGasPrice.ToInt(), gas.Value) - - reader := testSetupRealContracts( - ctx, - t, - chain1, - //evmconfig.DestReaderConfig, - map[cciptypes.ChainSelector][]types.BoundContract{ - cciptypes.ChainSelector(chain1): { - { - Address: state.Chains[chain1].FeeQuoter.Address().String(), - Name: consts.ContractNameFeeQuoter, - }, - }, - }, - nil, - env, - ) - - updates := reader.GetChainFeePriceUpdate(ctx, []cciptypes.ChainSelector{cs(chain1), cs(chain2)}) - // only chain1 has a bound contract - require.Len(t, updates, 1) - require.Equal(t, defaultGasPrice.ToInt(), updates[cs(chain2)].Value.Int) -} - -func Test_LinkPriceUSD(t *testing.T) { - t.Parallel() - ctx := tests.Context(t) - env := changeset.NewMemoryEnvironment(t) - state, err := changeset.LoadOnchainState(env.Env) - require.NoError(t, err) - - selectors := env.Env.AllChainSelectors() - chain1, chain2 := selectors[0], selectors[1] - - changeset.AddLaneWithDefaultPricesAndFeeQuoterConfig(t, &env, state, chain1, chain2, false) - changeset.AddLaneWithDefaultPricesAndFeeQuoterConfig(t, &env, state, chain2, chain1, false) - - reader := testSetupRealContracts( - ctx, - t, - chain1, - map[cciptypes.ChainSelector][]types.BoundContract{ - cciptypes.ChainSelector(chain1): { - { - Address: state.Chains[chain1].FeeQuoter.Address().String(), - Name: consts.ContractNameFeeQuoter, - }, - }, - }, - nil, - env, - ) - - linkPriceUSD, err := reader.LinkPriceUSD(ctx) - require.NoError(t, err) - require.NotNil(t, linkPriceUSD.Int) - require.Equal(t, changeset.DefaultLinkPrice, linkPriceUSD.Int) -} - -func Test_GetMedianDataAvailabilityGasConfig(t *testing.T) { - t.Parallel() - ctx := tests.Context(t) - env := changeset.NewMemoryEnvironment(t, changeset.WithChains(4)) - state, err := changeset.LoadOnchainState(env.Env) - require.NoError(t, err) - - selectors := env.Env.AllChainSelectors() - destChain, chain1, chain2, chain3 := selectors[0], selectors[1], selectors[2], selectors[3] - - changeset.AddLaneWithDefaultPricesAndFeeQuoterConfig(t, &env, state, chain1, destChain, false) - changeset.AddLaneWithDefaultPricesAndFeeQuoterConfig(t, &env, state, chain2, destChain, false) - changeset.AddLaneWithDefaultPricesAndFeeQuoterConfig(t, &env, state, chain3, destChain, false) - - boundContracts := map[cciptypes.ChainSelector][]types.BoundContract{} - for i, selector := range env.Env.AllChainSelectorsExcluding([]uint64{destChain}) { - feeQuoter := state.Chains[selector].FeeQuoter - destChainCfg := changeset.DefaultFeeQuoterDestChainConfig() - //nolint:gosec // disable G115 - destChainCfg.DestDataAvailabilityOverheadGas = uint32(100 + i) - //nolint:gosec // disable G115 - destChainCfg.DestGasPerDataAvailabilityByte = uint16(200 + i) - //nolint:gosec // disable G115 - destChainCfg.DestDataAvailabilityMultiplierBps = uint16(1 + i) - _, err2 := feeQuoter.ApplyDestChainConfigUpdates(env.Env.Chains[selector].DeployerKey, []fee_quoter.FeeQuoterDestChainConfigArgs{ - { - DestChainSelector: destChain, - DestChainConfig: destChainCfg, - }, - }) - require.NoError(t, err2) - be := env.Env.Chains[selector].Client.(*memory.Backend) - be.Commit() - boundContracts[cs(selector)] = []types.BoundContract{ - { - Address: feeQuoter.Address().String(), - Name: consts.ContractNameFeeQuoter, - }, - } - } - - reader := testSetupRealContracts( - ctx, - t, - destChain, - boundContracts, - nil, - env, - ) - - daConfig, err := reader.GetMedianDataAvailabilityGasConfig(ctx) - require.NoError(t, err) - - // Verify the results - require.Equal(t, uint32(101), daConfig.DestDataAvailabilityOverheadGas) - require.Equal(t, uint16(201), daConfig.DestGasPerDataAvailabilityByte) - require.Equal(t, uint16(2), daConfig.DestDataAvailabilityMultiplierBps) -} - -func Test_GetWrappedNativeTokenPriceUSD(t *testing.T) { - t.Parallel() - ctx := tests.Context(t) - env := changeset.NewMemoryEnvironment(t) - state, err := changeset.LoadOnchainState(env.Env) - require.NoError(t, err) - - selectors := env.Env.AllChainSelectors() - chain1, chain2 := selectors[0], selectors[1] - - changeset.AddLaneWithDefaultPricesAndFeeQuoterConfig(t, &env, state, chain1, chain2, false) - changeset.AddLaneWithDefaultPricesAndFeeQuoterConfig(t, &env, state, chain2, chain1, false) - - reader := testSetupRealContracts( - ctx, - t, - chain1, - map[cciptypes.ChainSelector][]types.BoundContract{ - cciptypes.ChainSelector(chain1): { - { - Address: state.Chains[chain1].FeeQuoter.Address().String(), - Name: consts.ContractNameFeeQuoter, - }, - { - Address: state.Chains[chain1].Router.Address().String(), - Name: consts.ContractNameRouter, - }, - }, - }, - nil, - env, - ) - - prices := reader.GetWrappedNativeTokenPriceUSD(ctx, []cciptypes.ChainSelector{cciptypes.ChainSelector(chain1), cciptypes.ChainSelector(chain2)}) - - // Only chainD has reader contracts bound - require.Len(t, prices, 1) - require.Equal(t, changeset.DefaultWethPrice, prices[cciptypes.ChainSelector(chain1)].Int) -} - -// Benchmark Results: -// Benchmark_CCIPReader_CommitReportsGTETimestamp/FirstLogs_0_MatchLogs_0-14 16948 67728 ns/op 30387 B/op 417 allocs/op -// Benchmark_CCIPReader_CommitReportsGTETimestamp/FirstLogs_1_MatchLogs_10-14 1650 741741 ns/op 528334 B/op 9929 allocs/op -// Benchmark_CCIPReader_CommitReportsGTETimestamp/FirstLogs_10_MatchLogs_100-14 195 6096328 ns/op 4739856 B/op 92345 allocs/op -// Benchmark_CCIPReader_CommitReportsGTETimestamp/FirstLogs_100_MatchLogs_10000-14 2 582712583 ns/op 454375304 B/op 8931990 allocs/op -func Benchmark_CCIPReader_CommitReportsGTETimestamp(b *testing.B) { - tests := []struct { - logsInsertedFirst int - logsInsertedMatching int - }{ - {0, 0}, - {1, 10}, - {10, 100}, - {100, 10_000}, - } - - for _, tt := range tests { - b.Run(fmt.Sprintf("FirstLogs_%d_MatchLogs_%d", tt.logsInsertedMatching, tt.logsInsertedFirst), func(b *testing.B) { - benchmarkCommitReports(b, tt.logsInsertedFirst, tt.logsInsertedMatching) - }) - } -} - -func benchmarkCommitReports(b *testing.B, logsInsertedFirst int, logsInsertedMatching int) { - // Initialize test setup - ctx := tests.Context(b) - s, _, _ := setupGetCommitGTETimestampTest(ctx, b, 0, true) - - if logsInsertedFirst > 0 { - populateDatabaseForCommitReportAccepted(ctx, b, s, chainD, chainS1, logsInsertedFirst, 0) - } - - queryTimestamp := time.Now() - - if logsInsertedMatching > 0 { - populateDatabaseForCommitReportAccepted(ctx, b, s, chainD, chainS1, logsInsertedMatching, logsInsertedFirst) - } - - // Reset timer to measure only the query time - b.ResetTimer() - - for i := 0; i < b.N; i++ { - reports, err := s.reader.CommitReportsGTETimestamp(ctx, chainD, queryTimestamp, logsInsertedFirst) - require.NoError(b, err) - require.Len(b, reports, logsInsertedFirst) - } -} - -func populateDatabaseForCommitReportAccepted( - ctx context.Context, - b *testing.B, - testEnv *testSetupData, - destChain cciptypes.ChainSelector, - sourceChain cciptypes.ChainSelector, - numOfReports int, - offset int, -) { - var logs []logpoller.Log - commitReportEvent, exists := offrampABI.Events[consts.EventNameCommitReportAccepted] - require.True(b, exists, "Event CommitReportAccepted not found in ABI") - - commitReportEventSig := commitReportEvent.ID - commitReportAddress := testEnv.contractAddr - - // Calculate timestamp based on whether these are the first logs or matching logs - var timestamp time.Time - if offset == 0 { - // For first set of logs, set timestamp to 1 hour ago - timestamp = time.Now().Add(-1 * time.Hour) - } else { - // For matching logs, use current time - timestamp = time.Now() - } - - for i := 0; i < numOfReports; i++ { - // Calculate unique BlockNumber and LogIndex - blockNumber := int64(offset + i + 1) // Offset ensures unique block numbers - logIndex := int64(offset + i + 1) // Offset ensures unique log indices - - // Simulate merkleRoots - merkleRoots := []offramp.InternalMerkleRoot{ - { - SourceChainSelector: uint64(sourceChain), - OnRampAddress: utils.RandomAddress().Bytes(), - // #nosec G115 - MinSeqNr: uint64(i * 100), - // #nosec G115 - MaxSeqNr: uint64(i*100 + 99), - MerkleRoot: utils.RandomBytes32(), - }, - } - - sourceToken := utils.RandomAddress() - - // Simulate priceUpdates - priceUpdates := offramp.InternalPriceUpdates{ - TokenPriceUpdates: []offramp.InternalTokenPriceUpdate{ - {SourceToken: sourceToken, UsdPerToken: big.NewInt(8)}, - }, - GasPriceUpdates: []offramp.InternalGasPriceUpdate{ - {DestChainSelector: uint64(1), UsdPerUnitGas: big.NewInt(10)}, - }, - } - - // Combine encoded data - encodedData, err := commitReportEvent.Inputs.Pack(merkleRoots, priceUpdates) - require.NoError(b, err) - - // Topics (first one is the event signature) - topics := [][]byte{ - commitReportEventSig[:], - } - - // Create log entry - logs = append(logs, logpoller.Log{ - EvmChainId: ubig.New(new(big.Int).SetUint64(uint64(destChain))), - LogIndex: logIndex, - BlockHash: utils.NewHash(), - BlockNumber: blockNumber, - BlockTimestamp: timestamp, - EventSig: commitReportEventSig, - Topics: topics, - Address: commitReportAddress, - TxHash: utils.NewHash(), - Data: encodedData, - CreatedAt: time.Now(), - }) - } - - // Insert logs into the database - require.NoError(b, testEnv.orm.InsertLogs(ctx, logs)) - require.NoError(b, testEnv.orm.InsertBlock(ctx, utils.RandomHash(), int64(offset+numOfReports), timestamp, int64(offset+numOfReports))) -} - -// Benchmark Results: -// Benchmark_CCIPReader_ExecutedMessageRanges/LogsInserted_0_StartSeq_0_EndSeq_10-14 13599 93414 ns/op 43389 B/op 654 allocs/op -// Benchmark_CCIPReader_ExecutedMessageRanges/LogsInserted_10_StartSeq_10_EndSeq_20-14 13471 88392 ns/op 43011 B/op 651 allocs/op -// Benchmark_CCIPReader_ExecutedMessageRanges/LogsInserted_10_StartSeq_0_EndSeq_9-14 2799 473396 ns/op 303737 B/op 4535 allocs/op -// Benchmark_CCIPReader_ExecutedMessageRanges/LogsInserted_100_StartSeq_0_EndSeq_100-14 438 2724414 ns/op 2477573 B/op 37468 allocs/op -// Benchmark_CCIPReader_ExecutedMessageRanges/LogsInserted_100000_StartSeq_99744_EndSeq_100000-14 40 29118796 ns/op 12607995 B/op 179396 allocs/op -func Benchmark_CCIPReader_ExecutedMessageRanges(b *testing.B) { - tests := []struct { - logsInserted int - startSeqNum cciptypes.SeqNum - endSeqNum cciptypes.SeqNum - }{ - {0, 0, 10}, // no logs - {10, 10, 20}, // out of bounds - {10, 0, 9}, // get all messages with 10 logs - {100, 0, 100}, // get all messages with 100 logs - {100_000, 100_000 - 256, 100_000}, // get the last 256 messages - } - - for _, tt := range tests { - b.Run(fmt.Sprintf("LogsInserted_%d_StartSeq_%d_EndSeq_%d", tt.logsInserted, tt.startSeqNum, tt.endSeqNum), func(b *testing.B) { - benchmarkExecutedMessageRanges(b, tt.logsInserted, tt.startSeqNum, tt.endSeqNum) - }) - } -} - -func benchmarkExecutedMessageRanges(b *testing.B, logsInsertedFirst int, startSeqNum, endSeqNum cciptypes.SeqNum) { - // Initialize test setup - ctx := tests.Context(b) - s := setupExecutedMessageRangesTest(ctx, b, true) - expectedRangeLen := calculateExpectedRangeLen(logsInsertedFirst, startSeqNum, endSeqNum) - - // Insert logs in two phases based on parameters - if logsInsertedFirst > 0 { - populateDatabaseForExecutionStateChanged(ctx, b, s, chainS1, chainD, logsInsertedFirst, 0) - } - - // Reset timer to measure only the query time - b.ResetTimer() - - for i := 0; i < b.N; i++ { - executedRanges, err := s.reader.ExecutedMessageRanges( - ctx, - chainS1, - chainD, - cciptypes.NewSeqNumRange(startSeqNum, endSeqNum), - ) - require.NoError(b, err) - require.Len(b, executedRanges, expectedRangeLen) - } -} - -func populateDatabaseForExecutionStateChanged( - ctx context.Context, - b *testing.B, - testEnv *testSetupData, - sourceChain cciptypes.ChainSelector, - destChain cciptypes.ChainSelector, - numOfEvents int, - offset int, -) { - var logs []logpoller.Log - executionStateEvent, exists := offrampABI.Events[consts.EventNameExecutionStateChanged] - require.True(b, exists, "Event ExecutionStateChanged not found in ABI") - - executionStateEventSig := executionStateEvent.ID - executionStateEventAddress := testEnv.contractAddr - - for i := 0; i < numOfEvents; i++ { - // Calculate unique BlockNumber and LogIndex - blockNumber := int64(offset + i + 1) // Offset ensures unique block numbers - logIndex := int64(offset + i + 1) // Offset ensures unique log indices - - // Populate fields for the event - sourceChainSelector := uint64(sourceChain) - // #nosec G115 - sequenceNumber := uint64(offset + i) - messageID := utils.NewHash() - messageHash := utils.NewHash() - state := uint8(1) - returnData := []byte{0x01, 0x02} - gasUsed := big.NewInt(int64(10000 + i)) - - // Encode the non indexed event data - encodedData, err := executionStateEvent.Inputs.NonIndexed().Pack( - messageHash, - state, - returnData, - gasUsed, - ) - require.NoError(b, err) - - // Topics (event signature and indexed fields) - topics := [][]byte{ - executionStateEventSig[:], // Event signature - logpoller.EvmWord(sourceChainSelector).Bytes(), // Indexed sourceChainSelector - logpoller.EvmWord(sequenceNumber).Bytes(), // Indexed sequenceNumber - messageID[:], // Indexed messageId - } - - // Create log entry - logs = append(logs, logpoller.Log{ - EvmChainId: ubig.New(big.NewInt(0).SetUint64(uint64(destChain))), - LogIndex: logIndex, - BlockHash: utils.NewHash(), - BlockNumber: blockNumber, - BlockTimestamp: time.Now(), - EventSig: executionStateEventSig, - Topics: topics, - Address: executionStateEventAddress, - TxHash: utils.NewHash(), - Data: encodedData, - CreatedAt: time.Now(), - }) - } - - // Insert logs into the database - require.NoError(b, testEnv.orm.InsertLogs(ctx, logs)) - require.NoError(b, testEnv.orm.InsertBlock(ctx, utils.RandomHash(), int64(offset+numOfEvents), time.Now(), int64(offset+numOfEvents))) -} - -// Benchmark Results: -// Benchmark_CCIPReader_MessageSentRanges/LogsInserted_0_StartSeq_0_EndSeq_10-14 13729 85838 ns/op 43473 B/op 647 allocs/op -// Benchmark_CCIPReader_MessageSentRanges/LogsInserted_10_StartSeq_0_EndSeq_9-14 870 1405208 ns/op 1156315 B/op 21102 allocs/op -// Benchmark_CCIPReader_MessageSentRanges/LogsInserted_100_StartSeq_0_EndSeq_100-14 90 12129488 ns/op 10833395 B/op 201076 allocs/op -// Benchmark_CCIPReader_MessageSentRanges/LogsInserted_100000_StartSeq_99744_EndSeq_100000-14 10 105741438 ns/op 49103282 B/op 796213 allocs/op -func Benchmark_CCIPReader_MessageSentRanges(b *testing.B) { - tests := []struct { - logsInserted int - startSeqNum cciptypes.SeqNum - endSeqNum cciptypes.SeqNum - }{ - {0, 0, 10}, // No logs - {10, 0, 9}, // Get all messages with 10 logs - {100, 0, 100}, // Get all messages with 100 logs - {100_000, 100_000 - 256, 100_000}, // Get the last 256 messages - } - - for _, tt := range tests { - b.Run(fmt.Sprintf("LogsInserted_%d_StartSeq_%d_EndSeq_%d", tt.logsInserted, tt.startSeqNum, tt.endSeqNum), func(b *testing.B) { - benchmarkMessageSentRanges(b, tt.logsInserted, tt.startSeqNum, tt.endSeqNum) - }) - } -} - -func benchmarkMessageSentRanges(b *testing.B, logsInserted int, startSeqNum, endSeqNum cciptypes.SeqNum) { - // Initialize test setup - ctx := tests.Context(b) - s := setupMsgsBetweenSeqNumsTest(ctx, b, true) - expectedRangeLen := calculateExpectedRangeLen(logsInserted, startSeqNum, endSeqNum) - - err := s.extendedCR.Bind(ctx, []types.BoundContract{ - { - Address: s.contractAddr.String(), - Name: consts.ContractNameOnRamp, - }, - }) - require.NoError(b, err) - - // Insert logs if needed - if logsInserted > 0 { - populateDatabaseForMessageSent(ctx, b, s, chainS1, chainD, logsInserted, 0) - } - - // Reset timer to measure only the query time - b.ResetTimer() - - for i := 0; i < b.N; i++ { - msgs, err := s.reader.MsgsBetweenSeqNums( - ctx, - chainS1, - cciptypes.NewSeqNumRange(startSeqNum, endSeqNum), - ) - require.NoError(b, err) - require.Len(b, msgs, expectedRangeLen) - } -} - -func populateDatabaseForMessageSent( - ctx context.Context, - b *testing.B, - testEnv *testSetupData, - sourceChain cciptypes.ChainSelector, - destChain cciptypes.ChainSelector, - numOfEvents int, - offset int, -) { - var logs []logpoller.Log - messageSentEvent, exists := onrampABI.Events[consts.EventNameCCIPMessageSent] - require.True(b, exists, "Event CCIPMessageSent not found in ABI") - - messageSentEventSig := messageSentEvent.ID - messageSentEventAddress := testEnv.contractAddr - - for i := 0; i < numOfEvents; i++ { - // Calculate unique BlockNumber and LogIndex - blockNumber := int64(offset + i + 1) // Offset ensures unique block numbers - logIndex := int64(offset + i + 1) // Offset ensures unique log indices - - // Populate fields for the event - destChainSelector := uint64(destChain) - // #nosec G115 - sequenceNumber := uint64(offset + i) - - // Create InternalRampMessageHeader struct - header := onramp.InternalRampMessageHeader{ - MessageId: utils.NewHash(), - SourceChainSelector: uint64(sourceChain), - DestChainSelector: destChainSelector, - SequenceNumber: sequenceNumber, - // #nosec G115 - Nonce: uint64(i), - } - - // Create InternalEVM2AnyTokenTransfer slice - tokenTransfers := []onramp.InternalEVM2AnyTokenTransfer{ - { - SourcePoolAddress: utils.RandomAddress(), - DestTokenAddress: []byte{0x01, 0x02}, - ExtraData: []byte{0x03}, - // #nosec G115 - Amount: big.NewInt(1000 + int64(i)), - DestExecData: []byte{}, - }, - } - - // Create InternalEVM2AnyRampMessage struct - message := onramp.InternalEVM2AnyRampMessage{ - Header: header, - Sender: utils.RandomAddress(), - Data: []byte{0x04, 0x05}, - Receiver: []byte{0x06, 0x07}, - ExtraArgs: []byte{0x08}, - FeeToken: utils.RandomAddress(), - // #nosec G115 - FeeTokenAmount: big.NewInt(2000 + int64(i)), - // #nosec G115 - - FeeValueJuels: big.NewInt(3000 + int64(i)), - TokenAmounts: tokenTransfers, - } - - // Encode the non-indexed event data - encodedData, err := messageSentEvent.Inputs.NonIndexed().Pack( - message, - ) - require.NoError(b, err) - - // Topics (event signature and indexed fields) - topics := [][]byte{ - messageSentEventSig[:], // Event signature - logpoller.EvmWord(destChainSelector).Bytes(), // Indexed destChainSelector - logpoller.EvmWord(sequenceNumber).Bytes(), // Indexed sequenceNumber - } - - // Create log entry - logs = append(logs, logpoller.Log{ - EvmChainId: ubig.New(big.NewInt(0).SetUint64(uint64(sourceChain))), - LogIndex: logIndex, - BlockHash: utils.NewHash(), - BlockNumber: blockNumber, - BlockTimestamp: time.Now(), - EventSig: messageSentEventSig, - Topics: topics, - Address: messageSentEventAddress, - TxHash: utils.NewHash(), - Data: encodedData, - CreatedAt: time.Now(), - }) - } - - // Insert logs into the database - require.NoError(b, testEnv.orm.InsertLogs(ctx, logs)) - require.NoError(b, testEnv.orm.InsertBlock(ctx, utils.RandomHash(), int64(offset+numOfEvents), time.Now(), int64(offset+numOfEvents))) -} - -func calculateExpectedRangeLen(logsInserted int, startSeq, endSeq cciptypes.SeqNum) int { - if logsInserted == 0 { - return 0 - } - start := uint64(startSeq) - end := uint64(endSeq) - // #nosec G115 - logs := uint64(logsInserted) - - if start >= logs { - return 0 - } - - if end >= logs { - end = logs - 1 - } - - // #nosec G115 - return int(end - start + 1) -} - -func setupSimulatedBackendAndAuth(t testing.TB) (*simulated.Backend, *bind.TransactOpts) { - privateKey, err := crypto.GenerateKey() - require.NoError(t, err) - - blnc, ok := big.NewInt(0).SetString("999999999999999999999999999999999999", 10) - require.True(t, ok) - - alloc := map[common.Address]ethtypes.Account{crypto.PubkeyToAddress(privateKey.PublicKey): {Balance: blnc}} - simulatedBackend := simulated.NewBackend(alloc, simulated.WithBlockGasLimit(8000000)) - - auth, err := bind.NewKeyedTransactorWithChainID(privateKey, big.NewInt(1337)) - require.NoError(t, err) - auth.GasLimit = uint64(6000000) - - return simulatedBackend, auth -} - -func testSetupRealContracts( - ctx context.Context, - t *testing.T, - destChain uint64, - toBindContracts map[cciptypes.ChainSelector][]types.BoundContract, - toMockBindings map[cciptypes.ChainSelector][]types.BoundContract, - env changeset.DeployedEnv, -) ccipreaderpkg.CCIPReader { - db := pgtest.NewSqlxDB(t) - lpOpts := logpoller.Opts{ - PollPeriod: time.Millisecond, - FinalityDepth: 0, - BackfillBatchSize: 10, - RpcBatchSize: 10, - KeepFinalizedBlocksDepth: 100000, - } - lggr := logger.TestLogger(t) - lggr.SetLogLevel(zapcore.ErrorLevel) - - var crs = make(map[cciptypes.ChainSelector]contractreader.Extended) - for chain, bindings := range toBindContracts { - be := env.Env.Chains[uint64(chain)].Client.(*memory.Backend) - cl := client.NewSimulatedBackendClient(t, be.Sim, big.NewInt(0).SetUint64(uint64(chain))) - headTracker := headtracker.NewSimulatedHeadTracker(cl, lpOpts.UseFinalityTag, lpOpts.FinalityDepth) - lp := logpoller.NewLogPoller(logpoller.NewORM(big.NewInt(0).SetUint64(uint64(chain)), db, lggr), - cl, - lggr, - headTracker, - lpOpts, - ) - require.NoError(t, lp.Start(ctx)) - - var cfg evmtypes.ChainReaderConfig - if chain == cs(destChain) { - cfg = evmconfig.DestReaderConfig - } else { - cfg = evmconfig.SourceReaderConfig - } - cr, err := evm.NewChainReaderService(ctx, lggr, lp, headTracker, cl, cfg) - require.NoError(t, err) - - extendedCr2 := contractreader.NewExtendedContractReader(cr) - err = extendedCr2.Bind(ctx, bindings) - require.NoError(t, err) - crs[cciptypes.ChainSelector(chain)] = extendedCr2 - - err = cr.Start(ctx) - require.NoError(t, err) - - t.Cleanup(func() { - require.NoError(t, cr.Close()) - require.NoError(t, lp.Close()) - require.NoError(t, db.Close()) - }) - } - - for chain, bindings := range toMockBindings { - if _, ok := crs[chain]; ok { - require.False(t, ok, "chain %d already exists", chain) - } - m := readermocks.NewMockContractReaderFacade(t) - m.EXPECT().Bind(ctx, bindings).Return(nil) - ecr := contractreader.NewExtendedContractReader(m) - err := ecr.Bind(ctx, bindings) - require.NoError(t, err) - crs[chain] = ecr - } - - contractReaders := map[cciptypes.ChainSelector]contractreader.Extended{} - for chain, cr := range crs { - contractReaders[chain] = cr - } - contractWriters := make(map[cciptypes.ChainSelector]types.ContractWriter) - reader := ccipreaderpkg.NewCCIPReaderWithExtendedContractReaders(ctx, lggr, contractReaders, contractWriters, cciptypes.ChainSelector(destChain), nil) - - return reader -} - -func testSetup( - ctx context.Context, - t testing.TB, - params testSetupParams, -) *testSetupData { - address, _, _, err := ccip_reader_tester.DeployCCIPReaderTester(params.Auth, params.SimulatedBackend.Client()) - assert.NoError(t, err) - params.SimulatedBackend.Commit() - - // Setup contract client - contract, err := ccip_reader_tester.NewCCIPReaderTester(address, params.SimulatedBackend.Client()) - assert.NoError(t, err) - - lggr := logger.TestLogger(t) - lggr.SetLogLevel(zapcore.ErrorLevel) - // Parameterize database selection - var db *sqlx.DB - if params.UseHeavyDB { - _, db = heavyweight.FullTestDBV2(t, nil) // Heavyweight database for benchmarks - } else { - db = pgtest.NewSqlxDB(t) // Simple in-memory DB for tests - } - lpOpts := logpoller.Opts{ - PollPeriod: time.Millisecond, - FinalityDepth: params.FinalityDepth, - BackfillBatchSize: 10, - RpcBatchSize: 10, - KeepFinalizedBlocksDepth: 100000, - } - cl := client.NewSimulatedBackendClient(t, params.SimulatedBackend, big.NewInt(0).SetUint64(uint64(params.ReaderChain))) - headTracker := headtracker.NewSimulatedHeadTracker(cl, lpOpts.UseFinalityTag, lpOpts.FinalityDepth) - orm := logpoller.NewORM(big.NewInt(0).SetUint64(uint64(params.ReaderChain)), db, lggr) - lp := logpoller.NewLogPoller( - orm, - cl, - lggr, - headTracker, - lpOpts, - ) - assert.NoError(t, lp.Start(ctx)) - - for sourceChain, seqNum := range params.OnChainSeqNums { - _, err1 := contract.SetSourceChainConfig(params.Auth, uint64(sourceChain), ccip_reader_tester.OffRampSourceChainConfig{ - IsEnabled: true, - MinSeqNr: uint64(seqNum), - OnRamp: utils.RandomAddress().Bytes(), - }) - assert.NoError(t, err1) - params.SimulatedBackend.Commit() - scc, err1 := contract.GetSourceChainConfig(&bind.CallOpts{Context: ctx}, uint64(sourceChain)) - assert.NoError(t, err1) - assert.Equal(t, seqNum, cciptypes.SeqNum(scc.MinSeqNr)) - } - - cr, err := evm.NewChainReaderService(ctx, lggr, lp, headTracker, cl, params.Cfg) - require.NoError(t, err) - - extendedCr := contractreader.NewExtendedContractReader(cr) - - if params.BindTester { - err = extendedCr.Bind(ctx, []types.BoundContract{ - { - Address: address.String(), - Name: params.ContractNameToBind, - }, - }) - require.NoError(t, err) - } - - var otherCrs = make(map[cciptypes.ChainSelector]contractreader.Extended) - for chain, bindings := range params.ToBindContracts { - cl2 := client.NewSimulatedBackendClient(t, params.SimulatedBackend, big.NewInt(0).SetUint64(uint64(chain))) - headTracker2 := headtracker.NewSimulatedHeadTracker(cl2, lpOpts.UseFinalityTag, lpOpts.FinalityDepth) - lp2 := logpoller.NewLogPoller(logpoller.NewORM(big.NewInt(0).SetUint64(uint64(chain)), db, lggr), - cl2, - lggr, - headTracker2, - lpOpts, - ) - require.NoError(t, lp2.Start(ctx)) - - cr2, err2 := evm.NewChainReaderService(ctx, lggr, lp2, headTracker2, cl2, params.Cfg) - require.NoError(t, err2) - - extendedCr2 := contractreader.NewExtendedContractReader(cr2) - err2 = extendedCr2.Bind(ctx, bindings) - require.NoError(t, err2) - otherCrs[chain] = extendedCr2 - } - - for chain, bindings := range params.ToMockBindings { - if _, ok := otherCrs[chain]; ok { - require.False(t, ok, "chain %d already exists", chain) - } - m := readermocks.NewMockContractReaderFacade(t) - m.EXPECT().Bind(ctx, bindings).Return(nil) - ecr := contractreader.NewExtendedContractReader(m) - err = ecr.Bind(ctx, bindings) - require.NoError(t, err) - otherCrs[chain] = ecr - } - - err = cr.Start(ctx) - require.NoError(t, err) - - contractReaders := map[cciptypes.ChainSelector]contractreader.Extended{params.ReaderChain: extendedCr} - for chain, cr := range otherCrs { - contractReaders[chain] = cr - } - contractWriters := make(map[cciptypes.ChainSelector]types.ContractWriter) - reader := ccipreaderpkg.NewCCIPReaderWithExtendedContractReaders(ctx, lggr, contractReaders, contractWriters, params.DestChain, nil) - - t.Cleanup(func() { - require.NoError(t, cr.Close()) - require.NoError(t, lp.Close()) - require.NoError(t, db.Close()) - }) - - return &testSetupData{ - contractAddr: address, - contract: contract, - sb: params.SimulatedBackend, - auth: params.Auth, - orm: orm, - lp: lp, - cl: cl, - reader: reader, - extendedCR: extendedCr, - } -} - -type testSetupParams struct { - ReaderChain cciptypes.ChainSelector - DestChain cciptypes.ChainSelector - OnChainSeqNums map[cciptypes.ChainSelector]cciptypes.SeqNum - Cfg evmtypes.ChainReaderConfig - ToBindContracts map[cciptypes.ChainSelector][]types.BoundContract - ToMockBindings map[cciptypes.ChainSelector][]types.BoundContract - BindTester bool - ContractNameToBind string - SimulatedBackend *simulated.Backend - Auth *bind.TransactOpts - FinalityDepth int64 - UseHeavyDB bool -} - -type testSetupData struct { - contractAddr common.Address - contract *ccip_reader_tester.CCIPReaderTester - sb *simulated.Backend - auth *bind.TransactOpts - orm logpoller.ORM - lp logpoller.LogPoller - cl client.Client - reader ccipreaderpkg.CCIPReader - extendedCR contractreader.Extended -} - -func cs(i uint64) cciptypes.ChainSelector { - return cciptypes.ChainSelector(i) -} diff --git a/integration-tests/contracts/ethereum_contracts_automation.go b/integration-tests/contracts/ethereum_contracts_automation.go index 1a4624c2dd3..3e18fe177f0 100644 --- a/integration-tests/contracts/ethereum_contracts_automation.go +++ b/integration-tests/contracts/ethereum_contracts_automation.go @@ -2809,14 +2809,14 @@ type AutomationConsumerBenchmarkUpkeepObserver struct { firstBlockNum uint64 // Records the number of the first block that came in lastBlockNum uint64 // Records the number of the last block that came in - blockRange uint64 // How many blocks to watch upkeeps for + blockRange int64 // How many blocks to watch upkeeps for upkeepSLA int64 // SLA after which an upkeep is counted as 'missed' metricsReporter *testreporters.KeeperBenchmarkTestReporter // Testreporter to track results upkeepIndex int64 firstEligibleBuffer int64 // State variables, changes as we get blocks - blocksSinceSubscription uint64 // How many blocks have passed since subscribing + blocksSinceSubscription int64 // How many blocks have passed since subscribing blocksSinceEligible int64 // How many blocks have come in since upkeep has been eligible for check countEligible int64 // Number of times the upkeep became eligible countMissed int64 // Number of times we missed SLA for performing upkeep @@ -2832,7 +2832,7 @@ func NewAutomationConsumerBenchmarkUpkeepObserver( contract AutomationConsumerBenchmark, registry KeeperRegistry, upkeepID *big.Int, - blockRange uint64, + blockRange int64, upkeepSLA int64, metricsReporter *testreporters.KeeperBenchmarkTestReporter, upkeepIndex int64, @@ -2906,7 +2906,7 @@ func (o *AutomationConsumerBenchmarkUpkeepObserver) ReceiveHeader(receivedHeader o.blocksSinceEligible = 0 } - isEligible, err := o.instance.CheckEligible(context.Background(), big.NewInt(o.upkeepIndex), new(big.Int).SetUint64(o.blockRange), big.NewInt(o.firstEligibleBuffer)) + isEligible, err := o.instance.CheckEligible(context.Background(), big.NewInt(o.upkeepIndex), big.NewInt(o.blockRange), big.NewInt(o.firstEligibleBuffer)) if err != nil { return false, err } @@ -2924,7 +2924,7 @@ func (o *AutomationConsumerBenchmarkUpkeepObserver) ReceiveHeader(receivedHeader o.blocksSinceEligible++ } - if o.blocksSinceSubscription >= o.blockRange || o.lastBlockNum-o.firstBlockNum >= o.blockRange { + if o.blocksSinceSubscription >= o.blockRange || int64(o.lastBlockNum-o.firstBlockNum) >= o.blockRange { if o.blocksSinceEligible > 0 { if o.blocksSinceEligible > o.upkeepSLA { o.l.Warn(). @@ -2953,7 +2953,7 @@ func (o *AutomationConsumerBenchmarkUpkeepObserver) ReceiveHeader(receivedHeader Str("Upkeep_ID", o.upkeepID.String()). Str("Contract_Address", o.instance.Address()). Int64("Upkeeps_Performed", upkeepCount.Int64()). - Uint64("Total_Blocks_Watched", o.blocksSinceSubscription). + Int64("Total_Blocks_Watched", o.blocksSinceSubscription). Str("Registry_Address", o.registry.Address()). Msg("Finished Watching for Upkeeps") diff --git a/integration-tests/crib/README.md b/integration-tests/crib/README.md index b3ba2c41823..c37cbfec9c9 100644 --- a/integration-tests/crib/README.md +++ b/integration-tests/crib/README.md @@ -6,7 +6,7 @@ It runs OCRv1 and reboots the environment confirming integration with environmen Go to the [CRIB](https://github.com/smartcontractkit/crib) repository and spin up a cluster. ```shell -DEVSPACE_NAMESPACE=crib-oh-my-crib crib init +./scripts/cribbit.sh crib-oh-my-crib devspace deploy --debug --profile local-dev-simulated-core-ocr1 ``` diff --git a/integration-tests/docker/test_env/cl_node.go b/integration-tests/docker/test_env/cl_node.go index 8ebaf579d0a..04a0b003821 100644 --- a/integration-tests/docker/test_env/cl_node.go +++ b/integration-tests/docker/test_env/cl_node.go @@ -24,6 +24,7 @@ import ( "github.com/smartcontractkit/chainlink-testing-framework/lib/docker" "github.com/smartcontractkit/chainlink-testing-framework/lib/docker/test_env" "github.com/smartcontractkit/chainlink-testing-framework/lib/logging" + "github.com/smartcontractkit/chainlink-testing-framework/lib/logstream" "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/testcontext" "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" @@ -125,11 +126,11 @@ func WithPgDBOptions(opts ...test_env.PostgresDbOption) ClNodeOption { } } -func NewClNode(networks []string, imageName, imageVersion string, nodeConfig *chainlink.Config, opts ...ClNodeOption) (*ClNode, error) { +func NewClNode(networks []string, imageName, imageVersion string, nodeConfig *chainlink.Config, logStream *logstream.LogStream, opts ...ClNodeOption) (*ClNode, error) { nodeDefaultCName := fmt.Sprintf("%s-%s", "cl-node", uuid.NewString()[0:8]) pgDefaultCName := fmt.Sprintf("pg-%s", nodeDefaultCName) - pgDb, err := test_env.NewPostgresDb(networks, test_env.WithPostgresDbContainerName(pgDefaultCName)) + pgDb, err := test_env.NewPostgresDb(networks, test_env.WithPostgresDbContainerName(pgDefaultCName), test_env.WithPostgresDbLogStream(logStream)) if err != nil { return nil, err } @@ -139,6 +140,7 @@ func NewClNode(networks []string, imageName, imageVersion string, nodeConfig *ch ContainerImage: imageName, ContainerVersion: imageVersion, Networks: networks, + LogStream: logStream, StartupTimeout: 3 * time.Minute, }, UserEmail: "local@local.com", @@ -147,6 +149,7 @@ func NewClNode(networks []string, imageName, imageVersion string, nodeConfig *ch PostgresDb: pgDb, l: log.Logger, } + n.SetDefaultHooks() for _, opt := range opts { opt(n) } @@ -488,6 +491,13 @@ func (n *ClNode) getContainerRequest(secrets string) ( FileMode: 0644, }, }, + LifecycleHooks: []tc.ContainerLifecycleHooks{ + { + PostStarts: n.PostStartsHooks, + PostStops: n.PostStopsHooks, + PreTerminates: n.PreTerminatesHooks, + }, + }, }, nil } diff --git a/integration-tests/docker/test_env/test_env.go b/integration-tests/docker/test_env/test_env.go index a37b7f813a7..1ca50760d17 100644 --- a/integration-tests/docker/test_env/test_env.go +++ b/integration-tests/docker/test_env/test_env.go @@ -20,6 +20,8 @@ import ( "github.com/smartcontractkit/chainlink-testing-framework/lib/docker" "github.com/smartcontractkit/chainlink-testing-framework/lib/docker/test_env" "github.com/smartcontractkit/chainlink-testing-framework/lib/logging" + "github.com/smartcontractkit/chainlink-testing-framework/lib/logstream" + "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/runid" "github.com/smartcontractkit/chainlink/integration-tests/testconfig/ccip" "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" @@ -34,6 +36,7 @@ var ( type CLClusterTestEnv struct { Cfg *TestEnvConfig DockerNetwork *tc.DockerNetwork + LogStream *logstream.LogStream TestConfig ctf_config.GlobalTestConfig /* components */ @@ -66,7 +69,7 @@ func (te *CLClusterTestEnv) WithTestEnvConfig(cfg *TestEnvConfig) *CLClusterTest te.Cfg = cfg if cfg.MockAdapter.ContainerName != "" { n := []string{te.DockerNetwork.Name} - te.MockAdapter = test_env.NewKillgrave(n, te.Cfg.MockAdapter.ImpostersPath, test_env.WithContainerName(te.Cfg.MockAdapter.ContainerName)) + te.MockAdapter = test_env.NewKillgrave(n, te.Cfg.MockAdapter.ImpostersPath, test_env.WithContainerName(te.Cfg.MockAdapter.ContainerName), test_env.WithLogStream(te.LogStream)) } return te } @@ -96,6 +99,7 @@ func (te *CLClusterTestEnv) StartEthereumNetwork(cfg *ctf_config.EthereumNetwork builder := test_env.NewEthereumNetworkBuilder() c, err := builder.WithExistingConfig(*cfg). WithTest(te.t). + WithLogStream(te.LogStream). Build() if err != nil { return blockchain.EVMNetwork{}, test_env.RpcProvider{}, err @@ -128,6 +132,7 @@ func (te *CLClusterTestEnv) StartJobDistributor(cfg *ccip.JDConfig) error { job_distributor.WithVersion(cfg.GetJDVersion()), job_distributor.WithDBURL(jdDB.InternalURL.String()), ) + jd.LogStream = te.LogStream err = jd.StartContainer() if err != nil { return fmt.Errorf("failed to start job-distributor: %w", err) @@ -155,7 +160,7 @@ func (te *CLClusterTestEnv) StartClCluster(nodeConfig *chainlink.Config, count i opts = append(opts, WithSecrets(secretsConfig)) te.ClCluster = &ClCluster{} for i := 0; i < count; i++ { - ocrNode, err := NewClNode([]string{te.DockerNetwork.Name}, *testconfig.GetChainlinkImageConfig().Image, *testconfig.GetChainlinkImageConfig().Version, nodeConfig, opts...) + ocrNode, err := NewClNode([]string{te.DockerNetwork.Name}, *testconfig.GetChainlinkImageConfig().Image, *testconfig.GetChainlinkImageConfig().Version, nodeConfig, te.LogStream, opts...) if err != nil { return err } @@ -188,6 +193,11 @@ type CleanupOpts struct { func (te *CLClusterTestEnv) Cleanup(opts CleanupOpts) error { te.l.Info().Msg("Cleaning up test environment") + runIdErr := runid.RemoveLocalRunId(te.TestConfig.GetLoggingConfig().RunId) + if runIdErr != nil { + te.l.Warn().Msgf("Failed to remove .run.id file due to: %s (not a big deal, you can still remove it manually)", runIdErr.Error()) + } + if te.t == nil { return fmt.Errorf("cannot cleanup test environment without a testing.T") } diff --git a/integration-tests/docker/test_env/test_env_builder.go b/integration-tests/docker/test_env/test_env_builder.go index e11a3c96095..610c3e29e1e 100644 --- a/integration-tests/docker/test_env/test_env_builder.go +++ b/integration-tests/docker/test_env/test_env_builder.go @@ -4,23 +4,25 @@ import ( "fmt" "os" "path/filepath" + "slices" "strings" - "sync" "testing" "time" "github.com/rs/zerolog" "github.com/rs/zerolog/log" "go.uber.org/zap/zapcore" - "golang.org/x/sync/errgroup" + + "github.com/smartcontractkit/chainlink-testing-framework/seth" "github.com/smartcontractkit/chainlink-testing-framework/lib/blockchain" ctf_config "github.com/smartcontractkit/chainlink-testing-framework/lib/config" - ctf_docker "github.com/smartcontractkit/chainlink-testing-framework/lib/docker" "github.com/smartcontractkit/chainlink-testing-framework/lib/docker/test_env" "github.com/smartcontractkit/chainlink-testing-framework/lib/logging" + "github.com/smartcontractkit/chainlink-testing-framework/lib/logstream" "github.com/smartcontractkit/chainlink-testing-framework/lib/networks" "github.com/smartcontractkit/chainlink-testing-framework/lib/testreporters" + "github.com/smartcontractkit/chainlink-testing-framework/lib/testsummary" "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/osutil" "github.com/smartcontractkit/chainlink/integration-tests/testconfig/ccip" @@ -43,6 +45,7 @@ type ChainlinkNodeLogScannerSettings struct { } type CLTestEnvBuilder struct { + hasLogStream bool hasKillgrave bool jdConfig *ccip.JDConfig clNodeConfig *chainlink.Config @@ -86,6 +89,7 @@ func GetDefaultChainlinkNodeLogScannerSettingsWithExtraAllowedMessages(extraAllo func NewCLTestEnvBuilder() *CLTestEnvBuilder { return &CLTestEnvBuilder{ l: log.Logger, + hasLogStream: true, isEVM: true, chainlinkNodeLogScannerSettings: &DefaultChainlinkNodeLogScannerSettings, } @@ -129,6 +133,12 @@ func (b *CLTestEnvBuilder) WithTestInstance(t *testing.T) *CLTestEnvBuilder { return b } +// WithoutLogStream disables LogStream logging component +func (b *CLTestEnvBuilder) WithoutLogStream() *CLTestEnvBuilder { + b.hasLogStream = false + return b +} + func (b *CLTestEnvBuilder) WithoutChainlinkNodeLogScanner() *CLTestEnvBuilder { b.chainlinkNodeLogScannerSettings = &ChainlinkNodeLogScannerSettings{} return b @@ -239,105 +249,96 @@ func (b *CLTestEnvBuilder) Build() (*CLClusterTestEnv, error) { b.te.WithTestInstance(b.t) } - // this clean up has to be added as the FIRST one, because cleanup functions are executed in reverse order (LIFO) - if b.t != nil && b.cleanUpType != CleanUpTypeNone { - b.t.Cleanup(func() { - logsDir := fmt.Sprintf("logs/%s-%s", b.t.Name(), time.Now().Format("2006-01-02T15-04-05")) - loggingErr := ctf_docker.WriteAllContainersLogs(b.l, logsDir) - if loggingErr != nil { - b.l.Error().Err(loggingErr).Msg("Error writing all Docker containers logs") - } + if b.hasLogStream { + loggingConfig := b.testConfig.GetLoggingConfig() + // we need to enable logging to file if we want to scan logs + if b.chainlinkNodeLogScannerSettings != nil && !slices.Contains(loggingConfig.LogStream.LogTargets, string(logstream.File)) { + b.l.Debug().Msg("Enabling logging to file in order to support Chainlink node log scanning") + loggingConfig.LogStream.LogTargets = append(loggingConfig.LogStream.LogTargets, string(logstream.File)) + } + b.te.LogStream, err = logstream.NewLogStream(b.te.t, b.testConfig.GetLoggingConfig()) + if err != nil { + return nil, err + } - if b == nil || b.te == nil || b.te.ClCluster == nil || b.te.ClCluster.Nodes == nil { - log.Warn().Msg("Won't dump container and postgres logs, because test environment doesn't have any nodes") - return - } + // this clean up has to be added as the FIRST one, because cleanup functions are executed in reverse order (LIFO) + if b.t != nil && b.cleanUpType != CleanUpTypeNone { + b.t.Cleanup(func() { + b.l.Info().Msg("Shutting down LogStream") + logPath, err := osutil.GetAbsoluteFolderPath("logs") + if err == nil { + b.l.Info().Str("Absolute path", logPath).Msg("LogStream logs folder location") + } + + // flush logs when test failed or when we are explicitly told to collect logs + flushLogStream := b.t.Failed() || *b.testConfig.GetLoggingConfig().TestLogCollect - if b.chainlinkNodeLogScannerSettings != nil { - var logFiles []*os.File + // run even if test has failed, as we might be able to catch additional problems without running the test again + if b.chainlinkNodeLogScannerSettings != nil { + logProcessor := logstream.NewLogProcessor[int](b.te.LogStream) + + processFn := func(log logstream.LogContent, count *int) error { + countSoFar := count + newCount, err := testreporters.ScanLogLine(b.l, string(log.Content), b.chainlinkNodeLogScannerSettings.FailingLogLevel, uint(*countSoFar), b.chainlinkNodeLogScannerSettings.Threshold, b.chainlinkNodeLogScannerSettings.AllowedMessages) + if err != nil { + return err + } + *count = int(newCount) + return nil + } - // when tests run in parallel, we need to make sure that we only process logs that belong to nodes created by the current test - // that is required, because some tests might have custom log messages that are allowed, but only for that test (e.g. because they restart the CL node) - var belongsToCurrentEnv = func(filePath string) bool { - for _, clNode := range b.te.ClCluster.Nodes { - if clNode == nil { + // we cannot do parallel processing here, because ProcessContainerLogs() locks a mutex that controls whether + // new logs can be added to the log stream, so parallel processing would get stuck on waiting for it to be unlocked + LogScanningLoop: + for i := 0; i < b.clNodesCount; i++ { + // if something went wrong during environment setup we might not have all nodes, and we don't want an NPE + if b == nil || b.te == nil || b.te.ClCluster == nil || b.te.ClCluster.Nodes == nil || len(b.te.ClCluster.Nodes)-1 < i || b.te.ClCluster.Nodes[i] == nil { continue } - if strings.EqualFold(filePath, clNode.ContainerName+".log") { - return true + // ignore count return, because we are only interested in the error + _, err := logProcessor.ProcessContainerLogs(b.te.ClCluster.Nodes[i].ContainerName, processFn) + if err != nil && !strings.Contains(err.Error(), testreporters.MultipleLogsAtLogLevelErr) && !strings.Contains(err.Error(), testreporters.OneLogAtLogLevelErr) { + b.l.Error().Err(err).Msg("Error processing CL node logs") + continue + } else if err != nil && (strings.Contains(err.Error(), testreporters.MultipleLogsAtLogLevelErr) || strings.Contains(err.Error(), testreporters.OneLogAtLogLevelErr)) { + flushLogStream = true + b.t.Errorf("Found a concerning log in Chainklink Node logs: %v", err) + break LogScanningLoop } } - return false + b.l.Info().Msg("Finished scanning Chainlink Node logs for concerning errors") } - fileWalkErr := filepath.Walk(logsDir, func(path string, info os.FileInfo, err error) error { - if err != nil { - return err + if flushLogStream { + b.l.Info().Msg("Flushing LogStream logs") + // we can't do much if this fails, so we just log the error in LogStream + if err := b.te.LogStream.FlushAndShutdown(); err != nil { + b.l.Error().Err(err).Msg("Error flushing and shutting down LogStream") } - if !info.IsDir() && belongsToCurrentEnv(info.Name()) { - file, fileErr := os.Open(path) - if fileErr != nil { - return fmt.Errorf("failed to open file %s: %w", path, fileErr) - } - logFiles = append(logFiles, file) - } - return nil - }) - - if len(logFiles) != len(b.te.ClCluster.Nodes) { - b.l.Warn().Int("Expected", len(b.te.ClCluster.Nodes)).Int("Got", len(logFiles)).Msg("Number of log files does not match number of nodes. Some logs might be missing.") + b.te.LogStream.PrintLogTargetsLocations() + b.te.LogStream.SaveLogLocationInTestSummary() } + b.l.Info().Msg("Finished shutting down LogStream") - if fileWalkErr != nil { - b.l.Error().Err(fileWalkErr).Msg("Error walking through log files. Skipping log verification.") - } else { - verifyLogsGroup := &errgroup.Group{} - for _, f := range logFiles { - file := f - verifyLogsGroup.Go(func() error { - verifyErr := testreporters.VerifyLogFile(file, b.chainlinkNodeLogScannerSettings.FailingLogLevel, b.chainlinkNodeLogScannerSettings.Threshold, b.chainlinkNodeLogScannerSettings.AllowedMessages...) - _ = file.Close() - // ignore processing errors - if verifyErr != nil && !strings.Contains(verifyErr.Error(), testreporters.MultipleLogsAtLogLevelErr) && !strings.Contains(verifyErr.Error(), testreporters.OneLogAtLogLevelErr) { - b.l.Error().Err(verifyErr).Msg("Error processing CL node logs") - - return nil - - // if it's not a processing error, we want to fail the test; we also can stop processing logs all together at this point - } else if verifyErr != nil && (strings.Contains(verifyErr.Error(), testreporters.MultipleLogsAtLogLevelErr) || strings.Contains(verifyErr.Error(), testreporters.OneLogAtLogLevelErr)) { - - return verifyErr - } - return nil - }) - } + if b.t.Failed() || *b.testConfig.GetLoggingConfig().TestLogCollect { + b.l.Info().Msg("Dump state of all Postgres DBs used by Chainlink Nodes") - if logVerificationErr := verifyLogsGroup.Wait(); logVerificationErr != nil { - b.t.Errorf("Found a concerning log in Chainklink Node logs: %v", logVerificationErr) + dbDumpFolder := "db_dumps" + dbDumpPath := fmt.Sprintf("%s/%s-%s", dbDumpFolder, b.t.Name(), time.Now().Format("2006-01-02T15-04-05")) + if err := os.MkdirAll(dbDumpPath, os.ModePerm); err != nil { + b.l.Error().Err(err).Msg("Error creating folder for Postgres DB dump") + return } - } - } - b.l.Info().Msg("Staring to dump state of all Postgres DBs used by Chainlink Nodes") - - dbDumpFolder := "db_dumps" - dbDumpPath := fmt.Sprintf("%s/%s-%s", dbDumpFolder, b.t.Name(), time.Now().Format("2006-01-02T15-04-05")) - if err := os.MkdirAll(dbDumpPath, os.ModePerm); err != nil { - b.l.Error().Err(err).Msg("Error creating folder for Postgres DB dump") - } else { - absDbDumpPath, err := osutil.GetAbsoluteFolderPath(dbDumpFolder) - if err == nil { - b.l.Info().Str("Absolute path", absDbDumpPath).Msg("PostgresDB dump folder location") - } + absDbDumpPath, err := osutil.GetAbsoluteFolderPath(dbDumpFolder) + if err == nil { + b.l.Info().Str("Absolute path", absDbDumpPath).Msg("PostgresDB dump folder location") + } - dbDumpGroup := sync.WaitGroup{} - for i := 0; i < b.clNodesCount; i++ { - dbDumpGroup.Add(1) - go func() { - defer dbDumpGroup.Done() + for i := 0; i < b.clNodesCount; i++ { // if something went wrong during environment setup we might not have all nodes, and we don't want an NPE if b == nil || b.te == nil || b.te.ClCluster == nil || b.te.ClCluster.Nodes == nil || len(b.te.ClCluster.Nodes)-1 < i || b.te.ClCluster.Nodes[i] == nil || b.te.ClCluster.Nodes[i].PostgresDb == nil { - return + continue } filePath := filepath.Join(dbDumpPath, fmt.Sprintf("postgres_db_dump_%s.sql", b.te.ClCluster.Nodes[i].ContainerName)) @@ -345,23 +346,24 @@ func (b *CLTestEnvBuilder) Build() (*CLClusterTestEnv, error) { if err != nil { b.l.Error().Err(err).Msg("Error creating localDbDumpFile for Postgres DB dump") _ = localDbDumpFile.Close() - return + continue } if err := b.te.ClCluster.Nodes[i].PostgresDb.ExecPgDumpFromContainer(localDbDumpFile); err != nil { b.l.Error().Err(err).Msg("Error dumping Postgres DB") } _ = localDbDumpFile.Close() - }() + } + b.l.Info().Msg("Finished dumping state of all Postgres DBs used by Chainlink Nodes") } - dbDumpGroup.Wait() - - b.l.Info().Msg("Finished dumping state of all Postgres DBs used by Chainlink Nodes") - } - }) - } else { - b.l.Warn().Msg("Won't dump container and postgres logs, because either test instance is not set or cleanup type is set to none") + if b.testConfig.GetSethConfig() != nil && ((b.t.Failed() && slices.Contains(b.testConfig.GetSethConfig().TraceOutputs, seth.TraceOutput_DOT) && b.testConfig.GetSethConfig().TracingLevel != seth.TracingLevel_None) || (!b.t.Failed() && slices.Contains(b.testConfig.GetSethConfig().TraceOutputs, seth.TraceOutput_DOT) && b.testConfig.GetSethConfig().TracingLevel == seth.TracingLevel_All)) { + _ = testsummary.AddEntry(b.t.Name(), "dot_graphs", "true") + } + }) + } else { + b.l.Warn().Msg("LogStream won't be cleaned up, because either test instance is not set or cleanup type is set to none") + } } if b.hasKillgrave { @@ -369,7 +371,7 @@ func (b *CLTestEnvBuilder) Build() (*CLClusterTestEnv, error) { return nil, fmt.Errorf("test environment builder failed: %w", fmt.Errorf("cannot start mock adapter without a network")) } - b.te.MockAdapter = test_env.NewKillgrave([]string{b.te.DockerNetwork.Name}, "") + b.te.MockAdapter = test_env.NewKillgrave([]string{b.te.DockerNetwork.Name}, "", test_env.WithLogStream(b.te.LogStream)) err = b.te.StartMockAdapter() if err != nil { @@ -397,6 +399,10 @@ func (b *CLTestEnvBuilder) Build() (*CLClusterTestEnv, error) { return b.te, fmt.Errorf("test environment builder failed: %w", fmt.Errorf("explicit cleanup type must be set when building test environment")) } + if b.te.LogStream == nil && b.chainlinkNodeLogScannerSettings != nil { + log.Warn().Msg("Chainlink node log scanner settings provided, but LogStream is not enabled. Ignoring Chainlink node log scanner settings, as no logs will be available.") + } + if b.jdConfig != nil { err := b.te.StartJobDistributor(b.jdConfig) if err != nil { @@ -488,7 +494,7 @@ func (b *CLTestEnvBuilder) Build() (*CLClusterTestEnv, error) { b.te.EVMNetworks = append(b.te.EVMNetworks, &networkConfig) if b.isEVM { - if len(b.evmNetworkOption) > 0 { + if b.evmNetworkOption != nil && len(b.evmNetworkOption) > 0 { for _, fn := range b.evmNetworkOption { fn(&networkConfig) } diff --git a/integration-tests/example.env b/integration-tests/example.env index fbc9a76091e..35db6263644 100644 --- a/integration-tests/example.env +++ b/integration-tests/example.env @@ -3,7 +3,6 @@ ########## General Test Settings ########## export CHAINLINK_ENV_USER="Satoshi-Nakamoto" # Name of the person running the tests (change to your own) -export CHAINLINK_USER_TEAM="My awesome team" # Name of the team you are running the test for (change to your own) export TEST_LOG_LEVEL="info" # info | debug | trace ########## Soak/Chaos/Load Test Specific Settings ########## @@ -17,7 +16,6 @@ export SLACK_API_KEY="xoxb-example-key" # API key used to report soak test resul export SLACK_CHANNEL="C000000000" # Channel ID for the slack bot to post test results export SLACK_USER="U000000000" # User ID of the person running the soak tests to properly notify them -##### ---- applicable only, when using legacy EVMClient ---- ##### ########## Network Settings ########## # General EVM Settings, used only for quick prototyping when using GENERAL as the SELECTED_NETWORK export EVM_NAME="General EVM" diff --git a/integration-tests/go.mod b/integration-tests/go.mod index 86b89b82582..e3054210700 100644 --- a/integration-tests/go.mod +++ b/integration-tests/go.mod @@ -1,26 +1,16 @@ module github.com/smartcontractkit/chainlink/integration-tests -go 1.23.3 - -toolchain go1.23.4 +go 1.22.8 // Make sure we're working with the latest chainlink libs replace github.com/smartcontractkit/chainlink/v2 => ../ replace github.com/smartcontractkit/chainlink/deployment => ../deployment -// Using a separate `require` here to avoid surrounding line changes -// creating potential merge conflicts. -require ( - github.com/smartcontractkit/chainlink/deployment v0.0.0-20241206210521-125d98cdaf66 - github.com/smartcontractkit/chainlink/v2 v2.0.0-20241206210521-125d98cdaf66 -) - require ( dario.cat/mergo v1.0.1 github.com/AlekSi/pointer v1.1.0 github.com/Masterminds/semver/v3 v3.3.0 - github.com/avast/retry-go v3.0.0+incompatible github.com/avast/retry-go/v4 v4.6.0 github.com/barkimedes/go-deepcopy v0.0.0-20220514131651-17c30cfc62df github.com/chaos-mesh/chaos-mesh/api v0.0.0-20240821051457-da69c6d9617a @@ -44,16 +34,18 @@ require ( github.com/segmentio/ksuid v1.0.4 github.com/shopspring/decimal v1.4.0 github.com/slack-go/slack v0.15.0 - github.com/smartcontractkit/chain-selectors v1.0.34 + github.com/smartcontractkit/chain-selectors v1.0.29 github.com/smartcontractkit/chainlink-automation v0.8.1 - github.com/smartcontractkit/chainlink-ccip v0.0.0-20241218114855-f74219171000 - github.com/smartcontractkit/chainlink-common v0.4.1-0.20241217120918-bbe318cd0760 - github.com/smartcontractkit/chainlink-protos/job-distributor v0.6.0 + github.com/smartcontractkit/chainlink-ccip v0.0.0-20241118091009-43c2b4804cec + github.com/smartcontractkit/chainlink-common v0.3.1-0.20241114134822-aadff98ef068 + github.com/smartcontractkit/chainlink-protos/job-distributor v0.4.0 github.com/smartcontractkit/chainlink-testing-framework/havoc v1.50.2 - github.com/smartcontractkit/chainlink-testing-framework/lib v1.50.19 + github.com/smartcontractkit/chainlink-testing-framework/lib v1.50.13 github.com/smartcontractkit/chainlink-testing-framework/lib/grafana v1.50.0 - github.com/smartcontractkit/chainlink-testing-framework/seth v1.50.9 + github.com/smartcontractkit/chainlink-testing-framework/seth v1.50.5 github.com/smartcontractkit/chainlink-testing-framework/wasp v1.50.2 + github.com/smartcontractkit/chainlink/deployment v0.0.0-00010101000000-000000000000 + github.com/smartcontractkit/chainlink/v2 v2.14.0-mercury-20240807.0.20241106193309-5560cd76211a github.com/smartcontractkit/libocr v0.0.0-20241007185508-adbe57025f12 github.com/spf13/cobra v1.8.1 github.com/stretchr/testify v1.9.0 @@ -64,13 +56,13 @@ require ( go.uber.org/atomic v1.11.0 go.uber.org/multierr v1.11.0 go.uber.org/zap v1.27.0 - golang.org/x/crypto v0.31.0 + golang.org/x/crypto v0.28.0 golang.org/x/exp v0.0.0-20241009180824-f66d83c29e7c - golang.org/x/sync v0.10.0 - golang.org/x/text v0.21.0 + golang.org/x/sync v0.8.0 + golang.org/x/text v0.19.0 google.golang.org/grpc v1.67.1 gopkg.in/guregu/null.v4 v4.0.0 - k8s.io/apimachinery v0.31.2 + k8s.io/apimachinery v0.31.1 ) require ( @@ -93,8 +85,6 @@ require ( github.com/CosmWasm/wasmd v0.40.1 // indirect github.com/CosmWasm/wasmvm v1.2.4 // indirect github.com/DataDog/zstd v1.5.2 // indirect - github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.25.0 // indirect - github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.49.0 // indirect github.com/Khan/genqlient v0.7.0 // indirect github.com/MakeNowJust/heredoc v1.0.0 // indirect github.com/Masterminds/goutils v1.1.1 // indirect @@ -105,10 +95,11 @@ require ( github.com/VictoriaMetrics/fastcache v1.12.2 // indirect github.com/XSAM/otelsql v0.27.0 // indirect github.com/alecthomas/units v0.0.0-20240626203959-61d1e3462e30 // indirect - github.com/andybalholm/brotli v1.1.1 // indirect + github.com/andybalholm/brotli v1.1.0 // indirect github.com/armon/go-metrics v0.4.1 // indirect github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect github.com/atombender/go-jsonschema v0.16.1-0.20240916205339-a74cd4e2851c // indirect + github.com/avast/retry-go v3.0.0+incompatible // indirect github.com/awalterschulze/gographviz v2.0.3+incompatible // indirect github.com/aws/aws-sdk-go v1.54.19 // indirect github.com/aws/aws-sdk-go-v2 v1.32.2 // indirect @@ -245,7 +236,7 @@ require ( github.com/go-viper/mapstructure/v2 v2.1.0 // indirect github.com/go-webauthn/webauthn v0.9.4 // indirect github.com/go-webauthn/x v0.1.5 // indirect - github.com/goccy/go-json v0.10.3 // indirect + github.com/goccy/go-json v0.10.2 // indirect github.com/goccy/go-yaml v1.12.0 // indirect github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2 // indirect github.com/gofrs/flock v0.8.1 // indirect @@ -266,7 +257,6 @@ require ( github.com/google/gofuzz v1.2.0 // indirect github.com/google/pprof v0.0.0-20240827171923-fa2c70bbbfe5 // indirect github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect - github.com/googleapis/gax-go/v2 v2.14.0 // indirect github.com/gorilla/context v1.1.1 // indirect github.com/gorilla/mux v1.8.0 // indirect github.com/gorilla/securecookie v1.1.2 // indirect @@ -337,12 +327,12 @@ require ( github.com/json-iterator/go v1.1.12 // indirect github.com/julienschmidt/httprouter v1.3.0 // indirect github.com/kelseyhightower/envconfig v1.4.0 // indirect - github.com/klauspost/compress v1.17.11 // indirect - github.com/klauspost/cpuid/v2 v2.2.8 // indirect + github.com/klauspost/compress v1.17.9 // indirect + github.com/klauspost/cpuid/v2 v2.2.7 // indirect github.com/kr/pretty v0.3.1 // indirect github.com/kr/text v0.2.0 // indirect github.com/kylelemons/godebug v1.1.0 // indirect - github.com/leanovate/gopter v0.2.11 // indirect + github.com/leanovate/gopter v0.2.10-0.20210127095200-9abe2343507a // indirect github.com/leodido/go-urn v1.4.0 // indirect github.com/libp2p/go-buffer-pool v0.1.0 // indirect github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de // indirect @@ -408,7 +398,7 @@ require ( github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect github.com/rivo/uniseg v0.4.4 // indirect github.com/robfig/cron/v3 v3.0.1 // indirect - github.com/rogpeppe/go-internal v1.13.1 // indirect + github.com/rogpeppe/go-internal v1.12.0 // indirect github.com/rs/cors v1.10.1 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/sagikazarmark/locafero v0.4.0 // indirect @@ -423,17 +413,17 @@ require ( github.com/shirou/gopsutil/v3 v3.24.3 // indirect github.com/shoenig/go-m1cpu v0.1.6 // indirect github.com/sirupsen/logrus v1.9.3 // indirect - github.com/smartcontractkit/ccip-owner-contracts v0.0.0-salt-fix // indirect - github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241202195413-82468150ac1e // indirect - github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20241216163550-fa030d178ba3 // indirect + github.com/smartcontractkit/ccip-owner-contracts v0.0.0-20240926212305-a6deabdfce86 // indirect + github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241017133723-5277829bd53f // indirect + github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20241018134907-a00ba3729b5e // indirect github.com/smartcontractkit/chainlink-feeds v0.1.1 // indirect - github.com/smartcontractkit/chainlink-protos/orchestrator v0.4.0 // indirect - github.com/smartcontractkit/chainlink-solana v1.1.1-0.20241219173444-150f7443fdd3 // indirect - github.com/smartcontractkit/chainlink-starknet/relayer v0.1.1-0.20241202202529-2033490e77b8 // indirect + github.com/smartcontractkit/chainlink-protos/orchestrator v0.3.0 // indirect + github.com/smartcontractkit/chainlink-solana v1.1.1-0.20241115191142-8b8369c1f44e // indirect + github.com/smartcontractkit/chainlink-starknet/relayer v0.1.1-0.20241017135645-176a23722fd8 // indirect github.com/smartcontractkit/grpc-proxy v0.0.0-20240830132753-a7e17fec5ab7 // indirect github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20241009055228-33d0c0bf38de // indirect github.com/smartcontractkit/tdh2/go/tdh2 v0.0.0-20241009055228-33d0c0bf38de // indirect - github.com/smartcontractkit/wsrpc v0.8.3 // indirect + github.com/smartcontractkit/wsrpc v0.8.2 // indirect github.com/soheilhy/cmux v0.1.5 // indirect github.com/sony/gobreaker v0.5.0 // indirect github.com/sourcegraph/conc v0.3.0 // indirect @@ -509,17 +499,16 @@ require ( golang.org/x/mod v0.21.0 // indirect golang.org/x/net v0.30.0 // indirect golang.org/x/oauth2 v0.23.0 // indirect - golang.org/x/sys v0.28.0 // indirect - golang.org/x/term v0.27.0 // indirect + golang.org/x/sys v0.26.0 // indirect + golang.org/x/term v0.25.0 // indirect golang.org/x/time v0.7.0 // indirect golang.org/x/tools v0.26.0 // indirect golang.org/x/xerrors v0.0.0-20240903120638-7835f813f4da // indirect gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect gonum.org/v1/gonum v0.15.1 // indirect - google.golang.org/api v0.205.0 // indirect google.golang.org/genproto v0.0.0-20241021214115-324edc3d5d38 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20241104194629-dd2ea8efbc28 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20241104194629-dd2ea8efbc28 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20241021214115-324edc3d5d38 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20241021214115-324edc3d5d38 // indirect google.golang.org/protobuf v1.35.1 // indirect gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect gopkg.in/inf.v0 v0.9.1 // indirect @@ -527,14 +516,14 @@ require ( gopkg.in/natefinch/lumberjack.v2 v2.2.1 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect - k8s.io/api v0.31.2 // indirect + k8s.io/api v0.31.1 // indirect k8s.io/apiextensions-apiserver v0.31.0 // indirect - k8s.io/cli-runtime v0.31.2 // indirect - k8s.io/client-go v0.31.2 // indirect - k8s.io/component-base v0.31.2 // indirect + k8s.io/cli-runtime v0.31.1 // indirect + k8s.io/client-go v0.31.1 // indirect + k8s.io/component-base v0.31.1 // indirect k8s.io/klog/v2 v2.130.1 // indirect k8s.io/kube-openapi v0.0.0-20240709000822-3c01b740850f // indirect - k8s.io/kubectl v0.31.2 // indirect + k8s.io/kubectl v0.31.1 // indirect k8s.io/utils v0.0.0-20240711033017-18e509b52bc8 // indirect pgregory.net/rapid v1.1.0 // indirect rsc.io/tmplfunc v0.0.3 // indirect diff --git a/integration-tests/go.sum b/integration-tests/go.sum index b2101edcd73..b2ea8488a23 100644 --- a/integration-tests/go.sum +++ b/integration-tests/go.sum @@ -16,17 +16,12 @@ cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKV cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs= cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc= cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= -cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI= -cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk= -cloud.google.com/go v0.78.0/go.mod h1:QjdrLG0uq+YwhjoVOLsS1t7TW8fs36kLs4XO5R5ECHg= -cloud.google.com/go v0.79.0/go.mod h1:3bzgcEeQlzbuEAYu4mrWhKqWjmpprinYgKJLgKHnbb8= -cloud.google.com/go v0.81.0/go.mod h1:mk/AM35KwGk/Nm2YSeZbxXdrNK3KZOYHmLkOqC2V6E0= cloud.google.com/go v0.116.0 h1:B3fRrSDkLRt5qSHWe40ERJvhvnQwdZiHu0bJOpldweE= cloud.google.com/go v0.116.0/go.mod h1:cEPSRWPzZEswwdr9BxE6ChEn01dWlTaF05LiC2Xs70U= -cloud.google.com/go/auth v0.10.1 h1:TnK46qldSfHWt2a0b/hciaiVJsmDXWy9FqyUan0uYiI= -cloud.google.com/go/auth v0.10.1/go.mod h1:xxA5AqpDrvS+Gkmo9RqrGGRh6WSNKKOXhY3zNOr38tI= -cloud.google.com/go/auth/oauth2adapt v0.2.5 h1:2p29+dePqsCHPP1bqDJcKj4qxRyYCcbzKpFyKGt3MTk= -cloud.google.com/go/auth/oauth2adapt v0.2.5/go.mod h1:AlmsELtlEBnaNTL7jCj8VQFLy6mbZv0s4Q7NGBeQ5E8= +cloud.google.com/go/auth v0.9.9 h1:BmtbpNQozo8ZwW2t7QJjnrQtdganSdmqeIBxHxNkEZQ= +cloud.google.com/go/auth v0.9.9/go.mod h1:xxA5AqpDrvS+Gkmo9RqrGGRh6WSNKKOXhY3zNOr38tI= +cloud.google.com/go/auth/oauth2adapt v0.2.3 h1:MlxF+Pd3OmSudg/b1yZ5lJwoXCEaeedAguodky1PcKI= +cloud.google.com/go/auth/oauth2adapt v0.2.3/go.mod h1:tMQXOfZzFuNuUxOypHlQEXgdfX5cuhwU+ffUuXRJE8I= cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= @@ -34,8 +29,8 @@ cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUM cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= cloud.google.com/go/compute v1.28.1 h1:XwPcZjgMCnU2tkwY10VleUjSAfpTj9RDn+kGrbYsi8o= -cloud.google.com/go/compute/metadata v0.5.2 h1:UxK4uu/Tn+I3p2dYWTfiX4wva7aYlKixAHn3fyqngqo= -cloud.google.com/go/compute/metadata v0.5.2/go.mod h1:C66sj2AluDcIqakBq/M8lw8/ybHgOZqin2obFxa/E5k= +cloud.google.com/go/compute/metadata v0.5.0 h1:Zr0eK8JbFv6+Wi4ilXAR8FJ3wyNdpxHKJNPos6LTZOY= +cloud.google.com/go/compute/metadata v0.5.0/go.mod h1:aHnloV2TPI38yx4s9+wAZhHykWvVCfu7hQbF+9CWoiY= cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= cloud.google.com/go/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk= @@ -120,12 +115,12 @@ github.com/Depado/ginprom v1.8.0 h1:zaaibRLNI1dMiiuj1MKzatm8qrcHzikMlCc1anqOdyo= github.com/Depado/ginprom v1.8.0/go.mod h1:XBaKzeNBqPF4vxJpNLincSQZeMDnZp1tIbU0FU0UKgg= github.com/GeertJohan/go.incremental v1.0.0/go.mod h1:6fAjUhbVuX1KcMD3c8TEgVUqmo4seqhv0i0kdATSkM0= github.com/GeertJohan/go.rice v1.0.0/go.mod h1:eH6gbSOAUv07dQuZVnBmoDP8mgsM1rtixis4Tib9if0= -github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.25.0 h1:3c8yed4lgqTt+oTQ+JNMDo+F4xprBf+O/il4ZC0nRLw= -github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.25.0/go.mod h1:obipzmGjfSjam60XLwGfqUkJsfiheAl+TUjG+4yzyPM= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.24.3 h1:cb3br57K508pQEFgBxn9GDhPS9HefpyMPK1RzmtMNzk= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.24.3/go.mod h1:itPGVDKf9cC/ov4MdvJ2QZ0khw4bfoo9jzwTJlaxy2k= github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.48.3 h1:xir5X8TS8UBVPWg2jHL+cSTf0jZgqYQSA54TscSt1/0= github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.48.3/go.mod h1:SsdWig2J5PMnfMvfJuEb1uZa8Y+kvNyvrULFo69gTFk= -github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.49.0 h1:GYUJLfvd++4DMuMhCFLgLXvFwofIxh/qOwoGuS/LTew= -github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.49.0/go.mod h1:wRbFgBQUVm1YXrvWKofAEmq9HNJTDphbAaJSSX01KUI= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.48.3 h1:2vcVkrNdSMJpoOVAWi9ApsQR5iqNeFGt5Qx8Xlt3IoI= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.48.3/go.mod h1:wRbFgBQUVm1YXrvWKofAEmq9HNJTDphbAaJSSX01KUI= github.com/HdrHistogram/hdrhistogram-go v1.1.2 h1:5IcZpTvzydCQeHzK4Ef/D5rrSqwxob0t8PQPMybUNFM= github.com/HdrHistogram/hdrhistogram-go v1.1.2/go.mod h1:yDgFjdqOqDEKOvasDdhWNXYg9BVp4O+o5f6V/ehm6Oo= github.com/Khan/genqlient v0.7.0 h1:GZ1meyRnzcDTK48EjqB8t3bcfYvHArCUUvgOwpz1D4w= @@ -180,11 +175,9 @@ github.com/allegro/bigcache v1.2.1/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2uc github.com/andres-erbsen/clock v0.0.0-20160526145045-9e14626cd129/go.mod h1:rFgpPQZYZ8vdbc+48xibu8ALc3yeyd64IhHS+PU6Yyg= github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883 h1:bvNMNQO63//z+xNgfBlViaCIJKLlCJ6/fmUseuG0wVQ= github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8= -github.com/andybalholm/brotli v1.1.1 h1:PR2pgnyFznKEugtsUo0xLdDop5SKXd5Qf5ysW+7XdTA= -github.com/andybalholm/brotli v1.1.1/go.mod h1:05ib4cKhjx3OQYUY22hTVd34Bc8upXjOLL2rKwwZBoA= +github.com/andybalholm/brotli v1.1.0 h1:eLKJA0d02Lf0mVpIDgYnqXcUn0GqVmEFny3VuID1U3M= +github.com/andybalholm/brotli v1.1.0/go.mod h1:sms7XGricyQI9K10gOSf56VKKWS4oLer58Q+mhRPtnY= github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= -github.com/apache/arrow-go/v18 v18.0.0 h1:1dBDaSbH3LtulTyOVYaBCHO3yVRwjV+TZaqn3g6V7ZM= -github.com/apache/arrow-go/v18 v18.0.0/go.mod h1:t6+cWRSmKgdQ6HsxisQjok+jBpKGhRDiqcf3p0p/F+A= github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= @@ -262,7 +255,6 @@ github.com/bgentry/speakeasy v0.1.1-0.20220910012023-760eaf8b6816/go.mod h1:+zsy github.com/bits-and-blooms/bitset v1.13.0 h1:bAQ9OPNFYbGHV6Nez0tmNI0RiEu7/hxlYJRUA0wFAVE= github.com/bits-and-blooms/bitset v1.13.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8= github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84= -github.com/bketelsen/crypt v0.0.4/go.mod h1:aI6NrJ0pMGgvZKL1iVgXLnfIFJtfV+bKCoqOes/6LfM= github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM= github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ= github.com/blendle/zapdriver v1.3.1 h1:C3dydBOWYRiOk+B8X9IVZ5IOe+7cl+tGOexN4QqHfpE= @@ -270,10 +262,10 @@ github.com/blendle/zapdriver v1.3.1/go.mod h1:mdXfREi6u5MArG4j9fewC+FGnXaBR+T4Ox github.com/btcsuite/btcd v0.22.1 h1:CnwP9LM/M9xuRrGSCGeMVs9iv09uMqwsVX7EeIpgV2c= github.com/btcsuite/btcd/btcec/v2 v2.3.2 h1:5n0X6hX0Zk+6omWcihdYvdAlGf2DfasC0GMf7DClJ3U= github.com/btcsuite/btcd/btcec/v2 v2.3.2/go.mod h1:zYzJ8etWJQIv1Ogk7OzpWjowwOdXY1W/17j2MW85J04= -github.com/btcsuite/btcd/btcutil v1.1.5 h1:+wER79R5670vs/ZusMTF1yTcRYE5GUsFbdjdisflzM8= -github.com/btcsuite/btcd/btcutil v1.1.5/go.mod h1:PSZZ4UitpLBWzxGd5VGOrLnmOjtPP/a6HaFo12zMs00= -github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0 h1:59Kx4K6lzOW5w6nFlA0v5+lk/6sjybR934QNHSJZPTQ= -github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= +github.com/btcsuite/btcd/btcutil v1.1.3 h1:xfbtw8lwpp0G6NwSHb+UE67ryTFHJAiNuipusjXSohQ= +github.com/btcsuite/btcd/btcutil v1.1.3/go.mod h1:UR7dsSJzJUfMmFiiLlIrMq1lS9jh9EdCV7FStZSnpi0= +github.com/btcsuite/btcd/chaincfg/chainhash v1.0.3 h1:SDlJ7bAm4ewvrmZtR0DaiYbQGdKPeaaIm7bM+qRhFeU= +github.com/btcsuite/btcd/chaincfg/chainhash v1.0.3/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= github.com/bufbuild/protocompile v0.4.0 h1:LbFKd2XowZvQ/kajzguUp2DC9UEIQhIq77fZZlaQsNA= github.com/bufbuild/protocompile v0.4.0/go.mod h1:3v93+mbWn/v3xzN+31nwkJfrEpAUwp+BagBSZWx+TP8= github.com/buger/jsonparser v1.1.1 h1:2PnMjfWD7wBILjqQbt530v576A/cAbQvEW9gGIpYMUs= @@ -334,7 +326,6 @@ github.com/cloudwego/base64x v0.1.4/go.mod h1:0zlkT4Wn5C6NdauXdJRhSKRlJvmclQ1hhJ github.com/cloudwego/iasm v0.2.0 h1:1KNIy1I1H9hNNFEEH3DVnI4UujN+1zjpuk6gwHLTssg= github.com/cloudwego/iasm v0.2.0/go.mod h1:8rXZaNYT2n95jn+zTI1sDr+IgcD2GVs0nlbbQPiEFhY= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= -github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cncf/xds/go v0.0.0-20240723142845-024c85f92f20 h1:N+3sFI5GUjRKBi+i0TxYVST9h4Ie192jJWpHvthBBgg= github.com/cncf/xds/go v0.0.0-20240723142845-024c85f92f20/go.mod h1:W+zGtBO5Y1IgJhy4+A9GOqVhqLpfZi+vwmdNXUehLA8= @@ -386,7 +377,6 @@ github.com/coreos/go-semver v0.3.1 h1:yi21YpKnrx1gt5R+la8n5WgS0kCrsPp33dmEyHReZr github.com/coreos/go-semver v0.3.1/go.mod h1:irMmmIw/7yzSRPWryHsK7EYSg09caPQL03VsM8rvUec= github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= -github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs= github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= @@ -491,9 +481,7 @@ github.com/emicklei/go-restful/v3 v3.12.1/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRr github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= -github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po= github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= -github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= github.com/envoyproxy/go-control-plane v0.13.0 h1:HzkeUz1Knt+3bK+8LG1bxOO/jzWZmdxpwC51i202les= github.com/envoyproxy/go-control-plane v0.13.0/go.mod h1:GRaKG3dwvFoTg4nj7aXdZnvMg4d7nvT/wl9WgVXn3Q8= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= @@ -552,8 +540,8 @@ github.com/gedex/inflector v0.0.0-20170307190818-16278e9db813/go.mod h1:P+oSoE9y github.com/getsentry/sentry-go v0.27.0 h1:Pv98CIbtB3LkMWmXi4Joa5OOcwbmnX88sF5qbK3r3Ps= github.com/getsentry/sentry-go v0.27.0/go.mod h1:lc76E2QywIyW8WuBnwl8Lc4bkmQH4+w1gwTf25trprY= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= -github.com/gin-contrib/cors v1.7.2 h1:oLDHxdg8W/XDoN/8zamqk/Drgt4oVZDvaV0YmvVICQw= -github.com/gin-contrib/cors v1.7.2/go.mod h1:SUJVARKgQ40dmrzgXEVxj2m7Ig1v1qIboQkPDTQ9t2E= +github.com/gin-contrib/cors v1.5.0 h1:DgGKV7DDoOn36DFkNtbHrjoRiT5ExCe+PC9/xp7aKvk= +github.com/gin-contrib/cors v1.5.0/go.mod h1:TvU7MAZ3EwrPLI2ztzTt3tqgvBCq+wn8WpZmfADjupI= github.com/gin-contrib/expvar v0.0.1 h1:IuU5ArEgihz50vG8Onrwz22kJr7Mcvgv9xSSpfU5g+w= github.com/gin-contrib/expvar v0.0.1/go.mod h1:8o2CznfQi1JjktORdHr2/abg3wSV6OCnXh0yGypvvVw= github.com/gin-contrib/sessions v0.0.5 h1:CATtfHmLMQrMNpJRgzjWXD7worTh7g7ritsQfmF+0jE= @@ -644,8 +632,8 @@ github.com/go-webauthn/x v0.1.5 h1:V2TCzDU2TGLd0kSZOXdrqDVV5JB9ILnKxA9S53CSBw0= github.com/go-webauthn/x v0.1.5/go.mod h1:qbzWwcFcv4rTwtCLOZd+icnr6B7oSsAGZJqlt8cukqY= github.com/go-zookeeper/zk v1.0.3 h1:7M2kwOsc//9VeeFiPtf+uSJlVpU66x9Ba5+8XK7/TDg= github.com/go-zookeeper/zk v1.0.3/go.mod h1:nOB03cncLtlp4t+UAkGSV+9beXP/akpekBwL+UX1Qcw= -github.com/goccy/go-json v0.10.3 h1:KZ5WoDbxAIgm2HNbYckL0se1fHD6rz5j4ywS6ebzDqA= -github.com/goccy/go-json v0.10.3/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M= +github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU= +github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= github.com/goccy/go-yaml v1.12.0 h1:/1WHjnMsI1dlIBQutrvSMGZRQufVO3asrHfTwfACoPM= github.com/goccy/go-yaml v1.12.0/go.mod h1:wKnAMd44+9JAAnGQpWVEgBzGt3YuTaQ4uXoHvE4m7WU= github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2 h1:ZpnhV/YsD2/4cESfV5+Hoeu/iUR3ruzNvZ+yQfO03a0= @@ -681,7 +669,6 @@ github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= -github.com/golang/mock v1.5.0/go.mod h1:CWnOUgYIOo4TcNZ0wHX3YZCqsaM1I1Jvs6v3mP3KVu8= github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc= github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= @@ -713,8 +700,6 @@ github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Z github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.1.2 h1:xf4v41cLI2Z6FxbKm+8Bu+m8ifhj15JuZ9sa0jZCMUU= github.com/google/btree v1.1.2/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4= -github.com/google/flatbuffers v24.3.25+incompatible h1:CX395cjN9Kke9mmalRoL3d81AtFUxJM+yDthflgJGkI= -github.com/google/flatbuffers v24.3.25+incompatible/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8= github.com/google/gnostic-models v0.6.9-0.20230804172637-c7be7c783f49 h1:0VpGH+cDhbDtdcweoyCVsF3fhN8kejK6rFe/2FFX2nU= github.com/google/gnostic-models v0.6.9-0.20230804172637-c7be7c783f49/go.mod h1:BkkQ4L1KS1xMt2aWSPStnn55ChGC0DPOn2FQYj+f25M= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= @@ -745,7 +730,6 @@ github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= -github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= github.com/google/orderedcode v0.0.1 h1:UzfcAexk9Vhv8+9pNOgRu41f16lHq725vPwnSeiG/Us= github.com/google/orderedcode v0.0.1/go.mod h1:iVyU4/qPKHY5h/wSd6rZZCDcLJNxiWO6dvsYES2Sb20= github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= @@ -755,16 +739,12 @@ github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hf github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20240827171923-fa2c70bbbfe5 h1:5iH8iuqE5apketRbSFBy+X1V0o+l+8NF1avt4HWl7cA= github.com/google/pprof v0.0.0-20240827171923-fa2c70bbbfe5/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= -github.com/google/s2a-go v0.1.8 h1:zZDs9gcbt9ZPLV0ndSyQk6Kacx2g/X+SKYovpnz3SMM= -github.com/google/s2a-go v0.1.8/go.mod h1:6iNWHTpQ+nfNRN5E00MSdfDwVesa8hhS32PhPO8deJA= +github.com/google/s2a-go v0.1.7 h1:60BLSyTrOV4/haCDW4zb1guZItoSq8foHCXrAnjBo/o= +github.com/google/s2a-go v0.1.7/go.mod h1:50CgR4k1jNlWBu4UfS4AcfhVe1r6pdZPygJ3R8F0Qdw= github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4= github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ= github.com/google/subcommands v1.2.0/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk= @@ -773,16 +753,15 @@ github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+ github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/googleapis/enterprise-certificate-proxy v0.3.4 h1:XYIDZApgAnrN1c855gTgghdIA6Stxb52D5RnLI1SLyw= -github.com/googleapis/enterprise-certificate-proxy v0.3.4/go.mod h1:YKe7cfqYXjKGpGvmSg28/fFvhNzinZQm8DGnaburhGA= +github.com/googleapis/enterprise-certificate-proxy v0.3.2 h1:Vie5ybvEvT75RniqhfFxPRy3Bf7vr3h0cechB90XaQs= +github.com/googleapis/enterprise-certificate-proxy v0.3.2/go.mod h1:VLSiSSBs/ksPL8kq3OBOQ6WRI2QnaFynd1DCjZ62+V0= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= -github.com/googleapis/gax-go/v2 v2.14.0 h1:f+jMrjBPl+DL9nI4IQzLUxMq7XrAqFYB7hBPqMNIe8o= -github.com/googleapis/gax-go/v2 v2.14.0/go.mod h1:lhBCnjdLrWRaPvLWhmc8IS24m9mr07qSYnHncrgo+zk= +github.com/googleapis/gax-go/v2 v2.13.0 h1:yitjD5f7jQHhyDsnhKEBU52NdvvdSeGzlAnDPT0hH1s= +github.com/googleapis/gax-go/v2 v2.13.0/go.mod h1:Z/fvTZXF8/uw7Xu5GuslPw+bplx6SS338j1Is2S+B7A= github.com/gophercloud/gophercloud v1.13.0 h1:8iY9d1DAbzMW6Vok1AxbbK5ZaUjzMp0tdyt4fX9IeJ0= github.com/gophercloud/gophercloud v1.13.0/go.mod h1:aAVqcocTSXh2vYFZ1JTvx4EQmfgzxRcNupUfxZbBNDM= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= -github.com/gopherjs/gopherjs v1.17.2/go.mod h1:pRRIvn/QzFLrKfvEz3qUuEhtE/zLCWfreZ6J5gM2i+k= github.com/gorilla/context v1.1.1 h1:AWwleXJkX/nhcU9bZSnZoi3h/qGYqQAGhq6zZe/aQW8= github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= github.com/gorilla/handlers v1.5.1 h1:9lRY6j8DEeeBT10CvO9hGW0gmky0BprnvDI5vfhUHH4= @@ -1043,18 +1022,17 @@ github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+o github.com/klauspost/compress v1.11.4/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= github.com/klauspost/compress v1.12.3/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg= github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= -github.com/klauspost/compress v1.17.11 h1:In6xLpyWOi1+C7tXUUWv2ot1QvBjxevKAaI6IXrJmUc= -github.com/klauspost/compress v1.17.11/go.mod h1:pMDklpSncoRMuLFrf1W9Ss9KT+0rH90U12bZKk7uwG0= +github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA= +github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= -github.com/klauspost/cpuid/v2 v2.2.8 h1:+StwCXwm9PdpiEkPyzBXIy+M9KUb4ODm0Zarf1kS5BM= -github.com/klauspost/cpuid/v2 v2.2.8/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws= +github.com/klauspost/cpuid/v2 v2.2.7 h1:ZWSB3igEs+d0qvnxR/ZBzXVmxkgt8DdzP6m9pfuVLDM= +github.com/klauspost/cpuid/v2 v2.2.7/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws= github.com/knz/go-libedit v1.10.1/go.mod h1:MZTVkCWyz0oBc7JOWP3wNAzd002ZbM/5hgShxwh4x8M= github.com/kolo/xmlrpc v0.0.0-20220921171641-a4b6fa1dd06b h1:udzkj9S/zlT5X367kqJis0QP7YMxobob6zhzq6Yre00= github.com/kolo/xmlrpc v0.0.0-20220921171641-a4b6fa1dd06b/go.mod h1:pcaDhQK0/NJZEvtCO0qQPPropqV0sJOJ6YW7X+9kRwM= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= @@ -1067,8 +1045,8 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= -github.com/leanovate/gopter v0.2.11 h1:vRjThO1EKPb/1NsDXuDrzldR28RLkBflWYcU9CvzWu4= -github.com/leanovate/gopter v0.2.11/go.mod h1:aK3tzZP/C+p1m3SPRE4SYZFGP7jjkuSI4f7Xvpt0S9c= +github.com/leanovate/gopter v0.2.10-0.20210127095200-9abe2343507a h1:dHCfT5W7gghzPtfsW488uPmEOm85wewI+ypUwibyTdU= +github.com/leanovate/gopter v0.2.10-0.20210127095200-9abe2343507a/go.mod h1:U2L/78B+KVFIx2VmW6onHJQzXtFb+p5y3y2Sh+Jxxv8= github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ= github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI= github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= @@ -1095,7 +1073,6 @@ github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I= github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= -github.com/magiconair/properties v1.8.5/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= @@ -1104,8 +1081,6 @@ github.com/manifoldco/promptui v0.9.0 h1:3V4HzJk1TtXW1MTZMP7mdlwbBpIinw3HztaIlYt github.com/manifoldco/promptui v0.9.0/go.mod h1:ka04sppxSGFAtxX0qhlYQjISsg9mR4GWtQEhdbn6Pgg= github.com/manyminds/api2go v0.0.0-20171030193247-e7b693844a6f h1:tVvGiZQFjOXP+9YyGqSA6jE55x1XVxmoPYudncxrZ8U= github.com/manyminds/api2go v0.0.0-20171030193247-e7b693844a6f/go.mod h1:Z60vy0EZVSu0bOugCHdcN5ZxFMKSpjRgsnh0XKPFqqk= -github.com/marcboeker/go-duckdb v1.8.3 h1:ZkYwiIZhbYsT6MmJsZ3UPTHrTZccDdM4ztoqSlEMXiQ= -github.com/marcboeker/go-duckdb v1.8.3/go.mod h1:C9bYRE1dPYb1hhfu/SSomm78B0FXmNgRvv6YBW/Hooc= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ= github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= @@ -1217,8 +1192,6 @@ github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f h1:KUppIJq7/+ github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f h1:y5//uYreIhSUg3J1GEMiLbxo1LJaP8RfCpH6pymGZus= github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw= -github.com/neelance/astrewrite v0.0.0-20160511093645-99348263ae86/go.mod h1:kHJEU3ofeGjhHklVoIGuVj85JJwZ6kWPaJwCIxgnFmo= -github.com/neelance/sourcemap v0.0.0-20200213170602-2833bce08e4c/go.mod h1:Qr6/a/Q4r9LP1IltGz7tA7iOK1WonHEYhu1HRBA7ZiM= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= github.com/nkovacs/streamquote v0.0.0-20170412213628-49af9bddb229/go.mod h1:0aYXnNPJ8l7uZxf45rWW1a/uME32OF0rhiYGNQ2oF2E= github.com/nsf/jsondiff v0.0.0-20230430225905-43f6cf3098c1 h1:dOYG7LS/WK00RWZc8XGgcUTlTxpp3mKhdR2Q9z9HbXM= @@ -1275,7 +1248,6 @@ github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTK github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58 h1:onHthvaw9LFnH4t2DcNVpwGmV9E1BkGknEliJkfwQj0= github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58/go.mod h1:DXv8WO4yhMYhSNPKjeNKa5WY9YCIEBRbNzFFPJbWO6Y= github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= -github.com/pelletier/go-toml v1.9.3/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8= github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= github.com/pelletier/go-toml/v2 v2.2.3 h1:YmeHyLY8mFWbdkNWwpr+qIL2bEqT0o95WSdkNHvL12M= @@ -1285,8 +1257,8 @@ github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR github.com/petermattis/goid v0.0.0-20180202154549-b0b1615b78e5/go.mod h1:jvVRKCrJTQWu0XVbaOlby/2lO20uSCHEMzzplHXte1o= github.com/petermattis/goid v0.0.0-20230317030725-371a4b8eda08 h1:hDSdbBuw3Lefr6R18ax0tZ2BJeNB3NehB3trOwYBsdU= github.com/petermattis/goid v0.0.0-20230317030725-371a4b8eda08/go.mod h1:pxMtw7cyUw6B2bRH0ZBANSPg+AoSud1I1iyJHI69jH4= -github.com/pierrec/lz4/v4 v4.1.21 h1:yOVMLb6qSIDP67pl/5F7RepeKYu/VmTyEXvuMI5d9mQ= -github.com/pierrec/lz4/v4 v4.1.21/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= +github.com/pierrec/lz4/v4 v4.1.18 h1:xaKrnTkyoqfh1YItXl56+6KJNVYWlEEPuAQW9xsplYQ= +github.com/pierrec/lz4/v4 v4.1.18/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= github.com/pingcap/errors v0.11.4 h1:lFuQV/oaUMGcD2tqt+01ROSmJs75VG1ToEOkZIZ4nE4= github.com/pingcap/errors v0.11.4/go.mod h1:Oi8TUi2kEtXXLMJk9l1cGmz20kV3TaQ0usTwv5KuLY8= github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c h1:+mdjkGKdHQG3305AYmdv1U2eRNDiU2ErMBj1gwrq8eQ= @@ -1296,7 +1268,6 @@ github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI= github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10 h1:GFCKgmp0tecUJ0sJuv4pzYCqS9+RGSn52M3FUwPs+uo= github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10/go.mod h1:t/avpk3KcrXxUnYOhZhMXJlSEyie6gQbtLq5NM3loB8= github.com/pmezard/go-difflib v0.0.0-20151028094244-d8ed2627bdf0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= @@ -1364,8 +1335,8 @@ github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6So github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= -github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII= -github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o= +github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= +github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= github.com/rs/cors v1.10.1 h1:L0uuZVXIKlI1SShY2nhFfo44TYvDPQ1w4oFkUJNfhyo= github.com/rs/cors v1.10.1/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU= github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ= @@ -1417,51 +1388,47 @@ github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFR github.com/shopspring/decimal v1.3.1/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= github.com/shopspring/decimal v1.4.0 h1:bxl37RwXBklmTi0C79JfXCEBD1cqqHt0bbgBAGFp81k= github.com/shopspring/decimal v1.4.0/go.mod h1:gawqmDU56v4yIKSwfBSFip1HdCCXN8/+DMd9qYNcwME= -github.com/shurcooL/go v0.0.0-20200502201357-93f07166e636/go.mod h1:TDJrrUr11Vxrven61rcy3hJMUqaf/CLWYhHNPmT14Lk= -github.com/shurcooL/httpfs v0.0.0-20190707220628-8d4bc4ba7749/go.mod h1:ZY1cvUeJuFPAdZ/B6v7RHavJWZn2YPVFQ1OSXhCGOkg= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= -github.com/shurcooL/vfsgen v0.0.0-20200824052919-0d455de96546/go.mod h1:TrYk7fJVaAttu97ZZKrO9UbRa8izdowaMIZcxYMbVaw= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= -github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/slack-go/slack v0.15.0 h1:LE2lj2y9vqqiOf+qIIy0GvEoxgF1N5yLGZffmEZykt0= github.com/slack-go/slack v0.15.0/go.mod h1:hlGi5oXA+Gt+yWTPP0plCdRKmjsDxecdHxYQdlMQKOw= -github.com/smartcontractkit/ccip-owner-contracts v0.0.0-salt-fix h1:DPJD++yKLSx0EfT+U14P8vLVxjXFmoIETiCO9lVwQo8= -github.com/smartcontractkit/ccip-owner-contracts v0.0.0-salt-fix/go.mod h1:NnT6w4Kj42OFFXhSx99LvJZWPpMjmo4+CpDEWfw61xY= -github.com/smartcontractkit/chain-selectors v1.0.34 h1:MJ17OGu8+jjl426pcKrJkCf3fePb3eCreuAnUA3RBj4= -github.com/smartcontractkit/chain-selectors v1.0.34/go.mod h1:xsKM0aN3YGcQKTPRPDDtPx2l4mlTN1Djmg0VVXV40b8= +github.com/smartcontractkit/ccip-owner-contracts v0.0.0-20240926212305-a6deabdfce86 h1:qQH6fZZe31nBAG6INHph3z5ysDTPptyu0TR9uoJ1+ok= +github.com/smartcontractkit/ccip-owner-contracts v0.0.0-20240926212305-a6deabdfce86/go.mod h1:WtWOoVQQEHxRHL2hNmuRrvDfYfQG/CioFNoa9Rr2mBE= +github.com/smartcontractkit/chain-selectors v1.0.29 h1:aZ9+OoUSMn4nqnissHtDvDoKR7JONfDqTHX3MHYIUIE= +github.com/smartcontractkit/chain-selectors v1.0.29/go.mod h1:xsKM0aN3YGcQKTPRPDDtPx2l4mlTN1Djmg0VVXV40b8= github.com/smartcontractkit/chainlink-automation v0.8.1 h1:sTc9LKpBvcKPc1JDYAmgBc2xpDKBco/Q4h4ydl6+UUU= github.com/smartcontractkit/chainlink-automation v0.8.1/go.mod h1:Iij36PvWZ6blrdC5A/nrQUBuf3MH3JvsBB9sSyc9W08= -github.com/smartcontractkit/chainlink-ccip v0.0.0-20241218114855-f74219171000 h1:6Zzr/R1j6P7bbvcUlt5WUIbItvrrGdGzIsiAzQezcwo= -github.com/smartcontractkit/chainlink-ccip v0.0.0-20241218114855-f74219171000/go.mod h1:ncjd6mPZSRlelEqH/2KeLE1pU3UlqzBSn8RYkEoECzY= -github.com/smartcontractkit/chainlink-common v0.4.1-0.20241217120918-bbe318cd0760 h1:lB5A3TP0zOVuu1n0kEm6d8/o/4Knh6HLvsU/GChk+sI= -github.com/smartcontractkit/chainlink-common v0.4.1-0.20241217120918-bbe318cd0760/go.mod h1:yti7e1+G9hhkYhj+L5sVUULn9Bn3bBL5/AxaNqdJ5YQ= -github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241202195413-82468150ac1e h1:PRoeby6ZlTuTkv2f+7tVU4+zboTfRzI+beECynF4JQ0= -github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241202195413-82468150ac1e/go.mod h1:mUh5/woemsVaHgTorA080hrYmO3syBCmPdnWc/5dOqk= -github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20241216163550-fa030d178ba3 h1:aeiBdBHGY8QNftps+VqrIk6OnfeeOD5z4jrAabW4ZSc= -github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20241216163550-fa030d178ba3/go.mod h1:AS6zY2BkcRwfiGzNabGbHhfrLSrXrcI/GmjnT4jQ5/s= +github.com/smartcontractkit/chainlink-ccip v0.0.0-20241118091009-43c2b4804cec h1:5vS1k8Qn09p8SQ3JzvS8iy4Pve7s3aVq+UPIdl74smY= +github.com/smartcontractkit/chainlink-ccip v0.0.0-20241118091009-43c2b4804cec/go.mod h1:4adKaHNaxFsRvV/lYfqtbsWyyvIPUMLR0FdOJN/ljis= +github.com/smartcontractkit/chainlink-common v0.3.1-0.20241114134822-aadff98ef068 h1:2llRW4Tn9W/EZp2XvXclQ9IjeTBwwxVPrrqaerX+vCE= +github.com/smartcontractkit/chainlink-common v0.3.1-0.20241114134822-aadff98ef068/go.mod h1:ny87uTW6hLjCTLiBqBRNFEhETSXhHWevYlPclT5lSco= +github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241017133723-5277829bd53f h1:BwrIaQIx5Iy6eT+DfLhFfK2XqjxRm74mVdlX8gbu4dw= +github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241017133723-5277829bd53f/go.mod h1:wHtwSR3F1CQSJJZDQKuqaqFYnvkT+kMyget7dl8Clvo= +github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20241018134907-a00ba3729b5e h1:JiETqdNM0bktAUGMc62COwXIaw3rR3M77Me6bBLG0Fg= +github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20241018134907-a00ba3729b5e/go.mod h1:iK3BNHKCLgSgkOyiu3iE7sfZ20Qnuk7xwjV/yO/6gnQ= github.com/smartcontractkit/chainlink-feeds v0.1.1 h1:JzvUOM/OgGQA1sOqTXXl52R6AnNt+Wg64sVG+XSA49c= github.com/smartcontractkit/chainlink-feeds v0.1.1/go.mod h1:55EZ94HlKCfAsUiKUTNI7QlE/3d3IwTlsU3YNa/nBb4= -github.com/smartcontractkit/chainlink-protos/job-distributor v0.6.0 h1:0ewLMbAz3rZrovdRUCgd028yOXX8KigB4FndAUdI2kM= -github.com/smartcontractkit/chainlink-protos/job-distributor v0.6.0/go.mod h1:/dVVLXrsp+V0AbcYGJo3XMzKg3CkELsweA/TTopCsKE= -github.com/smartcontractkit/chainlink-protos/orchestrator v0.4.0 h1:ZBat8EBvE2LpSQR9U1gEbRV6PfAkiFdINmQ8nVnXIAQ= -github.com/smartcontractkit/chainlink-protos/orchestrator v0.4.0/go.mod h1:m/A3lqD7ms/RsQ9BT5P2uceYY0QX5mIt4KQxT2G6qEo= -github.com/smartcontractkit/chainlink-solana v1.1.1-0.20241219173444-150f7443fdd3 h1:AIIiwrZ5T4nEjFT33aLZKoXwD63JSMu72wWe/rUdfm0= -github.com/smartcontractkit/chainlink-solana v1.1.1-0.20241219173444-150f7443fdd3/go.mod h1:ARILnIgKelP0YkVzxXO111S9j0b4uKyt7iLpYjOkCtU= -github.com/smartcontractkit/chainlink-starknet/relayer v0.1.1-0.20241202202529-2033490e77b8 h1:tNS7U9lrxkFvEuyxQv11HHOiV9LPDGC9wYEy+yM/Jv4= -github.com/smartcontractkit/chainlink-starknet/relayer v0.1.1-0.20241202202529-2033490e77b8/go.mod h1:EBrEgcdIbwepqguClkv8Ohy7CbyWSJaE4EC9aBJlQK0= +github.com/smartcontractkit/chainlink-protos/job-distributor v0.4.0 h1:1xTm8UGeDUAjvCXRh08+4xBRX33owH5MqC522JdelM0= +github.com/smartcontractkit/chainlink-protos/job-distributor v0.4.0/go.mod h1:/dVVLXrsp+V0AbcYGJo3XMzKg3CkELsweA/TTopCsKE= +github.com/smartcontractkit/chainlink-protos/orchestrator v0.3.0 h1:PBUaFfPLm+Efq7H9kdfGBivH+QhJ6vB5EZTR/sCZsxI= +github.com/smartcontractkit/chainlink-protos/orchestrator v0.3.0/go.mod h1:m/A3lqD7ms/RsQ9BT5P2uceYY0QX5mIt4KQxT2G6qEo= +github.com/smartcontractkit/chainlink-solana v1.1.1-0.20241115191142-8b8369c1f44e h1:XxTWJ9VIXK+XuAjP5131PqqBn0NEt5lBvnRAWRdqy8A= +github.com/smartcontractkit/chainlink-solana v1.1.1-0.20241115191142-8b8369c1f44e/go.mod h1:mGmRvlk54ufCufV4EBWizOGtXoXfePoFAuYEVC8EwdY= +github.com/smartcontractkit/chainlink-starknet/relayer v0.1.1-0.20241017135645-176a23722fd8 h1:B4DFdk6MGcQnoCjjMBCx7Z+GWQpxRWJ4O8W/dVJyWGA= +github.com/smartcontractkit/chainlink-starknet/relayer v0.1.1-0.20241017135645-176a23722fd8/go.mod h1:WkBqgBo+g34Gm5vWkDDl8Fh3Mzd7bF5hXp7rryg0t5o= github.com/smartcontractkit/chainlink-testing-framework/havoc v1.50.2 h1:GDGrC5OGiV0RyM1znYWehSQXyZQWTOzrEeJRYmysPCE= github.com/smartcontractkit/chainlink-testing-framework/havoc v1.50.2/go.mod h1:DsT43c1oTBmp3iQkMcoZOoKThwZvt8X3Pz6UmznJ4GY= -github.com/smartcontractkit/chainlink-testing-framework/lib v1.50.19 h1:9PMwKNqFKc5FXf4VchyD3CGzZelnSgi13fgVdT2X7T4= -github.com/smartcontractkit/chainlink-testing-framework/lib v1.50.19/go.mod h1:ag7LEgejsVtPXaUNkcoFPpAoDkl1J8V2HSbqVUxfEtk= +github.com/smartcontractkit/chainlink-testing-framework/lib v1.50.13 h1:T0kbw07Vb6xUyA9MIJZfErMgWseWi1zf7cYvRpoq7ug= +github.com/smartcontractkit/chainlink-testing-framework/lib v1.50.13/go.mod h1:1CKUOzoK+Ga19WuhRH9pxZ+qUUnrlIx108VEA6qSzeQ= github.com/smartcontractkit/chainlink-testing-framework/lib/grafana v1.50.0 h1:VIxK8u0Jd0Q/VuhmsNm6Bls6Tb31H/sA3A/rbc5hnhg= github.com/smartcontractkit/chainlink-testing-framework/lib/grafana v1.50.0/go.mod h1:lyAu+oMXdNUzEDScj2DXB2IueY+SDXPPfyl/kb63tMM= -github.com/smartcontractkit/chainlink-testing-framework/seth v1.50.9 h1:yB1x5UXvpZNka+5h57yo1/GrKfXKCqMzChCISpldZx4= -github.com/smartcontractkit/chainlink-testing-framework/seth v1.50.9/go.mod h1:lJk0atEJ5Zyo3Tqrmf1Pl9jUEe79EgDb9bD3K5OTUBI= +github.com/smartcontractkit/chainlink-testing-framework/seth v1.50.5 h1:BxN9wddNLiugruN3k7nYoSMQTO0tz9qR+vILFW2l0Ps= +github.com/smartcontractkit/chainlink-testing-framework/seth v1.50.5/go.mod h1:lJk0atEJ5Zyo3Tqrmf1Pl9jUEe79EgDb9bD3K5OTUBI= github.com/smartcontractkit/chainlink-testing-framework/wasp v1.50.2 h1:7bCdbTUWzyczQg+kwHCxlx6y07zE8HNB8+ntTne6qd8= github.com/smartcontractkit/chainlink-testing-framework/wasp v1.50.2/go.mod h1:MltlNu3jcXm/DyLN98I5TFNtu/o1NNAcaPAFKMXWk70= github.com/smartcontractkit/grpc-proxy v0.0.0-20240830132753-a7e17fec5ab7 h1:12ijqMM9tvYVEm+nR826WsrNi6zCKpwBhuApq127wHs= @@ -1472,12 +1439,10 @@ github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20241009055228- github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20241009055228-33d0c0bf38de/go.mod h1:Sl2MF/Fp3fgJIVzhdGhmZZX2BlnM0oUUyBP4s4xYb6o= github.com/smartcontractkit/tdh2/go/tdh2 v0.0.0-20241009055228-33d0c0bf38de h1:66VQxXx3lvTaAZrMBkIcdH9VEjujUEvmBQdnyOJnkOc= github.com/smartcontractkit/tdh2/go/tdh2 v0.0.0-20241009055228-33d0c0bf38de/go.mod h1:NSc7hgOQbXG3DAwkOdWnZzLTZENXSwDJ7Va1nBp0YU0= -github.com/smartcontractkit/wsrpc v0.8.3 h1:9tDf7Ut61g36RJIyxV9iI73SqoOMasKPfURV9oMLrPg= -github.com/smartcontractkit/wsrpc v0.8.3/go.mod h1:2u/wfnhl5R4RlSXseN4n6HHIWk8w1Am3AT6gWftQbNg= -github.com/smarty/assertions v1.15.0/go.mod h1:yABtdzeQs6l1brC900WlRNwj6ZR55d7B+E8C6HtKdec= +github.com/smartcontractkit/wsrpc v0.8.2 h1:XB/xcn/MMseHW+8JE8+a/rceA86ck7Ur6cEa9LiUC8M= +github.com/smartcontractkit/wsrpc v0.8.2/go.mod h1:2u/wfnhl5R4RlSXseN4n6HHIWk8w1Am3AT6gWftQbNg= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= -github.com/smartystreets/goconvey v1.8.1/go.mod h1:+/u4qLyY6x1jReYOp7GOM2FSt8aP9CzCZL03bI28W60= github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= github.com/soheilhy/cmux v0.1.5 h1:jjzc5WVemNEDTLwv9tlmemhC73tI08BNOIGwBOo10Js= github.com/soheilhy/cmux v0.1.5/go.mod h1:T7TcVDs9LWfQgPlPsdngu6I6QIoyIFZDDC6sNE1GqG0= @@ -1489,7 +1454,6 @@ github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasO github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI= github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= -github.com/spf13/afero v1.6.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I= github.com/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8= github.com/spf13/afero v1.11.0/go.mod h1:GH9Y3pIexgf1MTIWtNGyogA5MwRIDXGUr+hbWNoBjkY= github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= @@ -1498,18 +1462,15 @@ github.com/spf13/cast v1.6.0 h1:GEiTHELF+vaR5dhz3VqZfFSzZjYbgeKDpBxQVS4GYJ0= github.com/spf13/cast v1.6.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo= github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU= github.com/spf13/cobra v1.1.1/go.mod h1:WnodtKOvamDL/PwE2M4iKs8aMDBZ5Q5klgD3qfVJQMI= -github.com/spf13/cobra v1.2.1/go.mod h1:ExllRjgxM/piMAM+3tAZvg8fsklGAf3tPfi+i8t68Nk= github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM= github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y= github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= -github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= github.com/spf13/viper v1.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg= github.com/spf13/viper v1.7.1/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg= -github.com/spf13/viper v1.8.1/go.mod h1:o0Pch8wJ9BVSWGQMbra6iw0oQ5oktSIBaujf1rJH9Ns= github.com/spf13/viper v1.19.0 h1:RWq5SEjt8o25SROyN3z2OrDB9l7RPd3lwTWU8EcEdcI= github.com/spf13/viper v1.19.0/go.mod h1:GQUN9bilAbhU/jgc1bKs99f/suXKeUMct8Adx5+Ntkg= github.com/status-im/keycard-go v0.2.0 h1:QDLFswOQu1r5jsycloeQh3bVU8n/NatHHaZobtDnDzA= @@ -1620,8 +1581,6 @@ github.com/xlab/treeprint v1.2.0/go.mod h1:gj5Gd3gPdKtR1ikdDK6fnFLdmIS0X30kTTuNd github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 h1:gEOO8jv9F4OT7lGCjxCBTO/36wtF6j2nSip77qHd4x4= github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1/go.mod h1:Ohn+xnUBiLI6FVj/9LpzZWtj1/D6lUovWYBkxHVV3aM= -github.com/xyproto/randomstring v1.0.5 h1:YtlWPoRdgMu3NZtP45drfy1GKoojuR7hmRcnhZqKjWU= -github.com/xyproto/randomstring v1.0.5/go.mod h1:rgmS5DeNXLivK7YprL0pY+lTuhNQW3iGxZ18UQApw/E= github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d/go.mod h1:rHwXgn7JulP+udvsHwJoVG1YGAP6VLg4y9I5dyZdqmA= github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= @@ -1633,8 +1592,6 @@ github.com/yuin/gopher-lua v1.1.0 h1:BojcDhfyDWgU2f2TOzYK/g5p2gxMrku8oupLDqlnSqE github.com/yuin/gopher-lua v1.1.0/go.mod h1:GBR0iDaNXjAgGg9zfCvksxSRnQx76gclCIb7kdAd1Pw= github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo0= github.com/yusufpapurcu/wmi v1.2.4/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= -github.com/zeebo/xxh3 v1.0.2 h1:xZmwmqxHZA8AI603jOQ0tMqmBr9lPeFwGg6d+xy9DC0= -github.com/zeebo/xxh3 v1.0.2/go.mod h1:5NWz9Sef7zIDm2JHfFlcQvNekmcEl9ekUZQQKCYaDcA= github.com/zenazn/goji v0.9.0/go.mod h1:7S9M489iMyHBNxwZnk9/EHS098H4/F6TATF2mIxtB1Q= github.com/zondax/hid v0.9.2 h1:WCJFnEDMiqGF64nlZz28E9qLVZ0KSJ7xpc5DLEyma2U= github.com/zondax/hid v0.9.2/go.mod h1:l5wttcP0jwtdLjqjMMWFVEE7d1zO0jvSPA9OPZxWpEM= @@ -1652,13 +1609,10 @@ go.dedis.ch/protobuf v1.0.11/go.mod h1:97QR256dnkimeNdfmURz0wAMNVbd1VmLXhG1CrTYr go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.etcd.io/bbolt v1.3.9 h1:8x7aARPEXiXbHmtUwAIv7eV2fQFHrLLavdiJ3uzJXoI= go.etcd.io/bbolt v1.3.9/go.mod h1:zaO32+Ti0PK1ivdPtgMESzuzL2VPoIG1PCQNvOdo/dE= -go.etcd.io/etcd/api/v3 v3.5.0/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs= go.etcd.io/etcd/api/v3 v3.5.14 h1:vHObSCxyB9zlF60w7qzAdTcGaglbJOpSj1Xj9+WGxq0= go.etcd.io/etcd/api/v3 v3.5.14/go.mod h1:BmtWcRlQvwa1h3G2jvKYwIQy4PkHlDej5t7uLMUdJUU= -go.etcd.io/etcd/client/pkg/v3 v3.5.0/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g= go.etcd.io/etcd/client/pkg/v3 v3.5.14 h1:SaNH6Y+rVEdxfpA2Jr5wkEvN6Zykme5+YnbCkxvuWxQ= go.etcd.io/etcd/client/pkg/v3 v3.5.14/go.mod h1:8uMgAokyG1czCtIdsq+AGyYQMvpIKnSvPjFMunkgeZI= -go.etcd.io/etcd/client/v2 v2.305.0/go.mod h1:h9puh54ZTgAKtEbut2oe9P4L/oqKCVB6xsXlzd7alYQ= go.etcd.io/etcd/client/v3 v3.5.14 h1:CWfRs4FDaDoSz81giL7zPpZH2Z35tbOrAJkkjMqOupg= go.etcd.io/etcd/client/v3 v3.5.14/go.mod h1:k3XfdV/VIHy/97rqWjoUzrj9tk7GgJGH9J8L4dNXmAk= go.mongodb.org/mongo-driver v1.11.0/go.mod h1:s7p5vEtfbeR1gYi6pnj3c3/urpbLv2T5Sfd6Rp2HBB8= @@ -1671,7 +1625,6 @@ go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= -go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= go.opentelemetry.io/collector/pdata v1.12.0 h1:Xx5VK1p4VO0md8MWm2icwC1MnJ7f8EimKItMWw46BmA= @@ -1749,7 +1702,6 @@ go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= go.uber.org/zap v1.14.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= go.uber.org/zap v1.16.0/go.mod h1:MA8QOfq0BHJwdXa996Y4dYkAqRKB8/1K1QMMZVaNZjQ= -go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo= go.uber.org/zap v1.21.0/go.mod h1:wjWOCqI0f2ZZrJF/UufIOkiC8ii6tm1iqIsLo76RfJw= go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= @@ -1782,8 +1734,8 @@ golang.org/x/crypto v0.0.0-20220214200702-86341886e292/go.mod h1:IxCIyHEi3zRg3s0 golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.3.0/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4= golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc= -golang.org/x/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U= -golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk= +golang.org/x/crypto v0.28.0 h1:GBDwsMXVQi34v5CCYUm2jkJvu4cbtru2U4TN2PSyQnw= +golang.org/x/crypto v0.28.0/go.mod h1:rmgy+3RHxRZMyY0jjAJShp2zgEdOqj2AO7U0pYmeQ7U= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -1809,7 +1761,6 @@ golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRu golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= @@ -1818,12 +1769,9 @@ golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzB golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/mod v0.9.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.21.0 h1:vvrHzRwRfVKSiLrG+d4FMl/Qi4ukBCE6kZlTUkDYRT0= golang.org/x/mod v0.21.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -1863,11 +1811,8 @@ golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81R golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc= golang.org/x/net v0.0.0-20210331212208-0fccb6fa2b5c/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= @@ -1881,7 +1826,6 @@ golang.org/x/net v0.0.0-20220607020251-c690dde0001d/go.mod h1:XRhObCWvk6IyKnWLug golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= -golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/net v0.30.0 h1:AcW1SDZMkb8IpzCdQUaIq2sP4sZ4zw+55h6ynffypl4= golang.org/x/net v0.30.0/go.mod h1:2wGyMJ5iFasEhkwi13ChkO/t1ECNC4X4eBKkVFyYFlU= @@ -1890,13 +1834,6 @@ golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4Iltr golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210220000619-9bb904979d93/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210313182246-cd4f82c27b84/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210402161424-2e8d93401602/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.23.0 h1:PbgcYx2W7i4LvjJWEbf0ngHV6qJYr86PkAV3bXdLEbs= golang.org/x/oauth2 v0.23.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= @@ -1913,8 +1850,8 @@ golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ= -golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ= +golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -1966,23 +1903,17 @@ golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210303074136-134d130e1a04/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210305230114-8fe3ee5dd75b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210331175145-43e1dd70ce54/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -2010,8 +1941,8 @@ golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA= -golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo= +golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20201210144234-2321bbc49cbf/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= @@ -2019,11 +1950,10 @@ golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuX golang.org/x/term v0.0.0-20220526004731-065cf7ba2467/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= -golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU= -golang.org/x/term v0.27.0 h1:WP60Sv1nlK1T6SupCHbXzSaN0b9wUmsPoRS9b61A23Q= -golang.org/x/term v0.27.0/go.mod h1:iMsnZpn0cago0GOrHO2+Y7u7JPn5AylBrcoWkElMTSM= +golang.org/x/term v0.25.0 h1:WtHI/ltw4NvSUig5KARz9h521QvRC8RmF/cuYqifU24= +golang.org/x/term v0.25.0/go.mod h1:RPyXicDX+6vLxogjjRxjgD2TKtmAO6NZBsBRfrOLu7M= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -2035,11 +1965,10 @@ golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= -golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo= -golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ= +golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM= +golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -2096,19 +2025,12 @@ golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roY golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE= -golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= -golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= -golang.org/x/tools v0.7.0/go.mod h1:4pg6aUX35JBAogB10C9AtvVL+qowtN4pT3CGSQex14s= golang.org/x/tools v0.26.0 h1:v/60pFQmzmT9ExmjDv2gGIfi3OqfKoEP6I5+umXlbnQ= golang.org/x/tools v0.26.0/go.mod h1:TPVVj70c7JJ3WCazhD8OdXcZg/og+b9+tH/KxylGwH0= golang.org/x/xerrors v0.0.0-20190410155217-1f06c39b4373/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -2141,14 +2063,8 @@ google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0M google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM= google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc= -google.golang.org/api v0.35.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg= -google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34qYtE= -google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8= -google.golang.org/api v0.41.0/go.mod h1:RkxM5lITDfTzmyKFPt+wGrCJbVfniCr2ool8kTBzRTU= -google.golang.org/api v0.43.0/go.mod h1:nQsDGjRXMo4lvh5hP0TKqF244gqhGcr/YSIykhUk/94= -google.golang.org/api v0.44.0/go.mod h1:EBOGZqzyhtvMDoxwS97ctnh0zUmYY6CxqXsc1AvkYD8= -google.golang.org/api v0.205.0 h1:LFaxkAIpDb/GsrWV20dMMo5MR0h8UARTbn24LmD+0Pg= -google.golang.org/api v0.205.0/go.mod h1:NrK1EMqO8Xk6l6QwRAmrXXg2v6dzukhlOyvkYtnvUuc= +google.golang.org/api v0.202.0 h1:y1iuVHMqokQbimW79ZqPZWo4CiyFu6HcCYHwSNyzlfo= +google.golang.org/api v0.202.0/go.mod h1:3Jjeq7M/SFblTNCp7ES2xhq+WvGL0KeXI0joHQBfwTQ= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= @@ -2192,24 +2108,13 @@ google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7Fc google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210222152913-aa3ee6e6a81c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210303154014-9728d6b83eeb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210310155132-4ce2db91004e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210319143718-93e7006c17a6/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210401141331-865547bb08e2/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A= -google.golang.org/genproto v0.0.0-20210402141018-6c239bbf2bb1/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A= -google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= google.golang.org/genproto v0.0.0-20241021214115-324edc3d5d38 h1:Q3nlH8iSQSRUwOskjbcSMcF2jiYMNiQYZ0c2KEJLKKU= google.golang.org/genproto v0.0.0-20241021214115-324edc3d5d38/go.mod h1:xBI+tzfqGGN2JBeSebfKXFSdBpWVQ7sLW40PTupVRm4= -google.golang.org/genproto/googleapis/api v0.0.0-20241104194629-dd2ea8efbc28 h1:M0KvPgPmDZHPlbRbaNU1APr28TvwvvdUPlSv7PUvy8g= -google.golang.org/genproto/googleapis/api v0.0.0-20241104194629-dd2ea8efbc28/go.mod h1:dguCy7UOdZhTvLzDyt15+rOrawrpM4q7DD9dQ1P11P4= -google.golang.org/genproto/googleapis/rpc v0.0.0-20241104194629-dd2ea8efbc28 h1:XVhgTWWV3kGQlwJHR3upFWZeTsei6Oks1apkZSeonIE= -google.golang.org/genproto/googleapis/rpc v0.0.0-20241104194629-dd2ea8efbc28/go.mod h1:GX3210XPVPUjJbTUbvwI8f2IpZDMZuPJWDzDuebbviI= +google.golang.org/genproto/googleapis/api v0.0.0-20241021214115-324edc3d5d38 h1:2oV8dfuIkM1Ti7DwXc0BJfnwr9csz4TDXI9EmiI+Rbw= +google.golang.org/genproto/googleapis/api v0.0.0-20241021214115-324edc3d5d38/go.mod h1:vuAjtvlwkDKF6L1GQ0SokiRLCGFfeBUXWr/aFFkHACc= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241021214115-324edc3d5d38 h1:zciRKQ4kBpFgpfC5QQCVtnnNAcLIqweL7plyZRQHVpI= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241021214115-324edc3d5d38/go.mod h1:GX3210XPVPUjJbTUbvwI8f2IpZDMZuPJWDzDuebbviI= google.golang.org/grpc v1.12.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= @@ -2225,14 +2130,9 @@ google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKa google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= -google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= -google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8= -google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= -google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= google.golang.org/grpc v1.36.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= -google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= google.golang.org/grpc v1.67.1 h1:zWnc1Vrcno+lHZCOofnIMvycFcc0QRGIzm9dhnDX68E= google.golang.org/grpc v1.67.1/go.mod h1:1gLDyUQU7CTLJI90u3nXZ9ekeghjeM7pTDZlqFNg2AA= google.golang.org/grpc/stats/opentelemetry v0.0.0-20241022174616-4bb0170ac65f h1:TsfHqsKI7qhOoYugDRyFDSKAuzegDVmkSCpjUyLkb+8= @@ -2268,7 +2168,6 @@ gopkg.in/inconshreveable/log15.v2 v2.0.0-20180818164646-67afb5ed74ec/go.mod h1:a gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= -gopkg.in/ini.v1 v1.62.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/natefinch/lumberjack.v2 v2.2.1 h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST95x9zc= @@ -2301,24 +2200,24 @@ honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= honnef.co/go/tools v0.1.3/go.mod h1:NgwopIslSNH47DimFoV78dnkksY2EFtX0ajyb3K/las= -k8s.io/api v0.31.2 h1:3wLBbL5Uom/8Zy98GRPXpJ254nEFpl+hwndmk9RwmL0= -k8s.io/api v0.31.2/go.mod h1:bWmGvrGPssSK1ljmLzd3pwCQ9MgoTsRCuK35u6SygUk= +k8s.io/api v0.31.1 h1:Xe1hX/fPW3PXYYv8BlozYqw63ytA92snr96zMW9gWTU= +k8s.io/api v0.31.1/go.mod h1:sbN1g6eY6XVLeqNsZGLnI5FwVseTrZX7Fv3O26rhAaI= k8s.io/apiextensions-apiserver v0.31.0 h1:fZgCVhGwsclj3qCw1buVXCV6khjRzKC5eCFt24kyLSk= k8s.io/apiextensions-apiserver v0.31.0/go.mod h1:b9aMDEYaEe5sdK+1T0KU78ApR/5ZVp4i56VacZYEHxk= -k8s.io/apimachinery v0.31.2 h1:i4vUt2hPK56W6mlT7Ry+AO8eEsyxMD1U44NR22CLTYw= -k8s.io/apimachinery v0.31.2/go.mod h1:rsPdaZJfTfLsNJSQzNHQvYoTmxhoOEofxtOsF3rtsMo= -k8s.io/cli-runtime v0.31.2 h1:7FQt4C4Xnqx8V1GJqymInK0FFsoC+fAZtbLqgXYVOLQ= -k8s.io/cli-runtime v0.31.2/go.mod h1:XROyicf+G7rQ6FQJMbeDV9jqxzkWXTYD6Uxd15noe0Q= -k8s.io/client-go v0.31.2 h1:Y2F4dxU5d3AQj+ybwSMqQnpZH9F30//1ObxOKlTI9yc= -k8s.io/client-go v0.31.2/go.mod h1:NPa74jSVR/+eez2dFsEIHNa+3o09vtNaWwWwb1qSxSs= -k8s.io/component-base v0.31.2 h1:Z1J1LIaC0AV+nzcPRFqfK09af6bZ4D1nAOpWsy9owlA= -k8s.io/component-base v0.31.2/go.mod h1:9PeyyFN/drHjtJZMCTkSpQJS3U9OXORnHQqMLDz0sUQ= +k8s.io/apimachinery v0.31.1 h1:mhcUBbj7KUjaVhyXILglcVjuS4nYXiwC+KKFBgIVy7U= +k8s.io/apimachinery v0.31.1/go.mod h1:rsPdaZJfTfLsNJSQzNHQvYoTmxhoOEofxtOsF3rtsMo= +k8s.io/cli-runtime v0.31.1 h1:/ZmKhmZ6hNqDM+yf9s3Y4KEYakNXUn5sod2LWGGwCuk= +k8s.io/cli-runtime v0.31.1/go.mod h1:pKv1cDIaq7ehWGuXQ+A//1OIF+7DI+xudXtExMCbe9U= +k8s.io/client-go v0.31.1 h1:f0ugtWSbWpxHR7sjVpQwuvw9a3ZKLXX0u0itkFXufb0= +k8s.io/client-go v0.31.1/go.mod h1:sKI8871MJN2OyeqRlmA4W4KM9KBdBUpDLu/43eGemCg= +k8s.io/component-base v0.31.1 h1:UpOepcrX3rQ3ab5NB6g5iP0tvsgJWzxTyAo20sgYSy8= +k8s.io/component-base v0.31.1/go.mod h1:WGeaw7t/kTsqpVTaCoVEtillbqAhF2/JgvO0LDOMa0w= k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk= k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE= k8s.io/kube-openapi v0.0.0-20240709000822-3c01b740850f h1:2sXuKesAYbRHxL3aE2PN6zX/gcJr22cjrsej+W784Tc= k8s.io/kube-openapi v0.0.0-20240709000822-3c01b740850f/go.mod h1:UxDHUPsUwTOOxSU+oXURfFBcAS6JwiRXTYqYwfuGowc= -k8s.io/kubectl v0.31.2 h1:gTxbvRkMBwvTSAlobiTVqsH6S8Aa1aGyBcu5xYLsn8M= -k8s.io/kubectl v0.31.2/go.mod h1:EyASYVU6PY+032RrTh5ahtSOMgoDRIux9V1JLKtG5xM= +k8s.io/kubectl v0.31.1 h1:ih4JQJHxsEggFqDJEHSOdJ69ZxZftgeZvYo7M/cpp24= +k8s.io/kubectl v0.31.1/go.mod h1:aNuQoR43W6MLAtXQ/Bu4GDmoHlbhHKuyD49lmTC8eJM= k8s.io/utils v0.0.0-20240711033017-18e509b52bc8 h1:pUdcCO1Lk/tbT5ztQWOBi5HBgbBP1J8+AsQnQCKsi8A= k8s.io/utils v0.0.0-20240711033017-18e509b52bc8/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= nhooyr.io/websocket v1.8.10 h1:mv4p+MnGrLDcPlBoWsvPP7XCzTYMXP9F9eIGoKbgx7Q= diff --git a/integration-tests/load/automationv2_1/automationv2_1_test.go b/integration-tests/load/automationv2_1/automationv2_1_test.go index 823c1bd8825..65f1d21257a 100644 --- a/integration-tests/load/automationv2_1/automationv2_1_test.go +++ b/integration-tests/load/automationv2_1/automationv2_1_test.go @@ -196,12 +196,6 @@ Load Config: loadDuration := time.Duration(*loadedTestConfig.Automation.General.Duration) * time.Second automationDefaultLinkFunds := big.NewInt(0).Mul(big.NewInt(1e18), big.NewInt(int64(10000))) //10000 LINK - nsLabels, err := environment.GetRequiredChainLinkNamespaceLabels(string(tc.Automation), testType) - require.NoError(t, err, "Error creating required chain.link labels for namespace") - - workloadPodLabels, err := environment.GetRequiredChainLinkWorkloadAndPodLabels(string(tc.Automation), testType) - require.NoError(t, err, "Error creating required chain.link labels for workloads and pods") - testEnvironment := environment.New(&environment.Config{ TTL: loadDuration.Round(time.Hour) + time.Hour, NamespacePrefix: fmt.Sprintf( @@ -209,9 +203,6 @@ Load Config: testType, strings.ReplaceAll(strings.ToLower(testNetwork.Name), " ", "-"), ), - Labels: nsLabels, - WorkloadLabels: workloadPodLabels, - PodLabels: workloadPodLabels, Test: t, PreventPodEviction: true, }) diff --git a/integration-tests/load/functions/gateway.go b/integration-tests/load/functions/gateway.go index 59443ac6e30..ac5f895ac18 100644 --- a/integration-tests/load/functions/gateway.go +++ b/integration-tests/load/functions/gateway.go @@ -8,7 +8,6 @@ import ( "encoding/hex" "encoding/json" "fmt" - "math" "time" "github.com/ethereum/go-ethereum/crypto" @@ -120,9 +119,6 @@ func UploadS4Secrets(rc *resty.Client, s4Cfg *S4SecretsCfg) (uint8, uint64, erro return 0, 0, fmt.Errorf("node response was not successful") } } - if envelope.SlotID > math.MaxUint8 { - return 0, 0, fmt.Errorf("slot ID overflows uint8: %d", envelope.SlotID) - } return uint8(envelope.SlotID), envelope.Version, nil } diff --git a/integration-tests/load/functions/gateway_gun.go b/integration-tests/load/functions/gateway_gun.go index 5dd2aee4f06..38eddd3163e 100644 --- a/integration-tests/load/functions/gateway_gun.go +++ b/integration-tests/load/functions/gateway_gun.go @@ -41,20 +41,14 @@ func NewGatewaySecretsSetGun(cfg types.FunctionsTestConfig, method string, pKey func callSecretsSet(m *GatewaySecretsSetGun) *wasp.Response { randNum := strconv.Itoa(rand.Intn(100000)) - randSlot := rand.Intn(5) - if randSlot < 0 { - panic(fmt.Errorf("negative rand slot: %d", randSlot)) - } - version := time.Now().UnixNano() - if version < 0 { - panic(fmt.Errorf("negative timestamp: %d", version)) - } + randSlot := uint(rand.Intn(5)) + version := uint64(time.Now().UnixNano()) expiration := int64(60 * 60 * 1000) secret := fmt.Sprintf("{\"ltsecret\": \"%s\"}", randNum) log.Debug(). - Int("SlotID", randSlot). + Uint("SlotID", randSlot). Str("MessageID", randNum). - Int64("Version", version). + Uint64("Version", version). Int64("Expiration", expiration). Str("Secret", secret). Msg("Sending S4 envelope") @@ -79,8 +73,8 @@ func callSecretsSet(m *GatewaySecretsSetGun) *wasp.Response { MessageID: randNum, Method: "secrets_set", DonID: *cfg.Common.DONID, - S4SetSlotID: uint(randSlot), - S4SetVersion: uint64(version), + S4SetSlotID: randSlot, + S4SetVersion: version, S4SetExpirationPeriod: expiration, S4SetPayload: secrets, }) @@ -92,14 +86,8 @@ func callSecretsSet(m *GatewaySecretsSetGun) *wasp.Response { func callSecretsList(m *GatewaySecretsSetGun) *wasp.Response { randNum := strconv.Itoa(rand.Intn(100000)) - randSlot := rand.Intn(5) - if randSlot < 0 { - panic(fmt.Errorf("negative rand slot: %d", randSlot)) - } - version := time.Now().UnixNano() - if version < 0 { - panic(fmt.Errorf("negative timestamp: %d", version)) - } + randSlot := uint(rand.Intn(5)) + version := uint64(time.Now().UnixNano()) expiration := int64(60 * 60 * 1000) network := m.Cfg.GetNetworkConfig().SelectedNetworks[0] if len(m.Cfg.GetNetworkConfig().WalletKeys[network]) < 1 { @@ -113,8 +101,8 @@ func callSecretsList(m *GatewaySecretsSetGun) *wasp.Response { MessageID: randNum, Method: m.Method, DonID: *cfg.Common.DONID, - S4SetSlotID: uint(randSlot), - S4SetVersion: uint64(version), + S4SetSlotID: randSlot, + S4SetVersion: version, S4SetExpirationPeriod: expiration, }); err != nil { return &wasp.Response{Error: err.Error(), Failed: true} diff --git a/integration-tests/load/functions/setup.go b/integration-tests/load/functions/setup.go index f018655a54e..46c2c12921a 100644 --- a/integration-tests/load/functions/setup.go +++ b/integration-tests/load/functions/setup.go @@ -123,22 +123,14 @@ func SetupLocalLoadTestEnv(globalConfig ctf_config.GlobalTestConfig, functionsCo if err != nil { return nil, fmt.Errorf("failed to generate tdh2 secrets: %w", err) } - randInt := mrand.Intn(5) - if randInt < 0 { - return nil, fmt.Errorf("negative random int: %d", randInt) - } - now := time.Now().UnixNano() - if now < 0 { - return nil, fmt.Errorf("negative timestamp: %d", now) - } slotID, slotVersion, err := UploadS4Secrets(resty.New(), &S4SecretsCfg{ GatewayURL: *cfg.Common.GatewayURL, PrivateKey: selectedNetwork.PrivateKeys[0], MessageID: strconv.Itoa(mrand.Intn(100000-1) + 1), Method: "secrets_set", DonID: *cfg.Common.DONID, - S4SetSlotID: uint(randInt), - S4SetVersion: uint64(now), + S4SetSlotID: uint(mrand.Intn(5)), + S4SetVersion: uint64(time.Now().UnixNano()), S4SetExpirationPeriod: 60 * 60 * 1000, S4SetPayload: encryptedSecrets, }) diff --git a/integration-tests/load/go.mod b/integration-tests/load/go.mod index 2467d35684b..9a1fb0d62ab 100644 --- a/integration-tests/load/go.mod +++ b/integration-tests/load/go.mod @@ -1,8 +1,6 @@ module github.com/smartcontractkit/chainlink/load-tests -go 1.23.3 - -toolchain go1.23.4 +go 1.22.8 // Make sure we're working with the latest chainlink libs replace github.com/smartcontractkit/chainlink/v2 => ../../ @@ -11,14 +9,6 @@ replace github.com/smartcontractkit/chainlink/deployment => ../../deployment replace github.com/smartcontractkit/chainlink/integration-tests => ../ -// Using a separate `require` here to avoid surrounding line changes -// creating potential merge conflicts. -require ( - github.com/smartcontractkit/chainlink/deployment v0.0.0-20241206210521-125d98cdaf66 - github.com/smartcontractkit/chainlink/integration-tests v0.0.0-20241206210521-125d98cdaf66 - github.com/smartcontractkit/chainlink/v2 v2.0.0-20241206210521-125d98cdaf66 -) - require ( github.com/K-Phoen/grabana v0.22.2 github.com/ethereum/go-ethereum v1.14.11 @@ -27,15 +17,17 @@ require ( github.com/pkg/errors v0.9.1 github.com/rs/zerolog v1.33.0 github.com/slack-go/slack v0.15.0 - github.com/smartcontractkit/chainlink-common v0.4.1-0.20241217120918-bbe318cd0760 - github.com/smartcontractkit/chainlink-testing-framework/lib v1.50.19 - github.com/smartcontractkit/chainlink-testing-framework/seth v1.50.9 + github.com/smartcontractkit/chainlink-common v0.3.1-0.20241114134822-aadff98ef068 + github.com/smartcontractkit/chainlink-testing-framework/lib v1.50.13 + github.com/smartcontractkit/chainlink-testing-framework/seth v1.50.5 github.com/smartcontractkit/chainlink-testing-framework/wasp v1.50.2 + github.com/smartcontractkit/chainlink/deployment v0.0.0-00010101000000-000000000000 + github.com/smartcontractkit/chainlink/integration-tests v0.0.0-20241030133659-9ec788e78b4f + github.com/smartcontractkit/chainlink/v2 v2.14.0-mercury-20240807.0.20241106193309-5560cd76211a github.com/smartcontractkit/tdh2/go/tdh2 v0.0.0-20241009055228-33d0c0bf38de github.com/stretchr/testify v1.9.0 github.com/wiremock/go-wiremock v1.9.0 go.uber.org/ratelimit v0.3.1 - golang.org/x/exp v0.0.0-20241009180824-f66d83c29e7c ) require ( @@ -46,6 +38,57 @@ require ( cosmossdk.io/errors v1.0.1 // indirect cosmossdk.io/math v1.3.0 // indirect dario.cat/mergo v1.0.1 // indirect + github.com/awalterschulze/gographviz v2.0.3+incompatible // indirect + github.com/aws/aws-sdk-go-v2 v1.32.2 // indirect + github.com/aws/aws-sdk-go-v2/config v1.28.0 // indirect + github.com/aws/aws-sdk-go-v2/credentials v1.17.41 // indirect + github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.17 // indirect + github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.21 // indirect + github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.21 // indirect + github.com/aws/aws-sdk-go-v2/internal/ini v1.8.1 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.0 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.2 // indirect + github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.34.2 // indirect + github.com/aws/aws-sdk-go-v2/service/sso v1.24.2 // indirect + github.com/aws/aws-sdk-go-v2/service/ssooidc v1.28.2 // indirect + github.com/aws/aws-sdk-go-v2/service/sts v1.32.2 // indirect + github.com/aws/smithy-go v1.22.0 // indirect + github.com/blang/semver/v4 v4.0.0 // indirect + github.com/bytedance/sonic/loader v0.1.1 // indirect + github.com/cloudwego/base64x v0.1.4 // indirect + github.com/cloudwego/iasm v0.2.0 // indirect + github.com/coder/websocket v1.8.12 // indirect + github.com/go-viper/mapstructure/v2 v2.1.0 // indirect + github.com/golang-jwt/jwt/v4 v4.5.0 // indirect + github.com/google/gnostic-models v0.6.9-0.20230804172637-c7be7c783f49 // indirect + github.com/linxGnu/grocksdb v1.7.16 // indirect + github.com/russross/blackfriday/v2 v2.1.0 // indirect + github.com/sagikazarmark/locafero v0.4.0 // indirect + github.com/sagikazarmark/slog-shim v0.1.0 // indirect + github.com/smartcontractkit/chainlink-ccip v0.0.0-20241118091009-43c2b4804cec // indirect + github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241017133723-5277829bd53f // indirect + github.com/smartcontractkit/chainlink-testing-framework/havoc v1.50.2 // indirect + github.com/smartcontractkit/grpc-proxy v0.0.0-20240830132753-a7e17fec5ab7 // indirect + github.com/sourcegraph/conc v0.3.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc v0.0.0-20240823153156-2a54df7bffb9 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.6.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.28.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.30.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.30.0 // indirect + go.opentelemetry.io/otel/exporters/stdout/stdoutlog v0.4.0 // indirect + go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.28.0 // indirect + go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.28.0 // indirect + go.opentelemetry.io/otel/log v0.6.0 // indirect + go.opentelemetry.io/otel/sdk/log v0.6.0 // indirect + go.opentelemetry.io/otel/sdk/metric v1.31.0 // indirect + gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect + k8s.io/apimachinery v0.31.1 // indirect +) + +// avoids ambigious imports of indirect dependencies +exclude github.com/hashicorp/consul v1.2.1 + +require ( filippo.io/edwards25519 v1.1.0 // indirect github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 // indirect github.com/99designs/keyring v1.2.1 // indirect @@ -72,30 +115,15 @@ require ( github.com/VictoriaMetrics/fastcache v1.12.2 // indirect github.com/XSAM/otelsql v0.27.0 // indirect github.com/alecthomas/units v0.0.0-20240626203959-61d1e3462e30 // indirect - github.com/andybalholm/brotli v1.1.1 // indirect + github.com/andybalholm/brotli v1.1.0 // indirect github.com/armon/go-metrics v0.4.1 // indirect github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect github.com/atombender/go-jsonschema v0.16.1-0.20240916205339-a74cd4e2851c // indirect github.com/avast/retry-go v3.0.0+incompatible // indirect github.com/avast/retry-go/v4 v4.6.0 // indirect - github.com/awalterschulze/gographviz v2.0.3+incompatible // indirect github.com/aws/aws-sdk-go v1.54.19 // indirect - github.com/aws/aws-sdk-go-v2 v1.32.2 // indirect - github.com/aws/aws-sdk-go-v2/config v1.28.0 // indirect - github.com/aws/aws-sdk-go-v2/credentials v1.17.41 // indirect - github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.17 // indirect - github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.21 // indirect - github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.21 // indirect - github.com/aws/aws-sdk-go-v2/internal/ini v1.8.1 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.0 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.2 // indirect - github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.34.2 // indirect - github.com/aws/aws-sdk-go-v2/service/sso v1.24.2 // indirect - github.com/aws/aws-sdk-go-v2/service/ssooidc v1.28.2 // indirect - github.com/aws/aws-sdk-go-v2/service/sts v1.32.2 // indirect github.com/aws/constructs-go/constructs/v10 v10.4.2 // indirect github.com/aws/jsii-runtime-go v1.104.0 // indirect - github.com/aws/smithy-go v1.22.0 // indirect github.com/bahlo/generic-list-go v0.2.0 // indirect github.com/barkimedes/go-deepcopy v0.0.0-20220514131651-17c30cfc62df // indirect github.com/bboreham/go-loser v0.0.0-20230920113527-fcc2c21820a3 // indirect @@ -103,13 +131,11 @@ require ( github.com/beorn7/perks v1.0.1 // indirect github.com/bgentry/speakeasy v0.1.1-0.20220910012023-760eaf8b6816 // indirect github.com/bits-and-blooms/bitset v1.13.0 // indirect - github.com/blang/semver/v4 v4.0.0 // indirect github.com/blendle/zapdriver v1.3.1 // indirect github.com/btcsuite/btcd/btcec/v2 v2.3.4 // indirect github.com/buger/jsonparser v1.1.1 // indirect github.com/bytecodealliance/wasmtime-go/v23 v23.0.0 // indirect github.com/bytedance/sonic v1.11.6 // indirect - github.com/bytedance/sonic/loader v0.1.1 // indirect github.com/c2h5oh/datasize v0.0.0-20220606134207-859f65c6625b // indirect github.com/c9s/goprocinfo v0.0.0-20210130143923-c95fcf8c64a8 // indirect github.com/cdk8s-team/cdk8s-core-go/cdk8s/v2 v2.7.5 // indirect @@ -119,15 +145,12 @@ require ( github.com/cespare/xxhash/v2 v2.3.0 // indirect github.com/chai2010/gettext-go v1.0.2 // indirect github.com/chaos-mesh/chaos-mesh/api v0.0.0-20240821051457-da69c6d9617a // indirect - github.com/cloudwego/base64x v0.1.4 // indirect - github.com/cloudwego/iasm v0.2.0 // indirect github.com/cockroachdb/errors v1.11.3 // indirect github.com/cockroachdb/fifo v0.0.0-20240606204812-0bbfbd93a7ce // indirect github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b // indirect github.com/cockroachdb/pebble v1.1.2 // indirect github.com/cockroachdb/redact v1.1.5 // indirect github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 // indirect - github.com/coder/websocket v1.8.12 // indirect github.com/cometbft/cometbft v0.37.5 // indirect github.com/cometbft/cometbft-db v0.8.0 // indirect github.com/confio/ics23/go v0.9.0 // indirect @@ -213,24 +236,21 @@ require ( github.com/go-playground/universal-translator v0.18.1 // indirect github.com/go-playground/validator/v10 v10.22.0 // indirect github.com/go-redis/redis/v8 v8.11.5 // indirect - github.com/go-viper/mapstructure/v2 v2.1.0 // indirect github.com/go-webauthn/webauthn v0.9.4 // indirect github.com/go-webauthn/x v0.1.5 // indirect - github.com/goccy/go-json v0.10.3 // indirect + github.com/goccy/go-json v0.10.2 // indirect github.com/goccy/go-yaml v1.12.0 // indirect github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2 // indirect github.com/gofrs/flock v0.8.1 // indirect github.com/gogo/googleapis v1.4.1 // indirect github.com/gogo/protobuf v1.3.3 // indirect github.com/gogo/status v1.1.1 // indirect - github.com/golang-jwt/jwt/v4 v4.5.0 // indirect github.com/golang-jwt/jwt/v5 v5.2.1 // indirect github.com/golang/glog v1.2.2 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/golang/protobuf v1.5.4 // indirect github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb // indirect github.com/google/btree v1.1.2 // indirect - github.com/google/gnostic-models v0.6.9-0.20230804172637-c7be7c783f49 // indirect github.com/google/go-cmp v0.6.0 // indirect github.com/google/go-github/v41 v41.0.0 // indirect github.com/google/go-querystring v1.1.0 // indirect @@ -312,17 +332,16 @@ require ( github.com/json-iterator/go v1.1.12 // indirect github.com/julienschmidt/httprouter v1.3.0 // indirect github.com/kelseyhightower/envconfig v1.4.0 // indirect - github.com/klauspost/compress v1.17.11 // indirect - github.com/klauspost/cpuid/v2 v2.2.8 // indirect + github.com/klauspost/compress v1.17.9 // indirect + github.com/klauspost/cpuid/v2 v2.2.7 // indirect github.com/kr/pretty v0.3.1 // indirect github.com/kr/text v0.2.0 // indirect github.com/kylelemons/godebug v1.1.0 // indirect - github.com/leanovate/gopter v0.2.11 // indirect + github.com/leanovate/gopter v0.2.10-0.20210127095200-9abe2343507a // indirect github.com/leodido/go-urn v1.4.0 // indirect github.com/lib/pq v1.10.9 // indirect github.com/libp2p/go-buffer-pool v0.1.0 // indirect github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de // indirect - github.com/linxGnu/grocksdb v1.7.16 // indirect github.com/logrusorgru/aurora v2.0.3+incompatible // indirect github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect github.com/magiconair/properties v1.8.7 // indirect @@ -386,11 +405,8 @@ require ( github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect github.com/rivo/uniseg v0.4.4 // indirect github.com/robfig/cron/v3 v3.0.1 // indirect - github.com/rogpeppe/go-internal v1.13.1 // indirect + github.com/rogpeppe/go-internal v1.12.0 // indirect github.com/rs/cors v1.10.1 // indirect - github.com/russross/blackfriday/v2 v2.1.0 // indirect - github.com/sagikazarmark/locafero v0.4.0 // indirect - github.com/sagikazarmark/slog-shim v0.1.0 // indirect github.com/sanity-io/litter v1.5.5 // indirect github.com/santhosh-tekuri/jsonschema/v5 v5.3.1 // indirect github.com/sasha-s/go-deadlock v0.3.1 // indirect @@ -398,31 +414,25 @@ require ( github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529 // indirect github.com/segmentio/ksuid v1.0.4 // indirect github.com/sercand/kuberesolver/v5 v5.1.1 // indirect - github.com/sethvargo/go-retry v0.2.4 // indirect github.com/shirou/gopsutil v3.21.11+incompatible // indirect github.com/shirou/gopsutil/v3 v3.24.3 // indirect github.com/shoenig/go-m1cpu v0.1.6 // indirect github.com/shoenig/test v0.6.6 // indirect github.com/shopspring/decimal v1.4.0 // indirect github.com/sirupsen/logrus v1.9.3 // indirect - github.com/smartcontractkit/chain-selectors v1.0.34 // indirect + github.com/smartcontractkit/chain-selectors v1.0.29 // indirect github.com/smartcontractkit/chainlink-automation v0.8.1 // indirect - github.com/smartcontractkit/chainlink-ccip v0.0.0-20241218114855-f74219171000 // indirect - github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241202195413-82468150ac1e // indirect - github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20241216163550-fa030d178ba3 // indirect + github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20241018134907-a00ba3729b5e // indirect github.com/smartcontractkit/chainlink-feeds v0.1.1 // indirect - github.com/smartcontractkit/chainlink-protos/orchestrator v0.4.0 // indirect - github.com/smartcontractkit/chainlink-solana v1.1.1-0.20241219173444-150f7443fdd3 // indirect - github.com/smartcontractkit/chainlink-starknet/relayer v0.1.1-0.20241202202529-2033490e77b8 // indirect - github.com/smartcontractkit/chainlink-testing-framework/havoc v1.50.2 // indirect + github.com/smartcontractkit/chainlink-protos/orchestrator v0.3.0 // indirect + github.com/smartcontractkit/chainlink-solana v1.1.1-0.20241115191142-8b8369c1f44e // indirect + github.com/smartcontractkit/chainlink-starknet/relayer v0.1.1-0.20241017135645-176a23722fd8 // indirect github.com/smartcontractkit/chainlink-testing-framework/lib/grafana v1.50.0 // indirect - github.com/smartcontractkit/grpc-proxy v0.0.0-20240830132753-a7e17fec5ab7 // indirect github.com/smartcontractkit/libocr v0.0.0-20241007185508-adbe57025f12 // indirect github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20241009055228-33d0c0bf38de // indirect - github.com/smartcontractkit/wsrpc v0.8.3 // indirect + github.com/smartcontractkit/wsrpc v0.8.2 // indirect github.com/soheilhy/cmux v0.1.5 // indirect github.com/sony/gobreaker v0.5.0 // indirect - github.com/sourcegraph/conc v0.3.0 // indirect github.com/spf13/afero v1.11.0 // indirect github.com/spf13/cast v1.6.0 // indirect github.com/spf13/cobra v1.8.1 // indirect @@ -475,21 +485,10 @@ require ( go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.56.0 // indirect go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.56.0 // indirect go.opentelemetry.io/otel v1.31.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc v0.0.0-20240823153156-2a54df7bffb9 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.6.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.28.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.30.0 // indirect go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.30.0 // indirect go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.28.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.30.0 // indirect - go.opentelemetry.io/otel/exporters/stdout/stdoutlog v0.4.0 // indirect - go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.28.0 // indirect - go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.28.0 // indirect - go.opentelemetry.io/otel/log v0.6.0 // indirect go.opentelemetry.io/otel/metric v1.31.0 // indirect go.opentelemetry.io/otel/sdk v1.31.0 // indirect - go.opentelemetry.io/otel/sdk/log v0.6.0 // indirect - go.opentelemetry.io/otel/sdk/metric v1.31.0 // indirect go.opentelemetry.io/otel/trace v1.31.0 // indirect go.opentelemetry.io/proto/otlp v1.3.1 // indirect go.starlark.net v0.0.0-20230525235612-a134d8f9ddca // indirect @@ -499,40 +498,39 @@ require ( go.uber.org/zap v1.27.0 // indirect go4.org/netipx v0.0.0-20230125063823-8449b0a6169f // indirect golang.org/x/arch v0.11.0 // indirect - golang.org/x/crypto v0.31.0 // indirect + golang.org/x/crypto v0.28.0 // indirect + golang.org/x/exp v0.0.0-20241009180824-f66d83c29e7c // indirect golang.org/x/mod v0.21.0 // indirect golang.org/x/net v0.30.0 // indirect golang.org/x/oauth2 v0.23.0 // indirect - golang.org/x/sync v0.10.0 // indirect - golang.org/x/sys v0.28.0 // indirect - golang.org/x/term v0.27.0 // indirect - golang.org/x/text v0.21.0 // indirect + golang.org/x/sync v0.8.0 // indirect + golang.org/x/sys v0.26.0 // indirect + golang.org/x/term v0.25.0 // indirect + golang.org/x/text v0.19.0 // indirect golang.org/x/time v0.7.0 // indirect golang.org/x/tools v0.26.0 // indirect golang.org/x/xerrors v0.0.0-20240903120638-7835f813f4da // indirect gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect gonum.org/v1/gonum v0.15.1 // indirect google.golang.org/genproto v0.0.0-20241021214115-324edc3d5d38 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20241104194629-dd2ea8efbc28 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20241104194629-dd2ea8efbc28 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20241021214115-324edc3d5d38 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20241021214115-324edc3d5d38 // indirect google.golang.org/grpc v1.67.1 // indirect google.golang.org/protobuf v1.35.1 // indirect - gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect gopkg.in/guregu/null.v4 v4.0.0 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/natefinch/lumberjack.v2 v2.2.1 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect - k8s.io/api v0.31.2 // indirect + k8s.io/api v0.31.1 // indirect k8s.io/apiextensions-apiserver v0.31.0 // indirect - k8s.io/apimachinery v0.31.2 // indirect - k8s.io/cli-runtime v0.31.2 // indirect - k8s.io/client-go v0.31.2 // indirect - k8s.io/component-base v0.31.2 // indirect + k8s.io/cli-runtime v0.31.1 // indirect + k8s.io/client-go v0.31.1 // indirect + k8s.io/component-base v0.31.1 // indirect k8s.io/klog/v2 v2.130.1 // indirect k8s.io/kube-openapi v0.0.0-20240709000822-3c01b740850f // indirect - k8s.io/kubectl v0.31.2 // indirect + k8s.io/kubectl v0.31.1 // indirect k8s.io/utils v0.0.0-20240711033017-18e509b52bc8 // indirect pgregory.net/rapid v1.1.0 // indirect rsc.io/tmplfunc v0.0.3 // indirect @@ -541,12 +539,9 @@ require ( sigs.k8s.io/kustomize/api v0.17.2 // indirect sigs.k8s.io/kustomize/kyaml v0.17.1 // indirect sigs.k8s.io/structured-merge-diff/v4 v4.4.1 // indirect - sigs.k8s.io/yaml v1.4.0 // indirect + sigs.k8s.io/yaml v1.4.0 // indirect; indirect nhooyr.io/websocket v1.8.7 // indirect ) -// avoids ambigious imports of indirect dependencies -exclude github.com/hashicorp/consul v1.2.1 - replace ( // geth wants v2.3.4 but that is incompatible with github.com/cometbft/cometbft v0.37.5 which when bumped is incompatible with github.com/cosmos/cosmos-sdk // This line can be removed after these imports are bumped or removed. diff --git a/integration-tests/load/go.sum b/integration-tests/load/go.sum index bb187d252b5..9b3962dd1a5 100644 --- a/integration-tests/load/go.sum +++ b/integration-tests/load/go.sum @@ -16,11 +16,6 @@ cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKV cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs= cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc= cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= -cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI= -cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk= -cloud.google.com/go v0.78.0/go.mod h1:QjdrLG0uq+YwhjoVOLsS1t7TW8fs36kLs4XO5R5ECHg= -cloud.google.com/go v0.79.0/go.mod h1:3bzgcEeQlzbuEAYu4mrWhKqWjmpprinYgKJLgKHnbb8= -cloud.google.com/go v0.81.0/go.mod h1:mk/AM35KwGk/Nm2YSeZbxXdrNK3KZOYHmLkOqC2V6E0= cloud.google.com/go v0.116.0 h1:B3fRrSDkLRt5qSHWe40ERJvhvnQwdZiHu0bJOpldweE= cloud.google.com/go v0.116.0/go.mod h1:cEPSRWPzZEswwdr9BxE6ChEn01dWlTaF05LiC2Xs70U= cloud.google.com/go/auth v0.9.9 h1:BmtbpNQozo8ZwW2t7QJjnrQtdganSdmqeIBxHxNkEZQ= @@ -120,12 +115,12 @@ github.com/Depado/ginprom v1.8.0 h1:zaaibRLNI1dMiiuj1MKzatm8qrcHzikMlCc1anqOdyo= github.com/Depado/ginprom v1.8.0/go.mod h1:XBaKzeNBqPF4vxJpNLincSQZeMDnZp1tIbU0FU0UKgg= github.com/GeertJohan/go.incremental v1.0.0/go.mod h1:6fAjUhbVuX1KcMD3c8TEgVUqmo4seqhv0i0kdATSkM0= github.com/GeertJohan/go.rice v1.0.0/go.mod h1:eH6gbSOAUv07dQuZVnBmoDP8mgsM1rtixis4Tib9if0= -github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.25.0 h1:3c8yed4lgqTt+oTQ+JNMDo+F4xprBf+O/il4ZC0nRLw= -github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.25.0/go.mod h1:obipzmGjfSjam60XLwGfqUkJsfiheAl+TUjG+4yzyPM= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.24.3 h1:cb3br57K508pQEFgBxn9GDhPS9HefpyMPK1RzmtMNzk= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.24.3/go.mod h1:itPGVDKf9cC/ov4MdvJ2QZ0khw4bfoo9jzwTJlaxy2k= github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.48.3 h1:xir5X8TS8UBVPWg2jHL+cSTf0jZgqYQSA54TscSt1/0= github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.48.3/go.mod h1:SsdWig2J5PMnfMvfJuEb1uZa8Y+kvNyvrULFo69gTFk= -github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.49.0 h1:GYUJLfvd++4DMuMhCFLgLXvFwofIxh/qOwoGuS/LTew= -github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.49.0/go.mod h1:wRbFgBQUVm1YXrvWKofAEmq9HNJTDphbAaJSSX01KUI= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.48.3 h1:2vcVkrNdSMJpoOVAWi9ApsQR5iqNeFGt5Qx8Xlt3IoI= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.48.3/go.mod h1:wRbFgBQUVm1YXrvWKofAEmq9HNJTDphbAaJSSX01KUI= github.com/HdrHistogram/hdrhistogram-go v1.1.2 h1:5IcZpTvzydCQeHzK4Ef/D5rrSqwxob0t8PQPMybUNFM= github.com/HdrHistogram/hdrhistogram-go v1.1.2/go.mod h1:yDgFjdqOqDEKOvasDdhWNXYg9BVp4O+o5f6V/ehm6Oo= github.com/K-Phoen/grabana v0.22.2 h1:tMiSvcKHnDbXi3IgBCax2+sg5qL6x0G6wMURHgjGDag= @@ -184,11 +179,9 @@ github.com/allegro/bigcache v1.2.1/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2uc github.com/andres-erbsen/clock v0.0.0-20160526145045-9e14626cd129/go.mod h1:rFgpPQZYZ8vdbc+48xibu8ALc3yeyd64IhHS+PU6Yyg= github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883 h1:bvNMNQO63//z+xNgfBlViaCIJKLlCJ6/fmUseuG0wVQ= github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8= -github.com/andybalholm/brotli v1.1.1 h1:PR2pgnyFznKEugtsUo0xLdDop5SKXd5Qf5ysW+7XdTA= -github.com/andybalholm/brotli v1.1.1/go.mod h1:05ib4cKhjx3OQYUY22hTVd34Bc8upXjOLL2rKwwZBoA= +github.com/andybalholm/brotli v1.1.0 h1:eLKJA0d02Lf0mVpIDgYnqXcUn0GqVmEFny3VuID1U3M= +github.com/andybalholm/brotli v1.1.0/go.mod h1:sms7XGricyQI9K10gOSf56VKKWS4oLer58Q+mhRPtnY= github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= -github.com/apache/arrow-go/v18 v18.0.0 h1:1dBDaSbH3LtulTyOVYaBCHO3yVRwjV+TZaqn3g6V7ZM= -github.com/apache/arrow-go/v18 v18.0.0/go.mod h1:t6+cWRSmKgdQ6HsxisQjok+jBpKGhRDiqcf3p0p/F+A= github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= @@ -266,7 +259,6 @@ github.com/bgentry/speakeasy v0.1.1-0.20220910012023-760eaf8b6816/go.mod h1:+zsy github.com/bits-and-blooms/bitset v1.13.0 h1:bAQ9OPNFYbGHV6Nez0tmNI0RiEu7/hxlYJRUA0wFAVE= github.com/bits-and-blooms/bitset v1.13.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8= github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84= -github.com/bketelsen/crypt v0.0.4/go.mod h1:aI6NrJ0pMGgvZKL1iVgXLnfIFJtfV+bKCoqOes/6LfM= github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM= github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ= github.com/blendle/zapdriver v1.3.1 h1:C3dydBOWYRiOk+B8X9IVZ5IOe+7cl+tGOexN4QqHfpE= @@ -274,10 +266,10 @@ github.com/blendle/zapdriver v1.3.1/go.mod h1:mdXfREi6u5MArG4j9fewC+FGnXaBR+T4Ox github.com/btcsuite/btcd v0.22.1 h1:CnwP9LM/M9xuRrGSCGeMVs9iv09uMqwsVX7EeIpgV2c= github.com/btcsuite/btcd/btcec/v2 v2.3.2 h1:5n0X6hX0Zk+6omWcihdYvdAlGf2DfasC0GMf7DClJ3U= github.com/btcsuite/btcd/btcec/v2 v2.3.2/go.mod h1:zYzJ8etWJQIv1Ogk7OzpWjowwOdXY1W/17j2MW85J04= -github.com/btcsuite/btcd/btcutil v1.1.5 h1:+wER79R5670vs/ZusMTF1yTcRYE5GUsFbdjdisflzM8= -github.com/btcsuite/btcd/btcutil v1.1.5/go.mod h1:PSZZ4UitpLBWzxGd5VGOrLnmOjtPP/a6HaFo12zMs00= -github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0 h1:59Kx4K6lzOW5w6nFlA0v5+lk/6sjybR934QNHSJZPTQ= -github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= +github.com/btcsuite/btcd/btcutil v1.1.3 h1:xfbtw8lwpp0G6NwSHb+UE67ryTFHJAiNuipusjXSohQ= +github.com/btcsuite/btcd/btcutil v1.1.3/go.mod h1:UR7dsSJzJUfMmFiiLlIrMq1lS9jh9EdCV7FStZSnpi0= +github.com/btcsuite/btcd/chaincfg/chainhash v1.0.3 h1:SDlJ7bAm4ewvrmZtR0DaiYbQGdKPeaaIm7bM+qRhFeU= +github.com/btcsuite/btcd/chaincfg/chainhash v1.0.3/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= github.com/bufbuild/protocompile v0.4.0 h1:LbFKd2XowZvQ/kajzguUp2DC9UEIQhIq77fZZlaQsNA= github.com/bufbuild/protocompile v0.4.0/go.mod h1:3v93+mbWn/v3xzN+31nwkJfrEpAUwp+BagBSZWx+TP8= github.com/buger/jsonparser v1.1.1 h1:2PnMjfWD7wBILjqQbt530v576A/cAbQvEW9gGIpYMUs= @@ -328,7 +320,6 @@ github.com/cloudwego/base64x v0.1.4/go.mod h1:0zlkT4Wn5C6NdauXdJRhSKRlJvmclQ1hhJ github.com/cloudwego/iasm v0.2.0 h1:1KNIy1I1H9hNNFEEH3DVnI4UujN+1zjpuk6gwHLTssg= github.com/cloudwego/iasm v0.2.0/go.mod h1:8rXZaNYT2n95jn+zTI1sDr+IgcD2GVs0nlbbQPiEFhY= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= -github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cncf/xds/go v0.0.0-20240723142845-024c85f92f20 h1:N+3sFI5GUjRKBi+i0TxYVST9h4Ie192jJWpHvthBBgg= github.com/cncf/xds/go v0.0.0-20240723142845-024c85f92f20/go.mod h1:W+zGtBO5Y1IgJhy4+A9GOqVhqLpfZi+vwmdNXUehLA8= @@ -380,7 +371,6 @@ github.com/coreos/go-semver v0.3.1 h1:yi21YpKnrx1gt5R+la8n5WgS0kCrsPp33dmEyHReZr github.com/coreos/go-semver v0.3.1/go.mod h1:irMmmIw/7yzSRPWryHsK7EYSg09caPQL03VsM8rvUec= github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= -github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs= github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= @@ -485,9 +475,7 @@ github.com/emicklei/go-restful/v3 v3.12.1/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRr github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= -github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po= github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= -github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= github.com/envoyproxy/go-control-plane v0.13.0 h1:HzkeUz1Knt+3bK+8LG1bxOO/jzWZmdxpwC51i202les= github.com/envoyproxy/go-control-plane v0.13.0/go.mod h1:GRaKG3dwvFoTg4nj7aXdZnvMg4d7nvT/wl9WgVXn3Q8= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= @@ -546,8 +534,8 @@ github.com/gedex/inflector v0.0.0-20170307190818-16278e9db813/go.mod h1:P+oSoE9y github.com/getsentry/sentry-go v0.27.0 h1:Pv98CIbtB3LkMWmXi4Joa5OOcwbmnX88sF5qbK3r3Ps= github.com/getsentry/sentry-go v0.27.0/go.mod h1:lc76E2QywIyW8WuBnwl8Lc4bkmQH4+w1gwTf25trprY= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= -github.com/gin-contrib/cors v1.7.2 h1:oLDHxdg8W/XDoN/8zamqk/Drgt4oVZDvaV0YmvVICQw= -github.com/gin-contrib/cors v1.7.2/go.mod h1:SUJVARKgQ40dmrzgXEVxj2m7Ig1v1qIboQkPDTQ9t2E= +github.com/gin-contrib/cors v1.5.0 h1:DgGKV7DDoOn36DFkNtbHrjoRiT5ExCe+PC9/xp7aKvk= +github.com/gin-contrib/cors v1.5.0/go.mod h1:TvU7MAZ3EwrPLI2ztzTt3tqgvBCq+wn8WpZmfADjupI= github.com/gin-contrib/expvar v0.0.1 h1:IuU5ArEgihz50vG8Onrwz22kJr7Mcvgv9xSSpfU5g+w= github.com/gin-contrib/expvar v0.0.1/go.mod h1:8o2CznfQi1JjktORdHr2/abg3wSV6OCnXh0yGypvvVw= github.com/gin-contrib/sessions v0.0.5 h1:CATtfHmLMQrMNpJRgzjWXD7worTh7g7ritsQfmF+0jE= @@ -638,8 +626,8 @@ github.com/go-webauthn/x v0.1.5 h1:V2TCzDU2TGLd0kSZOXdrqDVV5JB9ILnKxA9S53CSBw0= github.com/go-webauthn/x v0.1.5/go.mod h1:qbzWwcFcv4rTwtCLOZd+icnr6B7oSsAGZJqlt8cukqY= github.com/go-zookeeper/zk v1.0.3 h1:7M2kwOsc//9VeeFiPtf+uSJlVpU66x9Ba5+8XK7/TDg= github.com/go-zookeeper/zk v1.0.3/go.mod h1:nOB03cncLtlp4t+UAkGSV+9beXP/akpekBwL+UX1Qcw= -github.com/goccy/go-json v0.10.3 h1:KZ5WoDbxAIgm2HNbYckL0se1fHD6rz5j4ywS6ebzDqA= -github.com/goccy/go-json v0.10.3/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M= +github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU= +github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= github.com/goccy/go-yaml v1.12.0 h1:/1WHjnMsI1dlIBQutrvSMGZRQufVO3asrHfTwfACoPM= github.com/goccy/go-yaml v1.12.0/go.mod h1:wKnAMd44+9JAAnGQpWVEgBzGt3YuTaQ4uXoHvE4m7WU= github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2 h1:ZpnhV/YsD2/4cESfV5+Hoeu/iUR3ruzNvZ+yQfO03a0= @@ -675,7 +663,6 @@ github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= -github.com/golang/mock v1.5.0/go.mod h1:CWnOUgYIOo4TcNZ0wHX3YZCqsaM1I1Jvs6v3mP3KVu8= github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc= github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= @@ -707,8 +694,6 @@ github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Z github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.1.2 h1:xf4v41cLI2Z6FxbKm+8Bu+m8ifhj15JuZ9sa0jZCMUU= github.com/google/btree v1.1.2/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4= -github.com/google/flatbuffers v24.3.25+incompatible h1:CX395cjN9Kke9mmalRoL3d81AtFUxJM+yDthflgJGkI= -github.com/google/flatbuffers v24.3.25+incompatible/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8= github.com/google/gnostic-models v0.6.9-0.20230804172637-c7be7c783f49 h1:0VpGH+cDhbDtdcweoyCVsF3fhN8kejK6rFe/2FFX2nU= github.com/google/gnostic-models v0.6.9-0.20230804172637-c7be7c783f49/go.mod h1:BkkQ4L1KS1xMt2aWSPStnn55ChGC0DPOn2FQYj+f25M= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= @@ -739,7 +724,6 @@ github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= -github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= github.com/google/orderedcode v0.0.1 h1:UzfcAexk9Vhv8+9pNOgRu41f16lHq725vPwnSeiG/Us= github.com/google/orderedcode v0.0.1/go.mod h1:iVyU4/qPKHY5h/wSd6rZZCDcLJNxiWO6dvsYES2Sb20= github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= @@ -749,10 +733,6 @@ github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hf github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20240827171923-fa2c70bbbfe5 h1:5iH8iuqE5apketRbSFBy+X1V0o+l+8NF1avt4HWl7cA= github.com/google/pprof v0.0.0-20240827171923-fa2c70bbbfe5/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144= @@ -771,12 +751,11 @@ github.com/googleapis/enterprise-certificate-proxy v0.3.2 h1:Vie5ybvEvT75RniqhfF github.com/googleapis/enterprise-certificate-proxy v0.3.2/go.mod h1:VLSiSSBs/ksPL8kq3OBOQ6WRI2QnaFynd1DCjZ62+V0= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= -github.com/googleapis/gax-go/v2 v2.14.0 h1:f+jMrjBPl+DL9nI4IQzLUxMq7XrAqFYB7hBPqMNIe8o= -github.com/googleapis/gax-go/v2 v2.14.0/go.mod h1:lhBCnjdLrWRaPvLWhmc8IS24m9mr07qSYnHncrgo+zk= +github.com/googleapis/gax-go/v2 v2.13.0 h1:yitjD5f7jQHhyDsnhKEBU52NdvvdSeGzlAnDPT0hH1s= +github.com/googleapis/gax-go/v2 v2.13.0/go.mod h1:Z/fvTZXF8/uw7Xu5GuslPw+bplx6SS338j1Is2S+B7A= github.com/gophercloud/gophercloud v1.13.0 h1:8iY9d1DAbzMW6Vok1AxbbK5ZaUjzMp0tdyt4fX9IeJ0= github.com/gophercloud/gophercloud v1.13.0/go.mod h1:aAVqcocTSXh2vYFZ1JTvx4EQmfgzxRcNupUfxZbBNDM= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= -github.com/gopherjs/gopherjs v1.17.2/go.mod h1:pRRIvn/QzFLrKfvEz3qUuEhtE/zLCWfreZ6J5gM2i+k= github.com/gorilla/context v1.1.1 h1:AWwleXJkX/nhcU9bZSnZoi3h/qGYqQAGhq6zZe/aQW8= github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= github.com/gorilla/handlers v1.5.1 h1:9lRY6j8DEeeBT10CvO9hGW0gmky0BprnvDI5vfhUHH4= @@ -1039,18 +1018,17 @@ github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+o github.com/klauspost/compress v1.11.4/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= github.com/klauspost/compress v1.12.3/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg= github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= -github.com/klauspost/compress v1.17.11 h1:In6xLpyWOi1+C7tXUUWv2ot1QvBjxevKAaI6IXrJmUc= -github.com/klauspost/compress v1.17.11/go.mod h1:pMDklpSncoRMuLFrf1W9Ss9KT+0rH90U12bZKk7uwG0= +github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA= +github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= -github.com/klauspost/cpuid/v2 v2.2.8 h1:+StwCXwm9PdpiEkPyzBXIy+M9KUb4ODm0Zarf1kS5BM= -github.com/klauspost/cpuid/v2 v2.2.8/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws= +github.com/klauspost/cpuid/v2 v2.2.7 h1:ZWSB3igEs+d0qvnxR/ZBzXVmxkgt8DdzP6m9pfuVLDM= +github.com/klauspost/cpuid/v2 v2.2.7/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws= github.com/knz/go-libedit v1.10.1/go.mod h1:MZTVkCWyz0oBc7JOWP3wNAzd002ZbM/5hgShxwh4x8M= github.com/kolo/xmlrpc v0.0.0-20220921171641-a4b6fa1dd06b h1:udzkj9S/zlT5X367kqJis0QP7YMxobob6zhzq6Yre00= github.com/kolo/xmlrpc v0.0.0-20220921171641-a4b6fa1dd06b/go.mod h1:pcaDhQK0/NJZEvtCO0qQPPropqV0sJOJ6YW7X+9kRwM= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= @@ -1063,8 +1041,8 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= -github.com/leanovate/gopter v0.2.11 h1:vRjThO1EKPb/1NsDXuDrzldR28RLkBflWYcU9CvzWu4= -github.com/leanovate/gopter v0.2.11/go.mod h1:aK3tzZP/C+p1m3SPRE4SYZFGP7jjkuSI4f7Xvpt0S9c= +github.com/leanovate/gopter v0.2.10-0.20210127095200-9abe2343507a h1:dHCfT5W7gghzPtfsW488uPmEOm85wewI+ypUwibyTdU= +github.com/leanovate/gopter v0.2.10-0.20210127095200-9abe2343507a/go.mod h1:U2L/78B+KVFIx2VmW6onHJQzXtFb+p5y3y2Sh+Jxxv8= github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ= github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI= github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= @@ -1089,7 +1067,6 @@ github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I= github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= -github.com/magiconair/properties v1.8.5/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= @@ -1098,8 +1075,6 @@ github.com/manifoldco/promptui v0.9.0 h1:3V4HzJk1TtXW1MTZMP7mdlwbBpIinw3HztaIlYt github.com/manifoldco/promptui v0.9.0/go.mod h1:ka04sppxSGFAtxX0qhlYQjISsg9mR4GWtQEhdbn6Pgg= github.com/manyminds/api2go v0.0.0-20171030193247-e7b693844a6f h1:tVvGiZQFjOXP+9YyGqSA6jE55x1XVxmoPYudncxrZ8U= github.com/manyminds/api2go v0.0.0-20171030193247-e7b693844a6f/go.mod h1:Z60vy0EZVSu0bOugCHdcN5ZxFMKSpjRgsnh0XKPFqqk= -github.com/marcboeker/go-duckdb v1.8.3 h1:ZkYwiIZhbYsT6MmJsZ3UPTHrTZccDdM4ztoqSlEMXiQ= -github.com/marcboeker/go-duckdb v1.8.3/go.mod h1:C9bYRE1dPYb1hhfu/SSomm78B0FXmNgRvv6YBW/Hooc= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ= github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= @@ -1207,8 +1182,6 @@ github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f h1:KUppIJq7/+ github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f h1:y5//uYreIhSUg3J1GEMiLbxo1LJaP8RfCpH6pymGZus= github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw= -github.com/neelance/astrewrite v0.0.0-20160511093645-99348263ae86/go.mod h1:kHJEU3ofeGjhHklVoIGuVj85JJwZ6kWPaJwCIxgnFmo= -github.com/neelance/sourcemap v0.0.0-20200213170602-2833bce08e4c/go.mod h1:Qr6/a/Q4r9LP1IltGz7tA7iOK1WonHEYhu1HRBA7ZiM= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= github.com/nkovacs/streamquote v0.0.0-20170412213628-49af9bddb229/go.mod h1:0aYXnNPJ8l7uZxf45rWW1a/uME32OF0rhiYGNQ2oF2E= github.com/nsf/jsondiff v0.0.0-20230430225905-43f6cf3098c1 h1:dOYG7LS/WK00RWZc8XGgcUTlTxpp3mKhdR2Q9z9HbXM= @@ -1265,7 +1238,6 @@ github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTK github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58 h1:onHthvaw9LFnH4t2DcNVpwGmV9E1BkGknEliJkfwQj0= github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58/go.mod h1:DXv8WO4yhMYhSNPKjeNKa5WY9YCIEBRbNzFFPJbWO6Y= github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= -github.com/pelletier/go-toml v1.9.3/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8= github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= github.com/pelletier/go-toml/v2 v2.2.3 h1:YmeHyLY8mFWbdkNWwpr+qIL2bEqT0o95WSdkNHvL12M= @@ -1275,8 +1247,8 @@ github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR github.com/petermattis/goid v0.0.0-20180202154549-b0b1615b78e5/go.mod h1:jvVRKCrJTQWu0XVbaOlby/2lO20uSCHEMzzplHXte1o= github.com/petermattis/goid v0.0.0-20230317030725-371a4b8eda08 h1:hDSdbBuw3Lefr6R18ax0tZ2BJeNB3NehB3trOwYBsdU= github.com/petermattis/goid v0.0.0-20230317030725-371a4b8eda08/go.mod h1:pxMtw7cyUw6B2bRH0ZBANSPg+AoSud1I1iyJHI69jH4= -github.com/pierrec/lz4/v4 v4.1.21 h1:yOVMLb6qSIDP67pl/5F7RepeKYu/VmTyEXvuMI5d9mQ= -github.com/pierrec/lz4/v4 v4.1.21/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= +github.com/pierrec/lz4/v4 v4.1.18 h1:xaKrnTkyoqfh1YItXl56+6KJNVYWlEEPuAQW9xsplYQ= +github.com/pierrec/lz4/v4 v4.1.18/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= github.com/pingcap/errors v0.11.4 h1:lFuQV/oaUMGcD2tqt+01ROSmJs75VG1ToEOkZIZ4nE4= github.com/pingcap/errors v0.11.4/go.mod h1:Oi8TUi2kEtXXLMJk9l1cGmz20kV3TaQ0usTwv5KuLY8= github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c h1:+mdjkGKdHQG3305AYmdv1U2eRNDiU2ErMBj1gwrq8eQ= @@ -1286,7 +1258,6 @@ github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI= github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10 h1:GFCKgmp0tecUJ0sJuv4pzYCqS9+RGSn52M3FUwPs+uo= github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10/go.mod h1:t/avpk3KcrXxUnYOhZhMXJlSEyie6gQbtLq5NM3loB8= github.com/pmezard/go-difflib v0.0.0-20151028094244-d8ed2627bdf0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= @@ -1354,8 +1325,8 @@ github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6So github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= -github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII= -github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o= +github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= +github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= github.com/rs/cors v1.10.1 h1:L0uuZVXIKlI1SShY2nhFfo44TYvDPQ1w4oFkUJNfhyo= github.com/rs/cors v1.10.1/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU= github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ= @@ -1408,51 +1379,43 @@ github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFR github.com/shopspring/decimal v1.3.1/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= github.com/shopspring/decimal v1.4.0 h1:bxl37RwXBklmTi0C79JfXCEBD1cqqHt0bbgBAGFp81k= github.com/shopspring/decimal v1.4.0/go.mod h1:gawqmDU56v4yIKSwfBSFip1HdCCXN8/+DMd9qYNcwME= -github.com/shurcooL/go v0.0.0-20200502201357-93f07166e636/go.mod h1:TDJrrUr11Vxrven61rcy3hJMUqaf/CLWYhHNPmT14Lk= -github.com/shurcooL/httpfs v0.0.0-20190707220628-8d4bc4ba7749/go.mod h1:ZY1cvUeJuFPAdZ/B6v7RHavJWZn2YPVFQ1OSXhCGOkg= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= -github.com/shurcooL/vfsgen v0.0.0-20200824052919-0d455de96546/go.mod h1:TrYk7fJVaAttu97ZZKrO9UbRa8izdowaMIZcxYMbVaw= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= -github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/slack-go/slack v0.15.0 h1:LE2lj2y9vqqiOf+qIIy0GvEoxgF1N5yLGZffmEZykt0= github.com/slack-go/slack v0.15.0/go.mod h1:hlGi5oXA+Gt+yWTPP0plCdRKmjsDxecdHxYQdlMQKOw= -github.com/smartcontractkit/ccip-owner-contracts v0.0.0-salt-fix h1:DPJD++yKLSx0EfT+U14P8vLVxjXFmoIETiCO9lVwQo8= -github.com/smartcontractkit/ccip-owner-contracts v0.0.0-salt-fix/go.mod h1:NnT6w4Kj42OFFXhSx99LvJZWPpMjmo4+CpDEWfw61xY= -github.com/smartcontractkit/chain-selectors v1.0.34 h1:MJ17OGu8+jjl426pcKrJkCf3fePb3eCreuAnUA3RBj4= -github.com/smartcontractkit/chain-selectors v1.0.34/go.mod h1:xsKM0aN3YGcQKTPRPDDtPx2l4mlTN1Djmg0VVXV40b8= +github.com/smartcontractkit/chain-selectors v1.0.29 h1:aZ9+OoUSMn4nqnissHtDvDoKR7JONfDqTHX3MHYIUIE= +github.com/smartcontractkit/chain-selectors v1.0.29/go.mod h1:xsKM0aN3YGcQKTPRPDDtPx2l4mlTN1Djmg0VVXV40b8= github.com/smartcontractkit/chainlink-automation v0.8.1 h1:sTc9LKpBvcKPc1JDYAmgBc2xpDKBco/Q4h4ydl6+UUU= github.com/smartcontractkit/chainlink-automation v0.8.1/go.mod h1:Iij36PvWZ6blrdC5A/nrQUBuf3MH3JvsBB9sSyc9W08= -github.com/smartcontractkit/chainlink-ccip v0.0.0-20241218114855-f74219171000 h1:6Zzr/R1j6P7bbvcUlt5WUIbItvrrGdGzIsiAzQezcwo= -github.com/smartcontractkit/chainlink-ccip v0.0.0-20241218114855-f74219171000/go.mod h1:ncjd6mPZSRlelEqH/2KeLE1pU3UlqzBSn8RYkEoECzY= -github.com/smartcontractkit/chainlink-common v0.4.1-0.20241217120918-bbe318cd0760 h1:lB5A3TP0zOVuu1n0kEm6d8/o/4Knh6HLvsU/GChk+sI= -github.com/smartcontractkit/chainlink-common v0.4.1-0.20241217120918-bbe318cd0760/go.mod h1:yti7e1+G9hhkYhj+L5sVUULn9Bn3bBL5/AxaNqdJ5YQ= -github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241202195413-82468150ac1e h1:PRoeby6ZlTuTkv2f+7tVU4+zboTfRzI+beECynF4JQ0= -github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241202195413-82468150ac1e/go.mod h1:mUh5/woemsVaHgTorA080hrYmO3syBCmPdnWc/5dOqk= -github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20241216163550-fa030d178ba3 h1:aeiBdBHGY8QNftps+VqrIk6OnfeeOD5z4jrAabW4ZSc= -github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20241216163550-fa030d178ba3/go.mod h1:AS6zY2BkcRwfiGzNabGbHhfrLSrXrcI/GmjnT4jQ5/s= +github.com/smartcontractkit/chainlink-ccip v0.0.0-20241118091009-43c2b4804cec h1:5vS1k8Qn09p8SQ3JzvS8iy4Pve7s3aVq+UPIdl74smY= +github.com/smartcontractkit/chainlink-ccip v0.0.0-20241118091009-43c2b4804cec/go.mod h1:4adKaHNaxFsRvV/lYfqtbsWyyvIPUMLR0FdOJN/ljis= +github.com/smartcontractkit/chainlink-common v0.3.1-0.20241114134822-aadff98ef068 h1:2llRW4Tn9W/EZp2XvXclQ9IjeTBwwxVPrrqaerX+vCE= +github.com/smartcontractkit/chainlink-common v0.3.1-0.20241114134822-aadff98ef068/go.mod h1:ny87uTW6hLjCTLiBqBRNFEhETSXhHWevYlPclT5lSco= +github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241017133723-5277829bd53f h1:BwrIaQIx5Iy6eT+DfLhFfK2XqjxRm74mVdlX8gbu4dw= +github.com/smartcontractkit/chainlink-cosmos v0.5.2-0.20241017133723-5277829bd53f/go.mod h1:wHtwSR3F1CQSJJZDQKuqaqFYnvkT+kMyget7dl8Clvo= +github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20241018134907-a00ba3729b5e h1:JiETqdNM0bktAUGMc62COwXIaw3rR3M77Me6bBLG0Fg= +github.com/smartcontractkit/chainlink-data-streams v0.1.1-0.20241018134907-a00ba3729b5e/go.mod h1:iK3BNHKCLgSgkOyiu3iE7sfZ20Qnuk7xwjV/yO/6gnQ= github.com/smartcontractkit/chainlink-feeds v0.1.1 h1:JzvUOM/OgGQA1sOqTXXl52R6AnNt+Wg64sVG+XSA49c= github.com/smartcontractkit/chainlink-feeds v0.1.1/go.mod h1:55EZ94HlKCfAsUiKUTNI7QlE/3d3IwTlsU3YNa/nBb4= -github.com/smartcontractkit/chainlink-protos/job-distributor v0.6.0 h1:0ewLMbAz3rZrovdRUCgd028yOXX8KigB4FndAUdI2kM= -github.com/smartcontractkit/chainlink-protos/job-distributor v0.6.0/go.mod h1:/dVVLXrsp+V0AbcYGJo3XMzKg3CkELsweA/TTopCsKE= -github.com/smartcontractkit/chainlink-protos/orchestrator v0.4.0 h1:ZBat8EBvE2LpSQR9U1gEbRV6PfAkiFdINmQ8nVnXIAQ= -github.com/smartcontractkit/chainlink-protos/orchestrator v0.4.0/go.mod h1:m/A3lqD7ms/RsQ9BT5P2uceYY0QX5mIt4KQxT2G6qEo= -github.com/smartcontractkit/chainlink-solana v1.1.1-0.20241219173444-150f7443fdd3 h1:AIIiwrZ5T4nEjFT33aLZKoXwD63JSMu72wWe/rUdfm0= -github.com/smartcontractkit/chainlink-solana v1.1.1-0.20241219173444-150f7443fdd3/go.mod h1:ARILnIgKelP0YkVzxXO111S9j0b4uKyt7iLpYjOkCtU= -github.com/smartcontractkit/chainlink-starknet/relayer v0.1.1-0.20241202202529-2033490e77b8 h1:tNS7U9lrxkFvEuyxQv11HHOiV9LPDGC9wYEy+yM/Jv4= -github.com/smartcontractkit/chainlink-starknet/relayer v0.1.1-0.20241202202529-2033490e77b8/go.mod h1:EBrEgcdIbwepqguClkv8Ohy7CbyWSJaE4EC9aBJlQK0= +github.com/smartcontractkit/chainlink-protos/orchestrator v0.3.0 h1:PBUaFfPLm+Efq7H9kdfGBivH+QhJ6vB5EZTR/sCZsxI= +github.com/smartcontractkit/chainlink-protos/orchestrator v0.3.0/go.mod h1:m/A3lqD7ms/RsQ9BT5P2uceYY0QX5mIt4KQxT2G6qEo= +github.com/smartcontractkit/chainlink-solana v1.1.1-0.20241115191142-8b8369c1f44e h1:XxTWJ9VIXK+XuAjP5131PqqBn0NEt5lBvnRAWRdqy8A= +github.com/smartcontractkit/chainlink-solana v1.1.1-0.20241115191142-8b8369c1f44e/go.mod h1:mGmRvlk54ufCufV4EBWizOGtXoXfePoFAuYEVC8EwdY= +github.com/smartcontractkit/chainlink-starknet/relayer v0.1.1-0.20241017135645-176a23722fd8 h1:B4DFdk6MGcQnoCjjMBCx7Z+GWQpxRWJ4O8W/dVJyWGA= +github.com/smartcontractkit/chainlink-starknet/relayer v0.1.1-0.20241017135645-176a23722fd8/go.mod h1:WkBqgBo+g34Gm5vWkDDl8Fh3Mzd7bF5hXp7rryg0t5o= github.com/smartcontractkit/chainlink-testing-framework/havoc v1.50.2 h1:GDGrC5OGiV0RyM1znYWehSQXyZQWTOzrEeJRYmysPCE= github.com/smartcontractkit/chainlink-testing-framework/havoc v1.50.2/go.mod h1:DsT43c1oTBmp3iQkMcoZOoKThwZvt8X3Pz6UmznJ4GY= -github.com/smartcontractkit/chainlink-testing-framework/lib v1.50.19 h1:9PMwKNqFKc5FXf4VchyD3CGzZelnSgi13fgVdT2X7T4= -github.com/smartcontractkit/chainlink-testing-framework/lib v1.50.19/go.mod h1:ag7LEgejsVtPXaUNkcoFPpAoDkl1J8V2HSbqVUxfEtk= +github.com/smartcontractkit/chainlink-testing-framework/lib v1.50.13 h1:T0kbw07Vb6xUyA9MIJZfErMgWseWi1zf7cYvRpoq7ug= +github.com/smartcontractkit/chainlink-testing-framework/lib v1.50.13/go.mod h1:1CKUOzoK+Ga19WuhRH9pxZ+qUUnrlIx108VEA6qSzeQ= github.com/smartcontractkit/chainlink-testing-framework/lib/grafana v1.50.0 h1:VIxK8u0Jd0Q/VuhmsNm6Bls6Tb31H/sA3A/rbc5hnhg= github.com/smartcontractkit/chainlink-testing-framework/lib/grafana v1.50.0/go.mod h1:lyAu+oMXdNUzEDScj2DXB2IueY+SDXPPfyl/kb63tMM= -github.com/smartcontractkit/chainlink-testing-framework/seth v1.50.9 h1:yB1x5UXvpZNka+5h57yo1/GrKfXKCqMzChCISpldZx4= -github.com/smartcontractkit/chainlink-testing-framework/seth v1.50.9/go.mod h1:lJk0atEJ5Zyo3Tqrmf1Pl9jUEe79EgDb9bD3K5OTUBI= +github.com/smartcontractkit/chainlink-testing-framework/seth v1.50.5 h1:BxN9wddNLiugruN3k7nYoSMQTO0tz9qR+vILFW2l0Ps= +github.com/smartcontractkit/chainlink-testing-framework/seth v1.50.5/go.mod h1:lJk0atEJ5Zyo3Tqrmf1Pl9jUEe79EgDb9bD3K5OTUBI= github.com/smartcontractkit/chainlink-testing-framework/wasp v1.50.2 h1:7bCdbTUWzyczQg+kwHCxlx6y07zE8HNB8+ntTne6qd8= github.com/smartcontractkit/chainlink-testing-framework/wasp v1.50.2/go.mod h1:MltlNu3jcXm/DyLN98I5TFNtu/o1NNAcaPAFKMXWk70= github.com/smartcontractkit/grpc-proxy v0.0.0-20240830132753-a7e17fec5ab7 h1:12ijqMM9tvYVEm+nR826WsrNi6zCKpwBhuApq127wHs= @@ -1463,12 +1426,10 @@ github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20241009055228- github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20241009055228-33d0c0bf38de/go.mod h1:Sl2MF/Fp3fgJIVzhdGhmZZX2BlnM0oUUyBP4s4xYb6o= github.com/smartcontractkit/tdh2/go/tdh2 v0.0.0-20241009055228-33d0c0bf38de h1:66VQxXx3lvTaAZrMBkIcdH9VEjujUEvmBQdnyOJnkOc= github.com/smartcontractkit/tdh2/go/tdh2 v0.0.0-20241009055228-33d0c0bf38de/go.mod h1:NSc7hgOQbXG3DAwkOdWnZzLTZENXSwDJ7Va1nBp0YU0= -github.com/smartcontractkit/wsrpc v0.8.3 h1:9tDf7Ut61g36RJIyxV9iI73SqoOMasKPfURV9oMLrPg= -github.com/smartcontractkit/wsrpc v0.8.3/go.mod h1:2u/wfnhl5R4RlSXseN4n6HHIWk8w1Am3AT6gWftQbNg= -github.com/smarty/assertions v1.15.0/go.mod h1:yABtdzeQs6l1brC900WlRNwj6ZR55d7B+E8C6HtKdec= +github.com/smartcontractkit/wsrpc v0.8.2 h1:XB/xcn/MMseHW+8JE8+a/rceA86ck7Ur6cEa9LiUC8M= +github.com/smartcontractkit/wsrpc v0.8.2/go.mod h1:2u/wfnhl5R4RlSXseN4n6HHIWk8w1Am3AT6gWftQbNg= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= -github.com/smartystreets/goconvey v1.8.1/go.mod h1:+/u4qLyY6x1jReYOp7GOM2FSt8aP9CzCZL03bI28W60= github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= github.com/soheilhy/cmux v0.1.5 h1:jjzc5WVemNEDTLwv9tlmemhC73tI08BNOIGwBOo10Js= github.com/soheilhy/cmux v0.1.5/go.mod h1:T7TcVDs9LWfQgPlPsdngu6I6QIoyIFZDDC6sNE1GqG0= @@ -1480,7 +1441,6 @@ github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasO github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI= github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= -github.com/spf13/afero v1.6.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I= github.com/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8= github.com/spf13/afero v1.11.0/go.mod h1:GH9Y3pIexgf1MTIWtNGyogA5MwRIDXGUr+hbWNoBjkY= github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= @@ -1489,18 +1449,15 @@ github.com/spf13/cast v1.6.0 h1:GEiTHELF+vaR5dhz3VqZfFSzZjYbgeKDpBxQVS4GYJ0= github.com/spf13/cast v1.6.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo= github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU= github.com/spf13/cobra v1.1.1/go.mod h1:WnodtKOvamDL/PwE2M4iKs8aMDBZ5Q5klgD3qfVJQMI= -github.com/spf13/cobra v1.2.1/go.mod h1:ExllRjgxM/piMAM+3tAZvg8fsklGAf3tPfi+i8t68Nk= github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM= github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y= github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= -github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= github.com/spf13/viper v1.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg= github.com/spf13/viper v1.7.1/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg= -github.com/spf13/viper v1.8.1/go.mod h1:o0Pch8wJ9BVSWGQMbra6iw0oQ5oktSIBaujf1rJH9Ns= github.com/spf13/viper v1.19.0 h1:RWq5SEjt8o25SROyN3z2OrDB9l7RPd3lwTWU8EcEdcI= github.com/spf13/viper v1.19.0/go.mod h1:GQUN9bilAbhU/jgc1bKs99f/suXKeUMct8Adx5+Ntkg= github.com/status-im/keycard-go v0.2.0 h1:QDLFswOQu1r5jsycloeQh3bVU8n/NatHHaZobtDnDzA= @@ -1611,8 +1568,6 @@ github.com/xlab/treeprint v1.2.0/go.mod h1:gj5Gd3gPdKtR1ikdDK6fnFLdmIS0X30kTTuNd github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 h1:gEOO8jv9F4OT7lGCjxCBTO/36wtF6j2nSip77qHd4x4= github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1/go.mod h1:Ohn+xnUBiLI6FVj/9LpzZWtj1/D6lUovWYBkxHVV3aM= -github.com/xyproto/randomstring v1.0.5 h1:YtlWPoRdgMu3NZtP45drfy1GKoojuR7hmRcnhZqKjWU= -github.com/xyproto/randomstring v1.0.5/go.mod h1:rgmS5DeNXLivK7YprL0pY+lTuhNQW3iGxZ18UQApw/E= github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d/go.mod h1:rHwXgn7JulP+udvsHwJoVG1YGAP6VLg4y9I5dyZdqmA= github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= @@ -1624,8 +1579,6 @@ github.com/yuin/gopher-lua v1.1.0 h1:BojcDhfyDWgU2f2TOzYK/g5p2gxMrku8oupLDqlnSqE github.com/yuin/gopher-lua v1.1.0/go.mod h1:GBR0iDaNXjAgGg9zfCvksxSRnQx76gclCIb7kdAd1Pw= github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo0= github.com/yusufpapurcu/wmi v1.2.4/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= -github.com/zeebo/xxh3 v1.0.2 h1:xZmwmqxHZA8AI603jOQ0tMqmBr9lPeFwGg6d+xy9DC0= -github.com/zeebo/xxh3 v1.0.2/go.mod h1:5NWz9Sef7zIDm2JHfFlcQvNekmcEl9ekUZQQKCYaDcA= github.com/zenazn/goji v0.9.0/go.mod h1:7S9M489iMyHBNxwZnk9/EHS098H4/F6TATF2mIxtB1Q= github.com/zondax/hid v0.9.2 h1:WCJFnEDMiqGF64nlZz28E9qLVZ0KSJ7xpc5DLEyma2U= github.com/zondax/hid v0.9.2/go.mod h1:l5wttcP0jwtdLjqjMMWFVEE7d1zO0jvSPA9OPZxWpEM= @@ -1643,13 +1596,10 @@ go.dedis.ch/protobuf v1.0.11/go.mod h1:97QR256dnkimeNdfmURz0wAMNVbd1VmLXhG1CrTYr go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.etcd.io/bbolt v1.3.9 h1:8x7aARPEXiXbHmtUwAIv7eV2fQFHrLLavdiJ3uzJXoI= go.etcd.io/bbolt v1.3.9/go.mod h1:zaO32+Ti0PK1ivdPtgMESzuzL2VPoIG1PCQNvOdo/dE= -go.etcd.io/etcd/api/v3 v3.5.0/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs= go.etcd.io/etcd/api/v3 v3.5.14 h1:vHObSCxyB9zlF60w7qzAdTcGaglbJOpSj1Xj9+WGxq0= go.etcd.io/etcd/api/v3 v3.5.14/go.mod h1:BmtWcRlQvwa1h3G2jvKYwIQy4PkHlDej5t7uLMUdJUU= -go.etcd.io/etcd/client/pkg/v3 v3.5.0/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g= go.etcd.io/etcd/client/pkg/v3 v3.5.14 h1:SaNH6Y+rVEdxfpA2Jr5wkEvN6Zykme5+YnbCkxvuWxQ= go.etcd.io/etcd/client/pkg/v3 v3.5.14/go.mod h1:8uMgAokyG1czCtIdsq+AGyYQMvpIKnSvPjFMunkgeZI= -go.etcd.io/etcd/client/v2 v2.305.0/go.mod h1:h9puh54ZTgAKtEbut2oe9P4L/oqKCVB6xsXlzd7alYQ= go.etcd.io/etcd/client/v3 v3.5.14 h1:CWfRs4FDaDoSz81giL7zPpZH2Z35tbOrAJkkjMqOupg= go.etcd.io/etcd/client/v3 v3.5.14/go.mod h1:k3XfdV/VIHy/97rqWjoUzrj9tk7GgJGH9J8L4dNXmAk= go.mongodb.org/mongo-driver v1.11.0/go.mod h1:s7p5vEtfbeR1gYi6pnj3c3/urpbLv2T5Sfd6Rp2HBB8= @@ -1662,7 +1612,6 @@ go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= -go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= go.opentelemetry.io/collector/pdata v1.12.0 h1:Xx5VK1p4VO0md8MWm2icwC1MnJ7f8EimKItMWw46BmA= @@ -1740,7 +1689,6 @@ go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= go.uber.org/zap v1.14.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= go.uber.org/zap v1.16.0/go.mod h1:MA8QOfq0BHJwdXa996Y4dYkAqRKB8/1K1QMMZVaNZjQ= -go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo= go.uber.org/zap v1.21.0/go.mod h1:wjWOCqI0f2ZZrJF/UufIOkiC8ii6tm1iqIsLo76RfJw= go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= @@ -1773,8 +1721,8 @@ golang.org/x/crypto v0.0.0-20220214200702-86341886e292/go.mod h1:IxCIyHEi3zRg3s0 golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.3.0/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4= golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc= -golang.org/x/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U= -golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk= +golang.org/x/crypto v0.28.0 h1:GBDwsMXVQi34v5CCYUm2jkJvu4cbtru2U4TN2PSyQnw= +golang.org/x/crypto v0.28.0/go.mod h1:rmgy+3RHxRZMyY0jjAJShp2zgEdOqj2AO7U0pYmeQ7U= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -1800,7 +1748,6 @@ golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRu golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= @@ -1809,12 +1756,9 @@ golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzB golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/mod v0.9.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.21.0 h1:vvrHzRwRfVKSiLrG+d4FMl/Qi4ukBCE6kZlTUkDYRT0= golang.org/x/mod v0.21.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -1854,11 +1798,8 @@ golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81R golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc= golang.org/x/net v0.0.0-20210331212208-0fccb6fa2b5c/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= @@ -1872,7 +1813,6 @@ golang.org/x/net v0.0.0-20220607020251-c690dde0001d/go.mod h1:XRhObCWvk6IyKnWLug golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= -golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/net v0.30.0 h1:AcW1SDZMkb8IpzCdQUaIq2sP4sZ4zw+55h6ynffypl4= golang.org/x/net v0.30.0/go.mod h1:2wGyMJ5iFasEhkwi13ChkO/t1ECNC4X4eBKkVFyYFlU= @@ -1881,13 +1821,6 @@ golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4Iltr golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210220000619-9bb904979d93/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210313182246-cd4f82c27b84/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210402161424-2e8d93401602/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.23.0 h1:PbgcYx2W7i4LvjJWEbf0ngHV6qJYr86PkAV3bXdLEbs= golang.org/x/oauth2 v0.23.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= @@ -1904,8 +1837,8 @@ golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ= -golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ= +golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -1956,23 +1889,17 @@ golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210303074136-134d130e1a04/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210305230114-8fe3ee5dd75b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210331175145-43e1dd70ce54/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -1999,8 +1926,8 @@ golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA= -golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo= +golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20201210144234-2321bbc49cbf/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= @@ -2008,11 +1935,10 @@ golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuX golang.org/x/term v0.0.0-20220526004731-065cf7ba2467/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= -golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU= -golang.org/x/term v0.27.0 h1:WP60Sv1nlK1T6SupCHbXzSaN0b9wUmsPoRS9b61A23Q= -golang.org/x/term v0.27.0/go.mod h1:iMsnZpn0cago0GOrHO2+Y7u7JPn5AylBrcoWkElMTSM= +golang.org/x/term v0.25.0 h1:WtHI/ltw4NvSUig5KARz9h521QvRC8RmF/cuYqifU24= +golang.org/x/term v0.25.0/go.mod h1:RPyXicDX+6vLxogjjRxjgD2TKtmAO6NZBsBRfrOLu7M= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -2024,11 +1950,10 @@ golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= -golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo= -golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ= +golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM= +golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -2085,19 +2010,12 @@ golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roY golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE= -golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= -golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= -golang.org/x/tools v0.7.0/go.mod h1:4pg6aUX35JBAogB10C9AtvVL+qowtN4pT3CGSQex14s= golang.org/x/tools v0.26.0 h1:v/60pFQmzmT9ExmjDv2gGIfi3OqfKoEP6I5+umXlbnQ= golang.org/x/tools v0.26.0/go.mod h1:TPVVj70c7JJ3WCazhD8OdXcZg/og+b9+tH/KxylGwH0= golang.org/x/xerrors v0.0.0-20190410155217-1f06c39b4373/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -2130,14 +2048,8 @@ google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0M google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM= google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc= -google.golang.org/api v0.35.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg= -google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34qYtE= -google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8= -google.golang.org/api v0.41.0/go.mod h1:RkxM5lITDfTzmyKFPt+wGrCJbVfniCr2ool8kTBzRTU= -google.golang.org/api v0.43.0/go.mod h1:nQsDGjRXMo4lvh5hP0TKqF244gqhGcr/YSIykhUk/94= -google.golang.org/api v0.44.0/go.mod h1:EBOGZqzyhtvMDoxwS97ctnh0zUmYY6CxqXsc1AvkYD8= -google.golang.org/api v0.205.0 h1:LFaxkAIpDb/GsrWV20dMMo5MR0h8UARTbn24LmD+0Pg= -google.golang.org/api v0.205.0/go.mod h1:NrK1EMqO8Xk6l6QwRAmrXXg2v6dzukhlOyvkYtnvUuc= +google.golang.org/api v0.202.0 h1:y1iuVHMqokQbimW79ZqPZWo4CiyFu6HcCYHwSNyzlfo= +google.golang.org/api v0.202.0/go.mod h1:3Jjeq7M/SFblTNCp7ES2xhq+WvGL0KeXI0joHQBfwTQ= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= @@ -2181,24 +2093,13 @@ google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7Fc google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210222152913-aa3ee6e6a81c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210303154014-9728d6b83eeb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210310155132-4ce2db91004e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210319143718-93e7006c17a6/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210401141331-865547bb08e2/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A= -google.golang.org/genproto v0.0.0-20210402141018-6c239bbf2bb1/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A= -google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= google.golang.org/genproto v0.0.0-20241021214115-324edc3d5d38 h1:Q3nlH8iSQSRUwOskjbcSMcF2jiYMNiQYZ0c2KEJLKKU= google.golang.org/genproto v0.0.0-20241021214115-324edc3d5d38/go.mod h1:xBI+tzfqGGN2JBeSebfKXFSdBpWVQ7sLW40PTupVRm4= -google.golang.org/genproto/googleapis/api v0.0.0-20241104194629-dd2ea8efbc28 h1:M0KvPgPmDZHPlbRbaNU1APr28TvwvvdUPlSv7PUvy8g= -google.golang.org/genproto/googleapis/api v0.0.0-20241104194629-dd2ea8efbc28/go.mod h1:dguCy7UOdZhTvLzDyt15+rOrawrpM4q7DD9dQ1P11P4= -google.golang.org/genproto/googleapis/rpc v0.0.0-20241104194629-dd2ea8efbc28 h1:XVhgTWWV3kGQlwJHR3upFWZeTsei6Oks1apkZSeonIE= -google.golang.org/genproto/googleapis/rpc v0.0.0-20241104194629-dd2ea8efbc28/go.mod h1:GX3210XPVPUjJbTUbvwI8f2IpZDMZuPJWDzDuebbviI= +google.golang.org/genproto/googleapis/api v0.0.0-20241021214115-324edc3d5d38 h1:2oV8dfuIkM1Ti7DwXc0BJfnwr9csz4TDXI9EmiI+Rbw= +google.golang.org/genproto/googleapis/api v0.0.0-20241021214115-324edc3d5d38/go.mod h1:vuAjtvlwkDKF6L1GQ0SokiRLCGFfeBUXWr/aFFkHACc= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241021214115-324edc3d5d38 h1:zciRKQ4kBpFgpfC5QQCVtnnNAcLIqweL7plyZRQHVpI= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241021214115-324edc3d5d38/go.mod h1:GX3210XPVPUjJbTUbvwI8f2IpZDMZuPJWDzDuebbviI= google.golang.org/grpc v1.12.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= @@ -2214,14 +2115,9 @@ google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKa google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= -google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= -google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8= -google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= -google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= google.golang.org/grpc v1.36.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= -google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= google.golang.org/grpc v1.67.1 h1:zWnc1Vrcno+lHZCOofnIMvycFcc0QRGIzm9dhnDX68E= google.golang.org/grpc v1.67.1/go.mod h1:1gLDyUQU7CTLJI90u3nXZ9ekeghjeM7pTDZlqFNg2AA= google.golang.org/grpc/stats/opentelemetry v0.0.0-20241022174616-4bb0170ac65f h1:TsfHqsKI7qhOoYugDRyFDSKAuzegDVmkSCpjUyLkb+8= @@ -2257,7 +2153,6 @@ gopkg.in/inconshreveable/log15.v2 v2.0.0-20180818164646-67afb5ed74ec/go.mod h1:a gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= -gopkg.in/ini.v1 v1.62.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/natefinch/lumberjack.v2 v2.2.1 h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST95x9zc= @@ -2290,24 +2185,24 @@ honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= honnef.co/go/tools v0.1.3/go.mod h1:NgwopIslSNH47DimFoV78dnkksY2EFtX0ajyb3K/las= -k8s.io/api v0.31.2 h1:3wLBbL5Uom/8Zy98GRPXpJ254nEFpl+hwndmk9RwmL0= -k8s.io/api v0.31.2/go.mod h1:bWmGvrGPssSK1ljmLzd3pwCQ9MgoTsRCuK35u6SygUk= +k8s.io/api v0.31.1 h1:Xe1hX/fPW3PXYYv8BlozYqw63ytA92snr96zMW9gWTU= +k8s.io/api v0.31.1/go.mod h1:sbN1g6eY6XVLeqNsZGLnI5FwVseTrZX7Fv3O26rhAaI= k8s.io/apiextensions-apiserver v0.31.0 h1:fZgCVhGwsclj3qCw1buVXCV6khjRzKC5eCFt24kyLSk= k8s.io/apiextensions-apiserver v0.31.0/go.mod h1:b9aMDEYaEe5sdK+1T0KU78ApR/5ZVp4i56VacZYEHxk= -k8s.io/apimachinery v0.31.2 h1:i4vUt2hPK56W6mlT7Ry+AO8eEsyxMD1U44NR22CLTYw= -k8s.io/apimachinery v0.31.2/go.mod h1:rsPdaZJfTfLsNJSQzNHQvYoTmxhoOEofxtOsF3rtsMo= -k8s.io/cli-runtime v0.31.2 h1:7FQt4C4Xnqx8V1GJqymInK0FFsoC+fAZtbLqgXYVOLQ= -k8s.io/cli-runtime v0.31.2/go.mod h1:XROyicf+G7rQ6FQJMbeDV9jqxzkWXTYD6Uxd15noe0Q= -k8s.io/client-go v0.31.2 h1:Y2F4dxU5d3AQj+ybwSMqQnpZH9F30//1ObxOKlTI9yc= -k8s.io/client-go v0.31.2/go.mod h1:NPa74jSVR/+eez2dFsEIHNa+3o09vtNaWwWwb1qSxSs= -k8s.io/component-base v0.31.2 h1:Z1J1LIaC0AV+nzcPRFqfK09af6bZ4D1nAOpWsy9owlA= -k8s.io/component-base v0.31.2/go.mod h1:9PeyyFN/drHjtJZMCTkSpQJS3U9OXORnHQqMLDz0sUQ= +k8s.io/apimachinery v0.31.1 h1:mhcUBbj7KUjaVhyXILglcVjuS4nYXiwC+KKFBgIVy7U= +k8s.io/apimachinery v0.31.1/go.mod h1:rsPdaZJfTfLsNJSQzNHQvYoTmxhoOEofxtOsF3rtsMo= +k8s.io/cli-runtime v0.31.1 h1:/ZmKhmZ6hNqDM+yf9s3Y4KEYakNXUn5sod2LWGGwCuk= +k8s.io/cli-runtime v0.31.1/go.mod h1:pKv1cDIaq7ehWGuXQ+A//1OIF+7DI+xudXtExMCbe9U= +k8s.io/client-go v0.31.1 h1:f0ugtWSbWpxHR7sjVpQwuvw9a3ZKLXX0u0itkFXufb0= +k8s.io/client-go v0.31.1/go.mod h1:sKI8871MJN2OyeqRlmA4W4KM9KBdBUpDLu/43eGemCg= +k8s.io/component-base v0.31.1 h1:UpOepcrX3rQ3ab5NB6g5iP0tvsgJWzxTyAo20sgYSy8= +k8s.io/component-base v0.31.1/go.mod h1:WGeaw7t/kTsqpVTaCoVEtillbqAhF2/JgvO0LDOMa0w= k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk= k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE= k8s.io/kube-openapi v0.0.0-20240709000822-3c01b740850f h1:2sXuKesAYbRHxL3aE2PN6zX/gcJr22cjrsej+W784Tc= k8s.io/kube-openapi v0.0.0-20240709000822-3c01b740850f/go.mod h1:UxDHUPsUwTOOxSU+oXURfFBcAS6JwiRXTYqYwfuGowc= -k8s.io/kubectl v0.31.2 h1:gTxbvRkMBwvTSAlobiTVqsH6S8Aa1aGyBcu5xYLsn8M= -k8s.io/kubectl v0.31.2/go.mod h1:EyASYVU6PY+032RrTh5ahtSOMgoDRIux9V1JLKtG5xM= +k8s.io/kubectl v0.31.1 h1:ih4JQJHxsEggFqDJEHSOdJ69ZxZftgeZvYo7M/cpp24= +k8s.io/kubectl v0.31.1/go.mod h1:aNuQoR43W6MLAtXQ/Bu4GDmoHlbhHKuyD49lmTC8eJM= k8s.io/utils v0.0.0-20240711033017-18e509b52bc8 h1:pUdcCO1Lk/tbT5ztQWOBi5HBgbBP1J8+AsQnQCKsi8A= k8s.io/utils v0.0.0-20240711033017-18e509b52bc8/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= nhooyr.io/websocket v1.8.10 h1:mv4p+MnGrLDcPlBoWsvPP7XCzTYMXP9F9eIGoKbgx7Q= diff --git a/integration-tests/load/vrfv2/gun.go b/integration-tests/load/vrfv2/gun.go index 9a680e5bd99..20a20b40834 100644 --- a/integration-tests/load/vrfv2/gun.go +++ b/integration-tests/load/vrfv2/gun.go @@ -4,7 +4,6 @@ import ( "math/rand" "github.com/rs/zerolog" - "golang.org/x/exp/constraints" "github.com/smartcontractkit/chainlink-testing-framework/wasp" @@ -124,9 +123,9 @@ func (m *SingleHashGun) Call(_ *wasp.Generator) *wasp.Response { func deviateValue(requestCountPerTX uint16, deviation uint16) uint16 { if randBool() && requestCountPerTX > deviation { - requestCountPerTX -= randInRange(0, deviation) + requestCountPerTX -= uint16(randInRange(0, int(deviation))) } else { - requestCountPerTX += randInRange(0, deviation) + requestCountPerTX += uint16(randInRange(0, int(deviation))) } return requestCountPerTX } @@ -134,7 +133,6 @@ func deviateValue(requestCountPerTX uint16, deviation uint16) uint16 { func randBool() bool { return rand.Intn(2) == 1 } - -func randInRange[I constraints.Integer](lower, upper I) I { - return I(rand.Intn(int(upper-lower)+1)) + lower +func randInRange(min int, max int) int { + return rand.Intn(max-min+1) + min } diff --git a/integration-tests/load/vrfv2plus/gun.go b/integration-tests/load/vrfv2plus/gun.go index f6a194ab6ce..4aac3927518 100644 --- a/integration-tests/load/vrfv2plus/gun.go +++ b/integration-tests/load/vrfv2plus/gun.go @@ -5,7 +5,6 @@ import ( "math/rand" "github.com/rs/zerolog" - "golang.org/x/exp/constraints" "github.com/smartcontractkit/chainlink-testing-framework/wasp" @@ -132,13 +131,13 @@ func (m *SingleHashGun) Call(_ *wasp.Generator) *wasp.Response { func deviateValue(requestCountPerTX uint16, deviation uint16) uint16 { if actions.RandBool() && requestCountPerTX > deviation { - requestCountPerTX -= randInRange(0, deviation) + requestCountPerTX -= uint16(randInRange(0, int(deviation))) } else { - requestCountPerTX += randInRange(0, deviation) + requestCountPerTX += uint16(randInRange(0, int(deviation))) } return requestCountPerTX } -func randInRange[I constraints.Integer](lower, upper I) I { - return I(rand.Intn(int(upper-lower)+1)) + lower +func randInRange(min int, max int) int { + return rand.Intn(max-min+1) + min } diff --git a/integration-tests/smoke/ccip/ccip_batching_test.go b/integration-tests/smoke/ccip/ccip_batching_test.go deleted file mode 100644 index 3752faa4e6e..00000000000 --- a/integration-tests/smoke/ccip/ccip_batching_test.go +++ /dev/null @@ -1,534 +0,0 @@ -package smoke - -import ( - "context" - "fmt" - "math/big" - "sync" - "testing" - - "github.com/ethereum/go-ethereum/accounts/abi/bind" - "github.com/ethereum/go-ethereum/common" - "github.com/stretchr/testify/require" - "golang.org/x/exp/maps" - - "github.com/smartcontractkit/chainlink-ccip/pkg/types/ccipocr3" - "github.com/smartcontractkit/chainlink-common/pkg/merklemulti" - - testsetups "github.com/smartcontractkit/chainlink/integration-tests/testsetups/ccip" - - "github.com/smartcontractkit/chainlink/deployment" - "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/offramp" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/onramp" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/router" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/shared/generated/multicall3" -) - -const ( - numMessages = 40 -) - -type batchTestSetup struct { - e changeset.DeployedEnv - state changeset.CCIPOnChainState - sourceChain1 uint64 - sourceChain2 uint64 - destChain uint64 -} - -func newBatchTestSetup(t *testing.T) batchTestSetup { - // Setup 3 chains, with 2 lanes going to the dest. - e, _ := testsetups.NewIntegrationEnvironment( - t, - changeset.WithMultiCall3(), - changeset.WithChains(3), - changeset.WithUsersPerChain(2), - ) - - state, err := changeset.LoadOnchainState(e.Env) - require.NoError(t, err) - - allChainSelectors := maps.Keys(e.Env.Chains) - require.Len(t, allChainSelectors, 3, "this test expects 3 chains") - sourceChain1 := allChainSelectors[0] - sourceChain2 := allChainSelectors[1] - destChain := allChainSelectors[2] - t.Log("All chain selectors:", allChainSelectors, - ", home chain selector:", e.HomeChainSel, - ", feed chain selector:", e.FeedChainSel, - ", source chain selector 1:", sourceChain1, - ", source chain selector 2:", sourceChain2, - ", dest chain selector:", destChain, - ) - - // connect sourceChain1 and sourceChain2 to destChain - changeset.AddLaneWithDefaultPricesAndFeeQuoterConfig(t, &e, state, sourceChain1, destChain, false) - changeset.AddLaneWithDefaultPricesAndFeeQuoterConfig(t, &e, state, sourceChain2, destChain, false) - - return batchTestSetup{e, state, sourceChain1, sourceChain2, destChain} -} - -func Test_CCIPBatching_MaxBatchSizeEVM(t *testing.T) { - t.Parallel() - - ctx := changeset.Context(t) - setup := newBatchTestSetup(t) - sourceChain1, sourceChain2, destChain, e, state := setup.sourceChain1, setup.sourceChain2, setup.destChain, setup.e, setup.state - - var ( - startSeqNum = map[uint64]ccipocr3.SeqNum{ - sourceChain1: 1, - sourceChain2: 1, - } - sourceChain = sourceChain1 - transactors = []*bind.TransactOpts{ - e.Env.Chains[sourceChain].DeployerKey, - e.Env.Chains[sourceChain].Users[0], - } - errs = make(chan error, len(transactors)) - ) - - for _, transactor := range transactors { - go func() { - err := sendMessages( - ctx, - t, - e.Env.Chains[sourceChain], - transactor, - state.Chains[sourceChain].OnRamp, - state.Chains[sourceChain].Router, - state.Chains[sourceChain].Multicall3, - destChain, - merklemulti.MaxNumberTreeLeaves/2, - common.LeftPadBytes(state.Chains[destChain].Receiver.Address().Bytes(), 32), - ) - t.Log("sendMessages error:", err, ", writing to channel") - errs <- err - t.Log("sent error to channel") - }() - } - - var i = 0 - for i < len(transactors) { - select { - case err := <-errs: - require.NoError(t, err) - i++ - case <-ctx.Done(): - require.FailNow(t, "didn't get all errors before test context was done") - } - } - - _, err := changeset.ConfirmCommitWithExpectedSeqNumRange( - t, - e.Env.Chains[sourceChain], - e.Env.Chains[destChain], - state.Chains[destChain].OffRamp, - nil, // startBlock - ccipocr3.NewSeqNumRange( - startSeqNum[sourceChain], - startSeqNum[sourceChain]+ccipocr3.SeqNum(merklemulti.MaxNumberTreeLeaves)-1, - ), - true, - ) - require.NoErrorf(t, err, "failed to confirm commit from chain %d", sourceChain) -} - -func Test_CCIPBatching_MultiSource(t *testing.T) { - // t.Skip("Exec not working, boosting not working correctly") - - t.Parallel() - - // Setup 3 chains, with 2 lanes going to the dest. - ctx := changeset.Context(t) - setup := newBatchTestSetup(t) - sourceChain1, sourceChain2, destChain, e, state := setup.sourceChain1, setup.sourceChain2, setup.destChain, setup.e, setup.state - - var ( - wg sync.WaitGroup - sourceChains = []uint64{sourceChain1, sourceChain2} - errs = make(chan error, len(sourceChains)) - startSeqNum = map[uint64]ccipocr3.SeqNum{ - sourceChain1: 1, - sourceChain2: 1, - } - ) - - for _, srcChain := range sourceChains { - wg.Add(1) - go sendMessagesAsync( - ctx, - t, - e, - state, - srcChain, - destChain, - numMessages, - &wg, - errs, - ) - } - - wg.Wait() - - var i int - for i < len(sourceChains) { - select { - case err := <-errs: - require.NoError(t, err) - i++ - case <-ctx.Done(): - require.FailNow(t, "didn't get all errors before test context was done") - } - } - - // confirm the commit reports - outputErrs := make(chan outputErr[*offramp.OffRampCommitReportAccepted], len(sourceChains)) - for _, srcChain := range sourceChains { - wg.Add(1) - go assertCommitReportsAsync( - t, - e, - state, - srcChain, - destChain, - startSeqNum[srcChain], - startSeqNum[srcChain]+ccipocr3.SeqNum(numMessages)-1, - &wg, - outputErrs, - ) - } - - t.Log("waiting for commit report") - wg.Wait() - - i = 0 - var reports []*offramp.OffRampCommitReportAccepted - for i < len(sourceChains) { - select { - case outputErr := <-outputErrs: - require.NoError(t, outputErr.err) - reports = append(reports, outputErr.output) - i++ - case <-ctx.Done(): - require.FailNow(t, "didn't get all commit reports before test context was done") - } - } - - // the reports should be the same for both, since both roots should be batched within - // that one report. - require.Lenf(t, reports, len(sourceChains), "expected %d commit reports", len(sourceChains)) - require.NotNil(t, reports[0], "commit report should not be nil") - require.NotNil(t, reports[1], "commit report should not be nil") - // TODO: this assertion is failing, despite messages being sent at the same time. - // require.Equal(t, reports[0], reports[1], "commit reports should be the same") - - // confirm execution - execErrs := make(chan outputErr[map[uint64]int], len(sourceChains)) - for _, srcChain := range sourceChains { - wg.Add(1) - go assertExecAsync( - t, - e, - state, - srcChain, - destChain, - genSeqNrRange(startSeqNum[srcChain], startSeqNum[srcChain]+ccipocr3.SeqNum(numMessages)-1), - &wg, - execErrs, - ) - } - - t.Log("waiting for exec reports") - wg.Wait() - - i = 0 - var execStates []map[uint64]int - for i < len(sourceChains) { - select { - case outputErr := <-execErrs: - require.NoError(t, outputErr.err) - execStates = append(execStates, outputErr.output) - i++ - case <-ctx.Done(): - require.FailNow(t, "didn't get all exec reports before test context was done") - } - } - - // assert that all states are successful - for _, states := range execStates { - for _, state := range states { - require.Equal(t, changeset.EXECUTION_STATE_SUCCESS, state) - } - } -} - -func Test_CCIPBatching_SingleSource(t *testing.T) { - t.Parallel() - - // Setup 3 chains, with 2 lanes going to the dest. - ctx := changeset.Context(t) - setup := newBatchTestSetup(t) - sourceChain1, sourceChain2, destChain, e, state := setup.sourceChain1, setup.sourceChain2, setup.destChain, setup.e, setup.state - - var ( - startSeqNum = map[uint64]ccipocr3.SeqNum{ - sourceChain1: 1, - sourceChain2: 1, - } - ) - - var ( - sourceChain = sourceChain1 - ) - err := sendMessages( - ctx, - t, - e.Env.Chains[sourceChain], - e.Env.Chains[sourceChain].DeployerKey, - state.Chains[sourceChain].OnRamp, - state.Chains[sourceChain].Router, - state.Chains[sourceChain].Multicall3, - destChain, - numMessages, - common.LeftPadBytes(state.Chains[destChain].Receiver.Address().Bytes(), 32), - ) - require.NoError(t, err) - - _, err = changeset.ConfirmCommitWithExpectedSeqNumRange( - t, - e.Env.Chains[sourceChain], - e.Env.Chains[destChain], - state.Chains[destChain].OffRamp, - nil, - ccipocr3.NewSeqNumRange(startSeqNum[sourceChain], startSeqNum[sourceChain]+numMessages-1), - true, - ) - require.NoErrorf(t, err, "failed to confirm commit from chain %d", sourceChain) - - states, err := changeset.ConfirmExecWithSeqNrs( - t, - e.Env.Chains[sourceChain], - e.Env.Chains[destChain], - state.Chains[destChain].OffRamp, - nil, - genSeqNrRange(startSeqNum[sourceChain], startSeqNum[sourceChain]+numMessages-1), - ) - require.NoError(t, err) - // assert that all states are successful - for _, state := range states { - require.Equal(t, changeset.EXECUTION_STATE_SUCCESS, state) - } -} - -type outputErr[T any] struct { - output T - err error -} - -func assertExecAsync( - t *testing.T, - e changeset.DeployedEnv, - state changeset.CCIPOnChainState, - sourceChainSelector, - destChainSelector uint64, - seqNums []uint64, - wg *sync.WaitGroup, - errs chan<- outputErr[map[uint64]int], -) { - defer wg.Done() - states, err := changeset.ConfirmExecWithSeqNrs( - t, - e.Env.Chains[sourceChainSelector], - e.Env.Chains[destChainSelector], - state.Chains[destChainSelector].OffRamp, - nil, - seqNums, - ) - - errs <- outputErr[map[uint64]int]{states, err} -} - -func assertCommitReportsAsync( - t *testing.T, - e changeset.DeployedEnv, - state changeset.CCIPOnChainState, - sourceChainSelector, - destChainSelector uint64, - startSeqNum, - endSeqNum ccipocr3.SeqNum, - wg *sync.WaitGroup, - errs chan<- outputErr[*offramp.OffRampCommitReportAccepted], -) { - defer wg.Done() - commitReport, err := changeset.ConfirmCommitWithExpectedSeqNumRange( - t, - e.Env.Chains[sourceChainSelector], - e.Env.Chains[destChainSelector], - state.Chains[destChainSelector].OffRamp, - nil, - ccipocr3.NewSeqNumRange(startSeqNum, endSeqNum), - true, - ) - - errs <- outputErr[*offramp.OffRampCommitReportAccepted]{commitReport, err} -} - -func sendMessagesAsync( - ctx context.Context, - t *testing.T, - e changeset.DeployedEnv, - state changeset.CCIPOnChainState, - sourceChainSelector, - destChainSelector uint64, - numMessages int, - wg *sync.WaitGroup, - out chan<- error, -) { - defer wg.Done() - var err error - - const ( - numRetries = 3 - ) - - // we retry a bunch of times just in case there is a race b/w the prices being - // posted and the messages being sent. - for i := 0; i < numRetries; i++ { - err = sendMessages( - ctx, - t, - e.Env.Chains[sourceChainSelector], - e.Env.Chains[sourceChainSelector].DeployerKey, - state.Chains[sourceChainSelector].OnRamp, - state.Chains[sourceChainSelector].Router, - state.Chains[sourceChainSelector].Multicall3, - destChainSelector, - numMessages, - common.LeftPadBytes(state.Chains[destChainSelector].Receiver.Address().Bytes(), 32), - ) - if err == nil { - break - } - - t.Log("sendMessagesAsync error is non-nil:", err, ", retrying") - } - - t.Log("sendMessagesAsync error:", err, ", writing to channel") - out <- err -} - -func sendMessages( - ctx context.Context, - t *testing.T, - sourceChain deployment.Chain, - sourceTransactOpts *bind.TransactOpts, - sourceOnRamp *onramp.OnRamp, - sourceRouter *router.Router, - sourceMulticall3 *multicall3.Multicall3, - destChainSelector uint64, - numMessages int, - receiver []byte, -) error { - calls, totalValue, err := genMessages( - ctx, - sourceRouter, - destChainSelector, - numMessages, - receiver, - ) - if err != nil { - return fmt.Errorf("generate messages: %w", err) - } - - currBalance, err := sourceChain.Client.BalanceAt(ctx, sourceTransactOpts.From, nil) - if err != nil { - return fmt.Errorf("get balance: %w", err) - } - - // Send the tx with the messages through the multicall - t.Logf("Sending %d messages with total value %s, current balance: %s", numMessages, totalValue.String(), currBalance.String()) - tx, err := sourceMulticall3.Aggregate3Value( - &bind.TransactOpts{ - From: sourceTransactOpts.From, - Signer: sourceTransactOpts.Signer, - Value: totalValue, - }, - calls, - ) - _, err = deployment.ConfirmIfNoError(sourceChain, tx, err) - if err != nil { - return fmt.Errorf("send messages via multicall3: %w", err) - } - - // check that the message was emitted - iter, err := sourceOnRamp.FilterCCIPMessageSent( - nil, []uint64{destChainSelector}, nil, - ) - if err != nil { - return fmt.Errorf("get message sent event: %w", err) - } - defer func() { - require.NoError(t, iter.Close()) - }() - - // there should be numMessages messages emitted - for i := 0; i < numMessages; i++ { - if !iter.Next() { - return fmt.Errorf("expected %d messages, got %d", numMessages, i) - } - t.Logf("Message id of msg %d: %x", i, iter.Event.Message.Header.MessageId[:]) - } - - return nil -} - -func genMessages( - ctx context.Context, - sourceRouter *router.Router, - destChainSelector uint64, - count int, - receiver []byte, -) (calls []multicall3.Multicall3Call3Value, totalValue *big.Int, err error) { - totalValue = big.NewInt(0) - for i := 0; i < count; i++ { - msg := router.ClientEVM2AnyMessage{ - Receiver: receiver, - Data: []byte(fmt.Sprintf("hello world %d", i)), - TokenAmounts: nil, - FeeToken: common.HexToAddress("0x0"), - ExtraArgs: changeset.MakeEVMExtraArgsV2(50_000, false), - } - - fee, err := sourceRouter.GetFee(&bind.CallOpts{Context: ctx}, destChainSelector, msg) - if err != nil { - return nil, nil, fmt.Errorf("router get fee: %w", err) - } - - totalValue.Add(totalValue, fee) - - calldata, err := changeset.CCIPSendCalldata(destChainSelector, msg) - if err != nil { - return nil, nil, fmt.Errorf("generate calldata: %w", err) - } - - calls = append(calls, multicall3.Multicall3Call3Value{ - Target: sourceRouter.Address(), - AllowFailure: false, - CallData: calldata, - Value: fee, - }) - } - - return calls, totalValue, nil -} - -// creates an array of uint64 from start to end inclusive -func genSeqNrRange(start, end ccipocr3.SeqNum) []uint64 { - var seqNrs []uint64 - for i := start; i <= end; i++ { - seqNrs = append(seqNrs, uint64(i)) - } - return seqNrs -} diff --git a/integration-tests/smoke/ccip/ccip_fee_boosting_test.go b/integration-tests/smoke/ccip/ccip_fee_boosting_test.go deleted file mode 100644 index 3b0ebf22455..00000000000 --- a/integration-tests/smoke/ccip/ccip_fee_boosting_test.go +++ /dev/null @@ -1,281 +0,0 @@ -package smoke - -import ( - "context" - "math/big" - "testing" - "time" - - "github.com/smartcontractkit/chainlink-common/pkg/config" - - commoncs "github.com/smartcontractkit/chainlink/deployment/common/changeset" - testsetups "github.com/smartcontractkit/chainlink/integration-tests/testsetups/ccip" - - "github.com/ethereum/go-ethereum/accounts/abi/bind" - "github.com/ethereum/go-ethereum/common" - "github.com/test-go/testify/require" - "golang.org/x/exp/maps" - - "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/testcontext" - - cciptypes "github.com/smartcontractkit/chainlink-ccip/pkg/types/ccipocr3" - - "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/ccipevm" - - "github.com/smartcontractkit/chainlink/deployment" - "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/onramp" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/router" -) - -var ( - linkPrice = deployment.E18Mult(100) - wethPrice = deployment.E18Mult(4000) -) - -func Test_CCIPFeeBoosting(t *testing.T) { - e, _ := testsetups.NewIntegrationEnvironment( - t, - changeset.WithOCRConfigOverride(func(params changeset.CCIPOCRParams) changeset.CCIPOCRParams { - // Only 1 boost (=OCR round) is enough to cover the fee - params.ExecuteOffChainConfig.RelativeBoostPerWaitHour = 10 - // Disable token price updates - params.CommitOffChainConfig.TokenPriceBatchWriteFrequency = *config.MustNewDuration(1_000_000 * time.Hour) - // Disable gas price updates - params.CommitOffChainConfig.RemoteGasPriceBatchWriteFrequency = *config.MustNewDuration(1_000_000 * time.Hour) - // Disable token price updates - params.CommitOffChainConfig.TokenInfo = nil - return params - }), - ) - - state, err := changeset.LoadOnchainState(e.Env) - require.NoError(t, err) - - allChainSelectors := maps.Keys(e.Env.Chains) - require.Len(t, allChainSelectors, 2) - sourceChain := allChainSelectors[0] - destChain := allChainSelectors[1] - t.Log("All chain selectors:", allChainSelectors, - ", home chain selector:", e.HomeChainSel, - ", feed chain selector:", e.FeedChainSel, - ", source chain selector:", sourceChain, - ", dest chain selector:", destChain, - ) - - // TODO: discrepancy between client and the gas estimator gas price to be fixed - hardcoded for now - // fetchedGasPriceDest, err := e.Env.Chains[destChain].Client.SuggestGasPrice(tests.Context(t)) - fetchedGasPriceDest := big.NewInt(20e9) // 20 Gwei = default gas price - require.NoError(t, err) - originalGasPriceDestUSD := new(big.Int).Div( - new(big.Int).Mul(fetchedGasPriceDest, wethPrice), - big.NewInt(1e18), - ) - t.Log("Gas price on dest chain (USD):", originalGasPriceDestUSD) - - // Adjust destination gas price on source fee quoter to 95% of the current value - adjustedGasPriceDest := - new(big.Int).Div( - new(big.Int).Mul(originalGasPriceDestUSD, big.NewInt(95)), - big.NewInt(100), - ) - t.Log("Adjusted gas price on dest chain:", adjustedGasPriceDest) - - changeset.AddLane(t, &e, sourceChain, destChain, false, - map[uint64]*big.Int{ - destChain: changeset.ToPackedFee(adjustedGasPriceDest, big.NewInt(0)), - }, - map[common.Address]*big.Int{ - state.Chains[sourceChain].LinkToken.Address(): linkPrice, - state.Chains[sourceChain].Weth9.Address(): wethPrice, - }, - changeset.DefaultFeeQuoterDestChainConfig()) - - // Update token prices in destination chain FeeQuoter - e.Env, err = commoncs.ApplyChangesets(t, e.Env, e.TimelockContracts(t), []commoncs.ChangesetApplication{ - { - Changeset: commoncs.WrapChangeSet(changeset.UpdateFeeQuoterPricesCS), - Config: changeset.UpdateFeeQuoterPricesConfig{ - PricesByChain: map[uint64]changeset.FeeQuoterPriceUpdatePerSource{ - destChain: { - TokenPrices: map[common.Address]*big.Int{ - state.Chains[destChain].LinkToken.Address(): linkPrice, - state.Chains[destChain].Weth9.Address(): wethPrice, - }, - }, - }, - }, - }, - }) - require.NoError(t, err) - - startBlocks := make(map[uint64]*uint64) - expectedSeqNum := make(map[changeset.SourceDestPair]uint64) - expectedSeqNumExec := make(map[changeset.SourceDestPair][]uint64) - - latesthdr, err := e.Env.Chains[sourceChain].Client.HeaderByNumber(testcontext.Get(t), nil) - require.NoError(t, err) - block := latesthdr.Number.Uint64() - msgSentEvent := changeset.TestSendRequest(t, e.Env, state, sourceChain, destChain, false, router.ClientEVM2AnyMessage{ - Receiver: common.LeftPadBytes(state.Chains[destChain].Receiver.Address().Bytes(), 32), - Data: []byte("message that needs fee boosting"), - TokenAmounts: nil, - FeeToken: common.HexToAddress("0x0"), - ExtraArgs: nil, - }) - startBlocks[sourceChain] = &block - expectedSeqNum[changeset.SourceDestPair{ - SourceChainSelector: sourceChain, - DestChainSelector: destChain, - }] = msgSentEvent.SequenceNumber - expectedSeqNumExec[changeset.SourceDestPair{ - SourceChainSelector: sourceChain, - DestChainSelector: destChain, - }] = []uint64{msgSentEvent.SequenceNumber} - - e.Env, err = commoncs.ApplyChangesets(t, e.Env, e.TimelockContracts(t), []commoncs.ChangesetApplication{ - { - Changeset: commoncs.WrapChangeSet(changeset.UpdateFeeQuoterPricesCS), - Config: changeset.UpdateFeeQuoterPricesConfig{ - PricesByChain: map[uint64]changeset.FeeQuoterPriceUpdatePerSource{ - sourceChain: { - GasPrices: map[uint64]*big.Int{ - destChain: originalGasPriceDestUSD, - }, - }, - }, - }, - }, - }) - require.NoError(t, err) - - // Confirm gas prices are updated - srcFeeQuoter := state.Chains[sourceChain].FeeQuoter - err = changeset.ConfirmGasPriceUpdated(t, e.Env.Chains[destChain], srcFeeQuoter, 0, originalGasPriceDestUSD) - require.NoError(t, err) - - // Confirm that fee boosting will be triggered - require.True(t, willTriggerFeeBoosting(t, msgSentEvent, state, sourceChain, destChain)) - - // hack - time.Sleep(30 * time.Second) - replayBlocks := make(map[uint64]uint64) - replayBlocks[sourceChain] = 1 - replayBlocks[destChain] = 1 - changeset.ReplayLogs(t, e.Env.Offchain, replayBlocks) - - // Confirm that the message is committed and executed - changeset.ConfirmCommitForAllWithExpectedSeqNums(t, e.Env, state, expectedSeqNum, startBlocks) - changeset.ConfirmExecWithSeqNrsForAll(t, e.Env, state, expectedSeqNumExec, startBlocks) -} - -// TODO: Find a more accurate way to determine if fee boosting will be triggered -func willTriggerFeeBoosting( - t *testing.T, - msgSentEvent *onramp.OnRampCCIPMessageSent, - state changeset.CCIPOnChainState, - srcChain, destChain uint64) bool { - msg := convertToMessage(msgSentEvent.Message) - t.Log("\n=== Fee Boosting Analysis ===") - t.Logf("Src Chain: %d", msg.Header.SourceChainSelector) - t.Logf("Dest Chain: %d", msg.Header.DestChainSelector) - - ep := ccipevm.NewGasEstimateProvider() - chainState, exists := state.Chains[srcChain] - require.True(t, exists) - feeQuoter := chainState.FeeQuoter - - premium, err := feeQuoter.GetPremiumMultiplierWeiPerEth(&bind.CallOpts{Context: context.Background()}, chainState.Weth9.Address()) - require.NoError(t, err) - t.Logf("Premium: %d", premium) - - // Get LINK price - linkPrice, err := feeQuoter.GetTokenPrice(&bind.CallOpts{Context: context.Background()}, chainState.LinkToken.Address()) - require.NoError(t, err) - t.Logf("LINK Price: %s", linkPrice.Value.String()) - t.Logf("Juels in message: %s", msg.FeeValueJuels.String()) - - // Calculate fee in USD token - fee := new(big.Int).Div( - new(big.Int).Mul(linkPrice.Value, msg.FeeValueJuels.Int), - new(big.Int).Exp(big.NewInt(10), big.NewInt(18), nil), - ) - t.Logf("Fee paid (in USD token): %s", fee.String()) - - // Calculate message gas - messageGas := new(big.Int).SetUint64(ep.CalculateMessageMaxGas(msg)) - t.Logf("Estimated message gas: %s", messageGas.String()) - - // Get token and gas prices - nativeTokenAddress := chainState.Weth9.Address() - tokenAndGasPrice, err := feeQuoter.GetTokenAndGasPrices(&bind.CallOpts{Context: context.Background()}, nativeTokenAddress, destChain) - require.NoError(t, err) - t.Logf("Raw gas price (uint224): %s for chain: %d", tokenAndGasPrice.GasPriceValue.String(), destChain) - - // Extract uint112 gas price - gasPrice, err := convertGasPriceToUint112(tokenAndGasPrice.GasPriceValue) - require.NoError(t, err) - t.Logf("Extracted gas price (uint112): %s", gasPrice.String()) - t.Logf("Native token price: %s", tokenAndGasPrice.TokenPrice.String()) - - // Calculate total execution cost - execCost := new(big.Int).Mul(messageGas, gasPrice) - t.Logf("Total execution cost: %s", execCost.String()) - - // Check if fee boosting will trigger - willBoost := execCost.Cmp(fee) > 0 - t.Logf("\nWill fee boosting trigger? %v", willBoost) - t.Logf("Execution cost / Fee ratio: %.2f", - new(big.Float).Quo( - new(big.Float).SetInt(execCost), - new(big.Float).SetInt(fee), - ), - ) - - return execCost.Cmp(fee) > 0 -} - -func convertGasPriceToUint112(gasPrice *big.Int) (*big.Int, error) { - // Create a mask for uint112 (112 bits of 1s) - mask := new(big.Int).Sub(new(big.Int).Lsh(big.NewInt(1), 112), big.NewInt(1)) - - // Extract the lower 112 bits using AND operation - result := new(big.Int).And(gasPrice, mask) - - return result, nil -} - -func convertToMessage(msg onramp.InternalEVM2AnyRampMessage) cciptypes.Message { - // Convert header - header := cciptypes.RampMessageHeader{ - MessageID: cciptypes.Bytes32(msg.Header.MessageId), - SourceChainSelector: cciptypes.ChainSelector(msg.Header.SourceChainSelector), - DestChainSelector: cciptypes.ChainSelector(msg.Header.DestChainSelector), - SequenceNumber: cciptypes.SeqNum(msg.Header.SequenceNumber), - Nonce: msg.Header.Nonce, - } - - // Convert token amounts - tokenAmounts := make([]cciptypes.RampTokenAmount, len(msg.TokenAmounts)) - for i, ta := range msg.TokenAmounts { - tokenAmounts[i] = cciptypes.RampTokenAmount{ - SourcePoolAddress: cciptypes.UnknownAddress(ta.SourcePoolAddress.Bytes()), - DestTokenAddress: cciptypes.UnknownAddress(ta.DestTokenAddress), - ExtraData: cciptypes.Bytes(ta.ExtraData), - Amount: cciptypes.BigInt{Int: ta.Amount}, - DestExecData: cciptypes.Bytes(ta.DestExecData), - } - } - - return cciptypes.Message{ - Header: header, - Sender: cciptypes.UnknownAddress(msg.Sender.Bytes()), - Data: cciptypes.Bytes(msg.Data), - Receiver: cciptypes.UnknownAddress(msg.Receiver), - ExtraArgs: cciptypes.Bytes(msg.ExtraArgs), - FeeToken: cciptypes.UnknownAddress(msg.FeeToken.Bytes()), - FeeTokenAmount: cciptypes.BigInt{Int: msg.FeeTokenAmount}, - FeeValueJuels: cciptypes.BigInt{Int: msg.FeeValueJuels}, - TokenAmounts: tokenAmounts, - } -} diff --git a/integration-tests/smoke/ccip/ccip_fees_test.go b/integration-tests/smoke/ccip/ccip_fees_test.go deleted file mode 100644 index 57a6bc58d82..00000000000 --- a/integration-tests/smoke/ccip/ccip_fees_test.go +++ /dev/null @@ -1,458 +0,0 @@ -package smoke - -import ( - "math/big" - "testing" - - "github.com/ethereum/go-ethereum/accounts/abi/bind" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/common/math" - "github.com/stretchr/testify/require" - - "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" - "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/testcontext" - - "github.com/smartcontractkit/chainlink/deployment" - "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" - testsetups "github.com/smartcontractkit/chainlink/integration-tests/testsetups/ccip" - "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/router" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/weth9_wrapper" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/shared/generated/burn_mint_erc677" - "github.com/smartcontractkit/chainlink/v2/core/logger" -) - -// setupTokens deploys transferable tokens on the source and dest, mints tokens for the source and dest, and -// approves the router to spend the tokens -func setupTokens( - t *testing.T, - state changeset.CCIPOnChainState, - tenv changeset.DeployedEnv, - src, dest uint64, - transferTokenMintAmount, - feeTokenMintAmount *big.Int, -) ( - srcToken *burn_mint_erc677.BurnMintERC677, - dstToken *burn_mint_erc677.BurnMintERC677, -) { - lggr := logger.TestLogger(t) - e := tenv.Env - - // Deploy the token to test transferring - srcToken, _, dstToken, _, err := changeset.DeployTransferableToken( - lggr, - tenv.Env.Chains, - src, - dest, - tenv.Env.Chains[src].DeployerKey, - tenv.Env.Chains[dest].DeployerKey, - state, - tenv.Env.ExistingAddresses, - "MY_TOKEN", - ) - require.NoError(t, err) - - linkToken := state.Chains[src].LinkToken - - tx, err := srcToken.Mint( - e.Chains[src].DeployerKey, - e.Chains[src].DeployerKey.From, - transferTokenMintAmount, - ) - _, err = deployment.ConfirmIfNoError(e.Chains[src], tx, err) - require.NoError(t, err) - - // Mint a destination token - tx, err = dstToken.Mint( - e.Chains[dest].DeployerKey, - e.Chains[dest].DeployerKey.From, - transferTokenMintAmount, - ) - _, err = deployment.ConfirmIfNoError(e.Chains[dest], tx, err) - require.NoError(t, err) - - // Approve the router to spend the tokens and confirm the tx's - // To prevent having to approve the router for every transfer, we approve a sufficiently large amount - tx, err = srcToken.Approve(e.Chains[src].DeployerKey, state.Chains[src].Router.Address(), math.MaxBig256) - _, err = deployment.ConfirmIfNoError(e.Chains[src], tx, err) - require.NoError(t, err) - - tx, err = dstToken.Approve(e.Chains[dest].DeployerKey, state.Chains[dest].Router.Address(), math.MaxBig256) - _, err = deployment.ConfirmIfNoError(e.Chains[dest], tx, err) - require.NoError(t, err) - - // Grant mint and burn roles to the deployer key for the newly deployed linkToken - // Since those roles are not granted automatically - tx, err = linkToken.GrantMintAndBurnRoles(e.Chains[src].DeployerKey, e.Chains[src].DeployerKey.From) - _, err = deployment.ConfirmIfNoError(e.Chains[src], tx, err) - require.NoError(t, err) - - // Mint link token and confirm the tx - tx, err = linkToken.Mint( - e.Chains[src].DeployerKey, - e.Chains[src].DeployerKey.From, - feeTokenMintAmount, - ) - _, err = deployment.ConfirmIfNoError(e.Chains[src], tx, err) - require.NoError(t, err) - - return srcToken, dstToken -} - -func Test_CCIPFees(t *testing.T) { - t.Parallel() - tenv, _ := testsetups.NewIntegrationEnvironment( - t, - changeset.WithMultiCall3(), - ) - e := tenv.Env - - allChains := tenv.Env.AllChainSelectors() - require.Len(t, allChains, 2, "need two chains for this test") - sourceChain := allChains[0] - destChain := allChains[1] - - // Get new state after migration. - state, err := changeset.LoadOnchainState(e) - require.NoError(t, err) - - srcToken, dstToken := setupTokens( - t, - state, - tenv, - sourceChain, - destChain, - deployment.E18Mult(10_000), - deployment.E18Mult(10_000), - ) - - // Ensure capreg logs are up to date. - changeset.ReplayLogs(t, e.Offchain, tenv.ReplayBlocks) - - // Add all lanes - changeset.AddLanesForAll(t, &tenv, state) - - t.Run("Send programmable token transfer pay with Link token", func(t *testing.T) { - runFeeTokenTestCase(feeTokenTestCase{ - t: t, - dst: destChain, - src: sourceChain, - env: tenv, - tokenAmounts: []router.ClientEVMTokenAmount{ - { - Token: srcToken.Address(), - Amount: deployment.E18Mult(2), - }, - }, - feeToken: state.Chains[sourceChain].LinkToken.Address(), - data: []byte("hello ptt world"), - receiver: common.LeftPadBytes(state.Chains[destChain].Receiver.Address().Bytes(), 32), - srcToken: srcToken, - dstToken: dstToken, - assertTokenBalance: true, - }) - }) - - t.Run("Send programmable token transfer pay with native", func(t *testing.T) { - runFeeTokenTestCase(feeTokenTestCase{ - t: t, - - // note the order of src and dest is reversed here - src: destChain, - dst: sourceChain, - - env: tenv, - tokenAmounts: []router.ClientEVMTokenAmount{ - { - Token: dstToken.Address(), - Amount: deployment.E18Mult(2), - }, - }, - feeToken: common.HexToAddress("0x0"), - data: []byte("hello ptt world"), - receiver: common.LeftPadBytes(state.Chains[sourceChain].Receiver.Address().Bytes(), 32), - - // note the order of src and dest is reversed here - srcToken: dstToken, - dstToken: srcToken, - assertTokenBalance: true, - }) - }) - - t.Run("Send programmable token transfer pay with wrapped native", func(t *testing.T) { - runFeeTokenTestCase(feeTokenTestCase{ - t: t, - src: sourceChain, - dst: destChain, - env: tenv, - tokenAmounts: []router.ClientEVMTokenAmount{ - { - Token: srcToken.Address(), - Amount: deployment.E18Mult(2), - }, - }, - feeToken: state.Chains[sourceChain].Weth9.Address(), - data: []byte("hello ptt world"), - receiver: common.LeftPadBytes(state.Chains[destChain].Receiver.Address().Bytes(), 32), - srcToken: srcToken, - dstToken: dstToken, - assertTokenBalance: true, - }) - }) - - t.Run("Send programmable token transfer but revert not enough tokens", func(t *testing.T) { - // Send to the receiver on the destination chain paying with LINK token - var ( - receiver = common.LeftPadBytes(state.Chains[destChain].Receiver.Address().Bytes(), 32) - data = []byte("") - feeToken = state.Chains[sourceChain].LinkToken.Address() - ) - - // Increase the token send amount to more than available to intentionally cause a revert - ccipMessage := router.ClientEVM2AnyMessage{ - Receiver: receiver, - Data: data, - TokenAmounts: []router.ClientEVMTokenAmount{ - { - Token: srcToken.Address(), - Amount: deployment.E18Mult(100_000_000), - }, - }, - FeeToken: feeToken, - ExtraArgs: nil, - } - - _, _, err = changeset.CCIPSendRequest( - e, - state, - &changeset.CCIPSendReqConfig{ - Sender: e.Chains[sourceChain].DeployerKey, - IsTestRouter: true, - SourceChain: sourceChain, - DestChain: destChain, - Evm2AnyMessage: ccipMessage, - }, - ) - require.Error(t, err) - }) - - t.Run("Send data-only message pay with link token", func(t *testing.T) { - runFeeTokenTestCase(feeTokenTestCase{ - t: t, - src: sourceChain, - dst: destChain, - env: tenv, - // no tokens, only data - tokenAmounts: nil, - feeToken: state.Chains[sourceChain].LinkToken.Address(), - data: []byte("hello link world"), - receiver: common.LeftPadBytes(state.Chains[destChain].Receiver.Address().Bytes(), 32), - srcToken: srcToken, - dstToken: dstToken, - assertTokenBalance: false, - }) - }) - - t.Run("Send message pay with native", func(t *testing.T) { - runFeeTokenTestCase(feeTokenTestCase{ - t: t, - src: sourceChain, - dst: destChain, - env: tenv, - // no tokens, only data - tokenAmounts: nil, - feeToken: common.HexToAddress("0x0"), - data: []byte("hello native world"), - receiver: common.LeftPadBytes(state.Chains[destChain].Receiver.Address().Bytes(), 32), - srcToken: srcToken, - dstToken: dstToken, - assertTokenBalance: false, - }) - }) - - t.Run("Send message pay with wrapped native", func(t *testing.T) { - runFeeTokenTestCase(feeTokenTestCase{ - t: t, - src: sourceChain, - dst: destChain, - env: tenv, - // no tokens, only data - tokenAmounts: nil, - feeToken: state.Chains[sourceChain].Weth9.Address(), - data: []byte("hello wrapped native world"), - receiver: common.LeftPadBytes(state.Chains[destChain].Receiver.Address().Bytes(), 32), - srcToken: srcToken, - dstToken: dstToken, - assertTokenBalance: false, - }) - }) -} - -type feeTokenTestCase struct { - t *testing.T - src, dst uint64 - env changeset.DeployedEnv - srcToken, dstToken *burn_mint_erc677.BurnMintERC677 - tokenAmounts []router.ClientEVMTokenAmount - feeToken common.Address - receiver []byte - data []byte - assertTokenBalance bool -} - -func runFeeTokenTestCase(tc feeTokenTestCase) { - ctx := tests.Context(tc.t) - // Need to keep track of the block number for each chain so that event subscription can be done from that block. - startBlocks := make(map[uint64]*uint64) - expectedSeqNum := make(map[changeset.SourceDestPair]uint64) - expectedSeqNumExec := make(map[changeset.SourceDestPair][]uint64) - - srcChain := tc.env.Env.Chains[tc.src] - dstChain := tc.env.Env.Chains[tc.dst] - - state, err := changeset.LoadOnchainState(tc.env.Env) - require.NoError(tc.t, err) - - var dstTokBalanceBefore *big.Int - if tc.assertTokenBalance { - var err error - dstTokBalanceBefore, err = tc.dstToken.BalanceOf(nil, state.Chains[tc.dst].Receiver.Address()) - require.NoError(tc.t, err) - tc.t.Logf("destination token balance before of receiver %s: %s", - state.Chains[tc.dst].Receiver.Address(), - dstTokBalanceBefore.String()) - } - - // if fee token is not native then approve the router to spend the fee token from the sender. - var feeTokenWrapper *burn_mint_erc677.BurnMintERC677 - if tc.feeToken != common.HexToAddress("0x0") { - if tc.feeToken == state.Chains[tc.src].Weth9.Address() { - // Deposit some ETH into the WETH contract - weth9, err := weth9_wrapper.NewWETH9(state.Chains[tc.src].Weth9.Address(), srcChain.Client) - require.NoError(tc.t, err) - - balance, err := srcChain.Client.BalanceAt(ctx, srcChain.DeployerKey.From, nil) - require.NoError(tc.t, err) - - tc.t.Logf("balance before deposit: %s", balance.String()) - - srcChain.DeployerKey.Value = assets.Ether(100).ToInt() - tx, err := weth9.Deposit(srcChain.DeployerKey) - _, err = deployment.ConfirmIfNoError(srcChain, tx, err) - require.NoError(tc.t, err) - srcChain.DeployerKey.Value = big.NewInt(0) - } - - var err error - feeTokenWrapper, err = burn_mint_erc677.NewBurnMintERC677(tc.feeToken, srcChain.Client) - require.NoError(tc.t, err) - - // Approve the router to spend fee token - tx, err := feeTokenWrapper.Approve(srcChain.DeployerKey, state.Chains[tc.src].Router.Address(), math.MaxBig256) - - _, err = deployment.ConfirmIfNoError(srcChain, tx, err) - require.NoError(tc.t, err) - } - - // get the header for the destination chain and the relevant block number - latesthdr, err := dstChain.Client.HeaderByNumber(testcontext.Get(tc.t), nil) - require.NoError(tc.t, err) - block := latesthdr.Number.Uint64() - startBlocks[tc.dst] = &block - - // Get the fee Token Balance Before, if not fee token set get native balance. - var feeTokenBalanceBefore *big.Int - if feeTokenWrapper != nil { - feeTokenBalanceBefore, err = feeTokenWrapper.BalanceOf(&bind.CallOpts{ - Context: ctx, - }, srcChain.DeployerKey.From) - require.NoError(tc.t, err) - } else { - feeTokenBalanceBefore, err = srcChain.Client.BalanceAt(ctx, srcChain.DeployerKey.From, nil) - require.NoError(tc.t, err) - } - tc.t.Logf("fee token balance before: %s, fee token enabled: %s", - feeTokenBalanceBefore.String(), tc.feeToken.String()) - - msgSentEvent := changeset.TestSendRequest( - tc.t, - tc.env.Env, - state, - tc.src, - tc.dst, - false, - router.ClientEVM2AnyMessage{ - Receiver: tc.receiver, - Data: tc.data, - TokenAmounts: tc.tokenAmounts, - FeeToken: tc.feeToken, - ExtraArgs: nil, - }, - ) - - expectedSeqNum[changeset.SourceDestPair{ - SourceChainSelector: tc.src, - DestChainSelector: tc.dst, - }] = msgSentEvent.SequenceNumber - expectedSeqNumExec[changeset.SourceDestPair{ - SourceChainSelector: tc.src, - DestChainSelector: tc.dst, - }] = []uint64{msgSentEvent.SequenceNumber} - - // Check the fee token balance after the request and ensure fee tokens were spent - var feeTokenBalanceAfter *big.Int - if feeTokenWrapper != nil { - feeTokenBalanceAfter, err = feeTokenWrapper.BalanceOf(&bind.CallOpts{ - Context: ctx, - }, srcChain.DeployerKey.From) - require.NoError(tc.t, err) - } else { - feeTokenBalanceAfter, err = srcChain.Client.BalanceAt(ctx, srcChain.DeployerKey.From, nil) - require.NoError(tc.t, err) - } - tc.t.Logf("fee token balance after: %s, fee token: %s, fee paid: %s", - feeTokenBalanceAfter.String(), tc.feeToken.String(), msgSentEvent.Message.FeeTokenAmount) - // in the case we have no fee token, native is also used to pay for the tx, - // so we have to subtract that as well - if feeTokenWrapper == nil { - receipt, err := srcChain.Client.TransactionReceipt(ctx, msgSentEvent.Raw.TxHash) - require.NoError(tc.t, err) - txCostWei := new(big.Int).Mul(new(big.Int).SetUint64(receipt.GasUsed), receipt.EffectiveGasPrice) - feeTokenBalanceBefore.Sub(feeTokenBalanceBefore, txCostWei) - } - require.Equal( - tc.t, - feeTokenBalanceAfter, - new(big.Int).Sub(feeTokenBalanceBefore, msgSentEvent.Message.FeeTokenAmount), - ) - - // Wait for all commit reports to land. - changeset.ConfirmCommitForAllWithExpectedSeqNums(tc.t, tc.env.Env, state, expectedSeqNum, startBlocks) - - // After commit is reported on all chains, token prices should be updated in FeeQuoter. - linkAddress := state.Chains[tc.dst].LinkToken.Address() - feeQuoter := state.Chains[tc.dst].FeeQuoter - timestampedPrice, err := feeQuoter.GetTokenPrice(&bind.CallOpts{ - Context: ctx, - }, linkAddress) - require.NoError(tc.t, err) - require.Equal(tc.t, changeset.MockLinkPrice, timestampedPrice.Value) - - // Wait for all exec reports to land - changeset.ConfirmExecWithSeqNrsForAll(tc.t, tc.env.Env, state, expectedSeqNumExec, startBlocks) - - if tc.assertTokenBalance { - require.Len(tc.t, tc.tokenAmounts, 1) - expectedTransferAmount := tc.tokenAmounts[0].Amount - - balanceAfter, err := tc.dstToken.BalanceOf(&bind.CallOpts{ - Context: ctx, - }, state.Chains[tc.dst].Receiver.Address()) - require.NoError(tc.t, err) - require.Equal( - tc.t, - new(big.Int).Add(dstTokBalanceBefore, expectedTransferAmount), - balanceAfter, - ) - } -} diff --git a/integration-tests/smoke/ccip/ccip_gas_price_updates_test.go b/integration-tests/smoke/ccip/ccip_gas_price_updates_test.go deleted file mode 100644 index 2c1d97f6c12..00000000000 --- a/integration-tests/smoke/ccip/ccip_gas_price_updates_test.go +++ /dev/null @@ -1,125 +0,0 @@ -package smoke - -import ( - "math/big" - "testing" - "time" - - "github.com/ethereum/go-ethereum/accounts/abi/bind" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - "golang.org/x/exp/maps" - - "github.com/smartcontractkit/chainlink-common/pkg/config" - "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" - - "github.com/smartcontractkit/chainlink/deployment" - "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" - testsetups "github.com/smartcontractkit/chainlink/integration-tests/testsetups/ccip" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/fee_quoter" -) - -// Test_CCIPGasPriceUpdates tests that chain fee price updates are propagated correctly when -// price reaches some deviation threshold or when the price has expired. -func Test_CCIPGasPriceUpdates(t *testing.T) { - ctx := changeset.Context(t) - callOpts := &bind.CallOpts{Context: ctx} - - var gasPriceExpiry = 5 * time.Second - e, _ := testsetups.NewIntegrationEnvironment(t, - changeset.WithOCRConfigOverride(func(params changeset.CCIPOCRParams) changeset.CCIPOCRParams { - params.CommitOffChainConfig.RemoteGasPriceBatchWriteFrequency = *config.MustNewDuration(gasPriceExpiry) - return params - }), - ) - state, err := changeset.LoadOnchainState(e.Env) - require.NoError(t, err) - changeset.AddLanesForAll(t, &e, state) - - allChainSelectors := maps.Keys(e.Env.Chains) - assert.GreaterOrEqual(t, len(allChainSelectors), 2, "test requires at least 2 chains") - - sourceChain1 := allChainSelectors[0] - sourceChain2 := allChainSelectors[1] - - feeQuoter1 := state.Chains[sourceChain1].FeeQuoter - feeQuoter2 := state.Chains[sourceChain2].FeeQuoter - - // get initial chain fees - initialChain2Fee, err := feeQuoter1.GetDestinationChainGasPrice(callOpts, sourceChain2) - require.NoError(t, err) - initialChain1Fee, err := feeQuoter2.GetDestinationChainGasPrice(callOpts, sourceChain1) - require.NoError(t, err) - t.Logf("initial chain1 fee (stored in chain2): %v", initialChain1Fee) - t.Logf("initial chain2 fee (stored in chain1): %v", initialChain2Fee) - - // get latest price updates sequence number from the offRamps - offRampChain1 := state.Chains[sourceChain1].OffRamp - offRampChain2 := state.Chains[sourceChain2].OffRamp - priceUpdatesSeqNumChain1, err := offRampChain1.GetLatestPriceSequenceNumber(callOpts) - require.NoError(t, err) - priceUpdatesSeqNumChain2, err := offRampChain2.GetLatestPriceSequenceNumber(callOpts) - require.NoError(t, err) - t.Logf("priceUpdatesSeqNumChain1: %v", priceUpdatesSeqNumChain1) - t.Logf("priceUpdatesSeqNumChain2: %v", priceUpdatesSeqNumChain2) - - // update the price of chain2 - tx, err := feeQuoter1.UpdatePrices(e.Env.Chains[sourceChain1].DeployerKey, fee_quoter.InternalPriceUpdates{ - TokenPriceUpdates: nil, - GasPriceUpdates: []fee_quoter.InternalGasPriceUpdate{ - {DestChainSelector: sourceChain2, UsdPerUnitGas: big.NewInt(5123)}, - }, - }) - require.NoError(t, err) - _, err = deployment.ConfirmIfNoError(e.Env.Chains[sourceChain1], tx, err) - require.NoError(t, err) - - // assert that the chain fees are updated by the commit plugin reports - priceDeviationChecked := false // flag to check if price deviation condition was met - assert.Eventually(t, func() bool { - // offRamps should have updated the sequence number - priceUpdatesSeqNumChain1Now, err := offRampChain1.GetLatestPriceSequenceNumber(callOpts) - require.NoError(t, err) - priceUpdatesSeqNumChain2Now, err := offRampChain2.GetLatestPriceSequenceNumber(callOpts) - require.NoError(t, err) - t.Logf("priceUpdatesSeqNumChain1: %v", priceUpdatesSeqNumChain1Now) - t.Logf("priceUpdatesSeqNumChain2: %v", priceUpdatesSeqNumChain2Now) - if priceUpdatesSeqNumChain1Now <= priceUpdatesSeqNumChain1 { - return false - } - if priceUpdatesSeqNumChain2Now <= priceUpdatesSeqNumChain2 { - return false - } - - chain2FeeNow, err := feeQuoter1.GetDestinationChainGasPrice(callOpts, sourceChain2) - require.NoError(t, err) - chain1FeeNow, err := feeQuoter2.GetDestinationChainGasPrice(callOpts, sourceChain1) - require.NoError(t, err) - t.Logf("chainFee1 (stored in chain2): %v", chain1FeeNow) - t.Logf("chainFee2 (stored in chain1): %v", chain2FeeNow) - - if !priceDeviationChecked { - // make sure there was a price update for chain2 when price deviation was reached - if chain2FeeNow.Value.Cmp(initialChain2Fee.Value) == 0 { - t.Logf("chainFee2 not updated: %v original=%v", chain2FeeNow, initialChain2Fee.Value) - return false - } - require.NotEqual(t, chain2FeeNow.Timestamp, initialChain2Fee.Timestamp) - priceDeviationChecked = true - } - - // make sure there was a price update for chain1 but with the same price - when expiration is reached - if chain1FeeNow.Timestamp == initialChain1Fee.Timestamp { - t.Logf("chainFee1 timestamp not updated: %v original=%v", chain1FeeNow, initialChain1Fee.Timestamp) - initialChain1Fee = chain1FeeNow - return false - } - if chain1FeeNow.Value.Cmp(initialChain1Fee.Value) != 0 { - t.Logf("chainFee1 changed: %v prev:%v", chain1FeeNow, initialChain1Fee.Value) - initialChain1Fee = chain1FeeNow - return false - } - - return priceDeviationChecked - }, tests.WaitTimeout(t), 500*time.Millisecond) -} diff --git a/integration-tests/smoke/ccip/ccip_legacy_test.go b/integration-tests/smoke/ccip/ccip_legacy_test.go deleted file mode 100644 index 2b5b6d77b58..00000000000 --- a/integration-tests/smoke/ccip/ccip_legacy_test.go +++ /dev/null @@ -1,51 +0,0 @@ -package smoke - -import ( - "context" - "testing" - - "github.com/ethereum/go-ethereum/common" - "github.com/stretchr/testify/require" - - "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" - "github.com/smartcontractkit/chainlink/deployment/ccip/changeset/v1_5" - testsetups "github.com/smartcontractkit/chainlink/integration-tests/testsetups/ccip" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/router" -) - -// This test does not run in CI, it is only written as an example of how to write a test for the legacy CCIP -func TestE2ELegacy(t *testing.T) { - e, _ := testsetups.NewIntegrationEnvironment(t, changeset.WithLegacyDeployment()) - state, err := changeset.LoadOnchainState(e.Env) - require.NoError(t, err) - allChains := e.Env.AllChainSelectors() - require.Len(t, allChains, 2) - src, dest := allChains[0], allChains[1] - srcChain := e.Env.Chains[src] - destChain := e.Env.Chains[dest] - pairs := []changeset.SourceDestPair{ - {SourceChainSelector: src, DestChainSelector: dest}, - } - e.Env = v1_5.AddLanes(t, e.Env, state, pairs) - // reload state after adding lanes - state, err = changeset.LoadOnchainState(e.Env) - require.NoError(t, err) - sentEvent, err := v1_5.SendRequest(t, e.Env, state, - changeset.WithSourceChain(src), - changeset.WithDestChain(dest), - changeset.WithTestRouter(false), - changeset.WithEvm2AnyMessage(router.ClientEVM2AnyMessage{ - Receiver: common.LeftPadBytes(state.Chains[dest].Receiver.Address().Bytes(), 32), - Data: []byte("hello"), - TokenAmounts: nil, - FeeToken: common.HexToAddress("0x0"), - ExtraArgs: nil, - }), - ) - require.NoError(t, err) - require.NotNil(t, sentEvent) - destStartBlock, err := destChain.Client.HeaderByNumber(context.Background(), nil) - require.NoError(t, err) - v1_5.WaitForCommit(t, srcChain, destChain, state.Chains[dest].CommitStore[src], sentEvent.Message.SequenceNumber) - v1_5.WaitForExecute(t, srcChain, destChain, state.Chains[dest].EVM2EVMOffRamp[src], []uint64{sentEvent.Message.SequenceNumber}, destStartBlock.Number.Uint64()) -} diff --git a/integration-tests/smoke/ccip/ccip_message_limitations_test.go b/integration-tests/smoke/ccip/ccip_message_limitations_test.go deleted file mode 100644 index f9299b735d0..00000000000 --- a/integration-tests/smoke/ccip/ccip_message_limitations_test.go +++ /dev/null @@ -1,186 +0,0 @@ -package smoke - -import ( - "math/big" - "slices" - "strings" - "testing" - - "github.com/ethereum/go-ethereum/accounts/abi/bind" - "github.com/ethereum/go-ethereum/common" - "github.com/stretchr/testify/require" - "golang.org/x/exp/maps" - - "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/testcontext" - - "github.com/smartcontractkit/chainlink/deployment" - "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" - testsetups "github.com/smartcontractkit/chainlink/integration-tests/testsetups/ccip" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/router" -) - -func Test_CCIPMessageLimitations(t *testing.T) { - ctx := testcontext.Get(t) - callOpts := &bind.CallOpts{Context: ctx} - - testEnv, _ := testsetups.NewIntegrationEnvironment(t) - chains := maps.Keys(testEnv.Env.Chains) - - onChainState, err := changeset.LoadOnchainState(testEnv.Env) - require.NoError(t, err) - - changeset.AddLanesForAll(t, &testEnv, onChainState) - - srcToken, _ := setupTokens( - t, - onChainState, - testEnv, - chains[0], - chains[1], - deployment.E18Mult(10_000), - deployment.E18Mult(10_000), - ) - - chain0DestConfig, err := onChainState.Chains[chains[0]].FeeQuoter.GetDestChainConfig(callOpts, chains[1]) - require.NoError(t, err) - t.Logf("0->1 destination config: %+v", chain0DestConfig) - - testMsgs := []struct { - name string - fromChain uint64 - toChain uint64 - msg router.ClientEVM2AnyMessage - expRevert bool - }{ - { - name: "hit limit on data", - fromChain: chains[0], - toChain: chains[1], - msg: router.ClientEVM2AnyMessage{ - Receiver: common.LeftPadBytes(onChainState.Chains[chains[1]].Receiver.Address().Bytes(), 32), - Data: []byte(strings.Repeat("0", int(chain0DestConfig.MaxDataBytes))), - FeeToken: common.HexToAddress("0x0"), - }, - }, - { - name: "hit limit on tokens", - fromChain: chains[0], - toChain: chains[1], - msg: router.ClientEVM2AnyMessage{ - Receiver: common.LeftPadBytes(onChainState.Chains[chains[1]].Receiver.Address().Bytes(), 32), - TokenAmounts: slices.Repeat([]router.ClientEVMTokenAmount{ - {Token: srcToken.Address(), Amount: big.NewInt(1)}, - }, int(chain0DestConfig.MaxNumberOfTokensPerMsg)), - FeeToken: common.HexToAddress("0x0"), - }, - }, - { - name: "hit limit on gas limit", - fromChain: chains[0], - toChain: chains[1], - msg: router.ClientEVM2AnyMessage{ - Receiver: common.LeftPadBytes(onChainState.Chains[chains[1]].Receiver.Address().Bytes(), 32), - Data: []byte(strings.Repeat("0", int(chain0DestConfig.MaxDataBytes))), - FeeToken: common.HexToAddress("0x0"), - ExtraArgs: changeset.MakeEVMExtraArgsV2(uint64(chain0DestConfig.MaxPerMsgGasLimit), true), - }, - }, - //{ // TODO: exec plugin never executed this message. CCIP-4471 - // name: "hit limit on maxDataBytes, tokens, gasLimit should succeed", - // fromChain: chains[0], - // toChain: chains[1], - // msg: router.ClientEVM2AnyMessage{ - // Receiver: common.LeftPadBytes(onChainState.Chains[chains[1]].Receiver.Address().Bytes(), 32), - // Data: []byte(strings.Repeat("0", int(chain0DestConfig.MaxDataBytes))), - // TokenAmounts: slices.Repeat([]router.ClientEVMTokenAmount{ - // {Token: srcToken.Address(), Amount: big.NewInt(1)}, - // }, int(chain0DestConfig.MaxNumberOfTokensPerMsg)), - // FeeToken: common.HexToAddress("0x0"), - // ExtraArgs: changeset.MakeEVMExtraArgsV2(uint64(chain0DestConfig.MaxPerMsgGasLimit), true), - // }, - //}, - { - name: "exceeding maxDataBytes", - fromChain: chains[0], - toChain: chains[1], - msg: router.ClientEVM2AnyMessage{ - Receiver: common.LeftPadBytes(onChainState.Chains[chains[1]].Receiver.Address().Bytes(), 32), - Data: []byte(strings.Repeat("0", int(chain0DestConfig.MaxDataBytes)+1)), - TokenAmounts: []router.ClientEVMTokenAmount{}, - FeeToken: common.HexToAddress("0x0"), - ExtraArgs: nil, - }, - expRevert: true, - }, - { - name: "exceeding number of tokens", - fromChain: chains[0], - toChain: chains[1], - msg: router.ClientEVM2AnyMessage{ - Receiver: common.LeftPadBytes(onChainState.Chains[chains[1]].Receiver.Address().Bytes(), 32), - Data: []byte("abc"), - TokenAmounts: slices.Repeat([]router.ClientEVMTokenAmount{ - {Token: srcToken.Address(), Amount: big.NewInt(1)}, - }, int(chain0DestConfig.MaxNumberOfTokensPerMsg)+1), - FeeToken: common.HexToAddress("0x0"), - ExtraArgs: nil, - }, - expRevert: true, - }, - { - name: "exceeding gas limit", - fromChain: chains[0], - toChain: chains[1], - msg: router.ClientEVM2AnyMessage{ - Receiver: common.LeftPadBytes(onChainState.Chains[chains[1]].Receiver.Address().Bytes(), 32), - Data: []byte("abc"), - TokenAmounts: []router.ClientEVMTokenAmount{}, - FeeToken: common.HexToAddress("0x0"), - ExtraArgs: changeset.MakeEVMExtraArgsV2(uint64(chain0DestConfig.MaxPerMsgGasLimit)+1, true), - }, - expRevert: true, - }, - } - - // Need to keep track of the block number for each chain so that event subscription can be done from that block. - startBlocks := make(map[uint64]*uint64) - // Send a message from each chain to every other chain. - expectedSeqNum := make(map[changeset.SourceDestPair]uint64) - expectedSeqNumExec := make(map[changeset.SourceDestPair][]uint64) - for _, msg := range testMsgs { - t.Logf("Sending msg: %s", msg.name) - require.NotEqual(t, msg.fromChain, msg.toChain, "fromChain and toChain cannot be the same") - startBlocks[msg.toChain] = nil - msgSentEvent, err := changeset.DoSendRequest( - t, testEnv.Env, onChainState, - changeset.WithSourceChain(msg.fromChain), - changeset.WithDestChain(msg.toChain), - changeset.WithTestRouter(false), - changeset.WithEvm2AnyMessage(msg.msg)) - - if msg.expRevert { - t.Logf("Message reverted as expected") - require.Error(t, err) - require.Contains(t, err.Error(), "execution reverted") - continue - } - require.NoError(t, err) - - t.Logf("Message not reverted as expected") - - expectedSeqNum[changeset.SourceDestPair{ - SourceChainSelector: msg.fromChain, - DestChainSelector: msg.toChain, - }] = msgSentEvent.SequenceNumber - - expectedSeqNumExec[changeset.SourceDestPair{ - SourceChainSelector: msg.fromChain, - DestChainSelector: msg.toChain, - }] = []uint64{msgSentEvent.SequenceNumber} - } - - // Wait for all commit reports to land. - changeset.ConfirmCommitForAllWithExpectedSeqNums(t, testEnv.Env, onChainState, expectedSeqNum, startBlocks) - // Wait for all exec reports to land - changeset.ConfirmExecWithSeqNrsForAll(t, testEnv.Env, onChainState, expectedSeqNumExec, startBlocks) -} diff --git a/integration-tests/smoke/ccip/ccip_ooo_execution_test.go b/integration-tests/smoke/ccip/ccip_ooo_execution_test.go deleted file mode 100644 index e3da473984d..00000000000 --- a/integration-tests/smoke/ccip/ccip_ooo_execution_test.go +++ /dev/null @@ -1,270 +0,0 @@ -package smoke - -import ( - "fmt" - "math/big" - "testing" - - "github.com/ethereum/go-ethereum/accounts/abi/bind" - "github.com/ethereum/go-ethereum/common" - "github.com/stretchr/testify/require" - "golang.org/x/exp/maps" - - "github.com/smartcontractkit/chainlink-ccip/pkg/types/ccipocr3" - "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" - - "github.com/smartcontractkit/chainlink/deployment" - "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" - testsetups "github.com/smartcontractkit/chainlink/integration-tests/testsetups/ccip" - "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/router" - "github.com/smartcontractkit/chainlink/v2/core/logger" -) - -// Send the following messages -// 1. src -> dest - out of order token transfer to EOA -// 2. src -> dest - ordered USDC token transfer, but with faulty attestation, should be stuck forever -// 3. src -> dest - ordered token transfer, should not be executed because previous message is stuck -// 4. src -> dest - out of order message transfer, should be executed anyway -// 5. src -> dest - ordered token transfer, but from a different sender -// -// All messages should be properly committed, but only 1 and 4, 5 are fully executed. -// Messages 2 and 3 are untouched, because ordering is enforced. -func Test_OutOfOrderExecution(t *testing.T) { - lggr := logger.TestLogger(t) - ctx := tests.Context(t) - tenv, _ := testsetups.NewIntegrationEnvironment( - t, - changeset.WithUSDC(), - changeset.WithUSDCAttestationMissing(), - changeset.WithUsersPerChain(2), - ) - - e := tenv.Env - state, err := changeset.LoadOnchainState(e) - require.NoError(t, err) - - allChainSelectors := maps.Keys(e.Chains) - sourceChain, destChain := allChainSelectors[0], allChainSelectors[1] - ownerSourceChain := e.Chains[sourceChain].DeployerKey - ownerDestChain := e.Chains[destChain].DeployerKey - - anotherSender, err := pickFirstAvailableUser(tenv, sourceChain, e) - require.NoError(t, err) - - oneE18 := new(big.Int).SetUint64(1e18) - - srcToken, _, destToken, _, err := changeset.DeployTransferableToken( - lggr, - tenv.Env.Chains, - sourceChain, - destChain, - ownerSourceChain, - ownerDestChain, - state, - e.ExistingAddresses, - "OWNER_TOKEN", - ) - require.NoError(t, err) - - srcUSDC, destUSDC, err := changeset.ConfigureUSDCTokenPools(lggr, e.Chains, sourceChain, destChain, state) - require.NoError(t, err) - - err = changeset.UpdateFeeQuoterForUSDC(lggr, e.Chains[sourceChain], state.Chains[sourceChain], destChain, srcUSDC) - require.NoError(t, err) - err = changeset.UpdateFeeQuoterForUSDC(lggr, e.Chains[destChain], state.Chains[destChain], sourceChain, destUSDC) - require.NoError(t, err) - - changeset.MintAndAllow( - t, - e, - state, - map[uint64][]changeset.MintTokenInfo{ - sourceChain: { - changeset.NewMintTokenInfo(ownerSourceChain, srcToken, srcUSDC), - changeset.NewMintTokenWithCustomSender(ownerSourceChain, anotherSender, srcToken), - }, - }, - ) - changeset.AddLanesForAll(t, &tenv, state) - - tokenTransfer := []router.ClientEVMTokenAmount{ - { - Token: srcToken.Address(), - Amount: oneE18, - }, - } - usdcTransfer := []router.ClientEVMTokenAmount{ - { - Token: srcUSDC.Address(), - Amount: oneE18, - }, - } - - identifier := changeset.SourceDestPair{ - SourceChainSelector: sourceChain, - DestChainSelector: destChain, - } - - startBlocks := make(map[uint64]*uint64) - expectedStatuses := make(map[uint64]int) - - latesthdr, err := e.Chains[destChain].Client.HeaderByNumber(ctx, nil) - require.NoError(t, err) - block := latesthdr.Number.Uint64() - startBlocks[destChain] = &block - - // Out of order execution to the EOA should be properly executed - firstReceiver := utils.RandomAddress() - firstMessage, _ := changeset.Transfer( - ctx, - t, - e, - state, - sourceChain, - destChain, - tokenTransfer, - firstReceiver, - nil, - changeset.MakeEVMExtraArgsV2(0, true), - ) - expectedStatuses[firstMessage.SequenceNumber] = changeset.EXECUTION_STATE_SUCCESS - t.Logf("Out of order messages sent from chain %d to chain %d with sequence number %d", - sourceChain, destChain, firstMessage.SequenceNumber, - ) - - // Ordered execution should fail because attestation is not present - secondReceiver := utils.RandomAddress() - secondMsg, _ := changeset.Transfer( - ctx, - t, - e, - state, - sourceChain, - destChain, - usdcTransfer, - secondReceiver, - nil, - nil, - ) - t.Logf("Ordered USDC transfer sent from chain %d to chain %d with sequence number %d", - sourceChain, destChain, secondMsg.SequenceNumber, - ) - - // Ordered token transfer should fail, because previous message cannot be executed - thirdReceiver := utils.RandomAddress() - thirdMessage, _ := changeset.Transfer( - ctx, - t, - e, - state, - sourceChain, - destChain, - tokenTransfer, - thirdReceiver, - nil, - changeset.MakeEVMExtraArgsV2(0, false), - ) - t.Logf("Ordered token transfer from chain %d to chain %d with sequence number %d", - sourceChain, destChain, thirdMessage.SequenceNumber, - ) - - // Out of order programmable token transfer should be executed - fourthReceiver := state.Chains[destChain].Receiver.Address() - fourthMessage, _ := changeset.Transfer( - ctx, - t, - e, - state, - sourceChain, - destChain, - tokenTransfer, - fourthReceiver, - []byte("this message has enough gas to execute"), - changeset.MakeEVMExtraArgsV2(300_000, true), - ) - expectedStatuses[fourthMessage.SequenceNumber] = changeset.EXECUTION_STATE_SUCCESS - t.Logf("Out of order programmable token transfer from chain %d to chain %d with sequence number %d", - sourceChain, destChain, fourthMessage.SequenceNumber, - ) - - // Ordered token transfer, but using different sender, should be executed - fifthReceiver := utils.RandomAddress() - fifthMessage, err := changeset.DoSendRequest(t, e, state, - changeset.WithSender(anotherSender), - changeset.WithSourceChain(sourceChain), - changeset.WithDestChain(destChain), - changeset.WithEvm2AnyMessage(router.ClientEVM2AnyMessage{ - Receiver: common.LeftPadBytes(fifthReceiver.Bytes(), 32), - Data: nil, - TokenAmounts: tokenTransfer, - FeeToken: common.HexToAddress("0x0"), - ExtraArgs: changeset.MakeEVMExtraArgsV2(0, false), - })) - require.NoError(t, err) - expectedStatuses[fifthMessage.SequenceNumber] = changeset.EXECUTION_STATE_SUCCESS - t.Logf("Ordered message send by %v from chain %d to chain %d with sequence number %d", - anotherSender.From, sourceChain, destChain, fifthMessage.SequenceNumber, - ) - - // All messages are committed, even these which are going to be reverted during the exec - _, err = changeset.ConfirmCommitWithExpectedSeqNumRange( - t, - e.Chains[sourceChain], - e.Chains[destChain], - state.Chains[destChain].OffRamp, - startBlocks[destChain], - ccipocr3.NewSeqNumRange( - ccipocr3.SeqNum(firstMessage.SequenceNumber), - ccipocr3.SeqNum(fifthMessage.SequenceNumber), - ), - // We don't verify batching here, so we don't need all messages to be in a single root - false, - ) - require.NoError(t, err) - - execStates := changeset.ConfirmExecWithSeqNrsForAll( - t, - e, - state, - map[changeset.SourceDestPair][]uint64{ - identifier: { - firstMessage.SequenceNumber, - fourthMessage.SequenceNumber, - fifthMessage.SequenceNumber, - }, - }, - startBlocks, - ) - require.Equal(t, expectedStatuses, execStates[identifier]) - - secondMsgState, err := state.Chains[destChain].OffRamp.GetExecutionState(&bind.CallOpts{Context: ctx}, sourceChain, secondMsg.SequenceNumber) - require.NoError(t, err) - require.Equal(t, uint8(changeset.EXECUTION_STATE_UNTOUCHED), secondMsgState) - - thirdMsgState, err := state.Chains[destChain].OffRamp.GetExecutionState(&bind.CallOpts{Context: ctx}, sourceChain, thirdMessage.SequenceNumber) - require.NoError(t, err) - require.Equal(t, uint8(changeset.EXECUTION_STATE_UNTOUCHED), thirdMsgState) - - changeset.WaitForTheTokenBalance(ctx, t, destToken.Address(), firstReceiver, e.Chains[destChain], oneE18) - changeset.WaitForTheTokenBalance(ctx, t, destUSDC.Address(), secondReceiver, e.Chains[destChain], big.NewInt(0)) - changeset.WaitForTheTokenBalance(ctx, t, destToken.Address(), thirdReceiver, e.Chains[destChain], big.NewInt(0)) - changeset.WaitForTheTokenBalance(ctx, t, destToken.Address(), fourthReceiver, e.Chains[destChain], oneE18) - changeset.WaitForTheTokenBalance(ctx, t, destToken.Address(), fifthReceiver, e.Chains[destChain], oneE18) -} - -func pickFirstAvailableUser( - tenv changeset.DeployedEnv, - sourceChain uint64, - e deployment.Environment, -) (*bind.TransactOpts, error) { - for _, user := range tenv.Users[sourceChain] { - if user == nil { - continue - } - if user.From != e.Chains[sourceChain].DeployerKey.From { - return user, nil - } - } - return nil, fmt.Errorf("user not found") -} diff --git a/integration-tests/smoke/ccip/ccip_rmn_test.go b/integration-tests/smoke/ccip/ccip_rmn_test.go deleted file mode 100644 index a3877013103..00000000000 --- a/integration-tests/smoke/ccip/ccip_rmn_test.go +++ /dev/null @@ -1,693 +0,0 @@ -package smoke - -import ( - "context" - "encoding/binary" - "errors" - "math/big" - "os" - "slices" - "strconv" - "strings" - "testing" - "time" - - mapset "github.com/deckarep/golang-set/v2" - "github.com/ethereum/go-ethereum/accounts/abi/bind" - "github.com/ethereum/go-ethereum/common" - "github.com/rs/zerolog" - "github.com/stretchr/testify/require" - - "github.com/smartcontractkit/chainlink-protos/job-distributor/v1/node" - "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/osutil" - "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/testcontext" - - "github.com/smartcontractkit/chainlink-ccip/pkg/reader" - - "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" - "github.com/smartcontractkit/chainlink/deployment/environment/devenv" - - "github.com/smartcontractkit/chainlink/deployment" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/rmn_home" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/rmn_remote" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/router" - - testsetups "github.com/smartcontractkit/chainlink/integration-tests/testsetups/ccip" -) - -func TestRMN_TwoMessagesOnTwoLanesIncludingBatching(t *testing.T) { - runRmnTestCase(t, rmnTestCase{ - name: "messages on two lanes including batching", - waitForExec: true, - homeChainConfig: homeChainConfig{ - f: map[int]int{chain0: 1, chain1: 1}, - }, - remoteChainsConfig: []remoteChainConfig{ - {chainIdx: chain0, f: 1}, - {chainIdx: chain1, f: 1}, - }, - rmnNodes: []rmnNode{ - {id: 0, isSigner: true, observedChainIdxs: []int{chain0, chain1}}, - {id: 1, isSigner: true, observedChainIdxs: []int{chain0, chain1}}, - {id: 2, isSigner: true, observedChainIdxs: []int{chain0, chain1}}, - }, - messagesToSend: []messageToSend{ - {fromChainIdx: chain0, toChainIdx: chain1, count: 1}, - {fromChainIdx: chain1, toChainIdx: chain0, count: 5}, - }, - }) -} - -func TestRMN_MultipleMessagesOnOneLaneNoWaitForExec(t *testing.T) { - runRmnTestCase(t, rmnTestCase{ - name: "multiple messages for rmn batching inspection and one rmn node down", - waitForExec: false, // do not wait for execution reports - homeChainConfig: homeChainConfig{ - f: map[int]int{chain0: 1, chain1: 1}, - }, - remoteChainsConfig: []remoteChainConfig{ - {chainIdx: chain0, f: 1}, - {chainIdx: chain1, f: 1}, - }, - rmnNodes: []rmnNode{ - {id: 0, isSigner: true, observedChainIdxs: []int{chain0, chain1}}, - {id: 1, isSigner: true, observedChainIdxs: []int{chain0, chain1}}, - {id: 2, isSigner: true, observedChainIdxs: []int{chain0, chain1}, forceExit: true}, // one rmn node is down - }, - messagesToSend: []messageToSend{ - {fromChainIdx: chain1, toChainIdx: chain0, count: 10}, - }, - }) -} - -func TestRMN_NotEnoughObservers(t *testing.T) { - runRmnTestCase(t, rmnTestCase{ - name: "one message but not enough observers, should not get a commit report", - passIfNoCommitAfter: 15 * time.Second, - homeChainConfig: homeChainConfig{ - f: map[int]int{chain0: 1, chain1: 1}, - }, - remoteChainsConfig: []remoteChainConfig{ - {chainIdx: chain0, f: 1}, - {chainIdx: chain1, f: 1}, - }, - rmnNodes: []rmnNode{ - {id: 0, isSigner: true, observedChainIdxs: []int{chain0, chain1}}, - {id: 1, isSigner: true, observedChainIdxs: []int{chain0, chain1}, forceExit: true}, - {id: 2, isSigner: true, observedChainIdxs: []int{chain0, chain1}, forceExit: true}, - }, - messagesToSend: []messageToSend{ - {fromChainIdx: chain0, toChainIdx: chain1, count: 1}, - }, - }) -} - -func TestRMN_DifferentSigners(t *testing.T) { - runRmnTestCase(t, rmnTestCase{ - name: "different signers and different observers", - homeChainConfig: homeChainConfig{ - f: map[int]int{chain0: 1, chain1: 1}, - }, - remoteChainsConfig: []remoteChainConfig{ - {chainIdx: chain0, f: 1}, - {chainIdx: chain1, f: 1}, - }, - rmnNodes: []rmnNode{ - {id: 0, isSigner: false, observedChainIdxs: []int{chain0, chain1}}, - {id: 1, isSigner: false, observedChainIdxs: []int{chain0, chain1}}, - {id: 2, isSigner: false, observedChainIdxs: []int{chain0, chain1}}, - {id: 3, isSigner: true, observedChainIdxs: []int{}}, - {id: 4, isSigner: true, observedChainIdxs: []int{}}, - {id: 5, isSigner: true, observedChainIdxs: []int{}}, - }, - messagesToSend: []messageToSend{ - {fromChainIdx: chain0, toChainIdx: chain1, count: 1}, - }, - }) -} - -func TestRMN_NotEnoughSigners(t *testing.T) { - runRmnTestCase(t, rmnTestCase{ - name: "different signers and different observers", - passIfNoCommitAfter: 15 * time.Second, - homeChainConfig: homeChainConfig{ - f: map[int]int{chain0: 1, chain1: 1}, - }, - remoteChainsConfig: []remoteChainConfig{ - {chainIdx: chain0, f: 1}, - {chainIdx: chain1, f: 1}, - }, - rmnNodes: []rmnNode{ - {id: 0, isSigner: false, observedChainIdxs: []int{chain0, chain1}}, - {id: 1, isSigner: false, observedChainIdxs: []int{chain0, chain1}}, - {id: 2, isSigner: false, observedChainIdxs: []int{chain0, chain1}}, - {id: 3, isSigner: true, observedChainIdxs: []int{}}, - {id: 4, isSigner: true, observedChainIdxs: []int{}, forceExit: true}, // signer is down - {id: 5, isSigner: true, observedChainIdxs: []int{}, forceExit: true}, // signer is down - }, - messagesToSend: []messageToSend{ - {fromChainIdx: chain0, toChainIdx: chain1, count: 1}, - }, - }) -} - -func TestRMN_DifferentRmnNodesForDifferentChains(t *testing.T) { - runRmnTestCase(t, rmnTestCase{ - name: "different rmn nodes support different chains", - waitForExec: false, - homeChainConfig: homeChainConfig{ - f: map[int]int{chain0: 1, chain1: 1}, - }, - remoteChainsConfig: []remoteChainConfig{ - {chainIdx: chain0, f: 1}, - {chainIdx: chain1, f: 1}, - }, - rmnNodes: []rmnNode{ - {id: 0, isSigner: true, observedChainIdxs: []int{chain0}}, - {id: 1, isSigner: true, observedChainIdxs: []int{chain0}}, - {id: 2, isSigner: true, observedChainIdxs: []int{chain0}}, - {id: 3, isSigner: true, observedChainIdxs: []int{chain1}}, - {id: 4, isSigner: true, observedChainIdxs: []int{chain1}}, - {id: 5, isSigner: true, observedChainIdxs: []int{chain1}}, - }, - messagesToSend: []messageToSend{ - {fromChainIdx: chain0, toChainIdx: chain1, count: 1}, - {fromChainIdx: chain1, toChainIdx: chain0, count: 1}, - }, - }) -} - -func TestRMN_TwoMessagesOneSourceChainCursed(t *testing.T) { - runRmnTestCase(t, rmnTestCase{ - name: "two messages, one source chain is cursed the other chain was cursed but curse is revoked", - passIfNoCommitAfter: 15 * time.Second, - cursedSubjectsPerChain: map[int][]int{ - chain1: {chain0}, - }, - revokedCursedSubjectsPerChain: map[int]map[int]time.Duration{ - chain0: {globalCurse: 5 * time.Second}, // chain0 will be globally cursed and curse will be revoked later - }, - homeChainConfig: homeChainConfig{ - f: map[int]int{chain0: 1, chain1: 1}, - }, - remoteChainsConfig: []remoteChainConfig{ - {chainIdx: chain0, f: 1}, - {chainIdx: chain1, f: 1}, - }, - rmnNodes: []rmnNode{ - {id: 0, isSigner: true, observedChainIdxs: []int{chain0, chain1}}, - {id: 1, isSigner: true, observedChainIdxs: []int{chain0, chain1}}, - {id: 2, isSigner: true, observedChainIdxs: []int{chain0, chain1}}, - }, - messagesToSend: []messageToSend{ - {fromChainIdx: chain0, toChainIdx: chain1, count: 1}, // <----- this message should not be committed - {fromChainIdx: chain1, toChainIdx: chain0, count: 1}, - }, - }) -} - -func TestRMN_GlobalCurseTwoMessagesOnTwoLanes(t *testing.T) { - runRmnTestCase(t, rmnTestCase{ - name: "global curse messages on two lanes", - waitForExec: false, - homeChainConfig: homeChainConfig{ - f: map[int]int{chain0: 1, chain1: 1}, - }, - remoteChainsConfig: []remoteChainConfig{ - {chainIdx: chain0, f: 1}, - {chainIdx: chain1, f: 1}, - }, - rmnNodes: []rmnNode{ - {id: 0, isSigner: true, observedChainIdxs: []int{chain0, chain1}}, - {id: 1, isSigner: true, observedChainIdxs: []int{chain0, chain1}}, - {id: 2, isSigner: true, observedChainIdxs: []int{chain0, chain1}}, - }, - messagesToSend: []messageToSend{ - {fromChainIdx: chain0, toChainIdx: chain1, count: 1}, - {fromChainIdx: chain1, toChainIdx: chain0, count: 5}, - }, - cursedSubjectsPerChain: map[int][]int{ - chain1: {globalCurse}, - chain0: {globalCurse}, - }, - passIfNoCommitAfter: 15 * time.Second, - }) -} - -const ( - chain0 = 0 - chain1 = 1 - globalCurse = 1000 -) - -func runRmnTestCase(t *testing.T, tc rmnTestCase) { - require.NoError(t, os.Setenv("ENABLE_RMN", "true")) - require.NoError(t, tc.validate()) - - ctx := testcontext.Get(t) - t.Logf("Running RMN test case: %s", tc.name) - - envWithRMN, rmnCluster := testsetups.NewIntegrationEnvironment(t, - changeset.WithRMNEnabled(len(tc.rmnNodes)), - ) - t.Logf("envWithRmn: %#v", envWithRMN) - - tc.populateFields(t, envWithRMN, rmnCluster) - - onChainState, err := changeset.LoadOnchainState(envWithRMN.Env) - require.NoError(t, err) - t.Logf("onChainState: %#v", onChainState) - - homeChainState, ok := onChainState.Chains[envWithRMN.HomeChainSel] - require.True(t, ok) - - allDigests, err := homeChainState.RMNHome.GetConfigDigests(&bind.CallOpts{Context: ctx}) - require.NoError(t, err) - - t.Logf("RMNHome candidateDigest before setting new candidate: %x, activeDigest: %x", - allDigests.CandidateConfigDigest[:], allDigests.ActiveConfigDigest[:]) - - staticConfig := rmn_home.RMNHomeStaticConfig{Nodes: tc.pf.rmnHomeNodes, OffchainConfig: []byte{}} - dynamicConfig := rmn_home.RMNHomeDynamicConfig{SourceChains: tc.pf.rmnHomeSourceChains, OffchainConfig: []byte{}} - t.Logf("Setting RMNHome candidate with staticConfig: %+v, dynamicConfig: %+v, current candidateDigest: %x", - staticConfig, dynamicConfig, allDigests.CandidateConfigDigest[:]) - - candidateDigest, err := homeChainState.RMNHome.GetCandidateDigest(&bind.CallOpts{Context: ctx}) - require.NoError(t, err) - - _, err = changeset.NewSetRMNHomeCandidateConfigChangeset(envWithRMN.Env, changeset.SetRMNHomeCandidateConfig{ - HomeChainSelector: envWithRMN.HomeChainSel, - RMNStaticConfig: staticConfig, - RMNDynamicConfig: dynamicConfig, - DigestToOverride: candidateDigest, - }) - require.NoError(t, err) - - candidateDigest, err = homeChainState.RMNHome.GetCandidateDigest(&bind.CallOpts{Context: ctx}) - require.NoError(t, err) - - t.Logf("RMNHome candidateDigest after setting new candidate: %x", candidateDigest[:]) - t.Logf("Promoting RMNHome candidate with candidateDigest: %x", candidateDigest[:]) - - _, err = changeset.NewPromoteCandidateConfigChangeset(envWithRMN.Env, changeset.PromoteRMNHomeCandidateConfig{ - HomeChainSelector: envWithRMN.HomeChainSel, - DigestToPromote: candidateDigest, - }) - require.NoError(t, err) - - // check the active digest is the same as the candidate digest - activeDigest, err := homeChainState.RMNHome.GetActiveDigest(&bind.CallOpts{Context: ctx}) - require.NoError(t, err) - require.Equalf(t, candidateDigest, activeDigest, - "active digest should be the same as the previously candidate digest after promotion, previous candidate: %x, active: %x", - candidateDigest[:], activeDigest[:]) - - rmnRemoteConfig := make(map[uint64]changeset.RMNRemoteConfig) - for _, remoteCfg := range tc.remoteChainsConfig { - selector := tc.pf.chainSelectors[remoteCfg.chainIdx] - if remoteCfg.f < 0 { - t.Fatalf("remoteCfg.f is negative: %d", remoteCfg.f) - } - rmnRemoteConfig[selector] = changeset.RMNRemoteConfig{ - F: uint64(remoteCfg.f), - Signers: tc.pf.rmnRemoteSigners, - } - } - - _, err = changeset.NewSetRMNRemoteConfigChangeset(envWithRMN.Env, changeset.SetRMNRemoteConfig{ - HomeChainSelector: envWithRMN.HomeChainSel, - RMNRemoteConfigs: rmnRemoteConfig, - }) - require.NoError(t, err) - - tc.killMarkedRmnNodes(t, rmnCluster) - - changeset.ReplayLogs(t, envWithRMN.Env.Offchain, envWithRMN.ReplayBlocks) - changeset.AddLanesForAll(t, &envWithRMN, onChainState) - disabledNodes := tc.disableOraclesIfThisIsACursingTestCase(ctx, t, envWithRMN) - - startBlocks, seqNumCommit, seqNumExec := tc.sendMessages(t, onChainState, envWithRMN) - t.Logf("Sent all messages, seqNumCommit: %v seqNumExec: %v", seqNumCommit, seqNumExec) - - tc.callContractsToCurseChains(ctx, t, onChainState, envWithRMN) - tc.callContractsToCurseAndRevokeCurse(ctx, t, onChainState, envWithRMN) - - tc.enableOracles(ctx, t, envWithRMN, disabledNodes) - - expectedSeqNum := make(map[changeset.SourceDestPair]uint64) - for k, v := range seqNumCommit { - cursedSubjectsOfDest, exists := tc.pf.cursedSubjectsPerChainSel[k.DestChainSelector] - shouldSkip := exists && (slices.Contains(cursedSubjectsOfDest, globalCurse) || - slices.Contains(cursedSubjectsOfDest, k.SourceChainSelector)) - - if !shouldSkip { - expectedSeqNum[k] = v - } - } - - t.Logf("expectedSeqNums: %v", expectedSeqNum) - t.Logf("expectedSeqNums including cursed chains: %v", seqNumCommit) - - if len(tc.cursedSubjectsPerChain) > 0 && len(seqNumCommit) == len(expectedSeqNum) { - t.Fatalf("test case is wrong: no message was sent to non-cursed chains when you " + - "define curse subjects, your test case should have at least one message not expected to be delivered") - } - - commitReportReceived := make(chan struct{}) - go func() { - if len(expectedSeqNum) > 0 { - changeset.ConfirmCommitForAllWithExpectedSeqNums(t, envWithRMN.Env, onChainState, expectedSeqNum, startBlocks) - commitReportReceived <- struct{}{} - } - - if len(seqNumCommit) > 0 && len(seqNumCommit) > len(expectedSeqNum) { - // wait for a duration and assert that commit reports were not delivered for cursed source chains - changeset.ConfirmCommitForAllWithExpectedSeqNums(t, envWithRMN.Env, onChainState, seqNumCommit, startBlocks) - commitReportReceived <- struct{}{} - } - }() - - if tc.passIfNoCommitAfter > 0 { // wait for a duration and assert that commit reports were not delivered - if len(expectedSeqNum) > 0 && len(seqNumCommit) > len(expectedSeqNum) { - t.Logf("⌛ Waiting for commit reports of non-cursed chains...") - <-commitReportReceived - t.Logf("✅ Commit reports of non-cursed chains received") - } - - tim := time.NewTimer(tc.passIfNoCommitAfter) - t.Logf("waiting for %s before asserting that commit report was not received", tc.passIfNoCommitAfter) - - select { - case <-commitReportReceived: - t.Errorf("Commit report was received while it was not expected") - return - case <-tim.C: - return - } - } - - t.Logf("⌛ Waiting for commit reports...") - <-commitReportReceived // wait for commit reports - t.Logf("✅ Commit report") - - if tc.waitForExec { - t.Logf("⌛ Waiting for exec reports...") - changeset.ConfirmExecWithSeqNrsForAll(t, envWithRMN.Env, onChainState, seqNumExec, startBlocks) - t.Logf("✅ Exec report") - } -} - -func createObserverNodesBitmap(chainSel uint64, rmnNodes []rmnNode, chainSelectors []uint64) *big.Int { - bitmap := new(big.Int) - for _, n := range rmnNodes { - observedChainSelectors := mapset.NewSet[uint64]() - for _, chainIdx := range n.observedChainIdxs { - observedChainSelectors.Add(chainSelectors[chainIdx]) - } - - if !observedChainSelectors.Contains(chainSel) { - continue - } - - bitmap.SetBit(bitmap, n.id, 1) - } - - return bitmap -} - -type homeChainConfig struct { - f map[int]int -} - -type remoteChainConfig struct { - chainIdx int - f int -} - -type rmnNode struct { - id int - isSigner bool - observedChainIdxs []int - forceExit bool // force exit will simply force exit the rmn node to simulate failure scenarios -} - -type messageToSend struct { - fromChainIdx int - toChainIdx int - count int -} - -type rmnTestCase struct { - name string - // If set to 0, the test will wait for commit reports. - // If set to a positive value, the test will wait for that duration and will assert that commit report was not delivered. - passIfNoCommitAfter time.Duration - cursedSubjectsPerChain map[int][]int - // revokedCursedSubjectsPerChain is used to revoke this specific curses after a timer expires - revokedCursedSubjectsPerChain map[int]map[int]time.Duration // chainIdx -> subjectIdx -> timer to revoke - waitForExec bool - homeChainConfig homeChainConfig - remoteChainsConfig []remoteChainConfig - rmnNodes []rmnNode - messagesToSend []messageToSend - - // populated fields after environment setup - pf testCasePopulatedFields -} - -type testCasePopulatedFields struct { - chainSelectors []uint64 - rmnHomeNodes []rmn_home.RMNHomeNode - rmnRemoteSigners []rmn_remote.RMNRemoteSigner - rmnHomeSourceChains []rmn_home.RMNHomeSourceChain - cursedSubjectsPerChainSel map[uint64][]uint64 - revokedCursedSubjectsPerChainSel map[uint64]map[uint64]time.Duration -} - -func (tc *rmnTestCase) populateFields(t *testing.T, envWithRMN changeset.DeployedEnv, rmnCluster devenv.RMNCluster) { - require.GreaterOrEqual(t, len(envWithRMN.Env.Chains), 2, "test assumes at least two chains") - for _, chain := range envWithRMN.Env.Chains { - tc.pf.chainSelectors = append(tc.pf.chainSelectors, chain.Selector) - } - - for _, rmnNodeInfo := range tc.rmnNodes { - rmn := rmnCluster.Nodes["rmn_"+strconv.Itoa(rmnNodeInfo.id)] - - var offchainPublicKey [32]byte - copy(offchainPublicKey[:], rmn.RMN.OffchainPublicKey) - - tc.pf.rmnHomeNodes = append(tc.pf.rmnHomeNodes, rmn_home.RMNHomeNode{ - PeerId: rmn.Proxy.PeerID, - OffchainPublicKey: offchainPublicKey, - }) - - if rmnNodeInfo.isSigner { - if rmnNodeInfo.id < 0 { - t.Fatalf("node id is negative: %d", rmnNodeInfo.id) - } - tc.pf.rmnRemoteSigners = append(tc.pf.rmnRemoteSigners, rmn_remote.RMNRemoteSigner{ - OnchainPublicKey: rmn.RMN.EVMOnchainPublicKey, - NodeIndex: uint64(rmnNodeInfo.id), - }) - } - } - - for remoteChainIdx, remoteF := range tc.homeChainConfig.f { - if remoteF < 0 { - t.Fatalf("negative remote F: %d", remoteF) - } - // configure remote chain details on the home contract - tc.pf.rmnHomeSourceChains = append(tc.pf.rmnHomeSourceChains, rmn_home.RMNHomeSourceChain{ - ChainSelector: tc.pf.chainSelectors[remoteChainIdx], - F: uint64(remoteF), - ObserverNodesBitmap: createObserverNodesBitmap(tc.pf.chainSelectors[remoteChainIdx], tc.rmnNodes, tc.pf.chainSelectors), - }) - } - - // populate cursed subjects with actual chain selectors - tc.pf.cursedSubjectsPerChainSel = make(map[uint64][]uint64) - for chainIdx, subjects := range tc.cursedSubjectsPerChain { - chainSel := tc.pf.chainSelectors[chainIdx] - for _, subject := range subjects { - subjSel := uint64(globalCurse) - if subject != globalCurse { - subjSel = tc.pf.chainSelectors[subject] - } - tc.pf.cursedSubjectsPerChainSel[chainSel] = append(tc.pf.cursedSubjectsPerChainSel[chainSel], subjSel) - } - } - - // populate revoked cursed subjects with actual chain selectors - tc.pf.revokedCursedSubjectsPerChainSel = make(map[uint64]map[uint64]time.Duration) - for chainIdx, subjects := range tc.revokedCursedSubjectsPerChain { - chainSel := tc.pf.chainSelectors[chainIdx] - for subject, revokeAfter := range subjects { - subjSel := uint64(globalCurse) - if subject != globalCurse { - subjSel = tc.pf.chainSelectors[subject] - } - if _, ok := tc.pf.revokedCursedSubjectsPerChainSel[chainSel]; !ok { - tc.pf.revokedCursedSubjectsPerChainSel[chainSel] = make(map[uint64]time.Duration) - } - tc.pf.revokedCursedSubjectsPerChainSel[chainSel][subjSel] = revokeAfter - } - } -} - -func (tc rmnTestCase) validate() error { - if len(tc.cursedSubjectsPerChain) > 0 && tc.passIfNoCommitAfter == 0 { - return errors.New("when you define cursed subjects you also need to define the duration that the " + - "test will wait for non-transmitted roots") - } - return nil -} - -func (tc rmnTestCase) killMarkedRmnNodes(t *testing.T, rmnCluster devenv.RMNCluster) { - for _, n := range tc.rmnNodes { - if n.forceExit { - t.Logf("Pausing RMN node %d", n.id) - rmnN := rmnCluster.Nodes["rmn_"+strconv.Itoa(n.id)] - require.NoError(t, osutil.ExecCmd(zerolog.Nop(), "docker kill "+rmnN.Proxy.ContainerName)) - t.Logf("Paused RMN node %d", n.id) - } - } -} - -func (tc rmnTestCase) disableOraclesIfThisIsACursingTestCase(ctx context.Context, t *testing.T, envWithRMN changeset.DeployedEnv) []string { - disabledNodes := make([]string, 0) - - if len(tc.cursedSubjectsPerChain) > 0 { - listNodesResp, err := envWithRMN.Env.Offchain.ListNodes(ctx, &node.ListNodesRequest{}) - require.NoError(t, err) - - for _, n := range listNodesResp.Nodes { - if strings.HasPrefix(n.Name, "bootstrap") { - continue - } - _, err := envWithRMN.Env.Offchain.DisableNode(ctx, &node.DisableNodeRequest{Id: n.Id}) - require.NoError(t, err) - disabledNodes = append(disabledNodes, n.Id) - t.Logf("node %s disabled", n.Id) - } - } - - return disabledNodes -} - -func (tc rmnTestCase) sendMessages(t *testing.T, onChainState changeset.CCIPOnChainState, envWithRMN changeset.DeployedEnv) (map[uint64]*uint64, map[changeset.SourceDestPair]uint64, map[changeset.SourceDestPair][]uint64) { - startBlocks := make(map[uint64]*uint64) - seqNumCommit := make(map[changeset.SourceDestPair]uint64) - seqNumExec := make(map[changeset.SourceDestPair][]uint64) - - for _, msg := range tc.messagesToSend { - fromChain := tc.pf.chainSelectors[msg.fromChainIdx] - toChain := tc.pf.chainSelectors[msg.toChainIdx] - - for i := 0; i < msg.count; i++ { - msgSentEvent := changeset.TestSendRequest(t, envWithRMN.Env, onChainState, fromChain, toChain, false, router.ClientEVM2AnyMessage{ - Receiver: common.LeftPadBytes(onChainState.Chains[toChain].Receiver.Address().Bytes(), 32), - Data: []byte("hello world"), - TokenAmounts: nil, - FeeToken: common.HexToAddress("0x0"), - ExtraArgs: nil, - }) - seqNumCommit[changeset.SourceDestPair{ - SourceChainSelector: fromChain, - DestChainSelector: toChain, - }] = msgSentEvent.SequenceNumber - seqNumExec[changeset.SourceDestPair{ - SourceChainSelector: fromChain, - DestChainSelector: toChain, - }] = []uint64{msgSentEvent.SequenceNumber} - t.Logf("Sent message from chain %d to chain %d with seqNum %d", fromChain, toChain, msgSentEvent.SequenceNumber) - } - - zero := uint64(0) - startBlocks[toChain] = &zero - } - - return startBlocks, seqNumCommit, seqNumExec -} - -func (tc rmnTestCase) callContractsToCurseChains(ctx context.Context, t *testing.T, onChainState changeset.CCIPOnChainState, envWithRMN changeset.DeployedEnv) { - for _, remoteCfg := range tc.remoteChainsConfig { - remoteSel := tc.pf.chainSelectors[remoteCfg.chainIdx] - chState, ok := onChainState.Chains[remoteSel] - require.True(t, ok) - chain, ok := envWithRMN.Env.Chains[remoteSel] - require.True(t, ok) - - cursedSubjects, ok := tc.cursedSubjectsPerChain[remoteCfg.chainIdx] - if !ok { - continue // nothing to curse on this chain - } - - for _, subjectDescription := range cursedSubjects { - subj := reader.GlobalCurseSubject - if subjectDescription != globalCurse { - subj = chainSelectorToBytes16(tc.pf.chainSelectors[subjectDescription]) - } - t.Logf("cursing subject %d (%d)", subj, subjectDescription) - txCurse, errCurse := chState.RMNRemote.Curse(chain.DeployerKey, subj) - _, errConfirm := deployment.ConfirmIfNoError(chain, txCurse, errCurse) - require.NoError(t, errConfirm) - } - - cs, err := chState.RMNRemote.GetCursedSubjects(&bind.CallOpts{Context: ctx}) - require.NoError(t, err) - t.Logf("Cursed subjects: %v", cs) - } -} - -func (tc rmnTestCase) callContractsToCurseAndRevokeCurse(ctx context.Context, t *testing.T, onChainState changeset.CCIPOnChainState, envWithRMN changeset.DeployedEnv) { - for _, remoteCfg := range tc.remoteChainsConfig { - remoteSel := tc.pf.chainSelectors[remoteCfg.chainIdx] - chState, ok := onChainState.Chains[remoteSel] - require.True(t, ok) - chain, ok := envWithRMN.Env.Chains[remoteSel] - require.True(t, ok) - - cursedSubjects, ok := tc.revokedCursedSubjectsPerChain[remoteCfg.chainIdx] - if !ok { - continue // nothing to curse on this chain - } - - for subjectDescription, revokeAfter := range cursedSubjects { - subj := reader.GlobalCurseSubject - if subjectDescription != globalCurse { - subj = chainSelectorToBytes16(tc.pf.chainSelectors[subjectDescription]) - } - t.Logf("cursing subject %d (%d)", subj, subjectDescription) - txCurse, errCurse := chState.RMNRemote.Curse(chain.DeployerKey, subj) - _, errConfirm := deployment.ConfirmIfNoError(chain, txCurse, errCurse) - require.NoError(t, errConfirm) - - go func() { - <-time.NewTimer(revokeAfter).C - t.Logf("revoking curse on subject %d (%d)", subj, subjectDescription) - txUncurse, errUncurse := chState.RMNRemote.Uncurse(chain.DeployerKey, subj) - _, errConfirm = deployment.ConfirmIfNoError(chain, txUncurse, errUncurse) - require.NoError(t, errConfirm) - }() - } - - cs, err := chState.RMNRemote.GetCursedSubjects(&bind.CallOpts{Context: ctx}) - require.NoError(t, err) - t.Logf("Cursed subjects: %v", cs) - } -} - -func (tc rmnTestCase) enableOracles(ctx context.Context, t *testing.T, envWithRMN changeset.DeployedEnv, nodeIDs []string) { - for _, n := range nodeIDs { - _, err := envWithRMN.Env.Offchain.EnableNode(ctx, &node.EnableNodeRequest{Id: n}) - require.NoError(t, err) - t.Logf("node %s enabled", n) - } -} - -func chainSelectorToBytes16(chainSel uint64) [16]byte { - var result [16]byte - // Convert the uint64 to bytes and place it in the last 8 bytes of the array - binary.BigEndian.PutUint64(result[8:], chainSel) - return result -} diff --git a/integration-tests/smoke/ccip/ccip_token_price_updates_test.go b/integration-tests/smoke/ccip/ccip_token_price_updates_test.go deleted file mode 100644 index fb7ddc847d4..00000000000 --- a/integration-tests/smoke/ccip/ccip_token_price_updates_test.go +++ /dev/null @@ -1,150 +0,0 @@ -package smoke - -import ( - "context" - "math" - "math/big" - "strings" - "testing" - "time" - - "github.com/ethereum/go-ethereum/accounts/abi/bind" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - "golang.org/x/exp/maps" - - "github.com/smartcontractkit/chainlink-common/pkg/config" - "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" - "github.com/smartcontractkit/chainlink-protos/job-distributor/v1/node" - - "github.com/smartcontractkit/chainlink/deployment" - "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" - testsetups "github.com/smartcontractkit/chainlink/integration-tests/testsetups/ccip" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/fee_quoter" -) - -func Test_CCIPTokenPriceUpdates(t *testing.T) { - ctx := changeset.Context(t) - callOpts := &bind.CallOpts{Context: ctx} - - var tokenPriceExpiry = 5 * time.Second - e, _ := testsetups.NewIntegrationEnvironment(t, - changeset.WithOCRConfigOverride(func(params changeset.CCIPOCRParams) changeset.CCIPOCRParams { - params.CommitOffChainConfig.TokenPriceBatchWriteFrequency = *config.MustNewDuration(tokenPriceExpiry) - return params - })) - state, err := changeset.LoadOnchainState(e.Env) - require.NoError(t, err) - changeset.AddLanesForAll(t, &e, state) - - allChainSelectors := maps.Keys(e.Env.Chains) - assert.GreaterOrEqual(t, len(allChainSelectors), 2, "test requires at least 2 chains") - - sourceChain1 := allChainSelectors[0] - - feeQuoter1 := state.Chains[sourceChain1].FeeQuoter - - feeTokensChain1, err := feeQuoter1.GetFeeTokens(callOpts) - require.NoError(t, err) - t.Logf("feeTokens: %v", feeTokensChain1) - - tokenPricesBefore, err := feeQuoter1.GetTokenPrices(callOpts, feeTokensChain1) - require.NoError(t, err) - t.Logf("tokenPrices: %v", tokenPricesBefore) - - // assert token prices updated due to time expiration - assert.Eventually(t, func() bool { - tokenPricesNow, err := feeQuoter1.GetTokenPrices(callOpts, feeTokensChain1) - require.NoError(t, err) - t.Logf("tokenPrices: %v", tokenPricesNow) - - // both tokens should have same price but different timestamp since there was an update due to time deviation - for i, price := range tokenPricesNow { - if tokenPricesBefore[i].Timestamp == price.Timestamp { - tokenPricesBefore = tokenPricesNow - return false // timestamp is the same - } - if tokenPricesBefore[i].Value.Cmp(price.Value) != 0 { - tokenPricesBefore = tokenPricesNow - return false // price was updated - } - } - t.Log("time expiration assertions complete") - return true - }, tests.WaitTimeout(t), 500*time.Millisecond) - - // disable oracles to prevent price updates while we manually edit token prices - disabledOracleIDs := disableOracles(ctx, t, e.Env.Offchain) - - assert.Eventually(t, func() bool { - // manually update token prices by setting values to maxUint64 and 0 - tx, err := feeQuoter1.UpdatePrices(e.Env.Chains[sourceChain1].DeployerKey, fee_quoter.InternalPriceUpdates{ - TokenPriceUpdates: []fee_quoter.InternalTokenPriceUpdate{ - {SourceToken: feeTokensChain1[0], UsdPerToken: big.NewInt(0).SetUint64(math.MaxUint64)}, - {SourceToken: feeTokensChain1[1], UsdPerToken: big.NewInt(0)}, - }, - }) - require.NoError(t, err) - - _, err = deployment.ConfirmIfNoError(e.Env.Chains[sourceChain1], tx, err) - require.NoError(t, err) - t.Logf("manually editing token prices") - - tokenPricesNow, err := feeQuoter1.GetTokenPrices(callOpts, feeTokensChain1) - require.NoError(t, err) - t.Logf("tokenPrices straight after: %v", tokenPricesNow) - - if uint64(math.MaxUint64) != tokenPricesNow[0].Value.Uint64() { - return false - } - if uint64(0) != tokenPricesNow[1].Value.Uint64() { - return false - } - return true - - // retry because there might've been a commit report inflight - }, tests.WaitTimeout(t), 200*time.Millisecond) - - enableOracles(ctx, t, e.Env.Offchain, disabledOracleIDs) - - // wait until price goes back to the original - assert.Eventually(t, func() bool { - tokenPricesNow, err := feeQuoter1.GetTokenPrices(callOpts, feeTokensChain1) - require.NoError(t, err) - t.Logf("tokenPrices: %v tokenPricesBefore: %v", tokenPricesNow, tokenPricesBefore) - - if tokenPricesNow[0].Value.Cmp(tokenPricesBefore[0].Value) != 0 { - return false - } - if tokenPricesNow[1].Value.Cmp(tokenPricesBefore[1].Value) != 0 { - return false - } - return true - }, tests.WaitTimeout(t), 500*time.Millisecond) -} - -func disableOracles(ctx context.Context, t *testing.T, client deployment.OffchainClient) []string { - var disabledOracleIDs []string - listNodesResp, err := client.ListNodes(ctx, &node.ListNodesRequest{}) - require.NoError(t, err) - - for _, n := range listNodesResp.Nodes { - if strings.HasPrefix(n.Name, "bootstrap") { - continue - } - _, err := client.DisableNode(ctx, &node.DisableNodeRequest{Id: n.Id}) - require.NoError(t, err) - disabledOracleIDs = append(disabledOracleIDs, n.Id) - t.Logf("node %s disabled", n.Id) - } - - return disabledOracleIDs -} - -func enableOracles(ctx context.Context, t *testing.T, client deployment.OffchainClient, oracleIDs []string) { - for _, n := range oracleIDs { - _, err := client.EnableNode(ctx, &node.EnableNodeRequest{Id: n}) - require.NoError(t, err) - t.Logf("node %s enabled", n) - } -} diff --git a/integration-tests/smoke/ccip/ccip_token_transfer_test.go b/integration-tests/smoke/ccip/ccip_token_transfer_test.go deleted file mode 100644 index c5cabfe63e4..00000000000 --- a/integration-tests/smoke/ccip/ccip_token_transfer_test.go +++ /dev/null @@ -1,219 +0,0 @@ -package smoke - -import ( - "math/big" - "testing" - - "golang.org/x/exp/maps" - - "github.com/ethereum/go-ethereum/common" - "github.com/stretchr/testify/require" - - "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" - - "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" - testsetups "github.com/smartcontractkit/chainlink/integration-tests/testsetups/ccip" - "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/router" - "github.com/smartcontractkit/chainlink/v2/core/logger" -) - -func TestTokenTransfer(t *testing.T) { - lggr := logger.TestLogger(t) - ctx := tests.Context(t) - - tenv, _ := testsetups.NewIntegrationEnvironment(t, - changeset.WithUsersPerChain(3)) - - e := tenv.Env - state, err := changeset.LoadOnchainState(e) - require.NoError(t, err) - require.GreaterOrEqual(t, len(e.Chains), 2) - - allChainSelectors := maps.Keys(e.Chains) - sourceChain, destChain := allChainSelectors[0], allChainSelectors[1] - ownerSourceChain := e.Chains[sourceChain].DeployerKey - ownerDestChain := e.Chains[destChain].DeployerKey - - require.GreaterOrEqual(t, len(tenv.Users[sourceChain]), 2) - require.GreaterOrEqual(t, len(tenv.Users[destChain]), 2) - selfServeSrcTokenPoolDeployer := tenv.Users[sourceChain][1] - selfServeDestTokenPoolDeployer := tenv.Users[destChain][1] - - oneE18 := new(big.Int).SetUint64(1e18) - - // Deploy tokens and pool by CCIP Owner - srcToken, _, destToken, _, err := changeset.DeployTransferableToken( - lggr, - tenv.Env.Chains, - sourceChain, - destChain, - ownerSourceChain, - ownerDestChain, - state, - e.ExistingAddresses, - "OWNER_TOKEN", - ) - require.NoError(t, err) - - // Deploy Self Serve tokens and pool - selfServeSrcToken, _, selfServeDestToken, _, err := changeset.DeployTransferableToken( - lggr, - tenv.Env.Chains, - sourceChain, - destChain, - selfServeSrcTokenPoolDeployer, - selfServeDestTokenPoolDeployer, - state, - e.ExistingAddresses, - "SELF_SERVE_TOKEN", - ) - require.NoError(t, err) - changeset.AddLanesForAll(t, &tenv, state) - - changeset.MintAndAllow( - t, - e, - state, - map[uint64][]changeset.MintTokenInfo{ - sourceChain: { - changeset.NewMintTokenInfo(selfServeSrcTokenPoolDeployer, selfServeSrcToken), - changeset.NewMintTokenInfo(ownerSourceChain, srcToken), - }, - destChain: { - changeset.NewMintTokenInfo(selfServeDestTokenPoolDeployer, selfServeDestToken), - changeset.NewMintTokenInfo(ownerDestChain, destToken), - }, - }, - ) - - tcs := []changeset.TestTransferRequest{ - { - Name: "Send token to EOA", - SourceChain: sourceChain, - DestChain: destChain, - Tokens: []router.ClientEVMTokenAmount{ - { - Token: srcToken.Address(), - Amount: oneE18, - }, - }, - Receiver: utils.RandomAddress(), - ExpectedTokenBalances: map[common.Address]*big.Int{ - destToken.Address(): oneE18, - }, - ExpectedStatus: changeset.EXECUTION_STATE_SUCCESS, - }, - { - Name: "Send token to contract", - SourceChain: sourceChain, - DestChain: destChain, - Tokens: []router.ClientEVMTokenAmount{ - { - Token: srcToken.Address(), - Amount: oneE18, - }, - }, - Receiver: state.Chains[destChain].Receiver.Address(), - ExpectedTokenBalances: map[common.Address]*big.Int{ - destToken.Address(): oneE18, - }, - ExpectedStatus: changeset.EXECUTION_STATE_SUCCESS, - }, - { - Name: "Send N tokens to contract", - SourceChain: destChain, - DestChain: sourceChain, - Tokens: []router.ClientEVMTokenAmount{ - { - Token: selfServeDestToken.Address(), - Amount: oneE18, - }, - { - Token: destToken.Address(), - Amount: oneE18, - }, - { - Token: selfServeDestToken.Address(), - Amount: oneE18, - }, - }, - Receiver: state.Chains[sourceChain].Receiver.Address(), - ExtraArgs: changeset.MakeEVMExtraArgsV2(300_000, false), - ExpectedTokenBalances: map[common.Address]*big.Int{ - selfServeSrcToken.Address(): new(big.Int).Add(oneE18, oneE18), - srcToken.Address(): oneE18, - }, - ExpectedStatus: changeset.EXECUTION_STATE_SUCCESS, - }, - { - Name: "Sending token transfer with custom gasLimits to the EOA is successful", - SourceChain: destChain, - DestChain: sourceChain, - Tokens: []router.ClientEVMTokenAmount{ - { - Token: selfServeDestToken.Address(), - Amount: oneE18, - }, - { - Token: destToken.Address(), - Amount: new(big.Int).Add(oneE18, oneE18), - }, - }, - Receiver: utils.RandomAddress(), - ExtraArgs: changeset.MakeEVMExtraArgsV2(1, false), - ExpectedTokenBalances: map[common.Address]*big.Int{ - selfServeSrcToken.Address(): oneE18, - srcToken.Address(): new(big.Int).Add(oneE18, oneE18), - }, - ExpectedStatus: changeset.EXECUTION_STATE_SUCCESS, - }, - { - Name: "Sending PTT with too low gas limit leads to the revert when receiver is a contract", - SourceChain: destChain, - DestChain: sourceChain, - Tokens: []router.ClientEVMTokenAmount{ - { - Token: selfServeDestToken.Address(), - Amount: oneE18, - }, - { - Token: destToken.Address(), - Amount: oneE18, - }, - }, - Receiver: state.Chains[sourceChain].Receiver.Address(), - Data: []byte("this should be reverted because gasLimit is too low, no tokens are transferred as well"), - ExtraArgs: changeset.MakeEVMExtraArgsV2(1, false), - ExpectedTokenBalances: map[common.Address]*big.Int{ - selfServeSrcToken.Address(): big.NewInt(0), - srcToken.Address(): big.NewInt(0), - }, - ExpectedStatus: changeset.EXECUTION_STATE_FAILURE, - }, - } - - startBlocks, expectedSeqNums, expectedExecutionStates, expectedTokenBalances := - changeset.TransferMultiple(ctx, t, e, state, tcs) - - err = changeset.ConfirmMultipleCommits( - t, - e.Chains, - state.Chains, - startBlocks, - false, - expectedSeqNums, - ) - require.NoError(t, err) - - execStates := changeset.ConfirmExecWithSeqNrsForAll( - t, - e, - state, - changeset.SeqNumberRangeToSlice(expectedSeqNums), - startBlocks, - ) - require.Equal(t, expectedExecutionStates, execStates) - - changeset.WaitForTokenBalances(ctx, t, e.Chains, expectedTokenBalances) -} diff --git a/integration-tests/smoke/ccip/ccip_usdc_test.go b/integration-tests/smoke/ccip/ccip_usdc_test.go deleted file mode 100644 index 7bea68a9cbf..00000000000 --- a/integration-tests/smoke/ccip/ccip_usdc_test.go +++ /dev/null @@ -1,258 +0,0 @@ -package smoke - -import ( - "math/big" - "testing" - - "github.com/ethereum/go-ethereum/common" - "github.com/stretchr/testify/require" - - "golang.org/x/exp/maps" - "golang.org/x/sync/errgroup" - - "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" - - "github.com/smartcontractkit/chainlink/deployment" - "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" - testsetups "github.com/smartcontractkit/chainlink/integration-tests/testsetups/ccip" - "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/router" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/shared/generated/burn_mint_erc677" - "github.com/smartcontractkit/chainlink/v2/core/logger" -) - -/* -* Chain topology for this test -* chainA (USDC, MY_TOKEN) -* | -* | ------- chainC (USDC, MY_TOKEN) -* | -* chainB (USDC) - */ -func TestUSDCTokenTransfer(t *testing.T) { - lggr := logger.TestLogger(t) - ctx := tests.Context(t) - tenv, _ := testsetups.NewIntegrationEnvironment(t, - changeset.WithUsersPerChain(3), - changeset.WithChains(3), - changeset.WithUSDC(), - ) - - e := tenv.Env - state, err := changeset.LoadOnchainState(e) - require.NoError(t, err) - - allChainSelectors := maps.Keys(e.Chains) - chainA := allChainSelectors[0] - chainC := allChainSelectors[1] - chainB := allChainSelectors[2] - - ownerChainA := e.Chains[chainA].DeployerKey - ownerChainC := e.Chains[chainC].DeployerKey - ownerChainB := e.Chains[chainB].DeployerKey - - aChainUSDC, cChainUSDC, err := changeset.ConfigureUSDCTokenPools(lggr, e.Chains, chainA, chainC, state) - require.NoError(t, err) - - bChainUSDC, _, err := changeset.ConfigureUSDCTokenPools(lggr, e.Chains, chainB, chainC, state) - require.NoError(t, err) - - aChainToken, _, cChainToken, _, err := changeset.DeployTransferableToken( - lggr, - tenv.Env.Chains, - chainA, - chainC, - ownerChainA, - ownerChainC, - state, - e.ExistingAddresses, - "MY_TOKEN", - ) - require.NoError(t, err) - - // Add all lanes - changeset.AddLanesForAll(t, &tenv, state) - - changeset.MintAndAllow( - t, - e, - state, - map[uint64][]changeset.MintTokenInfo{ - chainA: { - changeset.NewMintTokenInfo(ownerChainA, aChainUSDC, aChainToken), - }, - chainB: { - changeset.NewMintTokenInfo(ownerChainB, bChainUSDC), - }, - chainC: { - changeset.NewMintTokenInfo(ownerChainC, cChainUSDC, cChainToken), - }, - }, - ) - - err = updateFeeQuoters(lggr, e, state, chainA, chainB, chainC, aChainUSDC, bChainUSDC, cChainUSDC) - require.NoError(t, err) - - // MockE2EUSDCTransmitter always mint 1, see MockE2EUSDCTransmitter.sol for more details - tinyOneCoin := new(big.Int).SetUint64(1) - - tcs := []changeset.TestTransferRequest{ - { - Name: "single USDC token transfer to EOA", - Receiver: utils.RandomAddress(), - SourceChain: chainC, - DestChain: chainA, - Tokens: []router.ClientEVMTokenAmount{ - { - Token: cChainUSDC.Address(), - Amount: tinyOneCoin, - }}, - ExpectedTokenBalances: map[common.Address]*big.Int{ - aChainUSDC.Address(): tinyOneCoin, - }, - ExpectedStatus: changeset.EXECUTION_STATE_SUCCESS, - }, - { - Name: "multiple USDC tokens within the same message", - Receiver: utils.RandomAddress(), - SourceChain: chainC, - DestChain: chainA, - Tokens: []router.ClientEVMTokenAmount{ - { - Token: cChainUSDC.Address(), - Amount: tinyOneCoin, - }, - { - Token: cChainUSDC.Address(), - Amount: tinyOneCoin, - }, - }, - ExpectedTokenBalances: map[common.Address]*big.Int{ - // 2 coins because of the same Receiver - aChainUSDC.Address(): new(big.Int).Add(tinyOneCoin, tinyOneCoin), - }, - ExpectedStatus: changeset.EXECUTION_STATE_SUCCESS, - }, - { - Name: "USDC token together with another token transferred to EOA", - Receiver: utils.RandomAddress(), - SourceChain: chainA, - DestChain: chainC, - Tokens: []router.ClientEVMTokenAmount{ - { - Token: aChainUSDC.Address(), - Amount: tinyOneCoin, - }, - { - Token: aChainToken.Address(), - Amount: new(big.Int).Mul(tinyOneCoin, big.NewInt(10)), - }, - }, - ExpectedTokenBalances: map[common.Address]*big.Int{ - cChainUSDC.Address(): tinyOneCoin, - cChainToken.Address(): new(big.Int).Mul(tinyOneCoin, big.NewInt(10)), - }, - ExpectedStatus: changeset.EXECUTION_STATE_SUCCESS, - }, - { - Name: "USDC programmable token transfer to valid contract receiver", - Receiver: state.Chains[chainC].Receiver.Address(), - SourceChain: chainA, - DestChain: chainC, - Tokens: []router.ClientEVMTokenAmount{ - { - Token: aChainUSDC.Address(), - Amount: tinyOneCoin, - }, - }, - Data: []byte("hello world"), - ExpectedTokenBalances: map[common.Address]*big.Int{ - cChainUSDC.Address(): tinyOneCoin, - }, - ExpectedStatus: changeset.EXECUTION_STATE_SUCCESS, - }, - { - Name: "USDC programmable token transfer with too little gas", - Receiver: state.Chains[chainB].Receiver.Address(), - SourceChain: chainC, - DestChain: chainB, - Tokens: []router.ClientEVMTokenAmount{ - { - Token: cChainUSDC.Address(), - Amount: tinyOneCoin, - }, - }, - Data: []byte("gimme more gas to execute that!"), - ExpectedTokenBalances: map[common.Address]*big.Int{ - bChainUSDC.Address(): new(big.Int).SetUint64(0), - }, - ExtraArgs: changeset.MakeEVMExtraArgsV2(1, false), - ExpectedStatus: changeset.EXECUTION_STATE_FAILURE, - }, - { - Name: "USDC token transfer from a different source chain", - Receiver: utils.RandomAddress(), - SourceChain: chainB, - DestChain: chainC, - Tokens: []router.ClientEVMTokenAmount{ - { - Token: bChainUSDC.Address(), - Amount: tinyOneCoin, - }, - }, - Data: nil, - ExpectedTokenBalances: map[common.Address]*big.Int{ - cChainUSDC.Address(): tinyOneCoin, - }, - ExpectedStatus: changeset.EXECUTION_STATE_SUCCESS, - }, - } - - startBlocks, expectedSeqNums, expectedExecutionStates, expectedTokenBalances := - changeset.TransferMultiple(ctx, t, e, state, tcs) - - err = changeset.ConfirmMultipleCommits( - t, - e.Chains, - state.Chains, - startBlocks, - false, - expectedSeqNums, - ) - require.NoError(t, err) - - execStates := changeset.ConfirmExecWithSeqNrsForAll( - t, - e, - state, - changeset.SeqNumberRangeToSlice(expectedSeqNums), - startBlocks, - ) - require.Equal(t, expectedExecutionStates, execStates) - - changeset.WaitForTokenBalances(ctx, t, e.Chains, expectedTokenBalances) -} - -func updateFeeQuoters( - lggr logger.Logger, - e deployment.Environment, - state changeset.CCIPOnChainState, - chainA, chainB, chainC uint64, - aChainUSDC, bChainUSDC, cChainUSDC *burn_mint_erc677.BurnMintERC677, -) error { - updateFeeQtrGrp := errgroup.Group{} - updateFeeQtrGrp.Go(func() error { - return changeset.UpdateFeeQuoterForUSDC(lggr, e.Chains[chainA], state.Chains[chainA], chainC, aChainUSDC) - }) - updateFeeQtrGrp.Go(func() error { - return changeset.UpdateFeeQuoterForUSDC(lggr, e.Chains[chainB], state.Chains[chainB], chainC, bChainUSDC) - }) - updateFeeQtrGrp.Go(func() error { - err1 := changeset.UpdateFeeQuoterForUSDC(lggr, e.Chains[chainC], state.Chains[chainC], chainA, cChainUSDC) - if err1 != nil { - return err1 - } - return changeset.UpdateFeeQuoterForUSDC(lggr, e.Chains[chainC], state.Chains[chainC], chainB, cChainUSDC) - }) - return updateFeeQtrGrp.Wait() -} diff --git a/integration-tests/smoke/ccip/ccip_messaging_test.go b/integration-tests/smoke/ccip_messaging_test.go similarity index 74% rename from integration-tests/smoke/ccip/ccip_messaging_test.go rename to integration-tests/smoke/ccip_messaging_test.go index 8ee18a31918..4aa9ba34229 100644 --- a/integration-tests/smoke/ccip/ccip_messaging_test.go +++ b/integration-tests/smoke/ccip_messaging_test.go @@ -15,20 +15,23 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/hashutil" "github.com/smartcontractkit/chainlink-common/pkg/merklemulti" "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" + jobv1 "github.com/smartcontractkit/chainlink-protos/job-distributor/v1/job" "github.com/smartcontractkit/chainlink/deployment" + ccdeploy "github.com/smartcontractkit/chainlink/deployment/ccip" "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" - testsetups "github.com/smartcontractkit/chainlink/integration-tests/testsetups/ccip" + "github.com/smartcontractkit/chainlink/integration-tests/ccip-tests/testsetups" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/offramp" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/onramp" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/router" + "github.com/smartcontractkit/chainlink/v2/core/logger" ) type testCaseSetup struct { t *testing.T sender []byte - deployedEnv changeset.DeployedEnv - onchainState changeset.CCIPOnChainState + deployedEnv ccdeploy.DeployedEnv + onchainState ccdeploy.CCIPOnChainState sourceChain, destChain uint64 } @@ -46,10 +49,11 @@ type messagingTestCaseOutput struct { func Test_CCIPMessaging(t *testing.T) { // Setup 2 chains and a single lane. - ctx := changeset.Context(t) - e, _ := testsetups.NewIntegrationEnvironment(t) + lggr := logger.TestLogger(t) + ctx := ccdeploy.Context(t) + e, _, _ := testsetups.NewLocalDevEnvironmentWithDefaultPrice(t, lggr) - state, err := changeset.LoadOnchainState(e.Env) + state, err := ccdeploy.LoadOnchainState(e.Env) require.NoError(t, err) allChainSelectors := maps.Keys(e.Env.Chains) @@ -62,8 +66,46 @@ func Test_CCIPMessaging(t *testing.T) { ", source chain selector:", sourceChain, ", dest chain selector:", destChain, ) + output, err := changeset.DeployPrerequisites(e.Env, changeset.DeployPrerequisiteConfig{ + ChainSelectors: e.Env.AllChainSelectors(), + }) + require.NoError(t, err) + require.NoError(t, e.Env.ExistingAddresses.Merge(output.AddressBook)) + + tokenConfig := ccdeploy.NewTestTokenConfig(state.Chains[e.FeedChainSel].USDFeeds) + // Apply migration + output, err = changeset.InitialDeploy(e.Env, ccdeploy.DeployCCIPContractConfig{ + HomeChainSel: e.HomeChainSel, + FeedChainSel: e.FeedChainSel, + ChainsToDeploy: allChainSelectors, + TokenConfig: tokenConfig, + MCMSConfig: ccdeploy.NewTestMCMSConfig(t, e.Env), + OCRSecrets: deployment.XXXGenerateTestOCRSecrets(), + }) + require.NoError(t, err) + require.NoError(t, e.Env.ExistingAddresses.Merge(output.AddressBook)) + // Get new state after migration. + state, err = ccdeploy.LoadOnchainState(e.Env) + require.NoError(t, err) + + // Ensure capreg logs are up to date. + ccdeploy.ReplayLogs(t, e.Env.Offchain, e.ReplayBlocks) + + // Apply the jobs. + for nodeID, jobs := range output.JobSpecs { + for _, job := range jobs { + // Note these auto-accept + _, err := e.Env.Offchain.ProposeJob(ctx, + &jobv1.ProposeJobRequest{ + NodeId: nodeID, + Spec: job, + }) + require.NoError(t, err) + } + } + // connect a single lane, source to dest - changeset.AddLaneWithDefaultPricesAndFeeQuoterConfig(t, &e, state, sourceChain, destChain, false) + require.NoError(t, ccdeploy.AddLaneWithDefaultPrices(e.Env, state, sourceChain, destChain)) var ( replayed bool @@ -88,8 +130,8 @@ func Test_CCIPMessaging(t *testing.T) { }, common.HexToAddress("0xdead"), []byte("hello eoa"), - nil, // default extraArgs - changeset.EXECUTION_STATE_SUCCESS, // success because offRamp won't call an EOA + nil, // default extraArgs + ccdeploy.EXECUTION_STATE_SUCCESS, // success because offRamp won't call an EOA ) }) @@ -102,8 +144,8 @@ func Test_CCIPMessaging(t *testing.T) { }, state.Chains[destChain].FeeQuoter.Address(), []byte("hello FeeQuoter"), - nil, // default extraArgs - changeset.EXECUTION_STATE_SUCCESS, // success because offRamp won't call a contract not implementing CCIPReceiver + nil, // default extraArgs + ccdeploy.EXECUTION_STATE_SUCCESS, // success because offRamp won't call a contract not implementing CCIPReceiver ) }) @@ -119,7 +161,7 @@ func Test_CCIPMessaging(t *testing.T) { state.Chains[destChain].Receiver.Address(), []byte("hello CCIPReceiver"), nil, // default extraArgs - changeset.EXECUTION_STATE_SUCCESS, + ccdeploy.EXECUTION_STATE_SUCCESS, func(t *testing.T) { iter, err := state.Chains[destChain].Receiver.FilterMessageReceived(&bind.FilterOpts{ Context: ctx, @@ -143,8 +185,8 @@ func Test_CCIPMessaging(t *testing.T) { }, state.Chains[destChain].Receiver.Address(), []byte("hello CCIPReceiver with low exec gas"), - changeset.MakeEVMExtraArgsV2(1, false), // 1 gas is too low. - changeset.EXECUTION_STATE_FAILURE, // state would be failed onchain due to low gas + ccdeploy.MakeEVMExtraArgsV2(1, false), // 1 gas is too low. + ccdeploy.EXECUTION_STATE_FAILURE, // state would be failed onchain due to low gas ) manuallyExecute(ctx, t, latestHead.Number.Uint64(), state, destChain, out, sourceChain, e, sender) @@ -158,11 +200,11 @@ func manuallyExecute( ctx context.Context, t *testing.T, startBlock uint64, - state changeset.CCIPOnChainState, + state ccdeploy.CCIPOnChainState, destChain uint64, out messagingTestCaseOutput, sourceChain uint64, - e changeset.DeployedEnv, + e ccdeploy.DeployedEnv, sender []byte, ) { merkleRoot := getMerkleRoot( @@ -229,7 +271,7 @@ func manuallyExecute( newExecutionState, err := state.Chains[destChain].OffRamp.GetExecutionState(&bind.CallOpts{Context: ctx}, sourceChain, out.msgSentEvent.SequenceNumber) require.NoError(t, err) - require.Equal(t, uint8(changeset.EXECUTION_STATE_SUCCESS), newExecutionState) + require.Equal(t, uint8(ccdeploy.EXECUTION_STATE_SUCCESS), newExecutionState) } func getMerkleRoot( @@ -285,12 +327,12 @@ func getMessageHash( return iter.Event.MessageHash } -func sleepAndReplay(t *testing.T, e changeset.DeployedEnv, sourceChain, destChain uint64) { +func sleepAndReplay(t *testing.T, e ccdeploy.DeployedEnv, sourceChain, destChain uint64) { time.Sleep(30 * time.Second) replayBlocks := make(map[uint64]uint64) replayBlocks[sourceChain] = 1 replayBlocks[destChain] = 1 - changeset.ReplayLogs(t, e.Env.Offchain, replayBlocks) + ccdeploy.ReplayLogs(t, e.Env.Offchain, replayBlocks) } func runMessagingTestCase( @@ -309,25 +351,15 @@ func runMessagingTestCase( require.Equal(tc.t, tc.nonce, latestNonce) startBlocks := make(map[uint64]*uint64) - msgSentEvent := changeset.TestSendRequest(tc.t, tc.deployedEnv.Env, tc.onchainState, tc.sourceChain, tc.destChain, false, router.ClientEVM2AnyMessage{ + msgSentEvent := ccdeploy.TestSendRequest(tc.t, tc.deployedEnv.Env, tc.onchainState, tc.sourceChain, tc.destChain, false, router.ClientEVM2AnyMessage{ Receiver: common.LeftPadBytes(receiver.Bytes(), 32), Data: msgData, TokenAmounts: nil, FeeToken: common.HexToAddress("0x0"), ExtraArgs: extraArgs, }) - expectedSeqNum := map[changeset.SourceDestPair]uint64{ - { - SourceChainSelector: tc.sourceChain, - DestChainSelector: tc.destChain, - }: msgSentEvent.SequenceNumber, - } - expectedSeqNumExec := map[changeset.SourceDestPair][]uint64{ - { - SourceChainSelector: tc.sourceChain, - DestChainSelector: tc.destChain, - }: {msgSentEvent.SequenceNumber}, - } + expectedSeqNum := make(map[uint64]uint64) + expectedSeqNum[tc.destChain] = msgSentEvent.SequenceNumber out.msgSentEvent = msgSentEvent // hack @@ -336,23 +368,17 @@ func runMessagingTestCase( out.replayed = true } - changeset.ConfirmCommitForAllWithExpectedSeqNums(tc.t, tc.deployedEnv.Env, tc.onchainState, expectedSeqNum, startBlocks) - execStates := changeset.ConfirmExecWithSeqNrsForAll(tc.t, tc.deployedEnv.Env, tc.onchainState, expectedSeqNumExec, startBlocks) + ccdeploy.ConfirmCommitForAllWithExpectedSeqNums(tc.t, tc.deployedEnv.Env, tc.onchainState, expectedSeqNum, startBlocks) + execStates := ccdeploy.ConfirmExecWithSeqNrForAll(tc.t, tc.deployedEnv.Env, tc.onchainState, expectedSeqNum, startBlocks) require.Equalf( tc.t, expectedExecutionState, - execStates[changeset.SourceDestPair{ - SourceChainSelector: tc.sourceChain, - DestChainSelector: tc.destChain, - }][msgSentEvent.SequenceNumber], + execStates[msgSentEvent.SequenceNumber], "wrong execution state for seq nr %d, expected %d, got %d", msgSentEvent.SequenceNumber, expectedExecutionState, - execStates[changeset.SourceDestPair{ - SourceChainSelector: tc.sourceChain, - DestChainSelector: tc.destChain, - }][msgSentEvent.SequenceNumber], + execStates[msgSentEvent.SequenceNumber], ) // check the sender latestNonce on the dest, should be incremented diff --git a/integration-tests/smoke/ccip_rmn_test.go b/integration-tests/smoke/ccip_rmn_test.go new file mode 100644 index 00000000000..7372e10550c --- /dev/null +++ b/integration-tests/smoke/ccip_rmn_test.go @@ -0,0 +1,459 @@ +package smoke + +import ( + "math/big" + "os" + "strconv" + "testing" + "time" + + mapset "github.com/deckarep/golang-set/v2" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "github.com/rs/zerolog" + "github.com/stretchr/testify/require" + + jobv1 "github.com/smartcontractkit/chainlink-protos/job-distributor/v1/job" + "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/osutil" + "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/testcontext" + "github.com/smartcontractkit/chainlink/deployment" + ccipdeployment "github.com/smartcontractkit/chainlink/deployment/ccip" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/rmn_home" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/rmn_remote" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/router" + + "github.com/smartcontractkit/chainlink/integration-tests/ccip-tests/testsetups" + "github.com/smartcontractkit/chainlink/v2/core/logger" +) + +// Set false to run the RMN tests +const skipRmnTest = true + +func TestRMN_TwoMessagesOnTwoLanes(t *testing.T) { + runRmnTestCase(t, rmnTestCase{ + name: "messages on two lanes", + waitForExec: true, + homeChainConfig: homeChainConfig{ + f: map[int]int{chain0: 1, chain1: 1}, + }, + remoteChainsConfig: []remoteChainConfig{ + {chainIdx: chain0, f: 1}, + {chainIdx: chain1, f: 1}, + }, + rmnNodes: []rmnNode{ + {id: 0, isSigner: true, observedChainIdxs: []int{chain0, chain1}}, + {id: 1, isSigner: true, observedChainIdxs: []int{chain0, chain1}}, + {id: 2, isSigner: true, observedChainIdxs: []int{chain0, chain1}}, + }, + messagesToSend: []messageToSend{ + {fromChainIdx: chain0, toChainIdx: chain1, count: 1}, + {fromChainIdx: chain1, toChainIdx: chain0, count: 1}, + }, + }) +} + +func TestRMN_MultipleMessagesOnOneLaneNoWaitForExec(t *testing.T) { + runRmnTestCase(t, rmnTestCase{ + name: "multiple messages for rmn batching inspection and one rmn node down", + waitForExec: false, // do not wait for execution reports + homeChainConfig: homeChainConfig{ + f: map[int]int{chain0: 1, chain1: 1}, + }, + remoteChainsConfig: []remoteChainConfig{ + {chainIdx: chain0, f: 1}, + {chainIdx: chain1, f: 1}, + }, + rmnNodes: []rmnNode{ + {id: 0, isSigner: true, observedChainIdxs: []int{chain0, chain1}}, + {id: 1, isSigner: true, observedChainIdxs: []int{chain0, chain1}}, + {id: 2, isSigner: true, observedChainIdxs: []int{chain0, chain1}, forceExit: true}, // one rmn node is down + }, + messagesToSend: []messageToSend{ + {fromChainIdx: chain1, toChainIdx: chain0, count: 10}, + }, + }) +} + +func TestRMN_NotEnoughObservers(t *testing.T) { + runRmnTestCase(t, rmnTestCase{ + name: "one message but not enough observers, should not get a commit report", + passIfNoCommitAfter: time.Minute, // wait for a minute and assert that commit report was not delivered + homeChainConfig: homeChainConfig{ + f: map[int]int{chain0: 1, chain1: 1}, + }, + remoteChainsConfig: []remoteChainConfig{ + {chainIdx: chain0, f: 1}, + {chainIdx: chain1, f: 1}, + }, + rmnNodes: []rmnNode{ + {id: 0, isSigner: true, observedChainIdxs: []int{chain0, chain1}}, + {id: 1, isSigner: true, observedChainIdxs: []int{chain0, chain1}, forceExit: true}, + {id: 2, isSigner: true, observedChainIdxs: []int{chain0, chain1}, forceExit: true}, + }, + messagesToSend: []messageToSend{ + {fromChainIdx: chain0, toChainIdx: chain1, count: 1}, + }, + }) +} + +func TestRMN_DifferentSigners(t *testing.T) { + runRmnTestCase(t, rmnTestCase{ + name: "different signers and different observers", + homeChainConfig: homeChainConfig{ + f: map[int]int{chain0: 1, chain1: 1}, + }, + remoteChainsConfig: []remoteChainConfig{ + {chainIdx: chain0, f: 1}, + {chainIdx: chain1, f: 1}, + }, + rmnNodes: []rmnNode{ + {id: 0, isSigner: false, observedChainIdxs: []int{chain0, chain1}}, + {id: 1, isSigner: false, observedChainIdxs: []int{chain0, chain1}}, + {id: 2, isSigner: false, observedChainIdxs: []int{chain0, chain1}}, + {id: 3, isSigner: true, observedChainIdxs: []int{}}, + {id: 4, isSigner: true, observedChainIdxs: []int{}}, + {id: 5, isSigner: true, observedChainIdxs: []int{}}, + }, + messagesToSend: []messageToSend{ + {fromChainIdx: chain0, toChainIdx: chain1, count: 1}, + }, + }) +} + +func TestRMN_NotEnoughSigners(t *testing.T) { + runRmnTestCase(t, rmnTestCase{ + name: "different signers and different observers", + passIfNoCommitAfter: time.Minute, // wait for a minute and assert that commit report was not delivered + homeChainConfig: homeChainConfig{ + f: map[int]int{chain0: 1, chain1: 1}, + }, + remoteChainsConfig: []remoteChainConfig{ + {chainIdx: chain0, f: 1}, + {chainIdx: chain1, f: 1}, + }, + rmnNodes: []rmnNode{ + {id: 0, isSigner: false, observedChainIdxs: []int{chain0, chain1}}, + {id: 1, isSigner: false, observedChainIdxs: []int{chain0, chain1}}, + {id: 2, isSigner: false, observedChainIdxs: []int{chain0, chain1}}, + {id: 3, isSigner: true, observedChainIdxs: []int{}}, + {id: 4, isSigner: true, observedChainIdxs: []int{}, forceExit: true}, // signer is down + {id: 5, isSigner: true, observedChainIdxs: []int{}, forceExit: true}, // signer is down + }, + messagesToSend: []messageToSend{ + {fromChainIdx: chain0, toChainIdx: chain1, count: 1}, + }, + }) +} + +func TestRMN_DifferentRmnNodesForDifferentChains(t *testing.T) { + runRmnTestCase(t, rmnTestCase{ + name: "different rmn nodes support different chains", + waitForExec: false, + homeChainConfig: homeChainConfig{ + f: map[int]int{chain0: 1, chain1: 1}, + }, + remoteChainsConfig: []remoteChainConfig{ + {chainIdx: chain0, f: 1}, + {chainIdx: chain1, f: 1}, + }, + rmnNodes: []rmnNode{ + {id: 0, isSigner: true, observedChainIdxs: []int{chain0}}, + {id: 1, isSigner: true, observedChainIdxs: []int{chain0}}, + {id: 2, isSigner: true, observedChainIdxs: []int{chain0}}, + {id: 3, isSigner: true, observedChainIdxs: []int{chain1}}, + {id: 4, isSigner: true, observedChainIdxs: []int{chain1}}, + {id: 5, isSigner: true, observedChainIdxs: []int{chain1}}, + }, + messagesToSend: []messageToSend{ + {fromChainIdx: chain0, toChainIdx: chain1, count: 1}, + {fromChainIdx: chain1, toChainIdx: chain0, count: 1}, + }, + }) +} + +const ( + chain0 = 0 + chain1 = 1 +) + +func runRmnTestCase(t *testing.T, tc rmnTestCase) { + if skipRmnTest { + t.Skip("Local only") + } + require.NoError(t, os.Setenv("ENABLE_RMN", "true")) + + envWithRMN, rmnCluster := testsetups.NewLocalDevEnvironmentWithRMN(t, logger.TestLogger(t), len(tc.rmnNodes)) + t.Logf("envWithRmn: %#v", envWithRMN) + + var chainSelectors []uint64 + for _, chain := range envWithRMN.Env.Chains { + chainSelectors = append(chainSelectors, chain.Selector) + } + require.Greater(t, len(chainSelectors), 1, "There should be at least two chains") + + remoteChainSelectors := make([]uint64, 0, len(envWithRMN.Env.Chains)-1) + for _, chain := range envWithRMN.Env.Chains { + remoteChainSelectors = append(remoteChainSelectors, chain.Selector) + } + require.Greater(t, len(remoteChainSelectors), 0, "There should be at least one remote chain") + + var ( + rmnHomeNodes []rmn_home.RMNHomeNode + rmnRemoteSigners []rmn_remote.RMNRemoteSigner + ) + + for _, rmnNodeInfo := range tc.rmnNodes { + rmn := rmnCluster.Nodes["rmn_"+strconv.Itoa(rmnNodeInfo.id)] + + t.Log(rmnNodeInfo.id, rmn.Proxy.PeerID, rmn.RMN.OffchainPublicKey, rmn.RMN.EVMOnchainPublicKey) + + var offchainPublicKey [32]byte + copy(offchainPublicKey[:], rmn.RMN.OffchainPublicKey) + + rmnHomeNodes = append(rmnHomeNodes, rmn_home.RMNHomeNode{ + PeerId: rmn.Proxy.PeerID, + OffchainPublicKey: offchainPublicKey, + }) + + rmnRemoteSigners = append(rmnRemoteSigners, rmn_remote.RMNRemoteSigner{ + OnchainPublicKey: rmn.RMN.EVMOnchainPublicKey, + NodeIndex: uint64(rmnNodeInfo.id), + }) + } + + var rmnHomeSourceChains []rmn_home.RMNHomeSourceChain + for remoteChainIdx, remoteF := range tc.homeChainConfig.f { + // configure remote chain details on the home contract + rmnHomeSourceChains = append(rmnHomeSourceChains, rmn_home.RMNHomeSourceChain{ + ChainSelector: chainSelectors[remoteChainIdx], + F: uint64(remoteF), + ObserverNodesBitmap: createObserverNodesBitmap(chainSelectors[remoteChainIdx], tc.rmnNodes, chainSelectors), + }) + } + + onChainState, err := ccipdeployment.LoadOnchainState(envWithRMN.Env) + require.NoError(t, err) + t.Logf("onChainState: %#v", onChainState) + + homeChain, ok := envWithRMN.Env.Chains[envWithRMN.HomeChainSel] + require.True(t, ok) + + homeChainState, ok := onChainState.Chains[envWithRMN.HomeChainSel] + require.True(t, ok) + + allDigests, err := homeChainState.RMNHome.GetConfigDigests(&bind.CallOpts{ + Context: testcontext.Get(t), + }) + require.NoError(t, err) + + t.Logf("RMNHome candidateDigest before setting new candidate: %x, activeDigest: %x", + allDigests.CandidateConfigDigest[:], allDigests.ActiveConfigDigest[:]) + + staticConfig := rmn_home.RMNHomeStaticConfig{ + Nodes: rmnHomeNodes, + OffchainConfig: []byte{}, + } + dynamicConfig := rmn_home.RMNHomeDynamicConfig{ + SourceChains: rmnHomeSourceChains, + OffchainConfig: []byte{}, + } + t.Logf("Setting RMNHome candidate with staticConfig: %+v, dynamicConfig: %+v, current candidateDigest: %x", + staticConfig, dynamicConfig, allDigests.CandidateConfigDigest[:]) + tx, err := homeChainState.RMNHome.SetCandidate(homeChain.DeployerKey, staticConfig, dynamicConfig, allDigests.CandidateConfigDigest) + require.NoError(t, err) + + _, err = deployment.ConfirmIfNoError(homeChain, tx, err) + require.NoError(t, err) + + candidateDigest, err := homeChainState.RMNHome.GetCandidateDigest(&bind.CallOpts{ + Context: testcontext.Get(t), + }) + require.NoError(t, err) + + t.Logf("RMNHome candidateDigest after setting new candidate: %x", candidateDigest[:]) + t.Logf("Promoting RMNHome candidate with candidateDigest: %x", candidateDigest[:]) + + tx, err = homeChainState.RMNHome.PromoteCandidateAndRevokeActive( + homeChain.DeployerKey, candidateDigest, allDigests.ActiveConfigDigest) + require.NoError(t, err) + + _, err = deployment.ConfirmIfNoError(homeChain, tx, err) + require.NoError(t, err) + + // check the active digest is the same as the candidate digest + activeDigest, err := homeChainState.RMNHome.GetActiveDigest(&bind.CallOpts{ + Context: testcontext.Get(t), + }) + require.NoError(t, err) + require.Equalf(t, candidateDigest, activeDigest, + "active digest should be the same as the previously candidate digest after promotion, previous candidate: %x, active: %x", + candidateDigest[:], activeDigest[:]) + + // Set RMN remote config appropriately + for _, remoteCfg := range tc.remoteChainsConfig { + remoteSel := chainSelectors[remoteCfg.chainIdx] + chState, ok := onChainState.Chains[remoteSel] + require.True(t, ok) + rmnRemoteConfig := rmn_remote.RMNRemoteConfig{ + RmnHomeContractConfigDigest: activeDigest, + Signers: rmnRemoteSigners, + F: uint64(remoteCfg.f), + } + + chain := envWithRMN.Env.Chains[chainSelectors[remoteCfg.chainIdx]] + + t.Logf("Setting RMNRemote config with RMNHome active digest: %x, cfg: %+v", activeDigest[:], rmnRemoteConfig) + tx2, err2 := chState.RMNRemote.SetConfig(chain.DeployerKey, rmnRemoteConfig) + require.NoError(t, err2) + _, err2 = deployment.ConfirmIfNoError(chain, tx2, err2) + require.NoError(t, err2) + + // confirm the config is set correctly + config, err2 := chState.RMNRemote.GetVersionedConfig(&bind.CallOpts{ + Context: testcontext.Get(t), + }) + require.NoError(t, err2) + require.Equalf(t, + activeDigest, + config.Config.RmnHomeContractConfigDigest, + "RMNRemote config digest should be the same as the active digest of RMNHome after setting, RMNHome active: %x, RMNRemote config: %x", + activeDigest[:], config.Config.RmnHomeContractConfigDigest[:]) + + t.Logf("RMNRemote config digest after setting: %x", config.Config.RmnHomeContractConfigDigest[:]) + } + + // Kill the RMN nodes that are marked for force exit + for _, n := range tc.rmnNodes { + if n.forceExit { + t.Logf("Pausing RMN node %d", n.id) + rmnN := rmnCluster.Nodes["rmn_"+strconv.Itoa(n.id)] + require.NoError(t, osutil.ExecCmd(zerolog.Nop(), "docker kill "+rmnN.Proxy.ContainerName)) + t.Logf("Paused RMN node %d", n.id) + } + } + + jobSpecs, err := ccipdeployment.NewCCIPJobSpecs(envWithRMN.Env.NodeIDs, envWithRMN.Env.Offchain) + require.NoError(t, err) + + ctx := ccipdeployment.Context(t) + + ccipdeployment.ReplayLogs(t, envWithRMN.Env.Offchain, envWithRMN.ReplayBlocks) + + for nodeID, jobs := range jobSpecs { + for _, job := range jobs { + _, err := envWithRMN.Env.Offchain.ProposeJob(ctx, + &jobv1.ProposeJobRequest{ + NodeId: nodeID, + Spec: job, + }) + require.NoError(t, err) + } + } + + // Add all lanes + require.NoError(t, ccipdeployment.AddLanesForAll(envWithRMN.Env, onChainState)) + + // Need to keep track of the block number for each chain so that event subscription can be done from that block. + startBlocks := make(map[uint64]*uint64) + expectedSeqNum := make(map[uint64]uint64) + for _, msg := range tc.messagesToSend { + fromChain := chainSelectors[msg.fromChainIdx] + toChain := chainSelectors[msg.toChainIdx] + + for i := 0; i < msg.count; i++ { + msgSentEvent := ccipdeployment.TestSendRequest(t, envWithRMN.Env, onChainState, fromChain, toChain, false, router.ClientEVM2AnyMessage{ + Receiver: common.LeftPadBytes(onChainState.Chains[toChain].Receiver.Address().Bytes(), 32), + Data: []byte("hello world"), + TokenAmounts: nil, + FeeToken: common.HexToAddress("0x0"), + ExtraArgs: nil, + }) + expectedSeqNum[toChain] = msgSentEvent.SequenceNumber + t.Logf("Sent message from chain %d to chain %d with seqNum %d", fromChain, toChain, msgSentEvent.SequenceNumber) + } + + zero := uint64(0) + startBlocks[toChain] = &zero + } + t.Logf("Sent all messages, expectedSeqNum: %v", expectedSeqNum) + + commitReportReceived := make(chan struct{}) + go func() { + ccipdeployment.ConfirmCommitForAllWithExpectedSeqNums(t, envWithRMN.Env, onChainState, expectedSeqNum, startBlocks) + commitReportReceived <- struct{}{} + }() + + if tc.passIfNoCommitAfter > 0 { // wait for a duration and assert that commit reports were not delivered + tim := time.NewTimer(tc.passIfNoCommitAfter) + t.Logf("waiting for %s before asserting that commit report was not received", tc.passIfNoCommitAfter) + select { + case <-commitReportReceived: + t.Errorf("Commit report was received while it was not expected") + return + case <-tim.C: + return + } + } + + t.Logf("⌛ Waiting for commit reports...") + <-commitReportReceived // wait for commit reports + t.Logf("✅ Commit report") + + if tc.waitForExec { + t.Logf("⌛ Waiting for exec reports...") + ccipdeployment.ConfirmExecWithSeqNrForAll(t, envWithRMN.Env, onChainState, expectedSeqNum, startBlocks) + t.Logf("✅ Exec report") + } +} + +func createObserverNodesBitmap(chainSel uint64, rmnNodes []rmnNode, chainSelectors []uint64) *big.Int { + bitmap := new(big.Int) + for _, n := range rmnNodes { + observedChainSelectors := mapset.NewSet[uint64]() + for _, chainIdx := range n.observedChainIdxs { + observedChainSelectors.Add(chainSelectors[chainIdx]) + } + + if !observedChainSelectors.Contains(chainSel) { + continue + } + + bitmap.SetBit(bitmap, n.id, 1) + } + + return bitmap +} + +type homeChainConfig struct { + f map[int]int +} + +type remoteChainConfig struct { + chainIdx int + f int +} + +type rmnNode struct { + id int + isSigner bool + observedChainIdxs []int + forceExit bool // force exit will simply force exit the rmn node to simulate failure scenarios +} + +type messageToSend struct { + fromChainIdx int + toChainIdx int + count int +} + +type rmnTestCase struct { + name string + // If set to 0, the test will wait for commit reports. + // If set to a positive value, the test will wait for that duration and will assert that commit report was not delivered. + passIfNoCommitAfter time.Duration + waitForExec bool + homeChainConfig homeChainConfig + remoteChainsConfig []remoteChainConfig + rmnNodes []rmnNode + messagesToSend []messageToSend +} diff --git a/integration-tests/smoke/ccip_test.go b/integration-tests/smoke/ccip_test.go new file mode 100644 index 00000000000..007a3c37e52 --- /dev/null +++ b/integration-tests/smoke/ccip_test.go @@ -0,0 +1,272 @@ +package smoke + +import ( + "math/big" + "testing" + + "github.com/ethereum/go-ethereum/common" + "github.com/stretchr/testify/require" + + jobv1 "github.com/smartcontractkit/chainlink-protos/job-distributor/v1/job" + "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/testcontext" + + "github.com/smartcontractkit/chainlink/deployment" + ccdeploy "github.com/smartcontractkit/chainlink/deployment/ccip" + "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" + "github.com/smartcontractkit/chainlink/integration-tests/ccip-tests/testsetups" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/router" + "github.com/smartcontractkit/chainlink/v2/core/logger" +) + +func TestInitialDeployOnLocal(t *testing.T) { + t.Parallel() + lggr := logger.TestLogger(t) + ctx := ccdeploy.Context(t) + tenv, _, _ := testsetups.NewLocalDevEnvironmentWithDefaultPrice(t, lggr) + e := tenv.Env + + state, err := ccdeploy.LoadOnchainState(tenv.Env) + require.NoError(t, err) + + feeds := state.Chains[tenv.FeedChainSel].USDFeeds + output, err := changeset.DeployPrerequisites(tenv.Env, changeset.DeployPrerequisiteConfig{ + ChainSelectors: tenv.Env.AllChainSelectors(), + }) + require.NoError(t, err) + require.NoError(t, tenv.Env.ExistingAddresses.Merge(output.AddressBook)) + + // Apply migration + output, err = changeset.InitialDeploy(tenv.Env, ccdeploy.DeployCCIPContractConfig{ + HomeChainSel: tenv.HomeChainSel, + FeedChainSel: tenv.FeedChainSel, + ChainsToDeploy: tenv.Env.AllChainSelectors(), + TokenConfig: ccdeploy.NewTestTokenConfig(feeds), + MCMSConfig: ccdeploy.NewTestMCMSConfig(t, e), + OCRSecrets: deployment.XXXGenerateTestOCRSecrets(), + }) + require.NoError(t, err) + require.NoError(t, tenv.Env.ExistingAddresses.Merge(output.AddressBook)) + // Get new state after migration. + state, err = ccdeploy.LoadOnchainState(e) + require.NoError(t, err) + + // Ensure capreg logs are up to date. + ccdeploy.ReplayLogs(t, e.Offchain, tenv.ReplayBlocks) + + // Apply the jobs. + for nodeID, jobs := range output.JobSpecs { + for _, job := range jobs { + // Note these auto-accept + _, err := e.Offchain.ProposeJob(ctx, + &jobv1.ProposeJobRequest{ + NodeId: nodeID, + Spec: job, + }) + require.NoError(t, err) + } + } + + // Add all lanes + require.NoError(t, ccdeploy.AddLanesForAll(e, state)) + // Need to keep track of the block number for each chain so that event subscription can be done from that block. + startBlocks := make(map[uint64]*uint64) + // Send a message from each chain to every other chain. + expectedSeqNum := make(map[uint64]uint64) + for src := range e.Chains { + for dest, destChain := range e.Chains { + if src == dest { + continue + } + latesthdr, err := destChain.Client.HeaderByNumber(testcontext.Get(t), nil) + require.NoError(t, err) + block := latesthdr.Number.Uint64() + startBlocks[dest] = &block + msgSentEvent := ccdeploy.TestSendRequest(t, e, state, src, dest, false, router.ClientEVM2AnyMessage{ + Receiver: common.LeftPadBytes(state.Chains[dest].Receiver.Address().Bytes(), 32), + Data: []byte("hello world"), + TokenAmounts: nil, + FeeToken: common.HexToAddress("0x0"), + ExtraArgs: nil, + }) + expectedSeqNum[dest] = msgSentEvent.SequenceNumber + } + } + + // Wait for all commit reports to land. + ccdeploy.ConfirmCommitForAllWithExpectedSeqNums(t, e, state, expectedSeqNum, startBlocks) + + // After commit is reported on all chains, token prices should be updated in FeeQuoter. + for dest := range e.Chains { + linkAddress := state.Chains[dest].LinkToken.Address() + feeQuoter := state.Chains[dest].FeeQuoter + timestampedPrice, err := feeQuoter.GetTokenPrice(nil, linkAddress) + require.NoError(t, err) + require.Equal(t, ccdeploy.MockLinkPrice, timestampedPrice.Value) + } + + // Wait for all exec reports to land + ccdeploy.ConfirmExecWithSeqNrForAll(t, e, state, expectedSeqNum, startBlocks) + + // TODO: Apply the proposal. +} + +func TestTokenTransfer(t *testing.T) { + t.Parallel() + lggr := logger.TestLogger(t) + ctx := ccdeploy.Context(t) + tenv, _, _ := testsetups.NewLocalDevEnvironmentWithDefaultPrice(t, lggr) + + e := tenv.Env + state, err := ccdeploy.LoadOnchainState(e) + require.NoError(t, err) + + output, err := changeset.DeployPrerequisites(e, changeset.DeployPrerequisiteConfig{ + ChainSelectors: e.AllChainSelectors(), + }) + require.NoError(t, err) + require.NoError(t, e.ExistingAddresses.Merge(output.AddressBook)) + + // Apply migration + output, err = changeset.InitialDeploy(e, ccdeploy.DeployCCIPContractConfig{ + HomeChainSel: tenv.HomeChainSel, + FeedChainSel: tenv.FeedChainSel, + ChainsToDeploy: e.AllChainSelectors(), + TokenConfig: ccdeploy.NewTestTokenConfig(state.Chains[tenv.FeedChainSel].USDFeeds), + MCMSConfig: ccdeploy.NewTestMCMSConfig(t, e), + OCRSecrets: deployment.XXXGenerateTestOCRSecrets(), + }) + require.NoError(t, err) + require.NoError(t, e.ExistingAddresses.Merge(output.AddressBook)) + // Get new state after migration and mock USDC token deployment. + state, err = ccdeploy.LoadOnchainState(e) + require.NoError(t, err) + + srcToken, _, dstToken, _, err := ccdeploy.DeployTransferableToken( + lggr, + tenv.Env.Chains, + tenv.HomeChainSel, + tenv.FeedChainSel, + state, + e.ExistingAddresses, + "MY_TOKEN", + ) + require.NoError(t, err) + + // Ensure capreg logs are up to date. + ccdeploy.ReplayLogs(t, e.Offchain, tenv.ReplayBlocks) + + // Apply the jobs. + for nodeID, jobs := range output.JobSpecs { + for _, job := range jobs { + // Note these auto-accept + _, err := e.Offchain.ProposeJob(ctx, + &jobv1.ProposeJobRequest{ + NodeId: nodeID, + Spec: job, + }) + require.NoError(t, err) + } + } + + // Add all lanes + require.NoError(t, ccdeploy.AddLanesForAll(e, state)) + // Need to keep track of the block number for each chain so that event subscription can be done from that block. + startBlocks := make(map[uint64]*uint64) + // Send a message from each chain to every other chain. + expectedSeqNum := make(map[uint64]uint64) + + twoCoins := new(big.Int).Mul(big.NewInt(1e18), big.NewInt(2)) + tx, err := srcToken.Mint( + e.Chains[tenv.HomeChainSel].DeployerKey, + e.Chains[tenv.HomeChainSel].DeployerKey.From, + new(big.Int).Mul(twoCoins, big.NewInt(10)), + ) + require.NoError(t, err) + _, err = e.Chains[tenv.HomeChainSel].Confirm(tx) + require.NoError(t, err) + + tx, err = dstToken.Mint( + e.Chains[tenv.FeedChainSel].DeployerKey, + e.Chains[tenv.FeedChainSel].DeployerKey.From, + new(big.Int).Mul(twoCoins, big.NewInt(10)), + ) + require.NoError(t, err) + _, err = e.Chains[tenv.FeedChainSel].Confirm(tx) + require.NoError(t, err) + + tx, err = srcToken.Approve(e.Chains[tenv.HomeChainSel].DeployerKey, state.Chains[tenv.HomeChainSel].Router.Address(), twoCoins) + require.NoError(t, err) + _, err = e.Chains[tenv.HomeChainSel].Confirm(tx) + require.NoError(t, err) + tx, err = dstToken.Approve(e.Chains[tenv.FeedChainSel].DeployerKey, state.Chains[tenv.FeedChainSel].Router.Address(), twoCoins) + require.NoError(t, err) + _, err = e.Chains[tenv.FeedChainSel].Confirm(tx) + require.NoError(t, err) + + tokens := map[uint64][]router.ClientEVMTokenAmount{ + tenv.HomeChainSel: {{ + Token: srcToken.Address(), + Amount: twoCoins, + }}, + tenv.FeedChainSel: {{ + Token: dstToken.Address(), + Amount: twoCoins, + }}, + } + + for src := range e.Chains { + for dest, destChain := range e.Chains { + if src == dest { + continue + } + latesthdr, err := destChain.Client.HeaderByNumber(testcontext.Get(t), nil) + require.NoError(t, err) + block := latesthdr.Number.Uint64() + startBlocks[dest] = &block + + var ( + receiver = common.LeftPadBytes(state.Chains[dest].Receiver.Address().Bytes(), 32) + data = []byte("hello world") + feeToken = common.HexToAddress("0x0") + ) + if src == tenv.HomeChainSel && dest == tenv.FeedChainSel { + msgSentEvent := ccdeploy.TestSendRequest(t, e, state, src, dest, false, router.ClientEVM2AnyMessage{ + Receiver: receiver, + Data: data, + TokenAmounts: tokens[src], + FeeToken: feeToken, + ExtraArgs: nil, + }) + expectedSeqNum[dest] = msgSentEvent.SequenceNumber + } else { + msgSentEvent := ccdeploy.TestSendRequest(t, e, state, src, dest, false, router.ClientEVM2AnyMessage{ + Receiver: receiver, + Data: data, + TokenAmounts: nil, + FeeToken: feeToken, + ExtraArgs: nil, + }) + expectedSeqNum[dest] = msgSentEvent.SequenceNumber + } + } + } + + // Wait for all commit reports to land. + ccdeploy.ConfirmCommitForAllWithExpectedSeqNums(t, e, state, expectedSeqNum, startBlocks) + + // After commit is reported on all chains, token prices should be updated in FeeQuoter. + for dest := range e.Chains { + linkAddress := state.Chains[dest].LinkToken.Address() + feeQuoter := state.Chains[dest].FeeQuoter + timestampedPrice, err := feeQuoter.GetTokenPrice(nil, linkAddress) + require.NoError(t, err) + require.Equal(t, ccdeploy.MockLinkPrice, timestampedPrice.Value) + } + + // Wait for all exec reports to land + ccdeploy.ConfirmExecWithSeqNrForAll(t, e, state, expectedSeqNum, startBlocks) + + balance, err := dstToken.BalanceOf(nil, state.Chains[tenv.FeedChainSel].Receiver.Address()) + require.NoError(t, err) + require.Equal(t, twoCoins, balance) +} diff --git a/integration-tests/smoke/ccip_usdc_test.go b/integration-tests/smoke/ccip_usdc_test.go new file mode 100644 index 00000000000..9fb4544d9f6 --- /dev/null +++ b/integration-tests/smoke/ccip_usdc_test.go @@ -0,0 +1,283 @@ +package smoke + +import ( + "math/big" + "net/http" + "net/http/httptest" + "testing" + "time" + + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "github.com/stretchr/testify/require" + + "golang.org/x/exp/maps" + + cciptypes "github.com/smartcontractkit/chainlink-ccip/pkg/types/ccipocr3" + "github.com/smartcontractkit/chainlink-ccip/pluginconfig" + commonconfig "github.com/smartcontractkit/chainlink-common/pkg/config" + "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" + jobv1 "github.com/smartcontractkit/chainlink-protos/job-distributor/v1/job" + "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/testcontext" + "github.com/smartcontractkit/chainlink/deployment" + ccdeploy "github.com/smartcontractkit/chainlink/deployment/ccip" + "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" + "github.com/smartcontractkit/chainlink/integration-tests/ccip-tests/actions" + "github.com/smartcontractkit/chainlink/integration-tests/ccip-tests/testsetups" + + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/router" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/shared/generated/burn_mint_erc677" + "github.com/smartcontractkit/chainlink/v2/core/logger" +) + +func TestUSDCTokenTransfer(t *testing.T) { + lggr := logger.TestLogger(t) + ctx := ccdeploy.Context(t) + tenv, cluster, _ := testsetups.NewLocalDevEnvironmentWithDefaultPrice(t, lggr) + + var endpoint string + // When inmemory env then spin up in memory mock server + if cluster == nil { + server := mockAttestationResponse() + defer server.Close() + endpoint = server.URL + } else { + err := actions.SetMockServerWithUSDCAttestation(tenv.Env.MockAdapter, nil) + require.NoError(t, err) + endpoint = tenv.Env.MockAdapter.InternalEndpoint + } + + e := tenv.Env + state, err := ccdeploy.LoadOnchainState(e) + require.NoError(t, err) + + allChainSelectors := maps.Keys(e.Chains) + sourceChain := allChainSelectors[0] + destChain := allChainSelectors[1] + + feeds := state.Chains[tenv.FeedChainSel].USDFeeds + tokenConfig := ccdeploy.NewTokenConfig() + tokenConfig.UpsertTokenInfo(ccdeploy.LinkSymbol, + pluginconfig.TokenInfo{ + AggregatorAddress: cciptypes.UnknownEncodedAddress(feeds[ccdeploy.LinkSymbol].Address().String()), + Decimals: ccdeploy.LinkDecimals, + DeviationPPB: cciptypes.NewBigIntFromInt64(1e9), + }, + ) + + output, err := changeset.DeployPrerequisites(e, changeset.DeployPrerequisiteConfig{ + ChainSelectors: e.AllChainSelectors(), + }) + require.NoError(t, err) + require.NoError(t, tenv.Env.ExistingAddresses.Merge(output.AddressBook)) + + // Apply migration + output, err = changeset.InitialDeploy(e, ccdeploy.DeployCCIPContractConfig{ + HomeChainSel: tenv.HomeChainSel, + FeedChainSel: tenv.FeedChainSel, + ChainsToDeploy: e.AllChainSelectors(), + TokenConfig: tokenConfig, + MCMSConfig: ccdeploy.NewTestMCMSConfig(t, e), + OCRSecrets: deployment.XXXGenerateTestOCRSecrets(), + USDCConfig: ccdeploy.USDCConfig{ + Enabled: true, + USDCAttestationConfig: ccdeploy.USDCAttestationConfig{ + API: endpoint, + APITimeout: commonconfig.MustNewDuration(time.Second), + APIInterval: commonconfig.MustNewDuration(500 * time.Millisecond), + }, + }, + }) + require.NoError(t, err) + require.NoError(t, e.ExistingAddresses.Merge(output.AddressBook)) + + state, err = ccdeploy.LoadOnchainState(e) + require.NoError(t, err) + + srcUSDC, dstUSDC, err := ccdeploy.ConfigureUSDCTokenPools(lggr, e.Chains, sourceChain, destChain, state) + require.NoError(t, err) + + // Ensure capreg logs are up to date. + ccdeploy.ReplayLogs(t, e.Offchain, tenv.ReplayBlocks) + + // Apply the jobs. + for nodeID, jobs := range output.JobSpecs { + for _, job := range jobs { + // Note these auto-accept + _, err := e.Offchain.ProposeJob(ctx, + &jobv1.ProposeJobRequest{ + NodeId: nodeID, + Spec: job, + }) + require.NoError(t, err) + } + } + + // Add all lanes + require.NoError(t, ccdeploy.AddLanesForAll(e, state)) + + mintAndAllow(t, e, state, map[uint64]*burn_mint_erc677.BurnMintERC677{ + sourceChain: srcUSDC, + destChain: dstUSDC, + }) + + err = ccdeploy.UpdateFeeQuoterForUSDC(lggr, e.Chains[sourceChain], state.Chains[sourceChain], destChain, srcUSDC) + require.NoError(t, err) + + err = ccdeploy.UpdateFeeQuoterForUSDC(lggr, e.Chains[destChain], state.Chains[destChain], sourceChain, dstUSDC) + require.NoError(t, err) + + // MockE2EUSDCTransmitter always mint 1, see MockE2EUSDCTransmitter.sol for more details + tinyOneCoin := new(big.Int).SetUint64(1) + + srcDstTokenMapping := map[common.Address]*burn_mint_erc677.BurnMintERC677{ + srcUSDC.Address(): dstUSDC, + dstUSDC.Address(): srcUSDC, + } + + tcs := []struct { + name string + receiver common.Address + sourceChain uint64 + destChain uint64 + tokens []router.ClientEVMTokenAmount + data []byte + }{ + { + name: "single USDC token transfer to EOA", + receiver: utils.RandomAddress(), + sourceChain: destChain, + destChain: sourceChain, + tokens: []router.ClientEVMTokenAmount{ + { + Token: dstUSDC.Address(), + Amount: tinyOneCoin, + }}, + }, + { + name: "programmable token transfer to valid contract receiver", + receiver: state.Chains[destChain].Receiver.Address(), + sourceChain: sourceChain, + destChain: destChain, + tokens: []router.ClientEVMTokenAmount{ + { + Token: srcUSDC.Address(), + Amount: tinyOneCoin, + }, + }, + data: []byte("hello world"), + }, + } + + for _, tt := range tcs { + t.Run(tt.name, func(t *testing.T) { + initialBalances := map[common.Address]*big.Int{} + for _, token := range tt.tokens { + destToken := srcDstTokenMapping[token.Token] + + initialBalance, err := destToken.BalanceOf(&bind.CallOpts{Context: tests.Context(t)}, tt.receiver) + require.NoError(t, err) + initialBalances[token.Token] = initialBalance + } + + transferAndWaitForSuccess( + t, + e, + state, + tt.sourceChain, + tt.destChain, + tt.tokens, + tt.receiver, + tt.data, + ) + + for _, token := range tt.tokens { + destToken := srcDstTokenMapping[token.Token] + + balance, err := destToken.BalanceOf(&bind.CallOpts{Context: tests.Context(t)}, tt.receiver) + require.NoError(t, err) + require.Equal(t, new(big.Int).Add(initialBalances[token.Token], tinyOneCoin), balance) + } + }) + } +} + +// mintAndAllow mints tokens for deployers and allow router to spend them +func mintAndAllow( + t *testing.T, + e deployment.Environment, + state ccdeploy.CCIPOnChainState, + tokens map[uint64]*burn_mint_erc677.BurnMintERC677, +) { + for chain, token := range tokens { + twoCoins := new(big.Int).Mul(big.NewInt(1e18), big.NewInt(2)) + + tx, err := token.Mint( + e.Chains[chain].DeployerKey, + e.Chains[chain].DeployerKey.From, + new(big.Int).Mul(twoCoins, big.NewInt(10)), + ) + require.NoError(t, err) + _, err = e.Chains[chain].Confirm(tx) + require.NoError(t, err) + + tx, err = token.Approve(e.Chains[chain].DeployerKey, state.Chains[chain].Router.Address(), twoCoins) + require.NoError(t, err) + _, err = e.Chains[chain].Confirm(tx) + require.NoError(t, err) + } +} + +// transferAndWaitForSuccess sends a message from sourceChain to destChain and waits for it to be executed +func transferAndWaitForSuccess( + t *testing.T, + env deployment.Environment, + state ccdeploy.CCIPOnChainState, + sourceChain, destChain uint64, + tokens []router.ClientEVMTokenAmount, + receiver common.Address, + data []byte, +) { + startBlocks := make(map[uint64]*uint64) + expectedSeqNum := make(map[uint64]uint64) + + latesthdr, err := env.Chains[destChain].Client.HeaderByNumber(testcontext.Get(t), nil) + require.NoError(t, err) + block := latesthdr.Number.Uint64() + startBlocks[destChain] = &block + + msgSentEvent := ccdeploy.TestSendRequest(t, env, state, sourceChain, destChain, false, router.ClientEVM2AnyMessage{ + Receiver: common.LeftPadBytes(receiver.Bytes(), 32), + Data: data, + TokenAmounts: tokens, + FeeToken: common.HexToAddress("0x0"), + ExtraArgs: nil, + }) + expectedSeqNum[destChain] = msgSentEvent.SequenceNumber + + // Wait for all commit reports to land. + ccdeploy.ConfirmCommitForAllWithExpectedSeqNums(t, env, state, expectedSeqNum, startBlocks) + + // Wait for all exec reports to land + ccdeploy.ConfirmExecWithSeqNrForAll(t, env, state, expectedSeqNum, startBlocks) +} + +// mockAttestationResponse mocks the USDC attestation server, it returns random Attestation. +// We don't need to return exactly the same attestation, because our Mocked USDC contract doesn't rely on any specific +// value, but instead of that it just checks if the attestation is present. Therefore, it makes the test a bit simpler +// and doesn't require very detailed mocks. Please see tests in chainlink-ccip for detailed tests using real attestations +func mockAttestationResponse() *httptest.Server { + server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + response := `{ + "status": "complete", + "attestation": "0x9049623e91719ef2aa63c55f357be2529b0e7122ae552c18aff8db58b4633c4d3920ff03d3a6d1ddf11f06bf64d7fd60d45447ac81f527ba628877dc5ca759651b08ffae25a6d3b1411749765244f0a1c131cbfe04430d687a2e12fd9d2e6dc08e118ad95d94ad832332cf3c4f7a4f3da0baa803b7be024b02db81951c0f0714de1b" + }` + + _, err := w.Write([]byte(response)) + if err != nil { + panic(err) + } + })) + return server +} diff --git a/integration-tests/smoke/fee_boosting_test.go b/integration-tests/smoke/fee_boosting_test.go new file mode 100644 index 00000000000..625200360e8 --- /dev/null +++ b/integration-tests/smoke/fee_boosting_test.go @@ -0,0 +1,158 @@ +package smoke + +import ( + "math/big" + "testing" + "time" + + "github.com/ethereum/go-ethereum/common" + "github.com/test-go/testify/require" + "golang.org/x/exp/maps" + + jobv1 "github.com/smartcontractkit/chainlink-protos/job-distributor/v1/job" + "github.com/smartcontractkit/chainlink/deployment" + ccdeploy "github.com/smartcontractkit/chainlink/deployment/ccip" + "github.com/smartcontractkit/chainlink/deployment/ccip/changeset" + "github.com/smartcontractkit/chainlink/integration-tests/ccip-tests/testsetups" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/router" + "github.com/smartcontractkit/chainlink/v2/core/logger" +) + +type feeboostTestCase struct { + t *testing.T + sender []byte + deployedEnv ccdeploy.DeployedEnv + onchainState ccdeploy.CCIPOnChainState + initialPrices ccdeploy.InitialPrices + priceFeedPrices priceFeedPrices + sourceChain, destChain uint64 +} + +type priceFeedPrices struct { + linkPrice *big.Int + wethPrice *big.Int +} + +// TODO: find a way to reuse the same test setup for all tests +func Test_CCIPFeeBoosting(t *testing.T) { + ctx := ccdeploy.Context(t) + + setupTestEnv := func(t *testing.T, numChains int) (ccdeploy.DeployedEnv, ccdeploy.CCIPOnChainState, []uint64) { + e, _, _ := testsetups.NewLocalDevEnvironment( + t, logger.TestLogger(t), + deployment.E18Mult(5), + big.NewInt(9e8)) + + state, err := ccdeploy.LoadOnchainState(e.Env) + require.NoError(t, err) + + allChainSelectors := maps.Keys(e.Env.Chains) + require.Len(t, allChainSelectors, numChains) + + output, err := changeset.DeployPrerequisites(e.Env, changeset.DeployPrerequisiteConfig{ + ChainSelectors: e.Env.AllChainSelectors(), + }) + require.NoError(t, err) + require.NoError(t, e.Env.ExistingAddresses.Merge(output.AddressBook)) + + tokenConfig := ccdeploy.NewTestTokenConfig(state.Chains[e.FeedChainSel].USDFeeds) + // Apply migration + output, err = changeset.InitialDeploy(e.Env, ccdeploy.DeployCCIPContractConfig{ + HomeChainSel: e.HomeChainSel, + FeedChainSel: e.FeedChainSel, + ChainsToDeploy: allChainSelectors, + TokenConfig: tokenConfig, + MCMSConfig: ccdeploy.NewTestMCMSConfig(t, e.Env), + OCRSecrets: deployment.XXXGenerateTestOCRSecrets(), + }) + require.NoError(t, err) + require.NoError(t, e.Env.ExistingAddresses.Merge(output.AddressBook)) + state, err = ccdeploy.LoadOnchainState(e.Env) + require.NoError(t, err) + + // Ensure capreg logs are up to date. + ccdeploy.ReplayLogs(t, e.Env.Offchain, e.ReplayBlocks) + + // Apply the jobs. + for nodeID, jobs := range output.JobSpecs { + for _, job := range jobs { + // Note these auto-accept + _, err := e.Env.Offchain.ProposeJob(ctx, + &jobv1.ProposeJobRequest{ + NodeId: nodeID, + Spec: job, + }) + require.NoError(t, err) + } + } + + return e, state, allChainSelectors + } + + t.Run("boost needed due to WETH price increase (also covering gas price inscrease)", func(t *testing.T) { + e, state, chains := setupTestEnv(t, 2) + runFeeboostTestCase(feeboostTestCase{ + t: t, + sender: common.LeftPadBytes(e.Env.Chains[chains[0]].DeployerKey.From.Bytes(), 32), + deployedEnv: e, + onchainState: state, + initialPrices: ccdeploy.InitialPrices{ + LinkPrice: deployment.E18Mult(5), + WethPrice: deployment.E18Mult(9), + GasPrice: ccdeploy.ToPackedFee(big.NewInt(1.8e11), big.NewInt(0)), + }, + priceFeedPrices: priceFeedPrices{ + linkPrice: deployment.E18Mult(5), + wethPrice: big.NewInt(9.9e8), // increase from 9e8 to 9.9e8 + }, + sourceChain: chains[0], + destChain: chains[1], + }) + }) + + t.Run("boost needed due to LINK price decrease", func(t *testing.T) { + e, state, chains := setupTestEnv(t, 2) + runFeeboostTestCase(feeboostTestCase{ + t: t, + sender: common.LeftPadBytes(e.Env.Chains[chains[0]].DeployerKey.From.Bytes(), 32), + deployedEnv: e, + onchainState: state, + initialPrices: ccdeploy.InitialPrices{ + LinkPrice: deployment.E18Mult(5), + WethPrice: deployment.E18Mult(9), + GasPrice: ccdeploy.ToPackedFee(big.NewInt(1.8e11), big.NewInt(0)), + }, + priceFeedPrices: priceFeedPrices{ + linkPrice: big.NewInt(4.5e18), // decrease from 5e18 to 4.5e18 + wethPrice: big.NewInt(9e8), + }, + sourceChain: chains[0], + destChain: chains[1], + }) + }) +} + +func runFeeboostTestCase(tc feeboostTestCase) { + require.NoError(tc.t, ccdeploy.AddLane(tc.deployedEnv.Env, tc.onchainState, tc.sourceChain, tc.destChain, tc.initialPrices)) + + startBlocks := make(map[uint64]*uint64) + expectedSeqNum := make(map[uint64]uint64) + msgSentEvent := ccdeploy.TestSendRequest(tc.t, tc.deployedEnv.Env, tc.onchainState, tc.sourceChain, tc.destChain, false, router.ClientEVM2AnyMessage{ + Receiver: common.LeftPadBytes(tc.onchainState.Chains[tc.destChain].Receiver.Address().Bytes(), 32), + Data: []byte("message that needs fee boosting"), + TokenAmounts: nil, + FeeToken: common.HexToAddress("0x0"), + ExtraArgs: nil, + }) + expectedSeqNum[tc.destChain] = msgSentEvent.SequenceNumber + + // hack + time.Sleep(30 * time.Second) + replayBlocks := make(map[uint64]uint64) + replayBlocks[tc.sourceChain] = 1 + replayBlocks[tc.destChain] = 1 + ccdeploy.ReplayLogs(tc.t, tc.deployedEnv.Env.Offchain, replayBlocks) + + ccdeploy.ConfirmCommitForAllWithExpectedSeqNums(tc.t, tc.deployedEnv.Env, tc.onchainState, expectedSeqNum, startBlocks) + ccdeploy.ConfirmExecWithSeqNrForAll(tc.t, tc.deployedEnv.Env, tc.onchainState, expectedSeqNum, startBlocks) +} diff --git a/integration-tests/smoke/forwarders_ocr2_test.go b/integration-tests/smoke/forwarders_ocr2_test.go index 3f2f4dadae8..0cc7d9fafe4 100644 --- a/integration-tests/smoke/forwarders_ocr2_test.go +++ b/integration-tests/smoke/forwarders_ocr2_test.go @@ -100,10 +100,7 @@ func TestForwarderOCR2Basic(t *testing.T) { err = actions.ConfigureOCRv2AggregatorContracts(ocrv2Config, ocrInstances) require.NoError(t, err, "Error configuring OCRv2 aggregator contracts") - if sethClient.ChainID < 0 { - t.Errorf("negative chain ID: %d", sethClient.ChainID) - } - err = actions.CreateOCRv2JobsLocal(ocrInstances, bootstrapNode, workerNodes, env.MockAdapter, "ocr2", 5, uint64(sethClient.ChainID), true, false) //nolint:gosec // G115 false positive + err = actions.CreateOCRv2JobsLocal(ocrInstances, bootstrapNode, workerNodes, env.MockAdapter, "ocr2", 5, uint64(sethClient.ChainID), true, false) require.NoError(t, err, "Error creating OCRv2 jobs with forwarders") err = actions.WatchNewOCRRound(l, sethClient, 1, contracts.V2OffChainAgrregatorToOffChainAggregatorWithRounds(ocrInstances), time.Duration(10*time.Minute)) diff --git a/integration-tests/smoke/log_poller_test.go b/integration-tests/smoke/log_poller_test.go index edf8c228a07..b5891e7a3e8 100644 --- a/integration-tests/smoke/log_poller_test.go +++ b/integration-tests/smoke/log_poller_test.go @@ -3,7 +3,6 @@ package smoke import ( "context" "fmt" - "math" "math/big" "testing" "time" @@ -131,9 +130,6 @@ func executeBasicLogPollerTest(t *testing.T, logScannerSettings test_env.Chainli // Save block number before starting to emit events, so that we can later use it when querying logs sb, err := sethClient.Client.BlockNumber(testcontext.Get(t)) require.NoError(t, err, "Error getting latest block number") - if sb > math.MaxInt64 { - t.Fatalf("start block overflows int64: %d", sb) - } startBlock := int64(sb) l.Info().Int64("Starting Block", startBlock).Msg("STARTING EVENT EMISSION") @@ -167,9 +163,6 @@ func executeBasicLogPollerTest(t *testing.T, logScannerSettings test_env.Chainli chaosError := <-chaosDoneCh require.NoError(t, chaosError, "Error encountered during chaos experiment") - if eb > math.MaxInt64 { - t.Fatalf("end block overflows int64: %d", eb) - } // use ridciuously high end block so that we don't have to find out the block number of the last block in which logs were emitted // as that's not trivial to do (i.e. just because chain was at block X when log emission ended it doesn't mean all events made it to that block) endBlock := int64(eb) + 10000 @@ -212,9 +205,6 @@ func executeLogPollerReplay(t *testing.T, consistencyTimeout string) { // Save block number before starting to emit events, so that we can later use it when querying logs sb, err := sethClient.Client.BlockNumber(testcontext.Get(t)) require.NoError(t, err, "Error getting latest block number") - if sb > math.MaxInt64 { - t.Fatalf("start block overflows int64: %d", sb) - } startBlock := int64(sb) l.Info().Int64("Starting Block", startBlock).Msg("STARTING EVENT EMISSION") @@ -229,9 +219,6 @@ func executeLogPollerReplay(t *testing.T, consistencyTimeout string) { eb, err := sethClient.Client.BlockNumber(testcontext.Get(t)) require.NoError(t, err, "Error getting latest block number") - if eb > math.MaxInt64 { - t.Fatalf("end block overflows int64: %d", eb) - } endBlock, err := logpoller.GetEndBlockToWaitFor(int64(eb), *evmNetwork, cfg) require.NoError(t, err, "Error getting end block to wait for") @@ -295,7 +282,7 @@ type logPollerEnvironment struct { // deploying registry and log emitter contracts and registering log triggered upkeeps func prepareEnvironment(l zerolog.Logger, t *testing.T, testConfig *tc.TestConfig, logScannerSettings test_env.ChainlinkNodeLogScannerSettings) logPollerEnvironment { cfg := testConfig.LogPoller - if len(cfg.General.EventsToEmit) == 0 { + if cfg.General.EventsToEmit == nil || len(cfg.General.EventsToEmit) == 0 { l.Warn().Msg("No events to emit specified, using all events from log emitter contract") for _, event := range logpoller.EmitterABI.Events { cfg.General.EventsToEmit = append(cfg.General.EventsToEmit, event) diff --git a/integration-tests/smoke/ocr2_test.go b/integration-tests/smoke/ocr2_test.go index 8416ec05c7e..325c88f979a 100644 --- a/integration-tests/smoke/ocr2_test.go +++ b/integration-tests/smoke/ocr2_test.go @@ -1,19 +1,14 @@ package smoke import ( - "bufio" "fmt" "math/big" "net/http" - "os" - "path/filepath" - "regexp" "strings" - "sync" "testing" "time" - "github.com/onsi/gomega" + "github.com/smartcontractkit/chainlink/integration-tests/utils" "github.com/ethereum/go-ethereum/common" "github.com/rs/zerolog" @@ -21,8 +16,8 @@ import ( "github.com/smartcontractkit/chainlink-testing-framework/seth" - ctf_docker "github.com/smartcontractkit/chainlink-testing-framework/lib/docker" "github.com/smartcontractkit/chainlink-testing-framework/lib/logging" + "github.com/smartcontractkit/chainlink-testing-framework/lib/logstream" "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/testcontext" "github.com/smartcontractkit/chainlink/v2/core/config/env" @@ -31,7 +26,6 @@ import ( "github.com/smartcontractkit/chainlink/integration-tests/contracts" "github.com/smartcontractkit/chainlink/integration-tests/docker/test_env" tc "github.com/smartcontractkit/chainlink/integration-tests/testconfig" - "github.com/smartcontractkit/chainlink/integration-tests/utils" ) type ocr2test struct { @@ -131,7 +125,7 @@ func TestOCRv2JobReplacement(t *testing.T) { err = actions.DeleteBridges(nodeClients) require.NoError(t, err) - err = actions.CreateOCRv2JobsLocal(aggregatorContracts, bootstrapNode, workerNodes, testEnv.MockAdapter, "ocr2", 15, uint64(sethClient.ChainID), false, false) //nolint:gosec // G115 false positive + err = actions.CreateOCRv2JobsLocal(aggregatorContracts, bootstrapNode, workerNodes, testEnv.MockAdapter, "ocr2", 15, uint64(sethClient.ChainID), false, false) require.NoError(t, err, "Error creating OCRv2 jobs") err = actions.WatchNewOCRRound(l, sethClient, 3, contracts.V2OffChainAgrregatorToOffChainAggregatorWithRounds(aggregatorContracts), time.Minute*3) @@ -201,10 +195,7 @@ func prepareORCv2SmokeTestEnv(t *testing.T, testData ocr2test, l zerolog.Logger, aggregatorContracts, err := actions.SetupOCRv2Contracts(l, sethClient, config.OCR2, common.HexToAddress(linkContract.Address()), transmitters, ocrOffChainOptions) require.NoError(t, err, "Error deploying OCRv2 aggregator contracts") - if sethClient.ChainID < 0 { - t.Errorf("negative chain ID: %d", sethClient.ChainID) - } - err = actions.CreateOCRv2JobsLocal(aggregatorContracts, bootstrapNode, workerNodes, testEnv.MockAdapter, "ocr2", 5, uint64(sethClient.ChainID), false, testData.chainReaderAndCodec) //nolint:gosec // G115 false positive + err = actions.CreateOCRv2JobsLocal(aggregatorContracts, bootstrapNode, workerNodes, testEnv.MockAdapter, "ocr2", 5, uint64(sethClient.ChainID), false, testData.chainReaderAndCodec) require.NoError(t, err, "Error creating OCRv2 jobs") if !config.OCR2.UseExistingOffChainAggregatorsContracts() || (config.OCR2.UseExistingOffChainAggregatorsContracts() && config.OCR2.ConfigureExistingOffChainAggregatorsContracts()) { @@ -230,150 +221,33 @@ func prepareORCv2SmokeTestEnv(t *testing.T, testData ocr2test, l zerolog.Logger, } func assertCorrectNodeConfiguration(t *testing.T, l zerolog.Logger, totalNodeCount int, testData ocr2test, testEnv *test_env.CLClusterTestEnv) { - l.Info().Msg("Checking if all nodes have correct plugin configuration applied") - - // we have to use gomega here, because sometimes there's a delay in the logs being written (especially in the CI) - // and this check fails on the first execution, and we don't want to add any hardcoded sleeps - - gom := gomega.NewGomegaWithT(t) - gom.Eventually(func(g gomega.Gomega) { - allNodesHaveCorrectConfig := false - - var expectedPatterns []string - expectedNodeCount := totalNodeCount - 1 - - if testData.env[string(env.MedianPlugin.Cmd)] != "" { - expectedPatterns = append(expectedPatterns, `Registered loopp.*OCR2.*Median.*`) - } - - if testData.chainReaderAndCodec { - expectedPatterns = append(expectedPatterns, `relayConfig.chainReader`) - } else { - expectedPatterns = append(expectedPatterns, "ChainReader missing from RelayConfig; falling back to internal MedianContract") - } - - logFilePaths := make(map[string]string) - tempLogsDir := os.TempDir() - - var nodesToInclude []string - for i := 1; i < totalNodeCount; i++ { - nodesToInclude = append(nodesToInclude, testEnv.ClCluster.Nodes[i].ContainerName+".log") - } - - // save all log files in temp dir - loggingErr := ctf_docker.WriteAllContainersLogs(l, tempLogsDir) - if loggingErr != nil { - l.Debug().Err(loggingErr).Msg("Error writing all containers logs. Trying again...") - - // try again - return - } - - var fileNameIncludeFilter = func(name string) bool { - for _, n := range nodesToInclude { - if strings.EqualFold(name, n) { - return true - } - } - return false - } - - // find log files for CL nodes - fileWalkErr := filepath.Walk(tempLogsDir, func(path string, info os.FileInfo, err error) error { - if err != nil { - if os.IsPermission(err) { - return nil - } - return err - } - if !info.IsDir() && fileNameIncludeFilter(info.Name()) { - absPath, err := filepath.Abs(path) - if err != nil { - return err - } - logFilePaths[strings.TrimSuffix(info.Name(), ".log")] = absPath - } - return nil - }) - - if fileWalkErr != nil { - l.Debug().Err(fileWalkErr).Msg("Error walking through log files. Trying again...") - - return - } - - if len(logFilePaths) != expectedNodeCount { - l.Debug().Msgf("Expected number of log files to match number of nodes (excluding bootstrap node). Expected: %d, Found: %d. Trying again...", expectedNodeCount, len(logFilePaths)) - - return - } - - // search for expected pattern in log file - var searchForLineInFile = func(filePath string, pattern string) bool { - file, fileErr := os.Open(filePath) - if fileErr != nil { - return false - } - - defer func(file *os.File) { - _ = file.Close() - }(file) - - scanner := bufio.NewScanner(file) - scanner.Split(bufio.ScanLines) - pc := regexp.MustCompile(pattern) + expectedNodesWithConfiguration := totalNodeCount - 1 // minus bootstrap node + var expectedPatterns []string - for scanner.Scan() { - jsonLogLine := scanner.Text() - if pc.MatchString(jsonLogLine) { - return true - } - - } - return false - } - - wg := sync.WaitGroup{} - resultsCh := make(chan map[string][]string, len(logFilePaths)) - - // process all logs in parallel - for nodeName, logFilePath := range logFilePaths { - wg.Add(1) - filePath := logFilePath - go func() { - defer wg.Done() - var patternsFound []string - for _, pattern := range expectedPatterns { - found := searchForLineInFile(filePath, pattern) - if found { - patternsFound = append(patternsFound, pattern) - } - } - resultsCh <- map[string][]string{nodeName: patternsFound} - }() - } + if testData.env[string(env.MedianPlugin.Cmd)] != "" { + expectedPatterns = append(expectedPatterns, "Registered loopp.*OCR2.*Median.*") + } - wg.Wait() - close(resultsCh) + if testData.chainReaderAndCodec { + expectedPatterns = append(expectedPatterns, "relayConfig\\.chainReader") + } else { + expectedPatterns = append(expectedPatterns, "ChainReader missing from RelayConfig; falling back to internal MedianContract") + } + // make sure that nodes are correctly configured by scanning the logs + for _, pattern := range expectedPatterns { + l.Info().Msgf("Checking for pattern: '%s' in CL node logs", pattern) var correctlyConfiguredNodes []string - var incorrectlyConfiguredNodes []string - - // check results - for result := range resultsCh { - for nodeName, patternsFound := range result { - if len(patternsFound) == len(expectedPatterns) { - correctlyConfiguredNodes = append(correctlyConfiguredNodes, nodeName) - } else { - incorrectlyConfiguredNodes = append(incorrectlyConfiguredNodes, nodeName) - } + for i := 1; i < len(testEnv.ClCluster.Nodes); i++ { + logProcessor, processFn, err := logstream.GetRegexMatchingProcessor(testEnv.LogStream, pattern) + require.NoError(t, err, "Error getting regex matching processor") + + count, err := logProcessor.ProcessContainerLogs(testEnv.ClCluster.Nodes[i].ContainerName, processFn) + require.NoError(t, err, "Error processing container logs") + if *count >= 1 { + correctlyConfiguredNodes = append(correctlyConfiguredNodes, testEnv.ClCluster.Nodes[i].ContainerName) } } - - allNodesHaveCorrectConfig = len(correctlyConfiguredNodes) == expectedNodeCount - - g.Expect(allNodesHaveCorrectConfig).To(gomega.BeTrue(), "%d nodes' logs were missing expected plugin configuration entries. Correctly configured nodes: %s. Nodes with missing configuration: %s. Expected log patterns: %s", expectedNodeCount-len(correctlyConfiguredNodes), strings.Join(correctlyConfiguredNodes, ", "), strings.Join(incorrectlyConfiguredNodes, ", "), strings.Join(expectedPatterns, ", ")) - }, "1m", "10s").Should(gomega.Succeed()) - - l.Info().Msg("All nodes have correct plugin configuration applied") + require.Equal(t, expectedNodesWithConfiguration, len(correctlyConfiguredNodes), "expected correct plugin config to be applied to %d cl-nodes, but only following ones had it: %s; regexp used: %s", expectedNodesWithConfiguration, strings.Join(correctlyConfiguredNodes, ", "), string(pattern)) + } } diff --git a/integration-tests/smoke/vrfv2_test.go b/integration-tests/smoke/vrfv2_test.go index 1e2c4711527..3c9beec5ddb 100644 --- a/integration-tests/smoke/vrfv2_test.go +++ b/integration-tests/smoke/vrfv2_test.go @@ -2,7 +2,6 @@ package smoke import ( "fmt" - "math" "math/big" "os" "strconv" @@ -168,7 +167,7 @@ func TestVRFv2Basic(t *testing.T) { require.True(t, status.Fulfilled) l.Info().Bool("Fulfilment Status", status.Fulfilled).Msg("Random Words Request Fulfilment Status") - require.Equal(t, int(*configCopy.VRFv2.General.NumberOfWords), len(status.RandomWords)) + require.Equal(t, *configCopy.VRFv2.General.NumberOfWords, uint32(len(status.RandomWords))) for _, w := range status.RandomWords { l.Info().Str("Output", w.String()).Msg("Randomness fulfilled") require.Equal(t, 1, w.Cmp(big.NewInt(0)), "Expected the VRF job give an answer bigger than 0") @@ -323,7 +322,7 @@ func TestVRFv2Basic(t *testing.T) { require.Equal(t, expectedWrapperConsumerJuelsBalance, wrapperConsumerJuelsBalanceAfterRequest) // Check random word count - require.Equal(t, int(*configCopy.VRFv2.General.NumberOfWords), len(consumerStatus.RandomWords)) + require.Equal(t, *configCopy.VRFv2.General.NumberOfWords, uint32(len(consumerStatus.RandomWords))) for _, w := range consumerStatus.RandomWords { l.Info().Str("Output", w.String()).Msg("Randomness fulfilled") require.Equal(t, 1, w.Cmp(big.NewInt(0)), "Expected the VRF job give an answer bigger than 0") @@ -774,7 +773,7 @@ func TestVRFOwner(t *testing.T) { require.True(t, status.Fulfilled) l.Info().Bool("Fulfilment Status", status.Fulfilled).Msg("Random Words Request Fulfilment Status") - require.Equal(t, int(*configCopy.VRFv2.General.NumberOfWords), len(status.RandomWords)) + require.Equal(t, *configCopy.VRFv2.General.NumberOfWords, uint32(len(status.RandomWords))) for _, w := range status.RandomWords { l.Info().Str("Output", w.String()).Msg("Randomness fulfilled") require.Equal(t, 1, w.Cmp(big.NewInt(0)), "Expected the VRF job give an answer bigger than 0") @@ -944,18 +943,14 @@ func TestVRFV2WithBHS(t *testing.T) { ) require.NoError(t, err, "error requesting randomness") randRequestBlockNumber := randomWordsRequestedEvent.Raw.BlockNumber - _, err = vrfContracts.BHS.GetBlockHash(testcontext.Get(t), new(big.Int).SetUint64(randRequestBlockNumber)) + _, err = vrfContracts.BHS.GetBlockHash(testcontext.Get(t), big.NewInt(int64(randRequestBlockNumber))) require.Error(t, err, "error not occurred when getting blockhash for a blocknumber which was not stored in BHS contract") - blocks := *configCopy.VRFv2.General.BHSJobWaitBlocks - if blocks < 0 { - t.Fatalf("negative blocks: %d", blocks) - } var wg sync.WaitGroup wg.Add(1) _, err = actions.WaitForBlockNumberToBe( testcontext.Get(t), - randRequestBlockNumber+uint64(blocks), + randRequestBlockNumber+uint64(*configCopy.VRFv2.General.BHSJobWaitBlocks), sethClient, &wg, nil, @@ -1001,7 +996,7 @@ func TestVRFV2WithBHS(t *testing.T) { } var randRequestBlockHash [32]byte gom.Eventually(func(g gomega.Gomega) { - randRequestBlockHash, err = vrfContracts.BHS.GetBlockHash(testcontext.Get(t), new(big.Int).SetUint64(randRequestBlockNumber)) + randRequestBlockHash, err = vrfContracts.BHS.GetBlockHash(testcontext.Get(t), big.NewInt(int64(randRequestBlockNumber))) g.Expect(err).ShouldNot(gomega.HaveOccurred(), "error getting blockhash for a blocknumber which was stored in BHS contract") }, "2m", "1s").Should(gomega.Succeed()) l.Info(). @@ -1273,9 +1268,6 @@ func TestVRFv2BatchFulfillmentEnabledDisabled(t *testing.T) { vrfcommon.LogSubDetails(l, subscription, strconv.FormatUint(subID, 10), vrfContracts.CoordinatorV2) subIDsForCancellingAfterTest = append(subIDsForCancellingAfterTest, subIDs...) - if randRequestCount > math.MaxUint16 { - t.Fatalf("rand request count overflows uint16: %d", randRequestCount) - } configCopy.VRFv2.General.RandomnessRequestCountPerRequest = ptr.Ptr(uint16(randRequestCount)) // test and assert @@ -1397,10 +1389,7 @@ func TestVRFv2BatchFulfillmentEnabledDisabled(t *testing.T) { vrfcommon.LogSubDetails(l, subscription, strconv.FormatUint(subID, 10), vrfContracts.CoordinatorV2) subIDsForCancellingAfterTest = append(subIDsForCancellingAfterTest, subIDs...) - if randRequestCount > math.MaxUint16 { - t.Fatalf("rand request count overflows uint16: %d", randRequestCount) - } - configCopy.VRFv2.General.RandomnessRequestCountPerRequest = ptr.Ptr(uint16(randRequestCount)) //nolint:gosec // G115 false positive + configCopy.VRFv2.General.RandomnessRequestCountPerRequest = ptr.Ptr(uint16(randRequestCount)) // test and assert _, randomWordsFulfilledEvent, err := vrfv2.RequestRandomnessAndWaitForFulfillment( diff --git a/integration-tests/smoke/vrfv2plus_test.go b/integration-tests/smoke/vrfv2plus_test.go index a57230f1a0c..df0917fd4fb 100644 --- a/integration-tests/smoke/vrfv2plus_test.go +++ b/integration-tests/smoke/vrfv2plus_test.go @@ -2,7 +2,6 @@ package smoke import ( "fmt" - "math" "math/big" "os" "strings" @@ -157,7 +156,7 @@ func TestVRFv2Plus(t *testing.T) { require.True(t, status.Fulfilled) l.Info().Bool("Fulfilment Status", status.Fulfilled).Msg("Random Words Request Fulfilment Status") - require.Equal(t, int(*configCopy.VRFv2Plus.General.NumberOfWords), len(status.RandomWords)) + require.Equal(t, *configCopy.VRFv2Plus.General.NumberOfWords, uint32(len(status.RandomWords))) for _, w := range status.RandomWords { l.Info().Str("Output", w.String()).Msg("Randomness fulfilled") require.Equal(t, 1, w.Cmp(big.NewInt(0)), "Expected the VRF job give an answer bigger than 0") @@ -220,7 +219,7 @@ func TestVRFv2Plus(t *testing.T) { require.True(t, status.Fulfilled) l.Info().Bool("Fulfilment Status", status.Fulfilled).Msg("Random Words Request Fulfilment Status") - require.Equal(t, int(*testConfig.NumberOfWords), len(status.RandomWords)) + require.Equal(t, *testConfig.NumberOfWords, uint32(len(status.RandomWords))) for _, w := range status.RandomWords { l.Info().Str("Output", w.String()).Msg("Randomness fulfilled") require.Equal(t, 1, w.Cmp(big.NewInt(0)), "Expected the VRF job give an answer bigger than 0") @@ -328,7 +327,7 @@ func TestVRFv2Plus(t *testing.T) { //require.Equal(t, 1, consumerStatus.Paid.Cmp(randomWordsFulfilledEvent.Payment), "Expected Consumer contract pay more than the Coordinator Sub") vrfcommon.LogFulfillmentDetailsLinkBilling(l, wrapperConsumerJuelsBalanceBeforeRequest, wrapperConsumerJuelsBalanceAfterRequest, consumerStatus, randomWordsFulfilledEvent) - require.Equal(t, int(*testConfig.NumberOfWords), len(consumerStatus.RandomWords)) + require.Equal(t, *testConfig.NumberOfWords, uint32(len(consumerStatus.RandomWords))) for _, w := range consumerStatus.RandomWords { l.Info().Str("Output", w.String()).Msg("Randomness fulfilled") require.Equal(t, 1, w.Cmp(big.NewInt(0)), "Expected the VRF job give an answer bigger than 0") @@ -377,7 +376,7 @@ func TestVRFv2Plus(t *testing.T) { //require.Equal(t, 1, consumerStatus.Paid.Cmp(randomWordsFulfilledEvent.Payment), "Expected Consumer contract pay more than the Coordinator Sub") vrfcommon.LogFulfillmentDetailsNativeBilling(l, wrapperConsumerBalanceBeforeRequestWei, wrapperConsumerBalanceAfterRequestWei, consumerStatus, randomWordsFulfilledEvent) - require.Equal(t, int(*testConfig.NumberOfWords), len(consumerStatus.RandomWords)) + require.Equal(t, *testConfig.NumberOfWords, uint32(len(consumerStatus.RandomWords))) for _, w := range consumerStatus.RandomWords { l.Info().Str("Output", w.String()).Msg("Randomness fulfilled") require.Equal(t, 1, w.Cmp(big.NewInt(0)), "Expected the VRF job give an answer bigger than 0") @@ -959,7 +958,7 @@ func TestVRFv2PlusMigration(t *testing.T) { newCoordinator, err := contracts.DeployVRFCoordinatorV2PlusUpgradedVersion(sethClient, vrfContracts.BHS.Address()) require.NoError(t, err, "error deploying VRF CoordinatorV2PlusUpgradedVersion") - _, err = vrfv2plus.VRFV2PlusUpgradedVersionRegisterProvingKey(vrfKey.VRFKey, newCoordinator, assets.GWei(*configCopy.VRFv2Plus.General.CLNodeMaxGasPriceGWei).ToInt().Uint64()) + _, err = vrfv2plus.VRFV2PlusUpgradedVersionRegisterProvingKey(vrfKey.VRFKey, newCoordinator, uint64(assets.GWei(*configCopy.VRFv2Plus.General.CLNodeMaxGasPriceGWei).Int64())) require.NoError(t, err, fmt.Errorf("%s, err: %w", vrfcommon.ErrRegisteringProvingKey, err)) err = newCoordinator.SetConfig( @@ -1128,7 +1127,7 @@ func TestVRFv2PlusMigration(t *testing.T) { newCoordinator, err := contracts.DeployVRFCoordinatorV2PlusUpgradedVersion(sethClient, vrfContracts.BHS.Address()) require.NoError(t, err, "error deploying VRF CoordinatorV2PlusUpgradedVersion") - _, err = vrfv2plus.VRFV2PlusUpgradedVersionRegisterProvingKey(vrfKey.VRFKey, newCoordinator, assets.GWei(*configCopy.VRFv2Plus.General.CLNodeMaxGasPriceGWei).ToInt().Uint64()) + _, err = vrfv2plus.VRFV2PlusUpgradedVersionRegisterProvingKey(vrfKey.VRFKey, newCoordinator, uint64(assets.GWei(*configCopy.VRFv2Plus.General.CLNodeMaxGasPriceGWei).Int64())) require.NoError(t, err, fmt.Errorf("%s, err: %w", vrfcommon.ErrRegisteringProvingKey, err)) err = newCoordinator.SetConfig( @@ -1346,13 +1345,13 @@ func TestVRFV2PlusWithBHS(t *testing.T) { var wg sync.WaitGroup wg.Add(1) - const waitForNumberOfBlocks = 257 + waitForNumberOfBlocks := 257 desiredBlockNumberReached := make(chan bool) go func() { //Wait at least 256 blocks _, err = actions.WaitForBlockNumberToBe( testcontext.Get(t), - randRequestBlockNumber+waitForNumberOfBlocks, + randRequestBlockNumber+uint64(waitForNumberOfBlocks), sethClient, &wg, desiredBlockNumberReached, @@ -1397,7 +1396,7 @@ func TestVRFV2PlusWithBHS(t *testing.T) { require.True(t, status.Fulfilled) l.Info().Bool("Fulfilment Status", status.Fulfilled).Msg("Random Words Request Fulfilment Status") - randRequestBlockHash, err := vrfContracts.BHS.GetBlockHash(testcontext.Get(t), new(big.Int).SetUint64(randRequestBlockNumber)) + randRequestBlockHash, err := vrfContracts.BHS.GetBlockHash(testcontext.Get(t), big.NewInt(int64(randRequestBlockNumber))) require.NoError(t, err, "error getting blockhash for a blocknumber which was stored in BHS contract") l.Info(). @@ -1444,17 +1443,14 @@ func TestVRFV2PlusWithBHS(t *testing.T) { ) require.NoError(t, err, "error requesting randomness") randRequestBlockNumber := randomWordsRequestedEvent.Raw.BlockNumber - _, err = vrfContracts.BHS.GetBlockHash(testcontext.Get(t), new(big.Int).SetUint64(randRequestBlockNumber)) + _, err = vrfContracts.BHS.GetBlockHash(testcontext.Get(t), big.NewInt(int64(randRequestBlockNumber))) require.Error(t, err, "error not occurred when getting blockhash for a blocknumber which was not stored in BHS contract") - if *configCopy.VRFv2Plus.General.BHSJobWaitBlocks < 0 { - t.Fatalf("negative job wait blocks: %d", *configCopy.VRFv2Plus.General.BHSJobWaitBlocks) - } var wg sync.WaitGroup wg.Add(1) _, err = actions.WaitForBlockNumberToBe( testcontext.Get(t), - randRequestBlockNumber+uint64(*configCopy.VRFv2Plus.General.BHSJobWaitBlocks)+10, //nolint:gosec // G115 false positive + randRequestBlockNumber+uint64(*configCopy.VRFv2Plus.General.BHSJobWaitBlocks+10), sethClient, &wg, nil, @@ -1501,7 +1497,7 @@ func TestVRFV2PlusWithBHS(t *testing.T) { var randRequestBlockHash [32]byte gom.Eventually(func(g gomega.Gomega) { - randRequestBlockHash, err = vrfContracts.BHS.GetBlockHash(testcontext.Get(t), new(big.Int).SetUint64(randRequestBlockNumber)) + randRequestBlockHash, err = vrfContracts.BHS.GetBlockHash(testcontext.Get(t), big.NewInt(int64(randRequestBlockNumber))) g.Expect(err).ShouldNot(gomega.HaveOccurred(), "error getting blockhash for a blocknumber which was stored in BHS contract") }, "2m", "1s").Should(gomega.Succeed()) l.Info(). @@ -1646,7 +1642,7 @@ func TestVRFV2PlusWithBHF(t *testing.T) { } require.True(t, batchBHSTxFound) - randRequestBlockHash, err := vrfContracts.BHS.GetBlockHash(testcontext.Get(t), new(big.Int).SetUint64(randRequestBlockNumber)) + randRequestBlockHash, err := vrfContracts.BHS.GetBlockHash(testcontext.Get(t), big.NewInt(int64(randRequestBlockNumber))) require.NoError(t, err, "error getting blockhash for a blocknumber which was stored in BHS contract") l.Info(). @@ -2152,9 +2148,6 @@ func TestVRFv2PlusBatchFulfillmentEnabledDisabled(t *testing.T) { vrfcommon.LogSubDetails(l, subscription, subID.String(), vrfContracts.CoordinatorV2Plus) subIDsForCancellingAfterTest = append(subIDsForCancellingAfterTest, subIDs...) - if randRequestCount > math.MaxUint16 { - t.Fatalf("rand request count overflows uint16: %d", randRequestCount) - } configCopy.VRFv2Plus.General.RandomnessRequestCountPerRequest = ptr.Ptr(uint16(randRequestCount)) // test and assert @@ -2269,9 +2262,6 @@ func TestVRFv2PlusBatchFulfillmentEnabledDisabled(t *testing.T) { vrfcommon.LogSubDetails(l, subscription, subID.String(), vrfContracts.CoordinatorV2Plus) subIDsForCancellingAfterTest = append(subIDsForCancellingAfterTest, subIDs...) - if randRequestCount > math.MaxUint16 { - t.Fatalf("rand request count overflows uint16: %d", randRequestCount) - } configCopy.VRFv2Plus.General.RandomnessRequestCountPerRequest = ptr.Ptr(uint16(randRequestCount)) // test and assert diff --git a/integration-tests/testconfig/automation/example.toml b/integration-tests/testconfig/automation/example.toml index c239e5a3966..3bbe78d693d 100644 --- a/integration-tests/testconfig/automation/example.toml +++ b/integration-tests/testconfig/automation/example.toml @@ -7,6 +7,14 @@ version="2.7.0" # if set to true will save logs even if test did not fail test_log_collect=false +[Logging.LogStream] +# supported targets: file, loki, in-memory. if empty no logs will be persistet +log_targets=["file"] +# context timeout for starting log producer and also time-frame for requesting logs +log_producer_timeout="10s" +# number of retries before log producer gives up and stops listening to logs +log_producer_retry_limit=10 + # if you want to use polygon_mumbial [Network] selected_networks=["polygon_mumbai"] diff --git a/integration-tests/testconfig/ccip/ccip.toml b/integration-tests/testconfig/ccip/ccip.toml index 3f4ba43c48c..5ccda6ab4e3 100644 --- a/integration-tests/testconfig/ccip/ccip.toml +++ b/integration-tests/testconfig/ccip/ccip.toml @@ -9,17 +9,8 @@ selected_networks = ['SIMULATED_1', 'SIMULATED_2'] evm_name = 'chain-1337' evm_chain_id = 1337 evm_keys = [ - "59c6995e998f97a5a0044966f0945389dc9e86dae88c7a8412f4603b6b78690d", "ac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80", - "5de4111afa1a4b94908f83103eb1f1706367c2e68ca870fc3fb9a804cdab365a", - "7c852118294e51e653712a81e05800f419141751be58f605c371e15141b007a6", - "47e179ec197488593b187f80a00eb0da91f1b9d0b13f8733639f19c30a34926a", - "8b3a350cf5c34c9194ca85829a2df0ec3153be0318b5e2d3348e872092edffba", - "92db14e403b83dfe3df233f83dfa3a0d7096f21ca9b0d6d6b8d88b2b4ec1564e", - "4bbbf85ce3377467afe5d46f804f221813b2bb87f24d81f60f1fcdbf7cbf4356", - "dbda1821b80551c9d65939329250298aa3472ba22feea921c0cf5d620ea67b97", - "2a871d0798f97d79848a013d4936a73bf4cc922c825d33c1cf7073dff6d409c6", - "f214f2b2cd398c806f84e317254e0f0b801d0643303237d97a22a48e01628897" + "59c6995e998f97a5a0044966f0945389dc9e86dae88c7a8412f4603b6b78690d", ] evm_simulated = true client_implementation = 'Ethereum' @@ -37,41 +28,6 @@ evm_chain_id = 2337 evm_keys = [ "59c6995e998f97a5a0044966f0945389dc9e86dae88c7a8412f4603b6b78690d", "ac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80", - "5de4111afa1a4b94908f83103eb1f1706367c2e68ca870fc3fb9a804cdab365a", - "7c852118294e51e653712a81e05800f419141751be58f605c371e15141b007a6", - "47e179ec197488593b187f80a00eb0da91f1b9d0b13f8733639f19c30a34926a", - "8b3a350cf5c34c9194ca85829a2df0ec3153be0318b5e2d3348e872092edffba", - "92db14e403b83dfe3df233f83dfa3a0d7096f21ca9b0d6d6b8d88b2b4ec1564e", - "4bbbf85ce3377467afe5d46f804f221813b2bb87f24d81f60f1fcdbf7cbf4356", - "dbda1821b80551c9d65939329250298aa3472ba22feea921c0cf5d620ea67b97", - "2a871d0798f97d79848a013d4936a73bf4cc922c825d33c1cf7073dff6d409c6", - "f214f2b2cd398c806f84e317254e0f0b801d0643303237d97a22a48e01628897" -] -evm_simulated = true -client_implementation = 'Ethereum' -evm_chainlink_transaction_limit = 50000 -evm_transaction_timeout = '2m' -evm_minimum_confirmations = 1 -evm_gas_estimation_buffer = 1000 -evm_supports_eip1559 = true -evm_default_gas_limit = 6000000 -evm_finality_depth = 1 - -[Network.EVMNetworks.SIMULATED_3] -evm_name = 'chain-3337' -evm_chain_id = 3337 -evm_keys = [ - "59c6995e998f97a5a0044966f0945389dc9e86dae88c7a8412f4603b6b78690d", - "ac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80", - "5de4111afa1a4b94908f83103eb1f1706367c2e68ca870fc3fb9a804cdab365a", - "7c852118294e51e653712a81e05800f419141751be58f605c371e15141b007a6", - "47e179ec197488593b187f80a00eb0da91f1b9d0b13f8733639f19c30a34926a", - "8b3a350cf5c34c9194ca85829a2df0ec3153be0318b5e2d3348e872092edffba", - "92db14e403b83dfe3df233f83dfa3a0d7096f21ca9b0d6d6b8d88b2b4ec1564e", - "4bbbf85ce3377467afe5d46f804f221813b2bb87f24d81f60f1fcdbf7cbf4356", - "dbda1821b80551c9d65939329250298aa3472ba22feea921c0cf5d620ea67b97", - "2a871d0798f97d79848a013d4936a73bf4cc922c825d33c1cf7073dff6d409c6", - "f214f2b2cd398c806f84e317254e0f0b801d0643303237d97a22a48e01628897" ] evm_simulated = true client_implementation = 'Ethereum' @@ -171,15 +127,6 @@ chain_id = 1337 addresses_to_fund = [ "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", "0x70997970C51812dc3A010C7d01b50e0d17dc79C8", - "0x3c44cdddb6a900fa2b585dd299e03d12fa4293bc", - "0x90f79bf6eb2c4f870365e785982e1f101e93b906", - "0x15d34aaf54267db7d7c367839aaf71a00a2c6a65", - "0x9965507d1a55bcc2695c58ba16fb37d819b0a4dc", - "0x976ea74026e726554db657fa54763abd0c3a0aa9", - "0x14dc79964da2c08b23698b3d3cc7ca32193d9955", - "0x23618e81e3f5cdf7f54c3d65f7fbc0abf5b21e8f", - "0xa0ee7a142d267c1f36714e4a8f75612f20a79720", - "0xBcd4042DE499D14e55001CcbB24a551F3b954096" ] @@ -202,41 +149,8 @@ chain_id = 2337 addresses_to_fund = [ "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", "0x70997970C51812dc3A010C7d01b50e0d17dc79C8", - "0x3c44cdddb6a900fa2b585dd299e03d12fa4293bc", - "0x90f79bf6eb2c4f870365e785982e1f101e93b906", - "0x15d34aaf54267db7d7c367839aaf71a00a2c6a65", - "0x9965507d1a55bcc2695c58ba16fb37d819b0a4dc", - "0x976ea74026e726554db657fa54763abd0c3a0aa9", - "0x14dc79964da2c08b23698b3d3cc7ca32193d9955", - "0x23618e81e3f5cdf7f54c3d65f7fbc0abf5b21e8f", - "0xa0ee7a142d267c1f36714e4a8f75612f20a79720", - "0xBcd4042DE499D14e55001CcbB24a551F3b954096" -] - -[CCIP.PrivateEthereumNetworks.SIMULATED_3] -ethereum_version = "eth1" -execution_layer = "geth" - -[CCIP.PrivateEthereumNetworks.SIMULATED_3.EthereumChainConfig] -seconds_per_slot = 3 -slots_per_epoch = 2 -genesis_delay = 15 -validator_count = 4 -chain_id = 3337 -addresses_to_fund = [ - "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", - "0x70997970C51812dc3A010C7d01b50e0d17dc79C8", - "0x3c44cdddb6a900fa2b585dd299e03d12fa4293bc", - "0x90f79bf6eb2c4f870365e785982e1f101e93b906", - "0x15d34aaf54267db7d7c367839aaf71a00a2c6a65", - "0x9965507d1a55bcc2695c58ba16fb37d819b0a4dc", - "0x976ea74026e726554db657fa54763abd0c3a0aa9", - "0x14dc79964da2c08b23698b3d3cc7ca32193d9955", - "0x23618e81e3f5cdf7f54c3d65f7fbc0abf5b21e8f", - "0xa0ee7a142d267c1f36714e4a8f75612f20a79720", - "0xBcd4042DE499D14e55001CcbB24a551F3b954096" ] [Seth] # Seth specific configuration, no need for generating ephemeral addresses for ccip-tests. -ephemeral_addresses_number = 0 +ephemeral_addresses_number = 0 \ No newline at end of file diff --git a/integration-tests/testconfig/ccip/config.go b/integration-tests/testconfig/ccip/config.go index 70c850fd591..560c816d85f 100644 --- a/integration-tests/testconfig/ccip/config.go +++ b/integration-tests/testconfig/ccip/config.go @@ -2,28 +2,25 @@ package ccip import ( "fmt" - "math" "strconv" "github.com/AlekSi/pointer" chainselectors "github.com/smartcontractkit/chain-selectors" + "github.com/smartcontractkit/chainlink-testing-framework/lib/blockchain" + ctfconfig "github.com/smartcontractkit/chainlink-testing-framework/lib/config" "github.com/smartcontractkit/chainlink/deployment/environment/nodeclient" ) const ( - E2E_JD_IMAGE = "E2E_JD_IMAGE" - E2E_JD_VERSION = "E2E_JD_VERSION" - E2E_JD_GRPC = "E2E_JD_GRPC" - E2E_JD_WSRPC = "E2E_JD_WSRPC" - DEFAULT_DB_NAME = "JD_DB" - DEFAULT_DB_VERSION = "14.1" - E2E_RMN_RAGEPROXY_IMAGE = "E2E_RMN_RAGEPROXY_IMAGE" - E2E_RMN_RAGEPROXY_VERSION = "E2E_RMN_RAGEPROXY_VERSION" - E2E_RMN_AFN2PROXY_IMAGE = "E2E_RMN_AFN2PROXY_IMAGE" - E2E_RMN_AFN2PROXY_VERSION = "E2E_RMN_AFN2PROXY_VERSION" + E2E_JD_IMAGE = "E2E_JD_IMAGE" + E2E_JD_VERSION = "E2E_JD_VERSION" + E2E_JD_GRPC = "E2E_JD_GRPC" + E2E_JD_WSRPC = "E2E_JD_WSRPC" + DEFAULT_DB_NAME = "JD_DB" + DEFAULT_DB_VERSION = "14.1" ) var ( @@ -48,38 +45,6 @@ type RMNConfig struct { AFNVersion *string `toml:",omitempty"` } -func (r *RMNConfig) GetProxyImage() string { - image := pointer.GetString(r.ProxyImage) - if image == "" { - return ctfconfig.MustReadEnvVar_String(E2E_RMN_RAGEPROXY_IMAGE) - } - return image -} - -func (r *RMNConfig) GetProxyVersion() string { - version := pointer.GetString(r.ProxyVersion) - if version == "" { - return ctfconfig.MustReadEnvVar_String(E2E_RMN_RAGEPROXY_VERSION) - } - return version -} - -func (r *RMNConfig) GetAFN2ProxyImage() string { - image := pointer.GetString(r.AFNImage) - if image == "" { - return ctfconfig.MustReadEnvVar_String(E2E_RMN_AFN2PROXY_IMAGE) - } - return image -} - -func (r *RMNConfig) GetAFN2ProxyVersion() string { - version := pointer.GetString(r.AFNVersion) - if version == "" { - return ctfconfig.MustReadEnvVar_String(E2E_RMN_AFN2PROXY_VERSION) - } - return version -} - type NodeConfig struct { NoOfPluginNodes *int `toml:",omitempty"` NoOfBootstraps *int `toml:",omitempty"` @@ -145,68 +110,48 @@ func (o *JDConfig) GetJDDBVersion() string { } func (o *Config) Validate() error { - var chainIds []int64 - for _, net := range o.PrivateEthereumNetworks { - if net.EthereumChainConfig.ChainID < 0 { - return fmt.Errorf("negative chain ID found for network %d", net.EthereumChainConfig.ChainID) - } - chainIds = append(chainIds, int64(net.EthereumChainConfig.ChainID)) - } + return nil +} + +func (o *Config) GetHomeChainSelector(evmNetworks []blockchain.EVMNetwork) (uint64, error) { homeChainSelector, err := strconv.ParseUint(pointer.GetString(o.HomeChainSelector), 10, 64) if err != nil { - return err + return 0, err } - isValid, err := IsSelectorValid(homeChainSelector, chainIds) + isValid, err := IsSelectorValid(homeChainSelector, evmNetworks) if err != nil { - return err + return 0, err } if !isValid { - return ErrInvalidHomeChainSelector + return 0, ErrInvalidHomeChainSelector } + return homeChainSelector, nil +} + +func (o *Config) GetFeedChainSelector(evmNetworks []blockchain.EVMNetwork) (uint64, error) { feedChainSelector, err := strconv.ParseUint(pointer.GetString(o.FeedChainSelector), 10, 64) if err != nil { - return err + return 0, err } - isValid, err = IsSelectorValid(feedChainSelector, chainIds) + isValid, err := IsSelectorValid(feedChainSelector, evmNetworks) if err != nil { - return err + return 0, err } if !isValid { - return ErrInvalidFeedChainSelector + return 0, ErrInvalidFeedChainSelector } - return nil + return feedChainSelector, nil } -func (o *Config) GetHomeChainSelector() uint64 { - selector, _ := strconv.ParseUint(pointer.GetString(o.HomeChainSelector), 10, 64) - return selector -} - -func (o *Config) GetFeedChainSelector() uint64 { - selector, _ := strconv.ParseUint(pointer.GetString(o.FeedChainSelector), 10, 64) - return selector -} - -func IsSelectorValid(selector uint64, chainIds []int64) (bool, error) { +func IsSelectorValid(selector uint64, evmNetworks []blockchain.EVMNetwork) (bool, error) { chainId, err := chainselectors.ChainIdFromSelector(selector) if err != nil { return false, err } - - for _, cID := range chainIds { - if isEqualUint64AndInt64(chainId, cID) { + for _, net := range evmNetworks { + if net.ChainID == int64(chainId) { return true, nil } } return false, nil } - -func isEqualUint64AndInt64(u uint64, i int64) bool { - if i < 0 { - return false // uint64 cannot be equal to a negative int64 - } - if u > math.MaxInt64 { - return false // uint64 cannot be equal to an int64 if it exceeds the maximum int64 value - } - return u == uint64(i) -} diff --git a/integration-tests/testconfig/ccip/overrides/sepolia_avax_binance.toml b/integration-tests/testconfig/ccip/overrides/sepolia_avax_binance.toml index 72c43b12da5..06af64d5d91 100644 --- a/integration-tests/testconfig/ccip/overrides/sepolia_avax_binance.toml +++ b/integration-tests/testconfig/ccip/overrides/sepolia_avax_binance.toml @@ -5,6 +5,10 @@ chainlink_node_funding = 2 [Logging] test_log_collect = true +[Logging.LogStream] +# supported targets: file, loki, in-memory. if empty no logs will be persisted +log_targets = ["loki"] + [Network] selected_networks = ['SEPOLIA', 'AVALANCHE_FUJI', 'BSC_TESTNET'] diff --git a/integration-tests/testconfig/default.toml b/integration-tests/testconfig/default.toml index 8180b40ae21..385d35c67cb 100644 --- a/integration-tests/testconfig/default.toml +++ b/integration-tests/testconfig/default.toml @@ -2,9 +2,22 @@ # set to true to flush logs to selected target regardless of test result; otherwise logs are only flushed if test failed test_log_collect = false +[Logging.Grafana] +base_url="https://grafana.ops.prod.cldev.sh" +base_url_github_ci="http://localhost:8080/primary" +dashboard_url="/d/ddf75041-1e39-42af-aa46-361fe4c36e9e/ci-e2e-tests-logs" + +[Logging.LogStream] +# supported targets: file, loki, in-memory. if empty no logs will be persisted +log_targets = ["file"] +# context timeout for starting log producer and also time-frame for requesting logs +log_producer_timeout = "10s" +# number of retries before log producer gives up and stops listening to logs +log_producer_retry_limit = 10 + [ChainlinkImage] # postgres version to use -postgres_version = "12.0" +postgres_version = "15.6" # chainlink image tag to use version = "2.12.0" # Set chainlink image using E2E_TEST_CHAINLINK_IMAGE env, as it is a test secret diff --git a/integration-tests/testconfig/forwarder_ocr/example.toml b/integration-tests/testconfig/forwarder_ocr/example.toml index 6ca4b8bbcc3..517a341f803 100644 --- a/integration-tests/testconfig/forwarder_ocr/example.toml +++ b/integration-tests/testconfig/forwarder_ocr/example.toml @@ -7,6 +7,33 @@ version="2.7.0" # if set to true will save logs even if test did not fail test_log_collect=false +[Logging.LogStream] +# supported targets: file, loki, in-memory. if empty no logs will be persistet +log_targets=["file"] +# context timeout for starting log producer and also time-frame for requesting logs +log_producer_timeout="10s" +# number of retries before log producer gives up and stops listening to logs +log_producer_retry_limit=10 + +[Logging.Loki] +tenant_id="tenant_id" +# full URL of Loki ingest endpoint +endpoint="https://loki.url/api/v3/push" +# currently only needed when using public instance +basic_auth_secret="loki-basic-auth" +# only needed for cloud grafana +bearer_token_secret="bearer_token" + +# LogStream will try to shorten Grafana URLs by default (if all 3 variables are set) +[Logging.Grafana] +# grafana url (trailing "/" will be stripped) +base_url="http://grafana.url" +# url of your grafana dashboard (prefix and suffix "/" are stirpped), example: /d/ad61652-2712-1722/my-dashboard +dashboard_url="/d/your-dashboard" +# Grafana dashboard uid to annotate. Find it in Dashboard Settings -> JSON Model +dashboard_uid="dashboard-uid-to-annotate" +bearer_token_secret="my-awesome-token" + # if you want to use polygon_mumbial [Network] selected_networks=["polygon_mumbai"] diff --git a/integration-tests/testconfig/forwarder_ocr2/example.toml b/integration-tests/testconfig/forwarder_ocr2/example.toml index e3fb66a0f3a..3ec3e4c690a 100644 --- a/integration-tests/testconfig/forwarder_ocr2/example.toml +++ b/integration-tests/testconfig/forwarder_ocr2/example.toml @@ -8,6 +8,33 @@ version="2.7.0" # if set to true will save logs even if test did not fail test_log_collect=false +[Logging.LogStream] +# supported targets: file, loki, in-memory. if empty no logs will be persistet +log_targets=["file"] +# context timeout for starting log producer and also time-frame for requesting logs +log_producer_timeout="10s" +# number of retries before log producer gives up and stops listening to logs +log_producer_retry_limit=10 + +[Logging.Loki] +tenant_id="tenant_id" +# full URL of Loki ingest endpoint +endpoint="https://loki.url/api/v3/push" +# currently only needed when using public instance +basic_auth_secret="loki-basic-auth" +# only needed for cloud grafana +bearer_token_secret="bearer_token" + +# LogStream will try to shorten Grafana URLs by default (if all 3 variables are set) +[Logging.Grafana] +# grafana url (trailing "/" will be stripped) +base_url="http://grafana.url" +# url of your grafana dashboard (prefix and suffix "/" are stirpped), example: /d/ad61652-2712-1722/my-dashboard +dashboard_url="/d/your-dashboard" +# Grafana dashboard uid to annotate. Find it in Dashboard Settings -> JSON Model +dashboard_uid="dashboard-uid-to-annotate" +bearer_token_secret="my-awesome-token" + # if you want to use polygon_mumbial [Network] selected_networks=["polygon_mumbai"] diff --git a/integration-tests/testconfig/functions/example.toml b/integration-tests/testconfig/functions/example.toml index ec7076fa9f9..74d931632a8 100644 --- a/integration-tests/testconfig/functions/example.toml +++ b/integration-tests/testconfig/functions/example.toml @@ -7,6 +7,14 @@ version="2.7.0" # if set to true will save logs even if test did not fail test_log_collect=false +[Logging.LogStream] +# supported targets: file, loki, in-memory. if empty no logs will be persistet +log_targets=["file"] +# context timeout for starting log producer and also time-frame for requesting logs +log_producer_timeout="10s" +# number of retries before log producer gives up and stops listening to logs +log_producer_retry_limit=10 + # if you want to use simulated network [Network] selected_networks=["polygon_mumbai"] diff --git a/integration-tests/testconfig/keeper/example.toml b/integration-tests/testconfig/keeper/example.toml index 7fe3bf26d0a..4efbf974827 100644 --- a/integration-tests/testconfig/keeper/example.toml +++ b/integration-tests/testconfig/keeper/example.toml @@ -7,6 +7,14 @@ version="2.7.0" # if set to true will save logs even if test did not fail test_log_collect=false +[Logging.LogStream] +# supported targets: file, loki, in-memory. if empty no logs will be persistet +log_targets=["file"] +# context timeout for starting log producer and also time-frame for requesting logs +log_producer_timeout="10s" +# number of retries before log producer gives up and stops listening to logs +log_producer_retry_limit=10 + # if you want to use polygon_mumbial [Network] selected_networks=["polygon_mumbai"] diff --git a/integration-tests/testconfig/log_poller/example.toml b/integration-tests/testconfig/log_poller/example.toml index b94b6e0e202..78f3b5482d9 100644 --- a/integration-tests/testconfig/log_poller/example.toml +++ b/integration-tests/testconfig/log_poller/example.toml @@ -7,6 +7,14 @@ version="2.7.0" # if set to true will save logs even if test did not fail test_log_collect=false +[Logging.LogStream] +# supported targets: file, loki, in-memory. if empty no logs will be persistet +log_targets=["file"] +# context timeout for starting log producer and also time-frame for requesting logs +log_producer_timeout="10s" +# number of retries before log producer gives up and stops listening to logs +log_producer_retry_limit=10 + # if you want to use polygon_mumbial [Network] selected_networks=["polygon_mumbai"] diff --git a/integration-tests/testconfig/node/example.toml b/integration-tests/testconfig/node/example.toml index 4635e40c037..bc5628e46b3 100644 --- a/integration-tests/testconfig/node/example.toml +++ b/integration-tests/testconfig/node/example.toml @@ -7,6 +7,14 @@ version="2.7.0" # if set to true will save logs even if test did not fail test_log_collect=false +[Logging.LogStream] +# supported targets: file, loki, in-memory. if empty no logs will be persistet +log_targets=["file"] +# context timeout for starting log producer and also time-frame for requesting logs +log_producer_timeout="10s" +# number of retries before log producer gives up and stops listening to logs +log_producer_retry_limit=10 + # if you want to use polygon_mumbial [Network] selected_networks=["polygon_mumbai"] diff --git a/integration-tests/testconfig/ocr/example.toml b/integration-tests/testconfig/ocr/example.toml index d1edd3a67fd..7c1c755567f 100644 --- a/integration-tests/testconfig/ocr/example.toml +++ b/integration-tests/testconfig/ocr/example.toml @@ -7,6 +7,33 @@ version="2.7.0" # if set to true will save logs even if test did not fail test_log_collect=false +[Logging.LogStream] +# supported targets: file, loki, in-memory. if empty no logs will be persistet +log_targets=["file"] +# context timeout for starting log producer and also time-frame for requesting logs +log_producer_timeout="10s" +# number of retries before log producer gives up and stops listening to logs +log_producer_retry_limit=10 + +[Logging.Loki] +tenant_id="tenant_id" +# full URL of Loki ingest endpoint +endpoint="https://loki.url/api/v3/push" +# currently only needed when using public instance +basic_auth_secret="loki-basic-auth" +# only needed for cloud grafana +bearer_token_secret="bearer_token" + +# LogStream will try to shorten Grafana URLs by default (if all 3 variables are set) +[Logging.Grafana] +# grafana url (trailing "/" will be stripped) +base_url="http://grafana.url" +# url of your grafana dashboard (prefix and suffix "/" are stirpped), example: /d/ad61652-2712-1722/my-dashboard +dashboard_url="/d/your-dashboard" +# Grafana dashboard uid to annotate. Find it in Dashboard Settings -> JSON Model +dashboard_uid="dashboard-uid-to-annotate" +bearer_token_secret="my-awesome-token" + # if you want to use polygon_mumbial [Network] selected_networks=["polygon_mumbai"] diff --git a/integration-tests/testconfig/ocr2/example.toml b/integration-tests/testconfig/ocr2/example.toml index 679e4527a31..319f64d2580 100644 --- a/integration-tests/testconfig/ocr2/example.toml +++ b/integration-tests/testconfig/ocr2/example.toml @@ -7,6 +7,33 @@ version="2.7.0" # if set to true will save logs even if test did not fail test_log_collect=false +[Logging.LogStream] +# supported targets: file, loki, in-memory. if empty no logs will be persistet +log_targets=["file"] +# context timeout for starting log producer and also time-frame for requesting logs +log_producer_timeout="10s" +# number of retries before log producer gives up and stops listening to logs +log_producer_retry_limit=10 + +[Logging.Loki] +tenant_id="tenant_id" +# full URL of Loki ingest endpoint +endpoint="https://loki.url/api/v3/push" +# currently only needed when using public instance +basic_auth_secret="loki-basic-auth" +# only needed for cloud grafana +bearer_token_secret="bearer_token" + +# LogStream will try to shorten Grafana URLs by default (if all 3 variables are set) +[Logging.Grafana] +# grafana url (trailing "/" will be stripped) +base_url="http://grafana.url" +# url of your grafana dashboard (prefix and suffix "/" are stirpped), example: /d/ad61652-2712-1722/my-dashboard +dashboard_url="/d/your-dashboard" +# Grafana dashboard uid to annotate. Find it in Dashboard Settings -> JSON Model +dashboard_uid="dashboard-uid-to-annotate" +bearer_token_secret="my-awesome-token" + # if you want to use polygon_mumbial [Network] selected_networks=["polygon_mumbai"] diff --git a/integration-tests/testconfig/testconfig.go b/integration-tests/testconfig/testconfig.go index 19e3f0b7ada..545818e3348 100644 --- a/integration-tests/testconfig/testconfig.go +++ b/integration-tests/testconfig/testconfig.go @@ -6,6 +6,7 @@ import ( "fmt" "math/big" "os" + "slices" "strings" "github.com/barkimedes/go-deepcopy" @@ -630,6 +631,26 @@ func (c *TestConfig) Validate() error { return fmt.Errorf("logging config must be set") } + if err := c.Logging.Validate(); err != nil { + return errors.Wrapf(err, "logging config validation failed") + } + + if c.Logging.Loki != nil { + if err := c.Logging.Loki.Validate(); err != nil { + return errors.Wrapf(err, "loki config validation failed") + } + } + + if c.Logging.LogStream != nil && slices.Contains(c.Logging.LogStream.LogTargets, "loki") { + if c.Logging.Loki == nil { + return fmt.Errorf("in order to use Loki as logging target you must set Loki config in logging config") + } + + if err := c.Logging.Loki.Validate(); err != nil { + return errors.Wrapf(err, "loki config validation failed") + } + } + if c.Pyroscope != nil { if err := c.Pyroscope.Validate(); err != nil { return errors.Wrapf(err, "pyroscope config validation failed") diff --git a/integration-tests/testconfig/testconfig_utils.go b/integration-tests/testconfig/testconfig_utils.go index 8d41ed55be9..e7b38ea3e4e 100644 --- a/integration-tests/testconfig/testconfig_utils.go +++ b/integration-tests/testconfig/testconfig_utils.go @@ -1,7 +1,6 @@ package testconfig import ( - "errors" "fmt" "os" "strings" @@ -19,12 +18,12 @@ Chainlink version must be set in toml config. ` if os.Getenv("E2E_TEST_CHAINLINK_IMAGE") == "" || os.Getenv("E2E_TEST_CHAINLINK_UPGRADE_IMAGE") == "" { - return fmt.Errorf("%s\n%s", errStr, missingImage) + return fmt.Errorf(fmt.Sprintf("%s\n%s", errStr, missingImage)) } if os.Getenv("CHAINLINK_VERSION") == "" || os.Getenv("CHAINLINK_UPGRADE_VERSION") == "" { - return fmt.Errorf("%s\n%s", errStr, missingVersion) + return fmt.Errorf(fmt.Sprintf("%s\n%s", errStr, missingVersion)) } - return errors.New(errStr) + return fmt.Errorf(errStr) } // NoSelectedNetworkInfoAsError return a helfpul error message when the no selected network info is found in TOML config. @@ -35,6 +34,8 @@ You might have used old configuration approach. If so, use TOML instead of env v Please refer to integration-tests/testconfig/README.md for more information. ` + finalErrStr := fmt.Sprintf("%s\n%s", errStr, intro) + if net := os.Getenv("SELECTED_NETWORKS"); net != "" { parts := strings.Split(net, ",") selectedNetworkStr := "[" @@ -51,10 +52,10 @@ Please refer to integration-tests/testconfig/README.md for more information. Or if you want to run your tests right now add following content to integration-tests/testconfig/overrides.toml: [Network] selected_networks=` - return fmt.Errorf("%s\n%s%s%s", errStr, intro, extraInfo, selectedNetworkStr) + finalErrStr = fmt.Sprintf("%s\n%s%s%s", errStr, intro, extraInfo, selectedNetworkStr) } - return fmt.Errorf("%s\n%s", errStr, intro) + return fmt.Errorf(finalErrStr) } func GetChainAndTestTypeSpecificConfig(testType string, product Product) (TestConfig, error) { diff --git a/integration-tests/testconfig/vrfv2/example.toml b/integration-tests/testconfig/vrfv2/example.toml index 3665c2f43cf..13af6dee620 100644 --- a/integration-tests/testconfig/vrfv2/example.toml +++ b/integration-tests/testconfig/vrfv2/example.toml @@ -7,6 +7,14 @@ version="2.7.0" # if set to true will save logs even if test did not fail test_log_collect=false +[Logging.LogStream] +# supported targets: file, loki, in-memory. if empty no logs will be persistet +log_targets=["file"] +# context timeout for starting log producer and also time-frame for requesting logs +log_producer_timeout="10s" +# number of retries before log producer gives up and stops listening to logs +log_producer_retry_limit=10 + # if you want to use polygon_mumbial [Network] selected_networks=["polygon_mumbai"] diff --git a/integration-tests/testconfig/vrfv2plus/example.toml b/integration-tests/testconfig/vrfv2plus/example.toml index a45d53f67b8..160e9ba03a9 100644 --- a/integration-tests/testconfig/vrfv2plus/example.toml +++ b/integration-tests/testconfig/vrfv2plus/example.toml @@ -7,6 +7,14 @@ version="2.7.0" # if set to true will save logs even if test did not fail test_log_collect=false +[Logging.LogStream] +# supported targets: file, loki, in-memory. if empty no logs will be persistet +log_targets=["file"] +# context timeout for starting log producer and also time-frame for requesting logs +log_producer_timeout="10s" +# number of retries before log producer gives up and stops listening to logs +log_producer_retry_limit=10 + # if you want to use polygon_mumbial [Network] selected_networks=["polygon_mumbai"] diff --git a/integration-tests/testreporters/keeper.go b/integration-tests/testreporters/keeper.go index bfa9585b8bc..dfafda06e86 100644 --- a/integration-tests/testreporters/keeper.go +++ b/integration-tests/testreporters/keeper.go @@ -4,6 +4,7 @@ import ( "encoding/csv" "encoding/json" "fmt" + "math" "os" "path/filepath" "sync" @@ -64,7 +65,7 @@ func (k *KeeperBlockTimeTestReporter) WriteReport(folderLocation string) error { } var totalExpected, totalSuccessful, totalMissed, worstMiss int64 for contractIndex, report := range k.Reports { - avg, maxVal := int64AvgMax(report.AllMissedUpkeeps) + avg, max := int64AvgMax(report.AllMissedUpkeeps) err = keeperReportWriter.Write([]string{ fmt.Sprint(contractIndex), report.ContractAddress, @@ -72,13 +73,13 @@ func (k *KeeperBlockTimeTestReporter) WriteReport(folderLocation string) error { fmt.Sprint(report.TotalSuccessfulUpkeeps), fmt.Sprint(len(report.AllMissedUpkeeps)), fmt.Sprint(avg), - fmt.Sprint(maxVal), + fmt.Sprint(max), fmt.Sprintf("%.2f%%", (float64(report.TotalSuccessfulUpkeeps)/float64(report.TotalExpectedUpkeeps))*100), }) totalExpected += report.TotalExpectedUpkeeps totalSuccessful += report.TotalSuccessfulUpkeeps totalMissed += int64(len(report.AllMissedUpkeeps)) - worstMiss = max(maxVal, worstMiss) + worstMiss = int64(math.Max(float64(max), float64(worstMiss))) if err != nil { return err } @@ -159,13 +160,13 @@ func (k *KeeperBlockTimeTestReporter) SendSlackNotification(t *testing.T, slackC // int64AvgMax helper calculates the avg and the max values in a list func int64AvgMax(in []int64) (float64, int64) { var sum int64 - var val int64 // max + var max int64 if len(in) == 0 { return 0, 0 } for _, num := range in { sum += num - val = max(val, num) + max = int64(math.Max(float64(max), float64(num))) } - return float64(sum) / float64(len(in)), val + return float64(sum) / float64(len(in)), max } diff --git a/integration-tests/testreporters/keeper_benchmark.go b/integration-tests/testreporters/keeper_benchmark.go index 81a792002d9..00a31a12411 100644 --- a/integration-tests/testreporters/keeper_benchmark.go +++ b/integration-tests/testreporters/keeper_benchmark.go @@ -129,7 +129,7 @@ func (k *KeeperBenchmarkTestReporter) WriteReport(folderLocation string) error { if err != nil { return err } - avg, median, ninetyPct, ninetyNinePct, maxVal := IntListStats(allDelays) + avg, median, ninetyPct, ninetyNinePct, max := IntListStats(allDelays) err = keeperReportWriter.Write([]string{ fmt.Sprint(totalEligibleCount), fmt.Sprint(totalPerformed), @@ -139,7 +139,7 @@ func (k *KeeperBenchmarkTestReporter) WriteReport(folderLocation string) error { fmt.Sprint(median), fmt.Sprint(ninetyPct), fmt.Sprint(ninetyNinePct), - fmt.Sprint(maxVal), + fmt.Sprint(max), fmt.Sprintf("%.2f%%", pctWithinSLA), fmt.Sprintf("%.2f%%", pctReverted), fmt.Sprintf("%.2f%%", pctStale), @@ -156,7 +156,7 @@ func (k *KeeperBenchmarkTestReporter) WriteReport(folderLocation string) error { Int64("Median Perform Delay", median). Int64("90th pct Perform Delay", ninetyPct). Int64("99th pct Perform Delay", ninetyNinePct). - Int64("Max Perform Delay", maxVal). + Int64("Max Perform Delay", max). Float64("Percent Within SLA", pctWithinSLA). Float64("Percent Reverted", pctReverted). Msg("Calculated Aggregate Results") @@ -179,7 +179,7 @@ func (k *KeeperBenchmarkTestReporter) WriteReport(folderLocation string) error { } for contractIndex, report := range k.Reports { - avg, median, ninetyPct, ninetyNinePct, maxVal = IntListStats(report.AllCheckDelays) + avg, median, ninetyPct, ninetyNinePct, max = IntListStats(report.AllCheckDelays) err = keeperReportWriter.Write([]string{ fmt.Sprint(contractIndex), report.RegistryAddress, @@ -190,7 +190,7 @@ func (k *KeeperBenchmarkTestReporter) WriteReport(folderLocation string) error { fmt.Sprint(median), fmt.Sprint(ninetyPct), fmt.Sprint(ninetyNinePct), - fmt.Sprint(maxVal), + fmt.Sprint(max), fmt.Sprintf("%.2f%%", (1.0-float64(report.TotalSLAMissedUpkeeps)/float64(report.TotalEligibleCount))*100), }) if err != nil { @@ -215,7 +215,7 @@ func (k *KeeperBenchmarkTestReporter) WriteReport(folderLocation string) error { "median": median, "90p": ninetyPct, "99p": ninetyNinePct, - "max": maxVal, + "max": max, } k.Summary.Metrics.PercentWithinSLA = pctWithinSLA k.Summary.Metrics.PercentRevert = pctReverted diff --git a/integration-tests/testsetups/automation_benchmark.go b/integration-tests/testsetups/automation_benchmark.go index d6f5615965c..18e13816f5a 100644 --- a/integration-tests/testsetups/automation_benchmark.go +++ b/integration-tests/testsetups/automation_benchmark.go @@ -303,15 +303,11 @@ func (k *KeeperBenchmarkTest) Run() { startedObservations.Add(1) k.log.Info().Int("Channel index", chIndex).Str("UpkeepID", upkeepIDCopy.String()).Msg("Starting upkeep observation") - upKeepSLA := inputs.Upkeeps.BlockRange + inputs.UpkeepSLA - if upKeepSLA < 0 { - k.t.Fatalf("negative upkeep SLA: %d", upKeepSLA) - } confirmer := contracts.NewAutomationConsumerBenchmarkUpkeepObserver( k.keeperConsumerContracts[registryIndex], k.keeperRegistries[registryIndex], upkeepIDCopy, - uint64(upKeepSLA), + inputs.Upkeeps.BlockRange+inputs.UpkeepSLA, inputs.UpkeepSLA, &k.TestReporter, upkeepIndex, @@ -727,9 +723,6 @@ func (k *KeeperBenchmarkTest) SetupBenchmarkKeeperContracts(index int, a *automa err = actions.SetupMultiCallAndFundDeploymentAddresses(k.chainClient, k.linkToken, upkeep.NumberOfUpkeeps, linkFunds, a.TestConfig) require.NoError(k.t, err, "Sending link funds to deployment addresses shouldn't fail") - if upkeep.UpkeepGasLimit < 0 || upkeep.UpkeepGasLimit > math.MaxUint32 { - k.t.Fatalf("upkeep gas limit overflows uint32: %d", upkeep.UpkeepGasLimit) - } upkeepIds := actions.RegisterUpkeepContractsWithCheckData(k.t, k.chainClient, k.linkToken, linkFunds, uint32(upkeep.UpkeepGasLimit), a.Registry, a.Registrar, upkeep.NumberOfUpkeeps, upkeepAddresses, checkData, false, false, false, nil) k.automationTests[index] = *a diff --git a/integration-tests/testsetups/ocr.go b/integration-tests/testsetups/ocr.go index 7a90c38fdd0..69da49ae404 100644 --- a/integration-tests/testsetups/ocr.go +++ b/integration-tests/testsetups/ocr.go @@ -64,14 +64,13 @@ type OCRSoakTest struct { Config *tc.TestConfig TestReporter testreporters.OCRSoakTestReporter OperatorForwarderFlow bool - sethClient *seth.Client + seth *seth.Client OCRVersion string t *testing.T startTime time.Time timeLeft time.Duration startingBlockNum uint64 - startingValue int testEnvironment *environment.Environment namespace string log zerolog.Logger @@ -89,8 +88,6 @@ type OCRSoakTest struct { ocrV2Instances []contracts.OffchainAggregatorV2 ocrV2InstanceMap map[string]contracts.OffchainAggregatorV2 // address : instance - linkContract *contracts.EthereumLinkToken - rpcNetwork blockchain.EVMNetwork // network configuration for the blockchain node reorgHappened bool // flag to indicate if a reorg happened during the test gasSpikeSimulationHappened bool // flag to indicate if a gas spike simulation happened during the test @@ -163,21 +160,11 @@ func (o *OCRSoakTest) DeployEnvironment(ocrTestConfig tt.OcrTestConfig) { nsPre = fmt.Sprintf("%s%s", nsPre, strings.ReplaceAll(strings.ToLower(nodeNetwork.Name), " ", "-")) nsPre = strings.ReplaceAll(nsPre, "_", "-") - productName := fmt.Sprintf("data-feedsv%s.0", o.OCRVersion) - nsLabels, err := environment.GetRequiredChainLinkNamespaceLabels(productName, "soak") - require.NoError(o.t, err, "Error creating required chain.link labels for namespace") - - workloadPodLabels, err := environment.GetRequiredChainLinkWorkloadAndPodLabels(productName, "soak") - require.NoError(o.t, err, "Error creating required chain.link labels for workloads and pods") - baseEnvironmentConfig := &environment.Config{ TTL: time.Hour * 720, // 30 days, NamespacePrefix: nsPre, Test: o.t, PreventPodEviction: true, - Labels: nsLabels, - WorkloadLabels: workloadPodLabels, - PodLabels: workloadPodLabels, } testEnv := environment.New(baseEnvironmentConfig). @@ -283,151 +270,107 @@ func (o *OCRSoakTest) Environment() *environment.Environment { return o.testEnvironment } -// Setup initializes the OCR Soak Test by setting up clients, funding nodes, and deploying OCR contracts. func (o *OCRSoakTest) Setup(ocrTestConfig tt.OcrTestConfig) { - o.initializeClients() - o.deployLinkTokenContract(ocrTestConfig) - o.fundChainlinkNodes() - - o.startingValue = 5 - - var forwarders []common.Address - if o.OperatorForwarderFlow { - _, forwarders = o.deployForwarderContracts() - } - - o.setupOCRContracts(ocrTestConfig, forwarders) - o.log.Info().Msg("OCR Soak Test Setup Complete") -} - -// initializeClients sets up the Seth client, Chainlink nodes, and mock server. -func (o *OCRSoakTest) initializeClients() { sethClient, err := seth_utils.GetChainClient(o.Config, o.rpcNetwork) require.NoError(o.t, err, "Error creating seth client") - o.sethClient = sethClient + o.seth = sethClient nodes, err := nodeclient.ConnectChainlinkNodes(o.testEnvironment) require.NoError(o.t, err, "Connecting to chainlink nodes shouldn't fail") o.bootstrapNode, o.workerNodes = nodes[0], nodes[1:] - o.mockServer = ctf_client.ConnectMockServer(o.testEnvironment) require.NoError(o.t, err, "Creating mockserver clients shouldn't fail") -} -func (o *OCRSoakTest) deployLinkTokenContract(ocrTestConfig tt.OcrTestConfig) { - linkContract, err := actions.LinkTokenContract(o.log, o.sethClient, ocrTestConfig.GetActiveOCRConfig()) + linkContract, err := actions.LinkTokenContract(o.log, sethClient, ocrTestConfig.GetActiveOCRConfig()) require.NoError(o.t, err, "Error loading/deploying link token contract") - o.linkContract = linkContract -} -// fundChainlinkNodes funds the Chainlink worker nodes. -func (o *OCRSoakTest) fundChainlinkNodes() { + // Fund Chainlink nodes, excluding the bootstrap node o.log.Info().Float64("ETH amount per node", *o.Config.Common.ChainlinkNodeFunding).Msg("Funding Chainlink nodes") - err := actions.FundChainlinkNodesFromRootAddress(o.log, o.sethClient, contracts.ChainlinkK8sClientToChainlinkNodeWithKeysAndAddress(o.workerNodes), big.NewFloat(*o.Config.Common.ChainlinkNodeFunding)) + err = actions.FundChainlinkNodesFromRootAddress(o.log, sethClient, contracts.ChainlinkK8sClientToChainlinkNodeWithKeysAndAddress(o.workerNodes), big.NewFloat(*o.Config.Common.ChainlinkNodeFunding)) require.NoError(o.t, err, "Error funding Chainlink nodes") -} - -// deployForwarderContracts deploys forwarder contracts if OperatorForwarderFlow is enabled. -func (o *OCRSoakTest) deployForwarderContracts() (operators []common.Address, forwarders []common.Address) { - operators, forwarders, _ = actions.DeployForwarderContracts( - o.t, o.sethClient, common.HexToAddress(o.linkContract.Address()), len(o.workerNodes), - ) - require.Equal(o.t, len(o.workerNodes), len(operators), "Number of operators should match number of nodes") - require.Equal(o.t, len(o.workerNodes), len(forwarders), "Number of authorized forwarders should match number of nodes") - - forwarderNodesAddresses, err := actions.ChainlinkNodeAddresses(o.workerNodes) - require.NoError(o.t, err, "Retrieving on-chain wallet addresses for chainlink nodes shouldn't fail") - for i := range o.workerNodes { - actions.AcceptAuthorizedReceiversOperator(o.t, o.log, o.sethClient, operators[i], forwarders[i], []common.Address{forwarderNodesAddresses[i]}) - require.NoError(o.t, err, "Accepting Authorize Receivers on Operator shouldn't fail") - actions.TrackForwarder(o.t, o.sethClient, forwarders[i], o.workerNodes[i]) - } - return operators, forwarders -} - -// setupOCRContracts deploys and configures OCR contracts based on the version and forwarder flow. -func (o *OCRSoakTest) setupOCRContracts(ocrTestConfig tt.OcrTestConfig, forwarders []common.Address) { - if o.OCRVersion == "1" { - o.setupOCRv1Contracts(forwarders) - } else if o.OCRVersion == "2" { - o.setupOCRv2Contracts(ocrTestConfig, forwarders) - } -} -// setupOCRv1Contracts deploys and configures OCRv1 contracts based on the forwarder flow. -func (o *OCRSoakTest) setupOCRv1Contracts(forwarders []common.Address) { - var err error + var forwarders []common.Address if o.OperatorForwarderFlow { - o.ocrV1Instances, err = actions.DeployOCRContractsForwarderFlow( - o.log, - o.sethClient, - o.Config.GetActiveOCRConfig(), - common.HexToAddress(o.linkContract.Address()), - contracts.ChainlinkK8sClientToChainlinkNodeWithKeysAndAddress(o.workerNodes), - forwarders, + var operators []common.Address + operators, forwarders, _ = actions.DeployForwarderContracts( + o.t, o.seth, common.HexToAddress(linkContract.Address()), len(o.workerNodes), ) - require.NoError(o.t, err, "Error deploying OCR Forwarder contracts") - o.createJobsWithForwarder() - } else { - o.ocrV1Instances, err = actions.SetupOCRv1Contracts( + require.Equal(o.t, len(o.workerNodes), len(operators), "Number of operators should match number of nodes") + require.Equal(o.t, len(o.workerNodes), len(forwarders), "Number of authorized forwarders should match number of nodes") + forwarderNodesAddresses, err := actions.ChainlinkNodeAddresses(o.workerNodes) + require.NoError(o.t, err, "Retrieving on-chain wallet addresses for chainlink nodes shouldn't fail") + for i := range o.workerNodes { + actions.AcceptAuthorizedReceiversOperator( + o.t, o.log, o.seth, operators[i], forwarders[i], []common.Address{forwarderNodesAddresses[i]}) + require.NoError(o.t, err, "Accepting Authorize Receivers on Operator shouldn't fail") + actions.TrackForwarder(o.t, o.seth, forwarders[i], o.workerNodes[i]) + } + } else if o.OCRVersion == "1" { + if o.OperatorForwarderFlow { + o.ocrV1Instances, err = actions.DeployOCRContractsForwarderFlow( + o.log, + o.seth, + o.Config.GetActiveOCRConfig(), + common.HexToAddress(linkContract.Address()), + contracts.ChainlinkK8sClientToChainlinkNodeWithKeysAndAddress(o.workerNodes), + forwarders, + ) + require.NoError(o.t, err, "Error deploying OCR Forwarder contracts") + } else { + o.ocrV1Instances, err = actions.SetupOCRv1Contracts( + o.log, + sethClient, + o.Config.GetActiveOCRConfig(), + common.HexToAddress(linkContract.Address()), + contracts.ChainlinkK8sClientToChainlinkNodeWithKeysAndAddress(o.workerNodes), + ) + require.NoError(o.t, err) + } + } else if o.OCRVersion == "2" { + var transmitters []string + + if o.OperatorForwarderFlow { + for _, forwarder := range forwarders { + transmitters = append(transmitters, forwarder.Hex()) + } + } else { + for _, node := range o.workerNodes { + nodeAddress, err := node.PrimaryEthAddress() + require.NoError(o.t, err, "Error getting node's primary ETH address") + transmitters = append(transmitters, nodeAddress) + } + } + + ocrOffchainOptions := contracts.DefaultOffChainAggregatorOptions() + o.ocrV2Instances, err = actions.SetupOCRv2Contracts( o.log, - o.sethClient, - o.Config.GetActiveOCRConfig(), - common.HexToAddress(o.linkContract.Address()), - contracts.ChainlinkK8sClientToChainlinkNodeWithKeysAndAddress(o.workerNodes), + o.seth, + ocrTestConfig.GetActiveOCRConfig(), + common.HexToAddress(linkContract.Address()), + transmitters, + ocrOffchainOptions, ) - require.NoError(o.t, err, "Error setting up OCRv1 contracts") - err = o.createOCRv1Jobs() - require.NoError(o.t, err, "Error creating OCR jobs") - } - - o.storeOCRInstancesV1() -} + require.NoError(o.t, err, "Error deploying OCRv2 contracts") -// setupOCRv2Contracts sets up and configures OCRv2 contracts. -func (o *OCRSoakTest) setupOCRv2Contracts(ocrTestConfig tt.OcrTestConfig, forwarders []common.Address) { - var err error - var transmitters []string - if o.OperatorForwarderFlow { - for _, forwarder := range forwarders { - transmitters = append(transmitters, forwarder.Hex()) - } - } else { - for _, node := range o.workerNodes { - nodeAddress, err := node.PrimaryEthAddress() - require.NoError(o.t, err, "Error getting node's primary ETH address") - transmitters = append(transmitters, nodeAddress) + if !ocrTestConfig.GetActiveOCRConfig().UseExistingOffChainAggregatorsContracts() || (ocrTestConfig.GetActiveOCRConfig().UseExistingOffChainAggregatorsContracts() && ocrTestConfig.GetActiveOCRConfig().ConfigureExistingOffChainAggregatorsContracts()) { + contractConfig, err := actions.BuildMedianOCR2Config(o.workerNodes, ocrOffchainOptions) + require.NoError(o.t, err, "Error building median config") + err = actions.ConfigureOCRv2AggregatorContracts(contractConfig, o.ocrV2Instances) + require.NoError(o.t, err, "Error configuring OCRv2 aggregator contracts") } } - ocrOffchainOptions := contracts.DefaultOffChainAggregatorOptions() - o.ocrV2Instances, err = actions.SetupOCRv2Contracts( - o.log, o.sethClient, ocrTestConfig.GetActiveOCRConfig(), common.HexToAddress(o.linkContract.Address()), transmitters, ocrOffchainOptions, - ) - require.NoError(o.t, err, "Error deploying OCRv2 contracts") - err = o.createOCRv2Jobs() - require.NoError(o.t, err, "Error creating OCR jobs") - if !ocrTestConfig.GetActiveOCRConfig().UseExistingOffChainAggregatorsContracts() || (ocrTestConfig.GetActiveOCRConfig().UseExistingOffChainAggregatorsContracts() && ocrTestConfig.GetActiveOCRConfig().ConfigureExistingOffChainAggregatorsContracts()) { - contractConfig, err := actions.BuildMedianOCR2Config(o.workerNodes, ocrOffchainOptions) - require.NoError(o.t, err, "Error building median config") - err = actions.ConfigureOCRv2AggregatorContracts(contractConfig, o.ocrV2Instances) - require.NoError(o.t, err, "Error configuring OCRv2 aggregator contracts") - } - o.storeOCRInstancesV2() -} - -// storeOCRInstancesV1 stores OCRv1 contract instances by their addresses. -func (o *OCRSoakTest) storeOCRInstancesV1() { - for _, ocrInstance := range o.ocrV1Instances { - o.ocrV1InstanceMap[ocrInstance.Address()] = ocrInstance + if o.OCRVersion == "1" { + for _, ocrInstance := range o.ocrV1Instances { + o.ocrV1InstanceMap[ocrInstance.Address()] = ocrInstance + } + } else if o.OCRVersion == "2" { + for _, ocrInstance := range o.ocrV2Instances { + o.ocrV2InstanceMap[ocrInstance.Address()] = ocrInstance + } } -} -// storeOCRInstancesV2 stores OCRv2 contract instances by their addresses. -func (o *OCRSoakTest) storeOCRInstancesV2() { - for _, ocrInstance := range o.ocrV2Instances { - o.ocrV2InstanceMap[ocrInstance.Address()] = ocrInstance - } + o.log.Info().Msg("OCR Soak Test Setup Complete") } // Run starts the OCR soak test @@ -436,52 +379,36 @@ func (o *OCRSoakTest) Run() { require.NoError(o.t, err, "Error getting config") ctx, cancel := context.WithTimeout(testcontext.Get(o.t), time.Second*5) - latestBlockNum, err := o.sethClient.Client.BlockNumber(ctx) + latestBlockNum, err := o.seth.Client.BlockNumber(ctx) cancel() require.NoError(o.t, err, "Error getting current block number") o.startingBlockNum = latestBlockNum + startingValue := 5 + if o.OperatorForwarderFlow { + actions.CreateOCRJobsWithForwarder(o.t, o.ocrV1Instances, o.bootstrapNode, o.workerNodes, startingValue, o.mockServer, o.seth.ChainID) + } else if o.OCRVersion == "1" { + ctx, cancel := context.WithTimeout(testcontext.Get(o.t), time.Second*5) + chainId, err := o.seth.Client.ChainID(ctx) + cancel() + require.NoError(o.t, err, "Error getting chain ID") + err = actions.CreateOCRJobs(o.ocrV1Instances, o.bootstrapNode, o.workerNodes, startingValue, o.mockServer, chainId.String()) + require.NoError(o.t, err, "Error creating OCR jobs") + } else if o.OCRVersion == "2" { + err := actions.CreateOCRv2Jobs(o.ocrV2Instances, o.bootstrapNode, o.workerNodes, o.mockServer, startingValue, o.seth.ChainID, o.OperatorForwarderFlow) + require.NoError(o.t, err, "Error creating OCR jobs") + } + o.log.Info(). Str("Test Duration", o.Config.GetActiveOCRConfig().Common.TestDuration.Duration.Truncate(time.Second).String()). Int("Number of OCR Contracts", *config.GetActiveOCRConfig().Common.NumberOfContracts). Str("OCR Version", o.OCRVersion). Msg("Starting OCR Soak Test") - o.testLoop(o.Config.GetActiveOCRConfig().Common.TestDuration.Duration, o.startingValue) + o.testLoop(o.Config.GetActiveOCRConfig().Common.TestDuration.Duration, startingValue) o.complete() } -// createJobsWithForwarder creates OCR jobs with the forwarder setup. -func (o *OCRSoakTest) createJobsWithForwarder() { - actions.CreateOCRJobsWithForwarder(o.t, o.ocrV1Instances, o.bootstrapNode, o.workerNodes, o.startingValue, o.mockServer, o.sethClient.ChainID) -} - -// createOCRv1Jobs creates OCRv1 jobs. -func (o *OCRSoakTest) createOCRv1Jobs() error { - ctx, cancel := context.WithTimeout(testcontext.Get(o.t), time.Second*5) - defer cancel() - - chainId, err := o.sethClient.Client.ChainID(ctx) - if err != nil { - return fmt.Errorf("error getting chain ID: %w", err) - } - - err = actions.CreateOCRJobs(o.ocrV1Instances, o.bootstrapNode, o.workerNodes, o.startingValue, o.mockServer, chainId.String()) - if err != nil { - return fmt.Errorf("error creating OCRv1 jobs: %w", err) - } - return nil -} - -// createOCRv2Jobs creates OCRv2 jobs. -func (o *OCRSoakTest) createOCRv2Jobs() error { - err := actions.CreateOCRv2Jobs(o.ocrV2Instances, o.bootstrapNode, o.workerNodes, o.mockServer, o.startingValue, o.sethClient.ChainID, o.OperatorForwarderFlow, o.log) - if err != nil { - return fmt.Errorf("error creating OCRv2 jobs: %w", err) - } - return nil -} - // Networks returns the networks that the test is running on func (o *OCRSoakTest) TearDownVals(t *testing.T) ( *testing.T, @@ -491,7 +418,7 @@ func (o *OCRSoakTest) TearDownVals(t *testing.T) ( reportModel.TestReporter, reportModel.GrafanaURLProvider, ) { - return t, o.sethClient, o.namespace, append(o.workerNodes, o.bootstrapNode), &o.TestReporter, o.Config + return t, o.seth, o.namespace, append(o.workerNodes, o.bootstrapNode), &o.TestReporter, o.Config } // ********************* @@ -605,7 +532,7 @@ func (o *OCRSoakTest) LoadState() error { if testState.OCRVersion == "1" { o.ocrV1Instances = make([]contracts.OffchainAggregator, len(testState.OCRContractAddresses)) for i, addr := range testState.OCRContractAddresses { - instance, err := contracts.LoadOffChainAggregator(o.log, o.sethClient, common.HexToAddress(addr)) + instance, err := contracts.LoadOffChainAggregator(o.log, o.seth, common.HexToAddress(addr)) if err != nil { return fmt.Errorf("failed to instantiate OCR instance: %w", err) } @@ -614,7 +541,7 @@ func (o *OCRSoakTest) LoadState() error { } else if testState.OCRVersion == "2" { o.ocrV2Instances = make([]contracts.OffchainAggregatorV2, len(testState.OCRContractAddresses)) for i, addr := range testState.OCRContractAddresses { - instance, err := contracts.LoadOffchainAggregatorV2(o.log, o.sethClient, common.HexToAddress(addr)) + instance, err := contracts.LoadOffchainAggregatorV2(o.log, o.seth, common.HexToAddress(addr)) if err != nil { return err } @@ -853,7 +780,7 @@ func (o *OCRSoakTest) startAnvilGasSpikeSimulation(network blockchain.EVMNetwork func (o *OCRSoakTest) startAnvilGasLimitSimulation(network blockchain.EVMNetwork, conf ctf_config.GasLimitSimulationConfig) { client := ctf_client.NewRPCClient(network.HTTPURLs[0], nil) - latestBlock, err := o.sethClient.Client.BlockByNumber(context.Background(), nil) + latestBlock, err := o.seth.Client.BlockByNumber(context.Background(), nil) require.NoError(o.t, err) newGasLimit := int64(math.Ceil(float64(latestBlock.GasUsed()) * conf.NextGasLimitPercentage)) o.log.Info(). @@ -979,7 +906,7 @@ func (o *OCRSoakTest) pollingOCREvents(ctx context.Context, wg *sync.WaitGroup, // Helper function to poll events and update eventCounter func (o *OCRSoakTest) fetchAndProcessEvents(eventCounter *int, expectedEvents int, processedBlockNum *uint64) { - latestBlock, err := o.sethClient.Client.BlockNumber(context.Background()) + latestBlock, err := o.seth.Client.BlockNumber(context.Background()) if err != nil { o.log.Error().Err(err).Msg("Error getting latest block number") return @@ -1012,7 +939,7 @@ func (o *OCRSoakTest) fetchAndProcessEvents(eventCounter *int, expectedEvents in Uint64("To Block", latestBlock). Msg("Fetching logs for the specified range") - logs, err := o.sethClient.Client.FilterLogs(context.Background(), o.filterQuery) + logs, err := o.seth.Client.FilterLogs(context.Background(), o.filterQuery) if err != nil { o.log.Error().Err(err).Msg("Error fetching logs") return @@ -1129,12 +1056,12 @@ func (o *OCRSoakTest) collectEvents() error { o.log.Info().Interface("Filter Query", o.filterQuery).Str("Timeout", timeout.String()).Msg("Retrieving on-chain events") ctx, cancel := context.WithTimeout(testcontext.Get(o.t), timeout) - contractEvents, err := o.sethClient.Client.FilterLogs(ctx, o.filterQuery) + contractEvents, err := o.seth.Client.FilterLogs(ctx, o.filterQuery) cancel() for err != nil { o.log.Info().Interface("Filter Query", o.filterQuery).Str("Timeout", timeout.String()).Msg("Retrieving on-chain events") ctx, cancel := context.WithTimeout(testcontext.Get(o.t), timeout) - contractEvents, err = o.sethClient.Client.FilterLogs(ctx, o.filterQuery) + contractEvents, err = o.seth.Client.FilterLogs(ctx, o.filterQuery) cancel() if err != nil { o.log.Warn().Interface("Filter Query", o.filterQuery).Str("Timeout", timeout.String()).Msg("Error collecting on-chain events, trying again") diff --git a/integration-tests/types/config/node/core.go b/integration-tests/types/config/node/core.go index b3c20a26455..7b5230f401f 100644 --- a/integration-tests/types/config/node/core.go +++ b/integration-tests/types/config/node/core.go @@ -90,26 +90,13 @@ func WithPrivateEVMs(networks []blockchain.EVMNetwork, commonChainConfig *evmcfg var evmConfigs []*evmcfg.EVMConfig for _, network := range networks { var evmNodes []*evmcfg.Node - - // The CL node cannot have missing HTTP urls. If there are more WS URLs it will fail validation. - // If len(network.HTTPURLs) == 2 then len(network.URLs) must be 2 or less. - urlCount := len(network.HTTPURLs) - - for i := 0; i < urlCount; i++ { - node := &evmcfg.Node{ - Name: ptr.Ptr(fmt.Sprintf("%s-%d", network.Name, i)), - } - // Assign HTTP URL if available - if i < len(network.HTTPURLs) { - node.HTTPURL = itutils.MustURL(network.HTTPURLs[i]) - } - // Assign WS URL if available - if i < len(network.URLs) { - node.WSURL = itutils.MustURL(network.URLs[i]) - } - evmNodes = append(evmNodes, node) + for i := range network.URLs { + evmNodes = append(evmNodes, &evmcfg.Node{ + Name: ptr.Ptr(fmt.Sprintf("%s-%d", network.Name, i)), + WSURL: itutils.MustURL(network.URLs[i]), + HTTPURL: itutils.MustURL(network.HTTPURLs[i]), + }) } - evmConfig := &evmcfg.EVMConfig{ ChainID: ubig.New(big.NewInt(network.ChainID)), Nodes: evmNodes, diff --git a/integration-tests/universal/log_poller/helpers.go b/integration-tests/universal/log_poller/helpers.go index 0c127d576c0..52a5594564b 100644 --- a/integration-tests/universal/log_poller/helpers.go +++ b/integration-tests/universal/log_poller/helpers.go @@ -4,7 +4,6 @@ import ( "bytes" "context" "fmt" - "math" "math/big" "math/rand" "sort" @@ -442,15 +441,7 @@ func (m *MissingLogs) IsEmpty() bool { } // GetMissingLogs returns a map of CL node name to missing logs in that node compared to EVM node to which the provided evm client is connected -func GetMissingLogs( - startBlock, endBlock int64, - logEmitters []*contracts.LogEmitter, - client *seth.Client, - clnodeCluster *test_env.ClCluster, - l zerolog.Logger, - coreLogger core_logger.SugaredLogger, - cfg *lp_config.Config, -) (MissingLogs, error) { +func GetMissingLogs(startBlock, endBlock int64, logEmitters []*contracts.LogEmitter, client *seth.Client, clnodeCluster *test_env.ClCluster, l zerolog.Logger, coreLogger core_logger.SugaredLogger, cfg *lp_config.Config) (MissingLogs, error) { wg := &sync.WaitGroup{} type dbQueryResult struct { @@ -573,12 +564,6 @@ func GetMissingLogs( missingLogs := make([]geth_types.Log, 0) for i, evmLog := range allLogsInEVMNode { logFound := false - if evmLog.BlockNumber > math.MaxInt64 { - panic(fmt.Errorf("block number overflows int64: %d", evmLog.BlockNumber)) - } - if evmLog.Index > math.MaxInt64 { - panic(fmt.Errorf("index overflows int64: %d", evmLog.Index)) - } for _, logPollerLog := range allLogPollerLogs[nodeName] { if logPollerLog.BlockNumber == int64(evmLog.BlockNumber) && logPollerLog.TxHash == evmLog.TxHash && bytes.Equal(logPollerLog.Data, evmLog.Data) && logPollerLog.LogIndex == int64(evmLog.Index) && logPollerLog.Address == evmLog.Address && logPollerLog.BlockHash == evmLog.BlockHash && bytes.Equal(logPollerLog.Topics[0][:], evmLog.Topics[0].Bytes()) { @@ -997,9 +982,6 @@ func GetEndBlockToWaitFor(endBlock int64, network blockchain.EVMNetwork, cfg *lp return endBlock + 1, nil } - if network.FinalityDepth > math.MaxInt64 { - return -1, fmt.Errorf("finality depth overflows int64: %d", network.FinalityDepth) - } return endBlock + int64(network.FinalityDepth), nil } diff --git a/integration-tests/utils/pgtest/pgtest.go b/integration-tests/utils/pgtest/pgtest.go deleted file mode 100644 index 3baccc791b6..00000000000 --- a/integration-tests/utils/pgtest/pgtest.go +++ /dev/null @@ -1,20 +0,0 @@ -package pgtest - -import ( - "testing" - - "github.com/jmoiron/sqlx" - - "github.com/smartcontractkit/chainlink-common/pkg/sqlutil/pg" - - "github.com/smartcontractkit/chainlink/v2/core/config/env" -) - -func NewSqlxDB(t testing.TB) *sqlx.DB { - dbURL := string(env.DatabaseURL.Get()) - if dbURL == "" { - t.Errorf("you must provide a CL_DATABASE_URL environment variable") - return nil - } - return pg.NewTestDB(t, dbURL) -} diff --git a/internal/testdb/testdb.go b/internal/testdb/testdb.go index 1a52b1173e3..88251ae2c6f 100644 --- a/internal/testdb/testdb.go +++ b/internal/testdb/testdb.go @@ -7,7 +7,7 @@ import ( "net/url" "strings" - pgcommon "github.com/smartcontractkit/chainlink-common/pkg/sqlutil/pg" + "github.com/smartcontractkit/chainlink/v2/core/store/dialects" ) const ( @@ -33,7 +33,7 @@ func CreateOrReplace(parsed url.URL, suffix string, withTemplate bool) (string, // Cannot drop test database if we are connected to it, so we must connect // to a different one. 'postgres' should be present on all postgres installations parsed.Path = "/postgres" - db, err := sql.Open(string(pgcommon.Postgres), parsed.String()) + db, err := sql.Open(string(dialects.Postgres), parsed.String()) if err != nil { return "", fmt.Errorf("in order to drop the test database, we need to connect to a separate database"+ " called 'postgres'. But we are unable to open 'postgres' database: %+v\n", err) @@ -66,7 +66,7 @@ func Drop(dbURL url.URL) error { // Cannot drop test database if we are connected to it, so we must connect // to a different one. 'postgres' should be present on all postgres installations dbURL.Path = "/postgres" - db, err := sql.Open(string(pgcommon.Postgres), dbURL.String()) + db, err := sql.Open(string(dialects.Postgres), dbURL.String()) if err != nil { return fmt.Errorf("in order to drop the test database, we need to connect to a separate database"+ " called 'postgres'. But we are unable to open 'postgres' database: %+v\n", err) diff --git a/operator_ui/TAG b/operator_ui/TAG index b0d5ea37b87..b4622723757 100644 --- a/operator_ui/TAG +++ b/operator_ui/TAG @@ -1 +1 @@ -v0.8.0-445b190 +v0.8.0-ca7e4da diff --git a/plugins/chainlink.Dockerfile b/plugins/chainlink.Dockerfile index 883aa83c9cf..6d42567c745 100644 --- a/plugins/chainlink.Dockerfile +++ b/plugins/chainlink.Dockerfile @@ -1,5 +1,5 @@ # Build image: Chainlink binary -FROM golang:1.23-bullseye as buildgo +FROM golang:1.22-bullseye as buildgo RUN go version WORKDIR /chainlink @@ -12,18 +12,12 @@ RUN go mod download # Env vars needed for chainlink build ARG COMMIT_SHA -# Flags for Go Delve debugger -ARG GO_GCFLAGS - COPY . . RUN apt-get update && apt-get install -y jq -# Install Delve for debugging -RUN go install github.com/go-delve/delve/cmd/dlv@latest - # Build the golang binaries -RUN make GO_GCFLAGS="${GO_GCFLAGS}" install-chainlink +RUN make install-chainlink # Install medianpoc binary RUN make install-medianpoc @@ -39,7 +33,7 @@ RUN mkdir /chainlink-starknet RUN go list -m -f "{{.Dir}}" github.com/smartcontractkit/chainlink-starknet/relayer | xargs -I % ln -s % /chainlink-starknet/relayer # Build image: Plugins -FROM golang:1.23-bullseye as buildplugins +FROM golang:1.22-bullseye as buildplugins RUN go version WORKDIR /chainlink-feeds @@ -58,7 +52,6 @@ WORKDIR /chainlink-starknet/relayer COPY --from=buildgo /chainlink-starknet/relayer . RUN go install ./pkg/chainlink/cmd/chainlink-starknet - # Final image: ubuntu with chainlink binary FROM ubuntu:20.04 @@ -72,9 +65,6 @@ RUN curl https://www.postgresql.org/media/keys/ACCC4CF8.asc | apt-key add - \ && apt-get update && apt-get install -y postgresql-client-16 \ && apt-get clean all -# Copy Delve debugger from build stage -COPY --from=buildgo /go/bin/dlv /usr/local/bin/dlv - COPY --from=buildgo /go/bin/chainlink /usr/local/bin/ COPY --from=buildgo /go/bin/chainlink-medianpoc /usr/local/bin/ COPY --from=buildgo /go/bin/chainlink-ocr3-capability /usr/local/bin/ diff --git a/plugins/registrar.go b/plugins/registrar.go index 8523d3980cc..2a82f2a6204 100644 --- a/plugins/registrar.go +++ b/plugins/registrar.go @@ -6,7 +6,7 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/loop" ) -// RegistrarConfig generates contains static configuration +// RegistrarConfig generates contains static configuration inher type RegistrarConfig interface { RegisterLOOP(config CmdConfig) (func() *exec.Cmd, loop.GRPCOpts, error) UnregisterLOOP(ID string) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 492624a2a6c..5458e7e0f9f 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -20,16 +20,20 @@ importers: packages: - '@babel/code-frame@7.26.2': - resolution: {integrity: sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==} + '@babel/code-frame@7.24.7': + resolution: {integrity: sha512-BcYH1CVJBO9tvyIZ2jVeXgSIMvGZ2FDRvDdOIVQyuklNKSsx+eppDEBq/g47Ayw+RqNFE+URvOShmf+f/qwAlA==} engines: {node: '>=6.9.0'} - '@babel/helper-validator-identifier@7.25.9': - resolution: {integrity: sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==} + '@babel/helper-validator-identifier@7.24.7': + resolution: {integrity: sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w==} engines: {node: '>=6.9.0'} - '@babel/runtime@7.26.0': - resolution: {integrity: sha512-FDSOghenHTiToteC/QRlv2q3DhPZ/oOXTBoirfWNx1Cx3TMVcGWQtMMmQcSvb/JjpNeGzx8Pq/b4fKEJuWm1sw==} + '@babel/highlight@7.24.7': + resolution: {integrity: sha512-EStJpq4OuY8xYfhGVXngigBJRWxftKX9ksiGDnmlY3o7B/V7KIAc9X4oiK87uPJSc/vs5L869bem5fhZa8caZw==} + engines: {node: '>=6.9.0'} + + '@babel/runtime@7.25.6': + resolution: {integrity: sha512-VBj9MYyDb9tuLq7yzqjgzt6Q+IBQLrGZfdjOekyEirZPHxXWoTSGUTMrpsfi58Up73d13NfYLv8HT9vmznjzhQ==} engines: {node: '>=6.9.0'} '@changesets/apply-release-plan@6.1.4': @@ -293,8 +297,8 @@ packages: error-ex@1.3.2: resolution: {integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==} - es-abstract@1.23.5: - resolution: {integrity: sha512-vlmniQ0WNPwXqA0BnmwV3Ng7HxiGlh6r5U6JcTMNx8OilcAGqVJBHJcPjqOMaczU9fRuRK5Px2BdVyPRnKMMVQ==} + es-abstract@1.23.3: + resolution: {integrity: sha512-e+HfNH61Bj1X9/jLc5v1owaLYuHdeHHSQlkhCBiTK8rBvKaULl/beGMxwrMXjpYrv4pz22BlY570vVePA2ho4A==} engines: {node: '>= 0.4'} es-define-property@1.0.0: @@ -316,8 +320,8 @@ packages: es-shim-unscopables@1.0.2: resolution: {integrity: sha512-J3yBRXCzDu4ULnQwxyToo/OjdMx6akgVC7K6few0a7F/0wLtmKKN7I73AH5T2836UuXRqN7Qg+IIUw/+YJksRw==} - es-to-primitive@1.3.0: - resolution: {integrity: sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g==} + es-to-primitive@1.2.1: + resolution: {integrity: sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==} engines: {node: '>= 0.4'} escalade@3.2.0: @@ -479,10 +483,6 @@ packages: is-arrayish@0.2.1: resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==} - is-async-function@2.0.0: - resolution: {integrity: sha512-Y1JXKrfykRJGdlDwdKlLpLyMIiWqWvuSd17TvZk68PLAOGOoF4Xyav1z0Xhoi+gCYjZVeC5SI+hYFOfvXmGRCA==} - engines: {node: '>= 0.4'} - is-bigint@1.0.4: resolution: {integrity: sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==} @@ -514,26 +514,14 @@ packages: resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} engines: {node: '>=0.10.0'} - is-finalizationregistry@1.1.0: - resolution: {integrity: sha512-qfMdqbAQEwBw78ZyReKnlA8ezmPdb9BemzIIip/JkjaZUhitfXDkkr+3QTboW0JrSXT1QWyYShpvnNHGZ4c4yA==} - engines: {node: '>= 0.4'} - is-fullwidth-code-point@3.0.0: resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} engines: {node: '>=8'} - is-generator-function@1.0.10: - resolution: {integrity: sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==} - engines: {node: '>= 0.4'} - is-glob@4.0.3: resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} engines: {node: '>=0.10.0'} - is-map@2.0.3: - resolution: {integrity: sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==} - engines: {node: '>= 0.4'} - is-negative-zero@2.0.3: resolution: {integrity: sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==} engines: {node: '>= 0.4'} @@ -554,10 +542,6 @@ packages: resolution: {integrity: sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==} engines: {node: '>= 0.4'} - is-set@2.0.3: - resolution: {integrity: sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==} - engines: {node: '>= 0.4'} - is-shared-array-buffer@1.0.3: resolution: {integrity: sha512-nA2hv5XIhLR3uVzDDfCIknerhx8XUKnstuOERPNNIinXG7v9u+ohXF67vxm4TPTEPU6lm61ZkwP3c9PCB97rhg==} engines: {node: '>= 0.4'} @@ -578,17 +562,9 @@ packages: resolution: {integrity: sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw==} engines: {node: '>= 0.4'} - is-weakmap@2.0.2: - resolution: {integrity: sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==} - engines: {node: '>= 0.4'} - is-weakref@1.0.2: resolution: {integrity: sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==} - is-weakset@2.0.3: - resolution: {integrity: sha512-LvIm3/KWzS9oRFHugab7d+M/GcBXuXX5xZkzPmN+NxihdQlZUQ4dWuSV1xR/sq6upL1TJEDrfBgRepHFdBtSNQ==} - engines: {node: '>= 0.4'} - is-windows@1.0.2: resolution: {integrity: sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==} engines: {node: '>=0.10.0'} @@ -685,8 +661,8 @@ packages: normalize-package-data@2.5.0: resolution: {integrity: sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==} - object-inspect@1.13.3: - resolution: {integrity: sha512-kDCGIbxkDSXE3euJZZXzc6to7fCrKHNI/hSRQnRuQ+BWjFNzZwiFF8fj/6o2t2G9/jTj8PSIYTfCLelLZEeRpA==} + object-inspect@1.13.2: + resolution: {integrity: sha512-IRZSRuzJiynemAXPYtPe5BoI/RESNYR7TYm50MC5Mqbd3Jmw5y790sErYw3V6SryFJD64b74qQQs9wn5Bg/k3g==} engines: {node: '>= 0.4'} object-keys@1.1.1: @@ -747,8 +723,8 @@ packages: resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} engines: {node: '>=8'} - picocolors@1.1.1: - resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} + picocolors@1.1.0: + resolution: {integrity: sha512-TQ92mBOW0l3LeMeyLV6mzy/kWr8lkd/hp3mTg7wYK7zJhuBStmGMBG0BdeDZS/dZx1IukaX6Bk11zcln25o1Aw==} picomatch@2.3.1: resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} @@ -801,15 +777,11 @@ packages: resolution: {integrity: sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==} engines: {node: '>=8'} - reflect.getprototypeof@1.0.7: - resolution: {integrity: sha512-bMvFGIUKlc/eSfXNX+aZ+EL95/EgZzuwA0OBPTbZZDEJw/0AkentjMuM1oiRfwHrshqk4RzdgiTg5CcDalXN5g==} - engines: {node: '>= 0.4'} - regenerator-runtime@0.14.1: resolution: {integrity: sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==} - regexp.prototype.flags@1.5.3: - resolution: {integrity: sha512-vqlC04+RQoFalODCbCumG2xIOvapzVMHwsyIGM/SIE8fRhFFsXeH8/QQ+s0T0kDAhKc4k30s73/0ydkHQz6HlQ==} + regexp.prototype.flags@1.5.2: + resolution: {integrity: sha512-NcDiDkTLuPR+++OCKB0nWafEmhg/Da8aUPLPMQbK+bxKKCm1/S5he+AqYa4PlMCVBalb4/yxIRub6qkEx5yJbw==} engines: {node: '>= 0.4'} require-directory@2.1.1: @@ -993,12 +965,12 @@ packages: resolution: {integrity: sha512-3iMJ9q0ao7WE9tWcaYKIptkNBuOIcZCCT0d4MRvuuH88fEoEH62IuQe0OtraD3ebQEoTRk8XCBoknUNc1Y67pw==} engines: {node: '>= 0.4'} - typed-array-byte-offset@1.0.3: - resolution: {integrity: sha512-GsvTyUHTriq6o/bHcTd0vM7OQ9JEdlvluu9YISaA7+KzDzPaIzEeDFNkTfhdE3MYcNhNi0vq/LlegYgIs5yPAw==} + typed-array-byte-offset@1.0.2: + resolution: {integrity: sha512-Ous0vodHa56FviZucS2E63zkgtgrACj7omjwd/8lTEMEPFFyjfixMZ1ZXenpgCFBBt4EC1J2XsyVS2gkG0eTFA==} engines: {node: '>= 0.4'} - typed-array-length@1.0.7: - resolution: {integrity: sha512-3KS2b+kL7fsuk/eJZ7EQdnEmQoaho/r6KUef7hxvltNA5DR8NAUM+8wJMbJyZ4G9/7i3v5zPBIMN5aybAh2/Jg==} + typed-array-length@1.0.6: + resolution: {integrity: sha512-/OxDN6OtAk5KBpGb28T+HZc2M+ADtvRxXrKKbUwtsLgdoxgX13hyy7ek6bFRl5+aBs2yZzB0c4CnQfAtVypW/g==} engines: {node: '>= 0.4'} unbox-primitive@1.0.2: @@ -1023,14 +995,6 @@ packages: which-boxed-primitive@1.0.2: resolution: {integrity: sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==} - which-builtin-type@1.2.0: - resolution: {integrity: sha512-I+qLGQ/vucCby4tf5HsLmGueEla4ZhwTBSqaooS+Y0BuxN4Cp+okmGuV+8mXZ84KDI9BA+oklo+RzKg0ONdSUA==} - engines: {node: '>= 0.4'} - - which-collection@1.0.2: - resolution: {integrity: sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==} - engines: {node: '>= 0.4'} - which-module@2.0.1: resolution: {integrity: sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==} @@ -1038,8 +1002,8 @@ packages: resolution: {integrity: sha512-MOiaDbA5ZZgUjkeMWM5EkJp4loW5ZRoa5bc3/aeMox/PJelMhE6t7S/mLuiY43DBupyxH+S0U1bTui9kWUlmsw==} engines: {node: '>=8.15'} - which-typed-array@1.1.16: - resolution: {integrity: sha512-g+N+GAWiRj66DngFwHvISJd+ITsyphZvD1vChfVg6cEdnzy53GzB3oy0fUNlvhz7H7+MiqhYr26qxQShCpKTTQ==} + which-typed-array@1.1.15: + resolution: {integrity: sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA==} engines: {node: '>= 0.4'} which@1.3.1: @@ -1086,21 +1050,27 @@ packages: snapshots: - '@babel/code-frame@7.26.2': + '@babel/code-frame@7.24.7': dependencies: - '@babel/helper-validator-identifier': 7.25.9 - js-tokens: 4.0.0 - picocolors: 1.1.1 + '@babel/highlight': 7.24.7 + picocolors: 1.1.0 + + '@babel/helper-validator-identifier@7.24.7': {} - '@babel/helper-validator-identifier@7.25.9': {} + '@babel/highlight@7.24.7': + dependencies: + '@babel/helper-validator-identifier': 7.24.7 + chalk: 2.4.2 + js-tokens: 4.0.0 + picocolors: 1.1.0 - '@babel/runtime@7.26.0': + '@babel/runtime@7.25.6': dependencies: regenerator-runtime: 0.14.1 '@changesets/apply-release-plan@6.1.4': dependencies: - '@babel/runtime': 7.26.0 + '@babel/runtime': 7.25.6 '@changesets/config': 2.3.1 '@changesets/get-version-range-type': 0.3.2 '@changesets/git': 2.0.0 @@ -1116,7 +1086,7 @@ snapshots: '@changesets/assemble-release-plan@5.2.4': dependencies: - '@babel/runtime': 7.26.0 + '@babel/runtime': 7.25.6 '@changesets/errors': 0.1.4 '@changesets/get-dependents-graph': 1.3.6 '@changesets/types': 5.2.1 @@ -1129,7 +1099,7 @@ snapshots: '@changesets/cli@2.26.2': dependencies: - '@babel/runtime': 7.26.0 + '@babel/runtime': 7.25.6 '@changesets/apply-release-plan': 6.1.4 '@changesets/assemble-release-plan': 5.2.4 '@changesets/changelog-git': 0.1.14 @@ -1194,7 +1164,7 @@ snapshots: '@changesets/get-release-plan@3.0.17': dependencies: - '@babel/runtime': 7.26.0 + '@babel/runtime': 7.25.6 '@changesets/assemble-release-plan': 5.2.4 '@changesets/config': 2.3.1 '@changesets/pre': 1.0.14 @@ -1206,7 +1176,7 @@ snapshots: '@changesets/git@2.0.0': dependencies: - '@babel/runtime': 7.26.0 + '@babel/runtime': 7.25.6 '@changesets/errors': 0.1.4 '@changesets/types': 5.2.1 '@manypkg/get-packages': 1.1.3 @@ -1225,7 +1195,7 @@ snapshots: '@changesets/pre@1.0.14': dependencies: - '@babel/runtime': 7.26.0 + '@babel/runtime': 7.25.6 '@changesets/errors': 0.1.4 '@changesets/types': 5.2.1 '@manypkg/get-packages': 1.1.3 @@ -1233,7 +1203,7 @@ snapshots: '@changesets/read@0.5.9': dependencies: - '@babel/runtime': 7.26.0 + '@babel/runtime': 7.25.6 '@changesets/git': 2.0.0 '@changesets/logger': 0.0.5 '@changesets/parse': 0.3.16 @@ -1248,7 +1218,7 @@ snapshots: '@changesets/write@0.2.3': dependencies: - '@babel/runtime': 7.26.0 + '@babel/runtime': 7.25.6 '@changesets/types': 5.2.1 fs-extra: 7.0.1 human-id: 1.0.2 @@ -1256,14 +1226,14 @@ snapshots: '@manypkg/find-root@1.1.0': dependencies: - '@babel/runtime': 7.26.0 + '@babel/runtime': 7.25.6 '@types/node': 12.20.55 find-up: 4.1.0 fs-extra: 8.1.0 '@manypkg/get-packages@1.1.3': dependencies: - '@babel/runtime': 7.26.0 + '@babel/runtime': 7.25.6 '@changesets/types': 4.1.0 '@manypkg/find-root': 1.1.0 fs-extra: 8.1.0 @@ -1321,7 +1291,7 @@ snapshots: dependencies: call-bind: 1.0.7 define-properties: 1.2.1 - es-abstract: 1.23.5 + es-abstract: 1.23.3 es-shim-unscopables: 1.0.2 arraybuffer.prototype.slice@1.0.3: @@ -1329,7 +1299,7 @@ snapshots: array-buffer-byte-length: 1.0.1 call-bind: 1.0.7 define-properties: 1.2.1 - es-abstract: 1.23.5 + es-abstract: 1.23.3 es-errors: 1.3.0 get-intrinsic: 1.2.4 is-array-buffer: 3.0.4 @@ -1489,7 +1459,7 @@ snapshots: dependencies: is-arrayish: 0.2.1 - es-abstract@1.23.5: + es-abstract@1.23.3: dependencies: array-buffer-byte-length: 1.0.1 arraybuffer.prototype.slice: 1.0.3 @@ -1502,7 +1472,7 @@ snapshots: es-errors: 1.3.0 es-object-atoms: 1.0.0 es-set-tostringtag: 2.0.3 - es-to-primitive: 1.3.0 + es-to-primitive: 1.2.1 function.prototype.name: 1.1.6 get-intrinsic: 1.2.4 get-symbol-description: 1.0.2 @@ -1522,10 +1492,10 @@ snapshots: is-string: 1.0.7 is-typed-array: 1.1.13 is-weakref: 1.0.2 - object-inspect: 1.13.3 + object-inspect: 1.13.2 object-keys: 1.1.1 object.assign: 4.1.5 - regexp.prototype.flags: 1.5.3 + regexp.prototype.flags: 1.5.2 safe-array-concat: 1.1.2 safe-regex-test: 1.0.3 string.prototype.trim: 1.2.9 @@ -1533,10 +1503,10 @@ snapshots: string.prototype.trimstart: 1.0.8 typed-array-buffer: 1.0.2 typed-array-byte-length: 1.0.1 - typed-array-byte-offset: 1.0.3 - typed-array-length: 1.0.7 + typed-array-byte-offset: 1.0.2 + typed-array-length: 1.0.6 unbox-primitive: 1.0.2 - which-typed-array: 1.1.16 + which-typed-array: 1.1.15 es-define-property@1.0.0: dependencies: @@ -1558,7 +1528,7 @@ snapshots: dependencies: hasown: 2.0.2 - es-to-primitive@1.3.0: + es-to-primitive@1.2.1: dependencies: is-callable: 1.2.7 is-date-object: 1.0.5 @@ -1631,7 +1601,7 @@ snapshots: dependencies: call-bind: 1.0.7 define-properties: 1.2.1 - es-abstract: 1.23.5 + es-abstract: 1.23.3 functions-have-names: 1.2.3 functions-have-names@1.2.3: {} @@ -1727,10 +1697,6 @@ snapshots: is-arrayish@0.2.1: {} - is-async-function@2.0.0: - dependencies: - has-tostringtag: 1.0.2 - is-bigint@1.0.4: dependencies: has-bigints: 1.0.2 @@ -1760,22 +1726,12 @@ snapshots: is-extglob@2.1.1: {} - is-finalizationregistry@1.1.0: - dependencies: - call-bind: 1.0.7 - is-fullwidth-code-point@3.0.0: {} - is-generator-function@1.0.10: - dependencies: - has-tostringtag: 1.0.2 - is-glob@4.0.3: dependencies: is-extglob: 2.1.1 - is-map@2.0.3: {} - is-negative-zero@2.0.3: {} is-number-object@1.0.7: @@ -1791,8 +1747,6 @@ snapshots: call-bind: 1.0.7 has-tostringtag: 1.0.2 - is-set@2.0.3: {} - is-shared-array-buffer@1.0.3: dependencies: call-bind: 1.0.7 @@ -1811,19 +1765,12 @@ snapshots: is-typed-array@1.1.13: dependencies: - which-typed-array: 1.1.16 - - is-weakmap@2.0.2: {} + which-typed-array: 1.1.15 is-weakref@1.0.2: dependencies: call-bind: 1.0.7 - is-weakset@2.0.3: - dependencies: - call-bind: 1.0.7 - get-intrinsic: 1.2.4 - is-windows@1.0.2: {} isarray@2.0.5: {} @@ -1917,7 +1864,7 @@ snapshots: semver: 5.7.2 validate-npm-package-license: 3.0.4 - object-inspect@1.13.3: {} + object-inspect@1.13.2: {} object-keys@1.1.1: {} @@ -1958,7 +1905,7 @@ snapshots: parse-json@5.2.0: dependencies: - '@babel/code-frame': 7.26.2 + '@babel/code-frame': 7.24.7 error-ex: 1.3.2 json-parse-even-better-errors: 2.3.1 lines-and-columns: 1.2.4 @@ -1969,7 +1916,7 @@ snapshots: path-type@4.0.0: {} - picocolors@1.1.1: {} + picocolors@1.1.0: {} picomatch@2.3.1: {} @@ -2021,19 +1968,9 @@ snapshots: indent-string: 4.0.0 strip-indent: 3.0.0 - reflect.getprototypeof@1.0.7: - dependencies: - call-bind: 1.0.7 - define-properties: 1.2.1 - es-abstract: 1.23.5 - es-errors: 1.3.0 - get-intrinsic: 1.2.4 - gopd: 1.0.1 - which-builtin-type: 1.2.0 - regenerator-runtime@0.14.1: {} - regexp.prototype.flags@1.5.3: + regexp.prototype.flags@1.5.2: dependencies: call-bind: 1.0.7 define-properties: 1.2.1 @@ -2106,7 +2043,7 @@ snapshots: call-bind: 1.0.7 es-errors: 1.3.0 get-intrinsic: 1.2.4 - object-inspect: 1.13.3 + object-inspect: 1.13.2 signal-exit@3.0.7: {} @@ -2156,7 +2093,7 @@ snapshots: dependencies: call-bind: 1.0.7 define-properties: 1.2.1 - es-abstract: 1.23.5 + es-abstract: 1.23.3 es-object-atoms: 1.0.0 string.prototype.trimend@1.0.8: @@ -2235,7 +2172,7 @@ snapshots: has-proto: 1.0.3 is-typed-array: 1.1.13 - typed-array-byte-offset@1.0.3: + typed-array-byte-offset@1.0.2: dependencies: available-typed-arrays: 1.0.7 call-bind: 1.0.7 @@ -2243,16 +2180,15 @@ snapshots: gopd: 1.0.1 has-proto: 1.0.3 is-typed-array: 1.1.13 - reflect.getprototypeof: 1.0.7 - typed-array-length@1.0.7: + typed-array-length@1.0.6: dependencies: call-bind: 1.0.7 for-each: 0.3.3 gopd: 1.0.1 + has-proto: 1.0.3 is-typed-array: 1.1.13 possible-typed-array-names: 1.0.0 - reflect.getprototypeof: 1.0.7 unbox-primitive@1.0.2: dependencies: @@ -2287,29 +2223,6 @@ snapshots: is-string: 1.0.7 is-symbol: 1.0.4 - which-builtin-type@1.2.0: - dependencies: - call-bind: 1.0.7 - function.prototype.name: 1.1.6 - has-tostringtag: 1.0.2 - is-async-function: 2.0.0 - is-date-object: 1.0.5 - is-finalizationregistry: 1.1.0 - is-generator-function: 1.0.10 - is-regex: 1.1.4 - is-weakref: 1.0.2 - isarray: 2.0.5 - which-boxed-primitive: 1.0.2 - which-collection: 1.0.2 - which-typed-array: 1.1.16 - - which-collection@1.0.2: - dependencies: - is-map: 2.0.3 - is-set: 2.0.3 - is-weakmap: 2.0.2 - is-weakset: 2.0.3 - which-module@2.0.1: {} which-pm@2.2.0: @@ -2317,7 +2230,7 @@ snapshots: load-yaml-file: 0.2.0 path-exists: 4.0.0 - which-typed-array@1.1.16: + which-typed-array@1.1.15: dependencies: available-typed-arrays: 1.0.7 call-bind: 1.0.7 diff --git a/shell.nix b/shell.nix index 4065e7e3def..8d5b4351b25 100644 --- a/shell.nix +++ b/shell.nix @@ -1,6 +1,6 @@ {pkgs, isCrib}: with pkgs; let - go = go_1_23; + go = go_1_21; postgresql = postgresql_15; nodejs = nodejs-18_x; nodePackages = pkgs.nodePackages.override {inherit nodejs;}; diff --git a/testdata/scripts/chains/cosmos/help.txtar b/testdata/scripts/chains/cosmos/help.txtar index 4fe0a930ac0..edef6f7345c 100644 --- a/testdata/scripts/chains/cosmos/help.txtar +++ b/testdata/scripts/chains/cosmos/help.txtar @@ -3,13 +3,13 @@ cmp stdout out.txt -- out.txt -- NAME: - chainlink chains cosmos - Commands for handling cosmos chains + chainlink chains cosmos - Commands for handling Cosmos chains USAGE: chainlink chains cosmos command [command options] [arguments...] COMMANDS: - list List all existing cosmos chains + list List all existing Cosmos chains OPTIONS: --help, -h show help diff --git a/testdata/scripts/chains/cosmos/list/help.txtar b/testdata/scripts/chains/cosmos/list/help.txtar index d1f2d166374..7e9be2efb00 100644 --- a/testdata/scripts/chains/cosmos/list/help.txtar +++ b/testdata/scripts/chains/cosmos/list/help.txtar @@ -3,7 +3,7 @@ cmp stdout out.txt -- out.txt -- NAME: - chainlink chains cosmos list - List all existing cosmos chains + chainlink chains cosmos list - List all existing Cosmos chains USAGE: chainlink chains cosmos list [arguments...] diff --git a/testdata/scripts/chains/evm/help.txtar b/testdata/scripts/chains/evm/help.txtar index b3e9e366810..e15dde5ecd2 100644 --- a/testdata/scripts/chains/evm/help.txtar +++ b/testdata/scripts/chains/evm/help.txtar @@ -3,13 +3,13 @@ cmp stdout out.txt -- out.txt -- NAME: - chainlink chains evm - Commands for handling evm chains + chainlink chains evm - Commands for handling EVM chains USAGE: chainlink chains evm command [command options] [arguments...] COMMANDS: - list List all existing evm chains + list List all existing EVM chains OPTIONS: --help, -h show help diff --git a/testdata/scripts/chains/evm/list/help.txtar b/testdata/scripts/chains/evm/list/help.txtar index bb5eec199b7..154ee110ad5 100644 --- a/testdata/scripts/chains/evm/list/help.txtar +++ b/testdata/scripts/chains/evm/list/help.txtar @@ -3,7 +3,7 @@ cmp stdout out.txt -- out.txt -- NAME: - chainlink chains evm list - List all existing evm chains + chainlink chains evm list - List all existing EVM chains USAGE: chainlink chains evm list [arguments...] diff --git a/testdata/scripts/chains/help.txtar b/testdata/scripts/chains/help.txtar index ccfb54d2928..83a342925e1 100644 --- a/testdata/scripts/chains/help.txtar +++ b/testdata/scripts/chains/help.txtar @@ -9,11 +9,10 @@ USAGE: chainlink chains command [command options] [arguments...] COMMANDS: - aptos Commands for handling aptos chains - cosmos Commands for handling cosmos chains - evm Commands for handling evm chains - solana Commands for handling solana chains - starknet Commands for handling starknet chains + evm Commands for handling EVM chains + cosmos Commands for handling Cosmos chains + solana Commands for handling Solana chains + starknet Commands for handling StarkNet chains OPTIONS: --help, -h show help diff --git a/testdata/scripts/chains/solana/help.txtar b/testdata/scripts/chains/solana/help.txtar index ddc27fed18f..be3ab9b343b 100644 --- a/testdata/scripts/chains/solana/help.txtar +++ b/testdata/scripts/chains/solana/help.txtar @@ -3,13 +3,13 @@ cmp stdout out.txt -- out.txt -- NAME: - chainlink chains solana - Commands for handling solana chains + chainlink chains solana - Commands for handling Solana chains USAGE: chainlink chains solana command [command options] [arguments...] COMMANDS: - list List all existing solana chains + list List all existing Solana chains OPTIONS: --help, -h show help diff --git a/testdata/scripts/chains/solana/list/help.txtar b/testdata/scripts/chains/solana/list/help.txtar index ed8a857529d..794085d43d9 100644 --- a/testdata/scripts/chains/solana/list/help.txtar +++ b/testdata/scripts/chains/solana/list/help.txtar @@ -3,7 +3,7 @@ cmp stdout out.txt -- out.txt -- NAME: - chainlink chains solana list - List all existing solana chains + chainlink chains solana list - List all existing Solana chains USAGE: chainlink chains solana list [arguments...] diff --git a/testdata/scripts/chains/starknet/help.txtar b/testdata/scripts/chains/starknet/help.txtar index 5cb8fe93746..992623d842c 100644 --- a/testdata/scripts/chains/starknet/help.txtar +++ b/testdata/scripts/chains/starknet/help.txtar @@ -3,13 +3,13 @@ cmp stdout out.txt -- out.txt -- NAME: - chainlink chains starknet - Commands for handling starknet chains + chainlink chains starknet - Commands for handling StarkNet chains USAGE: chainlink chains starknet command [command options] [arguments...] COMMANDS: - list List all existing starknet chains + list List all existing StarkNet chains OPTIONS: --help, -h show help diff --git a/testdata/scripts/chains/starknet/list/help.txtar b/testdata/scripts/chains/starknet/list/help.txtar index 67315ce6c1e..723318bf098 100644 --- a/testdata/scripts/chains/starknet/list/help.txtar +++ b/testdata/scripts/chains/starknet/list/help.txtar @@ -3,7 +3,7 @@ cmp stdout out.txt -- out.txt -- NAME: - chainlink chains starknet list - List all existing starknet chains + chainlink chains starknet list - List all existing StarkNet chains USAGE: chainlink chains starknet list [arguments...] diff --git a/testdata/scripts/config/merge_raw_configs.txtar b/testdata/scripts/config/merge_raw_configs.txtar index efac49f8ef8..b3d50f22b36 100644 --- a/testdata/scripts/config/merge_raw_configs.txtar +++ b/testdata/scripts/config/merge_raw_configs.txtar @@ -384,7 +384,6 @@ CertFile = '' [Mercury.Transmitter] TransmitQueueMaxSize = 10000 TransmitTimeout = '5s' -TransmitConcurrency = 100 [Capabilities] [Capabilities.Peering] @@ -416,11 +415,6 @@ Address = '' NetworkID = 'evm' ChainID = '1' -[Capabilities.WorkflowRegistry] -Address = '' -NetworkID = 'evm' -ChainID = '1' - [Capabilities.GatewayConnector] ChainIDForNodeKey = '' NodeAddress = '' diff --git a/testdata/scripts/help-all/help-all.txtar b/testdata/scripts/help-all/help-all.txtar index 078853ef6a5..372b149bd19 100644 --- a/testdata/scripts/help-all/help-all.txtar +++ b/testdata/scripts/help-all/help-all.txtar @@ -24,16 +24,14 @@ bridges destroy # Destroys the Bridge for an External Adapter bridges list # List all Bridges to External Adapters bridges show # Show a Bridge's details chains # Commands for handling chain configuration -chains aptos # Commands for handling aptos chains -chains aptos list # List all existing aptos chains -chains cosmos # Commands for handling cosmos chains -chains cosmos list # List all existing cosmos chains -chains evm # Commands for handling evm chains -chains evm list # List all existing evm chains -chains solana # Commands for handling solana chains -chains solana list # List all existing solana chains -chains starknet # Commands for handling starknet chains -chains starknet list # List all existing starknet chains +chains cosmos # Commands for handling Cosmos chains +chains cosmos list # List all existing Cosmos chains +chains evm # Commands for handling EVM chains +chains evm list # List all existing EVM chains +chains solana # Commands for handling Solana chains +chains solana list # List all existing Solana chains +chains starknet # Commands for handling StarkNet chains +chains starknet list # List all existing StarkNet chains config # Commands for the node's configuration config loglevel # Set log level config logsql # Enable/disable SQL statement logging @@ -134,16 +132,14 @@ node start # Run the Chainlink node node status # Displays the health of various services running inside the node. node validate # Validate the TOML configuration and secrets that are passed as flags to the `node` command. Prints the full effective configuration, with defaults included nodes # Commands for handling node configuration -nodes aptos # Commands for handling aptos node configuration -nodes aptos list # List all existing aptos nodes -nodes cosmos # Commands for handling cosmos node configuration -nodes cosmos list # List all existing cosmos nodes -nodes evm # Commands for handling evm node configuration -nodes evm list # List all existing evm nodes -nodes solana # Commands for handling solana node configuration -nodes solana list # List all existing solana nodes -nodes starknet # Commands for handling starknet node configuration -nodes starknet list # List all existing starknet nodes +nodes cosmos # Commands for handling Cosmos node configuration +nodes cosmos list # List all existing Cosmos nodes +nodes evm # Commands for handling EVM node configuration +nodes evm list # List all existing EVM nodes +nodes solana # Commands for handling Solana node configuration +nodes solana list # List all existing Solana nodes +nodes starknet # Commands for handling StarkNet node configuration +nodes starknet list # List all existing StarkNet nodes txs # Commands for handling transactions txs cosmos # Commands for handling Cosmos transactions txs cosmos create # Send of from node Cosmos account to destination . diff --git a/testdata/scripts/node/validate/default.txtar b/testdata/scripts/node/validate/default.txtar index d4e4a188d2a..5e8b847ceda 100644 --- a/testdata/scripts/node/validate/default.txtar +++ b/testdata/scripts/node/validate/default.txtar @@ -249,7 +249,6 @@ CertFile = '' [Mercury.Transmitter] TransmitQueueMaxSize = 10000 TransmitTimeout = '5s' -TransmitConcurrency = 100 [Capabilities] [Capabilities.Peering] @@ -281,11 +280,6 @@ Address = '' NetworkID = 'evm' ChainID = '1' -[Capabilities.WorkflowRegistry] -Address = '' -NetworkID = 'evm' -ChainID = '1' - [Capabilities.GatewayConnector] ChainIDForNodeKey = '' NodeAddress = '' diff --git a/testdata/scripts/node/validate/defaults-override.txtar b/testdata/scripts/node/validate/defaults-override.txtar index eaa8b9b2e43..bf8bece28bf 100644 --- a/testdata/scripts/node/validate/defaults-override.txtar +++ b/testdata/scripts/node/validate/defaults-override.txtar @@ -310,7 +310,6 @@ CertFile = '' [Mercury.Transmitter] TransmitQueueMaxSize = 10000 TransmitTimeout = '5s' -TransmitConcurrency = 100 [Capabilities] [Capabilities.Peering] @@ -342,11 +341,6 @@ Address = '' NetworkID = 'evm' ChainID = '1' -[Capabilities.WorkflowRegistry] -Address = '' -NetworkID = 'evm' -ChainID = '1' - [Capabilities.GatewayConnector] ChainIDForNodeKey = '' NodeAddress = '' @@ -393,7 +387,6 @@ FinalizedBlockOffset = 0 NoNewFinalizedHeadsThreshold = '9m0s' [EVM.Transactions] -Enabled = true ForwardersEnabled = false MaxInFlight = 16 MaxQueued = 250 diff --git a/testdata/scripts/node/validate/disk-based-logging-disabled.txtar b/testdata/scripts/node/validate/disk-based-logging-disabled.txtar index 8e632f7b23f..2e72ed7e9bb 100644 --- a/testdata/scripts/node/validate/disk-based-logging-disabled.txtar +++ b/testdata/scripts/node/validate/disk-based-logging-disabled.txtar @@ -293,7 +293,6 @@ CertFile = '' [Mercury.Transmitter] TransmitQueueMaxSize = 10000 TransmitTimeout = '5s' -TransmitConcurrency = 100 [Capabilities] [Capabilities.Peering] @@ -325,11 +324,6 @@ Address = '' NetworkID = 'evm' ChainID = '1' -[Capabilities.WorkflowRegistry] -Address = '' -NetworkID = 'evm' -ChainID = '1' - [Capabilities.GatewayConnector] ChainIDForNodeKey = '' NodeAddress = '' @@ -376,7 +370,6 @@ FinalizedBlockOffset = 0 NoNewFinalizedHeadsThreshold = '9m0s' [EVM.Transactions] -Enabled = true ForwardersEnabled = false MaxInFlight = 16 MaxQueued = 250 diff --git a/testdata/scripts/node/validate/disk-based-logging-no-dir.txtar b/testdata/scripts/node/validate/disk-based-logging-no-dir.txtar index cbe09179049..7b27328f7a6 100644 --- a/testdata/scripts/node/validate/disk-based-logging-no-dir.txtar +++ b/testdata/scripts/node/validate/disk-based-logging-no-dir.txtar @@ -293,7 +293,6 @@ CertFile = '' [Mercury.Transmitter] TransmitQueueMaxSize = 10000 TransmitTimeout = '5s' -TransmitConcurrency = 100 [Capabilities] [Capabilities.Peering] @@ -325,11 +324,6 @@ Address = '' NetworkID = 'evm' ChainID = '1' -[Capabilities.WorkflowRegistry] -Address = '' -NetworkID = 'evm' -ChainID = '1' - [Capabilities.GatewayConnector] ChainIDForNodeKey = '' NodeAddress = '' @@ -376,7 +370,6 @@ FinalizedBlockOffset = 0 NoNewFinalizedHeadsThreshold = '9m0s' [EVM.Transactions] -Enabled = true ForwardersEnabled = false MaxInFlight = 16 MaxQueued = 250 diff --git a/testdata/scripts/node/validate/disk-based-logging.txtar b/testdata/scripts/node/validate/disk-based-logging.txtar index ed6d3d608d8..83d23546175 100644 --- a/testdata/scripts/node/validate/disk-based-logging.txtar +++ b/testdata/scripts/node/validate/disk-based-logging.txtar @@ -293,7 +293,6 @@ CertFile = '' [Mercury.Transmitter] TransmitQueueMaxSize = 10000 TransmitTimeout = '5s' -TransmitConcurrency = 100 [Capabilities] [Capabilities.Peering] @@ -325,11 +324,6 @@ Address = '' NetworkID = 'evm' ChainID = '1' -[Capabilities.WorkflowRegistry] -Address = '' -NetworkID = 'evm' -ChainID = '1' - [Capabilities.GatewayConnector] ChainIDForNodeKey = '' NodeAddress = '' @@ -376,7 +370,6 @@ FinalizedBlockOffset = 0 NoNewFinalizedHeadsThreshold = '9m0s' [EVM.Transactions] -Enabled = true ForwardersEnabled = false MaxInFlight = 16 MaxQueued = 250 diff --git a/testdata/scripts/node/validate/invalid-ocr-p2p.txtar b/testdata/scripts/node/validate/invalid-ocr-p2p.txtar index 2cc7b7afe0e..3fccffc4e69 100644 --- a/testdata/scripts/node/validate/invalid-ocr-p2p.txtar +++ b/testdata/scripts/node/validate/invalid-ocr-p2p.txtar @@ -278,7 +278,6 @@ CertFile = '' [Mercury.Transmitter] TransmitQueueMaxSize = 10000 TransmitTimeout = '5s' -TransmitConcurrency = 100 [Capabilities] [Capabilities.Peering] @@ -310,11 +309,6 @@ Address = '' NetworkID = 'evm' ChainID = '1' -[Capabilities.WorkflowRegistry] -Address = '' -NetworkID = 'evm' -ChainID = '1' - [Capabilities.GatewayConnector] ChainIDForNodeKey = '' NodeAddress = '' diff --git a/testdata/scripts/node/validate/invalid.txtar b/testdata/scripts/node/validate/invalid.txtar index f0882d0d24c..5ea0aa289a8 100644 --- a/testdata/scripts/node/validate/invalid.txtar +++ b/testdata/scripts/node/validate/invalid.txtar @@ -283,7 +283,6 @@ CertFile = '' [Mercury.Transmitter] TransmitQueueMaxSize = 10000 TransmitTimeout = '5s' -TransmitConcurrency = 100 [Capabilities] [Capabilities.Peering] @@ -315,11 +314,6 @@ Address = '' NetworkID = 'evm' ChainID = '1' -[Capabilities.WorkflowRegistry] -Address = '' -NetworkID = 'evm' -ChainID = '1' - [Capabilities.GatewayConnector] ChainIDForNodeKey = '' NodeAddress = '' @@ -366,7 +360,6 @@ FinalizedBlockOffset = 0 NoNewFinalizedHeadsThreshold = '9m0s' [EVM.Transactions] -Enabled = true ForwardersEnabled = false MaxInFlight = 16 MaxQueued = 250 diff --git a/testdata/scripts/node/validate/valid.txtar b/testdata/scripts/node/validate/valid.txtar index f7278540745..26641c0ef76 100644 --- a/testdata/scripts/node/validate/valid.txtar +++ b/testdata/scripts/node/validate/valid.txtar @@ -290,7 +290,6 @@ CertFile = '' [Mercury.Transmitter] TransmitQueueMaxSize = 10000 TransmitTimeout = '5s' -TransmitConcurrency = 100 [Capabilities] [Capabilities.Peering] @@ -322,11 +321,6 @@ Address = '' NetworkID = 'evm' ChainID = '1' -[Capabilities.WorkflowRegistry] -Address = '' -NetworkID = 'evm' -ChainID = '1' - [Capabilities.GatewayConnector] ChainIDForNodeKey = '' NodeAddress = '' @@ -373,7 +367,6 @@ FinalizedBlockOffset = 0 NoNewFinalizedHeadsThreshold = '9m0s' [EVM.Transactions] -Enabled = true ForwardersEnabled = false MaxInFlight = 16 MaxQueued = 250 diff --git a/testdata/scripts/node/validate/warnings.txtar b/testdata/scripts/node/validate/warnings.txtar index 85b7bc6a253..51b3e897741 100644 --- a/testdata/scripts/node/validate/warnings.txtar +++ b/testdata/scripts/node/validate/warnings.txtar @@ -272,7 +272,6 @@ CertFile = '' [Mercury.Transmitter] TransmitQueueMaxSize = 10000 TransmitTimeout = '5s' -TransmitConcurrency = 100 [Capabilities] [Capabilities.Peering] @@ -304,11 +303,6 @@ Address = '' NetworkID = 'evm' ChainID = '1' -[Capabilities.WorkflowRegistry] -Address = '' -NetworkID = 'evm' -ChainID = '1' - [Capabilities.GatewayConnector] ChainIDForNodeKey = '' NodeAddress = '' diff --git a/testdata/scripts/nodes/cosmos/help.txtar b/testdata/scripts/nodes/cosmos/help.txtar index 78939331b6b..b605e676f8c 100644 --- a/testdata/scripts/nodes/cosmos/help.txtar +++ b/testdata/scripts/nodes/cosmos/help.txtar @@ -3,13 +3,13 @@ cmp stdout out.txt -- out.txt -- NAME: - chainlink nodes cosmos - Commands for handling cosmos node configuration + chainlink nodes cosmos - Commands for handling Cosmos node configuration USAGE: chainlink nodes cosmos command [command options] [arguments...] COMMANDS: - list List all existing cosmos nodes + list List all existing Cosmos nodes OPTIONS: --help, -h show help diff --git a/testdata/scripts/nodes/cosmos/list/help.txtar b/testdata/scripts/nodes/cosmos/list/help.txtar index 372693c704c..c984b4f3e18 100644 --- a/testdata/scripts/nodes/cosmos/list/help.txtar +++ b/testdata/scripts/nodes/cosmos/list/help.txtar @@ -3,7 +3,7 @@ cmp stdout out.txt -- out.txt -- NAME: - chainlink nodes cosmos list - List all existing cosmos nodes + chainlink nodes cosmos list - List all existing Cosmos nodes USAGE: chainlink nodes cosmos list [arguments...] diff --git a/testdata/scripts/nodes/cosmos/list/list.txtar b/testdata/scripts/nodes/cosmos/list/list.txtar deleted file mode 100644 index dafaa736717..00000000000 --- a/testdata/scripts/nodes/cosmos/list/list.txtar +++ /dev/null @@ -1,55 +0,0 @@ -# start node -exec sh -c 'eval "echo \"$(cat config.toml.tmpl)\" > config.toml"' -exec chainlink node -c config.toml start -p password -a creds & - -# initialize client -env NODEURL=http://localhost:$PORT -exec curl --retry 10 --retry-max-time 60 --retry-connrefused $NODEURL -exec chainlink --remote-node-url $NODEURL admin login -file creds --bypass-version-check - -exec chainlink --remote-node-url $NODEURL nodes cosmos list -cmp stdout out.txt - --- testdb.txt -- -CL_DATABASE_URL --- testport.txt -- -PORT - --- password -- -T.tLHkcmwePT/p,]sYuntjwHKAsrhm#4eRs4LuKHwvHejWYAC2JP4M8HimwgmbaZ --- creds -- -notreal@fakeemail.ch -fj293fbBnlQ!f9vNs - --- config.toml.tmpl -- -[Webserver] -HTTPPort = $PORT - -[[Cosmos]] -ChainID = '68472' - -[[Cosmos.Nodes]] -Name = 'Blue' -TendermintURL = 'wss://primaryfoo.bar' - -[[Cosmos.Nodes]] -Name = 'Yellow' -TendermintURL = 'wss://sendonlyfoo.bar' - --- out.txt -- - ---------------------------------------- -Name: Blue -Chain ID: 68472 -State: -Config: Name = 'Blue' -TendermintURL = 'wss://primaryfoo.bar' - ---------------------------------------- -Name: Yellow -Chain ID: 68472 -State: -Config: Name = 'Yellow' -TendermintURL = 'wss://sendonlyfoo.bar' - ---------------------------------------- diff --git a/testdata/scripts/nodes/evm/help.txtar b/testdata/scripts/nodes/evm/help.txtar index 5e9d9d482ab..dfc13eba9aa 100644 --- a/testdata/scripts/nodes/evm/help.txtar +++ b/testdata/scripts/nodes/evm/help.txtar @@ -3,13 +3,13 @@ cmp stdout out.txt -- out.txt -- NAME: - chainlink nodes evm - Commands for handling evm node configuration + chainlink nodes evm - Commands for handling EVM node configuration USAGE: chainlink nodes evm command [command options] [arguments...] COMMANDS: - list List all existing evm nodes + list List all existing EVM nodes OPTIONS: --help, -h show help diff --git a/testdata/scripts/nodes/evm/list/help.txtar b/testdata/scripts/nodes/evm/list/help.txtar index 3ecfe32de40..62d3814823d 100644 --- a/testdata/scripts/nodes/evm/list/help.txtar +++ b/testdata/scripts/nodes/evm/list/help.txtar @@ -3,7 +3,7 @@ cmp stdout out.txt -- out.txt -- NAME: - chainlink nodes evm list - List all existing evm nodes + chainlink nodes evm list - List all existing EVM nodes USAGE: chainlink nodes evm list [arguments...] diff --git a/testdata/scripts/nodes/evm/list/list.txtar b/testdata/scripts/nodes/evm/list/list.txtar deleted file mode 100644 index 162a8558bba..00000000000 --- a/testdata/scripts/nodes/evm/list/list.txtar +++ /dev/null @@ -1,63 +0,0 @@ -# start node -exec sh -c 'eval "echo \"$(cat config.toml.tmpl)\" > config.toml"' -exec chainlink node -c config.toml start -p password -a creds & - -# initialize client -env NODEURL=http://localhost:$PORT -exec curl --retry 10 --retry-max-time 60 --retry-connrefused $NODEURL -exec chainlink --remote-node-url $NODEURL admin login -file creds --bypass-version-check - -exec chainlink --remote-node-url $NODEURL nodes evm list -cmp stdout out.txt - --- testdb.txt -- -CL_DATABASE_URL --- testport.txt -- -PORT - --- password -- -T.tLHkcmwePT/p,]sYuntjwHKAsrhm#4eRs4LuKHwvHejWYAC2JP4M8HimwgmbaZ --- creds -- -notreal@fakeemail.ch -fj293fbBnlQ!f9vNs - --- config.toml.tmpl -- -[Webserver] -HTTPPort = $PORT - -[[EVM]] -ChainID = '68472' - -[[EVM.Nodes]] -Name = 'Blue' -WSURL = 'wss://primaryfoo.bar/ws' -HTTPURL = 'https://primaryfoo.bar' - -[[EVM.Nodes]] -Name = 'Yellow' -WSURL = 'wss://sendonlyfoo.bar/ws' -HTTPURL = 'https://sendonlyfoo.bar' -SendOnly = true - --- out.txt -- - ------------------------------------ -Name: Blue -Chain ID: 68472 -State: Unreachable -Config: Name = 'Blue' -WSURL = 'wss://primaryfoo.bar/ws' -HTTPURL = 'https://primaryfoo.bar' -Order = 100 - ------------------------------------ -Name: Yellow -Chain ID: 68472 -State: Unreachable -Config: Name = 'Yellow' -WSURL = 'wss://sendonlyfoo.bar/ws' -HTTPURL = 'https://sendonlyfoo.bar' -SendOnly = true -Order = 100 - ------------------------------------ diff --git a/testdata/scripts/nodes/help.txtar b/testdata/scripts/nodes/help.txtar index f9132045d29..8a8f31f4166 100644 --- a/testdata/scripts/nodes/help.txtar +++ b/testdata/scripts/nodes/help.txtar @@ -9,11 +9,10 @@ USAGE: chainlink nodes command [command options] [arguments...] COMMANDS: - aptos Commands for handling aptos node configuration - cosmos Commands for handling cosmos node configuration - evm Commands for handling evm node configuration - solana Commands for handling solana node configuration - starknet Commands for handling starknet node configuration + evm Commands for handling EVM node configuration + cosmos Commands for handling Cosmos node configuration + solana Commands for handling Solana node configuration + starknet Commands for handling StarkNet node configuration OPTIONS: --help, -h show help diff --git a/testdata/scripts/nodes/solana/help.txtar b/testdata/scripts/nodes/solana/help.txtar index 3b10772e3e4..8a0d3751ed7 100644 --- a/testdata/scripts/nodes/solana/help.txtar +++ b/testdata/scripts/nodes/solana/help.txtar @@ -3,13 +3,13 @@ cmp stdout out.txt -- out.txt -- NAME: - chainlink nodes solana - Commands for handling solana node configuration + chainlink nodes solana - Commands for handling Solana node configuration USAGE: chainlink nodes solana command [command options] [arguments...] COMMANDS: - list List all existing solana nodes + list List all existing Solana nodes OPTIONS: --help, -h show help diff --git a/testdata/scripts/nodes/solana/list/help.txtar b/testdata/scripts/nodes/solana/list/help.txtar index 29787c54d94..9cb124a84d8 100644 --- a/testdata/scripts/nodes/solana/list/help.txtar +++ b/testdata/scripts/nodes/solana/list/help.txtar @@ -3,7 +3,7 @@ cmp stdout out.txt -- out.txt -- NAME: - chainlink nodes solana list - List all existing solana nodes + chainlink nodes solana list - List all existing Solana nodes USAGE: chainlink nodes solana list [arguments...] diff --git a/testdata/scripts/nodes/solana/list/list.txtar b/testdata/scripts/nodes/solana/list/list.txtar deleted file mode 100644 index b13335ae102..00000000000 --- a/testdata/scripts/nodes/solana/list/list.txtar +++ /dev/null @@ -1,57 +0,0 @@ -# start node -exec sh -c 'eval "echo \"$(cat config.toml.tmpl)\" > config.toml"' -exec chainlink node -c config.toml start -p password -a creds & - -# initialize client -env NODEURL=http://localhost:$PORT -exec curl --retry 10 --retry-max-time 60 --retry-connrefused $NODEURL -exec chainlink --remote-node-url $NODEURL admin login -file creds --bypass-version-check - -exec chainlink --remote-node-url $NODEURL nodes solana list -cmp stdout out.txt - --- testdb.txt -- -CL_DATABASE_URL --- testport.txt -- -PORT - --- password -- -T.tLHkcmwePT/p,]sYuntjwHKAsrhm#4eRs4LuKHwvHejWYAC2JP4M8HimwgmbaZ --- creds -- -notreal@fakeemail.ch -fj293fbBnlQ!f9vNs - --- config.toml.tmpl -- -[Webserver] -HTTPPort = $PORT - -[[Solana]] -ChainID = '68472' - -[[Solana.Nodes]] -Name = 'Blue' -URL = 'wss://primaryfoo.bar' - -[[Solana.Nodes]] -Name = 'Yellow' -URL = 'wss://sendonlyfoo.bar' - --- out.txt -- - ------------------------------ -Name: Blue -Chain ID: 68472 -State: -Config: Name = 'Blue' -URL = 'wss://primaryfoo.bar' -SendOnly = false - ------------------------------ -Name: Yellow -Chain ID: 68472 -State: -Config: Name = 'Yellow' -URL = 'wss://sendonlyfoo.bar' -SendOnly = false - ------------------------------ diff --git a/testdata/scripts/nodes/starknet/help.txtar b/testdata/scripts/nodes/starknet/help.txtar index 0ec3bc19730..bd0b11c6ec5 100644 --- a/testdata/scripts/nodes/starknet/help.txtar +++ b/testdata/scripts/nodes/starknet/help.txtar @@ -3,13 +3,13 @@ cmp stdout out.txt -- out.txt -- NAME: - chainlink nodes starknet - Commands for handling starknet node configuration + chainlink nodes starknet - Commands for handling StarkNet node configuration USAGE: chainlink nodes starknet command [command options] [arguments...] COMMANDS: - list List all existing starknet nodes + list List all existing StarkNet nodes OPTIONS: --help, -h show help diff --git a/testdata/scripts/nodes/starknet/list/help.txtar b/testdata/scripts/nodes/starknet/list/help.txtar index b4bbdf5ae76..e38b2ff8867 100644 --- a/testdata/scripts/nodes/starknet/list/help.txtar +++ b/testdata/scripts/nodes/starknet/list/help.txtar @@ -3,7 +3,7 @@ cmp stdout out.txt -- out.txt -- NAME: - chainlink nodes starknet list - List all existing starknet nodes + chainlink nodes starknet list - List all existing StarkNet nodes USAGE: chainlink nodes starknet list [arguments...] diff --git a/testdata/scripts/nodes/starknet/list/list.txtar b/testdata/scripts/nodes/starknet/list/list.txtar deleted file mode 100644 index ac4c78701f9..00000000000 --- a/testdata/scripts/nodes/starknet/list/list.txtar +++ /dev/null @@ -1,55 +0,0 @@ -# start node -exec sh -c 'eval "echo \"$(cat config.toml.tmpl)\" > config.toml"' -exec chainlink node -c config.toml start -p password -a creds & - -# initialize client -env NODEURL=http://localhost:$PORT -exec curl --retry 10 --retry-max-time 60 --retry-connrefused $NODEURL -exec chainlink --remote-node-url $NODEURL admin login -file creds --bypass-version-check - -exec chainlink --remote-node-url $NODEURL nodes starknet list -cmp stdout out.txt - --- testdb.txt -- -CL_DATABASE_URL --- testport.txt -- -PORT - --- password -- -T.tLHkcmwePT/p,]sYuntjwHKAsrhm#4eRs4LuKHwvHejWYAC2JP4M8HimwgmbaZ --- creds -- -notreal@fakeemail.ch -fj293fbBnlQ!f9vNs - --- config.toml.tmpl -- -[Webserver] -HTTPPort = $PORT - -[[Starknet]] -ChainID = '68472' - -[[Starknet.Nodes]] -Name = 'Blue' -URL = 'wss://primaryfoo.bar' - -[[Starknet.Nodes]] -Name = 'Yellow' -URL = 'wss://sendonlyfoo.bar' - --- out.txt -- - ------------------------------ -Name: Blue -Chain ID: 68472 -State: -Config: Name = 'Blue' -URL = 'wss://primaryfoo.bar' - ------------------------------ -Name: Yellow -Chain ID: 68472 -State: -Config: Name = 'Yellow' -URL = 'wss://sendonlyfoo.bar' - ------------------------------ diff --git a/tools/bin/go_core_ccip_deployment_tests b/tools/bin/go_core_ccip_deployment_tests index 2a598c55cbd..5249496cc0a 100755 --- a/tools/bin/go_core_ccip_deployment_tests +++ b/tools/bin/go_core_ccip_deployment_tests @@ -3,18 +3,26 @@ set -o pipefail set +e SCRIPT_PATH=`dirname "$0"`; SCRIPT_PATH=`eval "cd \"$SCRIPT_PATH\" && pwd"` -OUTPUT_FILE=${OUTPUT_FILE:-"../output.txt"} -EXTRA_FLAGS="" +OUTPUT_FILE="../output.txt" +USE_TEE="${USE_TEE:-true}" cd ./deployment || exit go mod download -echo "Test execution results: ---------------------" +echo "Failed tests and panics: ---------------------" echo "" - if [[ $GITHUB_EVENT_NAME == "schedule" ]]; then - EXTRA_FLAGS="-covermode=atomic -coverpkg=./... -coverprofile=coverage.txt" + if [[ $DEBUG == "true" ]]; then + go test -json -vet=off ./... -covermode=atomic -coverpkg=./... -coverprofile=coverage.txt | tee $OUTPUT_FILE + else + go test -json -vet=off ./... -covermode=atomic -coverpkg=./... -coverprofile=coverage.txt | cat > $OUTPUT_FILE + fi +else + if [[ $DEBUG == "true" ]]; then + go test -vet=off ./... | tee $OUTPUT_FILE + else + go test -vet=off ./... | cat > $OUTPUT_FILE + fi fi -go test ./... $EXTRA_FLAGS | tee $OUTPUT_FILE | grep -Ev '\[no test files\]|\[no tests to run\]' EXITCODE=${PIPESTATUS[0]} # Assert no known sensitive strings present in test logger output diff --git a/tools/bin/go_core_fuzz b/tools/bin/go_core_fuzz index 65c9273a418..49aaf33b65e 100755 --- a/tools/bin/go_core_fuzz +++ b/tools/bin/go_core_fuzz @@ -19,7 +19,7 @@ echo "timeout minutes: $FUZZ_TIMEOUT_MINUTES" echo "fuzz seconds: $FUZZ_SECONDS" echo "Failed fuzz tests and panics: ---------------------" echo "" -timeout "${FUZZ_TIMEOUT_MINUTES}"m ./fuzz/fuzz_all_native.py --ci --seconds "$FUZZ_SECONDS" --go_module_root ./ | tee $OUTPUT_FILE | grep -Ev '\[no test files\]|\[no tests to run\]' +timeout "${FUZZ_TIMEOUT_MINUTES}"m ./fuzz/fuzz_all_native.py --ci --seconds "$FUZZ_SECONDS" --go_module_root ./ | tee $OUTPUT_FILE EXITCODE=${PIPESTATUS[0]} # Assert no known sensitive strings present in test logger output diff --git a/tools/bin/go_core_race_tests b/tools/bin/go_core_race_tests index 467dda4e92f..2c4071bc20f 100755 --- a/tools/bin/go_core_race_tests +++ b/tools/bin/go_core_race_tests @@ -4,9 +4,21 @@ OUTPUT_FILE=${OUTPUT_FILE:-"./output.txt"} TIMEOUT="${TIMEOUT:-10s}" COUNT="${COUNT:-5}" -echo "Test execution results: ---------------------" +echo "Failed tests and panics: ---------------------" echo "" -GORACE="log_path=$PWD/race" go test -race -shuffle on -timeout "$TIMEOUT" -count "$COUNT" $1 | cat > $OUTPUT_FILE +if [[ $GITHUB_EVENT_NAME == "schedule" ]]; then + if [[ $DEBUG == "true" ]]; then + GORACE="log_path=$PWD/race" go test -json -vet=off -race -shuffle on -timeout "$TIMEOUT" -count "$COUNT" $1 | tee $OUTPUT_FILE + else + GORACE="log_path=$PWD/race" go test -vet=off -race -shuffle on -timeout "$TIMEOUT" -count "$COUNT" $1 | cat > $OUTPUT_FILE + fi +else + if [[ $DEBUG == "true" ]]; then + GORACE="log_path=$PWD/race" go test -json -vet=off -race -shuffle on -timeout "$TIMEOUT" -count "$COUNT" $1 | tee $OUTPUT_FILE + else + GORACE="log_path=$PWD/race" go test -vet=off -race -shuffle on -timeout "$TIMEOUT" -count "$COUNT" $1 | cat > $OUTPUT_FILE + fi +fi EXITCODE=${PIPESTATUS[0]} diff --git a/tools/bin/go_core_scripts_tests b/tools/bin/go_core_scripts_tests deleted file mode 100755 index e4380264215..00000000000 --- a/tools/bin/go_core_scripts_tests +++ /dev/null @@ -1,36 +0,0 @@ -#!/usr/bin/env bash -set -o pipefail -set +e - -SCRIPT_PATH=`dirname "$0"`; SCRIPT_PATH=`eval "cd \"$SCRIPT_PATH\" && pwd"` -OUTPUT_FILE=${OUTPUT_FILE:-"./output.txt"} -EXTRA_FLAGS="" - -cd ./core/scripts || exit -go mod download -echo "Test execution results: ---------------------" -echo "" - -if [[ $GITHUB_EVENT_NAME == "schedule" ]]; then - EXTRA_FLAGS="-covermode=atomic -coverpkg=./... -coverprofile=coverage.txt" -fi -go test ./... $EXTRA_FLAGS | tee $OUTPUT_FILE | grep -Ev '\[no test files\]|\[no tests to run\]' -EXITCODE=${PIPESTATUS[0]} - -# Assert no known sensitive strings present in test logger output -printf "\n----------------------------------------------\n\n" -echo "Beginning check of output logs for sensitive strings" -$SCRIPT_PATH/scrub_logs $OUTPUT_FILE -cd .. -if [[ $? != 0 ]]; then - exit 1 -fi - -echo "Exit code: $EXITCODE" -if [[ $EXITCODE != 0 ]]; then - echo "Encountered test failures." -else - echo "All tests passed!" -fi -echo "go_core_scripts_tests exiting with code $EXITCODE" -exit $EXITCODE diff --git a/tools/bin/go_core_tests b/tools/bin/go_core_tests index 3679988a896..90713e15563 100755 --- a/tools/bin/go_core_tests +++ b/tools/bin/go_core_tests @@ -4,14 +4,22 @@ set +e SCRIPT_PATH=`dirname "$0"`; SCRIPT_PATH=`eval "cd \"$SCRIPT_PATH\" && pwd"` OUTPUT_FILE=${OUTPUT_FILE:-"./output.txt"} -EXTRA_FLAGS="-timeout 20m" -echo "Test execution results: ---------------------" +echo "Failed tests and panics: ---------------------" echo "" if [[ $GITHUB_EVENT_NAME == "schedule" ]]; then - EXTRA_FLAGS="-covermode=atomic -coverpkg=./... -coverprofile=coverage.txt" + if [[ $DEBUG == "true" ]]; then + go test -json -vet=off -covermode=atomic -coverpkg=./... -coverprofile=coverage.txt $1 | tee $OUTPUT_FILE + else + go test -json -vet=off -covermode=atomic -coverpkg=./... -coverprofile=coverage.txt $1 | cat > $OUTPUT_FILE + fi +else + if [[ $DEBUG == "true" ]]; then + go test -vet=off $1 | tee $OUTPUT_FILE + else + go test -vet=off $1 | cat > $OUTPUT_FILE + fi fi -go test $EXTRA_FLAGS $1 | tee $OUTPUT_FILE | grep -Ev '\[no test files\]|\[no tests to run\]' EXITCODE=${PIPESTATUS[0]} # Assert no known sensitive strings present in test logger output @@ -29,4 +37,4 @@ else echo "All tests passed!" fi echo "go_core_tests exiting with code $EXITCODE" -exit $EXITCODE \ No newline at end of file +exit $EXITCODE diff --git a/tools/bin/go_core_tests_integration b/tools/bin/go_core_tests_integration index 70a9118d286..6dfe22583cd 100755 --- a/tools/bin/go_core_tests_integration +++ b/tools/bin/go_core_tests_integration @@ -4,7 +4,6 @@ set +e SCRIPT_PATH=$(dirname "$0"); SCRIPT_PATH=$(eval "cd \"$SCRIPT_PATH\" && pwd") OUTPUT_FILE=${OUTPUT_FILE:-"./output.txt"} -EXTRA_FLAGS="" echo "Finding and running integration-tagged tests" INTEGRATION_TAGGED_TEST_FILES=$(find . -name '*_test.go' -exec grep -l '//go:build integration' {} +) @@ -15,15 +14,24 @@ fi INTEGRATION_TEST_DIRS=$(echo "$INTEGRATION_TAGGED_TEST_FILES" | xargs -n1 dirname | sort -u) INTEGRATION_TEST_DIRS_SPACE_DELIMITED=$(echo "$INTEGRATION_TEST_DIRS" | tr '\n' ' ') -echo "Test execution results: ---------------------" +echo "Failed tests and panics: ---------------------" echo "" if [[ $GITHUB_EVENT_NAME == "schedule" ]]; then # Experimental code to minimize size of this coverage report # ALL_IMPORTS=$(go list -f '{{ join .Imports "\n" }}' $INTEGRATION_TEST_DIRS | sort -u) # COVERPKG_DIRS=$(echo "$INTEGRATION_TEST_DIRS $ALL_IMPORTS" | grep "smartcontractkit/chainlink" | tr '\n' ',') - EXTRA_FLAGS="-covermode=atomic -coverpkg=./... -coverprofile=coverage.txt" + if [[ $DEBUG == "true" ]]; then + go test -json -tags integration -vet=off -covermode=atomic -coverpkg=./... -coverprofile=coverage.txt $INTEGRATION_TEST_DIRS_SPACE_DELIMITED | tee $OUTPUT_FILE + else + go test -json -tags integration -vet=off -covermode=atomic -coverpkg=./... -coverprofile=coverage.txt $INTEGRATION_TEST_DIRS_SPACE_DELIMITED | cat > $OUTPUT_FILE + fi +else + if [[ $DEBUG == "true" ]]; then + go test -vet=off -tags integration $INTEGRATION_TEST_DIRS_SPACE_DELIMITED | tee $OUTPUT_FILE + else + go test -vet=off -tags integration $INTEGRATION_TEST_DIRS_SPACE_DELIMITED | cat > $OUTPUT_FILE + fi fi -go test -tags integration $EXTRA_FLAGS $INTEGRATION_TEST_DIRS_SPACE_DELIMITED | tee $OUTPUT_FILE | grep -Ev '\[no test files\]|\[no tests to run\]' EXITCODE=${PIPESTATUS[0]} # Assert no known sensitive strings present in test logger output diff --git a/tools/bin/goreleaser_utils b/tools/bin/goreleaser_utils index 0bf745d5a58..52e37cefd51 100755 --- a/tools/bin/goreleaser_utils +++ b/tools/bin/goreleaser_utils @@ -27,10 +27,8 @@ before_hook() { # linux_arm64, rather than being suffixless on native platforms if [ "$GOARCH" = "arm64" ]; then if [ -d "$BIN_DIR/linux_arm64" ]; then - cp "$BIN_DIR/linux_arm64"/chainlink* "$PLUGIN_DIR" - elif [ -d "$BIN_DIR/linux_arm64_v8.0" ]; then cp "$BIN_DIR/linux_arm64_v8.0"/chainlink* "$PLUGIN_DIR" - else + else cp "$BIN_DIR"/chainlink* "$PLUGIN_DIR" fi # Call patchelf --set-interpreter on all plugins diff --git a/tools/gomod-local-update/README.md b/tools/gomod-local-update/README.md deleted file mode 100644 index a49a663ecaa..00000000000 --- a/tools/gomod-local-update/README.md +++ /dev/null @@ -1,41 +0,0 @@ -# gomod-local-update - -Updates any module that is `replace`'d with a local path to have its required module version in `go.mod` to match the latest git SHA from a remote branch. - -Is meant to run within each directory where a `go.mod` file is present. - -## Configuration - -Command Line Flags: - -```shell -Optional: - -org-name Organization name (default: smartcontractkit) - -repo-name Repository name (default: chainlink) - -repo-remote Git remote to use (default: origin) - -branch-trunk Branch to get SHA from (default: develop) - -dry-run Preview changes without applying them (default: false) -``` - -## Installation - -The installed binary will be placed in your `$GOPATH/bin` directory. Make sure this directory is in your system's PATH to run the command from anywhere. From the root of this repository, run: - -```shell -go install ./tools/gomod-local-update/cmd/gomod-local-update -``` - -## Usage Examples - -Run from the root of a go module directory. - -```shell -gomod-local-update -``` - -Was designed to be used with [gomods](https://github.com/jmank88/gomods) like: - -```shell -gomods -w gomod-local-update -gomods tidy -``` diff --git a/tools/gomod-local-update/cmd/gomod-local-update/main.go b/tools/gomod-local-update/cmd/gomod-local-update/main.go deleted file mode 100644 index c471e8db776..00000000000 --- a/tools/gomod-local-update/cmd/gomod-local-update/main.go +++ /dev/null @@ -1,48 +0,0 @@ -package main - -import ( - "fmt" - "log" - "os" - - "github.com/smartcontractkit/chainlink/v2/tools/gomod-local-update/internal/updater" -) - -const ( - goBinaryName = "gomod-local-update" -) - -var version = "dev" -var usage = fmt.Sprintf(`%s version %%s - -Usage: - cd /path/to/go/module - %s [flags] -`, goBinaryName, goBinaryName) - -func main() { - cfg, err := updater.ParseFlags(os.Args[1:], version) - if err != nil { - fmt.Fprintf(os.Stderr, usage, version) - log.Fatal(err) - } - - if cfg.ShowVersion { - fmt.Printf("%s version %s\n", goBinaryName, version) - os.Exit(0) - } - - if err := cfg.Validate(); err != nil { - fmt.Fprintf(os.Stderr, usage, version) - log.Fatal(err) - } - - u := updater.New( - cfg, - updater.NewSystemOperator(), - ) - - if err := u.Run(); err != nil { - log.Fatal(err) - } -} diff --git a/tools/gomod-local-update/internal/updater/config.go b/tools/gomod-local-update/internal/updater/config.go deleted file mode 100644 index 444193b8086..00000000000 --- a/tools/gomod-local-update/internal/updater/config.go +++ /dev/null @@ -1,69 +0,0 @@ -package updater - -import ( - "flag" - "fmt" -) - -const ( - DefaultRepoRemote = "origin" - DefaultBranchTrunk = "develop" - DefaultOrgName = "smartcontractkit" - DefaultRepoName = "chainlink" -) - -type Config struct { - RepoRemote string - BranchTrunk string - DryRun bool - ShowVersion bool - OrgName string - RepoName string -} - -func ParseFlags(args []string, version string) (*Config, error) { - flags := flag.NewFlagSet("default", flag.ContinueOnError) - - cfg := &Config{} - - flags.StringVar(&cfg.RepoRemote, "repo-remote", DefaultRepoRemote, "Git remote to use") - flags.StringVar(&cfg.BranchTrunk, "branch-trunk", DefaultBranchTrunk, "Branch to get SHA from") - flags.BoolVar(&cfg.DryRun, "dry-run", false, "Preview changes without applying them") - flags.BoolVar(&cfg.ShowVersion, "version", false, "Show version information") - flags.StringVar(&cfg.OrgName, "org-name", DefaultOrgName, "GitHub organization name") - flags.StringVar(&cfg.RepoName, "repo-name", DefaultRepoName, "GitHub repository name") - - if err := flags.Parse(args); err != nil { - return nil, err - } - - return cfg, nil -} - -func (c *Config) Validate() error { - if c.ShowVersion { - return nil - } - - if c.OrgName == "" { - return fmt.Errorf("%w: org name must be provided", ErrInvalidConfig) - } - if c.RepoName == "" { - return fmt.Errorf("%w: repo name must be provided", ErrInvalidConfig) - } - if c.RepoRemote == "" { - return fmt.Errorf("%w: repo remote must be provided", ErrInvalidConfig) - } - if c.BranchTrunk == "" { - return fmt.Errorf("%w: trunk branch must be provided", ErrInvalidConfig) - } - - if !gitRemoteRE.MatchString(c.RepoRemote) { - return fmt.Errorf("%w: git remote '%s' contains invalid characters", ErrInvalidConfig, c.RepoRemote) - } - if !gitBranchRE.MatchString(c.BranchTrunk) { - return fmt.Errorf("%w: git branch '%s' contains invalid characters", ErrInvalidConfig, c.BranchTrunk) - } - - return nil -} diff --git a/tools/gomod-local-update/internal/updater/config_test.go b/tools/gomod-local-update/internal/updater/config_test.go deleted file mode 100644 index 21b867aea8d..00000000000 --- a/tools/gomod-local-update/internal/updater/config_test.go +++ /dev/null @@ -1,177 +0,0 @@ -package updater - -import ( - "errors" - "testing" -) - -func TestConfig_Validate(t *testing.T) { - tests := []struct { - name string - config *Config - wantErr bool - }{ - { - name: "valid config", - config: &Config{ - RepoRemote: DefaultRepoRemote, - BranchTrunk: DefaultBranchTrunk, - OrgName: DefaultOrgName, - RepoName: DefaultRepoName, - }, - wantErr: false, - }, - { - name: "version flag bypasses validation", - config: &Config{ - ShowVersion: true, - }, - wantErr: false, - }, - { - name: "missing repo remote", - config: &Config{ - BranchTrunk: DefaultBranchTrunk, - OrgName: DefaultOrgName, - RepoName: DefaultRepoName, - }, - wantErr: true, - }, - { - name: "missing branch trunk", - config: &Config{ - RepoRemote: DefaultRepoRemote, - OrgName: DefaultOrgName, - RepoName: DefaultRepoName, - }, - wantErr: true, - }, - { - name: "missing org name", - config: &Config{ - RepoRemote: DefaultRepoRemote, - BranchTrunk: DefaultBranchTrunk, - RepoName: DefaultRepoName, - }, - wantErr: true, - }, - { - name: "missing repo name", - config: &Config{ - RepoRemote: DefaultRepoRemote, - BranchTrunk: DefaultBranchTrunk, - OrgName: DefaultOrgName, - }, - wantErr: true, - }, - { - name: "invalid remote characters", - config: &Config{ - OrgName: "test", - RepoName: "test", - RepoRemote: "origin!@#", - BranchTrunk: "main", - }, - wantErr: true, - }, - { - name: "invalid branch characters", - config: &Config{ - OrgName: "test", - RepoName: "test", - RepoRemote: "origin", - BranchTrunk: "main!@#", - }, - wantErr: true, - }, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - err := tt.config.Validate() - if (err != nil) != tt.wantErr { - t.Errorf("Validate() error = %v, wantErr %v", err, tt.wantErr) - } - }) - } -} - -func TestConfig_ValidateErrorType(t *testing.T) { - cfg := &Config{ - RepoRemote: "invalid*remote", - BranchTrunk: "develop", - OrgName: "test", - RepoName: "test", - } - - err := cfg.Validate() - if err == nil { - t.Error("expected error due to invalid repo remote, got nil") - return - } - - if !errors.Is(err, ErrInvalidConfig) { - t.Errorf("expected error to be ErrInvalidConfig, got: %v", err) - } -} - -func TestParseFlags(t *testing.T) { - tests := []struct { - name string - args []string - wantCfg *Config - wantErr bool - }{ - { - name: "default flags", - args: []string{}, - wantCfg: &Config{ - RepoRemote: "origin", - BranchTrunk: "develop", - }, - wantErr: false, - }, - { - name: "show version", - args: []string{"-version"}, - wantCfg: &Config{ - ShowVersion: true, - RepoRemote: "origin", - BranchTrunk: "develop", - }, - wantErr: false, - }, - { - name: "custom remote and branch", - args: []string{"-repo-remote", "upstream", "-branch-trunk", "main"}, - wantCfg: &Config{ - RepoRemote: "upstream", - BranchTrunk: "main", - }, - wantErr: false, - }, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - got, err := ParseFlags(tt.args, "test-version") - if (err != nil) != tt.wantErr { - t.Errorf("ParseFlags() error = %v, wantErr %v", err, tt.wantErr) - return - } - if err != nil { - return - } - - if got.RepoRemote != tt.wantCfg.RepoRemote { - t.Errorf("ParseFlags() RepoRemote = %v, want %v", got.RepoRemote, tt.wantCfg.RepoRemote) - } - if got.BranchTrunk != tt.wantCfg.BranchTrunk { - t.Errorf("ParseFlags() BranchTrunk = %v, want %v", got.BranchTrunk, tt.wantCfg.BranchTrunk) - } - if got.ShowVersion != tt.wantCfg.ShowVersion { - t.Errorf("ParseFlags() ShowVersion = %v, want %v", got.ShowVersion, tt.wantCfg.ShowVersion) - } - }) - } -} diff --git a/tools/gomod-local-update/internal/updater/errors.go b/tools/gomod-local-update/internal/updater/errors.go deleted file mode 100644 index 288eb49f66d..00000000000 --- a/tools/gomod-local-update/internal/updater/errors.go +++ /dev/null @@ -1,11 +0,0 @@ -package updater - -import "errors" - -var ( - // ErrModOperation indicates a failure in a module-related operation. - ErrModOperation = errors.New("module operation failed") - - // ErrInvalidConfig indicates invalid configuration parameters. - ErrInvalidConfig = errors.New("invalid configuration") -) diff --git a/tools/gomod-local-update/internal/updater/system_operator.go b/tools/gomod-local-update/internal/updater/system_operator.go deleted file mode 100644 index 59ccfb15ed7..00000000000 --- a/tools/gomod-local-update/internal/updater/system_operator.go +++ /dev/null @@ -1,34 +0,0 @@ -package updater - -import ( - "os" - "path/filepath" -) - -// SystemOperator provides an interface for file system operations. -type SystemOperator interface { - // ReadFile reads the entire contents of a file - ReadFile(path string) ([]byte, error) - // WriteFile writes data to a file with specific permissions - WriteFile(path string, data []byte, perm os.FileMode) error -} - -type systemOperator struct{} - -func NewSystemOperator() SystemOperator { - return &systemOperator{} -} - -func (s *systemOperator) ReadFile(path string) ([]byte, error) { - path = filepath.Clean(path) - return os.ReadFile(path) -} - -func (s *systemOperator) WriteFile(path string, data []byte, perm os.FileMode) error { - path = filepath.Clean(path) - dir := filepath.Dir(path) - if err := os.MkdirAll(dir, 0755); err != nil { - return err - } - return os.WriteFile(path, data, perm) -} diff --git a/tools/gomod-local-update/internal/updater/updater.go b/tools/gomod-local-update/internal/updater/updater.go deleted file mode 100644 index cfb873ed3ca..00000000000 --- a/tools/gomod-local-update/internal/updater/updater.go +++ /dev/null @@ -1,253 +0,0 @@ -package updater - -import ( - "context" - "errors" - "fmt" - "log" - "os" - "os/exec" - "regexp" - "strings" - "time" - - "golang.org/x/mod/modfile" - "golang.org/x/mod/module" -) - -// gitExecutor allows mocking git commands in tests -type gitExecutor interface { - Command(ctx context.Context, args ...string) ([]byte, error) -} - -// systemGitExecutor executes git commands on the host system -type systemGitExecutor struct{} - -func (g *systemGitExecutor) Command(ctx context.Context, args ...string) ([]byte, error) { - return exec.CommandContext(ctx, "git", args...).Output() -} - -const ( - // File and mode constants - goModFile = "go.mod" - goModFileMode = 0644 - gitSHALength = 12 - gitTimeout = 30 * time.Second - gitTimeFormat = time.RFC3339 - - // Regex pattern constants - gitRemotePattern = `^[a-zA-Z0-9][-a-zA-Z0-9_.]*$` - gitBranchPattern = `^[a-zA-Z0-9][-a-zA-Z0-9/_]*$` - majorVersionPattern = `/v\d+$` - shaPattern = `^[a-fA-F0-9]{40}$` // SHA-1 hashes are 40 hexadecimal characters -) - -var ( - // Pre-compiled regular expressions - gitRemoteRE = regexp.MustCompile(gitRemotePattern) - gitBranchRE = regexp.MustCompile(gitBranchPattern) - gitShaRE = regexp.MustCompile(shaPattern) - majorVersionRE = regexp.MustCompile(majorVersionPattern) -) - -type Updater struct { - config *Config - system SystemOperator - git gitExecutor -} - -// New creates a new Updater -func New(config *Config, system SystemOperator) *Updater { - return &Updater{ - config: config, - system: system, - git: &systemGitExecutor{}, - } -} - -// validateSHA checks if the SHA consists of exactly 40 hexadecimal digits -func (u *Updater) validateSHA(sha string) error { - if !gitShaRE.MatchString(sha) { - return fmt.Errorf("%w: invalid git SHA '%s'", ErrInvalidConfig, sha) - } - return nil -} - -// getGitInfo retrieves the latest commit SHA and timestamp from a Git repository -func (u *Updater) getGitInfo(remote, branch string) (string, time.Time, error) { - ctx, cancel := context.WithTimeout(context.Background(), gitTimeout) - defer cancel() - - // Use u.git.Command for ls-remote - out, err := u.git.Command(ctx, "ls-remote", remote, "refs/heads/"+branch) - if err != nil { - return "", time.Time{}, fmt.Errorf("%w: failed to fetch commit SHA from %s/%s: %w", - ErrModOperation, remote, branch, err) - } - if len(out) == 0 { - return "", time.Time{}, fmt.Errorf("%w: no output from git ls-remote", ErrModOperation) - } - sha := strings.Split(string(out), "\t")[0] - if len(sha) == 0 { - return "", time.Time{}, fmt.Errorf("%w: empty SHA from git ls-remote", ErrModOperation) - } - - // Validate the SHA - if err := u.validateSHA(sha); err != nil { - return "", time.Time{}, err - } - - // Use u.git.Command for show - showOut, showErr := u.git.Command(ctx, "show", "-s", "--format=%cI", sha) - if showErr != nil { - return "", time.Time{}, fmt.Errorf("failed to get commit time: %w", showErr) - } - - commitTime, parseErr := time.Parse(gitTimeFormat, strings.TrimSpace(string(showOut))) - if parseErr != nil { - return "", time.Time{}, fmt.Errorf("failed to parse commit time: %w", parseErr) - } - - return sha[:gitSHALength], commitTime, nil -} - -// Run starts the module update process -func (u *Updater) Run() error { - logger := log.New(os.Stdout, "", log.LstdFlags) - - logger.Printf("info: auto-detecting modules with local replace directives") - - f, err := u.readModFile() - if err != nil { - return fmt.Errorf("%w: failed to read and parse go.mod file", ErrModOperation) - } - - // Auto-detect modules to update - modulesToUpdate, err := u.findLocalReplaceModules() - if err != nil { - return fmt.Errorf("%w: failed to detect local replace modules", ErrModOperation) - } - if len(modulesToUpdate) == 0 { - logger.Printf("info: no modules found to update in %s", f.Module.Mod.Path) - return nil - } - logger.Printf("info: found %d modules with local replace directives: %v", - len(modulesToUpdate), modulesToUpdate) - - // Get commit info once for all modules - sha, commitTime, err := u.getGitInfo(u.config.RepoRemote, u.config.BranchTrunk) - if err != nil { - if errors.Is(err, ErrInvalidConfig) { - return err - } - return fmt.Errorf("%w: failed to get git commit info from remote", ErrModOperation) - } - - // Update the modules in the same file handle - if err := u.updateGoMod(f, modulesToUpdate, sha, commitTime); err != nil { - return fmt.Errorf("%w: failed to update module versions in go.mod", ErrModOperation) - } - - return u.writeModFile(f) -} - -// updateGoMod updates the go.mod file with new pseudo-versions -func (u *Updater) updateGoMod(modFile *modfile.File, modulesToUpdate []string, sha string, commitTime time.Time) error { - for _, modulePath := range modulesToUpdate { - majorVersion := getMajorVersion(modulePath) - pseudoVersion := module.PseudoVersion(majorVersion, "", commitTime, sha[:gitSHALength]) - - // Find and update version - for _, req := range modFile.Require { - if req.Mod.Path == modulePath { - if u.config.DryRun { - log.Printf("[DRY RUN] Would update %s: %s => %s", modulePath, req.Mod.Version, pseudoVersion) - continue - } - - if err := modFile.AddRequire(modulePath, pseudoVersion); err != nil { - return fmt.Errorf("%w: failed to update version for module %s", - ErrModOperation, modulePath) - } - break - } - } - } - - return nil -} - -// getMajorVersion extracts the major version number from a module path -// Returns "v2" for /v2, "v0" for no version suffix -func getMajorVersion(modulePath string) string { - if match := majorVersionRE.FindString(modulePath); match != "" { - return strings.TrimPrefix(match, "/") - } - return "v0" -} - -// findLocalReplaceModules finds modules with local replace directives -func (u *Updater) findLocalReplaceModules() ([]string, error) { - modFile, err := u.readModFile() - if err != nil { - return nil, err - } - - orgPrefix := fmt.Sprintf("github.com/%s/%s", u.config.OrgName, u.config.RepoName) - localModules := make(map[string]bool) - var modules []string - - // First find all local replaces for our org - for _, rep := range modFile.Replace { - if strings.HasPrefix(rep.Old.Path, orgPrefix) && - rep.New.Version == "" && - isLocalPath(rep.New.Path) { - localModules[rep.Old.Path] = true - } - } - - // Then check requires that match our replaces - for _, req := range modFile.Require { - if localModules[req.Mod.Path] { - modules = append(modules, req.Mod.Path) - } - } - - return modules, nil -} - -// isLocalPath checks if the path is a local path -func isLocalPath(path string) bool { - return path == "." || path == ".." || - strings.HasPrefix(path, "./") || - strings.HasPrefix(path, "../") -} - -// readModFile reads the go.mod file -func (u *Updater) readModFile() (*modfile.File, error) { - content, err := u.system.ReadFile(goModFile) - if err != nil { - return nil, fmt.Errorf("unable to read go.mod: %w", err) - } - - modFile, err := modfile.Parse(goModFile, content, nil) - if err != nil { - return nil, fmt.Errorf("%w: invalid go.mod format: %w", ErrModOperation, err) - } - - return modFile, nil -} - -// writeModFile writes the go.mod file -func (u *Updater) writeModFile(modFile *modfile.File) error { - content, err := modFile.Format() - if err != nil { - return fmt.Errorf("%w: failed to format go.mod content", ErrModOperation) - } - - if err := u.system.WriteFile(goModFile, content, goModFileMode); err != nil { - return fmt.Errorf("%w: failed to write updated go.mod file", ErrModOperation) - } - - return nil -} diff --git a/tools/gomod-local-update/internal/updater/updater_test.go b/tools/gomod-local-update/internal/updater/updater_test.go deleted file mode 100644 index ba17024dd37..00000000000 --- a/tools/gomod-local-update/internal/updater/updater_test.go +++ /dev/null @@ -1,320 +0,0 @@ -package updater - -import ( - "context" - "fmt" - "os" - "strings" - "testing" - "time" -) - -// mockGitExecutor simulates git commands for testing as an alternative to systemGitExecutor -type mockGitExecutor struct { - sha string - time time.Time -} - -func (m *mockGitExecutor) Command(ctx context.Context, args ...string) ([]byte, error) { - switch args[0] { - case "ls-remote": - // Validate inputs - if len(args) != 3 { - return nil, fmt.Errorf("expected 3 args for ls-remote, got %d", len(args)) - } - remote := args[1] - if remote == "invalid*remote" { - return nil, fmt.Errorf("%w: git remote '%s' contains invalid characters", ErrInvalidConfig, remote) - } - // Return a full 40-character SHA - fullSHA := fmt.Sprintf("%s%s", m.sha, strings.Repeat("0", 40-len(m.sha))) - return []byte(fullSHA + "\trefs/heads/" + args[2] + "\n"), nil - case "show": - if len(args) != 4 { - return nil, fmt.Errorf("unexpected show args: %v", args) - } - // Use the full SHA for validation - fullSHA := fmt.Sprintf("%s%s", m.sha, strings.Repeat("0", 40-len(m.sha))) - if args[3] != fullSHA { - return nil, fmt.Errorf("unexpected SHA: got %s, want %s", args[3], fullSHA) - } - return []byte(m.time.Format(gitTimeFormat) + "\n"), nil - default: - return nil, fmt.Errorf("unexpected git command: %v", args) - } -} - -type mockSystemOperator struct { - files map[string][]byte - err error -} - -func newMockSystemOperator() *mockSystemOperator { - return &mockSystemOperator{ - files: make(map[string][]byte), - } -} - -func (m *mockSystemOperator) ReadFile(path string) ([]byte, error) { - if m.err != nil { - return nil, m.err - } - content, ok := m.files[path] - if !ok { - return nil, fmt.Errorf("file not found: %s", path) - } - return content, nil -} - -func (m *mockSystemOperator) WriteFile(path string, data []byte, perm os.FileMode) error { - if m.err != nil { - return m.err - } - m.files[path] = data - return nil -} - -func TestUpdater_Run(t *testing.T) { - testTime := time.Date(2024, 11, 22, 18, 21, 10, 0, time.UTC) - // Use a full 40-character SHA - testSHA := "ac7a7395feed" + strings.Repeat("0", 28) - - tests := []struct { - name string - config *Config - sysOp *mockSystemOperator - wantErr bool - wantFile string - }{ - { - name: "successful update", - config: &Config{ - RepoRemote: "origin", - BranchTrunk: "develop", - OrgName: "smartcontractkit", - RepoName: "chainlink", - }, - sysOp: func() *mockSystemOperator { - m := newMockSystemOperator() - m.files["go.mod"] = []byte(`module test -require github.com/smartcontractkit/chainlink/v2 v2.0.0 -replace github.com/smartcontractkit/chainlink/v2 => ../ -`) - return m - }(), - wantErr: false, - wantFile: fmt.Sprintf(`module test - -require github.com/smartcontractkit/chainlink/v2 v2.0.0-20241122182110-%s - -replace github.com/smartcontractkit/chainlink/v2 => ../ -`, testSHA[:12]), - }, - { - name: "handles module with local replace", - config: &Config{ - RepoRemote: "origin", - BranchTrunk: "develop", - OrgName: "smartcontractkit", - RepoName: "chainlink", - }, - sysOp: func() *mockSystemOperator { - m := newMockSystemOperator() - m.files["go.mod"] = []byte(`module test -require github.com/smartcontractkit/chainlink/v2 v2.0.0 -replace github.com/smartcontractkit/chainlink/v2 => ../ -`) - return m - }(), - wantErr: false, - }, - { - name: "v1 module update", - config: &Config{ - RepoRemote: "origin", - BranchTrunk: "develop", - OrgName: "example", - RepoName: "mod", - }, - sysOp: func() *mockSystemOperator { - m := newMockSystemOperator() - m.files["go.mod"] = []byte(`module test -require github.com/example/mod v1.0.0 -`) - return m - }(), - wantErr: false, - }, - { - name: "updates v2 module with timestamp", - config: &Config{ - RepoRemote: "origin", - BranchTrunk: "develop", - OrgName: "smartcontractkit", - RepoName: "chainlink", - }, - sysOp: func() *mockSystemOperator { - m := newMockSystemOperator() - m.files["go.mod"] = []byte(`module test -require github.com/smartcontractkit/chainlink/v2 v2.0.0-20241119120536-03115e80382d -`) - return m - }(), - wantErr: false, - wantFile: fmt.Sprintf(`module test - -require github.com/smartcontractkit/chainlink/v2 v2.0.0-20241122182110-%s - -replace github.com/smartcontractkit/chainlink/v2 => ../ -`, testSHA[:12]), - }, - { - name: "updates v0 module with timestamp", - config: &Config{ - RepoRemote: "origin", - BranchTrunk: "develop", - OrgName: "smartcontractkit", - RepoName: "chainlink", - }, - sysOp: func() *mockSystemOperator { - m := newMockSystemOperator() - m.files["go.mod"] = []byte(`module test -require github.com/smartcontractkit/chainlink/deployment v0.0.0-20241119120536-03115e80382d -`) - return m - }(), - wantErr: false, - wantFile: fmt.Sprintf(`module test - -require github.com/smartcontractkit/chainlink/deployment v0.0.0-20241122182110-%s - -replace github.com/smartcontractkit/chainlink/deployment => ../ -`, testSHA[:12]), - }, - { - name: "handles multiple modules with different versions", - config: &Config{ - RepoRemote: "origin", - BranchTrunk: "develop", - OrgName: "smartcontractkit", - RepoName: "chainlink", - }, - sysOp: func() *mockSystemOperator { - m := newMockSystemOperator() - m.files["go.mod"] = []byte(`module test -require ( - github.com/smartcontractkit/chainlink/v2 v2.0.0-20241119120536-03115e80382d - github.com/smartcontractkit/chainlink/deployment v0.0.0-20241119120536-03115e80382d -) -`) - return m - }(), - wantErr: false, - wantFile: fmt.Sprintf(`module test - -require ( - github.com/smartcontractkit/chainlink/v2 v2.0.0-20241122182110-%s - github.com/smartcontractkit/chainlink/deployment v0.0.0-20241122182110-%s -) - -replace github.com/smartcontractkit/chainlink/v2 => ../ - -replace github.com/smartcontractkit/chainlink/deployment => ../ -`, testSHA[:12], testSHA[:12]), - }, - { - name: "updates v3 module with timestamp", - config: &Config{ - RepoRemote: "origin", - BranchTrunk: "develop", - OrgName: "smartcontractkit", - RepoName: "chainlink", - }, - sysOp: func() *mockSystemOperator { - m := newMockSystemOperator() - m.files["go.mod"] = []byte(`module test -require github.com/smartcontractkit/chainlink/v3 v3.0.0-20241119120536-03115e80382d -`) - return m - }(), - wantErr: false, - wantFile: fmt.Sprintf(`module test - -require github.com/smartcontractkit/chainlink/v3 v3.0.0-20241122182110-%s - -replace github.com/smartcontractkit/chainlink/v3 => ../ -`, testSHA[:12]), - }, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - u := New(tt.config, tt.sysOp) - - // Add local replace directive for modules that should be updated - if !strings.Contains(tt.name, "v1 module update") { - modContent := string(tt.sysOp.files["go.mod"]) - for _, module := range []string{"v2", "v3", "deployment"} { - modulePath := fmt.Sprintf("github.com/%s/%s/%s", - tt.config.OrgName, tt.config.RepoName, module) - if strings.Contains(modContent, modulePath) && - !strings.Contains(modContent, "replace "+modulePath) { - modContent += fmt.Sprintf("\nreplace %s => ../\n", modulePath) - } - } - tt.sysOp.files["go.mod"] = []byte(modContent) - } - - // Override the git executor with our mock - u.git = &mockGitExecutor{ - sha: testSHA, - time: testTime, - } - err := u.Run() - if (err != nil) != tt.wantErr { - t.Errorf("Updater.Run() error = %v, wantErr %v", err, tt.wantErr) - } - - if tt.wantFile != "" { - got := string(tt.sysOp.files["go.mod"]) - if got != tt.wantFile { - t.Errorf("File content mismatch\nGot:\n%s\nWant:\n%s", got, tt.wantFile) - } - } - }) - } -} - -func TestUpdater_FindLocalReplaceModules(t *testing.T) { - sysOp := newMockSystemOperator() - sysOp.files["go.mod"] = []byte(` -module test -require ( - github.com/smartcontractkit/chainlink/v2 v2.0.0 - github.com/other/repo v1.0.0 -) -replace ( - github.com/smartcontractkit/chainlink/v2 => ../ - github.com/other/repo => ../other -)`) - - cfg := &Config{ - OrgName: "smartcontractkit", - RepoName: "chainlink", - } - - u := New(cfg, sysOp) - modules, err := u.findLocalReplaceModules() - if err != nil { - t.Errorf("unexpected error: %v", err) - return - } - - if len(modules) != 1 { - t.Errorf("expected 1 module, got %d", len(modules)) - return - } - if modules[0] != "github.com/smartcontractkit/chainlink/v2" { - t.Errorf("expected chainlink module, got %s", modules[0]) - } -}